@vuu-ui/vuu-utils 2.1.15 → 2.1.17

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 (45) hide show
  1. package/cjs/packages/vuu-utils/src/data-editing/EditButtons.js +6 -3
  2. package/cjs/packages/vuu-utils/src/data-editing/EditButtons.js.map +1 -1
  3. package/cjs/packages/vuu-utils/src/data-editing/EditSession.js +126 -53
  4. package/cjs/packages/vuu-utils/src/data-editing/EditSession.js.map +1 -1
  5. package/cjs/packages/vuu-utils/src/data-editing/edit-utils.js +32 -1
  6. package/cjs/packages/vuu-utils/src/data-editing/edit-utils.js.map +1 -1
  7. package/cjs/packages/vuu-utils/src/data-editing/useEditableTable.js +17 -9
  8. package/cjs/packages/vuu-utils/src/data-editing/useEditableTable.js.map +1 -1
  9. package/cjs/packages/vuu-utils/src/data-utils.js +7 -7
  10. package/cjs/packages/vuu-utils/src/data-utils.js.map +1 -1
  11. package/cjs/packages/vuu-utils/src/datasource/BaseDataSource.js +0 -1
  12. package/cjs/packages/vuu-utils/src/datasource/BaseDataSource.js.map +1 -1
  13. package/cjs/packages/vuu-utils/src/datasource/datasource-utils.js +2 -0
  14. package/cjs/packages/vuu-utils/src/datasource/datasource-utils.js.map +1 -1
  15. package/cjs/packages/vuu-utils/src/index.js +10 -2
  16. package/cjs/packages/vuu-utils/src/index.js.map +1 -1
  17. package/cjs/packages/vuu-utils/src/protocol-message-utils.js +10 -0
  18. package/cjs/packages/vuu-utils/src/protocol-message-utils.js.map +1 -1
  19. package/esm/packages/vuu-utils/src/data-editing/EditButtons.js +7 -4
  20. package/esm/packages/vuu-utils/src/data-editing/EditButtons.js.map +1 -1
  21. package/esm/packages/vuu-utils/src/data-editing/EditSession.js +126 -54
  22. package/esm/packages/vuu-utils/src/data-editing/EditSession.js.map +1 -1
  23. package/esm/packages/vuu-utils/src/data-editing/edit-utils.js +32 -2
  24. package/esm/packages/vuu-utils/src/data-editing/edit-utils.js.map +1 -1
  25. package/esm/packages/vuu-utils/src/data-editing/useEditableTable.js +17 -9
  26. package/esm/packages/vuu-utils/src/data-editing/useEditableTable.js.map +1 -1
  27. package/esm/packages/vuu-utils/src/data-utils.js +7 -7
  28. package/esm/packages/vuu-utils/src/data-utils.js.map +1 -1
  29. package/esm/packages/vuu-utils/src/datasource/BaseDataSource.js +0 -1
  30. package/esm/packages/vuu-utils/src/datasource/BaseDataSource.js.map +1 -1
  31. package/esm/packages/vuu-utils/src/datasource/datasource-utils.js +2 -1
  32. package/esm/packages/vuu-utils/src/datasource/datasource-utils.js.map +1 -1
  33. package/esm/packages/vuu-utils/src/index.js +4 -4
  34. package/esm/packages/vuu-utils/src/protocol-message-utils.js +6 -1
  35. package/esm/packages/vuu-utils/src/protocol-message-utils.js.map +1 -1
  36. package/package.json +6 -6
  37. package/types/data-editing/EditButtons.d.ts +1 -1
  38. package/types/data-editing/EditSession.d.ts +28 -11
  39. package/types/data-editing/edit-utils.d.ts +2 -0
  40. package/types/data-editing/useEditableTable.d.ts +1 -1
  41. package/types/data-utils.d.ts +12 -1
  42. package/types/datasource/datasource-utils.d.ts +2 -1
  43. package/types/filters/filter-utils.d.ts +2 -1
  44. package/types/index.d.ts +3 -2
  45. package/types/protocol-message-utils.d.ts +6 -1
@@ -10,6 +10,9 @@ const EditButtons = ({
10
10
  onSave
11
11
  }) => {
12
12
  const [editState, setEditState] = React.useState("clean");
13
+ const handleSave = React.useCallback(() => {
14
+ onSave(editState === "stale");
15
+ }, [editState, onSave]);
13
16
  React.useMemo(() => {
14
17
  editSession?.on("editState", setEditState);
15
18
  }, [editSession]);
@@ -17,10 +20,10 @@ const EditButtons = ({
17
20
  /* @__PURE__ */ jsxRuntime.jsx(
18
21
  core.Button,
19
22
  {
20
- disabled: editState === "clean",
21
- onClick: onSave,
23
+ disabled: editState === "clean" || editState === "invalid",
24
+ onClick: handleSave,
22
25
  sentiment: "accented",
23
- children: "Save"
26
+ children: editState === "stale" ? "Save (force)" : "Save"
24
27
  }
25
28
  ),
26
29
  /* @__PURE__ */ jsxRuntime.jsx(core.Button, { onClick: onCancel, children: "Cancel" })
@@ -1 +1 @@
1
- {"version":3,"file":"EditButtons.js","sources":["../../../../../../../packages/vuu-utils/src/data-editing/EditButtons.tsx"],"sourcesContent":["import { Button } from \"@salt-ds/core\";\nimport { EditState, EditSession } from \"./EditSession\";\nimport { useMemo, useState } from \"react\";\n\nexport interface EditButtonProps {\n editSession?: EditSession;\n onCancel: () => void;\n onSave: () => void;\n}\n\nexport const EditButtons = ({\n editSession,\n onCancel,\n onSave,\n}: EditButtonProps) => {\n const [editState, setEditState] = useState<EditState>(\"clean\");\n\n useMemo(() => {\n editSession?.on(\"editState\", setEditState);\n }, [editSession]);\n\n return (\n <>\n <Button\n disabled={editState === \"clean\"}\n onClick={onSave}\n sentiment=\"accented\"\n >\n Save\n </Button>\n <Button onClick={onCancel}>Cancel</Button>\n </>\n );\n};\n"],"names":["useState","useMemo","jsxs","Fragment","jsx","Button"],"mappings":";;;;;;AAUO,MAAM,cAAc,CAAC;AAAA,EAC1B,WAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAuB,KAAA;AACrB,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAIA,eAAoB,OAAO,CAAA;AAE7D,EAAAC,aAAA,CAAQ,MAAM;AACZ,IAAa,WAAA,EAAA,EAAA,CAAG,aAAa,YAAY,CAAA;AAAA,GAC3C,EAAG,CAAC,WAAW,CAAC,CAAA;AAEhB,EAAA,uBAEIC,eAAA,CAAAC,mBAAA,EAAA,EAAA,QAAA,EAAA;AAAA,oBAAAC,cAAA;AAAA,MAACC,WAAA;AAAA,MAAA;AAAA,QACC,UAAU,SAAc,KAAA,OAAA;AAAA,QACxB,OAAS,EAAA,MAAA;AAAA,QACT,SAAU,EAAA,UAAA;AAAA,QACX,QAAA,EAAA;AAAA;AAAA,KAED;AAAA,oBACCD,cAAA,CAAAC,WAAA,EAAA,EAAO,OAAS,EAAA,QAAA,EAAU,QAAM,EAAA,QAAA,EAAA;AAAA,GACnC,EAAA,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"EditButtons.js","sources":["../../../../../../../packages/vuu-utils/src/data-editing/EditButtons.tsx"],"sourcesContent":["import { Button } from \"@salt-ds/core\";\nimport { EditState, EditSession } from \"./EditSession\";\nimport { useCallback, useMemo, useState } from \"react\";\n\nexport interface EditButtonProps {\n editSession?: EditSession;\n onCancel: () => void;\n onSave: (force?: boolean) => void;\n}\n\nexport const EditButtons = ({\n editSession,\n onCancel,\n onSave,\n}: EditButtonProps) => {\n const [editState, setEditState] = useState<EditState>(\"clean\");\n\n const handleSave = useCallback(() => {\n onSave(editState === \"stale\");\n }, [editState, onSave]);\n\n useMemo(() => {\n editSession?.on(\"editState\", setEditState);\n }, [editSession]);\n\n return (\n <>\n <Button\n disabled={editState === \"clean\" || editState === \"invalid\"}\n onClick={handleSave}\n sentiment=\"accented\"\n >\n {editState === \"stale\" ? \"Save (force)\" : \"Save\"}\n </Button>\n <Button onClick={onCancel}>Cancel</Button>\n </>\n );\n};\n"],"names":["useState","useCallback","useMemo","jsxs","Fragment","jsx","Button"],"mappings":";;;;;;AAUO,MAAM,cAAc,CAAC;AAAA,EAC1B,WAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAuB,KAAA;AACrB,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAIA,eAAoB,OAAO,CAAA;AAE7D,EAAM,MAAA,UAAA,GAAaC,kBAAY,MAAM;AACnC,IAAA,MAAA,CAAO,cAAc,OAAO,CAAA;AAAA,GAC3B,EAAA,CAAC,SAAW,EAAA,MAAM,CAAC,CAAA;AAEtB,EAAAC,aAAA,CAAQ,MAAM;AACZ,IAAa,WAAA,EAAA,EAAA,CAAG,aAAa,YAAY,CAAA;AAAA,GAC3C,EAAG,CAAC,WAAW,CAAC,CAAA;AAEhB,EAAA,uBAEIC,eAAA,CAAAC,mBAAA,EAAA,EAAA,QAAA,EAAA;AAAA,oBAAAC,cAAA;AAAA,MAACC,WAAA;AAAA,MAAA;AAAA,QACC,QAAA,EAAU,SAAc,KAAA,OAAA,IAAW,SAAc,KAAA,SAAA;AAAA,QACjD,OAAS,EAAA,UAAA;AAAA,QACT,SAAU,EAAA,UAAA;AAAA,QAET,QAAA,EAAA,SAAA,KAAc,UAAU,cAAiB,GAAA;AAAA;AAAA,KAC5C;AAAA,oBACCD,cAAA,CAAAC,WAAA,EAAA,EAAO,OAAS,EAAA,QAAA,EAAU,QAAM,EAAA,QAAA,EAAA;AAAA,GACnC,EAAA,CAAA;AAEJ;;;;"}
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var eventEmitter = require('../event-emitter.js');
4
+ var protocolMessageUtils = require('../protocol-message-utils.js');
4
5
 
5
6
  var __typeError = (msg) => {
6
7
  throw TypeError(msg);
@@ -9,27 +10,23 @@ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot
9
10
  var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
10
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);
11
12
  var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), member.set(obj, value), value);
