@dative-gpi/foundation-shared-components 1.0.69 → 1.0.71-groupings-2

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.
Files changed (296) hide show
  1. package/assets/images/map/snow.png +0 -0
  2. package/components/FSAccordionPanel.vue +40 -21
  3. package/components/FSBreadcrumbs.vue +21 -12
  4. package/components/FSButton.vue +11 -9
  5. package/components/FSCalendar.vue +50 -12
  6. package/components/FSCalendarTwin.vue +95 -43
  7. package/components/FSCard.vue +61 -9
  8. package/components/FSCardPlaceholder.vue +8 -5
  9. package/components/FSCheckbox.vue +5 -4
  10. package/components/FSChip.vue +73 -45
  11. package/components/FSChipGroup.vue +69 -0
  12. package/components/FSClickable.vue +11 -9
  13. package/components/FSClock.vue +30 -12
  14. package/components/FSCol.vue +11 -5
  15. package/components/FSDialog.vue +2 -1
  16. package/components/FSDialogContent.vue +12 -11
  17. package/components/FSDialogForm.vue +22 -2
  18. package/components/FSDialogFormBody.vue +50 -31
  19. package/components/FSDialogMenu.vue +17 -8
  20. package/components/FSDialogMultiFormBody.vue +23 -13
  21. package/components/FSDialogRemove.vue +7 -8
  22. package/components/FSDialogSubmit.vue +20 -11
  23. package/components/FSEditImageUI.vue +13 -5
  24. package/components/FSFadeOut.vue +53 -21
  25. package/components/FSForm.vue +10 -8
  26. package/components/FSGrid.vue +0 -1
  27. package/components/FSIcon.vue +2 -2
  28. package/components/FSIconCard.vue +68 -12
  29. package/components/FSInformationsMenu.vue +142 -0
  30. package/components/FSInstantPicker.vue +268 -0
  31. package/components/FSLink.vue +25 -9
  32. package/components/FSLoader.vue +28 -10
  33. package/components/FSMenu.vue +47 -0
  34. package/components/FSOptionGroup.vue +8 -8
  35. package/components/FSOptionItem.vue +4 -4
  36. package/components/FSOptionsMenu.vue +165 -0
  37. package/components/FSPagination.vue +1 -1
  38. package/components/FSPlayButtons.vue +72 -0
  39. package/components/FSProgressBar.vue +94 -0
  40. package/components/FSRadio.vue +5 -4
  41. package/components/FSRadioGroup.vue +3 -3
  42. package/components/FSRangePicker.vue +275 -0
  43. package/components/FSRangeSlider.vue +84 -0
  44. package/components/FSRouterLink.vue +42 -0
  45. package/components/FSSlideGroup.vue +9 -7
  46. package/components/FSSlider.vue +44 -79
  47. package/components/FSSpan.vue +22 -8
  48. package/components/FSSwitch.vue +44 -48
  49. package/components/FSTab.vue +15 -13
  50. package/components/FSTabs.vue +5 -2
  51. package/components/FSTag.vue +3 -3
  52. package/components/FSTagGroup.vue +6 -4
  53. package/components/FSText.vue +21 -8
  54. package/components/FSToggleSet.vue +7 -7
  55. package/components/FSTreeView.vue +107 -0
  56. package/components/FSWindow.vue +122 -5
  57. package/components/agenda/FSAgenda.vue +26 -7
  58. package/components/agenda/FSAgendaDialogCalendar.vue +2 -2
  59. package/components/agenda/FSAgendaHeader.vue +35 -10
  60. package/components/agenda/FSAgendaHorizontalEvent.vue +18 -6
  61. package/components/agenda/FSAgendaHoursRow.vue +48 -8
  62. package/components/agenda/FSAgendaVerticalEvent.vue +1 -1
  63. package/components/agenda/FSDayAgenda.vue +0 -1
  64. package/components/agenda/FSMonthAgenda.vue +1 -6
  65. package/components/agenda/FSSelectAgendaMode.vue +2 -2
  66. package/components/agenda/FSWeekAgenda.vue +5 -10
  67. package/components/autocompletes/FSAutoCompleteAddress.vue +25 -20
  68. package/components/autocompletes/FSAutocompleteLanguage.vue +7 -1
  69. package/components/autocompletes/FSAutocompleteTimeZone.vue +7 -1
  70. package/components/buttons/FSButtonAdd.vue +1 -1
  71. package/components/buttons/FSButtonAddLabel.vue +1 -1
  72. package/components/buttons/FSButtonCancel.vue +1 -1
  73. package/components/buttons/FSButtonCancelLabel.vue +1 -1
  74. package/components/buttons/FSButtonCheckbox.vue +4 -4
  75. package/components/buttons/FSButtonCopy.vue +1 -1
  76. package/components/buttons/FSButtonCopyLabel.vue +1 -1
  77. package/components/buttons/FSButtonDuplicate.vue +1 -1
  78. package/components/buttons/FSButtonDuplicateLabel.vue +1 -1
  79. package/components/buttons/FSButtonEdit.vue +1 -1
  80. package/components/buttons/FSButtonEditLabel.vue +1 -1
  81. package/components/buttons/FSButtonFile.vue +1 -1
  82. package/components/buttons/FSButtonFileLabel.vue +1 -1
  83. package/components/buttons/FSButtonNext.vue +1 -1
  84. package/components/buttons/FSButtonNextLabel.vue +1 -1
  85. package/components/buttons/FSButtonPrevious.vue +1 -1
  86. package/components/buttons/FSButtonPreviousLabel.vue +1 -1
  87. package/components/buttons/FSButtonRedo.vue +1 -1
  88. package/components/buttons/FSButtonRedoLabel.vue +1 -1
  89. package/components/buttons/FSButtonRemove.vue +1 -1
  90. package/components/buttons/FSButtonRemoveLabel.vue +1 -1
  91. package/components/buttons/FSButtonSave.vue +1 -1
  92. package/components/buttons/FSButtonSaveLabel.vue +1 -1
  93. package/components/buttons/FSButtonSearch.vue +1 -1
  94. package/components/buttons/FSButtonSearchLabel.vue +1 -1
  95. package/components/buttons/FSButtonUndo.vue +1 -1
  96. package/components/buttons/FSButtonUndoLabel.vue +1 -1
  97. package/components/buttons/FSButtonUpdate.vue +1 -1
  98. package/components/buttons/FSButtonUpdateLabel.vue +1 -1
  99. package/components/buttons/FSButtonValidate.vue +1 -1
  100. package/components/buttons/FSButtonValidateLabel.vue +1 -1
  101. package/components/calendar/FSSimpleCalendar.vue +145 -0
  102. package/components/calendar/FSSimpleCalendarHeader.vue +60 -0
  103. package/components/calendar/FSSimpleMonthSelector.vue +138 -0
  104. package/components/carousels/FSCarousel.vue +23 -0
  105. package/components/carousels/FSCarouselItem.vue +14 -0
  106. package/components/deviceOrganisations/FSConnectivity.vue +5 -3
  107. package/components/deviceOrganisations/FSStatus.vue +5 -3
  108. package/components/deviceOrganisations/FSStatusCard.vue +7 -9
  109. package/components/deviceOrganisations/FSStatusRichCard.vue +171 -0
  110. package/components/deviceOrganisations/FSWorstAlert.vue +24 -36
  111. package/components/deviceOrganisations/FSWorstAlertCard.vue +8 -47
  112. package/components/fields/FSAutocompleteField.vue +85 -82
  113. package/components/fields/FSAutocompleteTag.vue +1 -1
  114. package/components/fields/FSBaseField.vue +42 -25
  115. package/components/fields/FSClosableSearchField.vue +83 -0
  116. package/components/fields/FSColorField.vue +12 -10
  117. package/components/fields/FSCommentField.vue +28 -16
  118. package/components/fields/FSDateField.vue +13 -10
  119. package/components/fields/FSDateRangeField.vue +6 -5
  120. package/components/fields/FSDateTimeField.vue +14 -11
  121. package/components/fields/FSDateTimeRangeDialog.vue +160 -0
  122. package/components/fields/FSDateTimeRangeField.vue +23 -115
  123. package/components/fields/FSEntityFieldUI.vue +19 -16
  124. package/components/fields/FSGradientField.vue +5 -5
  125. package/components/fields/FSIconField.vue +16 -9
  126. package/components/fields/FSMapAddressField.vue +187 -0
  127. package/components/fields/FSNumberField.vue +8 -4
  128. package/components/fields/FSPasswordField.vue +7 -7
  129. package/components/fields/FSPoliciesValidationField.vue +101 -0
  130. package/components/fields/FSRichTextField.vue +78 -58
  131. package/components/fields/FSSearchField.vue +9 -115
  132. package/components/fields/FSSelectField.vue +69 -71
  133. package/components/fields/FSTagField.vue +9 -9
  134. package/components/fields/FSTermField.vue +69 -46
  135. package/components/fields/FSTextArea.vue +17 -11
  136. package/components/fields/FSTextField.vue +15 -10
  137. package/components/fields/FSTimeField.vue +14 -10
  138. package/components/fields/FSTimeRangeField.vue +117 -187
  139. package/components/fields/FSTimeStepField.vue +5 -5
  140. package/components/fields/FSTranslateField.vue +10 -10
  141. package/components/fields/FSTranslateRichTextField.vue +41 -20
  142. package/components/fields/FSTranslateTextArea.vue +10 -10
  143. package/components/fields/FSTreeViewField.vue +21 -19
  144. package/components/fields/periodicField/FSPeriodicDailyField.vue +7 -7
  145. package/components/fields/periodicField/FSPeriodicField.vue +15 -15
  146. package/components/fields/periodicField/FSPeriodicMonthlyField.vue +16 -16
  147. package/components/fields/periodicField/FSPeriodicWeeklyField.vue +28 -18
  148. package/components/fields/periodicField/FSPeriodicYearlyField.vue +12 -12
  149. package/components/lists/FSDataIteratorItem.vue +23 -67
  150. package/components/lists/FSDataTableUI.vue +194 -119
  151. package/components/lists/FSFilterButton.vue +14 -16
  152. package/components/lists/FSHeaderButton.vue +11 -9
  153. package/components/lists/FSHiddenButton.vue +9 -9
  154. package/components/lists/FSLoadDataTable.vue +10 -7
  155. package/components/lists/FSSimpleList.vue +95 -88
  156. package/components/lists/FSSimpleListItem.vue +131 -0
  157. package/components/map/FSMap.vue +144 -158
  158. package/components/map/FSMapFeatureGroup.vue +7 -1
  159. package/components/map/FSMapLayerButton.vue +3 -3
  160. package/components/map/FSMapMarker.vue +103 -42
  161. package/components/map/FSMapMarkerClusterGroup.vue +32 -7
  162. package/components/map/FSMapOverlay.vue +44 -24
  163. package/components/map/FSMapPolygon.vue +16 -4
  164. package/components/map/FSMapTileLayer.vue +26 -9
  165. package/components/map/layers.ts +0 -0
  166. package/components/selects/FSSelectAutoRefresh.vue +8 -8
  167. package/components/selects/FSSelectDashboardVariableType.vue +4 -3
  168. package/components/selects/FSSelectDateSetting.vue +2 -2
  169. package/components/selects/FSSelectDays.vue +8 -8
  170. package/components/selects/FSSelectListMode.vue +2 -2
  171. package/components/selects/FSSelectMapLayer.vue +68 -0
  172. package/components/selects/FSSelectMonths.vue +13 -13
  173. package/components/selects/chartSelectors/FSAggregationSelector.vue +52 -0
  174. package/components/selects/chartSelectors/FSAxisTypeSelector.vue +49 -0
  175. package/components/selects/chartSelectors/FSDisplayAsSelector.vue +53 -0
  176. package/components/selects/chartSelectors/FSFilterTypeSelector.vue +54 -0
  177. package/components/selects/chartSelectors/FSHeatmapRuleSelector.vue +54 -0
  178. package/components/selects/chartSelectors/FSOperationOnSelector.vue +53 -0
  179. package/components/selects/chartSelectors/FSPlanningTypeSelector.vue +53 -0
  180. package/components/selects/chartSelectors/FSSelectEntityType.vue +59 -0
  181. package/components/selects/chartSelectors/FSSerieTypeSelector.vue +53 -0
  182. package/components/tiles/FSAlertTileUI.vue +90 -0
  183. package/components/tiles/FSChartTileUI.vue +61 -52
  184. package/components/tiles/FSCommentTileUI.vue +38 -13
  185. package/components/tiles/FSDashboardOrganisationTypeTileUI.vue +14 -2
  186. package/components/tiles/FSDashboardShallowTileUI.vue +14 -2
  187. package/components/tiles/FSDeviceOrganisationTileUI.vue +0 -6
  188. package/components/tiles/FSEntityCountBadge.vue +83 -0
  189. package/components/tiles/FSFolderTileUI.vue +38 -4
  190. package/components/tiles/FSGroupTileUI.vue +32 -136
  191. package/components/tiles/FSGroupingTileUI.vue +52 -0
  192. package/components/tiles/FSLoadTile.vue +16 -10
  193. package/components/tiles/FSLocationTileUI.vue +50 -80
  194. package/components/tiles/FSServiceAccountOrganisationTileUI.vue +0 -6
  195. package/components/tiles/FSSimpleTileUI.vue +32 -27
  196. package/components/tiles/FSTile.vue +46 -39
  197. package/components/tiles/FSUserOrganisationTileUI.vue +1 -7
  198. package/components/tiles/FSUserTileUI.vue +119 -0
  199. package/components/toggleSets/FSToggleSetPosition.vue +1 -1
  200. package/components/views/FSBaseView.vue +64 -0
  201. package/components/views/FSEntityView.vue +12 -146
  202. package/components/views/FSSimpleView.vue +29 -0
  203. package/components/views/desktop/FSBaseDefaultDesktopView.vue +135 -0
  204. package/components/views/desktop/FSBaseDesktopView.vue +53 -0
  205. package/components/views/desktop/FSBaseEntityDesktopView.vue +211 -0
  206. package/components/views/mobile/FSBaseDefaultMobileView.vue +133 -0
  207. package/components/views/mobile/FSBaseEntityMobileView.vue +206 -0
  208. package/components/views/mobile/FSBaseMobileView.vue +53 -0
  209. package/composables/index.ts +1 -1
  210. package/composables/useAddress.ts +40 -8
  211. package/composables/useBreakpoints.ts +40 -4
  212. package/composables/useColors.ts +16 -7
  213. package/composables/useMapLayers.ts +69 -0
  214. package/composables/useSlots.ts +2 -1
  215. package/models/colors.ts +2 -1
  216. package/models/deviceAlerts.ts +1 -0
  217. package/models/index.ts +0 -1
  218. package/models/map.ts +12 -10
  219. package/models/rules.ts +5 -2
  220. package/models/tables.ts +2 -1
  221. package/models/variableNode.ts +8 -5
  222. package/package.json +5 -5
  223. package/styles/components/fs_agenda.scss +4 -0
  224. package/styles/components/fs_agenda_event.scss +1 -1
  225. package/styles/components/fs_agenda_hours_row.scss +0 -8
  226. package/styles/components/fs_autocomplete_field.scss +0 -13
  227. package/styles/components/fs_breadcrumbs.scss +18 -36
  228. package/styles/components/fs_button.scss +7 -5
  229. package/styles/components/fs_calendar.scss +1 -0
  230. package/styles/components/fs_card.scss +9 -0
  231. package/styles/components/fs_chip.scss +13 -7
  232. package/styles/components/fs_clickable.scss +16 -23
  233. package/styles/components/fs_clock.scss +0 -10
  234. package/styles/components/fs_col.scss +1 -1
  235. package/styles/components/fs_color_field.scss +0 -4
  236. package/styles/components/fs_data_table.scss +6 -9
  237. package/styles/components/fs_dialog.scss +4 -10
  238. package/styles/components/fs_dialog_menu.scss +4 -2
  239. package/styles/components/fs_draggable.scss +0 -5
  240. package/styles/components/fs_fade_out.scss +10 -2
  241. package/styles/components/fs_filter_button.scss +1 -1
  242. package/styles/components/fs_hidden_button.scss +2 -7
  243. package/styles/components/fs_image_card.scss +6 -4
  244. package/styles/components/fs_magic_config_field.scss +1 -2
  245. package/styles/components/fs_map.scss +57 -17
  246. package/styles/components/fs_meta_field.scss +3 -5
  247. package/styles/components/fs_password_field.scss +4 -2
  248. package/styles/components/fs_progress_bar.scss +14 -0
  249. package/styles/components/fs_radio.scss +0 -11
  250. package/styles/components/fs_rich_text_field.scss +1 -10
  251. package/styles/components/fs_select_field.scss +4 -13
  252. package/styles/components/fs_slide_group.scss +3 -1
  253. package/styles/components/fs_slider.scss +0 -40
  254. package/styles/components/fs_span.scss +17 -5
  255. package/styles/components/fs_status_rich_card.scss +6 -0
  256. package/styles/components/fs_tabs.scss +18 -37
  257. package/styles/components/fs_tag.scss +8 -22
  258. package/styles/components/fs_text_area.scss +2 -21
  259. package/styles/components/fs_tile.scss +0 -19
  260. package/styles/components/fs_window.scss +3 -1
  261. package/styles/components/fs_wrap_group.scss +3 -0
  262. package/styles/components/index.scss +2 -6
  263. package/styles/globals/index.scss +1 -5
  264. package/styles/globals/overrides.scss +26 -44
  265. package/styles/globals/scrollbars.scss +8 -0
  266. package/styles/globals/text_fonts.scss +18 -66
  267. package/styles/globals/touchscreen.scss +2 -2
  268. package/tools/alertsTools.ts +94 -18
  269. package/tools/chartsTools.ts +156 -16
  270. package/tools/index.ts +1 -0
  271. package/tools/reportsTools.ts +38 -0
  272. package/tools/timeRangeTools.ts +99 -40
  273. package/utils/badge.ts +9 -5
  274. package/utils/index.ts +2 -0
  275. package/utils/leafletMarkers.ts +4 -4
  276. package/utils/operations.ts +108 -0
  277. package/utils/picker.ts +40 -0
  278. package/utils/sort.ts +2 -2
  279. package/utils/time.ts +13 -13
  280. package/components/fields/FSMagicConfigField.vue +0 -163
  281. package/components/fields/FSMagicField.vue +0 -193
  282. package/components/fields/FSTimeSlotField.vue +0 -250
  283. package/components/views/FSEntityHeader.vue +0 -343
  284. package/components/views/FSListHeader.vue +0 -83
  285. package/components/views/FSListView.vue +0 -83
  286. package/components/views/FSSkeletonView.vue +0 -100
  287. package/composables/useMagicFieldProvider.ts +0 -23
  288. package/models/magicFields.ts +0 -10
  289. package/styles/components/fs_data_iterator_item.scss +0 -33
  290. package/styles/components/fs_icon_field.scss +0 -12
  291. package/styles/components/fs_search_field.scss +0 -3
  292. package/styles/components/fs_tag_field.scss +0 -8
  293. package/styles/components/fs_time_field.scss +0 -12
  294. package/styles/components/fs_timeslot_field.scss +0 -12
  295. package/styles/globals/breakpoints.scss +0 -20
  296. package/styles/globals/fixes.scss +0 -5
