@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.
- package/CHANGELOG.md +39 -1
- package/Jenkinsfile +1 -1
- package/cypress/integration/01-slate-footnote-block.js +80 -0
- package/cypress/support/commands.js +171 -1
- package/cypress/support/index.js +79 -5
- package/cypress.json +6 -1
- package/package.json +1 -1
- package/src/Blocks/Footnote/FootnotesBlockView.jsx +34 -10
- package/src/editor/FootnoteEditor.jsx +48 -16
- package/src/editor/MultiSelectSearchWidget.jsx +150 -0
- package/src/editor/extensions.js +1 -2
- package/src/editor/render.jsx +219 -40
- package/src/editor/styles.less +3 -27
- package/src/editor/utils.js +126 -28
- package/src/index.js +1 -1
- package/cypress/integration/01-block-basics.js +0 -36
- package/cypress/integration/02-block-slate.js +0 -63
package/CHANGELOG.md
CHANGED
|
@@ -4,8 +4,46 @@ All notable changes to this project will be documented in this file. Dates are d
|
|
|
4
4
|
|
|
5
5
|
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
6
6
|
|
|
7
|
-
#### [
|
|
7
|
+
#### [4.0.0](https://github.com/eea/volto-slate-footnote/compare/3.2.0...4.0.0)
|
|
8
8
|
|
|
9
|
+
- Use new slate namespaced pluginids [`#23`](https://github.com/eea/volto-slate-footnote/pull/23)
|
|
10
|
+
- Add Sonarqube tag using climate-energy-frontend addons list [`80a159b`](https://github.com/eea/volto-slate-footnote/commit/80a159bb67698cddedadc494e7ae2da32a96faea)
|
|
11
|
+
|
|
12
|
+
#### [3.2.0](https://github.com/eea/volto-slate-footnote/compare/3.1.1...3.2.0)
|
|
13
|
+
|
|
14
|
+
> 13 September 2021
|
|
15
|
+
|
|
16
|
+
- Release Multiple citations (#20) [`#21`](https://github.com/eea/volto-slate-footnote/pull/21)
|
|
17
|
+
- Multiple citations [`#20`](https://github.com/eea/volto-slate-footnote/pull/20)
|
|
18
|
+
- Release 3.2.0 [`6795fcd`](https://github.com/eea/volto-slate-footnote/commit/6795fcd1a4fc429bb70334fbdfa2cb0eedd748fa)
|
|
19
|
+
|
|
20
|
+
#### [3.1.1](https://github.com/eea/volto-slate-footnote/compare/3.1.0...3.1.1)
|
|
21
|
+
|
|
22
|
+
> 10 September 2021
|
|
23
|
+
|
|
24
|
+
- Citations in metadata [`#19`](https://github.com/eea/volto-slate-footnote/pull/19)
|
|
25
|
+
- Citations in metadata [`#18`](https://github.com/eea/volto-slate-footnote/pull/18)
|
|
26
|
+
- Remove console.log [`b5d83e7`](https://github.com/eea/volto-slate-footnote/commit/b5d83e7c13240151f602d122ecf09ba9b8e335f3)
|
|
27
|
+
- Fix slate json field default value in DX layout [`f2805bb`](https://github.com/eea/volto-slate-footnote/commit/f2805bbc15c51ebd914ee5f4eb9dd34ef32e095b)
|
|
28
|
+
- Fix cypress api_url [`6a4966a`](https://github.com/eea/volto-slate-footnote/commit/6a4966a2f92e932e1d0df35351989cda535f15c8)
|
|
29
|
+
- Add Sonarqube tag using ims-frontend addons list [`aed3984`](https://github.com/eea/volto-slate-footnote/commit/aed39840ecd467689eaf0adb352bd00ce95bdbbe)
|
|
30
|
+
|
|
31
|
+
#### [3.1.0](https://github.com/eea/volto-slate-footnote/compare/3.0.0...3.1.0)
|
|
32
|
+
|
|
33
|
+
> 9 September 2021
|
|
34
|
+
|
|
35
|
+
- Release [`#17`](https://github.com/eea/volto-slate-footnote/pull/17)
|
|
36
|
+
- render elements with multiple citations [`#15`](https://github.com/eea/volto-slate-footnote/pull/15)
|
|
37
|
+
- make accordion reference toggle when clicking citations refs #137423 [`#16`](https://github.com/eea/volto-slate-footnote/pull/16)
|
|
38
|
+
- Release 3.1.0 [`d87a1b0`](https://github.com/eea/volto-slate-footnote/commit/d87a1b0b893bb8fc090dcde193d3ac628471c352)
|
|
39
|
+
- Fix cypress tests [`cb08192`](https://github.com/eea/volto-slate-footnote/commit/cb08192508964c274eaaed3dab2d2c5392c43d2d)
|
|
40
|
+
|
|
41
|
+
### [3.0.0](https://github.com/eea/volto-slate-footnote/compare/2.4.0...3.0.0)
|
|
42
|
+
|
|
43
|
+
> 3 September 2021
|
|
44
|
+
|
|
45
|
+
- Release 3.0.0 [`#14`](https://github.com/eea/volto-slate-footnote/pull/14)
|
|
46
|
+
- Cypress increase wait time [`06fe6e9`](https://github.com/eea/volto-slate-footnote/commit/06fe6e9cea79dc3a5d2a3e88db8d3cc35b967da3)
|
|
9
47
|
- Update package metadata [`8d45704`](https://github.com/eea/volto-slate-footnote/commit/8d457042b24f4795eb453baebcb0bf0f6740d153)
|
|
10
48
|
- Make it work with DX metadata [`a5139d2`](https://github.com/eea/volto-slate-footnote/commit/a5139d2af0e7947ba16d7c28912565683726554f)
|
|
11
49
|
|
package/Jenkinsfile
CHANGED
|
@@ -4,7 +4,7 @@ pipeline {
|
|
|
4
4
|
environment {
|
|
5
5
|
GIT_NAME = "volto-slate-footnote"
|
|
6
6
|
NAMESPACE = "@eeacms"
|
|
7
|
-
SONARQUBE_TAGS = "volto.eea.europa.eu,biodiversity.europa.eu"
|
|
7
|
+
SONARQUBE_TAGS = "volto.eea.europa.eu,biodiversity.europa.eu,www.eea.europa.eu-ims,climate-energy.eea.europa.eu"
|
|
8
8
|
DEPENDENCIES = ""
|
|
9
9
|
}
|
|
10
10
|
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { slateBeforeEach, slateAfterEach } from '../support';
|
|
2
|
+
|
|
3
|
+
describe('Slate citations', () => {
|
|
4
|
+
beforeEach(slateBeforeEach);
|
|
5
|
+
afterEach(slateAfterEach);
|
|
6
|
+
|
|
7
|
+
it('Add Footnotes block and create citation', () => {
|
|
8
|
+
// Complete chained commands
|
|
9
|
+
cy.getSlateEditorAndType('Colorless green ideas sleep furiously.');
|
|
10
|
+
|
|
11
|
+
// Footnote
|
|
12
|
+
cy.setSlateSelection('Colorless', 'green');
|
|
13
|
+
cy.clickSlateButton('Footnote');
|
|
14
|
+
|
|
15
|
+
cy.get('.sidebar-container .field-wrapper-footnote .react-select-container')
|
|
16
|
+
.click()
|
|
17
|
+
.type('Citation{enter}');
|
|
18
|
+
cy.get('.sidebar-container .form .header button:first-of-type').click();
|
|
19
|
+
|
|
20
|
+
// Add block
|
|
21
|
+
cy.getSlateEditorAndType('{enter}');
|
|
22
|
+
|
|
23
|
+
cy.get('.ui.basic.icon.button.block-add-button').first().click();
|
|
24
|
+
cy.get('.blocks-chooser .title').contains('Text').click();
|
|
25
|
+
cy.get('.content.active.text .button.slateFootnotes')
|
|
26
|
+
.contains('Footnotes')
|
|
27
|
+
.click();
|
|
28
|
+
|
|
29
|
+
// Configure block
|
|
30
|
+
cy.get('[id=sidebar-properties] [name=title]').click().type('Footnotes');
|
|
31
|
+
cy.get('[id=sidebar-properties] label[for=field-global]').click();
|
|
32
|
+
|
|
33
|
+
// Save
|
|
34
|
+
cy.get('#toolbar-save').click();
|
|
35
|
+
cy.url().should('eq', Cypress.config().baseUrl + '/cypress/my-page');
|
|
36
|
+
|
|
37
|
+
// then the page view should contain our changes
|
|
38
|
+
cy.get('span.citation-item').contains('Colorless green');
|
|
39
|
+
cy.contains('Footnotes');
|
|
40
|
+
cy.contains('Citation');
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('Add Footnotes block and create multiple citations', () => {
|
|
44
|
+
// Complete chained commands
|
|
45
|
+
cy.getSlateEditorAndType('Colorless green ideas sleep furiously.');
|
|
46
|
+
|
|
47
|
+
// Footnote
|
|
48
|
+
cy.setSlateSelection('Colorless', 'green');
|
|
49
|
+
cy.clickSlateButton('Footnote');
|
|
50
|
+
|
|
51
|
+
cy.get('.sidebar-container .field-wrapper-footnote .react-select-container')
|
|
52
|
+
.click()
|
|
53
|
+
.type('Citation{enter}')
|
|
54
|
+
.type('Yet another citation{enter}');
|
|
55
|
+
cy.get('.sidebar-container .form .header button:first-of-type').click();
|
|
56
|
+
|
|
57
|
+
// Add block
|
|
58
|
+
cy.getSlateEditorAndType('{enter}');
|
|
59
|
+
|
|
60
|
+
cy.get('.ui.basic.icon.button.block-add-button').first().click();
|
|
61
|
+
cy.get('.blocks-chooser .title').contains('Text').click();
|
|
62
|
+
cy.get('.content.active.text .button.slateFootnotes')
|
|
63
|
+
.contains('Footnotes')
|
|
64
|
+
.click();
|
|
65
|
+
|
|
66
|
+
// Configure block
|
|
67
|
+
cy.get('[id=sidebar-properties] [name=title]').click().type('Footnotes');
|
|
68
|
+
cy.get('[id=sidebar-properties] label[for=field-global]').click();
|
|
69
|
+
|
|
70
|
+
// Save
|
|
71
|
+
cy.get('#toolbar-save').click();
|
|
72
|
+
cy.url().should('eq', Cypress.config().baseUrl + '/cypress/my-page');
|
|
73
|
+
|
|
74
|
+
// then the page view should contain our changes
|
|
75
|
+
cy.get('span.citation-item').contains('Colorless green');
|
|
76
|
+
cy.contains('Footnotes');
|
|
77
|
+
cy.contains('Citation');
|
|
78
|
+
cy.contains('Yet another citation');
|
|
79
|
+
});
|
|
80
|
+
});
|
|
@@ -92,7 +92,7 @@ Cypress.Commands.add(
|
|
|
92
92
|
title: contentTitle,
|
|
93
93
|
blocks: {
|
|
94
94
|
'd3f1c443-583f-4e8e-a682-3bf25752a300': { '@type': 'title' },
|
|
95
|
-
'7624cf59-05d0-4055-8f55-5fd6597d84b0': { '@type': '
|
|
95
|
+
'7624cf59-05d0-4055-8f55-5fd6597d84b0': { '@type': 'slate' },
|
|
96
96
|
},
|
|
97
97
|
blocks_layout: {
|
|
98
98
|
items: [
|
|
@@ -125,6 +125,100 @@ Cypress.Commands.add(
|
|
|
125
125
|
},
|
|
126
126
|
);
|
|
127
127
|
|
|
128
|
+
// --- Add DX Content-Type ----------------------------------------------------------
|
|
129
|
+
Cypress.Commands.add('addContentType', (name) => {
|
|
130
|
+
let api_url, auth;
|
|
131
|
+
api_url = Cypress.env('API_PATH') || 'http://localhost:8080/Plone';
|
|
132
|
+
auth = {
|
|
133
|
+
user: 'admin',
|
|
134
|
+
pass: 'admin',
|
|
135
|
+
};
|
|
136
|
+
return cy
|
|
137
|
+
.request({
|
|
138
|
+
method: 'POST',
|
|
139
|
+
url: `${api_url}/@controlpanels/dexterity-types/${name}`,
|
|
140
|
+
headers: {
|
|
141
|
+
Accept: 'application/json',
|
|
142
|
+
},
|
|
143
|
+
auth: auth,
|
|
144
|
+
body: {
|
|
145
|
+
title: name,
|
|
146
|
+
},
|
|
147
|
+
})
|
|
148
|
+
.then(() => console.log(`${name} content-type added.`));
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
// --- Remove DX behavior ----------------------------------------------------------
|
|
152
|
+
Cypress.Commands.add('removeContentType', (name) => {
|
|
153
|
+
let api_url, auth;
|
|
154
|
+
api_url = Cypress.env('API_PATH') || 'http://localhost:8080/Plone';
|
|
155
|
+
auth = {
|
|
156
|
+
user: 'admin',
|
|
157
|
+
pass: 'admin',
|
|
158
|
+
};
|
|
159
|
+
return cy
|
|
160
|
+
.request({
|
|
161
|
+
method: 'DELETE',
|
|
162
|
+
url: `${api_url}/@controlpanels/dexterity-types/${name}`,
|
|
163
|
+
headers: {
|
|
164
|
+
Accept: 'application/json',
|
|
165
|
+
},
|
|
166
|
+
auth: auth,
|
|
167
|
+
body: {},
|
|
168
|
+
})
|
|
169
|
+
.then(() => console.log(`${name} content-type removed.`));
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
// --- Add DX field ----------------------------------------------------------
|
|
173
|
+
Cypress.Commands.add('addSlateJSONField', (type, name) => {
|
|
174
|
+
let api_url, auth;
|
|
175
|
+
api_url = Cypress.env('API_PATH') || 'http://localhost:8080/Plone';
|
|
176
|
+
auth = {
|
|
177
|
+
user: 'admin',
|
|
178
|
+
pass: 'admin',
|
|
179
|
+
};
|
|
180
|
+
return cy
|
|
181
|
+
.request({
|
|
182
|
+
method: 'POST',
|
|
183
|
+
url: `${api_url}/@types/${type}`,
|
|
184
|
+
headers: {
|
|
185
|
+
Accept: 'application/json',
|
|
186
|
+
},
|
|
187
|
+
auth: auth,
|
|
188
|
+
body: {
|
|
189
|
+
id: name,
|
|
190
|
+
title: name,
|
|
191
|
+
description: 'Slate JSON Field',
|
|
192
|
+
factory: 'SlateJSONField',
|
|
193
|
+
required: false,
|
|
194
|
+
},
|
|
195
|
+
})
|
|
196
|
+
.then(() => console.log(`${name} SlateJSONField field added to ${type}`));
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
// --- Remove DX field ----------------------------------------------------------
|
|
200
|
+
Cypress.Commands.add('removeSlateJSONField', (type, name) => {
|
|
201
|
+
let api_url, auth;
|
|
202
|
+
api_url = Cypress.env('API_PATH') || 'http://localhost:8080/Plone';
|
|
203
|
+
auth = {
|
|
204
|
+
user: 'admin',
|
|
205
|
+
pass: 'admin',
|
|
206
|
+
};
|
|
207
|
+
return cy
|
|
208
|
+
.request({
|
|
209
|
+
method: 'DELETE',
|
|
210
|
+
url: `${api_url}/@types/${type}/${name}`,
|
|
211
|
+
headers: {
|
|
212
|
+
Accept: 'application/json',
|
|
213
|
+
},
|
|
214
|
+
auth: auth,
|
|
215
|
+
body: {},
|
|
216
|
+
})
|
|
217
|
+
.then(() =>
|
|
218
|
+
console.log(`${name} SlateJSONField field removed from ${type}`),
|
|
219
|
+
);
|
|
220
|
+
});
|
|
221
|
+
|
|
128
222
|
// --- REMOVE CONTENT --------------------------------------------------------
|
|
129
223
|
Cypress.Commands.add('removeContent', (path) => {
|
|
130
224
|
let api_url, auth;
|
|
@@ -146,6 +240,41 @@ Cypress.Commands.add('removeContent', (path) => {
|
|
|
146
240
|
.then(() => console.log(`${path} removed`));
|
|
147
241
|
});
|
|
148
242
|
|
|
243
|
+
Cypress.Commands.add('typeInSlate', { prevSubject: true }, (subject, text) => {
|
|
244
|
+
return (
|
|
245
|
+
cy
|
|
246
|
+
.wrap(subject)
|
|
247
|
+
.then((subject) => {
|
|
248
|
+
subject[0].dispatchEvent(
|
|
249
|
+
new InputEvent('beforeinput', {
|
|
250
|
+
inputType: 'insertText',
|
|
251
|
+
data: text,
|
|
252
|
+
}),
|
|
253
|
+
);
|
|
254
|
+
return subject;
|
|
255
|
+
})
|
|
256
|
+
// TODO: do this only for Electron-based browser which does not understand instantaneously
|
|
257
|
+
// that the user inserted some text in the block
|
|
258
|
+
.wait(1000)
|
|
259
|
+
);
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
Cypress.Commands.add('lineBreakInSlate', { prevSubject: true }, (subject) => {
|
|
263
|
+
return (
|
|
264
|
+
cy
|
|
265
|
+
.wrap(subject)
|
|
266
|
+
.then((subject) => {
|
|
267
|
+
subject[0].dispatchEvent(
|
|
268
|
+
new InputEvent('beforeinput', { inputType: 'insertLineBreak' }),
|
|
269
|
+
);
|
|
270
|
+
return subject;
|
|
271
|
+
})
|
|
272
|
+
// TODO: do this only for Electron-based browser which does not understand instantaneously
|
|
273
|
+
// that the block was split
|
|
274
|
+
.wait(1000)
|
|
275
|
+
);
|
|
276
|
+
});
|
|
277
|
+
|
|
149
278
|
// --- SET WORKFLOW ----------------------------------------------------------
|
|
150
279
|
Cypress.Commands.add(
|
|
151
280
|
'setWorkflow',
|
|
@@ -247,6 +376,47 @@ Cypress.Commands.add(
|
|
|
247
376
|
},
|
|
248
377
|
);
|
|
249
378
|
|
|
379
|
+
Cypress.Commands.add('getSlateEditorAndType', (type) => {
|
|
380
|
+
cy.get('.content-area .slate-editor [contenteditable=true]')
|
|
381
|
+
.focus()
|
|
382
|
+
.click()
|
|
383
|
+
.wait(1000)
|
|
384
|
+
.type(type);
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
Cypress.Commands.add('setSlateSelection', (subject, query, endQuery) => {
|
|
388
|
+
cy.get('.slate-editor.selected [contenteditable=true]')
|
|
389
|
+
.focus()
|
|
390
|
+
.click()
|
|
391
|
+
.setSelection(subject, query, endQuery)
|
|
392
|
+
.wait(1000);
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
Cypress.Commands.add('setSlateCursor', (subject, query, endQuery) => {
|
|
396
|
+
cy.get('.slate-editor.selected [contenteditable=true]')
|
|
397
|
+
.focus()
|
|
398
|
+
.click()
|
|
399
|
+
.setCursor(subject, query, endQuery)
|
|
400
|
+
.wait(1000);
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
Cypress.Commands.add('clickSlateButton', (button) => {
|
|
404
|
+
cy.get(`.slate-inline-toolbar .button-wrapper a[title="${button}"]`).click();
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
Cypress.Commands.add('toolbarSave', () => {
|
|
408
|
+
cy.wait(1000);
|
|
409
|
+
|
|
410
|
+
// Save
|
|
411
|
+
cy.get('#toolbar-save').click();
|
|
412
|
+
cy.waitForResourceToLoad('@navigation');
|
|
413
|
+
cy.waitForResourceToLoad('@breadcrumbs');
|
|
414
|
+
cy.waitForResourceToLoad('@actions');
|
|
415
|
+
cy.waitForResourceToLoad('@types');
|
|
416
|
+
cy.waitForResourceToLoad('my-page');
|
|
417
|
+
cy.url().should('eq', Cypress.config().baseUrl + '/cypress/my-page');
|
|
418
|
+
});
|
|
419
|
+
|
|
250
420
|
// Low level command reused by `setCursorBefore` and `setCursorAfter`, equal to `setCursorAfter`
|
|
251
421
|
Cypress.Commands.add(
|
|
252
422
|
'setCursor',
|
package/cypress/support/index.js
CHANGED
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
|
|
16
16
|
// Import commands.js using ES2015 syntax:
|
|
17
17
|
import './commands';
|
|
18
|
-
|
|
19
18
|
// Alternatively you can use CommonJS syntax:
|
|
20
19
|
// require('./commands')
|
|
21
20
|
|
|
@@ -24,7 +23,7 @@ import './commands';
|
|
|
24
23
|
import '@cypress/code-coverage/support';
|
|
25
24
|
coverage-end */
|
|
26
25
|
|
|
27
|
-
export const
|
|
26
|
+
export const slateBeforeEach = (contentType = 'Document') => {
|
|
28
27
|
cy.autologin();
|
|
29
28
|
cy.createContent({
|
|
30
29
|
contentType: 'Folder',
|
|
@@ -32,7 +31,7 @@ export const setupBeforeEach = () => {
|
|
|
32
31
|
contentTitle: 'Cypress',
|
|
33
32
|
});
|
|
34
33
|
cy.createContent({
|
|
35
|
-
contentType:
|
|
34
|
+
contentType: contentType,
|
|
36
35
|
contentId: 'my-page',
|
|
37
36
|
contentTitle: 'My Page',
|
|
38
37
|
path: 'cypress',
|
|
@@ -44,10 +43,85 @@ export const setupBeforeEach = () => {
|
|
|
44
43
|
cy.waitForResourceToLoad('@types');
|
|
45
44
|
cy.waitForResourceToLoad('my-page');
|
|
46
45
|
cy.navigate('/cypress/my-page/edit');
|
|
47
|
-
cy.get(`.block.title [data-contents]`);
|
|
48
46
|
};
|
|
49
47
|
|
|
50
|
-
export const
|
|
48
|
+
export const slateAfterEach = () => {
|
|
51
49
|
cy.autologin();
|
|
52
50
|
cy.removeContent('cypress');
|
|
53
51
|
};
|
|
52
|
+
|
|
53
|
+
export const slateJsonBeforeEach = (contentType = 'slate') => {
|
|
54
|
+
cy.autologin();
|
|
55
|
+
cy.addContentType(contentType);
|
|
56
|
+
cy.addSlateJSONField(contentType, 'slate');
|
|
57
|
+
slateBeforeEach(contentType);
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export const slateJsonAfterEach = (contentType = 'slate') => {
|
|
61
|
+
cy.autologin();
|
|
62
|
+
cy.removeContentType(contentType);
|
|
63
|
+
slateAfterEach();
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export const getSelectedSlateEditor = () => {
|
|
67
|
+
return cy.get('.slate-editor.selected [contenteditable=true]').click();
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export const createSlateBlock = () => {
|
|
71
|
+
cy.get('.ui.basic.icon.button.block-add-button').first().click();
|
|
72
|
+
cy.get('.blocks-chooser .title').contains('Text').click();
|
|
73
|
+
cy.get('.ui.basic.icon.button.slate').contains('Text').click();
|
|
74
|
+
return getSelectedSlateEditor();
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export const getSlateBlockValue = (sb) => {
|
|
78
|
+
return sb.invoke('attr', 'data-slate-value').then((str) => {
|
|
79
|
+
return typeof str === 'undefined' ? [] : JSON.parse(str);
|
|
80
|
+
});
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export const createSlateBlockWithList = ({
|
|
84
|
+
numbered,
|
|
85
|
+
firstItemText,
|
|
86
|
+
secondItemText,
|
|
87
|
+
}) => {
|
|
88
|
+
let s1 = createSlateBlock();
|
|
89
|
+
|
|
90
|
+
s1.typeInSlate(firstItemText + secondItemText);
|
|
91
|
+
|
|
92
|
+
// select all contents of slate block
|
|
93
|
+
// - this opens hovering toolbar
|
|
94
|
+
cy.contains(firstItemText + secondItemText).then((el) => {
|
|
95
|
+
selectSlateNodeOfWord(el);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// TODO: do not hardcode these selectors:
|
|
99
|
+
if (numbered) {
|
|
100
|
+
// this is the numbered list option in the hovering toolbar
|
|
101
|
+
cy.get('.slate-inline-toolbar > :nth-child(9)').click();
|
|
102
|
+
} else {
|
|
103
|
+
// this is the bulleted list option in the hovering toolbar
|
|
104
|
+
cy.get('.slate-inline-toolbar > :nth-child(10)').click();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// move the text cursor
|
|
108
|
+
const sse = getSelectedSlateEditor();
|
|
109
|
+
sse.type('{leftarrow}');
|
|
110
|
+
for (let i = 0; i < firstItemText.length; ++i) {
|
|
111
|
+
sse.type('{rightarrow}');
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// simulate pressing Enter
|
|
115
|
+
getSelectedSlateEditor().lineBreakInSlate();
|
|
116
|
+
|
|
117
|
+
return s1;
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
export const selectSlateNodeOfWord = (el) => {
|
|
121
|
+
return cy.window().then((win) => {
|
|
122
|
+
var event = new CustomEvent('Test_SelectWord', {
|
|
123
|
+
detail: el[0],
|
|
124
|
+
});
|
|
125
|
+
win.document.dispatchEvent(event);
|
|
126
|
+
});
|
|
127
|
+
};
|
package/cypress.json
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"baseUrl": "http://localhost:3000",
|
|
3
3
|
"viewportWidth": 1280,
|
|
4
|
-
"defaultCommandTimeout":
|
|
4
|
+
"defaultCommandTimeout": 8888,
|
|
5
|
+
"chromeWebSecurity": false,
|
|
5
6
|
"reporter": "junit",
|
|
6
7
|
"video": true,
|
|
8
|
+
"retries": {
|
|
9
|
+
"runMode": 8,
|
|
10
|
+
"openMode": 0
|
|
11
|
+
},
|
|
7
12
|
"reporterOptions": {
|
|
8
13
|
"mochaFile": "cypress/reports/cypress-[hash].xml",
|
|
9
14
|
"jenkinsMode": true,
|
package/package.json
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React, { useEffect, useState } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { getAllBlocksAndSlateFields } from '@eeacms/volto-slate-footnote/editor/utils';
|
|
3
|
+
|
|
3
4
|
import './less/public.less';
|
|
4
5
|
import {
|
|
5
6
|
makeFootnoteListOfUniqueItems,
|
|
@@ -25,7 +26,7 @@ const FootnotesBlockView = (props) => {
|
|
|
25
26
|
useEffect(() => {
|
|
26
27
|
if (properties) {
|
|
27
28
|
const globalMetadata = global ? metadata : properties;
|
|
28
|
-
const blocks =
|
|
29
|
+
const blocks = getAllBlocksAndSlateFields(globalMetadata);
|
|
29
30
|
const notesObjResult = makeFootnoteListOfUniqueItems(blocks);
|
|
30
31
|
|
|
31
32
|
setNodesObjs(notesObjResult);
|
|
@@ -39,28 +40,51 @@ const FootnotesBlockView = (props) => {
|
|
|
39
40
|
<ol>
|
|
40
41
|
{Object.keys(notesObj).map((noteId) => {
|
|
41
42
|
const note = notesObj[noteId];
|
|
42
|
-
const { uid, footnote, zoteroId } = note;
|
|
43
|
+
const { uid, footnote, zoteroId, parentUid } = note;
|
|
43
44
|
const { refs } = note;
|
|
44
45
|
const refsList = refs ? Object.keys(refs) : null;
|
|
45
46
|
|
|
46
47
|
return (
|
|
47
|
-
<li
|
|
48
|
+
<li
|
|
49
|
+
key={`footnote-${zoteroId || uid}`}
|
|
50
|
+
id={`footnote-${zoteroId || uid}`}
|
|
51
|
+
>
|
|
48
52
|
<div
|
|
49
53
|
dangerouslySetInnerHTML={{
|
|
50
54
|
__html: makeFootnote(footnote),
|
|
51
55
|
}}
|
|
52
56
|
/>
|
|
53
57
|
{refsList ? (
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
+
<>
|
|
59
|
+
{/** some footnotes are never parent so we need the parent to reference */}
|
|
60
|
+
{/** int this case the first from refs has reference to the parent*/}
|
|
61
|
+
<sup
|
|
62
|
+
id={`cite_ref-${refsList[0]}`}
|
|
63
|
+
key={`indice-${refsList[0]}`}
|
|
64
|
+
>
|
|
65
|
+
<a
|
|
66
|
+
href={`#ref-${parentUid || uid}`}
|
|
67
|
+
aria-label="Back to content"
|
|
68
|
+
>
|
|
69
|
+
{alphabet[0]}
|
|
58
70
|
</a>{' '}
|
|
59
71
|
</sup>
|
|
60
|
-
|
|
72
|
+
{/** following refs will have the uid of the one that references it*/}
|
|
73
|
+
{refsList.slice(1).map((ref, index) => (
|
|
74
|
+
<sup id={`cite_ref-${ref}`} key={`indice-${ref}`}>
|
|
75
|
+
<a href={`#ref-${ref}`} aria-label="Back to content">
|
|
76
|
+
{alphabet[index + 1]}
|
|
77
|
+
</a>{' '}
|
|
78
|
+
</sup>
|
|
79
|
+
))}
|
|
80
|
+
</>
|
|
61
81
|
) : (
|
|
62
82
|
<sup id={`cite_ref-${uid}`}>
|
|
63
|
-
|
|
83
|
+
{/** some footnotes are never parent so we need the parent to reference */}
|
|
84
|
+
<a
|
|
85
|
+
href={`#ref-${parentUid || uid}`}
|
|
86
|
+
aria-label="Back to content"
|
|
87
|
+
>
|
|
64
88
|
↵
|
|
65
89
|
</a>{' '}
|
|
66
90
|
</sup>
|