@dative-gpi/foundation-shared-components 0.0.101 → 0.0.103

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.
@@ -5,7 +5,9 @@
5
5
  :style="style"
6
6
  v-bind="$attrs"
7
7
  >
8
- <slot v-bind="{ color: $props.color, colors }" />
8
+ <slot
9
+ v-bind="{ color: $props.color, colors }"
10
+ />
9
11
  </FSCard>
10
12
  </template>
11
13
 
@@ -39,7 +41,7 @@ export default defineComponent({
39
41
 
40
42
  const colors = computed(() => getColors(props.color));
41
43
 
42
- const style = computed((): { [key: string] : string | undefined } => {
44
+ const style = computed((): { [key: string] : string | null | undefined } => {
43
45
  return {
44
46
  "--fs-color-background-color": colors.value.light,
45
47
  "--fs-color-border-color" : colors.value.lightContrast,
@@ -228,7 +228,6 @@ export default defineComponent({
228
228
  };
229
229
 
230
230
  const onSubmit = () => {
231
- console.log(valid.value)
232
231
  if (valid.value) {
233
232
  switch (currentStep.value) {
234
233
  case props.steps:
@@ -14,27 +14,37 @@
14
14
  <FSCol
15
15
  gap="2px"
16
16
  >
17
- <template v-if="headerSlot(item.code)">
17
+ <template
18
+ v-if="headerSlot(item.code)"
19
+ >
18
20
  <component
19
21
  :is="headerSlot(item.code)"
20
22
  v-bind="{ item }"
21
23
  />
22
24
  </template>
23
- <template v-else>
25
+ <template
26
+ v-else
27
+ >
24
28
  <FSText
25
29
  :font="item.hideDefault ? 'text-body' : 'text-overline'"
26
30
  >
27
31
  {{ item.label }}
28
32
  </FSText>
29
33
  </template>
30
- <template v-if="!item.hideDefault">
31
- <template v-if="itemSlot(item.code)">
34
+ <template
35
+ v-if="!item.hideDefault"
36
+ >
37
+ <template
38
+ v-if="itemSlot(item.code)"
39
+ >
32
40
  <component
33
41
  :is="itemSlot(item.code)"
34
42
  v-bind="{ item }"
35
43
  />
36
44
  </template>
37
- <template v-else>
45
+ <template
46
+ v-else
47
+ >
38
48
  <FSText>
39
49
  {{ item.value }}
40
50
  </FSText>
@@ -75,8 +85,8 @@ export default defineComponent({
75
85
  props: {
76
86
  items: {
77
87
  type: Array as PropType<FSGridItem[]>,
78
- default: [],
79
- required: false
88
+ required: false,
89
+ default: () => []
80
90
  }
81
91
  },
82
92
  setup() {
@@ -123,9 +133,9 @@ export default defineComponent({
123
133
 
124
134
  return {
125
135
  style,
126
- itemSlot,
136
+ itemEndSlot,
127
137
  headerSlot,
128
- itemEndSlot
138
+ itemSlot
129
139
  };
130
140
  }
131
141
  });
@@ -18,8 +18,14 @@
18
18
  <FSGrid
19
19
  :items="item.items"
20
20
  >
21
- <template v-for="(_, name) in $slots" v-slot:[name]="slotData">
22
- <slot :name="name" v-bind="slotData" />
21
+ <template
22
+ v-for="(_, name) in $slots"
23
+ v-slot:[name]="slotData"
24
+ >
25
+ <slot
26
+ :name="name"
27
+ v-bind="slotData"
28
+ />
23
29
  </template>
24
30
  </FSGrid>
25
31
  </FSCol>
@@ -47,8 +53,8 @@ export default defineComponent({
47
53
  props: {
48
54
  items: {
49
55
  type: Array as PropType<FSGridMosaic[]>,
50
- default: [],
51
- required: false
56
+ required: false,
57
+ default: () => []
52
58
  },
53
59
  cols: {
54
60
  type: Number as PropType<1 | 2>,
@@ -60,7 +66,7 @@ export default defineComponent({
60
66
  const { isExtraSmall } = useBreakpoints();
61
67
 
62
68
  const width = computed(() => {
63
- return props.cols == 2 && !isExtraSmall.value ? "calc(50% - 16px)" : "100%";
69
+ return props.cols == 2 && !isExtraSmall.value ? "calc(50% - 16px)" : "100%";
64
70
  });
65
71
 
66
72
  return {
@@ -1,36 +1,66 @@
1
1
  <template>
2
2
  <FSRow
3
- v-for="(modelStatus, index) in $props.modelStatuses"
4
- align="center-center"
5
- width="hug"
3
+ align="center-left"
6
4
  gap="4px"
7
- :key="index"
8
5
  :wrap="false"
9
6
  >
10
- <FSStatus
11
- v-for="(statusGroup, index) in deviceStatus(modelStatus)"
12
- :modelStatus="modelStatus"
13
- :statusGroup="statusGroup"
14
- :key="index"
7
+ <FSConnectivity
8
+ v-if="$props.deviceConnectivity && $props.deviceConnectivity.status != ConnectivityStatus.None"
9
+ :deviceConnectivity="$props.deviceConnectivity"
15
10
  />
11
+ <FSWorstAlert
12
+ v-if="$props.deviceWorstAlert"
13
+ :deviceAlerts="$props.deviceAlerts.length"
14
+ :deviceAlert="$props.deviceWorstAlert"
15
+ />
16
+ <template
17
+ v-for="(modelStatus, index) in $props.modelStatuses"
18
+ >
19
+ <FSStatus
20
+ v-if="deviceStatus(modelStatus)"
21
+ :statusGroup="deviceStatus(modelStatus)"
22
+ :modelStatus="modelStatus"
23
+ :key="index"
24
+ />
25
+ </template>
16
26
  </FSRow>
17
27
  </template>
18
28
 
19
29
  <script lang="ts">
20
30
  import { defineComponent, PropType } from "vue";
21
31
 
22
- import { FSDeviceStatus, FSDeviceStatusGroup, FSModelStatus } from "@dative-gpi/foundation-shared-components/models";
32
+ import { FSDeviceAlert, FSDeviceConnectivity, FSDeviceStatus, FSDeviceStatusGroup, FSModelStatus } from "@dative-gpi/foundation-shared-components/models";
33
+ import { ConnectivityStatus } from "@dative-gpi/foundation-shared-domain/models";
23
34
 
35
+ import FSConnectivity from "./FSConnectivity.vue";
36
+ import FSWorstAlert from "./FSWorstAlert.vue";
24
37
  import FSStatus from "./FSStatus.vue";
25
38
  import FSRow from "../FSRow.vue";
26
39
 
27
40
  export default defineComponent({
28
41
  name: "FSStatusesRow",
29
42
  components: {
43
+ FSConnectivity,
44
+ FSWorstAlert,
30
45
  FSStatus,
31
46
  FSRow
32
47
  },
33
48
  props: {
49
+ deviceConnectivity: {
50
+ type: Object as PropType<FSDeviceConnectivity>,
51
+ required: false,
52
+ default: null
53
+ },
54
+ deviceWorstAlert: {
55
+ type: Object as PropType<FSDeviceAlert>,
56
+ required: false,
57
+ default: null
58
+ },
59
+ deviceAlerts: {
60
+ type: Array as PropType<FSDeviceAlert[]>,
61
+ required: false,
62
+ default: () => []
63
+ },
34
64
  modelStatuses: {
35
65
  type: Array as PropType<FSModelStatus[]>,
36
66
  required: true
@@ -41,23 +71,24 @@ export default defineComponent({
41
71
  }
42
72
  },
43
73
  setup(props) {
44
- const deviceStatus = (modelStatus: FSModelStatus): FSDeviceStatusGroup[] => {
74
+ const deviceStatus = (modelStatus: FSModelStatus): FSDeviceStatusGroup | null => {
45
75
  const deviceStatus = props.deviceStatuses
46
76
  .find((deviceStatus: FSDeviceStatus) => deviceStatus.modelStatusId === modelStatus.id);
47
77
  if (deviceStatus != null) {
48
- return deviceStatus.statusGroups;
78
+ return deviceStatus.statusGroups[0];
49
79
  }
50
80
  if (modelStatus.showDefault) {
51
- return [{
81
+ return {
52
82
  label: modelStatus.label,
53
83
  icon: modelStatus.iconDefault!,
54
84
  color: modelStatus.colorDefault!
55
- }];
85
+ };
56
86
  }
57
- return [];
58
- }
87
+ return null;
88
+ };
59
89
 
60
90
  return {
91
+ ConnectivityStatus,
61
92
  deviceStatus
62
93
  };
63
94
  }
@@ -0,0 +1,653 @@
1
+ <template>
2
+ <FSBaseField
3
+ :label="$props.label"
4
+ :description="$props.description"
5
+ :hideHeader="$props.hideHeader"
6
+ :required="$props.required"
7
+ :editable="$props.editable"
8
+ :messages="messages"
9
+ >
10
+ <FSForm
11
+ v-model="valid"
12
+ >
13
+ <FSRow>
14
+ <FSSelectDateSetting
15
+ :lastPeriod="$props.lastPeriod"
16
+ :editable="$props.editable"
17
+ :variant="$props.variant"
18
+ :modelValue="localDateSetting"
19
+ @update:modelValue="localDateSettingChange"
20
+ />
21
+ <FSNumberField
22
+ v-if="pastSettings.includes(localDateSetting)"
23
+ :rules="[NumberRules.required(), NumberRules.min(0)]"
24
+ :editable="$props.editable"
25
+ :hideHeader="true"
26
+ :modelValue="localDateValue"
27
+ @update:modelValue="localDateValueChange"
28
+ />
29
+ <template
30
+ v-else-if="localDateSetting === DateSetting.Expression"
31
+ >
32
+ <FSRow
33
+ align="center-left"
34
+ :wrap="false"
35
+ >
36
+ <FSIcon>
37
+ mdi-clock-start
38
+ </FSIcon>
39
+ <FSTextField
40
+ :rules="[TextRules.required(), DateRules.validateExpression($props.variant)]"
41
+ :editable="$props.editable"
42
+ :hideHeader="true"
43
+ :modelValue="localStartDate"
44
+ @update:modelValue="localStartDateChange"
45
+ />
46
+ </FSRow>
47
+ <FSRow
48
+ align="center-left"
49
+ :wrap="false"
50
+ >
51
+ <FSIcon>
52
+ mdi-clock-end
53
+ </FSIcon>
54
+ <FSTextField
55
+ :rules="[TextRules.required(), DateRules.validateExpression($props.variant)]"
56
+ :editable="$props.editable"
57
+ :hideHeader="true"
58
+ :modelValue="localEndDate"
59
+ @update:modelValue="localEndDateChange"
60
+ />
61
+ </FSRow>
62
+ </template>
63
+ <FSDateTimeRangeField
64
+ v-else-if="localDateSetting === DateSetting.Pick"
65
+ :rules="[DateRules.required()]"
66
+ :editable="$props.editable"
67
+ :hideHeader="true"
68
+ :modelValue="[parseForPicker(localStartDate)!, parseForPicker(localEndDate)!]"
69
+ @update:modelValue="onPickDates"
70
+ />
71
+ </FSRow>
72
+ </FSForm>
73
+ </FSBaseField>
74
+ </template>
75
+
76
+ <script lang="ts">
77
+ import { computed, defineComponent, onMounted, PropType, ref} from "vue";
78
+ import _ from "lodash";
79
+
80
+ import { DateRules, NumberRules, TextRules } from "@dative-gpi/foundation-shared-components/models";
81
+ import { useAppTimeZone } from "@dative-gpi/foundation-shared-services/composables";
82
+ import { useRules } from "@dative-gpi/foundation-shared-components/composables";
83
+ import { DateSetting } from "@dative-gpi/foundation-shared-domain/models";
84
+
85
+ import FSSelectDateSetting from "../selects/FSSelectDateSetting.vue";
86
+ import FSDateTimeRangeField from "./FSDateTimeRangeField.vue";
87
+ import FSNumberField from "./FSNumberField.vue";
88
+ import FSBaseField from "./FSBaseField.vue";
89
+ import FSTextField from "./FSTextField.vue";
90
+ import FSForm from "../FSForm.vue";
91
+ import FSIcon from "../FSIcon.vue";
92
+ import FSRow from "../FSRow.vue";
93
+
94
+ export default defineComponent({
95
+ name: "FSTermField",
96
+ components: {
97
+ FSDateTimeRangeField,
98
+ FSSelectDateSetting,
99
+ FSNumberField,
100
+ FSBaseField,
101
+ FSTextField,
102
+ FSForm,
103
+ FSIcon,
104
+ FSRow
105
+ },
106
+ props: {
107
+ label: {
108
+ type: String as PropType<string | null>,
109
+ required: false,
110
+ default: null
111
+ },
112
+ description: {
113
+ type: String as PropType<string | null>,
114
+ required: false,
115
+ default: null
116
+ },
117
+ startDate: {
118
+ type: String,
119
+ required: true
120
+ },
121
+ endDate: {
122
+ type: String,
123
+ required: true
124
+ },
125
+ variant : {
126
+ type: String as PropType<"default" | "before-after">,
127
+ required: false,
128
+ default: "default"
129
+ },
130
+ hideHeader: {
131
+ type: Boolean,
132
+ required: false,
133
+ default: false
134
+ },
135
+ lastPeriod: {
136
+ type: Boolean,
137
+ required: false,
138
+ default: false
139
+ },
140
+ required: {
141
+ type: Boolean,
142
+ required: false,
143
+ default: false
144
+ },
145
+ rules: {
146
+ type: Array as PropType<any[]>,
147
+ required: false,
148
+ default: () => []
149
+ },
150
+ messages: {
151
+ type: Array as PropType<string[]>,
152
+ required: false,
153
+ default: null
154
+ },
155
+ editable: {
156
+ type: Boolean,
157
+ required: false,
158
+ default: true
159
+ }
160
+ },
161
+ emits: ["update:startDate", "update:endDate"],
162
+ setup(props, { emit }) {
163
+ const { parseForPicker,formatFromPicker, formatCurrentForPicker } = useAppTimeZone();
164
+ const { getMessages } = useRules();
165
+
166
+ const localDateSetting = ref<DateSetting>(DateSetting.PastDays);
167
+ const localDateValue = ref<number>(1);
168
+ const localStartDate = ref<string>("now - 1d");
169
+ const localEndDate = ref<string>("now");
170
+
171
+ const valid = ref<boolean>(false);
172
+
173
+ const pastSettings = computed((): DateSetting[] => {
174
+ return [
175
+ DateSetting.PastHours, DateSetting.PastDays, DateSetting.PastWeeks, DateSetting.PastMonths, DateSetting.PastYears,
176
+ DateSetting.MinutesBeforeAfter, DateSetting.HoursBeforeAfter, DateSetting.DaysBeforeAfter, DateSetting.WeeksBeforeAfter,
177
+ DateSetting.MinutesBefore, DateSetting.HoursBefore, DateSetting.DaysBefore, DateSetting.WeeksBefore
178
+ ];
179
+ });
180
+
181
+ const messages = computed((): string[] => {
182
+ return props.messages ??
183
+ getMessages(props.startDate, props.rules).concat(getMessages(props.endDate, props.rules));
184
+ });
185
+
186
+ const localStartDateChange = (value: string) => {
187
+ debouncedStartDate(value);
188
+ };
189
+
190
+ const onStartDateChange = (value: string) => {
191
+ localStartDate.value = value;
192
+ if (valid.value) {
193
+ emit("update:startDate", value);
194
+ }
195
+ };
196
+
197
+ const debouncedStartDate = _.debounce(onStartDateChange, 1000);
198
+
199
+ const localEndDateChange = (value: string) => {
200
+ debouncedEndDate(value);
201
+ };
202
+
203
+ const onEndDateChange = (value: string) => {
204
+ localEndDate.value = value;
205
+ if (valid.value) {
206
+ emit("update:endDate", value);
207
+ }
208
+ };
209
+
210
+ const debouncedEndDate = _.debounce(onEndDateChange, 1000);
211
+
212
+ const localDateSettingChange = (value: DateSetting) => {
213
+ localDateSetting.value = value;
214
+ switch (value) {
215
+ case DateSetting.None:
216
+ return;
217
+ case DateSetting.PastHours:
218
+ localStartDate.value = `now - ${localDateValue.value}h`;
219
+ localEndDate.value = "now";
220
+ break;
221
+ case DateSetting.PastDays:
222
+ localStartDate.value = `now - ${localDateValue.value}d`;
223
+ localEndDate.value = "now";
224
+ break;
225
+ case DateSetting.PastWeeks:
226
+ localStartDate.value = `now - ${localDateValue.value}w`;
227
+ localEndDate.value = "now";
228
+ break;
229
+ case DateSetting.PastMonths:
230
+ localStartDate.value = `now - ${localDateValue.value}M`;
231
+ localEndDate.value = "now";
232
+ break;
233
+ case DateSetting.PastYears:
234
+ localStartDate.value = `now - ${localDateValue.value}y`;
235
+ localEndDate.value = "now";
236
+ break;
237
+ case DateSetting.CurrentHour:
238
+ localStartDate.value = "now/h";
239
+ localEndDate.value = "now";
240
+ break;
241
+ case DateSetting.CurrentDay:
242
+ localStartDate.value = "now/d";
243
+ localEndDate.value = "now";
244
+ break;
245
+ case DateSetting.CurrentWeek:
246
+ localStartDate.value = "now/w";
247
+ localEndDate.value = "now";
248
+ break;
249
+ case DateSetting.CurrentMonth:
250
+ localStartDate.value = "now/M";
251
+ localEndDate.value = "now";
252
+ break;
253
+ case DateSetting.CurrentYear:
254
+ localStartDate.value = "now/y";
255
+ localEndDate.value = "now";
256
+ break;
257
+ case DateSetting.LastDay:
258
+ localStartDate.value = `now - 1d/d`;
259
+ localEndDate.value = "now/d";
260
+ break;
261
+ case DateSetting.LastWeek:
262
+ localStartDate.value = `now - 1w/w`;
263
+ localEndDate.value = "now/w";
264
+ break;
265
+ case DateSetting.LastMonth:
266
+ localStartDate.value = `now - 1M/M`;
267
+ localEndDate.value = "now/M";
268
+ break;
269
+ case DateSetting.LastYear:
270
+ localStartDate.value = `now - 1y/y`;
271
+ localEndDate.value = "now/y";
272
+ break;
273
+ case DateSetting.SinceLastDay:
274
+ localStartDate.value = `now - 1d/d`;
275
+ localEndDate.value = "now";
276
+ break;
277
+ case DateSetting.SinceLastWeek:
278
+ localStartDate.value = `now - 1w/w`;
279
+ localEndDate.value = "now";
280
+ break;
281
+ case DateSetting.SinceLastMonth:
282
+ localStartDate.value = `now - 1M/M`;
283
+ localEndDate.value = "now";
284
+ break;
285
+ case DateSetting.SinceLastYear:
286
+ localStartDate.value = `now - 1y/y`;
287
+ localEndDate.value = "now";
288
+ break;
289
+ case DateSetting.LastPeriod:
290
+ localStartDate.value = "from - to + from";
291
+ localEndDate.value = "from";
292
+ break;
293
+ case DateSetting.MinutesBeforeAfter:
294
+ localStartDate.value = `alertstart - ${localDateValue.value}m`;
295
+ localEndDate.value = `alertend + ${localDateValue.value}m`;
296
+ break;
297
+ case DateSetting.HoursBeforeAfter:
298
+ localStartDate.value = `alertstart - ${localDateValue.value}h`;
299
+ localEndDate.value = `alertend + ${localDateValue.value}h`;
300
+ break;
301
+ case DateSetting.DaysBeforeAfter:
302
+ localStartDate.value = `alertstart - ${localDateValue.value}d`;
303
+ localEndDate.value = `alertend + ${localDateValue.value}d`;
304
+ break;
305
+ case DateSetting.WeeksBeforeAfter:
306
+ localStartDate.value = `alertstart - ${localDateValue.value}w`;
307
+ localEndDate.value = `alertend + ${localDateValue.value}w`;
308
+ break;
309
+ case DateSetting.MinutesBefore:
310
+ localStartDate.value = `alertstart - ${localDateValue.value}m`;
311
+ localEndDate.value = "alertend";
312
+ break;
313
+ case DateSetting.HoursBefore:
314
+ localStartDate.value = `alertstart - ${localDateValue.value}h`;
315
+ localEndDate.value = "alertend";
316
+ break;
317
+ case DateSetting.DaysBefore:
318
+ localStartDate.value = `alertstart - ${localDateValue.value}d`;
319
+ localEndDate.value = "alertend";
320
+ break;
321
+ case DateSetting.WeeksBefore:
322
+ localStartDate.value = `alertstart - ${localDateValue.value}w`;
323
+ localEndDate.value = "alertend";
324
+ break;
325
+ case DateSetting.Expression:
326
+ if (props.variant === "before-after") {
327
+ localStartDate.value = `alertstart - ${localDateValue.value}d`;
328
+ localEndDate.value = "alertend";
329
+ }
330
+ else {
331
+ localStartDate.value = `now - ${localDateValue.value}d`;
332
+ localEndDate.value = "now";
333
+ }
334
+ break;
335
+ case DateSetting.Pick:
336
+ localEndDate.value = formatCurrentForPicker(0);
337
+ localStartDate.value = formatCurrentForPicker(-1);
338
+ break;
339
+ }
340
+ emit("update:startDate", localStartDate.value);
341
+ emit("update:endDate", localEndDate.value);
342
+ };
343
+
344
+ const localDateValueChange = (value: number) => {
345
+ localDateValue.value = value ? value : 1;
346
+
347
+ switch (localDateSetting.value) {
348
+ case DateSetting.None:
349
+ return;
350
+ case DateSetting.PastHours:
351
+ localStartDate.value = `now - ${localDateValue.value}h`;
352
+ localEndDate.value = "now";
353
+ break;
354
+ case DateSetting.PastDays:
355
+ localStartDate.value = `now - ${localDateValue.value}d`;
356
+ localEndDate.value = "now";
357
+ break;
358
+ case DateSetting.PastWeeks:
359
+ localStartDate.value = `now - ${localDateValue.value}w`;
360
+ localEndDate.value = "now";
361
+ break;
362
+ case DateSetting.PastMonths:
363
+ localStartDate.value = `now - ${localDateValue.value}M`;
364
+ localEndDate.value = "now";
365
+ break;
366
+ case DateSetting.PastYears:
367
+ localStartDate.value = `now - ${localDateValue.value}y`;
368
+ localEndDate.value = "now";
369
+ break;
370
+ case DateSetting.MinutesBeforeAfter:
371
+ localStartDate.value = `alertstart - ${localDateValue.value}m`;
372
+ localEndDate.value = `alertend + ${localDateValue.value}m`;
373
+ break;
374
+ case DateSetting.HoursBeforeAfter:
375
+ localStartDate.value = `alertstart - ${localDateValue.value}h`;
376
+ localEndDate.value = `alertend + ${localDateValue.value}h`;
377
+ break;
378
+ case DateSetting.DaysBeforeAfter:
379
+ localStartDate.value = `alertstart - ${localDateValue.value}d`;
380
+ localEndDate.value = `alertend + ${localDateValue.value}d`;
381
+ break;
382
+ case DateSetting.WeeksBeforeAfter:
383
+ localStartDate.value = `alertstart - ${localDateValue.value}w`;
384
+ localEndDate.value = `alertend + ${localDateValue.value}w`;
385
+ break;
386
+ case DateSetting.MinutesBefore:
387
+ localStartDate.value = `alertstart - ${localDateValue.value}m`;
388
+ localEndDate.value = "alertend";
389
+ break;
390
+ case DateSetting.HoursBefore:
391
+ localStartDate.value = `alertstart - ${localDateValue.value}h`;
392
+ localEndDate.value = "alertend";
393
+ break;
394
+ case DateSetting.DaysBefore:
395
+ localStartDate.value = `alertstart - ${localDateValue.value}d`;
396
+ localEndDate.value = "alertend";
397
+ break;
398
+ case DateSetting.WeeksBefore:
399
+ localStartDate.value = `alertstart - ${localDateValue.value}w`;
400
+ localEndDate.value = "alertend";
401
+ break;
402
+ }
403
+ emit("update:startDate", localStartDate.value);
404
+ emit("update:endDate", localEndDate.value);
405
+ };
406
+
407
+ const onPickDates = (value: number[] | null) => {
408
+ if (!value) {
409
+ localEndDate.value = formatCurrentForPicker(0);
410
+ localStartDate.value = formatCurrentForPicker(-1);
411
+ if (valid.value) {
412
+ emit("update:startDate", localStartDate.value);
413
+ emit("update:endDate", localEndDate.value);
414
+ }
415
+ }
416
+ else {
417
+ if (value && value[0] != null && formatFromPicker(value[0]) !== localStartDate.value) {
418
+ localStartDate.value = formatFromPicker(value[0]);
419
+ if (valid.value) {
420
+ emit("update:startDate", localStartDate.value);
421
+ }
422
+ }
423
+ if (value && value[1] != null && formatFromPicker(value[1]) !== localEndDate.value) {
424
+ localEndDate.value = formatFromPicker(value[1]);
425
+ if (valid.value) {
426
+ emit("update:endDate", localEndDate.value);
427
+ }
428
+ }
429
+ }
430
+ };
431
+
432
+ const reset = (): void => {
433
+ localStartDate.value = props.startDate;
434
+ localEndDate.value = props.endDate;
435
+
436
+ if (props.variant === "before-after") {
437
+ if (props.endDate === "alertend") {
438
+ let match = /^alertstart-([\d]+)([mhdw])$/g.exec(props.startDate.replaceAll(" ", ""));
439
+ if (match != null) {
440
+ localDateValue.value = parseInt(match[1]);
441
+ switch (match[2]) {
442
+ case 'm': {
443
+ localDateSetting.value = DateSetting.MinutesBefore;
444
+ return;
445
+ }
446
+ case 'h': {
447
+ localDateSetting.value = DateSetting.HoursBefore;
448
+ return;
449
+ }
450
+ case 'd': {
451
+ localDateSetting.value = DateSetting.DaysBefore;
452
+ return;
453
+ }
454
+ case 'w': {
455
+ localDateSetting.value = DateSetting.WeeksBefore;
456
+ return;
457
+ }
458
+ default: {
459
+ localDateSetting.value = DateSetting.Expression;
460
+ localDateValue.value = 1;
461
+ return;
462
+ }
463
+ }
464
+ }
465
+ }
466
+
467
+ if (
468
+ /^alertstart-([\d]+)([mhdw])$/g.test(props.startDate.replaceAll(" ", "")) &&
469
+ /^alertend\+([\d]+)([mhdw])$/g.test(props.endDate.replaceAll(" ", ""))
470
+ ) {
471
+ let startMatch = /^alertstart-([\d]+)([mhdw])$/g.exec(props.startDate.replaceAll(" ", ""));
472
+ let endMatch = /^alertend\+([\d]+)([mhdw])$/g.exec(props.endDate.replaceAll(" ", ""));
473
+ if (startMatch != null && endMatch != null && startMatch[1] === endMatch[1] && startMatch[2] === endMatch[2]) {
474
+ localDateValue.value = parseInt(startMatch[1]);
475
+ switch(startMatch[2]) {
476
+ case 'm': {
477
+ localDateSetting.value = DateSetting.MinutesBeforeAfter;
478
+ return;
479
+ }
480
+ case 'h': {
481
+ localDateSetting.value = DateSetting.HoursBeforeAfter;
482
+ return;
483
+ }
484
+ case 'd': {
485
+ localDateSetting.value = DateSetting.DaysBeforeAfter;
486
+ return;
487
+ }
488
+ case 'w': {
489
+ localDateSetting.value = DateSetting.WeeksBeforeAfter;
490
+ return;
491
+ }
492
+ default: {
493
+ localDateSetting.value = DateSetting.Expression;
494
+ localDateValue.value = 1;
495
+ return;
496
+ }
497
+ }
498
+ }
499
+ }
500
+
501
+ localDateSetting.value = DateSetting.Expression;
502
+ localDateValue.value = 1;
503
+ return;
504
+ }
505
+
506
+ if (props.lastPeriod && props.endDate === "from" && props.startDate === "from - to + from") {
507
+ localDateSetting.value = DateSetting.LastPeriod;
508
+ return;
509
+ }
510
+ if (props.endDate === "now/d" && props.startDate === "now - 1d/d") {
511
+ localDateSetting.value = DateSetting.LastDay;
512
+ return;
513
+ }
514
+ if (props.endDate === "now/w" && props.startDate === "now - 1w/w") {
515
+ localDateSetting.value = DateSetting.LastWeek;
516
+ return;
517
+ }
518
+ if (props.endDate === "now/M" && props.startDate === "now - 1M/M") {
519
+ localDateSetting.value = DateSetting.LastMonth;
520
+ return;
521
+ }
522
+ if (props.endDate === "now/y" && props.startDate === "now - 1y/y") {
523
+ localDateSetting.value = DateSetting.LastYear;
524
+ return;
525
+ }
526
+
527
+ if (props.endDate === "now") {
528
+ let match = /^now-1([dwMy])\/([dwMy])$/g.exec(props.startDate.replaceAll(" ", ""));
529
+ if (match != null) {
530
+ localDateValue.value = 1;
531
+ switch (match[1]) {
532
+ case 'd': {
533
+ localDateSetting.value = DateSetting.SinceLastDay;
534
+ return;
535
+ }
536
+ case 'w': {
537
+ localDateSetting.value = DateSetting.SinceLastWeek;
538
+ return;
539
+ }
540
+ case 'M': {
541
+ localDateSetting.value = DateSetting.SinceLastMonth;
542
+ return;
543
+ }
544
+ case 'y': {
545
+ localDateSetting.value = DateSetting.SinceLastYear;
546
+ return;
547
+ }
548
+ default: {
549
+ localDateSetting.value = DateSetting.Expression;
550
+ return;
551
+ }
552
+ }
553
+ }
554
+ match = /^now-([\d]+)([hdwMy])$/g.exec(props.startDate.replaceAll(" ", ""));
555
+ if (match != null) {
556
+ localDateValue.value = parseInt(match[1]);
557
+ switch (match[2]) {
558
+ case 'h': {
559
+ localDateSetting.value = DateSetting.PastHours;
560
+ return;
561
+ }
562
+ case 'd': {
563
+ localDateSetting.value = DateSetting.PastDays;
564
+ return;
565
+ }
566
+ case 'w': {
567
+ localDateSetting.value = DateSetting.PastWeeks;
568
+ return;
569
+ }
570
+ case 'M': {
571
+ localDateSetting.value = DateSetting.PastMonths;
572
+ return;
573
+ }
574
+ case 'y': {
575
+ localDateSetting.value = DateSetting.PastYears;
576
+ return;
577
+ }
578
+ default: {
579
+ localDateSetting.value = DateSetting.Expression;
580
+ localDateValue.value = 1;
581
+ return;
582
+ }
583
+ }
584
+ }
585
+
586
+ match = /^now\/([hdwMy])$/g.exec(props.startDate.replaceAll(" ", ""));
587
+ if (match != null) {
588
+ localDateValue.value = 1;
589
+ switch (match[1]) {
590
+ case 'h': {
591
+ localDateSetting.value = DateSetting.CurrentHour;
592
+ return;
593
+ }
594
+ case 'd': {
595
+ localDateSetting.value = DateSetting.CurrentDay;
596
+ return;
597
+ }
598
+ case 'w': {
599
+ localDateSetting.value = DateSetting.CurrentWeek;
600
+ return;
601
+ }
602
+ case 'M': {
603
+ localDateSetting.value = DateSetting.CurrentMonth;
604
+ return;
605
+ }
606
+ case 'y': {
607
+ localDateSetting.value = DateSetting.CurrentYear;
608
+ return;
609
+ }
610
+ default: {
611
+ localDateSetting.value = DateSetting.Expression;
612
+ return;
613
+ }
614
+ }
615
+ }
616
+ }
617
+
618
+ if (parseForPicker(props.endDate) != null && parseForPicker(props.startDate) != null) {
619
+ localDateSetting.value = DateSetting.Pick;
620
+ localDateValue.value = 1;
621
+ return;
622
+ }
623
+
624
+ localDateSetting.value = DateSetting.Expression;
625
+ localDateValue.value = 1;
626
+ };
627
+
628
+ onMounted(() => {
629
+ reset();
630
+ });
631
+
632
+ return {
633
+ localDateSetting,
634
+ localDateValue,
635
+ localStartDate,
636
+ localEndDate,
637
+ pastSettings,
638
+ DateSetting,
639
+ NumberRules,
640
+ DateRules,
641
+ TextRules,
642
+ messages,
643
+ valid,
644
+ localDateSettingChange,
645
+ localDateValueChange,
646
+ localStartDateChange,
647
+ localEndDateChange,
648
+ parseForPicker,
649
+ onPickDates
650
+ };
651
+ }
652
+ });
653
+ </script>
@@ -124,7 +124,7 @@ export default defineComponent({
124
124
  },
125
125
  emits: ["update:modelValue"],
126
126
  setup(props, { emit }) {
127
- const { validateOn, blurred, getMessages } = useRules();
127
+ const { validateOn, getMessages } = useRules();
128
128
  const { getColors } = useColors();
129
129
 
130
130
  const errors = getColors(ColorEnum.Error);
@@ -238,7 +238,6 @@ export default defineComponent({
238
238
  ColorEnum,
239
239
  dayStart,
240
240
  messages,
241
- blurred,
242
241
  dayEnd,
243
242
  style,
244
243
  onChangeHourStart,
@@ -0,0 +1,99 @@
1
+ <template>
2
+ <FSSelectField
3
+ :editable="$props.editable"
4
+ :items="dateSettings"
5
+ :hideHeader="true"
6
+ :clearable="false"
7
+ :modelValue="$props.modelValue"
8
+ @update:modelValue="$emit('update:modelValue', $event)"
9
+ v-bind="$attrs"
10
+ />
11
+ </template>
12
+
13
+ <script lang="ts">
14
+ import { computed, defineComponent, PropType } from "vue";
15
+
16
+ import { useTranslations as useTranslationsProvider } from "@dative-gpi/bones-ui/composables";
17
+ import { DateSetting } from "@dative-gpi/foundation-shared-domain/models";
18
+
19
+ import FSSelectField from "../fields/FSSelectField.vue";
20
+
21
+ export default defineComponent({
22
+ name: "FSSelectDateSetting",
23
+ components: {
24
+ FSSelectField
25
+ },
26
+ props: {
27
+ variant: {
28
+ type: String as PropType<"default" | "before-after">,
29
+ required: false,
30
+ default: "default"
31
+ },
32
+ modelValue: {
33
+ type: Number as PropType<DateSetting>,
34
+ required: true
35
+ },
36
+ lastPeriod: {
37
+ type: Boolean,
38
+ required: false,
39
+ default: false
40
+ },
41
+ editable: {
42
+ type: Boolean,
43
+ required: false,
44
+ default: true
45
+ }
46
+ },
47
+ emits: ["update:modelValue"],
48
+ setup(props) {
49
+ const { $tr } = useTranslationsProvider();
50
+
51
+ const dateSettings = computed((): { id: DateSetting, label: string }[] => {
52
+ if (props.variant === "before-after") {
53
+ return [
54
+ { id: DateSetting.Pick, label: $tr("ui.common.pick-dates", "Pick dates") },
55
+ { id: DateSetting.MinutesBeforeAfter, label: $tr("ui.common.x-minutes-before-after-hour", "x Minutes before/after") },
56
+ { id: DateSetting.HoursBeforeAfter, label: $tr("ui.common.x-hours-before-after-hour", "x Hours before/after") },
57
+ { id: DateSetting.DaysBeforeAfter, label: $tr("ui.common.x-days-before-after-hour", "x Days before/after") },
58
+ { id: DateSetting.WeeksBeforeAfter, label: $tr("ui.common.x-weeks-before-after-hour", "x Weeks before/after") },
59
+ { id: DateSetting.MinutesBefore, label: $tr("ui.common.x-minutes-before", "x Minutes before") },
60
+ { id: DateSetting.HoursBefore, label: $tr("ui.common.x-hours-before", "x Hours before") },
61
+ { id: DateSetting.DaysBefore, label: $tr("ui.common.x-days-before", "x Days before") },
62
+ { id: DateSetting.WeeksBefore, label: $tr("ui.common.x-weeks-before", "x Weeks before") },
63
+ { id: DateSetting.Expression, label: $tr("ui.common.expression", "Expression") }
64
+ ];
65
+ }
66
+ let dateSettings = [
67
+ { id: DateSetting.Pick, label: $tr("ui.common.pick-dates", "Pick dates") },
68
+ { id: DateSetting.CurrentHour, label: $tr("ui.common.this-hour", "This hour") },
69
+ { id: DateSetting.CurrentDay, label: $tr("ui.common.this-day", "This day") },
70
+ { id: DateSetting.CurrentWeek, label: $tr("ui.common.this-week", "This week") },
71
+ { id: DateSetting.CurrentMonth, label: $tr("ui.common.this-month", "This month") },
72
+ { id: DateSetting.CurrentYear, label: $tr("ui.common.this-year", "This year") },
73
+ { id: DateSetting.LastDay, label: $tr("ui.common.last-day", "Last day") },
74
+ { id: DateSetting.LastWeek, label: $tr("ui.common.last-week", "Last week") },
75
+ { id: DateSetting.LastMonth, label: $tr("ui.common.last-month", "Last month") },
76
+ { id: DateSetting.LastYear, label: $tr("ui.common.last-year", "Last year") },
77
+ { id: DateSetting.SinceLastDay, label: $tr("ui.common.since-last-day", "Since last day") },
78
+ { id: DateSetting.SinceLastWeek, label: $tr("ui.common.since-last-week", "Since last week") },
79
+ { id: DateSetting.SinceLastMonth, label: $tr("ui.common.since-last-month", "Since last month") },
80
+ { id: DateSetting.SinceLastYear, label: $tr("ui.common.since-last-year", "Since last year") },
81
+ { id: DateSetting.PastHours, label: $tr("ui.common.past-x-hours", "Past x hours") },
82
+ { id: DateSetting.PastDays, label: $tr("ui.common.past-x-days", "Past x days") },
83
+ { id: DateSetting.PastWeeks, label: $tr("ui.common.past-x-weeks", "Past x weeks") },
84
+ { id: DateSetting.PastMonths, label: $tr("ui.common.past-x-months", "Past x months") },
85
+ { id: DateSetting.PastYears, label: $tr("ui.common.past-x-years", "Past x years") },
86
+ { id: DateSetting.Expression, label: $tr("ui.common.expression", "Expression") }
87
+ ];
88
+ if (props.lastPeriod) {
89
+ dateSettings.push({ id: DateSetting.LastPeriod, label: $tr("ui.common.last-period", "Last period") });
90
+ }
91
+ return dateSettings;
92
+ })
93
+
94
+ return {
95
+ dateSettings
96
+ };
97
+ }
98
+ });
99
+ </script>
@@ -1,15 +1,23 @@
1
1
  <template>
2
- <FSSelectField itemTitle="id"
2
+ <FSSelectField
3
+ itemTitle="id"
3
4
  :items="timeZones"
4
5
  :modelValue="$props.modelValue"
5
6
  @update:modelValue="$emit('update:modelValue', $event)"
6
- v-bind="$attrs">
7
- <template #append-inner>
8
- <slot name="append-inner">
9
- <FSChip v-if="offset"
7
+ v-bind="$attrs"
8
+ >
9
+ <template
10
+ #append-inner
11
+ >
12
+ <slot
13
+ name="append-inner"
14
+ >
15
+ <FSChip
16
+ v-if="offset"
10
17
  variant="standard"
11
18
  :color="ColorEnum.Dark"
12
- :label="offset" />
19
+ :label="offset"
20
+ />
13
21
  </slot>
14
22
  </template>
15
23
  </FSSelectField>
@@ -12,8 +12,8 @@
12
12
  <FSRow
13
13
  align="center-center"
14
14
  gap="24px"
15
- :wrap="false"
16
15
  :height="imageSize"
16
+ :wrap="false"
17
17
  >
18
18
  <FSCol
19
19
  gap="12px"
@@ -35,23 +35,13 @@
35
35
  {{ $props.code }}
36
36
  </FSText>
37
37
  </FSCol>
38
- <FSRow
39
- gap="4px"
40
- >
41
- <FSConnectivity
42
- v-if="$props.deviceConnectivity && $props.deviceConnectivity.status != ConnectivityStatus.None"
43
- :deviceConnectivity="$props.deviceConnectivity"
44
- />
45
- <FSWorstAlert
46
- v-if="$props.deviceWorstAlert"
47
- :deviceAlert="$props.deviceWorstAlert"
48
- :deviceAlerts="$props.deviceAlerts.length"
49
- />
50
- <FSStatusesRow
51
- :modelStatuses="lineModelStatuses"
52
- :deviceStatuses="lineDeviceStatuses"
53
- />
54
- </FSRow>
38
+ <FSStatusesRow
39
+ :deviceConnectivity="$props.deviceConnectivity"
40
+ :deviceWorstAlert="$props.deviceWorstAlert"
41
+ :deviceStatuses="singleDeviceStatuses"
42
+ :modelStatuses="singleModelStatuses"
43
+ :deviceAlerts="$props.deviceAlerts"
44
+ />
55
45
  </FSCol>
56
46
  <FSImage
57
47
  v-if="$props.imageId"
@@ -77,13 +67,10 @@ import { computed, defineComponent, PropType } from "vue";
77
67
 
78
68
  import { FSModelStatus, FSDeviceStatus, FSDeviceAlert, FSDeviceConnectivity } from "@dative-gpi/foundation-shared-components/models";
79
69
  import { useBreakpoints } from "@dative-gpi/foundation-shared-components/composables";
80
- import { ConnectivityStatus } from "@dative-gpi/foundation-shared-domain/models";
81
70
  import { ColorEnum } from "@dative-gpi/foundation-shared-components/models";
82
71
 
83
72
  import FSStatusesCarousel from "../deviceOrganisations/FSStatusesCarousel.vue";
84
- import FSConnectivity from "../deviceOrganisations/FSConnectivity.vue";
85
73
  import FSStatusesRow from "../deviceOrganisations/FSStatusesRow.vue";
86
- import FSWorstAlert from "../deviceOrganisations/FSWorstAlert.vue";
87
74
  import FSDivider from "../FSDivider.vue";
88
75
  import FSImage from "../FSImage.vue";
89
76
  import FSText from "../FSText.vue";
@@ -95,9 +82,7 @@ export default defineComponent({
95
82
  name: "FSDeviceOrganisationTileUI",
96
83
  components: {
97
84
  FSStatusesCarousel,
98
- FSConnectivity,
99
85
  FSStatusesRow,
100
- FSWorstAlert,
101
86
  FSDivider,
102
87
  FSImage,
103
88
  FSText,
@@ -160,9 +145,9 @@ export default defineComponent({
160
145
  setup(props) {
161
146
  const { isMobileSized } = useBreakpoints();
162
147
 
163
- const lineModelStatuses = computed((): FSModelStatus[] => {
148
+ const singleModelStatuses = computed((): FSModelStatus[] => {
164
149
  return props.modelStatuses.filter(modelStatus => {
165
- if (!modelStatus.inline || modelStatus.groupById) {
150
+ if (modelStatus.groupById != null) {
166
151
  return false;
167
152
  }
168
153
  if (!modelStatus.showDefault) {
@@ -171,24 +156,18 @@ export default defineComponent({
171
156
  }
172
157
  }
173
158
  return true;
174
- }).slice(0, 4).sort((a, b) => a.index - b.index);
159
+ }).slice(0, 5).sort((a, b) => a.index - b.index);
175
160
  });
176
161
 
177
- const lineDeviceStatuses = computed((): FSDeviceStatus[] => {
162
+ const singleDeviceStatuses = computed((): FSDeviceStatus[] => {
178
163
  return props.deviceStatuses.filter(deviceStatus => {
179
- return lineModelStatuses.value.some(modelStatus => modelStatus.id === deviceStatus.modelStatusId)
164
+ return singleModelStatuses.value.some(modelStatus => modelStatus.id === deviceStatus.modelStatusId)
180
165
  });
181
166
  });
182
167
 
183
168
  const carouselModelStatuses = computed((): FSModelStatus[] => {
184
- const notCarouselModelStatuses = props.modelStatuses.filter(modelStatus => {
185
- if (!modelStatus.inline || modelStatus.groupById) {
186
- return false;
187
- }
188
- return true;
189
- }).slice(0, 4);
190
169
  return props.modelStatuses.filter(modelStatus => {
191
- if (notCarouselModelStatuses.some(lineModelStatus => modelStatus.id === lineModelStatus.id)) {
170
+ if (modelStatus.groupById == null) {
192
171
  return false;
193
172
  }
194
173
  if (!modelStatus.showDefault) {
@@ -197,7 +176,7 @@ export default defineComponent({
197
176
  }
198
177
  }
199
178
  return true;
200
- }).sort((a, b) => (a.index + (a.inline ? b.index : 0)) - b.index);
179
+ }).sort((a, b) => a.index - b.index);
201
180
  });
202
181
 
203
182
  const carouselDeviceStatuses = computed((): FSDeviceStatus[] => {
@@ -219,12 +198,11 @@ export default defineComponent({
219
198
  });
220
199
 
221
200
  return {
222
- ColorEnum,
223
- lineModelStatuses,
224
- lineDeviceStatuses,
225
- ConnectivityStatus,
226
- carouselModelStatuses,
227
201
  carouselDeviceStatuses,
202
+ carouselModelStatuses,
203
+ singleDeviceStatuses,
204
+ singleModelStatuses,
205
+ ColorEnum,
228
206
  imageSize,
229
207
  infoWidth
230
208
  };
@@ -1,11 +1,10 @@
1
1
  export interface FSModelStatus {
2
- id: string;
3
- label: string;
4
- inline: boolean;
5
- index: number;
6
- groupById?: string | null;
7
- groupByLabel?: string | null;
8
- showDefault: boolean;
9
- iconDefault?: string | null;
10
- colorDefault?: string | null;
2
+ id: string;
3
+ label: string;
4
+ index: number;
5
+ groupById?: string | null;
6
+ groupByLabel?: string | null;
7
+ showDefault: boolean;
8
+ iconDefault?: string | null;
9
+ colorDefault?: string | null;
11
10
  }
package/models/rules.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { useTranslations as useTranslationsProvider } from "@dative-gpi/bones-ui/composables";
2
2
  import { useAppTimeZone } from "@dative-gpi/foundation-shared-services/composables";
3
+ import { validateExpression } from "@dative-gpi/foundation-shared-domain/tools";
3
4
 
4
5
  import { getTimeBestString } from "../utils";
5
6
 
@@ -39,7 +40,8 @@ export const IconRules = {
39
40
  export const DateRules = {
40
41
  required: (message: string | undefined = undefined) => (value: string) => !!value || (message ?? $tr("ui.rules.required", "Required")),
41
42
  min: (min: number, message: string | undefined = undefined) => (value: number) => (!value || value >= min) || (message ?? $tr("ui.rules.date-min", "Must be after {0}", epochToLongDateFormat(min))),
42
- max: (max: number, message: string | undefined = undefined) => (value: number) => (!value || value <= max) || (message ?? $tr("ui.rules.date-max", "Must be before {0}", epochToLongDateFormat(max)))
43
+ max: (max: number, message: string | undefined = undefined) => (value: number) => (!value || value <= max) || (message ?? $tr("ui.rules.date-max", "Must be before {0}", epochToLongDateFormat(max))),
44
+ validateExpression: (variant: "default" | "before-after") => (value: string) => validateExpression(value, variant)
43
45
  };
44
46
 
45
47
  export const SelectRules = {
@@ -62,4 +64,4 @@ export const TimeRules = {
62
64
 
63
65
  export const ToggleRules = {
64
66
  required: (message: string | undefined = undefined) => (value: boolean) => value || (message ?? $tr("ui.rules.required", "Required"))
65
- }
67
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@dative-gpi/foundation-shared-components",
3
3
  "sideEffects": false,
4
- "version": "0.0.101",
4
+ "version": "0.0.103",
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": "0.0.101",
14
- "@dative-gpi/foundation-shared-services": "0.0.101",
13
+ "@dative-gpi/foundation-shared-domain": "0.0.103",
14
+ "@dative-gpi/foundation-shared-services": "0.0.103",
15
15
  "@fontsource/montserrat": "^5.0.16",
16
16
  "@lexical/clipboard": "^0.12.5",
17
17
  "@lexical/history": "^0.12.5",
@@ -32,5 +32,5 @@
32
32
  "sass": "^1.69.5",
33
33
  "sass-loader": "^13.3.2"
34
34
  },
35
- "gitHead": "8ab763942b592e5d46dc629ca95e80cfb7729400"
35
+ "gitHead": "dd1b4c1e23a1826d70e02de27cb419205392fc5c"
36
36
  }