@vc-shell/framework 1.1.8 → 1.1.10

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 (41) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/core/composables/index.ts +1 -0
  3. package/core/composables/useDynamicProperties/index.ts +344 -0
  4. package/core/services/toolbar-service.ts +28 -18
  5. package/core/services/widget-service.ts +30 -20
  6. package/dist/core/composables/index.d.ts +1 -0
  7. package/dist/core/composables/index.d.ts.map +1 -1
  8. package/dist/core/composables/useDynamicProperties/index.d.ts +54 -0
  9. package/dist/core/composables/useDynamicProperties/index.d.ts.map +1 -0
  10. package/dist/core/services/toolbar-service.d.ts.map +1 -1
  11. package/dist/core/services/widget-service.d.ts +2 -2
  12. package/dist/core/services/widget-service.d.ts.map +1 -1
  13. package/dist/framework.js +19 -18
  14. package/dist/{index-BeE65IDG.js → index-B--OcPUC.js} +1 -1
  15. package/dist/{index-DjGE0Oe5.js → index-BIsysa10.js} +1 -1
  16. package/dist/{index-BSMDwAsD.js → index-BRZPSFE2.js} +1 -1
  17. package/dist/{index-cAxs8v2c.js → index-BXgd9ZaL.js} +1 -1
  18. package/dist/{index-CcUXsEpB.js → index-CI6QfkN3.js} +1 -1
  19. package/dist/{index-nY-vksAs.js → index-ChYHar7m.js} +1 -1
  20. package/dist/{index-CM-cQwyJ.js → index-CnJXGndQ.js} +1 -1
  21. package/dist/{index-BcE8cPQ1.js → index-D2LH2BNS.js} +1 -1
  22. package/dist/{index-BjulAuhE.js → index-D9EWvMeh.js} +1 -1
  23. package/dist/{index-BRzLUR4F.js → index-DMRpdHXp.js} +1 -1
  24. package/dist/{index-83AS8awQ.js → index-DWRHtYyK.js} +23081 -22902
  25. package/dist/{index-DkbufypA.js → index-FldC5gs9.js} +1 -1
  26. package/dist/{index-C1julODM.js → index-ezL0teRD.js} +1 -1
  27. package/dist/{index-BdXB4Rc2.js → index-kAPaQznk.js} +1 -1
  28. package/dist/{index-CCh6DcPw.js → index-oltQZrqH.js} +1 -1
  29. package/dist/{index-VBkCq_SK.js → index-slurPVW3.js} +1 -1
  30. package/dist/{index-D77dHT9M.js → index-zSXR4JKy.js} +1 -1
  31. package/dist/tsconfig.tsbuildinfo +1 -1
  32. package/dist/ui/components/organisms/vc-blade/_internal/vc-blade-widget-container/_internal/vc-widget-container-desktop.vue.d.ts +1 -0
  33. package/dist/ui/components/organisms/vc-blade/_internal/vc-blade-widget-container/_internal/vc-widget-container-desktop.vue.d.ts.map +1 -1
  34. package/dist/ui/components/organisms/vc-blade/_internal/vc-blade-widget-container/_internal/vc-widget-container-mobile.vue.d.ts.map +1 -1
  35. package/dist/ui/components/organisms/vc-blade/_internal/vc-blade-widget-container/vc-widget-container.vue.d.ts.map +1 -1
  36. package/package.json +4 -4
  37. package/shared/components/blade-navigation/components/vc-blade-view/vc-blade-view.ts +1 -1
  38. package/ui/components/organisms/vc-blade/_internal/vc-blade-toolbar/vc-blade-toolbar.vue +1 -1
  39. package/ui/components/organisms/vc-blade/_internal/vc-blade-widget-container/_internal/vc-widget-container-desktop.vue +2 -0
  40. package/ui/components/organisms/vc-blade/_internal/vc-blade-widget-container/_internal/vc-widget-container-mobile.vue +1 -0
  41. package/ui/components/organisms/vc-blade/_internal/vc-blade-widget-container/vc-widget-container.vue +4 -3
