@atlaskit/editor-plugin-synced-block 5.3.0 → 5.3.2

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 (43) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/afm-cc/tsconfig.json +4 -1
  3. package/dist/cjs/editor-commands/index.js +4 -0
  4. package/dist/cjs/pm-plugins/main.js +8 -1
  5. package/dist/cjs/pm-plugins/utils/handle-bodied-sync-block-removal.js +2 -2
  6. package/dist/cjs/ui/DeleteConfirmationModal.compiled.css +2 -0
  7. package/dist/cjs/ui/DeleteConfirmationModal.js +151 -13
  8. package/dist/cjs/ui/SyncBlockLabel.js +82 -38
  9. package/dist/cjs/ui/SyncBlockRendererWrapper.js +8 -3
  10. package/dist/cjs/ui/SyncedLocationDropdown.js +9 -3
  11. package/dist/cjs/ui/floating-toolbar.js +2 -2
  12. package/dist/cjs/ui/utils/time.js +63 -0
  13. package/dist/es2019/editor-commands/index.js +4 -0
  14. package/dist/es2019/pm-plugins/main.js +8 -1
  15. package/dist/es2019/pm-plugins/utils/handle-bodied-sync-block-removal.js +2 -2
  16. package/dist/es2019/ui/DeleteConfirmationModal.compiled.css +2 -0
  17. package/dist/es2019/ui/DeleteConfirmationModal.js +121 -12
  18. package/dist/es2019/ui/SyncBlockLabel.js +52 -17
  19. package/dist/es2019/ui/SyncBlockRendererWrapper.js +8 -3
  20. package/dist/es2019/ui/SyncedLocationDropdown.js +9 -3
  21. package/dist/es2019/ui/floating-toolbar.js +2 -2
  22. package/dist/es2019/ui/utils/time.js +56 -0
  23. package/dist/esm/editor-commands/index.js +4 -0
  24. package/dist/esm/pm-plugins/main.js +8 -1
  25. package/dist/esm/pm-plugins/utils/handle-bodied-sync-block-removal.js +2 -2
  26. package/dist/esm/ui/DeleteConfirmationModal.compiled.css +2 -0
  27. package/dist/esm/ui/DeleteConfirmationModal.js +152 -14
  28. package/dist/esm/ui/SyncBlockLabel.js +80 -38
  29. package/dist/esm/ui/SyncBlockRendererWrapper.js +8 -3
  30. package/dist/esm/ui/SyncedLocationDropdown.js +9 -3
  31. package/dist/esm/ui/floating-toolbar.js +2 -2
  32. package/dist/esm/ui/utils/time.js +56 -0
  33. package/dist/types/pm-plugins/utils/handle-bodied-sync-block-removal.d.ts +2 -2
  34. package/dist/types/syncedBlockPluginType.d.ts +1 -1
  35. package/dist/types/ui/SyncBlockLabel.d.ts +3 -2
  36. package/dist/types/ui/SyncBlockRendererWrapper.d.ts +2 -2
  37. package/dist/types/ui/utils/time.d.ts +2 -0
  38. package/dist/types-ts4.5/pm-plugins/utils/handle-bodied-sync-block-removal.d.ts +2 -2
  39. package/dist/types-ts4.5/syncedBlockPluginType.d.ts +1 -1
  40. package/dist/types-ts4.5/ui/SyncBlockLabel.d.ts +3 -2
  41. package/dist/types-ts4.5/ui/SyncBlockRendererWrapper.d.ts +2 -2
  42. package/dist/types-ts4.5/ui/utils/time.d.ts +2 -0
  43. package/package.json +7 -6
package/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # @atlaskit/editor-plugin-synced-block
2
2
 
3
+ ## 5.3.2
4
+
5
+ ### Patch Changes
6
+
7
+ - [`41d5a8796f3e1`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/41d5a8796f3e1) -
8
+ [EDITOR-4472] Update content copy for sync block
9
+ - [`28434cbe03f1e`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/28434cbe03f1e) -
10
+ [ux] [EDITOR-2851]
11
+ - Implement unsync feature for source sync block
12
+ - Update deletion confirmation modal and reference block UI after source deletion
13
+
14
+ - Updated dependencies
15
+
16
+ ## 5.3.1
17
+
18
+ ### Patch Changes
19
+
20
+ - [`87abc5dda86fe`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/87abc5dda86fe) -
21
+ [ux] Show last edited time in sync block tooltip
22
+ - Updated dependencies
23
+
3
24
  ## 5.3.0
4
25
 
5
26
  ### Minor Changes
@@ -7,7 +7,10 @@
7
7
  "composite": true,
8
8
  "noCheck": true
9
9
  },
10
- "include": ["../src/**/*.ts", "../src/**/*.tsx"],
10
+ "include": [
11
+ "../src/**/*.ts",
12
+ "../src/**/*.tsx"
13
+ ],
11
14
  "exclude": [
12
15
  "../src/**/__tests__/*",
13
16
  "../src/**/*.test.*",
@@ -193,6 +193,10 @@ var unsync = exports.unsync = function unsync(storeManager, isBodiedSyncBlock, v
193
193
  return false;
194
194
  }
195
195
  if (isBodiedSyncBlock) {
196
+ var content = syncBlock === null || syncBlock === void 0 ? void 0 : syncBlock.node.content;
197
+ var tr = state.tr;
198
+ tr.replaceWith(syncBlock.pos, syncBlock.pos + syncBlock.node.nodeSize, content).setMeta('deletionReason', 'source-block-unsynced');
199
+ view.dispatch(tr);
196
200
  return true;
197
201
  }
198
202
 
@@ -43,6 +43,13 @@ var showCopiedFlag = function showCopiedFlag(api) {
43
43
  });
