@eeacms/volto-slate-footnote 3.0.0 → 4.0.0

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.
@@ -1,5 +1,6 @@
1
1
  import config from '@plone/volto/registry';
2
2
  import { Node } from 'slate';
3
+ import { getAllBlocks } from 'volto-slate/utils';
3
4
 
4
5
  /**
5
6
  * remove <?xml version="1.0"?> from the string
@@ -12,6 +13,46 @@ export const makeFootnote = (footnote) => {
12
13
  return free;
13
14
  };
14
15
 
16
+ /**
17
+ * Extends volto-slate getAllBlocks functionality also to SlateJSONFields
18
+ * inserted within blocks via Metadata / Metadata section block
19
+ * @param {Object} properties metadata properties received by the View component
20
+ * @returns {Array} Returns a flat array of blocks and slate fields
21
+ */
22
+ export const getAllBlocksAndSlateFields = (properties) => {
23
+ const blocks = getAllBlocks(properties, []);
24
+ const flat_blocks = [];
25
+ for (const b_idx in blocks) {
26
+ const block = blocks[b_idx];
27
+ if (block['@type'] === 'metadataSection') {
28
+ const fields = block.fields;
29
+ for (const f_idx in fields) {
30
+ const field = fields[f_idx];
31
+ if (field?.field?.widget === 'slate') {
32
+ const field_id = field.field.id;
33
+ flat_blocks.push({
34
+ '@type': 'slate',
35
+ id: field_id,
36
+ value: properties[field_id]?.length ? properties[field_id] : null,
37
+ });
38
+ }
39
+ }
40
+ } else if (block['@type'] === 'metadata') {
41
+ if (block?.data?.widget === 'slate') {
42
+ const f_id = block.data.id;
43
+ flat_blocks.push({
44
+ '@type': 'slate',
45
+ id: f_id,
46
+ value: properties[f_id]?.length ? properties[f_id] : null,
47
+ });
48
+ }
49
+ } else {
50
+ flat_blocks.push(block);
51
+ }
52
+ }
53
+ return flat_blocks;
54
+ };
55
+
15
56
  /**
16
57
  * Will make an object with keys for every zoteroId and some uid that are unique
17
58
  * or referenced multiple times
@@ -34,37 +75,28 @@ export const makeFootnoteListOfUniqueItems = (blocks) => {
34
75
  if (footnotes.includes(node.type) && node.data) {
35
76
  // for citations (Zotero items) create refs for same zoteroId
36
77
  if (node.data.zoteroId) {
37
- if (!notesObjResult[node.data.zoteroId]) {
38
- notesObjResult[node.data.zoteroId] = {
39
- ...node.data,
40
- };
41
- } else if (notesObjResult[node.data.zoteroId].refs) {
42
- notesObjResult[node.data.zoteroId].refs[node.data.uid] = true;
43
- } else {
44
- // add its own uid in refs for easier parsing in html
45
- notesObjResult[node.data.zoteroId].refs = {
46
- [notesObjResult[node.data.zoteroId].uid]: true,
47
- [node.data.uid]: true,
48
- };
78
+ iterateZoteroObj(notesObjResult, node.data);
79
+ // itereate the extra obj for multiple citations
80
+ if (node.data.extra) {
81
+ node.data.extra.forEach((zoteroObjItem) =>
82
+ // send the uid of the parent
83
+ // of the word the will have the reference indice
84
+ iterateZoteroObj(notesObjResult, zoteroObjItem, node.data.uid),
85
+ );
49
86
  }
50
87
  // for footnotes - create refs, on identical text
51
- } else {
52
- const found = Object.keys(notesObjResult).find(
53
- (noteId) =>
54
- notesObjResult[noteId].footnote === node.data.footnote,
88
+ } else if (node.data.extra) {
89
+ iterateFootnoteObj(notesObjResult, node.data);
90
+ node.data.extra.forEach((footnoteObjItem) =>
91
+ // since is called in case of extra, the parent is needed
92
+ iterateFootnoteObj(
93
+ notesObjResult,
94
+ footnoteObjItem,
95
+ node.data.uid,
96
+ ),
55
97
  );
56
-
57
- if (!found) {
58
- notesObjResult[node.data.uid] = { ...node.data };
59
- } else if (notesObjResult[found].refs) {
60
- notesObjResult[found].refs[node.data.uid] = true;
61
- } else {
62
- // add its own uid in refs for easier parsing in html
63
- notesObjResult[found].refs = {
64
- [notesObjResult[found].uid]: true,
65
- [node.data.uid]: true,
66
- };
67
- }
98
+ } else {
99
+ iterateFootnoteObj(notesObjResult, node.data);
68
100
  }
69
101
  }
70
102
  });
@@ -72,3 +104,69 @@ export const makeFootnoteListOfUniqueItems = (blocks) => {
72
104
 
73
105
  return notesObjResult;
74
106
  };
107
+
108
+ /**
109
+ * Will change the notesObjResultTemp to add new property if the zoteroId is new or add to the existing ones refs
110
+ * @param {Object} notesObjResultTemp - the object that will configure the zotero items
111
+ * @param {Object} zoteroObj - the footnote object
112
+ * @param {string} zoteroObj.zoteroId - id of the zotero citation
113
+ * @param {string} zoteroObj.uid - id of the slate item
114
+ * @param {string} zoteroObj.footnote - xml citation from zotero
115
+ * @param {string} parentUid - will be needed because html element (the word) that references multiple citations
116
+ * will have the id as the main uid, the ids from the extra will not matter in this case
117
+ */
118
+ const iterateZoteroObj = (notesObjResultTemp, zoteroObj, parentUid) => {
119
+ const uid = parentUid || zoteroObj.uid;
120
+ // add new zoteroId
121
+ if (!notesObjResultTemp[zoteroObj.zoteroId]) {
122
+ notesObjResultTemp[zoteroObj.zoteroId] = {
123
+ ...zoteroObj,
124
+ uid,
125
+ };
126
+ // if zoteroId and refs exist then add the uid to the refs
127
+ } else if (notesObjResultTemp[zoteroObj.zoteroId].refs) {
128
+ notesObjResultTemp[zoteroObj.zoteroId].refs[uid] = true;
129
+ } else {
130
+ // if zoteroId exists but not refs, add its own uid also in refs for easier parsing in html
131
+ notesObjResultTemp[zoteroObj.zoteroId].refs = {
132
+ [notesObjResultTemp[zoteroObj.zoteroId].uid]: true,
133
+ [uid]: true,
134
+ };
135
+ }
136
+ };
137
+
138
+ /**
139
+ * Will change the notesObjResultTemp to add new property if the footnote uid is new or add to the refs of the existing ones
140
+ * Some footnotes will always be in extra, so we need parentId to know where to find it in render
141
+ * @param {Object} notesObjResultTemp - the object that will configure the zotero items
142
+ * @param {Object} node - the footnote object
143
+ * @param {string} node.zoteroId - id of the zotero citation
144
+ * @param {string} node.parentUid - id of the parent footnote
145
+ * @param {string} node.uid - id of the slate item
146
+ * @param {string} node.footnote - xml citation from zotero
147
+ * @param {string} parentUid - will be needed because html element (the word) that references multiple citations
148
+ * will have the id as the main uid, the ids from the extra will not matter in this case
149
+ */
150
+ const iterateFootnoteObj = (notesObjResultTemp, node, parentUid) => {
151
+ const uid = parentUid || node.uid;
152
+ const found = Object.keys(notesObjResultTemp).find((noteId) => {
153
+ return notesObjResultTemp[noteId].footnote === node.footnote;
154
+ });
155
+ // has not yet been added
156
+ if (!found) {
157
+ // will use the parentUid instead of own uid for render to be able to reference to the correct element
158
+ //(word containing the footnotes)
159
+ notesObjResultTemp[node.uid] = parentUid
160
+ ? { ...node, parentUid }
161
+ : { ...node };
162
+ // the element is found, just add it's own uid to the list of refs, the parent is already known
163
+ } else if (notesObjResultTemp[found].refs) {
164
+ notesObjResultTemp[found].refs[node.uid] = true;
165
+ } else {
166
+ // element found but doesn't have refs yet, this means that it is a parent, so add it's existing uid and the current one
167
+ notesObjResultTemp[found].refs = {
168
+ [notesObjResultTemp[found].uid]: true,
169
+ [uid]: true,
170
+ };
171
+ }
172
+ };
package/src/index.js CHANGED
@@ -5,7 +5,7 @@ import FootnotesBlockEdit from './Blocks/Footnote/FootnotesBlockEdit';
5
5
  import FootnotesBlockSchema from './Blocks/Footnote/FootnotesBlockSchema';
