@eeacms/volto-marine-policy 1.1.0 → 1.1.2

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 CHANGED
@@ -4,12 +4,33 @@ 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
+ ### [1.1.2](https://github.com/eea/volto-marine-policy/compare/1.1.1...1.1.2) - 22 April 2024
8
+
9
+ #### :hammer_and_wrench: Others
10
+
11
+ - update header customizations with eea design, fix logo width [nileshgulia1 - [`8187c47`](https://github.com/eea/volto-marine-policy/commit/8187c47c860a7efda632ed050d854e6a42e7e3a0)]
12
+ ### [1.1.1](https://github.com/eea/volto-marine-policy/compare/1.1.0...1.1.1) - 19 April 2024
13
+
14
+ #### :rocket: New Features
15
+
16
+ - feat:install contextNavigation block,fix toc block [nileshgulia1 - [`46bf29c`](https://github.com/eea/volto-marine-policy/commit/46bf29cee029a343e87d8b2a3e0adeba61ec04d9)]
17
+
18
+ #### :bug: Bug Fixes
19
+
20
+ - fix: add tests [nileshgulia1 - [`6ea02e3`](https://github.com/eea/volto-marine-policy/commit/6ea02e300fdc45b9921aeccf34ce746b11390005)]
21
+
22
+ #### :hammer_and_wrench: Others
23
+
24
+ - update [nileshgulia1 - [`33ee2a0`](https://github.com/eea/volto-marine-policy/commit/33ee2a00edaf2dadc088e5cc16f5d565484ce357)]
25
+ - eslint . [nileshgulia1 - [`dba2fc6`](https://github.com/eea/volto-marine-policy/commit/dba2fc6697b36506d3b86b9647cd7fd5d9d0d17d)]
26
+ - update tests [nileshgulia1 - [`b668e15`](https://github.com/eea/volto-marine-policy/commit/b668e15bd5aa2b0b9a419fcfa8a9ab6bfe6a5fb6)]
27
+ - remove comment [nileshgulia1 - [`6deadba`](https://github.com/eea/volto-marine-policy/commit/6deadbabbe99cf5a1f7e1b480076bdcaad333921)]
28
+ - fix tests [nileshgulia1 - [`2db4819`](https://github.com/eea/volto-marine-policy/commit/2db4819596c8a1727cdb37f0fc33ba53ea757aef)]
7
29
  ### [1.1.0](https://github.com/eea/volto-marine-policy/compare/1.0.0...1.1.0) - 15 April 2024
8
30
 
9
31
  #### :hammer_and_wrench: Others
10
32
 
11
33
  - fix cypress [nileshgulia1 - [`9d588e7`](https://github.com/eea/volto-marine-policy/commit/9d588e7e9ba1cf258c4356a3d25bcc6f1ae98356)]
12
- - bump version [nileshgulia1 - [`55f8b71`](https://github.com/eea/volto-marine-policy/commit/55f8b7144a8c41fcd6ee327660dfd0eb512fb0ea)]
13
34
  - add policy customizations [nileshgulia1 - [`8355128`](https://github.com/eea/volto-marine-policy/commit/8355128ef8c713d86261ce57d709250a38213ef6)]
14
35
  - delete tpl files [nileshgulia1 - [`d21afd0`](https://github.com/eea/volto-marine-policy/commit/d21afd0ae83ad54240bea00e68656c1b87630d8e)]
15
36
  ## [1.0.0](https://github.com/eea/volto-marine-policy/compare/0.1.20...1.0.0) - 14 April 2024
@@ -36,10 +36,10 @@ module.exports = {
36
36
  },
37
37
  coverageThreshold: {
38
38
  global: {
39
- branches: 5,
40
- functions: 5,
41
- lines: 5,
42
- statements: 5,
39
+ branches: 1,
40
+ functions: 1,
41
+ lines: 1,
42
+ statements: 1,
43
43
  },
44
44
  },
45
45
  ...(process.env.JEST_USE_SETUP === 'ON' && {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeacms/volto-marine-policy",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "description": "@eeacms/volto-marine-policy: Volto add-on",
5
5
  "main": "src/index.js",
6
6
  "author": "European Environment Agency: IDM2 A-Team",
@@ -0,0 +1,83 @@
1
+ import React from 'react';
2
+ import { Accordion as SemanticAccordion, Icon } from 'semantic-ui-react';
3
+
4
+ import AccordionContent from './AccordionContent';
5
+ import { useHistory } from 'react-router-dom';
6
+
7
+ const Accordion = (props) => {
8
+ const { items = {}, curent_location, activeMenu, data = {} } = props;
9
+ const [currentIndex, setIndex] = React.useState(activeMenu ?? 0);
10
+ const history = useHistory();
11
+
12
+ const handleClick = (e, item) => {
13
+ let itemUrl = '/' + item['@id'].split('/').slice(3).join('/');
14
+ history.push(itemUrl);
15
+ };
16
+
17
+ const handleIconClick = (e, index) => {
18
+ e.stopPropagation();
19
+ const newIndex = currentIndex === index ? -1 : index;
20
+ setIndex(newIndex);
21
+ };
22
+ return (
23
+ <>
24
+ <div className="context-navigation-header">{data?.title}</div>
25
+ {items.map((item, index) => {
26
+ const { id } = item;
27
+ const active = currentIndex === index;
28
+
29
+ return (
30
+ <SemanticAccordion id={id} key={index} className="secondary">
31
+ <SemanticAccordion.Title
32
+ role="button"
33
+ tabIndex={0}
34
+ active={activeMenu === index}
35
+ aria-expanded={activeMenu === index}
36
+ index={index}
37
+ onClick={(e) => {
38
+ handleClick(e, item);
39
+ }}
40
+ onKeyDown={(e) => {
41
+ if (e.keyCode === 13 || e.keyCode === 32) {
42
+ e.preventDefault();
43
+ handleClick(e, item);
44
+ }
45
+ }}
46
+ >
47
+ <span className="item-title">{item.title}</span>
48
+ {active ? (
49
+ <Icon
50
+ className="ri-arrow-up-s-line"
51
+ onClick={(e) => {
52
+ handleIconClick(e, index);
53
+ }}
54
+ />
55
+ ) : (
56
+ <Icon
57
+ className="ri-arrow-down-s-line"
58
+ onClick={(e) => {
59
+ handleIconClick(e, index);
60
+ }}
61
+ />
62
+ )}
63
+ </SemanticAccordion.Title>
64
+ <SemanticAccordion.Content active={active}>
65
+ <AccordionContent
66
+ curent_location={curent_location}
67
+ key={index}
68
+ main={{
69
+ title: item.title,
70
+ href: item['@id'],
71
+ url: item.url,
72
+ }}
73
+ data={data}
74
+ />
75
+ </SemanticAccordion.Content>
76
+ </SemanticAccordion>
77
+ );
78
+ })}
79
+ </>
80
+ );
81
+ };
82
+
83
+ export default Accordion;
@@ -0,0 +1,47 @@
1
+ import React from 'react';
2
+ import { MemoryRouter } from 'react-router-dom';
3
+ import configureStore from 'redux-mock-store';
4
+ import { render } from '@testing-library/react';
5
+ import '@testing-library/jest-dom/extend-expect';
6
+ import { Provider } from 'react-intl-redux';
7
+ import Accordion from './Accordion';
8
+
9
+ const mockStore = configureStore();
10
+
11
+ describe('RASTAccordion', () => {
12
+ it('should render the component', () => {
13
+ const data = {
14
+ items: [
15
+ {
16
+ id: 'my-item',
17
+ title: 'Hello',
18
+ '@id': '/my-item',
19
+ '@type': 'Folder',
20
+ href: '/my-item-href',
21
+ },
22
+ ],
23
+ activeMenu: 1,
24
+ curent_location: '/my-item-href',
25
+ };
26
+
27
+ const store = mockStore({
28
+ userSession: { token: '1234' },
29
+ intl: {
30
+ locale: 'en',
31
+ messages: {},
32
+ },
33
+ content: {
34
+ subrequests: {},
35
+ },
36
+ });
37
+
38
+ const { container } = render(
39
+ <Provider store={store}>
40
+ <MemoryRouter>
41
+ <Accordion {...data} />
42
+ </MemoryRouter>
43
+ </Provider>,
44
+ );
45
+ expect(container.querySelector('.accordion')).toBeInTheDocument();
46
+ });
47
+ });
@@ -0,0 +1,57 @@
1
+ import React from 'react';
2
+ import { List } from 'semantic-ui-react';
3
+ import { Link } from 'react-router-dom';
4
+ import { compose } from 'redux';
5
+ import { flattenToAppURL, getBaseUrl } from '@plone/volto/helpers';
6
+ import { useChildren } from './View';
7
+
8
+ const AccordionContent = (props) => {
9
+ const {
10
+ main,
11
+ curent_location,
12
+ data: { types = [] },
13
+ } = props;
14
+ const location = main.url;
15
+
16
+ // React.useEffect(() => {
17
+ // const action = getContent(location, null, location);
18
+ // dispatch(action);
19
+ // }, [location, dispatch]);
20
+
21
+ // items = useSelector(
22
+ // (state) => state.content?.subrequests?.[location]?.data?.items || [],
23
+ // );
24
+ const items = useChildren(location);
25
+ return (
26
+ <div className="dataset-content">
27
+ <div>
28
+ {items.length
29
+ ? items
30
+ .filter((item) =>
31
+ types.length ? types.includes(item['@type']) : item,
32
+ )
33
+ .map((item) => (
34
+ <List.Item
35
+ key={item.id}
36
+ className={`${
37
+ item['@id'].endsWith(curent_location.pathname)
38
+ ? 'active'
39
+ : ''
40
+ }`}
41
+ >
42
+ <List.Content>
43
+ <div className="dataset-item">
44
+ <Link to={flattenToAppURL(getBaseUrl(item['@id']))}>
45
+ {item.title}
46
+ </Link>
47
+ </div>
48
+ </List.Content>
49
+ </List.Item>
50
+ ))
51
+ : null}
52
+ </div>
53
+ </div>
54
+ );
55
+ };
56
+
57
+ export default compose()(AccordionContent);
@@ -0,0 +1,41 @@
1
+ import React from 'react';
2
+ import { compose } from 'redux';
3
+
4
+ import Accordion from './Accordion';
5
+ import { useLocation } from 'react-router-dom';
6
+
7
+ /**
8
+ * A navigation slot implementation, similar to the classic Plone navigation
9
+ * portlet. It uses the same API, so the options are similar to
10
+ * INavigationPortlet
11
+ */
12
+ export function ContextNavigationComponent(props) {
13
+ const { items, data } = props;
14
+ let activeMenu = null;
15
+
16
+ const curent_location = useLocation();
17
+ for (let i = 0; i < items.length; i++) {
18
+ let itemUrl = '/' + items[i]['@id'].split('/').slice(3).join('/');
19
+ items[i].is_active = false;
20
+ if (curent_location.pathname.includes(itemUrl)) {
21
+ activeMenu = i;
22
+ items[i].is_active = true;
23
+ }
24
+ }
25
+
26
+ return (
27
+ <>
28
+ {items.length ? (
29
+ <Accordion
30
+ items={items}
31
+ curent_location={curent_location}
32
+ activeMenu={activeMenu}
33
+ data={data}
34
+ />
35
+ ) : null}
36
+ </>
37
+ );
38
+ }
39
+
40
+ // withContentNavigation
41
+ export default compose()(ContextNavigationComponent);
@@ -0,0 +1,41 @@
1
+ import React from 'react';
2
+ import { useSelector } from 'react-redux';
3
+ import { SidebarPortal } from '@plone/volto/components';
4
+ import BlockDataForm from '@plone/volto/components/manage/Form/BlockDataForm';
5
+
6
+ import View from './View';
7
+ import schema from './schema';
8
+
9
+ export default function Edit(props) {
10
+ const {
11
+ block,
12
+ data = {},
13
+ onChangeBlock,
14
+ selected,
15
+ id,
16
+ formData = {},
17
+ } = props;
18
+ const contentTypes = useSelector((state) => state?.types.types);
19
+ const blockSchema = schema({ formData, data, contentTypes });
20
+
21
+ return (
22
+ <div>
23
+ <View data={data} id={id} mode="edit" />
24
+ <SidebarPortal selected={selected}>
25
+ <BlockDataForm
26
+ block={block}
27
+ title={blockSchema.title}
28
+ schema={blockSchema}
29
+ onChangeField={(id, value) => {
30
+ onChangeBlock(block, {
31
+ ...data,
32
+ [id]: value,
33
+ });
34
+ }}
35
+ onChangeBlock={onChangeBlock}
36
+ formData={data}
37
+ />
38
+ </SidebarPortal>
39
+ </div>
40
+ );
41
+ }
@@ -0,0 +1,71 @@
1
+ import React from 'react';
2
+ import { render } from '@testing-library/react';
3
+ import { Provider } from 'react-intl-redux';
4
+ import configureStore from 'redux-mock-store';
5
+ import ContextNavigationEdit from './Edit';
6
+ import { Router } from 'react-router-dom';
7
+ import { createMemoryHistory } from 'history';
8
+ import '@testing-library/jest-dom/extend-expect';
9
+
10
+ const mockStore = configureStore();
11
+
12
+ jest.mock('@plone/volto/components', () => ({
13
+ SidebarPortal: ({ children }) => (
14
+ <div>
15
+ <div>SidebarPortal</div>
16
+ {children}
17
+ </div>
18
+ ),
19
+ }));
20
+
21
+ jest.mock('@plone/volto/components/manage/Form/BlockDataForm', () => {
22
+ return {
23
+ __esModule: true,
24
+ default: ({ params }) => {
25
+ return <div>BlockDataForm {params}</div>;
26
+ },
27
+ };
28
+ });
29
+
30
+ const store = mockStore({
31
+ userSession: { token: '1234' },
32
+ intl: {
33
+ locale: 'en',
34
+ messages: {},
35
+ },
36
+ content: {
37
+ subrequests: {},
38
+ },
39
+ types: {
40
+ types: [],
41
+ },
42
+ });
43
+
44
+ describe('ContextNavigationEdit', () => {
45
+ it('renders corectly', () => {
46
+ const history = createMemoryHistory();
47
+ const { getByText } = render(
48
+ <Provider store={store}>
49
+ <Router history={history}>
50
+ <ContextNavigationEdit />
51
+ </Router>
52
+ </Provider>,
53
+ );
54
+
55
+ expect(getByText('SidebarPortal')).toBeInTheDocument();
56
+ });
57
+
58
+ it('renders corectly', () => {
59
+ const history = createMemoryHistory();
60
+ const { getByText } = render(
61
+ <Provider store={store}>
62
+ <Router history={history}>
63
+ <ContextNavigationEdit selected={true} onChangeBlock={() => {}} />
64
+ </Router>
65
+ </Provider>,
66
+ );
67
+
68
+ // expect(getByText('InlineForm')).toBeInTheDocument();
69
+ expect(getByText('SidebarPortal')).toBeInTheDocument();
70
+ });
71
+ });
@@ -0,0 +1,42 @@
1
+ import React from 'react';
2
+ import './styles.less';
3
+ import ContextNavigation from './ContextNavigation';
4
+ import { useDispatch, useSelector } from 'react-redux';
5
+ import { getContent } from '@plone/volto/actions';
6
+
7
+ export function useChildren(location) {
8
+ const dispatch = useDispatch();
9
+ React.useEffect(() => {
10
+ const action = getContent(location, null, location);
11
+ dispatch(action);
12
+ }, [location, dispatch]);
13
+
14
+ const items = useSelector(
15
+ (state) => state.content.subrequests?.[location]?.data?.items || [],
16
+ );
17
+ return items;
18
+ }
19
+
20
+ export default function View(props) {
21
+ const { data } = props;
22
+ let root_path = data?.root_path;
23
+ if (typeof root_path === 'undefined') {
24
+ root_path = '/';
25
+ }
26
+ let items = useChildren(root_path);
27
+ if (root_path === '/') {
28
+ items = [];
29
+ }
30
+
31
+ return (
32
+ <div className="block rast-block">
33
+ <ContextNavigation
34
+ items={items}
35
+ location={{
36
+ pathname: root_path,
37
+ }}
38
+ data={data}
39
+ />
40
+ </div>
41
+ );
42
+ }
@@ -0,0 +1,71 @@
1
+ import React from 'react';
2
+ import { render } from '@testing-library/react';
3
+ import ContextNavigationView from './View';
4
+ import { Router } from 'react-router-dom';
5
+ import { Provider } from 'react-intl-redux';
6
+ import configureStore from 'redux-mock-store';
7
+ import { createMemoryHistory } from 'history';
8
+ import '@testing-library/jest-dom/extend-expect';
9
+
10
+ const mockStore = configureStore();
11
+
12
+ const store = mockStore({
13
+ userSession: { token: '1234' },
14
+ intl: {
15
+ locale: 'en',
16
+ messages: {},
17
+ },
18
+ content: {
19
+ subrequests: {},
20
+ },
21
+ types: {
22
+ types: {},
23
+ },
24
+ });
25
+
26
+ jest.mock(
27
+ '@eeacms/volto-marine-policy/components/Blocks/ContextNavigation/ContextNavigation',
28
+ () => {
29
+ return {
30
+ __esModule: true,
31
+ default: ({ params }) => {
32
+ return <div>ContextNavigation {params}</div>;
33
+ },
34
+ };
35
+ },
36
+ );
37
+
38
+ describe('ContextNavigationView', () => {
39
+ let history;
40
+ beforeEach(() => {
41
+ history = createMemoryHistory();
42
+ });
43
+
44
+ it('renders corectly', () => {
45
+ const { container } = render(
46
+ <Provider store={store}>
47
+ <Router history={history}>
48
+ <ContextNavigationView />
49
+ </Router>
50
+ </Provider>,
51
+ );
52
+
53
+ expect(container.firstChild).toHaveTextContent('ContextNavigation');
54
+ });
55
+
56
+ it('renders corectly', () => {
57
+ const { container } = render(
58
+ <Provider store={store}>
59
+ <Router history={history}>
60
+ <ContextNavigationView
61
+ data={{
62
+ navProps: { root_path: 'https://localhost:3000/test' },
63
+ root_node: [{ '@id': 'root_node' }],
64
+ }}
65
+ />
66
+ </Router>
67
+ </Provider>,
68
+ );
69
+ expect(container.firstChild).toHaveTextContent('ContextNavigation');
70
+ });
71
+ });
@@ -0,0 +1,25 @@
1
+ import zoomSVG from '@plone/volto/icons/zoom.svg';
2
+ import Edit from './Edit';
3
+ import View from './View';
4
+
5
+ export default function installBlock(config) {
6
+ const blocksConfig = config.blocks.blocksConfig;
7
+
8
+ blocksConfig.contextNavigation = {
9
+ id: 'contextNavigation',
10
+ title: 'Context Navigation',
11
+ icon: zoomSVG,
12
+ group: 'site',
13
+ view: View,
14
+ edit: Edit,
15
+ sidebarTab: 1,
16
+ security: {
17
+ addPermission: [],
18
+ view: [],
19
+ },
20
+ variations: [],
21
+ restricted: false,
22
+ };
23
+
24
+ return config;
25
+ }
@@ -0,0 +1,41 @@
1
+ const fields = ['root_path', 'title', 'types'];
2
+
3
+ export default ({ contentTypes }) => {
4
+ const availableTypes = contentTypes.map((type) => [
5
+ type.id,
6
+ type.title || type.name,
7
+ ]);
8
+ return {
9
+ title: 'RAST',
10
+
11
+ fieldsets: [
12
+ {
13
+ id: 'default',
14
+ title: 'Default',
15
+ fields,
16
+ },
17
+ ],
18
+
19
+ properties: {
20
+ root_path: {
21
+ title: 'Rooth path',
22
+ type: 'string',
23
+ description:
24
+ 'Ex: /en/knowledge-and-data/regional-adaptation-support-tool',
25
+ required: true,
26
+ noValueOption: false,
27
+ },
28
+ title: {
29
+ title: 'Title',
30
+ },
31
+ types: {
32
+ title: 'Display content types',
33
+ description: 'Choose content types displayed as children',
34
+ choices: availableTypes,
35
+ isMulti: true,
36
+ },
37
+ },
38
+
39
+ required: [],
40
+ };
41
+ };
@@ -0,0 +1,65 @@
1
+ @type: 'extra';
2
+ @element: 'custom';
3
+
4
+ @import (multiple, reference, optional) '../../theme.config';
5
+
6
+ .rast-block {
7
+ a rect.circle:hover {
8
+ fill: #183 !important;
9
+ }
10
+
11
+ .ui.accordion[class*='ary'] > .active.title,
12
+ .ui.accordion[class*='ary'].inverted > .title,
13
+ .ui.accordion[class*='ary'].inverted > .icon,
14
+ .ui.accordion[class*='ary'] > .filter {
15
+ --text-color-secondary: #ffffff;
16
+ --text-color-hover: #0079cf;
17
+ --text-color: #0079cf;
18
+ border-bottom: 0.0625rem solid #e6e7e8;
19
+ font-weight: bold;
20
+ }
21
+
22
+ .ui.accordion[class*='ary'] > .title,
23
+ .ui.accordion[class*='ary'].inverted > .title,
24
+ .ui.accordion[class*='ary'].inverted > .icon,
25
+ .ui.accordion[class*='ary'] > .filter {
26
+ color: var(--text-color);
27
+ font-weight: bold;
28
+
29
+ .icon {
30
+ color: var(--text-color);
31
+ }
32
+ }
33
+
34
+ .ui.accordion .content.active {
35
+ --bg-color: #ffffff;
36
+ border-bottom: 0.0625rem solid #e6e7e8;
37
+
38
+ .item > .content {
39
+ &:hover {
40
+ background: #f9f9f9;
41
+
42
+ a {
43
+ color: var(--text-color-hover, #0079cf);
44
+ }
45
+ }
46
+ }
47
+
48
+ a {
49
+ color: var(--text-color);
50
+ }
51
+ }
52
+
53
+ a rect.circle {
54
+ pointer-events: all !important;
55
+ }
56
+
57
+ svg,
58
+ svg * {
59
+ pointer-events: none;
60
+ }
61
+
62
+ .item.active a {
63
+ font-weight: bold;
64
+ }
65
+ }
@@ -262,27 +262,29 @@ const Main = ({
262
262
  <Grid.Column mobile={4} tablet={4} computer={8}>
263
263
  <div className={inverted ? 'main-menu inverted' : 'main-menu'}>
264
264
  {menuItems && (
265
- <ul
266
- className="ui text eea-main-menu tablet or lower hidden menu"
267
- ref={desktopMenuRef}
268
- id={'navigation'}
269
- >
270
- {menuItems.map((item) => (
271
- <Menu.Item
272
- name={item['@id'] || item.url}
273
- key={item['@id'] || item.url}
274
- as={'li'}
275
- active={
276
- activeItem.indexOf(item['@id']) !== -1 ||
277
- activeItem.indexOf(item.url) !== -1
278
- }
279
- >
280
- {renderGlobalMenuItem(item, {
281
- onClick: menuOnClick,
282
- })}
283
- </Menu.Item>
284
- ))}
285
- </ul>
265
+ <nav aria-label={'Main'} className="main-nav">
266
+ <ul
267
+ className="ui text eea-main-menu tablet or lower hidden menu"
268
+ ref={desktopMenuRef}
269
+ id={'navigation'}
270
+ >
271
+ {menuItems.map((item) => (
272
+ <Menu.Item
273
+ name={item['@id'] || item.url}
274
+ key={item['@id'] || item.url}
275
+ as={'li'}
276
+ active={
277
+ activeItem.indexOf(item['@id']) !== -1 ||
278
+ activeItem.indexOf(item.url) !== -1
279
+ }
280
+ >
281
+ {renderGlobalMenuItem(item, {
282
+ onClick: menuOnClick,
283
+ })}
284
+ </Menu.Item>
285
+ ))}
286
+ </ul>
287
+ </nav>
286
288
  )}
287
289
  {!hideSearch && (
288
290
  <button
package/src/index.js CHANGED
@@ -14,6 +14,7 @@ import installMsfdDataExplorerBlock from './components/Blocks/MsfdDataExplorerBl
14
14
  import { breadcrumb, localnavigation } from './reducers';
15
15
  import customBlockTemplates from '@eeacms/volto-marine-policy/components/Blocks/CustomBlockTemplates/customBlockTemplates';
16
16
  import TextAlignWidget from './components/Widgets/TextAlign';
17
+ import installContextNavigation from './components/Blocks/ContextNavigation';
17
18
  import './slate-styles.less';
18
19
 
19
20
  import installSearchEngine from './search';
@@ -26,7 +27,7 @@ import { LinkElement } from '@plone/volto-slate/editor/plugins/AdvancedLink/rend
26
27
  import { withLink } from '@plone/volto-slate/editor/plugins/AdvancedLink/extensions';
27
28
  import { linkDeserializer } from '@plone/volto-slate/editor/plugins/AdvancedLink/deserialize';
28
29
  import LinkEditSchema from '@plone/volto-slate/editor/plugins/AdvancedLink/schema';
29
-
30
+ import { getBlocks } from '@plone/volto/helpers';
30
31
  import { defineMessages } from 'react-intl'; // , defineMessages
31
32
 
32
33
  import marineLogo from '@eeacms/volto-marine-policy/../theme/assets/images/Header/wise-marine-logo.svg';
@@ -263,6 +264,11 @@ const applyConfig = (config) => {
263
264
  },
264
265
  ];
265
266
 
267
+ config.settings.openExternalLinkInNewTab = true;
268
+
269
+ if (config.blocks.blocksConfig.contextNavigation)
270
+ config.blocks.blocksConfig.contextNavigation.restricted = false;
271
+
266
272
  config.settings.pluggableStyles = [
267
273
  ...(config.settings.pluggableStyles || []),
268
274
  {
@@ -426,6 +432,29 @@ const applyConfig = (config) => {
426
432
  organisationName: 'Marine Water Information System for Europe',
427
433
  };
428
434
 
435
+ if (config.blocks.blocksConfig.columnsBlock) {
436
+ config.blocks.blocksConfig.columnsBlock.tocEntries = (
437
+ block = {},
438
+ tocData,
439
+ ) => {
440
+ // integration with volto-block-toc
441
+ const headlines = tocData.levels || ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'];
442
+ let entries = [];
443
+ const sorted_column_blocks = getBlocks(block?.data || {});
444
+ sorted_column_blocks.forEach((column_block) => {
445
+ const sorted_blocks = getBlocks(column_block[1]);
446
+ sorted_blocks.forEach((block) => {
447
+ const { value, plaintext } = block[1];
448
+ const type = value?.[0]?.type;
449
+ if (headlines.includes(type)) {
450
+ entries.push([parseInt(type.slice(1)), plaintext, block[0]]);
451
+ }
452
+ });
453
+ });
454
+ return entries;
455
+ };
456
+ }
457
+
429
458
  // SPMeasure View widget
430
459
  config.views.contentTypesViews.spmeasure = MeasureView;
431
460
 
@@ -456,10 +485,11 @@ const applyConfig = (config) => {
456
485
  const [installLinkEditor] = makeInlineElementPlugin(opts);
457
486
  config = installLinkEditor(config);
458
487
 
459
- const final = [installMsfdDataExplorerBlock, installSearchEngine].reduce(
460
- (acc, apply) => apply(acc),
461
- config,
462
- );
488
+ const final = [
489
+ installMsfdDataExplorerBlock,
490
+ installSearchEngine,
491
+ installContextNavigation,
492
+ ].reduce((acc, apply) => apply(acc), config);
463
493
 
464
494
  return final;
465
495
  };
@@ -2,19 +2,6 @@
2
2
  HEADER MAIN BAR DESKTOP
3
3
  ----------------------------------------------------------------------------*/
4
4
 
5
- #main {
6
- .main.bar {
7
- .ui.container {
8
- .main-menu {
9
- .item:first-child {
10
- display: flex !important;
11
- }
12
- }
13
-
14
- .ui.text.menu {
15
- flex-wrap: wrap;
16
- justify-content: end;
17
- }
18
- }
19
- }
5
+ #main .main.bar .ui.container .main-nav ul {
6
+ width: max-content;
20
7
  }
@@ -53,7 +53,7 @@ body {
53
53
  // Header
54
54
  @media only screen and (min-width: 992px) {
55
55
  .eea.header .eea-logo {
56
- max-width: 350px;
56
+ max-width: 330px;
57
57
  }
58
58
  }
59
59