@manuscripts/body-editor 1.6.9 → 1.6.10
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/components/keywords/DeleteKeywordDialog.js +46 -0
- package/dist/cjs/configs/editor-plugins.js +0 -2
- package/dist/cjs/configs/editor-views.js +3 -3
- package/dist/cjs/index.js +0 -1
- package/dist/cjs/views/keyword.js +58 -2
- package/dist/cjs/views/{keywords_element.js → keyword_group.js} +10 -13
- package/dist/es/components/keywords/DeleteKeywordDialog.js +19 -0
- package/dist/es/configs/editor-plugins.js +0 -2
- package/dist/es/configs/editor-views.js +3 -3
- package/dist/es/index.js +0 -1
- package/dist/es/views/keyword.js +55 -2
- package/dist/es/views/{keywords_element.js → keyword_group.js} +8 -11
- package/dist/types/components/keywords/DeleteKeywordDialog.d.ts +6 -0
- package/dist/types/configs/editor-views.d.ts +3 -3
- package/dist/types/index.d.ts +0 -1
- package/dist/types/views/keyword.d.ts +9 -9
- package/dist/types/views/{keywords_element.d.ts → keyword_group.d.ts} +3 -4
- package/package.json +1 -1
- package/styles/AdvancedEditor.css +40 -35
- package/dist/cjs/components/keywords/DeleteKeyword.js +0 -92
- package/dist/cjs/plugins/keywords.js +0 -121
- package/dist/es/components/keywords/DeleteKeyword.js +0 -65
- package/dist/es/plugins/keywords.js +0 -115
- package/dist/types/components/keywords/DeleteKeyword.d.ts +0 -10
- package/dist/types/plugins/keywords.d.ts +0 -28
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.DeleteKeywordDialog = void 0;
|
|
27
|
+
const style_guide_1 = require("@manuscripts/style-guide");
|
|
28
|
+
const react_1 = __importStar(require("react"));
|
|
29
|
+
const DeleteKeywordDialog = ({ keyword, handleDelete, }) => {
|
|
30
|
+
const [isOpen, setOpen] = (0, react_1.useState)(true);
|
|
31
|
+
return (react_1.default.createElement(style_guide_1.Dialog, { isOpen: isOpen, actions: {
|
|
32
|
+
primary: {
|
|
33
|
+
action: () => setOpen(false),
|
|
34
|
+
title: 'Cancel',
|
|
35
|
+
},
|
|
36
|
+
secondary: {
|
|
37
|
+
action: () => {
|
|
38
|
+
setOpen(false);
|
|
39
|
+
handleDelete();
|
|
40
|
+
},
|
|
41
|
+
title: 'Delete',
|
|
42
|
+
},
|
|
43
|
+
}, category: style_guide_1.Category.confirmation, header: 'Delete Keyword', message: `Are you sure you want to delete "${keyword}" keyword?
|
|
44
|
+
` }));
|
|
45
|
+
};
|
|
46
|
+
exports.DeleteKeywordDialog = DeleteKeywordDialog;
|
|
@@ -30,7 +30,6 @@ const comment_annotation_1 = __importDefault(require("../plugins/comment_annotat
|
|
|
30
30
|
const elements_1 = __importDefault(require("../plugins/elements"));
|
|
31
31
|
const footnotes_1 = __importDefault(require("../plugins/footnotes"));
|
|
32
32
|
const highlight_1 = __importDefault(require("../plugins/highlight"));
|
|
33
|
-
const keywords_1 = __importDefault(require("../plugins/keywords"));
|
|
34
33
|
const objects_1 = __importDefault(require("../plugins/objects"));
|
|
35
34
|
const paragraphs_1 = __importDefault(require("../plugins/paragraphs"));
|
|
36
35
|
const persist_1 = __importDefault(require("../plugins/persist"));
|
|
@@ -54,7 +53,6 @@ exports.default = (props) => {
|
|
|
54
53
|
(0, persist_1.default)(),
|
|
55
54
|
(0, sections_1.default)(),
|
|
56
55
|
(0, toc_1.default)(props),
|
|
57
|
-
(0, keywords_1.default)(props),
|
|
58
56
|
(0, bibliography_1.default)(props),
|
|
59
57
|
(0, objects_1.default)(props),
|
|
60
58
|
(0, comment_annotation_1.default)(props),
|
|
@@ -34,7 +34,7 @@ const footnotes_element_1 = __importDefault(require("../views/footnotes_element"
|
|
|
34
34
|
const inline_equation_editable_1 = __importDefault(require("../views/inline_equation_editable"));
|
|
35
35
|
const inline_footnote_editable_1 = __importDefault(require("../views/inline_footnote_editable"));
|
|
36
36
|
const keyword_1 = __importDefault(require("../views/keyword"));
|
|
37
|
-
const
|
|
37
|
+
const keyword_group_1 = __importDefault(require("../views/keyword_group"));
|
|
38
38
|
const link_editable_1 = __importDefault(require("../views/link_editable"));
|
|
39
39
|
const listing_editable_1 = __importDefault(require("../views/listing_editable"));
|
|
40
40
|
const listing_element_editable_1 = __importDefault(require("../views/listing_element_editable"));
|
|
@@ -65,8 +65,8 @@ exports.default = (props, dispatch) => {
|
|
|
65
65
|
footnotes_element: (0, footnotes_element_1.default)(props),
|
|
66
66
|
inline_equation: (0, inline_equation_editable_1.default)(props),
|
|
67
67
|
inline_footnote: (0, inline_footnote_editable_1.default)(props),
|
|
68
|
-
keyword: (0, keyword_1.default)(props),
|
|
69
|
-
|
|
68
|
+
keyword: (0, keyword_1.default)(props, dispatch),
|
|
69
|
+
keyword_group: (0, keyword_group_1.default)(props, dispatch),
|
|
70
70
|
link: (0, link_editable_1.default)(props),
|
|
71
71
|
listing: (0, listing_editable_1.default)(props),
|
|
72
72
|
listing_element: (0, listing_element_editable_1.default)(props),
|
package/dist/cjs/index.js
CHANGED
|
@@ -56,6 +56,5 @@ var comment_annotation_1 = require("./plugins/comment_annotation");
|
|
|
56
56
|
Object.defineProperty(exports, "commentScroll", { enumerable: true, get: function () { return comment_annotation_1.commentScroll; } });
|
|
57
57
|
Object.defineProperty(exports, "isThereSelector", { enumerable: true, get: function () { return comment_annotation_1.isThereSelector; } });
|
|
58
58
|
Object.defineProperty(exports, "isHighlightComment", { enumerable: true, get: function () { return comment_annotation_1.isHighlightComment; } });
|
|
59
|
-
__exportStar(require("./plugins/keywords"), exports);
|
|
60
59
|
__exportStar(require("./lib/utils"), exports);
|
|
61
60
|
__exportStar(require("./useEditor"), exports);
|
|
@@ -14,15 +14,71 @@
|
|
|
14
14
|
* See the License for the specific language governing permissions and
|
|
15
15
|
* limitations under the License.
|
|
16
16
|
*/
|
|
17
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
18
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
19
|
+
};
|
|
17
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
21
|
exports.KeywordView = void 0;
|
|
22
|
+
const DeleteKeywordDialog_1 = require("../components/keywords/DeleteKeywordDialog");
|
|
23
|
+
const track_changes_utils_1 = require("../lib/track-changes-utils");
|
|
19
24
|
const base_node_view_1 = require("./base_node_view");
|
|
20
25
|
const creators_1 = require("./creators");
|
|
26
|
+
const ReactSubView_1 = __importDefault(require("./ReactSubView"));
|
|
27
|
+
const deleteIcon = '<svg width="8px" height="8px" viewBox="0 0 26 26" xmlns="http://www.w3.org/2000/svg">\n' +
|
|
28
|
+
' <g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">\n' +
|
|
29
|
+
' <g fill="#6E6E6E">\n' +
|
|
30
|
+
' <rect id="Rectangle-23-Copy" transform="translate(13.000000, 13.000000) rotate(-45.000000) translate(-13.000000, -13.000000) " x="-3" y="11" width="32" height="4" rx="2"></rect>\n' +
|
|
31
|
+
' <rect id="Rectangle-23-Copy-2" transform="translate(13.000000, 13.000000) scale(1, -1) rotate(-45.000000) translate(-13.000000, -13.000000) " x="-3" y="11" width="32" height="4" rx="2"></rect>\n' +
|
|
32
|
+
' </g>\n' +
|
|
33
|
+
' </g>\n' +
|
|
34
|
+
'</svg>';
|
|
21
35
|
class KeywordView extends base_node_view_1.BaseNodeView {
|
|
22
36
|
constructor() {
|
|
23
37
|
super(...arguments);
|
|
24
|
-
this.
|
|
25
|
-
|
|
38
|
+
this.initialise = () => {
|
|
39
|
+
this.createDOM();
|
|
40
|
+
this.updateContents();
|
|
41
|
+
};
|
|
42
|
+
this.createDOM = () => {
|
|
43
|
+
this.dom = document.createElement('span');
|
|
44
|
+
this.contentDOM = document.createElement('span');
|
|
45
|
+
};
|
|
46
|
+
this.updateContents = () => {
|
|
47
|
+
const keyword = document.createElement('span');
|
|
48
|
+
const classes = ['keyword', ...(0, track_changes_utils_1.getChangeClasses)(this.node)];
|
|
49
|
+
keyword.classList.add(...classes);
|
|
50
|
+
keyword.appendChild(this.contentDOM);
|
|
51
|
+
const can = this.props.getCapabilities();
|
|
52
|
+
if (can.editArticle) {
|
|
53
|
+
const svg = new DOMParser()
|
|
54
|
+
.parseFromString(deleteIcon, 'image/svg+xml')
|
|
55
|
+
.querySelector('svg');
|
|
56
|
+
svg.classList.add('delete-keyword');
|
|
57
|
+
svg.addEventListener('click', this.showConfirmationDialog);
|
|
58
|
+
keyword.appendChild(svg);
|
|
59
|
+
}
|
|
60
|
+
this.dom.innerHTML = '';
|
|
61
|
+
this.dom.appendChild(keyword);
|
|
62
|
+
};
|
|
63
|
+
this.showConfirmationDialog = () => {
|
|
64
|
+
var _a;
|
|
65
|
+
(_a = this.dialog) === null || _a === void 0 ? void 0 : _a.remove();
|
|
66
|
+
const keyword = this.node;
|
|
67
|
+
const pos = this.getPos();
|
|
68
|
+
const handleDelete = () => {
|
|
69
|
+
const tr = this.view.state.tr;
|
|
70
|
+
tr.delete(pos, pos + keyword.nodeSize);
|
|
71
|
+
this.view.dispatch(tr);
|
|
72
|
+
};
|
|
73
|
+
const componentProps = {
|
|
74
|
+
keyword: keyword.textContent,
|
|
75
|
+
handleDelete: handleDelete,
|
|
76
|
+
};
|
|
77
|
+
this.dialog = (0, ReactSubView_1.default)(this.props, DeleteKeywordDialog_1.DeleteKeywordDialog, componentProps, this.node, this.getPos, this.view, 'keywords-delete');
|
|
78
|
+
if (this.dialog) {
|
|
79
|
+
this.dom.appendChild(this.dialog);
|
|
80
|
+
}
|
|
81
|
+
};
|
|
26
82
|
}
|
|
27
83
|
}
|
|
28
84
|
exports.KeywordView = KeywordView;
|
|
@@ -18,36 +18,33 @@ 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
|
-
exports.
|
|
21
|
+
exports.KeywordGroupView = void 0;
|
|
22
22
|
const AddKeywordInline_1 = require("../components/keywords/AddKeywordInline");
|
|
23
|
-
const DeleteKeyword_1 = require("../components/keywords/DeleteKeyword");
|
|
24
23
|
const block_view_1 = __importDefault(require("./block_view"));
|
|
25
24
|
const creators_1 = require("./creators");
|
|
26
25
|
const ReactSubView_1 = __importDefault(require("./ReactSubView"));
|
|
27
|
-
class
|
|
26
|
+
class KeywordGroupView extends block_view_1.default {
|
|
28
27
|
constructor() {
|
|
29
28
|
super(...arguments);
|
|
30
29
|
this.ignoreMutation = () => true;
|
|
31
30
|
this.stopEvent = () => true;
|
|
32
31
|
this.createElement = () => {
|
|
33
32
|
this.element = document.createElement('div');
|
|
34
|
-
this.element.classList.add('block');
|
|
33
|
+
this.element.classList.add('block', 'keyword-group-container');
|
|
35
34
|
this.dom.appendChild(this.element);
|
|
36
35
|
this.contentDOM = document.createElement('div');
|
|
37
|
-
this.contentDOM.classList.add('
|
|
36
|
+
this.contentDOM.classList.add('keyword-group');
|
|
38
37
|
this.contentDOM.setAttribute('id', this.node.attrs.id);
|
|
39
38
|
this.contentDOM.setAttribute('contenteditable', 'false');
|
|
40
39
|
this.element.appendChild(this.contentDOM);
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
this.element.appendChild(this.addingTools);
|
|
40
|
+
if (this.props.getCapabilities().editArticle) {
|
|
41
|
+
this.addingTools = (0, ReactSubView_1.default)(this.props, AddKeywordInline_1.AddKeywordInline, { getUpdatedNode: () => this.node }, this.node, this.getPos, this.view, 'keywords-editor');
|
|
44
42
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
this.element.appendChild(this.deleteTools);
|
|
43
|
+
if (this.addingTools) {
|
|
44
|
+
this.element.appendChild(this.addingTools);
|
|
48
45
|
}
|
|
49
46
|
};
|
|
50
47
|
}
|
|
51
48
|
}
|
|
52
|
-
exports.
|
|
53
|
-
exports.default = (0, creators_1.createNodeView)(
|
|
49
|
+
exports.KeywordGroupView = KeywordGroupView;
|
|
50
|
+
exports.default = (0, creators_1.createNodeView)(KeywordGroupView);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Category, Dialog } from '@manuscripts/style-guide';
|
|
2
|
+
import React, { useState } from 'react';
|
|
3
|
+
export const DeleteKeywordDialog = ({ keyword, handleDelete, }) => {
|
|
4
|
+
const [isOpen, setOpen] = useState(true);
|
|
5
|
+
return (React.createElement(Dialog, { isOpen: isOpen, actions: {
|
|
6
|
+
primary: {
|
|
7
|
+
action: () => setOpen(false),
|
|
8
|
+
title: 'Cancel',
|
|
9
|
+
},
|
|
10
|
+
secondary: {
|
|
11
|
+
action: () => {
|
|
12
|
+
setOpen(false);
|
|
13
|
+
handleDelete();
|
|
14
|
+
},
|
|
15
|
+
title: 'Delete',
|
|
16
|
+
},
|
|
17
|
+
}, category: Category.confirmation, header: 'Delete Keyword', message: `Are you sure you want to delete "${keyword}" keyword?
|
|
18
|
+
` }));
|
|
19
|
+
};
|
|
@@ -25,7 +25,6 @@ import comment_annotation from '../plugins/comment_annotation';
|
|
|
25
25
|
import elements from '../plugins/elements';
|
|
26
26
|
import footnotes from '../plugins/footnotes';
|
|
27
27
|
import highlights from '../plugins/highlight';
|
|
28
|
-
import keywords from '../plugins/keywords';
|
|
29
28
|
import objects from '../plugins/objects';
|
|
30
29
|
import paragraphs from '../plugins/paragraphs';
|
|
31
30
|
import persist from '../plugins/persist';
|
|
@@ -49,7 +48,6 @@ export default (props) => {
|
|
|
49
48
|
persist(),
|
|
50
49
|
sections(),
|
|
51
50
|
toc(props),
|
|
52
|
-
keywords(props),
|
|
53
51
|
bibliography(props),
|
|
54
52
|
objects(props),
|
|
55
53
|
comment_annotation(props),
|
|
@@ -29,7 +29,7 @@ import footnotesElement from '../views/footnotes_element';
|
|
|
29
29
|
import inlineEquation from '../views/inline_equation_editable';
|
|
30
30
|
import inlineFootnote from '../views/inline_footnote_editable';
|
|
31
31
|
import keyword from '../views/keyword';
|
|
32
|
-
import
|
|
32
|
+
import keywordGroup from '../views/keyword_group';
|
|
33
33
|
import link from '../views/link_editable';
|
|
34
34
|
import listing from '../views/listing_editable';
|
|
35
35
|
import listingElement from '../views/listing_element_editable';
|
|
@@ -60,8 +60,8 @@ export default (props, dispatch) => {
|
|
|
60
60
|
footnotes_element: footnotesElement(props),
|
|
61
61
|
inline_equation: inlineEquation(props),
|
|
62
62
|
inline_footnote: inlineFootnote(props),
|
|
63
|
-
keyword: keyword(props),
|
|
64
|
-
|
|
63
|
+
keyword: keyword(props, dispatch),
|
|
64
|
+
keyword_group: keywordGroup(props, dispatch),
|
|
65
65
|
link: link(props),
|
|
66
66
|
listing: listing(props),
|
|
67
67
|
listing_element: listingElement(props),
|
package/dist/es/index.js
CHANGED
|
@@ -27,6 +27,5 @@ export { PopperManager } from './lib/popper';
|
|
|
27
27
|
export { toolbar } from './toolbar';
|
|
28
28
|
export * from './plugins/highlight';
|
|
29
29
|
export { commentScroll, isThereSelector, isHighlightComment, } from './plugins/comment_annotation';
|
|
30
|
-
export * from './plugins/keywords';
|
|
31
30
|
export * from './lib/utils';
|
|
32
31
|
export * from './useEditor';
|
package/dist/es/views/keyword.js
CHANGED
|
@@ -13,13 +13,66 @@
|
|
|
13
13
|
* See the License for the specific language governing permissions and
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
|
+
import { DeleteKeywordDialog, } from '../components/keywords/DeleteKeywordDialog';
|
|
17
|
+
import { getChangeClasses } from '../lib/track-changes-utils';
|
|
16
18
|
import { BaseNodeView } from './base_node_view';
|
|
17
19
|
import { createNodeView } from './creators';
|
|
20
|
+
import ReactSubView from './ReactSubView';
|
|
21
|
+
const deleteIcon = '<svg width="8px" height="8px" viewBox="0 0 26 26" xmlns="http://www.w3.org/2000/svg">\n' +
|
|
22
|
+
' <g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">\n' +
|
|
23
|
+
' <g fill="#6E6E6E">\n' +
|
|
24
|
+
' <rect id="Rectangle-23-Copy" transform="translate(13.000000, 13.000000) rotate(-45.000000) translate(-13.000000, -13.000000) " x="-3" y="11" width="32" height="4" rx="2"></rect>\n' +
|
|
25
|
+
' <rect id="Rectangle-23-Copy-2" transform="translate(13.000000, 13.000000) scale(1, -1) rotate(-45.000000) translate(-13.000000, -13.000000) " x="-3" y="11" width="32" height="4" rx="2"></rect>\n' +
|
|
26
|
+
' </g>\n' +
|
|
27
|
+
' </g>\n' +
|
|
28
|
+
'</svg>';
|
|
18
29
|
export class KeywordView extends BaseNodeView {
|
|
19
30
|
constructor() {
|
|
20
31
|
super(...arguments);
|
|
21
|
-
this.
|
|
22
|
-
|
|
32
|
+
this.initialise = () => {
|
|
33
|
+
this.createDOM();
|
|
34
|
+
this.updateContents();
|
|
35
|
+
};
|
|
36
|
+
this.createDOM = () => {
|
|
37
|
+
this.dom = document.createElement('span');
|
|
38
|
+
this.contentDOM = document.createElement('span');
|
|
39
|
+
};
|
|
40
|
+
this.updateContents = () => {
|
|
41
|
+
const keyword = document.createElement('span');
|
|
42
|
+
const classes = ['keyword', ...getChangeClasses(this.node)];
|
|
43
|
+
keyword.classList.add(...classes);
|
|
44
|
+
keyword.appendChild(this.contentDOM);
|
|
45
|
+
const can = this.props.getCapabilities();
|
|
46
|
+
if (can.editArticle) {
|
|
47
|
+
const svg = new DOMParser()
|
|
48
|
+
.parseFromString(deleteIcon, 'image/svg+xml')
|
|
49
|
+
.querySelector('svg');
|
|
50
|
+
svg.classList.add('delete-keyword');
|
|
51
|
+
svg.addEventListener('click', this.showConfirmationDialog);
|
|
52
|
+
keyword.appendChild(svg);
|
|
53
|
+
}
|
|
54
|
+
this.dom.innerHTML = '';
|
|
55
|
+
this.dom.appendChild(keyword);
|
|
56
|
+
};
|
|
57
|
+
this.showConfirmationDialog = () => {
|
|
58
|
+
var _a;
|
|
59
|
+
(_a = this.dialog) === null || _a === void 0 ? void 0 : _a.remove();
|
|
60
|
+
const keyword = this.node;
|
|
61
|
+
const pos = this.getPos();
|
|
62
|
+
const handleDelete = () => {
|
|
63
|
+
const tr = this.view.state.tr;
|
|
64
|
+
tr.delete(pos, pos + keyword.nodeSize);
|
|
65
|
+
this.view.dispatch(tr);
|
|
66
|
+
};
|
|
67
|
+
const componentProps = {
|
|
68
|
+
keyword: keyword.textContent,
|
|
69
|
+
handleDelete: handleDelete,
|
|
70
|
+
};
|
|
71
|
+
this.dialog = ReactSubView(this.props, DeleteKeywordDialog, componentProps, this.node, this.getPos, this.view, 'keywords-delete');
|
|
72
|
+
if (this.dialog) {
|
|
73
|
+
this.dom.appendChild(this.dialog);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
23
76
|
}
|
|
24
77
|
}
|
|
25
78
|
export default createNodeView(KeywordView);
|
|
@@ -14,33 +14,30 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
import { AddKeywordInline } from '../components/keywords/AddKeywordInline';
|
|
17
|
-
import { DeleteKeyword } from '../components/keywords/DeleteKeyword';
|
|
18
17
|
import BlockView from './block_view';
|
|
19
18
|
import { createNodeView } from './creators';
|
|
20
19
|
import ReactSubView from './ReactSubView';
|
|
21
|
-
export class
|
|
20
|
+
export class KeywordGroupView extends BlockView {
|
|
22
21
|
constructor() {
|
|
23
22
|
super(...arguments);
|
|
24
23
|
this.ignoreMutation = () => true;
|
|
25
24
|
this.stopEvent = () => true;
|
|
26
25
|
this.createElement = () => {
|
|
27
26
|
this.element = document.createElement('div');
|
|
28
|
-
this.element.classList.add('block');
|
|
27
|
+
this.element.classList.add('block', 'keyword-group-container');
|
|
29
28
|
this.dom.appendChild(this.element);
|
|
30
29
|
this.contentDOM = document.createElement('div');
|
|
31
|
-
this.contentDOM.classList.add('
|
|
30
|
+
this.contentDOM.classList.add('keyword-group');
|
|
32
31
|
this.contentDOM.setAttribute('id', this.node.attrs.id);
|
|
33
32
|
this.contentDOM.setAttribute('contenteditable', 'false');
|
|
34
33
|
this.element.appendChild(this.contentDOM);
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
this.element.appendChild(this.addingTools);
|
|
34
|
+
if (this.props.getCapabilities().editArticle) {
|
|
35
|
+
this.addingTools = ReactSubView(this.props, AddKeywordInline, { getUpdatedNode: () => this.node }, this.node, this.getPos, this.view, 'keywords-editor');
|
|
38
36
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
this.element.appendChild(this.deleteTools);
|
|
37
|
+
if (this.addingTools) {
|
|
38
|
+
this.element.appendChild(this.addingTools);
|
|
42
39
|
}
|
|
43
40
|
};
|
|
44
41
|
}
|
|
45
42
|
}
|
|
46
|
-
export default createNodeView(
|
|
43
|
+
export default createNodeView(KeywordGroupView);
|
|
@@ -18,7 +18,7 @@ import { Dispatch } from '../commands';
|
|
|
18
18
|
import { CitationViewProps } from '../views/citation';
|
|
19
19
|
import { EditableBlockProps } from '../views/editable_block';
|
|
20
20
|
import { FigureProps } from '../views/figure_editable';
|
|
21
|
-
import { KeywordsElementProps } from '../views/
|
|
21
|
+
import { KeywordsElementProps } from '../views/keyword_group';
|
|
22
22
|
type EditorProps = EditableBlockProps & CitationViewProps & FigureProps & KeywordsElementProps & {
|
|
23
23
|
theme: DefaultTheme;
|
|
24
24
|
};
|
|
@@ -260,8 +260,8 @@ declare const _default: (props: EditorProps, dispatch: Dispatch) => {
|
|
|
260
260
|
footnotes_element: import("../types").NodeViewCreator<import("../views/footnotes_element").FootnotesElementView<any>>;
|
|
261
261
|
inline_equation: import("../types").NodeViewCreator<import("../views/inline_equation_editable").InlineEquationEditableView>;
|
|
262
262
|
inline_footnote: import("../types").NodeViewCreator<import("../views/inline_footnote").InlineFootnoteView<any>>;
|
|
263
|
-
keyword: import("../types").NodeViewCreator<import("../views/keyword").KeywordView
|
|
264
|
-
|
|
263
|
+
keyword: import("../types").NodeViewCreator<import("../views/keyword").KeywordView>;
|
|
264
|
+
keyword_group: import("../types").NodeViewCreator<import("../views/keyword_group").KeywordGroupView>;
|
|
265
265
|
link: import("../types").NodeViewCreator<import("../views/link_editable").LinkEditableView>;
|
|
266
266
|
listing: import("../types").NodeViewCreator<import("../views/listing_editable").ListingEditableView>;
|
|
267
267
|
listing_element: import("../types").NodeViewCreator<{
|
package/dist/types/index.d.ts
CHANGED
|
@@ -28,6 +28,5 @@ export { PopperManager } from './lib/popper';
|
|
|
28
28
|
export { toolbar } from './toolbar';
|
|
29
29
|
export * from './plugins/highlight';
|
|
30
30
|
export { commentScroll, isThereSelector, isHighlightComment, } from './plugins/comment_annotation';
|
|
31
|
-
export * from './plugins/keywords';
|
|
32
31
|
export * from './lib/utils';
|
|
33
32
|
export * from './useEditor';
|
|
@@ -13,15 +13,15 @@
|
|
|
13
13
|
* See the License for the specific language governing permissions and
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
|
-
import { Capabilities } from '@manuscripts/style-guide';
|
|
17
16
|
import { ManuscriptNodeView } from '@manuscripts/transform';
|
|
18
|
-
import {
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
import { BaseNodeView } from './base_node_view';
|
|
18
|
+
import { EditableBlockProps } from './editable_block';
|
|
19
|
+
export declare class KeywordView extends BaseNodeView<EditableBlockProps> implements ManuscriptNodeView {
|
|
20
|
+
private dialog;
|
|
21
|
+
initialise: () => void;
|
|
22
|
+
createDOM: () => void;
|
|
23
|
+
updateContents: () => void;
|
|
24
|
+
private showConfirmationDialog;
|
|
21
25
|
}
|
|
22
|
-
|
|
23
|
-
stopEvent: () => boolean;
|
|
24
|
-
ignoreMutation: () => boolean;
|
|
25
|
-
}
|
|
26
|
-
declare const _default: (props: BaseNodeProps, dispatch?: import("..").Dispatch | undefined) => import("../types").NodeViewCreator<KeywordView<any>>;
|
|
26
|
+
declare const _default: (props: import("./base_node_view").BaseNodeProps, dispatch?: import("..").Dispatch | undefined) => import("../types").NodeViewCreator<KeywordView>;
|
|
27
27
|
export default _default;
|
|
@@ -27,13 +27,12 @@ export interface KeywordsElementProps {
|
|
|
27
27
|
retrySync: (componentIDs: string[]) => Promise<void>;
|
|
28
28
|
saveModel: <T extends Model>(model: T | Build<T> | Partial<T>) => Promise<T>;
|
|
29
29
|
}
|
|
30
|
-
export declare class
|
|
30
|
+
export declare class KeywordGroupView extends BlockView<BaseNodeProps & KeywordsElementProps> {
|
|
31
31
|
private element;
|
|
32
|
-
addingTools
|
|
33
|
-
deleteTools: HTMLDivElement;
|
|
32
|
+
private addingTools;
|
|
34
33
|
ignoreMutation: () => boolean;
|
|
35
34
|
stopEvent: () => boolean;
|
|
36
35
|
createElement: () => void;
|
|
37
36
|
}
|
|
38
|
-
declare const _default: (props: BaseNodeProps, dispatch?: Dispatch | undefined) => import("../types").NodeViewCreator<
|
|
37
|
+
declare const _default: (props: BaseNodeProps, dispatch?: Dispatch | undefined) => import("../types").NodeViewCreator<KeywordGroupView>;
|
|
39
38
|
export default _default;
|
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.10",
|
|
5
5
|
"repository": "github:Atypon-OpenSource/manuscripts-body-editor",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"main": "dist/cjs",
|
|
@@ -545,10 +545,6 @@ Next levels are shifted 'up' by 1
|
|
|
545
545
|
border-radius: 0 0 32px 32px;
|
|
546
546
|
}
|
|
547
547
|
|
|
548
|
-
.keywords {
|
|
549
|
-
margin: 0 0 36px;
|
|
550
|
-
}
|
|
551
|
-
|
|
552
548
|
.ProseMirror > .keywords > .block-section_title > h1 {
|
|
553
549
|
color: #353535 !important;
|
|
554
550
|
font-size: 12px !important;
|
|
@@ -558,76 +554,76 @@ Next levels are shifted 'up' by 1
|
|
|
558
554
|
margin-top: 4px !important;
|
|
559
555
|
}
|
|
560
556
|
|
|
561
|
-
.keywords
|
|
562
|
-
margin: 0;
|
|
563
|
-
display: inline;
|
|
564
|
-
}
|
|
565
|
-
|
|
566
|
-
.keywords-list span.keyword {
|
|
557
|
+
.keywords .keyword {
|
|
567
558
|
display: inline-block;
|
|
568
559
|
color: #353535;
|
|
569
560
|
background-color: #f2f2f2;
|
|
570
|
-
font-family: Lato,
|
|
561
|
+
font-family: Lato,sans-serif;
|
|
571
562
|
font-size: 14px;
|
|
572
563
|
line-height: 16px;
|
|
573
564
|
margin-right: 4px;
|
|
574
565
|
margin-bottom: 4px;
|
|
575
|
-
border: 1px solid
|
|
566
|
+
border: 1px solid transparent;
|
|
576
567
|
border-radius: 6px;
|
|
577
568
|
position: relative;
|
|
578
569
|
cursor: default;
|
|
570
|
+
padding: 4px 8px
|
|
579
571
|
}
|
|
580
572
|
|
|
581
|
-
.keywords
|
|
582
|
-
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
.keywords-list span.keyword ins,
|
|
586
|
-
.keywords-list span.keyword del {
|
|
587
|
-
display: inline-block;
|
|
588
|
-
padding: 4px 8px;
|
|
589
|
-
border-radius: 6px;
|
|
573
|
+
.keywords .keyword ins, .keywords .keyword del {
|
|
574
|
+
background-color: inherit !important
|
|
590
575
|
}
|
|
591
576
|
|
|
592
|
-
.keywords
|
|
593
|
-
|
|
594
|
-
.keywords-list span.keyword:hover del {
|
|
595
|
-
background-color: #f2fbfc;
|
|
596
|
-
border-color: #f2fbfc;
|
|
577
|
+
.keywords .keyword:hover {
|
|
578
|
+
background-color:#f2fbfc !important;
|
|
597
579
|
}
|
|
598
580
|
|
|
599
|
-
.keywords
|
|
581
|
+
.keywords .keyword.selected {
|
|
600
582
|
background-color: #f2fbfc;
|
|
601
583
|
border-color: #bce7f6;
|
|
602
584
|
}
|
|
603
585
|
|
|
604
|
-
.keywords
|
|
605
|
-
.keywords-list .keyword.deleted.accepted {
|
|
586
|
+
.keywords .keyword.deleted.pending,.keywords .keyword.deleted.accepted {
|
|
606
587
|
text-decoration: line-through;
|
|
607
588
|
}
|
|
608
|
-
|
|
589
|
+
|
|
590
|
+
.keywords .keyword .track-changes--control {
|
|
609
591
|
top: 0;
|
|
610
592
|
}
|
|
611
593
|
|
|
612
|
-
.keywords
|
|
594
|
+
.keywords .delete-keyword {
|
|
613
595
|
cursor: pointer;
|
|
614
596
|
margin: 0 0 0 8px;
|
|
615
597
|
opacity: 0.5;
|
|
616
598
|
}
|
|
617
599
|
|
|
618
|
-
.keywords
|
|
600
|
+
.keywords .delete-keyword:hover {
|
|
619
601
|
opacity: 1;
|
|
620
602
|
}
|
|
621
603
|
|
|
622
|
-
.keywords
|
|
604
|
+
.keywords .deleted .delete-keyword {
|
|
605
|
+
display: none;
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
.keywords .deleted.rejected .delete-keyword {
|
|
609
|
+
display: inline;
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
.keywords .inserted.pending .delete-keyword {
|
|
623
613
|
display: none;
|
|
624
614
|
}
|
|
625
615
|
|
|
626
|
-
.keywords-
|
|
616
|
+
.keywords .keyword-group-container {
|
|
617
|
+
position: relative;
|
|
618
|
+
margin: 0 0 36px !important;
|
|
619
|
+
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
.keywords .keyword-group {
|
|
627
623
|
display: inline;
|
|
628
624
|
}
|
|
629
625
|
|
|
630
|
-
.keywords-editor {
|
|
626
|
+
.keywords .keywords-editor {
|
|
631
627
|
position: static;
|
|
632
628
|
display: inline-block;
|
|
633
629
|
width: auto;
|
|
@@ -643,6 +639,15 @@ Next levels are shifted 'up' by 1
|
|
|
643
639
|
align-items: center;
|
|
644
640
|
}
|
|
645
641
|
|
|
642
|
+
.keywords .block-comment-button {
|
|
643
|
+
position: absolute;
|
|
644
|
+
right: 0;
|
|
645
|
+
top: 0;
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
.keywords .block-comment-button .comment-icon {
|
|
649
|
+
top: 8px;
|
|
650
|
+
}
|
|
646
651
|
|
|
647
652
|
.attrs-popper-button-active,
|
|
648
653
|
.attrs-track-mark:hover .attrs-popper-button {
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
24
|
-
};
|
|
25
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.DeleteKeyword = void 0;
|
|
27
|
-
const style_guide_1 = require("@manuscripts/style-guide");
|
|
28
|
-
const react_1 = __importStar(require("react"));
|
|
29
|
-
const DeleteKeyword = ({ viewProps }) => {
|
|
30
|
-
const [isDeletingKeyword, setIsDeletingKeyword] = (0, react_1.useState)(false);
|
|
31
|
-
const [keywordToDelete, setKeywordToDelete] = (0, react_1.useState)('');
|
|
32
|
-
const [keywordToDeleteId, setKeywordToDeleteId] = (0, react_1.useState)('');
|
|
33
|
-
const { getPos, view, node } = viewProps;
|
|
34
|
-
const getKeywords = () => {
|
|
35
|
-
let position = 0, elementSize = 0;
|
|
36
|
-
node.descendants((node, pos) => {
|
|
37
|
-
if (node.attrs.id === keywordToDeleteId) {
|
|
38
|
-
position = pos + getPos();
|
|
39
|
-
elementSize = node.nodeSize;
|
|
40
|
-
return false;
|
|
41
|
-
}
|
|
42
|
-
});
|
|
43
|
-
return { pos: position, to: position + elementSize + 1 };
|
|
44
|
-
};
|
|
45
|
-
const handleClick = (event) => {
|
|
46
|
-
var _a, _b;
|
|
47
|
-
const clickTarget = event.target;
|
|
48
|
-
const deleteIcon = clickTarget.closest('.delete-keyword');
|
|
49
|
-
if (deleteIcon) {
|
|
50
|
-
const keywordId = ((_a = deleteIcon.closest('.keyword')) === null || _a === void 0 ? void 0 : _a.getAttribute('id')) || '';
|
|
51
|
-
const keywordContent = ((_b = deleteIcon.closest('.keyword')) === null || _b === void 0 ? void 0 : _b.textContent) || '';
|
|
52
|
-
setKeywordToDeleteId(keywordId);
|
|
53
|
-
setKeywordToDelete(keywordContent);
|
|
54
|
-
setIsDeletingKeyword(true);
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
const handleCancel = () => {
|
|
58
|
-
resetState();
|
|
59
|
-
};
|
|
60
|
-
const handleDelete = () => {
|
|
61
|
-
if (keywordToDeleteId) {
|
|
62
|
-
const { pos, to } = getKeywords();
|
|
63
|
-
if (view.dispatch) {
|
|
64
|
-
view.dispatch(view.state.tr.delete(pos, to).setMeta('keywordsUpdated', true));
|
|
65
|
-
}
|
|
66
|
-
resetState();
|
|
67
|
-
}
|
|
68
|
-
};
|
|
69
|
-
const resetState = () => {
|
|
70
|
-
setIsDeletingKeyword(false);
|
|
71
|
-
setKeywordToDeleteId('');
|
|
72
|
-
};
|
|
73
|
-
(0, react_1.useEffect)(() => {
|
|
74
|
-
document.addEventListener('mousedown', handleClick);
|
|
75
|
-
return () => {
|
|
76
|
-
document.removeEventListener('mousedown', handleClick);
|
|
77
|
-
};
|
|
78
|
-
}, []);
|
|
79
|
-
const actions = {
|
|
80
|
-
primary: {
|
|
81
|
-
action: handleCancel,
|
|
82
|
-
title: 'Cancel',
|
|
83
|
-
},
|
|
84
|
-
secondary: {
|
|
85
|
-
action: handleDelete,
|
|
86
|
-
title: 'Delete',
|
|
87
|
-
},
|
|
88
|
-
};
|
|
89
|
-
return (react_1.default.createElement(style_guide_1.Dialog, { isOpen: isDeletingKeyword, actions: actions, category: style_guide_1.Category.confirmation, header: 'Delete Keyword', message: `Are you sure you want to delete "${keywordToDelete}" keyword?
|
|
90
|
-
` }));
|
|
91
|
-
};
|
|
92
|
-
exports.DeleteKeyword = DeleteKeyword;
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*!
|
|
3
|
-
* © 2019 Atypon Systems LLC
|
|
4
|
-
*
|
|
5
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
-
* you may not use this file except in compliance with the License.
|
|
7
|
-
* You may obtain a copy of the License at
|
|
8
|
-
*
|
|
9
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
-
*
|
|
11
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
-
* See the License for the specific language governing permissions and
|
|
15
|
-
* limitations under the License.
|
|
16
|
-
*/
|
|
17
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
18
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
19
|
-
};
|
|
20
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
-
exports.keywordsKey = void 0;
|
|
22
|
-
const CloseIconDark_1 = __importDefault(require("@manuscripts/assets/react/CloseIconDark"));
|
|
23
|
-
const json_schema_1 = require("@manuscripts/json-schema");
|
|
24
|
-
const transform_1 = require("@manuscripts/transform");
|
|
25
|
-
const prosemirror_state_1 = require("prosemirror-state");
|
|
26
|
-
const prosemirror_view_1 = require("prosemirror-view");
|
|
27
|
-
const react_1 = require("react");
|
|
28
|
-
const react_dom_1 = __importDefault(require("react-dom"));
|
|
29
|
-
const track_changes_utils_1 = require("../lib/track-changes-utils");
|
|
30
|
-
exports.keywordsKey = new prosemirror_state_1.PluginKey('keywords');
|
|
31
|
-
const isKeywordNode = (node) => node.type === node.type.schema.nodes.keyword;
|
|
32
|
-
const buildKeywordNodes = (doc) => {
|
|
33
|
-
const keywordNodes = [];
|
|
34
|
-
doc.descendants((node, pos) => {
|
|
35
|
-
if (isKeywordNode(node)) {
|
|
36
|
-
keywordNodes.push([node, pos]);
|
|
37
|
-
}
|
|
38
|
-
});
|
|
39
|
-
return keywordNodes;
|
|
40
|
-
};
|
|
41
|
-
const keywordsUpdated = (transactions) => transactions.some((tr) => {
|
|
42
|
-
const metaDeleted = tr.getMeta('keywordsUpdated');
|
|
43
|
-
return metaDeleted;
|
|
44
|
-
});
|
|
45
|
-
const buildDecorations = (keywordNodes, getCapabilities) => {
|
|
46
|
-
const decorations = [];
|
|
47
|
-
for (const [node, pos] of keywordNodes) {
|
|
48
|
-
const nodeClasses = [...(0, track_changes_utils_1.getChangeClasses)(node)];
|
|
49
|
-
if (!(0, track_changes_utils_1.isTracked)(node)) {
|
|
50
|
-
nodeClasses.push('no-tracking');
|
|
51
|
-
}
|
|
52
|
-
const classesDecoration = prosemirror_view_1.Decoration.node(pos, pos + node.nodeSize, {
|
|
53
|
-
class: nodeClasses.join(' '),
|
|
54
|
-
});
|
|
55
|
-
decorations.push(classesDecoration);
|
|
56
|
-
if (!(0, track_changes_utils_1.isPending)(node) && !(0, track_changes_utils_1.isDeleted)(node) && getCapabilities().editArticle) {
|
|
57
|
-
const removeIconDecoration = prosemirror_view_1.Decoration.widget(pos + node.nodeSize - 1, () => {
|
|
58
|
-
const closeIconWrapper = document.createElement('span');
|
|
59
|
-
closeIconWrapper.classList.add('delete-keyword');
|
|
60
|
-
react_dom_1.default.render((0, react_1.createElement)(CloseIconDark_1.default, {
|
|
61
|
-
height: 8,
|
|
62
|
-
width: 8,
|
|
63
|
-
color: '#353535',
|
|
64
|
-
}), closeIconWrapper);
|
|
65
|
-
return closeIconWrapper;
|
|
66
|
-
}, { side: -1 });
|
|
67
|
-
decorations.push(removeIconDecoration);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
return decorations;
|
|
71
|
-
};
|
|
72
|
-
exports.default = (props) => {
|
|
73
|
-
return new prosemirror_state_1.Plugin({
|
|
74
|
-
key: exports.keywordsKey,
|
|
75
|
-
state: {
|
|
76
|
-
init(config, instance) {
|
|
77
|
-
const keywordNodes = buildKeywordNodes(instance.doc);
|
|
78
|
-
return {
|
|
79
|
-
keywordNodes,
|
|
80
|
-
};
|
|
81
|
-
},
|
|
82
|
-
apply(tr, value, oldState, newState) {
|
|
83
|
-
const keywordNodes = buildKeywordNodes(newState.doc);
|
|
84
|
-
return {
|
|
85
|
-
keywordNodes,
|
|
86
|
-
};
|
|
87
|
-
},
|
|
88
|
-
},
|
|
89
|
-
appendTransaction(transactions, oldState, newState) {
|
|
90
|
-
if (!keywordsUpdated(transactions)) {
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
const keywordsElements = [];
|
|
94
|
-
const { tr } = newState;
|
|
95
|
-
tr.doc.descendants((node, pos) => {
|
|
96
|
-
if (node.type === node.type.schema.nodes.keywords_element) {
|
|
97
|
-
keywordsElements.push({
|
|
98
|
-
node,
|
|
99
|
-
pos,
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
});
|
|
103
|
-
if (keywordsElements.length) {
|
|
104
|
-
for (const { node, pos } of keywordsElements) {
|
|
105
|
-
tr.setNodeMarkup(pos, undefined, Object.assign(Object.assign({}, node.attrs), { id: node.attrs.id || (0, transform_1.generateID)(json_schema_1.ObjectTypes.KeywordsElement) }));
|
|
106
|
-
}
|
|
107
|
-
if (tr.selection instanceof prosemirror_state_1.NodeSelection) {
|
|
108
|
-
tr.setSelection(prosemirror_state_1.NodeSelection.create(tr.doc, tr.selection.from));
|
|
109
|
-
}
|
|
110
|
-
tr.setMeta('origin', exports.keywordsKey);
|
|
111
|
-
return tr;
|
|
112
|
-
}
|
|
113
|
-
},
|
|
114
|
-
props: {
|
|
115
|
-
decorations(state) {
|
|
116
|
-
const { keywordNodes } = exports.keywordsKey.getState(state);
|
|
117
|
-
return prosemirror_view_1.DecorationSet.create(state.doc, buildDecorations(keywordNodes, props.getCapabilities));
|
|
118
|
-
},
|
|
119
|
-
},
|
|
120
|
-
});
|
|
121
|
-
};
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { Category, Dialog } from '@manuscripts/style-guide';
|
|
2
|
-
import React, { useEffect, useState } from 'react';
|
|
3
|
-
export const DeleteKeyword = ({ viewProps }) => {
|
|
4
|
-
const [isDeletingKeyword, setIsDeletingKeyword] = useState(false);
|
|
5
|
-
const [keywordToDelete, setKeywordToDelete] = useState('');
|
|
6
|
-
const [keywordToDeleteId, setKeywordToDeleteId] = useState('');
|
|
7
|
-
const { getPos, view, node } = viewProps;
|
|
8
|
-
const getKeywords = () => {
|
|
9
|
-
let position = 0, elementSize = 0;
|
|
10
|
-
node.descendants((node, pos) => {
|
|
11
|
-
if (node.attrs.id === keywordToDeleteId) {
|
|
12
|
-
position = pos + getPos();
|
|
13
|
-
elementSize = node.nodeSize;
|
|
14
|
-
return false;
|
|
15
|
-
}
|
|
16
|
-
});
|
|
17
|
-
return { pos: position, to: position + elementSize + 1 };
|
|
18
|
-
};
|
|
19
|
-
const handleClick = (event) => {
|
|
20
|
-
var _a, _b;
|
|
21
|
-
const clickTarget = event.target;
|
|
22
|
-
const deleteIcon = clickTarget.closest('.delete-keyword');
|
|
23
|
-
if (deleteIcon) {
|
|
24
|
-
const keywordId = ((_a = deleteIcon.closest('.keyword')) === null || _a === void 0 ? void 0 : _a.getAttribute('id')) || '';
|
|
25
|
-
const keywordContent = ((_b = deleteIcon.closest('.keyword')) === null || _b === void 0 ? void 0 : _b.textContent) || '';
|
|
26
|
-
setKeywordToDeleteId(keywordId);
|
|
27
|
-
setKeywordToDelete(keywordContent);
|
|
28
|
-
setIsDeletingKeyword(true);
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
const handleCancel = () => {
|
|
32
|
-
resetState();
|
|
33
|
-
};
|
|
34
|
-
const handleDelete = () => {
|
|
35
|
-
if (keywordToDeleteId) {
|
|
36
|
-
const { pos, to } = getKeywords();
|
|
37
|
-
if (view.dispatch) {
|
|
38
|
-
view.dispatch(view.state.tr.delete(pos, to).setMeta('keywordsUpdated', true));
|
|
39
|
-
}
|
|
40
|
-
resetState();
|
|
41
|
-
}
|
|
42
|
-
};
|
|
43
|
-
const resetState = () => {
|
|
44
|
-
setIsDeletingKeyword(false);
|
|
45
|
-
setKeywordToDeleteId('');
|
|
46
|
-
};
|
|
47
|
-
useEffect(() => {
|
|
48
|
-
document.addEventListener('mousedown', handleClick);
|
|
49
|
-
return () => {
|
|
50
|
-
document.removeEventListener('mousedown', handleClick);
|
|
51
|
-
};
|
|
52
|
-
}, []);
|
|
53
|
-
const actions = {
|
|
54
|
-
primary: {
|
|
55
|
-
action: handleCancel,
|
|
56
|
-
title: 'Cancel',
|
|
57
|
-
},
|
|
58
|
-
secondary: {
|
|
59
|
-
action: handleDelete,
|
|
60
|
-
title: 'Delete',
|
|
61
|
-
},
|
|
62
|
-
};
|
|
63
|
-
return (React.createElement(Dialog, { isOpen: isDeletingKeyword, actions: actions, category: Category.confirmation, header: 'Delete Keyword', message: `Are you sure you want to delete "${keywordToDelete}" keyword?
|
|
64
|
-
` }));
|
|
65
|
-
};
|
|
@@ -1,115 +0,0 @@
|
|
|
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 CloseIconDark from '@manuscripts/assets/react/CloseIconDark';
|
|
17
|
-
import { ObjectTypes } from '@manuscripts/json-schema';
|
|
18
|
-
import { generateID } from '@manuscripts/transform';
|
|
19
|
-
import { NodeSelection, Plugin, PluginKey, } from 'prosemirror-state';
|
|
20
|
-
import { Decoration, DecorationSet } from 'prosemirror-view';
|
|
21
|
-
import { createElement } from 'react';
|
|
22
|
-
import ReactDOM from 'react-dom';
|
|
23
|
-
import { getChangeClasses, isDeleted, isPending, isTracked, } from '../lib/track-changes-utils';
|
|
24
|
-
export const keywordsKey = new PluginKey('keywords');
|
|
25
|
-
const isKeywordNode = (node) => node.type === node.type.schema.nodes.keyword;
|
|
26
|
-
const buildKeywordNodes = (doc) => {
|
|
27
|
-
const keywordNodes = [];
|
|
28
|
-
doc.descendants((node, pos) => {
|
|
29
|
-
if (isKeywordNode(node)) {
|
|
30
|
-
keywordNodes.push([node, pos]);
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
return keywordNodes;
|
|
34
|
-
};
|
|
35
|
-
const keywordsUpdated = (transactions) => transactions.some((tr) => {
|
|
36
|
-
const metaDeleted = tr.getMeta('keywordsUpdated');
|
|
37
|
-
return metaDeleted;
|
|
38
|
-
});
|
|
39
|
-
const buildDecorations = (keywordNodes, getCapabilities) => {
|
|
40
|
-
const decorations = [];
|
|
41
|
-
for (const [node, pos] of keywordNodes) {
|
|
42
|
-
const nodeClasses = [...getChangeClasses(node)];
|
|
43
|
-
if (!isTracked(node)) {
|
|
44
|
-
nodeClasses.push('no-tracking');
|
|
45
|
-
}
|
|
46
|
-
const classesDecoration = Decoration.node(pos, pos + node.nodeSize, {
|
|
47
|
-
class: nodeClasses.join(' '),
|
|
48
|
-
});
|
|
49
|
-
decorations.push(classesDecoration);
|
|
50
|
-
if (!isPending(node) && !isDeleted(node) && getCapabilities().editArticle) {
|
|
51
|
-
const removeIconDecoration = Decoration.widget(pos + node.nodeSize - 1, () => {
|
|
52
|
-
const closeIconWrapper = document.createElement('span');
|
|
53
|
-
closeIconWrapper.classList.add('delete-keyword');
|
|
54
|
-
ReactDOM.render(createElement(CloseIconDark, {
|
|
55
|
-
height: 8,
|
|
56
|
-
width: 8,
|
|
57
|
-
color: '#353535',
|
|
58
|
-
}), closeIconWrapper);
|
|
59
|
-
return closeIconWrapper;
|
|
60
|
-
}, { side: -1 });
|
|
61
|
-
decorations.push(removeIconDecoration);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
return decorations;
|
|
65
|
-
};
|
|
66
|
-
export default (props) => {
|
|
67
|
-
return new Plugin({
|
|
68
|
-
key: keywordsKey,
|
|
69
|
-
state: {
|
|
70
|
-
init(config, instance) {
|
|
71
|
-
const keywordNodes = buildKeywordNodes(instance.doc);
|
|
72
|
-
return {
|
|
73
|
-
keywordNodes,
|
|
74
|
-
};
|
|
75
|
-
},
|
|
76
|
-
apply(tr, value, oldState, newState) {
|
|
77
|
-
const keywordNodes = buildKeywordNodes(newState.doc);
|
|
78
|
-
return {
|
|
79
|
-
keywordNodes,
|
|
80
|
-
};
|
|
81
|
-
},
|
|
82
|
-
},
|
|
83
|
-
appendTransaction(transactions, oldState, newState) {
|
|
84
|
-
if (!keywordsUpdated(transactions)) {
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
const keywordsElements = [];
|
|
88
|
-
const { tr } = newState;
|
|
89
|
-
tr.doc.descendants((node, pos) => {
|
|
90
|
-
if (node.type === node.type.schema.nodes.keywords_element) {
|
|
91
|
-
keywordsElements.push({
|
|
92
|
-
node,
|
|
93
|
-
pos,
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
});
|
|
97
|
-
if (keywordsElements.length) {
|
|
98
|
-
for (const { node, pos } of keywordsElements) {
|
|
99
|
-
tr.setNodeMarkup(pos, undefined, Object.assign(Object.assign({}, node.attrs), { id: node.attrs.id || generateID(ObjectTypes.KeywordsElement) }));
|
|
100
|
-
}
|
|
101
|
-
if (tr.selection instanceof NodeSelection) {
|
|
102
|
-
tr.setSelection(NodeSelection.create(tr.doc, tr.selection.from));
|
|
103
|
-
}
|
|
104
|
-
tr.setMeta('origin', keywordsKey);
|
|
105
|
-
return tr;
|
|
106
|
-
}
|
|
107
|
-
},
|
|
108
|
-
props: {
|
|
109
|
-
decorations(state) {
|
|
110
|
-
const { keywordNodes } = keywordsKey.getState(state);
|
|
111
|
-
return DecorationSet.create(state.doc, buildDecorations(keywordNodes, props.getCapabilities));
|
|
112
|
-
},
|
|
113
|
-
},
|
|
114
|
-
});
|
|
115
|
-
};
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { ManuscriptEditorView, ManuscriptNode } from '@manuscripts/transform';
|
|
2
|
-
import React from 'react';
|
|
3
|
-
export declare const DeleteKeyword: React.FC<{
|
|
4
|
-
viewProps: {
|
|
5
|
-
view: ManuscriptEditorView;
|
|
6
|
-
getPos: () => number;
|
|
7
|
-
node: ManuscriptNode;
|
|
8
|
-
};
|
|
9
|
-
getUpdatedNode: () => ManuscriptNode;
|
|
10
|
-
}>;
|
|
@@ -1,28 +0,0 @@
|
|
|
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 type { KeywordNode } from '@manuscripts/transform';
|
|
18
|
-
import { Plugin, PluginKey } from 'prosemirror-state';
|
|
19
|
-
export declare const keywordsKey: PluginKey<any>;
|
|
20
|
-
interface PluginState {
|
|
21
|
-
keywordNodes: KeywordNodes;
|
|
22
|
-
}
|
|
23
|
-
interface KeywordsProps {
|
|
24
|
-
getCapabilities: () => Capabilities;
|
|
25
|
-
}
|
|
26
|
-
type KeywordNodes = Array<[KeywordNode, number]>;
|
|
27
|
-
declare const _default: (props: KeywordsProps) => Plugin<PluginState>;
|
|
28
|
-
export default _default;
|