@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
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import NumberWidget from './NumberWidget';
|
|
3
|
+
import Wrapper from '@plone/volto/storybook';
|
|
4
|
+
|
|
5
|
+
const NumberWidgetComponent = ({ 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
|
+
<NumberWidget
|
|
12
|
+
{...args}
|
|
13
|
+
id="field"
|
|
14
|
+
title="Number"
|
|
15
|
+
block="testBlock"
|
|
16
|
+
value={value}
|
|
17
|
+
onChange={onChange}
|
|
18
|
+
default={10}
|
|
19
|
+
/>
|
|
20
|
+
</div>
|
|
21
|
+
<pre>Value: {JSON.stringify(value, null, 4)}</pre>
|
|
22
|
+
</Wrapper>
|
|
23
|
+
);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const Number = NumberWidgetComponent.bind({});
|
|
27
|
+
|
|
28
|
+
export default {
|
|
29
|
+
title: 'Widgets/Number',
|
|
30
|
+
component: NumberWidget,
|
|
31
|
+
decorators: [
|
|
32
|
+
(Story) => (
|
|
33
|
+
<div className="ui segment form attached" style={{ width: '400px' }}>
|
|
34
|
+
<Story />
|
|
35
|
+
</div>
|
|
36
|
+
),
|
|
37
|
+
],
|
|
38
|
+
argTypes: {},
|
|
39
|
+
};
|
|
@@ -30,6 +30,32 @@ const messages = defineMessages({
|
|
|
30
30
|
},
|
|
31
31
|
});
|
|
32
32
|
|
|
33
|
+
/**
|
|
34
|
+
* This is a DataGridField-equivalent widget for schema-based values.
|
|
35
|
+
* The shape of the items in the array is defined using a schema.
|
|
36
|
+
*
|
|
37
|
+
* ObjectListWidget can receive an optional `schemaExtender` prop which is
|
|
38
|
+
* a function that can mutate the schema for each individual item in the array.
|
|
39
|
+
* An example schema definition of the a field that renders with the
|
|
40
|
+
* ObjectListWidget:
|
|
41
|
+
*
|
|
42
|
+
* ```jsx
|
|
43
|
+
* columns: {
|
|
44
|
+
* title: 'Columns',
|
|
45
|
+
* description: 'Leave empty to show all columns',
|
|
46
|
+
* schema: SomeItemSchema,
|
|
47
|
+
* widget: 'object_list',
|
|
48
|
+
* schemaExtender: (schema, data) => {
|
|
49
|
+
* const mutated = lodash.cloneDeep(schema);
|
|
50
|
+
* mutated.properties.extraField = {
|
|
51
|
+
* title: 'Extra field',
|
|
52
|
+
* }
|
|
53
|
+
* mutated.fieldsets[0].fields.push('extraField');
|
|
54
|
+
* return mutated;
|
|
55
|
+
* }
|
|
56
|
+
* },
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
33
59
|
const ObjectListWidget = (props) => {
|
|
34
60
|
const {
|
|
35
61
|
block,
|
|
@@ -3,46 +3,89 @@ import Wrapper from '@plone/volto/storybook';
|
|
|
3
3
|
import React from 'react';
|
|
4
4
|
import { searchResults } from './ObjectBrowserWidget.stories';
|
|
5
5
|
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
6
|
+
const defaultSchema = {
|
|
7
|
+
title: 'Item',
|
|
8
|
+
addMessage: 'Add item',
|
|
9
|
+
fieldsets: [
|
|
10
|
+
{
|
|
11
|
+
id: 'default',
|
|
12
|
+
title: 'Default',
|
|
13
|
+
fields: ['href', 'title', 'description', 'preview_image'],
|
|
14
|
+
},
|
|
15
|
+
],
|
|
16
|
+
|
|
17
|
+
properties: {
|
|
18
|
+
href: {
|
|
19
|
+
title: 'Source',
|
|
20
|
+
widget: 'object_browser',
|
|
21
|
+
mode: 'link',
|
|
22
|
+
selectedItemAttrs: [
|
|
23
|
+
'Title',
|
|
24
|
+
'Description',
|
|
25
|
+
'hasPreviewImage',
|
|
26
|
+
'headtitle',
|
|
27
|
+
],
|
|
28
|
+
allowExternals: true,
|
|
29
|
+
},
|
|
30
|
+
title: {
|
|
31
|
+
title: 'Title',
|
|
32
|
+
},
|
|
33
|
+
description: {
|
|
34
|
+
title: 'Description',
|
|
35
|
+
},
|
|
36
|
+
preview_image: {
|
|
37
|
+
title: 'Preview image',
|
|
38
|
+
widget: 'object_browser',
|
|
39
|
+
mode: 'image',
|
|
40
|
+
allowExternals: true,
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
required: [],
|
|
44
|
+
};
|
|
17
45
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
'hasPreviewImage',
|
|
27
|
-
'headtitle',
|
|
28
|
-
],
|
|
29
|
-
allowExternals: true,
|
|
30
|
-
},
|
|
31
|
-
title: {
|
|
32
|
-
title: 'Title',
|
|
33
|
-
},
|
|
34
|
-
description: {
|
|
35
|
-
title: 'Description',
|
|
36
|
-
},
|
|
37
|
-
preview_image: {
|
|
38
|
-
title: 'Preview image',
|
|
39
|
-
widget: 'object_browser',
|
|
40
|
-
mode: 'image',
|
|
41
|
-
allowExternals: true,
|
|
42
|
-
},
|
|
46
|
+
const multiFieldsetSchema = {
|
|
47
|
+
title: 'Item',
|
|
48
|
+
addMessage: 'Add item',
|
|
49
|
+
fieldsets: [
|
|
50
|
+
{
|
|
51
|
+
id: 'default',
|
|
52
|
+
title: 'Default',
|
|
53
|
+
fields: ['href', 'title', 'description'],
|
|
43
54
|
},
|
|
44
|
-
|
|
45
|
-
|
|
55
|
+
{
|
|
56
|
+
id: 'preview',
|
|
57
|
+
title: 'Preview',
|
|
58
|
+
fields: ['preview_image'],
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
|
|
62
|
+
properties: {
|
|
63
|
+
href: {
|
|
64
|
+
title: 'Source',
|
|
65
|
+
widget: 'object_browser',
|
|
66
|
+
mode: 'link',
|
|
67
|
+
selectedItemAttrs: [
|
|
68
|
+
'Title',
|
|
69
|
+
'Description',
|
|
70
|
+
'hasPreviewImage',
|
|
71
|
+
'headtitle',
|
|
72
|
+
],
|
|
73
|
+
allowExternals: true,
|
|
74
|
+
},
|
|
75
|
+
title: {
|
|
76
|
+
title: 'Title',
|
|
77
|
+
},
|
|
78
|
+
description: {
|
|
79
|
+
title: 'Description',
|
|
80
|
+
},
|
|
81
|
+
preview_image: {
|
|
82
|
+
title: 'Preview image',
|
|
83
|
+
widget: 'object_browser',
|
|
84
|
+
mode: 'image',
|
|
85
|
+
allowExternals: true,
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
required: [],
|
|
46
89
|
};
|
|
47
90
|
|
|
48
91
|
const customStore = {
|
|
@@ -59,7 +102,12 @@ const customStore = {
|
|
|
59
102
|
},
|
|
60
103
|
};
|
|
61
104
|
|
|
62
|
-
const ObjectListWidgetComponent = (
|
|
105
|
+
const ObjectListWidgetComponent = ({
|
|
106
|
+
children,
|
|
107
|
+
secondarySchema,
|
|
108
|
+
enableSchemaExtender,
|
|
109
|
+
...args
|
|
110
|
+
}) => {
|
|
63
111
|
const [value, setValue] = React.useState([]);
|
|
64
112
|
const onChange = (block, value) => setValue(value);
|
|
65
113
|
|
|
@@ -69,6 +117,7 @@ const ObjectListWidgetComponent = (args) => {
|
|
|
69
117
|
customStore={customStore}
|
|
70
118
|
>
|
|
71
119
|
<div className="ui segment form attached" style={{ width: '400px' }}>
|
|
120
|
+
{children}
|
|
72
121
|
<ObjectListWidgetDefault
|
|
73
122
|
{...args}
|
|
74
123
|
id="SliderItem"
|
|
@@ -76,25 +125,98 @@ const ObjectListWidgetComponent = (args) => {
|
|
|
76
125
|
block="testBlock"
|
|
77
126
|
value={value}
|
|
78
127
|
onChange={onChange}
|
|
79
|
-
|
|
128
|
+
schemaExtender={
|
|
129
|
+
enableSchemaExtender &&
|
|
130
|
+
((schema, data, intl) => {
|
|
131
|
+
const finalSchema =
|
|
132
|
+
data?.href?.[0]?.['@id'] === '/image'
|
|
133
|
+
? {
|
|
134
|
+
...schema,
|
|
135
|
+
fieldsets: [
|
|
136
|
+
{
|
|
137
|
+
...schema.fieldsets[0],
|
|
138
|
+
fields: [
|
|
139
|
+
...schema.fieldsets[0].fields,
|
|
140
|
+
...secondarySchema.fieldsets[0].fields,
|
|
141
|
+
],
|
|
142
|
+
},
|
|
143
|
+
...schema.fieldsets.slice(1),
|
|
144
|
+
...secondarySchema.fieldsets.slice(1),
|
|
145
|
+
],
|
|
146
|
+
properties: {
|
|
147
|
+
...schema.properties,
|
|
148
|
+
...secondarySchema.properties,
|
|
149
|
+
},
|
|
150
|
+
}
|
|
151
|
+
: schema;
|
|
152
|
+
return finalSchema;
|
|
153
|
+
})
|
|
154
|
+
}
|
|
80
155
|
/>
|
|
156
|
+
<hr />
|
|
157
|
+
<strong>Resulting value</strong>
|
|
81
158
|
<pre>{JSON.stringify(value, null, 4)}</pre>
|
|
82
159
|
</div>
|
|
83
160
|
</Wrapper>
|
|
84
161
|
);
|
|
85
162
|
};
|
|
86
163
|
|
|
164
|
+
export const Default = ObjectListWidgetComponent.bind({});
|
|
165
|
+
Default.args = {
|
|
166
|
+
schema: defaultSchema,
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
export const MultipleFieldsets = ObjectListWidgetComponent.bind({});
|
|
170
|
+
MultipleFieldsets.args = {
|
|
171
|
+
schema: multiFieldsetSchema,
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
const defaultSecondarySchema = {
|
|
175
|
+
title: 'Additional fields',
|
|
176
|
+
fieldsets: [
|
|
177
|
+
{
|
|
178
|
+
id: 'Default',
|
|
179
|
+
title: 'Default',
|
|
180
|
+
fields: ['size'],
|
|
181
|
+
},
|
|
182
|
+
],
|
|
183
|
+
properties: {
|
|
184
|
+
size: {
|
|
185
|
+
title: 'Image size',
|
|
186
|
+
},
|
|
187
|
+
},
|
|
188
|
+
required: [],
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
export const SchemaExtender = (args) => {
|
|
192
|
+
return (
|
|
193
|
+
<ObjectListWidgetComponent enableSchemaExtender={true} {...args}>
|
|
194
|
+
<>
|
|
195
|
+
Notice the form changes if you pick "I am an image" for the{' '}
|
|
196
|
+
<em>source</em> field. We're achieving that by passing a custom{' '}
|
|
197
|
+
<em>schemaExtender</em> that combines the fields of the{' '}
|
|
198
|
+
<em>secondarySchema</em> storybook control.
|
|
199
|
+
</>
|
|
200
|
+
</ObjectListWidgetComponent>
|
|
201
|
+
);
|
|
202
|
+
};
|
|
203
|
+
SchemaExtender.args = {
|
|
204
|
+
schema: defaultSchema,
|
|
205
|
+
secondarySchema: defaultSecondarySchema,
|
|
206
|
+
};
|
|
207
|
+
|
|
87
208
|
export default {
|
|
88
|
-
title: 'Widgets/Object List
|
|
209
|
+
title: 'Widgets/Object List (JSON)',
|
|
89
210
|
component: ObjectListWidgetDefault,
|
|
90
211
|
decorators: [
|
|
91
212
|
(Story) => (
|
|
92
213
|
<div className="ui segment form attached" style={{ width: '400px' }}>
|
|
214
|
+
<h4>A DataGridField-like for lists of JSON objects</h4>
|
|
93
215
|
<Story />
|
|
94
216
|
</div>
|
|
95
217
|
),
|
|
96
218
|
],
|
|
97
|
-
|
|
219
|
+
argTypes: {
|
|
220
|
+
schema: {},
|
|
221
|
+
},
|
|
98
222
|
};
|
|
99
|
-
|
|
100
|
-
export const ObjectListWidget = () => <ObjectListWidgetComponent />;
|
|
@@ -58,17 +58,11 @@ const FieldSet = ({
|
|
|
58
58
|
|
|
59
59
|
/**
|
|
60
60
|
*
|
|
61
|
-
*
|
|
61
|
+
* A JSON data editor widget based on a schema. If you want to represent complex
|
|
62
|
+
* data using a single field, this is the widget to use.
|
|
62
63
|
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
* Each tab has the title of the fieldset it renders.
|
|
66
|
-
*
|
|
67
|
-
* @param {object} schema Schema, follows Plone dexterity serialized schema
|
|
68
|
-
* @param {object} value Object value, a JS object
|
|
69
|
-
* @param {function} onChange Callback for object changed
|
|
70
|
-
* @param {object} errors A list errors
|
|
71
|
-
* @param {string} id Field id
|
|
64
|
+
* If there are multiple field sets, it renders a Tab component with multiple
|
|
65
|
+
* tab panes. Each tab has the title of the fieldset it renders.
|
|
72
66
|
*/
|
|
73
67
|
const ObjectWidget = ({
|
|
74
68
|
block,
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { searchResults } from './ObjectBrowserWidget.stories';
|
|
3
|
+
import ObjectWidgetDefault from './ObjectWidget';
|
|
4
|
+
import Wrapper from '@plone/volto/storybook';
|
|
5
|
+
|
|
6
|
+
const defaultSchema = {
|
|
7
|
+
title: 'Item',
|
|
8
|
+
addMessage: 'Add item',
|
|
9
|
+
fieldsets: [
|
|
10
|
+
{
|
|
11
|
+
id: 'default',
|
|
12
|
+
title: 'Default',
|
|
13
|
+
fields: ['href', 'title', 'description', 'preview_image'],
|
|
14
|
+
},
|
|
15
|
+
],
|
|
16
|
+
|
|
17
|
+
properties: {
|
|
18
|
+
href: {
|
|
19
|
+
title: 'Source',
|
|
20
|
+
widget: 'object_browser',
|
|
21
|
+
mode: 'link',
|
|
22
|
+
selectedItemAttrs: [
|
|
23
|
+
'Title',
|
|
24
|
+
'Description',
|
|
25
|
+
'hasPreviewImage',
|
|
26
|
+
'headtitle',
|
|
27
|
+
],
|
|
28
|
+
allowExternals: true,
|
|
29
|
+
},
|
|
30
|
+
title: {
|
|
31
|
+
title: 'Title',
|
|
32
|
+
},
|
|
33
|
+
description: {
|
|
34
|
+
title: 'Description',
|
|
35
|
+
},
|
|
36
|
+
preview_image: {
|
|
37
|
+
title: 'Preview image',
|
|
38
|
+
widget: 'object_browser',
|
|
39
|
+
mode: 'image',
|
|
40
|
+
allowExternals: true,
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
required: [],
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const multipleFieldsets = {
|
|
47
|
+
title: 'Item',
|
|
48
|
+
addMessage: 'Add item',
|
|
49
|
+
fieldsets: [
|
|
50
|
+
{
|
|
51
|
+
id: 'default',
|
|
52
|
+
title: 'Default',
|
|
53
|
+
fields: ['href', 'title', 'description', 'preview_image'],
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
id: 'second',
|
|
57
|
+
title: 'Secondary',
|
|
58
|
+
fields: ['contributors'],
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
|
|
62
|
+
properties: {
|
|
63
|
+
contributors: {
|
|
64
|
+
title: 'Contributors',
|
|
65
|
+
description: 'Example field with contributors information',
|
|
66
|
+
wiget: 'textarea',
|
|
67
|
+
},
|
|
68
|
+
href: {
|
|
69
|
+
title: 'Source',
|
|
70
|
+
widget: 'object_browser',
|
|
71
|
+
mode: 'link',
|
|
72
|
+
selectedItemAttrs: [
|
|
73
|
+
'Title',
|
|
74
|
+
'Description',
|
|
75
|
+
'hasPreviewImage',
|
|
76
|
+
'headtitle',
|
|
77
|
+
],
|
|
78
|
+
allowExternals: true,
|
|
79
|
+
},
|
|
80
|
+
title: {
|
|
81
|
+
title: 'Title',
|
|
82
|
+
},
|
|
83
|
+
description: {
|
|
84
|
+
title: 'Description',
|
|
85
|
+
},
|
|
86
|
+
preview_image: {
|
|
87
|
+
title: 'Preview image',
|
|
88
|
+
widget: 'object_browser',
|
|
89
|
+
mode: 'image',
|
|
90
|
+
allowExternals: true,
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
required: [],
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const customStore = {
|
|
97
|
+
search: {
|
|
98
|
+
subrequests: {
|
|
99
|
+
'testBlock-link': searchResults,
|
|
100
|
+
'testBlock-image': searchResults,
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
userSession: { token: '1234' },
|
|
104
|
+
intl: {
|
|
105
|
+
locale: 'en',
|
|
106
|
+
messages: {},
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const ObjectWidgetComponent = ({ children, ...args }) => {
|
|
111
|
+
const [value, setValue] = React.useState();
|
|
112
|
+
const onChange = (block, value) => setValue(value);
|
|
113
|
+
return (
|
|
114
|
+
<Wrapper
|
|
115
|
+
location={{ pathname: '/folder2/folder21/doc212' }}
|
|
116
|
+
customStore={customStore}
|
|
117
|
+
>
|
|
118
|
+
<div className="ui segment form attached" style={{ width: '400px' }}>
|
|
119
|
+
<ObjectWidgetDefault
|
|
120
|
+
{...args}
|
|
121
|
+
id="SliderItem"
|
|
122
|
+
title="Slider Item"
|
|
123
|
+
block="testBlock"
|
|
124
|
+
value={value}
|
|
125
|
+
onChange={onChange}
|
|
126
|
+
/>
|
|
127
|
+
<pre>Value: {JSON.stringify(value, null, 4)}</pre>
|
|
128
|
+
</div>
|
|
129
|
+
</Wrapper>
|
|
130
|
+
);
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
export const Default = ObjectWidgetComponent.bind({});
|
|
134
|
+
Default.args = {
|
|
135
|
+
schema: defaultSchema,
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
export const MultipleFieldsets = ObjectWidgetComponent.bind({});
|
|
139
|
+
MultipleFieldsets.args = {
|
|
140
|
+
schema: multipleFieldsets,
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
export default {
|
|
144
|
+
title: 'Widgets/Object (JSON)',
|
|
145
|
+
component: ObjectWidgetDefault,
|
|
146
|
+
decorators: [
|
|
147
|
+
(Story) => (
|
|
148
|
+
<div className="ui segment form attached" style={{ width: '400px' }}>
|
|
149
|
+
<h4>Schema-based editing of JSON values</h4>
|
|
150
|
+
<Story />
|
|
151
|
+
</div>
|
|
152
|
+
),
|
|
153
|
+
],
|
|
154
|
+
argTypes: {
|
|
155
|
+
schema: {},
|
|
156
|
+
},
|
|
157
|
+
};
|
|
@@ -11,8 +11,15 @@ import { injectIntl } from 'react-intl';
|
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* PasswordWidget component class.
|
|
14
|
-
*
|
|
15
|
-
*
|
|
14
|
+
*
|
|
15
|
+
* To use it, in schema properties, declare a field like:
|
|
16
|
+
*
|
|
17
|
+
* ```jsx
|
|
18
|
+
* {
|
|
19
|
+
* title: "Password",
|
|
20
|
+
* type: 'password',
|
|
21
|
+
* }
|
|
22
|
+
* ```
|
|
16
23
|
*/
|
|
17
24
|
const PasswordWidget = (props) => {
|
|
18
25
|
const { id, value, onChange, onBlur, onClick, minLength, maxLength } = props;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PasswordWidget from './PasswordWidget';
|
|
3
|
+
import Wrapper from '@plone/volto/storybook';
|
|
4
|
+
|
|
5
|
+
const PasswordWidgetComponent = ({ 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
|
+
<PasswordWidget
|
|
12
|
+
{...args}
|
|
13
|
+
id="field"
|
|
14
|
+
title="Password"
|
|
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 Password = PasswordWidgetComponent.bind({});
|
|
26
|
+
|
|
27
|
+
export default {
|
|
28
|
+
title: 'Widgets/Password',
|
|
29
|
+
component: PasswordWidget,
|
|
30
|
+
decorators: [
|
|
31
|
+
(Story) => (
|
|
32
|
+
<div className="ui segment form attached" style={{ width: '400px' }}>
|
|
33
|
+
<Story />
|
|
34
|
+
</div>
|
|
35
|
+
),
|
|
36
|
+
],
|
|
37
|
+
argTypes: {},
|
|
38
|
+
};
|
|
@@ -41,9 +41,7 @@ const messages = defineMessages({
|
|
|
41
41
|
});
|
|
42
42
|
|
|
43
43
|
/**
|
|
44
|
-
*
|
|
45
|
-
* @class QuerystringWidget
|
|
46
|
-
* @extends Component
|
|
44
|
+
* Widget for a querystring value, to define a catalog search criteria.
|
|
47
45
|
*/
|
|
48
46
|
class QuerystringWidget extends Component {
|
|
49
47
|
/**
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import QueryWidget from './QueryWidget';
|
|
3
|
+
import Wrapper from '@plone/volto/storybook';
|
|
4
|
+
|
|
5
|
+
const QueryWidgetComponent = ({ 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
|
+
<QueryWidget
|
|
12
|
+
{...args}
|
|
13
|
+
id="field"
|
|
14
|
+
title="Query"
|
|
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 Query = QueryWidgetComponent.bind({});
|
|
26
|
+
|
|
27
|
+
export default {
|
|
28
|
+
title: 'Widgets/Query',
|
|
29
|
+
component: QueryWidget,
|
|
30
|
+
decorators: [
|
|
31
|
+
(Story) => (
|
|
32
|
+
<div className="ui segment form attached" style={{ width: '400px' }}>
|
|
33
|
+
<Story />
|
|
34
|
+
</div>
|
|
35
|
+
),
|
|
36
|
+
],
|
|
37
|
+
argTypes: {},
|
|
38
|
+
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { SelectWidgetComponent } from './SelectWidget';
|
|
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 SelectComponent = injectLazyLibs([
|
|
7
7
|
'reactSelect',
|
|
@@ -11,9 +11,10 @@ import { injectIntl } from 'react-intl';
|
|
|
11
11
|
import { Icon, FormFieldWrapper } from '@plone/volto/components';
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
14
|
+
* The simple text widget.
|
|
15
|
+
*
|
|
16
|
+
* It is the default fallback widget, so if no other widget is found based on
|
|
17
|
+
* passed field properties, it will be used.
|
|
17
18
|
*/
|
|
18
19
|
class TextWidget extends Component {
|
|
19
20
|
/**
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import TextWidget from './TextWidget';
|
|
3
|
+
import Wrapper from '@plone/volto/storybook';
|
|
4
|
+
|
|
5
|
+
const TextWidgetComponent = ({ 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
|
+
<TextWidget
|
|
12
|
+
{...args}
|
|
13
|
+
id="field"
|
|
14
|
+
title="Text"
|
|
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 Text = TextWidgetComponent.bind({});
|
|
26
|
+
|
|
27
|
+
export default {
|
|
28
|
+
title: 'Widgets/Text',
|
|
29
|
+
component: TextWidget,
|
|
30
|
+
decorators: [
|
|
31
|
+
(Story) => (
|
|
32
|
+
<div className="ui segment form attached" style={{ width: '400px' }}>
|
|
33
|
+
<Story />
|
|
34
|
+
</div>
|
|
35
|
+
),
|
|
36
|
+
],
|
|
37
|
+
argTypes: {},
|
|
38
|
+
};
|