@dative-gpi/foundation-shared-components 1.0.167 → 1.0.168

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,107 @@
1
+ <template>
2
+ <template
3
+ v-if="$props.loading"
4
+ >
5
+ <FSCol>
6
+ <FSLoader
7
+ v-if="$props.loading"
8
+ width="100%"
9
+ :height="['40px', '36px']"
10
+ />
11
+ </FSCol>
12
+ </template>
13
+ <template
14
+ v-else
15
+ >
16
+ <v-treeview
17
+ :itemTitle="$props.itemTitle"
18
+ :itemValue="$props.itemValue"
19
+ :items="treeItems"
20
+ >
21
+ <template
22
+ v-for="(_, name) in $slots"
23
+ v-slot:[name]="slotData"
24
+ >
25
+ <slot
26
+ :name="name"
27
+ v-bind="slotData"
28
+ />
29
+ </template>
30
+ </v-treeview>
31
+ </template>
32
+ </template>
33
+
34
+ <script lang="ts">
35
+ import { computed, defineComponent, type PropType } from "vue";
36
+ import { VTreeview } from "vuetify/labs/VTreeview";
37
+
38
+
39
+ import FSLoader from "./FSLoader.vue";
40
+ import FSCol from "./FSCol.vue";
41
+
42
+ export default defineComponent({
43
+ name: "FSTreeView",
44
+ components: {
45
+ VTreeview,
46
+ FSLoader,
47
+ FSCol,
48
+ },
49
+ props: {
50
+ items: {
51
+ type: Array as PropType<any[]>,
52
+ required: true
53
+ },
54
+ itemValue: {
55
+ type: String,
56
+ required: false,
57
+ default: "id"
58
+ },
59
+ itemTitle: {
60
+ type: String,
61
+ required: false,
62
+ default: "label"
63
+ },
64
+ itemParent: {
65
+ type: String,
66
+ required: false,
67
+ default: "parentId"
68
+ },
69
+ exclude: {
70
+ type: Array as PropType<string[]>,
71
+ required: false,
72
+ default: () => []
73
+ },
74
+ loading: {
75
+ type: Boolean,
76
+ required: false,
77
+ default: false
78
+ }
79
+ },
80
+ setup(props) {
81
+ const treeItems = computed((): any[] => {
82
+ const filter = ((parentId: string | null) => {
83
+ return props.items.filter((item: any) => {
84
+ if (props.exclude.includes(item[props.itemValue])) {
85
+ return false;
86
+ }
87
+ return item[props.itemParent] == parentId;
88
+ });
89
+ });
90
+ const process = ((item: any): any => {
91
+ if (props.items.some((child: any) => child[props.itemParent] === item[props.itemValue])) {
92
+ return {
93
+ ...item,
94
+ children: filter(item[props.itemValue]).map(process)
95
+ };
96
+ }
97
+ return item;
98
+ });
99
+ return filter(null).map(process);
100
+ });
101
+
102
+ return {
103
+ treeItems
104
+ };
105
+ }
106
+ });
107
+ </script>
@@ -0,0 +1,23 @@
1
+ <template>
2
+ <v-carousel
3
+ v-bind="$attrs"
4
+ >
5
+ <template
6
+ v-for="(_, name) in $slots"
7
+ v-slot:[name]="slotData"
8
+ >
9
+ <slot
10
+ :name="name"
11
+ v-bind="slotData"
12
+ />
13
+ </template>
14
+ </v-carousel>
15
+ </template>
16
+
17
+ <script lang="ts">
18
+ import { defineComponent } from "vue";
19
+
20
+ export default defineComponent({
21
+ name: "FSCarousel"
22
+ });
23
+ </script>
@@ -0,0 +1,14 @@
1
+ <template>
2
+ <v-carousel-item
3
+ v-bind="$attrs"
4
+ >
5
+ <slot/>
6
+ </v-carousel-item>
7
+ </template>
8
+
9
+ <script lang="ts">
10
+ import { defineComponent } from "vue";
11
+ export default defineComponent({
12
+ name: "FSCarouselItem"
13
+ });
14
+ </script>
@@ -0,0 +1,187 @@
1
+ <template>
2
+ <FSCol>
3
+ <FSMap
4
+ :lockZoomOnFlyTo="true"
5
+ v-model:center="center"
6
+ :enableScrollWheelZoom="true"
7
+ :showMyLocation="true"
8
+ :zoom="5"
9
+ v-model:currentLayer="mapLayer"
10
+ @click:latlng="(latlng: any) => onNewLatLng(latlng.lat, latlng.lng, false)"
11
+ v-bind="$attrs"
12
+ >
13
+ <FSMapMarker
14
+ v-if="actualLatitude && actualLongitude"
15
+ :label="$props.label"
16
+ :icon="$props.icon"
17
+ :latlng="{ lat: actualLatitude, lng: actualLongitude }"
18
+ :selected="true"
19
+ />
20
+ </FSMap>
21
+ <FSCol>
22
+ <FSAutoCompleteAddress
23
+ :maxWidth="null"
24
+ :modelValue="$props.modelValue"
25
+ @update:modelValue="$emit('update:modelValue', $event)"
26
+ />
27
+ <FSRow>
28
+ <FSNumberField
29
+ :label="$tr('ui.location.latitude', 'Latitude')"
30
+ :modelValue="actualLatitude"
31
+ :clearable="false"
32
+ :rules="[NumberRules.max(90), NumberRules.min(-90), NumberRules.required()]"
33
+ @update:modelValue="onNewLatLng($event, actualLongitude ?? 0, true)"
34
+ />
35
+ <FSNumberField
36
+ :label="$tr('ui.location.longitude', 'Longitude')"
37
+ :modelValue="actualLongitude"
38
+ :clearable="false"
39
+ :rules="[NumberRules.max(180), NumberRules.min(-180), NumberRules.required()]"
40
+ @update:modelValue="onNewLatLng(actualLatitude ?? 0, $event, true)"
41
+ />
42
+ </FSRow>
43
+ </FSCol>
44
+ </FSCol>
45
+ </template>
46
+
47
+ <script lang="ts">
48
+ import { computed, defineComponent, ref, watch, type PropType } from "vue";
49
+
50
+ import type { Address } from "@dative-gpi/foundation-shared-domain";
51
+ import { useAddress } from "@dative-gpi/foundation-shared-components/composables";
52
+ import { MapLayers, NumberRules } from '@dative-gpi/foundation-shared-components/models';
53
+
54
+ import FSAutoCompleteAddress from '@dative-gpi/foundation-shared-components/components/autocompletes/FSAutoCompleteAddress.vue';
55
+ import FSNumberField from "@dative-gpi/foundation-shared-components/components/fields/FSNumberField.vue"
56
+ import FSMapMarker from '@dative-gpi/foundation-shared-components/components/map/FSMapMarker.vue';
57
+ import FSMap from "@dative-gpi/foundation-shared-components/components/map/FSMap.vue";
58
+ import FSRow from '@dative-gpi/foundation-shared-components/components/FSRow.vue';
59
+ import FSCol from '@dative-gpi/foundation-shared-components/components/FSCol.vue';
60
+
61
+
62
+ export function debounceAsync<T, U extends any[]>(
63
+ callback: (...args: U) => Promise<T>,
64
+ wait: number,
65
+ ): (...args: U) => Promise<T> {
66
+ let timeoutId: number | null = null;
67
+ let rejectPromise: (((reason?: any) => void) | null) = null;
68
+
69
+ return (...args: U) => {
70
+ if (timeoutId) {
71
+ clearTimeout(timeoutId);
72
+ timeoutId = null;
73
+ }
74
+ if (rejectPromise) {
75
+ rejectPromise("debounced");
76
+ rejectPromise = null;
77
+ }
78
+
79
+ return new Promise<T>((resolve) => {
80
+ const timeoutPromise = new Promise<void>((resolve, reject) => {
81
+ timeoutId = setTimeout(resolve, wait);
82
+ rejectPromise = reject;
83
+ });
84
+ timeoutPromise.then(async () => {
85
+ resolve(await callback(...args));
86
+ });
87
+ });
88
+ };
89
+ }
90
+
91
+ export default defineComponent({
92
+ name: "FSMapAddressField",
93
+ components: {
94
+ FSAutoCompleteAddress,
95
+ FSNumberField,
96
+ FSMapMarker,
97
+ FSMap,
98
+ FSRow,
99
+ FSCol
100
+ },
101
+ emits: ["update:modelValue"],
102
+ props: {
103
+ label: {
104
+ type: String,
105
+ required: true,
106
+ },
107
+ icon: {
108
+ type: String,
109
+ required: true,
110
+ },
111
+ modelValue: {
112
+ type: Object as PropType<Address | null>,
113
+ required: false,
114
+ }
115
+ },
116
+ setup(props, { emit }) {
117
+ const { reverseSearch } = useAddress();
118
+
119
+ const loading = ref(false);
120
+ const actualLatitude = ref<number | null>(null);
121
+ const actualLongitude = ref<number | null>(null);
122
+ const mapLayer = ref(MapLayers.Map);
123
+
124
+ const center = computed(() => {
125
+ return props.modelValue ? [props.modelValue.latitude, props.modelValue.longitude] : null;
126
+ });
127
+
128
+ const reverseSearchDebounced = debounceAsync(reverseSearch, 500);
129
+
130
+ const onNewLatLng = async (lat: number|string, lng: number|string, debounced: boolean) => {
131
+ if(typeof lat === 'string') {
132
+ lat = parseFloat(lat);
133
+ if(isNaN(lat)) {
134
+ return;
135
+ }
136
+ }
137
+
138
+ if(typeof lng === 'string') {
139
+ lng = parseFloat(lng);
140
+ if(isNaN(lng)) {
141
+ return;
142
+ }
143
+ }
144
+
145
+ actualLatitude.value = lat;
146
+ actualLongitude.value = lng;
147
+
148
+ let fullAddress;
149
+ loading.value = true;
150
+ if(debounced) {
151
+ try {
152
+ fullAddress = await reverseSearchDebounced(lat, lng);
153
+ } catch {
154
+ return;
155
+ }
156
+ } else {
157
+ fullAddress = await reverseSearch(lat, lng);
158
+ }
159
+
160
+ emit("update:modelValue", {
161
+ ...fullAddress,
162
+ latitude: actualLatitude.value,
163
+ longitude: actualLongitude.value,
164
+ });
165
+ loading.value = false;
166
+ }
167
+
168
+ watch(() => props.modelValue, (newValue) => {
169
+ if(newValue) {
170
+ actualLatitude.value = newValue.latitude;
171
+ actualLongitude.value = newValue.longitude;
172
+ }
173
+ }, { immediate: true });
174
+
175
+ return {
176
+ center,
177
+ mapLayer,
178
+ NumberRules,
179
+ actualLatitude,
180
+ actualLongitude,
181
+ onNewLatLng
182
+ };
183
+ }
184
+ });
185
+
186
+
187
+ </script>
@@ -59,7 +59,7 @@
59
59
  <FSFadeOut
