@dative-gpi/foundation-shared-components 1.0.158 → 1.0.159-sankey
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/FSInstantPicker.vue +9 -4
- package/components/FSOptionsMenu.vue +165 -0
- package/components/FSRangePicker.vue +318 -0
- package/components/FSRangeSlider.vue +116 -0
- package/components/map/FSMap.vue +0 -2
- package/components/map/FSMapMarker.vue +52 -13
- package/composables/useMapLayers.ts +3 -3
- package/package.json +4 -4
- package/tools/alertsTools.ts +2 -1
|
@@ -97,9 +97,9 @@ import FSCol from '@dative-gpi/foundation-shared-components/components/FSCol.vue
|
|
|
97
97
|
import FSSpan from '@dative-gpi/foundation-shared-components/components/FSSpan.vue';
|
|
98
98
|
import FSText from '@dative-gpi/foundation-shared-components/components/FSText.vue';
|
|
99
99
|
import FSSlider from '@dative-gpi/foundation-shared-components/components/FSSlider.vue';
|
|
100
|
+
import FSPlayButtons from '@dative-gpi/foundation-shared-components/components/FSPlayButtons.vue';
|
|
100
101
|
import FSBaseField from '@dative-gpi/foundation-shared-components/components/fields/FSBaseField.vue';
|
|
101
102
|
import FSTermField from '@dative-gpi/foundation-shared-components/components/fields/FSTermField.vue';
|
|
102
|
-
import FSPlayButtons from '@dative-gpi/foundation-shared-components/components/FSPlayButtons.vue';
|
|
103
103
|
|
|
104
104
|
export default defineComponent({
|
|
105
105
|
name: "FSInstantPicker",
|
|
@@ -110,7 +110,7 @@ export default defineComponent({
|
|
|
110
110
|
FSSlider,
|
|
111
111
|
FSTermField,
|
|
112
112
|
FSBaseField,
|
|
113
|
-
FSPlayButtons
|
|
113
|
+
FSPlayButtons,
|
|
114
114
|
},
|
|
115
115
|
props: {
|
|
116
116
|
label: {
|
|
@@ -119,8 +119,7 @@ export default defineComponent({
|
|
|
119
119
|
},
|
|
120
120
|
modelValue: {
|
|
121
121
|
type: Number,
|
|
122
|
-
required: false
|
|
123
|
-
default: 0,
|
|
122
|
+
required: false
|
|
124
123
|
},
|
|
125
124
|
startDate: {
|
|
126
125
|
type: String,
|
|
@@ -231,6 +230,12 @@ export default defineComponent({
|
|
|
231
230
|
}
|
|
232
231
|
}, { immediate: true });
|
|
233
232
|
|
|
233
|
+
watch(() => props.modelValue, (value) => {
|
|
234
|
+
if(!value) {
|
|
235
|
+
emit('update:modelValue', endTimestamp.value);
|
|
236
|
+
}
|
|
237
|
+
}, { immediate: true });
|
|
238
|
+
|
|
234
239
|
watch(playing, (value) => {
|
|
235
240
|
if(!value && playingInterval.value) {
|
|
236
241
|
clearInterval(playingInterval.value);
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<FSMenu
|
|
3
|
+
:location="$props.location"
|
|
4
|
+
:closeOnContentClick="true"
|
|
5
|
+
:contained="false"
|
|
6
|
+
minWidth="0"
|
|
7
|
+
v-model="modelValue"
|
|
8
|
+
v-bind="$attrs"
|
|
9
|
+
>
|
|
10
|
+
<template
|
|
11
|
+
#activator="{ props }"
|
|
12
|
+
>
|
|
13
|
+
<slot
|
|
14
|
+
name="activator"
|
|
15
|
+
v-bind="props"
|
|
16
|
+
>
|
|
17
|
+
<FSButton
|
|
18
|
+
v-bind="props"
|
|
19
|
+
:icon="$props.icon"
|
|
20
|
+
:iconSize="$props.iconSize"
|
|
21
|
+
:color="$props.buttonColor"
|
|
22
|
+
:variant="$props.buttonVariant"
|
|
23
|
+
/>
|
|
24
|
+
</slot>
|
|
25
|
+
</template>
|
|
26
|
+
<FSCard
|
|
27
|
+
:maxWidth="$props.maxWidth"
|
|
28
|
+
:width="$props.width"
|
|
29
|
+
padding="2px"
|
|
30
|
+
:border="false"
|
|
31
|
+
:elevation="true"
|
|
32
|
+
align="center-center"
|
|
33
|
+
>
|
|
34
|
+
<slot
|
|
35
|
+
name="content"
|
|
36
|
+
>
|
|
37
|
+
<FSCol
|
|
38
|
+
gap="0px"
|
|
39
|
+
>
|
|
40
|
+
<FSFadeOut
|
|
41
|
+
:scrollOutside="false"
|
|
42
|
+
maxHeight="80dvh"
|
|
43
|
+
>
|
|
44
|
+
<FSClickable
|
|
45
|
+
v-for="(item, index) in $props.items"
|
|
46
|
+
width="100%"
|
|
47
|
+
padding="8px"
|
|
48
|
+
height="40px"
|
|
49
|
+
:key="index"
|
|
50
|
+
:border="false"
|
|
51
|
+
@click="onClickItem(item)"
|
|
52
|
+
>
|
|
53
|
+
<slot
|
|
54
|
+
name="item"
|
|
55
|
+
v-bind="{ item, index }"
|
|
56
|
+
>
|
|
57
|
+
<FSRow
|
|
58
|
+
align="center-left"
|
|
59
|
+
>
|
|
60
|
+
<FSIcon
|
|
61
|
+
v-if="item.icon"
|
|
62
|
+
:icon="item.icon"
|
|
63
|
+
/>
|
|
64
|
+
<FSText
|
|
65
|
+
font="text-body"
|
|
66
|
+
>
|
|
67
|
+
{{ item.label }}
|
|
68
|
+
</FSText>
|
|
69
|
+
</FSRow>
|
|
70
|
+
</slot>
|
|
71
|
+
</FSClickable>
|
|
72
|
+
</FSFadeOut>
|
|
73
|
+
</FSCol>
|
|
74
|
+
</slot>
|
|
75
|
+
</FSCard>
|
|
76
|
+
</FSMenu>
|
|
77
|
+
</template>
|
|
78
|
+
|
|
79
|
+
<script lang="ts">
|
|
80
|
+
import { defineComponent, ref, type PropType } from "vue";
|
|
81
|
+
|
|
82
|
+
import { useColors } from "@dative-gpi/foundation-shared-components/composables";
|
|
83
|
+
|
|
84
|
+
import { ColorEnum, type ColorBase } from '@dative-gpi/foundation-shared-components/models';
|
|
85
|
+
|
|
86
|
+
import FSRow from '@dative-gpi/foundation-shared-components/components/FSRow.vue';
|
|
87
|
+
import FSCol from '@dative-gpi/foundation-shared-components/components/FSCol.vue';
|
|
88
|
+
import FSIcon from '@dative-gpi/foundation-shared-components/components/FSIcon.vue';
|
|
89
|
+
import FSMenu from '@dative-gpi/foundation-shared-components/components/FSMenu.vue';
|
|
90
|
+
import FSCard from '@dative-gpi/foundation-shared-components/components/FSCard.vue';
|
|
91
|
+
import FSText from '@dative-gpi/foundation-shared-components/components/FSText.vue';
|
|
92
|
+
import FSButton from '@dative-gpi/foundation-shared-components/components/FSButton.vue';
|
|
93
|
+
import FSClickable from '@dative-gpi/foundation-shared-components/components/FSClickable.vue';
|
|
94
|
+
|
|
95
|
+
export default defineComponent({
|
|
96
|
+
name: "FSInformationsMenu",
|
|
97
|
+
components: {
|
|
98
|
+
FSMenu,
|
|
99
|
+
FSCard,
|
|
100
|
+
FSRow,
|
|
101
|
+
FSText,
|
|
102
|
+
FSButton,
|
|
103
|
+
FSCol,
|
|
104
|
+
FSIcon,
|
|
105
|
+
FSClickable
|
|
106
|
+
},
|
|
107
|
+
props: {
|
|
108
|
+
items: {
|
|
109
|
+
type: Array as PropType<{label: string, icon?: string, onClick: () => void, closeOnContentClick?: boolean}[]>,
|
|
110
|
+
default: () => []
|
|
111
|
+
},
|
|
112
|
+
location: {
|
|
113
|
+
type: String,
|
|
114
|
+
default: "bottom"
|
|
115
|
+
},
|
|
116
|
+
width: {
|
|
117
|
+
type: [Array, String, Number] as PropType<string[] | number[] | string | number | null>,
|
|
118
|
+
default: null
|
|
119
|
+
},
|
|
120
|
+
maxWidth: {
|
|
121
|
+
type: [Array, String, Number] as PropType<string[] | number[] | string | number | null>,
|
|
122
|
+
default: "90dvw"
|
|
123
|
+
},
|
|
124
|
+
icon: {
|
|
125
|
+
type: String,
|
|
126
|
+
default: "mdi-dots-horizontal"
|
|
127
|
+
},
|
|
128
|
+
iconSize: {
|
|
129
|
+
type: String,
|
|
130
|
+
default: "18px"
|
|
131
|
+
},
|
|
132
|
+
buttonColor: {
|
|
133
|
+
type: String as PropType<ColorBase>,
|
|
134
|
+
default: ColorEnum.Light
|
|
135
|
+
},
|
|
136
|
+
buttonVariant: {
|
|
137
|
+
type: String as PropType<"standard" | "full" | "icon">,
|
|
138
|
+
required: false,
|
|
139
|
+
default: "icon"
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
emits: ["update:modelValue"],
|
|
143
|
+
setup() {
|
|
144
|
+
const modelValue = ref(false);
|
|
145
|
+
|
|
146
|
+
const { getColors } = useColors();
|
|
147
|
+
|
|
148
|
+
const lightColors = getColors(ColorEnum.Light);
|
|
149
|
+
|
|
150
|
+
const onClickItem = (item: { onClick: () => void, closeOnContentClick?: boolean }) => {
|
|
151
|
+
item.onClick();
|
|
152
|
+
if (item.closeOnContentClick !== false) {
|
|
153
|
+
modelValue.value = false;
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
return {
|
|
158
|
+
ColorEnum,
|
|
159
|
+
modelValue,
|
|
160
|
+
lightColors,
|
|
161
|
+
onClickItem
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
</script>
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<FSBaseField
|
|
3
|
+
:description="$props.description"
|
|
4
|
+
:hideHeader="$props.hideHeader"
|
|
5
|
+
:required="$props.required"
|
|
6
|
+
:disabled="$props.disabled"
|
|
7
|
+
:label="$props.label"
|
|
8
|
+
:maxWidth="$props.maxWidth"
|
|
9
|
+
>
|
|
10
|
+
<FSRow
|
|
11
|
+
align="bottom-center"
|
|
12
|
+
gap="32px"
|
|
13
|
+
>
|
|
14
|
+
<FSTermField
|
|
15
|
+
width="430px"
|
|
16
|
+
:label="$tr('ui.instant-picker.analyze-period', 'Analyze Period')"
|
|
17
|
+
:startDate="$props.startDate"
|
|
18
|
+
:endDate="$props.endDate"
|
|
19
|
+
:disabled="$props.disabled"
|
|
20
|
+
@update:startDate="$emit('update:startDate', $event)"
|
|
21
|
+
@update:endDate="$emit('update:endDate', $event)"
|
|
22
|
+
/>
|
|
23
|
+
<FSRow
|
|
24
|
+
padding="0 0 2px 0"
|
|
25
|
+
align="center-center"
|
|
26
|
+
>
|
|
27
|
+
<FSCol
|
|
28
|
+
width="fill"
|
|
29
|
+
>
|
|
30
|
+
<FSRangeSlider
|
|
31
|
+
minWidth='min(300px, 90vw)'
|
|
32
|
+
:disabled="$props.disabled"
|
|
33
|
+
:color="ColorEnum.Dark"
|
|
34
|
+
:thumbColor="ColorEnum.Primary"
|
|
35
|
+
:trackFillColor="ColorEnum.Primary"
|
|
36
|
+
:trackSize="8"
|
|
37
|
+
thumb-label="always"
|
|
38
|
+
:step="$props.stepTime"
|
|
39
|
+
:min="startTimestamp"
|
|
40
|
+
:max="endTimestamp"
|
|
41
|
+
:ticks="ticks"
|
|
42
|
+
showTicks="always"
|
|
43
|
+
:tick-size="4"
|
|
44
|
+
:modelValue="$props.modelValue"
|
|
45
|
+
@update:modelValue="$emit('update:modelValue', $event)"
|
|
46
|
+
>
|
|
47
|
+
<template
|
|
48
|
+
#thumb-label="{ modelValue }"
|
|
49
|
+
>
|
|
50
|
+
<FSSpan
|
|
51
|
+
font="text-overline"
|
|
52
|
+
>
|
|
53
|
+
{{ epochToMonthShortTimeFormat(modelValue) }}
|
|
54
|
+
</FSSpan>
|
|
55
|
+
</template>
|
|
56
|
+
<template
|
|
57
|
+
#tick-label="{ tick }"
|
|
58
|
+
>
|
|
59
|
+
<FSRow>
|
|
60
|
+
<FSText
|
|
61
|
+
:color="lightColors.dark"
|
|
62
|
+
font="text-overline"
|
|
63
|
+
>
|
|
64
|
+
{{ ticksPrecision === TimePrecision.Hours ? epochToShortTimeOnlyFormat(tick.value) : epochToDayMonthShortOnly(tick.value) }}
|
|
65
|
+
</FSText>
|
|
66
|
+
</FSRow>
|
|
67
|
+
</template>
|
|
68
|
+
</FSRangeSlider>
|
|
69
|
+
</FSCol>
|
|
70
|
+
<FSPlayButtons
|
|
71
|
+
v-if="$props.playable"
|
|
72
|
+
:disabled="$props.disabled"
|
|
73
|
+
:modelValue="playing"
|
|
74
|
+
@click:backward="onClickBackward"
|
|
75
|
+
@click:forward="onClickForward"
|
|
76
|
+
@update:modelValue="onPlayingChange"
|
|
77
|
+
/>
|
|
78
|
+
</FSRow>
|
|
79
|
+
</FSRow>
|
|
80
|
+
</FSBaseField>
|
|
81
|
+
</template>
|
|
82
|
+
|
|
83
|
+
<script lang="ts">
|
|
84
|
+
import { computed, defineComponent, ref, watch, type PropType } from "vue";
|
|
85
|
+
|
|
86
|
+
import { useDateFormat, useDateExpression } from "@dative-gpi/foundation-shared-services/composables";
|
|
87
|
+
|
|
88
|
+
import { ColorEnum } from "@dative-gpi/foundation-shared-components/models";
|
|
89
|
+
import { useBreakpoints, useColors } from '@dative-gpi/foundation-shared-components/composables';
|
|
90
|
+
|
|
91
|
+
import FSCol from '@dative-gpi/foundation-shared-components/components/FSCol.vue';
|
|
92
|
+
import FSSpan from '@dative-gpi/foundation-shared-components/components/FSSpan.vue';
|
|
93
|
+
import FSText from '@dative-gpi/foundation-shared-components/components/FSText.vue';
|
|
94
|
+
import FSPlayButtons from '@dative-gpi/foundation-shared-components/components/FSPlayButtons.vue';
|
|
95
|
+
import FSRangeSlider from '@dative-gpi/foundation-shared-components/components/FSRangeSlider.vue';
|
|
96
|
+
import FSBaseField from '@dative-gpi/foundation-shared-components/components/fields/FSBaseField.vue';
|
|
97
|
+
import FSTermField from '@dative-gpi/foundation-shared-components/components/fields/FSTermField.vue';
|
|
98
|
+
|
|
99
|
+
enum TimePrecision {
|
|
100
|
+
Hours = 1,
|
|
101
|
+
Days = 2,
|
|
102
|
+
Months = 3
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export default defineComponent({
|
|
106
|
+
name: "FSRangePicker",
|
|
107
|
+
components: {
|
|
108
|
+
FSCol,
|
|
109
|
+
FSSpan,
|
|
110
|
+
FSText,
|
|
111
|
+
FSTermField,
|
|
112
|
+
FSBaseField,
|
|
113
|
+
FSRangeSlider,
|
|
114
|
+
FSPlayButtons,
|
|
115
|
+
},
|
|
116
|
+
props: {
|
|
117
|
+
label: {
|
|
118
|
+
type: String,
|
|
119
|
+
required: false,
|
|
120
|
+
},
|
|
121
|
+
mode: {
|
|
122
|
+
type: String as () => 'single' | 'range',
|
|
123
|
+
required: false,
|
|
124
|
+
default: 'single'
|
|
125
|
+
},
|
|
126
|
+
modelValue: {
|
|
127
|
+
type: Object as () => [number, number],
|
|
128
|
+
required: true
|
|
129
|
+
},
|
|
130
|
+
startDate: {
|
|
131
|
+
type: String,
|
|
132
|
+
required: true
|
|
133
|
+
},
|
|
134
|
+
endDate: {
|
|
135
|
+
type: String,
|
|
136
|
+
required: true
|
|
137
|
+
},
|
|
138
|
+
description: {
|
|
139
|
+
type: String,
|
|
140
|
+
required: false,
|
|
141
|
+
default: null
|
|
142
|
+
},
|
|
143
|
+
hideHeader: {
|
|
144
|
+
type: Boolean,
|
|
145
|
+
required: false,
|
|
146
|
+
default: false
|
|
147
|
+
},
|
|
148
|
+
required: {
|
|
149
|
+
type: Boolean,
|
|
150
|
+
required: false,
|
|
151
|
+
default: false
|
|
152
|
+
},
|
|
153
|
+
disabled: {
|
|
154
|
+
type: Boolean,
|
|
155
|
+
required: false,
|
|
156
|
+
default: false
|
|
157
|
+
},
|
|
158
|
+
playable: {
|
|
159
|
+
type: Boolean,
|
|
160
|
+
required: false,
|
|
161
|
+
default: true
|
|
162
|
+
},
|
|
163
|
+
stepTime: {
|
|
164
|
+
type: Number,
|
|
165
|
+
required: false,
|
|
166
|
+
default: 60000
|
|
167
|
+
},
|
|
168
|
+
playingStepDuration: {
|
|
169
|
+
type: Number,
|
|
170
|
+
required: false,
|
|
171
|
+
default: 50
|
|
172
|
+
},
|
|
173
|
+
maxWidth: {
|
|
174
|
+
type: String as PropType<string | null>,
|
|
175
|
+
required: false,
|
|
176
|
+
default: null
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
emits: ['update:modelValue', 'update:startDate', 'update:endDate'],
|
|
180
|
+
setup(props, { emit }) {
|
|
181
|
+
const { epochToShortTimeOnlyFormat, epochToShortDateFormat, epochToDayMonthShortOnly, epochToISO, epochToMonthShortTimeFormat } = useDateFormat();
|
|
182
|
+
const { convert : convertTermToEpoch } = useDateExpression();
|
|
183
|
+
const { isMobileSized, isExtraSmall } = useBreakpoints();
|
|
184
|
+
const { getColors } = useColors();
|
|
185
|
+
|
|
186
|
+
const lightColors = getColors(ColorEnum.Light);
|
|
187
|
+
const playing = ref(false);
|
|
188
|
+
const playingInterval = ref();
|
|
189
|
+
|
|
190
|
+
const startTimestamp = computed(() => convertTermToEpoch(props.startDate));
|
|
191
|
+
const endTimestamp = computed(() => convertTermToEpoch(props.endDate));
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
const tickCountToShow = computed(() => {
|
|
196
|
+
if (isExtraSmall.value) {
|
|
197
|
+
return 3;
|
|
198
|
+
}
|
|
199
|
+
if (isMobileSized.value) {
|
|
200
|
+
return 4;
|
|
201
|
+
}
|
|
202
|
+
return 5;
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
const ticksPrecision = computed(() => {
|
|
206
|
+
const rangeDuration = endTimestamp.value - startTimestamp.value;
|
|
207
|
+
if (rangeDuration <= 86400000 * tickCountToShow.value) {
|
|
208
|
+
return TimePrecision.Hours;
|
|
209
|
+
}
|
|
210
|
+
if (rangeDuration <= 2592000000 * tickCountToShow.value) {
|
|
211
|
+
return TimePrecision.Days;
|
|
212
|
+
}
|
|
213
|
+
return TimePrecision.Months;
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
const ticks = computed(() => {
|
|
217
|
+
const ticks: number[] = [];
|
|
218
|
+
const count = tickCountToShow.value;
|
|
219
|
+
const precision = ticksPrecision.value;
|
|
220
|
+
|
|
221
|
+
const start = startTimestamp.value;
|
|
222
|
+
const end = endTimestamp.value;
|
|
223
|
+
const range = end - start;
|
|
224
|
+
|
|
225
|
+
let step: number;
|
|
226
|
+
|
|
227
|
+
if (precision === TimePrecision.Hours) {
|
|
228
|
+
step = Math.ceil(range / count / 3600000) * 3600000;
|
|
229
|
+
const alignedStart = Math.ceil(start / 3600000) * 3600000;
|
|
230
|
+
|
|
231
|
+
for (let i = 0; i < count; i++) {
|
|
232
|
+
const tick = alignedStart + i * step;
|
|
233
|
+
if (tick < end) {
|
|
234
|
+
ticks.push(tick);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
} else if (precision === TimePrecision.Days) {
|
|
239
|
+
step = Math.ceil(range / count / 86400000) * 86400000;
|
|
240
|
+
|
|
241
|
+
const date = new Date(start);
|
|
242
|
+
date.setHours(0, 0, 0, 0);
|
|
243
|
+
const alignedStart = date.getTime() + (date.getTime() < start ? step : 0);
|
|
244
|
+
|
|
245
|
+
for (let i = 0; i < count; i++) {
|
|
246
|
+
const tick = alignedStart + i * step;
|
|
247
|
+
if (tick < end) {
|
|
248
|
+
ticks.push(tick);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
} else {
|
|
253
|
+
const interval = range / count;
|
|
254
|
+
for (let i = 0; i < count; i++) {
|
|
255
|
+
ticks.push(start + i * interval);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
return ticks;
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
const onPlayingChange = (value: boolean) => {
|
|
264
|
+
playing.value = value;
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
const onClickBackward = () => {
|
|
268
|
+
const modelValueDuration = props.modelValue[1] - props.modelValue[0];
|
|
269
|
+
emit('update:modelValue', [startTimestamp.value, startTimestamp.value + modelValueDuration]);
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
const onClickForward = () => {
|
|
273
|
+
const modelValueDuration = props.modelValue[1] - props.modelValue[0];
|
|
274
|
+
emit('update:modelValue', [endTimestamp.value - modelValueDuration, endTimestamp.value]);
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
watch([() => props.startDate, () => props.endDate, () => props.modelValue], () => {
|
|
278
|
+
if((props.modelValue[0] < startTimestamp.value || props.modelValue[1] > endTimestamp.value)) {
|
|
279
|
+
emit('update:modelValue', [startTimestamp.value, endTimestamp.value]);
|
|
280
|
+
}
|
|
281
|
+
}, { immediate: true });
|
|
282
|
+
|
|
283
|
+
watch(playing, (value) => {
|
|
284
|
+
if(!value && playingInterval.value) {
|
|
285
|
+
clearInterval(playingInterval.value);
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
playingInterval.value = setInterval(() => {
|
|
290
|
+
if(props.modelValue[0] + props.stepTime <= endTimestamp.value && props.modelValue[1] + props.stepTime <= endTimestamp.value) {
|
|
291
|
+
emit('update:modelValue', [props.modelValue[0] + props.stepTime, props.modelValue[1] + props.stepTime]);
|
|
292
|
+
} else {
|
|
293
|
+
playing.value = false;
|
|
294
|
+
}
|
|
295
|
+
}, props.playingStepDuration);
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
return {
|
|
299
|
+
ticks,
|
|
300
|
+
playing,
|
|
301
|
+
ColorEnum,
|
|
302
|
+
lightColors,
|
|
303
|
+
endTimestamp,
|
|
304
|
+
TimePrecision,
|
|
305
|
+
startTimestamp,
|
|
306
|
+
ticksPrecision,
|
|
307
|
+
epochToISO,
|
|
308
|
+
onPlayingChange,
|
|
309
|
+
onClickForward,
|
|
310
|
+
onClickBackward,
|
|
311
|
+
epochToShortDateFormat,
|
|
312
|
+
epochToShortTimeOnlyFormat,
|
|
313
|
+
epochToDayMonthShortOnly,
|
|
314
|
+
epochToMonthShortTimeFormat
|
|
315
|
+
};
|
|
316
|
+
},
|
|
317
|
+
});
|
|
318
|
+
</script>
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<FSBaseField
|
|
3
|
+
:label="$props.label"
|
|
4
|
+
:description="$props.description"
|
|
5
|
+
:required="$props.required"
|
|
6
|
+
:disabled="$props.disabled"
|
|
7
|
+
:style="style"
|
|
8
|
+
>
|
|
9
|
+
<FSRow>
|
|
10
|
+
<v-range-slider
|
|
11
|
+
class="fs-range-slider"
|
|
12
|
+
hide-details
|
|
13
|
+
width="100%"
|
|
14
|
+
:disabled="$props.disabled"
|
|
15
|
+
:ripple="false"
|
|
16
|
+
:color="$props.color"
|
|
17
|
+
:style="style"
|
|
18
|
+
:elevation="0"
|
|
19
|
+
:tickSize="4"
|
|
20
|
+
:modelValue="$props.modelValue ?? undefined"
|
|
21
|
+
@update:modelValue="$emit('update:modelValue', $event)"
|
|
22
|
+
v-bind="$attrs"
|
|
23
|
+
>
|
|
24
|
+
<template
|
|
25
|
+
v-for="(_, name) in $slots"
|
|
26
|
+
v-slot:[name]="slotData"
|
|
27
|
+
>
|
|
28
|
+
<slot
|
|
29
|
+
:name="name"
|
|
30
|
+
v-bind="slotData"
|
|
31
|
+
/>
|
|
32
|
+
</template>
|
|
33
|
+
</v-range-slider>
|
|
34
|
+
</FSRow>
|
|
35
|
+
</FSBaseField>
|
|
36
|
+
</template>
|
|
37
|
+
|
|
38
|
+
<script lang="ts">
|
|
39
|
+
import { computed, defineComponent, type PropType, type StyleValue } from "vue";
|
|
40
|
+
|
|
41
|
+
import { type ColorBase, ColorEnum } from "@dative-gpi/foundation-shared-components/models";
|
|
42
|
+
import { useColors } from "@dative-gpi/foundation-shared-components/composables";
|
|
43
|
+
|
|
44
|
+
import FSBaseField from '@dative-gpi/foundation-shared-components/components/fields/FSBaseField.vue';
|
|
45
|
+
|
|
46
|
+
export default defineComponent({
|
|
47
|
+
name: "FSRangeSlider",
|
|
48
|
+
components: {
|
|
49
|
+
FSBaseField
|
|
50
|
+
},
|
|
51
|
+
props: {
|
|
52
|
+
label: {
|
|
53
|
+
type: String as PropType<string | null>,
|
|
54
|
+
required: false,
|
|
55
|
+
default: null
|
|
56
|
+
},
|
|
57
|
+
description: {
|
|
58
|
+
type: String as PropType<string | null>,
|
|
59
|
+
required: false,
|
|
60
|
+
default: null
|
|
61
|
+
},
|
|
62
|
+
modelValue: {
|
|
63
|
+
type: Object as PropType<[number, number] | null>,
|
|
64
|
+
required: false,
|
|
65
|
+
default: null
|
|
66
|
+
},
|
|
67
|
+
color: {
|
|
68
|
+
type: String as PropType<ColorBase>,
|
|
69
|
+
required: false,
|
|
70
|
+
default: ColorEnum.Dark
|
|
71
|
+
},
|
|
72
|
+
required: {
|
|
73
|
+
type: Boolean,
|
|
74
|
+
required: false,
|
|
75
|
+
default: false
|
|
76
|
+
},
|
|
77
|
+
disabled: {
|
|
78
|
+
type: Boolean,
|
|
79
|
+
required: false,
|
|
80
|
+
default: false
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
emits: ["update:modelValue"],
|
|
84
|
+
setup(props) {
|
|
85
|
+
const { getColors } = useColors();
|
|
86
|
+
|
|
87
|
+
const colors = computed(() => getColors(props.color));
|
|
88
|
+
const lights = getColors(ColorEnum.Light);
|
|
89
|
+
const darks = getColors(ColorEnum.Dark);
|
|
90
|
+
|
|
91
|
+
const style = computed((): StyleValue => {
|
|
92
|
+
if (props.disabled) {
|
|
93
|
+
return {
|
|
94
|
+
"--fs-range-slider-cursor" : "default",
|
|
95
|
+
"--fs-range-slider-track-color": lights.base,
|
|
96
|
+
"--fs-range-slider-thumb-color": lights.dark,
|
|
97
|
+
"--fs-range-slider-fill-color" : lights.dark,
|
|
98
|
+
"--fs-range-slider-color" : lights.dark
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
console.log(colors.value);
|
|
102
|
+
return {
|
|
103
|
+
"--fs-range-slider-cursor" : "pointer",
|
|
104
|
+
"--fs-range-slider-track-color": colors.value.light,
|
|
105
|
+
"--fs-range-slider-fill-color" : colors.value.base,
|
|
106
|
+
"--fs-range-slider-thumb-color": colors.value.base,
|
|
107
|
+
"--fs-range-slider-color" : darks.base
|
|
108
|
+
};
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
return {
|
|
112
|
+
style
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
</script>
|
package/components/map/FSMap.vue
CHANGED
|
@@ -3,11 +3,13 @@
|
|
|
3
3
|
</template>
|
|
4
4
|
|
|
5
5
|
<script lang="ts">
|
|
6
|
-
import { inject, type PropType, type Ref, watch, ref, onUnmounted,
|
|
6
|
+
import { inject, type PropType, type Ref, watch, ref, onUnmounted, computed } from 'vue';
|
|
7
|
+
import { type RouteLocation } from "vue-router";
|
|
7
8
|
|
|
8
|
-
import { type Map, divIcon, type LatLng, marker, type Marker, type MarkerClusterGroup
|
|
9
|
+
import { type Map, divIcon, type LatLng, marker, type Marker, type MarkerClusterGroup } from 'leaflet';
|
|
9
10
|
|
|
10
11
|
import { useColors } from "../../composables";
|
|
12
|
+
import { useRouting } from '@dative-gpi/foundation-shared-services/composables';
|
|
11
13
|
|
|
12
14
|
import { gpsMarkerHtml, locationMarkerHtml, pinMarkerHtml } from '../../utils/leafletMarkers';
|
|
13
15
|
import { MAP, MARKERCLUSTERGROUP } from './keys';
|
|
@@ -41,14 +43,28 @@ export default {
|
|
|
41
43
|
label: {
|
|
42
44
|
type: String,
|
|
43
45
|
required: false
|
|
46
|
+
},
|
|
47
|
+
to: {
|
|
48
|
+
type: Object as PropType<RouteLocation | null>,
|
|
49
|
+
required: false
|
|
44
50
|
}
|
|
45
51
|
},
|
|
46
|
-
emits: ['click'],
|
|
52
|
+
emits: ['click', 'auxclick'],
|
|
47
53
|
setup(props, { emit }) {
|
|
48
54
|
const map = inject<Ref<Map | null>>(MAP);
|
|
49
55
|
const markerClusterGroup = inject<Ref<MarkerClusterGroup | null>>(MARKERCLUSTERGROUP, ref(null));
|
|
50
|
-
|
|
56
|
+
|
|
51
57
|
const { getColors } = useColors();
|
|
58
|
+
const { handleRoutingEvent } = useRouting();
|
|
59
|
+
|
|
60
|
+
if(!map) {
|
|
61
|
+
throw new Error('FSMapTileLayer must be used inside a FSMap component');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if(!map.value) {
|
|
65
|
+
throw new Error('FSMapTileLayer must be used inside a FSMap component with a map');
|
|
66
|
+
}
|
|
67
|
+
|
|
52
68
|
const getMarkerIcon = () => {
|
|
53
69
|
if(props.variant === 'gps') {
|
|
54
70
|
const size = 16;
|
|
@@ -81,12 +97,32 @@ export default {
|
|
|
81
97
|
|
|
82
98
|
const actualMarker = ref(marker(props.latlng ?? [0, 0], { icon: getMarkerIcon() }));
|
|
83
99
|
|
|
84
|
-
|
|
85
|
-
|
|
100
|
+
const markerElement = computed(() => {
|
|
101
|
+
return actualMarker.value.getElement();
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
const onClick = (event: MouseEvent) => {
|
|
105
|
+
if(props.to) {
|
|
106
|
+
handleRoutingEvent(event, props.to, true);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
emit('click', {
|
|
111
|
+
...event,
|
|
112
|
+
latlng: props.latlng
|
|
113
|
+
});
|
|
86
114
|
}
|
|
87
115
|
|
|
88
|
-
|
|
89
|
-
|
|
116
|
+
const onAuxClick = (event: MouseEvent) => {
|
|
117
|
+
if(props.to) {
|
|
118
|
+
handleRoutingEvent(event, props.to);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
emit('auxclick', {
|
|
123
|
+
...event,
|
|
124
|
+
latlng: props.latlng
|
|
125
|
+
});
|
|
90
126
|
}
|
|
91
127
|
|
|
92
128
|
watch(map, () => {
|
|
@@ -118,11 +154,14 @@ export default {
|
|
|
118
154
|
actualMarker.value.setLatLng(props.latlng);
|
|
119
155
|
});
|
|
120
156
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
}
|
|
125
|
-
|
|
157
|
+
watch(markerElement, (newMarkerElement) => {
|
|
158
|
+
if(!newMarkerElement) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
newMarkerElement.addEventListener('click', onClick);
|
|
163
|
+
newMarkerElement.addEventListener('auxclick', onAuxClick);
|
|
164
|
+
}, { immediate: true });
|
|
126
165
|
|
|
127
166
|
onUnmounted(() => {
|
|
128
167
|
if(actualMarker.value && map.value) {
|
|
@@ -13,7 +13,7 @@ export const useMapLayers = () => {
|
|
|
13
13
|
{
|
|
14
14
|
name: MapLayers.Map,
|
|
15
15
|
label: $tr("ui.map-layer.map", "Map"),
|
|
16
|
-
image: new URL("
|
|
16
|
+
image: new URL("../assets/images/map/map.png", import.meta.url).href,
|
|
17
17
|
layers: [
|
|
18
18
|
tileLayer(`https://{s}.google.com/vt/lyrs=m&x={x}&y={y}&z={z}&key=${apiKey}`, {
|
|
19
19
|
maxZoom: 22,
|
|
@@ -26,7 +26,7 @@ export const useMapLayers = () => {
|
|
|
26
26
|
{
|
|
27
27
|
name: MapLayers.Imagery,
|
|
28
28
|
label: $tr("ui.map-layer.imagery", "Imagery"),
|
|
29
|
-
image: new URL("
|
|
29
|
+
image: new URL("../assets/images/map/imagery.png", import.meta.url).href,
|
|
30
30
|
layers: [
|
|
31
31
|
tileLayer(`https://{s}.google.com/vt/lyrs=s,h&x={x}&y={y}&z={z}&key=${apiKey}`, {
|
|
32
32
|
maxZoom: 22,
|
|
@@ -39,7 +39,7 @@ export const useMapLayers = () => {
|
|
|
39
39
|
{
|
|
40
40
|
name: MapLayers.Snow,
|
|
41
41
|
label: $tr("ui.map-layer.snow", "Snow ski map"),
|
|
42
|
-
image: new URL("
|
|
42
|
+
image: new URL("../assets/images/map/snow.png", import.meta.url).href,
|
|
43
43
|
layers: [
|
|
44
44
|
tileLayer(`https://{s}.google.com/vt/lyrs=m&x={x}&y={y}&z={z}&key=${apiKey}`, {
|
|
45
45
|
maxZoom: 22,
|
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.
|
|
4
|
+
"version": "1.0.159-sankey",
|
|
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.
|
|
14
|
-
"@dative-gpi/foundation-shared-services": "1.0.
|
|
13
|
+
"@dative-gpi/foundation-shared-domain": "1.0.159-sankey",
|
|
14
|
+
"@dative-gpi/foundation-shared-services": "1.0.159-sankey"
|
|
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": "2e082499c169cb28d4480d2fb76993f1240d9c87"
|
|
39
39
|
}
|
package/tools/alertsTools.ts
CHANGED
|
@@ -74,9 +74,10 @@ export const AlertTools = {
|
|
|
74
74
|
},
|
|
75
75
|
criticityLabel(value: Criticity): string {
|
|
76
76
|
switch (value) {
|
|
77
|
+
case Criticity.Information: return $tr('ui.common.information', 'Information');
|
|
77
78
|
case Criticity.Warning: return $tr('ui.common.warning', 'Warning');
|
|
78
79
|
case Criticity.Error: return $tr('ui.common.error', 'Error');
|
|
79
|
-
default: return $tr(
|
|
80
|
+
default: return $tr("ui.common.none", "None");
|
|
80
81
|
}
|
|
81
82
|
},
|
|
82
83
|
statusColor(status: AlertStatus): ColorEnum {
|