@@ -0,0 +1,108 @@
1
+ const MinusOperator = "-";
2
+
3
+ /**
4
+ * Splits an expression by operators while keeping unary minus signs.
5
+ */
6
+ const splitByOperators = (expression: string): string[] => {
7
+ const tokens: string[] = [];
8
+ let current = '';
9
+ let expectOperand = true;
10
+
11
+ for (let i = 0; i < expression.length; i++) {
12
+ const char = expression[i];
13
+ if ('+-*/'.includes(char)) {
14
+ const isUnaryMinus = char === '-' && expectOperand;
15
+ if (isUnaryMinus) {
16
+ current += char;
17
+ expectOperand = true;
18
+ } else {
19
+ if (expectOperand) {
20
+ // 2 consecutive operators or operator at the start
21
+ return [];
22
+ }
23
+ if (current !== '') {
24
+ tokens.push(current);
25
+ current = '';
26
+ }
27
+ tokens.push(char);
28
+ expectOperand = true;
29
+ }
30
+ } else {
31
+ current += char;
32
+ expectOperand = false;
33
+ }
34
+ }
35
+ if (current !== '') {
36
+ tokens.push(current);
37
+ }
38
+ return tokens;
39
+ };
40
+
41
+ // Matches a nested block of parenthesis
42
+ const parenthesisRegex = new RegExp(/\([^)(]+\)/gm);
43
+
44
+ // Match a positive decimal number
45
+ const decimalRegex = new RegExp(/^\d+(.\d+)?$/gm);
46
+
47
+ const validateBlock = (block: string, operands: string[] = [], variables: string[] = []) => {
48
+ // Remove parenthesis from the block
49
+ block = block.replaceAll("(", "").replaceAll(")", "");
50
+
51
+ // Split block on operators (Leave negative signs)
52
+ const tokens = splitByOperators(block);
53
+ if (tokens.length === 0) {
54
+ return false;
55
+ }
56
+ const components = tokens.filter(token => !'+-*/'.includes(token));
57
+
58
+ // Check if each bit is a valid operand
59
+ for (let i = 0; i < components.length; i++) {
60
+ // Remove negative sign
61
+ if (components[i].startsWith(MinusOperator)) {
62
+ components[i] = components[i].substring(1);
63
+ }
64
+ if (!operands.includes(components[i]) && !variables.includes(components[i]) && !components[i].match(decimalRegex)) {
65
+ return false;
66
+ }
67
+ }
68
+ return true;
69
+ }
70
+
71
+ export const validateOperation = (rawOperation: string, operands: string[] = [], variables: string[] = []) => {
72
+ // Remove spaces
73
+ let operation = rawOperation.replaceAll(" ", "");
74
+
75
+ // Check parenthesis
76
+ const parenthesis: number[] = [];
77
+
78
+ for (let i = 0; i < operation.length; i++) {
79
+ if (operation[i] == '(') {
80
+ parenthesis.push(i);
81
+ }
82
+ else if (operation[i] == ')') {
83
+ if (parenthesis.length > 0) {
84
+ if (i == parenthesis.pop()! + 1) {
85
+ return false;
86
+ }
87
+ }
88
+ else {
89
+ return false;
90
+ }
91
+ }
92
+ }
93
+ if (parenthesis.length > 0) {
94
+ return false;
95
+ }
96
+
97
+ // Check each block between parenthesis
98
+ let match = operation.match(parenthesisRegex);
99
+
100
+ while (match?.[0]) {
101
+ if (!validateBlock(match[0], operands, variables)) {
102
+ return false;
103
+ }
104
+ operation = operation.replace(match[0], "1");
105
+ match = operation.match(parenthesisRegex);
106
+ }
107
+ return validateBlock(operation, operands, variables);
108
+ }
@@ -0,0 +1,40 @@
1
+ export enum TimePrecision {
2
+ Hours = 1,
3
+ Days = 2,
4
+ Months = 3
5
+ }
6
+
7
+ /**
8
+ * Compute ticks for a time range based on the specified precision.
9
+ */
10
+ export const computeTicks = ({ start, end, tickCount, precision }: { start: number, end: number, tickCount: number, precision: TimePrecision }): number[] => {
11
+ const ticks: number[] = [];
12
+ const range = end - start;
13
+
14
+ if (precision === TimePrecision.Hours) {
15
+ // Tick toutes les X heures, aligné sur l'heure pleine
16
+ const step = Math.ceil(range / tickCount / 3600000) * 3600000;
17
+ const alignedStart = Math.ceil(start / 3600000) * 3600000;
18
+ for (let i = 0; i < tickCount; i++) {
19
+ const tick = alignedStart + i * step;
20
+ if (tick < end) { ticks.push(tick); }
21
+ }
22
+ } else if (precision === TimePrecision.Days) {
23
+ // Tick tous les X jours, aligné sur minuit
24
+ const step = Math.ceil(range / tickCount / 86400000) * 86400000;
25
+ const date = new Date(start);
26
+ date.setHours(0, 0, 0, 0);
27
+ const alignedStart = date.getTime() + (date.getTime() < start ? step : 0);
28
+ for (let i = 0; i < tickCount; i++) {
29
+ const tick = alignedStart + i * step;
30
+ if (tick < end) { ticks.push(tick); }
31
+ }
32
+ } else {
33
+ // Tick tous les X mois (approximation linéaire)
34
+ const interval = range / tickCount;
35
+ for (let i = 0; i < tickCount; i++) {
36
+ ticks.push(start + i * interval);
37
+ }
38
+ }
39
+ return ticks;
40
+ }
package/utils/sort.ts CHANGED
@@ -23,7 +23,7 @@ export const alphanumericSort = (a: any, b: any) => {
23
23
  if (b == null) {
24
24
  return 1;
25
25
  }
26
- a = asString(a);
27
- b = asString(b);
26
+ a = asString(a).trim();
27
+ b = asString(b).trim();
28
28
  return a.localeCompare(b, undefined, { numeric: true });
29
29
  };
