@atlaskit/editor-synced-block-provider 0.2.0 → 0.4.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 +14 -0
- package/dist/cjs/common/rebase-transaction.js +31 -0
- package/dist/cjs/common/syncBlockProvider.js +24 -12
- package/dist/cjs/common/syncBlockStoreManager.js +24 -11
- package/dist/cjs/index.js +34 -1
- package/dist/cjs/providers/confluenceContentAPI.js +238 -0
- package/dist/cjs/utils/ari.js +42 -0
- package/dist/cjs/utils/contentProperty.js +192 -0
- package/dist/es2019/common/rebase-transaction.js +26 -0
- package/dist/es2019/common/syncBlockProvider.js +25 -13
- package/dist/es2019/common/syncBlockStoreManager.js +18 -7
- package/dist/es2019/index.js +5 -2
- package/dist/es2019/providers/confluenceContentAPI.js +150 -0
- package/dist/es2019/utils/ari.js +32 -0
- package/dist/es2019/utils/contentProperty.js +160 -0
- package/dist/esm/common/rebase-transaction.js +26 -0
- package/dist/esm/common/syncBlockProvider.js +24 -12
- package/dist/esm/common/syncBlockStoreManager.js +24 -11
- package/dist/esm/index.js +5 -2
- package/dist/esm/providers/confluenceContentAPI.js +232 -0
- package/dist/esm/utils/ari.js +36 -0
- package/dist/esm/utils/contentProperty.js +185 -0
- package/dist/types/common/rebase-transaction.d.ts +11 -0
- package/dist/types/common/syncBlockProvider.d.ts +3 -1
- package/dist/types/common/syncBlockStoreManager.d.ts +5 -2
- package/dist/types/common/types.d.ts +1 -0
- package/dist/types/index.d.ts +5 -2
- package/dist/types/providers/confluenceContentAPI.d.ts +41 -0
- package/dist/types/utils/ari.d.ts +10 -0
- package/dist/types/utils/contentProperty.d.ts +61 -0
- package/dist/types-ts4.5/common/rebase-transaction.d.ts +11 -0
- package/dist/types-ts4.5/common/syncBlockProvider.d.ts +3 -1
- package/dist/types-ts4.5/common/syncBlockStoreManager.d.ts +5 -2
- package/dist/types-ts4.5/common/types.d.ts +1 -0
- package/dist/types-ts4.5/index.d.ts +5 -2
- package/dist/types-ts4.5/providers/confluenceContentAPI.d.ts +41 -0
- package/dist/types-ts4.5/utils/ari.d.ts +10 -0
- package/dist/types-ts4.5/utils/contentProperty.d.ts +61 -0
- package/package.json +2 -2
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { getConfluencePageAri } from './ari';
|
|
2
|
+
const COMMON_HEADERS = {
|
|
3
|
+
'Content-Type': 'application/json',
|
|
4
|
+
Accept: 'application/json'
|
|
5
|
+
};
|
|
6
|
+
const AGG_HEADERS = {
|
|
7
|
+
'X-ExperimentalApi': 'confluence-agg-beta'
|
|
8
|
+
};
|
|
9
|
+
const GRAPHQL_ENDPOINT = '/gateway/api/graphql';
|
|
10
|
+
const GET_OPERATION_NAME = 'EDITOR_SYNCED_BLOCK_GET';
|
|
11
|
+
const CREATE_OPERATION_NAME = 'EDITOR_SYNCED_BLOCK_CREATE';
|
|
12
|
+
const UPDATE_OPERATION_NAME = 'EDITOR_SYNCED_BLOCK_UPDATE';
|
|
13
|
+
/**
|
|
14
|
+
* Query to get the page property by key
|
|
15
|
+
* @param documentARI
|
|
16
|
+
* @param key
|
|
17
|
+
* @returns
|
|
18
|
+
*/
|
|
19
|
+
const GET_QUERY = `query ${GET_OPERATION_NAME} ($id: ID!, $keys: [String]!) {
|
|
20
|
+
confluence {
|
|
21
|
+
page (id: $id) {
|
|
22
|
+
properties(keys: $keys) {
|
|
23
|
+
key,
|
|
24
|
+
value
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}`;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Query to create a page property with key and value
|
|
32
|
+
* @param documentARI
|
|
33
|
+
* @param key
|
|
34
|
+
* @param value
|
|
35
|
+
* @returns
|
|
36
|
+
*/
|
|
37
|
+
const CREATE_QUERY = `mutation ${CREATE_OPERATION_NAME} ($input: ConfluenceCreatePagePropertyInput!){
|
|
38
|
+
confluence {
|
|
39
|
+
createPageProperty(input: $input) {
|
|
40
|
+
pageProperty {
|
|
41
|
+
key,
|
|
42
|
+
value
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}`;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Query to update a page property with key and value without bumping the version
|
|
50
|
+
* @param documentARI
|
|
51
|
+
* @param key
|
|
52
|
+
* @param value
|
|
53
|
+
* @returns
|
|
54
|
+
*/
|
|
55
|
+
const UPDATE_QUERY = `mutation ${UPDATE_OPERATION_NAME} ($input: ConfluenceUpdateValuePagePropertyInput!) {
|
|
56
|
+
confluence {
|
|
57
|
+
updateValuePageProperty(input: $input) {
|
|
58
|
+
pageProperty {
|
|
59
|
+
key,
|
|
60
|
+
value
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}`;
|
|
65
|
+
export const getContentProperty = async ({
|
|
66
|
+
pageId,
|
|
67
|
+
key,
|
|
68
|
+
cloudId
|
|
69
|
+
}) => {
|
|
70
|
+
const documentARI = getConfluencePageAri(pageId, cloudId);
|
|
71
|
+
const bodyData = {
|
|
72
|
+
query: GET_QUERY,
|
|
73
|
+
operationName: GET_OPERATION_NAME,
|
|
74
|
+
variables: {
|
|
75
|
+
id: documentARI,
|
|
76
|
+
keys: [key]
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
const response = await fetch(GRAPHQL_ENDPOINT, {
|
|
80
|
+
method: 'POST',
|
|
81
|
+
headers: {
|
|
82
|
+
...COMMON_HEADERS,
|
|
83
|
+
...AGG_HEADERS
|
|
84
|
+
},
|
|
85
|
+
body: JSON.stringify(bodyData)
|
|
86
|
+
});
|
|
87
|
+
if (!response.ok) {
|
|
88
|
+
throw new Error(`Failed to get content property: ${response.statusText}`);
|
|
89
|
+
}
|
|
90
|
+
const contentProperty = await response.json();
|
|
91
|
+
return contentProperty;
|
|
92
|
+
};
|
|
93
|
+
export const updateContentProperty = async ({
|
|
94
|
+
pageId,
|
|
95
|
+
key,
|
|
96
|
+
value,
|
|
97
|
+
cloudId
|
|
98
|
+
}) => {
|
|
99
|
+
const documentARI = getConfluencePageAri(pageId, cloudId);
|
|
100
|
+
const bodyData = {
|
|
101
|
+
query: UPDATE_QUERY,
|
|
102
|
+
operationName: UPDATE_OPERATION_NAME,
|
|
103
|
+
variables: {
|
|
104
|
+
input: {
|
|
105
|
+
pageId: documentARI,
|
|
106
|
+
key,
|
|
107
|
+
value,
|
|
108
|
+
useSameVersion: true
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
const response = await fetch(GRAPHQL_ENDPOINT, {
|
|
113
|
+
method: 'POST',
|
|
114
|
+
headers: {
|
|
115
|
+
...COMMON_HEADERS,
|
|
116
|
+
...AGG_HEADERS
|
|
117
|
+
},
|
|
118
|
+
body: JSON.stringify(bodyData)
|
|
119
|
+
});
|
|
120
|
+
if (!response.ok) {
|
|
121
|
+
throw new Error(`Failed to update content property: ${response.statusText}`);
|
|
122
|
+
}
|
|
123
|
+
const contentProperty = await response.json();
|
|
124
|
+
return contentProperty;
|
|
125
|
+
};
|
|
126
|
+
export const createContentProperty = async ({
|
|
127
|
+
pageId,
|
|
128
|
+
key,
|
|
129
|
+
value,
|
|
130
|
+
cloudId
|
|
131
|
+
}) => {
|
|
132
|
+
const documentARI = getConfluencePageAri(pageId, cloudId);
|
|
133
|
+
|
|
134
|
+
// eslint-disable-next-line require-unicode-regexp
|
|
135
|
+
const escapedValue = value.replace(/"/g, '\\"');
|
|
136
|
+
const bodyData = {
|
|
137
|
+
query: CREATE_QUERY,
|
|
138
|
+
operationName: CREATE_OPERATION_NAME,
|
|
139
|
+
variables: {
|
|
140
|
+
input: {
|
|
141
|
+
pageId: documentARI,
|
|
142
|
+
key,
|
|
143
|
+
value: escapedValue
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
const response = await fetch(GRAPHQL_ENDPOINT, {
|
|
148
|
+
method: 'POST',
|
|
149
|
+
headers: {
|
|
150
|
+
...COMMON_HEADERS,
|
|
151
|
+
...AGG_HEADERS
|
|
152
|
+
},
|
|
153
|
+
body: JSON.stringify(bodyData)
|
|
154
|
+
});
|
|
155
|
+
if (!response.ok) {
|
|
156
|
+
throw new Error(`Failed to create content property: ${response.statusText}`);
|
|
157
|
+
}
|
|
158
|
+
const contentProperty = await response.json();
|
|
159
|
+
return contentProperty;
|
|
160
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Mapping } from '@atlaskit/editor-prosemirror/transform';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Rebase `currentTr` over `incomingTr` based on the provided `state`.
|
|
5
|
+
* This function adjusts the steps in `currentTr` to account for the changes made by `incomingTr`.
|
|
6
|
+
*
|
|
7
|
+
* @param currentTr - The transaction to be rebased.
|
|
8
|
+
* @param incomingTr - The transaction that has already been applied to the state.
|
|
9
|
+
* @param state - The editor state after applying `incomingTr`.
|
|
10
|
+
* @returns A new transaction that represents `currentTr` rebased over `incomingTr`.
|
|
11
|
+
*/
|
|
12
|
+
export var rebaseTransaction = function rebaseTransaction(currentTr, incomingTr, state) {
|
|
13
|
+
if (!incomingTr.docChanged) {
|
|
14
|
+
return currentTr;
|
|
15
|
+
}
|
|
16
|
+
var currentMapping = new Mapping(incomingTr.mapping.maps);
|
|
17
|
+
var rebasedTransaction = state.tr;
|
|
18
|
+
currentTr.steps.forEach(function (step) {
|
|
19
|
+
var mappedStep = step.map(currentMapping);
|
|
20
|
+
if (mappedStep) {
|
|
21
|
+
rebasedTransaction.step(mappedStep);
|
|
22
|
+
currentMapping.appendMap(mappedStep.getMap());
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
return rebasedTransaction;
|
|
26
|
+
};
|
|
@@ -9,7 +9,7 @@ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbol
|
|
|
9
9
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
10
10
|
function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }
|
|
11
11
|
function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
|
|
12
|
-
import { useEffect, useState } from 'react';
|
|
12
|
+
import { useEffect, useState, useMemo } from 'react';
|
|
13
13
|
import { convertSyncBlockPMNodeToSyncBlockData } from '../utils/utils';
|
|
14
14
|
import { SyncBlockDataProvider } from './types';
|
|
15
15
|
export var SyncBlockProvider = /*#__PURE__*/function (_SyncBlockDataProvide) {
|
|
@@ -48,6 +48,9 @@ export var SyncBlockProvider = /*#__PURE__*/function (_SyncBlockDataProvide) {
|
|
|
48
48
|
});
|
|
49
49
|
return Promise.all(resourceIds);
|
|
50
50
|
});
|
|
51
|
+
_defineProperty(_this, "getSourceId", function () {
|
|
52
|
+
return _this.sourceId;
|
|
53
|
+
});
|
|
51
54
|
_this.fetchProvider = fetchProvider;
|
|
52
55
|
_this.writeProvider = writeProvider;
|
|
53
56
|
_this.sourceId = sourceId;
|
|
@@ -61,25 +64,34 @@ export var useFetchDocNode = function useFetchDocNode(editorView, node, defaultD
|
|
|
61
64
|
_useState2 = _slicedToArray(_useState, 2),
|
|
62
65
|
docNode = _useState2[0],
|
|
63
66
|
setDocNode = _useState2[1];
|
|
67
|
+
var fetchNode = function fetchNode(editorView, node, provider) {
|
|
68
|
+
var nodes = [convertSyncBlockPMNodeToSyncBlockData(node, false)];
|
|
69
|
+
provider === null || provider === void 0 || provider.fetchNodesData(nodes).then(function (data) {
|
|
70
|
+
var _data$;
|
|
71
|
+
if (data && (_data$ = data[0]) !== null && _data$ !== void 0 && _data$.content) {
|
|
72
|
+
var newNode = editorView.state.schema.nodeFromJSON(data[0].content);
|
|
73
|
+
setDocNode(_objectSpread(_objectSpread({}, newNode.toJSON()), {}, {
|
|
74
|
+
version: 1
|
|
75
|
+
}));
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
};
|
|
64
79
|
useEffect(function () {
|
|
65
80
|
if (!provider) {
|
|
66
81
|
return;
|
|
67
82
|
}
|
|
83
|
+
fetchNode(editorView, node, provider);
|
|
68
84
|
var interval = window.setInterval(function () {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
var _data$;
|
|
72
|
-
if (data && (_data$ = data[0]) !== null && _data$ !== void 0 && _data$.content) {
|
|
73
|
-
var newNode = editorView.state.schema.nodeFromJSON(data[0].content);
|
|
74
|
-
setDocNode(_objectSpread(_objectSpread({}, newNode.toJSON()), {}, {
|
|
75
|
-
version: 1
|
|
76
|
-
}));
|
|
77
|
-
}
|
|
78
|
-
});
|
|
79
|
-
}, 1000);
|
|
85
|
+
fetchNode(editorView, node, provider);
|
|
86
|
+
}, 3000);
|
|
80
87
|
return function () {
|
|
81
88
|
window.clearInterval(interval);
|
|
82
89
|
};
|
|
83
90
|
}, [editorView, node, provider]);
|
|
84
91
|
return docNode;
|
|
92
|
+
};
|
|
93
|
+
export var useMemoizedSyncedBlockProvider = function useMemoizedSyncedBlockProvider(fetchProvider, writeProvider, sourceId) {
|
|
94
|
+
return useMemo(function () {
|
|
95
|
+
return new SyncBlockProvider(fetchProvider, writeProvider, sourceId);
|
|
96
|
+
}, [fetchProvider, writeProvider, sourceId]);
|
|
85
97
|
};
|
|
@@ -3,6 +3,7 @@ import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
|
|
|
3
3
|
import _createClass from "@babel/runtime/helpers/createClass";
|
|
4
4
|
import _regeneratorRuntime from "@babel/runtime/regenerator";
|
|
5
5
|
import uuid from 'uuid';
|
|
6
|
+
import { rebaseTransaction as _rebaseTransaction } from './rebase-transaction';
|
|
6
7
|
|
|
7
8
|
// Do this typedef to make it clear that
|
|
8
9
|
// this is a local identifier for a resource for local use
|
|
@@ -13,9 +14,10 @@ import uuid from 'uuid';
|
|
|
13
14
|
// Handles caching, debouncing updates, and publish/subscribe for local changes.
|
|
14
15
|
// Ensures consistency between local and remote state, and can be used in both editor and renderer contexts.
|
|
15
16
|
export var SyncBlockStoreManager = /*#__PURE__*/function () {
|
|
16
|
-
function SyncBlockStoreManager(
|
|
17
|
+
function SyncBlockStoreManager(dataProvider) {
|
|
17
18
|
_classCallCheck(this, SyncBlockStoreManager);
|
|
18
19
|
this.syncBlocks = new Map();
|
|
20
|
+
this.dataProvider = dataProvider;
|
|
19
21
|
}
|
|
20
22
|
return _createClass(SyncBlockStoreManager, [{
|
|
21
23
|
key: "setEditorView",
|
|
@@ -25,14 +27,13 @@ export var SyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
25
27
|
}, {
|
|
26
28
|
key: "isSourceBlock",
|
|
27
29
|
value: function isSourceBlock(node) {
|
|
28
|
-
var _this$syncBlocks$get;
|
|
29
30
|
if (node.type.name !== 'syncBlock') {
|
|
30
31
|
return false;
|
|
31
32
|
}
|
|
32
33
|
var _node$attrs = node.attrs,
|
|
33
34
|
resourceId = _node$attrs.resourceId,
|
|
34
35
|
localId = _node$attrs.localId;
|
|
35
|
-
return
|
|
36
|
+
return resourceId.includes(localId);
|
|
36
37
|
}
|
|
37
38
|
}, {
|
|
38
39
|
key: "registerConfirmationCallback",
|
|
@@ -51,15 +52,18 @@ export var SyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
51
52
|
}, {
|
|
52
53
|
key: "createSyncBlockNode",
|
|
53
54
|
value: function createSyncBlockNode() {
|
|
55
|
+
var _this$dataProvider;
|
|
54
56
|
// TODO: EDITOR-1644 - properly implement creation of the synced block
|
|
55
57
|
// below is a temporary implementation for the creation of the synced block
|
|
56
58
|
// the resource id needs to have pageId and content property key in it
|
|
59
|
+
// Note: If the data provider is not set, the resource id will be the local id
|
|
57
60
|
|
|
58
|
-
var blockInstanceId = uuid();
|
|
59
61
|
var localId = uuid();
|
|
62
|
+
var sourceId = (_this$dataProvider = this.dataProvider) === null || _this$dataProvider === void 0 ? void 0 : _this$dataProvider.getSourceId();
|
|
63
|
+
var resourceId = sourceId ? "".concat(sourceId, "/").concat(localId) : localId;
|
|
60
64
|
var syncBlockNode = {
|
|
61
65
|
attrs: {
|
|
62
|
-
resourceId:
|
|
66
|
+
resourceId: resourceId,
|
|
63
67
|
localId: localId
|
|
64
68
|
},
|
|
65
69
|
type: 'syncBlock'
|
|
@@ -80,23 +84,24 @@ export var SyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
80
84
|
while (1) switch (_context.prev = _context.next) {
|
|
81
85
|
case 0:
|
|
82
86
|
if (!this.confirmationCallback) {
|
|
83
|
-
_context.next =
|
|
87
|
+
_context.next = 7;
|
|
84
88
|
break;
|
|
85
89
|
}
|
|
86
|
-
|
|
90
|
+
this.confirmationTransaction = tr;
|
|
91
|
+
_context.next = 4;
|
|
87
92
|
return this.confirmationCallback();
|
|
88
|
-
case
|
|
93
|
+
case 4:
|
|
89
94
|
confirmed = _context.sent;
|
|
90
95
|
if (confirmed) {
|
|
91
|
-
|
|
92
|
-
(_this$editorView = this.editorView) === null || _this$editorView === void 0 || _this$editorView.dispatch(tr.setMeta('isConfirmedSyncBlockDeletion', true));
|
|
96
|
+
(_this$editorView = this.editorView) === null || _this$editorView === void 0 || _this$editorView.dispatch(this.confirmationTransaction.setMeta('isConfirmedSyncBlockDeletion', true));
|
|
93
97
|
// Need to update the BE on deletion
|
|
94
98
|
syncBlockIds.forEach(function (_ref) {
|
|
95
99
|
var resourceId = _ref.resourceId;
|
|
96
100
|
return _this2.syncBlocks.delete(resourceId);
|
|
97
101
|
});
|
|
98
102
|
}
|
|
99
|
-
|
|
103
|
+
this.confirmationTransaction = undefined;
|
|
104
|
+
case 7:
|
|
100
105
|
case "end":
|
|
101
106
|
return _context.stop();
|
|
102
107
|
}
|
|
@@ -107,5 +112,13 @@ export var SyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
107
112
|
}
|
|
108
113
|
return deleteSyncBlocksWithConfirmation;
|
|
109
114
|
}()
|
|
115
|
+
}, {
|
|
116
|
+
key: "rebaseTransaction",
|
|
117
|
+
value: function rebaseTransaction(incomingTr, state) {
|
|
118
|
+
if (!this.confirmationTransaction) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
this.confirmationTransaction = _rebaseTransaction(this.confirmationTransaction, incomingTr, state);
|
|
122
|
+
}
|
|
110
123
|
}]);
|
|
111
124
|
}();
|
package/dist/esm/index.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
/* eslint-disable @atlaskit/editor/no-re-export */
|
|
2
2
|
|
|
3
|
-
export { SyncBlockProvider as SyncedBlockProvider, useFetchDocNode } from './common/syncBlockProvider';
|
|
3
|
+
export { SyncBlockProvider as SyncedBlockProvider, useFetchDocNode, useMemoizedSyncedBlockProvider } from './common/syncBlockProvider';
|
|
4
4
|
export { SyncBlockStoreManager } from './common/syncBlockStoreManager';
|
|
5
5
|
export { inMemoryFetchProvider, inMemoryWriteProvider } from './providers/inMemory';
|
|
6
|
+
export { getDefaultSyncBlockSchema } from './common/schema';
|
|
7
|
+
export { createContentAPIProvidersWithDefaultKey, useMemoizedContentAPIProviders } from './providers/confluenceContentAPI';
|
|
8
|
+
export { getConfluencePageAri } from './utils/ari';
|
|
6
9
|
export { convertSyncBlockPMNodeToSyncBlockData, generateSyncBlockSourceUrl } from './utils/utils';
|
|
7
|
-
export {
|
|
10
|
+
export { rebaseTransaction } from './common/rebase-transaction';
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
+
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
|
|
3
|
+
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
|
|
4
|
+
import _createClass from "@babel/runtime/helpers/createClass";
|
|
5
|
+
import _regeneratorRuntime from "@babel/runtime/regenerator";
|
|
6
|
+
import { useMemo } from 'react';
|
|
7
|
+
import { getLocalIdFromAri, getPageIdFromAri } from '../utils/ari';
|
|
8
|
+
import { getContentProperty, createContentProperty, updateContentProperty } from '../utils/contentProperty';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Configuration for Content API providers
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
var getContentPropertyKey = function getContentPropertyKey(contentPropertyKey, localId) {
|
|
15
|
+
return contentPropertyKey + '-' + localId;
|
|
16
|
+
};
|
|
17
|
+
var parseSyncedBlockContentPropertyValue = function parseSyncedBlockContentPropertyValue(value) {
|
|
18
|
+
try {
|
|
19
|
+
if (typeof value === 'string') {
|
|
20
|
+
return JSON.parse(value);
|
|
21
|
+
}
|
|
22
|
+
return value;
|
|
23
|
+
} catch (error) {
|
|
24
|
+
// eslint-disable-next-line no-console
|
|
25
|
+
console.error('Failed to parse synced block content:', error);
|
|
26
|
+
return {
|
|
27
|
+
content: undefined
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* ADFFetchProvider implementation that fetches synced block data from Confluence Content API
|
|
34
|
+
*/
|
|
35
|
+
var ConfluenceADFFetchProvider = /*#__PURE__*/function () {
|
|
36
|
+
function ConfluenceADFFetchProvider(config) {
|
|
37
|
+
_classCallCheck(this, ConfluenceADFFetchProvider);
|
|
38
|
+
this.config = config;
|
|
39
|
+
}
|
|
40
|
+
return _createClass(ConfluenceADFFetchProvider, [{
|
|
41
|
+
key: "fetchData",
|
|
42
|
+
value: function () {
|
|
43
|
+
var _fetchData = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(resourceId) {
|
|
44
|
+
var _contentProperty$data, pageId, localId, key, options, contentProperty, value, syncedBlockData;
|
|
45
|
+
return _regeneratorRuntime.wrap(function _callee$(_context) {
|
|
46
|
+
while (1) switch (_context.prev = _context.next) {
|
|
47
|
+
case 0:
|
|
48
|
+
_context.prev = 0;
|
|
49
|
+
pageId = getPageIdFromAri(resourceId);
|
|
50
|
+
localId = getLocalIdFromAri(resourceId);
|
|
51
|
+
key = getContentPropertyKey(this.config.contentPropertyKey, localId);
|
|
52
|
+
options = {
|
|
53
|
+
pageId: pageId,
|
|
54
|
+
key: key,
|
|
55
|
+
cloudId: this.config.cloudId
|
|
56
|
+
};
|
|
57
|
+
_context.next = 7;
|
|
58
|
+
return getContentProperty(options);
|
|
59
|
+
case 7:
|
|
60
|
+
contentProperty = _context.sent;
|
|
61
|
+
value = (_contentProperty$data = contentProperty.data.confluence.page.properties) === null || _contentProperty$data === void 0 || (_contentProperty$data = _contentProperty$data[0]) === null || _contentProperty$data === void 0 ? void 0 : _contentProperty$data.value;
|
|
62
|
+
if (value) {
|
|
63
|
+
_context.next = 11;
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
throw new Error('Content property value does not exist');
|
|
67
|
+
case 11:
|
|
68
|
+
// Parse the synced block content from the property value
|
|
69
|
+
syncedBlockData = parseSyncedBlockContentPropertyValue(value);
|
|
70
|
+
return _context.abrupt("return", {
|
|
71
|
+
content: syncedBlockData.content
|
|
72
|
+
});
|
|
73
|
+
case 15:
|
|
74
|
+
_context.prev = 15;
|
|
75
|
+
_context.t0 = _context["catch"](0);
|
|
76
|
+
// eslint-disable-next-line no-console
|
|
77
|
+
console.error('Failed to fetch synced block data:', _context.t0);
|
|
78
|
+
return _context.abrupt("return", {
|
|
79
|
+
content: undefined
|
|
80
|
+
});
|
|
81
|
+
case 19:
|
|
82
|
+
case "end":
|
|
83
|
+
return _context.stop();
|
|
84
|
+
}
|
|
85
|
+
}, _callee, this, [[0, 15]]);
|
|
86
|
+
}));
|
|
87
|
+
function fetchData(_x) {
|
|
88
|
+
return _fetchData.apply(this, arguments);
|
|
89
|
+
}
|
|
90
|
+
return fetchData;
|
|
91
|
+
}()
|
|
92
|
+
}]);
|
|
93
|
+
}();
|
|
94
|
+
/**
|
|
95
|
+
* ADFWriteProvider implementation that writes synced block data to Confluence Content API
|
|
96
|
+
*/
|
|
97
|
+
var ConfluenceADFWriteProvider = /*#__PURE__*/function () {
|
|
98
|
+
function ConfluenceADFWriteProvider(config) {
|
|
99
|
+
var _this = this;
|
|
100
|
+
_classCallCheck(this, ConfluenceADFWriteProvider);
|
|
101
|
+
_defineProperty(this, "createNewContentProperty", /*#__PURE__*/function () {
|
|
102
|
+
var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(pageId, key, value) {
|
|
103
|
+
var _contentProperty$data2;
|
|
104
|
+
var contentProperty;
|
|
105
|
+
return _regeneratorRuntime.wrap(function _callee2$(_context2) {
|
|
106
|
+
while (1) switch (_context2.prev = _context2.next) {
|
|
107
|
+
case 0:
|
|
108
|
+
_context2.next = 2;
|
|
109
|
+
return createContentProperty({
|
|
110
|
+
pageId: pageId,
|
|
111
|
+
key: key,
|
|
112
|
+
value: value,
|
|
113
|
+
cloudId: _this.config.cloudId
|
|
114
|
+
});
|
|
115
|
+
case 2:
|
|
116
|
+
contentProperty = _context2.sent;
|
|
117
|
+
if (!(((_contentProperty$data2 = contentProperty.data.confluence.createPageProperty.pageProperty) === null || _contentProperty$data2 === void 0 ? void 0 : _contentProperty$data2.key) === key)) {
|
|
118
|
+
_context2.next = 7;
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
return _context2.abrupt("return", key);
|
|
122
|
+
case 7:
|
|
123
|
+
throw new Error('Failed to create content property');
|
|
124
|
+
case 8:
|
|
125
|
+
case "end":
|
|
126
|
+
return _context2.stop();
|
|
127
|
+
}
|
|
128
|
+
}, _callee2);
|
|
129
|
+
}));
|
|
130
|
+
return function (_x2, _x3, _x4) {
|
|
131
|
+
return _ref.apply(this, arguments);
|
|
132
|
+
};
|
|
133
|
+
}());
|
|
134
|
+
this.config = config;
|
|
135
|
+
}
|
|
136
|
+
return _createClass(ConfluenceADFWriteProvider, [{
|
|
137
|
+
key: "writeData",
|
|
138
|
+
value: function () {
|
|
139
|
+
var _writeData = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3(sourceId, localId, data, resourceId) {
|
|
140
|
+
var pageId, syncedBlockValue, _contentProperty$data3, _localId, key, contentProperty, _key;
|
|
141
|
+
return _regeneratorRuntime.wrap(function _callee3$(_context3) {
|
|
142
|
+
while (1) switch (_context3.prev = _context3.next) {
|
|
143
|
+
case 0:
|
|
144
|
+
_context3.prev = 0;
|
|
145
|
+
pageId = getPageIdFromAri(sourceId);
|
|
146
|
+
syncedBlockValue = JSON.stringify({
|
|
147
|
+
content: data
|
|
148
|
+
});
|
|
149
|
+
if (!resourceId) {
|
|
150
|
+
_context3.next = 20;
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
153
|
+
// Update existing content property
|
|
154
|
+
_localId = getLocalIdFromAri(resourceId);
|
|
155
|
+
key = getContentPropertyKey(this.config.contentPropertyKey, _localId);
|
|
156
|
+
_context3.next = 8;
|
|
157
|
+
return updateContentProperty({
|
|
158
|
+
pageId: pageId,
|
|
159
|
+
key: key,
|
|
160
|
+
value: syncedBlockValue,
|
|
161
|
+
cloudId: this.config.cloudId
|
|
162
|
+
});
|
|
163
|
+
case 8:
|
|
164
|
+
contentProperty = _context3.sent;
|
|
165
|
+
if (!(((_contentProperty$data3 = contentProperty.data.confluence.updateValuePageProperty.pageProperty) === null || _contentProperty$data3 === void 0 ? void 0 : _contentProperty$data3.key) === key)) {
|
|
166
|
+
_context3.next = 13;
|
|
167
|
+
break;
|
|
168
|
+
}
|
|
169
|
+
return _context3.abrupt("return", key);
|
|
170
|
+
case 13:
|
|
171
|
+
if (!(contentProperty.data.confluence.updateValuePageProperty.pageProperty === null)) {
|
|
172
|
+
_context3.next = 17;
|
|
173
|
+
break;
|
|
174
|
+
}
|
|
175
|
+
return _context3.abrupt("return", this.createNewContentProperty(pageId, key, syncedBlockValue));
|
|
176
|
+
case 17:
|
|
177
|
+
throw new Error('Failed to update content property');
|
|
178
|
+
case 18:
|
|
179
|
+
_context3.next = 22;
|
|
180
|
+
break;
|
|
181
|
+
case 20:
|
|
182
|
+
// Create new content property
|
|
183
|
+
_key = getContentPropertyKey(this.config.contentPropertyKey, localId);
|
|
184
|
+
return _context3.abrupt("return", this.createNewContentProperty(pageId, _key, syncedBlockValue));
|
|
185
|
+
case 22:
|
|
186
|
+
_context3.next = 28;
|
|
187
|
+
break;
|
|
188
|
+
case 24:
|
|
189
|
+
_context3.prev = 24;
|
|
190
|
+
_context3.t0 = _context3["catch"](0);
|
|
191
|
+
// eslint-disable-next-line no-console
|
|
192
|
+
console.error('Failed to write synced block data:', _context3.t0);
|
|
193
|
+
return _context3.abrupt("return", Promise.reject(_context3.t0));
|
|
194
|
+
case 28:
|
|
195
|
+
case "end":
|
|
196
|
+
return _context3.stop();
|
|
197
|
+
}
|
|
198
|
+
}, _callee3, this, [[0, 24]]);
|
|
199
|
+
}));
|
|
200
|
+
function writeData(_x5, _x6, _x7, _x8) {
|
|
201
|
+
return _writeData.apply(this, arguments);
|
|
202
|
+
}
|
|
203
|
+
return writeData;
|
|
204
|
+
}()
|
|
205
|
+
}]);
|
|
206
|
+
}();
|
|
207
|
+
/**
|
|
208
|
+
* Factory function to create both providers with shared configuration
|
|
209
|
+
*/
|
|
210
|
+
var createContentAPIProviders = function createContentAPIProviders(config) {
|
|
211
|
+
var fetchProvider = new ConfluenceADFFetchProvider(config);
|
|
212
|
+
var writeProvider = new ConfluenceADFWriteProvider(config);
|
|
213
|
+
return {
|
|
214
|
+
fetchProvider: fetchProvider,
|
|
215
|
+
writeProvider: writeProvider
|
|
216
|
+
};
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Convenience function to create providers with default content property key
|
|
221
|
+
*/
|
|
222
|
+
export var createContentAPIProvidersWithDefaultKey = function createContentAPIProvidersWithDefaultKey(cloudId) {
|
|
223
|
+
return createContentAPIProviders({
|
|
224
|
+
cloudId: cloudId,
|
|
225
|
+
contentPropertyKey: 'editor-synced-block'
|
|
226
|
+
});
|
|
227
|
+
};
|
|
228
|
+
export var useMemoizedContentAPIProviders = function useMemoizedContentAPIProviders(cloudId) {
|
|
229
|
+
return useMemo(function () {
|
|
230
|
+
return createContentAPIProvidersWithDefaultKey(cloudId);
|
|
231
|
+
}, [cloudId]);
|
|
232
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export var getConfluencePageAri = function getConfluencePageAri(pageId, cloudId) {
|
|
2
|
+
return "ari:cloud:confluence:".concat(cloudId, ":page/").concat(pageId);
|
|
3
|
+
};
|
|
4
|
+
export var getPageIdFromAri = function getPageIdFromAri(ari) {
|
|
5
|
+
// eslint-disable-next-line require-unicode-regexp
|
|
6
|
+
var match = ari.match(/ari:cloud:confluence:[^:]+:page\/(\d+)/);
|
|
7
|
+
if (match !== null && match !== void 0 && match[1]) {
|
|
8
|
+
return match[1];
|
|
9
|
+
}
|
|
10
|
+
throw new Error("Invalid page ARI: ".concat(ari));
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
*
|
|
15
|
+
* @param ari ari:cloud:confluence:<cloudId>:page/<pageId>/<localId>
|
|
16
|
+
* @returns
|
|
17
|
+
*/
|
|
18
|
+
export var getLocalIdFromAri = function getLocalIdFromAri(ari) {
|
|
19
|
+
// eslint-disable-next-line require-unicode-regexp
|
|
20
|
+
var match = ari.match(/ari:cloud:confluence:[^:]+:page\/\d+\/([a-zA-Z0-9-]+)/);
|
|
21
|
+
if (match !== null && match !== void 0 && match[1]) {
|
|
22
|
+
return match[1];
|
|
23
|
+
}
|
|
24
|
+
throw new Error("Invalid page ARI: ".concat(ari));
|
|
25
|
+
};
|
|
26
|
+
export var getContentPropertyAri = function getContentPropertyAri(contentPropertyId, cloudId) {
|
|
27
|
+
return "ari:cloud:confluence:".concat(cloudId, ":content/").concat(contentPropertyId);
|
|
28
|
+
};
|
|
29
|
+
export var getContentPropertyIdFromAri = function getContentPropertyIdFromAri(ari) {
|
|
30
|
+
// eslint-disable-next-line require-unicode-regexp
|
|
31
|
+
var match = ari.match(/ari:cloud:confluence:[^:]+:content\/([^/]+)/);
|
|
32
|
+
if (match) {
|
|
33
|
+
return match[1];
|
|
34
|
+
}
|
|
35
|
+
throw new Error("Invalid content property ARI: ".concat(ari));
|
|
36
|
+
};
|