44
44
  }, 0);
45
45
  };
46
+ var getDeleteReason = function getDeleteReason(tr) {
47
+ var reason = tr.getMeta('deletionReason');
48
+ if (!reason) {
49
+ return 'source-block-deleted';
50
+ }
51
+ return reason;
52
+ };
46
53
  var createPlugin = exports.createPlugin = function createPlugin(options, pmPluginFactoryParams, syncBlockStore, api) {
47
54
  var _ref2 = options || {},
48
55
  _ref2$useLongPressSel = _ref2.useLongPressSelection,
@@ -206,7 +213,7 @@ var createPlugin = exports.createPlugin = function createPlugin(options, pmPlugi
206
213
  if (!isOffline) {
207
214
  if (bodiedSyncBlockRemoved.length > 0) {
208
215
  confirmationTransactionRef.current = tr;
209
- return (0, _handleBodiedSyncBlockRemoval.handleBodiedSyncBlockRemoval)(tr, bodiedSyncBlockRemoved, syncBlockStore, api, confirmationTransactionRef);
216
+ return (0, _handleBodiedSyncBlockRemoval.handleBodiedSyncBlockRemoval)(bodiedSyncBlockRemoved, syncBlockStore, api, confirmationTransactionRef, (0, _platformFeatureFlags.fg)('platform_synced_block_dogfooding') ? getDeleteReason(tr) : undefined);
210
217
  }
211
218
  if (bodiedSyncBlockAdded.length > 0) {
212
219
  if (Boolean(tr.getMeta(_utils.pmHistoryPluginKey))) {
@@ -32,7 +32,7 @@ var onDismissed = function onDismissed(syncBlockStore) {
32
32
  });
33
33
  };
34
34
  };
35
- var handleBodiedSyncBlockRemoval = exports.handleBodiedSyncBlockRemoval = function handleBodiedSyncBlockRemoval(tr, bodiedSyncBlockRemoved, syncBlockStore, api, confirmationTransactionRef) {
35
+ var handleBodiedSyncBlockRemoval = exports.handleBodiedSyncBlockRemoval = function handleBodiedSyncBlockRemoval(bodiedSyncBlockRemoved, syncBlockStore, api, confirmationTransactionRef, deletionReason) {
36
36
  // Clear potential old pending deletion to retreat the deletion as first attempt
37
37
  syncBlockStore.sourceManager.clearPendingDeletion();
38
38
 
@@ -42,7 +42,7 @@ var handleBodiedSyncBlockRemoval = exports.handleBodiedSyncBlockRemoval = functi
42
42
  // proceed with deletion.
43
43
  syncBlockStore.sourceManager.deleteSyncBlocksWithConfirmation(bodiedSyncBlockRemoved.map(function (node) {
44
44
  return node.attrs;
45
- }), function () {
45
+ }), deletionReason, function () {
46
46
  var _api$core2;
47
47
  var confirmationTransaction = confirmationTransactionRef.current;
48
48
  if (!confirmationTransaction) {
@@ -0,0 +1,2 @@
1
+ ._195g1wug{margin-inline:auto}
2
+ ._1mou1wug{margin-block:auto}
@@ -1,3 +1,4 @@
1
+ /* DeleteConfirmationModal.tsx generated by @compiled/babel-plugin v0.38.1 */
1
2
  "use strict";
2
3
 
3
4
  var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
@@ -6,6 +7,10 @@ Object.defineProperty(exports, "__esModule", {
6
7
  value: true
7
8
  });
8
9
  exports.DeleteConfirmationModal = void 0;
10
+ require("./DeleteConfirmationModal.compiled.css");
11
+ var _runtime = require("@compiled/react/runtime");
12
+ var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
13
+ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
9
14
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
10
15
  var _react = _interopRequireWildcard(require("react"));
11
16
  var _reactIntlNext = require("react-intl-next");
@@ -16,20 +21,52 @@ var _editorPluginConnectivity = require("@atlaskit/editor-plugin-connectivity");
16
21
  var _modalDialog = _interopRequireWildcard(require("@atlaskit/modal-dialog"));
17
22
  var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
18
23
  var _compiled = require("@atlaskit/primitives/compiled");
24
+ var _spinner = _interopRequireDefault(require("@atlaskit/spinner"));
19
25
  var _main = require("../pm-plugins/main");
20
26
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
27
+ var modalContentMap = {
28
+ 'source-block-deleted': {
29
+ titleMultiple: _messages.syncBlockMessages.deleteConfirmationModalTitleSingle,
30
+ titleSingle: _messages.syncBlockMessages.deleteConfirmationModalTitleSingle,
31
+ descriptionSingle: _messages.syncBlockMessages.deleteConfirmationModalDescriptionNoRef,
32
+ descriptionMultiple: _messages.syncBlockMessages.deleteConfirmationModalDescription,
33
+ confirmButtonLabel: _messages.syncBlockMessages.deleteConfirmationModalDeleteButton
34
+ },
35
+ 'source-block-unsynced': {
36
+ titleMultiple: _messages.syncBlockMessages.unsyncConfirmationModalTitle,
37
+ titleSingle: _messages.syncBlockMessages.unsyncConfirmationModalTitle,
38
+ descriptionSingle: _messages.syncBlockMessages.unsyncConfirmationModalDescriptionSingle,
39
+ descriptionMultiple: _messages.syncBlockMessages.unsyncConfirmationModalDescriptionMultiple,
40
+ confirmButtonLabel: _messages.syncBlockMessages.deleteConfirmationModalUnsyncButton
41
+ }
42
+ };
43
+ var styles = {
44
+ spinner: "_1mou1wug _195g1wug"
45
+ };
21
46
  var DeleteConfirmationModal = exports.DeleteConfirmationModal = function DeleteConfirmationModal(_ref) {
22
- var _api$core2, _api$core4, _api$core6;
47
+ var _api$core2, _api$core4, _api$core6, _syncBlockIds$length;
23
48
  var syncBlockStoreManager = _ref.syncBlockStoreManager,
24
49
  api = _ref.api;
25
50
  var _useState = (0, _react.useState)(false),
26
51
  _useState2 = (0, _slicedToArray2.default)(_useState, 2),
27
52
  isOpen = _useState2[0],
28
53
  setIsOpen = _useState2[1];
29
- var _useState3 = (0, _react.useState)(1),
54
+ var _useState3 = (0, _react.useState)(undefined),
30
55
  _useState4 = (0, _slicedToArray2.default)(_useState3, 2),
31
- syncBlockCount = _useState4[0],
32
- setSyncBlockCount = _useState4[1];
56
+ syncBlockIds = _useState4[0],
57
+ setSyncBlockIds = _useState4[1];
58
+ var _useState5 = (0, _react.useState)(undefined),
59
+ _useState6 = (0, _slicedToArray2.default)(_useState5, 2),
60
+ referenceCount = _useState6[0],
61
+ setReferenceCount = _useState6[1];
62
+ var _useState7 = (0, _react.useState)('source-block-deleted'),
63
+ _useState8 = (0, _slicedToArray2.default)(_useState7, 2),
64
+ deleteReason = _useState8[0],
65
+ setDeleteReason = _useState8[1];
66
+ var _useState9 = (0, _react.useState)('none'),
67
+ _useState0 = (0, _slicedToArray2.default)(_useState9, 2),
68
+ fetchStatus = _useState0[0],
69
+ setFetchStatus = _useState0[1];
33
70
  var _useSharedPluginState = (0, _hooks.useSharedPluginStateWithSelector)(api, ['connectivity', 'syncedBlock'], function (states) {
34
71
  var _states$connectivityS, _states$syncedBlockSt, _states$syncedBlockSt2;
35
72
  return {
@@ -53,6 +90,8 @@ var DeleteConfirmationModal = exports.DeleteConfirmationModal = function DeleteC
53
90
  }
54
91
  if (!confirm) {
55
92
  setIsOpen(false);
93
+ setFetchStatus('none');
94
+ setReferenceCount(undefined);
56
95
  }
57
96
  api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(function (_ref2) {
58
97
  var tr = _ref2.tr;
@@ -63,9 +102,12 @@ var DeleteConfirmationModal = exports.DeleteConfirmationModal = function DeleteC
63
102
  });
64
103
  };
65
104
  }, [api === null || api === void 0 || (_api$core2 = api.core) === null || _api$core2 === void 0 ? void 0 : _api$core2.actions]);
66
- var confirmationCallback = (0, _react.useCallback)(function (syncBlockCount) {
105
+ var confirmationCallback = (0, _react.useCallback)(function (syncBlockIds, deleteReason) {
67
106
  setIsOpen(true);
68
- setSyncBlockCount(syncBlockCount);
107
+ setSyncBlockIds(syncBlockIds);
108
+ if (deleteReason) {
109
+ setDeleteReason(deleteReason);
110
+ }
69
111
  var confirmedPromise = new Promise(function (resolve) {
70
112
  resolverRef.current = resolve;
71
113
  });
@@ -92,6 +134,7 @@ var DeleteConfirmationModal = exports.DeleteConfirmationModal = function DeleteC
92
134
  var _api$core5;
93
135
  // auto close modal once deletion is successful
94
136
  setIsOpen(false);
137
+ setFetchStatus('none');
95
138
  api === null || api === void 0 || (_api$core5 = api.core) === null || _api$core5 === void 0 || _api$core5.actions.execute(function (_ref4) {
96
139
  var tr = _ref4.tr;
97
140
  return tr.setMeta(_main.syncedBlockPluginKey, {
@@ -101,15 +144,76 @@ var DeleteConfirmationModal = exports.DeleteConfirmationModal = function DeleteC
101
144
  });
102
145
  }
103
146
  }, [api === null || api === void 0 || (_api$core6 = api.core) === null || _api$core6 === void 0 ? void 0 : _api$core6.actions, bodiedSyncBlockDeletionStatus, isOpen]);
147
+ (0, _react.useEffect)(function () {
148
+ if (isOpen && syncBlockIds !== undefined && (0, _platformFeatureFlags.fg)('platform_synced_block_dogfooding')) {
149
+ var _referenceCount = 0;
150
+ setFetchStatus('loading');
151
+ var fetchFailed = false;
152
+ syncBlockIds.forEach( /*#__PURE__*/function () {
153
+ var _ref5 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(syncBlockId) {
154
+ var references, _references$reference, _references$reference2;
155
+ return _regenerator.default.wrap(function _callee$(_context) {
156
+ while (1) switch (_context.prev = _context.next) {
157
+ case 0:
158
+ if (!fetchFailed) {
159
+ _context.next = 2;
160
+ break;
161
+ }
162
+ return _context.abrupt("return");
163
+ case 2:
164
+ _context.next = 4;
165
+ return syncBlockStoreManager.sourceManager.fetchReferences(syncBlockId.resourceId);
166
+ case 4:
167
+ references = _context.sent;
168
+ if (!references.error) {
169
+ _context.next = 11;
170
+ break;
171
+ }
172
+ // Consider fetch fails as soon as one of the fetches fails
173
+ setFetchStatus('error');
174
+ fetchFailed = true;
175
+ return _context.abrupt("return");
176
+ case 11:
177
+ _referenceCount += (_references$reference = (_references$reference2 = references.references) === null || _references$reference2 === void 0 ? void 0 : _references$reference2.length) !== null && _references$reference !== void 0 ? _references$reference : 0;
178
+ case 12:
179
+ case "end":
180
+ return _context.stop();
181
+ }
182
+ }, _callee);
183
+ }));
184
+ return function (_x) {
185
+ return _ref5.apply(this, arguments);
186
+ };
187
+ }());
188
+ if (!fetchFailed) {
189
+ setReferenceCount(_referenceCount);
190
+ setFetchStatus('success');
191
+ }
192
+ }
193
+ }, [isOpen, syncBlockIds, syncBlockStoreManager.sourceManager]);
104
194
  return /*#__PURE__*/_react.default.createElement(_modalDialog.ModalTransition, null, isOpen && /*#__PURE__*/_react.default.createElement(_modalDialog.default, {
105
195
  onClose: handleClick(false),
106
- testId: "sync-block-delete-confirmation"
107
- }, /*#__PURE__*/_react.default.createElement(_modalDialog.ModalHeader, {
196
+ testId: "sync-block-delete-confirmation",
197
+ height: 184
198
+ }, (0, _platformFeatureFlags.fg)('platform_synced_block_dogfooding') ? /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, referenceCount === undefined ? /*#__PURE__*/_react.default.createElement(_compiled.Box, {
199
+ xcss: styles.spinner
200
+ }, /*#__PURE__*/_react.default.createElement(_spinner.default, {
201
+ size: "large"
202
+ })) : /*#__PURE__*/_react.default.createElement(ModalContent, {
203
+ content: modalContentMap[deleteReason],
204
+ referenceCount: referenceCount,
205
+ handleClick: handleClick,
206
+ formatMessage: formatMessage,
207
+ isDeleting: bodiedSyncBlockDeletionStatus === 'processing',
208
+ isDisabled: (0, _editorPluginConnectivity.isOfflineMode)(mode),
209
+ deleteReason: deleteReason,
210
+ failToFetch: fetchStatus === 'error'
211
+ })) : /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_modalDialog.ModalHeader, {
108
212
  hasCloseButton: true
109
213
  }, /*#__PURE__*/_react.default.createElement(_modalDialog.ModalTitle, {
110
214
  appearance: "warning"
111
- }, formatMessage(_messages.syncBlockMessages.deleteConfirmationModalTitle))), /*#__PURE__*/_react.default.createElement(_modalDialog.ModalBody, null, /*#__PURE__*/_react.default.createElement(_compiled.Text, null, formatMessage(_messages.syncBlockMessages.deleteConfirmationModalDescription, {
112
- syncBlockCount: syncBlockCount
215
+ }, formatMessage(_messages.syncBlockMessages.deleteConfirmationModalTitleSingle))), /*#__PURE__*/_react.default.createElement(_modalDialog.ModalBody, null, /*#__PURE__*/_react.default.createElement(_compiled.Text, null, formatMessage(_messages.syncBlockMessages.deleteConfirmationModalDescription, {
216
+ syncBlockCount: (_syncBlockIds$length = syncBlockIds === null || syncBlockIds === void 0 ? void 0 : syncBlockIds.length) !== null && _syncBlockIds$length !== void 0 ? _syncBlockIds$length : 1
113
217
  }))), /*#__PURE__*/_react.default.createElement(_modalDialog.ModalFooter, null, /*#__PURE__*/_react.default.createElement(_new.default, {
114
218
  appearance: "subtle",
115
219
  onClick: handleClick(false)
@@ -118,7 +222,41 @@ var DeleteConfirmationModal = exports.DeleteConfirmationModal = function DeleteC
118
222
  onClick: handleClick(true),
119
223
  autoFocus: true,
120
224
  isDisabled: (0, _editorPluginConnectivity.isOfflineMode)(mode),
121
- isLoading: bodiedSyncBlockDeletionStatus === 'processing',
122
- testId: (0, _platformFeatureFlags.fg)('platform_synced_block_dogfooding') ? 'synced-block-delete-confirmation-modal-delete-button' : undefined
123
- }, formatMessage(_messages.syncBlockMessages.deleteConfirmationModalDeleteButton)))));
225
+ isLoading: bodiedSyncBlockDeletionStatus === 'processing'
226
+ }, formatMessage(_messages.syncBlockMessages.deleteConfirmationModalDeleteButton))))));
227
+ };
228
+ var ModalContent = function ModalContent(_ref6) {
229
+ var content = _ref6.content,
230
+ referenceCount = _ref6.referenceCount,
231
+ handleClick = _ref6.handleClick,
232
+ formatMessage = _ref6.formatMessage,
233
+ isDeleting = _ref6.isDeleting,
234
+ isDisabled = _ref6.isDisabled,
235
+ deleteReason = _ref6.deleteReason,
236
+ failToFetch = _ref6.failToFetch;
237
+ var titleMultiple = content.titleMultiple,
238
+ titleSingle = content.titleSingle,
239
+ descriptionSingle = content.descriptionSingle,
240
+ descriptionMultiple = content.descriptionMultiple,
241
+ confirmButtonLabel = content.confirmButtonLabel;
242
+ var hasNoReferenceOrFailToFetch = referenceCount === 0 || failToFetch;
243
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_modalDialog.ModalHeader, {
244
+ hasCloseButton: true
245
+ }, /*#__PURE__*/_react.default.createElement(_modalDialog.ModalTitle, {
246
+ appearance: "warning"
247
+ }, hasNoReferenceOrFailToFetch ? formatMessage(titleSingle) : formatMessage(titleMultiple, {
248
+ count: referenceCount
249
+ }))), /*#__PURE__*/_react.default.createElement(_modalDialog.ModalBody, null, /*#__PURE__*/_react.default.createElement(_compiled.Text, null, hasNoReferenceOrFailToFetch ? formatMessage(descriptionSingle) : formatMessage(descriptionMultiple, {
250
+ syncBlockCount: referenceCount
251
+ }))), /*#__PURE__*/_react.default.createElement(_modalDialog.ModalFooter, null, /*#__PURE__*/_react.default.createElement(_new.default, {
252
+ appearance: "subtle",
253
+ onClick: handleClick(false)
254
+ }, formatMessage(_messages.syncBlockMessages.deleteConfirmationModalCancelButton)), /*#__PURE__*/_react.default.createElement(_new.default, {
255
+ appearance: "warning",
256
+ onClick: handleClick(true),
257
+ autoFocus: true,
258
+ isDisabled: isDisabled,
259
+ isLoading: isDeleting,
260
+ testId: "synced-block-delete-confirmation-modal-".concat(deleteReason, "-button")
261
+ }, formatMessage(confirmButtonLabel))));
124
262
  };
