ui-soxo-bootstrap-core 2.6.1-dev.11 → 2.6.1-dev.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/core/components/landing-api/landing-api.js +66 -2
- package/core/components/landing-api/landing-api.scss +22 -0
- package/core/lib/models/forms/components/form-creator/form-creator.scss +1 -1
- package/core/models/core-scripts/core-scripts.js +134 -135
- package/core/models/menus/components/menu-lists/menu-lists.js +49 -46
- package/core/modules/reporting/components/reporting-dashboard/adavance-search/advance-search.js +49 -168
- package/core/modules/reporting/components/reporting-dashboard/adavance-search/advance-search.scss +76 -0
- package/core/modules/reporting/components/reporting-dashboard/reporting-dashboard.js +31 -148
- package/core/modules/steps/action-buttons.js +6 -0
- package/core/modules/steps/action-buttons.scss +9 -3
- package/core/modules/steps/steps.js +46 -5
- package/core/modules/steps/steps.scss +82 -13
- package/package.json +1 -1
package/core/modules/reporting/components/reporting-dashboard/adavance-search/advance-search.js
CHANGED
|
@@ -1,137 +1,20 @@
|
|
|
1
1
|
|
|
2
|
-
|
|
3
|
-
// import React, { useState, useEffect, useRef } from "react";
|
|
4
|
-
// import { Select, Checkbox, Input, Spin } from "antd";
|
|
5
|
-
// import { CoreScripts } from "../../../../../models";
|
|
6
|
-
|
|
7
|
-
// const { Search } = Input;
|
|
8
|
-
|
|
9
|
-
// export default function AdvancedSearchSelect({ field, value = [], onChange }) {
|
|
10
|
-
// const [searchResults, setSearchResults] = useState([]); // only API results
|
|
11
|
-
// const [selectedItems, setSelectedItems] = useState(value); // persisted selections
|
|
12
|
-
// const [loading, setLoading] = useState(false);
|
|
13
|
-
// const debounceRef = useRef(null);
|
|
14
|
-
|
|
15
|
-
// // Sync selectedItems if parent value changes externally
|
|
16
|
-
// useEffect(() => {
|
|
17
|
-
// setSelectedItems(value);
|
|
18
|
-
// }, [value]);
|
|
19
|
-
|
|
20
|
-
// const loadOptions = async (searchText = "") => {
|
|
21
|
-
// try {
|
|
22
|
-
// setLoading(true);
|
|
23
|
-
|
|
24
|
-
// let query = field?.search_query || "";
|
|
25
|
-
// query = query.replace("@search_text;", searchText || "");
|
|
26
|
-
|
|
27
|
-
// const res = await CoreScripts.getQuery({ script: query });
|
|
28
|
-
// const data = Array.isArray(res) ? res[0] : [];
|
|
29
|
-
// const apiValues = data?.map((r) => r[field.field]) || [];
|
|
30
|
-
|
|
31
|
-
// setSearchResults(apiValues);
|
|
32
|
-
// } catch (error) {
|
|
33
|
-
// console.error("Search API error", error);
|
|
34
|
-
// } finally {
|
|
35
|
-
// setLoading(false);
|
|
36
|
-
// }
|
|
37
|
-
// };
|
|
38
|
-
|
|
39
|
-
// useEffect(() => {
|
|
40
|
-
// loadOptions("");
|
|
41
|
-
// }, [field]);
|
|
42
|
-
|
|
43
|
-
// const handleSearch = (text) => {
|
|
44
|
-
// if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
45
|
-
// debounceRef.current = setTimeout(() => loadOptions(text), 400);
|
|
46
|
-
// };
|
|
47
|
-
|
|
48
|
-
// const toggleValue = (checked, item) => {
|
|
49
|
-
// let newValues;
|
|
50
|
-
|
|
51
|
-
// if (checked) {
|
|
52
|
-
// newValues = [...selectedItems, item];
|
|
53
|
-
// } else {
|
|
54
|
-
// newValues = selectedItems.filter((v) => v !== item);
|
|
55
|
-
// }
|
|
56
|
-
|
|
57
|
-
// setSelectedItems(newValues); // update local persisted state immediately
|
|
58
|
-
// onChange(newValues);
|
|
59
|
-
// };
|
|
60
|
-
|
|
61
|
-
// // Merge: selected items always on top, then search results (excluding already selected)
|
|
62
|
-
// const displayOptions = [
|
|
63
|
-
// ...selectedItems,
|
|
64
|
-
// ...searchResults.filter((item) => !selectedItems.includes(item)),
|
|
65
|
-
// ];
|
|
66
|
-
|
|
67
|
-
// return (
|
|
68
|
-
// <Select
|
|
69
|
-
// mode="multiple"
|
|
70
|
-
// value={value}
|
|
71
|
-
// style={{ width: 250 }}
|
|
72
|
-
// placeholder={field.caption}
|
|
73
|
-
// allowClear
|
|
74
|
-
// maxTagCount={0}
|
|
75
|
-
// onChange={onChange}
|
|
76
|
-
// maxTagPlaceholder={() => (
|
|
77
|
-
// <span style={{ display: "flex", alignItems: "center", gap: 8 }}>
|
|
78
|
-
// {field.caption}
|
|
79
|
-
// <span
|
|
80
|
-
// style={{
|
|
81
|
-
// background: "#e6f0ff",
|
|
82
|
-
// color: "#1677ff",
|
|
83
|
-
// borderRadius: "10px",
|
|
84
|
-
// padding: "0 8px",
|
|
85
|
-
// fontWeight: 600,
|
|
86
|
-
// fontSize: 12,
|
|
87
|
-
// }}
|
|
88
|
-
// >
|
|
89
|
-
// {value?.length || 0}
|
|
90
|
-
// </span>
|
|
91
|
-
// </span>
|
|
92
|
-
// )}
|
|
93
|
-
// dropdownRender={() => (
|
|
94
|
-
// <div style={{ padding: 10 }}>
|
|
95
|
-
// <Search
|
|
96
|
-
// placeholder={`Search ${field.caption}`}
|
|
97
|
-
// onChange={(e) => handleSearch(e.target.value)}
|
|
98
|
-
// />
|
|
99
|
-
|
|
100
|
-
// <div style={{ maxHeight: 200, overflowY: "auto", marginTop: 10 }}>
|
|
101
|
-
// {loading ? (
|
|
102
|
-
// <Spin />
|
|
103
|
-
// ) : (
|
|
104
|
-
// displayOptions.map((item) => (
|
|
105
|
-
// <div key={item} style={{ marginBottom: 6 }}>
|
|
106
|
-
// <Checkbox
|
|
107
|
-
// checked={selectedItems.includes(item)}
|
|
108
|
-
// onChange={(e) => toggleValue(e.target.checked, item)}
|
|
109
|
-
// >
|
|
110
|
-
// {item}
|
|
111
|
-
// </Checkbox>
|
|
112
|
-
// </div>
|
|
113
|
-
// ))
|
|
114
|
-
// )}
|
|
115
|
-
// </div>
|
|
116
|
-
// </div>
|
|
117
|
-
// )}
|
|
118
|
-
// />
|
|
119
|
-
// );
|
|
120
|
-
// }
|
|
121
|
-
|
|
122
2
|
import React, { useState, useEffect, useRef } from "react";
|
|
123
3
|
import { Select, Checkbox, Input, Spin } from "antd";
|
|
124
4
|
import { CoreScripts } from "../../../../../models";
|
|
5
|
+
import "./advance-search.scss";
|
|
125
6
|
|
|
126
7
|
const { Search } = Input;
|
|
127
8
|
|
|
128
|
-
export default function AdvancedSearchSelect({ field, value = [], onChange }) {
|
|
129
|
-
|
|
130
|
-
const
|
|
9
|
+
export default function AdvancedSearchSelect({ reportId, field, value = [], onChange ,onReset}) {
|
|
10
|
+
|
|
11
|
+
const isSearchQuery = !!field.search_query;
|
|
12
|
+
|
|
13
|
+
const [searchResults, setSearchResults] = useState([]);
|
|
14
|
+
const [selectedItems, setSelectedItems] = useState(value);
|
|
131
15
|
const [loading, setLoading] = useState(false);
|
|
132
16
|
const debounceRef = useRef(null);
|
|
133
17
|
|
|
134
|
-
// Sync selectedItems if parent value changes externally
|
|
135
18
|
useEffect(() => {
|
|
136
19
|
setSelectedItems(value);
|
|
137
20
|
}, [value]);
|
|
@@ -140,11 +23,14 @@ export default function AdvancedSearchSelect({ field, value = [], onChange }) {
|
|
|
140
23
|
try {
|
|
141
24
|
setLoading(true);
|
|
142
25
|
|
|
143
|
-
|
|
144
|
-
|
|
26
|
+
const formBody = {
|
|
27
|
+
script_id: reportId,
|
|
28
|
+
search_field: field.field,
|
|
29
|
+
search_condition: searchText,
|
|
30
|
+
};
|
|
145
31
|
|
|
146
|
-
const res = await CoreScripts.
|
|
147
|
-
const data = Array.isArray(res) ? res
|
|
32
|
+
const res = await CoreScripts.getQuerySeacch(formBody);
|
|
33
|
+
const data = Array.isArray(res.data) ? res.data : [];
|
|
148
34
|
const apiValues = data?.map((r) => r[field.field]) || [];
|
|
149
35
|
|
|
150
36
|
setSearchResults(apiValues);
|
|
@@ -156,7 +42,7 @@ export default function AdvancedSearchSelect({ field, value = [], onChange }) {
|
|
|
156
42
|
};
|
|
157
43
|
|
|
158
44
|
useEffect(() => {
|
|
159
|
-
loadOptions("");
|
|
45
|
+
if (isSearchQuery) loadOptions("");
|
|
160
46
|
}, [field]);
|
|
161
47
|
|
|
162
48
|
const handleSearch = (text) => {
|
|
@@ -167,11 +53,8 @@ export default function AdvancedSearchSelect({ field, value = [], onChange }) {
|
|
|
167
53
|
const toggleValue = (checked, item) => {
|
|
168
54
|
let newValues;
|
|
169
55
|
|
|
170
|
-
if (checked)
|
|
171
|
-
|
|
172
|
-
} else {
|
|
173
|
-
newValues = selectedItems.filter((v) => v !== item);
|
|
174
|
-
}
|
|
56
|
+
if (checked) newValues = [...selectedItems, item];
|
|
57
|
+
else newValues = selectedItems.filter((v) => v !== item);
|
|
175
58
|
|
|
176
59
|
setSelectedItems(newValues);
|
|
177
60
|
onChange(newValues);
|
|
@@ -180,53 +63,67 @@ export default function AdvancedSearchSelect({ field, value = [], onChange }) {
|
|
|
180
63
|
const handleReset = () => {
|
|
181
64
|
setSelectedItems([]);
|
|
182
65
|
onChange([]);
|
|
66
|
+
// if (onReset) {
|
|
67
|
+
onReset(); // 🔥 trigger dashboard refresh
|
|
68
|
+
// }
|
|
183
69
|
};
|
|
184
70
|
|
|
185
|
-
// Merge: selected items always on top, then search results
|
|
186
71
|
const displayOptions = [
|
|
187
72
|
...selectedItems,
|
|
188
73
|
...searchResults.filter((item) => !selectedItems.includes(item)),
|
|
189
74
|
];
|
|
190
75
|
|
|
76
|
+
const isActive = value && value.length > 0;
|
|
77
|
+
|
|
78
|
+
// -------- INPUT MODE --------
|
|
79
|
+
if (!isSearchQuery) {
|
|
80
|
+
return (
|
|
81
|
+
<Input
|
|
82
|
+
className={`advanced-search-input ${isActive ? "advanced-search-active" : ""}`}
|
|
83
|
+
placeholder={`Search ${field.caption}`}
|
|
84
|
+
// The parent provides an array for `value`.
|
|
85
|
+
// We take the first element for the input's display value.
|
|
86
|
+
value={value[0] || ""}
|
|
87
|
+
onChange={(e) => {
|
|
88
|
+
const text = e.target.value;
|
|
89
|
+
// Always pass an array back to the parent to be consistent with the Select mode.
|
|
90
|
+
onChange(text ? [text] : []);
|
|
91
|
+
}}
|
|
92
|
+
/>
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// -------- SELECT MODE --------
|
|
191
97
|
return (
|
|
192
98
|
<Select
|
|
99
|
+
className={`advanced-search-select ${isActive ? "advanced-search-active" : ""}`}
|
|
193
100
|
mode="multiple"
|
|
194
101
|
value={value}
|
|
195
|
-
style={{ width: 250 }}
|
|
196
102
|
placeholder={field.caption}
|
|
197
103
|
allowClear
|
|
198
104
|
maxTagCount={0}
|
|
199
105
|
onChange={onChange}
|
|
200
106
|
maxTagPlaceholder={() => (
|
|
201
|
-
<span
|
|
107
|
+
<span className="tag-placeholder">
|
|
202
108
|
{field.caption}
|
|
203
|
-
<span
|
|
204
|
-
style={{
|
|
205
|
-
background: "#e6f0ff",
|
|
206
|
-
color: "#1677ff",
|
|
207
|
-
borderRadius: "10px",
|
|
208
|
-
padding: "0 8px",
|
|
209
|
-
fontWeight: 600,
|
|
210
|
-
fontSize: 12,
|
|
211
|
-
}}
|
|
212
|
-
>
|
|
109
|
+
<span className="tag-placeholder-count">
|
|
213
110
|
{value?.length || 0}
|
|
214
111
|
</span>
|
|
215
112
|
</span>
|
|
216
113
|
)}
|
|
217
114
|
dropdownRender={() => (
|
|
218
|
-
<div
|
|
115
|
+
<div className="dropdown-content">
|
|
219
116
|
<Search
|
|
220
117
|
placeholder={`Search ${field.caption}`}
|
|
221
118
|
onChange={(e) => handleSearch(e.target.value)}
|
|
222
119
|
/>
|
|
223
120
|
|
|
224
|
-
<div
|
|
121
|
+
<div className="dropdown-options-list">
|
|
225
122
|
{loading ? (
|
|
226
123
|
<Spin />
|
|
227
124
|
) : (
|
|
228
125
|
displayOptions.map((item) => (
|
|
229
|
-
<div key={item}
|
|
126
|
+
<div key={item} className="dropdown-option-item">
|
|
230
127
|
<Checkbox
|
|
231
128
|
checked={selectedItems.includes(item)}
|
|
232
129
|
onChange={(e) => toggleValue(e.target.checked, item)}
|
|
@@ -238,24 +135,8 @@ export default function AdvancedSearchSelect({ field, value = [], onChange }) {
|
|
|
238
135
|
)}
|
|
239
136
|
</div>
|
|
240
137
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
style={{
|
|
244
|
-
display: "flex",
|
|
245
|
-
justifyContent: "flex-end",
|
|
246
|
-
marginTop: 10,
|
|
247
|
-
borderTop: "1px solid #f0f0f0",
|
|
248
|
-
paddingTop: 8,
|
|
249
|
-
}}
|
|
250
|
-
>
|
|
251
|
-
<span
|
|
252
|
-
style={{
|
|
253
|
-
color: "#1677ff",
|
|
254
|
-
cursor: "pointer",
|
|
255
|
-
fontWeight: 500,
|
|
256
|
-
}}
|
|
257
|
-
onClick={handleReset}
|
|
258
|
-
>
|
|
138
|
+
<div className="dropdown-footer">
|
|
139
|
+
<span className="dropdown-reset-button" onClick={handleReset}>
|
|
259
140
|
Reset
|
|
260
141
|
</span>
|
|
261
142
|
</div>
|
package/core/modules/reporting/components/reporting-dashboard/adavance-search/advance-search.scss
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// .advanced-search-select,
|
|
2
|
+
/* Base select width */
|
|
3
|
+
.advanced-search-select {
|
|
4
|
+
width: 160px;
|
|
5
|
+
}
|
|
6
|
+
.advanced-search-input {
|
|
7
|
+
width: 160px;
|
|
8
|
+
}
|
|
9
|
+
/* Active state (when value selected) */
|
|
10
|
+
.advanced-search-select.advanced-search-active .ant-select-selector {
|
|
11
|
+
border-color: #1677ff !important;
|
|
12
|
+
box-shadow: 0 0 0 2px rgba(22, 119, 255, 0.2) !important;
|
|
13
|
+
border-radius: 6px !important;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/* Input active state */
|
|
17
|
+
.advanced-search-input.advanced-search-active {
|
|
18
|
+
border-color: #1677ff !important;
|
|
19
|
+
box-shadow: 0 0 0 2px rgba(22, 119, 255, 0.2);
|
|
20
|
+
border-radius: 6px;
|
|
21
|
+
}
|
|
22
|
+
// .advanced-search-input {
|
|
23
|
+
// width: 250px;
|
|
24
|
+
|
|
25
|
+
// &.advanced-search-active {
|
|
26
|
+
// // Antd Select and Input don't share the same border-radius property,
|
|
27
|
+
// // so we apply a wrapper style that works for both.
|
|
28
|
+
// // For more specific control, you might need to target internal antd classes.
|
|
29
|
+
// border: 1px solid #91caff !important;
|
|
30
|
+
// box-shadow: 0 0 0 1px #91caff;
|
|
31
|
+
// border-radius: 6px;
|
|
32
|
+
// }
|
|
33
|
+
// }
|
|
34
|
+
|
|
35
|
+
.tag-placeholder {
|
|
36
|
+
display: flex;
|
|
37
|
+
align-items: center;
|
|
38
|
+
gap: 8px;
|
|
39
|
+
|
|
40
|
+
.tag-placeholder-count {
|
|
41
|
+
background: #e6f0ff;
|
|
42
|
+
color: #1677ff;
|
|
43
|
+
border-radius: 10px;
|
|
44
|
+
padding: 0 8px;
|
|
45
|
+
font-weight: 600;
|
|
46
|
+
font-size: 12px;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.dropdown-content {
|
|
51
|
+
padding: 10px;
|
|
52
|
+
|
|
53
|
+
.dropdown-options-list {
|
|
54
|
+
max-height: 200px;
|
|
55
|
+
overflow-y: auto;
|
|
56
|
+
margin-top: 10px;
|
|
57
|
+
|
|
58
|
+
.dropdown-option-item {
|
|
59
|
+
margin-bottom: 6px;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.dropdown-footer {
|
|
64
|
+
display: flex;
|
|
65
|
+
justify-content: flex-end;
|
|
66
|
+
margin-top: 10px;
|
|
67
|
+
border-top: 1px solid #f0f0f0;
|
|
68
|
+
padding-top: 8px;
|
|
69
|
+
|
|
70
|
+
.dropdown-reset-button {
|
|
71
|
+
color: #1677ff;
|
|
72
|
+
cursor: pointer;
|
|
73
|
+
font-weight: 500;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -344,144 +344,6 @@ export default function ReportingDashboard({
|
|
|
344
344
|
}
|
|
345
345
|
};
|
|
346
346
|
|
|
347
|
-
/**
|
|
348
|
-
*
|
|
349
|
-
* @param {*} searchValues
|
|
350
|
-
* @param {*} searchParameters
|
|
351
|
-
* @returns
|
|
352
|
-
*/
|
|
353
|
-
const buildSearchCondition = (searchValues, searchParameters) => {
|
|
354
|
-
let searchCondition = '';
|
|
355
|
-
|
|
356
|
-
Object.keys(searchValues).forEach((key) => {
|
|
357
|
-
const arr = searchValues[key];
|
|
358
|
-
if (!Array.isArray(arr) || arr.length === 0) return;
|
|
359
|
-
|
|
360
|
-
const param = searchParameters.find((p) => p.field === key);
|
|
361
|
-
if (!param) return;
|
|
362
|
-
|
|
363
|
-
const operator = (param.search_operator || '').trim().toUpperCase();
|
|
364
|
-
const column = param.db_column || key;
|
|
365
|
-
|
|
366
|
-
if (operator === 'LIKE') {
|
|
367
|
-
const likeConditions = arr.map((v) => `${column} LIKE '${v}'`).join(' OR ');
|
|
368
|
-
searchCondition += ` AND (${likeConditions})`;
|
|
369
|
-
} else if (operator === 'IN') {
|
|
370
|
-
const valueList = arr.map((v) => `'${v}'`).join(',');
|
|
371
|
-
searchCondition += ` AND ${column} IN (${valueList})`;
|
|
372
|
-
} else if (operator === '=') {
|
|
373
|
-
const eqConditions = arr.map((v) => `${column} = '${v}'`).join(' OR ');
|
|
374
|
-
searchCondition += ` AND (${eqConditions})`;
|
|
375
|
-
} else if (operator === '!=') {
|
|
376
|
-
const neqConditions = arr.map((v) => `${column} != '${v}'`).join(' AND ');
|
|
377
|
-
searchCondition += ` AND (${neqConditions})`;
|
|
378
|
-
} else {
|
|
379
|
-
// fallback for other operators like > < >= <=
|
|
380
|
-
const conditions = arr.map((v) => `${column} ${operator} '${v}'`).join(' OR ');
|
|
381
|
-
searchCondition += ` AND (${conditions})`;
|
|
382
|
-
}
|
|
383
|
-
});
|
|
384
|
-
|
|
385
|
-
return searchCondition;
|
|
386
|
-
};
|
|
387
|
-
// const handleSubmit = (values) => {
|
|
388
|
-
// const hasSearchValues = Object.values(searchValues).some((v) => Array.isArray(v) && v.length > 0);
|
|
389
|
-
|
|
390
|
-
// // Check if regular form values have changed since the last submission.
|
|
391
|
-
// const regularValuesChanged = (() => {
|
|
392
|
-
// const newKeys = Object.keys(values);
|
|
393
|
-
// const oldKeys = Object.keys(formContents);
|
|
394
|
-
|
|
395
|
-
// if (newKeys.length !== oldKeys.length) return true;
|
|
396
|
-
|
|
397
|
-
// for (const key of newKeys) {
|
|
398
|
-
// const newValue = values[key];
|
|
399
|
-
// const oldValue = formContents[key];
|
|
400
|
-
|
|
401
|
-
// if (moment.isMoment(newValue) && moment.isMoment(oldValue)) {
|
|
402
|
-
// if (!newValue.isSame(oldValue)) {
|
|
403
|
-
// return true;
|
|
404
|
-
// }
|
|
405
|
-
// } else if (newValue !== oldValue) {
|
|
406
|
-
// // This is a shallow comparison, but should work for primitives and new array/object references.
|
|
407
|
-
// return true;
|
|
408
|
-
// }
|
|
409
|
-
// }
|
|
410
|
-
// return false;
|
|
411
|
-
// })();
|
|
412
|
-
|
|
413
|
-
// if (hasSearchValues && regularValuesChanged) {
|
|
414
|
-
// Modal.confirm({
|
|
415
|
-
// title: 'Combine Filters',
|
|
416
|
-
// content: 'You have applied both standard and advanced filters. Do you want to combine them?',
|
|
417
|
-
// okText: 'Yes, Apply Both',
|
|
418
|
-
// cancelText: 'No, Use Advanced Only',
|
|
419
|
-
// onOk: () => {
|
|
420
|
-
// // User chose to combine filters.
|
|
421
|
-
// const searchCondition = buildSearchCondition(searchValues, searchParameters);
|
|
422
|
-
// const finalValues = {
|
|
423
|
-
// ...values,
|
|
424
|
-
// search_condition: searchCondition,
|
|
425
|
-
// };
|
|
426
|
-
// onFinish(finalValues, 1);
|
|
427
|
-
// },
|
|
428
|
-
// onCancel: () => {
|
|
429
|
-
// // User chose to use only advanced search.
|
|
430
|
-
// const searchCondition = buildSearchCondition(searchValues, searchParameters);
|
|
431
|
-
// const resetValues = {};
|
|
432
|
-
// Object.keys(values).forEach((key) => {
|
|
433
|
-
// resetValues[key] = null;
|
|
434
|
-
// });
|
|
435
|
-
// const finalValues = {
|
|
436
|
-
// ...resetValues,
|
|
437
|
-
// search_condition: searchCondition,
|
|
438
|
-
// };
|
|
439
|
-
// onFinish(finalValues, 1);
|
|
440
|
-
// },
|
|
441
|
-
// });
|
|
442
|
-
// return; // Stop further execution, wait for modal response.
|
|
443
|
-
// }
|
|
444
|
-
|
|
445
|
-
// // --- Default behavior if the condition for the modal is not met ---
|
|
446
|
-
|
|
447
|
-
// let finalValues = values;
|
|
448
|
-
// if (hasSearchValues) {
|
|
449
|
-
// // If only advanced search has values (or regular filters haven't changed), reset regular filters.
|
|
450
|
-
// const searchCondition = buildSearchCondition(searchValues, searchParameters);
|
|
451
|
-
// const resetValues = {};
|
|
452
|
-
// Object.keys(values).forEach((key) => {
|
|
453
|
-
// resetValues[key] = null;
|
|
454
|
-
// });
|
|
455
|
-
// finalValues = {
|
|
456
|
-
// ...resetValues,
|
|
457
|
-
// search_condition: searchCondition,
|
|
458
|
-
// };
|
|
459
|
-
// }
|
|
460
|
-
|
|
461
|
-
// const { pageSize } = pagination;
|
|
462
|
-
// const resetPage = 1;
|
|
463
|
-
|
|
464
|
-
// scriptId.current = null;
|
|
465
|
-
|
|
466
|
-
// // Update URL only when NOT using advanced search
|
|
467
|
-
// if (!hasSearchValues) {
|
|
468
|
-
// const currentUrlParams = Location.search();
|
|
469
|
-
// const { script_id, selected_card, ...cleanParams } = currentUrlParams;
|
|
470
|
-
|
|
471
|
-
// const newParams = new URLSearchParams({
|
|
472
|
-
// ...cleanParams,
|
|
473
|
-
// current: resetPage,
|
|
474
|
-
// pageSize,
|
|
475
|
-
// });
|
|
476
|
-
|
|
477
|
-
// const newUrl = `${window.location.pathname}?${newParams.toString()}`;
|
|
478
|
-
// window.history.replaceState({}, '', newUrl);
|
|
479
|
-
// }
|
|
480
|
-
|
|
481
|
-
// // Call report API
|
|
482
|
-
// onFinish(finalValues, resetPage);
|
|
483
|
-
// };
|
|
484
|
-
|
|
485
347
|
const handleSubmit = (values) => {
|
|
486
348
|
const hasSearchValues = Object.values(searchValues).some((v) => Array.isArray(v) && v.length > 0);
|
|
487
349
|
|
|
@@ -511,11 +373,9 @@ export default function ReportingDashboard({
|
|
|
511
373
|
|
|
512
374
|
onOk() {
|
|
513
375
|
// YES → send form values + search condition
|
|
514
|
-
const searchCondition = buildSearchCondition(searchValues, searchParameters);
|
|
515
|
-
|
|
516
376
|
const finalValues = {
|
|
517
377
|
...values,
|
|
518
|
-
|
|
378
|
+
search_values: searchValues,
|
|
519
379
|
};
|
|
520
380
|
|
|
521
381
|
runSubmit(finalValues);
|
|
@@ -523,8 +383,6 @@ export default function ReportingDashboard({
|
|
|
523
383
|
|
|
524
384
|
onCancel() {
|
|
525
385
|
// NO → reset form values
|
|
526
|
-
const searchCondition = buildSearchCondition(searchValues, searchParameters);
|
|
527
|
-
|
|
528
386
|
const resetValues = {};
|
|
529
387
|
Object.keys(values).forEach((key) => {
|
|
530
388
|
resetValues[key] = null;
|
|
@@ -532,7 +390,7 @@ export default function ReportingDashboard({
|
|
|
532
390
|
|
|
533
391
|
const finalValues = {
|
|
534
392
|
...resetValues,
|
|
535
|
-
|
|
393
|
+
search_values: searchValues,
|
|
536
394
|
};
|
|
537
395
|
|
|
538
396
|
runSubmit(finalValues);
|
|
@@ -540,8 +398,6 @@ export default function ReportingDashboard({
|
|
|
540
398
|
});
|
|
541
399
|
} else {
|
|
542
400
|
// no form change
|
|
543
|
-
const searchCondition = buildSearchCondition(searchValues, searchParameters);
|
|
544
|
-
|
|
545
401
|
const resetValues = {};
|
|
546
402
|
Object.keys(values).forEach((key) => {
|
|
547
403
|
resetValues[key] = null;
|
|
@@ -549,7 +405,7 @@ export default function ReportingDashboard({
|
|
|
549
405
|
|
|
550
406
|
const finalValues = {
|
|
551
407
|
...resetValues,
|
|
552
|
-
|
|
408
|
+
search_values: searchValues,
|
|
553
409
|
};
|
|
554
410
|
|
|
555
411
|
runSubmit(finalValues);
|
|
@@ -562,7 +418,7 @@ export default function ReportingDashboard({
|
|
|
562
418
|
|
|
563
419
|
scriptId.current = null;
|
|
564
420
|
|
|
565
|
-
const hasSearchValues = finalValues.
|
|
421
|
+
const hasSearchValues = finalValues.search_values && Object.values(finalValues.search_values).some((v) => Array.isArray(v) && v.length > 0);
|
|
566
422
|
|
|
567
423
|
if (!hasSearchValues) {
|
|
568
424
|
const currentUrlParams = Location.search();
|
|
@@ -746,6 +602,7 @@ export default function ReportingDashboard({
|
|
|
746
602
|
key={param.field}
|
|
747
603
|
parameter={param}
|
|
748
604
|
field={param}
|
|
605
|
+
reportId={reportId}
|
|
749
606
|
value={searchValues[param.field] || []}
|
|
750
607
|
onChange={(value) => {
|
|
751
608
|
setSearchValues((prev) => ({
|
|
@@ -753,6 +610,32 @@ export default function ReportingDashboard({
|
|
|
753
610
|
[param.field]: value,
|
|
754
611
|
}));
|
|
755
612
|
}}
|
|
613
|
+
onReset={() => {
|
|
614
|
+
setSearchValues((prev) => {
|
|
615
|
+
const updated = {
|
|
616
|
+
...prev,
|
|
617
|
+
[param.field]: [],
|
|
618
|
+
};
|
|
619
|
+
|
|
620
|
+
// const finalValues = {
|
|
621
|
+
// ...formContents,
|
|
622
|
+
// search_values: updated,
|
|
623
|
+
// };
|
|
624
|
+
// console.log(finalValues);
|
|
625
|
+
// runSubmit(finalValues); // 🔥 refresh report correctly
|
|
626
|
+
getPatientDetails();
|
|
627
|
+
|
|
628
|
+
return updated;
|
|
629
|
+
});
|
|
630
|
+
}}
|
|
631
|
+
// onReset={() => {
|
|
632
|
+
// setSearchValues((prev) => ({
|
|
633
|
+
// ...prev,
|
|
634
|
+
// [param.field]: [],
|
|
635
|
+
// }));
|
|
636
|
+
|
|
637
|
+
// handleSubmit(formContents); // 🔥 refresh report
|
|
638
|
+
// }}
|
|
756
639
|
/>
|
|
757
640
|
))
|
|
758
641
|
: null}
|
|
@@ -13,6 +13,8 @@ export default function ActionButtons({
|
|
|
13
13
|
steps,
|
|
14
14
|
activeStep,
|
|
15
15
|
isStepCompleted,
|
|
16
|
+
isFullscreen,
|
|
17
|
+
onToggleFullscreen,
|
|
16
18
|
renderDynamicComponent,
|
|
17
19
|
handlePrevious,
|
|
18
20
|
handleNext,
|
|
@@ -37,6 +39,10 @@ export default function ActionButtons({
|
|
|
37
39
|
Back
|
|
38
40
|
</Button>
|
|
39
41
|
|
|
42
|
+
<Button type="default" onClick={onToggleFullscreen}>
|
|
43
|
+
{isFullscreen ? 'Exit Full Screen' : 'Switch to Full Screen'}
|
|
44
|
+
</Button>
|
|
45
|
+
|
|
40
46
|
{/* Skip button */}
|
|
41
47
|
{steps.length > 0 && steps[activeStep]?.allow_skip === 'Y' && (
|
|
42
48
|
<Button type="default" onClick={handleSkip} disabled={activeStep === steps.length - 1}>
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
overflow-y: auto;
|
|
12
12
|
overflow-x: hidden;
|
|
13
13
|
overscroll-behavior: contain;
|
|
14
|
+
|
|
14
15
|
padding-bottom: 8px;
|
|
15
16
|
}
|
|
16
17
|
|
|
@@ -27,7 +28,6 @@
|
|
|
27
28
|
border-top: 1px solid #f0f0f0;
|
|
28
29
|
box-shadow: 0 -2px 10px rgba(15, 23, 42, 0.04);
|
|
29
30
|
|
|
30
|
-
|
|
31
31
|
width: 61%;
|
|
32
32
|
padding: 10px;
|
|
33
33
|
position: fixed;
|
|
@@ -37,9 +37,15 @@
|
|
|
37
37
|
display: flex;
|
|
38
38
|
border-radius: 4px;
|
|
39
39
|
box-shadow: -1px -4px 10px 2px #f7f7f76e;
|
|
40
|
-
|
|
40
|
+
flex-wrap: wrap;
|
|
41
41
|
|
|
42
42
|
.ant-btn {
|
|
43
43
|
border-radius: 4px;
|
|
44
44
|
}
|
|
45
|
-
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.process-steps-page.is-fullscreen .action-buttons-container {
|
|
48
|
+
width: calc(100% - 24px);
|
|
49
|
+
left: 12px;
|
|
50
|
+
right: 12px;
|
|
51
|
+
}
|