inviton-powerduck 0.0.128 → 0.0.129
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -83,4 +83,9 @@ export interface IPowerduckSystemResources {
|
|
|
83
83
|
signInX: string;
|
|
84
84
|
signInFigma: string;
|
|
85
85
|
signInDribble: string;
|
|
86
|
+
gpsBoundingBoxLabel: string;
|
|
87
|
+
gpsBoundingBoxX1: string;
|
|
88
|
+
gpsBoundingBoxX2: string;
|
|
89
|
+
gpsBoundingBoxY1: string;
|
|
90
|
+
gpsBoundingBoxY2: string;
|
|
86
91
|
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { Component, Prop, toNative } from 'vue-facing-decorator';
|
|
2
|
+
import TsxComponent from '../../app/vuetsx';
|
|
3
|
+
import { ValidationState } from '../../common/static-wrappers/interfaces/validation-interface';
|
|
4
|
+
import BoundingBox from '../../data/bounding-box';
|
|
5
|
+
import FlexContainer from '../form/flex-container';
|
|
6
|
+
import FlexFormItem from '../form/form-item-flex';
|
|
7
|
+
import FormItemWrapper from '../form/form-item-wrapper';
|
|
8
|
+
import OpenStreetMap from '../open-street-map/open-street-map';
|
|
9
|
+
import NumericInput, { NumericInputMode } from './numeric-input';
|
|
10
|
+
import PowerduckState from '../../app/powerduck-state';
|
|
11
|
+
|
|
12
|
+
interface GpsBoundingBoxInputArgs {
|
|
13
|
+
bBoxModel: BoundingBox;
|
|
14
|
+
mandatory?: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
@Component
|
|
18
|
+
class GpsBoundingBoxInputComponent extends TsxComponent<GpsBoundingBoxInputArgs> implements GpsBoundingBoxInputArgs {
|
|
19
|
+
@Prop() bBoxModel: BoundingBox;
|
|
20
|
+
@Prop() mandatory?: boolean;
|
|
21
|
+
|
|
22
|
+
onChange (field: keyof BoundingBox, value: number) {
|
|
23
|
+
if (value) {
|
|
24
|
+
this.bBoxModel[field] = parseFloat(value.toFixed(7));
|
|
25
|
+
} else {
|
|
26
|
+
this.bBoxModel[field] = null;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
renderInput (
|
|
31
|
+
h: any,
|
|
32
|
+
label: string,
|
|
33
|
+
value: number,
|
|
34
|
+
onChanged?: (value: number) => void,
|
|
35
|
+
showClearValueButton?: boolean,
|
|
36
|
+
validationState?: ValidationState,
|
|
37
|
+
) {
|
|
38
|
+
return (
|
|
39
|
+
<FlexFormItem flexFill={true}>
|
|
40
|
+
<NumericInput
|
|
41
|
+
mandatory={this.mandatory}
|
|
42
|
+
label={label}
|
|
43
|
+
value={value}
|
|
44
|
+
step={0.000001}
|
|
45
|
+
mode={NumericInputMode.Clasic}
|
|
46
|
+
showClearValueButton={showClearValueButton}
|
|
47
|
+
validationState={validationState}
|
|
48
|
+
changed={(e) => {
|
|
49
|
+
if (onChanged != null) {
|
|
50
|
+
onChanged(e);
|
|
51
|
+
}
|
|
52
|
+
}}
|
|
53
|
+
/>
|
|
54
|
+
</FlexFormItem>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
render (h) {
|
|
59
|
+
if (!this.bBoxModel) {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<div>
|
|
65
|
+
<FormItemWrapper label={PowerduckState.getResourceValue('gpsBoundingBoxLabel')} mandatory={this.mandatory}>
|
|
66
|
+
<FlexContainer fullWidthOnMobile={true}>
|
|
67
|
+
<FlexFormItem>
|
|
68
|
+
{this.renderInput(
|
|
69
|
+
h,
|
|
70
|
+
PowerduckState.getResourceValue('gpsBoundingBoxX1'),
|
|
71
|
+
this.bBoxModel.x1,
|
|
72
|
+
e => this.onChange('x1', e),
|
|
73
|
+
)}
|
|
74
|
+
{this.renderInput(
|
|
75
|
+
h,
|
|
76
|
+
PowerduckState.getResourceValue('gpsBoundingBoxX2'),
|
|
77
|
+
this.bBoxModel.x2,
|
|
78
|
+
e => this.onChange('x2', e),
|
|
79
|
+
)}
|
|
80
|
+
</FlexFormItem>
|
|
81
|
+
<FlexFormItem>
|
|
82
|
+
{this.renderInput(
|
|
83
|
+
h,
|
|
84
|
+
PowerduckState.getResourceValue('gpsBoundingBoxY1'),
|
|
85
|
+
this.bBoxModel.y1,
|
|
86
|
+
e => this.onChange('y1', e),
|
|
87
|
+
)}
|
|
88
|
+
{this.renderInput(
|
|
89
|
+
h,
|
|
90
|
+
PowerduckState.getResourceValue('gpsBoundingBoxY2'),
|
|
91
|
+
this.bBoxModel.y2,
|
|
92
|
+
e => this.onChange('y2', e),
|
|
93
|
+
)}
|
|
94
|
+
</FlexFormItem>
|
|
95
|
+
</FlexContainer>
|
|
96
|
+
</FormItemWrapper>
|
|
97
|
+
|
|
98
|
+
<FormItemWrapper label={null} mandatory={false}>
|
|
99
|
+
<div class="rounded">
|
|
100
|
+
<OpenStreetMap
|
|
101
|
+
ref="openStreetMap"
|
|
102
|
+
isCenterHidden={true}
|
|
103
|
+
bBox={this.bBoxModel}
|
|
104
|
+
/>
|
|
105
|
+
</div>
|
|
106
|
+
</FormItemWrapper>
|
|
107
|
+
</div>
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const GpsBoundingBoxInput = toNative(GpsBoundingBoxInputComponent);
|
|
113
|
+
export default GpsBoundingBoxInput;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { LGeoJson, LLayerGroup, LMap, LMarker, LTileLayer } from '@vue-leaflet/vue-leaflet';
|
|
1
|
+
import { LGeoJson, LLayerGroup, LMap, LMarker, LPolygon, LTileLayer } from '@vue-leaflet/vue-leaflet';
|
|
2
2
|
import L from 'leaflet';
|
|
3
3
|
import * as LCluster from 'leaflet.markercluster';
|
|
4
4
|
import { Prop, toNative, Watch } from 'vue-facing-decorator';
|
|
5
5
|
import TsxComponent, { Component } from '../../app/vuetsx';
|
|
6
6
|
import { isNullOrEmpty } from '../../common/utils/is-null-or-empty';
|
|
7
7
|
import { ModalUtils } from '../modal/modal-utils';
|
|
8
|
+
import BoundingBox from '../../data/bounding-box';
|
|
8
9
|
import iconUrl from './img/marker-icon.png';
|
|
9
10
|
import GestureHandling from './ts/gesture-handling/gesture-handling';
|
|
10
11
|
import 'leaflet/dist/leaflet.css';
|
|
@@ -57,6 +58,7 @@ interface OpenStreetMapClusterOptions {
|
|
|
57
58
|
interface OpenStreetMapArgs {
|
|
58
59
|
latitude?: string;
|
|
59
60
|
longitude?: string;
|
|
61
|
+
bBox?: BoundingBox;
|
|
60
62
|
name?: string;
|
|
61
63
|
address?: string;
|
|
62
64
|
is16by9?: boolean;
|
|
@@ -75,7 +77,7 @@ interface OpenStreetMapArgs {
|
|
|
75
77
|
}
|
|
76
78
|
|
|
77
79
|
export class OpenStreetMapHelper {
|
|
78
|
-
static getMarkerIcon(): L.Icon<L.IconOptions> {
|
|
80
|
+
static getMarkerIcon (): L.Icon<L.IconOptions> {
|
|
79
81
|
return L.icon({
|
|
80
82
|
iconUrl,
|
|
81
83
|
iconAnchor: [
|
|
@@ -109,11 +111,13 @@ export interface GoogleMapRefreshArgs {
|
|
|
109
111
|
'l-marker': LMarker,
|
|
110
112
|
'l-geo-json': LGeoJson,
|
|
111
113
|
'l-layer-group': LLayerGroup,
|
|
114
|
+
'l-polygon': LPolygon,
|
|
112
115
|
},
|
|
113
116
|
})
|
|
114
117
|
export class OpenStreetMapComponent extends TsxComponent<OpenStreetMapArgs> implements OpenStreetMapArgs {
|
|
115
118
|
@Prop() latitude!: string;
|
|
116
119
|
@Prop() longitude!: string;
|
|
120
|
+
@Prop() bBox?: BoundingBox;
|
|
117
121
|
@Prop() name!: string;
|
|
118
122
|
@Prop() address!: string;
|
|
119
123
|
@Prop() is16by9!: boolean;
|
|
@@ -132,12 +136,14 @@ export class OpenStreetMapComponent extends TsxComponent<OpenStreetMapArgs> impl
|
|
|
132
136
|
leafletIcon: any = null;
|
|
133
137
|
markerClusters: LCluster.MarkerClusterGroup = null;
|
|
134
138
|
|
|
135
|
-
mounted() {
|
|
139
|
+
mounted () {
|
|
136
140
|
this.initIcon();
|
|
137
141
|
this.waitForLeaflet().then(() => {
|
|
138
142
|
ModalUtils.handleModalMountDelay(this, () => {
|
|
139
143
|
this.initGestureHandling();
|
|
140
144
|
this.invalidateSize();
|
|
145
|
+
this.onBoundingBoxChanged();
|
|
146
|
+
|
|
141
147
|
if (this.initComplete != null) {
|
|
142
148
|
this.$nextTick(() => {
|
|
143
149
|
this.initComplete(this.getLeaflet(), this.getMap());
|
|
@@ -147,7 +153,15 @@ export class OpenStreetMapComponent extends TsxComponent<OpenStreetMapArgs> impl
|
|
|
147
153
|
});
|
|
148
154
|
}
|
|
149
155
|
|
|
150
|
-
|
|
156
|
+
@Watch('bBox', { immediate: false, deep: true })
|
|
157
|
+
onBoundingBoxChanged () {
|
|
158
|
+
const bounds = this.getBoundingBoxLatLngBounds();
|
|
159
|
+
if (bounds) {
|
|
160
|
+
this.getLeaflet()?.fitBounds(bounds);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
async waitForLeaflet (timeout = 15000, interval = 100) {
|
|
151
165
|
const startTime = Date.now();
|
|
152
166
|
while (!this.getLeaflet()) {
|
|
153
167
|
if (Date.now() - startTime > timeout) {
|
|
@@ -160,25 +174,25 @@ export class OpenStreetMapComponent extends TsxComponent<OpenStreetMapArgs> impl
|
|
|
160
174
|
return this.getLeaflet();
|
|
161
175
|
}
|
|
162
176
|
|
|
163
|
-
initIcon() {
|
|
177
|
+
initIcon () {
|
|
164
178
|
if (this.leafletIcon == null) {
|
|
165
179
|
this.leafletIcon = OpenStreetMapHelper.getMarkerIcon();
|
|
166
180
|
}
|
|
167
181
|
}
|
|
168
182
|
|
|
169
183
|
@Watch('geoJSON')
|
|
170
|
-
onGeoJsonChanged() {
|
|
184
|
+
onGeoJsonChanged () {
|
|
171
185
|
if (this.geoJSONClustering) {
|
|
172
186
|
this.initCluster();
|
|
173
187
|
}
|
|
174
188
|
}
|
|
175
189
|
|
|
176
190
|
@Watch('mapUrl')
|
|
177
|
-
onMapUrlChanged() {
|
|
191
|
+
onMapUrlChanged () {
|
|
178
192
|
this.invalidateSize();
|
|
179
193
|
}
|
|
180
194
|
|
|
181
|
-
initGestureHandling() {
|
|
195
|
+
initGestureHandling () {
|
|
182
196
|
if (this.gestureHandling == true) {
|
|
183
197
|
const leaflet = this.getLeaflet();
|
|
184
198
|
if ((leaflet as any)._gesturesBinder != true) {
|
|
@@ -188,10 +202,10 @@ export class OpenStreetMapComponent extends TsxComponent<OpenStreetMapArgs> impl
|
|
|
188
202
|
}
|
|
189
203
|
}
|
|
190
204
|
|
|
191
|
-
initCluster() {
|
|
205
|
+
initCluster () {
|
|
192
206
|
this.markerClusters?.clearLayers();
|
|
193
207
|
this.markerClusters = new LCluster.MarkerClusterGroup(this.clusterOptions || {
|
|
194
|
-
iconCreateFunction(cluster) {
|
|
208
|
+
iconCreateFunction (cluster) {
|
|
195
209
|
const html = `<div class="cluster-marker ">${cluster.getChildCount()}<div class="pulse-animation"></div></div>`;
|
|
196
210
|
return L.divIcon({ html, className: 'cluster-icon' });
|
|
197
211
|
},
|
|
@@ -209,7 +223,7 @@ export class OpenStreetMapComponent extends TsxComponent<OpenStreetMapArgs> impl
|
|
|
209
223
|
}
|
|
210
224
|
}
|
|
211
225
|
|
|
212
|
-
invalidateSize() {
|
|
226
|
+
invalidateSize () {
|
|
213
227
|
const leaflet = this.getLeaflet();
|
|
214
228
|
if (leaflet != null) {
|
|
215
229
|
this.$nextTick(() => {
|
|
@@ -218,41 +232,88 @@ export class OpenStreetMapComponent extends TsxComponent<OpenStreetMapArgs> impl
|
|
|
218
232
|
}
|
|
219
233
|
}
|
|
220
234
|
|
|
221
|
-
getNumeric(val: string): number {
|
|
235
|
+
getNumeric (val: string): number {
|
|
222
236
|
return Number((val || '').toString().split(',').join(''));
|
|
223
237
|
}
|
|
224
238
|
|
|
225
|
-
getZoomValue(): number {
|
|
239
|
+
getZoomValue (): number {
|
|
226
240
|
if (this.defaultZoom != null) {
|
|
227
241
|
return this.defaultZoom;
|
|
242
|
+
} else if (this.bBox != null) {
|
|
243
|
+
return undefined;
|
|
228
244
|
} else {
|
|
229
245
|
return 16;
|
|
230
246
|
}
|
|
231
247
|
}
|
|
232
248
|
|
|
233
|
-
|
|
249
|
+
getCenter () {
|
|
250
|
+
if (this.bBox != null) {
|
|
251
|
+
const { x1, x2, y1, y2 } = this.bBox;
|
|
252
|
+
const lat = (y1 + y2) / 2;
|
|
253
|
+
const lng = (x1 + x2) / 2;
|
|
254
|
+
return [lat, lng];
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
const locArr = this.getLocArr();
|
|
258
|
+
return locArr;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
getLocPoint () {
|
|
234
262
|
return {
|
|
235
263
|
lat: this.getNumeric(this.latitude),
|
|
236
264
|
lng: this.getNumeric(this.longitude),
|
|
237
265
|
};
|
|
238
266
|
}
|
|
239
267
|
|
|
240
|
-
getLocArr() {
|
|
268
|
+
getLocArr () {
|
|
241
269
|
return [
|
|
242
270
|
this.getNumeric(this.latitude),
|
|
243
271
|
this.getNumeric(this.longitude),
|
|
244
272
|
];
|
|
245
273
|
}
|
|
246
274
|
|
|
247
|
-
getMap() {
|
|
275
|
+
getMap () {
|
|
248
276
|
return this.$refs.mainMap;
|
|
249
277
|
}
|
|
250
278
|
|
|
251
|
-
getLeaflet() {
|
|
279
|
+
getLeaflet () {
|
|
252
280
|
return (this.getMap() as any)?.leafletObject;
|
|
253
281
|
}
|
|
254
282
|
|
|
255
|
-
|
|
283
|
+
getBoundingBoxCorners () {
|
|
284
|
+
if (!this.bBox) {
|
|
285
|
+
return [];
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
const { x1, x2, y1, y2 } = this.bBox;
|
|
289
|
+
if ([x1, x2, y1, y2].some(p => p == null)) {
|
|
290
|
+
return [];
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
const minLat = Math.min(y1, y2);
|
|
294
|
+
const maxLat = Math.max(y1, y2);
|
|
295
|
+
const minLng = Math.min(x1, x2);
|
|
296
|
+
const maxLng = Math.max(x1, x2);
|
|
297
|
+
|
|
298
|
+
return [
|
|
299
|
+
[maxLat, minLng],
|
|
300
|
+
[maxLat, maxLng],
|
|
301
|
+
[minLat, maxLng],
|
|
302
|
+
[minLat, minLng],
|
|
303
|
+
[maxLat, minLng],
|
|
304
|
+
];
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
getBoundingBoxLatLngBounds (): L.LatLngBounds {
|
|
308
|
+
const corners = this.getBoundingBoxCorners();
|
|
309
|
+
if (corners.length < 2) {
|
|
310
|
+
return null;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
return L.latLngBounds(corners);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
render (h) {
|
|
256
317
|
if (this.is16by9 == false) {
|
|
257
318
|
return this.renderLeaflet(h, { height: '100%' });
|
|
258
319
|
}
|
|
@@ -270,17 +331,26 @@ export class OpenStreetMapComponent extends TsxComponent<OpenStreetMapArgs> impl
|
|
|
270
331
|
);
|
|
271
332
|
}
|
|
272
333
|
|
|
273
|
-
private renderLeaflet(h, style: object) {
|
|
334
|
+
private renderLeaflet (h, style: object) {
|
|
274
335
|
const locArr = this.getLocArr();
|
|
275
336
|
|
|
276
337
|
return (
|
|
277
|
-
<l-map style={style} zoom={this.getZoomValue()} options={this.mapOptions} maxZoom={this.maxZoom} center={
|
|
338
|
+
<l-map style={style} zoom={this.getZoomValue()} options={this.mapOptions} maxZoom={this.maxZoom} center={this.getCenter()} ref="mainMap">
|
|
278
339
|
<l-tile-layer url={this.mapUrl} options={this.options} noWrap attribution={'© <a target="_blank" href="http://osm.org/copyright">OpenStreetMap</a> contributors'}></l-tile-layer>
|
|
279
340
|
{!this.isCenterHidden
|
|
280
|
-
|
|
341
|
+
&& <l-marker lat-lng={locArr} icon={this.leafletIcon}></l-marker>}
|
|
281
342
|
|
|
282
343
|
{!isNullOrEmpty(this.geoJSON)
|
|
283
|
-
|
|
344
|
+
&& <l-geo-json ref="geoJson" options={this.geoJSONConfig != null && this.geoJSONConfig} geojson={this.geoJSONClustering ? [] : this.geoJSON}></l-geo-json>}
|
|
345
|
+
|
|
346
|
+
{this.bBox && (
|
|
347
|
+
<l-polygon
|
|
348
|
+
lat-lngs={this.getBoundingBoxCorners()}
|
|
349
|
+
color="blue"
|
|
350
|
+
weight={2}
|
|
351
|
+
fillOpacity={0.1}
|
|
352
|
+
/>
|
|
353
|
+
)}
|
|
284
354
|
|
|
285
355
|
{this.$slots.default?.()}
|
|
286
356
|
</l-map>
|