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 && ( + + This content has no image, this is a default placeholder. + + )} + {item.image_field && ( + {item.title})} +
+
+ {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 && ( + + This content has no image, this is a default placeholder. + + )} + {item.image_field && ( + + {item.title} + + )} + )} + + {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 && ( + + This content has no image, this is a default placeholder. + + )} + {item.image_field && ( + + {item.title} + + )} + )} +
+ )) + )} + +
+ +
+ ); + + +}; + +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 && ( This content has no image, this is a default placeholder. {item.title} )} - - )} - - + )} + + {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 && ( This content has no image, this is a default placeholder. {item.title} )} -
- )} +
)} +
+ )) + )} + {['background'].includes(imageSide) && ( + items.map((item) => ( + + +
+ +
+ {!item.image_field && ( + + This content has no image, this is a default placeholder. + + )} + {item.image_field && ( + {item.title})} +
+
+ {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