@manuscripts/body-editor 1.6.6 → 1.6.7-LEAN-3083-3
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/configs/editor-plugins.js +2 -0
- package/dist/cjs/configs/editor-views.js +4 -0
- package/dist/cjs/plugins/affiliations.js +94 -0
- package/dist/cjs/plugins/highlight/index.js +0 -1
- package/dist/cjs/views/affiliation.js +74 -0
- package/dist/cjs/views/affiliations.js +17 -0
- package/dist/cjs/views/contributors.js +142 -11
- package/dist/es/configs/editor-plugins.js +2 -0
- package/dist/es/configs/editor-views.js +4 -0
- package/dist/es/plugins/affiliations.js +90 -0
- package/dist/es/plugins/highlight/index.js +0 -1
- package/dist/es/views/affiliation.js +70 -0
- package/dist/es/views/affiliations.js +10 -0
- package/dist/es/views/contributors.js +142 -11
- package/dist/types/configs/ManuscriptsEditor.d.ts +2 -0
- package/dist/types/configs/editor-views.d.ts +2 -0
- package/dist/types/plugins/affiliations.d.ts +25 -0
- package/dist/types/types.d.ts +4 -0
- package/dist/types/views/affiliation.d.ts +31 -0
- package/dist/types/views/affiliations.d.ts +8 -0
- package/dist/types/views/contributors.d.ts +24 -8
- package/package.json +2 -2
- package/styles/AdvancedEditor.css +126 -36
- package/styles/Editor.css +1 -2
|
@@ -25,6 +25,7 @@ const prosemirror_dropcursor_1 = require("prosemirror-dropcursor");
|
|
|
25
25
|
const prosemirror_history_1 = require("prosemirror-history");
|
|
26
26
|
const prosemirror_tables_1 = require("prosemirror-tables");
|
|
27
27
|
const keys_1 = __importDefault(require("../keys"));
|
|
28
|
+
const affiliations_1 = __importDefault(require("../plugins/affiliations"));
|
|
28
29
|
const bibliography_1 = __importDefault(require("../plugins/bibliography"));
|
|
29
30
|
const comment_annotation_1 = __importDefault(require("../plugins/comment_annotation"));
|
|
30
31
|
const elements_1 = __importDefault(require("../plugins/elements"));
|
|
@@ -57,6 +58,7 @@ exports.default = (props) => {
|
|
|
57
58
|
(0, keywords_1.default)(props),
|
|
58
59
|
(0, bibliography_1.default)(props),
|
|
59
60
|
(0, objects_1.default)(props),
|
|
61
|
+
(0, affiliations_1.default)(),
|
|
60
62
|
(0, comment_annotation_1.default)(props),
|
|
61
63
|
(0, paragraphs_1.default)(),
|
|
62
64
|
(0, placeholder_1.default)(),
|
|
@@ -18,6 +18,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
18
18
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
19
19
|
};
|
|
20
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
const affiliation_1 = __importDefault(require("../views/affiliation"));
|
|
22
|
+
const affiliations_1 = __importDefault(require("../views/affiliations"));
|
|
21
23
|
const bibliography_element_editable_1 = __importDefault(require("../views/bibliography_element_editable"));
|
|
22
24
|
const blockquote_element_editable_1 = __importDefault(require("../views/blockquote_element_editable"));
|
|
23
25
|
const bullet_list_editable_1 = __importDefault(require("../views/bullet_list_editable"));
|
|
@@ -57,6 +59,8 @@ exports.default = (props, dispatch) => {
|
|
|
57
59
|
citation: (0, citation_editable_1.default)(props),
|
|
58
60
|
cross_reference: (0, cross_reference_editable_1.default)(props),
|
|
59
61
|
contributors: (0, contributors_1.default)(props, dispatch),
|
|
62
|
+
affiliations: (0, affiliations_1.default)(props, dispatch),
|
|
63
|
+
affiliation: (0, affiliation_1.default)(props, dispatch),
|
|
60
64
|
equation: (0, equation_editable_1.default)(props),
|
|
61
65
|
equation_element: (0, equation_element_editable_1.default)(props),
|
|
62
66
|
figure: (0, figure_editable_1.default)(props, dispatch),
|
|
@@ -0,0 +1,94 @@
|
|
|
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
|
+
exports.buildPluginState = exports.affiliationsKey = void 0;
|
|
19
|
+
const transform_1 = require("@manuscripts/transform");
|
|
20
|
+
const prosemirror_state_1 = require("prosemirror-state");
|
|
21
|
+
const prosemirror_view_1 = require("prosemirror-view");
|
|
22
|
+
const track_changes_utils_1 = require("../lib/track-changes-utils");
|
|
23
|
+
exports.affiliationsKey = new prosemirror_state_1.PluginKey('affiliations');
|
|
24
|
+
const buildPluginState = (doc) => {
|
|
25
|
+
const contributors = [];
|
|
26
|
+
const affiliations = [];
|
|
27
|
+
doc.descendants((node, pos) => {
|
|
28
|
+
if ((0, track_changes_utils_1.isDeleted)(node)) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if ((0, transform_1.isAffiliationNode)(node)) {
|
|
32
|
+
affiliations.push([node, pos]);
|
|
33
|
+
}
|
|
34
|
+
if ((0, transform_1.isContributorNode)(node)) {
|
|
35
|
+
contributors.push([node, pos]);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
const iAffiliations = new Set();
|
|
39
|
+
contributors
|
|
40
|
+
.map(([node]) => node)
|
|
41
|
+
.sort((a, b) => {
|
|
42
|
+
return Number(a.attrs.priority) - Number(b.attrs.priority);
|
|
43
|
+
})
|
|
44
|
+
.forEach((author) => {
|
|
45
|
+
author.attrs.affiliations.forEach((aff) => {
|
|
46
|
+
iAffiliations.add(aff);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
const indexedAffiliationIds = new Map([...iAffiliations].map((id, i) => [id, i + 1]));
|
|
50
|
+
return {
|
|
51
|
+
indexedAffiliationIds,
|
|
52
|
+
contributors,
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
exports.buildPluginState = buildPluginState;
|
|
56
|
+
let count = 0;
|
|
57
|
+
exports.default = () => {
|
|
58
|
+
return new prosemirror_state_1.Plugin({
|
|
59
|
+
key: exports.affiliationsKey,
|
|
60
|
+
state: {
|
|
61
|
+
init(config, instance) {
|
|
62
|
+
return (0, exports.buildPluginState)(instance.doc);
|
|
63
|
+
},
|
|
64
|
+
apply(tr, value, oldState, newState) {
|
|
65
|
+
const prevPluginState = exports.affiliationsKey.getState(oldState);
|
|
66
|
+
if (!tr.docChanged && prevPluginState) {
|
|
67
|
+
return prevPluginState;
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
return (0, exports.buildPluginState)(newState.doc);
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
props: {
|
|
75
|
+
decorations: (state) => {
|
|
76
|
+
const decorations = [];
|
|
77
|
+
const allNodes = [];
|
|
78
|
+
state.doc.descendants((node, pos) => {
|
|
79
|
+
if ((0, transform_1.isAffiliationNode)(node) || (0, transform_1.isContributorNode)(node)) {
|
|
80
|
+
allNodes.push([node, pos]);
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
if (allNodes.length) {
|
|
84
|
+
allNodes.forEach(([node, pos]) => {
|
|
85
|
+
decorations.push(prosemirror_view_1.Decoration.node(pos, pos + node.nodeSize, {}, {
|
|
86
|
+
refresh: count++,
|
|
87
|
+
}));
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
return prosemirror_view_1.DecorationSet.create(state.doc, decorations);
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
};
|
|
@@ -54,7 +54,6 @@ const buildPluginState = (doc) => {
|
|
|
54
54
|
const decorations = prosemirror_view_1.DecorationSet.create(doc, highlights.map((h) => prosemirror_view_1.Decoration.inline(h.start, h.end, {
|
|
55
55
|
nodeName: 'span',
|
|
56
56
|
class: 'highlight',
|
|
57
|
-
style: `background: rgba(250, 224, 150, 0.6)`,
|
|
58
57
|
})));
|
|
59
58
|
return { highlights, decorations };
|
|
60
59
|
};
|
|
@@ -0,0 +1,74 @@
|
|
|
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
|
+
exports.AffiliationView = void 0;
|
|
19
|
+
const affiliations_1 = require("../plugins/affiliations");
|
|
20
|
+
const base_node_view_1 = require("./base_node_view");
|
|
21
|
+
const creators_1 = require("./creators");
|
|
22
|
+
class AffiliationView extends base_node_view_1.BaseNodeView {
|
|
23
|
+
constructor() {
|
|
24
|
+
super(...arguments);
|
|
25
|
+
this.initialise = () => {
|
|
26
|
+
this.createDOM();
|
|
27
|
+
};
|
|
28
|
+
this.updateContents = () => {
|
|
29
|
+
var _a;
|
|
30
|
+
const attrs = this.node.attrs;
|
|
31
|
+
const pluginState = affiliations_1.affiliationsKey.getState(this.view.state);
|
|
32
|
+
this.dom.innerHTML = this.formatAddress(attrs);
|
|
33
|
+
if (pluginState === null || pluginState === void 0 ? void 0 : pluginState.indexedAffiliationIds) {
|
|
34
|
+
const order = pluginState.indexedAffiliationIds.get(attrs.id);
|
|
35
|
+
this.dom.innerHTML = order
|
|
36
|
+
? order + ' ' + this.dom.innerHTML
|
|
37
|
+
: this.dom.innerHTML;
|
|
38
|
+
this.dom.setAttribute('style', 'order: ' + (order || 0));
|
|
39
|
+
}
|
|
40
|
+
if ((_a = attrs.dataTracked) === null || _a === void 0 ? void 0 : _a.length) {
|
|
41
|
+
this.dom.setAttribute('data-track-status', attrs.dataTracked[0].status);
|
|
42
|
+
this.dom.setAttribute('data-track-op', attrs.dataTracked[0].operation);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
this.dom.removeAttribute('data-track-status');
|
|
46
|
+
this.dom.removeAttribute('data-track-type');
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
this.createDOM = () => {
|
|
50
|
+
this.dom = document.createElement('div');
|
|
51
|
+
this.dom.classList.add('affiliation');
|
|
52
|
+
this.dom.setAttribute('id', this.node.attrs.id);
|
|
53
|
+
this.updateContents();
|
|
54
|
+
};
|
|
55
|
+
this.ignoreMutation = () => true;
|
|
56
|
+
this.stopEvent = () => true;
|
|
57
|
+
this.formatAddress = (affiliation) => {
|
|
58
|
+
const { department, institution, addressLine1, city, county, country, postCode, } = affiliation;
|
|
59
|
+
return [
|
|
60
|
+
department,
|
|
61
|
+
institution,
|
|
62
|
+
addressLine1,
|
|
63
|
+
city,
|
|
64
|
+
county,
|
|
65
|
+
country,
|
|
66
|
+
postCode,
|
|
67
|
+
]
|
|
68
|
+
.filter(Boolean)
|
|
69
|
+
.join(', ');
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
exports.AffiliationView = AffiliationView;
|
|
74
|
+
exports.default = (0, creators_1.createNodeView)(AffiliationView);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.AffiliationsView = void 0;
|
|
7
|
+
const block_view_1 = __importDefault(require("./block_view"));
|
|
8
|
+
const creators_1 = require("./creators");
|
|
9
|
+
class AffiliationsView extends block_view_1.default {
|
|
10
|
+
constructor() {
|
|
11
|
+
super(...arguments);
|
|
12
|
+
this.ignoreMutation = () => true;
|
|
13
|
+
this.stopEvent = () => true;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
exports.AffiliationsView = AffiliationsView;
|
|
17
|
+
exports.default = (0, creators_1.createNodeView)(AffiliationsView);
|
|
@@ -4,32 +4,163 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.ContributorsView = void 0;
|
|
7
|
-
const
|
|
7
|
+
const style_guide_1 = require("@manuscripts/style-guide");
|
|
8
|
+
const transform_1 = require("@manuscripts/transform");
|
|
9
|
+
const affiliations_1 = require("../plugins/affiliations");
|
|
10
|
+
const block_view_1 = __importDefault(require("./block_view"));
|
|
8
11
|
const creators_1 = require("./creators");
|
|
9
12
|
const ReactSubView_1 = __importDefault(require("./ReactSubView"));
|
|
10
|
-
class ContributorsView extends
|
|
13
|
+
class ContributorsView extends block_view_1.default {
|
|
11
14
|
constructor() {
|
|
12
15
|
super(...arguments);
|
|
13
16
|
this.initialise = () => {
|
|
14
17
|
this.createDOM();
|
|
18
|
+
this.createGutter('block-gutter', this.gutterButtons().filter(Boolean));
|
|
19
|
+
this.createElement();
|
|
20
|
+
this.createGutter('action-gutter', this.actionGutterButtons().filter(Boolean));
|
|
21
|
+
this.updateContents();
|
|
22
|
+
};
|
|
23
|
+
this.updateContents = () => {
|
|
24
|
+
this.updateClasses();
|
|
25
|
+
this.updateAttributes();
|
|
26
|
+
this.container.innerHTML = '';
|
|
27
|
+
this.buildAuthors();
|
|
28
|
+
this.createEditButton();
|
|
29
|
+
this.createLegend();
|
|
30
|
+
};
|
|
31
|
+
this.buildAuthors = () => {
|
|
32
|
+
var _a;
|
|
33
|
+
const authors = [];
|
|
34
|
+
const authorsWrapper = document.createElement('div');
|
|
35
|
+
authorsWrapper.classList.add('contributors-list');
|
|
36
|
+
(_a = this.node.content) === null || _a === void 0 ? void 0 : _a.forEach((node) => {
|
|
37
|
+
if ((0, transform_1.isContributorNode)(node)) {
|
|
38
|
+
authors.push(node);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
authors
|
|
42
|
+
.sort((a, b) => Number(a.attrs.priority) - Number(b.attrs.priority))
|
|
43
|
+
.forEach((author, i) => {
|
|
44
|
+
const jointAuthors = this.isJointFirstAuthor(authors, i);
|
|
45
|
+
authorsWrapper.appendChild(this.buildAuthor(author, jointAuthors));
|
|
46
|
+
});
|
|
47
|
+
this.container.appendChild(authorsWrapper);
|
|
48
|
+
};
|
|
49
|
+
this.buildAuthor = (node, isJointFirstAuthor) => {
|
|
50
|
+
var _a;
|
|
51
|
+
const pluginState = affiliations_1.affiliationsKey.getState(this.view.state);
|
|
52
|
+
const attrs = node.attrs;
|
|
53
|
+
const container = document.createElement('button');
|
|
54
|
+
container.classList.add('contributor');
|
|
55
|
+
container.setAttribute('id', attrs.id);
|
|
56
|
+
container.setAttribute('contenteditable', 'false');
|
|
57
|
+
if ((_a = attrs.dataTracked) === null || _a === void 0 ? void 0 : _a.length) {
|
|
58
|
+
container.setAttribute('data-track-status', attrs.dataTracked[0].status);
|
|
59
|
+
container.setAttribute('data-track-op', attrs.dataTracked[0].operation);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
container.removeAttribute('data-track-status');
|
|
63
|
+
container.removeAttribute('data-track-type');
|
|
64
|
+
}
|
|
65
|
+
const can = this.props.getCapabilities();
|
|
66
|
+
const disableEditButton = !can.editMetadata;
|
|
67
|
+
const { bibliographicName, isCorresponding, email, id } = attrs;
|
|
68
|
+
container.addEventListener('click', (e) => {
|
|
69
|
+
e.preventDefault();
|
|
70
|
+
if (!disableEditButton) {
|
|
71
|
+
this.props.openAuthorEditing();
|
|
72
|
+
this.props.selectAuthorForEditing(id);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
const name = this.buildNameLiteral(bibliographicName);
|
|
76
|
+
container.innerHTML = isCorresponding && email ? `${name} (${email})` : name;
|
|
77
|
+
let noteText = '';
|
|
78
|
+
if (pluginState === null || pluginState === void 0 ? void 0 : pluginState.indexedAffiliationIds) {
|
|
79
|
+
attrs.affiliations.map((af) => {
|
|
80
|
+
const index = pluginState === null || pluginState === void 0 ? void 0 : pluginState.indexedAffiliationIds.get(af);
|
|
81
|
+
if (index) {
|
|
82
|
+
noteText += index.toString();
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
if (isJointFirstAuthor) {
|
|
87
|
+
container.appendChild(this.createNote('†', 'Joint contributor'));
|
|
88
|
+
}
|
|
89
|
+
if (noteText) {
|
|
90
|
+
container.appendChild(this.createNote(noteText));
|
|
91
|
+
}
|
|
92
|
+
if (attrs.isCorresponding) {
|
|
93
|
+
container.appendChild(this.createNote('*', 'Corresponding author'));
|
|
94
|
+
}
|
|
95
|
+
return container;
|
|
96
|
+
};
|
|
97
|
+
this.initials = (given) => given
|
|
98
|
+
? given
|
|
99
|
+
.trim()
|
|
100
|
+
.split(' ')
|
|
101
|
+
.map((part) => part.substr(0, 1).toUpperCase() + '.')
|
|
102
|
+
.join('')
|
|
103
|
+
: '';
|
|
104
|
+
this.buildNameLiteral = ({ given = '', family = '', suffix = '' }) => {
|
|
105
|
+
if (!given && !family) {
|
|
106
|
+
return 'Unknown Author';
|
|
107
|
+
}
|
|
108
|
+
return [this.initials(given), family, suffix]
|
|
109
|
+
.filter((part) => part)
|
|
110
|
+
.join(' ');
|
|
111
|
+
};
|
|
112
|
+
this.isJointFirstAuthor = (authors, index) => {
|
|
113
|
+
const author = index === 0 ? authors[index] : authors[index - 1];
|
|
114
|
+
return Boolean(author.attrs.isJointContributor);
|
|
115
|
+
};
|
|
116
|
+
this.createElement = () => {
|
|
117
|
+
this.inner = document.createElement('div');
|
|
118
|
+
this.inner.classList.add('authors-container', 'block');
|
|
119
|
+
this.dom.appendChild(this.inner);
|
|
120
|
+
this.container = document.createElement('div');
|
|
121
|
+
this.container.classList.add('contributors');
|
|
122
|
+
this.inner.appendChild(this.container);
|
|
15
123
|
};
|
|
16
124
|
this.createDOM = () => {
|
|
17
125
|
this.dom = document.createElement('div');
|
|
18
|
-
this.dom.classList.add('
|
|
126
|
+
this.dom.classList.add('block-container', `block-${this.node.type.name}`);
|
|
127
|
+
};
|
|
128
|
+
this.createEditButton = () => {
|
|
19
129
|
const can = this.props.getCapabilities();
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
130
|
+
const button = (0, ReactSubView_1.default)(this.props, style_guide_1.SecondaryButton, {
|
|
131
|
+
mini: true,
|
|
132
|
+
onClick: this.props.openAuthorEditing,
|
|
133
|
+
className: 'edit-authors-button',
|
|
134
|
+
disabled: !can.editMetadata,
|
|
135
|
+
children: 'Edit Authors',
|
|
136
|
+
}, this.node, this.getPos, this.view);
|
|
137
|
+
this.container.appendChild(button);
|
|
138
|
+
};
|
|
139
|
+
this.createLegend = () => {
|
|
140
|
+
const state = affiliations_1.affiliationsKey.getState(this.view.state);
|
|
141
|
+
if (state === null || state === void 0 ? void 0 : state.contributors) {
|
|
142
|
+
const isThereJointContributor = state.contributors.find(([contributor]) => contributor.attrs.isJointContributor);
|
|
143
|
+
if (isThereJointContributor) {
|
|
144
|
+
const element = document.createElement('p');
|
|
145
|
+
element.classList.add('contributors-legend');
|
|
146
|
+
element.innerHTML =
|
|
147
|
+
'<span class="symbol">†</span>These authors contributed equally to this work.';
|
|
148
|
+
this.container.appendChild(element);
|
|
149
|
+
}
|
|
28
150
|
}
|
|
29
151
|
};
|
|
30
152
|
this.ignoreMutation = () => true;
|
|
31
153
|
this.stopEvent = () => true;
|
|
32
154
|
}
|
|
155
|
+
createNote(text = '', title = '') {
|
|
156
|
+
const el = document.createElement('span');
|
|
157
|
+
el.innerHTML = text;
|
|
158
|
+
if (title) {
|
|
159
|
+
el.setAttribute('title', title);
|
|
160
|
+
}
|
|
161
|
+
el.classList.add('contributor-note');
|
|
162
|
+
return el;
|
|
163
|
+
}
|
|
33
164
|
}
|
|
34
165
|
exports.ContributorsView = ContributorsView;
|
|
35
166
|
exports.default = (0, creators_1.createNodeView)(ContributorsView);
|
|
@@ -20,6 +20,7 @@ import { dropCursor } from 'prosemirror-dropcursor';
|
|
|
20
20
|
import { history } from 'prosemirror-history';
|
|
21
21
|
import { tableEditing } from 'prosemirror-tables';
|
|
22
22
|
import keys from '../keys';
|
|
23
|
+
import affiliations from '../plugins/affiliations';
|
|
23
24
|
import bibliography from '../plugins/bibliography';
|
|
24
25
|
import comment_annotation from '../plugins/comment_annotation';
|
|
25
26
|
import elements from '../plugins/elements';
|
|
@@ -52,6 +53,7 @@ export default (props) => {
|
|
|
52
53
|
keywords(props),
|
|
53
54
|
bibliography(props),
|
|
54
55
|
objects(props),
|
|
56
|
+
affiliations(),
|
|
55
57
|
comment_annotation(props),
|
|
56
58
|
paragraphs(),
|
|
57
59
|
placeholder(),
|
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
* See the License for the specific language governing permissions and
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
|
+
import affiliation from '../views/affiliation';
|
|
17
|
+
import affiliationsSection from '../views/affiliations';
|
|
16
18
|
import bibliographyElement from '../views/bibliography_element_editable';
|
|
17
19
|
import blockquoteElement from '../views/blockquote_element_editable';
|
|
18
20
|
import bulletList from '../views/bullet_list_editable';
|
|
@@ -52,6 +54,8 @@ export default (props, dispatch) => {
|
|
|
52
54
|
citation: citation(props),
|
|
53
55
|
cross_reference: crossReference(props),
|
|
54
56
|
contributors: contributorsSection(props, dispatch),
|
|
57
|
+
affiliations: affiliationsSection(props, dispatch),
|
|
58
|
+
affiliation: affiliation(props, dispatch),
|
|
55
59
|
equation: equation(props),
|
|
56
60
|
equation_element: equationElement(props),
|
|
57
61
|
figure: figure(props, dispatch),
|
|
@@ -0,0 +1,90 @@
|
|
|
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 { isAffiliationNode, isContributorNode, } from '@manuscripts/transform';
|
|
17
|
+
import { Plugin, PluginKey } from 'prosemirror-state';
|
|
18
|
+
import { Decoration, DecorationSet } from 'prosemirror-view';
|
|
19
|
+
import { isDeleted } from '../lib/track-changes-utils';
|
|
20
|
+
export const affiliationsKey = new PluginKey('affiliations');
|
|
21
|
+
export const buildPluginState = (doc) => {
|
|
22
|
+
const contributors = [];
|
|
23
|
+
const affiliations = [];
|
|
24
|
+
doc.descendants((node, pos) => {
|
|
25
|
+
if (isDeleted(node)) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
if (isAffiliationNode(node)) {
|
|
29
|
+
affiliations.push([node, pos]);
|
|
30
|
+
}
|
|
31
|
+
if (isContributorNode(node)) {
|
|
32
|
+
contributors.push([node, pos]);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
const iAffiliations = new Set();
|
|
36
|
+
contributors
|
|
37
|
+
.map(([node]) => node)
|
|
38
|
+
.sort((a, b) => {
|
|
39
|
+
return Number(a.attrs.priority) - Number(b.attrs.priority);
|
|
40
|
+
})
|
|
41
|
+
.forEach((author) => {
|
|
42
|
+
author.attrs.affiliations.forEach((aff) => {
|
|
43
|
+
iAffiliations.add(aff);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
const indexedAffiliationIds = new Map([...iAffiliations].map((id, i) => [id, i + 1]));
|
|
47
|
+
return {
|
|
48
|
+
indexedAffiliationIds,
|
|
49
|
+
contributors,
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
let count = 0;
|
|
53
|
+
export default () => {
|
|
54
|
+
return new Plugin({
|
|
55
|
+
key: affiliationsKey,
|
|
56
|
+
state: {
|
|
57
|
+
init(config, instance) {
|
|
58
|
+
return buildPluginState(instance.doc);
|
|
59
|
+
},
|
|
60
|
+
apply(tr, value, oldState, newState) {
|
|
61
|
+
const prevPluginState = affiliationsKey.getState(oldState);
|
|
62
|
+
if (!tr.docChanged && prevPluginState) {
|
|
63
|
+
return prevPluginState;
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
return buildPluginState(newState.doc);
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
props: {
|
|
71
|
+
decorations: (state) => {
|
|
72
|
+
const decorations = [];
|
|
73
|
+
const allNodes = [];
|
|
74
|
+
state.doc.descendants((node, pos) => {
|
|
75
|
+
if (isAffiliationNode(node) || isContributorNode(node)) {
|
|
76
|
+
allNodes.push([node, pos]);
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
if (allNodes.length) {
|
|
80
|
+
allNodes.forEach(([node, pos]) => {
|
|
81
|
+
decorations.push(Decoration.node(pos, pos + node.nodeSize, {}, {
|
|
82
|
+
refresh: count++,
|
|
83
|
+
}));
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
return DecorationSet.create(state.doc, decorations);
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
};
|
|
@@ -48,7 +48,6 @@ const buildPluginState = (doc) => {
|
|
|
48
48
|
const decorations = DecorationSet.create(doc, highlights.map((h) => Decoration.inline(h.start, h.end, {
|
|
49
49
|
nodeName: 'span',
|
|
50
50
|
class: 'highlight',
|
|
51
|
-
style: `background: rgba(250, 224, 150, 0.6)`,
|
|
52
51
|
})));
|
|
53
52
|
return { highlights, decorations };
|
|
54
53
|
};
|
|
@@ -0,0 +1,70 @@
|
|
|
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 { affiliationsKey } from '../plugins/affiliations';
|
|
17
|
+
import { BaseNodeView } from './base_node_view';
|
|
18
|
+
import { createNodeView } from './creators';
|
|
19
|
+
export class AffiliationView extends BaseNodeView {
|
|
20
|
+
constructor() {
|
|
21
|
+
super(...arguments);
|
|
22
|
+
this.initialise = () => {
|
|
23
|
+
this.createDOM();
|
|
24
|
+
};
|
|
25
|
+
this.updateContents = () => {
|
|
26
|
+
var _a;
|
|
27
|
+
const attrs = this.node.attrs;
|
|
28
|
+
const pluginState = affiliationsKey.getState(this.view.state);
|
|
29
|
+
this.dom.innerHTML = this.formatAddress(attrs);
|
|
30
|
+
if (pluginState === null || pluginState === void 0 ? void 0 : pluginState.indexedAffiliationIds) {
|
|
31
|
+
const order = pluginState.indexedAffiliationIds.get(attrs.id);
|
|
32
|
+
this.dom.innerHTML = order
|
|
33
|
+
? order + ' ' + this.dom.innerHTML
|
|
34
|
+
: this.dom.innerHTML;
|
|
35
|
+
this.dom.setAttribute('style', 'order: ' + (order || 0));
|
|
36
|
+
}
|
|
37
|
+
if ((_a = attrs.dataTracked) === null || _a === void 0 ? void 0 : _a.length) {
|
|
38
|
+
this.dom.setAttribute('data-track-status', attrs.dataTracked[0].status);
|
|
39
|
+
this.dom.setAttribute('data-track-op', attrs.dataTracked[0].operation);
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
this.dom.removeAttribute('data-track-status');
|
|
43
|
+
this.dom.removeAttribute('data-track-type');
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
this.createDOM = () => {
|
|
47
|
+
this.dom = document.createElement('div');
|
|
48
|
+
this.dom.classList.add('affiliation');
|
|
49
|
+
this.dom.setAttribute('id', this.node.attrs.id);
|
|
50
|
+
this.updateContents();
|
|
51
|
+
};
|
|
52
|
+
this.ignoreMutation = () => true;
|
|
53
|
+
this.stopEvent = () => true;
|
|
54
|
+
this.formatAddress = (affiliation) => {
|
|
55
|
+
const { department, institution, addressLine1, city, county, country, postCode, } = affiliation;
|
|
56
|
+
return [
|
|
57
|
+
department,
|
|
58
|
+
institution,
|
|
59
|
+
addressLine1,
|
|
60
|
+
city,
|
|
61
|
+
county,
|
|
62
|
+
country,
|
|
63
|
+
postCode,
|
|
64
|
+
]
|
|
65
|
+
.filter(Boolean)
|
|
66
|
+
.join(', ');
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
export default createNodeView(AffiliationView);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import BlockView from './block_view';
|
|
2
|
+
import { createNodeView } from './creators';
|
|
3
|
+
export class AffiliationsView extends BlockView {
|
|
4
|
+
constructor() {
|
|
5
|
+
super(...arguments);
|
|
6
|
+
this.ignoreMutation = () => true;
|
|
7
|
+
this.stopEvent = () => true;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export default createNodeView(AffiliationsView);
|
|
@@ -1,28 +1,159 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SecondaryButton } from '@manuscripts/style-guide';
|
|
2
|
+
import { isContributorNode } from '@manuscripts/transform';
|
|
3
|
+
import { affiliationsKey } from '../plugins/affiliations';
|
|
4
|
+
import BlockView from './block_view';
|
|
2
5
|
import { createNodeView } from './creators';
|
|
3
6
|
import ReactSubView from './ReactSubView';
|
|
4
|
-
export class ContributorsView extends
|
|
7
|
+
export class ContributorsView extends BlockView {
|
|
5
8
|
constructor() {
|
|
6
9
|
super(...arguments);
|
|
7
10
|
this.initialise = () => {
|
|
8
11
|
this.createDOM();
|
|
12
|
+
this.createGutter('block-gutter', this.gutterButtons().filter(Boolean));
|
|
13
|
+
this.createElement();
|
|
14
|
+
this.createGutter('action-gutter', this.actionGutterButtons().filter(Boolean));
|
|
15
|
+
this.updateContents();
|
|
16
|
+
};
|
|
17
|
+
this.updateContents = () => {
|
|
18
|
+
this.updateClasses();
|
|
19
|
+
this.updateAttributes();
|
|
20
|
+
this.container.innerHTML = '';
|
|
21
|
+
this.buildAuthors();
|
|
22
|
+
this.createEditButton();
|
|
23
|
+
this.createLegend();
|
|
24
|
+
};
|
|
25
|
+
this.buildAuthors = () => {
|
|
26
|
+
var _a;
|
|
27
|
+
const authors = [];
|
|
28
|
+
const authorsWrapper = document.createElement('div');
|
|
29
|
+
authorsWrapper.classList.add('contributors-list');
|
|
30
|
+
(_a = this.node.content) === null || _a === void 0 ? void 0 : _a.forEach((node) => {
|
|
31
|
+
if (isContributorNode(node)) {
|
|
32
|
+
authors.push(node);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
authors
|
|
36
|
+
.sort((a, b) => Number(a.attrs.priority) - Number(b.attrs.priority))
|
|
37
|
+
.forEach((author, i) => {
|
|
38
|
+
const jointAuthors = this.isJointFirstAuthor(authors, i);
|
|
39
|
+
authorsWrapper.appendChild(this.buildAuthor(author, jointAuthors));
|
|
40
|
+
});
|
|
41
|
+
this.container.appendChild(authorsWrapper);
|
|
42
|
+
};
|
|
43
|
+
this.buildAuthor = (node, isJointFirstAuthor) => {
|
|
44
|
+
var _a;
|
|
45
|
+
const pluginState = affiliationsKey.getState(this.view.state);
|
|
46
|
+
const attrs = node.attrs;
|
|
47
|
+
const container = document.createElement('button');
|
|
48
|
+
container.classList.add('contributor');
|
|
49
|
+
container.setAttribute('id', attrs.id);
|
|
50
|
+
container.setAttribute('contenteditable', 'false');
|
|
51
|
+
if ((_a = attrs.dataTracked) === null || _a === void 0 ? void 0 : _a.length) {
|
|
52
|
+
container.setAttribute('data-track-status', attrs.dataTracked[0].status);
|
|
53
|
+
container.setAttribute('data-track-op', attrs.dataTracked[0].operation);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
container.removeAttribute('data-track-status');
|
|
57
|
+
container.removeAttribute('data-track-type');
|
|
58
|
+
}
|
|
59
|
+
const can = this.props.getCapabilities();
|
|
60
|
+
const disableEditButton = !can.editMetadata;
|
|
61
|
+
const { bibliographicName, isCorresponding, email, id } = attrs;
|
|
62
|
+
container.addEventListener('click', (e) => {
|
|
63
|
+
e.preventDefault();
|
|
64
|
+
if (!disableEditButton) {
|
|
65
|
+
this.props.openAuthorEditing();
|
|
66
|
+
this.props.selectAuthorForEditing(id);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
const name = this.buildNameLiteral(bibliographicName);
|
|
70
|
+
container.innerHTML = isCorresponding && email ? `${name} (${email})` : name;
|
|
71
|
+
let noteText = '';
|
|
72
|
+
if (pluginState === null || pluginState === void 0 ? void 0 : pluginState.indexedAffiliationIds) {
|
|
73
|
+
attrs.affiliations.map((af) => {
|
|
74
|
+
const index = pluginState === null || pluginState === void 0 ? void 0 : pluginState.indexedAffiliationIds.get(af);
|
|
75
|
+
if (index) {
|
|
76
|
+
noteText += index.toString();
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
if (isJointFirstAuthor) {
|
|
81
|
+
container.appendChild(this.createNote('†', 'Joint contributor'));
|
|
82
|
+
}
|
|
83
|
+
if (noteText) {
|
|
84
|
+
container.appendChild(this.createNote(noteText));
|
|
85
|
+
}
|
|
86
|
+
if (attrs.isCorresponding) {
|
|
87
|
+
container.appendChild(this.createNote('*', 'Corresponding author'));
|
|
88
|
+
}
|
|
89
|
+
return container;
|
|
90
|
+
};
|
|
91
|
+
this.initials = (given) => given
|
|
92
|
+
? given
|
|
93
|
+
.trim()
|
|
94
|
+
.split(' ')
|
|
95
|
+
.map((part) => part.substr(0, 1).toUpperCase() + '.')
|
|
96
|
+
.join('')
|
|
97
|
+
: '';
|
|
98
|
+
this.buildNameLiteral = ({ given = '', family = '', suffix = '' }) => {
|
|
99
|
+
if (!given && !family) {
|
|
100
|
+
return 'Unknown Author';
|
|
101
|
+
}
|
|
102
|
+
return [this.initials(given), family, suffix]
|
|
103
|
+
.filter((part) => part)
|
|
104
|
+
.join(' ');
|
|
105
|
+
};
|
|
106
|
+
this.isJointFirstAuthor = (authors, index) => {
|
|
107
|
+
const author = index === 0 ? authors[index] : authors[index - 1];
|
|
108
|
+
return Boolean(author.attrs.isJointContributor);
|
|
109
|
+
};
|
|
110
|
+
this.createElement = () => {
|
|
111
|
+
this.inner = document.createElement('div');
|
|
112
|
+
this.inner.classList.add('authors-container', 'block');
|
|
113
|
+
this.dom.appendChild(this.inner);
|
|
114
|
+
this.container = document.createElement('div');
|
|
115
|
+
this.container.classList.add('contributors');
|
|
116
|
+
this.inner.appendChild(this.container);
|
|
9
117
|
};
|
|
10
118
|
this.createDOM = () => {
|
|
11
119
|
this.dom = document.createElement('div');
|
|
12
|
-
this.dom.classList.add('
|
|
120
|
+
this.dom.classList.add('block-container', `block-${this.node.type.name}`);
|
|
121
|
+
};
|
|
122
|
+
this.createEditButton = () => {
|
|
13
123
|
const can = this.props.getCapabilities();
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
124
|
+
const button = ReactSubView(this.props, SecondaryButton, {
|
|
125
|
+
mini: true,
|
|
126
|
+
onClick: this.props.openAuthorEditing,
|
|
127
|
+
className: 'edit-authors-button',
|
|
128
|
+
disabled: !can.editMetadata,
|
|
129
|
+
children: 'Edit Authors',
|
|
130
|
+
}, this.node, this.getPos, this.view);
|
|
131
|
+
this.container.appendChild(button);
|
|
132
|
+
};
|
|
133
|
+
this.createLegend = () => {
|
|
134
|
+
const state = affiliationsKey.getState(this.view.state);
|
|
135
|
+
if (state === null || state === void 0 ? void 0 : state.contributors) {
|
|
136
|
+
const isThereJointContributor = state.contributors.find(([contributor]) => contributor.attrs.isJointContributor);
|
|
137
|
+
if (isThereJointContributor) {
|
|
138
|
+
const element = document.createElement('p');
|
|
139
|
+
element.classList.add('contributors-legend');
|
|
140
|
+
element.innerHTML =
|
|
141
|
+
'<span class="symbol">†</span>These authors contributed equally to this work.';
|
|
142
|
+
this.container.appendChild(element);
|
|
143
|
+
}
|
|
22
144
|
}
|
|
23
145
|
};
|
|
24
146
|
this.ignoreMutation = () => true;
|
|
25
147
|
this.stopEvent = () => true;
|
|
26
148
|
}
|
|
149
|
+
createNote(text = '', title = '') {
|
|
150
|
+
const el = document.createElement('span');
|
|
151
|
+
el.innerHTML = text;
|
|
152
|
+
if (title) {
|
|
153
|
+
el.setAttribute('title', title);
|
|
154
|
+
}
|
|
155
|
+
el.classList.add('contributor-note');
|
|
156
|
+
return el;
|
|
157
|
+
}
|
|
27
158
|
}
|
|
28
159
|
export default createNodeView(ContributorsView);
|
|
@@ -58,6 +58,8 @@ export interface EditorProps {
|
|
|
58
58
|
retrySync: (componentIDs: string[]) => Promise<void>;
|
|
59
59
|
environment?: string;
|
|
60
60
|
collabProvider?: CollabProvider;
|
|
61
|
+
openAuthorEditing: () => void;
|
|
62
|
+
selectAuthorForEditing: (authorId: string) => void;
|
|
61
63
|
}
|
|
62
64
|
export declare const createEditorState: (props: EditorProps) => EditorState;
|
|
63
65
|
export declare const createEditorView: (props: EditorProps, root: HTMLElement, state: EditorState, dispatch: Dispatch) => EditorView;
|
|
@@ -141,6 +141,8 @@ declare const _default: (props: EditorProps, dispatch: Dispatch) => {
|
|
|
141
141
|
citation: import("../types").NodeViewCreator<import("../views/citation_editable").CitationEditableView>;
|
|
142
142
|
cross_reference: import("../types").NodeViewCreator<import("../views/cross_reference_editable").CrossReferenceEditableView>;
|
|
143
143
|
contributors: import("../types").NodeViewCreator<import("../views/contributors").ContributorsView<any>>;
|
|
144
|
+
affiliations: import("../types").NodeViewCreator<import("../views/affiliations").AffiliationsView<any>>;
|
|
145
|
+
affiliation: import("../types").NodeViewCreator<import("../views/affiliation").AffiliationView<any>>;
|
|
144
146
|
equation: import("../types").NodeViewCreator<import("../views/equation_editable").EquationEditableView>;
|
|
145
147
|
equation_element: import("../types").NodeViewCreator<{
|
|
146
148
|
gutterButtons: () => HTMLElement[];
|
|
@@ -0,0 +1,25 @@
|
|
|
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 { ContributorNode, ManuscriptNode } from '@manuscripts/transform';
|
|
17
|
+
import { Plugin, PluginKey } from 'prosemirror-state';
|
|
18
|
+
interface PluginState {
|
|
19
|
+
indexedAffiliationIds: Map<string, number>;
|
|
20
|
+
contributors: Array<[ContributorNode, number]>;
|
|
21
|
+
}
|
|
22
|
+
export declare const affiliationsKey: PluginKey<PluginState>;
|
|
23
|
+
export declare const buildPluginState: (doc: ManuscriptNode) => PluginState;
|
|
24
|
+
declare const _default: () => Plugin<PluginState>;
|
|
25
|
+
export default _default;
|
package/dist/types/types.d.ts
CHANGED
|
@@ -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 { ManuscriptEditorState, ManuscriptEditorView, ManuscriptNode, ManuscriptNodeView, ManuscriptTransaction } from '@manuscripts/transform';
|
|
17
18
|
import { Decoration } from 'prosemirror-view';
|
|
18
19
|
export type EditorAction = (state: ManuscriptEditorState, dispatch?: (tr: ManuscriptTransaction) => void, view?: ManuscriptEditorView) => boolean;
|
|
@@ -24,3 +25,6 @@ export type ChangeReceiver = (op: string, id?: string, data?: ManuscriptNode | n
|
|
|
24
25
|
export interface SyncError {
|
|
25
26
|
_id: string;
|
|
26
27
|
}
|
|
28
|
+
export type TrackableAttributes<T extends ManuscriptNode> = T['attrs'] & {
|
|
29
|
+
dataTracked?: TrackedAttrs[];
|
|
30
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
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 { Capabilities } from '@manuscripts/style-guide';
|
|
17
|
+
import { AffiliationNode, ManuscriptNodeView } from '@manuscripts/transform';
|
|
18
|
+
import { BaseNodeProps, BaseNodeView } from './base_node_view';
|
|
19
|
+
export interface Props extends BaseNodeProps {
|
|
20
|
+
getCapabilities: () => Capabilities;
|
|
21
|
+
}
|
|
22
|
+
export declare class AffiliationView<PropsType extends BaseNodeProps> extends BaseNodeView<PropsType> implements ManuscriptNodeView {
|
|
23
|
+
initialise: () => void;
|
|
24
|
+
updateContents: () => void;
|
|
25
|
+
protected createDOM: () => void;
|
|
26
|
+
ignoreMutation: () => boolean;
|
|
27
|
+
stopEvent: () => boolean;
|
|
28
|
+
formatAddress: (affiliation: AffiliationNode['attrs']) => string;
|
|
29
|
+
}
|
|
30
|
+
declare const _default: (props: BaseNodeProps, dispatch?: import("..").Dispatch | undefined) => import("../types").NodeViewCreator<AffiliationView<any>>;
|
|
31
|
+
export default _default;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import BlockView from './block_view';
|
|
2
|
+
import { EditableBlockProps } from './editable_block';
|
|
3
|
+
export declare class AffiliationsView<PropsType extends EditableBlockProps> extends BlockView<PropsType> {
|
|
4
|
+
ignoreMutation: () => boolean;
|
|
5
|
+
stopEvent: () => boolean;
|
|
6
|
+
}
|
|
7
|
+
declare const _default: (props: import("./base_node_view").BaseNodeProps, dispatch?: import("..").Dispatch | undefined) => import("../types").NodeViewCreator<AffiliationsView<any>>;
|
|
8
|
+
export default _default;
|
|
@@ -1,15 +1,31 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import
|
|
1
|
+
import { Capabilities } from '@manuscripts/style-guide';
|
|
2
|
+
import { ContributorNode } from '@manuscripts/transform';
|
|
3
|
+
import BlockView from './block_view';
|
|
4
4
|
import { EditableBlockProps } from './editable_block';
|
|
5
5
|
export interface ContributorsProps extends EditableBlockProps {
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
getCapabilities: () => Capabilities;
|
|
7
|
+
openAuthorEditing: () => void;
|
|
8
|
+
selectAuthorForEditing: (authorId: string) => void;
|
|
8
9
|
}
|
|
9
|
-
export declare class ContributorsView<PropsType extends ContributorsProps> extends
|
|
10
|
-
private metadata;
|
|
10
|
+
export declare class ContributorsView<PropsType extends ContributorsProps> extends BlockView<PropsType> {
|
|
11
11
|
initialise: () => void;
|
|
12
|
-
|
|
12
|
+
updateContents: () => void;
|
|
13
|
+
buildAuthors: () => void;
|
|
14
|
+
container: HTMLElement;
|
|
15
|
+
inner: HTMLElement;
|
|
16
|
+
buildAuthor: (node: ContributorNode, isJointFirstAuthor: boolean) => HTMLButtonElement;
|
|
17
|
+
createNote(text?: string, title?: string): HTMLSpanElement;
|
|
18
|
+
initials: (given: string) => string;
|
|
19
|
+
buildNameLiteral: ({ given, family, suffix }: {
|
|
20
|
+
given?: string | undefined;
|
|
21
|
+
family?: string | undefined;
|
|
22
|
+
suffix?: string | undefined;
|
|
23
|
+
}) => string;
|
|
24
|
+
isJointFirstAuthor: (authors: ContributorNode[], index: number) => boolean;
|
|
25
|
+
createElement: () => void;
|
|
26
|
+
createDOM: () => void;
|
|
27
|
+
createEditButton: () => void;
|
|
28
|
+
createLegend: () => void;
|
|
13
29
|
ignoreMutation: () => boolean;
|
|
14
30
|
stopEvent: () => boolean;
|
|
15
31
|
}
|
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.6.
|
|
4
|
+
"version": "1.6.7-LEAN-3083-3",
|
|
5
5
|
"repository": "github:Atypon-OpenSource/manuscripts-body-editor",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"main": "dist/cjs",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"@manuscripts/library": "1.3.0",
|
|
34
34
|
"@manuscripts/style-guide": "1.5.0",
|
|
35
35
|
"@manuscripts/track-changes-plugin": "^1.7.5",
|
|
36
|
-
"@manuscripts/transform": "2.0.
|
|
36
|
+
"@manuscripts/transform": "2.0.1-LEAN-3083-5",
|
|
37
37
|
"astrocite-eutils": "^0.16.4",
|
|
38
38
|
"axios": "^1.2.2",
|
|
39
39
|
"codemirror": "^5.58.1",
|
|
@@ -40,7 +40,11 @@ Next levels are shifted 'up' by 1
|
|
|
40
40
|
.ProseMirror > div.body {
|
|
41
41
|
counter-reset: level_1;
|
|
42
42
|
}
|
|
43
|
-
.ProseMirror
|
|
43
|
+
.ProseMirror
|
|
44
|
+
> div.body
|
|
45
|
+
> section:not(.toc)
|
|
46
|
+
> .block-section_title
|
|
47
|
+
> h1::before {
|
|
44
48
|
content: counter(level_1, decimal) '. ';
|
|
45
49
|
}
|
|
46
50
|
|
|
@@ -90,13 +94,7 @@ Next levels are shifted 'up' by 1
|
|
|
90
94
|
counter-increment: level_3;
|
|
91
95
|
counter-reset: level_4;
|
|
92
96
|
}
|
|
93
|
-
.ProseMirror
|
|
94
|
-
> div
|
|
95
|
-
> section
|
|
96
|
-
> section
|
|
97
|
-
> section
|
|
98
|
-
> .block-section_title
|
|
99
|
-
> h1 {
|
|
97
|
+
.ProseMirror > div > section > section > section > .block-section_title > h1 {
|
|
100
98
|
font-size: 12pt !important;
|
|
101
99
|
font-style: normal !important;
|
|
102
100
|
font-weight: bold !important;
|
|
@@ -297,17 +295,15 @@ Next levels are shifted 'up' by 1
|
|
|
297
295
|
}
|
|
298
296
|
.ProseMirror div.backmatter::before {
|
|
299
297
|
content: '';
|
|
300
|
-
border-bottom: 1px dashed #
|
|
298
|
+
border-bottom: 1px dashed #c9c9c9;
|
|
301
299
|
display: block;
|
|
302
300
|
margin: 11pt 49pt;
|
|
303
|
-
|
|
304
301
|
}
|
|
305
302
|
.ProseMirror div.backmatter .block-section_title > h1 {
|
|
306
303
|
font-size: 13.5pt !important;
|
|
307
|
-
color: #
|
|
304
|
+
color: #6e6e6e !important;
|
|
308
305
|
}
|
|
309
306
|
|
|
310
|
-
|
|
311
307
|
.ProseMirror p.block {
|
|
312
308
|
font-size: 12pt !important;
|
|
313
309
|
font-style: normal !important;
|
|
@@ -550,12 +546,12 @@ Next levels are shifted 'up' by 1
|
|
|
550
546
|
}
|
|
551
547
|
|
|
552
548
|
.ProseMirror > .keywords > .block-section_title > h1 {
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
549
|
+
color: #353535 !important;
|
|
550
|
+
font-size: 12px !important;
|
|
551
|
+
font-style: italic !important;
|
|
552
|
+
font-weight: 400 !important;
|
|
553
|
+
line-height: 16px !important;
|
|
554
|
+
margin-top: 4px !important;
|
|
559
555
|
}
|
|
560
556
|
|
|
561
557
|
.keywords-list {
|
|
@@ -643,11 +639,6 @@ Next levels are shifted 'up' by 1
|
|
|
643
639
|
align-items: center;
|
|
644
640
|
}
|
|
645
641
|
|
|
646
|
-
.ProseMirror .inserted.accepted,
|
|
647
|
-
.ProseMirror .set_attrs.accepted {
|
|
648
|
-
background: #bffca7;
|
|
649
|
-
text-decoration: none;
|
|
650
|
-
}
|
|
651
642
|
.attrs-popper-button-active,
|
|
652
643
|
.attrs-track-mark:hover .attrs-popper-button {
|
|
653
644
|
display: inline-flex;
|
|
@@ -682,28 +673,66 @@ Next levels are shifted 'up' by 1
|
|
|
682
673
|
right: 0;
|
|
683
674
|
}
|
|
684
675
|
|
|
676
|
+
.ProseMirror span.highlight {
|
|
677
|
+
background-color: var(--highlight-bg-color);
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
.ProseMirror {
|
|
681
|
+
--pending-bg-color: #e6f7fc;
|
|
682
|
+
--accepted-bg-color: #d1edaf;
|
|
683
|
+
--deleted-color: #f35143;
|
|
684
|
+
--highlight-bg-color: #ffeebf;
|
|
685
|
+
--selection-bg-color: #bce7f6;
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
.ProseMirror ::selection {
|
|
689
|
+
background: var(--selection-bg-color);
|
|
690
|
+
}
|
|
691
|
+
|
|
685
692
|
.ProseMirror .inserted.pending {
|
|
686
|
-
background:
|
|
693
|
+
background: var(--pending-bg-color);
|
|
687
694
|
text-decoration: none;
|
|
688
695
|
}
|
|
689
|
-
.ProseMirror .inserted.
|
|
690
|
-
|
|
696
|
+
.ProseMirror .inserted.accepted {
|
|
697
|
+
background: var(--accepted-bg-color);
|
|
691
698
|
text-decoration: none;
|
|
692
699
|
}
|
|
693
700
|
.ProseMirror .inserted.rejected {
|
|
694
701
|
display: none;
|
|
695
702
|
}
|
|
703
|
+
|
|
704
|
+
.ProseMirror .set_attrs.pending {
|
|
705
|
+
background: var(--pending-bg-color);
|
|
706
|
+
text-decoration: none;
|
|
707
|
+
}
|
|
708
|
+
.ProseMirror .set_attrs.accepted {
|
|
709
|
+
background: var(--accepted-bg-color);
|
|
710
|
+
text-decoration: none;
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
.ProseMirror .deleted.pending {
|
|
714
|
+
background: var(--pending-bg-color);
|
|
715
|
+
color: var(--deleted-color);
|
|
716
|
+
text-decoration: line-through;
|
|
717
|
+
}
|
|
696
718
|
.ProseMirror .deleted.accepted {
|
|
697
|
-
background:
|
|
719
|
+
background: var(--accepted-bg-color);
|
|
720
|
+
color: var(--deleted-color);
|
|
721
|
+
text-decoration: line-through;
|
|
698
722
|
}
|
|
699
723
|
.ProseMirror .deleted.rejected {
|
|
700
724
|
text-decoration: none;
|
|
701
725
|
}
|
|
726
|
+
|
|
727
|
+
.affiliation[data-track-status='pending'],
|
|
728
|
+
.contributor[data-track-status='pending'],
|
|
702
729
|
.ProseMirror .inserted.pending,
|
|
703
730
|
.ProseMirror .set_attrs.pending,
|
|
704
731
|
.ProseMirror .deleted.pending {
|
|
705
732
|
background: #ddf3fa;
|
|
706
733
|
}
|
|
734
|
+
.ProseMirror .affiliation[data-track-status='rejected'][data-track-op='insert'],
|
|
735
|
+
.ProseMirror .contributor[data-track-status='rejected'][data-track-op='insert'],
|
|
707
736
|
.ProseMirror figure[data-track-status='rejected'][data-track-op='insert'],
|
|
708
737
|
.ProseMirror table[data-track-status='rejected'][data-track-op='insert'],
|
|
709
738
|
.ProseMirror
|
|
@@ -711,6 +740,12 @@ Next levels are shifted 'up' by 1
|
|
|
711
740
|
display: none;
|
|
712
741
|
}
|
|
713
742
|
|
|
743
|
+
.affiliation[data-track-status='pending'][data-track-op='delete'],
|
|
744
|
+
.contributor[data-track-status='pending'][data-track-op='delete'] {
|
|
745
|
+
text-decoration: line-through;
|
|
746
|
+
background: #e6f7fc;
|
|
747
|
+
}
|
|
748
|
+
|
|
714
749
|
.citation-wrapper {
|
|
715
750
|
position: relative;
|
|
716
751
|
}
|
|
@@ -732,24 +767,79 @@ Next levels are shifted 'up' by 1
|
|
|
732
767
|
|
|
733
768
|
.contributors {
|
|
734
769
|
white-space: initial;
|
|
735
|
-
margin-bottom: 24px;
|
|
736
770
|
margin-top: 24px;
|
|
771
|
+
align-items: center;
|
|
772
|
+
display: flex;
|
|
773
|
+
}
|
|
774
|
+
.contributors-list {
|
|
775
|
+
flex: 1 0 auto;
|
|
737
776
|
}
|
|
738
777
|
|
|
739
778
|
.contributors .tools-panel {
|
|
740
779
|
position: initial;
|
|
741
780
|
}
|
|
742
781
|
|
|
743
|
-
.
|
|
744
|
-
|
|
745
|
-
|
|
782
|
+
.contributor {
|
|
783
|
+
display: inline-flex;
|
|
784
|
+
background: transparent;
|
|
785
|
+
border: 0;
|
|
786
|
+
font-size: 1rem;
|
|
787
|
+
text-decoration: none;
|
|
788
|
+
color: inherit;
|
|
789
|
+
outline: none;
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
.contributor:not(:disabled):hover {
|
|
793
|
+
text-decoration: underline;
|
|
794
|
+
cursor: pointer !important;
|
|
795
|
+
}
|
|
796
|
+
.contributor:not(:disabled):focus {
|
|
797
|
+
text-decoration: underline;
|
|
798
|
+
cursor: pointer !important;
|
|
799
|
+
}
|
|
800
|
+
.contributor::after {
|
|
801
|
+
content: ', ';
|
|
802
|
+
}
|
|
803
|
+
.contributor:last-child::after {
|
|
804
|
+
content: '';
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
.block-affiliations {
|
|
808
|
+
margin-top: 16px;
|
|
809
|
+
color: #6e6e6e;
|
|
810
|
+
margin-bottom: 24px;
|
|
811
|
+
}
|
|
812
|
+
.affiliation {
|
|
813
|
+
line-height: 1.2;
|
|
814
|
+
}
|
|
815
|
+
.block-affiliations .block {
|
|
816
|
+
display: flex;
|
|
817
|
+
width: 100%;
|
|
818
|
+
flex-direction: column;
|
|
819
|
+
align-items: flex-start;
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
.contributors-legend {
|
|
823
|
+
margin: 16px 0 0 0;
|
|
746
824
|
}
|
|
747
825
|
|
|
748
|
-
.
|
|
749
|
-
|
|
750
|
-
|
|
826
|
+
.contributor-legend .symbol {
|
|
827
|
+
display: inline-block;
|
|
828
|
+
font-size: 0.75em;
|
|
829
|
+
line-height: 1;
|
|
830
|
+
vertical-align: top;
|
|
751
831
|
}
|
|
752
832
|
|
|
753
|
-
.contributors
|
|
754
|
-
|
|
833
|
+
.contributors .tools-panel {
|
|
834
|
+
align-items: center;
|
|
835
|
+
display: flex;
|
|
836
|
+
margin-left: 8px;
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
.contributor-note {
|
|
840
|
+
display: inline-block;
|
|
841
|
+
font-size: 0.75em;
|
|
842
|
+
margin: 0 1px;
|
|
843
|
+
line-height: 1;
|
|
844
|
+
vertical-align: top;
|
|
755
845
|
}
|
package/styles/Editor.css
CHANGED
|
@@ -731,7 +731,6 @@
|
|
|
731
731
|
text-align: center;
|
|
732
732
|
}
|
|
733
733
|
|
|
734
|
-
|
|
735
734
|
.ProseMirror .bib-item {
|
|
736
735
|
position: relative;
|
|
737
736
|
margin-right: 40px;
|
|
@@ -956,7 +955,7 @@
|
|
|
956
955
|
}
|
|
957
956
|
.article-titles {
|
|
958
957
|
cursor: text;
|
|
959
|
-
font-family:
|
|
958
|
+
font-family: 'PT Serif', serif;
|
|
960
959
|
font-size: 28px;
|
|
961
960
|
font-weight: 700;
|
|
962
961
|
line-height: 1.43;
|