io-sanita-theme 2.13.0 → 2.15.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.
Files changed (32) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/RELEASE.md +16 -0
  3. package/locales/de/LC_MESSAGES/volto.po +5 -0
  4. package/locales/en/LC_MESSAGES/volto.po +5 -0
  5. package/locales/es/LC_MESSAGES/volto.po +5 -0
  6. package/locales/fr/LC_MESSAGES/volto.po +5 -0
  7. package/locales/it/LC_MESSAGES/volto.po +5 -0
  8. package/locales/volto.pot +6 -1
  9. package/package.json +2 -2
  10. package/src/components/Home/HomeSchemaOrg.jsx +38 -14
  11. package/src/components/View/ComeFarePer/ComeFarePerSchemaOrg.jsx +73 -0
  12. package/src/components/View/ComeFarePer/ComeFarePerView.jsx +2 -0
  13. package/src/components/View/ComeFarePer/Steps/Steps.jsx +4 -23
  14. package/src/components/View/ComeFarePer/Steps/helpers.js +43 -0
  15. package/src/components/View/ComeFarePer/index.js +5 -0
  16. package/src/components/View/Evento/EventoSchemaOrg.jsx +137 -0
  17. package/src/components/View/Evento/EventoView.jsx +2 -0
  18. package/src/components/View/Evento/index.js +6 -0
  19. package/src/components/View/NewsItem/NewsItemSchemaOrg.jsx +69 -0
  20. package/src/components/View/NewsItem/NewsItemView.jsx +2 -0
  21. package/src/components/View/NewsItem/index.js +50 -56
  22. package/src/components/View/Persona/PersonaSchemaOrg.jsx +63 -0
  23. package/src/components/View/Persona/PersonaView.jsx +2 -0
  24. package/src/components/View/Persona/index.js +6 -0
  25. package/src/components/View/Servizio/ServizioSchemaOrg.jsx +126 -0
  26. package/src/components/View/Servizio/ServizioView.jsx +2 -0
  27. package/src/components/View/Servizio/index.js +107 -84
  28. package/src/components/View/Struttura/StrutturaSchemaOrg.jsx +70 -0
  29. package/src/components/View/Struttura/StrutturaView.jsx +2 -0
  30. package/src/components/View/Struttura/index.js +5 -0
  31. package/src/components/View/commons/Metadata/Metadata.jsx +4 -0
  32. package/src/components/View/commons/PageHeader/PageHeaderPersona.jsx +9 -10