12
- var _active, _rowEdits, _editCount, _sourceTableDataSource, _sessionDataSource, _inEditMode;
13
+ var _rowEdits, _editCount, _invalidCount, _sourceTableDataSource, _sessionDataSource, _inEditMode;
14
+ class StaleUpdateError extends Error {
15
+ }
13
16
  class EditSession extends eventEmitter.EventEmitter {
14
17
  constructor(dataSource) {
15
18
  super();
16
- __privateAdd(this, _active, false);
17
19
  /**
18
20
  * Row key => row edits
19
21
  */
20
22
  __privateAdd(this, _rowEdits, /* @__PURE__ */ new Map());
21
23
  __privateAdd(this, _editCount, 0);
24
+ __privateAdd(this, _invalidCount, 0);
22
25
  __privateAdd(this, _sourceTableDataSource);
23
26
  __privateAdd(this, _sessionDataSource);
24
27
  __privateAdd(this, _inEditMode, false);
25
28
  __privateSet(this, _sourceTableDataSource, dataSource);
26
29
  }
27
- get active() {
28
- return __privateGet(this, _active);
29
- }
30
- set active(isActive) {
31
- __privateSet(this, _active, isActive);
32
- }
33
30
  get editCount() {
34
31
  return __privateGet(this, _editCount);
35
32
  }
@@ -44,22 +41,51 @@ class EditSession extends eventEmitter.EventEmitter {
44
41
  }
45
42
  }
46
43
  }
44
+ get invalidCount() {
45
+ return __privateGet(this, _invalidCount);
46
+ }
47
+ set invalidCount(val) {
48
+ if (val !== __privateGet(this, _invalidCount)) {
49
+ const oldCount = __privateGet(this, _invalidCount);
50
+ __privateSet(this, _invalidCount, val);
51
+ if (val === 0) {
52
+ this.emit("editState", __privateGet(this, _editCount) === 0 ? "clean" : "dirty");
53
+ } else if (oldCount === 0) {
54
+ this.emit("editState", "invalid");
55
+ }
56
+ }
57
+ }
47
58
  clear() {
48
59
  __privateGet(this, _rowEdits).clear();
49
60
  __privateSet(this, _editCount, 0);
61
+ __privateSet(this, _inEditMode, false);
50
62
  }
51
63
  async begin(editSessionMode) {
52
- __privateSet(this, _inEditMode, true);
53
- const sessionDataSource = await __privateGet(this, _sourceTableDataSource)?.beginEditSession?.(editSessionMode);
54
- __privateSet(this, _sessionDataSource, sessionDataSource);
55
- return sessionDataSource;
64
+ try {
65
+ __privateSet(this, _inEditMode, true);
66
+ const sessionDataSource = await __privateGet(this, _sourceTableDataSource)?.beginEditSession?.(editSessionMode);
67
+ __privateSet(this, _sessionDataSource, sessionDataSource);
68
+ return sessionDataSource;
69
+ } catch (e) {
70
+ __privateSet(this, _inEditMode, false);
71
+ }
56
72
  }
57
73
  get dataSource() {
58
74
  return __privateGet(this, _sessionDataSource) ?? __privateGet(this, _sourceTableDataSource);
59
75
  }
