From 97413b2115b2227656fab7dc31d32a42c8ce5324 Mon Sep 17 00:00:00 2001 From: Tiberiu Ichim Date: Thu, 17 Sep 2020 17:36:59 +0300 Subject: [PATCH] Add package content, extracted and improved from tiberiuichim/volto-blocks-form --- .gitignore | 1 + src/ColumnsBlock/ColumnsBlockEdit.jsx | 106 ++++++++++++++++++++++++ src/ColumnsBlock/ColumnsBlockView.jsx | 26 ++++++ src/ColumnsBlock/index.js | 2 + src/ColumnsBlock/schema.js | 21 +++++ src/ColumnsBlock/styles.less | 28 +++++++ src/ColumnsBlock/utils.js | 19 +++++ src/ColumnsWidget/ColumnsWidget.jsx | 115 ++++++++++++++++++++++++++ src/ColumnsWidget/index.js | 2 + src/index.js | 30 ++++++- 10 files changed, 346 insertions(+), 4 deletions(-) create mode 100644 src/ColumnsBlock/ColumnsBlockEdit.jsx create mode 100644 src/ColumnsBlock/ColumnsBlockView.jsx create mode 100644 src/ColumnsBlock/index.js create mode 100644 src/ColumnsBlock/schema.js create mode 100644 src/ColumnsBlock/styles.less create mode 100644 src/ColumnsBlock/utils.js create mode 100644 src/ColumnsWidget/ColumnsWidget.jsx create mode 100644 src/ColumnsWidget/index.js diff --git a/.gitignore b/.gitignore index 211dab2..a88924a 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ dist .env.development.local .env.test.local .env.production.local +*~ diff --git a/src/ColumnsBlock/ColumnsBlockEdit.jsx b/src/ColumnsBlock/ColumnsBlockEdit.jsx new file mode 100644 index 0000000..d14ad0d --- /dev/null +++ b/src/ColumnsBlock/ColumnsBlockEdit.jsx @@ -0,0 +1,106 @@ +import React from 'react'; +import { Grid } from 'semantic-ui-react'; +import { isEmpty } from 'lodash'; +import { SidebarPortal, InlineForm, BlocksForm } from '@plone/volto/components'; +import { emptyBlocksForm } from '@plone/volto/helpers'; + +import { ColumnsBlockSchema } from './schema'; +import { getColumns, empty } from './utils'; + +import './styles.less'; + +const ColumnsBlockEdit = (props) => { + const { + block, + data, + onChangeBlock, + onChangeField, + pathname, + selected, + } = props; + + React.useEffect(() => { + if (!data.coldata) { + onChangeBlock(block, { ...data, coldata: empty() }); + } + }); + + const [colSelections, setColSelections] = React.useState({}); + + const { coldata = empty() } = data; + const columnList = getColumns(coldata); + + return ( + <> +
+ {/* {

{data.block_title}

} */} + + {columnList.map(([colId, column], index) => { + return ( + + {/*

{`Column ${index}`}

*/} + + setColSelections({ + // this invalidates selection in all other columns + [colId]: id, + }) + } + onChangeFormData={(newFormData) => { + onChangeBlock(block, { + ...data, + coldata: { + ...coldata, + columns: { + ...coldata.columns, + [colId]: newFormData, + }, + }, + }); + }} + onChangeField={(id, value) => { + if (['blocks', 'blocks_layout'].indexOf(id) > -1) { + onChangeBlock(block, { + ...data, + coldata: { + ...coldata, + columns: { + ...coldata.columns, + [colId]: { + ...coldata.columns?.[colId], + [id]: value, + }, + }, + }, + }); + } else { + onChangeField(id, value); + } + }} + pathname={pathname} + /> +
+ ); + })} +
+
+ + { + onChangeBlock(block, { + ...data, + [id]: value, + }); + }} + formData={data} + /> + + + ); +}; + +export default ColumnsBlockEdit; diff --git a/src/ColumnsBlock/ColumnsBlockView.jsx b/src/ColumnsBlock/ColumnsBlockView.jsx new file mode 100644 index 0000000..233ccbc --- /dev/null +++ b/src/ColumnsBlock/ColumnsBlockView.jsx @@ -0,0 +1,26 @@ +import React from 'react'; +import { Grid } from 'semantic-ui-react'; +import { renderBlocks } from '@plone/volto/helpers'; +import { getColumns, empty } from './utils'; + +const ColumnsBlockView = (props) => { + const { coldata = empty(), block_title } = props.data; + const columnList = getColumns(coldata); + return ( +
+ {block_title ?

{block_title}

: ''} + + {columnList.map(([id, column], index) => { + return ( + +

{`Column ${index}`}

+ {renderBlocks(column, props)} +
+ ); + })} +
+
+ ); +}; + +export default ColumnsBlockView; diff --git a/src/ColumnsBlock/index.js b/src/ColumnsBlock/index.js new file mode 100644 index 0000000..0959b48 --- /dev/null +++ b/src/ColumnsBlock/index.js @@ -0,0 +1,2 @@ +export ColumnsBlockView from './ColumnsBlockView'; +export ColumnsBlockEdit from './ColumnsBlockEdit'; diff --git a/src/ColumnsBlock/schema.js b/src/ColumnsBlock/schema.js new file mode 100644 index 0000000..bc75d50 --- /dev/null +++ b/src/ColumnsBlock/schema.js @@ -0,0 +1,21 @@ +export const ColumnsBlockSchema = { + title: 'Columns block', + fieldsets: [ + { + id: 'default', + title: 'Default', + fields: ['block_title', 'coldata'], // 'nrColumns' + }, + ], + properties: { + block_title: { + title: 'Block title', + default: 'Columns', + }, + coldata: { + title: 'Columns', + type: 'columns', + }, + }, + required: ['title'], +}; diff --git a/src/ColumnsBlock/styles.less b/src/ColumnsBlock/styles.less new file mode 100644 index 0000000..c668d5f --- /dev/null +++ b/src/ColumnsBlock/styles.less @@ -0,0 +1,28 @@ +.columns-block { + .block-column { + padding: 0.3em; + } +} + +.drag-drop-list-widget { + .columns-area { + padding: 1em 0em; + + [data-rbd-draggable-context-id] { + margin-bottom: 0.3em; + } + + .column-area { + display: flex; + + .label { + flex-grow: 2; + padding-left: 1em; + } + + button { + flex-grow: 0; + } + } + } +} diff --git a/src/ColumnsBlock/utils.js b/src/ColumnsBlock/utils.js new file mode 100644 index 0000000..667eaf4 --- /dev/null +++ b/src/ColumnsBlock/utils.js @@ -0,0 +1,19 @@ +import { v4 as uuid } from 'uuid'; +import { emptyBlocksForm } from '@plone/volto/helpers'; + +export const getColumns = (coldata) => { + return (coldata?.columns_layout?.items || []).map((id) => [ + id, + coldata.columns?.[id], + ]); +}; + +export const empty = () => { + const id = uuid(); + return { + columns: { [id]: emptyBlocksForm() }, + columns_layout: { + items: [id], + }, + }; +}; diff --git a/src/ColumnsWidget/ColumnsWidget.jsx b/src/ColumnsWidget/ColumnsWidget.jsx new file mode 100644 index 0000000..5a4375d --- /dev/null +++ b/src/ColumnsWidget/ColumnsWidget.jsx @@ -0,0 +1,115 @@ +import React from 'react'; +import { v4 as uuid } from 'uuid'; +import { omit, without } from 'lodash'; +import move from 'lodash-move'; +import { DragDropList, Icon, FormFieldWrapper } from '@plone/volto/components'; +import { emptyBlocksForm } from '@plone/volto/helpers'; + +import dragSVG from '@plone/volto/icons/drag.svg'; +import trashSVG from '@plone/volto/icons/delete.svg'; +import plusSVG from '@plone/volto/icons/circle-plus.svg'; + +export function moveColumn(formData, source, destination) { + return { + ...formData, + columns_layout: { + items: move(formData.columns_layout?.items, source, destination), + }, + }; +} + +const empty = () => { + return [uuid(), emptyBlocksForm()]; +}; + +const ColumnsWidget = (props) => { + const { value = {}, id, onChange } = props; + const { columns = {} } = value; + const columnsList = (value.columns_layout?.items || []).map((id) => [ + id, + columns[id], + ]); + return ( + +
+ { + const { source, destination } = result; + if (!destination) { + return; + } + const newFormData = moveColumn( + value, + source.index, + destination.index, + ); + onChange(id, newFormData); + return true; + }} + renderChild={(child, childId, index, draginfo) => ( +
+
+
+ +
+
+
Column {index}
+ +
+
+
+ )} + /> + +
+
+ ); +}; + +export default ColumnsWidget; diff --git a/src/ColumnsWidget/index.js b/src/ColumnsWidget/index.js new file mode 100644 index 0000000..b00aba5 --- /dev/null +++ b/src/ColumnsWidget/index.js @@ -0,0 +1,2 @@ +import ColumnsWidget from './ColumnsWidget'; +export default ColumnsWidget; diff --git a/src/index.js b/src/index.js index cb042f0..49bc7d1 100644 --- a/src/index.js +++ b/src/index.js @@ -1,5 +1,27 @@ -const applyConfig = (config) => { - return config; -}; +import codeSVG from '@plone/volto/icons/code.svg'; + +import { ColumnsBlockView, ColumnsBlockEdit } from './ColumnsBlock'; +import ColumnsWidget from './ColumnsWidget'; + +export default function install(config) { + config.blocks.blocksConfig.columnsBlock = { + id: 'columnsBlock', + title: 'Columns', + icon: codeSVG, + group: 'common', + view: ColumnsBlockView, + edit: ColumnsBlockEdit, + restricted: false, + mostUsed: true, + blockHasOwnFocusManagement: true, + sidebarTab: 1, + security: { + addPermission: [], + view: [], + }, + }; -export default applyConfig; + config.widgets.type.columns = ColumnsWidget; + + return config; +}