@plone/volto 18.34.0 → 18.35.1
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/.release-it.json +3 -0
- package/CHANGELOG.md +60 -0
- package/locales/af/LC_MESSAGES/volto.po +35 -5
- package/locales/af.json +1 -1
- package/locales/ar/LC_MESSAGES/volto.po +35 -5
- package/locales/ar.json +1 -1
- package/locales/bg/LC_MESSAGES/volto.po +35 -5
- package/locales/bg.json +1 -1
- package/locales/bn/LC_MESSAGES/volto.po +35 -5
- package/locales/bn.json +1 -1
- package/locales/ca/LC_MESSAGES/volto.po +37 -7
- package/locales/ca.json +1 -1
- package/locales/cs/LC_MESSAGES/volto.po +35 -5
- package/locales/cs.json +1 -1
- package/locales/cy/LC_MESSAGES/volto.po +35 -5
- package/locales/cy.json +1 -1
- package/locales/da/LC_MESSAGES/volto.po +35 -5
- package/locales/da.json +1 -1
- package/locales/de/LC_MESSAGES/volto.po +39 -9
- package/locales/de.json +1 -1
- package/locales/el/LC_MESSAGES/volto.po +35 -5
- package/locales/el.json +1 -1
- package/locales/en/LC_MESSAGES/volto.po +35 -5
- package/locales/en.json +1 -1
- package/locales/en_AU/LC_MESSAGES/volto.po +35 -5
- package/locales/en_AU.json +1 -1
- package/locales/en_GB/LC_MESSAGES/volto.po +35 -5
- package/locales/en_GB.json +1 -1
- package/locales/eo/LC_MESSAGES/volto.po +35 -5
- package/locales/eo.json +1 -1
- package/locales/es/LC_MESSAGES/volto.po +36 -6
- package/locales/es.json +1 -1
- package/locales/et/LC_MESSAGES/volto.po +35 -5
- package/locales/et.json +1 -1
- package/locales/eu/LC_MESSAGES/volto.po +38 -8
- package/locales/eu.json +1 -1
- package/locales/fa/LC_MESSAGES/volto.po +35 -5
- package/locales/fa.json +1 -1
- package/locales/fi/LC_MESSAGES/volto.po +35 -5
- package/locales/fi.json +1 -1
- package/locales/fr/LC_MESSAGES/volto.po +36 -6
- package/locales/fr.json +1 -1
- package/locales/fu/LC_MESSAGES/volto.po +35 -5
- package/locales/fu.json +1 -1
- package/locales/gl/LC_MESSAGES/volto.po +35 -5
- package/locales/gl.json +1 -1
- package/locales/he/LC_MESSAGES/volto.po +35 -5
- package/locales/he.json +1 -1
- package/locales/hi/LC_MESSAGES/volto.po +38 -8
- package/locales/hi.json +1 -1
- package/locales/hr/LC_MESSAGES/volto.po +35 -5
- package/locales/hr.json +1 -1
- package/locales/hu/LC_MESSAGES/volto.po +35 -5
- package/locales/hu.json +1 -1
- package/locales/hy/LC_MESSAGES/volto.po +35 -5
- package/locales/hy.json +1 -1
- package/locales/id/LC_MESSAGES/volto.po +35 -5
- package/locales/id.json +1 -1
- package/locales/it/LC_MESSAGES/volto.po +36 -6
- package/locales/it.json +1 -1
- package/locales/ja/LC_MESSAGES/volto.po +35 -5
- package/locales/ja.json +1 -1
- package/locales/ka/LC_MESSAGES/volto.po +35 -5
- package/locales/ka.json +1 -1
- package/locales/kn/LC_MESSAGES/volto.po +35 -5
- package/locales/kn.json +1 -1
- package/locales/ko/LC_MESSAGES/volto.po +35 -5
- package/locales/ko.json +1 -1
- package/locales/lt/LC_MESSAGES/volto.po +35 -5
- package/locales/lt.json +1 -1
- package/locales/lv/LC_MESSAGES/volto.po +35 -5
- package/locales/lv.json +1 -1
- package/locales/mi/LC_MESSAGES/volto.po +35 -5
- package/locales/mi.json +1 -1
- package/locales/mk/LC_MESSAGES/volto.po +35 -5
- package/locales/mk.json +1 -1
- package/locales/my/LC_MESSAGES/volto.po +35 -5
- package/locales/my.json +1 -1
- package/locales/nb_NO/LC_MESSAGES/volto.po +35 -5
- package/locales/nb_NO.json +1 -1
- package/locales/nl/LC_MESSAGES/volto.po +36 -6
- package/locales/nl.json +1 -1
- package/locales/nn/LC_MESSAGES/volto.po +35 -5
- package/locales/nn.json +1 -1
- package/locales/pl/LC_MESSAGES/volto.po +35 -5
- package/locales/pl.json +1 -1
- package/locales/pt/LC_MESSAGES/volto.po +35 -5
- package/locales/pt.json +1 -1
- package/locales/pt_BR/LC_MESSAGES/volto.po +49 -19
- package/locales/pt_BR.json +1 -1
- package/locales/rm/LC_MESSAGES/volto.po +35 -5
- package/locales/rm.json +1 -1
- package/locales/ro/LC_MESSAGES/volto.po +36 -6
- package/locales/ro.json +1 -1
- package/locales/ru/LC_MESSAGES/volto.po +36 -6
- package/locales/ru.json +1 -1
- package/locales/sk/LC_MESSAGES/volto.po +35 -5
- package/locales/sk.json +1 -1
- package/locales/sl/LC_MESSAGES/volto.po +35 -5
- package/locales/sl.json +1 -1
- package/locales/sm/LC_MESSAGES/volto.po +35 -5
- package/locales/sm.json +1 -1
- package/locales/sq/LC_MESSAGES/volto.po +35 -5
- package/locales/sq.json +1 -1
- package/locales/sr/LC_MESSAGES/volto.po +35 -5
- package/locales/sr.json +1 -1
- package/locales/sr@cyrl/LC_MESSAGES/volto.po +35 -5
- package/locales/sr@cyrl.json +1 -1
- package/locales/sr@latn/LC_MESSAGES/volto.po +35 -5
- package/locales/sr@latn.json +1 -1
- package/locales/sv/LC_MESSAGES/volto.po +35 -5
- package/locales/sv.json +1 -1
- package/locales/ta/LC_MESSAGES/volto.po +36 -6
- package/locales/ta.json +1 -1
- package/locales/te/LC_MESSAGES/volto.po +35 -5
- package/locales/te.json +1 -1
- package/locales/th/LC_MESSAGES/volto.po +35 -5
- package/locales/th.json +1 -1
- package/locales/to/LC_MESSAGES/volto.po +35 -5
- package/locales/to.json +1 -1
- package/locales/tr/LC_MESSAGES/volto.po +35 -5
- package/locales/tr.json +1 -1
- package/locales/uk/LC_MESSAGES/volto.po +35 -5
- package/locales/uk.json +1 -1
- package/locales/vi/LC_MESSAGES/volto.po +35 -5
- package/locales/vi.json +1 -1
- package/locales/volto.pot +36 -6
- package/locales/zh_CN/LC_MESSAGES/volto.po +35 -5
- package/locales/zh_CN.json +1 -1
- package/locales/zh_Hant/LC_MESSAGES/volto.po +35 -5
- package/locales/zh_Hant.json +1 -1
- package/locales/zh_Hant_HK/LC_MESSAGES/volto.po +35 -5
- package/locales/zh_Hant_HK.json +1 -1
- package/news/7308.fix +1 -0
- package/news/8084.fix +1 -0
- package/package.json +28 -32
- package/src/actions/querystringsearch/querystringsearch.js +4 -1
- package/src/actions/querystringsearch/querystringsearch.test.js +77 -0
- package/src/components/manage/BlockChooser/BlockChooser.jsx +7 -10
- package/src/components/manage/Blocks/Block/Edit.jsx +9 -10
- package/src/components/manage/Blocks/Block/Order/Item.jsx +9 -4
- package/src/components/manage/Blocks/Image/View.test.jsx +8 -8
- package/src/components/manage/Contents/ContentsBreadcrumbs.jsx +7 -6
- package/src/components/manage/Controlpanels/ContentTypes.jsx +9 -2
- package/src/components/manage/Controlpanels/Users/UsersControlpanel.jsx +58 -5
- package/src/components/manage/Controlpanels/Users/UsersControlpanel.ssr.test.jsx +624 -0
- package/src/components/manage/Controlpanels/Users/UsersControlpanel.test.jsx +8 -0
- package/src/components/manage/Form/Form.jsx +6 -1
- package/src/components/manage/Form/ModalForm.jsx +165 -87
- package/src/components/manage/Sidebar/ObjectBrowser.jsx +7 -0
- package/src/components/manage/Sidebar/ObjectBrowserBody.jsx +7 -3
- package/src/components/manage/Sidebar/ObjectBrowserBody.test.jsx +52 -0
- package/src/components/manage/Sidebar/Sidebar.jsx +1 -0
- package/src/components/manage/Toast/Toast.jsx +35 -1
- package/src/components/manage/Toast/Toast.test.jsx +8 -5
- package/src/components/manage/Widgets/ArrayWidget.jsx +3 -2
- package/src/components/manage/Widgets/FormFieldWrapper.jsx +16 -3
- package/src/components/manage/Widgets/ObjectBrowserWidget.jsx +1 -0
- package/src/components/manage/Widgets/QuerystringWidget.jsx +1 -18
- package/src/components/manage/Widgets/QuerystringWidget.test.jsx +45 -2
- package/src/components/manage/Widgets/SelectStyling.jsx +33 -1
- package/src/components/manage/Widgets/SelectWidget.jsx +3 -2
- package/src/components/manage/Widgets/TextWidget.test.jsx +44 -0
- package/src/components/theme/Search/Search.jsx +24 -1
- package/src/components/theme/Unauthorized/Unauthorized.jsx +1 -2
- package/src/components/theme/View/EventView.stories.jsx +89 -0
- package/src/components/theme/View/FileView.stories.jsx +50 -0
- package/src/components/theme/View/LinkView.stories.jsx +57 -0
- package/src/components/theme/View/ListingView.stories.jsx +70 -0
- package/src/components/theme/View/NewsItemView.stories.jsx +58 -0
- package/src/components/theme/View/RenderBlocks.stories.jsx +112 -0
- package/src/components/theme/View/SummaryView.stories.jsx +71 -0
- package/src/components/theme/View/TabularView.stories.jsx +66 -0
- package/src/helpers/FormValidation/validators.ts +15 -2
- package/src/helpers/I18n/I18n.test.ts +44 -0
- package/src/helpers/I18n/I18n.ts +31 -0
- package/src/helpers/index.js +1 -0
- package/src/server.jsx +7 -1
- package/theme/themes/pastanaga/collections/form.overrides +21 -0
- package/theme/themes/pastanaga/elements/button.overrides +30 -3
- package/theme/themes/pastanaga/extras/main.less +1 -0
- package/types/components/manage/Controlpanels/Relations/RelationsMatrix.d.ts +1 -1
- package/types/components/manage/Controlpanels/Users/UsersControlpanel.d.ts +2 -6
- package/types/components/manage/Controlpanels/Users/UsersControlpanel.ssr.test.d.ts +1 -0
- package/types/components/manage/Controlpanels/index.d.ts +1 -1
- package/types/components/manage/Multilingual/ManageTranslations.d.ts +1 -1
- package/types/components/manage/Sidebar/ObjectBrowser.d.ts +1 -1
- package/types/components/manage/Sidebar/ObjectBrowserBody.test.d.ts +1 -0
- package/types/components/manage/Widgets/ImageWidget.d.ts +1 -1
- package/types/components/manage/Widgets/InternalUrlWidget.d.ts +1 -1
- package/types/components/manage/Widgets/QuerystringWidget.d.ts +0 -4
- package/types/components/manage/Widgets/UrlWidget.d.ts +1 -1
- package/types/components/manage/Widgets/index.d.ts +2 -2
- package/types/components/theme/View/EventView.stories.d.ts +19 -0
- package/types/components/theme/View/FileView.stories.d.ts +18 -0
- package/types/components/theme/View/LinkView.stories.d.ts +18 -0
- package/types/components/theme/View/ListingView.stories.d.ts +24 -0
- package/types/components/theme/View/NewsItemView.stories.d.ts +23 -0
- package/types/components/theme/View/RenderBlocks.stories.d.ts +23 -0
- package/types/components/theme/View/SummaryView.stories.d.ts +23 -0
- package/types/components/theme/View/TabularView.stories.d.ts +23 -0
- package/types/helpers/I18n/I18n.d.ts +20 -0
- package/types/helpers/index.d.ts +1 -0
|
@@ -4,7 +4,7 @@ import configureStore from 'redux-mock-store';
|
|
|
4
4
|
import { Provider } from 'react-intl-redux';
|
|
5
5
|
import { waitFor } from '@testing-library/react';
|
|
6
6
|
|
|
7
|
-
import QuerystringWidget from './QuerystringWidget';
|
|
7
|
+
import QuerystringWidget, { objectSchema } from './QuerystringWidget';
|
|
8
8
|
|
|
9
9
|
const mockStore = configureStore();
|
|
10
10
|
|
|
@@ -25,6 +25,47 @@ test('renders an querystring widget component', async () => {
|
|
|
25
25
|
expect(component.toJSON()).toMatchSnapshot();
|
|
26
26
|
});
|
|
27
27
|
|
|
28
|
+
describe('objectSchema', () => {
|
|
29
|
+
const mockIntl = { formatMessage: ({ defaultMessage }) => defaultMessage };
|
|
30
|
+
|
|
31
|
+
it('does not include depth in the default fieldset', () => {
|
|
32
|
+
const schema = objectSchema({ intl: mockIntl });
|
|
33
|
+
const fields = schema.fieldsets[0].fields;
|
|
34
|
+
|
|
35
|
+
expect(fields).not.toContain('depth');
|
|
36
|
+
expect(fields).toEqual([
|
|
37
|
+
'query',
|
|
38
|
+
'sort_on',
|
|
39
|
+
'sort_order_boolean',
|
|
40
|
+
'limit',
|
|
41
|
+
'b_size',
|
|
42
|
+
]);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('does not include depth in the schema properties', () => {
|
|
46
|
+
const schema = objectSchema({ intl: mockIntl });
|
|
47
|
+
|
|
48
|
+
expect(schema.properties).not.toHaveProperty('depth');
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('does not include depth even when value contains a path criterion', () => {
|
|
52
|
+
const value = {
|
|
53
|
+
query: [
|
|
54
|
+
{
|
|
55
|
+
i: 'path',
|
|
56
|
+
o: 'plone.app.querystring.operation.string.path',
|
|
57
|
+
v: '/folder',
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
};
|
|
61
|
+
const schema = objectSchema({ intl: mockIntl, value });
|
|
62
|
+
const fields = schema.fieldsets[0].fields;
|
|
63
|
+
|
|
64
|
+
expect(fields).not.toContain('depth');
|
|
65
|
+
expect(schema.properties).not.toHaveProperty('depth');
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
28
69
|
test('can take a schemaEnhancer', async () => {
|
|
29
70
|
const store = mockStore({
|
|
30
71
|
querystring: { indexes: {} },
|
|
@@ -51,6 +92,8 @@ test('can take a schemaEnhancer', async () => {
|
|
|
51
92
|
/>
|
|
52
93
|
</Provider>,
|
|
53
94
|
);
|
|
54
|
-
await waitFor(() => {
|
|
95
|
+
await waitFor(() => {
|
|
96
|
+
expect(component.toJSON()?.children).toHaveLength(3);
|
|
97
|
+
});
|
|
55
98
|
expect(component.toJSON()).toMatchSnapshot();
|
|
56
99
|
});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import { defineMessages, useIntl } from 'react-intl';
|
|
2
3
|
import { Popup } from 'semantic-ui-react';
|
|
3
4
|
import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
|
|
4
5
|
import Icon from '@plone/volto/components/theme/Icon/Icon';
|
|
@@ -10,6 +11,13 @@ import checkSVG from '@plone/volto/icons/check.svg';
|
|
|
10
11
|
import checkBlankSVG from '@plone/volto/icons/check-blank.svg';
|
|
11
12
|
import clearSVG from '@plone/volto/icons/clear.svg';
|
|
12
13
|
|
|
14
|
+
const messages = defineMessages({
|
|
15
|
+
clearSelection: {
|
|
16
|
+
id: 'Clear selection',
|
|
17
|
+
defaultMessage: 'Clear selection',
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
|
|
13
21
|
export const MenuList = ({ children }) => {
|
|
14
22
|
return <DynamicHeightList>{children}</DynamicHeightList>;
|
|
15
23
|
};
|
|
@@ -86,8 +94,32 @@ export const DropdownIndicator = injectLazyLibs('reactSelect')((props) => {
|
|
|
86
94
|
|
|
87
95
|
export const ClearIndicator = injectLazyLibs('reactSelect')((props) => {
|
|
88
96
|
const { ClearIndicator } = props.reactSelect.components;
|
|
97
|
+
const intl = useIntl();
|
|
98
|
+
const fieldLabelId = props.selectProps?.['aria-labelledby'];
|
|
99
|
+
const clearLabelId = `${props.selectProps?.inputId}-clear-label`;
|
|
89
100
|
return (
|
|
90
|
-
<ClearIndicator
|
|
101
|
+
<ClearIndicator
|
|
102
|
+
{...props}
|
|
103
|
+
innerProps={{
|
|
104
|
+
...props.innerProps,
|
|
105
|
+
'aria-hidden': false,
|
|
106
|
+
...(fieldLabelId
|
|
107
|
+
? { 'aria-labelledby': `${fieldLabelId} ${clearLabelId}` }
|
|
108
|
+
: { 'aria-label': intl.formatMessage(messages.clearSelection) }),
|
|
109
|
+
role: 'button',
|
|
110
|
+
tabIndex: 0,
|
|
111
|
+
onKeyDown: (e) => {
|
|
112
|
+
if (e.key === 'Enter' || e.key === ' ' || e.key === 'Spacebar') {
|
|
113
|
+
e.preventDefault();
|
|
114
|
+
e.stopPropagation();
|
|
115
|
+
props.clearValue();
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
}}
|
|
119
|
+
>
|
|
120
|
+
<span id={clearLabelId} hidden>
|
|
121
|
+
{intl.formatMessage(messages.clearSelection)}
|
|
122
|
+
</span>
|
|
91
123
|
<Icon name={clearSVG} size="18px" color="#e40166" />
|
|
92
124
|
</ClearIndicator>
|
|
93
125
|
);
|
|
@@ -263,9 +263,10 @@ class SelectWidget extends Component {
|
|
|
263
263
|
<FormFieldWrapper {...this.props}>
|
|
264
264
|
<Select
|
|
265
265
|
id={`field-${id}`}
|
|
266
|
+
fieldTitle={this.props.title}
|
|
266
267
|
key={choices}
|
|
267
268
|
name={id}
|
|
268
|
-
aria-
|
|
269
|
+
aria-label={this.props.title || undefined}
|
|
269
270
|
menuShouldScrollIntoView={false}
|
|
270
271
|
isDisabled={disabled}
|
|
271
272
|
isSearchable={true}
|
|
@@ -304,7 +305,7 @@ class SelectWidget extends Component {
|
|
|
304
305
|
: undefined,
|
|
305
306
|
);
|
|
306
307
|
}}
|
|
307
|
-
isClearable={this.props.isClearable}
|
|
308
|
+
isClearable={!this.props.required && this.props.isClearable}
|
|
308
309
|
/>
|
|
309
310
|
</FormFieldWrapper>
|
|
310
311
|
);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import renderer from 'react-test-renderer';
|
|
3
|
+
import { render, screen } from '@testing-library/react';
|
|
3
4
|
import configureStore from 'redux-mock-store';
|
|
4
5
|
import { Provider } from 'react-intl-redux';
|
|
5
6
|
|
|
@@ -30,3 +31,46 @@ test('renders a text widget component', () => {
|
|
|
30
31
|
const json = component.toJSON();
|
|
31
32
|
expect(json).toMatchSnapshot();
|
|
32
33
|
});
|
|
34
|
+
|
|
35
|
+
test('adds aria-required attribute to input when required prop is true', () => {
|
|
36
|
+
const store = mockStore({
|
|
37
|
+
intl: { locale: 'en', messages: {} },
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
render(
|
|
41
|
+
<Provider store={store}>
|
|
42
|
+
<TextWidget
|
|
43
|
+
id="my-field"
|
|
44
|
+
title="My field"
|
|
45
|
+
onChange={() => {}}
|
|
46
|
+
onBlur={() => {}}
|
|
47
|
+
onClick={() => {}}
|
|
48
|
+
required={true}
|
|
49
|
+
/>
|
|
50
|
+
</Provider>,
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
expect(screen.getByRole('textbox')).toHaveAttribute('aria-required', 'true');
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test('adds aria-invalid attribute to input when field has errors', () => {
|
|
57
|
+
const store = mockStore({
|
|
58
|
+
intl: { locale: 'en', messages: {} },
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
render(
|
|
62
|
+
<Provider store={store}>
|
|
63
|
+
<TextWidget
|
|
64
|
+
id="my-field"
|
|
65
|
+
title="My field"
|
|
66
|
+
onChange={() => {}}
|
|
67
|
+
onBlur={() => {}}
|
|
68
|
+
onClick={() => {}}
|
|
69
|
+
required={true}
|
|
70
|
+
error={['This field is required']}
|
|
71
|
+
/>
|
|
72
|
+
</Provider>,
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
expect(screen.getByRole('textbox')).toHaveAttribute('aria-invalid', 'true');
|
|
76
|
+
});
|
|
@@ -85,6 +85,7 @@ class Search extends Component {
|
|
|
85
85
|
componentDidMount() {
|
|
86
86
|
this.doSearch();
|
|
87
87
|
this.setState({ isClient: true });
|
|
88
|
+
this.focusResults();
|
|
88
89
|
}
|
|
89
90
|
|
|
90
91
|
/**
|
|
@@ -97,6 +98,22 @@ class Search extends Component {
|
|
|
97
98
|
if (this.props.location.search !== nextProps.location.search) {
|
|
98
99
|
this.doSearch();
|
|
99
100
|
}
|
|
101
|
+
|
|
102
|
+
if (
|
|
103
|
+
JSON.stringify(this.props.search) !== JSON.stringify(nextProps.search)
|
|
104
|
+
) {
|
|
105
|
+
//on opening results page, move focus on results
|
|
106
|
+
this.focusResults();
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
focusResults = () => {
|
|
111
|
+
//on opening results page, move focus on results
|
|
112
|
+
setTimeout(function () {
|
|
113
|
+
if (document.querySelector('#page-search #search-results')) {
|
|
114
|
+
document.querySelector('#page-search #search-results').focus();
|
|
115
|
+
}
|
|
116
|
+
}, 100);
|
|
100
117
|
};
|
|
101
118
|
|
|
102
119
|
/**
|
|
@@ -162,7 +179,13 @@ class Search extends Component {
|
|
|
162
179
|
return (
|
|
163
180
|
<Container id="page-search">
|
|
164
181
|
<Helmet title={this.props.intl.formatMessage(messages.Search)} />
|
|
165
|
-
<div
|
|
182
|
+
<div
|
|
183
|
+
className="container"
|
|
184
|
+
role="region"
|
|
185
|
+
aria-live="polite"
|
|
186
|
+
id="search-results"
|
|
187
|
+
tabIndex={-1}
|
|
188
|
+
>
|
|
166
189
|
<article id="content">
|
|
167
190
|
<header>
|
|
168
191
|
<h1 className="documentFirstHeading">
|
|
@@ -4,7 +4,6 @@ import { Container } from 'semantic-ui-react';
|
|
|
4
4
|
import { useSelector } from 'react-redux';
|
|
5
5
|
import { useLocation } from 'react-router-dom';
|
|
6
6
|
import { withServerErrorCode } from '@plone/volto/helpers/Utils/Utils';
|
|
7
|
-
import { getBaseUrl } from '@plone/volto/helpers/Url/Url';
|
|
8
7
|
import BodyClass from '@plone/volto/helpers/BodyClass/BodyClass';
|
|
9
8
|
|
|
10
9
|
const Unauthorized = () => {
|
|
@@ -33,7 +32,7 @@ const Unauthorized = () => {
|
|
|
33
32
|
login: (
|
|
34
33
|
<Link
|
|
35
34
|
to={{
|
|
36
|
-
pathname: `${
|
|
35
|
+
pathname: `${location.pathname.replace(/\/$/, '')}/login`,
|
|
37
36
|
state: {
|
|
38
37
|
// This is needed to cover the use case of being logged in in
|
|
39
38
|
// another backend (eg. in development), having a token for
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { injectIntl } from 'react-intl';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import EventViewComponent from './EventView';
|
|
4
|
+
import { RealStoreWrapper as Wrapper } from '@plone/volto/storybook';
|
|
5
|
+
import config from '@plone/volto/registry';
|
|
6
|
+
const IntlEventViewComponent = injectIntl(EventViewComponent);
|
|
7
|
+
const { settings } = config;
|
|
8
|
+
|
|
9
|
+
function StoryComponent(args) {
|
|
10
|
+
return (
|
|
11
|
+
<Wrapper
|
|
12
|
+
customStore={{
|
|
13
|
+
intl: {
|
|
14
|
+
locale: 'en',
|
|
15
|
+
messages: {},
|
|
16
|
+
},
|
|
17
|
+
}}
|
|
18
|
+
>
|
|
19
|
+
<div id="toolbar" style={{ display: 'none' }} />
|
|
20
|
+
<IntlEventViewComponent
|
|
21
|
+
content={{
|
|
22
|
+
'@id': 'http://localhost:8080/Plone/my-page',
|
|
23
|
+
...args,
|
|
24
|
+
}}
|
|
25
|
+
/>
|
|
26
|
+
</Wrapper>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export const Default = StoryComponent.bind({});
|
|
31
|
+
Default.args = {
|
|
32
|
+
title: 'Hello World!',
|
|
33
|
+
end: '2019-06-23T16:20:00+00:00',
|
|
34
|
+
start: '2019-06-23T15:20:00+00:00',
|
|
35
|
+
attendees: [],
|
|
36
|
+
subjects: [],
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export const EventViewAllProps = StoryComponent.bind({});
|
|
40
|
+
EventViewAllProps.args = {
|
|
41
|
+
title: 'Hello World!',
|
|
42
|
+
description: 'Hi',
|
|
43
|
+
text: {
|
|
44
|
+
data: '<p>Hello World!</p>',
|
|
45
|
+
},
|
|
46
|
+
attendees: ['John Doe', 'Mario Rossi'],
|
|
47
|
+
contact_email: 'test@example.com',
|
|
48
|
+
contact_name: 'John Doe',
|
|
49
|
+
contact_phone: '0123456789',
|
|
50
|
+
end: '2019-06-24T15:20:00+00:00',
|
|
51
|
+
event_url: 'https://www.example.com',
|
|
52
|
+
location: 'Volto, Plone',
|
|
53
|
+
open_end: false,
|
|
54
|
+
recurrence: 'RRULE:FREQ=DAILY;INTERVAL=7;COUNT=7',
|
|
55
|
+
start: '2019-06-23T15:20:00+00:00',
|
|
56
|
+
subjects: ['Guillotina', 'Volto'],
|
|
57
|
+
whole_day: false,
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export const EventViewWithoutLinkToApiInTheText = StoryComponent.bind({});
|
|
61
|
+
EventViewWithoutLinkToApiInTheText.args = {
|
|
62
|
+
title: 'Hello World!',
|
|
63
|
+
attendees: [],
|
|
64
|
+
end: '2019-06-23T16:20:00+00:00',
|
|
65
|
+
start: '2019-06-23T15:20:00+00:00',
|
|
66
|
+
subjects: [],
|
|
67
|
+
text: {
|
|
68
|
+
data: `<p>Hello World!</p><p>This is an <a href="${settings.apiPath}/foo/bar">internal link</a> and a <a href="${settings.apiPath}/foo/baz">second link</a></p>`,
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
export default {
|
|
72
|
+
title: 'Public components/View/EventView',
|
|
73
|
+
component: EventViewComponent,
|
|
74
|
+
decorators: [
|
|
75
|
+
(Story) => (
|
|
76
|
+
<div className="ui segment form attached" style={{ width: '900px' }}>
|
|
77
|
+
<Story />
|
|
78
|
+
</div>
|
|
79
|
+
),
|
|
80
|
+
],
|
|
81
|
+
argTypes: {
|
|
82
|
+
end: {
|
|
83
|
+
control: 'date',
|
|
84
|
+
},
|
|
85
|
+
start: {
|
|
86
|
+
control: 'date',
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { injectIntl } from 'react-intl';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import FileViewComponent from './FileView';
|
|
4
|
+
import { RealStoreWrapper as Wrapper } from '@plone/volto/storybook';
|
|
5
|
+
|
|
6
|
+
const IntlFileViewComponent = injectIntl(FileViewComponent);
|
|
7
|
+
|
|
8
|
+
function StoryComponent(args) {
|
|
9
|
+
return (
|
|
10
|
+
<Wrapper customStore={{}}>
|
|
11
|
+
<div id="toolbar" style={{ display: 'none' }} />
|
|
12
|
+
<IntlFileViewComponent
|
|
13
|
+
content={{
|
|
14
|
+
...args,
|
|
15
|
+
file: {
|
|
16
|
+
download: 'file:///preview.pdf',
|
|
17
|
+
...args,
|
|
18
|
+
},
|
|
19
|
+
}}
|
|
20
|
+
/>
|
|
21
|
+
</Wrapper>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const Default = StoryComponent.bind({});
|
|
26
|
+
Default.args = {
|
|
27
|
+
title: 'Hello World!',
|
|
28
|
+
description: 'Hi',
|
|
29
|
+
filename: 'preview.pdf',
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export default {
|
|
33
|
+
title: 'Public components/View/FileView',
|
|
34
|
+
component: FileViewComponent,
|
|
35
|
+
decorators: [
|
|
36
|
+
(Story) => (
|
|
37
|
+
<div className="ui segment form attached" style={{ width: '900px' }}>
|
|
38
|
+
<Story />
|
|
39
|
+
</div>
|
|
40
|
+
),
|
|
41
|
+
],
|
|
42
|
+
argTypes: {
|
|
43
|
+
title: {
|
|
44
|
+
description: 'Title of the component',
|
|
45
|
+
},
|
|
46
|
+
filename: {
|
|
47
|
+
description: 'Name of the file',
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { injectIntl } from 'react-intl';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import LinkViewComponent from './LinkView';
|
|
4
|
+
import { RealStoreWrapper as Wrapper } from '@plone/volto/storybook';
|
|
5
|
+
|
|
6
|
+
const IntlLinkViewComponent = injectIntl(LinkViewComponent);
|
|
7
|
+
|
|
8
|
+
function StoryComponent(args) {
|
|
9
|
+
return (
|
|
10
|
+
<Wrapper
|
|
11
|
+
customStore={{
|
|
12
|
+
userSession: {
|
|
13
|
+
token: null,
|
|
14
|
+
},
|
|
15
|
+
intl: {
|
|
16
|
+
locale: 'en',
|
|
17
|
+
messages: {},
|
|
18
|
+
},
|
|
19
|
+
}}
|
|
20
|
+
>
|
|
21
|
+
<div id="toolbar" style={{ display: 'none' }} />
|
|
22
|
+
<IntlLinkViewComponent
|
|
23
|
+
token="1234"
|
|
24
|
+
content={{
|
|
25
|
+
...args,
|
|
26
|
+
}}
|
|
27
|
+
/>
|
|
28
|
+
</Wrapper>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export const Default = StoryComponent.bind({});
|
|
33
|
+
Default.args = {
|
|
34
|
+
title: 'Hello World!',
|
|
35
|
+
description: 'Hi',
|
|
36
|
+
remoteUrl: '/news',
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export default {
|
|
40
|
+
title: 'Public components/View/LinkView',
|
|
41
|
+
component: LinkViewComponent,
|
|
42
|
+
decorators: [
|
|
43
|
+
(Story) => (
|
|
44
|
+
<div className="ui segment form attached" style={{ width: '900px' }}>
|
|
45
|
+
<Story />
|
|
46
|
+
</div>
|
|
47
|
+
),
|
|
48
|
+
],
|
|
49
|
+
argTypes: {
|
|
50
|
+
title: {
|
|
51
|
+
description: 'Title of the component',
|
|
52
|
+
},
|
|
53
|
+
remoteUrl: {
|
|
54
|
+
description: 'remoteUrl mentioned in the page',
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { injectIntl } from 'react-intl';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import ListingViewComponent from './ListingView';
|
|
4
|
+
import { RealStoreWrapper as Wrapper } from '@plone/volto/storybook';
|
|
5
|
+
|
|
6
|
+
const IntlListingViewComponent = injectIntl(ListingViewComponent);
|
|
7
|
+
|
|
8
|
+
function StoryComponent(args) {
|
|
9
|
+
return (
|
|
10
|
+
<Wrapper
|
|
11
|
+
customStore={{
|
|
12
|
+
intl: {
|
|
13
|
+
locale: 'en',
|
|
14
|
+
messages: {},
|
|
15
|
+
},
|
|
16
|
+
}}
|
|
17
|
+
>
|
|
18
|
+
<div id="toolbar" style={{ display: 'none' }} />
|
|
19
|
+
<IntlListingViewComponent
|
|
20
|
+
content={{
|
|
21
|
+
title: 'Hello World!',
|
|
22
|
+
description: 'Hi',
|
|
23
|
+
...args,
|
|
24
|
+
}}
|
|
25
|
+
/>
|
|
26
|
+
</Wrapper>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export const Default = StoryComponent.bind({});
|
|
31
|
+
Default.args = {
|
|
32
|
+
items: [
|
|
33
|
+
{
|
|
34
|
+
title: 'My item',
|
|
35
|
+
description: 'My item description',
|
|
36
|
+
url: '/item',
|
|
37
|
+
'@type': 'Document',
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
title: 'Second item',
|
|
41
|
+
description: 'My second item description',
|
|
42
|
+
url: '/item2',
|
|
43
|
+
'@type': 'Document',
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export default {
|
|
49
|
+
title: 'Public components/View/ListingView',
|
|
50
|
+
component: ListingViewComponent,
|
|
51
|
+
decorators: [
|
|
52
|
+
(Story) => (
|
|
53
|
+
<div className="ui segment form attached" style={{ width: '900px' }}>
|
|
54
|
+
<Story />
|
|
55
|
+
</div>
|
|
56
|
+
),
|
|
57
|
+
],
|
|
58
|
+
argTypes: {
|
|
59
|
+
items: {
|
|
60
|
+
control: 'object',
|
|
61
|
+
description: 'Listed pages',
|
|
62
|
+
},
|
|
63
|
+
title: {
|
|
64
|
+
description: 'Title of the page listed',
|
|
65
|
+
},
|
|
66
|
+
description: {
|
|
67
|
+
description: 'Description of the page',
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { injectIntl } from 'react-intl';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import NewsItemViewComponent from './NewsItemView';
|
|
4
|
+
import { RealStoreWrapper as Wrapper } from '@plone/volto/storybook';
|
|
5
|
+
|
|
6
|
+
const IntlNewsItemViewComponent = injectIntl(NewsItemViewComponent);
|
|
7
|
+
|
|
8
|
+
function StoryComponent(args) {
|
|
9
|
+
return (
|
|
10
|
+
<Wrapper
|
|
11
|
+
customStore={{
|
|
12
|
+
intl: {
|
|
13
|
+
locale: 'en',
|
|
14
|
+
messages: {},
|
|
15
|
+
},
|
|
16
|
+
}}
|
|
17
|
+
>
|
|
18
|
+
<div id="toolbar" style={{ display: 'none' }} />
|
|
19
|
+
<IntlNewsItemViewComponent
|
|
20
|
+
content={{
|
|
21
|
+
...args,
|
|
22
|
+
}}
|
|
23
|
+
/>
|
|
24
|
+
</Wrapper>
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const Default = StoryComponent.bind({});
|
|
29
|
+
Default.args = {
|
|
30
|
+
title: 'Hello World!',
|
|
31
|
+
description: 'Hi',
|
|
32
|
+
text: {
|
|
33
|
+
data: '<p>Hello World!</p>',
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export default {
|
|
38
|
+
title: 'Public components/View/NewsItemView',
|
|
39
|
+
component: NewsItemViewComponent,
|
|
40
|
+
decorators: [
|
|
41
|
+
(Story) => (
|
|
42
|
+
<div className="ui segment form attached" style={{ width: '900px' }}>
|
|
43
|
+
<Story />
|
|
44
|
+
</div>
|
|
45
|
+
),
|
|
46
|
+
],
|
|
47
|
+
argTypes: {
|
|
48
|
+
title: {
|
|
49
|
+
description: 'Title of the page listed',
|
|
50
|
+
},
|
|
51
|
+
description: {
|
|
52
|
+
description: 'Description of the page',
|
|
53
|
+
},
|
|
54
|
+
text: {
|
|
55
|
+
description: 'Content',
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
};
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { injectIntl } from 'react-intl';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import RenderBlocksComponent from './RenderBlocks';
|
|
4
|
+
import { RealStoreWrapper as Wrapper } from '@plone/volto/storybook';
|
|
5
|
+
|
|
6
|
+
import config from '@plone/volto/registry';
|
|
7
|
+
|
|
8
|
+
const IntlRenderBlocksComponent = injectIntl(RenderBlocksComponent);
|
|
9
|
+
|
|
10
|
+
function StoryComponent(args) {
|
|
11
|
+
return (
|
|
12
|
+
<Wrapper
|
|
13
|
+
customStore={{
|
|
14
|
+
intl: {
|
|
15
|
+
locale: 'en',
|
|
16
|
+
messages: {},
|
|
17
|
+
},
|
|
18
|
+
}}
|
|
19
|
+
>
|
|
20
|
+
<div id="toolbar" style={{ display: 'none' }} />
|
|
21
|
+
<IntlRenderBlocksComponent
|
|
22
|
+
blocksConfig={{
|
|
23
|
+
...config.blocks.blocksConfig,
|
|
24
|
+
custom: {
|
|
25
|
+
id: 'custom',
|
|
26
|
+
...args,
|
|
27
|
+
},
|
|
28
|
+
}}
|
|
29
|
+
content={{
|
|
30
|
+
blocks_layout: {
|
|
31
|
+
items: ['a', 'b'],
|
|
32
|
+
},
|
|
33
|
+
...args,
|
|
34
|
+
}}
|
|
35
|
+
path="/foo"
|
|
36
|
+
/>
|
|
37
|
+
</Wrapper>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const Default = StoryComponent.bind({});
|
|
42
|
+
Default.args = {
|
|
43
|
+
view: ({ id, data }) => (
|
|
44
|
+
<div>
|
|
45
|
+
{id} - {data.text}
|
|
46
|
+
</div>
|
|
47
|
+
),
|
|
48
|
+
blocks: {
|
|
49
|
+
a: {
|
|
50
|
+
'@type': 'custom',
|
|
51
|
+
text: 'a',
|
|
52
|
+
},
|
|
53
|
+
b: {
|
|
54
|
+
'@type': 'custom',
|
|
55
|
+
text: 'b',
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
export const PathToBlocks = StoryComponent.bind({});
|
|
60
|
+
PathToBlocks.args = {
|
|
61
|
+
view: ({ id, data, path }) => (
|
|
62
|
+
<div>
|
|
63
|
+
id: {id} - text: {data.text} - path: {path}
|
|
64
|
+
</div>
|
|
65
|
+
),
|
|
66
|
+
|
|
67
|
+
blocks: {
|
|
68
|
+
a: {
|
|
69
|
+
'@type': 'custom',
|
|
70
|
+
text: 'bar',
|
|
71
|
+
},
|
|
72
|
+
b: {
|
|
73
|
+
'@type': 'custom',
|
|
74
|
+
text: 'foo',
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export const InvalidBlocks = StoryComponent.bind({});
|
|
80
|
+
InvalidBlocks.args = {
|
|
81
|
+
blocks_layout: {
|
|
82
|
+
items: ['MISSING-YOU-1', 'a', 'MISSING-YOU-2'],
|
|
83
|
+
},
|
|
84
|
+
blocks: {
|
|
85
|
+
a: {
|
|
86
|
+
'@type': 'custom',
|
|
87
|
+
text: 'bar',
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
export default {
|
|
92
|
+
title: 'Internal components/View/RenderBlocks',
|
|
93
|
+
component: RenderBlocksComponent,
|
|
94
|
+
decorators: [
|
|
95
|
+
(Story) => (
|
|
96
|
+
<div className="ui segment form attached" style={{ width: '900px' }}>
|
|
97
|
+
<Story />
|
|
98
|
+
</div>
|
|
99
|
+
),
|
|
100
|
+
],
|
|
101
|
+
argTypes: {
|
|
102
|
+
view: {
|
|
103
|
+
description: 'Pattern in which to place block content',
|
|
104
|
+
},
|
|
105
|
+
blocks: {
|
|
106
|
+
description: 'blocks in the page',
|
|
107
|
+
},
|
|
108
|
+
blocks_layout: {
|
|
109
|
+
description: 'block layout in the page',
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
};
|