60
- async end(saveChanges = false) {
61
- await this.dataSource?.endEditSession?.(saveChanges);
62
- this.clear();
76
+ async end(saveChanges = false, force = false) {
77
+ try {
78
+ if (__privateGet(this, _inEditMode)) {
79
+ await this.dataSource?.endEditSession?.(saveChanges, force);
80
+ this.clear();
81
+ }
82
+ } catch (e) {
83
+ if (e instanceof StaleUpdateError) {
84
+ this.emit("editState", "stale");
85
+ } else {
86
+ console.error(`[EditSession] ${e.message}`);
87
+ }
88
+ }
63
89
  }
64
90
  get inEditMode() {
65
91
  return __privateGet(this, _inEditMode);
@@ -67,65 +93,112 @@ class EditSession extends eventEmitter.EventEmitter {
67
93
  get editState() {
68
94
  return this.editCount === 0 ? "clean" : "dirty";
69
95
  }
70
- // TODO how do we deal with the '_edited' pattern
71
- edit(key, columnName, originalValue, newValue) {
96
+ getOrCreateRowEdits(key) {
72
97
  const rowEditDetails = __privateGet(this, _rowEdits).get(key);
73
98
  if (rowEditDetails) {
74
- const { cellEdits } = rowEditDetails;
75
- const cellEdit = cellEdits.get(columnName);
76
- if (cellEdit) {
77
- if (newValue === cellEdit.originalValue) {
78
- if (cellEdits.size === 1) {
79
- __privateGet(this, _rowEdits).delete(key);
80
- } else {
81
- cellEdits.delete(columnName);
82
- }
83
- this.editCount = __privateGet(this, _editCount) - 1;
99
+ return rowEditDetails;
100
+ } else {
101
+ const rowEditDetails2 = {
102
+ cellEdits: /* @__PURE__ */ new Map()
103
+ };
104
+ __privateGet(this, _rowEdits).set(key, rowEditDetails2);
105
+ return rowEditDetails2;
106
+ }
107
+ }
108
+ storeCellEdit(cellEdits, column, originalValue, editedValue, isValid) {
109
+ const cellEdit = cellEdits.get(column);
110
+ if (cellEdit) {
111
+ if (cellEdit.originalValue === editedValue) {
112
+ cellEdits.delete(column);
113
+ cellEdit.isDeleted = true;
114
+ if (cellEdit.isValid) {
115
+ this.editCount -= 1;
84
116
  } else {
85
- cellEdit.editedValue = newValue;
117
+ this.invalidCount -= 1;
86
118
  }
87
119
  } else {
88
- cellEdits.set(columnName, {
89
- originalValue,
90
- editedValue: newValue
91
- });
92
- this.editCount = __privateGet(this, _editCount) + 1;
120
+ if (isValid && cellEdit.isValid === false) {
121
+ cellEdit.isValid = true;
122
+ cellEdit.editedValue = editedValue;
123
+ __privateSet(this, _invalidCount, __privateGet(this, _invalidCount) - 1);
124
+ this.editCount += 1;
125
+ }
93
126
  }
127
+ return cellEdit;
94
128
  } else {
95
- __privateGet(this, _rowEdits).set(key, {
96
- cellEdits: /* @__PURE__ */ new Map([
97
- [columnName, { originalValue, editedValue: newValue }]
98
- ])
99
- });
100
- this.editCount = __privateGet(this, _editCount) + 1;
129
+ const cellEdit2 = {
130
+ originalValue,
131
+ editedValue,
132
+ isValid
133
+ };
134
+ cellEdits.set(column, cellEdit2);
135
+ if (isValid) {
136
+ this.editCount += 1;
137
+ }
138
+ return cellEdit2;
101
139
  }
102
140
  }
103
- async commit(key, columnName, typedValue) {
104
- const rowEditDetails = __privateGet(this, _rowEdits).get(key);
105
- if (rowEditDetails) {
141
+ async commit(key, columnName, originalValue, typedValue, isValid) {
142
+ if (!__privateGet(this, _inEditMode)) {
143
+ throw new Error("No edit session in progress");
144
+ }
145
+ const rowEditDetails = this.getOrCreateRowEdits(key);
146
+ if (isValid) {
106
147
  const { cellEdits } = rowEditDetails;
107
- const cellEditValues = cellEdits.get(columnName);
108
- if (cellEditValues) {
109
- try {
110
- this.dataSource?.editCell?.(key, columnName, typedValue);
111
- } catch (e) {
112
- console.error(e);
148
+ const cellEdit = this.storeCellEdit(
149
+ cellEdits,
150
+ columnName,
151
+ originalValue,
152
+ typedValue,
153
+ isValid
154
+ );
155
+ if (cellEdit.isDeleted) {
156
+ if (rowEditDetails.cellEdits.size === 0) {
157
+ __privateGet(this, _rowEdits).delete(key);
158
+ }
159
+ }
160
+ if (this.dataSource?.editCell) {
161
+ const response = await this.dataSource.editCell(
162
+ key,
163
+ columnName,
164
+ typedValue
165
+ );
166
+ if (protocolMessageUtils.isRpcError(response)) {
167
+ cellEdit.isValid = false;
168
+ this.invalidCount += 1;
113
169
  }
170
+ return {
171
+ editedDuringCurrentSession: cellEdit.originalValue !== typedValue,
172
+ ...response
173
+ };
114
174
  }
115
175
  } else {
116
- return {
117
- errorMessage: "CHANGE_REVERTED",
118
- type: "ERROR_RESULT"
119
- };
176
+ const { cellEdits } = rowEditDetails;
177
+ let cellEdit = cellEdits.get(columnName);
178
+ if (cellEdit && cellEdit.isValid !== false) {
179
+ cellEdit.isValid = false;
180
+ this.invalidCount += 1;
181
+ } else if (cellEdit === void 0) {
182
+ cellEdit = this.storeCellEdit(
183
+ cellEdits,
184
+ columnName,
185
+ originalValue,
186
+ typedValue,
187
+ isValid
188
+ );
189
+ this.invalidCount += 1;
190
+ }
191
+ return { editedDuringCurrentSession: false };
120
192
  }
121
193
  }
122
194
  }
123
- _active = new WeakMap();
124
195
  _rowEdits = new WeakMap();
125
196
  _editCount = new WeakMap();
197
+ _invalidCount = new WeakMap();
126
198
  _sourceTableDataSource = new WeakMap();
127
199
  _sessionDataSource = new WeakMap();
128
200
  _inEditMode = new WeakMap();
129
201
 
130
202
  exports.EditSession = EditSession;
203
+ exports.StaleUpdateError = StaleUpdateError;
131
204
  //# sourceMappingURL=EditSession.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"EditSession.js","sources":["../../../../../../../packages/vuu-utils/src/data-editing/EditSession.tsx"],"sourcesContent":["import { DataSource, EditSessionMode } from \"@vuu-ui/vuu-data-types\";\nimport type {\n RpcResultError,\n VuuRowDataItemType,\n} from \"@vuu-ui/vuu-protocol-types\";\nimport { EventEmitter } from \"../event-emitter\";\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 EditSessionEvents = {\n editState: (editState: EditState) => void;\n};\n\nexport class EditSession extends EventEmitter<EditSessionEvents> {\n #active = false;\n /**\n * Row key => row edits\n */\n #rowEdits = new Map<string, RowEditDetails>();\n #editCount = 0;\n #sourceTableDataSource?: DataSource;\n #sessionDataSource?: DataSource;\n #inEditMode = false;\n\n constructor(dataSource: DataSource) {\n super();\n this.#sourceTableDataSource = dataSource;\n }\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 clear() {\n this.#rowEdits.clear();\n this.#editCount = 0;\n }\n\n async begin(editSessionMode?: EditSessionMode) {\n this.#inEditMode = true;\n\n const sessionDataSource =\n await this.#sourceTableDataSource?.beginEditSession?.(editSessionMode);\n\n this.#sessionDataSource = sessionDataSource;\n\n return sessionDataSource;\n }\n\n get dataSource() {\n return this.#sessionDataSource ?? this.#sourceTableDataSource;\n }\n\n async end(saveChanges = false) {\n await this.dataSource?.endEditSession?.(saveChanges);\n this.clear();\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 // 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(\n key: string,\n columnName: string,\n typedValue: string | number | boolean,\n ) {\n const rowEditDetails = this.#rowEdits.get(key);\n if (rowEditDetails) {\n const { cellEdits } = rowEditDetails;\n const cellEditValues = cellEdits.get(columnName);\n if (cellEditValues) {\n try {\n this.dataSource?.editCell?.(key, columnName, typedValue);\n } catch (e) {\n // ??\n console.error(e);\n }\n }\n } else {\n return {\n errorMessage: \"CHANGE_REVERTED\",\n type: \"ERROR_RESULT\",\n } as RpcResultError;\n }\n }\n}\n"],"names":["EventEmitter"],"mappings":";;;;;;;;;;;AAAA,IAAA,OAAA,EAAA,SAAA,EAAA,UAAA,EAAA,sBAAA,EAAA,kBAAA,EAAA,WAAA;AAyBO,MAAM,oBAAoBA,yBAAgC,CAAA;AAAA,EAW/D,YAAY,UAAwB,EAAA;AAClC,IAAM,KAAA,EAAA;AAXR,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,sBAAA,CAAA;AACA,IAAA,YAAA,CAAA,IAAA,EAAA,kBAAA,CAAA;AACA,IAAc,YAAA,CAAA,IAAA,EAAA,WAAA,EAAA,KAAA,CAAA;AAIZ,IAAA,YAAA,CAAA,IAAA,EAAK,sBAAyB,EAAA,UAAA,CAAA;AAAA;AAChC,EAEA,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,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,MAAM,eAAmC,EAAA;AAC7C,IAAA,YAAA,CAAA,IAAA,EAAK,WAAc,EAAA,IAAA,CAAA;AAEnB,IAAA,MAAM,iBACJ,GAAA,MAAM,YAAK,CAAA,IAAA,EAAA,sBAAA,CAAA,EAAwB,mBAAmB,eAAe,CAAA;AAEvE,IAAA,YAAA,CAAA,IAAA,EAAK,kBAAqB,EAAA,iBAAA,CAAA;AAE1B,IAAO,OAAA,iBAAA;AAAA;AACT,EAEA,IAAI,UAAa,GAAA;AACf,IAAO,OAAA,YAAA,CAAA,IAAA,EAAK,uBAAsB,YAAK,CAAA,IAAA,EAAA,sBAAA,CAAA;AAAA;AACzC,EAEA,MAAM,GAAI,CAAA,WAAA,GAAc,KAAO,EAAA;AAC7B,IAAM,MAAA,IAAA,CAAK,UAAY,EAAA,cAAA,GAAiB,WAAW,CAAA;AACnD,IAAA,IAAA,CAAK,KAAM,EAAA;AAAA;AACb,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;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,MAAA,CACJ,GACA,EAAA,UAAA,EACA,UACA,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,cAAA,GAAiB,SAAU,CAAA,GAAA,CAAI,UAAU,CAAA;AAC/C,MAAA,IAAI,cAAgB,EAAA;AAClB,QAAI,IAAA;AACF,UAAA,IAAA,CAAK,UAAY,EAAA,QAAA,GAAW,GAAK,EAAA,UAAA,EAAY,UAAU,CAAA;AAAA,iBAChD,CAAG,EAAA;AAEV,UAAA,OAAA,CAAQ,MAAM,CAAC,CAAA;AAAA;AACjB;AACF,KACK,MAAA;AACL,MAAO,OAAA;AAAA,QACL,YAAc,EAAA,iBAAA;AAAA,QACd,IAAM,EAAA;AAAA,OACR;AAAA;AACF;AAEJ;AAvIE,OAAA,GAAA,IAAA,OAAA,EAAA;AAIA,SAAA,GAAA,IAAA,OAAA,EAAA;AACA,UAAA,GAAA,IAAA,OAAA,EAAA;AACA,sBAAA,GAAA,IAAA,OAAA,EAAA;AACA,kBAAA,GAAA,IAAA,OAAA,EAAA;AACA,WAAA,GAAA,IAAA,OAAA,EAAA;;;;"}
1
+ {"version":3,"file":"EditSession.js","sources":["../../../../../../../packages/vuu-utils/src/data-editing/EditSession.tsx"],"sourcesContent":["import { EditApi, EditSessionMode } from \"@vuu-ui/vuu-data-types\";\nimport type { VuuRowDataItemType } from \"@vuu-ui/vuu-protocol-types\";\nimport { EventEmitter } from \"../event-emitter\";\nimport { isRpcError } from \"../protocol-message-utils\";\n\nexport type EditState = \"clean\" | \"dirty\" | \"invalid\" | \"stale\";\n\nexport class EditError extends Error {}\n\ntype CellEdit = {\n originalValue: VuuRowDataItemType;\n editedValue: VuuRowDataItemType;\n isValid?: boolean;\n isDeleted?: boolean;\n};\n\n// TODO can add more when when we know what the server implementation of error columns will look like\nexport class StaleUpdateError extends Error {}\n\ntype RowEditDetails = {\n /**\n * Column name => cell edit details\n */\n cellEdits: Map<string, CellEdit>;\n};\n\ntype EditSessionEvents = {\n editState: (editState: EditState) => void;\n};\n\nexport class EditSession extends EventEmitter<EditSessionEvents> {\n /**\n * Row key => row edits\n */\n #rowEdits = new Map<string, RowEditDetails>();\n #editCount = 0;\n #invalidCount = 0;\n #sourceTableDataSource?: EditApi;\n #sessionDataSource?: EditApi;\n #inEditMode = false;\n\n constructor(dataSource: EditApi) {\n super();\n this.#sourceTableDataSource = dataSource;\n }\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 get invalidCount() {\n return this.#invalidCount;\n }\n\n set invalidCount(val: number) {\n if (val !== this.#invalidCount) {\n const oldCount = this.#invalidCount;\n this.#invalidCount = val;\n if (val === 0) {\n this.emit(\"editState\", this.#editCount === 0 ? \"clean\" : \"dirty\");\n } else if (oldCount === 0) {\n this.emit(\"editState\", \"invalid\");\n }\n }\n }\n\n clear() {\n this.#rowEdits.clear();\n this.#editCount = 0;\n this.#inEditMode = false;\n }\n\n async begin(editSessionMode?: EditSessionMode) {\n try {\n this.#inEditMode = true;\n const sessionDataSource =\n await this.#sourceTableDataSource?.beginEditSession?.(editSessionMode);\n\n this.#sessionDataSource = sessionDataSource;\n\n return sessionDataSource;\n } catch (e) {\n this.#inEditMode = false;\n }\n }\n\n get dataSource() {\n return this.#sessionDataSource ?? this.#sourceTableDataSource;\n }\n\n async end(saveChanges = false, force = false) {\n try {\n if (this.#inEditMode) {\n await this.dataSource?.endEditSession?.(saveChanges, force);\n this.clear();\n }\n } catch (e) {\n if (e instanceof StaleUpdateError) {\n this.emit(\"editState\", \"stale\");\n } else {\n console.error(`[EditSession] ${(e as Error).message}`);\n }\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 getOrCreateRowEdits(key: string): RowEditDetails {\n const rowEditDetails = this.#rowEdits.get(key);\n if (rowEditDetails) {\n return rowEditDetails;\n } else {\n const rowEditDetails = {\n cellEdits: new Map(),\n };\n this.#rowEdits.set(key, rowEditDetails);\n return rowEditDetails;\n }\n }\n\n storeCellEdit(\n cellEdits: Map<string, CellEdit>,\n column: string,\n originalValue: VuuRowDataItemType,\n editedValue: VuuRowDataItemType,\n isValid: boolean,\n ) {\n const cellEdit = cellEdits.get(column);\n if (cellEdit) {\n if (cellEdit.originalValue === editedValue) {\n cellEdits.delete(column);\n cellEdit.isDeleted = true;\n if (cellEdit.isValid) {\n this.editCount -= 1;\n } else {\n this.invalidCount -= 1;\n }\n } else {\n if (isValid && cellEdit.isValid === false) {\n cellEdit.isValid = true;\n cellEdit.editedValue = editedValue;\n // do not trigger the event, save it for the editCount\n this.#invalidCount -= 1;\n this.editCount += 1;\n }\n }\n return cellEdit;\n } else {\n const cellEdit: CellEdit = {\n originalValue,\n editedValue,\n isValid,\n };\n cellEdits.set(column, cellEdit);\n if (isValid) {\n this.editCount += 1;\n }\n return cellEdit;\n }\n }\n\n async commit(\n key: string,\n columnName: string,\n originalValue: VuuRowDataItemType,\n typedValue: string | number | boolean,\n isValid: boolean,\n ) {\n if (!this.#inEditMode) {\n throw new Error(\"No edit session in progress\");\n }\n const rowEditDetails = this.getOrCreateRowEdits(key);\n\n if (isValid) {\n const { cellEdits } = rowEditDetails;\n\n const cellEdit = this.storeCellEdit(\n cellEdits,\n columnName,\n originalValue,\n typedValue,\n isValid,\n );\n\n if (cellEdit.isDeleted) {\n if (rowEditDetails.cellEdits.size === 0) {\n this.#rowEdits.delete(key);\n }\n }\n\n if (this.dataSource?.editCell) {\n const response = await this.dataSource.editCell(\n key,\n columnName,\n typedValue,\n );\n if (isRpcError(response)) {\n cellEdit.isValid = false;\n this.invalidCount += 1;\n }\n\n return {\n editedDuringCurrentSession: cellEdit.originalValue !== typedValue,\n ...response,\n };\n }\n } else {\n const { cellEdits } = rowEditDetails;\n let cellEdit = cellEdits.get(columnName);\n if (cellEdit && cellEdit.isValid !== false) {\n cellEdit.isValid = false;\n this.invalidCount += 1;\n } else if (cellEdit === undefined) {\n cellEdit = this.storeCellEdit(\n cellEdits,\n columnName,\n originalValue,\n typedValue,\n isValid,\n );\n this.invalidCount += 1;\n }\n return { editedDuringCurrentSession: false };\n }\n }\n}\n"],"names":["EventEmitter","rowEditDetails","cellEdit","isRpcError"],"mappings":"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"}
@@ -1,6 +1,37 @@
1
1
  'use strict';
2
2
 
3
- const isInlineEditingSession = (editSessionMode) => editSessionMode === "inline-all-rows";
3
+ var jsxRuntime = require('react/jsx-runtime');
4
+ require('../date/date-utils.js');
5
+ require('../date/dateTimePattern.js');
6
+ var formatter = require('../date/formatter.js');
4
7
 
8
+ const isInlineEditingSession = (editSessionMode) => editSessionMode.startsWith("inline");
9
+ const timeFormatter = formatter.formatDate({ time: "hh:mm:ss" });
10
+ const getVuuEditMessage = (dataRow, column, originalValue) => {
11
+ const vuuMsg = dataRow.vuuMsg;
12
+ if (typeof vuuMsg === "string" && vuuMsg !== "") {
13
+ const columnMessages = vuuMsg.split(",");
14
+ const msgForCol = columnMessages.find(
15
+ (msg) => msg.startsWith(`${column.name}:`)
16
+ );
17
+ if (msgForCol) {
18
+ const [, value, updatedValue, ts] = msgForCol.split(":");
19
+ const updateTime = timeFormatter(new Date(parseInt(ts)));
20
+ return /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
21
+ "Update rejected. Original value ",
22
+ /* @__PURE__ */ jsxRuntime.jsx("b", { children: originalValue }),
23
+ " could not be updated to ",
24
+ /* @__PURE__ */ jsxRuntime.jsx("b", { children: value }),
25
+ ". It was updated to ",
26
+ /* @__PURE__ */ jsxRuntime.jsx("b", { children: updatedValue }),
27
+ " at ",
28
+ updateTime,
29
+ "."
30
+ ] });
31
+ }
32
+ }
33
+ };
34
+
35
+ exports.getVuuEditMessage = getVuuEditMessage;
5
36
  exports.isInlineEditingSession = isInlineEditingSession;
6
37
  //# sourceMappingURL=edit-utils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"edit-utils.js","sources":["../../../../../../../packages/vuu-utils/src/data-editing/edit-utils.ts"],"sourcesContent":["import { EditSessionMode, InlineEditSessionMode } from \"@vuu-ui/vuu-data-types\";\n\nexport const isInlineEditingSession = (\n editSessionMode: EditSessionMode,\n): editSessionMode is InlineEditSessionMode =>\n editSessionMode === \"inline-all-rows\";\n"],"names":[],"mappings":";;AAEa,MAAA,sBAAA,GAAyB,CACpC,eAAA,KAEA,eAAoB,KAAA;;;;"}
1
+ {"version":3,"file":"edit-utils.js","sources":["../../../../../../../packages/vuu-utils/src/data-editing/edit-utils.tsx"],"sourcesContent":["import { EditSessionMode, InlineEditSessionMode } from \"@vuu-ui/vuu-data-types\";\nimport { DataRow, RuntimeColumnDescriptor } from \"@vuu-ui/vuu-table-types\";\nimport { formatDate } from \"../date\";\n\nexport const isInlineEditingSession = (\n editSessionMode: EditSessionMode,\n): editSessionMode is InlineEditSessionMode =>\n editSessionMode.startsWith(\"inline\");\n\nconst timeFormatter = formatDate({ time: \"hh:mm:ss\" });\n\nexport const getVuuEditMessage = (\n dataRow: DataRow,\n column: RuntimeColumnDescriptor,\n originalValue: string,\n) => {\n const vuuMsg = dataRow.vuuMsg as string;\n if (typeof vuuMsg === \"string\" && vuuMsg !== \"\") {\n const columnMessages = vuuMsg.split(\",\");\n const msgForCol = columnMessages.find((msg) =>\n msg.startsWith(`${column.name}:`),\n );\n if (msgForCol) {\n const [, value, updatedValue, ts] = msgForCol.split(\":\");\n const updateTime = timeFormatter(new Date(parseInt(ts as string)));\n return (\n <span>\n {\"Update rejected. Original value \"}\n <b>{originalValue}</b>\n {\" could not be updated to \"}\n <b>{value}</b>\n {\". It was updated to \"}\n <b>{updatedValue}</b>\n {\" at \"}\n {updateTime}\n {\".\"}\n </span>\n );\n }\n }\n};\n"],"names":["formatDate","jsx"],"mappings":";;;;;;;AAIO,MAAM,sBAAyB,GAAA,CACpC,eAEA,KAAA,eAAA,CAAgB,WAAW,QAAQ;AAErC,MAAM,aAAgB,GAAAA,oBAAA,CAAW,EAAE,IAAA,EAAM,YAAY,CAAA;AAE9C,MAAM,iBAAoB,GAAA,CAC/B,OACA,EAAA,MAAA,EACA,aACG,KAAA;AACH,EAAA,MAAM,SAAS,OAAQ,CAAA,MAAA;AACvB,EAAA,IAAI,OAAO,MAAA,KAAW,QAAY,IAAA,MAAA,KAAW,EAAI,EAAA;AAC/C,IAAM,MAAA,cAAA,GAAiB,MAAO,CAAA,KAAA,CAAM,GAAG,CAAA;AACvC,IAAA,MAAM,YAAY,cAAe,CAAA,IAAA;AAAA,MAAK,CAAC,GACrC,KAAA,GAAA,CAAI,WAAW,CAAG,EAAA,MAAA,CAAO,IAAI,CAAG,CAAA,CAAA;AAAA,KAClC;AACA,IAAA,IAAI,SAAW,EAAA;AACb,MAAM,MAAA,GAAG,KAAO,EAAA,YAAA,EAAc,EAAE,CAAI,GAAA,SAAA,CAAU,MAAM,GAAG,CAAA;AACvD,MAAA,MAAM,aAAa,aAAc,CAAA,IAAI,KAAK,QAAS,CAAA,EAAY,CAAC,CAAC,CAAA;AACjE,MAAA,uCACG,MACE,EAAA,EAAA,QAAA,EAAA;AAAA,QAAA,kCAAA;AAAA,wBACDC,cAAA,CAAC,OAAG,QAAc,EAAA,aAAA,EAAA,CAAA;AAAA,QACjB,2BAAA;AAAA,wBACDA,cAAA,CAAC,OAAG,QAAM,EAAA,KAAA,EAAA,CAAA;AAAA,QACT,sBAAA;AAAA,wBACDA,cAAA,CAAC,OAAG,QAAa,EAAA,YAAA,EAAA,CAAA;AAAA,QAChB,MAAA;AAAA,QACA,UAAA;AAAA,QACA;AAAA,OACH,EAAA,CAAA;AAAA;AAEJ;AAEJ;;;;;"}
@@ -8,7 +8,7 @@ var EditSession = require('./EditSession.js');
8
8
  const useEditableTable = ({
9
9
  columns,
10
10
  dataSource: dataSourceProp,
11
- editSessionMode = "all-rows",
11
+ editSessionMode = "inline-all-rows",
12
12
  isEditMode,
13
13
  onCancel,
14
14
  onSave,
@@ -38,14 +38,20 @@ const useEditableTable = ({
38
38
  } catch (e) {
39
39
  }
40
40
  }, [editSession, onCancel]);
41
- const handleSave = React.useCallback(async () => {
42
- dataSource.resume?.();
43
- try {
44
- await editSession.end(true);
45
- onSave();
46
- } catch (e) {
47
- }
48
- }, [dataSource, editSession, onSave]);
41
+ const handleSave = React.useCallback(
42
+ async (force = false) => {
43
+ dataSource.resume?.();
44
+ try {
45
+ await editSession.end(true, force);
46
+ if (editSession.inEditMode === false) {
47
+ onSave();
48
+ }
49
+ } catch (e) {
50
+ console.log(`[useEditableTable] handleSave ${e.message}`);
51
+ }
52
+ },
53
+ [dataSource, editSession, onSave]
54
+ );
49
55
  React.useMemo(async () => {
50
56
  console.log(`[useEditableTable] editMode ${isEditMode}`);
51
57
  if (isEditMode) {
@@ -58,6 +64,8 @@ const useEditableTable = ({
58
64
  console.error(e);
59
65
  onCancel();
60
66
  }
67
+ } else {
68
+ await editSession.end();
61
69
  }
62
70
  }, [editSession, editSessionMode, isEditMode, onCancel]);
63
71
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"useEditableTable.js","sources":["../../../../../../../packages/vuu-utils/src/data-editing/useEditableTable.ts"],"sourcesContent":["import { DataSource, EditSessionMode } from \"@vuu-ui/vuu-data-types\";\n// import { useNotifications } from \"@vuu-ui/vuu-notifications\";\nimport { VuuTable } from \"@vuu-ui/vuu-protocol-types\";\nimport { useCallback, useMemo, useState } from \"react\";\nimport { useData } from \"../context-definitions/DataProvider\";\nimport { useLayoutEffectSkipFirst } from \"../useLayoutEffectSkipFirst\";\nimport { EditSession } from \"./EditSession\";\n// import { useNotifications } from \"@vuu-ui/vuu-notifications\";\n\nexport type EditMode = \"edit\" | \"view\";\n\nexport interface EditableTableHookProps {\n /**\n * columns to be included in subscription. If not provided,\n * default will be '*'. Ignored if dataSource prop present.\n */\n columns?: string[];\n dataSource?: DataSource;\n editSessionMode?: EditSessionMode;\n isEditMode: boolean;\n onCancel: () => void;\n onSave: () => void;\n /**\n * If dataSource not provided, new DataSource\n * will be created using table and columns\n */\n table?: VuuTable;\n}\n\nexport const useEditableTable = ({\n columns,\n dataSource: dataSourceProp,\n editSessionMode = \"all-rows\",\n isEditMode,\n onCancel,\n onSave,\n table,\n}: EditableTableHookProps) => {\n const { VuuDataSource } = useData();\n const [sessionDataSource, setSessionDataSource] = useState<\n DataSource | undefined\n >(undefined);\n // const { showNotification } = useNotifications();\n useLayoutEffectSkipFirst(() => {\n console.warn(`[useEditableTable] columns and or table changed`);\n }, [columns, table]);\n\n const dataSource = useMemo(() => {\n // The dataSource would normally be managed by client and passed in, but for\n // simple use cases we can create it here.\n if (dataSourceProp) {\n return dataSourceProp;\n } else if (table) {\n return new VuuDataSource({ columns, table });\n } else {\n throw Error(\n `useEditableTable unable to provide DataSource, neither dataSource nor table available as props`,\n );\n }\n }, [VuuDataSource, columns, dataSourceProp, table]);\n\n // The editSession will be made available to all the edit controls in scope by\n // wrapping the edit component with a DataEditingProvider.\n const editSession = useMemo(() => new EditSession(dataSource), [dataSource]);\n\n const handleCancel = useCallback(() => {\n // editTracker.dataSource = dataSource;\n try {\n editSession.end();\n onCancel();\n } catch (e) {\n //\n }\n }, [editSession, onCancel]);\n\n const handleSave = useCallback(async () => {\n dataSource.resume?.();\n try {\n await editSession.end(true);\n onSave();\n } catch (e) {\n // cleanup\n }\n }, [dataSource, editSession, onSave]);\n\n useMemo(async () => {\n console.log(`[useEditableTable] editMode ${isEditMode}`);\n if (isEditMode) {\n try {\n const sessionDataSource = await editSession.begin(editSessionMode);\n if (sessionDataSource) {\n setSessionDataSource(sessionDataSource);\n }\n } catch (e) {\n console.error(e);\n // deal with error\n // showNotification?.({\n // header: \"Error unable to edit\",\n // status: \"error\",\n // type: \"toast\",\n // });\n onCancel();\n }\n }\n }, [editSession, editSessionMode, isEditMode, onCancel]);\n\n return {\n dataSource,\n editSession,\n onCancel: handleCancel,\n onSave: handleSave,\n sessionDataSource,\n };\n};\n"],"names":["useData","useState","useLayoutEffectSkipFirst","useMemo","EditSession","useCallback","sessionDataSource"],"mappings":";;;;;;;AA6BO,MAAM,mBAAmB,CAAC;AAAA,EAC/B,OAAA;AAAA,EACA,UAAY,EAAA,cAAA;AAAA,EACZ,eAAkB,GAAA,UAAA;AAAA,EAClB,UAAA;AAAA,EACA,QAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF,CAA8B,KAAA;AAC5B,EAAM,MAAA,EAAE,aAAc,EAAA,GAAIA,oBAAQ,EAAA;AAClC,EAAA,MAAM,CAAC,iBAAA,EAAmB,oBAAoB,CAAA,GAAIC,eAEhD,KAAS,CAAA,CAAA;AAEX,EAAAC,iDAAA,CAAyB,MAAM;AAC7B,IAAA,OAAA,CAAQ,KAAK,CAAiD,+CAAA,CAAA,CAAA;AAAA,GAC7D,EAAA,CAAC,OAAS,EAAA,KAAK,CAAC,CAAA;AAEnB,EAAM,MAAA,UAAA,GAAaC,cAAQ,MAAM;AAG/B,IAAA,IAAI,cAAgB,EAAA;AAClB,MAAO,OAAA,cAAA;AAAA,eACE,KAAO,EAAA;AAChB,MAAA,OAAO,IAAI,aAAA,CAAc,EAAE,OAAA,EAAS,OAAO,CAAA;AAAA,KACtC,MAAA;AACL,MAAM,MAAA,KAAA;AAAA,QACJ,CAAA,8FAAA;AAAA,OACF;AAAA;AACF,KACC,CAAC,aAAA,EAAe,OAAS,EAAA,cAAA,EAAgB,KAAK,CAAC,CAAA;AAIlD,EAAM,MAAA,WAAA,GAAcA,cAAQ,MAAM,IAAIC,wBAAY,UAAU,CAAA,EAAG,CAAC,UAAU,CAAC,CAAA;AAE3E,EAAM,MAAA,YAAA,GAAeC,kBAAY,MAAM;AAErC,IAAI,IAAA;AACF,MAAA,WAAA,CAAY,GAAI,EAAA;AAChB,MAAS,QAAA,EAAA;AAAA,aACF,CAAG,EAAA;AAAA;AAEZ,GACC,EAAA,CAAC,WAAa,EAAA,QAAQ,CAAC,CAAA;AAE1B,EAAM,MAAA,UAAA,GAAaA,kBAAY,YAAY;AACzC,IAAA,UAAA,CAAW,MAAS,IAAA;AACpB,IAAI,IAAA;AACF,MAAM,MAAA,WAAA,CAAY,IAAI,IAAI,CAAA;AAC1B,MAAO,MAAA,EAAA;AAAA,aACA,CAAG,EAAA;AAAA;AAEZ,GACC,EAAA,CAAC,UAAY,EAAA,WAAA,EAAa,MAAM,CAAC,CAAA;AAEpC,EAAAF,aAAA,CAAQ,YAAY;AAClB,IAAQ,OAAA,CAAA,GAAA,CAAI,CAA+B,4BAAA,EAAA,UAAU,CAAE,CAAA,CAAA;AACvD,IAAA,IAAI,UAAY,EAAA;AACd,MAAI,IAAA;AACF,QAAA,MAAMG,kBAAoB,GAAA,MAAM,WAAY,CAAA,KAAA,CAAM,eAAe,CAAA;AACjE,QAAA,IAAIA,kBAAmB,EAAA;AACrB,UAAA,oBAAA,CAAqBA,kBAAiB,CAAA;AAAA;AACxC,eACO,CAAG,EAAA;AACV,QAAA,OAAA,CAAQ,MAAM,CAAC,CAAA;AAOf,QAAS,QAAA,EAAA;AAAA;AACX;AACF,KACC,CAAC,WAAA,EAAa,eAAiB,EAAA,UAAA,EAAY,QAAQ,CAAC,CAAA;AAEvD,EAAO,OAAA;AAAA,IACL,UAAA;AAAA,IACA,WAAA;AAAA,IACA,QAAU,EAAA,YAAA;AAAA,IACV,MAAQ,EAAA,UAAA;AAAA,IACR;AAAA,GACF;AACF;;;;"}
1
+ {"version":3,"file":"useEditableTable.js","sources":["../../../../../../../packages/vuu-utils/src/data-editing/useEditableTable.ts"],"sourcesContent":["import { DataSource, EditSessionMode } from \"@vuu-ui/vuu-data-types\";\n// import { useNotifications } from \"@vuu-ui/vuu-notifications\";\nimport { VuuTable } from \"@vuu-ui/vuu-protocol-types\";\nimport { useCallback, useMemo, useState } from \"react\";\nimport { useData } from \"../context-definitions/DataProvider\";\nimport { useLayoutEffectSkipFirst } from \"../useLayoutEffectSkipFirst\";\nimport { EditSession } from \"./EditSession\";\n// import { useNotifications } from \"@vuu-ui/vuu-notifications\";\n\nexport type EditMode = \"edit\" | \"view\";\n\nexport interface EditableTableHookProps {\n /**\n * columns to be included in subscription. If not provided,\n * default will be '*'. Ignored if dataSource prop present.\n */\n columns?: string[];\n dataSource?: DataSource;\n editSessionMode?: EditSessionMode;\n isEditMode: boolean;\n onCancel: () => void;\n onSave: () => void;\n /**\n * If dataSource not provided, new DataSource\n * will be created using table and columns\n */\n table?: VuuTable;\n}\n\nexport const useEditableTable = ({\n columns,\n dataSource: dataSourceProp,\n editSessionMode = \"inline-all-rows\",\n isEditMode,\n onCancel,\n onSave,\n table,\n}: EditableTableHookProps) => {\n const { VuuDataSource } = useData();\n const [sessionDataSource, setSessionDataSource] = useState<\n DataSource | undefined\n >(undefined);\n // const { showNotification } = useNotifications();\n useLayoutEffectSkipFirst(() => {\n console.warn(`[useEditableTable] columns and or table changed`);\n }, [columns, table]);\n\n const dataSource = useMemo(() => {\n // The dataSource would normally be managed by client and passed in, but for\n // simple use cases we can create it here.\n if (dataSourceProp) {\n return dataSourceProp;\n } else if (table) {\n return new VuuDataSource({ columns, table });\n } else {\n throw Error(\n `useEditableTable unable to provide DataSource, neither dataSource nor table available as props`,\n );\n }\n }, [VuuDataSource, columns, dataSourceProp, table]);\n\n // The editSession will be made available to all the edit controls in scope by\n // wrapping the edit component with a DataEditingProvider.\n const editSession = useMemo(() => new EditSession(dataSource), [dataSource]);\n\n const handleCancel = useCallback(() => {\n // editTracker.dataSource = dataSource;\n try {\n editSession.end();\n onCancel();\n } catch (e) {\n //\n }\n }, [editSession, onCancel]);\n\n const handleSave = useCallback(\n async (force = false) => {\n // TODO is this right\n dataSource.resume?.();\n try {\n await editSession.end(true, force);\n if (editSession.inEditMode === false) {\n // Everything was ok data saved\n onSave();\n }\n } catch (e) {\n console.log(`[useEditableTable] handleSave ${(e as Error).message}`);\n }\n },\n [dataSource, editSession, onSave],\n );\n\n useMemo(async () => {\n console.log(`[useEditableTable] editMode ${isEditMode}`);\n if (isEditMode) {\n try {\n const sessionDataSource = await editSession.begin(editSessionMode);\n if (sessionDataSource) {\n setSessionDataSource(sessionDataSource);\n }\n } catch (e) {\n console.error(e);\n // deal with error\n // showNotification?.({\n // header: \"Error unable to edit\",\n // status: \"error\",\n // type: \"toast\",\n // });\n onCancel();\n }\n } else {\n await editSession.end();\n }\n }, [editSession, editSessionMode, isEditMode, onCancel]);\n\n return {\n dataSource,\n editSession,\n onCancel: handleCancel,\n onSave: handleSave,\n sessionDataSource,\n };\n};\n"],"names":["useData","useState","useLayoutEffectSkipFirst","useMemo","EditSession","useCallback","sessionDataSource"],"mappings":";;;;;;;AA6BO,MAAM,mBAAmB,CAAC;AAAA,EAC/B,OAAA;AAAA,EACA,UAAY,EAAA,cAAA;AAAA,EACZ,eAAkB,GAAA,iBAAA;AAAA,EAClB,UAAA;AAAA,EACA,QAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF,CAA8B,KAAA;AAC5B,EAAM,MAAA,EAAE,aAAc,EAAA,GAAIA,oBAAQ,EAAA;AAClC,EAAA,MAAM,CAAC,iBAAA,EAAmB,oBAAoB,CAAA,GAAIC,eAEhD,KAAS,CAAA,CAAA;AAEX,EAAAC,iDAAA,CAAyB,MAAM;AAC7B,IAAA,OAAA,CAAQ,KAAK,CAAiD,+CAAA,CAAA,CAAA;AAAA,GAC7D,EAAA,CAAC,OAAS,EAAA,KAAK,CAAC,CAAA;AAEnB,EAAM,MAAA,UAAA,GAAaC,cAAQ,MAAM;AAG/B,IAAA,IAAI,cAAgB,EAAA;AAClB,MAAO,OAAA,cAAA;AAAA,eACE,KAAO,EAAA;AAChB,MAAA,OAAO,IAAI,aAAA,CAAc,EAAE,OAAA,EAAS,OAAO,CAAA;AAAA,KACtC,MAAA;AACL,MAAM,MAAA,KAAA;AAAA,QACJ,CAAA,8FAAA;AAAA,OACF;AAAA;AACF,KACC,CAAC,aAAA,EAAe,OAAS,EAAA,cAAA,EAAgB,KAAK,CAAC,CAAA;AAIlD,EAAM,MAAA,WAAA,GAAcA,cAAQ,MAAM,IAAIC,wBAAY,UAAU,CAAA,EAAG,CAAC,UAAU,CAAC,CAAA;AAE3E,EAAM,MAAA,YAAA,GAAeC,kBAAY,MAAM;AAErC,IAAI,IAAA;AACF,MAAA,WAAA,CAAY,GAAI,EAAA;AAChB,MAAS,QAAA,EAAA;AAAA,aACF,CAAG,EAAA;AAAA;AAEZ,GACC,EAAA,CAAC,WAAa,EAAA,QAAQ,CAAC,CAAA;AAE1B,EAAA,MAAM,UAAa,GAAAA,iBAAA;AAAA,IACjB,OAAO,QAAQ,KAAU,KAAA;AAEvB,MAAA,UAAA,CAAW,MAAS,IAAA;AACpB,MAAI,IAAA;AACF,QAAM,MAAA,WAAA,CAAY,GAAI,CAAA,IAAA,EAAM,KAAK,CAAA;AACjC,QAAI,IAAA,WAAA,CAAY,eAAe,KAAO,EAAA;AAEpC,UAAO,MAAA,EAAA;AAAA;AACT,eACO,CAAG,EAAA;AACV,QAAA,OAAA,CAAQ,GAAI,CAAA,CAAA,8BAAA,EAAkC,CAAY,CAAA,OAAO,CAAE,CAAA,CAAA;AAAA;AACrE,KACF;AAAA,IACA,CAAC,UAAY,EAAA,WAAA,EAAa,MAAM;AAAA,GAClC;AAEA,EAAAF,aAAA,CAAQ,YAAY;AAClB,IAAQ,OAAA,CAAA,GAAA,CAAI,CAA+B,4BAAA,EAAA,UAAU,CAAE,CAAA,CAAA;AACvD,IAAA,IAAI,UAAY,EAAA;AACd,MAAI,IAAA;AACF,QAAA,MAAMG,kBAAoB,GAAA,MAAM,WAAY,CAAA,KAAA,CAAM,eAAe,CAAA;AACjE,QAAA,IAAIA,kBAAmB,EAAA;AACrB,UAAA,oBAAA,CAAqBA,kBAAiB,CAAA;AAAA;AACxC,eACO,CAAG,EAAA;AACV,QAAA,OAAA,CAAQ,MAAM,CAAC,CAAA;AAOf,QAAS,QAAA,EAAA;AAAA;AACX,KACK,MAAA;AACL,MAAA,MAAM,YAAY,GAAI,EAAA;AAAA;AACxB,KACC,CAAC,WAAA,EAAa,eAAiB,EAAA,UAAA,EAAY,QAAQ,CAAC,CAAA;AAEvD,EAAO,OAAA;AAAA,IACL,UAAA;AAAA,IACA,WAAA;AAAA,IACA,QAAU,EAAA,YAAA;AAAA,IACV,MAAQ,EAAA,UAAA;AAAA,IACR;AAAA,GACF;AACF;;;;"}
@@ -52,17 +52,17 @@ function getMovingValueDirection(newValue, direction, prevValue, decimalPlaces)
52
52
  }
53
53
  }
54
54
  }
55
- function asInteger(index, defaultValue) {
56
- if (typeof index === "number") {
57
- return index;
55
+ function asInteger(value, defaultValue) {
56
+ if (typeof value === "number") {
57
+ return Number.isInteger(value) ? value : value < 0 ? Math.ceil(value) : Math.floor(value);
58
58
  } else {
59
- const numIdx = parseInt(index ?? "");
60
- if (!isNaN(numIdx)) {
61
- return numIdx;
59
+ const integerValue = parseInt(value ?? "");
60
+ if (!isNaN(integerValue)) {
61
+ return integerValue;
62
62
  } else if (typeof defaultValue === "number") {
63
63
  return defaultValue;
64
64
  }
65
- throw Error(`parseIndex invalid value ${index}`);
65
+ throw Error(`parseIndex invalid value ${value}`);
66
66
  }
67
67
  }
68
68
  const dataDescriptorTypeToVuuRowDataItemType = ({
@@ -1 +1 @@
1
- {"version":3,"file":"data-utils.js","sources":["../../../../../../packages/vuu-utils/src/data-utils.ts"],"sourcesContent":["import { DataValueDescriptor } from \"@vuu-ui/vuu-data-types\";\n\nexport type valueChangeDirection = \"up1\" | \"up2\" | \"down1\" | \"down2\" | \"\";\n\nexport const UP1 = \"up1\";\nexport const UP2 = \"up2\";\nexport const DOWN1 = \"down1\";\nexport const DOWN2 = \"down2\";\n\nconst decimalPattern = /^-?[0-9]*\\.[0-9]+$/;\n\nexport const stringIsValidInt = (val: string) =>\n parseInt(val, 10).toString() === val;\n\nexport const stringIsValidDecimal = (val: string) =>\n stringIsValidInt(val) || decimalPattern.test(val);\n\nexport const stringIsValidNumber = (val: string) =>\n stringIsValidInt(val) || stringIsValidDecimal(val);\n\nexport const numericTypeOfStringValue = (val: string) =>\n stringIsValidInt(val) ? \"int\" : stringIsValidDecimal(val) ? \"double\" : \"NaN\";\n\nexport const isValidNumber = (n: unknown): n is number =>\n typeof n === \"number\" && isFinite(n);\n\nconst EMPTY = {};\nexport const shallowEquals = (\n o1: { [key: string]: unknown } = EMPTY,\n o2: { [key: string]: unknown } = EMPTY,\n) => {\n const props1 = Object.keys(o1);\n const props2 = Object.keys(o2);\n return (\n props1.length === props2.length &&\n props1.every((key) => o1[key] === o2[key])\n );\n};\n\nexport function getMovingValueDirection(\n newValue?: number,\n direction?: valueChangeDirection,\n prevValue?: number,\n /** the number of decimal places to take into account when highlighting a change */\n decimalPlaces?: number,\n): valueChangeDirection {\n if (newValue === undefined) {\n return \"\";\n }\n if (\n !isFinite(newValue) ||\n prevValue === undefined ||\n direction === undefined\n ) {\n return \"\";\n } else {\n let diff = newValue - prevValue;\n if (diff) {\n // make sure there is still a diff when reduced to number of decimals to be displayed\n if (typeof decimalPlaces === \"number\") {\n diff =\n +newValue.toFixed(decimalPlaces) - +prevValue.toFixed(decimalPlaces);\n }\n }\n\n if (diff) {\n if (direction === \"\") {\n if (diff < 0) {\n return DOWN1;\n } else {\n return UP1;\n }\n } else if (diff > 0) {\n if (direction === DOWN1 || direction === DOWN2 || direction === UP2) {\n return UP1;\n } else {\n return UP2;\n }\n } else if (\n direction === UP1 ||\n direction === UP2 ||\n direction === DOWN2\n ) {\n return DOWN1;\n } else {\n return DOWN2;\n }\n } else {\n return \"\";\n }\n }\n}\n\nexport function asInteger(\n index: number | string | undefined,\n defaultValue?: number,\n) {\n if (typeof index === \"number\") {\n return index;\n } else {\n const numIdx = parseInt(index ?? \"\");\n if (!isNaN(numIdx)) {\n return numIdx;\n } else if (typeof defaultValue === \"number\") {\n return defaultValue;\n }\n throw Error(`parseIndex invalid value ${index}`);\n }\n}\n\nexport const dataDescriptorTypeToVuuRowDataItemType = ({\n serverDataType = \"string\",\n}: DataValueDescriptor): \"string\" | \"number\" | \"boolean\" => {\n switch (serverDataType) {\n case \"double\":\n case \"int\":\n case \"long\":\n return \"number\";\n case \"boolean\":\n return \"boolean\";\n default:\n return \"string\";\n }\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"data-utils.js","sources":["../../../../../../packages/vuu-utils/src/data-utils.ts"],"sourcesContent":["import { DataValueDescriptor } from \"@vuu-ui/vuu-data-types\";\n\nexport type valueChangeDirection = \"up1\" | \"up2\" | \"down1\" | \"down2\" | \"\";\n\nexport const UP1 = \"up1\";\nexport const UP2 = \"up2\";\nexport const DOWN1 = \"down1\";\nexport const DOWN2 = \"down2\";\n\nconst decimalPattern = /^-?[0-9]*\\.[0-9]+$/;\n\nexport const stringIsValidInt = (val: string) =>\n parseInt(val, 10).toString() === val;\n\nexport const stringIsValidDecimal = (val: string) =>\n stringIsValidInt(val) || decimalPattern.test(val);\n\nexport const stringIsValidNumber = (val: string) =>\n stringIsValidInt(val) || stringIsValidDecimal(val);\n\nexport const numericTypeOfStringValue = (val: string) =>\n stringIsValidInt(val) ? \"int\" : stringIsValidDecimal(val) ? \"double\" : \"NaN\";\n\nexport const isValidNumber = (n: unknown): n is number =>\n typeof n === \"number\" && isFinite(n);\n\nconst EMPTY = {};\nexport const shallowEquals = (\n o1: { [key: string]: unknown } = EMPTY,\n o2: { [key: string]: unknown } = EMPTY,\n) => {\n const props1 = Object.keys(o1);\n const props2 = Object.keys(o2);\n return (\n props1.length === props2.length &&\n props1.every((key) => o1[key] === o2[key])\n );\n};\n\nexport function getMovingValueDirection(\n newValue?: number,\n direction?: valueChangeDirection,\n prevValue?: number,\n /** the number of decimal places to take into account when highlighting a change */\n decimalPlaces?: number,\n): valueChangeDirection {\n if (newValue === undefined) {\n return \"\";\n }\n if (\n !isFinite(newValue) ||\n prevValue === undefined ||\n direction === undefined\n ) {\n return \"\";\n } else {\n let diff = newValue - prevValue;\n if (diff) {\n // make sure there is still a diff when reduced to number of decimals to be displayed\n if (typeof decimalPlaces === \"number\") {\n diff =\n +newValue.toFixed(decimalPlaces) - +prevValue.toFixed(decimalPlaces);\n }\n }\n\n if (diff) {\n if (direction === \"\") {\n if (diff < 0) {\n return DOWN1;\n } else {\n return UP1;\n }\n } else if (diff > 0) {\n if (direction === DOWN1 || direction === DOWN2 || direction === UP2) {\n return UP1;\n } else {\n return UP2;\n }\n } else if (\n direction === UP1 ||\n direction === UP2 ||\n direction === DOWN2\n ) {\n return DOWN1;\n } else {\n return DOWN2;\n }\n } else {\n return \"\";\n }\n }\n}\n\n/**\n * Convert a value to integer.\n * If value is a number, remove any decimals.\n * If value is a string, parse as integer. If NaN,\n * return defaultValue else throw.\n * If value is integer numeric, return value.\n *\n * @param value\n * @param defaultValue\n * @returns\n */\nexport function asInteger(\n value: number | string | undefined,\n defaultValue?: number,\n): number {\n if (typeof value === \"number\") {\n return Number.isInteger(value)\n ? value\n : value < 0\n ? Math.ceil(value)\n : Math.floor(value);\n } else {\n const integerValue = parseInt(value ?? \"\");\n if (!isNaN(integerValue)) {\n return integerValue;\n } else if (typeof defaultValue === \"number\") {\n return defaultValue;\n }\n throw Error(`parseIndex invalid value ${value}`);\n }\n}\n\nexport const dataDescriptorTypeToVuuRowDataItemType = ({\n serverDataType = \"string\",\n}: DataValueDescriptor): \"string\" | \"number\" | \"boolean\" => {\n switch (serverDataType) {\n case \"double\":\n case \"int\":\n case \"long\":\n return \"number\";\n case \"boolean\":\n return \"boolean\";\n default:\n return \"string\";\n }\n};\n"],"names":[],"mappings":"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"}
@@ -69,7 +69,6 @@ class BaseDataSource extends eventEmitter.EventEmitter {
69
69
  filterSpec,
70
70
  viewport = this.viewport || (this.viewport = index.uuid())
71
71
  }, callback) {
72
- console.log(`[BaseDataSource] subscribe to ${this.viewport}`);
73
72
  this._clientCallback = callback;
74
73
  this.viewport = viewport;
75
74
  if (aggregations || baseFilterSpec || columns || filterSpec || groupBy || sort) {