@atlaskit/editor-synced-block-provider 2.2.3 → 2.3.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 +7 -0
- package/dist/cjs/hooks/useFetchSyncBlockData.js +5 -30
- package/dist/cjs/providers/syncBlockProvider.js +23 -4
- package/dist/cjs/store-manager/referenceSyncBlockStoreManager.js +319 -63
- package/dist/cjs/store-manager/syncBlockStoreManager.js +27 -4
- package/dist/cjs/utils/mergeFetchSyncBlockDataResult.js +38 -0
- package/dist/es2019/hooks/useFetchSyncBlockData.js +6 -31
- package/dist/es2019/providers/syncBlockProvider.js +17 -3
- package/dist/es2019/store-manager/referenceSyncBlockStoreManager.js +172 -44
- package/dist/es2019/store-manager/syncBlockStoreManager.js +21 -4
- package/dist/es2019/utils/mergeFetchSyncBlockDataResult.js +30 -0
- package/dist/esm/hooks/useFetchSyncBlockData.js +6 -31
- package/dist/esm/providers/syncBlockProvider.js +21 -2
- package/dist/esm/store-manager/referenceSyncBlockStoreManager.js +320 -64
- package/dist/esm/store-manager/syncBlockStoreManager.js +27 -4
- package/dist/esm/utils/mergeFetchSyncBlockDataResult.js +31 -0
- package/dist/types/common/schema.d.ts +1 -1
- package/dist/types/providers/syncBlockProvider.d.ts +1 -1
- package/dist/types/providers/types.d.ts +1 -0
- package/dist/types/store-manager/referenceSyncBlockStoreManager.d.ts +24 -8
- package/dist/types/store-manager/syncBlockStoreManager.d.ts +12 -4
- package/dist/types/utils/mergeFetchSyncBlockDataResult.d.ts +12 -0
- package/dist/types-ts4.5/common/schema.d.ts +1 -1
- package/dist/types-ts4.5/providers/syncBlockProvider.d.ts +1 -1
- package/dist/types-ts4.5/providers/types.d.ts +1 -0
- package/dist/types-ts4.5/store-manager/referenceSyncBlockStoreManager.d.ts +24 -8
- package/dist/types-ts4.5/store-manager/syncBlockStoreManager.d.ts +12 -4
- package/dist/types-ts4.5/utils/mergeFetchSyncBlockDataResult.d.ts +12 -0
- package/package.json +1 -1
|
@@ -1,39 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { SyncBlockError } from '../common/types';
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
3
2
|
export const SYNC_BLOCK_FETCH_INTERVAL = 3000;
|
|
4
3
|
export const useFetchSyncBlockData = (manager, syncBlockNode) => {
|
|
5
4
|
const [fetchSyncBlockDataResult, setFetchSyncBlockDataResult] = useState(null);
|
|
6
|
-
const fetchSyncBlockNode = useCallback(() => {
|
|
7
|
-
manager.fetchSyncBlockData(syncBlockNode).then(data => {
|
|
8
|
-
if (data !== null && data !== void 0 && data.error) {
|
|
9
|
-
// if there is an error, we don't want to replace real existing data with the error data
|
|
10
|
-
setFetchSyncBlockDataResult(prev => {
|
|
11
|
-
if (!prev || prev.error) {
|
|
12
|
-
return data;
|
|
13
|
-
}
|
|
14
|
-
return prev;
|
|
15
|
-
});
|
|
16
|
-
} else {
|
|
17
|
-
setFetchSyncBlockDataResult(data !== null && data !== void 0 ? data : null);
|
|
18
|
-
}
|
|
19
|
-
}).catch(() => {
|
|
20
|
-
//TODO: EDITOR-1921 - add error analytics
|
|
21
|
-
setFetchSyncBlockDataResult(prev => {
|
|
22
|
-
if (!prev || prev.error) {
|
|
23
|
-
return {
|
|
24
|
-
error: SyncBlockError.Errored
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
return prev;
|
|
28
|
-
});
|
|
29
|
-
});
|
|
30
|
-
}, [manager, syncBlockNode]);
|
|
31
5
|
useEffect(() => {
|
|
32
|
-
|
|
33
|
-
|
|
6
|
+
const unsubscribe = manager.subscribeToSyncBlockData(syncBlockNode, data => {
|
|
7
|
+
setFetchSyncBlockDataResult(data);
|
|
8
|
+
});
|
|
34
9
|
return () => {
|
|
35
|
-
|
|
10
|
+
unsubscribe();
|
|
36
11
|
};
|
|
37
|
-
}, [
|
|
12
|
+
}, [manager, setFetchSyncBlockDataResult, syncBlockNode]);
|
|
38
13
|
return fetchSyncBlockDataResult;
|
|
39
14
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
2
|
import { useMemo } from 'react';
|
|
3
|
+
import { SyncBlockError } from '../common/types';
|
|
3
4
|
import { SyncBlockDataProvider } from '../providers/types';
|
|
4
5
|
import { getLocalIdFromAri, getPageARIFromResourceId } from '../utils/ari';
|
|
5
6
|
export class SyncBlockProvider extends SyncBlockDataProvider {
|
|
@@ -17,9 +18,22 @@ export class SyncBlockProvider extends SyncBlockDataProvider {
|
|
|
17
18
|
return node.attrs.localId;
|
|
18
19
|
}
|
|
19
20
|
fetchNodesData(nodes) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
const resourceIdSet = new Set(nodes.map(node => node.attrs.resourceId));
|
|
22
|
+
const resourceIds = [...resourceIdSet];
|
|
23
|
+
return Promise.allSettled(resourceIds.map(resourceId => {
|
|
24
|
+
return this.fetchProvider.fetchData(resourceId).then(data => {
|
|
25
|
+
return data;
|
|
26
|
+
}, () => {
|
|
27
|
+
return {
|
|
28
|
+
status: SyncBlockError.Errored,
|
|
29
|
+
resourceId
|
|
30
|
+
};
|
|
31
|
+
});
|
|
32
|
+
})).then(results => {
|
|
33
|
+
return results.filter(result => {
|
|
34
|
+
return result.status === 'fulfilled';
|
|
35
|
+
}).map(result => result.value);
|
|
36
|
+
});
|
|
23
37
|
}
|
|
24
38
|
|
|
25
39
|
/**
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
+
import { resolveFetchSyncBlockDataResult } from '../utils/mergeFetchSyncBlockDataResult';
|
|
1
3
|
const createSyncBlockNode = (localId, resourceId) => {
|
|
2
4
|
return {
|
|
3
5
|
type: 'syncBlock',
|
|
@@ -9,80 +11,206 @@ const createSyncBlockNode = (localId, resourceId) => {
|
|
|
9
11
|
};
|
|
10
12
|
export class ReferenceSyncBlockStoreManager {
|
|
11
13
|
constructor(dataProvider) {
|
|
12
|
-
this
|
|
14
|
+
_defineProperty(this, "isInitialized", false);
|
|
15
|
+
_defineProperty(this, "isRefreshingSubscriptions", false);
|
|
13
16
|
this.syncBlockCache = new Map();
|
|
17
|
+
this.subscriptions = new Map();
|
|
18
|
+
this.dataProvider = dataProvider;
|
|
14
19
|
this.syncBlockURLRequests = new Map();
|
|
15
20
|
}
|
|
21
|
+
async init(editorView) {
|
|
22
|
+
if (!this.editorView && !this.isInitialized) {
|
|
23
|
+
this.editorView = editorView;
|
|
24
|
+
const syncBlockNodes = editorView.state.doc.children.filter(node => node.type.name === 'syncBlock').map(node => {
|
|
25
|
+
return node.toJSON();
|
|
26
|
+
}) || [];
|
|
27
|
+
if (syncBlockNodes.length > 0) {
|
|
28
|
+
try {
|
|
29
|
+
const dataResults = await this.fetchSyncBlocksData(syncBlockNodes);
|
|
30
|
+
if (!dataResults) {
|
|
31
|
+
throw new Error('No data results returned when initializing sync block store manager');
|
|
32
|
+
}
|
|
33
|
+
dataResults.forEach(dataResult => {
|
|
34
|
+
this.updateCache(dataResult);
|
|
35
|
+
});
|
|
36
|
+
} catch (error) {
|
|
37
|
+
// TODO: EDITOR-1921 - add error analytics
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
this.isInitialized = true;
|
|
42
|
+
}
|
|
16
43
|
|
|
17
44
|
/**
|
|
18
|
-
*
|
|
19
|
-
* @
|
|
20
|
-
* @param resourceId - The resource ID of the sync block to get the source URL for
|
|
21
|
-
* Fetches source URl for a sync block and updates sync block data with the source URL asynchronously.
|
|
45
|
+
* Refreshes the subscriptions for all sync blocks.
|
|
46
|
+
* @returns {Promise<void>}
|
|
22
47
|
*/
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
48
|
+
async refreshSubscriptions() {
|
|
49
|
+
if (this.isRefreshingSubscriptions || !this.isInitialized) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
this.isRefreshingSubscriptions = true;
|
|
53
|
+
const syncBlocks = [];
|
|
54
|
+
for (const [resourceId, callbacks] of this.subscriptions.entries()) {
|
|
55
|
+
Object.keys(callbacks).forEach(localId => {
|
|
56
|
+
syncBlocks.push(createSyncBlockNode(localId, resourceId));
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
try {
|
|
60
|
+
// fetch latest data for all subscribed sync blocks
|
|
61
|
+
// this function will update the cache and call the subscriptions
|
|
62
|
+
await this.fetchSyncBlocksData(syncBlocks);
|
|
63
|
+
} catch (error) {
|
|
64
|
+
// TODO: EDITOR-1921 - add error analytics
|
|
65
|
+
} finally {
|
|
66
|
+
this.isRefreshingSubscriptions = false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
fetchSyncBlockSourceURL(resourceId) {
|
|
70
|
+
if (!resourceId || !this.dataProvider) {
|
|
28
71
|
return;
|
|
29
72
|
}
|
|
30
73
|
|
|
31
74
|
// if the sync block is a reference block, we need to fetch the URL to the source
|
|
32
75
|
// we could optimise this further by checking if the sync block is on the same page as the source
|
|
33
|
-
if (!this.syncBlockURLRequests.get(
|
|
34
|
-
this.syncBlockURLRequests.set(
|
|
35
|
-
this.dataProvider.retrieveSyncBlockSourceUrl(createSyncBlockNode(
|
|
36
|
-
const existingSyncBlock = this.
|
|
37
|
-
if (existingSyncBlock) {
|
|
38
|
-
existingSyncBlock.
|
|
76
|
+
if (!this.syncBlockURLRequests.get(resourceId)) {
|
|
77
|
+
this.syncBlockURLRequests.set(resourceId, true);
|
|
78
|
+
this.dataProvider.retrieveSyncBlockSourceUrl(createSyncBlockNode('', resourceId)).then(sourceURL => {
|
|
79
|
+
const existingSyncBlock = this.getFromCache(resourceId);
|
|
80
|
+
if (existingSyncBlock && existingSyncBlock.data) {
|
|
81
|
+
existingSyncBlock.data = {
|
|
82
|
+
...existingSyncBlock.data,
|
|
83
|
+
sourceURL
|
|
84
|
+
};
|
|
85
|
+
this.updateCache(existingSyncBlock);
|
|
39
86
|
}
|
|
40
87
|
}).finally(() => {
|
|
41
|
-
this.syncBlockURLRequests.set(
|
|
88
|
+
this.syncBlockURLRequests.set(resourceId, false);
|
|
42
89
|
});
|
|
43
90
|
}
|
|
44
91
|
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Fetch sync block data for a given sync block node.
|
|
95
|
+
* @param syncBlockNode - The sync block node to fetch data for
|
|
96
|
+
* @returns The fetched sync block data result
|
|
97
|
+
*/
|
|
45
98
|
async fetchSyncBlockData(syncBlockNode) {
|
|
46
99
|
if (!this.dataProvider) {
|
|
47
100
|
throw new Error('Data provider not set');
|
|
48
101
|
}
|
|
49
102
|
const syncNode = createSyncBlockNode(syncBlockNode.attrs.localId, syncBlockNode.attrs.resourceId);
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
if (!(existingSyncBlock !== null && existingSyncBlock !== void 0 && existingSyncBlock.sourceURL)) {
|
|
54
|
-
this.fetchSyncBlockSourceURL({
|
|
55
|
-
localId: syncBlockNode.attrs.localId,
|
|
56
|
-
resourceId: syncBlockNode.attrs.resourceId
|
|
57
|
-
});
|
|
103
|
+
const data = await this.fetchSyncBlocksData([syncNode]);
|
|
104
|
+
if (!data || data.length === 0) {
|
|
105
|
+
throw new Error('Failed to fetch sync block data');
|
|
58
106
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
107
|
+
return data[0];
|
|
108
|
+
}
|
|
109
|
+
async fetchSyncBlocksData(syncBlockNodes) {
|
|
110
|
+
if (!this.dataProvider) {
|
|
111
|
+
throw new Error('Data provider not set');
|
|
112
|
+
}
|
|
113
|
+
const data = await this.dataProvider.fetchNodesData(syncBlockNodes);
|
|
114
|
+
if (!data) {
|
|
66
115
|
throw new Error('Failed to fetch sync block node data');
|
|
67
116
|
}
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
117
|
+
const resolvedData = [];
|
|
118
|
+
data.forEach(fetchSyncBlockDataResult => {
|
|
119
|
+
var _resolvedFetchSyncBlo;
|
|
120
|
+
if (!fetchSyncBlockDataResult.resourceId) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
const existingSyncBlock = this.getFromCache(fetchSyncBlockDataResult.resourceId);
|
|
124
|
+
const resolvedFetchSyncBlockDataResult = existingSyncBlock ? resolveFetchSyncBlockDataResult(existingSyncBlock, fetchSyncBlockDataResult) : fetchSyncBlockDataResult;
|
|
125
|
+
this.updateCache(resolvedFetchSyncBlockDataResult);
|
|
126
|
+
resolvedData.push(resolvedFetchSyncBlockDataResult);
|
|
127
|
+
|
|
128
|
+
// fetch source URL if not already present
|
|
129
|
+
if (!((_resolvedFetchSyncBlo = resolvedFetchSyncBlockDataResult.data) !== null && _resolvedFetchSyncBlo !== void 0 && _resolvedFetchSyncBlo.sourceURL) && resolvedFetchSyncBlockDataResult.resourceId) {
|
|
130
|
+
this.fetchSyncBlockSourceURL(resolvedFetchSyncBlockDataResult.resourceId);
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
return resolvedData;
|
|
134
|
+
}
|
|
135
|
+
updateCache(syncBlock) {
|
|
136
|
+
const {
|
|
137
|
+
resourceId
|
|
138
|
+
} = syncBlock;
|
|
139
|
+
if (resourceId) {
|
|
140
|
+
this.syncBlockCache.set(resourceId, syncBlock);
|
|
141
|
+
const callbacks = this.subscriptions.get(resourceId);
|
|
142
|
+
if (callbacks) {
|
|
143
|
+
Object.values(callbacks).forEach(callback => {
|
|
144
|
+
callback(syncBlock);
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
getFromCache(resourceId) {
|
|
150
|
+
return this.syncBlockCache.get(resourceId);
|
|
151
|
+
}
|
|
152
|
+
deleteFromCache(resourceId) {
|
|
153
|
+
this.syncBlockCache.delete(resourceId);
|
|
154
|
+
}
|
|
155
|
+
subscribe(node, callback) {
|
|
156
|
+
// check node is a sync block, as we only support sync block subscriptions
|
|
157
|
+
if (node.type.name !== 'syncBlock') {
|
|
158
|
+
return () => {};
|
|
75
159
|
}
|
|
76
|
-
|
|
160
|
+
const {
|
|
161
|
+
resourceId,
|
|
162
|
+
localId
|
|
163
|
+
} = node.attrs;
|
|
164
|
+
if (!localId || !resourceId) {
|
|
165
|
+
return () => {};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// add to subscriptions map
|
|
169
|
+
const resourceSubscriptions = this.subscriptions.get(resourceId) || {};
|
|
170
|
+
this.subscriptions.set(resourceId, {
|
|
171
|
+
...resourceSubscriptions,
|
|
172
|
+
[localId]: callback
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
// call the callback immediately if we have cached data
|
|
176
|
+
const cachedData = this.getFromCache(resourceId);
|
|
177
|
+
if (cachedData) {
|
|
178
|
+
callback(cachedData);
|
|
179
|
+
} else {
|
|
180
|
+
this.fetchSyncBlockData(node).catch(() => {});
|
|
181
|
+
}
|
|
182
|
+
return () => {
|
|
183
|
+
const resourceSubscriptions = this.subscriptions.get(resourceId);
|
|
184
|
+
if (resourceSubscriptions) {
|
|
185
|
+
delete resourceSubscriptions[localId];
|
|
186
|
+
if (Object.keys(resourceSubscriptions).length === 0) {
|
|
187
|
+
this.subscriptions.delete(resourceId);
|
|
188
|
+
this.deleteFromCache(resourceId);
|
|
189
|
+
} else {
|
|
190
|
+
this.subscriptions.set(resourceId, resourceSubscriptions);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
};
|
|
77
194
|
}
|
|
78
195
|
|
|
79
196
|
/**
|
|
80
197
|
* Get the URL for a sync block.
|
|
81
|
-
* @param
|
|
198
|
+
* @param resourceId - The resource ID of the sync block
|
|
82
199
|
* @returns
|
|
83
200
|
*/
|
|
84
|
-
getSyncBlockURL(
|
|
85
|
-
|
|
86
|
-
|
|
201
|
+
getSyncBlockURL(resourceId) {
|
|
202
|
+
var _syncBlock$data;
|
|
203
|
+
const syncBlock = this.getFromCache(resourceId);
|
|
204
|
+
if (!syncBlock) {
|
|
205
|
+
return undefined;
|
|
206
|
+
}
|
|
207
|
+
return (_syncBlock$data = syncBlock.data) === null || _syncBlock$data === void 0 ? void 0 : _syncBlock$data.sourceURL;
|
|
208
|
+
}
|
|
209
|
+
destroy() {
|
|
210
|
+
this.syncBlockCache.clear();
|
|
211
|
+
this.subscriptions.clear();
|
|
212
|
+
this.syncBlockURLRequests.clear();
|
|
213
|
+
this.editorView = undefined;
|
|
214
|
+
this.isInitialized = false;
|
|
87
215
|
}
|
|
88
216
|
}
|
|
@@ -11,6 +11,12 @@ export class SyncBlockStoreManager {
|
|
|
11
11
|
this.referenceSyncBlockStoreManager = new ReferenceSyncBlockStoreManager(dataProvider);
|
|
12
12
|
this.sourceSyncBlockStoreManager = new SourceSyncBlockStoreManager(dataProvider);
|
|
13
13
|
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Fetch sync block data for a given sync block node.
|
|
17
|
+
* @param syncBlockNode - The sync block node to fetch data for
|
|
18
|
+
* @returns The fetched sync block data result
|
|
19
|
+
*/
|
|
14
20
|
fetchSyncBlockData(syncBlockNode) {
|
|
15
21
|
if (!['bodiedSyncBlock', 'syncBlock'].includes(syncBlockNode.type.name)) {
|
|
16
22
|
throw new Error('Node is not a sync block');
|
|
@@ -45,16 +51,18 @@ export class SyncBlockStoreManager {
|
|
|
45
51
|
|
|
46
52
|
/**
|
|
47
53
|
* Get the URL for a sync block.
|
|
48
|
-
* @param
|
|
54
|
+
* @param resourceId - The resource ID of the sync block to get the URL for
|
|
49
55
|
* @returns
|
|
50
56
|
*/
|
|
51
|
-
getSyncBlockURL(
|
|
57
|
+
getSyncBlockURL(resourceId) {
|
|
52
58
|
// only applicable to reference sync block, for now (will be refactored further)
|
|
53
|
-
return this.referenceSyncBlockStoreManager.getSyncBlockURL(
|
|
59
|
+
return this.referenceSyncBlockStoreManager.getSyncBlockURL(resourceId);
|
|
54
60
|
}
|
|
55
61
|
setEditorView(editorView) {
|
|
56
|
-
// only applicable to source sync block, for now (will be refactored further)
|
|
57
62
|
this.sourceSyncBlockStoreManager.setEditorView(editorView);
|
|
63
|
+
if (editorView) {
|
|
64
|
+
this.referenceSyncBlockStoreManager.init(editorView);
|
|
65
|
+
}
|
|
58
66
|
}
|
|
59
67
|
isSourceBlock(node) {
|
|
60
68
|
return node.type.name === 'bodiedSyncBlock';
|
|
@@ -71,6 +79,12 @@ export class SyncBlockStoreManager {
|
|
|
71
79
|
// only applicable to source sync block, for now (will be refactored further)
|
|
72
80
|
return this.sourceSyncBlockStoreManager.createSyncBlockNode();
|
|
73
81
|
}
|
|
82
|
+
subscribeToSyncBlockData(node, callback) {
|
|
83
|
+
return this.referenceSyncBlockStoreManager.subscribe(node, callback);
|
|
84
|
+
}
|
|
85
|
+
refreshSubscriptions() {
|
|
86
|
+
this.referenceSyncBlockStoreManager.refreshSubscriptions();
|
|
87
|
+
}
|
|
74
88
|
deleteSyncBlocksWithConfirmation(tr, syncBlockIds) {
|
|
75
89
|
// only applicable to source sync block, for now (will be refactored further)
|
|
76
90
|
return this.sourceSyncBlockStoreManager.deleteSyncBlocksWithConfirmation(tr, syncBlockIds);
|
|
@@ -79,4 +93,7 @@ export class SyncBlockStoreManager {
|
|
|
79
93
|
// only applicable to source sync block, for now (will be refactored further)
|
|
80
94
|
this.sourceSyncBlockStoreManager.rebaseTransaction(incomingTr, state);
|
|
81
95
|
}
|
|
96
|
+
destroy() {
|
|
97
|
+
this.referenceSyncBlockStoreManager.destroy();
|
|
98
|
+
}
|
|
82
99
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Merges two FetchSyncBlockDataResult objects,
|
|
3
|
+
* currently it only preserves the sourceURL from the old result,
|
|
4
|
+
* but this can be extended in the future to preserve other fields and resolve conflicts as needed.
|
|
5
|
+
* e.g. compare timestamps or version numbers to determine which data is more recent.
|
|
6
|
+
*
|
|
7
|
+
* @param oldResult - The existing FetchSyncBlockDataResult object.
|
|
8
|
+
* @param newResult - The new FetchSyncBlockDataResult object to merge.
|
|
9
|
+
* @returns A merged FetchSyncBlockDataResult object.
|
|
10
|
+
*/
|
|
11
|
+
export const resolveFetchSyncBlockDataResult = (oldResult, newResult) => {
|
|
12
|
+
var _newResult$data, _oldResult$data;
|
|
13
|
+
// if the old result has no data, we simple return the new result
|
|
14
|
+
if (!oldResult.data) {
|
|
15
|
+
return newResult;
|
|
16
|
+
} else if (!newResult.data) {
|
|
17
|
+
// if the new result has no data, we simply return the old result
|
|
18
|
+
// TODO: EDITOR-2533 - handle this case based on the error type and whether we should keep old data or not
|
|
19
|
+
return oldResult;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// otherwise, we merge the two results, preserving the sourceURL from the old result if it exists
|
|
23
|
+
return {
|
|
24
|
+
...newResult,
|
|
25
|
+
data: {
|
|
26
|
+
...newResult.data,
|
|
27
|
+
sourceURL: ((_newResult$data = newResult.data) === null || _newResult$data === void 0 ? void 0 : _newResult$data.sourceURL) || ((_oldResult$data = oldResult.data) === null || _oldResult$data === void 0 ? void 0 : _oldResult$data.sourceURL) || undefined
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
};
|
|
@@ -1,43 +1,18 @@
|
|
|
1
1
|
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
2
|
-
import {
|
|
3
|
-
import { SyncBlockError } from '../common/types';
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
4
3
|
export var SYNC_BLOCK_FETCH_INTERVAL = 3000;
|
|
5
4
|
export var useFetchSyncBlockData = function useFetchSyncBlockData(manager, syncBlockNode) {
|
|
6
5
|
var _useState = useState(null),
|
|
7
6
|
_useState2 = _slicedToArray(_useState, 2),
|
|
8
7
|
fetchSyncBlockDataResult = _useState2[0],
|
|
9
8
|
setFetchSyncBlockDataResult = _useState2[1];
|
|
10
|
-
var fetchSyncBlockNode = useCallback(function () {
|
|
11
|
-
manager.fetchSyncBlockData(syncBlockNode).then(function (data) {
|
|
12
|
-
if (data !== null && data !== void 0 && data.error) {
|
|
13
|
-
// if there is an error, we don't want to replace real existing data with the error data
|
|
14
|
-
setFetchSyncBlockDataResult(function (prev) {
|
|
15
|
-
if (!prev || prev.error) {
|
|
16
|
-
return data;
|
|
17
|
-
}
|
|
18
|
-
return prev;
|
|
19
|
-
});
|
|
20
|
-
} else {
|
|
21
|
-
setFetchSyncBlockDataResult(data !== null && data !== void 0 ? data : null);
|
|
22
|
-
}
|
|
23
|
-
}).catch(function () {
|
|
24
|
-
//TODO: EDITOR-1921 - add error analytics
|
|
25
|
-
setFetchSyncBlockDataResult(function (prev) {
|
|
26
|
-
if (!prev || prev.error) {
|
|
27
|
-
return {
|
|
28
|
-
error: SyncBlockError.Errored
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
return prev;
|
|
32
|
-
});
|
|
33
|
-
});
|
|
34
|
-
}, [manager, syncBlockNode]);
|
|
35
9
|
useEffect(function () {
|
|
36
|
-
|
|
37
|
-
|
|
10
|
+
var unsubscribe = manager.subscribeToSyncBlockData(syncBlockNode, function (data) {
|
|
11
|
+
setFetchSyncBlockDataResult(data);
|
|
12
|
+
});
|
|
38
13
|
return function () {
|
|
39
|
-
|
|
14
|
+
unsubscribe();
|
|
40
15
|
};
|
|
41
|
-
}, [
|
|
16
|
+
}, [manager, setFetchSyncBlockDataResult, syncBlockNode]);
|
|
42
17
|
return fetchSyncBlockDataResult;
|
|
43
18
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
|
|
2
|
+
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
|
2
3
|
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
|
|
3
4
|
import _createClass from "@babel/runtime/helpers/createClass";
|
|
4
5
|
import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
|
|
@@ -9,6 +10,7 @@ import _regeneratorRuntime from "@babel/runtime/regenerator";
|
|
|
9
10
|
function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }
|
|
10
11
|
function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
|
|
11
12
|
import { useMemo } from 'react';
|
|
13
|
+
import { SyncBlockError } from '../common/types';
|
|
12
14
|
import { SyncBlockDataProvider } from '../providers/types';
|
|
13
15
|
import { getLocalIdFromAri, getPageARIFromResourceId } from '../utils/ari';
|
|
14
16
|
export var SyncBlockProvider = /*#__PURE__*/function (_SyncBlockDataProvide) {
|
|
@@ -37,9 +39,26 @@ export var SyncBlockProvider = /*#__PURE__*/function (_SyncBlockDataProvide) {
|
|
|
37
39
|
key: "fetchNodesData",
|
|
38
40
|
value: function fetchNodesData(nodes) {
|
|
39
41
|
var _this2 = this;
|
|
40
|
-
|
|
41
|
-
return
|
|
42
|
+
var resourceIdSet = new Set(nodes.map(function (node) {
|
|
43
|
+
return node.attrs.resourceId;
|
|
42
44
|
}));
|
|
45
|
+
var resourceIds = _toConsumableArray(resourceIdSet);
|
|
46
|
+
return Promise.allSettled(resourceIds.map(function (resourceId) {
|
|
47
|
+
return _this2.fetchProvider.fetchData(resourceId).then(function (data) {
|
|
48
|
+
return data;
|
|
49
|
+
}, function () {
|
|
50
|
+
return {
|
|
51
|
+
status: SyncBlockError.Errored,
|
|
52
|
+
resourceId: resourceId
|
|
53
|
+
};
|
|
54
|
+
});
|
|
55
|
+
})).then(function (results) {
|
|
56
|
+
return results.filter(function (result) {
|
|
57
|
+
return result.status === 'fulfilled';
|
|
58
|
+
}).map(function (result) {
|
|
59
|
+
return result.value;
|
|
60
|
+
});
|
|
61
|
+
});
|
|
43
62
|
}
|
|
44
63
|
|
|
45
64
|
/**
|