6
6
  import { FOOTNOTE } from './constants';
7
7
  import installFootnoteEditor from './editor';
8
- import SearchWidget from '@eeacms/volto-slate-footnote/editor/SearchWidget';
8
+ import SearchWidget from '@eeacms/volto-slate-footnote/editor/MultiSelectSearchWidget';
9
9
 
10
10
  /**
11
11
  * @summary Called from Volto to configure new or existing Volto block types.
@@ -1,36 +0,0 @@
1
- import { setupBeforeEach, tearDownAfterEach } from '../support';
2
-
3
- describe('Blocks Tests', () => {
4
- beforeEach(setupBeforeEach);
5
- afterEach(tearDownAfterEach);
6
-
7
- it('Add Block: Empty', () => {
8
- // Change page title
9
- cy.get('.documentFirstHeading > .public-DraftStyleDefault-block')
10
- .clear()
11
- .type('My Add-on Page')
12
- .get('.documentFirstHeading span[data-text]')
13
- .contains('My Add-on Page');
14
-
15
- cy.get('.documentFirstHeading > .public-DraftStyleDefault-block').type(
16
- '{enter}',
17
- );
18
-
19
- // Add block
20
- cy.get('.ui.basic.icon.button.block-add-button').first().click();
21
- cy.get('.blocks-chooser .title').contains('Text').click();
22
- cy.get('.content.active.text .button.slateFootnotes').contains('Footnotes').click();
23
-
24
- // Configure block
25
- cy.get('[id=sidebar-properties] [name=title]').click().type('Footnotes');
26
- cy.get('[id=sidebar-properties] label[for=field-global]').click();
27
-
28
- // Save
29
- cy.get('#toolbar-save').click();
30
- cy.url().should('eq', Cypress.config().baseUrl + '/cypress/my-page');
31
-
32
- // then the page view should contain our changes
33
- cy.contains('My Add-on Page');
34
- cy.contains('Footnotes');
35
- });
36
- });
@@ -1,63 +0,0 @@
1
- import { setupBeforeEach, tearDownAfterEach } from '../support';
2
-
3
- describe('Blocks Tests', () => {
4
- beforeEach(setupBeforeEach);
5
- afterEach(tearDownAfterEach);
6
-
7
- it('Add Block and create footnote', () => {
8
- // Change page title
9
- cy.get('.documentFirstHeading > .public-DraftStyleDefault-block')
10
- .clear()
11
- .type('My Add-on Page')
12
- .get('.documentFirstHeading span[data-text]')
13
- .contains('My Add-on Page');
14
-
15
- cy.get('.documentFirstHeading > .public-DraftStyleDefault-block').type(
16
- '{enter}',
17
- );
18
-
19
- // Add some text with footnotes
20
- cy.get('.slate-editor [contenteditable=true]')
21
- .focus()
22
- .click()
23
- .wait(1000)
24
- .type('Colorless green ideas sleep furiously.');
25
-
26
- cy.get('.slate-editor.selected [contenteditable=true]').setSelection(
27
- 'furiously',
28
- );
29
-
30
- cy.wait(1000);
31
-
32
- cy.get('.slate-inline-toolbar .button-wrapper a[title="Footnote"]').click();
33
- cy.get('.sidebar-container [id=field-footnote]').click().type('Citation');
34
- cy.get('.sidebar-container .form .header button:first-of-type').click();
35
-
36
- // Add block
37
- cy.get('.slate-editor [contenteditable=true]')
38
- .focus()
39
- .click()
40
- .wait(1000)
41
- .type('{enter}');
42
-
43
- cy.get('.ui.basic.icon.button.block-add-button').first().click();
44
- cy.get('.blocks-chooser .title').contains('Text').click();
45
- cy.get('.content.active.text .button.slateFootnotes')
46
- .contains('Footnotes')
47
- .click();
48
-
49
- // Configure block
50
- cy.get('[id=sidebar-properties] [name=title]').click().type('Footnotes');
51
- cy.get('[id=sidebar-properties] label[for=field-global]').click();
52
-
53
- // Save
54
- cy.get('#toolbar-save').click();
55
- cy.url().should('eq', Cypress.config().baseUrl + '/cypress/my-page');
56
-
57
- // then the page view should contain our changes
58
- cy.contains('My Add-on Page');
59
- cy.get('span.citation-item').contains('furiously');
60
- cy.contains('Footnotes');
61
- cy.contains('Citation');
62
- });
63
- });