Layout Components
Buttons
identifier: stringstyle: primary|dashed|danger|link|-icon: stringhttps://antdv.com/components/icon/link: objectLink to other resourcehref: stringURL/URI of resourceexternal: booleanIf the link refers to a resource from another pagetarget: stringhttps://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#attributes
display_style: scrollable|block|flex|-options.flex: 1|-options.justify_content: ?stringhttps://developer.mozilla.org/de/docs/Web/CSS/justify-contentoptions.items: ?arrayarray of dropdown items. button will be displayed as a dropdown-buttonoptions.items[index].identifier: stringdropdown item will be rendered as a divider if emptyoptions.items[index].icon: ?stringhttps://antdv.com/components/icon/
Customizing the default Buttons
There are some default buttons present in every system. These Buttons handle basic functions like saving a resource, redirecting to /create and more. You can modify the behaviour of these buttons for each module by defining custom options in the bakery plan module definition.
Code example:
{ "bakery_resource_module": "module_identifier", "bakery_resource": { "buttons": { "button_key": { "<option>": "<argument>" } } }}The keys are:
savefor default ‘save’ button in create viewupdatefor default ‘save’ button in update/edit viewcontinuefor default ‘save and continue’ button in update/edit viewdeletefor default ‘delete’ button in show vieweditfor default ‘edit’ button in show viewcreatefor default ‘create’ button in index viewexcelfor default ‘excel’ button in index viewplansfor the default subscription plans button in the show view.
All buttons can take the following options:
display: Boolean(whether to display the button at all. Default: true)title: String(a custom title for the button. will be prefixed withbuttons.for translations)trigger: event_identifier(The event identifier to trigger when the button is clicked. this will change the functionality of the button and not trigger the default actions)style: primary|dashed|danger|link|-(Actually, this is a lie, most buttons don’t support this)
All of these options can be used individually or combined.
A note to trigger: if the button_key is save, update or contiune (the buttons in /edit and /create) the current
value of any fields will be sent to the prototype output of the event element.
Adding Custom Buttons
You can add custom buttons to the Buttonbar that can trigger any webhook. These Buttons will be shown before other
webhook buttons that where auto added by workflow elements using show_in_button_bar: true.
These Buttons are defined the same way and in the same place as customising the default buttons, and they support (mostly) the same options.
There are a few quirks to look out for though:
- Custom Buttons have to use an identifier that is not one of the keys for default buttons defined above!
- The
displayoption is ignored and does nothing when defined on custom buttons. Set ‘show_in’ to an empty array if you want to hide a button! - If the
triggeroption is not set, the identifier of the button will be used and treated as a webhook identifier - If the
titleoption is not set, the identifier of the button will be used as the translation suffix - If
show_inis not set, the button will show in every view. If it is set, it will respect the common module modes (e.b. “module.show”) - Using the
iconoption with a valid antd icon identifier changes the icon
Adding Buttons in Lists
You can define buttons in lists that will trigger webhooks with the current entity and field / row information of the clicked button. This enables you to get the specific tuple from the list that’s in the row where the corresponding button was pressed.
These Buttons will only show up in module.show.
The Webhook will receive the field & row information in the selector output.
It is an object with two keys.
fieldIdentifier <String>: Is the identifier of the list from where the button was triggered.rowIndex <String>: Is the index of the row from where the button was triggered.
Code example for a list field:
{ "identifier": "list_field", "type": "list", "options": { "buttons": [ { "title": "custom_button", "trigger": "webhook_identifier", "icon": "api", "position": 0 } ], "fields": [ { ... } ] }}This Code example will create buttons in the first col of the list that will trigger the webhook webhook_identifier.
The translation key of the th element will be buttons.custom_button. The button will show the api icon in the list.
Only the trigger key is required. All other keys are optional.
- if no
titleis set, the title will bebuttons.webhook_identifier. - if no
iconis set, a default icon will be used. Only valid antd icon identifiers are supported. - if no
positionis set, the button col will be appended as the last col in the list.
Headline
options.identifier: stringoptions.size: small|-options.align: center|-
Text
options.identifier: stringuses translation keymodule.texts.identifieroptions.text: stringfallback if no identifier is set (be aware that this can not be translated)options.has_border: booleanwhether the text component itself should have an extra border. Useful when using in combination withshow_inand in a col withoptions.borderless: true
Calendar
| Option name | Type | Default | Description |
|---|---|---|---|
available_views | array<ViewType> | ['year', 'month', 'week', 'day','list'] | View types (like “month”, “day”, etc.) that the user can choose from |
custom_views | array<ViewTypeDef> | [] | Definitions for custom views |
default_view | ViewType | month | Determines the view that is opened when opening the layout |
events | array<EventDef> | [] | The “event types” that this calendar will display |
editable | boolean | true | Determines if the events can be edited within the calendar by dragging and resizing |
height | string/int | 80vh | The height of the calendar |
week_numbers | boolean | false | Whether to show week numbers in day grid views (e.g. “month”) |
nav_buttons | boolean | true | Whether to show the navigation buttons |
filter_sidebar | boolean | true | Whether to show the filter sidebar |
Events
| Option name | Type | Default | Description |
|---|---|---|---|
identifier | string | Identifier of this event type. Used as a translation key. | |
module | module_identifier | The module containing the field defined in the field attribute | |
field | field_identifier | The field identifier of the field that contains the date of an event. This field needs to be of the types date,datetime or dateRange | |
color | #hex | #1890ff | The event background color |
icon | Icon | An icon that will be displayed within the event element | |
quick_create | boolean | If quick creation in calendar view is possible for the event | |
pre_filters | array<PreFilter> | Filters out entities before displaying | |
recurrence | string object | Determines a pattern by which this event will reoccur within the calendar (e.g. monthly). Reference. | |
text_color | #hex | #ffffff | The event text color |
title | string | The event title | |
recipes | Recipes | Recipes for all event attributes |
[ { "type": "calendar", "options": { "availableViews": [ "list7days" ], "custom_views": { "list7days": { "type": "list", "duration": { "days": 7 } } }, "default_view": "list7days", "editable": false, "events": [ { "identifier": "employeeHoliday", "module": "holidays", "field": "dateRange", "color": "#7db5ff", "pre_filters": [ { "column": "employee.id", "operator": "=", "recipe": "user().id" } ], "recipes": { "title": "'Birthday: ' + this.employee.name" } }, { "identifier": "employeeBirthdays", "module": "employees", "field": "birthdate", "color": "#4adeff", "text_color": "rgba(0, 0, 0, 0.85)", "pre_filters": [ { "column": "id", "operator": "=", "recipe": "user().id" } ], "recurrence": "yearly", "recipes": { "title": "'Birthday: ' + this.first_name + ' ' + this.family_name" } } ], "height": "50vh", "navButtons": false, "filterSidebar": false, "weekNumbers": true } }]Fields
See Layout -> Fields
Resource Table
module: module_identifierthe identifier of the module where resources will be loaded fromworkflow: webhook_identifierthe identifier of the workflow event if you want to use a workflow to fill the resource tablepre_filters: array<PreFilterObject>defines prefilters for the tablehide_crud_buttons: booleanhides the default ‘read’, ‘edit’, ‘delete’ buttons from the ‘actions’ colbuttons: array<Buttons>contains an array with button definitions that will be rendered in the ‘actions’ colselectable: booleandetermines if the entries of the table can be selected. Defaults totrue.columns: array<string>|ColumnDefarray of columns to be displayed/fetched. By default, all fields (except for list fields) will be shown. Only the visible columns are fetched by default. If needed, the list of fetched columns can be expanded when using aColumnDef` definition.bulk_actions: array<Buttons>array of buttons shown over the resource table that are hidden until an entry is selected.aggregates: array<AggregateDef>defines which aggregates should be loaded to be available in recipes.summary: array<SummaryDef>defines what the “summary”-rows at the bottom of the table should display.options: pageSize : intdefault number of entities which get shown upon load
An array of IDs of the selected entries, ordered by their position in the table, will be sent to the given webhook event.
Standard actions (currently only deletions) can still be used by using the “action” property.
Options for custom Buttons
title: Stringtranslation key. will be prefixed withbuttons.(title: test) will be passed asbuttons.testto the translator.icon: Stringname of the antd icon typetype: primary|secondary|dashed|danger|linkantd button typeevent: Stringwebhook event name that will be triggered on a click. The Event gets the resource the current row represents.
Example of a table with one custom Button and no CRUD Buttons:
{ "type": "resource_table", "options": { "module": "module_for_resources", "hide_crud_buttons": true, "buttons": [{ "title": "button_title_translation_key", "icon": "ant_icon_name", "type": "ant_button_type", "event": "webhook_event_name"} ]}}Example of a table with one custom bulk action and a custom “bulk-delete” button:
{ "type": "resource_table", "options": { "module": "<module_for_resources>", "selectable": true, "bulk_actions": [{ "identifier": "<Name of webhook event>", "icon": "<ant_icon_name>"},{ "action": "delete", "icon": "<ant_icon_name>", "style": "<ant_button_style>", "title": "_.bulk_delete"} ]}}Pre-Filters
schema of a pre-filter Object:
{ "column": "column_name", "operator": "operator", "value": "value"}Pre-filter Object using current module’s field:
{ "column": "column_name", "operator": "operator", "field": "field_identifier"}Pre-filter Object using recipe:
{ "column": "column_name", "operator": "operator", "recipe": "this.field_identifier + _context.context_field_identifier"}full example of a resource table using a ColumnDef object
{ "type": "resource_table", "options": { "module": "module_for_resources", "row_settings": { "recipes": { "style": "field_needed_for_recipe ? 'background: green' : ''" } }, "columns": { "display": [ "field_displayed_1", "field_displayed_2" ], "fetch": [ "field_displayed_1", "field_displayed_2", "field_needed_for_recipe" ] } }}schema of a computed style:
{ "type": "resource_table", "options": { "module": "manufacturers", "column_settings": { "status": { "recipes": { "style": "(status == 'good') ? 'background-color: green; color: white;' : '' || (status == 'bad') ? 'background-color: red; color: white;' : ''" } } }, "row_settings": { "recipes": { "style": "on_hold ? 'background-color: lightgray' : ''" } } }}AggregateDef schema
The key within the functions object determines the key the loaded aggregate can later be
referenced in recipes by the key $.aggregates.<function_name>.
The function can be every aggregate function that MySQL
supports (like count, sum, min, max, avg).
Example definition
{"functions": {"totalCount": { "function": "count", "fields": [ "id" ]}}}With pre-filters:
{ "pre_filters": [ { "column": "completed", "operator": "=", "value": true } ], "functions": { "completedCount": { "function": "sum", "fields": [ "completed" ] } }}SummaryDef schema
This definition consists of an object, whose keys are a field_identifier that determine
under which column the defined data should be displayed.
The SummaryDef is defined within an array, every new array element means another
summary row will be appended to the table.
Use the recipe option to calculate a fitting display of your data.
The type allows the following values:
text- Displays the data as text. Supports HTML.statistic- Displays the data as an AntDesign “Statistic” component.progress- Displays the data as a progress-bar. Needs to be a value between 0-100.
Example definition
{"completed": {"type": "text","recipe": "$.aggregates.completedCount"},"total_amount": {"recipe": "sum(this[*].total_amount)"}}Example definition of a progress bar summary field
{"completed": {"type": "progress","title": "completed","recipe": "round(sum(this[*].completed) / len(this[*].completed) * 1000) / 10"}}Workflow resource
You can get data from your workflow and put this to your resourceTable by using an event/webhook and a response/ResourceTable. Your workflow should return data structured like this:
{ "your_key": "data", "your_key_a": "data_a"}with the same keys as your resource_table
"columns": [ { "identifier": "your_key", }, { "identifier": "your_key_a", },]Differences to modules:
- No persistent data. ( No Edit / Delete or View)
- No row selection
- You have to use the input data in workflow to add searching, filtering and sorting functionalities
Example of Workflow Resource Table
{ "type": "resource_table", "options": { "workflow": "YourWorkflowsWebhookName", "columns": [ { "identifier": "your_key" }, { "identifier": "your_key_without_sorter", "options": { "no_sorter_in_entity_table": true } }, { "identifier": "your_key_without_search", "options": { "no_filter_in_entity_table": true } } ]}}What a workflow must consist of:
The event/webhook event which receives the following data:
result:Result countpageCurrent pagefilters : arraySearchfilter for columns Example: [column_key] => ( [0] => „searchstring“)sortField : stringColumn to filtersortOrder : stringSort Order ( Ascend / Descend )seach : stringGlobal search stringentity : arrayCurrent Resource / Entity
you could get these by adding a variable to output like:
Key | Value data | input:
An elment to get your data Array like source/entities or a just an op/recipe with data
And at least the response/resourceTable Element which needs following data:
Resource Data- Array of your DataCurrent Page- Number of your Current Page (You could use $data.page if you have this set up)Entity per Page- The number of entities per pageTotal- The total amount of entities (Input will be ignored if you use Auto Pagination)Auto Pagination- If it is set to True, your input array will be divided into the number of entries per page.

Collapsibles
Full example
{ "cols": [ { "span": 24, "components": [ { "type": "collapse", "options": { "title": "group", "accordion": true, "active_key": "my_key", "no_padding": true, "panels": [ { "title": "my_title", "key": "my_key", "components": [ { "type": "field_group", "options": { "fields": [] } } ] }, { "title": "my_title2", "key": "my_key2", "components": [ { "type": "field_group", "options": { "fields": [] } } ] } ] } } ] } ]}collapsible
title: Stringaccordion: booleandetermine if only one panel should be open at a timeactive_key: booleanselect the open panel when the page is loadedno_padding: booleanpanels: arraythe list of panels identified by their key
Panel
title: Stringkey: Stringused to reference a panel
Affix
A component where its content is “sticky”, meaning that it will be fixed on top of the page when scrolling past it.
top: intdetermines the offset from the top in pixelscomponents: array<Component>layout components placed in the affix bar
Widgets
With the widget component, different charts can be displayed. The current chart options include: Donut, Line, Column and Progress
chart: Stringdetermines the type of chart. This can be ‘donut’, ‘line’, ‘column’ or ‘progress’
Options for Donut
headline : Stringinstances : ArraylabelsBelow : booleanhideLegend : boolean
The instances array holds objects with the following values:
color : Hexlabel : Stringtrigger: TriggerObject(Optional)value : Int
The TriggerObject holds the following keys, all except type are optional:
type: StringRequired. Values:redirect|webhooktarget_module: String(module identifier)target_resource: Int(resource id)target_data: ObjectWill be passed directly into the body of the webhook requesttarget_action: StringModule action (e.g.module.create). Used for typeredirect, default ismoduletarget_anchor: StringAnchor tag, will be appended to url with leading#when using typeredirect
Donut Example
{ "type": "widget", "chart": "donut", "options": { "headline": "customer_lead", "instances": [ { "color": "#00BFFF", "label": "new_lead", "value": 30 }, { "color": "#5F9EA0", "label": "in_contact_with_customer", "value": 20 }, { "color": "#ADD8E6", "label": "lead_completed", "value": 20 } ] }}headline : Stringaxis : ArrayThis Array stores strings. They are the labels to be displayed on the x-axis. (e.g. year numbers)lines : ArrayThis Array stores objects. One object stores the data for one line.
The lines Array holds objects with the following values:
label : StringThe name of the linecolor : HexThe color in which the line should be displayedvalues : ArrayThis Array stores Int values
Line Example
{ "type": "widget", "chart": "line", "options": { "headline": "job_performance", "axis": [ "2004", "2005", "2006", "2007", "2008" ], "lines": [ { "label": "peter", "color": "#b80f0f", "values": [ 10, 20, 5, 60, 30 ] } ] }}Options for Column
headline : Stringaxis : ArrayThis Array stores strings. They are the labels to be displayed on the x-axis. (e.g. year numbers)columns : ArrayThis Array stores objects. One object stores the data for one column.
The columns Array holds objects with the following values:
label : StringThe name of the columncolor : HexThe color in which the column should be displayedvalues : ArrayThis Array stores Int values
Column Example
{ "span": 24, "components": [ { "type": "widget", "chart": "column", "options": { "headline": "test_data", "axis": [ "2004", "2005", "2006", "2007", "2008" ], "columns": [ { "label": "column1", "color": "#b80f0f", "values": [ 10, 20, 5, 60, 30 ] }, { "label": "column2", "color": "#fcf912", "values": [ 20, 8, 15, 50, 80 ] } ] } } ]}Options for Progressbar
headline : Stringmax : Intthis defines which value would be 100%current : Intdefines the current number of completed steps/products/…color : Hex
ProgressBar Example
{ "type": "widget", "chart": "progress", "options": { "headline": "realized_product", "current": 600, "max": 1800, "color": "#0fb83c" }}Navigation
The component navigation can calculate a route between two addresses. It has input fields and shows the arrival time. It can display an interactive map of the calculated route.
Options for Navigation
map: Stringset this value to “true” if you want the map to be displayed. Otherwise the component will only show time and distance.
Map
The map component displays a single address with a marker on an interactive map. It has no input fields and shows the map only, the address data has to be set via api.
Options for Map
address: Stringheight: Stringthis is css, so values could be 30vh, 300px or something elsemode: heatmap;heatmap shows additional heat information via a workflow response (*1)event: Workfloweventyou can use workflows to fill address data as its response
{ "type": "map", "options": { "recipes": { "address": "zip" }, "height": "40vh" }}Too large for expand/collapsePath is api/database/seeds/3b/workflows/setGeoDataForLeads.workflow.jsonToo large for expand/collapsePath is api/database/seeds/3b/workflows/getGeoDataForLeads.workflow.json