@eeacms/volto-cca-policy 0.2.1 → 0.2.3

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.
@@ -0,0 +1,13 @@
1
+ import { DefaultEdit } from '@eeacms/volto-tabs-block/components';
2
+ import Spotlight from './Spotlight';
3
+
4
+ export default function applyConfig(config) {
5
+ config.blocks.blocksConfig.tabs_block.variations.push({
6
+ id: 'spotlight',
7
+ title: 'Spotlight',
8
+ isDefault: false,
9
+ edit: DefaultEdit,
10
+ view: Spotlight,
11
+ });
12
+ return config;
13
+ }
@@ -0,0 +1,20 @@
1
+ .spotlight-tabs {
2
+ // this is the container div
3
+ }
4
+
5
+ .ui.menu.menu-tabs-spotlight-variant {
6
+ // this is the menu
7
+ flex-wrap: wrap;
8
+ border: none;
9
+ box-shadow: none;
10
+ // background: #cc000033;
11
+
12
+ .item {
13
+ flex-grow: 2;
14
+
15
+ &:before {
16
+ // border: 0px !important;
17
+ background: none;
18
+ }
19
+ }
20
+ }
@@ -1,6 +1,6 @@
1
1
  import { compose } from 'redux';
2
2
 
3
- import installMKHMap from './MKHMap';
3
+ // import installMKHMap from './MKHMap';
4
4
  import installECDEIndicatorsBlock from './ECDEIndicators';
5
5
  import installCaseStudyExplorerBlock from './CaseStudyExplorer';
6
6
  import installSearchAceContent from './SearchAceContent';
@@ -18,6 +18,7 @@ import installC3SIndicatorsOverviewBlock from './C3SIndicatorsOverviewBlock';
18
18
  import installC3SIndicatorsGlossaryBlock from './C3SIndicatorsGlossaryBlock';
19
19
  import installReadMore from './ReadMore';
20
20
  import installCollectionStats from './CollectionStatistics';
21
+ import installTabsBlock from './TabsBlock';
21
22
 
