@dative-gpi/foundation-shared-components 0.0.24 → 0.0.26

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.
@@ -0,0 +1,27 @@
1
+ <template>
2
+ <v-expansion-panels variant="accordion">
3
+ <template
4
+ v-for="(component, index) in getChildren()"
5
+ :key="index"
6
+ >
7
+ <component :is="component" />
8
+ </template>
9
+ </v-expansion-panels>
10
+ </template>
11
+
12
+ <script lang="ts">
13
+ import { defineComponent } from "vue";
14
+
15
+ import { useSlots } from "@dative-gpi/foundation-shared-components/composables";
16
+
17
+ export default defineComponent({
18
+ name: "FSAccordion",
19
+ setup() {
20
+ const { getChildren } = useSlots();
21
+
22
+ return {
23
+ getChildren
24
+ }
25
+ }
26
+ })
27
+ </script>
@@ -0,0 +1,123 @@
1
+ <template>
2
+ <v-expansion-panel
3
+ class="fs-accordion-panel"
4
+ :collapseIcon="$props.collapseIcon"
5
+ :expandIcon="$props.expandIcon"
6
+ :disabled="false"
7
+ :elevation="0"
8
+ :style="style"
9
+ v-bind="$attrs"
10
+ >
11
+ <template #title>
12
+ <slot name="title">
13
+ <FSRow>
14
+ <FSIcon
15
+ v-if="$props.prependIcon"
16
+ >
17
+ {{ $props.prependIcon }}
18
+ </FSIcon>
19
+ <FSSpan
20
+ class="fs-accordion-panel-title"
21
+ >
22
+ {{ $props.title }}
23
+ </FSSpan>
24
+ </FSRow>
25
+ </slot>
26
+ </template>
27
+ <template #text>
28
+ <slot name="content">
29
+ <FSText>
30
+ {{ $props.content }}
31
+ </FSText>
32
+ </slot>
33
+ </template>
34
+ </v-expansion-panel>
35
+ </template>
36
+
37
+ <script lang="ts">
38
+ import { computed, defineComponent, PropType } from "vue";
39
+
40
+ import { ColorBase, ColorEnum } from "@dative-gpi/foundation-shared-components/models";
41
+ import { useColors } from "@dative-gpi/foundation-shared-components/composables";
42
+ import { sizeToVar } from "@dative-gpi/foundation-shared-components/utils";
43
+
44
+ import FSIcon from "./FSIcon.vue";
45
+ import FSSpan from "./FSSpan.vue";
46
+ import FSText from "./FSText.vue";
47
+ import FSRow from "./FSRow.vue";
48
+
49
+ export default defineComponent({
50
+ name: "FSAccordionPanel",
51
+ components: {
52
+ FSIcon,
53
+ FSSpan,
54
+ FSText,
55
+ FSRow
56
+ },
57
+ props: {
58
+ prependIcon: {
59
+ type: String,
60
+ required: false,
61
+ default: null
62
+ },
63
+ title: {
64
+ type: String,
65
+ required: false,
66
+ default: null
67
+ },
68
+ content: {
69
+ type: String,
70
+ required: false,
71
+ default: null
72
+ },
73
+ borderRadius: {
74
+ type: [String, Number],
75
+ required: false,
76
+ default: "4px"
77
+ },
78
+ divider: {
79
+ type: Boolean,
80
+ required: false,
81
+ default: false
82
+ },
83
+ expandIcon: {
84
+ type: String,
85
+ required: false,
86
+ default: "mdi-chevron-down"
87
+ },
88
+ collapseIcon: {
89
+ type: String,
90
+ required: false,
91
+ default: "mdi-chevron-up"
92
+ },
93
+ color: {
94
+ type: String as PropType<ColorBase>,
95
+ required: false,
96
+ default: ColorEnum.Primary
97
+ }
98
+ },
99
+ setup(props) {
100
+ const { getColors } = useColors();
101
+
102
+ const colors = computed(() => getColors(props.color));
103
+ const backgrounds = getColors(ColorEnum.Background);
104
+ const darks = getColors(ColorEnum.Dark);
105
+
106
+ const style = computed((): {[code: string]: string} & Partial<CSSStyleDeclaration> => {
107
+ return {
108
+ "--fs-accordion-panel-border-radius" : sizeToVar(props.borderRadius),
109
+ "--fs-accordion-panel-border-size" : props.divider ? "1px" : "0",
110
+ "--fs-accordion-panel-border-color" : darks.base,
111
+ "--fs-accordion-panel-background-color" : backgrounds.base,
112
+ "--fs-accordion-panel-color" : darks.base,
113
+ "--fs-accordion-panel-hover-background-color": colors.value.light,
114
+ "--fs-accordion-panel-hover-color" : colors.value.base,
115
+ };
116
+ });
117
+
118
+ return {
119
+ style
120
+ };
121
+ }
122
+ });
123
+ </script>
@@ -1,19 +1,23 @@
1
1
  <template>
2
- <FSCard
2
+ <button
3
3
  v-if="!href"