@@ -1,57 +1,101 @@
1
1
  "use strict";
2
2
 
3
3
  var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ var _typeof = require("@babel/runtime/helpers/typeof");
4
5
  Object.defineProperty(exports, "__esModule", {
5
6
  value: true
6
7
  });
7
8
  exports.SyncBlockLabel = void 0;
8
- var _react = _interopRequireDefault(require("react"));
9
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
10
+ var _react = _interopRequireWildcard(require("react"));
9
11
  var _reactIntlNext = require("react-intl-next");
10
12
  var _messages = require("@atlaskit/editor-common/messages");
11
13
  var _syncBlock = require("@atlaskit/editor-common/sync-block");
12
14
  var _blockSynced = _interopRequireDefault(require("@atlaskit/icon-lab/core/block-synced"));
15
+ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
13
16
  var _compiled = require("@atlaskit/primitives/compiled");
14
17
  var _tooltip = _interopRequireDefault(require("@atlaskit/tooltip"));
15
18
  var _visuallyHidden = _interopRequireDefault(require("@atlaskit/visually-hidden"));
19
+ var _time = require("./utils/time");
20
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
16
21
  var SyncBlockLabelDataId = 'sync-block-label';
17
22
  var SyncBlockLabelComponent = function SyncBlockLabelComponent(_ref) {
18
- var isSource = _ref.isSource,
19
- useFetchSyncBlockTitle = _ref.useFetchSyncBlockTitle,
20
- localId = _ref.localId;
21
- var _useIntl = (0, _reactIntlNext.useIntl)(),
22
- formatMessage = _useIntl.formatMessage;
23
- var title = useFetchSyncBlockTitle === null || useFetchSyncBlockTitle === void 0 ? void 0 : useFetchSyncBlockTitle();
24
- var tooltipContent = isSource ? formatMessage(_messages.syncBlockMessages.sourceSyncBlockTooltip) : title ? formatMessage(_messages.syncBlockMessages.referenceSyncBlockTooltip, {
25
- title: title
26
- }) : formatMessage(_messages.syncBlockMessages.defaultSyncBlockTooltip);
23
+ var contentUpdatedAt = _ref.contentUpdatedAt,
24
+ isSource = _ref.isSource,
25
+ localId = _ref.localId,
26
+ title = _ref.title;
27
+ var intl = (0, _reactIntlNext.useIntl)();
28
+ var formatMessage = intl.formatMessage;
29
+ var _useState = (0, _react.useState)(formatMessage(_messages.syncBlockMessages.defaultSyncBlockTooltip)),
30
+ _useState2 = (0, _slicedToArray2.default)(_useState, 2),
31
+ tooltipContent = _useState2[0],
32
+ setTooltipContent = _useState2[1];
33
+ var tooltipMessage = formatMessage(_messages.syncBlockMessages.defaultSyncBlockTooltip);
34
+ if (isSource && !(0, _platformFeatureFlags.fg)('platform_synced_block_dogfooding')) {
35
+ tooltipMessage = formatMessage(_messages.syncBlockMessages.sourceSyncBlockTooltip);
36
+ } else if (title) {
37
+ tooltipMessage = formatMessage(_messages.syncBlockMessages.referenceSyncBlockTooltip, {
38
+ title: title
39
+ });
40
+ }
41
+ var updateTooltipContent = (0, _react.useCallback)(function () {
42
+ if (!(0, _platformFeatureFlags.fg)('platform_synced_block_dogfooding')) {
43
+ return;
44
+ }
45
+ var tooltipContent = tooltipMessage;
46
+ if (contentUpdatedAt) {
47
+ var elapsedTime = (0, _time.formatElapsedTime)(contentUpdatedAt, intl);
48
+ tooltipContent = /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement(_compiled.Text, {
49
+ size: "small",
50
+ color: "color.text.inverse"
51
+ }, tooltipMessage), /*#__PURE__*/_react.default.createElement("br", null), /*#__PURE__*/_react.default.createElement("br", null), /*#__PURE__*/_react.default.createElement(_compiled.Text, {
52
+ size: "small",
53
+ color: "color.text.inverse",
54
+ weight: "bold"
55
+ }, formatMessage(_messages.syncBlockMessages.referenceSyncBlockLastEdited)), /*#__PURE__*/_react.default.createElement(_compiled.Text, {
56
+ size: "small",
57
+ color: "color.text.inverse"
58
+ }, elapsedTime));
59
+ }
60
+ setTooltipContent(tooltipContent);
61
+ }, [contentUpdatedAt, formatMessage, intl, tooltipMessage]);
27
62
  var ariaDescribedById = "sync-block-label-description-".concat(localId);