package/CHANGELOG.md CHANGED
@@ -1,5 +1,33 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.15.0](https://github.com/RedTurtle/io-sanita-theme/compare/2.14.0...2.15.0) (2025-05-20)
4
+
5
+ ### Features
6
+
7
+ * added SchemaOrg ct servizio ([#88](https://github.com/RedTurtle/io-sanita-theme/issues/88)) ([7cd86d5](https://github.com/RedTurtle/io-sanita-theme/commit/7cd86d5338d0325a93931f590f11234a2cd11fb2))
8
+ * added schemaOrg Struttura ([#89](https://github.com/RedTurtle/io-sanita-theme/issues/89)) ([5b7c091](https://github.com/RedTurtle/io-sanita-theme/commit/5b7c0917da5d9dbed9e3785936645e040707e4cf))
9
+ * Schema.org Event and Homepage ([#87](https://github.com/RedTurtle/io-sanita-theme/issues/87)) ([073148a](https://github.com/RedTurtle/io-sanita-theme/commit/073148a9987b6d2cb045c3a0c274e911ca9a7258))
10
+
11
+ ### Documentation
12
+
13
+ * updated RELEASE.md ([ef8c5d5](https://github.com/RedTurtle/io-sanita-theme/commit/ef8c5d57214932d53f3fd26dcce58703a03d5f4f))
14
+
15
+ ## [2.14.0](https://github.com/RedTurtle/io-sanita-theme/compare/2.13.0...2.14.0) (2025-05-19)
16
+
17
+ ### Features
18
+
19
+ * Persona Schema.org ([a22ad2f](https://github.com/RedTurtle/io-sanita-theme/commit/a22ad2f005e1fb907eba408d0708b3e47f165c8d))
20
+ * Schema.org ComeFarePer ([#84](https://github.com/RedTurtle/io-sanita-theme/issues/84)) ([7832265](https://github.com/RedTurtle/io-sanita-theme/commit/78322651fec3d2c9b84a72cb38a12009e5af6849))
21
+ * schema.org for CT Notizia ([#85](https://github.com/RedTurtle/io-sanita-theme/issues/85)) ([8774a96](https://github.com/RedTurtle/io-sanita-theme/commit/8774a96ad440640ab5b13e47bbd5c752ef6e232e))
22
+
23
+ ### Bug Fixes
24
+
25
+ * missed id 'rights' for Metadata field ([#86](https://github.com/RedTurtle/io-sanita-theme/issues/86)) ([3d3bf9d](https://github.com/RedTurtle/io-sanita-theme/commit/3d3bf9d2965da118de0693244bd71d67137ca8a9))
26
+
27
+ ### Maintenance
28
+
29
+ * udpated volto-gdpr-privacy to fix arrow in widget ([4c5c33a](https://github.com/RedTurtle/io-sanita-theme/commit/4c5c33a232760a2eebe91813861473c8a3653d34))
30
+
3
31
  ## [2.13.0](https://github.com/RedTurtle/io-sanita-theme/compare/2.12.2...2.13.0) (2025-04-24)
4
32
 
5
33
  ### Features
package/RELEASE.md CHANGED
@@ -41,6 +41,22 @@
41
41
  - ...
42
42
  -->
43
43
 
44
+ ## Versione 2.15.0 (20/05/2025)
45
+
46
+ ### Novità
47
+
48
+ - Implementato lo Schema.org per i tipi di contenuti Struttura, Servizio ed Evento
49
+
50
+ ### Migliorie
51
+
52
+ - Migliorato lo Schema.org della Homepage
53
+
54
+ ## Versione 2.14.0 (19/05/2025)
55
+
56
+ ### Novità
57
+
58
+ - Implementato lo Schema.org per i tipi di contenuti Notizia, Persona e ComeFarePer
59
+
44
60
  ## Versione 2.11.1 (31/03/2025)
45
61
 
46
62
  ### Fix
@@ -2701,6 +2701,11 @@ msgstr ""
2701
2701
  msgid "related_items"
2702
2702
  msgstr ""
2703
2703
 
2704
+ #. Default: "Diritti"
2705
+ #: components/View/commons/Metadata/Metadata
2706
+ msgid "rights"
2707
+ msgstr "Rechte"
2708
+
2704
2709
  #. Default: "il giorno"
2705
2710
  #: overrideTranslations
2706
2711
  msgid "rrule_in"
@@ -2696,6 +2696,11 @@ msgstr "Reading time"
2696
2696
  msgid "related_items"
2697
2697
  msgstr "Related items"
2698
2698
 
2699
+ #. Default: "Diritti"
2700
+ #: components/View/commons/Metadata/Metadata
2701
+ msgid "rights"
2702
+ msgstr "Rights"
2703
+
2699
2704
  #. Default: "il giorno"
2700
2705
  #: overrideTranslations
2701
2706
  msgid "rrule_in"
@@ -2703,6 +2703,11 @@ msgstr "Tiempo de leer"
2703
2703
  msgid "related_items"
2704
2704
  msgstr ""
2705
2705
 
2706
+ #. Default: "Diritti"
2707
+ #: components/View/commons/Metadata/Metadata
2708
+ msgid "rights"
2709
+ msgstr "Derechos"
2710
+
2706
2711
  #. Default: "il giorno"
2707
2712
  #: overrideTranslations
2708
2713
  msgid "rrule_in"
@@ -2703,6 +2703,11 @@ msgstr "Temps de lecture"
2703
2703
  msgid "related_items"
2704
2704
  msgstr ""
2705
2705
 
2706
+ #. Default: "Diritti"
2707
+ #: components/View/commons/Metadata/Metadata
2708
+ msgid "rights"
2709
+ msgstr "Droits"
2710
+
2706
2711
  #. Default: "il giorno"
2707
2712
  #: overrideTranslations
2708
2713
  msgid "rrule_in"
@@ -2696,6 +2696,11 @@ msgstr "Tempo di lettura"
2696
2696
  msgid "related_items"
2697
2697
  msgstr ""
2698
2698
 
2699
+ #. Default: "Diritti"
2700
+ #: components/View/commons/Metadata/Metadata
2701
+ msgid "rights"
2702
+ msgstr ""
2703
+
2699
2704
  #. Default: "il giorno"
2700
2705
  #: overrideTranslations
2701
2706
  msgid "rrule_in"
package/locales/volto.pot CHANGED
@@ -1,7 +1,7 @@
1
1
  msgid ""
2
2
  msgstr ""
3
3
  "Project-Id-Version: Plone\n"
4
- "POT-Creation-Date: 2025-04-24T07:37:09.946Z\n"
4
+ "POT-Creation-Date: 2025-05-16T08:50:36.599Z\n"
5
5
  "Last-Translator: Plone i18n <plone-i18n@lists.sourceforge.net>\n"
6
6
  "Language-Team: Plone i18n <plone-i18n@lists.sourceforge.net>\n"
7
7
  "Content-Type: text/plain; charset=utf-8\n"
@@ -2698,6 +2698,11 @@ msgstr ""
2698
2698
  msgid "related_items"
2699
2699
  msgstr ""
2700
2700
 
2701
+ #. Default: "Diritti"
2702
+ #: components/View/commons/Metadata/Metadata
2703
+ msgid "rights"
2704
+ msgstr ""
2705
+
2701
2706
  #. Default: "il giorno"
2702
2707
  #: overrideTranslations
2703
2708
  msgid "rrule_in"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "io-sanita-theme",
3
- "version": "2.13.0",
3
+ "version": "2.15.0",
4
4
  "description": "io-sanita-theme: Volto add-on",
5
5
  "main": "src/index.js",
6
6
  "license": "MIT",
@@ -104,7 +104,7 @@
104
104
  "volto-feedback-italia": "1.0.8",
105
105
  "volto-form-block": "3.10.2",
106
106
  "volto-form-block-italia": "1.0.5",
107
- "volto-gdpr-privacy": "2.2.14",
107
+ "volto-gdpr-privacy": "2.2.15",
108
108
  "volto-querywidget-with-browser": "0.4.3",
109
109
  "volto-rss-block": "3.0.1",
110
110
  "volto-rt-carousel": "1.0.0",
@@ -1,30 +1,54 @@
1
1
  import { useIntl } from 'react-intl';
2
2
  import { toPublicURL } from '@plone/volto/helpers';
3
+ import { useSelector } from 'react-redux';
3
4
  import { SiteProperty } from 'volto-site-settings';
4
5
  import { SchemaOrg, getSiteProperty } from 'io-sanita-theme/helpers';
5
6
 
6
7
  const HomeSchemaOrg = ({ content }) => {
7
8
  const intl = useIntl();
9
+ const socialSettings = useSelector((state) => state.socialSettings?.results);
10
+
11
+ const name = SiteProperty({
12
+ property: 'site_title',
13
+ defaultValue: getSiteProperty('siteTitle', intl.locale),
14
+ getValue: true,
15
+ });
16
+ const description = SiteProperty({
17
+ property: 'site_subtitle',
18
+ defaultValue: getSiteProperty('siteSubtitle', intl.locale),
19
+ getValue: true,
20
+ });
21
+
8
22
  let schemaOrg = null;
9
23
  if (content?.['@type'] == 'Plone Site' || content?.['@type'] == 'LRF') {
10
- const name = SiteProperty({
11
- property: 'site_title',
12
- defaultValue: getSiteProperty('siteTitle', intl.locale),
13
- getValue: true,
14
- });
15
- const description = SiteProperty({
16
- property: 'site_subtitle',
17
- defaultValue: getSiteProperty('siteSubtitle', intl.locale),
18
- getValue: true,
19
- });
24
+ let socialLinks = null;
25
+ if (socialSettings && socialSettings?.length > 0) {
26
+ socialLinks = socialSettings.map((item) => item.url);
27
+ }
20
28
 
21
29
  schemaOrg = {
22
- '@type': 'MedicalOrganization',
23
- name: name,
24
- description: description,
25
- url: toPublicURL(content['@id']),
30
+ '@graph': [
31
+ {
32
+ '@type': 'WebSite',
33
+ url: toPublicURL('/'),
34
+ name: name,
35
+ description: description || null,
36
+ potentialAction: {
37
+ '@type': 'SearchAction',
38
+ target: toPublicURL(content['@id']) + '/search',
39
+ },
40
+ },
41
+ {
42
+ '@type': 'MedicalOrganization',
43
+ name: name,
44
+ description: description || null,
45
+ url: toPublicURL('/'),
46
+ sameAs: socialLinks,
47
+ },
48
+ ],
26
49
  };
27
50
  }
51
+
28
52
  return schemaOrg ? <SchemaOrg schema={schemaOrg} /> : <></>;
29
53
  };
30
54
 
@@ -0,0 +1,73 @@
1
+ import { toPublicURL } from '@plone/volto/helpers';
2
+ import {
3
+ SchemaOrg,
4
+ SchemaOrgUtils,
5
+ richTextHasContent,
6
+ } from 'io-sanita-theme/helpers';
7
+
8
+ import { useLoadSteps } from 'io-sanita-theme/components/View/ComeFarePer/Steps/helpers';
9
+ import { positions } from 'slate';
10
+
11
+ const ComeFarePerSchemaOrg = ({ content }) => {
12
+ const siteTitle = SchemaOrgUtils.getSiteTitle();
13
+
14
+ let description = [];
15
+ let _yield = [];
16
+ let steps = content?.items?.filter((item) => item['@type'] === 'Step') ?? [];
17
+ const { loadedSteps } = useLoadSteps(steps);
18
+
19
+ //description
20
+ if (content.description) {
21
+ description.push(content.description);
22
+ }
23
+ if (content.sottotitolo) {
24
+ description.push(content.sottotitolo);
25
+ }
26
+
27
+ let schemaOrg = {
28
+ '@type': 'HowTo',
29
+ url: toPublicURL(content['@id']),
30
+ };
31
+
32
+ if (description.length > 0) {
33
+ schemaOrg.description = description.join('. ');
34
+ }
35
+
36
+ //yield -- The quantity that results by performing instructions. For example, a paper airplane, 10 personalized candles.
37
+ if (richTextHasContent(content.panoramica)) {
38
+ _yield.push(SchemaOrgUtils.fieldDataToPlainText(content.panoramica));
39
+ }
40
+ if (_yield.length > 0) {
41
+ schemaOrg.yield = _yield.join('. ');
42
+ }
43
+
44
+ if (richTextHasContent(content.come_fare)) {
45
+ schemaOrg.conditionsOfAccess = SchemaOrgUtils.fieldDataToPlainText(
46
+ content.come_fare,
47
+ );
48
+ }
49
+ if (richTextHasContent(content.a_chi_si_rivolge)) {
50
+ schemaOrg.audience = SchemaOrgUtils.fieldDataToPlainText(
51
+ content.a_chi_si_rivolge,
52
+ );
53
+ }
54
+
55
+ if (steps.length > 0 && Object.keys(loadedSteps).length === steps.length) {
56
+ schemaOrg.step = Object.keys(loadedSteps).map((id, index) => {
57
+ const step = loadedSteps[id];
58
+ const stepSchemaOrg = {
59
+ '@type': 'HowToStep',
60
+ position: index + 1,
61
+ name: step.title ?? 'Step ' + (index + 1),
62
+ };
63
+ if (richTextHasContent(step.testo)) {
64
+ stepSchemaOrg.text = SchemaOrgUtils.fieldDataToPlainText(step.testo);
65
+ }
66
+ return stepSchemaOrg;
67
+ });
68
+ }
69
+
70
+ return <SchemaOrg content={content} schema={schemaOrg} />;
71
+ };
72
+
73
+ export default ComeFarePerSchemaOrg;
@@ -26,6 +26,7 @@ import {
26
26
  ComeFarePerComeFare,
27
27
  ComeFarePerApprofondimenti,
28
28
  ComeFarePerUlterioriInformazioni,
29
+ ComeFarePerSchemaOrg,
29
30
  } from 'io-sanita-theme/components/View/ComeFarePer';
30
31
 
31
32
  export const ComeFarePerViewSectionsOrder = [
@@ -39,6 +40,7 @@ export const ComeFarePerViewSectionsOrder = [
39
40
  ComeFarePerUlterioriInformazioni,
40
41
  },
41
42
  { /* METADATA */ component: Metadata },
43
+ { /* SCHEMA ORG*/ component: ComeFarePerSchemaOrg },
42
44
  ];
43
45
 
44
46
  /**
@@ -6,8 +6,7 @@
6
6
  import React, { useState, useEffect } from 'react';
7
7
  import { useIntl, defineMessages } from 'react-intl';
8
8
  import { useDispatch, useSelector } from 'react-redux';
9
- import { getContent, resetContent } from '@plone/volto/actions/content/content';
10
- import { flattenToAppURL } from '@plone/volto/helpers/Url/Url';
9
+
11
10
  import PropTypes from 'prop-types';
12
11
  import {
13
12
  richTextHasContent,
@@ -23,7 +22,7 @@ import {
23
22
  } from 'design-react-kit';
24
23
  import { Icon, CardPlace, CardContatti } from 'io-sanita-theme/components';
25
24
  import { Attachments } from 'io-sanita-theme/components/View/commons';
26
-
25
+ import { useLoadSteps } from 'io-sanita-theme/components/View/ComeFarePer/Steps/helpers';
27
26
  import './steps.scss';
28
27
 
29
28
  const messages = defineMessages({
@@ -72,25 +71,7 @@ const Steps = ({ content, steps = [] }) => {
72
71
  setActiveItem('');
73
72
  }, [allOpen]);
74
73
 
75
- const searchSteps = useSelector((state) => state.content?.subrequests);
76
-
77
- // one request is made for every step
78
- useEffect(() => {
79
- steps.forEach((item) => {
80
- const url = flattenToAppURL(item['@id']);
81
- const loaded = searchSteps?.[url]?.loading || searchSteps?.[url]?.loaded;
82
-
83
- if (!loaded) {
84
- dispatch(getContent(url, null, url));
85
- }
86
- });
87
-
88
- return () => {
89
- steps.forEach((item) => {
90
- dispatch(resetContent(flattenToAppURL(item['@id'])));
91
- });
92
- };
93
- }, []);
74
+ const { loadedSteps } = useLoadSteps(steps);
94
75
 
95
76
  return steps.length > 0 ? (
96
77
  <div className="steps">
@@ -114,7 +95,7 @@ const Steps = ({ content, steps = [] }) => {
114
95
  </Button>
115
96
  <Accordion background="active">
116
97
  {steps.map((s, index) => {
117
- const step = searchSteps[flattenToAppURL(s['@id'])]?.data ?? s;
98
+ const step = loadedSteps[s['@id']] ?? s;
118
99
  const itemIndex = index + 1;
119
100
  const toggleItem = () => {
120
101
  setActiveItem(activeItem !== itemIndex ? itemIndex : '');
@@ -0,0 +1,43 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import { useDispatch, useSelector } from 'react-redux';
3
+ import { flattenToAppURL } from '@plone/volto/helpers/Url/Url';
4
+ import { getContent, resetContent } from '@plone/volto/actions/content/content';
5
+
6
+ export const useLoadSteps = (steps = []) => {
7
+ const dispatch = useDispatch();
8
+ const subrequests = useSelector((state) => state.content?.subrequests);
9
+ const [loadedSteps, setLoadedSteps] = useState({});
10
+
11
+ // one request is made for every step
12
+ useEffect(() => {
13
+ steps.forEach((item) => {
14
+ const url = flattenToAppURL(item['@id']);
15
+ const subrequest_id = item['@id'];
16
+ const requested =
17
+ subrequests?.[subrequest_id]?.loading ||
18
+ subrequests?.[subrequest_id]?.loaded;
19
+
20
+ if (!requested) {
21
+ dispatch(getContent(url, null, subrequest_id));
22
+ }
23
+ });
24
+
25
+ return () => {
26
+ steps.forEach((item) => {
27
+ dispatch(resetContent(subrequest_id));
28
+ });
29
+ };
30
+ }, []);
31
+
32
+ useEffect(() => {
33
+ steps.forEach((item) => {
34
+ const subrequest_id = item['@id'];
35
+ const step = subrequests?.[subrequest_id]?.data;
36
+ if (subrequests?.[subrequest_id]?.loaded && step) {
37
+ setLoadedSteps({ ...loadedSteps, [item['@id']]: step });
38
+ }
39
+ });
40
+ }, [subrequests]);
41
+
42
+ return { loadedSteps };
43
+ };
@@ -36,6 +36,11 @@ export const ComeFarePerApprofondimenti = loadable(() =>
36
36
  /* webpackChunkName: "ISComeFarePerView" */ 'io-sanita-theme/components/View/ComeFarePer/ComeFarePerApprofondimenti'
37
37
  ),
38
38
  );
39
+ export const ComeFarePerSchemaOrg = loadable(() =>
40
+ import(
41
+ /* webpackChunkName: "ISComeFarePerView" */ 'io-sanita-theme/components/View/ComeFarePer/ComeFarePerSchemaOrg'
42
+ ),
43
+ );
39
44
  export const Steps = loadable(() =>
40
45
  import(
41
46
  /* webpackChunkName: "ISComeFarePerView" */ 'io-sanita-theme/components/View/ComeFarePer/Steps/Steps'
@@ -0,0 +1,137 @@
1
+ import { toPublicURL } from '@plone/volto/helpers';
2
+ import {
3
+ SchemaOrg,
4
+ SchemaOrgUtils,
5
+ richTextHasContent,
6
+ } from 'io-sanita-theme/helpers';
7
+
8
+ const EventoSchemaOrg = ({ content }) => {
9
+ let schemaOrg = {
10
+ '@type': 'Event',
11
+ name: content?.title,
12
+ startDate: content?.start,
13
+ endDate: content?.end,
14
+ url: toPublicURL(content['@id']),
15
+ };
16
+
17
+ let description = [];
18
+ if (content.description) {
19
+ description.push(content.description);
20
+ }
21
+ if (richTextHasContent(content.descrizione_estesa)) {
22
+ description.push(
23
+ SchemaOrgUtils.fieldDataToPlainText(content.descrizione_estesa),
24
+ );
25
+ }
26
+ if (description.length > 0) {
27
+ schemaOrg.description = description.join('. ');
28
+ }
29
+
30
+ // se l'evento è online
31
+ if (richTextHasContent(content.webinar)) {
32
+ schemaOrg.eventAttendanceMode = SchemaOrgUtils.fieldDataToPlainText(
33
+ content.webinar,
34
+ );
35
+ }
36
+ // se l'evento è fisico priorità all'indirizzo scritto direttamente nel CT, in alternativa la prima struttura associata
37
+ if (content.street && content.zip_code && content.city) {
38
+ schemaOrg.location = {
39
+ '@type': 'Place',
40
+ name: content?.nome_sede || 'Sede',
41
+ address: {
42
+ '@type': 'PostalAddress',
43
+ streetAddress: content.street,
44
+ addressLocality: content.city,
45
+ postalCode: content.zip_code,
46
+ addressCountry: 'IT',
47
+ },
48
+ };
49
+ } else if (content.struttura_correlata.length > 0) {
50
+ schemaOrg.location = {
51
+ '@type': 'Place',
52
+ name: content.struttura_correlata[0].title,
53
+ address: {
54
+ '@type': 'PostalAddress',
55
+ // questi sono campi obbligatori per la struttura
56
+ streetAddress: content.struttura_correlata[0].street,
57
+ addressLocality: content.struttura_correlata[0].city,
58
+ postalCode: content.struttura_correlata[0].zip_code,
59
+ addressCountry: 'IT',
60
+ },
61
+ };
62
+ }
63
+
64
+ // organizzatore interno
65
+ if (content.organizzato_da_interno.length > 0) {
66
+ schemaOrg.organizer = {
67
+ '@type': 'Organization',
68
+ name: content.organizzato_da_interno[0].title,
69
+ url: toPublicURL(content.organizzato_da_interno[0]['@id']),
70
+ };
71
+ }
72
+
73
+ // contributo esterno
74
+ if (richTextHasContent(content.organizzato_da_esterno)) {
75
+ schemaOrg.contributor = {
76
+ '@type': 'Organization',
77
+ name: SchemaOrgUtils.fieldDataToPlainText(content.organizzato_da_esterno),
78
+ };
79
+ }
80
+
81
+ //chi partecipa
82
+ let attendeeList = [];
83
+ if (richTextHasContent(content.parteciperanno)) {
84
+ attendeeList.push(
85
+ SchemaOrgUtils.fieldDataToPlainText(content.parteciperanno),
86
+ );
87
+ }
88
+ if (content.persona_correlata.length > 0) {
89
+ attendeeList.push(content.persona_correlata.map((item) => item.title));
90
+ }
91
+ if (attendeeList.length > 0) {
92
+ schemaOrg.attendee = {
93
+ '@type': 'Person',
94
+ name: attendeeList.join(', '),
95
+ };
96
+ }
97
+
98
+ // a chi si rivolge
99
+ let audienceList = [];
100
+ if (richTextHasContent(content.a_chi_si_rivolge)) {
101
+ audienceList.push(
102
+ SchemaOrgUtils.fieldDataToPlainText(content.a_chi_si_rivolge),
103
+ );
104
+ }
105
+ if (content.a_chi_si_rivolge_tassonomia.length > 0) {
106
+ audienceList.push(
107
+ content.a_chi_si_rivolge_tassonomia.map((item) => item.title),
108
+ );
109
+ }
110
+ if (audienceList.length > 0) {
111
+ schemaOrg.audience = {
112
+ '@type': 'Audience',
113
+ audienceType: audienceList.join(', '),
114
+ };
115
+ }
116
+
117
+ // costi o biglietti
118
+ if (richTextHasContent(content.costo)) {
119
+ schemaOrg.offers = {
120
+ '@type': 'Offer',
121
+ price: SchemaOrgUtils.fieldDataToPlainText(content.costo),
122
+ priceCurrency: 'EUR',
123
+ };
124
+ }
125
+
126
+ // sponsor
127
+ if (richTextHasContent(content.patrocinato_da)) {
128
+ schemaOrg.sponsor = {
129
+ '@type': 'Organization',
130
+ name: SchemaOrgUtils.fieldDataToPlainText(content.patrocinato_da),
131
+ };
132
+ }
133
+
134
+ return <SchemaOrg content={content} schema={schemaOrg} />;
135
+ };
136
+
137
+ export default EventoSchemaOrg;
@@ -20,6 +20,7 @@ import {
20
20
  } from 'io-sanita-theme/components/View/commons';
21
21
 
22
22
  import {
23
+ EventoSchemaOrg,
23
24
  EventoCosE,
24
25
  EventoPartecipanti,
25
26
  EventoAChiSiRivolge,
@@ -38,6 +39,7 @@ import {
38
39
  } from 'io-sanita-theme/components/View/Evento';
39
40
 
40
41
  export const EventoViewSectionsOrder = [
42
+ { /* METADATI SCHEMA.ORG */ component: EventoSchemaOrg },
41
43
  { /* COS'è */ component: EventoCosE },
42
44
  { /* CHI PARTECIPA */ component: EventoPartecipanti },
43
45
  { /* EVENTI PADRI */ component: EventoFaParteDi },
@@ -111,3 +111,9 @@ export const EventoEventiCorrelati = loadable(
111
111
  /* webpackChunkName: "ISEventView" */ 'io-sanita-theme/components/View/Evento/EventoEventiCorrelati'
112
112
  ),
113
113
  );
114
+ export const EventoSchemaOrg = loadable(
115
+ () =>
116
+ import(
117
+ /* webpackChunkName: "ISEventView" */ 'io-sanita-theme/components/View/Evento/EventoSchemaOrg'
118
+ ),
119
+ );
@@ -0,0 +1,69 @@
1
+ import { useIntl } from 'react-intl';
2
+ import { toPublicURL } from '@plone/volto/helpers';
3
+ import { SiteProperty } from 'volto-site-settings';
4
+ import {
5
+ getSiteProperty,
6
+ SchemaOrgUtils,
7
+ richTextHasContent,
8
+ SchemaOrg,
9
+ } from 'io-sanita-theme/helpers';
10
+
11
+ const NewsItemSchemaOrg = ({ content }) => {
12
+ const intl = useIntl();
13
+
14
+ let siteTitle = SchemaOrgUtils.getSiteTitle();
15
+
16
+ let schemaOrg = {
17
+ '@type': 'NewsArticle',
18
+ headline: content.title,
19
+ url: toPublicURL(content['@id']),
20
+ };
21
+
22
+ let description = [];
23
+
24
+ if (content.description) {
25
+ description.push(content.description);
26
+ }
27
+
28
+ if (richTextHasContent(content.descrizione_estesa)) {
29
+ description.push(
30
+ SchemaOrgUtils.fieldDataToPlainText(content.descrizione_estesa),
31
+ );
32
+ }
33
+
34
+ if (description.length > 0) {
35
+ schemaOrg.description = description.join('. ');
36
+ }
37
+
38
+ if (content.uo_correlata?.length > 0) {
39
+ schemaOrg.author = content.uo_correlata.map((e) => {
40
+ const author = {
41
+ '@type': 'Organization',
42
+ name: e.title,
43
+ };
44
+
45
+ return author;
46
+ });
47
+ }
48
+
49
+ if (content.language) {
50
+ schemaOrg.inLanguage = content.language.token;
51
+ }
52
+
53
+ schemaOrg.publisher = {
54
+ '@type': 'Organization',
55
+ name: siteTitle,
56
+ };
57
+
58
+ if (content.effective) {
59
+ schemaOrg.datePublished = content.effective;
60
+ }
61
+
62
+ if (content.modified) {
63
+ schemaOrg.dateModified = content.modified;
64
+ }
65
+
66
+ return <SchemaOrg content={content} schema={schemaOrg} />;
67
+ };
68
+
69
+ export default NewsItemSchemaOrg;
@@ -32,9 +32,11 @@ import {
32
32
  NewsItemACuraDi,
33
33
  NewsItemNotizieCorrelate,
34
34
  NewsItemUlterioriInformazioni,
35
+ NewsItemSchemaOrg,
35
36
  } from 'io-sanita-theme/components/View/NewsItem';
36
37
 
37
38
  export const NewsItemViewSectionsOrder = [
39
+ { /* METADATI SCHEMA.ORG */ component: NewsItemSchemaOrg },
38
40
  { /* TESTO COMPLETO */ component: NewsItemTesto },
39
41
  { /* DOCUMENTI */ component: NewsItemDocumenti },
40
42
  { /* GALLERY */ component: NewsItemGallery },