Configuration
Declare a settings form and Prism builds it in the dashboard.
A config class describes a settings form. Prism draws the form on the Configs page, saves what the admin enters and gives your code the values. You write no web code.
Put config classes in resources/config/. Each file is one group of settings.
import { Configs } from "#prism/modules";
export class SettingsConfig extends Configs {
constructor(prism) {
super(prism, { name: "settings", label: "Example", description: "Sync and alert settings" });
}
schema() {
return {
api: {
type: "section",
label: "API",
fields: {
token: { type: "secret", default: "", label: "API Token" },
sync_every: { type: "number", default: 5, label: "Sync Every", unit: "sync_unit" },
sync_unit: { type: "select", default: "minutes", label: "Unit", options: [{ value: "minutes", label: "Minutes" }, { value: "hours", label: "Hours" }] }
}
},
alerts: {
type: "section",
label: "Alerts",
fields: {
enabled: { type: "boolean", default: false, label: "Send Alerts" },
product: { type: "select", default: "", label: "Product", source: { module: "core", endpoint: "/products", label: "name", value: "id" }, empty: "No products found", visibleWhen: { field: "enabled", value: true } }
}
}
};
}
}| Option | What it does |
|---|---|
name | The group ID. Used to read and save the values. |
label | The heading shown on the Configs page. Defaults to name. |
description | A line under the heading. |
preview | An image URL shown beside the group. |
Field Types
| Type | Saved as | Control |
|---|---|---|
string | string | Text input. |
text | string | Multi-line text. |
secret | string | Hidden input with a show button. |
number | number | Number input. |
boolean | boolean | Switch. |
select | string | Dropdown. |
multiselect | string[] | Dropdown with several picks. |
tags | string[] | Free text chips. |
color | string | Colour picker with a hex value. |
list | object[] | Rows of sub-fields, added and removed by the admin. |
Any other type throws when the module loads. A field can also be a bare value, such as retries: 3, which becomes a number field with that default.
Field Options
| Option | What it does |
|---|---|
default | The value before anything is saved. |
label | The field label. Defaults to the key. Leave out description so rows stay aligned. |
options | { value, label } choices for select and multiselect. |
source | Load choices from a route instead of options. See below. |
empty | Text shown when source returns nothing. The dropdown stays disabled. |
unit | The key of a select to join onto this number, such as minutes or hours. |
visibleWhen | Only show the field when a condition is true. |
disabledWhen | Grey the field out when a condition is true. |
item | The sub-fields of a list. |
migrate | (stored) => value, used once to fill a new key from older saved settings. |
Sections
A section entry groups fields under a heading. It holds its own fields object and is not a value itself, so keys inside it are read as if they were at the top level.
Conditions
visibleWhen and disabledWhen compare another field in the same group:
| Condition | True when |
|---|---|
{ field: "mode", value: "auto" } | mode is "auto". |
{ field: "mode", not: "off" } | mode is anything but "off". |
{ field: "mode", in: ["a", "b"] } | mode is one of the list. |
{ field: "mode", notIn: ["a", "b"] } | mode is none of the list. |
{ field: "token", notEmpty: true } | token has a value. |
{ field: "enabled" } | enabled is set and not false. |
Options From a Route
source fills a dropdown from a route that returns { rows: [...] }:
source: { module: "core", endpoint: "/products", label: "name", value: "id" }module defaults to your own module. label and value name the columns to use. Prism adds limit=500 to the request.
When the route returns nothing, the dropdown shows the empty text and stays disabled. Never fall back to a text input or a "None" option.
Lists
rules: {
type: "list",
label: "Rules",
default: [],
item: {
name: { type: "string", default: "", label: "Name" },
valid: { type: "boolean", default: true, label: "Type", states: ["Allow", "Block"] },
message: { type: "string", default: "", label: "Message", labelBy: { field: "valid", on: "Allow Message", off: "Block Message" } }
}
}List sub-fields take the same options, plus:
| Option | What it does |
|---|---|
states | Labels for a boolean's on and off states. |
labelBy | Change the label based on another sub-field. |
wide | Span two columns in the row. |
Reading Values
const settings = this.prism.modules.config.values("example", "settings");
const token = this.prism.modules.config.value("example", "settings", "token");values returns every field in the group, with defaults filled in for anything not saved yet. Values are converted to their type on save, so a number is always a number and tags are always an array.
When an admin saves, Prism fires config.saved with { module, group, values }. Listen for it to react straight away:
export class SettingsSaved extends Events {
constructor(prism) {
super(prism, { name: "settingsSaved", event: "config.saved" });
}
async run({ module, group, values }) {
if (module === "example" && group === "settings") await this.prism.modules.handlers.get("example", "sync").restart(values);
}
}Settings are stored in the database with the rest of Prism's settings, under module:<id>.