package/utils/time.ts CHANGED
@@ -5,13 +5,13 @@ import { TimeUnit } from "@dative-gpi/foundation-shared-domain/enums"
5
5
  const { $tr } = useTranslationsProvider();
6
6
 
7
7
  export const timeSteps = [
8
- { id: TimeUnit.Second, label: $tr("ui.time-step.second.singular", "Second"), plural: $tr("ui.time-step.second.plural", "Seconds") },
9
- { id: TimeUnit.Minute, label: $tr("ui.time-step.minute.singular", "Minute"), plural: $tr("ui.time-step.minute.plural", "Minutes") },
10
- { id: TimeUnit.Hour, label: $tr("ui.time-step.hour.singular", "Hour"), plural: $tr("ui.time-step.hour.plural", "Hours") },
11
- { id: TimeUnit.Day, label: $tr("ui.time-step.day.singular", "Day"), plural: $tr("ui.time-step.day.plural", "Days") },
12
- { id: TimeUnit.Week, label: $tr("ui.time-step.week.singular", "Week"), plural: $tr("ui.time-step.week.plural", "Weeks") },
13
- { id: TimeUnit.Month, label: $tr("ui.time-step.month.singular", "Month"), plural: $tr("ui.time-step.month.plural", "Months") },
14
- { id: TimeUnit.Year, label: $tr("ui.time-step.year.singular", "Year"), plural: $tr("ui.time-step.year.plural", "Years") },
8
+ { id: TimeUnit.Second, get label() { return $tr("ui.common.second", "Second") }, get plural() { return $tr("ui.common.seconds", "Seconds") } },
9
+ { id: TimeUnit.Minute, get label() { return $tr("ui.common.minute", "Minute") }, get plural() { return $tr("ui.common.minutes", "Minutes") } },
10
+ { id: TimeUnit.Hour, get label() { return $tr("ui.common.hour", "Hour") }, get plural() { return $tr("ui.common.hours", "Hours") } },
11
+ { id: TimeUnit.Day, get label() { return $tr("ui.common.day", "Day") }, get plural() { return $tr("ui.common.days", "Days") } },
12
+ { id: TimeUnit.Week, get label() { return $tr("ui.common.week", "Week") }, get plural() { return $tr("ui.common.weeks", "Weeks") } },
13
+ { id: TimeUnit.Month, get label() { return $tr("ui.common.month", "Month") }, get plural() { return $tr("ui.common.months", "Months") } },
14
+ { id: TimeUnit.Year, get label() { return $tr("ui.common.year", "Year") }, get plural() { return $tr("ui.common.years", "Years") } },
15
15
  ];
