@kitconcept/volto-light-theme 8.0.0-alpha.2 → 8.0.0-alpha.20
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.draft +3 -4
- package/CHANGELOG.md +226 -0
- package/locales/de/LC_MESSAGES/volto.po +30 -115
- package/locales/en/LC_MESSAGES/volto.po +30 -115
- package/locales/es/LC_MESSAGES/volto.po +31 -116
- package/locales/eu/LC_MESSAGES/volto.po +58 -124
- package/locales/pt_BR/LC_MESSAGES/volto.po +38 -123
- package/locales/volto.pot +31 -116
- package/package.json +18 -15
- package/src/__mocks__/semantic-ui-react.ts +31 -0
- package/src/components/Blocks/Block/Edit.jsx +14 -6
- package/src/components/Blocks/Block/EditBlockWrapper.jsx +9 -3
- package/src/components/Blocks/Block/ErrorBoundary.test.tsx +55 -0
- package/src/components/Blocks/Block/ErrorBoundary.tsx +92 -0
- package/src/components/Blocks/Block/ErrorBoundaryMessage.tsx +66 -0
- package/src/components/Blocks/EventCalendar/Search/components/EventTemplate.tsx +1 -1
- package/src/components/Blocks/Image/Edit.jsx +1 -0
- package/src/components/Blocks/Listing/DefaultTemplate.jsx +12 -6
- package/src/components/Blocks/Listing/GridTemplate.jsx +16 -7
- package/src/components/Blocks/Listing/ListingBody.jsx +4 -1
- package/src/components/Blocks/Listing/SummaryTemplate.jsx +16 -7
- package/src/components/Blocks/Teaser/DefaultBody.tsx +25 -5
- package/src/components/Blocks/schema.ts +69 -0
- package/src/components/Breadcrumbs/Breadcrumbs.test.tsx +128 -0
- package/src/components/Breadcrumbs/Breadcrumbs.tsx +117 -0
- package/src/components/Caption/Caption.test.tsx +31 -0
- package/src/components/Caption/{Caption.jsx → Caption.tsx} +14 -21
- package/src/components/Footer/ColumnLinks.tsx +2 -2
- package/src/components/Footer/slots/Colophon.tsx +13 -1
- package/src/components/Footer/slots/CoreFooter.tsx +4 -2
- package/src/components/Header/Header.tsx +3 -3
- package/src/components/LanguageSelector/LanguageSelector.tsx +91 -0
- package/src/components/MobileNavigation/MobileNavigation.jsx +11 -9
- package/src/components/Navigation/Navigation.test.tsx +176 -0
- package/src/components/Navigation/{Navigation.jsx → Navigation.tsx} +77 -37
- package/src/components/StickyMenu/MobileCarouselArrowButton.tsx +81 -0
- package/src/components/StickyMenu/MobileStickyMenu.tsx +76 -0
- package/src/components/Summary/DefaultSummary.tsx +10 -3
- package/src/components/Summary/EventSummary.tsx +10 -3
- package/src/components/Summary/FileSummary.tsx +10 -3
- package/src/components/Summary/NewsItemSummary.tsx +10 -3
- package/src/components/Summary/PersonSummary.tsx +10 -3
- package/src/components/Summary/Summary.stories.tsx +46 -30
- package/src/components/Tags/Tags.test.tsx +71 -0
- package/src/components/Tags/{Tags.jsx → Tags.tsx} +9 -25
- package/src/components/Theme/EventView.jsx +4 -4
- package/src/components/Theme/NewsItemView.jsx +4 -4
- package/src/components/Theme/RenderBlocks.jsx +45 -37
- package/src/components/Theme/RenderBlocksV2.jsx +51 -20
- package/src/components/Widgets/ColorSwatch.stories.tsx +197 -0
- package/src/components/Widgets/ColorSwatch.test.tsx +188 -0
- package/src/components/Widgets/ColorSwatch.tsx +77 -39
- package/src/components/Widgets/SoftTextWidget.tsx +129 -0
- package/src/components/Widgets/SoftTextareaWidget.tsx +118 -0
- package/src/components/Widgets/ThemeColorSwatch.tsx +5 -9
- package/src/config/blocks.tsx +21 -29
- package/src/config/slots.ts +7 -0
- package/src/config/widgets.ts +5 -9
- package/src/customizations/volto/components/manage/DragDropList/DragDropList.jsx +263 -0
- package/src/customizations/volto/components/theme/LanguageSelector/LanguageSelector.tsx +10 -0
- package/src/helpers/styleDefinitions.test.tsx +30 -0
- package/src/helpers/styleDefinitions.ts +49 -0
- package/src/icons/block_icn_accordion.svg +0 -0
- package/src/icons/block_icn_grid.svg +0 -0
- package/src/internalChecks.test.ts +94 -0
- package/src/primitives/Card/Card.stories.tsx +4 -1
- package/src/primitives/Card/Card.test.tsx +11 -33
- package/src/primitives/Card/Card.tsx +33 -43
- package/src/primitives/IconLinkList.tsx +53 -52
- package/src/theme/_bgcolor-blocks-layout.scss +43 -45
- package/src/theme/_content.scss +12 -13
- package/src/theme/_export_import.scss +94 -0
- package/src/theme/_footer.scss +64 -19
- package/src/theme/_header.scss +21 -4
- package/src/theme/_insets.scss +1 -1
- package/src/theme/_layout.scss +34 -15
- package/src/theme/_mobile-sticky-menu.scss +92 -0
- package/src/theme/_search-page.scss +249 -0
- package/src/theme/_typo-custom.scss +16 -5
- package/src/theme/_variables.scss +19 -4
- package/src/theme/_widgets.scss +15 -27
- package/src/theme/blocks/_accordion.scss +11 -4
- package/src/theme/blocks/_grid.scss +9 -77
- package/src/theme/blocks/_listing.scss +60 -126
- package/src/theme/blocks/_search.scss +3 -4
- package/src/theme/blocks/_table.scss +1 -0
- package/src/theme/blocks/_teaser.scss +7 -117
- package/src/theme/blocks/error-boundary.scss +11 -0
- package/src/theme/card.scss +107 -70
- package/src/theme/main.scss +5 -0
- package/src/theme/notfound.scss +27 -0
- package/src/theme/person.scss +28 -12
- package/src/theme/sticky-menu.scss +7 -5
- package/src/types.d.ts +1 -0
- package/vitest.config.mjs +4 -0
- package/razzle.extend.js +0 -38
- package/src/components/Blocks/schema.js +0 -44
- package/src/components/Breadcrumbs/Breadcrumbs.jsx +0 -118
- package/src/components/Widgets/AlignWidget.tsx +0 -84
- package/src/components/Widgets/BlockAlignment.tsx +0 -88
- package/src/components/Widgets/BlockWidth.tsx +0 -101
- package/src/components/Widgets/Buttons.tsx +0 -144
- package/src/components/Widgets/Size.tsx +0 -78
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kitconcept/volto-light-theme",
|
|
3
|
-
"version": "8.0.0-alpha.
|
|
3
|
+
"version": "8.0.0-alpha.20",
|
|
4
4
|
"description": "Volto Light Theme by kitconcept",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"types": "src/index.ts",
|
|
@@ -26,11 +26,20 @@
|
|
|
26
26
|
"publishConfig": {
|
|
27
27
|
"access": "public"
|
|
28
28
|
},
|
|
29
|
+
"scripts": {
|
|
30
|
+
"i18n": "rm -rf build/messages && NODE_ENV=production i18n --addon",
|
|
31
|
+
"dry-release": "release-it --dry-run",
|
|
32
|
+
"release": "release-it",
|
|
33
|
+
"release-major-alpha": "release-it major --preRelease=alpha",
|
|
34
|
+
"release-alpha": "release-it --preRelease=alpha",
|
|
35
|
+
"release-rc": "release-it --preRelease=rc"
|
|
36
|
+
},
|
|
29
37
|
"addons": [
|
|
30
38
|
"@kitconcept/volto-bm3-compat"
|
|
31
39
|
],
|
|
32
40
|
"devDependencies": {
|
|
33
41
|
"@plone/scripts": "^3.6.2",
|
|
42
|
+
"@plone/types": "workspace:*",
|
|
34
43
|
"@storybook/react": "^8.6.12",
|
|
35
44
|
"@testing-library/cypress": "10.0.3",
|
|
36
45
|
"@testing-library/jest-dom": "^6.8.0",
|
|
@@ -40,24 +49,26 @@
|
|
|
40
49
|
"@types/node": "^22",
|
|
41
50
|
"@types/react": "^18.3.12",
|
|
42
51
|
"@types/react-dom": "^18.3.1",
|
|
52
|
+
"@playwright/test": "^1.55.0",
|
|
53
|
+
"playwright": "^1.55.0",
|
|
43
54
|
"react-intl-redux": "2.3.0",
|
|
44
55
|
"redux-mock-store": "1.5.4",
|
|
45
56
|
"release-it": "^19.0.3",
|
|
46
57
|
"typescript": "^5.7.3",
|
|
47
|
-
"vitest": "^3.1.2"
|
|
48
|
-
"@plone/types": "2.0.0-alpha.7"
|
|
58
|
+
"vitest": "^3.1.2"
|
|
49
59
|
},
|
|
50
60
|
"dependencies": {
|
|
51
61
|
"@dnd-kit/core": "6.0.8",
|
|
52
62
|
"@dnd-kit/sortable": "7.0.2",
|
|
53
63
|
"@dnd-kit/utilities": "3.2.2",
|
|
64
|
+
"@kitconcept/volto-bm3-compat": "workspace:^",
|
|
65
|
+
"@plone/components": "workspace:^",
|
|
54
66
|
"embla-carousel-autoplay": "^8.0.0",
|
|
55
67
|
"embla-carousel-react": "^8.0.0",
|
|
56
68
|
"react-animate-height": "^3.2.3",
|
|
57
|
-
"react-aria-components": "^1.
|
|
69
|
+
"react-aria-components": "^1.14.0",
|
|
58
70
|
"react-colorful": "^5.6.1",
|
|
59
|
-
"uuid": "^11.0.0"
|
|
60
|
-
"@plone/components": "^4.0.0-alpha.1"
|
|
71
|
+
"uuid": "^11.0.0"
|
|
61
72
|
},
|
|
62
73
|
"peerDependencies": {
|
|
63
74
|
"classnames": "^2.5.1",
|
|
@@ -67,13 +78,5 @@
|
|
|
67
78
|
"react-intl": "^3.12.1",
|
|
68
79
|
"react-redux": "^8.1.2",
|
|
69
80
|
"react-router-dom": "^5.2.0"
|
|
70
|
-
},
|
|
71
|
-
"scripts": {
|
|
72
|
-
"i18n": "rm -rf build/messages && NODE_ENV=production i18n --addon",
|
|
73
|
-
"dry-release": "release-it --dry-run",
|
|
74
|
-
"release": "release-it",
|
|
75
|
-
"release-major-alpha": "release-it major --preRelease=alpha",
|
|
76
|
-
"release-alpha": "release-it --preRelease=alpha",
|
|
77
|
-
"release-rc": "release-it --preRelease=rc"
|
|
78
81
|
}
|
|
79
|
-
}
|
|
82
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
type GenericProps = {
|
|
4
|
+
children?: React.ReactNode;
|
|
5
|
+
} & Record<string, unknown>;
|
|
6
|
+
|
|
7
|
+
const createComponent =
|
|
8
|
+
(element: keyof JSX.IntrinsicElements = 'div') =>
|
|
9
|
+
({ children, ...rest }: GenericProps) =>
|
|
10
|
+
React.createElement(element, rest, children);
|
|
11
|
+
|
|
12
|
+
export const Container = createComponent('div');
|
|
13
|
+
export const Segment = createComponent('section');
|
|
14
|
+
export const Button = createComponent('button');
|
|
15
|
+
export const Form = createComponent('form');
|
|
16
|
+
export const Input = createComponent('input');
|
|
17
|
+
export const Pagination = createComponent('div');
|
|
18
|
+
export const Dimmer = createComponent('div');
|
|
19
|
+
export const Loader = createComponent('div');
|
|
20
|
+
|
|
21
|
+
// eslint-disable-next-line import/no-anonymous-default-export
|
|
22
|
+
export default {
|
|
23
|
+
Container,
|
|
24
|
+
Segment,
|
|
25
|
+
Button,
|
|
26
|
+
Form,
|
|
27
|
+
Input,
|
|
28
|
+
Pagination,
|
|
29
|
+
Dimmer,
|
|
30
|
+
Loader,
|
|
31
|
+
};
|
|
@@ -35,6 +35,7 @@ import {
|
|
|
35
35
|
buildStyleClassNamesExtenders,
|
|
36
36
|
} from '@plone/volto/helpers/Blocks/Blocks';
|
|
37
37
|
import MaybeWrap from '@plone/volto/components/manage/MaybeWrap/MaybeWrap';
|
|
38
|
+
import ErrorBoundary from './ErrorBoundary';
|
|
38
39
|
|
|
39
40
|
const messages = defineMessages({
|
|
40
41
|
unknownBlock: {
|
|
@@ -288,12 +289,19 @@ export class Edit extends Component {
|
|
|
288
289
|
as={'div'}
|
|
289
290
|
className="block-inner-container"
|
|
290
291
|
>
|
|
291
|
-
<
|
|
292
|
-
{
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
292
|
+
<ErrorBoundary
|
|
293
|
+
name={`blockId-${this.props.id}-type-${type}`}
|
|
294
|
+
block={this.props.block}
|
|
295
|
+
type={type}
|
|
296
|
+
isEdit
|
|
297
|
+
>
|
|
298
|
+
<Block
|
|
299
|
+
{...this.props}
|
|
300
|
+
blockNode={this.blockNode}
|
|
301
|
+
data={this.props.data}
|
|
302
|
+
className={cx({ contained: parentIsContainer })}
|
|
303
|
+
/>
|
|
304
|
+
</ErrorBoundary>
|
|
297
305
|
</MaybeWrap>
|
|
298
306
|
|
|
299
307
|
{blocksConfig?.[type]?.blockModel === 3 && (
|
|
@@ -84,7 +84,15 @@ const EditBlockWrapper = (props) => {
|
|
|
84
84
|
style: { ...style, ...draginfo.draggableProps.style },
|
|
85
85
|
};
|
|
86
86
|
|
|
87
|
-
|
|
87
|
+
if (blocksConfig?.[type]?.blockModel === 3) {
|
|
88
|
+
// We still need to attach the draggable props/ref so RBD stays happy,
|
|
89
|
+
// but we skip rendering the drag handle and friends
|
|
90
|
+
// consider removing the whole EditBlockWrapper for BlockModelv3 blocks in the future
|
|
91
|
+
// or moving the handlers here.
|
|
92
|
+
return <>{children}</>;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return (
|
|
88
96
|
<div
|
|
89
97
|
ref={draginfo.innerRef}
|
|
90
98
|
{...styleMergedWithDragProps}
|
|
@@ -160,8 +168,6 @@ const EditBlockWrapper = (props) => {
|
|
|
160
168
|
</div>
|
|
161
169
|
</div>
|
|
162
170
|
</div>
|
|
163
|
-
) : (
|
|
164
|
-
<>{children}</>
|
|
165
171
|
);
|
|
166
172
|
};
|
|
167
173
|
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import React, { type FC } from 'react';
|
|
2
|
+
import { render, screen } from '@testing-library/react';
|
|
3
|
+
import { afterAll, afterEach, describe, expect, it, vi } from 'vitest';
|
|
4
|
+
import { Provider } from 'react-intl-redux';
|
|
5
|
+
import { ErrorBoundary } from './ErrorBoundary';
|
|
6
|
+
import configureStore from 'redux-mock-store';
|
|
7
|
+
|
|
8
|
+
describe('Error boundary', () => {
|
|
9
|
+
const consoleErrorSpy = vi
|
|
10
|
+
.spyOn(console, 'error')
|
|
11
|
+
.mockImplementation(() => undefined);
|
|
12
|
+
|
|
13
|
+
afterEach(() => {
|
|
14
|
+
consoleErrorSpy.mockClear();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
afterAll(() => {
|
|
18
|
+
consoleErrorSpy.mockRestore();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
const mockStore = configureStore();
|
|
22
|
+
|
|
23
|
+
const store = mockStore({
|
|
24
|
+
intl: {
|
|
25
|
+
locale: 'en',
|
|
26
|
+
messages: {},
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('renders fallback UI when a child throws', () => {
|
|
31
|
+
const ThrowError: FC = () => {
|
|
32
|
+
throw new Error('Test');
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const { container } = render(
|
|
36
|
+
<Provider store={store}>
|
|
37
|
+
<ErrorBoundary
|
|
38
|
+
name="test"
|
|
39
|
+
block="123"
|
|
40
|
+
type="slate"
|
|
41
|
+
blocks={null}
|
|
42
|
+
blocksLayout={null}
|
|
43
|
+
title={null}
|
|
44
|
+
>
|
|
45
|
+
<ThrowError />
|
|
46
|
+
</ErrorBoundary>
|
|
47
|
+
</Provider>,
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
expect(screen.getByText('Block error:')).toBeInTheDocument();
|
|
51
|
+
expect(
|
|
52
|
+
container.querySelector('.block-error-boundary .title'),
|
|
53
|
+
).toBeInTheDocument();
|
|
54
|
+
});
|
|
55
|
+
});
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { ErrorInfo, ReactNode } from 'react';
|
|
3
|
+
import { connect } from 'react-redux';
|
|
4
|
+
import type { BlocksData } from '@plone/types';
|
|
5
|
+
import ErrorBoundaryMessage from './ErrorBoundaryMessage';
|
|
6
|
+
|
|
7
|
+
type OwnProps = {
|
|
8
|
+
name?: string;
|
|
9
|
+
block?: string;
|
|
10
|
+
type?: string;
|
|
11
|
+
isEdit?: boolean;
|
|
12
|
+
children?: ReactNode;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
type StateProps = {
|
|
16
|
+
blocks: BlocksData['blocks'];
|
|
17
|
+
blocksLayout: BlocksData['blocks_layout'];
|
|
18
|
+
title: string | null;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
type ErrorBoundaryState = {
|
|
22
|
+
hasError: boolean;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
type ErrorBoundaryProps = OwnProps & StateProps;
|
|
26
|
+
|
|
27
|
+
export class ErrorBoundary extends React.Component<
|
|
28
|
+
ErrorBoundaryProps,
|
|
29
|
+
ErrorBoundaryState
|
|
30
|
+
> {
|
|
31
|
+
state: ErrorBoundaryState = { hasError: false };
|
|
32
|
+
|
|
33
|
+
static getDerivedStateFromError(_error: Error): ErrorBoundaryState {
|
|
34
|
+
// Update state so the next render will show the fallback UI.
|
|
35
|
+
return { hasError: true };
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
componentDidUpdate(prevProps: ErrorBoundaryProps) {
|
|
39
|
+
const titleChanged = prevProps.title !== this.props.title;
|
|
40
|
+
const blocksChanged = prevProps.blocks !== this.props.blocks;
|
|
41
|
+
const blocksLayoutChanged =
|
|
42
|
+
prevProps.blocksLayout !== this.props.blocksLayout;
|
|
43
|
+
|
|
44
|
+
if (
|
|
45
|
+
(blocksChanged || blocksLayoutChanged || titleChanged) &&
|
|
46
|
+
this.state.hasError
|
|
47
|
+
) {
|
|
48
|
+
this.setState({ hasError: false });
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
|
|
53
|
+
// eslint-disable-next-line
|
|
54
|
+
console.error(error, errorInfo);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
render(): ReactNode {
|
|
58
|
+
if (this.state.hasError) {
|
|
59
|
+
return (
|
|
60
|
+
<ErrorBoundaryMessage
|
|
61
|
+
name={this.props.name}
|
|
62
|
+
block={this.props.block}
|
|
63
|
+
type={this.props.type}
|
|
64
|
+
isEdit={this.props.isEdit}
|
|
65
|
+
/>
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return this.props.children;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
type ReduxState = {
|
|
74
|
+
form?: {
|
|
75
|
+
global?: {
|
|
76
|
+
blocks?: BlocksData['blocks'];
|
|
77
|
+
blocks_layout?: BlocksData['blocks_layout'];
|
|
78
|
+
title: string | null;
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const mapStateToProps = (state: ReduxState): StateProps => ({
|
|
84
|
+
blocks: state.form?.global?.blocks ?? null,
|
|
85
|
+
blocksLayout: state.form?.global?.blocks_layout ?? null,
|
|
86
|
+
// Title is used for demonstration purposes
|
|
87
|
+
// If we want to use it in metadata sources, we should connect it to the full state
|
|
88
|
+
// which I am reluctant to do because nowadays the form state can be quite large
|
|
89
|
+
title: state.form?.global?.title ?? null,
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
export default connect(mapStateToProps)(ErrorBoundary);
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
|
2
|
+
|
|
3
|
+
type ErrorBoundaryMessageProps = {
|
|
4
|
+
name?: string;
|
|
5
|
+
block?: string;
|
|
6
|
+
type?: string;
|
|
7
|
+
isEdit?: boolean;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const messages = defineMessages({
|
|
11
|
+
title: {
|
|
12
|
+
id: 'blockErrorBoundaryTitle',
|
|
13
|
+
defaultMessage: 'Block error:',
|
|
14
|
+
},
|
|
15
|
+
description: {
|
|
16
|
+
id: 'blockErrorBoundaryDescription',
|
|
17
|
+
defaultMessage:
|
|
18
|
+
'The {type} block with the id {block} has encountered an error.{lineBreak}You can try to undo your changes (via the undo toolbar or pressing {shortcut}), or try to delete the block and recreate it again.',
|
|
19
|
+
},
|
|
20
|
+
viewDescription: {
|
|
21
|
+
id: 'blockErrorBoundaryViewDescription',
|
|
22
|
+
defaultMessage:
|
|
23
|
+
'The {type} block with the id {block} errored and cannot be displayed.{lineBreak}Please contact the site administrator for further assistance.',
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const ErrorBoundaryMessage = (props: ErrorBoundaryMessageProps) => {
|
|
28
|
+
const intl = useIntl();
|
|
29
|
+
|
|
30
|
+
if (props.isEdit) {
|
|
31
|
+
return (
|
|
32
|
+
<div className="block-error-boundary">
|
|
33
|
+
<div className="title">{intl.formatMessage(messages.title)}</div>
|
|
34
|
+
<p>
|
|
35
|
+
<FormattedMessage
|
|
36
|
+
{...messages.description}
|
|
37
|
+
values={{
|
|
38
|
+
type: <code>{props.type}</code>,
|
|
39
|
+
block: <code>{props.block}</code>,
|
|
40
|
+
lineBreak: <br />,
|
|
41
|
+
shortcut: <code>ctrl/cmd + Z</code>,
|
|
42
|
+
}}
|
|
43
|
+
/>
|
|
44
|
+
</p>
|
|
45
|
+
</div>
|
|
46
|
+
);
|
|
47
|
+
} else {
|
|
48
|
+
return (
|
|
49
|
+
<div className="block-error-boundary">
|
|
50
|
+
<div className="title">{intl.formatMessage(messages.title)}</div>
|
|
51
|
+
<p>
|
|
52
|
+
<FormattedMessage
|
|
53
|
+
{...messages.viewDescription}
|
|
54
|
+
values={{
|
|
55
|
+
type: <code>{props.type}</code>,
|
|
56
|
+
block: <code>{props.block}</code>,
|
|
57
|
+
lineBreak: <br />,
|
|
58
|
+
}}
|
|
59
|
+
/>
|
|
60
|
+
</p>
|
|
61
|
+
</div>
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export default ErrorBoundaryMessage;
|
|
@@ -13,6 +13,7 @@ import Caption from '../../Caption/Caption';
|
|
|
13
13
|
function Edit(props) {
|
|
14
14
|
const { data } = props;
|
|
15
15
|
const Image = config.getComponent({ name: 'Image' }).component;
|
|
16
|
+
|
|
16
17
|
const onSelectItem = React.useCallback(
|
|
17
18
|
(url, item) => {
|
|
18
19
|
const dataAdapter = props.blocksConfig[props.data['@type']].dataAdapter;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// See Customization for more info
|
|
2
|
+
import { useSelector } from 'react-redux';
|
|
2
3
|
import PropTypes from 'prop-types';
|
|
3
4
|
import ConditionalLink from '@plone/volto/components/manage/ConditionalLink/ConditionalLink';
|
|
4
5
|
import Card from '../../../primitives/Card/Card';
|
|
@@ -11,6 +12,8 @@ import cx from 'classnames';
|
|
|
11
12
|
const DefaultTemplate = ({ items, linkTitle, linkHref, isEditMode }) => {
|
|
12
13
|
let link = null;
|
|
13
14
|
let href = linkHref?.[0]?.['@id'] || '';
|
|
15
|
+
const site = useSelector((state) => state.site?.data);
|
|
16
|
+
const hideProfileLinks = site?.['kitconcept.disable_profile_links'];
|
|
14
17
|
|
|
15
18
|
if (isInternalURL(href)) {
|
|
16
19
|
link = (
|
|
@@ -24,16 +27,19 @@ const DefaultTemplate = ({ items, linkTitle, linkHref, isEditMode }) => {
|
|
|
24
27
|
|
|
25
28
|
return (
|
|
26
29
|
<>
|
|
27
|
-
<
|
|
30
|
+
<ul className="items">
|
|
28
31
|
{items.map((item) => {
|
|
29
32
|
const Summary =
|
|
30
33
|
config.getComponent({
|
|
31
34
|
name: 'Summary',
|
|
32
35
|
dependencies: [item['@type']],
|
|
33
36
|
}).component || DefaultSummary;
|
|
34
|
-
|
|
37
|
+
let showLink = !Summary.hideLink && !isEditMode;
|
|
38
|
+
if (item['@type'] === 'Person' && hideProfileLinks !== undefined) {
|
|
39
|
+
showLink = !hideProfileLinks && !isEditMode;
|
|
40
|
+
}
|
|
35
41
|
return (
|
|
36
|
-
<
|
|
42
|
+
<li
|
|
37
43
|
className={cx('listing-item', {
|
|
38
44
|
[`${item['@type']?.toLowerCase()}-listing`]: item['@type'],
|
|
39
45
|
})}
|
|
@@ -41,13 +47,13 @@ const DefaultTemplate = ({ items, linkTitle, linkHref, isEditMode }) => {
|
|
|
41
47
|
>
|
|
42
48
|
<Card item={showLink ? item : null}>
|
|
43
49
|
<Card.Summary>
|
|
44
|
-
<Summary item={item}
|
|
50
|
+
<Summary item={item} />
|
|
45
51
|
</Card.Summary>
|
|
46
52
|
</Card>
|
|
47
|
-
</
|
|
53
|
+
</li>
|
|
48
54
|
);
|
|
49
55
|
})}
|
|
50
|
-
</
|
|
56
|
+
</ul>
|
|
51
57
|
|
|
52
58
|
{link && <div className="footer">{link}</div>}
|
|
53
59
|
</>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
|
+
import { useSelector } from 'react-redux';
|
|
3
4
|
import ConditionalLink from '@plone/volto/components/manage/ConditionalLink/ConditionalLink';
|
|
4
5
|
import Card from '../../../primitives/Card/Card';
|
|
5
6
|
import { flattenToAppURL, isInternalURL } from '@plone/volto/helpers/Url/Url';
|
|
@@ -11,6 +12,8 @@ const GridTemplate = ({ items, linkTitle, linkHref, isEditMode }) => {
|
|
|
11
12
|
let link = null;
|
|
12
13
|
let href = linkHref?.[0]?.['@id'] || '';
|
|
13
14
|
const PreviewImageComponent = config.getComponent('PreviewImage').component;
|
|
15
|
+
const site = useSelector((state) => state.site?.data);
|
|
16
|
+
const hideProfileLinks = site?.['kitconcept.disable_profile_links'];
|
|
14
17
|
|
|
15
18
|
if (isInternalURL(href)) {
|
|
16
19
|
link = (
|
|
@@ -24,7 +27,7 @@ const GridTemplate = ({ items, linkTitle, linkHref, isEditMode }) => {
|
|
|
24
27
|
|
|
25
28
|
return (
|
|
26
29
|
<>
|
|
27
|
-
<
|
|
30
|
+
<ul className="items">
|
|
28
31
|
{items.map((item) => {
|
|
29
32
|
const CustomItemBodyTemplate = config.getComponent({
|
|
30
33
|
name: 'GridListingItemTemplate',
|
|
@@ -35,7 +38,10 @@ const GridTemplate = ({ items, linkTitle, linkHref, isEditMode }) => {
|
|
|
35
38
|
name: 'Summary',
|
|
36
39
|
dependencies: [item['@type']],
|
|
37
40
|
}).component || DefaultSummary;
|
|
38
|
-
|
|
41
|
+
let showLink = !Summary.hideLink && !isEditMode;
|
|
42
|
+
if (item['@type'] === 'Person' && hideProfileLinks !== undefined) {
|
|
43
|
+
showLink = !hideProfileLinks && !isEditMode;
|
|
44
|
+
}
|
|
39
45
|
|
|
40
46
|
const ItemBodyTemplate = (props) =>
|
|
41
47
|
CustomItemBodyTemplate ? (
|
|
@@ -49,14 +55,17 @@ const GridTemplate = ({ items, linkTitle, linkHref, isEditMode }) => {
|
|
|
49
55
|
imageComponent={PreviewImageComponent}
|
|
50
56
|
/>
|
|
51
57
|
)}
|
|
52
|
-
<Card.Summary
|
|
53
|
-
|
|
58
|
+
<Card.Summary
|
|
59
|
+
a11yLabelId={props.a11yLabelId}
|
|
60
|
+
LinkToItem={props.LinkToItem}
|
|
61
|
+
>
|
|
62
|
+
<Summary item={item} />
|
|
54
63
|
</Card.Summary>
|
|
55
64
|
</>
|
|
56
65
|
);
|
|
57
66
|
|
|
58
67
|
return (
|
|
59
|
-
<
|
|
68
|
+
<li
|
|
60
69
|
className={cx('listing-item', {
|
|
61
70
|
[`${item['@type']?.toLowerCase()}-listing`]: item['@type'],
|
|
62
71
|
})}
|
|
@@ -65,10 +74,10 @@ const GridTemplate = ({ items, linkTitle, linkHref, isEditMode }) => {
|
|
|
65
74
|
<Card item={showLink ? item : null}>
|
|
66
75
|
<ItemBodyTemplate item={item} />
|
|
67
76
|
</Card>
|
|
68
|
-
</
|
|
77
|
+
</li>
|
|
69
78
|
);
|
|
70
79
|
})}
|
|
71
|
-
</
|
|
80
|
+
</ul>
|
|
72
81
|
|
|
73
82
|
{link && <div className="footer">{link}</div>}
|
|
74
83
|
</>
|
|
@@ -6,6 +6,7 @@ import Slugger from 'github-slugger';
|
|
|
6
6
|
import { renderLinkElement } from '@plone/volto-slate/editor/render';
|
|
7
7
|
import config from '@plone/volto/registry';
|
|
8
8
|
import withQuerystringResults from '@plone/volto/components/manage/Blocks/Listing/withQuerystringResults';
|
|
9
|
+
import SlotRenderer from '@plone/volto/components/theme/SlotRenderer/SlotRenderer';
|
|
9
10
|
|
|
10
11
|
const messages = defineMessages({
|
|
11
12
|
PaginationNavigationFor: {
|
|
@@ -38,7 +39,7 @@ const Headline = ({
|
|
|
38
39
|
mode={!isEditMode && 'view'}
|
|
39
40
|
children={data.headline}
|
|
40
41
|
attributes={attr}
|
|
41
|
-
className={cx('headline', {
|
|
42
|
+
className={cx('headline block-title', {
|
|
42
43
|
emptyListing: !listingItems?.length > 0,
|
|
43
44
|
})}
|
|
44
45
|
style={style}
|
|
@@ -63,6 +64,7 @@ export const ListingBody = (props) => {
|
|
|
63
64
|
id,
|
|
64
65
|
total,
|
|
65
66
|
properties,
|
|
67
|
+
content,
|
|
66
68
|
} = props;
|
|
67
69
|
|
|
68
70
|
let ListingBodyTemplate;
|
|
@@ -99,6 +101,7 @@ export const ListingBody = (props) => {
|
|
|
99
101
|
isEditMode={isEditMode}
|
|
100
102
|
/>
|
|
101
103
|
)}
|
|
104
|
+
<SlotRenderer name="aboveListingItems" content={content} data={data} />
|
|
102
105
|
{listingItems?.length > 0 ? (
|
|
103
106
|
<div ref={listingRef}>
|
|
104
107
|
<ListingBodyTemplate
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
|
+
import { useSelector } from 'react-redux';
|
|
3
4
|
import ConditionalLink from '@plone/volto/components/manage/ConditionalLink/ConditionalLink';
|
|
4
5
|
import Card from '../../../primitives/Card/Card';
|
|
5
6
|
import { flattenToAppURL, isInternalURL } from '@plone/volto/helpers/Url/Url';
|
|
@@ -8,6 +9,8 @@ import DefaultSummary from '@kitconcept/volto-light-theme/components/Summary/Def
|
|
|
8
9
|
import cx from 'classnames';
|
|
9
10
|
|
|
10
11
|
const SummaryTemplate = ({ items, linkTitle, linkHref, isEditMode }) => {
|
|
12
|
+
const site = useSelector((state) => state.site?.data);
|
|
13
|
+
const hideProfileLinks = site?.['kitconcept.disable_profile_links'];
|
|
11
14
|
let link = null;
|
|
12
15
|
let href = linkHref?.[0]?.['@id'] || '';
|
|
13
16
|
const PreviewImageComponent = config.getComponent('PreviewImage').component;
|
|
@@ -23,7 +26,7 @@ const SummaryTemplate = ({ items, linkTitle, linkHref, isEditMode }) => {
|
|
|
23
26
|
|
|
24
27
|
return (
|
|
25
28
|
<>
|
|
26
|
-
<
|
|
29
|
+
<ul className="items">
|
|
27
30
|
{items.map((item) => {
|
|
28
31
|
const CustomItemBodyTemplate = config.getComponent({
|
|
29
32
|
name: 'SummaryListingItemTemplate',
|
|
@@ -34,7 +37,10 @@ const SummaryTemplate = ({ items, linkTitle, linkHref, isEditMode }) => {
|
|
|
34
37
|
name: 'Summary',
|
|
35
38
|
dependencies: [item['@type']],
|
|
36
39
|
}).component || DefaultSummary;
|
|
37
|
-
|
|
40
|
+
let showLink = !Summary.hideLink && !isEditMode;
|
|
41
|
+
if (item['@type'] === 'Person' && hideProfileLinks !== undefined) {
|
|
42
|
+
showLink = !hideProfileLinks && !isEditMode;
|
|
43
|
+
}
|
|
38
44
|
const ItemBodyTemplate = (props) =>
|
|
39
45
|
CustomItemBodyTemplate ? (
|
|
40
46
|
<CustomItemBodyTemplate item={item} />
|
|
@@ -45,13 +51,16 @@ const SummaryTemplate = ({ items, linkTitle, linkHref, isEditMode }) => {
|
|
|
45
51
|
showPlaceholderImage={true}
|
|
46
52
|
imageComponent={PreviewImageComponent}
|
|
47
53
|
/>
|
|
48
|
-
<Card.Summary
|
|
49
|
-
|
|
54
|
+
<Card.Summary
|
|
55
|
+
a11yLabelId={props.a11yLabelId}
|
|
56
|
+
LinkToItem={props.LinkToItem}
|
|
57
|
+
>
|
|
58
|
+
<Summary item={item} />
|
|
50
59
|
</Card.Summary>
|
|
51
60
|
</>
|
|
52
61
|
);
|
|
53
62
|
return (
|
|
54
|
-
<
|
|
63
|
+
<li
|
|
55
64
|
className={cx('listing-item has--align--left', {
|
|
56
65
|
[`${item['@type']?.toLowerCase()}-listing`]: item['@type'],
|
|
57
66
|
})}
|
|
@@ -60,10 +69,10 @@ const SummaryTemplate = ({ items, linkTitle, linkHref, isEditMode }) => {
|
|
|
60
69
|
<Card item={showLink ? item : null}>
|
|
61
70
|
<ItemBodyTemplate item={item} />
|
|
62
71
|
</Card>
|
|
63
|
-
</
|
|
72
|
+
</li>
|
|
64
73
|
);
|
|
65
74
|
})}
|
|
66
|
-
</
|
|
75
|
+
</ul>
|
|
67
76
|
|
|
68
77
|
{link && <div className="footer">{link}</div>}
|
|
69
78
|
</>
|