@atlaskit/editor-synced-block-provider 2.15.4 → 2.15.6
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 +19 -0
- package/dist/cjs/index.js +6 -7
- package/dist/cjs/providers/block-service/blockServiceAPI.js +2 -1
- package/dist/cjs/providers/syncBlockProvider.js +16 -10
- package/dist/cjs/store-manager/referenceSyncBlockStoreManager.js +49 -31
- package/dist/cjs/store-manager/sourceSyncBlockStoreManager.js +10 -3
- package/dist/cjs/store-manager/syncBlockStoreManager.js +9 -2
- package/dist/es2019/index.js +3 -2
- package/dist/es2019/providers/block-service/blockServiceAPI.js +3 -2
- package/dist/es2019/providers/syncBlockProvider.js +11 -9
- package/dist/es2019/store-manager/referenceSyncBlockStoreManager.js +34 -16
- package/dist/es2019/store-manager/sourceSyncBlockStoreManager.js +10 -3
- package/dist/es2019/store-manager/syncBlockStoreManager.js +8 -1
- package/dist/esm/index.js +3 -2
- package/dist/esm/providers/block-service/blockServiceAPI.js +2 -1
- package/dist/esm/providers/syncBlockProvider.js +16 -10
- package/dist/esm/store-manager/referenceSyncBlockStoreManager.js +49 -31
- package/dist/esm/store-manager/sourceSyncBlockStoreManager.js +10 -3
- package/dist/esm/store-manager/syncBlockStoreManager.js +8 -1
- package/dist/types/index.d.ts +2 -2
- package/dist/types/providers/syncBlockProvider.d.ts +2 -1
- package/dist/types/providers/types.d.ts +1 -0
- package/dist/types/store-manager/referenceSyncBlockStoreManager.d.ts +4 -3
- package/dist/types/store-manager/syncBlockStoreManager.d.ts +1 -0
- package/dist/types-ts4.5/index.d.ts +2 -2
- package/dist/types-ts4.5/providers/syncBlockProvider.d.ts +2 -1
- package/dist/types-ts4.5/providers/types.d.ts +1 -0
- package/dist/types-ts4.5/store-manager/referenceSyncBlockStoreManager.d.ts +4 -3
- package/dist/types-ts4.5/store-manager/syncBlockStoreManager.d.ts +1 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @atlaskit/editor-synced-block-provider
|
|
2
2
|
|
|
3
|
+
## 2.15.6
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`d40079fdeef5d`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/d40079fdeef5d) -
|
|
8
|
+
EDITOR-4044 Fix a race condition in source sync block dirty tracking logic
|
|
9
|
+
- [`267f0abf6b4cf`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/267f0abf6b4cf) -
|
|
10
|
+
EDITOR-4044 Fix a race condition in reference sync block dirty tracking logic
|
|
11
|
+
- Updated dependencies
|
|
12
|
+
|
|
13
|
+
## 2.15.5
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- [`a4ed9f55162ae`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/a4ed9f55162ae) -
|
|
18
|
+
EDITOR-3960 Refactor Synced Blocks initialization to remove multiple re-renders and duplicated
|
|
19
|
+
fetches
|
|
20
|
+
- Updated dependencies
|
|
21
|
+
|
|
3
22
|
## 2.15.4
|
|
4
23
|
|
|
5
24
|
### Patch Changes
|
package/dist/cjs/index.js
CHANGED
|
@@ -3,12 +3,6 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
Object.defineProperty(exports, "ReferenceSyncBlockStoreManager", {
|
|
7
|
-
enumerable: true,
|
|
8
|
-
get: function get() {
|
|
9
|
-
return _referenceSyncBlockStoreManager.ReferenceSyncBlockStoreManager;
|
|
10
|
-
}
|
|
11
|
-
});
|
|
12
6
|
Object.defineProperty(exports, "SyncBlockError", {
|
|
13
7
|
enumerable: true,
|
|
14
8
|
get: function get() {
|
|
@@ -171,6 +165,12 @@ Object.defineProperty(exports, "useMemoizedContentAPIProviders", {
|
|
|
171
165
|
return _confluenceContentAPI.useMemoizedContentAPIProviders;
|
|
172
166
|
}
|
|
173
167
|
});
|
|
168
|
+
Object.defineProperty(exports, "useMemoizedSyncBlockStoreManager", {
|
|
169
|
+
enumerable: true,
|
|
170
|
+
get: function get() {
|
|
171
|
+
return _syncBlockStoreManager.useMemoizedSyncBlockStoreManager;
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
174
|
Object.defineProperty(exports, "useMemoizedSyncedBlockProvider", {
|
|
175
175
|
enumerable: true,
|
|
176
176
|
get: function get() {
|
|
@@ -188,7 +188,6 @@ var _blockServiceAPI = require("./providers/block-service/blockServiceAPI");
|
|
|
188
188
|
var _confluenceContentAPI = require("./providers/confluence/confluenceContentAPI");
|
|
189
189
|
var _sourceInfo = require("./clients/confluence/sourceInfo");
|
|
190
190
|
var _syncBlockProvider = require("./providers/syncBlockProvider");
|
|
191
|
-
var _referenceSyncBlockStoreManager = require("./store-manager/referenceSyncBlockStoreManager");
|
|
192
191
|
var _syncBlockStoreManager = require("./store-manager/syncBlockStoreManager");
|
|
193
192
|
var _resolveSyncBlockInstance = require("./utils/resolveSyncBlockInstance");
|
|
194
193
|
var _utils = require("./utils/utils");
|
|
@@ -386,7 +386,8 @@ var BlockServiceADFWriteProvider = /*#__PURE__*/function () {
|
|
|
386
386
|
blockAri: (0, _ari.generateBlockAriFromReference)(_this.sourceAri, block.resourceId),
|
|
387
387
|
blockInstanceId: block.localId
|
|
388
388
|
};
|
|
389
|
-
},
|
|
389
|
+
}),
|
|
390
|
+
noContent: noContent
|
|
390
391
|
});
|
|
391
392
|
case 3:
|
|
392
393
|
return _context6.abrupt("return", {
|
|
@@ -32,7 +32,7 @@ var SyncBlockProvider = exports.SyncBlockProvider = /*#__PURE__*/function (_Sync
|
|
|
32
32
|
* @param sourceId
|
|
33
33
|
* @param nestedRendererDataProviders
|
|
34
34
|
*/
|
|
35
|
-
function SyncBlockProvider(fetchProvider, writeProvider, sourceId
|
|
35
|
+
function SyncBlockProvider(fetchProvider, writeProvider, sourceId) {
|
|
36
36
|
var _this;
|
|
37
37
|
(0, _classCallCheck2.default)(this, SyncBlockProvider);
|
|
38
38
|
_this = _callSuper(this, SyncBlockProvider);
|
|
@@ -40,11 +40,16 @@ var SyncBlockProvider = exports.SyncBlockProvider = /*#__PURE__*/function (_Sync
|
|
|
40
40
|
_this.fetchProvider = fetchProvider;
|
|
41
41
|
_this.writeProvider = writeProvider;
|
|
42
42
|
_this.sourceId = sourceId;
|
|
43
|
-
_this.providerOptions =
|
|
43
|
+
_this.providerOptions = {};
|
|
44
44
|
return _this;
|
|
45
45
|
}
|
|
46
46
|
(0, _inherits2.default)(SyncBlockProvider, _SyncBlockDataProvide);
|
|
47
47
|
return (0, _createClass2.default)(SyncBlockProvider, [{
|
|
48
|
+
key: "setProviderOptions",
|
|
49
|
+
value: function setProviderOptions(providerOptions) {
|
|
50
|
+
this.providerOptions = providerOptions;
|
|
51
|
+
}
|
|
52
|
+
}, {
|
|
48
53
|
key: "getProduct",
|
|
49
54
|
value: function getProduct() {
|
|
50
55
|
return this.writeProvider.product;
|
|
@@ -304,12 +309,13 @@ var SyncBlockProvider = exports.SyncBlockProvider = /*#__PURE__*/function (_Sync
|
|
|
304
309
|
}]);
|
|
305
310
|
}(_types2.SyncBlockDataProvider);
|
|
306
311
|
var useMemoizedSyncedBlockProvider = exports.useMemoizedSyncedBlockProvider = function useMemoizedSyncedBlockProvider(fetchProvider, writeProvider, sourceId, providerOptions, getSSRData) {
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
}
|
|
312
|
+
var syncBlockProvider = (0, _react.useMemo)(function () {
|
|
313
|
+
return new SyncBlockProvider(fetchProvider, writeProvider, sourceId);
|
|
314
|
+
}, [fetchProvider, writeProvider, sourceId]);
|
|
315
|
+
syncBlockProvider.setProviderOptions(providerOptions);
|
|
316
|
+
var ssrData = getSSRData ? getSSRData() : undefined;
|
|
317
|
+
if (ssrData) {
|
|
318
|
+
syncBlockProvider.setSSRData(ssrData);
|
|
319
|
+
}
|
|
320
|
+
return syncBlockProvider;
|
|
315
321
|
};
|
|
@@ -39,7 +39,8 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
|
|
|
39
39
|
this.subscriptions = new Map();
|
|
40
40
|
this.titleSubscriptions = new Map();
|
|
41
41
|
this.dataProvider = dataProvider;
|
|
42
|
-
this.
|
|
42
|
+
this.syncBlockFetchDataRequests = new Map();
|
|
43
|
+
this.syncBlockSourceInfoRequests = new Map();
|
|
43
44
|
this.providerFactories = new Map();
|
|
44
45
|
this.fireAnalyticsEvent = fireAnalyticsEvent;
|
|
45
46
|
}
|
|
@@ -160,7 +161,7 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
|
|
|
160
161
|
if (!resourceId || !this.dataProvider) {
|
|
161
162
|
throw new Error('Data provider or resourceId not set');
|
|
162
163
|
}
|
|
163
|
-
if (this.
|
|
164
|
+
if (this.syncBlockSourceInfoRequests.get(resourceId)) {
|
|
164
165
|
return;
|
|
165
166
|
}
|
|
166
167
|
var existingSyncBlock = this.getFromCache(resourceId);
|
|
@@ -181,7 +182,7 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
|
|
|
181
182
|
(_this$fireAnalyticsEv2 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv2 === void 0 || _this$fireAnalyticsEv2.call(this, (0, _errorHandling.getSourceInfoErrorPayload)('SourceAri, product or blockInstanceId missing'));
|
|
182
183
|
return;
|
|
183
184
|
}
|
|
184
|
-
this.
|
|
185
|
+
this.syncBlockSourceInfoRequests.set(resourceId, true);
|
|
185
186
|
this.dataProvider.fetchSyncBlockSourceInfo(blockInstanceId, sourceAri, product, this.fireAnalyticsEvent).then(function (sourceInfo) {
|
|
186
187
|
if (!sourceInfo) {
|
|
187
188
|
return;
|
|
@@ -194,7 +195,7 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
|
|
|
194
195
|
var _this$fireAnalyticsEv3;
|
|
195
196
|
(_this$fireAnalyticsEv3 = _this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv3 === void 0 || _this$fireAnalyticsEv3.call(_this, (0, _errorHandling.getSourceInfoErrorPayload)(error.message));
|
|
196
197
|
}).finally(function () {
|
|
197
|
-
_this.
|
|
198
|
+
_this.syncBlockSourceInfoRequests.delete(resourceId);
|
|
198
199
|
});
|
|
199
200
|
} catch (error) {
|
|
200
201
|
var _this$fireAnalyticsEv4;
|
|
@@ -215,7 +216,7 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
|
|
|
215
216
|
value: (function () {
|
|
216
217
|
var _fetchSyncBlocksData = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2(syncBlockNodes) {
|
|
217
218
|
var _this2 = this;
|
|
218
|
-
var nodesToFetch,
|
|
219
|
+
var nodesToFetch, data, resolvedData;
|
|
219
220
|
return _regenerator.default.wrap(function _callee2$(_context3) {
|
|
220
221
|
while (1) switch (_context3.prev = _context3.next) {
|
|
221
222
|
case 0:
|
|
@@ -223,7 +224,7 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
|
|
|
223
224
|
_context3.next = 2;
|
|
224
225
|
break;
|
|
225
226
|
}
|
|
226
|
-
return _context3.abrupt("return"
|
|
227
|
+
return _context3.abrupt("return");
|
|
227
228
|
case 2:
|
|
228
229
|
if (this.dataProvider) {
|
|
229
230
|
_context3.next = 4;
|
|
@@ -232,18 +233,27 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
|
|
|
232
233
|
throw new Error('Data provider not set');
|
|
233
234
|
case 4:
|
|
234
235
|
// Don't fetch for not_found error since the source is already deleted
|
|
235
|
-
nodesToFetch = []
|
|
236
|
+
nodesToFetch = [];
|
|
236
237
|
syncBlockNodes.forEach(function (node) {
|
|
238
|
+
if (_this2.syncBlockFetchDataRequests.get(node.attrs.resourceId)) {
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
237
241
|
var existingSyncBlock = _this2.getFromCache(node.attrs.resourceId);
|
|
238
242
|
if ((existingSyncBlock === null || existingSyncBlock === void 0 ? void 0 : existingSyncBlock.error) === _types.SyncBlockError.NotFound) {
|
|
239
|
-
|
|
240
|
-
} else {
|
|
241
|
-
nodesToFetch.push(node);
|
|
243
|
+
return;
|
|
242
244
|
}
|
|
245
|
+
nodesToFetch.push(node);
|
|
243
246
|
});
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
+
nodesToFetch.forEach(function (node) {
|
|
248
|
+
_this2.syncBlockFetchDataRequests.set(node.attrs.resourceId, true);
|
|
249
|
+
});
|
|
250
|
+
_context3.next = 9;
|
|
251
|
+
return this.dataProvider.fetchNodesData(nodesToFetch).finally(function () {
|
|
252
|
+
nodesToFetch.forEach(function (node) {
|
|
253
|
+
_this2.syncBlockFetchDataRequests.delete(node.attrs.resourceId);
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
case 9:
|
|
247
257
|
data = _context3.sent;
|
|
248
258
|
resolvedData = [];
|
|
249
259
|
data.forEach(function (syncBlockInstance) {
|
|
@@ -263,7 +273,6 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
|
|
|
263
273
|
}
|
|
264
274
|
_this2.fetchSyncBlockSourceInfo(resolvedSyncBlockInstance.resourceId);
|
|
265
275
|
});
|
|
266
|
-
return _context3.abrupt("return", [].concat(resolvedData, blocksWithNotFoundError));
|
|
267
276
|
case 12:
|
|
268
277
|
case "end":
|
|
269
278
|
return _context3.stop();
|
|
@@ -527,7 +536,7 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
|
|
|
527
536
|
|
|
528
537
|
/**
|
|
529
538
|
* Update reference synced blocks on the document with the BE
|
|
530
|
-
*
|
|
539
|
+
*
|
|
531
540
|
* @returns true if the reference synced blocks are updated successfully, false otherwise
|
|
532
541
|
*/
|
|
533
542
|
}, {
|
|
@@ -565,42 +574,50 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
|
|
|
565
574
|
});
|
|
566
575
|
});
|
|
567
576
|
if (!(blocks.length === 0)) {
|
|
568
|
-
_context4.next =
|
|
577
|
+
_context4.next = 11;
|
|
569
578
|
break;
|
|
570
579
|
}
|
|
580
|
+
this.isCacheDirty = false;
|
|
571
581
|
return _context4.abrupt("return", true);
|
|
572
|
-
case
|
|
573
|
-
|
|
582
|
+
case 11:
|
|
583
|
+
// reset isCacheDirty early to prevent race condition
|
|
584
|
+
// There is a race condition where if a user makes changes (create/delete) to a reference sync block
|
|
585
|
+
// on a live page and the reference sync block is being saved while the user
|
|
586
|
+
// is still making changes, the new changes might not be saved if they all happen
|
|
587
|
+
// exactly at a time when the updateReferenceData is being executed asynchronously.
|
|
588
|
+
this.isCacheDirty = false;
|
|
589
|
+
_context4.next = 14;
|
|
574
590
|
return this.dataProvider.updateReferenceData(blocks);
|
|
575
|
-
case
|
|
591
|
+
case 14:
|
|
576
592
|
updateResult = _context4.sent;
|
|
577
593
|
if (!updateResult.success) {
|
|
578
594
|
success = false;
|
|
579
595
|
(_this$fireAnalyticsEv9 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv9 === void 0 || _this$fireAnalyticsEv9.call(this, (0, _errorHandling.updateReferenceErrorPayload)(updateResult.error || 'Failed to update reference synced blocks on the document'));
|
|
580
596
|
}
|
|
581
|
-
_context4.next =
|
|
597
|
+
_context4.next = 23;
|
|
582
598
|
break;
|
|
583
|
-
case
|
|
584
|
-
_context4.prev =
|
|
599
|
+
case 18:
|
|
600
|
+
_context4.prev = 18;
|
|
585
601
|
_context4.t0 = _context4["catch"](3);
|
|
586
602
|
success = false;
|
|
587
603
|
(0, _monitoring.logException)(_context4.t0, {
|
|
588
604
|
location: 'editor-synced-block-provider/referenceSyncBlockStoreManager'
|
|
589
605
|
});
|
|
590
606
|
(_this$fireAnalyticsEv0 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv0 === void 0 || _this$fireAnalyticsEv0.call(this, (0, _errorHandling.updateReferenceErrorPayload)(_context4.t0.message));
|
|
591
|
-
case
|
|
592
|
-
_context4.prev =
|
|
593
|
-
if (success) {
|
|
594
|
-
|
|
607
|
+
case 23:
|
|
608
|
+
_context4.prev = 23;
|
|
609
|
+
if (!success) {
|
|
610
|
+
// set isCacheDirty back to true for cases where it failed to update the reference synced blocks on the BE
|
|
611
|
+
this.isCacheDirty = true;
|
|
595
612
|
}
|
|
596
|
-
return _context4.finish(
|
|
597
|
-
case
|
|
613
|
+
return _context4.finish(23);
|
|
614
|
+
case 26:
|
|
598
615
|
return _context4.abrupt("return", success);
|
|
599
|
-
case
|
|
616
|
+
case 27:
|
|
600
617
|
case "end":
|
|
601
618
|
return _context4.stop();
|
|
602
619
|
}
|
|
603
|
-
}, _callee3, this, [[3,
|
|
620
|
+
}, _callee3, this, [[3, 18, 23, 26]]);
|
|
604
621
|
}));
|
|
605
622
|
function flush() {
|
|
606
623
|
return _flush.apply(this, arguments);
|
|
@@ -614,7 +631,8 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
|
|
|
614
631
|
this.syncBlockCache.clear();
|
|
615
632
|
this.subscriptions.clear();
|
|
616
633
|
this.titleSubscriptions.clear();
|
|
617
|
-
this.
|
|
634
|
+
this.syncBlockFetchDataRequests.clear();
|
|
635
|
+
this.syncBlockSourceInfoRequests.clear();
|
|
618
636
|
this.providerFactories.clear();
|
|
619
637
|
this.isRefreshingSubscriptions = false;
|
|
620
638
|
this.providerFactories.forEach(function (providerFactory) {
|
|
@@ -109,6 +109,13 @@ var SourceSyncBlockStoreManager = exports.SourceSyncBlockStoreManager = /*#__PUR
|
|
|
109
109
|
}
|
|
110
110
|
});
|
|
111
111
|
bodiedSyncBlockData.push(syncBlockData);
|
|
112
|
+
|
|
113
|
+
// reset isDirty early to prevent race condition
|
|
114
|
+
// There is a race condition where if a user makes changes to a source sync block
|
|
115
|
+
// on a live page and the source sync block is being saved while the user
|
|
116
|
+
// is still making changes, the new changes might not be saved if they all happen
|
|
117
|
+
// exactly at a time when the writeNodesData is being executed asynchronously.
|
|
118
|
+
syncBlockData.isDirty = false;
|
|
112
119
|
}
|
|
113
120
|
});
|
|
114
121
|
if (!(bodiedSyncBlockNodes.length === 0)) {
|
|
@@ -122,11 +129,11 @@ var SourceSyncBlockStoreManager = exports.SourceSyncBlockStoreManager = /*#__PUR
|
|
|
122
129
|
case 10:
|
|
123
130
|
writeResults = _context.sent;
|
|
124
131
|
writeResults.forEach(function (result) {
|
|
125
|
-
// set isDirty to
|
|
126
|
-
if (result.resourceId &&
|
|
132
|
+
// set isDirty to true for cases where it failed to save the sync block to the BE
|
|
133
|
+
if (result.resourceId && result.error && result.error !== _types.SyncBlockError.NotFound) {
|
|
127
134
|
var cachedData = _this2.syncBlockCache.get(result.resourceId);
|
|
128
135
|
if (cachedData) {
|
|
129
|
-
cachedData.isDirty =
|
|
136
|
+
cachedData.isDirty = true;
|
|
130
137
|
}
|
|
131
138
|
}
|
|
132
139
|
});
|
|
@@ -4,9 +4,10 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
|
|
|
4
4
|
Object.defineProperty(exports, "__esModule", {
|
|
5
5
|
value: true
|
|
6
6
|
});
|
|
7
|
-
exports.SyncBlockStoreManager = void 0;
|
|
7
|
+
exports.useMemoizedSyncBlockStoreManager = exports.SyncBlockStoreManager = void 0;
|
|
8
8
|
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
|
|
9
9
|
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
|
|
10
|
+
var _react = require("react");
|
|
10
11
|
var _referenceSyncBlockStoreManager = require("./referenceSyncBlockStoreManager");
|
|
11
12
|
var _sourceSyncBlockStoreManager = require("./sourceSyncBlockStoreManager");
|
|
12
13
|
// A parent store manager responsible for the lifecycle and state management of sync blocks in an editor instance.
|
|
@@ -39,4 +40,10 @@ var SyncBlockStoreManager = exports.SyncBlockStoreManager = /*#__PURE__*/functio
|
|
|
39
40
|
this.sourceSyncBlockStoreManager.destroy();
|
|
40
41
|
}
|
|
41
42
|
}]);
|
|
42
|
-
}();
|
|
43
|
+
}();
|
|
44
|
+
var useMemoizedSyncBlockStoreManager = exports.useMemoizedSyncBlockStoreManager = function useMemoizedSyncBlockStoreManager(dataProvider, fireAnalyticsEvent) {
|
|
45
|
+
return (0, _react.useMemo)(function () {
|
|
46
|
+
var syncBlockStoreManager = new SyncBlockStoreManager(dataProvider, fireAnalyticsEvent);
|
|
47
|
+
return syncBlockStoreManager;
|
|
48
|
+
}, [dataProvider, fireAnalyticsEvent]);
|
|
49
|
+
};
|
package/dist/es2019/index.js
CHANGED
|
@@ -17,9 +17,10 @@ export { useMemoizedBlockServiceAPIProviders } from './providers/block-service/b
|
|
|
17
17
|
export { createContentAPIProvidersWithDefaultKey, useMemoizedContentAPIProviders } from './providers/confluence/confluenceContentAPI';
|
|
18
18
|
export { fetchConfluencePageInfo } from './clients/confluence/sourceInfo';
|
|
19
19
|
export { SyncBlockProvider as SyncedBlockProvider, useMemoizedSyncedBlockProvider } from './providers/syncBlockProvider';
|
|
20
|
+
|
|
20
21
|
// store managers
|
|
21
|
-
|
|
22
|
-
export { SyncBlockStoreManager } from './store-manager/syncBlockStoreManager';
|
|
22
|
+
|
|
23
|
+
export { SyncBlockStoreManager, useMemoizedSyncBlockStoreManager } from './store-manager/syncBlockStoreManager';
|
|
23
24
|
|
|
24
25
|
// utils
|
|
25
26
|
export { resolveSyncBlockInstance } from './utils/resolveSyncBlockInstance';
|
|
@@ -213,7 +213,7 @@ class BlockServiceADFWriteProvider {
|
|
|
213
213
|
} catch (error) {
|
|
214
214
|
if (error instanceof BlockError) {
|
|
215
215
|
if (error.status === 404) {
|
|
216
|
-
// User should not be blocked by not_found error when deleting,
|
|
216
|
+
// User should not be blocked by not_found error when deleting,
|
|
217
217
|
// hence returns successful result for 404 error
|
|
218
218
|
return {
|
|
219
219
|
resourceId,
|
|
@@ -248,7 +248,8 @@ class BlockServiceADFWriteProvider {
|
|
|
248
248
|
blocks: blocks.map(block => ({
|
|
249
249
|
blockAri: generateBlockAriFromReference(this.sourceAri, block.resourceId),
|
|
250
250
|
blockInstanceId: block.localId
|
|
251
|
-
}),
|
|
251
|
+
})),
|
|
252
|
+
noContent
|
|
252
253
|
});
|
|
253
254
|
return {
|
|
254
255
|
success: true
|
|
@@ -15,12 +15,15 @@ export class SyncBlockProvider extends SyncBlockDataProvider {
|
|
|
15
15
|
* @param sourceId
|
|
16
16
|
* @param nestedRendererDataProviders
|
|
17
17
|
*/
|
|
18
|
-
constructor(fetchProvider, writeProvider, sourceId
|
|
18
|
+
constructor(fetchProvider, writeProvider, sourceId) {
|
|
19
19
|
super();
|
|
20
20
|
_defineProperty(this, "name", 'syncBlockProvider');
|
|
21
21
|
this.fetchProvider = fetchProvider;
|
|
22
22
|
this.writeProvider = writeProvider;
|
|
23
23
|
this.sourceId = sourceId;
|
|
24
|
+
this.providerOptions = {};
|
|
25
|
+
}
|
|
26
|
+
setProviderOptions(providerOptions) {
|
|
24
27
|
this.providerOptions = providerOptions;
|
|
25
28
|
}
|
|
26
29
|
getProduct() {
|
|
@@ -205,12 +208,11 @@ export class SyncBlockProvider extends SyncBlockDataProvider {
|
|
|
205
208
|
}
|
|
206
209
|
}
|
|
207
210
|
export const useMemoizedSyncedBlockProvider = (fetchProvider, writeProvider, sourceId, providerOptions, getSSRData) => {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
}, [fetchProvider, writeProvider, sourceId, providerOptions, getSSRData]);
|
|
211
|
+
const syncBlockProvider = useMemo(() => new SyncBlockProvider(fetchProvider, writeProvider, sourceId), [fetchProvider, writeProvider, sourceId]);
|
|
212
|
+
syncBlockProvider.setProviderOptions(providerOptions);
|
|
213
|
+
const ssrData = getSSRData ? getSSRData() : undefined;
|
|
214
|
+
if (ssrData) {
|
|
215
|
+
syncBlockProvider.setSSRData(ssrData);
|
|
216
|
+
}
|
|
217
|
+
return syncBlockProvider;
|
|
216
218
|
};
|
|
@@ -22,7 +22,8 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
22
22
|
this.subscriptions = new Map();
|
|
23
23
|
this.titleSubscriptions = new Map();
|
|
24
24
|
this.dataProvider = dataProvider;
|
|
25
|
-
this.
|
|
25
|
+
this.syncBlockFetchDataRequests = new Map();
|
|
26
|
+
this.syncBlockSourceInfoRequests = new Map();
|
|
26
27
|
this.providerFactories = new Map();
|
|
27
28
|
this.fireAnalyticsEvent = fireAnalyticsEvent;
|
|
28
29
|
}
|
|
@@ -76,7 +77,7 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
76
77
|
if (!resourceId || !this.dataProvider) {
|
|
77
78
|
throw new Error('Data provider or resourceId not set');
|
|
78
79
|
}
|
|
79
|
-
if (this.
|
|
80
|
+
if (this.syncBlockSourceInfoRequests.get(resourceId)) {
|
|
80
81
|
return;
|
|
81
82
|
}
|
|
82
83
|
const existingSyncBlock = this.getFromCache(resourceId);
|
|
@@ -98,7 +99,7 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
98
99
|
(_this$fireAnalyticsEv2 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv2 === void 0 ? void 0 : _this$fireAnalyticsEv2.call(this, getSourceInfoErrorPayload('SourceAri, product or blockInstanceId missing'));
|
|
99
100
|
return;
|
|
100
101
|
}
|
|
101
|
-
this.
|
|
102
|
+
this.syncBlockSourceInfoRequests.set(resourceId, true);
|
|
102
103
|
this.dataProvider.fetchSyncBlockSourceInfo(blockInstanceId, sourceAri, product, this.fireAnalyticsEvent).then(sourceInfo => {
|
|
103
104
|
if (!sourceInfo) {
|
|
104
105
|
return;
|
|
@@ -111,7 +112,7 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
111
112
|
var _this$fireAnalyticsEv3;
|
|
112
113
|
(_this$fireAnalyticsEv3 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv3 === void 0 ? void 0 : _this$fireAnalyticsEv3.call(this, getSourceInfoErrorPayload(error.message));
|
|
113
114
|
}).finally(() => {
|
|
114
|
-
this.
|
|
115
|
+
this.syncBlockSourceInfoRequests.delete(resourceId);
|
|
115
116
|
});
|
|
116
117
|
} catch (error) {
|
|
117
118
|
var _this$fireAnalyticsEv4;
|
|
@@ -129,24 +130,32 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
129
130
|
*/
|
|
130
131
|
async fetchSyncBlocksData(syncBlockNodes) {
|
|
131
132
|
if (syncBlockNodes.length === 0) {
|
|
132
|
-
return
|
|
133
|
+
return;
|
|
133
134
|
}
|
|
134
135
|
if (!this.dataProvider) {
|
|
135
136
|
throw new Error('Data provider not set');
|
|
136
137
|
}
|
|
137
138
|
|
|
138
139
|
// Don't fetch for not_found error since the source is already deleted
|
|
139
|
-
const nodesToFetch = []
|
|
140
|
-
blocksWithNotFoundError = [];
|
|
140
|
+
const nodesToFetch = [];
|
|
141
141
|
syncBlockNodes.forEach(node => {
|
|
142
|
+
if (this.syncBlockFetchDataRequests.get(node.attrs.resourceId)) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
142
145
|
const existingSyncBlock = this.getFromCache(node.attrs.resourceId);
|
|
143
146
|
if ((existingSyncBlock === null || existingSyncBlock === void 0 ? void 0 : existingSyncBlock.error) === SyncBlockError.NotFound) {
|
|
144
|
-
|
|
145
|
-
} else {
|
|
146
|
-
nodesToFetch.push(node);
|
|
147
|
+
return;
|
|
147
148
|
}
|
|
149
|
+
nodesToFetch.push(node);
|
|
150
|
+
});
|
|
151
|
+
nodesToFetch.forEach(node => {
|
|
152
|
+
this.syncBlockFetchDataRequests.set(node.attrs.resourceId, true);
|
|
153
|
+
});
|
|
154
|
+
const data = await this.dataProvider.fetchNodesData(nodesToFetch).finally(() => {
|
|
155
|
+
nodesToFetch.forEach(node => {
|
|
156
|
+
this.syncBlockFetchDataRequests.delete(node.attrs.resourceId);
|
|
157
|
+
});
|
|
148
158
|
});
|
|
149
|
-
const data = await this.dataProvider.fetchNodesData(nodesToFetch);
|
|
150
159
|
const resolvedData = [];
|
|
151
160
|
data.forEach(syncBlockInstance => {
|
|
152
161
|
if (!syncBlockInstance.resourceId) {
|
|
@@ -165,7 +174,6 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
165
174
|
}
|
|
166
175
|
this.fetchSyncBlockSourceInfo(resolvedSyncBlockInstance.resourceId);
|
|
167
176
|
});
|
|
168
|
-
return [...resolvedData, ...blocksWithNotFoundError];
|
|
169
177
|
}
|
|
170
178
|
updateCacheWithSourceInfo(resourceId, sourceInfo) {
|
|
171
179
|
const existingSyncBlock = this.getFromCache(resourceId);
|
|
@@ -409,7 +417,7 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
409
417
|
|
|
410
418
|
/**
|
|
411
419
|
* Update reference synced blocks on the document with the BE
|
|
412
|
-
*
|
|
420
|
+
*
|
|
413
421
|
* @returns true if the reference synced blocks are updated successfully, false otherwise
|
|
414
422
|
*/
|
|
415
423
|
async flush() {
|
|
@@ -433,8 +441,16 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
433
441
|
});
|
|
434
442
|
});
|
|
435
443
|
if (blocks.length === 0) {
|
|
444
|
+
this.isCacheDirty = false;
|
|
436
445
|
return true;
|
|
437
446
|
}
|
|
447
|
+
|
|
448
|
+
// reset isCacheDirty early to prevent race condition
|
|
449
|
+
// There is a race condition where if a user makes changes (create/delete) to a reference sync block
|
|
450
|
+
// on a live page and the reference sync block is being saved while the user
|
|
451
|
+
// is still making changes, the new changes might not be saved if they all happen
|
|
452
|
+
// exactly at a time when the updateReferenceData is being executed asynchronously.
|
|
453
|
+
this.isCacheDirty = false;
|
|
438
454
|
const updateResult = await this.dataProvider.updateReferenceData(blocks);
|
|
439
455
|
if (!updateResult.success) {
|
|
440
456
|
var _this$fireAnalyticsEv10;
|
|
@@ -449,8 +465,9 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
449
465
|
});
|
|
450
466
|
(_this$fireAnalyticsEv11 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv11 === void 0 ? void 0 : _this$fireAnalyticsEv11.call(this, updateReferenceErrorPayload(error.message));
|
|
451
467
|
} finally {
|
|
452
|
-
if (success) {
|
|
453
|
-
|
|
468
|
+
if (!success) {
|
|
469
|
+
// set isCacheDirty back to true for cases where it failed to update the reference synced blocks on the BE
|
|
470
|
+
this.isCacheDirty = true;
|
|
454
471
|
}
|
|
455
472
|
}
|
|
456
473
|
return success;
|
|
@@ -460,7 +477,8 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
460
477
|
this.syncBlockCache.clear();
|
|
461
478
|
this.subscriptions.clear();
|
|
462
479
|
this.titleSubscriptions.clear();
|
|
463
|
-
this.
|
|
480
|
+
this.syncBlockFetchDataRequests.clear();
|
|
481
|
+
this.syncBlockSourceInfoRequests.clear();
|
|
464
482
|
this.providerFactories.clear();
|
|
465
483
|
this.isRefreshingSubscriptions = false;
|
|
466
484
|
this.providerFactories.forEach(providerFactory => {
|
|
@@ -82,6 +82,13 @@ export class SourceSyncBlockStoreManager {
|
|
|
82
82
|
}
|
|
83
83
|
});
|
|
84
84
|
bodiedSyncBlockData.push(syncBlockData);
|
|
85
|
+
|
|
86
|
+
// reset isDirty early to prevent race condition
|
|
87
|
+
// There is a race condition where if a user makes changes to a source sync block
|
|
88
|
+
// on a live page and the source sync block is being saved while the user
|
|
89
|
+
// is still making changes, the new changes might not be saved if they all happen
|
|
90
|
+
// exactly at a time when the writeNodesData is being executed asynchronously.
|
|
91
|
+
syncBlockData.isDirty = false;
|
|
85
92
|
}
|
|
86
93
|
});
|
|
87
94
|
if (bodiedSyncBlockNodes.length === 0) {
|
|
@@ -89,11 +96,11 @@ export class SourceSyncBlockStoreManager {
|
|
|
89
96
|
}
|
|
90
97
|
const writeResults = await this.dataProvider.writeNodesData(bodiedSyncBlockNodes, bodiedSyncBlockData);
|
|
91
98
|
writeResults.forEach(result => {
|
|
92
|
-
// set isDirty to
|
|
93
|
-
if (result.resourceId &&
|
|
99
|
+
// set isDirty to true for cases where it failed to save the sync block to the BE
|
|
100
|
+
if (result.resourceId && result.error && result.error !== SyncBlockError.NotFound) {
|
|
94
101
|
const cachedData = this.syncBlockCache.get(result.resourceId);
|
|
95
102
|
if (cachedData) {
|
|
96
|
-
cachedData.isDirty =
|
|
103
|
+
cachedData.isDirty = true;
|
|
97
104
|
}
|
|
98
105
|
}
|
|
99
106
|
});
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
1
2
|
import { ReferenceSyncBlockStoreManager } from './referenceSyncBlockStoreManager';
|
|
2
3
|
import { SourceSyncBlockStoreManager } from './sourceSyncBlockStoreManager';
|
|
3
4
|
|
|
@@ -23,4 +24,10 @@ export class SyncBlockStoreManager {
|
|
|
23
24
|
this.referenceSyncBlockStoreManager.destroy();
|
|
24
25
|
this.sourceSyncBlockStoreManager.destroy();
|
|
25
26
|
}
|
|
26
|
-
}
|
|
27
|
+
}
|
|
28
|
+
export const useMemoizedSyncBlockStoreManager = (dataProvider, fireAnalyticsEvent) => {
|
|
29
|
+
return useMemo(() => {
|
|
30
|
+
const syncBlockStoreManager = new SyncBlockStoreManager(dataProvider, fireAnalyticsEvent);
|
|
31
|
+
return syncBlockStoreManager;
|
|
32
|
+
}, [dataProvider, fireAnalyticsEvent]);
|
|
33
|
+
};
|
package/dist/esm/index.js
CHANGED
|
@@ -17,9 +17,10 @@ export { useMemoizedBlockServiceAPIProviders } from './providers/block-service/b
|
|
|
17
17
|
export { createContentAPIProvidersWithDefaultKey, useMemoizedContentAPIProviders } from './providers/confluence/confluenceContentAPI';
|
|
18
18
|
export { fetchConfluencePageInfo } from './clients/confluence/sourceInfo';
|
|
19
19
|
export { SyncBlockProvider as SyncedBlockProvider, useMemoizedSyncedBlockProvider } from './providers/syncBlockProvider';
|
|
20
|
+
|
|
20
21
|
// store managers
|
|
21
|
-
|
|
22
|
-
export { SyncBlockStoreManager } from './store-manager/syncBlockStoreManager';
|
|
22
|
+
|
|
23
|
+
export { SyncBlockStoreManager, useMemoizedSyncBlockStoreManager } from './store-manager/syncBlockStoreManager';
|
|
23
24
|
|
|
24
25
|
// utils
|
|
25
26
|
export { resolveSyncBlockInstance } from './utils/resolveSyncBlockInstance';
|
|
@@ -378,7 +378,8 @@ var BlockServiceADFWriteProvider = /*#__PURE__*/function () {
|
|
|
378
378
|
blockAri: generateBlockAriFromReference(_this.sourceAri, block.resourceId),
|
|
379
379
|
blockInstanceId: block.localId
|
|
380
380
|
};
|
|
381
|
-
},
|
|
381
|
+
}),
|
|
382
|
+
noContent: noContent
|
|
382
383
|
});
|
|
383
384
|
case 3:
|
|
384
385
|
return _context6.abrupt("return", {
|
|
@@ -25,7 +25,7 @@ export var SyncBlockProvider = /*#__PURE__*/function (_SyncBlockDataProvide) {
|
|
|
25
25
|
* @param sourceId
|
|
26
26
|
* @param nestedRendererDataProviders
|
|
27
27
|
*/
|
|
28
|
-
function SyncBlockProvider(fetchProvider, writeProvider, sourceId
|
|
28
|
+
function SyncBlockProvider(fetchProvider, writeProvider, sourceId) {
|
|
29
29
|
var _this;
|
|
30
30
|
_classCallCheck(this, SyncBlockProvider);
|
|
31
31
|
_this = _callSuper(this, SyncBlockProvider);
|
|
@@ -33,11 +33,16 @@ export var SyncBlockProvider = /*#__PURE__*/function (_SyncBlockDataProvide) {
|
|
|
33
33
|
_this.fetchProvider = fetchProvider;
|
|
34
34
|
_this.writeProvider = writeProvider;
|
|
35
35
|
_this.sourceId = sourceId;
|
|
36
|
-
_this.providerOptions =
|
|
36
|
+
_this.providerOptions = {};
|
|
37
37
|
return _this;
|
|
38
38
|
}
|
|
39
39
|
_inherits(SyncBlockProvider, _SyncBlockDataProvide);
|
|
40
40
|
return _createClass(SyncBlockProvider, [{
|
|
41
|
+
key: "setProviderOptions",
|
|
42
|
+
value: function setProviderOptions(providerOptions) {
|
|
43
|
+
this.providerOptions = providerOptions;
|
|
44
|
+
}
|
|
45
|
+
}, {
|
|
41
46
|
key: "getProduct",
|
|
42
47
|
value: function getProduct() {
|
|
43
48
|
return this.writeProvider.product;
|
|
@@ -297,12 +302,13 @@ export var SyncBlockProvider = /*#__PURE__*/function (_SyncBlockDataProvide) {
|
|
|
297
302
|
}]);
|
|
298
303
|
}(SyncBlockDataProvider);
|
|
299
304
|
export var useMemoizedSyncedBlockProvider = function useMemoizedSyncedBlockProvider(fetchProvider, writeProvider, sourceId, providerOptions, getSSRData) {
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
}
|
|
305
|
+
var syncBlockProvider = useMemo(function () {
|
|
306
|
+
return new SyncBlockProvider(fetchProvider, writeProvider, sourceId);
|
|
307
|
+
}, [fetchProvider, writeProvider, sourceId]);
|
|
308
|
+
syncBlockProvider.setProviderOptions(providerOptions);
|
|
309
|
+
var ssrData = getSSRData ? getSSRData() : undefined;
|
|
310
|
+
if (ssrData) {
|
|
311
|
+
syncBlockProvider.setSSRData(ssrData);
|
|
312
|
+
}
|
|
313
|
+
return syncBlockProvider;
|
|
308
314
|
};
|
|
@@ -33,7 +33,8 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
33
33
|
this.subscriptions = new Map();
|
|
34
34
|
this.titleSubscriptions = new Map();
|
|
35
35
|
this.dataProvider = dataProvider;
|
|
36
|
-
this.
|
|
36
|
+
this.syncBlockFetchDataRequests = new Map();
|
|
37
|
+
this.syncBlockSourceInfoRequests = new Map();
|
|
37
38
|
this.providerFactories = new Map();
|
|
38
39
|
this.fireAnalyticsEvent = fireAnalyticsEvent;
|
|
39
40
|
}
|
|
@@ -154,7 +155,7 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
154
155
|
if (!resourceId || !this.dataProvider) {
|
|
155
156
|
throw new Error('Data provider or resourceId not set');
|
|
156
157
|
}
|
|
157
|
-
if (this.
|
|
158
|
+
if (this.syncBlockSourceInfoRequests.get(resourceId)) {
|
|
158
159
|
return;
|
|
159
160
|
}
|
|
160
161
|
var existingSyncBlock = this.getFromCache(resourceId);
|
|
@@ -175,7 +176,7 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
175
176
|
(_this$fireAnalyticsEv2 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv2 === void 0 || _this$fireAnalyticsEv2.call(this, getSourceInfoErrorPayload('SourceAri, product or blockInstanceId missing'));
|
|
176
177
|
return;
|
|
177
178
|
}
|
|
178
|
-
this.
|
|
179
|
+
this.syncBlockSourceInfoRequests.set(resourceId, true);
|
|
179
180
|
this.dataProvider.fetchSyncBlockSourceInfo(blockInstanceId, sourceAri, product, this.fireAnalyticsEvent).then(function (sourceInfo) {
|
|
180
181
|
if (!sourceInfo) {
|
|
181
182
|
return;
|
|
@@ -188,7 +189,7 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
188
189
|
var _this$fireAnalyticsEv3;
|
|
189
190
|
(_this$fireAnalyticsEv3 = _this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv3 === void 0 || _this$fireAnalyticsEv3.call(_this, getSourceInfoErrorPayload(error.message));
|
|
190
191
|
}).finally(function () {
|
|
191
|
-
_this.
|
|
192
|
+
_this.syncBlockSourceInfoRequests.delete(resourceId);
|
|
192
193
|
});
|
|
193
194
|
} catch (error) {
|
|
194
195
|
var _this$fireAnalyticsEv4;
|
|
@@ -209,7 +210,7 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
209
210
|
value: (function () {
|
|
210
211
|
var _fetchSyncBlocksData = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(syncBlockNodes) {
|
|
211
212
|
var _this2 = this;
|
|
212
|
-
var nodesToFetch,
|
|
213
|
+
var nodesToFetch, data, resolvedData;
|
|
213
214
|
return _regeneratorRuntime.wrap(function _callee2$(_context3) {
|
|
214
215
|
while (1) switch (_context3.prev = _context3.next) {
|
|
215
216
|
case 0:
|
|
@@ -217,7 +218,7 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
217
218
|
_context3.next = 2;
|
|
218
219
|
break;
|
|
219
220
|
}
|
|
220
|
-
return _context3.abrupt("return"
|
|
221
|
+
return _context3.abrupt("return");
|
|
221
222
|
case 2:
|
|
222
223
|
if (this.dataProvider) {
|
|
223
224
|
_context3.next = 4;
|
|
@@ -226,18 +227,27 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
226
227
|
throw new Error('Data provider not set');
|
|
227
228
|
case 4:
|
|
228
229
|
// Don't fetch for not_found error since the source is already deleted
|
|
229
|
-
nodesToFetch = []
|
|
230
|
+
nodesToFetch = [];
|
|
230
231
|
syncBlockNodes.forEach(function (node) {
|
|
232
|
+
if (_this2.syncBlockFetchDataRequests.get(node.attrs.resourceId)) {
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
231
235
|
var existingSyncBlock = _this2.getFromCache(node.attrs.resourceId);
|
|
232
236
|
if ((existingSyncBlock === null || existingSyncBlock === void 0 ? void 0 : existingSyncBlock.error) === SyncBlockError.NotFound) {
|
|
233
|
-
|
|
234
|
-
} else {
|
|
235
|
-
nodesToFetch.push(node);
|
|
237
|
+
return;
|
|
236
238
|
}
|
|
239
|
+
nodesToFetch.push(node);
|
|
237
240
|
});
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
+
nodesToFetch.forEach(function (node) {
|
|
242
|
+
_this2.syncBlockFetchDataRequests.set(node.attrs.resourceId, true);
|
|
243
|
+
});
|
|
244
|
+
_context3.next = 9;
|
|
245
|
+
return this.dataProvider.fetchNodesData(nodesToFetch).finally(function () {
|
|
246
|
+
nodesToFetch.forEach(function (node) {
|
|
247
|
+
_this2.syncBlockFetchDataRequests.delete(node.attrs.resourceId);
|
|
248
|
+
});
|
|
249
|
+
});
|
|
250
|
+
case 9:
|
|
241
251
|
data = _context3.sent;
|
|
242
252
|
resolvedData = [];
|
|
243
253
|
data.forEach(function (syncBlockInstance) {
|
|
@@ -257,7 +267,6 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
257
267
|
}
|
|
258
268
|
_this2.fetchSyncBlockSourceInfo(resolvedSyncBlockInstance.resourceId);
|
|
259
269
|
});
|
|
260
|
-
return _context3.abrupt("return", [].concat(resolvedData, blocksWithNotFoundError));
|
|
261
270
|
case 12:
|
|
262
271
|
case "end":
|
|
263
272
|
return _context3.stop();
|
|
@@ -521,7 +530,7 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
521
530
|
|
|
522
531
|
/**
|
|
523
532
|
* Update reference synced blocks on the document with the BE
|
|
524
|
-
*
|
|
533
|
+
*
|
|
525
534
|
* @returns true if the reference synced blocks are updated successfully, false otherwise
|
|
526
535
|
*/
|
|
527
536
|
}, {
|
|
@@ -559,42 +568,50 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
559
568
|
});
|
|
560
569
|
});
|
|
561
570
|
if (!(blocks.length === 0)) {
|
|
562
|
-
_context4.next =
|
|
571
|
+
_context4.next = 11;
|
|
563
572
|
break;
|
|
564
573
|
}
|
|
574
|
+
this.isCacheDirty = false;
|
|
565
575
|
return _context4.abrupt("return", true);
|
|
566
|
-
case
|
|
567
|
-
|
|
576
|
+
case 11:
|
|
577
|
+
// reset isCacheDirty early to prevent race condition
|
|
578
|
+
// There is a race condition where if a user makes changes (create/delete) to a reference sync block
|
|
579
|
+
// on a live page and the reference sync block is being saved while the user
|
|
580
|
+
// is still making changes, the new changes might not be saved if they all happen
|
|
581
|
+
// exactly at a time when the updateReferenceData is being executed asynchronously.
|
|
582
|
+
this.isCacheDirty = false;
|
|
583
|
+
_context4.next = 14;
|
|
568
584
|
return this.dataProvider.updateReferenceData(blocks);
|
|
569
|
-
case
|
|
585
|
+
case 14:
|
|
570
586
|
updateResult = _context4.sent;
|
|
571
587
|
if (!updateResult.success) {
|
|
572
588
|
success = false;
|
|
573
589
|
(_this$fireAnalyticsEv9 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv9 === void 0 || _this$fireAnalyticsEv9.call(this, updateReferenceErrorPayload(updateResult.error || 'Failed to update reference synced blocks on the document'));
|
|
574
590
|
}
|
|
575
|
-
_context4.next =
|
|
591
|
+
_context4.next = 23;
|
|
576
592
|
break;
|
|
577
|
-
case
|
|
578
|
-
_context4.prev =
|
|
593
|
+
case 18:
|
|
594
|
+
_context4.prev = 18;
|
|
579
595
|
_context4.t0 = _context4["catch"](3);
|
|
580
596
|
success = false;
|
|
581
597
|
logException(_context4.t0, {
|
|
582
598
|
location: 'editor-synced-block-provider/referenceSyncBlockStoreManager'
|
|
583
599
|
});
|
|
584
600
|
(_this$fireAnalyticsEv0 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv0 === void 0 || _this$fireAnalyticsEv0.call(this, updateReferenceErrorPayload(_context4.t0.message));
|
|
585
|
-
case
|
|
586
|
-
_context4.prev =
|
|
587
|
-
if (success) {
|
|
588
|
-
|
|
601
|
+
case 23:
|
|
602
|
+
_context4.prev = 23;
|
|
603
|
+
if (!success) {
|
|
604
|
+
// set isCacheDirty back to true for cases where it failed to update the reference synced blocks on the BE
|
|
605
|
+
this.isCacheDirty = true;
|
|
589
606
|
}
|
|
590
|
-
return _context4.finish(
|
|
591
|
-
case
|
|
607
|
+
return _context4.finish(23);
|
|
608
|
+
case 26:
|
|
592
609
|
return _context4.abrupt("return", success);
|
|
593
|
-
case
|
|
610
|
+
case 27:
|
|
594
611
|
case "end":
|
|
595
612
|
return _context4.stop();
|
|
596
613
|
}
|
|
597
|
-
}, _callee3, this, [[3,
|
|
614
|
+
}, _callee3, this, [[3, 18, 23, 26]]);
|
|
598
615
|
}));
|
|
599
616
|
function flush() {
|
|
600
617
|
return _flush.apply(this, arguments);
|
|
@@ -608,7 +625,8 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
608
625
|
this.syncBlockCache.clear();
|
|
609
626
|
this.subscriptions.clear();
|
|
610
627
|
this.titleSubscriptions.clear();
|
|
611
|
-
this.
|
|
628
|
+
this.syncBlockFetchDataRequests.clear();
|
|
629
|
+
this.syncBlockSourceInfoRequests.clear();
|
|
612
630
|
this.providerFactories.clear();
|
|
613
631
|
this.isRefreshingSubscriptions = false;
|
|
614
632
|
this.providerFactories.forEach(function (providerFactory) {
|
|
@@ -103,6 +103,13 @@ export var SourceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
103
103
|
}
|
|
104
104
|
});
|
|
105
105
|
bodiedSyncBlockData.push(syncBlockData);
|
|
106
|
+
|
|
107
|
+
// reset isDirty early to prevent race condition
|
|
108
|
+
// There is a race condition where if a user makes changes to a source sync block
|
|
109
|
+
// on a live page and the source sync block is being saved while the user
|
|
110
|
+
// is still making changes, the new changes might not be saved if they all happen
|
|
111
|
+
// exactly at a time when the writeNodesData is being executed asynchronously.
|
|
112
|
+
syncBlockData.isDirty = false;
|
|
106
113
|
}
|
|
107
114
|
});
|
|
108
115
|
if (!(bodiedSyncBlockNodes.length === 0)) {
|
|
@@ -116,11 +123,11 @@ export var SourceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
116
123
|
case 10:
|
|
117
124
|
writeResults = _context.sent;
|
|
118
125
|
writeResults.forEach(function (result) {
|
|
119
|
-
// set isDirty to
|
|
120
|
-
if (result.resourceId &&
|
|
126
|
+
// set isDirty to true for cases where it failed to save the sync block to the BE
|
|
127
|
+
if (result.resourceId && result.error && result.error !== SyncBlockError.NotFound) {
|
|
121
128
|
var cachedData = _this2.syncBlockCache.get(result.resourceId);
|
|
122
129
|
if (cachedData) {
|
|
123
|
-
cachedData.isDirty =
|
|
130
|
+
cachedData.isDirty = true;
|
|
124
131
|
}
|
|
125
132
|
}
|
|
126
133
|
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
|
|
2
2
|
import _createClass from "@babel/runtime/helpers/createClass";
|
|
3
|
+
import { useMemo } from 'react';
|
|
3
4
|
import { ReferenceSyncBlockStoreManager } from './referenceSyncBlockStoreManager';
|
|
4
5
|
import { SourceSyncBlockStoreManager } from './sourceSyncBlockStoreManager';
|
|
5
6
|
|
|
@@ -33,4 +34,10 @@ export var SyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
33
34
|
this.sourceSyncBlockStoreManager.destroy();
|
|
34
35
|
}
|
|
35
36
|
}]);
|
|
36
|
-
}();
|
|
37
|
+
}();
|
|
38
|
+
export var useMemoizedSyncBlockStoreManager = function useMemoizedSyncBlockStoreManager(dataProvider, fireAnalyticsEvent) {
|
|
39
|
+
return useMemo(function () {
|
|
40
|
+
var syncBlockStoreManager = new SyncBlockStoreManager(dataProvider, fireAnalyticsEvent);
|
|
41
|
+
return syncBlockStoreManager;
|
|
42
|
+
}, [dataProvider, fireAnalyticsEvent]);
|
|
43
|
+
};
|
package/dist/types/index.d.ts
CHANGED
|
@@ -11,8 +11,8 @@ export { createContentAPIProvidersWithDefaultKey, useMemoizedContentAPIProviders
|
|
|
11
11
|
export { fetchConfluencePageInfo } from './clients/confluence/sourceInfo';
|
|
12
12
|
export { SyncBlockProvider as SyncedBlockProvider, useMemoizedSyncedBlockProvider, } from './providers/syncBlockProvider';
|
|
13
13
|
export type { ADFFetchProvider, ADFWriteProvider, SyncBlockDataProvider, SyncBlockInstance, MediaEmojiProviderOptions, SyncedBlockRendererProviderOptions, SyncBlockRendererProviderCreator, } from './providers/types';
|
|
14
|
-
export { ReferenceSyncBlockStoreManager } from './store-manager/referenceSyncBlockStoreManager';
|
|
15
|
-
export { SyncBlockStoreManager } from './store-manager/syncBlockStoreManager';
|
|
14
|
+
export { type ReferenceSyncBlockStoreManager } from './store-manager/referenceSyncBlockStoreManager';
|
|
15
|
+
export { SyncBlockStoreManager, useMemoizedSyncBlockStoreManager, } from './store-manager/syncBlockStoreManager';
|
|
16
16
|
export { resolveSyncBlockInstance } from './utils/resolveSyncBlockInstance';
|
|
17
17
|
export { createSyncBlockNode, convertSyncBlockPMNodeToSyncBlockData, convertSyncBlockJSONNodeToSyncBlockNode, convertPMNodesToSyncBlockNodes, getContentIdAndProductFromResourceId } from './utils/utils';
|
|
18
18
|
export { fetchErrorPayload } from './utils/errorHandling';
|
|
@@ -16,7 +16,8 @@ export declare class SyncBlockProvider extends SyncBlockDataProvider {
|
|
|
16
16
|
* @param sourceId
|
|
17
17
|
* @param nestedRendererDataProviders
|
|
18
18
|
*/
|
|
19
|
-
constructor(fetchProvider: ADFFetchProvider, writeProvider: ADFWriteProvider, sourceId: string
|
|
19
|
+
constructor(fetchProvider: ADFFetchProvider, writeProvider: ADFWriteProvider, sourceId: string);
|
|
20
|
+
setProviderOptions(providerOptions: SyncedBlockRendererProviderOptions): void;
|
|
20
21
|
getProduct(): SyncBlockProduct | undefined;
|
|
21
22
|
/**
|
|
22
23
|
* Check if the node is supported by the provider
|
|
@@ -85,6 +85,7 @@ export declare abstract class SyncBlockDataProvider extends NodeDataProvider<Syn
|
|
|
85
85
|
abstract getSourceId(): ResourceId;
|
|
86
86
|
abstract getProduct(): SyncBlockProduct | undefined;
|
|
87
87
|
abstract fetchSyncBlockSourceInfo(localId: BlockInstanceId, sourceAri: string, sourceProduct: SyncBlockProduct, fireAnalyticsEvent?: (payload: RendererSyncBlockEventPayload) => void): Promise<SyncBlockSourceInfo | undefined>;
|
|
88
|
+
abstract setProviderOptions(providerOptions: SyncedBlockRendererProviderOptions): void;
|
|
88
89
|
abstract getSyncedBlockRendererProviderOptions(): SyncedBlockRendererProviderOptions;
|
|
89
90
|
abstract retrieveSyncBlockParentInfo(sourceAri: string, sourceProduct: SyncBlockProduct): SyncBlockParentInfo | undefined;
|
|
90
91
|
/**
|
|
@@ -11,7 +11,8 @@ export declare class ReferenceSyncBlockStoreManager {
|
|
|
11
11
|
private titleSubscriptions;
|
|
12
12
|
private providerFactories;
|
|
13
13
|
private fireAnalyticsEvent?;
|
|
14
|
-
private
|
|
14
|
+
private syncBlockFetchDataRequests;
|
|
15
|
+
private syncBlockSourceInfoRequests;
|
|
15
16
|
private isRefreshingSubscriptions;
|
|
16
17
|
constructor(dataProvider?: SyncBlockDataProvider, fireAnalyticsEvent?: (payload: RendererSyncBlockEventPayload) => void);
|
|
17
18
|
generateResourceIdForReference(sourceId: ResourceId): ResourceId;
|
|
@@ -28,11 +29,11 @@ export declare class ReferenceSyncBlockStoreManager {
|
|
|
28
29
|
* @param syncBlockNodes - The array of sync block nodes to fetch data for
|
|
29
30
|
* @returns The fetched sync block data results
|
|
30
31
|
*/
|
|
31
|
-
fetchSyncBlocksData(syncBlockNodes: SyncBlockNode[]): Promise<
|
|
32
|
+
fetchSyncBlocksData(syncBlockNodes: SyncBlockNode[]): Promise<void>;
|
|
32
33
|
private updateCacheWithSourceInfo;
|
|
33
34
|
private updateCache;
|
|
34
35
|
private updateSourceTitleSubscriptions;
|
|
35
|
-
|
|
36
|
+
getFromCache(resourceId: ResourceId): SyncBlockInstance | undefined;
|
|
36
37
|
private deleteFromCache;
|
|
37
38
|
subscribeToSyncBlock(resourceId: string, localId: string, callback: SubscriptionCallback): () => void;
|
|
38
39
|
subscribeToSourceTitle(node: PMNode, callback: TitleSubscriptionCallback): () => void;
|
|
@@ -10,3 +10,4 @@ export declare class SyncBlockStoreManager {
|
|
|
10
10
|
get sourceManager(): SourceSyncBlockStoreManager;
|
|
11
11
|
destroy(): void;
|
|
12
12
|
}
|
|
13
|
+
export declare const useMemoizedSyncBlockStoreManager: (dataProvider?: SyncBlockDataProvider, fireAnalyticsEvent?: (payload: SyncBlockEventPayload) => void) => SyncBlockStoreManager;
|
|
@@ -11,8 +11,8 @@ export { createContentAPIProvidersWithDefaultKey, useMemoizedContentAPIProviders
|
|
|
11
11
|
export { fetchConfluencePageInfo } from './clients/confluence/sourceInfo';
|
|
12
12
|
export { SyncBlockProvider as SyncedBlockProvider, useMemoizedSyncedBlockProvider, } from './providers/syncBlockProvider';
|
|
13
13
|
export type { ADFFetchProvider, ADFWriteProvider, SyncBlockDataProvider, SyncBlockInstance, MediaEmojiProviderOptions, SyncedBlockRendererProviderOptions, SyncBlockRendererProviderCreator, } from './providers/types';
|
|
14
|
-
export { ReferenceSyncBlockStoreManager } from './store-manager/referenceSyncBlockStoreManager';
|
|
15
|
-
export { SyncBlockStoreManager } from './store-manager/syncBlockStoreManager';
|
|
14
|
+
export { type ReferenceSyncBlockStoreManager } from './store-manager/referenceSyncBlockStoreManager';
|
|
15
|
+
export { SyncBlockStoreManager, useMemoizedSyncBlockStoreManager, } from './store-manager/syncBlockStoreManager';
|
|
16
16
|
export { resolveSyncBlockInstance } from './utils/resolveSyncBlockInstance';
|
|
17
17
|
export { createSyncBlockNode, convertSyncBlockPMNodeToSyncBlockData, convertSyncBlockJSONNodeToSyncBlockNode, convertPMNodesToSyncBlockNodes, getContentIdAndProductFromResourceId } from './utils/utils';
|
|
18
18
|
export { fetchErrorPayload } from './utils/errorHandling';
|
|
@@ -16,7 +16,8 @@ export declare class SyncBlockProvider extends SyncBlockDataProvider {
|
|
|
16
16
|
* @param sourceId
|
|
17
17
|
* @param nestedRendererDataProviders
|
|
18
18
|
*/
|
|
19
|
-
constructor(fetchProvider: ADFFetchProvider, writeProvider: ADFWriteProvider, sourceId: string
|
|
19
|
+
constructor(fetchProvider: ADFFetchProvider, writeProvider: ADFWriteProvider, sourceId: string);
|
|
20
|
+
setProviderOptions(providerOptions: SyncedBlockRendererProviderOptions): void;
|
|
20
21
|
getProduct(): SyncBlockProduct | undefined;
|
|
21
22
|
/**
|
|
22
23
|
* Check if the node is supported by the provider
|
|
@@ -85,6 +85,7 @@ export declare abstract class SyncBlockDataProvider extends NodeDataProvider<Syn
|
|
|
85
85
|
abstract getSourceId(): ResourceId;
|
|
86
86
|
abstract getProduct(): SyncBlockProduct | undefined;
|
|
87
87
|
abstract fetchSyncBlockSourceInfo(localId: BlockInstanceId, sourceAri: string, sourceProduct: SyncBlockProduct, fireAnalyticsEvent?: (payload: RendererSyncBlockEventPayload) => void): Promise<SyncBlockSourceInfo | undefined>;
|
|
88
|
+
abstract setProviderOptions(providerOptions: SyncedBlockRendererProviderOptions): void;
|
|
88
89
|
abstract getSyncedBlockRendererProviderOptions(): SyncedBlockRendererProviderOptions;
|
|
89
90
|
abstract retrieveSyncBlockParentInfo(sourceAri: string, sourceProduct: SyncBlockProduct): SyncBlockParentInfo | undefined;
|
|
90
91
|
/**
|
|
@@ -11,7 +11,8 @@ export declare class ReferenceSyncBlockStoreManager {
|
|
|
11
11
|
private titleSubscriptions;
|
|
12
12
|
private providerFactories;
|
|
13
13
|
private fireAnalyticsEvent?;
|
|
14
|
-
private
|
|
14
|
+
private syncBlockFetchDataRequests;
|
|
15
|
+
private syncBlockSourceInfoRequests;
|
|
15
16
|
private isRefreshingSubscriptions;
|
|
16
17
|
constructor(dataProvider?: SyncBlockDataProvider, fireAnalyticsEvent?: (payload: RendererSyncBlockEventPayload) => void);
|
|
17
18
|
generateResourceIdForReference(sourceId: ResourceId): ResourceId;
|
|
@@ -28,11 +29,11 @@ export declare class ReferenceSyncBlockStoreManager {
|
|
|
28
29
|
* @param syncBlockNodes - The array of sync block nodes to fetch data for
|
|
29
30
|
* @returns The fetched sync block data results
|
|
30
31
|
*/
|
|
31
|
-
fetchSyncBlocksData(syncBlockNodes: SyncBlockNode[]): Promise<
|
|
32
|
+
fetchSyncBlocksData(syncBlockNodes: SyncBlockNode[]): Promise<void>;
|
|
32
33
|
private updateCacheWithSourceInfo;
|
|
33
34
|
private updateCache;
|
|
34
35
|
private updateSourceTitleSubscriptions;
|
|
35
|
-
|
|
36
|
+
getFromCache(resourceId: ResourceId): SyncBlockInstance | undefined;
|
|
36
37
|
private deleteFromCache;
|
|
37
38
|
subscribeToSyncBlock(resourceId: string, localId: string, callback: SubscriptionCallback): () => void;
|
|
38
39
|
subscribeToSourceTitle(node: PMNode, callback: TitleSubscriptionCallback): () => void;
|
|
@@ -10,3 +10,4 @@ export declare class SyncBlockStoreManager {
|
|
|
10
10
|
get sourceManager(): SourceSyncBlockStoreManager;
|
|
11
11
|
destroy(): void;
|
|
12
12
|
}
|
|
13
|
+
export declare const useMemoizedSyncBlockStoreManager: (dataProvider?: SyncBlockDataProvider, fireAnalyticsEvent?: (payload: SyncBlockEventPayload) => void) => SyncBlockStoreManager;
|
package/package.json
CHANGED
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"uuid": "^3.1.0"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
|
-
"@atlaskit/editor-common": "^110.
|
|
36
|
+
"@atlaskit/editor-common": "^110.48.0",
|
|
37
37
|
"react": "^18.2.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
}
|
|
77
77
|
},
|
|
78
78
|
"name": "@atlaskit/editor-synced-block-provider",
|
|
79
|
-
"version": "2.15.
|
|
79
|
+
"version": "2.15.6",
|
|
80
80
|
"description": "Synced Block Provider for @atlaskit/editor-plugin-synced-block",
|
|
81
81
|
"author": "Atlassian Pty Ltd",
|
|
82
82
|
"license": "Apache-2.0",
|