@plone/volto 16.22.1 → 16.22.2

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.
Files changed (35) hide show
  1. package/.changelog.draft +14 -17
  2. package/.yarn/install-state.gz +0 -0
  3. package/CHANGELOG.md +23 -0
  4. package/CONTRIBUTING.md +5 -1
  5. package/package.json +1 -1
  6. package/packages/volto-slate/build/messages/src/blocks/Table/TableBlockEdit.json +90 -0
  7. package/packages/volto-slate/build/messages/src/blocks/Text/DefaultTextBlockEditor.json +6 -0
  8. package/packages/volto-slate/build/messages/src/blocks/Text/DetachedTextBlockEditor.json +6 -0
  9. package/packages/volto-slate/build/messages/src/blocks/Text/SlashMenu.json +6 -0
  10. package/packages/volto-slate/build/messages/src/editor/plugins/AdvancedLink/index.json +10 -0
  11. package/packages/volto-slate/build/messages/src/editor/plugins/Link/index.json +10 -0
  12. package/packages/volto-slate/build/messages/src/editor/plugins/Table/index.json +30 -0
  13. package/packages/volto-slate/build/messages/src/elementEditor/messages.json +10 -0
  14. package/packages/volto-slate/build/messages/src/widgets/HtmlSlateWidget.json +6 -0
  15. package/packages/volto-slate/build/messages/src/widgets/RichTextWidgetView.json +6 -0
  16. package/packages/volto-slate/package.json +1 -1
  17. package/pyvenv.cfg +3 -0
  18. package/share/man/man1/ttx.1 +225 -0
  19. package/src/components/manage/Blocks/Listing/withQuerystringResults.jsx +18 -11
  20. package/src/components/manage/Contents/Contents.jsx +27 -0
  21. package/src/components/manage/Diff/DiffField.jsx +25 -1
  22. package/src/components/manage/Sharing/Sharing.jsx +11 -5
  23. package/src/components/manage/Widgets/FormFieldWrapper.jsx +1 -1
  24. package/src/components/theme/Sitemap/Sitemap.jsx +24 -13
  25. package/src/components/theme/Sitemap/Sitemap.test.jsx +23 -2
  26. package/styles/Vocab/Plone/accept.txt +9 -2
  27. package/styles/Vocab/Plone/reject.txt +2 -5
  28. package/theme/themes/pastanaga/collections/form.overrides +46 -0
  29. package/theme/themes/pastanaga/elements/input.overrides +6 -0
  30. package/theme/themes/pastanaga/elements/label.overrides +10 -0
  31. package/.gitignore~ +0 -71
  32. package/locales/volto.pot~ +0 -4705
  33. package/news/4547.breaking~ +0 -1
  34. package/package.json~ +0 -444
  35. package/src/config/index.js~ +0 -223