28
- return /*#__PURE__*/_react.default.createElement(_tooltip.default, {
29
- position: "top",
30
- content: tooltipContent
31
- // workaround because tooltip adds aria-describedby with a new id every time the tooltip is opened
32
- // this causes an infinite rerender loop because of the forwardRef from the node view we are inside in bodiedSyncBlock
33
- // tooltip content is available for screen readers in visually hidden content after the label
34
- ,
35
- isScreenReaderAnnouncementDisabled: true
36
- }, /*#__PURE__*/_react.default.createElement("div", {
37
- "data-testid": SyncBlockLabelDataId
38
- // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop
39
- ,
40
- className: _syncBlock.SyncBlockLabelSharedCssClassName.labelClassName,
41
- "aria-describedby": ariaDescribedById
42
- }, /*#__PURE__*/_react.default.createElement(_blockSynced.default, {
43
- color: "var(--ds-icon-subtle, #505258)",
44
- size: "small",
45
- label: ""
46
- }), isSource || !title ? /*#__PURE__*/_react.default.createElement(_compiled.Text, {
47
- size: "small",
48
- color: "color.text.subtle"
49
- }, formatMessage(_messages.syncBlockMessages.syncedBlockLabel)) : /*#__PURE__*/_react.default.createElement(_compiled.Text, {
50
- maxLines: 1,
51
- size: "small",
52
- color: "color.text.subtle"
53
- }, title)), /*#__PURE__*/_react.default.createElement(_visuallyHidden.default, {
54
- id: ariaDescribedById
55
- }, tooltipContent));
63
+ var LabelComponent = function LabelComponent() {
64
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("div", {
65
+ "data-testid": SyncBlockLabelDataId
66
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop
67
+ ,
68
+ className: _syncBlock.SyncBlockLabelSharedCssClassName.labelClassName,
69
+ "aria-describedby": ariaDescribedById
70
+ }, /*#__PURE__*/_react.default.createElement(_blockSynced.default, {
71
+ color: "var(--ds-icon-subtle, #505258)",
72
+ size: "small",
73
+ label: ""
74
+ }), isSource || !title ? /*#__PURE__*/_react.default.createElement(_compiled.Text, {
75
+ size: "small",
76
+ color: "color.text.subtle"
77
+ }, formatMessage(_messages.syncBlockMessages.syncedBlockLabel)) : /*#__PURE__*/_react.default.createElement(_compiled.Text, {
78
+ maxLines: 1,
79
+ size: "small",
80
+ color: "color.text.subtle"
81
+ }, title)), /*#__PURE__*/_react.default.createElement(_visuallyHidden.default, {
82
+ id: ariaDescribedById
83
+ }, tooltipContent));
84
+ };
85
+ var LabelWithTooltip = function LabelWithTooltip() {
86
+ return /*#__PURE__*/_react.default.createElement(_tooltip.default, {
87
+ position: "top",
88
+ content: (0, _platformFeatureFlags.fg)('platform_synced_block_dogfooding') ? tooltipContent : tooltipMessage
89
+ // workaround because tooltip adds aria-describedby with a new id every time the tooltip is opened
90
+ // this causes an infinite rerender loop because of the forwardRef from the node view we are inside in bodiedSyncBlock
91
+ // tooltip content is available for screen readers in visually hidden content after the label
92
+ ,
93
+ isScreenReaderAnnouncementDisabled: true
94
+ // using this to ensure that the 'last edited' time is updated when the tooltip is opened
95
+ ,
96
+ onShow: updateTooltipContent
97
+ }, /*#__PURE__*/_react.default.createElement(LabelComponent, null));
98
+ };
99
+ return (0, _platformFeatureFlags.fg)('platform_synced_block_dogfooding') ? isSource ? /*#__PURE__*/_react.default.createElement(LabelComponent, null) : /*#__PURE__*/_react.default.createElement(LabelWithTooltip, null) : /*#__PURE__*/_react.default.createElement(LabelWithTooltip, null);
56
100
  };
