@manuscripts/body-editor 3.6.10 → 3.6.12
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/commands.js +12 -9
- package/dist/cjs/components/LanguageDropdown/index.js +3 -18
- package/dist/cjs/components/LanguageDropdown/languages.js +16 -112
- package/dist/cjs/components/outline/DraggableTree.js +1 -0
- package/dist/cjs/configs/editor-views.js +4 -1
- package/dist/cjs/lib/doc.js +7 -5
- package/dist/cjs/plugins/placeholder.js +3 -0
- package/dist/cjs/versions.js +1 -1
- package/dist/cjs/views/abstracts.js +0 -36
- package/dist/cjs/views/editable_block.js +1 -0
- package/dist/cjs/views/section.js +83 -0
- package/dist/cjs/views/section_title.js +1 -0
- package/dist/cjs/views/supplement.js +175 -0
- package/dist/cjs/views/supplement_editable.js +20 -0
- package/dist/cjs/views/supplements.js +56 -0
- package/dist/cjs/views/supplements_editable.js +21 -0
- package/dist/cjs/views/translated_abstract.js +7 -5
- package/dist/es/commands.js +13 -10
- package/dist/es/components/LanguageDropdown/index.js +4 -19
- package/dist/es/components/LanguageDropdown/languages.js +15 -72
- package/dist/es/components/outline/DraggableTree.js +1 -0
- package/dist/es/configs/editor-views.js +4 -1
- package/dist/es/lib/doc.js +5 -3
- package/dist/es/plugins/placeholder.js +3 -0
- package/dist/es/versions.js +1 -1
- package/dist/es/views/abstracts.js +0 -36
- package/dist/es/views/editable_block.js +1 -0
- package/dist/es/views/section.js +83 -0
- package/dist/es/views/section_title.js +1 -0
- package/dist/es/views/supplement.js +171 -0
- package/dist/es/views/supplement_editable.js +18 -0
- package/dist/es/views/supplements.js +49 -0
- package/dist/es/views/supplements_editable.js +19 -0
- package/dist/es/views/translated_abstract.js +8 -6
- package/dist/types/commands.d.ts +1 -1
- package/dist/types/components/LanguageDropdown/index.d.ts +2 -0
- package/dist/types/components/LanguageDropdown/languages.d.ts +21 -12
- package/dist/types/configs/ManuscriptsEditor.d.ts +2 -0
- package/dist/types/lib/doc.d.ts +2 -2
- package/dist/types/versions.d.ts +1 -1
- package/dist/types/views/abstracts.d.ts +0 -2
- package/dist/types/views/section.d.ts +7 -0
- package/dist/types/views/supplement.d.ts +37 -0
- package/dist/types/views/supplement_editable.d.ts +18 -0
- package/dist/types/views/supplements.d.ts +27 -0
- package/dist/types/views/supplements_editable.d.ts +44 -0
- package/dist/types/views/translated_abstract.d.ts +1 -1
- package/package.json +2 -3
- package/styles/AdvancedEditor.css +32 -4
- package/styles/Editor.css +159 -0
package/dist/cjs/commands.js
CHANGED
|
@@ -297,18 +297,21 @@ const insertTable = (config, state, dispatch) => {
|
|
|
297
297
|
return true;
|
|
298
298
|
};
|
|
299
299
|
exports.insertTable = insertTable;
|
|
300
|
-
const insertSupplement = (file,
|
|
300
|
+
const insertSupplement = (file, view) => {
|
|
301
301
|
const supplement = transform_1.schema.nodes.supplement.createAndFill({
|
|
302
302
|
id: (0, transform_1.generateNodeID)(transform_1.schema.nodes.supplement),
|
|
303
303
|
href: file.id,
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
}
|
|
304
|
+
}, [
|
|
305
|
+
transform_1.schema.nodes.figcaption.create({}, [
|
|
306
|
+
transform_1.schema.nodes.caption_title.create(),
|
|
307
|
+
transform_1.schema.nodes.caption.create(),
|
|
308
|
+
]),
|
|
309
|
+
]);
|
|
310
|
+
const tr = view.state.tr;
|
|
311
|
+
const { pos } = (0, doc_1.upsertSupplementsSection)(tr, supplement);
|
|
312
|
+
tr.setSelection(prosemirror_state_1.NodeSelection.create(tr.doc, pos));
|
|
313
|
+
view.focus();
|
|
314
|
+
view.dispatch(tr.scrollIntoView());
|
|
312
315
|
return true;
|
|
313
316
|
};
|
|
314
317
|
exports.insertSupplement = insertSupplement;
|
|
@@ -60,24 +60,9 @@ const LanguageOptionItem = ({ language, isSelected, onSelect }) => (react_1.defa
|
|
|
60
60
|
language.nativeName && ` (${language.nativeName})`,
|
|
61
61
|
isSelected && (react_1.default.createElement(TickIconWrapper, null,
|
|
62
62
|
react_1.default.createElement(style_guide_1.TickIcon, null)))));
|
|
63
|
-
const LanguageDropdown = ({ onLanguageSelect, onClose, currentLanguage = 'en', showButton = false, selectedLanguageDisplay, onCloseParent, }) => {
|
|
64
|
-
const [allLanguages, setAllLanguages] = (0, react_1.useState)([]);
|
|
63
|
+
const LanguageDropdown = ({ onLanguageSelect, onClose, currentLanguage = 'en', showButton = false, selectedLanguageDisplay, onCloseParent, languages, }) => {
|
|
65
64
|
const [isOpen, setIsOpen] = (0, react_1.useState)(!showButton);
|
|
66
65
|
const dropdownRef = (0, react_1.useRef)(null);
|
|
67
|
-
(0, react_1.useEffect)(() => {
|
|
68
|
-
const loadLanguages = async () => {
|
|
69
|
-
try {
|
|
70
|
-
const languages = await (0, languages_1.loadAllLanguages)();
|
|
71
|
-
const sortedLanguages = (0, languages_1.sortLanguagesByCommonality)(languages);
|
|
72
|
-
setAllLanguages(sortedLanguages);
|
|
73
|
-
}
|
|
74
|
-
catch (error) {
|
|
75
|
-
console.error('Failed to load language data:', error);
|
|
76
|
-
setAllLanguages([]);
|
|
77
|
-
}
|
|
78
|
-
};
|
|
79
|
-
loadLanguages();
|
|
80
|
-
}, []);
|
|
81
66
|
(0, react_1.useEffect)(() => {
|
|
82
67
|
const handleClickOutside = (event) => {
|
|
83
68
|
if (dropdownRef.current &&
|
|
@@ -103,7 +88,7 @@ const LanguageDropdown = ({ onLanguageSelect, onClose, currentLanguage = 'en', s
|
|
|
103
88
|
onLanguageSelect(languageCode);
|
|
104
89
|
};
|
|
105
90
|
const getDisplayName = (languageCode) => {
|
|
106
|
-
return (0, languages_1.getSelectedLanguageName)(languageCode,
|
|
91
|
+
return (0, languages_1.getSelectedLanguageName)(languageCode, languages);
|
|
107
92
|
};
|
|
108
93
|
return (react_1.default.createElement(style_guide_1.DropdownContainer, { ref: dropdownRef },
|
|
109
94
|
showButton && (react_1.default.createElement(LanguageButton, { onClick: toggleDropdown },
|
|
@@ -114,7 +99,7 @@ const LanguageDropdown = ({ onLanguageSelect, onClose, currentLanguage = 'en', s
|
|
|
114
99
|
react_1.default.createElement(SelectedLanguage, null, selectedLanguageDisplay || getDisplayName(currentLanguage))))),
|
|
115
100
|
isOpen && (react_1.default.createElement(DropdownMenu, { direction: "right", width: 231, height: 400, top: 18 },
|
|
116
101
|
!showButton && react_1.default.createElement(DropdownTitle, null, "Choose language"),
|
|
117
|
-
|
|
102
|
+
languages.map((language) => (react_1.default.createElement(LanguageOptionItem, { key: language.code, language: language, isSelected: currentLanguage === language.code, onSelect: handleSelect })))))));
|
|
118
103
|
};
|
|
119
104
|
const StyledDropdownList = (0, styled_components_1.default)(style_guide_1.DropdownList) `
|
|
120
105
|
overflow-y: auto;
|
|
@@ -1,98 +1,26 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
-
};
|
|
2
|
+
/*!
|
|
3
|
+
* © 2025 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
|
+
*/
|
|
38
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.
|
|
40
|
-
const i18n_iso_languages_1 = __importDefault(require("@cospired/i18n-iso-languages"));
|
|
41
|
-
exports.COMMON_LANGUAGES_INFO = {
|
|
42
|
-
en: { englishName: 'English', nativeName: 'Default' },
|
|
43
|
-
es: { englishName: 'Spanish', nativeName: 'Español' },
|
|
44
|
-
fr: { englishName: 'French', nativeName: 'Français' },
|
|
45
|
-
de: { englishName: 'German', nativeName: 'Deutsch' },
|
|
46
|
-
it: { englishName: 'Italian', nativeName: 'Italiano' },
|
|
47
|
-
pt: { englishName: 'Portuguese', nativeName: 'Português' },
|
|
48
|
-
ru: { englishName: 'Russian', nativeName: 'Русский' },
|
|
49
|
-
ja: { englishName: 'Japanese', nativeName: '日本語' },
|
|
50
|
-
ko: { englishName: 'Korean', nativeName: '한국어' },
|
|
51
|
-
zh: { englishName: 'Chinese', nativeName: '中文' },
|
|
52
|
-
ar: { englishName: 'Arabic', nativeName: 'العربية' },
|
|
53
|
-
};
|
|
54
|
-
exports.COMMON_LANGUAGES = Object.keys(exports.COMMON_LANGUAGES_INFO);
|
|
18
|
+
exports.getLanguageDisplayName = exports.getSelectedLanguageName = exports.ENGLISH_FALLBACK = void 0;
|
|
55
19
|
exports.ENGLISH_FALLBACK = {
|
|
56
20
|
code: 'en',
|
|
57
21
|
name: 'English',
|
|
58
22
|
nativeName: 'English',
|
|
59
|
-
isCommon: true,
|
|
60
|
-
};
|
|
61
|
-
const initializeLanguageData = async () => {
|
|
62
|
-
try {
|
|
63
|
-
const englishLanguageData = await Promise.resolve().then(() => __importStar(require('@cospired/i18n-iso-languages/langs/en.json')));
|
|
64
|
-
i18n_iso_languages_1.default.registerLocale(englishLanguageData.default);
|
|
65
|
-
}
|
|
66
|
-
catch (error) {
|
|
67
|
-
console.error('Failed to initialize language data:', error);
|
|
68
|
-
throw error;
|
|
69
|
-
}
|
|
70
23
|
};
|
|
71
|
-
exports.initializeLanguageData = initializeLanguageData;
|
|
72
|
-
const loadAllLanguages = async () => {
|
|
73
|
-
try {
|
|
74
|
-
await (0, exports.initializeLanguageData)();
|
|
75
|
-
const languageCodes = i18n_iso_languages_1.default.getAlpha2Codes();
|
|
76
|
-
return Object.keys(languageCodes).map((code) => {
|
|
77
|
-
const commonLanguageInfo = exports.COMMON_LANGUAGES_INFO[code];
|
|
78
|
-
return {
|
|
79
|
-
code,
|
|
80
|
-
name: commonLanguageInfo?.englishName ||
|
|
81
|
-
i18n_iso_languages_1.default.getName(code, 'en') ||
|
|
82
|
-
code.toUpperCase(),
|
|
83
|
-
nativeName: commonLanguageInfo?.nativeName ||
|
|
84
|
-
i18n_iso_languages_1.default.getName(code, code) ||
|
|
85
|
-
undefined,
|
|
86
|
-
isCommon: exports.COMMON_LANGUAGES.includes(code),
|
|
87
|
-
};
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
catch (error) {
|
|
91
|
-
console.error('Failed to load languages:', error);
|
|
92
|
-
return [exports.ENGLISH_FALLBACK];
|
|
93
|
-
}
|
|
94
|
-
};
|
|
95
|
-
exports.loadAllLanguages = loadAllLanguages;
|
|
96
24
|
const getSelectedLanguageName = (selectedLanguage, allLanguages) => {
|
|
97
25
|
if (!allLanguages.length) {
|
|
98
26
|
return 'English (Default)';
|
|
@@ -105,30 +33,6 @@ const getSelectedLanguageName = (selectedLanguage, allLanguages) => {
|
|
|
105
33
|
};
|
|
106
34
|
exports.getSelectedLanguageName = getSelectedLanguageName;
|
|
107
35
|
const getLanguageDisplayName = (languageCode) => {
|
|
108
|
-
const languageInfo = exports.COMMON_LANGUAGES_INFO[languageCode];
|
|
109
|
-
if (languageInfo) {
|
|
110
|
-
const { englishName, nativeName } = languageInfo;
|
|
111
|
-
if (nativeName !== englishName && nativeName !== 'Default') {
|
|
112
|
-
return `${englishName} (${nativeName})`;
|
|
113
|
-
}
|
|
114
|
-
return englishName;
|
|
115
|
-
}
|
|
116
|
-
const englishName = i18n_iso_languages_1.default.getName(languageCode, 'en');
|
|
117
|
-
if (englishName) {
|
|
118
|
-
return englishName;
|
|
119
|
-
}
|
|
120
36
|
return languageCode.toUpperCase();
|
|
121
37
|
};
|
|
122
38
|
exports.getLanguageDisplayName = getLanguageDisplayName;
|
|
123
|
-
const sortLanguagesByCommonality = (languages) => {
|
|
124
|
-
return [...languages].sort((a, b) => {
|
|
125
|
-
if (a.isCommon && !b.isCommon) {
|
|
126
|
-
return -1;
|
|
127
|
-
}
|
|
128
|
-
if (!a.isCommon && b.isCommon) {
|
|
129
|
-
return 1;
|
|
130
|
-
}
|
|
131
|
-
return a.name.localeCompare(b.name);
|
|
132
|
-
});
|
|
133
|
-
};
|
|
134
|
-
exports.sortLanguagesByCommonality = sortLanguagesByCommonality;
|
|
@@ -63,6 +63,7 @@ const excludedTypes = [
|
|
|
63
63
|
transform_1.schema.nodes.trans_abstract,
|
|
64
64
|
transform_1.schema.nodes.subtitles,
|
|
65
65
|
transform_1.schema.nodes.subtitle,
|
|
66
|
+
transform_1.schema.nodes.supplements,
|
|
66
67
|
];
|
|
67
68
|
const childrenExcludedTypes = [
|
|
68
69
|
transform_1.schema.nodes.pullquote_element,
|
|
@@ -47,6 +47,8 @@ const section_label_1 = __importDefault(require("../views/section_label"));
|
|
|
47
47
|
const section_title_editable_1 = __importDefault(require("../views/section_title_editable"));
|
|
48
48
|
const subtitle_editable_1 = __importDefault(require("../views/subtitle_editable"));
|
|
49
49
|
const subtitles_editable_1 = __importDefault(require("../views/subtitles_editable"));
|
|
50
|
+
const supplement_editable_1 = __importDefault(require("../views/supplement_editable"));
|
|
51
|
+
const supplements_editable_1 = __importDefault(require("../views/supplements_editable"));
|
|
50
52
|
const table_cell_1 = __importDefault(require("../views/table_cell"));
|
|
51
53
|
const table_element_editable_1 = __importDefault(require("../views/table_element_editable"));
|
|
52
54
|
const table_element_footer_1 = __importDefault(require("../views/table_element_footer"));
|
|
@@ -96,7 +98,8 @@ exports.default = (props, dispatch) => {
|
|
|
96
98
|
table_header: (0, table_cell_1.default)(props),
|
|
97
99
|
table_element_footer: (0, table_element_footer_1.default)(props),
|
|
98
100
|
comments: (0, empty_1.default)('comments'),
|
|
99
|
-
supplements: (0,
|
|
101
|
+
supplements: (0, supplements_editable_1.default)(props, dispatch),
|
|
102
|
+
supplement: (0, supplement_editable_1.default)(props, dispatch),
|
|
100
103
|
author_notes: (0, author_notes_1.default)(props, dispatch),
|
|
101
104
|
awards: (0, awards_1.default)(props, dispatch),
|
|
102
105
|
award: (0, award_1.default)(props, dispatch),
|
package/dist/cjs/lib/doc.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.findNodeByID = exports.findGraphicalAbstractFigureElement = exports.findFootnotesSection = exports.findBibliographySection = exports.findBackmatter = exports.findBody = exports.findAbstractsNode = exports.insertFootnotesSection = exports.insertAttachmentsNode = exports.
|
|
3
|
+
exports.findNodeByID = exports.findGraphicalAbstractFigureElement = exports.findFootnotesSection = exports.findBibliographySection = exports.findBackmatter = exports.findBody = exports.findAbstractsNode = exports.insertFootnotesSection = exports.insertAttachmentsNode = exports.upsertSupplementsSection = exports.insertAwardsNode = void 0;
|
|
4
4
|
const transform_1 = require("@manuscripts/transform");
|
|
5
5
|
const prosemirror_utils_1 = require("prosemirror-utils");
|
|
6
6
|
const utils_1 = require("./utils");
|
|
@@ -19,21 +19,23 @@ const insertAwardsNode = (tr) => {
|
|
|
19
19
|
};
|
|
20
20
|
};
|
|
21
21
|
exports.insertAwardsNode = insertAwardsNode;
|
|
22
|
-
const
|
|
22
|
+
const upsertSupplementsSection = (tr, supplement) => {
|
|
23
23
|
const doc = tr.doc;
|
|
24
24
|
const supplements = (0, prosemirror_utils_1.findChildrenByType)(doc, transform_1.schema.nodes.supplements)[0];
|
|
25
25
|
if (supplements) {
|
|
26
|
-
|
|
26
|
+
const pos = supplements.pos + supplements.node.nodeSize - 1;
|
|
27
|
+
tr.insert(pos, supplement);
|
|
28
|
+
return { node: supplements.node, pos };
|
|
27
29
|
}
|
|
28
30
|
const pos = (0, utils_1.findInsertionPosition)(transform_1.schema.nodes.supplements, doc);
|
|
29
|
-
const node = transform_1.schema.nodes.supplements.createAndFill();
|
|
31
|
+
const node = transform_1.schema.nodes.supplements.createAndFill({ id: (0, transform_1.generateNodeID)(transform_1.schema.nodes.supplements) }, [supplement]);
|
|
30
32
|
tr.insert(pos, node);
|
|
31
33
|
return {
|
|
32
34
|
node,
|
|
33
35
|
pos,
|
|
34
36
|
};
|
|
35
37
|
};
|
|
36
|
-
exports.
|
|
38
|
+
exports.upsertSupplementsSection = upsertSupplementsSection;
|
|
37
39
|
const insertAttachmentsNode = (tr) => {
|
|
38
40
|
const attachmentsNodes = (0, prosemirror_utils_1.findChildrenByType)(tr.doc, transform_1.schema.nodes.attachments);
|
|
39
41
|
if (attachmentsNodes.length) {
|
|
@@ -84,6 +84,9 @@ exports.default = () => new prosemirror_state_1.Plugin({
|
|
|
84
84
|
if ((0, prosemirror_utils_1.findParentNodeOfTypeClosestToPos)($pos, transform_1.schema.nodes.box_element)) {
|
|
85
85
|
placeholderText = 'Optional box title...';
|
|
86
86
|
}
|
|
87
|
+
if ((0, prosemirror_utils_1.findParentNodeOfTypeClosestToPos)($pos, transform_1.schema.nodes.supplements)) {
|
|
88
|
+
placeholderText = 'Supplements';
|
|
89
|
+
}
|
|
87
90
|
decorations.push(prosemirror_view_1.Decoration.widget(pos + 1, placeholderWidget(placeholderText)));
|
|
88
91
|
}
|
|
89
92
|
else if (node.type === node.type.schema.nodes.trans_abstract) {
|
package/dist/cjs/versions.js
CHANGED
|
@@ -16,29 +16,12 @@
|
|
|
16
16
|
*/
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
18
|
exports.AbstractsView = void 0;
|
|
19
|
-
const prosemirror_state_1 = require("prosemirror-state");
|
|
20
|
-
const icons_1 = require("../icons");
|
|
21
19
|
const base_node_view_1 = require("./base_node_view");
|
|
22
20
|
const creators_1 = require("./creators");
|
|
23
21
|
class AbstractsView extends base_node_view_1.BaseNodeView {
|
|
24
22
|
constructor() {
|
|
25
23
|
super(...arguments);
|
|
26
24
|
this.elementType = 'div';
|
|
27
|
-
this.addTranslation = () => {
|
|
28
|
-
const { state } = this.view;
|
|
29
|
-
const { schema } = state;
|
|
30
|
-
const documentLanguage = state.doc.attrs.primaryLanguageCode || 'en';
|
|
31
|
-
const sectionTitle = schema.nodes.section_title.create();
|
|
32
|
-
const paragraph = schema.nodes.paragraph.create();
|
|
33
|
-
const transAbstractNode = schema.nodes.trans_abstract.create({
|
|
34
|
-
lang: documentLanguage,
|
|
35
|
-
}, [sectionTitle, paragraph]);
|
|
36
|
-
const tr = state.tr.insert(this.getPos() + this.node.nodeSize - 1, transAbstractNode);
|
|
37
|
-
const titlePos = this.getPos() + this.node.nodeSize;
|
|
38
|
-
const selection = prosemirror_state_1.TextSelection.create(tr.doc, titlePos);
|
|
39
|
-
tr.setSelection(selection).scrollIntoView();
|
|
40
|
-
this.view.dispatch(tr);
|
|
41
|
-
};
|
|
42
25
|
}
|
|
43
26
|
initialise() {
|
|
44
27
|
this.createDOM();
|
|
@@ -52,25 +35,6 @@ class AbstractsView extends base_node_view_1.BaseNodeView {
|
|
|
52
35
|
createElement() {
|
|
53
36
|
this.contentDOM = document.createElement(this.elementType);
|
|
54
37
|
this.dom.appendChild(this.contentDOM);
|
|
55
|
-
this.addTranslationBtn();
|
|
56
|
-
}
|
|
57
|
-
addTranslationBtn() {
|
|
58
|
-
if (this.props.getCapabilities()?.editArticle) {
|
|
59
|
-
const btnContainer = document.createElement('div');
|
|
60
|
-
btnContainer.classList.add('add-translation-container');
|
|
61
|
-
btnContainer.addEventListener('click', () => this.addTranslation());
|
|
62
|
-
const addTranslationBtn = Object.assign(document.createElement('button'), {
|
|
63
|
-
className: 'add-button',
|
|
64
|
-
innerHTML: icons_1.addBtnIcon,
|
|
65
|
-
title: 'Add Translation',
|
|
66
|
-
});
|
|
67
|
-
const textElement = document.createElement('span');
|
|
68
|
-
textElement.textContent = 'Add translation';
|
|
69
|
-
textElement.classList.add('add-translation-text');
|
|
70
|
-
btnContainer.appendChild(addTranslationBtn);
|
|
71
|
-
btnContainer.appendChild(textElement);
|
|
72
|
-
this.dom.prepend(btnContainer);
|
|
73
|
-
}
|
|
74
38
|
}
|
|
75
39
|
updateContents() {
|
|
76
40
|
super.updateContents();
|
|
@@ -42,6 +42,7 @@ const EditableBlock = (Base) => {
|
|
|
42
42
|
const nodeType = this.node.type;
|
|
43
43
|
if (nodeType === transform_1.schema.nodes.hero_image ||
|
|
44
44
|
nodeType === transform_1.schema.nodes.subtitles ||
|
|
45
|
+
nodeType === transform_1.schema.nodes.supplements ||
|
|
45
46
|
(0, utils_1.hasParent)($pos, [
|
|
46
47
|
transform_1.schema.nodes.keywords,
|
|
47
48
|
transform_1.schema.nodes.bibliography_section,
|
|
@@ -19,6 +19,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
19
19
|
};
|
|
20
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
21
|
exports.SectionView = void 0;
|
|
22
|
+
const transform_1 = require("@manuscripts/transform");
|
|
23
|
+
const prosemirror_state_1 = require("prosemirror-state");
|
|
24
|
+
const prosemirror_utils_1 = require("prosemirror-utils");
|
|
25
|
+
const icons_1 = require("../icons");
|
|
22
26
|
const section_title_1 = require("../plugins/section_title");
|
|
23
27
|
const block_view_1 = __importDefault(require("./block_view"));
|
|
24
28
|
const creators_1 = require("./creators");
|
|
@@ -26,6 +30,26 @@ class SectionView extends block_view_1.default {
|
|
|
26
30
|
constructor() {
|
|
27
31
|
super(...arguments);
|
|
28
32
|
this.elementType = 'section';
|
|
33
|
+
this.addTranslationButton = null;
|
|
34
|
+
this.addTranslation = () => {
|
|
35
|
+
const { state } = this.view;
|
|
36
|
+
const { schema } = state;
|
|
37
|
+
const documentLanguage = state.doc.attrs.primaryLanguageCode || 'en';
|
|
38
|
+
const sectionTitle = schema.nodes.section_title.create();
|
|
39
|
+
const paragraph = schema.nodes.paragraph.create();
|
|
40
|
+
const transAbstractNode = schema.nodes.trans_abstract.create({
|
|
41
|
+
lang: documentLanguage,
|
|
42
|
+
category: this.node.attrs.category,
|
|
43
|
+
}, [sectionTitle, paragraph]);
|
|
44
|
+
const abstracts = (0, prosemirror_utils_1.findParentNodeOfTypeClosestToPos)(this.view.state.doc.resolve(this.getPos()), schema.nodes.abstracts);
|
|
45
|
+
if (abstracts) {
|
|
46
|
+
const tr = state.tr.insert(abstracts.pos + abstracts.node.nodeSize - 1, transAbstractNode);
|
|
47
|
+
const titlePos = abstracts.pos + abstracts.node.nodeSize;
|
|
48
|
+
const selection = prosemirror_state_1.TextSelection.create(tr.doc, titlePos);
|
|
49
|
+
tr.setSelection(selection).scrollIntoView();
|
|
50
|
+
this.view.dispatch(tr);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
29
53
|
}
|
|
30
54
|
initialise() {
|
|
31
55
|
this.createDOM();
|
|
@@ -40,6 +64,7 @@ class SectionView extends block_view_1.default {
|
|
|
40
64
|
super.updateContents();
|
|
41
65
|
this.dom.setAttribute('data-category', this.node.attrs.category);
|
|
42
66
|
this.handleSectionNumbering();
|
|
67
|
+
this.handleAddTranslationButton();
|
|
43
68
|
}
|
|
44
69
|
handleSectionNumbering() {
|
|
45
70
|
const sections = section_title_1.sectionTitleKey.getState(this.view.state);
|
|
@@ -54,6 +79,64 @@ class SectionView extends block_view_1.default {
|
|
|
54
79
|
}
|
|
55
80
|
});
|
|
56
81
|
}
|
|
82
|
+
handleAddTranslationButton() {
|
|
83
|
+
this.cleanupAddTranslationButton();
|
|
84
|
+
const $pos = this.view.state.doc.resolve(this.getPos());
|
|
85
|
+
const isInAbstracts = (0, prosemirror_utils_1.findParentNodeOfTypeClosestToPos)($pos, transform_1.schema.nodes.abstracts);
|
|
86
|
+
const isAbstractCategory = this.isAbstractCategory(this.node.attrs.category);
|
|
87
|
+
if (isInAbstracts &&
|
|
88
|
+
isAbstractCategory &&
|
|
89
|
+
this.props.getCapabilities()?.editArticle) {
|
|
90
|
+
this.createAddTranslationButton();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
isAbstractCategory(category) {
|
|
94
|
+
const sectionCategories = this.props.sectionCategories;
|
|
95
|
+
if (!sectionCategories) {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
const categoryObj = sectionCategories.get(category);
|
|
99
|
+
if (!categoryObj) {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
return (categoryObj.group === 'abstracts' ||
|
|
103
|
+
categoryObj.group === 'abstracts-graphic');
|
|
104
|
+
}
|
|
105
|
+
createAddTranslationButton() {
|
|
106
|
+
const btnContainer = document.createElement('div');
|
|
107
|
+
btnContainer.classList.add('add-translation-container');
|
|
108
|
+
btnContainer.addEventListener('mousedown', (event) => {
|
|
109
|
+
event.preventDefault();
|
|
110
|
+
event.stopPropagation();
|
|
111
|
+
this.addTranslation();
|
|
112
|
+
});
|
|
113
|
+
const addTranslationBtn = Object.assign(document.createElement('button'), {
|
|
114
|
+
className: 'add-button',
|
|
115
|
+
innerHTML: icons_1.addBtnIcon,
|
|
116
|
+
title: 'Add Translation',
|
|
117
|
+
type: 'button',
|
|
118
|
+
});
|
|
119
|
+
const textElement = document.createElement('span');
|
|
120
|
+
textElement.textContent = 'Add translation';
|
|
121
|
+
textElement.classList.add('add-translation-text');
|
|
122
|
+
btnContainer.appendChild(addTranslationBtn);
|
|
123
|
+
btnContainer.appendChild(textElement);
|
|
124
|
+
this.dom.appendChild(btnContainer);
|
|
125
|
+
this.addTranslationButton = addTranslationBtn;
|
|
126
|
+
}
|
|
127
|
+
cleanupAddTranslationButton() {
|
|
128
|
+
if (this.addTranslationButton) {
|
|
129
|
+
const container = this.addTranslationButton.closest('.add-translation-container');
|
|
130
|
+
if (container) {
|
|
131
|
+
container.remove();
|
|
132
|
+
}
|
|
133
|
+
this.addTranslationButton = null;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
destroy() {
|
|
137
|
+
this.cleanupAddTranslationButton();
|
|
138
|
+
super.destroy();
|
|
139
|
+
}
|
|
57
140
|
}
|
|
58
141
|
exports.SectionView = SectionView;
|
|
59
142
|
exports.default = (0, creators_1.createNodeView)(SectionView);
|
|
@@ -32,6 +32,7 @@ class SectionTitleView extends block_view_1.default {
|
|
|
32
32
|
transform_1.schema.nodes.bibliography_section,
|
|
33
33
|
transform_1.schema.nodes.footnotes_section,
|
|
34
34
|
transform_1.schema.nodes.graphical_abstract_section,
|
|
35
|
+
transform_1.schema.nodes.supplements,
|
|
35
36
|
];
|
|
36
37
|
this.createElement = () => {
|
|
37
38
|
this.contentDOM = document.createElement(this.elementType);
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*!
|
|
3
|
+
* © 2025 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.SupplementView = void 0;
|
|
19
|
+
const style_guide_1 = require("@manuscripts/style-guide");
|
|
20
|
+
const server_1 = require("react-dom/server");
|
|
21
|
+
const icons_1 = require("../icons");
|
|
22
|
+
const doc_1 = require("../lib/doc");
|
|
23
|
+
const base_node_view_1 = require("./base_node_view");
|
|
24
|
+
const creators_1 = require("./creators");
|
|
25
|
+
class SupplementView extends base_node_view_1.BaseNodeView {
|
|
26
|
+
constructor() {
|
|
27
|
+
super(...arguments);
|
|
28
|
+
this.ignoreMutation = () => true;
|
|
29
|
+
this.createElement = () => {
|
|
30
|
+
this.dom = document.createElement('div');
|
|
31
|
+
this.dom.classList.add('supplement-item');
|
|
32
|
+
this.dom.classList.add('block');
|
|
33
|
+
this.dom.setAttribute('id', this.node.attrs.id);
|
|
34
|
+
this.dom.setAttribute('href', this.node.attrs.href);
|
|
35
|
+
this.dom.draggable = true;
|
|
36
|
+
this.contentDOM = document.createElement('div');
|
|
37
|
+
this.contentDOM.classList.add('supplement-caption');
|
|
38
|
+
this.dom.appendChild(this.contentDOM);
|
|
39
|
+
this.addFileInfo();
|
|
40
|
+
this.addDragIcon();
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
initialise() {
|
|
44
|
+
this.createElement();
|
|
45
|
+
this.updateContents();
|
|
46
|
+
this.setupDragAndDrop();
|
|
47
|
+
}
|
|
48
|
+
updateContents() {
|
|
49
|
+
super.updateContents();
|
|
50
|
+
this.refreshFileInfo();
|
|
51
|
+
}
|
|
52
|
+
getDropSide(element, clientY) {
|
|
53
|
+
const { top, bottom } = element.getBoundingClientRect();
|
|
54
|
+
const middleY = (top + bottom) / 2;
|
|
55
|
+
return clientY > middleY ? 'after' : 'before';
|
|
56
|
+
}
|
|
57
|
+
noActualMove(currentPos, nodeSize, targetPos) {
|
|
58
|
+
return targetPos === currentPos || targetPos === currentPos + nodeSize;
|
|
59
|
+
}
|
|
60
|
+
handleDragStart() {
|
|
61
|
+
const supplementId = this.node.attrs.id;
|
|
62
|
+
SupplementView.currentDragSupplementId = supplementId;
|
|
63
|
+
this.dom.classList.add('dragging');
|
|
64
|
+
}
|
|
65
|
+
setupDragAndDrop() {
|
|
66
|
+
const clearDropClasses = () => {
|
|
67
|
+
this.dom.classList.remove('drop-target-above', 'drop-target-below');
|
|
68
|
+
};
|
|
69
|
+
this.dom.addEventListener('dragstart', () => {
|
|
70
|
+
if (this.node.attrs.id) {
|
|
71
|
+
this.handleDragStart();
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
this.dom.addEventListener('dragend', () => {
|
|
75
|
+
SupplementView.currentDragSupplementId = null;
|
|
76
|
+
this.dom.classList.remove('dragging');
|
|
77
|
+
clearDropClasses();
|
|
78
|
+
});
|
|
79
|
+
this.dom.addEventListener('dragover', (e) => {
|
|
80
|
+
if (SupplementView.currentDragSupplementId) {
|
|
81
|
+
e.preventDefault();
|
|
82
|
+
e.stopPropagation();
|
|
83
|
+
const side = this.getDropSide(this.dom, e.clientY);
|
|
84
|
+
clearDropClasses();
|
|
85
|
+
this.dom.classList.add(side === 'before' ? 'drop-target-above' : 'drop-target-below');
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
this.dom.addEventListener('dragleave', (e) => {
|
|
89
|
+
if (!this.dom.contains(e.relatedTarget)) {
|
|
90
|
+
clearDropClasses();
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
this.dom.addEventListener('drop', (e) => {
|
|
94
|
+
if (!SupplementView.currentDragSupplementId) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
e.preventDefault();
|
|
98
|
+
e.stopPropagation();
|
|
99
|
+
const supplementId = SupplementView.currentDragSupplementId;
|
|
100
|
+
if (!supplementId) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const { state } = this.view;
|
|
104
|
+
const supplement = (0, doc_1.findNodeByID)(state.doc, supplementId);
|
|
105
|
+
if (!supplement) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const toPos = this.getPos();
|
|
109
|
+
const side = this.getDropSide(this.dom, e.clientY);
|
|
110
|
+
const targetPos = side === 'before' ? toPos : toPos + this.node.nodeSize;
|
|
111
|
+
if (this.noActualMove(supplement.pos, supplement.node.nodeSize, targetPos)) {
|
|
112
|
+
clearDropClasses();
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
this.moveSupplement(supplement.pos, supplement.node, targetPos);
|
|
116
|
+
clearDropClasses();
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
moveSupplement(fromPos, fromNode, targetPos) {
|
|
120
|
+
const { state } = this.view;
|
|
121
|
+
const { tr } = state;
|
|
122
|
+
tr.insert(targetPos, fromNode);
|
|
123
|
+
const mappedFrom = tr.mapping.map(fromPos, -1);
|
|
124
|
+
tr.delete(mappedFrom, mappedFrom + fromNode.nodeSize);
|
|
125
|
+
this.view.dispatch(tr);
|
|
126
|
+
}
|
|
127
|
+
addFileInfo() {
|
|
128
|
+
this.supplementInfoEl = document.createElement('div');
|
|
129
|
+
this.supplementInfoEl.classList.add('supplement-file-info');
|
|
130
|
+
this.supplementInfoEl.contentEditable = 'false';
|
|
131
|
+
const files = this.props.getFiles();
|
|
132
|
+
const file = files.find((f) => f.id === this.node.attrs.href);
|
|
133
|
+
if (file) {
|
|
134
|
+
const iconElement = document.createElement('span');
|
|
135
|
+
iconElement.classList.add('supplement-file-icon');
|
|
136
|
+
const icon = (0, style_guide_1.getFileIcon)(file.name);
|
|
137
|
+
if (icon) {
|
|
138
|
+
iconElement.innerHTML = (0, server_1.renderToStaticMarkup)(icon);
|
|
139
|
+
}
|
|
140
|
+
this.supplementInfoEl.appendChild(iconElement);
|
|
141
|
+
const fileName = document.createElement('span');
|
|
142
|
+
fileName.classList.add('supplement-file-name');
|
|
143
|
+
fileName.textContent = file.name;
|
|
144
|
+
this.supplementInfoEl.appendChild(fileName);
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
const placeholder = document.createElement('span');
|
|
148
|
+
placeholder.textContent = 'File not found';
|
|
149
|
+
this.supplementInfoEl.appendChild(placeholder);
|
|
150
|
+
}
|
|
151
|
+
this.dom.appendChild(this.supplementInfoEl);
|
|
152
|
+
}
|
|
153
|
+
refreshFileInfo() {
|
|
154
|
+
this.supplementInfoEl.remove();
|
|
155
|
+
this.addFileInfo();
|
|
156
|
+
}
|
|
157
|
+
addDragIcon() {
|
|
158
|
+
if (this.dragIcon) {
|
|
159
|
+
this.dragIcon.remove();
|
|
160
|
+
this.dragIcon = undefined;
|
|
161
|
+
}
|
|
162
|
+
const dragIcon = document.createElement('div');
|
|
163
|
+
dragIcon.className = 'drag-icon';
|
|
164
|
+
dragIcon.innerHTML = icons_1.draggableIcon;
|
|
165
|
+
dragIcon.draggable = false;
|
|
166
|
+
dragIcon.addEventListener('mousedown', (e) => {
|
|
167
|
+
e.stopPropagation();
|
|
168
|
+
});
|
|
169
|
+
this.dragIcon = dragIcon;
|
|
170
|
+
this.dom.appendChild(dragIcon);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
exports.SupplementView = SupplementView;
|
|
174
|
+
SupplementView.currentDragSupplementId = null;
|
|
175
|
+
exports.default = (0, creators_1.createNodeView)(SupplementView);
|