diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 347dc2b..1ca9fd7 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -6,7 +6,7 @@ }, "metadata": { "description": "Claude skills for Dynamicweb 10 — organized by task domain, bundled by role.", - "version": "5.8.8" + "version": "5.8.9" }, "plugins": [ { diff --git a/CHANGELOG.md b/CHANGELOG.md index 40cc7aa..fc7f677 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,20 @@ All notable changes to the Dynamicweb Skills plugin are recorded here. The `version` field in `.claude-plugin/marketplace.json` tracks these entries. +## [5.8.9] + +- **`dw-demo-pim` `screen-authoring.md`: one layout, one tab per product type.** A tab whose editors the + product lacks is not rendered, so one `ProductEditScreen` layout with a tab per category shows each + product type its own tab. Unplaced editors go to the `IsCatchAll` group and vanish silently without one; + group names must be unique across the layout. Saves renumber `Order`, `ScreenLayoutDelete` cascades, + writes apply on the next load. +- **`dw-demo-pim` `screen-authoring.md`: query list presets render headers but blank cells.** Row data comes + from the user's own default `ProductListScreen` preset, not the query's `ListScreenViewPresetId`; give each + worklist user a default list preset covering every query column (platform defect, DW 10.29.6). +- **Translation worklist that opens side by side.** Query edit-screen languages plus *Open product in edit + mode* open Multi Edit; the hidden `ProductQueryListWidget` is added by system name and has product-aware + rows. Recipe in `dw-demo-pim` `localization.md`, widget row in `dw-pim-completeness` `rules-and-dashboards.md`. + ## [5.8.8] - **`dw-pim-completeness`: per-language completeness works with the "Completeness feature" flag on.** diff --git a/manifest.json b/manifest.json index 98344e5..08e09fc 100644 --- a/manifest.json +++ b/manifest.json @@ -1,6 +1,6 @@ { "version": 2, - "generatedAt": "2026-10-07T10:22:42.391Z", + "generatedAt": "2026-10-07T10:25:34.190Z", "worksOn": { "dw": { "ring": "R1", diff --git a/skills/dw-demo-pim/references/localization.md b/skills/dw-demo-pim/references/localization.md index 5635e3f..376fcbc 100644 --- a/skills/dw-demo-pim/references/localization.md +++ b/skills/dw-demo-pim/references/localization.md @@ -31,6 +31,29 @@ The demo deltas on top of that sequence: 3. **Translate the hero products' name + short description.** Skip custom-field translation in a first pass; the fallback handles it. 4. This recipe fits between **Step 3 (languages)** and **Step 4 (manufacturers)** of [`canonical-setup-order.md`](canonical-setup-order.md); the first `EcomLanguage` row is set up there, additional languages follow this doc. +## Translation worklist that opens side by side + +A translation dashboard whose rows open the product in the side-by-side language view is native, and +no widget setting carries it: the query does [dw 10.29.6]. + +1. **The query**: a translation-gap predicate (with the Completeness feature flag on, a per-language + `CompletionRule| < 100` query; see + [`../../dw-pim-localization/SKILL.md`](../../dw-pim-localization/SKILL.md) "Per-language completeness"), + *Edit screen languages* set to every language to compare (MCP `editScreenLanguageIds`), an edit preset + (`editScreenViewPresetId`), and *Open product in edit mode* on. +2. When those languages resolve to more than one language the product has, a row click opens + `/Admin/UI/Products/MultiEdit?...&Type=MultiEditByQuery` with the languages side by side and the edit + preset applied. Any product-aware row inherits this from the query. +3. **The widget**: `Dynamicweb.Products.UI.Dashboard.Widgets.ProductQueryListWidget` renders the query's + rows as product list rows, so a click opens Multi Edit. It is `[AddInActive(false)]` and absent from + the Add widget picker, but `add_widgets_to_dashboards` with that system name (parameters `Query`, + `TitleField`, `HintField`, `RightField`) adds it and it renders. It cannot be re-added from the picker + once removed. `RepositoryGridWidget` rows are not product-aware and open the plain editor. A + `RepositoryCountWidget` tile opens the query list, whose rows then open Multi Edit. + +Validate by clicking a widget row: the URL is `MultiEdit` with one model identifier per configured +language. + ## Demo philosophy PIM localization sells the "single product master, multiple market storefronts" story — high-leverage. But: diff --git a/skills/dw-demo-pim/references/screen-authoring.md b/skills/dw-demo-pim/references/screen-authoring.md index 4670013..6520fd6 100644 --- a/skills/dw-demo-pim/references/screen-authoring.md +++ b/skills/dw-demo-pim/references/screen-authoring.md @@ -5,7 +5,9 @@ - [The entity chain](#the-entity-chain) - [`ScreenType` is a fully-qualified .NET type name](#screentype-is-a-fully-qualified-net-type-name) - [Three column grammars, and only the platform picker lists them](#three-column-grammars-and-only-the-platform-picker-lists-them) +- [One layout, one tab per product type, and the catch-all group](#one-layout-one-tab-per-product-type-and-the-catch-all-group) - [Screen presets: create, audience, default](#screen-presets-create-audience-default) +- [Query list presets: headers render, cells come from the user's default](#query-list-presets-headers-render-cells-come-from-the-users-default) - ["No tab strip" has two causes and one discriminator](#no-tab-strip-has-two-causes-and-one-discriminator) - [Grid edit and Bulk update have no Management API surface](#grid-edit-and-bulk-update-have-no-management-api-surface) - [Bulk update writes an EMPTY value when the dual list is untouched](#bulk-update-writes-an-empty-value-when-the-dual-list-is-untouched) @@ -70,7 +72,9 @@ tab from the strip** with no error, no log line and no clue: 4 of 5 configured t missing tab's 3 groups and 30 editors are all correct in the database, and deleting, recreating, recycling and renaming all change nothing. Tabs that mix in at least one bare product property survive and mask the problem. Diagnostic: **if a whole tab is missing from the strip while its rows -are correct, its editors are all unresolvable. Check the `CategoryFields|` prefix first.** +are correct, its editors are all unresolvable. Check the `CategoryFields|` prefix first.** The same rule drops a tab whose +correctly named editors the product simply does not carry, which is what makes per-product-type tabs +work (next section). `ScreenPresetSave` has the same hole: it accepts any string in `ConfigurableColumns` and answers `status: ok`, so a wrong column name is indistinguishable from a right one until the grid renders @@ -93,6 +97,26 @@ the worklist grid rendering the named headers. **Local installs only** for the `SELECT`: on a hosted install, the rendered worklist grid is the check. +## One layout, one tab per product type, and the catch-all group + +`ScreenLayout` exists once per screen type, not per data model, yet one layout can still show each +product type its own editor [dw 10.29.6]. The edit screen builds every tab and group of the layout and +then places only the editors the product renders; a tab left with no editors is not rendered. So: + +1. One `ProductEditScreen` layout, with **one tab per category**, its editors named + `CategoryFields|ProductCategory||`. A product shows the general tabs plus its own + category's tab; a variant shows only the tabs that hold variant-level fields. +2. **Always one group flagged `IsCatchAll`.** Editors not placed in any group land there. **With no + catch-all group they are dropped from the editor silently**: price, stock and SEO vanish. +3. **Group names unique across the whole layout.** Groups are identified by name (`screenType|tab|group`) + and the catch-all is found by group name across every tab. +4. Narrow further per worklist with an edit preset on the query; the preset filters the layout's editors + (see "No tab strip" below). + +Tab, group and editor saves renumber `Order` from 1, so read the order back rather than writing gaps. +`ScreenLayoutDelete` cascades to tabs, groups and editors. Layout writes apply on the next screen load, +without a recycle. + ## Screen presets: create, audience, default **Sweep `ScreenPresetAccessUserRelation` before creating the first preset.** `ScreenPresetDelete` does @@ -118,6 +142,21 @@ screen type's default untouched, and it leaves `ScreenPresetAccessUserRelation` (the preset stays granted to the user). `ScreenPresetDelete` is not the alternative: it removes the preset for everyone. +## Query list presets: headers render, cells come from the user's default + +**A query's list preset renders its column headers, but the row cells come from the signed-in user's +own `ProductListScreen` preset** [dw 10.29.6]. The query's `ListScreenViewPresetId` (set by +`create_or_update_product_queries` or in Manage query) sets the headers. The row data is mapped earlier +by `MappingContextHelper.GetMappingContextForScreen`, which reads only the user's temporary or default +list preset (`GetUserSpecifiedOrDefault`) and ignores the query's. Every cell outside that preset is +blank: a nine-column worklist preset showed values only for Name, Number and Completeness, with workflow +state, manufacturer, translated names and every category column empty. This is a platform defect. + +**Workaround: give each worklist user a default list preset that covers every column the query presets +use**, with `ScreenPresetSetAsDefault` on `ProductListScreen`. One `CustomFields|` column maps all custom +fields, but each `CategoryFields|` column must be listed on its own. Side effect: "All products" shows +that preset for the user. Read the result on a rendered worklist row, not on the headers. + ## "No tab strip" has two causes and one discriminator A product editor rendering two unlabelled cards (Identity, Classification) and **no tab strip** is diff --git a/skills/dw-pim-completeness/references/rules-and-dashboards.md b/skills/dw-pim-completeness/references/rules-and-dashboards.md index 933acd4..838eb6f 100644 --- a/skills/dw-pim-completeness/references/rules-and-dashboards.md +++ b/skills/dw-pim-completeness/references/rules-and-dashboards.md @@ -212,6 +212,7 @@ A PIM governance dashboard lives or dies on the "click the count, land on the of | `Dynamicweb.Application.UI.Dashboard.Widgets.RepositoryCountWidget` | **Yes** — clicking the count opens the filtered product list from the backing query | Per-rule / per-blocker counts | | `Dynamicweb.Application.UI.Dashboard.Widgets.RepositoryGridWidget` | **Yes** — each row links to the product | "Offender list" surface — show the exact SKUs that are failing | | `Dynamicweb.Application.UI.Dashboard.Widgets.RepositoryListWidget` | **Yes** | Title / hint pairs from a query | +| `Dynamicweb.Products.UI.Dashboard.Widgets.ProductQueryListWidget` | **Yes, product-aware**: a row click honours the query's edit languages and edit preset, so it can open the side-by-side Multi Edit view | Translation worklists. Hidden from the Add widget picker (`[AddInActive(false)]`); add it with `add_widgets_to_dashboards` by system name, parameters `Query`, `TitleField`, `HintField`, `RightField` [dw 10.29.6]. `RepositoryGridWidget` rows are not product-aware | | `Dynamicweb.Application.UI.Dashboard.Widgets.RepositoryFacetWidget` | **Yes** — facet filters are clickable | Catalog-by-category breakdowns | | `Dynamicweb.Products.UI.Dashboard.Widgets.LastChangedProductsWidget` | **Yes** | Recent edits | | `Dynamicweb.Insights.UI.Dashboard.Widgets.ScalarSqlCountWidget` | **NO — dead end** | Avoid for governance dashboards. It renders a bare number with NO drill-through. Only use when there's no queryable surrogate (e.g. counting rows in a non-product table). |