@plone/volto 19.0.0-alpha.35 → 19.0.0-alpha.37

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 (218) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/README.md +1 -1
  3. package/locales/af/LC_MESSAGES/volto.po +29 -13
  4. package/locales/af.json +1 -1
  5. package/locales/ar/LC_MESSAGES/volto.po +29 -13
  6. package/locales/ar.json +1 -1
  7. package/locales/bg/LC_MESSAGES/volto.po +29 -13
  8. package/locales/bg.json +1 -1
  9. package/locales/bn/LC_MESSAGES/volto.po +29 -13
  10. package/locales/bn.json +1 -1
  11. package/locales/ca/LC_MESSAGES/volto.po +32 -16
  12. package/locales/ca.json +1 -1
  13. package/locales/cs/LC_MESSAGES/volto.po +30 -14
  14. package/locales/cs.json +1 -1
  15. package/locales/cy/LC_MESSAGES/volto.po +29 -13
  16. package/locales/cy.json +1 -1
  17. package/locales/da/LC_MESSAGES/volto.po +29 -13
  18. package/locales/da.json +1 -1
  19. package/locales/de/LC_MESSAGES/volto.po +32 -16
  20. package/locales/de.json +1 -1
  21. package/locales/el/LC_MESSAGES/volto.po +29 -13
  22. package/locales/el.json +1 -1
  23. package/locales/en/LC_MESSAGES/volto.po +25 -10
  24. package/locales/en.json +1 -1
  25. package/locales/en_AU/LC_MESSAGES/volto.po +29 -13
  26. package/locales/en_AU.json +1 -1
  27. package/locales/en_GB/LC_MESSAGES/volto.po +29 -13
  28. package/locales/en_GB.json +1 -1
  29. package/locales/eo/LC_MESSAGES/volto.po +29 -13
  30. package/locales/eo.json +1 -1
  31. package/locales/es/LC_MESSAGES/volto.po +67 -52
  32. package/locales/es.json +1 -1
  33. package/locales/et/LC_MESSAGES/volto.po +29 -13
  34. package/locales/et.json +1 -1
  35. package/locales/eu/LC_MESSAGES/volto.po +55 -40
  36. package/locales/eu.json +1 -1
  37. package/locales/fa/LC_MESSAGES/volto.po +29 -13
  38. package/locales/fa.json +1 -1
  39. package/locales/fi/LC_MESSAGES/volto.po +30 -14
  40. package/locales/fi.json +1 -1
  41. package/locales/fr/LC_MESSAGES/volto.po +208 -193
  42. package/locales/fr.json +1 -1
  43. package/locales/fu/LC_MESSAGES/volto.po +29 -13
  44. package/locales/fu.json +1 -1
  45. package/locales/gl/LC_MESSAGES/volto.po +58 -43
  46. package/locales/gl.json +1 -1
  47. package/locales/he/LC_MESSAGES/volto.po +29 -13
  48. package/locales/he.json +1 -1
  49. package/locales/hi/LC_MESSAGES/volto.po +34 -18
  50. package/locales/hi.json +1 -1
  51. package/locales/hr/LC_MESSAGES/volto.po +30 -14
  52. package/locales/hr.json +1 -1
  53. package/locales/hu/LC_MESSAGES/volto.po +29 -13
  54. package/locales/hu.json +1 -1
  55. package/locales/hy/LC_MESSAGES/volto.po +29 -13
  56. package/locales/hy.json +1 -1
  57. package/locales/id/LC_MESSAGES/volto.po +29 -13
  58. package/locales/id.json +1 -1
  59. package/locales/it/LC_MESSAGES/volto.po +34 -18
  60. package/locales/it.json +1 -1
  61. package/locales/ja/LC_MESSAGES/volto.po +29 -13
  62. package/locales/ja.json +1 -1
  63. package/locales/ka/LC_MESSAGES/volto.po +29 -13
  64. package/locales/ka.json +1 -1
  65. package/locales/kn/LC_MESSAGES/volto.po +29 -13
  66. package/locales/kn.json +1 -1
  67. package/locales/ko/LC_MESSAGES/volto.po +29 -13
  68. package/locales/ko.json +1 -1
  69. package/locales/lt/LC_MESSAGES/volto.po +30 -14
  70. package/locales/lt.json +1 -1
  71. package/locales/lv/LC_MESSAGES/volto.po +29 -13
  72. package/locales/lv.json +1 -1
  73. package/locales/mi/LC_MESSAGES/volto.po +29 -13
  74. package/locales/mi.json +1 -1
  75. package/locales/mk/LC_MESSAGES/volto.po +29 -13
  76. package/locales/mk.json +1 -1
  77. package/locales/my/LC_MESSAGES/volto.po +29 -13
  78. package/locales/my.json +1 -1
  79. package/locales/nb_NO/LC_MESSAGES/volto.po +29 -13
  80. package/locales/nb_NO.json +1 -1
  81. package/locales/nl/LC_MESSAGES/volto.po +69 -53
  82. package/locales/nl.json +1 -1
  83. package/locales/nn/LC_MESSAGES/volto.po +29 -13
  84. package/locales/nn.json +1 -1
  85. package/locales/pl/LC_MESSAGES/volto.po +30 -14
  86. package/locales/pl.json +1 -1
  87. package/locales/pt/LC_MESSAGES/volto.po +30 -14
  88. package/locales/pt.json +1 -1
  89. package/locales/pt_BR/LC_MESSAGES/volto.po +54 -39
  90. package/locales/pt_BR.json +1 -1
  91. package/locales/rm/LC_MESSAGES/volto.po +29 -13
  92. package/locales/rm.json +1 -1
  93. package/locales/ro/LC_MESSAGES/volto.po +30 -15
  94. package/locales/ro.json +1 -1
  95. package/locales/ru/LC_MESSAGES/volto.po +30 -14
  96. package/locales/ru.json +1 -1
  97. package/locales/sk/LC_MESSAGES/volto.po +30 -14
  98. package/locales/sk.json +1 -1
  99. package/locales/sl/LC_MESSAGES/volto.po +29 -13
  100. package/locales/sl.json +1 -1
  101. package/locales/sm/LC_MESSAGES/volto.po +29 -13
  102. package/locales/sm.json +1 -1
  103. package/locales/sq/LC_MESSAGES/volto.po +29 -13
  104. package/locales/sq.json +1 -1
  105. package/locales/sr/LC_MESSAGES/volto.po +30 -14
  106. package/locales/sr.json +1 -1
  107. package/locales/sr@cyrl/LC_MESSAGES/volto.po +29 -13
  108. package/locales/sr@cyrl.json +1 -1
  109. package/locales/sr@latn/LC_MESSAGES/volto.po +29 -13
  110. package/locales/sr@latn.json +1 -1
  111. package/locales/sv/LC_MESSAGES/volto.po +31 -15
  112. package/locales/sv.json +1 -1
  113. package/locales/ta/LC_MESSAGES/volto.po +30 -15
  114. package/locales/ta.json +1 -1
  115. package/locales/te/LC_MESSAGES/volto.po +29 -13
  116. package/locales/te.json +1 -1
  117. package/locales/th/LC_MESSAGES/volto.po +29 -13
  118. package/locales/th.json +1 -1
  119. package/locales/to/LC_MESSAGES/volto.po +29 -13
  120. package/locales/to.json +1 -1
  121. package/locales/tr/LC_MESSAGES/volto.po +29 -14
  122. package/locales/tr.json +1 -1
  123. package/locales/uk/LC_MESSAGES/volto.po +30 -14
  124. package/locales/uk.json +1 -1
  125. package/locales/vi/LC_MESSAGES/volto.po +29 -13
  126. package/locales/vi.json +1 -1
  127. package/locales/volto.pot +26 -11
  128. package/locales/zh_CN/LC_MESSAGES/volto.po +29 -14
  129. package/locales/zh_CN.json +1 -1
  130. package/locales/zh_Hant/LC_MESSAGES/volto.po +29 -13
  131. package/locales/zh_Hant.json +1 -1
  132. package/locales/zh_Hant_HK/LC_MESSAGES/volto.po +29 -13
  133. package/locales/zh_Hant_HK.json +1 -1
  134. package/package.json +10 -10
  135. package/src/components/manage/Add/Add.test.jsx +10 -3
  136. package/src/components/manage/Aliases/Aliases.test.jsx +5 -2
  137. package/src/components/manage/BlockChooser/BlockChooser.jsx +7 -10
  138. package/src/components/manage/Blocks/Block/Edit.jsx +19 -10
  139. package/src/components/manage/Blocks/Block/Order/Item.jsx +9 -4
  140. package/src/components/manage/Contents/Contents.test.jsx +7 -4
  141. package/src/components/manage/Contents/DropZoneContent.jsx +1 -0
  142. package/src/components/manage/Controlpanels/AddonsControlpanel.test.jsx +7 -4
  143. package/src/components/manage/Controlpanels/Aliases.test.jsx +7 -4
  144. package/src/components/manage/Controlpanels/BlockType.tsx +2 -3
  145. package/src/components/manage/Controlpanels/ContentType.test.jsx +12 -9
  146. package/src/components/manage/Controlpanels/ContentTypeLayout.test.jsx +12 -9
  147. package/src/components/manage/Controlpanels/ContentTypes.jsx +9 -2
  148. package/src/components/manage/Controlpanels/ContentTypes.test.jsx +7 -4
  149. package/src/components/manage/Controlpanels/Controlpanel.test.jsx +7 -4
  150. package/src/components/manage/Controlpanels/Controlpanels.test.jsx +13 -8
  151. package/src/components/manage/Controlpanels/Groups/GroupsControlpanel.test.jsx +7 -4
  152. package/src/components/manage/Controlpanels/ModerateComments.test.jsx +7 -4
  153. package/src/components/manage/Controlpanels/Rules/AddRule.test.jsx +7 -4
  154. package/src/components/manage/Controlpanels/Rules/ConfigureRule.test.jsx +9 -6
  155. package/src/components/manage/Controlpanels/Rules/EditRule.test.jsx +7 -4
  156. package/src/components/manage/Controlpanels/Rules/Rules.test.jsx +7 -4
  157. package/src/components/manage/Controlpanels/UndoControlpanel.test.jsx +7 -4
  158. package/src/components/manage/Controlpanels/Users/UserGroupMembershipControlPanel.test.jsx +7 -4
  159. package/src/components/manage/Controlpanels/Users/UsersControlpanel.jsx +58 -5
  160. package/src/components/manage/Controlpanels/Users/UsersControlpanel.ssr.test.jsx +624 -0
  161. package/src/components/manage/Controlpanels/Users/UsersControlpanel.test.jsx +21 -8
  162. package/src/components/manage/Delete/Delete.test.jsx +13 -8
  163. package/src/components/manage/Diff/Diff.test.jsx +7 -4
  164. package/src/components/manage/Edit/Edit.test.jsx +11 -6
  165. package/src/components/manage/Form/Form.jsx +6 -1
  166. package/src/components/manage/Form/ModalForm.jsx +164 -88
  167. package/src/components/manage/History/History.test.jsx +15 -8
  168. package/src/components/manage/LinksToItem/LinksToItem.test.jsx +7 -4
  169. package/src/components/manage/Multilingual/ManageTranslations.test.jsx +15 -12
  170. package/src/components/manage/Preferences/ChangePassword.test.jsx +7 -4
  171. package/src/components/manage/Preferences/PersonalPreferences.test.jsx +9 -6
  172. package/src/components/manage/Rules/Rules.test.jsx +5 -2
  173. package/src/components/manage/Sharing/Sharing.test.jsx +9 -6
  174. package/src/components/manage/Sidebar/ObjectBrowser.jsx +7 -0
  175. package/src/components/manage/Sidebar/ObjectBrowserBody.jsx +7 -3
  176. package/src/components/manage/Sidebar/ObjectBrowserBody.test.jsx +52 -0
  177. package/src/components/manage/Sidebar/Sidebar.jsx +2 -0
  178. package/src/components/manage/Sidebar/Sidebar.test.jsx +4 -1
  179. package/src/components/manage/Toolbar/Toolbar.jsx +89 -7
  180. package/src/components/manage/Toolbar/Toolbar.test.jsx +15 -10
  181. package/src/components/manage/Widgets/FormFieldWrapper.jsx +7 -5
  182. package/src/components/manage/Widgets/ObjectBrowserWidget.jsx +1 -0
  183. package/src/components/manage/Widgets/QuerystringWidget.test.jsx +3 -1
  184. package/src/components/manage/Widgets/TextWidget.jsx +4 -0
  185. package/src/components/manage/Widgets/TokenWidget.jsx +142 -186
  186. package/src/components/theme/App/App.test.jsx +13 -10
  187. package/src/components/theme/ContactForm/ContactForm.test.jsx +13 -8
  188. package/src/components/theme/MultilingualRedirector/MultilingualRedirector.test.jsx +6 -3
  189. package/src/components/theme/Search/Search.jsx +218 -328
  190. package/src/components/theme/Search/Search.test.jsx +14 -14
  191. package/src/components/theme/Sitemap/Sitemap.jsx +22 -30
  192. package/src/components/theme/Sitemap/Sitemap.test.jsx +18 -0
  193. package/src/components/theme/Unauthorized/Unauthorized.jsx +23 -30
  194. package/src/components/theme/Unauthorized/Unauthorized.test.jsx +6 -4
  195. package/src/components/theme/View/View.test.jsx +37 -24
  196. package/src/config/index.js +1 -0
  197. package/src/helpers/Api/Api.js +2 -2
  198. package/src/helpers/I18n/I18n.test.ts +44 -0
  199. package/src/helpers/I18n/I18n.ts +31 -0
  200. package/src/helpers/Robots/Robots.js +1 -1
  201. package/src/helpers/Robots/Robots.test.js +34 -0
  202. package/src/helpers/index.js +1 -0
  203. package/theme/themes/pastanaga/collections/form.overrides +21 -0
  204. package/theme/themes/pastanaga/elements/button.overrides +30 -3
  205. package/types/components/manage/Controlpanels/Relations/RelationsMatrix.d.ts +1 -1
  206. package/types/components/manage/Controlpanels/Users/UsersControlpanel.d.ts +2 -6
  207. package/types/components/manage/Controlpanels/Users/UsersControlpanel.ssr.test.d.ts +1 -0
  208. package/types/components/manage/Controlpanels/index.d.ts +1 -1
  209. package/types/components/manage/Multilingual/ManageTranslations.d.ts +1 -1
  210. package/types/components/manage/Sidebar/ObjectBrowser.d.ts +1 -1
  211. package/types/components/manage/Sidebar/ObjectBrowserBody.test.d.ts +1 -0
  212. package/types/components/manage/Widgets/ImageWidget.d.ts +1 -1
  213. package/types/components/manage/Widgets/InternalUrlWidget.d.ts +1 -1
  214. package/types/components/manage/Widgets/UrlWidget.d.ts +1 -1
  215. package/types/components/manage/Widgets/index.d.ts +2 -2
  216. package/types/components/theme/Search/Search.d.ts +1 -1
  217. package/types/helpers/I18n/I18n.d.ts +20 -0
  218. package/types/helpers/index.d.ts +1 -0
