@ramesesinc/platform-core 0.1.6 → 0.1.9
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/LookupPage.js +9 -31
- package/dist/components/action/ViewPage.d.ts +2 -0
- package/dist/components/action/ViewPage.js +25 -31
- package/dist/components/common/UIComponent.js +4 -3
- package/dist/components/index.d.ts +3 -0
- package/dist/components/index.js +1 -0
- package/dist/components/table/DataList.js +2 -2
- package/dist/components/view/PopupView.d.ts +13 -0
- package/dist/components/view/PopupView.js +25 -20
- package/dist/core/DataContext.d.ts +7 -4
- package/dist/core/DataContext.js +16 -4
- package/dist/core/Page.js +25 -26
- package/dist/core/PageCache.js +7 -7
- package/dist/core/PageContext.js +17 -7
- package/dist/core/PageViewContext.d.ts +13 -1
- package/dist/core/PageViewContext.js +75 -2
- package/dist/core/PopupContext.d.ts +49 -0
- package/dist/core/PopupContext.js +380 -0
- package/dist/core/RowContext.js +1 -1
- package/dist/core/WindowContext.d.ts +15 -0
- package/dist/core/WindowContext.js +28 -0
- package/dist/core/index.d.ts +17 -0
- package/dist/core/index.js +1 -0
- package/dist/index.css +25 -7
- package/dist/lib/utils/BeanUtils.js +7 -7
- package/dist/templates/DataListTemplate.js +7 -2
- package/dist/templates/ExplorerTemplate.js +1 -1
- package/package.json +5 -5
- package/dist/components/action/AlertMessage.tsx +0 -38
- package/dist/components/action/Button.tsx +0 -230
- package/dist/components/action/CancelEdit.tsx +0 -40
- package/dist/components/action/DeleteData.tsx +0 -73
- package/dist/components/action/Edit.tsx +0 -40
- package/dist/components/action/LookupPage.tsx +0 -113
- package/dist/components/action/ProcessRunner.tsx +0 -337
- package/dist/components/action/Refresh.tsx +0 -35
- package/dist/components/action/SaveData.tsx +0 -74
- package/dist/components/action/SelectData.tsx +0 -47
- package/dist/components/action/Undo.tsx +0 -50
- package/dist/components/action/UpdateData.tsx +0 -49
- package/dist/components/action/UpdateState.tsx +0 -40
- package/dist/components/action/ViewBackPage.tsx +0 -46
- package/dist/components/action/ViewPage.tsx +0 -141
- package/dist/components/common/UIComponent.tsx +0 -86
- package/dist/components/common/UIInput.tsx +0 -49
- package/dist/components/common/UIMenu.tsx +0 -91
- package/dist/components/index.ts +0 -51
- package/dist/components/input/CodeEditor.tsx +0 -188
- package/dist/components/input/DateField.tsx +0 -274
- package/dist/components/input/DayPicker.tsx +0 -5
- package/dist/components/input/HtmlCode.tsx +0 -203
- package/dist/components/input/JsonCode.tsx +0 -205
- package/dist/components/input/MonthPicker.tsx +0 -5
- package/dist/components/input/ScriptCode.tsx +0 -195
- package/dist/components/input/Select.tsx +0 -78
- package/dist/components/input/SqlCode.tsx +0 -162
- package/dist/components/input/StringDecision.tsx +0 -64
- package/dist/components/input/Text.tsx +0 -57
- package/dist/components/input/YearPicker.tsx +0 -81
- package/dist/components/list/IconMenu.tsx +0 -115
- package/dist/components/list/TabMenu.tsx +0 -127
- package/dist/components/list/TreeMenu.tsx +0 -279
- package/dist/components/list/TxnTaskList.tsx +0 -198
- package/dist/components/output/Label.tsx +0 -50
- package/dist/components/table/DataList.tsx +0 -820
- package/dist/components/table/DataTable.tsx +0 -572
- package/dist/components/table/ListHandler.ts +0 -276
- package/dist/components/table/TableContext.tsx +0 -122
- package/dist/components/view/ComponentView.tsx +0 -102
- package/dist/components/view/FilterView.tsx +0 -21
- package/dist/components/view/HtmlForm.tsx +0 -176
- package/dist/components/view/HtmlView.tsx +0 -98
- package/dist/components/view/IFrameView.tsx +0 -48
- package/dist/components/view/Modal.tsx +0 -72
- package/dist/components/view/PageView.tsx +0 -131
- package/dist/components/view/PopupView.tsx +0 -160
- package/dist/components/view/RootView.tsx +0 -109
- package/dist/components/view/WizardView.tsx +0 -48
- package/dist/lib/layouts/BorderLayout.tsx +0 -31
- package/dist/lib/layouts/CardLayout.tsx +0 -73
- package/dist/lib/layouts/CenterLayout.tsx +0 -20
- package/dist/lib/layouts/GridLayout.tsx +0 -20
- package/dist/lib/layouts/HPanel.tsx +0 -31
- package/dist/lib/layouts/HorizontalLayout.tsx +0 -29
- package/dist/lib/layouts/MainLayout.tsx +0 -16
- package/dist/lib/layouts/PageLayout.tsx +0 -29
- package/dist/lib/layouts/VPanel.tsx +0 -27
- package/dist/lib/layouts/XLayout.tsx +0 -29
- package/dist/lib/layouts/YLayout.tsx +0 -29
- package/dist/lib/layouts/index.ts +0 -13
package/dist/index.css
CHANGED
|
@@ -681,6 +681,9 @@ video {
|
|
|
681
681
|
.z-\[9999\] {
|
|
682
682
|
z-index: 9999;
|
|
683
683
|
}
|
|
684
|
+
.m-0 {
|
|
685
|
+
margin: 0px;
|
|
686
|
+
}
|
|
684
687
|
.mb-2 {
|
|
685
688
|
margin-bottom: 0.5rem;
|
|
686
689
|
}
|
|
@@ -813,6 +816,9 @@ video {
|
|
|
813
816
|
.max-h-\[60px\] {
|
|
814
817
|
max-height: 60px;
|
|
815
818
|
}
|
|
819
|
+
.min-h-\[100px\] {
|
|
820
|
+
min-height: 100px;
|
|
821
|
+
}
|
|
816
822
|
.min-h-\[60px\] {
|
|
817
823
|
min-height: 60px;
|
|
818
824
|
}
|
|
@@ -879,9 +885,18 @@ video {
|
|
|
879
885
|
.w-full {
|
|
880
886
|
width: 100%;
|
|
881
887
|
}
|
|
888
|
+
.min-w-\[100px\] {
|
|
889
|
+
min-width: 100px;
|
|
890
|
+
}
|
|
882
891
|
.min-w-\[180px\] {
|
|
883
892
|
min-width: 180px;
|
|
884
893
|
}
|
|
894
|
+
.min-w-\[200px\] {
|
|
895
|
+
min-width: 200px;
|
|
896
|
+
}
|
|
897
|
+
.min-w-\[300px\] {
|
|
898
|
+
min-width: 300px;
|
|
899
|
+
}
|
|
885
900
|
.min-w-\[50px\] {
|
|
886
901
|
min-width: 50px;
|
|
887
902
|
}
|
|
@@ -1112,10 +1127,6 @@ video {
|
|
|
1112
1127
|
--tw-bg-opacity: 1;
|
|
1113
1128
|
background-color: rgb(232 240 254 / var(--tw-bg-opacity, 1));
|
|
1114
1129
|
}
|
|
1115
|
-
.bg-black {
|
|
1116
|
-
--tw-bg-opacity: 1;
|
|
1117
|
-
background-color: rgb(0 0 0 / var(--tw-bg-opacity, 1));
|
|
1118
|
-
}
|
|
1119
1130
|
.bg-black\/40 {
|
|
1120
1131
|
background-color: rgb(0 0 0 / 0.4);
|
|
1121
1132
|
}
|
|
@@ -1185,9 +1196,6 @@ video {
|
|
|
1185
1196
|
--tw-bg-opacity: 1;
|
|
1186
1197
|
background-color: rgb(250 204 21 / var(--tw-bg-opacity, 1));
|
|
1187
1198
|
}
|
|
1188
|
-
.bg-opacity-50 {
|
|
1189
|
-
--tw-bg-opacity: 0.5;
|
|
1190
|
-
}
|
|
1191
1199
|
.object-contain {
|
|
1192
1200
|
-o-object-fit: contain;
|
|
1193
1201
|
object-fit: contain;
|
|
@@ -1196,6 +1204,9 @@ video {
|
|
|
1196
1204
|
-o-object-fit: cover;
|
|
1197
1205
|
object-fit: cover;
|
|
1198
1206
|
}
|
|
1207
|
+
.p-0 {
|
|
1208
|
+
padding: 0px;
|
|
1209
|
+
}
|
|
1199
1210
|
.p-1 {
|
|
1200
1211
|
padding: 0.25rem;
|
|
1201
1212
|
}
|
|
@@ -1450,6 +1461,9 @@ video {
|
|
|
1450
1461
|
--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);
|
|
1451
1462
|
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
|
1452
1463
|
}
|
|
1464
|
+
.outline {
|
|
1465
|
+
outline-style: solid;
|
|
1466
|
+
}
|
|
1453
1467
|
.filter {
|
|
1454
1468
|
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
|
|
1455
1469
|
}
|
|
@@ -1566,6 +1580,10 @@ video {
|
|
|
1566
1580
|
--tw-text-opacity: 1;
|
|
1567
1581
|
color: rgb(75 85 99 / var(--tw-text-opacity, 1));
|
|
1568
1582
|
}
|
|
1583
|
+
.hover\:text-gray-700:hover {
|
|
1584
|
+
--tw-text-opacity: 1;
|
|
1585
|
+
color: rgb(55 65 81 / var(--tw-text-opacity, 1));
|
|
1586
|
+
}
|
|
1569
1587
|
.hover\:text-gray-800:hover {
|
|
1570
1588
|
--tw-text-opacity: 1;
|
|
1571
1589
|
color: rgb(31 41 55 / var(--tw-text-opacity, 1));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export const getValue = (path, data) => {
|
|
2
2
|
if (path == null)
|
|
3
|
-
return
|
|
3
|
+
return null;
|
|
4
4
|
// If path is an object, recursively resolve all its values
|
|
5
5
|
if (typeof path === "object") {
|
|
6
6
|
const resolved = {};
|
|
@@ -10,7 +10,7 @@ export const getValue = (path, data) => {
|
|
|
10
10
|
return resolved;
|
|
11
11
|
}
|
|
12
12
|
if (typeof path !== "string")
|
|
13
|
-
return
|
|
13
|
+
return null;
|
|
14
14
|
if (!path.includes("{"))
|
|
15
15
|
return path;
|
|
16
16
|
// If the entire string is a single placeholder e.g. "{vdata}" or "{vdata.company.name}"
|
|
@@ -21,10 +21,10 @@ export const getValue = (path, data) => {
|
|
|
21
21
|
let current = data;
|
|
22
22
|
for (const token of tokens) {
|
|
23
23
|
if (current == null)
|
|
24
|
-
return
|
|
24
|
+
return null;
|
|
25
25
|
current = current[token];
|
|
26
26
|
}
|
|
27
|
-
return current
|
|
27
|
+
return current == null ? null : current;
|
|
28
28
|
}
|
|
29
29
|
// If the string contains placeholders mixed with other text e.g. "Hello {name}!"
|
|
30
30
|
// fall back to string replacement
|
|
@@ -36,13 +36,13 @@ export const getValue = (path, data) => {
|
|
|
36
36
|
return match;
|
|
37
37
|
current = current[token];
|
|
38
38
|
}
|
|
39
|
-
return current
|
|
39
|
+
return current == null ? null : current;
|
|
40
40
|
});
|
|
41
41
|
};
|
|
42
42
|
export const replaceValues = (obj, source) => {
|
|
43
43
|
// Handle null or undefined
|
|
44
|
-
if (obj
|
|
45
|
-
return
|
|
44
|
+
if (obj == null) {
|
|
45
|
+
return null;
|
|
46
46
|
}
|
|
47
47
|
// Handle primitives (numbers, booleans)
|
|
48
48
|
if (typeof obj !== 'object' && typeof obj !== 'string') {
|
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import DataList from "../components/table/DataList";
|
|
3
|
+
import { usePageViewContext } from "../core/PageViewContext";
|
|
3
4
|
import Panel from "../core/Panel";
|
|
4
5
|
import BorderLayout from "../layouts/BorderLayout";
|
|
5
6
|
const DataListTemplate = (props) => {
|
|
6
7
|
const { title, cols, data, rowsPerPage, rowActions, bulkActions, toolbarActions, header, footer, right, left, commonActions, filters, disableTotalCount, emptyMessage, errorMessage, striped, bordered, hover, dense, showPagination, paginationPosition, showPageInfo, showTotalCount, showRowsPerPage, rowsPerPageOptions, searchable, searchPlaceholder, searchDebounce, onSearchChange, showFilterPanel, onFilterChange, sortable, defaultSort, showSortIndicator, selectable, selectionMode, onSelectionChange, selectOnRowClick, onRowClick, onRowDoubleClick, toolbarTitle, showRefreshButton, showExportButton, onError, onRefresh, onExport, className, rowClassName, } = props !== null && props !== void 0 ? props : {};
|
|
7
|
-
const
|
|
8
|
+
const pageView = usePageViewContext();
|
|
9
|
+
const getPreferredTitle = () => {
|
|
10
|
+
return title !== null && title !== void 0 ? title : pageView.getUI().getTitle();
|
|
11
|
+
};
|
|
12
|
+
const attr = { title: getPreferredTitle(), cols, data, rowsPerPage, commonActions, rowActions, toolbarActions, bulkActions, filters };
|
|
8
13
|
const loadPanel = (section) => {
|
|
9
14
|
return _jsx(Panel, { content: section });
|
|
10
15
|
};
|
|
11
|
-
return (_jsx(BorderLayout, { className: "
|
|
16
|
+
return (_jsx(BorderLayout, { className: "p-0", north: loadPanel(header), south: loadPanel(footer), east: loadPanel(right), west: loadPanel(left), children: _jsx(DataList, { attr: attr }) }));
|
|
12
17
|
};
|
|
13
18
|
export default DataListTemplate;
|
|
@@ -11,7 +11,7 @@ const ExplorerTemplate = (props) => {
|
|
|
11
11
|
width: "230px",
|
|
12
12
|
opacity: open ? 1 : 0,
|
|
13
13
|
pointerEvents: open ? "auto" : "none",
|
|
14
|
-
}, children: _jsx(TreeMenu, { name: name, menugroup: menugroup, items: items, data: data }) }) }), _jsx("button", { onClick: () => setOpen((prev) => !prev), className: "absolute top-5 -right-4 w-8 h-8 bg-white border rounded-full flex items-center justify-center shadow z-10", children: open ? _jsx(ChevronLeft, { size: 18 }) : _jsx(ChevronRight, { size: 18 }) })] }), children: _jsx("div", { className: "px-6 py-
|
|
14
|
+
}, children: _jsx(TreeMenu, { name: name, menugroup: menugroup, items: items, data: data }) }) }), _jsx("button", { onClick: () => setOpen((prev) => !prev), className: "absolute top-5 -right-4 w-8 h-8 bg-white border rounded-full flex items-center justify-center shadow z-10", children: open ? _jsx(ChevronLeft, { size: 18 }) : _jsx(ChevronRight, { size: 18 }) })] }), children: _jsx("div", { className: "px-6 py-1", children: _jsx(PageView, { name: name, depends: name }) }) }) }));
|
|
15
15
|
};
|
|
16
16
|
ExplorerTemplate.hasSelectionHandling = true;
|
|
17
17
|
export default ExplorerTemplate;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ramesesinc/platform-core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.9",
|
|
4
4
|
"description": "Platform Core Library",
|
|
5
5
|
"author": "Rameses Systems Inc.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"./index.css": "./dist/index.css"
|
|
21
21
|
},
|
|
22
22
|
"scripts": {
|
|
23
|
-
"build": "rm -rf dist && tsc && postcss src/styles/index.css -o dist/index.css
|
|
23
|
+
"build": "rm -rf dist && tsc && postcss src/styles/index.css -o dist/index.css",
|
|
24
24
|
"build2": "rm -rf dist && tsc",
|
|
25
25
|
"clean": "rm -rf dist",
|
|
26
26
|
"dev": "tsc --watch",
|
|
@@ -36,9 +36,9 @@
|
|
|
36
36
|
"react-dom": ">=18.2.0"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"@ramesesinc/app-forms": "
|
|
40
|
-
"@ramesesinc/client": "
|
|
41
|
-
"@ramesesinc/lib": "
|
|
39
|
+
"@ramesesinc/app-forms": "*",
|
|
40
|
+
"@ramesesinc/client": "*",
|
|
41
|
+
"@ramesesinc/lib": "*",
|
|
42
42
|
"@types/crypto-js": "^4.2.2",
|
|
43
43
|
"@types/js-cookie": "^3.0.6",
|
|
44
44
|
"@types/node": "^20",
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { usePageContext } from "../../core/PageContext";
|
|
4
|
-
import { render } from "../../lib/utils/ExprUtil";
|
|
5
|
-
import { AbstractComponent } from "../../types/component";
|
|
6
|
-
|
|
7
|
-
/* ------------------------------------------------------------------ */
|
|
8
|
-
/* Types */
|
|
9
|
-
|
|
10
|
-
interface AlertMessageProps extends AbstractComponent {
|
|
11
|
-
expr: string;
|
|
12
|
-
className?: string;
|
|
13
|
-
title?: string;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/* ------------------------------------------------------------------ */
|
|
17
|
-
/* Component */
|
|
18
|
-
|
|
19
|
-
const AlertMessage = (props: AlertMessageProps) => {
|
|
20
|
-
const { expr, className = "", title } = props ?? {};
|
|
21
|
-
const pageContext = usePageContext();
|
|
22
|
-
|
|
23
|
-
/* ---------------------- Events ---------------------- */
|
|
24
|
-
const handleClick = () => {
|
|
25
|
-
if (expr) {
|
|
26
|
-
alert(render(expr, pageContext?.getAllData()));
|
|
27
|
-
}
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
/* ---------------------- Render ---------------------- */
|
|
31
|
-
return (
|
|
32
|
-
<button onClick={handleClick} className={`px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors ${className}`}>
|
|
33
|
-
{title || "Alert"}
|
|
34
|
-
</button>
|
|
35
|
-
);
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
export default AlertMessage;
|
|
@@ -1,230 +0,0 @@
|
|
|
1
|
-
import { getError, mergeCN, UIButtonControl } from "@ramesesinc/client";
|
|
2
|
-
import React, { ReactNode, useState } from "react";
|
|
3
|
-
import { useApp } from "../../core/AppContext";
|
|
4
|
-
import { usePageContext } from "../../core/PageContext";
|
|
5
|
-
|
|
6
|
-
const RADIUS_STYLES = {
|
|
7
|
-
none: "rounded-none",
|
|
8
|
-
md: "rounded-md",
|
|
9
|
-
lg: "rounded-lg",
|
|
10
|
-
xl: "rounded-xl",
|
|
11
|
-
"2xl": "rounded-2xl",
|
|
12
|
-
"3xl": "rounded-3xl",
|
|
13
|
-
full: "rounded-full",
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
interface BaseButtonProps extends UIButtonControl {
|
|
17
|
-
children?: ReactNode;
|
|
18
|
-
title?: string;
|
|
19
|
-
icon?: ReactNode;
|
|
20
|
-
iconOrientation?: "left" | "right" | "top" | "bottom";
|
|
21
|
-
|
|
22
|
-
loader?: ReactNode | (() => ReactNode);
|
|
23
|
-
loaderLabel?: string;
|
|
24
|
-
|
|
25
|
-
variant?: "primary" | "secondary" | "danger" | "text" | "contained" | "outlined";
|
|
26
|
-
|
|
27
|
-
radius?: "none" | "md" | "lg" | "xl" | "2xl" | "3xl" | "full";
|
|
28
|
-
|
|
29
|
-
size?: "sm" | "md" | "lg";
|
|
30
|
-
|
|
31
|
-
type?: "button" | "submit";
|
|
32
|
-
|
|
33
|
-
isLoading?: boolean;
|
|
34
|
-
|
|
35
|
-
actionid?: string;
|
|
36
|
-
actionParams?: Record<string, any>;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const BaseButton = ({
|
|
40
|
-
binding,
|
|
41
|
-
className = "",
|
|
42
|
-
title,
|
|
43
|
-
disabled = false,
|
|
44
|
-
immediate = false,
|
|
45
|
-
onClick,
|
|
46
|
-
|
|
47
|
-
children,
|
|
48
|
-
|
|
49
|
-
icon,
|
|
50
|
-
iconOrientation = "left",
|
|
51
|
-
loader,
|
|
52
|
-
loaderLabel,
|
|
53
|
-
|
|
54
|
-
variant = "text",
|
|
55
|
-
radius = "md",
|
|
56
|
-
size = "md",
|
|
57
|
-
|
|
58
|
-
isLoading = false,
|
|
59
|
-
actionid,
|
|
60
|
-
actionParams,
|
|
61
|
-
}: BaseButtonProps) => {
|
|
62
|
-
const pageContext = usePageContext();
|
|
63
|
-
binding = pageContext.binding;
|
|
64
|
-
const { tenant, module } = useApp();
|
|
65
|
-
|
|
66
|
-
// --- Style Calculation ---
|
|
67
|
-
const baseStyles =
|
|
68
|
-
"inline-flex items-center justify-center px-4 py-[4px] text-md font-medium shadow-sm transition-all duration-150 ease-in-out space-x-2";
|
|
69
|
-
const focusStyles =
|
|
70
|
-
"focus:outline-none focus:ring-2 focus:ring-offset-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2";
|
|
71
|
-
|
|
72
|
-
const variantStyles = {
|
|
73
|
-
primary: "border border-transparent bg-blue-500 text-blue-50 hover:bg-blue-600 focus:ring-blue-500",
|
|
74
|
-
secondary: "border border-gray-300 bg-white text-gray-700 hover:bg-gray-50 focus:ring-indigo-300",
|
|
75
|
-
danger: "border border-transparent bg-red-600 text-white hover:bg-red-700 focus:ring-red-400",
|
|
76
|
-
|
|
77
|
-
text: "border border-transparent bg-transparent text-blue-600 hover:bg-blue-50 focus:ring-indigo-300",
|
|
78
|
-
contained: "border border-transparent bg-blue-500 text-blue-50 hover:bg-blue-600 focus:ring-blue-500",
|
|
79
|
-
outlined: "border bg-transparent border-blue-500 text-blue-600 hover:bg-blue-50 focus:ring-indigo-300",
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
const disabledStyles = "opacity-70 cursor-not-allowed";
|
|
83
|
-
const isVertical = iconOrientation === "top" || iconOrientation === "bottom";
|
|
84
|
-
const flexDirectionClass = isVertical ? "flex-col" : "flex-row";
|
|
85
|
-
|
|
86
|
-
// Gap is needed if an icon is present OR if no custom loader is provided (fallback uses a spinner).
|
|
87
|
-
const gapClass = icon || (isLoading && !loader) ? (isVertical ? "gap-1" : "gap-2") : "";
|
|
88
|
-
|
|
89
|
-
let roundingStyle = RADIUS_STYLES[radius || "md"];
|
|
90
|
-
if (roundingStyle == null) {
|
|
91
|
-
roundingStyle = RADIUS_STYLES["md"];
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
const finalClassNames = mergeCN(
|
|
95
|
-
baseStyles,
|
|
96
|
-
focusStyles,
|
|
97
|
-
variantStyles[variant],
|
|
98
|
-
flexDirectionClass,
|
|
99
|
-
gapClass,
|
|
100
|
-
roundingStyle,
|
|
101
|
-
`${disabled || isLoading ? disabledStyles : ""}`,
|
|
102
|
-
className ?? "",
|
|
103
|
-
);
|
|
104
|
-
|
|
105
|
-
const [internalLoading, setInternalLoading] = useState(false);
|
|
106
|
-
|
|
107
|
-
const loading = isLoading || internalLoading;
|
|
108
|
-
|
|
109
|
-
// --- Content Calculation ---
|
|
110
|
-
// This is the main logic block that determines what to display.
|
|
111
|
-
let content: ReactNode;
|
|
112
|
-
|
|
113
|
-
if (loading) {
|
|
114
|
-
// LOADING STATE
|
|
115
|
-
if (loader) {
|
|
116
|
-
// If a custom loader is provided, use it.
|
|
117
|
-
content = typeof loader === "function" ? loader() : loader;
|
|
118
|
-
} else {
|
|
119
|
-
// Fallback loader: Spinner + original title
|
|
120
|
-
content = (
|
|
121
|
-
<>
|
|
122
|
-
<svg className="animate-spin h-5 w-5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
|
123
|
-
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
|
|
124
|
-
<path
|
|
125
|
-
className="opacity-75"
|
|
126
|
-
fill="currentColor"
|
|
127
|
-
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
|
128
|
-
></path>
|
|
129
|
-
</svg>
|
|
130
|
-
<span>{loaderLabel ?? children}</span>
|
|
131
|
-
</>
|
|
132
|
-
);
|
|
133
|
-
}
|
|
134
|
-
} else {
|
|
135
|
-
// NORMAL STATE
|
|
136
|
-
content = (
|
|
137
|
-
<>
|
|
138
|
-
{icon && (iconOrientation === "left" || iconOrientation === "top") && icon}
|
|
139
|
-
<span>{title || children}</span>
|
|
140
|
-
{icon && (iconOrientation === "right" || iconOrientation === "bottom") && icon}
|
|
141
|
-
</>
|
|
142
|
-
);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
|
|
146
|
-
if (loading || disabled) return;
|
|
147
|
-
|
|
148
|
-
try {
|
|
149
|
-
setInternalLoading(true);
|
|
150
|
-
|
|
151
|
-
if (!immediate && binding) {
|
|
152
|
-
const validationResult = binding.validate();
|
|
153
|
-
if (validationResult != null && validationResult !== "") {
|
|
154
|
-
return;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
if (onClick != null) {
|
|
159
|
-
const result = onClick?.(event);
|
|
160
|
-
if (result != null && typeof result.then === "function") {
|
|
161
|
-
result
|
|
162
|
-
.then(() => {
|
|
163
|
-
// successful execution
|
|
164
|
-
})
|
|
165
|
-
.catch((err: any) => {
|
|
166
|
-
const e = getError(err);
|
|
167
|
-
binding?.setError(e.message);
|
|
168
|
-
});
|
|
169
|
-
}
|
|
170
|
-
} else if (actionid != null && actionid.trim() !== "") {
|
|
171
|
-
Promise.resolve()
|
|
172
|
-
.then(async () => {
|
|
173
|
-
// const actionFunc = await ResourceLoader.getAction(actionid || "");
|
|
174
|
-
// const opt = { tenant, module };
|
|
175
|
-
// const params = { ...actionParams, opt };
|
|
176
|
-
// resolveParams(params ?? {});
|
|
177
|
-
// const result = await actionFunc(params);
|
|
178
|
-
// console.log("result", result);
|
|
179
|
-
})
|
|
180
|
-
.catch((err: any) => {
|
|
181
|
-
console.log("action error", err);
|
|
182
|
-
const e = getError(err);
|
|
183
|
-
binding?.setError(e.message);
|
|
184
|
-
});
|
|
185
|
-
}
|
|
186
|
-
} catch (err) {
|
|
187
|
-
console.log("err", err);
|
|
188
|
-
const e = getError(err);
|
|
189
|
-
binding?.setError(e.message);
|
|
190
|
-
} finally {
|
|
191
|
-
setInternalLoading(false);
|
|
192
|
-
}
|
|
193
|
-
};
|
|
194
|
-
|
|
195
|
-
const resolveParams = (source: Record<string, any>) => {
|
|
196
|
-
Object.entries(source || {}).forEach(([key, value]) => {
|
|
197
|
-
if (value != null && typeof value === "string" && value.startsWith("{") && value.endsWith("}")) {
|
|
198
|
-
const name = value.slice(1, -1);
|
|
199
|
-
if (name === "data") {
|
|
200
|
-
source[key] = binding?.getData();
|
|
201
|
-
} else {
|
|
202
|
-
source[key] = binding?.get(name);
|
|
203
|
-
}
|
|
204
|
-
} else if (value != null && typeof value === "object") {
|
|
205
|
-
resolveParams(value);
|
|
206
|
-
}
|
|
207
|
-
});
|
|
208
|
-
};
|
|
209
|
-
|
|
210
|
-
return (
|
|
211
|
-
<button type="submit" onClick={handleClick} className={finalClassNames} disabled={disabled || loading}>
|
|
212
|
-
{content}
|
|
213
|
-
</button>
|
|
214
|
-
);
|
|
215
|
-
};
|
|
216
|
-
|
|
217
|
-
// Button
|
|
218
|
-
const Button = (props: BaseButtonProps) => {
|
|
219
|
-
const { variant = "text" } = props ?? {};
|
|
220
|
-
return <BaseButton {...props} variant={variant} type="button" />;
|
|
221
|
-
};
|
|
222
|
-
|
|
223
|
-
// Submit
|
|
224
|
-
const Submit = (props: BaseButtonProps) => {
|
|
225
|
-
const { variant = "primary" } = props ?? {};
|
|
226
|
-
return <BaseButton {...props} variant={variant} type="submit" />;
|
|
227
|
-
};
|
|
228
|
-
|
|
229
|
-
export default Button;
|
|
230
|
-
export { Button, Submit };
|
|
@@ -1,40 +0,0 @@
|
|
|
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 CancelEditProps extends AbstractComponent {
|
|
11
|
-
children?: React.ReactNode;
|
|
12
|
-
className?: string;
|
|
13
|
-
title?: string;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/* ------------------------------------------------------------------ */
|
|
17
|
-
/* Component */
|
|
18
|
-
|
|
19
|
-
const CancelEdit = (props: CancelEditProps) => {
|
|
20
|
-
const { children, className = "", title } = props ?? {};
|
|
21
|
-
const pageContext = usePageContext();
|
|
22
|
-
|
|
23
|
-
/* ---------------------- Events ---------------------- */
|
|
24
|
-
const handleClick = async () => {
|
|
25
|
-
try {
|
|
26
|
-
await pageContext?.set("mode", "read");
|
|
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 || "Cancel Edit"}
|
|
36
|
-
</button>
|
|
37
|
-
);
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
export default CancelEdit;
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import React from "react";
|
|
4
|
-
import { usePageContext } from "../../core/PageContext";
|
|
5
|
-
import { usePageViewContext } from "../../core/PageViewContext";
|
|
6
|
-
import { useRowContext } from "../../core/RowContext";
|
|
7
|
-
import { getValue } from "../../lib/utils/BeanUtils";
|
|
8
|
-
import { getUrlPageParams } from "../../lib/utils/PageUtils";
|
|
9
|
-
import { AbstractComponent } from "../../types/component";
|
|
10
|
-
|
|
11
|
-
/* ------------------------------------------------------------------ */
|
|
12
|
-
/* Types */
|
|
13
|
-
|
|
14
|
-
interface DeleteDataProps extends AbstractComponent {
|
|
15
|
-
api: string;
|
|
16
|
-
className?: string;
|
|
17
|
-
title?: string;
|
|
18
|
-
icon?: string | React.ReactNode;
|
|
19
|
-
opt?: Record<string, any>;
|
|
20
|
-
iconOnly?: boolean;
|
|
21
|
-
params: Record<string, any>;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/* ------------------------------------------------------------------ */
|
|
25
|
-
/* Component */
|
|
26
|
-
|
|
27
|
-
const DeleteData = (props: DeleteDataProps) => {
|
|
28
|
-
const { api, className = "", title, icon, opt = {}, params, iconOnly = false } = props ?? {};
|
|
29
|
-
const { data = {} } = opt;
|
|
30
|
-
|
|
31
|
-
const rowContext = useRowContext();
|
|
32
|
-
const pageView = usePageViewContext();
|
|
33
|
-
const pageContext = usePageContext();
|
|
34
|
-
|
|
35
|
-
/* ---------------------- Events ---------------------- */
|
|
36
|
-
const handleClick = async () => {
|
|
37
|
-
try {
|
|
38
|
-
if (!api) throw new Error("api not defined");
|
|
39
|
-
if (data) {
|
|
40
|
-
const allData = pageContext?.getAllData() ?? {};
|
|
41
|
-
const urlParams = getUrlPageParams();
|
|
42
|
-
const d = getValue(params, { ...allData, ...urlParams?.params, ...data });
|
|
43
|
-
await pageContext?.execService(api, d);
|
|
44
|
-
} else {
|
|
45
|
-
const vdata = pageContext?.getData() ?? {};
|
|
46
|
-
const urlParams = getUrlPageParams();
|
|
47
|
-
const d = getValue(params, { ...urlParams?.params, ...vdata });
|
|
48
|
-
await pageContext?.execService(api, vdata);
|
|
49
|
-
}
|
|
50
|
-
// pageContext?.refresh();
|
|
51
|
-
} catch (err: any) {
|
|
52
|
-
alert(err.message);
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
/* ---------------------- Render ---------------------- */
|
|
57
|
-
return (
|
|
58
|
-
<>
|
|
59
|
-
{iconOnly ? (
|
|
60
|
-
<span onClick={handleClick} className={`cursor-pointer ${className}`}>
|
|
61
|
-
{icon}
|
|
62
|
-
</span>
|
|
63
|
-
) : (
|
|
64
|
-
<button onClick={handleClick} className={`px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors ${className}`}>
|
|
65
|
-
{icon && <span className="dl-action-icon">{icon}</span>}
|
|
66
|
-
{title || "Remove"}
|
|
67
|
-
</button>
|
|
68
|
-
)}
|
|
69
|
-
</>
|
|
70
|
-
);
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
export default DeleteData;
|
|
@@ -1,40 +0,0 @@
|
|
|
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;
|