Service by Configuration
commands
{
id: "assign-person-to-study",
url: "/commands/:id",
method: "POST",
fields: [
{ key: "study_id", type: "integer" },
{ key: "title", type: "string", select: true, collection: ["Dr", "Mr", "Mrs", "Miss"], validate: { presence: true, included: :collection } },
{ key: "first_name", type: "string", validate: { presence: true, length: 255 } },
{ key: "last_name", type: "string", validate: { presence: true, length: 255 } },
{ key: "email_address", type: "email", label: "Email", validate: { presence: true, uniquness: true } },
{ key: "phone_number", type: "text", label: "Phone", validate: { presence: true } },
{ key: "category_id", type: "integer", select: true, label: "Category", collection: { url: 'people/categories', label: '#name', value: '#id' }, validate: { uniqueness: true } }
]
}
We could have basic types, string
, integer
etc. or richer types such as email
which imply certain validations with regards to the shape of the data, i.e. a regex.
The url is where to submit the command too, in this case /commands/:id
is a generic controller. Note that :id
refers to the command, “assign-person-to-study”, not a record id. The URL could also contain references to any of the form data, for example:
“/organisation/{{ organisation_id }}/people”.
In the case of category_id
the collection (possible selections) are to be fetched by the UI from the given URL, a JSON document is expected back and the label and value are the keys within the document to use, they could be specifyed as xpath or css selectors.
The collection
will determin the possible values for a field (it will usually, but does not have to be, be rendered as select or autocomplete). Possible configurations to collection
include:
static source
collection: { values: ["a", "b", "c"] }
collection: { values: { "a" => "1", "a" => 2, "c" => 3 }
HTTP source
collection: { url: "http://od.documas.eu", root: "#collection", label: "#name", value: "#organisation-code" }
collection: { url: "http://example.co,/service", format: "xml", label: "#name", value: "#id" }
root
, label
and value
are xpath-like selectors.
The url
source would work for a JSON document such as:
{
collection: [ { name: "ABC Corp", organisation-code: "1001PTO" }, ... ],
count: 102
}
SQL source
collection: { sql: "SELECT name,id FROM people", label: '#name', value: '#id' }
Does the SQL need to have values injected?
{
id: "update-person-assigned-to-study",
inherit: "add-person-to-study",
fields: [ { key: 'id'
}
{
id: "deassign-person-from-study",
fields: [
{ key: "study_id" },
{ key: "person_id" }
]
}
forms
id: "assign-person-to-study-form",
command: "assign-person-to-study",
ui: [
{ key: "names", label: "Names", type: "panel", content: [{ field: "first_name" }, { field: "last_name" }] },
{ key: "contact_details", type: "panel", content: [{ field: "email_address} }, { field: "phone_number" }] }
{ key: "save-button", type: "button", submit: true, label: "Save" }
]
content
could contain any kind of UI component, not just fields. This allows us to build any kind of UI, not just plain forms.
The above schemas would be fetchable by the UI as JSON and the HTML built client-side or the server could return HTML.
maybe one form can inherit from another:
{
id: "update-person-assigned-to-study-form",
inherit: "assign-person-to-study-form",
}
{
id: "deassign-person-from-study",
ui: [
{ type: "field", key: "study_id", type: "hidden" },
{ type: "field", key: "person_id", type: "hidden },
{ type: "button", label: "Delete" }
]
}
This would render as a button. How to put it at the side of a table row?
It might be better to not make this form specific but UI, so:
id: "assign-person-to-study-form",
ui: [
form: {
command: "assign-person-to-study",
fields: [
{ key: "names", label: "Names", type: "panel", content: [{ field: "first_name" }, { field: "last_name" }] },
{ key: "contact_details", type: "panel", content: [{ field: "email_address} }, { field: "phone_number" }] }
{ key: "save-button", type: "button", submit: true, label: "Save" }
]
]
This will allow us to use the same system to build any UI, not just forms.
Also one UI config can be embedable in another:
ui: [
tabs: [
{ name: '...', content: [:assign-person-to-study-form] },
{ ... }
]
]