@plone/volto 18.11.1 → 19.0.0-alpha.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.
Files changed (61) hide show
  1. package/.eslintrc.core.js +6 -0
  2. package/CHANGELOG.md +33 -6
  3. package/README.md +0 -3
  4. package/cypress/support/commands.js +19 -2
  5. package/locales/ca/LC_MESSAGES/volto.po +7 -5
  6. package/locales/ca.json +1 -1
  7. package/locales/de/LC_MESSAGES/volto.po +82 -80
  8. package/locales/de.json +1 -1
  9. package/locales/en/LC_MESSAGES/volto.po +7 -5
  10. package/locales/en.json +1 -1
  11. package/locales/es/LC_MESSAGES/volto.po +7 -5
  12. package/locales/es.json +1 -1
  13. package/locales/eu/LC_MESSAGES/volto.po +7 -5
  14. package/locales/eu.json +1 -1
  15. package/locales/fi/LC_MESSAGES/volto.po +7 -5
  16. package/locales/fi.json +1 -1
  17. package/locales/fr/LC_MESSAGES/volto.po +7 -5
  18. package/locales/fr.json +1 -1
  19. package/locales/hi/LC_MESSAGES/volto.po +7 -5
  20. package/locales/hi.json +1 -1
  21. package/locales/it/LC_MESSAGES/volto.po +7 -5
  22. package/locales/it.json +1 -1
  23. package/locales/ja/LC_MESSAGES/volto.po +7 -5
  24. package/locales/ja.json +1 -1
  25. package/locales/nl/LC_MESSAGES/volto.po +7 -5
  26. package/locales/nl.json +1 -1
  27. package/locales/pt/LC_MESSAGES/volto.po +7 -5
  28. package/locales/pt.json +1 -1
  29. package/locales/pt_BR/LC_MESSAGES/volto.po +7 -5
  30. package/locales/pt_BR.json +1 -1
  31. package/locales/ro/LC_MESSAGES/volto.po +7 -5
  32. package/locales/ro.json +1 -1
  33. package/locales/ru/LC_MESSAGES/volto.po +7 -5
  34. package/locales/ru.json +1 -1
  35. package/locales/volto.pot +8 -6
  36. package/locales/zh_CN/LC_MESSAGES/volto.po +7 -5
  37. package/locales/zh_CN.json +1 -1
  38. package/package.json +5 -5
  39. package/src/actions/querystring/querystring.js +11 -6
  40. package/src/actions/querystring/querystring.test.js +26 -5
  41. package/src/actions/vocabularies/vocabularies.js +5 -2
  42. package/src/actions/vocabularies/vocabularies.test.js +5 -5
  43. package/src/components/manage/Blocks/Block/BlocksForm.jsx +3 -3
  44. package/src/components/manage/Contents/ContentsDeleteModal.jsx +1 -1
  45. package/src/components/manage/Contents/ContentsDeleteModal.stories.jsx +137 -0
  46. package/src/components/manage/Contents/ContentsUploadModal.jsx +6 -2
  47. package/src/components/manage/Widgets/FileWidget.jsx +3 -3
  48. package/src/components/manage/Widgets/IdWidget.test.jsx +4 -2
  49. package/src/components/manage/Widgets/ImageWidget.jsx +27 -2
  50. package/src/components/manage/Widgets/ObjectBrowserWidget.jsx +3 -2
  51. package/src/components/manage/Widgets/RegistryImageWidget.jsx +3 -3
  52. package/src/components/theme/Logo/Logo.jsx +2 -1
  53. package/src/components/theme/Navigation/ContextNavigation.jsx +7 -2
  54. package/src/components/theme/View/LinkView.jsx +10 -4
  55. package/src/components/theme/View/LinkView.test.jsx +9 -1
  56. package/src/config/Blocks.jsx +1 -1
  57. package/src/helpers/Blocks/Blocks.js +1 -1
  58. package/theme/themes/pastanaga/extras/main.less +3 -0
  59. package/types/components/manage/Contents/ContentsDeleteModal.stories.d.ts +20 -0
  60. package/types/components/theme/View/LinkView.d.ts +1 -2
  61. package/types/config/Blocks.d.ts +1 -1
