forked from geolba/tethys.backend
- add EventEmmitter for directly binding Events to component
- add NotificationToast for messages - add leaflet map component and zoom control component - change focus:ring to focus:ring-2 inside BaseButton - `@tailwindcss/line-clamp` plugin is now included by default...remove it from tailwind.config.js - npm updates
This commit is contained in:
parent
080c21126b
commit
cd66f318b6
|
@ -155,14 +155,22 @@ export default class DatasetController {
|
||||||
schema.object().members({
|
schema.object().members({
|
||||||
value: schema.string({ trim: true }, [rules.minLength(3), rules.maxLength(255)]),
|
value: schema.string({ trim: true }, [rules.minLength(3), rules.maxLength(255)]),
|
||||||
type: schema.enum(Object.values(TitleTypes)),
|
type: schema.enum(Object.values(TitleTypes)),
|
||||||
language: schema.string({ trim: true }, [rules.minLength(2), rules.maxLength(255)]),
|
language: schema.string({ trim: true }, [
|
||||||
|
rules.minLength(2),
|
||||||
|
rules.maxLength(255),
|
||||||
|
rules.translatedLanguage('/language', 'type')
|
||||||
|
]),
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
descriptions: schema.array([rules.minLength(1)]).members(
|
descriptions: schema.array([rules.minLength(1)]).members(
|
||||||
schema.object().members({
|
schema.object().members({
|
||||||
value: schema.string({ trim: true }, [rules.minLength(3), rules.maxLength(255)]),
|
value: schema.string({ trim: true }, [rules.minLength(3), rules.maxLength(255)]),
|
||||||
type: schema.enum(Object.values(DescriptionTypes)),
|
type: schema.enum(Object.values(DescriptionTypes)),
|
||||||
language: schema.string({ trim: true }, [rules.minLength(2), rules.maxLength(255)]),
|
language: schema.string({ trim: true }, [
|
||||||
|
rules.minLength(2),
|
||||||
|
rules.maxLength(255),
|
||||||
|
rules.translatedLanguage('/language', 'type')
|
||||||
|
]),
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
authors: schema.array([rules.minLength(1)]).members(schema.object().members({ email: schema.string({ trim: true }) })),
|
authors: schema.array([rules.minLength(1)]).members(schema.object().members({ email: schema.string({ trim: true }) })),
|
||||||
|
|
635
package-lock.json
generated
635
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
|
@ -44,7 +44,7 @@
|
||||||
"@mdi/js": "^7.1.96",
|
"@mdi/js": "^7.1.96",
|
||||||
"@symfony/webpack-encore": "^4.2.0",
|
"@symfony/webpack-encore": "^4.2.0",
|
||||||
"@tailwindcss/forms": "^0.5.2",
|
"@tailwindcss/forms": "^0.5.2",
|
||||||
"@tailwindcss/line-clamp": "^0.4.0",
|
"@types/leaflet": "^1.9.3",
|
||||||
"@types/node": "^18.14.4",
|
"@types/node": "^18.14.4",
|
||||||
"@types/proxy-addr": "^2.0.0",
|
"@types/proxy-addr": "^2.0.0",
|
||||||
"@types/source-map-support": "^0.5.6",
|
"@types/source-map-support": "^0.5.6",
|
||||||
|
@ -88,11 +88,13 @@
|
||||||
"bcryptjs": "^2.4.3",
|
"bcryptjs": "^2.4.3",
|
||||||
"crypto": "^1.0.1",
|
"crypto": "^1.0.1",
|
||||||
"dayjs": "^1.11.7",
|
"dayjs": "^1.11.7",
|
||||||
|
"leaflet": "^1.9.3",
|
||||||
"luxon": "^3.2.1",
|
"luxon": "^3.2.1",
|
||||||
"notiwind": "^2.0.0",
|
"notiwind": "^2.0.0",
|
||||||
"pg": "^8.9.0",
|
"pg": "^8.9.0",
|
||||||
"proxy-addr": "^2.0.7",
|
"proxy-addr": "^2.0.7",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
|
"rxjs": "^7.8.0",
|
||||||
"source-map-support": "^0.5.21",
|
"source-map-support": "^0.5.21",
|
||||||
"vue-facing-decorator": "^2.1.13"
|
"vue-facing-decorator": "^2.1.13"
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,5 +11,8 @@
|
||||||
"assets/fonts/inter-greek-400-normal.woff2": "http://localhost:8080/assets/fonts/inter-greek-400-normal.0278a49f.woff2",
|
"assets/fonts/inter-greek-400-normal.woff2": "http://localhost:8080/assets/fonts/inter-greek-400-normal.0278a49f.woff2",
|
||||||
"assets/fonts/inter-cyrillic-400-normal.woff2": "http://localhost:8080/assets/fonts/inter-cyrillic-400-normal.8684fef6.woff2",
|
"assets/fonts/inter-cyrillic-400-normal.woff2": "http://localhost:8080/assets/fonts/inter-cyrillic-400-normal.8684fef6.woff2",
|
||||||
"assets/fonts/inter-greek-ext-400-normal.woff2": "http://localhost:8080/assets/fonts/inter-greek-ext-400-normal.3f642a92.woff2",
|
"assets/fonts/inter-greek-ext-400-normal.woff2": "http://localhost:8080/assets/fonts/inter-greek-ext-400-normal.3f642a92.woff2",
|
||||||
"assets/fonts/inter-vietnamese-400-normal.woff2": "http://localhost:8080/assets/fonts/inter-vietnamese-400-normal.789afb71.woff2"
|
"assets/fonts/inter-vietnamese-400-normal.woff2": "http://localhost:8080/assets/fonts/inter-vietnamese-400-normal.789afb71.woff2",
|
||||||
|
"assets/images/marker-icon.png": "http://localhost:8080/assets/images/marker-icon.2b3e1faf.png",
|
||||||
|
"assets/images/layers-2x.png": "http://localhost:8080/assets/images/layers-2x.8f2c4d11.png",
|
||||||
|
"assets/images/layers.png": "http://localhost:8080/assets/images/layers.416d9136.png"
|
||||||
}
|
}
|
|
@ -14,7 +14,7 @@ progress {
|
||||||
@apply bg-blue-500;
|
@apply bg-blue-500;
|
||||||
}
|
}
|
||||||
|
|
||||||
progress::-ms-fill {
|
/* progress::-ms-fill {
|
||||||
@apply bg-blue-500 border-0;
|
@apply bg-blue-500 border-0;
|
||||||
}
|
} */
|
||||||
|
|
|
@ -16,9 +16,9 @@ html {
|
||||||
@apply bg-gray-400 rounded;
|
@apply bg-gray-400 rounded;
|
||||||
}
|
}
|
||||||
|
|
||||||
html::-webkit-scrollbar-thumb:hover {
|
/* html::-webkit-scrollbar-thumb:hover {
|
||||||
@apply bg-gray-500;
|
@apply bg-gray-500;
|
||||||
}
|
} */
|
||||||
|
|
||||||
html.dark-scrollbars {
|
html.dark-scrollbars {
|
||||||
scrollbar-color: #374151 #111827;
|
scrollbar-color: #374151 #111827;
|
||||||
|
@ -32,7 +32,7 @@ html {
|
||||||
@apply bg-gray-700;
|
@apply bg-gray-700;
|
||||||
}
|
}
|
||||||
|
|
||||||
html.dark-scrollbars::-webkit-scrollbar-thumb:hover {
|
/* html.dark-scrollbars::-webkit-scrollbar-thumb:hover {
|
||||||
@apply bg-gray-600;
|
@apply bg-gray-600;
|
||||||
}
|
} */
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
@import '_scrollbars.css';
|
@import '_scrollbars.css';
|
||||||
@import '_table.css';
|
@import '_table.css';
|
||||||
|
|
||||||
|
@import '~leaflet/dist/leaflet.css';
|
||||||
@import '@fontsource/inter/index.css';
|
@import '@fontsource/inter/index.css';
|
||||||
@import '@fontsource/archivo-black/index.css';
|
@import '@fontsource/archivo-black/index.css';
|
||||||
|
|
||||||
|
|
|
@ -80,7 +80,7 @@ const componentClass = computed(() => {
|
||||||
'whitespace-nowrap',
|
'whitespace-nowrap',
|
||||||
'focus:outline-none',
|
'focus:outline-none',
|
||||||
'transition-colors',
|
'transition-colors',
|
||||||
'focus:ring',
|
'focus:ring-2',
|
||||||
'duration-150',
|
'duration-150',
|
||||||
'border',
|
'border',
|
||||||
props.roundedFull ? 'rounded-full' : 'rounded',
|
props.roundedFull ? 'rounded-full' : 'rounded',
|
||||||
|
|
|
@ -28,6 +28,10 @@ const props = defineProps({
|
||||||
type: [String, Number, Boolean],
|
type: [String, Number, Boolean],
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
|
deleteId: {
|
||||||
|
type: Number,
|
||||||
|
default: null
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits(['update:modelValue', 'cancel', 'confirm']);
|
const emit = defineEmits(['update:modelValue', 'cancel', 'confirm']);
|
||||||
|
@ -37,9 +41,15 @@ const value = computed({
|
||||||
set: (value) => emit('update:modelValue', value),
|
set: (value) => emit('update:modelValue', value),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// mode = cancel or confirm
|
||||||
const confirmCancel = (mode) => {
|
const confirmCancel = (mode) => {
|
||||||
value.value = false;
|
value.value = false;//close
|
||||||
emit(mode);
|
if (props.deleteId){
|
||||||
|
emit(mode, props.deleteId);
|
||||||
|
} else {
|
||||||
|
emit(mode);
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const confirm = () => confirmCancel('confirm');
|
const confirm = () => confirmCancel('confirm');
|
||||||
|
|
153
resources/js/Components/Map/EventEmitter.ts
Normal file
153
resources/js/Components/Map/EventEmitter.ts
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
import {PartialObserver, Subject, Subscription} from 'rxjs';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use in components with the `@Output` directive to emit custom events
|
||||||
|
* synchronously or asynchronously, and register handlers for those events
|
||||||
|
* by subscribing to an instance.
|
||||||
|
*
|
||||||
|
* @usageNotes
|
||||||
|
*
|
||||||
|
* Extends
|
||||||
|
* [RxJS `Subject`](https://rxjs.dev/api/index/class/Subject)
|
||||||
|
* for Angular by adding the `emit()` method.
|
||||||
|
*
|
||||||
|
* In the following example, a component defines two output properties
|
||||||
|
* that create event emitters. When the title is clicked, the emitter
|
||||||
|
* emits an open or close event to toggle the current visibility state.
|
||||||
|
*
|
||||||
|
* ```html
|
||||||
|
* @Component({
|
||||||
|
* selector: 'zippy',
|
||||||
|
* template: `
|
||||||
|
* <div class="zippy">
|
||||||
|
* <div (click)="toggle()">Toggle</div>
|
||||||
|
* <div [hidden]="!visible">
|
||||||
|
* <ng-content></ng-content>
|
||||||
|
* </div>
|
||||||
|
* </div>`})
|
||||||
|
* export class Zippy {
|
||||||
|
* visible: boolean = true;
|
||||||
|
* @Output() open: EventEmitter<any> = new EventEmitter();
|
||||||
|
* @Output() close: EventEmitter<any> = new EventEmitter();
|
||||||
|
*
|
||||||
|
* toggle() {
|
||||||
|
* this.visible = !this.visible;
|
||||||
|
* if (this.visible) {
|
||||||
|
* this.open.emit(null);
|
||||||
|
* } else {
|
||||||
|
* this.close.emit(null);
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Access the event object with the `$event` argument passed to the output event
|
||||||
|
* handler:
|
||||||
|
*
|
||||||
|
* ```html
|
||||||
|
* <zippy (open)="onOpen($event)" (close)="onClose($event)"></zippy>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @see [Observables in Angular](guide/observables-in-angular)
|
||||||
|
* @publicApi
|
||||||
|
*/
|
||||||
|
export interface EventEmitter<T> extends Subject<T> {
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
__isAsync: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an instance of this class that can
|
||||||
|
* deliver events synchronously or asynchronously.
|
||||||
|
*
|
||||||
|
* @param [isAsync=false] When true, deliver events asynchronously.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
new(isAsync?: boolean): EventEmitter<T>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emits an event containing a given value.
|
||||||
|
* @param value The value to emit.
|
||||||
|
*/
|
||||||
|
emit(value?: T): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers handlers for events emitted by this instance.
|
||||||
|
* @param next When supplied, a custom handler for emitted events.
|
||||||
|
* @param error When supplied, a custom handler for an error notification from this emitter.
|
||||||
|
* @param complete When supplied, a custom handler for a completion notification from this
|
||||||
|
* emitter.
|
||||||
|
*/
|
||||||
|
subscribe(next?: (value: T) => void, error?: (error: any) => void, complete?: () => void):
|
||||||
|
Subscription;
|
||||||
|
/**
|
||||||
|
* Registers handlers for events emitted by this instance.
|
||||||
|
* @param observerOrNext When supplied, a custom handler for emitted events, or an observer
|
||||||
|
* object.
|
||||||
|
* @param error When supplied, a custom handler for an error notification from this emitter.
|
||||||
|
* @param complete When supplied, a custom handler for a completion notification from this
|
||||||
|
* emitter.
|
||||||
|
*/
|
||||||
|
subscribe(observerOrNext?: any, error?: any, complete?: any): Subscription;
|
||||||
|
}
|
||||||
|
|
||||||
|
class EventEmitter_ extends Subject<any> {
|
||||||
|
__isAsync: boolean; // tslint:disable-line
|
||||||
|
|
||||||
|
constructor(isAsync: boolean = false) {
|
||||||
|
super();
|
||||||
|
this.__isAsync = isAsync;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit(value?: any) {
|
||||||
|
super.next(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
override subscribe(observerOrNext?: any, error?: any, complete?: any): Subscription {
|
||||||
|
let nextFn = observerOrNext;
|
||||||
|
let errorFn = error || (() => null);
|
||||||
|
let completeFn = complete;
|
||||||
|
|
||||||
|
if (observerOrNext && typeof observerOrNext === 'object') {
|
||||||
|
const observer = observerOrNext as PartialObserver<unknown>;
|
||||||
|
nextFn = observer.next?.bind(observer);
|
||||||
|
errorFn = observer.error?.bind(observer);
|
||||||
|
completeFn = observer.complete?.bind(observer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.__isAsync) {
|
||||||
|
errorFn = _wrapInTimeout(errorFn);
|
||||||
|
|
||||||
|
if (nextFn) {
|
||||||
|
nextFn = _wrapInTimeout(nextFn);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (completeFn) {
|
||||||
|
completeFn = _wrapInTimeout(completeFn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const sink = super.subscribe({next: nextFn, error: errorFn, complete: completeFn});
|
||||||
|
|
||||||
|
if (observerOrNext instanceof Subscription) {
|
||||||
|
observerOrNext.add(sink);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sink;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _wrapInTimeout(fn: (value: unknown) => any) {
|
||||||
|
return (value: unknown) => {
|
||||||
|
setTimeout(fn, undefined, value);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @publicApi
|
||||||
|
*/
|
||||||
|
export const EventEmitter: {
|
||||||
|
new (isAsync?: boolean): EventEmitter<any>; new<T>(isAsync?: boolean): EventEmitter<T>;
|
||||||
|
readonly prototype: EventEmitter<any>;
|
||||||
|
} = EventEmitter_ as any;
|
14
resources/js/Components/Map/MapOptions.ts
Normal file
14
resources/js/Components/Map/MapOptions.ts
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
import { Layer } from 'leaflet';
|
||||||
|
|
||||||
|
// https://github.com/52North/helgoland-toolbox/blob/develop/libs/map/src/lib/base/map-options.ts
|
||||||
|
|
||||||
|
export interface LayerOptions {
|
||||||
|
label: string;
|
||||||
|
visible: boolean;
|
||||||
|
layer: Layer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// export type LayerMap = Map<string, LayerOptions>;
|
||||||
|
|
||||||
|
export class LayerMap extends Map<string, LayerOptions> {
|
||||||
|
}
|
134
resources/js/Components/Map/map.component.vue
Normal file
134
resources/js/Components/Map/map.component.vue
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
<template>
|
||||||
|
<div style="position: relative">
|
||||||
|
<!-- <Map className="h-36" :center="state.center" :zoom="state.zoom"> // map component content </Map> -->
|
||||||
|
<div :id="mapId" class="map-container mapDesktop rounded">
|
||||||
|
<ZoomControlComponent :mapId="mapId"></ZoomControlComponent>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { EventEmitter } from './EventEmitter';
|
||||||
|
import { Component, Vue, Prop } from 'vue-facing-decorator';
|
||||||
|
// import type { Coverage } from '@/Dataset';
|
||||||
|
import { Map, Control, MapOptions, LatLngBoundsExpression, tileLayer, latLng, latLngBounds, FeatureGroup } from 'leaflet';
|
||||||
|
import { LayerOptions, LayerMap } from './MapOptions';
|
||||||
|
import { MapService } from '@/Stores/map';
|
||||||
|
import ZoomControlComponent from './zoom.component.vue';
|
||||||
|
|
||||||
|
const DEFAULT_BASE_LAYER_NAME = 'BaseLayer';
|
||||||
|
// const DEFAULT_BASE_LAYER_URL = 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
|
||||||
|
const DEFAULT_BASE_LAYER_ATTRIBUTION = '© <a target="_blank" href="http://osm.org/copyright">OpenStreetMap</a> contributors';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
name: 'MapComponent',
|
||||||
|
components: {
|
||||||
|
ZoomControlComponent,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
export default class MapComponent extends Vue {
|
||||||
|
/**
|
||||||
|
* A map with the given ID is created inside this component.
|
||||||
|
* This ID can be used the get the map instance over the map cache service.
|
||||||
|
*/
|
||||||
|
@Prop()
|
||||||
|
public mapId: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The corresponding leaflet map options (see: https://leafletjs.com/reference-1.3.4.html#map-option)
|
||||||
|
*/
|
||||||
|
@Prop()
|
||||||
|
public mapOptions: MapOptions;
|
||||||
|
|
||||||
|
// markerService: MarkerService
|
||||||
|
/**
|
||||||
|
* Bounds for the map
|
||||||
|
*/
|
||||||
|
@Prop({ default: null })
|
||||||
|
public fitBounds: LatLngBoundsExpression;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describes the the zoom control options (see: https://leafletjs.com/reference-1.3.4.html#control-zoom)
|
||||||
|
*/
|
||||||
|
@Prop()
|
||||||
|
public zoomControlOptions: Control.ZoomOptions;
|
||||||
|
|
||||||
|
@Prop()
|
||||||
|
public baseMaps: LayerMap;
|
||||||
|
|
||||||
|
mapService = MapService();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Informs when initialization is done with map id.
|
||||||
|
*/
|
||||||
|
public onMapInitializedEvent: EventEmitter<string> = new EventEmitter<string>();
|
||||||
|
|
||||||
|
protected map!: Map;
|
||||||
|
protected drawnItems!: FeatureGroup<any>;
|
||||||
|
|
||||||
|
// @Prop({ type: Object })
|
||||||
|
// geolocation: Coverage;
|
||||||
|
|
||||||
|
mounted(): void {
|
||||||
|
this.initMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
public deleteTest(): void {
|
||||||
|
this.onMapInitializedEvent.emit(this.mapId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Emit(this.onMapInitializedEvent)
|
||||||
|
protected initMap(): void {
|
||||||
|
let map: Map = (this.map = new Map(this.mapId, this.mapOptions));
|
||||||
|
this.mapService.setMap(this.mapId, map);
|
||||||
|
map.scrollWheelZoom.disable();
|
||||||
|
|
||||||
|
// return this.mapId;
|
||||||
|
// this.$emit("onMapInitializedEvent", this.mapId);
|
||||||
|
this.onMapInitializedEvent.emit(this.mapId);
|
||||||
|
this.addBaseMap();
|
||||||
|
|
||||||
|
// if (this.fitBounds) {
|
||||||
|
// this.map.fitBounds(this.fitBounds);
|
||||||
|
// }
|
||||||
|
const southWest = latLng(46.5, 9.9);
|
||||||
|
const northEast = latLng(48.9, 16.9);
|
||||||
|
const bounds = latLngBounds(southWest, northEast);
|
||||||
|
map.fitBounds(bounds);
|
||||||
|
|
||||||
|
// Initialise the FeatureGroup to store editable layers
|
||||||
|
let drawnItems = (this.drawnItems = new FeatureGroup());
|
||||||
|
map.addLayer(drawnItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
private addBaseMap(layerOptions?: LayerOptions): void {
|
||||||
|
if (this.map) {
|
||||||
|
if (!this.baseMaps || this.baseMaps.size === 0) {
|
||||||
|
// let bmapgrau = tileLayer('https://{s}.wien.gv.at/basemap/bmapgrau/normal/google3857/{z}/{y}/{x}.png', {
|
||||||
|
// subdomains: ['maps', 'maps1', 'maps2', 'maps3', 'maps4'],
|
||||||
|
// attribution: 'Datenquelle: <a href="http://www.basemap.at/">basemap.at</a>',
|
||||||
|
// });
|
||||||
|
let osmGgray = tileLayer.wms('https://ows.terrestris.de/osm-gray/service', {
|
||||||
|
format: 'image/png',
|
||||||
|
attribution: DEFAULT_BASE_LAYER_ATTRIBUTION,
|
||||||
|
layers: 'OSM-WMS',
|
||||||
|
});
|
||||||
|
layerOptions = {
|
||||||
|
label: DEFAULT_BASE_LAYER_NAME,
|
||||||
|
visible: true,
|
||||||
|
layer: osmGgray,
|
||||||
|
};
|
||||||
|
this.map.attributionControl.setPrefix(false);
|
||||||
|
layerOptions.layer.addTo(this.map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="css">
|
||||||
|
.leaflet-container {
|
||||||
|
height: 600px; /* <-- map height */
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
106
resources/js/Components/Map/zoom.component.vue
Normal file
106
resources/js/Components/Map/zoom.component.vue
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
<template>
|
||||||
|
<div class="gba-control-zoom btn-group-vertical">
|
||||||
|
<!-- <button ref="inputPlus" type="button" class="button is-light is-small" :click.prevent="zoomIn">
|
||||||
|
<fa-icon [icon]="faPlus"></fa-icon>
|
||||||
|
</button> -->
|
||||||
|
<!-- <BaseButton ref="inputPlus" :icon="mdiPlus" color="white" rounded small @click.prevent="zoomIn" /> -->
|
||||||
|
<button
|
||||||
|
ref="inputPlus"
|
||||||
|
class="inline-flex cursor-pointer justify-center items-center whitespace-nowrap focus:outline-none transition-colors duration-150 border rounded ring-blue-700 bg-teal-50 text-black border-teal-50 hover:bg-gray-200 text-sm p-1"
|
||||||
|
type="button"
|
||||||
|
@click.prevent="zoomIn"
|
||||||
|
>
|
||||||
|
<BaseIcon v-if="mdiPlus" :path="mdiPlus" />
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
ref="inputMinus"
|
||||||
|
class="inline-flex cursor-pointer justify-center items-center whitespace-nowrap focus:outline-none transition-colors duration-150 border rounded ring-blue-700 bg-teal-50 text-black border-teal-50 hover:bg-gray-200 text-sm p-1"
|
||||||
|
type="button"
|
||||||
|
@click.prevent="zoomOut"
|
||||||
|
>
|
||||||
|
<BaseIcon v-if="mdiMinus" :path="mdiMinus" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { Component, Vue, Prop, Ref } from 'vue-facing-decorator';
|
||||||
|
import { MapService } from '@/Stores/map';
|
||||||
|
|
||||||
|
import BaseIcon from '@/Components/BaseIcon.vue';
|
||||||
|
import { mdiPlus, mdiMinus } from '@mdi/js';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
name: 'zoom-control',
|
||||||
|
components: {
|
||||||
|
BaseIcon
|
||||||
|
},
|
||||||
|
})
|
||||||
|
export default class ZoomControlComponent extends Vue {
|
||||||
|
mdiPlus = mdiPlus;
|
||||||
|
mdiMinus = mdiMinus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connect map id.
|
||||||
|
*/
|
||||||
|
@Prop() public mapId: string;
|
||||||
|
|
||||||
|
@Ref('inputPlus') private _inputPlus: HTMLElement;
|
||||||
|
@Ref('inputMinus') private _inpuMinus: HTMLElement;
|
||||||
|
|
||||||
|
mapService = MapService();
|
||||||
|
|
||||||
|
public zoomIn() {
|
||||||
|
let map = this.mapService.getMap(this.mapId);
|
||||||
|
map && map.zoomIn();
|
||||||
|
}
|
||||||
|
|
||||||
|
public zoomOut() {
|
||||||
|
let map = this.mapService.getMap(this.mapId);
|
||||||
|
map && map.zoomOut();
|
||||||
|
}
|
||||||
|
|
||||||
|
public updateDisabled() {
|
||||||
|
let map = this.mapService.getMap(this.mapId);
|
||||||
|
// let className = 'leaflet-disabled';
|
||||||
|
|
||||||
|
// this._inputPlus.nativeElement.disabled = false;
|
||||||
|
this._inputPlus.setAttribute('aria-disabled', 'false');
|
||||||
|
|
||||||
|
// this._inpuMinus.nativeElement.disabled = false;
|
||||||
|
this._inpuMinus.setAttribute('aria-disabled', 'false');
|
||||||
|
|
||||||
|
if (map.getZoom() === map.getMinZoom()) {
|
||||||
|
// this._inpuMinus.nativeElement.disabled = true;
|
||||||
|
this._inpuMinus.setAttribute('aria-disabled', 'true');
|
||||||
|
}
|
||||||
|
if (map.getZoom() === map.getMaxZoom()) {
|
||||||
|
// this._inputPlus.nativeElement.disabled = true;
|
||||||
|
this._inputPlus.setAttribute('aria-disabled', 'true');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="css">
|
||||||
|
.gba-control-zoom {
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 4px;
|
||||||
|
position: absolute;
|
||||||
|
left: 10px;
|
||||||
|
top: 10px;
|
||||||
|
z-index: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-group-vertical button {
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
margin-left: 0;
|
||||||
|
margin-top: 0.5em;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -34,7 +34,7 @@ import { Notification, NotificationGroup } from '@/notiwind';
|
||||||
<div class="px-4 py-2 -mx-3">
|
<div class="px-4 py-2 -mx-3">
|
||||||
<div class="mx-3">
|
<div class="mx-3">
|
||||||
<span class="font-semibold text-blue-500">{{ notification.title }}</span>
|
<span class="font-semibold text-blue-500">{{ notification.title }}</span>
|
||||||
<p class="text-sm text-gray-600">T{{ notification.text }}</p>
|
<p class="text-sm text-gray-600">{{ notification.text }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { Ref } from 'vue';
|
import { Ref } from 'vue';
|
||||||
|
|
||||||
export interface Dataset {
|
export interface Dataset {
|
||||||
[key: string]: string | Ref<string>| boolean | Array<Title> | Array<Description>| Array<Person> | number | (IErrorMessage | undefined);
|
[key: string]: string | Ref<string>| boolean | Array<Title> | Array<Description>| Array<Person> | number | (IErrorMessage | undefined) | Coverage;
|
||||||
language: Ref<string>;
|
language: Ref<string>;
|
||||||
// licenses: Array<number>;
|
// licenses: Array<number>;
|
||||||
rights: boolean;
|
rights: boolean;
|
||||||
|
@ -13,6 +13,7 @@ export interface Dataset {
|
||||||
contributors: Array<Person>;
|
contributors: Array<Person>;
|
||||||
project_id?: number;
|
project_id?: number;
|
||||||
embargo_date?: string,
|
embargo_date?: string,
|
||||||
|
coverage: Coverage,
|
||||||
errors?: IErrorMessage;
|
errors?: IErrorMessage;
|
||||||
// async (user): Promise<void>;
|
// async (user): Promise<void>;
|
||||||
}
|
}
|
||||||
|
@ -42,3 +43,21 @@ export interface Person {
|
||||||
interface IErrorMessage {
|
interface IErrorMessage {
|
||||||
[key: string]: Array<string>;
|
[key: string]: Array<string>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface Coverage {
|
||||||
|
x_min: number;
|
||||||
|
y_min: number;
|
||||||
|
x_max: number;
|
||||||
|
y_max: number;
|
||||||
|
elevation_min?: number;
|
||||||
|
elevation_max?: number;
|
||||||
|
elevation_absolut?: number;
|
||||||
|
|
||||||
|
depth_min?: number;
|
||||||
|
depth_max?: number;
|
||||||
|
depth_absolut?: number;
|
||||||
|
|
||||||
|
time_min?: number,
|
||||||
|
time_max?: number,
|
||||||
|
time_absolut?: number
|
||||||
|
}
|
56
resources/js/Decorators/confirmable.decorator.ts
Normal file
56
resources/js/Decorators/confirmable.decorator.ts
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
// import Swal, { SweetAlertOptions } from 'sweetalert2';
|
||||||
|
|
||||||
|
// Where “target” represents the class containing the method we’re decorating, “propertyKey” represents the method name,
|
||||||
|
// and “descriptor” will contain the method implementation. Within the decorator function we are able to do things before /
|
||||||
|
// after the method executes, or skip execution altogether based on arbitrary conditions. For example
|
||||||
|
|
||||||
|
// export function Test(target: Object, propertyKey: string, descriptor: PropertyDescriptor) {
|
||||||
|
export function Test(descriptor: PropertyDescriptor) {
|
||||||
|
// we first cache the original method implementation
|
||||||
|
const originalMethod = descriptor.value;
|
||||||
|
|
||||||
|
// then we overwrite it with a new implementation,
|
||||||
|
// ...args represent the original arguments
|
||||||
|
|
||||||
|
descriptor.value = function (...args) {
|
||||||
|
// do custom logic before executing the original method
|
||||||
|
// execute original method with the original arguments
|
||||||
|
const result = originalMethod.apply(this, args);
|
||||||
|
// execute custom logic after executing the original method
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
return descriptor;
|
||||||
|
}
|
||||||
|
// export function Confirmable(target?: Object, propertyKey: string, descriptor: PropertyDescriptor) {
|
||||||
|
// export function Confirmable(descriptor: PropertyDescriptor) {
|
||||||
|
// // Again, cache the original method for later use
|
||||||
|
// const originalMethod = descriptor.value;
|
||||||
|
|
||||||
|
// // the configuration object for sweetalert
|
||||||
|
// // const config: SweetAlertOptions = {
|
||||||
|
// const config: SweetAlertOptions = {
|
||||||
|
// title: 'Are you sure?',
|
||||||
|
// html: 'Do you want to perform this action?',
|
||||||
|
// showDenyButton: true,
|
||||||
|
// confirmButtonText: 'Yes',
|
||||||
|
// denyButtonText: 'No',
|
||||||
|
// icon: 'question',
|
||||||
|
// };
|
||||||
|
|
||||||
|
// // we write a new implementation for the method
|
||||||
|
// descriptor.value = async function (...args) {
|
||||||
|
// const res = await Swal.fire(config);
|
||||||
|
// // fire sweetalert with the config object
|
||||||
|
// if (res.isConfirmed) {
|
||||||
|
// // if user clicked yes,
|
||||||
|
// // we run the original method with the original arguments
|
||||||
|
// const result = originalMethod.apply(this, args);
|
||||||
|
|
||||||
|
// // and return the result
|
||||||
|
// return result;
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
// return descriptor;
|
||||||
|
// }
|
|
@ -15,6 +15,7 @@ import { stardust } from '@eidellev/adonis-stardust/client';
|
||||||
import CardBoxModal from '@/Components/CardBoxModal.vue';
|
import CardBoxModal from '@/Components/CardBoxModal.vue';
|
||||||
|
|
||||||
const isModalDangerActive = ref(false);
|
const isModalDangerActive = ref(false);
|
||||||
|
const deleteId = ref();
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
roles: {
|
roles: {
|
||||||
|
@ -51,22 +52,27 @@ const formDelete = useForm({});
|
||||||
// };
|
// };
|
||||||
|
|
||||||
const destroy = (id, e) => {
|
const destroy = (id, e) => {
|
||||||
console.log(id);
|
// console.log(id);
|
||||||
|
deleteId.value = id;
|
||||||
isModalDangerActive.value = true;
|
isModalDangerActive.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
const onConfirm = async () => {
|
const onConfirm = async (id) => {
|
||||||
await ormDelete.delete(stardust.route('role.destroy', [id]));
|
// let id = 6;
|
||||||
|
await formDelete.delete(stardust.route('role.destroy', [id]));
|
||||||
|
deleteId.value = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const onCancel = () => {
|
const onCancel = (id) => {
|
||||||
console.log('cancel');
|
// console.log('cancel');
|
||||||
|
deleteId.value = null;
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<CardBoxModal
|
<CardBoxModal
|
||||||
v-model="isModalDangerActive"
|
v-model="isModalDangerActive"
|
||||||
|
:delete-id="deleteId"
|
||||||
large-title="Please confirm"
|
large-title="Please confirm"
|
||||||
button="danger"
|
button="danger"
|
||||||
button-label="Delete"
|
button-label="Delete"
|
||||||
|
|
|
@ -10,6 +10,7 @@ import {
|
||||||
mdiInformationOutline,
|
mdiInformationOutline,
|
||||||
mdiBookOpenPageVariant,
|
mdiBookOpenPageVariant,
|
||||||
mdiImageText,
|
mdiImageText,
|
||||||
|
mdiEarthPlus,
|
||||||
} from '@mdi/js';
|
} from '@mdi/js';
|
||||||
import LayoutAuthenticated from '@/Layouts/LayoutAuthenticated.vue';
|
import LayoutAuthenticated from '@/Layouts/LayoutAuthenticated.vue';
|
||||||
import SectionMain from '@/Components/SectionMain.vue';
|
import SectionMain from '@/Components/SectionMain.vue';
|
||||||
|
@ -35,7 +36,9 @@ import SearchAutocomplete from '@/Components/SearchAutocomplete.vue';
|
||||||
import TablePersons from '@/Components/TablePersons.vue';
|
import TablePersons from '@/Components/TablePersons.vue';
|
||||||
import { MainService } from '@/Stores/main';
|
import { MainService } from '@/Stores/main';
|
||||||
import { notify } from '@/notiwind';
|
import { notify } from '@/notiwind';
|
||||||
// import NotificationToast from '@/Components/NotificationToast.vue';
|
import LocationMap from '@/Components/Map/map.component.vue';
|
||||||
|
import { MapOptions, LatLngBoundsExpression } from 'leaflet';
|
||||||
|
import { LayerOptions } from '@/Components/Map/MapOptions';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
licenses: {
|
licenses: {
|
||||||
|
@ -89,6 +92,21 @@ if (Object.keys(mainService.dataset).length == 0) {
|
||||||
contributors: [],
|
contributors: [],
|
||||||
project_id: undefined,
|
project_id: undefined,
|
||||||
embargo_date: '',
|
embargo_date: '',
|
||||||
|
coverage: {
|
||||||
|
x_min: 0,
|
||||||
|
y_min: 0,
|
||||||
|
x_max: 0,
|
||||||
|
y_max: 0,
|
||||||
|
elevation_min: undefined,
|
||||||
|
elevation_max: undefined,
|
||||||
|
elevation_absolut: undefined,
|
||||||
|
depth_min: undefined,
|
||||||
|
depth_max: undefined,
|
||||||
|
depth_absolut: undefined,
|
||||||
|
time_min: undefined,
|
||||||
|
time_max: undefined,
|
||||||
|
time_absolut: undefined,
|
||||||
|
},
|
||||||
// errors: undefined,
|
// errors: undefined,
|
||||||
};
|
};
|
||||||
// mainService.setDataset(dataset, language);
|
// mainService.setDataset(dataset, language);
|
||||||
|
@ -109,6 +127,7 @@ if (Object.keys(mainService.dataset).length == 0) {
|
||||||
contributors: mainService.dataset.contributors,
|
contributors: mainService.dataset.contributors,
|
||||||
project_id: mainService.dataset.project_id,
|
project_id: mainService.dataset.project_id,
|
||||||
embargo_date: mainService.dataset.embargo_date,
|
embargo_date: mainService.dataset.embargo_date,
|
||||||
|
coverage: mainService.dataset.coverage,
|
||||||
};
|
};
|
||||||
for (let index in mainService.dataset.titles) {
|
for (let index in mainService.dataset.titles) {
|
||||||
let title: Title = mainService.dataset.titles[index];
|
let title: Title = mainService.dataset.titles[index];
|
||||||
|
@ -134,7 +153,6 @@ if (Object.keys(mainService.dataset).length == 0) {
|
||||||
// descriptions: [{ value: '', type: 'Abstract', language: language }],
|
// descriptions: [{ value: '', type: 'Abstract', language: language }],
|
||||||
// });
|
// });
|
||||||
const form = useForm<Dataset>(dataset);
|
const form = useForm<Dataset>(dataset);
|
||||||
// dataset.language.value = 'de';
|
|
||||||
|
|
||||||
// const emit = defineEmits(['update:modelValue', 'setRef']);
|
// const emit = defineEmits(['update:modelValue', 'setRef']);
|
||||||
// computed({
|
// computed({
|
||||||
|
@ -147,6 +165,18 @@ const form = useForm<Dataset>(dataset);
|
||||||
const isModalActive = ref(false);
|
const isModalActive = ref(false);
|
||||||
const formStep = ref(1);
|
const formStep = ref(1);
|
||||||
|
|
||||||
|
const mapOptions: MapOptions = {
|
||||||
|
center: [48.208174, 16.373819],
|
||||||
|
zoom: 3,
|
||||||
|
zoomControl: false,
|
||||||
|
};
|
||||||
|
const baseMaps: Map<string, LayerOptions> = new Map<string, LayerOptions>();
|
||||||
|
const fitBounds: LatLngBoundsExpression = [
|
||||||
|
[46.4318173285, 9.47996951665],
|
||||||
|
[49.0390742051, 16.9796667823],
|
||||||
|
];
|
||||||
|
const mapId = "test";
|
||||||
|
|
||||||
// const submit = async () => {
|
// const submit = async () => {
|
||||||
// await router.post(stardust.route('user.store'), form, {
|
// await router.post(stardust.route('user.store'), form, {
|
||||||
// onSuccess: () => {
|
// onSuccess: () => {
|
||||||
|
@ -224,6 +254,11 @@ const onAddContributor = (person) => {
|
||||||
notify({ type: 'info', text: 'person has been successfully added as contributor' }, 4000);
|
notify({ type: 'info', text: 'person has been successfully added as contributor' }, 4000);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onMapInitialized = (newItem) => {
|
||||||
|
// notify({ type: 'info', text: message });
|
||||||
|
console.log(newItem);
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -698,6 +733,18 @@ const onAddContributor = (person) => {
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</FormField>
|
</FormField>
|
||||||
</div>
|
</div>
|
||||||
|
<CardBox class="mb-6 shadow" has-table title="Geo Location" :icon="mdiEarthPlus">
|
||||||
|
<!-- @onMapInitialized="onMapInitialized" -->
|
||||||
|
<!-- v-bind-event="{ mapId, name: mapId }" -->
|
||||||
|
<LocationMap
|
||||||
|
:mapOptions="mapOptions"
|
||||||
|
:baseMaps="baseMaps"
|
||||||
|
:fitBounds="fitBounds"
|
||||||
|
:mapId="mapId"
|
||||||
|
v-bind-event:onMapInitializedEvent="onMapInitialized"
|
||||||
|
></LocationMap>
|
||||||
|
<!-- <label v-bind-event="{ for: mapId }" /> -->
|
||||||
|
</CardBox>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="formStep == 4">
|
<div v-if="formStep == 4">
|
||||||
|
|
46
resources/js/Stores/map.ts
Normal file
46
resources/js/Stores/map.ts
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
import { defineStore } from 'pinia';
|
||||||
|
// import axios from 'axios';
|
||||||
|
|
||||||
|
|
||||||
|
export const MapService = defineStore('map', {
|
||||||
|
state: () => ({
|
||||||
|
|
||||||
|
// dataset: {} as Dataset,
|
||||||
|
|
||||||
|
mapService: new Map<string, any>(),
|
||||||
|
|
||||||
|
}),
|
||||||
|
actions: {
|
||||||
|
// payload = authenticated user
|
||||||
|
setUser(payload) {
|
||||||
|
if (payload.name) {
|
||||||
|
this.userName = payload.name;
|
||||||
|
}
|
||||||
|
if (payload.email) {
|
||||||
|
this.userEmail = payload.email;
|
||||||
|
}
|
||||||
|
if (payload.avatar) {
|
||||||
|
this.userAvatar = payload.avatar;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
getMap(id: string): L.Map {
|
||||||
|
return this.mapService.get(id);
|
||||||
|
},
|
||||||
|
|
||||||
|
setMap(id: string, map) {
|
||||||
|
this.mapService.set(id, map);
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
hasMap(id: string): boolean {
|
||||||
|
return this.mapService.has(id);
|
||||||
|
},
|
||||||
|
|
||||||
|
deleteMap(id: string): boolean {
|
||||||
|
return this.mapService.delete(id);
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
},
|
||||||
|
});
|
|
@ -11,6 +11,7 @@ import { LayoutService } from '@/Stores/layout';
|
||||||
import { MainService } from '@/Stores/main';
|
import { MainService } from '@/Stores/main';
|
||||||
import { darkModeKey, styleKey } from '@/config';
|
import { darkModeKey, styleKey } from '@/config';
|
||||||
const pinia = createPinia();
|
const pinia = createPinia();
|
||||||
|
import { EmitterPlugin } from '@/test';
|
||||||
|
|
||||||
import { initRoutes } from '@eidellev/adonis-stardust/client';
|
import { initRoutes } from '@eidellev/adonis-stardust/client';
|
||||||
initRoutes();
|
initRoutes();
|
||||||
|
@ -42,6 +43,7 @@ createInertiaApp({
|
||||||
createApp({ render: () => h(App, props) })
|
createApp({ render: () => h(App, props) })
|
||||||
.use(plugin)
|
.use(plugin)
|
||||||
.use(pinia)
|
.use(pinia)
|
||||||
|
.use(EmitterPlugin)
|
||||||
// .component('inertia-link', Link)
|
// .component('inertia-link', Link)
|
||||||
.mount(el);
|
.mount(el);
|
||||||
},
|
},
|
||||||
|
|
66
resources/js/test.ts
Normal file
66
resources/js/test.ts
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
import type { Directive, Plugin } from 'vue';
|
||||||
|
import type { EventEmitter } from '@/Components/Map/EventEmitter';
|
||||||
|
|
||||||
|
// https://vuejs.org/guide/reusability/custom-directives.html#directive-hooks
|
||||||
|
// https://learnvue.co/articles/vue-custom-directives
|
||||||
|
let emitter: EventEmitter<string>;
|
||||||
|
|
||||||
|
export const EmitterDirective: Directive<any> = {
|
||||||
|
mounted: (el, binding, vnode) => {
|
||||||
|
// el: the element the directive is bound to. This can be used to directly manipulate
|
||||||
|
binding.arg && el.setAttribute('event', binding.arg);
|
||||||
|
|
||||||
|
// const vm = binding.instance;
|
||||||
|
// let iwas = vm?.$data.onMapInitializedEvent;
|
||||||
|
// var handlers = (vnode.data && vnode.data.on) ||
|
||||||
|
// (vnode.componentOptions && vnode.componentOptions.listeners);
|
||||||
|
|
||||||
|
//vnode: the underlying VNode representing the bound element.
|
||||||
|
|
||||||
|
//binding.instance: The instance of the component where the directive is used.
|
||||||
|
// const instance = binding.instance;
|
||||||
|
|
||||||
|
// if (vnode && vnode.dirs) {
|
||||||
|
// const instance = vnode.dirs[0].instance;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// binding.value
|
||||||
|
// arg: 'onMapInitialized'
|
||||||
|
// dir: {created: ƒ}
|
||||||
|
// instance: Proxy {__v_skip: true}
|
||||||
|
// modifiers: {}
|
||||||
|
// oldValue: undefined
|
||||||
|
// value: {mapId: 'test', name: 'test'}
|
||||||
|
const handler = binding.value;
|
||||||
|
|
||||||
|
// let instanceComp = binding.instance;
|
||||||
|
// @ts-ignore
|
||||||
|
if (vnode.ctx) {
|
||||||
|
// @ts-ignore
|
||||||
|
emitter = vnode.ctx.data[binding.arg];
|
||||||
|
emitter.subscribe(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
// for (const key in binding.value) {
|
||||||
|
// const k = key; //kebabCase(key);
|
||||||
|
// if (!el.hasAttribute(k)) {
|
||||||
|
// el.setAttribute(k, binding.value[key]);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
},
|
||||||
|
unmounted() {
|
||||||
|
emitter.unsubscribe();
|
||||||
|
},
|
||||||
|
// getSSRProps(binding) {
|
||||||
|
// /* c8 ignore next */
|
||||||
|
// if (!binding.value) return {};
|
||||||
|
|
||||||
|
// return Object.fromEntries(Object.entries(binding.value).map(([key, value]) => [kebabCase(key), value]));
|
||||||
|
// },
|
||||||
|
};
|
||||||
|
|
||||||
|
export const EmitterPlugin: Plugin = {
|
||||||
|
install(app) {
|
||||||
|
app.directive('bind-event', EmitterDirective);
|
||||||
|
},
|
||||||
|
};
|
|
@ -81,6 +81,7 @@ module.exports = {
|
||||||
{ values: theme('asideScrollbars') },
|
{ values: theme('asideScrollbars') },
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
require('@tailwindcss/line-clamp'),
|
// As of Tailwind CSS v3.3, the `@tailwindcss/line-clamp` plugin is now included by default
|
||||||
|
// require('@tailwindcss/line-clamp'),
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue
Block a user