57
101
  var SyncBlockLabel = exports.SyncBlockLabel = /*#__PURE__*/_react.default.memo(SyncBlockLabelComponent);
@@ -10,22 +10,27 @@ var _syncBlock = require("@atlaskit/editor-common/sync-block");
10
10
  var _SyncBlockLabel = require("./SyncBlockLabel");
11
11
  var SyncBlockRendererWrapperDataId = 'sync-block-plugin-renderer-wrapper';
12
12
  var SyncBlockRendererWrapperComponent = function SyncBlockRendererWrapperComponent(_ref) {
13
+ var _syncBlockFetchResult;
13
14
  var syncedBlockRenderer = _ref.syncedBlockRenderer,
14
15
  useFetchSyncBlockData = _ref.useFetchSyncBlockData,
15
- localId = _ref.localId,
16
16
  useFetchSyncBlockTitle = _ref.useFetchSyncBlockTitle,
17
+ localId = _ref.localId,
17
18
  api = _ref.api;
19
+ var syncBlockFetchResult = useFetchSyncBlockData();
20
+ var title = useFetchSyncBlockTitle === null || useFetchSyncBlockTitle === void 0 ? void 0 : useFetchSyncBlockTitle();
21
+ var contentUpdatedAt = syncBlockFetchResult === null || syncBlockFetchResult === void 0 || (_syncBlockFetchResult = syncBlockFetchResult.syncBlockInstance) === null || _syncBlockFetchResult === void 0 || (_syncBlockFetchResult = _syncBlockFetchResult.data) === null || _syncBlockFetchResult === void 0 ? void 0 : _syncBlockFetchResult.contentUpdatedAt;
18
22
  return /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("div", {
19
23
  "data-testid": SyncBlockRendererWrapperDataId
20
24
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop
21
25
  ,
22
26
  className: _syncBlock.SyncBlockSharedCssClassName.renderer
23
27
  }, syncedBlockRenderer({
24
- useFetchSyncBlockData: useFetchSyncBlockData,
28
+ syncBlockFetchResult: syncBlockFetchResult,
25
29
  api: api
26
30
  })), /*#__PURE__*/_react.default.createElement(_SyncBlockLabel.SyncBlockLabel, {
27
31
  isSource: false,
28
- useFetchSyncBlockTitle: useFetchSyncBlockTitle,
32
+ title: title,
33
+ contentUpdatedAt: contentUpdatedAt,
29
34
  localId: localId
30
35
  }));
