diff --git a/.npmignore b/.npmignore
new file mode 100644
index 0000000..211dab2
--- /dev/null
+++ b/.npmignore
@@ -0,0 +1,16 @@
+.vscode/
+.history
+logs
+*.log
+npm-debug.log*
+.DS_Store
+*.swp
+yarn-error.log
+
+node_modules
+build
+dist
+.env.local
+.env.development.local
+.env.test.local
+.env.production.local
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..32da33e
--- /dev/null
+++ b/package.json
@@ -0,0 +1,15 @@
+{
+ "name": "@codesyntax/volto-listingadvanced-variation",
+ "version": "0.0.1",
+ "description": "volto-listingadvanced-variation: Volto add-on",
+ "main": "src/index.js",
+ "license": "MIT",
+ "keywords": [
+ "volto-addon",
+ "volto-variation",
+ "volto-listing-block",
+ "volto",
+ "plone",
+ "react"
+ ]
+}
\ No newline at end of file
diff --git a/src/AdvancedListingBlockTemplate.jsx b/src/AdvancedListingBlockTemplate.jsx
new file mode 100644
index 0000000..3cb450c
--- /dev/null
+++ b/src/AdvancedListingBlockTemplate.jsx
@@ -0,0 +1,109 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { ConditionalLink } from '@plone/volto/components';
+import { flattenToAppURL } from '@plone/volto/helpers';
+import config from '@plone/volto/registry';
+
+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';
+
+const AdvancedListingBlockTemplate = ({
+ items,
+ linkTitle,
+ linkHref,
+ isEditMode,
+ imageSide,
+ imageWidth,
+ howManyColumns,
+ titleTag,
+}) => {
+ let link = null;
+ let href = linkHref?.[0]?.['@id'] || '';
+ if (isInternalURL(href)) {
+ link = (
+
+ {linkTitle || href}
+
+ );
+ } else if (href) {
+ link = {linkTitle || href};
+ }
+
+ const { settings } = config;
+ const hasImage = imageSide !== null;
+ imageWidth = imageWidth ? imageWidth : 2;
+ return (
+ <>
+
+ {items.map((item) => (
+
+
+
+ {imageSide === 'left' && (
+
+ {!item[settings.listingPreviewImageField] && (
+
+ )}
+ {item[settings.listingPreviewImageField] && (
+
+ )}
+
+ )}
+
+ {titleTag ? (
+ titleTag(item.title ? item.title : item.id)
+ ) : (
+ {item.title ? item.title : item.id}
+ )}
+ {item.description}
+
+ {imageSide === 'right' && (
+
+ {!item[settings.listingPreviewImageField] && (
+
+ )}
+ {item[settings.listingPreviewImageField] && (
+
+ )}
+
+ )}
+
+
+
+ ))}
+
+ {link &&
{link}
}
+ >
+ );
+};
+
+AdvancedListingBlockTemplate.propTypes = {
+ items: PropTypes.arrayOf(PropTypes.any).isRequired,
+ linkMore: PropTypes.any,
+ isEditMode: PropTypes.bool,
+};
+
+export default AdvancedListingBlockTemplate;
diff --git a/src/advancedSchema.js b/src/advancedSchema.js
new file mode 100644
index 0000000..e739b26
--- /dev/null
+++ b/src/advancedSchema.js
@@ -0,0 +1,84 @@
+import React from 'react';
+import messages from './messages';
+
+export const advancedSchema = (props) => {
+ const { intl, schema } = props;
+
+ return {
+ ...schema,
+ fieldsets: [
+ {
+ id: 'default',
+ title: 'Default',
+ fields: ['variation'],
+ },
+ {
+ id: 'querystring',
+ title: intl.formatMessage(messages.querystring),
+ fields: ['querystring'],
+ },
+ {
+ 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'],
+ },
+ ],
+ properties: {
+ ...schema.properties,
+ howManyColumns: {
+ title: intl.formatMessage(messages.columnsCountConfiguration),
+ choices: [
+ [1, '1'],
+ [2, '2'],
+ [3, '3'],
+ [4, '4'],
+ ],
+ },
+ imageWidth: {
+ title: intl.formatMessage(messages.imageWidthConfiguration),
+ description: intl.formatMessage(
+ messages.imageWidthConfigurationDescription,
+ ),
+ choices: [
+ [2, '2/12'],
+ [3, '3/12'],
+ [4, '4/12'],
+ [5, '5/12'],
+ [6, '6/12'],
+ ],
+ },
+ imageSide: {
+ title: intl.formatMessage(messages.imagePositionConfiguration),
+ description: intl.formatMessage(
+ messages.imagePositionConfigurationDescription,
+ ),
+ choices: [
+ [null, 'No image'],
+ ['right', 'right'],
+ ['left', 'left'],
+ ],
+ },
+ titleTag: {
+ title: intl.formatMessage(messages.titleTagConfiguration),
+ description: intl.formatMessage(
+ messages.titleTagConfigurationDescription,
+ ),
+ choices: [
+ [(children) => {children}
, 'H2'],
+ [(children) => {children}
, 'H3'],
+ [(children) => {children}
, 'H4'],
+ ],
+ },
+ },
+ };
+};
diff --git a/src/index.js b/src/index.js
new file mode 100644
index 0000000..2b7763a
--- /dev/null
+++ b/src/index.js
@@ -0,0 +1,17 @@
+import AdvancedListingBlockTemplate from './AdvancedListingBlockTemplate';
+import { advancedSchema } from './advancedSchema';
+
+const applyConfig = (config) => {
+ config.blocks.blocksConfig.listing.variations = [
+ ...config.blocks.blocksConfig.listing.variations,
+ {
+ id: 'advanced',
+ title: 'Advanced',
+ template: AdvancedListingBlockTemplate,
+ schemaEnhancer: advancedSchema,
+ },
+ ];
+ return config;
+};
+
+export default applyConfig;
diff --git a/src/messages.js b/src/messages.js
new file mode 100644
index 0000000..c33754f
--- /dev/null
+++ b/src/messages.js
@@ -0,0 +1,49 @@
+import { defineMessages } from 'react-intl';
+const messages = defineMessages({
+ querystring: {
+ id: 'Query',
+ defaultMessage: 'Query',
+ },
+ columnsConfiguration: {
+ id: 'Columns configuration',
+ defaultMessage: 'Columns configuration',
+ },
+ columnsCountConfiguration: {
+ id: 'How many columns:',
+ defaultMessage: 'How many columns:',
+ },
+ imageConfiguration: {
+ id: 'Image position/size',
+ defaultMessage: 'Image position/size',
+ },
+ imageWidthConfiguration: {
+ id: 'Image width (x/12):',
+ defaultMessage: 'Image width (x/12):',
+ },
+ imageWidthConfigurationDescription: {
+ id: 'Default image width will be 2/12',
+ defaultMessage: 'Default image width will be 2/12',
+ },
+ imagePositionConfiguration: {
+ id: 'Image position:',
+ defaultMessage: 'Image position:',
+ },
+ imagePositionConfigurationDescription: {
+ id: 'Default with no image',
+ defaultMessage: 'Default with no image',
+ },
+ titleConfiguration: {
+ id: 'Title configuration',
+ defaultMessage: 'Title configuration',
+ },
+ titleTagConfiguration: {
+ id: 'Title text HTML tag',
+ defaultMessage: 'Title text HTML tag',
+ },
+ titleTagConfigurationDescription: {
+ id: 'Default HTML tag will be H3',
+ defaultMessage: 'Default HTML tag will be H3',
+ },
+});
+
+export default messages;