@eeacms/volto-n2k 1.1.12 → 1.2.0

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,16 @@ 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.2.0](https://github.com/eea/volto-n2k/compare/1.1.12...1.2.0) - 3 February 2026
8
+
9
+ #### :rocket: New Features
10
+
11
+ - feat: add new variation for ImageGallery for Case Studies CT [nileshgulia1 - [`48173c5`](https://github.com/eea/volto-n2k/commit/48173c5626b94597e57af236ecb14a55383f63b1)]
12
+ - feat: add copyright text to tiles images refs-296409 [nileshgulia1 - [`614187b`](https://github.com/eea/volto-n2k/commit/614187b2d5c2cffcb1e2bf74ca72e88b2886520d)]
13
+
14
+ #### :hammer_and_wrench: Others
15
+
16
+ - bump v1.2.0 [nileshgulia1 - [`f94e2ff`](https://github.com/eea/volto-n2k/commit/f94e2ff9b244c126dff1930dcef265567712f4bc)]
7
17
  ### [1.1.12](https://github.com/eea/volto-n2k/compare/1.1.11...1.1.12) - 27 January 2026
8
18
 
9
19
  #### :hammer_and_wrench: Others
@@ -141,7 +151,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
141
151
 
142
152
  #### :house: Internal changes
143
153
 
144
- - chore: [JENKINS] Refactor automated testing [valentinab25 - [`e4f9fc8`](https://github.com/eea/volto-n2k/commit/e4f9fc800b753b97cca7c685bc47dd48804276f0)]
145
154
  - chore: husky, lint-staged use fixed versions [valentinab25 - [`647d621`](https://github.com/eea/volto-n2k/commit/647d621d52400c50f5bc629b3ddc4f2121f14ffa)]
146
155
  - chore:volto 16 in tests, update docs, fix stylelint overrides [valentinab25 - [`60d94b6`](https://github.com/eea/volto-n2k/commit/60d94b61ff8826abc57af9616793a1a247f585b5)]
147
156
 
@@ -156,11 +165,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
156
165
  - try to use volto-spotlight theme in jenkins [Miu Razvan - [`ec0b952`](https://github.com/eea/volto-n2k/commit/ec0b9525b967f907922ae660bd9f520119cd80c1)]
157
166
  - remove waitForResourceToLoad [ana-oprea - [`eaded9b`](https://github.com/eea/volto-n2k/commit/eaded9b9ecd1ca2eb78aa8dd65838c063d95db85)]
158
167
  - update image size from 300 to 800 px [Claudia Ifrim - [`8d9270a`](https://github.com/eea/volto-n2k/commit/8d9270a09506278ceaea25e8a72abdf5b22fcc78)]
159
- - test: [JENKINS] Use java17 for sonarqube scanner [valentinab25 - [`350f8a6`](https://github.com/eea/volto-n2k/commit/350f8a6928aafbf168472b572f8041a79f71f577)]
160
- - test: [JENKINS] Run cypress in started frontend container [valentinab25 - [`99b3a84`](https://github.com/eea/volto-n2k/commit/99b3a84a266710fadf7d430117359b741cadede8)]
161
- - test: [JENKINS] Add cpu limit on cypress docker [valentinab25 - [`050ac98`](https://github.com/eea/volto-n2k/commit/050ac982ec39e9a1b4885b665cdc118fca7b1283)]
162
- - test: [JENKINS] Increase shm-size to cypress docker [valentinab25 - [`3546040`](https://github.com/eea/volto-n2k/commit/35460409817f496fc752ab34e37d6d33a069b2e9)]
163
- - test: [JENKINS] Improve cypress time [valentinab25 - [`06a4ab1`](https://github.com/eea/volto-n2k/commit/06a4ab151799b8cdf4a316dbcb0c323e0f568e30)]
164
168
  - test: EN locales, pre-commit fix, feature PRs checks Refs #257193 [valentinab25 - [`4850d6a`](https://github.com/eea/volto-n2k/commit/4850d6a65349fe49dbe9244c30592ae38c9aeaba)]
165
169
  - test: Update Makefile and docker-compose to align it with Jenkinsfile [valentinab25 - [`2c91856`](https://github.com/eea/volto-n2k/commit/2c9185688a2fe6b36e5eeb2963f6c8676e3c5628)]
166
170
  ### [1.0.33](https://github.com/eea/volto-n2k/compare/1.0.32...1.0.33) - 3 July 2023
@@ -417,7 +421,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
417
421
  - Update [razvanMiu - [`42ab50e`](https://github.com/eea/volto-n2k/commit/42ab50e6681a47251d15ac06b836c6f8c27157fa)]
418
422
  - Added bubble chart [razvanMiu - [`89fba5e`](https://github.com/eea/volto-n2k/commit/89fba5e5db41aa955ba2d0ed58c9f0042c461504)]
419
423
  - Group species by id_eunis in species list [razvanMiu - [`543c957`](https://github.com/eea/volto-n2k/commit/543c9573b53acd8eecc9afbb6ae7beeddba53966)]
420
- - Add Sonarqube tag using frontend addons list [EEA Jenkins - [`2ca3e4c`](https://github.com/eea/volto-n2k/commit/2ca3e4c092211f92339791d71db81f5b4ca2d562)]
421
424
  - update maps - species and habitats distribution maps [Claudia Ifrim - [`ad12eb1`](https://github.com/eea/volto-n2k/commit/ad12eb141907d6f28444f1eafc3f687735d2a68d)]
422
425
  - update format for common name and author [Claudia Ifrim - [`26b7a2f`](https://github.com/eea/volto-n2k/commit/26b7a2f3d20c7701b57fb24f39fc7dfeceec3ce8)]
423
426
  - update format for species name (common / scientific) [Claudia Ifrim - [`abdedcf`](https://github.com/eea/volto-n2k/commit/abdedcfe645665031dedf050fd2c5cdde8c14a50)]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeacms/volto-n2k",
3
- "version": "1.1.12",
3
+ "version": "1.2.0",
4
4
  "description": "volto-n2k: Volto add-on",
5
5
  "main": "src/index.js",
6
6
  "author": "European Environment Agency: IDM2 A-Team",
@@ -1,19 +1,18 @@
1
1
  import React from 'react';
2
2
  import { SidebarPortal } from '@plone/volto/components';
3
- import InlineForm from '@plone/volto/components/manage/Form/InlineForm';
3
+ import BlockDataForm from '@plone/volto/components/manage/Form/BlockDataForm';
4
4
  import TilesImagesView from './View';
5
5
  import getSchema from './schema';
6
- import './styles.less';
7
6
 
8
7
  const Edit = (props) => {
9
- const { selected = false } = props;
10
- const schema = getSchema();
8
+ const { selected = false, data = {} } = props;
9
+ const schema = getSchema({ formData: data });
11
10
 
12
11
  return (
13
12
  <>
14
13
  <TilesImagesView {...props} mode="edit" />
15
14
  <SidebarPortal selected={selected}>
16
- <InlineForm
15
+ <BlockDataForm
17
16
  schema={schema}
18
17
  title={schema.title}
19
18
  onChangeField={(id, value) => {
@@ -22,6 +21,8 @@ const Edit = (props) => {
22
21
  [id]: value,
23
22
  });
24
23
  }}
24
+ onChangeBlock={props.onChangeBlock}
25
+ block={props.block}
25
26
  formData={props.data}
26
27
  />
27
28
  </SidebarPortal>
@@ -1,38 +1,16 @@
1
1
  import React from 'react';
2
- import { UniversalLink } from '@plone/volto/components';
3
- import cx from 'classnames';
4
- import './styles.less';
2
+ import { withBlockExtensions } from '@plone/volto/helpers/Extensions';
3
+ import config from '@plone/volto/registry';
5
4
 
6
5
  const View = (props) => {
7
- const { data = {}, mode = 'view' } = props;
8
- const images = data.images || [];
6
+ const { mode = 'view', variation } = props;
9
7
 
10
- return (
11
- <div className={cx('tiles-images', mode, data.theme || 'light')}>
12
- {mode === 'edit' && !images.length ? <p>Tiles images block</p> : ''}
13
- {images.map((image) => (
14
- <p
15
- key={`tile-${image.title}`}
16
- className={cx('p-image', {
17
- 'with-border': data.hasBorder ?? true,
18
- 'rounded-border': data.rounded ?? true,
19
- })}
20
- >
21
- <UniversalLink href={image.link || '#'} title={image.title}>
22
- <img
23
- src={`${image.image}/@@images/image/mini`}
24
- alt={image.title}
25
- style={
26
- data.size
27
- ? { width: `${data.size}px`, height: `${data.size}px` }
28
- : {}
29
- }
30
- />
31
- </UniversalLink>
32
- </p>
33
- ))}
34
- </div>
35
- );
8
+ const variations =
9
+ config.blocks?.blocksConfig['tiles_images']?.variations || [];
10
+ const defaultVariation = variations.filter((item) => item.isDefault)?.[0];
11
+ const Template = variation?.template ?? defaultVariation?.template ?? null;
12
+
13
+ return <Template {...props} mode={mode} />;
36
14
  };
37
15
 
38
- export default View;
16
+ export default withBlockExtensions(View);
@@ -1,4 +1,6 @@
1
1
  import TilesImagesEdit from './Edit';
2
+ import ImageGallery from './variations/ImageGallery/ImageGallery';
3
+ import DefaultView from './variations/Default/Default';
2
4
  import TilesImagesView from './View';
3
5
  import worldSVG from '@plone/volto/icons/world.svg';
4
6
 
@@ -18,6 +20,20 @@ export default function applyConfig(config) {
18
20
  addPermission: [],
19
21
  view: [],
20
22
  },
23
+ variations: [
24
+ {
25
+ id: 'default',
26
+ isDefault: true,
27
+ title: 'Default',
28
+ template: DefaultView,
29
+ },
30
+ {
31
+ id: 'imageGallery',
32
+ isDefault: false,
33
+ title: 'ImageGallery',
34
+ template: ImageGallery,
35
+ },
36
+ ],
21
37
  };
22
38
  return config;
23
39
  }
@@ -4,7 +4,7 @@ const imageSchema = {
4
4
  {
5
5
  id: 'default',
6
6
  title: 'Default',
7
- fields: ['image', 'link', 'title'],
7
+ fields: ['image', 'link', 'title', 'copyright'],
8
8
  },
9
9
  ],
10
10
  properties: {
@@ -19,11 +19,14 @@ const imageSchema = {
19
19
  title: {
20
20
  title: 'Title',
21
21
  },
22
+ copyright: {
23
+ title: 'Copyright',
24
+ },
22
25
  },
23
26
  required: ['url', 'title'],
24
27
  };
25
28
 
26
- export default function getSchema() {
29
+ export default function getSchema({ formData }) {
27
30
  return {
28
31
  title: 'Tiles images',
29
32
  fieldsets: [
@@ -32,11 +35,15 @@ export default function getSchema() {
32
35
  title: 'Default',
33
36
  fields: ['theme', 'images'],
34
37
  },
35
- {
36
- id: 'advanced',
37
- title: 'Advanced',
38
- fields: ['size', 'hasBorder', 'rounded'],
39
- },
38
+ ...(formData?.variation === 'default'
39
+ ? [
40
+ {
41
+ id: 'advanced',
42
+ title: 'Advanced',
43
+ fields: ['size', 'hasBorder', 'rounded'],
44
+ },
45
+ ]
46
+ : []),
40
47
  ],
41
48
  properties: {
42
49
  size: {
@@ -0,0 +1,36 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+
4
+ Copyright.propTypes = {
5
+ copyrightPosition: PropTypes.oneOf(['left', 'right']),
6
+ };
7
+
8
+ function Copyright({ children, ...rest }) {
9
+ return (
10
+ <div className={`eea copyright ${rest.copyrightPosition}`}>
11
+ <div className={'wrapper'}>{children}</div>
12
+ </div>
13
+ );
14
+ }
15
+
16
+ Copyright.Prefix = ({ children, ...rest }) =>
17
+ children ? (
18
+ <span {...rest} className={'icon-prefix'}>
19
+ {children}
20
+ </span>
21
+ ) : (
22
+ ''
23
+ );
24
+
25
+ Copyright.Icon = ({ children, ...rest }) => (
26
+ <span {...rest} className={'icon-wrapper'}>
27
+ {children}
28
+ </span>
29
+ );
30
+
31
+ Copyright.Text = ({ children, ...rest }) => (
32
+ <span {...rest} className={'icon-content'}>
33
+ {children}
34
+ </span>
35
+ );
36
+ export default Copyright;
@@ -0,0 +1,55 @@
1
+ import React from 'react';
2
+ import { UniversalLink } from '@plone/volto/components';
3
+ import cx from 'classnames';
4
+ import './styles.less';
5
+ import Copyright from './Copyright';
6
+
7
+ const DefaultView = (props) => {
8
+ const { mode = 'view', data = {} } = props;
9
+
10
+ const images = data.images || [];
11
+
12
+ return (
13
+ <div className={cx('tiles-images', mode, data.theme || 'light')}>
14
+ {mode === 'edit' && !images.length ? <p>Tiles images block</p> : ''}
15
+ {images.map((image) => {
16
+ const { copyright } = image;
17
+ return (
18
+ <p
19
+ key={`tile-${image.title}`}
20
+ className={cx('p-image', {
21
+ 'with-border': data.hasBorder ?? true,
22
+ 'rounded-border': data.rounded ?? true,
23
+ })}
24
+ >
25
+ <UniversalLink href={image.link || '#'} title={image.title}>
26
+ <>
27
+ <img
28
+ src={`${image.image}/@@images/image/mini`}
29
+ alt={image.title}
30
+ style={
31
+ data.size
32
+ ? { width: `${data.size}px`, height: `${data.size}px` }
33
+ : {}
34
+ }
35
+ />
36
+ <div className={`copyright-wrapper ${'left'}`}>
37
+ {copyright ? (
38
+ <Copyright copyrightPosition={'left'}>
39
+ <Copyright.Icon>@</Copyright.Icon>
40
+ <Copyright.Text>{copyright}</Copyright.Text>
41
+ </Copyright>
42
+ ) : (
43
+ ''
44
+ )}
45
+ </div>
46
+ </>
47
+ </UniversalLink>
48
+ </p>
49
+ );
50
+ })}
51
+ </div>
52
+ );
53
+ };
54
+
55
+ export default DefaultView;
@@ -0,0 +1,106 @@
1
+ import React from 'react';
2
+ import loadable from '@loadable/component';
3
+ import { Modal, Image } from 'semantic-ui-react';
4
+
5
+ import 'slick-carousel/slick/slick.css';
6
+ import 'slick-carousel/slick/slick-theme.css';
7
+
8
+ import './styles.less';
9
+
10
+ const Slider = loadable(() => import('react-slick'));
11
+
12
+ const ImageGallery = (props) => {
13
+ const { data = {}, mode } = props;
14
+ const items = data.images || [];
15
+ const [open, setOpen] = React.useState(false);
16
+ const [slideIndex, setSlideIndex] = React.useState(0);
17
+
18
+ const [updateCount, setUpdateCount] = React.useState(0);
19
+ const sliderRef = React.useRef(null);
20
+
21
+ const carouselSettings = React.useMemo(
22
+ () => ({
23
+ afterChange: () => setUpdateCount(updateCount + 1),
24
+ beforeChange: (current, next) => setSlideIndex(next),
25
+ infinite: true,
26
+ slidesToShow: 1,
27
+ slidesToScroll: 1,
28
+ dots: false,
29
+ arrows: true,
30
+ adaptiveHeight: true,
31
+ autoplay: false,
32
+ fade: false,
33
+ useTransform: false,
34
+ initialSlide: slideIndex,
35
+ }),
36
+ [slideIndex, setSlideIndex, updateCount],
37
+ );
38
+
39
+ const handleClick = () => {
40
+ if (items.length) {
41
+ setSlideIndex(0);
42
+ setOpen(true);
43
+ }
44
+ };
45
+
46
+ const image = items[slideIndex];
47
+
48
+ return (
49
+ <div className="image-gallery">
50
+ <div
51
+ tabIndex={0}
52
+ role="button"
53
+ onKeyDown={handleClick}
54
+ onClick={handleClick}
55
+ >
56
+ <Image
57
+ src={`${items[0]?.image}/@@images/image/preview`}
58
+ alt={items[0]?.title}
59
+ className="preview-image"
60
+ />
61
+ </div>
62
+ {mode === 'view' ? (
63
+ <Modal
64
+ closeIcon
65
+ open={open}
66
+ className="slider-modal"
67
+ onClose={() => setOpen(false)}
68
+ onOpen={() => setOpen(true)}
69
+ >
70
+ <Modal.Content>
71
+ <h3>{image?.title}</h3>
72
+ <p>{image?.description}</p>
73
+ <Slider {...carouselSettings} ref={sliderRef}>
74
+ {items.map((item, i) => {
75
+ return item.copyright ? (
76
+ <div key={i}>
77
+ <div className="image-slide">
78
+ <div className="image-rights">@ {item.copyright}</div>
79
+ <Image
80
+ src={`${item.image}/@@images/image/larger`}
81
+ alt={item?.title}
82
+ />
83
+ </div>
84
+ </div>
85
+ ) : (
86
+ <Image
87
+ key={i}
88
+ src={`${item.image}/@@images/image/larger`}
89
+ alt={item?.title}
90
+ />
91
+ );
92
+ })}
93
+ </Slider>
94
+ <div className="slide-image-count">
95
+ <strong>{slideIndex + 1}</strong> of {items.length}
96
+ </div>
97
+ </Modal.Content>
98
+ </Modal>
99
+ ) : (
100
+ <p>Save the block to preview the Image Gallery Carousel.</p>
101
+ )}
102
+ </div>
103
+ );
104
+ };
105
+
106
+ export default ImageGallery;
@@ -0,0 +1,17 @@
1
+ .image-slide {
2
+ position: relative;
3
+ display: inline-block;
4
+
5
+ .image-rights {
6
+ position: absolute;
7
+ z-index: 100;
8
+ right: 0em;
9
+ bottom: 0em;
10
+ left: 0em;
11
+ padding: 10px;
12
+ // background: rgba(0, 0, 0, 0.5); /* optional: semi-transparent background */
13
+ color: white; /* text color */
14
+ font-size: 14px; /* adjust font size as needed */
15
+ text-align: left; /* optional: center the text */
16
+ }
17
+ }