31
36
  };
@@ -16,6 +16,7 @@ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/
16
16
  var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
17
17
  var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
18
18
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
19
+ var _react2 = require("@compiled/react");
19
20
  var _dropdownMenu = _interopRequireWildcard(require("@atlaskit/dropdown-menu"));
20
21
  var _messages = require("@atlaskit/editor-common/messages");
21
22
  var _ui = require("@atlaskit/editor-common/ui");
@@ -46,13 +47,18 @@ var styles = {
46
47
  note: "_syaz1rpy _o5721q9c",
47
48
  lozenge: "_ahbq12x7 _1ul91wqb",
48
49
  noResultsContainer: "_1bsbo8uj _y3gn1h6o",
49
- dropdownContent: "_1rjcv77o _1bsbsmdz _1tkeqkoa _c71lko4j _1e0c1txw _1bah1h6o _4cvr1h6o",
50
+ dropdownContent: "_1rjcv77o _1bsbsmdz _c71lko4j _1e0c1txw _1bah1h6o _4cvr1h6o",
51
+ containerWithMinHeight: "_1tkeqkoa",
50
52
  contentContainer: "_y44vfmxe _1bsb1osq _1wpz1fhb _18m91wug",
51
53
  errorContainer: "_1bsbo8uj _1e0c1txw",
52
54
  errorIcon: "_1mour5cr",
53
55
  learnMoreLink: "_4bfu1r31 _1hmsglyw _ajmmnqa1",
54
56
  requestAccess: "_1bsb19n7 _o5721q9c _ahbq12x7 _syaz1rpy"
55
57
  };
