Skip to content
This repository has been archived by the owner on Apr 25, 2024. It is now read-only.

Commit

Permalink
Added DiscodataConnectorBlock
Browse files Browse the repository at this point in the history
  • Loading branch information
razvanMiu committed Feb 3, 2022
1 parent f9e33fb commit 7502a9e
Show file tree
Hide file tree
Showing 10 changed files with 1,047 additions and 167 deletions.
24 changes: 24 additions & 0 deletions src/components/manage/Blocks/DiscodataConnectorBlock/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import worldSVG from '@plone/volto/icons/world.svg';
import DiscodataConnectorBlockEdit from './v1/Edit';
import DiscodataConnectorBlockView from './v1/View';

// TODO: Move this to volto-forests-theme

export default (config) => {
config.blocks.blocksConfig.discodata_connector_block = {
id: 'discodata_connector_block',
title: 'Discodata connector block',
icon: worldSVG,
group: 'data_blocks',
view: DiscodataConnectorBlockView,
edit: DiscodataConnectorBlockEdit,
restricted: false,
mostUsed: false,
sidebarTab: 1,
security: {
addPermission: [],
view: [],
},
};
return config;
};
16 changes: 16 additions & 0 deletions src/components/manage/Blocks/DiscodataConnectorBlock/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
.connected-data-block {
background-color: lightblue;
}

.block-container .data-content span {
white-space: break-spaces;
}

#sidebar-properties .accordion .ui.menu {
flex-wrap: wrap;
}

#sidebar-properties .accordion .ui.menu .active.item {
border: 1px solid #d4d4d5;
border-radius: 0.28rem !important;
}
90 changes: 90 additions & 0 deletions src/components/manage/Blocks/DiscodataConnectorBlock/v1/Edit.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import React, { useState, useEffect } from 'react';
import { compose } from 'redux';
import _uniqueId from 'lodash/uniqueId';
import { v4 as uuid } from 'uuid';
import View from './View';
import { SidebarPortal } from '@plone/volto/components';
import InlineForm from '@plone/volto/components/manage/Form/InlineForm';
import { connectToMultipleProviders } from '@eeacms/volto-datablocks/hocs';

import { getSchema } from './schema';

import '../styles.css';

const Edit = (props) => {
const [state, setState] = useState({
id: _uniqueId('block_'),
schema: getSchema(props),
});

useEffect(() => {
const newData = { ...props.data };
if (props.data.data_providers) {
if (
typeof props.data?.data_providers === 'object' &&
props.data?.data_providers?.value
) {
try {
newData.data_providers = [];
const dataProvidersSchema = JSON.parse(
props.data?.data_providers?.value,
);
dataProvidersSchema?.fieldsets?.[0]?.fields &&
dataProvidersSchema.fieldsets[0].fields.forEach((dataProvider) => {
newData.data_providers.push({
...dataProvidersSchema.properties[dataProvider],
'@id': uuid(),
id: dataProvider,
});
});
} catch {}
}
}
if (JSON.stringify(newData) !== JSON.stringify(props.data)) {
props.onChangeBlock(props.block, {
...newData,
});
}
/* eslint-disable-next-line */
}, []);

useEffect(() => {
setState({
...state,
schema: getSchema(props),
});
/* eslint-disable-next-line */
}, [props.providers_data, props.data.data_providers_new]);

return (
<div>
<SidebarPortal selected={props.selected}>
<InlineForm
schema={state.schema}
title={state.schema.title}
onChangeField={(field, data) => {
props.onChangeBlock(props.block, {
...(props.data || {}),
[field]: data,
});
}}
formData={props.data || {}}
block={props.block}
/>
</SidebarPortal>
<View {...props} id={state.id} />
</div>
);
};

export default compose(
connectToMultipleProviders((props) => ({
providers:
props.data?.data_providers
?.map((provider) => ({
provider_url: provider.path,
title: provider.title,
}))
?.filter((provider) => provider.provider_url) || [],
})),
)(Edit);
180 changes: 180 additions & 0 deletions src/components/manage/Blocks/DiscodataConnectorBlock/v1/View.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
import React, { useState, useEffect } from 'react';
import { compose } from 'redux';
import { connectToMultipleProviders } from '@eeacms/volto-datablocks/hocs';
import { DataConnectedValue } from '@eeacms/volto-datablocks/Utils';
import { Sources } from '@eeacms/volto-datablocks/Utils';

