What’s New in Nelio Content’s Editorial Calendar

Published in Inside Nelio.

Last week, Antonio explained what to do when a client cancels their subscription to your plugins and recommended contacting them to understand the reasons behind it (and, hopefully, prevent them from leaving). One of the main advantages of talking to ex-clients is that they can tell you what things you can improve about your plugin. After all, they have been using it for some time and therefore they know very well what its strengths and weaknesses are.

At Nelio we always say that we like to listen to our current and ex-users to understand their needs and thus be able to better adapt our offer. In today’s post, we will see what new features Nelio Content brings and how its implementation has been the direct result of the feedback we received.

Gathering Feedback

If you want to create a successful plugin, you must listen to your users and give them what they need. At the end of the day, you created your plugin to solve a specific problem, right? And those who suffer the problem (i.e. your users) are the most qualified people to let you know how to tackle it better.

We have several channels through which we can get in touch with our users: email, social networks, Freshdesk’s ticketing system, WordPress.org support threads, and blog comments. Ruth, Toni and I are continuously monitoring all these channels and we try to attend to all the requests, comments, and ideas we receive.

A request that had been repeated lately was related to the quick post editor included in Nelio Content’s editorial calendar. Until now, when you created or edited a post from the editorial calendar, this is what you saw:

Old post editor in Nelio Content's editorial calendar
Old post editor in Nelio Content’s editorial calendar.

It allowed you to specify the type of content you wanted to create (post, page, etc) along with its title, author, and publication date and time. Also, when creating blog posts, you were able to select a category.

A couple of weeks ago a user wrote to us on WordPress.org with the following request:

Hello, I see that when creating a new post with the calendar, the quick form only allows to choose one of our main categories but not any subcategories.

However when publishing new content, our editors have to choose a subcategory and don’t have to set the main category at all. So instead of showing only main categories, best for us would be to show only subcategories. Or main- and sub-categories, of course.

Is that possible?

w-sky en WordPress.org

In other words, given a category hierarchy like this:

  • WordPress
    • Plugins
      • Premium Plugins
      • Free Plugins
    • Themes
    • Community
  • Business
    • Services
    • Ideas
  • Marketing

the previous version of Nelio Content only allowed you to select WordPress, Business, or Marketing. However, @w-sky’s team needed to be able to select any category (WordPress, Plugins, Free Plugins, Services, etc).

Not only did we receive @w-sky‘s request, but also an email from a different user that wanted the very same feature (i.e. full control of post categories), as well as full control of post tags. And a couple of weeks earlier, yet another user also mentioned that it’d be nice if the post editor allowed users to set the post status and customize their look and feel in the calendar:

Posts with different statuses in the Nelio Content calendar
Posts with different statuses in the Nelio Content calendar.

It’s pretty clear, right? There’s plenty of users who want more from our quick post editor… so it’s time to deliver what they need!

Implementing a New Post Editor

The first thing we did was implement a new version of our quick post editor. That is, we just got rid of the previous code, which used High-Order Components, and rewrite the editor using React hooks (I mention this because I believe it’s a good strategy to update your code little by little).

To give you an idea of the end result, let me show you an example. The original (sub)component that managed a post’s publication time looked like this:

/**
 * Internal dependencies
 */
import { compose } from '@wordpress/compose';
import { withSelect, withDispatch } from '@wordpress/data';
/**
 * Internal dependencies
 */
import { TimeInput } from '@nelio-content/components';
const TimeSelector = ( {
  canUserEditPost,
  disabled,
  isPublished,
  setTimeValue,
  timeValue,
} ) => (
  <div className="nelio-content-post-quick-editor__time">
    <TimeInput
      disabled={ disabled || isPublished || ! canUserEditPost }
      type="time"
      value={ timeValue }
      onChange={ setTimeValue }
    />
  </div>
);
const withTime = withSelect( ( select ) => {
  const { getTimeValue, isPublished } = select(
    'nelio-content/post-quick-editor'
  );
  return {
    timeValue: getTimeValue(),
    isPublished: isPublished(),
  };
} );
const withTimeSetter = withDispatch( ( dispatch ) => {
  const { setTimeValue } = dispatch( 'nelio-content/post-quick-editor' );
  return { setTimeValue };
} );
export default compose( withTime, withTimeSetter )( TimeSelector );

I’m sure you’ll agree: even though it’s supposed to be quite simple, the implementation looks… chaotic. Some of its props (timeValue, isPublished, and setTimeValue) are provided by the HOCs you see in the previous snippet (we retrieve them using withSelect and withDispatch), while others (disabled or canUserEditPost) are provided by the parent component. Confusing!

The new version of this component is much more elegant, simple, and easy to understand, as it no longer receives any props and all the data it needs is retrieved via hooks:

/**
 * WordPress dependencies
 */
import { useSelect, useDispatch } from '@wordpress/data';
/**
 * External dependencies
 */
import { TimeInput } from '@nelio-content/components';
/**
 * Internal dependencies
 */
