@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.
@@ -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 base_node_view_1 = require("./base_node_view");
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 base_node_view_1.BaseNodeView {
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('contributors');
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 { components: { AuthorsInlineViewContainer }, subscribeStore, } = this.props;
21
- this.metadata = (0, ReactSubView_1.default)(this.props, AuthorsInlineViewContainer, {
22
- showAuthorEditButton: true,
23
- disableEditButton: !can.editMetadata,
24
- subscribe: subscribeStore,
25
- }, this.node, this.getPos, this.view, 'metadata-container');
26
- if (this.metadata) {
27
- this.dom.appendChild(this.metadata);
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 { BaseNodeView } from './base_node_view';
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 BaseNodeView {
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('contributors');
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 { components: { AuthorsInlineViewContainer }, subscribeStore, } = this.props;
15
- this.metadata = ReactSubView(this.props, AuthorsInlineViewContainer, {
16
- showAuthorEditButton: true,
17
- disableEditButton: !can.editMetadata,
18
- subscribe: subscribeStore,
19
- }, this.node, this.getPos, this.view, 'metadata-container');
20
- if (this.metadata) {
21
- this.dom.appendChild(this.metadata);
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;
@@ -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 { ManuscriptNodeView } from '@manuscripts/transform';
2
- import React from 'react';
3
- import { BaseNodeView } from './base_node_view';
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
- components: Record<string, React.ComponentType<unknown>>;
7
- subscribeStore: unknown;
6
+ getCapabilities: () => Capabilities;
7
+ openAuthorEditing: () => void;
8
+ selectAuthorForEditing: (authorId: string) => void;
8
9
  }
9
- export declare class ContributorsView<PropsType extends ContributorsProps> extends BaseNodeView<PropsType> implements ManuscriptNodeView {
10
- private metadata;
10
+ export declare class ContributorsView<PropsType extends ContributorsProps> extends BlockView<PropsType> {
11
11
  initialise: () => void;
12
- protected createDOM: () => void;
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.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.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 > div.body > section:not(.toc) > .block-section_title > h1::before {
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 #C9C9C9;
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: #6E6E6E !important;
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
- color: #353535 !important;
554
- font-size: 12px !important;
555
- font-style: italic !important;
556
- font-weight: 400 !important;
557
- line-height: 16px !important;
558
- margin-top: 4px !important;
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: #ddf3fa;
693
+ background: var(--pending-bg-color);
687
694
  text-decoration: none;
688
695
  }
689
- .ProseMirror .inserted.pending,
690
- .ProseMirror .set_attrs.pending {
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: #bffca7;
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
- .contributors table {
744
- line-height: initial;
745
- width: inherit;
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
- .contributors tr th, .contributors tr td {
749
- border: none !important;
750
- background: none !important;
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 th, .contributors td {
754
- padding: initial;
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: "PT Serif", serif;
958
+ font-family: 'PT Serif', serif;
960
959
  font-size: 28px;
961
960
  font-weight: 700;
962
961
  line-height: 1.43;