@vc-shell/framework 1.0.158 → 1.0.160

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vc-shell/framework",
3
- "version": "1.0.158",
3
+ "version": "1.0.160",
4
4
  "type": "module",
5
5
  "main": "./dist/framework.js",
6
6
  "types": "./dist/index.d.ts",
@@ -53,9 +53,9 @@
53
53
  "whatwg-fetch": "^3.6.19"
54
54
  },
55
55
  "devDependencies": {
56
- "@vc-shell/api-client-generator": "^1.0.158",
57
- "@vc-shell/config-generator": "^1.0.158",
58
- "@vc-shell/ts-config": "^1.0.158",
56
+ "@vc-shell/api-client-generator": "^1.0.160",
57
+ "@vc-shell/config-generator": "^1.0.160",
58
+ "@vc-shell/ts-config": "^1.0.160",
59
59
  "@vitejs/plugin-vue": "^5.0.3",
60
60
  "sass": "^1.69.6",
61
61
  "typescript": "^5.3.3",
@@ -44,11 +44,6 @@ const render = () => {
44
44
  closable: index >= 1,
45
45
  expandable: quantity.value > 1,
46
46
  expanded: index === quantity.value - 1,
47
- "onUpdate:expanded": (value: boolean) => {
48
- if (value) {
49
- closeBlade(index + 1);
50
- }
51
- },
52
47
  "onClose:blade": () => closeBlade(index),
53
48
  "onParent:call": (args: IParentCallArgs) => {
54
49
  const instance = blades.value?.[index - 1]?.props?.navigation?.instance.value;
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
1
2
  import {
2
3
  h,
3
4
  ref,
@@ -6,13 +7,13 @@ import {
6
7
  unref,
7
8
  Component,
8
9
  onMounted,
9
- reactive,
10
10
  RendererElement,
11
11
  RendererNode,
12
12
  VNode,
13
13
  ComputedRef,
14
14
  readonly,
15
15
  toValue,
16
+ Ref,
16
17
  } from "vue";
17
18
  import * as _ from "lodash-es";
18
19
  import { Checkbox, InputField } from "../../components/factories";
@@ -20,14 +21,7 @@ import { AsyncAction } from "../../../../../core/composables";
20
21
  import { VcButton, VcCol, VcContainer, VcRow } from "../../../../../ui/components";
21
22
  import { createUnrefFn } from "@vueuse/core";
22
23
  import { useI18n } from "vue-i18n";
23
-
24
- interface RawControl {
25
- field: string;
26
- component: string;
27
- label?: string;
28
- multiple?: boolean;
29
- data?: { value: string; displayName: string }[];
30
- }
24
+ import { FilterBase, FilterCheckbox, FilterDateInput } from "../../types";
31
25
 
32
26
  interface Control {
33
27
  title: string;
@@ -36,13 +30,6 @@ interface Control {
36
30
  };
37
31
  }
38
32
 
39
- interface Data {
40
- columns: {
41
- title: string;
42
- controls: RawControl[];
43
- }[];
44
- }
45
-
46
33
  export interface UseFilterBuilder {
47
34
  filterComponent: (slotMethods: { close: () => void }) =>
48
35
  | VNode<
@@ -62,15 +49,16 @@ export interface UseFilterBuilder {
62
49
  }
63
50
 
64
51
  export default <Query>(args: {
65
- data: Data | undefined;
52
+ data: FilterBase | undefined;
66
53
  query: MaybeRef<Query>;
67
54
  load: AsyncAction<Query>;
55
+ scope: ComputedRef<Record<string, any>> | undefined;
68
56
  }): UseFilterBuilder => {
69
57
  const _search = args.load;
70
58
  const _data = args.data;
71
59
 
72
60
  const isFilterVisible = ref(true);
73
- const filter: Record<string, unknown> = reactive({});
61
+ const filter: Ref<Record<string, unknown>> = ref({});
74
62
  const { t } = useI18n({ useScope: "global" });
75
63
 
76
64
  const controls = ref<Control[]>([]);
@@ -86,7 +74,7 @@ export default <Query>(args: {
86
74
  onMounted(() => createFilterControls());
87
75
 
88
76
  function isItemSelected(value: string, field: string) {
89
- const item = filter[field];
77
+ const item = filter.value[field];
90
78
  if (Array.isArray(item) && typeof item !== "string") {
91
79
  return item.some((x) => x === value);
92
80
  } else {
@@ -96,13 +84,13 @@ export default <Query>(args: {
96
84
 
97
85
  function selectFilterItem(e: boolean, value: string, field: string, multiple = true) {
98
86
  if (multiple) {
99
- filter[field] = e
100
- ? [...((filter[field] as string[]) || []), value]
101
- : ((filter[field] as string[]) || []).filter((x) => x !== value);
87
+ filter.value[field] = e
88
+ ? [...((filter.value[field] as string[]) || []), value]
89
+ : ((filter.value[field] as string[]) || []).filter((x) => x !== value);
102
90
 
103
- if (!(filter[field] as string[]).length) filter[field] = undefined;
91
+ if (!(filter.value[field] as string[]).length) filter.value[field] = undefined;
104
92
  } else {
105
- filter[field] = e ? value : undefined;
93
+ filter.value[field] = e ? value : undefined;
106
94
  }
107
95
  }
108
96
 
@@ -116,7 +104,8 @@ export default <Query>(args: {
116
104
  (obj, control) => {
117
105
  if (control.component === "vc-checkbox") {
118
106
  const filterData = control.data;
119
- const fields = createCheckboxFromData(filterData, control);
107
+ const filterDataFromScope = unref(args.scope)?.[filterData] ?? [];
108
+ const fields = createCheckboxFromData(filterDataFromScope, control);
120
109
 
121
110
  if (fields) {
122
111
  obj = fields;
@@ -138,18 +127,20 @@ export default <Query>(args: {
138
127
  });
139
128
  }
140
129
 
141
- function createCheckboxFromData(data: RawControl["data"], control: RawControl) {
142
- if (!(data && data.length)) return;
143
- return data.reduce(
130
+ // TODO add to documentation support of dynamic data for filter
131
+ function createCheckboxFromData(data: MaybeRef<Record<string, string>[]>, control: FilterCheckbox) {
132
+ if (!(toValue(data) && toValue(data).length)) return;
133
+ return toValue(data).reduce(
144
134
  (obj, currC) => {
145
- obj[currC.value] = Checkbox({
135
+ obj[currC[control.optionValue]] = Checkbox({
146
136
  props: {
147
137
  class: "tw-mb-2",
148
- modelValue: computed(() => isItemSelected(currC.value, control.field)),
149
- "onUpdate:modelValue": (e: boolean) => selectFilterItem(e, currC.value, control.field, control.multiple),
138
+ modelValue: computed(() => isItemSelected(currC[control.optionValue], control.field)),
139
+ "onUpdate:modelValue": (e: boolean) =>
140
+ selectFilterItem(e, currC[control.optionValue], control.field, control.multiple),
150
141
  },
151
142
  slots: {
152
- default: () => unref(computed(() => t(currC.displayName))),
143
+ default: () => toValue(currC[control.optionLabel]),
153
144
  },
154
145
  });
155
146
 
@@ -159,14 +150,14 @@ export default <Query>(args: {
159
150
  );
160
151
  }
161
152
 
162
- function createInput(control: RawControl) {
153
+ function createInput(control: FilterDateInput) {
163
154
  return InputField({
164
155
  props: {
165
156
  type: "date",
166
157
  class: "tw-mb-3",
167
158
  label: toValue(computed(() => t(control.label ?? ""))),
168
- modelValue: computed(() => filter[control.field]),
169
- "onUpdate:modelValue": (e: unknown) => (filter[control.field] = e),
159
+ modelValue: computed(() => filter.value[control.field]),
160
+ "onUpdate:modelValue": (e: unknown) => (filter.value[control.field] = e),
170
161
  },
171
162
  });
172
163
  }
@@ -175,10 +166,10 @@ export default <Query>(args: {
175
166
  filterHandlerFn();
176
167
  await _search({
177
168
  ...unref(args.query),
178
- ...filter,
169
+ ...filter.value,
179
170
  });
180
171
  appliedFilter.value = {
181
- ...filter,
172
+ ...filter.value,
182
173
  };
183
174
  }
184
175
 
@@ -189,62 +180,72 @@ export default <Query>(args: {
189
180
 
190
181
  await _search({
191
182
  ...unref(args.query),
192
- ...filter,
183
+ ...filter.value,
193
184
  });
194
185
  }
195
186
 
196
187
  function render(slotMethods: { close: () => void }) {
197
188
  if (_.isEmpty(controls.value)) return;
198
- return h(VcContainer, () => [
199
- h(VcRow, () =>
200
- Object.values(controls.value).map(({ title, fields }) =>
201
- h(VcCol, { class: "tw-p-2" }, () => [
202
- h(
203
- "div",
204
- { class: "tw-mb-4 tw-text-[#a1c0d4] tw-font-bold tw-text-[17px]" },
205
- unref(computed(() => t(title))),
206
- ),
207
- Object.values(fields).map((item) => {
208
- if ("component" in item && item.component) {
209
- return h(
210
- item.component as Component,
211
- { ...item.props, class: item.props.class },
212
- "slots" in item && item.slots ? { ...item.slots } : {},
213
- );
214
- }
215
- }),
216
- ]),
189
+ return h(
190
+ VcContainer,
191
+ {
192
+ onVnodeBeforeMount: () => {
193
+ if (Object.keys(appliedFilter.value).length) {
194
+ filter.value = _.cloneDeep(appliedFilter.value);
195
+ }
196
+ },
197
+ },
198
+ () => [
199
+ h(VcRow, () =>
200
+ Object.values(controls.value).map(({ title, fields }) =>
201
+ h(VcCol, { class: "tw-p-2" }, () => [
202
+ h(
203
+ "div",
204
+ { class: "tw-mb-4 tw-text-[#a1c0d4] tw-font-bold tw-text-[17px]" },
205
+ unref(computed(() => t(title))),
206
+ ),
207
+ Object.values(fields).map((item) => {
208
+ if ("component" in item && item.component) {
209
+ return h(
210
+ item.component as Component,
211
+ { ...item.props, class: item.props.class },
212
+ "slots" in item && item.slots ? { ...item.slots } : {},
213
+ );
214
+ }
215
+ }),
216
+ ]),
217
+ ),
217
218
  ),
218
- ),
219
- h(VcRow, () =>
220
- h(VcCol, { class: "tw-p-2" }, () =>
221
- h("div", { class: "tw-flex tw-justify-end" }, [
222
- h(
223
- VcButton,
224
- {
225
- outline: true,
226
- class: "tw-mr-4",
227
- disabled: isDisabled(appliedFilter),
228
- onClick: () => resetFilters(slotMethods.close),
229
- },
230
- () => t("COMPONENTS.FILTERS.RESET"),
231
- ),
232
- h(
233
- VcButton,
234
- {
235
- disabled: isDisabled(filter),
236
- onClick: () => applyFilters(slotMethods.close),
237
- },
238
- () => t("COMPONENTS.FILTERS.APPLY"),
239
- ),
240
- ]),
219
+ h(VcRow, () =>
220
+ h(VcCol, { class: "tw-p-2" }, () =>
221
+ h("div", { class: "tw-flex tw-justify-end" }, [
222
+ h(
223
+ VcButton,
224
+ {
225
+ outline: true,
226
+ class: "tw-mr-4",
227
+ disabled: isDisabled(appliedFilter),
228
+ onClick: () => resetFilters(slotMethods.close),
229
+ },
230
+ () => t("COMPONENTS.FILTERS.RESET"),
231
+ ),
232
+ h(
233
+ VcButton,
234
+ {
235
+ disabled: isDisabled(filter),
236
+ onClick: () => applyFilters(slotMethods.close),
237
+ },
238
+ () => t("COMPONENTS.FILTERS.APPLY"),
239
+ ),
240
+ ]),
241
+ ),
241
242
  ),
242
- ),
243
- ]);
243
+ ],
244
+ );
244
245
  }
245
246
 
246
247
  async function reset() {
247
- Object.keys(filter).forEach((key: string) => (filter[key] = undefined));
248
+ Object.keys(filter.value).forEach((key: string) => (filter.value[key] = undefined));
248
249
 
249
250
  appliedFilter.value = {};
250
251
  }
@@ -252,7 +253,7 @@ export default <Query>(args: {
252
253
  return {
253
254
  filterComponent: render,
254
255
  activeFilterCount,
255
- filter: readonly(filter),
256
+ filter: readonly(filter.value),
256
257
  isFilterVisible: computed(() => isFilterVisible.value),
257
258
  reset,
258
259
  };
@@ -297,6 +297,7 @@ const {
297
297
  data: bladeOptions.tableData?.filter,
298
298
  query,
299
299
  load,
300
+ scope,
300
301
  });
301
302
 
302
303
  const bladeContext = ref<ListBladeContext>({
@@ -912,7 +912,9 @@ export type FilterCheckbox = {
912
912
  id: string;
913
913
  field: string;
914
914
  multiple?: boolean;
915
- data?: { value: string; displayName: string }[];
915
+ data: string;
916
+ optionValue: string;
917
+ optionLabel: string;
916
918
  component: CheckboxSchema["component"];
917
919
  };
918
920