Working with designs directly
- 9 minutes to read
Let's consider the following scenario. You have a list of design templates prepared by your artwork team. You want to let the user to choose one of them, open it in the editor, modify it, and save a personalized copy. After that, you want to export the result as a JPEG or PDF file.
Here are some of situations when this scenario makes sense:
- Creating digital images (i.e. not print products) - for example, personalized images for Instagram or Facebook marketing campaigns.
- As a part of the online ordering process, when the designs are not a part of the product catalog (i.e. a product is "Letter-size, 4/4, 80 lbs. cardstock" rather than "Wedding Invitation - Cherry Blossom template").
- As a part of a direct mail or other variable data printing scenario when a user modifies a template by adding their own variable fields or other elements before populating it with a data.
No matter what the situation is, to implement this scenario, you need to solve these tasks:
- Display a list of designs.
- Load a specified design to the editor.
- Save a private design (i.e. a design personalized by a specific user).
Design List
As you may have learned from What are BackOffice services, a service that is responsible for all CRUD operations (including listing all designs) is called Asset Storage API. Use the Designs_GetAll method to get a list of the designs.
Filtering a design list
If you call this endpoint without any parameters, you will get all designs available in your tenant. However, you usually need to show a limited list of designs, e.g. only letter-size format or the designs belonging to a particular category. Let's take a look at the filtering options.
By folders
You may organize your designs in folders in accordance to the structure of your products or categories. For example, you may have folders like
\Commercial Printing
\Business Cards
\Letter-size Flyer
\Tabloid-size Poster
...
\Stickers
\Rectangular
\1x1
\2x2
\2x3
\3x3
...
\Ellipse
\1x1
\2x2
\2x3
...
In each folder you will have designs for a specific size and product type.
When a user orders, say, a letter-size flyer, you need to use a path
parameter of Designs_GetAll and send /Commercial Printing/Letter-size Flyer
.
You may also send an includeSubfolders
parameter (true
or false
) to specify whether you need to return files only from this particular folder or select designs from subfolders.
If you prefer to build a treeview and make the navigation similar to a file manager, you may prefer to use another endpoint - Designs_GetFolder. Unlike Designs_GetAll, you get not only a list of entries in a folder, but also a list of all subfolders. Also, this endpoint has fewer filtering features.
By custom fields
Designs stored in Asset Storage support custom fields. At the moment, we only allow adding them through the API via the Designs_Update endpoint. It allows for adding an arbitrary JSON object as a customFields
dictionary to any design, like this:
{
"Product Type": "Flyer",
"Category": "Retail"
}
Then, you may pass a JSON object that has been made into a string to the customFields
parameter to the Designs_GetAll endpoint to return only those values that match the specified fields. For example, to return all designs that have Product Type equal to Flyer, you need to pass the {"Product Type": "Flyer"}
string to customFields
.
By a part of a name
Sometimes you may want to have a search bar where the user can type in a name and narrow down a list of designs to only those that contain a specified text as a part of the design name. To do this, use the search
parameter of the Designs_GetAll endpoint.
Pagination
Let's imagine that you have a few hundred designs in a single category. You most likely don't want to show them at once and would like to implement a pagination or "infinite scroll" in the design list browser.
To do this, use two parameters - take
- how many items you want to fetch per one request and skip
- how many items you have already received and want to skip.
Note, the response always looks like this:
{
"total": 123,
"items": [...]
}
The total
always contains the real amount of items that match the filtering parameters, even if the take
is a smaller value (and therefore the items
array has fewer elements). This way, you may use it to calculate the number of pages.
Design items
Each entry you receive using this API contains a number of fields, for example:
- ID
- Name
- Last modified date
- Custom fields
- ...and others
In addition, it contains the metadata, which is mainly used by Customer's Canvas internally. You may still find it useful, for example, how many surfaces (pages) it has or what are the dimensions of the design.
It also includes a link to a preview - a crucial element for every design browser interface. We will discuss them in the next section.
Previews
Some assets, like designs, images or fonts, may have previews. Previews are generated only once and information about them is automatically added to the asset metadata. If you update an asset file (for example, modify the design), the preview is invalidated and automatically removed.
Each asset may contain more than one preview. For example, it may be a preview for an admin app or for a storefront, or perhaps a storefront app may require a small thumbnail and a larger preview.
"previews": {
"<namespace>-<name>": {
"id": "6064221fe810853799cbf2f3",
"name": "<name>",
"namespace": "<namespace>",
"width": 248,
"height": 141,
"url": "<URL>"
}
}
Here, the <namespace>
is an unique application name, for example, online-store
, backoffice
, mystore
, etc. The <name>
specifies a preview type (like thumbnail
, websized
, tiny-icon
, etc).
To make Customer's Canvas generate a preview, you need to use the Asset Processor API. It has the DesignProcessor_PreparePreview endpoint, where you can specify the namespace
, name
, width
, height
and some other parameters, and then it will generate the preview and update the metadata.
You don't have to re-request a design element after that. This endpoint returns a preview as a stream that can be sent to a browser right away. Also, there is a version of this endpoint that returns the result as a URL - DesignProcessor_PreparePreviewUrl.
This way, the workflow is the following:
- Request a design entry.
- Check whether the
metadata.preview["<your_namespace>-<preview_name>"]
is not empty. - If you find the preview information, read its
url
property and insert acquired url into the<img>
tag. - Otherwise, send a request to Asset Processor and use its output instead of the URL extracted from metadata. Customer's Canvas will automatically add preview information to the design metadata, and it will be recognized the next time Step 2 is performed.
C# Example
You can find an example of how the design browser can be implemented in this demo app:
https://github.com/aurigma/CCHSample-BackOfficeIntegration-aspnetmvc
See the Demo 1 section.
Editor
We now have a page displaying a list of designs we need. Next, you want to allow a user to click on a thumbnail and open the appropriate design in an editor.
This is how you do it:
- Prepare an HTML page where the editor should be hosted.
- Integrate a UI Framework to this page.
- Create a UI Framework config for your editor where you will pass a design ID and other settings.
HTML page
Depending on your needs, this can be the same page with a list (e.g. the editor may be opened in a popup dialog) or a separate page. You should insert a <div>
element that will be a container for our editor. Adjust its CSS styles to set the right width and height and ensure that it is large enough to hold the designer interface on different screen sizes.
UI Framework
Before reading further, you may want to read the About UI Framework article for a better understanding of how it works.
You need to add the code that loads a UI Framework to this page and load the editor to the container <div>
. This setup code will be pretty much the same for any Customer's Canvas editor and UI Framework configuration.
It is better to organize this code to store the UI Framework separately (in a file system or even a database). This way, you will have a universal editor page that can be reused for quite different scenarios and editors.
Config
This config will most likely have a simple structure - it will consist of one or two steps (the second one is a preview/approval screen). The primary step will hold only the design-editor widget in a main panel.
The design-editor config consists of two important parts:
- A product definition
- An editor config
You can simply set the design ID as the product definition. Alternatively, you can put a full path, including a slash character in the beginning (e.g. /Invitations/Cherry-Blossom
). Both approaches have their pros and cons. If you are using ID, it will always remain the same event if you move a design to another folder. On the other hand, file names are easier in troubleshooting and it is also possible to write some code based on some naming conventions.
The editor config is a large JSON object containing settings of the editor such as a configuration of a toolbox, whether to turn on/off certain buttons, specify a list of fonts available in the editor and many others. It is recommended to familiarize yourself with the User Interface section for a better understanding what exactly you can configure and see the Editor config reference for a full list of available keys in this JSON.
Other than the design-editor widget parameters, you also need to know how to write UI Framework configs in general. The following articles may help:
Example
The Embedding the Design Editor article gives an explanation of how to add an editor to a page in practice.
Saving results
Fortunately, this part isn't complicated. The editor has a JavaScript method that allows for saving the result. When you do this, a private design is created in the Asset Storage. You receive its ID, which you can use to do the further operations:
- Generate a print file
- Insert Variable Data into the file
- Re-open it in the editor
- ...
Along with the private design (state) ID, you also receive URLs for the proof images and print files. If you just need to display a proof image (e.g. in a shopping cart) or download a PDF file, just use them without any additional APIs.
You now have an understanding of all the tasks we need to accomplish to implement this W2P scenario. Let's take a look at how to add a design editor to your page in practice.