namirasoft-account-react 1.5.38 → 1.5.39

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 (145) 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/FieldCacheService.js +4 -0
  6. package/dist/FieldCacheService.js.map +1 -1
  7. package/dist/NSARouterMaker.js +1 -1
  8. package/dist/NSARouterMaker.js.map +1 -1
  9. package/dist/Router.d.ts +1 -1
  10. package/dist/UseParams.d.ts +1 -1
  11. package/dist/components/NSAAccessListDialog.d.ts +2 -2
  12. package/dist/components/NSAAccessListDialog.module.css +71 -71
  13. package/dist/components/NSABoxSecret.d.ts +1 -1
  14. package/dist/components/NSABoxSecret.module.css +23 -23
  15. package/dist/components/NSAMasterMenu.d.ts +1 -1
  16. package/dist/components/NSAMasterMenu.js +4 -0
  17. package/dist/components/NSAMasterMenu.js.map +1 -1
  18. package/dist/components/NSAMasterMenu.module.css +250 -250
  19. package/dist/components/NSAMasterMenuItem.d.ts +1 -1
  20. package/dist/components/NSAMessageListDialog.d.ts +1 -1
  21. package/dist/components/NSAMessageListDialog.module.css +99 -99
  22. package/dist/components/NSANavigationGuard.d.ts +1 -1
  23. package/dist/components/NSAProductListDialog.d.ts +1 -1
  24. package/dist/components/NSAProductListDialog.module.css +44 -44
  25. package/dist/components/NSATaskBar.d.ts +1 -1
  26. package/dist/components/NSATaskBar.module.css +57 -57
  27. package/dist/components/NSAUserDialog.d.ts +1 -1
  28. package/dist/components/NSAUserDialog.module.css +67 -67
  29. package/dist/components/NSAWorkspaceListDialog.d.ts +1 -1
  30. package/dist/components/NSAWorkspaceListDialog.module.css +41 -41
  31. package/dist/components/NSFBoxCategoryScope.d.ts +1 -1
  32. package/dist/components/NSFBoxField.d.ts +1 -1
  33. package/dist/components/NSFBoxSlot.d.ts +1 -1
  34. package/dist/components/NSFBoxWrapper.d.ts +1 -1
  35. package/dist/components/NSLabelSecret.d.ts +1 -1
  36. package/dist/components/quickfilter/NSAFilterBoxEnum.module.css +51 -51
  37. package/dist/components/quickfilter/NSAQuickFilterBar.d.ts +1 -1
  38. package/dist/components/quickfilter/NSAQuickFilterBar.module.css +20 -20
  39. package/dist/components/quickfilter/NSAQuickFilterDialog.d.ts +1 -1
  40. package/dist/components/quickfilter/NSAQuickFilterDialog.module.css +74 -74
  41. package/dist/layouts/NSALayout.d.ts +1 -1
  42. package/dist/layouts/NSASectionEdit.d.ts +1 -1
  43. package/dist/layouts/NSASectionEditTabPage.d.ts +1 -1
  44. package/dist/layouts/NSASectionEditTabPage.module.css +4 -4
  45. package/dist/layouts/NSASectionList.d.ts +1 -1
  46. package/dist/layouts/NSASectionList.module.css +24 -24
  47. package/dist/layouts/NSASectionView.d.ts +1 -1
  48. package/dist/layouts/NSASectionViewTabMore.d.ts +1 -1
  49. package/dist/layouts/NSASectionViewTabPage.d.ts +1 -1
  50. package/dist/layouts/NSASectionViewTabPage.module.css +47 -47
  51. package/dist/pages/NSAConsentPage.module.css +26 -26
  52. package/dist/pages/NSAEmailVerificationPage.d.ts +1 -1
  53. package/dist/pages/NSAHomePage.d.ts +1 -1
  54. package/dist/pages/NSAHomePage.module.css +41 -41
  55. package/dist/pages/NSALoginPage.d.ts +1 -1
  56. package/dist/pages/NSALoginPage.module.css +26 -26
  57. package/dist/pages/NSAPhoneVerificationPage.d.ts +1 -1
  58. package/dist/pages/NSAVerificationPage.d.ts +1 -1
  59. package/dist/pages/NSAVerificationPage.module.css +31 -31
  60. package/package.json +94 -94
  61. package/public/index.html +21 -21
  62. package/src/App.tsx +72 -72
  63. package/src/CTFRow.ts +7 -7
  64. package/src/FieldCacheService.tsx +113 -108
  65. package/src/IEntityInfo.ts +33 -33
  66. package/src/NSACacheService.ts +126 -126
  67. package/src/NSAFilterOperators.ts +94 -94
  68. package/src/NSARouterMaker.tsx +141 -141
  69. package/src/NSARouterMakerProps.ts +23 -23
  70. package/src/NSARouterMakerResult.ts +24 -24
  71. package/src/NSFRouterMaker.tsx +35 -35
  72. package/src/NSFRouterProps.ts +7 -7
  73. package/src/NSFRoutes.ts +30 -30
  74. package/src/Router.tsx +48 -48
  75. package/src/UseParams.tsx +17 -17
  76. package/src/components/NSAAccessListDialog.module.css +71 -71
  77. package/src/components/NSAAccessListDialog.tsx +178 -178
  78. package/src/components/NSABoxSecret.module.css +23 -23
  79. package/src/components/NSABoxSecret.tsx +264 -264
  80. package/src/components/NSAMasterMenu.module.css +250 -250
  81. package/src/components/NSAMasterMenu.tsx +174 -169
  82. package/src/components/NSAMasterMenuItem.tsx +250 -250
  83. package/src/components/NSAMessageListDialog.module.css +99 -99
  84. package/src/components/NSAMessageListDialog.tsx +144 -144
  85. package/src/components/NSANavigationGuard.tsx +79 -79
  86. package/src/components/NSAProductListDialog.module.css +44 -44
  87. package/src/components/NSAProductListDialog.tsx +88 -88
  88. package/src/components/NSATable.tsx +494 -494
  89. package/src/components/NSATaskBar.module.css +57 -57
  90. package/src/components/NSATaskBar.tsx +193 -193
  91. package/src/components/NSAUserDialog.module.css +67 -67
  92. package/src/components/NSAUserDialog.tsx +122 -122
  93. package/src/components/NSAWorkspaceListDialog.module.css +41 -41
  94. package/src/components/NSAWorkspaceListDialog.tsx +147 -147
  95. package/src/components/NSFBoxCategoryScope.tsx +52 -52
  96. package/src/components/NSFBoxField.tsx +37 -37
  97. package/src/components/NSFBoxSlot.tsx +73 -73
  98. package/src/components/NSFBoxWrapper.tsx +69 -69
  99. package/src/components/NSLabelSecret.tsx +37 -37
  100. package/src/components/quickfilter/NSAFilterBoxBase.tsx +110 -110
  101. package/src/components/quickfilter/NSAFilterBoxBoolean.tsx +72 -72
  102. package/src/components/quickfilter/NSAFilterBoxDate.tsx +110 -110
  103. package/src/components/quickfilter/NSAFilterBoxDateTime.tsx +110 -110
  104. package/src/components/quickfilter/NSAFilterBoxEnum.module.css +51 -51
  105. package/src/components/quickfilter/NSAFilterBoxEnum.tsx +103 -103
  106. package/src/components/quickfilter/NSAFilterBoxNumber.tsx +145 -145
  107. package/src/components/quickfilter/NSAFilterBoxString.tsx +83 -83
  108. package/src/components/quickfilter/NSAFilterBoxTime.tsx +106 -106
  109. package/src/components/quickfilter/NSAQuickFilterBar.module.css +20 -20
  110. package/src/components/quickfilter/NSAQuickFilterBar.tsx +142 -142
  111. package/src/components/quickfilter/NSAQuickFilterDialog.module.css +74 -74
  112. package/src/components/quickfilter/NSAQuickFilterDialog.tsx +297 -297
  113. package/src/css.d.ts +13 -13
  114. package/src/formatters/SecretFormatter.tsx +24 -24
  115. package/src/index.tsx +27 -27
  116. package/src/layouts/Actions.ts +146 -146
  117. package/src/layouts/CFTUtil.ts +18 -18
  118. package/src/layouts/NSALayout.tsx +750 -750
  119. package/src/layouts/NSALayout_Field.ts +125 -125
  120. package/src/layouts/NSASectionEdit.tsx +279 -279
  121. package/src/layouts/NSASectionEditTabPage.module.css +4 -4
  122. package/src/layouts/NSASectionEditTabPage.tsx +256 -256
  123. package/src/layouts/NSASectionList.module.css +24 -24
  124. package/src/layouts/NSASectionList.tsx +165 -165
  125. package/src/layouts/NSASectionView.tsx +98 -98
  126. package/src/layouts/NSASectionViewTabMore.tsx +78 -78
  127. package/src/layouts/NSASectionViewTabPage.module.css +47 -47
  128. package/src/layouts/NSASectionViewTabPage.tsx +400 -400
  129. package/src/main.ts +52 -52
  130. package/src/pages/NSAConsentPage.module.css +26 -26
  131. package/src/pages/NSAConsentPage.tsx +120 -120
  132. package/src/pages/NSAEmailVerificationPage.tsx +30 -30
  133. package/src/pages/NSAHomePage.module.css +41 -41
  134. package/src/pages/NSAHomePage.tsx +113 -113
  135. package/src/pages/NSALoginPage.module.css +26 -26
  136. package/src/pages/NSALoginPage.tsx +87 -87
  137. package/src/pages/NSAPhoneVerificationPage.tsx +106 -106
  138. package/src/pages/NSAVerificationPage.module.css +31 -31
  139. package/src/pages/NSAVerificationPage.tsx +185 -185
  140. package/src/pages/NSFCategoryEditPage.tsx +87 -87
  141. package/src/pages/NSFCategoryListPage.tsx +23 -23
  142. package/src/pages/NSFCategoryViewPage.tsx +23 -23
  143. package/src/pages/NSFEntities.ts +58 -58
  144. package/src/pages/PaymentRequired.tsx +80 -80
  145. package/tsconfig.json +43 -43
