@manuscripts/body-editor 1.7.4 → 1.7.5
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/dist/cjs/assets.js +25 -1
- package/dist/cjs/configs/editor-plugins.js +2 -4
- package/dist/cjs/index.js +3 -1
- package/dist/cjs/lib/track-changes-utils.js +13 -4
- package/dist/cjs/plugins/comment_annotation.js +2 -1
- package/dist/cjs/plugins/selected-suggestion-ui.js +129 -0
- package/dist/cjs/views/affiliation.js +2 -1
- package/dist/cjs/views/bibliography_element.js +23 -6
- package/dist/cjs/views/citation.js +4 -1
- package/dist/cjs/views/contributors.js +14 -3
- package/dist/cjs/views/cross_reference.js +4 -1
- package/dist/cjs/views/keyword.js +17 -7
- package/dist/es/assets.js +24 -0
- package/dist/es/configs/editor-plugins.js +2 -4
- package/dist/es/index.js +1 -0
- package/dist/es/lib/track-changes-utils.js +11 -3
- package/dist/es/plugins/comment_annotation.js +2 -1
- package/dist/es/plugins/selected-suggestion-ui.js +126 -0
- package/dist/es/views/affiliation.js +2 -1
- package/dist/es/views/bibliography_element.js +22 -5
- package/dist/es/views/citation.js +4 -1
- package/dist/es/views/contributors.js +14 -3
- package/dist/es/views/cross_reference.js +4 -1
- package/dist/es/views/keyword.js +17 -7
- package/dist/types/assets.d.ts +1 -0
- package/dist/types/configs/editor-plugins.d.ts +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/lib/track-changes-utils.d.ts +3 -1
- package/dist/types/plugins/{track-changes-ui.d.ts → selected-suggestion-ui.d.ts} +7 -5
- package/dist/types/views/affiliation.d.ts +0 -1
- package/dist/types/views/base_node_view.d.ts +1 -0
- package/dist/types/views/bibliography_element.d.ts +1 -0
- package/dist/types/views/contributors.d.ts +1 -1
- package/package.json +2 -2
- package/styles/AdvancedEditor.css +18 -3
- package/dist/cjs/plugins/track-changes-ui.js +0 -104
- package/dist/cjs/plugins/tracking-mark.js +0 -123
- package/dist/es/plugins/track-changes-ui.js +0 -102
- package/dist/es/plugins/tracking-mark.js +0 -118
- package/dist/types/plugins/tracking-mark.d.ts +0 -7
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* © 2019 Atypon Systems LLC
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
import { trackChangesPluginKey } from '@manuscripts/track-changes-plugin';
|
|
17
|
+
import { isEqual } from 'lodash';
|
|
18
|
+
import { Plugin, PluginKey } from 'prosemirror-state';
|
|
19
|
+
import { Decoration, DecorationSet } from 'prosemirror-view';
|
|
20
|
+
class SuggestionView {
|
|
21
|
+
constructor(view) {
|
|
22
|
+
this.listener = (e) => {
|
|
23
|
+
const changeId = e.currentTarget.getAttribute('data-track-id');
|
|
24
|
+
this.view.dispatch(this.view.state.tr.setMeta(SET_SUGGESTION_ID, changeId));
|
|
25
|
+
};
|
|
26
|
+
this.view = view;
|
|
27
|
+
this.addEventListener(view);
|
|
28
|
+
this.update(view, undefined);
|
|
29
|
+
}
|
|
30
|
+
update(view, prevState) {
|
|
31
|
+
var _a, _b;
|
|
32
|
+
this.view = view;
|
|
33
|
+
if (!prevState) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const oldChanges = ((_a = trackChangesPluginKey.getState(prevState)) === null || _a === void 0 ? void 0 : _a.changeSet.changes) || [];
|
|
37
|
+
const newChangeSet = (_b = trackChangesPluginKey.getState(view.state)) === null || _b === void 0 ? void 0 : _b.changeSet;
|
|
38
|
+
if (newChangeSet && !isEqual(oldChanges, newChangeSet.changes)) {
|
|
39
|
+
this.addEventListener(view);
|
|
40
|
+
oldChanges.map((change) => {
|
|
41
|
+
var _a;
|
|
42
|
+
if (!newChangeSet.get(change.id) ||
|
|
43
|
+
((_a = newChangeSet.get(change.id)) === null || _a === void 0 ? void 0 : _a.dataTracked.status) === 'rejected') {
|
|
44
|
+
const dom = view.dom.querySelector(`[data-track-id="${change.id}"]`);
|
|
45
|
+
dom === null || dom === void 0 ? void 0 : dom.removeEventListener('click', this.listener);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
destroy() {
|
|
51
|
+
this.view.dom
|
|
52
|
+
.querySelectorAll('[data-track-status="pending"], [data-track-status="accepted"]')
|
|
53
|
+
.forEach((dom) => {
|
|
54
|
+
var _a, _b;
|
|
55
|
+
if ((_b = (_a = dom.parentElement) === null || _a === void 0 ? void 0 : _a.parentElement) === null || _b === void 0 ? void 0 : _b.classList.contains('keyword')) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
dom.removeEventListener('click', this.listener);
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
addEventListener(view) {
|
|
62
|
+
view.dom
|
|
63
|
+
.querySelectorAll('[data-track-status="pending"], [data-track-status="accepted"]')
|
|
64
|
+
.forEach((dom) => {
|
|
65
|
+
var _a, _b;
|
|
66
|
+
if ((_b = (_a = dom.parentElement) === null || _a === void 0 ? void 0 : _a.parentElement) === null || _b === void 0 ? void 0 : _b.classList.contains('keyword')) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
dom.addEventListener('click', this.listener);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
const getTrackChangesData = (node) => {
|
|
74
|
+
var _a;
|
|
75
|
+
const trackChangesMark = node.marks.find((mark) => (mark.type.name === 'tracked_insert' ||
|
|
76
|
+
mark.type.name === 'tracked_delete') &&
|
|
77
|
+
mark.attrs.dataTracked);
|
|
78
|
+
return (_a = trackChangesMark === null || trackChangesMark === void 0 ? void 0 : trackChangesMark.attrs) === null || _a === void 0 ? void 0 : _a.dataTracked;
|
|
79
|
+
};
|
|
80
|
+
export const SET_SUGGESTION_ID = 'SET_SELECTED_SUGGESTION_ID';
|
|
81
|
+
const CLEAR_SUGGESTION_ID = 'CLEAR_SUGGESTION_ID';
|
|
82
|
+
export const selectedSuggestionKey = new PluginKey('selected_suggestion');
|
|
83
|
+
export default (props) => new Plugin({
|
|
84
|
+
key: selectedSuggestionKey,
|
|
85
|
+
view: (view) => new SuggestionView(view),
|
|
86
|
+
state: {
|
|
87
|
+
init: () => DecorationSet.empty,
|
|
88
|
+
apply: (tr, value, _, state) => {
|
|
89
|
+
const suggestionId = tr.getMeta(SET_SUGGESTION_ID);
|
|
90
|
+
if (suggestionId) {
|
|
91
|
+
return buildSelectedSuggestionDecoration(suggestionId, state, props);
|
|
92
|
+
}
|
|
93
|
+
if (tr.getMeta(CLEAR_SUGGESTION_ID) ||
|
|
94
|
+
tr.getMeta('track-changes-refresh-changes')) {
|
|
95
|
+
props.setEditorSelectedSuggestion(undefined);
|
|
96
|
+
return DecorationSet.empty;
|
|
97
|
+
}
|
|
98
|
+
return value;
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
props: {
|
|
102
|
+
handleClick(view, pos) {
|
|
103
|
+
const nodeClicked = view.state.doc.nodeAt(pos);
|
|
104
|
+
const trackChangesData = nodeClicked && getTrackChangesData(nodeClicked);
|
|
105
|
+
if (!trackChangesData) {
|
|
106
|
+
view.dispatch(view.state.tr.setMeta(CLEAR_SUGGESTION_ID, true));
|
|
107
|
+
props.setEditorSelectedSuggestion(undefined);
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
decorations: (state) => selectedSuggestionKey.getState(state),
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
const buildSelectedSuggestionDecoration = (suggestionId, state, props) => {
|
|
114
|
+
var _a;
|
|
115
|
+
const change = (_a = trackChangesPluginKey
|
|
116
|
+
.getState(state)) === null || _a === void 0 ? void 0 : _a.changeSet.get(suggestionId);
|
|
117
|
+
const decorations = [];
|
|
118
|
+
if (change) {
|
|
119
|
+
const decoration = change.type === 'text-change' ? Decoration.inline : Decoration.node;
|
|
120
|
+
decorations.push(decoration(change.from, change.to, {
|
|
121
|
+
class: 'selected-suggestion',
|
|
122
|
+
}));
|
|
123
|
+
props.setEditorSelectedSuggestion(change.id);
|
|
124
|
+
}
|
|
125
|
+
return DecorationSet.create(state.doc, decorations);
|
|
126
|
+
};
|
|
@@ -36,10 +36,12 @@ export class AffiliationView extends BaseNodeView {
|
|
|
36
36
|
this.dom.setAttribute('style', 'order: ' + (order || (pluginState === null || pluginState === void 0 ? void 0 : pluginState.affiliations.length) + 1));
|
|
37
37
|
}
|
|
38
38
|
if ((_a = attrs.dataTracked) === null || _a === void 0 ? void 0 : _a.length) {
|
|
39
|
+
this.dom.setAttribute('data-track-id', attrs.dataTracked[0].id);
|
|
39
40
|
this.dom.setAttribute('data-track-status', attrs.dataTracked[0].status);
|
|
40
41
|
this.dom.setAttribute('data-track-op', attrs.dataTracked[0].operation);
|
|
41
42
|
}
|
|
42
43
|
else {
|
|
44
|
+
this.dom.removeAttribute('data-track-id');
|
|
43
45
|
this.dom.removeAttribute('data-track-status');
|
|
44
46
|
this.dom.removeAttribute('data-track-type');
|
|
45
47
|
}
|
|
@@ -51,7 +53,6 @@ export class AffiliationView extends BaseNodeView {
|
|
|
51
53
|
this.updateContents();
|
|
52
54
|
};
|
|
53
55
|
this.ignoreMutation = () => true;
|
|
54
|
-
this.stopEvent = () => true;
|
|
55
56
|
this.formatAddress = (affiliation) => {
|
|
56
57
|
const { department, institution, addressLine1, city, county, country, postCode, } = affiliation;
|
|
57
58
|
return [
|
|
@@ -26,9 +26,10 @@ import { CHANGE_OPERATION, CHANGE_STATUS, } from '@manuscripts/track-changes-plu
|
|
|
26
26
|
import { buildComment, Decoder, } from '@manuscripts/transform';
|
|
27
27
|
import { commentIcon, editIcon } from '../assets';
|
|
28
28
|
import { sanitize } from '../lib/dompurify';
|
|
29
|
+
import { getAttrsTrackingButton, getChangeClasses, } from '../lib/track-changes-utils';
|
|
29
30
|
import { getBibliographyPluginState } from '../plugins/bibliography';
|
|
30
31
|
import { commentAnnotation } from '../plugins/comment_annotation';
|
|
31
|
-
import {
|
|
32
|
+
import { selectedSuggestionKey, SET_SUGGESTION_ID, } from '../plugins/selected-suggestion-ui';
|
|
32
33
|
import BlockView from './block_view';
|
|
33
34
|
import { createNodeView } from './creators';
|
|
34
35
|
import ReactSubView from './ReactSubView';
|
|
@@ -55,11 +56,13 @@ export class BibliographyElementBlockView extends BlockView {
|
|
|
55
56
|
this.updateContents = () => __awaiter(this, void 0, void 0, function* () {
|
|
56
57
|
const bib = getBibliographyPluginState(this.view.state);
|
|
57
58
|
const commentsDecorationSet = commentAnnotation.getState(this.view.state);
|
|
59
|
+
const selectedSuggestion = selectedSuggestionKey.getState(this.view.state);
|
|
58
60
|
const commentElementMap = new Map();
|
|
59
61
|
const dataTrackedMap = new Map();
|
|
62
|
+
let selectedBibItemSuggestion;
|
|
60
63
|
this.node.descendants((node, pos) => {
|
|
64
|
+
const nodePosition = this.getPos() + pos + 2;
|
|
61
65
|
if (commentsDecorationSet) {
|
|
62
|
-
const nodePosition = this.getPos() + pos + 2;
|
|
63
66
|
const commentWidget = commentsDecorationSet.find(nodePosition, nodePosition);
|
|
64
67
|
if (commentWidget.length) {
|
|
65
68
|
const commentElement = commentWidget[0].type.toDOM();
|
|
@@ -71,6 +74,10 @@ export class BibliographyElementBlockView extends BlockView {
|
|
|
71
74
|
const lastChange = dataTracked[dataTracked.length - 1];
|
|
72
75
|
dataTrackedMap.set(node.attrs.id, lastChange);
|
|
73
76
|
}
|
|
77
|
+
if ((dataTracked === null || dataTracked === void 0 ? void 0 : dataTracked.length) &&
|
|
78
|
+
(selectedSuggestion === null || selectedSuggestion === void 0 ? void 0 : selectedSuggestion.find(nodePosition, nodePosition + node.nodeSize).length)) {
|
|
79
|
+
selectedBibItemSuggestion = node.attrs.id;
|
|
80
|
+
}
|
|
74
81
|
});
|
|
75
82
|
const can = this.props.getCapabilities();
|
|
76
83
|
const wrapper = document.createElement('div');
|
|
@@ -108,13 +115,16 @@ export class BibliographyElementBlockView extends BlockView {
|
|
|
108
115
|
}
|
|
109
116
|
const dataTracked = dataTrackedMap.get(element.id);
|
|
110
117
|
if (dataTracked) {
|
|
111
|
-
element.classList.add('attrs-track-mark');
|
|
112
|
-
const decoration = getMarkDecoration(dataTracked);
|
|
113
|
-
decoration.style && element.setAttribute('style', decoration.style);
|
|
118
|
+
element.classList.add('attrs-track-mark', ...getChangeClasses([dataTracked]));
|
|
114
119
|
if (dataTracked.status === CHANGE_STATUS.pending &&
|
|
115
120
|
dataTracked.operation === CHANGE_OPERATION.set_node_attributes) {
|
|
116
121
|
element.appendChild(getAttrsTrackingButton(dataTracked.id));
|
|
117
122
|
}
|
|
123
|
+
this.addClickListenerToBibItem(element, dataTracked);
|
|
124
|
+
}
|
|
125
|
+
if (selectedBibItemSuggestion &&
|
|
126
|
+
selectedBibItemSuggestion === element.id) {
|
|
127
|
+
element.classList.add('selected-suggestion');
|
|
118
128
|
}
|
|
119
129
|
wrapper.append(element);
|
|
120
130
|
}
|
|
@@ -140,6 +150,13 @@ export class BibliographyElementBlockView extends BlockView {
|
|
|
140
150
|
this.handleDelete = (item) => {
|
|
141
151
|
return this.deleteNode(item._id);
|
|
142
152
|
};
|
|
153
|
+
this.addClickListenerToBibItem = (element, dataTracked) => {
|
|
154
|
+
if (dataTracked.status !== CHANGE_STATUS.rejected) {
|
|
155
|
+
element.addEventListener('click', () => {
|
|
156
|
+
this.view.dispatch(this.view.state.tr.setMeta(SET_SUGGESTION_ID, dataTracked.id));
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
};
|
|
143
160
|
}
|
|
144
161
|
}
|
|
145
162
|
export default createNodeView(BibliographyElementBlockView);
|
|
@@ -41,7 +41,10 @@ export class CitationView extends BaseNodeView {
|
|
|
41
41
|
this.updateContents = () => {
|
|
42
42
|
const bib = getBibliographyPluginState(this.view.state);
|
|
43
43
|
const citation = this.getCitation();
|
|
44
|
-
const classes = [
|
|
44
|
+
const classes = [
|
|
45
|
+
'citation',
|
|
46
|
+
...getChangeClasses(this.node.attrs.dataTracked),
|
|
47
|
+
];
|
|
45
48
|
const element = document.createElement('span');
|
|
46
49
|
element.className = classes.join(' ');
|
|
47
50
|
const text = bib.renderedCitations.get(citation._id);
|
|
@@ -2,6 +2,7 @@ import { SecondaryButton } from '@manuscripts/style-guide';
|
|
|
2
2
|
import { isContributorNode } from '@manuscripts/transform';
|
|
3
3
|
import { getActualAttrs } from '../lib/track-changes-utils';
|
|
4
4
|
import { affiliationsKey } from '../plugins/affiliations';
|
|
5
|
+
import { selectedSuggestionKey } from '../plugins/selected-suggestion-ui';
|
|
5
6
|
import BlockView from './block_view';
|
|
6
7
|
import { createNodeView } from './creators';
|
|
7
8
|
import ReactSubView from './ReactSubView';
|
|
@@ -25,12 +26,17 @@ export class ContributorsView extends BlockView {
|
|
|
25
26
|
};
|
|
26
27
|
this.buildAuthors = () => {
|
|
27
28
|
var _a;
|
|
29
|
+
const selectedSuggestion = selectedSuggestionKey.getState(this.view.state);
|
|
30
|
+
let selectedAuthor;
|
|
28
31
|
const authors = [];
|
|
29
32
|
const authorsWrapper = document.createElement('div');
|
|
30
33
|
authorsWrapper.classList.add('contributors-list');
|
|
31
|
-
(_a = this.node.content) === null || _a === void 0 ? void 0 : _a.forEach((node) => {
|
|
34
|
+
(_a = this.node.content) === null || _a === void 0 ? void 0 : _a.forEach((node, offset) => {
|
|
32
35
|
if (isContributorNode(node)) {
|
|
33
36
|
authors.push(node);
|
|
37
|
+
if (selectedSuggestion === null || selectedSuggestion === void 0 ? void 0 : selectedSuggestion.find(this.getPos() + offset + 2, this.getPos() + offset + node.nodeSize + 2).length) {
|
|
38
|
+
selectedAuthor = node.attrs.id;
|
|
39
|
+
}
|
|
34
40
|
}
|
|
35
41
|
});
|
|
36
42
|
authors
|
|
@@ -40,11 +46,11 @@ export class ContributorsView extends BlockView {
|
|
|
40
46
|
return;
|
|
41
47
|
}
|
|
42
48
|
const jointAuthors = this.isJointFirstAuthor(authors, i);
|
|
43
|
-
authorsWrapper.appendChild(this.buildAuthor(author, jointAuthors));
|
|
49
|
+
authorsWrapper.appendChild(this.buildAuthor(author, jointAuthors, selectedAuthor));
|
|
44
50
|
});
|
|
45
51
|
this.container.appendChild(authorsWrapper);
|
|
46
52
|
};
|
|
47
|
-
this.buildAuthor = (node, isJointFirstAuthor) => {
|
|
53
|
+
this.buildAuthor = (node, isJointFirstAuthor, selectedAuthor) => {
|
|
48
54
|
var _a;
|
|
49
55
|
const pluginState = affiliationsKey.getState(this.view.state);
|
|
50
56
|
const attrs = node.attrs;
|
|
@@ -54,10 +60,12 @@ export class ContributorsView extends BlockView {
|
|
|
54
60
|
container.setAttribute('id', attrs.id);
|
|
55
61
|
container.setAttribute('contenteditable', 'false');
|
|
56
62
|
if ((_a = attrs.dataTracked) === null || _a === void 0 ? void 0 : _a.length) {
|
|
63
|
+
container.setAttribute('data-track-id', attrs.dataTracked[0].id);
|
|
57
64
|
container.setAttribute('data-track-status', attrs.dataTracked[0].status);
|
|
58
65
|
container.setAttribute('data-track-op', attrs.dataTracked[0].operation);
|
|
59
66
|
}
|
|
60
67
|
else {
|
|
68
|
+
container.removeAttribute('data-track-id');
|
|
61
69
|
container.removeAttribute('data-track-status');
|
|
62
70
|
container.removeAttribute('data-track-type');
|
|
63
71
|
}
|
|
@@ -94,6 +102,9 @@ export class ContributorsView extends BlockView {
|
|
|
94
102
|
if (displayAttr.isCorresponding) {
|
|
95
103
|
container.appendChild(this.createNote('*', 'Corresponding author'));
|
|
96
104
|
}
|
|
105
|
+
if (selectedAuthor && selectedAuthor === attrs.id) {
|
|
106
|
+
container.classList.add('selected-suggestion');
|
|
107
|
+
}
|
|
97
108
|
return container;
|
|
98
109
|
};
|
|
99
110
|
this.initials = (given) => given
|
|
@@ -33,7 +33,10 @@ export class CrossReferenceView extends BaseNodeView {
|
|
|
33
33
|
});
|
|
34
34
|
};
|
|
35
35
|
this.updateContents = () => {
|
|
36
|
-
const nodeClasses = [
|
|
36
|
+
const nodeClasses = [
|
|
37
|
+
'cross-reference',
|
|
38
|
+
...getChangeClasses(this.node.attrs.dataTracked),
|
|
39
|
+
];
|
|
37
40
|
this.dom.className = nodeClasses.join(' ');
|
|
38
41
|
this.dom.textContent = this.node.attrs.customLabel || this.node.attrs.label;
|
|
39
42
|
this.dom.addEventListener('click', this.handleClick);
|
package/dist/es/views/keyword.js
CHANGED
|
@@ -39,10 +39,14 @@ export class KeywordView extends BaseNodeView {
|
|
|
39
39
|
this.contentDOM = document.createElement('span');
|
|
40
40
|
};
|
|
41
41
|
this.updateContents = () => {
|
|
42
|
-
|
|
43
|
-
const classes = [
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
var _a;
|
|
43
|
+
const classes = [
|
|
44
|
+
'keyword',
|
|
45
|
+
...getChangeClasses(this.node.attrs.dataTracked),
|
|
46
|
+
];
|
|
47
|
+
this.dom.className = classes.join(' ');
|
|
48
|
+
this.dom.innerHTML = '';
|
|
49
|
+
this.dom.appendChild(this.contentDOM);
|
|
46
50
|
const can = this.props.getCapabilities();
|
|
47
51
|
if (can.editArticle) {
|
|
48
52
|
const svg = new DOMParser()
|
|
@@ -50,10 +54,16 @@ export class KeywordView extends BaseNodeView {
|
|
|
50
54
|
.querySelector('svg');
|
|
51
55
|
svg.classList.add('delete-keyword');
|
|
52
56
|
svg.addEventListener('click', this.showConfirmationDialog);
|
|
53
|
-
|
|
57
|
+
this.dom.appendChild(svg);
|
|
58
|
+
}
|
|
59
|
+
if ((_a = this.node.attrs.dataTracked) === null || _a === void 0 ? void 0 : _a.length) {
|
|
60
|
+
this.dom.setAttribute('data-track-id', this.node.attrs.dataTracked[0].id);
|
|
61
|
+
this.dom.setAttribute('data-track-status', this.node.attrs.dataTracked[0].status);
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
this.dom.removeAttribute('data-track-id');
|
|
65
|
+
this.dom.removeAttribute('data-track-status');
|
|
54
66
|
}
|
|
55
|
-
this.dom.innerHTML = '';
|
|
56
|
-
this.dom.appendChild(keyword);
|
|
57
67
|
};
|
|
58
68
|
this.showConfirmationDialog = () => {
|
|
59
69
|
var _a;
|
package/dist/types/assets.d.ts
CHANGED
|
@@ -15,3 +15,4 @@
|
|
|
15
15
|
*/
|
|
16
16
|
export declare const editIcon = "\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 14 14\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M8.706 2.33624L11.553 5.19824L4.345 12.4422L1.498 9.58124L8.706 2.33624V2.33624ZM13.714 1.64624L12.444 0.37024C12.3273 0.253047 12.1886 0.160056 12.0359 0.0966039C11.8831 0.0331518 11.7194 0.000488281 11.554 0.000488281C11.3886 0.000488281 11.2249 0.0331518 11.0721 0.0966039C10.9194 0.160056 10.7807 0.253047 10.664 0.37024L9.447 1.59224L12.295 4.45424L13.715 3.02824C13.8976 2.84462 14.0001 2.59619 14.0001 2.33724C14.0001 2.07829 13.8976 1.82986 13.715 1.64624H13.714ZM0.00800253 13.6032C-0.00418388 13.6571 -0.00246802 13.7131 0.0129883 13.7661C0.0284447 13.819 0.0571327 13.8672 0.096349 13.906C0.135565 13.9448 0.184019 13.973 0.237143 13.9879C0.290268 14.0028 0.346315 14.004 0.400003 13.9912L3.573 13.2172L0.727003 10.3552L0.0070026 13.6032H0.00800253Z\"\n fill=\"#6E6E6E\"\n />\n </svg>\n";
|
|
17
17
|
export declare const commentIcon = "\n<svg\n width=\"20\"\n height=\"15\"\n viewBox=\"0 0 20 15\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n fill-rule=\"evenodd\"\n clip-rule=\"evenodd\"\n d=\"M7.94841 4.18311C7.98238 3.9602 8 3.73191 8 3.49951C8 3.22073 7.97465 2.94787 7.92613 2.68311H13.5C14.8854 2.68311 16.25 3.6425 16.25 5.09977V9.02453L19.1086 12.9949C19.2731 13.2233 19.2958 13.5245 19.1675 13.775C19.0392 14.0255 18.7814 14.1831 18.5 14.1831H5.5C4.11463 14.1831 2.75 13.2237 2.75 11.7664V7.93729C2.9939 7.97821 3.24446 7.99951 3.5 7.99951C3.75553 7.99951 4.00609 7.97821 4.25 7.93729V11.7664C4.25 12.1508 4.67537 12.6831 5.5 12.6831H17.0358L14.8913 9.70467C14.7994 9.57703 14.75 9.42372 14.75 9.26644V5.09977C14.75 4.71538 14.3246 4.18311 13.5 4.18311H7.94841Z\"\n fill=\"#FFBD26\"\n />\n <path\n d=\"M11.5 6.99951H8.5\"\n stroke=\"#FFBD26\"\n stroke-width=\"1.5\"\n stroke-miterlimit=\"10\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n <path\n d=\"M12 9.99951H7\"\n stroke=\"#FFBD26\"\n stroke-width=\"1.5\"\n stroke-miterlimit=\"10\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n <path\n d=\"M3.5 1L3.5 6\"\n stroke=\"#FFBD26\"\n stroke-width=\"1.5\"\n stroke-miterlimit=\"10\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n <path\n d=\"M6 3.5L1 3.5\"\n stroke=\"#FFBD26\"\n stroke-width=\"1.5\"\n stroke-miterlimit=\"10\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n";
|
|
18
|
+
export declare const editAttrsTrackingIcon = "\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M12 2L14 4L9 9L6 10L7 7L12 2Z\"\n stroke=\"#353535\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n <path\n d=\"M13 10V11.5C13 12.328 12.328 13 11.5 13H4.5C3.672 13 3 12.328 3 11.5V4.5C3 3.672 3.672 3 4.5 3H6\"\n stroke=\"#353535\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n";
|
|
@@ -28,7 +28,7 @@ interface PluginProps {
|
|
|
28
28
|
deleteModel: (id: string) => Promise<string>;
|
|
29
29
|
setComment: (comment?: CommentAnnotation) => void;
|
|
30
30
|
setSelectedComment: (id?: string) => void;
|
|
31
|
-
setEditorSelectedSuggestion
|
|
31
|
+
setEditorSelectedSuggestion: (id?: string) => void;
|
|
32
32
|
getCapabilities: () => Capabilities;
|
|
33
33
|
plugins?: Plugin<ManuscriptSchema>[];
|
|
34
34
|
cslProps: CSLProps;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -26,6 +26,7 @@ export { PopperManager } from './lib/popper';
|
|
|
26
26
|
export * from './toolbar';
|
|
27
27
|
export * from './plugins/highlight';
|
|
28
28
|
export { commentScroll, isThereSelector, isHighlightComment, } from './plugins/comment_annotation';
|
|
29
|
+
export { SET_SUGGESTION_ID } from './plugins/selected-suggestion-ui';
|
|
29
30
|
export * from './lib/utils';
|
|
30
31
|
export * from './lib/track-changes-utils';
|
|
31
32
|
export * from './useEditor';
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
* See the License for the specific language governing permissions and
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
|
+
import { TrackedAttrs } from '@manuscripts/track-changes-plugin';
|
|
16
17
|
import { ManuscriptNode } from '@manuscripts/transform';
|
|
17
18
|
import { Node as ProsemirrorNode } from 'prosemirror-model';
|
|
18
19
|
export declare function isRejectedInsert(node: ProsemirrorNode): boolean;
|
|
@@ -20,6 +21,7 @@ export declare function isDeleted(node: ProsemirrorNode): boolean;
|
|
|
20
21
|
export declare function isPendingInsert(node: ProsemirrorNode): boolean;
|
|
21
22
|
export declare function isPending(node: ProsemirrorNode): boolean;
|
|
22
23
|
export declare function isPendingSetAttrs(node: ProsemirrorNode): boolean;
|
|
23
|
-
export declare function getChangeClasses(
|
|
24
|
+
export declare function getChangeClasses(dataTracked?: TrackedAttrs[]): string[];
|
|
24
25
|
export declare function isTracked(node: ProsemirrorNode): boolean;
|
|
25
26
|
export declare function getActualAttrs<T extends ManuscriptNode>(node: T): T["attrs"];
|
|
27
|
+
export declare const getAttrsTrackingButton: (changeID: string) => HTMLButtonElement;
|
|
@@ -13,10 +13,12 @@
|
|
|
13
13
|
* See the License for the specific language governing permissions and
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
interface
|
|
19
|
-
setEditorSelectedSuggestion
|
|
16
|
+
import { Plugin, PluginKey } from 'prosemirror-state';
|
|
17
|
+
import { DecorationSet } from 'prosemirror-view';
|
|
18
|
+
interface SelectedSuggestionProps {
|
|
19
|
+
setEditorSelectedSuggestion: (id?: string) => void;
|
|
20
20
|
}
|
|
21
|
-
declare const
|
|
21
|
+
export declare const SET_SUGGESTION_ID = "SET_SELECTED_SUGGESTION_ID";
|
|
22
|
+
export declare const selectedSuggestionKey: PluginKey<DecorationSet>;
|
|
23
|
+
declare const _default: (props: SelectedSuggestionProps) => Plugin<DecorationSet>;
|
|
22
24
|
export default _default;
|
|
@@ -24,7 +24,6 @@ export declare class AffiliationView<PropsType extends BaseNodeProps> extends Ba
|
|
|
24
24
|
updateContents: () => void;
|
|
25
25
|
protected createDOM: () => void;
|
|
26
26
|
ignoreMutation: () => boolean;
|
|
27
|
-
stopEvent: () => boolean;
|
|
28
27
|
formatAddress: (affiliation: AffiliationNode['attrs']) => string;
|
|
29
28
|
}
|
|
30
29
|
declare const _default: (props: BaseNodeProps, dispatch?: import("..").Dispatch | undefined) => import("../types").NodeViewCreator<AffiliationView<any>>;
|
|
@@ -24,6 +24,7 @@ export interface BaseNodeProps {
|
|
|
24
24
|
getModelMap: () => Map<string, Model>;
|
|
25
25
|
popper: PopperManager;
|
|
26
26
|
cslProps: CSLProps;
|
|
27
|
+
setEditorSelectedSuggestion: (id?: string) => void;
|
|
27
28
|
}
|
|
28
29
|
export declare class BaseNodeView<PropsType extends BaseNodeProps> implements NodeView {
|
|
29
30
|
readonly props: PropsType;
|
|
@@ -32,6 +32,7 @@ export declare class BibliographyElementBlockView<PropsType extends Bibliography
|
|
|
32
32
|
createElement: () => void;
|
|
33
33
|
private handleSave;
|
|
34
34
|
private handleDelete;
|
|
35
|
+
private addClickListenerToBibItem;
|
|
35
36
|
}
|
|
36
37
|
declare const _default: (props: BaseNodeProps, dispatch?: import("..").Dispatch | undefined) => import("../types").NodeViewCreator<BibliographyElementBlockView<any>>;
|
|
37
38
|
export default _default;
|
|
@@ -13,7 +13,7 @@ export declare class ContributorsView<PropsType extends ContributorsProps> exten
|
|
|
13
13
|
buildAuthors: () => void;
|
|
14
14
|
container: HTMLElement;
|
|
15
15
|
inner: HTMLElement;
|
|
16
|
-
buildAuthor: (node: ContributorNode, isJointFirstAuthor: boolean) => HTMLButtonElement;
|
|
16
|
+
buildAuthor: (node: ContributorNode, isJointFirstAuthor: boolean, selectedAuthor?: string) => HTMLButtonElement;
|
|
17
17
|
createNote(text?: string, title?: string): HTMLSpanElement;
|
|
18
18
|
initials: (given: string) => string;
|
|
19
19
|
buildNameLiteral: ({ given, family, suffix }: {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@manuscripts/body-editor",
|
|
3
3
|
"description": "Prosemirror components for editing and viewing manuscripts",
|
|
4
|
-
"version": "1.7.
|
|
4
|
+
"version": "1.7.5",
|
|
5
5
|
"repository": "github:Atypon-OpenSource/manuscripts-body-editor",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"main": "dist/cjs",
|
|
@@ -109,4 +109,4 @@
|
|
|
109
109
|
"resolutions": {
|
|
110
110
|
"@types/react": "^17.0.2"
|
|
111
111
|
}
|
|
112
|
-
}
|
|
112
|
+
}
|
|
@@ -571,7 +571,7 @@ Next levels are shifted 'up' by 1
|
|
|
571
571
|
background-color: inherit !important;
|
|
572
572
|
}
|
|
573
573
|
|
|
574
|
-
.keywords .keyword:hover {
|
|
574
|
+
.keywords .keyword:hover:not(.pending) {
|
|
575
575
|
background-color: #f2fbfc !important;
|
|
576
576
|
}
|
|
577
577
|
|
|
@@ -688,8 +688,19 @@ Next levels are shifted 'up' by 1
|
|
|
688
688
|
--selection-bg-color: #bce7f6;
|
|
689
689
|
}
|
|
690
690
|
|
|
691
|
-
.
|
|
692
|
-
background:
|
|
691
|
+
.selected-suggestion::selection {
|
|
692
|
+
background: none;
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
.selected-suggestion {
|
|
696
|
+
background: #BCE7F6 !important;
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
.selected-suggestion {
|
|
700
|
+
border-width: 2px 0 2px 0 !important;
|
|
701
|
+
border-color: #20AEDF !important;
|
|
702
|
+
border-radius: 3px !important;
|
|
703
|
+
border-style: solid !important;
|
|
693
704
|
}
|
|
694
705
|
|
|
695
706
|
.ProseMirror .inserted.pending {
|
|
@@ -880,3 +891,7 @@ Next levels are shifted 'up' by 1
|
|
|
880
891
|
flex-direction: column;
|
|
881
892
|
align-items: flex-start;
|
|
882
893
|
}
|
|
894
|
+
|
|
895
|
+
* {
|
|
896
|
+
scroll-behavior: smooth;
|
|
897
|
+
}
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*!
|
|
3
|
-
* © 2019 Atypon Systems LLC
|
|
4
|
-
*
|
|
5
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
-
* you may not use this file except in compliance with the License.
|
|
7
|
-
* You may obtain a copy of the License at
|
|
8
|
-
*
|
|
9
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
-
*
|
|
11
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
-
* See the License for the specific language governing permissions and
|
|
15
|
-
* limitations under the License.
|
|
16
|
-
*/
|
|
17
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
-
const track_changes_plugin_1 = require("@manuscripts/track-changes-plugin");
|
|
19
|
-
const prosemirror_state_1 = require("prosemirror-state");
|
|
20
|
-
const prosemirror_view_1 = require("prosemirror-view");
|
|
21
|
-
const ACCEPT_BUTTON_XLINK = '#track-changes-action-accept';
|
|
22
|
-
const REJECT_BUTTON_XLINK = '#track-changes-action-reject';
|
|
23
|
-
const BASE_CLASS = 'track-changes';
|
|
24
|
-
var CLASSES;
|
|
25
|
-
(function (CLASSES) {
|
|
26
|
-
CLASSES["focused"] = "focused";
|
|
27
|
-
CLASSES["control"] = "control";
|
|
28
|
-
})(CLASSES || (CLASSES = {}));
|
|
29
|
-
const createControl = (change, action, xLink) => {
|
|
30
|
-
return `
|
|
31
|
-
<button type="button" data-action="${action}" data-changeid="${change.id}">
|
|
32
|
-
<svg><use href="${xLink}"></use></svg>
|
|
33
|
-
</button>
|
|
34
|
-
`;
|
|
35
|
-
};
|
|
36
|
-
const getClassnames = (...types) => {
|
|
37
|
-
return [BASE_CLASS].concat(types.filter(Boolean).map((type) => `${BASE_CLASS}--${type}`));
|
|
38
|
-
};
|
|
39
|
-
const addClassnamesToEl = (el, ...types) => {
|
|
40
|
-
getClassnames(...types).forEach((classname) => el.classList.add(classname));
|
|
41
|
-
};
|
|
42
|
-
const geControlsPosition = (change) => {
|
|
43
|
-
const NODE_OFFSET = {
|
|
44
|
-
'text-change': 0,
|
|
45
|
-
'wrap-change': 0,
|
|
46
|
-
'mark-change': 0,
|
|
47
|
-
'node-attr-change': 0,
|
|
48
|
-
'node-change-keyword': 1,
|
|
49
|
-
};
|
|
50
|
-
const offset = (change.type === 'node-change'
|
|
51
|
-
? NODE_OFFSET[`${change.type}-${change.nodeType}`]
|
|
52
|
-
: NODE_OFFSET[change.type]) || 0;
|
|
53
|
-
return change.to - offset;
|
|
54
|
-
};
|
|
55
|
-
const createControls = (change) => {
|
|
56
|
-
return prosemirror_view_1.Decoration.widget(geControlsPosition(change), () => {
|
|
57
|
-
const el = document.createElement('div');
|
|
58
|
-
addClassnamesToEl(el, CLASSES.control);
|
|
59
|
-
el.dataset.changeid = change.id;
|
|
60
|
-
el.innerHTML =
|
|
61
|
-
createControl(change, 'reject', REJECT_BUTTON_XLINK) +
|
|
62
|
-
createControl(change, 'accept', ACCEPT_BUTTON_XLINK);
|
|
63
|
-
return el;
|
|
64
|
-
}, { side: -1 });
|
|
65
|
-
};
|
|
66
|
-
const decorateChanges = (state) => {
|
|
67
|
-
const pluginState = track_changes_plugin_1.trackChangesPluginKey.getState(state);
|
|
68
|
-
if (!pluginState) {
|
|
69
|
-
return [];
|
|
70
|
-
}
|
|
71
|
-
const { pending } = pluginState.changeSet;
|
|
72
|
-
return pending.reduce((decorations, change) => {
|
|
73
|
-
if (change.id === null) {
|
|
74
|
-
return decorations;
|
|
75
|
-
}
|
|
76
|
-
return [...decorations, createControls(change)];
|
|
77
|
-
}, []);
|
|
78
|
-
};
|
|
79
|
-
const getTrackChangesData = (node) => {
|
|
80
|
-
var _a;
|
|
81
|
-
const trackChangesMark = node.marks.find((mark) => (mark.type.name === 'tracked_insert' ||
|
|
82
|
-
mark.type.name === 'tracked_delete') &&
|
|
83
|
-
mark.attrs.dataTracked);
|
|
84
|
-
return (_a = trackChangesMark === null || trackChangesMark === void 0 ? void 0 : trackChangesMark.attrs) === null || _a === void 0 ? void 0 : _a.dataTracked;
|
|
85
|
-
};
|
|
86
|
-
exports.default = (props) => new prosemirror_state_1.Plugin({
|
|
87
|
-
props: {
|
|
88
|
-
handleClick(view, pos) {
|
|
89
|
-
if (props.setEditorSelectedSuggestion) {
|
|
90
|
-
const nodeClicked = view.state.doc.nodeAt(pos);
|
|
91
|
-
const trackChangesData = nodeClicked && getTrackChangesData(nodeClicked);
|
|
92
|
-
if (trackChangesData) {
|
|
93
|
-
props.setEditorSelectedSuggestion(trackChangesData.id);
|
|
94
|
-
}
|
|
95
|
-
else {
|
|
96
|
-
props.setEditorSelectedSuggestion(undefined);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
},
|
|
100
|
-
decorations: (state) => {
|
|
101
|
-
return prosemirror_view_1.DecorationSet.create(state.doc, decorateChanges(state));
|
|
102
|
-
},
|
|
103
|
-
},
|
|
104
|
-
});
|