const providerView = (dataProviderKey, dataProvider) => {
return (
<div
key={`land-data-for-${dataProviderKey}`}
className={dataProvider.className}
>
<span>
{dataProvider.hasDiscodataConnector && (
<DataConnectedValue
url={dataProvider.path}
column={dataProvider.displayColumn}
textTemplate={dataProvider.textTemplate}
specifier={dataProvider.specifier}
placeholder="_"
/>
)}
{dataProvider.measurmentUnit || ''}
</span>
{' ' + (dataProvider.additionalText || '')}
</div>
);
};

const bulletListView = (items) => (
<div className="ui bulleted list">
{items &&
Object.entries(items).map(([key, item]) => (
<div className="item">
{item.leftText}
<span className="float-right">{item.rightText}</span>
</div>
))}
</div>
);

const View = (props) => {
const [dataProviders, setDataProviders] = useState({});
const [parentsDataProviders, setParentsDataProviders] = useState({});
const { providers_data, providers_metadata } = props;
const bulletList =
props.data?.bullet_list?.value &&
JSON.parse(props.data?.bullet_list?.value).properties;

const updateDataProviders = () => {
let newDataProviders = { ...dataProviders };
if (props.data.data_providers) {
if (
typeof props.data.data_providers === 'object' &&
props.data.data_providers.value
) {
newDataProviders = {};
const dataProvidersSchema =
props.data?.data_providers?.value &&
JSON.parse(props.data?.data_providers?.value);
dataProvidersSchema?.fieldsets?.[0]?.fields &&
dataProvidersSchema.fieldsets[0].fields.forEach((dataProvider) => {
newDataProviders[dataProvider] = {
...dataProvidersSchema.properties[dataProvider],
};
});
} else if (Array.isArray(props.data.data_providers)) {
newDataProviders = {};
props.data.data_providers.forEach((provider) => {
newDataProviders[provider.id] = { ...provider };
});
}
}
setDataProviders({ ...newDataProviders });
return newDataProviders;
};

const updateParentsDataProviders = () => {
const newParentsDataProviders = {};
dataProviders &&
Object.entries(dataProviders).forEach(
([dataProviderKey, dataProvider]) => {
if (!dataProvider.hasParent) {
newParentsDataProviders[dataProviderKey] = { ...dataProvider };
} else if (
dataProvider.parent &&
newParentsDataProviders[dataProvider.parent]
) {
if (!newParentsDataProviders[dataProvider.parent].children) {
newParentsDataProviders[dataProvider.parent].children = {};
}
newParentsDataProviders[dataProvider.parent].children[
dataProviderKey
] = dataProvider;
}
},
);
setParentsDataProviders({ ...newParentsDataProviders });
return newParentsDataProviders;
};

useEffect(() => {
updateDataProviders();
/* eslint-disable-next-line */
}, [JSON.stringify(props.data?.data_providers)]);

useEffect(() => {
updateParentsDataProviders();
/* eslint-disable-next-line */
}, [JSON.stringify(dataProviders)]);

const view = (
<div className="flex h-100 pa-1">
<div className="flex flex-column w-100">
{/* {props.data?.block_title ? <h5>{props.data.block_title}</h5> : ''} */}
{parentsDataProviders &&
Object.entries(parentsDataProviders).map(
([dataProviderKey, dataProvider]) => {
if (dataProvider.children) {
return (
<div
className={dataProvider.wrapperClassName}
key={`data-wrapper-${dataProviderKey}`}
>
{providerView(dataProviderKey, dataProvider)}
{Object.entries(
dataProvider.children,
).map(([cildrenKey, children]) =>
providerView(cildrenKey, children),
)}
</div>
);
}
return (
<div
className={dataProvider.wrapperClassName}
key={`data-wrapper-${dataProviderKey}`}
>
{providerView(dataProviderKey, dataProvider)}
</div>
);
},
)}
{bulletList && bulletListView(bulletList)}
{props?.data?.chartSources && (
<div>
<Sources
sources={props.data?.chartSources}
providers_data={providers_data}
providers_metadata={providers_metadata}
download_button={props.data?.download_button}
title={
props.data?.block_title ||
props.data?.data_providers
?.map((provider) => provider.path)
?.filter((path) => path)?.[0]
}
/>
</div>
)}
</div>
</div>
);
return view;
};

export default compose(
connectToMultipleProviders((props) => ({
providers:
props.data?.data_providers
?.map((provider) => ({
provider_url: provider.path,
title: provider.title,
has_data_query_by_context: provider.has_data_query_by_context,
has_data_query_by_provider: provider.has_data_query_by_provider,
data_query: provider.data_query,
}))
?.filter((provider) => provider.provider_url) || [],
})),
)(View);
Loading

0 comments on commit 7502a9e

Please sign in to comment.