@@ -1334,6 +1334,9 @@ class Contents extends Component {
1334
1334
  as={Button}
1335
1335
  onClick={this.upload}
1336
1336
  className="upload"
1337
+ aria-label={this.props.intl.formatMessage(
1338
+ messages.upload,
1339
+ )}
1337
1340
  >
1338
1341
  <Icon
1339
1342
  name={uploadSVG}
@@ -1358,6 +1361,9 @@ class Contents extends Component {
1358
1361
  as={Button}
1359
1362
  onClick={this.rename}
1360
1363
  disabled={!selected}
1364
+ aria-label={this.props.intl.formatMessage(
1365
+ messages.rename,
1366
+ )}
1361
1367
  >
1362
1368
  <Icon
1363
1369
  name={renameSVG}
@@ -1380,6 +1386,9 @@ class Contents extends Component {
1380
1386
  as={Button}
1381
1387
  onClick={this.workflow}
1382
1388
  disabled={!selected}
1389
+ aria-label={this.props.intl.formatMessage(
1390
+ messages.state,
1391
+ )}
1383
1392
  >
1384
1393
  <Icon
1385
1394
  name={semaphoreSVG}
@@ -1402,6 +1411,9 @@ class Contents extends Component {
1402
1411
  as={Button}
1403
1412
  onClick={this.tags}
1404
1413
  disabled={!selected}
1414
+ aria-label={this.props.intl.formatMessage(
1415
+ messages.tags,
1416
+ )}
1405
1417
  >
1406
1418
  <Icon
1407
1419
  name={tagSVG}
@@ -1425,6 +1437,9 @@ class Contents extends Component {
1425
1437
  as={Button}
1426
1438
  onClick={this.properties}
1427
1439
  disabled={!selected}
1440
+ aria-label={this.props.intl.formatMessage(
1441
+ messages.properties,
1442
+ )}
1428
1443
  >
1429
1444
  <Icon
1430
1445
  name={propertiesSVG}
@@ -1449,6 +1464,9 @@ class Contents extends Component {
1449
1464
  as={Button}
1450
1465
  onClick={this.cut}
1451
1466
  disabled={!selected}
1467
+ aria-label={this.props.intl.formatMessage(
1468
+ messages.cut,
1469
+ )}
1452
1470
  >
1453
1471
  <Icon
1454
1472
  name={cutSVG}
@@ -1471,6 +1489,9 @@ class Contents extends Component {
1471
1489
  as={Button}
1472
1490
  onClick={this.copy}
1473
1491
  disabled={!selected}
1492
+ aria-label={this.props.intl.formatMessage(
1493
+ messages.copy,
1494
+ )}
1474
1495
  >
1475
1496
  <Icon
1476
1497
  name={copySVG}
@@ -1494,6 +1515,9 @@ class Contents extends Component {
1494
1515
  as={Button}
1495
1516
  onClick={this.paste}
1496
1517
  disabled={!this.props.action}
1518
+ aria-label={this.props.intl.formatMessage(
1519
+ messages.paste,
1520
+ )}
1497
1521
  >
1498
1522
  <Icon
1499
1523
  name={pasteSVG}
@@ -1517,6 +1541,9 @@ class Contents extends Component {
1517
1541
  as={Button}
1518
1542
  onClick={this.delete}
1519
1543
  disabled={!selected}
1544
+ aria-label={this.props.intl.formatMessage(
1545
+ messages.delete,
1546
+ )}
1520
1547
  >
1521
1548
  <Icon
1522
1549
  name={deleteSVG}
@@ -17,6 +17,7 @@ import { useSelector } from 'react-redux';
17
17
  import { Api } from '@plone/volto/helpers';
18
18
  import configureStore from '@plone/volto/store';
19
19
  import { DefaultView } from '@plone/volto/components/';
20
+ import { serializeNodes } from '@plone/volto-slate/editor/render';
20
21
 
21
22
  import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
22
23
 
@@ -69,7 +70,7 @@ const DiffField = ({
69
70
  .replace('\u202F', ' '),
70
71
  );
71
72
  break;
72
- case 'json':
73
+ case 'json': {
73
74
  const api = new Api();
74
75
  const history = createBrowserHistory();
75
76
  const store = configureStore(window.__data, history, api);
@@ -90,6 +91,29 @@ const DiffField = ({
90
91
  ),
91
92
  );
92
93
  break;
94
+ }
95
+ case 'slate': {
96
+ const api = new Api();
97
+ const history = createBrowserHistory();
98
+ const store = configureStore(window.__data, history, api);
99
+ parts = diffWords(
100
+ ReactDOMServer.renderToStaticMarkup(
101
+ <Provider store={store}>
102
+ <ConnectedRouter history={history}>
103
+ {serializeNodes(one)}
104
+ </ConnectedRouter>
105
+ </Provider>,
106
+ ),
107
+ ReactDOMServer.renderToStaticMarkup(
108
+ <Provider store={store}>
109
+ <ConnectedRouter history={history}>
110
+ {serializeNodes(two)}
111
+ </ConnectedRouter>
112
+ </Provider>,
113
+ ),
114
+ );
115
+ break;
116
+ }
93
117
  case 'textarea':
94
118
  default:
95
119
  parts = diffWords(one, two);
@@ -246,9 +246,9 @@ class SharingComponent extends Component {
246
246
  * @returns {undefined}
247
247
  */
248
248
  onToggleInherit() {
249
- this.setState({
250
- inherit: !this.state.inherit,
251
- });
249
+ this.setState((state) => ({
250
+ inherit: !state.inherit,
251
+ }));
252
252
  }
253
253
 
254
254
  /**
@@ -404,9 +404,15 @@ class SharingComponent extends Component {
404
404
  <Segment attached>
405
405
  <Form.Field>
406
406
  <Checkbox
407
- checked={this.state.inherit}
407
+ id="inherit-permissions-checkbox"
408
+ name="inherit-permissions-checkbox"
409
+ defaultChecked={this.state.inherit}
408
410
  onChange={this.onToggleInherit}
409
- label={this.props.intl.formatMessage(messages.inherit)}
411
+ label={
412
+ <label htmlFor="inherit-permissions-checkbox">
413
+ {this.props.intl.formatMessage(messages.inherit)}
414
+ </label>
415
+ }
410
416
  />
411
417
  </Form.Field>
412
418
  <p className="help">
@@ -96,7 +96,7 @@ class FormFieldWrapper extends Component {
96
96
  {this.props.children}
97
97
 
98
98
  {map(error, (message) => (
99
- <Label key={message} basic color="red" pointing>
99
+ <Label key={message} basic color="red" className="form-error-label">
100
100
  {message}
101
101
  </Label>
102
102
  ))}
@@ -22,6 +22,13 @@ const messages = defineMessages({
22
22
  defaultMessage: 'Sitemap',
23
23
  },
24
24
  });
25
+
26
+ export function getSitemapPath(pathname = '', lang) {
27
+ const prefix = pathname.replace(/\/sitemap$/gm, '').replace(/^\//, '');
28
+ const path = prefix || lang || '';
29
+ return path;
30
+ }
31
+
25
32
  /**
26
33
  * Sitemap class.
27
34
  * @class Sitemap
@@ -39,11 +46,13 @@ class Sitemap extends Component {
39
46
 
40
47
  componentDidMount() {
41
48
  const { settings } = config;
42
- if (settings.isMultilingual) {
43
- this.props.getNavigation(`${toBackendLang(this.props.lang)}`, 4);
44
- } else {
45
- this.props.getNavigation('', 4);
46
- }
49
+
50
+ const lang = settings.isMultilingual
51
+ ? `${toBackendLang(this.props.lang)}`
52
+ : null;
53
+
54
+ const path = getSitemapPath(this.props.location.pathname, lang);
55
+ this.props.getNavigation(path, 4);
47
56
  }
48
57
 
49
58
  /**
@@ -105,15 +114,17 @@ export default compose(
105
114
  {
106
115
  key: 'navigation',
107
116
  promise: ({ location, store: { dispatch, getState } }) => {
117
+ if (!__SERVER__) return;
108
118
  const { settings } = config;
109
- const lang = getState().intl.locale;
110
- if (settings.isMultilingual) {
111
- return (
112
- __SERVER__ && dispatch(getNavigation(`${toBackendLang(lang)}`, 4))
113
- );
114
- } else {
115
- return __SERVER__ && dispatch(getNavigation('', 4));
116
- }
119
+
120
+ const path = getSitemapPath(
121
+ location.pathname,
122
+ settings.isMultilingual
123
+ ? toBackendLang(getState().intl.locale)
124
+ : null,
125
+ );
126
+
127
+ return dispatch(getNavigation(path, 4));
117
128
  },
118
129
  },
119
130
  ]),
@@ -4,7 +4,7 @@ import configureStore from 'redux-mock-store';
4
4
  import { Provider } from 'react-intl-redux';
5
5
  import { MemoryRouter } from 'react-router-dom';
6
6
 
7
- import { __test__ as Sitemap } from './Sitemap';
7
+ import { __test__ as Sitemap, getSitemapPath } from './Sitemap';
8
8
 
9
9
  const mockStore = configureStore();
10
10
 
@@ -46,7 +46,7 @@ describe('Sitemap', () => {
46
46
  const component = renderer.create(
47
47
  <Provider store={store}>
48
48
  <MemoryRouter>
49
- <Sitemap />
49
+ <Sitemap location={{ pathname: '/page-1' }} />
50
50
  </MemoryRouter>
51
51
  </Provider>,
52
52
  );
@@ -54,3 +54,24 @@ describe('Sitemap', () => {
54
54
  expect(json).toMatchSnapshot();
55
55
  });
56
56
  });
57
+
58
+ describe('getSitemapPath', () => {
59
+ it('accepts empty path', () => {
60
+ expect(getSitemapPath('', null)).toBe('');
61
+ });
62
+
63
+ it('accepts a path', () => {
64
+ expect(getSitemapPath('/page-1/sitemap', null)).toBe('page-1');
65
+ });
66
+ it('accepts a path', () => {
67
+ expect(getSitemapPath('/page-1/sitemap', null)).toBe('page-1');
68
+ });
69
+
70
+ it('uses a language as default root', () => {
71
+ expect(getSitemapPath('/', 'de')).toBe('de');
72
+ });
73
+
74
+ it('accepts language-rooted paths', () => {
75
+ expect(getSitemapPath('/de/mission', 'de')).toBe('de/mission');
76
+ });
77
+ });
@@ -1,10 +1,17 @@
1
+ -{0,1}plone-{0,1}
2
+ -{0,1}volto-{0,1}
1
3
  `plone.restapi`
2
4
  `plone.volto`
5
+ [Aa]sync
6
+ [Bb]ackend
7
+ JavaScript
3
8
  npm
9
+ nvm
10
+ Pastanaga
4
11
  Plone
5
12
  Razzle
6
13
  RichText
14
+ Sass
7
15
  Volto
16
+ Vue
8
17
  Zope
9
- JavaScript
10
- NodeJS
@@ -1,5 +1,2 @@
1
- node
2
- nodejs
3
- javascript
4
- js
5
- Javascript
1
+ [^.]js
2
+ NodeJS
@@ -49,6 +49,52 @@
49
49
  }
50
50
  }
51
51
 
52
+ .ui.form .fields.error .field textarea,
53
+ .ui.form .fields.error .field select,
54
+ .ui.form .fields.error .field input:not([type]),
55
+ .ui.form .fields.error .field input[type='date'],
56
+ .ui.form .fields.error .field input[type='datetime-local'],
57
+ .ui.form .fields.error .field input[type='email'],
58
+ .ui.form .fields.error .field input[type='number'],
59
+ .ui.form .fields.error .field input[type='password'],
60
+ .ui.form .fields.error .field input[type='search'],
61
+ .ui.form .fields.error .field input[type='tel'],
62
+ .ui.form .fields.error .field input[type='time'],
63
+ .ui.form .fields.error .field input[type='text'],
64
+ .ui.form .fields.error .field input[type='file'],
65
+ .ui.form .fields.error .field input[type='url'],
66
+ .ui.form .field.error textarea,
67
+ .ui.form .field.error select,
68
+ .ui.form .field.error input:not([type]),
69
+ .ui.form .field.error input[type='date'],
70
+ .ui.form .field.error input[type='datetime-local'],
71
+ .ui.form .field.error input[type='email'],
72
+ .ui.form .field.error input[type='number'],
73
+ .ui.form .field.error input[type='password'],
74
+ .ui.form .field.error input[type='search'],
75
+ .ui.form .field.error input[type='tel'],
76
+ .ui.form .field.error input[type='time'],
77
+ .ui.form .field.error input[type='text'],
78
+ .ui.form .field.error input[type='file'],
79
+ .ui.form .field.error input[type='url'],
80
+ .ui.form .field.error textarea:focus,
81
+ .ui.form .field.error select:focus,
82
+ .ui.form .field.error input:not([type]):focus,
83
+ .ui.form .field.error input[type='date']:focus,
84
+ .ui.form .field.error input[type='datetime-local']:focus,
85
+ .ui.form .field.error input[type='email']:focus,
86
+ .ui.form .field.error input[type='number']:focus,
87
+ .ui.form .field.error input[type='password']:focus,
88
+ .ui.form .field.error input[type='search']:focus,
89
+ .ui.form .field.error input[type='tel']:focus,
90
+ .ui.form .field.error input[type='time']:focus,
91
+ .ui.form .field.error input[type='text']:focus,
92
+ .ui.form .field.error input[type='file']:focus,
93
+ .ui.form .field.error input[type='url']:focus {
94
+ border-color: #d01157;
95
+ background: none;
96
+ }
97
+
52
98
  .ui.form .field > .selection.dropdown {
53
99
  height: 60px;
54
100
  }
@@ -6,6 +6,12 @@
6
6
  font-weight: @inputFontWeight;
7
7
  }
8
8
 
9
+ /* This aligns the height of the field name label to the other side in case
10
+ of an error is present, it overrides a default from SemanticUI grid definitions. */
11
+ .ui.grid > .stretched.row > .column > .wrapper {
12
+ flex-grow: 0;
13
+ }
14
+
9
15
  .inline.field {
10
16
  .wrapper {
11
17
  display: flex;
@@ -6,3 +6,13 @@
6
6
  margin: 0em 0em 0em 0.75em;
7
7
  }
8
8
  }
9
+
10
+ .ui.form {
11
+ .ui.basic.red.label.form-error-label {
12
+ padding-left: 0;
13
+ border: none;
14
+ margin-top: 0;
15
+ color: #d01157 !important;
16
+ font-weight: normal;
17
+ }
18
+ }
package/.gitignore~ DELETED
@@ -1,71 +0,0 @@
1
- # Node
2
- node_modules
3
- coverage
4
- jsdoc
5
- webpack-assets.json
6
- webpack-stats.json
7
- npm-debug.log
8
- junit.xml
9
- eslint.xml
10
- yarn-error.log
11
- build
12
-
13
- # Other
14
- .DS_Store
15
- .idea
16
- lighthouse-report.html
17
- .vscode/
18
- .#*
19
- *~
20
-
21
- # Python
22
- /api/.installed.cfg
23
- /api/.mr.developer.cfg
24
- /api/bin/
25
- /api/develop-eggs/
26
- /api/eggs/
27
- /api/include/
28
- /api/lib/
29
- /api/lib64/
30
- /api/notebook/env/
31
- /api/parts/
32
- /api/share/python-wheels/
33
- /api/src/
34
- /api/test/
35
- /api/var/
36
- /api/venv/
37
- /bin/
38
- /lib/
39
- .Python
40
- include
41
- pip-selfcheck.json
42
- pyvenv.cfg
43
- share
44
- /api/lib64
45
- lib64
46
-
47
- # locales
48
- locales/*.json
49
-
50
- # Tests
51
- /tests/bin
52
- /tests/develop-eggs
53
- /tests/parts
54
- /tests/.installed.cfg
55
- *.pyc
56
- geckodriver.log
57
- log.html
58
- output.xml
59
- report.html
60
- selenium-screenshot-*.png
61
- /selenium/
62
- cypress/videos/
63
- cypress/screenshots
64
-
65
- # Local environment setup
66
- .env
67
- public/critical.css
68
-
69
- # Sphinx and MyST
70
- docs/_build/
71
- /.python-version