@dative-gpi/foundation-shared-components 1.0.156 → 1.0.157-mobile

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.
@@ -3,9 +3,9 @@
3
3
  </template>
4
4
 
5
5
  <script lang="ts">
6
- import { inject, type PropType, onMounted, type Ref, watch, ref, onUnmounted } from 'vue';
6
+ import { inject, type PropType, type Ref, watch, ref, onUnmounted, onMounted } from 'vue';
7
7
 
8
- import { type Map, type DivIcon, divIcon, type LatLng, marker, type Marker, type MarkerClusterGroup } from 'leaflet';
8
+ import { type Map, divIcon, type LatLng, marker, type Marker, type MarkerClusterGroup, type LeafletMouseEvent } from 'leaflet';
9
9
 
10
10
  import { useColors } from "../../composables";
11
11
 
@@ -49,87 +49,90 @@ export default {
49
49
  const markerClusterGroup = inject<Ref<MarkerClusterGroup | null>>(MARKERCLUSTERGROUP, ref(null));
50
50
 
51
51
  const { getColors } = useColors();
52
-
53
- const lastMarker = ref<Marker | null>(null);
54
-
55
- if(!map) {
56
- throw new Error('FSMapTileLayer must be used inside a FSMap component');
57
- }
58
-
59
- if(!map.value) {
60
- throw new Error('FSMapTileLayer must be used inside a FSMap component with a map');
61
- }
62
-
63
- const updateMarker = () => {
64
- if(!map.value || !props.latlng) {
65
- return;
66
- }
67
-
68
- if(lastMarker.value) {
69
- if(markerClusterGroup && markerClusterGroup.value) {
70
- markerClusterGroup.value.removeLayer(lastMarker.value as Marker);
71
- } else {
72
- map.value.removeLayer(lastMarker.value as Marker);
73
- }
74
- }
75
-
76
- let icon: DivIcon | null = null;
52
+ const getMarkerIcon = () => {
77
53
  if(props.variant === 'gps') {
78
54
  const size = 16;
79
- icon = divIcon({
55
+ return divIcon({
80
56
  html: gpsMarkerHtml(),
81
57
  className: 'fs-map-mylocation',
82
58
  iconSize: [size, size],
83
59
  iconAnchor: [size / 2, size / 2],
84
60
  });
85
- } else if(props.variant === 'location') {
61
+ }
62
+
63
+ if(props.variant === 'location') {
86
64
  const size = 36;
87
- icon = divIcon({
65
+ return divIcon({
88
66
  html: locationMarkerHtml(props.icon ?? "mdi-map-marker", getColors(props.color).base, props.label),
89
67
  iconSize: [size, size],
90
68
  className: props.selected ? 'fs-map-marker fs-map-location fs-map-location-selected' : 'fs-map-marker fs-map-location',
91
69
  iconAnchor: [size / 2, size / 2],
92
70
  });
93
- } else {
94
- const size = 16;
95
- icon = divIcon({
96
- html: pinMarkerHtml(getColors(props.color).base, props.label),
97
- iconSize: [size, size],
98
- className: props.selected ? 'fs-map-marker fs-map-pin fs-map-pin-selected' : 'fs-map-marker fs-map-pin',
99
- iconAnchor: [size / 2, size / 2],
100
- });
101
71
  }
102
-
103
- lastMarker.value = marker(props.latlng, { icon });
104
- lastMarker.value.on('click', (e) => {
105
- emit('click', e);
72
+
73
+ const size = 16;
74
+ return divIcon({
75
+ html: pinMarkerHtml(getColors(props.color).base, props.label),
76
+ iconSize: [size, size],
77
+ className: props.selected ? 'fs-map-marker fs-map-pin fs-map-pin-selected' : 'fs-map-marker fs-map-pin',
78
+ iconAnchor: [size / 2, size / 2],
106
79
  });
80
+ }
81
+
82
+ const actualMarker = ref(marker(props.latlng ?? [0, 0], { icon: getMarkerIcon() }));
83
+
84
+ if(!map) {
85
+ throw new Error('FSMapTileLayer must be used inside a FSMap component');
86
+ }
87
+
88
+ if(!map.value) {
89
+ throw new Error('FSMapTileLayer must be used inside a FSMap component with a map');
90
+ }
91
+
92
+ watch(map, () => {
93
+ if(!map.value) {
94
+ return;
95
+ }
107
96
 
108
97
  if(markerClusterGroup && markerClusterGroup.value) {
109
- lastMarker.value.addTo(markerClusterGroup.value);
98
+ actualMarker.value.addTo(markerClusterGroup.value);
110
99
  } else {
111
- lastMarker.value.addTo(map.value);
100
+ actualMarker.value.addTo(map.value);
112
101
  }
113
- };
102
+ }, { immediate: true });
103
+
104
+ watch([() => props.variant, () => props.color, () => props.selected], () => {
105
+ if(!actualMarker.value || !map.value) {
106
+ return;
107
+ }
108
+
109
+ const icon = getMarkerIcon();
110
+ actualMarker.value?.setIcon(icon);
111
+ });
112
+
113
+ watch([() => props.latlng?.lat, () => props.latlng?.lng], () => {
114
+ if(!actualMarker.value || !map.value || !props.latlng) {
115
+ return;
116
+ }
117
+
118
+ actualMarker.value.setLatLng(props.latlng);
119
+ });
114
120
 
115
121
  onMounted(() => {
116
- updateMarker();
122
+ actualMarker.value.on('click', (event: LeafletMouseEvent) => {
123
+ emit('click', event);
124
+ });
117
125
  });
118
126
 
119
127
  onUnmounted(() => {
120
- if(lastMarker.value && map.value) {
128
+ if(actualMarker.value && map.value) {
121
129
  if(markerClusterGroup && markerClusterGroup.value) {
122
- markerClusterGroup.value.removeLayer(lastMarker.value as Marker);
130
+ markerClusterGroup.value.removeLayer(actualMarker.value as Marker);
123
131
  } else {
124
- map.value.removeLayer(lastMarker.value as Marker);
132
+ map.value.removeLayer(actualMarker.value as Marker);
125
133
  }
126
134
  }
127
- lastMarker.value = null;
128
135
  })
129
-
130
- watch([() => props.variant, () => props.color, () => props.latlng?.lat, () => props.latlng?.lng, () => props.selected],
131
- updateMarker,
132
- );
133
136
  }
134
137
  };
135
138
  </script>
@@ -58,27 +58,30 @@ export default {
58
58
  if (!map.value) {
59
59
  return;
60
60
  }
61
+
61
62
  const layers = markerClusterGroup.value.getLayers();
62
- if (layers.length === props.expectedLayers && !added) {
63
- markerClusterGroup.value.addTo(map.value);
64
- added = true;
65
- }
66
63
 
67
64
  if (layers.length === 0 && added) {
68
65
  map.value.removeLayer(markerClusterGroup.value as unknown as L.Layer);
69
66
  added = false;
67
+ return;
70
68
  }
71
-
72
- const bounds = new LatLngBounds([]);
73
- for (const layer of layers as any[]) {
74
- if (layer.getBounds) {
75
- bounds.extend(layer.getBounds());
76
- } else if (layer.getLatLng) {
77
- bounds.extend(layer.getLatLng());
78
- }
69
+ if (layers.length === props.expectedLayers && !added) {
70
+ markerClusterGroup.value.addTo(map.value);
71
+ added = true;
79
72
  }
73
+ if (layers.length === props.expectedLayers) {
74
+ const bounds = new LatLngBounds([]);
75
+ for (const layer of layers as any[]) {
76
+ if (layer.getBounds) {
77
+ bounds.extend(layer.getBounds());
78
+ } else if (layer.getLatLng) {
79
+ bounds.extend(layer.getLatLng());
80
+ }
81
+ }
80
82
 
81
- emit("update:bounds", layers.length > 0 ? bounds : null);
83
+ emit("update:bounds", layers.length > 0 ? bounds : null);
84
+ }
82
85
  };
83
86
 
84
87
  markerClusterGroup.value.on("layeradd", handleLayerChange);
@@ -29,7 +29,7 @@
29
29
  </FSRow>
30
30
  <FSCol
31
31
  v-if="$props.breadcrumbs && $props.breadcrumbs.length > 0"
32
- :padding="$slots.toolbar ? '0px 24px 8px 24px' : '0px 24px'"
32
+ :padding="$slots.toolbar ? '0px 24px 16px 24px' : '0px 24px'"
33
33
  gap="16px"
34
34
  >
35
35
  <FSCol>
@@ -9,6 +9,7 @@
9
9
  >
10
10
  <FSRow
11
11
  gap="24px"
12
+ :height="actualImageSize"
12
13
  :wrap="false"
13
14
  >
14
15
  <template
@@ -54,7 +55,7 @@
54
55
  >
55
56
  <slot
56
57
  name="subtitle"
57
- v-if="topOffset < 60"
58
+ v-if="topOffset < 64"
58
59
  >
59
60
  <FSText
60
61
  v-if="$props.subtitle"
@@ -65,10 +66,11 @@
65
66
  </slot>
66
67
  <slot
67
68
  name="description"
68
- v-if="topOffset < 20"
69
+ v-if="topOffset < 24"
69
70
  >
70
71
  <FSText
71
72
  v-if="$props.description"
73
+ :lineClamp="2"
72
74
  font="text-body"
73
75
  >
74
76
  {{ $props.description }}
@@ -146,9 +148,9 @@ export default defineComponent({
146
148
  default: () => ["124px", "96px", "80px"]
147
149
  },
148
150
  icon: {
149
- type: String as PropType<string>,
151
+ type: String as PropType<string | null>,
150
152
  required: false,
151
- default: "mdi-ab-testing"
153
+ default: null
152
154
  },
153
155
  iconColor: {
154
156
  type: String as PropType<ColorBase>,
@@ -15,7 +15,7 @@
15
15
  <FSRow
16
16
  style="position: sticky; top: 0px; z-index: 3;"
17
17
  :style="{ backgroundColor, marginTop: $props.stickyTitleTopOffset }"
18
- :padding="`24px ${isTouchScreenEnabled ? '24px' : '16px'} 16px 24px`"
18
+ :padding="`16px ${isTouchScreenEnabled ? '20px' : '12px'} 12px 12px`"
19
19
  >
20
20
  <slot
21
21
  name="title"
@@ -29,7 +29,7 @@
29
29
  </FSRow>
30
30
  <FSCol
31
31
  v-if="$props.breadcrumbs && $props.breadcrumbs.length > 0"
32
- :padding="$slots.toolbar ? '0px 24px 8px 24px' : '0px 24px'"
32
+ :padding="`0px ${isTouchScreenEnabled ? '20px' : '12px'} ${$slots.toolbar ? '12px' : '0px'} 12px`"
33
33
  gap="16px"
34
34
  >
35
35
  <FSCol>
@@ -45,7 +45,7 @@
45
45
  <FSRow
46
46
  v-if="$slots.toolbar"
47
47
  :style="stickyToolbar ? `position: sticky; top: ${$props.toolbarTopOffset}; z-index: 3; background-color: ${backgroundColor}` : undefined"
48
- :padding="`0px ${isTouchScreenEnabled ? '24px' : '16px'} 8px 24px`"
48
+ :padding="`0px ${isTouchScreenEnabled ? '20px' : '12px'} 12px 12px`"
49
49
  >
50
50
  <FSSlideGroup>
51
51
  <slot
@@ -58,7 +58,7 @@
58
58
  <FSCol
59
59
  height="fill"
60
60
  gap="0px"
61
- :padding="`${$slots.toolbar ? '8px' : '16px'} ${isTouchScreenEnabled ? '24px' : '16px'} 24px 24px`"
61
+ :padding="`0px ${isTouchScreenEnabled ? '20px' : '12px'} 16px 12px`"
62
62
  >
63
63
  <slot />
64
64
  </FSCol>
@@ -8,7 +8,8 @@
8
8
  #title
9
9
  >
10
10
  <FSRow
11
- gap="24px"
11
+ gap="12px"
12
+ :height="actualImageSize"
12
13
  :wrap="false"
13
14
  >
14
15
  <FSImage
@@ -31,6 +32,7 @@
31
32
  style="min-width: 0"
32
33
  align="center-left"
33
34
  height="fill"
35
+ :gap="$props.subtitle && $props.description ? '6px' : '8px'"
34
36
  >
35
37
  <slot
36
38
  name="title"
@@ -44,26 +46,31 @@
44
46
  name="title-extra"
45
47
  v-bind="{ topOffset }"
46
48
  >
47
- <slot
48
- name="subtitle"
49
+ <FSCol
50
+ gap="4px"
49
51
  >
50
- <FSText
51
- v-if="$props.subtitle && topOffset < 60"
52
- font="text-button"
52
+ <slot
53
+ name="subtitle"
53
54
  >
54
- {{ $props.subtitle }}
55
- </FSText>
56
- </slot>
57
- <slot
58
- name="description"
59
- >
60
- <FSText
61
- v-if="$props.description && topOffset < 20"
62
- font="text-body"
55
+ <FSText
56
+ v-if="$props.subtitle && topOffset < 48"
57
+ font="text-button"
58
+ >
59
+ {{ $props.subtitle }}
60
+ </FSText>
61
+ </slot>
62
+ <slot
63
+ name="description"
63
64
  >
64
- {{ $props.description }}
65
- </FSText>
66
- </slot>
65
+ <FSText
66
+ v-if="$props.description && topOffset < 8"
67
+ :lineClamp="2"
68
+ font="text-body"
69
+ >
70
+ {{ $props.description }}
71
+ </FSText>
72
+ </slot>
73
+ </FSCol>
67
74
  </slot>
68
75
  </slot>
69
76
  </FSCol>
@@ -136,9 +143,9 @@ export default defineComponent({
136
143
  default: () => ["124px", "96px", "80px"]
137
144
  },
138
145
  icon: {
139
- type: String as PropType<string>,
146
+ type: String as PropType<string | null>,
140
147
  required: false,
141
- default: "mdi-ab-testing"
148
+ default: null
142
149
  },
143
150
  iconColor: {
144
151
  type: String as PropType<ColorBase>,
@@ -183,7 +190,7 @@ export default defineComponent({
183
190
  const minSize = sizeToVar(props.minImageSize);
184
191
  const actualMinSize = parseInt(minSize);
185
192
 
186
- topOffset.value = Math.max(0, Math.min(actualScrollTop, actualMinSize + 16 + 24));
193
+ topOffset.value = Math.max(0, Math.min(actualScrollTop, actualMinSize + 16 + 12));
187
194
  }
188
195
 
189
196
  delete slots.title;
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.156",
4
+ "version": "1.0.157-mobile",
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.156",
14
- "@dative-gpi/foundation-shared-services": "1.0.156"
13
+ "@dative-gpi/foundation-shared-domain": "1.0.157-mobile",
14
+ "@dative-gpi/foundation-shared-services": "1.0.157-mobile"
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": "d67f90e266b8ae583f46c82aec2dbd381c5d3629"
38
+ "gitHead": "d47f58fd240a2f085a13ed5880243a5472bf79f9"
39
39
  }
@@ -21,19 +21,19 @@ export const AlertTools = {
21
21
  statusLabel(value: AlertStatus): string {
22
22
  switch (value) {
23
23
  case AlertStatus.Pending:
24
- return $tr('ui.alert-status.pending','Pending');
24
+ return $tr('ui.alert-status.pending', 'Pending');
25
25
  case AlertStatus.Untriggered:
26
- return $tr('ui.alert-status.untriggered','Untriggered');
26
+ return $tr('ui.alert-status.untriggered', 'Untriggered');
27
27
  case AlertStatus.Unresolved:
28
- return $tr('ui.alert-status.unresolved','Unresolved');
28
+ return $tr('ui.alert-status.unresolved', 'Unresolved');
29
29
  case AlertStatus.Resolved:
30
- return $tr('ui.alert-status.resolved','Resolved');
30
+ return $tr('ui.alert-status.resolved', 'Resolved');
31
31
  case AlertStatus.Expired:
32
- return $tr('ui.alert-status.expired','Expired');
32
+ return $tr('ui.alert-status.expired', 'Expired');
33
33
  case AlertStatus.Triggered:
34
- return $tr('ui.alert-status.triggered','Triggered');
34
+ return $tr('ui.alert-status.triggered', 'Triggered');
35
35
  case AlertStatus.Abandoned:
36
- return $tr('ui.alert-status.abandoned','Abandoned');
36
+ return $tr('ui.alert-status.abandoned', 'Abandoned');
37
37
  default: return "";
38
38
  }
39
39
  },
@@ -74,11 +74,43 @@ export const AlertTools = {
74
74
  },
75
75
  criticityLabel(value: Criticity): string {
76
76
  switch (value) {
77
- case Criticity.Warning: return $tr('ui.common.warning','Warning');
78
- case Criticity.Error: return $tr('ui.common.error','Error');
79
- default: return $tr('ui.common.information','Information');
77
+ case Criticity.Warning: return $tr('ui.common.warning', 'Warning');
78
+ case Criticity.Error: return $tr('ui.common.error', 'Error');
79
+ default: return $tr('ui.common.information', 'Information');
80
+ }
81
+ },
82
+ statusColor(status: AlertStatus): ColorEnum {
83
+ switch (status) {
84
+ case AlertStatus.None:
85
+ case AlertStatus.Pending:
86
+ case AlertStatus.Expired:
87
+ return ColorEnum.Warning;
88
+ case AlertStatus.Unresolved:
89
+ case AlertStatus.Triggered:
90
+ return ColorEnum.Error;
91
+ case AlertStatus.Resolved:
92
+ case AlertStatus.Untriggered:
93
+ return ColorEnum.Success;
94
+ default:
95
+ return ColorEnum.Warning;
96
+ }
97
+ },
98
+
99
+ formatValue(value: string) {
100
+ const n = parseFloat(value);
101
+
102
+ if (isNaN(n)) {
103
+ return value;
104
+ }
105
+
106
+ if (Number.isInteger(n)) {
107
+ return n;
108
+ }
109
+ else {
110
+ return n.toFixed(2);
80
111
  }
81
112
  }
113
+
82
114
  }
83
115
 
84
116
  export const prettyDuration = (n: number | undefined) => {