From 58acdd588d5b66f8bcd4171ce01eb48de0d4d1b1 Mon Sep 17 00:00:00 2001 From: rduteil Date: Wed, 9 Oct 2024 10:26:52 +0200 Subject: [PATCH 1/6] Fix message id --- src/Bones.UI/core/eventQueue.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Bones.UI/core/eventQueue.ts b/src/Bones.UI/core/eventQueue.ts index 24ebf2f..fec2709 100644 --- a/src/Bones.UI/core/eventQueue.ts +++ b/src/Bones.UI/core/eventQueue.ts @@ -1,6 +1,8 @@ import _ from "lodash"; import Ajv, { JSONSchemaType, ValidateFunction } from "ajv"; +import { uuidv4 } from "../tools"; + interface WindowsMessage { id: string; topic: string; @@ -55,8 +57,7 @@ export class EventQueue { this.publishInternal(topic, payload); if (window.top && window.top !== window.self) { - this.messageCounter++; - const id = "remote_" + this.messageCounter; + const id = uuidv4(); const message: WindowsMessage = { id, @@ -65,6 +66,7 @@ export class EventQueue { }; this.buffer[this.messageCounter % bufferSize] = message.id; + this.messageCounter++; window.top.postMessage(JSON.stringify(message), "*"); } From b9a1df93b5ee2b793f67c3a95210467289abdb8e Mon Sep 17 00:00:00 2001 From: qschroter Date: Tue, 5 Nov 2024 17:00:45 +0100 Subject: [PATCH 2/6] add subscribe composable factory --- src/Bones.UI/abstractions/inotifyService.ts | 4 +++- src/Bones.UI/core/composableFactory.ts | 21 +++++++++++++++++++ .../services/testUserService.ts | 7 +++++++ 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/Bones.UI/abstractions/inotifyService.ts b/src/Bones.UI/abstractions/inotifyService.ts index 5cacd7b..75a40f5 100644 --- a/src/Bones.UI/abstractions/inotifyService.ts +++ b/src/Bones.UI/abstractions/inotifyService.ts @@ -15,4 +15,6 @@ export type AllEvent = NotifyEvent | "all"; export type AddOrUpdateCallback = (ev: AddOrUpdateEvent, payload: TDetails) => void; export type DeleteCallback = (ev: DeleteEvent, id: any) => void; export type ResetCallback = (ev: ResetEvent) => void; -export type AllCallback = AddOrUpdateCallback | DeleteCallback | ResetCallback; \ No newline at end of file +export type AllCallback = AddOrUpdateCallback | DeleteCallback | ResetCallback; + +export type SubscribeCall = [AddOrUpdateEvent, AddOrUpdateCallback] | [DeleteEvent, DeleteCallback] | [ResetEvent, ResetCallback] | [AllEvent, AllCallback]; \ No newline at end of file diff --git a/src/Bones.UI/core/composableFactory.ts b/src/Bones.UI/core/composableFactory.ts index e9419c7..b2d9aa8 100644 --- a/src/Bones.UI/core/composableFactory.ts +++ b/src/Bones.UI/core/composableFactory.ts @@ -25,6 +25,27 @@ export class ComposableFactory { return ComposableFactory.customRemove(service.remove); } + public static subscribe(service: INotifyService) { + return () => { + let subscribersIds: number[] = []; + + onUnmounted(() => { + subscribersIds.forEach(id => service.unsubscribe(id)); + subscribersIds = []; + }); + + const subscribe: INotifyService["subscribe"] = (ev: any, callback: any) => { + const subscriberId = service.subscribe(ev, callback); + subscribersIds.push(subscriberId); + return subscriberId; + } + + return { + subscribe + } + } + } + public static custom(method: (...args: TArgs) => Promise, applyFactory?: () => (entity: Ref) => void) { return () => { const apply = applyFactory ? applyFactory() : () => { }; diff --git a/tests/Bones.UI.Tests/services/testUserService.ts b/tests/Bones.UI.Tests/services/testUserService.ts index 5b4c9e3..2bb3b96 100644 --- a/tests/Bones.UI.Tests/services/testUserService.ts +++ b/tests/Bones.UI.Tests/services/testUserService.ts @@ -23,6 +23,13 @@ const AccountLoginFactory = new ServiceFactory(testUserServiceFactory); export const useTestUserTrack = ComposableFactory.trackRef(testUserServiceFactory); +export const useTestUserSubscribe = ComposableFactory.subscribe(testUserServiceFactory); + +const { subscribe } = useTestUserSubscribe(); + +subscribe("add", (ev, payload) => { + console.log(ev, payload); +}); export const useLogin = ComposableFactory.custom(AccountLoginFactory.login, () => { const { sync } = useTestUsersSync(); From b414d2470b88b4172f2122c08b71588c64cc08fa Mon Sep 17 00:00:00 2001 From: peyronth Date: Tue, 1 Apr 2025 16:08:03 +0200 Subject: [PATCH 3/6] Fix $tr from useTranslations when having two parameters with the same value --- src/Bones.UI/composables/useTranslations.ts | 4 ++-- tests/Bones.UI.Tests/tests/plugins.test.ts | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 tests/Bones.UI.Tests/tests/plugins.test.ts diff --git a/src/Bones.UI/composables/useTranslations.ts b/src/Bones.UI/composables/useTranslations.ts index c17d411..7ec3d18 100644 --- a/src/Bones.UI/composables/useTranslations.ts +++ b/src/Bones.UI/composables/useTranslations.ts @@ -7,8 +7,8 @@ export function useTranslations() { const $tr = (code: string, defaultValue: string, ...parameters: (string | number)[]): string => { let translation = _translations.value.find(t => t.code === code)?.value ?? defaultValue; if (translation && parameters.length) { - for (let p of parameters) { - translation = translation.replace(`{${parameters.indexOf(p)}}`, p.toString()); + for (let i = 0; i < parameters.length; i++) { + translation = translation.replace(`{${i}}`, parameters[i].toString()); } } return translation; diff --git a/tests/Bones.UI.Tests/tests/plugins.test.ts b/tests/Bones.UI.Tests/tests/plugins.test.ts new file mode 100644 index 0000000..ccd0ea4 --- /dev/null +++ b/tests/Bones.UI.Tests/tests/plugins.test.ts @@ -0,0 +1,21 @@ +import { useTranslations } from '@dative-gpi/bones-ui'; + +describe('Translation plugin', () => { + const { $tr } = useTranslations(); + + it('should return the correct default value with formatted parameter', () => { + const result = $tr('code', 'default value : {0}m', "72"); + expect(result).toBe('default value : 72m'); + }); + + it('should return the correct default value with formatted parameters', () => { + const result = $tr('code', 'default value : {0}m, {1}°C', "72", 85); + expect(result).toBe('default value : 72m, 85°C'); + }); + + it('should return the correct default value with equals formatted parameters', () => { + const result = $tr('code', 'default value : {0}m, {1}°C', "72", "72"); + expect(result).toBe('default value : 72m, 72°C'); + }); +}); + From 1578519e5f163ab43a605434c7381908f3c615d0 Mon Sep 17 00:00:00 2001 From: qschroter Date: Tue, 27 May 2025 13:47:31 +0200 Subject: [PATCH 4/6] add devMode and getAsPost --- src/Bones.UI/composables/useDevMode.ts | 23 +++++++++++++++++++++ src/Bones.UI/composables/useTranslations.ts | 7 +++++++ src/Bones.UI/core/serviceFactory.ts | 17 ++++++++++++--- 3 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 src/Bones.UI/composables/useDevMode.ts diff --git a/src/Bones.UI/composables/useDevMode.ts b/src/Bones.UI/composables/useDevMode.ts new file mode 100644 index 0000000..e4dc391 --- /dev/null +++ b/src/Bones.UI/composables/useDevMode.ts @@ -0,0 +1,23 @@ +import { ref, computed } from "vue"; + +import { EventQueue } from "../core/eventQueue"; + +const devMode = ref(false); + +EventQueue.instance.subscribe('devMode', (_topic: string, payload: boolean) => { + devMode.value = payload; + console.log(`Dev mode is now ${devMode.value ? 'enabled' : 'disabled'}`); +}); + +export function useDevMode() { + const toggleDevMode = () => { + EventQueue.instance.publish('devMode', !devMode.value); + }; + + const isDevMode = computed(() => devMode.value); + + return { + toggleDevMode, + isDevMode + }; +} \ No newline at end of file diff --git a/src/Bones.UI/composables/useTranslations.ts b/src/Bones.UI/composables/useTranslations.ts index c17d411..2a33630 100644 --- a/src/Bones.UI/composables/useTranslations.ts +++ b/src/Bones.UI/composables/useTranslations.ts @@ -1,10 +1,17 @@ import { ref } from 'vue' +import { useDevMode } from './useDevMode'; const _translations = ref<{ code: string, value: string }[]>([]); export function useTranslations() { + const { isDevMode } = useDevMode(); + const $tr = (code: string, defaultValue: string, ...parameters: (string | number)[]): string => { + if (isDevMode.value) { + return code; + } + let translation = _translations.value.find(t => t.code === code)?.value ?? defaultValue; if (translation && parameters.length) { for (let p of parameters) { diff --git a/src/Bones.UI/core/serviceFactory.ts b/src/Bones.UI/core/serviceFactory.ts index 6006535..3c8c680 100644 --- a/src/Bones.UI/core/serviceFactory.ts +++ b/src/Bones.UI/core/serviceFactory.ts @@ -6,6 +6,7 @@ import { INotifyService } from "../abstractions"; export class ServiceFactory { static http: AxiosInstance = axios; + static getAsPost = false; private notifyService: NotifyService; EntityDetails: new (dto: TDetailsDTO) => TDetails; @@ -40,7 +41,17 @@ export class ServiceFactory { const getMany = async (filter?: TFilter) => { const realUrl = typeof url === "string" ? url : url(); - const response = await ServiceFactory.http.get(buildURL(realUrl, filter)); + let response; + + // If the service is configured to use GET as POST to prevent issues with large query strings, + // we send the filter as a POST request with a "_method" parameter to indicate it's a GET request. + if (ServiceFactory.getAsPost && filter) { + response = await ServiceFactory.http.post(buildURL(realUrl, { "_method": "GET" }), filter); + } + else { + response = await ServiceFactory.http.get(buildURL(realUrl, filter)); + } + const dtos: TInfosDTO[] = response.data; return dtos.map(dto => new entity(dto)); @@ -145,8 +156,8 @@ export class ServiceFactory { build(target: T, source1: U, source2: V, source3: W, source4: X): T & U & V & W & X build(target: T, source1: U, source2: V, source3: W, source4: X, source5: Y): T & U & V & W & X & Y build(target: T, source1: U, source2: V, source3: W, source4: X, source5: Y, source6: Z): T & U & V & W & X & Y & Z - build(target: T, source1: U, source2: V, source3: W, source4: X, source5: Y, source6: Z, source7: Z1 ): T & U & V & W & X & Y & Z & Z1 - build(target: T, source1: U, source2: V, source3: W, source4: X, source5: Y, source6: Z, source7: Z1, source8: Z2 ): T & U & V & W & X & Y & Z & Z1 & Z2 + build(target: T, source1: U, source2: V, source3: W, source4: X, source5: Y, source6: Z, source7: Z1): T & U & V & W & X & Y & Z & Z1 + build(target: T, source1: U, source2: V, source3: W, source4: X, source5: Y, source6: Z, source7: Z1, source8: Z2): T & U & V & W & X & Y & Z & Z1 & Z2 build(target: T, source1: U, source2: V, source3: W, source4: X, source5: Y, source6: Z, source7: Z1, source8: Z2, source9: Z3): T & U & V & W & X & Y & Z & Z1 & Z2 & Z3 build(target: T, source1: U, source2: V, source3: W, source4: X, source5: Y, source6: Z, source7: Z1, source8: Z2, source9: Z3, source10: Z4): T & U & V & W & X & Y & Z & Z1 & Z2 & Z3 & Z4 build(target: T, source1: U, source2: V, source3: W, source4: X, source5: Y, source6: Z, source7: Z1, source8: Z2, source9: Z3, source10: Z4, source11: Z5): T & U & V & W & X & Y & Z & Z1 & Z2 & Z3 & Z4 & Z5 From 02afe4060119a0fb07d72cfe51b94933cc6b5493 Mon Sep 17 00:00:00 2001 From: qschroter Date: Tue, 27 May 2025 13:58:44 +0200 Subject: [PATCH 5/6] clean with const parameter --- src/Bones.UI/composables/useDevMode.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Bones.UI/composables/useDevMode.ts b/src/Bones.UI/composables/useDevMode.ts index e4dc391..f36f5d0 100644 --- a/src/Bones.UI/composables/useDevMode.ts +++ b/src/Bones.UI/composables/useDevMode.ts @@ -2,16 +2,17 @@ import { ref, computed } from "vue"; import { EventQueue } from "../core/eventQueue"; +const DEV_MODE_TOPIC = 'devMode'; const devMode = ref(false); -EventQueue.instance.subscribe('devMode', (_topic: string, payload: boolean) => { +EventQueue.instance.subscribe(DEV_MODE_TOPIC, (_topic: string, payload: boolean) => { devMode.value = payload; console.log(`Dev mode is now ${devMode.value ? 'enabled' : 'disabled'}`); }); export function useDevMode() { const toggleDevMode = () => { - EventQueue.instance.publish('devMode', !devMode.value); + EventQueue.instance.publish(DEV_MODE_TOPIC, !devMode.value); }; const isDevMode = computed(() => devMode.value); From bf2dc80b89f30273b6c5dff0376eb1924c84e5b1 Mon Sep 17 00:00:00 2001 From: peyronth Date: Tue, 27 May 2025 14:07:04 +0200 Subject: [PATCH 6/6] Use jsdom to run jest tests --- tests/Bones.UI.Tests/jest.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Bones.UI.Tests/jest.config.js b/tests/Bones.UI.Tests/jest.config.js index 6c9773c..b860027 100644 --- a/tests/Bones.UI.Tests/jest.config.js +++ b/tests/Bones.UI.Tests/jest.config.js @@ -1,5 +1,5 @@ /** @type {import('ts-jest').JestConfigWithTsJest} */ module.exports = { preset: 'ts-jest', - testEnvironment: 'node' + testEnvironment: 'jsdom', }; \ No newline at end of file