@eeacms/volto-marine-policy 2.0.35 → 2.0.37

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,6 +4,24 @@ 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
+ ### [2.0.37](https://github.com/eea/volto-marine-policy/compare/2.0.36...2.0.37) - 27 November 2025
8
+
9
+ #### :hammer_and_wrench: Others
10
+
11
+ - Delete src/customizations/@plone-collective/volto-authomatic/components/Login directory [dobri1408 - [`6ae6856`](https://github.com/eea/volto-marine-policy/commit/6ae68563420e56e32f073cd5950494fdc210b0a1)]
12
+ ### [2.0.36](https://github.com/eea/volto-marine-policy/compare/2.0.35...2.0.36) - 10 November 2025
13
+
14
+ #### :rocket: New Features
15
+
16
+ - feat: new variation for Demo sites explorer [laszlocseh - [`58799b2`](https://github.com/eea/volto-marine-policy/commit/58799b23a8c0ff0f34ff2aeee8991113baaaa3d9)]
17
+
18
+ #### :house: Internal changes
19
+
20
+ - style: Automated code fix [eea-jenkins - [`db0e43a`](https://github.com/eea/volto-marine-policy/commit/db0e43a4def21dddc41640173ff963ad97b6d32a)]
21
+
22
+ #### :hammer_and_wrench: Others
23
+
24
+ - fix demo sites map [laszlocseh - [`b4e676a`](https://github.com/eea/volto-marine-policy/commit/b4e676a445bcee52dc74b36662c36e149c74c841)]
7
25
  ### [2.0.35](https://github.com/eea/volto-marine-policy/compare/2.0.34...2.0.35) - 3 November 2025
8
26
 
9
27
  #### :rocket: New Features
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeacms/volto-marine-policy",
3
- "version": "2.0.35",
3
+ "version": "2.0.37",
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",
@@ -19,8 +19,7 @@ export default function DemoSitesExplorerView(props) {
19
19
  : '/marine/@@demo-sites-map.arcgis.json';
20
20
  let cases = useCases(addAppURL(cases_url));
21
21
  const [selectedCase, onSelectedCase] = React.useState(null);
22
- const { enableMarineMO } = props.data;
23
- // console.log('enableMarineMO', enableMarineMO);
22
+ const { mapVariation } = props.data;
24
23
  const { properties } = props;
25
24
  // if the map is rendered on the indicator page we hide the Target and
26
25
  // the Indicator filters, and hide the chart on the right side
@@ -39,7 +38,10 @@ export default function DemoSitesExplorerView(props) {
39
38
  const [filters, setFilters] = React.useState([]);
40
39
  const [map, setMap] = React.useState();
41
40
  const [highlightedIndex, setHighlightedIndex] = React.useState(-1);
42
- const columnsLength = hideFilters || enableMarineMO ? 12 : 8;
41
+ const columnsLength =
42
+ hideFilters || ['blueParks', 'blueParksObj1'].includes(mapVariation)
43
+ ? 12
44
+ : 8;
43
45
 
44
46
  React.useEffect(() => {
45
47
  const _filters = getFilters(activeItems, indicatorOnly);
@@ -60,11 +62,11 @@ export default function DemoSitesExplorerView(props) {
60
62
  cases,
61
63
  activeFilters,
62
64
  indicatorOnly,
63
- enableMarineMO,
65
+ mapVariation,
64
66
  );
65
67
 
66
68
  setActiveItems(activeItems);
67
- }, [activeFilters, cases, indicatorOnly, enableMarineMO]);
69
+ }, [activeFilters, cases, indicatorOnly, mapVariation]);
68
70
 
69
71
  if (__SERVER__) return '';
70
72
 
@@ -86,7 +88,7 @@ export default function DemoSitesExplorerView(props) {
86
88
  hideFilters={hideFilters}
87
89
  setActiveFilters={setActiveFilters}
88
90
  highlightedIndex={highlightedIndex}
89
- enableMarineMO={enableMarineMO}
91
+ mapVariation={mapVariation}
90
92
  />
91
93
  </Grid.Row>
92
94
  <Grid.Row>
@@ -108,10 +110,13 @@ export default function DemoSitesExplorerView(props) {
108
110
  setMap={setMap}
109
111
  highlightedIndex={highlightedIndex}
110
112
  setHighlightedIndex={setHighlightedIndex}
111
- enableMarineMO={enableMarineMO}
113
+ mapVariation={mapVariation}
112
114
  />
113
115
  </Grid.Column>
114
- {!(hideFilters || enableMarineMO) ? (
116
+ {!(
117
+ hideFilters ||
118
+ ['blueParks', 'blueParksObj1'].includes(mapVariation)
119
+ ) ? (
115
120
  <Grid.Column
116
121
  mobile={4}
117
122
  tablet={4}
@@ -142,7 +147,7 @@ export default function DemoSitesExplorerView(props) {
142
147
  <div className="circle">
143
148
  {/* <div className="dot-demosite"></div> */}
144
149
  <img
145
- src="/marine/europe-seas/eu-mission-restore-our-oceans-and-water/icon-point.png/@@images/image/small"
150
+ src="/marine/europe-seas/eu-mission-restore-our-oceans-and-water/icon-point-light.png/@@images/image/small"
146
151
  alt=""
147
152
  />
148
153
  </div>
@@ -152,7 +157,7 @@ export default function DemoSitesExplorerView(props) {
152
157
  <div className="circle">
153
158
  {/* <div className="dot-region"></div> */}
154
159
  <img
155
- src="/marine/europe-seas/eu-mission-restore-our-oceans-and-water/icon-region.png/@@images/image/small"
160
+ src="/marine/europe-seas/eu-mission-restore-our-oceans-and-water/icon-region-light.png/@@images/image/small"
156
161
  alt=""
157
162
  />
158
163
  </div>
@@ -165,7 +165,7 @@ export function DemoSitesFilters(props) {
165
165
  hideFilters,
166
166
  setActiveFilters,
167
167
  highlightedIndex,
168
- enableMarineMO,
168
+ mapVariation,
169
169
  } = props;
170
170
 
171
171
  React.useEffect(() => {
@@ -180,7 +180,7 @@ export function DemoSitesFilters(props) {
180
180
  });
181
181
  }, []);
182
182
 
183
- return !enableMarineMO ? (
183
+ return !['blueParks', 'blueParksObj1'].includes(mapVariation) ? (
184
184
  <>
185
185
  {!hideFilters ? (
186
186
  <DemoSitesFilter
@@ -42,7 +42,7 @@ function DemoSitesMap(props) {
42
42
  setMap,
43
43
  highlightedIndex,
44
44
  setHighlightedIndex,
45
- enableMarineMO,
45
+ mapVariation,
46
46
  ol,
47
47
  } = props;
48
48
  const features = getFeatures({ cases: items, ol });
@@ -135,8 +135,8 @@ function DemoSitesMap(props) {
135
135
  }, [map, selectedCase, resetMapButtonClass, setResetMapButtonClass, ol]);
136
136
 
137
137
  const clusterStyle = React.useMemo(
138
- () => selectedClusterStyle({ selectedCase, ol, enableMarineMO }),
139
- [selectedCase, ol, enableMarineMO],
138
+ () => selectedClusterStyle({ selectedCase, ol, mapVariation }),
139
+ [selectedCase, ol, mapVariation],
140
140
  );
141
141
 
142
142
  const MapWithSelection = React.useMemo(() => Map, []);
@@ -196,7 +196,9 @@ function DemoSitesMap(props) {
196
196
  // selectedCase={selectedCase}
197
197
  />
198
198
  <Layer.Tile source={tileWMSSources[0]} zIndex={0} />
199
- {enableMarineMO && <Layer.Tile source={arcgisSource} zIndex={0} />}
199
+ {['blueParks', 'blueParksObj1'].includes(mapVariation) && (
200
+ <Layer.Tile source={arcgisSource} zIndex={0} />
201
+ )}
200
202
  <Layer.Vector
201
203
  style={clusterStyle}
202
204
  source={clusterSource}
@@ -209,7 +211,7 @@ function DemoSitesMap(props) {
209
211
  ) : null;
210
212
  }
211
213
 
212
- const selectedClusterStyle = ({ selectedFeature, ol, enableMarineMO }) => {
214
+ const selectedClusterStyle = ({ selectedFeature, ol, mapVariation }) => {
213
215
  function _clusterStyle(feature, selectedFeature) {
214
216
  const size = feature.get('features').length;
215
217
  let clusterStyle = styleCache[size];
@@ -235,52 +237,64 @@ const selectedClusterStyle = ({ selectedFeature, ol, enableMarineMO }) => {
235
237
  });
236
238
  styleCache[size] = clusterStyle;
237
239
  }
238
- // set size === 1 to enable clusterization
239
- if (size) {
240
- if (enableMarineMO) {
240
+ // use condition size === 1 to enable clusterization
241
+ if (true) {
242
+ let iconType = '-light';
243
+ let iconSize = 'icon';
244
+
245
+ if ('blueParks' === mapVariation) {
241
246
  return new ol.style.Style({
242
247
  image: new ol.style.Icon({
243
248
  anchor: [0.5, 1],
244
- // size: [52, 52],
245
- // offset: [52, 0],
246
- // opacity: 1,
247
249
  scale: 0.8,
248
250
  src: '/marine/europe-seas/eu-mission-restore-our-oceans-and-water/icon-point.png/@@images/image/tiny',
249
251
  }),
250
252
  });
251
- } else {
252
- // let color = feature.values_.features[0].values_['color'];
253
- // type_is_region
254
- // let color = '#0179cf';
255
- // let width = feature.values_.features[0].values_['width'];
256
- // let radius = feature.values_.features[0].values_['radius'];
257
-
258
- // return new ol.style.Style({
259
- // image: new ol.style.Circle({
260
- // radius: radius,
261
- // fill: new ol.style.Fill({
262
- // color: '#fff',
263
- // }),
264
- // stroke: new ol.style.Stroke({
265
- // color: color,
266
- // width: width,
267
- // }),
268
- // }),
269
- // });
270
- let iconUrl =
271
- feature.values_.features[0].values_['type_is_region'] ===
272
- 'Associated region'
273
- ? '/marine/europe-seas/eu-mission-restore-our-oceans-and-water/icon-region.png/@@images/image/icon'
274
- : '/marine/europe-seas/eu-mission-restore-our-oceans-and-water/icon-point.png/@@images/image/icon';
253
+ } else if ('blueParksObj1' === mapVariation) {
254
+ iconType = '-light';
255
+ iconSize = 'tiny';
275
256
 
276
- return new ol.style.Style({
277
- image: new ol.style.Icon({
278
- anchor: [0.5, 1],
279
- scale: 0.8,
280
- src: iconUrl,
281
- }),
282
- });
257
+ if (
258
+ ['BioProtect', 'BLUE CONNECT', 'BLUE4ALL', 'EFFECTIVE'].includes(
259
+ feature.values_.features[0].values_['project'],
260
+ )
261
+ ) {
262
+ iconType = '';
263
+ iconSize = 'tiny';
264
+ }
283
265
  }
266
+ // let color = feature.values_.features[0].values_['color'];
267
+ // type_is_region
268
+ // let color = '#0179cf';
269
+ // let width = feature.values_.features[0].values_['width'];
270
+ // let radius = feature.values_.features[0].values_['radius'];
271
+
272
+ // return new ol.style.Style({
273
+ // image: new ol.style.Circle({
274
+ // radius: radius,
275
+ // fill: new ol.style.Fill({
276
+ // color: '#fff',
277
+ // }),
278
+ // stroke: new ol.style.Stroke({
279
+ // color: color,
280
+ // width: width,
281
+ // }),
282
+ // }),
283
+ // });
284
+
285
+ let iconUrl =
286
+ feature.values_.features[0].values_['type_is_region'] ===
287
+ 'Associated region'
288
+ ? `/marine/europe-seas/eu-mission-restore-our-oceans-and-water/icon-region${iconType}.png/@@images/image/${iconSize}`
289
+ : `/marine/europe-seas/eu-mission-restore-our-oceans-and-water/icon-point${iconType}.png/@@images/image/${iconSize}`;
290
+
291
+ return new ol.style.Style({
292
+ image: new ol.style.Icon({
293
+ anchor: [0.5, 1],
294
+ scale: 0.8,
295
+ src: iconUrl,
296
+ }),
297
+ });
284
298
  } else {
285
299
  return clusterStyle;
286
300
  }
@@ -4,20 +4,28 @@ const DemoSitesExplorerSchema = {
4
4
  {
5
5
  id: 'default',
6
6
  title: 'Default',
7
- fields: ['enableMarineMO'],
7
+ fields: ['mapVariation'],
8
8
  },
9
9
  ],
10
10
 
11
11
  properties: {
12
- enableMarineMO: {
13
- title: 'Enable Marine Protected Areas layer',
12
+ mapVariation: {
13
+ title: 'Choose the type of map',
14
14
  description:
15
15
  'If enabled, the Marine Protected Areas layer will be displayed on the map, without the filters and the chart on the right side',
16
- type: 'boolean',
17
- default: false,
16
+ // type: 'boolean',
17
+ choices: [
18
+ ['standard', 'Standard map with filters and chart'],
19
+ ['blueParks', 'Marine protected areas map with Blue Parks projects'],
20
+ [
21
+ 'blueParksObj1',
22
+ 'Marine protected areas map with Objective 1 and Blue Parks projects',
23
+ ],
24
+ ],
25
+ default: 'standard',
18
26
  },
19
27
  },
20
- required: ['enableMarineMO'],
28
+ required: ['mapVariation'],
21
29
  };
22
30
 
23
31
  export default DemoSitesExplorerSchema;
@@ -144,12 +144,7 @@ export function getFeatures({ cases, ol }) {
144
144
  });
145
145
  }
146
146
 
147
- export function filterCases(
148
- cases,
149
- activeFilters,
150
- indicatorOnly,
151
- enableMarineMO,
152
- ) {
147
+ export function filterCases(cases, activeFilters, indicatorOnly, mapVariation) {
153
148
  const data = cases.filter((_case) => {
154
149
  let flag_objective = false;
155
150
  let flag_target = false;
@@ -163,21 +158,20 @@ export function filterCases(
163
158
  return item['title'].toString();
164
159
  });
165
160
  if (indicators?.includes(indicatorOnly)) flag_indicatorOnly = true;
166
- } else if (enableMarineMO) {
167
- let indicators = _case.properties.indicators?.map((item) => {
168
- return item['title'].toString();
169
- });
170
- if (
171
- indicators?.includes('Marine protected areas') ||
172
- indicators?.includes('Marine strictly protected areas')
173
- )
174
- flag_indicatorOnly = true;
175
161
  } else {
176
162
  flag_indicatorOnly = true;
177
163
  }
178
164
 
179
165
  // debugger;
180
- if (!activeFilters.objective_filter.length) {
166
+ if ('blueParksObj1' === mapVariation) {
167
+ let objective = _case.properties.objective;
168
+ if (
169
+ objective.includes(
170
+ 'Objective 1: Protect and restore marine and freshwater ecosystems and biodiversity',
171
+ )
172
+ )
173
+ flag_objective = true;
174
+ } else if (!activeFilters.objective_filter.length) {
181
175
  flag_objective = true;
182
176
  } else {
183
177
  let objective = _case.properties.objective;
@@ -209,7 +203,16 @@ export function filterCases(
209
203
  });
210
204
  }
211
205
 
212
- if (!activeFilters.project_filter.length) {
206
+ // BioProtect, BLUE CONNECT, BLUE4ALL, EFFECTIVE
207
+ if (['blueParks'].includes(mapVariation)) {
208
+ let project = _case.properties.project;
209
+ if (
210
+ ['BioProtect', 'BLUE CONNECT', 'BLUE4ALL', 'EFFECTIVE'].includes(
211
+ project,
212
+ )
213
+ )
214
+ flag_project = true;
215
+ } else if (!activeFilters.project_filter.length) {
213
216
  flag_project = true;
214
217
  } else {
215
218
  let project = _case.properties.project;
@@ -1,389 +0,0 @@
1
- /**
2
- * Combined Login container - supports both external providers and Plone login.
3
- * @module components/Login/Login
4
- */
5
- import React, { useEffect, useState } from 'react';
6
- import { useDispatch, useSelector, shallowEqual } from 'react-redux';
7
- import { Link, useHistory, useLocation } from 'react-router-dom';
8
- import {
9
- Container,
10
- Button,
11
- Form,
12
- Input,
13
- Segment,
14
- Grid,
15
- } from 'semantic-ui-react';
16
- import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
17
- import qs from 'query-string';
18
- import { useCookies } from 'react-cookie';
19
-
20
- import { Helmet } from '@plone/volto/helpers';
21
- import config from '@plone/volto/registry';
22
- import { Icon } from '@plone/volto/components';
23
- import { login, resetLoginRequest } from '@plone/volto/actions';
24
- import { toast } from 'react-toastify';
25
- import { Toast } from '@plone/volto/components';
26
- import aheadSVG from '@plone/volto/icons/ahead.svg';
27
- import clearSVG from '@plone/volto/icons/clear.svg';
28
- import './Login.less';
29
-
30
- // Import authomatic components and actions
31
- import {
32
- authomaticRedirect,
33
- listAuthOptions,
34
- oidcRedirect,
35
- } from '@plone-collective/volto-authomatic/actions';
36
- import AuthProviders from '@plone-collective/volto-authomatic/components/AuthProviders/AuthProviders';
37
-
38
- const messages = defineMessages({
39
- login: {
40
- id: 'Log in',
41
- defaultMessage: 'Log in',
42
- },
43
- loginName: {
44
- id: 'Login Name',
45
- defaultMessage: 'Login Name',
46
- },
47
- Login: {
48
- id: 'Login',
49
- defaultMessage: 'Login',
50
- },
51
- password: {
52
- id: 'Password',
53
- defaultMessage: 'Password',
54
- },
55
- cancel: {
56
- id: 'Cancel',
57
- defaultMessage: 'Cancel',
58
- },
59
- error: {
60
- id: 'Error',
61
- defaultMessage: 'Error',
62
- },
63
- loginFailed: {
64
- id: 'Login Failed',
65
- defaultMessage: 'Login Failed',
66
- },
67
- loginFailedContent: {
68
- id: 'Both email address and password are case sensitive, check that caps lock is not enabled.',
69
- defaultMessage:
70
- 'Both email address and password are case sensitive, check that caps lock is not enabled.',
71
- },
72
- register: {
73
- id: 'Register',
74
- defaultMessage: 'Register',
75
- },
76
- forgotPassword: {
77
- id: 'box_forgot_password_option',
78
- defaultMessage: 'Forgot your password?',
79
- },
80
- signInWith: {
81
- id: 'Sign in with EEA Microsoft Entra ID',
82
- defaultMessage: 'Sign in with EEA Microsoft Entra ID',
83
- },
84
- orSignIn: {
85
- id: 'Or sign in with EEA Entra ID:',
86
- defaultMessage: 'Or sign in with EEA Entra ID:',
87
- },
88
- loading: {
89
- id: 'Loading',
90
- defaultMessage: 'Loading',
91
- },
92
- });
93
-
94
- /**
95
- * Get return url function.
96
- * @function getReturnUrl
97
- * @param {Object} location Location object.
98
- * @returns {string} Return url.
99
- */
100
- function getReturnUrl(location) {
101
- return `${
102
- qs.parse(location.search).return_url ||
103
- (location.pathname === '/login'
104
- ? '/'
105
- : location.pathname.replace('/login', ''))
106
- }`;
107
- }
108
-
109
- /**
110
- * Combined Login function.
111
- * @function Login
112
- * @returns {JSX.Element} Markup of the Login page.
113
- */
114
- function Login({ intl }) {
115
- const dispatch = useDispatch();
116
- const history = useHistory();
117
- const location = useLocation();
118
-
119
- // Authomatic state
120
- const [startedOAuth, setStartedOAuth] = useState(false);
121
- const [startedOIDC, setStartedOIDC] = useState(false);
122
- const loading = useSelector((state) => state.authOptions.loading);
123
- const options = useSelector((state) => state.authOptions.options);
124
- const loginOAuthValues = useSelector((state) => state.authomaticRedirect);
125
- const loginOIDCValues = useSelector((state) => state.oidcRedirect);
126
- const [, setCookie] = useCookies();
127
-
128
- // Plone login state
129
- const token = useSelector((state) => state.userSession.token, shallowEqual);
130
- const error = useSelector((state) => state.userSession.login.error);
131
- const ploneLoading = useSelector((state) => state.userSession.login.loading);
132
-
133
- const returnUrl =
134
- qs.parse(location.search).return_url ||
135
- location.pathname.replace(/\/login\/?$/, '').replace(/\/logout\/?$/, '') ||
136
- '/';
137
-
138
- useEffect(() => {
139
- dispatch(listAuthOptions());
140
- }, [dispatch]);
141
-
142
- // Handle successful Plone login
143
- useEffect(() => {
144
- if (token) {
145
- history.push(returnUrl || '/');
146
- if (toast.isActive('loggedOut')) {
147
- toast.dismiss('loggedOut');
148
- }
149
- if (toast.isActive('loginFailed')) {
150
- toast.dismiss('loginFailed');
151
- }
152
- }
153
- if (error) {
154
- if (toast.isActive('loggedOut')) {
155
- toast.dismiss('loggedOut');
156
- }
157
- if (!toast.isActive('loginFailed')) {
158
- toast.error(
159
- <Toast
160
- error
161
- title={intl.formatMessage(messages.loginFailed)}
162
- content={intl.formatMessage(messages.loginFailedContent)}
163
- />,
164
- { autoClose: false, toastId: 'loginFailed' },
165
- );
166
- }
167
- }
168
- return () => {
169
- if (toast.isActive('loginFailed')) {
170
- toast.dismiss('loginFailed');
171
- dispatch(resetLoginRequest());
172
- }
173
- };
174
- }, [dispatch, token, error, intl, history, returnUrl]);
175
-
176
- // Handle OAuth redirects
177
- useEffect(() => {
178
- const next_url = loginOAuthValues.next_url;
179
- const session = loginOAuthValues.session;
180
- if (next_url && session && startedOAuth) {
181
- setStartedOAuth(false);
182
- // Give time to save state to localstorage
183
- setTimeout(function () {
184
- window.location.href = next_url;
185
- }, 500);
186
- }
187
- }, [startedOAuth, loginOAuthValues]);
188
-
189
- useEffect(() => {
190
- const next_url = loginOIDCValues.next_url;
191
- if (next_url && startedOIDC) {
192
- setStartedOIDC(false);
193
- // Give time to save state to localstorage
194
- setTimeout(function () {
195
- window.location.href = next_url;
196
- }, 500);
197
- }
198
- }, [startedOIDC, loginOIDCValues]);
199
-
200
- useEffect(() => {
201
- if (
202
- options !== undefined &&
203
- options.length === 1 &&
204
- options[0].id === 'oidc'
205
- ) {
206
- setStartedOIDC(true);
207
- dispatch(oidcRedirect('oidc'));
208
- }
209
- }, [options, dispatch]);
210
-
211
- // Handle provider selection
212
- const onSelectProvider = (provider) => {
213
- setStartedOAuth(true);
214
- setCookie('return_url', getReturnUrl(location), { path: '/' });
215
- dispatch(authomaticRedirect(provider.id));
216
- };
217
-
218
- // Handle Plone login form submission
219
- const onLogin = (event) => {
220
- dispatch(
221
- login(
222
- document.getElementsByName('login')[0].value,
223
- document.getElementsByName('password')[0].value,
224
- ),
225
- );
226
- event.preventDefault();
227
- };
228
-
229
- // Prepare providers for external login
230
- const validProviders = options
231
- ? options.filter((provider) => provider.id !== 'oidc')
232
- : [];
233
-
234
- return (
235
- <div id="page-login">
236
- <Helmet title={intl.formatMessage(messages.Login)} />
237
- <Container text>
238
- <Segment.Group raised>
239
- <Segment className="primary">
240
- <FormattedMessage id="Log In" defaultMessage="Login" />
241
- </Segment>
242
- <Segment secondary>
243
- <FormattedMessage
244
- id="Sign in to start session"
245
- defaultMessage="Sign in to start session"
246
- />
247
- </Segment>
248
-
249
- {/* Plone Login Form */}
250
- <Segment className="form">
251
- <Form method="post" onSubmit={onLogin}>
252
- <Form.Field inline className="help">
253
- <Grid>
254
- <Grid.Row stretched>
255
- <Grid.Column width="4">
256
- <div className="wrapper">
257
- <label htmlFor="login">
258
- <FormattedMessage
259
- id="Login Name"
260
- defaultMessage="Login Name"
261
- />
262
- </label>
263
- </div>
264
- </Grid.Column>
265
- <Grid.Column width="8">
266
- <Input
267
- id="login"
268
- name="login"
269
- placeholder={intl.formatMessage(messages.loginName)}
270
- />
271
- </Grid.Column>
272
- </Grid.Row>
273
- </Grid>
274
- </Form.Field>
275
- <Form.Field inline className="help">
276
- <Grid>
277
- <Grid.Row stretched>
278
- <Grid.Column stretched width="4">
279
- <div className="wrapper">
280
- <label htmlFor="password">
281
- <FormattedMessage
282
- id="Password"
283
- defaultMessage="Password"
284
- />
285
- </label>
286
- </div>
287
- </Grid.Column>
288
- <Grid.Column stretched width="8">
289
- <Input
290
- type="password"
291
- id="password"
292
- autoComplete="current-password"
293
- name="password"
294
- placeholder={intl.formatMessage(messages.password)}
295
- tabIndex={0}
296
- />
297
- </Grid.Column>
298
- </Grid.Row>
299
- </Grid>
300
- </Form.Field>
301
- <Form.Field inline className="help">
302
- <Grid>
303
- <Grid.Row stretched>
304
- {config.settings.showSelfRegistration && (
305
- <Grid.Column stretched width="12">
306
- <p className="help">
307
- <Link to="/register">
308
- {intl.formatMessage(messages.register)}
309
- </Link>
310
- </p>
311
- </Grid.Column>
312
- )}
313
- <Grid.Column stretched width="12">
314
- <p className="help">
315
- <Link to="/passwordreset">
316
- {intl.formatMessage(messages.forgotPassword)}
317
- </Link>
318
- </p>
319
- </Grid.Column>
320
- </Grid.Row>
321
- </Grid>
322
- </Form.Field>
323
- </Form>
324
- </Segment>
325
-
326
- <Segment className="actions" clearing>
327
- <Button
328
- basic
329
- primary
330
- icon
331
- floated="right"
332
- type="submit"
333
- form="login-form"
334
- id="login-form-submit"
335
- aria-label={intl.formatMessage(messages.login)}
336
- title={intl.formatMessage(messages.login)}
337
- loading={ploneLoading}
338
- onClick={onLogin}
339
- >
340
- <Icon className="circled" name={aheadSVG} size="30px" />
341
- </Button>
342
-
343
- <Button
344
- basic
345
- secondary
346
- icon
347
- floated="right"
348
- id="login-form-cancel"
349
- as={Link}
350
- to="/"
351
- aria-label={intl.formatMessage(messages.cancel)}
352
- title={intl.formatMessage(messages.cancel)}
353
- >
354
- <Icon className="circled" name={clearSVG} size="30px" />
355
- </Button>
356
- </Segment>
357
- </Segment.Group>
358
-
359
- {/* External Login Providers - Outside the main form */}
360
- {validProviders && validProviders.length > 0 && (
361
- <div style={{ marginTop: '2rem', width: '100%' }}>
362
- <div style={{ textAlign: 'center', marginBottom: '1rem' }}>
363
- <FormattedMessage
364
- id="Or sign in with EEA Entra ID:"
365
- defaultMessage="Or sign in with EEA Entra ID:"
366
- />
367
- </div>
368
- <div style={{ width: '100%' }}>
369
- {!loading && validProviders && (
370
- <AuthProviders
371
- providers={validProviders}
372
- action="login"
373
- onSelectProvider={onSelectProvider}
374
- />
375
- )}
376
- {(loading || validProviders.length === 0) && (
377
- <div style={{ textAlign: 'center', padding: '1rem' }}>
378
- {intl.formatMessage(messages.loading)}
379
- </div>
380
- )}
381
- </div>
382
- </div>
383
- )}
384
- </Container>
385
- </div>
386
- );
387
- }
388
-
389
- export default injectIntl(Login);
@@ -1,8 +0,0 @@
1
- .ui.button.authenticationProvider {
2
- display: inline-flex;
3
- width: 100% !important;
4
- align-items: center;
5
- border-radius: 3px;
6
- margin: 0.5rem auto;
7
- box-shadow: rgba(0, 0, 0, 0.5) 0 1px 2px;
8
- }