diff --git a/src/components/manage/Blocks/FiltersBlock/Search.js b/src/components/manage/Blocks/FiltersBlock/Search.js
index 7433ff1..7185a1c 100644
--- a/src/components/manage/Blocks/FiltersBlock/Search.js
+++ b/src/components/manage/Blocks/FiltersBlock/Search.js
@@ -24,10 +24,10 @@ const getSites = (value) => {
const db_version =
process.env.RAZZLE_DB_VERSION || config.settings.db_version || 'latest';
const query = `SELECT siteName
- FROM [IED].[${db_version}].[SiteMap]
- WHERE [siteName] COLLATE Latin1_General_CI_AI LIKE '%${value}%'
- GROUP BY siteName
- ORDER BY [siteName]`;
+ FROM [IED].[${db_version}].[SiteMap]
+ WHERE [siteName] COLLATE Latin1_General_CI_AI LIKE '%${value}%'
+ GROUP BY siteName
+ ORDER BY [siteName]`;
return axios.get(
providerUrl + `?${getEncodedQueryString(query)}&p=1&nrOfHits=6`,
@@ -43,11 +43,27 @@ const getLocations = (value, providers_data) => {
);
};
+const getFacilities = (value) => {
+ const providerUrl = config.settings.providerUrl;
+ const db_version =
+ process.env.RAZZLE_DB_VERSION || config.settings.db_version || 'latest';
+ const query = `SELECT facilityName
+ FROM [IED].[${db_version}].[ProductionFacility]
+ WHERE [facilityName] COLLATE Latin1_General_CI_AI LIKE '%${value}%'
+ GROUP BY facilityName
+ ORDER BY [facilityName]`;
+
+ return axios.get(
+ providerUrl + `?${getEncodedQueryString(query)}&p=1&nrOfHits=6`,
+ );
+};
+
const Search = ({ data, providers_data, query, setQuery, ...props }) => {
const searchContainer = React.useRef();
const [loading, setLoading] = React.useState(false);
const [showResults, setShowResults] = React.useState(false);
const [sites, setSites] = React.useState([]);
+ const [facilities, setFacilities] = React.useState([]);
const [locations, setLocations] = React.useState([]);
const value = React.useMemo(() => {
@@ -69,18 +85,65 @@ const Search = ({ data, providers_data, query, setQuery, ...props }) => {
const items = React.useMemo(() => {
if (loading) return [];
- const half = MAX_RESULTS / 2;
- let _locations = locations.slice(0, half);
- let _sites = sites.slice(0, half);
- if (_locations.length < half) {
- _sites = sites.slice(0, MAX_RESULTS - _locations.length);
+ const slices = MAX_RESULTS / 3;
+ let total_entities = 1;
+ let empty_slices = 0;
+ let entities = 0;
+ let _locations = locations.slice(0, slices);
+ let _sites = sites.slice(0, slices);
+ let _facilities = facilities.slice(0, slices);
+
+ if (_locations.length < slices) {
+ empty_slices += slices - _locations.length;
+ entities++;
+ } else if (_locations.length <= slices) {
+ total_entities++;
}
- if (_sites.length < half) {
- _locations = locations.slice(0, MAX_RESULTS - _sites.length);
+ if (_sites.length < slices) {
+ empty_slices += slices - _sites.length;
+ entities++;
+ } else if (_sites.length <= slices) {
+ total_entities++;
+ }
+ if (_facilities.length < slices) {
+ empty_slices += slices - _facilities.length;
+ entities++;
+ } else if (_facilities.length <= slices) {
+ total_entities++;
+ }
+
+ if (locations.length > slices && empty_slices > 0) {
+ const used_slices = Math.round(
+ empty_slices / (total_entities - entities),
+ );
+ _locations = locations.slice(0, slices + used_slices);
+ empty_slices -= used_slices;
+ } else {
+ total_entities--;
+ }
+
+ if (sites.length > slices && empty_slices > 0) {
+ const used_slices = Math.round(
+ empty_slices / (total_entities - entities),
+ );
+ _sites = sites.slice(0, slices + used_slices);
+ empty_slices -= used_slices;
+ } else {
+ total_entities--;
}
- return [..._locations, ..._sites];
- }, [sites, locations, loading]);
+ if (facilities.length > slices && empty_slices > 0) {
+ const used_slices = Math.round(
+ empty_slices / (total_entities - entities),
+ );
+ _facilities = facilities.slice(0, slices + used_slices);
+ empty_slices -= used_slices;
+ } else {
+ total_entities--;
+ }
+
+ return [..._locations, ..._sites, ..._facilities];
+ }, [sites, facilities, locations, loading]);
const handleClickOutside = React.useCallback((event) => {
if (!doesNodeContainClick(searchContainer.current, event)) {
@@ -96,6 +159,7 @@ const Search = ({ data, providers_data, query, setQuery, ...props }) => {
const requests = [];
if (value.length >= 3) {
requests.push(getSites(value));
+ requests.push(getFacilities(value));
requests.push(getLocations(value, providers_data));
Promise.all(requests).then((responses) => {
@@ -105,17 +169,24 @@ const Search = ({ data, providers_data, query, setQuery, ...props }) => {
type: 'site',
})) || [],
);
+ setFacilities(
+ responses[1].data?.results?.map((item) => ({
+ text: item.facilityName,
+ type: 'facility',
+ })) || [],
+ );
setLocations(
- responses[1].data?.suggestions?.map((item) => ({
+ responses[2].data?.suggestions?.map((item) => ({
...item,
type: 'location',
})) || [],
);
+ setLoading(false);
});
- setLoading(false);
} else {
setLoading(false);
setSites([]);
+ setFacilities([]);
setLocations([]);
}
},
diff --git a/src/components/manage/Blocks/IndustryDataTable/View.jsx b/src/components/manage/Blocks/IndustryDataTable/View.jsx
index 8114957..8ba3544 100644
--- a/src/components/manage/Blocks/IndustryDataTable/View.jsx
+++ b/src/components/manage/Blocks/IndustryDataTable/View.jsx
@@ -177,6 +177,7 @@ const getConditions = (query) => {
};
const View = (props) => {
+ const table = React.useRef();
const context = React.useContext(ConnectorContext);
const [openedRow, setOpenedRow] = React.useState(null);
const {
@@ -218,7 +219,7 @@ const View = (props) => {
}, [JSON.stringify(query)]);
return (
-
+
{row_size && tableData ? (
{
{
if (pagination.activePage > 1) {
updatePagination({
@@ -469,7 +472,7 @@ const View = (props) => {
{
as="a"
icon
disabled={
- props.isPending ||
+ props.loadingProviderData ||
pagination.activePage === pagination.lastPage
}
onClick={() => {
diff --git a/src/components/manage/Blocks/IndustryMap/View.jsx b/src/components/manage/Blocks/IndustryMap/View.jsx
index 94ddfb2..ddf39b4 100644
--- a/src/components/manage/Blocks/IndustryMap/View.jsx
+++ b/src/components/manage/Blocks/IndustryMap/View.jsx
@@ -25,6 +25,7 @@ import {
getLayerBaseURL,
getLocationExtent,
getSiteExtent,
+ getFacilityExtent,
getCountriesExtent,
getWhereStatement,
} from './index';
@@ -197,6 +198,31 @@ class View extends React.PureComponent {
});
}
});
+ } else if (filter_change.type === 'search-facility') {
+ getFacilityExtent(filter_search).then(({ data }) => {
+ const extent = data?.results?.[0] || {};
+ if (
+ extent.MIN_X === null ||
+ extent.MIN_Y === null ||
+ extent.MAX_X === null ||
+ extent.MAX_Y === null
+ ) {
+ toast.warn(
+ ,
+ );
+ } else {
+ this.map.current
+ .getView()
+ .fit([extent.MIN_X, extent.MIN_Y, extent.MAX_X, extent.MAX_Y], {
+ maxZoom: 16,
+ duration: 1000,
+ });
+ }
+ });
} else if (
(filter_change.type === 'advanced-filter' ||
filter_change.type === 'simple-filter') &&
diff --git a/src/components/manage/Blocks/IndustryMap/index.js b/src/components/manage/Blocks/IndustryMap/index.js
index 1618df6..234e79e 100644
--- a/src/components/manage/Blocks/IndustryMap/index.js
+++ b/src/components/manage/Blocks/IndustryMap/index.js
@@ -192,13 +192,31 @@ export const getSiteExtent = (data) => {
MAX(shape_wm.STX) AS MAX_X,
MAX(shape_wm.STY) AS MAX_Y
FROM [IED].[${db_version}].[SiteMap]
- WHERE [siteName] COLLATE Latin1_General_CI_AI LIKE '%${data.text.replace(
+ WHERE [siteName] COLLATE Latin1_General_CI_AI LIKE '%${data.text.replaceAll(
"'",
"''",
)}%'`)}`,
);
};
+export const getFacilityExtent = (data) => {
+ const db_version =
+ process.env.RAZZLE_DB_VERSION || config.settings.db_version || 'latest';
+
+ let text = data.text.replaceAll('\n', '');
+ text = text.replaceAll("'", "''");
+
+ return axios.get(
+ `${config.settings.providerUrl}?${getEncodedQueryString(`SELECT
+ MIN(shape_wm.STX) AS MIN_X,
+ MIN(shape_wm.STY) AS MIN_Y,
+ MAX(shape_wm.STX) AS MAX_X,
+ MAX(shape_wm.STY) AS MAX_Y
+ FROM [IED].[${db_version}].[SiteMap]
+ WHERE [facilityNames] COLLATE Latin1_General_CI_AI LIKE '%${text}%'`)}`,
+ );
+};
+
export const getCountriesExtent = (countries) => {
const requests = [];
countries.forEach((country) => {
diff --git a/src/customizations/volto/components/theme/View/DefaultView.jsx b/src/customizations/volto/components/theme/View/DefaultView.jsx
new file mode 100644
index 0000000..a36f173
--- /dev/null
+++ b/src/customizations/volto/components/theme/View/DefaultView.jsx
@@ -0,0 +1,117 @@
+/**
+ * Document view component.
+ * @module components/theme/View/DefaultView
+ */
+
+import React from 'react';
+import PropTypes from 'prop-types';
+import { injectIntl } from 'react-intl';
+
+import { Container, Segment, Grid, Label } from 'semantic-ui-react';
+import config from '@plone/volto/registry';
+import { getSchema } from '@plone/volto/actions';
+import { getWidget } from '@plone/volto/helpers/Widget/utils';
+import RenderBlocks from '@plone/volto/components/theme/View/RenderBlocks';
+
+import { hasBlocksData, getBaseUrl } from '@plone/volto/helpers';
+import { useDispatch, useSelector } from 'react-redux';
+
+/**
+ * Component to display the default view.
+ * @function DefaultView
+ * @param {Object} content Content object.
+ * @returns {string} Markup of the component.
+ */
+const DefaultView = (props) => {
+ const { content, location } = props;
+ const path = getBaseUrl(location?.pathname || '');
+ const dispatch = useDispatch();
+ const { views } = config.widgets;
+ const contentSchema = useSelector((state) => state.schema?.schema);
+ const fieldsetsToExclude = [
+ 'categorization',
+ 'dates',
+ 'ownership',
+ 'settings',
+ ];
+ const fieldsets = contentSchema?.fieldsets.filter(
+ (fs) => !fieldsetsToExclude.includes(fs.id),
+ );
+
+ React.useEffect(() => {
+ content?.['@type'] &&
+ !hasBlocksData(content) &&
+ dispatch(getSchema(content['@type'], location.pathname));
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, []);
+
+ return hasBlocksData(content) ? (
+
+
+
+ ) : (
+
+ {fieldsets?.map((fs) => {
+ return (
+
+ {fs.id !== 'default' &&
{fs.title}
}
+ {fs.fields?.map((f, key) => {
+ let field = {
+ ...contentSchema?.properties[f],
+ id: f,
+ widget: getWidget(f, contentSchema?.properties[f]),
+ };
+ let Widget = views?.getWidget(field);
+ return f !== 'title' ? (
+
+
+
+
+
+
+
+
+
+
+ ) : (
+
+ );
+ })}
+
+ );
+ })}
+
+ );
+};
+
+/**
+ * Property types.
+ * @property {Object} propTypes Property types.
+ * @static
+ */
+DefaultView.propTypes = {
+ /**
+ * Content of the object
+ */
+ content: PropTypes.shape({
+ /**
+ * Title of the object
+ */
+ title: PropTypes.string,
+ /**
+ * Description of the object
+ */
+ description: PropTypes.string,
+ /**
+ * Text of the object
+ */
+ text: PropTypes.shape({
+ /**
+ * Data of the text of the object
+ */
+ data: PropTypes.string,
+ }),
+ }).isRequired,
+};
+
+export default injectIntl(DefaultView);
diff --git a/src/customizations/volto/components/theme/View/RenderBlocks.jsx b/src/customizations/volto/components/theme/View/RenderBlocks.jsx
new file mode 100644
index 0000000..148c996
--- /dev/null
+++ b/src/customizations/volto/components/theme/View/RenderBlocks.jsx
@@ -0,0 +1,65 @@
+import React from 'react';
+import { getBaseUrl, applyBlockDefaults } from '@plone/volto/helpers';
+import { defineMessages, injectIntl } from 'react-intl';
+import { map } from 'lodash';
+import {
+ getBlocksFieldname,
+ getBlocksLayoutFieldname,
+ hasBlocksData,
+} from '@plone/volto/helpers';
+import StyleWrapper from '@plone/volto/components/manage/Blocks/Block/StyleWrapper';
+import config from '@plone/volto/registry';
+
+const messages = defineMessages({
+ unknownBlock: {
+ id: 'Unknown Block',
+ defaultMessage: 'Unknown Block {block}',
+ },
+});
+
+const RenderBlocks = (props) => {
+ const { content, intl, location, metadata } = props;
+ const blocksFieldname = getBlocksFieldname(content);
+ const blocksLayoutFieldname = getBlocksLayoutFieldname(content);
+ const blocksConfig = props.blocksConfig || config.blocks.blocksConfig;
+ const CustomTag = props.as || React.Fragment;
+
+ return hasBlocksData(content) ? (
+
+ {map(content[blocksLayoutFieldname].items, (block) => {
+ const Block =
+ blocksConfig[content[blocksFieldname]?.[block]?.['@type']]?.view;
+
+ const blockData = applyBlockDefaults({
+ data: content[blocksFieldname][block],
+ intl,
+ metadata,
+ properties: content,
+ });
+
+ return Block ? (
+
+
+
+ ) : (
+
+ {intl.formatMessage(messages.unknownBlock, {
+ block: content[blocksFieldname]?.[block]?.['@type'],
+ })}
+
+ );
+ })}
+
+ ) : (
+ ''
+ );
+};
+
+export default injectIntl(RenderBlocks);