diff --git a/.changeset/12484-approvals-served-page.md b/.changeset/12484-approvals-served-page.md deleted file mode 100644 index 9949a22795..0000000000 --- a/.changeset/12484-approvals-served-page.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@object-ui/console': patch ---- - -The Approvals Inbox opens a request on the page the platform serves for it, and its side sheet is gone (objectui#12484). - -A row, a mobile card, Enter on the focused row, and a notification's `?request=` deep link now open the request's record page: the `sys_approval_request_detail` page `@objectstack/plugin-approvals` serves, on the console's standard record route. That page shows the request's title (the flow's label), its decision panel (the declared amount and snapshot summary, the approvers, the step line and the decisions), its highlights, its target record, and its timeline. The deep link takes its own place in the browser history, so Back returns to where the reader came from; from a row, Back returns to the inbox. - -The inbox's own request sheet is deleted. Its quick paths stay: inline approve and reject, bulk decisions, filters, sorting and keyboard navigation. diff --git a/.changeset/13076-nav-visible-data.md b/.changeset/13076-nav-visible-data.md deleted file mode 100644 index a3edebb4a5..0000000000 --- a/.changeset/13076-nav-visible-data.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@object-ui/types': minor ---- - -`NavigationItemSchema` now refuses a navigation entry whose `visible` reads `data` but which declares no `dataSource`, as `@objectstack/spec`'s `NavigationItemSchema` already does (objectui#13076). The rule is the spec's own exported `navItemVisibleDataNeedsDataSource`, chained on every navigation arm (the flat arm and the `doc` arm), not restated, so `objectui validate` and the platform's save door refuse the same entry with the same issue at `visible`. - -This narrows the published validator toward the spec: an entry such as `{ id: 'nav_envs', type: 'object', objectName: 'sys_environment', visible: 'data.total == 1' }` validated clean here and failed at publish; it is now refused here too. Declare the `dataSource` whose bound value `visible` reads, or gate on `current_user` or `features` instead. An entry with a `dataSource`, or whose `visible` is a boolean, absent, or reads no `data`, is unaffected. diff --git a/.changeset/13119-org-admin-holders-docs.md b/.changeset/13119-org-admin-holders-docs.md deleted file mode 100644 index 0c3e597599..0000000000 --- a/.changeset/13119-org-admin-holders-docs.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@object-ui/app-shell': patch ---- - -The README's "Setup half of an item" now says what objectstack's shipped organization administrator set does on the assignment objects: it creates and removes rows on `sys_user_position` and `sys_user_permission_set` and never edits them, bounded on the server by the delegated-administration gate, so that administrator sees Add and Remove on a position's and a permission set's holders. No behaviour change. diff --git a/.changeset/13121-package-edit-dependencies.md b/.changeset/13121-package-edit-dependencies.md deleted file mode 100644 index a64964871f..0000000000 --- a/.changeset/13121-package-edit-dependencies.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@object-ui/app-shell': patch ---- - -The package edit dialog (Studio / Setup) now edits a package's `dependencies`. The row is no longer locked once the package exists, and saving sends it to `PATCH /api/v1/packages/:id` beside the name, description and version when the author changed it; emptying it sends `{}`, which clears the declaration. The server's `400 VALIDATION_ERROR` for a malformed row and `422 WRITABLE_PACKAGE_REQUIRED` for a read-only package show in the dialog, which stays open. diff --git a/.changeset/13183-bulk-confirm-text-envelope.md b/.changeset/13183-bulk-confirm-text-envelope.md deleted file mode 100644 index 15e46fc1fe..0000000000 --- a/.changeset/13183-bulk-confirm-text-envelope.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@object-ui/types': patch -'@object-ui/plugin-grid': patch ---- - -The bulk action confirm step reads `confirmText` as a string or as a `{ dialect: 'template', source }` envelope (objectui#13183). - -`@objectstack/spec` is making a bulk action's `confirmText` a `template` slot (objectstack#24947), so a parsed bulk definition serves the envelope where it served a string. The confirm step rendered `confirmText` as it came, so an envelope would have broken it. It now shows the string, or the envelope's `source` as written; a blank or absent value still shows the default sentence ("This will apply to N record(s)."). `{{ }}` holes are not filled yet: `{{ count }}` still shows as written. `BulkActionDef.confirmText` in `@object-ui/types` is typed `string | { dialect?: 'template'; source: string }`, and `@object-ui/plugin-grid` reads it through one helper, `bulkConfirmTextSource`. diff --git a/.changeset/13216-header-widget-face.md b/.changeset/13216-header-widget-face.md deleted file mode 100644 index 56f6cbfbd8..0000000000 --- a/.changeset/13216-header-widget-face.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@object-ui/components': minor -'@object-ui/fields': patch ---- - -The record page heading draws a `nameField` that declares a widget with a read face of its own through that face, the one the field's list column draws (objectui#13216). A record share (`nameField: 'recipient_id'`, which declares `widget: 'recipient-picker'` and `dependsOn: ['recipient_type']`) now heads its page with the recipient's name instead of the user id it stores. Every other heading is unchanged: a plain text or select `nameField`, a `titleFormat`, an explicit `title`, an object with no `nameField`, a widget with no read face of its own, a widget whose key has no face registered under it (it draws the stored text), and a host that does not load `@object-ui/fields`. - -`@object-ui/components` adds a field-face seam on its entry: `setFieldReadFaceResolver(resolver)` installs the resolver, `resolveFieldReadFace(field)` asks it, and the types `FieldReadFace`, `FieldReadFaceProps` and `FieldReadFaceResolver` describe them. `@object-ui/fields` fills it when it loads, with the same `getCellRenderer(resolveCellRendererType(field))` lookup the grid's cells make, so a host has nothing to wire. `RecordTitleChip` gains an optional `titleNode` prop, drawn inside its heading in place of the `title` text; `title` stays a required string. diff --git a/.changeset/13270-clone-switch-source-off.md b/.changeset/13270-clone-switch-source-off.md deleted file mode 100644 index 19a8bbe443..0000000000 --- a/.changeset/13270-clone-switch-source-off.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -'@object-ui/app-shell': patch -'@object-ui/i18n': patch ---- - -Setup › Packaged automation: the clone result now offers the next steps (objectui#13270). - -A clone of a packaged flow is created `draft`, which does not switch it off, so a cloned record-change or schedule flow runs beside the flow it was copied from. The result used to show the server's notice and nothing to click. It now keeps that notice and adds: - -- **Switch "SOURCE" off** — calls the same packaged-flow toggle as the row's own switch, for the flow that was cloned. On success the row reads off and the result says the source is switched off. A refusal shows the server's message beside the button, and the button stays. When the source is already off, no switch-off is offered. -- **Open the clone in Studio** — links the package-less Studio scope (`/studio/~org/automations`) opened on the clone. - -The clone itself is unchanged. Three new language-pack keys, `packagedAutomation.cloneSwitchSourceOff`, `.cloneSourceOff` and `.cloneOpen`, in all ten packs. diff --git a/.changeset/13271-default-from-row-id.md b/.changeset/13271-default-from-row-id.md deleted file mode 100644 index ce6caaf62d..0000000000 --- a/.changeset/13271-default-from-row-id.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@object-ui/fields': patch ---- - -A row action's `defaultFromRow` param backed by a relation is seeded with the related record's id again, not the whole record (objectui#13271). - -Related lists read their rows with the relations they show expanded, so a `lookup`, `master_detail`, `user` or `tree` value arrives as the related record. The param seed copied that record verbatim, and the action sent it where the endpoint expects the id. Setup → Teams → Remove from Team answered 400 "User is not a member of the organization" for every member. - -The seed now uses the row's stored form, by the same field-type rule the predicate and Undo paths use: a field the row's object declares relational becomes its id, and a `multiple` one becomes the array of ids. Every other field, including a `json` value that has an `id` key, is seeded exactly as before. The dialog still shows the related record's name. Nothing is added to the package entry. diff --git a/.changeset/13272-clone-notice-stale.md b/.changeset/13272-clone-notice-stale.md deleted file mode 100644 index 7948068aff..0000000000 --- a/.changeset/13272-clone-notice-stale.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@object-ui/app-shell': patch ---- - -The permission-set editor no longer keeps the clone notice once the copy is held or saved (objectui#13272). - -"Clone to customize" opens the copy with the server's notice: what was not copied, and that the copy is held by nobody yet. The notice is the server's answer at the moment of the clone. It stayed on the copy for as long as the copy was open, so after a user was assigned and the copy was saved it still said nobody held it. The notice now goes when the copy's Assigned Users list first shows anyone (a direct grant or a holder through a position), or when a save of the copy succeeds. A refused save keeps it, and so does a failed read of the holders. On an embedded host, where the copy is announced on the set it was cloned from, saving that set keeps it too. While the notice shows, it is still shown whole and in the server's words. diff --git a/.changeset/13273-app-report-index-contributions.md b/.changeset/13273-app-report-index-contributions.md deleted file mode 100644 index 7004f610c4..0000000000 --- a/.changeset/13273-app-report-index-contributions.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@object-ui/app-shell': patch ---- - -The app's report index (`/apps/APP/reports`) and the ⌘K palette's report list now include the reports a module contributes to the app's navigation (`navigationContributions`), not only the reports the app's own package owns. The index lists the union of the app package's reports and every report a `type: 'report'` navigation entry names, deduplicated by name; an entry naming a report the server does not serve is left out, and the dataset read gate still hides a report the member may not read. diff --git a/.changeset/13278-dependencies-editor.md b/.changeset/13278-dependencies-editor.md deleted file mode 100644 index eb07fe2e21..0000000000 --- a/.changeset/13278-dependencies-editor.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@object-ui/app-shell': patch ---- - -The package dialog's Dependencies row is now an author-facing editor (objectui#13278). It used to be the spec form's raw JSON box under the developer hint "widget object-fields — falling back to JSON until a custom renderer is registered", because the manifest's `dependencies` is a string map the spec form has no renderer for. - -The row now lists one line per dependency, a package name and a version range, with add and remove, in create, edit and view mode. It sends the same flat map as before: in edit mode only when changed, and `{}` when every row is removed. An empty or duplicate package name is flagged under its row and keeps save disabled. The ranges are judged by the server, whose refusals render in the dialog as before. - -Nothing is added to the package entry: no export, prop or type member. The new copy lives in the metadata-admin designer's own string tables (en and zh). diff --git a/.changeset/13286-page-predicate-fail-closed.md b/.changeset/13286-page-predicate-fail-closed.md deleted file mode 100644 index 06a379de75..0000000000 --- a/.changeset/13286-page-predicate-fail-closed.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@object-ui/components': patch ---- - -A `page:tabs` item whose `visibleWhen` faults on evaluation is no longer drawn (objectui#13286). - -A predicate that cannot be evaluated (a source over the CEL engine's AST bound, a type error, an unbound root, a missing function) used to fall back to visible, so the tab drew for a viewer the predicate was written to exclude. It now fails closed: the tab, header and panel, is withheld, and the fault is logged once per authored source through the same console report as before, now saying the tab was withheld. If the withheld tab was the active one, the strip falls back to the first visible tab. A tab with no `visibleWhen`, or a blank one, is still shown, and a predicate that evaluates decides exactly as before. Form field rules keep their documented fail-open. diff --git a/.changeset/13287-settings-format-check.md b/.changeset/13287-settings-format-check.md deleted file mode 100644 index 724bbcf5b2..0000000000 --- a/.changeset/13287-settings-format-check.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@object-ui/console': patch -'@object-ui/i18n': patch ---- - -Settings pages: a `url`, `email`, `phone` or `color` value that misses the format its type declares now blocks Save (objectui#13287). No request goes out, the row is marked inline with a message naming what the format expects, and focus moves to the first such row, on the same path as the `required` check. The grammars are the settings service's own (objectstack#24882), judged on the trimmed value; an empty value is left to `required`, and a hidden or env-locked row is not judged. Adds `console.settingsView.invalidPhone` and `console.settingsView.invalidColor` to every locale pack; `email` and `url` reuse `validation.email` and `validation.url`. diff --git a/.changeset/13292-record-level-refusal.md b/.changeset/13292-record-level-refusal.md deleted file mode 100644 index fd3f207559..0000000000 --- a/.changeset/13292-record-level-refusal.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@object-ui/plugin-detail': patch ---- - -The inline-edit save bar shows an object-level rule's refusal as the rule's own message, without a field label (objectui#13292). - -The server names an object-level rule (a `script` rule, or one that lists no fields) with the `_record` sentinel. The bar used to print that sentinel as a field label, so the banner read `_record: …`. Now an entry that names `_record`, or names no field of the record, is shown alone in the banner and is not published as a per-field hint. Field-level entries are unchanged: they keep their label and their hint beside the input. diff --git a/.changeset/13295-cloud-console-findings.md b/.changeset/13295-cloud-console-findings.md deleted file mode 100644 index b3cb42eab4..0000000000 --- a/.changeset/13295-cloud-console-findings.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@object-ui/fields': patch ---- - -A password or secret input now tells the browser what it is for (objectui#13295). - -The password widget's editable input carries an `autocomplete` token. A field or action parameter whose name reads as the user's existing password (a word `current`, `old` or `existing` in the name, as in `current_password` or `oldPassword`) gets `current-password`; every other password or secret gets `new-password`. Before, the input had no token, so a browser treated each one as a sign-in field: it offered the saved site password for an API key or a new password, and its password manager could not tell the old password from the new one in a change-password dialog. The masked input and its show/hide toggle are unchanged. diff --git a/.changeset/13299-node-visibility-fail-closed.md b/.changeset/13299-node-visibility-fail-closed.md deleted file mode 100644 index 6b05b92336..0000000000 --- a/.changeset/13299-node-visibility-fail-closed.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@object-ui/react": patch -"@object-ui/components": patch ---- - -A page node whose declared `visibleWhen` / `visible` / `visibleOn` predicate cannot be evaluated (over the CEL bounds, a type error, an unbound root, a missing function) is no longer rendered: page visibility gates now fail closed, as a `page:tabs` item already did. The fault is still reported once, and the console line says the node was withheld. A blank gate still means "no gate", and a predicate that evaluates decides as before. A `page:tabs` badge no longer counts a related list withheld this way. Form field rules keep their fail-open (objectui#13299). diff --git a/.changeset/13301-product-blocks-namespace.md b/.changeset/13301-product-blocks-namespace.md deleted file mode 100644 index 0369ede531..0000000000 --- a/.changeset/13301-product-blocks-namespace.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@object-ui/app-shell': patch -'@object-ui/cli': patch ---- - -The console home blocks `hero`, `stat`, `usage-bar`, `checklist` and `tile-grid` register under the `app-shell` namespace, so the console no longer logs a "without a namespace is deprecated" warning for each on every boot (objectui#13301). - -Pages keep writing the bare key: `type: 'hero'` still draws the block through the registry's bare fallback. `objectui check` now knows the five `app-shell:` keys as registered, and `objectui validate` refuses them at `type`, so the bare spelling stays the one authorable key. diff --git a/.changeset/13303-withholding-copy.md b/.changeset/13303-withholding-copy.md deleted file mode 100644 index c1f8a456f4..0000000000 --- a/.changeset/13303-withholding-copy.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@object-ui/react": patch ---- - -The console line for a visibility predicate that cannot be evaluated, on a gate that withholds what it gates, no longer says "a navigation entry" was withheld. The same line is printed for a navigation entry, a `page:tabs` item and a page node, so it now says "an element whose visibility predicate cannot be evaluated is WITHHELD". The verdict, the line's opening, and when it is printed are unchanged (objectui#13303). diff --git a/.changeset/13304-position-preview-permission-sets.md b/.changeset/13304-position-preview-permission-sets.md deleted file mode 100644 index b3d55b4138..0000000000 --- a/.changeset/13304-position-preview-permission-sets.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@object-ui/app-shell': patch ---- - -The Position preview lists the permission sets a position declares in `permissionSets` (ADR-0131 D4), by machine name in declared order. The "positions don't grant data access on their own — bind it to Permission Sets" note now shows only for a position that declares none (objectui#13304). diff --git a/.changeset/13308-add-record-retired-keys.md b/.changeset/13308-add-record-retired-keys.md deleted file mode 100644 index 0d9cd3f6df..0000000000 --- a/.changeset/13308-add-record-retired-keys.md +++ /dev/null @@ -1,4 +0,0 @@ ---- ---- - -Test-only change to two `@object-ui/types` spec-alignment tests: they stop authoring `addRecord.mode` / `addRecord.formView`, which `@objectstack/spec` retired. No published behaviour changes. diff --git a/.changeset/13309-dropped-fields-reason-pin.md b/.changeset/13309-dropped-fields-reason-pin.md deleted file mode 100644 index 6b799ef6fc..0000000000 --- a/.changeset/13309-dropped-fields-reason-pin.md +++ /dev/null @@ -1,4 +0,0 @@ ---- ---- - -Test-only change: the batch-6 spec-symbol pin in `@object-ui/data-objectstack` states `DroppedFieldsEvent['reason']` with `stored_expression` subtracted, so it compiles against both the pinned spec and objectstack `main` (objectui#13309). No published behaviour changes. diff --git a/.changeset/13310-data-page-relation-filters.md b/.changeset/13310-data-page-relation-filters.md deleted file mode 100644 index 3bcbd794bf..0000000000 --- a/.changeset/13310-data-page-relation-filters.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@object-ui/app-shell': patch ---- - -The `/data` page's generated filter bar now offers single-value relation fields (`lookup`, `master_detail` and `user`) beside the picklist fields (objectui#13310). A relation chip opens the list's existing remote-search picker, which queries the related object through the caller's data source, and a pick filters the rows by the related record's id. The selection persists in the same `uf_*` URL params as the picklist filters, so it survives a reload; an id that no longer resolves shows as the id. - -So an organization's Members "View all" page, which anchors no declared view, can now be filtered by User as well as by Role. - -Picklist fields keep their slots: relation fields follow them in declaration order and take only the slots the picklists leave under the bar's four-field cap. A multi-value relation (`multiple: true`), a hidden field and a field the caller cannot read are not offered. An object without a single-value relation field renders the same bar as before. diff --git a/.changeset/13315-import-wizard-csv-door.md b/.changeset/13315-import-wizard-csv-door.md deleted file mode 100644 index 4a06cbd1fd..0000000000 --- a/.changeset/13315-import-wizard-csv-door.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -'@object-ui/plugin-grid': patch -'@object-ui/app-shell': patch ---- - -The Import Wizard sends a CSV file to the import door as CSV text (objectui#13315). When you import a `.csv`, `.tsv` or `.txt` file, the request is now `format: 'csv'` with the rows the preview shows written out as CSV. This holds on the hand-mapped path, and with a saved mapping that does not declare `sourceFormat: 'json'`. Before, those rows were sent as JSON, so the server never read the file's cells through its CSV import rule, the one its CSV export pairs with. - -- **The text is the preview's rows.** The wizard writes the CSV from the rows it shows, not from the file as uploaded, as it already did for a mapping that declares `sourceFormat: 'csv'`. A cell you corrected in the preview is sent corrected. The dry-run check sends the same request as the import. -- **Unchanged:** an `.xlsx` sheet and a pasted table are sent as JSON rows. A saved mapping that declares `sourceFormat: 'json'` still gets JSON rows from any file, because the import door does not accept CSV text for it. -- **User import** (`sys_user`) sends a CSV file as CSV text too, in batches of at most 500 rows. Each one-time password is still shown with the email or phone number of its row. - -Three shapes now import differently from what the preview shows: - -- **A last row whose mapped cells are all empty is not imported.** When the file's last row, or a run of last rows, has data only in columns you did not map, the server does not read it. The import counts one row fewer than the preview, and that row creates no record and reports no error. A row of that shape anywhere else in the file is imported as before, so row numbers keep matching the preview. User import sends the file in batches of 500 rows, so there the same holds for the last row of each batch. -- **A cell that begins with an apostrophe and ends in a tab or a line break keeps the apostrophe** when the rest of it starts with `+` or `-` and holds only digits, spaces and `( ) + - . ,`. The preview trims the tab or line break before the cell is sent, and a server whose CSV import removes the apostrophe the CSV export adds leaves this trimmed cell as it is. The wizard imported such a cell with its apostrophe before this change too. -- **A space before a leading apostrophe is trimmed first.** On a server whose CSV import removes the apostrophe the CSV export adds, a cell typed as a space, an apostrophe and a value the export would write with an apostrophe now imports without the apostrophe. Before this change it imported with it. - -No export, prop or type is added to either package entry. diff --git a/.changeset/13317-settings-leaveguard-race.md b/.changeset/13317-settings-leaveguard-race.md deleted file mode 100644 index 721a36252f..0000000000 --- a/.changeset/13317-settings-leaveguard-race.md +++ /dev/null @@ -1,4 +0,0 @@ ---- ---- - -Test-only change to the settings page's leave-guard suite: the case "after a successful save the page is clean again" now waits on the guard itself rather than on the unsaved bar. No published behaviour changes. diff --git a/.changeset/13318-datasource-sync-managed.md b/.changeset/13318-datasource-sync-managed.md deleted file mode 100644 index a9e9b2bfb9..0000000000 --- a/.changeset/13318-datasource-sync-managed.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@object-ui/app-shell': patch ---- - -Setup → Datasources offers "Sync objects" only on a datasource that can be synced (objectui#13318). - -The server refuses every Sync step (listing remote tables, drafting and importing an object) on a datasource whose schema mode is `managed`, with a `400` that names the rule and the remedy. A datasource saved without a schema mode is managed too, and so is the platform's `default` datasource. The page still showed the button on every row, so on such a row it opened a dialog that could only show the refusal. - -The button now shows only on a row whose schema mode is `external` or `validate-only`, and never on the `default` row. To sync from a managed datasource, edit it and set its Schema mode to External or Validate only. diff --git a/.changeset/13323-one-read-per-open.md b/.changeset/13323-one-read-per-open.md deleted file mode 100644 index e2a8facd6a..0000000000 --- a/.changeset/13323-one-read-per-open.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'@object-ui/react': minor -'@object-ui/app-shell': patch ---- - -A navigation entry's API `dataSource` and a page element bound to the same read now make one request per console open (objectui#13323). Before, `readElementApi` shared a request only while it was in flight, so when the sidebar's read for an entry's `visible` had settled before the page element mounted, the element sent a second `GET` for an answer the console already held. - -`@object-ui/react` exports `ElementApiOpenScope` (with `useElementApiOpen` and the `ElementApiOpen` type): inside it, a read that has already answered under the same `open` name is answered again with no request. A failed read is not kept, a read under another `open` asks again, and any `notifyDataChanged` drops what the open kept. `readElementApi` takes the open as an optional third argument; without one it behaves as before. - -`@object-ui/app-shell`'s `ConnectedShell` mounts the scope and names one open per visit of a history entry: following a link or a navigation entry, and Back or Forward, start a new open and read again, even on an entry visited before; a redirect that replaces the address (the app root's landing on its first entry) stays in the open. A language switch starts over. No read happens at a different time than before; only whether a second read in one open reaches the network changes. diff --git a/.changeset/13324-approval-page-member-reads.md b/.changeset/13324-approval-page-member-reads.md deleted file mode 100644 index 2be35207cd..0000000000 --- a/.changeset/13324-approval-page-member-reads.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'@object-ui/permissions': minor -'@object-ui/console': patch ---- - -An approver who is not an administrator sees the whole approval request page again: its fields, its decision panel with the decisions they may take, and its Timeline (objectui#13324). - -The console reads a request, and its timeline, through the approvals routes, which serve a request to each party to it. The record page then gated what it drew on the permissions answer for the data API, which names neither approval object for a member, because the platform keeps that door closed to them. So the page folded the request down to its id, drew no decision, and dropped the Timeline. Opening a request from the Approvals inbox showed a blank page. - -`@object-ui/permissions` adds `ServerReadScope`. Below it, the read verdicts for the objects it names (`check(object, 'read')` and `checkField(object, field, 'read')`) answer "allowed": whatever the server serves is what the viewer may read. Every other action, the field write and create verdicts, and every other object keep the enclosing provider's answer. The console mounts it for the two approval objects over every app. No read grant on either object is added: the data API stays closed to members. diff --git a/.changeset/13327-test-gate-check-runs.md b/.changeset/13327-test-gate-check-runs.md deleted file mode 100644 index b2b4422a2b..0000000000 --- a/.changeset/13327-test-gate-check-runs.md +++ /dev/null @@ -1,4 +0,0 @@ ---- ---- - -CI-only change to the aggregate `Test` gate (`scripts/check-test-shard-results.mjs`): a shard the Actions jobs API serves without a conclusion is also read from its own check run, and the gate reads its own job's check run once per run (objectui#13327). No published package changes. diff --git a/.changeset/13330-managed-environment-users.md b/.changeset/13330-managed-environment-users.md deleted file mode 100644 index 3ab0c699de..0000000000 --- a/.changeset/13330-managed-environment-users.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -'@object-ui/auth': minor -'@object-ui/plugin-grid': minor -'@object-ui/plugin-list': minor -'@object-ui/app-shell': patch -'@object-ui/i18n': patch ---- - -On a cloud-managed environment (`features.cloudManaged: true` from `/auth/config`), the console says what the server already enforces. Setup → Users shows one line saying where people are invited (the organization, in the cloud) and marks a user who holds no permission set beyond the baseline as "Not authorized", read from their `sys_user_permission_set` and `sys_user_position` rows. The identity import entry is not offered, the organization members page shows a note instead of Invite member, and the recovery-password reminder does not show. With the flag absent or `false`, nothing changes. - -`AuthPublicConfig['features']` gains `cloudManaged`. `ObjectGrid` gains the `rowAdornment` host prop, a node drawn beside one row's title (the declared name field's cell, else the first shown column, and the card title in the card view), and `ListView` forwards its own `rowAdornment` to the grid. - -Clause-②: yes -Metadata-protocol: none diff --git a/.changeset/13331-highlight-date-year.md b/.changeset/13331-highlight-date-year.md deleted file mode 100644 index 6535d814f6..0000000000 --- a/.changeset/13331-highlight-date-year.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -'@object-ui/core': patch -'@object-ui/fields': patch -'@object-ui/plugin-detail': patch ---- - -The record header's highlights write the year on every date (objectui#13331). - -A current-year date dropped its year in the strip, so a contract record read "Start Date Sep 15, 2025 | End Date Sep 15" and a contract that ended this September looked like it ended next month. The strip now asks for the year, and both dates read alike. Dates inside the ±7-day window keep their relative phrase ("In 2 days"). - -`formatDate` takes a new opt-in option, `alwaysShowYear`, which keeps the year on its default face; the `date` and `datetime` cell renderers take an `alwaysShowYear` prop that hands it on. Neither is on by default: grid cells and cards still drop the current year. diff --git a/.changeset/13332-refusal-plain-sentence-first.md b/.changeset/13332-refusal-plain-sentence-first.md deleted file mode 100644 index 110e90a51d..0000000000 --- a/.changeset/13332-refusal-plain-sentence-first.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@object-ui/app-shell": patch -"@object-ui/i18n": patch ---- - -Setup refusals lead with one plain sentence. The Packages sheet, the metadata editor's error banner (Positions and every other metadata type) and the action parameter dialog (OAuth application registration among them) now show the first sentence of the server's message, without a leading bracketed code or field path and without the trailing declared code. The whole message, byte for byte, sits behind a "More" toggle with a copy button. A one-sentence message renders as before. New `refusalDetails.*` strings in all ten locale packs (objectui#13332). diff --git a/.changeset/13333-named-delete-confirm.md b/.changeset/13333-named-delete-confirm.md deleted file mode 100644 index b4dbf57bae..0000000000 --- a/.changeset/13333-named-delete-confirm.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'@object-ui/app-shell': patch -'@object-ui/plugin-detail': patch -'@object-ui/i18n': patch ---- - -Setup's metadata deletes and the related list's row delete now ask in the console's in-app confirm dialog and name what goes (objectui#13333). - -- The metadata editor's Reset overlay / Delete and Discard draft, the history timeline's Rollback, the Datasources page's Delete and a metadata type's `confirmText` action no longer use the browser's native `confirm()`. Each opens an in-app AlertDialog whose title names the item: by its type label and its own label for Reset / Delete (for example `Delete Object "Account"?`), with the machine `type/name` in the body; by label and name for a datasource; by action and item for a type action. -- The related list's row Delete no longer asks "Are you sure you want to delete this record?". The sentence names the row by its record title, the same resolver the record header uses, so a grant row reads by its declared title (the grant and the user it belongs to). The `detail.deleteRowConfirmation` string now takes a `{{name}}` value in all ten locales. diff --git a/.changeset/13334-one-main-landmark.md b/.changeset/13334-one-main-landmark.md deleted file mode 100644 index 44515e474c..0000000000 --- a/.changeset/13334-one-main-landmark.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@object-ui/layout": patch ---- - -`AppShell` now draws one `main` landmark. `SidebarInset` already renders a `
`, and the content element inside it was a second `
`, so every console page (Setup record pages included) announced two main regions to screen readers. The content element is now a `
`; `className` still lands on it, and the skip link still targets the console's route slot. diff --git a/.changeset/13335-restricted-lookup-label.md b/.changeset/13335-restricted-lookup-label.md deleted file mode 100644 index e46a8bcb81..0000000000 --- a/.changeset/13335-restricted-lookup-label.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@object-ui/fields': patch -'@object-ui/i18n': patch ---- - -A lookup / master-detail / tree value whose referenced record the viewer's own read answers "not found" for (a 404, which is what the server answers for a record this viewer may not read) now reads "Restricted record", translated, with a lock icon, no record id and no link, in grids and on the record page (objectui#13335). It used to print the raw id beside a question mark. No additional read is made: the label comes from the same lookup read the cell already performed, so it reveals nothing the id did not. A reference that is still loading, whose read failed, or that is empty renders as before, and a readable reference still shows its name as a link. New key: `detail.restrictedLookupReference` in all ten locale packs. diff --git a/.changeset/13336-nav-group-default-open.md b/.changeset/13336-nav-group-default-open.md deleted file mode 100644 index 13abc1b9cd..0000000000 --- a/.changeset/13336-nav-group-default-open.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'@object-ui/layout': patch -'@object-ui/app-shell': patch ---- - -A sidebar navigation group now opens on first view unless it declares `expanded: false` (or the legacy `defaultOpen: false`), however many entries it holds (objectui#13336). - -`NavigationRenderer` used to collapse any group that declared neither field once it had eight or more children. On Setup that closed Configuration (13 entries) although only Advanced declares `expanded: false`, hiding entries such as Localization, Email and Authentication on first view. The count rule is gone: a group holding the current route opens; otherwise its declared `expanded` / `defaultOpen` decides; otherwise it opens. Studio's navigation preview follows the same rule, so it still matches the running sidebar. - -An app that relied on a long, undeclared group starting closed should now declare `expanded: false` on it. diff --git a/.changeset/13337-position-editor.md b/.changeset/13337-position-editor.md deleted file mode 100644 index 43e3a28413..0000000000 --- a/.changeset/13337-position-editor.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'@object-ui/app-shell': patch ---- - -Setup → Positions: a new position is created together with its permission sets, Save is labelled, Remove holder asks first, and the holder picker offers organization members only (objectui#13337). - -- New Position shows the Permission Sets picker beside the label, name and description, so binding a set no longer takes a first save and a second edit. -- The metadata editor's Save draws the word "Save" beside its icon. Its accessible name and tooltip are unchanged: the shortcut hint, or why Save is withheld. -- Removing a position holder opens a confirm that names the person; nothing is sent until it is confirmed. -- Add holder reads the active organization's `sys_member` rows when it opens and offers only the users they name, so a user removed from the organization is no longer offered (the server already refuses such an assignment). With no active organization, or no `sys_member` object registered, the picker lists every user it may read, as before. diff --git a/.changeset/13338-deactivate-confirm.md b/.changeset/13338-deactivate-confirm.md deleted file mode 100644 index a8a5a9d358..0000000000 --- a/.changeset/13338-deactivate-confirm.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@object-ui/app-shell': patch ---- - -Setup's Permission Sets and Positions lists ask before the Active switch turns an item off, and a toast confirms the change either way (objectui#13338). - -Switching a permission set or a position off opens a confirm that names how many users lose the access. The count is read from the server when the confirm opens: for a position, its `sys_user_position` rows; for a permission set, its `sys_user_permission_set` rows and the holders of every position whose definition lists the set, one person counted once, as the set's Assigned Users section counts them. A set bound to the `everyone` position is said to reach every signed-in member. A count that cannot be read is said as such, never as "0 users", and the admin may still go ahead. Cancel leaves the item on. Switching an item on asks nothing. diff --git a/.changeset/13339-adopt-loose-items-confirm.md b/.changeset/13339-adopt-loose-items-confirm.md deleted file mode 100644 index 6b504d1c28..0000000000 --- a/.changeset/13339-adopt-loose-items-confirm.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@object-ui/app-shell': patch ---- - -Setup → Packages: in a package's sheet, *Adopt loose items* asks in the in-app confirmation, reports how many items it adopted, and each action clears the previous action's message (objectui#13339). - -*Adopt loose items* used the browser's native confirm, which an embedded frame can block or answer on its own. It now opens the sheet's in-app dialog, like Delete and Discard; its Cancel sends nothing. After an adoption the sheet says "N items adopted into this base.", with the count the server answers (`reassignedCount`), so an adoption that found nothing reads "0 items adopted into this base." instead of "Loose items adopted into this base.". - -The sheet's message line now answers the action the administrator started last. Pressing Duplicate, Delete app, Discard changes, Adopt loose items, Edit or View info clears the previous action's message, as the actions that run straight away already did; a Revert refusal no longer stays under the Duplicate form. English and Chinese. diff --git a/.changeset/13340-toaster-top-center.md b/.changeset/13340-toaster-top-center.md deleted file mode 100644 index 7bb7c73749..0000000000 --- a/.changeset/13340-toaster-top-center.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@object-ui/app-shell': patch ---- - -Console toasts no longer cover the page header's actions (objectui#13340). With no drawer open the toaster now sits top-centre, just below the console's top bar, instead of in the top-right corner, which is where every page header puts its actions. At 1440×900 a toast used to cover a list's New and Import buttons for its whole 4 s life. While a right-side drawer is open the toaster still goes to the top-right corner and steps clear of the drawer as before (objectui#11685), and it still never uses the bottom-right corner, which belongs to the assistant (objectui#7482). - -New tests check that one server refusal raises one error toast, on the record form renderer and on an action's parameter dialog (Users → Create User, Teams → Add Member). diff --git a/.changeset/13341-explain-once-after-action.md b/.changeset/13341-explain-once-after-action.md deleted file mode 100644 index 3e82c7417a..0000000000 --- a/.changeset/13341-explain-once-after-action.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'@object-ui/plugin-detail': patch -'@object-ui/plugin-grid': patch ---- - -After a save, delete or action, the record page and the list ask the platform's explain engine each record's edit and delete question once (objectui#13341). - -One write often reaches the console's data-change bus twice: once when the data source reports it, and again from the page or list that made it. When the second notice arrived while the fresh permission check was still waiting for its answer, the check was thrown away and sent again, so one Setup save could send `POST /api/v1/security/explain` two to six times. Now a notice that arrives while a record's fresh check is on its way joins that check. A check that was already on its way before the write is still discarded and asked again, and a change announced after the check has answered still asks again, so Edit and Delete still follow the record's state after the write. - -The list also stops asking again about rows whose answer is already on its way when its own re-read changes the rows on screen, and asks only about the rows nobody has asked about yet. A list whose rows go past the server's batch limit now sends its batches at once instead of one after another. diff --git a/.changeset/13342-refused-flow-message-only.md b/.changeset/13342-refused-flow-message-only.md deleted file mode 100644 index 369766201e..0000000000 --- a/.changeset/13342-refused-flow-message-only.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@object-ui/app-shell': patch ---- - -A screen flow that ends refused shows its message and Close alone (objectui#13342). - -When a screen-flow run ends with `outcome: 'refused'`, the dialog used to keep the screen the run had paused on under the refusal: its input fields stayed visible and editable, though a refused run is never resumed and nothing would submit them. The dialog now shows the flow's name, the step's heading, the refusal message and Close, with no screen fields. An `object-form` step, whose Close lived in the form's own button bar, gets the runner's Close instead, and the dialog takes its narrow width. - -A screen still waiting for input renders as before, and a run that fails keeps its screen and the typed values under the reason. diff --git a/.changeset/13343-preselect-only-mapping.md b/.changeset/13343-preselect-only-mapping.md deleted file mode 100644 index 682e67e3e9..0000000000 --- a/.changeset/13343-preselect-only-mapping.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@object-ui/plugin-grid': patch ---- - -The import wizard now opens its mapping step with the object's saved mapping applied when the object ships exactly one that the target accepts (objectui#13343). Before, the step always opened on "Map columns manually", so a user who never opened the "Saved mapping" menu imported without the mapping's renames and transforms. The preselection applies the mapping the same way picking it from the menu does, and the wizard decides it once per opening: a re-fetched mapping list or a re-render does not apply it again after the user switches back to manual mapping. With no saved mapping, or with several the target accepts, the step still opens on manual mapping. A mapping whose write mode the target refuses is still listed disabled and is not counted. diff --git a/.changeset/13344-clone-name-prefill.md b/.changeset/13344-clone-name-prefill.md deleted file mode 100644 index 52aa116ebd..0000000000 --- a/.changeset/13344-clone-name-prefill.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'@object-ui/app-shell': patch -'@object-ui/i18n': patch ---- - -Setup › Packaged automation: the Clone dialog now opens with a name and label filled in (objectui#13344). - -It used to open with both fields empty. It now proposes `_copy` as the machine name and " (copy)" as the label, using the flow's machine name when it has no label. Both fields stay editable, and the dialog can be submitted as it opens: the proposed name keeps the lowercase snake_case shape a flow name must have, and it is the same name the server suggests when a name is taken. A name that is already taken is still refused by the server with its 409 message, shown as sent. - -One new language-pack key, `packagedAutomation.cloneCopyLabel`, in all ten packs. diff --git a/.changeset/13352-schemaform-label-only.md b/.changeset/13352-schemaform-label-only.md deleted file mode 100644 index d87826d533..0000000000 --- a/.changeset/13352-schemaform-label-only.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@object-ui/app-shell': patch ---- - -A metadata form row now shows the field's label only (objectui#13352). `SchemaForm`'s default row used to draw the field's machine key in a code chip beside the label whenever the label did not spell it, so Setup → Packages → New package read `Display name* name`. The key is now offered on demand instead, as the label's hover tooltip ("Machine name: name"), under the same rule as before: only when the label does not already spell the key, judged alike in every locale. The control's accessible name is the label alone. diff --git a/.changeset/13355-agent-key-name-confirm.md b/.changeset/13355-agent-key-name-confirm.md deleted file mode 100644 index 9f322fe1ed..0000000000 --- a/.changeset/13355-agent-key-name-confirm.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@object-ui/app-shell': patch -'@object-ui/i18n': patch ---- - -Connect an Agent no longer mints an unnamed API key in one click (objectui#13355). "Create key" stays disabled until the administrator types a name, and the name is sent as typed: the key is no longer created as `agent-key` when the name box is empty. Clicking "Create key" now opens an in-app confirm naming the key; Cancel creates nothing, and confirming creates the key and shows it once to copy, as before. This matches Setup → API Keys → Create Key, which also requires a name. - -New string: `connectAgent.apiKey.confirmTitle`, in all ten locale packs. diff --git a/.changeset/13356-installed-apps-title.md b/.changeset/13356-installed-apps-title.md deleted file mode 100644 index c3ae0b82a0..0000000000 --- a/.changeset/13356-installed-apps-title.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@object-ui/app-shell': patch ---- - -Setup → Installed Apps is titled "Installed Apps" and says when no app is installed from the marketplace yet (objectui#13356). - -The Installed Apps entry opens the Packages page filtered to marketplace installs (`?source=marketplace`). That view now carries the entry's title instead of "Packages", and with no marketplace install it reads "No apps installed from the marketplace yet" instead of "No packages match your filters.", which blamed a filter the administrator had not set. "No packages match your filters." stays for a filter the viewer did set: a search that hides the marketplace installs that exist, or another Source. Setup → Packages, opened without a Source, is unchanged. English and Chinese. diff --git a/.changeset/13367-action-copy-template.md b/.changeset/13367-action-copy-template.md deleted file mode 100644 index a42aaf7091..0000000000 --- a/.changeset/13367-action-copy-template.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -'@object-ui/core': minor -'@object-ui/react': patch -'@object-ui/app-shell': patch ---- - -An action's `confirmText`, `successMessage` and `errorMessage` read the `template` envelope and fill `{{ }}` holes (objectui#13367). - -`@objectstack/spec` is making these three keys `template` slots (objectstack#24814), so a parsed action serves `{ dialect: 'template', source }` where it served a string. Before this change the success toast skipped the envelope and showed the default text, and the error toast showed the generic failure. `ActionRunner` now reads a string or the envelope for all three, and fills `{{ path }}` / `{{ path | formatter }}` holes with `@objectstack/formula`'s `templateEngine`, the engine the flow notifications render with: - -- `confirmText`: `record` (the record the action runs against, the clicked row on a list) and `params` (the action's static params); -- `successMessage`: `result` (the payload `${result.*}` reads) and `record`; -- `errorMessage`: no hole is filled; the text shows as written. - -A sentence with no `{{ }}` hole keeps today's `${…}` reading, so the platform's own `${result.email}`-style success sentences still work until the spec converts them. A sentence is read in one dialect only: a value filled into a `{{ }}` hole is never read again as `${…}`. An envelope with no text never reaches the dialog or a toast as an object; a `confirmText` envelope with no text still asks for confirmation. - -`useActionTextLocalizer` keeps the envelope: it used to read it as a per-locale map and hand the runner the word `template`. A bundle entry replaces the envelope's `source`. On a flow action the console reads the envelope too, so the action's own success copy still outranks the flow's (`flowSuccessCopy`). `@object-ui/core` exports the reader it uses: `ActionCopyTemplate`, `isActionCopyEnvelope`, `actionCopySource`, `hasTemplateHoles` and `fillTemplateHoles`. - -Clause-②: yes -Metadata-protocol: none diff --git a/.changeset/13377-lookup-cell-tooltip.md b/.changeset/13377-lookup-cell-tooltip.md deleted file mode 100644 index db18283480..0000000000 --- a/.changeset/13377-lookup-cell-tooltip.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -'@object-ui/types': minor -'@object-ui/components': patch -'@object-ui/plugin-grid': patch ---- - -Grids: hovering a `lookup` or `master_detail` cell no longer shows the referenced record's raw id (objectui#13377). - -The table's cell wrapper set its `title` tooltip to the cell's raw value, and for a reference column that value is the related record's id. So hovering beside the drawn name, or beside "Restricted record" for a record the viewer cannot read, still showed the id. - -- **`@object-ui/types`:** `TableColumn` gains an optional `foreignKey` boolean: the column's raw value is the id of a referenced record. The zod mirror (`TableColumnSchema`) keeps it, and the static `table` column refuses it by name, like `masked` and `chips`. -- **`@object-ui/components`:** a `data-table` column with `foreignKey: true` draws no `title` tooltip. Nothing else changes for it: copy, CSV export, inline edit, search and sort behave as before. -- **`@object-ui/plugin-grid`:** `ObjectGrid` sets `foreignKey` on every `lookup`, `master_detail`, `tree` and `user` column, read from the column's own type or the object's field type. Every other column keeps its tooltip. diff --git a/.changeset/13379-onsuccess-navigate-host.md b/.changeset/13379-onsuccess-navigate-host.md deleted file mode 100644 index 4d08b17220..0000000000 --- a/.changeset/13379-onsuccess-navigate-host.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@object-ui/app-shell': patch ---- - -An action's `onSuccess.navigate` to a path with no app segment opens that page in the current app (objectui#13379). - -`onSuccess: { navigate: '/crm_opportunity/${result.id}' }` used to land on Home: the console handed the path to its router unchanged, and under the `/_console` basename it matched no route. The console action runtime now hosts such a path under the current app, the same way an inbox notification link is hosted, so it opens `/apps/APP/crm_opportunity/...`. With no app current (on Home), it is hosted under the first app the user can open, as notification links are. - -These are unchanged: a path that already names its app (`/apps/APP/...`), an external URL, a `mailto:` address, a `./` path, and a console route outside an app (`/forms/NAME`, which `type: 'form'` actions open, and `/home`, `/studio`, `/setup` and the other top-level routes). A `type: 'url'` action shares this navigator, so its app-relative paths are hosted the same way. diff --git a/.changeset/13380-form-entry-inline-locale.md b/.changeset/13380-form-entry-inline-locale.md deleted file mode 100644 index 45606129b0..0000000000 --- a/.changeset/13380-form-entry-inline-locale.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@object-ui/console': patch ---- - -A form field entry whose `label`, `placeholder` or `helpText` is an inline locale map (`{ en, 'zh-CN' }`) now renders in the visitor's language, on the public form `/f/:slug` and on the signed-in `/forms/:name` route (objectui#13380). - -`@objectstack/spec` types all three keys as `I18nLabel`, so the map is valid metadata, but the form page passed it straight into text slots: a map on a label or help line blanked the page for every visitor (React error #31), and one on a placeholder read `[object Object]`. The map is now collapsed to the visitor's language when the form's rows are built, with the same resolver the console uses for an action's inline-map copy. A plain-string entry renders exactly as before. diff --git a/.changeset/13382-settings-reread-after-save.md b/.changeset/13382-settings-reread-after-save.md deleted file mode 100644 index 9ab48f92be..0000000000 --- a/.changeset/13382-settings-reread-after-save.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@object-ui/console': patch ---- - -A Setup settings page reads its namespace again after a successful save or action, and takes the whole answer, manifest included (objectui#13382). The server computes parts of a namespace's manifest on every read: objectstack#25448 puts a live-status banner first on the page, so Setup → Email says whether mail leaves the machine. The page used to merge only the saved values and keep the manifest from its first load, so after an administrator configured SMTP the banner still said no mail leaves the machine until the page was reloaded. - -The re-read does not show the loading placeholder. An action leaves the unsaved edits as they are. If the re-read fails, the page keeps the saved values and the success message, and does not turn into an error. diff --git a/.changeset/13383-agent-section-key-confirm.md b/.changeset/13383-agent-section-key-confirm.md deleted file mode 100644 index 74c884667c..0000000000 --- a/.changeset/13383-agent-section-key-confirm.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@object-ui/console': patch ---- - -Integrations → Connect an AI agent no longer mints an API key in one click (objectui#13383). "Generate key" stays disabled while the name box is blank or whitespace-only, and the name is sent trimmed: a cleared box no longer mints a key under the default name `Agent key`. Clicking "Generate key" now opens an in-app confirm naming the key; Cancel creates nothing, and confirming creates the key and shows it once, as before. The name box still opens prefilled with `Agent key`, which is minted only once the administrator confirms it. This matches the Connect an Agent card (objectui#13355). diff --git a/.changeset/13384-record-action-row-guard.md b/.changeset/13384-record-action-row-guard.md deleted file mode 100644 index 39dd9dcdad..0000000000 --- a/.changeset/13384-record-action-row-guard.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -'@object-ui/core': patch -'@object-ui/i18n': patch -'@object-ui/app-shell': patch ---- - -A single-record action launched with 0 or several rows selected is refused before any dialog opens, and the refusal is translated (objectui#13384). - -`ActionRunner` now asks the handler it will dispatch to for an early refusal (`ActionRunnerHandler`'s optional `refuseBeforeInput`) before the confirmation and the param dialog. The handlers `createServerActionHandler` builds answer it with the row-count check the dispatch already runs, so "select a row first" and "select exactly one row" are shown before the user fills anything in, and nothing is sent. With exactly one row the dialog behaves as before. A host that wraps the built handler in its own function keeps the early refusal only by forwarding `refuseBeforeInput`; the console's `createConsoleServerActionHandler` now forwards it, so on a list page (HotCRM's "Add to Campaign" on My Leads) the refusal toast shows and no dialog opens. - -Both refusals now carry a pack key (`actions.selectRowFirst`, `actions.selectExactlyOneRow`, defined in every shipped pack). `resolveServerActionRecordId` returns it as `errorKey` beside the English `error`, and the runner's early refusal goes through its translator by that key. diff --git a/.changeset/13385-setup-managed-by-chip.md b/.changeset/13385-setup-managed-by-chip.md deleted file mode 100644 index 8591b8f74a..0000000000 --- a/.changeset/13385-setup-managed-by-chip.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@object-ui/react': minor -'@object-ui/components': minor -'@object-ui/app-shell': patch ---- - -A record page inside the Setup app no longer draws the floating managed-by badge (the amber "Identity" chip at the top-right of an organization, team, business unit or user record) (objectui#13385). The header's object label ("Organization") carries the badge's note instead: hovering or focusing it shows "Organization · Managed by the identity provider", and the note is the label's accessible description. The note is the badge's own tooltip title, under the same gate: only a caller who can author metadata sees it, and a `platform` object shows none. Every record page outside Setup, a `sys_*` object opened in another app included, and every list header keep the badge unchanged. - -`RecordContextValue` (`@object-ui/react`) gains an optional, host-injected `objectLabelNote`, which `page:header` forwards to `RecordTitleChip`. `RecordTitleChip` (`@object-ui/components`) gains an optional `objectLabelNote` prop: with it the object label becomes a focusable tooltip trigger described by the note; without it the label draws exactly as before. diff --git a/.changeset/13387-command-palette-query-change.md b/.changeset/13387-command-palette-query-change.md deleted file mode 100644 index f98981bc35..0000000000 --- a/.changeset/13387-command-palette-query-change.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -'@object-ui/app-shell': patch ---- - -Changing the ⌘K query no longer blanks the console (objectui#13387). - -The palette lists record hits under one heading per object. When a new query stopped finding an object, that object's heading went away while cmdk's own sort still walked it, and the error unmounted the whole console until a reload. The palette already decides which entries show (its own matching, and the server's ranked record hits), so cmdk's filter and sort are now off: what the palette renders is what shows, in the order it renders it. A record hit's value no longer carries the query. - -The palette also sits behind its own error boundary. An error inside it closes the palette and is reported; the console stays, and the next ⌘K opens a fresh palette. - -Clause-②: no -Metadata-protocol: none diff --git a/.changeset/13389-cjk-identifier-not-derived.md b/.changeset/13389-cjk-identifier-not-derived.md deleted file mode 100644 index f09e3f1ec0..0000000000 --- a/.changeset/13389-cjk-identifier-not-derived.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@object-ui/app-shell': patch ---- - -Studio says when a display name yields no identifier, and Add field no longer names a field `field_` behind the author's back (objectui#13389). - -A display name with no Latin letters (a Chinese one, say) makes no identifier, since identifiers take lowercase letters, digits and underscores only. Before this change the identifier box stayed empty and Create stayed off, and nothing said why. New object and the other Studio create dialogs now say it under the identifier and ask for one. On New package, the line under Package ID gives the same reason instead of "Filled in from the display name until you edit it". - -Add field shows the api name the label derives before Create. When the label derives none, or derives a name another field already has, the popover shows an API name box and Create waits for a name. Before, the field was created as `field_`, and that name becomes the column and the API field name once it is published. A Latin label works as before. diff --git a/.changeset/13390-line-axis-edge-labels.md b/.changeset/13390-line-axis-edge-labels.md deleted file mode 100644 index d1b1af2f13..0000000000 --- a/.changeset/13390-line-axis-edge-labels.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@object-ui/plugin-charts": patch ---- - -charts: a line or area chart no longer cuts its first or last x-axis label at the chart's edge. recharts draws their categorical x axis as a point scale, which puts the edge categories on the plot edges, so a monthly trend chart drew its newest bucket "2026-10" as "2026". The axis is now inset at both ends by half a `YYYY-MM` label at the tick font. Bar charts, whose band axis already centres every category, and combo charts, which draw a value axis on each side, are unchanged (objectui#13390). diff --git a/.changeset/13396-record-page-navigate-host.md b/.changeset/13396-record-page-navigate-host.md deleted file mode 100644 index cc553c0ad9..0000000000 --- a/.changeset/13396-record-page-navigate-host.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@object-ui/app-shell': patch ---- - -An action run from a record page's action bar with an `onSuccess.navigate` to a path with no app segment opens that page in the record page's app (objectui#13396). - -The record page mounts its own action provider, and its navigator still handed such a path to the router unchanged, so `onSuccess: { navigate: '/crm_opportunity/${result.id}' }` landed on Home there even after objectui#13379 fixed the same hop elsewhere in the console. The record page's navigator now sorts the path the way the console action runtime does and hosts it under the app in the record page's URL, opening `/apps/APP/crm_opportunity/...`. - -These are unchanged: a path that already names its app (`/apps/APP/...`), an external URL, a `mailto:` address, a `./` path, and a console route outside an app (`/forms/NAME`, `/home` and the other top-level routes). diff --git a/.changeset/13397-flow-row-guard.md b/.changeset/13397-flow-row-guard.md deleted file mode 100644 index cf41b9df31..0000000000 --- a/.changeset/13397-flow-row-guard.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'@object-ui/i18n': patch -'@object-ui/app-shell': patch ---- - -A record-scoped flow action launched from a list toolbar with 0 or several rows selected is refused before its param dialog opens, and its refusal is translated (objectui#13397). - -The console's `flowHandler` now carries `refuseBeforeInput`, the early refusal objectui#13384 gave the `script` handler, answered by the same resolver its dispatch runs. The runner asks it before the confirmation and the param dialog, so "select a row first" and "select exactly one row" show in the session's language before the user fills anything in, and nothing is sent. With exactly one row the flow behaves as before. A direct call that is refused at dispatch time is shown through the refusal's pack key too. - -The console server-action wrapper's `newTabUrl` refusal ("no record id available") now has a pack key, `console.serverAction.noRecordId`, defined in every shipped pack, and the wrapper's fast path shows the resolver's own refusal through its pack key. diff --git a/.changeset/13402-zh-override-wording.md b/.changeset/13402-zh-override-wording.md deleted file mode 100644 index bd1df51ae7..0000000000 --- a/.changeset/13402-zh-override-wording.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@object-ui/i18n': patch ---- - -zh-CN: the admin-override approval copy no longer calls the override 越权 ("exceeding one's authority", the word for a violation). The override levers now read 管理员代为通过 / 管理员代为拒绝 / 管理员代为转签 / 管理员代为撤回 (`approvalsInbox.overrideActionLabel` is `管理员代为{{action}}`), the history chip reads 管理员代办 (`viaOverrideChip`) and its hint names the 管理员代办 path (`viaOverrideHint`), and the confirmation notices say 以管理员身份代为处理 and 记录为管理员代办 (`overrideNotice*`, `overrideReassignNotice*`, `overrideRecallNotice*`). Only the zh pack changes; the rest of each sentence and every placeholder are unchanged (objectui#13402). diff --git a/.changeset/13403-object-chart-category-order.md b/.changeset/13403-object-chart-category-order.md deleted file mode 100644 index 157c53b3b6..0000000000 --- a/.changeset/13403-object-chart-category-order.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@object-ui/plugin-charts': patch ---- - -A page-level `object-chart` bound to a `dataset` now draws a select dimension in the order its field declares its options, the order the dashboard's dataset widget already uses for the same dataset (objectui#11809). Before, the page block drew the dataset's GROUP BY order (the stored values, alphabetically), so a priority axis read High, Low, Medium, Urgent instead of Low, Medium, High, Urgent (objectui#13403). The rows are charted in declared order, values the options do not declare follow, and the empty bucket comes last; the schema handed to the renderer also carries the `categoryOrder` from `@object-ui/core`'s `buildCategoryOrder`, which a funnel orders its stages by. A dimension whose field declares no options keeps the dataset's order. diff --git a/.changeset/13404-sankey-funnel-labels.md b/.changeset/13404-sankey-funnel-labels.md deleted file mode 100644 index ce08580188..0000000000 --- a/.changeset/13404-sankey-funnel-labels.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@object-ui/plugin-charts": patch -"@object-ui/i18n": patch ---- - -charts: a sankey now names every node and colours its flows, and a funnel labels every stage. Sankey nodes were bare bars with no text and every link was one grey, so the chart could not be read without hovering. Each node now carries its name (to its right, or to its left in the last column so it stays on the chart), and each link is stroked in the palette colour of the category it flows into. Every link leaves the same root node, so colouring by source would paint them all one colour again. A funnel labelled each stage to the right of its segment, past the plot's edge, so only the narrowest stage's label showed. Labels now sit centred inside their segments, in foreground text with a background halo so a name wider than the narrowest segment stays legible. The sankey's "Showing N of M rows" footnote now comes from the locale packs under the new count family `chart.sankeyOmittedRows`, translated in all ten packs. The English text is unchanged (objectui#13404). diff --git a/.changeset/13407-objectstack-pin-915e940.md b/.changeset/13407-objectstack-pin-915e940.md deleted file mode 100644 index 0516dc4413..0000000000 --- a/.changeset/13407-objectstack-pin-915e940.md +++ /dev/null @@ -1,6 +0,0 @@ ---- ---- - -No package released: the `@objectstack/*` pin moves from `830a63a6805f` to objectstack `915e940499` (objectstack#25489), past `925fd0772c` (objectstack#24947, a bulk action's `confirmText` is a template slot over `count` and its params), and nothing objectui publishes changes behaviour (objectui#13407). - -Only `.objectstack-sha` moves. The packed manifests in `.objectstack-pin/` and `pnpm-lock.yaml` are unchanged: the bump wrote byte-identical manifests, and `pnpm install` left the lockfile as it was. The pin stops before objectstack#25483 on purpose. The renderer already reads the `{ dialect: 'template', source }` envelope (objectui#13319), so the spec's widened `confirmText` type needs no source change here. diff --git a/.changeset/13408-assigned-users-confirm.md b/.changeset/13408-assigned-users-confirm.md deleted file mode 100644 index 140a3a6501..0000000000 --- a/.changeset/13408-assigned-users-confirm.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@object-ui/app-shell': patch ---- - -Setup → Permission Sets → Assigned Users: Remove asks first, and the add picker offers organization members only (objectui#13408), the same shape as the positions page (objectui#13337). - -- Removing a direct grant opens a confirm that names the person; nothing is sent until it is confirmed, and Cancel writes nothing. -- Add user reads the active organization's `sys_member` rows when it opens and offers only the users they name, so a user removed from the organization is no longer offered (the server already refuses such a grant). A refused membership read is said in the server's words and the picker stays shut. With no active organization, or no `sys_member` object registered, the picker lists every user it may read, as before. -- The membership read is one helper shared by both pages (`organization-members.ts`). diff --git a/.changeset/13410-chatbot-core-subpath.md b/.changeset/13410-chatbot-core-subpath.md deleted file mode 100644 index cd97346fb5..0000000000 --- a/.changeset/13410-chatbot-core-subpath.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -'@object-ui/plugin-chatbot': minor -'@object-ui/app-shell': patch -'@object-ui/console': patch ---- - -The Console's first page load no longer downloads the chat UI (objectui#13410). The `plugin-chatbot` chunk (169.6 KB gzipped, the third-largest eager chunk) and most of `vendor-markdown` used to load on every page, including for users who never open a chat, because the console shell imported a handful of small helpers from the `@object-ui/plugin-chatbot` package root, and the root re-exports the renderer that registers the chat components when it is evaluated. Measured on the Console's production build, the eager closure drops by 254,055 gzipped bytes (3,326,111 to 3,072,056). The chat now loads when it is first shown: opening the dock, visiting `/ai…` or `/s/:token`, or rendering a `chatbot`, `chatbot-enhanced` or `chatbot-floating` node. - -`@object-ui/plugin-chatbot` adds a side-effect-free `@object-ui/plugin-chatbot/core` subpath: `useAgents`, `resolveDefaultAgentName`, `PLATFORM_DEFAULT_AGENT`, `agentHasCapability`, the agent alias helpers (`AGENT_ALIAS_GROUPS`, `agentAliasGroup`, `agentRouteName`, `resolveAgentParam`, `isBuiltinAgentName`, `isBuildAgent`, `isAskAgent`), `AI_USAGE_REFRESH_EVENT`, `emitAiUsageRefresh`, `publishHealthFromResponse` and `detectPendingApproval`, with their types. Importing it registers nothing and reaches no chat UI module. The package root still exports every one of these names, unchanged. - -`@object-ui/app-shell` takes those names from `/core`, and the ChatDock loads its default chat body on first render instead of importing it. `resolveApiBase` is still exported from the same places. diff --git a/.changeset/13412-boolean-false-neutral.md b/.changeset/13412-boolean-false-neutral.md deleted file mode 100644 index 205ea890a7..0000000000 --- a/.changeset/13412-boolean-false-neutral.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@object-ui/fields': patch ---- - -A boolean renders the same whatever its name (objectui#13412). `BooleanCellRenderer` drew a red destructive "LABEL — Off" badge for `false` when the field was named `active`, `is_active`, `enabled`, `is_enabled`, `verified` or `is_verified`, so a plain `Field.boolean` named `verified` read as an error on every new record, in lists and on the record page. Those names now draw the same unchecked checkbox as any other boolean, named by the field's label, and `true` still draws the checked box. The completion indicator for `completed`, `is_completed`, `done` and `is_done` is unchanged. diff --git a/.changeset/13427-external-org-role.md b/.changeset/13427-external-org-role.md deleted file mode 100644 index 43bab54ffd..0000000000 --- a/.changeset/13427-external-org-role.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@object-ui/auth': minor -'@object-ui/i18n': patch ---- - -The console knows the `external` organization role that objectstack#25515 added to `@objectstack/spec`'s membership vocabulary (objectui#13427). Without it `ORG_ROLE_LABELS` no longer type-checked against an `@objectstack/spec` that lists the role. - -`@object-ui/auth` exports `ORG_ROLE_EXTERNAL` and labels it (`organization.roles.external`, "External"). Every pack in `@object-ui/i18n` carries the key; zh reads 外部成员, as the server's own `sys_member.role` option does. Wherever the installed spec lists the role, the invite dialog offers it to every issuer who can invite, a delegated admin included, because objectstack's invitation cap admits it from any issuer: it confers less than a member. Owners and admins can also set it from the members page. On the grade ladder it sits with `member`, as it does in objectstack's cap, so it never unlocks an administrative affordance. diff --git a/.changeset/13433-form-action-in-app-shell.md b/.changeset/13433-form-action-in-app-shell.md deleted file mode 100644 index 7521c6bfdb..0000000000 --- a/.changeset/13433-form-action-in-app-shell.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -'@object-ui/app-shell': patch -'@object-ui/console': patch ---- - -A `type: 'form'` action fired inside an app opens its form inside that app, headed by a label, with a Cancel (objectui#13433). - -The form opened on the app-less `/forms/:name`, so the app's sidebar, switcher and branding disappeared. The page was headed by the raw view name (`showcase_task.form`) and had only Submit, so the browser's Back button was the only way out without saving. - -- The console now also serves the form at `/apps/:appName/forms/:name`, inside the app's own shell. The record page, object list and page action navigators open a form hop there when their own route is an app route. The console-wide runtime has no route of its own, so its form hops keep the app-less route. `/forms/:name` is unchanged and still serves every other link. -- A form view with no label and no form `title` is headed by its object's label in the session's language. An authored view label or `title` still wins. -- The internal form has a Cancel. It goes back to the page the form was opened from. With no such page (a cold link) it goes to the record being edited, else to the app's home, or to Home on the app-less route. The public `/f/:slug` form has no Cancel. diff --git a/.changeset/13436-create-form-readonlywhen.md b/.changeset/13436-create-form-readonlywhen.md deleted file mode 100644 index 2c5cf3c65b..0000000000 --- a/.changeset/13436-create-form-readonlywhen.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@object-ui/components": patch ---- - -A create form no longer locks fields through `readonlyWhen`. The server does not apply `readonlyWhen` on insert, but the form evaluated it against the seeded defaults, so a predicate over a defaulted column (`record.status == 'pending_verify'` with `status` defaulting to `'pending_verify'`) or a `!=` over an unset one (`record.approval_status != 'returned'`) rendered fields read-only on New that the API accepts. `readonlyWhen` now applies only to an edit form (one given `previousValues`), and no longer warns a fault on a create form; static `readonly: true` still locks on create, and `visibleWhen` / `requiredWhen` are unchanged. diff --git a/.changeset/13440-objectstack-pin-e649c2d.md b/.changeset/13440-objectstack-pin-e649c2d.md deleted file mode 100644 index c839d79ca7..0000000000 --- a/.changeset/13440-objectstack-pin-e649c2d.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@object-ui/auth': patch ---- - -The `@objectstack/*` pin moves from `915e940499` to objectstack `e649c2d91e`, the 18.1.0 release commit (objectstack#25606), past objectstack#25483 and objectstack#25564, which ship together in that release (objectui#13440). - -`@object-ui/auth` now takes `ORG_ROLE_EXTERNAL` from `@objectstack/spec`'s `MEMBERSHIP_ROLE_EXTERNAL` instead of spelling the literal. The exported name and its value (`'external'`) are unchanged, and `ORG_ROLE_LABELS` is typed by `OrgRole` alone again. The published module now imports that constant, so it needs an `@objectstack/spec` that exports it (18.1.0 or later); the publish step floors the `@objectstack/*` ranges at the release that contains the pin. With that spec the invite dialog lists `external` among the roles it offers, as objectui#13427 described for a spec that lists the role. diff --git a/.changeset/25330-bar-one-series-colour.md b/.changeset/25330-bar-one-series-colour.md deleted file mode 100644 index c74ad6fbbe..0000000000 --- a/.changeset/25330-bar-one-series-colour.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@object-ui/plugin-charts': patch ---- - -A single-series bar chart draws every bar in its series colour (objectstack#25330). - -A bar or horizontal-bar chart with one measure used to paint each bar a different palette colour, so the colour named nothing: the System Overview "Events by User" board drew each user in its own hue. A bar's colour now names its series. A dimension's semantic option colour (a select field's `options[].color`, such as health green/red/yellow) still paints its own bar; a category without one takes the series colour instead of a palette slot. Pie and donut slices keep one colour per category, and a chart with two or more series keeps one colour per series. diff --git a/.changeset/25330-carry-credential-meta.md b/.changeset/25330-carry-credential-meta.md deleted file mode 100644 index 4aea3453dd..0000000000 --- a/.changeset/25330-carry-credential-meta.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@object-ui/types": patch ---- - -types: a node derived from an `@objectstack/spec` schema keeps the spec's `credential` registry key (`'value' | 'map'`, objectstack#25036, which marks the webhook's `secret` and `headers` as credential fields). `credential` joins `CARRIED_REGISTRY_META_KEYS`, so the derivation no longer drops it. The pin move to objectstack 830a63a6 put the key on the published surface, and the registry census (objectui#9102) reported it as unclassified. diff --git a/.changeset/25330-dataset-null-label.md b/.changeset/25330-dataset-null-label.md deleted file mode 100644 index 802732b4f9..0000000000 --- a/.changeset/25330-dataset-null-label.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@object-ui/plugin-dashboard": patch ---- - -dashboard: a dataset chart draws its null bucket under the name the dataset declares for it (`fields[].nullLabel`, the dimension's `nullLabel` resolved by the server), over the global `chart.nullCategory` default. System Overview's "Events by User" now reads "System" for the rows the platform writes itself instead of "(None)". A column without one keeps the locale default, and a two-dimension pivot takes a declared name only when both dimensions declare the same one (objectstack#25330). diff --git a/.changeset/25333-position-list-holders-and-grants.md b/.changeset/25333-position-list-holders-and-grants.md deleted file mode 100644 index efbb9f804e..0000000000 --- a/.changeset/25333-position-list-holders-and-grants.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -'@object-ui/app-shell': minor -'@object-ui/data-objectstack': minor ---- - -Setup → Positions now says who holds each position and which permission sets it grants, and a click anywhere on a row opens the item (objectstack#25333). - -- **Two columns, both the server's.** The position list reads `GET /meta/position?include=grants`. **Holders** shows the served `_holderCount`, and **Permission sets** shows the served `_grantedPermissionSets` in the order the server sends them. The server computes both where the authorization resolver enforces them, and the console computes neither. -- **The set a position grants by its name is shown, marked "(by name)".** That set shares the position's name, and the position-name fold grants it even though the definition does not list it (objectstack#24757). A tooltip says why it is there. Sets the definition lists carry no mark. -- **A count nobody measured is "—", never 0.** That covers a count the server did not serve (`null`: no active organization, or a caller who may not read position assignments) and a server that predates `include=grants`. -- **The whole row opens the item** on every Setup metadata list, as a record list's row does. The first cell keeps its link for the keyboard, screen readers and opening in a new tab. A click on a control in the row (the Active switch, Clone, a link) is still that control's. A modified click, a click that ends a text selection, and a click inside a dialog a row control opened do not open the row. -- **`@object-ui/data-objectstack`**: `MetadataClient.list` / `listResponse` accept `include: 'grants'`, sent as the `include` query parameter. diff --git a/.changeset/25338-no-readable-object-landing.md b/.changeset/25338-no-readable-object-landing.md deleted file mode 100644 index 89d00b75dd..0000000000 --- a/.changeset/25338-no-readable-object-landing.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -'@object-ui/app-shell': patch -'@object-ui/i18n': patch ---- - -A member who may read none of the objects an app names now lands on one page that says they need access and whom to ask, instead of the app's dashboard drawn as a grid of "You don't have access" tiles (objectstack-ai/objectstack#25338). - -The app root's landing asks the object-read prune's own verdict (`useNavMemberGates().can`) over every `type: 'object'` entry the app names, at every depth and in every area. When the app names at least one object and the member may read none of them, it renders `AppNoAccessEmptyState` with the new `reason="no-readable-object"`: "Your account cannot read any of the records in this app yet. Ask an administrator to assign you a permission set.", plus the Setup link for a member who may grant access. One readable object, or an app that names no object at all, lands exactly as before. - -Clause-②: yes -Metadata-protocol: none diff --git a/.changeset/25438-bulk-confirm-text-source-optional.md b/.changeset/25438-bulk-confirm-text-source-optional.md deleted file mode 100644 index 6d7b396807..0000000000 --- a/.changeset/25438-bulk-confirm-text-source-optional.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@object-ui/types': patch ---- - -`BulkActionDef.confirmText`'s template envelope types `source` as optional, as `@objectstack/spec`'s `Expression` does, and so does its zod twin (objectstack#25438). - -`@objectstack/spec` made a bulk action's `confirmText` a `template` slot (objectstack#24947), and its envelope carries `source` or `ast`. With `source` typed as required, `@object-ui/plugin-view` refused the spec's own bulk action type when it handed a named view's `bulkActionDefs` to the grid, so the console no longer built against the current spec. The confirm step is unchanged: an envelope with no `source` shows the default sentence ("This will apply to N record(s)."). diff --git a/.changeset/7611-registry-capability-lint.md b/.changeset/7611-registry-capability-lint.md deleted file mode 100644 index f80e0e1162..0000000000 --- a/.changeset/7611-registry-capability-lint.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -'@object-ui/app-shell': patch ---- - -Publish from Home no longer reports a `defineCapability` declaration as a capability that resolves nowhere (objectui#7611). - -The advisory capability-reference lint that runs over pending drafts before **Publish** handed `@objectstack/lint`'s `validateCapabilityReferences` the drafts and the permission sets only, so a capability a package declares with `defineCapability` and no permission set grants yet was flagged on every object, field, action or app draft that required it. The lint now also reads the capabilities the registry serves (`GET /api/v1/meta/capability`) into the rule's `capabilities` source. A misspelled capability is still reported. If that read fails, the lint runs on the other sources as before and never blocks publishing. - -Internal, no behaviour change: `approverIdentity` drops a display-column entry for `sys_position`, which no approver binding has named since `position` became registry-bound. - -Clause-②: no -Metadata-protocol: none diff --git a/.changeset/cell-text-selection.md b/.changeset/cell-text-selection.md deleted file mode 100644 index 84c9e326f5..0000000000 --- a/.changeset/cell-text-selection.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@object-ui/components": patch -"@object-ui/plugin-grid": patch ---- - -data-table / VirtualGrid: selecting a cell's text no longer opens the record or starts an inline edit, and Ctrl/Cmd+C copies the selected text instead of the whole cell value. A plain click still opens or edits as before (objectui#13188). diff --git a/.changeset/rich-text-display-sanitizer.md b/.changeset/rich-text-display-sanitizer.md deleted file mode 100644 index 2cd49abac8..0000000000 --- a/.changeset/rich-text-display-sanitizer.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@object-ui/fields': patch ---- - -`html` and `richtext` values are now sanitized with `rehype-sanitize`, the sanitizer the `markdown` pipeline already used, instead of a hand-written pattern filter. - -A stored value is parsed with the browser's HTML parser, filtered against one allow-list of elements, attributes and URL protocols, and rendered as React elements. Both display pipelines share that allow-list. Headings, paragraphs, emphasis, lists, quotes, code, tables, links and images keep their formatting. Event-handler attributes, `style`, script-bearing URLs, embedded frames and objects, and SVG and MathML content are dropped. A link whose URL is refused now renders without an `href`, where it used to point at `#`. Stored `id` and `name` values are prefixed with `user-content-`. diff --git a/.changeset/select-all-align.md b/.changeset/select-all-align.md deleted file mode 100644 index 0f2f941164..0000000000 --- a/.changeset/select-all-align.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@object-ui/components": patch ---- - -data-table: with row numbers on, the header's select-all checkbox, each row's checkbox and the row number now share one centre line in the leading column (objectui#13293). diff --git a/.changeset/settings-visible-expression-interpreter.md b/.changeset/settings-visible-expression-interpreter.md deleted file mode 100644 index e4702dd7e0..0000000000 --- a/.changeset/settings-visible-expression-interpreter.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@object-ui/console': patch ---- - -Settings: a setting's `visible` predicate is evaluated with the renderer's expression interpreter, and a predicate that does not evaluate hides the setting. - -The settings page used to compile a manifest's `visible` string into a JavaScript function and show the setting whenever that failed. It now evaluates the string with `ExpressionEvaluator` from `@object-ui/core`, the CSP-safe interpreter every other `visible` predicate in the renderer uses, with the namespace's values bound as `data` (`${data.provider === 'cloudflare'}`). A predicate it cannot evaluate hides the setting, the same way the server refuses a save whose `visible` it cannot parse. Every predicate the shipped manifests declare (comparisons, `&&`, `||`, `!` over `data.`) reads as before. diff --git a/.changeset/user-filters-all-records-label-13405.md b/.changeset/user-filters-all-records-label-13405.md deleted file mode 100644 index 2af0e29a3b..0000000000 --- a/.changeset/user-filters-all-records-label-13405.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@object-ui/plugin-list': patch -'@object-ui/i18n': patch ---- - -fix(plugin-list): the synthetic "All records" tab of a tabs-mode user-filter bar (`showAllRecords`) now reads its label from the new `list.userFilters.allRecords` i18n key, filled in every shipped locale (zh: 全部记录), instead of a hard-coded English string (objectui#13405). The tab's `__all__` id and behaviour are unchanged. diff --git a/QUICK_REFERENCE.md b/QUICK_REFERENCE.md index 428aa5686d..097d88086c 100644 --- a/QUICK_REFERENCE.md +++ b/QUICK_REFERENCE.md @@ -125,7 +125,7 @@ release path runs the sync itself: `changeset:version` bumps every manifest and this block in the same commit, so a release can no longer leave the block a version behind (objectui#5394 — that had happened once per release, three times). -- **Version:** 18.0.0 (the version every `@object-ui/*` manifest carries — they are one +- **Version:** 18.1.0 (the version every `@object-ui/*` manifest carries — they are one `fixed` group in `.changeset/config.json`, so a release moves all of them together) - **Spec:** `@objectstack/spec` ^18.0.0-next.1 (declared by the root `package.json` and by `apps/console/package.json`) diff --git a/apps/console/CHANGELOG.md b/apps/console/CHANGELOG.md index da1fb2413b..07e2934a5a 100644 --- a/apps/console/CHANGELOG.md +++ b/apps/console/CHANGELOG.md @@ -1,5 +1,44 @@ # @object-ui/console +## 18.1.0 + +### Patch Changes + +- a91f6bb: The Approvals Inbox opens a request on the page the platform serves for it, and its side sheet is gone (objectui#12484). + + A row, a mobile card, Enter on the focused row, and a notification's `?request=` deep link now open the request's record page: the `sys_approval_request_detail` page `@objectstack/plugin-approvals` serves, on the console's standard record route. That page shows the request's title (the flow's label), its decision panel (the declared amount and snapshot summary, the approvers, the step line and the decisions), its highlights, its target record, and its timeline. The deep link takes its own place in the browser history, so Back returns to where the reader came from; from a row, Back returns to the inbox. + + The inbox's own request sheet is deleted. Its quick paths stay: inline approve and reject, bulk decisions, filters, sorting and keyboard navigation. +- 0093b2c: Settings pages: a `url`, `email`, `phone` or `color` value that misses the format its type declares now blocks Save (objectui#13287). No request goes out, the row is marked inline with a message naming what the format expects, and focus moves to the first such row, on the same path as the `required` check. The grammars are the settings service's own (objectstack#24882), judged on the trimmed value; an empty value is left to `required`, and a hidden or env-locked row is not judged. Adds `console.settingsView.invalidPhone` and `console.settingsView.invalidColor` to every locale pack; `email` and `url` reuse `validation.email` and `validation.url`. +- 0d12e95: An approver who is not an administrator sees the whole approval request page again: its fields, its decision panel with the decisions they may take, and its Timeline (objectui#13324). + + The console reads a request, and its timeline, through the approvals routes, which serve a request to each party to it. The record page then gated what it drew on the permissions answer for the data API, which names neither approval object for a member, because the platform keeps that door closed to them. So the page folded the request down to its id, drew no decision, and dropped the Timeline. Opening a request from the Approvals inbox showed a blank page. + + `@object-ui/permissions` adds `ServerReadScope`. Below it, the read verdicts for the objects it names (`check(object, 'read')` and `checkField(object, field, 'read')`) answer "allowed": whatever the server serves is what the viewer may read. Every other action, the field write and create verdicts, and every other object keep the enclosing provider's answer. The console mounts it for the two approval objects over every app. No read grant on either object is added: the data API stays closed to members. +- 4824ad7: A form field entry whose `label`, `placeholder` or `helpText` is an inline locale map (`{ en, 'zh-CN' }`) now renders in the visitor's language, on the public form `/f/:slug` and on the signed-in `/forms/:name` route (objectui#13380). + + `@objectstack/spec` types all three keys as `I18nLabel`, so the map is valid metadata, but the form page passed it straight into text slots: a map on a label or help line blanked the page for every visitor (React error #31), and one on a placeholder read `[object Object]`. The map is now collapsed to the visitor's language when the form's rows are built, with the same resolver the console uses for an action's inline-map copy. A plain-string entry renders exactly as before. +- d17f670: A Setup settings page reads its namespace again after a successful save or action, and takes the whole answer, manifest included (objectui#13382). The server computes parts of a namespace's manifest on every read: objectstack#25448 puts a live-status banner first on the page, so Setup → Email says whether mail leaves the machine. The page used to merge only the saved values and keep the manifest from its first load, so after an administrator configured SMTP the banner still said no mail leaves the machine until the page was reloaded. + + The re-read does not show the loading placeholder. An action leaves the unsaved edits as they are. If the re-read fails, the page keeps the saved values and the success message, and does not turn into an error. +- 3a8a117: Integrations → Connect an AI agent no longer mints an API key in one click (objectui#13383). "Generate key" stays disabled while the name box is blank or whitespace-only, and the name is sent trimmed: a cleared box no longer mints a key under the default name `Agent key`. Clicking "Generate key" now opens an in-app confirm naming the key; Cancel creates nothing, and confirming creates the key and shows it once, as before. The name box still opens prefilled with `Agent key`, which is minted only once the administrator confirms it. This matches the Connect an Agent card (objectui#13355). +- 47138b7: The Console's first page load no longer downloads the chat UI (objectui#13410). The `plugin-chatbot` chunk (169.6 KB gzipped, the third-largest eager chunk) and most of `vendor-markdown` used to load on every page, including for users who never open a chat, because the console shell imported a handful of small helpers from the `@object-ui/plugin-chatbot` package root, and the root re-exports the renderer that registers the chat components when it is evaluated. Measured on the Console's production build, the eager closure drops by 254,055 gzipped bytes (3,326,111 to 3,072,056). The chat now loads when it is first shown: opening the dock, visiting `/ai…` or `/s/:token`, or rendering a `chatbot`, `chatbot-enhanced` or `chatbot-floating` node. + + `@object-ui/plugin-chatbot` adds a side-effect-free `@object-ui/plugin-chatbot/core` subpath: `useAgents`, `resolveDefaultAgentName`, `PLATFORM_DEFAULT_AGENT`, `agentHasCapability`, the agent alias helpers (`AGENT_ALIAS_GROUPS`, `agentAliasGroup`, `agentRouteName`, `resolveAgentParam`, `isBuiltinAgentName`, `isBuildAgent`, `isAskAgent`), `AI_USAGE_REFRESH_EVENT`, `emitAiUsageRefresh`, `publishHealthFromResponse` and `detectPendingApproval`, with their types. Importing it registers nothing and reaches no chat UI module. The package root still exports every one of these names, unchanged. + + `@object-ui/app-shell` takes those names from `/core`, and the ChatDock loads its default chat body on first render instead of importing it. `resolveApiBase` is still exported from the same places. +- 576fd25: A `type: 'form'` action fired inside an app opens its form inside that app, headed by a label, with a Cancel (objectui#13433). + + The form opened on the app-less `/forms/:name`, so the app's sidebar, switcher and branding disappeared. The page was headed by the raw view name (`showcase_task.form`) and had only Submit, so the browser's Back button was the only way out without saving. + + - The console now also serves the form at `/apps/:appName/forms/:name`, inside the app's own shell. The record page, object list and page action navigators open a form hop there when their own route is an app route. The console-wide runtime has no route of its own, so its form hops keep the app-less route. `/forms/:name` is unchanged and still serves every other link. + - A form view with no label and no form `title` is headed by its object's label in the session's language. An authored view label or `title` still wins. + - The internal form has a Cancel. It goes back to the page the form was opened from. With no such page (a cold link) it goes to the record being edited, else to the app's home, or to Home on the app-less route. The public `/f/:slug` form has no Cancel. +- 06ce712: Settings: a setting's `visible` predicate is evaluated with the renderer's expression interpreter, and a predicate that does not evaluate hides the setting. + + The settings page used to compile a manifest's `visible` string into a JavaScript function and show the setting whenever that failed. It now evaluates the string with `ExpressionEvaluator` from `@object-ui/core`, the CSP-safe interpreter every other `visible` predicate in the renderer uses, with the namespace's values bound as `data` (`${data.provider === 'cloudflare'}`). A predicate it cannot evaluate hides the setting, the same way the server refuses a save whose `visible` it cannot parse. Every predicate the shipped manifests declare (comparisons, `&&`, `||`, `!` over `data.`) reads as before. +- @object-ui/sdui-parser@18.1.0 + ## 18.0.0 ### Major Changes diff --git a/apps/console/package.json b/apps/console/package.json index b897e199d0..723e5dc8ed 100644 --- a/apps/console/package.json +++ b/apps/console/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/console", - "version": "18.0.0", + "version": "18.1.0", "description": "ObjectStack Console — opinionated, fork-ready runtime console built on @object-ui/app-shell with the full plugin set wired up. Ships as a Hono UI plugin serving a pre-built SPA.", "license": "MIT", "type": "module", diff --git a/packages/app-shell/CHANGELOG.md b/packages/app-shell/CHANGELOG.md index 14334ee38b..4671479e51 100644 --- a/packages/app-shell/CHANGELOG.md +++ b/packages/app-shell/CHANGELOG.md @@ -1,5 +1,276 @@ # @object-ui/app-shell — Changelog +## 18.1.0 + +### Minor Changes + +- a14737b: Setup → Positions now says who holds each position and which permission sets it grants, and a click anywhere on a row opens the item (objectstack#25333). + + - **Two columns, both the server's.** The position list reads `GET /meta/position?include=grants`. **Holders** shows the served `_holderCount`, and **Permission sets** shows the served `_grantedPermissionSets` in the order the server sends them. The server computes both where the authorization resolver enforces them, and the console computes neither. + - **The set a position grants by its name is shown, marked "(by name)".** That set shares the position's name, and the position-name fold grants it even though the definition does not list it (objectstack#24757). A tooltip says why it is there. Sets the definition lists carry no mark. + - **A count nobody measured is "—", never 0.** That covers a count the server did not serve (`null`: no active organization, or a caller who may not read position assignments) and a server that predates `include=grants`. + - **The whole row opens the item** on every Setup metadata list, as a record list's row does. The first cell keeps its link for the keyboard, screen readers and opening in a new tab. A click on a control in the row (the Active switch, Clone, a link) is still that control's. A modified click, a click that ends a text selection, and a click inside a dialog a row control opened do not open the row. + - **`@object-ui/data-objectstack`**: `MetadataClient.list` / `listResponse` accept `include: 'grants'`, sent as the `include` query parameter. + +### Patch Changes + +- b001d21: The README's "Setup half of an item" now says what objectstack's shipped organization administrator set does on the assignment objects: it creates and removes rows on `sys_user_position` and `sys_user_permission_set` and never edits them, bounded on the server by the delegated-administration gate, so that administrator sees Add and Remove on a position's and a permission set's holders. No behaviour change. +- 36b70c0: The package edit dialog (Studio / Setup) now edits a package's `dependencies`. The row is no longer locked once the package exists, and saving sends it to `PATCH /api/v1/packages/:id` beside the name, description and version when the author changed it; emptying it sends `{}`, which clears the declaration. The server's `400 VALIDATION_ERROR` for a malformed row and `422 WRITABLE_PACKAGE_REQUIRED` for a read-only package show in the dialog, which stays open. +- 5235d6d: Setup › Packaged automation: the clone result now offers the next steps (objectui#13270). + + A clone of a packaged flow is created `draft`, which does not switch it off, so a cloned record-change or schedule flow runs beside the flow it was copied from. The result used to show the server's notice and nothing to click. It now keeps that notice and adds: + + - **Switch "SOURCE" off** — calls the same packaged-flow toggle as the row's own switch, for the flow that was cloned. On success the row reads off and the result says the source is switched off. A refusal shows the server's message beside the button, and the button stays. When the source is already off, no switch-off is offered. + - **Open the clone in Studio** — links the package-less Studio scope (`/studio/~org/automations`) opened on the clone. + + The clone itself is unchanged. Three new language-pack keys, `packagedAutomation.cloneSwitchSourceOff`, `.cloneSourceOff` and `.cloneOpen`, in all ten packs. +- cf153eb: The permission-set editor no longer keeps the clone notice once the copy is held or saved (objectui#13272). + + "Clone to customize" opens the copy with the server's notice: what was not copied, and that the copy is held by nobody yet. The notice is the server's answer at the moment of the clone. It stayed on the copy for as long as the copy was open, so after a user was assigned and the copy was saved it still said nobody held it. The notice now goes when the copy's Assigned Users list first shows anyone (a direct grant or a holder through a position), or when a save of the copy succeeds. A refused save keeps it, and so does a failed read of the holders. On an embedded host, where the copy is announced on the set it was cloned from, saving that set keeps it too. While the notice shows, it is still shown whole and in the server's words. +- 9e1bff6: The app's report index (`/apps/APP/reports`) and the ⌘K palette's report list now include the reports a module contributes to the app's navigation (`navigationContributions`), not only the reports the app's own package owns. The index lists the union of the app package's reports and every report a `type: 'report'` navigation entry names, deduplicated by name; an entry naming a report the server does not serve is left out, and the dataset read gate still hides a report the member may not read. +- 53dea27: The package dialog's Dependencies row is now an author-facing editor (objectui#13278). It used to be the spec form's raw JSON box under the developer hint "widget object-fields — falling back to JSON until a custom renderer is registered", because the manifest's `dependencies` is a string map the spec form has no renderer for. + + The row now lists one line per dependency, a package name and a version range, with add and remove, in create, edit and view mode. It sends the same flat map as before: in edit mode only when changed, and `{}` when every row is removed. An empty or duplicate package name is flagged under its row and keeps save disabled. The ranges are judged by the server, whose refusals render in the dialog as before. + + Nothing is added to the package entry: no export, prop or type member. The new copy lives in the metadata-admin designer's own string tables (en and zh). +- 7e9708e: The console home blocks `hero`, `stat`, `usage-bar`, `checklist` and `tile-grid` register under the `app-shell` namespace, so the console no longer logs a "without a namespace is deprecated" warning for each on every boot (objectui#13301). + + Pages keep writing the bare key: `type: 'hero'` still draws the block through the registry's bare fallback. `objectui check` now knows the five `app-shell:` keys as registered, and `objectui validate` refuses them at `type`, so the bare spelling stays the one authorable key. +- 2794254: The Position preview lists the permission sets a position declares in `permissionSets` (ADR-0131 D4), by machine name in declared order. The "positions don't grant data access on their own — bind it to Permission Sets" note now shows only for a position that declares none (objectui#13304). +- 78bd6d7: The `/data` page's generated filter bar now offers single-value relation fields (`lookup`, `master_detail` and `user`) beside the picklist fields (objectui#13310). A relation chip opens the list's existing remote-search picker, which queries the related object through the caller's data source, and a pick filters the rows by the related record's id. The selection persists in the same `uf_*` URL params as the picklist filters, so it survives a reload; an id that no longer resolves shows as the id. + + So an organization's Members "View all" page, which anchors no declared view, can now be filtered by User as well as by Role. + + Picklist fields keep their slots: relation fields follow them in declaration order and take only the slots the picklists leave under the bar's four-field cap. A multi-value relation (`multiple: true`), a hidden field and a field the caller cannot read are not offered. An object without a single-value relation field renders the same bar as before. +- 56cf4d8: The Import Wizard sends a CSV file to the import door as CSV text (objectui#13315). When you import a `.csv`, `.tsv` or `.txt` file, the request is now `format: 'csv'` with the rows the preview shows written out as CSV. This holds on the hand-mapped path, and with a saved mapping that does not declare `sourceFormat: 'json'`. Before, those rows were sent as JSON, so the server never read the file's cells through its CSV import rule, the one its CSV export pairs with. + + - **The text is the preview's rows.** The wizard writes the CSV from the rows it shows, not from the file as uploaded, as it already did for a mapping that declares `sourceFormat: 'csv'`. A cell you corrected in the preview is sent corrected. The dry-run check sends the same request as the import. + - **Unchanged:** an `.xlsx` sheet and a pasted table are sent as JSON rows. A saved mapping that declares `sourceFormat: 'json'` still gets JSON rows from any file, because the import door does not accept CSV text for it. + - **User import** (`sys_user`) sends a CSV file as CSV text too, in batches of at most 500 rows. Each one-time password is still shown with the email or phone number of its row. + + Three shapes now import differently from what the preview shows: + + - **A last row whose mapped cells are all empty is not imported.** When the file's last row, or a run of last rows, has data only in columns you did not map, the server does not read it. The import counts one row fewer than the preview, and that row creates no record and reports no error. A row of that shape anywhere else in the file is imported as before, so row numbers keep matching the preview. User import sends the file in batches of 500 rows, so there the same holds for the last row of each batch. + - **A cell that begins with an apostrophe and ends in a tab or a line break keeps the apostrophe** when the rest of it starts with `+` or `-` and holds only digits, spaces and `( ) + - . ,`. The preview trims the tab or line break before the cell is sent, and a server whose CSV import removes the apostrophe the CSV export adds leaves this trimmed cell as it is. The wizard imported such a cell with its apostrophe before this change too. + - **A space before a leading apostrophe is trimmed first.** On a server whose CSV import removes the apostrophe the CSV export adds, a cell typed as a space, an apostrophe and a value the export would write with an apostrophe now imports without the apostrophe. Before this change it imported with it. + + No export, prop or type is added to either package entry. +- b8fa223: Setup → Datasources offers "Sync objects" only on a datasource that can be synced (objectui#13318). + + The server refuses every Sync step (listing remote tables, drafting and importing an object) on a datasource whose schema mode is `managed`, with a `400` that names the rule and the remedy. A datasource saved without a schema mode is managed too, and so is the platform's `default` datasource. The page still showed the button on every row, so on such a row it opened a dialog that could only show the refusal. + + The button now shows only on a row whose schema mode is `external` or `validate-only`, and never on the `default` row. To sync from a managed datasource, edit it and set its Schema mode to External or Validate only. +- b911ebb: A navigation entry's API `dataSource` and a page element bound to the same read now make one request per console open (objectui#13323). Before, `readElementApi` shared a request only while it was in flight, so when the sidebar's read for an entry's `visible` had settled before the page element mounted, the element sent a second `GET` for an answer the console already held. + + `@object-ui/react` exports `ElementApiOpenScope` (with `useElementApiOpen` and the `ElementApiOpen` type): inside it, a read that has already answered under the same `open` name is answered again with no request. A failed read is not kept, a read under another `open` asks again, and any `notifyDataChanged` drops what the open kept. `readElementApi` takes the open as an optional third argument; without one it behaves as before. + + `@object-ui/app-shell`'s `ConnectedShell` mounts the scope and names one open per visit of a history entry: following a link or a navigation entry, and Back or Forward, start a new open and read again, even on an entry visited before; a redirect that replaces the address (the app root's landing on its first entry) stays in the open. A language switch starts over. No read happens at a different time than before; only whether a second read in one open reaches the network changes. +- ff77cfc: On a cloud-managed environment (`features.cloudManaged: true` from `/auth/config`), the console says what the server already enforces. Setup → Users shows one line saying where people are invited (the organization, in the cloud) and marks a user who holds no permission set beyond the baseline as "Not authorized", read from their `sys_user_permission_set` and `sys_user_position` rows. The identity import entry is not offered, the organization members page shows a note instead of Invite member, and the recovery-password reminder does not show. With the flag absent or `false`, nothing changes. + + `AuthPublicConfig['features']` gains `cloudManaged`. `ObjectGrid` gains the `rowAdornment` host prop, a node drawn beside one row's title (the declared name field's cell, else the first shown column, and the card title in the card view), and `ListView` forwards its own `rowAdornment` to the grid. + + Clause-②: yes + Metadata-protocol: none +- 241cb78: Setup refusals lead with one plain sentence. The Packages sheet, the metadata editor's error banner (Positions and every other metadata type) and the action parameter dialog (OAuth application registration among them) now show the first sentence of the server's message, without a leading bracketed code or field path and without the trailing declared code. The whole message, byte for byte, sits behind a "More" toggle with a copy button. A one-sentence message renders as before. New `refusalDetails.*` strings in all ten locale packs (objectui#13332). +- 404ccae: Setup's metadata deletes and the related list's row delete now ask in the console's in-app confirm dialog and name what goes (objectui#13333). + + - The metadata editor's Reset overlay / Delete and Discard draft, the history timeline's Rollback, the Datasources page's Delete and a metadata type's `confirmText` action no longer use the browser's native `confirm()`. Each opens an in-app AlertDialog whose title names the item: by its type label and its own label for Reset / Delete (for example `Delete Object "Account"?`), with the machine `type/name` in the body; by label and name for a datasource; by action and item for a type action. + - The related list's row Delete no longer asks "Are you sure you want to delete this record?". The sentence names the row by its record title, the same resolver the record header uses, so a grant row reads by its declared title (the grant and the user it belongs to). The `detail.deleteRowConfirmation` string now takes a `{{name}}` value in all ten locales. +- fb25620: A sidebar navigation group now opens on first view unless it declares `expanded: false` (or the legacy `defaultOpen: false`), however many entries it holds (objectui#13336). + + `NavigationRenderer` used to collapse any group that declared neither field once it had eight or more children. On Setup that closed Configuration (13 entries) although only Advanced declares `expanded: false`, hiding entries such as Localization, Email and Authentication on first view. The count rule is gone: a group holding the current route opens; otherwise its declared `expanded` / `defaultOpen` decides; otherwise it opens. Studio's navigation preview follows the same rule, so it still matches the running sidebar. + + An app that relied on a long, undeclared group starting closed should now declare `expanded: false` on it. +- 3ec84be: Setup → Positions: a new position is created together with its permission sets, Save is labelled, Remove holder asks first, and the holder picker offers organization members only (objectui#13337). + + - New Position shows the Permission Sets picker beside the label, name and description, so binding a set no longer takes a first save and a second edit. + - The metadata editor's Save draws the word "Save" beside its icon. Its accessible name and tooltip are unchanged: the shortcut hint, or why Save is withheld. + - Removing a position holder opens a confirm that names the person; nothing is sent until it is confirmed. + - Add holder reads the active organization's `sys_member` rows when it opens and offers only the users they name, so a user removed from the organization is no longer offered (the server already refuses such an assignment). With no active organization, or no `sys_member` object registered, the picker lists every user it may read, as before. +- fcbf1b2: Setup's Permission Sets and Positions lists ask before the Active switch turns an item off, and a toast confirms the change either way (objectui#13338). + + Switching a permission set or a position off opens a confirm that names how many users lose the access. The count is read from the server when the confirm opens: for a position, its `sys_user_position` rows; for a permission set, its `sys_user_permission_set` rows and the holders of every position whose definition lists the set, one person counted once, as the set's Assigned Users section counts them. A set bound to the `everyone` position is said to reach every signed-in member. A count that cannot be read is said as such, never as "0 users", and the admin may still go ahead. Cancel leaves the item on. Switching an item on asks nothing. +- 8d305ab: Setup → Packages: in a package's sheet, *Adopt loose items* asks in the in-app confirmation, reports how many items it adopted, and each action clears the previous action's message (objectui#13339). + + *Adopt loose items* used the browser's native confirm, which an embedded frame can block or answer on its own. It now opens the sheet's in-app dialog, like Delete and Discard; its Cancel sends nothing. After an adoption the sheet says "N items adopted into this base.", with the count the server answers (`reassignedCount`), so an adoption that found nothing reads "0 items adopted into this base." instead of "Loose items adopted into this base.". + + The sheet's message line now answers the action the administrator started last. Pressing Duplicate, Delete app, Discard changes, Adopt loose items, Edit or View info clears the previous action's message, as the actions that run straight away already did; a Revert refusal no longer stays under the Duplicate form. English and Chinese. +- 4603b8c: Console toasts no longer cover the page header's actions (objectui#13340). With no drawer open the toaster now sits top-centre, just below the console's top bar, instead of in the top-right corner, which is where every page header puts its actions. At 1440×900 a toast used to cover a list's New and Import buttons for its whole 4 s life. While a right-side drawer is open the toaster still goes to the top-right corner and steps clear of the drawer as before (objectui#11685), and it still never uses the bottom-right corner, which belongs to the assistant (objectui#7482). + + New tests check that one server refusal raises one error toast, on the record form renderer and on an action's parameter dialog (Users → Create User, Teams → Add Member). +- 05049f8: A screen flow that ends refused shows its message and Close alone (objectui#13342). + + When a screen-flow run ends with `outcome: 'refused'`, the dialog used to keep the screen the run had paused on under the refusal: its input fields stayed visible and editable, though a refused run is never resumed and nothing would submit them. The dialog now shows the flow's name, the step's heading, the refusal message and Close, with no screen fields. An `object-form` step, whose Close lived in the form's own button bar, gets the runner's Close instead, and the dialog takes its narrow width. + + A screen still waiting for input renders as before, and a run that fails keeps its screen and the typed values under the reason. +- 0f4adc3: Setup › Packaged automation: the Clone dialog now opens with a name and label filled in (objectui#13344). + + It used to open with both fields empty. It now proposes `_copy` as the machine name and " (copy)" as the label, using the flow's machine name when it has no label. Both fields stay editable, and the dialog can be submitted as it opens: the proposed name keeps the lowercase snake_case shape a flow name must have, and it is the same name the server suggests when a name is taken. A name that is already taken is still refused by the server with its 409 message, shown as sent. + + One new language-pack key, `packagedAutomation.cloneCopyLabel`, in all ten packs. +- 5b40cea: A metadata form row now shows the field's label only (objectui#13352). `SchemaForm`'s default row used to draw the field's machine key in a code chip beside the label whenever the label did not spell it, so Setup → Packages → New package read `Display name* name`. The key is now offered on demand instead, as the label's hover tooltip ("Machine name: name"), under the same rule as before: only when the label does not already spell the key, judged alike in every locale. The control's accessible name is the label alone. +- fa31856: Connect an Agent no longer mints an unnamed API key in one click (objectui#13355). "Create key" stays disabled until the administrator types a name, and the name is sent as typed: the key is no longer created as `agent-key` when the name box is empty. Clicking "Create key" now opens an in-app confirm naming the key; Cancel creates nothing, and confirming creates the key and shows it once to copy, as before. This matches Setup → API Keys → Create Key, which also requires a name. + + New string: `connectAgent.apiKey.confirmTitle`, in all ten locale packs. +- 3a73c07: Setup → Installed Apps is titled "Installed Apps" and says when no app is installed from the marketplace yet (objectui#13356). + + The Installed Apps entry opens the Packages page filtered to marketplace installs (`?source=marketplace`). That view now carries the entry's title instead of "Packages", and with no marketplace install it reads "No apps installed from the marketplace yet" instead of "No packages match your filters.", which blamed a filter the administrator had not set. "No packages match your filters." stays for a filter the viewer did set: a search that hides the marketplace installs that exist, or another Source. Setup → Packages, opened without a Source, is unchanged. English and Chinese. +- 8e90779: An action's `confirmText`, `successMessage` and `errorMessage` read the `template` envelope and fill `{{ }}` holes (objectui#13367). + + `@objectstack/spec` is making these three keys `template` slots (objectstack#24814), so a parsed action serves `{ dialect: 'template', source }` where it served a string. Before this change the success toast skipped the envelope and showed the default text, and the error toast showed the generic failure. `ActionRunner` now reads a string or the envelope for all three, and fills `{{ path }}` / `{{ path | formatter }}` holes with `@objectstack/formula`'s `templateEngine`, the engine the flow notifications render with: + + - `confirmText`: `record` (the record the action runs against, the clicked row on a list) and `params` (the action's static params); + - `successMessage`: `result` (the payload `${result.*}` reads) and `record`; + - `errorMessage`: no hole is filled; the text shows as written. + + A sentence with no `{{ }}` hole keeps today's `${…}` reading, so the platform's own `${result.email}`-style success sentences still work until the spec converts them. A sentence is read in one dialect only: a value filled into a `{{ }}` hole is never read again as `${…}`. An envelope with no text never reaches the dialog or a toast as an object; a `confirmText` envelope with no text still asks for confirmation. + + `useActionTextLocalizer` keeps the envelope: it used to read it as a per-locale map and hand the runner the word `template`. A bundle entry replaces the envelope's `source`. On a flow action the console reads the envelope too, so the action's own success copy still outranks the flow's (`flowSuccessCopy`). `@object-ui/core` exports the reader it uses: `ActionCopyTemplate`, `isActionCopyEnvelope`, `actionCopySource`, `hasTemplateHoles` and `fillTemplateHoles`. + + Clause-②: yes + Metadata-protocol: none +- 6183aa9: An action's `onSuccess.navigate` to a path with no app segment opens that page in the current app (objectui#13379). + + `onSuccess: { navigate: '/crm_opportunity/${result.id}' }` used to land on Home: the console handed the path to its router unchanged, and under the `/_console` basename it matched no route. The console action runtime now hosts such a path under the current app, the same way an inbox notification link is hosted, so it opens `/apps/APP/crm_opportunity/...`. With no app current (on Home), it is hosted under the first app the user can open, as notification links are. + + These are unchanged: a path that already names its app (`/apps/APP/...`), an external URL, a `mailto:` address, a `./` path, and a console route outside an app (`/forms/NAME`, which `type: 'form'` actions open, and `/home`, `/studio`, `/setup` and the other top-level routes). A `type: 'url'` action shares this navigator, so its app-relative paths are hosted the same way. +- 7f60e9d: A single-record action launched with 0 or several rows selected is refused before any dialog opens, and the refusal is translated (objectui#13384). + + `ActionRunner` now asks the handler it will dispatch to for an early refusal (`ActionRunnerHandler`'s optional `refuseBeforeInput`) before the confirmation and the param dialog. The handlers `createServerActionHandler` builds answer it with the row-count check the dispatch already runs, so "select a row first" and "select exactly one row" are shown before the user fills anything in, and nothing is sent. With exactly one row the dialog behaves as before. A host that wraps the built handler in its own function keeps the early refusal only by forwarding `refuseBeforeInput`; the console's `createConsoleServerActionHandler` now forwards it, so on a list page (HotCRM's "Add to Campaign" on My Leads) the refusal toast shows and no dialog opens. + + Both refusals now carry a pack key (`actions.selectRowFirst`, `actions.selectExactlyOneRow`, defined in every shipped pack). `resolveServerActionRecordId` returns it as `errorKey` beside the English `error`, and the runner's early refusal goes through its translator by that key. +- d9aff15: A record page inside the Setup app no longer draws the floating managed-by badge (the amber "Identity" chip at the top-right of an organization, team, business unit or user record) (objectui#13385). The header's object label ("Organization") carries the badge's note instead: hovering or focusing it shows "Organization · Managed by the identity provider", and the note is the label's accessible description. The note is the badge's own tooltip title, under the same gate: only a caller who can author metadata sees it, and a `platform` object shows none. Every record page outside Setup, a `sys_*` object opened in another app included, and every list header keep the badge unchanged. + + `RecordContextValue` (`@object-ui/react`) gains an optional, host-injected `objectLabelNote`, which `page:header` forwards to `RecordTitleChip`. `RecordTitleChip` (`@object-ui/components`) gains an optional `objectLabelNote` prop: with it the object label becomes a focusable tooltip trigger described by the note; without it the label draws exactly as before. +- 01b85d8: Changing the ⌘K query no longer blanks the console (objectui#13387). + + The palette lists record hits under one heading per object. When a new query stopped finding an object, that object's heading went away while cmdk's own sort still walked it, and the error unmounted the whole console until a reload. The palette already decides which entries show (its own matching, and the server's ranked record hits), so cmdk's filter and sort are now off: what the palette renders is what shows, in the order it renders it. A record hit's value no longer carries the query. + + The palette also sits behind its own error boundary. An error inside it closes the palette and is reported; the console stays, and the next ⌘K opens a fresh palette. + + Clause-②: no + Metadata-protocol: none +- 78e00db: Studio says when a display name yields no identifier, and Add field no longer names a field `field_` behind the author's back (objectui#13389). + + A display name with no Latin letters (a Chinese one, say) makes no identifier, since identifiers take lowercase letters, digits and underscores only. Before this change the identifier box stayed empty and Create stayed off, and nothing said why. New object and the other Studio create dialogs now say it under the identifier and ask for one. On New package, the line under Package ID gives the same reason instead of "Filled in from the display name until you edit it". + + Add field shows the api name the label derives before Create. When the label derives none, or derives a name another field already has, the popover shows an API name box and Create waits for a name. Before, the field was created as `field_`, and that name becomes the column and the API field name once it is published. A Latin label works as before. +- 4b1ddf3: An action run from a record page's action bar with an `onSuccess.navigate` to a path with no app segment opens that page in the record page's app (objectui#13396). + + The record page mounts its own action provider, and its navigator still handed such a path to the router unchanged, so `onSuccess: { navigate: '/crm_opportunity/${result.id}' }` landed on Home there even after objectui#13379 fixed the same hop elsewhere in the console. The record page's navigator now sorts the path the way the console action runtime does and hosts it under the app in the record page's URL, opening `/apps/APP/crm_opportunity/...`. + + These are unchanged: a path that already names its app (`/apps/APP/...`), an external URL, a `mailto:` address, a `./` path, and a console route outside an app (`/forms/NAME`, `/home` and the other top-level routes). +- 4eeb174: A record-scoped flow action launched from a list toolbar with 0 or several rows selected is refused before its param dialog opens, and its refusal is translated (objectui#13397). + + The console's `flowHandler` now carries `refuseBeforeInput`, the early refusal objectui#13384 gave the `script` handler, answered by the same resolver its dispatch runs. The runner asks it before the confirmation and the param dialog, so "select a row first" and "select exactly one row" show in the session's language before the user fills anything in, and nothing is sent. With exactly one row the flow behaves as before. A direct call that is refused at dispatch time is shown through the refusal's pack key too. + + The console server-action wrapper's `newTabUrl` refusal ("no record id available") now has a pack key, `console.serverAction.noRecordId`, defined in every shipped pack, and the wrapper's fast path shows the resolver's own refusal through its pack key. +- 130c77d: Setup → Permission Sets → Assigned Users: Remove asks first, and the add picker offers organization members only (objectui#13408), the same shape as the positions page (objectui#13337). + + - Removing a direct grant opens a confirm that names the person; nothing is sent until it is confirmed, and Cancel writes nothing. + - Add user reads the active organization's `sys_member` rows when it opens and offers only the users they name, so a user removed from the organization is no longer offered (the server already refuses such a grant). A refused membership read is said in the server's words and the picker stays shut. With no active organization, or no `sys_member` object registered, the picker lists every user it may read, as before. + - The membership read is one helper shared by both pages (`organization-members.ts`). +- 47138b7: The Console's first page load no longer downloads the chat UI (objectui#13410). The `plugin-chatbot` chunk (169.6 KB gzipped, the third-largest eager chunk) and most of `vendor-markdown` used to load on every page, including for users who never open a chat, because the console shell imported a handful of small helpers from the `@object-ui/plugin-chatbot` package root, and the root re-exports the renderer that registers the chat components when it is evaluated. Measured on the Console's production build, the eager closure drops by 254,055 gzipped bytes (3,326,111 to 3,072,056). The chat now loads when it is first shown: opening the dock, visiting `/ai…` or `/s/:token`, or rendering a `chatbot`, `chatbot-enhanced` or `chatbot-floating` node. + + `@object-ui/plugin-chatbot` adds a side-effect-free `@object-ui/plugin-chatbot/core` subpath: `useAgents`, `resolveDefaultAgentName`, `PLATFORM_DEFAULT_AGENT`, `agentHasCapability`, the agent alias helpers (`AGENT_ALIAS_GROUPS`, `agentAliasGroup`, `agentRouteName`, `resolveAgentParam`, `isBuiltinAgentName`, `isBuildAgent`, `isAskAgent`), `AI_USAGE_REFRESH_EVENT`, `emitAiUsageRefresh`, `publishHealthFromResponse` and `detectPendingApproval`, with their types. Importing it registers nothing and reaches no chat UI module. The package root still exports every one of these names, unchanged. + + `@object-ui/app-shell` takes those names from `/core`, and the ChatDock loads its default chat body on first render instead of importing it. `resolveApiBase` is still exported from the same places. +- 576fd25: A `type: 'form'` action fired inside an app opens its form inside that app, headed by a label, with a Cancel (objectui#13433). + + The form opened on the app-less `/forms/:name`, so the app's sidebar, switcher and branding disappeared. The page was headed by the raw view name (`showcase_task.form`) and had only Submit, so the browser's Back button was the only way out without saving. + + - The console now also serves the form at `/apps/:appName/forms/:name`, inside the app's own shell. The record page, object list and page action navigators open a form hop there when their own route is an app route. The console-wide runtime has no route of its own, so its form hops keep the app-less route. `/forms/:name` is unchanged and still serves every other link. + - A form view with no label and no form `title` is headed by its object's label in the session's language. An authored view label or `title` still wins. + - The internal form has a Cancel. It goes back to the page the form was opened from. With no such page (a cold link) it goes to the record being edited, else to the app's home, or to Home on the app-less route. The public `/f/:slug` form has no Cancel. +- 2c4e5f5: A member who may read none of the objects an app names now lands on one page that says they need access and whom to ask, instead of the app's dashboard drawn as a grid of "You don't have access" tiles (objectstack-ai/objectstack#25338). + + The app root's landing asks the object-read prune's own verdict (`useNavMemberGates().can`) over every `type: 'object'` entry the app names, at every depth and in every area. When the app names at least one object and the member may read none of them, it renders `AppNoAccessEmptyState` with the new `reason="no-readable-object"`: "Your account cannot read any of the records in this app yet. Ask an administrator to assign you a permission set.", plus the Setup link for a member who may grant access. One readable object, or an app that names no object at all, lands exactly as before. + + Clause-②: yes + Metadata-protocol: none +- f2f4b7d: Publish from Home no longer reports a `defineCapability` declaration as a capability that resolves nowhere (objectui#7611). + + The advisory capability-reference lint that runs over pending drafts before **Publish** handed `@objectstack/lint`'s `validateCapabilityReferences` the drafts and the permission sets only, so a capability a package declares with `defineCapability` and no permission set grants yet was flagged on every object, field, action or app draft that required it. The lint now also reads the capabilities the registry serves (`GET /api/v1/meta/capability`) into the rule's `capabilities` source. A misspelled capability is still reported. If that read fails, the lint runs on the other sources as before and never blocks publishing. + + Internal, no behaviour change: `approverIdentity` drops a display-column entry for `sys_position`, which no approver binding has named since `position` became registry-bound. + + Clause-②: no + Metadata-protocol: none +- Updated dependencies [8556295] +- Updated dependencies [cd14d8e] +- Updated dependencies [8701f1e] +- Updated dependencies [5235d6d] +- Updated dependencies [8e649da] +- Updated dependencies [7c405b7] +- Updated dependencies [0093b2c] +- Updated dependencies [f669732] +- Updated dependencies [813c3d9] +- Updated dependencies [3aafc0d] +- Updated dependencies [601c406] +- Updated dependencies [56cf4d8] +- Updated dependencies [b911ebb] +- Updated dependencies [0d12e95] +- Updated dependencies [ff77cfc] +- Updated dependencies [49a536d] +- Updated dependencies [241cb78] +- Updated dependencies [404ccae] +- Updated dependencies [8cf3a86] +- Updated dependencies [ec627ab] +- Updated dependencies [fb25620] +- Updated dependencies [b93c9f6] +- Updated dependencies [d019aaa] +- Updated dependencies [0f4adc3] +- Updated dependencies [fa31856] +- Updated dependencies [8e90779] +- Updated dependencies [f1a4b08] +- Updated dependencies [7f60e9d] +- Updated dependencies [d9aff15] +- Updated dependencies [eadceab] +- Updated dependencies [4eeb174] +- Updated dependencies [afcf654] +- Updated dependencies [b317942] +- Updated dependencies [2c3dc72] +- Updated dependencies [47138b7] +- Updated dependencies [cee3bc5] +- Updated dependencies [2958f17] +- Updated dependencies [a78608f] +- Updated dependencies [0984c77] +- Updated dependencies [56b65c0] +- Updated dependencies [1d178e0] +- Updated dependencies [1d178e0] +- Updated dependencies [a14737b] +- Updated dependencies [2c4e5f5] +- Updated dependencies [6fb31dc] +- Updated dependencies [fbb4b23] +- Updated dependencies [f3044f7] +- Updated dependencies [c8f8b10] +- Updated dependencies [ad74e98] + - @object-ui/types@18.1.0 + - @object-ui/plugin-grid@18.1.0 + - @object-ui/components@18.1.0 + - @object-ui/fields@18.1.0 + - @object-ui/i18n@18.1.0 + - @object-ui/plugin-detail@18.1.0 + - @object-ui/react@18.1.0 + - @object-ui/permissions@18.1.0 + - @object-ui/auth@18.1.0 + - @object-ui/plugin-list@18.1.0 + - @object-ui/core@18.1.0 + - @object-ui/layout@18.1.0 + - @object-ui/plugin-charts@18.1.0 + - @object-ui/plugin-chatbot@18.1.0 + - @object-ui/plugin-dashboard@18.1.0 + - @object-ui/data-objectstack@18.1.0 + - @object-ui/collaboration@18.1.0 + - @object-ui/plugin-calendar@18.1.0 + - @object-ui/plugin-designer@18.1.0 + - @object-ui/plugin-editor@18.1.0 + - @object-ui/plugin-form@18.1.0 + - @object-ui/plugin-kanban@18.1.0 + - @object-ui/plugin-report@18.1.0 + - @object-ui/plugin-view@18.1.0 + - @object-ui/providers@18.1.0 + ## 18.0.0 ### Major Changes diff --git a/packages/app-shell/package.json b/packages/app-shell/package.json index e4f9a755b9..3670820175 100644 --- a/packages/app-shell/package.json +++ b/packages/app-shell/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/app-shell", - "version": "18.0.0", + "version": "18.1.0", "type": "module", "sideEffects": [ "./dist/index.js", diff --git a/packages/auth/CHANGELOG.md b/packages/auth/CHANGELOG.md index 10d9b00e61..8998441d00 100644 --- a/packages/auth/CHANGELOG.md +++ b/packages/auth/CHANGELOG.md @@ -1,5 +1,25 @@ # @object-ui/auth +## 18.1.0 + +### Minor Changes + +- ff77cfc: On a cloud-managed environment (`features.cloudManaged: true` from `/auth/config`), the console says what the server already enforces. Setup → Users shows one line saying where people are invited (the organization, in the cloud) and marks a user who holds no permission set beyond the baseline as "Not authorized", read from their `sys_user_permission_set` and `sys_user_position` rows. The identity import entry is not offered, the organization members page shows a note instead of Invite member, and the recovery-password reminder does not show. With the flag absent or `false`, nothing changes. + + `AuthPublicConfig['features']` gains `cloudManaged`. `ObjectGrid` gains the `rowAdornment` host prop, a node drawn beside one row's title (the declared name field's cell, else the first shown column, and the card title in the card view), and `ListView` forwards its own `rowAdornment` to the grid. + + Clause-②: yes + Metadata-protocol: none +- 2958f17: The console knows the `external` organization role that objectstack#25515 added to `@objectstack/spec`'s membership vocabulary (objectui#13427). Without it `ORG_ROLE_LABELS` no longer type-checked against an `@objectstack/spec` that lists the role. + + `@object-ui/auth` exports `ORG_ROLE_EXTERNAL` and labels it (`organization.roles.external`, "External"). Every pack in `@object-ui/i18n` carries the key; zh reads 外部成员, as the server's own `sys_member.role` option does. Wherever the installed spec lists the role, the invite dialog offers it to every issuer who can invite, a delegated admin included, because objectstack's invitation cap admits it from any issuer: it confers less than a member. Owners and admins can also set it from the members page. On the grade ladder it sits with `member`, as it does in objectstack's cap, so it never unlocks an administrative affordance. + +### Patch Changes + +- 0984c77: The `@objectstack/*` pin moves from `915e940499` to objectstack `e649c2d91e`, the 18.1.0 release commit (objectstack#25606), past objectstack#25483 and objectstack#25564, which ship together in that release (objectui#13440). + + `@object-ui/auth` now takes `ORG_ROLE_EXTERNAL` from `@objectstack/spec`'s `MEMBERSHIP_ROLE_EXTERNAL` instead of spelling the literal. The exported name and its value (`'external'`) are unchanged, and `ORG_ROLE_LABELS` is typed by `OrgRole` alone again. The published module now imports that constant, so it needs an `@objectstack/spec` that exports it (18.1.0 or later); the publish step floors the `@objectstack/*` ranges at the release that contains the pin. With that spec the invite dialog lists `external` among the roles it offers, as objectui#13427 described for a spec that lists the role. + ## 18.0.0 ### Major Changes diff --git a/packages/auth/package.json b/packages/auth/package.json index b9bb881332..f35250f4cc 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/auth", - "version": "18.0.0", + "version": "18.1.0", "type": "module", "license": "MIT", "description": "Authentication system for Object UI with AuthProvider, useAuth hook, AuthGuard, and form components.", diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index d288b741f8..651777ee5d 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,31 @@ # @object-ui/cli +## 18.1.0 + +### Patch Changes + +- 7e9708e: The console home blocks `hero`, `stat`, `usage-bar`, `checklist` and `tile-grid` register under the `app-shell` namespace, so the console no longer logs a "without a namespace is deprecated" warning for each on every boot (objectui#13301). + + Pages keep writing the bare key: `type: 'hero'` still draws the block through the registry's bare fallback. `objectui check` now knows the five `app-shell:` keys as registered, and `objectui validate` refuses them at `type`, so the bare spelling stays the one authorable key. +- Updated dependencies [8556295] +- Updated dependencies [cd14d8e] +- Updated dependencies [8701f1e] +- Updated dependencies [7c405b7] +- Updated dependencies [3aafc0d] +- Updated dependencies [601c406] +- Updated dependencies [b911ebb] +- Updated dependencies [8e90779] +- Updated dependencies [f1a4b08] +- Updated dependencies [d9aff15] +- Updated dependencies [a78608f] +- Updated dependencies [1d178e0] +- Updated dependencies [6fb31dc] +- Updated dependencies [fbb4b23] +- Updated dependencies [c8f8b10] + - @object-ui/types@18.1.0 + - @object-ui/components@18.1.0 + - @object-ui/react@18.1.0 + ## 18.0.0 ### Major Changes diff --git a/packages/cli/package.json b/packages/cli/package.json index 7f802f69ef..3f46a6d494 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/cli", - "version": "18.0.0", + "version": "18.1.0", "description": "Standalone CLI for Object UI — scaffold, develop, build and validate JSON/YAML schema-driven applications.", "type": "module", "homepage": "https://www.objectui.org/docs/utilities/cli", diff --git a/packages/collaboration/CHANGELOG.md b/packages/collaboration/CHANGELOG.md index 8dc40fd86e..3f518bce3a 100644 --- a/packages/collaboration/CHANGELOG.md +++ b/packages/collaboration/CHANGELOG.md @@ -1,5 +1,32 @@ # @object-ui/collaboration +## 18.1.0 + +### Patch Changes + +- Updated dependencies [8556295] +- Updated dependencies [cd14d8e] +- Updated dependencies [5235d6d] +- Updated dependencies [0093b2c] +- Updated dependencies [ff77cfc] +- Updated dependencies [241cb78] +- Updated dependencies [404ccae] +- Updated dependencies [ec627ab] +- Updated dependencies [0f4adc3] +- Updated dependencies [fa31856] +- Updated dependencies [f1a4b08] +- Updated dependencies [7f60e9d] +- Updated dependencies [4eeb174] +- Updated dependencies [afcf654] +- Updated dependencies [2c3dc72] +- Updated dependencies [2958f17] +- Updated dependencies [1d178e0] +- Updated dependencies [2c4e5f5] +- Updated dependencies [6fb31dc] +- Updated dependencies [ad74e98] + - @object-ui/types@18.1.0 + - @object-ui/i18n@18.1.0 + ## 18.0.0 ### Major Changes diff --git a/packages/collaboration/package.json b/packages/collaboration/package.json index 15eb0c6eeb..b76929f22a 100644 --- a/packages/collaboration/package.json +++ b/packages/collaboration/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/collaboration", - "version": "18.0.0", + "version": "18.1.0", "type": "module", "license": "MIT", "description": "Real-time collaboration for Object UI with presence tracking, live cursors, conflict resolution, and comment threads.", diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 181a4e412d..8d8e21cac3 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -1,5 +1,65 @@ # @object-ui/components +## 18.1.0 + +### Minor Changes + +- 8701f1e: The record page heading draws a `nameField` that declares a widget with a read face of its own through that face, the one the field's list column draws (objectui#13216). A record share (`nameField: 'recipient_id'`, which declares `widget: 'recipient-picker'` and `dependsOn: ['recipient_type']`) now heads its page with the recipient's name instead of the user id it stores. Every other heading is unchanged: a plain text or select `nameField`, a `titleFormat`, an explicit `title`, an object with no `nameField`, a widget with no read face of its own, a widget whose key has no face registered under it (it draws the stored text), and a host that does not load `@object-ui/fields`. + + `@object-ui/components` adds a field-face seam on its entry: `setFieldReadFaceResolver(resolver)` installs the resolver, `resolveFieldReadFace(field)` asks it, and the types `FieldReadFace`, `FieldReadFaceProps` and `FieldReadFaceResolver` describe them. `@object-ui/fields` fills it when it loads, with the same `getCellRenderer(resolveCellRendererType(field))` lookup the grid's cells make, so a host has nothing to wire. `RecordTitleChip` gains an optional `titleNode` prop, drawn inside its heading in place of the `title` text; `title` stays a required string. +- d9aff15: A record page inside the Setup app no longer draws the floating managed-by badge (the amber "Identity" chip at the top-right of an organization, team, business unit or user record) (objectui#13385). The header's object label ("Organization") carries the badge's note instead: hovering or focusing it shows "Organization · Managed by the identity provider", and the note is the label's accessible description. The note is the badge's own tooltip title, under the same gate: only a caller who can author metadata sees it, and a `platform` object shows none. Every record page outside Setup, a `sys_*` object opened in another app included, and every list header keep the badge unchanged. + + `RecordContextValue` (`@object-ui/react`) gains an optional, host-injected `objectLabelNote`, which `page:header` forwards to `RecordTitleChip`. `RecordTitleChip` (`@object-ui/components`) gains an optional `objectLabelNote` prop: with it the object label becomes a focusable tooltip trigger described by the note; without it the label draws exactly as before. + +### Patch Changes + +- 7c405b7: A `page:tabs` item whose `visibleWhen` faults on evaluation is no longer drawn (objectui#13286). + + A predicate that cannot be evaluated (a source over the CEL engine's AST bound, a type error, an unbound root, a missing function) used to fall back to visible, so the tab drew for a viewer the predicate was written to exclude. It now fails closed: the tab, header and panel, is withheld, and the fault is logged once per authored source through the same console report as before, now saying the tab was withheld. If the withheld tab was the active one, the strip falls back to the first visible tab. A tab with no `visibleWhen`, or a blank one, is still shown, and a predicate that evaluates decides exactly as before. Form field rules keep their documented fail-open. +- 3aafc0d: A page node whose declared `visibleWhen` / `visible` / `visibleOn` predicate cannot be evaluated (over the CEL bounds, a type error, an unbound root, a missing function) is no longer rendered: page visibility gates now fail closed, as a `page:tabs` item already did. The fault is still reported once, and the console line says the node was withheld. A blank gate still means "no gate", and a predicate that evaluates decides as before. A `page:tabs` badge no longer counts a related list withheld this way. Form field rules keep their fail-open (objectui#13299). +- f1a4b08: Grids: hovering a `lookup` or `master_detail` cell no longer shows the referenced record's raw id (objectui#13377). + + The table's cell wrapper set its `title` tooltip to the cell's raw value, and for a reference column that value is the related record's id. So hovering beside the drawn name, or beside "Restricted record" for a record the viewer cannot read, still showed the id. + + - **`@object-ui/types`:** `TableColumn` gains an optional `foreignKey` boolean: the column's raw value is the id of a referenced record. The zod mirror (`TableColumnSchema`) keeps it, and the static `table` column refuses it by name, like `masked` and `chips`. + - **`@object-ui/components`:** a `data-table` column with `foreignKey: true` draws no `title` tooltip. Nothing else changes for it: copy, CSV export, inline edit, search and sort behave as before. + - **`@object-ui/plugin-grid`:** `ObjectGrid` sets `foreignKey` on every `lookup`, `master_detail`, `tree` and `user` column, read from the column's own type or the object's field type. Every other column keeps its tooltip. +- a78608f: A create form no longer locks fields through `readonlyWhen`. The server does not apply `readonlyWhen` on insert, but the form evaluated it against the seeded defaults, so a predicate over a defaulted column (`record.status == 'pending_verify'` with `status` defaulting to `'pending_verify'`) or a `!=` over an unset one (`record.approval_status != 'returned'`) rendered fields read-only on New that the API accepts. `readonlyWhen` now applies only to an edit form (one given `previousValues`), and no longer warns a fault on a create form; static `readonly: true` still locks on create, and `visibleWhen` / `requiredWhen` are unchanged. +- fbb4b23: data-table / VirtualGrid: selecting a cell's text no longer opens the record or starts an inline edit, and Ctrl/Cmd+C copies the selected text instead of the whole cell value. A plain click still opens or edits as before (objectui#13188). +- c8f8b10: data-table: with row numbers on, the header's select-all checkbox, each row's checkbox and the row number now share one centre line in the leading column (objectui#13293). +- Updated dependencies [8556295] +- Updated dependencies [cd14d8e] +- Updated dependencies [5235d6d] +- Updated dependencies [0093b2c] +- Updated dependencies [3aafc0d] +- Updated dependencies [601c406] +- Updated dependencies [b911ebb] +- Updated dependencies [ff77cfc] +- Updated dependencies [49a536d] +- Updated dependencies [241cb78] +- Updated dependencies [404ccae] +- Updated dependencies [ec627ab] +- Updated dependencies [0f4adc3] +- Updated dependencies [fa31856] +- Updated dependencies [8e90779] +- Updated dependencies [f1a4b08] +- Updated dependencies [7f60e9d] +- Updated dependencies [d9aff15] +- Updated dependencies [4eeb174] +- Updated dependencies [afcf654] +- Updated dependencies [2c3dc72] +- Updated dependencies [2958f17] +- Updated dependencies [1d178e0] +- Updated dependencies [2c4e5f5] +- Updated dependencies [6fb31dc] +- Updated dependencies [ad74e98] + - @object-ui/types@18.1.0 + - @object-ui/i18n@18.1.0 + - @object-ui/react@18.1.0 + - @object-ui/core@18.1.0 + - @object-ui/sdui-parser@18.1.0 + - @object-ui/react-runtime@18.1.0 + ## 18.0.0 ### Major Changes diff --git a/packages/components/package.json b/packages/components/package.json index 576e0cd505..798c589de9 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/components", - "version": "18.0.0", + "version": "18.1.0", "type": "module", "license": "MIT", "description": "Standard UI component library for Object UI, built with Shadcn UI + Tailwind CSS", diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md index 228e27b545..b7e7b66d9f 100644 --- a/packages/core/CHANGELOG.md +++ b/packages/core/CHANGELOG.md @@ -1,5 +1,43 @@ # @object-ui/core +## 18.1.0 + +### Minor Changes + +- 8e90779: An action's `confirmText`, `successMessage` and `errorMessage` read the `template` envelope and fill `{{ }}` holes (objectui#13367). + + `@objectstack/spec` is making these three keys `template` slots (objectstack#24814), so a parsed action serves `{ dialect: 'template', source }` where it served a string. Before this change the success toast skipped the envelope and showed the default text, and the error toast showed the generic failure. `ActionRunner` now reads a string or the envelope for all three, and fills `{{ path }}` / `{{ path | formatter }}` holes with `@objectstack/formula`'s `templateEngine`, the engine the flow notifications render with: + + - `confirmText`: `record` (the record the action runs against, the clicked row on a list) and `params` (the action's static params); + - `successMessage`: `result` (the payload `${result.*}` reads) and `record`; + - `errorMessage`: no hole is filled; the text shows as written. + + A sentence with no `{{ }}` hole keeps today's `${…}` reading, so the platform's own `${result.email}`-style success sentences still work until the spec converts them. A sentence is read in one dialect only: a value filled into a `{{ }}` hole is never read again as `${…}`. An envelope with no text never reaches the dialog or a toast as an object; a `confirmText` envelope with no text still asks for confirmation. + + `useActionTextLocalizer` keeps the envelope: it used to read it as a per-locale map and hand the runner the word `template`. A bundle entry replaces the envelope's `source`. On a flow action the console reads the envelope too, so the action's own success copy still outranks the flow's (`flowSuccessCopy`). `@object-ui/core` exports the reader it uses: `ActionCopyTemplate`, `isActionCopyEnvelope`, `actionCopySource`, `hasTemplateHoles` and `fillTemplateHoles`. + + Clause-②: yes + Metadata-protocol: none + +### Patch Changes + +- 49a536d: The record header's highlights write the year on every date (objectui#13331). + + A current-year date dropped its year in the strip, so a contract record read "Start Date Sep 15, 2025 | End Date Sep 15" and a contract that ended this September looked like it ended next month. The strip now asks for the year, and both dates read alike. Dates inside the ±7-day window keep their relative phrase ("In 2 days"). + + `formatDate` takes a new opt-in option, `alwaysShowYear`, which keeps the year on its default face; the `date` and `datetime` cell renderers take an `alwaysShowYear` prop that hands it on. Neither is on by default: grid cells and cards still drop the current year. +- 7f60e9d: A single-record action launched with 0 or several rows selected is refused before any dialog opens, and the refusal is translated (objectui#13384). + + `ActionRunner` now asks the handler it will dispatch to for an early refusal (`ActionRunnerHandler`'s optional `refuseBeforeInput`) before the confirmation and the param dialog. The handlers `createServerActionHandler` builds answer it with the row-count check the dispatch already runs, so "select a row first" and "select exactly one row" are shown before the user fills anything in, and nothing is sent. With exactly one row the dialog behaves as before. A host that wraps the built handler in its own function keeps the early refusal only by forwarding `refuseBeforeInput`; the console's `createConsoleServerActionHandler` now forwards it, so on a list page (HotCRM's "Add to Campaign" on My Leads) the refusal toast shows and no dialog opens. + + Both refusals now carry a pack key (`actions.selectRowFirst`, `actions.selectExactlyOneRow`, defined in every shipped pack). `resolveServerActionRecordId` returns it as `errorKey` beside the English `error`, and the runner's early refusal goes through its translator by that key. +- Updated dependencies [8556295] +- Updated dependencies [cd14d8e] +- Updated dependencies [f1a4b08] +- Updated dependencies [1d178e0] +- Updated dependencies [6fb31dc] + - @object-ui/types@18.1.0 + ## 18.0.0 ### Major Changes diff --git a/packages/core/package.json b/packages/core/package.json index d656615104..48aee52b0b 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/core", - "version": "18.0.0", + "version": "18.1.0", "type": "module", "sideEffects": false, "license": "MIT", diff --git a/packages/create-plugin/CHANGELOG.md b/packages/create-plugin/CHANGELOG.md index 42e61cd457..4d7bd98db1 100644 --- a/packages/create-plugin/CHANGELOG.md +++ b/packages/create-plugin/CHANGELOG.md @@ -1,5 +1,7 @@ # @object-ui/create-plugin +## 18.1.0 + ## 18.0.0 ### Major Changes diff --git a/packages/create-plugin/package.json b/packages/create-plugin/package.json index 5f19aea7ae..dabb4d118a 100644 --- a/packages/create-plugin/package.json +++ b/packages/create-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/create-plugin", - "version": "18.0.0", + "version": "18.1.0", "description": "CLI tool to scaffold ObjectUI plugins", "type": "module", "license": "MIT", diff --git a/packages/data-objectstack/CHANGELOG.md b/packages/data-objectstack/CHANGELOG.md index c887afbe91..c4eae00d19 100644 --- a/packages/data-objectstack/CHANGELOG.md +++ b/packages/data-objectstack/CHANGELOG.md @@ -1,5 +1,30 @@ # @object-ui/data-objectstack +## 18.1.0 + +### Minor Changes + +- a14737b: Setup → Positions now says who holds each position and which permission sets it grants, and a click anywhere on a row opens the item (objectstack#25333). + + - **Two columns, both the server's.** The position list reads `GET /meta/position?include=grants`. **Holders** shows the served `_holderCount`, and **Permission sets** shows the served `_grantedPermissionSets` in the order the server sends them. The server computes both where the authorization resolver enforces them, and the console computes neither. + - **The set a position grants by its name is shown, marked "(by name)".** That set shares the position's name, and the position-name fold grants it even though the definition does not list it (objectstack#24757). A tooltip says why it is there. Sets the definition lists carry no mark. + - **A count nobody measured is "—", never 0.** That covers a count the server did not serve (`null`: no active organization, or a caller who may not read position assignments) and a server that predates `include=grants`. + - **The whole row opens the item** on every Setup metadata list, as a record list's row does. The first cell keeps its link for the keyboard, screen readers and opening in a new tab. A click on a control in the row (the Active switch, Clone, a link) is still that control's. A modified click, a click that ends a text selection, and a click inside a dialog a row control opened do not open the row. + - **`@object-ui/data-objectstack`**: `MetadataClient.list` / `listResponse` accept `include: 'grants'`, sent as the `include` query parameter. + +### Patch Changes + +- Updated dependencies [8556295] +- Updated dependencies [cd14d8e] +- Updated dependencies [49a536d] +- Updated dependencies [8e90779] +- Updated dependencies [f1a4b08] +- Updated dependencies [7f60e9d] +- Updated dependencies [1d178e0] +- Updated dependencies [6fb31dc] + - @object-ui/types@18.1.0 + - @object-ui/core@18.1.0 + ## 18.0.0 ### Major Changes diff --git a/packages/data-objectstack/package.json b/packages/data-objectstack/package.json index b4efc51b82..3f5bacaea4 100644 --- a/packages/data-objectstack/package.json +++ b/packages/data-objectstack/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/data-objectstack", - "version": "18.0.0", + "version": "18.1.0", "description": "ObjectStack Data Adapter for Object UI", "license": "MIT", "type": "module", diff --git a/packages/fields/CHANGELOG.md b/packages/fields/CHANGELOG.md index 8bda8c200f..92c4ab68af 100644 --- a/packages/fields/CHANGELOG.md +++ b/packages/fields/CHANGELOG.md @@ -1,5 +1,70 @@ # @object-ui/fields +## 18.1.0 + +### Patch Changes + +- 8701f1e: The record page heading draws a `nameField` that declares a widget with a read face of its own through that face, the one the field's list column draws (objectui#13216). A record share (`nameField: 'recipient_id'`, which declares `widget: 'recipient-picker'` and `dependsOn: ['recipient_type']`) now heads its page with the recipient's name instead of the user id it stores. Every other heading is unchanged: a plain text or select `nameField`, a `titleFormat`, an explicit `title`, an object with no `nameField`, a widget with no read face of its own, a widget whose key has no face registered under it (it draws the stored text), and a host that does not load `@object-ui/fields`. + + `@object-ui/components` adds a field-face seam on its entry: `setFieldReadFaceResolver(resolver)` installs the resolver, `resolveFieldReadFace(field)` asks it, and the types `FieldReadFace`, `FieldReadFaceProps` and `FieldReadFaceResolver` describe them. `@object-ui/fields` fills it when it loads, with the same `getCellRenderer(resolveCellRendererType(field))` lookup the grid's cells make, so a host has nothing to wire. `RecordTitleChip` gains an optional `titleNode` prop, drawn inside its heading in place of the `title` text; `title` stays a required string. +- 8e649da: A row action's `defaultFromRow` param backed by a relation is seeded with the related record's id again, not the whole record (objectui#13271). + + Related lists read their rows with the relations they show expanded, so a `lookup`, `master_detail`, `user` or `tree` value arrives as the related record. The param seed copied that record verbatim, and the action sent it where the endpoint expects the id. Setup → Teams → Remove from Team answered 400 "User is not a member of the organization" for every member. + + The seed now uses the row's stored form, by the same field-type rule the predicate and Undo paths use: a field the row's object declares relational becomes its id, and a `multiple` one becomes the array of ids. Every other field, including a `json` value that has an `id` key, is seeded exactly as before. The dialog still shows the related record's name. Nothing is added to the package entry. +- 813c3d9: A password or secret input now tells the browser what it is for (objectui#13295). + + The password widget's editable input carries an `autocomplete` token. A field or action parameter whose name reads as the user's existing password (a word `current`, `old` or `existing` in the name, as in `current_password` or `oldPassword`) gets `current-password`; every other password or secret gets `new-password`. Before, the input had no token, so a browser treated each one as a sign-in field: it offered the saved site password for an API key or a new password, and its password manager could not tell the old password from the new one in a change-password dialog. The masked input and its show/hide toggle are unchanged. +- 49a536d: The record header's highlights write the year on every date (objectui#13331). + + A current-year date dropped its year in the strip, so a contract record read "Start Date Sep 15, 2025 | End Date Sep 15" and a contract that ended this September looked like it ended next month. The strip now asks for the year, and both dates read alike. Dates inside the ±7-day window keep their relative phrase ("In 2 days"). + + `formatDate` takes a new opt-in option, `alwaysShowYear`, which keeps the year on its default face; the `date` and `datetime` cell renderers take an `alwaysShowYear` prop that hands it on. Neither is on by default: grid cells and cards still drop the current year. +- ec627ab: A lookup / master-detail / tree value whose referenced record the viewer's own read answers "not found" for (a 404, which is what the server answers for a record this viewer may not read) now reads "Restricted record", translated, with a lock icon, no record id and no link, in grids and on the record page (objectui#13335). It used to print the raw id beside a question mark. No additional read is made: the label comes from the same lookup read the cell already performed, so it reveals nothing the id did not. A reference that is still loading, whose read failed, or that is empty renders as before, and a readable reference still shows its name as a link. New key: `detail.restrictedLookupReference` in all ten locale packs. +- cee3bc5: A boolean renders the same whatever its name (objectui#13412). `BooleanCellRenderer` drew a red destructive "LABEL — Off" badge for `false` when the field was named `active`, `is_active`, `enabled`, `is_enabled`, `verified` or `is_verified`, so a plain `Field.boolean` named `verified` read as an error on every new record, in lists and on the record page. Those names now draw the same unchecked checkbox as any other boolean, named by the field's label, and `true` still draws the checked box. The completion indicator for `completed`, `is_completed`, `done` and `is_done` is unchanged. +- f3044f7: `html` and `richtext` values are now sanitized with `rehype-sanitize`, the sanitizer the `markdown` pipeline already used, instead of a hand-written pattern filter. + + A stored value is parsed with the browser's HTML parser, filtered against one allow-list of elements, attributes and URL protocols, and rendered as React elements. Both display pipelines share that allow-list. Headings, paragraphs, emphasis, lists, quotes, code, tables, links and images keep their formatting. Event-handler attributes, `style`, script-bearing URLs, embedded frames and objects, and SVG and MathML content are dropped. A link whose URL is refused now renders without an `href`, where it used to point at `#`. Stored `id` and `name` values are prefixed with `user-content-`. +- Updated dependencies [8556295] +- Updated dependencies [cd14d8e] +- Updated dependencies [8701f1e] +- Updated dependencies [5235d6d] +- Updated dependencies [7c405b7] +- Updated dependencies [0093b2c] +- Updated dependencies [3aafc0d] +- Updated dependencies [601c406] +- Updated dependencies [b911ebb] +- Updated dependencies [0d12e95] +- Updated dependencies [ff77cfc] +- Updated dependencies [49a536d] +- Updated dependencies [241cb78] +- Updated dependencies [404ccae] +- Updated dependencies [ec627ab] +- Updated dependencies [0f4adc3] +- Updated dependencies [fa31856] +- Updated dependencies [8e90779] +- Updated dependencies [f1a4b08] +- Updated dependencies [7f60e9d] +- Updated dependencies [d9aff15] +- Updated dependencies [4eeb174] +- Updated dependencies [afcf654] +- Updated dependencies [2c3dc72] +- Updated dependencies [2958f17] +- Updated dependencies [a78608f] +- Updated dependencies [1d178e0] +- Updated dependencies [2c4e5f5] +- Updated dependencies [6fb31dc] +- Updated dependencies [fbb4b23] +- Updated dependencies [c8f8b10] +- Updated dependencies [ad74e98] + - @object-ui/types@18.1.0 + - @object-ui/components@18.1.0 + - @object-ui/i18n@18.1.0 + - @object-ui/react@18.1.0 + - @object-ui/permissions@18.1.0 + - @object-ui/core@18.1.0 + - @object-ui/providers@18.1.0 + ## 18.0.0 ### Major Changes diff --git a/packages/fields/package.json b/packages/fields/package.json index ebb960550f..33da48b9d1 100644 --- a/packages/fields/package.json +++ b/packages/fields/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/fields", - "version": "18.0.0", + "version": "18.1.0", "description": "Field renderers and registry for Object UI", "license": "MIT", "type": "module", diff --git a/packages/i18n/CHANGELOG.md b/packages/i18n/CHANGELOG.md index eb042d1601..5ed3cda286 100644 --- a/packages/i18n/CHANGELOG.md +++ b/packages/i18n/CHANGELOG.md @@ -1,5 +1,65 @@ # @object-ui/i18n +## 18.1.0 + +### Patch Changes + +- 5235d6d: Setup › Packaged automation: the clone result now offers the next steps (objectui#13270). + + A clone of a packaged flow is created `draft`, which does not switch it off, so a cloned record-change or schedule flow runs beside the flow it was copied from. The result used to show the server's notice and nothing to click. It now keeps that notice and adds: + + - **Switch "SOURCE" off** — calls the same packaged-flow toggle as the row's own switch, for the flow that was cloned. On success the row reads off and the result says the source is switched off. A refusal shows the server's message beside the button, and the button stays. When the source is already off, no switch-off is offered. + - **Open the clone in Studio** — links the package-less Studio scope (`/studio/~org/automations`) opened on the clone. + + The clone itself is unchanged. Three new language-pack keys, `packagedAutomation.cloneSwitchSourceOff`, `.cloneSourceOff` and `.cloneOpen`, in all ten packs. +- 0093b2c: Settings pages: a `url`, `email`, `phone` or `color` value that misses the format its type declares now blocks Save (objectui#13287). No request goes out, the row is marked inline with a message naming what the format expects, and focus moves to the first such row, on the same path as the `required` check. The grammars are the settings service's own (objectstack#24882), judged on the trimmed value; an empty value is left to `required`, and a hidden or env-locked row is not judged. Adds `console.settingsView.invalidPhone` and `console.settingsView.invalidColor` to every locale pack; `email` and `url` reuse `validation.email` and `validation.url`. +- ff77cfc: On a cloud-managed environment (`features.cloudManaged: true` from `/auth/config`), the console says what the server already enforces. Setup → Users shows one line saying where people are invited (the organization, in the cloud) and marks a user who holds no permission set beyond the baseline as "Not authorized", read from their `sys_user_permission_set` and `sys_user_position` rows. The identity import entry is not offered, the organization members page shows a note instead of Invite member, and the recovery-password reminder does not show. With the flag absent or `false`, nothing changes. + + `AuthPublicConfig['features']` gains `cloudManaged`. `ObjectGrid` gains the `rowAdornment` host prop, a node drawn beside one row's title (the declared name field's cell, else the first shown column, and the card title in the card view), and `ListView` forwards its own `rowAdornment` to the grid. + + Clause-②: yes + Metadata-protocol: none +- 241cb78: Setup refusals lead with one plain sentence. The Packages sheet, the metadata editor's error banner (Positions and every other metadata type) and the action parameter dialog (OAuth application registration among them) now show the first sentence of the server's message, without a leading bracketed code or field path and without the trailing declared code. The whole message, byte for byte, sits behind a "More" toggle with a copy button. A one-sentence message renders as before. New `refusalDetails.*` strings in all ten locale packs (objectui#13332). +- 404ccae: Setup's metadata deletes and the related list's row delete now ask in the console's in-app confirm dialog and name what goes (objectui#13333). + + - The metadata editor's Reset overlay / Delete and Discard draft, the history timeline's Rollback, the Datasources page's Delete and a metadata type's `confirmText` action no longer use the browser's native `confirm()`. Each opens an in-app AlertDialog whose title names the item: by its type label and its own label for Reset / Delete (for example `Delete Object "Account"?`), with the machine `type/name` in the body; by label and name for a datasource; by action and item for a type action. + - The related list's row Delete no longer asks "Are you sure you want to delete this record?". The sentence names the row by its record title, the same resolver the record header uses, so a grant row reads by its declared title (the grant and the user it belongs to). The `detail.deleteRowConfirmation` string now takes a `{{name}}` value in all ten locales. +- ec627ab: A lookup / master-detail / tree value whose referenced record the viewer's own read answers "not found" for (a 404, which is what the server answers for a record this viewer may not read) now reads "Restricted record", translated, with a lock icon, no record id and no link, in grids and on the record page (objectui#13335). It used to print the raw id beside a question mark. No additional read is made: the label comes from the same lookup read the cell already performed, so it reveals nothing the id did not. A reference that is still loading, whose read failed, or that is empty renders as before, and a readable reference still shows its name as a link. New key: `detail.restrictedLookupReference` in all ten locale packs. +- 0f4adc3: Setup › Packaged automation: the Clone dialog now opens with a name and label filled in (objectui#13344). + + It used to open with both fields empty. It now proposes `_copy` as the machine name and " (copy)" as the label, using the flow's machine name when it has no label. Both fields stay editable, and the dialog can be submitted as it opens: the proposed name keeps the lowercase snake_case shape a flow name must have, and it is the same name the server suggests when a name is taken. A name that is already taken is still refused by the server with its 409 message, shown as sent. + + One new language-pack key, `packagedAutomation.cloneCopyLabel`, in all ten packs. +- fa31856: Connect an Agent no longer mints an unnamed API key in one click (objectui#13355). "Create key" stays disabled until the administrator types a name, and the name is sent as typed: the key is no longer created as `agent-key` when the name box is empty. Clicking "Create key" now opens an in-app confirm naming the key; Cancel creates nothing, and confirming creates the key and shows it once to copy, as before. This matches Setup → API Keys → Create Key, which also requires a name. + + New string: `connectAgent.apiKey.confirmTitle`, in all ten locale packs. +- 7f60e9d: A single-record action launched with 0 or several rows selected is refused before any dialog opens, and the refusal is translated (objectui#13384). + + `ActionRunner` now asks the handler it will dispatch to for an early refusal (`ActionRunnerHandler`'s optional `refuseBeforeInput`) before the confirmation and the param dialog. The handlers `createServerActionHandler` builds answer it with the row-count check the dispatch already runs, so "select a row first" and "select exactly one row" are shown before the user fills anything in, and nothing is sent. With exactly one row the dialog behaves as before. A host that wraps the built handler in its own function keeps the early refusal only by forwarding `refuseBeforeInput`; the console's `createConsoleServerActionHandler` now forwards it, so on a list page (HotCRM's "Add to Campaign" on My Leads) the refusal toast shows and no dialog opens. + + Both refusals now carry a pack key (`actions.selectRowFirst`, `actions.selectExactlyOneRow`, defined in every shipped pack). `resolveServerActionRecordId` returns it as `errorKey` beside the English `error`, and the runner's early refusal goes through its translator by that key. +- 4eeb174: A record-scoped flow action launched from a list toolbar with 0 or several rows selected is refused before its param dialog opens, and its refusal is translated (objectui#13397). + + The console's `flowHandler` now carries `refuseBeforeInput`, the early refusal objectui#13384 gave the `script` handler, answered by the same resolver its dispatch runs. The runner asks it before the confirmation and the param dialog, so "select a row first" and "select exactly one row" show in the session's language before the user fills anything in, and nothing is sent. With exactly one row the flow behaves as before. A direct call that is refused at dispatch time is shown through the refusal's pack key too. + + The console server-action wrapper's `newTabUrl` refusal ("no record id available") now has a pack key, `console.serverAction.noRecordId`, defined in every shipped pack, and the wrapper's fast path shows the resolver's own refusal through its pack key. +- afcf654: zh-CN: the admin-override approval copy no longer calls the override 越权 ("exceeding one's authority", the word for a violation). The override levers now read 管理员代为通过 / 管理员代为拒绝 / 管理员代为转签 / 管理员代为撤回 (`approvalsInbox.overrideActionLabel` is `管理员代为{{action}}`), the history chip reads 管理员代办 (`viaOverrideChip`) and its hint names the 管理员代办 path (`viaOverrideHint`), and the confirmation notices say 以管理员身份代为处理 and 记录为管理员代办 (`overrideNotice*`, `overrideReassignNotice*`, `overrideRecallNotice*`). Only the zh pack changes; the rest of each sentence and every placeholder are unchanged (objectui#13402). +- 2c3dc72: charts: a sankey now names every node and colours its flows, and a funnel labels every stage. Sankey nodes were bare bars with no text and every link was one grey, so the chart could not be read without hovering. Each node now carries its name (to its right, or to its left in the last column so it stays on the chart), and each link is stroked in the palette colour of the category it flows into. Every link leaves the same root node, so colouring by source would paint them all one colour again. A funnel labelled each stage to the right of its segment, past the plot's edge, so only the narrowest stage's label showed. Labels now sit centred inside their segments, in foreground text with a background halo so a name wider than the narrowest segment stays legible. The sankey's "Showing N of M rows" footnote now comes from the locale packs under the new count family `chart.sankeyOmittedRows`, translated in all ten packs. The English text is unchanged (objectui#13404). +- 2958f17: The console knows the `external` organization role that objectstack#25515 added to `@objectstack/spec`'s membership vocabulary (objectui#13427). Without it `ORG_ROLE_LABELS` no longer type-checked against an `@objectstack/spec` that lists the role. + + `@object-ui/auth` exports `ORG_ROLE_EXTERNAL` and labels it (`organization.roles.external`, "External"). Every pack in `@object-ui/i18n` carries the key; zh reads 外部成员, as the server's own `sys_member.role` option does. Wherever the installed spec lists the role, the invite dialog offers it to every issuer who can invite, a delegated admin included, because objectstack's invitation cap admits it from any issuer: it confers less than a member. Owners and admins can also set it from the members page. On the grade ladder it sits with `member`, as it does in objectstack's cap, so it never unlocks an administrative affordance. +- 2c4e5f5: A member who may read none of the objects an app names now lands on one page that says they need access and whom to ask, instead of the app's dashboard drawn as a grid of "You don't have access" tiles (objectstack-ai/objectstack#25338). + + The app root's landing asks the object-read prune's own verdict (`useNavMemberGates().can`) over every `type: 'object'` entry the app names, at every depth and in every area. When the app names at least one object and the member may read none of them, it renders `AppNoAccessEmptyState` with the new `reason="no-readable-object"`: "Your account cannot read any of the records in this app yet. Ask an administrator to assign you a permission set.", plus the Setup link for a member who may grant access. One readable object, or an app that names no object at all, lands exactly as before. + + Clause-②: yes + Metadata-protocol: none +- ad74e98: fix(plugin-list): the synthetic "All records" tab of a tabs-mode user-filter bar (`showAllRecords`) now reads its label from the new `list.userFilters.allRecords` i18n key, filled in every shipped locale (zh: 全部记录), instead of a hard-coded English string (objectui#13405). The tab's `__all__` id and behaviour are unchanged. +- Updated dependencies [49a536d] +- Updated dependencies [8e90779] +- Updated dependencies [7f60e9d] + - @object-ui/core@18.1.0 + ## 18.0.0 ### Major Changes diff --git a/packages/i18n/package.json b/packages/i18n/package.json index 4c56d95b43..2cd6ac057e 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/i18n", - "version": "18.0.0", + "version": "18.1.0", "type": "module", "sideEffects": false, "license": "MIT", diff --git a/packages/layout/CHANGELOG.md b/packages/layout/CHANGELOG.md index a085c82143..84da850d96 100644 --- a/packages/layout/CHANGELOG.md +++ b/packages/layout/CHANGELOG.md @@ -1,5 +1,37 @@ # @object-ui/layout +## 18.1.0 + +### Patch Changes + +- 8cf3a86: `AppShell` now draws one `main` landmark. `SidebarInset` already renders a `
`, and the content element inside it was a second `
`, so every console page (Setup record pages included) announced two main regions to screen readers. The content element is now a `
`; `className` still lands on it, and the skip link still targets the console's route slot. +- fb25620: A sidebar navigation group now opens on first view unless it declares `expanded: false` (or the legacy `defaultOpen: false`), however many entries it holds (objectui#13336). + + `NavigationRenderer` used to collapse any group that declared neither field once it had eight or more children. On Setup that closed Configuration (13 entries) although only Advanced declares `expanded: false`, hiding entries such as Localization, Email and Authentication on first view. The count rule is gone: a group holding the current route opens; otherwise its declared `expanded` / `defaultOpen` decides; otherwise it opens. Studio's navigation preview follows the same rule, so it still matches the running sidebar. + + An app that relied on a long, undeclared group starting closed should now declare `expanded: false` on it. +- Updated dependencies [8556295] +- Updated dependencies [cd14d8e] +- Updated dependencies [8701f1e] +- Updated dependencies [7c405b7] +- Updated dependencies [3aafc0d] +- Updated dependencies [601c406] +- Updated dependencies [b911ebb] +- Updated dependencies [49a536d] +- Updated dependencies [8e90779] +- Updated dependencies [f1a4b08] +- Updated dependencies [7f60e9d] +- Updated dependencies [d9aff15] +- Updated dependencies [a78608f] +- Updated dependencies [1d178e0] +- Updated dependencies [6fb31dc] +- Updated dependencies [fbb4b23] +- Updated dependencies [c8f8b10] + - @object-ui/types@18.1.0 + - @object-ui/components@18.1.0 + - @object-ui/react@18.1.0 + - @object-ui/core@18.1.0 + ## 18.0.0 ### Major Changes diff --git a/packages/layout/package.json b/packages/layout/package.json index 1205fe3d6c..9b4700d971 100644 --- a/packages/layout/package.json +++ b/packages/layout/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/layout", - "version": "18.0.0", + "version": "18.1.0", "type": "module", "sideEffects": [ "./dist/index.js", diff --git a/packages/mobile/CHANGELOG.md b/packages/mobile/CHANGELOG.md index d274b89322..fa8b9857be 100644 --- a/packages/mobile/CHANGELOG.md +++ b/packages/mobile/CHANGELOG.md @@ -1,5 +1,16 @@ # @object-ui/mobile +## 18.1.0 + +### Patch Changes + +- Updated dependencies [8556295] +- Updated dependencies [cd14d8e] +- Updated dependencies [f1a4b08] +- Updated dependencies [1d178e0] +- Updated dependencies [6fb31dc] + - @object-ui/types@18.1.0 + ## 18.0.0 ### Major Changes diff --git a/packages/mobile/package.json b/packages/mobile/package.json index d275324c68..eaedef1861 100644 --- a/packages/mobile/package.json +++ b/packages/mobile/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/mobile", - "version": "18.0.0", + "version": "18.1.0", "type": "module", "license": "MIT", "description": "Mobile optimization for Object UI with responsive components, PWA support, and touch gesture handling.", diff --git a/packages/permissions/CHANGELOG.md b/packages/permissions/CHANGELOG.md index 62005343b7..ef63deaa7e 100644 --- a/packages/permissions/CHANGELOG.md +++ b/packages/permissions/CHANGELOG.md @@ -1,5 +1,24 @@ # @object-ui/permissions +## 18.1.0 + +### Minor Changes + +- 0d12e95: An approver who is not an administrator sees the whole approval request page again: its fields, its decision panel with the decisions they may take, and its Timeline (objectui#13324). + + The console reads a request, and its timeline, through the approvals routes, which serve a request to each party to it. The record page then gated what it drew on the permissions answer for the data API, which names neither approval object for a member, because the platform keeps that door closed to them. So the page folded the request down to its id, drew no decision, and dropped the Timeline. Opening a request from the Approvals inbox showed a blank page. + + `@object-ui/permissions` adds `ServerReadScope`. Below it, the read verdicts for the objects it names (`check(object, 'read')` and `checkField(object, field, 'read')`) answer "allowed": whatever the server serves is what the viewer may read. Every other action, the field write and create verdicts, and every other object keep the enclosing provider's answer. The console mounts it for the two approval objects over every app. No read grant on either object is added: the data API stays closed to members. + +### Patch Changes + +- Updated dependencies [8556295] +- Updated dependencies [cd14d8e] +- Updated dependencies [f1a4b08] +- Updated dependencies [1d178e0] +- Updated dependencies [6fb31dc] + - @object-ui/types@18.1.0 + ## 18.0.0 ### Major Changes diff --git a/packages/permissions/package.json b/packages/permissions/package.json index b955c43be2..982665ccf2 100644 --- a/packages/permissions/package.json +++ b/packages/permissions/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/permissions", - "version": "18.0.0", + "version": "18.1.0", "type": "module", "license": "MIT", "description": "RBAC permission system for Object UI with object/field/row-level access control, permission guards, and hooks.", diff --git a/packages/plugin-ai/CHANGELOG.md b/packages/plugin-ai/CHANGELOG.md index c58aa42ebe..bfe8fdf5d8 100644 --- a/packages/plugin-ai/CHANGELOG.md +++ b/packages/plugin-ai/CHANGELOG.md @@ -1,5 +1,43 @@ # @object-ui/plugin-ai +## 18.1.0 + +### Patch Changes + +- Updated dependencies [8556295] +- Updated dependencies [cd14d8e] +- Updated dependencies [8701f1e] +- Updated dependencies [5235d6d] +- Updated dependencies [7c405b7] +- Updated dependencies [0093b2c] +- Updated dependencies [3aafc0d] +- Updated dependencies [ff77cfc] +- Updated dependencies [49a536d] +- Updated dependencies [241cb78] +- Updated dependencies [404ccae] +- Updated dependencies [ec627ab] +- Updated dependencies [0f4adc3] +- Updated dependencies [fa31856] +- Updated dependencies [8e90779] +- Updated dependencies [f1a4b08] +- Updated dependencies [7f60e9d] +- Updated dependencies [d9aff15] +- Updated dependencies [4eeb174] +- Updated dependencies [afcf654] +- Updated dependencies [2c3dc72] +- Updated dependencies [2958f17] +- Updated dependencies [a78608f] +- Updated dependencies [1d178e0] +- Updated dependencies [2c4e5f5] +- Updated dependencies [6fb31dc] +- Updated dependencies [fbb4b23] +- Updated dependencies [c8f8b10] +- Updated dependencies [ad74e98] + - @object-ui/types@18.1.0 + - @object-ui/components@18.1.0 + - @object-ui/i18n@18.1.0 + - @object-ui/core@18.1.0 + ## 18.0.0 ### Major Changes diff --git a/packages/plugin-ai/package.json b/packages/plugin-ai/package.json index 45c3ef3289..0441d6ca27 100644 --- a/packages/plugin-ai/package.json +++ b/packages/plugin-ai/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/plugin-ai", - "version": "18.0.0", + "version": "18.1.0", "type": "module", "main": "dist/index.umd.cjs", "module": "dist/index.js", diff --git a/packages/plugin-calendar/CHANGELOG.md b/packages/plugin-calendar/CHANGELOG.md index 9aca846cd2..1414485b44 100644 --- a/packages/plugin-calendar/CHANGELOG.md +++ b/packages/plugin-calendar/CHANGELOG.md @@ -1,5 +1,52 @@ # @object-ui/plugin-calendar +## 18.1.0 + +### Patch Changes + +- Updated dependencies [8556295] +- Updated dependencies [cd14d8e] +- Updated dependencies [8701f1e] +- Updated dependencies [5235d6d] +- Updated dependencies [7c405b7] +- Updated dependencies [0093b2c] +- Updated dependencies [f669732] +- Updated dependencies [3aafc0d] +- Updated dependencies [601c406] +- Updated dependencies [b911ebb] +- Updated dependencies [0d12e95] +- Updated dependencies [ff77cfc] +- Updated dependencies [49a536d] +- Updated dependencies [241cb78] +- Updated dependencies [404ccae] +- Updated dependencies [ec627ab] +- Updated dependencies [b93c9f6] +- Updated dependencies [0f4adc3] +- Updated dependencies [fa31856] +- Updated dependencies [8e90779] +- Updated dependencies [f1a4b08] +- Updated dependencies [7f60e9d] +- Updated dependencies [d9aff15] +- Updated dependencies [4eeb174] +- Updated dependencies [afcf654] +- Updated dependencies [2c3dc72] +- Updated dependencies [2958f17] +- Updated dependencies [a78608f] +- Updated dependencies [1d178e0] +- Updated dependencies [2c4e5f5] +- Updated dependencies [6fb31dc] +- Updated dependencies [fbb4b23] +- Updated dependencies [c8f8b10] +- Updated dependencies [ad74e98] + - @object-ui/types@18.1.0 + - @object-ui/components@18.1.0 + - @object-ui/i18n@18.1.0 + - @object-ui/plugin-detail@18.1.0 + - @object-ui/react@18.1.0 + - @object-ui/permissions@18.1.0 + - @object-ui/core@18.1.0 + - @object-ui/mobile@18.1.0 + ## 18.0.0 ### Major Changes diff --git a/packages/plugin-calendar/package.json b/packages/plugin-calendar/package.json index 4b6855f583..e5381a1d64 100644 --- a/packages/plugin-calendar/package.json +++ b/packages/plugin-calendar/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/plugin-calendar", - "version": "18.0.0", + "version": "18.1.0", "type": "module", "license": "MIT", "description": "Calendar view plugins for Object UI - includes both ObjectQL-integrated and standalone calendar components", diff --git a/packages/plugin-charts/CHANGELOG.md b/packages/plugin-charts/CHANGELOG.md index 2d087cb691..f7bf84368b 100644 --- a/packages/plugin-charts/CHANGELOG.md +++ b/packages/plugin-charts/CHANGELOG.md @@ -1,5 +1,52 @@ # @object-ui/plugin-charts +## 18.1.0 + +### Patch Changes + +- eadceab: charts: a line or area chart no longer cuts its first or last x-axis label at the chart's edge. recharts draws their categorical x axis as a point scale, which puts the edge categories on the plot edges, so a monthly trend chart drew its newest bucket "2026-10" as "2026". The axis is now inset at both ends by half a `YYYY-MM` label at the tick font. Bar charts, whose band axis already centres every category, and combo charts, which draw a value axis on each side, are unchanged (objectui#13390). +- b317942: A page-level `object-chart` bound to a `dataset` now draws a select dimension in the order its field declares its options, the order the dashboard's dataset widget already uses for the same dataset (objectui#11809). Before, the page block drew the dataset's GROUP BY order (the stored values, alphabetically), so a priority axis read High, Low, Medium, Urgent instead of Low, Medium, High, Urgent (objectui#13403). The rows are charted in declared order, values the options do not declare follow, and the empty bucket comes last; the schema handed to the renderer also carries the `categoryOrder` from `@object-ui/core`'s `buildCategoryOrder`, which a funnel orders its stages by. A dimension whose field declares no options keeps the dataset's order. +- 2c3dc72: charts: a sankey now names every node and colours its flows, and a funnel labels every stage. Sankey nodes were bare bars with no text and every link was one grey, so the chart could not be read without hovering. Each node now carries its name (to its right, or to its left in the last column so it stays on the chart), and each link is stroked in the palette colour of the category it flows into. Every link leaves the same root node, so colouring by source would paint them all one colour again. A funnel labelled each stage to the right of its segment, past the plot's edge, so only the narrowest stage's label showed. Labels now sit centred inside their segments, in foreground text with a background halo so a name wider than the narrowest segment stays legible. The sankey's "Showing N of M rows" footnote now comes from the locale packs under the new count family `chart.sankeyOmittedRows`, translated in all ten packs. The English text is unchanged (objectui#13404). +- 56b65c0: A single-series bar chart draws every bar in its series colour (objectstack#25330). + + A bar or horizontal-bar chart with one measure used to paint each bar a different palette colour, so the colour named nothing: the System Overview "Events by User" board drew each user in its own hue. A bar's colour now names its series. A dimension's semantic option colour (a select field's `options[].color`, such as health green/red/yellow) still paints its own bar; a category without one takes the series colour instead of a palette slot. Pie and donut slices keep one colour per category, and a chart with two or more series keeps one colour per series. +- Updated dependencies [8556295] +- Updated dependencies [cd14d8e] +- Updated dependencies [8701f1e] +- Updated dependencies [5235d6d] +- Updated dependencies [7c405b7] +- Updated dependencies [0093b2c] +- Updated dependencies [3aafc0d] +- Updated dependencies [601c406] +- Updated dependencies [b911ebb] +- Updated dependencies [ff77cfc] +- Updated dependencies [49a536d] +- Updated dependencies [241cb78] +- Updated dependencies [404ccae] +- Updated dependencies [ec627ab] +- Updated dependencies [0f4adc3] +- Updated dependencies [fa31856] +- Updated dependencies [8e90779] +- Updated dependencies [f1a4b08] +- Updated dependencies [7f60e9d] +- Updated dependencies [d9aff15] +- Updated dependencies [4eeb174] +- Updated dependencies [afcf654] +- Updated dependencies [2c3dc72] +- Updated dependencies [2958f17] +- Updated dependencies [a78608f] +- Updated dependencies [1d178e0] +- Updated dependencies [2c4e5f5] +- Updated dependencies [6fb31dc] +- Updated dependencies [fbb4b23] +- Updated dependencies [c8f8b10] +- Updated dependencies [ad74e98] + - @object-ui/types@18.1.0 + - @object-ui/components@18.1.0 + - @object-ui/i18n@18.1.0 + - @object-ui/react@18.1.0 + - @object-ui/core@18.1.0 + ## 18.0.0 ### Major Changes diff --git a/packages/plugin-charts/package.json b/packages/plugin-charts/package.json index d29324f664..825b639b71 100644 --- a/packages/plugin-charts/package.json +++ b/packages/plugin-charts/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/plugin-charts", - "version": "18.0.0", + "version": "18.1.0", "type": "module", "license": "MIT", "description": "Chart components plugin for Object UI, powered by Recharts", diff --git a/packages/plugin-chatbot/CHANGELOG.md b/packages/plugin-chatbot/CHANGELOG.md index 425c91b167..602c83db51 100644 --- a/packages/plugin-chatbot/CHANGELOG.md +++ b/packages/plugin-chatbot/CHANGELOG.md @@ -1,5 +1,54 @@ # @object-ui/plugin-chatbot +## 18.1.0 + +### Minor Changes + +- 47138b7: The Console's first page load no longer downloads the chat UI (objectui#13410). The `plugin-chatbot` chunk (169.6 KB gzipped, the third-largest eager chunk) and most of `vendor-markdown` used to load on every page, including for users who never open a chat, because the console shell imported a handful of small helpers from the `@object-ui/plugin-chatbot` package root, and the root re-exports the renderer that registers the chat components when it is evaluated. Measured on the Console's production build, the eager closure drops by 254,055 gzipped bytes (3,326,111 to 3,072,056). The chat now loads when it is first shown: opening the dock, visiting `/ai…` or `/s/:token`, or rendering a `chatbot`, `chatbot-enhanced` or `chatbot-floating` node. + + `@object-ui/plugin-chatbot` adds a side-effect-free `@object-ui/plugin-chatbot/core` subpath: `useAgents`, `resolveDefaultAgentName`, `PLATFORM_DEFAULT_AGENT`, `agentHasCapability`, the agent alias helpers (`AGENT_ALIAS_GROUPS`, `agentAliasGroup`, `agentRouteName`, `resolveAgentParam`, `isBuiltinAgentName`, `isBuildAgent`, `isAskAgent`), `AI_USAGE_REFRESH_EVENT`, `emitAiUsageRefresh`, `publishHealthFromResponse` and `detectPendingApproval`, with their types. Importing it registers nothing and reaches no chat UI module. The package root still exports every one of these names, unchanged. + + `@object-ui/app-shell` takes those names from `/core`, and the ChatDock loads its default chat body on first render instead of importing it. `resolveApiBase` is still exported from the same places. + +### Patch Changes + +- Updated dependencies [8556295] +- Updated dependencies [cd14d8e] +- Updated dependencies [8701f1e] +- Updated dependencies [5235d6d] +- Updated dependencies [7c405b7] +- Updated dependencies [0093b2c] +- Updated dependencies [3aafc0d] +- Updated dependencies [601c406] +- Updated dependencies [b911ebb] +- Updated dependencies [ff77cfc] +- Updated dependencies [49a536d] +- Updated dependencies [241cb78] +- Updated dependencies [404ccae] +- Updated dependencies [ec627ab] +- Updated dependencies [0f4adc3] +- Updated dependencies [fa31856] +- Updated dependencies [8e90779] +- Updated dependencies [f1a4b08] +- Updated dependencies [7f60e9d] +- Updated dependencies [d9aff15] +- Updated dependencies [4eeb174] +- Updated dependencies [afcf654] +- Updated dependencies [2c3dc72] +- Updated dependencies [2958f17] +- Updated dependencies [a78608f] +- Updated dependencies [1d178e0] +- Updated dependencies [2c4e5f5] +- Updated dependencies [6fb31dc] +- Updated dependencies [fbb4b23] +- Updated dependencies [c8f8b10] +- Updated dependencies [ad74e98] + - @object-ui/types@18.1.0 + - @object-ui/components@18.1.0 + - @object-ui/i18n@18.1.0 + - @object-ui/react@18.1.0 + - @object-ui/core@18.1.0 + ## 18.0.0 ### Major Changes diff --git a/packages/plugin-chatbot/package.json b/packages/plugin-chatbot/package.json index 3e6ed01622..4bfae09345 100644 --- a/packages/plugin-chatbot/package.json +++ b/packages/plugin-chatbot/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/plugin-chatbot", - "version": "18.0.0", + "version": "18.1.0", "type": "module", "license": "MIT", "description": "Chatbot interface plugin for Object UI", diff --git a/packages/plugin-dashboard/CHANGELOG.md b/packages/plugin-dashboard/CHANGELOG.md index 2396d34e35..85af8775d1 100644 --- a/packages/plugin-dashboard/CHANGELOG.md +++ b/packages/plugin-dashboard/CHANGELOG.md @@ -1,5 +1,54 @@ # @object-ui/plugin-dashboard +## 18.1.0 + +### Patch Changes + +- 1d178e0: dashboard: a dataset chart draws its null bucket under the name the dataset declares for it (`fields[].nullLabel`, the dimension's `nullLabel` resolved by the server), over the global `chart.nullCategory` default. System Overview's "Events by User" now reads "System" for the rows the platform writes itself instead of "(None)". A column without one keeps the locale default, and a two-dimension pivot takes a declared name only when both dimensions declare the same one (objectstack#25330). +- Updated dependencies [8556295] +- Updated dependencies [cd14d8e] +- Updated dependencies [8701f1e] +- Updated dependencies [5235d6d] +- Updated dependencies [8e649da] +- Updated dependencies [7c405b7] +- Updated dependencies [0093b2c] +- Updated dependencies [813c3d9] +- Updated dependencies [3aafc0d] +- Updated dependencies [601c406] +- Updated dependencies [b911ebb] +- Updated dependencies [0d12e95] +- Updated dependencies [ff77cfc] +- Updated dependencies [49a536d] +- Updated dependencies [241cb78] +- Updated dependencies [404ccae] +- Updated dependencies [ec627ab] +- Updated dependencies [0f4adc3] +- Updated dependencies [fa31856] +- Updated dependencies [8e90779] +- Updated dependencies [f1a4b08] +- Updated dependencies [7f60e9d] +- Updated dependencies [d9aff15] +- Updated dependencies [4eeb174] +- Updated dependencies [afcf654] +- Updated dependencies [2c3dc72] +- Updated dependencies [cee3bc5] +- Updated dependencies [2958f17] +- Updated dependencies [a78608f] +- Updated dependencies [1d178e0] +- Updated dependencies [2c4e5f5] +- Updated dependencies [6fb31dc] +- Updated dependencies [fbb4b23] +- Updated dependencies [f3044f7] +- Updated dependencies [c8f8b10] +- Updated dependencies [ad74e98] + - @object-ui/types@18.1.0 + - @object-ui/components@18.1.0 + - @object-ui/fields@18.1.0 + - @object-ui/i18n@18.1.0 + - @object-ui/react@18.1.0 + - @object-ui/permissions@18.1.0 + - @object-ui/core@18.1.0 + ## 18.0.0 ### Major Changes diff --git a/packages/plugin-dashboard/package.json b/packages/plugin-dashboard/package.json index 74b57d858d..4c2fda9f89 100644 --- a/packages/plugin-dashboard/package.json +++ b/packages/plugin-dashboard/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/plugin-dashboard", - "version": "18.0.0", + "version": "18.1.0", "type": "module", "license": "MIT", "description": "Dashboard plugin for Object UI", diff --git a/packages/plugin-designer/CHANGELOG.md b/packages/plugin-designer/CHANGELOG.md index c6db15e019..be7a576aa6 100644 --- a/packages/plugin-designer/CHANGELOG.md +++ b/packages/plugin-designer/CHANGELOG.md @@ -1,5 +1,56 @@ # @object-ui/plugin-designer +## 18.1.0 + +### Patch Changes + +- Updated dependencies [8556295] +- Updated dependencies [cd14d8e] +- Updated dependencies [8701f1e] +- Updated dependencies [5235d6d] +- Updated dependencies [7c405b7] +- Updated dependencies [0093b2c] +- Updated dependencies [3aafc0d] +- Updated dependencies [601c406] +- Updated dependencies [56cf4d8] +- Updated dependencies [b911ebb] +- Updated dependencies [ff77cfc] +- Updated dependencies [49a536d] +- Updated dependencies [241cb78] +- Updated dependencies [404ccae] +- Updated dependencies [8cf3a86] +- Updated dependencies [ec627ab] +- Updated dependencies [fb25620] +- Updated dependencies [b93c9f6] +- Updated dependencies [d019aaa] +- Updated dependencies [0f4adc3] +- Updated dependencies [fa31856] +- Updated dependencies [8e90779] +- Updated dependencies [f1a4b08] +- Updated dependencies [7f60e9d] +- Updated dependencies [d9aff15] +- Updated dependencies [4eeb174] +- Updated dependencies [afcf654] +- Updated dependencies [2c3dc72] +- Updated dependencies [2958f17] +- Updated dependencies [a78608f] +- Updated dependencies [1d178e0] +- Updated dependencies [a14737b] +- Updated dependencies [2c4e5f5] +- Updated dependencies [6fb31dc] +- Updated dependencies [fbb4b23] +- Updated dependencies [c8f8b10] +- Updated dependencies [ad74e98] + - @object-ui/types@18.1.0 + - @object-ui/plugin-grid@18.1.0 + - @object-ui/components@18.1.0 + - @object-ui/i18n@18.1.0 + - @object-ui/react@18.1.0 + - @object-ui/core@18.1.0 + - @object-ui/layout@18.1.0 + - @object-ui/data-objectstack@18.1.0 + - @object-ui/plugin-form@18.1.0 + ## 18.0.0 ### Major Changes diff --git a/packages/plugin-designer/package.json b/packages/plugin-designer/package.json index 87d34f81c1..c1bc16dce5 100644 --- a/packages/plugin-designer/package.json +++ b/packages/plugin-designer/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/plugin-designer", - "version": "18.0.0", + "version": "18.1.0", "type": "module", "license": "MIT", "description": "Visual designer plugin for Object UI with page, data model, process, and report designers plus collaborative editing.", diff --git a/packages/plugin-detail/CHANGELOG.md b/packages/plugin-detail/CHANGELOG.md index 02a4609f2d..716736f810 100644 --- a/packages/plugin-detail/CHANGELOG.md +++ b/packages/plugin-detail/CHANGELOG.md @@ -1,5 +1,70 @@ # @object-ui/plugin-detail +## 18.1.0 + +### Patch Changes + +- f669732: The inline-edit save bar shows an object-level rule's refusal as the rule's own message, without a field label (objectui#13292). + + The server names an object-level rule (a `script` rule, or one that lists no fields) with the `_record` sentinel. The bar used to print that sentinel as a field label, so the banner read `_record: …`. Now an entry that names `_record`, or names no field of the record, is shown alone in the banner and is not published as a per-field hint. Field-level entries are unchanged: they keep their label and their hint beside the input. +- 49a536d: The record header's highlights write the year on every date (objectui#13331). + + A current-year date dropped its year in the strip, so a contract record read "Start Date Sep 15, 2025 | End Date Sep 15" and a contract that ended this September looked like it ended next month. The strip now asks for the year, and both dates read alike. Dates inside the ±7-day window keep their relative phrase ("In 2 days"). + + `formatDate` takes a new opt-in option, `alwaysShowYear`, which keeps the year on its default face; the `date` and `datetime` cell renderers take an `alwaysShowYear` prop that hands it on. Neither is on by default: grid cells and cards still drop the current year. +- 404ccae: Setup's metadata deletes and the related list's row delete now ask in the console's in-app confirm dialog and name what goes (objectui#13333). + + - The metadata editor's Reset overlay / Delete and Discard draft, the history timeline's Rollback, the Datasources page's Delete and a metadata type's `confirmText` action no longer use the browser's native `confirm()`. Each opens an in-app AlertDialog whose title names the item: by its type label and its own label for Reset / Delete (for example `Delete Object "Account"?`), with the machine `type/name` in the body; by label and name for a datasource; by action and item for a type action. + - The related list's row Delete no longer asks "Are you sure you want to delete this record?". The sentence names the row by its record title, the same resolver the record header uses, so a grant row reads by its declared title (the grant and the user it belongs to). The `detail.deleteRowConfirmation` string now takes a `{{name}}` value in all ten locales. +- b93c9f6: After a save, delete or action, the record page and the list ask the platform's explain engine each record's edit and delete question once (objectui#13341). + + One write often reaches the console's data-change bus twice: once when the data source reports it, and again from the page or list that made it. When the second notice arrived while the fresh permission check was still waiting for its answer, the check was thrown away and sent again, so one Setup save could send `POST /api/v1/security/explain` two to six times. Now a notice that arrives while a record's fresh check is on its way joins that check. A check that was already on its way before the write is still discarded and asked again, and a change announced after the check has answered still asks again, so Edit and Delete still follow the record's state after the write. + + The list also stops asking again about rows whose answer is already on its way when its own re-read changes the rows on screen, and asks only about the rows nobody has asked about yet. A list whose rows go past the server's batch limit now sends its batches at once instead of one after another. +- Updated dependencies [8556295] +- Updated dependencies [cd14d8e] +- Updated dependencies [8701f1e] +- Updated dependencies [5235d6d] +- Updated dependencies [8e649da] +- Updated dependencies [7c405b7] +- Updated dependencies [0093b2c] +- Updated dependencies [813c3d9] +- Updated dependencies [3aafc0d] +- Updated dependencies [601c406] +- Updated dependencies [b911ebb] +- Updated dependencies [0d12e95] +- Updated dependencies [ff77cfc] +- Updated dependencies [49a536d] +- Updated dependencies [241cb78] +- Updated dependencies [404ccae] +- Updated dependencies [ec627ab] +- Updated dependencies [0f4adc3] +- Updated dependencies [fa31856] +- Updated dependencies [8e90779] +- Updated dependencies [f1a4b08] +- Updated dependencies [7f60e9d] +- Updated dependencies [d9aff15] +- Updated dependencies [4eeb174] +- Updated dependencies [afcf654] +- Updated dependencies [2c3dc72] +- Updated dependencies [cee3bc5] +- Updated dependencies [2958f17] +- Updated dependencies [a78608f] +- Updated dependencies [1d178e0] +- Updated dependencies [2c4e5f5] +- Updated dependencies [6fb31dc] +- Updated dependencies [fbb4b23] +- Updated dependencies [f3044f7] +- Updated dependencies [c8f8b10] +- Updated dependencies [ad74e98] + - @object-ui/types@18.1.0 + - @object-ui/components@18.1.0 + - @object-ui/fields@18.1.0 + - @object-ui/i18n@18.1.0 + - @object-ui/react@18.1.0 + - @object-ui/permissions@18.1.0 + - @object-ui/core@18.1.0 + ## 18.0.0 ### Major Changes diff --git a/packages/plugin-detail/package.json b/packages/plugin-detail/package.json index c30c6bd559..f888dfcb09 100644 --- a/packages/plugin-detail/package.json +++ b/packages/plugin-detail/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/plugin-detail", - "version": "18.0.0", + "version": "18.1.0", "type": "module", "license": "MIT", "description": "DetailView plugin for Object UI - comprehensive detail page with sections, tabs, and related lists", diff --git a/packages/plugin-editor/CHANGELOG.md b/packages/plugin-editor/CHANGELOG.md index ce60fb5f1f..b9891aa2f1 100644 --- a/packages/plugin-editor/CHANGELOG.md +++ b/packages/plugin-editor/CHANGELOG.md @@ -1,5 +1,28 @@ # @object-ui/plugin-editor +## 18.1.0 + +### Patch Changes + +- Updated dependencies [8556295] +- Updated dependencies [cd14d8e] +- Updated dependencies [8701f1e] +- Updated dependencies [7c405b7] +- Updated dependencies [3aafc0d] +- Updated dependencies [49a536d] +- Updated dependencies [8e90779] +- Updated dependencies [f1a4b08] +- Updated dependencies [7f60e9d] +- Updated dependencies [d9aff15] +- Updated dependencies [a78608f] +- Updated dependencies [1d178e0] +- Updated dependencies [6fb31dc] +- Updated dependencies [fbb4b23] +- Updated dependencies [c8f8b10] + - @object-ui/types@18.1.0 + - @object-ui/components@18.1.0 + - @object-ui/core@18.1.0 + ## 18.0.0 ### Major Changes diff --git a/packages/plugin-editor/package.json b/packages/plugin-editor/package.json index ab96ec172b..a8b493318e 100644 --- a/packages/plugin-editor/package.json +++ b/packages/plugin-editor/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/plugin-editor", - "version": "18.0.0", + "version": "18.1.0", "type": "module", "license": "MIT", "description": "Rich text editor plugin for Object UI, powered by Monaco Editor", diff --git a/packages/plugin-form/CHANGELOG.md b/packages/plugin-form/CHANGELOG.md index 46aa4c927b..9a705ec145 100644 --- a/packages/plugin-form/CHANGELOG.md +++ b/packages/plugin-form/CHANGELOG.md @@ -1,5 +1,53 @@ # @object-ui/plugin-form +## 18.1.0 + +### Patch Changes + +- Updated dependencies [8556295] +- Updated dependencies [cd14d8e] +- Updated dependencies [8701f1e] +- Updated dependencies [5235d6d] +- Updated dependencies [8e649da] +- Updated dependencies [7c405b7] +- Updated dependencies [0093b2c] +- Updated dependencies [813c3d9] +- Updated dependencies [3aafc0d] +- Updated dependencies [601c406] +- Updated dependencies [b911ebb] +- Updated dependencies [0d12e95] +- Updated dependencies [ff77cfc] +- Updated dependencies [49a536d] +- Updated dependencies [241cb78] +- Updated dependencies [404ccae] +- Updated dependencies [ec627ab] +- Updated dependencies [0f4adc3] +- Updated dependencies [fa31856] +- Updated dependencies [8e90779] +- Updated dependencies [f1a4b08] +- Updated dependencies [7f60e9d] +- Updated dependencies [d9aff15] +- Updated dependencies [4eeb174] +- Updated dependencies [afcf654] +- Updated dependencies [2c3dc72] +- Updated dependencies [cee3bc5] +- Updated dependencies [2958f17] +- Updated dependencies [a78608f] +- Updated dependencies [1d178e0] +- Updated dependencies [2c4e5f5] +- Updated dependencies [6fb31dc] +- Updated dependencies [fbb4b23] +- Updated dependencies [f3044f7] +- Updated dependencies [c8f8b10] +- Updated dependencies [ad74e98] + - @object-ui/types@18.1.0 + - @object-ui/components@18.1.0 + - @object-ui/fields@18.1.0 + - @object-ui/i18n@18.1.0 + - @object-ui/react@18.1.0 + - @object-ui/permissions@18.1.0 + - @object-ui/core@18.1.0 + ## 18.0.0 ### Major Changes diff --git a/packages/plugin-form/package.json b/packages/plugin-form/package.json index 319ce3333e..ea1b0e70f5 100644 --- a/packages/plugin-form/package.json +++ b/packages/plugin-form/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/plugin-form", - "version": "18.0.0", + "version": "18.1.0", "type": "module", "license": "MIT", "description": "Form plugin for Object UI", diff --git a/packages/plugin-gantt/CHANGELOG.md b/packages/plugin-gantt/CHANGELOG.md index d1c9f96ec4..1995378f03 100644 --- a/packages/plugin-gantt/CHANGELOG.md +++ b/packages/plugin-gantt/CHANGELOG.md @@ -1,5 +1,56 @@ # @object-ui/plugin-gantt +## 18.1.0 + +### Patch Changes + +- Updated dependencies [8556295] +- Updated dependencies [cd14d8e] +- Updated dependencies [8701f1e] +- Updated dependencies [5235d6d] +- Updated dependencies [8e649da] +- Updated dependencies [7c405b7] +- Updated dependencies [0093b2c] +- Updated dependencies [f669732] +- Updated dependencies [813c3d9] +- Updated dependencies [3aafc0d] +- Updated dependencies [601c406] +- Updated dependencies [b911ebb] +- Updated dependencies [0d12e95] +- Updated dependencies [ff77cfc] +- Updated dependencies [49a536d] +- Updated dependencies [241cb78] +- Updated dependencies [404ccae] +- Updated dependencies [ec627ab] +- Updated dependencies [b93c9f6] +- Updated dependencies [0f4adc3] +- Updated dependencies [fa31856] +- Updated dependencies [8e90779] +- Updated dependencies [f1a4b08] +- Updated dependencies [7f60e9d] +- Updated dependencies [d9aff15] +- Updated dependencies [4eeb174] +- Updated dependencies [afcf654] +- Updated dependencies [2c3dc72] +- Updated dependencies [cee3bc5] +- Updated dependencies [2958f17] +- Updated dependencies [a78608f] +- Updated dependencies [1d178e0] +- Updated dependencies [2c4e5f5] +- Updated dependencies [6fb31dc] +- Updated dependencies [fbb4b23] +- Updated dependencies [f3044f7] +- Updated dependencies [c8f8b10] +- Updated dependencies [ad74e98] + - @object-ui/types@18.1.0 + - @object-ui/components@18.1.0 + - @object-ui/fields@18.1.0 + - @object-ui/i18n@18.1.0 + - @object-ui/plugin-detail@18.1.0 + - @object-ui/react@18.1.0 + - @object-ui/permissions@18.1.0 + - @object-ui/core@18.1.0 + ## 18.0.0 ### Major Changes diff --git a/packages/plugin-gantt/package.json b/packages/plugin-gantt/package.json index 80f7f965e9..f4c8c760ee 100644 --- a/packages/plugin-gantt/package.json +++ b/packages/plugin-gantt/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/plugin-gantt", - "version": "18.0.0", + "version": "18.1.0", "type": "module", "license": "MIT", "description": "Gantt chart plugin for Object UI", diff --git a/packages/plugin-grid/CHANGELOG.md b/packages/plugin-grid/CHANGELOG.md index 41695f345f..ded5a511e8 100644 --- a/packages/plugin-grid/CHANGELOG.md +++ b/packages/plugin-grid/CHANGELOG.md @@ -1,5 +1,96 @@ # @object-ui/plugin-grid +## 18.1.0 + +### Minor Changes + +- ff77cfc: On a cloud-managed environment (`features.cloudManaged: true` from `/auth/config`), the console says what the server already enforces. Setup → Users shows one line saying where people are invited (the organization, in the cloud) and marks a user who holds no permission set beyond the baseline as "Not authorized", read from their `sys_user_permission_set` and `sys_user_position` rows. The identity import entry is not offered, the organization members page shows a note instead of Invite member, and the recovery-password reminder does not show. With the flag absent or `false`, nothing changes. + + `AuthPublicConfig['features']` gains `cloudManaged`. `ObjectGrid` gains the `rowAdornment` host prop, a node drawn beside one row's title (the declared name field's cell, else the first shown column, and the card title in the card view), and `ListView` forwards its own `rowAdornment` to the grid. + + Clause-②: yes + Metadata-protocol: none + +### Patch Changes + +- cd14d8e: The bulk action confirm step reads `confirmText` as a string or as a `{ dialect: 'template', source }` envelope (objectui#13183). + + `@objectstack/spec` is making a bulk action's `confirmText` a `template` slot (objectstack#24947), so a parsed bulk definition serves the envelope where it served a string. The confirm step rendered `confirmText` as it came, so an envelope would have broken it. It now shows the string, or the envelope's `source` as written; a blank or absent value still shows the default sentence ("This will apply to N record(s)."). `{{ }}` holes are not filled yet: `{{ count }}` still shows as written. `BulkActionDef.confirmText` in `@object-ui/types` is typed `string | { dialect?: 'template'; source: string }`, and `@object-ui/plugin-grid` reads it through one helper, `bulkConfirmTextSource`. +- 56cf4d8: The Import Wizard sends a CSV file to the import door as CSV text (objectui#13315). When you import a `.csv`, `.tsv` or `.txt` file, the request is now `format: 'csv'` with the rows the preview shows written out as CSV. This holds on the hand-mapped path, and with a saved mapping that does not declare `sourceFormat: 'json'`. Before, those rows were sent as JSON, so the server never read the file's cells through its CSV import rule, the one its CSV export pairs with. + + - **The text is the preview's rows.** The wizard writes the CSV from the rows it shows, not from the file as uploaded, as it already did for a mapping that declares `sourceFormat: 'csv'`. A cell you corrected in the preview is sent corrected. The dry-run check sends the same request as the import. + - **Unchanged:** an `.xlsx` sheet and a pasted table are sent as JSON rows. A saved mapping that declares `sourceFormat: 'json'` still gets JSON rows from any file, because the import door does not accept CSV text for it. + - **User import** (`sys_user`) sends a CSV file as CSV text too, in batches of at most 500 rows. Each one-time password is still shown with the email or phone number of its row. + + Three shapes now import differently from what the preview shows: + + - **A last row whose mapped cells are all empty is not imported.** When the file's last row, or a run of last rows, has data only in columns you did not map, the server does not read it. The import counts one row fewer than the preview, and that row creates no record and reports no error. A row of that shape anywhere else in the file is imported as before, so row numbers keep matching the preview. User import sends the file in batches of 500 rows, so there the same holds for the last row of each batch. + - **A cell that begins with an apostrophe and ends in a tab or a line break keeps the apostrophe** when the rest of it starts with `+` or `-` and holds only digits, spaces and `( ) + - . ,`. The preview trims the tab or line break before the cell is sent, and a server whose CSV import removes the apostrophe the CSV export adds leaves this trimmed cell as it is. The wizard imported such a cell with its apostrophe before this change too. + - **A space before a leading apostrophe is trimmed first.** On a server whose CSV import removes the apostrophe the CSV export adds, a cell typed as a space, an apostrophe and a value the export would write with an apostrophe now imports without the apostrophe. Before this change it imported with it. + + No export, prop or type is added to either package entry. +- b93c9f6: After a save, delete or action, the record page and the list ask the platform's explain engine each record's edit and delete question once (objectui#13341). + + One write often reaches the console's data-change bus twice: once when the data source reports it, and again from the page or list that made it. When the second notice arrived while the fresh permission check was still waiting for its answer, the check was thrown away and sent again, so one Setup save could send `POST /api/v1/security/explain` two to six times. Now a notice that arrives while a record's fresh check is on its way joins that check. A check that was already on its way before the write is still discarded and asked again, and a change announced after the check has answered still asks again, so Edit and Delete still follow the record's state after the write. + + The list also stops asking again about rows whose answer is already on its way when its own re-read changes the rows on screen, and asks only about the rows nobody has asked about yet. A list whose rows go past the server's batch limit now sends its batches at once instead of one after another. +- d019aaa: The import wizard now opens its mapping step with the object's saved mapping applied when the object ships exactly one that the target accepts (objectui#13343). Before, the step always opened on "Map columns manually", so a user who never opened the "Saved mapping" menu imported without the mapping's renames and transforms. The preselection applies the mapping the same way picking it from the menu does, and the wizard decides it once per opening: a re-fetched mapping list or a re-render does not apply it again after the user switches back to manual mapping. With no saved mapping, or with several the target accepts, the step still opens on manual mapping. A mapping whose write mode the target refuses is still listed disabled and is not counted. +- f1a4b08: Grids: hovering a `lookup` or `master_detail` cell no longer shows the referenced record's raw id (objectui#13377). + + The table's cell wrapper set its `title` tooltip to the cell's raw value, and for a reference column that value is the related record's id. So hovering beside the drawn name, or beside "Restricted record" for a record the viewer cannot read, still showed the id. + + - **`@object-ui/types`:** `TableColumn` gains an optional `foreignKey` boolean: the column's raw value is the id of a referenced record. The zod mirror (`TableColumnSchema`) keeps it, and the static `table` column refuses it by name, like `masked` and `chips`. + - **`@object-ui/components`:** a `data-table` column with `foreignKey: true` draws no `title` tooltip. Nothing else changes for it: copy, CSV export, inline edit, search and sort behave as before. + - **`@object-ui/plugin-grid`:** `ObjectGrid` sets `foreignKey` on every `lookup`, `master_detail`, `tree` and `user` column, read from the column's own type or the object's field type. Every other column keeps its tooltip. +- fbb4b23: data-table / VirtualGrid: selecting a cell's text no longer opens the record or starts an inline edit, and Ctrl/Cmd+C copies the selected text instead of the whole cell value. A plain click still opens or edits as before (objectui#13188). +- Updated dependencies [8556295] +- Updated dependencies [cd14d8e] +- Updated dependencies [8701f1e] +- Updated dependencies [5235d6d] +- Updated dependencies [8e649da] +- Updated dependencies [7c405b7] +- Updated dependencies [0093b2c] +- Updated dependencies [f669732] +- Updated dependencies [813c3d9] +- Updated dependencies [3aafc0d] +- Updated dependencies [601c406] +- Updated dependencies [b911ebb] +- Updated dependencies [0d12e95] +- Updated dependencies [ff77cfc] +- Updated dependencies [49a536d] +- Updated dependencies [241cb78] +- Updated dependencies [404ccae] +- Updated dependencies [ec627ab] +- Updated dependencies [b93c9f6] +- Updated dependencies [0f4adc3] +- Updated dependencies [fa31856] +- Updated dependencies [8e90779] +- Updated dependencies [f1a4b08] +- Updated dependencies [7f60e9d] +- Updated dependencies [d9aff15] +- Updated dependencies [4eeb174] +- Updated dependencies [afcf654] +- Updated dependencies [2c3dc72] +- Updated dependencies [cee3bc5] +- Updated dependencies [2958f17] +- Updated dependencies [a78608f] +- Updated dependencies [1d178e0] +- Updated dependencies [2c4e5f5] +- Updated dependencies [6fb31dc] +- Updated dependencies [fbb4b23] +- Updated dependencies [f3044f7] +- Updated dependencies [c8f8b10] +- Updated dependencies [ad74e98] + - @object-ui/types@18.1.0 + - @object-ui/components@18.1.0 + - @object-ui/fields@18.1.0 + - @object-ui/i18n@18.1.0 + - @object-ui/plugin-detail@18.1.0 + - @object-ui/react@18.1.0 + - @object-ui/permissions@18.1.0 + - @object-ui/core@18.1.0 + - @object-ui/mobile@18.1.0 + ## 18.0.0 ### Major Changes diff --git a/packages/plugin-grid/package.json b/packages/plugin-grid/package.json index e2012c0886..acb5327d1f 100644 --- a/packages/plugin-grid/package.json +++ b/packages/plugin-grid/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/plugin-grid", - "version": "18.0.0", + "version": "18.1.0", "type": "module", "license": "MIT", "description": "Grid plugin for Object UI", diff --git a/packages/plugin-kanban/CHANGELOG.md b/packages/plugin-kanban/CHANGELOG.md index a7197c8d39..a373acb972 100644 --- a/packages/plugin-kanban/CHANGELOG.md +++ b/packages/plugin-kanban/CHANGELOG.md @@ -1,5 +1,56 @@ # @object-ui/plugin-kanban +## 18.1.0 + +### Patch Changes + +- Updated dependencies [8556295] +- Updated dependencies [cd14d8e] +- Updated dependencies [8701f1e] +- Updated dependencies [5235d6d] +- Updated dependencies [8e649da] +- Updated dependencies [7c405b7] +- Updated dependencies [0093b2c] +- Updated dependencies [f669732] +- Updated dependencies [813c3d9] +- Updated dependencies [3aafc0d] +- Updated dependencies [601c406] +- Updated dependencies [b911ebb] +- Updated dependencies [0d12e95] +- Updated dependencies [ff77cfc] +- Updated dependencies [49a536d] +- Updated dependencies [241cb78] +- Updated dependencies [404ccae] +- Updated dependencies [ec627ab] +- Updated dependencies [b93c9f6] +- Updated dependencies [0f4adc3] +- Updated dependencies [fa31856] +- Updated dependencies [8e90779] +- Updated dependencies [f1a4b08] +- Updated dependencies [7f60e9d] +- Updated dependencies [d9aff15] +- Updated dependencies [4eeb174] +- Updated dependencies [afcf654] +- Updated dependencies [2c3dc72] +- Updated dependencies [cee3bc5] +- Updated dependencies [2958f17] +- Updated dependencies [a78608f] +- Updated dependencies [1d178e0] +- Updated dependencies [2c4e5f5] +- Updated dependencies [6fb31dc] +- Updated dependencies [fbb4b23] +- Updated dependencies [f3044f7] +- Updated dependencies [c8f8b10] +- Updated dependencies [ad74e98] + - @object-ui/types@18.1.0 + - @object-ui/components@18.1.0 + - @object-ui/fields@18.1.0 + - @object-ui/i18n@18.1.0 + - @object-ui/plugin-detail@18.1.0 + - @object-ui/react@18.1.0 + - @object-ui/permissions@18.1.0 + - @object-ui/core@18.1.0 + ## 18.0.0 ### Major Changes diff --git a/packages/plugin-kanban/package.json b/packages/plugin-kanban/package.json index f0cd16a40e..9d4cf8ae1d 100644 --- a/packages/plugin-kanban/package.json +++ b/packages/plugin-kanban/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/plugin-kanban", - "version": "18.0.0", + "version": "18.1.0", "type": "module", "license": "MIT", "description": "Kanban board plugin for Object UI, powered by dnd-kit", diff --git a/packages/plugin-list/CHANGELOG.md b/packages/plugin-list/CHANGELOG.md index 465bc148fe..44b492983d 100644 --- a/packages/plugin-list/CHANGELOG.md +++ b/packages/plugin-list/CHANGELOG.md @@ -1,5 +1,64 @@ # @object-ui/plugin-list +## 18.1.0 + +### Minor Changes + +- ff77cfc: On a cloud-managed environment (`features.cloudManaged: true` from `/auth/config`), the console says what the server already enforces. Setup → Users shows one line saying where people are invited (the organization, in the cloud) and marks a user who holds no permission set beyond the baseline as "Not authorized", read from their `sys_user_permission_set` and `sys_user_position` rows. The identity import entry is not offered, the organization members page shows a note instead of Invite member, and the recovery-password reminder does not show. With the flag absent or `false`, nothing changes. + + `AuthPublicConfig['features']` gains `cloudManaged`. `ObjectGrid` gains the `rowAdornment` host prop, a node drawn beside one row's title (the declared name field's cell, else the first shown column, and the card title in the card view), and `ListView` forwards its own `rowAdornment` to the grid. + + Clause-②: yes + Metadata-protocol: none + +### Patch Changes + +- ad74e98: fix(plugin-list): the synthetic "All records" tab of a tabs-mode user-filter bar (`showAllRecords`) now reads its label from the new `list.userFilters.allRecords` i18n key, filled in every shipped locale (zh: 全部记录), instead of a hard-coded English string (objectui#13405). The tab's `__all__` id and behaviour are unchanged. +- Updated dependencies [8556295] +- Updated dependencies [cd14d8e] +- Updated dependencies [8701f1e] +- Updated dependencies [5235d6d] +- Updated dependencies [8e649da] +- Updated dependencies [7c405b7] +- Updated dependencies [0093b2c] +- Updated dependencies [813c3d9] +- Updated dependencies [3aafc0d] +- Updated dependencies [601c406] +- Updated dependencies [b911ebb] +- Updated dependencies [0d12e95] +- Updated dependencies [ff77cfc] +- Updated dependencies [49a536d] +- Updated dependencies [241cb78] +- Updated dependencies [404ccae] +- Updated dependencies [ec627ab] +- Updated dependencies [0f4adc3] +- Updated dependencies [fa31856] +- Updated dependencies [8e90779] +- Updated dependencies [f1a4b08] +- Updated dependencies [7f60e9d] +- Updated dependencies [d9aff15] +- Updated dependencies [4eeb174] +- Updated dependencies [afcf654] +- Updated dependencies [2c3dc72] +- Updated dependencies [cee3bc5] +- Updated dependencies [2958f17] +- Updated dependencies [a78608f] +- Updated dependencies [1d178e0] +- Updated dependencies [2c4e5f5] +- Updated dependencies [6fb31dc] +- Updated dependencies [fbb4b23] +- Updated dependencies [f3044f7] +- Updated dependencies [c8f8b10] +- Updated dependencies [ad74e98] + - @object-ui/types@18.1.0 + - @object-ui/components@18.1.0 + - @object-ui/fields@18.1.0 + - @object-ui/i18n@18.1.0 + - @object-ui/react@18.1.0 + - @object-ui/permissions@18.1.0 + - @object-ui/core@18.1.0 + - @object-ui/mobile@18.1.0 + ## 18.0.0 ### Major Changes diff --git a/packages/plugin-list/package.json b/packages/plugin-list/package.json index 07a2fd133e..51693fc344 100644 --- a/packages/plugin-list/package.json +++ b/packages/plugin-list/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/plugin-list", - "version": "18.0.0", + "version": "18.1.0", "type": "module", "license": "MIT", "description": "ListView plugin for Object UI - unified view component with view type switching", diff --git a/packages/plugin-map/CHANGELOG.md b/packages/plugin-map/CHANGELOG.md index 3799cc2680..e7f87d3170 100644 --- a/packages/plugin-map/CHANGELOG.md +++ b/packages/plugin-map/CHANGELOG.md @@ -1,5 +1,33 @@ # @object-ui/plugin-map +## 18.1.0 + +### Patch Changes + +- Updated dependencies [8556295] +- Updated dependencies [cd14d8e] +- Updated dependencies [8701f1e] +- Updated dependencies [7c405b7] +- Updated dependencies [3aafc0d] +- Updated dependencies [601c406] +- Updated dependencies [b911ebb] +- Updated dependencies [0d12e95] +- Updated dependencies [49a536d] +- Updated dependencies [8e90779] +- Updated dependencies [f1a4b08] +- Updated dependencies [7f60e9d] +- Updated dependencies [d9aff15] +- Updated dependencies [a78608f] +- Updated dependencies [1d178e0] +- Updated dependencies [6fb31dc] +- Updated dependencies [fbb4b23] +- Updated dependencies [c8f8b10] + - @object-ui/types@18.1.0 + - @object-ui/components@18.1.0 + - @object-ui/react@18.1.0 + - @object-ui/permissions@18.1.0 + - @object-ui/core@18.1.0 + ## 18.0.0 ### Major Changes diff --git a/packages/plugin-map/package.json b/packages/plugin-map/package.json index b3bffdce2c..4cfc2f29c5 100644 --- a/packages/plugin-map/package.json +++ b/packages/plugin-map/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/plugin-map", - "version": "18.0.0", + "version": "18.1.0", "type": "module", "license": "MIT", "description": "Map visualization plugin for Object UI", diff --git a/packages/plugin-markdown/CHANGELOG.md b/packages/plugin-markdown/CHANGELOG.md index 25d1140307..4f3c42487c 100644 --- a/packages/plugin-markdown/CHANGELOG.md +++ b/packages/plugin-markdown/CHANGELOG.md @@ -1,5 +1,28 @@ # @object-ui/plugin-markdown +## 18.1.0 + +### Patch Changes + +- Updated dependencies [8556295] +- Updated dependencies [cd14d8e] +- Updated dependencies [8701f1e] +- Updated dependencies [7c405b7] +- Updated dependencies [3aafc0d] +- Updated dependencies [49a536d] +- Updated dependencies [8e90779] +- Updated dependencies [f1a4b08] +- Updated dependencies [7f60e9d] +- Updated dependencies [d9aff15] +- Updated dependencies [a78608f] +- Updated dependencies [1d178e0] +- Updated dependencies [6fb31dc] +- Updated dependencies [fbb4b23] +- Updated dependencies [c8f8b10] + - @object-ui/types@18.1.0 + - @object-ui/components@18.1.0 + - @object-ui/core@18.1.0 + ## 18.0.0 ### Major Changes diff --git a/packages/plugin-markdown/package.json b/packages/plugin-markdown/package.json index 7551673d71..4ff89d17fc 100644 --- a/packages/plugin-markdown/package.json +++ b/packages/plugin-markdown/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/plugin-markdown", - "version": "18.0.0", + "version": "18.1.0", "type": "module", "license": "MIT", "description": "Markdown rendering plugin for Object UI, powered by react-markdown", diff --git a/packages/plugin-report/CHANGELOG.md b/packages/plugin-report/CHANGELOG.md index 3e14cff4cb..dc90f68ed0 100644 --- a/packages/plugin-report/CHANGELOG.md +++ b/packages/plugin-report/CHANGELOG.md @@ -1,5 +1,51 @@ # @object-ui/plugin-report +## 18.1.0 + +### Patch Changes + +- Updated dependencies [8556295] +- Updated dependencies [cd14d8e] +- Updated dependencies [8701f1e] +- Updated dependencies [5235d6d] +- Updated dependencies [8e649da] +- Updated dependencies [7c405b7] +- Updated dependencies [0093b2c] +- Updated dependencies [813c3d9] +- Updated dependencies [3aafc0d] +- Updated dependencies [601c406] +- Updated dependencies [b911ebb] +- Updated dependencies [ff77cfc] +- Updated dependencies [49a536d] +- Updated dependencies [241cb78] +- Updated dependencies [404ccae] +- Updated dependencies [ec627ab] +- Updated dependencies [0f4adc3] +- Updated dependencies [fa31856] +- Updated dependencies [8e90779] +- Updated dependencies [f1a4b08] +- Updated dependencies [7f60e9d] +- Updated dependencies [d9aff15] +- Updated dependencies [4eeb174] +- Updated dependencies [afcf654] +- Updated dependencies [2c3dc72] +- Updated dependencies [cee3bc5] +- Updated dependencies [2958f17] +- Updated dependencies [a78608f] +- Updated dependencies [1d178e0] +- Updated dependencies [2c4e5f5] +- Updated dependencies [6fb31dc] +- Updated dependencies [fbb4b23] +- Updated dependencies [f3044f7] +- Updated dependencies [c8f8b10] +- Updated dependencies [ad74e98] + - @object-ui/types@18.1.0 + - @object-ui/components@18.1.0 + - @object-ui/fields@18.1.0 + - @object-ui/i18n@18.1.0 + - @object-ui/react@18.1.0 + - @object-ui/core@18.1.0 + ## 18.0.0 ### Major Changes diff --git a/packages/plugin-report/package.json b/packages/plugin-report/package.json index 5cb7646e09..179e3d4802 100644 --- a/packages/plugin-report/package.json +++ b/packages/plugin-report/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/plugin-report", - "version": "18.0.0", + "version": "18.1.0", "type": "module", "main": "dist/index.umd.cjs", "module": "dist/index.js", diff --git a/packages/plugin-timeline/CHANGELOG.md b/packages/plugin-timeline/CHANGELOG.md index 048fc86705..bf6c981aa1 100644 --- a/packages/plugin-timeline/CHANGELOG.md +++ b/packages/plugin-timeline/CHANGELOG.md @@ -1,5 +1,49 @@ # @object-ui/plugin-timeline +## 18.1.0 + +### Patch Changes + +- Updated dependencies [8556295] +- Updated dependencies [cd14d8e] +- Updated dependencies [8701f1e] +- Updated dependencies [5235d6d] +- Updated dependencies [7c405b7] +- Updated dependencies [0093b2c] +- Updated dependencies [3aafc0d] +- Updated dependencies [601c406] +- Updated dependencies [b911ebb] +- Updated dependencies [0d12e95] +- Updated dependencies [ff77cfc] +- Updated dependencies [49a536d] +- Updated dependencies [241cb78] +- Updated dependencies [404ccae] +- Updated dependencies [ec627ab] +- Updated dependencies [0f4adc3] +- Updated dependencies [fa31856] +- Updated dependencies [8e90779] +- Updated dependencies [f1a4b08] +- Updated dependencies [7f60e9d] +- Updated dependencies [d9aff15] +- Updated dependencies [4eeb174] +- Updated dependencies [afcf654] +- Updated dependencies [2c3dc72] +- Updated dependencies [2958f17] +- Updated dependencies [a78608f] +- Updated dependencies [1d178e0] +- Updated dependencies [2c4e5f5] +- Updated dependencies [6fb31dc] +- Updated dependencies [fbb4b23] +- Updated dependencies [c8f8b10] +- Updated dependencies [ad74e98] + - @object-ui/types@18.1.0 + - @object-ui/components@18.1.0 + - @object-ui/i18n@18.1.0 + - @object-ui/react@18.1.0 + - @object-ui/permissions@18.1.0 + - @object-ui/core@18.1.0 + - @object-ui/mobile@18.1.0 + ## 18.0.0 ### Major Changes diff --git a/packages/plugin-timeline/package.json b/packages/plugin-timeline/package.json index b62f4ab588..2e1dd69d7c 100644 --- a/packages/plugin-timeline/package.json +++ b/packages/plugin-timeline/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/plugin-timeline", - "version": "18.0.0", + "version": "18.1.0", "type": "module", "license": "MIT", "description": "Timeline component plugin for Object UI", diff --git a/packages/plugin-tree/CHANGELOG.md b/packages/plugin-tree/CHANGELOG.md index be3337e6be..b1bfb9c47b 100644 --- a/packages/plugin-tree/CHANGELOG.md +++ b/packages/plugin-tree/CHANGELOG.md @@ -1,5 +1,56 @@ # @object-ui/plugin-tree +## 18.1.0 + +### Patch Changes + +- Updated dependencies [8556295] +- Updated dependencies [cd14d8e] +- Updated dependencies [8701f1e] +- Updated dependencies [5235d6d] +- Updated dependencies [8e649da] +- Updated dependencies [7c405b7] +- Updated dependencies [0093b2c] +- Updated dependencies [f669732] +- Updated dependencies [813c3d9] +- Updated dependencies [3aafc0d] +- Updated dependencies [601c406] +- Updated dependencies [b911ebb] +- Updated dependencies [0d12e95] +- Updated dependencies [ff77cfc] +- Updated dependencies [49a536d] +- Updated dependencies [241cb78] +- Updated dependencies [404ccae] +- Updated dependencies [ec627ab] +- Updated dependencies [b93c9f6] +- Updated dependencies [0f4adc3] +- Updated dependencies [fa31856] +- Updated dependencies [8e90779] +- Updated dependencies [f1a4b08] +- Updated dependencies [7f60e9d] +- Updated dependencies [d9aff15] +- Updated dependencies [4eeb174] +- Updated dependencies [afcf654] +- Updated dependencies [2c3dc72] +- Updated dependencies [cee3bc5] +- Updated dependencies [2958f17] +- Updated dependencies [a78608f] +- Updated dependencies [1d178e0] +- Updated dependencies [2c4e5f5] +- Updated dependencies [6fb31dc] +- Updated dependencies [fbb4b23] +- Updated dependencies [f3044f7] +- Updated dependencies [c8f8b10] +- Updated dependencies [ad74e98] + - @object-ui/types@18.1.0 + - @object-ui/components@18.1.0 + - @object-ui/fields@18.1.0 + - @object-ui/i18n@18.1.0 + - @object-ui/plugin-detail@18.1.0 + - @object-ui/react@18.1.0 + - @object-ui/permissions@18.1.0 + - @object-ui/core@18.1.0 + ## 18.0.0 ### Major Changes diff --git a/packages/plugin-tree/package.json b/packages/plugin-tree/package.json index 52376347bd..eed5b095a2 100644 --- a/packages/plugin-tree/package.json +++ b/packages/plugin-tree/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/plugin-tree", - "version": "18.0.0", + "version": "18.1.0", "type": "module", "license": "MIT", "description": "Tree / tree-grid visualization plugin for Object UI", diff --git a/packages/plugin-view/CHANGELOG.md b/packages/plugin-view/CHANGELOG.md index ff2fcfb4eb..fa04f9e67b 100644 --- a/packages/plugin-view/CHANGELOG.md +++ b/packages/plugin-view/CHANGELOG.md @@ -1,5 +1,53 @@ # @object-ui/plugin-view +## 18.1.0 + +### Patch Changes + +- Updated dependencies [8556295] +- Updated dependencies [cd14d8e] +- Updated dependencies [8701f1e] +- Updated dependencies [5235d6d] +- Updated dependencies [7c405b7] +- Updated dependencies [0093b2c] +- Updated dependencies [3aafc0d] +- Updated dependencies [601c406] +- Updated dependencies [56cf4d8] +- Updated dependencies [b911ebb] +- Updated dependencies [0d12e95] +- Updated dependencies [ff77cfc] +- Updated dependencies [49a536d] +- Updated dependencies [241cb78] +- Updated dependencies [404ccae] +- Updated dependencies [ec627ab] +- Updated dependencies [b93c9f6] +- Updated dependencies [d019aaa] +- Updated dependencies [0f4adc3] +- Updated dependencies [fa31856] +- Updated dependencies [8e90779] +- Updated dependencies [f1a4b08] +- Updated dependencies [7f60e9d] +- Updated dependencies [d9aff15] +- Updated dependencies [4eeb174] +- Updated dependencies [afcf654] +- Updated dependencies [2c3dc72] +- Updated dependencies [2958f17] +- Updated dependencies [a78608f] +- Updated dependencies [1d178e0] +- Updated dependencies [2c4e5f5] +- Updated dependencies [6fb31dc] +- Updated dependencies [fbb4b23] +- Updated dependencies [c8f8b10] +- Updated dependencies [ad74e98] + - @object-ui/types@18.1.0 + - @object-ui/plugin-grid@18.1.0 + - @object-ui/components@18.1.0 + - @object-ui/i18n@18.1.0 + - @object-ui/react@18.1.0 + - @object-ui/permissions@18.1.0 + - @object-ui/core@18.1.0 + - @object-ui/plugin-form@18.1.0 + ## 18.0.0 ### Major Changes diff --git a/packages/plugin-view/package.json b/packages/plugin-view/package.json index a69a7a83d9..2a7e30b143 100644 --- a/packages/plugin-view/package.json +++ b/packages/plugin-view/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/plugin-view", - "version": "18.0.0", + "version": "18.1.0", "type": "module", "license": "MIT", "description": "Object View plugin for Object UI", diff --git a/packages/providers/CHANGELOG.md b/packages/providers/CHANGELOG.md index 6bac2b0277..c2f70938f1 100644 --- a/packages/providers/CHANGELOG.md +++ b/packages/providers/CHANGELOG.md @@ -1,5 +1,16 @@ # @object-ui/providers — Changelog +## 18.1.0 + +### Patch Changes + +- Updated dependencies [8556295] +- Updated dependencies [cd14d8e] +- Updated dependencies [f1a4b08] +- Updated dependencies [1d178e0] +- Updated dependencies [6fb31dc] + - @object-ui/types@18.1.0 + ## 18.0.0 ### Major Changes diff --git a/packages/providers/package.json b/packages/providers/package.json index 0c1b278382..4e061c9b6c 100644 --- a/packages/providers/package.json +++ b/packages/providers/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/providers", - "version": "18.0.0", + "version": "18.1.0", "type": "module", "license": "MIT", "description": "Reusable context providers for ObjectUI applications", diff --git a/packages/react-runtime/CHANGELOG.md b/packages/react-runtime/CHANGELOG.md index 018e3f7e71..04616a7e4f 100644 --- a/packages/react-runtime/CHANGELOG.md +++ b/packages/react-runtime/CHANGELOG.md @@ -1,5 +1,7 @@ # @object-ui/react-runtime +## 18.1.0 + ## 18.0.0 ### Major Changes diff --git a/packages/react-runtime/package.json b/packages/react-runtime/package.json index b384e111f9..893e750815 100644 --- a/packages/react-runtime/package.json +++ b/packages/react-runtime/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/react-runtime", - "version": "18.0.0", + "version": "18.1.0", "type": "module", "sideEffects": false, "license": "MIT", diff --git a/packages/react/CHANGELOG.md b/packages/react/CHANGELOG.md index c5a6311c03..4416c338de 100644 --- a/packages/react/CHANGELOG.md +++ b/packages/react/CHANGELOG.md @@ -1,5 +1,64 @@ # @object-ui/react +## 18.1.0 + +### Minor Changes + +- b911ebb: A navigation entry's API `dataSource` and a page element bound to the same read now make one request per console open (objectui#13323). Before, `readElementApi` shared a request only while it was in flight, so when the sidebar's read for an entry's `visible` had settled before the page element mounted, the element sent a second `GET` for an answer the console already held. + + `@object-ui/react` exports `ElementApiOpenScope` (with `useElementApiOpen` and the `ElementApiOpen` type): inside it, a read that has already answered under the same `open` name is answered again with no request. A failed read is not kept, a read under another `open` asks again, and any `notifyDataChanged` drops what the open kept. `readElementApi` takes the open as an optional third argument; without one it behaves as before. + + `@object-ui/app-shell`'s `ConnectedShell` mounts the scope and names one open per visit of a history entry: following a link or a navigation entry, and Back or Forward, start a new open and read again, even on an entry visited before; a redirect that replaces the address (the app root's landing on its first entry) stays in the open. A language switch starts over. No read happens at a different time than before; only whether a second read in one open reaches the network changes. +- d9aff15: A record page inside the Setup app no longer draws the floating managed-by badge (the amber "Identity" chip at the top-right of an organization, team, business unit or user record) (objectui#13385). The header's object label ("Organization") carries the badge's note instead: hovering or focusing it shows "Organization · Managed by the identity provider", and the note is the label's accessible description. The note is the badge's own tooltip title, under the same gate: only a caller who can author metadata sees it, and a `platform` object shows none. Every record page outside Setup, a `sys_*` object opened in another app included, and every list header keep the badge unchanged. + + `RecordContextValue` (`@object-ui/react`) gains an optional, host-injected `objectLabelNote`, which `page:header` forwards to `RecordTitleChip`. `RecordTitleChip` (`@object-ui/components`) gains an optional `objectLabelNote` prop: with it the object label becomes a focusable tooltip trigger described by the note; without it the label draws exactly as before. + +### Patch Changes + +- 3aafc0d: A page node whose declared `visibleWhen` / `visible` / `visibleOn` predicate cannot be evaluated (over the CEL bounds, a type error, an unbound root, a missing function) is no longer rendered: page visibility gates now fail closed, as a `page:tabs` item already did. The fault is still reported once, and the console line says the node was withheld. A blank gate still means "no gate", and a predicate that evaluates decides as before. A `page:tabs` badge no longer counts a related list withheld this way. Form field rules keep their fail-open (objectui#13299). +- 601c406: The console line for a visibility predicate that cannot be evaluated, on a gate that withholds what it gates, no longer says "a navigation entry" was withheld. The same line is printed for a navigation entry, a `page:tabs` item and a page node, so it now says "an element whose visibility predicate cannot be evaluated is WITHHELD". The verdict, the line's opening, and when it is printed are unchanged (objectui#13303). +- 8e90779: An action's `confirmText`, `successMessage` and `errorMessage` read the `template` envelope and fill `{{ }}` holes (objectui#13367). + + `@objectstack/spec` is making these three keys `template` slots (objectstack#24814), so a parsed action serves `{ dialect: 'template', source }` where it served a string. Before this change the success toast skipped the envelope and showed the default text, and the error toast showed the generic failure. `ActionRunner` now reads a string or the envelope for all three, and fills `{{ path }}` / `{{ path | formatter }}` holes with `@objectstack/formula`'s `templateEngine`, the engine the flow notifications render with: + + - `confirmText`: `record` (the record the action runs against, the clicked row on a list) and `params` (the action's static params); + - `successMessage`: `result` (the payload `${result.*}` reads) and `record`; + - `errorMessage`: no hole is filled; the text shows as written. + + A sentence with no `{{ }}` hole keeps today's `${…}` reading, so the platform's own `${result.email}`-style success sentences still work until the spec converts them. A sentence is read in one dialect only: a value filled into a `{{ }}` hole is never read again as `${…}`. An envelope with no text never reaches the dialog or a toast as an object; a `confirmText` envelope with no text still asks for confirmation. + + `useActionTextLocalizer` keeps the envelope: it used to read it as a per-locale map and hand the runner the word `template`. A bundle entry replaces the envelope's `source`. On a flow action the console reads the envelope too, so the action's own success copy still outranks the flow's (`flowSuccessCopy`). `@object-ui/core` exports the reader it uses: `ActionCopyTemplate`, `isActionCopyEnvelope`, `actionCopySource`, `hasTemplateHoles` and `fillTemplateHoles`. + + Clause-②: yes + Metadata-protocol: none +- Updated dependencies [8556295] +- Updated dependencies [cd14d8e] +- Updated dependencies [5235d6d] +- Updated dependencies [0093b2c] +- Updated dependencies [ff77cfc] +- Updated dependencies [49a536d] +- Updated dependencies [241cb78] +- Updated dependencies [404ccae] +- Updated dependencies [ec627ab] +- Updated dependencies [0f4adc3] +- Updated dependencies [fa31856] +- Updated dependencies [8e90779] +- Updated dependencies [f1a4b08] +- Updated dependencies [7f60e9d] +- Updated dependencies [4eeb174] +- Updated dependencies [afcf654] +- Updated dependencies [2c3dc72] +- Updated dependencies [2958f17] +- Updated dependencies [1d178e0] +- Updated dependencies [a14737b] +- Updated dependencies [2c4e5f5] +- Updated dependencies [6fb31dc] +- Updated dependencies [ad74e98] + - @object-ui/types@18.1.0 + - @object-ui/i18n@18.1.0 + - @object-ui/core@18.1.0 + - @object-ui/data-objectstack@18.1.0 + ## 18.0.0 ### Major Changes diff --git a/packages/react/package.json b/packages/react/package.json index f5b3dc3c1f..728eca422f 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/react", - "version": "18.0.0", + "version": "18.1.0", "type": "module", "license": "MIT", "description": "React bindings and SchemaRenderer component for Object UI", diff --git a/packages/runner/CHANGELOG.md b/packages/runner/CHANGELOG.md index bbb6814aca..1275a38800 100644 --- a/packages/runner/CHANGELOG.md +++ b/packages/runner/CHANGELOG.md @@ -1,5 +1,37 @@ # @object-ui/runner +## 18.1.0 + +### Patch Changes + +- Updated dependencies [8556295] +- Updated dependencies [cd14d8e] +- Updated dependencies [8701f1e] +- Updated dependencies [7c405b7] +- Updated dependencies [3aafc0d] +- Updated dependencies [601c406] +- Updated dependencies [b911ebb] +- Updated dependencies [49a536d] +- Updated dependencies [8e90779] +- Updated dependencies [f1a4b08] +- Updated dependencies [7f60e9d] +- Updated dependencies [d9aff15] +- Updated dependencies [eadceab] +- Updated dependencies [b317942] +- Updated dependencies [2c3dc72] +- Updated dependencies [a78608f] +- Updated dependencies [56b65c0] +- Updated dependencies [1d178e0] +- Updated dependencies [6fb31dc] +- Updated dependencies [fbb4b23] +- Updated dependencies [c8f8b10] + - @object-ui/types@18.1.0 + - @object-ui/components@18.1.0 + - @object-ui/react@18.1.0 + - @object-ui/core@18.1.0 + - @object-ui/plugin-charts@18.1.0 + - @object-ui/plugin-kanban@18.1.0 + ## 18.0.0 ### Major Changes diff --git a/packages/runner/package.json b/packages/runner/package.json index 7b65a57474..e651e262ba 100644 --- a/packages/runner/package.json +++ b/packages/runner/package.json @@ -1,7 +1,7 @@ { "name": "@object-ui/runner", "private": false, - "version": "18.0.0", + "version": "18.1.0", "description": "Universal Object UI Application Runner", "type": "module", "homepage": "https://www.objectui.org/docs/utilities/runner", diff --git a/packages/sdui-parser/CHANGELOG.md b/packages/sdui-parser/CHANGELOG.md index 2a6ccf36c9..b984bfe557 100644 --- a/packages/sdui-parser/CHANGELOG.md +++ b/packages/sdui-parser/CHANGELOG.md @@ -1,5 +1,7 @@ # @object-ui/sdui-parser +## 18.1.0 + ## 18.0.0 ### Major Changes diff --git a/packages/sdui-parser/package.json b/packages/sdui-parser/package.json index 8567351ce3..b302b8538b 100644 --- a/packages/sdui-parser/package.json +++ b/packages/sdui-parser/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/sdui-parser", - "version": "18.0.0", + "version": "18.1.0", "type": "module", "sideEffects": false, "license": "MIT", diff --git a/packages/types/CHANGELOG.md b/packages/types/CHANGELOG.md index da479fa076..fada6261be 100644 --- a/packages/types/CHANGELOG.md +++ b/packages/types/CHANGELOG.md @@ -1,5 +1,30 @@ # @object-ui/types +## 18.1.0 + +### Minor Changes + +- 8556295: `NavigationItemSchema` now refuses a navigation entry whose `visible` reads `data` but which declares no `dataSource`, as `@objectstack/spec`'s `NavigationItemSchema` already does (objectui#13076). The rule is the spec's own exported `navItemVisibleDataNeedsDataSource`, chained on every navigation arm (the flat arm and the `doc` arm), not restated, so `objectui validate` and the platform's save door refuse the same entry with the same issue at `visible`. + + This narrows the published validator toward the spec: an entry such as `{ id: 'nav_envs', type: 'object', objectName: 'sys_environment', visible: 'data.total == 1' }` validated clean here and failed at publish; it is now refused here too. Declare the `dataSource` whose bound value `visible` reads, or gate on `current_user` or `features` instead. An entry with a `dataSource`, or whose `visible` is a boolean, absent, or reads no `data`, is unaffected. +- f1a4b08: Grids: hovering a `lookup` or `master_detail` cell no longer shows the referenced record's raw id (objectui#13377). + + The table's cell wrapper set its `title` tooltip to the cell's raw value, and for a reference column that value is the related record's id. So hovering beside the drawn name, or beside "Restricted record" for a record the viewer cannot read, still showed the id. + + - **`@object-ui/types`:** `TableColumn` gains an optional `foreignKey` boolean: the column's raw value is the id of a referenced record. The zod mirror (`TableColumnSchema`) keeps it, and the static `table` column refuses it by name, like `masked` and `chips`. + - **`@object-ui/components`:** a `data-table` column with `foreignKey: true` draws no `title` tooltip. Nothing else changes for it: copy, CSV export, inline edit, search and sort behave as before. + - **`@object-ui/plugin-grid`:** `ObjectGrid` sets `foreignKey` on every `lookup`, `master_detail`, `tree` and `user` column, read from the column's own type or the object's field type. Every other column keeps its tooltip. + +### Patch Changes + +- cd14d8e: The bulk action confirm step reads `confirmText` as a string or as a `{ dialect: 'template', source }` envelope (objectui#13183). + + `@objectstack/spec` is making a bulk action's `confirmText` a `template` slot (objectstack#24947), so a parsed bulk definition serves the envelope where it served a string. The confirm step rendered `confirmText` as it came, so an envelope would have broken it. It now shows the string, or the envelope's `source` as written; a blank or absent value still shows the default sentence ("This will apply to N record(s)."). `{{ }}` holes are not filled yet: `{{ count }}` still shows as written. `BulkActionDef.confirmText` in `@object-ui/types` is typed `string | { dialect?: 'template'; source: string }`, and `@object-ui/plugin-grid` reads it through one helper, `bulkConfirmTextSource`. +- 1d178e0: types: a node derived from an `@objectstack/spec` schema keeps the spec's `credential` registry key (`'value' | 'map'`, objectstack#25036, which marks the webhook's `secret` and `headers` as credential fields). `credential` joins `CARRIED_REGISTRY_META_KEYS`, so the derivation no longer drops it. The pin move to objectstack 830a63a6 put the key on the published surface, and the registry census (objectui#9102) reported it as unclassified. +- 6fb31dc: `BulkActionDef.confirmText`'s template envelope types `source` as optional, as `@objectstack/spec`'s `Expression` does, and so does its zod twin (objectstack#25438). + + `@objectstack/spec` made a bulk action's `confirmText` a `template` slot (objectstack#24947), and its envelope carries `source` or `ast`. With `source` typed as required, `@object-ui/plugin-view` refused the spec's own bulk action type when it handed a named view's `bulkActionDefs` to the grid, so the console no longer built against the current spec. The confirm step is unchanged: an envelope with no `source` shows the default sentence ("This will apply to N record(s)."). + ## 18.0.0 ### Major Changes diff --git a/packages/types/package.json b/packages/types/package.json index 6bd8442f40..fffdf7e1f5 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/types", - "version": "18.0.0", + "version": "18.1.0", "description": "Pure TypeScript type definitions for Object UI - The Protocol Layer", "type": "module", "sideEffects": false, diff --git a/packages/vscode-extension/CHANGELOG.md b/packages/vscode-extension/CHANGELOG.md index 11d9fe1113..c378f4820d 100644 --- a/packages/vscode-extension/CHANGELOG.md +++ b/packages/vscode-extension/CHANGELOG.md @@ -1,5 +1,20 @@ # Changelog +## 18.1.0 + +### Patch Changes + +- Updated dependencies [8556295] +- Updated dependencies [cd14d8e] +- Updated dependencies [49a536d] +- Updated dependencies [8e90779] +- Updated dependencies [f1a4b08] +- Updated dependencies [7f60e9d] +- Updated dependencies [1d178e0] +- Updated dependencies [6fb31dc] + - @object-ui/types@18.1.0 + - @object-ui/core@18.1.0 + ## 18.0.0 ### Major Changes diff --git a/packages/vscode-extension/package.json b/packages/vscode-extension/package.json index 6009c85b22..a3a6dd79c0 100644 --- a/packages/vscode-extension/package.json +++ b/packages/vscode-extension/package.json @@ -2,7 +2,7 @@ "name": "object-ui", "displayName": "Object UI", "description": "VSCode extension for Object UI - Schema-driven UI development with IntelliSense, validation, and live preview", - "version": "18.0.0", + "version": "18.1.0", "publisher": "objectui", "private": true, "icon": "icon.svg",