@@ -2,6 +2,7 @@ import React from 'react';
2
2
  import configureStore from 'redux-mock-store';
3
3
  import { Provider } from 'react-intl-redux';
4
4
  import { MemoryRouter } from 'react-router-dom';
5
+ import { CookiesProvider } from 'react-cookie';
5
6
  import { waitFor, render, screen } from '@testing-library/react';
6
7
 
7
8
  import Diff from './Diff';
@@ -75,10 +76,12 @@ describe('Diff', () => {
75
76
  });
76
77
  const { container } = render(
77
78
  <Provider store={store}>
78
- <MemoryRouter initialEntries={['/blog?one=0&two=1']}>
79
- <Diff />
80
- <div id="toolbar"></div>
81
- </MemoryRouter>
79
+ <CookiesProvider>
80
+ <MemoryRouter initialEntries={['/blog?one=0&two=1']}>
81
+ <Diff />
82
+ <div id="toolbar"></div>
83
+ </MemoryRouter>
84
+ </CookiesProvider>
82
85
  </Provider>,
83
86
  );
84
87
  await waitFor(() => screen.getByTestId('DiffField'));
@@ -2,6 +2,7 @@ import React from 'react';
2
2
  import { render } from '@testing-library/react';
3
3
  import configureStore from 'redux-mock-store';
