feat(events): the step editor reworked, and event templates (MODULE_API 1.13.0)
All checks were successful
PR Checks / bot-tests (pull_request) Successful in 2m26s
PR Checks / client-build (pull_request) Successful in 2m44s
PR Checks / server-tests (pull_request) Successful in 20m38s

Rust PLAN_REDESIGNS §2 (U-3-U-6, F11; D192, D334), core half. Game-agnostic:
Module-uo's steps get the new controls and nothing else.

Contract (MODULE_API 1.12.0 -> 1.13.0, four optional additions):
- api.registerEventTemplates([{ id, label, description, inputs, build }]):
  inputs are params (<= 8); core checks them, calls build() (10 s), validates
  the result as a spec and answers an unsaved draft.
  POST /admin/events/catalog/templates/:templateId (admin, editor).
- a param's duration: 'minutes' (int/float only); core.lease's minutes has it.
- a lease's example for its value.
- an option row's note (<= 300 chars), shown under the chosen field.

Editor:
- no type tags or bare asterisks; a required field says so in words once a
  save has been tried with it empty (and the save stops before the round trip).
- boolean: toggle when required, [Not set] [Yes] [No] when optional (D334).
- a choice of two or three is a row of buttons (lease values, small sources).
- core.lease drawn as the chosen lease: picked by label; value by the lease's
  type, range, values and example; target picker over target.source (F11);
  minutes with the lease's longest hold.
- a timed step keeps its run open: a phase with no advance rule gets
  after: <longest hold> when a timed step is added; a sentence under any phase
  whose run can end sooner (U-6).
- Start asks "Publish and start" or "Start version N" when the working copy is
  ahead of the published version (draftAhead on GET/PUT/publish; U-5).
- New event can start from a module's template.
- core's own examples name no game (§0.9).

Swagger, routes.manifest/guards and engagement-triggers.json regenerated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
This commit is contained in:
2026-10-12 02:08:04 -05:00
parent 43f706c003
commit 3e243ce772
19 changed files with 1603 additions and 72 deletions

View File

@@ -3931,6 +3931,14 @@
"limits": {
"type": "object",
"additionalProperties": true
},
"templates": {
"type": "array",
"description": "Event templates (MODULE_API 1.13.0): id, label, description, owner and inputs (each shaped like an action param). build() is never served.",
"items": {
"type": "object",
"additionalProperties": true
}
}
}
}
@@ -4026,6 +4034,10 @@
},
"group": {
"type": "string"
},
"note": {
"type": "string",
"description": "Advice shown under the field while this option is chosen (MODULE_API 1.13.0). At most 300 characters."
}
}
}
@@ -4056,6 +4068,144 @@
]
}
},
"/api/v1/admin/events/catalog/templates/{templateId}": {
"post": {
"tags": [
"Admin · Events"
],
"summary": "Fill an event template in, and get back a draft",
"description": "A module may register named event templates (MODULE_API 1.13.0). The catalog lists them with their inputs; this route checks the inputs against the template, calls the module to build the plan, validates the plan as a spec and answers it as a draft: a title, a summary and a spec. Nothing is saved, and nothing about the template is kept: the editor opens the draft like any new event and the author saves it through POST /admin/events. A refusal of the inputs is a 400 naming each problem; a module that fails or builds a plan core cannot accept is a 502.",
"parameters": [
{
"name": "templateId",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "The draft",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"draft": {
"type": "object",
"properties": {
"title": {
"type": "string"
},
"summary": {
"type": "string",
"nullable": true
},
"spec": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"400": {
"description": "The inputs were refused",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"errors": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
}
},
"403": {
"description": "Not an admin or editor",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "No module registers that template",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"errors": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
}
},
"502": {
"description": "The module failed to build the plan, or built one core cannot accept",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"errors": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
}
}
},
"security": [
{
"cookieAuth": []
},
{
"bearerAuth": []
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"inputs": {
"type": "object",
"additionalProperties": true,
"description": "One value per declared input, keyed by its name"
}
}
}
}
}
}
}
},
"/api/v1/admin/events/price": {
"post": {
"tags": [