-
-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Popup with options to remove metadata within the block (#331)
* added functionality to remove blocks along with their saved metadata in the modal component * build * improved some ui elements and styles * build * removed REST API functions for deleting post metadata * Fixed multiple issues: implemented hooks and useEntityProp state functions to manage post metadata * build * refactored handleConfirmDelete function * update only selected meta and not all * simplified component render condition * added useAllBlocks hook * fixed error affecting nested blocks and initial contained blocks in editor * build * simplified code to detect removed block changed useAllBlocks hook to always return blocks array * optimized useAllBlocks hook * improved remove meta modal code structure and added memoization * prevent displaying checkboxes for meta, which does not stored in the post simplified some code parts * build --------- Co-authored-by: Nikita <[email protected]>
- Loading branch information
Showing
14 changed files
with
251 additions
and
47 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import { registerPlugin } from '@wordpress/plugins'; | ||
import RemoveBlockWithSavedMeta from './remove-block-with-saved-post-meta'; | ||
|
||
registerPlugin('lazy-blocks-remove-block-with-saved-meta', { | ||
render: RemoveBlockWithSavedMeta, | ||
}); |
185 changes: 185 additions & 0 deletions
185
assets/editor/plugins/remove-block-with-saved-post-meta/index.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
import './index.scss'; | ||
// eslint-disable-next-line import/no-extraneous-dependencies | ||
import { differenceWith } from 'lodash'; | ||
import { useSelect } from '@wordpress/data'; | ||
import { useEffect, useState, useMemo, useCallback } from '@wordpress/element'; | ||
import { useEntityProp } from '@wordpress/core-data'; | ||
import { Button, ToggleControl } from '@wordpress/components'; | ||
import { usePrevious } from '@wordpress/compose'; | ||
import { __ } from '@wordpress/i18n'; | ||
|
||
import Modal from '../../../components/modal'; | ||
import useAllBlocks from '../../../hooks/use-all-blocks'; | ||
|
||
let options = window.lazyblocksGutenberg; | ||
if (!options?.blocks?.length) { | ||
options = { | ||
post_type: 'post', | ||
blocks: [], | ||
controls: {}, | ||
}; | ||
} | ||
|
||
function RemoveBlockWithSavedMeta() { | ||
const [isModalOpen, setIsModalOpen] = useState(false); | ||
const [savedMetaNames, setMetaNames] = useState([]); | ||
|
||
const allBlocks = useAllBlocks(); | ||
const prevAllBlocks = usePrevious(allBlocks); | ||
|
||
const postType = useSelect( | ||
(select) => select('core/editor')?.getCurrentPostType?.(), | ||
[] | ||
); | ||
|
||
const [meta, setMeta] = useEntityProp('postType', postType, 'meta'); | ||
|
||
// Memoize blocks with meta controls | ||
const blocksWithMetaControls = useMemo(() => { | ||
return options.blocks.filter((block) => | ||
Object.values(block.controls).some( | ||
(control) => control.save_in_meta === 'true' | ||
) | ||
); | ||
}, []); | ||
|
||
const handleMetaToggle = useCallback((index, value) => { | ||
setMetaNames((prev) => | ||
prev.map((prevMeta, i) => | ||
i === index ? { ...prevMeta, checked: value } : prevMeta | ||
) | ||
); | ||
}, []); | ||
|
||
const handleConfirmDelete = useCallback(() => { | ||
const metaToDelete = savedMetaNames.reduce((acc, savedMeta) => { | ||
if (savedMeta.checked) { | ||
acc[savedMeta.metaName] = null; | ||
} | ||
|
||
return acc; | ||
}, {}); | ||
|
||
if (Object.keys(metaToDelete).length) { | ||
setMeta(metaToDelete); | ||
} | ||
|
||
setIsModalOpen(false); | ||
}, [savedMetaNames, setMeta]); | ||
|
||
const handleCancel = useCallback(() => { | ||
setIsModalOpen(false); | ||
}, []); | ||
|
||
useEffect(() => { | ||
if (!prevAllBlocks) { | ||
return; | ||
} | ||
|
||
const removedBlocks = differenceWith( | ||
prevAllBlocks, | ||
allBlocks, | ||
(el1, el2) => el1.clientId === el2.clientId | ||
); | ||
|
||
if (!removedBlocks.length) { | ||
return; | ||
} | ||
|
||
const savedSlugs = blocksWithMetaControls.map((block) => block.slug); | ||
|
||
const processRemovedBlocks = () => { | ||
const uniqueMetaNames = new Set(); | ||
|
||
const metaNames = removedBlocks | ||
.filter((block) => savedSlugs.includes(block.name)) | ||
.flatMap((block) => { | ||
const savedBlock = blocksWithMetaControls.find( | ||
(saved) => saved.slug === block.name | ||
); | ||
|
||
return Object.values(savedBlock.controls) | ||
.filter((control) => control.save_in_meta === 'true') | ||
.map((control) => ({ | ||
metaName: control.save_in_meta_name || control.name, | ||
label: control.label, | ||
default: control.default, | ||
checked: false, | ||
})) | ||
.filter((control) => { | ||
if (uniqueMetaNames.has(control.metaName)) { | ||
return false; | ||
} | ||
|
||
uniqueMetaNames.add(control.metaName); | ||
|
||
return true; | ||
}); | ||
}) | ||
.filter((m) => { | ||
const metaValue = meta[m.metaName]; | ||
|
||
return ( | ||
metaValue !== m.default && | ||
metaValue !== undefined && | ||
metaValue !== null && | ||
metaValue !== '' | ||
); | ||
}); | ||
|
||
if (metaNames?.length) { | ||
setMetaNames(metaNames); | ||
setIsModalOpen(true); | ||
} | ||
}; | ||
|
||
processRemovedBlocks(); | ||
}, [meta, allBlocks, prevAllBlocks, blocksWithMetaControls]); | ||
|
||
if (!isModalOpen || !savedMetaNames.length) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<Modal | ||
title={__('Remove post meta used by this block?', 'lazy-blocks')} | ||
onRequestClose={handleCancel} | ||
size="medium" | ||
> | ||
<p style={{ marginTop: 0 }}> | ||
{__( | ||
'This block created metadata that is still saved in your post.', | ||
'lazy-blocks' | ||
)} | ||
<br /> | ||
{__( | ||
'Would you like to remove any of these meta fields?', | ||
'lazy-blocks' | ||
)} | ||
</p> | ||
<p>{__('Select post meta to remove:', 'lazy-blocks')}</p> | ||
{savedMetaNames.map((currentMeta, index) => ( | ||
<ToggleControl | ||
key={currentMeta.metaName} | ||
label={currentMeta.label} | ||
checked={currentMeta.checked} | ||
onChange={(value) => handleMetaToggle(index, value)} | ||
/> | ||
))} | ||
<div className="lzb-gutenberg-remove-post-meta-modal-buttons"> | ||
<Button | ||
variant="primary" | ||
onClick={handleConfirmDelete} | ||
disabled={!savedMetaNames.some((m) => m.checked)} | ||
> | ||
{__('Remove selected Meta', 'lazy-blocks')} | ||
</Button> | ||
<Button variant="link" onClick={handleCancel}> | ||
{__('Cancel', 'lazy-blocks')} | ||
</Button> | ||
</div> | ||
</Modal> | ||
); | ||
} | ||
|
||
export default RemoveBlockWithSavedMeta; |
5 changes: 5 additions & 0 deletions
5
assets/editor/plugins/remove-block-with-saved-post-meta/index.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
.lzb-gutenberg-remove-post-meta-modal-buttons { | ||
display: flex; | ||
gap: 16px; | ||
margin-top: 26px; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import { useCallback, useMemo } from '@wordpress/element'; | ||
import { useSelect } from '@wordpress/data'; | ||
|
||
/** | ||
* Custom hook to get all blocks recursively. | ||
* | ||
* @return {Function} Function to get all blocks. | ||
*/ | ||
function useAllBlocks() { | ||
const { allBlocks } = useSelect((select) => { | ||
const { getBlocks } = select('core/block-editor'); | ||
|
||
return { | ||
allBlocks: getBlocks(), | ||
}; | ||
}, []); | ||
|
||
const flattenBlocks = useCallback((blocks) => { | ||
if (!blocks?.length) { | ||
return []; | ||
} | ||
|
||
const result = []; | ||
|
||
blocks.forEach((data) => { | ||
result.push(data); | ||
|
||
if (data.innerBlocks?.length) { | ||
result.push(...flattenBlocks(data.innerBlocks)); | ||
} | ||
}); | ||
|
||
return result; | ||
}, []); | ||
|
||
return useMemo(() => flattenBlocks(allBlocks), [allBlocks, flattenBlocks]); | ||
} | ||
|
||
export default useAllBlocks; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-components', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '5ad81efea32da8e6a67c'); | ||
<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-components', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => 'b71835124bf0464c824e'); |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
<?php return array('dependencies' => array('lodash', 'react', 'react-dom', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-plugins'), 'version' => 'edbc2c4cddea46341962'); | ||
<?php return array('dependencies' => array('lodash', 'react', 'react-dom', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-plugins'), 'version' => 'c9355c9ad4d453a56d82'); |
Large diffs are not rendered by default.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
<?php return array('dependencies' => array('lodash', 'react', 'react-dom', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '61d7c5ab7c461a8c5833'); | ||
<?php return array('dependencies' => array('lodash', 'react', 'react-dom', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-plugins'), 'version' => 'b410994159c603f84602'); |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.