@atlaskit/editor-synced-block-provider 2.10.6 → 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.
Files changed (52) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/cjs/clients/block-service/blockService.js +5 -4
  3. package/dist/cjs/clients/confluence/sourceInfo.js +18 -15
  4. package/dist/cjs/hooks/useFetchSyncBlockData.js +20 -11
  5. package/dist/cjs/hooks/useHandleContentChanges.js +1 -5
  6. package/dist/cjs/providers/block-service/blockServiceAPI.js +17 -12
  7. package/dist/cjs/providers/syncBlockProvider.js +4 -4
  8. package/dist/cjs/store-manager/referenceSyncBlockStoreManager.js +118 -66
  9. package/dist/cjs/store-manager/sourceSyncBlockStoreManager.js +93 -43
  10. package/dist/cjs/store-manager/syncBlockStoreManager.js +3 -3
  11. package/dist/cjs/utils/errorHandling.js +31 -1
  12. package/dist/es2019/clients/block-service/blockService.js +5 -4
  13. package/dist/es2019/clients/confluence/sourceInfo.js +13 -8
  14. package/dist/es2019/hooks/useFetchSyncBlockData.js +15 -7
  15. package/dist/es2019/hooks/useHandleContentChanges.js +1 -5
  16. package/dist/es2019/providers/block-service/blockServiceAPI.js +13 -8
  17. package/dist/es2019/providers/syncBlockProvider.js +4 -4
  18. package/dist/es2019/store-manager/referenceSyncBlockStoreManager.js +105 -51
  19. package/dist/es2019/store-manager/sourceSyncBlockStoreManager.js +65 -24
  20. package/dist/es2019/store-manager/syncBlockStoreManager.js +3 -3
  21. package/dist/es2019/utils/errorHandling.js +17 -1
  22. package/dist/esm/clients/block-service/blockService.js +5 -4
  23. package/dist/esm/clients/confluence/sourceInfo.js +18 -15
  24. package/dist/esm/hooks/useFetchSyncBlockData.js +20 -11
  25. package/dist/esm/hooks/useHandleContentChanges.js +1 -5
  26. package/dist/esm/providers/block-service/blockServiceAPI.js +17 -12
  27. package/dist/esm/providers/syncBlockProvider.js +4 -4
  28. package/dist/esm/store-manager/referenceSyncBlockStoreManager.js +118 -66
  29. package/dist/esm/store-manager/sourceSyncBlockStoreManager.js +93 -43
  30. package/dist/esm/store-manager/syncBlockStoreManager.js +3 -3
  31. package/dist/esm/utils/errorHandling.js +30 -0
  32. package/dist/types/clients/block-service/blockService.d.ts +0 -2
  33. package/dist/types/clients/confluence/sourceInfo.d.ts +2 -1
  34. package/dist/types/hooks/useFetchSyncBlockData.d.ts +2 -1
  35. package/dist/types/providers/block-service/blockServiceAPI.d.ts +6 -3
  36. package/dist/types/providers/syncBlockProvider.d.ts +2 -1
  37. package/dist/types/providers/types.d.ts +2 -1
  38. package/dist/types/store-manager/referenceSyncBlockStoreManager.d.ts +4 -1
  39. package/dist/types/store-manager/sourceSyncBlockStoreManager.d.ts +3 -1
  40. package/dist/types/store-manager/syncBlockStoreManager.d.ts +2 -1
  41. package/dist/types/utils/errorHandling.d.ts +10 -0
  42. package/dist/types-ts4.5/clients/block-service/blockService.d.ts +0 -2
  43. package/dist/types-ts4.5/clients/confluence/sourceInfo.d.ts +2 -1
  44. package/dist/types-ts4.5/hooks/useFetchSyncBlockData.d.ts +2 -1
  45. package/dist/types-ts4.5/providers/block-service/blockServiceAPI.d.ts +6 -3
  46. package/dist/types-ts4.5/providers/syncBlockProvider.d.ts +2 -1
  47. package/dist/types-ts4.5/providers/types.d.ts +2 -1
  48. package/dist/types-ts4.5/store-manager/referenceSyncBlockStoreManager.d.ts +4 -1
  49. package/dist/types-ts4.5/store-manager/sourceSyncBlockStoreManager.d.ts +3 -1
  50. package/dist/types-ts4.5/store-manager/syncBlockStoreManager.d.ts +2 -1
  51. package/dist/types-ts4.5/utils/errorHandling.d.ts +10 -0
  52. package/package.json +2 -8
@@ -11,7 +11,9 @@ var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/cl
11
11
  var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