22
23
  export default function installBlocks(config) {
23
24
  config.blocks.blocksConfig.title.restricted = false;
@@ -32,7 +33,7 @@ export default function installBlocks(config) {
32
33
  installC3SIndicatorsOverviewBlock,
33
34
  installC3SIndicatorsListingBlock,
34
35
  installC3SIndicatorsGlossaryBlock,
35
- installMKHMap,
36
+ // installMKHMap,
36
37
  installECDEIndicatorsBlock,
37
38
  installCaseStudyExplorerBlock,
38
39
  installCountryMapObservatory,
@@ -44,6 +45,7 @@ export default function installBlocks(config) {
44
45
  installFilterAceContent,
45
46
  installTransRegionSelect,
46
47
  installCollectionStats,
48
+ installTabsBlock,
47
49
  installListing,
48
50
  )(config);
49
51
  }
@@ -0,0 +1,190 @@
1
+ import { HTMLField, BannerTitle } from '@eeacms/volto-cca-policy/helpers';
2
+ import { Container, Grid } from 'semantic-ui-react';
3
+ import { PortalMessage } from '@eeacms/volto-cca-policy/components';
4
+ import './styles.less';
5
+
6
+ function MissiongFundingCCAView(props) {
7
+ const { content } = props;
8
+
9
+ return (
10
+ <div className="mission-funding-cca-view">
11
+ <BannerTitle
12
+ content={{ ...content, image: '' }}
13
+ data={{
14
+ info: [{ description: '' }],
15
+ hideContentType: true,
16
+ hideCreationDate: true,
17
+ hideModificationDate: true,
18
+ hidePublishingDate: true,
19
+ hideDownloadButton: false,
20
+ hideShareButton: false,
21
+ subtitle: 'EU and National Funding of Climate Change Adaption',
22
+ }}
23
+ />
24
+
25
+ <Container>
26
+ <PortalMessage content={content} />
27
+ <Grid columns="12">
28
+ <div className="row">
29
+ <Grid.Column
30
+ mobile={12}
31
+ tablet={12}
32
+ computer={8}
33
+ className="col-left"
34
+ >
35
+ {!!content.objective && content.objective.data.length > 7 && (
36
+ <>
37
+ <h3>Objective of the funding programme</h3>
38
+ <HTMLField value={content.objective} />
39
+ </>
40
+ )}
41
+
42
+ {!!content.funding_type && (
43
+ <>
44
+ <h3>Type of funding</h3>
45
+ <HTMLField value={content.funding_type} />
46
+ </>
47
+ )}
48
+
49
+ {!!content.budget_range && (
50
+ <>
51
+ <h3>Expected budget range of proposals</h3>
52
+ <p>{content.budget_range}</p>
53
+ </>
54
+ )}
55
+
56
+ {!!content.funding_rate && (
57
+ <>
58
+ <h3>Funding rate (percentage of covered costs)</h3>
59
+ <p>{content.funding_rate}</p>
60
+ </>
61
+ )}
62
+ <h3>
63
+ Can the received funding be combined with other funding sources
64
+ (blended)?
65
+ </h3>
66
+ <p>{content.is_blended === true ? 'Yes' : 'No'}</p>
67
+ <h3>Is a Consortium required to apply for the funding?</h3>
68
+ <p>{content.is_consortium_required === true ? 'Yes' : 'No'}</p>
69
+ {!!content.authority && (
70
+ <>
71
+ <h3>Administering authority</h3>
72
+ <p>{content.authority}</p>
73
+ </>
74
+ )}
75
+ {!!content.publication_page && (
76
+ <>
77
+ <h3>Publication page</h3>
78
+ <a href={content.publication_page}>
79
+ {content.publication_page}
80
+ </a>
81
+ </>
82
+ )}
83
+ {!!content.general_info && (
84
+ <>
85
+ <h3>General information</h3>
86
+ <a href={content.general_info}>{content.general_info}</a>
87
+ </>
88
+ )}
89
+ {!!content.further_info && (
90
+ <>
91
+ <h3>Further information</h3>
92
+ <p>{content.further_info}</p>
93
+ </>
94
+ )}
95
+ </Grid.Column>
96
+ <Grid.Column
97
+ mobile={12}
98
+ tablet={12}
99
+ computer={4}
100
+ className="col-right"
101
+ >
102
+ <div className="metadata">
103
+ {!!content.country && content.country.length > 0 && (
104
+ <>
105
+ <h5>Countries where the funding opportunity is offered</h5>
106
+ <p>
107
+ {content.country
108
+ .map((country) => country.title)
109
+ .join(', ')}
110
+ </p>
111
+ </>
112
+ )}
113
+ {!!content.regions && content.regions.length > 0 && (
114
+ <>
115
+ <h5>Region where the funding is offered</h5>
116
+ <p>{content.regions}</p>
117
+ </>
118
+ )}
119
+ {!!content.rast_steps && content.rast_steps.length > 0 && (
120
+ <>
121
+ <h5>RAST step(s) of relevance</h5>
122
+ <ul>
123
+ {content.rast_steps.map((step) => (
124
+ <li>{step.title}</li>
125
+ ))}
126
+ </ul>
127
+ </>
128
+ )}
129
+ {!!content.eligible_entities &&
130
+ content.eligible_entities.length > 0 && (
131
+ <>
132
+ <h5>Eligible to receive funding</h5>
133
+ <ul>
134
+ {content.eligible_entities.map((entity) => (
135
+ <li>{entity.title}</li>
136
+ ))}
137
+ </ul>
138
+ </>
139
+ )}
140
+ {!!content.sectors && content.eligible_entities.length > 0 && (
141
+ <>
142
+ <h5>Adaptation Sectors</h5>
143
+ <ul>
144
+ {content.sectors.map((sector) => (
145
+ <li>{sector.title}</li>
146
+ ))}
147
+ </ul>
148
+ </>
149
+ )}
150
+ </div>
151
+ </Grid.Column>
152
+ </div>
153
+ </Grid>
154
+ <Grid columns="12">
155
+ <div className="row">
156
+ <Grid.Column
157
+ mobile={12}
158
+ tablet={12}
159
+ computer={12}
160
+ className="col-full"
161
+ >
162
+ <div className="styled-slate has--style_name--content-box-gray styled">
163
+ <div className="disclaimer content-box">
164
+ <div className="content-box-inner">
165
+ <p>
166
+ <strong>Disclaimer</strong>
167
+ <br />
168
+ The contents and links to third-party items on this
169
+ Mission webpage are developed by the MIP4Adapt team led by
170
+ Ricardo, under contract CINEA/2022/OP/0013/SI2.884597
171
+ funded by the European Union and do not necessarily
172
+ reflect those of the European Union, CINEA, or those of
173
+ the European Environment Agency (EEA) as host of the
174
+ Climate-ADAPT Platform. Neither the European Union nor
175
+ CINEA nor the EEA accepts responsibility or liability
176
+ arising out of or in connection with the information on
177
+ these pages.
178
+ </p>
179
+ </div>
180
+ </div>
181
+ </div>
182
+ </Grid.Column>
183
+ </div>
184
+ </Grid>
185
+ </Container>
186
+ </div>
187
+ );
188
+ }
189
+
190
+ export default MissiongFundingCCAView;
@@ -0,0 +1,106 @@
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 MissiongFundingCCAView from './MissionFundingCCAView';
8
+ import config from '@plone/volto/registry';
9
+
10
+ config.blocks = {
11
+ blocksConfig: {
12
+ title: {
13
+ view: () => <div>Title Block Component</div>,
14
+ },
15
+ },
16
+ };
17
+
18
+ const mockStore = configureStore();
19
+
20
+ describe('MissiongFundingCCAView', () => {
21
+ it('should render the component', () => {
22
+ const data = {
23
+ content: {
24
+ contributors: [],
25
+ country: [
26
+ {
27
+ title: 'Albania',
28
+ token: 'AL',
29
+ },
30
+ {
31
+ title: 'Armenia',
32
+ token: 'AM',
33
+ },
34
+ ],
35
+ description: 'Summary',
36
+ eligible_entities: [
37
+ {
38
+ title: 'Social, cultural, educational bodies',
39
+ token: 'B_SOCIAL_CULTURAL',
40
+ },
41
+ {
42
+ title: 'NGOs',
43
+ token: 'D_NGOS',
44
+ },
45
+ ],
46
+ funding_rate: 'funding rate',
47
+ funding_type: {
48
+ 'content-type': 'text/html',
49
+ data: '<p>type of funding</p>',
50
+ encoding: 'utf8',
51
+ },
52
+ further_info: 'further info',
53
+ general_info: '/sandbox',
54
+ is_blended: true,
55
+ is_consortium_required: false,
56
+ objective: {
57
+ 'content-type': 'text/html',
58
+ data: '<p></p>',
59
+ encoding: 'utf8',
60
+ },
61
+ publication_page: 'https://google.com',
62
+ rast_steps: [
63
+ {
64
+ title: 'Step 1. Preparing the ground for adaptation',
65
+ token: 'STEP_1',
66
+ },
67
+ {
68
+ title: 'Step 4. Assessing and selecting adaptation options',
69
+ token: 'STEP_4',
70
+ },
71
+ ],
72
+ regions: 'region here',
73
+ sectors: [
74
+ {
75
+ title: 'Biodiversity',
76
+ token: 'BIODIVERSITY',
77
+ },
78
+ {
79
+ title: 'Coastal areas',
80
+ token: 'COASTAL',
81
+ },
82
+ ],
83
+ title: 'Title here',
84
+ },
85
+ };
86
+
87
+ const store = mockStore({
88
+ userSession: { token: '1234' },
89
+ intl: {
90
+ locale: 'en',
91
+ messages: {},
92
+ },
93
+ });
94
+
95
+ const { container } = render(
96
+ <Provider store={store}>
97
+ <MemoryRouter>
98
+ <MissiongFundingCCAView {...data} />
99
+ </MemoryRouter>
100
+ </Provider>,
101
+ );
102
+ expect(
103
+ container.querySelector('.mission-funding-cca-view'),
104
+ ).toBeInTheDocument();
105
+ });
106
+ });
@@ -0,0 +1,7 @@
1
+ // MissionFundingCCAView
2
+ div.col-right {
3
+ div.metadata {
4
+ padding: 10px;
5
+ background: #e6e7e8;
6
+ }
7
+ }
@@ -0,0 +1,146 @@
1
+ /**
2
+ *
3
+ * Customization of https://github.com/plone/volto/blob/0630a6e7655637c0b811139a738353f682053b79/packages/volto-slate/src/blocks/Table/TableBlockView.jsx#L45
4
+ * to fix https://github.com/plone/volto/issues/5947
5
+ *
6
+ * Slate Table block's View component.
7
+ * @module volto-slate/blocks/Table/View
8
+ */
9
+
10
+ import React, { useState, useMemo } from 'react';
11
+ import PropTypes from 'prop-types';
12
+ import { Table } from 'semantic-ui-react';
13
+ import { map } from 'lodash';
14
+ import {
15
+ serializeNodes,
16
+ serializeNodesToText,
17
+ } from '@plone/volto-slate/editor/render';
18
+ // import { Node } from 'slate';
19
+
20
+ import '@plone/volto-slate/editor/plugins/Table/less/public.less';
21
+
22
+ /**
23
+ * Slate Table block's View class.
24
+ * @class View
25
+ * @extends Component
26
+ * @param {object} data The table data to render as a table.
27
+ */
28
+ const View = ({ data }) => {
29
+ const [state, setState] = useState({
30
+ column: null,
31
+ direction: null,
32
+ });
33
+
34
+ const headers = useMemo(() => {
35
+ return data.table.rows?.[0]?.cells;
36
+ }, [data.table.rows]);
37
+
38
+ const rows = useMemo(() => {
39
+ const items = [];
40
+ if (!data.table.rows) return [];
41
+ // Customization: we've removed the condition for Node.string(value)
42
+ data.table.rows.forEach((row, index) => {
43
+ if (index > 0) {
44
+ items[index] = [];
45
+ row.cells.forEach((cell, cellIndex) => {
46
+ items[index][cellIndex] = {
47
+ ...cell,
48
+ value: cell.value ? serializeNodes(cell.value) : '\u00A0',
49
+ valueText: cell.value ? serializeNodesToText(cell.value) : '\u00A0',
50
+ };
51
+ });
52
+ }
53
+ });
54
+ // end Customization
55
+ return items;
56
+ }, [data.table.rows]);
57
+
58
+ const sortedRows = useMemo(() => {
59
+ if (state.column === null) return Object.keys(rows);
60
+ return Object.keys(rows).sort((a, b) => {
61
+ const a_text = rows[a][state.column].valueText;
62
+ const b_text = rows[b][state.column].valueText;
63
+ if (state.direction === 'ascending' ? a_text < b_text : a_text > b_text) {
64
+ return -1;
65
+ }
66
+ if (state.direction === 'ascending' ? a_text > b_text : a_text < b_text) {
67
+ return 1;
68
+ }
69
+ return 0;
70
+ });
71
+ }, [state, rows]);
72
+
73
+ return (
74
+ <>
75
+ {data && data.table && (
76
+ <Table
77
+ fixed={data.table.fixed}
78
+ compact={data.table.compact}
79
+ basic={data.table.basic ? 'very' : false}
80
+ celled={data.table.celled}
81
+ inverted={data.table.inverted}
82
+ striped={data.table.striped}
83
+ sortable={data.table.sortable}
84
+ className="slate-table-block"
85
+ >
86
+ {!data.table.hideHeaders ? (
87
+ <Table.Header>
88
+ <Table.Row>
89
+ {headers.map((cell, index) => (
90
+ <Table.HeaderCell
91
+ key={cell.key}
92
+ textAlign="left"
93
+ verticalAlign="middle"
94
+ sorted={state.column === index ? state.direction : null}
95
+ onClick={() => {
96
+ if (!data.table.sortable) return;
97
+ setState({
98
+ column: index,
99
+ direction:
100
+ state.column !== index
101
+ ? 'ascending'
102
+ : state.direction === 'ascending'
103
+ ? 'descending'
104
+ : 'ascending',
105
+ });
106
+ }}
107
+ >
108
+ {cell.value ? serializeNodes(cell.value) : '\u00A0'}
109
+ </Table.HeaderCell>
110
+ ))}
111
+ </Table.Row>
112
+ </Table.Header>
113
+ ) : (
114
+ ''
115
+ )}
116
+ <Table.Body>
117
+ {map(sortedRows, (row) => (
118
+ <Table.Row key={row}>
119
+ {map(rows[row], (cell) => (
120
+ <Table.Cell
121
+ key={cell.key}
122
+ textAlign="left"
123
+ verticalAlign="middle"
124
+ >
125
+ {cell.value}
126
+ </Table.Cell>
127
+ ))}
128
+ </Table.Row>
129
+ ))}
130
+ </Table.Body>
131
+ </Table>
132
+ )}
133
+ </>
134
+ );
135
+ };
136
+
137
+ /**
138
+ * Property types.
139
+ * @property {Object} propTypes Property types.
140
+ * @static
141
+ */
142
+ View.propTypes = {
143
+ data: PropTypes.objectOf(PropTypes.any).isRequired,
144
+ };
145
+
146
+ export default View;
@@ -1,5 +1,5 @@
1
1
  import TableBlockEdit from '@plone/volto-slate/blocks/Table/TableBlockEdit';
2
- import TableBlockView from '@plone/volto-slate/blocks/Table/TableBlockView';
2
+ import TableBlockView from './TableBlockView';
3
3
  import { extractTables } from './deconstruct';
4
4
  import { normalizeTable } from '@plone/volto-slate/blocks/Table/extensions/normalizeTable';
5
5
  import { normalizeExternalData } from '@plone/volto-slate/blocks/Text/extensions';
package/src/index.js CHANGED
@@ -9,6 +9,7 @@ import CaseStudyView from './components/theme/Views/CaseStudyView';
9
9
  import ProjectView from './components/theme/Views/ProjectView';
10
10
  import C3SIndicatorView from './components/theme/Views/C3SIndicatorView';
11
11
  import DatabaseItemView from './components/theme/Views/DatabaseItemView';
12
+ import MissionFundingCCAView from './components/theme/Views/MissionFundingCCAView';
12
13
 
13
14
  import HealthHorizontalCardItem from './components/Result/HealthHorizontalCardItem';
14
15
 
@@ -285,6 +286,7 @@ const applyConfig = (config) => {
285
286
  'eea.climateadapt.c3sindicator': C3SIndicatorView,
286
287
  'eea.climateadapt.adaptationoption': AdaptationOptionView,
287
288
  'News Item': NewsItemView,
289
+ mission_funding_cca: MissionFundingCCAView,
288
290
  };
289
291
 
290
292
  config.views.layoutViewsNamesMapping.view_cca_event = 'CCA Event View';
@@ -18,51 +18,46 @@ export const clusters = {
18
18
  name: 'Case studies',
19
19
  icon: { name: 'file text' },
20
20
  values: ['Case study'],
21
- defaultResultView: 'horizontalCard',
22
21
  },
23
22
  {
24
23
  name: 'Guidance',
25
24
  icon: { name: 'compass' },
26
25
  values: ['Guidance'],
27
- defaultResultView: 'horizontalCard',
28
26
  },
29
27
  {
30
28
  name: 'Indicators',
31
29
  icon: { name: 'area chart' },
32
30
  values: ['Indicator'],
33
- defaultResultView: 'horizontalCard',
34
31
  },
35
32
  {
36
33
  name: 'Information portals',
37
34
  icon: { name: 'info circle' },
38
35
  values: ['Information portal'],
39
- defaultResultView: 'horizontalCard',
40
36
  },
41
37
  {
42
38
  name: 'Publications and reports',
43
39
  icon: { name: 'newspaper' },
44
40
  values: ['Publication reference'],
45
- defaultResultView: 'horizontalCard',
46
41
  },
47
42
  {
48
43
  name: 'Research and knowledge projects',
49
44
  icon: { name: 'university' },
50
45
  values: ['Research and knowledge project'],
51
- defaultResultView: 'horizontalCard',
52
46
  },
53
47
  {
54
48
  name: 'Tools',
55
49
  icon: { name: 'wrench' },
56
50
  values: ['Tool'],
57
- defaultResultView: 'horizontalCard',
58
51
  },
59
52
  {
60
53
  name: 'Videos',
61
54
  icon: { name: 'video play' },
62
55
  values: ['Video'],
63
- defaultResultView: 'horizontalCard',
64
56
  },
65
- ],
57
+ ].map((cluster) => ({
58
+ ...cluster,
59
+ defaultResultView: 'horizontalCard',
60
+ })),
66
61
  };
67
62
 
68
63
  export default function installMainSearch(config) {