@eeacms/volto-eea-website-policy 0.2.5 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/package.json +1 -1
- package/src/components/Blocks/ContextNavigation/ContextNavigationEdit.jsx +31 -0
- package/src/components/Blocks/ContextNavigation/ContextNavigationView.jsx +17 -0
- package/src/components/Blocks/ContextNavigation/index.js +26 -0
- package/src/components/Blocks/ContextNavigation/schema.js +81 -0
- package/src/components/Blocks/Item/schema.js +14 -5
- package/src/customizations/volto/components/manage/Toolbar/Toolbar.jsx +589 -0
- package/src/index.js +6 -4
package/CHANGELOG.md
CHANGED
|
@@ -4,8 +4,31 @@ All notable changes to this project will be documented in this file. Dates are d
|
|
|
4
4
|
|
|
5
5
|
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
6
6
|
|
|
7
|
+
#### [0.3.1](https://github.com/eea/volto-eea-website-policy/compare/0.3.0...0.3.1)
|
|
8
|
+
|
|
9
|
+
- feature(navigation): addde context navigation block [`2b0b6f6`](https://github.com/eea/volto-eea-website-policy/commit/2b0b6f616adf85ab41365a7cf6ee6e690ff9fd0c)
|
|
10
|
+
|
|
11
|
+
#### [0.3.0](https://github.com/eea/volto-eea-website-policy/compare/0.2.6...0.3.0)
|
|
12
|
+
|
|
13
|
+
> 6 July 2022
|
|
14
|
+
|
|
15
|
+
- change(teaser): enabled theming for icon and text color [`#13`](https://github.com/eea/volto-eea-website-policy/pull/13)
|
|
16
|
+
- change(package): bump release version [`1b00439`](https://github.com/eea/volto-eea-website-policy/commit/1b0043933442bb73c1042dce644a2c09e5f210f4)
|
|
17
|
+
- change(item): enable theming for icon and text color and added tertiary option [`58c2d28`](https://github.com/eea/volto-eea-website-policy/commit/58c2d2864fe94c9e7808064b61d3b6c4e6fccbb1)
|
|
18
|
+
- change(item): commented sizes too small for item icons and enabled tertiary theme [`0f02d7d`](https://github.com/eea/volto-eea-website-policy/commit/0f02d7d6204b068b78c3f977a561782a19b6f79e)
|
|
19
|
+
|
|
20
|
+
#### [0.2.6](https://github.com/eea/volto-eea-website-policy/compare/0.2.5...0.2.6)
|
|
21
|
+
|
|
22
|
+
> 1 July 2022
|
|
23
|
+
|
|
24
|
+
- Fix Cannot read properties of undefined (reading 'translations') [`8e7b8b8`](https://github.com/eea/volto-eea-website-policy/commit/8e7b8b8533b14f173d77783fe2d0b517c29c5937)
|
|
25
|
+
- Customize Toolbar.jsx - copied unchanged from @plone/volto 16.0.0.alpha.11 [`b7add4f`](https://github.com/eea/volto-eea-website-policy/commit/b7add4faa8ef2dde7d77489fc8bc431cbb023314)
|
|
26
|
+
|
|
7
27
|
#### [0.2.5](https://github.com/eea/volto-eea-website-policy/compare/0.2.4...0.2.5)
|
|
8
28
|
|
|
29
|
+
> 23 June 2022
|
|
30
|
+
|
|
31
|
+
- Rounded Card variation and disable ImageCards block [`#11`](https://github.com/eea/volto-eea-website-policy/pull/11)
|
|
9
32
|
- Rounded card via style wrapper [`6728684`](https://github.com/eea/volto-eea-website-policy/commit/67286844b00902aa4c6b316b50be35db95c531f0)
|
|
10
33
|
- Revert "Rounded Card variation - refs #148723" [`0168a86`](https://github.com/eea/volto-eea-website-policy/commit/0168a86fa644a9b848e37c7f5054eb4308c36784)
|
|
11
34
|
- Disable Image Cards block [`3ed8dc3`](https://github.com/eea/volto-eea-website-policy/commit/3ed8dc311cad8e30a8c918ecec7b21cc99260c50)
|
package/package.json
CHANGED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { EditSchema } from './schema';
|
|
3
|
+
import { InlineForm, SidebarPortal } from '@plone/volto/components';
|
|
4
|
+
import ContextNavigationView from './ContextNavigationView';
|
|
5
|
+
|
|
6
|
+
const ContextNavigationFillView = (props) => {
|
|
7
|
+
const schema = EditSchema();
|
|
8
|
+
return (
|
|
9
|
+
<>
|
|
10
|
+
<h3>Context navigation</h3>
|
|
11
|
+
<ContextNavigationView {...props} />{' '}
|
|
12
|
+
<SidebarPortal selected={props.selected}>
|
|
13
|
+
{props.selected && (
|
|
14
|
+
<InlineForm
|
|
15
|
+
title={schema.title}
|
|
16
|
+
schema={schema}
|
|
17
|
+
formData={props.data}
|
|
18
|
+
onChangeField={(id, value) => {
|
|
19
|
+
props.onChangeBlock(props.block, {
|
|
20
|
+
...props.data,
|
|
21
|
+
[id]: value,
|
|
22
|
+
});
|
|
23
|
+
}}
|
|
24
|
+
/>
|
|
25
|
+
)}
|
|
26
|
+
</SidebarPortal>
|
|
27
|
+
</>
|
|
28
|
+
);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export default ContextNavigationFillView;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import ConnectedContextNavigation from '@plone/volto/components/theme/Navigation/ContextNavigation';
|
|
3
|
+
import { flattenToAppURL } from '@plone/volto/helpers';
|
|
4
|
+
|
|
5
|
+
const ContextNavigationView = ({ data = {} }) => {
|
|
6
|
+
const navProps = { ...data };
|
|
7
|
+
const root_path = data?.root_node?.[0]?.['@id'];
|
|
8
|
+
if (root_path) navProps['root_path'] = flattenToAppURL(root_path);
|
|
9
|
+
|
|
10
|
+
return (
|
|
11
|
+
<>
|
|
12
|
+
<ConnectedContextNavigation params={navProps} />
|
|
13
|
+
</>
|
|
14
|
+
);
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export default ContextNavigationView;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import codeSVG from '@plone/volto/icons/code.svg';
|
|
2
|
+
import ContextNavigationEdit from './ContextNavigationEdit';
|
|
3
|
+
import ContextNavigationView from './ContextNavigationView';
|
|
4
|
+
import BlockSettingsSchema from '@plone/volto/components/manage/Blocks/Block/Schema';
|
|
5
|
+
|
|
6
|
+
export default (config) => {
|
|
7
|
+
config.blocks.blocksConfig.contextNavigation = {
|
|
8
|
+
id: 'contextNavigation',
|
|
9
|
+
title: 'Navigation',
|
|
10
|
+
icon: codeSVG,
|
|
11
|
+
group: 'site',
|
|
12
|
+
view: ContextNavigationView,
|
|
13
|
+
edit: ContextNavigationEdit,
|
|
14
|
+
schema: BlockSettingsSchema,
|
|
15
|
+
restricted: false,
|
|
16
|
+
mostUsed: true,
|
|
17
|
+
blockHasOwnFocusManagement: true,
|
|
18
|
+
sidebarTab: 1,
|
|
19
|
+
security: {
|
|
20
|
+
addPermission: [],
|
|
21
|
+
view: [],
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
return config;
|
|
26
|
+
};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
export const EditSchema = () => {
|
|
2
|
+
return {
|
|
3
|
+
title: 'Navigation',
|
|
4
|
+
fieldsets: [
|
|
5
|
+
{
|
|
6
|
+
id: 'default',
|
|
7
|
+
title: 'Default',
|
|
8
|
+
fields: [
|
|
9
|
+
'name',
|
|
10
|
+
'root_node',
|
|
11
|
+
'includeTop',
|
|
12
|
+
'currentFolderOnly',
|
|
13
|
+
'topLevel',
|
|
14
|
+
'bottomLevel',
|
|
15
|
+
'no_icons',
|
|
16
|
+
'thumb_scale',
|
|
17
|
+
'no_thumbs',
|
|
18
|
+
],
|
|
19
|
+
},
|
|
20
|
+
],
|
|
21
|
+
required: [],
|
|
22
|
+
properties: {
|
|
23
|
+
name: {
|
|
24
|
+
title: 'Title',
|
|
25
|
+
description: 'The title of the navigation tree',
|
|
26
|
+
},
|
|
27
|
+
root_node: {
|
|
28
|
+
title: 'Root node',
|
|
29
|
+
description:
|
|
30
|
+
'You may search for and choose a folder to act as the root of the navigation tree. Leave blank to use the Plone site root.',
|
|
31
|
+
widget: 'object_browser',
|
|
32
|
+
// TODO: these don't work. Why?
|
|
33
|
+
mode: 'link',
|
|
34
|
+
selectedItemAttrs: ['Title', 'Description'],
|
|
35
|
+
},
|
|
36
|
+
includeTop: {
|
|
37
|
+
title: 'Include top node',
|
|
38
|
+
description:
|
|
39
|
+
"Whether or not to show the top, or 'root', node in the navigation tree. This is affected by the 'Start level' setting.",
|
|
40
|
+
type: 'boolean',
|
|
41
|
+
},
|
|
42
|
+
currentFolderOnly: {
|
|
43
|
+
title: 'Only show the contents of the current folder',
|
|
44
|
+
description:
|
|
45
|
+
'If selected, the navigation tree will only show the current folder and its children at all times.',
|
|
46
|
+
type: 'boolean',
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
topLevel: {
|
|
50
|
+
title: 'Start level',
|
|
51
|
+
description:
|
|
52
|
+
'An integer value that specifies the number of folder levels below the site root that must be exceeded before the navigation tree will display. 0 means that the navigation tree should be displayed everywhere including pages in the root of the site. 1 means the tree only shows up inside folders located in the root and downwards, never showing at the top level.',
|
|
53
|
+
type: 'number',
|
|
54
|
+
default: 1,
|
|
55
|
+
},
|
|
56
|
+
bottomLevel: {
|
|
57
|
+
title: 'Navigation tree depth',
|
|
58
|
+
description:
|
|
59
|
+
'How many folders should be included before the navigation tree stops. 0 means no limit. 1 only includes the root folder.',
|
|
60
|
+
type: 'number',
|
|
61
|
+
default: 0,
|
|
62
|
+
},
|
|
63
|
+
no_icons: {
|
|
64
|
+
title: 'Supress icons',
|
|
65
|
+
description:
|
|
66
|
+
'If enabled, the portlet will not show document type icons.',
|
|
67
|
+
type: 'boolean',
|
|
68
|
+
},
|
|
69
|
+
thumb_scale: {
|
|
70
|
+
title: 'Override thumb scale',
|
|
71
|
+
description:
|
|
72
|
+
"Enter a valid scale name (see 'Image Handling' control panel) to override (e.g. icon, tile, thumb, mini, preview, ... ). Leave empty to use default (see 'Site' control panel).",
|
|
73
|
+
},
|
|
74
|
+
no_thumbs: {
|
|
75
|
+
title: 'Supress thumbs',
|
|
76
|
+
type: 'boolean',
|
|
77
|
+
description: 'If enabled, the portlet will not show thumbs.',
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
};
|
|
@@ -12,7 +12,13 @@ export default ({ data }) => {
|
|
|
12
12
|
? [{ id: 'image', title: 'Image', fields: ['image', 'imageSize'] }]
|
|
13
13
|
: []),
|
|
14
14
|
...(assetType === 'icon'
|
|
15
|
-
? [
|
|
15
|
+
? [
|
|
16
|
+
{
|
|
17
|
+
id: 'icon',
|
|
18
|
+
title: 'Icon',
|
|
19
|
+
fields: ['icon', 'iconSize', 'iconTheme'],
|
|
20
|
+
},
|
|
21
|
+
]
|
|
16
22
|
: []),
|
|
17
23
|
],
|
|
18
24
|
properties: {
|
|
@@ -31,10 +37,11 @@ export default ({ data }) => {
|
|
|
31
37
|
imageSize: {
|
|
32
38
|
title: 'Image size',
|
|
33
39
|
choices: [
|
|
34
|
-
|
|
35
|
-
['
|
|
36
|
-
['
|
|
37
|
-
['
|
|
40
|
+
// commented as they were too small to use as item icons
|
|
41
|
+
// ['mini', 'Mini'],
|
|
42
|
+
// ['tile', 'Tile'],
|
|
43
|
+
// ['tiny', 'Tiny'],
|
|
44
|
+
// ['small', 'Small'],
|
|
38
45
|
['large', 'Large'],
|
|
39
46
|
['big', 'Big'],
|
|
40
47
|
['huge', 'Huge'],
|
|
@@ -63,6 +70,7 @@ export default ({ data }) => {
|
|
|
63
70
|
choices: [
|
|
64
71
|
['primary', 'Primary'],
|
|
65
72
|
['secondary', 'Secondary'],
|
|
73
|
+
['tertiary', 'Tertiary'],
|
|
66
74
|
],
|
|
67
75
|
},
|
|
68
76
|
},
|
|
@@ -86,6 +94,7 @@ export const stylingSchema = ({ intl }) => ({
|
|
|
86
94
|
choices: [
|
|
87
95
|
['primary', 'Primary'],
|
|
88
96
|
['secondary', 'Secondary'],
|
|
97
|
+
['tertiary', 'Tertiary'],
|
|
89
98
|
],
|
|
90
99
|
},
|
|
91
100
|
verticalAlign: {
|
|
@@ -0,0 +1,589 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Toolbar component.
|
|
3
|
+
* @module components/manage/Toolbar/Toolbar
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React, { Component } from 'react';
|
|
7
|
+
import { defineMessages, injectIntl } from 'react-intl';
|
|
8
|
+
import PropTypes from 'prop-types';
|
|
9
|
+
import { Link } from 'react-router-dom';
|
|
10
|
+
import jwtDecode from 'jwt-decode';
|
|
11
|
+
import { connect } from 'react-redux';
|
|
12
|
+
import { compose } from 'redux';
|
|
13
|
+
import { doesNodeContainClick } from 'semantic-ui-react/dist/commonjs/lib';
|
|
14
|
+
import { withCookies } from 'react-cookie';
|
|
15
|
+
import { filter, find } from 'lodash';
|
|
16
|
+
import cx from 'classnames';
|
|
17
|
+
import config from '@plone/volto/registry';
|
|
18
|
+
|
|
19
|
+
import More from '@plone/volto/components/manage/Toolbar/More';
|
|
20
|
+
import PersonalTools from '@plone/volto/components/manage/Toolbar/PersonalTools';
|
|
21
|
+
import Types from '@plone/volto/components/manage/Toolbar/Types';
|
|
22
|
+
import PersonalInformation from '@plone/volto/components/manage/Preferences/PersonalInformation';
|
|
23
|
+
import PersonalPreferences from '@plone/volto/components/manage/Preferences/PersonalPreferences';
|
|
24
|
+
import StandardWrapper from '@plone/volto/components/manage/Toolbar/StandardWrapper';
|
|
25
|
+
import {
|
|
26
|
+
getTypes,
|
|
27
|
+
listActions,
|
|
28
|
+
setExpandedToolbar,
|
|
29
|
+
unlockContent,
|
|
30
|
+
} from '@plone/volto/actions';
|
|
31
|
+
import { Icon } from '@plone/volto/components';
|
|
32
|
+
import { BodyClass, getBaseUrl, getCookieOptions } from '@plone/volto/helpers';
|
|
33
|
+
import { Pluggable } from '@plone/volto/components/manage/Pluggable';
|
|
34
|
+
|
|
35
|
+
import penSVG from '@plone/volto/icons/pen.svg';
|
|
36
|
+
import unlockSVG from '@plone/volto/icons/unlock.svg';
|
|
37
|
+
import folderSVG from '@plone/volto/icons/folder.svg';
|
|
38
|
+
import addSVG from '@plone/volto/icons/add-document.svg';
|
|
39
|
+
import moreSVG from '@plone/volto/icons/more.svg';
|
|
40
|
+
import userSVG from '@plone/volto/icons/user.svg';
|
|
41
|
+
import clearSVG from '@plone/volto/icons/clear.svg';
|
|
42
|
+
|
|
43
|
+
const messages = defineMessages({
|
|
44
|
+
edit: {
|
|
45
|
+
id: 'Edit',
|
|
46
|
+
defaultMessage: 'Edit',
|
|
47
|
+
},
|
|
48
|
+
contents: {
|
|
49
|
+
id: 'Contents',
|
|
50
|
+
defaultMessage: 'Contents',
|
|
51
|
+
},
|
|
52
|
+
add: {
|
|
53
|
+
id: 'Add',
|
|
54
|
+
defaultMessage: 'Add',
|
|
55
|
+
},
|
|
56
|
+
more: {
|
|
57
|
+
id: 'More',
|
|
58
|
+
defaultMessage: 'More',
|
|
59
|
+
},
|
|
60
|
+
personalTools: {
|
|
61
|
+
id: 'Personal tools',
|
|
62
|
+
defaultMessage: 'Personal tools',
|
|
63
|
+
},
|
|
64
|
+
shrinkToolbar: {
|
|
65
|
+
id: 'Shrink toolbar',
|
|
66
|
+
defaultMessage: 'Shrink toolbar',
|
|
67
|
+
},
|
|
68
|
+
personalInformation: {
|
|
69
|
+
id: 'Personal Information',
|
|
70
|
+
defaultMessage: 'Personal Information',
|
|
71
|
+
},
|
|
72
|
+
personalPreferences: {
|
|
73
|
+
id: 'Personal Preferences',
|
|
74
|
+
defaultMessage: 'Personal Preferences',
|
|
75
|
+
},
|
|
76
|
+
collection: {
|
|
77
|
+
id: 'Collection',
|
|
78
|
+
defaultMessage: 'Collection',
|
|
79
|
+
},
|
|
80
|
+
file: {
|
|
81
|
+
id: 'File',
|
|
82
|
+
defaultMessage: 'File',
|
|
83
|
+
},
|
|
84
|
+
link: {
|
|
85
|
+
id: 'Link',
|
|
86
|
+
defaultMessage: 'Link',
|
|
87
|
+
},
|
|
88
|
+
newsItem: {
|
|
89
|
+
id: 'News Item',
|
|
90
|
+
defaultMessage: 'News Item',
|
|
91
|
+
},
|
|
92
|
+
page: {
|
|
93
|
+
id: 'Page',
|
|
94
|
+
defaultMessage: 'Page',
|
|
95
|
+
},
|
|
96
|
+
back: {
|
|
97
|
+
id: 'Back',
|
|
98
|
+
defaultMessage: 'Back',
|
|
99
|
+
},
|
|
100
|
+
unlock: {
|
|
101
|
+
id: 'Unlock',
|
|
102
|
+
defaultMessage: 'Unlock',
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
const toolbarComponents = {
|
|
107
|
+
personalTools: { component: PersonalTools, wrapper: null },
|
|
108
|
+
more: { component: More, wrapper: null },
|
|
109
|
+
types: { component: Types, wrapper: null, contentAsProps: true },
|
|
110
|
+
profile: {
|
|
111
|
+
component: PersonalInformation,
|
|
112
|
+
wrapper: StandardWrapper,
|
|
113
|
+
wrapperTitle: messages.personalInformation,
|
|
114
|
+
hideToolbarBody: true,
|
|
115
|
+
},
|
|
116
|
+
preferences: {
|
|
117
|
+
component: PersonalPreferences,
|
|
118
|
+
wrapper: StandardWrapper,
|
|
119
|
+
wrapperTitle: messages.personalPreferences,
|
|
120
|
+
hideToolbarBody: true,
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Toolbar container class.
|
|
126
|
+
* @class Toolbar
|
|
127
|
+
* @extends Component
|
|
128
|
+
*/
|
|
129
|
+
class Toolbar extends Component {
|
|
130
|
+
/**
|
|
131
|
+
* Property types.
|
|
132
|
+
* @property {Object} propTypes Property types.
|
|
133
|
+
* @static
|
|
134
|
+
*/
|
|
135
|
+
static propTypes = {
|
|
136
|
+
actions: PropTypes.shape({
|
|
137
|
+
object: PropTypes.arrayOf(PropTypes.object),
|
|
138
|
+
object_buttons: PropTypes.arrayOf(PropTypes.object),
|
|
139
|
+
user: PropTypes.arrayOf(PropTypes.object),
|
|
140
|
+
}),
|
|
141
|
+
token: PropTypes.string,
|
|
142
|
+
userId: PropTypes.string,
|
|
143
|
+
pathname: PropTypes.string.isRequired,
|
|
144
|
+
content: PropTypes.shape({
|
|
145
|
+
'@type': PropTypes.string,
|
|
146
|
+
is_folderish: PropTypes.bool,
|
|
147
|
+
review_state: PropTypes.string,
|
|
148
|
+
}),
|
|
149
|
+
getTypes: PropTypes.func.isRequired,
|
|
150
|
+
types: PropTypes.arrayOf(
|
|
151
|
+
PropTypes.shape({
|
|
152
|
+
'@id': PropTypes.string,
|
|
153
|
+
addable: PropTypes.bool,
|
|
154
|
+
title: PropTypes.string,
|
|
155
|
+
}),
|
|
156
|
+
),
|
|
157
|
+
listActions: PropTypes.func.isRequired,
|
|
158
|
+
unlockContent: PropTypes.func,
|
|
159
|
+
unlockRequest: PropTypes.objectOf(PropTypes.any),
|
|
160
|
+
inner: PropTypes.element.isRequired,
|
|
161
|
+
hideDefaultViewButtons: PropTypes.bool,
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Default properties.
|
|
166
|
+
* @property {Object} defaultProps Default properties.
|
|
167
|
+
* @static
|
|
168
|
+
*/
|
|
169
|
+
static defaultProps = {
|
|
170
|
+
actions: null,
|
|
171
|
+
token: null,
|
|
172
|
+
userId: null,
|
|
173
|
+
content: null,
|
|
174
|
+
hideDefaultViewButtons: false,
|
|
175
|
+
types: [],
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
toolbarWindow = React.createRef();
|
|
179
|
+
|
|
180
|
+
constructor(props) {
|
|
181
|
+
super(props);
|
|
182
|
+
const { cookies } = props;
|
|
183
|
+
this.state = {
|
|
184
|
+
expanded: cookies.get('toolbar_expanded') !== 'false',
|
|
185
|
+
showMenu: false,
|
|
186
|
+
menuStyle: {},
|
|
187
|
+
menuComponents: [],
|
|
188
|
+
loadedComponents: [],
|
|
189
|
+
hideToolbarBody: false,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Component will mount
|
|
195
|
+
* @method componentDidMount
|
|
196
|
+
* @returns {undefined}
|
|
197
|
+
*/
|
|
198
|
+
componentDidMount() {
|
|
199
|
+
this.props.listActions(getBaseUrl(this.props.pathname));
|
|
200
|
+
this.props.getTypes(getBaseUrl(this.props.pathname));
|
|
201
|
+
this.props.setExpandedToolbar(this.state.expanded);
|
|
202
|
+
document.addEventListener('mousedown', this.handleClickOutside, false);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Component will receive props
|
|
207
|
+
* @method componentWillReceiveProps
|
|
208
|
+
* @param {Object} nextProps Next properties
|
|
209
|
+
* @returns {undefined}
|
|
210
|
+
*/
|
|
211
|
+
UNSAFE_componentWillReceiveProps(nextProps) {
|
|
212
|
+
if (nextProps.pathname !== this.props.pathname) {
|
|
213
|
+
this.props.listActions(getBaseUrl(nextProps.pathname));
|
|
214
|
+
this.props.getTypes(getBaseUrl(nextProps.pathname));
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Unlock
|
|
218
|
+
if (this.props.unlockRequest.loading && nextProps.unlockRequest.loaded) {
|
|
219
|
+
this.props.listActions(getBaseUrl(nextProps.pathname));
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Component will receive props
|
|
225
|
+
* @method componentWillUnmount
|
|
226
|
+
* @returns {undefined}
|
|
227
|
+
*/
|
|
228
|
+
componentWillUnmount() {
|
|
229
|
+
document.removeEventListener('mousedown', this.handleClickOutside, false);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
handleShrink = () => {
|
|
233
|
+
const { cookies } = this.props;
|
|
234
|
+
cookies.set('toolbar_expanded', !this.state.expanded, getCookieOptions());
|
|
235
|
+
this.setState(
|
|
236
|
+
(state) => ({ expanded: !state.expanded }),
|
|
237
|
+
() => this.props.setExpandedToolbar(this.state.expanded),
|
|
238
|
+
);
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
closeMenu = () =>
|
|
242
|
+
this.setState(() => ({ showMenu: false, loadedComponents: [] }));
|
|
243
|
+
|
|
244
|
+
loadComponent = (type) => {
|
|
245
|
+
const { loadedComponents } = this.state;
|
|
246
|
+
if (!this.state.loadedComponents.includes(type)) {
|
|
247
|
+
this.setState({
|
|
248
|
+
loadedComponents: [...loadedComponents, type],
|
|
249
|
+
hideToolbarBody: toolbarComponents[type].hideToolbarBody || false,
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
unloadComponent = () => {
|
|
255
|
+
this.setState((state) => ({
|
|
256
|
+
loadedComponents: state.loadedComponents.slice(0, -1),
|
|
257
|
+
hideToolbarBody:
|
|
258
|
+
toolbarComponents[
|
|
259
|
+
state.loadedComponents[state.loadedComponents.length - 2]
|
|
260
|
+
].hideToolbarBody || false,
|
|
261
|
+
}));
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
toggleMenu = (e, selector) => {
|
|
265
|
+
if (this.state.showMenu) {
|
|
266
|
+
this.closeMenu();
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
// PersonalTools always shows at bottom
|
|
270
|
+
if (selector === 'personalTools') {
|
|
271
|
+
this.setState((state) => ({
|
|
272
|
+
showMenu: !state.showMenu,
|
|
273
|
+
menuStyle: { bottom: 0 },
|
|
274
|
+
}));
|
|
275
|
+
} else {
|
|
276
|
+
this.setState((state) => ({
|
|
277
|
+
showMenu: !state.showMenu,
|
|
278
|
+
menuStyle: { top: 0 },
|
|
279
|
+
}));
|
|
280
|
+
}
|
|
281
|
+
this.loadComponent(selector);
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
handleClickOutside = (e) => {
|
|
285
|
+
if (this.pusher && doesNodeContainClick(this.pusher, e)) return;
|
|
286
|
+
this.closeMenu();
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
unlock = (e) => {
|
|
290
|
+
this.props.unlockContent(getBaseUrl(this.props.pathname), true);
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Render method.
|
|
295
|
+
* @method render
|
|
296
|
+
* @returns {string} Markup for the component.
|
|
297
|
+
*/
|
|
298
|
+
render() {
|
|
299
|
+
const path = getBaseUrl(this.props.pathname);
|
|
300
|
+
const lock = this.props.content?.lock;
|
|
301
|
+
const unlockAction =
|
|
302
|
+
lock?.locked && lock?.stealable && lock?.creator !== this.props.userId;
|
|
303
|
+
const editAction =
|
|
304
|
+
!unlockAction && find(this.props.actions.object, { id: 'edit' });
|
|
305
|
+
const folderContentsAction = find(this.props.actions.object, {
|
|
306
|
+
id: 'folderContents',
|
|
307
|
+
});
|
|
308
|
+
const { expanded } = this.state;
|
|
309
|
+
|
|
310
|
+
return (
|
|
311
|
+
this.props.token && (
|
|
312
|
+
<>
|
|
313
|
+
<BodyClass
|
|
314
|
+
className={expanded ? 'has-toolbar' : 'has-toolbar-collapsed'}
|
|
315
|
+
/>
|
|
316
|
+
<div
|
|
317
|
+
style={this.state.menuStyle}
|
|
318
|
+
className={
|
|
319
|
+
this.state.showMenu ? 'toolbar-content show' : 'toolbar-content'
|
|
320
|
+
}
|
|
321
|
+
ref={this.toolbarWindow}
|
|
322
|
+
>
|
|
323
|
+
{this.state.showMenu && (
|
|
324
|
+
// This sets the scroll locker in the body tag in mobile
|
|
325
|
+
<BodyClass className="has-toolbar-menu-open" />
|
|
326
|
+
)}
|
|
327
|
+
<div
|
|
328
|
+
className="pusher-puller"
|
|
329
|
+
ref={(node) => (this.pusher = node)}
|
|
330
|
+
style={{
|
|
331
|
+
transform: this.toolbarWindow.current
|
|
332
|
+
? `translateX(-${
|
|
333
|
+
(this.state.loadedComponents.length - 1) *
|
|
334
|
+
this.toolbarWindow.current.getBoundingClientRect().width
|
|
335
|
+
}px)`
|
|
336
|
+
: null,
|
|
337
|
+
}}
|
|
338
|
+
>
|
|
339
|
+
{this.state.loadedComponents.map((component, index) =>
|
|
340
|
+
(() => {
|
|
341
|
+
const ToolbarComponent =
|
|
342
|
+
toolbarComponents[component].component;
|
|
343
|
+
const WrapperComponent = toolbarComponents[component].wrapper;
|
|
344
|
+
const haveActions =
|
|
345
|
+
toolbarComponents[component].hideToolbarBody;
|
|
346
|
+
const title =
|
|
347
|
+
toolbarComponents[component].wrapperTitle &&
|
|
348
|
+
this.props.intl.formatMessage(
|
|
349
|
+
toolbarComponents[component].wrapperTitle,
|
|
350
|
+
);
|
|
351
|
+
if (WrapperComponent) {
|
|
352
|
+
return (
|
|
353
|
+
<WrapperComponent
|
|
354
|
+
componentName={component}
|
|
355
|
+
componentTitle={title}
|
|
356
|
+
pathname={this.props.pathname}
|
|
357
|
+
loadComponent={this.loadComponent}
|
|
358
|
+
unloadComponent={this.unloadComponent}
|
|
359
|
+
componentIndex={index}
|
|
360
|
+
theToolbar={this.toolbarWindow}
|
|
361
|
+
key={`personalToolsComponent-${index}`}
|
|
362
|
+
closeMenu={this.closeMenu}
|
|
363
|
+
hasActions={haveActions}
|
|
364
|
+
>
|
|
365
|
+
<ToolbarComponent
|
|
366
|
+
pathname={this.props.pathname}
|
|
367
|
+
loadComponent={this.loadComponent}
|
|
368
|
+
unloadComponent={this.unloadComponent}
|
|
369
|
+
componentIndex={index}
|
|
370
|
+
theToolbar={this.toolbarWindow}
|
|
371
|
+
closeMenu={this.closeMenu}
|
|
372
|
+
isToolbarEmbedded
|
|
373
|
+
/>
|
|
374
|
+
</WrapperComponent>
|
|
375
|
+
);
|
|
376
|
+
} else {
|
|
377
|
+
return (
|
|
378
|
+
<ToolbarComponent
|
|
379
|
+
pathname={this.props.pathname}
|
|
380
|
+
loadComponent={this.loadComponent}
|
|
381
|
+
unloadComponent={this.unloadComponent}
|
|
382
|
+
componentIndex={index}
|
|
383
|
+
theToolbar={this.toolbarWindow}
|
|
384
|
+
key={`personalToolsComponent-${index}`}
|
|
385
|
+
closeMenu={this.closeMenu}
|
|
386
|
+
content={
|
|
387
|
+
toolbarComponents[component].contentAsProps
|
|
388
|
+
? this.props.content
|
|
389
|
+
: null
|
|
390
|
+
}
|
|
391
|
+
/>
|
|
392
|
+
);
|
|
393
|
+
}
|
|
394
|
+
})(),
|
|
395
|
+
)}
|
|
396
|
+
</div>
|
|
397
|
+
</div>
|
|
398
|
+
<div className={this.state.expanded ? 'toolbar expanded' : 'toolbar'}>
|
|
399
|
+
<div className="toolbar-body">
|
|
400
|
+
<div className="toolbar-actions">
|
|
401
|
+
{this.props.hideDefaultViewButtons && this.props.inner && (
|
|
402
|
+
<>{this.props.inner}</>
|
|
403
|
+
)}
|
|
404
|
+
{!this.props.hideDefaultViewButtons && (
|
|
405
|
+
<>
|
|
406
|
+
{unlockAction && (
|
|
407
|
+
<button
|
|
408
|
+
aria-label={this.props.intl.formatMessage(
|
|
409
|
+
messages.unlock,
|
|
410
|
+
)}
|
|
411
|
+
className="unlock"
|
|
412
|
+
onClick={(e) => this.unlock(e)}
|
|
413
|
+
tabIndex={0}
|
|
414
|
+
>
|
|
415
|
+
<Icon
|
|
416
|
+
name={unlockSVG}
|
|
417
|
+
size="30px"
|
|
418
|
+
className="unlock"
|
|
419
|
+
title={this.props.intl.formatMessage(messages.unlock)}
|
|
420
|
+
/>
|
|
421
|
+
</button>
|
|
422
|
+
)}
|
|
423
|
+
|
|
424
|
+
{editAction && (
|
|
425
|
+
<Link
|
|
426
|
+
aria-label={this.props.intl.formatMessage(
|
|
427
|
+
messages.edit,
|
|
428
|
+
)}
|
|
429
|
+
className="edit"
|
|
430
|
+
to={`${path}/edit`}
|
|
431
|
+
>
|
|
432
|
+
<Icon
|
|
433
|
+
name={penSVG}
|
|
434
|
+
size="30px"
|
|
435
|
+
className="circled"
|
|
436
|
+
title={this.props.intl.formatMessage(messages.edit)}
|
|
437
|
+
/>
|
|
438
|
+
</Link>
|
|
439
|
+
)}
|
|
440
|
+
{this.props.content &&
|
|
441
|
+
this.props.content.is_folderish &&
|
|
442
|
+
folderContentsAction &&
|
|
443
|
+
!this.props.pathname.endsWith('/contents') && (
|
|
444
|
+
<Link
|
|
445
|
+
aria-label={this.props.intl.formatMessage(
|
|
446
|
+
messages.contents,
|
|
447
|
+
)}
|
|
448
|
+
to={`${path}/contents`}
|
|
449
|
+
>
|
|
450
|
+
<Icon
|
|
451
|
+
name={folderSVG}
|
|
452
|
+
size="30px"
|
|
453
|
+
title={this.props.intl.formatMessage(
|
|
454
|
+
messages.contents,
|
|
455
|
+
)}
|
|
456
|
+
/>
|
|
457
|
+
</Link>
|
|
458
|
+
)}
|
|
459
|
+
{this.props.content &&
|
|
460
|
+
this.props.content.is_folderish &&
|
|
461
|
+
folderContentsAction &&
|
|
462
|
+
this.props.pathname.endsWith('/contents') && (
|
|
463
|
+
<Link
|
|
464
|
+
to={`${path}`}
|
|
465
|
+
aria-label={this.props.intl.formatMessage(
|
|
466
|
+
messages.back,
|
|
467
|
+
)}
|
|
468
|
+
>
|
|
469
|
+
<Icon
|
|
470
|
+
name={clearSVG}
|
|
471
|
+
className="contents circled"
|
|
472
|
+
size="30px"
|
|
473
|
+
title={this.props.intl.formatMessage(messages.back)}
|
|
474
|
+
/>
|
|
475
|
+
</Link>
|
|
476
|
+
)}
|
|
477
|
+
{this.props.content &&
|
|
478
|
+
((this.props.content.is_folderish &&
|
|
479
|
+
this.props.types.length > 0) ||
|
|
480
|
+
(config.settings.isMultilingual &&
|
|
481
|
+
this.props.content['@components']?.translations)) && (
|
|
482
|
+
<button
|
|
483
|
+
className="add"
|
|
484
|
+
aria-label={this.props.intl.formatMessage(
|
|
485
|
+
messages.add,
|
|
486
|
+
)}
|
|
487
|
+
onClick={(e) => this.toggleMenu(e, 'types')}
|
|
488
|
+
tabIndex={0}
|
|
489
|
+
id="toolbar-add"
|
|
490
|
+
>
|
|
491
|
+
<Icon
|
|
492
|
+
name={addSVG}
|
|
493
|
+
size="30px"
|
|
494
|
+
title={this.props.intl.formatMessage(messages.add)}
|
|
495
|
+
/>
|
|
496
|
+
</button>
|
|
497
|
+
)}
|
|
498
|
+
<div className="toolbar-button-spacer" />
|
|
499
|
+
<button
|
|
500
|
+
className="more"
|
|
501
|
+
aria-label={this.props.intl.formatMessage(messages.more)}
|
|
502
|
+
onClick={(e) => this.toggleMenu(e, 'more')}
|
|
503
|
+
tabIndex={0}
|
|
504
|
+
id="toolbar-more"
|
|
505
|
+
>
|
|
506
|
+
<Icon
|
|
507
|
+
className="mobile hidden"
|
|
508
|
+
name={moreSVG}
|
|
509
|
+
size="30px"
|
|
510
|
+
title={this.props.intl.formatMessage(messages.more)}
|
|
511
|
+
/>
|
|
512
|
+
{this.state.showMenu ? (
|
|
513
|
+
<Icon
|
|
514
|
+
className="mobile only"
|
|
515
|
+
name={clearSVG}
|
|
516
|
+
size="30px"
|
|
517
|
+
/>
|
|
518
|
+
) : (
|
|
519
|
+
<Icon
|
|
520
|
+
className="mobile only"
|
|
521
|
+
name={moreSVG}
|
|
522
|
+
size="30px"
|
|
523
|
+
/>
|
|
524
|
+
)}
|
|
525
|
+
</button>
|
|
526
|
+
</>
|
|
527
|
+
)}
|
|
528
|
+
</div>
|
|
529
|
+
<div className="toolbar-bottom">
|
|
530
|
+
<Pluggable name="main.toolbar.bottom" />
|
|
531
|
+
{!this.props.hideDefaultViewButtons && (
|
|
532
|
+
<button
|
|
533
|
+
className="user"
|
|
534
|
+
aria-label={this.props.intl.formatMessage(
|
|
535
|
+
messages.personalTools,
|
|
536
|
+
)}
|
|
537
|
+
onClick={(e) => this.toggleMenu(e, 'personalTools')}
|
|
538
|
+
tabIndex={0}
|
|
539
|
+
id="toolbar-personal"
|
|
540
|
+
>
|
|
541
|
+
<Icon
|
|
542
|
+
name={userSVG}
|
|
543
|
+
size="30px"
|
|
544
|
+
title={this.props.intl.formatMessage(
|
|
545
|
+
messages.personalTools,
|
|
546
|
+
)}
|
|
547
|
+
/>
|
|
548
|
+
</button>
|
|
549
|
+
)}
|
|
550
|
+
</div>
|
|
551
|
+
</div>
|
|
552
|
+
<div className="toolbar-handler">
|
|
553
|
+
<button
|
|
554
|
+
aria-label={this.props.intl.formatMessage(
|
|
555
|
+
messages.shrinkToolbar,
|
|
556
|
+
)}
|
|
557
|
+
className={cx({
|
|
558
|
+
[this.props.content?.review_state]: this.props.content
|
|
559
|
+
?.review_state,
|
|
560
|
+
})}
|
|
561
|
+
onClick={this.handleShrink}
|
|
562
|
+
/>
|
|
563
|
+
</div>
|
|
564
|
+
</div>
|
|
565
|
+
<div className="pusher" />
|
|
566
|
+
</>
|
|
567
|
+
)
|
|
568
|
+
);
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
export default compose(
|
|
573
|
+
injectIntl,
|
|
574
|
+
withCookies,
|
|
575
|
+
connect(
|
|
576
|
+
(state, props) => ({
|
|
577
|
+
actions: state.actions.actions,
|
|
578
|
+
token: state.userSession.token,
|
|
579
|
+
userId: state.userSession.token
|
|
580
|
+
? jwtDecode(state.userSession.token).sub
|
|
581
|
+
: '',
|
|
582
|
+
content: state.content.data,
|
|
583
|
+
pathname: props.pathname,
|
|
584
|
+
types: filter(state.types.types, 'addable'),
|
|
585
|
+
unlockRequest: state.content.unlock,
|
|
586
|
+
}),
|
|
587
|
+
{ getTypes, listActions, setExpandedToolbar, unlockContent },
|
|
588
|
+
),
|
|
589
|
+
)(Toolbar);
|
package/src/index.js
CHANGED
|
@@ -2,6 +2,7 @@ import { runtimeConfig } from '@plone/volto/runtime_config';
|
|
|
2
2
|
import installCallout from 'volto-slate/editor/plugins/Callout';
|
|
3
3
|
import installItemBlock from '@eeacms/volto-eea-website-policy/components/Blocks/Item';
|
|
4
4
|
import customizeTeaserBlock from '@eeacms/volto-eea-website-policy/components/Blocks/Teaser';
|
|
5
|
+
import installContextNavigationBlock from '@eeacms/volto-eea-website-policy/components/Blocks/ContextNavigation';
|
|
5
6
|
|
|
6
7
|
const applyConfig = (config) => {
|
|
7
8
|
// if (process.env.NODE_ENV === 'production') {
|
|
@@ -99,10 +100,11 @@ const applyConfig = (config) => {
|
|
|
99
100
|
}
|
|
100
101
|
|
|
101
102
|
// Custom blocks
|
|
102
|
-
config = [
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
103
|
+
config = [
|
|
104
|
+
installItemBlock,
|
|
105
|
+
installContextNavigationBlock,
|
|
106
|
+
customizeTeaserBlock,
|
|
107
|
+
].reduce((acc, apply) => apply(acc), config);
|
|
106
108
|
config.blocks.blocksConfig.item.mostUsed = true;
|
|
107
109
|
|
|
108
110
|
// Disable some blocks
|