diff --git a/src/components/manage/Blocks/ImageCards/View.jsx b/src/components/manage/Blocks/ImageCards/View.jsx
new file mode 100644
index 0000000..3adbb2c
--- /dev/null
+++ b/src/components/manage/Blocks/ImageCards/View.jsx
@@ -0,0 +1,195 @@
+import React from 'react';
+import cx from 'classnames';
+import config from '@plone/volto/registry';
+import DefaultImageSVG from '@plone/volto/components/manage/Blocks/Listing/default-image.svg';
+import { Card, Message } from 'semantic-ui-react';
+import { serializeNodes } from 'volto-slate/editor/render';
+import { compose } from 'redux';
+import { flattenToAppURL } from '@plone/volto/helpers';
+import { withRouter } from 'react-router-dom';
+import { injectIntl } from 'react-intl';
+
+import './styles.less';
+
+const alignmentTypes = {
+ left: 'left',
+ right: 'right',
+ center: 'centered',
+ full: 'left',
+};
+
+export const getScaleUrl = (url, size) =>
+ (url || '').includes(config.settings.apiPath)
+ ? `${flattenToAppURL(url.replace('/api', ''))}/@@images/image/${size}`
+ : `${url.replace('/api', '')}/@@images/image/${size}`;
+
+const Cards = (props) => {
+ const { data, editable, history } = props;
+ const {
+ align,
+ cards,
+ image_scale,
+ gridSize = 'one',
+ theme = 'default',
+ } = data;
+
+ const makeImage = (item) => {
+ const { attachedimage } = item;
+ return (
+
+ );
+ };
+
+ const makeTextBody = (item) => (
+ <>
+ {/*
+ {item.title ? item.title : item.id}
+ {item.meta && {serializeNodes(item.meta)}}
+ {item.text && (
+ {serializeNodes(item.text)}
+ )}
+
+ {item.link && (
+
+
+
+ {item.linkTitle || item.link}
+
+
+ )} */}
+
+ {item.title ? item.title : item.id}
+
+ {item.text && (
+ {serializeNodes(item.text)}
+ )}
+ >
+ );
+
+ const handleNavigate = (link) => {
+ history.push(flattenToAppURL(link));
+ };
+
+ return cards && cards.length > 0 ? (
+
+ {cards.map((item) => (
+ handleNavigate(item.link)}
+ key={item['@id']}
+ className={cx(
+ 'navigation-card',
+ alignmentTypes[align] || 'left',
+ theme,
+ )}
+ >
+ {makeImage(item)}
+ {makeTextBody(item)}
+
+ ))}
+
+ ) : (
+ <>{editable ? No image cards : ''}>
+ );
+};
+
+Cards.schema = () => ({
+ title: 'Image Card',
+ fieldsets: [
+ {
+ id: 'default',
+ title: 'Default',
+ fields: [
+ 'title',
+ 'meta',
+ 'text',
+ 'attachedimage',
+ 'link',
+ 'linkTitle',
+ 'copyright',
+ ],
+ },
+ ],
+
+ properties: {
+ title: {
+ type: 'string',
+ title: 'Title',
+ },
+ meta: {
+ widget: 'slate_richtext',
+ title: 'Meta data',
+ },
+ text: {
+ widget: 'slate_richtext',
+ title: 'Text',
+ },
+ link: {
+ widget: 'url',
+ title: 'Link',
+ },
+ linkTitle: {
+ type: 'string',
+ title: 'Link title',
+ },
+ attachedimage: {
+ widget: 'attachedimage',
+ title: 'Image',
+ },
+ copyright: {
+ widget: 'slate_richtext',
+ title: 'Copyright',
+ },
+ },
+
+ required: ['attachedimage'],
+});
+
+Cards.schemaExtender = (schema) => {
+ return {
+ ...schema,
+ fieldsets: [
+ ...schema.fieldsets,
+ {
+ id: 'cards_grid',
+ title: 'Cards grid',
+ fields: ['gridSize', 'theme'],
+ },
+ ],
+ properties: {
+ ...schema.properties,
+ gridSize: {
+ title: 'Grid Size',
+ choices: [
+ ['one', 'One'],
+ ['two', 'Two'],
+ ['three', 'Three'],
+ ['four', 'Four'],
+ ],
+ factory: 'Choice',
+ type: 'string',
+ },
+ theme: {
+ title: 'Theme',
+ choices: [
+ ['default', 'Default'],
+ ['primary', 'Primary'],
+ ['secondary', 'Secondary'],
+ ['tertiary', 'Tertiary'],
+ ],
+ },
+ },
+ };
+};
+
+export default compose(withRouter, injectIntl)(Cards);
diff --git a/src/components/manage/Blocks/ImageCards/index.js b/src/components/manage/Blocks/ImageCards/index.js
new file mode 100644
index 0000000..de2061b
--- /dev/null
+++ b/src/components/manage/Blocks/ImageCards/index.js
@@ -0,0 +1,17 @@
+import Cards from './View';
+
+export default (config) => {
+ config.blocks.blocksConfig.imagecards = {
+ ...config.blocks.blocksConfig.imagecards,
+ blockRenderers: {
+ ...config.blocks.blocksConfig.imagecards.blockRenderers,
+ fise_cards_grid: {
+ title: 'FISE cards grid',
+ view: Cards,
+ schema: Cards.schema,
+ schemaExtender: Cards.schemaExtender,
+ },
+ },
+ };
+ return config;
+};
diff --git a/src/components/manage/Blocks/ImageCards/styles.less b/src/components/manage/Blocks/ImageCards/styles.less
new file mode 100644
index 0000000..595a1e9
--- /dev/null
+++ b/src/components/manage/Blocks/ImageCards/styles.less
@@ -0,0 +1,31 @@
+.cards-tile-image {
+ height: 250px;
+ object-fit: cover;
+}
+
+.navigation-card {
+ border: none !important;
+ box-shadow: none !important;
+}
+
+.tile-listing-title {
+ margin: 10px 0 !important;
+ font-weight: bold;
+
+ p {
+ color: #564535;
+ font-size: 20px;
+ margin: 0 !important;
+ }
+}
+
+.tile-listing-title:hover {
+ p {
+ color: #cc4400;
+ }
+}
+
+.tile-listing-description {
+ font-size: 14px;
+ color: #666;
+}
diff --git a/src/index.js b/src/index.js
index ef75854..3ef2bfd 100644
--- a/src/index.js
+++ b/src/index.js
@@ -6,6 +6,7 @@ import installAppExtras from '@eeacms/volto-forests-theme/components/theme/AppEx
import { applyConfig as installFiseFrontend } from './localconfig';
import installDiscodataConnectorBlock from '@eeacms/volto-forests-theme/components/manage/Blocks/DiscodataConnectorBlock';
import installExpandableDataTable from './components/manage/Blocks/SimpleDataTable';
+import installImageCards from './components/manage/Blocks/ImageCards';
import ObjectListInlineWidget from './components/manage/Widgets/ObjectListInlineWidget';
import reducers from '@eeacms/volto-forests-theme/reducers';
@@ -19,6 +20,7 @@ export default function applyConfig(config) {
installFiseFrontend,
installDiscodataConnectorBlock,
installExpandableDataTable,
+ installImageCards,
].reduce((acc, apply) => apply(acc), config);
config.settings = {