@@ -6,7 +6,6 @@ import {
6
6
  Dimmer,
7
7
  Header,
8
8
  Icon,
9
- Image,
10
9
  Modal,
11
10
  Table,
12
11
  Segment,
@@ -24,6 +23,7 @@ import FormattedRelativeDate from '@plone/volto/components/theme/FormattedDate/F
24
23
  import { createContent } from '@plone/volto/actions/content/content';
25
24
  import { validateFileUploadSize } from '@plone/volto/helpers/FormValidation/FormValidation';
26
25
  import { usePrevious } from '@plone/volto/helpers/Utils/usePrevious';
26
+ import Image from '@plone/volto/components/theme/Image/Image';
27
27
 
28
28
  const Dropzone = loadable(() => import('react-dropzone'));
29
29
 
@@ -259,7 +259,11 @@ const ContentsUploadModal = (props) => {
259
259
  <Table.Cell>{filesize(file.size, { round: 0 })}</Table.Cell>
260
260
  <Table.Cell>
261
261
  {file.type.split('/')[0] === 'image' && (
262
- <Image src={file.preview} height={60} />
262
+ <Image
263
+ src={file.preview}
264
+ height={60}
265
+ className="ui image"
266
+ />
263
267
  )}
264
268
  </Table.Cell>
265
269
  <Table.Cell>
@@ -5,7 +5,7 @@
5
5
 
6
6
  import React from 'react';
7
7
  import PropTypes from 'prop-types';
8
- import { Button, Image, Dimmer } from 'semantic-ui-react';
8
+ import { Button, Dimmer } from 'semantic-ui-react';
9
9
  import { readAsDataURL } from 'promise-file-reader';
10
10
  import { injectIntl } from 'react-intl';
11
11
  import deleteSVG from '@plone/volto/icons/delete.svg';
@@ -13,6 +13,7 @@ import Icon from '@plone/volto/components/theme/Icon/Icon';
13
13
  import Toast from '@plone/volto/components/manage/Toast/Toast';
14
14
  import UniversalLink from '@plone/volto/components/manage/UniversalLink/UniversalLink';
15
15
  import FormFieldWrapper from '@plone/volto/components/manage/Widgets/FormFieldWrapper';
16
+ import Image from '@plone/volto/components/theme/Image/Image';
16
17
  import loadable from '@loadable/component';
17
18
  import { flattenToAppURL } from '@plone/volto/helpers/Url/Url';
18
19
  import { validateFileUploadSize } from '@plone/volto/helpers/FormValidation/FormValidation';
@@ -172,9 +173,8 @@ const FileWidget = (props) => {
172
173
  {isDragActive && <Dimmer active></Dimmer>}
173
174
  {fileType ? (
174
175
  <Image
175
- className="image-preview"
176
+ className="image-preview small ui image"
176
177
  id={`field-${id}-image`}
177
- size="small"
178
178
  src={imgsrc}
179
179
  />
180
180
  ) : (
@@ -1,12 +1,14 @@
1
1
  import React from 'react';
2
2
  import { Provider } from 'react-intl-redux';
3
3
  import { render, waitFor } from '@testing-library/react';
4
- import configureStore from 'redux-mock-store';
4
+ import configureMockStore from 'redux-mock-store';
5
+ import thunk from 'redux-thunk';
5
6
  import config from '@plone/volto/registry';
6
7
 
7
8
  import IdWidget from './IdWidget';
8
9
 
9
- const mockStore = configureStore();
10
+ const middlewares = [thunk];
11
+ const mockStore = configureMockStore(middlewares);
10
12
 
11
13
  describe('IdWidget', () => {
12
14
  test('renders an empty id widget component', async () => {
@@ -6,6 +6,7 @@ import { useLocation } from 'react-router-dom';
6
6
  import loadable from '@loadable/component';
7
7
  import { connect } from 'react-redux';
8
8
  import { compose } from 'redux';
9
+ import { toast } from 'react-toastify';
9
10
  import useLinkEditor from '@plone/volto/components/manage/AnchorPlugin/useLinkEditor';
10
11
  import withObjectBrowser from '@plone/volto/components/manage/Sidebar/ObjectBrowser';
11
12
 
@@ -20,6 +21,7 @@ import { createContent } from '@plone/volto/actions/content/content';
20
21
  import { readAsDataURL } from 'promise-file-reader';
21
22
  import FormFieldWrapper from '@plone/volto/components/manage/Widgets/FormFieldWrapper';
22
23
  import Icon from '@plone/volto/components/theme/Icon/Icon';
24
+ import Toast from '@plone/volto/components/manage/Toast/Toast';
23
25
 
24
26
  import imageBlockSVG from '@plone/volto/components/manage/Blocks/Image/block-image.svg';
25
27
  import clearSVG from '@plone/volto/icons/clear.svg';
@@ -60,6 +62,14 @@ const messages = defineMessages({
60
62
  id: 'Uploading image',
61
63
  defaultMessage: 'Uploading image',
62
64
  },
65
+ Error: {
66
+ id: 'Error',
67
+ defaultMessage: 'Error',
68
+ },
69
+ imageUploadErrorMessage: {
70
+ id: 'imageUploadErrorMessage',
71
+ defaultMessage: 'Please upload an image instead.',
72
+ },
63
73
  });
64
74
 
65
75
  const UnconnectedImageInput = (props) => {
@@ -184,7 +194,21 @@ const UnconnectedImageInput = (props) => {
184
194
  >
185
195
  <Dropzone
186
196
  noClick
187
- onDrop={handleUpload}
197
+ accept="image/*"
198
+ onDrop={(acceptedFiles) => {
199
+ if (acceptedFiles.length > 0) {
200
+ handleUpload(acceptedFiles);
201
+ } else {
202
+ setDragging(false);
203
+ toast.error(
204
+ <Toast
205
+ error
206
+ title={intl.formatMessage(messages.Error)}
207
+ content={intl.formatMessage(messages.imageUploadErrorMessage)}
208
+ />,
209
+ );
210
+ }
211
+ }}
188
212
  onDragEnter={onDragEnter}
189
213
  onDragLeave={onDragLeave}
190
214
  className="dropzone"
@@ -192,7 +216,7 @@ const UnconnectedImageInput = (props) => {
192
216
  {({ getRootProps, getInputProps }) => (
193
217
  <div {...getRootProps()}>
194
218
  <Message>
195
- {dragging && <Dimmer active></Dimmer>}
219
+ {dragging && <Dimmer active />}
196
220
  {uploading && (
197
221
  <Dimmer active>
198
222
  <Loader indeterminate>
@@ -253,6 +277,7 @@ const UnconnectedImageInput = (props) => {
253
277
  ref: imageUploadInputRef,
254
278
  onChange: handleUpload,
255
279
  style: { display: 'none' },
280
+ accept: 'image/*',
256
281
  })}
257
282
  />
258
283
  </Button.Group>
@@ -12,7 +12,7 @@ import isArray from 'lodash/isArray';
12
12
  import isEmpty from 'lodash/isEmpty';
13
13
  import remove from 'lodash/remove';
14
14
  import { connect } from 'react-redux';
15
- import { Image, Label, Popup, Button } from 'semantic-ui-react';
15
+ import { Label, Popup, Button } from 'semantic-ui-react';
16
16
  import {
17
17
  flattenToAppURL,
18
18
  isInternalURL,
@@ -33,6 +33,7 @@ import homeSVG from '@plone/volto/icons/home.svg';
33
33
  import aheadSVG from '@plone/volto/icons/ahead.svg';
34
34
  import blankSVG from '@plone/volto/icons/blank.svg';
35
35
  import { withRouter } from 'react-router';
36
+ import Image from '@plone/volto/components/theme/Image/Image';
36
37
 
37
38
  const messages = defineMessages({
38
39
  placeholder: {
@@ -131,7 +132,7 @@ export class ObjectBrowserWidgetComponent extends Component {
131
132
  <div className="item-title">
132
133
  {includes(config.settings.imageObjects, item['@type']) ? (
133
134
  <Image
134
- size="small"
135
+ className="small ui image"
135
136
  src={`${item['@id']}/@@images/image/thumb`}
136
137
  />
137
138
  ) : (
@@ -5,7 +5,7 @@
5
5
 
6
6
  import React, { useState } from 'react';
7
7
  import PropTypes from 'prop-types';
8
- import { Button, Image, Dimmer } from 'semantic-ui-react';
8
+ import { Button, Dimmer } from 'semantic-ui-react';
9
9
  import { readAsDataURL } from 'promise-file-reader';
10
10
  import { injectIntl } from 'react-intl';
11
11
  import deleteSVG from '@plone/volto/icons/delete.svg';
@@ -15,6 +15,7 @@ import loadable from '@loadable/component';
15
15
  import { defineMessages, useIntl } from 'react-intl';
16
16
  import { toPublicURL } from '@plone/volto/helpers/Url/Url';
17
17
  import { validateFileUploadSize } from '@plone/volto/helpers/FormValidation/FormValidation';
18
+ import Image from '@plone/volto/components/theme/Image/Image';
18
19
 
19
20
  const imageMimetypes = [
20
21
  'image/png',
@@ -119,9 +120,8 @@ const RegistryImageWidget = (props) => {
119
120
  {isDragActive && <Dimmer active></Dimmer>}
120
121
  {previewSrc ? (
121
122
  <Image
122
- className="image-preview"
123
+ className="image-preview small ui image"
123
124
  id={`field-${id}-image`}
124
- size="small"
125
125
  src={previewSrc}
126
126
  />
127
127
  ) : (
@@ -4,13 +4,13 @@
4
4
  */
5
5
  import { defineMessages, useIntl } from 'react-intl';
6
6
  import { useEffect } from 'react';
7
- import { Image } from 'semantic-ui-react';
8
7
  import LogoImage from '@plone/volto/components/theme/Logo/Logo.svg';
9
8
  import { useSelector, useDispatch } from 'react-redux';
10
9
  import { Link, useLocation } from 'react-router-dom';
11
10
  import { getNavroot } from '@plone/volto/actions/navroot/navroot';
12
11
  import { flattenToAppURL, getBaseUrl } from '@plone/volto/helpers/Url/Url';
13
12
  import { hasApiExpander } from '@plone/volto/helpers/Utils/Utils';
13
+ import Image from '@plone/volto/components/theme/Image/Image';
14
14
 
15
15
  /**
16
16
  * Logo component class.
@@ -47,6 +47,7 @@ const Logo = () => {
47
47
  return (
48
48
  <Link to={navRootPath} aria-label={intl.formatMessage(messages.home)}>
49
49
  <Image
50
+ className="ui image"
50
51
  src={
51
52
  site['plone.site_logo']
52
53
  ? flattenToAppURL(site['plone.site_logo'])
@@ -1,6 +1,6 @@
1
1
  import PropTypes from 'prop-types';
2
2
  import React from 'react';
3
- import { List, Image } from 'semantic-ui-react';
3
+ import { List } from 'semantic-ui-react';
4
4
  import { Link as RouterLink } from 'react-router-dom';
5
5
  import cx from 'classnames';
6
6
  import { compose } from 'redux';
@@ -13,6 +13,7 @@ import UniversalLink from '@plone/volto/components/manage/UniversalLink/Universa
13
13
  import { withContentNavigation } from './withContentNavigation';
14
14
 
15
15
  import leftIcon from '@plone/volto/icons/left-key.svg';
16
+ import Image from '@plone/volto/components/theme/Image/Image';
16
17
 
17
18
  const messages = defineMessages({
18
19
  navigation: {
@@ -38,7 +39,11 @@ function renderNode(node, parentLevel) {
38
39
  in_path: node.is_in_path,
39
40
  })}
40
41
  >
41
- {node.thumb ? <Image src={flattenToAppURL(node.thumb)} /> : ''}
42
+ {node.thumb ? (
43
+ <Image src={flattenToAppURL(node.thumb)} className="ui image" />
44
+ ) : (
45
+ ''
46
+ )}
42
47
  {node.title}
43
48
  {node.is_current ? (
44
49
  <List.Content className="active-indicator">
@@ -1,4 +1,5 @@
1
1
  import { useEffect } from 'react';
2
+ import { useSelector } from 'react-redux';
2
3
  import PropTypes from 'prop-types';
3
4
  import { useHistory } from 'react-router-dom';
4
5
  import { isInternalURL, flattenToAppURL } from '@plone/volto/helpers/Url/Url';
@@ -8,10 +9,15 @@ import { Redirect } from 'react-router-dom';
8
9
  import { FormattedMessage } from 'react-intl';
9
10
  import config from '@plone/volto/registry';
10
11
 
11
- const LinkView = ({ token, content }) => {
12
+ const LinkView = ({ content }) => {
12
13
  const history = useHistory();
14
+ const userCanEdit = useSelector(
15
+ (state) =>
16
+ !!state.actions.actions.object.find((action) => action.id === 'edit'),
17
+ );
18
+
13
19
  useEffect(() => {
14
- if (!token) {
20
+ if (!userCanEdit) {
15
21
  const { remoteUrl } = content;
16
22
  if (isInternalURL(remoteUrl)) {
17
23
  history.replace(flattenToAppURL(remoteUrl));
@@ -19,8 +25,8 @@ const LinkView = ({ token, content }) => {
19
25
  window.location.href = flattenToAppURL(remoteUrl);
20
26
  }
21
27
  }
22
- }, [content, history, token]);
23
- if (__SERVER__ && !token && content.remoteUrl) {
28
+ }, [content, history, userCanEdit]);
29
+ if (__SERVER__ && !userCanEdit && content.remoteUrl) {
24
30
  return <Redirect to={content.remoteUrl} />;
25
31
  }
26
32
  const { title, description, remoteUrl } = content;
@@ -17,6 +17,15 @@ const store = mockStore({
17
17
  locale: 'en',
18
18
  messages: {},
19
19
  },
20
+ actions: {
21
+ actions: {
22
+ object: [
23
+ {
24
+ id: 'edit',
25
+ },
26
+ ],
27
+ },
28
+ },
20
29
  });
21
30
 
22
31
  test('renders a link view component', () => {
@@ -24,7 +33,6 @@ test('renders a link view component', () => {
24
33
  <Provider store={store}>
25
34
  <MemoryRouter>
26
35
  <LinkView
27
- token="1234"
28
36
  content={{
29
37
  title: 'Hello World!',
30
38
  description: 'Hi',
@@ -527,7 +527,7 @@ blocksConfig.gridBlock.blocksConfig.teaser.schemaEnhancer =
527
527
  blocksConfig.gridBlock.blocksConfig.image.schemaEnhancer =
528
528
  gridImageDisableSizeAndPositionHandlersSchema;
529
529
 
530
- const requiredBlocks = ['title'];
530
+ const requiredBlocks = [];
531
531
 
532
532
  const initialBlocks = {};
533
533
  const initialBlocksFocus = {}; //{Document:'title'}
@@ -140,7 +140,7 @@ export function deleteBlock(formData, blockId, intl) {
140
140
  newFormData,
141
141
  config.settings.defaultBlockType,
142
142
  0,
143
- {},
143
+ null,
144
144
  intl,
145
145
  );
146
146
  }
@@ -17,6 +17,9 @@
17
17
 
18
18
  body {
19
19
  display: flex;
20
+ // react-aria-components popovers have problems with the default declaration
21
+ // in Semantic UI that forces `overflow-x: hidden` on the body.
22
+ overflow-x: initial;
20
23
 
21
24
  @media only screen and (max-width: @largestMobileScreen) {
22
25
  flex-direction: column;
@@ -0,0 +1,20 @@
1
+ export const Default: any;
2
+ export const DeleteMoreThanOne: any;
3
+ export const NoContainedItems: any;
4
+ export const MultipleLinkIntegrityResults: any;
5
+ export const MultipleBreaches: any;
6
+ export const WithoutLinkIntegrityBreaches: any;
7
+ declare namespace _default {
8
+ export let title: string;
9
+ export { Default as component };
10
+ export let decorators: ((Story: any) => import("react/jsx-runtime").JSX.Element)[];
11
+ export namespace argTypes {
12
+ namespace locale {
13
+ let options: string[];
14
+ namespace control {
15
+ let type: string;
16
+ }
17
+ }
18
+ }
19
+ }
20
+ export default _default;
@@ -1,6 +1,5 @@
1
1
  export default LinkView;
2
- declare function LinkView({ token, content }: {
3
- token: any;
2
+ declare function LinkView({ content }: {
4
3
  content: any;
5
4
  }): import("react/jsx-runtime").JSX.Element;
6
5
  declare namespace LinkView {
@@ -3,7 +3,7 @@ export const groupBlocksOrder: {
3
3
  id: string;
4
4
  title: string;
5
5
  }[];
6
- export const requiredBlocks: string[];
6
+ export const requiredBlocks: any[];
7
7
  export namespace blocksConfig {
8
8
  namespace gridBlock {
9
9
  namespace blocksConfig {