58
+ var shouldApplyMinHeight = function shouldApplyMinHeight(fetchStatus, itemCount) {
59
+ // When there are 1/2 items, dropdown height is less than minHeight 144px
60
+ return !(fetchStatus === 'success' && itemCount > 0);
61
+ };
56
62
  var ItemTitle = function ItemTitle(_ref) {
57
63
  var title = _ref.title,
58
64
  formatMessage = _ref.formatMessage,
@@ -66,7 +72,7 @@ var ItemTitle = function ItemTitle(_ref) {
66
72
  }, title), onSameDocument && /*#__PURE__*/React.createElement(_compiled.Box, {
67
73
  as: "span",
68
74
  xcss: styles.note
69
- }, "\xA0- ", formatMessage(productType === 'confluence-page' ? _messages.syncBlockMessages.syncedLocationDropdownTitleNoteForConfluencePage : _messages.syncBlockMessages.syncedLocationDropdownTitleNoteForJiraWorkItem)), isSource && /*#__PURE__*/React.createElement(_compiled.Box, {
75
+ }, "\xA0-", ' ', formatMessage(productType === 'confluence-page' ? _messages.syncBlockMessages.syncedLocationDropdownTitleNoteForConfluencePage : _messages.syncBlockMessages.syncedLocationDropdownTitleNoteForJiraWorkItem)), isSource && /*#__PURE__*/React.createElement(_compiled.Box, {
70
76
  as: "span",
71
77
  xcss: styles.lozenge
72
78
  }, /*#__PURE__*/React.createElement(_lozenge.default, null, formatMessage(_messages.syncBlockMessages.syncedLocationDropdownSourceLozenge))), !hasAccess && /*#__PURE__*/React.createElement(_compiled.Box, {
@@ -293,7 +299,7 @@ var DropdownContent = function DropdownContent(_ref7) {
293
299
  }
294
300
  };
295
301
  return /*#__PURE__*/React.createElement(_compiled.Box, {
296
- xcss: styles.dropdownContent
302
+ xcss: (0, _react2.cx)(styles.dropdownContent, shouldApplyMinHeight(fetchStatus, referenceData.length) && styles.containerWithMinHeight)
297
303
  }, content());
298
304
  };
