diff --git a/package.json b/package.json index 65de2f87..1317c586 100644 --- a/package.json +++ b/package.json @@ -87,6 +87,7 @@ "design-react-kit": "5.0.0-10", "htmldiff-js": "1.0.5", "marked": "9.0.0", + "moment-timezone": "0.6.0", "react-focus-lock": "2.12.1", "react-highlight-words": "0.20.0", "react-slick": "0.30.2", diff --git a/src/components/Blocks/Listing/Table/TableTemplate.jsx b/src/components/Blocks/Listing/Table/TableTemplate.jsx index db21a80b..1839dbe3 100644 --- a/src/components/Blocks/Listing/Table/TableTemplate.jsx +++ b/src/components/Blocks/Listing/Table/TableTemplate.jsx @@ -39,7 +39,7 @@ const TableTemplate = (props) => { // necessario per gli edditor nel momento in cui aggiungono nuove colonne const ct_schema = useSelector((state) => state.ct_schema?.subrequests); - let render_columns = + const render_columns = (columns ?? []).filter((c) => c.field === 'title').length > 0 ? columns : [ @@ -87,6 +87,7 @@ const TableTemplate = (props) => { ct_schema?.[c.ct]?.result?.properties?.[c.field] ?? {}; let render_value = JSON.stringify(item[c.field]); + let field_value = item[c.field]; if (field_properties) { const field = { @@ -100,23 +101,45 @@ const TableTemplate = (props) => { behavior: field_properties.behavior, }; if (field_properties.widget === 'datetime') { - widget_props.format = 'DD/MM/yyyy HH:MM'; - } - // per questi campi si è deciso dii non pubblicare ora:minuti - switch (c.field) { - case 'apertura_bando': - case 'chiusura_procedimento_bando': - case 'scadenza_domande_bando': - case 'scadenza_bando': + if (field_value?.indexOf('T') > 0) { + widget_props.format = 'DD/MM/yyyy HH:mm'; + field_value = + field_value + + (field_value.indexOf('Z') < 0 && + field_value.indexOf('+') < 0 + ? 'Z' + : ''); + } else { widget_props.format = 'DD/MM/yyyy'; + } + } + // per questi campi si è deciso di non pubblicare ora:minuti + // XXX: queste personalizzazioni sul formato dei datetime, basate sui nomi + // dei field sono da rivedere in modo differente + switch (c.ct) { + case 'ATAvviso': + case 'ATGara': + case 'ATAffidamento': + case 'ATConcorso': break; default: - break; + switch (c.field) { + case 'apertura_bando': + case 'chiusura_procedimento_bando': + case 'scadenza_domande_bando': + case 'scadenza_bando': + widget_props.format = 'DD/MM/yyyy'; + break; + default: + break; + } } - // rimuove ora, se non valorizzata + // rimuove ora, se non valorizzata (XXX: in realtà se la data è UTC + // non fa quello che ci si aspetterebbe) if ( field_properties.widget === 'datetime' && - item[c.field]?.indexOf('T00:00') > 0 + (field_value?.indexOf('T00:00') >= 0 || + field_value?.indexOf('T23:59') >= 0) ) { widget_props.format = 'DD/MM/yyyy'; } @@ -126,7 +149,7 @@ const TableTemplate = (props) => { } render_value = ( - + ); } if (c.field === 'title') { @@ -136,7 +159,7 @@ const TableTemplate = (props) => { href={isEditMode ? '#' : ''} className="img-link" > - {item[c.field]} + {field_value} ); } diff --git a/src/components/View/Bando/Dates.jsx b/src/components/View/Bando/Dates.jsx index 36c5edff..cea0ed24 100644 --- a/src/components/View/Bando/Dates.jsx +++ b/src/components/View/Bando/Dates.jsx @@ -2,8 +2,9 @@ import { defineMessages, useIntl } from 'react-intl'; import React from 'react'; import { Card, CardTitle, CardBody } from 'design-react-kit'; import PropTypes from 'prop-types'; - +import { useSelector } from 'react-redux'; import { viewDate } from 'io-sanita-theme/helpers'; +import moment from 'moment-timezone'; const messages = defineMessages({ effective: { @@ -88,43 +89,51 @@ const BandoDates = ({ content }) => { return content ? : null; }; -const Dates = ({ dates }) => ( -
- {dates.map((item, index) => { - return ( - item.date && ( -
-
- - {item.date.format('DD')} - - - {item.date.format('MMM')}/{item.date.format('YY')} - -
-
- { + const site = useSelector((state) => state.site.data); + const tz = site?.['plone.portal_timezone'] ?? 'Europe/Rome'; + + return ( +
+ {dates.map((item, index) => { + return ( + item.date && ( +
+
- - - {item.show_hour && <>{item.date.format('HH:mm')} - } - {item.label} - - - + + {moment.tz(item.date, tz).format('DD')} + + + {moment.tz(item.date, tz).format('MMM')}/ + {moment.tz(item.date, tz).format('YY')} + +
+
+ + + + {item.show_hour && ( + <>{moment.tz(item.date, tz).format('HH:mm')} - + )} + {item.label} + + + +
-
- ) - ); - })} -
-); + ) + ); + })} +
+ ); +}; export { Dates }; diff --git a/src/customizations/volto/components/theme/Widgets/DatetimeWidget.jsx b/src/customizations/volto/components/theme/Widgets/DatetimeWidget.jsx new file mode 100644 index 00000000..fffdd1c0 --- /dev/null +++ b/src/customizations/volto/components/theme/Widgets/DatetimeWidget.jsx @@ -0,0 +1,31 @@ +/* + * customization from @plone/volto 18.9.1 + * + * show time using the server timezone + * + */ + +import React from 'react'; +import cx from 'classnames'; +import moment from 'moment-timezone'; +import { useSelector } from 'react-redux'; +import { toBackendLang } from '@plone/volto/helpers/Utils/Utils'; + +const DatetimeWidget = ({ value, children, className, format = 'lll' }) => { + const lang = useSelector((state) => state.intl.locale); + const tz = useSelector( + (state) => state.site?.data?.['plone.portal_timezone'] ?? 'Europe/Rome', + ); + moment.locale(toBackendLang(lang)); + return value ? ( + + {children + ? children(moment.tz(value, tz).format(format)) + : moment.tz(value, tz).format(format)} + + ) : ( + '' + ); +}; + +export default DatetimeWidget;