Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Reusable block save button, snackbar on save and Welcome Guide #32464

Closed
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
8bc50d4
Add Reusable block save button, snackbar on save and Welcome Guide
thisissandip Jun 4, 2021
fd391bd
Update the way to check dirty records and Fix l10n
thisissandip Jun 11, 2021
afe9922
Remove External Link and Update Finish Button Text in Welcome Gudie
thisissandip Jun 11, 2021
424fbc9
Move Save Button to it's own group
thisissandip Jun 15, 2021
a4f9b21
move hasEdits to top useSelect
thisissandip Jun 15, 2021
297e62e
Fix ESLint Errors
thisissandip Jun 15, 2021
ea6ef3a
rebase
thisissandip Jun 29, 2021
38fbea7
Add welcome guide image
thisissandip Jul 7, 2021
355595a
welcome guide updates and make save button to 32px in height
thisissandip Jul 12, 2021
1046bc4
Save button box inset
thisissandip Jul 14, 2021
35e713b
fix typos and add css comments
thisissandip Jul 17, 2021
a0ab538
add dot to parent selector for reusable block
thisissandip Jul 28, 2021
da40570
Add dot to block parent seletor and reusable block toolbar
thisissandip Aug 4, 2021
1952b92
add two separate components for unsaved changes indicator
thisissandip Aug 12, 2021
cd7bca8
undo block switcher changes
thisissandip Aug 12, 2021
0df63a4
hide save btn when there are no changes
thisissandip Aug 30, 2021
2a213ee
Merge pull request #1 from thisissandip/add/dot-to-parent-selector
thisissandip Aug 31, 2021
74fcdd6
update label and adjust margin
thisissandip Sep 8, 2021
f038b11
use grid-unit-10
thisissandip Sep 8, 2021
6e5b545
adjust unsaved changes indicator margin
thisissandip Sep 9, 2021
bf3eaf9
increase parent selector focus indicator width
thisissandip Sep 14, 2021
740a109
gets rid of visual jump
kellychoffman Nov 1, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* WordPress dependencies
*/
import { getBlockType, store as blocksStore } from '@wordpress/blocks';
import { ToolbarButton } from '@wordpress/components';
import { ToolbarButton, Slot } from '@wordpress/components';
import { useSelect, useDispatch } from '@wordpress/data';
import { __, sprintf } from '@wordpress/i18n';
import { useRef } from '@wordpress/element';
Expand Down Expand Up @@ -78,6 +78,7 @@ export default function BlockParentSelector() {
ref={ nodeRef }
{ ...showMoversGestures }
>
<Slot name="parent-block-selector-unsaved-changes-indicator" />
<ToolbarButton
className="block-editor-block-parent-selector__button"
onClick={ () => selectBlock( firstParentClientId ) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,31 @@
border-radius: $radius-block-ui;
}
}

