diff --git a/backend/news/177.internal b/backend/news/177.internal new file mode 100644 index 000000000..8a035b71a --- /dev/null +++ b/backend/news/177.internal @@ -0,0 +1 @@ +Add example content for list with date variation for listing block @Tishasoumya-02 \ No newline at end of file diff --git a/backend/src/kitconcept/intranet/distributions/intranet/content/content/195d96ca9952493cbffa69cda040b8b3/data.json b/backend/src/kitconcept/intranet/distributions/intranet/content/content/195d96ca9952493cbffa69cda040b8b3/data.json index 5efa79c44..643970052 100644 --- a/backend/src/kitconcept/intranet/distributions/intranet/content/content/195d96ca9952493cbffa69cda040b8b3/data.json +++ b/backend/src/kitconcept/intranet/distributions/intranet/content/content/195d96ca9952493cbffa69cda040b8b3/data.json @@ -6,9 +6,7 @@ "changeNote": "", "contributors": [], "created": "2023-07-06T21:35:19+00:00", - "creators": [ - "admin" - ], + "creators": ["admin"], "description": "The Link content type can be used to display links on the page. Users are automatically redirected to the external site when they click on the link.", "effective": "2023-07-06T18:35:00+00:00", "exclude_from_nav": false, diff --git a/backend/src/kitconcept/intranet/distributions/intranet/content/content/6bd32a3367ea4254b295db642655b9d3/data.json b/backend/src/kitconcept/intranet/distributions/intranet/content/content/6bd32a3367ea4254b295db642655b9d3/data.json index 25d2452ad..63d1d57c7 100644 --- a/backend/src/kitconcept/intranet/distributions/intranet/content/content/6bd32a3367ea4254b295db642655b9d3/data.json +++ b/backend/src/kitconcept/intranet/distributions/intranet/content/content/6bd32a3367ea4254b295db642655b9d3/data.json @@ -483,6 +483,26 @@ }, "theme": "default" }, + "b72b932a-c191-4116-afed-024d0893b340": { + "@type": "listing", + "headlineTag": "h2", + "querystring": { + "query": [ + { + "i": "portal_type", + "o": "plone.app.querystring.operation.selection.any", + "v": [ + "Event", + "Document" + ] + } + ], + "sort_order": "ascending" + }, + "styles": {}, + "theme": "default", + "variation": "listDate" + }, "c2eaacd0-4e96-4344-a0ac-26ed644fc503": { "@type": "listing", "block": "c2eaacd0-4e96-4344-a0ac-26ed644fc503", @@ -547,6 +567,11 @@ "theme": "default", "variation": "grid" }, + "dacab3f8-187e-45da-9823-e67e6db70498": { + "@type": "heading", + "heading": "List with date", + "theme": "default" + }, "e405a8b2-9a83-47b7-a1c6-52a919f01e08": { "@type": "listing", "headline": "Person List", @@ -671,7 +696,9 @@ "ab005953-3360-4186-97ad-a4e1b4903b1c", "e405a8b2-9a83-47b7-a1c6-52a919f01e08", "e87a3b1a-493e-4cd7-8ca5-76b83a3595c2", - "245f8bda-5a49-4639-bbeb-d005c6a1a731" + "245f8bda-5a49-4639-bbeb-d005c6a1a731", + "dacab3f8-187e-45da-9823-e67e6db70498", + "b72b932a-c191-4116-afed-024d0893b340" ] }, "changeNote": "", diff --git a/frontend/cypress/tests/core/blocks/listing/blocks-listing-templates.cy.js b/frontend/cypress/tests/core/blocks/listing/blocks-listing-templates.cy.js index 7b389ed6a..7b3f12b51 100644 --- a/frontend/cypress/tests/core/blocks/listing/blocks-listing-templates.cy.js +++ b/frontend/cypress/tests/core/blocks/listing/blocks-listing-templates.cy.js @@ -166,4 +166,51 @@ describe('Folder Contents Tests', () => { expect($img[0].naturalWidth).to.be.greaterThan(0); }); }); + it('Should render list with date template with Event Content Type', () => { + let startDate; + let endDate; + const now = new Date(); + startDate = new Date(now); + startDate.setMonth(startDate.getMonth() + 1); + // End = start + 7 days + endDate = new Date(startDate.getTime() + 7 * 24 * 60 * 60 * 1000); + const formatDate = (date) => date.toISOString().replace('.000Z', '+00:00'); + const eventStart = new Date((startDate.getTime() + endDate.getTime()) / 2); + const eventEnd = new Date(eventStart.getTime() + 2 * 24 * 60 * 60 * 1000); + cy.createContent({ + contentType: 'Event', + contentId: 'my-event', + contentTitle: 'My Event', + bodyModifier(body) { + body.start = formatDate(eventStart); + body.end = formatDate(eventEnd); + return body; + }, + }); + cy.createContent({ + contentType: 'Event', + contentId: 'my-next-event', + contentTitle: 'My Next Event', + bodyModifier(body) { + body.start = formatDate(eventStart); + body.end = formatDate(eventEnd); + return body; + }, + }); + cy.visit('/my-folder/my-document'); + + cy.get('.edit').click(); + cy.addNewBlock('listing'); + cy.get('#field-variation').click().type('list with date{enter}'); + + // set Type criteria filter to Event + cy.configureListingWith('Event'); + cy.wait('@content'); + cy.get('#toolbar-save').click(); + cy.wait('@content'); + cy.get('.card-inner .date-inset') + .should('be.visible') + .and('contain', eventStart.getDate()) + .and('contain', eventEnd.getDate()); + }); }); diff --git a/frontend/packages/volto-intranet/news/+listingWithDate.feature b/frontend/packages/volto-intranet/news/+listingWithDate.feature new file mode 100644 index 000000000..8a937f7fb --- /dev/null +++ b/frontend/packages/volto-intranet/news/+listingWithDate.feature @@ -0,0 +1 @@ +Add listing template listing with Date and cypress test for the same @Tishasoumya-02 diff --git a/frontend/packages/volto-intranet/package.json b/frontend/packages/volto-intranet/package.json index 33f27eb74..56ea5f1e9 100644 --- a/frontend/packages/volto-intranet/package.json +++ b/frontend/packages/volto-intranet/package.json @@ -35,10 +35,10 @@ "devDependencies": { "@plone/scripts": "^3.6.2", "@plone/types": "workspace:*", + "@testing-library/react": "^16.2.0", "@types/lodash": "^4.14.201", "@types/react": "^18", "@types/react-dom": "^18", - "@testing-library/react": "^16.2.0", "release-it": "^17.1.1", "typescript": "^5.7.3", "vitest": "^3.1.2" @@ -51,9 +51,10 @@ "@kitconcept/volto-solr" ], "dependencies": { - "@plone/components": "workspace:*", "@kitconcept/core": "workspace:*", "@kitconcept/volto-solr": "2.0.0-alpha.1", + "@plone/components": "workspace:*", + "classnames": "2.5.1", "@plone-collective/volto-authomatic": "3.0.0-alpha.4", "lodash": "4.17.21", "volto-rss-block": "^3.0.1" diff --git a/frontend/packages/volto-intranet/src/components/Blocks/Listing/EventCalendarTemplate.tsx b/frontend/packages/volto-intranet/src/components/Blocks/Listing/EventCalendarTemplate.tsx new file mode 100644 index 000000000..116e4c38e --- /dev/null +++ b/frontend/packages/volto-intranet/src/components/Blocks/Listing/EventCalendarTemplate.tsx @@ -0,0 +1,124 @@ +import { useSelector } from 'react-redux'; +import Card from '@kitconcept/volto-light-theme/primitives/Card/Card'; +import DefaultSummary from '@kitconcept/volto-light-theme/components/Summary/DefaultSummary'; +import cx from 'classnames'; + +type IntlType = { + intl: { + locale: string; + }; +}; + +const itemDates = (item: any, lang: string) => { + const formatter = new Intl.DateTimeFormat(lang, { + year: 'numeric', + month: 'short', + }); + + const headFormatter = new Intl.DateTimeFormat(lang, { + day: 'numeric', + year: 'numeric', + month: 'long', + }); + + const start = + item['@type'] === 'Event' + ? item.start + ? new Date(item.start) + : null + : item.effective + ? new Date(item.effective) + : new Date(item.created); + + const end = + item['@type'] === 'Event' && (item.end ? new Date(item.end) : null); + + const notSameDay = end && start?.getDate() !== end?.getDate(); + const formattedStartDate = start ? formatter.format(start) : ''; + const formattedEndDate = end ? formatter.format(end) : ''; + const formattedHeaderDate = !end + ? start + ? headFormatter.format(start) + : '' + : start && end + ? headFormatter.formatRange(start, end) + : ''; + + return { + start, + end, + formattedStartDate, + formattedEndDate, + formattedHeaderDate, + notSameDay, + }; +}; +const EventItem = ({ + item, + lang, + isEditMode, +}: { + item: any; + lang: string; + isEditMode: boolean; +}) => { + const { + start, + end, + formattedHeaderDate, + notSameDay, + formattedStartDate, + formattedEndDate, + } = itemDates(item, lang); + + return ( +
+ + +
+
+ {start && String(start?.getDate()).padStart(2, '0')} +
+
{formattedStartDate}
+ {notSameDay && ( + <> +
+
+ {end && String(end?.getDate()).padStart(2, '0')} +
+
{formattedEndDate}
+ + )} +
+
+ +
+ {formattedHeaderDate} + {item.head_title && ( + {item.head_title} + )} +
+ +
+
+
+ ); +}; + +const EventCalendarTemplate = (props: any) => { + const lang = useSelector((state: IntlType) => state.intl.locale); + return ( +
+ {props.items.map((item: any, index: number) => ( + + ))} +
+ ); +}; + +export default EventCalendarTemplate; diff --git a/frontend/packages/volto-intranet/src/config/blocks.ts b/frontend/packages/volto-intranet/src/config/blocks.ts index 38c6c3776..2fa14adcb 100644 --- a/frontend/packages/volto-intranet/src/config/blocks.ts +++ b/frontend/packages/volto-intranet/src/config/blocks.ts @@ -3,6 +3,7 @@ import RssDefaultTemplate from '../components/Blocks/RSS/DefaultTemplate'; import RssGridTemplate from '../components/Blocks/RSS/GridTemplate'; import RssSummaryTemplate from '../components/Blocks/RSS/SummaryTemplate'; import type { StyleDefinition } from '@plone/types'; +import EventCalendarTemplate from '../components/Blocks/Listing/EventCalendarTemplate'; declare module '@plone/types' { export interface BlocksConfigData { @@ -21,6 +22,19 @@ declare module '@plone/types' { } export default function install(config: ConfigType) { + const listingBlockVariations = [ + ...(config.blocks.blocksConfig.listing.variations || []), + { + id: 'listDate', + title: 'List with date', + template: EventCalendarTemplate, + }, + ].filter((variation) => !!variation); + + config.blocks.blocksConfig.listing = { + ...config.blocks.blocksConfig.listing, + variations: listingBlockVariations, + }; config.blocks.blocksConfig.rssBlock.templates = { default: { label: 'List', diff --git a/frontend/packages/volto-intranet/src/theme/_main.scss b/frontend/packages/volto-intranet/src/theme/_main.scss index e3d72e205..63a3e294d 100644 --- a/frontend/packages/volto-intranet/src/theme/_main.scss +++ b/frontend/packages/volto-intranet/src/theme/_main.scss @@ -1,4 +1,5 @@ @import 'content'; @import 'slots'; @import 'components/search'; +@import 'components/eventsList.scss'; @import 'components/person'; diff --git a/frontend/packages/volto-intranet/src/theme/components/_eventsList.scss b/frontend/packages/volto-intranet/src/theme/components/_eventsList.scss new file mode 100644 index 000000000..44089b2aa --- /dev/null +++ b/frontend/packages/volto-intranet/src/theme/components/_eventsList.scss @@ -0,0 +1,66 @@ +.event-calendar { + @include default-container-width(); + @include adjustMarginsToContainer($default-container-width); + + .card-listing { + margin-bottom: 47px; + &:last-of-type { + .card-inner { + .card-summary { + border-bottom: none; + } + } + } + + .card-inner { + align-items: flex-start; + .image-wrapper { + flex-basis: 140px; + .date-inset { + width: 140px; + height: 140px; + &.has-end-date { + .day { + font-size: 36px; + line-height: 38px; + } + + .month { + font-size: 10px; + font-weight: 400; + line-height: 18px; + } + } + .separator { + width: 71%; + height: 1px; + margin-top: 5px; + margin-bottom: 5px; + background: $black; + } + } + } + + .card-summary { + align-self: stretch; + padding-bottom: 38px; + border-bottom: 1px solid $black; + + .headline { + display: none; + &.calendar { + display: block; + } + } + + .event-title { + &:before { + margin-right: 5px; + margin-left: 5px; + content: '|'; + } + } + } + } + } +} diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml index a6f5cbef3..47d5365c6 100644 --- a/frontend/pnpm-lock.yaml +++ b/frontend/pnpm-lock.yaml @@ -1811,6 +1811,9 @@ importers: '@plone/components': specifier: workspace:* version: link:../../core/packages/components + classnames: + specifier: 2.5.1 + version: 2.5.1 lodash: specifier: 4.17.21 version: 4.17.21