@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,9 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { AbstractComponent } from "../../types/component";
|
|
3
|
+
interface EditProps extends AbstractComponent {
|
|
4
|
+
children?: React.ReactNode;
|
|
5
|
+
className?: string;
|
|
6
|
+
title?: string;
|
|
7
|
+
}
|
|
8
|
+
declare const Edit: (props: EditProps) => import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export default Edit;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { usePageContext } from "../../core/PageContext";
|
|
4
|
+
/* ------------------------------------------------------------------ */
|
|
5
|
+
/* Component */
|
|
6
|
+
const Edit = (props) => {
|
|
7
|
+
const { children, className = "", title } = props !== null && props !== void 0 ? props : {};
|
|
8
|
+
const pageContext = usePageContext();
|
|
9
|
+
/* ---------------------- Events ---------------------- */
|
|
10
|
+
const handleClick = async () => {
|
|
11
|
+
try {
|
|
12
|
+
await (pageContext === null || pageContext === void 0 ? void 0 : pageContext.set("editable", true));
|
|
13
|
+
}
|
|
14
|
+
catch (err) {
|
|
15
|
+
alert(err.message);
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
/* ---------------------- Render ---------------------- */
|
|
19
|
+
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: children || title || "Edit" }));
|
|
20
|
+
};
|
|
21
|
+
export default Edit;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { usePageContext } from "../../core/PageContext";
|
|
5
|
+
import { AbstractComponent } from "../../types/component";
|
|
6
|
+
|
|
7
|
+
/* ------------------------------------------------------------------ */
|
|
8
|
+
/* Types */
|
|
9
|
+
|
|
10
|
+
interface EditProps extends AbstractComponent {
|
|
11
|
+
children?: React.ReactNode;
|
|
12
|
+
className?: string;
|
|
13
|
+
title?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/* ------------------------------------------------------------------ */
|
|
17
|
+
/* Component */
|
|
18
|
+
|
|
19
|
+
const Edit = (props: EditProps) => {
|
|
20
|
+
const { children, className = "", title } = props ?? {};
|
|
21
|
+
const pageContext = usePageContext();
|
|
22
|
+
|
|
23
|
+
/* ---------------------- Events ---------------------- */
|
|
24
|
+
const handleClick = async () => {
|
|
25
|
+
try {
|
|
26
|
+
await pageContext?.set("editable", true);
|
|
27
|
+
} catch (err: any) {
|
|
28
|
+
alert(err.message);
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/* ---------------------- Render ---------------------- */
|
|
33
|
+
return (
|
|
34
|
+
<button onClick={handleClick} className={`px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors ${className}`}>
|
|
35
|
+
{children || title || "Edit"}
|
|
36
|
+
</button>
|
|
37
|
+
);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export default Edit;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { AbstractComponent } from "../../types/component";
|
|
3
|
+
interface LookupPageProps extends AbstractComponent {
|
|
4
|
+
url: string;
|
|
5
|
+
name?: string;
|
|
6
|
+
result?: Record<string, any>;
|
|
7
|
+
children?: React.ReactNode;
|
|
8
|
+
className?: string;
|
|
9
|
+
title?: string;
|
|
10
|
+
icon?: string;
|
|
11
|
+
opt?: Record<string, any>;
|
|
12
|
+
iconOnly?: boolean;
|
|
13
|
+
popupClassName?: string;
|
|
14
|
+
}
|
|
15
|
+
declare const LookupPage: (props: LookupPageProps) => import("react/jsx-runtime").JSX.Element;
|
|
16
|
+
export default LookupPage;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { forwardRef, memo, useImperativeHandle, useRef, useState } from "react";
|
|
4
|
+
import { usePageContext } from "../../core/PageContext";
|
|
5
|
+
import { getValue, substituteExpr } from "../../lib/utils/BeanUtils";
|
|
6
|
+
import PopupView from "../view/PopupView";
|
|
7
|
+
/* ------------------------------------------------------------------ */
|
|
8
|
+
/* Component */
|
|
9
|
+
const LookupPage = (props) => {
|
|
10
|
+
const { url, name = "", result = null, children, className = "", title, icon, opt = {}, popupClassName = "", iconOnly = false } = props !== null && props !== void 0 ? props : {};
|
|
11
|
+
const { data = {} } = opt;
|
|
12
|
+
const pageContext = usePageContext();
|
|
13
|
+
const [showPopup, setShowPopup] = useState(false);
|
|
14
|
+
const [popupUrl, setPopupUrl] = useState("");
|
|
15
|
+
const slotRef = useRef(null);
|
|
16
|
+
const onClose = () => {
|
|
17
|
+
var _a;
|
|
18
|
+
(_a = slotRef.current) === null || _a === void 0 ? void 0 : _a.update(null);
|
|
19
|
+
};
|
|
20
|
+
/* ---------------------- Events ---------------------- */
|
|
21
|
+
const handleClick = () => {
|
|
22
|
+
var _a;
|
|
23
|
+
if (!url)
|
|
24
|
+
return;
|
|
25
|
+
//combine data if specified and pageContext all data if specified
|
|
26
|
+
const surl = substituteExpr(url, Object.assign(Object.assign({}, pageContext === null || pageContext === void 0 ? void 0 : pageContext.getAllData()), data));
|
|
27
|
+
setPopupUrl(surl);
|
|
28
|
+
setShowPopup(true);
|
|
29
|
+
const handler = {
|
|
30
|
+
onSelect: (itm) => {
|
|
31
|
+
let resdata = itm;
|
|
32
|
+
if (result != null) {
|
|
33
|
+
resdata = getValue(result, itm);
|
|
34
|
+
}
|
|
35
|
+
alert("item selected " + JSON.stringify(resdata));
|
|
36
|
+
if (name) {
|
|
37
|
+
pageContext.set(name, resdata);
|
|
38
|
+
}
|
|
39
|
+
onClose();
|
|
40
|
+
//pageContext.refresh();
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
//eventHandler={handler}
|
|
44
|
+
(_a = slotRef.current) === null || _a === void 0 ? void 0 : _a.update(_jsx(PopupView, { url: surl, onClose: onClose, eventHandler: handler }));
|
|
45
|
+
};
|
|
46
|
+
const handleClosePopup = () => {
|
|
47
|
+
setShowPopup(false);
|
|
48
|
+
};
|
|
49
|
+
/* ---------------------- Render ---------------------- */
|
|
50
|
+
return (_jsxs(_Fragment, { children: [iconOnly ? (_jsx("span", { onClick: handleClick, className: `cursor-pointer ${className}`, children: icon })) : (_jsxs("button", { onClick: handleClick, className: `px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors ${className}`, children: [icon && _jsx("span", { className: "dl-action-icon", children: icon }), title || "View Page"] })), _jsx(ChildrenSlot, { ref: slotRef })] }));
|
|
51
|
+
};
|
|
52
|
+
export default LookupPage;
|
|
53
|
+
const ChildrenSlot = memo(forwardRef((_, ref) => {
|
|
54
|
+
const [content, setContent] = useState(null);
|
|
55
|
+
useImperativeHandle(ref, () => ({
|
|
56
|
+
update: (content) => {
|
|
57
|
+
// console.log("view page children slot", content);
|
|
58
|
+
setContent(content);
|
|
59
|
+
},
|
|
60
|
+
}), []);
|
|
61
|
+
return _jsx(_Fragment, { children: content == null ? null : content });
|
|
62
|
+
}));
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import React, { forwardRef, memo, useImperativeHandle, useRef, useState } from "react";
|
|
4
|
+
import { usePageContext } from "../../core/PageContext";
|
|
5
|
+
import { getValue, substituteExpr } from "../../lib/utils/BeanUtils";
|
|
6
|
+
import { AbstractComponent } from "../../types/component";
|
|
7
|
+
import PopupView from "../view/PopupView";
|
|
8
|
+
|
|
9
|
+
/* ------------------------------------------------------------------ */
|
|
10
|
+
/* Types */
|
|
11
|
+
|
|
12
|
+
interface LookupPageProps extends AbstractComponent {
|
|
13
|
+
url: string;
|
|
14
|
+
name?: string;
|
|
15
|
+
result?: Record<string, any>;
|
|
16
|
+
children?: React.ReactNode;
|
|
17
|
+
className?: string;
|
|
18
|
+
title?: string;
|
|
19
|
+
icon?: string;
|
|
20
|
+
opt?: Record<string, any>;
|
|
21
|
+
iconOnly?: boolean; // ✅ added
|
|
22
|
+
popupClassName?: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/* ------------------------------------------------------------------ */
|
|
26
|
+
/* Component */
|
|
27
|
+
|
|
28
|
+
const LookupPage = (props: LookupPageProps) => {
|
|
29
|
+
const { url, name = "", result = null, children, className = "", title, icon, opt = {}, popupClassName = "", iconOnly = false } = props ?? {};
|
|
30
|
+
const { data = {} } = opt;
|
|
31
|
+
|
|
32
|
+
const pageContext = usePageContext();
|
|
33
|
+
const [showPopup, setShowPopup] = useState(false);
|
|
34
|
+
const [popupUrl, setPopupUrl] = useState("");
|
|
35
|
+
const slotRef = useRef<ChildrenSlotHandle>(null);
|
|
36
|
+
|
|
37
|
+
const onClose = () => {
|
|
38
|
+
slotRef.current?.update(null);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/* ---------------------- Events ---------------------- */
|
|
42
|
+
const handleClick = () => {
|
|
43
|
+
if (!url) return;
|
|
44
|
+
//combine data if specified and pageContext all data if specified
|
|
45
|
+
const surl = substituteExpr(url, { ...pageContext?.getAllData(), ...data });
|
|
46
|
+
setPopupUrl(surl);
|
|
47
|
+
setShowPopup(true);
|
|
48
|
+
|
|
49
|
+
const handler = {
|
|
50
|
+
onSelect: (itm: any) => {
|
|
51
|
+
let resdata = itm;
|
|
52
|
+
if (result != null) {
|
|
53
|
+
resdata = getValue(result, itm);
|
|
54
|
+
}
|
|
55
|
+
alert("item selected " + JSON.stringify(resdata));
|
|
56
|
+
if (name) {
|
|
57
|
+
pageContext.set(name, resdata);
|
|
58
|
+
}
|
|
59
|
+
onClose();
|
|
60
|
+
//pageContext.refresh();
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
//eventHandler={handler}
|
|
64
|
+
slotRef.current?.update(<PopupView url={surl} onClose={onClose} eventHandler={handler} />);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const handleClosePopup = () => {
|
|
68
|
+
setShowPopup(false);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
/* ---------------------- Render ---------------------- */
|
|
72
|
+
return (
|
|
73
|
+
<>
|
|
74
|
+
{iconOnly ? (
|
|
75
|
+
<span onClick={handleClick} className={`cursor-pointer ${className}`}>
|
|
76
|
+
{icon}
|
|
77
|
+
</span>
|
|
78
|
+
) : (
|
|
79
|
+
<button onClick={handleClick} className={`px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors ${className}`}>
|
|
80
|
+
{icon && <span className="dl-action-icon">{icon}</span>}
|
|
81
|
+
{title || "View Page"}
|
|
82
|
+
</button>
|
|
83
|
+
)}
|
|
84
|
+
|
|
85
|
+
<ChildrenSlot ref={slotRef} />
|
|
86
|
+
</>
|
|
87
|
+
);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export default LookupPage;
|
|
91
|
+
|
|
92
|
+
type ChildrenSlotHandle = {
|
|
93
|
+
update: (content: React.ReactNode) => void;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const ChildrenSlot = memo(
|
|
97
|
+
forwardRef<ChildrenSlotHandle>((_, ref) => {
|
|
98
|
+
const [content, setContent] = useState<React.ReactNode>(null);
|
|
99
|
+
|
|
100
|
+
useImperativeHandle(
|
|
101
|
+
ref,
|
|
102
|
+
() => ({
|
|
103
|
+
update: (content: React.ReactNode) => {
|
|
104
|
+
// console.log("view page children slot", content);
|
|
105
|
+
setContent(content);
|
|
106
|
+
},
|
|
107
|
+
}),
|
|
108
|
+
[],
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
return <>{content == null ? null : content}</>;
|
|
112
|
+
}),
|
|
113
|
+
);
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { AbstractComponent } from "../../types/component";
|
|
2
|
+
interface ProcessRunnerProps extends AbstractComponent {
|
|
3
|
+
/**
|
|
4
|
+
* Field expression for current progress value. Default: "{processedcount}"
|
|
5
|
+
*/
|
|
6
|
+
value?: string;
|
|
7
|
+
/**
|
|
8
|
+
* Field expression for max value. Default: "{totalcount}"
|
|
9
|
+
*/
|
|
10
|
+
maxValue?: string;
|
|
11
|
+
/**
|
|
12
|
+
* Field expression resolving to the server-side status field.
|
|
13
|
+
* Expected values (case-insensitive): IDLE | RUNNING | PAUSED | DONE.
|
|
14
|
+
* Default: "{status}"
|
|
15
|
+
*/
|
|
16
|
+
statusValue?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Optional label expression shown below the bar.
|
|
19
|
+
* Only rendered when provided.
|
|
20
|
+
* Example: "{processedcount} of {totalcount} records processed"
|
|
21
|
+
*/
|
|
22
|
+
labelExpr?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Data config: the API endpoint polled on interval to refresh the record.
|
|
25
|
+
* Should return the single record object: { _id, status, processedcount, totalcount, ... }
|
|
26
|
+
* May contain bound param expressions, e.g. "/processtask?_id={_id}"
|
|
27
|
+
*
|
|
28
|
+
* Note: The DataList (parent) fetches the initial list. This component
|
|
29
|
+
* polls independently for live updates on its own record.
|
|
30
|
+
*/
|
|
31
|
+
data?: {
|
|
32
|
+
api: string;
|
|
33
|
+
/** Action APIs called on button click, then immediately re-fetches. */
|
|
34
|
+
actions?: {
|
|
35
|
+
start?: string;
|
|
36
|
+
pause?: string;
|
|
37
|
+
resume?: string;
|
|
38
|
+
end?: string;
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Polling interval in milliseconds. Default: 5000.
|
|
43
|
+
* Timer only fires while status === "running".
|
|
44
|
+
*/
|
|
45
|
+
interval?: number;
|
|
46
|
+
/** Button label overrides */
|
|
47
|
+
labels?: {
|
|
48
|
+
start?: string;
|
|
49
|
+
pause?: string;
|
|
50
|
+
resume?: string;
|
|
51
|
+
end?: string;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Row data injected by the Table renderer (same as ViewPage opt.data).
|
|
55
|
+
* Carries the initial record: { _id, status, processedcount, totalcount }
|
|
56
|
+
* This is the seed — polling overlays it with fresh values.
|
|
57
|
+
*/
|
|
58
|
+
opt?: Record<string, any>;
|
|
59
|
+
className?: string;
|
|
60
|
+
}
|
|
61
|
+
declare const ProcessRunner: (props: ProcessRunnerProps) => import("react/jsx-runtime").JSX.Element;
|
|
62
|
+
export default ProcessRunner;
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
4
|
+
import { usePageContext } from "../../core/PageContext";
|
|
5
|
+
import { getValue, substituteExpr } from "../../lib/utils/BeanUtils";
|
|
6
|
+
import { getUrlPageParams } from "../../lib/utils/PageUtils";
|
|
7
|
+
/* ------------------------------------------------------------------ */
|
|
8
|
+
/* Helpers */
|
|
9
|
+
const toRunnerState = (raw) => {
|
|
10
|
+
switch (String(raw !== null && raw !== void 0 ? raw : "").toUpperCase()) {
|
|
11
|
+
case "RUNNING":
|
|
12
|
+
return "running";
|
|
13
|
+
case "PAUSED":
|
|
14
|
+
return "paused";
|
|
15
|
+
case "DONE":
|
|
16
|
+
return "done";
|
|
17
|
+
default:
|
|
18
|
+
return "idle";
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
const resolveNumeric = (expr, data) => {
|
|
22
|
+
const n = Number(getValue(expr, data));
|
|
23
|
+
return isNaN(n) ? 0 : n;
|
|
24
|
+
};
|
|
25
|
+
/* ------------------------------------------------------------------ */
|
|
26
|
+
/* Component */
|
|
27
|
+
const ProcessRunner = (props) => {
|
|
28
|
+
const { value: valueProp = "{processedcount}", maxValue: maxValueProp = "{totalcount}", statusValue = "{status}", labelExpr, data, interval = 5000, labels = {}, opt = {}, className = "", } = props !== null && props !== void 0 ? props : {};
|
|
29
|
+
const { data: optData = {} } = opt;
|
|
30
|
+
const { start: startLabel = "Start", pause: pauseLabel = "Pause", resume: resumeLabel = "Resume", end: endLabel = "End" } = labels;
|
|
31
|
+
const pageContext = usePageContext();
|
|
32
|
+
/* ----------------------------------------------------------------
|
|
33
|
+
liveData is the SOLE source of truth.
|
|
34
|
+
|
|
35
|
+
Seed it with optData (the row record from DataList) so the
|
|
36
|
+
component displays correctly on first render — before any poll fires.
|
|
37
|
+
Subsequent polls overwrite it entirely with the server's response.
|
|
38
|
+
---------------------------------------------------------------- */
|
|
39
|
+
const [liveData, setLiveData] = useState(optData);
|
|
40
|
+
const intervalRef = useRef(null);
|
|
41
|
+
const [isBusy, setIsBusy] = useState(false); // prevents double-clicks during action API call
|
|
42
|
+
// When optData changes from outside (table refresh, parent re-render),
|
|
43
|
+
// merge it in — but don't overwrite fields already updated by polling.
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
setLiveData((prev) => (Object.assign(Object.assign({}, optData), prev)));
|
|
46
|
+
}, [optData]);
|
|
47
|
+
/* ----------------------------------------------------------------
|
|
48
|
+
Resolution context — built from all data sources.
|
|
49
|
+
Priority (low → high): url params → page data → liveData
|
|
50
|
+
liveData already contains optData as its seed, so per-row fields
|
|
51
|
+
like {_id} resolve correctly from the very first render.
|
|
52
|
+
---------------------------------------------------------------- */
|
|
53
|
+
const resolveCtx = useMemo(() => {
|
|
54
|
+
const { params } = getUrlPageParams();
|
|
55
|
+
return Object.assign(Object.assign(Object.assign(Object.assign({}, params), pageContext.getAllData()), optData), liveData);
|
|
56
|
+
}, [liveData, optData, pageContext]);
|
|
57
|
+
/* ----------------------------------------------------------------
|
|
58
|
+
All display values are derived from resolveCtx — no separate state.
|
|
59
|
+
This is what makes multi-browser sync work: any change in the DB
|
|
60
|
+
flows through poll → liveData → resolveCtx → these values → render.
|
|
61
|
+
---------------------------------------------------------------- */
|
|
62
|
+
const state = toRunnerState(getValue(statusValue, resolveCtx));
|
|
63
|
+
const currentValue = resolveNumeric(valueProp, resolveCtx);
|
|
64
|
+
const maxValue = resolveNumeric(maxValueProp, resolveCtx);
|
|
65
|
+
const percent = maxValue > 0 ? Math.min((currentValue / maxValue) * 100, 100) : 0;
|
|
66
|
+
const resolvedLabel = labelExpr ? substituteExpr(labelExpr, resolveCtx) : null;
|
|
67
|
+
/* ----------------------------------------------------------------
|
|
68
|
+
Core fetch — retrieves the latest record and overwrites liveData.
|
|
69
|
+
Called both by the interval timer AND immediately after button actions.
|
|
70
|
+
---------------------------------------------------------------- */
|
|
71
|
+
const fetchRecord = useCallback(async () => {
|
|
72
|
+
if (!(data === null || data === void 0 ? void 0 : data.api))
|
|
73
|
+
return;
|
|
74
|
+
try {
|
|
75
|
+
const url = substituteExpr(data.api, resolveCtx);
|
|
76
|
+
const json = await (pageContext === null || pageContext === void 0 ? void 0 : pageContext.execService(url, resolveCtx));
|
|
77
|
+
if (!json)
|
|
78
|
+
return;
|
|
79
|
+
// Full overwrite — server response is authoritative.
|
|
80
|
+
// state, currentValue, maxValue all re-derive from this on next render.
|
|
81
|
+
setLiveData(json);
|
|
82
|
+
}
|
|
83
|
+
catch (_a) {
|
|
84
|
+
// Silently ignore — next tick will retry
|
|
85
|
+
}
|
|
86
|
+
}, [data === null || data === void 0 ? void 0 : data.api, resolveCtx, pageContext]);
|
|
87
|
+
/* ----------------------------------------------------------------
|
|
88
|
+
Polling — only runs while state === "running".
|
|
89
|
+
Starts automatically when state becomes "running" (either from a
|
|
90
|
+
button click confirming via re-fetch, or from another browser
|
|
91
|
+
changing the DB and the interval picking it up).
|
|
92
|
+
---------------------------------------------------------------- */
|
|
93
|
+
const startPolling = useCallback(() => {
|
|
94
|
+
if (intervalRef.current)
|
|
95
|
+
return;
|
|
96
|
+
intervalRef.current = setInterval(fetchRecord, interval);
|
|
97
|
+
}, [fetchRecord, interval]);
|
|
98
|
+
const stopPolling = useCallback(() => {
|
|
99
|
+
if (intervalRef.current) {
|
|
100
|
+
clearInterval(intervalRef.current);
|
|
101
|
+
intervalRef.current = null;
|
|
102
|
+
}
|
|
103
|
+
}, []);
|
|
104
|
+
// Manage timer based on derived state — not on button clicks.
|
|
105
|
+
// This means another browser pausing/completing the job will also
|
|
106
|
+
// stop the timer on this browser after the next tick confirms it.
|
|
107
|
+
useEffect(() => {
|
|
108
|
+
if (state === "running") {
|
|
109
|
+
startPolling();
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
stopPolling();
|
|
113
|
+
}
|
|
114
|
+
}, [state, startPolling, stopPolling]);
|
|
115
|
+
// Cleanup on unmount (row removed from table, page navigated away)
|
|
116
|
+
useEffect(() => () => stopPolling(), [stopPolling]);
|
|
117
|
+
/* ----------------------------------------------------------------
|
|
118
|
+
Action handler — the key pattern for button clicks:
|
|
119
|
+
1. Call action API (POST/GET — whatever your backend expects)
|
|
120
|
+
2. Immediately re-fetch the record — don't wait for next tick
|
|
121
|
+
3. liveData updates → state re-derives → UI updates instantly
|
|
122
|
+
No optimistic setState — server response is always the authority.
|
|
123
|
+
---------------------------------------------------------------- */
|
|
124
|
+
const fireAction = useCallback(async (actionUrl) => {
|
|
125
|
+
if (!actionUrl || isBusy)
|
|
126
|
+
return;
|
|
127
|
+
setIsBusy(true);
|
|
128
|
+
try {
|
|
129
|
+
const url = substituteExpr(actionUrl, resolveCtx);
|
|
130
|
+
await (pageContext === null || pageContext === void 0 ? void 0 : pageContext.execService(url, resolveCtx));
|
|
131
|
+
}
|
|
132
|
+
catch (_a) {
|
|
133
|
+
// Action failed — re-fetch anyway to show real current state
|
|
134
|
+
}
|
|
135
|
+
finally {
|
|
136
|
+
// Always re-fetch immediately after action — this is what makes
|
|
137
|
+
// the button feel instant rather than waiting for the next tick.
|
|
138
|
+
await fetchRecord();
|
|
139
|
+
setIsBusy(false);
|
|
140
|
+
}
|
|
141
|
+
}, [isBusy, resolveCtx, fetchRecord, pageContext]);
|
|
142
|
+
/* ----------------------------------------------------------------
|
|
143
|
+
Handlers — just delegate to fireAction with the right endpoint.
|
|
144
|
+
If no action API is configured, fetchRecord still runs so the
|
|
145
|
+
UI reflects whatever the server currently has.
|
|
146
|
+
---------------------------------------------------------------- */
|
|
147
|
+
const handleStart = () => { var _a; return fireAction((_a = data === null || data === void 0 ? void 0 : data.actions) === null || _a === void 0 ? void 0 : _a.start); };
|
|
148
|
+
const handlePause = () => { var _a; return fireAction((_a = data === null || data === void 0 ? void 0 : data.actions) === null || _a === void 0 ? void 0 : _a.pause); };
|
|
149
|
+
const handleResume = () => { var _a; return fireAction((_a = data === null || data === void 0 ? void 0 : data.actions) === null || _a === void 0 ? void 0 : _a.resume); };
|
|
150
|
+
const handleEnd = () => { var _a; return fireAction((_a = data === null || data === void 0 ? void 0 : data.actions) === null || _a === void 0 ? void 0 : _a.end); };
|
|
151
|
+
/* ----------------------------------------------------------------
|
|
152
|
+
Render
|
|
153
|
+
---------------------------------------------------------------- */
|
|
154
|
+
return (_jsxs("div", { className: `flex flex-col gap-2 ${className}`, children: [state === "idle" && (_jsx("button", { onClick: handleStart, disabled: isBusy, 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", children: isBusy ? "…" : startLabel })), state !== "idle" && (_jsxs("div", { className: "flex flex-col gap-1 w-full", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "flex-1 h-4 bg-gray-200 rounded-full overflow-hidden", role: "progressbar", "aria-valuenow": currentValue, "aria-valuemin": 0, "aria-valuemax": maxValue || undefined, "aria-label": "Process progress", children: _jsx("div", { className: `h-full rounded-full transition-all duration-500 ${state === "done" ? "bg-green-500" : state === "paused" ? "bg-yellow-400" : "bg-blue-500"}`, style: { width: `${percent}%` } }) }), _jsxs("span", { className: "text-xs text-gray-600 w-10 text-right tabular-nums", children: [Math.round(percent), "%"] }), state === "running" && (_jsx("button", { onClick: handlePause, disabled: isBusy, 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", children: isBusy ? "…" : pauseLabel })), state === "paused" && (_jsxs(_Fragment, { children: [_jsx("button", { onClick: handleResume, disabled: isBusy, 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", children: isBusy ? "…" : resumeLabel }), _jsx("button", { onClick: handleEnd, disabled: isBusy, 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", children: isBusy ? "…" : endLabel })] })), state === "done" && (_jsx("button", { onClick: handleEnd, disabled: isBusy, 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", children: isBusy ? "…" : endLabel }))] }), resolvedLabel && _jsx("p", { className: "text-xs text-gray-500 mt-0.5", children: resolvedLabel })] }))] }));
|
|
155
|
+
};
|
|
156
|
+
export default ProcessRunner;
|