@plone/volto 14.0.0 → 14.1.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/CHANGELOG.md +40 -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/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/Form/Form.jsx +11 -1
- package/src/components/manage/Form/UndoToolbar.jsx +78 -0
- package/src/components/manage/Widgets/AlignWidget.stories.jsx +5 -21
- package/src/components/manage/Widgets/ArrayWidget.jsx +83 -101
- package/src/components/manage/Widgets/ArrayWidget.stories.jsx +29 -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/Loadables.jsx +2 -0
- package/src/config/index.js +1 -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/middleware/Api.test.js +57 -6
- package/src/middleware/api.js +34 -13
- 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
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
import VocabularyTermsWidget from './VocabularyTermsWidget';
|
|
2
|
-
import Wrapper from '@plone/volto/storybook';
|
|
3
2
|
import React from 'react';
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
userSession: { token: '1234' },
|
|
7
|
-
intl: {
|
|
8
|
-
locale: 'en',
|
|
9
|
-
messages: {},
|
|
10
|
-
},
|
|
11
|
-
};
|
|
4
|
+
import WidgetStory from './story';
|
|
12
5
|
|
|
13
|
-
const
|
|
14
|
-
|
|
6
|
+
export const JSONField = WidgetStory.bind({
|
|
7
|
+
props: { id: 'simplevocabulary', title: 'Vocabulary terms' },
|
|
8
|
+
widget: VocabularyTermsWidget,
|
|
9
|
+
customStore: {
|
|
10
|
+
userSession: { token: '1234' },
|
|
11
|
+
intl: {
|
|
12
|
+
locale: 'en',
|
|
13
|
+
messages: {},
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
initialValue: {
|
|
15
17
|
items: [
|
|
16
18
|
{
|
|
17
19
|
token: 'talk',
|
|
@@ -30,60 +32,24 @@ const WrappedJSONField = (args) => {
|
|
|
30
32
|
},
|
|
31
33
|
},
|
|
32
34
|
],
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
return (
|
|
37
|
-
<Wrapper
|
|
38
|
-
location={{ pathname: '/folder2/folder21/doc212' }}
|
|
39
|
-
customStore={customStore}
|
|
40
|
-
>
|
|
41
|
-
<div className="ui segment form attached">
|
|
42
|
-
<VocabularyTermsWidget
|
|
43
|
-
{...args}
|
|
44
|
-
id="simplevocabulary"
|
|
45
|
-
title="Vocabulary terms"
|
|
46
|
-
block="testBlock"
|
|
47
|
-
value={value}
|
|
48
|
-
onChange={onChange}
|
|
49
|
-
/>
|
|
50
|
-
<pre>{JSON.stringify(value, null, 4)}</pre>
|
|
51
|
-
</div>
|
|
52
|
-
</Wrapper>
|
|
53
|
-
);
|
|
54
|
-
};
|
|
35
|
+
},
|
|
36
|
+
});
|
|
55
37
|
|
|
56
|
-
const
|
|
57
|
-
|
|
38
|
+
export const Simple = WidgetStory.bind({
|
|
39
|
+
props: { id: 'simplevocabulary', title: 'Vocabulary terms' },
|
|
40
|
+
widget: VocabularyTermsWidget,
|
|
41
|
+
customStore: {
|
|
42
|
+
userSession: { token: '1234' },
|
|
43
|
+
intl: {
|
|
44
|
+
locale: 'en',
|
|
45
|
+
messages: {},
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
initialValue: {
|
|
58
49
|
'001': 'manual',
|
|
59
50
|
'002': 'questions & answers',
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
return (
|
|
64
|
-
<Wrapper
|
|
65
|
-
location={{ pathname: '/folder2/folder21/doc212' }}
|
|
66
|
-
customStore={customStore}
|
|
67
|
-
>
|
|
68
|
-
<div className="ui segment form attached">
|
|
69
|
-
<VocabularyTermsWidget
|
|
70
|
-
{...args}
|
|
71
|
-
id="Simple"
|
|
72
|
-
title="Vocabulary terms"
|
|
73
|
-
block="testBlock"
|
|
74
|
-
value={value}
|
|
75
|
-
value_type={{
|
|
76
|
-
schema: {
|
|
77
|
-
type: 'string',
|
|
78
|
-
},
|
|
79
|
-
}}
|
|
80
|
-
onChange={onChange}
|
|
81
|
-
/>
|
|
82
|
-
<pre>{JSON.stringify(value, null, 4)}</pre>
|
|
83
|
-
</div>
|
|
84
|
-
</Wrapper>
|
|
85
|
-
);
|
|
86
|
-
};
|
|
51
|
+
},
|
|
52
|
+
});
|
|
87
53
|
|
|
88
54
|
export default {
|
|
89
55
|
title: 'Widgets/Vocabulary',
|
|
@@ -96,6 +62,3 @@ export default {
|
|
|
96
62
|
),
|
|
97
63
|
],
|
|
98
64
|
};
|
|
99
|
-
|
|
100
|
-
export const JSONField = () => <WrappedJSONField />;
|
|
101
|
-
export const Simple = () => <WrappedSimple />;
|
|
@@ -1,28 +1,11 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import WysiwygWidget from './WysiwygWidget';
|
|
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
|
-
<WysiwygWidget
|
|
12
|
-
{...args}
|
|
13
|
-
id="field"
|
|
14
|
-
title="Wysiwyg"
|
|
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 Wysiwyg = WysiwygWidgetComponent.bind({});
|
|
5
|
+
export const Wysiwyg = WidgetStory.bind({
|
|
6
|
+
props: { id: 'text', title: 'Rich text' },
|
|
7
|
+
widget: WysiwygWidget,
|
|
8
|
+
});
|
|
26
9
|
|
|
27
10
|
export default {
|
|
28
11
|
title: 'Widgets/Wysiwyg',
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {
|
|
3
|
+
RealStoreWrapper as Wrapper,
|
|
4
|
+
FormUndoWrapper,
|
|
5
|
+
} from '@plone/volto/storybook';
|
|
6
|
+
|
|
7
|
+
export default function StoryComponent({ children, ...args }) {
|
|
8
|
+
const Widget = this.widget;
|
|
9
|
+
const props = this.props || {};
|
|
10
|
+
return (
|
|
11
|
+
<Wrapper
|
|
12
|
+
location={{ pathname: '/folder2/folder21/doc212' }}
|
|
13
|
+
customStore={this.customStore}
|
|
14
|
+
>
|
|
15
|
+
<FormUndoWrapper
|
|
16
|
+
initialState={{
|
|
17
|
+
value: args.value || args.initialValue || this.initialValue,
|
|
18
|
+
}}
|
|
19
|
+
showControls={this.showUndoControls ?? true}
|
|
20
|
+
>
|
|
21
|
+
{({ state, onChange }) => (
|
|
22
|
+
<div className="ui segment form attached" style={{ width: '400px' }}>
|
|
23
|
+
<Widget
|
|
24
|
+
id="field"
|
|
25
|
+
title="Field"
|
|
26
|
+
block="block"
|
|
27
|
+
{...args}
|
|
28
|
+
{...props}
|
|
29
|
+
value={state.value}
|
|
30
|
+
onChange={(block, value) => onChange({ value })}
|
|
31
|
+
/>
|
|
32
|
+
<pre>Value: {JSON.stringify(state.value, null, 4)}</pre>
|
|
33
|
+
</div>
|
|
34
|
+
)}
|
|
35
|
+
</FormUndoWrapper>
|
|
36
|
+
</Wrapper>
|
|
37
|
+
);
|
|
38
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ContactFormComponent } from './ContactForm';
|
|
3
|
+
import { injectIntl } from 'react-intl';
|
|
4
|
+
import { RealStoreWrapper as Wrapper } from '@plone/volto/storybook';
|
|
5
|
+
|
|
6
|
+
const IntlContactFormComponent = injectIntl(ContactFormComponent);
|
|
7
|
+
|
|
8
|
+
const actions = {
|
|
9
|
+
actions: {
|
|
10
|
+
error: null,
|
|
11
|
+
actions: {
|
|
12
|
+
document_actions: [],
|
|
13
|
+
object: [
|
|
14
|
+
{
|
|
15
|
+
icon: '',
|
|
16
|
+
id: 'view',
|
|
17
|
+
title: 'View',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
icon: '',
|
|
21
|
+
id: 'edit',
|
|
22
|
+
title: 'Edit',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
icon: '',
|
|
26
|
+
id: 'folderContents',
|
|
27
|
+
title: 'Contents',
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
icon: '',
|
|
31
|
+
id: 'history',
|
|
32
|
+
title: 'History',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
icon: '',
|
|
36
|
+
id: 'local_roles',
|
|
37
|
+
title: 'Sharing',
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
object_buttons: [],
|
|
41
|
+
portal_tabs: [
|
|
42
|
+
{
|
|
43
|
+
icon: '',
|
|
44
|
+
id: 'index_html',
|
|
45
|
+
title: 'Home',
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
site_actions: [
|
|
49
|
+
{
|
|
50
|
+
icon: '',
|
|
51
|
+
id: 'sitemap',
|
|
52
|
+
title: 'Site Map',
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
icon: '',
|
|
56
|
+
id: 'accessibility',
|
|
57
|
+
title: 'Accessibility',
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
icon: '',
|
|
61
|
+
id: 'contact',
|
|
62
|
+
title: 'Contact',
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
user: [
|
|
66
|
+
{
|
|
67
|
+
icon: '',
|
|
68
|
+
id: 'preferences',
|
|
69
|
+
title: 'Preferences',
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
icon: '',
|
|
73
|
+
id: 'dashboard',
|
|
74
|
+
title: 'Dashboard',
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
icon: '',
|
|
78
|
+
id: 'plone_setup',
|
|
79
|
+
title: 'Site Setup',
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
icon: '',
|
|
83
|
+
id: 'logout',
|
|
84
|
+
title: 'Log out',
|
|
85
|
+
},
|
|
86
|
+
],
|
|
87
|
+
},
|
|
88
|
+
loaded: true,
|
|
89
|
+
loading: false,
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
function StoryComponent(props) {
|
|
94
|
+
return (
|
|
95
|
+
<Wrapper customStore={{ actions, unlockRequest: {} }}>
|
|
96
|
+
<div id="toolbar" style={{ display: 'none' }} />
|
|
97
|
+
<IntlContactFormComponent
|
|
98
|
+
{...props}
|
|
99
|
+
pathname="/contact"
|
|
100
|
+
error={props.error ? { message: props.error } : null}
|
|
101
|
+
/>
|
|
102
|
+
</Wrapper>
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export const ContactForm = StoryComponent.bind({});
|
|
107
|
+
ContactForm.args = {
|
|
108
|
+
error: { message: 'Something' },
|
|
109
|
+
loading: false,
|
|
110
|
+
loaded: true,
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
export default {
|
|
114
|
+
title: 'Public components/Contact Form',
|
|
115
|
+
component: ContactFormComponent,
|
|
116
|
+
decorators: [
|
|
117
|
+
(Story) => (
|
|
118
|
+
<div className="ui segment form attached" style={{ width: '400px' }}>
|
|
119
|
+
<Story />
|
|
120
|
+
</div>
|
|
121
|
+
),
|
|
122
|
+
],
|
|
123
|
+
argTypes: {
|
|
124
|
+
error: { control: 'text' },
|
|
125
|
+
},
|
|
126
|
+
};
|
|
@@ -61,8 +61,8 @@ const CorsError = () => (
|
|
|
61
61
|
}}
|
|
62
62
|
>
|
|
63
63
|
<FormattedMessage
|
|
64
|
-
id="The backend server of your website is not
|
|
65
|
-
defaultMessage="The backend server of your website is not
|
|
64
|
+
id="The backend server of your website is not answering, we apologize for the inconvenience. Please try to re-load the page and try again. If the problem persists please contact the site administrators."
|
|
65
|
+
defaultMessage="The backend server of your website is not answering, we apologize for the inconvenience. Please try to re-load the page and try again. If the problem persists please contact the site administrators."
|
|
66
66
|
/>
|
|
67
67
|
</p>
|
|
68
68
|
|
package/src/config/Loadables.jsx
CHANGED
package/src/config/index.js
CHANGED
|
@@ -123,23 +123,13 @@ class Html extends Component {
|
|
|
123
123
|
}}
|
|
124
124
|
/>
|
|
125
125
|
|
|
126
|
+
<link rel="icon" href="/favicon.ico" sizes="any" />
|
|
127
|
+
<link rel="icon" href="/icon.svg" type="image/svg+xml" />
|
|
126
128
|
<link
|
|
127
129
|
rel="apple-touch-icon"
|
|
128
130
|
sizes="180x180"
|
|
129
131
|
href="/apple-touch-icon.png"
|
|
130
132
|
/>
|
|
131
|
-
<link
|
|
132
|
-
rel="icon"
|
|
133
|
-
type="image/png"
|
|
134
|
-
sizes="32x32"
|
|
135
|
-
href="/favicon-32x32.png"
|
|
136
|
-
/>
|
|
137
|
-
<link
|
|
138
|
-
rel="icon"
|
|
139
|
-
type="image/png"
|
|
140
|
-
sizes="16x16"
|
|
141
|
-
href="/favicon-16x16.png"
|
|
142
|
-
/>
|
|
143
133
|
<link rel="manifest" href="/site.webmanifest" />
|
|
144
134
|
<meta name="generator" content="Plone 6 - https://plone.org" />
|
|
145
135
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import Undoo from 'undoo';
|
|
3
|
+
|
|
4
|
+
// Code based on Apache-2.0 License
|
|
5
|
+
// https://github.com/reaviz/reaflow/blob/78d60aa04f514947a17097c906efdbbd6bae5080/src/helpers/useUndo.ts
|
|
6
|
+
|
|
7
|
+
const useUndoManager = (
|
|
8
|
+
state,
|
|
9
|
+
onUndoRedo,
|
|
10
|
+
{ maxUndoLevels, enableHotKeys = true },
|
|
11
|
+
) => {
|
|
12
|
+
const [canUndo, setCanUndo] = React.useState(false);
|
|
13
|
+
const [canRedo, setCanRedo] = React.useState(false);
|
|
14
|
+
const manager = React.useRef(new Undoo({ maxLength: maxUndoLevels }));
|
|
15
|
+
// Reference:
|
|
16
|
+
// https://reactjs.org/docs/hooks-faq.html#how-to-read-an-often-changing-value-from-usecallback
|
|
17
|
+
const callbackRef = React.useRef(onUndoRedo);
|
|
18
|
+
React.useEffect(() => {
|
|
19
|
+
callbackRef.current = onUndoRedo;
|
|
20
|
+
}, [onUndoRedo]);
|
|
21
|
+
|
|
22
|
+
const doUndo = React.useCallback(() => {
|
|
23
|
+
manager.current.undo(({ state }) => {
|
|
24
|
+
const nextUndo = manager.current.canUndo();
|
|
25
|
+
const nextRedo = manager.current.canRedo();
|
|
26
|
+
setCanUndo(nextUndo);
|
|
27
|
+
setCanRedo(nextRedo);
|
|
28
|
+
|
|
29
|
+
callbackRef.current({
|
|
30
|
+
state,
|
|
31
|
+
type: 'undo',
|
|
32
|
+
canUndo: nextUndo,
|
|
33
|
+
canRedo: nextRedo,
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
}, []);
|
|
37
|
+
|
|
38
|
+
React.useEffect(() => {
|
|
39
|
+
manager.current.save({
|
|
40
|
+
state,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
setCanUndo(manager.current.canUndo());
|
|
44
|
+
setCanRedo(manager.current.canRedo());
|
|
45
|
+
}, [state]);
|
|
46
|
+
|
|
47
|
+
const doRedo = React.useCallback(() => {
|
|
48
|
+
manager.current.redo(({ state }) => {
|
|
49
|
+
const nextUndo = manager.current.canUndo();
|
|
50
|
+
const nextRedo = manager.current.canRedo();
|
|
51
|
+
setCanUndo(nextUndo);
|
|
52
|
+
setCanRedo(nextRedo);
|
|
53
|
+
|
|
54
|
+
callbackRef.current({
|
|
55
|
+
state,
|
|
56
|
+
type: 'redo',
|
|
57
|
+
canUndo: nextUndo,
|
|
58
|
+
canRedo: nextRedo,
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
}, []);
|
|
62
|
+
|
|
63
|
+
const handleKeys = React.useCallback(
|
|
64
|
+
(event) => {
|
|
65
|
+
const keyName = event.key;
|
|
66
|
+
|
|
67
|
+
if (keyName === 'Control' || keyName === 'Meta') {
|
|
68
|
+
// do not alert when only Control key is pressed.
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if (event.ctrlKey || event.metaKey) {
|
|
72
|
+
if (keyName === 'z') {
|
|
73
|
+
event.preventDefault();
|
|
74
|
+
event.stopPropagation();
|
|
75
|
+
doUndo();
|
|
76
|
+
} else if (keyName === 'y') {
|
|
77
|
+
event.preventDefault();
|
|
78
|
+
event.stopPropagation();
|
|
79
|
+
doRedo();
|
|
80
|
+
}
|
|
81
|
+
} else {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
[doUndo, doRedo],
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
React.useEffect(() => {
|
|
89
|
+
if (!enableHotKeys) return;
|
|
90
|
+
document.addEventListener('keydown', handleKeys);
|
|
91
|
+
return () => document.removeEventListener('keydown', handleKeys);
|
|
92
|
+
}, [enableHotKeys, handleKeys]);
|
|
93
|
+
|
|
94
|
+
return {
|
|
95
|
+
doUndo,
|
|
96
|
+
doRedo,
|
|
97
|
+
canUndo,
|
|
98
|
+
canRedo,
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
export default useUndoManager;
|
package/src/helpers/index.js
CHANGED
|
@@ -89,3 +89,4 @@ export { userHasRoles } from './User/User';
|
|
|
89
89
|
export { useDetectClickOutside } from './Utils/useDetectClickOutside';
|
|
90
90
|
export { usePrevious } from './Utils/usePrevious';
|
|
91
91
|
export { usePagination } from './Utils/usePagination';
|
|
92
|
+
export useUndoManager from './UndoManager/useUndoManager';
|
|
@@ -14,7 +14,7 @@ describe('api middleware helpers', () => {
|
|
|
14
14
|
const result = addExpandersToPath('/de/mypage', GET_CONTENT);
|
|
15
15
|
expect(result).toEqual('/de/mypage?expand=mycustomexpander');
|
|
16
16
|
});
|
|
17
|
-
it('addExpandersToPath with
|
|
17
|
+
it('addExpandersToPath - Custom expander from settings, with expander (translation) already present (multilingual) in query', () => {
|
|
18
18
|
config.settings.apiExpanders = [
|
|
19
19
|
{
|
|
20
20
|
match: '/',
|
|
@@ -28,7 +28,7 @@ describe('api middleware helpers', () => {
|
|
|
28
28
|
);
|
|
29
29
|
expect(result).toEqual('/de/mypage?expand=translations,mycustomexpander');
|
|
30
30
|
});
|
|
31
|
-
it('addExpandersToPath not matching', () => {
|
|
31
|
+
it('addExpandersToPath - Path not matching', () => {
|
|
32
32
|
config.settings.apiExpanders = [
|
|
33
33
|
{
|
|
34
34
|
match: '/de/otherpath',
|
|
@@ -39,7 +39,7 @@ describe('api middleware helpers', () => {
|
|
|
39
39
|
const result = addExpandersToPath('/de/mypage', GET_CONTENT);
|
|
40
40
|
expect(result).toEqual('/de/mypage');
|
|
41
41
|
});
|
|
42
|
-
it('addExpandersToPath not matching, preserve query', () => {
|
|
42
|
+
it('addExpandersToPath - Path not matching, preserve query', () => {
|
|
43
43
|
config.settings.apiExpanders = [
|
|
44
44
|
{
|
|
45
45
|
match: '/de/otherpath',
|
|
@@ -53,7 +53,7 @@ describe('api middleware helpers', () => {
|
|
|
53
53
|
);
|
|
54
54
|
expect(result).toEqual('/de/mypage/@navigation?expand.navigation.depth=3');
|
|
55
55
|
});
|
|
56
|
-
it('addExpandersToPath
|
|
56
|
+
it('addExpandersToPath - Two custom expanders from settings', () => {
|
|
57
57
|
config.settings.apiExpanders = [
|
|
58
58
|
{
|
|
59
59
|
match: '/',
|
|
@@ -67,7 +67,7 @@ describe('api middleware helpers', () => {
|
|
|
67
67
|
'/de/mypage?expand=mycustomexpander,mycustomexpander2',
|
|
68
68
|
);
|
|
69
69
|
});
|
|
70
|
-
it('addExpandersToPath
|
|
70
|
+
it('addExpandersToPath - Two custom expanders from settings, expansion nested (with dots notation) present', () => {
|
|
71
71
|
config.settings.apiExpanders = [
|
|
72
72
|
{
|
|
73
73
|
match: '/',
|
|
@@ -84,7 +84,7 @@ describe('api middleware helpers', () => {
|
|
|
84
84
|
'/de/mypage/@navigation?expand=mycustomexpander,mycustomexpander2&expand.navigation.depth=3',
|
|
85
85
|
);
|
|
86
86
|
});
|
|
87
|
-
it('addExpandersToPath
|
|
87
|
+
it('addExpandersToPath - Two custom expanders from settings, query present ', () => {
|
|
88
88
|
config.settings.apiExpanders = [
|
|
89
89
|
{
|
|
90
90
|
match: '/',
|
|
@@ -101,4 +101,55 @@ describe('api middleware helpers', () => {
|
|
|
101
101
|
'/de/mypage/@navigation?expand=mycustomexpander,mycustomexpander2&expand.navigation.depth=3&someotherquery=1',
|
|
102
102
|
);
|
|
103
103
|
});
|
|
104
|
+
it('addExpandersToPath - Two custom expanders from settings, a list parameter present', () => {
|
|
105
|
+
config.settings.apiExpanders = [
|
|
106
|
+
{
|
|
107
|
+
match: '/',
|
|
108
|
+
GET_CONTENT: ['mycustomexpander', 'mycustomexpander2'],
|
|
109
|
+
},
|
|
110
|
+
];
|
|
111
|
+
|
|
112
|
+
const result = addExpandersToPath(
|
|
113
|
+
'/de/mypage/@navigation?expand.navigation.depth=3&someotherquery=1&someotherquery=2',
|
|
114
|
+
GET_CONTENT,
|
|
115
|
+
);
|
|
116
|
+
// No need to stringify
|
|
117
|
+
expect(result).toEqual(
|
|
118
|
+
'/de/mypage/@navigation?expand=mycustomexpander,mycustomexpander2&expand.navigation.depth=3&someotherquery=1&someotherquery=2',
|
|
119
|
+
);
|
|
120
|
+
});
|
|
121
|
+
it('addExpandersToPath - Two custom expanders from settings, a list parameter present, and a translation expand already in query', () => {
|
|
122
|
+
config.settings.apiExpanders = [
|
|
123
|
+
{
|
|
124
|
+
match: '/',
|
|
125
|
+
GET_CONTENT: ['mycustomexpander', 'mycustomexpander2'],
|
|
126
|
+
},
|
|
127
|
+
];
|
|
128
|
+
|
|
129
|
+
const result = addExpandersToPath(
|
|
130
|
+
'/de/mypage/@navigation?expand=translations&expand.navigation.depth=3&someotherquery=1&someotherquery=2',
|
|
131
|
+
GET_CONTENT,
|
|
132
|
+
);
|
|
133
|
+
// No need to stringify
|
|
134
|
+
expect(result).toEqual(
|
|
135
|
+
'/de/mypage/@navigation?expand=translations,mycustomexpander,mycustomexpander2&expand.navigation.depth=3&someotherquery=1&someotherquery=2',
|
|
136
|
+
);
|
|
137
|
+
});
|
|
138
|
+
it('addExpandersToPath - Two custom expanders from settings, a list parameter present, and a two expand present already in query', () => {
|
|
139
|
+
config.settings.apiExpanders = [
|
|
140
|
+
{
|
|
141
|
+
match: '/',
|
|
142
|
+
GET_CONTENT: ['mycustomexpander', 'mycustomexpander2'],
|
|
143
|
+
},
|
|
144
|
+
];
|
|
145
|
+
|
|
146
|
+
const result = addExpandersToPath(
|
|
147
|
+
'/de/mypage/@navigation?expand=translations,secondexpand&expand.navigation.depth=3&someotherquery=1&someotherquery=2',
|
|
148
|
+
GET_CONTENT,
|
|
149
|
+
);
|
|
150
|
+
// No need to stringify
|
|
151
|
+
expect(result).toEqual(
|
|
152
|
+
'/de/mypage/@navigation?expand=translations,secondexpand,mycustomexpander,mycustomexpander2&expand.navigation.depth=3&someotherquery=1&someotherquery=2',
|
|
153
|
+
);
|
|
154
|
+
});
|
|
104
155
|
});
|
package/src/middleware/api.js
CHANGED
|
@@ -22,6 +22,13 @@ let socket = null;
|
|
|
22
22
|
/**
|
|
23
23
|
*
|
|
24
24
|
* Add configured expanders to an api call for an action
|
|
25
|
+
* Requirements:
|
|
26
|
+
*
|
|
27
|
+
* - It should add the expanders set in the config settings
|
|
28
|
+
* - It should preserve any query if present
|
|
29
|
+
* - It should preserve (and add) any expand parameter (if present) e.g. translations
|
|
30
|
+
* - It should take use the correct codification for arrays in querystring (repeated parameter for each member of the array)
|
|
31
|
+
*
|
|
25
32
|
* @function addExpandersToPath
|
|
26
33
|
* @param {string} path The url/path including the querystring
|
|
27
34
|
* @param {*} type The action type
|
|
@@ -31,24 +38,38 @@ export function addExpandersToPath(path, type) {
|
|
|
31
38
|
const { settings } = config;
|
|
32
39
|
const { apiExpanders = [] } = settings;
|
|
33
40
|
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
41
|
+
const {
|
|
42
|
+
url,
|
|
43
|
+
query: { expand, ...query },
|
|
44
|
+
} = qs.parseUrl(path);
|
|
45
|
+
|
|
46
|
+
const expandersFromConfig = apiExpanders
|
|
47
|
+
.filter((expand) => matchPath(url, expand.match) && expand[type])
|
|
37
48
|
.map((expand) => expand[type]);
|
|
38
|
-
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
49
|
+
|
|
50
|
+
const expandMerge = compact(union([expand, ...flatten(expandersFromConfig)]));
|
|
51
|
+
|
|
52
|
+
const stringifiedExpand = qs.stringify(
|
|
53
|
+
{ expand: expandMerge },
|
|
54
|
+
{
|
|
55
|
+
arrayFormat: 'comma',
|
|
56
|
+
encode: false,
|
|
57
|
+
},
|
|
58
|
+
);
|
|
59
|
+
|
|
43
60
|
const stringifiedQuery = qs.stringify(query, {
|
|
44
|
-
arrayFormat: 'comma',
|
|
45
61
|
encode: false,
|
|
46
62
|
});
|
|
47
|
-
if (!stringifiedQuery) {
|
|
48
|
-
return pathPart;
|
|
49
|
-
}
|
|
50
63
|
|
|
51
|
-
|
|
64
|
+
if (stringifiedQuery && stringifiedExpand) {
|
|
65
|
+
return `${url}?${stringifiedExpand}&${stringifiedQuery}`;
|
|
66
|
+
} else if (!stringifiedQuery && stringifiedExpand) {
|
|
67
|
+
return `${url}?${stringifiedExpand}`;
|
|
68
|
+
} else if (stringifiedQuery && !stringifiedExpand) {
|
|
69
|
+
return `${url}?${stringifiedQuery}`;
|
|
70
|
+
} else {
|
|
71
|
+
return url;
|
|
72
|
+
}
|
|
52
73
|
}
|
|
53
74
|
|
|
54
75
|
/**
|
|
@@ -71,6 +71,7 @@ export default function vocabularies(state = initialState, action = {}) {
|
|
|
71
71
|
[action.vocabulary]: {
|
|
72
72
|
...vocabState,
|
|
73
73
|
subrequests: {
|
|
74
|
+
...vocabState.subrequests,
|
|
74
75
|
[action.subrequest]: {
|
|
75
76
|
...subrequestState,
|
|
76
77
|
error: null,
|
|
@@ -141,8 +142,18 @@ export default function vocabularies(state = initialState, action = {}) {
|
|
|
141
142
|
...subrequestState,
|
|
142
143
|
error: null,
|
|
143
144
|
loaded: true,
|
|
144
|
-
loading: !!(
|
|
145
|
-
|
|
145
|
+
loading: !!(subrequestState.loading - 1),
|
|
146
|
+
...(action.token && {
|
|
147
|
+
[action.token]: action.result.items[0].title,
|
|
148
|
+
}),
|
|
149
|
+
...(action.tokens && {
|
|
150
|
+
items: [
|
|
151
|
+
...action.result.items.map((item) => ({
|
|
152
|
+
label: item.title,
|
|
153
|
+
value: item.token,
|
|
154
|
+
})),
|
|
155
|
+
],
|
|
156
|
+
}),
|
|
146
157
|
},
|
|
147
158
|
},
|
|
148
159
|
},
|