The Multi-step Editor
====================

The ordering and personalization process can be organized on a step-by-step basis. For example, your users may:
1. Edit the front side of the product.
1. Select an envelope.
1. Edit the back side.
1. Specify any order options.

Even more complicated workflows may exist.

The multi-step editor allows you to implement such a step-by-step sequence by composing your application with widgets, which act as building blocks from a configuration file. This makes Customer's Canvas more flexible, even for non-programmers, whether you need a simple editor or a multistep wizard.

## Before we start...

In order to explore the editor and its configuration, it is highly recommended that you either create a test page based on the information in the [Getting Started](getting-started.md) article or get the Test Stand application from Aurigma. If you are interested in Test Stand, contact us at info@aurigma.com.

## Editor Layout

The editor consists of one or multiple _steps_ and each step has a layout like this:

![Widgets in the multi-step editor](images/widgetPanels.png)

- The **navigation panel** allows for switching the steps.
- The **main panel** holds a basic widget like the design editor, preview, or preflight tool.
- The **left panel** (**tool panel**) may include an option selector, context-dependent blocks, a gallery, or a combination of these.
- The **bottom panel** allows you to enable additional widgets like a gallery.


## Steps

Since the ordering process can be a step-by-step process, you need to associate a set of widgets in each of these containers with a step in the config. For example:

1. **The first step**: the main panel displays Customer's Canvas, and the left panel displays the color options.
2. **The second step**: the main panel displays an approval page, and the left panel displays the delivery options.

In some cases, configs of different steps point to the same widget, but with different settings. A typical case is when Customer's Canvas should display the first page in the first step and other pages in the other steps. Also, widget containers may remain the same at different steps, e.g. you can use a single left panel for all steps.

You can hide the left and bottom panels if needed.

By default, this wizard starts with the first step, but you can also override this behavior in the config.

### Setting Up Widgets in Steps

For a better understanding, let's take a look at the structure of a config file.

As we explained earlier, you must first place widgets on the panels and then refer to them when defining steps. The following examples illustrate how you can enable the Customer's Canvas widget.

``` js
{
   "widgets": [
        { name: "cc", type: "design-editor", params: { ... } }  /* the DesignEditor widget */
    ],
    ...
    "steps": [{
        title: "Front Page",
        mainPanel: {
            name: "cc"
        }
    }]
}
```

Now, let's discuss widgets in more detail.

## Widgets

A widget is a control that may appear in the main, tool, or bottom panels. For example, image editor, radio buttons, text block, etc.

Technically, a widget can be placed in any of these panels. In practice, we assume that, for example, the Design Editor will always be in the main panel, the options list will be in the left panel, and so on.

### Widget Configs

Every widget may contain the following properties:

- `type` - the widget type specifying the module that the editor will load.
- `name` - the name of a widget instance that can be referenced.
- `title` - the name displayed in the user interface.
- `prompt` - explanatory text.
- `description` - help tips (appears as a tooltip).
- `params` - additional parameters of this widget. By default, this is an empty object.

### Supported widgets

Currently, the following widgets are supported:

- [StaticText](widgets/static-text.md)
- [Html](widgets/html.md)
- [Gallery](widgets/gallery.md)
- [Ajax](widgets/ajax.md)
- [DesignEditor](widgets/design-editor.md)
- [Preflight](widgets/preflight.md)
- [ImageCarousel](widgets/image-carousel.md)
- [Group](widgets/group.md)
- [Option](widgets/option.md)
- [Checkbox](widgets/checkbox.md)
- [InputText](widgets/input-text.md)
- [Button](widgets/button.md)
- [FinishButton](widgets/finish-button.md)
- [Order](widgets/order.md)
- [Cart](widgets/cart.md)
- [Steps](widgets/steps.md)

