chore: custom content types design groundwork
This commit is contained in:
1 parent
58d58f5a04
commit
e6e088c963
12 files changed
+929
-3
No files matched your search
@@ -0,0 +1,23 @@
|
||||
# Content
|
||||
|
||||
Route: `/content/:key`. API: GET /v1/content-type/{key} · GET /v1/content-type/{key}/entry?page=&size=&sort=. Auth: any verified user.
|
||||
|
||||
Visual reference: `RenewCMS Screens Schema.dc.html`, groups "Content and entry list". Frames: `SchemaFrame.dc.html` mounted in `AppFrame.dc.html` (shell, sidebar, topbar, drawer). Every state is drawn in light and dark (theme switch) at 1440×900 (shown at 50%) and 390×844 (shown at 75%). Copy is exact. Strings in a Copy cell are separated by " · " and listed in reading order. Nothing is clock-sensitive.
|
||||
|
||||
### 5 Content navigation and entry list (group "5 Content and entry list", 9 states)
|
||||
|
||||
Route: `/content/:key`. API: GET /v1/content-type/{key}, GET /v1/content-type/{key}/entry. Auth: Any verified user.
|
||||
|
||||
The sidebar gets a "Content" group, one item per custom type (a default icon: types have no icon in the API). With more than 5 types it shows the first 5 and the selected one, then "Show all N"; long names truncate with the full name in a tooltip. On mobile the group is one collapsed row in the drawer. List: ID, up to 6 chosen field columns (default: first 4), Created, Updated, Updated by. Sort: ID, Created, Updated, either direction (default Updated, newest first). Page size 5, 25, 50, 100 (default 25). No filter or search. URL: /content/events?page=2&size=50&sort=created_at:desc (defaults omitted). The response carries total, page, size and sort; the summary, the pager and the review dialog use them.
|
||||
|
||||
| # | State | Trigger | Copy | Scope |
|
||||
|---|---|---|---|---|
|
||||
| 1 | Populated | /content/events. 7 entries, one page: no pager, only the count. | Content · Events · events · 7 fields · New entry · Sort by · Last updated · Columns · Edit content type · ID · Title · Starts on · Ends on · Online · Created · Updated · Updated by · 7 entries | Available now |
|
||||
| 2 | Paginated, 5 per page | /content/events?size=5. 37 entries. | Showing 1–5 of 37 · 5 per page · Page 1 of 8 (mobile) | Available now |
|
||||
| 3 | Columns menu | The Columns button. Popover on desktop, sheet on mobile. Created and updated always show. | Columns · 4 of 6 · Choose up to 6 fields to show. 4 selected. · Created and updated dates always show · Reset · Done | Available now |
|
||||
| 4 | Many types in the sidebar | 14 custom types. Long names truncate. Mobile shows the drawer with the group expanded. | Content · Frequently asked questions and answers (truncated) · Show all 14 · All content types 14 (mobile, collapsed) | Available now |
|
||||
| 5 | Loading | First load or retry. | (skeleton) | Available now |
|
||||
| 6 | Empty for this type | Total is 0. The hint points to New entry. | No entries yet · Use New entry to add the first event. Each entry follows the fields of this content type. · New entry | Available now |
|
||||
| 7 | Error | 500 or network failure. | Couldn't load entries · GET /v1/content-type/events/entry failed. Check your connection and try again. · Try again | Available now |
|
||||
| 8 | Forbidden (403) | The API answers 403. Unverified accounts are redirected to /register/pending before this. | You don't have access to Events · Your account can't open this content right now. If you think this is a mistake, ask an owner or an admin. · Go to Home | Available now |
|
||||
| 9 | Type not found | 404 content_type_not_found on /content/unknown. | Content type not found · It may have been deleted, or the address may be mistyped. · Go to Home | Available now |
|
||||
@@ -0,0 +1,27 @@
|
||||
# Entry editor
|
||||
|
||||
Route: `/content/:key/new`, `/content/:key/:id`. API: POST /v1/content-type/{key}/entry · GET/PUT/DELETE /v1/content-type/{key}/entry/{id}. Auth: any verified user.
|
||||
|
||||
Visual reference: `RenewCMS Screens Schema.dc.html`, groups "Entry editor". Frames: `SchemaFrame.dc.html` mounted in `AppFrame.dc.html` (shell, sidebar, topbar, drawer). Every state is drawn in light and dark (theme switch) at 1440×900 (shown at 50%) and 390×844 (shown at 75%). Copy is exact. Strings in a Copy cell are separated by " · " and listed in reading order. Nothing is clock-sensitive.
|
||||
|
||||
### 6 Entry editor (group "6 Entry editor", 13 states)
|
||||
|
||||
Route: `/content/:key/new, /content/:key/:id`. API: POST /v1/content-type/{key}/entry, GET/PUT/DELETE /v1/content-type/{key}/entry/{id}. Auth: Any verified user.
|
||||
|
||||
The form is generated from the schema, one control per field in schema order. Required fields carry * and the line "Fields marked * are required." Defaults are pre-filled on create and tagged Default. Saving replaces the whole entry.
|
||||
|
||||
| # | State | Trigger | Copy | Scope |
|
||||
|---|---|---|---|---|
|
||||
| 1 | New entry | /content/events/new. Online is pre-filled from its default. | New entry · Events · Fields marked * are required. · Default · Each entry needs a different title. · Between 1 and 5000. · Choose an option · Pick a date · Save · Cancel · New entry · Not saved yet | Available now |
|
||||
| 2 | Editing | /content/events/42. Save is disabled until something changes. | Lime plaster workshop · Events · Entry 42 · Saved · Delete · Cancel · Save · Created by · Updated by · Inès Duarte · 12 Oct 2026, 09:14 · Marta Alves · 15 Oct 2026, 11:02 | Available now |
|
||||
| 3 | Unsaved changes | Any edit. | Unsaved changes · 32 / 80 | Available now |
|
||||
| 4 | Markdown preview | The Preview tab of a rich text field. | Write · Preview | Available now |
|
||||
| 5 | Saving | PUT or POST in flight. Form dims. | Saving… | Available now |
|
||||
| 6 | Saved | 200. | Saved at 11:02 · Entry saved · "Lime plaster workshop" is up to date. | Available now |
|
||||
| 7 | Save failed | 500 or network failure. Values stay. | Save failed · Couldn't save the entry · Something went wrong on our side. Your changes are still here. Try again in a moment. · Try again | Available now |
|
||||
| 8 | Required fields empty | 422 invalid_entry: title: required, starts_on: required. The first field with an error takes focus. | Fill in Title. · Pick a date for Starts on. · Not saved | Available now |
|
||||
| 9 | Rule errors | 422 invalid_entry for max, type, max and options. One rule per field is shown at a time. | Title can be up to 80 characters. · 91 / 80 · Ends on must be a date, like 2026-11-21. · Capacity must be at most 5000. · Choose one of: Talk, Workshop or Meetup. · Not saved | Available now |
|
||||
| 10 | Duplicate unique value (409) | 409 invalid_entry: title: unique. | Not saved · Another entry already uses this title. Change it and save again. · Another entry already uses this Title. Enter a different one. | Available now |
|
||||
| 11 | Entry not found | 404 entry_not_found, for example after a delete elsewhere. | Entry not found · It may have been deleted by someone else. · Back to Events | Available now |
|
||||
| 12 | Schema changed since load | 422 invalid_entry: room: required, or unknown_field. The form is read-only until reloaded. | The fields of Events changed · A field was removed and a new required field, Room, was added after you opened this form. Reload the form to continue. What you typed here can't be saved against the old fields. · Reload form | Available now |
|
||||
| 13 | Delete entry: confirm | Delete. | Delete this entry? · "Lime plaster workshop" will be deleted from Events. This can't be undone. · Cancel · Delete entry | Available now |
|
||||
@@ -0,0 +1,40 @@
|
||||
# Schema: later
|
||||
|
||||
All states on this page are **Later**: relations, permissions and schema export and import are not built. Drawn now so the model and the layout are settled.
|
||||
|
||||
Visual reference: `RenewCMS Screens Schema.dc.html`, groups "Relations", "Permissions", "Export and import". Frames: `SchemaFrame.dc.html` mounted in `AppFrame.dc.html` (shell, sidebar, topbar, drawer). Every state is drawn in light and dark (theme switch) at 1440×900 (shown at 50%) and 390×844 (shown at 75%). Copy is exact. Strings in a Copy cell are separated by " · " and listed in reading order. Nothing is clock-sensitive.
|
||||
|
||||
### 7 Relation field and picker (group "7 Relations", 3 states)
|
||||
|
||||
Route: `/schema/:key, /content/:key/:id`. API: not built. Auth: Owner or admin (picker), any verified user (form).
|
||||
|
||||
All later. The model reads as two sentences, with a live preview of both sides. Three shapes: one to one, one to many, many to many.
|
||||
|
||||
| # | State | Trigger | Copy | Scope |
|
||||
|---|---|---|---|---|
|
||||
| 1 | Relation in the builder | A seventh type, Relation, in the type gallery. | Relation · Related content type · How are they connected? · One to one · Each Event has one Venue, and each Venue has one Event. · One to many · Each Event has one Venue. A Venue has many Events. · Many to many · Each Event has many Venues, and each Venue has many Events. · Each Event has one Venue · Each Venue has many Events · shown on Venue as the field "Events" | Later |
|
||||
| 2 | Relation in the entry form | Search and pick; chips for many. | Venue · Speakers · Search to add · An event can have many speakers. | Later |
|
||||
| 3 | Relation in the list | One chip, two chips and +N, or a dash. | One chip for a single relation. Up to two chips and a "+N" for many. Empty shows a dash. | Later |
|
||||
|
||||
### 8 Permissions grid (group "8 Permissions", 2 states)
|
||||
|
||||
Route: `/settings/permissions`. API: not built. Auth: Owner or admin.
|
||||
|
||||
All later. Rows are types, columns are actions, one role at a time. Built-in rows are locked. Mobile collapses to one card per type with four checkboxes.
|
||||
|
||||
| # | State | Trigger | Copy | Scope |
|
||||
|---|---|---|---|---|
|
||||
| 1 | Default: today's rules | Role User selected. Everything on, as today. | Permissions · What each role can do with each content type. · Today's rules are the starting point · Owners and admins edit the schema. Any verified user can read, add, edit and delete entries. · Owner · Admin · User · Read · Create · Update · Delete · Built-in types. RenewCMS sets these rules. · Schema (create, edit and delete content types): owners and admins only. Set by RenewCMS. · No changes · Discard · Save permissions | Later |
|
||||
| 2 | Changed, not saved | Two types restricted for the User role. | 4 changes not saved · Changed | Later |
|
||||
|
||||
### 9 Schema export and import (group "9 Export and import", 3 states)
|
||||
|
||||
Route: `/schema (dialogs)`. API: not built. Auth: Owner or admin.
|
||||
|
||||
All later. Dev-to-production flow: export a file, import it elsewhere, preview, same compatibility review as group 3, explicit confirm.
|
||||
|
||||
| # | State | Trigger | Copy | Scope |
|
||||
|---|---|---|---|---|
|
||||
| 1 | Export | Export on /schema. | Export schema · Download the fields of your content types as a file. Entries aren't included. · All content types · 3 content types · One content type · Choose which one · File name · renewcms-schema.json · Import this file on another RenewCMS site to create the same content types. · Cancel · Download file | Later |
|
||||
| 2 | Import preview | A file was chosen. | Import schema · renewcms-schema.json · 3 content types · Create 1, change 1, no change 1 · Recipes · New content type with 4 fields. · Events · Add 2 fields, remove Description. Events has 37 entries on this site. · Removes data · Press mentions · Same as on this site. · Existing entries are checked against the changes when you import. If any entry doesn't fit, nothing is imported. · Cancel · Import schema | Later |
|
||||
| 3 | Import refused | The server answers schema_incompatible. | Nothing was imported · Some entries on this site don't fit the imported fields. RenewCMS can't tell which entries. The flagged change can cause this. · Try again | Later |
|
||||
@@ -0,0 +1,78 @@
|
||||
# Schema
|
||||
|
||||
Route: `/schema`, `/schema/new`, `/schema/:key`. API: GET/POST /v1/content-type · GET/PUT/DELETE /v1/content-type/{key}. Auth: owner or admin.
|
||||
|
||||
Custom content types: an owner or admin defines a type (for example Events) made of 1 to 50 ordered fields; any verified user then writes entries. Everything about a type happens on one screen. Primary words: content type, field, choice list, entry. "Key" is kept for the API identifier. The key of a type is chosen at creation and never changes; the key and type of a saved field never change. Built-in types (Articles, Authors, Sites, Media, Users) are listed with a lock and a "Built-in" badge and open a read-only view. Non-owner, non-admin users see no Schema entry; a direct link shows a 403 page.
|
||||
|
||||
Visual reference: `RenewCMS Screens Schema.dc.html`, groups "Schema list", "Schema builder", "Review and delete", "Field types". Frames: `SchemaFrame.dc.html` mounted in `AppFrame.dc.html` (shell, sidebar, topbar, drawer). Every state is drawn in light and dark (theme switch) at 1440×900 (shown at 50%) and 390×844 (shown at 75%). Copy is exact. Strings in a Copy cell are separated by " · " and listed in reading order. Nothing is clock-sensitive.
|
||||
|
||||
### 1 Schema: list of types (group "1 Schema list", 6 states)
|
||||
|
||||
Route: `/schema, /schema/:key (built-in)`. API: GET /v1/content-type. Auth: Owner or admin.
|
||||
|
||||
Sidebar entry "Schema" for owners and admins only. Built-in types are listed with a lock and a Built-in badge, always after the custom ones. They open a read-only view. Sample data: the field counts of built-ins are illustrative.
|
||||
|
||||
| # | State | Trigger | Copy | Scope |
|
||||
|---|---|---|---|---|
|
||||
| 1 | Populated | An owner or admin opens /schema. | Schema · Content types and the fields they are made of. · New content type · Name · Key · Fields · Last updated · Built-in types are managed by RenewCMS. You can read their fields, but not change them. · Built-in · 3 content types · 5 built-in | Available now |
|
||||
| 2 | Loading | First load or retry. Skeleton rows appear after 150 ms. New content type is disabled. | (skeleton) · New content type (disabled) | Available now |
|
||||
| 3 | Empty: no custom type yet | GET /v1/content-type returns []. Built-ins are still listed below. | No content types yet · Create a content type to manage your own kind of content, like events or recipes. The built-in types stay as they are. · New content type | Available now |
|
||||
| 4 | Error | 500 or network failure on the list request. | Couldn't load content types · GET /v1/content-type failed. Check your connection and try again. · Try again | Available now |
|
||||
| 5 | Forbidden (403) | A user who is not owner or admin types /schema. There is no sidebar entry, so the page explains instead of redirecting. | You don't have access to Schema · Only owners and admins can change content types. You can still add and edit entries from the Content menu. · Go to Home | Available now |
|
||||
| 6 | Built-in type: read-only view | Click Articles in the list. No edit, no delete, no add field. | Articles · Built-in · Managed by RenewCMS · Articles is a built-in type. You can read its fields here, but you can't edit it, delete it or add fields. · Label · Key · Type · Rules · Entries of built-in types are managed from their own screens, like Articles and Authors. | Available now |
|
||||
|
||||
### 2 Schema builder (group "2 Schema builder", 16 states)
|
||||
|
||||
Route: `/schema/new, /schema/:key`. API: POST /v1/content-type, GET/PUT /v1/content-type/{key}. Auth: Owner or admin.
|
||||
|
||||
One screen, three regions: type name and key on top, ordered field list on the left, field inspector on the right, collapsible API preview at the bottom. Mobile: the list is the page, the inspector is a 92% sheet, the API preview is a sheet. Field keys and types of saved fields are locked; fields added since the last save can still choose both.
|
||||
|
||||
| # | State | Trigger | Copy | Scope |
|
||||
|---|---|---|---|---|
|
||||
| 1 | New type | /schema/new. One starter field is added because a type needs at least one. | New content type · Name · For example, Events · Key · events · Used in URLs and the API. Lowercase letters, digits and hyphens. It can't change after you save. · Fields · 1 of 50 · Add field · Field: Title · Label · Key · The name used in the API. Starts with a letter. Lowercase letters, digits and underscores. · Type · Required · An entry can't be saved with this field empty. · Unique values · Default value · Used when an entry is created and this field is left out. · Shortest · Longest · Counted in characters. Entries show a counter. · Save · Discard | Available now |
|
||||
| 2 | Editing an existing type | /schema/events with 37 entries. Key is locked, saved field keys and types are locked. | 37 entries use this content type. Changes are checked against them when you save. · Key (lock) · Used in the API, so it can't change. · Can't change after saving · Saved | Available now |
|
||||
| 3 | Locked key: tooltip | Hover or focus the locked key. | The key is used in URLs and the API, so it can't change after the type is created. | Available now |
|
||||
| 4 | Unsaved changes | Two fields added, Capacity changed, Description removed. Rows carry New and Changed badges; removal shows an undo row. | Unsaved changes · New · Changed · Description will be removed · Undo · Save · Discard | Available now |
|
||||
| 5 | Field errors | Checked as the user types, and again on Save. The row is outlined and shows an alert icon. Save is disabled until all are fixed. | 3 problems to fix · Give the field a label. · Lowest value can't be above the highest value. · Choices can't be blank. · Two choices are the same. | Available now |
|
||||
| 6 | Type-level errors | New type with no name, a one-letter key and no fields. | Give the content type a name. · Use 2 to 40 lowercase letters, digits or hyphens. · No fields yet · A content type needs at least one field. · 3 problems to fix | Available now |
|
||||
| 7 | Field key error | A field added since the last save has an invalid key (hyphen). Checked as the user types. Field keys use underscores; type keys use hyphens. | Key · Start with a letter. Use lowercase letters, digits and underscores. · 1 problem to fix | Available now |
|
||||
| 8 | Choice list editor | A Choice field is selected. Add, remove and reorder; blanks and duplicates are flagged per row. | Choices · 5 of 50 · Add a choice · Add · Add 1 to 50 choices. Each one needs a different name. Removing a choice that entries use will be refused when you save. · Choices can't be blank. · Two choices are the same. | Available now |
|
||||
| 9 | Keyboard reorder | Focus the grip, press Space. Up and Down move, Space drops, Esc cancels. Move up, Move down and Remove buttons are on the selected row. | Moving Ends on. Position 2 of 7. Press Up or Down to move, Space to drop, Esc to cancel. (live region, polite) | Available now |
|
||||
| 10 | API preview open | The panel at the bottom. Updates as fields change. Copy JSON copies the sample entry. | API preview · Where entries of this type live · A sample entry. Values come from each field's type and default. · Updates as you edit. Fields you add or remove here appear after you save. · Copy JSON · Copied | Available now |
|
||||
| 11 | Saving | PUT in flight. Inputs dim, Save shows the loader, nothing can be dragged. | Saving… | Available now |
|
||||
| 12 | Saved | 200. A toast confirms, the badges clear. | Saved at 11:02 · Content type saved · Events now has 8 fields. | Available now |
|
||||
| 13 | Save failed | 500 or network failure. Nothing was sent as saved; the edits stay. | Save failed · Couldn't save the content type · Something went wrong on our side. Your changes are still here. Try again in a moment. · Try again | Available now |
|
||||
| 14 | Key already taken | 409 content_type_key_taken on POST. | The key "events" is already used by another content type. Choose a different key. | Available now |
|
||||
| 15 | Schema incompatible | 409 schema_incompatible on PUT. The review dialog (group 3) closes into this state. Changes of the kinds that can cause it are marked. | Nothing was changed · Some entries don't fit the new fields, so the whole change was refused. RenewCMS can't tell which entries. The changes that can cause this are marked. · Review changes · Possible cause | Available now |
|
||||
| 16 | Offline | navigator.onLine is false. Edits are kept; Save is disabled. | You're offline. Changes will be saved when you reconnect. · Waiting for connection | Available now |
|
||||
|
||||
### 3 Schema change review and delete type (group "3 Review and delete", 7 states)
|
||||
|
||||
Route: `/schema/:key (dialogs)`. API: PUT /v1/content-type/{key}, DELETE /v1/content-type/{key}. Auth: Owner or admin.
|
||||
|
||||
The review opens on Save when the type already has entries (37 here). It is informational: the server decides compatibility. Destructive changes (removing a field or a choice, tightening a limit, making a field unique or required) carry a warning flag. Per-change entry counts and a full diff are later.
|
||||
|
||||
| # | State | Trigger | Copy | Scope |
|
||||
|---|---|---|---|---|
|
||||
| 1 | Review before saving | Save on a type that has entries. | Review changes to Events · Apply them to save the content type. · Add 2 fields, change 1, remove 1 · Events has 37 entries. Each one is checked against the new fields when you apply. · Add Speaker · Text, optional. · Add Room · Choice, required, default "Main hall". Existing entries get the default, so they still fit. · Change Capacity · Highest value goes from 5000 to 2000. · Entries may not fit · Remove Description · Entries stop returning its values. · Removes data · Flagged changes can be refused if existing entries don't fit. If that happens, nothing is changed. · Back to editing · Apply changes | Available now |
|
||||
| 2 | Applying | PUT in flight. Dialog cannot be dismissed. | Applying… | Available now |
|
||||
| 3 | Refused (schema_incompatible) | 409 schema_incompatible. States that nothing changed and names the kind of change that likely caused it, never an entry. | Nothing was changed · RenewCMS refused the changes because some entries don't fit the new fields. It doesn't say which entries. · Your content type is as it was · No field was added, changed or removed. · The change that can cause this in your edit · Possible cause · This kind of change is refused when an entry is over the new limit, a new required field has no default, a field becomes unique while entries share a value, or a removed choice is still in use. · Discard changes · Back to editing | Available now |
|
||||
| 4 | Review with counts and diff | Per-change entry counts and a full diff need an API that does not exist yet. | Affects 0 entries · Affects 37 entries · Affects 3 entries · Affects 31 entries · View full diff · Per-change counts and diff come later | Later |
|
||||
| 5 | Delete type: blocked | Delete content type on a type with entries. No confirm button. | You can't delete Events yet · A content type can only be deleted when it has no entries. · Events has 37 entries · Delete all of its entries first, then delete the content type. · Close · View entries | Available now |
|
||||
| 6 | Delete type: confirm | Delete content type on an empty type. | Delete Recipes? · Recipes has no entries. Its fields and its API routes will be deleted. This can't be undone. · Key: recipes · Cancel · Delete content type | Available now |
|
||||
| 7 | Delete type: server fallback (409) | 409 content_type_has_entries. An entry was added after the page loaded. | Recipes now has entries · Someone added an entry after this page loaded, so nothing was deleted. Delete the entries first, then try again. · Close · View entries | Available now |
|
||||
|
||||
### 4 Field-type gallery (group "4 Field types", 6 states)
|
||||
|
||||
Route: `reference board`. API: none. Auth: n/a.
|
||||
|
||||
One frame per type: inspector options, the entry form control (default and open states), the list cell with its empty state, the error message for each rule, and the filter widget. Filters are later: filtering on custom fields is not in the API. Mobile drops the inspector column (the builder frames show it as a sheet).
|
||||
|
||||
| # | State | Trigger | Copy | Scope |
|
||||
|---|---|---|---|---|
|
||||
| 1 | Text | type: "text" | Text · Short text, like a title or a name · Shortest · Longest · characters · 74 / 80 · Fill in Title. · Title must be text. · Title needs at least 3 characters. · Title can be up to 80 characters. · Another entry already uses this Title. Enter a different one. | Available now |
|
||||
| 2 | Rich text | type: "richtext" | Rich text · Long text with formatting, written in Markdown · Write · Preview · Markdown. Switch to Preview to check the result. · 86 / 5000 · Not available for rich text. (Unique) | Available now |
|
||||
| 3 | Number | type: "number" | Number · Whole or decimal numbers · Lowest value · Highest value · Enter a number · Between 1 and 5000. · Description must be a number. · Capacity must be at least 1. · Capacity must be at most 5000. | Available now |
|
||||
| 4 | Yes or no | type: "boolean" | Yes or no · An on or off switch · On by default · Yes or no fields have no limits. · Not available for yes or no fields. (Unique) · Choose yes or no for Online. · Online must be yes or no. | Available now |
|
||||
| 5 | Date | type: "date" | Date · A calendar day, without a time · Earliest date · Latest date · Pick a date · Pick a date for Starts on. · Starts on must be a date, like 2026-11-21. · Starts on can't be before 1 Jan 2026. · Starts on can't be after 31 Dec 2027. | Available now |
|
||||
| 6 | Choice | type: "select" | Choice · One option from a list you define · Choices · Choose an option · Choose one of: Talk, Workshop or Meetup. · Another entry already uses this choice for Category. | Available now |
|
||||
Reference in new issue
Block a user