12
12
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
13
13
  var _uuid = _interopRequireDefault(require("uuid"));
14
+ var _monitoring = require("@atlaskit/editor-common/monitoring");
14
15
  var _rebaseTransaction2 = require("../common/rebase-transaction");
16
+ var _errorHandling = require("../utils/errorHandling");
15
17
  var _utils = require("../utils/utils");
16
18
  // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
17
19
  // A store manager responsible for the lifecycle and state management of source sync blocks in an editor instance.
@@ -20,7 +22,7 @@ var _utils = require("../utils/utils");
20
22
  // Handles caching, debouncing updates, and publish/subscribe for local changes.
21
23
  // Ensures consistency between local and remote state, and can be used in both editor and renderer contexts.
22
24
  var SourceSyncBlockStoreManager = exports.SourceSyncBlockStoreManager = /*#__PURE__*/function () {
23
- function SourceSyncBlockStoreManager(dataProvider) {
25
+ function SourceSyncBlockStoreManager(dataProvider, fireAnalyticsEvent) {
24
26
  var _this = this;
25
27
  (0, _classCallCheck2.default)(this, SourceSyncBlockStoreManager);
26
28
  (0, _defineProperty2.default)(this, "setPendingDeletion", function (Ids, value) {
@@ -31,6 +33,7 @@ var SourceSyncBlockStoreManager = exports.SourceSyncBlockStoreManager = /*#__PUR
31
33
  });
32
34
  this.dataProvider = dataProvider;
33
35
  this.syncBlockCache = new Map();
36
+ this.fireAnalyticsEvent = fireAnalyticsEvent;
34
37
  }
35
38
  return (0, _createClass2.default)(SourceSyncBlockStoreManager, [{
36
39
  key: "isSourceBlock",
@@ -45,18 +48,27 @@ var SourceSyncBlockStoreManager = exports.SourceSyncBlockStoreManager = /*#__PUR
45
48
  }, {
46
49
  key: "updateSyncBlockData",
47
50
  value: function updateSyncBlockData(syncBlockNode) {
48
- if (!this.isSourceBlock(syncBlockNode)) {
49
- throw new Error('Invalid sync block node type provided for updateSyncBlockData');
50
- }
51
- var _syncBlockNode$attrs = syncBlockNode.attrs,
52
- localId = _syncBlockNode$attrs.localId,
53
- resourceId = _syncBlockNode$attrs.resourceId;
54
- if (!localId || !resourceId) {
55
- throw new Error('Local ID or resource ID is not set');
51
+ try {
52
+ if (!this.isSourceBlock(syncBlockNode)) {
53
+ throw new Error('Invalid sync block node type provided for updateSyncBlockData');
54
+ }
55
+ var _syncBlockNode$attrs = syncBlockNode.attrs,
56
+ localId = _syncBlockNode$attrs.localId,
57
+ resourceId = _syncBlockNode$attrs.resourceId;
58
+ if (!localId || !resourceId) {
59
+ throw new Error('Local ID or resource ID is not set');
60
+ }
61
+ var syncBlockData = (0, _utils.convertSyncBlockPMNodeToSyncBlockData)(syncBlockNode);
62
+ this.syncBlockCache.set(resourceId, syncBlockData);
63
+ return true;
64
+ } catch (error) {
65
+ var _this$fireAnalyticsEv;
66
+ (0, _monitoring.logException)(error, {
67
+ location: 'editor-synced-block-provider/sourceSyncBlockStoreManager'
68
+ });
69
+ (_this$fireAnalyticsEv = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv === void 0 || _this$fireAnalyticsEv.call(this, (0, _errorHandling.updateCacheErrorPayload)(error.message));
70
+ return false;
56
71
  }
57
- var syncBlockData = (0, _utils.convertSyncBlockPMNodeToSyncBlockData)(syncBlockNode);
58
- this.syncBlockCache.set(resourceId, syncBlockData);
59
- return true;
60
72
  }
61
73
 
62
74
  /**
@@ -68,7 +80,8 @@ var SourceSyncBlockStoreManager = exports.SourceSyncBlockStoreManager = /*#__PUR
68
80
  key: "flush",
69
81
  value: (function () {
70
82
  var _flush = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee() {
71
- var bodiedSyncBlockNodes, bodiedSyncBlockData, writeResults;
83
+ var _this2 = this;
84
+ var bodiedSyncBlockNodes, bodiedSyncBlockData, writeResults, _this$fireAnalyticsEv2;
72
85
  return _regenerator.default.wrap(function _callee$(_context) {
73
86
  while (1) switch (_context.prev = _context.next) {
74
87
  case 0:
@@ -104,18 +117,37 @@ var SourceSyncBlockStoreManager = exports.SourceSyncBlockStoreManager = /*#__PUR
104
117
  return this.dataProvider.writeNodesData(bodiedSyncBlockNodes, bodiedSyncBlockData);
105
118
  case 10:
106
119
  writeResults = _context.sent;
107
- return _context.abrupt("return", writeResults.every(function (result) {
120
+ if (!writeResults.every(function (result) {
108
121
  return result.resourceId !== undefined;
109
- }));
110
- case 14:
111
- _context.prev = 14;
112
- _context.t0 = _context["catch"](0);
122
+ })) {
123
+ _context.next = 15;
124
+ break;
125
+ }
126
+ return _context.abrupt("return", true);
127
+ case 15:
128
+ writeResults.filter(function (result) {
129
+ return result.resourceId === undefined;
130
+ }).forEach(function (result) {
131
+ var _this2$fireAnalyticsE;
132
+ (_this2$fireAnalyticsE = _this2.fireAnalyticsEvent) === null || _this2$fireAnalyticsE === void 0 || _this2$fireAnalyticsE.call(_this2, (0, _errorHandling.updateErrorPayload)(result.error || 'Failed to write data'));
133
+ });
113
134
  return _context.abrupt("return", false);
114
135
  case 17:
136
+ _context.next = 24;
137
+ break;
138
+ case 19:
139
+ _context.prev = 19;
140
+ _context.t0 = _context["catch"](0);
141
+ (0, _monitoring.logException)(_context.t0, {
142
+ location: 'editor-synced-block-provider/sourceSyncBlockStoreManager'
143
+ });
144
+ (_this$fireAnalyticsEv2 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv2 === void 0 || _this$fireAnalyticsEv2.call(this, (0, _errorHandling.updateErrorPayload)(_context.t0.message));
145
+ return _context.abrupt("return", false);
146
+ case 24:
115
147
  case "end":
116
148
  return _context.stop();
117
149
  }
118
- }, _callee, this, [[0, 14]]);
150
+ }, _callee, this, [[0, 19]]);
119
151
  }));
120
152
  function flush() {
121
153
  return _flush.apply(this, arguments);
@@ -168,10 +200,10 @@ var SourceSyncBlockStoreManager = exports.SourceSyncBlockStoreManager = /*#__PUR
168
200
  }, {
169
201
  key: "registerConfirmationCallback",
170
202
  value: function registerConfirmationCallback(callback) {
171
- var _this2 = this;
203
+ var _this3 = this;
172
204
  this.confirmationCallback = callback;
173
205
  return function () {
174
- _this2.confirmationCallback = undefined;
206
+ _this3.confirmationCallback = undefined;
175
207
  };
176
208
  }
177
209
  }, {
@@ -191,7 +223,7 @@ var SourceSyncBlockStoreManager = exports.SourceSyncBlockStoreManager = /*#__PUR
191
223
  var localId = (0, _uuid.default)();
192
224
  var sourceId = (_this$dataProvider = this.dataProvider) === null || _this$dataProvider === void 0 ? void 0 : _this$dataProvider.getSourceId();
193
225
  if (!this.dataProvider || !sourceId) {
194
- throw new Error('Provider of sync block plugin is not set');
226
+ throw new Error('Data provider not set or source id not set');
195
227
  }
196
228
  var resourceId = this.dataProvider.generateResourceId(sourceId, localId);
197
229
  return {
@@ -207,7 +239,7 @@ var SourceSyncBlockStoreManager = exports.SourceSyncBlockStoreManager = /*#__PUR
207
239
  }, {
208
240
  key: "createBodiedSyncBlockNode",
209
241
  value: function createBodiedSyncBlockNode(attrs) {
210
- var _this3 = this;
242
+ var _this4 = this;
211
243
  try {
212
244
  if (!this.dataProvider) {
213
245
  throw new Error('Data provider not set');
@@ -222,35 +254,44 @@ var SourceSyncBlockStoreManager = exports.SourceSyncBlockStoreManager = /*#__PUR
222
254
  results.forEach(function (result) {
223
255
  var resourceId = result.resourceId;
224
256
  if (resourceId) {
225
- _this3.commitPendingCreation(true);
257
+ _this4.commitPendingCreation(true);
226
258
  } else {
227
- _this3.commitPendingCreation(false);
228
- // TODO: EDITOR-1921 - add error analytics
259
+ var _this4$fireAnalyticsE;
260
+ _this4.commitPendingCreation(false);
261
+ (_this4$fireAnalyticsE = _this4.fireAnalyticsEvent) === null || _this4$fireAnalyticsE === void 0 || _this4$fireAnalyticsE.call(_this4, (0, _errorHandling.createErrorPayload)(result.error || 'Failed to create bodied sync block'));
229
262
  }
230
263
  });
231
- }).catch(function (_reason) {
232
- _this3.commitPendingCreation(false);
233
- // TODO: EDITOR-1921 - add error analytics
264
+ }).catch(function (error) {
265
+ var _this4$fireAnalyticsE2;
266
+ _this4.commitPendingCreation(false);
267
+ (0, _monitoring.logException)(error, {
268
+ location: 'editor-synced-block-provider/sourceSyncBlockStoreManager'
269
+ });
270
+ (_this4$fireAnalyticsE2 = _this4.fireAnalyticsEvent) === null || _this4$fireAnalyticsE2 === void 0 || _this4$fireAnalyticsE2.call(_this4, (0, _errorHandling.createErrorPayload)(error.message));
234
271
  });
235
272
  this.registerPendingCreation(resourceId);
236
273
  } catch (error) {
274
+ var _this$fireAnalyticsEv3;
237
275
  if (this.hasPendingCreation()) {
238
276
  this.commitPendingCreation(false);
239
277
  }
240
- // TODO: EDITOR-1921 - add error analytics
278
+ (0, _monitoring.logException)(error, {
279
+ location: 'editor-synced-block-provider/sourceSyncBlockStoreManager'
280
+ });
281
+ (_this$fireAnalyticsEv3 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv3 === void 0 || _this$fireAnalyticsEv3.call(this, (0, _errorHandling.createErrorPayload)(error.message));
241
282
  }
242
283
  }
243
284
  }, {
244
285
  key: "deleteSyncBlocksWithConfirmation",
245
286
  value: function () {
246
287
  var _deleteSyncBlocksWithConfirmation = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2(tr, syncBlockIds) {
247
- var _this4 = this;
248
- var confirmed, _this$editorView, results, callback;
288
+ var _this5 = this;
289
+ var confirmed, _this$editorView, results, callback, _this$fireAnalyticsEv4;
249
290
  return _regenerator.default.wrap(function _callee2$(_context2) {
250
291
  while (1) switch (_context2.prev = _context2.next) {
251
292
  case 0:
252
293
  if (!this.confirmationCallback) {
253
- _context2.next = 22;
294
+ _context2.next = 24;
254
295
  break;
255
296
  }
256
297
  this.confirmationTransaction = tr;
@@ -259,7 +300,7 @@ var SourceSyncBlockStoreManager = exports.SourceSyncBlockStoreManager = /*#__PUR
259
300
  case 4:
260
301
  confirmed = _context2.sent;
261
302
  if (!confirmed) {
262
- _context2.next = 21;
303
+ _context2.next = 23;
263
304
  break;
264
305
  }
265
306
  (_this$editorView = this.editorView) === null || _this$editorView === void 0 || _this$editorView.dispatch(this.confirmationTransaction.setMeta('isConfirmedSyncBlockDeletion', true));
@@ -271,7 +312,7 @@ var SourceSyncBlockStoreManager = exports.SourceSyncBlockStoreManager = /*#__PUR
271
312
  throw new Error('Data provider not set');
272
313
  case 10:
273
314
  syncBlockIds.forEach(function (Ids) {
274
- _this4.setPendingDeletion(Ids, true);
315
+ _this5.setPendingDeletion(Ids, true);
275
316
  });
276
317
  _context2.next = 13;
277
318
  return this.dataProvider.deleteNodesData(syncBlockIds.map(function (attrs) {
@@ -283,27 +324,35 @@ var SourceSyncBlockStoreManager = exports.SourceSyncBlockStoreManager = /*#__PUR
283
324
  return result.success;
284
325
  })) {
285
326
  callback = function callback(Ids) {
286
- return _this4.syncBlockCache.delete(Ids.resourceId);
327
+ return _this5.syncBlockCache.delete(Ids.resourceId);
287
328
  };
288
329
  } else {
289
330
  callback = function callback(Ids) {
290
- _this4.setPendingDeletion(Ids, false);
331
+ _this5.setPendingDeletion(Ids, false);
291
332
  };
292
- // TODO: EDITOR-1921 - add error analytics
333
+ results.filter(function (result) {
334
+ return result.resourceId === undefined;
335
+ }).forEach(function (result) {
336
+ var _this5$fireAnalyticsE;
337
+ (_this5$fireAnalyticsE = _this5.fireAnalyticsEvent) === null || _this5$fireAnalyticsE === void 0 || _this5$fireAnalyticsE.call(_this5, (0, _errorHandling.deleteErrorPayload)(result.error || 'Failed to delete synced block'));
338
+ });
293
339
  }
294
340
  syncBlockIds.forEach(callback);
295
- _context2.next = 21;
341
+ _context2.next = 23;
296
342
  break;
297
343
  case 18:
298
344
  _context2.prev = 18;
299
345
  _context2.t0 = _context2["catch"](7);
300
346
  syncBlockIds.forEach(function (Ids) {
301
- _this4.setPendingDeletion(Ids, false);
347
+ _this5.setPendingDeletion(Ids, false);
348
+ });
349
+ (0, _monitoring.logException)(_context2.t0, {
350
+ location: 'editor-synced-block-provider/sourceSyncBlockStoreManager'
302
351
  });
303
- // TODO: EDITOR-1921 - add error analytics
304
- case 21:
352
+ (_this$fireAnalyticsEv4 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv4 === void 0 || _this$fireAnalyticsEv4.call(this, (0, _errorHandling.deleteErrorPayload)(_context2.t0.message));
353
+ case 23:
305
354
  this.confirmationTransaction = undefined;
306
- case 22:
355
+ case 24:
307
356
  case "end":
308
357
  return _context2.stop();
309
358
  }
@@ -332,6 +381,7 @@ var SourceSyncBlockStoreManager = exports.SourceSyncBlockStoreManager = /*#__PUR
332
381
  this.creationCallback = undefined;
333
382
  this.dataProvider = undefined;
334
383
  this.editorView = undefined;
384
+ this.fireAnalyticsEvent = undefined;
335
385
  }
336
386
  }]);
337
387
  }();
@@ -15,12 +15,12 @@ var _sourceSyncBlockStoreManager = require("./sourceSyncBlockStoreManager");
15
15
  // SourceSyncBlockStoreManager is responsible for the lifecycle and state management of source sync blocks in an editor instance.
16
16
  // Can be used in both editor and renderer contexts.
17
17
  var SyncBlockStoreManager = exports.SyncBlockStoreManager = /*#__PURE__*/function () {
18
- function SyncBlockStoreManager(dataProvider) {
18
+ function SyncBlockStoreManager(dataProvider, fireAnalyticsEvent) {
19
19
  (0, _classCallCheck2.default)(this, SyncBlockStoreManager);
20
20
  // In future, if reference manager needs to reach to source manager and read it's current in memorey cache
21
21
  // we can pass the source manager as a parameter to the reference manager constructor
22
- this.sourceSyncBlockStoreManager = new _sourceSyncBlockStoreManager.SourceSyncBlockStoreManager(dataProvider);
23
- this.referenceSyncBlockStoreManager = new _referenceSyncBlockStoreManager.ReferenceSyncBlockStoreManager(dataProvider);
22
+ this.sourceSyncBlockStoreManager = new _sourceSyncBlockStoreManager.SourceSyncBlockStoreManager(dataProvider, fireAnalyticsEvent);
23
+ this.referenceSyncBlockStoreManager = new _referenceSyncBlockStoreManager.ReferenceSyncBlockStoreManager(dataProvider, fireAnalyticsEvent);
24
24
  }
25
25
  return (0, _createClass2.default)(SyncBlockStoreManager, [{
26
26
  key: "referenceManager",
@@ -3,11 +3,41 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.stringifyError = void 0;
6
+ exports.updateErrorPayload = exports.updateCacheErrorPayload = exports.stringifyError = exports.getSourceInfoErrorPayload = exports.getErrorPayload = exports.fetchErrorPayload = exports.deleteErrorPayload = exports.createErrorPayload = void 0;
7
+ var _analytics = require("@atlaskit/editor-common/analytics");
7
8
  var stringifyError = exports.stringifyError = function stringifyError(error) {
8
9
  try {
9
10
  return JSON.stringify(error);
10
11
  } catch (_unused) {
11
12
  return undefined;
12
13
  }
14
+ };
15
+ var getErrorPayload = exports.getErrorPayload = function getErrorPayload(actionSubjectId, error) {
16
+ return {
17
+ action: _analytics.ACTION.ERROR,
18
+ actionSubject: _analytics.ACTION_SUBJECT.SYNCED_BLOCK,
19
+ actionSubjectId: actionSubjectId,
20
+ eventType: _analytics.EVENT_TYPE.OPERATIONAL,
21
+ attributes: {
22
+ error: error
23
+ }
24
+ };
25
+ };
26
+ var fetchErrorPayload = exports.fetchErrorPayload = function fetchErrorPayload(error) {
27
+ return getErrorPayload(_analytics.ACTION_SUBJECT_ID.SYNCED_BLOCK_FETCH, error);
28
+ };
29
+ var getSourceInfoErrorPayload = exports.getSourceInfoErrorPayload = function getSourceInfoErrorPayload(error) {
30
+ return getErrorPayload(_analytics.ACTION_SUBJECT_ID.SYNCED_BLOCK_GET_SOURCE_INFO, error);
31
+ };
32
+ var updateErrorPayload = exports.updateErrorPayload = function updateErrorPayload(error) {
33
+ return getErrorPayload(_analytics.ACTION_SUBJECT_ID.SYNCED_BLOCK_UPDATE, error);
34
+ };
35
+ var createErrorPayload = exports.createErrorPayload = function createErrorPayload(error) {
36
+ return getErrorPayload(_analytics.ACTION_SUBJECT_ID.SYNCED_BLOCK_CREATE, error);
37
+ };
38
+ var deleteErrorPayload = exports.deleteErrorPayload = function deleteErrorPayload(error) {
39
+ return getErrorPayload(_analytics.ACTION_SUBJECT_ID.SYNCED_BLOCK_DELETE, error);
40
+ };
41
+ var updateCacheErrorPayload = exports.updateCacheErrorPayload = function updateCacheErrorPayload(error) {
42
+ return getErrorPayload(_analytics.ACTION_SUBJECT_ID.SYNCED_BLOCK_UPDATE_CACHE, error);
13
43
  };
@@ -12,7 +12,7 @@ export class BlockError extends Error {
12
12
  export const getSyncedBlockContent = async ({
13
13
  blockAri
14
14
  }) => {
15
- const response = await fetch(`${BLOCK_SERVICE_API_URL}/block/${blockAri}`, {
15
+ const response = await fetch(`${BLOCK_SERVICE_API_URL}/block/${encodeURIComponent(blockAri)}`, {
16
16
  method: 'GET',
17
17
  headers: COMMON_HEADERS
18
18
  });
@@ -24,7 +24,7 @@ export const getSyncedBlockContent = async ({
24
24
  export const deleteSyncedBlock = async ({
25
25
  blockAri
26
26
  }) => {
27
- const response = await fetch(`${BLOCK_SERVICE_API_URL}/block/${blockAri}`, {
27
+ const response = await fetch(`${BLOCK_SERVICE_API_URL}/block/${encodeURIComponent(blockAri)}`, {
28
28
  method: 'DELETE',
29
29
  headers: COMMON_HEADERS
30
30
  });
@@ -36,7 +36,7 @@ export const updateSyncedBlock = async ({
36
36
  blockAri,
37
37
  content
38
38
  }) => {
39
- const response = await fetch(`${BLOCK_SERVICE_API_URL}/block/${blockAri}`, {
39
+ const response = await fetch(`${BLOCK_SERVICE_API_URL}/block/${encodeURIComponent(blockAri)}`, {
40
40
  method: 'PUT',
41
41
  headers: COMMON_HEADERS,
42
42
  body: JSON.stringify({
@@ -54,10 +54,11 @@ export const createSyncedBlock = async ({
54
54
  product,
55
55
  content
56
56
  }) => {
57
- const response = await fetch(`${BLOCK_SERVICE_API_URL}/block/${blockAri}`, {
57
+ const response = await fetch(`${BLOCK_SERVICE_API_URL}/block`, {
58
58
  method: 'POST',
59
59
  headers: COMMON_HEADERS,
60
60
  body: JSON.stringify({
61
+ blockAri,
61
62
  blockInstanceId,
62
63
  sourceAri,
63
64
  product,
@@ -1,5 +1,7 @@
1
1
  /* eslint-disable require-unicode-regexp */
2
2
 
3
+ import { logException } from '@atlaskit/editor-common/monitoring';
4
+ import { getSourceInfoErrorPayload } from '../../utils/errorHandling';
3
5
  import { getPageIdAndTypeFromConfluencePageAri } from './ari';
4
6
  import { isBlogPageType } from './utils';
5
7
  const COMMON_HEADERS = {
@@ -52,7 +54,7 @@ const getConfluenceSourceInfo = async ari => {
52
54
  }
53
55
  return await response.json();
54
56
  };
55
- export const fetchConfluencePageInfo = async (pageAri, localId) => {
57
+ export const fetchConfluencePageInfo = async (pageAri, localId, fireAnalyticsEvent) => {
56
58
  try {
57
59
  var _response$data, _response$data$conten, _response$data$conten2, _contentData$space;
58
60
  const {
@@ -60,15 +62,12 @@ export const fetchConfluencePageInfo = async (pageAri, localId) => {
60
62
  } = getPageIdAndTypeFromConfluencePageAri(pageAri);
61
63
  const response = await getConfluenceSourceInfo(pageAri);
62
64
  const contentData = (_response$data = response.data) === null || _response$data === void 0 ? void 0 : (_response$data$conten = _response$data.content) === null || _response$data$conten === void 0 ? void 0 : (_response$data$conten2 = _response$data$conten.nodes) === null || _response$data$conten2 === void 0 ? void 0 : _response$data$conten2[0];
63
- if (!contentData) {
64
- throw new Error(`Failed to get content data`);
65
- }
66
- const title = contentData.title;
65
+ const title = contentData === null || contentData === void 0 ? void 0 : contentData.title;
67
66
  let url;
68
67
  const {
69
68
  base
70
- } = contentData.links || {};
71
- if (base && (_contentData$space = contentData.space) !== null && _contentData$space !== void 0 && _contentData$space.key && contentData.id) {
69
+ } = (contentData === null || contentData === void 0 ? void 0 : contentData.links) || {};
70
+ 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) {
72
71
  if (isBlogPageType(pageType)) {
73
72
  url = `${base}/spaces/${contentData.space.key}/blog/edit-v2/${contentData.id}`;
74
73
  } else if (contentData.subType === 'live') {
@@ -78,12 +77,18 @@ export const fetchConfluencePageInfo = async (pageAri, localId) => {
78
77
  }
79
78
  }
80
79
  url = url && localId ? `${url}#block-${localId}` : url;
80
+ if (!title || !url) {
81
+ fireAnalyticsEvent === null || fireAnalyticsEvent === void 0 ? void 0 : fireAnalyticsEvent(getSourceInfoErrorPayload('Failed to get confluence page source info'));
82
+ }
81
83
  return Promise.resolve({
82
84
  title,
83
85
  url
84
86
  });
85
87
  } catch (error) {
86
- // TODO: EDITOR-1921 - add error analytics
88
+ logException(error, {
89
+ location: 'editor-synced-block-provider/sourceInfo'
90
+ });
91
+ fireAnalyticsEvent === null || fireAnalyticsEvent === void 0 ? void 0 : fireAnalyticsEvent(getSourceInfoErrorPayload(error.message));
87
92
  return Promise.resolve(undefined);
88
93
  }
89
94
  };
@@ -1,22 +1,30 @@
1
1
  import { useCallback, useEffect, useState } from 'react';
2
+ import { logException } from '@atlaskit/editor-common/monitoring';
2
3
  import { SyncBlockError } from '../common/types';
4
+ import { fetchErrorPayload } from '../utils/errorHandling';
3
5
  import { createSyncBlockNode } from '../utils/utils';
4
- export const useFetchSyncBlockData = (manager, resourceId, localId) => {
6
+ export const useFetchSyncBlockData = (manager, resourceId, localId, fireAnalyticsEvent) => {
5
7
  const [syncBlockInstance, setSyncBlockInstance] = useState(null);
6
8
  const [isLoading, setIsLoading] = useState(true);
7
9
  const reloadData = useCallback(async () => {
8
10
  if (isLoading) {
9
11
  return;
10
12
  }
11
- const syncBlockNode = resourceId && localId ? createSyncBlockNode(localId, resourceId) : null;
12
- if (!syncBlockNode) {
13
- return;
14
- }
15
- setIsLoading(true);
16
13
  try {
14
+ const syncBlockNode = resourceId && localId ? createSyncBlockNode(localId, resourceId) : null;
15
+ if (!syncBlockNode) {
16
+ throw new Error('Failed to create sync block node from resourceid and localid');
17
+ }
18
+ setIsLoading(true);
19
+
17
20
  // Fetch sync block data, the `subscribeToSyncBlock` will update the state once data is fetched
18
21
  await manager.referenceManager.fetchSyncBlocksData([syncBlockNode]);
19
22
  } catch (error) {
23
+ logException(error, {
24
+ location: 'editor-synced-block-provider/useFetchSyncBlockData'
25
+ });
26
+ fireAnalyticsEvent === null || fireAnalyticsEvent === void 0 ? void 0 : fireAnalyticsEvent(fetchErrorPayload(error.message));
27
+
20
28
  // Set error state if fetching fails
21
29
  setSyncBlockInstance({
22
30
  resourceId: resourceId || '',
@@ -24,7 +32,7 @@ export const useFetchSyncBlockData = (manager, resourceId, localId) => {
24
32
  });
25
33
  }
26
34
  setIsLoading(false);
27
- }, [isLoading, localId, manager.referenceManager, resourceId]);
35
+ }, [isLoading, localId, manager.referenceManager, resourceId, fireAnalyticsEvent]);
28
36
  useEffect(() => {
29
37
  const unsubscribe = manager.referenceManager.subscribeToSyncBlock(resourceId || '', localId || '', data => {
30
38
  setSyncBlockInstance(data);
@@ -1,10 +1,6 @@
1
1
  import { useEffect } from 'react';
2
2
  export const useHandleContentChanges = (manager, syncBlockNode) => {
3
3
  useEffect(() => {
4
- try {
5
- manager.sourceManager.updateSyncBlockData(syncBlockNode);
6
- } catch {
7
- //TODO: EDITOR-1921 - add error analytics
8
- }
4
+ manager.sourceManager.updateSyncBlockData(syncBlockNode);
9
5
  }, [manager, syncBlockNode]);
10
6
  };
@@ -62,6 +62,11 @@ class BlockServiceADFFetchProvider {
62
62
  * ADFWriteProvider implementation that writes synced block data to Block Service API
63
63
  */
64
64
  class BlockServiceADFWriteProvider {
65
+ constructor(sourceAri, product) {
66
+ this.sourceAri = sourceAri;
67
+ this.product = product;
68
+ }
69
+
65
70
  // it will first try to update and if it can't (404) then it will try to create
66
71
  async writeData(data) {
67
72
  const {
@@ -83,8 +88,8 @@ class BlockServiceADFWriteProvider {
83
88
  await createSyncedBlock({
84
89
  blockAri: resourceId,
85
90
  blockInstanceId: data.blockInstanceId,
86
- sourceAri: resourceId,
87
- product: 'confluence-page',
91
+ sourceAri: this.sourceAri,
92
+ product: this.product,
88
93
  content: JSON.stringify(data.content)
89
94
  });
90
95
  } else {
@@ -127,22 +132,22 @@ class BlockServiceADFWriteProvider {
127
132
  };
128
133
  }
129
134
  }
130
- generateResourceId(sourceId, localId) {
131
- return blockResourceIdFromSourceAndLocalId(sourceId, localId);
135
+ generateResourceId(sourceAri, localId) {
136
+ return blockResourceIdFromSourceAndLocalId(sourceAri, localId);
132
137
  }
133
138
  }
134
139
 
135
140
  /**
136
141
  * Factory function to create both providers with shared configuration
137
142
  */
138
- const createBlockServiceAPIProviders = () => {
143
+ const createBlockServiceAPIProviders = (sourceAri, product) => {
139
144
  const fetchProvider = new BlockServiceADFFetchProvider();
140
- const writeProvider = new BlockServiceADFWriteProvider();
145
+ const writeProvider = new BlockServiceADFWriteProvider(sourceAri, product);
141
146
  return {
142
147
  fetchProvider,
143
148
  writeProvider
144
149
  };
145
150
  };
146
- export const useMemoizedBlockServiceAPIProviders = () => {
147
- return useMemo(createBlockServiceAPIProviders, []);
151
+ export const useMemoizedBlockServiceAPIProviders = (sourceAri, product) => {
152
+ return useMemo(() => createBlockServiceAPIProviders(sourceAri, product), [sourceAri, product]);
148
153
  };
@@ -61,7 +61,7 @@ export class SyncBlockProvider extends SyncBlockDataProvider {
61
61
  return data;
62
62
  }, () => {
63
63
  return {
64
- status: SyncBlockError.Errored,
64
+ error: SyncBlockError.Errored,
65
65
  resourceId
66
66
  };
67
67
  });
@@ -139,13 +139,13 @@ export class SyncBlockProvider extends SyncBlockDataProvider {
139
139
  *
140
140
  * @returns The source info
141
141
  */
142
- fetchSyncBlockSourceInfo(localId, sourceAri, sourceProduct) {
142
+ fetchSyncBlockSourceInfo(localId, sourceAri, sourceProduct, fireAnalyticsEvent) {
143
143
  if (!sourceAri || !sourceProduct) {
144
- return Promise.resolve(undefined);
144
+ return Promise.reject(new Error('Source ari or source product is undefined'));
145
145
  }
146
146
  switch (sourceProduct) {
147
147
  case 'confluence-page':
148
- return fetchConfluencePageInfo(sourceAri, localId);
148
+ return fetchConfluencePageInfo(sourceAri, localId, fireAnalyticsEvent);
149
149
  case 'jira-work-item':
150
150
  return Promise.reject(new Error('Jira work item source product not supported'));
151
151
  default: