@plone/volto 14.0.0-alpha.33 → 14.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.
- package/CHANGELOG.md +44 -0
- package/README.md +4 -1
- package/package.json +1 -1
- package/src/actions/schema/schema.js +4 -2
- package/src/actions/schema/schema.test.js +10 -0
- package/src/actions/vocabularies/vocabularies.js +3 -10
- package/src/actions/vocabularies/vocabularies.test.js +26 -0
- package/src/components/manage/Add/Add.jsx +1 -1
- package/src/components/manage/Blocks/Block/Edit.jsx +6 -1
- package/src/components/manage/Blocks/HeroImageLeft/schema.js +1 -1
- package/src/components/manage/Blocks/Listing/schema.js +2 -0
- package/src/components/manage/Edit/Edit.jsx +4 -1
- package/src/components/manage/Sidebar/ObjectBrowserBody.jsx +1 -1
- package/src/components/manage/Sidebar/SidebarPopup.stories.jsx +42 -0
- package/src/components/manage/Widgets/AlignWidget.jsx +14 -6
- package/src/components/manage/Widgets/AlignWidget.stories.jsx +38 -0
- package/src/components/manage/Widgets/ArrayWidget.stories.jsx +2 -2
- package/src/components/manage/Widgets/CheckboxWidget.jsx +9 -0
- package/src/components/manage/Widgets/CheckboxWidget.stories.jsx +38 -0
- package/src/components/manage/Widgets/DatetimeWidget.jsx +9 -0
- package/src/components/manage/Widgets/DatetimeWidget.stories.jsx +38 -0
- package/src/components/manage/Widgets/EmailWidget.jsx +10 -3
- package/src/components/manage/Widgets/EmailWidget.stories.jsx +38 -0
- package/src/components/manage/Widgets/FileWidget.jsx +18 -0
- package/src/components/manage/Widgets/FileWidget.stories.jsx +38 -0
- package/src/components/manage/Widgets/NumberWidget.jsx +9 -2
- package/src/components/manage/Widgets/NumberWidget.stories.jsx +39 -0
- package/src/components/manage/Widgets/ObjectBrowserWidget.stories.js +1 -1
- package/src/components/manage/Widgets/ObjectListWidget.jsx +26 -0
- package/src/components/manage/Widgets/ObjectListWidget.stories.js +166 -44
- package/src/components/manage/Widgets/ObjectWidget.jsx +4 -10
- package/src/components/manage/Widgets/ObjectWidget.stories.jsx +157 -0
- package/src/components/manage/Widgets/PasswordWidget.jsx +9 -2
- package/src/components/manage/Widgets/PasswordWidget.stories.jsx +38 -0
- package/src/components/manage/Widgets/QueryWidget.jsx +1 -3
- package/src/components/manage/Widgets/QueryWidget.stories.jsx +38 -0
- package/src/components/manage/Widgets/SelectWidget.stories.jsx +1 -1
- package/src/components/manage/Widgets/TextWidget.jsx +4 -3
- package/src/components/manage/Widgets/TextWidget.stories.jsx +38 -0
- package/src/components/manage/Widgets/TextareaWidget.jsx +10 -3
- package/src/components/manage/Widgets/TextareaWidget.stories.jsx +38 -0
- package/src/components/manage/Widgets/UrlWidget.jsx +12 -4
- package/src/components/manage/Widgets/UrlWidget.stories.jsx +38 -0
- package/src/components/manage/Widgets/WysiwygWidget.jsx +11 -3
- package/src/components/manage/Widgets/WysiwygWidget.stories.jsx +41 -0
- package/src/components/theme/Anontools/Anontools.jsx +0 -2
- package/src/components/theme/Anontools/Anontools.stories.jsx +24 -0
- package/src/components/theme/Breadcrumbs/Breadcrumbs.jsx +2 -5
- package/src/components/theme/Breadcrumbs/Breadcrumbs.stories.jsx +30 -0
- package/src/components/theme/Navigation/ContextNavigation.stories.js +27 -29
- package/src/components/theme/Navigation/NavItem.jsx +36 -0
- package/src/components/theme/Navigation/NavItems.jsx +2 -15
- package/src/components/theme/Navigation/Navigation.test.jsx +26 -0
- package/src/components/theme/View/RenderBlocks.jsx +10 -2
- package/src/config/Blocks.jsx +8 -0
- package/src/helpers/Blocks/Blocks.js +45 -3
- package/src/helpers/Blocks/Blocks.test.js +212 -0
- package/src/helpers/Extensions/withBlockExtensions.js +42 -2
- package/src/helpers/Extensions/withBlockSchemaEnhancer.js +77 -3
- package/src/helpers/Url/Url.js +2 -1
- package/src/helpers/Url/Url.test.js +7 -0
- package/src/helpers/Vocabularies/Vocabularies.js +12 -0
- package/src/helpers/index.js +2 -0
- package/src/storybook.jsx +50 -0
- package/src/components/manage/Sidebar/SidebarPopup.stories.mdx +0 -41
- package/src/components/theme/Anontools/Anontools.stories.mdx +0 -18
- package/src/components/theme/Breadcrumbs/Breadcrumbs.stories.mdx +0 -30
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,47 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
## 14.0.0-alpha.37 (2021-11-26)
|
|
4
|
+
|
|
5
|
+
### Bugfix
|
|
6
|
+
|
|
7
|
+
- Fixed object browser selected items number. @giuliaghisini
|
|
8
|
+
- Fix action vocabularies call avoiding regex look behind @nzambello
|
|
9
|
+
|
|
10
|
+
### Internal
|
|
11
|
+
|
|
12
|
+
- Fix select family widgets stories in storybook @sneridagh
|
|
13
|
+
|
|
14
|
+
## 14.0.0-alpha.36 (2021-11-25)
|
|
15
|
+
|
|
16
|
+
### Bugfix
|
|
17
|
+
|
|
18
|
+
- Fix regression in actions vocabularies calls because the change to use contextual schemas @sneridagh
|
|
19
|
+
- Include block schema enhancers (main block schema enhancer + variation schema enhancer) when calculating block default data @tiberiuichim
|
|
20
|
+
|
|
21
|
+
### Internal
|
|
22
|
+
|
|
23
|
+
- Fix references to old configuration style in apiExpanders documentation @tiberiuichim
|
|
24
|
+
- Add `applySchemaDefaults`, in addition to `applyBlockDefaults`, to allow reuse in object widgets and other advanced scenarios @tiberiuichim
|
|
25
|
+
|
|
26
|
+
## 14.0.0-alpha.35 (2021-11-24)
|
|
27
|
+
|
|
28
|
+
### Bugfix
|
|
29
|
+
|
|
30
|
+
- Fix `isInternalURL` when `settings.internalApiPath` is empty @tiberiuichim
|
|
31
|
+
- Fix external link not supported by Navigation component #2853. @ericof
|
|
32
|
+
- Get Add/Edit schema contextually #2852 @ericof
|
|
33
|
+
|
|
34
|
+
### Internal
|
|
35
|
+
|
|
36
|
+
- Upgrade p.restapi to 8.15.2 @sneridagh
|
|
37
|
+
|
|
38
|
+
## 14.0.0-alpha.34 (2021-11-20)
|
|
39
|
+
|
|
40
|
+
### Feature
|
|
41
|
+
|
|
42
|
+
- Apply form defaults from RenderBlocks and block Edit using a new helper, `applyBlockDefaults` @tiberiuichim
|
|
43
|
+
- Now each block config object can declare a schema factory (a function that can produce a schema) and this will be used to derive the default data for the block @tiberiuichim
|
|
44
|
+
|
|
3
45
|
## 14.0.0-alpha.33 (2021-11-20)
|
|
4
46
|
|
|
5
47
|
### Bugfix
|
|
@@ -15,6 +57,8 @@
|
|
|
15
57
|
### Internal
|
|
16
58
|
|
|
17
59
|
- Upgrade stylelint to v14 (vscode-stylelint requires it now) @sneridagh
|
|
60
|
+
- Add several more stories for Storybook @tiberiuichim
|
|
61
|
+
- Add 2 new Volto websites by Eau de web for EEA @tiberiuichim
|
|
18
62
|
|
|
19
63
|
## 14.0.0-alpha.32 (2021-11-09)
|
|
20
64
|
|
package/README.md
CHANGED
|
@@ -138,7 +138,10 @@ Volto is actively developed since 2017 and used in production since 2018 on the
|
|
|
138
138
|
- [Biblioteche Pianura Est](https://bibest.it) (Website of the Associated libraries of eastern plain. Developed by [RedTurtle](https://redturtle.it), 2021)
|
|
139
139
|
- [Camera di Commercio di Reggio Emilia](https://www.re.camcom.gov.it/) (Website Chamber of Commerce of Reggio Emilia. Developed by [RedTurtle](https://redturtle.it), 2021)
|
|
140
140
|
- [RawMaterial](https://rawmaterial.it/en) (Company's website. Developed by [RawMaterial](https://rawmaterial.it/en), 2021)
|
|
141
|
-
-
|
|
141
|
+
- [WISE-Freshwater](https://water.europa.eu/freshwater) (WISE-Freshwater, the Freshwater Information System for Europe. Developed by [Eau de web](https://eaudeweb.ro) for the European Environmental Agency, 2021)
|
|
142
|
+
- [EEA-IMSv4](https://www.eea.europa.eu/ims) (EEA Indicator Management System v4. Developed by [Eau de web](https://eaudeweb.ro) for the European Environmental Agency, 2021)
|
|
143
|
+
|
|
144
|
+
Please create a new [issue](https://github.com/plone/volto/issues/new) or [pull request](https://github.com/plone/volto/pulls) to add your Volto-site here!
|
|
142
145
|
|
|
143
146
|
## Documentation
|
|
144
147
|
|
package/package.json
CHANGED
|
@@ -14,14 +14,16 @@ import {
|
|
|
14
14
|
* Get schema function.
|
|
15
15
|
* @function getSchema
|
|
16
16
|
* @param {string} type Content type.
|
|
17
|
+
* @param {string} url Content url.
|
|
17
18
|
* @returns {Object} Get schema action.
|
|
18
19
|
*/
|
|
19
|
-
export function getSchema(type) {
|
|
20
|
+
export function getSchema(type, url) {
|
|
21
|
+
url = typeof url !== 'undefined' ? url : '';
|
|
20
22
|
return {
|
|
21
23
|
type: GET_SCHEMA,
|
|
22
24
|
request: {
|
|
23
25
|
op: 'get',
|
|
24
|
-
path:
|
|
26
|
+
path: `${url}/@types/${type}`,
|
|
25
27
|
},
|
|
26
28
|
};
|
|
27
29
|
}
|
|
@@ -11,5 +11,15 @@ describe('Schema action', () => {
|
|
|
11
11
|
expect(action.request.op).toEqual('get');
|
|
12
12
|
expect(action.request.path).toEqual(`/@types/${type}`);
|
|
13
13
|
});
|
|
14
|
+
|
|
15
|
+
it('should create an action to get the schema if url is passed', () => {
|
|
16
|
+
const type = 'Document';
|
|
17
|
+
const url = '/path/to/folder';
|
|
18
|
+
const action = getSchema(type, url);
|
|
19
|
+
|
|
20
|
+
expect(action.type).toEqual(GET_SCHEMA);
|
|
21
|
+
expect(action.request.op).toEqual('get');
|
|
22
|
+
expect(action.request.path).toEqual(`${url}/@types/${type}`);
|
|
23
|
+
});
|
|
14
24
|
});
|
|
15
25
|
});
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
GET_VOCABULARY,
|
|
8
8
|
GET_VOCABULARY_TOKEN_TITLE,
|
|
9
9
|
} from '@plone/volto/constants/ActionTypes';
|
|
10
|
-
import
|
|
10
|
+
import { getVocabName } from '@plone/volto/helpers/Vocabularies/Vocabularies';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Get vocabulary given a URL (coming from a Schema) or from a vocabulary name.
|
|
@@ -18,11 +18,8 @@ import config from '@plone/volto/registry';
|
|
|
18
18
|
* @returns {Object} Get vocabulary action.
|
|
19
19
|
*/
|
|
20
20
|
export function getVocabulary(vocabNameOrURL, query = null, start = 0) {
|
|
21
|
-
const { settings } = config;
|
|
22
21
|
// In case we have a URL, we have to get the vocabulary name
|
|
23
|
-
const vocabulary =
|
|
24
|
-
vocabNameOrURL &&
|
|
25
|
-
vocabNameOrURL.replace(`${settings.apiPath}/@vocabularies/`, '');
|
|
22
|
+
const vocabulary = getVocabName(vocabNameOrURL);
|
|
26
23
|
let queryString = `b_start=${start}`;
|
|
27
24
|
if (query) {
|
|
28
25
|
queryString = `${queryString}&title=${query}`;
|
|
@@ -47,12 +44,8 @@ export function getVocabulary(vocabNameOrURL, query = null, start = 0) {
|
|
|
47
44
|
* @returns {Object} Get vocabulary action.
|
|
48
45
|
*/
|
|
49
46
|
export function getVocabularyTokenTitle(vocabNameOrURL, token = null) {
|
|
50
|
-
const { settings } = config;
|
|
51
47
|
// In case we have a URL, we have to get the vocabulary name
|
|
52
|
-
const vocabulary = vocabNameOrURL
|
|
53
|
-
`${settings.apiPath}/@vocabularies/`,
|
|
54
|
-
'',
|
|
55
|
-
);
|
|
48
|
+
const vocabulary = getVocabName(vocabNameOrURL);
|
|
56
49
|
|
|
57
50
|
return {
|
|
58
51
|
type: GET_VOCABULARY_TOKEN_TITLE,
|
|
@@ -15,5 +15,31 @@ describe('Vocabularies actions', () => {
|
|
|
15
15
|
`/@vocabularies/${vocabulary}?b_start=0&title=${query}`,
|
|
16
16
|
);
|
|
17
17
|
});
|
|
18
|
+
it('should create an action to get a vocabulary if a URL is passed', () => {
|
|
19
|
+
const vocabulary =
|
|
20
|
+
'http://localhost:8080/@vocabularies/plone.app.vocabularies.Keywords';
|
|
21
|
+
const query = 'john';
|
|
22
|
+
const action = getVocabulary(vocabulary, query);
|
|
23
|
+
|
|
24
|
+
expect(action.type).toEqual(GET_VOCABULARY);
|
|
25
|
+
expect(action.vocabulary).toEqual(vocabulary);
|
|
26
|
+
expect(action.request.op).toEqual('get');
|
|
27
|
+
expect(action.request.path).toEqual(
|
|
28
|
+
`/@vocabularies/plone.app.vocabularies.Keywords?b_start=0&title=${query}`,
|
|
29
|
+
);
|
|
30
|
+
});
|
|
31
|
+
it('should create an action to get a vocabulary if a URL with path is passed', () => {
|
|
32
|
+
const vocabulary =
|
|
33
|
+
'http://localhost:8080/de/foo/bar/@vocabularies/plone.app.vocabularies.Keywords';
|
|
34
|
+
const query = 'john';
|
|
35
|
+
const action = getVocabulary(vocabulary, query);
|
|
36
|
+
|
|
37
|
+
expect(action.type).toEqual(GET_VOCABULARY);
|
|
38
|
+
expect(action.vocabulary).toEqual(vocabulary);
|
|
39
|
+
expect(action.request.op).toEqual('get');
|
|
40
|
+
expect(action.request.path).toEqual(
|
|
41
|
+
`/@vocabularies/plone.app.vocabularies.Keywords?b_start=0&title=${query}`,
|
|
42
|
+
);
|
|
43
|
+
});
|
|
18
44
|
});
|
|
19
45
|
});
|
|
@@ -149,7 +149,7 @@ class Add extends Component {
|
|
|
149
149
|
* @returns {undefined}
|
|
150
150
|
*/
|
|
151
151
|
componentDidMount() {
|
|
152
|
-
this.props.getSchema(this.props.type);
|
|
152
|
+
this.props.getSchema(this.props.type, getBaseUrl(this.props.pathname));
|
|
153
153
|
this.setState({ isClient: true });
|
|
154
154
|
}
|
|
155
155
|
|
|
@@ -12,6 +12,7 @@ import cx from 'classnames';
|
|
|
12
12
|
import { setSidebarTab } from '@plone/volto/actions';
|
|
13
13
|
import config from '@plone/volto/registry';
|
|
14
14
|
import withObjectBrowser from '@plone/volto/components/manage/Sidebar/ObjectBrowser';
|
|
15
|
+
import { applyBlockDefaults } from '@plone/volto/helpers';
|
|
15
16
|
|
|
16
17
|
import {
|
|
17
18
|
SidebarPortal,
|
|
@@ -165,7 +166,11 @@ export class Edit extends Component {
|
|
|
165
166
|
/* eslint-disable jsx-a11y/no-noninteractive-tabindex */
|
|
166
167
|
tabIndex={!blockHasOwnFocusManagement ? -1 : null}
|
|
167
168
|
>
|
|
168
|
-
<Block
|
|
169
|
+
<Block
|
|
170
|
+
{...this.props}
|
|
171
|
+
blockNode={this.blockNode}
|
|
172
|
+
data={applyBlockDefaults(this.props)}
|
|
173
|
+
/>
|
|
169
174
|
{this.props.manage && (
|
|
170
175
|
<SidebarPortal
|
|
171
176
|
selected={this.props.selected}
|
|
@@ -136,7 +136,10 @@ class Edit extends Component {
|
|
|
136
136
|
*/
|
|
137
137
|
componentDidMount() {
|
|
138
138
|
if (this.props.getRequest.loaded && this.props.content?.['@type']) {
|
|
139
|
-
this.props.getSchema(
|
|
139
|
+
this.props.getSchema(
|
|
140
|
+
this.props.content['@type'],
|
|
141
|
+
getBaseUrl(this.props.pathname),
|
|
142
|
+
);
|
|
140
143
|
}
|
|
141
144
|
this.setState({
|
|
142
145
|
isClient: true,
|
|
@@ -448,7 +448,7 @@ class ObjectBrowserBody extends Component {
|
|
|
448
448
|
<Segment className="infos">
|
|
449
449
|
{this.props.intl.formatMessage(messages.SelectedItems)}:{' '}
|
|
450
450
|
{this.props.data?.length}
|
|
451
|
-
{this.props.maximumSelectionSize && (
|
|
451
|
+
{this.props.maximumSelectionSize > 0 && (
|
|
452
452
|
<>
|
|
453
453
|
{' '}
|
|
454
454
|
{this.props.intl.formatMessage(messages.of)}{' '}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import SidebarPopup from './SidebarPopup';
|
|
3
|
+
import Wrapper from '@plone/volto/storybook';
|
|
4
|
+
|
|
5
|
+
const SidebarComponent = ({ children, ...args }) => {
|
|
6
|
+
return (
|
|
7
|
+
<Wrapper location={{ pathname: '/folder2/folder21/doc212' }}>
|
|
8
|
+
<div className="ui segment form attached" style={{ width: '400px' }}>
|
|
9
|
+
<p>
|
|
10
|
+
Render a right-side sidebar. Mainly used to edit block settings and
|
|
11
|
+
documents metadata (in the case of composite pages, with blocks). Use
|
|
12
|
+
the controls to toggle the open state.
|
|
13
|
+
</p>
|
|
14
|
+
<SidebarPopup {...args}>
|
|
15
|
+
<div style={{ padding: '1em' }}>
|
|
16
|
+
<h1>What Is Volto</h1>
|
|
17
|
+
<p>
|
|
18
|
+
Volto is a React-based frontend for content management systems,
|
|
19
|
+
currently supporting three backend implementations: Plone,
|
|
20
|
+
Guillotina and a NodeJS reference implementation.
|
|
21
|
+
</p>
|
|
22
|
+
<p>
|
|
23
|
+
Plone is a powerful, flexible Content Management Solution that is
|
|
24
|
+
easy to install, use and extend..
|
|
25
|
+
</p>
|
|
26
|
+
</div>
|
|
27
|
+
</SidebarPopup>
|
|
28
|
+
</div>
|
|
29
|
+
</Wrapper>
|
|
30
|
+
);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const Sidebar = SidebarComponent.bind({});
|
|
34
|
+
Sidebar.args = {
|
|
35
|
+
open: true,
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export default {
|
|
39
|
+
title: 'Internal Components/Sidebar',
|
|
40
|
+
component: SidebarPopup,
|
|
41
|
+
argTypes: {},
|
|
42
|
+
};
|
|
@@ -1,15 +1,23 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* AlignWidget component.
|
|
3
|
-
* To benefit from styling integration, use with a field named 'align'
|
|
4
|
-
* @module components/manage/Widgets/AlignWidget
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
1
|
import React from 'react';
|
|
8
2
|
import { injectIntl } from 'react-intl';
|
|
9
3
|
|
|
10
4
|
import { FormFieldWrapper } from '@plone/volto/components';
|
|
11
5
|
import AlignBlock from '@plone/volto/components/manage/Sidebar/AlignBlock';
|
|
12
6
|
|
|
7
|
+
/**
|
|
8
|
+
* AlignWidget component.
|
|
9
|
+
* To benefit from styling integration, use with a field named 'align'
|
|
10
|
+
*
|
|
11
|
+
* Example how this field would look in schema:
|
|
12
|
+
*
|
|
13
|
+
* ```jsx
|
|
14
|
+
* {
|
|
15
|
+
* title: 'Align',
|
|
16
|
+
* description: 'Layout align',
|
|
17
|
+
* widget: 'align',
|
|
18
|
+
* }
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
13
21
|
const AlignWidget = (props) => {
|
|
14
22
|
const { id, onChange, value } = props;
|
|
15
23
|
return (
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import AlignWidget from './AlignWidget';
|
|
3
|
+
import Wrapper from '@plone/volto/storybook';
|
|
4
|
+
|
|
5
|
+
const AlignWidgetComponent = ({ children, ...args }) => {
|
|
6
|
+
const [value, setValue] = React.useState([]);
|
|
7
|
+
const onChange = (block, value) => setValue(value);
|
|
8
|
+
return (
|
|
9
|
+
<Wrapper location={{ pathname: '/folder2/folder21/doc212' }}>
|
|
10
|
+
<div className="ui segment form attached" style={{ width: '400px' }}>
|
|
11
|
+
<AlignWidget
|
|
12
|
+
{...args}
|
|
13
|
+
id="alignWidgetItem"
|
|
14
|
+
title="Align"
|
|
15
|
+
block="testBlock"
|
|
16
|
+
value={value}
|
|
17
|
+
onChange={onChange}
|
|
18
|
+
/>
|
|
19
|
+
</div>
|
|
20
|
+
</Wrapper>
|
|
21
|
+
);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const Align = AlignWidgetComponent.bind({});
|
|
25
|
+
|
|
26
|
+
export default {
|
|
27
|
+
title: 'Widgets/Align',
|
|
28
|
+
component: AlignWidget,
|
|
29
|
+
decorators: [
|
|
30
|
+
(Story) => (
|
|
31
|
+
<div className="ui segment form attached" style={{ width: '400px' }}>
|
|
32
|
+
<h4>Standard layout-oriented align widget</h4>
|
|
33
|
+
<Story />
|
|
34
|
+
</div>
|
|
35
|
+
),
|
|
36
|
+
],
|
|
37
|
+
argTypes: {},
|
|
38
|
+
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { ArrayWidgetComponent } from './ArrayWidget';
|
|
3
3
|
import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
|
|
4
|
-
import Wrapper from '@plone/volto/storybook';
|
|
4
|
+
import { RealStoreWrapper as Wrapper } from '@plone/volto/storybook';
|
|
5
5
|
|
|
6
6
|
const ArrayComponent = injectLazyLibs([
|
|
7
7
|
'reactSelectCreateable',
|
|
@@ -155,7 +155,7 @@ Disabled.args = {
|
|
|
155
155
|
};
|
|
156
156
|
|
|
157
157
|
export default {
|
|
158
|
-
title: 'Widgets/
|
|
158
|
+
title: 'Widgets/Array',
|
|
159
159
|
component: ArrayComponent,
|
|
160
160
|
decorators: [
|
|
161
161
|
(Story) => (
|
|
@@ -14,6 +14,15 @@ import { FormFieldWrapper } from '@plone/volto/components';
|
|
|
14
14
|
* CheckboxWidget component class.
|
|
15
15
|
* @function CheckboxWidget
|
|
16
16
|
* @returns {string} Markup of the component.
|
|
17
|
+
*
|
|
18
|
+
* To use it, in schema properties, declare a field like:
|
|
19
|
+
*
|
|
20
|
+
* ```jsx
|
|
21
|
+
* {
|
|
22
|
+
* title: "Active",
|
|
23
|
+
* type: 'boolean',
|
|
24
|
+
* }
|
|
25
|
+
* ```
|
|
17
26
|
*/
|
|
18
27
|
const CheckboxWidget = (props) => {
|
|
19
28
|
const { id, title, value, onChange, isDisabled } = props;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import CheckboxWidget from './CheckboxWidget';
|
|
3
|
+
import Wrapper from '@plone/volto/storybook';
|
|
4
|
+
|
|
5
|
+
const CheckboxWidgetComponent = ({ children, ...args }) => {
|
|
6
|
+
const [value, setValue] = React.useState(false);
|
|
7
|
+
const onChange = (block, value) => setValue(value);
|
|
8
|
+
return (
|
|
9
|
+
<Wrapper location={{ pathname: '/folder2/folder21/doc212' }}>
|
|
10
|
+
<div className="ui segment form attached" style={{ width: '400px' }}>
|
|
11
|
+
<CheckboxWidget
|
|
12
|
+
{...args}
|
|
13
|
+
id="field"
|
|
14
|
+
title="Checkbox"
|
|
15
|
+
block="testBlock"
|
|
16
|
+
value={value}
|
|
17
|
+
onChange={onChange}
|
|
18
|
+
/>
|
|
19
|
+
</div>
|
|
20
|
+
<pre>Value: {JSON.stringify(value, null, 4)}</pre>
|
|
21
|
+
</Wrapper>
|
|
22
|
+
);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const Checkbox = CheckboxWidgetComponent.bind({});
|
|
26
|
+
|
|
27
|
+
export default {
|
|
28
|
+
title: 'Widgets/Checkbox',
|
|
29
|
+
component: CheckboxWidget,
|
|
30
|
+
decorators: [
|
|
31
|
+
(Story) => (
|
|
32
|
+
<div className="ui segment form attached" style={{ width: '400px' }}>
|
|
33
|
+
<Story />
|
|
34
|
+
</div>
|
|
35
|
+
),
|
|
36
|
+
],
|
|
37
|
+
argTypes: {},
|
|
38
|
+
};
|
|
@@ -70,6 +70,15 @@ const defaultTimeDateOnly = {
|
|
|
70
70
|
* DatetimeWidget component class
|
|
71
71
|
* @class DatetimeWidget
|
|
72
72
|
* @extends Component
|
|
73
|
+
*
|
|
74
|
+
* To use it, in schema properties, declare a field like:
|
|
75
|
+
*
|
|
76
|
+
* ```jsx
|
|
77
|
+
* {
|
|
78
|
+
* title: "Publish date",
|
|
79
|
+
* type: 'datetime',
|
|
80
|
+
* }
|
|
81
|
+
* ```
|
|
73
82
|
*/
|
|
74
83
|
class DatetimeWidget extends Component {
|
|
75
84
|
/**
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import DatetimeWidget from './DatetimeWidget';
|
|
3
|
+
import Wrapper from '@plone/volto/storybook';
|
|
4
|
+
|
|
5
|
+
const DatetimeWidgetComponent = ({ children, ...args }) => {
|
|
6
|
+
const [value, setValue] = React.useState(false);
|
|
7
|
+
const onChange = (block, value) => setValue(value);
|
|
8
|
+
return (
|
|
9
|
+
<Wrapper location={{ pathname: '/folder2/folder21/doc212' }}>
|
|
10
|
+
<div className="ui segment form attached" style={{ width: '400px' }}>
|
|
11
|
+
<DatetimeWidget
|
|
12
|
+
{...args}
|
|
13
|
+
id="field"
|
|
14
|
+
title="Datetime"
|
|
15
|
+
block="testBlock"
|
|
16
|
+
value={value}
|
|
17
|
+
onChange={onChange}
|
|
18
|
+
/>
|
|
19
|
+
</div>
|
|
20
|
+
<pre>Value: {JSON.stringify(value, null, 4)}</pre>
|
|
21
|
+
</Wrapper>
|
|
22
|
+
);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const Datetime = DatetimeWidgetComponent.bind({});
|
|
26
|
+
|
|
27
|
+
export default {
|
|
28
|
+
title: 'Widgets/Datetime',
|
|
29
|
+
component: DatetimeWidget,
|
|
30
|
+
decorators: [
|
|
31
|
+
(Story) => (
|
|
32
|
+
<div className="ui segment form attached" style={{ width: '400px' }}>
|
|
33
|
+
<Story />
|
|
34
|
+
</div>
|
|
35
|
+
),
|
|
36
|
+
],
|
|
37
|
+
argTypes: {},
|
|
38
|
+
};
|
|
@@ -8,9 +8,16 @@ import PropTypes from 'prop-types';
|
|
|
8
8
|
import React from 'react';
|
|
9
9
|
import { Input } from 'semantic-ui-react';
|
|
10
10
|
|
|
11
|
-
/** EmailWidget
|
|
12
|
-
*
|
|
13
|
-
*
|
|
11
|
+
/** EmailWidget, a widget for email addresses
|
|
12
|
+
*
|
|
13
|
+
* To use it, in schema properties, declare a field like:
|
|
14
|
+
*
|
|
15
|
+
* ```jsx
|
|
16
|
+
* {
|
|
17
|
+
* title: "Email",
|
|
18
|
+
* widget: 'email',
|
|
19
|
+
* }
|
|
20
|
+
* ```
|
|
14
21
|
*/
|
|
15
22
|
const EmailWidget = (props) => {
|
|
16
23
|
const { id, value, onChange, onBlur, onClick, minLength, maxLength } = props;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import EmailWidget from './EmailWidget';
|
|
3
|
+
import Wrapper from '@plone/volto/storybook';
|
|
4
|
+
|
|
5
|
+
const EmailWidgetComponent = ({ children, ...args }) => {
|
|
6
|
+
const [value, setValue] = React.useState('');
|
|
7
|
+
const onChange = (block, value) => setValue(value);
|
|
8
|
+
return (
|
|
9
|
+
<Wrapper location={{ pathname: '/folder2/folder21/doc212' }}>
|
|
10
|
+
<div className="ui segment form attached" style={{ width: '400px' }}>
|
|
11
|
+
<EmailWidget
|
|
12
|
+
{...args}
|
|
13
|
+
id="field"
|
|
14
|
+
title="Email"
|
|
15
|
+
block="testBlock"
|
|
16
|
+
value={value}
|
|
17
|
+
onChange={onChange}
|
|
18
|
+
/>
|
|
19
|
+
</div>
|
|
20
|
+
<pre>Value: {JSON.stringify(value, null, 4)}</pre>
|
|
21
|
+
</Wrapper>
|
|
22
|
+
);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const Email = EmailWidgetComponent.bind({});
|
|
26
|
+
|
|
27
|
+
export default {
|
|
28
|
+
title: 'Widgets/Email',
|
|
29
|
+
component: EmailWidget,
|
|
30
|
+
decorators: [
|
|
31
|
+
(Story) => (
|
|
32
|
+
<div className="ui segment form attached" style={{ width: '400px' }}>
|
|
33
|
+
<Story />
|
|
34
|
+
</div>
|
|
35
|
+
),
|
|
36
|
+
],
|
|
37
|
+
argTypes: {},
|
|
38
|
+
};
|
|
@@ -51,6 +51,24 @@ const messages = defineMessages({
|
|
|
51
51
|
* FileWidget component class.
|
|
52
52
|
* @function FileWidget
|
|
53
53
|
* @returns {string} Markup of the component.
|
|
54
|
+
*
|
|
55
|
+
* To use it, in schema properties, declare a field like:
|
|
56
|
+
*
|
|
57
|
+
* ```jsx
|
|
58
|
+
* {
|
|
59
|
+
* title: "File",
|
|
60
|
+
* widget: 'file',
|
|
61
|
+
* }
|
|
62
|
+
* ```
|
|
63
|
+
* or:
|
|
64
|
+
*
|
|
65
|
+
* ```jsx
|
|
66
|
+
* {
|
|
67
|
+
* title: "File",
|
|
68
|
+
* type: 'object',
|
|
69
|
+
* }
|
|
70
|
+
* ```
|
|
71
|
+
*
|
|
54
72
|
*/
|
|
55
73
|
const FileWidget = (props) => {
|
|
56
74
|
const { id, value, onChange } = props;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import FileWidget from './FileWidget';
|
|
3
|
+
import Wrapper from '@plone/volto/storybook';
|
|
4
|
+
|
|
5
|
+
const FileWidgetComponent = ({ children, ...args }) => {
|
|
6
|
+
const [value, setValue] = React.useState('');
|
|
7
|
+
const onChange = (block, value) => setValue(value);
|
|
8
|
+
return (
|
|
9
|
+
<Wrapper location={{ pathname: '/folder2/folder21/doc212' }}>
|
|
10
|
+
<div className="ui segment form attached" style={{ width: '400px' }}>
|
|
11
|
+
<FileWidget
|
|
12
|
+
{...args}
|
|
13
|
+
id="field"
|
|
14
|
+
title="File"
|
|
15
|
+
block="testBlock"
|
|
16
|
+
value={value}
|
|
17
|
+
onChange={onChange}
|
|
18
|
+
/>
|
|
19
|
+
</div>
|
|
20
|
+
<pre>Value: {JSON.stringify(value, null, 4)}</pre>
|
|
21
|
+
</Wrapper>
|
|
22
|
+
);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const File = FileWidgetComponent.bind({});
|
|
26
|
+
|
|
27
|
+
export default {
|
|
28
|
+
title: 'Widgets/File',
|
|
29
|
+
component: FileWidget,
|
|
30
|
+
decorators: [
|
|
31
|
+
(Story) => (
|
|
32
|
+
<div className="ui segment form attached" style={{ width: '400px' }}>
|
|
33
|
+
<Story />
|
|
34
|
+
</div>
|
|
35
|
+
),
|
|
36
|
+
],
|
|
37
|
+
argTypes: {},
|
|
38
|
+
};
|
|
@@ -11,8 +11,15 @@ import { injectIntl } from 'react-intl';
|
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* NumberWidget component class.
|
|
14
|
-
*
|
|
15
|
-
*
|
|
14
|
+
*
|
|
15
|
+
* To use it, in schema properties, declare a field like:
|
|
16
|
+
*
|
|
17
|
+
* ```jsx
|
|
18
|
+
* {
|
|
19
|
+
* title: "Number",
|
|
20
|
+
* type: 'number',
|
|
21
|
+
* }
|
|
22
|
+
* ```
|
|
16
23
|
*/
|
|
17
24
|
const NumberWidget = (props) => {
|
|
18
25
|
const {
|