From bf3fdd9d5911b93504b7b6e73da378c1e470c22e Mon Sep 17 00:00:00 2001 From: Tiberiu Ichim Date: Mon, 31 Oct 2022 17:38:50 +0200 Subject: [PATCH] WIP refactor package structure --- src/blocks/Listing/index.js | 190 ++++++++------ .../{ => item-templates}/CardTemplates.jsx | 0 .../{ => item-templates}/ItemTemplates.jsx | 3 + .../SearchItemTemplate.jsx | 6 +- .../Carousel.jsx} | 9 +- .../Gallery.jsx} | 11 +- .../Listing.jsx} | 18 +- .../NewsList.jsx | 0 src/blocks/Listing/schema.js | 241 +++++++++++++++--- .../UniversalCard/UniversalCard.jsx | 2 +- .../{ => fragments}/CardDescription.jsx | 0 .../{ => fragments}/CardExtra.jsx | 0 .../{ => fragments}/CardImage.jsx | 0 .../{ => fragments}/CardMeta.jsx | 0 .../{ => fragments}/CardTitle.jsx | 0 src/components/UniversalCard/index.js | 10 +- src/components/UniversalCard/schema.js | 162 +++--------- .../UniversalItem/UniversalItem.jsx | 42 +-- src/components/UniversalItem/index.js | 5 - src/components/UniversalItem/model.js | 74 ------ src/components/UniversalItem/schema.js | 176 ++++--------- src/index.js | 2 +- src/schema-utils.js | 180 +++++++------ 23 files changed, 558 insertions(+), 573 deletions(-) rename src/blocks/Listing/{ => item-templates}/CardTemplates.jsx (100%) rename src/blocks/Listing/{ => item-templates}/ItemTemplates.jsx (92%) rename src/blocks/Listing/{ => item-templates}/SearchItemTemplate.jsx (89%) rename src/blocks/Listing/{templates/CardsCarousel.jsx => layout-templates/Carousel.jsx} (93%) rename src/blocks/Listing/{templates/CardsGallery.jsx => layout-templates/Gallery.jsx} (92%) rename src/blocks/Listing/{templates/Summary.jsx => layout-templates/Listing.jsx} (77%) rename src/blocks/Listing/{templates => layout-templates}/NewsList.jsx (100%) rename src/components/UniversalCard/{ => fragments}/CardDescription.jsx (100%) rename src/components/UniversalCard/{ => fragments}/CardExtra.jsx (100%) rename src/components/UniversalCard/{ => fragments}/CardImage.jsx (100%) rename src/components/UniversalCard/{ => fragments}/CardMeta.jsx (100%) rename src/components/UniversalCard/{ => fragments}/CardTitle.jsx (100%) delete mode 100644 src/components/UniversalItem/index.js delete mode 100644 src/components/UniversalItem/model.js diff --git a/src/blocks/Listing/index.js b/src/blocks/Listing/index.js index 26978c68..44593152 100644 --- a/src/blocks/Listing/index.js +++ b/src/blocks/Listing/index.js @@ -1,132 +1,176 @@ -import CardsCarousel from './templates/CardsCarousel'; -import CardsGallery from './templates/CardsGallery'; -import NewsList from './templates/NewsList'; -import Summary from './templates/Summary'; +import { compose } from 'redux'; +import Carousel from './layout-templates/Carousel'; +import Gallery from './layout-templates/Gallery'; +import Listing from './layout-templates/Listing'; +import { + setBasicStylingSchema, + setCardStylingSchema, + setCardModelSchema, + setItemModelSchema, +} from './schema'; import { DefaultCardLayout, ImageCardLayout, LeftImageCardLayout, RightImageCardLayout, -} from './CardTemplates'; - -import { DefaultItemLayout } from './ItemTemplates'; -import { SearchItemLayout } from './SearchItemTemplate'; +} from './item-templates/CardTemplates'; -import { BasicListingBlockStylesSchema } from './schema'; +import { DefaultItemLayout } from './item-templates/ItemTemplates'; +import { SearchItemLayout } from './item-templates/SearchItemTemplate'; -import { CardStylingSchemaEnhancer } from './schema'; +import universalCardSchemaEnhancer from '@eeacms/volto-listing-block/components/UniversalCard/schema'; const applyConfig = (config) => { // moment date locale. See https://momentjs.com/ - Multiple Locale Support - config.settings.dateLocale = config.settings.dateLocale || 'en'; + config.settings.dateLocale = config.settings.dateLocale ?? 'en'; const { listing } = config.blocks.blocksConfig; const blacklist = ['summary']; - const { schemaEnhancer } = listing; - - listing.stylesSchema = BasicListingBlockStylesSchema; - - listing.schemaEnhancer = (props) => { - // NOTE: this is a schema finalizer - const schema = schemaEnhancer ? schemaEnhancer(props) : props.schema; + listing.schemaEnhancer = moveQueryToFieldset(listing.schemaEnhancer); - // move querystring to its own fieldset; - schema.fieldsets[0].fields = schema.fieldsets[0].fields.filter( - (f) => f !== 'querystring', - ); - schema.fieldsets.splice(1, 0, { - id: 'querystring', - title: 'Query', - fields: ['querystring'], - }); - - return schema; - }; + // The split of responsibilities is as follows: + // the Listing block variation takes care of the Layout responsibility (how + // the items are listed) + // The variation takes care of how the individual item is displayed. + // With our own variations being based on the UniversalCard, we have another + // level of control on how each item is displayed. listing.variations = [ ...listing.variations.filter(({ id }) => blacklist.indexOf(id) === -1), { id: 'summary', isDefault: false, - title: 'Item listing', - template: Summary, - schemaEnhancer: Summary.schemaEnhancer, - stylesSchema: Summary.styleSchemaEnhancer, + title: 'Listing', + template: Listing, + schemaEnhancer: compose( + Listing.schemaEnhancer, // layout schema + setBasicStylingSchema, + universalCardSchemaEnhancer, + ), }, { id: 'cardsCarousel', isDefault: false, - title: 'Cards carousel', - template: CardsCarousel, - schemaEnhancer: CardsCarousel.schemaEnhancer, - stylesSchema: CardsCarousel.styleSchemaEnhancer, - }, - { - id: 'customCardsGalleryVariationId', - isDefault: false, - title: 'Cards gallery', - template: CardsGallery, - schemaEnhancer: CardsGallery.schemaEnhancer, - stylesSchema: CardStylingSchemaEnhancer, + title: 'Carousel', + template: Carousel, + schemaEnhancer: compose( + Carousel.schemaEnhancer, + setBasicStylingSchema, + universalCardSchemaEnhancer, + ), }, { - id: 'customNewsListVariationId', + id: 'cardsGallery', // 'customCardsGalleryVariationId' isDefault: false, - title: 'News List', - template: NewsList, - schemaEnhancer: NewsList.schemaEnhancer, + title: 'Gallery', + template: Gallery, + schemaEnhancer: compose( + Gallery.schemaEnhancer, + setBasicStylingSchema, + universalCardSchemaEnhancer, + ), }, ]; listing.extensions = { ...listing.extensions, - itemTemplates: [ - { - id: 'item', - isDefault: true, - title: 'Basic Item', - view: DefaultItemLayout, - }, - { - id: 'searchItem', - isDefault: false, - title: 'Search Item', - view: SearchItemLayout, - stylesSchema: SearchItemLayout.styleSchemaEnhancer, - }, - ], cardTemplates: [ { id: 'card', isDefault: true, title: 'Card (default)', - view: DefaultCardLayout, + template: DefaultCardLayout, + schemaEnhancer: compose(setCardModelSchema, setCardStylingSchema), }, { id: 'imageCard', title: 'Image Card', - view: ImageCardLayout, + template: ImageCardLayout, + schemaEnhancer: compose(setCardModelSchema, setCardStylingSchema), }, { id: 'imageOnLeft', title: 'Image on left', - view: LeftImageCardLayout, + template: LeftImageCardLayout, + schemaEnhancer: compose(setCardModelSchema, setCardStylingSchema), }, { id: 'imageOnRight', title: 'Image on right', - view: RightImageCardLayout, + template: RightImageCardLayout, + schemaEnhancer: compose(setCardModelSchema, setCardStylingSchema), + }, + { + id: 'item', + isDefault: true, + title: 'Listing Item', + template: DefaultItemLayout, + schemaEnhancer: compose( + setItemModelSchema, + setCardStylingSchema, + DefaultItemLayout.schemaEnhancer, + ), + }, + { + id: 'searchItem', + isDefault: false, + title: 'Search Item', + template: SearchItemLayout, + schemaEnhancer: compose( + setCardStylingSchema, + SearchItemLayout.schemaEnhancer, + ), }, ], }; - // Theming - // This bug needs to be fixed first: https://github.com/plone/volto/issues/3675 - // listing.enableStyling = true; - return config; }; export default applyConfig; + +const moveQueryToFieldset = (schemaEnhancer) => (props) => { + // NOTE: this is a schema finalizer + const schema = schemaEnhancer ? schemaEnhancer(props) : props.schema; + + // move querystring to its own fieldset; + schema.fieldsets[0].fields = schema.fieldsets[0].fields.filter( + (f) => f !== 'querystring', + ); + schema.fieldsets.splice(1, 0, { + id: 'querystring', + title: 'Query', + fields: ['querystring'], + }); + + return schema; +}; + +// import { CardStylingSchemaEnhancer } from '../schema'; +// CardsCarousel.styleSchemaEnhancer = ({ schema, intl }) => { +// return CardStylingSchemaEnhancer({ schema }); +// }; + +// Listing.schemaEnhancer = UniversalItem.schemaEnhancer; +// +// Listing.styleSchemaEnhancer = ({ schema, intl }) => { +// return schema; +// }; +// listing.stylesSchema = BasicListingBlockStylesSchema; +// stylesSchema: Summary.styleSchemaEnhancer, +// stylesSchema: CardStylingSchemaEnhancer, +// stylesSchema: CardsCarousel.styleSchemaEnhancer, +// stylesSchema: SearchItemLayout.styleSchemaEnhancer, +// { +// id: 'customNewsListVariationId', +// isDefault: false, +// title: 'News List', +// template: NewsList, +// // schemaEnhancer: NewsList.schemaEnhancer, +// }, +// Theming +// This bug needs to be fixed first: https://github.com/plone/volto/issues/3675 +// listing.enableStyling = true; +// import NewsList from './templates/NewsList'; diff --git a/src/blocks/Listing/CardTemplates.jsx b/src/blocks/Listing/item-templates/CardTemplates.jsx similarity index 100% rename from src/blocks/Listing/CardTemplates.jsx rename to src/blocks/Listing/item-templates/CardTemplates.jsx diff --git a/src/blocks/Listing/ItemTemplates.jsx b/src/blocks/Listing/item-templates/ItemTemplates.jsx similarity index 92% rename from src/blocks/Listing/ItemTemplates.jsx rename to src/blocks/Listing/item-templates/ItemTemplates.jsx index f03cdbf9..8caad376 100644 --- a/src/blocks/Listing/ItemTemplates.jsx +++ b/src/blocks/Listing/item-templates/ItemTemplates.jsx @@ -4,6 +4,7 @@ import { ConditionalLink, FormattedDate } from '@plone/volto/components'; import { getVoltoStyles } from '@eeacms/volto-listing-block/schema-utils'; import PreviewImage from '@eeacms/volto-listing-block/PreviewImage'; +// import { universalItemSchemaEnhancer } from '@eeacms/volto-listing-block/components/UniversalItem/schema'; const BodyText = ({ item, hasDate, hasDescription }) => { return ( @@ -77,3 +78,5 @@ const BasicItem = (props) => { export const DefaultItemLayout = (props) => { return ; }; + +// DefaultItemLayout.schemaEnhancer = universalItemSchemaEnhancer; diff --git a/src/blocks/Listing/SearchItemTemplate.jsx b/src/blocks/Listing/item-templates/SearchItemTemplate.jsx similarity index 89% rename from src/blocks/Listing/SearchItemTemplate.jsx rename to src/blocks/Listing/item-templates/SearchItemTemplate.jsx index 1fbfce83..2a9cff19 100644 --- a/src/blocks/Listing/SearchItemTemplate.jsx +++ b/src/blocks/Listing/item-templates/SearchItemTemplate.jsx @@ -1,5 +1,6 @@ import cx from 'classnames'; import PreviewImage from '@eeacms/volto-listing-block/PreviewImage'; +// import { universalItemSchemaEnhancer } from '@eeacms/volto-listing-block/components/UniversalItem/schema'; const BodyText = ({ item, hasDescription }) => { return ( @@ -59,6 +60,5 @@ const BasicItem = (props) => { export const SearchItemLayout = (props) => { return ; }; -SearchItemLayout.styleSchemaEnhancer = ({ schema, intl }) => { - return schema; -}; + +// SearchItemLayout.schemaEnhancer = universalItemSchemaEnhancer; diff --git a/src/blocks/Listing/templates/CardsCarousel.jsx b/src/blocks/Listing/layout-templates/Carousel.jsx similarity index 93% rename from src/blocks/Listing/templates/CardsCarousel.jsx rename to src/blocks/Listing/layout-templates/Carousel.jsx index a9e9631f..84ea5025 100644 --- a/src/blocks/Listing/templates/CardsCarousel.jsx +++ b/src/blocks/Listing/layout-templates/Carousel.jsx @@ -4,7 +4,6 @@ import loadable from '@loadable/component'; import UniversalCard from '@eeacms/volto-listing-block/components/UniversalCard/UniversalCard'; import ResponsiveContainer from '@eeacms/volto-listing-block/components/ResponsiveContainer'; -import { CardStylingSchemaEnhancer } from '../schema'; const Slider = loadable(() => import('react-slick')); @@ -116,8 +115,8 @@ const CardsCarousel = ({ block, items, ...rest }) => { ); }; -CardsCarousel.schemaEnhancer = (args) => { - const schema = UniversalCard.schemaEnhancer(args); +CardsCarousel.schemaEnhancer = ({ schema }) => { + // const schema = UniversalCard.schemaEnhancer(args); schema.fieldsets.splice(1, 0, { id: 'carousel', @@ -146,8 +145,4 @@ CardsCarousel.schemaEnhancer = (args) => { }; }; -CardsCarousel.styleSchemaEnhancer = ({ schema, intl }) => { - return CardStylingSchemaEnhancer({ schema }); -}; - export default CardsCarousel; diff --git a/src/blocks/Listing/templates/CardsGallery.jsx b/src/blocks/Listing/layout-templates/Gallery.jsx similarity index 92% rename from src/blocks/Listing/templates/CardsGallery.jsx rename to src/blocks/Listing/layout-templates/Gallery.jsx index 65641087..d07dbacb 100644 --- a/src/blocks/Listing/templates/CardsGallery.jsx +++ b/src/blocks/Listing/layout-templates/Gallery.jsx @@ -4,7 +4,7 @@ import React from 'react'; import UniversalCard from '@eeacms/volto-listing-block/components/UniversalCard/UniversalCard'; import config from '@plone/volto/registry'; -const CardsGallery = ({ +const Gallery = ({ block, items, gridSize, @@ -27,9 +27,10 @@ const CardsGallery = ({ ); }; -CardsGallery.schemaEnhancer = (args) => { - const schema = UniversalCard.schemaEnhancer(args); +Gallery.schemaEnhancer = ({ schema }) => { + // const schema = UniversalCard.schemaEnhancer(args); // schema.fieldsets[0].fields.push('gridSize'); + schema.fieldsets.splice(1, 0, { id: 'cardsGallery', title: 'Gallery', @@ -52,13 +53,13 @@ CardsGallery.schemaEnhancer = (args) => { return schema; }; -CardsGallery.propTypes = { +Gallery.propTypes = { items: PropTypes.arrayOf(PropTypes.any).isRequired, linkMore: PropTypes.any, isEditMode: PropTypes.bool, }; -export default CardsGallery; +export default Gallery; // const makeTextBody = (item) => ( // diff --git a/src/blocks/Listing/templates/Summary.jsx b/src/blocks/Listing/layout-templates/Listing.jsx similarity index 77% rename from src/blocks/Listing/templates/Summary.jsx rename to src/blocks/Listing/layout-templates/Listing.jsx index 3ec6527c..9b4a74f7 100644 --- a/src/blocks/Listing/templates/Summary.jsx +++ b/src/blocks/Listing/layout-templates/Listing.jsx @@ -3,12 +3,12 @@ import PropTypes from 'prop-types'; import moment from 'moment'; // TODO: this needs to be lazyloaded!!! import { ConditionalLink } from '@plone/volto/components'; -import UniversalItem from '@eeacms/volto-listing-block/components/UniversalItem/UniversalItem'; +import UniversalCard from '@eeacms/volto-listing-block/components/UniversalCard/UniversalCard'; import { flattenToAppURL } from '@plone/volto/helpers'; import { isInternalURL } from '@plone/volto/helpers/Url/Url'; import config from '@plone/volto/registry'; -const SummaryListing = (props) => { +const Listing = (props) => { const { block, items, linkTitle, linkHref, isEditMode } = props; let href = linkHref?.[0]?.['@id'] || ''; @@ -26,7 +26,7 @@ const SummaryListing = (props) => {
{items && items.length > 0 ? ( items.map((item, index) => ( - { ); }; -SummaryListing.schemaEnhancer = UniversalItem.schemaEnhancer; - -SummaryListing.styleSchemaEnhancer = ({ schema, intl }) => { - return schema; -}; - -SummaryListing.propTypes = { +Listing.propTypes = { items: PropTypes.arrayOf(PropTypes.any).isRequired, linkMore: PropTypes.any, isEditMode: PropTypes.bool, }; -export default SummaryListing; +Listing.schemaEnhancer = ({ schema }) => schema; + +export default Listing; diff --git a/src/blocks/Listing/templates/NewsList.jsx b/src/blocks/Listing/layout-templates/NewsList.jsx similarity index 100% rename from src/blocks/Listing/templates/NewsList.jsx rename to src/blocks/Listing/layout-templates/NewsList.jsx diff --git a/src/blocks/Listing/schema.js b/src/blocks/Listing/schema.js index e90e815f..aad307cc 100644 --- a/src/blocks/Listing/schema.js +++ b/src/blocks/Listing/schema.js @@ -8,7 +8,213 @@ const ALIGN_INFO_MAP = { align_center: [alignCenterSVG, 'Center'], }; -export const CardStylingSchemaEnhancer = ({ schema }) => { +export const setBasicStylingSchema = ({ schema, intl }) => { + schema.properties.styles.schema = { + fieldsets: [ + { + id: 'styling', + title: 'Styling', + fields: ['theme', 'inverted', 'rounded'], + }, + ], + properties: { + theme: { + title: intl.formatMessage(messages.Theme), + description: intl.formatMessage(messages.ThemeHelp), + choices: [ + ['', intl.formatMessage(messages.ThemeDefault)], + ['primary', intl.formatMessage(messages.ThemePrimary)], + ['secondary', intl.formatMessage(messages.ThemeSecondary)], + ['tertiary', intl.formatMessage(messages.ThemeTertiary)], + ], + }, + inverted: { + title: intl.formatMessage(messages.Inverted), + description: intl.formatMessage(messages.InvertedHelp), + type: 'boolean', + }, + rounded: { + title: intl.formatMessage(messages.Rounded), + description: intl.formatMessage(messages.RoundedHelp), + type: 'boolean', + }, + }, + required: [], + }; + + return schema; +}; + +const CallToActionSchema = ({ formData }) => { + return { + fieldsets: [ + { + id: 'default', + fields: [ + 'enable', + ...(formData.itemModel?.callToAction?.enable + ? [ + 'label', + formData['@type'] === 'listing' ? 'urlTemplate' : 'href', + ] + : []), + ], // + title: 'Default', + }, + ], + properties: { + enable: { + type: 'boolean', + title: 'Show action', + }, + label: { + title: 'Action label', + default: 'Read more', + defaultValue: 'Read more', + }, + href: { + title: 'Action URL', + widget: 'object_browser', + mode: 'link', + selectedItemAttrs: ['Title', 'Description'], + allowExternals: true, + }, + urlTemplate: { + title: 'Action URL Template', + description: + 'Enter a path. Available placeholders: $URL, $PORTAL_URL. If empty, the result URL will be used.', + }, + }, + required: [], + }; +}; + +export const setCardModelSchema = ({ formData, schema }) => { + const CardSchema = { + fieldsets: [ + { + id: 'cardDesigner', + title: 'Card', + fields: [ + 'hasDate', + 'hasDescription', + ...(formData?.itemModel?.hasDescription ? ['maxDescription'] : []), + 'hasMetaType', + 'hasLabel', + 'hasTags', + 'callToAction', + ], + }, + ], + properties: { + hasDate: { + title: 'Publication date', + type: 'boolean', + }, + hasDescription: { + title: 'Description', + type: 'boolean', + }, + maxDescription: { + title: 'Description max lines', + description: + "Limit description to a maximum number of lines by adding trailing '...'", + type: 'number', + default: 2, + minimum: 0, + maximum: 5, + }, + hasMetaType: { + title: 'Show portal type', + type: 'boolean', + }, + hasLabel: { + title: 'Show new/archived label', + type: 'boolean', + }, + hasTags: { + title: 'Show tags', + type: 'boolean', + }, + callToAction: { + widget: 'object', + schema: CallToActionSchema({ formData }), + }, + }, + required: [], + }; + + schema.properties.itemModel.schema = CardSchema; + return schema; +}; + +export const setItemModelSchema = ({ formData, schema }) => { + const ItemSchema = { + fieldsets: [ + { + id: 'itemDesigner', + title: 'Item', + fields: [ + 'hasDate', + 'hasDescription', + 'maxDescription', + 'hasImage', + ...(formData.itemModel?.hasImage ? ['imageOnRightSide'] : []), + // 'hasMetaType', + // 'hasLabel', + // 'hasTags', + // 'callToAction', + ], + }, + ], + properties: { + hasDate: { + title: 'Publication date', + type: 'boolean', + }, + hasDescription: { + title: 'Description', + type: 'boolean', + default: true, + }, + maxDescription: { + title: 'Description max lines', + description: + "Limit description to a maximum number of lines by adding trailing '...'", + type: 'number', + default: 2, + minimum: 0, + maximum: 5, + }, + hasImage: { + title: 'Image', + type: 'boolean', + default: true, + }, + imageOnRightSide: { + title: 'Image on Right (Default is Left)', + type: 'boolean', + }, + // hasMetaType: { + // title: 'Show portal type', + // type: 'boolean', + // }, + // hasLabel: { + // title: 'Show new/archived label', + // type: 'boolean', + // }, + // hasTags: { + // title: 'Show tags', + // type: 'boolean', + // }, + }, + required: [], + }; + schema.properties.itemModel.schema = ItemSchema; + return schema; +}; + +export const setCardStylingSchema = ({ schema }) => { const styleSchema = schema.properties.styles.schema; styleSchema.fieldsets[0].fields.push('text_align'); styleSchema.properties = { @@ -23,36 +229,3 @@ export const CardStylingSchemaEnhancer = ({ schema }) => { return schema; }; - -export const BasicListingBlockStylesSchema = ({ intl }) => ({ - fieldsets: [ - { - id: 'styling', - title: 'Styling', - fields: ['theme', 'inverted', 'rounded'], - }, - ], - properties: { - theme: { - title: intl.formatMessage(messages.Theme), - description: intl.formatMessage(messages.ThemeHelp), - choices: [ - ['', intl.formatMessage(messages.ThemeDefault)], - ['primary', intl.formatMessage(messages.ThemePrimary)], - ['secondary', intl.formatMessage(messages.ThemeSecondary)], - ['tertiary', intl.formatMessage(messages.ThemeTertiary)], - ], - }, - inverted: { - title: intl.formatMessage(messages.Inverted), - description: intl.formatMessage(messages.InvertedHelp), - type: 'boolean', - }, - rounded: { - title: intl.formatMessage(messages.Rounded), - description: intl.formatMessage(messages.RoundedHelp), - type: 'boolean', - }, - }, - required: [], -}); diff --git a/src/components/UniversalCard/UniversalCard.jsx b/src/components/UniversalCard/UniversalCard.jsx index f4f12df3..3404d94d 100644 --- a/src/components/UniversalCard/UniversalCard.jsx +++ b/src/components/UniversalCard/UniversalCard.jsx @@ -15,7 +15,7 @@ function UniversalCard(props) { itemModel, ); // const CardTemplate = BasicCard; - const CardTemplate = extension.view; + const CardTemplate = extension.template; const classNames = getVoltoStyles(styles); return ( diff --git a/src/components/UniversalCard/CardDescription.jsx b/src/components/UniversalCard/fragments/CardDescription.jsx similarity index 100% rename from src/components/UniversalCard/CardDescription.jsx rename to src/components/UniversalCard/fragments/CardDescription.jsx diff --git a/src/components/UniversalCard/CardExtra.jsx b/src/components/UniversalCard/fragments/CardExtra.jsx similarity index 100% rename from src/components/UniversalCard/CardExtra.jsx rename to src/components/UniversalCard/fragments/CardExtra.jsx diff --git a/src/components/UniversalCard/CardImage.jsx b/src/components/UniversalCard/fragments/CardImage.jsx similarity index 100% rename from src/components/UniversalCard/CardImage.jsx rename to src/components/UniversalCard/fragments/CardImage.jsx diff --git a/src/components/UniversalCard/CardMeta.jsx b/src/components/UniversalCard/fragments/CardMeta.jsx similarity index 100% rename from src/components/UniversalCard/CardMeta.jsx rename to src/components/UniversalCard/fragments/CardMeta.jsx diff --git a/src/components/UniversalCard/CardTitle.jsx b/src/components/UniversalCard/fragments/CardTitle.jsx similarity index 100% rename from src/components/UniversalCard/CardTitle.jsx rename to src/components/UniversalCard/fragments/CardTitle.jsx diff --git a/src/components/UniversalCard/index.js b/src/components/UniversalCard/index.js index af75b6d7..7c7a8750 100644 --- a/src/components/UniversalCard/index.js +++ b/src/components/UniversalCard/index.js @@ -1,5 +1,5 @@ -export CardDescription from './CardDescription'; -export CardExtra from './CardExtra'; -export CardImage from './CardImage'; -export CardMeta from './CardMeta'; -export CardTitle from './CardTitle'; +export CardDescription from './fragments/CardDescription'; +export CardExtra from './fragments/CardExtra'; +export CardImage from './fragments/CardImage'; +export CardMeta from './fragments/CardMeta'; +export CardTitle from './fragments/CardTitle'; diff --git a/src/components/UniversalCard/schema.js b/src/components/UniversalCard/schema.js index 8b8a7591..8e786f5a 100644 --- a/src/components/UniversalCard/schema.js +++ b/src/components/UniversalCard/schema.js @@ -1,8 +1,5 @@ import { defineMessages } from 'react-intl'; -import { - schemaEnhancerFactory, - enhanceStylingSchema, -} from '@eeacms/volto-listing-block/schema-utils'; +import { DefaultCardModelSchema } from '@eeacms/volto-listing-block/schema-utils'; const messages = defineMessages({ title: { @@ -11,144 +8,49 @@ const messages = defineMessages({ }, }); -const CallToActionSchema = ({ formData }) => { - return { - fieldsets: [ - { - id: 'default', - fields: [ - 'enable', - ...(formData.itemModel?.callToAction?.enable - ? [ - 'label', - formData['@type'] === 'listing' ? 'urlTemplate' : 'href', - ] - : []), - ], // - title: 'Default', - }, - ], - properties: { - enable: { - type: 'boolean', - title: 'Show action', - }, - label: { - title: 'Action label', - default: 'Read more', - defaultValue: 'Read more', - }, - href: { - title: 'Action URL', - widget: 'object_browser', - mode: 'link', - selectedItemAttrs: ['Title', 'Description'], - allowExternals: true, - }, - urlTemplate: { - title: 'Action URL Template', - description: - 'Enter a path. Available placeholders: $URL, $PORTAL_URL. If empty, the result URL will be used.', - }, - }, - required: [], - }; -}; - -const CardSchema = ({ formData }) => { - return { - fieldsets: [ - { - id: 'cardDesigner', - title: 'Card', - fields: [ - 'hasDate', - 'hasDescription', - ...(formData?.itemModel?.hasDescription ? ['maxDescription'] : []), - 'hasMetaType', - 'hasLabel', - 'hasTags', - 'callToAction', - ], - }, - ], - properties: { - hasDate: { - title: 'Publication date', - type: 'boolean', - }, - hasDescription: { - title: 'Description', - type: 'boolean', - }, - maxDescription: { - title: 'Description max lines', - description: - "Limit description to a maximum number of lines by adding trailing '...'", - type: 'number', - default: 2, - minimum: 0, - maximum: 5, - }, - hasMetaType: { - title: 'Show portal type', - type: 'boolean', - }, - hasLabel: { - title: 'Show new/archived label', - type: 'boolean', - }, - hasTags: { - title: 'Show tags', - type: 'boolean', - }, - callToAction: { - widget: 'object', - schema: CallToActionSchema({ formData }), - }, - }, - required: [], - }; -}; - export default function universalCardSchemaEnhancer(props) { const { schema } = props; - props.formData = props.formData || props.data; - const enhancer = schemaEnhancerFactory({ - extensionName: 'cardTemplates', - messages, - blockType: 'listing', - extensionField: '@type', + + // props.formData = props.formData || props.data; + // const enhancer = schemaEnhancerFactory({ + // extensionName: 'cardTemplates', + // messages, + // blockType: 'listing', + // extensionField: '@type', + // }); + // + schema.fieldsets.push({ + id: 'cardDesigner', + title: 'Card', + fields: ['itemModel'], }); + const baseSchema = { ...schema, - fieldsets: [ - ...schema.fieldsets, - { - id: 'cardDesigner', - title: 'Card', - fields: ['itemModel'], - }, - ], + fieldsets: [...schema.fieldsets], properties: { ...schema.properties, itemModel: { title: 'Card model', widget: 'object', - schema: enhancer({ - ...props, - schema: CardSchema(props), - }), + schema: DefaultCardModelSchema, + // schema: enhancer({ + // ...props, + // schema: CardSchema(props), + // }), }, }, }; - const styledSchema = enhanceStylingSchema({ - ...props, - schema: baseSchema, - // schema: baseSchema.properties.styles.schema, - formData: props.formData, - }); - - return styledSchema; + return baseSchema; } + +// enhanceStylingSchema, + +// const styledSchema = enhanceStylingSchema({ +// ...props, +// schema: baseSchema, +// // schema: baseSchema.properties.styles.schema, +// formData: props.formData, +// }); +// return styledSchema; diff --git a/src/components/UniversalItem/UniversalItem.jsx b/src/components/UniversalItem/UniversalItem.jsx index 067047f8..af364006 100644 --- a/src/components/UniversalItem/UniversalItem.jsx +++ b/src/components/UniversalItem/UniversalItem.jsx @@ -1,21 +1,21 @@ -import config from '@plone/volto/registry'; -import { resolveExtension } from '@plone/volto/helpers/Extensions/withBlockExtensions'; -import { Item } from './model'; - -import universalItemSchemaEnhancer from './schema'; - -function UniversalItem(props) { - const { itemModel = {}, item, ...rest } = props; - const extension = resolveExtension( - '@type', - config.blocks.blocksConfig.listing.extensions.itemTemplates, - itemModel, - ); - const ItemTemplate = extension.view; - - return ; -} - -UniversalItem.schemaEnhancer = universalItemSchemaEnhancer; - -export default UniversalItem; +// import config from '@plone/volto/registry'; +// import { resolveExtension } from '@plone/volto/helpers/Extensions/withBlockExtensions'; +// import { Item } from './model'; +// +// import universalItemSchemaEnhancer from './schema'; +// +// function UniversalItem(props) { +// const { itemModel = {}, item, ...rest } = props; +// const extension = resolveExtension( +// '@type', +// config.blocks.blocksConfig.listing.extensions.itemTemplates, +// itemModel, +// ); +// const ItemTemplate = extension.view; +// +// return ; +// } +// +// UniversalItem.schemaEnhancer = universalItemSchemaEnhancer; +// +// export default UniversalItem; diff --git a/src/components/UniversalItem/index.js b/src/components/UniversalItem/index.js deleted file mode 100644 index 3ce54731..00000000 --- a/src/components/UniversalItem/index.js +++ /dev/null @@ -1,5 +0,0 @@ -// export CardDescription from './CardDescription'; -// export CardExtra from './CardExtra'; -// export CardImage from './CardImage'; -// export CardMeta from './CardMeta'; -// export CardTitle from './CardTitle'; diff --git a/src/components/UniversalItem/model.js b/src/components/UniversalItem/model.js deleted file mode 100644 index bf116d25..00000000 --- a/src/components/UniversalItem/model.js +++ /dev/null @@ -1,74 +0,0 @@ -import { toDate } from '@plone/volto/helpers/Utils/Date'; - -export class BasicModel { - constructor(record) { - const basic = { - _original: record, - }; - - return new Proxy(basic, this); - } - - get(target, name) { - // console.log('get', target, name); - if (target.hasOwnProperty(name)) { - // console.log('hasOwn', name); - return target[name]; - } - - const proto = Object.getPrototypeOf(this); - const descriptors = Object.getOwnPropertyDescriptors(proto); - - if (descriptors[name] && descriptors[name].get) { - const value = descriptors[name].get.bind(target).apply(); - delete target[name]; - target[name] = value; - return target[name]; - } else { - return target._original[name]; - } - } -} - -// One day in milliseconds -const oneDay = 1000 * 60 * 60 * 24; - -const diffDates = (start, end) => - Math.round((end.getTime() - start.getTime()) / oneDay); - -const daysSinceIssued = (item) => { - const raw = item['EffectiveDate']; - if (!raw || raw === 'None') return Infinity; - - const res = diffDates(toDate(raw), new Date()); - - return res; -}; - -export class Item extends BasicModel { - get daysSinceIssued() { - return daysSinceIssued(this._original); - } - - get isNew() { - const days = daysSinceIssued(this._original); - return days < 30; - } - - get issued() { - const raw = this._original['EffectiveDate']; - return raw && raw !== 'None' ? toDate(raw) : null; - } - - get expires() { - const raw = this._original['ExpirationDate']; - return raw && raw !== 'None' ? toDate(raw) : null; - } - get isExpired() { - const raw = this._original['ExpirationDate']; - if (!raw || raw === 'None') return null; - - const date = toDate(raw); - return date < new Date(); - } -} diff --git a/src/components/UniversalItem/schema.js b/src/components/UniversalItem/schema.js index 9128ab29..882f40dc 100644 --- a/src/components/UniversalItem/schema.js +++ b/src/components/UniversalItem/schema.js @@ -1,120 +1,56 @@ -import { - schemaEnhancerFactory, - enhanceStylingSchema, -} from '@eeacms/volto-listing-block/schema-utils'; -import { defineMessages } from 'react-intl'; - -const messages = defineMessages({ - title: { - id: 'Item type', - defaultMessage: 'Item type', - }, -}); - -const ItemSchema = ({ formData }) => { - return { - fieldsets: [ - { - id: 'itemDesigner', - title: 'Item', - fields: [ - 'hasDate', - 'hasDescription', - 'maxDescription', - 'hasImage', - ...(formData.itemModel?.hasImage ? ['imageOnRightSide'] : []), - // 'hasMetaType', - // 'hasLabel', - // 'hasTags', - // 'callToAction', - ], - }, - ], - properties: { - hasDate: { - title: 'Publication date', - type: 'boolean', - }, - hasDescription: { - title: 'Description', - type: 'boolean', - default: true, - }, - maxDescription: { - title: 'Description max lines', - description: - "Limit description to a maximum number of lines by adding trailing '...'", - type: 'number', - default: 2, - minimum: 0, - maximum: 5, - }, - hasImage: { - title: 'Image', - type: 'boolean', - default: true, - }, - imageOnRightSide: { - title: 'Image on Right (Default is Left)', - type: 'boolean', - }, - // hasMetaType: { - // title: 'Show portal type', - // type: 'boolean', - // }, - // hasLabel: { - // title: 'Show new/archived label', - // type: 'boolean', - // }, - // hasTags: { - // title: 'Show tags', - // type: 'boolean', - // }, - }, - required: [], - }; -}; - -export default function universalItemSchemaEnhancer(props) { - const { schema } = props; - props.formData = props.formData || props.data; - - const enhanceItemModel = schemaEnhancerFactory({ - extensionName: 'itemTemplates', - messages, - blockType: 'listing', - extensionField: '@type', - }); - - const baseSchema = { - ...schema, - fieldsets: [ - ...schema.fieldsets, - { - id: 'itemDesigner', - title: 'Item', - fields: ['itemModel'], - }, - ], - properties: { - ...schema.properties, - itemModel: { - title: 'Item model', - widget: 'object', - schema: enhanceItemModel({ - ...props, - schema: ItemSchema(props), - }), - }, - }, - }; - - const styledSchema = enhanceStylingSchema({ - ...props, - schema: baseSchema, - // schema: baseSchema.properties.styles.schema, - formData: props.formData, - }); - - return styledSchema; -} +// import { +// schemaEnhancerFactory, +// enhanceStylingSchema, +// } from '@eeacms/volto-listing-block/schema-utils'; +// import { defineMessages } from 'react-intl'; +// +// const messages = defineMessages({ +// title: { +// id: 'Item type', +// defaultMessage: 'Item type', +// }, +// }); +// +// export default function universalItemSchemaEnhancer(props) { +// const { schema } = props; +// props.formData = props.formData || props.data; +// +// const enhanceItemModel = schemaEnhancerFactory({ +// extensionName: 'itemTemplates', +// messages, +// blockType: 'listing', +// extensionField: '@type', +// }); +// +// const baseSchema = { +// ...schema, +// fieldsets: [ +// ...schema.fieldsets, +// { +// id: 'itemDesigner', +// title: 'Item', +// fields: ['itemModel'], +// }, +// ], +// properties: { +// ...schema.properties, +// itemModel: { +// title: 'Item model', +// widget: 'object', +// schema: enhanceItemModel({ +// ...props, +// schema: ItemSchema(props), +// }), +// }, +// }, +// }; +// +// const styledSchema = enhanceStylingSchema({ +// ...props, +// schema: baseSchema, +// // schema: baseSchema.properties.styles.schema, +// formData: props.formData, +// }); +// +// return styledSchema; +// } diff --git a/src/index.js b/src/index.js index 4fc86e93..c532cc61 100644 --- a/src/index.js +++ b/src/index.js @@ -7,7 +7,7 @@ import customizeListingBlock from './blocks/Listing'; import './less/listing-cards.less'; export { default as UniversalCard } from './components/UniversalCard/UniversalCard'; -export { default as UniversalItem } from './components/UniversalItem/UniversalItem'; +// export { default as UniversalItem } from './components/UniversalItem/UniversalItem'; const applyConfig = (config) => { // moment date locale. See https://momentjs.com/ - Multiple Locale Support diff --git a/src/schema-utils.js b/src/schema-utils.js index a70f5069..ce6217a3 100644 --- a/src/schema-utils.js +++ b/src/schema-utils.js @@ -1,7 +1,7 @@ import { cloneDeep } from 'lodash'; import config from '@plone/volto/registry'; -import { defineMessages } from 'react-intl'; +// import { defineMessages } from 'react-intl'; const addTypeSelect = ({ intl, schema, extensionName, messages }) => { const field = '@type'; @@ -46,90 +46,104 @@ export const schemaEnhancerFactory = ({ return addTypeSelect({ schema, intl, extensionName, messages }); }; -const messages = defineMessages({ - variation: { - id: 'Variation', - defaultMessage: 'Variation', - }, - styling: { - id: 'Styling', - defaultMessage: 'Styling', - }, -}); - -const addStylesField = ({ schema, intl, formData }) => { - // Add the default style schema as the first step in the "ladder". - // The order is as follows: - // - // - default volto style schema - // - listing block -> default style schema enhancer - // - listing block variation -> style schema enhancer - // - listing block card/item extension -> style schema enhancer - // - // We omit the first step in ladder because of bugs in Volto < 16.0.0-alpha.36 - // In later versions we won't have to redefine the styles field - - if (schema.properties.styles) return schema; - - const defaultStyleSchema = config.blocks.blocksConfig.listing.stylesSchema; - - schema.fieldsets.push({ - id: 'styling', - title: intl.formatMessage(messages.styling), - fields: ['styles'], - }); - - schema.properties.styles = { - widget: 'object', - title: intl.formatMessage(messages.styling), - schema: defaultStyleSchema({ formData, intl, schema }), - }; - - return schema; +export const DefaultCardModelSchema = { + title: 'Card Model', + fieldsets: [ + { + id: 'default', + title: 'Default', + fields: [], + }, + ], + properties: {}, + required: [], }; -export const enhanceStylingSchema = ({ - formData, - schema, - blockType = 'listing', - extensionName = 'itemTemplates', - intl, -}) => { - // Adds (to the limited styles schema) the new styling schema enhancements - schema = addStylesField({ formData, schema, intl }); - - // first, enhance styling schema based on the variation - // then, enhance it based on the `${extensionName}` - - const blockConfig = config.blocks.blocksConfig[blockType]; - const activeVariationId = - formData['variation'] || - blockConfig.variations?.find(({ isDefault }) => isDefault)?.id; - // TODO: use resolveExtensions() from Volto - const activeVariation = activeVariationId - ? blockConfig.variations.find(({ id }) => id === activeVariationId) - : {}; - - // TODO: not needed when we will use latest Volto - const variationStyleSchema = activeVariation?.stylesSchema; - schema = variationStyleSchema - ? variationStyleSchema({ schema: cloneDeep(schema), formData, intl }) - : schema; - // end TODO - const extensionType = '@type'; // the attribute name that's stored in the block data - const extensionTemplates = blockConfig.extensions?.[extensionName]; - const activeItemName = formData?.itemModel?.[extensionType]; - let activeItem = extensionTemplates?.find( - (item) => item.id === activeItemName, - ); - - const stylingSchema = activeItem?.['stylesSchema']; - schema = stylingSchema - ? stylingSchema({ schema: cloneDeep(schema), formData, intl }) - : schema; - - return schema; -}; +// const messages = defineMessages({ +// variation: { +// id: 'Variation', +// defaultMessage: 'Variation', +// }, +// styling: { +// id: 'Styling', +// defaultMessage: 'Styling', +// }, +// }); + +// const addStylesField = ({ schema, intl, formData }) => { +// // Add the default style schema as the first step in the "ladder". +// // The order is as follows: +// // +// // - default volto style schema +// // - listing block -> default style schema enhancer +// // - listing block variation -> style schema enhancer +// // - listing block card/item extension -> style schema enhancer +// // +// // We omit the first step in ladder because of bugs in Volto < 16.0.0-alpha.36 +// // In later versions we won't have to redefine the styles field +// +// if (schema.properties.styles) return schema; +// +// const defaultStyleSchema = config.blocks.blocksConfig.listing.stylesSchema; +// +// schema.fieldsets.push({ +// id: 'styling', +// title: intl.formatMessage(messages.styling), +// fields: ['styles'], +// }); +// +// schema.properties.styles = { +// widget: 'object', +// title: intl.formatMessage(messages.styling), +// schema: defaultStyleSchema({ formData, intl, schema }), +// }; +// +// return schema; +// }; + +// export const enhanceStylingSchema = ({ +// formData, +// schema, +// blockType = 'listing', +// extensionName = 'itemTemplates', +// intl, +// }) => { +// // Adds (to the limited styles schema) the new styling schema enhancements +// schema = addStylesField({ formData, schema, intl }); +// +// // first, enhance styling schema based on the variation +// // then, enhance it based on the `${extensionName}` +// +// const blockConfig = config.blocks.blocksConfig[blockType]; +// const activeVariationId = +// formData['variation'] || +// blockConfig.variations?.find(({ isDefault }) => isDefault)?.id; +// // TODO: use resolveExtensions() from Volto +// const activeVariation = activeVariationId +// ? blockConfig.variations.find(({ id }) => id === activeVariationId) +// : {}; +// +// // TODO: not needed when we will use latest Volto +// const variationStyleSchema = activeVariation?.stylesSchema; +// schema = variationStyleSchema +// ? variationStyleSchema({ schema: cloneDeep(schema), formData, intl }) +// : schema; +// // end TODO +// +// const extensionType = '@type'; // the attribute name that's stored in the block data +// const extensionTemplates = blockConfig.extensions?.[extensionName]; +// const activeItemName = formData?.itemModel?.[extensionType]; +// let activeItem = extensionTemplates?.find( +// (item) => item.id === activeItemName, +// ); +// +// const stylingSchema = activeItem?.['stylesSchema']; +// schema = stylingSchema +// ? stylingSchema({ schema: cloneDeep(schema), formData, intl }) +// : schema; +// +// return schema; +// }; export const getVoltoStyles = (props) => { const styles = props ? props : {};