Skip to main content

Template Steps Customization

The Scaffolder Wizard allows you to define a set of input fields displayed to the user, by defining them inside the template.yaml.

To let users fill out the information required by your template, you will need to use value pickers. When you define a new field inside template.yaml, you are also defining the value picker that will help the user to fill the field. Value pickers are then rendered to HTML input fields, using React Json Schema library to render a form from a YAML file, providing an wide set of pickers that may fit your use case. On top of React Json Schema, Witboost provides an additional set of pickers tailored to the platform, allowing to perform more complex operations and enrich your templates leveraging the potential of the platform and its catalog.

Please refer to the Picker section for more information about each Witboost picker.

note

Some of the pickers listed below have an additional property called ui:style that you can use to customize the appearance of the component. By adding some CSS rules to it, you can change the appearance of the single pickers.

Use this feature with care, since it could break the page behaviour.

Most of the pickers listed below can also be hidden by setting their property ui:widget to hidden.

Layout

Object Layout

To group together pickers, you can use an object that will hold all of their values together. When defining an object, you can just list all of its children as properties:

ObjectExample:
type: object
title: My Object
description: an example object
required:
- name
- dataType
properties:
name:
type: string
title: Column Name
dataType:
type: string
default: TEXT
title: Column Data Type
enum:
- TEXT
- NUMBER
- DATE
- BOOLEAN

If you need just to group elements together, without showing a title or a description, you can just set the ui:option called displayTitle to false:

ObjectExample:
type: object
title: My Object
description: an example object
ui:options:
displayTitle: false
required:
- name
- dataType
properties:
name:
type: string
title: Column Name
dataType:
type: string
default: TEXT
title: Column Data Type
enum:
- TEXT
- NUMBER
- DATE
- BOOLEAN

Horizontal Layout

If you want to display different pickers inside an object horizontally instead of vertically, you can simply add the field ui:ObjectFieldTemplate: HorizontalTemplate. In this way, all the pickers inside said object will be displayed one after the other horizontally.

You can also specify additional options using the ui:options value:

  • elementsPerRow: how many elements per row should be displayed (this is honored if the overall width is less than the screen resolution)
  • minElementWidth: the minimum width of every element in the layout (default 200)
  • displayTitle: if false, title and description are not shown even if defined (default true)

As an example, you can display different pickers horizontally with 8 elements per row by defining:

HorizontalExample:
type: object
ui:ObjectFieldTemplate: HorizontalTemplate
ui:options:
elementsPerRow: 8
properties: ...

It could happen that fewer than 8 elements are displayed if the screen does not have 8 * minElementWidth pixels available. To fix this, you can try reducing the minimum elements width to 150:

HorizontalExample:
type: object
ui:ObjectFieldTemplate: HorizontalTemplate
ui:options:
elementsPerRow: 8
minElementWidth: 150
required:
- name
- dataType
properties: ...

You can also use the minElementWidth the other way around: by increasing it over 200, you can make elements go to a new line if there is not enough space for them.

Table Layout

Sometimes, you would like to display pickers that collect inputs needed to fill a table-like structure (e.g. when asking the user to insert a schema for a table). In this case, you usually would like to have an array of elements, each containing multiple values, but rendering that to the user in a friendly way can be very difficult.

To improve this, you can define a layout for such arrays by leveraging two custom layouts:

  • ui:ArrayFieldTemplate: ArrayTableTemplate that should be added to the array component
  • ui:ObjectFieldTemplate: TableRowTemplate that should be added to the items of the array

The resulting definition would be something like:

SchemaExample:
title: Schema Example
description: A Schema Example
type: array
ui:ArrayFieldTemplate: ArrayTableTemplate
ui:options:
maxDescriptionRows: 2
default: []
items:
type: object
ui:ObjectFieldTemplate: TableRowTemplate
required:
- name
- dataType
properties:
name:
type: string
title: Column Name
dataType:
type: string
default: TEXT
title: Column Data Type
enum:
- TEXT
- NUMBER
- DATE
- BOOLEAN
constraint:
type: string
title: Constraint
enum:
- PRIMARY_KEY
- NOT_NULL
- UNIQUE
- NO CONSTRAINT
dataLength:
type: integer
title: Column DataLength
precision:
type: integer
title: Column Precision
minimum: 1
scale:
type: integer
title: Column Scale
minimum: 1

When displaying items in a table, the description of the single fields are moved to the column headers. Since column headers could be stretched in case of long descriptions, you can configure how many lines of description are displayed at maximum by leveraging the ui:option called maxDescriptionRows (default 3).

Conditional Fields

If you need to display a picker only when a condition is met, you can leverage the React Json Form "if-then-else" functionality.

As an example, think about a case where you have a selector for the data type, and in case the selected value is a string, you want the user to insert also its length. You can achieve this behaviour leveraging the allOf feature:

The allOf property must be declared either at the root properties field or in any defined object field where a properties field is declared.

properties:
dataType:
type: string
title: data type
enum:
- array
- binary
- boolean
- date
- float
- int
- string
- varchar
allOf:
- if:
properties:
dataType:
anyOf:
- const: varchar
- const: string
required: [dataType]
then:
properties:
length:
title: Length
type: number
description: Maximum length of the string

You can also add multiple allOf clauses based on the selected values:

dataType:
type: string
title: data type
enum:
- array
- binary
- boolean
- date
- float
- int
- string
- varchar
allOf:
- if:
properties:
dataType:
anyOf:
- const: varchar
- const: string
required: [dataType]
then:
properties:
length:
title: Length
type: number
description: Maximum length of the string
- if:
properties:
dataType:
const: float
required: [dataType]
then:
properties:
columnScale:
title: Scale
type: number
description: The scale of the floating point number

Validation

Since there are default validations (like checking if the ID of the DP already exists), in order to achieve the best user experience, you need to define name, domain, and identifier in the same page of the template (also there needs to be a dataproduct field if you are creating a component definition).

Target repository for the template

At one point in the creation time, you will need to define on which (remote) location the template is going to exist. Currently, you need to provide either totally empty repository (non-initialized one, this means also without the README file) or non existing one (which will be created for you).

tip

When using GitLab and providing ExistingGroup/NonExistingGroupOne/NonExistingGroupTwo in the User/Group field, the NonExistingGroupOne and NonExistingGroupTwo will be created automatically(if the token provided has the corresponding rights).

Insert documentation in your Entities

You can document any type of entity (Templates, Systems, ...) following this procedure.

Create a mkdocs.yml file in the root of your repository with the following content:

site_name: 'example-docs'
nav:
- Home: index.md

plugins:
- techdocs-core

Update your component's entity description by adding the following lines to its catalog-info.yaml in the root of its repository:

metadata:
annotations:
backstage.io/techdocs-ref: dir:.

The backstage.io/techdocs-ref annotation is used by TechDocs to download the documentation source files for generating an entity's TechDocs site.

Create a /docs folder in the root of your repository with at least an index.md file in it. (If you add more markdown files, make sure to update the nav in the mkdocs.yml file to get proper navigation for your documentation.)

note

Although docs is a popular directory name for storing documentation, it can be renamed to something else and can be configured by mkdocs.yml. See https://www.mkdocs.org/user-guide/configuration/#docs_dir

The docs/index.md can for example have the following content:


# example docs

This is a basic example of documentation.