diff --git a/README.md b/README.md
index c4f7b0d..0d1cc41 100644
--- a/README.md
+++ b/README.md
@@ -4,11 +4,17 @@ Volto addon to add an additional variation to the default listing block with adv
This add-on adds a fully customizable variation to the default listing block. It adds the following features:
+- Select the number of columns in which the content will be shown
- Select to show the image of the item or not
- Select the position of the image in the item card
- Select the size of the card (to build mosaic-like listings)
+- An option to select to show the description
- An option to select to show the publication date
-- Select the number of columns in which the content will be shown
+- An option to select to show the event date
+- An option to select to show the event time
+- An option to select to show the event location
+
+![volto-listingadvanced-variation block details](https://github.com/rnunez80/volto-listingadvanced-variation/blob/main/Screenshot%202022-10-24%20at%2012.28.49%20PM.png?raw=true)
Installation:
diff --git a/search-block.png b/search-block.png
new file mode 100644
index 0000000..0e5599b
Binary files /dev/null and b/search-block.png differ
diff --git a/src/Advanced.css b/src/Advanced.css
new file mode 100644
index 0000000..986422d
--- /dev/null
+++ b/src/Advanced.css
@@ -0,0 +1,325 @@
+/* Start existing-content-backgroundimage */
+
+.backgroundimage {
+ background: #000;
+ aspect-ratio: 16/9;
+ object-fit: cover;
+ position: relative;
+ overflow: hidden;
+ width: 100%;
+}
+
+.backgroundimage .info-text {
+ color: #fff;
+ width: 100%;
+ display: block;
+ position: absolute;
+ bottom: 0px;
+ left: 0px;
+ z-index: 2;
+ background: linear-gradient(to bottom, rgba(0, 0, 0, 0) 0, #000 75%);
+ padding: 0 0.5em;
+ height: auto;
+}
+
+.backgroundimage .info-text h2,
+.backgroundimage .info-text h3,
+.backgroundimage .info-text h4 {
+ color: #fff;
+ text-shadow: 1px 1px 10px #000;
+ margin-bottom: 5px;
+}
+
+.card h2, .card h3, .card h4 {
+ margin-top: 0;
+}
+
+.backgroundimage .info-text p {
+ margin: 0em;
+}
+
+.backgroundimage .focuspoint img {
+ aspect-ratio: 16/9;
+ object-fit: cover;
+ z-index: 1
+}
+
+.backgroundimage:hover .info-text p {
+ height: 5em;
+ transition: 0.5s;
+}
+
+.backgroundimage a:hover .focuspoint {
+ filter: drop-shadow(2px 4px 6px black);
+ transition: 0.5s;
+}
+
+.backgroundimage .info-text p {
+ height: 0.2em;
+ overflow: hidden;
+ transition: 0.5s;
+}
+
+.backgroundimage:hover .info-text p.date {
+ height: 1.5em;
+ transition: 0.5s;
+}
+
+.backgroundimage:hover {
+ box-shadow: 1px 6px 8px;
+ transition: 0.5s;
+}
+
+.backgroundimage .event-when {
+ background: #b11116;
+ padding: 0 0.5em;
+}
+.limited-text {
+ text-overflow:ellipsis;
+ overflow:hidden;
+ display: -webkit-box !important;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+ white-space: normal;
+}
+.text-ellipsis{
+ text-overflow:ellipsis;
+ white-space:nowrap;
+ overflow:hidden;
+}
+/* End existing-content-backgroundimage */
+
+/* Start Slick */
+.slick-slide {
+ padding: 0 0.5em 0.5em 0.5em;
+}
+
+.backgroundimage h2, .backgroundimage h3, .backgroundimage h4 {
+ margin-top: 0 !important;
+}
+
+.top h2, .top h3, .top h4 {
+ margin-top: 0 !important;
+}
+
+.advancedView {
+ max-width: 100vw !important;
+}
+
+.advancedView {
+ width: calc(100% + 1em);
+ margin-left: -0.5em
+}
+
+.slick-prev:before, .slick-next:before {
+ color: #000;
+ box-shadow: 0px 1px 2px 0 rgba(0, 0, 0, 0.75);
+ border-radius: 50%;
+ background: #2e3233;
+ padding: 2px 1px 0 1px;
+}
+
+.advancedView.has--stretch--stretch {
+ margin-left: 0;
+}
+
+.advancedView.has--stretch--stretch {
+ margin-left: 0;
+}
+
+.advancedView.has--stretch--stretch .slick-slide {
+ padding: 0;
+}
+.advancedView.has--stretch--stretch .slick-slide {
+ padding: 0;
+}
+.advancedList .top.aligned.twelve.wide.column {padding:0 1em}
+
+/*@media screen and (min-width: 767px) and (max-width: 1790px) {*/
+/* body:not(.view-editview):not(.view-addview):not(.document_wide_view):not(.is-anonymous):not(.has-toolbar-collapsed) .stretch .advancedView {*/
+/* margin: 0 0 0 186px;*/
+/* width: calc(100% - 80px);*/
+/* }*/
+
+/* body:not(.view-editview):not(.view-addview):not(.document_wide_view):not(.is-anonymous):not(.has-toolbar) .stretch .advancedView {*/
+/* margin: 0 0 0 166px;*/
+/* width: calc(100% - 20px);*/
+
+/* }*/
+/*}*/
+@media only screen and (max-width: 1222px) {
+ .view-editview .advancedView {
+ max-width: calc(100vw - 475px) !important;
+ }
+}
+
+@media only screen and (min-width: 1223px) and (max-width: 1446px) {
+ .view-editview .advancedView {
+ max-width: 730px !important;
+ }
+}
+
+@media only screen and (min-width: 1447px) and (max-width: 1654px) {
+ .view-editview .advancedView {
+ max-width: 940px !important;
+ }
+}
+
+@media only screen and (min-width: 1655px) {
+ .view-editview .advancedView {
+ max-width: 1134px !important;
+ }
+}
+
+@media screen and (max-width: 766px) {
+ .view-editview .advancedView {
+ max-width: calc(100vw - 28px) !important;
+ }
+
+ .styled-listing.has--stretch--stretch.styled.stretch {
+ left: calc(50% - 50vw) !important;
+ width: 100vw !important;
+ margin: 0 !important
+ }
+}
+
+@media screen and (min-width: 767px) {
+ body:not(.view-editview):not(.view-addview):not(.document_wide_view):not(.is-anonymous):not(.has-toolbar-collapsed) .stretch {
+ max-width: 100vw !important;
+ width: calc(100vw - 80px) !important;
+ margin: 0 0 0 40px !important;
+ left: calc(50% - 50vw);
+ }
+
+ body:not(.view-editview):not(.view-addview):not(.document_wide_view):not(.is-anonymous):not(.has-toolbar) .stretch {
+ max-width: 100vw !important;
+ width: calc(100vw - 20px) !important;
+ margin: 0 0 0 10px !important;
+ left: calc(50% - 50vw);
+ }
+}
+
+
+@media (max-width: 766px) {
+ .advancedView .slick-prev {
+ z-index: 2;
+ transform: translateX(0);
+ opacity: 0
+ }
+
+ .advancedView:hover .slick-prev {
+ transform: translateX(42px);
+ opacity: 1;
+ transition: 1s;
+ }
+
+ .advancedView .slick-next {
+ z-index: 2;
+ transform: translateX(0);
+ opacity: 0
+ }
+
+ .advancedView:hover .slick-next {
+ transform: translateX(-42px);
+ opacity: 1;
+ transition: 1s;
+ }
+}
+
+.advancedView .column1 .slick-prev {
+ z-index: 2;
+ transform: translateX(0);
+ opacity: 0
+}
+
+.advancedView:hover .column1 .slick-prev {
+ transform: translateX(42px);
+ opacity: 1;
+ transition: 1s;
+}
+
+.advancedView .column1 .slick-next {
+ z-index: 2;
+ transform: translateX(0);
+ opacity: 0
+}
+
+.advancedView:hover .column1 .slick-next {
+ transform: translateX(-42px);
+ opacity: 1;
+ transition: 1s;
+}
+.advancedView .column1 .backgroundimage:hover {
+ box-shadow: 0 0 0;
+}
+.advancedView .ui.one.column.grid {
+ padding: 0;
+ margin: 0;
+}
+.advancedView.advancedList{
+ padding-left: 7px;
+}
+.advancedView .twelve.wide.column.advanced-item {
+ padding: 0;
+ margin: 0;}
+.slick-dots {
+ bottom: -1em !important;}
+/* End Slick */
+
+/* start listing */
+.ui.one.column.grid.advanced-item {
+ padding: 0;
+ margin: 0;
+}
+
+.ui.one.column.grid.advanced-item .column {
+ padding: 0.5em;
+ margin: 0;
+}
+.block.listing.advanced .ui.stackable.one.column.grid,
+.block.listing.advanced .ui.stackable.two.column.grid,
+.block.listing.advanced .ui.stackable.three.column.grid,
+.block.listing.advanced .ui.stackable.four.column.grid {
+ margin: 0 -0.5em 0 -0.5em
+}
+.event-when {font-weight: bold;}
+/* end listing */
+
+
+/* start eventCard */
+.cal_date {
+ box-shadow: 0 1px 3px rgb(0 0 0 / 25%), inset 0 -1px 0 rgb(0 0 0 / 10%);
+ overflow: hidden;
+ font-size: 0.8em;
+ float: left;
+ vertical-align: top;
+ text-align: center;
+ background-color: white;
+ border-radius: 0.5em;
+ min-width: 4.4em;
+ margin: 0 1em 0.5em 0 !important;
+}
+.cal_month {
+ background: #b11116;
+ padding: 0 0.5em;
+ color: #fff;
+ font-size: 1.1em;
+ line-height: 1.3em;
+ display: block;
+}
+.cal_day {
+ font-size: 2em;
+ display: block;
+ padding-top: 0.3em;
+}
+.cal_wkday {
+ display: block;
+ font-size: 1em;
+ font-weight: normal;
+ padding-bottom: 0.3em;
+ min-width: 7em;
+}
+.info-text .cal_wkday, .info-text .cal_day {
+ color: #000000;
+}
+/* end eventCard */
diff --git a/src/AdvancedCarouselBlockTemplate.jsx b/src/AdvancedCarouselBlockTemplate.jsx
new file mode 100644
index 0000000..44c8dbe
--- /dev/null
+++ b/src/AdvancedCarouselBlockTemplate.jsx
@@ -0,0 +1,342 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import {ConditionalLink} from '@plone/volto/components';
+import {flattenToAppURL} from '@plone/volto/helpers';
+
+import DefaultImageSVG from './placeholder.png';
+import {isInternalURL} from '@plone/volto/helpers/Url/Url';
+import {Grid, Image, Label, Icon} from 'semantic-ui-react';
+import moment from 'moment';
+import {useIntl} from 'react-intl';
+import loadable from '@loadable/component';
+import Slider from "react-slick";
+import './Advanced.css';
+
+//
+// import 'slick-carousel/slick/slick.css';
+// import 'slick-carousel/slick/slick-theme.css';
+
+import UniversalCard from '@eeacms/volto-listing-block/components/UniversalCard/UniversalCard';
+import ResponsiveContainer from '@eeacms/volto-listing-block/components/ResponsiveContainer';
+
+const AdvancedCarouselBlockTemplate = ({
+ items,
+ moreLinkText,
+ moreLinkUrl,
+ header,
+ headerUrl,
+ headerTag,
+ isEditMode,
+ imageSide,
+ imageWidth,
+ howManyColumns,
+ effectiveDate,
+ titleTag,
+ showTitle,
+ showDescription,
+ eventDate,
+ eventLocation,
+ eventTime,
+ slidesToScroll,
+ autoPlay,
+ autoplaySpeed,
+ eventCard
+ }) => {
+ let moreLink = null;
+ let moreHref = moreLinkUrl?.[0]?.['@id'] || '';
+ if (isInternalURL(moreHref)) {
+ moreLink = (
+
+ {moreLinkText || moreHref}
+
+ );
+ } else if (moreHref) {
+ moreLink = {moreLinkText || moreHref};
+ }
+
+ let headerLink = null;
+ let headerHref = headerUrl?.[0]?.['@id'] || '';
+ if (isInternalURL(headerHref)) {
+ headerLink = (
+
+ {header || headerHref}
+
+ );
+ } else if (headerHref) {
+ moreLink = {moreLinkText || headerHref};
+ }
+ const getEventCard = (item) => {
+ let startMonth = '', startDay = '', startWeekday = '', startTime = '';
+ if (item.start) {
+ const parsedDate = new Date(Date.parse(item.start));
+ startMonth = `${parsedDate.toLocaleString('default', {
+ month: 'long',
+ })}`;
+ startDay = parsedDate.getDate();
+ startWeekday = parsedDate.toLocaleString('default', {
+ weekday: 'long',
+ });
+ return
+ {startMonth}
+ {startDay}
+ {startWeekday}
+
;
+ } else {
+ return '';
+ }
+ ;
+ };
+ const getEventDate = (item) => {
+ let start = '',
+ end = '';
+
+ if (item.start) {
+ const parsedDate = new Date(Date.parse(item.start));
+ start = `${parsedDate.toLocaleString('default', {
+ month: 'short',
+ })} ${parsedDate.getDate()}, ${parsedDate.getFullYear()}`;
+ }
+
+ if (item.end) {
+ const parsedDate = new Date(Date.parse(item.end));
+ end = `${parsedDate.toLocaleString('default', {
+ month: 'short',
+ })} ${parsedDate.getDate()}, ${parsedDate.getFullYear()}`;
+ }
+ if (end == start) {
+ return start
+ } else {
+ return start + ' - ' + end;
+ }
+ ;
+ };
+ const getEventTime = (item) => {
+ let start = '',
+ end = '';
+
+ if (item.start) {
+ const parsedDate = new Date(Date.parse(item.start));
+ start = `${parsedDate.toLocaleString(
+ 'default',
+ {hour: 'numeric', minute: 'numeric', hour12: true},
+ )}`;
+ }
+
+ if (item.end) {
+ const parsedDate = new Date(Date.parse(item.end));
+ end = ` - ${parsedDate.toLocaleString(
+ 'default',
+ {hour: 'numeric', minute: 'numeric', hour12: true,}
+ )}`;
+ }
+
+ return start + end;
+ };
+ const hasImage = imageSide !== null;
+ const oneColumnElement = ['up', 'down', 'background', null].includes(imageSide);
+ const columnSize = oneColumnElement ? 1 : 2;
+ const imageGridWidth = oneColumnElement ? 12 : imageWidth ? imageWidth : 2;
+ const contentGridWidth = oneColumnElement
+ ? 12
+ : hasImage
+ ? 12 - imageWidth
+ : 12;
+ const intl = useIntl();
+ const TitleTag = titleTag ? titleTag : 'h3';
+ const HeaderTag = headerTag ? headerTag : 'h3';
+ const AutoPlay = autoPlay ? autoPlay : '1';
+ const AutoPlaySpeed = autoplaySpeed ? autoplaySpeed : '3';
+ moment.locale(intl.locale);
+ return (
+
+ {headerLink &&
+ {headerLink ? headerLink : header}
+ }
+
+
= 3 ? [
+ {
+ breakpoint: 1169,
+ settings: {
+ slidesToShow: 3,
+ },
+ },
+ {
+ breakpoint: 991,
+ settings: {
+ slidesToShow: 2,
+ slidesToScroll: 1,
+ },
+ },
+ {
+ breakpoint: 767,
+ settings: {
+ slidesToShow: 1,
+ slidesToScroll: 1,
+ },
+ },
+ ] : [
+ {
+ breakpoint: 767,
+ settings: {
+ slidesToShow: 1,
+ slidesToScroll: 1,
+ },
+ },
+ ]}
+ >
+ {['background'].includes(imageSide) && (
+ items.map((item) => (
+
+
+
+ {!item.image_field && (
+
+
+
+ )}
+ {item.image_field && (
+ )}
+
+
+ {eventCard && <>{getEventCard(item)}>}
+ {item.location && eventDate | eventTime &&
+
{eventDate && {getEventDate(item)}}
+ {eventTime && eventDate && | }
+ {eventTime && {getEventTime(item)}} || null}
+ {showTitle &&
{item.title ? item.title : item.id}}
+
+ {eventLocation && {item.location}
}
+ {effectiveDate && {moment(item.effective).format('L')}
}
+ {showDescription && item.description && (
+ {item.description}
+ )}
+
+
+
+
+ ))
+ )}
+ {!['background'].includes(imageSide) && (
+ items.map((item) => (
+
+ {['up', 'left'].includes(imageSide) && (
+
+ {!item.image_field && (
+
+
+
+ )}
+ {item.image_field && (
+
+
+
+ )}
+ )}
+
+ {eventCard && <>{getEventCard(item)}>}
+ {showTitle &&
+
+
+ {item.title ? item.title : item.id}
+
+ }
+ {item.location && eventDate | eventTime &&
+
+ {eventDate && {getEventDate(item)}}
+ {eventTime && eventDate && | }
+ {eventTime && {getEventTime(item)}}
|| null}
+ {eventLocation && {item.location}
}
+ {effectiveDate && {moment(item.effective).format('L')}
}
+ {showDescription && item.description && (
+ {item.description}
+ )}
+
+ {['right', 'down'].includes(imageSide) && (
+
+ {!item.image_field && (
+
+
+
+ )}
+ {item.image_field && (
+
+
+
+ )}
+ )}
+
+ ))
+ )}
+
+
+
+
+ );
+
+
+};
+
+AdvancedCarouselBlockTemplate.propTypes = {
+ items: PropTypes.arrayOf(PropTypes.any).isRequired,
+ linkMore: PropTypes.any,
+ isEditMode: PropTypes.bool,
+};
+
+export default AdvancedCarouselBlockTemplate;
diff --git a/src/AdvancedCarouselSchema.js b/src/AdvancedCarouselSchema.js
new file mode 100644
index 0000000..f8e546d
--- /dev/null
+++ b/src/AdvancedCarouselSchema.js
@@ -0,0 +1,116 @@
+import messages from './messages';
+
+export const advancedCarouselSchema = (props) => {
+ const {intl, schema, formData} = props;
+ // const imageWidth = ['right', 'left'].includes(formData.imageSide)
+ // ? ['imageWidth']
+ // : [];
+ const headingChoices = [
+ ['h2', 'H2'],
+ ['h3', 'H3'],
+ ['h4', 'H4'],
+ ];
+ return {
+ ...schema,
+ fieldsets: [
+ ...schema.fieldsets,
+ {
+ id: 'carousel',
+ title: 'Carousel/Slider Options',
+ fields: ['howManyColumns', 'slidesToScroll', 'autoPlay', 'autoplaySpeed', 'align'],
+ },
+ {
+ id: 'carouselDisplay',
+ title: intl.formatMessage(messages.itemDisplayOptions),
+ fields: ['titleTag', 'imageSide', 'showTitle', 'showDescription', 'eventCard', 'eventDate', 'eventTime', 'eventLocation', 'effectiveDate'],
+ },
+ ],
+ properties: {
+ ...schema.properties,
+ titleTag: {
+ title: intl.formatMessage(messages.titleTag),
+ choices: headingChoices,
+ default: 'h2',
+ },
+ howManyColumns: {
+ title: intl.formatMessage(messages.columnsCount),
+ choices: [
+ [1, '1'],
+ [2, '2'],
+ [3, '3'],
+ [4, '4'],
+ ],
+ default: 2,
+ },
+ slidesToScroll: {
+ title: 'Slides to scroll',
+ choices: [
+ [1, '1'],
+ [2, '2'],
+ [3, '3'],
+ [4, '4'],
+ ],
+ default: 1,
+ },
+ autoplaySpeed: {
+ title: 'Speed Autoplay',
+ type: 'number',
+ choices: [
+ [3, '3'],
+ [4, '4'],
+ [5, '5'],
+ [6, '6'],
+ [7, '7'],
+ [8, '8'],
+ [9, '9'],
+ [10, '10'],
+ ],
+ default: 5000
+ },
+ align: {
+ title: 'Alignment',
+ widget: 'align',
+ default: 'left',
+ },
+ imageSide: {
+ title: intl.formatMessage(messages.imagePosition),
+ choices: [
+ [null, 'No image'],
+ ['background', 'background'],
+ ['up', 'up'],
+ ],
+ default: 'up',
+ },
+ showTitle: {
+ title: 'Show Title',
+ type: 'boolean',
+ default: true,
+ },
+ showDescription: {
+ title: intl.formatMessage(messages.descriptionTitle),
+ type: 'boolean',
+ default: true,
+ },
+ effectiveDate: {
+ title: intl.formatMessage(messages.date),
+ type: 'boolean',
+ },
+ eventDate: {
+ title: intl.formatMessage(messages.eventDate),
+ type: 'boolean',
+ },
+ eventTime: {
+ title: intl.formatMessage(messages.eventTime),
+ type: 'boolean',
+ },
+ eventLocation: {
+ title: intl.formatMessage(messages.eventLocation),
+ type: 'boolean',
+ },
+ eventCard: {
+ title: 'Show Event Card',
+ type: 'boolean',
+ },
+ },
+ };
+};
diff --git a/src/AdvancedListingBlockTemplate.jsx b/src/AdvancedListingBlockTemplate.jsx
index 21d316d..7904174 100644
--- a/src/AdvancedListingBlockTemplate.jsx
+++ b/src/AdvancedListingBlockTemplate.jsx
@@ -1,28 +1,35 @@
import React from 'react';
import PropTypes from 'prop-types';
-import { ConditionalLink } from '@plone/volto/components';
-import { flattenToAppURL } from '@plone/volto/helpers';
+import {ConditionalLink} from '@plone/volto/components';
+import {flattenToAppURL} from '@plone/volto/helpers';
-import DefaultImageSVG from '@plone/volto/components/manage/Blocks/Listing/default-image.svg';
-import { isInternalURL } from '@plone/volto/helpers/Url/Url';
-import { Grid, Image } from 'semantic-ui-react';
+// import DefaultImageSVG from '@plone/volto/components/manage/Blocks/Listing/default-image.svg';
+import DefaultImageSVG from './placeholder.png';
+import {isInternalURL} from '@plone/volto/helpers/Url/Url';
+import {Grid, Image} from 'semantic-ui-react';
import moment from 'moment';
-import { useIntl } from 'react-intl';
+import {useIntl} from 'react-intl';
+
const AdvancedListingBlockTemplate = ({
- items,
- moreLinkText,
- moreLinkUrl,
- header,
- headerUrl,
- headerTag,
- isEditMode,
- imageSide,
- imageWidth,
- howManyColumns,
- effectiveDate,
- titleTag,
- showDescription,
-}) => {
+ items,
+ moreLinkText,
+ moreLinkUrl,
+ header,
+ headerUrl,
+ headerTag,
+ isEditMode,
+ imageSide,
+ imageWidth,
+ howManyColumns,
+ effectiveDate,
+ titleTag,
+ showDescription,
+ eventDate,
+ eventLocation,
+ eventTime,
+ showTitle,
+ eventCard
+ }) => {
let moreLink = null;
let moreHref = moreLinkUrl?.[0]?.['@id'] || '';
if (isInternalURL(moreHref)) {
@@ -46,34 +53,101 @@ const AdvancedListingBlockTemplate = ({
} else if (headerHref) {
moreLink = {moreLinkText || headerHref};
}
+ const getEventCard = (item) => {
+ let startMonth = '', startDay = '', startWeekday = '', startTime = '';
+ if (item.start) {
+ const parsedDate = new Date(Date.parse(item.start));
+ startMonth = `${parsedDate.toLocaleString('default', {
+ month: 'long',
+ })}`;
+ startDay = parsedDate.getDate();
+ startWeekday = parsedDate.toLocaleString('default', {
+ weekday: 'long',
+ });
+ return
+ {startMonth}
+ {startDay}
+ {startWeekday}
+
;
+ } else {
+ return '';
+ }
+ ;
+ };
+ const getEventDate = (item) => {
+ let start = '',
+ end = '';
+
+ if (item.start) {
+ const parsedDate = new Date(Date.parse(item.start));
+ start = `${parsedDate.toLocaleString('default', {
+ month: 'short',
+ })} ${parsedDate.getDate()}, ${parsedDate.getFullYear()}`;
+ }
+
+ if (item.end) {
+ const parsedDate = new Date(Date.parse(item.end));
+ end = `${parsedDate.toLocaleString('default', {
+ month: 'short',
+ })} ${parsedDate.getDate()}, ${parsedDate.getFullYear()}`;
+ }
+ if (end == start) {
+ return start
+ } else {
+ return start + ' - ' + end;
+ }
+ ;
+ };
+ const getEventTime = (item) => {
+ let start = '',
+ end = '';
+ if (item.start) {
+ const parsedDate = new Date(Date.parse(item.start));
+ start = `${parsedDate.toLocaleString(
+ 'default',
+ {hour: 'numeric', minute: 'numeric', hour12: true},
+ )}`;
+ }
+
+ if (item.end) {
+ const parsedDate = new Date(Date.parse(item.end));
+ end = ` - ${parsedDate.toLocaleString(
+ 'default',
+ {hour: 'numeric', minute: 'numeric', hour12: true,}
+ )}`;
+ }
+
+ return start + end;
+ };
const hasImage = imageSide !== null;
- const oneColumnElement = ['up', 'down', null].includes(imageSide);
+ const oneColumnElement = ['up', 'down', 'background', null].includes(imageSide);
const columnSize = oneColumnElement ? 1 : 2;
const imageGridWidth = oneColumnElement ? 12 : imageWidth ? imageWidth : 2;
const contentGridWidth = oneColumnElement
? 12
: hasImage
- ? 12 - imageWidth
- : 12;
+ ? 12 - imageWidth
+ : 12;
const intl = useIntl();
const TitleTag = titleTag ? titleTag : 'h3';
const HeaderTag = headerTag ? headerTag : 'h3';
moment.locale(intl.locale);
return (
- <>
-
+
+ {headerLink &&
{headerLink ? headerLink : header}
-
-
- {items.map((item) => (
-
-
+ }
+
+ {!['background'].includes(imageSide) && (
+ items.map((item) => (
+
{['up', 'left'].includes(imageSide) && (
{!item.image_field && (
)}
-
- )}
-
-
+ )}
+
+ {eventCard && <>{getEventCard(item)}>}
+ {showTitle &&
{item.title ? item.title : item.id}
-
+ }
+ {item.location && eventDate | eventTime &&
+ {eventDate && {getEventDate(item)}}
+ {eventTime && eventDate && | }
+ {eventTime && {getEventTime(item)}}
|| null}
+ {eventLocation && {item.location}
}
{effectiveDate && {moment(item.effective).format('L')}
}
{showDescription && item.description && (
{item.description}
@@ -109,6 +193,7 @@ const AdvancedListingBlockTemplate = ({
{!item.image_field && (
)}
-
- )}
+ )}
+
+ ))
+ )}
+ {['background'].includes(imageSide) && (
+ items.map((item) => (
+
+
+
+
+
+ {!item.image_field && (
+
+
+
+ )}
+ {item.image_field && (
+ )}
+
+
+ {eventCard && <>{getEventCard(item)}>}
+ {item.location && eventDate | eventTime &&
+
{eventDate && {getEventDate(item)}}
+ {eventTime && eventDate && | }
+ {eventTime && {getEventTime(item)}} || null}
+ {showTitle &&
{item.title ? item.title : item.id}}
+
+ {eventLocation && {item.location}
}
+ {effectiveDate && {moment(item.effective).format('L')}
}
+ {showDescription && item.description && (
+ {item.description}
+ )}
+
+
+
+
+
-
- ))}
+ ))
+ )}
- {moreLink &&
{moreLink}
}
- >
+
);
};
diff --git a/src/AdvancedListingSchema.js b/src/AdvancedListingSchema.js
new file mode 100644
index 0000000..6e88c0f
--- /dev/null
+++ b/src/AdvancedListingSchema.js
@@ -0,0 +1,96 @@
+import messages from './messages';
+
+export const advancedListingSchema = (props) => {
+ const {intl, schema, formData} = props;
+ // const imageWidth = ['right', 'left'].includes(formData.imageSide)
+ // ? ['imageWidth']
+ // : [];
+ const headingChoices = [
+ ['h2', 'H2'],
+ ['h3', 'H3'],
+ ['h4', 'H4'],
+ ];
+ return {
+ ...schema,
+ fieldsets: [
+ ...schema.fieldsets,
+ {
+ id: 'listingDisplay',
+ title: intl.formatMessage(messages.itemDisplayOptions),
+ fields: ['titleTag', 'howManyColumns', 'imageSide', 'imageWidth', 'showTitle', 'showDescription', 'eventCard', 'eventDate', 'eventTime', 'eventLocation', 'effectiveDate'],
+ },
+ ],
+ properties: {
+ ...schema.properties,
+ titleTag: {
+ title: intl.formatMessage(messages.titleTag),
+ choices: headingChoices,
+ default: 'h2',
+ },
+ howManyColumns: {
+ title: intl.formatMessage(messages.columnsCount),
+ choices: [
+ [1, '1'],
+ [2, '2'],
+ [3, '3'],
+ [4, '4'],
+ ],
+ default: 2,
+ },
+ imageWidth: {
+ title: intl.formatMessage(messages.imageWidth),
+ description: intl.formatMessage(messages.imageWidthDescription),
+ choices: [
+ [2, '2/12'],
+ [3, '3/12'],
+ [4, '4/12'],
+ [5, '5/12'],
+ [6, '6/12'],
+ ],
+ default: 4,
+ },
+ imageSide: {
+ title: intl.formatMessage(messages.imagePosition),
+ choices: [
+ [null, 'No image'],
+ ['background', 'background'],
+ ['up', 'up'],
+ ['left', 'left'],
+ ['right', 'right'],
+ ['down', 'down'],
+ ],
+ default: 'up',
+ },
+ showTitle: {
+ title: 'Show Title',
+ type: 'boolean',
+ default: true,
+ },
+ showDescription: {
+ title: intl.formatMessage(messages.descriptionTitle),
+ type: 'boolean',
+ default: true,
+ },
+ effectiveDate: {
+ title: intl.formatMessage(messages.date),
+ type: 'boolean',
+ },
+ eventCard: {
+ title: 'Show Event Card',
+ type: 'boolean',
+ },
+ eventDate: {
+ title: intl.formatMessage(messages.eventDate),
+ type: 'boolean',
+ },
+ eventTime: {
+ title: intl.formatMessage(messages.eventTime),
+ type: 'boolean',
+ },
+ eventLocation: {
+ title: intl.formatMessage(messages.eventLocation),
+ type: 'boolean',
+ },
+ },
+ };
+};
diff --git a/src/advancedSchema.js b/src/advancedSchema.js
deleted file mode 100644
index 01bb8ec..0000000
--- a/src/advancedSchema.js
+++ /dev/null
@@ -1,140 +0,0 @@
-import messages from './messages';
-
-export const advancedSchema = (props) => {
- const { intl, schema, formData } = props;
- const imageWidth = ['right', 'left'].includes(formData.imageSide)
- ? ['imageWidth']
- : [];
- const headingChoices = [
- ['h2', 'H2'],
- ['h3', 'H3'],
- ['h4', 'H4'],
- ];
- return {
- ...schema,
- fieldsets: [
- {
- id: 'default',
- title: 'Default',
- fields: ['variation'],
- },
- {
- id: 'querystring',
- title: intl.formatMessage(messages.querystring),
- fields: ['querystring'],
- },
- {
- id: 'header',
- title: intl.formatMessage(messages.headerConfiguration),
- fields: ['header', 'headerUrl', 'headerTag'],
- },
- {
- id: 'columns',
- title: intl.formatMessage(messages.columnsConfiguration),
- fields: ['howManyColumns'],
- },
- {
- id: 'image',
- title: intl.formatMessage(messages.imageConfiguration),
- fields: ['imageSide', ...imageWidth],
- },
- {
- id: 'title',
- title: intl.formatMessage(messages.titleConfiguration),
- fields: ['titleTag'],
- },
- {
- id: 'description',
- title: intl.formatMessage(messages.descriptionConfiguration),
- fields: ['showDescription'],
- },
- {
- id: 'date',
- title: intl.formatMessage(messages.dateConfiguration),
- fields: ['effectiveDate'],
- },
- {
- id: 'moreLink',
- title: intl.formatMessage(messages.moreLinkConfiguration),
- fields: ['moreLinkText', 'moreLinkUrl'],
- },
- ],
- properties: {
- ...schema.properties,
- header: {
- title: intl.formatMessage(messages.header),
- description: intl.formatMessage(messages.headerDescription),
- },
- headerUrl: {
- title: intl.formatMessage(messages.headerUrl),
- description: intl.formatMessage(messages.headerUrlDescription),
- widget: 'object_browser',
- mode: 'link',
- allowExternals: true,
- },
- headerTag: {
- title: intl.formatMessage(messages.headerTag),
- description: intl.formatMessage(messages.headerTagDescription),
- choices: [['h1', 'H1'], ...headingChoices],
- },
- howManyColumns: {
- title: intl.formatMessage(messages.columnsCount),
- choices: [
- [1, '1'],
- [2, '2'],
- [3, '3'],
- [4, '4'],
- ],
- },
- imageWidth: {
- title: intl.formatMessage(messages.imageWidth),
- description: intl.formatMessage(messages.imageWidthDescription),
- choices: [
- [2, '2/12'],
- [3, '3/12'],
- [4, '4/12'],
- [5, '5/12'],
- [6, '6/12'],
- ],
- },
- imageSide: {
- title: intl.formatMessage(messages.imagePosition),
- description: intl.formatMessage(messages.imagePositionDescription),
- choices: [
- [null, 'No image'],
- ['up', 'up'],
- ['left', 'left'],
- ['right', 'right'],
- ['down', 'down'],
- ],
- },
- titleTag: {
- title: intl.formatMessage(messages.titleTag),
- description: intl.formatMessage(messages.titleTagDescription),
- choices: headingChoices,
- },
- showDescription: {
- title: intl.formatMessage(messages.descriptionTitle),
- description: intl.formatMessage(messages.descriptionDescription),
- type: 'boolean',
- default: true,
- },
- effectiveDate: {
- title: intl.formatMessage(messages.date),
- description: intl.formatMessage(messages.dateDescription),
- type: 'boolean',
- },
- moreLinkText: {
- title: intl.formatMessage(messages.moreLinkText),
- description: intl.formatMessage(messages.moreLinkTextDescription),
- },
- moreLinkUrl: {
- title: intl.formatMessage(messages.moreLinkUrl),
- description: intl.formatMessage(messages.moreLinkUrlDescription),
- widget: 'object_browser',
- mode: 'link',
- allowExternals: true,
- },
- },
- };
-};
diff --git a/src/index.js b/src/index.js
index 2b7763a..de92d38 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,14 +1,22 @@
import AdvancedListingBlockTemplate from './AdvancedListingBlockTemplate';
-import { advancedSchema } from './advancedSchema';
+import AdvancedCarouselBlockTemplate from './AdvancedCarouselBlockTemplate';
+import {advancedListingSchema} from './AdvancedListingSchema';
+import {advancedCarouselSchema} from './AdvancedCarouselSchema';
const applyConfig = (config) => {
config.blocks.blocksConfig.listing.variations = [
...config.blocks.blocksConfig.listing.variations,
{
id: 'advanced',
- title: 'Advanced',
+ title: 'Advanced Listing',
template: AdvancedListingBlockTemplate,
- schemaEnhancer: advancedSchema,
+ schemaEnhancer: advancedListingSchema,
+ },
+ {
+ id: 'advancedCarousel',
+ title: 'Advanced Carousel',
+ template: AdvancedCarouselBlockTemplate,
+ schemaEnhancer: advancedCarouselSchema,
},
];
return config;
diff --git a/src/messages.js b/src/messages.js
index 640122e..847be9f 100644
--- a/src/messages.js
+++ b/src/messages.js
@@ -1,4 +1,5 @@
-import { defineMessages } from 'react-intl';
+import {defineMessages} from 'react-intl';
+
const messages = defineMessages({
querystring: {
id: 'Query',
@@ -12,10 +13,6 @@ const messages = defineMessages({
id: 'Header text',
defaultMessage: 'Header text',
},
- headerDescription: {
- id: 'Header description',
- defaultMessage: 'Block header text',
- },
headerUrl: {
id: 'Header url',
defaultMessage: 'Header url or object',
@@ -37,24 +34,24 @@ const messages = defineMessages({
defaultMessage: 'Columns',
},
columnsCount: {
- id: 'How many columns:',
- defaultMessage: 'How many columns:',
+ id: 'Number of columns',
+ defaultMessage: 'Number of columns',
},
imageConfiguration: {
id: 'Image position/size',
defaultMessage: 'Image position/size',
},
imageWidth: {
- id: 'Image width (x/12):',
- defaultMessage: 'Image width (x/12):',
+ id: 'Image width',
+ defaultMessage: 'Image width',
},
imageWidthDescription: {
- id: 'Default image width will be 2/12',
- defaultMessage: 'Default image width will be 2/12',
+ id: 'Left/Right image width (default 2/12)',
+ defaultMessage: 'Left/Right image width (default 4/12)',
},
imagePosition: {
- id: 'Image position:',
- defaultMessage: 'Image position:',
+ id: 'Image position',
+ defaultMessage: 'Image position',
},
imagePositionDescription: {
id: 'Default with no image',
@@ -65,8 +62,8 @@ const messages = defineMessages({
defaultMessage: 'Title',
},
titleTag: {
- id: 'Title text HTML tag',
- defaultMessage: 'HTML tag',
+ id: 'titleTag',
+ defaultMessage: 'Title Level',
},
titleTagDescription: {
id: 'Default HTML tag will be H3',
@@ -78,20 +75,12 @@ const messages = defineMessages({
},
descriptionTitle: {
id: 'descriptionTitle',
- defaultMessage: 'Show the description?',
+ defaultMessage: 'Description',
},
descriptionDescription: {
id: 'descriptionDescription',
defaultMessage: 'If selected, the description will be shown',
},
- dateConfiguration: {
- id: 'effectiveDate',
- defaultMessage: 'Effective date',
- },
- date: {
- id: 'effectiveDate',
- defaultMessage: 'Effective date',
- },
dateDescription: {
id: 'Show effectiveDate',
defaultMessage: 'Show effectiveDate',
@@ -116,6 +105,26 @@ const messages = defineMessages({
id: 'moreLinkUrlDescription',
defaultMessage: 'Paste an external link or a plone object',
},
+ itemDisplayOptions: {
+ id: 'itemDisplayOptions',
+ defaultMessage: 'Item Display Options',
+ },
+ eventDate: {
+ id: 'eventDate',
+ defaultMessage: 'Show Event Date',
+ },
+ eventTime: {
+ id: 'eventTime',
+ defaultMessage: 'Show Event Time',
+ },
+ eventLocation: {
+ id: 'eventLocation',
+ defaultMessage: 'Show Event Location',
+ },
+ date: {
+ id: 'date',
+ defaultMessage: 'Show Effective Date',
+ },
});
export default messages;
diff --git a/src/placeholder.png b/src/placeholder.png
new file mode 100644
index 0000000..0b19272
Binary files /dev/null and b/src/placeholder.png differ