@plone/volto 14.0.1 → 14.2.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.
- package/CHANGELOG.md +41 -0
- package/locales/ca/LC_MESSAGES/volto.po +12 -2
- package/locales/ca.json +1 -1
- package/locales/de/LC_MESSAGES/volto.po +12 -2
- package/locales/de.json +1 -1
- package/locales/en/LC_MESSAGES/volto.po +12 -2
- package/locales/en.json +1 -1
- package/locales/es/LC_MESSAGES/volto.po +12 -2
- package/locales/es.json +1 -1
- package/locales/eu/LC_MESSAGES/volto.po +12 -2
- package/locales/eu.json +1 -1
- package/locales/fr/LC_MESSAGES/volto.po +12 -2
- package/locales/fr.json +1 -1
- package/locales/it/LC_MESSAGES/volto.po +12 -2
- package/locales/it.json +1 -1
- package/locales/ja/LC_MESSAGES/volto.po +12 -2
- package/locales/ja.json +1 -1
- package/locales/nl/LC_MESSAGES/volto.po +12 -2
- package/locales/nl.json +1 -1
- package/locales/pt/LC_MESSAGES/volto.po +12 -2
- package/locales/pt.json +1 -1
- package/locales/pt_BR/LC_MESSAGES/volto.po +12 -2
- package/locales/pt_BR.json +1 -1
- package/locales/ro/LC_MESSAGES/volto.po +12 -2
- package/locales/ro.json +1 -1
- package/locales/volto.pot +12 -2
- package/package.json +2 -1
- package/public/icon.svg +13 -0
- package/src/actions/vocabularies/vocabularies.js +15 -3
- package/src/components/index.js +1 -0
- package/src/components/manage/Add/Add.jsx +1 -0
- package/src/components/manage/Blocks/HeroImageLeft/Edit.jsx +1 -1
- package/src/components/manage/Blocks/Listing/getAsyncData.js +1 -1
- package/src/components/manage/Blocks/Text/Edit.jsx +19 -0
- package/src/components/manage/Edit/Edit.jsx +1 -0
- package/src/components/manage/Form/Form.jsx +32 -6
- package/src/components/manage/Form/UndoToolbar.jsx +78 -0
- package/src/components/manage/Multilingual/TranslationObject.jsx +1 -0
- package/src/components/manage/Widgets/AlignWidget.stories.jsx +5 -21
- package/src/components/manage/Widgets/ArrayWidget.jsx +88 -88
- package/src/components/manage/Widgets/ArrayWidget.stories.jsx +37 -64
- package/src/components/manage/Widgets/CheckboxWidget.stories.jsx +5 -22
- package/src/components/manage/Widgets/DatetimeWidget.jsx +65 -74
- package/src/components/manage/Widgets/DatetimeWidget.stories.jsx +7 -23
- package/src/components/manage/Widgets/DatetimeWidget.test.jsx +17 -15
- package/src/components/manage/Widgets/EmailWidget.stories.jsx +5 -22
- package/src/components/manage/Widgets/FileWidget.stories.jsx +5 -22
- package/src/components/manage/Widgets/NumberWidget.stories.jsx +5 -23
- package/src/components/manage/Widgets/ObjectBrowserWidget.stories.js +24 -32
- package/src/components/manage/Widgets/ObjectListWidget.stories.js +44 -44
- package/src/components/manage/Widgets/ObjectWidget.stories.jsx +13 -28
- package/src/components/manage/Widgets/PasswordWidget.stories.jsx +5 -22
- package/src/components/manage/Widgets/QueryWidget.jsx +2 -2
- package/src/components/manage/Widgets/QueryWidget.stories.jsx +1637 -22
- package/src/components/manage/Widgets/SelectAutoComplete.jsx +79 -48
- package/src/components/manage/Widgets/SelectAutoComplete.test.jsx +16 -0
- package/src/components/manage/Widgets/SelectAutocompleteWidget.stories.jsx +161 -0
- package/src/components/manage/Widgets/SelectUtils.js +90 -30
- package/src/components/manage/Widgets/SelectUtils.test.jsx +76 -1
- package/src/components/manage/Widgets/SelectWidget.jsx +26 -37
- package/src/components/manage/Widgets/SelectWidget.stories.jsx +96 -28
- package/src/components/manage/Widgets/TextWidget.stories.jsx +5 -22
- package/src/components/manage/Widgets/TextareaWidget.stories.jsx +5 -22
- package/src/components/manage/Widgets/TokenWidget.jsx +19 -17
- package/src/components/manage/Widgets/TokenWidget.stories.jsx +141 -0
- package/src/components/manage/Widgets/UrlWidget.stories.jsx +5 -21
- package/src/components/manage/Widgets/VocabularyTermsWidget.stories.js +27 -64
- package/src/components/manage/Widgets/WysiwygWidget.stories.jsx +5 -22
- package/src/components/manage/Widgets/story.jsx +38 -0
- package/src/components/theme/ContactForm/ContactForm.jsx +1 -0
- package/src/components/theme/ContactForm/ContactForm.stories.jsx +126 -0
- package/src/components/theme/CorsError/CorsError.jsx +2 -2
- package/src/config/Blocks.jsx +8 -1
- package/src/config/Loadables.jsx +2 -0
- package/src/config/index.js +3 -0
- package/src/helpers/Html/Html.jsx +2 -12
- package/src/helpers/UndoManager/useUndoManager.js +102 -0
- package/src/helpers/index.js +1 -0
- package/src/reducers/vocabularies/vocabularies.js +13 -2
- package/src/store.js +1 -1
- package/src/storybook.jsx +55 -0
- package/theme/themes/pastanaga/extras/time-picker-overrides.less +1 -1
- package/include/python3.8/Python-ast.h +0 -715
- package/include/python3.8/Python.h +0 -160
- package/include/python3.8/abstract.h +0 -844
- package/include/python3.8/asdl.h +0 -46
- package/include/python3.8/ast.h +0 -37
- package/include/python3.8/bitset.h +0 -23
- package/include/python3.8/bltinmodule.h +0 -14
- package/include/python3.8/boolobject.h +0 -34
- package/include/python3.8/bytearrayobject.h +0 -62
- package/include/python3.8/bytes_methods.h +0 -69
- package/include/python3.8/bytesobject.h +0 -224
- package/include/python3.8/cellobject.h +0 -29
- package/include/python3.8/ceval.h +0 -231
- package/include/python3.8/classobject.h +0 -59
- package/include/python3.8/code.h +0 -180
- package/include/python3.8/codecs.h +0 -240
- package/include/python3.8/compile.h +0 -106
- package/include/python3.8/complexobject.h +0 -69
- package/include/python3.8/context.h +0 -84
- package/include/python3.8/cpython/abstract.h +0 -319
- package/include/python3.8/cpython/dictobject.h +0 -94
- package/include/python3.8/cpython/fileobject.h +0 -24
- package/include/python3.8/cpython/initconfig.h +0 -434
- package/include/python3.8/cpython/interpreteridobject.h +0 -19
- package/include/python3.8/cpython/object.h +0 -470
- package/include/python3.8/cpython/objimpl.h +0 -113
- package/include/python3.8/cpython/pyerrors.h +0 -188
- package/include/python3.8/cpython/pylifecycle.h +0 -78
- package/include/python3.8/cpython/pymem.h +0 -108
- package/include/python3.8/cpython/pystate.h +0 -252
- package/include/python3.8/cpython/sysmodule.h +0 -21
- package/include/python3.8/cpython/traceback.h +0 -22
- package/include/python3.8/cpython/tupleobject.h +0 -36
- package/include/python3.8/cpython/unicodeobject.h +0 -1239
- package/include/python3.8/datetime.h +0 -259
- package/include/python3.8/descrobject.h +0 -108
- package/include/python3.8/dictobject.h +0 -94
- package/include/python3.8/dtoa.h +0 -19
- package/include/python3.8/dynamic_annotations.h +0 -499
- package/include/python3.8/enumobject.h +0 -17
- package/include/python3.8/errcode.h +0 -38
- package/include/python3.8/eval.h +0 -37
- package/include/python3.8/fileobject.h +0 -49
- package/include/python3.8/fileutils.h +0 -185
- package/include/python3.8/floatobject.h +0 -130
- package/include/python3.8/frameobject.h +0 -92
- package/include/python3.8/funcobject.h +0 -104
- package/include/python3.8/genobject.h +0 -109
- package/include/python3.8/graminit.h +0 -94
- package/include/python3.8/grammar.h +0 -77
- package/include/python3.8/import.h +0 -149
- package/include/python3.8/internal/pycore_accu.h +0 -39
- package/include/python3.8/internal/pycore_atomic.h +0 -558
- package/include/python3.8/internal/pycore_ceval.h +0 -37
- package/include/python3.8/internal/pycore_code.h +0 -27
- package/include/python3.8/internal/pycore_condvar.h +0 -95
- package/include/python3.8/internal/pycore_context.h +0 -42
- package/include/python3.8/internal/pycore_fileutils.h +0 -54
- package/include/python3.8/internal/pycore_getopt.h +0 -22
- package/include/python3.8/internal/pycore_gil.h +0 -50
- package/include/python3.8/internal/pycore_hamt.h +0 -116
- package/include/python3.8/internal/pycore_initconfig.h +0 -166
- package/include/python3.8/internal/pycore_object.h +0 -81
- package/include/python3.8/internal/pycore_pathconfig.h +0 -75
- package/include/python3.8/internal/pycore_pyerrors.h +0 -62
- package/include/python3.8/internal/pycore_pyhash.h +0 -10
- package/include/python3.8/internal/pycore_pylifecycle.h +0 -118
- package/include/python3.8/internal/pycore_pymem.h +0 -212
- package/include/python3.8/internal/pycore_pystate.h +0 -326
- package/include/python3.8/internal/pycore_traceback.h +0 -96
- package/include/python3.8/internal/pycore_tupleobject.h +0 -19
- package/include/python3.8/internal/pycore_warnings.h +0 -25
- package/include/python3.8/interpreteridobject.h +0 -17
- package/include/python3.8/intrcheck.h +0 -33
- package/include/python3.8/iterobject.h +0 -25
- package/include/python3.8/listobject.h +0 -81
- package/include/python3.8/longintrepr.h +0 -99
- package/include/python3.8/longobject.h +0 -242
- package/include/python3.8/marshal.h +0 -28
- package/include/python3.8/memoryobject.h +0 -72
- package/include/python3.8/methodobject.h +0 -131
- package/include/python3.8/modsupport.h +0 -248
- package/include/python3.8/moduleobject.h +0 -90
- package/include/python3.8/namespaceobject.h +0 -19
- package/include/python3.8/node.h +0 -48
- package/include/python3.8/object.h +0 -753
- package/include/python3.8/objimpl.h +0 -284
- package/include/python3.8/odictobject.h +0 -43
- package/include/python3.8/opcode.h +0 -148
- package/include/python3.8/osdefs.h +0 -51
- package/include/python3.8/osmodule.h +0 -17
- package/include/python3.8/parsetok.h +0 -110
- package/include/python3.8/patchlevel.h +0 -35
- package/include/python3.8/picklebufobject.h +0 -31
- package/include/python3.8/py_curses.h +0 -100
- package/include/python3.8/pyarena.h +0 -64
- package/include/python3.8/pycapsule.h +0 -59
- package/include/python3.8/pyconfig.h +0 -1665
- package/include/python3.8/pyctype.h +0 -39
- package/include/python3.8/pydebug.h +0 -40
- package/include/python3.8/pydtrace.h +0 -59
- package/include/python3.8/pydtrace_probes.h +0 -228
- package/include/python3.8/pyerrors.h +0 -335
- package/include/python3.8/pyexpat.h +0 -55
- package/include/python3.8/pyfpe.h +0 -12
- package/include/python3.8/pyhash.h +0 -145
- package/include/python3.8/pylifecycle.h +0 -75
- package/include/python3.8/pymacconfig.h +0 -102
- package/include/python3.8/pymacro.h +0 -106
- package/include/python3.8/pymath.h +0 -230
- package/include/python3.8/pymem.h +0 -150
- package/include/python3.8/pyport.h +0 -850
- package/include/python3.8/pystate.h +0 -136
- package/include/python3.8/pystrcmp.h +0 -23
- package/include/python3.8/pystrhex.h +0 -22
- package/include/python3.8/pystrtod.h +0 -45
- package/include/python3.8/pythonrun.h +0 -210
- package/include/python3.8/pythread.h +0 -161
- package/include/python3.8/pytime.h +0 -246
- package/include/python3.8/rangeobject.h +0 -27
- package/include/python3.8/setobject.h +0 -108
- package/include/python3.8/sliceobject.h +0 -65
- package/include/python3.8/structmember.h +0 -74
- package/include/python3.8/structseq.h +0 -49
- package/include/python3.8/symtable.h +0 -123
- package/include/python3.8/sysmodule.h +0 -41
- package/include/python3.8/token.h +0 -92
- package/include/python3.8/traceback.h +0 -28
- package/include/python3.8/tracemalloc.h +0 -38
- package/include/python3.8/tupleobject.h +0 -48
- package/include/python3.8/typeslots.h +0 -85
- package/include/python3.8/ucnhash.h +0 -36
- package/include/python3.8/unicodeobject.h +0 -1044
- package/include/python3.8/warnings.h +0 -67
- package/include/python3.8/weakrefobject.h +0 -86
- package/src/components/theme/ContactForm/ContactForm.stories.mdx +0 -39
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
} from '@plone/volto/helpers';
|
|
17
17
|
import { FormFieldWrapper } from '@plone/volto/components';
|
|
18
18
|
import { getVocabulary, getVocabularyTokenTitle } from '@plone/volto/actions';
|
|
19
|
-
import { normalizeValue } from '
|
|
19
|
+
import { normalizeValue } from '@plone/volto/components/manage/Widgets/SelectUtils';
|
|
20
20
|
|
|
21
21
|
import {
|
|
22
22
|
customSelectStyles,
|
|
@@ -107,6 +107,8 @@ class SelectWidget extends Component {
|
|
|
107
107
|
PropTypes.object,
|
|
108
108
|
PropTypes.string,
|
|
109
109
|
PropTypes.bool,
|
|
110
|
+
PropTypes.func,
|
|
111
|
+
PropTypes.array,
|
|
110
112
|
]),
|
|
111
113
|
onChange: PropTypes.func.isRequired,
|
|
112
114
|
onBlur: PropTypes.func,
|
|
@@ -115,6 +117,8 @@ class SelectWidget extends Component {
|
|
|
115
117
|
onDelete: PropTypes.func,
|
|
116
118
|
wrapped: PropTypes.bool,
|
|
117
119
|
noValueOption: PropTypes.bool,
|
|
120
|
+
customOptionStyling: PropTypes.any,
|
|
121
|
+
isMulti: PropTypes.bool,
|
|
118
122
|
};
|
|
119
123
|
|
|
120
124
|
/**
|
|
@@ -140,11 +144,7 @@ class SelectWidget extends Component {
|
|
|
140
144
|
onEdit: null,
|
|
141
145
|
onDelete: null,
|
|
142
146
|
noValueOption: true,
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
state = {
|
|
146
|
-
// TODO: also take into account this.props.defaultValue?
|
|
147
|
-
selectedOption: normalizeValue(this.props.choices, this.props.value),
|
|
147
|
+
customOptionStyling: null,
|
|
148
148
|
};
|
|
149
149
|
|
|
150
150
|
/**
|
|
@@ -165,32 +165,14 @@ class SelectWidget extends Component {
|
|
|
165
165
|
}
|
|
166
166
|
}
|
|
167
167
|
|
|
168
|
-
componentDidUpdate() {
|
|
169
|
-
if (
|
|
170
|
-
!this.state.selectedOption &&
|
|
171
|
-
this.props.value &&
|
|
172
|
-
this.props.choices?.length > 0
|
|
173
|
-
) {
|
|
174
|
-
const normalizedValue = normalizeValue(
|
|
175
|
-
this.props.choices,
|
|
176
|
-
this.props.value,
|
|
177
|
-
);
|
|
178
|
-
|
|
179
|
-
if (normalizedValue != null) {
|
|
180
|
-
this.setState({
|
|
181
|
-
selectedOption: normalizedValue,
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
|
|
187
168
|
/**
|
|
188
169
|
* Render method.
|
|
189
170
|
* @method render
|
|
190
171
|
* @returns {string} Markup for the component.
|
|
191
172
|
*/
|
|
192
173
|
render() {
|
|
193
|
-
const { id, choices, onChange } = this.props;
|
|
174
|
+
const { id, choices, value, intl, onChange } = this.props;
|
|
175
|
+
const normalizedValue = normalizeValue(choices, value, intl);
|
|
194
176
|
// Make sure that both disabled and isDisabled (from the DX layout feat work)
|
|
195
177
|
const disabled = this.props.disabled || this.props.isDisabled;
|
|
196
178
|
const Select = this.props.reactSelect.default;
|
|
@@ -216,6 +198,10 @@ class SelectWidget extends Component {
|
|
|
216
198
|
: []),
|
|
217
199
|
];
|
|
218
200
|
|
|
201
|
+
const isMulti = this.props.isMulti
|
|
202
|
+
? this.props.isMulti
|
|
203
|
+
: id === 'roles' || id === 'groups';
|
|
204
|
+
|
|
219
205
|
return (
|
|
220
206
|
<FormFieldWrapper {...this.props}>
|
|
221
207
|
<Select
|
|
@@ -226,11 +212,7 @@ class SelectWidget extends Component {
|
|
|
226
212
|
isSearchable={true}
|
|
227
213
|
className="react-select-container"
|
|
228
214
|
classNamePrefix="react-select"
|
|
229
|
-
isMulti={
|
|
230
|
-
this.props.isMulti
|
|
231
|
-
? this.props.isMulti
|
|
232
|
-
: id === 'roles' || id === 'groups'
|
|
233
|
-
}
|
|
215
|
+
isMulti={isMulti}
|
|
234
216
|
options={options}
|
|
235
217
|
styles={customSelectStyles}
|
|
236
218
|
theme={selectTheme}
|
|
@@ -240,12 +222,20 @@ class SelectWidget extends Component {
|
|
|
240
222
|
}),
|
|
241
223
|
DropdownIndicator,
|
|
242
224
|
ClearIndicator,
|
|
243
|
-
Option,
|
|
225
|
+
Option: this.props.customOptionStyling || Option,
|
|
244
226
|
}}
|
|
245
|
-
value={
|
|
246
|
-
placeholder={
|
|
227
|
+
value={normalizedValue}
|
|
228
|
+
placeholder={
|
|
229
|
+
this.props.placeholder ??
|
|
230
|
+
this.props.intl.formatMessage(messages.select)
|
|
231
|
+
}
|
|
247
232
|
onChange={(selectedOption) => {
|
|
248
|
-
|
|
233
|
+
if (isMulti) {
|
|
234
|
+
return onChange(
|
|
235
|
+
id,
|
|
236
|
+
selectedOption.map((el) => el.value),
|
|
237
|
+
);
|
|
238
|
+
}
|
|
249
239
|
return onChange(
|
|
250
240
|
id,
|
|
251
241
|
selectedOption && selectedOption.value !== 'no-value'
|
|
@@ -263,7 +253,6 @@ class SelectWidget extends Component {
|
|
|
263
253
|
export const SelectWidgetComponent = injectIntl(SelectWidget);
|
|
264
254
|
|
|
265
255
|
export default compose(
|
|
266
|
-
injectIntl,
|
|
267
256
|
injectLazyLibs(['reactSelect']),
|
|
268
257
|
connect(
|
|
269
258
|
(state, props) => {
|
|
@@ -298,4 +287,4 @@ export default compose(
|
|
|
298
287
|
},
|
|
299
288
|
{ getVocabulary, getVocabularyTokenTitle },
|
|
300
289
|
),
|
|
301
|
-
)(
|
|
290
|
+
)(SelectWidgetComponent);
|
|
@@ -1,30 +1,24 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { SelectWidgetComponent } from './SelectWidget';
|
|
3
|
-
import
|
|
4
|
-
import { RealStoreWrapper as Wrapper } from '@plone/volto/storybook';
|
|
2
|
+
import SelectWidget, { SelectWidgetComponent } from './SelectWidget';
|
|
3
|
+
import WidgetStory from './story';
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
|
|
6
|
+
import checkSVG from '@plone/volto/icons/check.svg';
|
|
7
|
+
import { Icon } from '@plone/volto/components';
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
// args.onChange({ value });
|
|
12
|
-
setValue(value);
|
|
13
|
-
};
|
|
9
|
+
import bellRingingSVG from '@plone/volto/icons/bell-ringing.svg';
|
|
10
|
+
import blogSVG from '@plone/volto/icons/blog.svg';
|
|
11
|
+
import bookSVG from '@plone/volto/icons/book.svg';
|
|
14
12
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
</Wrapper>
|
|
19
|
-
);
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
export const Default = Select.bind({});
|
|
13
|
+
export const Default = WidgetStory.bind({
|
|
14
|
+
widget: SelectWidget,
|
|
15
|
+
});
|
|
23
16
|
Default.args = {
|
|
24
17
|
id: 'field-empty',
|
|
25
18
|
title: 'field 1 title',
|
|
26
19
|
description: 'Optional help text',
|
|
27
20
|
placeholder: 'Type something…',
|
|
21
|
+
isMulti: false,
|
|
28
22
|
choices: [
|
|
29
23
|
['Foo', 'Foo'],
|
|
30
24
|
['Bar', 'Bar'],
|
|
@@ -32,7 +26,9 @@ Default.args = {
|
|
|
32
26
|
],
|
|
33
27
|
};
|
|
34
28
|
|
|
35
|
-
export const Required =
|
|
29
|
+
export const Required = WidgetStory.bind({
|
|
30
|
+
widget: SelectWidget,
|
|
31
|
+
});
|
|
36
32
|
Required.args = {
|
|
37
33
|
id: 'field-empty',
|
|
38
34
|
title: 'field 1 title',
|
|
@@ -46,7 +42,9 @@ Required.args = {
|
|
|
46
42
|
required: true,
|
|
47
43
|
};
|
|
48
44
|
|
|
49
|
-
export const Filled =
|
|
45
|
+
export const Filled = WidgetStory.bind({
|
|
46
|
+
widget: SelectWidget,
|
|
47
|
+
});
|
|
50
48
|
Filled.args = {
|
|
51
49
|
id: 'field-filled',
|
|
52
50
|
title: 'Filled field title',
|
|
@@ -61,7 +59,9 @@ Filled.args = {
|
|
|
61
59
|
required: true,
|
|
62
60
|
};
|
|
63
61
|
|
|
64
|
-
export const Errored =
|
|
62
|
+
export const Errored = WidgetStory.bind({
|
|
63
|
+
widget: SelectWidget,
|
|
64
|
+
});
|
|
65
65
|
Errored.args = {
|
|
66
66
|
id: 'field-errored',
|
|
67
67
|
title: 'Errored field title',
|
|
@@ -88,7 +88,9 @@ Errored.args = {
|
|
|
88
88
|
required: true,
|
|
89
89
|
};
|
|
90
90
|
|
|
91
|
-
export const NoPlaceholder =
|
|
91
|
+
export const NoPlaceholder = WidgetStory.bind({
|
|
92
|
+
widget: SelectWidget,
|
|
93
|
+
});
|
|
92
94
|
NoPlaceholder.args = {
|
|
93
95
|
id: 'field-without-novalue',
|
|
94
96
|
title: 'Field title',
|
|
@@ -101,7 +103,9 @@ NoPlaceholder.args = {
|
|
|
101
103
|
required: true,
|
|
102
104
|
};
|
|
103
105
|
|
|
104
|
-
export const WithoutNoValueOption =
|
|
106
|
+
export const WithoutNoValueOption = WidgetStory.bind({
|
|
107
|
+
widget: SelectWidget,
|
|
108
|
+
});
|
|
105
109
|
WithoutNoValueOption.args = {
|
|
106
110
|
id: 'field-without-novalue',
|
|
107
111
|
title: 'Field title',
|
|
@@ -116,7 +120,9 @@ WithoutNoValueOption.args = {
|
|
|
116
120
|
noValueOption: false,
|
|
117
121
|
};
|
|
118
122
|
|
|
119
|
-
export const VocabularyBased =
|
|
123
|
+
export const VocabularyBased = WidgetStory.bind({
|
|
124
|
+
widget: SelectWidget,
|
|
125
|
+
});
|
|
120
126
|
VocabularyBased.args = {
|
|
121
127
|
id: 'field-vocab-based',
|
|
122
128
|
title: 'field title',
|
|
@@ -143,7 +149,9 @@ VocabularyBased.args = {
|
|
|
143
149
|
vocabBaseUrl: 'https://anapivocabularyURL',
|
|
144
150
|
};
|
|
145
151
|
|
|
146
|
-
export const Disabled =
|
|
152
|
+
export const Disabled = WidgetStory.bind({
|
|
153
|
+
widget: SelectWidget,
|
|
154
|
+
});
|
|
147
155
|
Disabled.args = {
|
|
148
156
|
id: 'field-disabled',
|
|
149
157
|
title: 'Disabled field title',
|
|
@@ -159,7 +167,9 @@ const getOptionsGenerator = (count) => {
|
|
|
159
167
|
return options;
|
|
160
168
|
};
|
|
161
169
|
|
|
162
|
-
export const ManyOptions1000 =
|
|
170
|
+
export const ManyOptions1000 = WidgetStory.bind({
|
|
171
|
+
widget: SelectWidget,
|
|
172
|
+
});
|
|
163
173
|
ManyOptions1000.args = {
|
|
164
174
|
id: 'field-empty',
|
|
165
175
|
title: 'field 1 title',
|
|
@@ -168,7 +178,9 @@ ManyOptions1000.args = {
|
|
|
168
178
|
choices: getOptionsGenerator(1000),
|
|
169
179
|
};
|
|
170
180
|
|
|
171
|
-
export const ManyOptions500 =
|
|
181
|
+
export const ManyOptions500 = WidgetStory.bind({
|
|
182
|
+
widget: SelectWidget,
|
|
183
|
+
});
|
|
172
184
|
ManyOptions500.args = {
|
|
173
185
|
id: 'field-empty',
|
|
174
186
|
title: 'field 1 title',
|
|
@@ -177,9 +189,65 @@ ManyOptions500.args = {
|
|
|
177
189
|
choices: getOptionsGenerator(500),
|
|
178
190
|
};
|
|
179
191
|
|
|
192
|
+
export const MultiSelection = WidgetStory.bind({
|
|
193
|
+
widget: SelectWidget,
|
|
194
|
+
});
|
|
195
|
+
MultiSelection.args = {
|
|
196
|
+
id: 'field-empty',
|
|
197
|
+
title: 'field 1 title',
|
|
198
|
+
description: 'Select multiple values',
|
|
199
|
+
placeholder: 'Type something…',
|
|
200
|
+
isMulti: true,
|
|
201
|
+
choices: [
|
|
202
|
+
['Foo', 'Foo'],
|
|
203
|
+
['Bar', 'Bar'],
|
|
204
|
+
['FooBar', 'FooBar'],
|
|
205
|
+
],
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
const Option = injectLazyLibs('reactSelect')((props) => {
|
|
209
|
+
const { Option } = props.reactSelect.components;
|
|
210
|
+
const icons = {
|
|
211
|
+
FooBar: bellRingingSVG,
|
|
212
|
+
Bar: blogSVG,
|
|
213
|
+
Foo: bookSVG,
|
|
214
|
+
};
|
|
215
|
+
return (
|
|
216
|
+
<Option {...props}>
|
|
217
|
+
<div>
|
|
218
|
+
{icons[props.value] && <Icon name={icons[props.value]} size="24px" />}
|
|
219
|
+
{props.label}
|
|
220
|
+
</div>
|
|
221
|
+
{props.isFocused && !props.isSelected && (
|
|
222
|
+
<Icon name={checkSVG} size="24px" color="#b8c6c8" />
|
|
223
|
+
)}
|
|
224
|
+
{props.isSelected && <Icon name={checkSVG} size="24px" color="#007bc1" />}
|
|
225
|
+
</Option>
|
|
226
|
+
);
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
export const CustomOptions = WidgetStory.bind({
|
|
230
|
+
widget: SelectWidget,
|
|
231
|
+
props: {
|
|
232
|
+
customOptionStyling: Option,
|
|
233
|
+
},
|
|
234
|
+
});
|
|
235
|
+
CustomOptions.args = {
|
|
236
|
+
id: 'field-empty',
|
|
237
|
+
title: 'field 1 title',
|
|
238
|
+
description: 'Select a value',
|
|
239
|
+
placeholder: 'Type something…',
|
|
240
|
+
isMulti: false,
|
|
241
|
+
choices: [
|
|
242
|
+
['Foo', 'Foo'],
|
|
243
|
+
['Bar', 'Bar'],
|
|
244
|
+
['FooBar', 'FooBar'],
|
|
245
|
+
],
|
|
246
|
+
};
|
|
247
|
+
|
|
180
248
|
export default {
|
|
181
249
|
title: 'Widgets/Select Widget',
|
|
182
|
-
component:
|
|
250
|
+
component: SelectWidgetComponent,
|
|
183
251
|
decorators: [
|
|
184
252
|
(Story) => (
|
|
185
253
|
<div style={{ width: '400px' }}>
|
|
@@ -1,28 +1,11 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import TextWidget from './TextWidget';
|
|
3
|
-
import
|
|
3
|
+
import WidgetStory from './story';
|
|
4
4
|
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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({});
|
|
5
|
+
export const Text = WidgetStory.bind({
|
|
6
|
+
props: { id: 'text', title: 'Text' },
|
|
7
|
+
widget: TextWidget,
|
|
8
|
+
});
|
|
26
9
|
|
|
27
10
|
export default {
|
|
28
11
|
title: 'Widgets/Text',
|
|
@@ -1,28 +1,11 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import TextareaWidget from './TextareaWidget';
|
|
3
|
-
import
|
|
3
|
+
import WidgetStory from './story';
|
|
4
4
|
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
<Wrapper location={{ pathname: '/folder2/folder21/doc212' }}>
|
|
10
|
-
<div className="ui segment form attached" style={{ width: '400px' }}>
|
|
11
|
-
<TextareaWidget
|
|
12
|
-
{...args}
|
|
13
|
-
id="field"
|
|
14
|
-
title="Textarea"
|
|
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 Textarea = TextareaWidgetComponent.bind({});
|
|
5
|
+
export const Textarea = WidgetStory.bind({
|
|
6
|
+
props: { id: 'textarea', title: 'Text area', block: 'block' },
|
|
7
|
+
widget: TextareaWidget,
|
|
8
|
+
});
|
|
26
9
|
|
|
27
10
|
export default {
|
|
28
11
|
title: 'Widgets/Textarea',
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* @module components/manage/Widgets/
|
|
2
|
+
* TokenWidget component.
|
|
3
|
+
* @module components/manage/Widgets/TokenWidget
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import React, { Component } from 'react';
|
|
@@ -39,6 +39,11 @@ const messages = defineMessages({
|
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
41
|
* TokenWidget component class.
|
|
42
|
+
*
|
|
43
|
+
* Because new terms are created through the web by using the widget, the token
|
|
44
|
+
* widget conflates the meaning of token, label and value and assumes they can
|
|
45
|
+
* be used interchangeably.
|
|
46
|
+
*
|
|
42
47
|
* @class TokenWidget
|
|
43
48
|
* @extends Component
|
|
44
49
|
*/
|
|
@@ -95,12 +100,6 @@ class TokenWidget extends Component {
|
|
|
95
100
|
constructor(props) {
|
|
96
101
|
super(props);
|
|
97
102
|
this.handleChange = this.handleChange.bind(this);
|
|
98
|
-
|
|
99
|
-
this.state = {
|
|
100
|
-
selectedOption: props.value
|
|
101
|
-
? props.value.map((item) => ({ label: item, value: item }))
|
|
102
|
-
: [],
|
|
103
|
-
};
|
|
104
103
|
}
|
|
105
104
|
|
|
106
105
|
/**
|
|
@@ -109,11 +108,13 @@ class TokenWidget extends Component {
|
|
|
109
108
|
* @returns {undefined}
|
|
110
109
|
*/
|
|
111
110
|
componentDidMount() {
|
|
112
|
-
this.props.
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
111
|
+
if (!this.props.choices?.length) {
|
|
112
|
+
this.props.getVocabulary({
|
|
113
|
+
vocabNameOrURL: this.props.vocabBaseUrl,
|
|
114
|
+
size: -1,
|
|
115
|
+
subrequest: this.props.intl.locale,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
117
118
|
}
|
|
118
119
|
|
|
119
120
|
/**
|
|
@@ -124,7 +125,6 @@ class TokenWidget extends Component {
|
|
|
124
125
|
* @returns {undefined}
|
|
125
126
|
*/
|
|
126
127
|
handleChange(selectedOption) {
|
|
127
|
-
this.setState({ selectedOption });
|
|
128
128
|
this.props.onChange(
|
|
129
129
|
this.props.id,
|
|
130
130
|
selectedOption ? selectedOption.map((item) => item.label) : null,
|
|
@@ -137,11 +137,13 @@ class TokenWidget extends Component {
|
|
|
137
137
|
* @returns {string} Markup for the component.
|
|
138
138
|
*/
|
|
139
139
|
render() {
|
|
140
|
-
const
|
|
140
|
+
const selectedOption = this.props.value
|
|
141
|
+
? this.props.value.map((item) => ({ label: item, value: item }))
|
|
142
|
+
: [];
|
|
143
|
+
|
|
141
144
|
const defaultOptions = (this.props.choices || [])
|
|
142
145
|
.filter(
|
|
143
|
-
(item) =>
|
|
144
|
-
!this.state.selectedOption.find(({ label }) => label === item.label),
|
|
146
|
+
(item) => !selectedOption.find(({ label }) => label === item.label),
|
|
145
147
|
)
|
|
146
148
|
.map((item) => ({
|
|
147
149
|
label: item.label || item.value,
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import TokenWidget from './TokenWidget';
|
|
3
|
+
|
|
4
|
+
import WidgetStory from './story';
|
|
5
|
+
|
|
6
|
+
const vocabBaseUrl = 'https://anapivocabularyURL';
|
|
7
|
+
|
|
8
|
+
const defaults = {
|
|
9
|
+
widget: TokenWidget,
|
|
10
|
+
props: {
|
|
11
|
+
widgetOptions: {
|
|
12
|
+
vocabulary: {
|
|
13
|
+
'@id': vocabBaseUrl,
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
customStore: {
|
|
18
|
+
userSession: { token: '1234' },
|
|
19
|
+
intl: {
|
|
20
|
+
locale: 'en',
|
|
21
|
+
messages: {},
|
|
22
|
+
},
|
|
23
|
+
vocabularies: {
|
|
24
|
+
[vocabBaseUrl]: {
|
|
25
|
+
subrequests: {
|
|
26
|
+
en: {
|
|
27
|
+
items: [
|
|
28
|
+
{ value: 'foo', label: 'Foo' },
|
|
29
|
+
{ value: 'bar', label: 'Bar' },
|
|
30
|
+
{ value: 'fooBar', label: 'FooBar' },
|
|
31
|
+
],
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export const Default = WidgetStory.bind(defaults);
|
|
40
|
+
Default.args = {
|
|
41
|
+
id: 'field-empty',
|
|
42
|
+
title: 'field 1 title',
|
|
43
|
+
description: 'Optional help text',
|
|
44
|
+
placeholder: 'Type something…',
|
|
45
|
+
vocabBaseUrl,
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export const Required = WidgetStory.bind(defaults);
|
|
49
|
+
Required.args = {
|
|
50
|
+
id: 'field-empty',
|
|
51
|
+
title: 'field 1 title',
|
|
52
|
+
description: 'Optional help text',
|
|
53
|
+
placeholder: 'Type something…',
|
|
54
|
+
required: true,
|
|
55
|
+
vocabBaseUrl,
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export const Filled = WidgetStory.bind(defaults);
|
|
59
|
+
Filled.args = {
|
|
60
|
+
id: 'field-filled',
|
|
61
|
+
title: 'Filled field title',
|
|
62
|
+
description: 'Optional help text',
|
|
63
|
+
value: ['Foo'],
|
|
64
|
+
placeholder: 'Type something…',
|
|
65
|
+
required: true,
|
|
66
|
+
vocabBaseUrl,
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export const Errored = WidgetStory.bind(defaults);
|
|
70
|
+
Errored.args = {
|
|
71
|
+
id: 'field-errored',
|
|
72
|
+
title: 'Errored field title',
|
|
73
|
+
description: 'Optional help text',
|
|
74
|
+
placeholder: 'Type something…',
|
|
75
|
+
// Simplest example in Plone - a "hardcoded, hand made" vocab using SimpleVocabulary/SimpleTerm
|
|
76
|
+
// allow_discussion = schema.Choice(
|
|
77
|
+
// title=_(u'Allow discussion'),
|
|
78
|
+
// description=_(u'Allow discussion for this content object.'),
|
|
79
|
+
// vocabulary=SimpleVocabulary([
|
|
80
|
+
// SimpleTerm(value=True, title=_(u'Yes')),
|
|
81
|
+
// SimpleTerm(value=False, title=_(u'No')),
|
|
82
|
+
// ]),
|
|
83
|
+
// required=False,
|
|
84
|
+
// default=None,
|
|
85
|
+
// )
|
|
86
|
+
value: ['Foo'],
|
|
87
|
+
error: ['This is the error'],
|
|
88
|
+
required: true,
|
|
89
|
+
vocabBaseUrl,
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export const NoPlaceholder = WidgetStory.bind(defaults);
|
|
93
|
+
NoPlaceholder.args = {
|
|
94
|
+
id: 'field-without-novalue',
|
|
95
|
+
title: 'Field title',
|
|
96
|
+
description: 'This field has no value option',
|
|
97
|
+
required: true,
|
|
98
|
+
vocabBaseUrl,
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
export const WithoutNoValueOption = WidgetStory.bind(defaults);
|
|
102
|
+
WithoutNoValueOption.args = {
|
|
103
|
+
id: 'field-without-novalue',
|
|
104
|
+
title: 'Field title',
|
|
105
|
+
description: 'This field has no value option',
|
|
106
|
+
placeholder: 'something…',
|
|
107
|
+
required: true,
|
|
108
|
+
noValueOption: false,
|
|
109
|
+
vocabBaseUrl,
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
export const Disabled = WidgetStory.bind(defaults);
|
|
113
|
+
Disabled.args = {
|
|
114
|
+
id: 'field-disabled',
|
|
115
|
+
title: 'Disabled field title',
|
|
116
|
+
description: 'This select field is disabled',
|
|
117
|
+
disabled: true,
|
|
118
|
+
vocabBaseUrl,
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
export default {
|
|
122
|
+
title: 'Widgets/Token',
|
|
123
|
+
component: TokenWidget,
|
|
124
|
+
decorators: [
|
|
125
|
+
(Story) => (
|
|
126
|
+
<div style={{ width: '400px' }}>
|
|
127
|
+
<Story />
|
|
128
|
+
</div>
|
|
129
|
+
),
|
|
130
|
+
],
|
|
131
|
+
argTypes: {
|
|
132
|
+
// controlled value prop
|
|
133
|
+
value: {
|
|
134
|
+
control: {
|
|
135
|
+
disable: true,
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
// excludeStories: ['searchResults'],
|
|
140
|
+
// subcomponents: { ArgsTable },
|
|
141
|
+
};
|
|
@@ -1,28 +1,12 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import UrlWidgetDefault, { UrlWidget } from './UrlWidget';
|
|
3
|
-
import Wrapper from '@plone/volto/storybook';
|
|
4
3
|
|
|
5
|
-
|
|
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
|
-
<UrlWidgetDefault
|
|
12
|
-
{...args}
|
|
13
|
-
id="field"
|
|
14
|
-
title="Url"
|
|
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
|
-
};
|
|
4
|
+
import WidgetStory from './story';
|
|
24
5
|
|
|
25
|
-
export const Url =
|
|
6
|
+
export const Url = WidgetStory.bind({
|
|
7
|
+
props: { id: 'align', title: 'URL' },
|
|
8
|
+
widget: UrlWidgetDefault,
|
|
9
|
+
});
|
|
26
10
|
|
|
27
11
|
export default {
|
|
28
12
|
title: 'Widgets/Url',
|