4
- :border="$props.border"
5
- :class="classes"
6
- :style="style"
4
+ :class="wrapperClasses"
7
5
  @click.stop="onClick"
8
- v-bind="$attrs"
9
6
  >
10
- <template v-for="(_, name) in $slots" v-slot:[name]="slotData">
11
- <slot :name="name" v-bind="slotData" />
12
- </template>
13
- </FSCard>
7
+ <FSCard
8
+ :border="$props.border"
9
+ :class="classes"
10
+ :style="style"
11
+ v-bind="$attrs"
12
+ >
13
+ <template v-for="(_, name) in $slots" v-slot:[name]="slotData">
14
+ <slot :name="name" v-bind="slotData" />
15
+ </template>
16
+ </FSCard>
17
+ </button>
14
18
  <a
15
19
  v-else
16
- :class="anchorClasses"
20
+ :class="wrapperClasses"
17
21
  :href="href"
18
22
  >
19
23
  <FSCard
@@ -138,10 +142,10 @@ export default defineComponent({
138
142
  return classNames;
139
143
  });
140
144
 
141
- const anchorClasses = computed((): string[] => {
145
+ const wrapperClasses = computed((): string[] => {
142
146
  const classNames: string[] = [];
143
147
  if (props.fullWidth) {
144
- classNames.push("fs-clickable-anchor-full-width");
148
+ classNames.push("fs-clickable-wrapper-full-width");
145
149
  }
146
150
  return classNames;
147
151
  });
@@ -165,7 +169,7 @@ export default defineComponent({
165
169
  };
166
170
 
167
171
  return {
168
- anchorClasses,
172
+ wrapperClasses,
169
173
  classes,
170
174
  style,
171
175
  href,
@@ -2,7 +2,7 @@
2
2
  <v-form
3
3
  ref="formRef"
4
4
  :validateOn="validateOn"
5
- @submit="submitted = true"
5
+ @submit.stop="onSubmit"
6
6
  @update:modelValue="$emit('update:modelValue', $event)"
7
7
  >
8
8
  <slot />
@@ -39,13 +39,20 @@ export default defineComponent({
39
39
  }
40
40
  });
41
41
 
42
- provide("validateOn", validateOn.value);
43
- provide("submitted", submitted.value);
42
+ const onSubmit = (event: SubmitEvent) => {
43
+ event.stopImmediatePropagation();
44
+ event.preventDefault();
45
+ submitted.value = true;
46
+ };
47
+
48
+ provide("validateOn", validateOn);
49
+ provide("submitted", submitted);
44
50
 
45
51
  return {
46
- formRef,
47
52
  validateOn,
48
- submitted
53
+ submitted,
54
+ formRef,
55
+ onSubmit
49
56
  };
50
57
  }
51
58
  });
@@ -1,6 +1,5 @@
1
1
  <template>
2
2
  <v-menu
3
- v-if="$props.deviceConnectivity"
4
3
  :closeOnContentClick="false"
5
4
  v-model="menu"
6
5
  >
@@ -14,68 +13,25 @@
14
13
  {{ $props.deviceConnectivity.icon }}
15
14
  </FSColorIcon>
16
15
  </template>
17
- <FSCard
18
- :elevation="true"
19
- :border="false"
20
- >
21
- <FSCol
22
- align="center-center"
23
- padding="6px 24px"
24
- >
25
- <FSCol
26
- align="center-center"
27
- gap="12px"
28
- >
29
- <FSChip
30
- :color="$props.deviceConnectivity.color"
31
- :prependIcon="$props.deviceConnectivity.icon"
32
- :label="connectivityLabel"
33
- />
34
- <FSRow
35
- width="hug"
36
- >
37
- <FSText>
38
- {{ $tr("ui.shared.device-connectivity.last-message", "Last message") }}
39
- </FSText>
40
- </FSRow>
41
- </FSCol>
42
- <FSRow
43
- v-if="deviceTimestamp"
44
- width="hug"
45
- >
46
- <FSSpan
47
- font="text-overline"
48
- >
49
- {{ deviceTimestamp }}
50
- </FSSpan>
51
- </FSRow>
52
- </FSCol>
53
- </FSCard>
16
+ <FSConnectivityCard
17
+ :deviceConnectivity="$props.deviceConnectivity"
18
+ />
54
19
  </v-menu>
55
20
  </template>
56
21
 
57
22
  <script lang="ts">
58
- import { computed, defineComponent, PropType, ref } from "vue";
23
+ import { defineComponent, PropType, ref } from "vue";
59
24
 
60
- import { useTranslations as useTranslationsProvider } from "@dative-gpi/bones-ui/composables";
61
25
  import { FSDeviceConnectivity } from "@dative-gpi/foundation-shared-components/models";
62
- import { ConnectivityStatus } from "@dative-gpi/foundation-shared-domain/models";
63
- import { useTimeZone } from "@dative-gpi/foundation-shared-services/composables";
64
26
 
27
+ import FSConnectivityCard from "./FSConnectivityCard.vue";
65
28
  import FSColorIcon from "../FSColorIcon.vue";