@@ -1,298 +1,298 @@
1
- import { FilterItemOperator } from "namirasoft-core";
2
- import { VariableType } from "namirasoft-schema";
3
- import { NSBoxBaseCombo, NSBoxCombo, NSBoxString, NSButton, NSButtonBlue, NSColumn, NSDialog, NSNoData, NSTitle, TableColumnInfo } from "namirasoft-site-react";
4
- import { Component, Fragment } from "react";
5
- import { NSAFilterOperators } from "../../NSAFilterOperators";
6
- import Styles from "./NSAQuickFilterDialog.module.css";
7
-
8
- export interface QuickFilterConfig
9
- {
10
- id: string;
11
- title?: string;
12
- column: {
13
- table: { name: string; text: string };
14
- name: string;
15
- text: string;
16
- type: string;
17
- columnType: VariableType;
18
- };
19
- operatorName?: string;
20
- }
21
-
22
- interface NSAQuickFilterDialogProps
23
- {
24
- configs: QuickFilterConfig[];
25
- defaults?: QuickFilterConfig[];
26
- getColumns: () => TableColumnInfo[];
27
- typeConverter: (type: string) => VariableType;
28
- onSave: (configs: QuickFilterConfig[]) => void;
29
- onConfirm: (configs: QuickFilterConfig[]) => void;
30
- onClose: () => void;
31
- }
32
-
33
- interface NSAQuickFilterDialogState
34
- {
35
- configs: QuickFilterConfig[];
36
- formMode: "add" | "edit" | null;
37
- editingId: string | null;
38
- formColumn: TableColumnInfo | null;
39
- formOperatorName: string | null;
40
- formTitle: string | null;
41
- formKey: number;
42
- }
43
-
44
- export class NSAQuickFilterDialog extends Component<NSAQuickFilterDialogProps, NSAQuickFilterDialogState>
45
- {
46
- constructor(props: NSAQuickFilterDialogProps)
47
- {
48
- super(props);
49
- this.state = {
50
- configs: [...props.configs],
51
- formMode: null,
52
- editingId: null,
53
- formColumn: null,
54
- formOperatorName: null,
55
- formTitle: null,
56
- formKey: 0,
57
- };
58
- }
59
-
60
- private openAdd = () =>
61
- {
62
- this.setState(prev => ({
63
- formMode: "add",
64
- editingId: null,
65
- formColumn: null,
66
- formOperatorName: null,
67
- formTitle: null,
68
- formKey: prev.formKey + 1,
69
- }));
70
- };
71
-
72
- private openEdit = (config: QuickFilterConfig) =>
73
- {
74
- const col = this.props.getColumns().find(
75
- c => c.table.name === config.column.table.name && c.name === config.column.name
76
- ) ?? null;
77
- this.setState(prev => ({
78
- formMode: "edit",
79
- editingId: config.id,
80
- formColumn: col,
81
- formOperatorName: config.operatorName ?? null,
82
- formTitle: config.title ?? null,
83
- formKey: prev.formKey + 1,
84
- }));
85
- };
86
-
87
- private deleteConfig = (id: string) =>
88
- {
89
- this.setState(prev => ({ configs: prev.configs.filter(c => c.id !== id) }));
90
- };
91
-
92
- private hasChanges(): boolean
93
- {
94
- return JSON.stringify(this.state.configs) !== JSON.stringify(this.props.configs);
95
- }
96
-
97
- // compares on column/operator (not id) so a manually re-added default still counts
98
- private isAtDefaults(): boolean
99
- {
100
- const key = (c: QuickFilterConfig) => `${c.column.table.name}|${c.column.name}|${c.operatorName ?? ""}|${c.title ?? ""}`;
101
- const defaults = this.props.defaults ?? [];
102
- return this.state.configs.length === defaults.length
103
- && this.state.configs.every((c, i) => key(c) === key(defaults[i]));
104
- }
105
-
106
- private resetToDefaults = () =>
107
- {
108
- this.setState({ configs: [...(this.props.defaults ?? [])] });
109
- };
110
-
111
- private saveForm = () =>
112
- {
113
- const { formColumn, formOperatorName, formTitle, formMode, editingId, configs } = this.state;
114
- if (!formColumn) return;
115
-
116
- const columnType = this.props.typeConverter(formColumn.type);
117
- const isBoolean = columnType === VariableType.Boolean;
118
-
119
- const newConfig: QuickFilterConfig = {
120
- id: formMode === "edit" && editingId ? editingId : crypto.randomUUID(),
121
- title: formTitle?.trim() || undefined,
122
- column: {
123
- table: { name: formColumn.table.name, text: formColumn.table.text },
124
- name: formColumn.name,
125
- text: formColumn.text,
126
- type: formColumn.type,
127
- columnType,
128
- },
129
- operatorName: isBoolean ? undefined : (formOperatorName ?? undefined),
130
- };
131
-
132
- const updatedConfigs = formMode === "edit" && editingId
133
- ? configs.map(c => c.id === editingId ? newConfig : c)
134
- : [...configs, newConfig];
135
-
136
- this.setState({ configs: updatedConfigs, formMode: null }, () =>
137
- {
138
- this.props.onSave(updatedConfigs);
139
- });
140
- };
141
-
142
- override render()
143
- {
144
- const { onClose, onConfirm, getColumns, typeConverter } = this.props;
145
- const { configs, formMode, formColumn, formOperatorName, formKey } = this.state;
146
-
147
- const columns = getColumns();
148
- const columnType = formColumn ? typeConverter(formColumn.type) : null;
149
- const isBoolean = columnType === VariableType.Boolean;
150
- const operators = columnType && !isBoolean ? NSAFilterOperators.getQuickFilterOperators(columnType) : [];
151
-
152
- return (
153
- <NSDialog
154
- center_dialog
155
- closeButton={{ show: true }}
156
- onClose={onClose}
157
- >
158
- <NSColumn classList={["align-items-center"]}>
159
- <NSTitle
160
- title="Quick Filters"
161
- style={{ marginBottom: 0, fontSize: 24 }}
162
- />
163
-
164
- {
165
- configs.length === 0 && !formMode &&
166
- <NSNoData lable="No quick filters defined" style={{ marginBottom: 16, fontSize: 20 }} />
167
- }
168
-
169
- {
170
- configs.length > 0 && !formMode && (
171
- <NSColumn classList={["gap-2"]}>
172
- {
173
- configs.map(cfg =>
174
- {
175
- const opLabel = cfg.operatorName
176
- ? FilterItemOperator.getByName(cfg.operatorName).name
177
- : "—";
178
- return (
179
- <div key={cfg.id} className={Styles.qf_item}>
180
- <div className={Styles.qf_item_info}>
181
- <span className={Styles.qf_item_label}>{cfg.title ?? cfg.column.text}</span>
182
- <span className={Styles.qf_item_op}>{opLabel}</span>
183
- </div>
184
- <div className={Styles.qf_item_actions}>
185
- <NSButton
186
- title=""
187
- icon={{ src: "https://static.namirasoft.com/image/concept/edit/blue.svg", alt: "edit" }}
188
- classList={[Styles.qf_item_btn]}
189
- onClick={{ action: () => this.openEdit(cfg), showLoading: false }}
190
- />
191
- <NSButton
192
- title=""
193
- icon={{ src: "https://static.namirasoft.com/image/concept/delete/blue.svg", alt: "delete" }}
194
- classList={[Styles.qf_item_btn]}
195
- onClick={{ action: () => this.deleteConfig(cfg.id), showLoading: false }}
196
- />
197
- </div>
198
- </div>
199
- );
200
- })
201
- }
202
- </NSColumn>
203
- )
204
- }
205
-
206
- {
207
- formMode &&
208
- <Fragment key={formKey}>
209
- <NSBoxString
210
- title="Title"
211
- required={false}
212
- defaultValue={this.state.formTitle ?? undefined}
213
- onChanged={e => this.setState({ formTitle: e.getValue() || null })}
214
- />
215
- <NSBoxBaseCombo<TableColumnInfo>
216
- title="Column"
217
- required
218
- defaultValue={formColumn?.name}
219
- getItems={async () => ({ count: columns.length, rows: columns })}
220
- getTitle={c => c.text}
221
- getValue={c => c.name}
222
- getSort={() => null}
223
- multiple={false}
224
- onChanged={e =>
225
- {
226
- const col = e.getDataOne();
227
- this.setState({ formColumn: col ?? null, formOperatorName: null });
228
- }}
229
- menu={{
230
- builtin: {
231
- copy: { enabled: false, getValue: () => "" }
232
- },
233
- items: []
234
- }}
235
- />
236
- <NSBoxCombo
237
- key={formColumn?.name}
238
- title="Operator"
239
- required
240
- disabled={!formColumn || isBoolean}
241
- defaultValue={formOperatorName ?? undefined}
242
- getOptions={() => operators.map(op => ({ value: NSAFilterOperators.getOperatorKey(op), title: `${op.sign} (${op.name})` }))}
243
- multiple={false}
244
- searchable={false}
245
- onChanged={e => this.setState({ formOperatorName: e.getValueOne(false) ?? null })}
246
- menu={{
247
- builtin: {
248
- copy: { enabled: false, getValue: () => "" }
249
- },
250
- items: []
251
- }}
252
- />
253
- <NSButtonBlue
254
- title="Save"
255
- onClick={{ action: this.saveForm, showLoading: false }}
256
- />
257
- <NSButton
258
- title=""
259
- icon={{ src: "https://static.namirasoft.com/image/concept/arrow/left/blue.svg", alt: "back" }}
260
- classList={[Styles.qf_back_btn]}
261
- onClick={{ action: () => this.setState({ formMode: null }), showLoading: false }}
262
- style={{ width: 40, height: 40 }}
263
- />
264
- </Fragment>
265
- }
266
-
267
- {
268
- !formMode &&
269
- <>
270
- {
271
- (this.props.defaults?.length ?? 0) > 0 && !this.isAtDefaults() &&
272
- <NSButton
273
- title=""
274
- icon={{ src: "https://static.namirasoft.com/image/concept/refresh/blue.svg", alt: "reset" }}
275
- classList={[Styles.qf_back_btn]}
276
- onClick={{ action: this.resetToDefaults, showLoading: false }}
277
- style={{ width: 40, height: 40 }}
278
- />
279
- }
280
- <NSButton
281
- title="+ Add Filter"
282
- onClick={{ action: this.openAdd, showLoading: false }}
283
- style={{ border: "1px solid #000" }}
284
- />
285
- {
286
- this.hasChanges() &&
287
- <NSButtonBlue
288
- title="Save Changes"
289
- onClick={{ action: () => onConfirm(this.state.configs), showLoading: false }}
290
- />
291
- }
292
- </>
293
- }
294
- </NSColumn>
295
- </NSDialog>
296
- );
297
- }
1
+ import { FilterItemOperator } from "namirasoft-core";
2
+ import { VariableType } from "namirasoft-schema";
3
+ import { NSBoxBaseCombo, NSBoxCombo, NSBoxString, NSButton, NSButtonBlue, NSColumn, NSDialog, NSNoData, NSTitle, TableColumnInfo } from "namirasoft-site-react";
4
+ import { Component, Fragment } from "react";
5
+ import { NSAFilterOperators } from "../../NSAFilterOperators";
6
+ import Styles from "./NSAQuickFilterDialog.module.css";
7
+
8
+ export interface QuickFilterConfig
9
+ {
10
+ id: string;
11
+ title?: string;
12
+ column: {
13
+ table: { name: string; text: string };
14
+ name: string;
15
+ text: string;
16
+ type: string;
17
+ columnType: VariableType;
18
+ };
19
+ operatorName?: string;
20
+ }
21
+
22
+ interface NSAQuickFilterDialogProps
23
+ {
24
+ configs: QuickFilterConfig[];
25
+ defaults?: QuickFilterConfig[];
26
+ getColumns: () => TableColumnInfo[];
27
+ typeConverter: (type: string) => VariableType;
28
+ onSave: (configs: QuickFilterConfig[]) => void;
29
+ onConfirm: (configs: QuickFilterConfig[]) => void;
30
+ onClose: () => void;
31
+ }
32
+
33
+ interface NSAQuickFilterDialogState
34
+ {
35
+ configs: QuickFilterConfig[];
36
+ formMode: "add" | "edit" | null;
37
+ editingId: string | null;
38
+ formColumn: TableColumnInfo | null;
39
+ formOperatorName: string | null;
40
+ formTitle: string | null;
41
+ formKey: number;
42
+ }
43
+
44
+ export class NSAQuickFilterDialog extends Component<NSAQuickFilterDialogProps, NSAQuickFilterDialogState>
45
+ {
46
+ constructor(props: NSAQuickFilterDialogProps)
47
+ {
48
+ super(props);
49
+ this.state = {
50
+ configs: [...props.configs],
51
+ formMode: null,
52
+ editingId: null,
53
+ formColumn: null,
54
+ formOperatorName: null,
55
+ formTitle: null,
56
+ formKey: 0,
57
+ };
58
+ }
59
+
60
+ private openAdd = () =>
61
+ {
62
+ this.setState(prev => ({
63
+ formMode: "add",
64
+ editingId: null,
65
+ formColumn: null,
66
+ formOperatorName: null,
67
+ formTitle: null,
68
+ formKey: prev.formKey + 1,
69
+ }));
70
+ };
71
+
72
+ private openEdit = (config: QuickFilterConfig) =>
73
+ {
74
+ const col = this.props.getColumns().find(
75
+ c => c.table.name === config.column.table.name && c.name === config.column.name
76
+ ) ?? null;
77
+ this.setState(prev => ({
78
+ formMode: "edit",
79
+ editingId: config.id,
80
+ formColumn: col,
81
+ formOperatorName: config.operatorName ?? null,
82
+ formTitle: config.title ?? null,
83
+ formKey: prev.formKey + 1,
84
+ }));
85
+ };
86
+
87
+ private deleteConfig = (id: string) =>
88
+ {
89
+ this.setState(prev => ({ configs: prev.configs.filter(c => c.id !== id) }));
90
+ };
91
+
92
+ private hasChanges(): boolean
93
+ {
94
+ return JSON.stringify(this.state.configs) !== JSON.stringify(this.props.configs);
95
+ }
96
+
97
+ // compares on column/operator (not id) so a manually re-added default still counts
98
+ private isAtDefaults(): boolean
99
+ {
100
+ const key = (c: QuickFilterConfig) => `${c.column.table.name}|${c.column.name}|${c.operatorName ?? ""}|${c.title ?? ""}`;
101
+ const defaults = this.props.defaults ?? [];
102
+ return this.state.configs.length === defaults.length
103
+ && this.state.configs.every((c, i) => key(c) === key(defaults[i]));
104
+ }
105
+
106
+ private resetToDefaults = () =>
107
+ {
108
+ this.setState({ configs: [...(this.props.defaults ?? [])] });
109
+ };
110
+
111
+ private saveForm = () =>
112
+ {
113
+ const { formColumn, formOperatorName, formTitle, formMode, editingId, configs } = this.state;
114
+ if (!formColumn) return;
115
+
116
+ const columnType = this.props.typeConverter(formColumn.type);
117
+ const isBoolean = columnType === VariableType.Boolean;
118
+
119
+ const newConfig: QuickFilterConfig = {
120
+ id: formMode === "edit" && editingId ? editingId : crypto.randomUUID(),
121
+ title: formTitle?.trim() || undefined,
122
+ column: {
123
+ table: { name: formColumn.table.name, text: formColumn.table.text },
124
+ name: formColumn.name,
125
+ text: formColumn.text,
126
+ type: formColumn.type,
127
+ columnType,
128
+ },
129
+ operatorName: isBoolean ? undefined : (formOperatorName ?? undefined),
130
+ };
131
+
132
+ const updatedConfigs = formMode === "edit" && editingId
133
+ ? configs.map(c => c.id === editingId ? newConfig : c)
134
+ : [...configs, newConfig];
135
+
136
+ this.setState({ configs: updatedConfigs, formMode: null }, () =>
137
+ {
138
+ this.props.onSave(updatedConfigs);
139
+ });
140
+ };
141
+
142
+ override render()
143
+ {
144
+ const { onClose, onConfirm, getColumns, typeConverter } = this.props;
145
+ const { configs, formMode, formColumn, formOperatorName, formKey } = this.state;
146
+
147
+ const columns = getColumns();
148
+ const columnType = formColumn ? typeConverter(formColumn.type) : null;
149
+ const isBoolean = columnType === VariableType.Boolean;
150
+ const operators = columnType && !isBoolean ? NSAFilterOperators.getQuickFilterOperators(columnType) : [];
151
+
152
+ return (
153
+ <NSDialog
154
+ center_dialog
155
+ closeButton={{ show: true }}
156
+ onClose={onClose}
157
+ >
158
+ <NSColumn classList={["align-items-center"]}>
159
+ <NSTitle
160
+ title="Quick Filters"
161
+ style={{ marginBottom: 0, fontSize: 24 }}
162
+ />
163
+
164
+ {
165
+ configs.length === 0 && !formMode &&
166
+ <NSNoData lable="No quick filters defined" style={{ marginBottom: 16, fontSize: 20 }} />
167
+ }
168
+
169
+ {
170
+ configs.length > 0 && !formMode && (
171
+ <NSColumn classList={["gap-2"]}>
172
+ {
173
+ configs.map(cfg =>
174
+ {
175
+ const opLabel = cfg.operatorName
176
+ ? FilterItemOperator.getByName(cfg.operatorName).name
177
+ : "—";
178
+ return (
179
+ <div key={cfg.id} className={Styles.qf_item}>
180
+ <div className={Styles.qf_item_info}>
181
+ <span className={Styles.qf_item_label}>{cfg.title ?? cfg.column.text}</span>
182
+ <span className={Styles.qf_item_op}>{opLabel}</span>
183
+ </div>
184
+ <div className={Styles.qf_item_actions}>
185
+ <NSButton
186
+ title=""
187
+ icon={{ src: "https://static.namirasoft.com/image/concept/edit/blue.svg", alt: "edit" }}
188
+ classList={[Styles.qf_item_btn]}
189
+ onClick={{ action: () => this.openEdit(cfg), showLoading: false }}
190
+ />
191
+ <NSButton
192
+ title=""
193
+ icon={{ src: "https://static.namirasoft.com/image/concept/delete/blue.svg", alt: "delete" }}
194
+ classList={[Styles.qf_item_btn]}
195
+ onClick={{ action: () => this.deleteConfig(cfg.id), showLoading: false }}
196
+ />
197
+ </div>
198
+ </div>
199
+ );
200
+ })
201
+ }
202
+ </NSColumn>
203
+ )
204
+ }
205
+
206
+ {
207
+ formMode &&
208
+ <Fragment key={formKey}>
209
+ <NSBoxString
210
+ title="Title"
211
+ required={false}
212
+ defaultValue={this.state.formTitle ?? undefined}
213
+ onChanged={e => this.setState({ formTitle: e.getValue() || null })}
214
+ />
215
+ <NSBoxBaseCombo<TableColumnInfo>
216
+ title="Column"
217
+ required
218
+ defaultValue={formColumn?.name}
219
+ getItems={async () => ({ count: columns.length, rows: columns })}
220
+ getTitle={c => c.text}
221
+ getValue={c => c.name}
222
+ getSort={() => null}
223
+ multiple={false}
224
+ onChanged={e =>
225
+ {
226
+ const col = e.getDataOne();
227
+ this.setState({ formColumn: col ?? null, formOperatorName: null });
228
+ }}
229
+ menu={{
230
+ builtin: {
231
+ copy: { enabled: false, getValue: () => "" }
232
+ },
233
+ items: []
234
+ }}
235
+ />
236
+ <NSBoxCombo
237
+ key={formColumn?.name}
238
+ title="Operator"
239
+ required
240
+ disabled={!formColumn || isBoolean}
241
+ defaultValue={formOperatorName ?? undefined}
242
+ getOptions={() => operators.map(op => ({ value: NSAFilterOperators.getOperatorKey(op), title: `${op.sign} (${op.name})` }))}
243
+ multiple={false}
244
+ searchable={false}
245
+ onChanged={e => this.setState({ formOperatorName: e.getValueOne(false) ?? null })}
246
+ menu={{
247
+ builtin: {
248
+ copy: { enabled: false, getValue: () => "" }
249
+ },
250
+ items: []
251
+ }}
252
+ />
253
+ <NSButtonBlue
254
+ title="Save"
255
+ onClick={{ action: this.saveForm, showLoading: false }}
256
+ />
257
+ <NSButton
258
+ title=""
259
+ icon={{ src: "https://static.namirasoft.com/image/concept/arrow/left/blue.svg", alt: "back" }}
260
+ classList={[Styles.qf_back_btn]}
261
+ onClick={{ action: () => this.setState({ formMode: null }), showLoading: false }}
262
+ style={{ width: 40, height: 40 }}
263
+ />
264
+ </Fragment>
265
+ }
266
+
267
+ {
268
+ !formMode &&
269
+ <>
270
+ {
271
+ (this.props.defaults?.length ?? 0) > 0 && !this.isAtDefaults() &&
272
+ <NSButton
273
+ title=""
274
+ icon={{ src: "https://static.namirasoft.com/image/concept/refresh/blue.svg", alt: "reset" }}
275
+ classList={[Styles.qf_back_btn]}
276
+ onClick={{ action: this.resetToDefaults, showLoading: false }}
277
+ style={{ width: 40, height: 40 }}
278
+ />
279
+ }
280
+ <NSButton
281
+ title="+ Add Filter"
282
+ onClick={{ action: this.openAdd, showLoading: false }}
283
+ style={{ border: "1px solid #000" }}
284
+ />
285
+ {
286
+ this.hasChanges() &&
287
+ <NSButtonBlue
288
+ title="Save Changes"
289
+ onClick={{ action: () => onConfirm(this.state.configs), showLoading: false }}
290
+ />
291
+ }
292
+ </>
293
+ }
294
+ </NSColumn>
295
+ </NSDialog>
296
+ );
297
+ }
298
298
  }
package/src/css.d.ts CHANGED
@@ -1,14 +1,14 @@
1
- let css_d = "";
2
-
3
- declare module "*.module.css" {
4
- const classes: { readonly [key: string]: string };
5
- export default classes;
6
- }
7
-
8
- declare module "*.module.scss" {
9
- const classes: { readonly [key: string]: string };
10
- export default classes;
11
- }
12
-
13
- declare module "*.css";
1
+ let css_d = "";
2
+
3
+ declare module "*.module.css" {
4
+ const classes: { readonly [key: string]: string };
5
+ export default classes;
6
+ }
7
+
8
+ declare module "*.module.scss" {
9
+ const classes: { readonly [key: string]: string };
10
+ export default classes;
11
+ }
12
+
13
+ declare module "*.css";
14
14
  declare module "*.scss";