60
60
  :maxHeight="maxHeight"
61
61
  >
62
- <v-treeview
62
+ <FSTreeView
63
63
  :itemTitle="$props.itemTitle"
64
64
  :itemValue="$props.itemValue"
65
65
  :items="treeItems"
@@ -123,7 +123,7 @@
123
123
  <template
124
124
  #title
125
125
  />
126
- </v-treeview>
126
+ </FSTreeView>
127
127
  </FSFadeOut>
128
128
  </template>
129
129
  </FSDialogMenu>
@@ -168,7 +168,7 @@
168
168
  </template>
169
169
  </FSTextField>
170
170
  </template>
171
- <v-treeview
171
+ <FSTreeView
172
172
  :itemTitle="$props.itemTitle"
173
173
  :itemValue="$props.itemValue"
174
174
  :items="treeItems"
@@ -232,7 +232,7 @@
232
232
  <template
233
233
  #title
234
234
  />
235
- </v-treeview>
235
+ </FSTreeView>
236
236
  </FSMenu>
237
237
  </template>
238
238
  </FSCol>
@@ -241,7 +241,6 @@
241
241
 
242
242
  <script lang="ts">
243
243
  import { computed, defineComponent, type PropType, ref, type StyleValue } from "vue";
244
- import { VTreeview } from "vuetify/labs/VTreeview";
245
244
 
