namirasoft-account-react 1.5.21 → 1.5.23

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 (143) hide show
  1. package/.env.template +15 -15
  2. package/SKILL.md +514 -514
  3. package/config-overrides.js +72 -72
  4. package/dist/App.d.ts +1 -1
  5. package/dist/Router.d.ts +1 -1
  6. package/dist/UseParams.d.ts +1 -1
  7. package/dist/components/NSAAccessListDialog.d.ts +2 -2
  8. package/dist/components/NSAAccessListDialog.module.css +71 -71
  9. package/dist/components/NSABoxSecret.d.ts +1 -1
  10. package/dist/components/NSABoxSecret.module.css +23 -23
  11. package/dist/components/NSAMasterMenu.d.ts +1 -1
  12. package/dist/components/NSAMasterMenu.module.css +250 -250
  13. package/dist/components/NSAMasterMenuItem.d.ts +1 -1
  14. package/dist/components/NSAMessageListDialog.d.ts +1 -1
  15. package/dist/components/NSAMessageListDialog.module.css +99 -99
  16. package/dist/components/NSANavigationGuard.d.ts +1 -1
  17. package/dist/components/NSAProductListDialog.d.ts +1 -1
  18. package/dist/components/NSAProductListDialog.module.css +44 -44
  19. package/dist/components/NSATaskBar.d.ts +1 -1
  20. package/dist/components/NSATaskBar.module.css +57 -57
  21. package/dist/components/NSAUserDialog.d.ts +1 -1
  22. package/dist/components/NSAUserDialog.module.css +67 -67
  23. package/dist/components/NSAWorkspaceListDialog.d.ts +1 -1
  24. package/dist/components/NSAWorkspaceListDialog.module.css +41 -41
  25. package/dist/components/NSFBoxCategoryScope.d.ts +1 -1
  26. package/dist/components/NSFBoxField.d.ts +1 -1
  27. package/dist/components/NSFBoxSlot.d.ts +1 -1
  28. package/dist/components/NSFBoxWrapper.d.ts +1 -1
  29. package/dist/components/NSLabelSecret.d.ts +1 -1
  30. package/dist/components/quickfilter/NSAFilterBoxEnum.module.css +44 -44
  31. package/dist/components/quickfilter/NSAQuickFilterBar.d.ts +1 -1
  32. package/dist/components/quickfilter/NSAQuickFilterBar.module.css +19 -19
  33. package/dist/components/quickfilter/NSAQuickFilterDialog.d.ts +1 -1
  34. package/dist/components/quickfilter/NSAQuickFilterDialog.module.css +74 -74
  35. package/dist/layouts/NSALayout.d.ts +1 -1
  36. package/dist/layouts/NSASectionEdit.d.ts +1 -1
  37. package/dist/layouts/NSASectionEditTabPage.d.ts +1 -1
  38. package/dist/layouts/NSASectionEditTabPage.module.css +4 -4
  39. package/dist/layouts/NSASectionList.d.ts +3 -1
  40. package/dist/layouts/NSASectionList.js +14 -6
  41. package/dist/layouts/NSASectionList.js.map +1 -1
  42. package/dist/layouts/NSASectionList.module.css +31 -31
  43. package/dist/layouts/NSASectionView.d.ts +1 -1
  44. package/dist/layouts/NSASectionViewTabMore.d.ts +1 -1
  45. package/dist/layouts/NSASectionViewTabPage.d.ts +1 -1
  46. package/dist/layouts/NSASectionViewTabPage.js +1 -0
  47. package/dist/layouts/NSASectionViewTabPage.js.map +1 -1
  48. package/dist/layouts/NSASectionViewTabPage.module.css +47 -47
  49. package/dist/pages/NSAConsentPage.module.css +26 -26
  50. package/dist/pages/NSAEmailVerificationPage.d.ts +1 -1
  51. package/dist/pages/NSAHomePage.d.ts +1 -1
  52. package/dist/pages/NSAHomePage.module.css +41 -41
  53. package/dist/pages/NSALoginPage.d.ts +1 -1
  54. package/dist/pages/NSALoginPage.module.css +26 -26
  55. package/dist/pages/NSAPhoneVerificationPage.d.ts +1 -1
  56. package/dist/pages/NSAVerificationPage.d.ts +1 -1
  57. package/dist/pages/NSAVerificationPage.module.css +31 -31
  58. package/package.json +95 -95
  59. package/public/index.html +21 -21
  60. package/src/App.tsx +19 -19
  61. package/src/CTFRow.ts +7 -7
  62. package/src/FieldCacheService.tsx +84 -84
  63. package/src/IEntityInfo.ts +33 -33
  64. package/src/NSACacheService.ts +120 -120
  65. package/src/NSAFilterOperators.ts +92 -92
  66. package/src/NSARouterMaker.tsx +140 -140
  67. package/src/NSARouterMakerProps.ts +23 -23
  68. package/src/NSARouterMakerResult.ts +24 -24
  69. package/src/NSFRouterMaker.tsx +35 -35
  70. package/src/NSFRouterProps.ts +7 -7
  71. package/src/NSFRoutes.ts +30 -30
  72. package/src/Router.tsx +48 -48
  73. package/src/UseParams.tsx +17 -17
  74. package/src/components/NSAAccessListDialog.module.css +71 -71
  75. package/src/components/NSAAccessListDialog.tsx +178 -178
  76. package/src/components/NSABoxSecret.module.css +23 -23
  77. package/src/components/NSABoxSecret.tsx +264 -264
  78. package/src/components/NSAMasterMenu.module.css +250 -250
  79. package/src/components/NSAMasterMenu.tsx +169 -169
  80. package/src/components/NSAMasterMenuItem.tsx +250 -250
  81. package/src/components/NSAMessageListDialog.module.css +99 -99
  82. package/src/components/NSAMessageListDialog.tsx +142 -142
  83. package/src/components/NSANavigationGuard.tsx +79 -79
  84. package/src/components/NSAProductListDialog.module.css +44 -44
  85. package/src/components/NSAProductListDialog.tsx +88 -88
  86. package/src/components/NSATable.tsx +494 -494
  87. package/src/components/NSATaskBar.module.css +57 -57
  88. package/src/components/NSATaskBar.tsx +193 -193
  89. package/src/components/NSAUserDialog.module.css +67 -67
  90. package/src/components/NSAUserDialog.tsx +122 -122
  91. package/src/components/NSAWorkspaceListDialog.module.css +41 -41
  92. package/src/components/NSAWorkspaceListDialog.tsx +147 -147
  93. package/src/components/NSFBoxCategoryScope.tsx +52 -52
  94. package/src/components/NSFBoxField.tsx +37 -37
  95. package/src/components/NSFBoxSlot.tsx +71 -71
  96. package/src/components/NSFBoxWrapper.tsx +69 -69
  97. package/src/components/NSLabelSecret.tsx +37 -37
  98. package/src/components/quickfilter/NSAFilterBoxBase.tsx +89 -89
  99. package/src/components/quickfilter/NSAFilterBoxBoolean.tsx +66 -66
  100. package/src/components/quickfilter/NSAFilterBoxDate.tsx +110 -110
  101. package/src/components/quickfilter/NSAFilterBoxDateTime.tsx +110 -110
  102. package/src/components/quickfilter/NSAFilterBoxEnum.module.css +44 -44
  103. package/src/components/quickfilter/NSAFilterBoxEnum.tsx +79 -79
  104. package/src/components/quickfilter/NSAFilterBoxNumber.tsx +145 -145
  105. package/src/components/quickfilter/NSAFilterBoxString.tsx +83 -83
  106. package/src/components/quickfilter/NSAFilterBoxTime.tsx +106 -106
  107. package/src/components/quickfilter/NSAQuickFilterBar.module.css +19 -19
  108. package/src/components/quickfilter/NSAQuickFilterBar.tsx +142 -142
  109. package/src/components/quickfilter/NSAQuickFilterDialog.module.css +74 -74
  110. package/src/components/quickfilter/NSAQuickFilterDialog.tsx +260 -260
  111. package/src/css.d.ts +13 -13
  112. package/src/formatters/SecretFormatter.tsx +24 -24
  113. package/src/index.tsx +26 -26
  114. package/src/layouts/Actions.ts +146 -146
  115. package/src/layouts/CFTUtil.ts +18 -18
  116. package/src/layouts/NSALayout.tsx +744 -744
  117. package/src/layouts/NSALayout_Field.ts +125 -125
  118. package/src/layouts/NSASectionEdit.tsx +281 -281
  119. package/src/layouts/NSASectionEditTabPage.module.css +4 -4
  120. package/src/layouts/NSASectionEditTabPage.tsx +256 -256
  121. package/src/layouts/NSASectionList.module.css +31 -31
  122. package/src/layouts/NSASectionList.tsx +166 -147
  123. package/src/layouts/NSASectionView.tsx +98 -98
  124. package/src/layouts/NSASectionViewTabMore.tsx +78 -78
  125. package/src/layouts/NSASectionViewTabPage.module.css +47 -47
  126. package/src/layouts/NSASectionViewTabPage.tsx +400 -399
  127. package/src/main.ts +52 -52
  128. package/src/pages/NSAConsentPage.module.css +26 -26
  129. package/src/pages/NSAConsentPage.tsx +120 -120
  130. package/src/pages/NSAEmailVerificationPage.tsx +30 -30
  131. package/src/pages/NSAHomePage.module.css +41 -41
  132. package/src/pages/NSAHomePage.tsx +124 -124
  133. package/src/pages/NSALoginPage.module.css +26 -26
  134. package/src/pages/NSALoginPage.tsx +87 -87
  135. package/src/pages/NSAPhoneVerificationPage.tsx +94 -94
  136. package/src/pages/NSAVerificationPage.module.css +31 -31
  137. package/src/pages/NSAVerificationPage.tsx +185 -185
  138. package/src/pages/NSFCategoryEditPage.tsx +87 -87
  139. package/src/pages/NSFCategoryListPage.tsx +23 -23
  140. package/src/pages/NSFCategoryViewPage.tsx +23 -23
  141. package/src/pages/NSFEntities.ts +58 -58
  142. package/src/pages/PaymentRequired.tsx +80 -80
  143. package/tsconfig.json +43 -43