4
4
  import { Provider } from 'react-intl-redux';
5
+ import { CookiesProvider } from 'react-cookie';
5
6
  import jwt from 'jsonwebtoken';
6
7
 
7
8
  import { __test__ as Edit } from './Edit';
@@ -55,9 +56,11 @@ describe('Edit', () => {
55
56
  });
56
57
  const { container } = render(
57
58
  <Provider store={store}>
58
- <div id="toolbar"></div>
59
- <Edit location={{ pathname: '/blog', search: {} }} />
60
- <div id="sidebar"></div>
59
+ <CookiesProvider>
60
+ <div id="toolbar"></div>
61
+ <Edit location={{ pathname: '/blog', search: {} }} />
62
+ <div id="sidebar"></div>
63
+ </CookiesProvider>
61
64
  </Provider>,
62
65
  );
63
66
 
@@ -104,9 +107,11 @@ describe('Edit', () => {
104
107
  });
105
108
  const { container } = render(
106
109
  <Provider store={store}>
107
- <div id="toolbar"></div>
108
- <Edit location={{ pathname: '/blog', search: {} }} />
109
- <div id="sidebar"></div>
110
+ <CookiesProvider>
111
+ <div id="toolbar"></div>
112
+ <Edit location={{ pathname: '/blog', search: {} }} />
113
+ <div id="sidebar"></div>
114
+ </CookiesProvider>
110
115
  </Provider>,
111
116
  );