246
245
  import { useBreakpoints, useColors, useRules, useSlots } from "@dative-gpi/foundation-shared-components/composables";
247
246
  import { ColorEnum } from "@dative-gpi/foundation-shared-components/models";
@@ -249,6 +248,7 @@ import { ColorEnum } from "@dative-gpi/foundation-shared-components/models";
249
248
  import FSDialogMenu from "../FSDialogMenu.vue";
250
249
  import FSTextField from "./FSTextField.vue";
251
250
  import FSCheckbox from "../FSCheckbox.vue";
251
+ import FSTreeView from "../FSTreeView.vue";
252
252
  import FSFadeOut from "../FSFadeOut.vue";
253
253
  import FSLoader from "../FSLoader.vue";
254
254
  import FSRadio from "../FSRadio.vue";
@@ -259,7 +259,7 @@ import FSCol from "../FSCol.vue";
259
259
  export default defineComponent({
260
260
  name: "FSTreeViewField",
261
261
  components: {
262
- VTreeview,
262
+ FSTreeView,
263
263
  FSDialogMenu,
264
264
  FSTextField,
265
265
  FSCheckbox,
@@ -5,7 +5,8 @@
5
5
  <FSColor
6
6
  height="24px"
7
7
  :color="$props.color"
8
- :border="false"
8
+ :border="$props.border"
9
+ :variant="$props.variant"
9
10
  >
10
11
  <FSRow
11
12
  align="center-center"
@@ -52,6 +53,16 @@ export default defineComponent({
52
53
  type: String as PropType<ColorBase>,
53
54
  required: false,
54
55
  default: () => ColorEnum.Primary
56
+ },
57
+ border: {
58
+ type: Boolean,
59
+ required: false,
60
+ default: false
61
+ },
62
+ variant: {
63
+ type: String as PropType<"standard" | "full">,
64
+ required: false,
65
+ default: "standard"
55
66
  }
56
67
  },
57
68
  components: {
@@ -0,0 +1,52 @@
1
+ <template>
2
+ <FSSimpleTileUI
3
+ :bottomColor="$props.bottomColor"
4
+ v-bind="$attrs"
5
+ >
6
+ <template
7
+ #append-info
8
+ >
9
+ <FSEntityCountBadge
10
+ :label="$tr('ui.common.subgroupings', 'Categories')"
11
+ :count="$props.subgroupingCount ?? 0"
12
+ :color="ColorEnum.Primary"
13
+ />
14
+ </template>
15
+ </FSSimpleTileUI>
16
+ </template>
17
+
18
+ <script lang="ts">
19
+ import { defineComponent, type PropType } from "vue";
20
+
21
+
22
+ import { ColorEnum, type ColorBase } from "@dative-gpi/foundation-shared-components/models";
23
+
24
+ import FSEntityCountBadge from "./FSEntityCountBadge.vue";
25
+ import FSSimpleTileUI from './FSSimpleTileUI.vue';
26
+
27
+ export default defineComponent({
28
+ name: "FSGroupingTileUI",
29
+ components: {
30
+ FSSimpleTileUI,
31
+ FSEntityCountBadge
32
+ },
33
+ props: {
34
+ subgroupingCount: {
35
+ type: Number,
36
+ required: false,
37
+ default: null
38
+ },
39
+ bottomColor: {
40
+ type: [Array, String] as PropType<ColorBase | ColorBase[] | null>,
41
+ required: false,
42
+ default: null
43
+ },
44
+
45
+ },
46
+ setup() {
47
+ return {
48
+ ColorEnum,
49
+ };
50
+ }
51
+ });
52
+ </script>
@@ -128,7 +128,7 @@ export default defineComponent({
128
128
  default: ColorEnum.Primary
129
129
  },
130
130
  bottomColor: {
131
- type: [Array, String] as PropType<ColorBase | ColorBase[]>,
131
+ type: [Array, String] as PropType<ColorBase | ColorBase[] | null>,
132
132
  required: false,
133
133
  default: ColorEnum.Light
134
134
  },
@@ -147,7 +147,7 @@ export default defineComponent({
147
147
  const { isMobileSized } = useBreakpoints();
148
148
 
149
149
  const iconBackgroundColor = computed((): ColorBase | ColorBase[] => {
150
- return props.iconBackgroundColor ? props.bottomColor : ColorEnum.Background;
150
+ return props.iconBackgroundColor ?? ColorEnum.Background;
151
151
  });
152
152
 
153
153
  const imageSize = computed((): number => {
@@ -3,7 +3,6 @@ export * from "./useAutocomplete";
3
3
  export * from "./useBreakpoints";
4
4
  export * from "./useColors";
5
5
  export * from "./useDebounce";
6
- export * from "./useMagicFieldProvider";
7
6
  export * from "./useMapLayers";
8
7
  export * from "./useRules";
9
8
  export * from "./useSlots";
package/models/index.ts CHANGED
@@ -8,7 +8,6 @@ export * from "./errors";
8
8
  export * from "./grids";
9
9
  export * from "./images";
10
10
  export * from "./map";
11
- export * from "./magicFields";
12
11
  export * from "./modelStatuses";
13
12
  export * from "./rules";
14
13
  export * from "./tables";
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.167",
4
+ "version": "1.0.168",
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.167",
14
- "@dative-gpi/foundation-shared-services": "1.0.167"
13
+ "@dative-gpi/foundation-shared-domain": "1.0.168",
14
+ "@dative-gpi/foundation-shared-services": "1.0.168"
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": "a4466335234a8b4151405d01a1c21801b1f2563d"
38
+ "gitHead": "979a5f1fe9ac68441c9fafb61eab835039852c69"
39
39
  }
@@ -178,6 +178,7 @@ export const plotPerLabel = (plotper: PlotPer | number): string => {
178
178
  case PlotPer.Group: return $tr("ui.common.group", "Group");
179
179
  case PlotPer.Location: return $tr("ui.common.location", "Location");
180
180
  case PlotPer.Device: return $tr("ui.common.device", "Device");
181
+ case PlotPer.Grouping: return $tr("ui.plot-per.grouping", "Personalized");
181
182
  default: return $tr("ui.common.none", "None");
182
183
  }
183
184
  };
@@ -1,171 +0,0 @@
1
- <template>
2
- <FSRow
3
- class="fs-magic-config-field"
4
- >
5
- <component
6
- v-if="$props.type"
7
- class="fs-magic-config-field-value"
8
- :is="get($props.type)"
9
- :label="$tr('ui.common.value', 'Value')"
10
- :disabled="$props.disabled"
11
- :required="true"
12
- :rules="rules"
13
- :modelValue="valueToInput"
14
- @update:modelValue="inputToValue"
15
- />
16
- <FSRow
17
- gap="24px"
18
- >
19
- <FSTranslateField
20
- :label="$tr('entity.common.label', 'Label')"
21
- :disabled="$props.disabled"
22
- :modelValue="$props.labelDefault"
23
- :translations="$props.translations"
24
- @update:modelValue="$emit('update:labelDefault', $event)"
25
- @update:translations="$emit('update:translations', $event)"
26
- />
27
- <FSRow
28
- class="fs-magic-config-field-actions"
29
- width="hug"
30
- :wrap="false"
31
- >
32
- <FSButtonRemoveIcon
33
- @click="$emit('click:remove')"
34
- />
35
- <FSButtonAddIcon
36
- @click="$emit('click:add')"
37
- />
38
- </FSRow>
39
- </FSRow>
40
- </FSRow>
41
- </template>
42
-
43
- <script lang="ts">
44
- import { computed, defineComponent, type PropType } from "vue";
45
-
46
- import { DateRules, IconRules, NumberRules, TextRules, TimeRules, TimeStepRules, AutocompleteRules } from "../../models";
47
- import { useMagicFieldProvider } from "../../composables";
48
- import { MagicFieldType } from "../../models/magicFields";
49
-
50
- import FSButtonRemoveIcon from "../buttons/FSButtonRemoveIcon.vue";
51
- import FSButtonAddIcon from "../buttons/FSButtonAddIcon.vue";
52
- import FSTranslateField from "./FSTranslateField.vue";
53
- import FSRow from "../FSRow.vue";
54
-
55
- export default defineComponent({
56
- name: "FSMagicConfigField",
57
- components: {
58
- FSButtonRemoveIcon,
59
- FSTranslateField,
60
- FSButtonAddIcon,
61
- FSRow
62
- },
63
- props: {
64
- type: {
65
- type: Number as PropType<MagicFieldType>,
66
- required: false,
67
- default: MagicFieldType.TextField
68
- },
69
- labelDefault: {
70
- type: String as PropType<string | null>,
71
- required: false,
72
- default: null
73
- },
74
- modelValue: {
75
- type: String as PropType<string | null>,
76
- required: false,
77
- default: null
78
- },
79
- translations: {
80
- type: Array as PropType<{ languageCode: string; label: string }[]>,
81
- required: false,
82
- default: () => []
83
- },
84
- disabled: {
85
- type: Boolean,
86
- required: false,
87
- default: false
88
- }
89
- },
90
- emits: ["click:remove", "click:add", "update:modelValue", "update:labelDefault", "update:translations"],
91
- setup(props, { emit }) {
92
- const { get } = useMagicFieldProvider();
93
-
94
- const rules = computed((): Function[] => {
95
- switch (props.type) {
96
- case MagicFieldType.NumberField:
97
- return [NumberRules.required()];
98
- case MagicFieldType.TextField:
99
- return [TextRules.required()];
100
- case MagicFieldType.DateTimeField:
101
- return [DateRules.required()];
102
- case MagicFieldType.IconField:
103
- return [IconRules.required()];
104
- case MagicFieldType.TimeField:
105
- return [TimeRules.required()];
106
- case MagicFieldType.TimeStepField:
107
- return [TimeStepRules.required()];
108
- case MagicFieldType.PlotPerField:
109
- return [AutocompleteRules.required()];
110
- }
111
- return [];
112
- });
113
-
114
- const valueToInput = computed((): any => {
115
- if (!props.modelValue) {
116
- return null;
117
- }
118
-
119
- switch (props.type) {
120
- case MagicFieldType.NumberField:
121
- case MagicFieldType.DateTimeField:
122
- case MagicFieldType.TimeField:
123
- if (isNaN(parseFloat(props.modelValue))) {
124
- return null;
125
- }
126
- return parseFloat(props.modelValue);
127
- case MagicFieldType.Switch:
128
- return props.modelValue === "true";
129
- case MagicFieldType.TimeStepField:
130
- return JSON.parse(props.modelValue);
131
- case MagicFieldType.PlotPerField:
132
- return parseInt(props.modelValue);
133
- default:
134
- return props.modelValue;
135
- }
136
- });
137
-
138
- const inputToValue = (value: any) => {
139
- if (!value) {
140
- emit("update:modelValue", null);
141
- }
142
-
143
- switch (props.type) {
144
- case MagicFieldType.NumberField:
145
- case MagicFieldType.Switch:
146
- case MagicFieldType.DateTimeField:
147
- case MagicFieldType.TimeField:
148
- emit("update:modelValue", value.toString());
149
- break;
150
- case MagicFieldType.TimeStepField:
151
- emit("update:modelValue", JSON.stringify(value));
152
- break;
153
- case MagicFieldType.PlotPerField:
154
- emit("update:modelValue", value.toString());
155
- break;
156
- default:
157
- emit("update:modelValue", value);
158
- break;
159
- }
160
- };
161
-
162
- return {
163
- MagicFieldType,
164
- valueToInput,
165
- rules,
166
- inputToValue,
167
- get
168
- };
169
- },
170
- });
171
- </script>
@@ -1,198 +0,0 @@
1
- <template>
2
- <component
3
- v-if="!$props.useOnlyAllowedValues"
4
- :is="get($props.type)"
5
- :modelValue="valueToInput"
6
- @update:modelValue="inputToValue"
7
- v-bind="$attrs"
8
- />
9
- <FSSelectField
10
- v-else
11
- itemValue="value"
12
- :items="items"
13
- :modelValue="$props.modelValue"
14
- @update:modelValue="$emit('update:modelValue', $event)"
15
- v-bind="$attrs"
16
- >
17
- <template
18
- v-if="$props.type === MagicFieldType.IconField"
19
- #selection="{ item }"
20
- >
21
- <FSRow
22
- align="center-center"
23
- :wrap="false"
24
- >
25
- <FSIcon
26
- v-if="item.raw.value"
27
- >
28
- {{ item.raw.value }}
29
- </FSIcon>
30
- <FSSpan
31
- v-if="item.raw.value !== item.raw.label"
32
- >
33
- {{ item.raw.label }}
34
- </FSSpan>
35
- </FSRow>
36
- </template>
37
- <template
38
- v-if="$props.type === MagicFieldType.IconField"
39
- #item-label="{ item }"
40
- >
41
- <FSRow
42
- align="center-center"
43
- :wrap="false"
44
- >
45
- <FSIcon
46
- v-if="item.raw.value"
47
- >
48
- {{ item.raw.value }}
49
- </FSIcon>
50
- <FSSpan
51
- v-if="item.raw.value !== item.raw.label"
52
- >
53
- {{ item.raw.label }}
54
- </FSSpan>
55
- </FSRow>
56
- </template>
57
- </FSSelectField>
58
- </template>
59
-
60
- <script lang="ts">
61
- import { computed, defineComponent, type PropType } from "vue";
62
-
63
- import { useTranslations as useTranslationsProvider } from "@dative-gpi/bones-ui/composables";
64
-
65
- import { useDateFormat } from "@dative-gpi/foundation-shared-services/composables";
66
-
67
- import { useMagicFieldProvider } from "../../composables";
68
- import { MagicFieldType } from "../../models/magicFields";
69
- import { getTimeBestString, timeStepToString } from "../../utils";
70
-
71
- import FSSelectField from "./FSSelectField.vue";
72
- import FSIcon from "../FSIcon.vue";
73
- import FSSpan from "../FSSpan.vue";
74
- import FSRow from "../FSRow.vue";
75
-
76
- export default defineComponent({
77
- name: "FSMagicField",
78
- components: {
79
- FSSelectField,
80
- FSIcon,
81
- FSSpan,
82
- FSRow
83
- },
84
- props: {
85
- type: {
86
- type: Number as PropType<MagicFieldType>,
87
- required: false,
88
- default: MagicFieldType.TextField
89
- },
90
- modelValue: {
91
- type: String as PropType<string | null>,
92
- required: false,
93
- default: null
94
- },
95
- allowedValues: {
96
- type: Array as PropType<{ value: string; label: string }[]>,
97
- required: false,
98
- default: () => []
99
- },
100
- useOnlyAllowedValues: {
101
- type: Boolean,
102
- required: false,
103
- default: false
104
- },
105
- },
106
- emits: ["update:modelValue"],
107
- setup(props, { emit }) {
108
- const { epochToShortTimeFormat } = useDateFormat();
109
- const { $tr } = useTranslationsProvider();
110
- const { get } = useMagicFieldProvider();
111
-
112
- const items = computed(() => props.allowedValues.map((av) => ({
113
- value: av.value,
114
- label: av.label || asString(av.value),
115
- })));
116
-
117
- const valueToInput = computed((): any => {
118
- if (props.modelValue == null) {
119
- return null;
120
- }
121
-
122
- switch (props.type) {
123
- case MagicFieldType.NumberField:
124
- case MagicFieldType.DateTimeField:
125
- case MagicFieldType.TimeField:
126
- if (isNaN(parseFloat(props.modelValue))) {
127
- return null;
128
- }
129
- return parseFloat(props.modelValue);
130
- case MagicFieldType.Switch:
131
- return props.modelValue === "true";
132
- case MagicFieldType.TimeStepField:
133
- return JSON.parse(props.modelValue);
134
- case MagicFieldType.PlotPerField:
135
- return parseInt(props.modelValue);
136
- default:
137
- return props.modelValue;
138
- }
139
- });
140
-
141
- const asString = (value: string): string | null => {
142
- if (value == null) {
143
- return "";
144
- }
145
-
146
- switch (props.type) {
147
- case MagicFieldType.NumberField:
148
- return value.toString();
149
- case MagicFieldType.Switch:
150
- if (value) {
151
- return $tr("magic-field.true", "True");
152
- }
153
- return $tr("magic-field.false", "False");
154
- case MagicFieldType.DateTimeField:
155
- return epochToShortTimeFormat(parseFloat(value));
156
- case MagicFieldType.TimeField:
157
- return getTimeBestString(parseFloat(value));
158
- case MagicFieldType.TimeStepField:
159
- return timeStepToString(JSON.parse(value));
160
- default:
161
- return value;
162
- }
163
- }
164
-
165
- const inputToValue = (value: any) => {
166
- if (value == null) {
167
- emit("update:modelValue", null);
168
- }
169
-
170
- switch (props.type) {
171
- case MagicFieldType.NumberField:
172
- case MagicFieldType.Switch:
173
- case MagicFieldType.DateTimeField:
174
- case MagicFieldType.TimeField:
175
- emit("update:modelValue", value.toString());
176
- break;
177
- case MagicFieldType.TimeStepField:
178
- emit("update:modelValue", JSON.stringify(value));
179
- break;
180
- case MagicFieldType.PlotPerField:
181
- emit("update:modelValue", value.toString());
182
- break;
183
- default:
184
- emit("update:modelValue", value);
185
- break;
186
- }
187
- };
188
-
189
- return {
190
- MagicFieldType,
191
- valueToInput,
192
- items,
193
- inputToValue,
194
- get
195
- };
196
- },
197
- });
198
- </script>
@@ -1,52 +0,0 @@
1
- <template>
2
- <FSAutocompleteField
3
- :label="label ?? $tr('ui.common.plot-per','Plot per')"
4
- :items="plotPerItems"
5
- :modelValue="modelValue"
6
- @update:modelValue="$emit('update:modelValue', $event)"
7
- v-bind="$attrs"
8
- />
9
- </template>
10
-
11
- <script lang="ts">
12
- import { computed, defineComponent, type PropType } from "vue";
13
-
14
- import {PlotPer} from "@dative-gpi/foundation-shared-domain/enums";
15
-
16
- import { getEnumEntries } from "@dative-gpi/foundation-shared-domain/tools";
17
- import { plotPerLabel } from "@dative-gpi/foundation-shared-components/tools";
18
-
19
- import FSAutocompleteField from "@dative-gpi/foundation-shared-components/components/fields/FSAutocompleteField.vue";
20
-
21
- export default defineComponent({
22
- components: {
23
- FSAutocompleteField
24
- },
25
- props: {
26
- modelValue: {
27
- type: Number as PropType<PlotPer>,
28
- required: false
29
- },
30
- label: {
31
- type: String,
32
- required: false
33
- }
34
- },
35
- emits: ['update:modelValue'],
36
- setup() {
37
-
38
- const plotPerItems = computed(()=>{
39
- return getEnumEntries(PlotPer).filter(f=>f.value != PlotPer.None).map((f)=>{
40
- return {
41
- id: f.value,
42
- label: plotPerLabel(f.value)
43
- }
44
- })
45
- });
46
-
47
- return {
48
- plotPerItems
49
- }
50
- }
51
- })
52
- </script>
@@ -1,24 +0,0 @@
1
- import { defineAsyncComponent } from "vue";
2
-
3
- import { MagicFieldType } from "../models/magicFields";
4
-
5
- const FIELDS = {
6
- [MagicFieldType.NumberField] : defineAsyncComponent(() => import("../components/fields/FSNumberField.vue")),
7
- [MagicFieldType.TextField] : defineAsyncComponent(() => import("../components/fields/FSTextField.vue")),
8
- [MagicFieldType.Switch] : defineAsyncComponent(() => import("../components/FSSwitch.vue")),
9
- [MagicFieldType.DateTimeField] : defineAsyncComponent(() => import("../components/fields/FSDateTimeField.vue")),
10
- [MagicFieldType.IconField] : defineAsyncComponent(() => import("../components/fields/FSIconField.vue")),
11
- [MagicFieldType.TimeField] : defineAsyncComponent(() => import("../components/fields/FSTimeField.vue")),
12
- [MagicFieldType.TimeStepField] : defineAsyncComponent(() => import("../components/fields/FSTimeStepField.vue")),
13
- [MagicFieldType.PlotPerField] : defineAsyncComponent(() => import("../components/selects/chartSelectors/FSPlotPerSelector.vue")),
14
- };
15
-
16
- export const useMagicFieldProvider = () => {
17
- const get = (code: keyof typeof FIELDS) => {
18
- return FIELDS[code];
19
- };
20
-
21
- return {
22
- get
23
- };
24
- };
@@ -1,11 +0,0 @@
1
- export enum MagicFieldType {
2
- None = 0,
3
- NumberField = 1,
4
- Switch = 2,
5
- TextField = 3,
6
- DateTimeField = 4,
7
- IconField = 5,
8
- TimeField = 6,
9
- TimeStepField = 7,
10
- PlotPerField = 8,
11
- }