@plone/volto 17.0.0-alpha.14 → 17.0.0-alpha.16
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/.yarn/install-state.gz +0 -0
- package/CHANGELOG.md +25 -0
- package/cypress/support/commands.js +18 -0
- package/locales/ca/LC_MESSAGES/volto.po +41 -0
- package/locales/ca.json +1 -1
- package/locales/de/LC_MESSAGES/volto.po +41 -0
- package/locales/de.json +1 -1
- package/locales/en/LC_MESSAGES/volto.po +41 -0
- package/locales/en.json +1 -1
- package/locales/es/LC_MESSAGES/volto.po +41 -0
- package/locales/es.json +1 -1
- package/locales/eu/LC_MESSAGES/volto.po +41 -0
- package/locales/eu.json +1 -1
- package/locales/fi/LC_MESSAGES/volto.po +41 -0
- package/locales/fi.json +1 -1
- package/locales/fr/LC_MESSAGES/volto.po +41 -0
- package/locales/fr.json +1 -1
- package/locales/it/LC_MESSAGES/volto.po +41 -0
- package/locales/it.json +1 -1
- package/locales/ja/LC_MESSAGES/volto.po +41 -0
- package/locales/ja.json +1 -1
- package/locales/nl/LC_MESSAGES/volto.po +41 -0
- package/locales/nl.json +1 -1
- package/locales/pt/LC_MESSAGES/volto.po +41 -0
- package/locales/pt.json +1 -1
- package/locales/pt_BR/LC_MESSAGES/volto.po +41 -0
- package/locales/pt_BR.json +1 -1
- package/locales/ro/LC_MESSAGES/volto.po +41 -0
- package/locales/ro.json +1 -1
- package/locales/volto.pot +42 -1
- package/locales/zh_CN/LC_MESSAGES/volto.po +41 -0
- package/locales/zh_CN.json +1 -1
- package/package.json +1 -1
- package/packages/volto-slate/package.json +1 -1
- package/packages/volto-slate/src/actions/index.js +1 -1
- package/packages/volto-slate/src/blocks/Text/index.js +10 -2
- package/packages/volto-slate/src/editor/index.js +4 -4
- package/packages/volto-slate/src/editor/ui/SlateContextToolbar.jsx +2 -2
- package/packages/volto-slate/src/editor/ui/index.js +15 -15
- package/packages/volto-slate/src/index.js +2 -2
- package/src/components/manage/AnchorPlugin/index.jsx +2 -2
- package/src/components/manage/AnchorPlugin/utils/EditorUtils.js +3 -1
- package/src/components/manage/Blocks/Block/BlocksForm.jsx +19 -2
- package/src/components/manage/Blocks/Block/Edit.jsx +1 -1
- package/src/components/manage/Blocks/Block/Style.jsx +2 -2
- package/src/components/manage/Blocks/Container/Data.jsx +32 -0
- package/src/components/manage/Blocks/Container/Edit.jsx +174 -0
- package/src/components/manage/Blocks/Container/EditBlockWrapper.jsx +120 -0
- package/src/components/manage/Blocks/Container/NewBlockAddButton.jsx +84 -0
- package/src/components/manage/Blocks/Container/SimpleContainerToolbar.jsx +54 -0
- package/src/components/manage/Blocks/Grid/Edit.jsx +33 -0
- package/src/components/manage/Blocks/Grid/View.jsx +42 -0
- package/src/components/manage/Blocks/Grid/adapter.js +14 -0
- package/src/components/manage/Blocks/Grid/grid-1.svg +6 -0
- package/src/components/manage/Blocks/Grid/grid-2.svg +9 -0
- package/src/components/manage/Blocks/Grid/grid-3.svg +10 -0
- package/src/components/manage/Blocks/Grid/grid-4.svg +11 -0
- package/src/components/manage/Blocks/Grid/schema.js +35 -0
- package/src/components/manage/Blocks/Grid/templates.js +47 -0
- package/src/components/manage/Blocks/Image/ImageSidebar.jsx +2 -1
- package/src/components/manage/Blocks/Image/schema.js +11 -0
- package/src/components/manage/Blocks/Listing/DefaultTemplate.jsx +18 -3
- package/src/components/manage/Blocks/Listing/getAsyncData.js +3 -5
- package/src/components/manage/Blocks/Search/components/index.js +13 -13
- package/src/components/manage/Blocks/Search/hocs/index.js +2 -2
- package/src/components/manage/Blocks/Search/hocs/withQueryString.jsx +2 -2
- package/src/components/manage/Blocks/Teaser/schema.js +5 -0
- package/src/components/manage/Blocks/ToC/variations/index.js +3 -1
- package/src/components/manage/DragDropList/DragDropList.jsx +18 -13
- package/src/components/manage/TemplateChooser/TemplateChooser.jsx +38 -0
- package/src/components/manage/TemplateChooser/TemplateChooser.test.jsx +34 -0
- package/src/components/manage/TemplateChooser/template.svg +10 -0
- package/src/components/theme/Anontools/Anontools.stories.jsx +16 -6
- package/src/components/theme/Component/Component.jsx +1 -1
- package/src/components/theme/View/RenderBlocks.jsx +56 -27
- package/src/components/theme/View/RenderEmptyBlock.jsx +5 -0
- package/src/config/Blocks.jsx +44 -0
- package/src/config/RichTextEditor/Blocks.jsx +2 -2
- package/src/config/RichTextEditor/FromHTML.jsx +2 -2
- package/src/config/RichTextEditor/Styles.jsx +1 -1
- package/src/constants/Indexes.js +3 -1
- package/src/express-middleware/devproxy.js +1 -1
- package/src/express-middleware/files.js +3 -3
- package/src/express-middleware/images.js +4 -4
- package/src/express-middleware/robotstxt.js +1 -1
- package/src/express-middleware/sitemap.js +1 -1
- package/src/express-middleware/static.js +3 -3
- package/src/helpers/Blocks/Blocks.js +26 -0
- package/src/helpers/Blocks/Blocks.test.js +21 -0
- package/src/helpers/Extensions/index.js +2 -1
- package/src/helpers/Utils/UseDetectClickOutside.stories.jsx +191 -0
- package/src/helpers/Utils/Utils.js +25 -0
- package/src/helpers/index.js +11 -10
- package/src/icons/grid-block.svg +11 -0
- package/src/middleware/index.js +2 -2
- package/src/start-server.js +2 -2
- package/theme/themes/pastanaga/extras/blocks.less +3 -1
- package/theme/themes/pastanaga/extras/grid.less +426 -0
- package/theme/themes/pastanaga/extras/main.less +1 -0
|
@@ -2,10 +2,15 @@ import React from 'react';
|
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import { ConditionalLink, UniversalLink } from '@plone/volto/components';
|
|
4
4
|
import { flattenToAppURL } from '@plone/volto/helpers';
|
|
5
|
-
|
|
6
5
|
import { isInternalURL } from '@plone/volto/helpers/Url/Url';
|
|
7
6
|
|
|
8
|
-
const DefaultTemplate = ({
|
|
7
|
+
const DefaultTemplate = ({
|
|
8
|
+
headlineTag,
|
|
9
|
+
items,
|
|
10
|
+
linkTitle,
|
|
11
|
+
linkHref,
|
|
12
|
+
isEditMode,
|
|
13
|
+
}) => {
|
|
9
14
|
let link = null;
|
|
10
15
|
let href = linkHref?.[0]?.['@id'] || '';
|
|
11
16
|
|
|
@@ -19,6 +24,16 @@ const DefaultTemplate = ({ items, linkTitle, linkHref, isEditMode }) => {
|
|
|
19
24
|
link = <UniversalLink href={href}>{linkTitle || href}</UniversalLink>;
|
|
20
25
|
}
|
|
21
26
|
|
|
27
|
+
const getTitleTag = (tag) => {
|
|
28
|
+
const level = tag.slice(-1);
|
|
29
|
+
if (/\d/.test(level)) {
|
|
30
|
+
return `h${Number(level) + 1}`;
|
|
31
|
+
} else {
|
|
32
|
+
return 'h3';
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
const TitleTag = headlineTag ? getTitleTag(headlineTag) : 'h3';
|
|
36
|
+
|
|
22
37
|
return (
|
|
23
38
|
<>
|
|
24
39
|
<div className="items">
|
|
@@ -26,7 +41,7 @@ const DefaultTemplate = ({ items, linkTitle, linkHref, isEditMode }) => {
|
|
|
26
41
|
<div className="listing-item" key={item['@id']}>
|
|
27
42
|
<ConditionalLink item={item} condition={!isEditMode}>
|
|
28
43
|
<div className="listing-body">
|
|
29
|
-
<
|
|
44
|
+
<TitleTag>{item.title ? item.title : item.id}</TitleTag>
|
|
30
45
|
<p>{item.description}</p>
|
|
31
46
|
</div>
|
|
32
47
|
</ConditionalLink>
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { getQueryStringResults } from '@plone/volto/actions';
|
|
2
2
|
import { resolveBlockExtensions } from '@plone/volto/helpers';
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
export default function getListingBlockAsyncData({
|
|
5
5
|
dispatch,
|
|
6
6
|
id,
|
|
7
7
|
data,
|
|
8
8
|
path,
|
|
9
9
|
blocksConfig,
|
|
10
|
-
})
|
|
10
|
+
}) {
|
|
11
11
|
const { resolvedExtensions } = resolveBlockExtensions(data, blocksConfig);
|
|
12
12
|
|
|
13
13
|
return [
|
|
@@ -24,6 +24,4 @@ const getListingBlockAsyncData = ({
|
|
|
24
24
|
),
|
|
25
25
|
),
|
|
26
26
|
];
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export default getListingBlockAsyncData;
|
|
27
|
+
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
export SearchDetails from './SearchDetails';
|
|
2
|
-
export Facets from './Facets';
|
|
3
|
-
export SelectFacet from './SelectFacet';
|
|
4
|
-
export CheckboxFacet from './CheckboxFacet';
|
|
5
|
-
export DateRangeFacet from './DateRangeFacet';
|
|
6
|
-
export SearchInput from './SearchInput';
|
|
7
|
-
export FilterList from './FilterList';
|
|
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';
|
|
13
|
-
export ViewSwitcher from './ViewSwitcher';
|
|
1
|
+
export { default as SearchDetails } from './SearchDetails';
|
|
2
|
+
export { default as Facets } from './Facets';
|
|
3
|
+
export { default as SelectFacet } from './SelectFacet';
|
|
4
|
+
export { default as CheckboxFacet } from './CheckboxFacet';
|
|
5
|
+
export { default as DateRangeFacet } from './DateRangeFacet';
|
|
6
|
+
export { default as SearchInput } from './SearchInput';
|
|
7
|
+
export { default as FilterList } from './FilterList';
|
|
8
|
+
export { default as SortOn } from './SortOn';
|
|
9
|
+
export { default as ToggleFacet } from './ToggleFacet';
|
|
10
|
+
export { default as SelectFacetFilterListEntry } from './SelectFacetFilterListEntry';
|
|
11
|
+
export { default as ToggleFacetFilterListEntry } from './ToggleFacetFilterListEntry';
|
|
12
|
+
export { default as DateRangeFacetFilterListEntry } from './DateRangeFacetFilterListEntry';
|
|
13
|
+
export { default as ViewSwitcher } from './ViewSwitcher';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export withQueryString from './withQueryString';
|
|
2
|
-
export withSearch from './withSearch';
|
|
1
|
+
export { default as withQueryString } from './withQueryString';
|
|
2
|
+
export { default as withSearch } from './withSearch';
|
|
@@ -10,7 +10,7 @@ function getDisplayName(WrappedComponent) {
|
|
|
10
10
|
* A HOC that injects querystring metadata information from the backend.
|
|
11
11
|
*
|
|
12
12
|
*/
|
|
13
|
-
export default (WrappedComponent)
|
|
13
|
+
export default function withQueryString(WrappedComponent) {
|
|
14
14
|
function WithQueryString(props) {
|
|
15
15
|
const dispatch = useDispatch();
|
|
16
16
|
|
|
@@ -29,4 +29,4 @@ export default (WrappedComponent) => {
|
|
|
29
29
|
WrappedComponent,
|
|
30
30
|
)})`;
|
|
31
31
|
return WithQueryString;
|
|
32
|
-
}
|
|
32
|
+
}
|
|
@@ -101,3 +101,8 @@ export const TeaserSchema = ({ intl }) => {
|
|
|
101
101
|
|
|
102
102
|
return schema;
|
|
103
103
|
};
|
|
104
|
+
|
|
105
|
+
export const gridTeaserDisableStylingSchema = ({ schema, formData, intl }) => {
|
|
106
|
+
schema.fieldsets = schema.fieldsets.filter((item) => item.id !== 'styling');
|
|
107
|
+
return schema;
|
|
108
|
+
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import DefaultTocRenderer from './DefaultTocRenderer';
|
|
2
2
|
import HorizontalMenu from './HorizontalMenu';
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
const ToCVariations = [
|
|
5
5
|
{
|
|
6
6
|
id: 'default',
|
|
7
7
|
title: 'Listing (default)',
|
|
@@ -14,3 +14,5 @@ export default [
|
|
|
14
14
|
view: HorizontalMenu,
|
|
15
15
|
},
|
|
16
16
|
];
|
|
17
|
+
|
|
18
|
+
export default ToCVariations;
|
|
@@ -53,6 +53,7 @@ const DragDropList = (props) => {
|
|
|
53
53
|
const {
|
|
54
54
|
childList,
|
|
55
55
|
children,
|
|
56
|
+
direction = 'vertical',
|
|
56
57
|
onMoveItem,
|
|
57
58
|
as = 'div',
|
|
58
59
|
style,
|
|
@@ -128,6 +129,7 @@ const DragDropList = (props) => {
|
|
|
128
129
|
>
|
|
129
130
|
<Droppable
|
|
130
131
|
droppableId={uid}
|
|
132
|
+
direction={direction}
|
|
131
133
|
renderClone={(provided, snapshot, rubric) => {
|
|
132
134
|
const index = rubric.source.index;
|
|
133
135
|
return children({
|
|
@@ -160,19 +162,22 @@ const DragDropList = (props) => {
|
|
|
160
162
|
</Draggable>
|
|
161
163
|
))}
|
|
162
164
|
{provided.placeholder}
|
|
163
|
-
{
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
165
|
+
{/* TODO: Fix the ghost problem if horizontal dnd is present */}
|
|
166
|
+
{direction !== 'horizontal' &&
|
|
167
|
+
!isEmpty(placeholderProps) &&
|
|
168
|
+
snapshot.isDraggingOver && (
|
|
169
|
+
<div
|
|
170
|
+
style={{
|
|
171
|
+
position: 'absolute',
|
|
172
|
+
top: placeholderProps.clientY,
|
|
173
|
+
left: placeholderProps.clientX,
|
|
174
|
+
height: placeholderProps.clientHeight,
|
|
175
|
+
background: '#eee',
|
|
176
|
+
width: placeholderProps.clientWidth,
|
|
177
|
+
borderRadius: '3px',
|
|
178
|
+
}}
|
|
179
|
+
/>
|
|
180
|
+
)}
|
|
176
181
|
</AsDomComponent>
|
|
177
182
|
)}
|
|
178
183
|
</Droppable>
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import PropTypes from 'prop-types';
|
|
2
|
+
import { useIntl } from 'react-intl';
|
|
3
|
+
import { Button, Grid, Message } from 'semantic-ui-react';
|
|
4
|
+
|
|
5
|
+
const TemplateChooser = ({ templates, onSelectTemplate }) => {
|
|
6
|
+
const intl = useIntl();
|
|
7
|
+
return (
|
|
8
|
+
<div className="template-chooser">
|
|
9
|
+
<Message>
|
|
10
|
+
<Grid columns={templates(intl).length}>
|
|
11
|
+
{templates(intl).map((template, index) => (
|
|
12
|
+
<Grid.Column key={template.id}>
|
|
13
|
+
<Button
|
|
14
|
+
className="template-chooser-item"
|
|
15
|
+
onClick={() => onSelectTemplate(index)}
|
|
16
|
+
>
|
|
17
|
+
<img src={template.image} alt="" />
|
|
18
|
+
<div className="template-chooser-title">
|
|
19
|
+
{intl.formatMessage({
|
|
20
|
+
id: template.id,
|
|
21
|
+
defaultMessage: template.title,
|
|
22
|
+
})}
|
|
23
|
+
</div>
|
|
24
|
+
</Button>
|
|
25
|
+
</Grid.Column>
|
|
26
|
+
))}
|
|
27
|
+
</Grid>
|
|
28
|
+
</Message>
|
|
29
|
+
</div>
|
|
30
|
+
);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
TemplateChooser.propTypes = {
|
|
34
|
+
templates: PropTypes.func.isRequired,
|
|
35
|
+
onSelectTemplate: PropTypes.func.isRequired,
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export default TemplateChooser;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import renderer from 'react-test-renderer';
|
|
3
|
+
import configureStore from 'redux-mock-store';
|
|
4
|
+
import { Provider } from 'react-intl-redux';
|
|
5
|
+
import TemplateChooser from './TemplateChooser';
|
|
6
|
+
import templateSVG from './template.svg';
|
|
7
|
+
|
|
8
|
+
const mockStore = configureStore();
|
|
9
|
+
|
|
10
|
+
test('renders a TemplateChooser component', () => {
|
|
11
|
+
const store = mockStore({
|
|
12
|
+
intl: {
|
|
13
|
+
locale: 'en',
|
|
14
|
+
messages: { templateid: 'Template default translation' },
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
const component = renderer.create(
|
|
19
|
+
<Provider store={store}>
|
|
20
|
+
<TemplateChooser
|
|
21
|
+
templates={() => [
|
|
22
|
+
{
|
|
23
|
+
image: templateSVG,
|
|
24
|
+
id: 'templateid',
|
|
25
|
+
defaultMessage: 'Template default translation',
|
|
26
|
+
},
|
|
27
|
+
]}
|
|
28
|
+
onSelectTemplate={() => {}}
|
|
29
|
+
/>
|
|
30
|
+
</Provider>,
|
|
31
|
+
);
|
|
32
|
+
const json = component.toJSON();
|
|
33
|
+
expect(json).toMatchSnapshot();
|
|
34
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="96" height="96" viewBox="0 0 96 96">
|
|
2
|
+
<g fill="none" fill-rule="evenodd">
|
|
3
|
+
<rect width="96" height="96" fill="#9FD1E5" rx="3"/>
|
|
4
|
+
<g fill="#FFF" opacity=".9" transform="translate(9 21)">
|
|
5
|
+
<rect width="78" height="29"/>
|
|
6
|
+
<rect width="36" height="8" y="33"/>
|
|
7
|
+
<rect width="77" height="10" y="45"/>
|
|
8
|
+
</g>
|
|
9
|
+
</g>
|
|
10
|
+
</svg>
|
|
@@ -1,15 +1,25 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import
|
|
2
|
+
import AnontoolsDefault from './Anontools';
|
|
3
3
|
import Wrapper from '@plone/volto/storybook';
|
|
4
4
|
|
|
5
5
|
const AnontoolsComponent = ({ children, ...args }) => {
|
|
6
6
|
return (
|
|
7
|
-
<Wrapper
|
|
7
|
+
<Wrapper
|
|
8
|
+
anonymous
|
|
9
|
+
location={{ pathname: '/folder2/folder21/doc212' }}
|
|
10
|
+
customStore={{
|
|
11
|
+
content: {
|
|
12
|
+
data: { '@id': 'http://myreturnURL' },
|
|
13
|
+
get: {
|
|
14
|
+
loaded: false,
|
|
15
|
+
loading: false,
|
|
16
|
+
error: null,
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
}}
|
|
20
|
+
>
|
|
8
21
|
<div className="ui segment form attached" style={{ width: '400px' }}>
|
|
9
|
-
<AnontoolsDefault
|
|
10
|
-
userSession={{ token: null }}
|
|
11
|
-
content={{ '@id': 'myid' }}
|
|
12
|
-
/>
|
|
22
|
+
<AnontoolsDefault />
|
|
13
23
|
</div>
|
|
14
24
|
</Wrapper>
|
|
15
25
|
);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import registry from '@plone/volto/registry';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* A component that can
|
|
4
|
+
* A component that can automatically look up its implementation from the
|
|
5
5
|
* registry based on the provided component `componentName`
|
|
6
6
|
*/
|
|
7
7
|
const Component = ({ componentName, dependencies, ...rest }) => {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { getBaseUrl, applyBlockDefaults } from '@plone/volto/helpers';
|
|
3
|
-
import { defineMessages,
|
|
3
|
+
import { defineMessages, useIntl } from 'react-intl';
|
|
4
4
|
import { map } from 'lodash';
|
|
5
|
+
import { MaybeWrap } from '@plone/volto/components';
|
|
5
6
|
import {
|
|
6
7
|
getBlocksFieldname,
|
|
7
8
|
getBlocksLayoutFieldname,
|
|
@@ -10,6 +11,7 @@ import {
|
|
|
10
11
|
import StyleWrapper from '@plone/volto/components/manage/Blocks/Block/StyleWrapper';
|
|
11
12
|
import config from '@plone/volto/registry';
|
|
12
13
|
import { ViewDefaultBlock } from '@plone/volto/components';
|
|
14
|
+
import RenderEmptyBlock from './RenderEmptyBlock';
|
|
13
15
|
|
|
14
16
|
const messages = defineMessages({
|
|
15
17
|
unknownBlock: {
|
|
@@ -23,7 +25,8 @@ const messages = defineMessages({
|
|
|
23
25
|
});
|
|
24
26
|
|
|
25
27
|
const RenderBlocks = (props) => {
|
|
26
|
-
const { content,
|
|
28
|
+
const { content, location, metadata, blockWrapperTag } = props;
|
|
29
|
+
const intl = useIntl();
|
|
27
30
|
const blocksFieldname = getBlocksFieldname(content);
|
|
28
31
|
const blocksLayoutFieldname = getBlocksLayoutFieldname(content);
|
|
29
32
|
const blocksConfig = props.blocksConfig || config.blocks.blocksConfig;
|
|
@@ -43,30 +46,56 @@ const RenderBlocks = (props) => {
|
|
|
43
46
|
properties: content,
|
|
44
47
|
});
|
|
45
48
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
49
|
+
if (content[blocksFieldname]?.[block]?.['@type'] === 'empty') {
|
|
50
|
+
return (
|
|
51
|
+
<MaybeWrap
|
|
52
|
+
key={block}
|
|
53
|
+
condition={blockWrapperTag}
|
|
54
|
+
as={blockWrapperTag}
|
|
55
|
+
>
|
|
56
|
+
<RenderEmptyBlock />
|
|
57
|
+
</MaybeWrap>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (Block) {
|
|
62
|
+
return (
|
|
63
|
+
<MaybeWrap
|
|
64
|
+
key={block}
|
|
65
|
+
condition={blockWrapperTag}
|
|
66
|
+
as={blockWrapperTag}
|
|
67
|
+
>
|
|
68
|
+
<StyleWrapper
|
|
69
|
+
key={block}
|
|
70
|
+
{...props}
|
|
71
|
+
id={block}
|
|
72
|
+
block={block}
|
|
73
|
+
data={blockData}
|
|
74
|
+
>
|
|
75
|
+
<Block
|
|
76
|
+
id={block}
|
|
77
|
+
metadata={metadata}
|
|
78
|
+
properties={content}
|
|
79
|
+
data={blockData}
|
|
80
|
+
path={getBaseUrl(location?.pathname || '')}
|
|
81
|
+
blocksConfig={blocksConfig}
|
|
82
|
+
/>
|
|
83
|
+
</StyleWrapper>
|
|
84
|
+
</MaybeWrap>
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (blockData) {
|
|
89
|
+
return (
|
|
90
|
+
<div key={block}>
|
|
91
|
+
{intl.formatMessage(messages.unknownBlock, {
|
|
92
|
+
block: content[blocksFieldname]?.[block]?.['@type'],
|
|
93
|
+
})}
|
|
94
|
+
</div>
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return (
|
|
70
99
|
<div key={block}>{intl.formatMessage(messages.invalidBlock)}</div>
|
|
71
100
|
);
|
|
72
101
|
})}
|
|
@@ -76,4 +105,4 @@ const RenderBlocks = (props) => {
|
|
|
76
105
|
);
|
|
77
106
|
};
|
|
78
107
|
|
|
79
|
-
export default
|
|
108
|
+
export default RenderBlocks;
|
package/src/config/Blocks.jsx
CHANGED
|
@@ -42,6 +42,7 @@ import tableSVG from '@plone/volto/icons/table.svg';
|
|
|
42
42
|
import listingBlockSVG from '@plone/volto/icons/content-listing.svg';
|
|
43
43
|
import tocSVG from '@plone/volto/icons/list-bullet.svg';
|
|
44
44
|
import searchSVG from '@plone/volto/icons/zoom.svg';
|
|
45
|
+
import gridSVG from '@plone/volto/icons/grid-block.svg';
|
|
45
46
|
import imagesSVG from '@plone/volto/icons/images.svg';
|
|
46
47
|
|
|
47
48
|
import ImageGalleryListingBlockTemplate from '@plone/volto/components/manage/Blocks/Listing/ImageGallery';
|
|
@@ -50,6 +51,14 @@ import TextSettingsSchema from '@plone/volto/components/manage/Blocks/Text/Schem
|
|
|
50
51
|
import ImageSettingsSchema from '@plone/volto/components/manage/Blocks/Image/LayoutSchema';
|
|
51
52
|
import ToCSettingsSchema from '@plone/volto/components/manage/Blocks/ToC/Schema';
|
|
52
53
|
|
|
54
|
+
import GridBlockView from '@plone/volto/components/manage/Blocks/Grid/View';
|
|
55
|
+
import GridBlockEdit from '@plone/volto/components/manage/Blocks/Grid/Edit';
|
|
56
|
+
import { GridBlockDataAdapter } from '@plone/volto/components/manage/Blocks/Grid/adapter';
|
|
57
|
+
import { GridBlockSchema } from '@plone/volto/components/manage/Blocks/Grid/schema';
|
|
58
|
+
import GridTemplates from '@plone/volto/components/manage/Blocks/Grid/templates';
|
|
59
|
+
import { gridTeaserDisableStylingSchema } from '@plone/volto/components/manage/Blocks/Teaser/schema';
|
|
60
|
+
import { gridImageDisableSizeAndPositionHandlersSchema } from '@plone/volto/components/manage/Blocks/Image/schema';
|
|
61
|
+
|
|
53
62
|
import SearchBlockView from '@plone/volto/components/manage/Blocks/Search/SearchBlockView';
|
|
54
63
|
import SearchBlockEdit from '@plone/volto/components/manage/Blocks/Search/SearchBlockEdit';
|
|
55
64
|
|
|
@@ -458,6 +467,27 @@ const blocksConfig = {
|
|
|
458
467
|
},
|
|
459
468
|
},
|
|
460
469
|
},
|
|
470
|
+
// This next block is not named just grid for some reasons:
|
|
471
|
+
// 1.- Naming it grid will collide with the SemanticUI CSS of the Grid component
|
|
472
|
+
// 2.- It would prevent the transition from the old grid
|
|
473
|
+
// (based on @kitconcept/volto-blocks-grid) without having to perform any migration.
|
|
474
|
+
// This way, both can co-exist at the same time.
|
|
475
|
+
gridBlock: {
|
|
476
|
+
id: 'gridBlock',
|
|
477
|
+
title: 'Grid',
|
|
478
|
+
icon: gridSVG,
|
|
479
|
+
group: 'common',
|
|
480
|
+
view: GridBlockView,
|
|
481
|
+
edit: GridBlockEdit,
|
|
482
|
+
blockSchema: GridBlockSchema,
|
|
483
|
+
dataAdapter: GridBlockDataAdapter,
|
|
484
|
+
restricted: false,
|
|
485
|
+
mostUsed: true,
|
|
486
|
+
sidebarTab: 1,
|
|
487
|
+
templates: GridTemplates,
|
|
488
|
+
maxLength: 4,
|
|
489
|
+
allowedBlocks: ['image', 'listing', 'slate', 'teaser'],
|
|
490
|
+
},
|
|
461
491
|
teaser: {
|
|
462
492
|
id: 'teaser',
|
|
463
493
|
title: 'Teaser',
|
|
@@ -481,6 +511,20 @@ const blocksConfig = {
|
|
|
481
511
|
},
|
|
482
512
|
};
|
|
483
513
|
|
|
514
|
+
// This is required in order to initialize the inner blocksConfig
|
|
515
|
+
// for the grid block, since we need to modify how the inner teaser
|
|
516
|
+
// block behave in it (= no schemaEnhancer fields for teasers inside a grid)
|
|
517
|
+
// Afterwards, it can be further customized in add-ons using the same technique.
|
|
518
|
+
blocksConfig.gridBlock.blocksConfig = { ...blocksConfig };
|
|
519
|
+
blocksConfig.gridBlock.blocksConfig.teaser = {
|
|
520
|
+
...blocksConfig.teaser,
|
|
521
|
+
schemaEnhancer: gridTeaserDisableStylingSchema,
|
|
522
|
+
};
|
|
523
|
+
blocksConfig.gridBlock.blocksConfig.image = {
|
|
524
|
+
...blocksConfig.image,
|
|
525
|
+
schemaEnhancer: gridImageDisableSizeAndPositionHandlersSchema,
|
|
526
|
+
};
|
|
527
|
+
|
|
484
528
|
const requiredBlocks = ['title'];
|
|
485
529
|
|
|
486
530
|
const initialBlocks = {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export default (props)
|
|
1
|
+
export default function Blocks(props) {
|
|
2
2
|
const { draftJs, immutableLib } = props;
|
|
3
3
|
const { DefaultDraftBlockRenderMap } = draftJs;
|
|
4
4
|
const { Map } = immutableLib;
|
|
@@ -27,4 +27,4 @@ export default (props) => {
|
|
|
27
27
|
const listBlockTypes = ['unordered-list-item', 'ordered-list-item'];
|
|
28
28
|
|
|
29
29
|
return { extendedBlockRenderMap, blockStyleFn, listBlockTypes };
|
|
30
|
-
}
|
|
30
|
+
}
|
|
@@ -13,7 +13,7 @@ import orderedListSVG from '@plone/volto/icons/list-numbered.svg';
|
|
|
13
13
|
import blockquoteSVG from '@plone/volto/icons/quote.svg';
|
|
14
14
|
import calloutSVG from '@plone/volto/icons/megaphone.svg';
|
|
15
15
|
|
|
16
|
-
export default function (props) {
|
|
16
|
+
export default function Styles(props) {
|
|
17
17
|
const createInlineStyleButton = props.draftJsCreateInlineStyleButton.default;
|
|
18
18
|
const createBlockStyleButton = props.draftJsCreateBlockStyleButton.default;
|
|
19
19
|
|
package/src/constants/Indexes.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* @module constants/indexes
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
const Indexes = {
|
|
7
7
|
sortable_title: { label: 'Title', type: 'string', sort_on: 'sortable_title' },
|
|
8
8
|
review_state: { label: 'Review state', type: 'string' },
|
|
9
9
|
ModificationDate: {
|
|
@@ -35,6 +35,8 @@ export default {
|
|
|
35
35
|
Type: { label: 'Type', type: 'string' },
|
|
36
36
|
};
|
|
37
37
|
|
|
38
|
+
export default Indexes;
|
|
39
|
+
|
|
38
40
|
export const defaultIndexes = [
|
|
39
41
|
'review_state',
|
|
40
42
|
'ModificationDate',
|
|
@@ -9,7 +9,7 @@ const HEADERS = [
|
|
|
9
9
|
'Content-Type',
|
|
10
10
|
];
|
|
11
11
|
|
|
12
|
-
function
|
|
12
|
+
function filesMiddlewareFn(req, res, next) {
|
|
13
13
|
getAPIResourceWithAuth(req)
|
|
14
14
|
.then((resource) => {
|
|
15
15
|
// Just forward the headers that we need
|
|
@@ -24,10 +24,10 @@ function fileMiddleware(req, res, next) {
|
|
|
24
24
|
.catch(next);
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
export default function () {
|
|
27
|
+
export default function filesMiddleware() {
|
|
28
28
|
const middleware = express.Router();
|
|
29
29
|
|
|
30
|
-
middleware.all(['**/@@download/*', '**/@@display-file/*'],
|
|
30
|
+
middleware.all(['**/@@download/*', '**/@@display-file/*'], filesMiddlewareFn);
|
|
31
31
|
middleware.id = 'filesResourcesProcessor';
|
|
32
32
|
return middleware;
|
|
33
33
|
}
|
|
@@ -3,7 +3,7 @@ import { getAPIResourceWithAuth } from '@plone/volto/helpers';
|
|
|
3
3
|
|
|
4
4
|
const HEADERS = ['content-type', 'content-disposition', 'cache-control'];
|
|
5
5
|
|
|
6
|
-
function
|
|
6
|
+
function imageMiddlewareFn(req, res, next) {
|
|
7
7
|
getAPIResourceWithAuth(req)
|
|
8
8
|
.then((resource) => {
|
|
9
9
|
// Just forward the headers that we need
|
|
@@ -17,11 +17,11 @@ function imageMiddleware(req, res, next) {
|
|
|
17
17
|
.catch(next);
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
export default function () {
|
|
20
|
+
export default function imagesMiddleware() {
|
|
21
21
|
const middleware = express.Router();
|
|
22
22
|
|
|
23
|
-
middleware.all(['**/@@images/*'],
|
|
24
|
-
middleware.all(['/@portrait/*'],
|
|
23
|
+
middleware.all(['**/@@images/*'], imageMiddlewareFn);
|
|
24
|
+
middleware.all(['/@portrait/*'], imageMiddlewareFn);
|
|
25
25
|
middleware.id = 'imageResourcesProcessor';
|
|
26
26
|
return middleware;
|
|
27
27
|
}
|
|
@@ -22,7 +22,7 @@ const envRobots = function (req, res, next) {
|
|
|
22
22
|
res.send(process.env.VOLTO_ROBOTSTXT);
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
-
export default function () {
|
|
25
|
+
export default function robotstxtMiddleware() {
|
|
26
26
|
const middleware = express.Router();
|
|
27
27
|
if (process.env.VOLTO_ROBOTSTXT) {
|
|
28
28
|
middleware.all('**/robots.txt', envRobots);
|