Skip to content

v0.x → v3.x Migration Guide

Nelson Pecora edited this page Oct 31, 2017 · 2 revisions

Kiln 3.0 is here! To take full advantage of it, though, you'll need to make a few changes to your setups.

Kiln Component

First things first, make sure your clay-kiln component is in a non-editable component list in your layouts. This prevents Kiln from trying to edit itself or reload its preloaded data. The convention we're using at NY Mag is to put Kiln (and any Kiln plugins) in a kiln-internals component list. The schema looks like this:

kilnInternals:
  _componentList:
    internals: true
    include:
      - clay-kiln
      - clay-space-edit

And the corresponding template looks like this (note the separate, editable foot component list, where we're putting invisible components):

<div class="foot" data-editable="foot">{{ > component-list foot }}</div>
<div class="kiln-internals">{{ > component-list kilnInternals }}</div>

Client-side Models and Templates

While Kiln v1.0 still supports server.js and server-side rendering, you should convert all of your components to model.js and handlebars templates (docs here) to allow them to render client-side instantly. This also enables cross-component updating for those components.

NOTE: model.save() and model.render() have timeouts to preserve the fast editing experience. There are a number of strategies to deal with slow saves (TK link to wiki page)

Preloading Data

In Kiln v1.0, the schemae and data for all components on the page will be preloaded when the page loads. This allows quick editing of those components without having to fetch extra data from the server. In addition, the models and (handlebars) templates of all installed components will be preloaded. Kiln's application code is not inlined, so it'll load in parallel with the html page and will be browser cached for speed.

Schema Changes

Kiln v1.0 allows for cross-component updating, tabbed sections in forms, behavior ordering, multiple buttons (like magic-button and lock) on text inputs, and much more consistent wysiwyg editing using Quill. It also introduces a number of new behaviors and breaking changes to current behaviors.

Cross-Component Updating

Components can affect other components on the page by publishing and subscribing to properties (such as title, description, ledeImage, etc). This allows many-to-many communication in Kiln, as multiple components can publish or subscribe to the same property, and components can publish or subscribe to multiple different properties. There are no restrictions on pubsub property names, so be sure to avoid unintended collisions!

Publishing

Components that use model.js may publish changes that they would like to propagate to other components on the page. To do so, add a _publish property to the specified field with the name of the property it should publish to.

pageTitle:
  _publish: pageTitle
  _has: text

Properties will be published after a component's model.save() function is called, allowing that component to perform logic before propagating its data. It may be useful to add extra fields to a component's schema which are only populated by model.js, if the data for them is generated from multiple user-editable fields.

Subscribing

Components that want to subscribe to properties should have a _subscribe property on the field(s) they want to update, with the name of the property it should subscribe to.

twitterTitle:
  _subscribe: pageTitle
  _has: text

Subscribed properties will trigger a component to save, thus allowing the subscribed component's model.save() function to do logic on the incoming data before it's sent to the server. If multiple properties are subscribed to, Kiln will wait until all of the data has been published before triggering the save.

PubSub Tips

Kiln intelligently prevents a component from saving more than once during pubsub, so you may safely create circular pubsub logic. For example, a tags component may update an article's primaryTag field, and the article may also allow editing of that field (and propagating those changes back to tags).

As cross-component updating is a feature of Kiln, it only works client-side. For third-party microservices or manual API calls, please make use of cascading PUTs to affect multiple components.

Tabbed Sections

Forms that aren't inline (e.g. overlay and settings) may now have tabbed sections. Specify the sections in the fields property of your group by wrapping the section name in parenthesis (similar to how you specify site-specific components in a component list).

_groups:
  settings:
    fields:
      - alt
      - imageLink
      - creditOverride
      - slideshowJSONPath (Slideshow)
      - slideshowButtonText (Slideshow)
      - slideshowType (Slideshow)
      - sass (Custom Styles)

If you specify sections for some fields but leave the other fields blank, they'll be added to a "General" section. Fields and sections will appear in the form in the order they've been listed.

Behavior Ordering

One very prominent change is that behaviors are now placed in specific parts of a field (before the input, in the main input, and after the input). Behaviors in the same slot (e.g. label and description) must be listed in order in a field's schema.

In Kiln v0.x, you might have a field that looks like this:

url:
  _label: Image URL
  _has:
    -
      fn: text # old text input had to be at the beginning of the list
      type: url
    - required # other behaviors added randomly
    -
      fn: description
      value: Paste the URL to your image or drag the image from Mediaplay into this field.
    - label

In Kiln v1.0, you must add them in order. Note that behaviors which go into different slots (e.g. label and text) can be in any order (i.e. you can still put text first in the list), but it's good practice to put them in the order that you expect them to appear in the Kiln UI.

url:
  _label: Image URL
  _has:
    - label
    - required
    -
      fn: description
      value: Paste the URL to your image or drag the image from Mediaplay into this field.
    -
      fn: text
      type: url

New Behaviors

Reveal

The new reveal behavior conditionally hides and shows a field based on the value of another field. (more info)

Conditional Required

The conditional-required behavior acts like the required behavior, but sets a field required or not based on the value of another field. (more info)

Updated Behaviors (and Placeholders)

For Kiln v1.0, all current behaviors have been rewritten as Vue components. Their full documentation is automatically generated, but here is a list of notable changes:

  • autocomplete and simple-list-primary are now part of simple-list, rather than separate behaviors
  • magic-button allows a store argument, which will pull component data from the client-side store rather than doing api calls to the server
  • magic-button preserves formatting when grabbing rich text from wysiwyg fields
  • lock can now be toggled, allowing re-locking of unlocked fields (they will always be locked when a form is opened, but this gives a nice appfeel for the end user)
  • _placeholder height is now a number, not a string with units
  • _placeholder text cannot display html, only plaintext

WYSIWYG

The wysiwyg behavior has been rewritten from the ground up to use Quill rather than medium-editor. This allows for more formatting options, better paste handling, and ironclad html sanitization due to being backed by a real document format. Full documentation of the new wysiwyg behavior is available here. Notable changes include:

  • enableKeyboardExtras is now separated into the type and pseudoBullet arguments
  • type: single-line is the affordances you had in Kiln v0.x with enableKeyboardExtras: false
  • type: multi-component is similar to enableKeyboardExtras: true (paste rules are parsed for multi-component paste, etc)
  • type: multi-line is new functionality enabling multiple paragraphs in a single wysiwyg field (useful for components like blockquotes)
  • newlines are now created with enter rather than shift + enter
  • new paragraphs are now created by pressing enter twice
  • multi-component wysiwyg fields allow keyboard arrow navigation between component instances
  • buttons and formats have extended functionality, including phrase (creates a <span> with a specified class)

Phrase

Phrases are spans that may have any whitelisted (see list) class. Specify them by passing in a string or object to the buttons argument.

fn: wysiwyg
buttons:
  - bold
  - italic
  - phrase # no class
  -
    phrase:
      class: clay-annotated # custom (whitelisted) class
      button: # custom button text

Custom Behaviors, Panes, Validators, Helpers, and Plugins

Whereas Kiln v0.x had a hodgepodge of events and globally-exposed services, Kiln v1.0 has proper API support for custom behaviors, panes, validators, handlebars helpers, and plugins (things that need to subscribe to changes in the client-side store).

Behaviors

Custom behaviors should be added to window.kiln.behaviors['your-behavior-name']. They should be a .vue file that exports a component, and they can overwrite built-in behaviors if desired.

Panes

Custom panes should be added to window.kiln.panes['your-pane-name']. They should be a .vue file that exports a component. Panes can be triggered by calling openPane:

store.dispatch('openPane', {
  title: 'Title of Your Pane',
  position: 'right', // 'left' is the default
  size: 'large', // 'medium' is the default
  content: {
    component: 'your-pane-name',
    args: {
      // any arguments you want to pass into your pane
    }
  }
});

Validators

In Kiln v0.x, validators received a hodgepodge of data and had to parse the DOM for a lot of their logic. In Kiln v1.0, validators now receive the client-side store's state object, with data for components, schema, page, etc. Validators may still access the DOM, but the vast majority of data validation should be done by simply mapping/reducing over the state.

Custom validators should be added to window.kiln.validators['your-validator-name'] and may overwrite built-in validators. Validators should export an object with label, description, type (error or warning), and validate (a function that receives state) properties.

If a validator passes, it should return either undefined or an empty array. For errors, return an array of error objects.

[{
  uri: 'domain.com/components/foo', // uri of the component
  field: 'someField', // optional field to link directly to in the validation message
  location: 'Component Name » Field', // human-readable error message
  preview: '...tk foo...' // optional preview of the bad data, or additional information about the error
}]

NOTE: Validators may return promises!

Handlebars Helpers

Kiln v1.0 pulls in the nymag-handlebars library, but you may add custom handlebars helpers to window.kiln.helpers['your-helper-name']. You may overwrite built-in helpers, but that is not recommended (as it makes troubleshooting templates issues a lot more difficult, and the helper namespace is effectively infinite).

Plugins

If you need to listen to mutations on the client-side store, you should create a plugin and add it to window.kiln.plugins['your-plugin-name']. These are passed directly into the vuex store.