import { useIsDisabled, useIsPublished } from '../hooks';
export const TimeSelector = () => {
  const [ time, setTime ] = useTime();
  const disabled = useIsDisabled();
  const published = useIsPublished();
  return (
    <div className="nelio-content-post-quick-editor__time">
      <TimeInput
        disabled={ disabled || published }
        type="time"
        value={ time }
        onChange={ setTime }
      />
    </div>
  );
};
// =====
// HOOKS
// =====
const useTime = () => {
  const timeValue = useSelect( ( select ) =>
    select( 'nelio-content/post-quick-editor' ).getTimeValue()
  );
  const { setTimeValue } = useDispatch( 'nelio-content/post-quick-editor' );
  return [ timeValue, setTimeValue ];
};

Before moving forward, I think it’s worth taking a closer look at the previous (new) implementation and, in particular, one of its hooks. useTime is a simple hook that relies on WordPress’ useSelect and useDispatch hooks, which let us retrieve some data and actions from the store. So here’s what we did: we pull the publication time from the store (using withSelect) and the action to update it (using withDispatch) and return a tuple with both values. This approach is quite interesting, because it’s the same approach used by the well-known useState hook and, therefore, the resulting interface is completely familiar to any developer.

You can see the result of the new editor in the following screenshot:

New post editor in Nelio Content's editorial calendar
New post editor in Nelio Content’s editorial calendar.

Needless to say, if you want to snoop a little more on the source code of this new editor, it’s all available here.

Editing Existing Posts…

Our quick post editor can be used to (a) create new posts or (b) edit existing posts. The editor is essentially the same in both cases, but it shows some extra details when editing an existing post (due to, again, some requests from our users).

In the following screenshot you can see the additional options available when we edit an existing post:

New options in Nelio Content's quick post editor
New options in Nelio Content’s quick post editor.

When you edit an existing post, there’s a tabbed section with some additional info about it:

  • Taxonomies is only available when editing a blog post. It lets you modify its categories and tags.
  • Tasks shows the list of related editorial tasks. It’s currently a “readonly list,” but we plan to extend it so that you can create, delete, and edit them in this quick editor.
  • References lists all the post’s suggested references. Again, this is, for the time being, a readonly list.

New Filter to Customize Statuses

Comparing the screenshots of the previous and current version of the post editor, you will see that in the new one it is possible to change their status: Draft, Pending, Scheduled, etc. These statuses are also reflected in the editorial calendar itself, where each post is colored according to its status. Where do these states come from? Is there a way to customize which states are available for each content type? Can we modify the appearance of them in the calendar?

Until now, the answer to these questions was simple: the states were hardcoded in Nelio Content, and users where unable to modify them. But not anymore! They can now tweak and customize them.

The Problem with get_post_stati

The first question you might have is: “why did you hardcode the statuses?” After all, in WordPress, there is a function to register new statuses: register_post_status and a function (get_post_stati) to retrieve them, so why not use them? The “problem” with these functions is that (new) statuses are not linked to a particular content type, which means you can use it everywhere (pages, posts, products, you name it) even when they weren’t intended for them.

For instance, if you take a look at the WooCommerce source code, you will see that in the includes/class-wc-post-types.php line 557 defines the statuses a WooCommerce order can be in: Pending, In Process, Completed, etc. None of these are in any way associated with the shop_order content type, so I could theoretically assign, e.g., wc-pending to a blog post, even though it doesn’t make any sense. This shouldn’t come as a surprise, as custom statuses is a pending issue in WordPress; just take a look at this bug from 2010 on the subject.

If our plugin were to retrieve all available statuses with get_post_stati and display them in our quick post editor, we’d let our users set a WooCommerce order status to our post. After all, there’s no way to tell which statuses can be used with which content types… or is it?

Solution

To solve the previous issue, we simply added a new filter nelio_content_post_statuses that lets our users establish the missing type/status relationships. For instance, imagine you have a new blog post status called “In progress” (in-progress) that tells an editor that the author of a given post is working on it. We know this status must have been registered using WordPress’ register_post_status function, but our plugin doesn’t know it can be used in a blog post. Well, using the filter we can let it know it’s available:

add_filter(
  'nelio_content_post_statuses',
  function ( $statuses, $post_type ) {
    if ( 'post' !== $post_type ) {
      return $statuses;
    }
    $statuses[] = array(
      'slug'   => 'in-progress',
      'name'   => 'In Progress',
      'icon'   => 'format-status',
      'colors' => array(
        'main'       => '#f9d510',
        'background' => '#fffdf1',
      ),
    );
    return $statuses;
  },
  10,
  2
);

And that’s it! When working with posts, there’s the following new status:

  • slug is the internal name of the status,
  • name is a user-friendly label,
  • icon is an optional attribute whose value is the name of a dashicon, and
  • colors is also an optional attribute that specifies the colors Nelio Content should use in the editorial calendar.

Listen to Your Users!

The best way to evolve a product and ensure it fits the target audience is (you guessed it) to listen to said target audience, duh. At Nelio we are always open to your ideas and requests, and we do our best to evolve our plugins in the direction that better suits your needs. Now it’s your turn: how do you deal with the requests you get? How do you prioritize them? Tell us about it in the comment section below!

Featured image by XiaoXiao Sun on Unsplash.

Leave a Reply

Your email address will not be published. Required fields are marked: •

I have read and agree to the Nelio Software Privacy Policy

Your personal data will be located on SiteGround and will be treated by Nelio Software with the sole purpose of publishing this comment here. The legitimation is carried out through your express consent. Contact us to access, rectify, limit, or delete your data.