There are no mandatory widgets, but without certain widgets, it is unlikely that you will be able to build a usable editor. In most cases, all your configs will contain **DesignEditor**, some **Option** widgets, and you will configure the output from the editor through the **Order** or **Cart** widget. Use the **ImageCarousel** to organize a preview section.

Another important widget is **Ajax**. It allows for receiving data from the server, such as a list of images, dynamically generated images, or any other data you may need.

## The Multi-step Editor Config

The config consists of the following sections:

- `logo` - the object containing a URL to the logo to insert in the steps section (see an example below). You may omit it.
- `language` - the localization language (like `en`, `fr`, `de`, `nl`, `ru`, etc.). You can find the translations in `configuration/locales/default.json`.
- `widgets` - the definitions of all widgets.
- `steps` - the definitions of every step that refers to the widgets for different panels.
- `showSteps` - if `false`, the steps panel is hidden. The default is `true`.
- `vars` - a container for the data you may want to use in the config.
- `defaultStep` - the `title` of a step from which you want to start your wizard. This is the optional parameter.

The config appears as follows:

``` js
{
    "logo": {
        "src": "https://customerscanvas.com/Aurigma/Theme3/img/common/logo_cc.svg"
    },
    "language": "en",
    "widgets": [
        { name: "cc", "type": "design-editor", /* other widget properties */ },
        { name: "approve", "type": "approval", /* other widget properties */ },
        { name: "options", type: "group", /* other properties */ }
    ],
    "steps": [
        /* step 1 - the personalization through Customer's Canvas */
        { 
            "title": "Personalize", 
            "mainPanel": {
                "name": "cc", /* takes the cc widget from mainPanels */
            }, 
            "toolPanel": {
                "name": "options" /* takes the options widget from toolPanels */
            }   
        },
        /* step 2 - the approval through Customer's Canvas */
        { 
            "title": "Approval",
            "mainPanel": {
                "name": "approve" /* takes the approve widget from mainPanels */
            }
        }
    ],
    "defaultStep": "Personalize" /* refers to the title; if omitted, the wizard starts from the first step */ 
}
```

Note that the **toolPanel** is not defined in the second step. This means that nothing will be displayed in the left panel.

If there is only one step, the navigation panel will be hidden.

The config may be dynamic, i.e. you can configure how one widget's settings depend on the user's input. For example, you may want to re-load a mockup in Customer's Canvas depending on the option value selected by a user.

See the [Dynamic Configs reference guide](dynamic-configs.md) for more details.

## Passing data to the config

It is often necessary to parametrize the config. For example, you may configure the editor to change the background image based on the user's choice in the [Gallery widget](widgets/gallery.md). However, it is unlikely that you want to hardcode a list of backgrounds in the config.

The first approach is to use the [Ajax widget](widgets/ajax.md) to fill the gallery with items. This approach is great when you want to update the list depending on the other choices.

However, you may often want to pre-fetch some data and pass it to the config before you initialize it. You can do this using the `vars` section.

You must add the JSON object describing your data to the `vars`:

``` json
{
    "vars": {
        "bands": [
            {
                "id": 0,
                "name": "The Beatles",
                "gentre": "Rock",
                "thumbnail": "http://example.com/1.jpg"
            },
            {
                "id": 1,
                "name": "Miles Davis Quintet",
                "gentre": "Jazz",
                "thumbnail": "http://example.com/2.jpg"
            }
        ]
    },
    ...
}
```

Based on this variable, you can write a dynamic config, which creates a proper structure of options.

``` json
{
    "widgets": [
        {
            "name": "band-gallery",
            "type": "gallery",
            "params": {
                "items": {
                    "{{#each vars.bands as band}}": {
                        "name": "{{band.id}}",
                        "title": "{{band.name + '(' + band.gentre + ')'}}",
                        "previewUrl": "{{band.thumbnail}}"
                    }
                }
            }
        }
    ]
}
```

All you need to do to apply another set of data is to modify the `vars` node of the config before initializing the editor with it.