// styles for parent block selector when parent block has changes
.block-editor-block-parent-selector.parent-block-has-changes {
left: calc(-#{$grid-unit-60} - #{$grid-unit-30} - #{$border-width});

// increase the width of parent selector to make room for the dot
.block-editor-block-parent-selector__button {
width: $grid-unit-60 + $grid-unit-20;
}

// move the parent selector icon to right side to make room for the dot
.block-editor-block-icon {
margin-right: -15px;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing this value to -16px (or $grid-unit-20) seems to get rid of the visual jump for me (tested on a couple of different screens at different viewport sizes).

}

// add the dot before the parent selector icon
.parent-block-selector-unsaved-changes-indicator {
position: absolute;
top: 50%;
transform: translateY(-50%);
background: var(--wp-admin-theme-color);
border-radius: 4px;
height: 8px;
width: 8px;
margin: 0 12px;
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
ToolbarButton,
ToolbarGroup,
ToolbarItem,
Slot,
} from '@wordpress/components';
import {
switchToBlockType,
Expand Down Expand Up @@ -147,6 +148,7 @@ export const BlockSwitcherDropdownMenu = ( { clientIds, blocks } ) => {
} }
icon={
<>
<Slot name="block-unsaved-changes-indicator" />
<BlockIcon
icon={ icon }
className="block-editor-block-switcher__toggle"
Expand Down
10 changes: 10 additions & 0 deletions packages/block-editor/src/components/block-switcher/style.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
.block-editor-block-switcher {
position: relative;

// Show dot before the block switcher in block toolbar if block has edits
.block-unsaved-changes-indicator {
position: relative;
background: var(--wp-admin-theme-color);
border-radius: 4px;
height: 8px;
width: 8px;
margin-right: 8px;
}
}

// Show an indicator triangle.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,15 @@
}
}

// move contextual toolbar to right when parent block has changes
.block-editor-block-contextual-toolbar.parent-block-has-changes:not(.is-fixed) {
margin-left: calc(#{$grid-unit-60} + #{$grid-unit-30});

.show-icon-labels & {
margin-left: 0;
}
}

.block-editor-block-parent-selector {
position: absolute;
top: -$border-width;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/**
* WordPress dependencies
*/
import { Fill } from '@wordpress/components';
import { useEffect } from '@wordpress/element';

function UnsavedChangesIndicator() {
useEffect( () => {
// add class to the parent selector to increase it's width
const parentSelectorBtn = document.querySelector(
'.block-editor-block-parent-selector'
);
parentSelectorBtn.classList.add( 'parent-block-has-changes' );
// add class to the contextual toolbar to move it to the right side
const contextualToolBar = document.querySelector(
'.block-editor-block-contextual-toolbar'
);
contextualToolBar.classList.add( 'parent-block-has-changes' );

return () => {
// remove classes from the parent selector and contextual toolbar when component unmounts
parentSelectorBtn.classList.remove( 'parent-block-has-changes' );
contextualToolBar.classList.remove( 'parent-block-has-changes' );
};
Comment on lines +9 to +24
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something that I mentioned on the other PR (thisissandip#1), I think it'd be good to make this slot not modify the element's class names in this way. This couples the UnsavedChangesIndicator to the class name of the parent selector button, if that classname changes then this breaks.

I recall it was because the parent selector button is positioned absolutely. That seems unusual to me, and like some tech debt. Maybe those toolbar styles can be refactored.

}, [] );

return (
<div className="parent-block-selector-unsaved-changes-indicator"></div>
);
}

function ParentBlockSelectorUnsavedChangesIndicator() {
return (
<>
<Fill name="parent-block-selector-unsaved-changes-indicator">
<UnsavedChangesIndicator />
</Fill>
</>
);
}

export default ParentBlockSelectorUnsavedChangesIndicator;
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* WordPress dependencies
*/
import { Fill } from '@wordpress/components';

function UnsavedChangesIndicator() {
return <div className="block-unsaved-changes-indicator"></div>;
}

function SelectedBlockUnsavedChangesIndicator() {
return (
<>
<Fill name="block-unsaved-changes-indicator">
<UnsavedChangesIndicator />
</Fill>
</>
);
}

export default SelectedBlockUnsavedChangesIndicator;
2 changes: 2 additions & 0 deletions packages/block-editor/src/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ export { default as BlockSettingsMenuControls } from './block-settings-menu-cont
export { default as BlockTitle } from './block-title';
export { default as BlockToolbar } from './block-toolbar';
export { default as BlockTools } from './block-tools';
export { default as __experimentalParentBlockSelectorUnsavedChangesIndicator } from './block-unsaved-changes-indicator/parent-block-selector-unsaved-changes-indicator';
export { default as __experimentalSelectedBlockUnsavedChangesIndicator } from './block-unsaved-changes-indicator/selected-block-unsaved-changes-indicator';
export {
default as CopyHandler,
useClipboardHandler as __unstableUseClipboardHandler,
Expand Down
87 changes: 86 additions & 1 deletion packages/block-library/src/block/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,35 @@ import {
TextControl,
PanelBody,
} from '@wordpress/components';
import { useState } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import {
__experimentalUseInnerBlocksProps as useInnerBlocksProps,
__experimentalUseNoRecursiveRenders as useNoRecursiveRenders,
__experimentalBlockContentOverlay as BlockContentOverlay,
__experimentalParentBlockSelectorUnsavedChangesIndicator as ParentBlockSelectorUnsavedChangesIndicator,
__experimentalSelectedBlockUnsavedChangesIndicator as SelectedBlockUnsavedChangesIndicator,
InnerBlocks,
BlockControls,
InspectorControls,
useBlockProps,
Warning,
store as blockEditorStore,
} from '@wordpress/block-editor';
import { store as reusableBlocksStore } from '@wordpress/reusable-blocks';
import { ungroup } from '@wordpress/icons';
import { store as noticesStore } from '@wordpress/notices';

/**
* Internal dependencies
*/
import ReusableBlockWelcomeGuide from './reusable-block-welcome-guide';

export default function ReusableBlockEdit( { attributes: { ref }, clientId } ) {
const [ hasAlreadyRendered, RecursionProvider ] = useNoRecursiveRenders(
ref
);
const { isMissing, hasResolved } = useSelect(
const { isMissing, hasResolved, hasEdits } = useSelect(
( select ) => {
const persistedBlock = select( coreStore ).getEntityRecord(
'postType',
Expand All @@ -47,14 +57,37 @@ export default function ReusableBlockEdit( { attributes: { ref }, clientId } ) {
'wp_block',
ref,
] );
const blockHasEdits = select( coreStore ).hasEditsForEntityRecord(
'postType',
'wp_block',
ref
);
return {
hasResolved: hasResolvedBlock,
isMissing: hasResolvedBlock && ! persistedBlock,
hasEdits: blockHasEdits,
};
},
[ ref, clientId ]
);

const { isChildSelected, isSelected } = useSelect( ( select ) => {
const { getBlockParents, getSelectedBlockClientId } = select(
blockEditorStore
);
const selectedBlockClientId = getSelectedBlockClientId();
const _isSelected = selectedBlockClientId === clientId;

const parents = getBlockParents( selectedBlockClientId );
const firstParentClientId = parents[ parents.length - 1 ];
const _isChildSelected = firstParentClientId === clientId;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't the case of changing nested blocks inside the reusable block been handled somehow? I was expecting here to see a getBlockRootClientId and check if is reusable and hasEdits... If we add a Group with a Paragraph inside the reusable block and change that paragraph, the block has edits but there is no indication for the changes. Of course in this case the Group block is the parent.. I'm not sure how it would be best to show this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was expecting here to see a getBlockRootClientId and check if is reusable and hasEdits

Yes, this is much cleaner and better. Thank you for the suggestion. Updating this in my next commit.

If we add a Group with a Paragraph inside the reusable block and change that paragraph, the block has edits but there is no indication for the changes. Of course in this case the Group block is the parent.. I'm not sure how it would be best to show this.

Even I am not sure about this case cause one has to select the Reusable block itself to access the save button in the block toolbar.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we add a Group with a Paragraph inside the reusable block and change that paragraph, the block has edits but there is no indication for the changes.

Introducing dot indicators into List view has come up as one possible solution that would help with more visibility in instances with a lot of nesting. Needs a design explore but I could look at this alongside other follow ups in #33988!


return {
isChildSelected: _isChildSelected,
isSelected: _isSelected,
};
}, [] );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clientId is a dependency here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! You saved me from future errors! 🚀


const {
__experimentalConvertBlockToStatic: convertBlockToStatic,
} = useDispatch( reusableBlocksStore );
Expand Down Expand Up @@ -85,6 +118,31 @@ export default function ReusableBlockEdit( { attributes: { ref }, clientId } ) {
}
);

// local states for gudie modal
const [ isGuideOpen, setIsGuideOpen ] = useState( false );

const { saveEditedEntityRecord } = useDispatch( coreStore );
const { createNotice } = useDispatch( noticesStore );

// save the unsaved records
const saveEditedRecords = () => {
saveEditedEntityRecord( 'postType', 'wp_block', ref );
showSnackbar();
};

const showSnackbar = () => {
createNotice( 'success', __( 'Reusable block saved.' ), {
type: 'snackbar',
isDismissible: true,
actions: [
{
label: __( 'Learn more' ),
onClick: () => setIsGuideOpen( true ),
},
],
} );
};

if ( hasAlreadyRendered ) {
return (
<div { ...blockProps }>
Expand Down Expand Up @@ -118,6 +176,14 @@ export default function ReusableBlockEdit( { attributes: { ref }, clientId } ) {
return (
<RecursionProvider>
<div { ...blockProps }>
{ isSelected && hasEdits && (
<SelectedBlockUnsavedChangesIndicator />
) }

{ isChildSelected && hasEdits && (
<ParentBlockSelectorUnsavedChangesIndicator />
) }

<BlockControls>
<ToolbarGroup>
<ToolbarButton
Expand All @@ -127,6 +193,19 @@ export default function ReusableBlockEdit( { attributes: { ref }, clientId } ) {
showTooltip
/>
</ToolbarGroup>
{ hasEdits && (
<ToolbarGroup>
<ToolbarButton
isPrimary
className="block-library-block__reusable-block-save-button"
onClick={ saveEditedRecords }
label={ __( 'Save globally' ) }
showTooltip
>
{ __( 'Save' ) }
</ToolbarButton>
</ToolbarGroup>
) }
</BlockControls>
<InspectorControls>
<PanelBody>
Expand All @@ -142,6 +221,12 @@ export default function ReusableBlockEdit( { attributes: { ref }, clientId } ) {
wrapperProps={ innerBlocksProps }
className="block-library-block__reusable-block-container"
/>
{ isGuideOpen && (
<ReusableBlockWelcomeGuide
isGuideOpen={ isGuideOpen }
setIsGuideOpen={ setIsGuideOpen }
/>
) }
</div>
</RecursionProvider>
);
Expand Down
44 changes: 44 additions & 0 deletions packages/block-library/src/block/editor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,47 @@
display: none;
}
}

// Styles for save button
.components-toolbar-group {
.block-library-block__reusable-block-save-button {
margin: 8px;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use $grid-unit-10 instead of 8px if you like.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, Yes! Thank you! 😄

height: $grid-unit-40;

// override the default box inset properties to match height and width of the save button
&::before {
left: 0 !important;
right: 0 !important;
height: $grid-unit-40 !important;
}
}
}


// Styles for Reusable Block Welcome Guide
.edit-reusable-block-welcome-guide {
$image-height: 240px;
$image-width: 312px;
width: 312px;

&__heading {
font-family: $default-font;
font-size: 24px;
line-height: 1.4;
margin: $grid-unit-20 0 $grid-unit-20 0;
padding: 0 $grid-unit-40;
}

&__text {
font-size: $default-font-size;
line-height: 1.4;
margin: 0 0 $grid-unit-30 0;
padding: 0 $grid-unit-40;
}

&__image {
background: #00a0d2;
height: 240px;
margin: 0 0 $grid-unit-20;
}
}
Loading