@dative-gpi/foundation-shared-services 0.0.230 → 0.1.68

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.
@@ -1,4 +1,4 @@
1
1
  export * from "./useAppLanguageCode";
2
2
  export * from "./useAppLanguages";
3
3
  export * from "./useAppTimeZone";
4
- export * from "./useExtensionJwt";
4
+ export * from "./useAppAuthToken";
@@ -0,0 +1,17 @@
1
+ import { computed, ref } from "vue";
2
+
3
+ const authToken = ref<string | undefined>(undefined);
4
+
5
+ export const useAppAuthToken = () => {
6
+ const setAppAuthToken = (payload: string) => {
7
+ authToken.value = payload;
8
+ };
9
+
10
+ const ready = computed(() => authToken.value !== null);
11
+
12
+ return {
13
+ authToken,
14
+ ready,
15
+ setAppAuthToken
16
+ };
17
+ }
@@ -5,7 +5,7 @@ import { type LanguageInfos } from "@dative-gpi/foundation-shared-domain/models"
5
5
  const languages = ref<LanguageInfos[] | undefined>(undefined);
6
6
 
7
7
  export const useAppLanguages = () => {
8
- const sepAppLanguages = (payload: LanguageInfos[]) => {
8
+ const setAppLanguages = (payload: LanguageInfos[]) => {
9
9
  languages.value = payload;
10
10
  };
11
11
 
@@ -14,6 +14,6 @@ export const useAppLanguages = () => {
14
14
  return {
15
15
  ready,
16
16
  languages,
17
- sepAppLanguages
17
+ setAppLanguages
18
18
  };
19
19
  }
@@ -1,265 +1,56 @@
1
- import { format, subDays, addDays, addMilliseconds, parse } from "date-fns";
2
- import type { Locale } from "date-fns/locale";
3
- import { enUS, enGB, fr, it, es, de } from "date-fns/locale";
4
1
  import { computed, ref } from "vue";
5
2
 
6
- import { useTranslations as useTranslationsProvider } from "@dative-gpi/bones-ui/composables";
7
- import type { TimeZoneInfos } from "@dative-gpi/foundation-shared-domain/models";
8
- import { isoTimeFormat } from "@dative-gpi/foundation-shared-domain/tools";
9
-
10
- import { useAppLanguageCode } from "./useAppLanguageCode";
11
-
12
- const timeZone = ref<TimeZoneInfos | null>(null);
3
+ const timeZone = ref<string | undefined>(undefined);
13
4
 
14
5
  export const useAppTimeZone = () => {
15
- const setAppTimeZone = (payload: TimeZoneInfos) => {
6
+ const setAppTimeZone = (payload: string) => {
16
7
  timeZone.value = payload;
17
8
  };
18
9
 
19
- const getOffsetNumber = (offsetString: string, hours: boolean = false): number => {
20
- let offset = 0;
21
- switch (offsetString.toLowerCase().replaceAll(" ", "")) {
22
- case "utc-11:00:00": offset = -11; break;
23
- case "utc-10:00:00": offset = -10; break;
24
- case "utc-09:00:00": offset = -9; break;
25
- case "utc-08:00:00": offset = -8; break;
26
- case "utc-07:00:00": offset = -7; break;
27
- case "utc-06:00:00": offset = -6; break;
28
- case "utc-05:00:00": offset = -5; break;
29
- case "utc-04:00:00": offset = -4; break;
30
- case "utc-03:00:00": offset = -3; break;
31
- case "utc-02:00:00": offset = -2; break;
32
- case "utc-01:00:00": offset = -1; break;
33
- case "utc+01:00:00": offset = +1; break;
34
- case "utc+02:00:00": offset = +2; break;
35
- case "utc+03:00:00": offset = +3; break;
36
- case "utc+04:00:00": offset = +4; break;
37
- case "utc+05:00:00": offset = +5; break;
38
- case "utc+06:00:00": offset = +6; break;
39
- case "utc+07:00:00": offset = +7; break;
40
- case "utc+08:00:00": offset = +8; break;
41
- case "utc+09:00:00": offset = +9; break;
42
- case "utc+10:00:00": offset = +10; break;
43
- case "utc+11:00:00": offset = +11; break;
44
- case "utc+12:00:00": offset = +12; break;
45
- case "utc+13:00:00": offset = +13; break;
46
- case "utc+14:00:00": offset = +14; break;
47
- }
48
- return hours ? offset : offset * 60 * 60 * 1000;
49
- };
50
-
51
- const userOffset = (): number => {
52
- return getOffsetNumber(getUserOffset());
53
- };
54
-
55
- const machineOffset = (): number => {
56
- return getOffsetNumber(getMachineOffset());
57
- };
58
-
59
- const getUserOffset = (): string => {
60
- return timeZone?.value?.offset ?? "UTC +00:00:00";
61
- };
62
-
63
- const getUserOffsetMillis = (): number => {
64
- const offset = timeZone?.value?.offset.slice(3) ?? "";
65
- const matchData = offset.match(/([+-])(\d+)(?::(\d+))?/);
66
- if (matchData) {
67
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
68
- const [_, sign, hour, minute] = matchData;
69
- return parseInt(sign + "1") * ((hour ? parseInt(hour) : 0) * 60 + (minute ? parseInt(minute) : 0)) * 60 * 1000;
70
- }
71
- return 0;
72
- };
73
-
74
- const getMachineOffset = (): string => {
75
- const timeZoneName = Intl.DateTimeFormat("ia", {
76
- timeZoneName: "short",
77
- timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone
78
- }).formatToParts().find((i) => i.type === "timeZoneName")?.value ?? "";
79
-
80
- const offset = timeZoneName.slice(3);
81
- if (!offset) {
82
- return "UTC +00:00:00";
83
- }
84
- const matchData = offset.match(/([+-])(\d+)(?::(\d+))?/);
85
- if (matchData) {
86
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
87
- const [_, sign, hour, minute] = matchData;
88
- return `UTC ${sign}${hour.padStart(2, "0")}:${(minute ?? "").padStart(2, "0")}:00`;
89
- }
90
- return "UTC +00:00:00";
91
- };
92
-
93
- const getMachineOffsetMillis = (): number => {
94
- const timeZoneName = Intl.DateTimeFormat("ia", {
95
- timeZoneName: "short",
96
- timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone
97
- }).formatToParts().find((i) => i.type === "timeZoneName")?.value ?? "";
98
-
99
- const offset = timeZoneName.slice(3);
100
- if (!offset) {
101
- return 0;
102
- }
103
- const matchData = offset.match(/([+-])(\d+)(?::(\d+))?/);
104
- if (matchData) {
105
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
106
- const [_, sign, hour, minute] = matchData;
107
- return parseInt(sign + "1") * ((hour ? parseInt(hour) : 0) * 60 + (minute ? parseInt(minute) : 0)) * 60 * 1000;
108
- }
109
- return 0;
110
- };
111
-
112
- const todayToEpoch = (resetHours: boolean): number => {
113
- const today = new Date();
114
- if (resetHours) {
115
- today.setHours(0, 0, 0, 0);
116
- }
117
- return today.getTime() + getMachineOffsetMillis() - getUserOffsetMillis();
118
- };
119
-
120
- const pickerToEpoch = (value: Date | null | undefined): number => {
121
- if (value != null) {
122
- // FSCalendar is always in machine time zone, so we need to convert it to user time zone
123
- return value.getTime() + getMachineOffsetMillis() - getUserOffsetMillis();
124
- }
125
- return 0;
126
- };
127
-
128
- const epochToPicker = (value: number | null | undefined): Date => {
129
- const date = new Date(0);
130
- if (value != null) {
131
- // Epoch is always without time zone, so we need to convert it to user time zone
132
- date.setUTCMilliseconds(value - getMachineOffsetMillis() + getUserOffsetMillis());
133
- }
134
- return date;
135
- };
136
-
137
- const epochToPickerHeader = (value: number): { d: number, m: number, y: number } => {
138
- const date = new Date(0);
139
- if (value != null) {
140
- date.setUTCMilliseconds(value - getMachineOffsetMillis() + getUserOffsetMillis());
141
- }
142
- return { d: date.getDate(), m: date.getMonth(), y: date.getFullYear() };
143
- };
144
-
145
- const epochToLongDateFormat = (value: number | null | undefined): string => {
146
- if (value == null || !isFinite(value)) {
147
- return "";
148
- }
149
- const date = new Date(0);
150
- date.setUTCMilliseconds(value - getMachineOffsetMillis() + getUserOffsetMillis());
151
- return format(date, "EEEE dd LLLL yyyy", { locale: getLocale() });
152
- };
153
-
154
- const epochToLongTimeFormat = (value: number | null | undefined): string => {
155
- if (value == null || !isFinite(value)) {
156
- return "";
157
- }
158
- const date = new Date(0);
159
- date.setUTCMilliseconds(value - getMachineOffsetMillis() + getUserOffsetMillis());
160
- return format(date, overrideFormat(date, "EEEE dd LLLL yyyy HH:mm"), { locale: getLocale() })
161
- };
162
-
163
- const epochToShortDateFormat = (value: number | null | undefined): string => {
164
- if (value == null || !isFinite(value)) {
165
- return "";
166
- }
167
- const date = new Date(0);
168
- date.setUTCMilliseconds(value - getMachineOffsetMillis() + getUserOffsetMillis());
169
- switch (getLocale()) {
170
- case enUS: {
171
- return format(date, "MM/dd/yyyy", { locale: getLocale() });
172
- }
173
- default: {
174
- return format(date, "dd/MM/yyyy", { locale: getLocale() });
175
- }
176
- }
177
- };
178
-
179
- const epochToTimeOnlyFormat = (value: number | null | undefined): string => {
180
- if (value == null || !isFinite(value)) {
181
- return "";
182
- }
183
- const date = new Date(0);
184
- date.setUTCMilliseconds(value - getMachineOffsetMillis() + getUserOffsetMillis());
185
- return format(date, "HH:mm:ss", { locale: getLocale() });
186
- };
187
-
188
- const epochToShortTimeFormat = (value: number | null | undefined): string => {
189
- if (value == null || !isFinite(value)) {
190
- return "";
191
- }
192
- const date = new Date(0);
193
- date.setUTCMilliseconds(value - getMachineOffsetMillis() + getUserOffsetMillis());
194
- switch (getLocale()) {
195
- case enUS: {
196
- return format(date, "MM/dd/yyyy HH:mm", { locale: getLocale() });
197
- }
198
- default: {
199
- return format(date, "dd/MM/yyyy HH:mm", { locale: getLocale() });
200
- }
201
- }
202
- };
10
+ const getUserFormatter = (): Intl.DateTimeFormat => {
11
+ return new Intl.DateTimeFormat(undefined, {
12
+ timeZone: timeZone.value || Intl.DateTimeFormat().resolvedOptions().timeZone,
13
+ timeZoneName: "longOffset"
14
+ });
15
+ }
203
16
 
204
- const todayTimeFormat = (): string => {
205
- return `'${useTranslationsProvider().$tr("ui.time-zone.today-at", "Today at").replace(/'/g, "''")}' HH:mm:ss`;
206
- };
17
+ const getMachineFormatter = (): Intl.DateTimeFormat => {
18
+ return new Intl.DateTimeFormat(undefined, {
19
+ timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,
20
+ timeZoneName: "longOffset"
21
+ });
22
+ }
207
23
 
208
- const yesterdayTimeFormat = (): string => {
209
- return `'${useTranslationsProvider().$tr("ui.time-zone.yesterday-at", "Yesterday at").replace(/'/g, "''")}' HH:mm:ss`;
210
- };
24
+ const getUserOffsetName = (): string => {
25
+ const formatter = getUserFormatter();
26
+ const currentDate = formatter.formatToParts(new Date());
27
+ const timeZoneName = currentDate.find((part) => part.type === "timeZoneName")?.value || "UTC+00:00";
28
+ return timeZoneName
29
+ }
211
30
 
212
- const overrideFormat = (date: Date, askedFormat: string): string => {
213
- const now = new Date();
214
- if (date.toDateString() === now.toDateString()) {
215
- return todayTimeFormat();
216
- }
217
- if (date.toDateString() === subDays(now, 1).toDateString()) {
218
- return yesterdayTimeFormat();
219
- }
220
- return askedFormat;
221
- };
31
+ const getUserOffset = (): number => {
32
+ const timeZoneName = getUserOffsetName();
33
+ const [hours, minutes] = timeZoneName.slice(3).split(':');
222
34
 
223
- const getLocale = (): Locale => {
224
- switch (useAppLanguageCode().languageCode.value) {
225
- case "fr-FR": return fr;
226
- case "es-ES": return es;
227
- case "it-IT": return it;
228
- case "en-GB": return enGB;
229
- case "de-DE": return de;
230
- default: return enUS;
231
- }
35
+ return (parseInt(hours) * 60 + parseInt(minutes)) * 60 * 1000;
232
36
  };
233
37
 
234
- const parseForPicker = (value: string, dateFormat: string = isoTimeFormat()): number | null => {
235
- let date = parse(value!, dateFormat, new Date());
236
- date = addMilliseconds(date, userOffset());
237
- if (!isFinite(date.getTime())) {
238
- return null;
239
- }
240
- return date.getTime();
38
+ const getMachineOffsetName = (): string => {
39
+ const formatter = getMachineFormatter();
40
+ const currentDate = formatter.formatToParts(new Date());
41
+ const timeZoneName = currentDate.find((part) => part.type === "timeZoneName")?.value || "UTC+00:00";
42
+ return timeZoneName;
241
43
  };
242
44
 
243
- const formatCurrentForPicker = (daysOffset: number = -1): string => {
244
- let date = new Date();
245
- date.setSeconds(0, 0);
246
- date = addMilliseconds(addDays(date, daysOffset), -machineOffset());
247
- return format(date, isoTimeFormat());
248
- };
45
+ const getMachineOffset = (): number => {
46
+ const timeZoneName = getMachineOffsetName();
47
+ const [hours, minutes] = timeZoneName.slice(3).split(':');
249
48
 
250
- const formatFromPicker = (date: number | null): string => {
251
- if (date != null) {
252
- const epoch = date - machineOffset() + (machineOffset() - userOffset());
253
- return format(epoch, isoTimeFormat());
254
- }
255
- return "";
256
- };
49
+ return (parseInt(hours) * 60 + parseInt(minutes)) * 60 * 1000;
50
+ }
257
51
 
258
- const formatEpochToVariable = (epoch: number | undefined): string => {
259
- if (epoch == null || !isFinite(epoch)) {
260
- return "";
261
- }
262
- return format(epoch - machineOffset(), isoTimeFormat());
52
+ const getOffsetDifference = (): number => {
53
+ return getUserOffset() - getMachineOffset();
263
54
  };
264
55
 
265
56
  const ready = computed(() => timeZone.value !== null);
@@ -269,21 +60,9 @@ export const useAppTimeZone = () => {
269
60
  timeZone,
270
61
  setAppTimeZone,
271
62
  getUserOffset,
63
+ getUserOffsetName,
272
64
  getMachineOffset,
273
- getUserOffsetMillis,
274
- getMachineOffsetMillis,
275
- todayToEpoch,
276
- pickerToEpoch,
277
- epochToPicker,
278
- epochToPickerHeader,
279
- epochToLongDateFormat,
280
- epochToLongTimeFormat,
281
- epochToShortDateFormat,
282
- epochToShortTimeFormat,
283
- epochToTimeOnlyFormat,
284
- parseForPicker,
285
- formatCurrentForPicker,
286
- formatFromPicker,
287
- formatEpochToVariable
65
+ getMachineOffsetName,
66
+ getOffsetDifference,
288
67
  };
289
68
  }
@@ -2,4 +2,5 @@ export * from "./services";
2
2
  export * from "./app";
3
3
 
4
4
  export * from "./useFiles";
5
- export * from "./useFoundationShared";
5
+ export * from "./useFoundationShared";
6
+ export * from "./useDateFormat";
@@ -1,6 +1,7 @@
1
1
  export * from "./useAuthTokens";
2
2
  export * from "./useImages";
3
3
  export * from "./useLanguages";
4
+ export * from "./useNotifications";
4
5
  export * from "./useOrganisations";
5
6
  export * from "./useTerminals";
6
7
  export * from "./useTimeZones";
@@ -1,11 +1,12 @@
1
1
  import { ComposableFactory, ServiceFactory } from "@dative-gpi/bones-ui/core";
2
- import type { BlurHashDTO } from "@dative-gpi/foundation-shared-domain/models";
3
- import { BlurHash } from "@dative-gpi/foundation-shared-domain/models";
2
+ import type { ImageDetailsDTO } from "@dative-gpi/foundation-shared-domain/models";
3
+ import { ImageDetails } from "@dative-gpi/foundation-shared-domain/models";
4
4
 
5
- import { IMAGE_BLURHASH_URL } from "../../config/urls";
5
+ import { IMAGE_URL } from "../../config/urls";
6
6
 
7
- const ImageServiceFactory = {
8
- ...ServiceFactory.addCustom("getBlurHash", (axios, imageId: string) => axios.get(IMAGE_BLURHASH_URL(imageId)), (dto: BlurHashDTO) => new BlurHash(dto))
9
- };
7
+ const ImageServiceFactory = new ServiceFactory<ImageDetailsDTO, ImageDetails>("image", ImageDetails).create(factory => factory.build(
8
+ factory.addGet(IMAGE_URL),
9
+ factory.addNotify()
10
+ ));
10
11
 
11
- export const useImageBlurHash = ComposableFactory.custom(ImageServiceFactory.getBlurHash);
12
+ export const useImage = ComposableFactory.get(ImageServiceFactory);
@@ -0,0 +1,41 @@
1
+ import { type NotificationDetailsDTO, type NotificationFilters, type NotificationInfosDTO } from "@dative-gpi/foundation-shared-domain/models";
2
+ import { NotificationDetails, NotificationInfos } from "@dative-gpi/foundation-shared-domain/models";
3
+ import { ComposableFactory, ServiceFactory } from "@dative-gpi/bones-ui/core";
4
+
5
+ import { HUBS, NOTIFICATION_URL, NOTIFICATIONS_HUB_URL, NOTIFICATIONS_URL } from "../../config";
6
+ import { HubFactory } from "../../tools";
7
+
8
+ const NotificationServiceFactory = new ServiceFactory<NotificationDetailsDTO, NotificationDetails>("notification", NotificationDetails).create(factory => factory.build(
9
+ factory.addGet(NOTIFICATION_URL),
10
+ factory.addGetMany<NotificationInfosDTO, NotificationInfos, NotificationFilters>(NOTIFICATIONS_URL, NotificationInfos),
11
+ factory.addNotify(notifyService => ({
12
+ notifyCreate: (notification: NotificationDetails) => notifyService.notify("add", notification),
13
+ ...ServiceFactory.addCustom("acknowledge", (axios, notificationId: string) => axios.patch(NOTIFICATION_URL(notificationId)), (dto: NotificationDetailsDTO) => {
14
+ const result = new NotificationDetails(dto);
15
+ notifyService.notify("update", result);
16
+ return result;
17
+ })
18
+ }))
19
+ ));
20
+
21
+ const useNotificationsHub = HubFactory.create(NOTIFICATIONS_HUB_URL,
22
+ (connection, { hasWatchers }) => {
23
+ connection.on(HUBS.CREATE_NOTIFICATION, (notificationId: string) => hasWatchers()
24
+ ? NotificationServiceFactory.get(notificationId).then(NotificationServiceFactory.notifyCreate)
25
+ : null);
26
+ },
27
+ async (connection) => {
28
+ await connection.invoke(HUBS.SUBSCRIBE);
29
+ }
30
+ );
31
+
32
+ const useWatchNotifications = HubFactory.createWatcher(useNotificationsHub);
33
+
34
+
35
+ export const useNotifications = ComposableFactory.getMany(NotificationServiceFactory, () => {
36
+ const { watchMany } = useWatchNotifications();
37
+ return () => {
38
+ watchMany();
39
+ }
40
+ });
41
+ export const useAcknowledgeNotification = ComposableFactory.custom(NotificationServiceFactory.acknowledge);
@@ -0,0 +1,220 @@
1
+ import { addMilliseconds, format, parse, subDays } from "date-fns";
2
+
3
+ import { useTranslations as useTranslationsProvider } from "@dative-gpi/bones-ui/composables";
4
+ import { ISO_FORMAT, OPTIONS } from "@dative-gpi/foundation-shared-domain/tools";
5
+
6
+ import { useAppLanguageCode, useAppTimeZone } from "./app/";
7
+
8
+ export const useDateFormat = () => {
9
+ const { $tr } = useTranslationsProvider();
10
+
11
+ const { languageCode } = useAppLanguageCode();
12
+ const { timeZone, getOffsetDifference, getMachineOffset, getUserOffset } = useAppTimeZone();
13
+
14
+ const isEpochToday = (value: number | null | undefined): boolean => {
15
+ if (value == null || !isFinite(value)) {
16
+ return false;
17
+ }
18
+ const date = new Date(value);
19
+ const now = new Date();
20
+ return date.toLocaleString(languageCode.value, { ...OPTIONS.shortDate, timeZone: timeZone.value })
21
+ === now.toLocaleString(languageCode.value, { ...OPTIONS.shortDate, timeZone: timeZone.value });
22
+ }
23
+
24
+ const isEpochYesterday = (value: number | null | undefined): boolean => {
25
+ if (value == null || !isFinite(value)) {
26
+ return false;
27
+ }
28
+ const date = new Date(value);
29
+ const now = new Date();
30
+ return date.toLocaleString(languageCode.value, { ...OPTIONS.shortDate, timeZone: timeZone.value })
31
+ === subDays(now, 1).toLocaleString(languageCode.value, { ...OPTIONS.shortDate, timeZone: timeZone.value });
32
+ }
33
+
34
+ const dayToMillisecond = (value: number): number => {
35
+ return value * 24 * 60 * 60 * 1000
36
+ }
37
+
38
+ const epochToDayMonthLongOnly = (value: number | null | undefined): string => {
39
+ if (value == null || !isFinite(value)) {
40
+ return "";
41
+ }
42
+ const date = new Date(value);
43
+ return date.toLocaleString(languageCode.value, { ...OPTIONS.dayMonthLongOnly, timeZone: timeZone.value });
44
+ }
45
+
46
+ const epochToShortDateFormat = (value: number | null | undefined): string => {
47
+ if (value == null || !isFinite(value)) {
48
+ return "";
49
+ }
50
+ const date = new Date(value);
51
+ return date.toLocaleString(languageCode.value, { ...OPTIONS.shortDate, timeZone: timeZone.value });
52
+ };
53
+
54
+ const epochToLongDateFormat = (value: number | null | undefined): string => {
55
+ if (value == null || !isFinite(value)) {
56
+ return "";
57
+ }
58
+ const date = new Date(value);
59
+ if (isEpochToday(value)) {
60
+ return $tr("ui.time-zone.today", "Today");
61
+ }
62
+ if (isEpochYesterday(value)) {
63
+ return $tr("ui.time-zone.yesterday", "Yesterday");
64
+ }
65
+ const dateString = date.toLocaleString(languageCode.value, { ...OPTIONS.longDate, timeZone: timeZone.value });
66
+ return dateString[0].toLocaleUpperCase() + dateString.slice(1);
67
+ };
68
+
69
+ const epochToShortTimeFormat = (value: number | null | undefined): string => {
70
+ if (value == null || !isFinite(value)) {
71
+ return "";
72
+ }
73
+ const date = new Date(value);
74
+ return date.toLocaleString(languageCode.value, { ...OPTIONS.shortTime, timeZone: timeZone.value });
75
+ };
76
+
77
+ const epochToLocalDayStart = (value: number | null | undefined): number => {
78
+ if (value == null || !isFinite(value)) {
79
+ return 0;
80
+ }
81
+ const date = new Date(value);
82
+ return date.setHours(0, 0, 0, 0);
83
+ }
84
+
85
+ const epochToLocalDayEnd = (value: number | null | undefined): number => {
86
+ if (value == null || !isFinite(value)) {
87
+ return 0;
88
+ }
89
+ const date = new Date(value);
90
+ return date.setHours(23, 59, 59, 999);
91
+ }
92
+
93
+ const epochToLongTimeFormat = (value: number | null | undefined): string => {
94
+ if (value == null || !isFinite(value)) {
95
+ return "";
96
+ }
97
+ const date = new Date(value);
98
+ if (isEpochToday(value)) {
99
+ return `${$tr("ui.time-zone.today-at", "Today at")} ${date.toLocaleString(languageCode.value, { ...OPTIONS.time, timeZone: timeZone.value })}`;
100
+ }
101
+ if (isEpochYesterday(value)) {
102
+ return `${$tr("ui.time-zone.yesterday-at", "Yesterday at")} ${date.toLocaleString(languageCode.value, { ...OPTIONS.time, timeZone: timeZone.value })}`;
103
+ }
104
+ const dateString = date.toLocaleString(languageCode.value, { ...OPTIONS.longTime, timeZone: timeZone.value });
105
+ return dateString[0].toLocaleUpperCase() + dateString.slice(1);
106
+ };
107
+
108
+ const epochToMonthYearOnlyFormat = (value: number | null | undefined): string => {
109
+ if (value == null || !isFinite(value)) {
110
+ return "";
111
+ }
112
+ const date = new Date(value);
113
+ return date.toLocaleString(languageCode.value, { ...OPTIONS.monthYearOnly, timeZone: timeZone.value });
114
+ }
115
+
116
+ const epochToTimeOnlyFormat = (value: number | null | undefined): string => {
117
+ if (value == null || !isFinite(value)) {
118
+ return "";
119
+ }
120
+ const date = new Date(value);
121
+ return date.toLocaleString(languageCode.value, { ...OPTIONS.time, timeZone: timeZone.value });
122
+ };
123
+
124
+ const epochToShortTimeOnlyFormat = (value: number | null | undefined): string => {
125
+ if (value == null || !isFinite(value)) {
126
+ return "";
127
+ }
128
+ const date = new Date(value);
129
+ return date.toLocaleString(languageCode.value, { ...OPTIONS.shortTimeOnly, timeZone: timeZone.value });
130
+ }
131
+
132
+ const epochToWeekNumber = (value: number | null | undefined): string => {
133
+ if (value == null || !isFinite(value)) {
134
+ return "";
135
+ }
136
+ const date = new Date(value);
137
+ date.setHours(0, 0, 0, 0);
138
+ date.setDate(date.getDate() + 3 - (date.getDay() + 6) % 7);
139
+ const week1 = new Date(date.getFullYear(), 0, 4);
140
+ return `${1 + Math.round(((date.getTime() - week1.getTime()) / 86400000 - 3 + (week1.getDay() + 6) % 7) / 7)}`;
141
+ }
142
+
143
+ const todayToEpoch = (): number => {
144
+ return new Date().getTime() + getOffsetDifference();
145
+ };
146
+
147
+ const pickerToEpoch = (value: Date | null | undefined): number => {
148
+ if (value != null) {
149
+ return value.getTime() - getOffsetDifference();
150
+ }
151
+ return 0;
152
+ };
153
+
154
+ const epochToPicker = (value: number | null | undefined): Date => {
155
+ if (value != null) {
156
+ return new Date(value + getOffsetDifference());
157
+ }
158
+ return new Date(0);
159
+ };
160
+
161
+ const epochToPickerHeader = (value: number): { d: number, m: number, y: number } => {
162
+ const date = epochToPicker(value);
163
+ return { d: date.getDate(), m: date.getMonth(), y: date.getFullYear() };
164
+ };
165
+
166
+ const millisecondToDay = (value: number): number => {
167
+ return value / 1000 / 60 / 60 / 24;
168
+ }
169
+
170
+ const todayToPicker = (): string => {
171
+ const date = addMilliseconds(new Date(), -getMachineOffset());
172
+ date.setSeconds(0, 0);
173
+ return format(date, ISO_FORMAT);
174
+ };
175
+
176
+ const yesterdayToPicker = (): string => {
177
+ const date = addMilliseconds(subDays(new Date(), 1), -getMachineOffset());
178
+ date.setSeconds(0, 0);
179
+ return format(date, ISO_FORMAT);
180
+ };
181
+
182
+ const parseForPicker = (value: string, dateFormat: string = ISO_FORMAT): number | null => {
183
+ const date = addMilliseconds(parse(value, dateFormat, new Date()), getUserOffset());
184
+ if (!isFinite(date.getTime())) {
185
+ return null;
186
+ }
187
+ return date.getTime();
188
+ };
189
+
190
+ const epochToISO = (date: number | null): string => {
191
+ if (date != null) {
192
+ return format(date - getMachineOffset(), ISO_FORMAT);
193
+ }
194
+ return "";
195
+ };
196
+
197
+ return {
198
+ todayToEpoch,
199
+ pickerToEpoch,
200
+ dayToMillisecond,
201
+ epochToDayMonthLongOnly,
202
+ epochToPicker,
203
+ epochToPickerHeader,
204
+ epochToLocalDayStart,
205
+ epochToLocalDayEnd,
206
+ epochToLongDateFormat,
207
+ epochToLongTimeFormat,
208
+ epochToMonthYearOnlyFormat,
209
+ epochToShortDateFormat,
210
+ epochToShortTimeFormat,
211
+ epochToShortTimeOnlyFormat,
212
+ epochToTimeOnlyFormat,
213
+ epochToWeekNumber,
214
+ millisecondToDay,
215
+ parseForPicker,
216
+ todayToPicker,
217
+ yesterdayToPicker,
218
+ epochToISO
219
+ };
220
+ }
package/config/index.ts CHANGED
@@ -1 +1,2 @@
1
+ export * from "./literals";
1
2
  export * from "./urls";
@@ -0,0 +1,16 @@
1
+ export const SUBSCRIBE = "Subscribe";
2
+ export const UNSUBSCRIBE = "Unsubscribe";
3
+
4
+ export const UPDATE_DEVICE_STATUS = "UpdateDeviceStatus";
5
+
6
+ export const UPDATE_DEVICE_CONNECTIVITY = "UpdateDeviceConnectivity";
7
+
8
+ export const CREATE_ALERT = "CreateAlert";
9
+ export const UPDATE_ALERT = "UpdateAlert";
10
+ export const REMOVE_ALERT = "RemoveAlert";
11
+
12
+ export const CREATE_CONNECTIVITY_ALERT = "CreateConnectivityAlert";
13
+ export const UPDATE_CONNECTIVITY_ALERT = "UpdateConnectivityAlert";
14
+ export const REMOVE_CONNECTIVITY_ALERT = "RemoveConnectivityAlert";
15
+
16
+ export const CREATE_NOTIFICATION = "CreateNotification";
@@ -0,0 +1 @@
1
+ export * as HUBS from "./hubs";
@@ -1 +1,3 @@
1
- export const GATEWAY_URL = () => "/api/foundation/shared/v1";
1
+ export const GATEWAY_URL = () => "/api/foundation/shared/v1";
2
+
3
+ export const HUBS_URL = () => "/api/foundation/hubs/v1";
@@ -2,12 +2,18 @@ import { GATEWAY_URL } from "./base";
2
2
 
3
3
  export const IMAGES_URL = () => `${GATEWAY_URL()}/images`;
4
4
 
5
- export const IMAGES_RAW_URL = () => `${IMAGES_URL()}/raw`;
6
- export const IMAGE_RAW_URL = (imageId: string) => `${IMAGES_RAW_URL()}/${encodeURIComponent(imageId)}`;
7
- export const IMAGE_RAW_EXTENSION_URL = (imageId: string, jwt: string) => `${IMAGE_RAW_URL(imageId)}?access_token=${jwt}`;
8
-
9
- export const IMAGES_THUMBNAIL_URL = () => `${IMAGES_URL()}/thumbnail`;
10
- export const IMAGE_THUMBNAIL_URL = (imageId: string) => `${IMAGES_THUMBNAIL_URL()}/${encodeURIComponent(imageId)}`;
11
-
12
- export const IMAGES_BLURHASH_URL = () => `${IMAGES_URL()}/blurHash`;
13
- export const IMAGE_BLURHASH_URL = (imageId: string) => `${IMAGES_BLURHASH_URL()}/${encodeURIComponent(imageId)}`;
5
+ export const IMAGE_URL = (imageId: string) => `${IMAGES_URL()}/${encodeURIComponent(imageId)}`;
6
+ export const IMAGE_RAW_URL = (imageId: string, accessToken?: string) => {
7
+ let url = `${IMAGE_URL(imageId)}/raw`;
8
+ if (accessToken) {
9
+ url += `?access_token=${encodeURIComponent(accessToken)}`;
10
+ }
11
+ return url;
12
+ };
13
+ export const IMAGE_THUMBNAIL_URL = (imageId: string, accessToken?: string) => {
14
+ let url = `${IMAGE_URL(imageId)}/thumbnail`;
15
+ if (accessToken) {
16
+ url += `?access_token=${encodeURIComponent(accessToken)}`;
17
+ }
18
+ return url;
19
+ };
@@ -2,6 +2,7 @@ export * from "./authTokens";
2
2
  export * from "./files";
3
3
  export * from "./images";
4
4
  export * from "./languages";
5
+ export * from "./notifications";
5
6
  export * from "./organisations";
6
7
  export * from "./terminals";
7
8
  export * from "./timeZones";
@@ -0,0 +1,6 @@
1
+ import { GATEWAY_URL, HUBS_URL } from "./base";
2
+
3
+ export const NOTIFICATIONS_URL = () => `${GATEWAY_URL()}/notifications`;
4
+ export const NOTIFICATION_URL = (notificationId: string) => `${GATEWAY_URL()}/notifications/${notificationId}`;
5
+
6
+ export const NOTIFICATIONS_HUB_URL = () => `${HUBS_URL()}/notifications`;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@dative-gpi/foundation-shared-services",
3
3
  "sideEffects": false,
4
- "version": "0.0.230",
4
+ "version": "0.1.68",
5
5
  "description": "",
6
6
  "publishConfig": {
7
7
  "access": "public"
@@ -10,7 +10,7 @@
10
10
  "author": "",
11
11
  "license": "ISC",
12
12
  "dependencies": {
13
- "@dative-gpi/foundation-shared-domain": "0.0.230"
13
+ "@dative-gpi/foundation-shared-domain": "0.1.68"
14
14
  },
15
15
  "peerDependencies": {
16
16
  "@dative-gpi/bones-ui": "^0.0.75",
@@ -18,5 +18,5 @@
18
18
  "vue": "^3.4.29",
19
19
  "vue-router": "^4.3.0"
20
20
  },
21
- "gitHead": "93365f65d39d6c9cc3821ffb48cba187200deaf9"
21
+ "gitHead": "fa2ed7031088f422751fc1d939f2fbe168ae0596"
22
22
  }
@@ -28,7 +28,12 @@ export class HubFactory {
28
28
  })
29
29
  }
30
30
  if (connection.state !== signalR.HubConnectionState.Connected) {
31
- await connection.start();
31
+ try {
32
+ await connection.start();
33
+ }
34
+ catch {
35
+ return;
36
+ }
32
37
  }
33
38
  if (!subscribed) {
34
39
  await init(connection);
package/tools/index.ts CHANGED
@@ -1 +1,2 @@
1
- export * from "./hubFactory";
1
+ export * from "./hubFactory";
2
+ export * from "./translate";
@@ -0,0 +1,17 @@
1
+ import { useAppLanguageCode } from "../composables";
2
+
3
+ export const translate = <TTranslation extends { languageCode: string }>(
4
+ translations: TTranslation[],
5
+ accessor: (item: TTranslation) => string,
6
+ defaultValue: string): string => {
7
+
8
+ const { languageCode } = useAppLanguageCode();
9
+
10
+ if(!languageCode.value) {
11
+ return defaultValue;
12
+ }
13
+
14
+ const translation = translations.find(t => t.languageCode === languageCode.value);
15
+
16
+ return translation ? accessor(translation) : defaultValue;
17
+ }
@@ -1,17 +0,0 @@
1
- import { computed, ref } from "vue";
2
-
3
- const jwt = ref<string | undefined>(undefined);
4
-
5
- export const useExtensionJwt = () => {
6
- const setExtensionJwt = (payload: string) => {
7
- jwt.value = payload;
8
- };
9
-
10
- const ready = computed(() => jwt.value !== null);
11
-
12
- return {
13
- jwt,
14
- ready,
15
- setExtensionJwt
16
- };
17
- }