@dative-gpi/foundation-core-components 0.0.96 → 0.0.98

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,195 @@
1
+ <template>
2
+ <FSSelectField
3
+ v-if="$props.customProperty.useOnlyAllowedValues"
4
+ :label="$props.customProperty.label"
5
+ :items="Object.keys($props.customProperty.allowedValues)"
6
+ :disabled="!editable"
7
+ :modelValue="$props.modelValue"
8
+ @update:modelValue="(event) => $emit('update:modelValue', event)"
9
+ >
10
+ <template
11
+ #selection="{ item }"
12
+ >
13
+ <FSSpan
14
+ v-if="customProperty.allowedValues[item.value] != null"
15
+ class="text-body-1"
16
+ >
17
+ {{ customProperty.allowedValues[item.value] }}
18
+ </FSSpan>
19
+ <FSSpan
20
+ v-else-if="[PropertyDataType.Number, PropertyDataType.String, PropertyDataType.DateTime].includes(customProperty.dataType)"
21
+ class="text-body-1"
22
+ >
23
+ {{ asSelector(item.value) }}
24
+ </FSSpan>
25
+ <FSIcon
26
+ v-else-if="[PropertyDataType.Boolean, PropertyDataType.Icon].includes(customProperty.dataType)"
27
+ >
28
+ {{ asSelector(item.value) }}
29
+ </FSIcon>
30
+ </template>
31
+ <template
32
+ #item="{ props, item }"
33
+ >
34
+ <v-list-item
35
+ v-bind="{ ...props, title: '' }"
36
+ >
37
+ <FSRow
38
+ align="center-left"
39
+ >
40
+ <FSSpan
41
+ v-if="customProperty.allowedValues[item.value] != null"
42
+ class="text-body-1"
43
+ >
44
+ {{ customProperty.allowedValues[item.value] }}
45
+ </FSSpan>
46
+ <FSSpan
47
+ v-else-if="[PropertyDataType.Number, PropertyDataType.String].includes($props.customProperty.dataType)"
48
+ class="text-body-1"
49
+ >
50
+ {{ asSelector(item.value) }}
51
+ </FSSpan>
52
+ <FSSpan
53
+ v-else-if="[PropertyDataType.DateTime].includes($props.customProperty.dataType)"
54
+ class="text-body-1"
55
+ >
56
+ {{ asSelector(item.value) }}
57
+ </FSSpan>
58
+ <FSIcon
59
+ v-else-if="[PropertyDataType.Boolean, PropertyDataType.Icon].includes($props.customProperty.dataType)"
60
+ >
61
+ {{ asSelector(item.value) }}
62
+ </FSIcon>
63
+ </FSRow>
64
+ </v-list-item>
65
+ </template>
66
+ </FSSelectField>
67
+ <template
68
+ v-else
69
+ >
70
+ <FSNumberField
71
+ v-if="$props.customProperty.dataType === PropertyDataType.Number"
72
+ :label="$props.customProperty.label"
73
+ :disabled="!editable"
74
+ :modelValue="asNumber()"
75
+ @update:modelValue="(event) => $emit('update:modelValue', event.toString())"
76
+ />
77
+ <FSSwitch
78
+ v-else-if="$props.customProperty.dataType === PropertyDataType.Boolean"
79
+ :label="$props.customProperty.label"
80
+ :editable="editable"
81
+ :modelValue="asBoolean()"
82
+ @update:modelValue="(event) => $emit('update:modelValue', event.toString())"
83
+ />
84
+ <FSTextField
85
+ v-else-if="$props.customProperty.dataType === PropertyDataType.String"
86
+ :label="$props.customProperty.label"
87
+ :disabled="!editable"
88
+ :modelValue="$props.modelValue"
89
+ @update:modelValue="(event) => $emit('update:modelValue', event)"
90
+ />
91
+ <FSDateTimeField
92
+ v-else-if="$props.customProperty.dataType === PropertyDataType.DateTime"
93
+ :label="$props.customProperty.label"
94
+ :editable="editable"
95
+ :modelValue="asNumber()"
96
+ @update:modelValue="(event) => $emit('update:modelValue', (event + getMachineOffsetMillis() - getUserOffsetMillis()).toString())"
97
+ />
98
+ <FSIconField
99
+ v-else-if="$props.customProperty.dataType === PropertyDataType.Icon"
100
+ :label="$props.customProperty.label"
101
+ :editable="editable"
102
+ :modelValue="modelValue"
103
+ @update:modelValue="(event) => $emit('update:modelValue', event.toString()) "
104
+ />
105
+ </template>
106
+ </template>
107
+
108
+ <script lang="ts">
109
+ import { PropType, defineComponent } from "vue";
110
+
111
+ import FSSwitch from "@dative-gpi/foundation-shared-components/components/FSSwitch.vue";
112
+ import FSIconField from "@dative-gpi/foundation-shared-components/components/fields/FSIconField.vue";
113
+ import FSSelectField from "@dative-gpi/foundation-shared-components/components/fields/FSSelectField.vue";
114
+ import FSNumberField from "@dative-gpi/foundation-shared-components/components/fields/FSNumberField.vue";
115
+ import FSDateTimeField from "@dative-gpi/foundation-shared-components/components/fields/FSDateTimeField.vue";
116
+
117
+ import { CustomPropertyInfos, PropertyDataType } from "../../../foundation-core-domain/models";
118
+ import { useAppTimeZone } from "@dative-gpi/foundation-shared-services/composables";
119
+
120
+
121
+ export default defineComponent({
122
+ name: "FSMetaField",
123
+ components: {
124
+ FSSwitch,
125
+ FSIconField,
126
+ FSSelectField,
127
+ FSNumberField,
128
+ FSDateTimeField
129
+ },
130
+ props: {
131
+ customProperty: {
132
+ type: Object as PropType<CustomPropertyInfos>,
133
+ required: true
134
+ },
135
+ modelValue: {
136
+ type: String,
137
+ required: true
138
+ },
139
+ editable: {
140
+ type: Boolean,
141
+ required: false,
142
+ default: true
143
+ }
144
+ },
145
+ setup(props) {
146
+ const { epochToLongTimeFormat, epochToPicker, getUserOffsetMillis, getMachineOffsetMillis } = useAppTimeZone();
147
+
148
+ const asSelector = (item: string): string => {
149
+ switch (props.customProperty.dataType) {
150
+ case PropertyDataType.Boolean: {
151
+ if (item?.toLowerCase() === "true") {
152
+ return "mdi-check-circle-outline";
153
+ }
154
+ return "mdi-close-circle-outline";
155
+ }
156
+ case PropertyDataType.DateTime: {
157
+ return epochToLongTimeFormat(parseInt(item));
158
+ }
159
+ default: {
160
+ return item;
161
+ }
162
+ }
163
+ }
164
+
165
+ const asNumber = (): number | undefined => {
166
+ if (!isNaN(parseFloat(props.modelValue))) {
167
+ return parseFloat(props.modelValue);
168
+ }
169
+ return undefined;
170
+ }
171
+
172
+ const asBoolean = (): boolean => {
173
+ return props.modelValue === "true";
174
+ }
175
+
176
+ const asDateTime = (): Date | undefined => {
177
+ let epoch: number | undefined = undefined;
178
+ if (props.modelValue != null && isFinite(parseInt(props.modelValue))) {
179
+ epoch = parseInt(props.modelValue);
180
+ }
181
+ return epochToPicker(epoch) ?? undefined;
182
+ }
183
+
184
+ return {
185
+ PropertyDataType,
186
+ getMachineOffsetMillis,
187
+ getUserOffsetMillis,
188
+ asSelector,
189
+ asDateTime,
190
+ asBoolean,
191
+ asNumber
192
+ };
193
+ }
194
+ });
195
+ </script>
@@ -0,0 +1,73 @@
1
+ <template>
2
+ <FSCol
3
+ :gap="24"
4
+ >
5
+ <FSCol
6
+ v-for="(properties, category) in categories"
7
+ :key="category"
8
+ :gap="16"
9
+ >
10
+ <FSRow>
11
+ <FSText
12
+ font="text-h3"
13
+ >
14
+ {{ category }}
15
+ </FSText>
16
+ </FSRow>
17
+ <FSMetaField
18
+ v-for="(property, index) in properties"
19
+ :customProperty="property"
20
+ :editable="editable"
21
+ :key="index"
22
+ :modelValue="modelValue[property.code]"
23
+ @update:modelValue="(event) => $emit('update:modelValue', { ...modelValue, [property.code]: event})"
24
+ />
25
+ </FSCol>
26
+ </FSCol>
27
+ </template>
28
+
29
+ <script lang="ts">
30
+ import { defineComponent, PropType } from 'vue';
31
+
32
+ import { CustomPropertyInfos } from '@dative-gpi/foundation-core-domain/models';
33
+
34
+ import FSText from '@dative-gpi/foundation-shared-components/components/FSText.vue';
35
+
36
+ import FSMetaField from './FSMetaField.vue';
37
+
38
+ export default defineComponent({
39
+ name: "FSMetaFormContent",
40
+ components: {
41
+ FSMetaField,
42
+ FSText
43
+ },
44
+ props: {
45
+ customProperties: {
46
+ type: [Object] as PropType<CustomPropertyInfos[]>,
47
+ required: true
48
+ },
49
+ modelValue: {
50
+ type: Object as PropType<{ [key: string]: string }>,
51
+ required: true
52
+ },
53
+ editable: {
54
+ type: Boolean,
55
+ required: false,
56
+ default: true
57
+ }
58
+ },
59
+ setup(props) {
60
+ const categories = props.customProperties.reduce((acc, curr) => {
61
+ if (acc[curr.categoryLabel] === undefined) {
62
+ acc[curr.categoryLabel] = [];
63
+ }
64
+ acc[curr.categoryLabel].push(curr);
65
+ return acc;
66
+ }, {} as { [key: string]: CustomPropertyInfos[] });
67
+
68
+ return {
69
+ categories
70
+ };
71
+ }
72
+ });
73
+ </script>
@@ -0,0 +1,89 @@
1
+ <template>
2
+ <FSButton
3
+ prependIcon="mdi-history"
4
+ label="history"
5
+ @click="dialog = !dialog"
6
+ />
7
+ <FSDialog
8
+ title="History"
9
+ width="500px"
10
+ v-model="dialog"
11
+ >
12
+ <template
13
+ #body
14
+ >
15
+ <FSCol>
16
+ <FSRow
17
+ v-for="(customPropertyValue, index) in customPropertyValues"
18
+ :key="index"
19
+ >
20
+ <FSText>{{ epochToLongTimeFormat(customPropertyValue.timestamp) }}</FSText>
21
+ <FSCol
22
+ padding="0 8px 0 0"
23
+ align="center-right"
24
+ >
25
+ <FSMetaValue
26
+ :customProperty="$props.customProperty"
27
+ :meta="{ code: customPropertyValue.value }"
28
+ />
29
+ </FSCol>
30
+ </FSRow>
31
+ </FSCol>
32
+ </template>
33
+ </FSDialog>
34
+ </template>
35
+ <script lang="ts">
36
+ import { PropType, defineComponent, ref, watch } from 'vue';
37
+ import _ from 'lodash';
38
+
39
+ import { useAppTimeZone } from '@dative-gpi/foundation-shared-services/composables';
40
+
41
+ import FSDialog from "@dative-gpi/foundation-shared-components/components/FSDialog.vue";
42
+ import FSButton from "@dative-gpi/foundation-shared-components/components/FSButton.vue";
43
+
44
+ import { CustomPropertyInfos, PropertyEntity } from '../../../foundation-core-domain/models';
45
+ import { useCustomPropertyValues } from '../../../foundation-core-services/composables';
46
+
47
+ import FSMetaValue from './FSMetaValue.vue';
48
+
49
+ export default defineComponent({
50
+ name: 'FSMetaHistory',
51
+ components: {
52
+ FSMetaValue,
53
+ FSButton,
54
+ FSDialog
55
+ },
56
+ props: {
57
+ customProperty: {
58
+ type: Object as PropType<CustomPropertyInfos>,
59
+ required: true
60
+ },
61
+ entityType: {
62
+ type: Number as PropType<PropertyEntity>,
63
+ required: true
64
+ },
65
+ entityId: {
66
+ type: String,
67
+ required: true
68
+ }
69
+ },
70
+ setup(props) {
71
+ const { epochToLongTimeFormat } = useAppTimeZone();
72
+ const { fetch, entity: customPropertyValues } = useCustomPropertyValues();
73
+
74
+ const dialog = ref(false);
75
+
76
+ watch(() => props.entityId, async (next, previous) => {
77
+ if (!_.isEqual(next, previous)) {
78
+ await fetch(props.entityType, props.entityId, props.customProperty.code);
79
+ }
80
+ }, { immediate: true });
81
+
82
+ return {
83
+ customPropertyValues,
84
+ dialog,
85
+ epochToLongTimeFormat
86
+ }
87
+ }
88
+ });
89
+ </script>
@@ -0,0 +1,75 @@
1
+ <template>
2
+ <FSText
3
+ v-if="$props.customProperty.useOnlyAllowedValues && $props.customProperty.allowedValues[meta[$props.customProperty.code]] != null"
4
+ :color="getColor($props.customProperty, meta[$props.customProperty.code])"
5
+ >
6
+ {{ value }}
7
+ </FSText>
8
+ <FSText
9
+ v-else-if="[PropertyDataType.Number, PropertyDataType.String, PropertyDataType.DateTime].includes($props.customProperty.dataType)"
10
+ :color="getColor($props.customProperty, meta[$props.customProperty.code])"
11
+ >
12
+ {{ value }}
13
+ </FSText>
14
+ <FSIcon
15
+ v-else-if="[PropertyDataType.Boolean, PropertyDataType.Icon].includes($props.customProperty.dataType)"
16
+ :color="getColor($props.customProperty, meta[$props.customProperty.code])"
17
+ >
18
+ {{ value }}
19
+ </FSIcon>
20
+ </template>
21
+
22
+ <script lang="ts">
23
+ import { PropType, computed, defineComponent } from "vue";
24
+
25
+ import { useAppTimeZone } from "@dative-gpi/foundation-shared-services/composables";
26
+
27
+ import { CustomPropertyInfos, PropertyDataType } from "../../../foundation-core-domain/models";
28
+ import { getColor } from "./helpers";
29
+
30
+
31
+ export default defineComponent({
32
+ name: "FSMetaValue",
33
+ props: {
34
+ customProperty: {
35
+ type: Object as PropType<CustomPropertyInfos>,
36
+ required: true
37
+ },
38
+ meta: {
39
+ type: Object as PropType<{ [key: string]: string }>,
40
+ required: true
41
+ }
42
+ },
43
+ setup(props) {
44
+ const { epochToLongTimeFormat } = useAppTimeZone();
45
+
46
+ const value = computed((): string => {
47
+ if (props.customProperty.useOnlyAllowedValues) {
48
+ if (props.customProperty.allowedValues[props.meta[props.customProperty.code]] != null) {
49
+ return props.customProperty.allowedValues[props.meta[props.customProperty.code]];
50
+ }
51
+ }
52
+ switch (props.customProperty.dataType) {
53
+ case PropertyDataType.Boolean: {
54
+ if (props.meta[props.customProperty.code]?.toLowerCase() === "true") {
55
+ return "mdi-check-circle-outline";
56
+ }
57
+ return "mdi-close-circle-outline";
58
+ }
59
+ case PropertyDataType.DateTime: {
60
+ return epochToLongTimeFormat(parseInt(props.meta[props.customProperty.code]));
61
+ }
62
+ default: {
63
+ return props.meta[props.customProperty.code];
64
+ }
65
+ }
66
+ });
67
+
68
+ return {
69
+ PropertyDataType,
70
+ value,
71
+ getColor
72
+ };
73
+ }
74
+ });
75
+ </script>
@@ -0,0 +1,190 @@
1
+ import { useAppTimeZone } from "@dative-gpi/foundation-shared-services/composables";
2
+ import { CustomPropertyInfos, FilterType, PropertyDataType } from "../../../foundation-core-domain/models";
3
+
4
+ const { getUserOffsetMillis, getMachineOffsetMillis } = useAppTimeZone();
5
+
6
+ export const getColor = (property: CustomPropertyInfos, value: string): string | undefined => {
7
+ if (property.colorful) {
8
+ for (const color of [...property.colorMap].sort((a, b) => b.priority - a.priority)) {
9
+ let filterValues = [...color.filterValues];
10
+ if ([PropertyDataType.DateTime].includes(property.dataType)) {
11
+ filterValues = filterValues.map(fv => getEpoch(fv));
12
+ }
13
+ switch (color.filterType) {
14
+ case FilterType.None: return color.color;
15
+ case FilterType.Equal: {
16
+ if (filterValues.includes(value)) {
17
+ return color.color;
18
+ }
19
+ break;
20
+ }
21
+ case FilterType.More: {
22
+ if (!isNaN(parseFloat(value))) {
23
+ if (filterValues.some(fv => !isNaN(parseFloat(fv)) && parseFloat(fv) < parseFloat(value))) {
24
+ return color.color;
25
+ }
26
+ }
27
+ break;
28
+ }
29
+ case FilterType.Less: {
30
+ if (!isNaN(parseFloat(value))) {
31
+ if (filterValues.some(fv => !isNaN(parseFloat(fv)) && parseFloat(fv) > parseFloat(value))) {
32
+ return color.color;
33
+ }
34
+ }
35
+ break;
36
+ }
37
+ case FilterType.MoreOrEqual: {
38
+ if (!isNaN(parseFloat(value))) {
39
+ if (filterValues.some(fv => !isNaN(parseFloat(fv)) && parseFloat(fv) <= parseFloat(value))) {
40
+ return color.color;
41
+ }
42
+ }
43
+ break;
44
+ }
45
+ case FilterType.LessOrEqual: {
46
+ if (!isNaN(parseFloat(value))) {
47
+ if (filterValues.some(fv => !isNaN(parseFloat(fv)) && parseFloat(fv) >= parseFloat(value))) {
48
+ return color.color;
49
+ }
50
+ }
51
+ break;
52
+ }
53
+ case FilterType.Different: {
54
+ if (!filterValues.includes(value)) {
55
+ return color.color;
56
+ }
57
+ break;
58
+ }
59
+ case FilterType.Contains: {
60
+ if (filterValues.some(fv => value.includes(fv))) {
61
+ return color.color;
62
+ }
63
+ break;
64
+ }
65
+ case FilterType.StartsWith: {
66
+ if (filterValues.some(fv => value.startsWith(fv))) {
67
+ return color.color;
68
+ }
69
+ break;
70
+ }
71
+ case FilterType.EndsWith: {
72
+ if (filterValues.some(fv => value.endsWith(fv))) {
73
+ return color.color;
74
+ }
75
+ break;
76
+ }
77
+ }
78
+ }
79
+ }
80
+ }
81
+
82
+ const getEpoch = (expression: string): string => {
83
+ if (!isNaN(parseInt(expression))) {
84
+ return expression;
85
+ }
86
+
87
+ const date = new Date();
88
+ if (expression.startsWith("now")) {
89
+ expression = expression.substring(3).replace(/\s/g, "");
90
+ }
91
+ else {
92
+ return (date.getTime()).toString();
93
+ }
94
+ let match = /^(?:(?:([-+])(\d*))?(\w+))?(?:\/(\w))?/g.exec(expression);
95
+ while (match != null && (match[0] != null && match[0].length > 0)) {
96
+ if (match[1] != null && match[3] != null) {
97
+ if (!["-", "+"].includes(match[1]) || isNaN(parseInt(match[2])) || !["s", "m", "h", "d", "w", "M", "y"].includes(match[3])) {
98
+ return (date.getTime()).toString();
99
+ }
100
+ const offset = match[1] == "-" ? -1 * parseInt(match[2]): 1* parseInt(match[2]);
101
+ switch (match[3]) {
102
+ case "s": {
103
+ date.setSeconds(date.getSeconds() + offset);
104
+ break;
105
+ }
106
+ case "m": {
107
+ date.setMinutes(date.getMinutes() + offset);
108
+ break;
109
+ }
110
+ case "h": {
111
+ date.setHours(date.getHours() + offset);
112
+ break;
113
+ }
114
+ case "d": {
115
+ date.setDate(date.getDate() + offset);
116
+ break;
117
+ }
118
+ case "w": {
119
+ date.setDate(date.getDate() + offset * 7);
120
+ break;
121
+ }
122
+ case "M": {
123
+ date.setMonth(date.getMonth() + offset);
124
+ break;
125
+ }
126
+ case "y": {
127
+ date.setFullYear(date.getFullYear() + offset);
128
+ break;
129
+ }
130
+ }
131
+ }
132
+ if (match[4] != null) {
133
+ if (!["s", "m", "h", "d", "w", "M", "y"].includes(match[4])) {
134
+ return (date.getTime()).toString();
135
+ }
136
+ switch (match[4]) {
137
+ case "s": {
138
+ date.setMilliseconds(0);
139
+ break;
140
+ }
141
+ case "m": {
142
+ date.setMilliseconds(0);
143
+ date.setSeconds(0);
144
+ break;
145
+ }
146
+ case "h": {
147
+ date.setMilliseconds(0);
148
+ date.setSeconds(0);
149
+ date.setMinutes(0);
150
+ break;
151
+ }
152
+ case "d": {
153
+ date.setMilliseconds(0);
154
+ date.setSeconds(0);
155
+ date.setMinutes(0);
156
+ date.setHours(0);
157
+ break;
158
+ }
159
+ case "w": {
160
+ date.setMilliseconds(0);
161
+ date.setSeconds(0);
162
+ date.setMinutes(0);
163
+ date.setHours(0);
164
+ date.setDate(date.getDate() - date.getDay() + (date.getDay() === 0 ? -6 : 1));
165
+ break;
166
+ }
167
+ case "M": {
168
+ date.setMilliseconds(0);
169
+ date.setSeconds(0);
170
+ date.setMinutes(0);
171
+ date.setHours(0);
172
+ date.setDate(1);
173
+ break;
174
+ }
175
+ case "y": {
176
+ date.setMilliseconds(0);
177
+ date.setSeconds(0);
178
+ date.setMinutes(0);
179
+ date.setHours(0);
180
+ date.setDate(1);
181
+ date.setMonth(0);
182
+ break;
183
+ }
184
+ }
185
+ }
186
+ expression = expression.substring(match[0].length);
187
+ match = /(?:(?:([-+])(\d*))?(\w+))?(?:\/(\w))?/g.exec(expression);
188
+ }
189
+ return (date.getTime() + getMachineOffsetMillis() - getUserOffsetMillis()).toString();
190
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@dative-gpi/foundation-core-components",
3
3
  "sideEffects": false,
4
- "version": "0.0.96",
4
+ "version": "0.0.98",
5
5
  "description": "",
6
6
  "publishConfig": {
7
7
  "access": "public"
@@ -10,11 +10,11 @@
10
10
  "author": "",
11
11
  "license": "ISC",
12
12
  "dependencies": {
13
- "@dative-gpi/foundation-core-domain": "0.0.96",
14
- "@dative-gpi/foundation-core-services": "0.0.96",
15
- "@dative-gpi/foundation-shared-components": "0.0.96",
16
- "@dative-gpi/foundation-shared-domain": "0.0.96",
17
- "@dative-gpi/foundation-shared-services": "0.0.96",
13
+ "@dative-gpi/foundation-core-domain": "0.0.98",
14
+ "@dative-gpi/foundation-core-services": "0.0.98",
15
+ "@dative-gpi/foundation-shared-components": "0.0.98",
16
+ "@dative-gpi/foundation-shared-domain": "0.0.98",
17
+ "@dative-gpi/foundation-shared-services": "0.0.98",
18
18
  "color": "^4.2.3",
19
19
  "vue": "^3.4.23",
20
20
  "vuedraggable": "^4.1.0"
@@ -24,5 +24,5 @@
24
24
  "sass": "^1.69.5",
25
25
  "sass-loader": "^13.3.2"
26
26
  },
27
- "gitHead": "36732331c6f295bbcd3abc4fe5e32d877fb8d80c"
27
+ "gitHead": "3e3b2cf8888bd50741bd2d91a76ebb7f53ff5f27"
28
28
  }