@vuu-ui/vuu-utils 2.0.0 → 2.1.0-alpha.1
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/cjs/packages/vuu-utils/src/data-editing/DataEditingProvider.js +25 -0
- package/cjs/packages/vuu-utils/src/data-editing/DataEditingProvider.js.map +1 -0
- package/cjs/packages/vuu-utils/src/data-editing/EditTracker.js +154 -0
- package/cjs/packages/vuu-utils/src/data-editing/EditTracker.js.map +1 -0
- package/cjs/packages/vuu-utils/src/data-editing/useEditableTable.js +69 -0
- package/cjs/packages/vuu-utils/src/data-editing/useEditableTable.js.map +1 -0
- package/cjs/packages/vuu-utils/src/index.js +7 -0
- package/cjs/packages/vuu-utils/src/index.js.map +1 -1
- package/esm/packages/vuu-utils/src/data-editing/DataEditingProvider.js +22 -0
- package/esm/packages/vuu-utils/src/data-editing/DataEditingProvider.js.map +1 -0
- package/esm/packages/vuu-utils/src/data-editing/EditTracker.js +152 -0
- package/esm/packages/vuu-utils/src/data-editing/EditTracker.js.map +1 -0
- package/esm/packages/vuu-utils/src/data-editing/useEditableTable.js +67 -0
- package/esm/packages/vuu-utils/src/data-editing/useEditableTable.js.map +1 -0
- package/esm/packages/vuu-utils/src/index.js +3 -0
- package/esm/packages/vuu-utils/src/index.js.map +1 -1
- package/package.json +6 -6
- package/types/data-editing/DataEditingProvider.d.ts +7 -0
- package/types/data-editing/EditButtons.d.ts +7 -0
- package/types/data-editing/EditTracker.d.ts +24 -0
- package/types/data-editing/useEditableTable.d.ts +15 -0
- package/types/index.d.ts +4 -1
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
+
var React = require('react');
|
|
5
|
+
|
|
6
|
+
const DataEditingContext = React.createContext(void 0);
|
|
7
|
+
const DataEditingProvider = ({
|
|
8
|
+
children,
|
|
9
|
+
editTracker
|
|
10
|
+
}) => {
|
|
11
|
+
return /* @__PURE__ */ jsxRuntime.jsx(DataEditingContext.Provider, { value: editTracker, children });
|
|
12
|
+
};
|
|
13
|
+
const useEditTracker = () => {
|
|
14
|
+
const editTracker = React.useContext(DataEditingContext);
|
|
15
|
+
if (editTracker === void 0) {
|
|
16
|
+
console.warn(
|
|
17
|
+
"[useEditTracker] no DataEditingContext in scope. You need to enclose editable component(s) with DataEditingProvider"
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
return editTracker;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
exports.DataEditingProvider = DataEditingProvider;
|
|
24
|
+
exports.useEditTracker = useEditTracker;
|
|
25
|
+
//# sourceMappingURL=DataEditingProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DataEditingProvider.js","sources":["../../../../../../../packages/vuu-utils/src/data-editing/DataEditingProvider.tsx"],"sourcesContent":["import { createContext, ReactNode, useContext } from \"react\";\nimport { EditTracker } from \"./EditTracker\";\n\nconst DataEditingContext = createContext<EditTracker | undefined>(undefined);\n\nexport const DataEditingProvider = ({\n children,\n editTracker,\n}: {\n children: ReactNode;\n editTracker: EditTracker;\n}) => {\n return (\n <DataEditingContext.Provider value={editTracker}>\n {children}\n </DataEditingContext.Provider>\n );\n};\n\nexport const useEditTracker = () => {\n const editTracker = useContext(DataEditingContext);\n if (editTracker === undefined) {\n console.warn(\n \"[useEditTracker] no DataEditingContext in scope. You need to enclose editable component(s) with DataEditingProvider\",\n );\n }\n return editTracker;\n};\n"],"names":["createContext","useContext"],"mappings":";;;;;AAGA,MAAM,kBAAA,GAAqBA,oBAAuC,KAAS,CAAA,CAAA;AAEpE,MAAM,sBAAsB,CAAC;AAAA,EAClC,QAAA;AAAA,EACA;AACF,CAGM,KAAA;AACJ,EAAA,sCACG,kBAAmB,CAAA,QAAA,EAAnB,EAA4B,KAAA,EAAO,aACjC,QACH,EAAA,CAAA;AAEJ;AAEO,MAAM,iBAAiB,MAAM;AAClC,EAAM,MAAA,WAAA,GAAcC,iBAAW,kBAAkB,CAAA;AACjD,EAAA,IAAI,gBAAgB,KAAW,CAAA,EAAA;AAC7B,IAAQ,OAAA,CAAA,IAAA;AAAA,MACN;AAAA,KACF;AAAA;AAEF,EAAO,OAAA,WAAA;AACT;;;;;"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var eventEmitter = require('../event-emitter.js');
|
|
4
|
+
var protocolMessageUtils = require('../protocol-message-utils.js');
|
|
5
|
+
|
|
6
|
+
var __typeError = (msg) => {
|
|
7
|
+
throw TypeError(msg);
|
|
8
|
+
};
|
|
9
|
+
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
10
|
+
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
11
|
+
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
12
|
+
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), member.set(obj, value), value);
|
|
13
|
+
var _active, _rowEdits, _editCount, _dataSource, _inEditMode;
|
|
14
|
+
class EditTracker extends eventEmitter.EventEmitter {
|
|
15
|
+
constructor() {
|
|
16
|
+
super(...arguments);
|
|
17
|
+
__privateAdd(this, _active, false);
|
|
18
|
+
/**
|
|
19
|
+
* Row key => row edits
|
|
20
|
+
*/
|
|
21
|
+
__privateAdd(this, _rowEdits, /* @__PURE__ */ new Map());
|
|
22
|
+
__privateAdd(this, _editCount, 0);
|
|
23
|
+
__privateAdd(this, _dataSource);
|
|
24
|
+
__privateAdd(this, _inEditMode, false);
|
|
25
|
+
}
|
|
26
|
+
get active() {
|
|
27
|
+
return __privateGet(this, _active);
|
|
28
|
+
}
|
|
29
|
+
set active(isActive) {
|
|
30
|
+
__privateSet(this, _active, isActive);
|
|
31
|
+
}
|
|
32
|
+
get editCount() {
|
|
33
|
+
return __privateGet(this, _editCount);
|
|
34
|
+
}
|
|
35
|
+
set editCount(val) {
|
|
36
|
+
if (val !== __privateGet(this, _editCount)) {
|
|
37
|
+
const oldCount = __privateGet(this, _editCount);
|
|
38
|
+
__privateSet(this, _editCount, val);
|
|
39
|
+
if (val === 0) {
|
|
40
|
+
this.emit("editState", "clean");
|
|
41
|
+
} else if (oldCount === 0) {
|
|
42
|
+
this.emit("editState", "dirty");
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
set dataSource(ds) {
|
|
47
|
+
__privateSet(this, _dataSource, ds);
|
|
48
|
+
}
|
|
49
|
+
clear() {
|
|
50
|
+
__privateGet(this, _rowEdits).clear();
|
|
51
|
+
__privateSet(this, _editCount, 0);
|
|
52
|
+
}
|
|
53
|
+
async enterEditMode() {
|
|
54
|
+
__privateSet(this, _inEditMode, true);
|
|
55
|
+
const rpcResponse = await __privateGet(this, _dataSource)?.rpcRequest?.({
|
|
56
|
+
type: "RPC_REQUEST",
|
|
57
|
+
rpcName: "ENTER_EDIT_MODE",
|
|
58
|
+
params: {}
|
|
59
|
+
});
|
|
60
|
+
if (protocolMessageUtils.isRpcSuccess(rpcResponse)) {
|
|
61
|
+
const { table: sessionTable } = rpcResponse.data;
|
|
62
|
+
return sessionTable;
|
|
63
|
+
} else {
|
|
64
|
+
console.log("fail");
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
get inEditMode() {
|
|
68
|
+
return __privateGet(this, _inEditMode);
|
|
69
|
+
}
|
|
70
|
+
get editState() {
|
|
71
|
+
return this.editCount === 0 ? "clean" : "dirty";
|
|
72
|
+
}
|
|
73
|
+
async cancelChanges() {
|
|
74
|
+
const rpcResponse = await __privateGet(this, _dataSource)?.rpcRequest?.({
|
|
75
|
+
type: "RPC_REQUEST",
|
|
76
|
+
rpcName: "EXIT_EDIT_MODE",
|
|
77
|
+
params: {}
|
|
78
|
+
});
|
|
79
|
+
this.clear();
|
|
80
|
+
return rpcResponse;
|
|
81
|
+
}
|
|
82
|
+
async saveChanges() {
|
|
83
|
+
const rpcResponse = await __privateGet(this, _dataSource)?.rpcRequest?.({
|
|
84
|
+
type: "RPC_REQUEST",
|
|
85
|
+
rpcName: "EXIT_EDIT_MODE",
|
|
86
|
+
params: { save: true }
|
|
87
|
+
});
|
|
88
|
+
this.clear();
|
|
89
|
+
return rpcResponse;
|
|
90
|
+
}
|
|
91
|
+
// TODO how do we deal with the '_edited' pattern
|
|
92
|
+
edit(key, columnName, originalValue, newValue) {
|
|
93
|
+
const rowEditDetails = __privateGet(this, _rowEdits).get(key);
|
|
94
|
+
if (rowEditDetails) {
|
|
95
|
+
const { cellEdits } = rowEditDetails;
|
|
96
|
+
const cellEdit = cellEdits.get(columnName);
|
|
97
|
+
if (cellEdit) {
|
|
98
|
+
if (newValue === cellEdit.originalValue) {
|
|
99
|
+
if (cellEdits.size === 1) {
|
|
100
|
+
__privateGet(this, _rowEdits).delete(key);
|
|
101
|
+
} else {
|
|
102
|
+
cellEdits.delete(columnName);
|
|
103
|
+
}
|
|
104
|
+
this.editCount = __privateGet(this, _editCount) - 1;
|
|
105
|
+
} else {
|
|
106
|
+
cellEdit.editedValue = newValue;
|
|
107
|
+
}
|
|
108
|
+
} else {
|
|
109
|
+
cellEdits.set(columnName, {
|
|
110
|
+
originalValue,
|
|
111
|
+
editedValue: newValue
|
|
112
|
+
});
|
|
113
|
+
this.editCount = __privateGet(this, _editCount) + 1;
|
|
114
|
+
}
|
|
115
|
+
} else {
|
|
116
|
+
__privateGet(this, _rowEdits).set(key, {
|
|
117
|
+
cellEdits: /* @__PURE__ */ new Map([
|
|
118
|
+
[columnName, { originalValue, editedValue: newValue }]
|
|
119
|
+
])
|
|
120
|
+
});
|
|
121
|
+
this.editCount = __privateGet(this, _editCount) + 1;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
async commit(key, columnName) {
|
|
125
|
+
const rowEditDetails = __privateGet(this, _rowEdits).get(key);
|
|
126
|
+
if (rowEditDetails) {
|
|
127
|
+
const { cellEdits } = rowEditDetails;
|
|
128
|
+
const cellEditValues = cellEdits.get(columnName);
|
|
129
|
+
if (cellEditValues) {
|
|
130
|
+
const { editedValue } = cellEditValues;
|
|
131
|
+
const rpcResponse = await __privateGet(this, _dataSource)?.rpcRequest?.({
|
|
132
|
+
type: "RPC_REQUEST",
|
|
133
|
+
rpcName: "editCell",
|
|
134
|
+
params: {
|
|
135
|
+
column: `${columnName}`,
|
|
136
|
+
data: editedValue,
|
|
137
|
+
key
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
return rpcResponse;
|
|
141
|
+
}
|
|
142
|
+
} else {
|
|
143
|
+
throw Error(`[EditTracker] commit, key ${key} not found `);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
_active = new WeakMap();
|
|
148
|
+
_rowEdits = new WeakMap();
|
|
149
|
+
_editCount = new WeakMap();
|
|
150
|
+
_dataSource = new WeakMap();
|
|
151
|
+
_inEditMode = new WeakMap();
|
|
152
|
+
|
|
153
|
+
exports.EditTracker = EditTracker;
|
|
154
|
+
//# sourceMappingURL=EditTracker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EditTracker.js","sources":["../../../../../../../packages/vuu-utils/src/data-editing/EditTracker.tsx"],"sourcesContent":["import { DataSource } from \"@vuu-ui/vuu-data-types\";\nimport type { VuuRowDataItemType, VuuTable } from \"@vuu-ui/vuu-protocol-types\";\nimport { EventEmitter } from \"../event-emitter\";\nimport { isRpcSuccess } from \"../protocol-message-utils\";\n\nexport type EditState = \"clean\" | \"dirty\";\n\ntype CellEdit = {\n originalValue: VuuRowDataItemType;\n editedValue: VuuRowDataItemType;\n};\n\ntype RowEditDetails = {\n /**\n * Column name => cell edit details\n */\n cellEdits: Map<string, CellEdit>;\n};\n\ntype EditTrackerEvents = {\n editState: (editState: EditState) => void;\n};\n\nexport class EditTracker extends EventEmitter<EditTrackerEvents> {\n #active = false;\n /**\n * Row key => row edits\n */\n #rowEdits = new Map<string, RowEditDetails>();\n #editCount = 0;\n #dataSource?: DataSource;\n #inEditMode = false;\n\n get active() {\n return this.#active;\n }\n set active(isActive: boolean) {\n this.#active = isActive;\n }\n get editCount() {\n return this.#editCount;\n }\n\n set editCount(val: number) {\n if (val !== this.#editCount) {\n const oldCount = this.#editCount;\n this.#editCount = val;\n if (val === 0) {\n this.emit(\"editState\", \"clean\");\n } else if (oldCount === 0) {\n this.emit(\"editState\", \"dirty\");\n }\n }\n }\n\n set dataSource(ds: DataSource) {\n this.#dataSource = ds;\n }\n\n clear() {\n this.#rowEdits.clear();\n this.#editCount = 0;\n }\n\n async enterEditMode() {\n this.#inEditMode = true;\n\n const rpcResponse = await this.#dataSource?.rpcRequest?.({\n type: \"RPC_REQUEST\",\n rpcName: \"ENTER_EDIT_MODE\",\n params: {},\n });\n\n if (isRpcSuccess(rpcResponse)) {\n const { table: sessionTable } = rpcResponse.data as { table: VuuTable };\n return sessionTable;\n } else {\n console.log(\"fail\");\n }\n }\n\n get inEditMode() {\n return this.#inEditMode;\n }\n\n get editState(): EditState {\n return this.editCount === 0 ? \"clean\" : \"dirty\";\n }\n\n async cancelChanges() {\n const rpcResponse = await this.#dataSource?.rpcRequest?.({\n type: \"RPC_REQUEST\",\n rpcName: \"EXIT_EDIT_MODE\",\n params: {},\n });\n this.clear();\n return rpcResponse;\n }\n\n async saveChanges() {\n const rpcResponse = await this.#dataSource?.rpcRequest?.({\n type: \"RPC_REQUEST\",\n rpcName: \"EXIT_EDIT_MODE\",\n params: { save: true },\n });\n this.clear();\n return rpcResponse;\n }\n\n // TODO how do we deal with the '_edited' pattern\n edit(\n key: string,\n columnName: string,\n originalValue: VuuRowDataItemType,\n newValue: VuuRowDataItemType,\n ) {\n const rowEditDetails = this.#rowEdits.get(key);\n if (rowEditDetails) {\n const { cellEdits } = rowEditDetails;\n const cellEdit = cellEdits.get(columnName);\n if (cellEdit) {\n if (newValue === cellEdit.originalValue) {\n if (cellEdits.size === 1) {\n this.#rowEdits.delete(key);\n } else {\n // re-editing a cell had removed the edit\n cellEdits.delete(columnName);\n }\n this.editCount = this.#editCount - 1;\n } else {\n cellEdit.editedValue = newValue;\n }\n } else {\n // row has already been edited, but this column has not\n cellEdits.set(columnName, {\n originalValue,\n editedValue: newValue,\n });\n this.editCount = this.#editCount + 1;\n }\n } else {\n this.#rowEdits.set(key, {\n cellEdits: new Map([\n [columnName, { originalValue, editedValue: newValue }],\n ]),\n });\n this.editCount = this.#editCount + 1;\n }\n }\n\n async commit(key: string, columnName: string) {\n const rowEditDetails = this.#rowEdits.get(key);\n if (rowEditDetails) {\n const { cellEdits } = rowEditDetails;\n const cellEditValues = cellEdits.get(columnName);\n if (cellEditValues) {\n const { editedValue } = cellEditValues;\n const rpcResponse = await this.#dataSource?.rpcRequest?.({\n type: \"RPC_REQUEST\",\n rpcName: \"editCell\",\n params: {\n column: `${columnName}`,\n data: editedValue,\n key,\n },\n });\n\n return rpcResponse;\n }\n } else {\n throw Error(`[EditTracker] commit, key ${key} not found `);\n }\n }\n}\n"],"names":["EventEmitter","isRpcSuccess"],"mappings":";;;;;;;;;;;;AAAA,IAAA,OAAA,EAAA,SAAA,EAAA,UAAA,EAAA,WAAA,EAAA,WAAA;AAuBO,MAAM,oBAAoBA,yBAAgC,CAAA;AAAA,EAA1D,WAAA,GAAA;AAAA,IAAA,KAAA,CAAA,GAAA,SAAA,CAAA;AACL,IAAU,YAAA,CAAA,IAAA,EAAA,OAAA,EAAA,KAAA,CAAA;AAIV;AAAA;AAAA;AAAA,IAAA,YAAA,CAAA,IAAA,EAAA,SAAA,sBAAgB,GAA4B,EAAA,CAAA;AAC5C,IAAa,YAAA,CAAA,IAAA,EAAA,UAAA,EAAA,CAAA,CAAA;AACb,IAAA,YAAA,CAAA,IAAA,EAAA,WAAA,CAAA;AACA,IAAc,YAAA,CAAA,IAAA,EAAA,WAAA,EAAA,KAAA,CAAA;AAAA;AAAA,EAEd,IAAI,MAAS,GAAA;AACX,IAAA,OAAO,YAAK,CAAA,IAAA,EAAA,OAAA,CAAA;AAAA;AACd,EACA,IAAI,OAAO,QAAmB,EAAA;AAC5B,IAAA,YAAA,CAAA,IAAA,EAAK,OAAU,EAAA,QAAA,CAAA;AAAA;AACjB,EACA,IAAI,SAAY,GAAA;AACd,IAAA,OAAO,YAAK,CAAA,IAAA,EAAA,UAAA,CAAA;AAAA;AACd,EAEA,IAAI,UAAU,GAAa,EAAA;AACzB,IAAI,IAAA,GAAA,KAAQ,mBAAK,UAAY,CAAA,EAAA;AAC3B,MAAA,MAAM,WAAW,YAAK,CAAA,IAAA,EAAA,UAAA,CAAA;AACtB,MAAA,YAAA,CAAA,IAAA,EAAK,UAAa,EAAA,GAAA,CAAA;AAClB,MAAA,IAAI,QAAQ,CAAG,EAAA;AACb,QAAK,IAAA,CAAA,IAAA,CAAK,aAAa,OAAO,CAAA;AAAA,OAChC,MAAA,IAAW,aAAa,CAAG,EAAA;AACzB,QAAK,IAAA,CAAA,IAAA,CAAK,aAAa,OAAO,CAAA;AAAA;AAChC;AACF;AACF,EAEA,IAAI,WAAW,EAAgB,EAAA;AAC7B,IAAA,YAAA,CAAA,IAAA,EAAK,WAAc,EAAA,EAAA,CAAA;AAAA;AACrB,EAEA,KAAQ,GAAA;AACN,IAAA,YAAA,CAAA,IAAA,EAAK,WAAU,KAAM,EAAA;AACrB,IAAA,YAAA,CAAA,IAAA,EAAK,UAAa,EAAA,CAAA,CAAA;AAAA;AACpB,EAEA,MAAM,aAAgB,GAAA;AACpB,IAAA,YAAA,CAAA,IAAA,EAAK,WAAc,EAAA,IAAA,CAAA;AAEnB,IAAA,MAAM,WAAc,GAAA,MAAM,YAAK,CAAA,IAAA,EAAA,WAAA,CAAA,EAAa,UAAa,GAAA;AAAA,MACvD,IAAM,EAAA,aAAA;AAAA,MACN,OAAS,EAAA,iBAAA;AAAA,MACT,QAAQ;AAAC,KACV,CAAA;AAED,IAAI,IAAAC,iCAAA,CAAa,WAAW,CAAG,EAAA;AAC7B,MAAA,MAAM,EAAE,KAAA,EAAO,YAAa,EAAA,GAAI,WAAY,CAAA,IAAA;AAC5C,MAAO,OAAA,YAAA;AAAA,KACF,MAAA;AACL,MAAA,OAAA,CAAQ,IAAI,MAAM,CAAA;AAAA;AACpB;AACF,EAEA,IAAI,UAAa,GAAA;AACf,IAAA,OAAO,YAAK,CAAA,IAAA,EAAA,WAAA,CAAA;AAAA;AACd,EAEA,IAAI,SAAuB,GAAA;AACzB,IAAO,OAAA,IAAA,CAAK,SAAc,KAAA,CAAA,GAAI,OAAU,GAAA,OAAA;AAAA;AAC1C,EAEA,MAAM,aAAgB,GAAA;AACpB,IAAA,MAAM,WAAc,GAAA,MAAM,YAAK,CAAA,IAAA,EAAA,WAAA,CAAA,EAAa,UAAa,GAAA;AAAA,MACvD,IAAM,EAAA,aAAA;AAAA,MACN,OAAS,EAAA,gBAAA;AAAA,MACT,QAAQ;AAAC,KACV,CAAA;AACD,IAAA,IAAA,CAAK,KAAM,EAAA;AACX,IAAO,OAAA,WAAA;AAAA;AACT,EAEA,MAAM,WAAc,GAAA;AAClB,IAAA,MAAM,WAAc,GAAA,MAAM,YAAK,CAAA,IAAA,EAAA,WAAA,CAAA,EAAa,UAAa,GAAA;AAAA,MACvD,IAAM,EAAA,aAAA;AAAA,MACN,OAAS,EAAA,gBAAA;AAAA,MACT,MAAA,EAAQ,EAAE,IAAA,EAAM,IAAK;AAAA,KACtB,CAAA;AACD,IAAA,IAAA,CAAK,KAAM,EAAA;AACX,IAAO,OAAA,WAAA;AAAA;AACT;AAAA,EAGA,IACE,CAAA,GAAA,EACA,UACA,EAAA,aAAA,EACA,QACA,EAAA;AACA,IAAA,MAAM,cAAiB,GAAA,YAAA,CAAA,IAAA,EAAK,SAAU,CAAA,CAAA,GAAA,CAAI,GAAG,CAAA;AAC7C,IAAA,IAAI,cAAgB,EAAA;AAClB,MAAM,MAAA,EAAE,WAAc,GAAA,cAAA;AACtB,MAAM,MAAA,QAAA,GAAW,SAAU,CAAA,GAAA,CAAI,UAAU,CAAA;AACzC,MAAA,IAAI,QAAU,EAAA;AACZ,QAAI,IAAA,QAAA,KAAa,SAAS,aAAe,EAAA;AACvC,UAAI,IAAA,SAAA,CAAU,SAAS,CAAG,EAAA;AACxB,YAAK,YAAA,CAAA,IAAA,EAAA,SAAA,CAAA,CAAU,OAAO,GAAG,CAAA;AAAA,WACpB,MAAA;AAEL,YAAA,SAAA,CAAU,OAAO,UAAU,CAAA;AAAA;AAE7B,UAAK,IAAA,CAAA,SAAA,GAAY,mBAAK,UAAa,CAAA,GAAA,CAAA;AAAA,SAC9B,MAAA;AACL,UAAA,QAAA,CAAS,WAAc,GAAA,QAAA;AAAA;AACzB,OACK,MAAA;AAEL,QAAA,SAAA,CAAU,IAAI,UAAY,EAAA;AAAA,UACxB,aAAA;AAAA,UACA,WAAa,EAAA;AAAA,SACd,CAAA;AACD,QAAK,IAAA,CAAA,SAAA,GAAY,mBAAK,UAAa,CAAA,GAAA,CAAA;AAAA;AACrC,KACK,MAAA;AACL,MAAK,YAAA,CAAA,IAAA,EAAA,SAAA,CAAA,CAAU,IAAI,GAAK,EAAA;AAAA,QACtB,SAAA,sBAAe,GAAI,CAAA;AAAA,UACjB,CAAC,UAAY,EAAA,EAAE,aAAe,EAAA,WAAA,EAAa,UAAU;AAAA,SACtD;AAAA,OACF,CAAA;AACD,MAAK,IAAA,CAAA,SAAA,GAAY,mBAAK,UAAa,CAAA,GAAA,CAAA;AAAA;AACrC;AACF,EAEA,MAAM,MAAO,CAAA,GAAA,EAAa,UAAoB,EAAA;AAC5C,IAAA,MAAM,cAAiB,GAAA,YAAA,CAAA,IAAA,EAAK,SAAU,CAAA,CAAA,GAAA,CAAI,GAAG,CAAA;AAC7C,IAAA,IAAI,cAAgB,EAAA;AAClB,MAAM,MAAA,EAAE,WAAc,GAAA,cAAA;AACtB,MAAM,MAAA,cAAA,GAAiB,SAAU,CAAA,GAAA,CAAI,UAAU,CAAA;AAC/C,MAAA,IAAI,cAAgB,EAAA;AAClB,QAAM,MAAA,EAAE,aAAgB,GAAA,cAAA;AACxB,QAAA,MAAM,WAAc,GAAA,MAAM,YAAK,CAAA,IAAA,EAAA,WAAA,CAAA,EAAa,UAAa,GAAA;AAAA,UACvD,IAAM,EAAA,aAAA;AAAA,UACN,OAAS,EAAA,UAAA;AAAA,UACT,MAAQ,EAAA;AAAA,YACN,MAAA,EAAQ,GAAG,UAAU,CAAA,CAAA;AAAA,YACrB,IAAM,EAAA,WAAA;AAAA,YACN;AAAA;AACF,SACD,CAAA;AAED,QAAO,OAAA,WAAA;AAAA;AACT,KACK,MAAA;AACL,MAAM,MAAA,KAAA,CAAM,CAA6B,0BAAA,EAAA,GAAG,CAAa,WAAA,CAAA,CAAA;AAAA;AAC3D;AAEJ;AArJE,OAAA,GAAA,IAAA,OAAA,EAAA;AAIA,SAAA,GAAA,IAAA,OAAA,EAAA;AACA,UAAA,GAAA,IAAA,OAAA,EAAA;AACA,WAAA,GAAA,IAAA,OAAA,EAAA;AACA,WAAA,GAAA,IAAA,OAAA,EAAA;;;;"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var React = require('react');
|
|
4
|
+
var EditTracker = require('./EditTracker.js');
|
|
5
|
+
var DataProvider = require('../context-definitions/DataProvider.js');
|
|
6
|
+
var protocolMessageUtils = require('../protocol-message-utils.js');
|
|
7
|
+
|
|
8
|
+
const useEditableTable = ({ table }) => {
|
|
9
|
+
const { VuuDataSource } = DataProvider.useData();
|
|
10
|
+
const [editMode, setEditMode] = React.useState("view");
|
|
11
|
+
const [sessionDataSource, setSessionDataSource] = React.useState(void 0);
|
|
12
|
+
const dataSource = React.useMemo(() => {
|
|
13
|
+
return new VuuDataSource({ table });
|
|
14
|
+
}, [table, VuuDataSource]);
|
|
15
|
+
const editTracker = React.useMemo(() => new EditTracker.EditTracker(), []);
|
|
16
|
+
React.useMemo(() => {
|
|
17
|
+
if (dataSource) {
|
|
18
|
+
editTracker.dataSource = dataSource;
|
|
19
|
+
}
|
|
20
|
+
}, [dataSource, editTracker]);
|
|
21
|
+
const onCancel = React.useCallback(() => {
|
|
22
|
+
editTracker.dataSource = dataSource;
|
|
23
|
+
editTracker.cancelChanges();
|
|
24
|
+
setEditMode("view");
|
|
25
|
+
setSessionDataSource(void 0);
|
|
26
|
+
dataSource.resume?.();
|
|
27
|
+
}, [dataSource, editTracker]);
|
|
28
|
+
const onSave = React.useCallback(async () => {
|
|
29
|
+
editTracker.dataSource = dataSource;
|
|
30
|
+
const response = await editTracker.saveChanges();
|
|
31
|
+
if (protocolMessageUtils.isRpcSuccess(response)) {
|
|
32
|
+
setEditMode("view");
|
|
33
|
+
setSessionDataSource(void 0);
|
|
34
|
+
dataSource.resume?.();
|
|
35
|
+
}
|
|
36
|
+
}, [dataSource, editTracker]);
|
|
37
|
+
const onToggleEditMode = React.useCallback(
|
|
38
|
+
async (e) => {
|
|
39
|
+
const toggleButton = e.target;
|
|
40
|
+
const editMode2 = toggleButton.value;
|
|
41
|
+
setEditMode(editMode2);
|
|
42
|
+
if (editMode2 === "edit") {
|
|
43
|
+
const sessionTable = await editTracker.enterEditMode();
|
|
44
|
+
if (sessionTable && dataSource.tableSchema) {
|
|
45
|
+
dataSource.suspend?.(false);
|
|
46
|
+
const sessionDataSource2 = new VuuDataSource({
|
|
47
|
+
columns: dataSource.columns,
|
|
48
|
+
table: sessionTable,
|
|
49
|
+
viewport: sessionTable.table
|
|
50
|
+
});
|
|
51
|
+
setSessionDataSource(sessionDataSource2);
|
|
52
|
+
editTracker.dataSource = sessionDataSource2;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
[VuuDataSource, dataSource, editTracker]
|
|
57
|
+
);
|
|
58
|
+
return {
|
|
59
|
+
dataSource: sessionDataSource ?? dataSource,
|
|
60
|
+
editMode,
|
|
61
|
+
editTracker,
|
|
62
|
+
onCancel,
|
|
63
|
+
onSave,
|
|
64
|
+
onToggleEditMode
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
exports.useEditableTable = useEditableTable;
|
|
69
|
+
//# sourceMappingURL=useEditableTable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useEditableTable.js","sources":["../../../../../../../packages/vuu-utils/src/data-editing/useEditableTable.ts"],"sourcesContent":["import { VuuTable } from \"@vuu-ui/vuu-protocol-types\";\nimport { SyntheticEvent, useCallback, useMemo, useState } from \"react\";\nimport { EditTracker } from \"./EditTracker\";\nimport { useData } from \"../context-definitions/DataProvider\";\nimport { DataSource } from \"@vuu-ui/vuu-data-types\";\nimport { isRpcSuccess } from \"../protocol-message-utils\";\n\nexport type EditMode = \"edit\" | \"view\";\n\nexport const useEditableTable = ({ table }: { table: VuuTable }) => {\n const { VuuDataSource } = useData();\n const [editMode, setEditMode] = useState<EditMode>(\"view\");\n const [sessionDataSource, setSessionDataSource] = useState<\n DataSource | undefined\n >(undefined);\n\n const dataSource = useMemo(() => {\n return new VuuDataSource({ table });\n }, [table, VuuDataSource]);\n\n const editTracker = useMemo(() => new EditTracker(), []);\n\n useMemo(() => {\n if (dataSource) {\n editTracker.dataSource = dataSource;\n }\n }, [dataSource, editTracker]);\n\n const onCancel = useCallback(() => {\n editTracker.dataSource = dataSource;\n editTracker.cancelChanges();\n setEditMode(\"view\");\n setSessionDataSource(undefined);\n dataSource.resume?.();\n }, [dataSource, editTracker]);\n\n const onSave = useCallback(async () => {\n editTracker.dataSource = dataSource;\n const response = await editTracker.saveChanges();\n if (isRpcSuccess(response)) {\n setEditMode(\"view\");\n setSessionDataSource(undefined);\n dataSource.resume?.();\n }\n }, [dataSource, editTracker]);\n\n const onToggleEditMode = useCallback(\n async (e: SyntheticEvent<HTMLButtonElement>) => {\n const toggleButton = e.target as HTMLButtonElement;\n const editMode = toggleButton.value as EditMode;\n setEditMode(editMode);\n if (editMode === \"edit\") {\n const sessionTable = await editTracker.enterEditMode();\n if (sessionTable && dataSource.tableSchema) {\n dataSource.suspend?.(false);\n const sessionDataSource = new VuuDataSource({\n columns: dataSource.columns,\n table: sessionTable,\n viewport: sessionTable.table,\n });\n setSessionDataSource(sessionDataSource);\n editTracker.dataSource = sessionDataSource;\n }\n }\n },\n [VuuDataSource, dataSource, editTracker],\n );\n\n return {\n dataSource: sessionDataSource ?? dataSource,\n editMode,\n editTracker,\n onCancel,\n onSave,\n onToggleEditMode,\n };\n};\n"],"names":["useData","useState","useMemo","EditTracker","useCallback","isRpcSuccess","editMode","sessionDataSource"],"mappings":";;;;;;;AASO,MAAM,gBAAmB,GAAA,CAAC,EAAE,KAAA,EAAiC,KAAA;AAClE,EAAM,MAAA,EAAE,aAAc,EAAA,GAAIA,oBAAQ,EAAA;AAClC,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAIC,eAAmB,MAAM,CAAA;AACzD,EAAA,MAAM,CAAC,iBAAA,EAAmB,oBAAoB,CAAA,GAAIA,eAEhD,KAAS,CAAA,CAAA;AAEX,EAAM,MAAA,UAAA,GAAaC,cAAQ,MAAM;AAC/B,IAAA,OAAO,IAAI,aAAA,CAAc,EAAE,KAAA,EAAO,CAAA;AAAA,GACjC,EAAA,CAAC,KAAO,EAAA,aAAa,CAAC,CAAA;AAEzB,EAAA,MAAM,cAAcA,aAAQ,CAAA,MAAM,IAAIC,uBAAY,EAAA,EAAG,EAAE,CAAA;AAEvD,EAAAD,aAAA,CAAQ,MAAM;AACZ,IAAA,IAAI,UAAY,EAAA;AACd,MAAA,WAAA,CAAY,UAAa,GAAA,UAAA;AAAA;AAC3B,GACC,EAAA,CAAC,UAAY,EAAA,WAAW,CAAC,CAAA;AAE5B,EAAM,MAAA,QAAA,GAAWE,kBAAY,MAAM;AACjC,IAAA,WAAA,CAAY,UAAa,GAAA,UAAA;AACzB,IAAA,WAAA,CAAY,aAAc,EAAA;AAC1B,IAAA,WAAA,CAAY,MAAM,CAAA;AAClB,IAAA,oBAAA,CAAqB,KAAS,CAAA,CAAA;AAC9B,IAAA,UAAA,CAAW,MAAS,IAAA;AAAA,GACnB,EAAA,CAAC,UAAY,EAAA,WAAW,CAAC,CAAA;AAE5B,EAAM,MAAA,MAAA,GAASA,kBAAY,YAAY;AACrC,IAAA,WAAA,CAAY,UAAa,GAAA,UAAA;AACzB,IAAM,MAAA,QAAA,GAAW,MAAM,WAAA,CAAY,WAAY,EAAA;AAC/C,IAAI,IAAAC,iCAAA,CAAa,QAAQ,CAAG,EAAA;AAC1B,MAAA,WAAA,CAAY,MAAM,CAAA;AAClB,MAAA,oBAAA,CAAqB,KAAS,CAAA,CAAA;AAC9B,MAAA,UAAA,CAAW,MAAS,IAAA;AAAA;AACtB,GACC,EAAA,CAAC,UAAY,EAAA,WAAW,CAAC,CAAA;AAE5B,EAAA,MAAM,gBAAmB,GAAAD,iBAAA;AAAA,IACvB,OAAO,CAAyC,KAAA;AAC9C,MAAA,MAAM,eAAe,CAAE,CAAA,MAAA;AACvB,MAAA,MAAME,YAAW,YAAa,CAAA,KAAA;AAC9B,MAAA,WAAA,CAAYA,SAAQ,CAAA;AACpB,MAAA,IAAIA,cAAa,MAAQ,EAAA;AACvB,QAAM,MAAA,YAAA,GAAe,MAAM,WAAA,CAAY,aAAc,EAAA;AACrD,QAAI,IAAA,YAAA,IAAgB,WAAW,WAAa,EAAA;AAC1C,UAAA,UAAA,CAAW,UAAU,KAAK,CAAA;AAC1B,UAAMC,MAAAA,kBAAAA,GAAoB,IAAI,aAAc,CAAA;AAAA,YAC1C,SAAS,UAAW,CAAA,OAAA;AAAA,YACpB,KAAO,EAAA,YAAA;AAAA,YACP,UAAU,YAAa,CAAA;AAAA,WACxB,CAAA;AACD,UAAA,oBAAA,CAAqBA,kBAAiB,CAAA;AACtC,UAAA,WAAA,CAAY,UAAaA,GAAAA,kBAAAA;AAAA;AAC3B;AACF,KACF;AAAA,IACA,CAAC,aAAe,EAAA,UAAA,EAAY,WAAW;AAAA,GACzC;AAEA,EAAO,OAAA;AAAA,IACL,YAAY,iBAAqB,IAAA,UAAA;AAAA,IACjC,QAAA;AAAA,IACA,WAAA;AAAA,IACA,QAAA;AAAA,IACA,MAAA;AAAA,IACA;AAAA,GACF;AACF;;;;"}
|
|
@@ -12,6 +12,9 @@ var commonTypes = require('./common-types.js');
|
|
|
12
12
|
var componentRegistry = require('./component-registry.js');
|
|
13
13
|
var cookieUtils = require('./cookie-utils.js');
|
|
14
14
|
var cssUtils = require('./css-utils.js');
|
|
15
|
+
var DataEditingProvider = require('./data-editing/DataEditingProvider.js');
|
|
16
|
+
var EditTracker = require('./data-editing/EditTracker.js');
|
|
17
|
+
var useEditableTable = require('./data-editing/useEditableTable.js');
|
|
15
18
|
var dataUtils = require('./data-utils.js');
|
|
16
19
|
var BaseDataSource = require('./datasource/BaseDataSource.js');
|
|
17
20
|
var datasourceActionUtils = require('./datasource/datasource-action-utils.js');
|
|
@@ -198,6 +201,10 @@ exports.registerConfigurationEditor = componentRegistry.registerConfigurationEdi
|
|
|
198
201
|
exports.getCookieValue = cookieUtils.getCookieValue;
|
|
199
202
|
exports.setCookieValue = cookieUtils.setCookieValue;
|
|
200
203
|
exports.importCSS = cssUtils.importCSS;
|
|
204
|
+
exports.DataEditingProvider = DataEditingProvider.DataEditingProvider;
|
|
205
|
+
exports.useEditTracker = DataEditingProvider.useEditTracker;
|
|
206
|
+
exports.EditTracker = EditTracker.EditTracker;
|
|
207
|
+
exports.useEditableTable = useEditableTable.useEditableTable;
|
|
201
208
|
exports.DOWN1 = dataUtils.DOWN1;
|
|
202
209
|
exports.DOWN2 = dataUtils.DOWN2;
|
|
203
210
|
exports.UP1 = dataUtils.UP1;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { createContext, useContext } from 'react';
|
|
3
|
+
|
|
4
|
+
const DataEditingContext = createContext(void 0);
|
|
5
|
+
const DataEditingProvider = ({
|
|
6
|
+
children,
|
|
7
|
+
editTracker
|
|
8
|
+
}) => {
|
|
9
|
+
return /* @__PURE__ */ jsx(DataEditingContext.Provider, { value: editTracker, children });
|
|
10
|
+
};
|
|
11
|
+
const useEditTracker = () => {
|
|
12
|
+
const editTracker = useContext(DataEditingContext);
|
|
13
|
+
if (editTracker === void 0) {
|
|
14
|
+
console.warn(
|
|
15
|
+
"[useEditTracker] no DataEditingContext in scope. You need to enclose editable component(s) with DataEditingProvider"
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
return editTracker;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export { DataEditingProvider, useEditTracker };
|
|
22
|
+
//# sourceMappingURL=DataEditingProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DataEditingProvider.js","sources":["../../../../../../../packages/vuu-utils/src/data-editing/DataEditingProvider.tsx"],"sourcesContent":["import { createContext, ReactNode, useContext } from \"react\";\nimport { EditTracker } from \"./EditTracker\";\n\nconst DataEditingContext = createContext<EditTracker | undefined>(undefined);\n\nexport const DataEditingProvider = ({\n children,\n editTracker,\n}: {\n children: ReactNode;\n editTracker: EditTracker;\n}) => {\n return (\n <DataEditingContext.Provider value={editTracker}>\n {children}\n </DataEditingContext.Provider>\n );\n};\n\nexport const useEditTracker = () => {\n const editTracker = useContext(DataEditingContext);\n if (editTracker === undefined) {\n console.warn(\n \"[useEditTracker] no DataEditingContext in scope. You need to enclose editable component(s) with DataEditingProvider\",\n );\n }\n return editTracker;\n};\n"],"names":[],"mappings":";;;AAGA,MAAM,kBAAA,GAAqB,cAAuC,KAAS,CAAA,CAAA;AAEpE,MAAM,sBAAsB,CAAC;AAAA,EAClC,QAAA;AAAA,EACA;AACF,CAGM,KAAA;AACJ,EAAA,2BACG,kBAAmB,CAAA,QAAA,EAAnB,EAA4B,KAAA,EAAO,aACjC,QACH,EAAA,CAAA;AAEJ;AAEO,MAAM,iBAAiB,MAAM;AAClC,EAAM,MAAA,WAAA,GAAc,WAAW,kBAAkB,CAAA;AACjD,EAAA,IAAI,gBAAgB,KAAW,CAAA,EAAA;AAC7B,IAAQ,OAAA,CAAA,IAAA;AAAA,MACN;AAAA,KACF;AAAA;AAEF,EAAO,OAAA,WAAA;AACT;;;;"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { EventEmitter } from '../event-emitter.js';
|
|
2
|
+
import { isRpcSuccess } from '../protocol-message-utils.js';
|
|
3
|
+
|
|
4
|
+
var __typeError = (msg) => {
|
|
5
|
+
throw TypeError(msg);
|
|
6
|
+
};
|
|
7
|
+
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
8
|
+
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
9
|
+
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
10
|
+
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), member.set(obj, value), value);
|
|
11
|
+
var _active, _rowEdits, _editCount, _dataSource, _inEditMode;
|
|
12
|
+
class EditTracker extends EventEmitter {
|
|
13
|
+
constructor() {
|
|
14
|
+
super(...arguments);
|
|
15
|
+
__privateAdd(this, _active, false);
|
|
16
|
+
/**
|
|
17
|
+
* Row key => row edits
|
|
18
|
+
*/
|
|
19
|
+
__privateAdd(this, _rowEdits, /* @__PURE__ */ new Map());
|
|
20
|
+
__privateAdd(this, _editCount, 0);
|
|
21
|
+
__privateAdd(this, _dataSource);
|
|
22
|
+
__privateAdd(this, _inEditMode, false);
|
|
23
|
+
}
|
|
24
|
+
get active() {
|
|
25
|
+
return __privateGet(this, _active);
|
|
26
|
+
}
|
|
27
|
+
set active(isActive) {
|
|
28
|
+
__privateSet(this, _active, isActive);
|
|
29
|
+
}
|
|
30
|
+
get editCount() {
|
|
31
|
+
return __privateGet(this, _editCount);
|
|
32
|
+
}
|
|
33
|
+
set editCount(val) {
|
|
34
|
+
if (val !== __privateGet(this, _editCount)) {
|
|
35
|
+
const oldCount = __privateGet(this, _editCount);
|
|
36
|
+
__privateSet(this, _editCount, val);
|
|
37
|
+
if (val === 0) {
|
|
38
|
+
this.emit("editState", "clean");
|
|
39
|
+
} else if (oldCount === 0) {
|
|
40
|
+
this.emit("editState", "dirty");
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
set dataSource(ds) {
|
|
45
|
+
__privateSet(this, _dataSource, ds);
|
|
46
|
+
}
|
|
47
|
+
clear() {
|
|
48
|
+
__privateGet(this, _rowEdits).clear();
|
|
49
|
+
__privateSet(this, _editCount, 0);
|
|
50
|
+
}
|
|
51
|
+
async enterEditMode() {
|
|
52
|
+
__privateSet(this, _inEditMode, true);
|
|
53
|
+
const rpcResponse = await __privateGet(this, _dataSource)?.rpcRequest?.({
|
|
54
|
+
type: "RPC_REQUEST",
|
|
55
|
+
rpcName: "ENTER_EDIT_MODE",
|
|
56
|
+
params: {}
|
|
57
|
+
});
|
|
58
|
+
if (isRpcSuccess(rpcResponse)) {
|
|
59
|
+
const { table: sessionTable } = rpcResponse.data;
|
|
60
|
+
return sessionTable;
|
|
61
|
+
} else {
|
|
62
|
+
console.log("fail");
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
get inEditMode() {
|
|
66
|
+
return __privateGet(this, _inEditMode);
|
|
67
|
+
}
|
|
68
|
+
get editState() {
|
|
69
|
+
return this.editCount === 0 ? "clean" : "dirty";
|
|
70
|
+
}
|
|
71
|
+
async cancelChanges() {
|
|
72
|
+
const rpcResponse = await __privateGet(this, _dataSource)?.rpcRequest?.({
|
|
73
|
+
type: "RPC_REQUEST",
|
|
74
|
+
rpcName: "EXIT_EDIT_MODE",
|
|
75
|
+
params: {}
|
|
76
|
+
});
|
|
77
|
+
this.clear();
|
|
78
|
+
return rpcResponse;
|
|
79
|
+
}
|
|
80
|
+
async saveChanges() {
|
|
81
|
+
const rpcResponse = await __privateGet(this, _dataSource)?.rpcRequest?.({
|
|
82
|
+
type: "RPC_REQUEST",
|
|
83
|
+
rpcName: "EXIT_EDIT_MODE",
|
|
84
|
+
params: { save: true }
|
|
85
|
+
});
|
|
86
|
+
this.clear();
|
|
87
|
+
return rpcResponse;
|
|
88
|
+
}
|
|
89
|
+
// TODO how do we deal with the '_edited' pattern
|
|
90
|
+
edit(key, columnName, originalValue, newValue) {
|
|
91
|
+
const rowEditDetails = __privateGet(this, _rowEdits).get(key);
|
|
92
|
+
if (rowEditDetails) {
|
|
93
|
+
const { cellEdits } = rowEditDetails;
|
|
94
|
+
const cellEdit = cellEdits.get(columnName);
|
|
95
|
+
if (cellEdit) {
|
|
96
|
+
if (newValue === cellEdit.originalValue) {
|
|
97
|
+
if (cellEdits.size === 1) {
|
|
98
|
+
__privateGet(this, _rowEdits).delete(key);
|
|
99
|
+
} else {
|
|
100
|
+
cellEdits.delete(columnName);
|
|
101
|
+
}
|
|
102
|
+
this.editCount = __privateGet(this, _editCount) - 1;
|
|
103
|
+
} else {
|
|
104
|
+
cellEdit.editedValue = newValue;
|
|
105
|
+
}
|
|
106
|
+
} else {
|
|
107
|
+
cellEdits.set(columnName, {
|
|
108
|
+
originalValue,
|
|
109
|
+
editedValue: newValue
|
|
110
|
+
});
|
|
111
|
+
this.editCount = __privateGet(this, _editCount) + 1;
|
|
112
|
+
}
|
|
113
|
+
} else {
|
|
114
|
+
__privateGet(this, _rowEdits).set(key, {
|
|
115
|
+
cellEdits: /* @__PURE__ */ new Map([
|
|
116
|
+
[columnName, { originalValue, editedValue: newValue }]
|
|
117
|
+
])
|
|
118
|
+
});
|
|
119
|
+
this.editCount = __privateGet(this, _editCount) + 1;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
async commit(key, columnName) {
|
|
123
|
+
const rowEditDetails = __privateGet(this, _rowEdits).get(key);
|
|
124
|
+
if (rowEditDetails) {
|
|
125
|
+
const { cellEdits } = rowEditDetails;
|
|
126
|
+
const cellEditValues = cellEdits.get(columnName);
|
|
127
|
+
if (cellEditValues) {
|
|
128
|
+
const { editedValue } = cellEditValues;
|
|
129
|
+
const rpcResponse = await __privateGet(this, _dataSource)?.rpcRequest?.({
|
|
130
|
+
type: "RPC_REQUEST",
|
|
131
|
+
rpcName: "editCell",
|
|
132
|
+
params: {
|
|
133
|
+
column: `${columnName}`,
|
|
134
|
+
data: editedValue,
|
|
135
|
+
key
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
return rpcResponse;
|
|
139
|
+
}
|
|
140
|
+
} else {
|
|
141
|
+
throw Error(`[EditTracker] commit, key ${key} not found `);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
_active = new WeakMap();
|
|
146
|
+
_rowEdits = new WeakMap();
|
|
147
|
+
_editCount = new WeakMap();
|
|
148
|
+
_dataSource = new WeakMap();
|
|
149
|
+
_inEditMode = new WeakMap();
|
|
150
|
+
|
|
151
|
+
export { EditTracker };
|
|
152
|
+
//# sourceMappingURL=EditTracker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EditTracker.js","sources":["../../../../../../../packages/vuu-utils/src/data-editing/EditTracker.tsx"],"sourcesContent":["import { DataSource } from \"@vuu-ui/vuu-data-types\";\nimport type { VuuRowDataItemType, VuuTable } from \"@vuu-ui/vuu-protocol-types\";\nimport { EventEmitter } from \"../event-emitter\";\nimport { isRpcSuccess } from \"../protocol-message-utils\";\n\nexport type EditState = \"clean\" | \"dirty\";\n\ntype CellEdit = {\n originalValue: VuuRowDataItemType;\n editedValue: VuuRowDataItemType;\n};\n\ntype RowEditDetails = {\n /**\n * Column name => cell edit details\n */\n cellEdits: Map<string, CellEdit>;\n};\n\ntype EditTrackerEvents = {\n editState: (editState: EditState) => void;\n};\n\nexport class EditTracker extends EventEmitter<EditTrackerEvents> {\n #active = false;\n /**\n * Row key => row edits\n */\n #rowEdits = new Map<string, RowEditDetails>();\n #editCount = 0;\n #dataSource?: DataSource;\n #inEditMode = false;\n\n get active() {\n return this.#active;\n }\n set active(isActive: boolean) {\n this.#active = isActive;\n }\n get editCount() {\n return this.#editCount;\n }\n\n set editCount(val: number) {\n if (val !== this.#editCount) {\n const oldCount = this.#editCount;\n this.#editCount = val;\n if (val === 0) {\n this.emit(\"editState\", \"clean\");\n } else if (oldCount === 0) {\n this.emit(\"editState\", \"dirty\");\n }\n }\n }\n\n set dataSource(ds: DataSource) {\n this.#dataSource = ds;\n }\n\n clear() {\n this.#rowEdits.clear();\n this.#editCount = 0;\n }\n\n async enterEditMode() {\n this.#inEditMode = true;\n\n const rpcResponse = await this.#dataSource?.rpcRequest?.({\n type: \"RPC_REQUEST\",\n rpcName: \"ENTER_EDIT_MODE\",\n params: {},\n });\n\n if (isRpcSuccess(rpcResponse)) {\n const { table: sessionTable } = rpcResponse.data as { table: VuuTable };\n return sessionTable;\n } else {\n console.log(\"fail\");\n }\n }\n\n get inEditMode() {\n return this.#inEditMode;\n }\n\n get editState(): EditState {\n return this.editCount === 0 ? \"clean\" : \"dirty\";\n }\n\n async cancelChanges() {\n const rpcResponse = await this.#dataSource?.rpcRequest?.({\n type: \"RPC_REQUEST\",\n rpcName: \"EXIT_EDIT_MODE\",\n params: {},\n });\n this.clear();\n return rpcResponse;\n }\n\n async saveChanges() {\n const rpcResponse = await this.#dataSource?.rpcRequest?.({\n type: \"RPC_REQUEST\",\n rpcName: \"EXIT_EDIT_MODE\",\n params: { save: true },\n });\n this.clear();\n return rpcResponse;\n }\n\n // TODO how do we deal with the '_edited' pattern\n edit(\n key: string,\n columnName: string,\n originalValue: VuuRowDataItemType,\n newValue: VuuRowDataItemType,\n ) {\n const rowEditDetails = this.#rowEdits.get(key);\n if (rowEditDetails) {\n const { cellEdits } = rowEditDetails;\n const cellEdit = cellEdits.get(columnName);\n if (cellEdit) {\n if (newValue === cellEdit.originalValue) {\n if (cellEdits.size === 1) {\n this.#rowEdits.delete(key);\n } else {\n // re-editing a cell had removed the edit\n cellEdits.delete(columnName);\n }\n this.editCount = this.#editCount - 1;\n } else {\n cellEdit.editedValue = newValue;\n }\n } else {\n // row has already been edited, but this column has not\n cellEdits.set(columnName, {\n originalValue,\n editedValue: newValue,\n });\n this.editCount = this.#editCount + 1;\n }\n } else {\n this.#rowEdits.set(key, {\n cellEdits: new Map([\n [columnName, { originalValue, editedValue: newValue }],\n ]),\n });\n this.editCount = this.#editCount + 1;\n }\n }\n\n async commit(key: string, columnName: string) {\n const rowEditDetails = this.#rowEdits.get(key);\n if (rowEditDetails) {\n const { cellEdits } = rowEditDetails;\n const cellEditValues = cellEdits.get(columnName);\n if (cellEditValues) {\n const { editedValue } = cellEditValues;\n const rpcResponse = await this.#dataSource?.rpcRequest?.({\n type: \"RPC_REQUEST\",\n rpcName: \"editCell\",\n params: {\n column: `${columnName}`,\n data: editedValue,\n key,\n },\n });\n\n return rpcResponse;\n }\n } else {\n throw Error(`[EditTracker] commit, key ${key} not found `);\n }\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { useState, useMemo, useCallback } from 'react';
|
|
2
|
+
import { EditTracker } from './EditTracker.js';
|
|
3
|
+
import { useData } from '../context-definitions/DataProvider.js';
|
|
4
|
+
import { isRpcSuccess } from '../protocol-message-utils.js';
|
|
5
|
+
|
|
6
|
+
const useEditableTable = ({ table }) => {
|
|
7
|
+
const { VuuDataSource } = useData();
|
|
8
|
+
const [editMode, setEditMode] = useState("view");
|
|
9
|
+
const [sessionDataSource, setSessionDataSource] = useState(void 0);
|
|
10
|
+
const dataSource = useMemo(() => {
|
|
11
|
+
return new VuuDataSource({ table });
|
|
12
|
+
}, [table, VuuDataSource]);
|
|
13
|
+
const editTracker = useMemo(() => new EditTracker(), []);
|
|
14
|
+
useMemo(() => {
|
|
15
|
+
if (dataSource) {
|
|
16
|
+
editTracker.dataSource = dataSource;
|
|
17
|
+
}
|
|
18
|
+
}, [dataSource, editTracker]);
|
|
19
|
+
const onCancel = useCallback(() => {
|
|
20
|
+
editTracker.dataSource = dataSource;
|
|
21
|
+
editTracker.cancelChanges();
|
|
22
|
+
setEditMode("view");
|
|
23
|
+
setSessionDataSource(void 0);
|
|
24
|
+
dataSource.resume?.();
|
|
25
|
+
}, [dataSource, editTracker]);
|
|
26
|
+
const onSave = useCallback(async () => {
|
|
27
|
+
editTracker.dataSource = dataSource;
|
|
28
|
+
const response = await editTracker.saveChanges();
|
|
29
|
+
if (isRpcSuccess(response)) {
|
|
30
|
+
setEditMode("view");
|
|
31
|
+
setSessionDataSource(void 0);
|
|
32
|
+
dataSource.resume?.();
|
|
33
|
+
}
|
|
34
|
+
}, [dataSource, editTracker]);
|
|
35
|
+
const onToggleEditMode = useCallback(
|
|
36
|
+
async (e) => {
|
|
37
|
+
const toggleButton = e.target;
|
|
38
|
+
const editMode2 = toggleButton.value;
|
|
39
|
+
setEditMode(editMode2);
|
|
40
|
+
if (editMode2 === "edit") {
|
|
41
|
+
const sessionTable = await editTracker.enterEditMode();
|
|
42
|
+
if (sessionTable && dataSource.tableSchema) {
|
|
43
|
+
dataSource.suspend?.(false);
|
|
44
|
+
const sessionDataSource2 = new VuuDataSource({
|
|
45
|
+
columns: dataSource.columns,
|
|
46
|
+
table: sessionTable,
|
|
47
|
+
viewport: sessionTable.table
|
|
48
|
+
});
|
|
49
|
+
setSessionDataSource(sessionDataSource2);
|
|
50
|
+
editTracker.dataSource = sessionDataSource2;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
[VuuDataSource, dataSource, editTracker]
|
|
55
|
+
);
|
|
56
|
+
return {
|
|
57
|
+
dataSource: sessionDataSource ?? dataSource,
|
|
58
|
+
editMode,
|
|
59
|
+
editTracker,
|
|
60
|
+
onCancel,
|
|
61
|
+
onSave,
|
|
62
|
+
onToggleEditMode
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export { useEditableTable };
|
|
67
|
+
//# sourceMappingURL=useEditableTable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useEditableTable.js","sources":["../../../../../../../packages/vuu-utils/src/data-editing/useEditableTable.ts"],"sourcesContent":["import { VuuTable } from \"@vuu-ui/vuu-protocol-types\";\nimport { SyntheticEvent, useCallback, useMemo, useState } from \"react\";\nimport { EditTracker } from \"./EditTracker\";\nimport { useData } from \"../context-definitions/DataProvider\";\nimport { DataSource } from \"@vuu-ui/vuu-data-types\";\nimport { isRpcSuccess } from \"../protocol-message-utils\";\n\nexport type EditMode = \"edit\" | \"view\";\n\nexport const useEditableTable = ({ table }: { table: VuuTable }) => {\n const { VuuDataSource } = useData();\n const [editMode, setEditMode] = useState<EditMode>(\"view\");\n const [sessionDataSource, setSessionDataSource] = useState<\n DataSource | undefined\n >(undefined);\n\n const dataSource = useMemo(() => {\n return new VuuDataSource({ table });\n }, [table, VuuDataSource]);\n\n const editTracker = useMemo(() => new EditTracker(), []);\n\n useMemo(() => {\n if (dataSource) {\n editTracker.dataSource = dataSource;\n }\n }, [dataSource, editTracker]);\n\n const onCancel = useCallback(() => {\n editTracker.dataSource = dataSource;\n editTracker.cancelChanges();\n setEditMode(\"view\");\n setSessionDataSource(undefined);\n dataSource.resume?.();\n }, [dataSource, editTracker]);\n\n const onSave = useCallback(async () => {\n editTracker.dataSource = dataSource;\n const response = await editTracker.saveChanges();\n if (isRpcSuccess(response)) {\n setEditMode(\"view\");\n setSessionDataSource(undefined);\n dataSource.resume?.();\n }\n }, [dataSource, editTracker]);\n\n const onToggleEditMode = useCallback(\n async (e: SyntheticEvent<HTMLButtonElement>) => {\n const toggleButton = e.target as HTMLButtonElement;\n const editMode = toggleButton.value as EditMode;\n setEditMode(editMode);\n if (editMode === \"edit\") {\n const sessionTable = await editTracker.enterEditMode();\n if (sessionTable && dataSource.tableSchema) {\n dataSource.suspend?.(false);\n const sessionDataSource = new VuuDataSource({\n columns: dataSource.columns,\n table: sessionTable,\n viewport: sessionTable.table,\n });\n setSessionDataSource(sessionDataSource);\n editTracker.dataSource = sessionDataSource;\n }\n }\n },\n [VuuDataSource, dataSource, editTracker],\n );\n\n return {\n dataSource: sessionDataSource ?? dataSource,\n editMode,\n editTracker,\n onCancel,\n onSave,\n onToggleEditMode,\n };\n};\n"],"names":["editMode","sessionDataSource"],"mappings":";;;;;AASO,MAAM,gBAAmB,GAAA,CAAC,EAAE,KAAA,EAAiC,KAAA;AAClE,EAAM,MAAA,EAAE,aAAc,EAAA,GAAI,OAAQ,EAAA;AAClC,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAI,SAAmB,MAAM,CAAA;AACzD,EAAA,MAAM,CAAC,iBAAA,EAAmB,oBAAoB,CAAA,GAAI,SAEhD,KAAS,CAAA,CAAA;AAEX,EAAM,MAAA,UAAA,GAAa,QAAQ,MAAM;AAC/B,IAAA,OAAO,IAAI,aAAA,CAAc,EAAE,KAAA,EAAO,CAAA;AAAA,GACjC,EAAA,CAAC,KAAO,EAAA,aAAa,CAAC,CAAA;AAEzB,EAAA,MAAM,cAAc,OAAQ,CAAA,MAAM,IAAI,WAAY,EAAA,EAAG,EAAE,CAAA;AAEvD,EAAA,OAAA,CAAQ,MAAM;AACZ,IAAA,IAAI,UAAY,EAAA;AACd,MAAA,WAAA,CAAY,UAAa,GAAA,UAAA;AAAA;AAC3B,GACC,EAAA,CAAC,UAAY,EAAA,WAAW,CAAC,CAAA;AAE5B,EAAM,MAAA,QAAA,GAAW,YAAY,MAAM;AACjC,IAAA,WAAA,CAAY,UAAa,GAAA,UAAA;AACzB,IAAA,WAAA,CAAY,aAAc,EAAA;AAC1B,IAAA,WAAA,CAAY,MAAM,CAAA;AAClB,IAAA,oBAAA,CAAqB,KAAS,CAAA,CAAA;AAC9B,IAAA,UAAA,CAAW,MAAS,IAAA;AAAA,GACnB,EAAA,CAAC,UAAY,EAAA,WAAW,CAAC,CAAA;AAE5B,EAAM,MAAA,MAAA,GAAS,YAAY,YAAY;AACrC,IAAA,WAAA,CAAY,UAAa,GAAA,UAAA;AACzB,IAAM,MAAA,QAAA,GAAW,MAAM,WAAA,CAAY,WAAY,EAAA;AAC/C,IAAI,IAAA,YAAA,CAAa,QAAQ,CAAG,EAAA;AAC1B,MAAA,WAAA,CAAY,MAAM,CAAA;AAClB,MAAA,oBAAA,CAAqB,KAAS,CAAA,CAAA;AAC9B,MAAA,UAAA,CAAW,MAAS,IAAA;AAAA;AACtB,GACC,EAAA,CAAC,UAAY,EAAA,WAAW,CAAC,CAAA;AAE5B,EAAA,MAAM,gBAAmB,GAAA,WAAA;AAAA,IACvB,OAAO,CAAyC,KAAA;AAC9C,MAAA,MAAM,eAAe,CAAE,CAAA,MAAA;AACvB,MAAA,MAAMA,YAAW,YAAa,CAAA,KAAA;AAC9B,MAAA,WAAA,CAAYA,SAAQ,CAAA;AACpB,MAAA,IAAIA,cAAa,MAAQ,EAAA;AACvB,QAAM,MAAA,YAAA,GAAe,MAAM,WAAA,CAAY,aAAc,EAAA;AACrD,QAAI,IAAA,YAAA,IAAgB,WAAW,WAAa,EAAA;AAC1C,UAAA,UAAA,CAAW,UAAU,KAAK,CAAA;AAC1B,UAAMC,MAAAA,kBAAAA,GAAoB,IAAI,aAAc,CAAA;AAAA,YAC1C,SAAS,UAAW,CAAA,OAAA;AAAA,YACpB,KAAO,EAAA,YAAA;AAAA,YACP,UAAU,YAAa,CAAA;AAAA,WACxB,CAAA;AACD,UAAA,oBAAA,CAAqBA,kBAAiB,CAAA;AACtC,UAAA,WAAA,CAAY,UAAaA,GAAAA,kBAAAA;AAAA;AAC3B;AACF,KACF;AAAA,IACA,CAAC,aAAe,EAAA,UAAA,EAAY,WAAW;AAAA,GACzC;AAEA,EAAO,OAAA;AAAA,IACL,YAAY,iBAAqB,IAAA,UAAA;AAAA,IACjC,QAAA;AAAA,IACA,WAAA;AAAA,IACA,QAAA;AAAA,IACA,MAAA;AAAA,IACA;AAAA,GACF;AACF;;;;"}
|
|
@@ -10,6 +10,9 @@ export { MEASURES } from './common-types.js';
|
|
|
10
10
|
export { getCellConfigPanelRenderer, getCellRenderer, getCellRendererOptions, getColumnHeaderContentRenderer, getColumnHeaderLabelRenderer, getConfigurationEditor, getEditRuleValidator, getLayoutComponent, getRegisteredCellRenderers, getRowClassNameGenerator, isContainer, isLayoutComponent, isView, registerComponent, registerConfigurationEditor } from './component-registry.js';
|
|
11
11
|
export { getCookieValue, setCookieValue } from './cookie-utils.js';
|
|
12
12
|
export { importCSS } from './css-utils.js';
|
|
13
|
+
export { DataEditingProvider, useEditTracker } from './data-editing/DataEditingProvider.js';
|
|
14
|
+
export { EditTracker } from './data-editing/EditTracker.js';
|
|
15
|
+
export { useEditableTable } from './data-editing/useEditableTable.js';
|
|
13
16
|
export { DOWN1, DOWN2, UP1, UP2, asInteger, getMovingValueDirection, isValidNumber, numericTypeOfStringValue, shallowEquals, stringIsValidDecimal, stringIsValidInt, stringIsValidNumber } from './data-utils.js';
|
|
14
17
|
export { BaseDataSource, defaultSuspenseProps } from './datasource/BaseDataSource.js';
|
|
15
18
|
export { isViewportMenusAction, isVisualLinkCreatedAction, isVisualLinkRemovedAction, isVisualLinksAction, isVuuFeatureAction } from './datasource/datasource-action-utils.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/package.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "2.0.
|
|
2
|
+
"version": "2.1.0-alpha.1",
|
|
3
3
|
"author": "heswell",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"types": "types/index.d.ts",
|
|
6
6
|
"devDependencies": {
|
|
7
|
-
"@vuu-ui/vuu-data-types": "2.0.
|
|
8
|
-
"@vuu-ui/vuu-table-types": "2.0.
|
|
9
|
-
"@vuu-ui/vuu-filter-types": "2.0.
|
|
10
|
-
"@vuu-ui/vuu-protocol-types": "2.0.
|
|
7
|
+
"@vuu-ui/vuu-data-types": "2.1.0-alpha.1",
|
|
8
|
+
"@vuu-ui/vuu-table-types": "2.1.0-alpha.1",
|
|
9
|
+
"@vuu-ui/vuu-filter-types": "2.1.0-alpha.1",
|
|
10
|
+
"@vuu-ui/vuu-protocol-types": "2.1.0-alpha.1"
|
|
11
11
|
},
|
|
12
12
|
"peerDependencies": {
|
|
13
13
|
"@internationalized/date": "^3.0.0",
|
|
14
|
-
"@vuu-ui/vuu-filter-parser": "2.0.
|
|
14
|
+
"@vuu-ui/vuu-filter-parser": "2.1.0-alpha.1",
|
|
15
15
|
"clsx": "^2.0.0",
|
|
16
16
|
"react": "^19.2.3",
|
|
17
17
|
"react-dom": "^19.2.3"
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
import { EditTracker } from "./EditTracker";
|
|
3
|
+
export declare const DataEditingProvider: ({ children, editTracker, }: {
|
|
4
|
+
children: ReactNode;
|
|
5
|
+
editTracker: EditTracker;
|
|
6
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
export declare const useEditTracker: () => EditTracker | undefined;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { EditTracker } from "./EditTracker";
|
|
2
|
+
export interface EditButtonProps {
|
|
3
|
+
editTracker?: EditTracker;
|
|
4
|
+
onCancel: () => void;
|
|
5
|
+
onSave: () => void;
|
|
6
|
+
}
|
|
7
|
+
export declare const EditButtons: ({ editTracker, onCancel, onSave, }: EditButtonProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { DataSource } from "@vuu-ui/vuu-data-types";
|
|
2
|
+
import type { VuuRowDataItemType, VuuTable } from "@vuu-ui/vuu-protocol-types";
|
|
3
|
+
import { EventEmitter } from "../event-emitter";
|
|
4
|
+
export type EditState = "clean" | "dirty";
|
|
5
|
+
type EditTrackerEvents = {
|
|
6
|
+
editState: (editState: EditState) => void;
|
|
7
|
+
};
|
|
8
|
+
export declare class EditTracker extends EventEmitter<EditTrackerEvents> {
|
|
9
|
+
#private;
|
|
10
|
+
get active(): boolean;
|
|
11
|
+
set active(isActive: boolean);
|
|
12
|
+
get editCount(): number;
|
|
13
|
+
set editCount(val: number);
|
|
14
|
+
set dataSource(ds: DataSource);
|
|
15
|
+
clear(): void;
|
|
16
|
+
enterEditMode(): Promise<VuuTable | undefined>;
|
|
17
|
+
get inEditMode(): boolean;
|
|
18
|
+
get editState(): EditState;
|
|
19
|
+
cancelChanges(): Promise<import("@vuu-ui/vuu-protocol-types").RpcResultSuccess | import("@vuu-ui/vuu-protocol-types").RpcResultError | undefined>;
|
|
20
|
+
saveChanges(): Promise<import("@vuu-ui/vuu-protocol-types").RpcResultSuccess | import("@vuu-ui/vuu-protocol-types").RpcResultError | undefined>;
|
|
21
|
+
edit(key: string, columnName: string, originalValue: VuuRowDataItemType, newValue: VuuRowDataItemType): void;
|
|
22
|
+
commit(key: string, columnName: string): Promise<import("@vuu-ui/vuu-protocol-types").RpcResultSuccess | import("@vuu-ui/vuu-protocol-types").RpcResultError | undefined>;
|
|
23
|
+
}
|
|
24
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { VuuTable } from "@vuu-ui/vuu-protocol-types";
|
|
2
|
+
import { SyntheticEvent } from "react";
|
|
3
|
+
import { EditTracker } from "./EditTracker";
|
|
4
|
+
import { DataSource } from "@vuu-ui/vuu-data-types";
|
|
5
|
+
export type EditMode = "edit" | "view";
|
|
6
|
+
export declare const useEditableTable: ({ table }: {
|
|
7
|
+
table: VuuTable;
|
|
8
|
+
}) => {
|
|
9
|
+
dataSource: DataSource;
|
|
10
|
+
editMode: EditMode;
|
|
11
|
+
editTracker: EditTracker;
|
|
12
|
+
onCancel: () => void;
|
|
13
|
+
onSave: () => Promise<void>;
|
|
14
|
+
onToggleEditMode: (e: SyntheticEvent<HTMLButtonElement>) => Promise<void>;
|
|
15
|
+
};
|
package/types/index.d.ts
CHANGED
|
@@ -12,6 +12,9 @@ export * from "./common-types";
|
|
|
12
12
|
export * from "./component-registry";
|
|
13
13
|
export * from "./cookie-utils";
|
|
14
14
|
export * from "./css-utils";
|
|
15
|
+
export { DataEditingProvider, useEditTracker, } from "./data-editing/DataEditingProvider";
|
|
16
|
+
export { EditTracker, type EditState } from "./data-editing/EditTracker";
|
|
17
|
+
export { useEditableTable } from "./data-editing/useEditableTable";
|
|
15
18
|
export * from "./data-utils";
|
|
16
19
|
export * from "./datasource/BaseDataSource";
|
|
17
20
|
export * from "./datasource/datasource-action-utils";
|
|
@@ -62,7 +65,7 @@ export * from "./url-utils";
|
|
|
62
65
|
export * from "./useId";
|
|
63
66
|
export * from "./useLayoutEffectSkipFirst";
|
|
64
67
|
export * from "./user-types";
|
|
65
|
-
export { WidthHeight, WidthOnly,
|
|
68
|
+
export { useResizeObserver, WidthHeight, WidthOnly, type measurements, type ResizeHandler, } from "./useResizeObserver";
|
|
66
69
|
export * from "./useStateRef";
|
|
67
70
|
/** Context declarations hosted in utils to minimize intra package dependencies */
|
|
68
71
|
export { DataContext } from "./context-definitions/DataContext";
|