@plone/volto 15.0.0-alpha.4 → 15.0.0-alpha.8
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/.github/ISSUE_TEMPLATE/bug_report.md +7 -6
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -1
- package/.github/workflows/docs.yml +15 -55
- package/CHANGELOG.md +57 -2
- package/CODE_OF_CONDUCT.md +0 -1
- package/COMMITLINT.md +19 -21
- package/README.md +1 -1
- package/SECURITY.md +0 -1
- package/addon-registry.js +6 -3
- package/dist/assets.json +1 -0
- package/dist/chunks.json +572 -0
- package/dist/loadable-stats.json +2099 -0
- package/dist/public/android-chrome-192x192.png +0 -0
- package/dist/public/android-chrome-512x512.png +0 -0
- package/dist/public/apple-touch-icon.png +0 -0
- package/dist/public/favicon-16x16.png +0 -0
- package/dist/public/favicon-32x32.png +0 -0
- package/dist/public/favicon.ico +0 -0
- package/dist/public/icon.svg +13 -0
- package/dist/public/index.html.spa +34 -0
- package/dist/public/robots.txt +2 -0
- package/dist/public/site.webmanifest +19 -0
- package/dist/public/static/css/15.2cdd5437.chunk.css +409 -0
- package/dist/public/static/css/15.2cdd5437.chunk.css.map +1 -0
- package/dist/public/static/css/8.37cef611.chunk.css +2 -0
- package/dist/public/static/css/8.37cef611.chunk.css.map +1 -0
- package/dist/public/static/css/client.4cb92c57.chunk.css +8 -0
- package/dist/public/static/css/client.4cb92c57.chunk.css.map +1 -0
- package/dist/public/static/css/plone-volto-components-manage-Widgets-DatetimeWidget.c847a331.chunk.css +2 -0
- package/dist/public/static/css/plone-volto-components-manage-Widgets-DatetimeWidget.c847a331.chunk.css.map +1 -0
- package/dist/public/static/js/0.3e794c57.chunk.js +2 -0
- package/dist/public/static/js/0.3e794c57.chunk.js.map +1 -0
- package/dist/public/static/js/1.fece2b93.chunk.js +3 -0
- package/dist/public/static/js/1.fece2b93.chunk.js.LICENSE.txt +8 -0
- package/dist/public/static/js/1.fece2b93.chunk.js.map +1 -0
- package/dist/public/static/js/15.2cdd5437.chunk.js +3 -0
- package/dist/public/static/js/15.2cdd5437.chunk.js.LICENSE.txt +120 -0
- package/dist/public/static/js/15.2cdd5437.chunk.js.map +1 -0
- package/dist/public/static/js/16.a3a0662d.chunk.js +3 -0
- package/dist/public/static/js/16.a3a0662d.chunk.js.LICENSE.txt +8 -0
- package/dist/public/static/js/16.a3a0662d.chunk.js.map +1 -0
- package/dist/public/static/js/17.9478c50d.chunk.js +2 -0
- package/dist/public/static/js/17.9478c50d.chunk.js.map +1 -0
- package/dist/public/static/js/18.388e65d0.chunk.js +2 -0
- package/dist/public/static/js/18.388e65d0.chunk.js.map +1 -0
- package/dist/public/static/js/19.7c6b4a80.chunk.js +2 -0
- package/dist/public/static/js/19.7c6b4a80.chunk.js.map +1 -0
- package/dist/public/static/js/2.e6b0d690.chunk.js +2 -0
- package/dist/public/static/js/2.e6b0d690.chunk.js.map +1 -0
- package/dist/public/static/js/20.ada67f0e.chunk.js +3 -0
- package/dist/public/static/js/20.ada67f0e.chunk.js.LICENSE.txt +8 -0
- package/dist/public/static/js/20.ada67f0e.chunk.js.map +1 -0
- package/dist/public/static/js/21.3de49ac8.chunk.js +2 -0
- package/dist/public/static/js/21.3de49ac8.chunk.js.map +1 -0
- package/dist/public/static/js/22.ecefb8f2.chunk.js +2 -0
- package/dist/public/static/js/22.ecefb8f2.chunk.js.map +1 -0
- package/dist/public/static/js/23.3027bc00.chunk.js +2 -0
- package/dist/public/static/js/23.3027bc00.chunk.js.map +1 -0
- package/dist/public/static/js/24.aaaf4abf.chunk.js +2 -0
- package/dist/public/static/js/24.aaaf4abf.chunk.js.map +1 -0
- package/dist/public/static/js/25.c4d7d5e0.chunk.js +2 -0
- package/dist/public/static/js/25.c4d7d5e0.chunk.js.map +1 -0
- package/dist/public/static/js/26.d59ac3c1.chunk.js +2 -0
- package/dist/public/static/js/26.d59ac3c1.chunk.js.map +1 -0
- package/dist/public/static/js/27.266d95dd.chunk.js +2 -0
- package/dist/public/static/js/27.266d95dd.chunk.js.map +1 -0
- package/dist/public/static/js/28.d965d304.chunk.js +2 -0
- package/dist/public/static/js/28.d965d304.chunk.js.map +1 -0
- package/dist/public/static/js/29.7d8d1992.chunk.js +2 -0
- package/dist/public/static/js/29.7d8d1992.chunk.js.map +1 -0
- package/dist/public/static/js/3.025ba843.chunk.js +2 -0
- package/dist/public/static/js/3.025ba843.chunk.js.map +1 -0
- package/dist/public/static/js/30.a3d54e31.chunk.js +2 -0
- package/dist/public/static/js/30.a3d54e31.chunk.js.map +1 -0
- package/dist/public/static/js/31.9edf64ee.chunk.js +2 -0
- package/dist/public/static/js/31.9edf64ee.chunk.js.map +1 -0
- package/dist/public/static/js/32.649dbfc2.chunk.js +2 -0
- package/dist/public/static/js/32.649dbfc2.chunk.js.map +1 -0
- package/dist/public/static/js/33.45949ca4.chunk.js +2 -0
- package/dist/public/static/js/33.45949ca4.chunk.js.map +1 -0
- package/dist/public/static/js/34.084257cf.chunk.js +2 -0
- package/dist/public/static/js/34.084257cf.chunk.js.map +1 -0
- package/dist/public/static/js/35.00679602.chunk.js +3 -0
- package/dist/public/static/js/35.00679602.chunk.js.LICENSE.txt +37 -0
- package/dist/public/static/js/35.00679602.chunk.js.map +1 -0
- package/dist/public/static/js/36.4a29fdbd.chunk.js +3 -0
- package/dist/public/static/js/36.4a29fdbd.chunk.js.LICENSE.txt +7 -0
- package/dist/public/static/js/36.4a29fdbd.chunk.js.map +1 -0
- package/dist/public/static/js/37.fbbe07b3.chunk.js +3 -0
- package/dist/public/static/js/37.fbbe07b3.chunk.js.LICENSE.txt +14 -0
- package/dist/public/static/js/37.fbbe07b3.chunk.js.map +1 -0
- package/dist/public/static/js/38.b31c59ad.chunk.js +3 -0
- package/dist/public/static/js/38.b31c59ad.chunk.js.LICENSE.txt +8 -0
- package/dist/public/static/js/38.b31c59ad.chunk.js.map +1 -0
- package/dist/public/static/js/39.69d6a789.chunk.js +2 -0
- package/dist/public/static/js/39.69d6a789.chunk.js.map +1 -0
- package/dist/public/static/js/4.bdc4a5c5.chunk.js +2 -0
- package/dist/public/static/js/4.bdc4a5c5.chunk.js.map +1 -0
- package/dist/public/static/js/40.90de6e4a.chunk.js +2 -0
- package/dist/public/static/js/40.90de6e4a.chunk.js.map +1 -0
- package/dist/public/static/js/7.7acc66bc.chunk.js +2 -0
- package/dist/public/static/js/7.7acc66bc.chunk.js.map +1 -0
- package/dist/public/static/js/8.37cef611.chunk.js +3 -0
- package/dist/public/static/js/8.37cef611.chunk.js.LICENSE.txt +25 -0
- package/dist/public/static/js/8.37cef611.chunk.js.map +1 -0
- package/dist/public/static/js/client.4cb92c57.chunk.js +2 -0
- package/dist/public/static/js/client.4cb92c57.chunk.js.map +1 -0
- package/dist/public/static/js/draft-js-lib-isSoftNewlineEvent.6cd05e34.chunk.js +2 -0
- package/dist/public/static/js/draft-js-lib-isSoftNewlineEvent.6cd05e34.chunk.js.map +1 -0
- package/dist/public/static/js/moment.2caa76d1.chunk.js +2 -0
- package/dist/public/static/js/moment.2caa76d1.chunk.js.map +1 -0
- package/dist/public/static/js/plone-volto-components-manage-Widgets-DatetimeWidget.c847a331.chunk.js +2 -0
- package/dist/public/static/js/plone-volto-components-manage-Widgets-DatetimeWidget.c847a331.chunk.js.map +1 -0
- package/dist/public/static/js/plone-volto-components-theme-View-EventView.433dd14b.chunk.js +2 -0
- package/dist/public/static/js/plone-volto-components-theme-View-EventView.433dd14b.chunk.js.map +1 -0
- package/dist/public/static/js/react-dates.f71abb7c.chunk.js +2 -0
- package/dist/public/static/js/react-dates.f71abb7c.chunk.js.map +1 -0
- package/dist/public/static/js/react-simple-code-editor.33478dc3.chunk.js +2 -0
- package/dist/public/static/js/react-simple-code-editor.33478dc3.chunk.js.map +1 -0
- package/dist/public/static/js/runtime~client.d372df0e.js +2 -0
- package/dist/public/static/js/runtime~client.d372df0e.js.map +1 -0
- package/dist/public/static/media/Logo.16e25cdf.svg +21 -0
- package/dist/public/static/media/block-image.8a4a14d5.svg +8 -0
- package/dist/public/static/media/block-maps.731e84f6.svg +7 -0
- package/dist/public/static/media/block-video.832fa3ff.svg +7 -0
- package/dist/public/static/media/default-image.9451b251.svg +13 -0
- package/dist/public/static/media/flags.9c74e172.png +0 -0
- package/dist/public/static/media/icons.022583c4.svg +320 -0
- package/dist/public/static/media/icons.06400145.ttf +0 -0
- package/dist/public/static/media/icons.dbc1ef8b.eot +0 -0
- package/dist/public/static/media/icons.df45b7de.woff +0 -0
- package/dist/server.js +2 -0
- package/locales/ca/LC_MESSAGES/volto.po +14 -0
- package/locales/ca.json +1 -1
- package/locales/de/LC_MESSAGES/volto.po +14 -0
- package/locales/de.json +1 -1
- package/locales/en/LC_MESSAGES/volto.po +14 -0
- package/locales/en.json +1 -1
- package/locales/es/LC_MESSAGES/volto.po +14 -0
- package/locales/es.json +1 -1
- package/locales/eu/LC_MESSAGES/volto.po +14 -0
- package/locales/eu.json +1 -1
- package/locales/fr/LC_MESSAGES/volto.po +14 -0
- package/locales/fr.json +1 -1
- package/locales/it/LC_MESSAGES/volto.po +14 -0
- package/locales/it.json +1 -1
- package/locales/ja/LC_MESSAGES/volto.po +14 -0
- package/locales/ja.json +1 -1
- package/locales/nl/LC_MESSAGES/volto.po +14 -0
- package/locales/nl.json +1 -1
- package/locales/pt/LC_MESSAGES/volto.po +14 -0
- package/locales/pt.json +1 -1
- package/locales/pt_BR/LC_MESSAGES/volto.po +14 -0
- package/locales/pt_BR.json +1 -1
- package/locales/ro/LC_MESSAGES/volto.po +14 -0
- package/locales/ro.json +1 -1
- package/locales/volto.pot +15 -1
- package/logos/Logo.png +0 -0
- package/logos/volto-colorful.png +0 -0
- package/logos/volto-colorful.svg +35 -0
- package/logos/volto-guide.png +0 -0
- package/logos/volto-h-transparent.svg +6 -0
- package/logos/volto-transparent.png +0 -0
- package/logos/volto-transparent.svg +19 -0
- package/logos/volto-transparent2.svg +5 -0
- package/logos/volto-yellow.svg +29 -0
- package/logos/volto.sketch +0 -0
- package/netlify.toml +2 -0
- package/package.json +6 -2
- package/razzle.config.js +2 -2
- package/src/actions/language/language.js +7 -2
- package/src/components/manage/AnchorPlugin/components/LinkButton/AddLinkForm.jsx +1 -2
- package/src/components/manage/AnchorPlugin/components/LinkButton/index.jsx +15 -6
- package/src/components/manage/AnchorPlugin/index.jsx +12 -5
- package/src/components/manage/AnchorPlugin/utils/EditorUtils.js +8 -7
- package/src/components/manage/Blocks/Description/Edit.jsx +33 -19
- package/src/components/manage/Blocks/Description/Edit.test.jsx +6 -0
- package/src/components/manage/Blocks/HeroImageLeft/Edit.jsx +37 -26
- package/src/components/manage/Blocks/HeroImageLeft/Edit.test.jsx +6 -0
- package/src/components/manage/Blocks/Search/README.md +20 -0
- package/src/components/manage/Blocks/Search/components/CheckboxFacet.jsx +16 -3
- package/src/components/manage/Blocks/Search/components/DateRangeFacet.jsx +120 -0
- package/src/components/manage/Blocks/Search/components/DateRangeFacet.test.jsx +34 -0
- package/src/components/manage/Blocks/Search/components/DateRangeFacetFilterListEntry.jsx +39 -0
- package/src/components/manage/Blocks/Search/components/Facets.jsx +24 -25
- package/src/components/manage/Blocks/Search/components/FilterList.jsx +37 -67
- package/src/components/manage/Blocks/Search/components/FilterList.test.jsx +49 -1
- package/src/components/manage/Blocks/Search/components/SelectFacet.jsx +9 -0
- package/src/components/manage/Blocks/Search/components/SelectFacetFilterListEntry.jsx +42 -0
- package/src/components/manage/Blocks/Search/components/SelectStyling.jsx +1 -1
- package/src/components/manage/Blocks/Search/components/ToggleFacet.jsx +38 -0
- package/src/components/manage/Blocks/Search/components/ToggleFacetFilterListEntry.jsx +39 -0
- package/src/components/manage/Blocks/Search/components/base.js +52 -0
- package/src/components/manage/Blocks/Search/components/index.js +5 -0
- package/src/components/manage/Blocks/Search/hocs/withSearch.jsx +68 -27
- package/src/components/manage/Blocks/Search/schema.js +7 -4
- package/src/components/manage/Blocks/Search/utils.js +16 -0
- package/src/components/manage/Blocks/Table/Cell.jsx +40 -14
- package/src/components/manage/Blocks/Table/Cell.test.jsx +7 -1
- package/src/components/manage/Blocks/Table/Edit.jsx +7 -3
- package/src/components/manage/Blocks/Table/Edit.test.jsx +6 -0
- package/src/components/manage/Blocks/Table/View.jsx +2 -2
- package/src/components/manage/Blocks/Text/Edit.jsx +56 -14
- package/src/components/manage/Blocks/Text/Edit.test.jsx +7 -1
- package/src/components/manage/Blocks/Text/View.jsx +2 -2
- package/src/components/manage/Blocks/Title/Edit.jsx +25 -13
- package/src/components/manage/Blocks/Title/Edit.test.jsx +6 -0
- package/src/components/manage/Sidebar/Sidebar.jsx +5 -1
- package/src/components/manage/Toolbar/Toolbar.jsx +3 -1
- package/src/components/manage/UniversalLink/UniversalLink.jsx +5 -2
- package/src/components/manage/Widgets/DatetimeWidget.jsx +3 -1
- package/src/components/manage/Widgets/UrlWidget.jsx +1 -1
- package/src/components/manage/Widgets/WysiwygWidget.jsx +45 -19
- package/src/components/manage/Widgets/WysiwygWidget.test.jsx +7 -1
- package/src/components/theme/View/LinkView.jsx +1 -1
- package/src/components/theme/View/View.jsx +5 -1
- package/src/config/Blocks.jsx +31 -0
- package/src/config/Loadables.jsx +22 -0
- package/src/config/RichTextEditor/Blocks.jsx +25 -20
- package/src/config/RichTextEditor/Plugins.jsx +38 -31
- package/src/config/RichTextEditor/Styles.jsx +48 -44
- package/src/config/RichTextEditor/index.js +25 -0
- package/src/config/index.js +14 -18
- package/src/helpers/Api/Api.js +18 -4
- package/src/helpers/Extensions/index.js +1 -1
- package/src/helpers/Extensions/withBlockExtensions.js +4 -0
- package/src/helpers/Extensions/withBlockExtensions.test.js +26 -1
- package/src/helpers/Url/Url.js +32 -1
- package/src/helpers/Url/urlRegex.js +7 -1
- package/src/helpers/index.js +2 -0
- package/src/middleware/api.js +21 -2
- package/src/server.jsx +9 -2
- package/test-setup-config.js +22 -7
- package/theme/themes/pastanaga/extras/blocks.less +29 -0
- package/src/components/manage/AnchorPlugin/utils/URLUtils.js +0 -36
- package/src/components/manage/AnchorPlugin/utils/mailRegex.js +0 -2
- package/src/components/manage/AnchorPlugin/utils/telRegex.js +0 -1
- package/src/components/manage/AnchorPlugin/utils/urlRegex.js +0 -54
|
@@ -5,6 +5,11 @@ import {
|
|
|
5
5
|
DropdownIndicator,
|
|
6
6
|
} from '@plone/volto/components/manage/Widgets/SelectStyling';
|
|
7
7
|
import { selectTheme, customSelectStyles } from './SelectStyling';
|
|
8
|
+
import {
|
|
9
|
+
selectFacetSchemaEnhancer,
|
|
10
|
+
selectFacetStateToValue,
|
|
11
|
+
selectFacetValueToQuery,
|
|
12
|
+
} from './base';
|
|
8
13
|
|
|
9
14
|
const SelectFacet = (props) => {
|
|
10
15
|
const {
|
|
@@ -47,4 +52,8 @@ const SelectFacet = (props) => {
|
|
|
47
52
|
);
|
|
48
53
|
};
|
|
49
54
|
|
|
55
|
+
SelectFacet.schemaEnhancer = selectFacetSchemaEnhancer;
|
|
56
|
+
SelectFacet.stateToValue = selectFacetStateToValue;
|
|
57
|
+
SelectFacet.valueToQuery = selectFacetValueToQuery;
|
|
58
|
+
|
|
50
59
|
export default injectLazyLibs('reactSelect')(SelectFacet);
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Label, Icon } from 'semantic-ui-react';
|
|
3
|
+
|
|
4
|
+
function SelectFacetFilterListEntry(props) {
|
|
5
|
+
const { facet, isEditMode, setFacets, facets } = props;
|
|
6
|
+
return typeof facets[facet] === 'string' ? (
|
|
7
|
+
<Label size="small">
|
|
8
|
+
{facets[facet]}
|
|
9
|
+
<Icon
|
|
10
|
+
name="delete"
|
|
11
|
+
onClick={() => {
|
|
12
|
+
!isEditMode &&
|
|
13
|
+
setFacets({
|
|
14
|
+
...facets,
|
|
15
|
+
[facet]: '',
|
|
16
|
+
});
|
|
17
|
+
}}
|
|
18
|
+
/>
|
|
19
|
+
</Label>
|
|
20
|
+
) : (
|
|
21
|
+
<>
|
|
22
|
+
{facets[facet].map((entry, i) => (
|
|
23
|
+
<Label size="small" key={i}>
|
|
24
|
+
{entry}
|
|
25
|
+
<Icon
|
|
26
|
+
name="delete"
|
|
27
|
+
onClick={() => {
|
|
28
|
+
const entries = facets[facet].filter((item) => item !== entry);
|
|
29
|
+
!isEditMode &&
|
|
30
|
+
setFacets({
|
|
31
|
+
...facets,
|
|
32
|
+
[facet]: entries,
|
|
33
|
+
});
|
|
34
|
+
}}
|
|
35
|
+
/>
|
|
36
|
+
</Label>
|
|
37
|
+
))}
|
|
38
|
+
</>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export default SelectFacetFilterListEntry;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Radio, Header } from 'semantic-ui-react';
|
|
3
|
+
|
|
4
|
+
const ToggleFacet = (props) => {
|
|
5
|
+
const { facet, isEditMode, onChange, value } = props; // value, choices, isMulti, onChange,
|
|
6
|
+
|
|
7
|
+
return (
|
|
8
|
+
<div className="checkbox-facet">
|
|
9
|
+
<Header as="h4">{facet?.title ?? facet?.field?.label}</Header>
|
|
10
|
+
<div className="radio">
|
|
11
|
+
<Radio
|
|
12
|
+
toggle
|
|
13
|
+
checked={value || typeof value === 'string'}
|
|
14
|
+
disabled={isEditMode}
|
|
15
|
+
onChange={(e, { checked }) => {
|
|
16
|
+
onChange(facet.field.value, checked);
|
|
17
|
+
}}
|
|
18
|
+
/>
|
|
19
|
+
</div>
|
|
20
|
+
</div>
|
|
21
|
+
);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
ToggleFacet.stateToValue = ({ facetSettings, index, selectedValue }) => {
|
|
25
|
+
return selectedValue || typeof selectedValue === 'string';
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
ToggleFacet.valueToQuery = ({ value, facet }) => {
|
|
29
|
+
return value || typeof value === 'string'
|
|
30
|
+
? {
|
|
31
|
+
i: facet.field.value,
|
|
32
|
+
o: 'plone.app.querystring.operation.boolean.isTrue',
|
|
33
|
+
v: '',
|
|
34
|
+
}
|
|
35
|
+
: null;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export default ToggleFacet;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Label, Icon } from 'semantic-ui-react';
|
|
3
|
+
import { defineMessages, useIntl } from 'react-intl';
|
|
4
|
+
|
|
5
|
+
const messages = defineMessages({
|
|
6
|
+
yes: {
|
|
7
|
+
id: 'yes',
|
|
8
|
+
defaultMessage: 'Yes',
|
|
9
|
+
},
|
|
10
|
+
no: {
|
|
11
|
+
id: 'no',
|
|
12
|
+
defaultMessage: 'No',
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
function ToggleFacetFilterListEntry(props) {
|
|
17
|
+
const { facet, isEditMode, setFacets, facets } = props;
|
|
18
|
+
const intl = useIntl();
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<Label size="small">
|
|
22
|
+
{intl.formatMessage(facets[facet] ? messages.yes : messages.no)}
|
|
23
|
+
<Icon
|
|
24
|
+
name="delete"
|
|
25
|
+
onClick={() => {
|
|
26
|
+
const filteredFacets = Object.assign(
|
|
27
|
+
{},
|
|
28
|
+
...Object.keys(facets)
|
|
29
|
+
.filter((f) => f !== facet)
|
|
30
|
+
.map((f) => ({ [f]: facets[f] })),
|
|
31
|
+
);
|
|
32
|
+
!isEditMode && setFacets(filteredFacets);
|
|
33
|
+
}}
|
|
34
|
+
/>
|
|
35
|
+
</Label>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export default ToggleFacetFilterListEntry;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { isEmpty } from 'lodash';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Converts the state (extracted from URL) to options for the facet control
|
|
5
|
+
*
|
|
6
|
+
* Shared by the SelectFacet and CheckboxFacet
|
|
7
|
+
*/
|
|
8
|
+
export const selectFacetStateToValue = ({
|
|
9
|
+
facetSettings,
|
|
10
|
+
index,
|
|
11
|
+
selectedValue,
|
|
12
|
+
}) => {
|
|
13
|
+
const isMulti = facetSettings.multiple;
|
|
14
|
+
return selectedValue
|
|
15
|
+
? isMulti
|
|
16
|
+
? Array.isArray(selectedValue)
|
|
17
|
+
? selectedValue.map((v) => ({
|
|
18
|
+
value: v,
|
|
19
|
+
label: index.values?.[v]?.title,
|
|
20
|
+
}))
|
|
21
|
+
: []
|
|
22
|
+
: {
|
|
23
|
+
value: selectedValue,
|
|
24
|
+
label: index.values?.[selectedValue]?.title,
|
|
25
|
+
}
|
|
26
|
+
: [];
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export const selectFacetSchemaEnhancer = ({ schema, formData }) => {
|
|
30
|
+
// adds (enables) the 'multiple' field after the 'type' dropdown
|
|
31
|
+
let { fields } = schema.fieldsets[0];
|
|
32
|
+
const pos = fields.indexOf('type') + 1;
|
|
33
|
+
fields = [
|
|
34
|
+
...fields.slice(0, pos),
|
|
35
|
+
'multiple',
|
|
36
|
+
...fields.slice(pos, fields.length),
|
|
37
|
+
];
|
|
38
|
+
schema.fieldsets[0].fields = fields;
|
|
39
|
+
return schema;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export const selectFacetValueToQuery = ({ value, facet }) => {
|
|
43
|
+
return !isEmpty(value)
|
|
44
|
+
? {
|
|
45
|
+
i: facet.field.value,
|
|
46
|
+
o: Array.isArray(value)
|
|
47
|
+
? 'plone.app.querystring.operation.list.contains'
|
|
48
|
+
: 'plone.app.querystring.operation.selection.is',
|
|
49
|
+
v: value,
|
|
50
|
+
}
|
|
51
|
+
: undefined;
|
|
52
|
+
};
|
|
@@ -2,6 +2,11 @@ export SearchDetails from './SearchDetails';
|
|
|
2
2
|
export Facets from './Facets';
|
|
3
3
|
export SelectFacet from './SelectFacet';
|
|
4
4
|
export CheckboxFacet from './CheckboxFacet';
|
|
5
|
+
export DateRangeFacet from './DateRangeFacet';
|
|
5
6
|
export SearchInput from './SearchInput';
|
|
6
7
|
export FilterList from './FilterList';
|
|
7
8
|
export SortOn from './SortOn';
|
|
9
|
+
export ToggleFacet from './ToggleFacet';
|
|
10
|
+
export SelectFacetFilterListEntry from './SelectFacetFilterListEntry';
|
|
11
|
+
export ToggleFacetFilterListEntry from './ToggleFacetFilterListEntry';
|
|
12
|
+
export DateRangeFacetFilterListEntry from './DateRangeFacetFilterListEntry';
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { useSelector } from 'react-redux';
|
|
3
|
-
import { isEmpty } from 'lodash';
|
|
4
3
|
import qs from 'query-string';
|
|
5
4
|
import { useLocation, useHistory } from 'react-router-dom';
|
|
6
5
|
|
|
6
|
+
import { resolveExtension } from '@plone/volto/helpers/Extensions/withBlockExtensions';
|
|
7
|
+
import config from '@plone/volto/registry';
|
|
8
|
+
|
|
7
9
|
function getDisplayName(WrappedComponent) {
|
|
8
10
|
return WrappedComponent.displayName || WrappedComponent.name || 'Component';
|
|
9
11
|
}
|
|
@@ -25,16 +27,30 @@ const PAQO = 'plone.app.querystring.operation';
|
|
|
25
27
|
*
|
|
26
28
|
*/
|
|
27
29
|
function getInitialState(data, facets, urlSearchText, id) {
|
|
30
|
+
const {
|
|
31
|
+
types: facetWidgetTypes,
|
|
32
|
+
} = config.blocks.blocksConfig.search.extensions.facetWidgets;
|
|
33
|
+
const facetSettings = data?.facets || [];
|
|
34
|
+
|
|
28
35
|
return {
|
|
29
36
|
query: [
|
|
30
37
|
...(data.query?.query || []),
|
|
31
|
-
...
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
+
...(facetSettings || [])
|
|
39
|
+
.map((facet) => {
|
|
40
|
+
if (!facet?.field) return null;
|
|
41
|
+
|
|
42
|
+
const { valueToQuery } = resolveExtension(
|
|
43
|
+
'type',
|
|
44
|
+
facetWidgetTypes,
|
|
45
|
+
facet,
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
const name = facet.field.value;
|
|
49
|
+
const value = facets[name];
|
|
50
|
+
|
|
51
|
+
return valueToQuery({ value, facet });
|
|
52
|
+
})
|
|
53
|
+
.filter((f) => !!f),
|
|
38
54
|
...(urlSearchText
|
|
39
55
|
? [
|
|
40
56
|
{
|
|
@@ -54,27 +70,42 @@ function getInitialState(data, facets, urlSearchText, id) {
|
|
|
54
70
|
}
|
|
55
71
|
|
|
56
72
|
/**
|
|
57
|
-
* "Normalizes" the search state to something that's serializable
|
|
58
|
-
*
|
|
73
|
+
* "Normalizes" the search state to something that's serializable
|
|
74
|
+
* (for querying) and used to compute data for the ListingBody
|
|
59
75
|
*
|
|
60
76
|
* @function normalizeState
|
|
61
77
|
*
|
|
62
78
|
*/
|
|
63
|
-
function normalizeState({
|
|
79
|
+
function normalizeState({
|
|
80
|
+
query, // base query
|
|
81
|
+
facets, // facet values
|
|
82
|
+
id, // block id
|
|
83
|
+
searchText, // SearchableText
|
|
84
|
+
sortOn,
|
|
85
|
+
sortOrder,
|
|
86
|
+
facetSettings, // data.facets extracted from block data
|
|
87
|
+
}) {
|
|
88
|
+
const {
|
|
89
|
+
types: facetWidgetTypes,
|
|
90
|
+
} = config.blocks.blocksConfig.search.extensions.facetWidgets;
|
|
91
|
+
|
|
64
92
|
const params = {
|
|
65
93
|
query: [
|
|
66
94
|
...(query.query || []),
|
|
67
|
-
...
|
|
68
|
-
!
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
95
|
+
...(facetSettings || []).map((facet) => {
|
|
96
|
+
if (!facet?.field) return null;
|
|
97
|
+
|
|
98
|
+
const { valueToQuery } = resolveExtension(
|
|
99
|
+
'type',
|
|
100
|
+
facetWidgetTypes,
|
|
101
|
+
facet,
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
const name = facet.field.value;
|
|
105
|
+
const value = facets[name];
|
|
106
|
+
|
|
107
|
+
return valueToQuery({ value, facet });
|
|
108
|
+
}),
|
|
78
109
|
].filter((o) => !!o),
|
|
79
110
|
sort_on: sortOn || query.sort_on,
|
|
80
111
|
sort_order: sortOrder || query.sort_order,
|
|
@@ -217,7 +248,7 @@ const withSearch = (options) => (WrappedComponent) => {
|
|
|
217
248
|
const [facets, setFacets] = React.useState(
|
|
218
249
|
Object.assign(
|
|
219
250
|
{},
|
|
220
|
-
...urlQuery.map(({ i, v }) => ({ [i]: v })),
|
|
251
|
+
...urlQuery.map(({ i, v }) => ({ [i]: v })), // TODO: the 'o' should be kept. This would be a major refactoring of the facets
|
|
221
252
|
|
|
222
253
|
// support for simple filters like ?Subject=something
|
|
223
254
|
// TODO: since the move to hash params this is no longer working.
|
|
@@ -245,19 +276,21 @@ const withSearch = (options) => (WrappedComponent) => {
|
|
|
245
276
|
);
|
|
246
277
|
|
|
247
278
|
const timeoutRef = React.useRef();
|
|
279
|
+
const facetSettings = data?.facets;
|
|
248
280
|
|
|
249
281
|
const onTriggerSearch = React.useCallback(
|
|
250
|
-
(
|
|
282
|
+
(toSearchText, toSearchFacets, toSortOn, toSortOrder) => {
|
|
251
283
|
if (timeoutRef.current) clearTimeout(timeoutRef.current);
|
|
252
284
|
timeoutRef.current = setTimeout(
|
|
253
285
|
() => {
|
|
254
286
|
const searchData = normalizeState({
|
|
287
|
+
id,
|
|
255
288
|
query: data.query || {},
|
|
256
289
|
facets: toSearchFacets || facets,
|
|
257
|
-
|
|
258
|
-
searchText: toSearch,
|
|
290
|
+
searchText: toSearchText,
|
|
259
291
|
sortOn: toSortOn || sortOn,
|
|
260
292
|
sortOrder: toSortOrder || sortOrder,
|
|
293
|
+
facetSettings,
|
|
261
294
|
});
|
|
262
295
|
if (toSearchFacets) setFacets(toSearchFacets);
|
|
263
296
|
if (toSortOn) setSortOn(toSortOn);
|
|
@@ -268,7 +301,15 @@ const withSearch = (options) => (WrappedComponent) => {
|
|
|
268
301
|
toSearchFacets ? inputDelay / 3 : inputDelay,
|
|
269
302
|
);
|
|
270
303
|
},
|
|
271
|
-
[
|
|
304
|
+
[
|
|
305
|
+
data.query,
|
|
306
|
+
facets,
|
|
307
|
+
id,
|
|
308
|
+
setLocationSearchData,
|
|
309
|
+
sortOn,
|
|
310
|
+
sortOrder,
|
|
311
|
+
facetSettings,
|
|
312
|
+
],
|
|
272
313
|
);
|
|
273
314
|
|
|
274
315
|
const querystringResults = useSelector(
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import config from '@plone/volto/registry';
|
|
2
2
|
import { defineMessages } from 'react-intl';
|
|
3
3
|
import { cloneDeep } from 'lodash';
|
|
4
|
+
import { hasNonValueOperation, hasDateOperation } from './utils';
|
|
4
5
|
|
|
5
6
|
const messages = defineMessages({
|
|
6
7
|
searchBlock: {
|
|
@@ -99,9 +100,9 @@ const messages = defineMessages({
|
|
|
99
100
|
|
|
100
101
|
const enhanceSchema = (originalSchema, formData) => {
|
|
101
102
|
const extensionName = 'facetWidgets';
|
|
102
|
-
const extensionType = 'type';
|
|
103
|
+
const extensionType = 'type'; // property name in stored block data
|
|
103
104
|
const variations =
|
|
104
|
-
config.blocks.blocksConfig.search.extensions[extensionName]
|
|
105
|
+
config.blocks.blocksConfig.search.extensions[extensionName].types;
|
|
105
106
|
|
|
106
107
|
const activeItemName = formData?.[extensionType];
|
|
107
108
|
let activeItem = variations?.find((item) => item.id === activeItemName);
|
|
@@ -122,7 +123,7 @@ const FacetSchema = ({ intl }) => ({
|
|
|
122
123
|
{
|
|
123
124
|
id: 'default',
|
|
124
125
|
title: 'Default',
|
|
125
|
-
fields: ['title', 'field', 'type', '
|
|
126
|
+
fields: ['title', 'field', 'type', 'hidden'],
|
|
126
127
|
},
|
|
127
128
|
],
|
|
128
129
|
properties: {
|
|
@@ -141,7 +142,9 @@ const FacetSchema = ({ intl }) => ({
|
|
|
141
142
|
return Object.assign(
|
|
142
143
|
{},
|
|
143
144
|
...Object.keys(options).map((k) =>
|
|
144
|
-
Object.keys(options[k].values || {}).length
|
|
145
|
+
Object.keys(options[k].values || {}).length ||
|
|
146
|
+
hasNonValueOperation(options[k].operations) ||
|
|
147
|
+
hasDateOperation(options[k].operations)
|
|
145
148
|
? { [k]: options[k] }
|
|
146
149
|
: {},
|
|
147
150
|
),
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export const NONVALUE_OPERATIONS = new Set([
|
|
2
|
+
'plone.app.querystring.operation.boolean.isFalse',
|
|
3
|
+
'plone.app.querystring.operation.boolean.isTrue',
|
|
4
|
+
]);
|
|
5
|
+
|
|
6
|
+
export const DATE_OPERATIONS = new Set([
|
|
7
|
+
'plone.app.querystring.operation.date.between',
|
|
8
|
+
]);
|
|
9
|
+
|
|
10
|
+
export const hasNonValueOperation = (ops) => {
|
|
11
|
+
return ops.filter((x) => NONVALUE_OPERATIONS.has(x)).length > 0;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const hasDateOperation = (ops) => {
|
|
15
|
+
return ops.filter((x) => DATE_OPERATIONS.has(x)).length > 0;
|
|
16
|
+
};
|
|
@@ -5,19 +5,20 @@
|
|
|
5
5
|
|
|
6
6
|
import React, { Component } from 'react';
|
|
7
7
|
import PropTypes from 'prop-types';
|
|
8
|
-
import Editor from 'draft-js-plugins-editor';
|
|
9
|
-
import { convertFromRaw, EditorState, RichUtils } from 'draft-js';
|
|
10
|
-
import createInlineToolbarPlugin from 'draft-js-inline-toolbar-plugin';
|
|
11
|
-
import isSoftNewlineEvent from 'draft-js/lib/isSoftNewlineEvent';
|
|
12
8
|
import { includes } from 'lodash';
|
|
13
9
|
import config from '@plone/volto/registry';
|
|
14
10
|
|
|
11
|
+
import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
|
|
12
|
+
import loadable from '@loadable/component';
|
|
13
|
+
|
|
14
|
+
const Editor = loadable(() => import('draft-js-plugins-editor'));
|
|
15
|
+
|
|
15
16
|
/**
|
|
16
17
|
* Edit text cell class.
|
|
17
18
|
* @class Cell
|
|
18
19
|
* @extends Component
|
|
19
20
|
*/
|
|
20
|
-
class
|
|
21
|
+
class CellComponent extends Component {
|
|
21
22
|
/**
|
|
22
23
|
* Property types.
|
|
23
24
|
* @property {Object} propTypes Property types.
|
|
@@ -54,12 +55,16 @@ class Cell extends Component {
|
|
|
54
55
|
constructor(props) {
|
|
55
56
|
super(props);
|
|
56
57
|
|
|
58
|
+
const { EditorState, convertFromRaw } = props.draftJs;
|
|
59
|
+
const createInlineToolbarPlugin = props.draftJsInlineToolbarPlugin.default;
|
|
60
|
+
|
|
57
61
|
if (!__SERVER__) {
|
|
62
|
+
this.draftConfig = config.settings.richtextEditorSettings(props);
|
|
58
63
|
let editorState;
|
|
59
64
|
editorState = EditorState.createWithContent(convertFromRaw(props.value));
|
|
60
65
|
|
|
61
66
|
const inlineToolbarPlugin = createInlineToolbarPlugin({
|
|
62
|
-
structure:
|
|
67
|
+
structure: this.draftConfig.richTextEditorInlineToolbarButtons,
|
|
63
68
|
});
|
|
64
69
|
|
|
65
70
|
this.state = {
|
|
@@ -125,7 +130,8 @@ class Cell extends Component {
|
|
|
125
130
|
}
|
|
126
131
|
|
|
127
132
|
const { InlineToolbar } = this.state.inlineToolbarPlugin;
|
|
128
|
-
const
|
|
133
|
+
const isSoftNewlineEvent = this.props.draftJsLibIsSoftNewlineEvent.default;
|
|
134
|
+
const { RichUtils } = this.props.draftJs;
|
|
129
135
|
|
|
130
136
|
return (
|
|
131
137
|
<div>
|
|
@@ -135,11 +141,11 @@ class Cell extends Component {
|
|
|
135
141
|
editorState={this.state.editorState}
|
|
136
142
|
plugins={[
|
|
137
143
|
this.state.inlineToolbarPlugin,
|
|
138
|
-
...
|
|
144
|
+
...this.draftConfig.richTextEditorPlugins,
|
|
139
145
|
]}
|
|
140
|
-
blockRenderMap={
|
|
141
|
-
blockStyleFn={
|
|
142
|
-
customStyleMap={
|
|
146
|
+
blockRenderMap={this.draftConfig.extendedBlockRenderMap}
|
|
147
|
+
blockStyleFn={this.draftConfig.blockStyleFn}
|
|
148
|
+
customStyleMap={this.draftConfig.customStyleMap}
|
|
143
149
|
handleReturn={(e) => {
|
|
144
150
|
if (isSoftNewlineEvent(e)) {
|
|
145
151
|
this.onChange(
|
|
@@ -155,10 +161,10 @@ class Cell extends Component {
|
|
|
155
161
|
anchorKey,
|
|
156
162
|
);
|
|
157
163
|
const blockType = currentContentBlock.getType();
|
|
158
|
-
if (!includes(
|
|
164
|
+
if (!includes(this.draftConfig.listBlockTypes, blockType)) {
|
|
159
165
|
this.props.onSelectBlock(
|
|
160
166
|
this.props.onAddBlock(
|
|
161
|
-
|
|
167
|
+
this.draftConfig.defaultBlockType,
|
|
162
168
|
this.props.index + 1,
|
|
163
169
|
),
|
|
164
170
|
);
|
|
@@ -178,4 +184,24 @@ class Cell extends Component {
|
|
|
178
184
|
}
|
|
179
185
|
}
|
|
180
186
|
|
|
181
|
-
export
|
|
187
|
+
export const Cell = injectLazyLibs([
|
|
188
|
+
'draftJs',
|
|
189
|
+
'draftJsBlockBreakoutPlugin',
|
|
190
|
+
'draftJsCreateBlockStyleButton',
|
|
191
|
+
'draftJsCreateInlineStyleButton',
|
|
192
|
+
'draftJsFilters',
|
|
193
|
+
'draftJsImportHtml',
|
|
194
|
+
'draftJsInlineToolbarPlugin',
|
|
195
|
+
'draftJsLibIsSoftNewlineEvent',
|
|
196
|
+
'immutableLib',
|
|
197
|
+
])(CellComponent);
|
|
198
|
+
|
|
199
|
+
const Preloader = (props) => {
|
|
200
|
+
const [loaded, setLoaded] = React.useState(false);
|
|
201
|
+
React.useEffect(() => {
|
|
202
|
+
Editor.load().then(() => setLoaded(true));
|
|
203
|
+
}, []);
|
|
204
|
+
return loaded ? <Cell {...props} /> : null;
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
export default Preloader;
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import renderer from 'react-test-renderer';
|
|
3
|
-
import Cell from './Cell';
|
|
3
|
+
import { Cell } from './Cell';
|
|
4
4
|
|
|
5
5
|
global.__SERVER__ = true; // eslint-disable-line no-underscore-dangle
|
|
6
6
|
|
|
7
|
+
jest.mock('@plone/volto/helpers/Loadable/Loadable');
|
|
8
|
+
beforeAll(
|
|
9
|
+
async () =>
|
|
10
|
+
await require('@plone/volto/helpers/Loadable/Loadable').__setLoadables(),
|
|
11
|
+
);
|
|
12
|
+
|
|
7
13
|
test('renders a cell component', () => {
|
|
8
14
|
const component = renderer.create(
|
|
9
15
|
<Cell onChange={() => {}} onSelectCell={() => {}} />,
|
|
@@ -5,15 +5,16 @@
|
|
|
5
5
|
|
|
6
6
|
import React, { Component } from 'react';
|
|
7
7
|
import PropTypes from 'prop-types';
|
|
8
|
+
import { compose } from 'redux';
|
|
8
9
|
import { map, remove } from 'lodash';
|
|
9
10
|
import { Button, Segment, Table, Form } from 'semantic-ui-react';
|
|
10
|
-
import { convertToRaw } from 'draft-js';
|
|
11
11
|
import { Portal } from 'react-portal';
|
|
12
12
|
import cx from 'classnames';
|
|
13
13
|
import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
|
|
14
14
|
|
|
15
15
|
import Cell from '@plone/volto/components/manage/Blocks/Table/Cell';
|
|
16
16
|
import { Field, Icon } from '@plone/volto/components';
|
|
17
|
+
import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
|
|
17
18
|
|
|
18
19
|
import rowBeforeSVG from '@plone/volto/icons/row-before.svg';
|
|
19
20
|
import rowAfterSVG from '@plone/volto/icons/row-after.svg';
|
|
@@ -208,6 +209,9 @@ class Edit extends Component {
|
|
|
208
209
|
this.toggleBasic = this.toggleBasic.bind(this);
|
|
209
210
|
this.toggleCelled = this.toggleCelled.bind(this);
|
|
210
211
|
this.toggleStriped = this.toggleStriped.bind(this);
|
|
212
|
+
|
|
213
|
+
const { convertToRaw } = props.draftJs;
|
|
214
|
+
this.convertToRaw = convertToRaw;
|
|
211
215
|
}
|
|
212
216
|
|
|
213
217
|
/**
|
|
@@ -261,7 +265,7 @@ class Edit extends Component {
|
|
|
261
265
|
*/
|
|
262
266
|
onChangeCell(row, cell, editorState) {
|
|
263
267
|
const table = { ...this.props.data.table };
|
|
264
|
-
table.rows[row].cells[cell].value = convertToRaw(
|
|
268
|
+
table.rows[row].cells[cell].value = this.convertToRaw(
|
|
265
269
|
editorState.getCurrentContent(),
|
|
266
270
|
);
|
|
267
271
|
this.props.onChangeBlock(this.props.block, {
|
|
@@ -740,4 +744,4 @@ class Edit extends Component {
|
|
|
740
744
|
}
|
|
741
745
|
}
|
|
742
746
|
|
|
743
|
-
export default injectIntl(Edit);
|
|
747
|
+
export default compose(injectLazyLibs(['draftJs']), injectIntl)(Edit);
|
|
@@ -5,6 +5,12 @@ import { Provider } from 'react-intl-redux';
|
|
|
5
5
|
|
|
6
6
|
import Edit from './Edit';
|
|
7
7
|
|
|
8
|
+
jest.mock('@plone/volto/helpers/Loadable/Loadable');
|
|
9
|
+
beforeAll(
|
|
10
|
+
async () =>
|
|
11
|
+
await require('@plone/volto/helpers/Loadable/Loadable').__setLoadables(),
|
|
12
|
+
);
|
|
13
|
+
|
|
8
14
|
const mockStore = configureStore();
|
|
9
15
|
|
|
10
16
|
test('renders an edit table block component', () => {
|
|
@@ -37,8 +37,8 @@ const View = ({ data }) =>
|
|
|
37
37
|
{cell.value && cell.value.blocks && cell.value.blocks[0].text
|
|
38
38
|
? redraft(
|
|
39
39
|
cell.value,
|
|
40
|
-
config.settings.ToHTMLRenderers,
|
|
41
|
-
config.settings.ToHTMLOptions,
|
|
40
|
+
config.settings.richtextViewSettings.ToHTMLRenderers,
|
|
41
|
+
config.settings.richtextViewSettings.ToHTMLOptions,
|
|
42
42
|
)
|
|
43
43
|
: '\u00A0'}
|
|
44
44
|
</Table.Cell>
|