@eeacms/volto-accordion-block
Advanced tools
Comparing version 7.1.0 to 8.0.0
@@ -7,2 +7,8 @@ ### Changelog | ||
### [8.0.0](https://github.com/eea/volto-accordion-block/compare/7.1.0...8.0.0) - 24 March 2023 | ||
#### :rocket: New Features | ||
- feat(paste): Possibility to cut/copy/paste blocks within/from accordion block - refs #157469 [dobri1408 - [`ae0f71a`](https://github.com/eea/volto-accordion-block/commit/ae0f71aced0a4d1f10077937d9490f410bc177c4)] | ||
### [7.1.0](https://github.com/eea/volto-accordion-block/compare/7.0.0...7.1.0) - 10 March 2023 | ||
@@ -9,0 +15,0 @@ |
{ | ||
"name": "@eeacms/volto-accordion-block", | ||
"version": "7.1.0", | ||
"version": "8.0.0", | ||
"description": "volto-accordion-block: Volto accordion block", | ||
@@ -5,0 +5,0 @@ "main": "src/index.js", |
@@ -1,5 +0,13 @@ | ||
import { BlocksForm, Icon, SidebarPortal } from '@plone/volto/components'; | ||
import { emptyBlocksForm } from '@plone/volto/helpers'; | ||
import { | ||
BlocksForm, | ||
Icon, | ||
SidebarPortal, | ||
BlocksToolbar, | ||
} from '@plone/volto/components'; | ||
import { | ||
emptyBlocksForm, | ||
getBlocksLayoutFieldname, | ||
} from '@plone/volto/helpers'; | ||
import helpSVG from '@plone/volto/icons/help.svg'; | ||
import { isEmpty } from 'lodash'; | ||
import { isEmpty, without } from 'lodash'; | ||
import React, { useState } from 'react'; | ||
@@ -20,2 +28,3 @@ import { Button, Segment } from 'semantic-ui-react'; | ||
const [selectedBlock, setSelectedBlock] = useState({}); | ||
const [multiSelected, setMultiSelected] = useState([]); | ||
const { | ||
@@ -36,3 +45,58 @@ block, | ||
const metadata = props.metadata || props.properties; | ||
const [currentUid, setCurrentUid] = useState(''); | ||
const onSelectBlock = (uid, id, isMultipleSelection, event, activeBlock) => { | ||
let newMultiSelected = []; | ||
let selected = id; | ||
if (Object.values(activeBlock || {})?.length > 0) { | ||
activeBlock = Object.values(activeBlock)[0]; | ||
} | ||
if (data?.data?.blocks?.hasOwnProperty(uid) && isMultipleSelection) { | ||
selected = null; | ||
const blocksLayoutFieldname = getBlocksLayoutFieldname( | ||
data.data.blocks[uid], | ||
); | ||
const blocks_layout = data.data.blocks[uid][blocksLayoutFieldname].items; | ||
if (event.shiftKey) { | ||
const anchor = | ||
multiSelected.length > 0 | ||
? blocks_layout.indexOf(multiSelected[0]) | ||
: blocks_layout.indexOf(activeBlock); | ||
const focus = blocks_layout.indexOf(id); | ||
if (anchor === focus) { | ||
newMultiSelected = [id]; | ||
} else if (focus > anchor) { | ||
newMultiSelected = [...blocks_layout.slice(anchor, focus + 1)]; | ||
} else { | ||
newMultiSelected = [...blocks_layout.slice(focus, anchor + 1)]; | ||
} | ||
} | ||
if ((event.ctrlKey || event.metaKey) && !event.shiftKey) { | ||
if (multiSelected.includes(id)) { | ||
selected = null; | ||
newMultiSelected = without(multiSelected, id); | ||
} else { | ||
newMultiSelected = [...(multiSelected || []), id]; | ||
} | ||
} | ||
} | ||
setSelectedBlock({ [uid]: selected }); | ||
setCurrentUid(uid); | ||
setMultiSelected(newMultiSelected); | ||
}; | ||
const searchElementInMultiSelection = (uid, blockprops) => { | ||
if ( | ||
multiSelected.find((el) => { | ||
if (el === blockprops.block) return true; | ||
return false; | ||
}) | ||
) | ||
return true; | ||
return false; | ||
}; | ||
const applySchemaEnhancer = (originalSchema) => { | ||
@@ -103,3 +167,3 @@ let schema, schemaEnhancer; | ||
properties.blocks_layout.items.map((item) => { | ||
if (isEmpty(properties.blocks[item].blocks)) { | ||
if (isEmpty(properties.blocks[item]?.blocks)) { | ||
return onChangeBlock(block, { | ||
@@ -156,2 +220,48 @@ ...data, | ||
const changeBlockData = (newBlockData) => { | ||
const selectedIndex = | ||
data.data.blocks[currentUid].blocks_layout.items.indexOf( | ||
Object.values(selectedBlock)[0], | ||
) + 1; | ||
let pastedBlocks = Object.entries(newBlockData.blocks).filter((block) => { | ||
let key = block[0]; | ||
if ( | ||
data?.data?.blocks[currentUid].blocks_layout.items.find( | ||
(x) => x === key, | ||
) | ||
) | ||
return false; | ||
return true; | ||
}); | ||
let blockLayout = pastedBlocks.map((el) => el[0]); | ||
onChangeBlock(block, { | ||
...data, | ||
data: { | ||
blocks: { | ||
...data.data.blocks, | ||
[currentUid]: { | ||
...data.data.blocks[currentUid], | ||
...newBlockData, | ||
blocks_layout: { | ||
items: [ | ||
...data.data.blocks[currentUid].blocks_layout.items.slice( | ||
0, | ||
selectedIndex, | ||
), | ||
...blockLayout, | ||
...data.data.blocks[currentUid].blocks_layout.items.slice( | ||
selectedIndex, | ||
), | ||
], | ||
}, | ||
}, | ||
}, | ||
blocks_layout: data.data.blocks_layout, | ||
}, | ||
}); | ||
}; | ||
return ( | ||
@@ -187,7 +297,8 @@ <fieldset className="accordion-block"> | ||
selectedBlock={selected ? selectedBlock[uid] : null} | ||
onSelectBlock={(id) => | ||
setSelectedBlock({ | ||
[uid]: id, | ||
}) | ||
} | ||
onSelectBlock={(id, l, e) => { | ||
const isMultipleSelection = e | ||
? e.shiftKey || e.ctrlKey || e.metaKey | ||
: false; | ||
onSelectBlock(uid, id, isMultipleSelection, e, selectedBlock); | ||
}} | ||
onChangeFormData={(newFormData) => { | ||
@@ -227,34 +338,60 @@ onChangeBlock(block, { | ||
> | ||
{({ draginfo }, editBlock, blockProps) => ( | ||
<EditBlockWrapper | ||
draginfo={draginfo} | ||
blockProps={blockProps} | ||
disabled={data.disableInnerButtons} | ||
extraControls={ | ||
<> | ||
{instructions && ( | ||
<> | ||
<Button | ||
icon | ||
basic | ||
title="Section help" | ||
onClick={() => { | ||
setSelectedBlock({}); | ||
const tab = manage ? 0 : 1; | ||
props.setSidebarTab(tab); | ||
}} | ||
> | ||
<Icon name={helpSVG} className="" size="19px" /> | ||
</Button> | ||
</> | ||
)} | ||
</> | ||
} | ||
> | ||
{editBlock} | ||
</EditBlockWrapper> | ||
)} | ||
{({ draginfo }, editBlock, blockProps) => { | ||
return ( | ||
<EditBlockWrapper | ||
draginfo={draginfo} | ||
blockProps={blockProps} | ||
disabled={data.disableInnerButtons} | ||
multiSelected={searchElementInMultiSelection(uid, blockProps)} | ||
extraControls={ | ||
<> | ||
{instructions && ( | ||
<> | ||
<Button | ||
icon | ||
basic | ||
title="Section help" | ||
onClick={() => { | ||
setSelectedBlock({}); | ||
const tab = manage ? 0 : 1; | ||
props.setSidebarTab(tab); | ||
}} | ||
> | ||
<Icon name={helpSVG} className="" size="19px" /> | ||
</Button> | ||
</> | ||
)} | ||
</> | ||
} | ||
> | ||
{editBlock} | ||
</EditBlockWrapper> | ||
); | ||
}} | ||
</BlocksForm> | ||
</AccordionEdit> | ||
))} | ||
{selected ? ( | ||
<BlocksToolbar | ||
selectedBlock={Object.keys(selectedBlock)[0]} | ||
formData={data?.data?.blocks[currentUid]} | ||
selectedBlocks={multiSelected} | ||
onSetSelectedBlocks={(blockIds) => { | ||
setMultiSelected(blockIds); | ||
}} | ||
onSelectBlock={(id, l, e) => { | ||
const isMultipleSelection = e | ||
? e.shiftKey || e.ctrlKey || e.metaKey | ||
: false; | ||
onSelectBlock(id, isMultipleSelection, e, selectedBlock); | ||
}} | ||
onChangeBlocks={(newBlockData) => { | ||
changeBlockData(newBlockData); | ||
}} | ||
/> | ||
) : ( | ||
'' | ||
)} | ||
<SidebarPortal selected={selected && !Object.keys(selectedBlock).length}> | ||
@@ -261,0 +398,0 @@ {instructions && ( |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
101929
1617