112
117
 
@@ -972,7 +972,12 @@ class Form extends Component {
972
972
  onTabChange={this.onTabChange}
973
973
  activeIndex={this.state.activeIndex}
974
974
  panes={map(schema.fieldsets, (item) => ({
975
- menuItem: item.title,
975
+ menuItem: {
976
+ key: item.id,
977
+ content: item.title,
978
+ as: 'button',
979
+ type: 'button',
980
+ },
976
981
  render: () => [
977
982
  !settings.verticalFormTabs && this.props.title && (
978
983
  <Segment secondary attached key={this.props.title}>
@@ -46,6 +46,14 @@ const messages = defineMessages({
46
46
  id: 'Cancel',
47
47
  defaultMessage: 'Cancel',
48
48
  },
49
+ dialogOpened: {
50
+ id: 'Pop-up opened: {title}',
51
+ defaultMessage: 'Pop-up opened: {title}',
52
+ },
53
+ dialogClosed: {
54
+ id: 'Pop-up closed.',
55
+ defaultMessage: 'Pop-up closed.',
56
+ },
49
57
  });
50
58
 
51
59
  /**
@@ -54,6 +62,7 @@ const messages = defineMessages({
54
62
  * @extends Component
55
63
  */
56
64
  class ModalForm extends Component {
65
+ static idCounter = 0;
57
66
  /**
58
67
  * Property types.
59
68
  * @property {Object} propTypes Property types.
@@ -110,17 +119,21 @@ class ModalForm extends Component {
110
119
  */
111
120
  constructor(props) {
112
121
  super(props);
122
+ this.headerId = `modal-title-${++ModalForm.idCounter}`;
113
123
  this.state = {
114
124
  currentTab: 0,
115
125
  errors: {},
116
126
  isFormPristine: true,
117
127
  formData: props.formData,
118
128
  };
129
+ this.modalRef = React.createRef();
130
+ this.announceRef = React.createRef();
119
131
  this.selectTab = this.selectTab.bind(this);
120
132
  this.onChangeField = this.onChangeField.bind(this);
121
133
  this.onBlurField = this.onBlurField.bind(this);
122
134
  this.onClickInput = this.onClickInput.bind(this);
123
135
  this.onSubmit = this.onSubmit.bind(this);
136
+ this.onKeyDown = this.onKeyDown.bind(this);
124
137
  }
125
138
 
126
139
  /**
@@ -209,12 +222,57 @@ class ModalForm extends Component {
209
222
  });
210
223
  }
211
224
 
225
+ onKeyDown(event) {
226
+ if (event.key !== 'Tab') return;
227
+ const modal = document.getElementById(this.headerId)?.closest('.ui.modal');
228
+ if (!modal) return;
229
+ const focusable = modal.querySelectorAll(
230
+ 'a[href],button:not([disabled]),input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex="-1"])',
231
+ );
232
+ if (!focusable.length) return;
233
+ const first = focusable[0];
234
+ const last = focusable[focusable.length - 1];
235
+ if (event.shiftKey) {
236
+ if (document.activeElement === first) {
237
+ event.preventDefault();
238
+ last.focus();
239
+ }
240
+ } else {
241
+ if (document.activeElement === last) {
242
+ event.preventDefault();
243
+ first.focus();
244
+ }
245
+ }
246
+ }
247
+
212
248
  /**
213
249
  * Component did update lifecycle handler
214
250
  * @param {Object} prevProps
215
251
  * @param {Object} prevState
216
252
  */
217
- async componentDidUpdate(prevProps, prevState) {
253
+ componentWillUnmount() {
254
+ document.removeEventListener('keydown', this.onKeyDown);
255
+ }
256
+
257
+ componentDidUpdate(prevProps, prevState) {
258
+ if (!prevProps.open && this.props.open) {
259
+ document.addEventListener('keydown', this.onKeyDown);
260
+ this.modalRef.current?.focus();
261
+ if (this.announceRef.current) {
262
+ this.announceRef.current.textContent = this.props.intl.formatMessage(
263
+ messages.dialogOpened,
264
+ { title: this.props.title },
265
+ );
266
+ }
267
+ }
268
+ if (prevProps.open && !this.props.open) {
269
+ document.removeEventListener('keydown', this.onKeyDown);
270
+ if (this.announceRef.current) {
271
+ this.announceRef.current.textContent = this.props.intl.formatMessage(
272
+ messages.dialogClosed,
273
+ );
274
+ }
275
+ }
218
276
  if (this.props.onChangeFormData) {
219
277
  if (!isEqual(prevState?.formData, this.state.formData)) {
220
278
  this.props.onChangeFormData(this.state.formData);
@@ -259,100 +317,118 @@ class ModalForm extends Component {
259
317
 
260
318
  const state_errors = keys(this.state.errors).length > 0;
261
319
  return (
262
- <Modal
263
- dimmer={this.props.dimmer}
264
- open={this.props.open}
265
- className={this.props.className}
266
- >
267
- <Header>{this.props.title}</Header>
268
- <Dimmer active={this.props.loading}>
269
- <Loader>
270
- {this.props.loadingMessage || (
271
- <FormattedMessage id="Loading" defaultMessage="Loading." />
272
- )}
273
- </Loader>
274
- </Dimmer>
275
- <Modal.Content scrolling>
276
- <UiForm
277
- method="post"
278
- onSubmit={this.onSubmit}
279
- error={state_errors || Boolean(this.props.submitError)}
280
- >
281
- {description}
282
- <Message error>
283
- {state_errors ? (
284
- <FormattedMessage
285
- id="There were some errors."
286
- defaultMessage="There were some errors."
287
- />
288
- ) : (
289
- ''
320
+ <>
321
+ {/* aria-live region outside Modal so it persists through open/close cycles */}
322
+ <div
323
+ ref={this.announceRef}
324
+ aria-live="assertive"
325
+ aria-atomic="true"
326
+ style={{
327
+ position: 'absolute',
328
+ width: '1px',
329
+ height: '1px',
330
+ overflow: 'hidden',
331
+ opacity: 0,
332
+ }}
333
+ />
334
+ <Modal
335
+ role="dialog"
336
+ dimmer={this.props.dimmer}
337
+ open={this.props.open}
338
+ className={this.props.className}
339
+ aria-labelledby={this.headerId}
340
+ aria-modal="true"
341
+ >
342
+ <Header id={this.headerId}>{this.props.title}</Header>
343
+ <Dimmer active={this.props.loading}>
344
+ <Loader>
345
+ {this.props.loadingMessage || (
346
+ <FormattedMessage id="Loading" defaultMessage="Loading." />
290
347
  )}
291
- <div>{this.props.submitError}</div>
292
- </Message>
293
- {schema.fieldsets?.length > 1 && (
294
- <Menu tabular stackable>
295
- {map(schema.fieldsets, (item, index) => (
296
- <Menu.Item
297
- name={item.id}
298
- index={index}
299
- key={item.id}
300
- active={this.state.currentTab === index}
301
- onClick={this.selectTab}
302
- >
303
- {item.title}
304
- </Menu.Item>
348
+ </Loader>
349
+ </Dimmer>
350
+ <Modal.Content scrolling>
351
+ {/* outline suppressed for programmatic focus via CSS :focus:not(:focus-visible) on .modal-focus-trap */}
352
+ {/* eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex */}
353
+ <div ref={this.modalRef} tabIndex={-1} className="modal-focus-trap">
354
+ <UiForm
355
+ method="post"
356
+ onSubmit={this.onSubmit}
357
+ error={state_errors || Boolean(this.props.submitError)}
358
+ >
359
+ {description}
360
+ <Message error>
361
+ {state_errors ? (
362
+ <FormattedMessage
363
+ id="There were some errors."
364
+ defaultMessage="There were some errors."
365
+ />
366
+ ) : (
367
+ ''
368
+ )}
369
+ <div>{this.props.submitError}</div>
370
+ </Message>
371
+ {schema.fieldsets?.length > 1 && (
372
+ <Menu tabular stackable>
373
+ {map(schema.fieldsets, (item, index) => (
374
+ <Menu.Item
375
+ name={item.id}
376
+ index={index}
377
+ key={item.id}
378
+ active={this.state.currentTab === index}
379
+ onClick={this.selectTab}
380
+ >
381
+ {item.title}
382
+ </Menu.Item>
383
+ ))}
384
+ </Menu>
385
+ )}
386
+ {fields.map((field) => (
387
+ <Field
388
+ {...field}
389
+ key={field.id}
390
+ onBlur={this.onBlurField}
391
+ onClick={this.onClickInput}
392
+ error={this.state.errors[field.id]}
393
+ />
305
394
  ))}
306
- </Menu>
395
+ </UiForm>
396
+ </div>
397
+ </Modal.Content>
398
+ <Modal.Actions>
399
+ {onCancel && (
400
+ <Button
401
+ type="button"
402
+ basic
403
+ secondary
404
+ aria-label={this.props.intl.formatMessage(messages.cancel)}
405
+ title={this.props.intl.formatMessage(messages.cancel)}
406
+ onClick={onCancel}
407
+ >
408
+ <Icon name={clearSVG} className="circled" size="30px" />
409
+ </Button>
307
410
  )}
308
- {fields.map((field) => (
309
- <Field
310
- {...field}
311
- key={field.id}
312
- onBlur={this.onBlurField}
313
- onClick={this.onClickInput}
314
- error={this.state.errors[field.id]}
315
- />
316
- ))}
317
- </UiForm>
318
- </Modal.Content>
319
- <Modal.Actions>
320
- <Button
321
- basic
322
- circular
323
- primary
324
- floated="right"
325
- aria-label={
326
- this.props.submitLabel
327
- ? this.props.submitLabel
328
- : this.props.intl.formatMessage(messages.save)
329
- }
330
- title={
331
- this.props.submitLabel
332
- ? this.props.submitLabel
333
- : this.props.intl.formatMessage(messages.save)
334
- }
335
- onClick={this.onSubmit}
336
- loading={this.props.loading}
337
- >
338
- <Icon name={aheadSVG} className="contents circled" size="30px" />
339
- </Button>
340
- {onCancel && (
341
411
  <Button
342
- type="button"
343
412
  basic
344
- circular
345
- secondary
346
- aria-label={this.props.intl.formatMessage(messages.cancel)}
347
- title={this.props.intl.formatMessage(messages.cancel)}
348
- floated="right"
349
- onClick={onCancel}
413
+ primary
414
+ aria-label={
415
+ this.props.submitLabel
416
+ ? this.props.submitLabel
417
+ : this.props.intl.formatMessage(messages.save)
418
+ }
419
+ title={
420
+ this.props.submitLabel
421
+ ? this.props.submitLabel
422
+ : this.props.intl.formatMessage(messages.save)
423
+ }
424
+ onClick={this.onSubmit}
425
+ loading={this.props.loading}
350
426
  >
351
- <Icon name={clearSVG} className="circled" size="30px" />
427
+ <Icon name={aheadSVG} className="contents circled" size="30px" />
352
428
  </Button>
353
- )}
354
- </Modal.Actions>
355
- </Modal>
429
+ </Modal.Actions>
430
+ </Modal>
431
+ </>
356
432
  );
357
433
  }
358
434
  }
@@ -2,6 +2,7 @@ import React from 'react';
2
2
  import { render } from '@testing-library/react';
3
3
  import configureStore from 'redux-mock-store';
4
4
  import { StaticRouter } from 'react-router-dom';
5
+ import { CookiesProvider } from 'react-cookie';
5
6
  import { Provider } from 'react-intl-redux';
6
7
  import jwt from 'jsonwebtoken';
7
8
 
@@ -89,8 +90,10 @@ describe('History', () => {
89
90
  });
90
91
  const { container } = render(
91
92
  <Provider store={store}>
92
- <History location={{ pathname: '/blog' }} />
93
- <div id="toolbar"></div>
93
+ <CookiesProvider>
94
+ <History location={{ pathname: '/blog' }} />
95
+ <div id="toolbar"></div>
96
+ </CookiesProvider>
94
97
  </Provider>,
95
98
  );
96
99
 
@@ -156,8 +159,10 @@ describe('History', () => {
156
159
  });
157
160
  const { container } = render(
158
161
  <Provider store={store}>
159
- <History location={{ pathname: '/blog' }} />
160
- <div id="toolbar"></div>
162
+ <CookiesProvider>
163
+ <History location={{ pathname: '/blog' }} />
164
+ <div id="toolbar"></div>
165
+ </CookiesProvider>
161
166
  </Provider>,
162
167
  );
163
168
 
@@ -221,10 +226,12 @@ describe('History', () => {
221
226
  });
222
227
  const { container } = render(
223
228
  <Provider store={store}>
224
- <StaticRouter context={{}} location={'/blog'}>
225
- <History location={{ pathname: '/blog' }} />
226
- <div id="toolbar"></div>
227
- </StaticRouter>
229
+ <CookiesProvider>
230
+ <StaticRouter context={{}} location={'/blog'}>
231
+ <History location={{ pathname: '/blog' }} />
232
+ <div id="toolbar"></div>
233
+ </StaticRouter>
234
+ </CookiesProvider>
228
235
  </Provider>,
229
236
  );
230
237
 
@@ -4,6 +4,7 @@ import { Provider } from 'react-intl-redux';
4
4
  import configureMockStore from 'redux-mock-store';
5
5
  import thunk from 'redux-thunk';
6
6
  import { MemoryRouter } from 'react-router-dom';
7
+ import { CookiesProvider } from 'react-cookie';
7
8
 
8
9
  import { __test__ as LinksToItem } from './LinksToItem';
9
10
 
@@ -102,10 +103,12 @@ describe('LinksToItem', () => {
102
103
  });
103
104
  const { container } = render(
104
105
  <Provider store={store}>
105
- <MemoryRouter>
106
- <LinksToItem location={{ pathname: '/page-1/links-to-item' }} />
107
- <div id="toolbar"></div>
108
- </MemoryRouter>
106
+ <CookiesProvider>
107
+ <MemoryRouter>
108
+ <LinksToItem location={{ pathname: '/page-1/links-to-item' }} />
109
+ <div id="toolbar"></div>
110
+ </MemoryRouter>
111
+ </CookiesProvider>
109
112
  </Provider>,
110
113
  );
111
114
 
@@ -3,6 +3,7 @@ import { render } from '@testing-library/react';
3
3
  import configureStore from 'redux-mock-store';
4
4
  import { Provider } from 'react-intl-redux';
5
5
  import { MemoryRouter } from 'react-router-dom';
6
+ import { CookiesProvider } from 'react-cookie';
6
7
  import config from '@plone/volto/registry';
7
8
 
8
9
  import ManageTranslations from './ManageTranslations';
@@ -41,18 +42,20 @@ describe('ManageTranslations', () => {
41
42
  });
42
43
  const { container } = render(
43
44
  <Provider store={store}>
44
- <MemoryRouter>
45
- <ManageTranslations
46
- location={{
47
- pathname: '/blog-post',
48
- state: {
49
- language: 'es',
50
- translationOf: '/en/page-en',
51
- },
52
- }}
53
- />
54
- <div id="toolbar"></div>
55
- </MemoryRouter>
45
+ <CookiesProvider>
46
+ <MemoryRouter>
47
+ <ManageTranslations
48
+ location={{
49
+ pathname: '/blog-post',
50
+ state: {
51
+ language: 'es',
52
+ translationOf: '/en/page-en',
53
+ },
54
+ }}
55
+ />
56
+ <div id="toolbar"></div>
57
+ </MemoryRouter>
58
+ </CookiesProvider>
56
59
  </Provider>,
57
60
  );
58
61
 
@@ -4,6 +4,7 @@ import { Provider } from 'react-intl-redux';
4
4
  import configureStore from 'redux-mock-store';
5
5
  import jwt from 'jsonwebtoken';
6
6
  import { MemoryRouter } from 'react-router-dom';
7
+ import { CookiesProvider } from 'react-cookie';
7
8
 
8
9
  import ChangePassword from './ChangePassword';
9
10
 
@@ -40,10 +41,12 @@ describe('ChangePassword', () => {
40
41
  });
41
42
  const { container } = render(
42
43
  <Provider store={store}>
43
- <MemoryRouter>
44
- <ChangePassword location={{ pathname: '/blog' }} />
45
- <div id="toolbar"></div>
46
- </MemoryRouter>
44
+ <CookiesProvider>
45
+ <MemoryRouter>
46
+ <ChangePassword location={{ pathname: '/blog' }} />
47
+ <div id="toolbar"></div>
48
+ </MemoryRouter>
49
+ </CookiesProvider>
47
50
  </Provider>,
48
51
  );
49
52
 
@@ -2,6 +2,7 @@ import React from 'react';
2
2
  import { Provider } from 'react-intl-redux';
3
3
  import configureStore from 'redux-mock-store';
4
4
  import { MemoryRouter } from 'react-router-dom';
5
+ import { CookiesProvider } from 'react-cookie';
5
6
  import { render } from '@testing-library/react';
6
7
 
7
8
  import PersonalPreferences from './PersonalPreferences';
@@ -37,12 +38,14 @@ describe('PersonalPreferences', () => {
37
38
  });
38
39
  const { container } = render(
39
40
  <Provider store={store}>
40
- <MemoryRouter>
41
- <PersonalPreferences
42
- location={{ pathname: '/blog' }}
43
- closeMenu={() => {}}
44
- />
45
- </MemoryRouter>
41
+ <CookiesProvider>
42
+ <MemoryRouter>
43
+ <PersonalPreferences
44
+ location={{ pathname: '/blog' }}
45
+ closeMenu={() => {}}
46
+ />
47
+ </MemoryRouter>
48
+ </CookiesProvider>
46
49
  </Provider>,
47
50
  );
48
51
  expect(container).toMatchSnapshot();
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import { render } from '@testing-library/react';
3
3
  import { Provider } from 'react-intl-redux';
4
+ import { CookiesProvider } from 'react-cookie';
4
5
  import configureMockStore from 'redux-mock-store';
5
6
  import thunk from 'redux-thunk';
6
7
 
@@ -69,8 +70,10 @@ describe('Rules', () => {
69
70
  });
70
71
  const { container } = render(
71
72
  <Provider store={store}>
72
- <Rules location={{ pathname: '/blog/rules' }} />
73
- <div id="toolbar"></div>
73
+ <CookiesProvider>
74
+ <Rules location={{ pathname: '/blog/rules' }} />
75
+ <div id="toolbar"></div>
76
+ </CookiesProvider>
74
77
  </Provider>,
75
78
  );
76
79
 
@@ -4,6 +4,7 @@ import configureStore from 'redux-mock-store';
4
4
  import { Provider } from 'react-intl-redux';
5
5
  import jwt from 'jsonwebtoken';
6
6
  import { MemoryRouter } from 'react-router-dom';
7
+ import { CookiesProvider } from 'react-cookie';
7
8
  import { PluggablesProvider } from '@plone/volto/components/manage/Pluggable';
8
9
 
9
10
  import Sharing from './Sharing';
@@ -60,12 +61,14 @@ describe('Sharing', () => {
60
61
 
61
62
  const { container } = render(
62
63
  <Provider store={store}>
63
- <PluggablesProvider>
64
- <MemoryRouter>
65
- <Sharing location={{ pathname: '/blog' }} />
66
- <div id="toolbar"></div>
67
- </MemoryRouter>
68
- </PluggablesProvider>
64
+ <CookiesProvider>
65
+ <PluggablesProvider>
66
+ <MemoryRouter>
67
+ <Sharing location={{ pathname: '/blog' }} />
68
+ <div id="toolbar"></div>
69
+ </MemoryRouter>
70
+ </PluggablesProvider>
71
+ </CookiesProvider>
69
72
  </Provider>,
70
73
  );
71
74
 
@@ -58,6 +58,7 @@ const withObjectBrowser = (WrappedComponent) =>
58
58
  selectableTypes,
59
59
  maximumSelectionSize,
60
60
  currentPath,
61
+ initialPath,
61
62
  onlyFolderishSelectable,
62
63
  } = {}) =>
63
64
  this.setState(() => ({
@@ -71,6 +72,7 @@ const withObjectBrowser = (WrappedComponent) =>
71
72
  selectableTypes,
72
73
  maximumSelectionSize,
73
74
  currentPath,
75
+ initialPath,
74
76
  onlyFolderishSelectable,
75
77
  }));
76
78
 
@@ -82,6 +84,10 @@ const withObjectBrowser = (WrappedComponent) =>
82
84
  this.props.pathname ||
83
85
  this.props.location?.pathname;
84
86
 
87
+ let initialPath = this.state?.initialPath
88
+ ? getBaseUrl(this.state.initialPath)
89
+ : null;
90
+
85
91
  return (
86
92
  <>
87
93
  <WrappedComponent
@@ -105,6 +111,7 @@ const withObjectBrowser = (WrappedComponent) =>
105
111
  : this.props.data
106
112
  }
107
113
  contextURL={getBaseUrl(contextURL)}
114
+ initialPath={initialPath}
108
115
  closeObjectBrowser={this.closeObjectBrowser}
109
116
  mode={this.state.mode}
110
117
  onSelectItem={this.state.onSelectItem}