ui-soxo-bootstrap-core 2.4.25-dev.28 → 2.4.25-dev.30
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/lib/components/sidemenu/sidemenu.js +39 -7
- package/core/lib/pages/profile/theme-config.js +1 -1
- package/core/modules/steps/action-buttons.js +29 -41
- package/core/modules/steps/action-buttons.scss +16 -0
- package/core/modules/steps/steps.js +5 -1
- package/core/modules/steps/steps.scss +4 -3
- package/package.json +1 -1
|
@@ -158,7 +158,6 @@ export default function SideMenu({ loading, modules = [], callback, appSettings,
|
|
|
158
158
|
|
|
159
159
|
// callback();
|
|
160
160
|
// };
|
|
161
|
-
|
|
162
161
|
|
|
163
162
|
const onMenuClick = (menu, index) => {
|
|
164
163
|
const key = menu.path || `menu-${menu.id || index}`;
|
|
@@ -176,19 +175,52 @@ export default function SideMenu({ loading, modules = [], callback, appSettings,
|
|
|
176
175
|
setMenu(menu);
|
|
177
176
|
if (callback) callback();
|
|
178
177
|
};
|
|
179
|
-
|
|
180
178
|
|
|
179
|
+
/**
|
|
180
|
+
* Controls submenu open/close behavior.
|
|
181
|
+
*
|
|
182
|
+
* - Detects the most recently opened menu key.
|
|
183
|
+
* - When opening a submenu, keeps only its full parent path expanded
|
|
184
|
+
* (accordion behavior).
|
|
185
|
+
* - When closing a submenu, updates state without recalculating paths.
|
|
186
|
+
*
|
|
187
|
+
* @param {string[]} keys - Currently open menu keys from the Menu component.
|
|
188
|
+
*
|
|
189
|
+
* Assumptions:
|
|
190
|
+
* - Menu keys are stable and unique.
|
|
191
|
+
* - Only one menu branch should be open at a time.
|
|
192
|
+
*/
|
|
181
193
|
const onOpenChange = (keys) => {
|
|
182
194
|
const latestOpenKey = keys.find((k) => !openKeys.includes(k));
|
|
183
195
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
setOpenKeys([latestOpenKey]);
|
|
196
|
+
if (!latestOpenKey) {
|
|
197
|
+
setOpenKeys(keys);
|
|
187
198
|
return;
|
|
188
199
|
}
|
|
189
200
|
|
|
190
|
-
|
|
191
|
-
|
|
201
|
+
const findPath = (items) => {
|
|
202
|
+
const sortedItems = Menus.screenMenus(items, 'order');
|
|
203
|
+
for (const item of sortedItems) {
|
|
204
|
+
const key = String(item.id || item.path || item.caption);
|
|
205
|
+
if (key === latestOpenKey) {
|
|
206
|
+
return [key];
|
|
207
|
+
}
|
|
208
|
+
if (item.sub_menus) {
|
|
209
|
+
const childPath = findPath(item.sub_menus);
|
|
210
|
+
if (childPath) {
|
|
211
|
+
return [key, ...childPath];
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return null;
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
const path = findPath(modules);
|
|
219
|
+
if (path) {
|
|
220
|
+
setOpenKeys(path);
|
|
221
|
+
} else {
|
|
222
|
+
setOpenKeys(keys);
|
|
223
|
+
}
|
|
192
224
|
};
|
|
193
225
|
|
|
194
226
|
/**
|
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
* Handles navigation and action controls for a multi-step process,
|
|
4
4
|
* including dynamic content rendering and process completion actions.
|
|
5
5
|
*/
|
|
6
|
-
import React from 'react';
|
|
6
|
+
import React, { useState } from 'react';
|
|
7
7
|
import { Skeleton } from 'antd';
|
|
8
8
|
import { Button } from '../../lib';
|
|
9
|
+
import './action-buttons.scss';
|
|
9
10
|
|
|
10
11
|
export default function ActionButtons({
|
|
11
12
|
loading,
|
|
@@ -21,63 +22,50 @@ export default function ActionButtons({
|
|
|
21
22
|
nextProcessId,
|
|
22
23
|
timelineCollapsed,
|
|
23
24
|
}) {
|
|
25
|
+
const [showNextProcess, setShowNextProcess] = useState(false);
|
|
26
|
+
|
|
24
27
|
return (
|
|
25
28
|
<>
|
|
26
29
|
<div style={{ minHeight: 300 }}>{loading ? <Skeleton active /> : renderDynamicComponent()}</div>
|
|
27
30
|
<>
|
|
28
|
-
<div
|
|
31
|
+
<div className="action-buttons-container">
|
|
29
32
|
{/* Back button */}
|
|
30
|
-
<Button disabled={activeStep === 0} onClick={handlePrevious}
|
|
33
|
+
<Button disabled={activeStep === 0} onClick={handlePrevious}>
|
|
31
34
|
Back
|
|
32
35
|
</Button>
|
|
33
36
|
|
|
34
37
|
{/* Skip button */}
|
|
35
38
|
{steps.length > 0 && steps[activeStep]?.allow_skip === 'Y' && (
|
|
36
|
-
<Button
|
|
37
|
-
type="default"
|
|
38
|
-
onClick={handleSkip}
|
|
39
|
-
style={{
|
|
40
|
-
borderRadius: 4,
|
|
41
|
-
}}
|
|
42
|
-
disabled={activeStep === steps.length - 1}
|
|
43
|
-
>
|
|
39
|
+
<Button type="default" onClick={handleSkip} disabled={activeStep === steps.length - 1}>
|
|
44
40
|
Skip
|
|
45
41
|
</Button>
|
|
46
42
|
)}
|
|
47
43
|
|
|
48
44
|
{/* Next / Finish / Start Next */}
|
|
49
45
|
{steps[activeStep]?.order_seqtype === 'E' ? (
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
onClick={
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
46
|
+
<>
|
|
47
|
+
{!showNextProcess && (
|
|
48
|
+
<Button
|
|
49
|
+
type="primary"
|
|
50
|
+
onClick={async () => {
|
|
51
|
+
const success = await handleFinish();
|
|
52
|
+
if (success && nextProcessId?.next_process_id) {
|
|
53
|
+
setShowNextProcess(true);
|
|
54
|
+
}
|
|
55
|
+
}}
|
|
56
|
+
>
|
|
57
|
+
Finish
|
|
58
|
+
</Button>
|
|
59
|
+
)}
|
|
60
|
+
|
|
61
|
+
{showNextProcess && nextProcessId?.next_process_id && (
|
|
62
|
+
<Button type="primary" onClick={handleStartNextProcess}>
|
|
63
|
+
Start {nextProcessId.next_process_name}
|
|
64
|
+
</Button>
|
|
65
|
+
)}
|
|
66
|
+
</>
|
|
71
67
|
) : (
|
|
72
|
-
<Button
|
|
73
|
-
type="primary"
|
|
74
|
-
// shape="round"
|
|
75
|
-
style={{
|
|
76
|
-
borderRadius: 4,
|
|
77
|
-
}}
|
|
78
|
-
disabled={activeStep === steps.length - 1 || !isStepCompleted}
|
|
79
|
-
onClick={handleNext}
|
|
80
|
-
>
|
|
68
|
+
<Button type="primary" disabled={activeStep === steps.length - 1 || !isStepCompleted} onClick={handleNext}>
|
|
81
69
|
Next →
|
|
82
70
|
</Button>
|
|
83
71
|
)}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
.action-buttons-container {
|
|
2
|
+
margin-top: 38px;
|
|
3
|
+
display: flex;
|
|
4
|
+
justify-content: flex-start;
|
|
5
|
+
gap: 10px;
|
|
6
|
+
position: sticky;
|
|
7
|
+
bottom: 0;
|
|
8
|
+
z-index: 1000;
|
|
9
|
+
background: #fff;
|
|
10
|
+
padding: 10px 0;
|
|
11
|
+
border-top: 1px solid #f0f0f0;
|
|
12
|
+
|
|
13
|
+
.ant-btn {
|
|
14
|
+
border-radius: 4px;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -204,7 +204,9 @@ export default function ProcessStepsPage({ processId, match, CustomComponents =
|
|
|
204
204
|
*/
|
|
205
205
|
const handleFinish = async () => {
|
|
206
206
|
const final = recordStepTime();
|
|
207
|
-
|
|
207
|
+
const success = await handleProcessSubmit(final);
|
|
208
|
+
if (success && !nextProcessId) props.history?.goBack();
|
|
209
|
+
return success;
|
|
208
210
|
};
|
|
209
211
|
/**
|
|
210
212
|
* Start Next Process
|
|
@@ -268,6 +270,7 @@ export default function ProcessStepsPage({ processId, match, CustomComponents =
|
|
|
268
270
|
* and external window view.
|
|
269
271
|
*/
|
|
270
272
|
const renderContent = () => (
|
|
273
|
+
<div>
|
|
271
274
|
<Card>
|
|
272
275
|
<Row gutter={20}>
|
|
273
276
|
<Col xs={24} sm={24} lg={timelineCollapsed ? 2 : 6}>
|
|
@@ -303,6 +306,7 @@ export default function ProcessStepsPage({ processId, match, CustomComponents =
|
|
|
303
306
|
</Col>
|
|
304
307
|
</Row>
|
|
305
308
|
</Card>
|
|
309
|
+
</div>
|
|
306
310
|
);
|
|
307
311
|
/**
|
|
308
312
|
* Renders content in both the main window and an external window
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
.timeline-card .ant-card-body {
|
|
2
|
-
padding: 20px;
|
|
2
|
+
// padding: 20px;
|
|
3
|
+
border: none;
|
|
3
4
|
min-height: 400px;
|
|
4
|
-
position: fixed; /* For positioning the arrow */
|
|
5
|
+
// position: fixed; /* For positioning the arrow */
|
|
5
6
|
}
|
|
6
7
|
|
|
7
8
|
.timeline-sidebar {
|
|
@@ -46,7 +47,7 @@
|
|
|
46
47
|
|
|
47
48
|
.vertical-line {
|
|
48
49
|
width: 2px;
|
|
49
|
-
height:
|
|
50
|
+
height: 20px;
|
|
50
51
|
background: #d9d9d9;
|
|
51
52
|
}
|
|
52
53
|
|