@atlaskit/editor-synced-block-provider 2.10.5 → 2.11.0
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 +21 -0
- package/dist/cjs/clients/block-service/blockService.js +5 -4
- package/dist/cjs/clients/confluence/sourceInfo.js +20 -17
- package/dist/cjs/hooks/useFetchSyncBlockData.js +20 -11
- package/dist/cjs/hooks/useHandleContentChanges.js +1 -5
- package/dist/cjs/index.js +2 -2
- package/dist/cjs/providers/block-service/blockServiceAPI.js +17 -26
- package/dist/cjs/providers/confluence/confluenceContentAPI.js +0 -15
- package/dist/cjs/providers/syncBlockProvider.js +31 -41
- package/dist/cjs/store-manager/referenceSyncBlockStoreManager.js +138 -63
- package/dist/cjs/store-manager/sourceSyncBlockStoreManager.js +93 -43
- package/dist/cjs/store-manager/syncBlockStoreManager.js +3 -3
- package/dist/cjs/utils/errorHandling.js +31 -1
- package/dist/es2019/clients/block-service/blockService.js +5 -4
- package/dist/es2019/clients/confluence/sourceInfo.js +13 -8
- package/dist/es2019/hooks/useFetchSyncBlockData.js +15 -7
- package/dist/es2019/hooks/useHandleContentChanges.js +1 -5
- package/dist/es2019/index.js +1 -1
- package/dist/es2019/providers/block-service/blockServiceAPI.js +13 -20
- package/dist/es2019/providers/confluence/confluenceContentAPI.js +1 -14
- package/dist/es2019/providers/syncBlockProvider.js +31 -45
- package/dist/es2019/store-manager/referenceSyncBlockStoreManager.js +124 -49
- package/dist/es2019/store-manager/sourceSyncBlockStoreManager.js +65 -24
- package/dist/es2019/store-manager/syncBlockStoreManager.js +3 -3
- package/dist/es2019/utils/errorHandling.js +17 -1
- package/dist/esm/clients/block-service/blockService.js +5 -4
- package/dist/esm/clients/confluence/sourceInfo.js +19 -16
- package/dist/esm/hooks/useFetchSyncBlockData.js +20 -11
- package/dist/esm/hooks/useHandleContentChanges.js +1 -5
- package/dist/esm/index.js +1 -1
- package/dist/esm/providers/block-service/blockServiceAPI.js +17 -26
- package/dist/esm/providers/confluence/confluenceContentAPI.js +1 -16
- package/dist/esm/providers/syncBlockProvider.js +32 -42
- package/dist/esm/store-manager/referenceSyncBlockStoreManager.js +138 -63
- package/dist/esm/store-manager/sourceSyncBlockStoreManager.js +93 -43
- package/dist/esm/store-manager/syncBlockStoreManager.js +3 -3
- package/dist/esm/utils/errorHandling.js +30 -0
- package/dist/types/clients/block-service/blockService.d.ts +0 -2
- package/dist/types/clients/confluence/sourceInfo.d.ts +2 -1
- package/dist/types/hooks/useFetchSyncBlockData.d.ts +2 -1
- package/dist/types/index.d.ts +2 -2
- package/dist/types/providers/block-service/blockServiceAPI.d.ts +7 -5
- package/dist/types/providers/confluence/confluenceContentAPI.d.ts +2 -3
- package/dist/types/providers/syncBlockProvider.d.ts +12 -9
- package/dist/types/providers/types.d.ts +9 -9
- package/dist/types/store-manager/referenceSyncBlockStoreManager.d.ts +6 -2
- package/dist/types/store-manager/sourceSyncBlockStoreManager.d.ts +3 -1
- package/dist/types/store-manager/syncBlockStoreManager.d.ts +2 -1
- package/dist/types/utils/errorHandling.d.ts +10 -0
- package/dist/types-ts4.5/clients/block-service/blockService.d.ts +0 -2
- package/dist/types-ts4.5/clients/confluence/sourceInfo.d.ts +2 -1
- package/dist/types-ts4.5/hooks/useFetchSyncBlockData.d.ts +2 -1
- package/dist/types-ts4.5/index.d.ts +2 -2
- package/dist/types-ts4.5/providers/block-service/blockServiceAPI.d.ts +7 -5
- package/dist/types-ts4.5/providers/confluence/confluenceContentAPI.d.ts +2 -3
- package/dist/types-ts4.5/providers/syncBlockProvider.d.ts +12 -9
- package/dist/types-ts4.5/providers/types.d.ts +9 -9
- package/dist/types-ts4.5/store-manager/referenceSyncBlockStoreManager.d.ts +6 -2
- package/dist/types-ts4.5/store-manager/sourceSyncBlockStoreManager.d.ts +3 -1
- package/dist/types-ts4.5/store-manager/syncBlockStoreManager.d.ts +2 -1
- package/dist/types-ts4.5/utils/errorHandling.d.ts +10 -0
- package/package.json +2 -8
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
+
import { logException } from '@atlaskit/editor-common/monitoring';
|
|
2
3
|
import { ProviderFactory } from '@atlaskit/editor-common/provider-factory';
|
|
3
4
|
import { SyncBlockError } from '../common/types';
|
|
5
|
+
import { fetchErrorPayload, getSourceInfoErrorPayload } from '../utils/errorHandling';
|
|
4
6
|
import { resolveSyncBlockInstance } from '../utils/resolveSyncBlockInstance';
|
|
5
7
|
import { createSyncBlockNode } from '../utils/utils';
|
|
6
8
|
|
|
@@ -10,7 +12,7 @@ import { createSyncBlockNode } from '../utils/utils';
|
|
|
10
12
|
// Handles fetching source URL and title for sync blocks.
|
|
11
13
|
// Can be used in both editor and renderer contexts.
|
|
12
14
|
export class ReferenceSyncBlockStoreManager {
|
|
13
|
-
constructor(dataProvider) {
|
|
15
|
+
constructor(dataProvider, fireAnalyticsEvent) {
|
|
14
16
|
_defineProperty(this, "isRefreshingSubscriptions", false);
|
|
15
17
|
this.syncBlockCache = new Map();
|
|
16
18
|
this.subscriptions = new Map();
|
|
@@ -18,6 +20,10 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
18
20
|
this.dataProvider = dataProvider;
|
|
19
21
|
this.syncBlockURLRequests = new Map();
|
|
20
22
|
this.providerFactories = new Map();
|
|
23
|
+
this.fireAnalyticsEvent = fireAnalyticsEvent;
|
|
24
|
+
}
|
|
25
|
+
updateFireAnalyticsEvent(fireAnalyticsEvent) {
|
|
26
|
+
this.fireAnalyticsEvent = fireAnalyticsEvent;
|
|
21
27
|
}
|
|
22
28
|
|
|
23
29
|
/**
|
|
@@ -40,38 +46,62 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
40
46
|
// this function will update the cache and call the subscriptions
|
|
41
47
|
await this.fetchSyncBlocksData(syncBlocks);
|
|
42
48
|
} catch (error) {
|
|
43
|
-
|
|
49
|
+
var _this$fireAnalyticsEv;
|
|
50
|
+
logException(error, {
|
|
51
|
+
location: 'editor-synced-block-provider/referenceSyncBlockStoreManager'
|
|
52
|
+
});
|
|
53
|
+
(_this$fireAnalyticsEv = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv === void 0 ? void 0 : _this$fireAnalyticsEv.call(this, fetchErrorPayload(error.message));
|
|
44
54
|
} finally {
|
|
45
55
|
this.isRefreshingSubscriptions = false;
|
|
46
56
|
}
|
|
47
57
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
if (!this.syncBlockURLRequests.get(resourceId)) {
|
|
58
|
+
fetchSyncBlockSourceInfo(resourceId) {
|
|
59
|
+
try {
|
|
60
|
+
var _existingSyncBlock$da, _existingSyncBlock$da2;
|
|
61
|
+
if (!resourceId || !this.dataProvider) {
|
|
62
|
+
throw new Error('Data provider or resourceId not set');
|
|
63
|
+
}
|
|
64
|
+
if (this.syncBlockURLRequests.get(resourceId)) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
58
67
|
this.syncBlockURLRequests.set(resourceId, true);
|
|
59
|
-
this.
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
68
|
+
const existingSyncBlock = this.getFromCache(resourceId);
|
|
69
|
+
if (!existingSyncBlock) {
|
|
70
|
+
throw new Error('No existing sync block to fetch source info for');
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// skip if source URL and title are already present
|
|
74
|
+
if ((_existingSyncBlock$da = existingSyncBlock.data) !== null && _existingSyncBlock$da !== void 0 && _existingSyncBlock$da.sourceURL && (_existingSyncBlock$da2 = existingSyncBlock.data) !== null && _existingSyncBlock$da2 !== void 0 && _existingSyncBlock$da2.sourceTitle) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const {
|
|
78
|
+
sourceAri,
|
|
79
|
+
product,
|
|
80
|
+
blockInstanceId
|
|
81
|
+
} = existingSyncBlock.data || {};
|
|
82
|
+
if (!sourceAri || !product || !blockInstanceId) {
|
|
83
|
+
throw new Error('SourceAri, product or blockInstanceId missing');
|
|
84
|
+
}
|
|
85
|
+
this.dataProvider.fetchSyncBlockSourceInfo(blockInstanceId, sourceAri, product, this.fireAnalyticsEvent).then(sourceInfo => {
|
|
86
|
+
if (!sourceInfo) {
|
|
87
|
+
return;
|
|
71
88
|
}
|
|
89
|
+
this.updateCacheWithSourceInfo(resourceId, sourceInfo);
|
|
90
|
+
if (sourceInfo.title) {
|
|
91
|
+
this.updateSourceTitleSubscriptions(resourceId, sourceInfo.title);
|
|
92
|
+
}
|
|
93
|
+
}).catch(error => {
|
|
94
|
+
var _this$fireAnalyticsEv2;
|
|
95
|
+
(_this$fireAnalyticsEv2 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv2 === void 0 ? void 0 : _this$fireAnalyticsEv2.call(this, getSourceInfoErrorPayload(error.message));
|
|
72
96
|
}).finally(() => {
|
|
73
|
-
this.syncBlockURLRequests.
|
|
97
|
+
this.syncBlockURLRequests.delete(resourceId);
|
|
98
|
+
});
|
|
99
|
+
} catch (error) {
|
|
100
|
+
var _this$fireAnalyticsEv3;
|
|
101
|
+
logException(error, {
|
|
102
|
+
location: 'editor-synced-block-provider/referenceSyncBlockStoreManager'
|
|
74
103
|
});
|
|
104
|
+
(_this$fireAnalyticsEv3 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv3 === void 0 ? void 0 : _this$fireAnalyticsEv3.call(this, getSourceInfoErrorPayload(error.message));
|
|
75
105
|
}
|
|
76
106
|
}
|
|
77
107
|
|
|
@@ -100,16 +130,16 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
100
130
|
}
|
|
101
131
|
});
|
|
102
132
|
const data = await this.dataProvider.fetchNodesData(nodesToFetch);
|
|
103
|
-
if (!data) {
|
|
104
|
-
throw new Error('Failed to fetch sync block node data');
|
|
105
|
-
}
|
|
106
133
|
const resolvedData = [];
|
|
107
134
|
data.forEach(syncBlockInstance => {
|
|
108
|
-
var _resolvedSyncBlockIns, _resolvedSyncBlockIns2;
|
|
109
135
|
if (!syncBlockInstance.resourceId) {
|
|
136
|
+
var _this$fireAnalyticsEv4;
|
|
137
|
+
(_this$fireAnalyticsEv4 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv4 === void 0 ? void 0 : _this$fireAnalyticsEv4.call(this, fetchErrorPayload(syncBlockInstance.error || 'Returned sync block instance does not have resource id'));
|
|
110
138
|
return;
|
|
111
139
|
}
|
|
112
140
|
if (syncBlockInstance.error) {
|
|
141
|
+
var _this$fireAnalyticsEv5;
|
|
142
|
+
(_this$fireAnalyticsEv5 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv5 === void 0 ? void 0 : _this$fireAnalyticsEv5.call(this, fetchErrorPayload(syncBlockInstance.error));
|
|
113
143
|
this.updateCache(syncBlockInstance);
|
|
114
144
|
resolvedData.push(syncBlockInstance);
|
|
115
145
|
return;
|
|
@@ -118,14 +148,22 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
118
148
|
const resolvedSyncBlockInstance = existingSyncBlock ? resolveSyncBlockInstance(existingSyncBlock, syncBlockInstance) : syncBlockInstance;
|
|
119
149
|
this.updateCache(resolvedSyncBlockInstance);
|
|
120
150
|
resolvedData.push(resolvedSyncBlockInstance);
|
|
121
|
-
|
|
122
|
-
// fetch source URL and title if not already present
|
|
123
|
-
if ((!((_resolvedSyncBlockIns = resolvedSyncBlockInstance.data) !== null && _resolvedSyncBlockIns !== void 0 && _resolvedSyncBlockIns.sourceURL) || !((_resolvedSyncBlockIns2 = resolvedSyncBlockInstance.data) !== null && _resolvedSyncBlockIns2 !== void 0 && _resolvedSyncBlockIns2.sourceTitle)) && resolvedSyncBlockInstance.resourceId) {
|
|
124
|
-
this.retrieveSyncBlockSourceInfo(resolvedSyncBlockInstance.resourceId);
|
|
125
|
-
}
|
|
151
|
+
this.fetchSyncBlockSourceInfo(resolvedSyncBlockInstance.resourceId);
|
|
126
152
|
});
|
|
127
153
|
return [...resolvedData, ...blocksWithNotFoundError];
|
|
128
154
|
}
|
|
155
|
+
updateCacheWithSourceInfo(resourceId, sourceInfo) {
|
|
156
|
+
const existingSyncBlock = this.getFromCache(resourceId);
|
|
157
|
+
if (existingSyncBlock && existingSyncBlock.data) {
|
|
158
|
+
existingSyncBlock.data.sourceURL = sourceInfo === null || sourceInfo === void 0 ? void 0 : sourceInfo.url;
|
|
159
|
+
existingSyncBlock.data = {
|
|
160
|
+
...existingSyncBlock.data,
|
|
161
|
+
sourceURL: sourceInfo === null || sourceInfo === void 0 ? void 0 : sourceInfo.url,
|
|
162
|
+
sourceTitle: sourceInfo === null || sourceInfo === void 0 ? void 0 : sourceInfo.title
|
|
163
|
+
};
|
|
164
|
+
this.updateCache(existingSyncBlock);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
129
167
|
updateCache(syncBlock) {
|
|
130
168
|
const {
|
|
131
169
|
resourceId
|
|
@@ -168,7 +206,13 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
168
206
|
if (cachedData) {
|
|
169
207
|
callback(cachedData);
|
|
170
208
|
} else {
|
|
171
|
-
this.fetchSyncBlocksData([createSyncBlockNode(localId, resourceId)]).catch(
|
|
209
|
+
this.fetchSyncBlocksData([createSyncBlockNode(localId, resourceId)]).catch(error => {
|
|
210
|
+
var _this$fireAnalyticsEv6;
|
|
211
|
+
logException(error, {
|
|
212
|
+
location: 'editor-synced-block-provider/referenceSyncBlockStoreManager'
|
|
213
|
+
});
|
|
214
|
+
(_this$fireAnalyticsEv6 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv6 === void 0 ? void 0 : _this$fireAnalyticsEv6.call(this, fetchErrorPayload(error.message));
|
|
215
|
+
});
|
|
172
216
|
}
|
|
173
217
|
return () => {
|
|
174
218
|
const resourceSubscriptions = this.subscriptions.get(resourceId);
|
|
@@ -220,18 +264,27 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
220
264
|
};
|
|
221
265
|
}
|
|
222
266
|
subscribe(node, callback) {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
267
|
+
try {
|
|
268
|
+
// check node is a sync block, as we only support sync block subscriptions
|
|
269
|
+
if (node.type.name !== 'syncBlock') {
|
|
270
|
+
throw new Error('Only sync block node subscriptions are supported');
|
|
271
|
+
}
|
|
272
|
+
const {
|
|
273
|
+
resourceId,
|
|
274
|
+
localId
|
|
275
|
+
} = node.attrs;
|
|
276
|
+
if (!localId || !resourceId) {
|
|
277
|
+
throw new Error('Missing local id or resource id');
|
|
278
|
+
}
|
|
279
|
+
return this.subscribeToSyncBlock(resourceId, localId, callback);
|
|
280
|
+
} catch (error) {
|
|
281
|
+
var _this$fireAnalyticsEv7;
|
|
282
|
+
logException(error, {
|
|
283
|
+
location: 'editor-synced-block-provider/referenceSyncBlockStoreManager'
|
|
284
|
+
});
|
|
285
|
+
(_this$fireAnalyticsEv7 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv7 === void 0 ? void 0 : _this$fireAnalyticsEv7.call(this, fetchErrorPayload(error.message));
|
|
232
286
|
return () => {};
|
|
233
287
|
}
|
|
234
|
-
return this.subscribeToSyncBlock(resourceId, localId, callback);
|
|
235
288
|
}
|
|
236
289
|
|
|
237
290
|
/**
|
|
@@ -249,6 +302,12 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
249
302
|
}
|
|
250
303
|
getProviderFactory(resourceId) {
|
|
251
304
|
if (!this.dataProvider) {
|
|
305
|
+
var _this$fireAnalyticsEv8;
|
|
306
|
+
const error = new Error('Data provider not set');
|
|
307
|
+
logException(error, {
|
|
308
|
+
location: 'editor-synced-block-provider/referenceSyncBlockStoreManager'
|
|
309
|
+
});
|
|
310
|
+
(_this$fireAnalyticsEv8 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv8 === void 0 ? void 0 : _this$fireAnalyticsEv8.call(this, fetchErrorPayload(error.message));
|
|
252
311
|
return undefined;
|
|
253
312
|
}
|
|
254
313
|
const {
|
|
@@ -265,23 +324,38 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
265
324
|
this.providerFactories.set(resourceId, providerFactory);
|
|
266
325
|
}
|
|
267
326
|
if (providerCreator) {
|
|
268
|
-
|
|
327
|
+
try {
|
|
328
|
+
this.retrieveDynamicProviders(resourceId, providerFactory, providerCreator);
|
|
329
|
+
} catch (error) {
|
|
330
|
+
var _this$fireAnalyticsEv9;
|
|
331
|
+
logException(error, {
|
|
332
|
+
location: 'editor-synced-block-provider/referenceSyncBlockStoreManager'
|
|
333
|
+
});
|
|
334
|
+
(_this$fireAnalyticsEv9 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv9 === void 0 ? void 0 : _this$fireAnalyticsEv9.call(this, fetchErrorPayload(error.message));
|
|
335
|
+
}
|
|
269
336
|
}
|
|
270
337
|
return providerFactory;
|
|
271
338
|
}
|
|
272
339
|
retrieveDynamicProviders(resourceId, providerFactory, providerCreator) {
|
|
340
|
+
var _syncBlock$data2, _syncBlock$data3, _syncBlock$data4, _syncBlock$data5;
|
|
273
341
|
if (!this.dataProvider) {
|
|
274
|
-
|
|
342
|
+
throw new Error('Data provider not set');
|
|
275
343
|
}
|
|
276
344
|
const hasMediaProvider = providerFactory.hasProvider('mediaProvider');
|
|
277
345
|
const hasEmojiProvider = providerFactory.hasProvider('emojiProvider');
|
|
278
346
|
if (hasMediaProvider && hasEmojiProvider) {
|
|
279
347
|
return;
|
|
280
348
|
}
|
|
281
|
-
const
|
|
282
|
-
if (!
|
|
349
|
+
const syncBlock = this.getFromCache(resourceId);
|
|
350
|
+
if (!syncBlock || !((_syncBlock$data2 = syncBlock.data) !== null && _syncBlock$data2 !== void 0 && _syncBlock$data2.sourceAri) || !((_syncBlock$data3 = syncBlock.data) !== null && _syncBlock$data3 !== void 0 && _syncBlock$data3.product)) {
|
|
351
|
+
var _this$fireAnalyticsEv0;
|
|
352
|
+
(_this$fireAnalyticsEv0 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv0 === void 0 ? void 0 : _this$fireAnalyticsEv0.call(this, fetchErrorPayload('Sync block or source ari or product not found'));
|
|
283
353
|
return;
|
|
284
354
|
}
|
|
355
|
+
const parentInfo = this.dataProvider.retrieveSyncBlockParentInfo((_syncBlock$data4 = syncBlock.data) === null || _syncBlock$data4 === void 0 ? void 0 : _syncBlock$data4.sourceAri, (_syncBlock$data5 = syncBlock.data) === null || _syncBlock$data5 === void 0 ? void 0 : _syncBlock$data5.product);
|
|
356
|
+
if (!parentInfo) {
|
|
357
|
+
throw new Error('Unable to retrive sync block parent info');
|
|
358
|
+
}
|
|
285
359
|
const {
|
|
286
360
|
contentId,
|
|
287
361
|
contentProduct
|
|
@@ -321,5 +395,6 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
321
395
|
providerFactory.destroy();
|
|
322
396
|
});
|
|
323
397
|
this.providerFactories.clear();
|
|
398
|
+
this.fireAnalyticsEvent = undefined;
|
|
324
399
|
}
|
|
325
400
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
2
|
// eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
|
|
3
3
|
import uuid from 'uuid';
|
|
4
|
+
import { logException } from '@atlaskit/editor-common/monitoring';
|
|
4
5
|
import { rebaseTransaction } from '../common/rebase-transaction';
|
|
6
|
+
import { updateErrorPayload, createErrorPayload, deleteErrorPayload, updateCacheErrorPayload } from '../utils/errorHandling';
|
|
5
7
|
import { convertSyncBlockPMNodeToSyncBlockData, createBodiedSyncBlockNode } from '../utils/utils';
|
|
6
8
|
// A store manager responsible for the lifecycle and state management of source sync blocks in an editor instance.
|
|
7
9
|
// Designed to manage local in-memory state and synchronize with an external data provider.
|
|
@@ -9,7 +11,7 @@ import { convertSyncBlockPMNodeToSyncBlockData, createBodiedSyncBlockNode } from
|
|
|
9
11
|
// Handles caching, debouncing updates, and publish/subscribe for local changes.
|
|
10
12
|
// Ensures consistency between local and remote state, and can be used in both editor and renderer contexts.
|
|
11
13
|
export class SourceSyncBlockStoreManager {
|
|
12
|
-
constructor(dataProvider) {
|
|
14
|
+
constructor(dataProvider, fireAnalyticsEvent) {
|
|
13
15
|
_defineProperty(this, "setPendingDeletion", (Ids, value) => {
|
|
14
16
|
const syncBlock = this.syncBlockCache.get(Ids.resourceId);
|
|
15
17
|
if (syncBlock) {
|
|
@@ -18,6 +20,7 @@ export class SourceSyncBlockStoreManager {
|
|
|
18
20
|
});
|
|
19
21
|
this.dataProvider = dataProvider;
|
|
20
22
|
this.syncBlockCache = new Map();
|
|
23
|
+
this.fireAnalyticsEvent = fireAnalyticsEvent;
|
|
21
24
|
}
|
|
22
25
|
isSourceBlock(node) {
|
|
23
26
|
return node.type.name === 'bodiedSyncBlock';
|
|
@@ -28,19 +31,28 @@ export class SourceSyncBlockStoreManager {
|
|
|
28
31
|
* @param syncBlockNode - The sync block node to update
|
|
29
32
|
*/
|
|
30
33
|
updateSyncBlockData(syncBlockNode) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
try {
|
|
35
|
+
if (!this.isSourceBlock(syncBlockNode)) {
|
|
36
|
+
throw new Error('Invalid sync block node type provided for updateSyncBlockData');
|
|
37
|
+
}
|
|
38
|
+
const {
|
|
39
|
+
localId,
|
|
40
|
+
resourceId
|
|
41
|
+
} = syncBlockNode.attrs;
|
|
42
|
+
if (!localId || !resourceId) {
|
|
43
|
+
throw new Error('Local ID or resource ID is not set');
|
|
44
|
+
}
|
|
45
|
+
const syncBlockData = convertSyncBlockPMNodeToSyncBlockData(syncBlockNode);
|
|
46
|
+
this.syncBlockCache.set(resourceId, syncBlockData);
|
|
47
|
+
return true;
|
|
48
|
+
} catch (error) {
|
|
49
|
+
var _this$fireAnalyticsEv;
|
|
50
|
+
logException(error, {
|
|
51
|
+
location: 'editor-synced-block-provider/sourceSyncBlockStoreManager'
|
|
52
|
+
});
|
|
53
|
+
(_this$fireAnalyticsEv = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv === void 0 ? void 0 : _this$fireAnalyticsEv.call(this, updateCacheErrorPayload(error.message));
|
|
54
|
+
return false;
|
|
40
55
|
}
|
|
41
|
-
const syncBlockData = convertSyncBlockPMNodeToSyncBlockData(syncBlockNode);
|
|
42
|
-
this.syncBlockCache.set(resourceId, syncBlockData);
|
|
43
|
-
return true;
|
|
44
56
|
}
|
|
45
57
|
|
|
46
58
|
/**
|
|
@@ -72,9 +84,21 @@ export class SourceSyncBlockStoreManager {
|
|
|
72
84
|
return Promise.resolve(true);
|
|
73
85
|
}
|
|
74
86
|
const writeResults = await this.dataProvider.writeNodesData(bodiedSyncBlockNodes, bodiedSyncBlockData);
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
87
|
+
if (writeResults.every(result => result.resourceId !== undefined)) {
|
|
88
|
+
return true;
|
|
89
|
+
} else {
|
|
90
|
+
writeResults.filter(result => result.resourceId === undefined).forEach(result => {
|
|
91
|
+
var _this$fireAnalyticsEv2;
|
|
92
|
+
(_this$fireAnalyticsEv2 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv2 === void 0 ? void 0 : _this$fireAnalyticsEv2.call(this, updateErrorPayload(result.error || 'Failed to write data'));
|
|
93
|
+
});
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
} catch (error) {
|
|
97
|
+
var _this$fireAnalyticsEv3;
|
|
98
|
+
logException(error, {
|
|
99
|
+
location: 'editor-synced-block-provider/sourceSyncBlockStoreManager'
|
|
100
|
+
});
|
|
101
|
+
(_this$fireAnalyticsEv3 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv3 === void 0 ? void 0 : _this$fireAnalyticsEv3.call(this, updateErrorPayload(error.message));
|
|
78
102
|
return false;
|
|
79
103
|
}
|
|
80
104
|
}
|
|
@@ -130,7 +154,7 @@ export class SourceSyncBlockStoreManager {
|
|
|
130
154
|
const localId = uuid();
|
|
131
155
|
const sourceId = (_this$dataProvider = this.dataProvider) === null || _this$dataProvider === void 0 ? void 0 : _this$dataProvider.getSourceId();
|
|
132
156
|
if (!this.dataProvider || !sourceId) {
|
|
133
|
-
throw new Error('
|
|
157
|
+
throw new Error('Data provider not set or source id not set');
|
|
134
158
|
}
|
|
135
159
|
const resourceId = this.dataProvider.generateResourceId(sourceId, localId);
|
|
136
160
|
return {
|
|
@@ -162,20 +186,29 @@ export class SourceSyncBlockStoreManager {
|
|
|
162
186
|
if (resourceId) {
|
|
163
187
|
this.commitPendingCreation(true);
|
|
164
188
|
} else {
|
|
189
|
+
var _this$fireAnalyticsEv4;
|
|
165
190
|
this.commitPendingCreation(false);
|
|
166
|
-
|
|
191
|
+
(_this$fireAnalyticsEv4 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv4 === void 0 ? void 0 : _this$fireAnalyticsEv4.call(this, createErrorPayload(result.error || 'Failed to create bodied sync block'));
|
|
167
192
|
}
|
|
168
193
|
});
|
|
169
|
-
}).catch(
|
|
194
|
+
}).catch(error => {
|
|
195
|
+
var _this$fireAnalyticsEv5;
|
|
170
196
|
this.commitPendingCreation(false);
|
|
171
|
-
|
|
197
|
+
logException(error, {
|
|
198
|
+
location: 'editor-synced-block-provider/sourceSyncBlockStoreManager'
|
|
199
|
+
});
|
|
200
|
+
(_this$fireAnalyticsEv5 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv5 === void 0 ? void 0 : _this$fireAnalyticsEv5.call(this, createErrorPayload(error.message));
|
|
172
201
|
});
|
|
173
202
|
this.registerPendingCreation(resourceId);
|
|
174
203
|
} catch (error) {
|
|
204
|
+
var _this$fireAnalyticsEv6;
|
|
175
205
|
if (this.hasPendingCreation()) {
|
|
176
206
|
this.commitPendingCreation(false);
|
|
177
207
|
}
|
|
178
|
-
|
|
208
|
+
logException(error, {
|
|
209
|
+
location: 'editor-synced-block-provider/sourceSyncBlockStoreManager'
|
|
210
|
+
});
|
|
211
|
+
(_this$fireAnalyticsEv6 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv6 === void 0 ? void 0 : _this$fireAnalyticsEv6.call(this, createErrorPayload(error.message));
|
|
179
212
|
}
|
|
180
213
|
}
|
|
181
214
|
async deleteSyncBlocksWithConfirmation(tr, syncBlockIds) {
|
|
@@ -200,14 +233,21 @@ export class SourceSyncBlockStoreManager {
|
|
|
200
233
|
callback = Ids => {
|
|
201
234
|
this.setPendingDeletion(Ids, false);
|
|
202
235
|
};
|
|
203
|
-
|
|
236
|
+
results.filter(result => result.resourceId === undefined).forEach(result => {
|
|
237
|
+
var _this$fireAnalyticsEv7;
|
|
238
|
+
(_this$fireAnalyticsEv7 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv7 === void 0 ? void 0 : _this$fireAnalyticsEv7.call(this, deleteErrorPayload(result.error || 'Failed to delete synced block'));
|
|
239
|
+
});
|
|
204
240
|
}
|
|
205
241
|
syncBlockIds.forEach(callback);
|
|
206
|
-
} catch (
|
|
242
|
+
} catch (error) {
|
|
243
|
+
var _this$fireAnalyticsEv8;
|
|
207
244
|
syncBlockIds.forEach(Ids => {
|
|
208
245
|
this.setPendingDeletion(Ids, false);
|
|
209
246
|
});
|
|
210
|
-
|
|
247
|
+
logException(error, {
|
|
248
|
+
location: 'editor-synced-block-provider/sourceSyncBlockStoreManager'
|
|
249
|
+
});
|
|
250
|
+
(_this$fireAnalyticsEv8 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv8 === void 0 ? void 0 : _this$fireAnalyticsEv8.call(this, deleteErrorPayload(error.message));
|
|
211
251
|
}
|
|
212
252
|
}
|
|
213
253
|
this.confirmationTransaction = undefined;
|
|
@@ -227,5 +267,6 @@ export class SourceSyncBlockStoreManager {
|
|
|
227
267
|
this.creationCallback = undefined;
|
|
228
268
|
this.dataProvider = undefined;
|
|
229
269
|
this.editorView = undefined;
|
|
270
|
+
this.fireAnalyticsEvent = undefined;
|
|
230
271
|
}
|
|
231
272
|
}
|
|
@@ -7,11 +7,11 @@ import { SourceSyncBlockStoreManager } from './sourceSyncBlockStoreManager';
|
|
|
7
7
|
// SourceSyncBlockStoreManager is responsible for the lifecycle and state management of source sync blocks in an editor instance.
|
|
8
8
|
// Can be used in both editor and renderer contexts.
|
|
9
9
|
export class SyncBlockStoreManager {
|
|
10
|
-
constructor(dataProvider) {
|
|
10
|
+
constructor(dataProvider, fireAnalyticsEvent) {
|
|
11
11
|
// In future, if reference manager needs to reach to source manager and read it's current in memorey cache
|
|
12
12
|
// we can pass the source manager as a parameter to the reference manager constructor
|
|
13
|
-
this.sourceSyncBlockStoreManager = new SourceSyncBlockStoreManager(dataProvider);
|
|
14
|
-
this.referenceSyncBlockStoreManager = new ReferenceSyncBlockStoreManager(dataProvider);
|
|
13
|
+
this.sourceSyncBlockStoreManager = new SourceSyncBlockStoreManager(dataProvider, fireAnalyticsEvent);
|
|
14
|
+
this.referenceSyncBlockStoreManager = new ReferenceSyncBlockStoreManager(dataProvider, fireAnalyticsEvent);
|
|
15
15
|
}
|
|
16
16
|
get referenceManager() {
|
|
17
17
|
return this.referenceSyncBlockStoreManager;
|
|
@@ -1,7 +1,23 @@
|
|
|
1
|
+
import { ACTION, ACTION_SUBJECT, EVENT_TYPE, ACTION_SUBJECT_ID } from "@atlaskit/editor-common/analytics";
|
|
1
2
|
export const stringifyError = error => {
|
|
2
3
|
try {
|
|
3
4
|
return JSON.stringify(error);
|
|
4
5
|
} catch {
|
|
5
6
|
return undefined;
|
|
6
7
|
}
|
|
7
|
-
};
|
|
8
|
+
};
|
|
9
|
+
export const getErrorPayload = (actionSubjectId, error) => ({
|
|
10
|
+
action: ACTION.ERROR,
|
|
11
|
+
actionSubject: ACTION_SUBJECT.SYNCED_BLOCK,
|
|
12
|
+
actionSubjectId,
|
|
13
|
+
eventType: EVENT_TYPE.OPERATIONAL,
|
|
14
|
+
attributes: {
|
|
15
|
+
error
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
export const fetchErrorPayload = error => getErrorPayload(ACTION_SUBJECT_ID.SYNCED_BLOCK_FETCH, error);
|
|
19
|
+
export const getSourceInfoErrorPayload = error => getErrorPayload(ACTION_SUBJECT_ID.SYNCED_BLOCK_GET_SOURCE_INFO, error);
|
|
20
|
+
export const updateErrorPayload = error => getErrorPayload(ACTION_SUBJECT_ID.SYNCED_BLOCK_UPDATE, error);
|
|
21
|
+
export const createErrorPayload = error => getErrorPayload(ACTION_SUBJECT_ID.SYNCED_BLOCK_CREATE, error);
|
|
22
|
+
export const deleteErrorPayload = error => getErrorPayload(ACTION_SUBJECT_ID.SYNCED_BLOCK_DELETE, error);
|
|
23
|
+
export const updateCacheErrorPayload = error => getErrorPayload(ACTION_SUBJECT_ID.SYNCED_BLOCK_UPDATE_CACHE, error);
|
|
@@ -32,7 +32,7 @@ export var getSyncedBlockContent = /*#__PURE__*/function () {
|
|
|
32
32
|
case 0:
|
|
33
33
|
blockAri = _ref.blockAri;
|
|
34
34
|
_context.next = 3;
|
|
35
|
-
return fetch("".concat(BLOCK_SERVICE_API_URL, "/block/").concat(blockAri), {
|
|
35
|
+
return fetch("".concat(BLOCK_SERVICE_API_URL, "/block/").concat(encodeURIComponent(blockAri)), {
|
|
36
36
|
method: 'GET',
|
|
37
37
|
headers: COMMON_HEADERS
|
|
38
38
|
});
|
|
@@ -66,7 +66,7 @@ export var deleteSyncedBlock = /*#__PURE__*/function () {
|
|
|
66
66
|
case 0:
|
|
67
67
|
blockAri = _ref3.blockAri;
|
|
68
68
|
_context2.next = 3;
|
|
69
|
-
return fetch("".concat(BLOCK_SERVICE_API_URL, "/block/").concat(blockAri), {
|
|
69
|
+
return fetch("".concat(BLOCK_SERVICE_API_URL, "/block/").concat(encodeURIComponent(blockAri)), {
|
|
70
70
|
method: 'DELETE',
|
|
71
71
|
headers: COMMON_HEADERS
|
|
72
72
|
});
|
|
@@ -95,7 +95,7 @@ export var updateSyncedBlock = /*#__PURE__*/function () {
|
|
|
95
95
|
case 0:
|
|
96
96
|
blockAri = _ref5.blockAri, content = _ref5.content;
|
|
97
97
|
_context3.next = 3;
|
|
98
|
-
return fetch("".concat(BLOCK_SERVICE_API_URL, "/block/").concat(blockAri), {
|
|
98
|
+
return fetch("".concat(BLOCK_SERVICE_API_URL, "/block/").concat(encodeURIComponent(blockAri)), {
|
|
99
99
|
method: 'PUT',
|
|
100
100
|
headers: COMMON_HEADERS,
|
|
101
101
|
body: JSON.stringify({
|
|
@@ -127,10 +127,11 @@ export var createSyncedBlock = /*#__PURE__*/function () {
|
|
|
127
127
|
case 0:
|
|
128
128
|
blockAri = _ref7.blockAri, blockInstanceId = _ref7.blockInstanceId, sourceAri = _ref7.sourceAri, product = _ref7.product, content = _ref7.content;
|
|
129
129
|
_context4.next = 3;
|
|
130
|
-
return fetch("".concat(BLOCK_SERVICE_API_URL, "/block
|
|
130
|
+
return fetch("".concat(BLOCK_SERVICE_API_URL, "/block"), {
|
|
131
131
|
method: 'POST',
|
|
132
132
|
headers: COMMON_HEADERS,
|
|
133
133
|
body: JSON.stringify({
|
|
134
|
+
blockAri: blockAri,
|
|
134
135
|
blockInstanceId: blockInstanceId,
|
|
135
136
|
sourceAri: sourceAri,
|
|
136
137
|
product: product,
|
|
@@ -5,6 +5,8 @@ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbol
|
|
|
5
5
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
6
6
|
/* eslint-disable require-unicode-regexp */
|
|
7
7
|
|
|
8
|
+
import { logException } from '@atlaskit/editor-common/monitoring';
|
|
9
|
+
import { getSourceInfoErrorPayload } from '../../utils/errorHandling';
|
|
8
10
|
import { getPageIdAndTypeFromConfluencePageAri } from './ari';
|
|
9
11
|
import { isBlogPageType } from './utils';
|
|
10
12
|
var COMMON_HEADERS = {
|
|
@@ -63,8 +65,8 @@ var getConfluenceSourceInfo = /*#__PURE__*/function () {
|
|
|
63
65
|
return _ref.apply(this, arguments);
|
|
64
66
|
};
|
|
65
67
|
}();
|
|
66
|
-
export var
|
|
67
|
-
var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(pageAri, localId) {
|
|
68
|
+
export var fetchConfluencePageInfo = /*#__PURE__*/function () {
|
|
69
|
+
var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(pageAri, localId, fireAnalyticsEvent) {
|
|
68
70
|
var _response$data, _contentData$space, _getPageIdAndTypeFrom, pageType, response, contentData, title, url, _ref3, base;
|
|
69
71
|
return _regeneratorRuntime.wrap(function _callee2$(_context2) {
|
|
70
72
|
while (1) switch (_context2.prev = _context2.next) {
|
|
@@ -76,15 +78,9 @@ export var fetchConfluenceSourceInfo = /*#__PURE__*/function () {
|
|
|
76
78
|
case 4:
|
|
77
79
|
response = _context2.sent;
|
|
78
80
|
contentData = (_response$data = response.data) === null || _response$data === void 0 || (_response$data = _response$data.content) === null || _response$data === void 0 || (_response$data = _response$data.nodes) === null || _response$data === void 0 ? void 0 : _response$data[0];
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
throw new Error("Failed to get content data");
|
|
84
|
-
case 8:
|
|
85
|
-
title = contentData.title;
|
|
86
|
-
_ref3 = contentData.links || {}, base = _ref3.base;
|
|
87
|
-
if (base && (_contentData$space = contentData.space) !== null && _contentData$space !== void 0 && _contentData$space.key && contentData.id) {
|
|
81
|
+
title = contentData === null || contentData === void 0 ? void 0 : contentData.title;
|
|
82
|
+
_ref3 = (contentData === null || contentData === void 0 ? void 0 : contentData.links) || {}, base = _ref3.base;
|
|
83
|
+
if (base && contentData !== null && contentData !== void 0 && (_contentData$space = contentData.space) !== null && _contentData$space !== void 0 && _contentData$space.key && contentData !== null && contentData !== void 0 && contentData.id) {
|
|
88
84
|
if (isBlogPageType(pageType)) {
|
|
89
85
|
url = "".concat(base, "/spaces/").concat(contentData.space.key, "/blog/edit-v2/").concat(contentData.id);
|
|
90
86
|
} else if (contentData.subType === 'live') {
|
|
@@ -94,21 +90,28 @@ export var fetchConfluenceSourceInfo = /*#__PURE__*/function () {
|
|
|
94
90
|
}
|
|
95
91
|
}
|
|
96
92
|
url = url && localId ? "".concat(url, "#block-").concat(localId) : url;
|
|
93
|
+
if (!title || !url) {
|
|
94
|
+
fireAnalyticsEvent === null || fireAnalyticsEvent === void 0 || fireAnalyticsEvent(getSourceInfoErrorPayload('Failed to get confluence page source info'));
|
|
95
|
+
}
|
|
97
96
|
return _context2.abrupt("return", Promise.resolve({
|
|
98
97
|
title: title,
|
|
99
98
|
url: url
|
|
100
99
|
}));
|
|
101
|
-
case
|
|
102
|
-
_context2.prev =
|
|
100
|
+
case 14:
|
|
101
|
+
_context2.prev = 14;
|
|
103
102
|
_context2.t0 = _context2["catch"](0);
|
|
103
|
+
logException(_context2.t0, {
|
|
104
|
+
location: 'editor-synced-block-provider/sourceInfo'
|
|
105
|
+
});
|
|
106
|
+
fireAnalyticsEvent === null || fireAnalyticsEvent === void 0 || fireAnalyticsEvent(getSourceInfoErrorPayload(_context2.t0.message));
|
|
104
107
|
return _context2.abrupt("return", Promise.resolve(undefined));
|
|
105
|
-
case
|
|
108
|
+
case 19:
|
|
106
109
|
case "end":
|
|
107
110
|
return _context2.stop();
|
|
108
111
|
}
|
|
109
|
-
}, _callee2, null, [[0,
|
|
112
|
+
}, _callee2, null, [[0, 14]]);
|
|
110
113
|
}));
|
|
111
|
-
return function
|
|
114
|
+
return function fetchConfluencePageInfo(_x2, _x3, _x4) {
|
|
112
115
|
return _ref2.apply(this, arguments);
|
|
113
116
|
};
|
|
114
117
|
}();
|