@eeacms/volto-clms-theme 1.1.260 → 1.1.262

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,17 @@ 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.262](https://github.com/eea/volto-clms-theme/compare/1.1.261...1.1.262) - 13 November 2025
8
+
9
+ #### :bug: Bug Fixes
10
+
11
+ - fix: Product pages having subtabs not positioning correctly - refs #293723 [ana-oprea - [`a564fbc`](https://github.com/eea/volto-clms-theme/commit/a564fbc6b7a5f4384c0eccf950c5dd6382963ab7)]
12
+
13
+ ### [1.1.261](https://github.com/eea/volto-clms-theme/compare/1.1.260...1.1.261) - 23 October 2025
14
+
15
+ #### :hammer_and_wrench: Others
16
+
17
+ - Refs #293096 - Custom CSRF protection for our forms. Use restapi endpoint to get CSRF token and set header. [GhitaB - [`2eaba3c`](https://github.com/eea/volto-clms-theme/commit/2eaba3c52309edbe86d8be7c5c6676397c898e31)]
7
18
  ### [1.1.260](https://github.com/eea/volto-clms-theme/compare/1.1.259...1.1.260) - 10 October 2025
8
19
 
9
20
  #### :house: Internal changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeacms/volto-clms-theme",
3
- "version": "1.1.260",
3
+ "version": "1.1.262",
4
4
  "description": "volto-clms-theme: Volto theme for CLMS site",
5
5
  "main": "src/index.js",
6
6
  "author": "CodeSyntax for the European Environment Agency",
@@ -2,7 +2,8 @@ import React, { useState, useEffect, useReducer, useRef } from 'react';
2
2
  import { useSelector, useDispatch } from 'react-redux';
3
3
  import PropTypes from 'prop-types';
4
4
  import { useIntl, defineMessages } from 'react-intl';
5
- import { submitForm } from 'volto-form-block/actions';
5
+ import { submitForm } from '../../../../customizations/volto-form-block/actions';
6
+
6
7
  import { getFieldName } from 'volto-form-block/components/utils';
7
8
  import FormView from 'volto-form-block/components/FormView';
8
9
  import { formatDate } from '@plone/volto/helpers/Utils/Date';
@@ -77,6 +78,7 @@ const View = ({ data, id, path }) => {
77
78
 
78
79
  const [formState, setFormState] = useReducer(formStateReducer, initialState);
79
80
  const [formErrors, setFormErrors] = useState([]);
81
+ const [csrfToken, setCsrfToken] = useState(null);
80
82
  const submitResults = useSelector((state) => state.submitForm);
81
83
  const captchaToken = useRef();
82
84
 
@@ -84,6 +86,22 @@ const View = ({ data, id, path }) => {
84
86
  setFormData({ field, value: { field_id, value, ...extras } });
85
87
  };
86
88
 
89
+ useEffect(() => {
90
+ fetch(`/++api++/@clms-get-csrf-token`, {
91
+ credentials: 'include',
92
+ headers: {
93
+ Accept: 'application/json',
94
+ },
95
+ })
96
+ .then((r) => {
97
+ if (!r.ok) throw new Error(`${r.status} ${r.statusText}`);
98
+ return r.json();
99
+ })
100
+ .then((data) => {
101
+ setCsrfToken(data.token);
102
+ });
103
+ }, [path]);
104
+
87
105
  useEffect(() => {
88
106
  if (formErrors.length > 0) {
89
107
  isValidForm();
@@ -204,6 +222,7 @@ const View = ({ data, id, path }) => {
204
222
  })),
205
223
  attachments,
206
224
  captcha,
225
+ csrfToken,
207
226
  ),
208
227
  );
209
228
  setFormState({ type: FORM_STATES.loading });
@@ -124,7 +124,15 @@ const TabsComponent = ({
124
124
  }, [activeTab, expandedTab, groupedTabs]);
125
125
 
126
126
  useEffect(() => {
127
- scrollToContentSection();
127
+ const urlParams = new URLSearchParams(location.search);
128
+ const hasHash = location.hash.length > 1;
129
+ const hasQueryTab = urlParams.has('tab');
130
+
131
+ if (hasHash || hasQueryTab) {
132
+ scrollToContentSection();
133
+ } else {
134
+ window.scrollTo({ top: 0, behavior: 'smooth' });
135
+ }
128
136
  }, [activeTab, location.hash.length, location.search]);
129
137
 
130
138
  return (
@@ -0,0 +1,90 @@
1
+ /**
2
+ * exportCsvFormData action
3
+ * @module actions/submitForm
4
+ */
5
+
6
+ export const SUBMIT_FORM_ACTION = 'SUBMIT_FORM_ACTION';
7
+
8
+ /**
9
+ * submitForm function
10
+ * @function submitForm
11
+ * @param {string} path
12
+ * @param {string} block_id
13
+ * @param {Object} data
14
+ * @returns {Object} attachments
15
+ *
16
+ * OVERRIDED to add CSRF token for CLMS custom forms
17
+ */
18
+ export function submitForm(
19
+ path = '',
20
+ block_id,
21
+ data,
22
+ attachments,
23
+ captcha,
24
+ csrfToken,
25
+ ) {
26
+ return {
27
+ type: SUBMIT_FORM_ACTION,
28
+ request: {
29
+ op: 'post',
30
+ path: path + '/@submit-form',
31
+ headers: {
32
+ 'X-CSRF-TOKEN': csrfToken,
33
+ },
34
+ data: {
35
+ block_id,
36
+ data,
37
+ attachments,
38
+ captcha,
39
+ },
40
+ },
41
+ };
42
+ }
43
+
44
+ /**
45
+ * exportCsvFormData action
46
+ * @module actions/exportCsvFormData
47
+ */
48
+ export const EXPORT_CSV_FORMDATA = 'EXPORT_CSV_FORMDATA';
49
+
50
+ export function exportCsvFormData(path = '') {
51
+ return {
52
+ type: EXPORT_CSV_FORMDATA,
53
+ request: {
54
+ op: 'get',
55
+ path: path + '/@form-data-export',
56
+ },
57
+ };
58
+ }
59
+
60
+ /**
61
+ * getFormData action
62
+ * @module actions/getFormData
63
+ */
64
+ export const GET_FORM_DATA = 'GET_FORMDATA';
65
+
66
+ export function getFormData(path = '') {
67
+ return {
68
+ type: GET_FORM_DATA,
69
+ request: {
70
+ op: 'get',
71
+ path: path + '/@form-data',
72
+ },
73
+ };
74
+ }
75
+
76
+ /**
77
+ * clearFormData action
78
+ * @module actions/getFormData
79
+ */
80
+ export const CLEAR_FORM_DATA = 'CLEAR_FORM_DATA';
81
+
82
+ export function clearFormData(path = '') {
83
+ return {
84
+ type: CLEAR_FORM_DATA,
85
+ request: {
86
+ op: 'get',
87
+ path: path + '/@form-data-clear',
88
+ },
89
+ };
90
+ }