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,107 +1,107 @@
1
- import { FilterItem, FilterItemOperator, SortItem } from "namirasoft-core";
2
- import { NSBoxEntity, NSBoxTime, NSBoxTimeRange } from "namirasoft-site-react";
3
- import { NSAFilterBoxBase, NSAFilterBoxBaseProps } from "./NSAFilterBoxBase";
4
- import { NSAFilterBoxBoolean } from "./NSAFilterBoxBoolean";
5
-
6
- export interface NSAFilterBoxTimeProps extends NSAFilterBoxBaseProps
7
- {
8
- getValues: (search: string) => Promise<{ value: string; title: string }[]>;
9
- }
10
-
11
- type ValueItem = { value: string; title: string };
12
-
13
- const ENTITY_OPERATORS = ["equals"];
14
-
15
- export class NSAFilterBoxTime extends NSAFilterBoxBase<NSAFilterBoxTimeProps>
16
- {
17
- private betweenActive = this.getInitialBetween() !== undefined;
18
-
19
- private list = async (
20
- filters: FilterItem[] | null,
21
- _page: number | null,
22
- _size: number | null,
23
- _sorts: SortItem[]
24
- ): Promise<{ count: number; rows: ValueItem[] }> =>
25
- {
26
- const searchFilter = filters?.find(f => f.values.length > 0);
27
- const search = searchFilter?.values[0] ?? "";
28
- const rows = await this.props.getValues(search);
29
- return { count: rows.length, rows };
30
- };
31
-
32
- override render(): JSX.Element | null
33
- {
34
- const { config, onChanged } = this.props;
35
- const op = config.operatorName
36
- ? FilterItemOperator.getByName(config.operatorName)
37
- : null;
38
-
39
- if (op && op.count === 0)
40
- return <NSAFilterBoxBoolean config={config} initial={this.props.initial} onChanged={onChanged} />;
41
-
42
- const between = this.getInitialBetween();
43
-
44
- if (config.operatorName === "between")
45
- return (
46
- <NSBoxTimeRange
47
- title={this.getLabel()}
48
- placeholder={this.getLabel()}
49
- required={false}
50
- hideHeader={true}
51
- preset={true}
52
- defaultValue={between ? { from: between.from, to: between.to } : undefined}
53
- onChanged={e =>
54
- {
55
- const val = e.getValue();
56
- if (val)
57
- {
58
- this.betweenActive = true;
59
- onChanged(this.buildBetweenFilterItems(val.from, val.to));
60
- }
61
- else if (this.betweenActive)
62
- {
63
- this.betweenActive = false;
64
- onChanged(null);
65
- }
66
- }}
67
- />
68
- );
69
-
70
- if (config.operatorName && ENTITY_OPERATORS.includes(config.operatorName))
71
- return (
72
- <NSBoxEntity<ValueItem>
73
- title={this.getLabel()}
74
- placeholder={this.getLabel()}
75
- required={false}
76
- hideHeader={true}
77
- multiple={false}
78
- defaultValue={this.getInitialValue()}
79
- list={this.list}
80
- table_name={config.column.table.name}
81
- getValue={item => item.value}
82
- getTitle={item => item.title}
83
- getSort={() => null}
84
- onChanged={e =>
85
- {
86
- const val = e.getValueOne();
87
- onChanged(val ? this.buildFilterItem(val) : null);
88
- }}
89
- />
90
- );
91
-
92
- return (
93
- <NSBoxTime
94
- title={this.getLabel()}
95
- placeholder={this.getLabel()}
96
- required={false}
97
- hideHeader={true}
98
- defaultValue={this.getInitialValue()}
99
- onChanged={e =>
100
- {
101
- const val = e.getValue();
102
- onChanged(val ? this.buildFilterItem(val) : null);
103
- }}
104
- />
105
- );
106
- }
1
+ import { FilterItem, FilterItemOperator, SortItem } from "namirasoft-core";
2
+ import { NSBoxEntity, NSBoxTime, NSBoxTimeRange } from "namirasoft-site-react";
3
+ import { NSAFilterBoxBase, NSAFilterBoxBaseProps } from "./NSAFilterBoxBase";
4
+ import { NSAFilterBoxBoolean } from "./NSAFilterBoxBoolean";
5
+
6
+ export interface NSAFilterBoxTimeProps extends NSAFilterBoxBaseProps
7
+ {
8
+ getValues: (search: string) => Promise<{ value: string; title: string }[]>;
9
+ }
10
+
11
+ type ValueItem = { value: string; title: string };
12
+
13
+ const ENTITY_OPERATORS = ["equals"];
14
+
15
+ export class NSAFilterBoxTime extends NSAFilterBoxBase<NSAFilterBoxTimeProps>
16
+ {
17
+ private betweenActive = this.getInitialBetween() !== undefined;
18
+
19
+ private list = async (
20
+ filters: FilterItem[] | null,
21
+ _page: number | null,
22
+ _size: number | null,
23
+ _sorts: SortItem[]
24
+ ): Promise<{ count: number; rows: ValueItem[] }> =>
25
+ {
26
+ const searchFilter = filters?.find(f => f.values.length > 0);
27
+ const search = searchFilter?.values[0] ?? "";
28
+ const rows = await this.props.getValues(search);
29
+ return { count: rows.length, rows };
30
+ };
31
+
32
+ override render(): JSX.Element | null
33
+ {
34
+ const { config, onChanged } = this.props;
35
+ const op = config.operatorName
36
+ ? FilterItemOperator.getByName(config.operatorName)
37
+ : null;
38
+
39
+ if (op && op.count === 0)
40
+ return <NSAFilterBoxBoolean config={config} initial={this.props.initial} onChanged={onChanged} />;
41
+
42
+ const between = this.getInitialBetween();
43
+
44
+ if (config.operatorName === "between")
45
+ return (
46
+ <NSBoxTimeRange
47
+ title={this.getLabel()}
48
+ placeholder={this.getLabel()}
49
+ required={false}
50
+ hideHeader={true}
51
+ preset={true}
52
+ defaultValue={between ? { from: between.from, to: between.to } : undefined}
53
+ onChanged={e =>
54
+ {
55
+ const val = e.getValue();
56
+ if (val)
57
+ {
58
+ this.betweenActive = true;
59
+ onChanged(this.buildBetweenFilterItems(val.from, val.to));
60
+ }
61
+ else if (this.betweenActive)
62
+ {
63
+ this.betweenActive = false;
64
+ onChanged(null);
65
+ }
66
+ }}
67
+ />
68
+ );
69
+
70
+ if (config.operatorName && ENTITY_OPERATORS.includes(config.operatorName))
71
+ return (
72
+ <NSBoxEntity<ValueItem>
73
+ title={this.getLabel()}
74
+ placeholder={this.getLabel()}
75
+ required={false}
76
+ hideHeader={true}
77
+ multiple={false}
78
+ defaultValue={this.getInitialValue()}
79
+ list={this.list}
80
+ table_name={config.column.table.name}
81
+ getValue={item => item.value}
82
+ getTitle={item => item.title}
83
+ getSort={() => null}
84
+ onChanged={e =>
85
+ {
86
+ const val = e.getValueOne();
87
+ onChanged(val ? this.buildFilterItem(val) : null);
88
+ }}
89
+ />
90
+ );
91
+
92
+ return (
93
+ <NSBoxTime
94
+ title={this.getLabel()}
95
+ placeholder={this.getLabel()}
96
+ required={false}
97
+ hideHeader={true}
98
+ defaultValue={this.getInitialValue()}
99
+ onChanged={e =>
100
+ {
101
+ const val = e.getValue();
102
+ onChanged(val ? this.buildFilterItem(val) : null);
103
+ }}
104
+ />
105
+ );
106
+ }
107
107
  }
@@ -1,20 +1,20 @@
1
- .qf_bar {
2
- display: flex;
3
- flex-wrap: wrap;
4
- flex-direction: column;
5
- align-items: center;
6
- gap: 8px;
7
- }
8
-
9
- .qf_card {
10
- display: flex;
11
- flex-direction: column;
12
- min-width: 288px;
13
- }
14
-
15
- @media screen and (min-width: 480px) {
16
- .qf_bar {
17
- flex-direction: row;
18
- align-items: normal;
19
- }
1
+ .qf_bar {
2
+ display: flex;
3
+ flex-wrap: wrap;
4
+ flex-direction: column;
5
+ align-items: center;
6
+ gap: 8px;
7
+ }
8
+
9
+ .qf_card {
10
+ display: flex;
11
+ flex-direction: column;
12
+ min-width: 288px;
13
+ }
14
+
15
+ @media screen and (min-width: 480px) {
16
+ .qf_bar {
17
+ flex-direction: row;
18
+ align-items: normal;
19
+ }
20
20
  }
@@ -1,143 +1,143 @@
1
- import { Component } from "react";
2
- import { FilterItem } from "namirasoft-core";
3
- import { VariableType } from "namirasoft-schema";
4
- import { QuickFilterConfig } from "./NSAQuickFilterDialog";
5
- import { NSAFilterBoxBoolean } from "./NSAFilterBoxBoolean";
6
- import { NSAFilterBoxDate } from "./NSAFilterBoxDate";
7
- import { NSAFilterBoxDateTime } from "./NSAFilterBoxDateTime";
8
- import { NSAFilterBoxEnum } from "./NSAFilterBoxEnum";
9
- import { NSAFilterBoxNumber } from "./NSAFilterBoxNumber";
10
- import { NSAFilterBoxString } from "./NSAFilterBoxString";
11
- import { NSAFilterBoxTime } from "./NSAFilterBoxTime";
12
- import Styles from "./NSAQuickFilterBar.module.css";
13
-
14
- interface NSAQuickFilterBarProps
15
- {
16
- configs: QuickFilterConfig[];
17
- getValues: (tableName: string, columnName: string, search: string) => Promise<{ value: string; title: string }[]>;
18
- initialItems?: FilterItem[];
19
- onChanged?: () => void;
20
- }
21
-
22
- interface NSAQuickFilterBarState
23
- {
24
- filterValues: { [id: string]: FilterItem | FilterItem[] | null };
25
- clearKeys: { [id: string]: number };
26
- }
27
-
28
- const NUMERIC_TYPES = new Set<VariableType>([
29
- VariableType.TinyInt, VariableType.SmallInt, VariableType.MediumInt,
30
- VariableType.Integer, VariableType.BigInt, VariableType.Float,
31
- VariableType.Double, VariableType.Decimal, VariableType.Real, VariableType.Money,
32
- ]);
33
-
34
- const STRING_TYPES = new Set<VariableType>([
35
- VariableType.String, VariableType.Email, VariableType.Phone, VariableType.URL,
36
- VariableType.Color, VariableType.Font, VariableType.FilePath, VariableType.Version,
37
- VariableType.IPV4, VariableType.IPV6, VariableType.IPV4Range, VariableType.IPV6Range,
38
- ]);
39
-
40
- export class NSAQuickFilterBar extends Component<NSAQuickFilterBarProps, NSAQuickFilterBarState>
41
- {
42
- constructor(props: NSAQuickFilterBarProps)
43
- {
44
- super(props);
45
- this.state = { filterValues: this.buildInitialValues(props), clearKeys: {} };
46
- }
47
-
48
- private buildInitialValues(props: NSAQuickFilterBarProps): { [id: string]: FilterItem | FilterItem[] | null }
49
- {
50
- const values: { [id: string]: FilterItem | FilterItem[] | null } = {};
51
- const items = props.initialItems ?? [];
52
- const consumed = new Set<number>();
53
- for (const config of props.configs)
54
- {
55
- const matched: FilterItem[] = [];
56
- items.forEach((item, index) =>
57
- {
58
- if (consumed.has(index))
59
- return;
60
- if (item.table.name === config.column.table.name && item.column.name === config.column.name)
61
- {
62
- matched.push(item);
63
- consumed.add(index);
64
- }
65
- });
66
- if (matched.length === 1)
67
- values[config.id] = matched[0];
68
- else if (matched.length > 1)
69
- values[config.id] = matched;
70
- }
71
- return values;
72
- }
73
-
74
- getFilterItems(): FilterItem[]
75
- {
76
- return Object.values(this.state.filterValues).flatMap(v =>
77
- {
78
- if (!v) return [];
79
- return Array.isArray(v) ? v : [v];
80
- });
81
- }
82
-
83
- private handleFilterChange = (configId: string, items: FilterItem | FilterItem[] | null) =>
84
- {
85
- this.setState(
86
- prev => ({ filterValues: { ...prev.filterValues, [configId]: items } }),
87
- this.props.onChanged
88
- );
89
- };
90
-
91
- private renderFilterBox(config: QuickFilterConfig, clearKey: number, colGetValues: (s: string) => Promise<{ value: string; title: string }[]>): JSX.Element | null
92
- {
93
- const { columnType } = config.column;
94
- const onChanged = (items: FilterItem | FilterItem[] | null) => this.handleFilterChange(config.id, items);
95
- const initial = this.state.filterValues[config.id] ?? null;
96
- const commonProps = { key: clearKey, config, initial, onChanged };
97
-
98
- if (columnType === VariableType.Boolean)
99
- return <NSAFilterBoxBoolean {...commonProps} />;
100
- if (NUMERIC_TYPES.has(columnType))
101
- return <NSAFilterBoxNumber {...commonProps} getValues={colGetValues} />;
102
- if (columnType === VariableType.Date)
103
- return <NSAFilterBoxDate {...commonProps} getValues={colGetValues} />;
104
- if (columnType === VariableType.DateTime)
105
- return <NSAFilterBoxDateTime {...commonProps} getValues={colGetValues} />;
106
- if (columnType === VariableType.Time)
107
- return <NSAFilterBoxTime {...commonProps} getValues={colGetValues} />;
108
- if (STRING_TYPES.has(columnType))
109
- return <NSAFilterBoxString {...commonProps} getValues={colGetValues} />;
110
- if (columnType === VariableType.Enum || columnType === VariableType.Entity)
111
- return <NSAFilterBoxEnum {...commonProps} getValues={colGetValues} />;
112
-
113
- return null;
114
- }
115
-
116
- private renderCard(config: QuickFilterConfig): JSX.Element | null
117
- {
118
- const { getValues } = this.props;
119
- const clearKey = this.state.clearKeys[config.id] ?? 0;
120
- const colGetValues = (s: string) => getValues(config.column.table.name, config.column.name, s);
121
- const box = this.renderFilterBox(config, clearKey, colGetValues);
122
- if (!box) return null;
123
-
124
- return (
125
- <div key={config.id} className={Styles.qf_card}>
126
- {box}
127
- </div>
128
- );
129
- }
130
-
131
- override render()
132
- {
133
- const { configs } = this.props;
134
- if (configs.length === 0)
135
- return null;
136
-
137
- return (
138
- <div className={Styles.qf_bar}>
139
- {configs.map(config => this.renderCard(config))}
140
- </div>
141
- );
142
- }
1
+ import { Component } from "react";
2
+ import { FilterItem } from "namirasoft-core";
3
+ import { VariableType } from "namirasoft-schema";
4
+ import { QuickFilterConfig } from "./NSAQuickFilterDialog";
5
+ import { NSAFilterBoxBoolean } from "./NSAFilterBoxBoolean";
6
+ import { NSAFilterBoxDate } from "./NSAFilterBoxDate";
7
+ import { NSAFilterBoxDateTime } from "./NSAFilterBoxDateTime";
8
+ import { NSAFilterBoxEnum } from "./NSAFilterBoxEnum";
9
+ import { NSAFilterBoxNumber } from "./NSAFilterBoxNumber";
10
+ import { NSAFilterBoxString } from "./NSAFilterBoxString";
11
+ import { NSAFilterBoxTime } from "./NSAFilterBoxTime";
12
+ import Styles from "./NSAQuickFilterBar.module.css";
13
+
14
+ interface NSAQuickFilterBarProps
15
+ {
16
+ configs: QuickFilterConfig[];
17
+ getValues: (tableName: string, columnName: string, search: string) => Promise<{ value: string; title: string }[]>;
18
+ initialItems?: FilterItem[];
19
+ onChanged?: () => void;
20
+ }
21
+
22
+ interface NSAQuickFilterBarState
23
+ {
24
+ filterValues: { [id: string]: FilterItem | FilterItem[] | null };
25
+ clearKeys: { [id: string]: number };
26
+ }
27
+
28
+ const NUMERIC_TYPES = new Set<VariableType>([
29
+ VariableType.TinyInt, VariableType.SmallInt, VariableType.MediumInt,
30
+ VariableType.Integer, VariableType.BigInt, VariableType.Float,
31
+ VariableType.Double, VariableType.Decimal, VariableType.Real, VariableType.Money,
32
+ ]);
33
+
34
+ const STRING_TYPES = new Set<VariableType>([
35
+ VariableType.String, VariableType.Email, VariableType.Phone, VariableType.URL,
36
+ VariableType.Color, VariableType.Font, VariableType.FilePath, VariableType.Version,
37
+ VariableType.IPV4, VariableType.IPV6, VariableType.IPV4Range, VariableType.IPV6Range,
38
+ ]);
39
+
40
+ export class NSAQuickFilterBar extends Component<NSAQuickFilterBarProps, NSAQuickFilterBarState>
41
+ {
42
+ constructor(props: NSAQuickFilterBarProps)
43
+ {
44
+ super(props);
45
+ this.state = { filterValues: this.buildInitialValues(props), clearKeys: {} };
46
+ }
47
+
48
+ private buildInitialValues(props: NSAQuickFilterBarProps): { [id: string]: FilterItem | FilterItem[] | null }
49
+ {
50
+ const values: { [id: string]: FilterItem | FilterItem[] | null } = {};
51
+ const items = props.initialItems ?? [];
52
+ const consumed = new Set<number>();
53
+ for (const config of props.configs)
54
+ {
55
+ const matched: FilterItem[] = [];
56
+ items.forEach((item, index) =>
57
+ {
58
+ if (consumed.has(index))
59
+ return;
60
+ if (item.table.name === config.column.table.name && item.column.name === config.column.name)
61
+ {
62
+ matched.push(item);
63
+ consumed.add(index);
64
+ }
65
+ });
66
+ if (matched.length === 1)
67
+ values[config.id] = matched[0];
68
+ else if (matched.length > 1)
69
+ values[config.id] = matched;
70
+ }
71
+ return values;
72
+ }
73
+
74
+ getFilterItems(): FilterItem[]
75
+ {
76
+ return Object.values(this.state.filterValues).flatMap(v =>
77
+ {
78
+ if (!v) return [];
79
+ return Array.isArray(v) ? v : [v];
80
+ });
81
+ }
82
+
83
+ private handleFilterChange = (configId: string, items: FilterItem | FilterItem[] | null) =>
84
+ {
85
+ this.setState(
86
+ prev => ({ filterValues: { ...prev.filterValues, [configId]: items } }),
87
+ this.props.onChanged
88
+ );
89
+ };
90
+
91
+ private renderFilterBox(config: QuickFilterConfig, clearKey: number, colGetValues: (s: string) => Promise<{ value: string; title: string }[]>): JSX.Element | null
92
+ {
93
+ const { columnType } = config.column;
94
+ const onChanged = (items: FilterItem | FilterItem[] | null) => this.handleFilterChange(config.id, items);
95
+ const initial = this.state.filterValues[config.id] ?? null;
96
+ const commonProps = { key: clearKey, config, initial, onChanged };
97
+
98
+ if (columnType === VariableType.Boolean)
99
+ return <NSAFilterBoxBoolean {...commonProps} />;
100
+ if (NUMERIC_TYPES.has(columnType))
101
+ return <NSAFilterBoxNumber {...commonProps} getValues={colGetValues} />;
102
+ if (columnType === VariableType.Date)
103
+ return <NSAFilterBoxDate {...commonProps} getValues={colGetValues} />;
104
+ if (columnType === VariableType.DateTime)
105
+ return <NSAFilterBoxDateTime {...commonProps} getValues={colGetValues} />;
106
+ if (columnType === VariableType.Time)
107
+ return <NSAFilterBoxTime {...commonProps} getValues={colGetValues} />;
108
+ if (STRING_TYPES.has(columnType))
109
+ return <NSAFilterBoxString {...commonProps} getValues={colGetValues} />;
110
+ if (columnType === VariableType.Enum || columnType === VariableType.Entity)
111
+ return <NSAFilterBoxEnum {...commonProps} getValues={colGetValues} />;
112
+
113
+ return null;
114
+ }
115
+
116
+ private renderCard(config: QuickFilterConfig): JSX.Element | null
117
+ {
118
+ const { getValues } = this.props;
119
+ const clearKey = this.state.clearKeys[config.id] ?? 0;
120
+ const colGetValues = (s: string) => getValues(config.column.table.name, config.column.name, s);
121
+ const box = this.renderFilterBox(config, clearKey, colGetValues);
122
+ if (!box) return null;
123
+
124
+ return (
125
+ <div key={config.id} className={Styles.qf_card}>
126
+ {box}
127
+ </div>
128
+ );
129
+ }
130
+
131
+ override render()
132
+ {
133
+ const { configs } = this.props;
134
+ if (configs.length === 0)
135
+ return null;
136
+
137
+ return (
138
+ <div className={Styles.qf_bar}>
139
+ {configs.map(config => this.renderCard(config))}
140
+ </div>
141
+ );
142
+ }
143
143
  }