@ramesesinc/platform-core 0.1.0
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/dist/components/action/AlertMessage.d.ts +8 -0
- package/dist/components/action/AlertMessage.js +19 -0
- package/dist/components/action/AlertMessage.tsx +38 -0
- package/dist/components/action/Button.d.ts +21 -0
- package/dist/components/action/Button.js +139 -0
- package/dist/components/action/Button.tsx +230 -0
- package/dist/components/action/CancelEdit.d.ts +9 -0
- package/dist/components/action/CancelEdit.js +21 -0
- package/dist/components/action/CancelEdit.tsx +40 -0
- package/dist/components/action/DeleteData.d.ts +13 -0
- package/dist/components/action/DeleteData.js +43 -0
- package/dist/components/action/DeleteData.tsx +73 -0
- package/dist/components/action/Edit.d.ts +9 -0
- package/dist/components/action/Edit.js +21 -0
- package/dist/components/action/Edit.tsx +40 -0
- package/dist/components/action/LookupPage.d.ts +16 -0
- package/dist/components/action/LookupPage.js +62 -0
- package/dist/components/action/LookupPage.tsx +113 -0
- package/dist/components/action/ProcessRunner.d.ts +62 -0
- package/dist/components/action/ProcessRunner.js +156 -0
- package/dist/components/action/ProcessRunner.tsx +337 -0
- package/dist/components/action/Refresh.d.ts +7 -0
- package/dist/components/action/Refresh.js +17 -0
- package/dist/components/action/Refresh.tsx +35 -0
- package/dist/components/action/SaveData.d.ts +10 -0
- package/dist/components/action/SaveData.js +54 -0
- package/dist/components/action/SaveData.tsx +74 -0
- package/dist/components/action/SelectData.d.ts +8 -0
- package/dist/components/action/SelectData.js +29 -0
- package/dist/components/action/SelectData.tsx +47 -0
- package/dist/components/action/Undo.d.ts +9 -0
- package/dist/components/action/Undo.js +31 -0
- package/dist/components/action/Undo.tsx +50 -0
- package/dist/components/action/UpdateContext.d.ts +9 -0
- package/dist/components/action/UpdateContext.js +21 -0
- package/dist/components/action/UpdateContext.tsx +40 -0
- package/dist/components/action/UpdateData.d.ts +9 -0
- package/dist/components/action/UpdateData.js +33 -0
- package/dist/components/action/UpdateData.tsx +49 -0
- package/dist/components/action/ViewBackPage.d.ts +9 -0
- package/dist/components/action/ViewBackPage.js +19 -0
- package/dist/components/action/ViewBackPage.tsx +46 -0
- package/dist/components/action/ViewPage.d.ts +14 -0
- package/dist/components/action/ViewPage.js +88 -0
- package/dist/components/action/ViewPage.tsx +141 -0
- package/dist/components/common/UIComponent.d.ts +11 -0
- package/dist/components/common/UIComponent.js +52 -0
- package/dist/components/common/UIComponent.tsx +84 -0
- package/dist/components/common/UIInput.d.ts +12 -0
- package/dist/components/common/UIInput.js +37 -0
- package/dist/components/common/UIInput.tsx +49 -0
- package/dist/components/common/UIMenu.d.ts +23 -0
- package/dist/components/common/UIMenu.js +61 -0
- package/dist/components/common/UIMenu.tsx +91 -0
- package/dist/components/index.d.ts +37 -0
- package/dist/components/index.js +44 -0
- package/dist/components/index.ts +51 -0
- package/dist/components/input/CodeEditor.d.ts +12 -0
- package/dist/components/input/CodeEditor.js +132 -0
- package/dist/components/input/CodeEditor.tsx +188 -0
- package/dist/components/input/DateField.d.ts +9 -0
- package/dist/components/input/DateField.js +140 -0
- package/dist/components/input/DateField.tsx +274 -0
- package/dist/components/input/DayPicker.d.ts +2 -0
- package/dist/components/input/DayPicker.js +5 -0
- package/dist/components/input/DayPicker.tsx +5 -0
- package/dist/components/input/HtmlCode.d.ts +8 -0
- package/dist/components/input/HtmlCode.js +157 -0
- package/dist/components/input/HtmlCode.tsx +203 -0
- package/dist/components/input/JsonCode.d.ts +9 -0
- package/dist/components/input/JsonCode.js +159 -0
- package/dist/components/input/JsonCode.tsx +205 -0
- package/dist/components/input/MonthPicker.d.ts +2 -0
- package/dist/components/input/MonthPicker.js +5 -0
- package/dist/components/input/MonthPicker.tsx +5 -0
- package/dist/components/input/ScriptCode.d.ts +8 -0
- package/dist/components/input/ScriptCode.js +153 -0
- package/dist/components/input/ScriptCode.tsx +195 -0
- package/dist/components/input/Select.d.ts +14 -0
- package/dist/components/input/Select.js +40 -0
- package/dist/components/input/Select.tsx +78 -0
- package/dist/components/input/SqlCode.d.ts +8 -0
- package/dist/components/input/SqlCode.js +121 -0
- package/dist/components/input/SqlCode.tsx +162 -0
- package/dist/components/input/StringDecision.d.ts +2 -0
- package/dist/components/input/StringDecision.js +34 -0
- package/dist/components/input/StringDecision.tsx +64 -0
- package/dist/components/input/Text.d.ts +7 -0
- package/dist/components/input/Text.js +39 -0
- package/dist/components/input/Text.tsx +57 -0
- package/dist/components/input/YearPicker.d.ts +8 -0
- package/dist/components/input/YearPicker.js +44 -0
- package/dist/components/input/YearPicker.tsx +81 -0
- package/dist/components/list/IconMenu.d.ts +14 -0
- package/dist/components/list/IconMenu.js +72 -0
- package/dist/components/list/IconMenu.tsx +115 -0
- package/dist/components/list/TabMenu.d.ts +10 -0
- package/dist/components/list/TabMenu.js +72 -0
- package/dist/components/list/TabMenu.tsx +127 -0
- package/dist/components/list/TreeMenu.d.ts +14 -0
- package/dist/components/list/TreeMenu.js +207 -0
- package/dist/components/list/TreeMenu.tsx +279 -0
- package/dist/components/list/TxnTaskList.d.ts +2 -0
- package/dist/components/list/TxnTaskList.js +77 -0
- package/dist/components/list/TxnTaskList.tsx +198 -0
- package/dist/components/output/Label.d.ts +8 -0
- package/dist/components/output/Label.js +33 -0
- package/dist/components/output/Label.tsx +51 -0
- package/dist/components/table/DataList.d.ts +88 -0
- package/dist/components/table/DataList.js +361 -0
- package/dist/components/table/DataList.tsx +782 -0
- package/dist/components/table/DataTable.d.ts +46 -0
- package/dist/components/table/DataTable.js +253 -0
- package/dist/components/table/DataTable.tsx +572 -0
- package/dist/components/table/ListHandler.d.ts +42 -0
- package/dist/components/table/ListHandler.js +197 -0
- package/dist/components/table/ListHandler.ts +276 -0
- package/dist/components/table/TableContext.d.ts +33 -0
- package/dist/components/table/TableContext.js +57 -0
- package/dist/components/table/TableContext.tsx +122 -0
- package/dist/components/view/ComponentView.d.ts +8 -0
- package/dist/components/view/ComponentView.js +78 -0
- package/dist/components/view/ComponentView.tsx +102 -0
- package/dist/components/view/FilterView.d.ts +2 -0
- package/dist/components/view/FilterView.js +14 -0
- package/dist/components/view/FilterView.tsx +21 -0
- package/dist/components/view/HtmlForm.d.ts +7 -0
- package/dist/components/view/HtmlForm.js +145 -0
- package/dist/components/view/HtmlForm.tsx +186 -0
- package/dist/components/view/HtmlView.d.ts +9 -0
- package/dist/components/view/HtmlView.js +85 -0
- package/dist/components/view/HtmlView.tsx +114 -0
- package/dist/components/view/IFrameView.d.ts +2 -0
- package/dist/components/view/IFrameView.js +34 -0
- package/dist/components/view/IFrameView.tsx +48 -0
- package/dist/components/view/Modal.d.ts +14 -0
- package/dist/components/view/Modal.js +28 -0
- package/dist/components/view/Modal.tsx +72 -0
- package/dist/components/view/PageView.d.ts +9 -0
- package/dist/components/view/PageView.js +90 -0
- package/dist/components/view/PageView.tsx +131 -0
- package/dist/components/view/PopupView.d.ts +9 -0
- package/dist/components/view/PopupView.js +91 -0
- package/dist/components/view/PopupView.tsx +160 -0
- package/dist/components/view/RootView.d.ts +8 -0
- package/dist/components/view/RootView.js +75 -0
- package/dist/components/view/RootView.tsx +109 -0
- package/dist/components/view/WizardView.d.ts +6 -0
- package/dist/components/view/WizardView.js +34 -0
- package/dist/components/view/WizardView.tsx +48 -0
- package/dist/core/AppContext.d.ts +25 -0
- package/dist/core/AppContext.js +159 -0
- package/dist/core/AuthContext.d.ts +13 -0
- package/dist/core/AuthContext.js +80 -0
- package/dist/core/ComponentCache.d.ts +15 -0
- package/dist/core/ComponentCache.js +25 -0
- package/dist/core/DataContext.d.ts +20 -0
- package/dist/core/DataContext.js +41 -0
- package/dist/core/DynamicComponent.d.ts +12 -0
- package/dist/core/DynamicComponent.js +30 -0
- package/dist/core/DynamicIcon.d.ts +6 -0
- package/dist/core/DynamicIcon.js +48 -0
- package/dist/core/DynamicTemplate.d.ts +4 -0
- package/dist/core/DynamicTemplate.js +17 -0
- package/dist/core/ErrorMessage.d.ts +5 -0
- package/dist/core/ErrorMessage.js +7 -0
- package/dist/core/EventHandler.d.ts +3 -0
- package/dist/core/EventHandler.js +1 -0
- package/dist/core/HtmlCache.d.ts +6 -0
- package/dist/core/HtmlCache.js +17 -0
- package/dist/core/Page.d.ts +6 -0
- package/dist/core/Page.js +141 -0
- package/dist/core/PageCache.d.ts +15 -0
- package/dist/core/PageCache.js +26 -0
- package/dist/core/PageContext.d.ts +49 -0
- package/dist/core/PageContext.js +207 -0
- package/dist/core/PageRegistry.d.ts +7 -0
- package/dist/core/PageRegistry.js +11 -0
- package/dist/core/PageViewContext.d.ts +45 -0
- package/dist/core/PageViewContext.js +277 -0
- package/dist/core/Panel.d.ts +16 -0
- package/dist/core/Panel.js +39 -0
- package/dist/core/RowContext.d.ts +11 -0
- package/dist/core/RowContext.js +16 -0
- package/dist/core/StepHandler.d.ts +9 -0
- package/dist/core/StepHandler.js +39 -0
- package/dist/core/UIDependHandler.d.ts +6 -0
- package/dist/core/UIDependHandler.js +31 -0
- package/dist/core/auth/index.d.ts +18 -0
- package/dist/core/auth/index.js +187 -0
- package/dist/core/auth/session.d.ts +4 -0
- package/dist/core/auth/session.js +45 -0
- package/dist/core/index.d.ts +3 -0
- package/dist/core/index.js +1 -0
- package/dist/core/page-helper.d.ts +27 -0
- package/dist/core/page-helper.js +47 -0
- package/dist/hooks/useUrlParams.d.ts +11 -0
- package/dist/hooks/useUrlParams.js +164 -0
- package/dist/index.d.ts +65 -0
- package/dist/index.js +69 -0
- package/dist/layouts/BorderLayout.d.ts +14 -0
- package/dist/layouts/BorderLayout.js +8 -0
- package/dist/layouts/CardLayout.d.ts +27 -0
- package/dist/layouts/CardLayout.js +36 -0
- package/dist/layouts/CenterLayout.d.ts +8 -0
- package/dist/layouts/CenterLayout.js +6 -0
- package/dist/layouts/GridLayout.d.ts +9 -0
- package/dist/layouts/GridLayout.js +5 -0
- package/dist/layouts/HPanel.d.ts +11 -0
- package/dist/layouts/HPanel.js +8 -0
- package/dist/layouts/HorizontalLayout.d.ts +11 -0
- package/dist/layouts/HorizontalLayout.js +6 -0
- package/dist/layouts/MainLayout.d.ts +6 -0
- package/dist/layouts/MainLayout.js +5 -0
- package/dist/layouts/PageLayout.d.ts +11 -0
- package/dist/layouts/PageLayout.js +6 -0
- package/dist/layouts/VPanel.d.ts +9 -0
- package/dist/layouts/VPanel.js +7 -0
- package/dist/layouts/XLayout.d.ts +10 -0
- package/dist/layouts/XLayout.js +10 -0
- package/dist/layouts/YLayout.d.ts +10 -0
- package/dist/layouts/YLayout.js +10 -0
- package/dist/lib/PlatformRoute.d.ts +5 -0
- package/dist/lib/PlatformRoute.js +288 -0
- package/dist/lib/WebPlatform.d.ts +13 -0
- package/dist/lib/WebPlatform.js +124 -0
- package/dist/lib/components/ActivityBar.d.ts +13 -0
- package/dist/lib/components/ActivityBar.js +39 -0
- package/dist/lib/components/CopyButton.d.ts +8 -0
- package/dist/lib/components/CopyButton.js +50 -0
- package/dist/lib/components/Header.d.ts +2 -0
- package/dist/lib/components/Header.js +74 -0
- package/dist/lib/components/QuickActionMenu.d.ts +18 -0
- package/dist/lib/components/QuickActionMenu.js +50 -0
- package/dist/lib/components/UserButton.d.ts +11 -0
- package/dist/lib/components/UserButton.js +66 -0
- package/dist/lib/layouts/BorderLayout.tsx +31 -0
- package/dist/lib/layouts/CardLayout.tsx +73 -0
- package/dist/lib/layouts/CenterLayout.tsx +20 -0
- package/dist/lib/layouts/GridLayout.tsx +20 -0
- package/dist/lib/layouts/HPanel.tsx +31 -0
- package/dist/lib/layouts/HorizontalLayout.tsx +29 -0
- package/dist/lib/layouts/MainLayout.tsx +16 -0
- package/dist/lib/layouts/PageLayout.tsx +29 -0
- package/dist/lib/layouts/VPanel.tsx +27 -0
- package/dist/lib/layouts/XLayout.tsx +29 -0
- package/dist/lib/layouts/YLayout.tsx +29 -0
- package/dist/lib/utils/BeanUtils.d.ts +3 -0
- package/dist/lib/utils/BeanUtils.js +75 -0
- package/dist/lib/utils/ComponentLoader.d.ts +13 -0
- package/dist/lib/utils/ComponentLoader.js +26 -0
- package/dist/lib/utils/ExprUtil.d.ts +7 -0
- package/dist/lib/utils/ExprUtil.js +44 -0
- package/dist/lib/utils/PageUtils.d.ts +6 -0
- package/dist/lib/utils/PageUtils.js +121 -0
- package/dist/lib/utils/ResourceLoader.d.ts +11 -0
- package/dist/lib/utils/ResourceLoader.js +37 -0
- package/dist/lib/utils/SectionProvider.d.ts +5 -0
- package/dist/lib/utils/SectionProvider.js +39 -0
- package/dist/lib/utils/initResourceLoader.d.ts +0 -0
- package/dist/lib/utils/initResourceLoader.js +95 -0
- package/dist/styles/index.css +38 -0
- package/dist/templates/BasicTemplate.d.ts +2 -0
- package/dist/templates/BasicTemplate.js +14 -0
- package/dist/templates/CrudFormTemplate.d.ts +2 -0
- package/dist/templates/CrudFormTemplate.js +38 -0
- package/dist/templates/DataListTemplate.d.ts +2 -0
- package/dist/templates/DataListTemplate.js +13 -0
- package/dist/templates/ExplorerTemplate.d.ts +10 -0
- package/dist/templates/ExplorerTemplate.js +17 -0
- package/dist/templates/TxnFormTemplate.d.ts +2 -0
- package/dist/templates/TxnFormTemplate.js +66 -0
- package/dist/templates/WizardTemplate.d.ts +9 -0
- package/dist/templates/WizardTemplate.js +37 -0
- package/dist/templates/index.d.ts +5 -0
- package/dist/templates/index.js +5 -0
- package/dist/types/action.d.ts +8 -0
- package/dist/types/action.js +1 -0
- package/dist/types/component.d.ts +18 -0
- package/dist/types/component.js +1 -0
- package/dist/types/list.d.ts +14 -0
- package/dist/types/list.js +1 -0
- package/dist/types/template.d.ts +6 -0
- package/dist/types/template.js +1 -0
- package/package.json +56 -0
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
3
|
+
import { usePageContext } from "../../core/PageContext";
|
|
4
|
+
import { getValue, substituteExpr } from "../../lib/utils/BeanUtils";
|
|
5
|
+
import { getUrlPageParams } from "../../lib/utils/PageUtils";
|
|
6
|
+
import { AbstractComponent } from "../../types/component";
|
|
7
|
+
|
|
8
|
+
/* ------------------------------------------------------------------ */
|
|
9
|
+
/* Types */
|
|
10
|
+
|
|
11
|
+
// Display state is always derived from the server record — never set directly.
|
|
12
|
+
type RunnerState = "idle" | "running" | "paused" | "done";
|
|
13
|
+
|
|
14
|
+
interface ProcessRunnerProps extends AbstractComponent {
|
|
15
|
+
/**
|
|
16
|
+
* Field expression for current progress value. Default: "{processedcount}"
|
|
17
|
+
*/
|
|
18
|
+
value?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Field expression for max value. Default: "{totalcount}"
|
|
21
|
+
*/
|
|
22
|
+
maxValue?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Field expression resolving to the server-side status field.
|
|
25
|
+
* Expected values (case-insensitive): IDLE | RUNNING | PAUSED | DONE.
|
|
26
|
+
* Default: "{status}"
|
|
27
|
+
*/
|
|
28
|
+
statusValue?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Optional label expression shown below the bar.
|
|
31
|
+
* Only rendered when provided.
|
|
32
|
+
* Example: "{processedcount} of {totalcount} records processed"
|
|
33
|
+
*/
|
|
34
|
+
labelExpr?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Data config: the API endpoint polled on interval to refresh the record.
|
|
37
|
+
* Should return the single record object: { _id, status, processedcount, totalcount, ... }
|
|
38
|
+
* May contain bound param expressions, e.g. "/processtask?_id={_id}"
|
|
39
|
+
*
|
|
40
|
+
* Note: The DataList (parent) fetches the initial list. This component
|
|
41
|
+
* polls independently for live updates on its own record.
|
|
42
|
+
*/
|
|
43
|
+
data?: {
|
|
44
|
+
api: string;
|
|
45
|
+
/** Action APIs called on button click, then immediately re-fetches. */
|
|
46
|
+
actions?: {
|
|
47
|
+
start?: string; // e.g. "/processtask/start?_id={_id}"
|
|
48
|
+
pause?: string; // e.g. "/processtask/pause?_id={_id}"
|
|
49
|
+
resume?: string; // e.g. "/processtask/resume?_id={_id}"
|
|
50
|
+
end?: string; // e.g. "/processtask/end?_id={_id}"
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Polling interval in milliseconds. Default: 5000.
|
|
55
|
+
* Timer only fires while status === "running".
|
|
56
|
+
*/
|
|
57
|
+
interval?: number;
|
|
58
|
+
/** Button label overrides */
|
|
59
|
+
labels?: {
|
|
60
|
+
start?: string;
|
|
61
|
+
pause?: string;
|
|
62
|
+
resume?: string;
|
|
63
|
+
end?: string;
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Row data injected by the Table renderer (same as ViewPage opt.data).
|
|
67
|
+
* Carries the initial record: { _id, status, processedcount, totalcount }
|
|
68
|
+
* This is the seed — polling overlays it with fresh values.
|
|
69
|
+
*/
|
|
70
|
+
opt?: Record<string, any>;
|
|
71
|
+
className?: string;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/* ------------------------------------------------------------------ */
|
|
75
|
+
/* Helpers */
|
|
76
|
+
|
|
77
|
+
const toRunnerState = (raw: unknown): RunnerState => {
|
|
78
|
+
switch (String(raw ?? "").toUpperCase()) {
|
|
79
|
+
case "RUNNING":
|
|
80
|
+
return "running";
|
|
81
|
+
case "PAUSED":
|
|
82
|
+
return "paused";
|
|
83
|
+
case "DONE":
|
|
84
|
+
return "done";
|
|
85
|
+
default:
|
|
86
|
+
return "idle";
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const resolveNumeric = (expr: string, data: Record<string, any>): number => {
|
|
91
|
+
const n = Number(getValue(expr, data));
|
|
92
|
+
return isNaN(n) ? 0 : n;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
/* ------------------------------------------------------------------ */
|
|
96
|
+
/* Component */
|
|
97
|
+
const ProcessRunner = (props: ProcessRunnerProps) => {
|
|
98
|
+
const {
|
|
99
|
+
value: valueProp = "{processedcount}",
|
|
100
|
+
maxValue: maxValueProp = "{totalcount}",
|
|
101
|
+
statusValue = "{status}",
|
|
102
|
+
labelExpr,
|
|
103
|
+
data,
|
|
104
|
+
interval = 5000,
|
|
105
|
+
labels = {},
|
|
106
|
+
opt = {},
|
|
107
|
+
className = "",
|
|
108
|
+
} = props ?? {};
|
|
109
|
+
|
|
110
|
+
const { data: optData = {} } = opt;
|
|
111
|
+
|
|
112
|
+
const { start: startLabel = "Start", pause: pauseLabel = "Pause", resume: resumeLabel = "Resume", end: endLabel = "End" } = labels;
|
|
113
|
+
|
|
114
|
+
const pageContext = usePageContext();
|
|
115
|
+
|
|
116
|
+
/* ----------------------------------------------------------------
|
|
117
|
+
liveData is the SOLE source of truth.
|
|
118
|
+
|
|
119
|
+
Seed it with optData (the row record from DataList) so the
|
|
120
|
+
component displays correctly on first render — before any poll fires.
|
|
121
|
+
Subsequent polls overwrite it entirely with the server's response.
|
|
122
|
+
---------------------------------------------------------------- */
|
|
123
|
+
const [liveData, setLiveData] = useState<Record<string, any>>(optData);
|
|
124
|
+
const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
|
|
125
|
+
const [isBusy, setIsBusy] = useState(false); // prevents double-clicks during action API call
|
|
126
|
+
|
|
127
|
+
// When optData changes from outside (table refresh, parent re-render),
|
|
128
|
+
// merge it in — but don't overwrite fields already updated by polling.
|
|
129
|
+
useEffect(() => {
|
|
130
|
+
setLiveData((prev) => ({ ...optData, ...prev }));
|
|
131
|
+
}, [optData]);
|
|
132
|
+
|
|
133
|
+
/* ----------------------------------------------------------------
|
|
134
|
+
Resolution context — built from all data sources.
|
|
135
|
+
Priority (low → high): url params → page data → liveData
|
|
136
|
+
liveData already contains optData as its seed, so per-row fields
|
|
137
|
+
like {_id} resolve correctly from the very first render.
|
|
138
|
+
---------------------------------------------------------------- */
|
|
139
|
+
const resolveCtx = useMemo(() => {
|
|
140
|
+
const { params } = getUrlPageParams();
|
|
141
|
+
return {
|
|
142
|
+
...params,
|
|
143
|
+
...pageContext.getAllData(),
|
|
144
|
+
...optData, // row record from Table — always live, not just a one-time seed
|
|
145
|
+
...liveData, // polled data wins last — overwrites optData after first fetch
|
|
146
|
+
};
|
|
147
|
+
}, [liveData, optData, pageContext]);
|
|
148
|
+
|
|
149
|
+
/* ----------------------------------------------------------------
|
|
150
|
+
All display values are derived from resolveCtx — no separate state.
|
|
151
|
+
This is what makes multi-browser sync work: any change in the DB
|
|
152
|
+
flows through poll → liveData → resolveCtx → these values → render.
|
|
153
|
+
---------------------------------------------------------------- */
|
|
154
|
+
const state = toRunnerState(getValue(statusValue, resolveCtx));
|
|
155
|
+
const currentValue = resolveNumeric(valueProp, resolveCtx);
|
|
156
|
+
const maxValue = resolveNumeric(maxValueProp, resolveCtx);
|
|
157
|
+
const percent = maxValue > 0 ? Math.min((currentValue / maxValue) * 100, 100) : 0;
|
|
158
|
+
const resolvedLabel = labelExpr ? substituteExpr(labelExpr, resolveCtx) : null;
|
|
159
|
+
|
|
160
|
+
/* ----------------------------------------------------------------
|
|
161
|
+
Core fetch — retrieves the latest record and overwrites liveData.
|
|
162
|
+
Called both by the interval timer AND immediately after button actions.
|
|
163
|
+
---------------------------------------------------------------- */
|
|
164
|
+
const fetchRecord = useCallback(async () => {
|
|
165
|
+
if (!data?.api) return;
|
|
166
|
+
try {
|
|
167
|
+
const url = substituteExpr(data.api, resolveCtx);
|
|
168
|
+
const json = await pageContext?.execService(url, resolveCtx);
|
|
169
|
+
if (!json) return;
|
|
170
|
+
// Full overwrite — server response is authoritative.
|
|
171
|
+
// state, currentValue, maxValue all re-derive from this on next render.
|
|
172
|
+
setLiveData(json);
|
|
173
|
+
} catch {
|
|
174
|
+
// Silently ignore — next tick will retry
|
|
175
|
+
}
|
|
176
|
+
}, [data?.api, resolveCtx, pageContext]);
|
|
177
|
+
|
|
178
|
+
/* ----------------------------------------------------------------
|
|
179
|
+
Polling — only runs while state === "running".
|
|
180
|
+
Starts automatically when state becomes "running" (either from a
|
|
181
|
+
button click confirming via re-fetch, or from another browser
|
|
182
|
+
changing the DB and the interval picking it up).
|
|
183
|
+
---------------------------------------------------------------- */
|
|
184
|
+
const startPolling = useCallback(() => {
|
|
185
|
+
if (intervalRef.current) return;
|
|
186
|
+
intervalRef.current = setInterval(fetchRecord, interval);
|
|
187
|
+
}, [fetchRecord, interval]);
|
|
188
|
+
|
|
189
|
+
const stopPolling = useCallback(() => {
|
|
190
|
+
if (intervalRef.current) {
|
|
191
|
+
clearInterval(intervalRef.current);
|
|
192
|
+
intervalRef.current = null;
|
|
193
|
+
}
|
|
194
|
+
}, []);
|
|
195
|
+
|
|
196
|
+
// Manage timer based on derived state — not on button clicks.
|
|
197
|
+
// This means another browser pausing/completing the job will also
|
|
198
|
+
// stop the timer on this browser after the next tick confirms it.
|
|
199
|
+
useEffect(() => {
|
|
200
|
+
if (state === "running") {
|
|
201
|
+
startPolling();
|
|
202
|
+
} else {
|
|
203
|
+
stopPolling();
|
|
204
|
+
}
|
|
205
|
+
}, [state, startPolling, stopPolling]);
|
|
206
|
+
|
|
207
|
+
// Cleanup on unmount (row removed from table, page navigated away)
|
|
208
|
+
useEffect(() => () => stopPolling(), [stopPolling]);
|
|
209
|
+
|
|
210
|
+
/* ----------------------------------------------------------------
|
|
211
|
+
Action handler — the key pattern for button clicks:
|
|
212
|
+
1. Call action API (POST/GET — whatever your backend expects)
|
|
213
|
+
2. Immediately re-fetch the record — don't wait for next tick
|
|
214
|
+
3. liveData updates → state re-derives → UI updates instantly
|
|
215
|
+
No optimistic setState — server response is always the authority.
|
|
216
|
+
---------------------------------------------------------------- */
|
|
217
|
+
const fireAction = useCallback(
|
|
218
|
+
async (actionUrl: string | undefined) => {
|
|
219
|
+
if (!actionUrl || isBusy) return;
|
|
220
|
+
setIsBusy(true);
|
|
221
|
+
try {
|
|
222
|
+
const url = substituteExpr(actionUrl, resolveCtx);
|
|
223
|
+
await pageContext?.execService(url, resolveCtx);
|
|
224
|
+
} catch {
|
|
225
|
+
// Action failed — re-fetch anyway to show real current state
|
|
226
|
+
} finally {
|
|
227
|
+
// Always re-fetch immediately after action — this is what makes
|
|
228
|
+
// the button feel instant rather than waiting for the next tick.
|
|
229
|
+
await fetchRecord();
|
|
230
|
+
setIsBusy(false);
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
[isBusy, resolveCtx, fetchRecord, pageContext],
|
|
234
|
+
);
|
|
235
|
+
|
|
236
|
+
/* ----------------------------------------------------------------
|
|
237
|
+
Handlers — just delegate to fireAction with the right endpoint.
|
|
238
|
+
If no action API is configured, fetchRecord still runs so the
|
|
239
|
+
UI reflects whatever the server currently has.
|
|
240
|
+
---------------------------------------------------------------- */
|
|
241
|
+
const handleStart = () => fireAction(data?.actions?.start);
|
|
242
|
+
const handlePause = () => fireAction(data?.actions?.pause);
|
|
243
|
+
const handleResume = () => fireAction(data?.actions?.resume);
|
|
244
|
+
const handleEnd = () => fireAction(data?.actions?.end);
|
|
245
|
+
|
|
246
|
+
/* ----------------------------------------------------------------
|
|
247
|
+
Render
|
|
248
|
+
---------------------------------------------------------------- */
|
|
249
|
+
return (
|
|
250
|
+
<div className={`flex flex-col gap-2 ${className}`}>
|
|
251
|
+
{/* IDLE — Start button */}
|
|
252
|
+
{state === "idle" && (
|
|
253
|
+
<button
|
|
254
|
+
onClick={handleStart}
|
|
255
|
+
disabled={isBusy}
|
|
256
|
+
className="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 disabled:opacity-50 transition-colors text-sm font-medium"
|
|
257
|
+
>
|
|
258
|
+
{isBusy ? "…" : startLabel}
|
|
259
|
+
</button>
|
|
260
|
+
)}
|
|
261
|
+
|
|
262
|
+
{/* RUNNING / PAUSED / DONE — progress bar + controls */}
|
|
263
|
+
{state !== "idle" && (
|
|
264
|
+
<div className="flex flex-col gap-1 w-full">
|
|
265
|
+
<div className="flex items-center gap-2">
|
|
266
|
+
{/* Bar */}
|
|
267
|
+
<div
|
|
268
|
+
className="flex-1 h-4 bg-gray-200 rounded-full overflow-hidden"
|
|
269
|
+
role="progressbar"
|
|
270
|
+
aria-valuenow={currentValue}
|
|
271
|
+
aria-valuemin={0}
|
|
272
|
+
aria-valuemax={maxValue || undefined}
|
|
273
|
+
aria-label="Process progress"
|
|
274
|
+
>
|
|
275
|
+
<div
|
|
276
|
+
className={`h-full rounded-full transition-all duration-500 ${
|
|
277
|
+
state === "done" ? "bg-green-500" : state === "paused" ? "bg-yellow-400" : "bg-blue-500"
|
|
278
|
+
}`}
|
|
279
|
+
style={{ width: `${percent}%` }}
|
|
280
|
+
/>
|
|
281
|
+
</div>
|
|
282
|
+
|
|
283
|
+
{/* Percent */}
|
|
284
|
+
<span className="text-xs text-gray-600 w-10 text-right tabular-nums">{Math.round(percent)}%</span>
|
|
285
|
+
|
|
286
|
+
{/* RUNNING → Pause */}
|
|
287
|
+
{state === "running" && (
|
|
288
|
+
<button
|
|
289
|
+
onClick={handlePause}
|
|
290
|
+
disabled={isBusy}
|
|
291
|
+
className="px-3 py-1 bg-yellow-400 text-yellow-900 rounded-md hover:bg-yellow-500 disabled:opacity-50 transition-colors text-xs font-medium"
|
|
292
|
+
>
|
|
293
|
+
{isBusy ? "…" : pauseLabel}
|
|
294
|
+
</button>
|
|
295
|
+
)}
|
|
296
|
+
|
|
297
|
+
{/* PAUSED → Resume | End */}
|
|
298
|
+
{state === "paused" && (
|
|
299
|
+
<>
|
|
300
|
+
<button
|
|
301
|
+
onClick={handleResume}
|
|
302
|
+
disabled={isBusy}
|
|
303
|
+
className="px-3 py-1 bg-blue-600 text-white rounded-md hover:bg-blue-700 disabled:opacity-50 transition-colors text-xs font-medium"
|
|
304
|
+
>
|
|
305
|
+
{isBusy ? "…" : resumeLabel}
|
|
306
|
+
</button>
|
|
307
|
+
<button
|
|
308
|
+
onClick={handleEnd}
|
|
309
|
+
disabled={isBusy}
|
|
310
|
+
className="px-3 py-1 bg-gray-500 text-white rounded-md hover:bg-gray-600 disabled:opacity-50 transition-colors text-xs font-medium"
|
|
311
|
+
>
|
|
312
|
+
{isBusy ? "…" : endLabel}
|
|
313
|
+
</button>
|
|
314
|
+
</>
|
|
315
|
+
)}
|
|
316
|
+
|
|
317
|
+
{/* DONE → End (reset) */}
|
|
318
|
+
{state === "done" && (
|
|
319
|
+
<button
|
|
320
|
+
onClick={handleEnd}
|
|
321
|
+
disabled={isBusy}
|
|
322
|
+
className="px-3 py-1 bg-green-600 text-white rounded-md hover:bg-green-700 disabled:opacity-50 transition-colors text-xs font-medium"
|
|
323
|
+
>
|
|
324
|
+
{isBusy ? "…" : endLabel}
|
|
325
|
+
</button>
|
|
326
|
+
)}
|
|
327
|
+
</div>
|
|
328
|
+
|
|
329
|
+
{/* Label below bar — only when labelExpr is provided */}
|
|
330
|
+
{resolvedLabel && <p className="text-xs text-gray-500 mt-0.5">{resolvedLabel}</p>}
|
|
331
|
+
</div>
|
|
332
|
+
)}
|
|
333
|
+
</div>
|
|
334
|
+
);
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
export default ProcessRunner;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { AbstractComponent } from "../../types/component";
|
|
2
|
+
interface RefreshProps extends AbstractComponent {
|
|
3
|
+
className?: string;
|
|
4
|
+
title?: string;
|
|
5
|
+
}
|
|
6
|
+
declare const Refresh: (props: RefreshProps) => import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
export default Refresh;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { usePageContext } from "../../core/PageContext";
|
|
4
|
+
/* ------------------------------------------------------------------ */
|
|
5
|
+
/* Component */
|
|
6
|
+
const Refresh = (props) => {
|
|
7
|
+
const { className = "", title } = props !== null && props !== void 0 ? props : {};
|
|
8
|
+
const pageContext = usePageContext();
|
|
9
|
+
/* ---------------------- Events ---------------------- */
|
|
10
|
+
const handleClick = () => {
|
|
11
|
+
// console.log("Refresh button", pageContext.refresh());
|
|
12
|
+
pageContext.notifyDepends();
|
|
13
|
+
};
|
|
14
|
+
/* ---------------------- Render ---------------------- */
|
|
15
|
+
return (_jsx("button", { onClick: handleClick, className: `px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors ${className}`, children: title || "Refresh" }));
|
|
16
|
+
};
|
|
17
|
+
export default Refresh;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { usePageContext } from "../../core/PageContext";
|
|
4
|
+
import { AbstractComponent } from "../../types/component";
|
|
5
|
+
|
|
6
|
+
/* ------------------------------------------------------------------ */
|
|
7
|
+
/* Types */
|
|
8
|
+
|
|
9
|
+
interface RefreshProps extends AbstractComponent {
|
|
10
|
+
className?: string;
|
|
11
|
+
title?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/* ------------------------------------------------------------------ */
|
|
15
|
+
/* Component */
|
|
16
|
+
|
|
17
|
+
const Refresh = (props: RefreshProps) => {
|
|
18
|
+
const { className = "", title } = props ?? {};
|
|
19
|
+
const pageContext = usePageContext();
|
|
20
|
+
|
|
21
|
+
/* ---------------------- Events ---------------------- */
|
|
22
|
+
const handleClick = () => {
|
|
23
|
+
// console.log("Refresh button", pageContext.refresh());
|
|
24
|
+
pageContext.notifyDepends();
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/* ---------------------- Render ---------------------- */
|
|
28
|
+
return (
|
|
29
|
+
<button onClick={handleClick} className={`px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors ${className}`}>
|
|
30
|
+
{title || "Refresh"}
|
|
31
|
+
</button>
|
|
32
|
+
);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export default Refresh;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { AbstractComponent } from "../../types/component";
|
|
2
|
+
interface SaveDataProps extends AbstractComponent {
|
|
3
|
+
className?: string;
|
|
4
|
+
title?: string;
|
|
5
|
+
api: string;
|
|
6
|
+
params?: string;
|
|
7
|
+
data?: Record<string, any> | null;
|
|
8
|
+
}
|
|
9
|
+
declare const SaveData: (props: SaveDataProps) => import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export default SaveData;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { usePageContext } from "../../core/PageContext";
|
|
4
|
+
import { usePageViewContext } from "../../core/PageViewContext";
|
|
5
|
+
import { getValue } from "../../lib/utils/BeanUtils";
|
|
6
|
+
import { getUrlPageParams } from "../../lib/utils/PageUtils";
|
|
7
|
+
/* ------------------------------------------------------------------ */
|
|
8
|
+
/* Component */
|
|
9
|
+
const SaveData = (props) => {
|
|
10
|
+
const { className = "", title, api, params, data = {} } = props !== null && props !== void 0 ? props : {};
|
|
11
|
+
// console.log("save data props", { api, params, props });
|
|
12
|
+
const pageContext = usePageContext();
|
|
13
|
+
const pageViewContext = usePageViewContext();
|
|
14
|
+
/* ---------------------- Events ---------------------- */
|
|
15
|
+
const handleClick = async (e) => {
|
|
16
|
+
var _a, _b, _c, _d;
|
|
17
|
+
e.preventDefault();
|
|
18
|
+
try {
|
|
19
|
+
if (!api)
|
|
20
|
+
throw new Error("api not defined");
|
|
21
|
+
if (params) {
|
|
22
|
+
const allData = (_a = pageContext === null || pageContext === void 0 ? void 0 : pageContext.getAllData()) !== null && _a !== void 0 ? _a : {};
|
|
23
|
+
// console.log("save data 1.1", allData);
|
|
24
|
+
const urlParams = (_b = getUrlPageParams()) !== null && _b !== void 0 ? _b : {};
|
|
25
|
+
// console.log("save data 1.2", urlParams);
|
|
26
|
+
const d = getValue(params, Object.assign(Object.assign({}, allData), urlParams === null || urlParams === void 0 ? void 0 : urlParams.params));
|
|
27
|
+
// console.log("save data", { api, d });
|
|
28
|
+
// console.log("data before save is ", params, d);
|
|
29
|
+
// throw new Error("test error");
|
|
30
|
+
await (pageContext === null || pageContext === void 0 ? void 0 : pageContext.execService(api, d));
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
const vdata = (_c = pageContext === null || pageContext === void 0 ? void 0 : pageContext.getData()) !== null && _c !== void 0 ? _c : {};
|
|
34
|
+
const req = {
|
|
35
|
+
data: vdata,
|
|
36
|
+
};
|
|
37
|
+
// console.log("save data", { api, vdata });
|
|
38
|
+
await (pageContext === null || pageContext === void 0 ? void 0 : pageContext.execService(api, req));
|
|
39
|
+
}
|
|
40
|
+
const eventHandler = (_d = pageViewContext.getEventHandler()) !== null && _d !== void 0 ? _d : {};
|
|
41
|
+
const { onSave } = eventHandler;
|
|
42
|
+
if (typeof onSave === "function") {
|
|
43
|
+
onSave({});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
catch (err) {
|
|
47
|
+
console.log("error save data", err);
|
|
48
|
+
alert(err.message);
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
/* ---------------------- Render ---------------------- */
|
|
52
|
+
return (_jsx("button", { onClick: handleClick, className: `px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors ${className}`, children: title || "Save" }));
|
|
53
|
+
};
|
|
54
|
+
export default SaveData;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { usePageContext } from "../../core/PageContext";
|
|
4
|
+
import { usePageViewContext } from "../../core/PageViewContext";
|
|
5
|
+
import { getValue } from "../../lib/utils/BeanUtils";
|
|
6
|
+
import { getUrlPageParams } from "../../lib/utils/PageUtils";
|
|
7
|
+
import { AbstractComponent } from "../../types/component";
|
|
8
|
+
|
|
9
|
+
/* ------------------------------------------------------------------ */
|
|
10
|
+
/* Types */
|
|
11
|
+
|
|
12
|
+
interface SaveDataProps extends AbstractComponent {
|
|
13
|
+
className?: string;
|
|
14
|
+
title?: string;
|
|
15
|
+
api: string;
|
|
16
|
+
params?: string;
|
|
17
|
+
data?: Record<string, any> | null;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/* ------------------------------------------------------------------ */
|
|
21
|
+
/* Component */
|
|
22
|
+
|
|
23
|
+
const SaveData = (props: SaveDataProps) => {
|
|
24
|
+
const { className = "", title, api, params, data = {} } = props ?? {};
|
|
25
|
+
// console.log("save data props", { api, params, props });
|
|
26
|
+
const pageContext = usePageContext();
|
|
27
|
+
const pageViewContext = usePageViewContext();
|
|
28
|
+
|
|
29
|
+
/* ---------------------- Events ---------------------- */
|
|
30
|
+
const handleClick = async (e: React.MouseEvent<HTMLButtonElement>) => {
|
|
31
|
+
e.preventDefault();
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
if (!api) throw new Error("api not defined");
|
|
35
|
+
if (params) {
|
|
36
|
+
const allData = pageContext?.getAllData() ?? {};
|
|
37
|
+
// console.log("save data 1.1", allData);
|
|
38
|
+
const urlParams = getUrlPageParams() ?? {};
|
|
39
|
+
// console.log("save data 1.2", urlParams);
|
|
40
|
+
const d = getValue(params, { ...allData, ...urlParams?.params });
|
|
41
|
+
// console.log("save data", { api, d });
|
|
42
|
+
|
|
43
|
+
// console.log("data before save is ", params, d);
|
|
44
|
+
// throw new Error("test error");
|
|
45
|
+
await pageContext?.execService(api, d);
|
|
46
|
+
} else {
|
|
47
|
+
const vdata = pageContext?.getData() ?? {};
|
|
48
|
+
const req = {
|
|
49
|
+
data: vdata,
|
|
50
|
+
};
|
|
51
|
+
// console.log("save data", { api, vdata });
|
|
52
|
+
await pageContext?.execService(api, req);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const eventHandler = pageViewContext.getEventHandler() ?? {};
|
|
56
|
+
const { onSave } = eventHandler;
|
|
57
|
+
if (typeof onSave === "function") {
|
|
58
|
+
onSave({});
|
|
59
|
+
}
|
|
60
|
+
} catch (err: any) {
|
|
61
|
+
console.log("error save data", err);
|
|
62
|
+
alert(err.message);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
/* ---------------------- Render ---------------------- */
|
|
67
|
+
return (
|
|
68
|
+
<button onClick={handleClick} className={`px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors ${className}`}>
|
|
69
|
+
{title || "Save"}
|
|
70
|
+
</button>
|
|
71
|
+
);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export default SaveData;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { AbstractComponent } from "../../types/component";
|
|
2
|
+
interface SelectDataProps extends AbstractComponent {
|
|
3
|
+
className?: string;
|
|
4
|
+
title?: string;
|
|
5
|
+
name: string;
|
|
6
|
+
}
|
|
7
|
+
declare const SelectData: (props: SelectDataProps) => import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export default SelectData;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { usePageContext } from "../../core/PageContext";
|
|
4
|
+
import { usePageViewContext } from "../../core/PageViewContext";
|
|
5
|
+
/* ------------------------------------------------------------------ */
|
|
6
|
+
/* Component */
|
|
7
|
+
const SelectData = (props) => {
|
|
8
|
+
const { className = "", title, name } = props !== null && props !== void 0 ? props : {};
|
|
9
|
+
const pageContext = usePageContext();
|
|
10
|
+
const pageViewContext = usePageViewContext();
|
|
11
|
+
/* ---------------------- Events ---------------------- */
|
|
12
|
+
const handleClick = async () => {
|
|
13
|
+
var _a;
|
|
14
|
+
try {
|
|
15
|
+
const eventHandler = (_a = pageViewContext.getEventHandler()) !== null && _a !== void 0 ? _a : {};
|
|
16
|
+
const { onSelect } = eventHandler;
|
|
17
|
+
if (typeof onSelect === "function") {
|
|
18
|
+
const d = pageContext.get(name);
|
|
19
|
+
onSelect(d);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
alert(err.message);
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
/* ---------------------- Render ---------------------- */
|
|
27
|
+
return (_jsx("button", { onClick: handleClick, className: `px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors ${className}`, children: title || "Save" }));
|
|
28
|
+
};
|
|
29
|
+
export default SelectData;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { usePageContext } from "../../core/PageContext";
|
|
4
|
+
import { usePageViewContext } from "../../core/PageViewContext";
|
|
5
|
+
import { AbstractComponent } from "../../types/component";
|
|
6
|
+
|
|
7
|
+
/* ------------------------------------------------------------------ */
|
|
8
|
+
/* Types */
|
|
9
|
+
|
|
10
|
+
interface SelectDataProps extends AbstractComponent {
|
|
11
|
+
className?: string;
|
|
12
|
+
title?: string;
|
|
13
|
+
name: string; //target name of data to extract
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/* ------------------------------------------------------------------ */
|
|
17
|
+
/* Component */
|
|
18
|
+
|
|
19
|
+
const SelectData = (props: SelectDataProps) => {
|
|
20
|
+
const { className = "", title, name } = props ?? {};
|
|
21
|
+
const pageContext = usePageContext();
|
|
22
|
+
const pageViewContext = usePageViewContext();
|
|
23
|
+
|
|
24
|
+
/* ---------------------- Events ---------------------- */
|
|
25
|
+
const handleClick = async () => {
|
|
26
|
+
try {
|
|
27
|
+
const eventHandler = pageViewContext.getEventHandler() ?? {};
|
|
28
|
+
const { onSelect } = eventHandler;
|
|
29
|
+
|
|
30
|
+
if (typeof onSelect === "function") {
|
|
31
|
+
const d = pageContext.get(name);
|
|
32
|
+
onSelect(d);
|
|
33
|
+
}
|
|
34
|
+
} catch (err: any) {
|
|
35
|
+
alert(err.message);
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/* ---------------------- Render ---------------------- */
|
|
40
|
+
return (
|
|
41
|
+
<button onClick={handleClick} className={`px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors ${className}`}>
|
|
42
|
+
{title || "Save"}
|
|
43
|
+
</button>
|
|
44
|
+
);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export default SelectData;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { AbstractComponent } from "../../types/component";
|
|
2
|
+
interface UndoProps extends AbstractComponent {
|
|
3
|
+
className?: string;
|
|
4
|
+
title?: string;
|
|
5
|
+
api: string;
|
|
6
|
+
data?: string;
|
|
7
|
+
}
|
|
8
|
+
declare const Undo: (props: UndoProps) => import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export default Undo;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { usePageContext } from "../../core/PageContext";
|
|
4
|
+
/* ------------------------------------------------------------------ */
|
|
5
|
+
/* Component */
|
|
6
|
+
const Undo = (props) => {
|
|
7
|
+
const { className = "", title, api, data } = props !== null && props !== void 0 ? props : {};
|
|
8
|
+
const pageContext = usePageContext();
|
|
9
|
+
/* ---------------------- Events ---------------------- */
|
|
10
|
+
const handleClick = async () => {
|
|
11
|
+
try {
|
|
12
|
+
/*
|
|
13
|
+
if(!api) throw new Error("api not defined");
|
|
14
|
+
const allData = pageContext?.getAllData() ?? {};
|
|
15
|
+
if( data ) {
|
|
16
|
+
const d = getValue( data, allData );
|
|
17
|
+
await pageContext?.execService( api, d );
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
await pageContext?.execService( api, allData );
|
|
21
|
+
}
|
|
22
|
+
*/
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
alert(err.message);
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
/* ---------------------- Render ---------------------- */
|
|
29
|
+
return (_jsx("button", { onClick: handleClick, className: `px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors ${className}`, children: title || "Update Context" }));
|
|
30
|
+
};
|
|
31
|
+
export default Undo;
|