@cosmicdrift/kumiko-samples 0.402.0 → 0.403.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosmicdrift/kumiko-samples",
3
- "version": "0.402.0",
3
+ "version": "0.403.0",
4
4
  "description": "Source trees of the Kumiko sample recipes, sample apps and bundled features in repo layout, for tooling such as few-shot corpus builds.",
5
5
  "license": "MIT",
6
6
  "author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosmicdrift/kumiko-bundled-features",
3
- "version": "0.402.0",
3
+ "version": "0.403.0",
4
4
  "description": "Built-in features — tenant, user, auth, delivery. The stuff you'd rewrite anyway, already typed.",
5
5
  "license": "MIT",
6
6
  "author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
@@ -28,6 +28,11 @@ query and the fields to read, the query does the counting.
28
28
  - **Fallback by reason**: `fallback: { forbidden, notFound }` renders a screen on
29
29
  403/404 of the gate query; other reasons get the default notice or an error
30
30
  banner with retry.
31
+ - **Named filter shared by tile and list**: the entity declares `namedFilters`,
32
+ the `ticket-queue` entityList lists the id in `namedFilters`, and the
33
+ `open-work` stat counts through the list's own query with `params.namedFilter`
34
+ and `navigate`. A click opens the queue filtered by the same rule, so tile and
35
+ list cannot drift.
31
36
 
32
37
  ## When to reach for it
33
38
 
@@ -21,10 +21,15 @@ export const ticketEntity = createEntity({
21
21
  title: createTextField({ personal: false, reason: "is_business_data", required: true }),
22
22
  status: createSelectField({ options: TICKET_STATUSES, default: "open", required: true }),
23
23
  },
24
+ // Defined once: the queue list and the dashboard tile both read it.
25
+ namedFilters: {
26
+ "open-work": { filters: () => [{ field: "status", op: "eq", value: "open" }] },
27
+ },
24
28
  });
25
29
 
26
30
  export const TICKET_STATS_QUERY = "tickets:query:ticket:stats";
27
31
  export const TICKET_CAPABILITIES_QUERY = "tickets:query:ticket:capabilities";
32
+ export const TICKET_LIST_QUERY = "tickets:query:ticket:list";
28
33
 
29
34
  const readerRoles = { roles: ["Admin", "User"] } as const;
30
35
 
@@ -109,6 +114,9 @@ export const ticketFeature = defineFeature("tickets", (r) => {
109
114
  "tickets.dashboard.open": { en: "Open" },
110
115
  "tickets.dashboard.closed": { en: "Closed" },
111
116
  "tickets.dashboard.total": { en: "All tickets" },
117
+ "tickets.dashboard.open-work": { en: "Open work" },
118
+ "tickets.filter.open-work": { en: "Open work" },
119
+ "screen:ticket-queue.title": { en: "Ticket queue" },
112
120
  },
113
121
  });
114
122
 
@@ -144,6 +152,16 @@ export const ticketFeature = defineFeature("tickets", (r) => {
144
152
  query: TICKET_STATS_QUERY,
145
153
  valueField: "total",
146
154
  },
155
+ // Counts through the list's own query with the same named filter, then links to that list.
156
+ {
157
+ kind: "stat",
158
+ id: "open-work",
159
+ label: "tickets.dashboard.open-work",
160
+ query: TICKET_LIST_QUERY,
161
+ valueField: "total",
162
+ params: { namedFilter: "open-work", limit: 1, totalCount: true },
163
+ navigate: { screen: "ticket-queue", namedFilter: "open-work" },
164
+ },
147
165
  ],
148
166
  access: readerRoles,
149
167
  });
@@ -152,6 +170,15 @@ export const ticketFeature = defineFeature("tickets", (r) => {
152
170
  // button, and a fallback chosen by reason.
153
171
  const gate = { query: TICKET_CAPABILITIES_QUERY, field: "canClose", eq: true } as const;
154
172
 
173
+ r.screen({
174
+ id: "ticket-queue",
175
+ type: "entityList",
176
+ entity: "ticket",
177
+ columns: ["title", "status"],
178
+ namedFilters: [{ id: "open-work", label: "tickets.filter.open-work" }],
179
+ access: readerRoles,
180
+ });
181
+
155
182
  // The list doubles as the fallback target: it has no visibleWhen of its own.
156
183
  r.screen({
157
184
  id: "ticket-list",