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

Issue-39: Allow post display options to be edited without a post being selected #43

Merged
merged 3 commits into from
Nov 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

All notable changes to `Newsletter Builder` will be documented in this file.

## 0.3.4 - 2023-11-13

- Allow editing of post block attributes with no block selected. Allow order attribute to be edited.

## 0.3.3 - 2023-11-10

- Add URL override attribute and slotfill to post block
Expand Down
182 changes: 112 additions & 70 deletions blocks/post/edit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-i18n/
*/
import { __ } from '@wordpress/i18n';
import { __, sprintf } from '@wordpress/i18n';
import { ImagePicker, PostPicker } from '@alleyinteractive/block-editor-tools';
import { useSelect } from '@wordpress/data';
import {
Expand All @@ -14,6 +14,9 @@ import {
Spinner,
TextControl,
} from '@wordpress/components';
import { arrayMoveImmutable } from 'array-move';

import SortableList, { SortableItem, SortableKnob } from 'react-easy-sort';

/**
* React hook that is used to mark the block wrapper element.
Expand Down Expand Up @@ -92,6 +95,47 @@ export default function Edit({
});
};

const isShown = (item: string) => {
switch (item) {
case 'image':
return showImage;
case 'title':
return true;
case 'byline':
return showByline;
case 'excerpt':
return showExcerpt;
case 'content':
return showContent;
case 'cta':
return showCta;
default:
return false;
}
};

const toggleShown = (item: string) => {
switch (item) {
case 'image':
setAttributes({ showImage: !showImage });
break;
case 'byline':
setAttributes({ showByline: !showByline });
break;
case 'excerpt':
setAttributes({ showExcerpt: !showExcerpt });
break;
case 'content':
setAttributes({ showContent: !showContent });
break;
case 'cta':
setAttributes({ showCta: !showCta });
break;
default:
break;
}
};
Copy link
Member

Choose a reason for hiding this comment

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

I went back and forth on this but something like this may be cleaner, but really not sure:

const displayPreferences = {
     'image': showImage,
     'byline': showByline,
     'excerpt': showExcerpt,
     'content': showContent,
     'cta': showCta,
     'title': true
  };

  const isShown = (item: string) => displayPreferences[item] ?? false;
  
  const toggleShown = (item: string) => {
    setAttributes((prevAttributes: EditProps["attributes"]) => ({
      ...prevAttributes,
      [`show${item.charAt(0).toUpperCase() + item.slice(1)}`]: !prevAttributes[`show${item.charAt(0).toUpperCase() + item.slice(1)}`]
    }));
  };

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I like this suggestion, but this work should be temporary (see #48) so I'm going to leave it as is for now.


Copy link
Member

Choose a reason for hiding this comment

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

Also for the ternary's in this file we may consider logical nullish
let postTitle = record?.title.rendered ?? '';
in place of
let postTitle = record ? record.title.rendered : '';

const removeLinks = (html: string) => (
html ? html.replace(/<a[^>]*?>(.*?)<\/a>/gi, '$1') : ''
);
Expand Down Expand Up @@ -130,6 +174,15 @@ export default function Edit({

const titleClass = smallerFont ? 'post__title--small' : '';

const onSortEnd = (oldIndex: number, newIndex: number) => {
const newOrder = arrayMoveImmutable(
[...order as string[]], // eslint-disable-line camelcase
oldIndex,
newIndex,
);
setAttributes({ order: newOrder });
};

return (
<div {...useBlockProps()}>
{postId && !record ? (
Expand Down Expand Up @@ -225,59 +278,62 @@ export default function Edit({
return '';
}
})}
<InspectorControls>
{/* @ts-ignore */}
<PanelBody
title={__('Post', 'wp-newsletter-builder')}
initialOpen
</>
) : (
<div>
{/* @ts-ignore */}
<PostPicker
onUpdate={handleSelect}
allowedTypes={['post']}
onReset={() => handleSelect(0)}
params={{ after: cutoff.toISOString(), per_page: 20 }}
title={__('Please select a post', 'wp-newsletter-builder')}
value={postId}
// @ts-ignore
searchRender={PostPickerResult}
/>
</div>
)}
<InspectorControls>
{/* @ts-ignore */}
<PanelBody
title={__('Post', 'wp-newsletter-builder')}
initialOpen
>
<PanelRow>
<SortableList
onSortEnd={onSortEnd}
className="sortable"
lockAxis="y"
>
{/* @ts-ignore */}
<PanelRow>
{/* @ts-ignore */}
<CheckboxControl
label={__('Show image', 'wp-newsletter-builder')}
checked={showImage}
onChange={(value) => setAttributes({ showImage: value })}
/>
</PanelRow>
{/* @ts-ignore */}
<PanelRow>
{/* @ts-ignore */}
<CheckboxControl
label={__('Show Byline', 'wp-newsletter-builder')}
checked={showByline}
onChange={(value) => setAttributes({ showByline: value })}
/>
</PanelRow>
{/* @ts-ignore */}
<PanelRow>
{/* @ts-ignore */}
<CheckboxControl
label={__('Show dek', 'wp-newsletter-builder')}
checked={showExcerpt}
onChange={(value) => setAttributes({ showExcerpt: value })}
/>
</PanelRow>
{/* @ts-ignore */}
<PanelRow>
{/* @ts-ignore */}
<CheckboxControl
label={__('Show content', 'wp-newsletter-builder')}
checked={showContent}
onChange={(value) => setAttributes({ showContent: value })}
/>
</PanelRow>
{/* @ts-ignore */}
<PanelRow>
{/* @ts-ignore */}
<CheckboxControl
label={__('Show CTA', 'wp-newsletter-builder')}
checked={showCta}
onChange={(value) => setAttributes({ showCta: value })}
/>
</PanelRow>
</PanelBody>
{/* @ts-ignore */}
{order.map((item) => (
<SortableItem key={item}>
<div style={{ display: 'flex' }}>
<SortableKnob>
<span
aria-label={__('Move item', 'wp-newsletter-builder')}
style={{ width: '15px', height: '100%', cursor: 'move' }}
>
::
</span>
</SortableKnob>
{item === 'title' ? (
<p>{__('Title', 'wp-newsletter-builder')}</p>
) : (
<CheckboxControl
label={sprintf(__('Show %s', 'wp-newsletter-builder'), item)}
checked={isShown(item)}
onChange={() => toggleShown(item)}
/>
)}
</div>
</SortableItem>
))}
</SortableList>
</PanelRow>
</PanelBody>
{postId ? (
<>
<PanelBody
title={__('Override Image', 'wp-newsletter-builder')}
initialOpen
Expand All @@ -303,23 +359,9 @@ export default function Edit({
/>
</PanelRow>
</PanelBody>
</InspectorControls>
</>
) : (
<div>
{/* @ts-ignore */}
<PostPicker
onUpdate={handleSelect}
allowedTypes={['post']}
onReset={() => handleSelect(0)}
params={{ after: cutoff.toISOString(), per_page: 20 }}
title={__('Please select a post', 'wp-newsletter-builder')}
value={postId}
// @ts-ignore
searchRender={PostPickerResult}
/>
</div>
)}
</>
) : null}
</InspectorControls>
</div>
);
}
2 changes: 1 addition & 1 deletion plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Plugin Name: Newsletter Builder
* Plugin URI: https://github.com/alleyinteractive/wp-newsletter-builder
* Description: Interface to manage email newsletters
* Version: 0.3.3
* Version: 0.3.4
* Author: Alley Interactive
* Author URI: https://github.com/alleyinteractive/wp-newsletter-builder
* Requires at least: 5.9
Expand Down