@@ -1,495 +1,495 @@
1
- import { EncodingOperation, FilterItem, FilterItemColumnType, NamingConvention, ObjectService, SearchOperation, SortItem } from "namirasoft-core";
2
- import { EntityResolveResponseRow } from "namirasoft-field";
3
- import { FilterItemColumnTypeBuilder, VariableType } from "namirasoft-schema";
4
- import { IBaseComponentProps, NSButtonProps, NSFilterBox, NSFilterBoxItems, NSFilterBoxProps_Table, NSSpace, NSSpaceSizeType, NSTable, TableColumnInfo, TableRowInfo } from "namirasoft-site-react";
5
- import { Component, ReactNode, createRef } from "react";
6
- import { IEntityInfo } from "../IEntityInfo";
7
- import { NSACacheService } from "../NSACacheService";
8
- import { NSAQuickFilterBar } from "./quickfilter/NSAQuickFilterBar";
9
- import { NSAQuickFilterDialog, QuickFilterConfig } from "./quickfilter/NSAQuickFilterDialog";
10
-
11
- export interface NSATableUIProps<RowType>
12
- {
13
- getRowAttributes?: (row_value: RowType, row_index: number, res: { rows: RowType[]; count: number; } | null) => { [key: string]: any };
14
- getColumnAttributes?: (column: TableColumnInfo) => { [key: string]: any };
15
- getCellFormattedValue?: (value: any, column: TableColumnInfo, row: TableRowInfo<RowType>) => any;
16
- search_box?: {
17
- exclude?: {
18
- show?: {
19
- table?: (table: string) => boolean;
20
- column?: (table: string, column: string) => boolean;
21
- },
22
- load_value?: (table: string, column: string) => boolean;
23
- }
24
- };
25
- }
26
-
27
- export interface NSATableProps<RowType extends { id: string }, RowTypeInput = RowType> extends IBaseComponentProps
28
- {
29
- entity: IEntityInfo<RowType, RowTypeInput>;
30
- ctf: {
31
- enabled: boolean;
32
- rows: EntityResolveResponseRow | null;
33
- };
34
- url: { getQuery(name: string, base64?: boolean, remove?: boolean): string };
35
- ui?: NSATableUIProps<RowType>;
36
- checkbox?: boolean;
37
- buttons?: NSButtonProps[];
38
- onSelectionChanged?: () => void;
39
- }
40
-
41
- interface NSATableState<RowType>
42
- {
43
- res: { rows: RowType[]; count: number; } | null;
44
- visible_column_keys: string[];
45
- quick_filter_configs: QuickFilterConfig[];
46
- show_quick_filter_dialog: boolean;
47
- filter_revision: number;
48
- }
49
-
50
- export class NSATable<RowType extends { id: string }, RowTypeInput = RowType>
51
- extends Component<NSATableProps<RowType, RowTypeInput>, NSATableState<RowType>>
52
- {
53
- public NSTable_Main = createRef<NSTable<RowType>>();
54
- public NSFilterBox_Top = createRef<NSFilterBox>();
55
- public NSAQuickFilterBar_Ref = createRef<NSAQuickFilterBar>();
56
-
57
- constructor(props: NSATableProps<RowType, RowTypeInput>)
58
- {
59
- super(props);
60
-
61
- let quick_filter_configs = NSACacheService.loadQuickFilters(props.entity.name);
62
- if (quick_filter_configs.length === 0)
63
- quick_filter_configs = this.buildDefaultQuickFilters();
64
- this.state = {
65
- res: null,
66
- visible_column_keys: [],
67
- quick_filter_configs,
68
- show_quick_filter_dialog: false,
69
- filter_revision: 0,
70
- };
71
- }
72
-
73
- override componentDidMount()
74
- {
75
- const visible = this.NSTable_Main.current?.getVisibleColumns() ?? [];
76
- if (visible.length > 0)
77
- this.setState({ visible_column_keys: visible.map(v => v.table + "." + v.column) });
78
-
79
- this.setState(prev => ({ filter_revision: prev.filter_revision + 1 }));
80
- }
81
-
82
- private getColumns(): TableColumnInfo[]
83
- {
84
- let columns = Object.values(this.props.entity.client.getColumns()).flat();
85
- columns.forEach(col =>
86
- {
87
- col.text = NamingConvention.auto.convert(col.text, NamingConvention.Pascal_Case_Space);
88
- });
89
- return columns;
90
- }
91
-
92
- private buildDefaultQuickFilters(): QuickFilterConfig[]
93
- {
94
- const getDefaults = this.props.entity.client.getQuickFilters;
95
- if (!getDefaults)
96
- return [];
97
-
98
- const columns = this.getColumns();
99
- const ans: QuickFilterConfig[] = [];
100
- for (const def of getDefaults())
101
- {
102
- const col = columns.find(c => c.name === def.column);
103
- if (!col)
104
- continue;
105
- const columnType = new ObjectService(col.type).getEnum(VariableType, VariableType.Any);
106
- ans.push({
107
- id: `default-${col.table.name}-${col.name}`,
108
- column: {
109
- table: { name: col.table.name, text: col.table.text },
110
- name: col.name,
111
- text: col.text,
112
- type: col.type,
113
- columnType,
114
- },
115
- operatorName: (def as { operator?: string }).operator,
116
- });
117
- }
118
- return ans;
119
- }
120
-
121
- private filterItemTypeConverter(type: string): FilterItemColumnType
122
- {
123
- let t = new ObjectService(type).getEnum(VariableType, VariableType.Any);
124
- let builder = new FilterItemColumnTypeBuilder(t);
125
- return builder.runSynch(() => { }) ?? FilterItemColumnType.Unknown;
126
- }
127
-
128
- private getIncomingFilterItems(): FilterItem[] | undefined
129
- {
130
- try
131
- {
132
- let encoded = this.props.url.getQuery("filters");
133
- if (encoded)
134
- return FilterItem.decode(encoded) ?? undefined;
135
- } catch (error)
136
- {
137
- }
138
- return undefined;
139
- }
140
-
141
- private itemMatchesQuickFilter(item: FilterItem): boolean
142
- {
143
- return this.state.quick_filter_configs.some(c =>
144
- c.column.table.name === item.table.name && c.column.name === item.column.name);
145
- }
146
- private getIncomingBoxItems(): FilterItem[] | undefined
147
- {
148
- let items = this.getIncomingFilterItems();
149
- if (!items)
150
- return undefined;
151
- return items.filter(i => !this.itemMatchesQuickFilter(i));
152
- }
153
- private getIncomingQuickItems(): FilterItem[]
154
- {
155
- let items = this.getIncomingFilterItems();
156
- if (!items)
157
- return [];
158
- return items.filter(i => this.itemMatchesQuickFilter(i));
159
- }
160
-
161
- private encodeFilters(items: FilterItem[]): string
162
- {
163
- let command = items.map(item =>
164
- {
165
- let key = item.operator.name.replace(/\s+/g, "").toLowerCase();
166
- let values = item.values.map(v => (v ?? "").toString().replace(/;/g, "\\;"));
167
- return [item.table.name, item.column.name, item.not ? "1" : "0", key, ...values].join(";");
168
- }).join(";");
169
- return EncodingOperation.Base64Encode(command);
170
- }
171
-
172
- private syncQueryFromFilters()
173
- {
174
- let items = this.getFilterItems();
175
- let url = new URL(window.location.href);
176
- let encoded = items.length > 0 ? this.encodeFilters(items) : "";
177
- if (encoded)
178
- url.searchParams.set("filters", encoded);
179
- else
180
- url.searchParams.delete("filters");
181
- window.history.replaceState({}, "", url.toString());
182
- }
183
-
184
- public reload(page: number | null, size: number | null): Promise<void> | undefined
185
- {
186
- return this.NSTable_Main.current?.reload(page, size);
187
- }
188
- public getSelectedIDs(): string[]
189
- {
190
- return this.NSTable_Main.current?.getSelectedIDs() ?? [];
191
- }
192
- public getSelectedRows(): RowType[]
193
- {
194
- return this.NSTable_Main.current?.getSelectedRows() ?? [];
195
- }
196
- public setSelectedIDs(ids: string[], rows: RowType[], callback?: () => void)
197
- {
198
- this.NSTable_Main.current?.setSelectedIDs(ids, rows, callback);
199
- }
200
- public getSortItems(): SortItem[]
201
- {
202
- return this.NSTable_Main.current?.getSortItems() ?? [];
203
- }
204
- public setSortItems(items: SortItem[] | null)
205
- {
206
- this.NSTable_Main.current?.setSortItems(items);
207
- }
208
- public getVisibleColumns(): { table: string, column: string }[]
209
- {
210
- return this.NSTable_Main.current?.getVisibleColumns() ?? [];
211
- }
212
- public setVisibleColumns(visible_columns: { table: string, column: string }[])
213
- {
214
- this.NSTable_Main.current?.setVisibleColumns(visible_columns);
215
- }
216
- public getFilterBoxItems(): FilterItem[]
217
- {
218
- return this.NSFilterBox_Top.current?.getFilterItems() ?? [];
219
- }
220
- public getQuickFilterItems(): FilterItem[]
221
- {
222
- return this.NSAQuickFilterBar_Ref.current?.getFilterItems() ?? [];
223
- }
224
- public getFilterItems(): FilterItem[]
225
- {
226
- return [...this.getFilterBoxItems(), ...this.getQuickFilterItems()];
227
- }
228
-
229
- private reloadFromFilters()
230
- {
231
- this.syncQueryFromFilters();
232
- this.NSTable_Main.current?.setSelectedIDs([], []);
233
- this.NSTable_Main.current?.reload(null, null);
234
- }
235
-
236
- private onFilterBoxChanged = () =>
237
- {
238
- this.reloadFromFilters();
239
- this.setState(prev => ({ filter_revision: prev.filter_revision + 1 }));
240
- };
241
-
242
- private buildButtons(): NSButtonProps[]
243
- {
244
- const buttons: NSButtonProps[] = [
245
- {
246
- title: "",
247
- icon: { src: "https://static.namirasoft.com/image/concept/sliders/blue.svg", alt: "filter" },
248
- attributes: { title: "Quick Filters" },
249
- onClick: {
250
- action: () => this.setState({ show_quick_filter_dialog: true }),
251
- showLoading: false,
252
- },
253
- },
254
- ];
255
- return [...buttons, ...(this.props.buttons ?? [])];
256
- }
257
-
258
- private renderFilterHeader(): ReactNode
259
- {
260
- return (
261
- <NSFilterBox
262
- ref={this.NSFilterBox_Top}
263
- filterItems={this.getIncomingBoxItems()}
264
- getTables={() =>
265
- {
266
- return this.props.entity.tables.map(table =>
267
- {
268
- let columns = table.table.getColumns().map(c => ({ id: c.name, ...c, type: this.filterItemTypeConverter(c.type) }));
269
- columns = columns.filter(c =>
270
- {
271
- if (this.props.ui?.search_box?.exclude?.show?.column)
272
- if (this.props.ui?.search_box?.exclude.show?.column(table.table.name, c.name))
273
- return false;
274
- return true;
275
- });
276
- return { name: table.table.name, text: table.table.text, columns, required: table.required };
277
- }).filter(t =>
278
- {
279
- if (this.props.ui?.search_box?.exclude?.show?.table)
280
- if (this.props.ui?.search_box?.exclude.show.table(t.name))
281
- return false;
282
- return true;
283
- });
284
- }}
285
- getMoreTables={async () =>
286
- {
287
- let ans: NSFilterBoxProps_Table[] = [];
288
- if (this.props.ctf.enabled)
289
- try
290
- {
291
- if (this.props.ctf.rows?.fields)
292
- if (this.props.ctf.rows.fields.length > 0)
293
- {
294
- let name = this.props.entity.name + "_field";
295
- ans.push({
296
- name,
297
- text: "Fields",
298
- columns: [{
299
- id: "field_id",
300
- name: "field_id",
301
- text: "ID",
302
- type: FilterItemColumnType.Unknown,
303
- getValues: async (search) =>
304
- {
305
- return this.props.ctf.rows?.fields?.filter(c => SearchOperation.match(c.id, search)).map(c => { return { value: c.id, title: c.id } }) ?? [];
306
- }
307
- }, {
308
- id: "field_name",
309
- name: "field_id",
310
- text: "Name",
311
- type: FilterItemColumnType.Unknown,
312
- getValues: async (search) =>
313
- {
314
- return this.props.ctf.rows?.fields?.filter(c => SearchOperation.match(c.name, search)).map(c => { return { value: c.id, title: c.name } }) ?? [];
315
- }
316
- }, {
317
- id: "field_value",
318
- name: "value",
319
- text: "Value",
320
- type: FilterItemColumnType.Unknown
321
- },
322
- ...this.props.ctf.rows?.fields.map(f =>
323
- {
324
- return {
325
- id: f.id,
326
- name: f.id,
327
- text: f.name,
328
- type: this.filterItemTypeConverter(f.type.type.type),
329
- getValues: async (search: string) =>
330
- {
331
- let values = await this.props.entity.server.value_list(name, "value", search, f.id, null);
332
- return values.map(v => { return { value: v, title: v } });
333
- }
334
- };
335
- }),],
336
- required: false
337
- });
338
- }
339
-
340
- if (this.props.ctf.rows?.categories)
341
- if (this.props.ctf.rows?.categories.length > 0)
342
- ans.push({
343
- name: this.props.entity.name + "_category",
344
- text: "Categories",
345
- columns: [{
346
- id: "category_id",
347
- name: "category_id",
348
- text: "ID",
349
- type: FilterItemColumnType.Unknown,
350
- getValues: async (search) =>
351
- {
352
- return this.props.ctf.rows?.categories?.filter(c => SearchOperation.match(c.id, search)).map(c => { return { value: c.id, title: c.id } }) ?? [];
353
- }
354
- }, {
355
- id: "category_name",
356
- name: "category_id",
357
- text: "Name",
358
- type: FilterItemColumnType.Unknown,
359
- getValues: async (search) =>
360
- {
361
- return this.props.ctf.rows?.categories?.filter(c => SearchOperation.match(c.name, search)).map(c => { return { value: c.id, title: c.name } }) ?? [];
362
- }
363
- }],
364
- required: false
365
- });
366
-
367
- } catch (error)
368
- {
369
- }
370
- // todo add tags
371
- return ans;
372
- }}
373
- getValues={async (table, column, value) =>
374
- {
375
- if (this.props.ui?.search_box?.exclude?.load_value)
376
- if (this.props.ui?.search_box?.exclude?.load_value(table.name, column.name))
377
- return [];
378
- if (column.type === FilterItemColumnType.Boolean)
379
- {
380
- const col = this.getColumns().find(c => c.table.name === table.name && c.name === column.name);
381
- return [true, false].map(b =>
382
- {
383
- const formatted = col ? col.formatter.format(b, col, { value: {} } as any, true) : null;
384
- return { value: String(b), title: formatted != null ? String(formatted) : String(b) };
385
- });
386
- }
387
- let values = await this.props.entity.server.value_list(table.name, column.name, value, null, null);
388
- return values.map(v => { return { value: v, title: v } });
389
- }}
390
- onChanged={this.onFilterBoxChanged}
391
- />
392
- );
393
- }
394
-
395
- private getOrderedColumns(): TableColumnInfo[]
396
- {
397
- const all = this.getColumns();
398
- const vk = this.state.visible_column_keys;
399
- if (vk.length === 0)
400
- return all;
401
- const ordered = vk.map(k => all.find(c => c.table.name + "." + c.name === k)).filter((c): c is TableColumnInfo => !!c);
402
- const rest = all.filter(c => !vk.includes(c.table.name + "." + c.name));
403
- return [...ordered, ...rest];
404
- }
405
-
406
- override render(): ReactNode
407
- {
408
- const filterBoxItems = this.NSFilterBox_Top.current?.getFilterItems() ?? [];
409
- const filterChips = filterBoxItems.length > 0 && (
410
- <>
411
- <NSFilterBoxItems
412
- filterItems={filterBoxItems}
413
- onClearFilterItems={() => this.NSFilterBox_Top.current?.setFilterItems([])}
414
- onRemoveFilterItem={(item) => this.NSFilterBox_Top.current?.removeFilterItem(item)}
415
- />
416
- <NSSpace size={NSSpaceSizeType.MINI} />
417
- </>
418
- );
419
-
420
- const quickFilterBar = this.state.quick_filter_configs.length > 0 && (
421
- <NSAQuickFilterBar
422
- key={this.state.quick_filter_configs.map(c => c.id).join("-")}
423
- ref={this.NSAQuickFilterBar_Ref}
424
- configs={this.state.quick_filter_configs}
425
- initialItems={this.getIncomingQuickItems()}
426
- getValues={async (tableName, columnName, search) =>
427
- {
428
- const values = await this.props.entity.server.value_list(tableName, columnName, search, null, null);
429
- const col = this.getColumns().find(c => c.table.name === tableName && c.name === columnName);
430
- return values.map(v =>
431
- {
432
- const formatted = col ? col.formatter.format(v, col, { value: {} } as any, true) : null;
433
- return { value: v, title: formatted != null ? String(formatted) : v };
434
- });
435
- }}
436
- onChanged={() => this.reloadFromFilters()}
437
- />
438
- );
439
-
440
- return (
441
- <>
442
- <NSTable<RowType>
443
- id={this.props.id}
444
- classList={this.props.classList}
445
- style={this.props.style}
446
- ref={this.NSTable_Main}
447
- name={NamingConvention.lower_case_dash.convert(this.props.entity.name, NamingConvention.Pascal_Case_Space)}
448
- checkbox={this.props.checkbox ?? true}
449
- headerChildren={this.renderFilterHeader()}
450
- buttons={this.buildButtons()}
451
- columns={this.getOrderedColumns()}
452
- getRows={async (page, size, sorts) =>
453
- {
454
- let res: { rows: RowType[], count: number } = { rows: [], count: 0 };
455
- if (this.props.entity.server.list)
456
- res = await this.props.entity.server.list(this.getFilterItems(), page, size, sorts, null);
457
- this.setState({ res });
458
- return res;
459
- }}
460
- getRowKey={(row) => row.value.id.toString()}
461
- sort={{
462
- onSort: () => { this.NSTable_Main.current?.reload(null, null); },
463
- }}
464
- getRowAttributes={(row_value, row_index) => this.props.ui?.getRowAttributes?.(row_value, row_index, this.state.res) ?? {}}
465
- getColumnAttributes={this.props.ui?.getColumnAttributes}
466
- getCellFormattedValue={this.props.ui?.getCellFormattedValue}
467
- onVisibleColumnsChanged={(visible_columns) => this.setState({ visible_column_keys: visible_columns.map(c => c.table + "." + c.column) })}
468
- onSelectedIDsChanged={() => this.props.onSelectionChanged?.()}
469
- >
470
- {filterChips}
471
- {quickFilterBar}
472
- </NSTable>
473
- {
474
- this.state.show_quick_filter_dialog &&
475
- <NSAQuickFilterDialog
476
- configs={this.state.quick_filter_configs}
477
- getColumns={() => this.getColumns()}
478
- typeConverter={(type: string) => new ObjectService(type).getEnum(VariableType, VariableType.Any)}
479
- onSave={configs =>
480
- {
481
- NSACacheService.saveQuickFilters(this.props.entity.name, configs);
482
- this.setState({ quick_filter_configs: configs }, () => this.reloadFromFilters());
483
- }}
484
- onConfirm={configs =>
485
- {
486
- NSACacheService.saveQuickFilters(this.props.entity.name, configs);
487
- this.setState({ quick_filter_configs: configs, show_quick_filter_dialog: false }, () => this.reloadFromFilters());
488
- }}
489
- onClose={() => this.setState({ show_quick_filter_dialog: false })}
490
- />
491
- }
492
- </>
493
- );
494
- }
1
+ import { EncodingOperation, FilterItem, FilterItemColumnType, NamingConvention, ObjectService, SearchOperation, SortItem } from "namirasoft-core";
2
+ import { EntityResolveResponseRow } from "namirasoft-field";
3
+ import { FilterItemColumnTypeBuilder, VariableType } from "namirasoft-schema";
4
+ import { IBaseComponentProps, NSButtonProps, NSFilterBox, NSFilterBoxItems, NSFilterBoxProps_Table, NSSpace, NSSpaceSizeType, NSTable, TableColumnInfo, TableRowInfo } from "namirasoft-site-react";
5
+ import { Component, ReactNode, createRef } from "react";
6
+ import { IEntityInfo } from "../IEntityInfo";
7
+ import { NSACacheService } from "../NSACacheService";
8
+ import { NSAQuickFilterBar } from "./quickfilter/NSAQuickFilterBar";
9
+ import { NSAQuickFilterDialog, QuickFilterConfig } from "./quickfilter/NSAQuickFilterDialog";
10
+
11
+ export interface NSATableUIProps<RowType>
12
+ {
13
+ getRowAttributes?: (row_value: RowType, row_index: number, res: { rows: RowType[]; count: number; } | null) => { [key: string]: any };
14
+ getColumnAttributes?: (column: TableColumnInfo) => { [key: string]: any };
15
+ getCellFormattedValue?: (value: any, column: TableColumnInfo, row: TableRowInfo<RowType>) => any;
16
+ search_box?: {
17
+ exclude?: {
18
+ show?: {
19
+ table?: (table: string) => boolean;
20
+ column?: (table: string, column: string) => boolean;
21
+ },
22
+ load_value?: (table: string, column: string) => boolean;
23
+ }
24
+ };
25
+ }
26
+
27
+ export interface NSATableProps<RowType extends { id: string }, RowTypeInput = RowType> extends IBaseComponentProps
28
+ {
29
+ entity: IEntityInfo<RowType, RowTypeInput>;
30
+ ctf: {
31
+ enabled: boolean;
32
+ rows: EntityResolveResponseRow | null;
33
+ };
34
+ url: { getQuery(name: string, base64?: boolean, remove?: boolean): string };
35
+ ui?: NSATableUIProps<RowType>;
36
+ checkbox?: boolean;
37
+ buttons?: NSButtonProps[];
38
+ onSelectionChanged?: () => void;
39
+ }
40
+
41
+ interface NSATableState<RowType>
42
+ {
43
+ res: { rows: RowType[]; count: number; } | null;
44
+ visible_column_keys: string[];
45
+ quick_filter_configs: QuickFilterConfig[];
46
+ show_quick_filter_dialog: boolean;
47
+ filter_revision: number;
48
+ }
49
+
50
+ export class NSATable<RowType extends { id: string }, RowTypeInput = RowType>
51
+ extends Component<NSATableProps<RowType, RowTypeInput>, NSATableState<RowType>>
52
+ {
53
+ public NSTable_Main = createRef<NSTable<RowType>>();
54
+ public NSFilterBox_Top = createRef<NSFilterBox>();
55
+ public NSAQuickFilterBar_Ref = createRef<NSAQuickFilterBar>();
56
+
57
+ constructor(props: NSATableProps<RowType, RowTypeInput>)
58
+ {
59
+ super(props);
60
+
61
+ let quick_filter_configs = NSACacheService.loadQuickFilters(props.entity.name);
62
+ if (quick_filter_configs.length === 0)
63
+ quick_filter_configs = this.buildDefaultQuickFilters();
64
+ this.state = {
65
+ res: null,
66
+ visible_column_keys: [],
67
+ quick_filter_configs,
68
+ show_quick_filter_dialog: false,
69
+ filter_revision: 0,
70
+ };
71
+ }
72
+
73
+ override componentDidMount()
74
+ {
75
+ const visible = this.NSTable_Main.current?.getVisibleColumns() ?? [];
76
+ if (visible.length > 0)
77
+ this.setState({ visible_column_keys: visible.map(v => v.table + "." + v.column) });
78
+
79
+ this.setState(prev => ({ filter_revision: prev.filter_revision + 1 }));
80
+ }
81
+
82
+ private getColumns(): TableColumnInfo[]
83
+ {
84
+ let columns = Object.values(this.props.entity.client.getColumns()).flat();
85
+ columns.forEach(col =>
86
+ {
87
+ col.text = NamingConvention.auto.convert(col.text, NamingConvention.Pascal_Case_Space);
88
+ });
89
+ return columns;
90
+ }
91
+
92
+ private buildDefaultQuickFilters(): QuickFilterConfig[]
93
+ {
94
+ const getDefaults = this.props.entity.client.getQuickFilters;
95
+ if (!getDefaults)
96
+ return [];
97
+
98
+ const columns = this.getColumns();
99
+ const ans: QuickFilterConfig[] = [];
100
+ for (const def of getDefaults())
101
+ {
102
+ const col = columns.find(c => c.name === def.column);
103
+ if (!col)
104
+ continue;
105
+ const columnType = new ObjectService(col.type).getEnum(VariableType, VariableType.Any);
106
+ ans.push({
107
+ id: `default-${col.table.name}-${col.name}`,
108
+ column: {
109
+ table: { name: col.table.name, text: col.table.text },
110
+ name: col.name,
111
+ text: col.text,
112
+ type: col.type,
113
+ columnType,
114
+ },
115
+ operatorName: (def as { operator?: string }).operator,
116
+ });
117
+ }
118
+ return ans;
119
+ }
120
+
121
+ private filterItemTypeConverter(type: string): FilterItemColumnType
122
+ {
123
+ let t = new ObjectService(type).getEnum(VariableType, VariableType.Any);
124
+ let builder = new FilterItemColumnTypeBuilder(t);
125
+ return builder.runSynch(() => { }) ?? FilterItemColumnType.Unknown;
126
+ }
127
+
128
+ private getIncomingFilterItems(): FilterItem[] | undefined
129
+ {
130
+ try
131
+ {
132
+ let encoded = this.props.url.getQuery("filters");
133
+ if (encoded)
134
+ return FilterItem.decode(encoded) ?? undefined;
135
+ } catch (error)
136
+ {
137
+ }
138
+ return undefined;
139
+ }
140
+
141
+ private itemMatchesQuickFilter(item: FilterItem): boolean
142
+ {
143
+ return this.state.quick_filter_configs.some(c =>
144
+ c.column.table.name === item.table.name && c.column.name === item.column.name);
145
+ }
146
+ private getIncomingBoxItems(): FilterItem[] | undefined
147
+ {
148
+ let items = this.getIncomingFilterItems();
149
+ if (!items)
150
+ return undefined;
151
+ return items.filter(i => !this.itemMatchesQuickFilter(i));
152
+ }
153
+ private getIncomingQuickItems(): FilterItem[]
154
+ {
155
+ let items = this.getIncomingFilterItems();
156
+ if (!items)
157
+ return [];
158
+ return items.filter(i => this.itemMatchesQuickFilter(i));
159
+ }
160
+
161
+ private encodeFilters(items: FilterItem[]): string
162
+ {
163
+ let command = items.map(item =>
164
+ {
165
+ let key = item.operator.name.replace(/\s+/g, "").toLowerCase();
166
+ let values = item.values.map(v => (v ?? "").toString().replace(/;/g, "\\;"));
167
+ return [item.table.name, item.column.name, item.not ? "1" : "0", key, ...values].join(";");
168
+ }).join(";");
169
+ return EncodingOperation.Base64Encode(command);
170
+ }
171
+
172
+ private syncQueryFromFilters()
173
+ {
174
+ let items = this.getFilterItems();
175
+ let url = new URL(window.location.href);
176
+ let encoded = items.length > 0 ? this.encodeFilters(items) : "";
177
+ if (encoded)
178
+ url.searchParams.set("filters", encoded);
179
+ else
180
+ url.searchParams.delete("filters");
181
+ window.history.replaceState({}, "", url.toString());
182
+ }
183
+
184
+ public reload(page: number | null, size: number | null): Promise<void> | undefined
185
+ {
186
+ return this.NSTable_Main.current?.reload(page, size);
187
+ }
188
+ public getSelectedIDs(): string[]
189
+ {
190
+ return this.NSTable_Main.current?.getSelectedIDs() ?? [];
191
+ }
192
+ public getSelectedRows(): RowType[]
193
+ {
194
+ return this.NSTable_Main.current?.getSelectedRows() ?? [];
195
+ }
196
+ public setSelectedIDs(ids: string[], rows: RowType[], callback?: () => void)
197
+ {
198
+ this.NSTable_Main.current?.setSelectedIDs(ids, rows, callback);
199
+ }
200
+ public getSortItems(): SortItem[]
201
+ {
202
+ return this.NSTable_Main.current?.getSortItems() ?? [];
203
+ }
204
+ public setSortItems(items: SortItem[] | null)
205
+ {
206
+ this.NSTable_Main.current?.setSortItems(items);
207
+ }
208
+ public getVisibleColumns(): { table: string, column: string }[]
209
+ {
210
+ return this.NSTable_Main.current?.getVisibleColumns() ?? [];
211
+ }
212
+ public setVisibleColumns(visible_columns: { table: string, column: string }[])
213
+ {
214
+ this.NSTable_Main.current?.setVisibleColumns(visible_columns);
215
+ }
216
+ public getFilterBoxItems(): FilterItem[]
217
+ {
218
+ return this.NSFilterBox_Top.current?.getFilterItems() ?? [];
219
+ }
220
+ public getQuickFilterItems(): FilterItem[]
221
+ {
222
+ return this.NSAQuickFilterBar_Ref.current?.getFilterItems() ?? [];
223
+ }
224
+ public getFilterItems(): FilterItem[]
225
+ {
226
+ return [...this.getFilterBoxItems(), ...this.getQuickFilterItems()];
227
+ }
228
+
229
+ private reloadFromFilters()
230
+ {
231
+ this.syncQueryFromFilters();
232
+ this.NSTable_Main.current?.setSelectedIDs([], []);
233
+ this.NSTable_Main.current?.reload(null, null);
234
+ }
235
+
236
+ private onFilterBoxChanged = () =>
237
+ {
238
+ this.reloadFromFilters();
239
+ this.setState(prev => ({ filter_revision: prev.filter_revision + 1 }));
240
+ };
241
+
242
+ private buildButtons(): NSButtonProps[]
243
+ {
244
+ const buttons: NSButtonProps[] = [
245
+ {
246
+ title: "",
247
+ icon: { src: "https://static.namirasoft.com/image/concept/sliders/blue.svg", alt: "filter" },
248
+ attributes: { title: "Quick Filters" },
249
+ onClick: {
250
+ action: () => this.setState({ show_quick_filter_dialog: true }),
251
+ showLoading: false,
252
+ },
253
+ },
254
+ ];
255
+ return [...buttons, ...(this.props.buttons ?? [])];
256
+ }
257
+
258
+ private renderFilterHeader(): ReactNode
259
+ {
260
+ return (
261
+ <NSFilterBox
262
+ ref={this.NSFilterBox_Top}
263
+ filterItems={this.getIncomingBoxItems()}
264
+ getTables={() =>
265
+ {
266
+ return this.props.entity.tables.map(table =>
267
+ {
268
+ let columns = table.table.getColumns().map(c => ({ id: c.name, ...c, type: this.filterItemTypeConverter(c.type) }));
269
+ columns = columns.filter(c =>
270
+ {
271
+ if (this.props.ui?.search_box?.exclude?.show?.column)
272
+ if (this.props.ui?.search_box?.exclude.show?.column(table.table.name, c.name))
273
+ return false;
274
+ return true;
275
+ });
276
+ return { name: table.table.name, text: table.table.text, columns, required: table.required };
277
+ }).filter(t =>
278
+ {
279
+ if (this.props.ui?.search_box?.exclude?.show?.table)
280
+ if (this.props.ui?.search_box?.exclude.show.table(t.name))
281
+ return false;
282
+ return true;
283
+ });
284
+ }}
285
+ getMoreTables={async () =>
286
+ {
287
+ let ans: NSFilterBoxProps_Table[] = [];
288
+ if (this.props.ctf.enabled)
289
+ try
290
+ {
291
+ if (this.props.ctf.rows?.fields)
292
+ if (this.props.ctf.rows.fields.length > 0)
293
+ {
294
+ let name = this.props.entity.name + "_field";
295
+ ans.push({
296
+ name,
297
+ text: "Fields",
298
+ columns: [{
299
+ id: "field_id",
300
+ name: "field_id",
301
+ text: "ID",
302
+ type: FilterItemColumnType.Unknown,
303
+ getValues: async (search) =>
304
+ {
305
+ return this.props.ctf.rows?.fields?.filter(c => SearchOperation.match(c.id, search)).map(c => { return { value: c.id, title: c.id } }) ?? [];
306
+ }
307
+ }, {
308
+ id: "field_name",
309
+ name: "field_id",
310
+ text: "Name",
311
+ type: FilterItemColumnType.Unknown,
312
+ getValues: async (search) =>
313
+ {
314
+ return this.props.ctf.rows?.fields?.filter(c => SearchOperation.match(c.name, search)).map(c => { return { value: c.id, title: c.name } }) ?? [];
315
+ }
316
+ }, {
317
+ id: "field_value",
318
+ name: "value",
319
+ text: "Value",
320
+ type: FilterItemColumnType.Unknown
321
+ },
322
+ ...this.props.ctf.rows?.fields.map(f =>
323
+ {
324
+ return {
325
+ id: f.id,
326
+ name: f.id,
327
+ text: f.name,
328
+ type: this.filterItemTypeConverter(f.type.type.type),
329
+ getValues: async (search: string) =>
330
+ {
331
+ let values = await this.props.entity.server.value_list(name, "value", search, f.id, null);
332
+ return values.map(v => { return { value: v, title: v } });
333
+ }
334
+ };
335
+ }),],
336
+ required: false
337
+ });
338
+ }
339
+
340
+ if (this.props.ctf.rows?.categories)
341
+ if (this.props.ctf.rows?.categories.length > 0)
342
+ ans.push({
343
+ name: this.props.entity.name + "_category",
344
+ text: "Categories",
345
+ columns: [{
346
+ id: "category_id",
347
+ name: "category_id",
348
+ text: "ID",
349
+ type: FilterItemColumnType.Unknown,
350
+ getValues: async (search) =>
351
+ {
352
+ return this.props.ctf.rows?.categories?.filter(c => SearchOperation.match(c.id, search)).map(c => { return { value: c.id, title: c.id } }) ?? [];
353
+ }
354
+ }, {
355
+ id: "category_name",
356
+ name: "category_id",
357
+ text: "Name",
358
+ type: FilterItemColumnType.Unknown,
359
+ getValues: async (search) =>
360
+ {
361
+ return this.props.ctf.rows?.categories?.filter(c => SearchOperation.match(c.name, search)).map(c => { return { value: c.id, title: c.name } }) ?? [];
362
+ }
363
+ }],
364
+ required: false
365
+ });
366
+
367
+ } catch (error)
368
+ {
369
+ }
370
+ // todo add tags
371
+ return ans;
372
+ }}
373
+ getValues={async (table, column, value) =>
374
+ {
375
+ if (this.props.ui?.search_box?.exclude?.load_value)
376
+ if (this.props.ui?.search_box?.exclude?.load_value(table.name, column.name))
377
+ return [];
378
+ if (column.type === FilterItemColumnType.Boolean)
379
+ {
380
+ const col = this.getColumns().find(c => c.table.name === table.name && c.name === column.name);
381
+ return [true, false].map(b =>
382
+ {
383
+ const formatted = col ? col.formatter.format(b, col, { value: {} } as any, true) : null;
384
+ return { value: String(b), title: formatted != null ? String(formatted) : String(b) };
385
+ });
386
+ }
387
+ let values = await this.props.entity.server.value_list(table.name, column.name, value, null, null);
388
+ return values.map(v => { return { value: v, title: v } });
389
+ }}
390
+ onChanged={this.onFilterBoxChanged}
391
+ />
392
+ );
393
+ }
394
+
395
+ private getOrderedColumns(): TableColumnInfo[]
396
+ {
397
+ const all = this.getColumns();
398
+ const vk = this.state.visible_column_keys;
399
+ if (vk.length === 0)
400
+ return all;
401
+ const ordered = vk.map(k => all.find(c => c.table.name + "." + c.name === k)).filter((c): c is TableColumnInfo => !!c);
402
+ const rest = all.filter(c => !vk.includes(c.table.name + "." + c.name));
403
+ return [...ordered, ...rest];
404
+ }
405
+
406
+ override render(): ReactNode
407
+ {
408
+ const filterBoxItems = this.NSFilterBox_Top.current?.getFilterItems() ?? [];
409
+ const filterChips = filterBoxItems.length > 0 && (
410
+ <>
411
+ <NSFilterBoxItems
412
+ filterItems={filterBoxItems}
413
+ onClearFilterItems={() => this.NSFilterBox_Top.current?.setFilterItems([])}
414
+ onRemoveFilterItem={(item) => this.NSFilterBox_Top.current?.removeFilterItem(item)}
415
+ />
416
+ <NSSpace size={NSSpaceSizeType.MINI} />
417
+ </>
418
+ );
419
+
420
+ const quickFilterBar = this.state.quick_filter_configs.length > 0 && (
421
+ <NSAQuickFilterBar
422
+ key={this.state.quick_filter_configs.map(c => c.id).join("-")}
423
+ ref={this.NSAQuickFilterBar_Ref}
424
+ configs={this.state.quick_filter_configs}
425
+ initialItems={this.getIncomingQuickItems()}
426
+ getValues={async (tableName, columnName, search) =>
427
+ {
428
+ const values = await this.props.entity.server.value_list(tableName, columnName, search, null, null);
429
+ const col = this.getColumns().find(c => c.table.name === tableName && c.name === columnName);
430
+ return values.map(v =>
431
+ {
432
+ const formatted = col ? col.formatter.format(v, col, { value: {} } as any, true) : null;
433
+ return { value: v, title: formatted != null ? String(formatted) : v };
434
+ });
435
+ }}
436
+ onChanged={() => this.reloadFromFilters()}
437
+ />
438
+ );
439
+
440
+ return (
441
+ <>
442
+ <NSTable<RowType>
443
+ id={this.props.id}
444
+ classList={this.props.classList}
445
+ style={this.props.style}
446
+ ref={this.NSTable_Main}
447
+ name={NamingConvention.lower_case_dash.convert(this.props.entity.name, NamingConvention.Pascal_Case_Space)}
448
+ checkbox={this.props.checkbox ?? true}
449
+ headerChildren={this.renderFilterHeader()}
450
+ buttons={this.buildButtons()}
451
+ columns={this.getOrderedColumns()}
452
+ getRows={async (page, size, sorts) =>
453
+ {
454
+ let res: { rows: RowType[], count: number } = { rows: [], count: 0 };
455
+ if (this.props.entity.server.list)
456
+ res = await this.props.entity.server.list(this.getFilterItems(), page, size, sorts, null);
457
+ this.setState({ res });
458
+ return res;
459
+ }}
460
+ getRowKey={(row) => row.value.id.toString()}
461
+ sort={{
462
+ onSort: () => { this.NSTable_Main.current?.reload(null, null); },
463
+ }}
464
+ getRowAttributes={(row_value, row_index) => this.props.ui?.getRowAttributes?.(row_value, row_index, this.state.res) ?? {}}
465
+ getColumnAttributes={this.props.ui?.getColumnAttributes}
466
+ getCellFormattedValue={this.props.ui?.getCellFormattedValue}
467
+ onVisibleColumnsChanged={(visible_columns) => this.setState({ visible_column_keys: visible_columns.map(c => c.table + "." + c.column) })}
468
+ onSelectedIDsChanged={() => this.props.onSelectionChanged?.()}
469
+ >
470
+ {filterChips}
471
+ {quickFilterBar}
472
+ </NSTable>
473
+ {
474
+ this.state.show_quick_filter_dialog &&
475
+ <NSAQuickFilterDialog
476
+ configs={this.state.quick_filter_configs}
477
+ getColumns={() => this.getColumns()}
478
+ typeConverter={(type: string) => new ObjectService(type).getEnum(VariableType, VariableType.Any)}
479
+ onSave={configs =>
480
+ {
481
+ NSACacheService.saveQuickFilters(this.props.entity.name, configs);
482
+ this.setState({ quick_filter_configs: configs }, () => this.reloadFromFilters());
483
+ }}
484
+ onConfirm={configs =>
485
+ {
486
+ NSACacheService.saveQuickFilters(this.props.entity.name, configs);
487
+ this.setState({ quick_filter_configs: configs, show_quick_filter_dialog: false }, () => this.reloadFromFilters());
488
+ }}
489
+ onClose={() => this.setState({ show_quick_filter_dialog: false })}
490
+ />
491
+ }
492
+ </>
493
+ );
494
+ }
495
495
  }