Skip to main content

Questionnaire

Custom questionnaire runtime for xOpat v3.

IDquestionaire
Version0.1.0
Sourceplugins/questionaire-new

Capabilities

  • questionaire.edit — Edit questionnaire schema

IO capabilities

  • bundle-export (bundle) — Questionaire schema export
  • bundle-import (bundle) — Questionaire schema import
  • crud:answer (crud) — Questionaire answer

Additional configuration keys

directory

See include.json for details and defaults.

Documentation

Questionnaire plugin

Custom questionnaire runtime and schema designer for xOpat v3. End users fill in a multi-page form; authors (when permitted) open the designer to build the schema, attach per-page viewer setups and recorder animations, and export/import the schema bundle.

Plugin id: questionaire (declared in include.json; also the IO owner id used for ENV.client.io.bindings and the rights-capability prefix).

Editing permission gate

Whether the designer ("Show designer" button + designer panel) is available is gated on the client-side roles/capabilities layer (src/USER_ROLES.md), so an external authority can allow or disallow editing per user at runtime — no reload, no code change.

PieceValue
Capabilityquestionaire.edit (default allow)
Declared ininclude.json → top-level capabilities[]
Consumed inplugin.tspluginReady() subscribes via this.onCapabilityChange("questionaire.edit", …) and folds the result into the toolbar guard (_enableEditor && !_isExported && _canEdit)
Effect of deny"Show designer" button hides; any open designer collapses live

Default is allow, so with no role config the plugin behaves exactly as before. Locking is opt-in. (The static enableEditor option still applies independently — editing needs both.)

Configuring roles (deployment)

Roles live in the deployment env (e.g. env/env.default.json) under core.roles. Example — viewers cannot edit, editors can:

"core": {
"roles": {
"default": ["viewer"],
"definitions": {
"viewer": { "label": "Read-only viewer",
"deny": ["questionaire.edit"] },
"editor": { "extends": ["viewer"],
"grant": ["questionaire.edit"] },
"admin": { "extends": ["editor"], "grant": ["*"] }
}
}
}

Assigning roles to the current user (rights-resolver)

Any plugin/module can be the "rights resolver" — it decides which roles the user holds and calls assignRoles. Typically driven off the login token:

const user = XOpatUser.instance();
user.addHandler('login:core', () => {
const groups: string[] = decodeJwt(user.getSecret('jwt', 'core'))?.groups ?? [];
user.assignRoles(groups.includes('curators') ? ['editor'] : ['viewer']);
});

Testing from devtools (no reload)

XOpatUser.instance().assignRoles(['viewer']); // designer button disappears
XOpatUser.instance().assignRoles(['editor']); // designer button returns
XOpatUser.describeCapability('questionaire.edit'); // → { default: 'allow', declaredBy: 'questionaire', … }

UI gating only. This controls what the browser renders. Real authorization belongs in the embedding backend; never trust the client's role claim for server-side enforcement.

See also