66
- import FSCard from "../FSCard.vue";
67
- import FSChip from "../FSChip.vue";
68
- import FSText from "../FSText.vue";
69
- import FSSpan from "../FSSpan.vue";
70
29
 
71
30
  export default defineComponent({
72
31
  name: "FSConnectivity",
73
32
  components: {
74
- FSColorIcon,
75
- FSCard,
76
- FSChip,
77
- FSText,
78
- FSSpan
33
+ FSConnectivityCard,
34
+ FSColorIcon
79
35
  },
80
36
  props: {
81
37
  deviceConnectivity: {
@@ -83,31 +39,10 @@ export default defineComponent({
83
39
  required: true
84
40
  }
85
41
  },
86
- setup(props) {
87
- const { epochToLongTimeFormat } = useTimeZone();
88
- const { $tr } = useTranslationsProvider();
89
-
42
+ setup() {
90
43
  const menu = ref(false);
91
44
 
92
- const connectivityLabel = computed((): string => {
93
- switch (props.deviceConnectivity.status) {
94
- case ConnectivityStatus.Connected: return $tr("ui.connectivity-status.connected", "Connected");
95
- case ConnectivityStatus.PartiallyConnected: return $tr("ui.connectivity-status.partially-connected", "Partially connected");
96
- case ConnectivityStatus.AlmostOffline: return $tr("ui.connectivity-status.almost-offline", "Almost offline");
97
- default: return $tr("ui.connectivity-status.offline", "Offline");
98
- }
99
- });
100
-
101
- const deviceTimestamp = computed((): string => {
102
- if (props.deviceConnectivity.sourceTimestamp) {
103
- return epochToLongTimeFormat(props.deviceConnectivity.sourceTimestamp);
104
- }
105
- return "";
106
- });
107
-
108
45
  return {
109
- connectivityLabel,
110
- deviceTimestamp,
111
46
  menu
112
47
  };
113
48
  }
@@ -0,0 +1,98 @@
1
+ <template>
2
+ <FSCard
3
+ :elevation="true"
4
+ :border="false"
5
+ >
6
+ <FSCol
7
+ align="center-center"
8
+ padding="6px 24px"
9
+ >
10
+ <FSCol
11
+ align="center-center"
12
+ gap="12px"
13
+ >
14
+ <FSChip
15
+ :color="$props.deviceConnectivity.color"
16
+ :prependIcon="$props.deviceConnectivity.icon"
17
+ :label="connectivityLabel"
18
+ />
19
+ <FSRow
20
+ width="hug"
21
+ >
22
+ <FSText>
23
+ {{ $tr("ui.shared.device-connectivity.last-message", "Last message") }}
24
+ </FSText>
25
+ </FSRow>
26
+ </FSCol>
27
+ <FSRow
28
+ v-if="deviceTimestamp"
29
+ width="hug"
30
+ >
31
+ <FSSpan
32
+ font="text-overline"
33
+ >
34
+ {{ deviceTimestamp }}
35
+ </FSSpan>
36
+ </FSRow>
37
+ </FSCol>
38
+ </FSCard>
39
+ </template>
40
+
41
+ <script lang="ts">
42
+ import { computed, defineComponent, PropType } from "vue";
43
+
44
+ import { useTranslations as useTranslationsProvider } from "@dative-gpi/bones-ui/composables";
45
+ import { FSDeviceConnectivity } from "@dative-gpi/foundation-shared-components/models";
46
+ import { ConnectivityStatus } from "@dative-gpi/foundation-shared-domain/models";
47
+ import { useTimeZone } from "@dative-gpi/foundation-shared-services/composables";
48
+
49
+ import FSCard from "../FSCard.vue";
50
+ import FSChip from "../FSChip.vue";
51
+ import FSText from "../FSText.vue";
52
+ import FSSpan from "../FSSpan.vue";
53
+ import FSCol from "../FSCol.vue";
54
+ import FSRow from "../FSRow.vue";
55
+
56
+ export default defineComponent({
57
+ name: "FSConnectivityCard",
58
+ components: {
59
+ FSCard,
60
+ FSChip,
61
+ FSText,
62
+ FSSpan,
63
+ FSCol,
64
+ FSRow
65
+ },
66
+ props: {
67
+ deviceConnectivity: {
68
+ type: Object as PropType<FSDeviceConnectivity>,
69
+ required: true
70
+ }
71
+ },
72
+ setup(props) {
73
+ const { epochToLongTimeFormat } = useTimeZone();
74
+ const { $tr } = useTranslationsProvider();
75
+
76
+ const connectivityLabel = computed((): string => {
77
+ switch (props.deviceConnectivity.status) {
78
+ case ConnectivityStatus.Connected: return $tr("ui.connectivity-status.connected", "Connected");
79
+ case ConnectivityStatus.PartiallyConnected: return $tr("ui.connectivity-status.partially-connected", "Partially connected");
80
+ case ConnectivityStatus.AlmostOffline: return $tr("ui.connectivity-status.almost-offline", "Almost offline");
81
+ default: return $tr("ui.connectivity-status.offline", "Offline");
82
+ }
83
+ });
84
+
85
+ const deviceTimestamp = computed((): string => {
86
+ if (props.deviceConnectivity.sourceTimestamp) {
87
+ return epochToLongTimeFormat(props.deviceConnectivity.sourceTimestamp);
88
+ }
89
+ return "";
90
+ });
91
+
92
+ return {
93
+ connectivityLabel,
94
+ deviceTimestamp
95
+ };
96
+ }
97
+ });
98
+ </script>
@@ -13,78 +13,26 @@
13
13
  {{ $props.statusGroup.icon }}
14
14
  </FSColorIcon>
15
15
  </template>
16
- <FSCard
17
- :elevation="true"
18
- :border="false"
19
- >
20
- <FSCol
21
- align="center-center"
22
- padding="6px 24px"
23
- >
24
- <FSCol
25
- align="center-center"
26
- gap="12px"
27
- >
28
- <FSChip
29
- :color="$props.statusGroup.color"
30
- :prependIcon="$props.statusGroup.icon"
31
- :label="$props.statusGroup.label"
32
- />
33
- <FSRow
34
- v-if="$props.statusGroup.value"
35
- width="hug"
36
- >
37
- <FSText
38
- font="text-button"
39
- :color="$props.statusGroup.color"
40
- >
41
- {{ $props.statusGroup.value }} {{ $props.statusGroup.unit }}
42
- </FSText>
43
- </FSRow>
44
- <FSRow
45
- v-if="$props.statusGroup.value && $props.modelStatus.groupById && $props.statusGroup.groupByValue"
46
- width="hug"
47
- >
48
- <FSSpan>
49
- {{ $props.modelStatus.groupByLabel }} {{ $props.statusGroup.groupByValue }}
50
- </FSSpan>
51
- </FSRow>
52
- </FSCol>
53
- <FSRow
54
- v-if="deviceTimestamp"
55
- width="hug"
56
- >
57
- <FSSpan
58
- font="text-overline"
59
- >
60
- {{ deviceTimestamp }}
61
- </FSSpan>
62
- </FSRow>
63
- </FSCol>
64
- </FSCard>
16
+ <FSStatusCard
17
+ :modelStatus="$props.modelStatus"
18
+ :statusGroup="$props.statusGroup"
19
+ />
65
20
  </v-menu>
66
21
  </template>
67
22
 
68
23
  <script lang="ts">
69
- import { computed, defineComponent, PropType, ref } from "vue";
24
+ import { defineComponent, PropType, ref } from "vue";
70
25
 
71
26
  import { FSDeviceStatusGroup, FSModelStatus } from "@dative-gpi/foundation-shared-components/models";
72
- import { useTimeZone } from "@dative-gpi/foundation-shared-services/composables";
73
27
 
28
+ import FSStatusCard from "./FSStatusCard.vue";
74
29
  import FSColorIcon from "../FSColorIcon.vue";
75
- import FSCard from "../FSCard.vue";
76
- import FSChip from "../FSChip.vue";
77
- import FSText from "../FSText.vue";
78
- import FSSpan from "../FSSpan.vue";
79
30
 
80
31
  export default defineComponent({
81
32
  name: "FSStatus",
82
33
  components: {
83
- FSColorIcon,
84
- FSCard,
85
- FSChip,
86
- FSText,
87
- FSSpan
34
+ FSStatusCard,
35
+ FSColorIcon
88
36
  },
89
37
  props: {
90
38
  modelStatus: {
@@ -96,20 +44,10 @@ export default defineComponent({
96
44
  required: true
97
45
  }
98
46
  },
99
- setup(props) {
100
- const { epochToLongTimeFormat } = useTimeZone();
101
-
47
+ setup() {
102
48
  const menu = ref(false);
103
49
 
104
- const deviceTimestamp = computed((): string => {
105
- if (props.statusGroup.sourceTimestamp) {
106
- return epochToLongTimeFormat(props.statusGroup.sourceTimestamp);
107
- }
108
- return "";
109
- });
110
-
111
50
  return {
112
- deviceTimestamp,
113
51
  menu
114
52
  };
115
53
  }
@@ -0,0 +1,101 @@
1
+ <template>
2
+ <FSCard
3
+ :elevation="true"
4
+ :border="false"
5
+ >
6
+ <FSCol
7
+ align="center-center"
8
+ padding="6px 24px"
9
+ >
10
+ <FSCol
11
+ align="center-center"
12
+ gap="12px"
13
+ >
14
+ <FSChip
15
+ :color="$props.statusGroup.color"
16
+ :prependIcon="$props.statusGroup.icon"
17
+ :label="$props.statusGroup.label"
18
+ />
19
+ <FSRow
20
+ v-if="$props.statusGroup.value"
21
+ width="hug"
22
+ >
23
+ <FSText
24
+ font="text-button"
25
+ :color="$props.statusGroup.color"
26
+ >
27
+ {{ $props.statusGroup.value }} {{ $props.statusGroup.unit }}
28
+ </FSText>
29
+ </FSRow>
30
+ <FSRow
31
+ v-if="$props.statusGroup.value && $props.modelStatus.groupById && $props.statusGroup.groupByValue"
32
+ width="hug"
33
+ >
34
+ <FSSpan>
35
+ {{ $props.modelStatus.groupByLabel }} {{ $props.statusGroup.groupByValue }}
36
+ </FSSpan>
37
+ </FSRow>
38
+ </FSCol>
39
+ <FSRow
40
+ v-if="deviceTimestamp"
41
+ width="hug"
42
+ >
43
+ <FSSpan
44
+ font="text-overline"
45
+ >
46
+ {{ deviceTimestamp }}
47
+ </FSSpan>
48
+ </FSRow>
49
+ </FSCol>
50
+ </FSCard>
51
+ </template>
52
+
53
+ <script lang="ts">
54
+ import { computed, defineComponent, PropType } from "vue";
55
+
56
+ import { FSDeviceStatusGroup, FSModelStatus } from "@dative-gpi/foundation-shared-components/models";
57
+ import { useTimeZone } from "@dative-gpi/foundation-shared-services/composables";
58
+
59
+ import FSCard from "../FSCard.vue";
60
+ import FSChip from "../FSChip.vue";
61
+ import FSText from "../FSText.vue";
62
+ import FSSpan from "../FSSpan.vue";
63
+ import FSCol from "../FSCol.vue";
64
+ import FSRow from "../FSRow.vue";
65
+
66
+ export default defineComponent({
67
+ name: "FSStatusCard",
68
+ components: {
69
+ FSCard,
70
+ FSChip,
71
+ FSText,
72
+ FSSpan,
73
+ FSCol,
74
+ FSRow
75
+ },
76
+ props: {
77
+ modelStatus: {
78
+ type: Object as PropType<FSModelStatus>,
79
+ required: true
80
+ },
81
+ statusGroup: {
82
+ type: Object as PropType<FSDeviceStatusGroup>,
83
+ required: true
84
+ }
85
+ },
86
+ setup(props) {
87
+ const { epochToLongTimeFormat } = useTimeZone();
88
+
89
+ const deviceTimestamp = computed((): string => {
90
+ if (props.statusGroup.sourceTimestamp) {
91
+ return epochToLongTimeFormat(props.statusGroup.sourceTimestamp);
92
+ }
93
+ return "";
94
+ });
95
+
96
+ return {
97
+ deviceTimestamp
98
+ };
99
+ }
100
+ });
101
+ </script>
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <FSCarousel
3
- :height="height"
3
+ :height="['26px', '20px']"
4
4
  >
5
5
  <template #prev="{ props }">
6
6
  <FSButton
@@ -39,10 +39,9 @@
39
39
  </template>
40
40
 
41
41
  <script lang="ts">
42
- import { computed, defineComponent, PropType, ref } from "vue";
42
+ import { defineComponent, PropType, ref } from "vue";
43
43
 
44
44
  import { FSDeviceStatus, FSDeviceStatusGroup, FSModelStatus } from "@dative-gpi/foundation-shared-components/models";
45
- import { useBreakpoints } from "@dative-gpi/foundation-shared-components/composables";
46
45
  import { ColorEnum } from "@dative-gpi/foundation-shared-components/models";
47
46
 
48
47
  import FSCarousel from "../FSCarousel.vue";
@@ -69,14 +68,8 @@ export default defineComponent({
69
68
  }
70
69
  },
71
70
  setup(props) {
72
- const { isMobileSized } = useBreakpoints();
73
-
74
71
  const tab = ref(0);
75
72
 
76
- const height = computed((): number => {
77
- return isMobileSized.value ? 20 : 26;
78
- });
79
-
80
73
  const deviceStatus = (modelStatus: FSModelStatus): FSDeviceStatusGroup[] => {
81
74
  const deviceStatus = props.deviceStatuses
82
75
  .find((deviceStatus: FSDeviceStatus) => deviceStatus.modelStatusId === modelStatus.id);
@@ -96,7 +89,6 @@ export default defineComponent({
96
89
 
97
90
  return {
98
91
  ColorEnum,
99
- height,
100
92
  tab,
101
93
  deviceStatus
102
94
  };
@@ -1,6 +1,5 @@
1
1
  <template>
2
2
  <v-menu
3
- v-if="$props.deviceAlert"
4
3
  :closeOnContentClick="false"
5
4
  v-model="menu"
6
5
  >
@@ -19,71 +18,29 @@
19
18
  </FSColorIcon>
20
19
  </FSBadge>
21
20
  </template>
22
- <FSCard
23
- :elevation="true"
24
- :border="false"
25
- >
26
- <FSCol
27
- align="center-center"
28
- padding="6px 24px"
29
- >
30
- <FSCol
31
- align="center-center"
32
- gap="12px"
33
- >
34
- <FSChip
35
- :color="criticityColor"
36
- :prependIcon="statusIcon"
37
- :label="$props.deviceAlert.label"
38
- />
39
- <FSRow
40
- width="hug"
41
- >
42
- <FSText>
43
- {{ statusLabel }}
44
- </FSText>
45
- </FSRow>
46
- </FSCol>
47
- <FSRow
48
- v-if="deviceTimestamp"
49
- width="hug"
50
- >
51
- <FSSpan
52
- font="text-overline"
53
- >
54
- {{ deviceTimestamp }}
55
- </FSSpan>
56
- </FSRow>
57
- </FSCol>
58
- </FSCard>
21
+ <FSWorstAlertCard
22
+ :deviceAlert="deviceAlert"
23
+ />
59
24
  </v-menu>
60
25
  </template>
61
26
 
62
27
  <script lang="ts">
63
28
  import { computed, defineComponent, PropType, ref } from "vue";
64
29
 
65
- import { useTranslations as useTranslationsProvider } from "@dative-gpi/bones-ui/composables";
66
30
  import { AlertStatus, Criticity } from "@dative-gpi/foundation-shared-domain/models";
67
- import { useTimeZone } from "@dative-gpi/foundation-shared-services/composables";
68
31
  import { FSDeviceAlert } from "@dative-gpi/foundation-shared-components/models";
69
32
  import { ColorEnum } from "@dative-gpi/foundation-shared-components/models";
70
33
 
34
+ import FSWorstAlertCard from "./FSWorstAlertCard.vue";
71
35
  import FSColorIcon from "../FSColorIcon.vue";
72
36
  import FSBadge from "../FSBadge.vue";
73
- import FSCard from "../FSCard.vue";
74
- import FSChip from "../FSChip.vue";
75
- import FSText from "../FSText.vue";
76
- import FSSpan from "../FSSpan.vue";
77
37
 
78
38
  export default defineComponent({
79
39
  name: "FSWorstAlert",
80
40
  components: {
41
+ FSWorstAlertCard,
81
42
  FSColorIcon,
82
- FSBadge,
83
- FSCard,
84
- FSChip,
85
- FSText,
86
- FSSpan
43
+ FSBadge
87
44
  },
88
45
  props: {
89
46
  deviceAlert: {
@@ -97,9 +54,6 @@ export default defineComponent({
97
54
  }
98
55
  },
99
56
  setup(props) {
100
- const { epochToLongTimeFormat } = useTimeZone();
101
- const { $tr } = useTranslationsProvider();
102
-
103
57
  const menu = ref(false);
104
58
 
105
59
  const criticityColor = computed(() => {
@@ -123,19 +77,6 @@ export default defineComponent({
123
77
  }
124
78
  });
125
79
 
126
- const statusLabel = computed(() => {
127
- switch (props.deviceAlert?.status) {
128
- case AlertStatus.Pending: return $tr("ui.alert-status.pending", "Pending");
129
- case AlertStatus.Untriggered: return $tr("ui.alert-status.untriggered", "Untriggered");
130
- case AlertStatus.Unresolved: return $tr("ui.alert-status.unresolved", "Unresolved");
131
- case AlertStatus.Resolved: return $tr("ui.alert-status.resolved", "Resolved");
132
- case AlertStatus.Expired: return $tr("ui.alert-status.expired", "Expired");
133
- case AlertStatus.Triggered: return $tr("ui.alert-status.triggered", "Triggered");
134
- case AlertStatus.Abandoned: return $tr("ui.alert-status.abandoned", "Abandoned");
135
- default: return "";
136
- }
137
- });
138
-
139
80
  const badgeLabel = computed((): string | null => {
140
81
  if (props.deviceAlerts < 1) {
141
82
  return null;
@@ -146,17 +87,8 @@ export default defineComponent({
146
87
  return (props.deviceAlerts + 1).toString();
147
88
  });
148
89
 
149
- const deviceTimestamp = computed((): string => {
150
- if (props.deviceAlert.sourceTimestamp) {
151
- return epochToLongTimeFormat(props.deviceAlert.sourceTimestamp);
152
- }
153
- return "";
154
- });
155
-
156
90
  return {
157
- deviceTimestamp,
158
91
  criticityColor,
159
- statusLabel,
160
92
  statusIcon,
161
93
  badgeLabel,
162
94
  menu
@@ -0,0 +1,126 @@
1
+ <template>
2
+ <FSCard
3
+ :elevation="true"
4
+ :border="false"
5
+ >
6
+ <FSCol
7
+ align="center-center"
8
+ padding="6px 24px"
9
+ >
10
+ <FSCol
11
+ align="center-center"
12
+ gap="12px"
13
+ >
14
+ <FSChip
15
+ :label="$props.deviceAlert.label"
16
+ :prependIcon="statusIcon"
17
+ :color="criticityColor"
18
+ />
19
+ <FSRow
20
+ width="hug"
21
+ >
22
+ <FSText>
23
+ {{ statusLabel }}
24
+ </FSText>
25
+ </FSRow>
26
+ </FSCol>
27
+ <FSRow
28
+ v-if="deviceTimestamp"
29
+ width="hug"
30
+ >
31
+ <FSSpan
32
+ font="text-overline"
33
+ >
34
+ {{ deviceTimestamp }}
35
+ </FSSpan>
36
+ </FSRow>
37
+ </FSCol>
38
+ </FSCard>
39
+ </template>
40
+
41
+ <script lang="ts">
42
+ import { computed, defineComponent, PropType, ref } from "vue";
43
+
44
+ import { useTranslations as useTranslationsProvider } from "@dative-gpi/bones-ui/composables";
45
+ import { AlertStatus, Criticity } from "@dative-gpi/foundation-shared-domain/models";
46
+ import { useTimeZone } from "@dative-gpi/foundation-shared-services/composables";
47
+ import { FSDeviceAlert } from "@dative-gpi/foundation-shared-components/models";
48
+ import { ColorEnum } from "@dative-gpi/foundation-shared-components/models";
49
+
50
+ import FSCard from "../FSCard.vue";
51
+ import FSChip from "../FSChip.vue";
52
+ import FSText from "../FSText.vue";
53
+ import FSSpan from "../FSSpan.vue";
54
+ import FSCol from "../FSCol.vue";
55
+ import FSRow from "../FSRow.vue";
56
+
57
+ export default defineComponent({
58
+ name: "FSWorstAlertCard",
59
+ components: {
60
+ FSCard,
61
+ FSChip,
62
+ FSText,
63
+ FSSpan,
64
+ FSCol,
65
+ FSRow
66
+ },
67
+ props: {
68
+ deviceAlert: {
69
+ type: Object as PropType<FSDeviceAlert>,
70
+ required: true
71
+ }
72
+ },
73
+ setup(props) {
74
+ const { epochToLongTimeFormat } = useTimeZone();
75
+ const { $tr } = useTranslationsProvider();
76
+
77
+ const criticityColor = computed(() => {
78
+ switch (props.deviceAlert?.criticity) {
79
+ case Criticity.Error: return ColorEnum.Error;
80
+ case Criticity.Warning: return ColorEnum.Warning;
81
+ default: return ColorEnum.Primary;
82
+ }
83
+ });
84
+
85
+ const statusIcon = computed(() => {
86
+ switch (props.deviceAlert?.status) {
87
+ case AlertStatus.Pending: return "mdi-timer-outline";
88
+ case AlertStatus.Untriggered: return "mdi-timer-off-outline";
89
+ case AlertStatus.Unresolved: return "mdi-alert-circle-outline";
90
+ case AlertStatus.Resolved: return "mdi-check-circle-outline";
91
+ case AlertStatus.Expired: return "mdi-clock-outline";
92
+ case AlertStatus.Triggered: return "mdi-alert-circle-outline";
93
+ case AlertStatus.Abandoned: return "mdi-cancel"
94
+ default: return "";
95
+ }
96
+ });
97
+
98
+ const statusLabel = computed(() => {
99
+ switch (props.deviceAlert?.status) {
100
+ case AlertStatus.Pending: return $tr("ui.alert-status.pending", "Pending");
101
+ case AlertStatus.Untriggered: return $tr("ui.alert-status.untriggered", "Untriggered");
102
+ case AlertStatus.Unresolved: return $tr("ui.alert-status.unresolved", "Unresolved");
103
+ case AlertStatus.Resolved: return $tr("ui.alert-status.resolved", "Resolved");
104
+ case AlertStatus.Expired: return $tr("ui.alert-status.expired", "Expired");
105
+ case AlertStatus.Triggered: return $tr("ui.alert-status.triggered", "Triggered");
106
+ case AlertStatus.Abandoned: return $tr("ui.alert-status.abandoned", "Abandoned");
107
+ default: return "";
108
+ }
109
+ });
110
+
111
+ const deviceTimestamp = computed((): string => {
112
+ if (props.deviceAlert.sourceTimestamp) {
113
+ return epochToLongTimeFormat(props.deviceAlert.sourceTimestamp);
114
+ }
115
+ return "";
116
+ });
117
+
118
+ return {
119
+ deviceTimestamp,
120
+ criticityColor,
121
+ statusLabel,
122
+ statusIcon
123
+ };
124
+ }
125
+ });
126
+ </script>
@@ -157,12 +157,13 @@ export default defineComponent({
157
157
  },
158
158
  emits: ["update:modelValue", "update:opacity"],
159
159
  setup(props, { emit }) {
160
+ const { getColors } = useColors();
160
161
  const { slots } = useSlots();
161
162
 
162
163
  delete slots.description;
163
164
 
164
- const lights = useColors().getColors(ColorEnum.Light);
165
- const darks = useColors().getColors(ColorEnum.Dark);
165
+ const lights = getColors(ColorEnum.Light);
166
+ const darks = getColors(ColorEnum.Dark);
166
167
 
167
168
  const menu = ref(false);
168
169
  const innerColor = ref(props.modelValue.toString().substring(0, 7));
@@ -1,7 +1,10 @@
1
1
  <template>
2
2
  <FSCol>
3
3
  <slot v-if="!$props.hideHeader" name="label">
4
- <FSRow :wrap="false">
4
+ <FSRow
5
+ height="16px"
6
+ :wrap="false"
7
+ >
5
8
  <FSSpan
6
9
  v-if="$props.label"
7
10
  class="fs-text-field-label"
@@ -1,14 +1,14 @@
1
- import { computed, inject, ref } from "vue";
1
+ import { Ref, computed, inject, ref } from "vue";
2
2
 
3
3
  export const useRules = () => {
4
- const innerValidateOn = inject<"submit" | "blur" | "input">("validateOn", 'input');
5
- const submitted = inject<boolean>("submitted", false);
4
+ const innerValidateOn = inject<Ref<"submit" | "blur" | "input">>("validateOn", ref('input'));
5
+ const submitted = inject<Ref<boolean>>("submitted", ref(false));
6
6
 
7
7
  const blurred = ref(false);
8
8
 
9
9
  const validateOn = computed((): string => {
10
- switch (innerValidateOn) {
11
- case "submit": return submitted ? "input" : "submit";
10
+ switch (innerValidateOn.value) {
11
+ case "submit": return submitted.value ? "input" : "submit";
12
12
  case "blur": return blurred.value ? "input" : "blur";
13
13
  case "input": return "input";
14
14
  }
@@ -20,7 +20,7 @@ export const useRules = () => {
20
20
  }
21
21
  switch (validateOn.value) {
22
22
  case "submit":
23
- if (!submitted) {
23
+ if (!submitted.value) {
24
24
  return [];
25
25
  }
26
26
  break;
package/models/rules.ts CHANGED
@@ -8,6 +8,7 @@ const { $tr } = useTranslationsProvider();
8
8
 
9
9
  export const TextRules = {
10
10
  required: (message: string) => (value: string) => !!value || (message ?? $tr("ui.rules.required", "Required")),
11
+ copy: (original: string, message: string) => (value: string) => value === original || (message ?? $tr("ui.rules.copy", "Different from original")),
11
12
  min: (min: number, message: string) => (value: string) => value.length >= min || (message ?? $tr("ui.rules.text-min", "Must be at least {0} characters", min.toString())),
12
13
  max: (max: number, message: string) => (value: string) => value.length <= max || (message ?? $tr("ui.rules.text-max", "Must be at most {0} characters", max.toString())),
13
14
  email: (message: string) => (value: string) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value) || (message ?? $tr("ui.rules.text-email", "Must be a valid email")),
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.24",
4
+ "version": "0.0.26",
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.24",
14
- "@dative-gpi/foundation-shared-services": "0.0.24",
13
+ "@dative-gpi/foundation-shared-domain": "0.0.26",
14
+ "@dative-gpi/foundation-shared-services": "0.0.26",
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": "4b773f42cd8d8a58a71fd995b3a9f40735d52e7a"
35
+ "gitHead": "58a49a5422156548728d405e3c289ba4e80cbe39"
36
36
  }
@@ -0,0 +1,38 @@
1
+ .fs-accordion-panel > .v-expansion-panel-title {
2
+ border-radius: var(--fs-accordion-panel-border-radius) !important;
3
+ transition: all 0.28s cubic-bezier(0.4, 0, 0.2, 1);
4
+ min-height: 0 !important;
5
+ cursor: pointer;
6
+ padding: 12px;
7
+
8
+ background-color: var(--fs-accordion-panel-background-color) !important;
9
+ color: var(--fs-accordion-panel-color) !important;
10
+
11
+ &:hover,
12
+ &--active {
13
+ background-color: var(--fs-accordion-panel-hover-background-color) !important;
14
+ color: var(--fs-accordion-panel-hover-color) !important;
15
+ min-height: 0 !important;
16
+
17
+ & .fs-accordion-panel-title {
18
+ @extend .text-button
19
+ }
20
+ }
21
+ }
22
+
23
+ .fs-accordion-panel > .v-expansion-panel-text {
24
+ border-radius: var(--fs-accordion-panel-border-radius) !important;
25
+ transition: all 0.28s cubic-bezier(0.4, 0, 0.2, 1);
26
+ padding: 12px;
27
+
28
+ background-color: var(--fs-accordion-panel-background-color) !important;
29
+ color: var(--fs-accordion-panel-color) !important;
30
+
31
+ & > .v-expansion-panel-text__wrapper {
32
+ padding: 0;
33
+ }
34
+ }
35
+
36
+ .v-expansion-panel:not(:first-child)::after {
37
+ border-top: var(--fs-accordion-panel-border-size) solid var(--fs-accordion-panel-border-color) !important;
38
+ }
@@ -30,6 +30,6 @@ a:has(.fs-clickable) {
30
30
  padding: 0 !important;
31
31
  }
32
32
 
33
- .fs-clickable-anchor-full-width {
33
+ .fs-clickable-wrapper-full-width {
34
34
  width: 100%;
35
35
  }
@@ -1,3 +1,4 @@
1
+ @import "fs_accordion_panel.scss";
1
2
  @import "fs_autocomplete_field.scss";
2
3
  @import "fs_breadcrumbs.scss";
3
4
  @import "fs_button.scss";
@@ -11,7 +11,7 @@
11
11
  // Applies to all inputs
12
12
  .v-input {
13
13
  padding: 0px !important;
14
- min-width: 240px;
14
+ min-width: 200px;
15
15
  width: 100%;
16
16
 
17
17
  & .v-input__prepend {