package/CHANGELOG.md CHANGED
@@ -1,3 +1,16 @@
1
+ ## [1.1.10](https://github.com/VirtoCommerce/vc-shell/compare/v1.1.9...v1.1.10) (2025-05-22)
2
+
3
+
4
+ ### Features
5
+
6
+ * **dynamic-properties:** add useDynamicProperties composable for managing dynamic property values and dictionaries ([5af9e0b](https://github.com/VirtoCommerce/vc-shell/commit/5af9e0bd27dd9930589166e17ef234fd8dae5998))
7
+
8
+
9
+
10
+ ## [1.1.9](https://github.com/VirtoCommerce/vc-shell/compare/v1.1.8...v1.1.9) (2025-05-15)
11
+
12
+
13
+
1
14
  ## [1.1.8](https://github.com/VirtoCommerce/vc-shell/compare/v1.1.7...v1.1.8) (2025-05-15)
2
15
 
3
16
 
@@ -19,3 +19,4 @@ export * from "./useDashboard";
19
19
  export * from "./useAppBarWidget";
20
20
  export * from "./useSettingsMenu";
21
21
  export * from "./useToolbar";
22
+ export * from "./useDynamicProperties";
@@ -0,0 +1,344 @@
1
+ import { useLoading } from "../useLoading";
2
+ import { useAsync } from "../useAsync";
3
+ import * as _ from "lodash-es";
4
+ import { ComputedRef } from "vue";
5
+
6
+ // Base interfaces that can be extended by specific API client types
7
+ export interface IBaseProperty<TPropertyValue> {
8
+ id?: string | null;
9
+ name?: string | null;
10
+ values?: TPropertyValue[] | null;
11
+ multilanguage?: boolean | null;
12
+ multivalue?: boolean | null;
13
+ dictionary?: boolean | null;
14
+ valueType?: string | null; // Consider using a more specific enum if possible
15
+ }
16
+
17
+ export interface IBasePropertyValue {
18
+ propertyName?: string | null;
19
+ propertyId?: string | null;
20
+ languageCode?: string | null;
21
+ alias?: string | null;
22
+ valueType?: string | null;
23
+ value?: any; // eslint-disable-line @typescript-eslint/no-explicit-any
24
+ valueId?: string | null;
25
+ isInherited?: boolean;
26
+ }
27
+
28
+ export interface IBasePropertyDictionaryItem {
29
+ id?: string | null;
30
+ propertyId?: string | null;
31
+ alias?: string | null;
32
+ localizedValues?: { languageCode?: string | null; value?: string | null }[] | null;
33
+ value?: string;
34
+ }
35
+
36
+ export interface IBasePropertyDictionaryItemSearchCriteria {
37
+ propertyIds?: string[] | null;
38
+ keyword?: string | null;
39
+ skip?: number | null;
40
+ take?: number | null;
41
+ }
42
+
43
+ export interface IUseDynamicProperties<
44
+ TProperty extends IBaseProperty<TPropertyValue>,
45
+ TPropertyValue extends IBasePropertyValue,
46
+ TPropertyDictionaryItem extends IBasePropertyDictionaryItem,
47
+ TPropertyDictionaryItemSearchCriteria extends IBasePropertyDictionaryItemSearchCriteria,
48
+ > {
49
+ loading: ComputedRef<boolean>;
50
+ loadDictionaries: (
51
+ propertyId: string,
52
+ keyword?: string,
53
+ locale?: string,
54
+ ) => Promise<TPropertyDictionaryItem[] | undefined>;
55
+ getPropertyValue: (
56
+ property: TProperty,
57
+ locale: string,
58
+ ) => string | TPropertyValue[] | (TPropertyDictionaryItem & { value: string })[];
59
+ setPropertyValue: (data: {
60
+ property: TProperty;
61
+ value: string | TPropertyValue[] | (TPropertyDictionaryItem & { value: string })[];
62
+ dictionary?: TPropertyDictionaryItem[];
63
+ locale?: string;
64
+ initialProp?: TProperty;
65
+ }) => void;
66
+ }
67
+
68
+ function isEmptyValues(value: unknown) {
69
+ return (
70
+ value === undefined ||
71
+ value === null ||
72
+ (typeof value === "number" && isNaN(value)) ||
73
+ (typeof value === "object" && Object.keys(value).length === 0) ||
74
+ (typeof value === "string" && value.trim().length === 0)
75
+ );
76
+ }
77
+
78
+ export const useDynamicProperties = <
79
+ TProperty extends IBaseProperty<TPropertyValue>,
80
+ TPropertyValue extends IBasePropertyValue,
81
+ TPropertyDictionaryItem extends IBasePropertyDictionaryItem,
82
+ TPropertyDictionaryItemSearchCriteria extends IBasePropertyDictionaryItemSearchCriteria,
83
+ >(
84
+ searchDictionaryItemsFunction: (
85
+ criteria: TPropertyDictionaryItemSearchCriteria,
86
+ ) => Promise<TPropertyDictionaryItem[] | undefined>,
87
+ PropertyValueConstructor: new (data?: Partial<TPropertyValue>) => TPropertyValue,
88
+ PropertyDictionaryItemConstructor: new (data?: Partial<TPropertyDictionaryItem>) => TPropertyDictionaryItem,
89
+ ): IUseDynamicProperties<TProperty, TPropertyValue, TPropertyDictionaryItem, TPropertyDictionaryItemSearchCriteria> => {
90
+ const { loading: dictionaryItemsLoading, action: searchDictionaryItems } = useAsync<
91
+ TPropertyDictionaryItemSearchCriteria,
92
+ TPropertyDictionaryItem[] | undefined
93
+ >(async (args: TPropertyDictionaryItemSearchCriteria | undefined) => {
94
+ if (args === undefined) {
95
+ return undefined;
96
+ }
97
+ return await searchDictionaryItemsFunction(args);
98
+ });
99
+
100
+ function getPropertyValue(property: TProperty, locale: string) {
101
+ if (property.multilanguage) {
102
+ const propValue = property.values?.find((x) => x.languageCode == locale);
103
+
104
+ if (property.multivalue) {
105
+ return property.values?.filter((x) => x.languageCode === locale) as TPropertyValue[];
106
+ } else if (!propValue) {
107
+ const aliasProp = property.values?.find((x) => x.propertyId === property.id);
108
+
109
+ if (aliasProp) {
110
+ property.values?.push(
111
+ new PropertyValueConstructor({
112
+ propertyName: property.name,
113
+ propertyId: property.id,
114
+ languageCode: locale,
115
+ alias: aliasProp?.alias,
116
+ valueType: property.valueType,
117
+ valueId: aliasProp?.valueId,
118
+ } as unknown as Partial<TPropertyValue>),
119
+ );
120
+ }
121
+ }
122
+
123
+ if (property.dictionary) {
124
+ return (propValue && propValue?.valueId) as string;
125
+ }
126
+ return propValue?.value as string;
127
+ } else {
128
+ if (property.multivalue) {
129
+ return property.values as TPropertyValue[];
130
+ }
131
+ if (property.dictionary) {
132
+ return property.values?.[0]?.valueId as string;
133
+ }
134
+ return property.values?.[0]?.value as string;
135
+ }
136
+ }
137
+
138
+ async function loadDictionaries(propertyId: string, keyword?: string, locale?: string) {
139
+ if (propertyId) {
140
+ let dictionaryItems = await searchDictionaryItems({
141
+ propertyIds: [propertyId],
142
+ keyword,
143
+ skip: 0,
144
+ } as TPropertyDictionaryItemSearchCriteria);
145
+ if (locale) {
146
+ dictionaryItems = dictionaryItems?.map((x: TPropertyDictionaryItem) => {
147
+ const localizedValue = x.localizedValues?.find(
148
+ (v: { languageCode?: string | null; value?: string | null }) => v.languageCode == locale,
149
+ )?.value;
150
+ return Object.assign(new PropertyDictionaryItemConstructor(x), {
151
+ value: localizedValue ?? x.alias,
152
+ });
153
+ });
154
+ }
155
+ return dictionaryItems;
156
+ }
157
+ }
158
+
159
+ function setPropertyValue(data: {
160
+ property: TProperty;
161
+ value: string | TPropertyValue[] | (TPropertyDictionaryItem & { value: string })[];
162
+ dictionary?: TPropertyDictionaryItem[];
163
+ locale?: string;
164
+ initialProp?: TProperty;
165
+ }) {
166
+ const { property, value, dictionary, locale } = data;
167
+
168
+ if (dictionary && dictionary.length > 0) {
169
+ const dict = dictionary.map((x) => new PropertyDictionaryItemConstructor(x));
170
+ if (property.multilanguage) {
171
+ // Multivalue Dictionary Multilanguage
172
+ if (Array.isArray(value)) {
173
+ property.values = (value as (TPropertyDictionaryItem & { value: string })[]).flatMap((item) => {
174
+ const dictItem = dict.find((x) => x.id === (item as unknown as TPropertyValue).valueId || x.id === item.id);
175
+ if (dictItem?.localizedValues?.length) {
176
+ return dictItem.localizedValues.map(
177
+ (x) =>
178
+ new PropertyValueConstructor({
179
+ propertyId: dictItem.propertyId,
180
+ alias: dictItem.alias,
181
+ languageCode: x.languageCode,
182
+ value: x.value ?? dictItem.alias,
183
+ valueId: dictItem.id,
184
+ } as unknown as Partial<TPropertyValue>),
185
+ );
186
+ }
187
+ return new PropertyValueConstructor(item as unknown as Partial<TPropertyValue>);
188
+ });
189
+ }
190
+ // Single value Dictionary Multilanguage
191
+ else {
192
+ const dictionaryItem = dictionary.find((x) => x.id === (value as string));
193
+ if (dictionaryItem) {
194
+ property.values = dictionaryItem?.localizedValues?.map(
195
+ (x) =>
196
+ new PropertyValueConstructor({
197
+ propertyId: dictionaryItem.propertyId,
198
+ alias: dictionaryItem.alias,
199
+ languageCode: x.languageCode,
200
+ value: x.value ?? dictionaryItem.alias,
201
+ valueId: dictionaryItem.id,
202
+ } as unknown as Partial<TPropertyValue>),
203
+ );
204
+ } else {
205
+ property.values = [];
206
+ }
207
+ }
208
+ } else {
209
+ // Multivalue Dictionary
210
+ if (Array.isArray(value)) {
211
+ property.values = (value as (TPropertyDictionaryItem & { value: string })[]).flatMap((item) => {
212
+ const dictItem = dict.find((x) => x.id === (item as unknown as TPropertyValue).valueId || x.id === item.id);
213
+ if (dictItem) {
214
+ return new PropertyValueConstructor({
215
+ propertyId: dictItem.propertyId,
216
+ alias: dictItem.alias,
217
+ value: item.value ?? dictItem.alias,
218
+ valueId: dictItem.id,
219
+ } as unknown as Partial<TPropertyValue>);
220
+ }
221
+ return new PropertyValueConstructor(item as unknown as Partial<TPropertyValue>);
222
+ });
223
+ }
224
+ // Single value Dictionary
225
+ else {
226
+ const dictionaryItem = dictionary.find((x) => x.id === (value as string));
227
+
228
+ if (isEmptyValues(value)) {
229
+ property.values = [];
230
+ } else {
231
+ property.values = [
232
+ new PropertyValueConstructor({
233
+ propertyId: dictionaryItem?.propertyId,
234
+ alias: dictionaryItem?.alias,
235
+ value: (dictionaryItem as TPropertyDictionaryItem & { value: string })?.value ?? dictionaryItem?.alias,
236
+ valueId: value as string,
237
+ } as unknown as Partial<TPropertyValue>),
238
+ ];
239
+ }
240
+ }
241
+ }
242
+ } else {
243
+ if (property.multilanguage) {
244
+ // Multivalue Multilanguage
245
+ if (Array.isArray(value)) {
246
+ property.values =
247
+ property.values &&
248
+ ([
249
+ ...property.values.filter((x) => x.languageCode !== locale),
250
+ ...(value as TPropertyValue[]).map(
251
+ (item) =>
252
+ new PropertyValueConstructor({ ...item, languageCode: locale } as unknown as Partial<TPropertyValue>),
253
+ ),
254
+ ] as TPropertyValue[]);
255
+ }
256
+ // Single value Multilanguage
257
+ else {
258
+ const propValue = property.values?.find((x) => x.languageCode == locale);
259
+ if (propValue) {
260
+ propValue.value = value as string;
261
+ } else {
262
+ property.values = [
263
+ new PropertyValueConstructor({
264
+ value: value as string,
265
+ isInherited: false,
266
+ languageCode: locale,
267
+ } as unknown as Partial<TPropertyValue>),
268
+ ];
269
+ }
270
+ }
271
+ } else {
272
+ // Multivalue
273
+ if (Array.isArray(value)) {
274
+ property.values = (value as TPropertyValue[]).map(
275
+ (item) => new PropertyValueConstructor(item as unknown as Partial<TPropertyValue>),
276
+ );
277
+ }
278
+ // Single value
279
+ else {
280
+ if (typeof value === "boolean") {
281
+ if (data.initialProp?.values?.length) {
282
+ property.values = [
283
+ property.values?.[0]
284
+ ? Object.assign(property.values[0], { value })
285
+ : new PropertyValueConstructor({
286
+ value: value,
287
+ isInherited: false,
288
+ } as unknown as Partial<TPropertyValue>),
289
+ ];
290
+ } else {
291
+ if (value) {
292
+ property.values = [
293
+ new PropertyValueConstructor({
294
+ value: value,
295
+ isInherited: false,
296
+ } as unknown as Partial<TPropertyValue>),
297
+ ];
298
+ } else {
299
+ property.values = [];
300
+ }
301
+ }
302
+ } else if (isEmptyValues(value)) {
303
+ // Ensure we create an empty PropertyValue if the original value was also empty, to signify an explicit clear.
304
+ // Otherwise, if there was a value and now it's empty, we clear the values array.
305
+ const hadOriginalValue = data.initialProp?.values?.find((v) =>
306
+ property.multilanguage ? v.languageCode === locale : true,
307
+ )?.value;
308
+ const originalValueWasEmpty = isEmptyValues(hadOriginalValue);
309
+
310
+ if (originalValueWasEmpty) {
311
+ property.values = [
312
+ new PropertyValueConstructor({
313
+ value: value as string,
314
+ isInherited: false,
315
+ languageCode: property.multilanguage ? locale : undefined,
316
+ } as unknown as Partial<TPropertyValue>),
317
+ ];
318
+ } else {
319
+ property.values = [];
320
+ }
321
+ } else {
322
+ property.values = property.values?.[0]
323
+ ? [Object.assign(property.values[0], { value: value as string })]
324
+ : [
325
+ new PropertyValueConstructor({
326
+ value: value as string,
327
+ isInherited: false,
328
+ } as unknown as Partial<TPropertyValue>),
329
+ ];
330
+ }
331
+ }
332
+ }
333
+ }
334
+ }
335
+
336
+ const loading = useLoading(dictionaryItemsLoading);
337
+
338
+ return {
339
+ loading,
340
+ loadDictionaries,
341
+ getPropertyValue,
342
+ setPropertyValue,
343
+ };
344
+ };
@@ -38,7 +38,8 @@ const preregisteredIds = new Set<string>();
38
38
  * Registers a toolbar button before the service is initialized
39
39
  */
40
40
  export function registerToolbarItem(toolbarItem: IToolbarItem, bladeId: string): void {
41
- preregisteredToolbarItems.push({ bladeId, toolbarItem });
41
+ const normalizedBladeId = bladeId.toLowerCase();
42
+ preregisteredToolbarItems.push({ bladeId: normalizedBladeId, toolbarItem });
42
43
  preregisteredIds.add(toolbarItem.id);
43
44
  }
44
45
 
@@ -48,14 +49,16 @@ export function createToolbarService(): IToolbarService {
48
49
  const registeredIds = reactive(new Set<string>());
49
50
 
50
51
  const registerToolbarItem = (toolbarItem: IToolbarItem, bladeId: string): void => {
51
- if (!toolbarRegistry[bladeId]) {
52
- toolbarRegistry[bladeId] = [];
52
+ const normalizedBladeId = bladeId.toLowerCase();
53
+
54
+ if (!toolbarRegistry[normalizedBladeId]) {
55
+ toolbarRegistry[normalizedBladeId] = [];
53
56
  }
54
57
 
55
- const existingIndex = toolbarRegistry[bladeId].findIndex((t) => t.id === toolbarItem.id);
58
+ const existingIndex = toolbarRegistry[normalizedBladeId].findIndex((t) => t.id === toolbarItem.id);
56
59
  if (existingIndex === -1) {
57
- toolbarRegistry[bladeId].push(reactive(toolbarItem));
58
- registeredToolbarItems.push({ bladeId, toolbarItem: reactive(toolbarItem) });
60
+ toolbarRegistry[normalizedBladeId].push(reactive(toolbarItem));
61
+ registeredToolbarItems.push({ bladeId: normalizedBladeId, toolbarItem: reactive(toolbarItem) });
59
62
  registeredIds.add(toolbarItem.id);
60
63
  }
61
64
  };
@@ -69,25 +72,29 @@ export function createToolbarService(): IToolbarService {
69
72
  bladeId: string;
70
73
  toolbarItem: Partial<IToolbarItem>;
71
74
  }): void => {
72
- if (toolbarRegistry[bladeId]) {
73
- const index = toolbarRegistry[bladeId].findIndex((t) => t.id === id);
75
+ const normalizedBladeId = bladeId.toLowerCase();
76
+
77
+ if (toolbarRegistry[normalizedBladeId]) {
78
+ const index = toolbarRegistry[normalizedBladeId].findIndex((t) => t.id === id);
74
79
  if (index !== -1) {
75
- toolbarRegistry[bladeId][index] = { ...toolbarRegistry[bladeId][index], ...toolbarItem };
80
+ toolbarRegistry[normalizedBladeId][index] = { ...toolbarRegistry[normalizedBladeId][index], ...toolbarItem };
76
81
  }
77
82
  }
78
83
  };
79
84
 
80
85
  const unregisterToolbarItem = (toolbarItemId: string, bladeId: string): void => {
81
- if (toolbarRegistry[bladeId]) {
82
- const index = toolbarRegistry[bladeId].findIndex((t) => t.id === toolbarItemId);
86
+ const normalizedBladeId = bladeId.toLowerCase();
87
+
88
+ if (toolbarRegistry[normalizedBladeId]) {
89
+ const index = toolbarRegistry[normalizedBladeId].findIndex((t) => t.id === toolbarItemId);
83
90
  if (index !== -1) {
84
- toolbarRegistry[bladeId].splice(index, 1);
91
+ toolbarRegistry[normalizedBladeId].splice(index, 1);
85
92
  registeredIds.delete(toolbarItemId);
86
93
  }
87
94
  }
88
95
 
89
96
  const regIndex = registeredToolbarItems.findIndex(
90
- (t) => t.bladeId === bladeId && t.toolbarItem.id === toolbarItemId,
97
+ (t) => t.bladeId === normalizedBladeId && t.toolbarItem.id === toolbarItemId,
91
98
  );
92
99
  if (regIndex !== -1) {
93
100
  registeredToolbarItems.splice(regIndex, 1);
@@ -95,19 +102,22 @@ export function createToolbarService(): IToolbarService {
95
102
  };
96
103
 
97
104
  const getToolbarItems = (bladeId: string): IToolbarItem[] => {
98
- return toolbarRegistry[bladeId] || [];
105
+ const normalizedBladeId = bladeId ? bladeId.toLowerCase() : "";
106
+ return toolbarRegistry[normalizedBladeId] || [];
99
107
  };
100
108
 
101
109
  const clearBladeToolbarItems = (bladeId: string): void => {
102
- if (toolbarRegistry[bladeId]) {
103
- toolbarRegistry[bladeId].forEach((toolbarItem) => {
110
+ const normalizedBladeId = bladeId.toLowerCase();
111
+
112
+ if (toolbarRegistry[normalizedBladeId]) {
113
+ toolbarRegistry[normalizedBladeId].forEach((toolbarItem) => {
104
114
  registeredIds.delete(toolbarItem.id);
105
115
  });
106
- delete toolbarRegistry[bladeId];
116
+ delete toolbarRegistry[normalizedBladeId];
107
117
  }
108
118
 
109
119
  const indices = registeredToolbarItems
110
- .map((t, i) => (t.bladeId === bladeId ? i : -1))
120
+ .map((t, i) => (t.bladeId === normalizedBladeId ? i : -1))
111
121
  .filter((i) => i !== -1)
112
122
  .reverse();
113
123
 
@@ -1,4 +1,4 @@
1
- import { ConcreteComponent, reactive, ref, ComponentInternalInstance, ComputedRef, Ref, getCurrentInstance } from "vue";
1
+ import { Component, reactive, ref, ComponentInternalInstance, ComputedRef, Ref, getCurrentInstance } from "vue";
2
2
  import { IBladeInstance } from "../../shared/components/blade-navigation/types";
3
3
 
4
4
  export type WidgetEventHandler = (...args: unknown[]) => void;
@@ -10,7 +10,7 @@ export interface IWidgetEvents {
10
10
  export interface IWidget {
11
11
  id: string;
12
12
  title?: string;
13
- component: ConcreteComponent;
13
+ component: Component;
14
14
  props?: Record<string, unknown>;
15
15
  events?: Record<string, unknown>;
16
16
  isVisible?: boolean | ComputedRef<boolean> | Ref<boolean> | ((blade?: IBladeInstance) => boolean);
@@ -44,7 +44,8 @@ const preregisteredIds = new Set<string>();
44
44
  * Registers a widget before the service is initialized
45
45
  */
46
46
  export function registerWidget(widget: IWidget, bladeId: string): void {
47
- preregisteredWidgets.push({ bladeId, widget });
47
+ const normalizedBladeId = bladeId.toLowerCase();
48
+ preregisteredWidgets.push({ bladeId: normalizedBladeId, widget });
48
49
  preregisteredIds.add(widget.id);
49
50
  }
50
51
 
@@ -55,56 +56,65 @@ export function createWidgetService(): IWidgetService {
55
56
  const registeredIds = reactive(new Set<string>());
56
57
 
57
58
  const registerWidget = (widget: IWidget, bladeId: string): void => {
58
- if (!widgetRegistry[bladeId]) {
59
- widgetRegistry[bladeId] = [];
59
+ const normalizedBladeId = bladeId.toLowerCase();
60
+
61
+ if (!widgetRegistry[normalizedBladeId]) {
62
+ widgetRegistry[normalizedBladeId] = [];
60
63
  }
61
64
 
62
- const existingIndex = widgetRegistry[bladeId].findIndex((w) => w.id === widget.id);
65
+ const existingIndex = widgetRegistry[normalizedBladeId].findIndex((w) => w.id === widget.id);
63
66
  if (existingIndex === -1) {
64
- widgetRegistry[bladeId].push(reactive(widget));
65
- registeredWidgets.push({ bladeId, widget: reactive(widget) });
67
+ widgetRegistry[normalizedBladeId].push(reactive(widget));
68
+ registeredWidgets.push({ bladeId: normalizedBladeId, widget: reactive(widget) });
66
69
  registeredIds.add(widget.id);
67
70
  }
68
71
  };
69
72
 
70
73
  const updateWidget = ({ id, bladeId, widget }: { id: string; bladeId: string; widget: Partial<IWidget> }): void => {
71
- if (widgetRegistry[bladeId]) {
72
- const index = widgetRegistry[bladeId].findIndex((w) => w.id === id);
74
+ const normalizedBladeId = bladeId.toLowerCase();
75
+
76
+ if (widgetRegistry[normalizedBladeId]) {
77
+ const index = widgetRegistry[normalizedBladeId].findIndex((w) => w.id === id);
73
78
  if (index !== -1) {
74
- widgetRegistry[bladeId][index] = { ...widgetRegistry[bladeId][index], ...widget };
79
+ widgetRegistry[normalizedBladeId][index] = { ...widgetRegistry[normalizedBladeId][index], ...widget };
75
80
  }
76
81
  }
77
82
  };
78
83
 
79
84
  const unregisterWidget = (widgetId: string, bladeId: string): void => {
80
- if (widgetRegistry[bladeId]) {
81
- const index = widgetRegistry[bladeId].findIndex((w) => w.id === widgetId);
85
+ const normalizedBladeId = bladeId.toLowerCase();
86
+
87
+ if (widgetRegistry[normalizedBladeId]) {
88
+ const index = widgetRegistry[normalizedBladeId].findIndex((w) => w.id === widgetId);
82
89
  if (index !== -1) {
83
- widgetRegistry[bladeId].splice(index, 1);
90
+ widgetRegistry[normalizedBladeId].splice(index, 1);
84
91
  registeredIds.delete(widgetId);
85
92
  }
86
93
  }
87
94
 
88
- const regIndex = registeredWidgets.findIndex((w) => w.bladeId === bladeId && w.widget.id === widgetId);
95
+ const regIndex = registeredWidgets.findIndex((w) => w.bladeId === normalizedBladeId && w.widget.id === widgetId);
89
96
  if (regIndex !== -1) {
90
97
  registeredWidgets.splice(regIndex, 1);
91
98
  }
92
99
  };
93
100
 
94
101
  const getWidgets = (bladeId: string): IWidget[] => {
95
- return widgetRegistry[bladeId] || [];
102
+ const normalizedBladeId = bladeId ? bladeId.toLowerCase() : "";
103
+ return widgetRegistry[normalizedBladeId] || [];
96
104
  };
97
105
 
98
106
  const clearBladeWidgets = (bladeId: string): void => {
99
- if (widgetRegistry[bladeId]) {
100
- widgetRegistry[bladeId].forEach((widget) => {
107
+ const normalizedBladeId = bladeId.toLowerCase();
108
+
109
+ if (widgetRegistry[normalizedBladeId]) {
110
+ widgetRegistry[normalizedBladeId].forEach((widget) => {
101
111
  registeredIds.delete(widget.id);
102
112
  });
103
- delete widgetRegistry[bladeId];
113
+ delete widgetRegistry[normalizedBladeId];
104
114
  }
105
115
 
106
116
  const indices = registeredWidgets
107
- .map((w, i) => (w.bladeId === bladeId ? i : -1))
117
+ .map((w, i) => (w.bladeId === normalizedBladeId ? i : -1))
108
118
  .filter((i) => i !== -1)
109
119
  .reverse();
110
120
 
@@ -19,4 +19,5 @@ export * from "./useDashboard";
19
19
  export * from "./useAppBarWidget";
20
20
  export * from "./useSettingsMenu";
21
21
  export * from "./useToolbar";
22
+ export * from "./useDynamicProperties";
22
23
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../core/composables/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../core/composables/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC;AAC7B,cAAc,wBAAwB,CAAC"}
@@ -0,0 +1,54 @@
1
+ import { ComputedRef } from "vue";
2
+ export interface IBaseProperty<TPropertyValue> {
3
+ id?: string | null;
4
+ name?: string | null;
5
+ values?: TPropertyValue[] | null;
6
+ multilanguage?: boolean | null;
7
+ multivalue?: boolean | null;
8
+ dictionary?: boolean | null;
9
+ valueType?: string | null;
10
+ }
11
+ export interface IBasePropertyValue {
12
+ propertyName?: string | null;
13
+ propertyId?: string | null;
14
+ languageCode?: string | null;
15
+ alias?: string | null;
16
+ valueType?: string | null;
17
+ value?: any;
18
+ valueId?: string | null;
19
+ isInherited?: boolean;
20
+ }
21
+ export interface IBasePropertyDictionaryItem {
22
+ id?: string | null;
23
+ propertyId?: string | null;
24
+ alias?: string | null;
25
+ localizedValues?: {
26
+ languageCode?: string | null;
27
+ value?: string | null;
28
+ }[] | null;
29
+ value?: string;
30
+ }
31
+ export interface IBasePropertyDictionaryItemSearchCriteria {
32
+ propertyIds?: string[] | null;
33
+ keyword?: string | null;
34
+ skip?: number | null;
35
+ take?: number | null;
36
+ }
37
+ export interface IUseDynamicProperties<TProperty extends IBaseProperty<TPropertyValue>, TPropertyValue extends IBasePropertyValue, TPropertyDictionaryItem extends IBasePropertyDictionaryItem, TPropertyDictionaryItemSearchCriteria extends IBasePropertyDictionaryItemSearchCriteria> {
38
+ loading: ComputedRef<boolean>;
39
+ loadDictionaries: (propertyId: string, keyword?: string, locale?: string) => Promise<TPropertyDictionaryItem[] | undefined>;
40
+ getPropertyValue: (property: TProperty, locale: string) => string | TPropertyValue[] | (TPropertyDictionaryItem & {
41
+ value: string;
42
+ })[];
43
+ setPropertyValue: (data: {
44
+ property: TProperty;
45
+ value: string | TPropertyValue[] | (TPropertyDictionaryItem & {
46
+ value: string;
47
+ })[];
48
+ dictionary?: TPropertyDictionaryItem[];
49
+ locale?: string;
50
+ initialProp?: TProperty;
51
+ }) => void;
52
+ }
53
+ export declare const useDynamicProperties: <TProperty extends IBaseProperty<TPropertyValue>, TPropertyValue extends IBasePropertyValue, TPropertyDictionaryItem extends IBasePropertyDictionaryItem, TPropertyDictionaryItemSearchCriteria extends IBasePropertyDictionaryItemSearchCriteria>(searchDictionaryItemsFunction: (criteria: TPropertyDictionaryItemSearchCriteria) => Promise<TPropertyDictionaryItem[] | undefined>, PropertyValueConstructor: new (data?: Partial<TPropertyValue>) => TPropertyValue, PropertyDictionaryItemConstructor: new (data?: Partial<TPropertyDictionaryItem>) => TPropertyDictionaryItem) => IUseDynamicProperties<TProperty, TPropertyValue, TPropertyDictionaryItem, TPropertyDictionaryItemSearchCriteria>;
54
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../core/composables/useDynamicProperties/index.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"toolbar-service.d.ts","sourceRoot":"","sources":["../../../core/services/toolbar-service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,WAAW,YAAa,SAAQ,aAAa;IACjD,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,YAAY,CAAC;CAC3B;AAED,MAAM,WAAW,eAAe;IAC9B,mBAAmB,EAAE,CAAC,WAAW,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1E,qBAAqB,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACxE,eAAe,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,YAAY,EAAE,CAAC;IACrD,sBAAsB,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,sBAAsB,EAAE,oBAAoB,EAAE,CAAC;IAC/C,uBAAuB,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC;IACjD,iBAAiB,EAAE,CAAC,EAClB,EAAE,EACF,OAAO,EACP,WAAW,GACZ,EAAE;QACD,EAAE,EAAE,MAAM,CAAC;QACX,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;KACpC,KAAK,IAAI,CAAC;CACZ;AAMD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAGpF;AAED,wBAAgB,oBAAoB,IAAI,eAAe,CAgGtD"}
1
+ {"version":3,"file":"toolbar-service.d.ts","sourceRoot":"","sources":["../../../core/services/toolbar-service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,WAAW,YAAa,SAAQ,aAAa;IACjD,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,YAAY,CAAC;CAC3B;AAED,MAAM,WAAW,eAAe;IAC9B,mBAAmB,EAAE,CAAC,WAAW,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1E,qBAAqB,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACxE,eAAe,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,YAAY,EAAE,CAAC;IACrD,sBAAsB,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,sBAAsB,EAAE,oBAAoB,EAAE,CAAC;IAC/C,uBAAuB,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC;IACjD,iBAAiB,EAAE,CAAC,EAClB,EAAE,EACF,OAAO,EACP,WAAW,GACZ,EAAE;QACD,EAAE,EAAE,MAAM,CAAC;QACX,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;KACpC,KAAK,IAAI,CAAC;CACZ;AAMD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAIpF;AAED,wBAAgB,oBAAoB,IAAI,eAAe,CAyGtD"}
@@ -1,4 +1,4 @@
1
- import { ConcreteComponent, ComponentInternalInstance, ComputedRef, Ref } from "vue";
1
+ import { Component, ComponentInternalInstance, ComputedRef, Ref } from "vue";
2
2
  import { IBladeInstance } from "../../shared/components/blade-navigation/types";
3
3
  export type WidgetEventHandler = (...args: unknown[]) => void;
4
4
  export interface IWidgetEvents {
@@ -7,7 +7,7 @@ export interface IWidgetEvents {
7
7
  export interface IWidget {
8
8
  id: string;
9
9
  title?: string;
10
- component: ConcreteComponent;
10
+ component: Component;
11
11
  props?: Record<string, unknown>;
12
12
  events?: Record<string, unknown>;
13
13
  isVisible?: boolean | ComputedRef<boolean> | Ref<boolean> | ((blade?: IBladeInstance) => boolean);