16
16
 
17
17
  export const timeStepToString = (value: { value: number, unit: TimeUnit } | null): string => {
@@ -28,12 +28,12 @@ export const timeStepToString = (value: { value: number, unit: TimeUnit } | null
28
28
  };
29
29
 
30
30
  // TODO : remove everything below this line
31
- export const timeScale: any[] = [
32
- { id: 1, label: $tr("ui.time-field.second.singular", "Second"), plural: $tr("ui.time-field.second.plural", "Seconds") },
33
- { id: 60, label: $tr("ui.time-field.minute.singular", "Minute"), plural: $tr("ui.time-field.minute.plural", "Minutes") },
34
- { id: 3600, label: $tr("ui.time-field.hour.singular", "Hour"), plural: $tr("ui.time-field.hour.plural", "Hours") },
35
- { id: 86400, label: $tr("ui.time-field.day.singular", "Day"), plural: $tr("ui.time-field.day.plural", "Days") },
36
- { id: 604800, label: $tr("ui.time-field.week.singular", "Week"), plural: $tr("ui.time-field.week.plural", "Weeks") },
31
+ export const timeScale = [
32
+ { id: 1, get label() { return $tr("ui.common.second", "Second") }, get plural() { return $tr("ui.common.seconds", "Seconds") } },
33
+ { id: 60, get label() { return $tr("ui.common.minute", "Minute") }, get plural() { return $tr("ui.common.minutes", "Minutes") } },
34
+ { id: 3600, get label() { return $tr("ui.common.hour", "Hour") }, get plural() { return $tr("ui.common.hours", "Hours") } },
35
+ { id: 86400, get label() { return $tr("ui.common.day", "Day") }, get plural() { return $tr("ui.common.days", "Days") } },
36
+ { id: 604800, get label() { return $tr("ui.common.week", "Week") }, get plural() { return $tr("ui.common.weeks", "Weeks") } },
37
37
  ];
38
38
 
39
39
  export const getTimeScaleIndex = (value: number): number => {
@@ -1,163 +0,0 @@
1
- <template>
2
- <FSRow
3
- class="fs-magic-config-field"
4
- >
5
- <component
6
- class="fs-magic-config-field-value"
7
- :is="get($props.type)"
8
- :label="$tr('ui.magic-config-field.value', 'Value')"
9
- :editable="$props.editable"
10
- :required="true"
11
- :rules="rules"
12
- :modelValue="valueToInput"
13
- @update:modelValue="inputToValue"
14
- />
15
- <FSRow
16
- gap="24px"
17
- >
18
- <FSTranslateField
19
- :label="$tr('ui.magic-config-field.label', 'Label')"
20
- :editable="$props.editable"
21
- :modelValue="$props.labelDefault"
22
- :translations="$props.translations"
23
- @update:modelValue="$emit('update:labelDefault', $event)"
24
- @update:translations="$emit('update:translations', $event)"
25
- />
26
- <FSRow
27
- class="fs-magic-config-field-actions"
28
- width="hug"
29
- :wrap="false"
30
- >
31
- <FSButtonRemoveIcon
32
- @click="$emit('click:remove')"
33
- />
34
- <FSButtonAddIcon
35
- @click="$emit('click:add')"
36
- />
37
- </FSRow>
38
- </FSRow>
39
- </FSRow>
40
- </template>
41
-
42
- <script lang="ts">
43
- import { computed, defineComponent, type PropType } from "vue";
44
-
45
- import { DateRules, IconRules, NumberRules, TextRules, TimeRules, TimeStepRules } from "../../models";
46
- import { useMagicFieldProvider } from "../../composables";
47
- import { MagicFieldType } from "../../models/magicFields";
48
-
49
- import FSButtonRemoveIcon from "../buttons/FSButtonRemoveIcon.vue";
50
- import FSButtonAddIcon from "../buttons/FSButtonAddIcon.vue";
51
- import FSTranslateField from "./FSTranslateField.vue";
52
- import FSRow from "../FSRow.vue";
53
-
54
- export default defineComponent({
55
- name: "FSMagicConfigField",
56
- components: {
57
- FSButtonRemoveIcon,
58
- FSTranslateField,
59
- FSButtonAddIcon,
60
- FSRow
61
- },
62
- props: {
63
- type: {
64
- type: Number as PropType<MagicFieldType>,
65
- required: false,
66
- default: MagicFieldType.TextField
67
- },
68
- labelDefault: {
69
- type: String as PropType<string | null>,
70
- required: false,
71
- default: null
72
- },
73
- modelValue: {
74
- type: String as PropType<string | null>,
75
- required: false,
76
- default: null
77
- },
78
- translations: {
79
- type: Array as PropType<{ languageCode: string; label: string }[]>,
80
- required: false,
81
- default: () => []
82
- },
83
- editable: {
84
- type: Boolean,
85
- required: false,
86
- default: true
87
- }
88
- },
89
- emits: ["click:remove", "click:add", "update:modelValue", "update:labelDefault", "update:translations"],
90
- setup(props, { emit }) {
91
- const { get } = useMagicFieldProvider();
92
-
93
- const rules = computed((): Function[] => {
94
- switch (props.type) {
95
- case MagicFieldType.NumberField:
96
- return [NumberRules.required()];
97
- case MagicFieldType.TextField:
98
- return [TextRules.required()];
99
- case MagicFieldType.DateTimeField:
100
- return [DateRules.required()];
101
- case MagicFieldType.IconField:
102
- return [IconRules.required()];
103
- case MagicFieldType.TimeField:
104
- return [TimeRules.required()];
105
- case MagicFieldType.TimeStepField:
106
- return [TimeStepRules.required()];
107
- }
108
- return [];
109
- });
110
-
111
- const valueToInput = computed((): any => {
112
- if (!props.modelValue) {
113
- return null;
114
- }
115
-
116
- switch (props.type) {
117
- case MagicFieldType.NumberField:
118
- case MagicFieldType.DateTimeField:
119
- case MagicFieldType.TimeField:
120
- if (isNaN(parseFloat(props.modelValue))) {
121
- return null;
122
- }
123
- return parseFloat(props.modelValue);
124
- case MagicFieldType.Switch:
125
- return props.modelValue === "true";
126
- case MagicFieldType.TimeStepField:
127
- return JSON.parse(props.modelValue);
128
- default:
129
- return props.modelValue;
130
- }
131
- });
132
-
133
- const inputToValue = (value: any) => {
134
- if (!value) {
135
- emit("update:modelValue", null);
136
- }
137
-
138
- switch (props.type) {
139
- case MagicFieldType.NumberField:
140
- case MagicFieldType.Switch:
141
- case MagicFieldType.DateTimeField:
142
- case MagicFieldType.TimeField:
143
- emit("update:modelValue", value.toString());
144
- break;
145
- case MagicFieldType.TimeStepField:
146
- emit("update:modelValue", JSON.stringify(value));
147
- break;
148
- default:
149
- emit("update:modelValue", value);
150
- break;
151
- }
152
- };
153
-
154
- return {
155
- MagicFieldType,
156
- valueToInput,
157
- rules,
158
- inputToValue,
159
- get
160
- };
161
- },
162
- });
163
- </script>
@@ -1,193 +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
- default:
135
- return props.modelValue;
136
- }
137
- });
138
-
139
- const asString = (value: string): string | null => {
140
- if (value == null) {
141
- return "";
142
- }
143
-
144
- switch (props.type) {
145
- case MagicFieldType.NumberField:
146
- return value.toString();
147
- case MagicFieldType.Switch:
148
- if (value) {
149
- return $tr("ui.magic-field.true", "True");
150
- }
151
- return $tr("ui.magic-field.false", "False");
152
- case MagicFieldType.DateTimeField:
153
- return epochToShortTimeFormat(parseFloat(value));
154
- case MagicFieldType.TimeField:
155
- return getTimeBestString(parseFloat(value));
156
- case MagicFieldType.TimeStepField:
157
- return timeStepToString(JSON.parse(value));
158
- default:
159
- return value;
160
- }
161
- }
162
-
163
- const inputToValue = (value: any) => {
164
- if (value == null) {
165
- emit("update:modelValue", null);
166
- }
167
-
168
- switch (props.type) {
169
- case MagicFieldType.NumberField:
170
- case MagicFieldType.Switch:
171
- case MagicFieldType.DateTimeField:
172
- case MagicFieldType.TimeField:
173
- emit("update:modelValue", value.toString());
174
- break;
175
- case MagicFieldType.TimeStepField:
176
- emit("update:modelValue", JSON.stringify(value));
177
- break;
178
- default:
179
- emit("update:modelValue", value);
180
- break;
181
- }
182
- };
183
-
184
- return {
185
- MagicFieldType,
186
- valueToInput,
187
- items,
188
- inputToValue,
189
- get
190
- };
191
- },
192
- });
193
- </script>