@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.
Files changed (70) hide show
  1. package/build/lowcode/assets-daily.json +11 -11
  2. package/build/lowcode/assets-dev.json +2 -2
  3. package/build/lowcode/assets-prod.json +11 -11
  4. package/build/lowcode/meta.js +1 -1
  5. package/build/lowcode/render/default/view.css +1 -1
  6. package/build/lowcode/render/default/view.js +14 -14
  7. package/build/lowcode/view.css +1 -1
  8. package/build/lowcode/view.js +14 -14
  9. package/es/index.d.ts +7 -1
  10. package/es/index.js +5 -1
  11. package/es/plus/inventory/BindingModal.js +94 -0
  12. package/es/plus/inventory/InventoryItemManagement.d.ts +7 -0
  13. package/es/plus/inventory/InventoryItemManagement.js +204 -0
  14. package/es/plus/inventory/InventoryLocationManagement.d.ts +7 -0
  15. package/es/plus/inventory/InventoryLocationManagement.js +296 -0
  16. package/es/plus/inventory/InventoryUnitManagement.d.ts +7 -0
  17. package/es/plus/inventory/InventoryUnitManagement.js +144 -0
  18. package/es/plus/inventory/ItemDrawer.js +266 -0
  19. package/es/plus/inventory/RecordDialog.js +141 -0
  20. package/es/plus/inventory/StockList.js +132 -0
  21. package/es/plus/inventory/api.js +66 -0
  22. package/es/plus/inventory/components.js +172 -0
  23. package/es/plus/inventory/context.js +118 -0
  24. package/es/plus/inventory/forms.js +46 -0
  25. package/es/plus/inventory/hooks.js +235 -0
  26. package/es/plus/inventory/index.less +559 -0
  27. package/es/plus/inventory/locales.js +277 -0
  28. package/es/plus/inventory/types.d.ts +10 -0
  29. package/es/plus/inventory/utils.js +24 -0
  30. package/es/plus/pisellSupersetDashboard/README.md +291 -0
  31. package/es/plus/pisellSupersetDashboard/index.d.ts +15 -0
  32. package/es/plus/pisellSupersetDashboard/index.js +187 -0
  33. package/es/plus/pisellSupersetDashboard/index.less +83 -0
  34. package/es/plus/pisellSupersetDashboard/locales.js +36 -0
  35. package/es/plus/pisellSupersetDashboard/serve.js +51 -0
  36. package/es/plus/pisellSupersetDashboard/types.d.ts +17 -0
  37. package/es/plus/skuOptionsSelection/store/createStore.js +2 -2
  38. package/lib/index.d.ts +7 -1
  39. package/lib/index.js +134 -126
  40. package/lib/plus/inventory/BindingModal.js +96 -0
  41. package/lib/plus/inventory/InventoryItemManagement.d.ts +7 -0
  42. package/lib/plus/inventory/InventoryItemManagement.js +206 -0
  43. package/lib/plus/inventory/InventoryLocationManagement.d.ts +7 -0
  44. package/lib/plus/inventory/InventoryLocationManagement.js +298 -0
  45. package/lib/plus/inventory/InventoryUnitManagement.d.ts +7 -0
  46. package/lib/plus/inventory/InventoryUnitManagement.js +146 -0
  47. package/lib/plus/inventory/ItemDrawer.js +268 -0
  48. package/lib/plus/inventory/RecordDialog.js +143 -0
  49. package/lib/plus/inventory/StockList.js +134 -0
  50. package/lib/plus/inventory/api.js +66 -0
  51. package/lib/plus/inventory/components.js +181 -0
  52. package/lib/plus/inventory/context.js +121 -0
  53. package/lib/plus/inventory/forms.js +50 -0
  54. package/lib/plus/inventory/hooks.js +240 -0
  55. package/lib/plus/inventory/index.less +559 -0
  56. package/lib/plus/inventory/locales.js +277 -0
  57. package/lib/plus/inventory/types.d.ts +10 -0
  58. package/lib/plus/inventory/utils.js +30 -0
  59. package/lib/plus/pisellSupersetDashboard/README.md +291 -0
  60. package/lib/plus/pisellSupersetDashboard/index.d.ts +15 -0
  61. package/lib/plus/pisellSupersetDashboard/index.js +189 -0
  62. package/lib/plus/pisellSupersetDashboard/index.less +83 -0
  63. package/lib/plus/pisellSupersetDashboard/locales.js +36 -0
  64. package/lib/plus/pisellSupersetDashboard/serve.js +52 -0
  65. package/lib/plus/pisellSupersetDashboard/types.d.ts +17 -0
  66. package/lowcode/inventory-item-management/meta.ts +20 -0
  67. package/lowcode/inventory-location-management/meta.ts +20 -0
  68. package/lowcode/inventory-unit-management/meta.ts +20 -0
  69. package/lowcode/pisell-superset-dashboard/meta.ts +75 -0
  70. 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 };