299
305
  var LoadingScreen = function LoadingScreen() {
@@ -26,13 +26,13 @@ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r
26
26
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
27
27
  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) { (0, _defineProperty2.default)(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; }
28
28
  var getToolbarConfig = exports.getToolbarConfig = function getToolbarConfig(state, intl, api, syncBlockStore) {
29
- var _api$decorations, _api$connectivity;
29
+ var _syncBlockInstance$er, _api$decorations, _api$connectivity;
30
30
  var syncBlockObject = (0, _utils2.findSyncBlockOrBodiedSyncBlock)(state.schema, state.selection);
31
31
  if (!syncBlockObject) {
32
32
  return;
33
33
  }
34
34
  var syncBlockInstance = syncBlockStore.referenceManager.getFromCache(syncBlockObject.node.attrs.resourceId);
35
- var isUnsyncedBlock = (syncBlockInstance === null || syncBlockInstance === void 0 ? void 0 : syncBlockInstance.error) === _editorSyncedBlockProvider.SyncBlockError.NotFound;
35
+ var isUnsyncedBlock = (syncBlockInstance === null || syncBlockInstance === void 0 || (_syncBlockInstance$er = syncBlockInstance.error) === null || _syncBlockInstance$er === void 0 ? void 0 : _syncBlockInstance$er.type) === _editorSyncedBlockProvider.SyncBlockError.NotFound;
36
36
  var isErroredBlock = syncBlockInstance === null || syncBlockInstance === void 0 ? void 0 : syncBlockInstance.error;
37
37
  var bodiedSyncBlock = state.schema.nodes.bodiedSyncBlock;
38
38
  var isBodiedSyncBlock = (0, _utils2.isBodiedSyncBlockNode)(syncBlockObject.node, bodiedSyncBlock);
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.formatElapsedTime = void 0;
8
+ var _isYesterday = _interopRequireDefault(require("date-fns/isYesterday"));
9
+ var SECONDS_IN_MINUTE = 60;
10
+ var SECONDS_IN_HOUR = SECONDS_IN_MINUTE * 60;
11
+ var SECONDS_IN_DAY = SECONDS_IN_HOUR * 24;
12
+ var SECONDS_IN_WEEK = SECONDS_IN_DAY * 7;
13
+ var SECONDS_IN_MONTH = SECONDS_IN_DAY * 30;
14
+ var SECONDS_IN_YEAR = SECONDS_IN_DAY * 365;
15
+ var formatElapsedTime = exports.formatElapsedTime = function formatElapsedTime(isoDate, intl) {
16
+ var now = Date.now();
17
+ var date = new Date(isoDate).getTime();
18
+ var diffInSeconds = Math.floor((now - date) / 1000);
19
+ var dateObj = new Date(isoDate);
20
+
21
+ // Show "yesterday" when timestamp is from the previous calendar day
22
+ if ((0, _isYesterday.default)(dateObj) && diffInSeconds >= SECONDS_IN_DAY) {
23
+ return intl.formatRelativeTime(-1, 'day', {
24
+ numeric: 'auto',
25
+ style: 'long'
26
+ });
27
+ }
28
+ if (diffInSeconds < SECONDS_IN_MINUTE) {
29
+ return intl.formatRelativeTime(-Math.max(diffInSeconds, 1), 'second', {
30
+ style: 'long'
31
+ });
32
+ } else if (diffInSeconds < SECONDS_IN_HOUR) {
33
+ var minutes = Math.floor(diffInSeconds / SECONDS_IN_MINUTE);
34
+ return intl.formatRelativeTime(-minutes, 'minute', {
35
+ style: 'long'
36
+ });
37
+ } else if (diffInSeconds < SECONDS_IN_DAY) {
38
+ var hours = Math.floor(diffInSeconds / SECONDS_IN_HOUR);
39
+ return intl.formatRelativeTime(-hours, 'hour', {
40
+ style: 'long'
41
+ });
42
+ } else if (diffInSeconds < SECONDS_IN_WEEK) {
43
+ var days = Math.floor(diffInSeconds / SECONDS_IN_DAY);
44
+ return intl.formatRelativeTime(-days, 'day', {
45
+ style: 'long'
46
+ });
47
+ } else if (diffInSeconds < SECONDS_IN_MONTH) {
48
+ var weeks = Math.floor(diffInSeconds / SECONDS_IN_WEEK);
49
+ return intl.formatRelativeTime(-weeks, 'week', {
50
+ style: 'long'
51
+ });
52
+ } else if (diffInSeconds < SECONDS_IN_YEAR) {
53
+ var months = Math.floor(diffInSeconds / SECONDS_IN_MONTH);
54
+ return intl.formatRelativeTime(-months, 'month', {
55
+ style: 'long'
56
+ });
57
+ } else {
58
+ var years = Math.floor(diffInSeconds / SECONDS_IN_YEAR);
59
+ return intl.formatRelativeTime(-years, 'year', {
60
+ style: 'long'
61
+ });
62
+ }
63
+ };
@@ -197,6 +197,10 @@ export const unsync = (storeManager, isBodiedSyncBlock, view) => {
197
197
  return false;
198
198
  }
199
199
  if (isBodiedSyncBlock) {
200
+ const content = syncBlock === null || syncBlock === void 0 ? void 0 : syncBlock.node.content;
201
+ const tr = state.tr;
202
+ tr.replaceWith(syncBlock.pos, syncBlock.pos + syncBlock.node.nodeSize, content).setMeta('deletionReason', 'source-block-unsynced');
203
+ view.dispatch(tr);
200
204
  return true;
201
205
  }
202
206