@airtable/blocks 1.8.0 → 1.9.0-experimental
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/CHANGELOG.md +16 -2
- package/dist/cjs/error_utils.js +17 -0
- package/dist/cjs/models/base.js +16 -5
- package/dist/cjs/models/cursor.js +2 -0
- package/dist/cjs/models/field.js +146 -27
- package/dist/cjs/models/grouped_record_query_result.js +5 -14
- package/dist/cjs/models/linked_records_query_result.js +75 -27
- package/dist/cjs/models/mutation_constants.js +3 -1
- package/dist/cjs/models/mutations.js +67 -176
- package/dist/cjs/models/query_manager.js +327 -0
- package/dist/cjs/models/record.js +308 -55
- package/dist/cjs/models/record_query_result.js +4 -1
- package/dist/cjs/models/record_store.js +554 -765
- package/dist/cjs/models/table.js +22 -13
- package/dist/cjs/models/table_or_view_query_result.js +480 -414
- package/dist/cjs/models/view_data_store.js +243 -295
- package/dist/cjs/private_utils.js +50 -0
- package/dist/cjs/sdk.js +12 -2
- package/dist/cjs/testing/{mock_airtable_interface.js → abstract_mock_airtable_interface.js} +71 -22
- package/dist/cjs/types/block_query_spec.js +85 -0
- package/dist/cjs/types/mutations.js +1 -0
- package/dist/cjs/ui/icon_config.js +4 -2
- package/dist/cjs/ui/use_global_config.js +1 -1
- package/dist/cjs/ui/use_records.js +5 -1
- package/dist/cjs/unstable_testing_utils.js +2 -2
- package/dist/cjs/watchable.js +123 -71
- package/dist/types/src/models/base.d.ts +10 -3
- package/dist/types/src/models/base.d.ts.map +1 -1
- package/dist/types/src/models/cursor.d.ts +2 -0
- package/dist/types/src/models/cursor.d.ts.map +1 -1
- package/dist/types/src/models/field.d.ts +65 -1
- package/dist/types/src/models/field.d.ts.map +1 -1
- package/dist/types/src/models/grouped_record_query_result.d.ts +3 -3
- package/dist/types/src/models/grouped_record_query_result.d.ts.map +1 -1
- package/dist/types/src/models/linked_records_query_result.d.ts.map +1 -1
- package/dist/types/src/models/mutation_constants.d.ts +1 -0
- package/dist/types/src/models/mutation_constants.d.ts.map +1 -1
- package/dist/types/src/models/mutations.d.ts.map +1 -1
- package/dist/types/src/models/query_manager.d.ts +2 -0
- package/dist/types/src/models/query_manager.d.ts.map +1 -0
- package/dist/types/src/models/record.d.ts +12 -3
- package/dist/types/src/models/record.d.ts.map +1 -1
- package/dist/types/src/models/record_query_result.d.ts +3 -2
- package/dist/types/src/models/record_query_result.d.ts.map +1 -1
- package/dist/types/src/models/record_store.d.ts.map +1 -1
- package/dist/types/src/models/table.d.ts +8 -4
- package/dist/types/src/models/table.d.ts.map +1 -1
- package/dist/types/src/models/table_or_view_query_result.d.ts +3 -5
- package/dist/types/src/models/table_or_view_query_result.d.ts.map +1 -1
- package/dist/types/src/models/view_data_store.d.ts +0 -1
- package/dist/types/src/models/view_data_store.d.ts.map +1 -1
- package/dist/types/src/models/view_metadata_query_result.d.ts +1 -1
- package/dist/types/src/models/view_metadata_query_result.d.ts.map +1 -1
- package/dist/types/src/private_utils.d.ts +30 -1
- package/dist/types/src/private_utils.d.ts.map +1 -1
- package/dist/types/src/sdk.d.ts.map +1 -1
- package/dist/types/src/testing/{mock_airtable_interface.d.ts → abstract_mock_airtable_interface.d.ts} +20 -15
- package/dist/types/src/testing/abstract_mock_airtable_interface.d.ts.map +1 -0
- package/dist/types/src/types/airtable_interface.d.ts +43 -19
- package/dist/types/src/types/airtable_interface.d.ts.map +1 -1
- package/dist/types/src/types/block_query_spec.d.ts +139 -0
- package/dist/types/src/types/block_query_spec.d.ts.map +1 -0
- package/dist/types/src/types/field.d.ts +80 -44
- package/dist/types/src/types/field.d.ts.map +1 -1
- package/dist/types/src/types/mutations.d.ts +31 -3
- package/dist/types/src/types/mutations.d.ts.map +1 -1
- package/dist/types/src/types/table.d.ts +0 -2
- package/dist/types/src/types/table.d.ts.map +1 -1
- package/dist/types/src/types/view.d.ts +3 -8
- package/dist/types/src/types/view.d.ts.map +1 -1
- package/dist/types/src/ui/icon_config.d.ts +5 -3
- package/dist/types/src/ui/icon_config.d.ts.map +1 -1
- package/dist/types/src/ui/link.d.ts +1 -1
- package/dist/types/src/ui/link.d.ts.map +1 -1
- package/dist/types/src/ui/use_global_config.d.ts +1 -1
- package/dist/types/src/unstable_testing_utils.d.ts +1 -1
- package/dist/types/src/unstable_testing_utils.d.ts.map +1 -1
- package/dist/types/src/watchable.d.ts.map +1 -1
- package/dist/types/test/airtable_interface_mocks/fixture_data.d.ts +121 -0
- package/dist/types/test/airtable_interface_mocks/fixture_data.d.ts.map +1 -0
- package/dist/types/test/airtable_interface_mocks/linked_records.d.ts +2 -2
- package/dist/types/test/airtable_interface_mocks/linked_records.d.ts.map +1 -1
- package/dist/types/test/airtable_interface_mocks/{mock_airtable_interface_internal.d.ts → mock_airtable_interface.d.ts} +26 -18
- package/dist/types/test/airtable_interface_mocks/mock_airtable_interface.d.ts.map +1 -0
- package/dist/types/test/airtable_interface_mocks/mock_base_data_stores.d.ts +51 -0
- package/dist/types/test/airtable_interface_mocks/mock_base_data_stores.d.ts.map +1 -0
- package/dist/types/test/airtable_interface_mocks/project_tracker.d.ts +2 -2
- package/dist/types/test/airtable_interface_mocks/project_tracker.d.ts.map +1 -1
- package/dist/types/test/test_helpers.d.ts +2 -0
- package/dist/types/test/test_helpers.d.ts.map +1 -1
- package/package.json +3 -1
- package/dist/types/src/testing/mock_airtable_interface.d.ts.map +0 -1
- package/dist/types/test/airtable_interface_mocks/mock_airtable_interface_internal.d.ts.map +0 -1
|
@@ -2,13 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
4
|
|
|
5
|
-
require("core-js/modules/es.
|
|
6
|
-
|
|
7
|
-
require("core-js/modules/es.symbol.description");
|
|
8
|
-
|
|
9
|
-
require("core-js/modules/es.array.filter");
|
|
10
|
-
|
|
11
|
-
require("core-js/modules/es.array.iterator");
|
|
5
|
+
require("core-js/modules/es.array.find");
|
|
12
6
|
|
|
13
7
|
require("core-js/modules/es.array.map");
|
|
14
8
|
|
|
@@ -16,17 +10,17 @@ require("core-js/modules/es.array.slice");
|
|
|
16
10
|
|
|
17
11
|
require("core-js/modules/es.object.to-string");
|
|
18
12
|
|
|
13
|
+
require("core-js/modules/es.object.values");
|
|
14
|
+
|
|
19
15
|
require("core-js/modules/es.promise");
|
|
20
16
|
|
|
21
|
-
require("core-js/modules/web.dom-collections.
|
|
17
|
+
require("core-js/modules/web.dom-collections.for-each");
|
|
22
18
|
|
|
23
19
|
Object.defineProperty(exports, "__esModule", {
|
|
24
20
|
value: true
|
|
25
21
|
});
|
|
26
22
|
exports.default = exports.WatchableViewDataStoreKeys = void 0;
|
|
27
23
|
|
|
28
|
-
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
29
|
-
|
|
30
24
|
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
|
|
31
25
|
|
|
32
26
|
require("regenerator-runtime/runtime");
|
|
@@ -35,11 +29,9 @@ var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/cl
|
|
|
35
29
|
|
|
36
30
|
var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
|
|
37
31
|
|
|
38
|
-
var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized"));
|
|
39
|
-
|
|
40
32
|
var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
|
|
41
33
|
|
|
42
|
-
var
|
|
34
|
+
var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized"));
|
|
43
35
|
|
|
44
36
|
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
|
|
45
37
|
|
|
@@ -51,11 +43,12 @@ var _private_utils = require("../private_utils");
|
|
|
51
43
|
|
|
52
44
|
var _error_utils = require("../error_utils");
|
|
53
45
|
|
|
46
|
+
var _block_query_spec = require("../types/block_query_spec");
|
|
47
|
+
|
|
54
48
|
var _abstract_model_with_async_data = _interopRequireDefault(require("./abstract_model_with_async_data"));
|
|
55
49
|
|
|
56
50
|
var WatchableViewDataStoreKeys = Object.freeze({
|
|
57
51
|
visibleRecords: 'visibleRecords',
|
|
58
|
-
visibleRecordIds: 'visibleRecordIds',
|
|
59
52
|
groups: 'groups',
|
|
60
53
|
groupLevels: 'groupLevels',
|
|
61
54
|
recordColors: 'recordColors',
|
|
@@ -66,9 +59,11 @@ var WatchableViewDataStoreKeys = Object.freeze({
|
|
|
66
59
|
|
|
67
60
|
exports.WatchableViewDataStoreKeys = WatchableViewDataStoreKeys;
|
|
68
61
|
|
|
69
|
-
// ViewDataStore
|
|
62
|
+
// ViewDataStore manages loadable data for a specific view. That means the set of visible records,
|
|
70
63
|
// and field order/visibility information. View itself only contains core schema information. The
|
|
71
|
-
// data here doesn't belong in View as it's record data or conditionally loaded
|
|
64
|
+
// data here doesn't belong in View as it's record data or conditionally loaded and therefore
|
|
65
|
+
// loaded via queries (and therefore managed by publicAirtableInterface)
|
|
66
|
+
// TODO: (#proj-blocks-sdk-record-limits) Remove AbstractModelWithAsyncData
|
|
72
67
|
|
|
73
68
|
/** @internal */
|
|
74
69
|
var ViewDataStore =
|
|
@@ -80,11 +75,6 @@ function (_AbstractModelWithAsy) {
|
|
|
80
75
|
value: function _isWatchableKey(key) {
|
|
81
76
|
return (0, _private_utils.isEnumValue)(WatchableViewDataStoreKeys, key);
|
|
82
77
|
}
|
|
83
|
-
}, {
|
|
84
|
-
key: "_shouldLoadDataForKey",
|
|
85
|
-
value: function _shouldLoadDataForKey(key) {
|
|
86
|
-
return true;
|
|
87
|
-
}
|
|
88
78
|
}]);
|
|
89
79
|
|
|
90
80
|
function ViewDataStore(sdk, parentRecordStore, viewId) {
|
|
@@ -94,16 +84,38 @@ function (_AbstractModelWithAsy) {
|
|
|
94
84
|
_this = (0, _possibleConstructorReturn2.default)(this, (0, _getPrototypeOf2.default)(ViewDataStore).call(this, sdk, "".concat(viewId, "-ViewDataStore")));
|
|
95
85
|
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "viewId", void 0);
|
|
96
86
|
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "parentRecordStore", void 0);
|
|
97
|
-
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "
|
|
98
|
-
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "
|
|
87
|
+
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "_publicViewStore", void 0);
|
|
88
|
+
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "_queryManager", void 0);
|
|
89
|
+
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "_queryIdFromReferenceCountedLoadData", null);
|
|
99
90
|
_this.parentRecordStore = parentRecordStore;
|
|
100
|
-
_this.
|
|
101
|
-
_this._mostRecentTableLoadPromise = null;
|
|
91
|
+
_this._queryManager = sdk._queryManager;
|
|
102
92
|
_this.viewId = viewId;
|
|
93
|
+
|
|
94
|
+
var publicViewStore = _this.parentRecordStore._airtableInterface.getViewMetadataStoreIfExists(_this.parentRecordStore.tableId, viewId);
|
|
95
|
+
|
|
96
|
+
(0, _error_utils.invariant)(publicViewStore, 'PublicViewStore must exist for all valid viewIds');
|
|
97
|
+
_this._publicViewStore = publicViewStore;
|
|
103
98
|
return _this;
|
|
104
99
|
}
|
|
105
100
|
|
|
106
101
|
(0, _createClass2.default)(ViewDataStore, [{
|
|
102
|
+
key: "_assertExistsAndLoaded",
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* @internal
|
|
106
|
+
*/
|
|
107
|
+
value: function _assertExistsAndLoaded() {
|
|
108
|
+
// Access data in order to throw if the data has been deleted / isn't loaded
|
|
109
|
+
var data = this._dataOrNullIfDeleted; // Currently it is not possible for the ViewDataStore to spawn an error on deletion
|
|
110
|
+
// because the parent TableOrViewQueryResult or ViewMetadataQueryResult throw their own
|
|
111
|
+
// errors when the view is deleted.
|
|
112
|
+
// istanbul ignore if
|
|
113
|
+
|
|
114
|
+
if (data === null) {
|
|
115
|
+
throw this._spawnErrorForDeletion();
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}, {
|
|
107
119
|
key: "_onChangeIsDataLoaded",
|
|
108
120
|
value: function _onChangeIsDataLoaded() {// noop
|
|
109
121
|
}
|
|
@@ -111,212 +123,58 @@ function (_AbstractModelWithAsy) {
|
|
|
111
123
|
key: "__onDataDeletion",
|
|
112
124
|
value: function __onDataDeletion() {
|
|
113
125
|
this._forceUnload();
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
key: "loadDataAsync",
|
|
117
|
-
value: function loadDataAsync() {
|
|
118
|
-
var tableLoadPromise;
|
|
119
|
-
return _regenerator.default.async(function loadDataAsync$(_context) {
|
|
120
|
-
while (1) {
|
|
121
|
-
switch (_context.prev = _context.next) {
|
|
122
|
-
case 0:
|
|
123
|
-
// Override this method to also load table data.
|
|
124
|
-
// NOTE: it's important that we call loadDataAsync on the table here and not in
|
|
125
|
-
// _loadDataAsync since we want the retain counts for the view and table to increase/decrease
|
|
126
|
-
// in lock-step. If we load table data in _loadDataAsync, the table's retain
|
|
127
|
-
// count only increments some of the time, which leads to unexpected behavior.
|
|
128
|
-
tableLoadPromise = this.parentRecordStore.loadRecordMetadataAsync();
|
|
129
|
-
this._mostRecentTableLoadPromise = tableLoadPromise;
|
|
130
|
-
_context.next = 4;
|
|
131
|
-
return _regenerator.default.awrap((0, _get2.default)((0, _getPrototypeOf2.default)(ViewDataStore.prototype), "loadDataAsync", this).call(this));
|
|
132
|
-
|
|
133
|
-
case 4:
|
|
134
|
-
case "end":
|
|
135
|
-
return _context.stop();
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}, null, this);
|
|
126
|
+
|
|
127
|
+
this._queryManager.forceUnloadWatchesOnWatchableModel(this);
|
|
139
128
|
}
|
|
140
129
|
}, {
|
|
141
130
|
key: "_loadDataAsync",
|
|
142
131
|
value: function _loadDataAsync() {
|
|
143
|
-
var
|
|
144
|
-
|
|
145
|
-
return _regenerator.default.async(function _loadDataAsync$(_context2) {
|
|
132
|
+
var changedKeysOnLoad;
|
|
133
|
+
return _regenerator.default.async(function _loadDataAsync$(_context) {
|
|
146
134
|
while (1) {
|
|
147
|
-
switch (
|
|
135
|
+
switch (_context.prev = _context.next) {
|
|
148
136
|
case 0:
|
|
149
|
-
//
|
|
150
|
-
//
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
return _regenerator.default.awrap(
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
this._data.colorsByRecordId = viewData.colorsByRecordId;
|
|
165
|
-
|
|
166
|
-
if (!this._data.colorsByRecordId) {
|
|
167
|
-
_context2.next = 32;
|
|
168
|
-
break;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
_iteratorNormalCompletion = true;
|
|
172
|
-
_didIteratorError = false;
|
|
173
|
-
_iteratorError = undefined;
|
|
174
|
-
_context2.prev = 16;
|
|
175
|
-
|
|
176
|
-
for (_iterator = this.visibleRecords[Symbol.iterator](); !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
|
177
|
-
record = _step.value;
|
|
178
|
-
|
|
179
|
-
if ((0, _private_utils.has)(this._data.colorsByRecordId, record.id)) {
|
|
180
|
-
record.__triggerOnChangeForRecordColorInViewId(this.viewId);
|
|
137
|
+
// TODO: (#proj-blocks-sdk-record-limits) Do we want to remove this reference counting semantic?
|
|
138
|
+
// We can assume that each query is identical, but it might be helpful to have all queries be
|
|
139
|
+
// registered across the bridge so that we can track utilization.
|
|
140
|
+
(0, _error_utils.invariant)(this._queryIdFromReferenceCountedLoadData === null, 'Can not reissue an identical view data store query');
|
|
141
|
+
_context.next = 3;
|
|
142
|
+
return _regenerator.default.awrap(this._queryManager.fetchAndSubscribeToQueryAsync({
|
|
143
|
+
sourceType: _block_query_spec.BlockQuerySourceType.VIEW,
|
|
144
|
+
sourceTableId: this.parentRecordStore.tableId,
|
|
145
|
+
sourceViewId: this.viewId,
|
|
146
|
+
viewMetadataSelection: {
|
|
147
|
+
shouldIncludeVisibleRecordIds: true,
|
|
148
|
+
shouldIncludeFieldOrder: true,
|
|
149
|
+
shouldIncludeGroups: true,
|
|
150
|
+
shouldIncludeGroupingLevels: true,
|
|
151
|
+
shouldIncludeColorsForRecordId: true
|
|
181
152
|
}
|
|
182
|
-
}
|
|
153
|
+
}));
|
|
183
154
|
|
|
184
|
-
|
|
185
|
-
|
|
155
|
+
case 3:
|
|
156
|
+
this._queryIdFromReferenceCountedLoadData = _context.sent;
|
|
157
|
+
changedKeysOnLoad = Object.values(WatchableViewDataStoreKeys);
|
|
186
158
|
|
|
187
|
-
|
|
188
|
-
_context2.prev = 20;
|
|
189
|
-
_context2.t0 = _context2["catch"](16);
|
|
190
|
-
_didIteratorError = true;
|
|
191
|
-
_iteratorError = _context2.t0;
|
|
159
|
+
this._queryManager.onLoadKeys(this, changedKeysOnLoad);
|
|
192
160
|
|
|
193
|
-
|
|
194
|
-
_context2.prev = 24;
|
|
195
|
-
_context2.prev = 25;
|
|
161
|
+
return _context.abrupt("return", []);
|
|
196
162
|
|
|
197
|
-
|
|
198
|
-
_iterator.return();
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
case 27:
|
|
202
|
-
_context2.prev = 27;
|
|
203
|
-
|
|
204
|
-
if (!_didIteratorError) {
|
|
205
|
-
_context2.next = 30;
|
|
206
|
-
break;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
throw _iteratorError;
|
|
210
|
-
|
|
211
|
-
case 30:
|
|
212
|
-
return _context2.finish(27);
|
|
213
|
-
|
|
214
|
-
case 31:
|
|
215
|
-
return _context2.finish(24);
|
|
216
|
-
|
|
217
|
-
case 32:
|
|
218
|
-
return _context2.abrupt("return", [WatchableViewDataStoreKeys.visibleRecords, WatchableViewDataStoreKeys.visibleRecordIds, WatchableViewDataStoreKeys.allFieldIds, WatchableViewDataStoreKeys.groups, WatchableViewDataStoreKeys.groupLevels, WatchableViewDataStoreKeys.visibleFieldIds, WatchableViewDataStoreKeys.recordColors]);
|
|
219
|
-
|
|
220
|
-
case 33:
|
|
163
|
+
case 7:
|
|
221
164
|
case "end":
|
|
222
|
-
return
|
|
165
|
+
return _context.stop();
|
|
223
166
|
}
|
|
224
167
|
}
|
|
225
|
-
}, null, this
|
|
226
|
-
}
|
|
227
|
-
}, {
|
|
228
|
-
key: "unloadData",
|
|
229
|
-
value: function unloadData() {
|
|
230
|
-
// Override this method to also unload the table's data.
|
|
231
|
-
// NOTE: it's important that we do this here, since we want the view and table's
|
|
232
|
-
// retain counts to increment/decrement in lock-step. If we unload the table's
|
|
233
|
-
// data in _unloadData, it leads to unexpected behavior.
|
|
234
|
-
(0, _get2.default)((0, _getPrototypeOf2.default)(ViewDataStore.prototype), "unloadData", this).call(this);
|
|
235
|
-
this.parentRecordStore.unloadRecordMetadata();
|
|
168
|
+
}, null, this);
|
|
236
169
|
}
|
|
237
170
|
}, {
|
|
238
171
|
key: "_unloadData",
|
|
239
172
|
value: function _unloadData() {
|
|
240
|
-
this.
|
|
241
|
-
|
|
242
|
-
this._airtableInterface.unsubscribeFromViewData(this.parentRecordStore.tableId, this.viewId);
|
|
243
|
-
|
|
244
|
-
if (!this.isDeleted) {
|
|
245
|
-
this._data.visibleRecordIds = undefined;
|
|
246
|
-
this._data.groups = undefined;
|
|
247
|
-
this._data.colorsByRecordId = undefined;
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
}, {
|
|
251
|
-
key: "__generateChangesForParentTableAddMultipleRecords",
|
|
252
|
-
value: function __generateChangesForParentTableAddMultipleRecords(recordIds) {
|
|
253
|
-
var newVisibleRecordIds = [...this.visibleRecordIds, ...recordIds];
|
|
254
|
-
return [{
|
|
255
|
-
path: ['tablesById', this.parentRecordStore.tableId, 'viewsById', this.viewId, 'visibleRecordIds'],
|
|
256
|
-
value: newVisibleRecordIds
|
|
257
|
-
}];
|
|
258
|
-
}
|
|
259
|
-
}, {
|
|
260
|
-
key: "__generateChangesForParentTableDeleteMultipleRecords",
|
|
261
|
-
value: function __generateChangesForParentTableDeleteMultipleRecords(recordIds) {
|
|
262
|
-
var recordIdsToDeleteSet = {};
|
|
263
|
-
var _iteratorNormalCompletion2 = true;
|
|
264
|
-
var _didIteratorError2 = false;
|
|
265
|
-
var _iteratorError2 = undefined;
|
|
266
|
-
|
|
267
|
-
try {
|
|
268
|
-
for (var _iterator2 = recordIds[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
|
|
269
|
-
var recordId = _step2.value;
|
|
270
|
-
recordIdsToDeleteSet[recordId] = true;
|
|
271
|
-
}
|
|
272
|
-
} catch (err) {
|
|
273
|
-
_didIteratorError2 = true;
|
|
274
|
-
_iteratorError2 = err;
|
|
275
|
-
} finally {
|
|
276
|
-
try {
|
|
277
|
-
if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
|
|
278
|
-
_iterator2.return();
|
|
279
|
-
}
|
|
280
|
-
} finally {
|
|
281
|
-
if (_didIteratorError2) {
|
|
282
|
-
throw _iteratorError2;
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
var newVisibleRecordIds = this.visibleRecordIds.filter(recordId => !recordIdsToDeleteSet[recordId]);
|
|
288
|
-
var changePayload = [{
|
|
289
|
-
path: ['tablesById', this.parentRecordStore.tableId, 'viewsById', this.viewId, 'visibleRecordIds'],
|
|
290
|
-
value: newVisibleRecordIds
|
|
291
|
-
}];
|
|
292
|
-
|
|
293
|
-
if (this._data.groups) {
|
|
294
|
-
var newGroups = this.__recursivelyRemoveRecordsFromGroupsInPlace((0, _private_utils.cloneDeep)(this._data.groups), recordIdsToDeleteSet);
|
|
295
|
-
|
|
296
|
-
changePayload.push({
|
|
297
|
-
path: ['tablesById', this.parentRecordStore.tableId, 'viewsById', this.viewId, 'groups'],
|
|
298
|
-
value: newGroups
|
|
299
|
-
});
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
return changePayload;
|
|
303
|
-
}
|
|
304
|
-
}, {
|
|
305
|
-
key: "__recursivelyRemoveRecordsFromGroupsInPlace",
|
|
306
|
-
value: function __recursivelyRemoveRecordsFromGroupsInPlace(groups, recordIdsToDeleteSet) {
|
|
307
|
-
if (!groups || groups.length === 0) {
|
|
308
|
-
return groups;
|
|
309
|
-
}
|
|
173
|
+
(0, _error_utils.invariant)(this._queryIdFromReferenceCountedLoadData, 'Can not unsubscribe from a view store that is not subscribed');
|
|
310
174
|
|
|
311
|
-
|
|
312
|
-
if (group.visibleRecordIds) {
|
|
313
|
-
group.visibleRecordIds = group.visibleRecordIds.filter(id => !recordIdsToDeleteSet[id]);
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
this.__recursivelyRemoveRecordsFromGroupsInPlace(group.groups, recordIdsToDeleteSet);
|
|
175
|
+
this._queryManager.unsubscribeFromQueryId(this._queryIdFromReferenceCountedLoadData);
|
|
317
176
|
|
|
318
|
-
|
|
319
|
-
});
|
|
177
|
+
this._queryIdFromReferenceCountedLoadData = null;
|
|
320
178
|
}
|
|
321
179
|
/**
|
|
322
180
|
* The record IDs that are not filtered out of this view.
|
|
@@ -334,107 +192,187 @@ function (_AbstractModelWithAsy) {
|
|
|
334
192
|
* @param recordOrRecordId the record/record id to get the color for
|
|
335
193
|
*/
|
|
336
194
|
value: function getRecordColor(record) {
|
|
337
|
-
var _ref3, _this$_data$colorsByR;
|
|
338
|
-
|
|
339
195
|
(0, _error_utils.invariant)(this.isDataLoaded, 'View data is not loaded');
|
|
340
|
-
|
|
196
|
+
|
|
197
|
+
this._assertExistsAndLoaded();
|
|
198
|
+
|
|
199
|
+
return this._publicViewStore.getColorForRecordId(record.id);
|
|
341
200
|
}
|
|
342
201
|
}, {
|
|
343
|
-
key: "
|
|
344
|
-
value: function
|
|
345
|
-
|
|
346
|
-
this._onChange(WatchableViewDataStoreKeys.visibleRecords);
|
|
202
|
+
key: "_findBlockSubscriptionChangedMatchingSubscriptionChangeTypeForViewIfExists",
|
|
203
|
+
value: function _findBlockSubscriptionChangedMatchingSubscriptionChangeTypeForViewIfExists(changes, changeTypeToMatch) {
|
|
204
|
+
var _changes$find;
|
|
347
205
|
|
|
348
|
-
|
|
349
|
-
|
|
206
|
+
return (_changes$find = changes.find(change => change.type === changeTypeToMatch && change.tableId === this.parentRecordStore.tableId && change.viewId === this.viewId)) !== null && _changes$find !== void 0 ? _changes$find : null;
|
|
207
|
+
}
|
|
208
|
+
}, {
|
|
209
|
+
key: "_constructBlockQuerySpecForWatchableKey",
|
|
210
|
+
value: function _constructBlockQuerySpecForWatchableKey(key, callbackForRegistration, context) {
|
|
211
|
+
var querySpecOptions = {};
|
|
212
|
+
|
|
213
|
+
var wrappedCallbackForQueryChange = () => {
|
|
214
|
+
callbackForRegistration.call(context, this, key);
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
switch (key) {
|
|
218
|
+
case WatchableViewDataStoreKeys.visibleRecords:
|
|
219
|
+
querySpecOptions.shouldIncludeVisibleRecordIds = true;
|
|
220
|
+
break;
|
|
221
|
+
|
|
222
|
+
case WatchableViewDataStoreKeys.groups:
|
|
223
|
+
{
|
|
224
|
+
querySpecOptions.shouldIncludeGroups = true;
|
|
225
|
+
break;
|
|
226
|
+
}
|
|
350
227
|
|
|
351
|
-
|
|
352
|
-
|
|
228
|
+
case WatchableViewDataStoreKeys.groupLevels:
|
|
229
|
+
{
|
|
230
|
+
querySpecOptions.shouldIncludeGroupingLevels = true;
|
|
231
|
+
break;
|
|
232
|
+
}
|
|
353
233
|
|
|
234
|
+
case WatchableViewDataStoreKeys.recordColors:
|
|
235
|
+
{
|
|
236
|
+
querySpecOptions.shouldIncludeColorsForRecordId = true;
|
|
354
237
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
// change since we derive group information from the groupLevels (fieldId)
|
|
238
|
+
wrappedCallbackForQueryChange = changes => {
|
|
239
|
+
var recordColorsChange = this._findBlockSubscriptionChangedMatchingSubscriptionChangeTypeForViewIfExists(changes, _block_query_spec.BlockQuerySubscriptionChangeType.CHANGED_COLORS_BY_RECORD_ID_FOR_VIEW);
|
|
358
240
|
|
|
241
|
+
var recordIdsOrNull = null;
|
|
359
242
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
243
|
+
if (recordColorsChange) {
|
|
244
|
+
(0, _error_utils.invariant)(recordColorsChange.type === _block_query_spec.BlockQuerySubscriptionChangeType.CHANGED_COLORS_BY_RECORD_ID_FOR_VIEW, 'Invalid record colors change event');
|
|
245
|
+
recordIdsOrNull = recordColorsChange.recordIds;
|
|
246
|
+
} // We also always call this, even if no recordColors changed to closely mirror
|
|
247
|
+
// the old version of the SDK (https://github.com/Hyperbase/blocks-sdk/blob/8e3ac1a37be9c9850e64085975b102a483116080/packages/sdk/src/models/view_data_store.ts#L319-L361)
|
|
248
|
+
// In the future, this should not be the case (don't call callback if nothing changed)
|
|
363
249
|
|
|
364
|
-
if (dirtyPaths.groupLevels) {
|
|
365
|
-
this._onChange(WatchableViewDataStoreKeys.groupLevels);
|
|
366
|
-
}
|
|
367
250
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
// Checking isRecordMetadataLoaded fixes a timing issue:
|
|
373
|
-
// When a new table loads in liveapp, we'll receive the record
|
|
374
|
-
// colors before getting the response to our loadData call.
|
|
375
|
-
// This is a temporary fix: we need a more general solution to
|
|
376
|
-
// avoid processing events associated with subscriptions whose
|
|
377
|
-
// data we haven't received yet.
|
|
378
|
-
if (this.parentRecordStore.isRecordMetadataLoaded) {
|
|
379
|
-
var _iteratorNormalCompletion3 = true;
|
|
380
|
-
var _didIteratorError3 = false;
|
|
381
|
-
var _iteratorError3 = undefined;
|
|
382
|
-
|
|
383
|
-
try {
|
|
384
|
-
for (var _iterator3 = changedRecordIds[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
|
|
385
|
-
var recordId = _step3.value;
|
|
386
|
-
var record = this.parentRecordStore.getRecordByIdIfExists(recordId); // Similar to above, we could be receiving the change notification
|
|
387
|
-
// for a record color before receiving the new record itself.
|
|
388
|
-
|
|
389
|
-
if (record) {
|
|
390
|
-
record.__triggerOnChangeForRecordColorInViewId(this.viewId);
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
} catch (err) {
|
|
394
|
-
_didIteratorError3 = true;
|
|
395
|
-
_iteratorError3 = err;
|
|
396
|
-
} finally {
|
|
397
|
-
try {
|
|
398
|
-
if (!_iteratorNormalCompletion3 && _iterator3.return != null) {
|
|
399
|
-
_iterator3.return();
|
|
400
|
-
}
|
|
401
|
-
} finally {
|
|
402
|
-
if (_didIteratorError3) {
|
|
403
|
-
throw _iteratorError3;
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
}
|
|
251
|
+
callbackForRegistration.call(context, this, key, recordIdsOrNull);
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
break;
|
|
407
255
|
}
|
|
408
|
-
}
|
|
409
256
|
|
|
410
|
-
|
|
257
|
+
case WatchableViewDataStoreKeys.allFieldIds:
|
|
258
|
+
{
|
|
259
|
+
querySpecOptions.shouldIncludeFieldOrder = true;
|
|
260
|
+
break;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
case WatchableViewDataStoreKeys.visibleFieldIds:
|
|
264
|
+
{
|
|
265
|
+
// TODO: This will trigger even if fieldIds which aren't visible in the view change.
|
|
266
|
+
// This is NOT a regression, a fix would be to add an intermediate callback
|
|
267
|
+
// which swallows changes if the visible fieldOrder does not change.
|
|
268
|
+
querySpecOptions.shouldIncludeFieldOrder = true;
|
|
269
|
+
break;
|
|
270
|
+
}
|
|
271
|
+
// TypeScript ensures that key is of type never so we don't need to test this via istanbul
|
|
272
|
+
// istanbul ignore next
|
|
273
|
+
|
|
274
|
+
default:
|
|
275
|
+
throw (0, _error_utils.spawnExhaustiveSwitchError)(key);
|
|
411
276
|
}
|
|
277
|
+
|
|
278
|
+
return {
|
|
279
|
+
querySpecToSubscribeWith: {
|
|
280
|
+
sourceType: _block_query_spec.BlockQuerySourceType.VIEW,
|
|
281
|
+
sourceTableId: this.parentRecordStore.tableId,
|
|
282
|
+
sourceViewId: this.viewId,
|
|
283
|
+
viewMetadataSelection: querySpecOptions
|
|
284
|
+
},
|
|
285
|
+
wrappedCallbackForQueryChange
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Watching a key that needs to load data asynchronously will automatically
|
|
290
|
+
* cause the data to be fetched. Once the data is available, the callback
|
|
291
|
+
* will be called.
|
|
292
|
+
*
|
|
293
|
+
* @inheritdoc
|
|
294
|
+
*/
|
|
295
|
+
|
|
296
|
+
}, {
|
|
297
|
+
key: "watch",
|
|
298
|
+
value: function watch(keys, callbackForWatchKey, context) {
|
|
299
|
+
this._assertNotForceUnloaded();
|
|
300
|
+
|
|
301
|
+
var validKeys = this._getWatchableValidKeysOrThrow(keys, 'view watch');
|
|
302
|
+
|
|
303
|
+
validKeys.forEach(validKey => {
|
|
304
|
+
var _this$_constructBlock = this._constructBlockQuerySpecForWatchableKey(validKey, callbackForWatchKey, context),
|
|
305
|
+
querySpecToSubscribeWith = _this$_constructBlock.querySpecToSubscribeWith,
|
|
306
|
+
wrappedCallbackForQueryChange = _this$_constructBlock.wrappedCallbackForQueryChange;
|
|
307
|
+
|
|
308
|
+
this._queryManager.watchWithQuerySpec(querySpecToSubscribeWith, this, validKey, wrappedCallbackForQueryChange, callbackForWatchKey, context);
|
|
309
|
+
});
|
|
310
|
+
return validKeys;
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Unwatching a key that needs to load data asynchronously will automatically
|
|
314
|
+
* cause the data to be released. Once the data is available, the callback
|
|
315
|
+
* will be called.
|
|
316
|
+
*
|
|
317
|
+
* @inheritdoc
|
|
318
|
+
*/
|
|
319
|
+
|
|
320
|
+
}, {
|
|
321
|
+
key: "unwatch",
|
|
322
|
+
value: function unwatch(keys, callbackForRegistration, context) {
|
|
323
|
+
// We have already unsubscribed from all watches (because query-based watches force data to be loaded)
|
|
324
|
+
// so no watches are subscribed
|
|
325
|
+
if (this._isForceUnloaded) {
|
|
326
|
+
return [];
|
|
327
|
+
} // We warn instead of throw here because we used to warn instead of throw and don't
|
|
328
|
+
// want to make a breaking change.
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
var validKeys = this._getWatchableValidKeysOrThrow(keys, 'view unwatch', true);
|
|
332
|
+
|
|
333
|
+
validKeys.forEach(key => this._queryManager.unwatchFromQueryKey(key, callbackForRegistration, context));
|
|
334
|
+
return validKeys;
|
|
335
|
+
}
|
|
336
|
+
}, {
|
|
337
|
+
key: "triggerOnChangeForDirtyPaths",
|
|
338
|
+
value: function triggerOnChangeForDirtyPaths(dirtyPaths) {// This is only triggered for changes to values in the type ViewData, which is
|
|
339
|
+
// populated and kept up to date by watching base schema (aka the view's id, name, type).
|
|
340
|
+
// None of these are watchable, so we don't need to call this._onChange() for them.
|
|
341
|
+
// In the future we may want to make the view's name watchable, which is the only property
|
|
342
|
+
// here that we'd expect to change. In this case, it would be handled here.
|
|
412
343
|
}
|
|
413
344
|
}, {
|
|
414
345
|
key: "_dataOrNullIfDeleted",
|
|
415
346
|
get: function get() {
|
|
416
|
-
var
|
|
347
|
+
var _ref;
|
|
417
348
|
|
|
418
349
|
var tableData = this._baseData.tablesById[this.parentRecordStore.tableId];
|
|
419
|
-
return (
|
|
350
|
+
return (_ref = tableData === null || tableData === void 0 ? void 0 : tableData.viewsById[this.viewId]) !== null && _ref !== void 0 ? _ref : null;
|
|
420
351
|
}
|
|
421
352
|
}, {
|
|
422
353
|
key: "isDataLoaded",
|
|
423
354
|
get: function get() {
|
|
424
|
-
return this._isDataLoaded
|
|
355
|
+
return this._isDataLoaded;
|
|
356
|
+
}
|
|
357
|
+
}, {
|
|
358
|
+
key: "isRecordDataLoadedForView",
|
|
359
|
+
get: function get() {
|
|
360
|
+
// We _currently_ only issue queries that also load cell data in the view which
|
|
361
|
+
// is synchronously returned with all other view data, so we can collapse this
|
|
362
|
+
// to if the viewData has loaded.
|
|
363
|
+
// TODO: (#proj-blocks-sdk-record-limits) Actually track if all cell data is loaded
|
|
364
|
+
// based on issued queries from ViewDataStore
|
|
365
|
+
return this.isDataLoaded;
|
|
425
366
|
}
|
|
426
367
|
}, {
|
|
427
368
|
key: "visibleRecordIds",
|
|
428
369
|
get: function get() {
|
|
429
|
-
|
|
430
|
-
(0, _error_utils.invariant)(visibleRecordIds, 'View data is not loaded'); // Freeze visibleRecordIds so users can't mutate it.
|
|
431
|
-
// If it changes from liveapp, we get an entire new array which will
|
|
432
|
-
// replace this one, so it's okay to freeze it.
|
|
370
|
+
this._assertExistsAndLoaded(); // Freezing the visibleRecordIds happens on the other side of the bridge
|
|
433
371
|
|
|
434
|
-
if (!Object.isFrozen(visibleRecordIds)) {
|
|
435
|
-
Object.freeze(visibleRecordIds);
|
|
436
|
-
}
|
|
437
372
|
|
|
373
|
+
var visibleRecordIds = this._publicViewStore.getVisibleRecordIds();
|
|
374
|
+
|
|
375
|
+
(0, _error_utils.invariant)(visibleRecordIds, 'View data is not loaded');
|
|
438
376
|
return visibleRecordIds;
|
|
439
377
|
}
|
|
440
378
|
/**
|
|
@@ -446,8 +384,12 @@ function (_AbstractModelWithAsy) {
|
|
|
446
384
|
}, {
|
|
447
385
|
key: "visibleRecords",
|
|
448
386
|
get: function get() {
|
|
449
|
-
(0, _error_utils.invariant)(this.
|
|
450
|
-
|
|
387
|
+
(0, _error_utils.invariant)(this.isRecordDataLoadedForView, 'Table data is not loaded for this view');
|
|
388
|
+
|
|
389
|
+
this._assertExistsAndLoaded();
|
|
390
|
+
|
|
391
|
+
var visibleRecordIds = this._publicViewStore.getVisibleRecordIds();
|
|
392
|
+
|
|
451
393
|
(0, _error_utils.invariant)(visibleRecordIds, 'View data is not loaded');
|
|
452
394
|
return visibleRecordIds.map(recordId => {
|
|
453
395
|
var record = this.parentRecordStore.getRecordByIdIfExists(recordId);
|
|
@@ -466,9 +408,9 @@ function (_AbstractModelWithAsy) {
|
|
|
466
408
|
}, {
|
|
467
409
|
key: "groups",
|
|
468
410
|
get: function get() {
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
return
|
|
411
|
+
this._assertExistsAndLoaded();
|
|
412
|
+
|
|
413
|
+
return this._publicViewStore.getGroups();
|
|
472
414
|
}
|
|
473
415
|
/**
|
|
474
416
|
* Gets the group config for this view, can be watched to know when groupLevels
|
|
@@ -478,23 +420,29 @@ function (_AbstractModelWithAsy) {
|
|
|
478
420
|
}, {
|
|
479
421
|
key: "groupLevels",
|
|
480
422
|
get: function get() {
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
return
|
|
423
|
+
this._assertExistsAndLoaded();
|
|
424
|
+
|
|
425
|
+
return this._publicViewStore.getGroupLevels();
|
|
484
426
|
}
|
|
485
427
|
}, {
|
|
486
428
|
key: "allFieldIds",
|
|
487
429
|
get: function get() {
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
430
|
+
this._assertExistsAndLoaded(); // TODO: (#proj-blocks-sdk-record-limits) Future sdk version shouldn't deep
|
|
431
|
+
// copy this, and it should be legal to return the frozen object directly
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
return (0, _private_utils.cloneDeep)(this._publicViewStore.getFieldOrder().fieldIds);
|
|
491
435
|
}
|
|
492
436
|
}, {
|
|
493
437
|
key: "visibleFieldIds",
|
|
494
438
|
get: function get() {
|
|
495
|
-
|
|
439
|
+
this._assertExistsAndLoaded();
|
|
440
|
+
|
|
441
|
+
var fieldOrder = this._publicViewStore.getFieldOrder();
|
|
442
|
+
|
|
496
443
|
(0, _error_utils.invariant)(fieldOrder, 'View data is not loaded');
|
|
497
|
-
var fieldIds = fieldOrder.fieldIds;
|
|
444
|
+
var fieldIds = fieldOrder.fieldIds; // Slice returns a mutable copy even though visibleFieldCount is readonly
|
|
445
|
+
|
|
498
446
|
return fieldIds.slice(0, fieldOrder.visibleFieldCount);
|
|
499
447
|
}
|
|
500
448
|
}]);
|