@dative-gpi/foundation-shared-components 1.0.137-maps4 → 1.0.137-reportV2
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.
- package/components/FSCheckbox.vue +0 -1
- package/components/FSRadio.vue +0 -1
- package/components/FSSlider.vue +1 -2
- package/components/FSSwitch.vue +44 -38
- package/components/fields/FSBaseField.vue +0 -1
- package/components/fields/FSRichTextField.vue +1 -2
- package/components/map/FSMap.vue +126 -74
- package/components/map/FSMapMarker.vue +6 -6
- package/components/map/FSMapMarkerClusterGroup.vue +1 -1
- package/components/map/FSMapOverlay.vue +11 -14
- package/components/map/FSMapTileLayer.vue +8 -14
- package/components/tiles/FSGroupTileUI.vue +1 -14
- package/models/map.ts +10 -12
- package/package.json +4 -4
- package/styles/components/fs_map.scss +10 -46
- package/styles/components/index.scss +0 -1
- package/tools/index.ts +1 -0
- package/tools/reportsTools.ts +38 -0
- package/assets/images/map/snow.png +0 -0
- package/components/deviceOrganisations/FSStatusRichCard.vue +0 -170
- package/components/selects/FSSelectMapLayer.vue +0 -68
- package/styles/components/fs_status_rich_card.scss +0 -13
package/components/FSRadio.vue
CHANGED
package/components/FSSlider.vue
CHANGED
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
:elevation="0"
|
|
36
36
|
:tickSize="4"
|
|
37
37
|
:modelValue="$props.modelValue ?? undefined"
|
|
38
|
-
@update:modelValue="$emit('update:modelValue',
|
|
38
|
+
@update:modelValue="(value) => $emit('update:modelValue', value)"
|
|
39
39
|
v-bind="$attrs"
|
|
40
40
|
>
|
|
41
41
|
<template
|
|
@@ -55,7 +55,6 @@
|
|
|
55
55
|
v-if="$props.description"
|
|
56
56
|
class="fs-slider-description"
|
|
57
57
|
font="text-overline"
|
|
58
|
-
:lineClamp="2"
|
|
59
58
|
:style="style"
|
|
60
59
|
>
|
|
61
60
|
{{ $props.description }}
|
package/components/FSSwitch.vue
CHANGED
|
@@ -1,25 +1,29 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
2
|
+
<FSRow
|
|
3
|
+
width="hug"
|
|
4
|
+
align="top-left"
|
|
5
|
+
gap="16px"
|
|
3
6
|
padding="8px 0px"
|
|
7
|
+
:wrap="false"
|
|
4
8
|
>
|
|
5
|
-
<
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
9
|
+
<v-switch
|
|
10
|
+
v-if="variant == 'left'"
|
|
11
|
+
class="fs-switch"
|
|
12
|
+
hide-details
|
|
13
|
+
inset
|
|
14
|
+
:validateOn="validateOn"
|
|
15
|
+
:rules="$props.rules"
|
|
16
|
+
:ripple="false"
|
|
17
|
+
:style="style"
|
|
18
|
+
:modelValue="$props.modelValue"
|
|
19
|
+
@update:modelValue="onToggle"
|
|
20
|
+
v-bind="$attrs"
|
|
21
|
+
/>
|
|
22
|
+
<slot>
|
|
23
|
+
<FSCol
|
|
24
|
+
width="hug"
|
|
25
|
+
v-if="$props.label || $props.description || $slots.description"
|
|
26
|
+
>
|
|
23
27
|
<FSSpan
|
|
24
28
|
v-if="$props.label"
|
|
25
29
|
class="fs-switch-label"
|
|
@@ -37,31 +41,33 @@
|
|
|
37
41
|
class="fs-switch-description"
|
|
38
42
|
font="text-overline"
|
|
39
43
|
:style="style"
|
|
40
|
-
:lineClamp="2"
|
|
41
44
|
>
|
|
42
45
|
{{ $props.description }}
|
|
43
46
|
</FSSpan>
|
|
44
47
|
</slot>
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
v-if="variant == 'right'"
|
|
48
|
-
align="center-right"
|
|
49
|
-
>
|
|
50
|
-
<v-switch
|
|
51
|
-
class="fs-switch"
|
|
52
|
-
hide-details
|
|
53
|
-
inset
|
|
54
|
-
:validateOn="validateOn"
|
|
55
|
-
:rules="$props.rules"
|
|
56
|
-
:ripple="false"
|
|
57
|
-
:style="style"
|
|
58
|
-
:modelValue="$props.modelValue"
|
|
59
|
-
@update:modelValue="onToggle"
|
|
60
|
-
v-bind="$attrs"
|
|
48
|
+
<slot
|
|
49
|
+
name="footer"
|
|
61
50
|
/>
|
|
62
|
-
</
|
|
51
|
+
</FSCol>
|
|
52
|
+
</slot>
|
|
53
|
+
<FSRow
|
|
54
|
+
v-if="variant == 'right'"
|
|
55
|
+
align="center-right"
|
|
56
|
+
>
|
|
57
|
+
<v-switch
|
|
58
|
+
class="fs-switch"
|
|
59
|
+
hide-details
|
|
60
|
+
inset
|
|
61
|
+
:validateOn="validateOn"
|
|
62
|
+
:rules="$props.rules"
|
|
63
|
+
:ripple="false"
|
|
64
|
+
:style="style"
|
|
65
|
+
:modelValue="$props.modelValue"
|
|
66
|
+
@update:modelValue="onToggle"
|
|
67
|
+
v-bind="$attrs"
|
|
68
|
+
/>
|
|
63
69
|
</FSRow>
|
|
64
|
-
</
|
|
70
|
+
</FSRow>
|
|
65
71
|
</template>
|
|
66
72
|
|
|
67
73
|
<script lang="ts">
|
package/components/map/FSMap.vue
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
v-if="map"
|
|
15
15
|
>
|
|
16
16
|
<FSMapTileLayer
|
|
17
|
-
:
|
|
17
|
+
:layer="actualLayer"
|
|
18
18
|
/>
|
|
19
19
|
<FSMapMarker
|
|
20
20
|
v-if="gpsPosition"
|
|
@@ -22,7 +22,38 @@
|
|
|
22
22
|
:color="ColorEnum.Primary"
|
|
23
23
|
:latlng="gpsPosition"
|
|
24
24
|
/>
|
|
25
|
-
|
|
25
|
+
|
|
26
|
+
<FSMapFeatureGroup
|
|
27
|
+
v-if="$props.areas"
|
|
28
|
+
:expected-layers="$props.areas.length"
|
|
29
|
+
@update:bounds="(bounds) => areaGroupBounds = bounds"
|
|
30
|
+
>
|
|
31
|
+
<FSMapPolygon
|
|
32
|
+
v-for="area in areas"
|
|
33
|
+
:key="area.id"
|
|
34
|
+
:color="area.color"
|
|
35
|
+
:latlngs="area.coordinates.map((coord) => ({lat: coord.latitude, lng: coord.longitude}))"
|
|
36
|
+
@click="$emit('update:selectedAreaId', area.id)"
|
|
37
|
+
/>
|
|
38
|
+
</FSMapFeatureGroup>
|
|
39
|
+
|
|
40
|
+
<FSMapMarkerClusterGroup
|
|
41
|
+
v-if="$props.locations"
|
|
42
|
+
:expected-layers="$props.locations.length"
|
|
43
|
+
:disableClusteringAtZoom="defaultZoom"
|
|
44
|
+
@update:bounds="(bounds) => locationGroupBounds = bounds"
|
|
45
|
+
>
|
|
46
|
+
<FSMapMarker
|
|
47
|
+
v-for="location in $props.locations"
|
|
48
|
+
:selected="location.id === $props.selectedLocationId"
|
|
49
|
+
:key="location.id"
|
|
50
|
+
:label="location.label"
|
|
51
|
+
:color="location.color ?? ColorEnum.Primary"
|
|
52
|
+
:icon="location.icon ?? 'mdi-map-marker'"
|
|
53
|
+
:latlng="{lat: location.address.latitude, lng: location.address.longitude}"
|
|
54
|
+
@click="$emit('update:selectedLocationId', location.id)"
|
|
55
|
+
/>
|
|
56
|
+
</FSMapMarkerClusterGroup>
|
|
26
57
|
</template>
|
|
27
58
|
</div>
|
|
28
59
|
|
|
@@ -69,7 +100,6 @@
|
|
|
69
100
|
</FSCol>
|
|
70
101
|
|
|
71
102
|
<FSMapOverlay
|
|
72
|
-
v-if="overlaySlots && Object.keys(overlaySlots).length"
|
|
73
103
|
:mode="$props.overlayMode"
|
|
74
104
|
@update:mode="$emit('update:overlayMode', $event)"
|
|
75
105
|
@update:height="(height) => overlayHeight = height"
|
|
@@ -95,9 +125,10 @@ import type {} from "leaflet.markercluster";
|
|
|
95
125
|
import { map as createMap, control, tileLayer, latLngBounds, latLng, type LatLng, type FitBoundsOptions, type ZoomPanOptions, type LatLngBounds } from "leaflet";
|
|
96
126
|
|
|
97
127
|
import { useTranslations as useTranslationsProvider } from "@dative-gpi/bones-ui/composables";
|
|
128
|
+
import { type FSArea } from '@dative-gpi/foundation-shared-domain/models';
|
|
98
129
|
|
|
99
130
|
import { useBreakpoints, useColors, useSlots } from "../../composables";
|
|
100
|
-
import { ColorEnum,
|
|
131
|
+
import { ColorEnum, type FSLocation, type MapLayer } from "../../models";
|
|
101
132
|
|
|
102
133
|
import FSMapLayerButton from "./FSMapLayerButton.vue";
|
|
103
134
|
import FSMapOverlay from "./FSMapOverlay.vue";
|
|
@@ -107,12 +138,19 @@ import FSCol from "../FSCol.vue";
|
|
|
107
138
|
|
|
108
139
|
import FSMapMarker from "./FSMapMarker.vue";
|
|
109
140
|
import FSMapTileLayer from "./FSMapTileLayer.vue";
|
|
141
|
+
import FSMapFeatureGroup from "./FSMapFeatureGroup.vue";
|
|
142
|
+
import FSMapMarkerClusterGroup from "./FSMapMarkerClusterGroup.vue";
|
|
143
|
+
import FSMapPolygon from "./FSMapPolygon.vue";
|
|
110
144
|
|
|
111
145
|
export default defineComponent({
|
|
112
146
|
name: "FSMap",
|
|
113
147
|
components: {
|
|
114
148
|
FSMapMarker,
|
|
115
149
|
FSMapTileLayer,
|
|
150
|
+
FSMapFeatureGroup,
|
|
151
|
+
FSMapMarkerClusterGroup,
|
|
152
|
+
FSMapPolygon,
|
|
153
|
+
|
|
116
154
|
FSMapLayerButton,
|
|
117
155
|
FSMapOverlay,
|
|
118
156
|
FSButton,
|
|
@@ -136,9 +174,9 @@ export default defineComponent({
|
|
|
136
174
|
default: false
|
|
137
175
|
},
|
|
138
176
|
overlayMode: {
|
|
139
|
-
type: String as PropType<
|
|
177
|
+
type: String as PropType<'collapse' | 'half' | 'expand'>,
|
|
140
178
|
required: false,
|
|
141
|
-
default:
|
|
179
|
+
default: 'collapse'
|
|
142
180
|
},
|
|
143
181
|
showMyLocation: {
|
|
144
182
|
type: Boolean,
|
|
@@ -156,29 +194,39 @@ export default defineComponent({
|
|
|
156
194
|
default: false
|
|
157
195
|
},
|
|
158
196
|
center: {
|
|
159
|
-
type: Array as PropType<number[]
|
|
197
|
+
type: Array as PropType<number[]>,
|
|
160
198
|
required: false,
|
|
161
|
-
default:
|
|
199
|
+
default: () => [45.71, 5.07]
|
|
162
200
|
},
|
|
163
|
-
|
|
164
|
-
type:
|
|
201
|
+
locations: {
|
|
202
|
+
type: Array as PropType<FSLocation[]>,
|
|
165
203
|
required: false,
|
|
166
|
-
default:
|
|
204
|
+
default: () => [],
|
|
205
|
+
},
|
|
206
|
+
areas: {
|
|
207
|
+
type: Array as PropType<FSArea[]>,
|
|
208
|
+
required: false,
|
|
209
|
+
default: () => [],
|
|
167
210
|
},
|
|
168
211
|
currentLayer: {
|
|
169
|
-
type: String as PropType<
|
|
212
|
+
type: String as PropType<"map" | "imagery">,
|
|
170
213
|
required: false,
|
|
171
|
-
default:
|
|
214
|
+
default: "map"
|
|
172
215
|
},
|
|
173
216
|
allowedLayers: {
|
|
174
|
-
type: Array as PropType<
|
|
217
|
+
type: Array as PropType<string[]>,
|
|
175
218
|
required: false,
|
|
176
|
-
default: () => [
|
|
219
|
+
default: () => ["map", "imagery"]
|
|
177
220
|
},
|
|
178
|
-
|
|
179
|
-
type:
|
|
221
|
+
selectedLocationId: {
|
|
222
|
+
type: String as PropType<string | null>,
|
|
180
223
|
required: false,
|
|
181
|
-
default:
|
|
224
|
+
default: null
|
|
225
|
+
},
|
|
226
|
+
selectedAreaId: {
|
|
227
|
+
type: String as PropType<string | null>,
|
|
228
|
+
required: false,
|
|
229
|
+
default: null
|
|
182
230
|
}
|
|
183
231
|
},
|
|
184
232
|
emits: ["update:modelValue", "update:selectedLocationId", "update:selectedAreaId", 'update:overlayMode', 'update:currentLayer', "click:latlng"],
|
|
@@ -198,7 +246,7 @@ export default defineComponent({
|
|
|
198
246
|
|
|
199
247
|
provide('map', map);
|
|
200
248
|
|
|
201
|
-
const defaultZoom =
|
|
249
|
+
const defaultZoom = 16;
|
|
202
250
|
const mapResizeObserver = new ResizeObserver(() => {
|
|
203
251
|
if(!map.value) {
|
|
204
252
|
return;
|
|
@@ -208,53 +256,29 @@ export default defineComponent({
|
|
|
208
256
|
|
|
209
257
|
const mapLayers: MapLayer[] = [
|
|
210
258
|
{
|
|
211
|
-
name:
|
|
259
|
+
name: "map",
|
|
212
260
|
label: $tr("ui.map-layer.map", "Map"),
|
|
213
261
|
image: new URL("../../assets/images/map/map.png", import.meta.url).href,
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
className: 'fs-map-tile-base-layer'
|
|
220
|
-
})
|
|
221
|
-
]
|
|
262
|
+
layer: tileLayer(`https://{s}.google.com/vt/lyrs=m&x={x}&y={y}&z={z}&key=${import.meta.env.VITE_GOOGLE_MAPS_API_KEY ?? ""}`, {
|
|
263
|
+
maxZoom: 22,
|
|
264
|
+
subdomains: ['mt0', 'mt1', 'mt2', 'mt3'],
|
|
265
|
+
attribution: '© Google Map Data'
|
|
266
|
+
})
|
|
222
267
|
},
|
|
223
268
|
{
|
|
224
|
-
name:
|
|
269
|
+
name: "imagery",
|
|
225
270
|
label: $tr("ui.map-layer.imagery", "Imagery"),
|
|
226
271
|
image: new URL("../../assets/images/map/imagery.png", import.meta.url).href,
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
className: 'fs-map-tile-base-layer'
|
|
233
|
-
})
|
|
234
|
-
]
|
|
235
|
-
},
|
|
236
|
-
{
|
|
237
|
-
name: MapLayers.Snow,
|
|
238
|
-
label: $tr("ui.map-layer.snow", "Snow ski map"),
|
|
239
|
-
image: new URL("../../assets/images/map/snow.png", import.meta.url).href,
|
|
240
|
-
layers: [
|
|
241
|
-
tileLayer(`https://{s}.google.com/vt/lyrs=m&x={x}&y={y}&z={z}&key=${import.meta.env.VITE_GOOGLE_MAPS_API_KEY ?? ""}`, {
|
|
242
|
-
maxZoom: 22,
|
|
243
|
-
subdomains: ['mt0', 'mt1', 'mt2', 'mt3'],
|
|
244
|
-
attribution: '© Google Map Data',
|
|
245
|
-
className: 'fs-map-tile-base-layer fs-map-tile-grayscale-layer'
|
|
246
|
-
}),
|
|
247
|
-
tileLayer(`https://tiles.opensnowmap.org/pistes/{z}/{x}/{y}.png`, {
|
|
248
|
-
maxZoom: 18,
|
|
249
|
-
attribution: 'Map data: © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors & ODbL, © <a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>',
|
|
250
|
-
className: 'fs-map-tile-base-layer'
|
|
251
|
-
})
|
|
252
|
-
]
|
|
272
|
+
layer: tileLayer(`https://{s}.google.com/vt/lyrs=s,h&x={x}&y={y}&z={z}&key=${import.meta.env.VITE_GOOGLE_MAPS_API_KEY ?? ""}`, {
|
|
273
|
+
maxZoom: 22,
|
|
274
|
+
subdomains: ['mt0', 'mt1', 'mt2', 'mt3'],
|
|
275
|
+
attribution: '© Google Map Data'
|
|
276
|
+
})
|
|
253
277
|
}
|
|
254
278
|
];
|
|
255
279
|
|
|
256
280
|
const bottomOffset = computed(() => {
|
|
257
|
-
if (props.overlayMode !==
|
|
281
|
+
if (props.overlayMode !== 'expand' && overlayHeight.value && isExtraSmall.value) {
|
|
258
282
|
return overlayHeight.value;
|
|
259
283
|
}
|
|
260
284
|
return 0;
|
|
@@ -276,7 +300,20 @@ export default defineComponent({
|
|
|
276
300
|
}));
|
|
277
301
|
|
|
278
302
|
const actualLayer = computed(() => {
|
|
279
|
-
return mapLayers.find((
|
|
303
|
+
return mapLayers.find((layer) => layer.name === props.currentLayer)?.layer ?? mapLayers[0].layer;
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
const bounds = computed<LatLngBounds | null>(() => {
|
|
307
|
+
if(!locationGroupBounds.value && !areaGroupBounds.value) {
|
|
308
|
+
return null;
|
|
309
|
+
}
|
|
310
|
+
let bounds = locationGroupBounds.value;
|
|
311
|
+
if(bounds && areaGroupBounds.value) {
|
|
312
|
+
bounds.extend(areaGroupBounds.value);
|
|
313
|
+
} else if(areaGroupBounds.value) {
|
|
314
|
+
bounds = areaGroupBounds.value;
|
|
315
|
+
}
|
|
316
|
+
return bounds as LatLngBounds;
|
|
280
317
|
});
|
|
281
318
|
|
|
282
319
|
const overlaySlots = computed(() => {
|
|
@@ -295,7 +332,7 @@ export default defineComponent({
|
|
|
295
332
|
return map.value.unproject(targetPoint, zoom);
|
|
296
333
|
}
|
|
297
334
|
|
|
298
|
-
const flyTo = (lat: number, lng: number, zoom: number = defaultZoom
|
|
335
|
+
const flyTo = (lat: number, lng: number, zoom: number = defaultZoom, options?: ZoomPanOptions) => {
|
|
299
336
|
if(!map.value) {
|
|
300
337
|
return;
|
|
301
338
|
}
|
|
@@ -323,7 +360,7 @@ export default defineComponent({
|
|
|
323
360
|
if(!map.value) {
|
|
324
361
|
return;
|
|
325
362
|
}
|
|
326
|
-
map.value.setView(calculateTargetPosition(latLng(lat, lng)
|
|
363
|
+
map.value.setView(calculateTargetPosition(latLng(lat, lng)), zoom);
|
|
327
364
|
}
|
|
328
365
|
|
|
329
366
|
const fitBounds = (bounds: LatLngBounds, options?: FitBoundsOptions) => {
|
|
@@ -357,12 +394,11 @@ export default defineComponent({
|
|
|
357
394
|
minZoom: 2,
|
|
358
395
|
maxZoom: 22,
|
|
359
396
|
maxBounds: latLngBounds(latLng(-90, -180), latLng(90, 180)),
|
|
360
|
-
maxBoundsViscosity: 1.0
|
|
361
|
-
zoom: defaultZoom.value,
|
|
362
|
-
center: props.center ? latLng(props.center[0], props.center[1]) : latLng(48.85782, 2.29521)
|
|
397
|
+
maxBoundsViscosity: 1.0
|
|
363
398
|
};
|
|
364
399
|
|
|
365
400
|
map.value = markRaw(createMap(leafletContainer.value, mapOptions));
|
|
401
|
+
setView(props.center[0], props.center[1], defaultZoom);
|
|
366
402
|
|
|
367
403
|
map.value.on('click', (e: L.LeafletMouseEvent) => {
|
|
368
404
|
emit('click:latlng', e.latlng);
|
|
@@ -392,27 +428,43 @@ export default defineComponent({
|
|
|
392
428
|
mapResizeObserver.disconnect();
|
|
393
429
|
});
|
|
394
430
|
|
|
395
|
-
watch (
|
|
396
|
-
if(!map.value
|
|
431
|
+
watch (() => props.center, (center) => {
|
|
432
|
+
if(!map.value) {
|
|
397
433
|
return;
|
|
398
434
|
}
|
|
399
|
-
setView(
|
|
400
|
-
}
|
|
435
|
+
setView(center[0], center[1], defaultZoom);
|
|
436
|
+
});
|
|
401
437
|
|
|
402
|
-
watch(
|
|
403
|
-
if(!map.value
|
|
438
|
+
watch (() => props.selectedLocationId, (selectedLocationId) => {
|
|
439
|
+
if(!map.value) {
|
|
404
440
|
return;
|
|
405
441
|
}
|
|
406
|
-
|
|
407
|
-
|
|
442
|
+
const selectedLocation = props.locations.find((location) => location.id === selectedLocationId);
|
|
443
|
+
if(!selectedLocation) {
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
flyTo(selectedLocation?.address.latitude, selectedLocation?.address.longitude, defaultZoom, { animate: false });
|
|
447
|
+
}, { immediate: true });
|
|
408
448
|
|
|
409
|
-
watch(() => props.
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
449
|
+
watch(() => props.selectedAreaId, (selectedAreaId) => {
|
|
450
|
+
if(!map.value) {
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
const selectedArea = props.areas.find((area) => area.id === selectedAreaId);
|
|
454
|
+
if(!selectedArea) {
|
|
455
|
+
return;
|
|
413
456
|
}
|
|
457
|
+
const bounds = latLngBounds(selectedArea.coordinates.map((coord) => latLng(coord.latitude, coord.longitude)));
|
|
458
|
+
fitBounds(bounds);
|
|
414
459
|
}, { immediate: true });
|
|
415
460
|
|
|
461
|
+
watch( () => bounds.value, (bounds) => {
|
|
462
|
+
if(!map.value || !bounds) {
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
fitBounds(bounds, { maxZoom: defaultZoom });
|
|
466
|
+
});
|
|
467
|
+
|
|
416
468
|
return {
|
|
417
469
|
ColorEnum,
|
|
418
470
|
defaultZoom,
|
|
@@ -82,20 +82,20 @@ export default {
|
|
|
82
82
|
iconSize: [size, size],
|
|
83
83
|
iconAnchor: [size / 2, size / 2],
|
|
84
84
|
});
|
|
85
|
-
} else if(props.variant === 'location') {
|
|
85
|
+
} else if(props.variant === 'location' && props.icon) {
|
|
86
86
|
const size = 36;
|
|
87
87
|
icon = divIcon({
|
|
88
|
-
html: locationMarkerHtml(props.icon
|
|
88
|
+
html: locationMarkerHtml(props.icon, getColors(props.color).base, props.label),
|
|
89
89
|
iconSize: [size, size],
|
|
90
|
-
className: props.selected ? 'fs-map-
|
|
90
|
+
className: props.selected ? 'fs-map-location fs-map-location-selected' : 'fs-map-location',
|
|
91
91
|
iconAnchor: [size / 2, size / 2],
|
|
92
92
|
});
|
|
93
93
|
} else {
|
|
94
|
-
const size =
|
|
94
|
+
const size = 20;
|
|
95
95
|
icon = divIcon({
|
|
96
|
-
html: pinMarkerHtml(getColors(props.color).base
|
|
96
|
+
html: pinMarkerHtml(getColors(props.color).base),
|
|
97
97
|
iconSize: [size, size],
|
|
98
|
-
className: props.selected ? 'fs-map-
|
|
98
|
+
className: props.selected ? 'fs-map-location fs-map-location-selected' : 'fs-map-location',
|
|
99
99
|
iconAnchor: [size / 2, size / 2],
|
|
100
100
|
});
|
|
101
101
|
}
|
|
@@ -45,7 +45,7 @@ export default {
|
|
|
45
45
|
|
|
46
46
|
return divIcon({
|
|
47
47
|
html: clusterMarkerHtml(cluster.getChildCount()),
|
|
48
|
-
className: 'fs-map-
|
|
48
|
+
className: 'fs-map-location fs-map-location-full',
|
|
49
49
|
iconSize: [size, size],
|
|
50
50
|
iconAnchor: [size / 2, size / 2],
|
|
51
51
|
});
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<v-overlay
|
|
3
3
|
v-if="isExtraSmall"
|
|
4
|
-
:modelValue="$props.mode ===
|
|
4
|
+
:modelValue="$props.mode === 'expand'"
|
|
5
5
|
:contained="true"
|
|
6
|
-
@click="$emit('update:mode',
|
|
6
|
+
@click="$emit('update:mode', 'collapse')"
|
|
7
7
|
zIndex="0"
|
|
8
8
|
/>
|
|
9
9
|
<div
|
|
10
10
|
v-show="isExtraSmall"
|
|
11
11
|
ref="mobileOverlayWrapper"
|
|
12
12
|
class="fs-map-overlay-mobile"
|
|
13
|
-
:style="{ height: $props.mode ===
|
|
13
|
+
:style="{ height: $props.mode === 'expand' ? '90%' : ($props.mode === 'half' ? '60%' : 'auto') }"
|
|
14
14
|
>
|
|
15
15
|
<FSCard
|
|
16
16
|
width="100%"
|
|
@@ -29,15 +29,15 @@
|
|
|
29
29
|
@mousedown="onClick"
|
|
30
30
|
>
|
|
31
31
|
<FSIcon>
|
|
32
|
-
{{ $props.mode ===
|
|
32
|
+
{{ $props.mode === 'expand' ? 'mdi-chevron-down' : 'mdi-chevron-up' }}
|
|
33
33
|
</FSIcon>
|
|
34
34
|
</FSRow>
|
|
35
35
|
<slot
|
|
36
|
-
v-if="$props.mode ===
|
|
36
|
+
v-if="$props.mode === 'collapse'"
|
|
37
37
|
name="collapsed"
|
|
38
38
|
/>
|
|
39
39
|
<FSCol
|
|
40
|
-
v-if="$props.mode !==
|
|
40
|
+
v-if="$props.mode !== 'collapse'"
|
|
41
41
|
height="fill"
|
|
42
42
|
style="min-height: 0;"
|
|
43
43
|
>
|
|
@@ -70,8 +70,6 @@ import { defineComponent, type PropType, onUnmounted, onMounted, ref } from "vue
|
|
|
70
70
|
|
|
71
71
|
import { useBreakpoints } from "../../composables";
|
|
72
72
|
|
|
73
|
-
import { MapOverlayPositions } from '@dative-gpi/foundation-shared-components/models';
|
|
74
|
-
|
|
75
73
|
import FSCard from "../FSCard.vue";
|
|
76
74
|
import FSIcon from "../FSIcon.vue";
|
|
77
75
|
import FSCol from "../FSCol.vue";
|
|
@@ -87,9 +85,9 @@ export default defineComponent({
|
|
|
87
85
|
},
|
|
88
86
|
props: {
|
|
89
87
|
mode: {
|
|
90
|
-
type: String as PropType<
|
|
88
|
+
type: String as PropType<"collapse" | "half" | "expand">,
|
|
91
89
|
required: false,
|
|
92
|
-
default:
|
|
90
|
+
default: "collapse"
|
|
93
91
|
}
|
|
94
92
|
},
|
|
95
93
|
emits: ["update:mode", "update:height", "update:width"],
|
|
@@ -103,11 +101,11 @@ export default defineComponent({
|
|
|
103
101
|
const desktopResizeObserver = ref<ResizeObserver | null>(null);
|
|
104
102
|
|
|
105
103
|
const onClick = (): void => {
|
|
106
|
-
if (props.mode ===
|
|
107
|
-
emit("update:mode",
|
|
104
|
+
if (props.mode === "expand") {
|
|
105
|
+
emit("update:mode", "collapse");
|
|
108
106
|
return;
|
|
109
107
|
}
|
|
110
|
-
emit("update:mode",
|
|
108
|
+
emit("update:mode", "expand");
|
|
111
109
|
}
|
|
112
110
|
|
|
113
111
|
onMounted(() => {
|
|
@@ -146,7 +144,6 @@ export default defineComponent({
|
|
|
146
144
|
return {
|
|
147
145
|
mobileOverlayWrapper,
|
|
148
146
|
isTouchScreenEnabled,
|
|
149
|
-
MapOverlayPositions,
|
|
150
147
|
desktopOverlay,
|
|
151
148
|
isExtraSmall,
|
|
152
149
|
onClick
|
|
@@ -12,15 +12,15 @@ import { MAP } from './keys';
|
|
|
12
12
|
export default {
|
|
13
13
|
name: 'FSMapTileLayer',
|
|
14
14
|
props: {
|
|
15
|
-
|
|
16
|
-
type: Object as PropType<Layer
|
|
15
|
+
layer: {
|
|
16
|
+
type: Object as PropType<Layer>,
|
|
17
17
|
required: false
|
|
18
18
|
}
|
|
19
19
|
},
|
|
20
20
|
setup(props) {
|
|
21
21
|
const map = inject<Ref<Map | null>>(MAP);
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
const lastLayer = props.layer;
|
|
24
24
|
|
|
25
25
|
if(!map) {
|
|
26
26
|
throw new Error('FSMapTileLayer must be used inside a FSMap component');
|
|
@@ -31,26 +31,20 @@ export default {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
const updateLayer = () => {
|
|
34
|
-
if (!props.
|
|
34
|
+
if (!props.layer || !map.value) {
|
|
35
35
|
return;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
if(
|
|
39
|
-
|
|
40
|
-
layer.removeFrom(map.value!);
|
|
41
|
-
});
|
|
38
|
+
if(lastLayer) {
|
|
39
|
+
map.value.removeLayer(lastLayer);
|
|
42
40
|
}
|
|
43
41
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
props.layers.forEach(layer => {
|
|
47
|
-
lastLayers?.push(layer.addTo(map.value!));
|
|
48
|
-
});
|
|
42
|
+
props.layer.addTo(map.value);
|
|
49
43
|
};
|
|
50
44
|
|
|
51
45
|
onMounted(updateLayer);
|
|
52
46
|
|
|
53
|
-
watch(() => props.
|
|
47
|
+
watch(() => props.layer, updateLayer);
|
|
54
48
|
}
|
|
55
49
|
};
|
|
56
50
|
</script>
|
|
@@ -97,13 +97,6 @@
|
|
|
97
97
|
:imageId="$props.imageId"
|
|
98
98
|
:width="imageSize"
|
|
99
99
|
/>
|
|
100
|
-
<FSIconCard
|
|
101
|
-
v-else-if="$props.icon"
|
|
102
|
-
backgroundVariant="standard"
|
|
103
|
-
:backgroundColor="ColorEnum.Background"
|
|
104
|
-
:icon="$props.icon"
|
|
105
|
-
:size="imageSize"
|
|
106
|
-
/>
|
|
107
100
|
</FSRow>
|
|
108
101
|
</FSCol>
|
|
109
102
|
</FSTile>
|
|
@@ -115,7 +108,6 @@ import { computed, defineComponent, type PropType } from "vue";
|
|
|
115
108
|
import { useBreakpoints } from "@dative-gpi/foundation-shared-components/composables";
|
|
116
109
|
import { ColorEnum } from "@dative-gpi/foundation-shared-components/models";
|
|
117
110
|
|
|
118
|
-
import FSIconCard from "../FSIconCard.vue";
|
|
119
111
|
import FSImage from "../FSImage.vue";
|
|
120
112
|
import FSColor from "../FSColor.vue";
|
|
121
113
|
import FSSpan from "../FSSpan.vue";
|
|
@@ -126,7 +118,6 @@ import FSRow from "../FSRow.vue";
|
|
|
126
118
|
export default defineComponent({
|
|
127
119
|
name: "FSGroupTileUI",
|
|
128
120
|
components: {
|
|
129
|
-
FSIconCard,
|
|
130
121
|
FSImage,
|
|
131
122
|
FSColor,
|
|
132
123
|
FSSpan,
|
|
@@ -140,10 +131,6 @@ export default defineComponent({
|
|
|
140
131
|
required: false,
|
|
141
132
|
default: null
|
|
142
133
|
},
|
|
143
|
-
icon: {
|
|
144
|
-
type: String,
|
|
145
|
-
required: false
|
|
146
|
-
},
|
|
147
134
|
label: {
|
|
148
135
|
type: String as PropType<string | null>,
|
|
149
136
|
required: false,
|
|
@@ -196,7 +183,7 @@ export default defineComponent({
|
|
|
196
183
|
});
|
|
197
184
|
|
|
198
185
|
const infoWidth = computed((): string => {
|
|
199
|
-
if (!props.imageId
|
|
186
|
+
if (!props.imageId) {
|
|
200
187
|
return "100%";
|
|
201
188
|
}
|
|
202
189
|
return `calc(100% - ${imageSize.value}px - 24px)`;
|
package/models/map.ts
CHANGED
|
@@ -1,20 +1,18 @@
|
|
|
1
1
|
import { type Layer } from "leaflet";
|
|
2
2
|
|
|
3
|
+
import { type Address } from "@dative-gpi/foundation-shared-domain/models";
|
|
4
|
+
|
|
3
5
|
export interface MapLayer {
|
|
4
|
-
name :
|
|
6
|
+
name : string;
|
|
5
7
|
label: string;
|
|
6
8
|
image: string;
|
|
7
|
-
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export enum MapLayers {
|
|
11
|
-
Map = "map",
|
|
12
|
-
Imagery = "imagery",
|
|
13
|
-
Snow= "snow"
|
|
9
|
+
layer: Layer;
|
|
14
10
|
}
|
|
15
11
|
|
|
16
|
-
export
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
12
|
+
export interface FSLocation {
|
|
13
|
+
id: string;
|
|
14
|
+
label: string;
|
|
15
|
+
icon: string | null;
|
|
16
|
+
address: Address;
|
|
17
|
+
color: string | null;
|
|
20
18
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dative-gpi/foundation-shared-components",
|
|
3
3
|
"sideEffects": false,
|
|
4
|
-
"version": "1.0.137-
|
|
4
|
+
"version": "1.0.137-reportV2",
|
|
5
5
|
"description": "",
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"access": "public"
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
"author": "",
|
|
11
11
|
"license": "ISC",
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@dative-gpi/foundation-shared-domain": "1.0.137-
|
|
14
|
-
"@dative-gpi/foundation-shared-services": "1.0.137-
|
|
13
|
+
"@dative-gpi/foundation-shared-domain": "1.0.137-reportV2",
|
|
14
|
+
"@dative-gpi/foundation-shared-services": "1.0.137-reportV2"
|
|
15
15
|
},
|
|
16
16
|
"peerDependencies": {
|
|
17
17
|
"@dative-gpi/bones-ui": "^1.0.0",
|
|
@@ -35,5 +35,5 @@
|
|
|
35
35
|
"sass": "1.71.1",
|
|
36
36
|
"sass-loader": "13.3.2"
|
|
37
37
|
},
|
|
38
|
-
"gitHead": "
|
|
38
|
+
"gitHead": "57f88a90528a7849e930dbc8eea7223a84c58c9f"
|
|
39
39
|
}
|
|
@@ -6,15 +6,7 @@
|
|
|
6
6
|
.fs-leaflet-container {
|
|
7
7
|
width: 100%;
|
|
8
8
|
height: 100%;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
.fs-map-tile-base-layer {
|
|
12
|
-
filter: grayscale(var(--fs-map-container-grayscale));
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
.fs-map-tile-grayscale-layer {
|
|
16
|
-
filter: grayscale(100%);
|
|
17
|
-
}
|
|
9
|
+
filter: grayscale(var(--fs-map-container-grayscale));
|
|
18
10
|
}
|
|
19
11
|
|
|
20
12
|
.fs-map-overlay-mobile {
|
|
@@ -85,10 +77,17 @@
|
|
|
85
77
|
}
|
|
86
78
|
}
|
|
87
79
|
|
|
88
|
-
.fs-map-
|
|
80
|
+
.fs-map-point-pin {
|
|
81
|
+
background-color: var(--fs-map-point-pin-color);
|
|
82
|
+
border-radius: 100%;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.fs-map-location > div {
|
|
89
86
|
display: flex;
|
|
90
87
|
height: 100%;
|
|
88
|
+
color: var(--fs-map-location-pin-color);
|
|
91
89
|
border-radius: 50%;
|
|
90
|
+
background-color: white;
|
|
92
91
|
filter: drop-shadow(0px 2px 4px rgba(0, 0, 0, 0.4));
|
|
93
92
|
align-items: center;
|
|
94
93
|
justify-content: center;
|
|
@@ -104,7 +103,7 @@
|
|
|
104
103
|
}
|
|
105
104
|
}
|
|
106
105
|
|
|
107
|
-
.fs-map-
|
|
106
|
+
.fs-map-location-full > div {
|
|
108
107
|
background-color: var(--fs-map-location-pin-color);
|
|
109
108
|
color: white;
|
|
110
109
|
}
|
|
@@ -127,41 +126,6 @@
|
|
|
127
126
|
}
|
|
128
127
|
}
|
|
129
128
|
|
|
130
|
-
.fs-map-location > div {
|
|
131
|
-
color: var(--fs-map-location-pin-color);
|
|
132
|
-
background-color: white;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
.fs-map-pin > div {
|
|
136
|
-
background-color: var(--fs-map-point-pin-color);
|
|
137
|
-
position: relative;
|
|
138
|
-
|
|
139
|
-
transition: transform 0.28s cubic-bezier(0.4, 0, 0.2, 1);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
.fs-map-pin > div::before {
|
|
143
|
-
content: "";
|
|
144
|
-
position: absolute;
|
|
145
|
-
top: -4px;
|
|
146
|
-
left: -4px;
|
|
147
|
-
width: calc(100% + 8px);
|
|
148
|
-
height: calc(100% + 8px);
|
|
149
|
-
border-radius: 50%;
|
|
150
|
-
border: 2px solid var(--fs-map-point-pin-color);
|
|
151
|
-
opacity: 0.4;
|
|
152
|
-
|
|
153
|
-
@include clickscreen {
|
|
154
|
-
&:hover {
|
|
155
|
-
opacity: 1;
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
.fs-map-pin-selected > div {
|
|
161
|
-
transform: scale(1.35);
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
|
|
165
129
|
.fs-map-site {
|
|
166
130
|
opacity: 0.6;
|
|
167
131
|
transition: opacity 0.28s cubic-bezier(0.4, 0, 0.2, 1);
|
package/tools/index.ts
CHANGED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { useTranslations as useTranslationsProvider } from "@dative-gpi/bones-ui/composables";
|
|
2
|
+
import { ColorEnum } from "../models";
|
|
3
|
+
import { JobState } from "@dative-gpi/foundation-shared-domain/enums";
|
|
4
|
+
|
|
5
|
+
const { $tr } = useTranslationsProvider();
|
|
6
|
+
|
|
7
|
+
export const getColorByState = (state: number | JobState | undefined) => {
|
|
8
|
+
switch (state) {
|
|
9
|
+
case JobState.Succeeded:
|
|
10
|
+
return ColorEnum.Success;
|
|
11
|
+
case JobState.Failed:
|
|
12
|
+
return ColorEnum.Error;
|
|
13
|
+
default:
|
|
14
|
+
return ColorEnum.Primary;
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const getIconByState = (state: number | JobState | undefined) => {
|
|
19
|
+
switch (state) {
|
|
20
|
+
case JobState.Succeeded:
|
|
21
|
+
return 'mdi-check-circle-outline';
|
|
22
|
+
case JobState.Failed:
|
|
23
|
+
return 'mdi-alert-circle-outline';
|
|
24
|
+
default:
|
|
25
|
+
return 'mdi-alert-circle-outline';
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export const getLabelByState = (state: number | JobState | undefined) => {
|
|
30
|
+
switch (state) {
|
|
31
|
+
case JobState.Succeeded:
|
|
32
|
+
return $tr('ui.common.success', 'Success');
|
|
33
|
+
case JobState.Failed:
|
|
34
|
+
return $tr('ui.common.error', 'Error');
|
|
35
|
+
default:
|
|
36
|
+
return $tr('ui.common.executed', 'Executed');
|
|
37
|
+
}
|
|
38
|
+
};
|
|
Binary file
|
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<component
|
|
3
|
-
v-if="$props.modelStatus"
|
|
4
|
-
class="fs-status-rich-card"
|
|
5
|
-
variant="standard"
|
|
6
|
-
:is="$attrs.onClick ? FSClickable : FSCard"
|
|
7
|
-
:padding="$props.padding"
|
|
8
|
-
:height="$props.height"
|
|
9
|
-
:width="$props.width"
|
|
10
|
-
:color="color"
|
|
11
|
-
:style="style"
|
|
12
|
-
>
|
|
13
|
-
<FSCol
|
|
14
|
-
align="center-center"
|
|
15
|
-
:gap="$props.gap"
|
|
16
|
-
>
|
|
17
|
-
<FSRow
|
|
18
|
-
align="top-center"
|
|
19
|
-
>
|
|
20
|
-
<FSIcon
|
|
21
|
-
v-if="icon"
|
|
22
|
-
>
|
|
23
|
-
{{ icon }}
|
|
24
|
-
</FSIcon>
|
|
25
|
-
<FSText
|
|
26
|
-
v-if="value"
|
|
27
|
-
font="text-button"
|
|
28
|
-
>
|
|
29
|
-
{{ value }}
|
|
30
|
-
</FSText>
|
|
31
|
-
</FSRow>
|
|
32
|
-
<FSText
|
|
33
|
-
font="text-overline"
|
|
34
|
-
align="center"
|
|
35
|
-
:lineClamp="$props.titleClamp"
|
|
36
|
-
>
|
|
37
|
-
{{ title }}
|
|
38
|
-
</FSText>
|
|
39
|
-
<slot
|
|
40
|
-
name="footer"
|
|
41
|
-
v-bind="{ color }"
|
|
42
|
-
/>
|
|
43
|
-
</FSCol>
|
|
44
|
-
<div
|
|
45
|
-
class="fs-status-rich-card-corner"
|
|
46
|
-
>
|
|
47
|
-
<slot
|
|
48
|
-
name="corner"
|
|
49
|
-
v-bind="{ color }"
|
|
50
|
-
/>
|
|
51
|
-
</div>
|
|
52
|
-
</component>
|
|
53
|
-
</template>
|
|
54
|
-
|
|
55
|
-
<script lang="ts">
|
|
56
|
-
import { computed, defineComponent, type PropType, type StyleValue } from "vue";
|
|
57
|
-
|
|
58
|
-
import { ColorEnum, type FSDeviceStatusGroup, type FSModelStatus } from "@dative-gpi/foundation-shared-components/models";
|
|
59
|
-
import { useColors } from "@dative-gpi/foundation-shared-components/composables";
|
|
60
|
-
|
|
61
|
-
import FSClickable from "../FSClickable.vue";
|
|
62
|
-
import FSCard from "../FSCard.vue";
|
|
63
|
-
import FSIcon from "../FSChip.vue";
|
|
64
|
-
import FSText from "../FSText.vue";
|
|
65
|
-
import FSCol from "../FSCol.vue";
|
|
66
|
-
|
|
67
|
-
export default defineComponent({
|
|
68
|
-
name: "FSStatusRichCard",
|
|
69
|
-
components: {
|
|
70
|
-
FSClickable,
|
|
71
|
-
FSCard,
|
|
72
|
-
FSIcon,
|
|
73
|
-
FSText,
|
|
74
|
-
FSCol
|
|
75
|
-
},
|
|
76
|
-
props: {
|
|
77
|
-
height: {
|
|
78
|
-
type: [Array, String, Number] as PropType<string[] | number[] | string | number | null>,
|
|
79
|
-
required: false,
|
|
80
|
-
default: "100px"
|
|
81
|
-
},
|
|
82
|
-
width: {
|
|
83
|
-
type: [Array, String, Number] as PropType<string[] | number[] | string | number | null>,
|
|
84
|
-
required: false,
|
|
85
|
-
default: "160px"
|
|
86
|
-
},
|
|
87
|
-
padding: {
|
|
88
|
-
type: [Array, String, Number] as PropType<string[] | number[] | string | number | null>,
|
|
89
|
-
required: false,
|
|
90
|
-
default: "12px"
|
|
91
|
-
},
|
|
92
|
-
gap: {
|
|
93
|
-
type: [Array, String, Number] as PropType<string[] | number[] | string | number | null>,
|
|
94
|
-
required: false,
|
|
95
|
-
default: "8px"
|
|
96
|
-
},
|
|
97
|
-
title: {
|
|
98
|
-
type: [String, null] as PropType<string | null>,
|
|
99
|
-
required: false,
|
|
100
|
-
default: null
|
|
101
|
-
},
|
|
102
|
-
titleClamp: {
|
|
103
|
-
type: Number,
|
|
104
|
-
required: false,
|
|
105
|
-
default: 2
|
|
106
|
-
},
|
|
107
|
-
color: {
|
|
108
|
-
type: [String, null] as PropType<string | null>,
|
|
109
|
-
required: false,
|
|
110
|
-
default: null
|
|
111
|
-
},
|
|
112
|
-
fillBackground: {
|
|
113
|
-
type: Boolean,
|
|
114
|
-
required: false,
|
|
115
|
-
default: false
|
|
116
|
-
},
|
|
117
|
-
modelStatus: {
|
|
118
|
-
type: Object as PropType<FSModelStatus | undefined>,
|
|
119
|
-
required: true
|
|
120
|
-
},
|
|
121
|
-
statusGroup: {
|
|
122
|
-
type: Object as PropType<FSDeviceStatusGroup | undefined>,
|
|
123
|
-
required: true
|
|
124
|
-
}
|
|
125
|
-
},
|
|
126
|
-
setup(props) {
|
|
127
|
-
const { getColors } = useColors();
|
|
128
|
-
|
|
129
|
-
const color = computed((): string => {
|
|
130
|
-
return props.color ?? props.statusGroup?.color ?? props.modelStatus?.colorDefault ?? ColorEnum.Primary;
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
const icon = computed((): string | null => {
|
|
134
|
-
return props.statusGroup?.icon ?? props.modelStatus?.iconDefault ?? null;
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
const title = computed((): string => {
|
|
138
|
-
return props.title ?? props.modelStatus?.label;
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
const value = computed((): string | null => {
|
|
142
|
-
if (props.statusGroup?.label) {
|
|
143
|
-
return props.statusGroup.label;
|
|
144
|
-
}
|
|
145
|
-
if (props.statusGroup?.value && !isNaN(parseFloat(props.statusGroup?.value))) {
|
|
146
|
-
return `${parseFloat(props.statusGroup.value).toLocaleString("fullwide", { maximumFractionDigits: 2 })} ${props.statusGroup.unit}`;
|
|
147
|
-
}
|
|
148
|
-
if (props.statusGroup?.value) {
|
|
149
|
-
return `${props.statusGroup?.value} ${props.statusGroup?.unit}`;
|
|
150
|
-
}
|
|
151
|
-
return null;
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
const style = computed((): StyleValue => ({
|
|
155
|
-
"--fs-status-rich-card-background-color": props.fillBackground ? getColors(color.value).light : "transparent",
|
|
156
|
-
"--fs-status-rich-card-border-color": props.fillBackground ? getColors(color.value).base : getColors(ColorEnum.Light).dark
|
|
157
|
-
}));
|
|
158
|
-
|
|
159
|
-
return {
|
|
160
|
-
FSClickable,
|
|
161
|
-
FSCard,
|
|
162
|
-
color,
|
|
163
|
-
style,
|
|
164
|
-
title,
|
|
165
|
-
value,
|
|
166
|
-
icon
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
});
|
|
170
|
-
</script>
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<FSSelectField
|
|
3
|
-
:items="items"
|
|
4
|
-
:modelValue="$props.modelValue"
|
|
5
|
-
@update:modelValue="$emit('update:modelValue', $event)"
|
|
6
|
-
v-bind="$attrs"
|
|
7
|
-
>
|
|
8
|
-
<template
|
|
9
|
-
#item-prepend="{ item }"
|
|
10
|
-
>
|
|
11
|
-
<FSIcon
|
|
12
|
-
:icon="item.icon"
|
|
13
|
-
/>
|
|
14
|
-
</template>
|
|
15
|
-
</FSSelectField>
|
|
16
|
-
</template>
|
|
17
|
-
|
|
18
|
-
<script lang="ts">
|
|
19
|
-
import type { PropType} from "vue";
|
|
20
|
-
import { defineComponent } from "vue";
|
|
21
|
-
|
|
22
|
-
import { useTranslations as useTranslationsProvider } from "@dative-gpi/bones-ui/composables";
|
|
23
|
-
|
|
24
|
-
import { MapLayers } from '@dative-gpi/foundation-shared-components/models';
|
|
25
|
-
|
|
26
|
-
import FSSelectField from "../fields/FSSelectField.vue";
|
|
27
|
-
import FSIcon from '@dative-gpi/foundation-shared-components/components/FSIcon.vue';
|
|
28
|
-
|
|
29
|
-
export default defineComponent({
|
|
30
|
-
name: "FSSelectMapLayer",
|
|
31
|
-
components: {
|
|
32
|
-
FSIcon,
|
|
33
|
-
FSSelectField
|
|
34
|
-
},
|
|
35
|
-
props: {
|
|
36
|
-
modelValue: {
|
|
37
|
-
type: [String, Array] as PropType<MapLayers | MapLayers[]>,
|
|
38
|
-
required: false
|
|
39
|
-
}
|
|
40
|
-
},
|
|
41
|
-
emits: ["update:modelValue"],
|
|
42
|
-
setup() {
|
|
43
|
-
const { $tr } = useTranslationsProvider();
|
|
44
|
-
|
|
45
|
-
const items = [
|
|
46
|
-
{
|
|
47
|
-
id: MapLayers.Map,
|
|
48
|
-
icon: 'mdi-map',
|
|
49
|
-
label: $tr("ui.map-layer.map", "Map")
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
id: MapLayers.Imagery,
|
|
53
|
-
icon: 'mdi-satellite',
|
|
54
|
-
label: $tr("ui.map-layer.imagery", "Imagery")
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
id: MapLayers.Snow,
|
|
58
|
-
icon: 'mdi-snowflake',
|
|
59
|
-
label: $tr("ui.map-layer.snow", "Snow ski map")
|
|
60
|
-
}
|
|
61
|
-
]
|
|
62
|
-
|
|
63
|
-
return {
|
|
64
|
-
items
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
});
|
|
68
|
-
</script>
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
.fs-status-rich-card {
|
|
2
|
-
position: relative;
|
|
3
|
-
flex-grow: 1;
|
|
4
|
-
background-color: var(--fs-status-rich-card-background-color);
|
|
5
|
-
border-color: var(--fs-status-rich-card-border-color);
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
.fs-status-rich-card-corner {
|
|
9
|
-
position: absolute;
|
|
10
|
-
display: flex;
|
|
11
|
-
right: 2px;
|
|
12
|
-
top: 2px;
|
|
13
|
-
}
|