Building an Opening Hours Field Type Plugin
Storyblok is the first headless CMS that works for developers & marketers alike.
Managing a lot of store or office locations on a company website can be a tedious task for content editors. There are many things to consider, like formatting the address data and opening hours of each location in the same way. At first, the problem might seem simple enough to use a plain text field where content editors can enter all the informations regarding a specific location. But rather sooner than later, you come back to the website, only to find out that the address and opening hour informations of some locations are formatted in a different way than others. One possible reason is that various people are responsible for the maintenance of certain locations.
No matter the reason exactly why the formatting got out of hand, in the end we as web developers are responsible for making it as easy as possible for the content editors to enter all the data in a uniform way. The best way to achieve this is to use input fields which are custom tailored to the particular need.
To solve the problem of formatting opening hours in a uniform way, we'll build a custom Storyblok field type plugin.
Setup
Thanks to the Storyblok plugin system, which is based on Vue.js components, it's very easy to build powerful custom field types.
Although, for very basic plugins, you can use the simple in-browser editor provided by Storyblok itself, usually we need to set up a simple development environment first, before we can get started building our own custom plugin.
There already is great documentation about how to set up a local development environment for building Storyblok plugins. Please follow the steps described in the article and come back when you're ready.
After setting up a fresh local development environment and starting the development server with npm run dev
we're ready to start developing our own plugin.
Creating the plugin
Although at first you might think there isn't much complexity involved in building a plugin to simply display the opening hours of a store, there are some pretty complex versions of this out there, built for a variety of content management systems. For example: some of those plugins allow to account for vacations and public holidays in advance.
In order to keep it simple, we'll build a rather basic implementation. It's up to you to add further functionalities.
Above you can see the initial content of our src/Plugin.vue
entry file. Currently we've only set up the bare minimum code we need to have a valid Storyblok plugin to work with.
The 7 days of the week
In order to limit the possibility for making mistakes as much as possible, we use separate fields for the opening hours for each day of the week.
Above you can see the updated code of our plugin. We're now rendering a new section for every day of the week. For now each day of the week has two time fields for the time at which the door is opened and the time at which the door is closed. We'll extend the plugin with the possibility of inserting breaks later.
The data for the v-for
loop, which is responsible for rendering the day sections, is coming from the days
array of our model.
Adding additional time fields
Next we want to add the possibility to split the opening hours into multiple parts in order to make it possible to insert breaks.
We add a new class OpeningHours__list-item
to add some spacing between multiple rows of time fields.
Above you can see that we add a new button at the bottom of every day section which triggers the newly added addFields()
method.
The addFields()
method inserts new fields into the times
array of the given day. This automatically triggers the Vue.js plugin to re-render and we can see two new fields added to the day section.
Removing time fields
Of course, if it's possible to add new time fields, it also should be possible to remove them.
In the two code diff blocks above you can see that we've added a new icon next to each time field row which triggers a removeFields()
method in order to remove the fields from the given day section.
The removeFields()
method filters the times
array of the given day and removes the given fields.
Copy previous times
Usually opening hours are quite similar every day except Saturday and / or Sunday. In order to make it even easier for our content editors to enter the same opening hours for the weekdays again and again, we can implement a functionality to copy the opening hours of the previous day to the current day.
We add a new copy icon right to every but the first day headline. Clicking it triggers the newly added copyFromPreviousDay()
method which copies the opening hours from the previous day over to the current day.
Using the opening hours plugin
Now that our opening hours plugin is ready, we can build the plugin by running npm run build
. Afterwards we have to copy and paste the generated code from dist/export.js
into the editor text field of the Storyblok app and click the publish button.
Our plugin is now added to our Storyblok spaces, which makes it possible to use it in our content types. Let's edit the schema of the content type for which we want to use opening hours.
After setting up the new field and entering our opening hours, we're ready to consume the data in our application.
Building an opening hours Vue.js component
The following example plugin is responsible to consume the data which is spit out by our newly created opening hours plugin. It's trying to do its best to combine multiple days if they have the same opening hours.
Above you can see how you can use the reduce()
JavaScript array method to create a compact version of the opening hours we receive from our Storyblok plugin and how to render those compact opening hours in a Vue.js component.
Wrapping it up
Usually I like to keep things simple. If something can be done with a plain text field I'm fine with it. But in certain situations even seemingly simple things can become quite complex. It's our job as developers to make the complex as straightforward as possible for our users. Entering opening hours for multiple stores is one of those problems which seem to be rather simple at first, but it can become a taunting task for our content editors to keep the formatting in sync between possible dozens of location entries.
By providing a custom tailored input field, we can remove the complexity of correctly formatting the opening hours from the list of things our content editors have to worry about.