diff --git a/src/actions/index.js b/src/actions/index.js
index f8575724..101af985 100644
--- a/src/actions/index.js
+++ b/src/actions/index.js
@@ -14,6 +14,7 @@ import {
SET_SECTION_TABS,
GET_PARENT_FOLDER_DATA,
GET_PAGE,
+ GET_SPARQL_DATA,
} from '~/constants/ActionTypes';
export function setSectionTabs(payload) {
@@ -43,3 +44,14 @@ export function getPage(url) {
},
};
}
+
+export function getSparqlData(path) {
+ return {
+ type: GET_SPARQL_DATA,
+ path,
+ request: {
+ op: 'get',
+ path: `${path}/@sparql-data`,
+ },
+ };
+}
diff --git a/src/components/manage/Blocks/ArticlesSparql/Edit.jsx b/src/components/manage/Blocks/ArticlesSparql/Edit.jsx
new file mode 100644
index 00000000..e2400883
--- /dev/null
+++ b/src/components/manage/Blocks/ArticlesSparql/Edit.jsx
@@ -0,0 +1,40 @@
+/**
+ * Edit map block.
+ * @module components/manage/Blocks/Maps/Edit
+ */
+import React, { useState } from 'react';
+import InlineForm from '@plone/volto/components/manage/Form/InlineForm';
+import { SidebarPortal } from '@plone/volto/components';
+import View from './View';
+import getSchema from './schema';
+
+const Edit = (props) => {
+ const [state, setState] = useState({
+ schema: getSchema(props),
+ });
+
+ const handleChangeBlock = (id, value) => {
+ const { data } = props;
+ props.onChangeBlock(props.block, {
+ ...data,
+ [id]: value,
+ });
+ };
+
+ return (
+
+
+
+
+
+
+ );
+};
+
+export default Edit;
diff --git a/src/components/manage/Blocks/ArticlesSparql/View.jsx b/src/components/manage/Blocks/ArticlesSparql/View.jsx
new file mode 100644
index 00000000..fe9f8cdc
--- /dev/null
+++ b/src/components/manage/Blocks/ArticlesSparql/View.jsx
@@ -0,0 +1,145 @@
+import React, { useState, useEffect } from 'react';
+import { compose } from 'redux';
+import { connect } from 'react-redux';
+import Icon from '@plone/volto/components/theme/Icon/Icon';
+import { Link } from 'react-router-dom';
+import { getSparqlData } from '~/actions';
+import { Image } from 'semantic-ui-react';
+import moment from 'moment';
+import cx from 'classnames';
+import downSVG from '@plone/volto/icons/down.svg';
+import upSVG from '@plone/volto/icons/up.svg';
+import placeholderImage from './placeholder.png';
+import './style.css';
+
+const View = (props) => {
+ const [activeItem, setActiveItem] = useState(1);
+ const { page = '/', redirectPage = null, preview = false } = props.data || {};
+ const items = props.sparql_data[page]?.items || [];
+
+ useEffect(() => {
+ if (!props.sparql_data[page]) {
+ props.getSparqlData(page);
+ }
+ /* eslint-disable-next-line */
+ }, []);
+
+ const isVisible = (index) => {
+ if (!preview) return true;
+ if (activeItem === 0) {
+ return index < 3;
+ } else {
+ return Math.abs(index - activeItem) < 2;
+ }
+ };
+
+ return (
+
+ {props.mode === 'edit' && !props.data.page ? (
+
Select SPARQL data from sidebar
+ ) : (
+ ''
+ )}
+ {props.mode === 'edit' && props.data.page && !items.length ? (
+
There is no SPARQL data
+ ) : (
+ ''
+ )}
+ {items.length ? (
+
+ {items.map((item, index) =>
+ isVisible(index) ? (
+
+
+
+
+
+
+
{item.title}
+
+
+
+ {moment(item.time).format('DD MMM YYYY')}
+
+
+
+
+
+
+ ) : (
+ ''
+ ),
+ )}
+
+ ) : (
+ ''
+ )}
+ {preview && redirectPage && items.length ? (
+
+ READ MORE
+
+ ) : (
+ ''
+ )}
+ {/* {items.length > 2 ? (
+
+ {activeItem > 1 ? (
+ {
+ setActiveItem(activeItem - 1);
+ }}
+ name={upSVG}
+ size="24px"
+ />
+ ) : (
+ ''
+ )}
+ {activeItem < items.length - 1 ? (
+ {
+ setActiveItem(activeItem + 1);
+ }}
+ name={downSVG}
+ size="24px"
+ />
+ ) : (
+ ''
+ )}
+
+ ) : (
+ ''
+ )} */}
+
+ );
+};
+
+export default compose(
+ connect(
+ (state, props) => ({
+ sparql_data: state.sparql.items,
+ }),
+ { getSparqlData },
+ ),
+)(View);
diff --git a/src/components/manage/Blocks/ArticlesSparql/placeholder.png b/src/components/manage/Blocks/ArticlesSparql/placeholder.png
new file mode 100644
index 00000000..bf1d3104
Binary files /dev/null and b/src/components/manage/Blocks/ArticlesSparql/placeholder.png differ
diff --git a/src/components/manage/Blocks/ArticlesSparql/schema.jsx b/src/components/manage/Blocks/ArticlesSparql/schema.jsx
new file mode 100644
index 00000000..1e181367
--- /dev/null
+++ b/src/components/manage/Blocks/ArticlesSparql/schema.jsx
@@ -0,0 +1,33 @@
+export const getSchema = (props) => {
+ return {
+ title: 'Detailed Link',
+
+ fieldsets: [
+ {
+ id: 'default',
+ title: 'Default',
+ fields: ['page', 'preview', 'redirectPage'],
+ },
+ ],
+
+ properties: {
+ page: {
+ title: 'Page',
+ widget: 'object_by_path',
+ },
+ preview: {
+ title: 'Preview',
+ type: 'boolean',
+ },
+ redirectPage: {
+ title: 'Redirect page',
+ widget: 'object_by_path',
+ description: 'Applies if preview is selected',
+ },
+ },
+
+ required: ['page'],
+ };
+};
+
+export default getSchema;
diff --git a/src/components/manage/Blocks/ArticlesSparql/style.css b/src/components/manage/Blocks/ArticlesSparql/style.css
new file mode 100644
index 00000000..5a1b64f7
--- /dev/null
+++ b/src/components/manage/Blocks/ArticlesSparql/style.css
@@ -0,0 +1,80 @@
+.articles-sparql {
+ position: relative;
+}
+
+.articles .articles-row {
+ align-items: center;
+ height: 250px;
+ justify-content: center;
+}
+
+.articles .article {
+ display: block;
+}
+
+.articles .articles-row.can-be-half:last-child {
+ -webkit-mask-image: -webkit-gradient(linear, left top,
+ left bottom, from(rgba(0,0,0,1)), to(rgba(0,0,0,0)));
+}
+.articles .articles-row.can-be-half:last-child .article {
+ height: 50%;
+ overflow: hidden;
+ -webkit-mask-image: -webkit-gradient(linear, left top,
+ left bottom, from(rgba(0,0,0,1)), to(rgba(0,0,0,0)));
+}
+
+.articles .article.hero img {
+ border-radius: 2em;
+}
+
+.articles .article-header,
+.articles .article-description {
+ display: block;
+ position: relative;
+}
+
+.articles .article-header h3 {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ -webkit-line-clamp: 1;
+ line-height: 1.5em;
+ max-height: 1.5em;
+}
+
+.articles .article-description p {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ -webkit-line-clamp: 3;
+ line-height: 1.5em;
+ max-height: 4.5em;
+}
+
+.articles-slideshow {
+ position: absolute;
+ display: flex;
+ flex-direction: column;
+ top: 50%;
+ right: 1em;
+ transform: translateY(-50%);
+}
+
+.articles-slideshow .icon {
+ cursor: pointer;
+}
+
+.articles-redirect {
+ position: absolute;
+ bottom: 7em;
+ left: 50%;
+ transform: translateX(-50%);
+}
+
+@media (min-width: 500px) and (max-width: 768px) {
+ .sm-height-fit-content {
+ height: fit-content !important;
+ }
+}
\ No newline at end of file
diff --git a/src/components/manage/Blocks/DiscodataOpenlayersMapBlock/View.jsx b/src/components/manage/Blocks/DiscodataOpenlayersMapBlock/View.jsx
index d3762dee..7290e8c4 100644
--- a/src/components/manage/Blocks/DiscodataOpenlayersMapBlock/View.jsx
+++ b/src/components/manage/Blocks/DiscodataOpenlayersMapBlock/View.jsx
@@ -502,10 +502,6 @@ const OpenlayersMapView = (props) => {
callback: function () {},
},
);
- setTimeout(() => {
- stateRef?.current?.map?.sitesSourceLayer &&
- stateRef.current.map.sitesSourceLayer.getSource().refresh();
- }, options.duration + 100);
}
})
.catch((error) => {});
@@ -532,10 +528,6 @@ const OpenlayersMapView = (props) => {
zoom: 15,
});
}
- setTimeout(() => {
- stateRef?.current?.map?.sitesSourceLayer &&
- stateRef.current.map.sitesSourceLayer.getSource().refresh();
- }, 1100);
})
.catch((error) => {});
}
@@ -896,7 +888,7 @@ const OpenlayersMapView = (props) => {
});
}
- map.once('postrender', function(event) {
+ map.once('postrender', function (event) {
sitesSourceLayer.getSource().refresh();
});
diff --git a/src/components/manage/Blocks/FiltersBlock/View.jsx b/src/components/manage/Blocks/FiltersBlock/View.jsx
index 0da3f5fc..b794a5e5 100644
--- a/src/components/manage/Blocks/FiltersBlock/View.jsx
+++ b/src/components/manage/Blocks/FiltersBlock/View.jsx
@@ -27,7 +27,6 @@ import circleMinus from '@plone/volto/icons/circle-minus.svg';
import clear from '@plone/volto/icons/clear.svg';
import './style.css';
-let nrOfRequests = 0;
const makeUrl = (providerUrl, url) => {
return encodeURI(providerUrl + `?query=${url}`);
};
@@ -41,6 +40,7 @@ const keyCodes = {
const View = ({ content, ...props }) => {
const providerUrl = settings.providerUrl;
const [state, setState] = useState({
+ id: _uniqueId('block_'),
open: false,
filters: {},
filtersMeta: {},
@@ -59,7 +59,6 @@ const View = ({ content, ...props }) => {
'permit_years',
],
factsDataOrder: ['Country_quick_facts', 'EU_quick_facts'],
- mounted: false,
firstLoad: false,
});
const [filtersMetaReady, setFiltersMetaReady] = useState(false);
@@ -74,9 +73,11 @@ const View = ({ content, ...props }) => {
const [triggerSearch, setTriggerSearch] = useState(false);
const [quickFactsListener, setQuickFactsListener] = useState(false);
const [sidebar, setSidebar] = useState(false);
+ const [mountState, setMountState] = useState(false);
const alphaFeatureRef = useRef({});
const searchContainerModal = useRef(null);
const searchContainer = useRef(null);
+ const mounted = useRef(false);
const modalButtonTitle = props.data.modalButtonTitle?.value;
const locationResultsTexts = locationResults.map((result) => result.text);
const mapSidebarExists = document?.getElementById('map-sidebar');
@@ -187,26 +188,24 @@ const View = ({ content, ...props }) => {
}
useEffect(function () {
- setState({ ...state, mounted: true });
+ mounted.current = true;
+ setMountState(true);
updateFactsData(true);
- setState({
- ...state,
- mounted: true,
- });
return () => {
if (quickFactsListener && document.getElementById(`dynamic-filter`)) {
document
.getElementById(`dynamic-filter`)
.removeEventListener('featurechange', onFeaturechange);
}
- setState({ ...state, mounted: false });
+ mounted.current = false;
+ setMountState(false);
};
/* eslint-disable-next-line */
}, []);
useEffect(() => {
alphaFeatureRef.current = alphaFeature;
- if (state.mounted) {
+ if (mountState) {
updateFactsData(false);
}
/* eslint-disable-next-line */
@@ -238,14 +237,14 @@ const View = ({ content, ...props }) => {
}, [state]);
useEffect(() => {
- if (typeof updateFilters === 'function') {
+ if (mountState) {
updateFilters();
- }
- if (Object.keys(state.filtersMeta).length && !filtersMetaReady) {
- setFiltersMetaReady(true);
+ if (Object.keys(state.filtersMeta).length && !filtersMetaReady) {
+ setFiltersMetaReady(true);
+ }
}
/* eslint-disable-next-line */
- }, [JSON.stringify(state.filters), JSON.stringify(state.filtersMeta)])
+ }, [JSON.stringify(state.filtersMeta)])
useEffect(() => {
if (
@@ -259,7 +258,7 @@ const View = ({ content, ...props }) => {
}, [filtersMetaReady])
useEffect(() => {
- if (state.mounted && __CLIENT__) {
+ if (mountState && __CLIENT__) {
let promises = [];
let metadata = [];
const siteCountryFilters =
@@ -559,7 +558,7 @@ const View = ({ content, ...props }) => {
}
Promise.all(promises)
.then((response) => {
- if (state.mounted) {
+ if (mounted.current) {
const filtersMeta = {
...state.filtersMeta,
};
@@ -569,7 +568,6 @@ const View = ({ content, ...props }) => {
}
});
response.forEach((res, index) => {
- nrOfRequests++;
const results = JSON.parse(res.request.response).results;
let filteringInputs = [];
if (state.filtersMeta[metadata[index]?.key]?.filteringInputs) {
@@ -613,14 +611,14 @@ const View = ({ content, ...props }) => {
}
const queries =
props.discodata_query.search[metadata[index].queryToSet] || [];
- const filteringInptsByQuery =
- queries.length > 1
- ? queries.map((query, index) => ({
- id: _uniqueId('select_'),
- type: 'select',
- position: index,
- }))
- : [metadata[index]?.firstInput];
+ let filteringInptsByQuery = [metadata[index]?.firstInput];
+ if (Array.isArray(queries) && queries.length > 1) {
+ filteringInptsByQuery = queries.map((query, index) => ({
+ id: _uniqueId('select_'),
+ type: 'select',
+ position: index,
+ }));
+ }
filtersMeta[metadata[index]?.key] = {
filteringInputs: filteringInputs.length
? filteringInputs
@@ -650,6 +648,7 @@ const View = ({ content, ...props }) => {
...(state.firstLoad === false ? { firstLoad: true } : {}),
});
}
+ return;
})
.catch((error) => {
setLoadingData(false);
@@ -661,7 +660,7 @@ const View = ({ content, ...props }) => {
}
/* eslint-disable-next-line */
}, [
- state.mounted,
+ mountState,
state.filters?.EEAActivity && JSON.stringify(state.filters.EEAActivity),
state.filters?.siteCountry && JSON.stringify(state.filters.siteCountry),
state.filters?.region && JSON.stringify(state.filters.region),
@@ -754,7 +753,7 @@ const View = ({ content, ...props }) => {
}
});
queryParamKeys.forEach((key, keyIndex) => {
- if (props.discodata_query.search[key]) {
+ if (Array.isArray(props.discodata_query.search[key])) {
newFilters[key] = props.discodata_query.search[key];
props.discodata_query.search[key].forEach((param, index) => {
if (
diff --git a/src/constants/ActionTypes.js b/src/constants/ActionTypes.js
index 8bfa1a23..49c1c6d0 100644
--- a/src/constants/ActionTypes.js
+++ b/src/constants/ActionTypes.js
@@ -8,3 +8,4 @@ export const SET_SECTION_TABS = 'SET_SECTION_TABS';
export const GET_PARENT_FOLDER_DATA = 'GET_PARENT_FOLDER_DATA';
export const GET_NAV_ITEMS = 'GET_NAV_ITEMS';
export const GET_PAGE = 'GET_PAGE';
+export const GET_SPARQL_DATA = 'GET_SPARQL_DATA';
diff --git a/src/localconfig.js b/src/localconfig.js
index d4d8228e..2a26dc54 100644
--- a/src/localconfig.js
+++ b/src/localconfig.js
@@ -7,6 +7,9 @@ import RedirectView from '~/components/theme/View/RedirectView';
import DetailedLinkView from '~/components/manage/Blocks/DetailedLink/View';
import DetailedLinkEdit from '~/components/manage/Blocks/DetailedLink/Edit';
+import ArticlesSparqlView from '~/components/manage/Blocks/ArticlesSparql/View';
+import ArticlesSparqlEdit from '~/components/manage/Blocks/ArticlesSparql/Edit';
+
import FolderContentsBlockView from '~/components/manage/Blocks/FolderContentsBlock/View';
import FolderContentsBlockEdit from '~/components/manage/Blocks/FolderContentsBlock/Edit';
@@ -120,6 +123,15 @@ export function applyConfig(voltoConfig) {
icon: listSVG,
};
+ config.blocks.blocksConfig.articles_sparql = {
+ id: 'articles_sparql',
+ title: 'Articles sparql',
+ group: 'eprtr_blocks',
+ view: ArticlesSparqlView,
+ edit: ArticlesSparqlEdit,
+ icon: listSVG,
+ };
+
config.blocks.blocksConfig.detailed_link = {
id: 'detailed_link',
title: 'Detailed Link',
diff --git a/src/reducers/index.js b/src/reducers/index.js
index d4d4f8e2..39e2f1ce 100644
--- a/src/reducers/index.js
+++ b/src/reducers/index.js
@@ -7,6 +7,7 @@ import defaultReducers from '@plone/volto/reducers';
import section_tabs from './section_tabs';
import parent_folder_data from './parent_folder_data';
import pages from './pages';
+import sparql from './sparql';
/**
* Root reducer.
* @function
@@ -18,6 +19,7 @@ const reducers = {
section_tabs,
parent_folder_data,
pages,
+ sparql,
...defaultReducers,
// Add your reducers here
};
diff --git a/src/reducers/sparql.js b/src/reducers/sparql.js
new file mode 100644
index 00000000..3bd878e2
--- /dev/null
+++ b/src/reducers/sparql.js
@@ -0,0 +1,42 @@
+import { GET_SPARQL_DATA } from '~/constants/ActionTypes';
+
+const initialState = {
+ error: null,
+ items: {},
+ loaded: false,
+ loading: false,
+};
+
+export default function pages(state = initialState, action = {}) {
+ switch (action.type) {
+ case `${GET_SPARQL_DATA}_PENDING`:
+ return {
+ ...state,
+ error: null,
+ loaded: false,
+ loading: true,
+ };
+ case `${GET_SPARQL_DATA}_SUCCESS`:
+ const items = {
+ ...state.items,
+ };
+ items[action.path] = action.result;
+ return {
+ ...state,
+ error: null,
+ items,
+ loaded: true,
+ loading: false,
+ };
+ case `${GET_SPARQL_DATA}_FAIL`:
+ return {
+ ...state,
+ error: action.error,
+ items: {},
+ loaded: false,
+ loading: false,
+ };
+ default:
+ return state;
+ }
+}