@pisell/private-materials 3.4.156 → 3.4.158
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/build/lowcode/assets-daily.json +11 -11
- package/build/lowcode/assets-dev.json +2 -2
- package/build/lowcode/assets-prod.json +11 -11
- package/build/lowcode/meta.js +1 -1
- package/build/lowcode/render/default/view.css +1 -1
- package/build/lowcode/render/default/view.js +14 -14
- package/build/lowcode/view.css +1 -1
- package/build/lowcode/view.js +14 -14
- package/es/index.d.ts +7 -1
- package/es/index.js +5 -1
- package/es/plus/inventory/BindingModal.js +94 -0
- package/es/plus/inventory/InventoryItemManagement.d.ts +7 -0
- package/es/plus/inventory/InventoryItemManagement.js +204 -0
- package/es/plus/inventory/InventoryLocationManagement.d.ts +7 -0
- package/es/plus/inventory/InventoryLocationManagement.js +296 -0
- package/es/plus/inventory/InventoryUnitManagement.d.ts +7 -0
- package/es/plus/inventory/InventoryUnitManagement.js +144 -0
- package/es/plus/inventory/ItemDrawer.js +266 -0
- package/es/plus/inventory/RecordDialog.js +141 -0
- package/es/plus/inventory/StockList.js +132 -0
- package/es/plus/inventory/api.js +66 -0
- package/es/plus/inventory/components.js +172 -0
- package/es/plus/inventory/context.js +118 -0
- package/es/plus/inventory/forms.js +46 -0
- package/es/plus/inventory/hooks.js +235 -0
- package/es/plus/inventory/index.less +559 -0
- package/es/plus/inventory/locales.js +277 -0
- package/es/plus/inventory/types.d.ts +10 -0
- package/es/plus/inventory/utils.js +24 -0
- package/es/plus/pisellSupersetDashboard/README.md +291 -0
- package/es/plus/pisellSupersetDashboard/index.d.ts +15 -0
- package/es/plus/pisellSupersetDashboard/index.js +187 -0
- package/es/plus/pisellSupersetDashboard/index.less +83 -0
- package/es/plus/pisellSupersetDashboard/locales.js +36 -0
- package/es/plus/pisellSupersetDashboard/serve.js +51 -0
- package/es/plus/pisellSupersetDashboard/types.d.ts +17 -0
- package/es/plus/skuOptionsSelection/store/createStore.js +2 -2
- package/lib/index.d.ts +7 -1
- package/lib/index.js +134 -126
- package/lib/plus/inventory/BindingModal.js +96 -0
- package/lib/plus/inventory/InventoryItemManagement.d.ts +7 -0
- package/lib/plus/inventory/InventoryItemManagement.js +206 -0
- package/lib/plus/inventory/InventoryLocationManagement.d.ts +7 -0
- package/lib/plus/inventory/InventoryLocationManagement.js +298 -0
- package/lib/plus/inventory/InventoryUnitManagement.d.ts +7 -0
- package/lib/plus/inventory/InventoryUnitManagement.js +146 -0
- package/lib/plus/inventory/ItemDrawer.js +268 -0
- package/lib/plus/inventory/RecordDialog.js +143 -0
- package/lib/plus/inventory/StockList.js +134 -0
- package/lib/plus/inventory/api.js +66 -0
- package/lib/plus/inventory/components.js +181 -0
- package/lib/plus/inventory/context.js +121 -0
- package/lib/plus/inventory/forms.js +50 -0
- package/lib/plus/inventory/hooks.js +240 -0
- package/lib/plus/inventory/index.less +559 -0
- package/lib/plus/inventory/locales.js +277 -0
- package/lib/plus/inventory/types.d.ts +10 -0
- package/lib/plus/inventory/utils.js +30 -0
- package/lib/plus/pisellSupersetDashboard/README.md +291 -0
- package/lib/plus/pisellSupersetDashboard/index.d.ts +15 -0
- package/lib/plus/pisellSupersetDashboard/index.js +189 -0
- package/lib/plus/pisellSupersetDashboard/index.less +83 -0
- package/lib/plus/pisellSupersetDashboard/locales.js +36 -0
- package/lib/plus/pisellSupersetDashboard/serve.js +52 -0
- package/lib/plus/pisellSupersetDashboard/types.d.ts +17 -0
- package/lowcode/inventory-item-management/meta.ts +20 -0
- package/lowcode/inventory-location-management/meta.ts +20 -0
- package/lowcode/inventory-unit-management/meta.ts +20 -0
- package/lowcode/pisell-superset-dashboard/meta.ts +75 -0
- package/package.json +5 -3
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { _objectSpread2 } from "../../_virtual/_@oxc-project_runtime@0.122.0/helpers/objectSpread2.js";
|
|
2
|
+
import { useInventory } from "./context.js";
|
|
3
|
+
import { useInventoryOptions } from "./hooks.js";
|
|
4
|
+
import React, { useMemo, useState } from "react";
|
|
5
|
+
import { Alert, Button, Empty, Input, Pagination, Select, Space, Spin, Tag } from "antd";
|
|
6
|
+
import { PisellDataSourceContainer } from "@pisell/materials";
|
|
7
|
+
import { useDebounce } from "ahooks";
|
|
8
|
+
import { LoadingOutlined } from "@ant-design/icons";
|
|
9
|
+
//#region src/plus/inventory/components.tsx
|
|
10
|
+
function RequestError({ error, retry }) {
|
|
11
|
+
const { errorText, t } = useInventory();
|
|
12
|
+
return error ? /* @__PURE__ */ React.createElement(Alert, {
|
|
13
|
+
type: "error",
|
|
14
|
+
showIcon: true,
|
|
15
|
+
message: errorText(error),
|
|
16
|
+
action: /* @__PURE__ */ React.createElement(Button, { onClick: retry }, t("retry"))
|
|
17
|
+
}) : null;
|
|
18
|
+
}
|
|
19
|
+
function StatusTag({ status }) {
|
|
20
|
+
const { t } = useInventory();
|
|
21
|
+
return status ? /* @__PURE__ */ React.createElement(Tag, { color: status === "active" ? "green" : "default" }, t(status)) : null;
|
|
22
|
+
}
|
|
23
|
+
function StatusSelect({ value, onChange }) {
|
|
24
|
+
const { t } = useInventory();
|
|
25
|
+
return /* @__PURE__ */ React.createElement(Select, {
|
|
26
|
+
className: "inventory-filter",
|
|
27
|
+
allowClear: true,
|
|
28
|
+
placeholder: t("allStatuses"),
|
|
29
|
+
value,
|
|
30
|
+
onChange,
|
|
31
|
+
options: ["active", "inactive"].map((status) => ({
|
|
32
|
+
value: status,
|
|
33
|
+
label: t(status)
|
|
34
|
+
}))
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
function SearchInput({ value, onChange, items = false }) {
|
|
38
|
+
const { t } = useInventory();
|
|
39
|
+
return /* @__PURE__ */ React.createElement(Input.Search, {
|
|
40
|
+
className: "inventory-search",
|
|
41
|
+
allowClear: true,
|
|
42
|
+
placeholder: t(items ? "searchItems" : "search"),
|
|
43
|
+
"aria-label": t(items ? "searchItems" : "search"),
|
|
44
|
+
value,
|
|
45
|
+
onChange: (event) => onChange(event.target.value)
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
function InventoryHeader({ title, description, children }) {
|
|
49
|
+
return /* @__PURE__ */ React.createElement("header", { className: "inventory-header" }, /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("h2", null, title), description && /* @__PURE__ */ React.createElement("p", null, description)), /* @__PURE__ */ React.createElement(Space, { wrap: true }, children));
|
|
50
|
+
}
|
|
51
|
+
function InventoryNavLoading() {
|
|
52
|
+
const { t } = useInventory();
|
|
53
|
+
return /* @__PURE__ */ React.createElement("div", {
|
|
54
|
+
className: "inventory-nav-loading",
|
|
55
|
+
role: "status"
|
|
56
|
+
}, /* @__PURE__ */ React.createElement(Spin, {
|
|
57
|
+
size: "small",
|
|
58
|
+
indicator: /* @__PURE__ */ React.createElement(LoadingOutlined, {
|
|
59
|
+
spin: true,
|
|
60
|
+
style: { fontSize: 16 }
|
|
61
|
+
})
|
|
62
|
+
}), /* @__PURE__ */ React.createElement("span", null, t("loading")));
|
|
63
|
+
}
|
|
64
|
+
function TableContent({ columns, loading, tableKey }) {
|
|
65
|
+
const context = PisellDataSourceContainer.useContainerContext();
|
|
66
|
+
const { t, scopeId } = useInventory();
|
|
67
|
+
return /* @__PURE__ */ React.createElement(Spin, {
|
|
68
|
+
spinning: loading,
|
|
69
|
+
delay: 150,
|
|
70
|
+
indicator: /* @__PURE__ */ React.createElement(LoadingOutlined, {
|
|
71
|
+
spin: true,
|
|
72
|
+
style: { fontSize: 24 }
|
|
73
|
+
}),
|
|
74
|
+
tip: t("loading"),
|
|
75
|
+
wrapperClassName: "inventory-table-loading"
|
|
76
|
+
}, /* @__PURE__ */ React.createElement(PisellDataSourceContainer.Table, _objectSpread2(_objectSpread2({}, context), {}, {
|
|
77
|
+
serverActions: _objectSpread2(_objectSpread2({}, context.serverActions), {}, { list: _objectSpread2(_objectSpread2({}, context.serverActions.list), {}, { loading: false }) }),
|
|
78
|
+
columns,
|
|
79
|
+
rowKey: "id",
|
|
80
|
+
scroll: { x: "max-content" },
|
|
81
|
+
__id: `${scopeId}-${tableKey}`,
|
|
82
|
+
scopeId: tableKey,
|
|
83
|
+
locale: { emptyText: loading ? /* @__PURE__ */ React.createElement("div", {
|
|
84
|
+
className: "inventory-table-loading-placeholder",
|
|
85
|
+
"aria-hidden": true
|
|
86
|
+
}) : /* @__PURE__ */ React.createElement(Empty, {
|
|
87
|
+
image: Empty.PRESENTED_IMAGE_SIMPLE,
|
|
88
|
+
description: t("empty")
|
|
89
|
+
}) }
|
|
90
|
+
})));
|
|
91
|
+
}
|
|
92
|
+
function InventoryTable(props) {
|
|
93
|
+
const { t, scopeId } = useInventory();
|
|
94
|
+
const overrideData = useMemo(() => ({ list: {
|
|
95
|
+
list: props.rows,
|
|
96
|
+
count: props.count
|
|
97
|
+
} }), [props.rows, props.count]);
|
|
98
|
+
const dataSource = useMemo(() => ({ key: `${scopeId}-${props.tableKey}` }), [scopeId, props.tableKey]);
|
|
99
|
+
return /* @__PURE__ */ React.createElement("div", { className: "inventory-table" }, /* @__PURE__ */ React.createElement(PisellDataSourceContainer, {
|
|
100
|
+
dataSource,
|
|
101
|
+
autoRun: { list: false },
|
|
102
|
+
pagination: false,
|
|
103
|
+
overrideData
|
|
104
|
+
}, /* @__PURE__ */ React.createElement(TableContent, {
|
|
105
|
+
columns: props.columns,
|
|
106
|
+
loading: props.loading,
|
|
107
|
+
tableKey: props.tableKey
|
|
108
|
+
})), /* @__PURE__ */ React.createElement(Pagination, {
|
|
109
|
+
className: "inventory-pagination",
|
|
110
|
+
current: props.page,
|
|
111
|
+
pageSize: props.size,
|
|
112
|
+
total: props.count,
|
|
113
|
+
showSizeChanger: true,
|
|
114
|
+
pageSizeOptions: [
|
|
115
|
+
20,
|
|
116
|
+
50,
|
|
117
|
+
100
|
|
118
|
+
],
|
|
119
|
+
onChange: props.onPageChange,
|
|
120
|
+
showTotal: (count) => `${t("count")} ${count}`,
|
|
121
|
+
disabled: props.loading
|
|
122
|
+
}));
|
|
123
|
+
}
|
|
124
|
+
function PagedInventorySelect({ resource, value, onChange, filters = {}, disabled = false, selected, placeholder, id }) {
|
|
125
|
+
const { name, t } = useInventory();
|
|
126
|
+
const [search, setSearch] = useState("");
|
|
127
|
+
const keyword = useDebounce(search, { wait: 250 });
|
|
128
|
+
const [revision, setRevision] = useState(0);
|
|
129
|
+
const [chosenRecord, setChosenRecord] = useState();
|
|
130
|
+
const options = useInventoryOptions(resource, _objectSpread2(_objectSpread2({}, filters), {}, { search: keyword || void 0 }), !disabled, revision);
|
|
131
|
+
const fallback = (chosenRecord === null || chosenRecord === void 0 ? void 0 : chosenRecord.id) === value ? chosenRecord : (selected === null || selected === void 0 ? void 0 : selected.id) === value ? selected : void 0;
|
|
132
|
+
const rows = fallback && !options.rows.some((record) => record.id === value) ? [fallback, ...options.rows] : options.rows;
|
|
133
|
+
return /* @__PURE__ */ React.createElement(Select, {
|
|
134
|
+
id,
|
|
135
|
+
style: { width: "100%" },
|
|
136
|
+
showSearch: true,
|
|
137
|
+
allowClear: true,
|
|
138
|
+
filterOption: false,
|
|
139
|
+
value,
|
|
140
|
+
placeholder,
|
|
141
|
+
disabled,
|
|
142
|
+
loading: options.loading,
|
|
143
|
+
onSearch: setSearch,
|
|
144
|
+
onChange: (nextValue) => {
|
|
145
|
+
setChosenRecord(rows.find((record) => record.id === nextValue));
|
|
146
|
+
onChange === null || onChange === void 0 || onChange(nextValue);
|
|
147
|
+
},
|
|
148
|
+
onDropdownVisibleChange: (open) => {
|
|
149
|
+
if (open) {
|
|
150
|
+
setSearch("");
|
|
151
|
+
setRevision((n) => n + 1);
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
options: rows.map((record) => ({
|
|
155
|
+
value: record.id,
|
|
156
|
+
label: `${name(record)}${record.status === "inactive" ? ` (${t("inactive")})` : ""}`
|
|
157
|
+
})),
|
|
158
|
+
notFoundContent: options.loading ? t("loading") : t("empty"),
|
|
159
|
+
dropdownRender: (menu) => /* @__PURE__ */ React.createElement(React.Fragment, null, menu, /* @__PURE__ */ React.createElement(RequestError, {
|
|
160
|
+
error: options.error,
|
|
161
|
+
retry: () => void options.reload()
|
|
162
|
+
}), options.hasMore && /* @__PURE__ */ React.createElement(Button, {
|
|
163
|
+
block: true,
|
|
164
|
+
type: "text",
|
|
165
|
+
loading: options.loading,
|
|
166
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
167
|
+
onClick: () => void options.loadMore()
|
|
168
|
+
}, t("loadMore")))
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
//#endregion
|
|
172
|
+
export { InventoryHeader, InventoryNavLoading, InventoryTable, PagedInventorySelect, RequestError, SearchInput, StatusSelect, StatusTag };
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import useEngineContext from "../../hooks/useEngineContext.js";
|
|
2
|
+
import useLocale from "../../hooks/useLocale.js";
|
|
3
|
+
import { createInventoryApi } from "./api.js";
|
|
4
|
+
import { getInventoryTexts } from "./locales.js";
|
|
5
|
+
import { inventoryName } from "./utils.js";
|
|
6
|
+
import React, { createContext, useCallback, useContext, useEffect, useId, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
7
|
+
import { ConfigProvider } from "antd";
|
|
8
|
+
import { PisellModal, PisellToast } from "@pisell/materials";
|
|
9
|
+
import "./index.less";
|
|
10
|
+
//#region src/plus/inventory/context.tsx
|
|
11
|
+
const InventoryContext = createContext(null);
|
|
12
|
+
function InventorySession({ children, client, locale, id }) {
|
|
13
|
+
const instanceId = useId();
|
|
14
|
+
const [confirmation, setConfirmation] = useState(null);
|
|
15
|
+
const resolveConfirmation = useRef(null);
|
|
16
|
+
const api = useMemo(() => createInventoryApi(client), [client]);
|
|
17
|
+
const texts = getInventoryTexts(locale);
|
|
18
|
+
const t = useCallback((key) => texts[key], [texts]);
|
|
19
|
+
const name = useCallback((record) => record ? inventoryName(record.name, locale) : t("missing"), [locale, t]);
|
|
20
|
+
const errorText = useCallback((error) => {
|
|
21
|
+
const messageValue = error && typeof error === "object" && "message" in error ? error.message : error;
|
|
22
|
+
const text = typeof messageValue === "string" ? messageValue : "";
|
|
23
|
+
return Object.prototype.hasOwnProperty.call(texts, text) ? t(text) : text || t("failed");
|
|
24
|
+
}, [texts, t]);
|
|
25
|
+
const report = useCallback((error) => {
|
|
26
|
+
PisellToast({ content: errorText(error) });
|
|
27
|
+
}, [errorText]);
|
|
28
|
+
const success = useCallback((key) => {
|
|
29
|
+
PisellToast({ content: t(key) });
|
|
30
|
+
}, [t]);
|
|
31
|
+
const finishConfirmation = useCallback((accepted) => {
|
|
32
|
+
const resolve = resolveConfirmation.current;
|
|
33
|
+
resolveConfirmation.current = null;
|
|
34
|
+
setConfirmation(null);
|
|
35
|
+
resolve === null || resolve === void 0 || resolve(accepted);
|
|
36
|
+
}, []);
|
|
37
|
+
useEffect(() => () => {
|
|
38
|
+
var _resolveConfirmation$;
|
|
39
|
+
(_resolveConfirmation$ = resolveConfirmation.current) === null || _resolveConfirmation$ === void 0 || _resolveConfirmation$.call(resolveConfirmation, false);
|
|
40
|
+
resolveConfirmation.current = null;
|
|
41
|
+
}, []);
|
|
42
|
+
const confirm = useCallback((title, content, discard = false) => {
|
|
43
|
+
if (resolveConfirmation.current) return Promise.resolve(false);
|
|
44
|
+
return new Promise((resolve) => {
|
|
45
|
+
resolveConfirmation.current = resolve;
|
|
46
|
+
setConfirmation({
|
|
47
|
+
title,
|
|
48
|
+
content,
|
|
49
|
+
discard
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
}, []);
|
|
53
|
+
const value = useMemo(() => ({
|
|
54
|
+
api,
|
|
55
|
+
locale,
|
|
56
|
+
t,
|
|
57
|
+
name,
|
|
58
|
+
errorText,
|
|
59
|
+
report,
|
|
60
|
+
success,
|
|
61
|
+
confirm,
|
|
62
|
+
scopeId: id || instanceId
|
|
63
|
+
}), [
|
|
64
|
+
api,
|
|
65
|
+
locale,
|
|
66
|
+
t,
|
|
67
|
+
name,
|
|
68
|
+
errorText,
|
|
69
|
+
report,
|
|
70
|
+
success,
|
|
71
|
+
confirm,
|
|
72
|
+
id,
|
|
73
|
+
instanceId
|
|
74
|
+
]);
|
|
75
|
+
return /* @__PURE__ */ React.createElement(InventoryContext.Provider, { value }, children, confirmation && /* @__PURE__ */ React.createElement(PisellModal, {
|
|
76
|
+
open: true,
|
|
77
|
+
size: "small",
|
|
78
|
+
title: t(confirmation.title),
|
|
79
|
+
okText: t(confirmation.discard ? "discard" : confirmation.title === "unbindTitle" ? "unbind" : "remove"),
|
|
80
|
+
cancelText: t("cancel"),
|
|
81
|
+
okButtonProps: { danger: true },
|
|
82
|
+
maskClosable: false,
|
|
83
|
+
onOk: () => finishConfirmation(true),
|
|
84
|
+
onCancel: () => finishConfirmation(false)
|
|
85
|
+
}, /* @__PURE__ */ React.createElement("div", { className: "inventory-modal-body" }, confirmation.content)));
|
|
86
|
+
}
|
|
87
|
+
function InventoryProvider({ children, id }) {
|
|
88
|
+
var _context$appHelper;
|
|
89
|
+
const context = useEngineContext();
|
|
90
|
+
const locale = useLocale();
|
|
91
|
+
const utils = context === null || context === void 0 || (_context$appHelper = context.appHelper) === null || _context$appHelper === void 0 ? void 0 : _context$appHelper.utils;
|
|
92
|
+
const store = utils === null || utils === void 0 ? void 0 : utils.store;
|
|
93
|
+
const subscribe = useCallback((listener) => {
|
|
94
|
+
var _store$subscribe;
|
|
95
|
+
return (store === null || store === void 0 || (_store$subscribe = store.subscribe) === null || _store$subscribe === void 0 ? void 0 : _store$subscribe.call(store, listener)) || (() => void 0);
|
|
96
|
+
}, [store]);
|
|
97
|
+
const getTenant = useCallback(() => {
|
|
98
|
+
var _store$getState$core$, _store$getState;
|
|
99
|
+
return String((_store$getState$core$ = store === null || store === void 0 || (_store$getState = store.getState) === null || _store$getState === void 0 || (_store$getState = _store$getState.call(store)) === null || _store$getState === void 0 || (_store$getState = _store$getState.core) === null || _store$getState === void 0 || (_store$getState = _store$getState.core) === null || _store$getState === void 0 || (_store$getState = _store$getState.tenant) === null || _store$getState === void 0 ? void 0 : _store$getState.tenant_id) !== null && _store$getState$core$ !== void 0 ? _store$getState$core$ : "");
|
|
100
|
+
}, [store]);
|
|
101
|
+
const tenant = useSyncExternalStore(subscribe, getTenant, getTenant);
|
|
102
|
+
return /* @__PURE__ */ React.createElement(ConfigProvider, {
|
|
103
|
+
prefixCls: "pisell-lowcode",
|
|
104
|
+
componentSize: "large"
|
|
105
|
+
}, /* @__PURE__ */ React.createElement(InventorySession, {
|
|
106
|
+
key: tenant,
|
|
107
|
+
client: utils === null || utils === void 0 ? void 0 : utils.request,
|
|
108
|
+
locale: locale || "en",
|
|
109
|
+
id
|
|
110
|
+
}, children));
|
|
111
|
+
}
|
|
112
|
+
function useInventory() {
|
|
113
|
+
const context = useContext(InventoryContext);
|
|
114
|
+
if (!context) throw new Error("InventoryProvider is required");
|
|
115
|
+
return context;
|
|
116
|
+
}
|
|
117
|
+
//#endregion
|
|
118
|
+
export { InventoryProvider, useInventory };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { useInventory } from "./context.js";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { Form, InputNumber, Select } from "antd";
|
|
4
|
+
import { BaseTranslation } from "@pisell/materials";
|
|
5
|
+
//#region src/plus/inventory/forms.tsx
|
|
6
|
+
function NameField({ disabled = false }) {
|
|
7
|
+
const { t } = useInventory();
|
|
8
|
+
return /* @__PURE__ */ React.createElement(Form.Item, {
|
|
9
|
+
name: "name",
|
|
10
|
+
label: t("name"),
|
|
11
|
+
rules: [{ validator: (_, value) => typeof (value === null || value === void 0 ? void 0 : value.original) === "string" && value.original.trim() ? Promise.resolve() : Promise.reject(new Error(t("originalRequired"))) }]
|
|
12
|
+
}, /* @__PURE__ */ React.createElement(BaseTranslation, {
|
|
13
|
+
renderMode: disabled ? "view" : "edit",
|
|
14
|
+
disabled,
|
|
15
|
+
placeholder: t("name")
|
|
16
|
+
}));
|
|
17
|
+
}
|
|
18
|
+
function StatusField() {
|
|
19
|
+
const { t } = useInventory();
|
|
20
|
+
return /* @__PURE__ */ React.createElement(Form.Item, {
|
|
21
|
+
name: "status",
|
|
22
|
+
label: t("status"),
|
|
23
|
+
rules: [{
|
|
24
|
+
required: true,
|
|
25
|
+
message: t("required")
|
|
26
|
+
}]
|
|
27
|
+
}, /* @__PURE__ */ React.createElement(Select, { options: ["active", "inactive"].map((value) => ({
|
|
28
|
+
value,
|
|
29
|
+
label: t(value)
|
|
30
|
+
})) }));
|
|
31
|
+
}
|
|
32
|
+
function SortField() {
|
|
33
|
+
const { t } = useInventory();
|
|
34
|
+
return /* @__PURE__ */ React.createElement(Form.Item, {
|
|
35
|
+
name: "sort",
|
|
36
|
+
label: t("sort"),
|
|
37
|
+
extra: t("sortHint"),
|
|
38
|
+
rules: [{ validator: (_, value) => Number.isInteger(value) && value >= 0 ? Promise.resolve() : Promise.reject(new Error(t("nonnegative"))) }]
|
|
39
|
+
}, /* @__PURE__ */ React.createElement(InputNumber, {
|
|
40
|
+
min: 0,
|
|
41
|
+
precision: 0,
|
|
42
|
+
style: { width: "100%" }
|
|
43
|
+
}));
|
|
44
|
+
}
|
|
45
|
+
//#endregion
|
|
46
|
+
export { NameField, SortField, StatusField };
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import { _objectSpread2 } from "../../_virtual/_@oxc-project_runtime@0.122.0/helpers/objectSpread2.js";
|
|
2
|
+
import { _asyncToGenerator } from "../../_virtual/_@oxc-project_runtime@0.122.0/helpers/asyncToGenerator.js";
|
|
3
|
+
import { mergeInventoryRecords } from "./utils.js";
|
|
4
|
+
import { useInventory } from "./context.js";
|
|
5
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
6
|
+
//#region src/plus/inventory/hooks.ts
|
|
7
|
+
function useInventoryQuery(load, queryKey, enabled = true) {
|
|
8
|
+
const { api } = useInventory();
|
|
9
|
+
const loadRef = useRef(load);
|
|
10
|
+
loadRef.current = load;
|
|
11
|
+
const [revision, setRevision] = useState(0);
|
|
12
|
+
const key = `${queryKey}:${revision}`;
|
|
13
|
+
const [result, setResult] = useState({
|
|
14
|
+
key: "",
|
|
15
|
+
loading: false
|
|
16
|
+
});
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
if (!enabled) return;
|
|
19
|
+
let current = true;
|
|
20
|
+
setResult({
|
|
21
|
+
key,
|
|
22
|
+
api,
|
|
23
|
+
loading: true
|
|
24
|
+
});
|
|
25
|
+
Promise.resolve().then(() => loadRef.current()).then((data) => {
|
|
26
|
+
if (current) setResult({
|
|
27
|
+
key,
|
|
28
|
+
api,
|
|
29
|
+
data,
|
|
30
|
+
loading: false
|
|
31
|
+
});
|
|
32
|
+
}, (error) => {
|
|
33
|
+
if (current) setResult({
|
|
34
|
+
key,
|
|
35
|
+
api,
|
|
36
|
+
error,
|
|
37
|
+
loading: false
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
return () => {
|
|
41
|
+
current = false;
|
|
42
|
+
};
|
|
43
|
+
}, [
|
|
44
|
+
key,
|
|
45
|
+
enabled,
|
|
46
|
+
api
|
|
47
|
+
]);
|
|
48
|
+
const reload = useCallback(() => setRevision((value) => value + 1), []);
|
|
49
|
+
const valid = enabled && result.key === key && result.api === api;
|
|
50
|
+
return {
|
|
51
|
+
data: valid ? result.data : void 0,
|
|
52
|
+
error: valid ? result.error : void 0,
|
|
53
|
+
loading: enabled && (!valid || result.loading),
|
|
54
|
+
reload
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
function useInventoryList(resource, filters = {}, enabled = true) {
|
|
58
|
+
var _query$data$count, _query$data, _query$data$list, _query$data2;
|
|
59
|
+
const { api } = useInventory();
|
|
60
|
+
const filterKey = JSON.stringify([resource, filters]);
|
|
61
|
+
const [pager, setPager] = useState({
|
|
62
|
+
key: filterKey,
|
|
63
|
+
page: 1,
|
|
64
|
+
size: 20
|
|
65
|
+
});
|
|
66
|
+
const page = pager.key === filterKey ? pager.page : 1;
|
|
67
|
+
const { size } = pager;
|
|
68
|
+
const local = resource === "item-unit";
|
|
69
|
+
const query = useInventoryQuery(_asyncToGenerator(function* () {
|
|
70
|
+
if (local) {
|
|
71
|
+
const units = yield api.units(filters);
|
|
72
|
+
return {
|
|
73
|
+
list: units,
|
|
74
|
+
count: units.length,
|
|
75
|
+
page: 1,
|
|
76
|
+
size: units.length
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
return api.list(resource, _objectSpread2(_objectSpread2({}, filters), {}, {
|
|
80
|
+
page,
|
|
81
|
+
size
|
|
82
|
+
}));
|
|
83
|
+
}), JSON.stringify([
|
|
84
|
+
filterKey,
|
|
85
|
+
local ? null : page,
|
|
86
|
+
local ? null : size
|
|
87
|
+
]), enabled);
|
|
88
|
+
const count = (_query$data$count = (_query$data = query.data) === null || _query$data === void 0 ? void 0 : _query$data.count) !== null && _query$data$count !== void 0 ? _query$data$count : 0;
|
|
89
|
+
useEffect(() => {
|
|
90
|
+
if (!query.data) return;
|
|
91
|
+
const lastPage = Math.max(1, Math.ceil(query.data.count / size));
|
|
92
|
+
if (page > lastPage) setPager({
|
|
93
|
+
key: filterKey,
|
|
94
|
+
page: lastPage,
|
|
95
|
+
size
|
|
96
|
+
});
|
|
97
|
+
}, [
|
|
98
|
+
query.data,
|
|
99
|
+
page,
|
|
100
|
+
size,
|
|
101
|
+
filterKey
|
|
102
|
+
]);
|
|
103
|
+
const rows = (_query$data$list = (_query$data2 = query.data) === null || _query$data2 === void 0 ? void 0 : _query$data2.list) !== null && _query$data$list !== void 0 ? _query$data$list : [];
|
|
104
|
+
return _objectSpread2(_objectSpread2({}, query), {}, {
|
|
105
|
+
count,
|
|
106
|
+
page,
|
|
107
|
+
size,
|
|
108
|
+
rows: local ? rows.slice((page - 1) * size, page * size) : rows,
|
|
109
|
+
onPageChange: (nextPage, nextSize) => setPager({
|
|
110
|
+
key: filterKey,
|
|
111
|
+
page: nextSize === size ? nextPage : 1,
|
|
112
|
+
size: nextSize
|
|
113
|
+
})
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
function useInventoryOptions(resource, filters = {}, enabled = true, revision = 0) {
|
|
117
|
+
const { api } = useInventory();
|
|
118
|
+
const key = JSON.stringify([
|
|
119
|
+
resource,
|
|
120
|
+
filters,
|
|
121
|
+
revision
|
|
122
|
+
]);
|
|
123
|
+
const generation = useRef(0);
|
|
124
|
+
const busy = useRef(false);
|
|
125
|
+
const [result, setResult] = useState({
|
|
126
|
+
key: "",
|
|
127
|
+
rows: [],
|
|
128
|
+
count: 0,
|
|
129
|
+
page: 0,
|
|
130
|
+
loading: false
|
|
131
|
+
});
|
|
132
|
+
const valid = enabled && result.key === key;
|
|
133
|
+
const fetchPage = useCallback(function() {
|
|
134
|
+
var _ref = _asyncToGenerator(function* (page) {
|
|
135
|
+
if (!enabled || page > 1 && busy.current) return;
|
|
136
|
+
const requestId = ++generation.current;
|
|
137
|
+
busy.current = true;
|
|
138
|
+
setResult((previous) => ({
|
|
139
|
+
key,
|
|
140
|
+
rows: page === 1 ? [] : previous.rows,
|
|
141
|
+
count: page === 1 ? 0 : previous.count,
|
|
142
|
+
page: page === 1 ? 0 : previous.page,
|
|
143
|
+
loading: true
|
|
144
|
+
}));
|
|
145
|
+
try {
|
|
146
|
+
const data = yield api.list(resource, _objectSpread2(_objectSpread2({}, JSON.parse(key)[1]), {}, {
|
|
147
|
+
page,
|
|
148
|
+
size: 20
|
|
149
|
+
}));
|
|
150
|
+
if (generation.current !== requestId) return;
|
|
151
|
+
setResult((previous) => ({
|
|
152
|
+
key,
|
|
153
|
+
rows: page === 1 ? data.list : mergeInventoryRecords(previous.rows, data.list),
|
|
154
|
+
count: data.count,
|
|
155
|
+
page,
|
|
156
|
+
loading: false
|
|
157
|
+
}));
|
|
158
|
+
} catch (error) {
|
|
159
|
+
if (generation.current === requestId) setResult((previous) => _objectSpread2(_objectSpread2({}, previous), {}, {
|
|
160
|
+
loading: false,
|
|
161
|
+
error
|
|
162
|
+
}));
|
|
163
|
+
} finally {
|
|
164
|
+
if (generation.current === requestId) busy.current = false;
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
return function(_x) {
|
|
168
|
+
return _ref.apply(this, arguments);
|
|
169
|
+
};
|
|
170
|
+
}(), [
|
|
171
|
+
api,
|
|
172
|
+
resource,
|
|
173
|
+
key,
|
|
174
|
+
enabled
|
|
175
|
+
]);
|
|
176
|
+
useEffect(() => {
|
|
177
|
+
if (enabled) fetchPage(1);
|
|
178
|
+
return () => {
|
|
179
|
+
++generation.current;
|
|
180
|
+
busy.current = false;
|
|
181
|
+
};
|
|
182
|
+
}, [fetchPage, enabled]);
|
|
183
|
+
return {
|
|
184
|
+
rows: valid ? result.rows : [],
|
|
185
|
+
loading: enabled && (!valid || result.loading),
|
|
186
|
+
error: valid ? result.error : void 0,
|
|
187
|
+
hasMore: valid && result.page * 20 < result.count,
|
|
188
|
+
loadMore: () => fetchPage(result.page + 1),
|
|
189
|
+
reload: () => fetchPage(1)
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
function useInventoryMutation() {
|
|
193
|
+
const { report } = useInventory();
|
|
194
|
+
const locked = useRef(false);
|
|
195
|
+
const mounted = useRef(true);
|
|
196
|
+
const [busy, setBusy] = useState(false);
|
|
197
|
+
useEffect(() => {
|
|
198
|
+
mounted.current = true;
|
|
199
|
+
return () => {
|
|
200
|
+
mounted.current = false;
|
|
201
|
+
};
|
|
202
|
+
}, []);
|
|
203
|
+
return {
|
|
204
|
+
busy,
|
|
205
|
+
run: function() {
|
|
206
|
+
var _ref2 = _asyncToGenerator(function* (operation) {
|
|
207
|
+
if (locked.current || !mounted.current) return;
|
|
208
|
+
locked.current = true;
|
|
209
|
+
setBusy(true);
|
|
210
|
+
try {
|
|
211
|
+
yield operation();
|
|
212
|
+
} catch (error) {
|
|
213
|
+
if (mounted.current) report(error);
|
|
214
|
+
} finally {
|
|
215
|
+
locked.current = false;
|
|
216
|
+
if (mounted.current) setBusy(false);
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
return function run(_x2) {
|
|
220
|
+
return _ref2.apply(this, arguments);
|
|
221
|
+
};
|
|
222
|
+
}()
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
function useUnsavedChanges() {
|
|
226
|
+
const { confirm, t } = useInventory();
|
|
227
|
+
const [dirty, setDirty] = useState(false);
|
|
228
|
+
return {
|
|
229
|
+
dirty,
|
|
230
|
+
setDirty,
|
|
231
|
+
canLeave: () => dirty ? confirm("unsavedTitle", t("unsavedHint"), true) : Promise.resolve(true)
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
//#endregion
|
|
235
|
+
export { useInventoryList, useInventoryMutation, useInventoryOptions, useInventoryQuery, useUnsavedChanges };
|