@sanity/ailf-studio 0.1.0 → 0.1.2
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/README.md +43 -6
- package/dist/index.d.ts +12 -7
- package/dist/index.js +1180 -673
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -18,9 +18,8 @@ var GraduateToNativeAction = (props) => {
|
|
|
18
18
|
const [isConfirming, setIsConfirming] = useState(false);
|
|
19
19
|
const doc = draft ?? published;
|
|
20
20
|
const origin = doc?.origin;
|
|
21
|
-
|
|
22
|
-
const
|
|
23
|
-
const repoUrl = origin.repo && origin.path && origin.branch ? `https://github.com/${origin.repo}/blob/${origin.branch}/${origin.path}` : null;
|
|
21
|
+
const repoDisplay = origin?.repo ?? "an external repository";
|
|
22
|
+
const repoUrl = origin?.repo && origin.path && origin.branch ? `https://github.com/${origin.repo}/blob/${origin.branch}/${origin.path}` : null;
|
|
24
23
|
const handleGraduate = useCallback(async () => {
|
|
25
24
|
try {
|
|
26
25
|
const publishedId = id.replace(/^drafts\./, "");
|
|
@@ -34,6 +33,7 @@ var GraduateToNativeAction = (props) => {
|
|
|
34
33
|
console.error("Failed to graduate task:", err);
|
|
35
34
|
}
|
|
36
35
|
}, [client, draft, id, onComplete]);
|
|
36
|
+
if (type !== "ailf.task" || !origin) return null;
|
|
37
37
|
return {
|
|
38
38
|
dialog: isConfirming ? {
|
|
39
39
|
type: "confirm",
|
|
@@ -60,19 +60,26 @@ var GraduateToNativeAction = (props) => {
|
|
|
60
60
|
onConfirm: handleGraduate
|
|
61
61
|
} : void 0,
|
|
62
62
|
icon: EditIcon,
|
|
63
|
-
label: "Graduate to
|
|
63
|
+
label: "Graduate to native task",
|
|
64
64
|
onHandle: () => setIsConfirming(true),
|
|
65
|
+
title: "Disconnect this task from its source repo so it becomes fully editable in Studio. This cannot be undone.",
|
|
65
66
|
tone: "caution"
|
|
66
67
|
};
|
|
67
68
|
};
|
|
68
69
|
GraduateToNativeAction.displayName = "GraduateToNativeAction";
|
|
69
70
|
|
|
70
71
|
// src/schema/eval-request.ts
|
|
71
|
-
import { defineField, defineType } from "sanity";
|
|
72
|
+
import { ALL_FIELDS_GROUP, defineField, defineType } from "sanity";
|
|
72
73
|
var evalRequestSchema = defineType({
|
|
74
|
+
groups: [
|
|
75
|
+
{ name: "main", title: "Main", default: true },
|
|
76
|
+
{ name: "optional", title: "Optional" },
|
|
77
|
+
ALL_FIELDS_GROUP
|
|
78
|
+
],
|
|
73
79
|
fields: [
|
|
74
80
|
defineField({
|
|
75
81
|
description: "Set when the pipeline completes",
|
|
82
|
+
group: ["optional", "all-fields"],
|
|
76
83
|
name: "completedAt",
|
|
77
84
|
readOnly: true,
|
|
78
85
|
title: "Completed At",
|
|
@@ -80,6 +87,7 @@ var evalRequestSchema = defineType({
|
|
|
80
87
|
}),
|
|
81
88
|
defineField({
|
|
82
89
|
description: "Sanity dataset name",
|
|
90
|
+
group: ["main", "all-fields"],
|
|
83
91
|
name: "dataset",
|
|
84
92
|
readOnly: true,
|
|
85
93
|
title: "Dataset",
|
|
@@ -88,6 +96,7 @@ var evalRequestSchema = defineType({
|
|
|
88
96
|
}),
|
|
89
97
|
defineField({
|
|
90
98
|
description: "Set by webhook handler when GitHub dispatch succeeds",
|
|
99
|
+
group: ["optional", "all-fields"],
|
|
91
100
|
name: "dispatchedAt",
|
|
92
101
|
readOnly: true,
|
|
93
102
|
title: "Dispatched At",
|
|
@@ -95,6 +104,7 @@ var evalRequestSchema = defineType({
|
|
|
95
104
|
}),
|
|
96
105
|
defineField({
|
|
97
106
|
description: "Error message if dispatch or pipeline failed",
|
|
107
|
+
group: ["optional", "all-fields"],
|
|
98
108
|
name: "error",
|
|
99
109
|
readOnly: true,
|
|
100
110
|
title: "Error",
|
|
@@ -102,6 +112,7 @@ var evalRequestSchema = defineType({
|
|
|
102
112
|
}),
|
|
103
113
|
defineField({
|
|
104
114
|
description: "Evaluation mode",
|
|
115
|
+
group: ["main", "all-fields"],
|
|
105
116
|
initialValue: "baseline",
|
|
106
117
|
name: "mode",
|
|
107
118
|
options: {
|
|
@@ -118,6 +129,7 @@ var evalRequestSchema = defineType({
|
|
|
118
129
|
}),
|
|
119
130
|
defineField({
|
|
120
131
|
description: "Content release perspective ID",
|
|
132
|
+
group: ["main", "all-fields"],
|
|
121
133
|
name: "perspective",
|
|
122
134
|
readOnly: true,
|
|
123
135
|
title: "Perspective",
|
|
@@ -126,6 +138,7 @@ var evalRequestSchema = defineType({
|
|
|
126
138
|
}),
|
|
127
139
|
defineField({
|
|
128
140
|
description: "Sanity project ID",
|
|
141
|
+
group: ["main", "all-fields"],
|
|
129
142
|
name: "projectId",
|
|
130
143
|
readOnly: true,
|
|
131
144
|
title: "Project ID",
|
|
@@ -134,6 +147,7 @@ var evalRequestSchema = defineType({
|
|
|
134
147
|
}),
|
|
135
148
|
defineField({
|
|
136
149
|
description: "Links to the resulting ailf.report document's reportId",
|
|
150
|
+
group: ["optional", "all-fields"],
|
|
137
151
|
name: "reportId",
|
|
138
152
|
readOnly: true,
|
|
139
153
|
title: "Report ID",
|
|
@@ -141,6 +155,7 @@ var evalRequestSchema = defineType({
|
|
|
141
155
|
}),
|
|
142
156
|
defineField({
|
|
143
157
|
description: "ISO timestamp of when the request was created",
|
|
158
|
+
group: ["main", "all-fields"],
|
|
144
159
|
name: "requestedAt",
|
|
145
160
|
readOnly: true,
|
|
146
161
|
title: "Requested At",
|
|
@@ -149,6 +164,7 @@ var evalRequestSchema = defineType({
|
|
|
149
164
|
}),
|
|
150
165
|
defineField({
|
|
151
166
|
description: "User ID of the person who clicked the button",
|
|
167
|
+
group: ["optional", "all-fields"],
|
|
152
168
|
name: "requestedBy",
|
|
153
169
|
readOnly: true,
|
|
154
170
|
title: "Requested By",
|
|
@@ -156,6 +172,7 @@ var evalRequestSchema = defineType({
|
|
|
156
172
|
}),
|
|
157
173
|
defineField({
|
|
158
174
|
description: "Request lifecycle: pending \u2192 dispatched \u2192 completed \u2192 failed. Only 'pending' is set by Studio; the webhook handler and pipeline callback update subsequent states.",
|
|
175
|
+
group: ["main", "all-fields"],
|
|
159
176
|
initialValue: "pending",
|
|
160
177
|
name: "status",
|
|
161
178
|
options: {
|
|
@@ -173,6 +190,7 @@ var evalRequestSchema = defineType({
|
|
|
173
190
|
}),
|
|
174
191
|
defineField({
|
|
175
192
|
description: 'Publish tag for the report (e.g. "release-my-release-2026-03-16")',
|
|
193
|
+
group: ["optional", "all-fields"],
|
|
176
194
|
name: "tag",
|
|
177
195
|
readOnly: true,
|
|
178
196
|
title: "Tag",
|
|
@@ -197,11 +215,17 @@ var evalRequestSchema = defineType({
|
|
|
197
215
|
});
|
|
198
216
|
|
|
199
217
|
// src/schema/feature-area.ts
|
|
200
|
-
import { defineField as defineField2, defineType as defineType2 } from "sanity";
|
|
218
|
+
import { ALL_FIELDS_GROUP as ALL_FIELDS_GROUP2, defineField as defineField2, defineType as defineType2 } from "sanity";
|
|
201
219
|
var featureAreaSchema = defineType2({
|
|
220
|
+
groups: [
|
|
221
|
+
{ name: "main", title: "Main", default: true },
|
|
222
|
+
{ name: "optional", title: "Optional" },
|
|
223
|
+
ALL_FIELDS_GROUP2
|
|
224
|
+
],
|
|
202
225
|
fields: [
|
|
203
226
|
defineField2({
|
|
204
227
|
description: 'Unique stable identifier (e.g., "groq"). Must be lowercase alphanumeric with hyphens. Used for CLI filtering (--area groq) and score aggregation.',
|
|
228
|
+
group: ["main", "all-fields"],
|
|
205
229
|
name: "areaId",
|
|
206
230
|
title: "Area ID",
|
|
207
231
|
type: "slug",
|
|
@@ -214,6 +238,7 @@ var featureAreaSchema = defineType2({
|
|
|
214
238
|
}),
|
|
215
239
|
defineField2({
|
|
216
240
|
description: 'Human-readable label shown in Studio and reports (e.g., "GROQ Query Language")',
|
|
241
|
+
group: ["main", "all-fields"],
|
|
217
242
|
name: "description",
|
|
218
243
|
title: "Description",
|
|
219
244
|
type: "string",
|
|
@@ -221,12 +246,14 @@ var featureAreaSchema = defineType2({
|
|
|
221
246
|
}),
|
|
222
247
|
defineField2({
|
|
223
248
|
description: "Team or person responsible for this feature area (optional)",
|
|
249
|
+
group: ["optional", "all-fields"],
|
|
224
250
|
name: "owner",
|
|
225
251
|
title: "Owner",
|
|
226
252
|
type: "string"
|
|
227
253
|
}),
|
|
228
254
|
defineField2({
|
|
229
255
|
description: "Additional categorization labels for filtering",
|
|
256
|
+
group: ["optional", "all-fields"],
|
|
230
257
|
name: "tags",
|
|
231
258
|
of: [{ type: "string" }],
|
|
232
259
|
title: "Tags",
|
|
@@ -252,31 +279,25 @@ var featureAreaSchema = defineType2({
|
|
|
252
279
|
});
|
|
253
280
|
|
|
254
281
|
// src/schema/reference-solution.ts
|
|
255
|
-
import { defineField as defineField3, defineType as defineType3 } from "sanity";
|
|
282
|
+
import { ALL_FIELDS_GROUP as ALL_FIELDS_GROUP3, defineField as defineField3, defineType as defineType3 } from "sanity";
|
|
256
283
|
var referenceSolutionSchema = defineType3({
|
|
284
|
+
groups: [
|
|
285
|
+
{ name: "main", title: "Main", default: true },
|
|
286
|
+
{ name: "optional", title: "Optional" },
|
|
287
|
+
ALL_FIELDS_GROUP3
|
|
288
|
+
],
|
|
257
289
|
fields: [
|
|
258
290
|
defineField3({
|
|
259
291
|
description: "Human-readable label for this reference solution",
|
|
292
|
+
group: ["main", "all-fields"],
|
|
260
293
|
name: "title",
|
|
261
294
|
title: "Title",
|
|
262
295
|
type: "string",
|
|
263
296
|
validation: (rule) => rule.required()
|
|
264
297
|
}),
|
|
265
|
-
defineField3({
|
|
266
|
-
description: "Primary programming language of the solution",
|
|
267
|
-
initialValue: "typescript",
|
|
268
|
-
name: "language",
|
|
269
|
-
options: {
|
|
270
|
-
list: [
|
|
271
|
-
{ title: "TypeScript", value: "typescript" },
|
|
272
|
-
{ title: "JavaScript", value: "javascript" }
|
|
273
|
-
]
|
|
274
|
-
},
|
|
275
|
-
title: "Language",
|
|
276
|
-
type: "string"
|
|
277
|
-
}),
|
|
278
298
|
defineField3({
|
|
279
299
|
description: "Gold-standard implementation with code blocks and prose explanation. Use code blocks for the implementation and regular text to explain why this is the correct approach.",
|
|
300
|
+
group: ["main", "all-fields"],
|
|
280
301
|
name: "content",
|
|
281
302
|
of: [{ type: "block" }, { type: "code" }],
|
|
282
303
|
title: "Content",
|
|
@@ -284,28 +305,23 @@ var referenceSolutionSchema = defineType3({
|
|
|
284
305
|
}),
|
|
285
306
|
defineField3({
|
|
286
307
|
description: "CDN-uploaded files for multi-file solutions (e.g., a Next.js page + a schema + a config). Each file is uploaded as an asset with its filename preserved.",
|
|
308
|
+
group: ["optional", "all-fields"],
|
|
287
309
|
name: "files",
|
|
288
310
|
of: [{ type: "file" }],
|
|
289
311
|
title: "Files",
|
|
290
312
|
type: "array"
|
|
291
313
|
}),
|
|
292
314
|
defineField3({
|
|
293
|
-
description: "
|
|
315
|
+
description: "Describe why this is the correct approach, including any rationale and decisions.",
|
|
316
|
+
group: ["optional", "all-fields"],
|
|
294
317
|
name: "notes",
|
|
295
|
-
title: "Notes",
|
|
318
|
+
title: "Author Notes",
|
|
296
319
|
type: "text"
|
|
297
320
|
})
|
|
298
321
|
],
|
|
299
322
|
name: "ailf.referenceSolution",
|
|
300
323
|
preview: {
|
|
301
|
-
prepare({ language, title }) {
|
|
302
|
-
return {
|
|
303
|
-
subtitle: typeof language === "string" ? language : "",
|
|
304
|
-
title: typeof title === "string" ? title : "Reference Solution"
|
|
305
|
-
};
|
|
306
|
-
},
|
|
307
324
|
select: {
|
|
308
|
-
language: "language",
|
|
309
325
|
title: "title"
|
|
310
326
|
}
|
|
311
327
|
},
|
|
@@ -314,7 +330,7 @@ var referenceSolutionSchema = defineType3({
|
|
|
314
330
|
});
|
|
315
331
|
|
|
316
332
|
// src/schema/report.ts
|
|
317
|
-
import { defineField as defineField4, defineType as defineType4 } from "sanity";
|
|
333
|
+
import { ALL_FIELDS_GROUP as ALL_FIELDS_GROUP4, defineField as defineField4, defineType as defineType4 } from "sanity";
|
|
318
334
|
function documentRefSchema() {
|
|
319
335
|
return {
|
|
320
336
|
fields: [
|
|
@@ -327,8 +343,14 @@ function documentRefSchema() {
|
|
|
327
343
|
};
|
|
328
344
|
}
|
|
329
345
|
var reportSchema = defineType4({
|
|
346
|
+
groups: [
|
|
347
|
+
{ name: "main", title: "Main", default: true },
|
|
348
|
+
{ name: "optional", title: "Optional" },
|
|
349
|
+
ALL_FIELDS_GROUP4
|
|
350
|
+
],
|
|
330
351
|
fields: [
|
|
331
352
|
defineField4({
|
|
353
|
+
group: ["main", "all-fields"],
|
|
332
354
|
name: "reportId",
|
|
333
355
|
readOnly: true,
|
|
334
356
|
title: "Report ID",
|
|
@@ -336,6 +358,7 @@ var reportSchema = defineType4({
|
|
|
336
358
|
validation: (rule) => rule.required()
|
|
337
359
|
}),
|
|
338
360
|
defineField4({
|
|
361
|
+
group: ["main", "all-fields"],
|
|
339
362
|
name: "completedAt",
|
|
340
363
|
readOnly: true,
|
|
341
364
|
title: "Completed At",
|
|
@@ -343,12 +366,14 @@ var reportSchema = defineType4({
|
|
|
343
366
|
validation: (rule) => rule.required()
|
|
344
367
|
}),
|
|
345
368
|
defineField4({
|
|
369
|
+
group: ["optional", "all-fields"],
|
|
346
370
|
name: "durationMs",
|
|
347
371
|
readOnly: true,
|
|
348
372
|
title: "Duration (ms)",
|
|
349
373
|
type: "number"
|
|
350
374
|
}),
|
|
351
375
|
defineField4({
|
|
376
|
+
group: ["optional", "all-fields"],
|
|
352
377
|
name: "tag",
|
|
353
378
|
readOnly: true,
|
|
354
379
|
title: "Tag",
|
|
@@ -528,6 +553,7 @@ var reportSchema = defineType4({
|
|
|
528
553
|
type: "object"
|
|
529
554
|
})
|
|
530
555
|
],
|
|
556
|
+
group: ["main", "all-fields"],
|
|
531
557
|
name: "provenance",
|
|
532
558
|
readOnly: true,
|
|
533
559
|
title: "Provenance",
|
|
@@ -976,6 +1002,7 @@ var reportSchema = defineType4({
|
|
|
976
1002
|
type: "array"
|
|
977
1003
|
})
|
|
978
1004
|
],
|
|
1005
|
+
group: ["main", "all-fields"],
|
|
979
1006
|
name: "summary",
|
|
980
1007
|
readOnly: true,
|
|
981
1008
|
title: "Score Summary",
|
|
@@ -1047,6 +1074,7 @@ var reportSchema = defineType4({
|
|
|
1047
1074
|
type: "string"
|
|
1048
1075
|
})
|
|
1049
1076
|
],
|
|
1077
|
+
group: ["optional", "all-fields"],
|
|
1050
1078
|
name: "comparison",
|
|
1051
1079
|
readOnly: true,
|
|
1052
1080
|
title: "Auto-Comparison",
|
|
@@ -1078,18 +1106,306 @@ var reportSchema = defineType4({
|
|
|
1078
1106
|
});
|
|
1079
1107
|
|
|
1080
1108
|
// src/schema/task.ts
|
|
1081
|
-
import { defineField as defineField5, defineType as defineType5 } from "sanity";
|
|
1109
|
+
import { ALL_FIELDS_GROUP as ALL_FIELDS_GROUP5, defineField as defineField5, defineType as defineType5 } from "sanity";
|
|
1110
|
+
|
|
1111
|
+
// src/components/AssertionInput.tsx
|
|
1112
|
+
import { HelpCircleIcon } from "@sanity/icons";
|
|
1113
|
+
import { Box as Box2, Card, Flex, Stack as Stack2, Text as Text2 } from "@sanity/ui";
|
|
1114
|
+
import { useCallback as useCallback2 } from "react";
|
|
1115
|
+
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1116
|
+
var TYPE_HELP = {
|
|
1117
|
+
"llm-rubric": {
|
|
1118
|
+
description: "Sends the LLM output to a grader model that scores it against a rubric template. Select a template and add task-specific criteria bullets that describe what the grader should check."
|
|
1119
|
+
},
|
|
1120
|
+
contains: {
|
|
1121
|
+
description: "Passes if the output contains this exact substring. Case-sensitive.",
|
|
1122
|
+
valueHint: "The exact text that must appear in the output.",
|
|
1123
|
+
example: "createClient"
|
|
1124
|
+
},
|
|
1125
|
+
"contains-any": {
|
|
1126
|
+
description: "Passes if the output contains at least one of the given substrings. Case-sensitive. Enter each substring on a separate line.",
|
|
1127
|
+
valueHint: "One substring per line \u2014 passes if any match.",
|
|
1128
|
+
example: "createClient\ngetClient"
|
|
1129
|
+
},
|
|
1130
|
+
"contains-all": {
|
|
1131
|
+
description: "Passes if the output contains all of the given substrings. Case-sensitive. Enter each substring on a separate line.",
|
|
1132
|
+
valueHint: "One substring per line \u2014 all must match.",
|
|
1133
|
+
example: "import\ncreateClient\nclient.fetch"
|
|
1134
|
+
},
|
|
1135
|
+
"not-contains": {
|
|
1136
|
+
description: "Passes if the output does NOT contain this substring. Case-sensitive. Useful for checking that deprecated patterns or incorrect APIs are absent.",
|
|
1137
|
+
valueHint: "Text that must NOT appear in the output.",
|
|
1138
|
+
example: "documentStore"
|
|
1139
|
+
},
|
|
1140
|
+
icontains: {
|
|
1141
|
+
description: "Like contains, but case-insensitive. Passes if the output contains this substring regardless of casing.",
|
|
1142
|
+
valueHint: "The text that must appear (case-insensitive).",
|
|
1143
|
+
example: "groq"
|
|
1144
|
+
},
|
|
1145
|
+
"icontains-any": {
|
|
1146
|
+
description: "Like contains-any, but case-insensitive. Passes if the output contains at least one substring, ignoring case. Enter each on a separate line.",
|
|
1147
|
+
valueHint: "One substring per line \u2014 passes if any match (case-insensitive).",
|
|
1148
|
+
example: "GROQ\ngroq\nGroq"
|
|
1149
|
+
},
|
|
1150
|
+
regex: {
|
|
1151
|
+
description: "Passes if the output matches this regular expression pattern. Uses JavaScript regex syntax (without delimiters).",
|
|
1152
|
+
valueHint: "A JavaScript regular expression pattern.",
|
|
1153
|
+
example: "import\\s+\\{.*createClient.*\\}\\s+from"
|
|
1154
|
+
},
|
|
1155
|
+
javascript: {
|
|
1156
|
+
description: "A JavaScript function body that evaluates the output. Receives the variable 'output' (string) and must return true (pass) or false (fail). Can also return a number 0\u20131 for scored assertions, or an object { pass: boolean, score: number, reason: string }.",
|
|
1157
|
+
valueHint: "JavaScript code \u2014 'output' variable is available.",
|
|
1158
|
+
example: "// Check for correct import pattern\nconst hasImport = output.includes('createClient');\nconst noDeprecated = !output.includes('documentStore');\nreturn hasImport && noDeprecated;"
|
|
1159
|
+
},
|
|
1160
|
+
similar: {
|
|
1161
|
+
description: "Passes if the output is semantically similar to the value text, using embedding-based cosine similarity. Set the threshold between 0 (no similarity required) and 1 (exact match).",
|
|
1162
|
+
valueHint: "Reference text to compare against.",
|
|
1163
|
+
thresholdHint: "Similarity score 0\u20131 (e.g. 0.8 for strong match)."
|
|
1164
|
+
},
|
|
1165
|
+
cost: {
|
|
1166
|
+
description: "Passes if the API call cost is below the threshold. Useful for ensuring tasks stay within budget.",
|
|
1167
|
+
thresholdHint: "Maximum cost in dollars (e.g. 0.05)."
|
|
1168
|
+
},
|
|
1169
|
+
latency: {
|
|
1170
|
+
description: "Passes if the API call latency is below the threshold. Useful for performance-sensitive evaluations.",
|
|
1171
|
+
thresholdHint: "Maximum latency in milliseconds (e.g. 5000)."
|
|
1172
|
+
}
|
|
1173
|
+
};
|
|
1174
|
+
var MONOSPACE_TYPES = /* @__PURE__ */ new Set(["javascript", "regex"]);
|
|
1175
|
+
var MONOSPACE_STYLE = `
|
|
1176
|
+
[data-ailf-monospace="true"] textarea {
|
|
1177
|
+
font-family: "SF Mono", "Fira Code", "Fira Mono", Menlo, Consolas, monospace !important;
|
|
1178
|
+
font-size: 13px !important;
|
|
1179
|
+
line-height: 1.5 !important;
|
|
1180
|
+
tab-size: 2;
|
|
1181
|
+
}
|
|
1182
|
+
`;
|
|
1183
|
+
var TEMPLATE_HELP = {
|
|
1184
|
+
"task-completion": {
|
|
1185
|
+
description: "Scores whether the LLM produced a functional implementation that satisfies the task requirements. This is the most heavily weighted dimension.",
|
|
1186
|
+
weight: "50% of composite score",
|
|
1187
|
+
scaleHint: "0 = couldn't attempt \u2192 50 = major gaps \u2192 100 = fully functional"
|
|
1188
|
+
},
|
|
1189
|
+
"code-correctness": {
|
|
1190
|
+
description: "Scores whether the code follows best practices, uses current APIs, and avoids anti-patterns. Checks for idiomatic implementation and correct API usage.",
|
|
1191
|
+
weight: "25% of composite score",
|
|
1192
|
+
scaleHint: "0 = broken/deprecated \u2192 50 = works but not idiomatic \u2192 100 = best practices"
|
|
1193
|
+
},
|
|
1194
|
+
"doc-coverage": {
|
|
1195
|
+
description: "Scores how much of the implementation could be derived from the provided documentation vs. requiring hallucination or guesswork. Measures doc quality.",
|
|
1196
|
+
weight: "25% of composite score",
|
|
1197
|
+
scaleHint: "0 = had to hallucinate \u2192 50 = inferred from partial info \u2192 100 = fully covered"
|
|
1198
|
+
}
|
|
1199
|
+
};
|
|
1200
|
+
function TypeHelpCard({ help }) {
|
|
1201
|
+
return /* @__PURE__ */ jsx2(Card, { padding: 3, radius: 2, tone: "transparent", border: true, children: /* @__PURE__ */ jsxs2(Stack2, { space: 3, children: [
|
|
1202
|
+
/* @__PURE__ */ jsxs2(Flex, { align: "flex-start", gap: 2, children: [
|
|
1203
|
+
/* @__PURE__ */ jsx2(Box2, { style: { flexShrink: 0, marginTop: 1 }, children: /* @__PURE__ */ jsx2(Text2, { size: 1, muted: true, children: /* @__PURE__ */ jsx2(HelpCircleIcon, {}) }) }),
|
|
1204
|
+
/* @__PURE__ */ jsx2(Text2, { size: 1, muted: true, children: help.description })
|
|
1205
|
+
] }),
|
|
1206
|
+
(help.valueHint || help.thresholdHint || help.example) && /* @__PURE__ */ jsxs2(Stack2, { space: 2, paddingLeft: 4, children: [
|
|
1207
|
+
help.valueHint && /* @__PURE__ */ jsxs2(Text2, { size: 0, muted: true, children: [
|
|
1208
|
+
/* @__PURE__ */ jsx2("strong", { children: "Value:" }),
|
|
1209
|
+
" ",
|
|
1210
|
+
help.valueHint
|
|
1211
|
+
] }),
|
|
1212
|
+
help.thresholdHint && /* @__PURE__ */ jsxs2(Text2, { size: 0, muted: true, children: [
|
|
1213
|
+
/* @__PURE__ */ jsx2("strong", { children: "Threshold:" }),
|
|
1214
|
+
" ",
|
|
1215
|
+
help.thresholdHint
|
|
1216
|
+
] }),
|
|
1217
|
+
help.example && /* @__PURE__ */ jsxs2(Box2, { marginTop: 1, children: [
|
|
1218
|
+
/* @__PURE__ */ jsx2(Text2, { size: 0, muted: true, children: /* @__PURE__ */ jsx2("strong", { children: "Example:" }) }),
|
|
1219
|
+
/* @__PURE__ */ jsx2(
|
|
1220
|
+
Box2,
|
|
1221
|
+
{
|
|
1222
|
+
marginTop: 1,
|
|
1223
|
+
style: {
|
|
1224
|
+
background: "var(--card-code-bg-color, #f5f5f5)",
|
|
1225
|
+
borderRadius: 3,
|
|
1226
|
+
padding: "6px 8px",
|
|
1227
|
+
fontFamily: '"SF Mono", "Fira Code", Menlo, Consolas, monospace',
|
|
1228
|
+
fontSize: 12,
|
|
1229
|
+
lineHeight: 1.5,
|
|
1230
|
+
whiteSpace: "pre-wrap",
|
|
1231
|
+
wordBreak: "break-word"
|
|
1232
|
+
},
|
|
1233
|
+
children: help.example
|
|
1234
|
+
}
|
|
1235
|
+
)
|
|
1236
|
+
] })
|
|
1237
|
+
] })
|
|
1238
|
+
] }) });
|
|
1239
|
+
}
|
|
1240
|
+
function TemplateHelpCard({ help }) {
|
|
1241
|
+
return /* @__PURE__ */ jsx2(Card, { padding: 3, radius: 2, tone: "transparent", border: true, children: /* @__PURE__ */ jsxs2(Stack2, { space: 2, children: [
|
|
1242
|
+
/* @__PURE__ */ jsxs2(Flex, { align: "flex-start", gap: 2, children: [
|
|
1243
|
+
/* @__PURE__ */ jsx2(Box2, { style: { flexShrink: 0, marginTop: 1 }, children: /* @__PURE__ */ jsx2(Text2, { size: 1, muted: true, children: /* @__PURE__ */ jsx2(HelpCircleIcon, {}) }) }),
|
|
1244
|
+
/* @__PURE__ */ jsx2(Text2, { size: 1, muted: true, children: help.description })
|
|
1245
|
+
] }),
|
|
1246
|
+
/* @__PURE__ */ jsxs2(Stack2, { space: 1, paddingLeft: 4, children: [
|
|
1247
|
+
/* @__PURE__ */ jsxs2(Text2, { size: 0, muted: true, children: [
|
|
1248
|
+
/* @__PURE__ */ jsx2("strong", { children: "Weight:" }),
|
|
1249
|
+
" ",
|
|
1250
|
+
help.weight
|
|
1251
|
+
] }),
|
|
1252
|
+
/* @__PURE__ */ jsxs2(Text2, { size: 0, muted: true, children: [
|
|
1253
|
+
/* @__PURE__ */ jsx2("strong", { children: "Scale:" }),
|
|
1254
|
+
" ",
|
|
1255
|
+
help.scaleHint
|
|
1256
|
+
] })
|
|
1257
|
+
] })
|
|
1258
|
+
] }) });
|
|
1259
|
+
}
|
|
1260
|
+
function AssertionInput(props) {
|
|
1261
|
+
const value = props.value;
|
|
1262
|
+
const selectedType = typeof value?.type === "string" ? value.type : null;
|
|
1263
|
+
const selectedTemplate = typeof value?.template === "string" ? value.template : null;
|
|
1264
|
+
const typeHelp = selectedType ? TYPE_HELP[selectedType] : null;
|
|
1265
|
+
const templateHelp = selectedTemplate ? TEMPLATE_HELP[selectedTemplate] : null;
|
|
1266
|
+
const isMonospace = selectedType ? MONOSPACE_TYPES.has(selectedType) : false;
|
|
1267
|
+
const { renderField: parentRenderField } = props;
|
|
1268
|
+
const renderField = useCallback2(
|
|
1269
|
+
(fieldProps) => {
|
|
1270
|
+
const rendered = parentRenderField(fieldProps);
|
|
1271
|
+
if (fieldProps.name === "type" && typeHelp) {
|
|
1272
|
+
return /* @__PURE__ */ jsxs2(Stack2, { space: 3, children: [
|
|
1273
|
+
rendered,
|
|
1274
|
+
/* @__PURE__ */ jsx2(TypeHelpCard, { help: typeHelp })
|
|
1275
|
+
] });
|
|
1276
|
+
}
|
|
1277
|
+
if (fieldProps.name === "template" && templateHelp) {
|
|
1278
|
+
return /* @__PURE__ */ jsxs2(Stack2, { space: 3, children: [
|
|
1279
|
+
rendered,
|
|
1280
|
+
/* @__PURE__ */ jsx2(TemplateHelpCard, { help: templateHelp })
|
|
1281
|
+
] });
|
|
1282
|
+
}
|
|
1283
|
+
return rendered;
|
|
1284
|
+
},
|
|
1285
|
+
[typeHelp, templateHelp, parentRenderField]
|
|
1286
|
+
);
|
|
1287
|
+
return /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
1288
|
+
isMonospace && /* @__PURE__ */ jsx2("style", { children: MONOSPACE_STYLE }),
|
|
1289
|
+
/* @__PURE__ */ jsx2("div", { "data-ailf-monospace": isMonospace ? "true" : void 0, children: props.renderDefault({ ...props, renderField }) })
|
|
1290
|
+
] });
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1293
|
+
// src/components/CanonicalDocInput.tsx
|
|
1294
|
+
import { HelpCircleIcon as HelpCircleIcon2 } from "@sanity/icons";
|
|
1295
|
+
import { Box as Box3, Card as Card2, Flex as Flex2, Stack as Stack3, Text as Text3 } from "@sanity/ui";
|
|
1296
|
+
import { useCallback as useCallback3 } from "react";
|
|
1297
|
+
import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1298
|
+
var REF_TYPE_HELP = {
|
|
1299
|
+
slug: {
|
|
1300
|
+
description: "References a single article document. Use the document picker below to select the article. The pipeline reads the slug, path, and ID directly from the referenced document.",
|
|
1301
|
+
valueHint: "Select an article document using the picker below."
|
|
1302
|
+
},
|
|
1303
|
+
perspective: {
|
|
1304
|
+
description: "Includes all articles from a content release. Use the release picker below to select a release. The pipeline auto-discovers every article in the release at evaluation time.",
|
|
1305
|
+
valueHint: "Select a content release using the picker below."
|
|
1306
|
+
}
|
|
1307
|
+
};
|
|
1308
|
+
function RefTypeHelpCard({ help }) {
|
|
1309
|
+
return /* @__PURE__ */ jsx3(Card2, { padding: 3, radius: 2, tone: "transparent", border: true, children: /* @__PURE__ */ jsxs3(Flex2, { align: "flex-start", gap: 2, children: [
|
|
1310
|
+
/* @__PURE__ */ jsx3(Box3, { style: { flexShrink: 0, marginTop: 1 }, children: /* @__PURE__ */ jsx3(Text3, { size: 1, muted: true, children: /* @__PURE__ */ jsx3(HelpCircleIcon2, {}) }) }),
|
|
1311
|
+
/* @__PURE__ */ jsx3(Text3, { size: 1, muted: true, children: help.description })
|
|
1312
|
+
] }) });
|
|
1313
|
+
}
|
|
1314
|
+
function CanonicalDocInput(props) {
|
|
1315
|
+
const value = props.value;
|
|
1316
|
+
const selectedType = typeof value?.refType === "string" ? value.refType : null;
|
|
1317
|
+
const help = selectedType ? REF_TYPE_HELP[selectedType] : null;
|
|
1318
|
+
const { renderField: parentRenderField } = props;
|
|
1319
|
+
const renderField = useCallback3(
|
|
1320
|
+
(fieldProps) => {
|
|
1321
|
+
const rendered = parentRenderField(fieldProps);
|
|
1322
|
+
if (fieldProps.name === "refType" && help) {
|
|
1323
|
+
return /* @__PURE__ */ jsxs3(Stack3, { space: 3, children: [
|
|
1324
|
+
rendered,
|
|
1325
|
+
/* @__PURE__ */ jsx3(RefTypeHelpCard, { help })
|
|
1326
|
+
] });
|
|
1327
|
+
}
|
|
1328
|
+
return rendered;
|
|
1329
|
+
},
|
|
1330
|
+
[help, parentRenderField]
|
|
1331
|
+
);
|
|
1332
|
+
return /* @__PURE__ */ jsx3(Fragment2, { children: props.renderDefault({ ...props, renderField }) });
|
|
1333
|
+
}
|
|
1334
|
+
|
|
1335
|
+
// src/components/CanonicalDocPreview.tsx
|
|
1336
|
+
import { Flex as Flex3, Text as Text4 } from "@sanity/ui";
|
|
1337
|
+
import { useMemo } from "react";
|
|
1338
|
+
import {
|
|
1339
|
+
getReleaseIdFromReleaseDocumentId,
|
|
1340
|
+
useActiveReleases,
|
|
1341
|
+
useArchivedReleases
|
|
1342
|
+
} from "sanity";
|
|
1343
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1344
|
+
function CanonicalDocPreview(props) {
|
|
1345
|
+
const { perspective, perspectiveTitle, reason, refType, slug, path } = props;
|
|
1346
|
+
const isPerspective = refType === "perspective";
|
|
1347
|
+
const { data: activeReleases } = useActiveReleases();
|
|
1348
|
+
const { data: archivedReleases } = useArchivedReleases();
|
|
1349
|
+
const resolvedTitle = useMemo(() => {
|
|
1350
|
+
if (!isPerspective) {
|
|
1351
|
+
return typeof props.title === "string" ? props.title : "Document";
|
|
1352
|
+
}
|
|
1353
|
+
if (typeof perspectiveTitle === "string" && perspectiveTitle.length > 0) {
|
|
1354
|
+
return perspectiveTitle;
|
|
1355
|
+
}
|
|
1356
|
+
if (typeof perspective === "string") {
|
|
1357
|
+
const allReleases = [
|
|
1358
|
+
...activeReleases ?? [],
|
|
1359
|
+
...archivedReleases ?? []
|
|
1360
|
+
];
|
|
1361
|
+
const match = allReleases.find(
|
|
1362
|
+
(r) => getReleaseIdFromReleaseDocumentId(r._id) === perspective
|
|
1363
|
+
);
|
|
1364
|
+
if (match?.metadata?.title) {
|
|
1365
|
+
return match.metadata.title;
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
return typeof perspective === "string" ? perspective : "Content Release";
|
|
1369
|
+
}, [
|
|
1370
|
+
isPerspective,
|
|
1371
|
+
perspectiveTitle,
|
|
1372
|
+
perspective,
|
|
1373
|
+
activeReleases,
|
|
1374
|
+
archivedReleases,
|
|
1375
|
+
props.title
|
|
1376
|
+
]);
|
|
1377
|
+
const icon = isPerspective ? "\u{1F4E6}" : "\u{1F4C4}";
|
|
1378
|
+
let subtitle;
|
|
1379
|
+
if (typeof reason === "string" && reason.length > 0) {
|
|
1380
|
+
subtitle = reason;
|
|
1381
|
+
} else if (isPerspective && typeof perspective === "string") {
|
|
1382
|
+
subtitle = perspective;
|
|
1383
|
+
} else if (typeof slug === "string") {
|
|
1384
|
+
subtitle = slug;
|
|
1385
|
+
} else if (typeof path === "string") {
|
|
1386
|
+
subtitle = path;
|
|
1387
|
+
} else {
|
|
1388
|
+
subtitle = "";
|
|
1389
|
+
}
|
|
1390
|
+
return /* @__PURE__ */ jsxs4(Flex3, { align: "center", gap: 2, padding: 2, children: [
|
|
1391
|
+
/* @__PURE__ */ jsx4(Text4, { size: 1, children: icon }),
|
|
1392
|
+
/* @__PURE__ */ jsxs4(Flex3, { direction: "column", gap: 1, flex: 1, children: [
|
|
1393
|
+
/* @__PURE__ */ jsx4(Text4, { size: 1, weight: "semibold", children: resolvedTitle }),
|
|
1394
|
+
subtitle && /* @__PURE__ */ jsx4(Text4, { muted: true, size: 0, children: subtitle })
|
|
1395
|
+
] })
|
|
1396
|
+
] });
|
|
1397
|
+
}
|
|
1082
1398
|
|
|
1083
1399
|
// src/components/OriginInput.tsx
|
|
1084
|
-
import { Stack as
|
|
1400
|
+
import { Stack as Stack5 } from "@sanity/ui";
|
|
1085
1401
|
|
|
1086
1402
|
// src/components/MirrorBanner.tsx
|
|
1087
1403
|
import { LinkIcon } from "@sanity/icons";
|
|
1088
|
-
import { Card, Flex, Stack as
|
|
1404
|
+
import { Card as Card3, Flex as Flex4, Stack as Stack4, Text as Text6 } from "@sanity/ui";
|
|
1089
1405
|
|
|
1090
1406
|
// src/components/SyncStatusBadge.tsx
|
|
1091
|
-
import { Badge, Box as
|
|
1092
|
-
import { jsx as
|
|
1407
|
+
import { Badge, Box as Box4, Text as Text5, Tooltip } from "@sanity/ui";
|
|
1408
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1093
1409
|
var MS_PER_DAY = 24 * 60 * 60 * 1e3;
|
|
1094
1410
|
var FRESH_THRESHOLD_MS = 3 * MS_PER_DAY;
|
|
1095
1411
|
var STALE_THRESHOLD_MS = 7 * MS_PER_DAY;
|
|
@@ -1113,33 +1429,33 @@ function SyncStatusBadge({
|
|
|
1113
1429
|
const label = ageMs < FRESH_THRESHOLD_MS ? "Synced" : ageMs < STALE_THRESHOLD_MS ? "Stale" : "Outdated";
|
|
1114
1430
|
const ageStr = formatAge(ageMs);
|
|
1115
1431
|
const shaStr = commitSha ? ` \xB7 ${commitSha.slice(0, 7)}` : "";
|
|
1116
|
-
return /* @__PURE__ */
|
|
1432
|
+
return /* @__PURE__ */ jsx5(
|
|
1117
1433
|
Tooltip,
|
|
1118
1434
|
{
|
|
1119
|
-
content: /* @__PURE__ */
|
|
1435
|
+
content: /* @__PURE__ */ jsx5(Box4, { padding: 2, children: /* @__PURE__ */ jsxs5(Text5, { size: 1, children: [
|
|
1120
1436
|
"Last synced ",
|
|
1121
1437
|
ageStr,
|
|
1122
1438
|
shaStr
|
|
1123
1439
|
] }) }),
|
|
1124
1440
|
portal: true,
|
|
1125
|
-
children: /* @__PURE__ */
|
|
1441
|
+
children: /* @__PURE__ */ jsx5(Badge, { fontSize, tone, children: label })
|
|
1126
1442
|
}
|
|
1127
1443
|
);
|
|
1128
1444
|
}
|
|
1129
1445
|
|
|
1130
1446
|
// src/components/MirrorBanner.tsx
|
|
1131
|
-
import { jsx as
|
|
1447
|
+
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1132
1448
|
function MirrorBanner({ origin }) {
|
|
1133
1449
|
const { repo, path, branch, commitSha, lastSyncedAt } = origin;
|
|
1134
1450
|
const repoUrl = repo && path && branch ? `https://github.com/${repo}/blob/${branch}/${path}` : null;
|
|
1135
1451
|
const repoDisplay = repo ?? "an external repository";
|
|
1136
|
-
return /* @__PURE__ */
|
|
1137
|
-
/* @__PURE__ */
|
|
1138
|
-
/* @__PURE__ */
|
|
1139
|
-
/* @__PURE__ */
|
|
1452
|
+
return /* @__PURE__ */ jsx6(Card3, { padding: 3, radius: 2, tone: "transparent", border: true, children: /* @__PURE__ */ jsxs6(Stack4, { space: 3, children: [
|
|
1453
|
+
/* @__PURE__ */ jsxs6(Flex4, { align: "center", gap: 2, children: [
|
|
1454
|
+
/* @__PURE__ */ jsx6(Text6, { size: 1, children: /* @__PURE__ */ jsx6(LinkIcon, {}) }),
|
|
1455
|
+
/* @__PURE__ */ jsxs6(Text6, { size: 1, children: [
|
|
1140
1456
|
"This task is managed in",
|
|
1141
1457
|
" ",
|
|
1142
|
-
repoUrl ? /* @__PURE__ */
|
|
1458
|
+
repoUrl ? /* @__PURE__ */ jsx6(
|
|
1143
1459
|
"a",
|
|
1144
1460
|
{
|
|
1145
1461
|
href: repoUrl,
|
|
@@ -1148,12 +1464,12 @@ function MirrorBanner({ origin }) {
|
|
|
1148
1464
|
style: { fontWeight: 600 },
|
|
1149
1465
|
children: repoDisplay
|
|
1150
1466
|
}
|
|
1151
|
-
) : /* @__PURE__ */
|
|
1467
|
+
) : /* @__PURE__ */ jsx6("strong", { children: repoDisplay }),
|
|
1152
1468
|
". Edit it there to make changes."
|
|
1153
1469
|
] })
|
|
1154
1470
|
] }),
|
|
1155
|
-
/* @__PURE__ */
|
|
1156
|
-
lastSyncedAt && /* @__PURE__ */
|
|
1471
|
+
/* @__PURE__ */ jsxs6(Flex4, { align: "center", gap: 2, wrap: "wrap", children: [
|
|
1472
|
+
lastSyncedAt && /* @__PURE__ */ jsx6(
|
|
1157
1473
|
SyncStatusBadge,
|
|
1158
1474
|
{
|
|
1159
1475
|
lastSyncedAt,
|
|
@@ -1161,17 +1477,17 @@ function MirrorBanner({ origin }) {
|
|
|
1161
1477
|
fontSize: 0
|
|
1162
1478
|
}
|
|
1163
1479
|
),
|
|
1164
|
-
branch && /* @__PURE__ */
|
|
1480
|
+
branch && /* @__PURE__ */ jsxs6(Text6, { size: 0, muted: true, children: [
|
|
1165
1481
|
branch,
|
|
1166
1482
|
commitSha ? ` @ ${commitSha.slice(0, 7)}` : ""
|
|
1167
1483
|
] }),
|
|
1168
|
-
path && /* @__PURE__ */
|
|
1484
|
+
path && /* @__PURE__ */ jsx6(Text6, { size: 0, muted: true, children: path })
|
|
1169
1485
|
] })
|
|
1170
1486
|
] }) });
|
|
1171
1487
|
}
|
|
1172
1488
|
|
|
1173
1489
|
// src/components/OriginInput.tsx
|
|
1174
|
-
import { jsx as
|
|
1490
|
+
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1175
1491
|
function OriginInput(props) {
|
|
1176
1492
|
const value = props.value;
|
|
1177
1493
|
if (!value) return props.renderDefault(props);
|
|
@@ -1184,12 +1500,123 @@ function OriginInput(props) {
|
|
|
1184
1500
|
commitSha: typeof value.commitSha === "string" ? value.commitSha : void 0,
|
|
1185
1501
|
lastSyncedAt: typeof value.lastSyncedAt === "string" ? value.lastSyncedAt : void 0
|
|
1186
1502
|
};
|
|
1187
|
-
return /* @__PURE__ */
|
|
1188
|
-
/* @__PURE__ */
|
|
1503
|
+
return /* @__PURE__ */ jsxs7(Stack5, { space: 3, children: [
|
|
1504
|
+
/* @__PURE__ */ jsx7(MirrorBanner, { origin }),
|
|
1189
1505
|
props.renderDefault(props)
|
|
1190
1506
|
] });
|
|
1191
1507
|
}
|
|
1192
1508
|
|
|
1509
|
+
// src/components/ReleasePicker.tsx
|
|
1510
|
+
import { SearchIcon } from "@sanity/icons";
|
|
1511
|
+
import { Autocomplete, Badge as Badge2, Card as Card4, Flex as Flex5, Stack as Stack6, Text as Text7 } from "@sanity/ui";
|
|
1512
|
+
import { useCallback as useCallback4, useEffect, useMemo as useMemo2, useRef } from "react";
|
|
1513
|
+
import {
|
|
1514
|
+
getReleaseIdFromReleaseDocumentId as getReleaseIdFromReleaseDocumentId2,
|
|
1515
|
+
PatchEvent,
|
|
1516
|
+
set,
|
|
1517
|
+
unset,
|
|
1518
|
+
useActiveReleases as useActiveReleases2,
|
|
1519
|
+
useArchivedReleases as useArchivedReleases2,
|
|
1520
|
+
useFormCallbacks
|
|
1521
|
+
} from "sanity";
|
|
1522
|
+
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1523
|
+
function StateBadge({ state }) {
|
|
1524
|
+
const tone = state === "active" ? "positive" : state === "published" ? "primary" : "default";
|
|
1525
|
+
return /* @__PURE__ */ jsx8(Badge2, { fontSize: 0, tone, children: state });
|
|
1526
|
+
}
|
|
1527
|
+
function ReleasePicker(props) {
|
|
1528
|
+
const { onChange, path, value = "" } = props;
|
|
1529
|
+
const { data: activeReleases } = useActiveReleases2();
|
|
1530
|
+
const { data: archivedReleases } = useArchivedReleases2();
|
|
1531
|
+
const { onChange: formOnChange } = useFormCallbacks();
|
|
1532
|
+
const titlePath = useMemo2(
|
|
1533
|
+
() => [...path.slice(0, -1), "perspectiveTitle"],
|
|
1534
|
+
[path]
|
|
1535
|
+
);
|
|
1536
|
+
const options = useMemo2(() => {
|
|
1537
|
+
const releases = [
|
|
1538
|
+
...(activeReleases ?? []).map((r) => ({ ...r, _state: "active" })),
|
|
1539
|
+
...(archivedReleases ?? []).map((r) => ({ ...r, _state: "archived" }))
|
|
1540
|
+
];
|
|
1541
|
+
const result = releases.map((release) => {
|
|
1542
|
+
const releaseId = getReleaseIdFromReleaseDocumentId2(release._id);
|
|
1543
|
+
const title = release.metadata?.title ?? releaseId;
|
|
1544
|
+
const state = release.state ?? release._state ?? "unknown";
|
|
1545
|
+
return {
|
|
1546
|
+
payload: { state: String(state), title },
|
|
1547
|
+
value: releaseId
|
|
1548
|
+
};
|
|
1549
|
+
}).sort((a, b) => {
|
|
1550
|
+
if (a.payload.state === "active" && b.payload.state !== "active")
|
|
1551
|
+
return -1;
|
|
1552
|
+
if (a.payload.state !== "active" && b.payload.state === "active")
|
|
1553
|
+
return 1;
|
|
1554
|
+
return a.payload.title.localeCompare(b.payload.title);
|
|
1555
|
+
});
|
|
1556
|
+
return result;
|
|
1557
|
+
}, [activeReleases, archivedReleases]);
|
|
1558
|
+
const hasSynced = useRef(false);
|
|
1559
|
+
useEffect(() => {
|
|
1560
|
+
if (hasSynced.current || !value || options.length === 0) return;
|
|
1561
|
+
const match = options.find((o) => o.value === value);
|
|
1562
|
+
if (match && match.payload.title !== value) {
|
|
1563
|
+
hasSynced.current = true;
|
|
1564
|
+
formOnChange(PatchEvent.from(set(match.payload.title, titlePath)));
|
|
1565
|
+
}
|
|
1566
|
+
}, [value, options, formOnChange, titlePath]);
|
|
1567
|
+
const handleChange = useCallback4(
|
|
1568
|
+
(newValue) => {
|
|
1569
|
+
if (newValue) {
|
|
1570
|
+
onChange(set(newValue));
|
|
1571
|
+
const option = options.find((o) => o.value === newValue);
|
|
1572
|
+
const title = option?.payload.title ?? newValue;
|
|
1573
|
+
formOnChange(PatchEvent.from(set(title, titlePath)));
|
|
1574
|
+
} else {
|
|
1575
|
+
onChange(unset());
|
|
1576
|
+
formOnChange(PatchEvent.from(unset(titlePath)));
|
|
1577
|
+
}
|
|
1578
|
+
},
|
|
1579
|
+
[onChange, formOnChange, titlePath, options]
|
|
1580
|
+
);
|
|
1581
|
+
return /* @__PURE__ */ jsxs8(Stack6, { space: 2, children: [
|
|
1582
|
+
/* @__PURE__ */ jsx8(
|
|
1583
|
+
Autocomplete,
|
|
1584
|
+
{
|
|
1585
|
+
filterOption: (query, option) => {
|
|
1586
|
+
const q = query.toLowerCase();
|
|
1587
|
+
const opt = option;
|
|
1588
|
+
return opt.value.toLowerCase().includes(q) || (opt.payload?.title ?? "").toLowerCase().includes(q);
|
|
1589
|
+
},
|
|
1590
|
+
icon: SearchIcon,
|
|
1591
|
+
id: "canonical-doc-release-picker",
|
|
1592
|
+
onChange: handleChange,
|
|
1593
|
+
openButton: true,
|
|
1594
|
+
options,
|
|
1595
|
+
placeholder: "Search releases by title or ID\u2026",
|
|
1596
|
+
renderOption: (option) => {
|
|
1597
|
+
const opt = option;
|
|
1598
|
+
return /* @__PURE__ */ jsx8(Card4, { as: "button", padding: 3, children: /* @__PURE__ */ jsxs8(Flex5, { align: "center", gap: 2, children: [
|
|
1599
|
+
/* @__PURE__ */ jsxs8(Stack6, { flex: 1, space: 1, children: [
|
|
1600
|
+
/* @__PURE__ */ jsx8(Text7, { size: 1, weight: "semibold", children: opt.payload.title }),
|
|
1601
|
+
opt.payload.title !== opt.value && /* @__PURE__ */ jsx8(Text7, { muted: true, size: 1, children: opt.value })
|
|
1602
|
+
] }),
|
|
1603
|
+
/* @__PURE__ */ jsx8(StateBadge, { state: opt.payload.state })
|
|
1604
|
+
] }) });
|
|
1605
|
+
},
|
|
1606
|
+
renderValue: (_v, option) => {
|
|
1607
|
+
const opt = option;
|
|
1608
|
+
return opt?.payload?.title ?? _v;
|
|
1609
|
+
},
|
|
1610
|
+
value
|
|
1611
|
+
}
|
|
1612
|
+
),
|
|
1613
|
+
value && /* @__PURE__ */ jsxs8(Text7, { muted: true, size: 0, children: [
|
|
1614
|
+
"Release ID: ",
|
|
1615
|
+
/* @__PURE__ */ jsx8("code", { children: value })
|
|
1616
|
+
] })
|
|
1617
|
+
] });
|
|
1618
|
+
}
|
|
1619
|
+
|
|
1193
1620
|
// src/schema/task.ts
|
|
1194
1621
|
var ASSERTION_TYPES = [
|
|
1195
1622
|
{ title: "LLM Rubric", value: "llm-rubric" },
|
|
@@ -1205,18 +1632,28 @@ var ASSERTION_TYPES = [
|
|
|
1205
1632
|
{ title: "Cost Constraint", value: "cost" },
|
|
1206
1633
|
{ title: "Latency Constraint", value: "latency" }
|
|
1207
1634
|
];
|
|
1635
|
+
var DOC_REF_TYPES = [
|
|
1636
|
+
{ title: "Document", value: "id" },
|
|
1637
|
+
{ title: "Content Release", value: "perspective" }
|
|
1638
|
+
];
|
|
1208
1639
|
var RUBRIC_TEMPLATES = [
|
|
1209
1640
|
{ title: "Task Completion", value: "task-completion" },
|
|
1210
1641
|
{ title: "Code Correctness", value: "code-correctness" },
|
|
1211
1642
|
{ title: "Doc Coverage", value: "doc-coverage" }
|
|
1212
1643
|
];
|
|
1213
1644
|
var taskSchema = defineType5({
|
|
1645
|
+
groups: [
|
|
1646
|
+
{ name: "main", title: "Main", default: true },
|
|
1647
|
+
{ name: "optional", title: "Optional" },
|
|
1648
|
+
ALL_FIELDS_GROUP5
|
|
1649
|
+
],
|
|
1214
1650
|
fields: [
|
|
1215
1651
|
// -----------------------------------------------------------------------
|
|
1216
1652
|
// Identity
|
|
1217
1653
|
// -----------------------------------------------------------------------
|
|
1218
1654
|
defineField5({
|
|
1219
1655
|
description: "Unique task identifier (e.g., 'groq-blog-queries'). Used for CLI filtering (--task groq-blog-queries), score aggregation, and report linkage.",
|
|
1656
|
+
group: ["main", "all-fields"],
|
|
1220
1657
|
name: "id",
|
|
1221
1658
|
title: "Task ID",
|
|
1222
1659
|
type: "slug",
|
|
@@ -1229,16 +1666,30 @@ var taskSchema = defineType5({
|
|
|
1229
1666
|
}),
|
|
1230
1667
|
defineField5({
|
|
1231
1668
|
description: "Human-readable label shown in reports and Studio",
|
|
1669
|
+
group: ["main", "all-fields"],
|
|
1232
1670
|
name: "description",
|
|
1233
1671
|
title: "Description",
|
|
1234
1672
|
type: "string",
|
|
1235
1673
|
validation: (rule) => rule.required()
|
|
1236
1674
|
}),
|
|
1237
1675
|
// -----------------------------------------------------------------------
|
|
1676
|
+
// Task prompt
|
|
1677
|
+
// -----------------------------------------------------------------------
|
|
1678
|
+
defineField5({
|
|
1679
|
+
description: "The implementation prompt sent to the evaluated LLM. This is the user-facing request (e.g., 'Write GROQ queries for a blog app...'). Plain text or Markdown.",
|
|
1680
|
+
group: ["main", "all-fields"],
|
|
1681
|
+
name: "taskPrompt",
|
|
1682
|
+
rows: 10,
|
|
1683
|
+
title: "Task Prompt",
|
|
1684
|
+
type: "text",
|
|
1685
|
+
validation: (rule) => rule.required()
|
|
1686
|
+
}),
|
|
1687
|
+
// -----------------------------------------------------------------------
|
|
1238
1688
|
// Classification
|
|
1239
1689
|
// -----------------------------------------------------------------------
|
|
1240
1690
|
defineField5({
|
|
1241
1691
|
description: "Feature area this task belongs to. Used for score aggregation and --area CLI filtering.",
|
|
1692
|
+
group: ["main", "all-fields"],
|
|
1242
1693
|
name: "featureArea",
|
|
1243
1694
|
title: "Feature Area",
|
|
1244
1695
|
to: [{ type: "ailf.featureArea" }],
|
|
@@ -1247,6 +1698,7 @@ var taskSchema = defineType5({
|
|
|
1247
1698
|
}),
|
|
1248
1699
|
defineField5({
|
|
1249
1700
|
description: "Freeform labels for filtering and organization",
|
|
1701
|
+
group: ["optional", "all-fields"],
|
|
1250
1702
|
name: "tags",
|
|
1251
1703
|
of: [{ type: "string" }],
|
|
1252
1704
|
title: "Tags",
|
|
@@ -1256,21 +1708,87 @@ var taskSchema = defineType5({
|
|
|
1256
1708
|
// Documentation references
|
|
1257
1709
|
// -----------------------------------------------------------------------
|
|
1258
1710
|
defineField5({
|
|
1259
|
-
description: "Documentation
|
|
1711
|
+
description: "Documentation that the LLM should use to complete this task. These become the gold-standard doc context injected in baseline mode. Each entry is either a single article document or a content release (whose articles are all included automatically).",
|
|
1712
|
+
group: ["main", "all-fields"],
|
|
1260
1713
|
name: "canonicalDocs",
|
|
1261
1714
|
of: [
|
|
1262
1715
|
{
|
|
1716
|
+
components: {
|
|
1717
|
+
input: CanonicalDocInput,
|
|
1718
|
+
preview: CanonicalDocPreview
|
|
1719
|
+
},
|
|
1263
1720
|
fields: [
|
|
1721
|
+
// Resolution type — drives conditional field visibility.
|
|
1722
|
+
// Stored as "slug" (Document) or "perspective" (Content Release).
|
|
1723
|
+
// Mirrored YAML tasks may carry "path" or "id" but those are
|
|
1724
|
+
// read-only in Studio and handled by the adapter.
|
|
1264
1725
|
defineField5({
|
|
1265
|
-
description: "
|
|
1726
|
+
description: "Document references a single article. Content Release includes all articles from a release.",
|
|
1727
|
+
name: "refType",
|
|
1728
|
+
options: {
|
|
1729
|
+
layout: "radio",
|
|
1730
|
+
direction: "horizontal",
|
|
1731
|
+
list: [...DOC_REF_TYPES]
|
|
1732
|
+
},
|
|
1733
|
+
title: "Resolution Type",
|
|
1734
|
+
type: "string",
|
|
1735
|
+
initialValue: "id",
|
|
1736
|
+
validation: (rule) => rule.required()
|
|
1737
|
+
}),
|
|
1738
|
+
// --- Article reference (Document mode) ---
|
|
1739
|
+
defineField5({
|
|
1740
|
+
description: "The article this canonical doc entry points to. The pipeline resolves the slug, path, and _id from this reference.",
|
|
1741
|
+
hidden: ({ parent }) => parent?.refType === "perspective",
|
|
1266
1742
|
name: "doc",
|
|
1267
1743
|
title: "Document",
|
|
1268
1744
|
to: [{ type: "article" }],
|
|
1269
|
-
type: "reference"
|
|
1270
|
-
|
|
1745
|
+
type: "reference"
|
|
1746
|
+
}),
|
|
1747
|
+
// --- Path (hidden — only populated by mirrored YAML tasks) ---
|
|
1748
|
+
defineField5({
|
|
1749
|
+
description: "Full path after /docs/ (e.g. 'groq/groq-introduction'). Populated automatically for mirrored YAML/repo tasks with refType 'path'. Not shown in Studio \u2014 the pipeline derives the path from the doc reference when needed.",
|
|
1750
|
+
hidden: true,
|
|
1751
|
+
name: "path",
|
|
1752
|
+
title: "Document Path",
|
|
1753
|
+
type: "string"
|
|
1754
|
+
}),
|
|
1755
|
+
// --- Document ID (hidden — only populated by mirrored YAML tasks) ---
|
|
1756
|
+
defineField5({
|
|
1757
|
+
description: "Sanity document _id. Populated automatically for mirrored YAML/repo tasks with refType 'id'. Not shown in Studio \u2014 the pipeline reads the _id from the doc reference.",
|
|
1758
|
+
hidden: true,
|
|
1759
|
+
name: "docId",
|
|
1760
|
+
title: "Document ID",
|
|
1761
|
+
type: "string"
|
|
1762
|
+
}),
|
|
1763
|
+
// --- Perspective resolution ---
|
|
1764
|
+
defineField5({
|
|
1765
|
+
components: {
|
|
1766
|
+
input: ReleasePicker
|
|
1767
|
+
},
|
|
1768
|
+
description: "Content release name (e.g. 'bundle-chatbox-launch'). All articles in this release are included as canonical docs. The pipeline auto-discovers articles at evaluation time.",
|
|
1769
|
+
hidden: ({ parent }) => parent?.refType !== "perspective",
|
|
1770
|
+
name: "perspective",
|
|
1771
|
+
title: "Content Release",
|
|
1772
|
+
type: "string",
|
|
1773
|
+
validation: (rule) => rule.custom((value, context) => {
|
|
1774
|
+
const parent = context.parent;
|
|
1775
|
+
if (parent?.refType === "perspective" && !value) {
|
|
1776
|
+
return "Content release ID is required for perspective resolution";
|
|
1777
|
+
}
|
|
1778
|
+
return true;
|
|
1779
|
+
})
|
|
1780
|
+
}),
|
|
1781
|
+
// --- Perspective title (hidden — populated by ReleasePicker) ---
|
|
1782
|
+
defineField5({
|
|
1783
|
+
description: "Human-readable title of the selected content release. Populated automatically by the release picker \u2014 used for list preview only, not by the pipeline.",
|
|
1784
|
+
hidden: true,
|
|
1785
|
+
name: "perspectiveTitle",
|
|
1786
|
+
title: "Release Title",
|
|
1787
|
+
type: "string"
|
|
1271
1788
|
}),
|
|
1789
|
+
// --- Reason (always visible) ---
|
|
1272
1790
|
defineField5({
|
|
1273
|
-
description: "Why this
|
|
1791
|
+
description: "Why this documentation helps with the task",
|
|
1274
1792
|
name: "reason",
|
|
1275
1793
|
title: "Reason",
|
|
1276
1794
|
type: "string"
|
|
@@ -1278,14 +1796,13 @@ var taskSchema = defineType5({
|
|
|
1278
1796
|
],
|
|
1279
1797
|
name: "canonicalDocRef",
|
|
1280
1798
|
preview: {
|
|
1281
|
-
prepare({ reason, title }) {
|
|
1282
|
-
return {
|
|
1283
|
-
subtitle: typeof reason === "string" ? reason : "",
|
|
1284
|
-
title: typeof title === "string" ? title : "Document"
|
|
1285
|
-
};
|
|
1286
|
-
},
|
|
1287
1799
|
select: {
|
|
1800
|
+
path: "path",
|
|
1801
|
+
perspective: "perspective",
|
|
1802
|
+
perspectiveTitle: "perspectiveTitle",
|
|
1288
1803
|
reason: "reason",
|
|
1804
|
+
refType: "refType",
|
|
1805
|
+
slug: "doc.slug.current",
|
|
1289
1806
|
title: "doc.title"
|
|
1290
1807
|
}
|
|
1291
1808
|
},
|
|
@@ -1298,34 +1815,26 @@ var taskSchema = defineType5({
|
|
|
1298
1815
|
}),
|
|
1299
1816
|
defineField5({
|
|
1300
1817
|
description: "Gold-standard implementation that demonstrates the correct approach",
|
|
1818
|
+
group: ["optional", "all-fields"],
|
|
1301
1819
|
name: "referenceSolution",
|
|
1302
1820
|
title: "Reference Solution",
|
|
1303
1821
|
to: [{ type: "ailf.referenceSolution" }],
|
|
1304
1822
|
type: "reference"
|
|
1305
1823
|
}),
|
|
1306
|
-
// -----------------------------------------------------------------------
|
|
1307
|
-
// Task prompt
|
|
1308
|
-
// -----------------------------------------------------------------------
|
|
1309
1824
|
defineField5({
|
|
1310
1825
|
description: "Auto-generate a doc-coverage rubric assertion. When true, the pipeline adds a doc-coverage assertion that checks whether the LLM's output reflects the content of the canonical documents.",
|
|
1826
|
+
group: ["optional", "all-fields"],
|
|
1311
1827
|
initialValue: false,
|
|
1312
1828
|
name: "docCoverage",
|
|
1313
1829
|
title: "Doc Coverage",
|
|
1314
1830
|
type: "boolean"
|
|
1315
1831
|
}),
|
|
1316
|
-
defineField5({
|
|
1317
|
-
description: "The implementation prompt sent to the evaluated LLM. This is the user-facing request (e.g., 'Write GROQ queries for a blog app...'). Plain text or Markdown \u2014 consumed as a raw string by the evaluation harness, not rendered by Studio.",
|
|
1318
|
-
name: "taskPrompt",
|
|
1319
|
-
rows: 10,
|
|
1320
|
-
title: "Task Prompt",
|
|
1321
|
-
type: "text",
|
|
1322
|
-
validation: (rule) => rule.required()
|
|
1323
|
-
}),
|
|
1324
1832
|
// -----------------------------------------------------------------------
|
|
1325
1833
|
// Assertions (grading criteria)
|
|
1326
1834
|
// -----------------------------------------------------------------------
|
|
1327
1835
|
defineField5({
|
|
1328
1836
|
description: "Grading criteria for evaluating the LLM's output. At least one assertion is required. Use llm-rubric with a template for scored evaluation, or value-based assertions for exact checks.",
|
|
1837
|
+
group: ["main", "all-fields"],
|
|
1329
1838
|
name: "assert",
|
|
1330
1839
|
of: [
|
|
1331
1840
|
{
|
|
@@ -1386,6 +1895,9 @@ var taskSchema = defineType5({
|
|
|
1386
1895
|
type: "number"
|
|
1387
1896
|
})
|
|
1388
1897
|
],
|
|
1898
|
+
components: {
|
|
1899
|
+
input: AssertionInput
|
|
1900
|
+
},
|
|
1389
1901
|
name: "assertion",
|
|
1390
1902
|
preview: {
|
|
1391
1903
|
prepare({
|
|
@@ -1423,6 +1935,7 @@ var taskSchema = defineType5({
|
|
|
1423
1935
|
// -----------------------------------------------------------------------
|
|
1424
1936
|
defineField5({
|
|
1425
1937
|
description: "Advanced: Raw Promptfoo assertion objects that bypass AILF's curated type validation and template resolution. These are appended directly to the expanded Promptfoo test case. Use for edge cases where the curated assertion types are insufficient.",
|
|
1938
|
+
group: ["optional", "all-fields"],
|
|
1426
1939
|
name: "rawAssert",
|
|
1427
1940
|
of: [
|
|
1428
1941
|
{
|
|
@@ -1460,6 +1973,7 @@ var taskSchema = defineType5({
|
|
|
1460
1973
|
// -----------------------------------------------------------------------
|
|
1461
1974
|
defineField5({
|
|
1462
1975
|
description: "Controls baseline variant generation. The baseline measures the LLM's performance without documentation (training data only).",
|
|
1976
|
+
group: ["optional", "all-fields"],
|
|
1463
1977
|
fields: [
|
|
1464
1978
|
defineField5({
|
|
1465
1979
|
description: "Generate a baseline variant (default: true)",
|
|
@@ -1496,6 +2010,7 @@ var taskSchema = defineType5({
|
|
|
1496
2010
|
// -----------------------------------------------------------------------
|
|
1497
2011
|
defineField5({
|
|
1498
2012
|
description: "Controls when and how this task runs in the pipeline. Tasks without execution controls use defaults: enabled, blocking, no filters, no threshold.",
|
|
2013
|
+
group: ["optional", "all-fields"],
|
|
1499
2014
|
fields: [
|
|
1500
2015
|
defineField5({
|
|
1501
2016
|
description: "Skip this task when false (default: true)",
|
|
@@ -1594,29 +2109,6 @@ var taskSchema = defineType5({
|
|
|
1594
2109
|
},
|
|
1595
2110
|
title: "Threshold",
|
|
1596
2111
|
type: "object"
|
|
1597
|
-
}),
|
|
1598
|
-
defineField5({
|
|
1599
|
-
description: "Doc source override \u2014 evaluate this task against a different source than the pipeline default (e.g., a branch deploy URL)",
|
|
1600
|
-
fields: [
|
|
1601
|
-
defineField5({
|
|
1602
|
-
name: "url",
|
|
1603
|
-
title: "URL",
|
|
1604
|
-
type: "url"
|
|
1605
|
-
}),
|
|
1606
|
-
defineField5({
|
|
1607
|
-
description: "Content release perspective ID",
|
|
1608
|
-
name: "perspective",
|
|
1609
|
-
title: "Perspective",
|
|
1610
|
-
type: "string"
|
|
1611
|
-
})
|
|
1612
|
-
],
|
|
1613
|
-
name: "source",
|
|
1614
|
-
options: {
|
|
1615
|
-
collapsible: true,
|
|
1616
|
-
collapsed: true
|
|
1617
|
-
},
|
|
1618
|
-
title: "Source Override",
|
|
1619
|
-
type: "object"
|
|
1620
2112
|
})
|
|
1621
2113
|
],
|
|
1622
2114
|
name: "execution",
|
|
@@ -1632,6 +2124,7 @@ var taskSchema = defineType5({
|
|
|
1632
2124
|
// -----------------------------------------------------------------------
|
|
1633
2125
|
defineField5({
|
|
1634
2126
|
description: "Source repo provenance for mirrored tasks. This field is populated automatically when the pipeline mirrors repo-based tasks into the Content Lake. Read-only \u2014 the source of truth is the repo.",
|
|
2127
|
+
group: ["optional", "all-fields"],
|
|
1635
2128
|
fields: [
|
|
1636
2129
|
defineField5({
|
|
1637
2130
|
name: "type",
|
|
@@ -1751,11 +2244,17 @@ var taskSchema = defineType5({
|
|
|
1751
2244
|
});
|
|
1752
2245
|
|
|
1753
2246
|
// src/schema/webhook-config.ts
|
|
1754
|
-
import { defineField as defineField6, defineType as defineType6 } from "sanity";
|
|
2247
|
+
import { ALL_FIELDS_GROUP as ALL_FIELDS_GROUP6, defineField as defineField6, defineType as defineType6 } from "sanity";
|
|
1755
2248
|
var webhookConfigSchema = defineType6({
|
|
2249
|
+
groups: [
|
|
2250
|
+
{ name: "main", title: "Main", default: true },
|
|
2251
|
+
{ name: "optional", title: "Optional" },
|
|
2252
|
+
ALL_FIELDS_GROUP6
|
|
2253
|
+
],
|
|
1756
2254
|
fields: [
|
|
1757
2255
|
defineField6({
|
|
1758
2256
|
description: "When enabled, publishing articles will automatically trigger AI Literacy evaluations for affected feature areas.",
|
|
2257
|
+
group: ["main", "all-fields"],
|
|
1759
2258
|
initialValue: false,
|
|
1760
2259
|
name: "enabled",
|
|
1761
2260
|
title: "Evaluate on Publish",
|
|
@@ -1763,6 +2262,7 @@ var webhookConfigSchema = defineType6({
|
|
|
1763
2262
|
}),
|
|
1764
2263
|
defineField6({
|
|
1765
2264
|
description: "Which evaluation mode to use for webhook-triggered evaluations.",
|
|
2265
|
+
group: ["main", "all-fields"],
|
|
1766
2266
|
initialValue: "baseline",
|
|
1767
2267
|
name: "mode",
|
|
1768
2268
|
options: {
|
|
@@ -1778,6 +2278,7 @@ var webhookConfigSchema = defineType6({
|
|
|
1778
2278
|
}),
|
|
1779
2279
|
defineField6({
|
|
1780
2280
|
description: "Maximum evaluations per day. Prevents runaway costs from rapid editing.",
|
|
2281
|
+
group: ["main", "all-fields"],
|
|
1781
2282
|
initialValue: 20,
|
|
1782
2283
|
name: "dailyBudget",
|
|
1783
2284
|
title: "Daily Budget",
|
|
@@ -1786,6 +2287,7 @@ var webhookConfigSchema = defineType6({
|
|
|
1786
2287
|
}),
|
|
1787
2288
|
defineField6({
|
|
1788
2289
|
description: "Seconds to wait after the last edit before dispatching. Coalesces rapid edits into a single evaluation.",
|
|
2290
|
+
group: ["optional", "all-fields"],
|
|
1789
2291
|
initialValue: 300,
|
|
1790
2292
|
name: "debounceSeconds",
|
|
1791
2293
|
title: "Debounce Window (seconds)",
|
|
@@ -1794,6 +2296,7 @@ var webhookConfigSchema = defineType6({
|
|
|
1794
2296
|
}),
|
|
1795
2297
|
defineField6({
|
|
1796
2298
|
description: "Specific feature areas to evaluate. Leave empty to evaluate all affected areas automatically.",
|
|
2299
|
+
group: ["optional", "all-fields"],
|
|
1797
2300
|
name: "areas",
|
|
1798
2301
|
of: [{ type: "string" }],
|
|
1799
2302
|
title: "Area Filter",
|
|
@@ -1801,6 +2304,7 @@ var webhookConfigSchema = defineType6({
|
|
|
1801
2304
|
}),
|
|
1802
2305
|
defineField6({
|
|
1803
2306
|
description: "Slack webhook URL for notifications about webhook-triggered evaluations.",
|
|
2307
|
+
group: ["optional", "all-fields"],
|
|
1804
2308
|
name: "notifySlack",
|
|
1805
2309
|
title: "Slack Notification URL",
|
|
1806
2310
|
type: "url"
|
|
@@ -1829,15 +2333,15 @@ import { route } from "sanity/router";
|
|
|
1829
2333
|
// src/components/Dashboard.tsx
|
|
1830
2334
|
import {
|
|
1831
2335
|
Container,
|
|
1832
|
-
Flex as
|
|
2336
|
+
Flex as Flex24,
|
|
1833
2337
|
Select as Select3,
|
|
1834
|
-
Stack as
|
|
2338
|
+
Stack as Stack24,
|
|
1835
2339
|
Tab,
|
|
1836
2340
|
TabList,
|
|
1837
2341
|
TabPanel,
|
|
1838
|
-
Text as
|
|
2342
|
+
Text as Text32
|
|
1839
2343
|
} from "@sanity/ui";
|
|
1840
|
-
import { useCallback as
|
|
2344
|
+
import { useCallback as useCallback14, useEffect as useEffect9, useState as useState10 } from "react";
|
|
1841
2345
|
import { useClient as useClient8 } from "sanity";
|
|
1842
2346
|
import { useRouter } from "sanity/router";
|
|
1843
2347
|
|
|
@@ -2082,8 +2586,8 @@ function filterSourceClause(param) {
|
|
|
2082
2586
|
}
|
|
2083
2587
|
|
|
2084
2588
|
// src/components/ComparisonView.tsx
|
|
2085
|
-
import { Badge as
|
|
2086
|
-
import { useCallback as
|
|
2589
|
+
import { Badge as Badge3, Box as Box7, Card as Card6, Flex as Flex7, Grid, Select, Stack as Stack8, Text as Text11 } from "@sanity/ui";
|
|
2590
|
+
import { useCallback as useCallback5, useEffect as useEffect2, useMemo as useMemo3, useState as useState2 } from "react";
|
|
2087
2591
|
import { useClient as useClient2 } from "sanity";
|
|
2088
2592
|
|
|
2089
2593
|
// src/glossary.ts
|
|
@@ -2163,11 +2667,11 @@ function scoreMap(summary) {
|
|
|
2163
2667
|
return new Map(summary.scores.map((s) => [s.feature, s]));
|
|
2164
2668
|
}
|
|
2165
2669
|
function allAreas(baseline, experiment) {
|
|
2166
|
-
const
|
|
2670
|
+
const set2 = /* @__PURE__ */ new Set([
|
|
2167
2671
|
...baseline.scores.map((s) => s.feature),
|
|
2168
2672
|
...experiment.scores.map((s) => s.feature)
|
|
2169
2673
|
]);
|
|
2170
|
-
return [...
|
|
2674
|
+
return [...set2].sort();
|
|
2171
2675
|
}
|
|
2172
2676
|
function classify(delta) {
|
|
2173
2677
|
if (delta >= NOISE_THRESHOLD) return "improved";
|
|
@@ -2277,16 +2781,16 @@ function formatDuration(ms) {
|
|
|
2277
2781
|
}
|
|
2278
2782
|
|
|
2279
2783
|
// src/components/PageBlurb.tsx
|
|
2280
|
-
import { Card as
|
|
2281
|
-
import { jsx as
|
|
2784
|
+
import { Card as Card5, Stack as Stack7, Text as Text8 } from "@sanity/ui";
|
|
2785
|
+
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
2282
2786
|
function PageBlurb({ text }) {
|
|
2283
|
-
return /* @__PURE__ */
|
|
2787
|
+
return /* @__PURE__ */ jsx9(Card5, { padding: 3, radius: 2, tone: "transparent", children: /* @__PURE__ */ jsx9(Stack7, { space: 2, children: /* @__PURE__ */ jsx9(Text8, { size: 1, children: text }) }) });
|
|
2284
2788
|
}
|
|
2285
2789
|
|
|
2286
2790
|
// src/components/primitives/ColumnHeader.tsx
|
|
2287
|
-
import { HelpCircleIcon } from "@sanity/icons";
|
|
2288
|
-
import { Box as
|
|
2289
|
-
import { jsx as
|
|
2791
|
+
import { HelpCircleIcon as HelpCircleIcon3 } from "@sanity/icons";
|
|
2792
|
+
import { Box as Box5, Flex as Flex6, Text as Text9, Tooltip as Tooltip2 } from "@sanity/ui";
|
|
2793
|
+
import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
2290
2794
|
function ColumnHeader({
|
|
2291
2795
|
label,
|
|
2292
2796
|
tooltip,
|
|
@@ -2296,9 +2800,9 @@ function ColumnHeader({
|
|
|
2296
2800
|
borderBottom: "1px solid var(--card-border-color)",
|
|
2297
2801
|
paddingBottom: 6
|
|
2298
2802
|
} : void 0;
|
|
2299
|
-
return /* @__PURE__ */
|
|
2300
|
-
/* @__PURE__ */
|
|
2301
|
-
|
|
2803
|
+
return /* @__PURE__ */ jsxs9(Flex6, { align: "center", gap: 1, style, children: [
|
|
2804
|
+
/* @__PURE__ */ jsx10(
|
|
2805
|
+
Text9,
|
|
2302
2806
|
{
|
|
2303
2807
|
muted: true,
|
|
2304
2808
|
size: 1,
|
|
@@ -2307,26 +2811,26 @@ function ColumnHeader({
|
|
|
2307
2811
|
children: label
|
|
2308
2812
|
}
|
|
2309
2813
|
),
|
|
2310
|
-
tooltip && /* @__PURE__ */
|
|
2814
|
+
tooltip && /* @__PURE__ */ jsx10(
|
|
2311
2815
|
Tooltip2,
|
|
2312
2816
|
{
|
|
2313
|
-
content: /* @__PURE__ */
|
|
2817
|
+
content: /* @__PURE__ */ jsx10(Box5, { padding: 2, children: /* @__PURE__ */ jsx10(Text9, { size: 1, children: tooltip }) }),
|
|
2314
2818
|
portal: true,
|
|
2315
|
-
children: /* @__PURE__ */
|
|
2819
|
+
children: /* @__PURE__ */ jsx10(Text9, { muted: true, size: 0, children: /* @__PURE__ */ jsx10(HelpCircleIcon3, {}) })
|
|
2316
2820
|
}
|
|
2317
2821
|
)
|
|
2318
2822
|
] });
|
|
2319
2823
|
}
|
|
2320
2824
|
|
|
2321
2825
|
// src/components/primitives/LoadingState.tsx
|
|
2322
|
-
import { Box as
|
|
2323
|
-
import { jsx as
|
|
2826
|
+
import { Box as Box6, Text as Text10 } from "@sanity/ui";
|
|
2827
|
+
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
2324
2828
|
function LoadingState({ message = "Loading\u2026" }) {
|
|
2325
|
-
return /* @__PURE__ */
|
|
2829
|
+
return /* @__PURE__ */ jsx11(Box6, { padding: 4, children: /* @__PURE__ */ jsx11(Text10, { muted: true, children: message }) });
|
|
2326
2830
|
}
|
|
2327
2831
|
|
|
2328
2832
|
// src/components/ComparisonView.tsx
|
|
2329
|
-
import { Fragment, jsx as
|
|
2833
|
+
import { Fragment as Fragment3, jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
2330
2834
|
function ComparisonView() {
|
|
2331
2835
|
const client = useClient2({ apiVersion: API_VERSION });
|
|
2332
2836
|
const [baselineId, setBaselineId] = useState2(null);
|
|
@@ -2337,14 +2841,14 @@ function ComparisonView() {
|
|
|
2337
2841
|
const [experimentSummary, setExperimentSummary] = useState2(null);
|
|
2338
2842
|
const [loading, setLoading] = useState2(false);
|
|
2339
2843
|
const [reports, setReports] = useState2([]);
|
|
2340
|
-
|
|
2844
|
+
useEffect2(() => {
|
|
2341
2845
|
client.fetch(latestReportsQuery, {
|
|
2342
2846
|
limit: 50,
|
|
2343
2847
|
mode: null,
|
|
2344
2848
|
source: null
|
|
2345
2849
|
}).then((data) => setReports(data ?? [])).catch(() => setReports([]));
|
|
2346
2850
|
}, [client]);
|
|
2347
|
-
|
|
2851
|
+
useEffect2(() => {
|
|
2348
2852
|
if (!baselineId || !experimentId) {
|
|
2349
2853
|
setBaselineSummary(null);
|
|
2350
2854
|
setExperimentSummary(null);
|
|
@@ -2365,75 +2869,75 @@ function ComparisonView() {
|
|
|
2365
2869
|
setLoading(false);
|
|
2366
2870
|
});
|
|
2367
2871
|
}, [baselineId, client, experimentId]);
|
|
2368
|
-
const baselineOptions =
|
|
2872
|
+
const baselineOptions = useMemo3(
|
|
2369
2873
|
() => reports.filter((r) => r.reportId !== experimentId),
|
|
2370
2874
|
[experimentId, reports]
|
|
2371
2875
|
);
|
|
2372
|
-
const experimentOptions =
|
|
2876
|
+
const experimentOptions = useMemo3(
|
|
2373
2877
|
() => reports.filter((r) => r.reportId !== baselineId),
|
|
2374
2878
|
[baselineId, reports]
|
|
2375
2879
|
);
|
|
2376
|
-
const areaDeltas =
|
|
2880
|
+
const areaDeltas = useMemo3(
|
|
2377
2881
|
() => baselineSummary && experimentSummary ? computeAreaDeltas(baselineSummary, experimentSummary) : [],
|
|
2378
2882
|
[baselineSummary, experimentSummary]
|
|
2379
2883
|
);
|
|
2380
|
-
const dimDeltas =
|
|
2884
|
+
const dimDeltas = useMemo3(
|
|
2381
2885
|
() => baselineSummary && experimentSummary ? computeDimensionDeltas(baselineSummary, experimentSummary) : [],
|
|
2382
2886
|
[baselineSummary, experimentSummary]
|
|
2383
2887
|
);
|
|
2384
|
-
const threeLayerDeltas =
|
|
2888
|
+
const threeLayerDeltas = useMemo3(
|
|
2385
2889
|
() => baselineSummary && experimentSummary ? computeThreeLayerDeltas(baselineSummary, experimentSummary) : [],
|
|
2386
2890
|
[baselineSummary, experimentSummary]
|
|
2387
2891
|
);
|
|
2388
2892
|
const hasThreeLayerData = threeLayerDeltas.some(
|
|
2389
2893
|
(d) => d.baseActual !== null || d.baseRetGap !== null
|
|
2390
2894
|
);
|
|
2391
|
-
const overallDelta =
|
|
2895
|
+
const overallDelta = useMemo3(() => {
|
|
2392
2896
|
if (!baselineSummary || !experimentSummary) return null;
|
|
2393
2897
|
const b = baselineSummary.overall.avgScore;
|
|
2394
2898
|
const e = experimentSummary.overall.avgScore;
|
|
2395
2899
|
return { baseline: b, delta: e - b, experiment: e };
|
|
2396
2900
|
}, [baselineSummary, experimentSummary]);
|
|
2397
|
-
const onBaseline =
|
|
2901
|
+
const onBaseline = useCallback5(
|
|
2398
2902
|
(e) => setBaselineId(e.currentTarget.value || null),
|
|
2399
2903
|
[]
|
|
2400
2904
|
);
|
|
2401
|
-
const onExperiment =
|
|
2905
|
+
const onExperiment = useCallback5(
|
|
2402
2906
|
(e) => setExperimentId(e.currentTarget.value || null),
|
|
2403
2907
|
[]
|
|
2404
2908
|
);
|
|
2405
2909
|
const hasBoth = baselineId && experimentId;
|
|
2406
2910
|
const hasData = baselineSummary && experimentSummary;
|
|
2407
|
-
return /* @__PURE__ */
|
|
2408
|
-
/* @__PURE__ */
|
|
2409
|
-
/* @__PURE__ */
|
|
2410
|
-
/* @__PURE__ */
|
|
2411
|
-
/* @__PURE__ */
|
|
2412
|
-
/* @__PURE__ */
|
|
2413
|
-
/* @__PURE__ */
|
|
2414
|
-
baselineOptions.map((r) => /* @__PURE__ */
|
|
2911
|
+
return /* @__PURE__ */ jsxs10(Stack8, { space: 4, children: [
|
|
2912
|
+
/* @__PURE__ */ jsx12(PageBlurb, { text: "Select two reports to compare." }),
|
|
2913
|
+
/* @__PURE__ */ jsxs10(Flex7, { gap: 3, children: [
|
|
2914
|
+
/* @__PURE__ */ jsx12(Box7, { flex: 1, children: /* @__PURE__ */ jsxs10(Stack8, { space: 2, children: [
|
|
2915
|
+
/* @__PURE__ */ jsx12(Text11, { size: 1, weight: "semibold", children: "Baseline (before)" }),
|
|
2916
|
+
/* @__PURE__ */ jsxs10(Select, { onChange: onBaseline, value: baselineId ?? "", children: [
|
|
2917
|
+
/* @__PURE__ */ jsx12("option", { value: "", children: "Select baseline\u2026" }),
|
|
2918
|
+
baselineOptions.map((r) => /* @__PURE__ */ jsx12("option", { value: r.reportId, children: formatOption(r) }, r.reportId))
|
|
2415
2919
|
] })
|
|
2416
2920
|
] }) }),
|
|
2417
|
-
/* @__PURE__ */
|
|
2418
|
-
/* @__PURE__ */
|
|
2419
|
-
/* @__PURE__ */
|
|
2420
|
-
/* @__PURE__ */
|
|
2421
|
-
experimentOptions.map((r) => /* @__PURE__ */
|
|
2921
|
+
/* @__PURE__ */ jsx12(Box7, { flex: 1, children: /* @__PURE__ */ jsxs10(Stack8, { space: 2, children: [
|
|
2922
|
+
/* @__PURE__ */ jsx12(Text11, { size: 1, weight: "semibold", children: "Experiment (after)" }),
|
|
2923
|
+
/* @__PURE__ */ jsxs10(Select, { onChange: onExperiment, value: experimentId ?? "", children: [
|
|
2924
|
+
/* @__PURE__ */ jsx12("option", { value: "", children: "Select experiment\u2026" }),
|
|
2925
|
+
experimentOptions.map((r) => /* @__PURE__ */ jsx12("option", { value: r.reportId, children: formatOption(r) }, r.reportId))
|
|
2422
2926
|
] })
|
|
2423
2927
|
] }) })
|
|
2424
2928
|
] }),
|
|
2425
|
-
hasBoth && loading && /* @__PURE__ */
|
|
2426
|
-
hasBoth && !loading && !hasData && /* @__PURE__ */
|
|
2427
|
-
hasBoth && !loading && hasData && /* @__PURE__ */
|
|
2428
|
-
/* @__PURE__ */
|
|
2929
|
+
hasBoth && loading && /* @__PURE__ */ jsx12(LoadingState, { message: "Loading comparison\u2026" }),
|
|
2930
|
+
hasBoth && !loading && !hasData && /* @__PURE__ */ jsx12(Card6, { padding: 4, tone: "caution", children: /* @__PURE__ */ jsx12(Text11, { size: 1, children: "Report not found." }) }),
|
|
2931
|
+
hasBoth && !loading && hasData && /* @__PURE__ */ jsxs10(Fragment3, { children: [
|
|
2932
|
+
/* @__PURE__ */ jsx12(
|
|
2429
2933
|
AreaComparisonTable,
|
|
2430
2934
|
{
|
|
2431
2935
|
areaDeltas,
|
|
2432
2936
|
overallDelta
|
|
2433
2937
|
}
|
|
2434
2938
|
),
|
|
2435
|
-
/* @__PURE__ */
|
|
2436
|
-
hasThreeLayerData && /* @__PURE__ */
|
|
2939
|
+
/* @__PURE__ */ jsx12(DimensionDeltasTable, { dimDeltas }),
|
|
2940
|
+
hasThreeLayerData && /* @__PURE__ */ jsx12(ThreeLayerDeltasTable, { threeLayerDeltas })
|
|
2437
2941
|
] })
|
|
2438
2942
|
] });
|
|
2439
2943
|
}
|
|
@@ -2441,23 +2945,23 @@ function AreaComparisonTable({
|
|
|
2441
2945
|
areaDeltas,
|
|
2442
2946
|
overallDelta
|
|
2443
2947
|
}) {
|
|
2444
|
-
return /* @__PURE__ */
|
|
2445
|
-
/* @__PURE__ */
|
|
2446
|
-
/* @__PURE__ */
|
|
2447
|
-
/* @__PURE__ */
|
|
2448
|
-
/* @__PURE__ */
|
|
2449
|
-
/* @__PURE__ */
|
|
2450
|
-
/* @__PURE__ */
|
|
2451
|
-
/* @__PURE__ */
|
|
2948
|
+
return /* @__PURE__ */ jsx12(Card6, { overflow: "auto", padding: 3, radius: 2, shadow: 1, children: /* @__PURE__ */ jsxs10(Stack8, { space: 3, children: [
|
|
2949
|
+
/* @__PURE__ */ jsx12(Text11, { size: 1, weight: "semibold", children: "Per-area comparison" }),
|
|
2950
|
+
/* @__PURE__ */ jsxs10(Grid, { columns: 5, gap: 2, children: [
|
|
2951
|
+
/* @__PURE__ */ jsx12(ColumnHeader, { label: "Area" }),
|
|
2952
|
+
/* @__PURE__ */ jsx12(ColumnHeader, { label: "Baseline", tooltip: GLOSSARY.baseline }),
|
|
2953
|
+
/* @__PURE__ */ jsx12(ColumnHeader, { label: "Experiment", tooltip: GLOSSARY.experiment }),
|
|
2954
|
+
/* @__PURE__ */ jsx12(ColumnHeader, { label: "Delta", tooltip: GLOSSARY.delta }),
|
|
2955
|
+
/* @__PURE__ */ jsx12(ColumnHeader, { label: "Change", tooltip: GLOSSARY.change })
|
|
2452
2956
|
] }),
|
|
2453
|
-
areaDeltas.map((row) => /* @__PURE__ */
|
|
2454
|
-
/* @__PURE__ */
|
|
2455
|
-
/* @__PURE__ */
|
|
2456
|
-
/* @__PURE__ */
|
|
2457
|
-
/* @__PURE__ */
|
|
2458
|
-
/* @__PURE__ */
|
|
2957
|
+
areaDeltas.map((row) => /* @__PURE__ */ jsxs10(Grid, { columns: 5, gap: 2, children: [
|
|
2958
|
+
/* @__PURE__ */ jsx12(Text11, { size: 1, children: row.area }),
|
|
2959
|
+
/* @__PURE__ */ jsx12(Text11, { size: 1, children: row.baseline.toFixed(1) }),
|
|
2960
|
+
/* @__PURE__ */ jsx12(Text11, { size: 1, children: row.experiment.toFixed(1) }),
|
|
2961
|
+
/* @__PURE__ */ jsx12(Text11, { size: 1, children: formatDelta(row.delta) }),
|
|
2962
|
+
/* @__PURE__ */ jsx12(Box7, { children: /* @__PURE__ */ jsx12(Badge3, { tone: changeTone(row.change), children: row.change }) })
|
|
2459
2963
|
] }, row.area)),
|
|
2460
|
-
overallDelta && /* @__PURE__ */
|
|
2964
|
+
overallDelta && /* @__PURE__ */ jsxs10(
|
|
2461
2965
|
Grid,
|
|
2462
2966
|
{
|
|
2463
2967
|
columns: 5,
|
|
@@ -2467,36 +2971,36 @@ function AreaComparisonTable({
|
|
|
2467
2971
|
paddingTop: 8
|
|
2468
2972
|
},
|
|
2469
2973
|
children: [
|
|
2470
|
-
/* @__PURE__ */
|
|
2471
|
-
/* @__PURE__ */
|
|
2472
|
-
/* @__PURE__ */
|
|
2473
|
-
/* @__PURE__ */
|
|
2474
|
-
/* @__PURE__ */
|
|
2974
|
+
/* @__PURE__ */ jsx12(Text11, { size: 1, weight: "semibold", children: "Overall" }),
|
|
2975
|
+
/* @__PURE__ */ jsx12(Text11, { size: 1, weight: "semibold", children: overallDelta.baseline.toFixed(1) }),
|
|
2976
|
+
/* @__PURE__ */ jsx12(Text11, { size: 1, weight: "semibold", children: overallDelta.experiment.toFixed(1) }),
|
|
2977
|
+
/* @__PURE__ */ jsx12(Text11, { size: 1, weight: "semibold", children: formatDelta(overallDelta.delta) }),
|
|
2978
|
+
/* @__PURE__ */ jsx12(Box7, { children: /* @__PURE__ */ jsx12(Badge3, { tone: changeTone(classify(overallDelta.delta)), children: classify(overallDelta.delta) }) })
|
|
2475
2979
|
]
|
|
2476
2980
|
}
|
|
2477
2981
|
)
|
|
2478
2982
|
] }) });
|
|
2479
2983
|
}
|
|
2480
2984
|
function DimensionDeltasTable({ dimDeltas }) {
|
|
2481
|
-
return /* @__PURE__ */
|
|
2482
|
-
/* @__PURE__ */
|
|
2483
|
-
/* @__PURE__ */
|
|
2484
|
-
/* @__PURE__ */
|
|
2485
|
-
/* @__PURE__ */
|
|
2985
|
+
return /* @__PURE__ */ jsx12(Card6, { overflow: "auto", padding: 3, radius: 2, shadow: 1, children: /* @__PURE__ */ jsxs10(Stack8, { space: 3, children: [
|
|
2986
|
+
/* @__PURE__ */ jsx12(Text11, { size: 1, weight: "semibold", children: "Dimension deltas" }),
|
|
2987
|
+
/* @__PURE__ */ jsxs10(Grid, { columns: 4, gap: 2, children: [
|
|
2988
|
+
/* @__PURE__ */ jsx12(ColumnHeader, { label: "Area" }),
|
|
2989
|
+
/* @__PURE__ */ jsx12(
|
|
2486
2990
|
ColumnHeader,
|
|
2487
2991
|
{
|
|
2488
2992
|
label: "Task completion",
|
|
2489
2993
|
tooltip: GLOSSARY.dimTaskCompletion
|
|
2490
2994
|
}
|
|
2491
2995
|
),
|
|
2492
|
-
/* @__PURE__ */
|
|
2996
|
+
/* @__PURE__ */ jsx12(
|
|
2493
2997
|
ColumnHeader,
|
|
2494
2998
|
{
|
|
2495
2999
|
label: "Code correctness",
|
|
2496
3000
|
tooltip: GLOSSARY.dimCodeCorrectness
|
|
2497
3001
|
}
|
|
2498
3002
|
),
|
|
2499
|
-
/* @__PURE__ */
|
|
3003
|
+
/* @__PURE__ */ jsx12(
|
|
2500
3004
|
ColumnHeader,
|
|
2501
3005
|
{
|
|
2502
3006
|
label: "Doc coverage",
|
|
@@ -2504,11 +3008,11 @@ function DimensionDeltasTable({ dimDeltas }) {
|
|
|
2504
3008
|
}
|
|
2505
3009
|
)
|
|
2506
3010
|
] }),
|
|
2507
|
-
dimDeltas.map((row) => /* @__PURE__ */
|
|
2508
|
-
/* @__PURE__ */
|
|
2509
|
-
/* @__PURE__ */
|
|
2510
|
-
/* @__PURE__ */
|
|
2511
|
-
/* @__PURE__ */
|
|
3011
|
+
dimDeltas.map((row) => /* @__PURE__ */ jsxs10(Grid, { columns: 4, gap: 2, children: [
|
|
3012
|
+
/* @__PURE__ */ jsx12(Text11, { size: 1, children: row.area }),
|
|
3013
|
+
/* @__PURE__ */ jsx12(Text11, { size: 1, children: formatDelta(row.taskDelta) }),
|
|
3014
|
+
/* @__PURE__ */ jsx12(Text11, { size: 1, children: formatDelta(row.codeDelta) }),
|
|
3015
|
+
/* @__PURE__ */ jsx12(Text11, { size: 1, children: formatDelta(row.docDelta) })
|
|
2512
3016
|
] }, row.area))
|
|
2513
3017
|
] }) });
|
|
2514
3018
|
}
|
|
@@ -2518,27 +3022,27 @@ function ThreeLayerDeltasTable({
|
|
|
2518
3022
|
const filtered = threeLayerDeltas.filter(
|
|
2519
3023
|
(d) => d.baseActual !== null || d.baseRetGap !== null
|
|
2520
3024
|
);
|
|
2521
|
-
return /* @__PURE__ */
|
|
2522
|
-
/* @__PURE__ */
|
|
2523
|
-
/* @__PURE__ */
|
|
2524
|
-
/* @__PURE__ */
|
|
3025
|
+
return /* @__PURE__ */ jsx12(Card6, { overflow: "auto", padding: 3, radius: 2, shadow: 1, children: /* @__PURE__ */ jsxs10(Stack8, { space: 3, children: [
|
|
3026
|
+
/* @__PURE__ */ jsxs10(Flex7, { align: "center", gap: 2, children: [
|
|
3027
|
+
/* @__PURE__ */ jsx12(Text11, { size: 1, weight: "semibold", children: "Three-layer decomposition deltas" }),
|
|
3028
|
+
/* @__PURE__ */ jsx12(Badge3, { fontSize: 0, tone: "primary", children: "full mode" })
|
|
2525
3029
|
] }),
|
|
2526
|
-
/* @__PURE__ */
|
|
2527
|
-
/* @__PURE__ */
|
|
2528
|
-
/* @__PURE__ */
|
|
2529
|
-
/* @__PURE__ */
|
|
2530
|
-
/* @__PURE__ */
|
|
2531
|
-
/* @__PURE__ */
|
|
2532
|
-
/* @__PURE__ */
|
|
2533
|
-
/* @__PURE__ */
|
|
3030
|
+
/* @__PURE__ */ jsxs10(Grid, { columns: 7, gap: 2, children: [
|
|
3031
|
+
/* @__PURE__ */ jsx12(ColumnHeader, { label: "Area" }),
|
|
3032
|
+
/* @__PURE__ */ jsx12(ColumnHeader, { label: "Actual (B)", tooltip: GLOSSARY.actual }),
|
|
3033
|
+
/* @__PURE__ */ jsx12(ColumnHeader, { label: "Actual (E)", tooltip: GLOSSARY.actual }),
|
|
3034
|
+
/* @__PURE__ */ jsx12(ColumnHeader, { label: "Actual \u0394", tooltip: GLOSSARY.actualDelta }),
|
|
3035
|
+
/* @__PURE__ */ jsx12(ColumnHeader, { label: "Ret. Gap \u0394", tooltip: GLOSSARY.retGapDelta }),
|
|
3036
|
+
/* @__PURE__ */ jsx12(ColumnHeader, { label: "Eff. (B)", tooltip: GLOSSARY.efficiency }),
|
|
3037
|
+
/* @__PURE__ */ jsx12(ColumnHeader, { label: "Eff. (E)", tooltip: GLOSSARY.efficiency })
|
|
2534
3038
|
] }),
|
|
2535
|
-
filtered.map((row) => /* @__PURE__ */
|
|
2536
|
-
/* @__PURE__ */
|
|
2537
|
-
/* @__PURE__ */
|
|
2538
|
-
/* @__PURE__ */
|
|
2539
|
-
/* @__PURE__ */
|
|
2540
|
-
/* @__PURE__ */
|
|
2541
|
-
|
|
3039
|
+
filtered.map((row) => /* @__PURE__ */ jsxs10(Grid, { columns: 7, gap: 2, children: [
|
|
3040
|
+
/* @__PURE__ */ jsx12(Text11, { size: 1, children: row.area }),
|
|
3041
|
+
/* @__PURE__ */ jsx12(Text11, { size: 1, children: row.baseActual != null ? row.baseActual.toFixed(1) : "\u2014" }),
|
|
3042
|
+
/* @__PURE__ */ jsx12(Text11, { size: 1, children: row.expActual != null ? row.expActual.toFixed(1) : "\u2014" }),
|
|
3043
|
+
/* @__PURE__ */ jsx12(Text11, { size: 1, children: row.actualDelta != null ? formatDelta(row.actualDelta) : "\u2014" }),
|
|
3044
|
+
/* @__PURE__ */ jsx12(
|
|
3045
|
+
Text11,
|
|
2542
3046
|
{
|
|
2543
3047
|
size: 1,
|
|
2544
3048
|
style: {
|
|
@@ -2547,8 +3051,8 @@ function ThreeLayerDeltasTable({
|
|
|
2547
3051
|
children: row.retGapDelta != null ? formatDelta(row.retGapDelta) : "\u2014"
|
|
2548
3052
|
}
|
|
2549
3053
|
),
|
|
2550
|
-
/* @__PURE__ */
|
|
2551
|
-
/* @__PURE__ */
|
|
3054
|
+
/* @__PURE__ */ jsx12(Text11, { size: 1, children: formatPercent(row.baseEfficiency) }),
|
|
3055
|
+
/* @__PURE__ */ jsx12(Text11, { size: 1, children: formatPercent(row.expEfficiency) })
|
|
2552
3056
|
] }, `tl-${row.area}`))
|
|
2553
3057
|
] }) });
|
|
2554
3058
|
}
|
|
@@ -2560,26 +3064,26 @@ function formatOption(r) {
|
|
|
2560
3064
|
// src/components/LatestReports.tsx
|
|
2561
3065
|
import { SortIcon } from "@sanity/icons";
|
|
2562
3066
|
import {
|
|
2563
|
-
Badge as
|
|
2564
|
-
Box as
|
|
3067
|
+
Badge as Badge12,
|
|
3068
|
+
Box as Box8,
|
|
2565
3069
|
Button,
|
|
2566
|
-
Card as
|
|
2567
|
-
Flex as
|
|
3070
|
+
Card as Card12,
|
|
3071
|
+
Flex as Flex16,
|
|
2568
3072
|
Menu,
|
|
2569
3073
|
MenuButton,
|
|
2570
3074
|
MenuItem,
|
|
2571
|
-
Stack as
|
|
2572
|
-
Text as
|
|
3075
|
+
Stack as Stack13,
|
|
3076
|
+
Text as Text20
|
|
2573
3077
|
} from "@sanity/ui";
|
|
2574
|
-
import { useCallback as
|
|
3078
|
+
import { useCallback as useCallback11, useEffect as useEffect6, useMemo as useMemo5, useState as useState6 } from "react";
|
|
2575
3079
|
import { useClient as useClient5 } from "sanity";
|
|
2576
3080
|
|
|
2577
3081
|
// src/components/content-filters/DocumentFilter.tsx
|
|
2578
|
-
import { SearchIcon } from "@sanity/icons";
|
|
2579
|
-
import { Autocomplete, Badge as
|
|
2580
|
-
import { useCallback as
|
|
3082
|
+
import { SearchIcon as SearchIcon2 } from "@sanity/icons";
|
|
3083
|
+
import { Autocomplete as Autocomplete2, Badge as Badge4, Card as Card7, Flex as Flex8, Stack as Stack9, Text as Text12 } from "@sanity/ui";
|
|
3084
|
+
import { useCallback as useCallback6, useEffect as useEffect3, useRef as useRef2, useState as useState3 } from "react";
|
|
2581
3085
|
import { useClient as useClient3 } from "sanity";
|
|
2582
|
-
import { jsx as
|
|
3086
|
+
import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
2583
3087
|
var SEARCH_DEBOUNCE_MS = 300;
|
|
2584
3088
|
function DocumentFilter({
|
|
2585
3089
|
value,
|
|
@@ -2589,13 +3093,13 @@ function DocumentFilter({
|
|
|
2589
3093
|
const client = useClient3({ apiVersion: API_VERSION });
|
|
2590
3094
|
const [options, setOptions] = useState3([]);
|
|
2591
3095
|
const [loading, setLoading] = useState3(false);
|
|
2592
|
-
const timer =
|
|
2593
|
-
|
|
3096
|
+
const timer = useRef2(null);
|
|
3097
|
+
useEffect3(() => {
|
|
2594
3098
|
return () => {
|
|
2595
3099
|
if (timer.current) clearTimeout(timer.current);
|
|
2596
3100
|
};
|
|
2597
3101
|
}, []);
|
|
2598
|
-
const handleQueryChange =
|
|
3102
|
+
const handleQueryChange = useCallback6(
|
|
2599
3103
|
(query) => {
|
|
2600
3104
|
if (timer.current) clearTimeout(timer.current);
|
|
2601
3105
|
const trimmed = (query ?? "").trim();
|
|
@@ -2639,7 +3143,7 @@ function DocumentFilter({
|
|
|
2639
3143
|
},
|
|
2640
3144
|
[client]
|
|
2641
3145
|
);
|
|
2642
|
-
const handleSelect =
|
|
3146
|
+
const handleSelect = useCallback6(
|
|
2643
3147
|
(selected) => {
|
|
2644
3148
|
const option = options.find((o) => o.value === selected);
|
|
2645
3149
|
const slug = option?.payload.slug ?? selected;
|
|
@@ -2650,29 +3154,29 @@ function DocumentFilter({
|
|
|
2650
3154
|
},
|
|
2651
3155
|
[options, onChange, onPerspectiveHint]
|
|
2652
3156
|
);
|
|
2653
|
-
const renderOption =
|
|
3157
|
+
const renderOption = useCallback6((option) => {
|
|
2654
3158
|
const { provenance, releaseId } = option.payload;
|
|
2655
3159
|
const badgeTone = provenance === "published" ? "positive" : provenance === "release" ? "primary" : "caution";
|
|
2656
3160
|
const badgeLabel = provenance === "published" ? "Published" : provenance === "release" ? releaseId ?? "Release" : "Draft";
|
|
2657
|
-
return /* @__PURE__ */
|
|
2658
|
-
/* @__PURE__ */
|
|
2659
|
-
/* @__PURE__ */
|
|
2660
|
-
/* @__PURE__ */
|
|
3161
|
+
return /* @__PURE__ */ jsx13(Card7, { as: "button", padding: 3, children: /* @__PURE__ */ jsxs11(Flex8, { align: "center", gap: 2, children: [
|
|
3162
|
+
/* @__PURE__ */ jsxs11(Stack9, { flex: 1, space: 1, children: [
|
|
3163
|
+
/* @__PURE__ */ jsx13(Text12, { size: 1, weight: "semibold", children: option.payload.title }),
|
|
3164
|
+
/* @__PURE__ */ jsx13(Text12, { muted: true, size: 1, children: option.payload.path })
|
|
2661
3165
|
] }),
|
|
2662
|
-
/* @__PURE__ */
|
|
3166
|
+
/* @__PURE__ */ jsx13(Badge4, { fontSize: 0, tone: badgeTone, children: badgeLabel })
|
|
2663
3167
|
] }) });
|
|
2664
3168
|
}, []);
|
|
2665
|
-
const renderValue =
|
|
3169
|
+
const renderValue = useCallback6((_value, option) => {
|
|
2666
3170
|
if (option?.payload.title) {
|
|
2667
3171
|
return `${option.payload.title} (${option.payload.slug})`;
|
|
2668
3172
|
}
|
|
2669
3173
|
return _value;
|
|
2670
3174
|
}, []);
|
|
2671
|
-
return /* @__PURE__ */
|
|
2672
|
-
|
|
3175
|
+
return /* @__PURE__ */ jsx13(
|
|
3176
|
+
Autocomplete2,
|
|
2673
3177
|
{
|
|
2674
3178
|
filterOption: () => true,
|
|
2675
|
-
icon:
|
|
3179
|
+
icon: SearchIcon2,
|
|
2676
3180
|
id: "document-filter-input",
|
|
2677
3181
|
loading,
|
|
2678
3182
|
onChange: handleSelect,
|
|
@@ -2698,33 +3202,33 @@ function classifyDocId(id) {
|
|
|
2698
3202
|
}
|
|
2699
3203
|
|
|
2700
3204
|
// src/components/content-filters/PerspectiveFilter.tsx
|
|
2701
|
-
import { SearchIcon as
|
|
2702
|
-
import { Autocomplete as
|
|
2703
|
-
import { useEffect as
|
|
3205
|
+
import { SearchIcon as SearchIcon3 } from "@sanity/icons";
|
|
3206
|
+
import { Autocomplete as Autocomplete3, Badge as Badge5, Card as Card8, Flex as Flex9, Stack as Stack10, Text as Text13 } from "@sanity/ui";
|
|
3207
|
+
import { useEffect as useEffect4, useMemo as useMemo4, useState as useState4 } from "react";
|
|
2704
3208
|
import {
|
|
2705
|
-
getReleaseIdFromReleaseDocumentId,
|
|
2706
|
-
useActiveReleases,
|
|
2707
|
-
useArchivedReleases,
|
|
3209
|
+
getReleaseIdFromReleaseDocumentId as getReleaseIdFromReleaseDocumentId3,
|
|
3210
|
+
useActiveReleases as useActiveReleases3,
|
|
3211
|
+
useArchivedReleases as useArchivedReleases3,
|
|
2708
3212
|
useClient as useClient4
|
|
2709
3213
|
} from "sanity";
|
|
2710
|
-
import { jsx as
|
|
3214
|
+
import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
2711
3215
|
function PerspectiveFilter({ value, onChange }) {
|
|
2712
3216
|
const client = useClient4({ apiVersion: API_VERSION });
|
|
2713
3217
|
const [reportPerspectives, setReportPerspectives] = useState4([]);
|
|
2714
|
-
const { data: activeReleases } =
|
|
2715
|
-
const { data: archivedReleases } =
|
|
2716
|
-
|
|
3218
|
+
const { data: activeReleases } = useActiveReleases3();
|
|
3219
|
+
const { data: archivedReleases } = useArchivedReleases3();
|
|
3220
|
+
useEffect4(() => {
|
|
2717
3221
|
client.fetch(distinctPerspectivesQuery).then(
|
|
2718
3222
|
(data) => setReportPerspectives((data ?? []).filter(Boolean).sort())
|
|
2719
3223
|
).catch(() => setReportPerspectives([]));
|
|
2720
3224
|
}, [client]);
|
|
2721
|
-
const options =
|
|
3225
|
+
const options = useMemo4(() => {
|
|
2722
3226
|
const releaseMap = /* @__PURE__ */ new Map();
|
|
2723
3227
|
for (const release of [
|
|
2724
3228
|
...activeReleases ?? [],
|
|
2725
3229
|
...archivedReleases ?? []
|
|
2726
3230
|
]) {
|
|
2727
|
-
const releaseId =
|
|
3231
|
+
const releaseId = getReleaseIdFromReleaseDocumentId3(release._id);
|
|
2728
3232
|
const title = release.metadata?.title ?? releaseId;
|
|
2729
3233
|
releaseMap.set(releaseId, title);
|
|
2730
3234
|
}
|
|
@@ -2744,27 +3248,27 @@ function PerspectiveFilter({ value, onChange }) {
|
|
|
2744
3248
|
}));
|
|
2745
3249
|
return result;
|
|
2746
3250
|
}, [activeReleases, archivedReleases, reportPerspectives]);
|
|
2747
|
-
return /* @__PURE__ */
|
|
2748
|
-
|
|
3251
|
+
return /* @__PURE__ */ jsx14(
|
|
3252
|
+
Autocomplete3,
|
|
2749
3253
|
{
|
|
2750
3254
|
filterOption: (query, option) => {
|
|
2751
3255
|
const q = query.toLowerCase();
|
|
2752
3256
|
const opt = option;
|
|
2753
3257
|
return opt.value.toLowerCase().includes(q) || (opt.payload?.title ?? "").toLowerCase().includes(q);
|
|
2754
3258
|
},
|
|
2755
|
-
icon:
|
|
3259
|
+
icon: SearchIcon3,
|
|
2756
3260
|
id: "perspective-filter-input",
|
|
2757
3261
|
onChange,
|
|
2758
3262
|
options,
|
|
2759
3263
|
placeholder: "Search by title or ID\u2026",
|
|
2760
3264
|
renderOption: (option) => {
|
|
2761
3265
|
const opt = option;
|
|
2762
|
-
return /* @__PURE__ */
|
|
2763
|
-
/* @__PURE__ */
|
|
2764
|
-
/* @__PURE__ */
|
|
2765
|
-
opt.payload.title !== opt.value && /* @__PURE__ */
|
|
3266
|
+
return /* @__PURE__ */ jsx14(Card8, { as: "button", padding: 3, children: /* @__PURE__ */ jsxs12(Flex9, { align: "center", gap: 2, children: [
|
|
3267
|
+
/* @__PURE__ */ jsxs12(Stack10, { flex: 1, space: 1, children: [
|
|
3268
|
+
/* @__PURE__ */ jsx14(Text13, { size: 1, weight: "semibold", children: opt.payload.title }),
|
|
3269
|
+
opt.payload.title !== opt.value && /* @__PURE__ */ jsx14(Text13, { muted: true, size: 1, children: opt.value })
|
|
2766
3270
|
] }),
|
|
2767
|
-
opt.payload.hasReport && /* @__PURE__ */
|
|
3271
|
+
opt.payload.hasReport && /* @__PURE__ */ jsx14(Badge5, { fontSize: 0, tone: "positive", children: "Has reports" })
|
|
2768
3272
|
] }) });
|
|
2769
3273
|
},
|
|
2770
3274
|
renderValue: (v, option) => {
|
|
@@ -2780,15 +3284,15 @@ function PerspectiveFilter({ value, onChange }) {
|
|
|
2780
3284
|
}
|
|
2781
3285
|
|
|
2782
3286
|
// src/components/report-card/ReportCard.tsx
|
|
2783
|
-
import { Badge as
|
|
2784
|
-
import { useCallback as
|
|
3287
|
+
import { Badge as Badge9, Card as Card9, Flex as Flex12, Text as Text16 } from "@sanity/ui";
|
|
3288
|
+
import { useCallback as useCallback7 } from "react";
|
|
2785
3289
|
|
|
2786
3290
|
// src/components/primitives/DeltaIndicator.tsx
|
|
2787
|
-
import { Text as
|
|
2788
|
-
import { jsx as
|
|
3291
|
+
import { Text as Text14 } from "@sanity/ui";
|
|
3292
|
+
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
2789
3293
|
function DeltaIndicator({ delta, size = 1 }) {
|
|
2790
|
-
return /* @__PURE__ */
|
|
2791
|
-
|
|
3294
|
+
return /* @__PURE__ */ jsx15(
|
|
3295
|
+
Text14,
|
|
2792
3296
|
{
|
|
2793
3297
|
size,
|
|
2794
3298
|
style: {
|
|
@@ -2800,18 +3304,18 @@ function DeltaIndicator({ delta, size = 1 }) {
|
|
|
2800
3304
|
}
|
|
2801
3305
|
|
|
2802
3306
|
// src/components/report-card/ReportMeta.tsx
|
|
2803
|
-
import { Stack as
|
|
3307
|
+
import { Stack as Stack11, Text as Text15 } from "@sanity/ui";
|
|
2804
3308
|
|
|
2805
3309
|
// src/components/report-card/AreaTags.tsx
|
|
2806
|
-
import { Badge as
|
|
2807
|
-
import { jsx as
|
|
3310
|
+
import { Badge as Badge6, Flex as Flex10 } from "@sanity/ui";
|
|
3311
|
+
import { jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
2808
3312
|
function AreaTags({ areas, targetDocuments }) {
|
|
2809
3313
|
const hasAreas = areas && areas.length > 0;
|
|
2810
3314
|
const hasDocs = targetDocuments && targetDocuments.length > 0;
|
|
2811
3315
|
if (!hasAreas && !hasDocs) return null;
|
|
2812
|
-
return /* @__PURE__ */
|
|
2813
|
-
hasAreas && areas.map((area) => /* @__PURE__ */
|
|
2814
|
-
|
|
3316
|
+
return /* @__PURE__ */ jsxs13(Flex10, { gap: 1, paddingTop: 1, wrap: "wrap", children: [
|
|
3317
|
+
hasAreas && areas.map((area) => /* @__PURE__ */ jsx16(
|
|
3318
|
+
Badge6,
|
|
2815
3319
|
{
|
|
2816
3320
|
fontSize: 0,
|
|
2817
3321
|
mode: "outline",
|
|
@@ -2820,7 +3324,7 @@ function AreaTags({ areas, targetDocuments }) {
|
|
|
2820
3324
|
},
|
|
2821
3325
|
`area-${area}`
|
|
2822
3326
|
)),
|
|
2823
|
-
hasDocs && targetDocuments.map((doc) => /* @__PURE__ */
|
|
3327
|
+
hasDocs && targetDocuments.map((doc) => /* @__PURE__ */ jsx16(Badge6, { fontSize: 0, mode: "outline", tone: "primary", children: doc }, `doc-${doc}`))
|
|
2824
3328
|
] });
|
|
2825
3329
|
}
|
|
2826
3330
|
|
|
@@ -2864,7 +3368,7 @@ function formatCardDate(iso) {
|
|
|
2864
3368
|
}
|
|
2865
3369
|
|
|
2866
3370
|
// src/components/report-card/ReportMeta.tsx
|
|
2867
|
-
import { jsx as
|
|
3371
|
+
import { jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
2868
3372
|
function ReportMeta({ data }) {
|
|
2869
3373
|
const segments = [data.mode, data.source];
|
|
2870
3374
|
if (data.models && data.models.length > 0) {
|
|
@@ -2876,15 +3380,15 @@ function ReportMeta({ data }) {
|
|
|
2876
3380
|
if (data.durationMs && data.durationMs > 0) {
|
|
2877
3381
|
segments.push(formatDuration(data.durationMs));
|
|
2878
3382
|
}
|
|
2879
|
-
return /* @__PURE__ */
|
|
2880
|
-
/* @__PURE__ */
|
|
2881
|
-
/* @__PURE__ */
|
|
2882
|
-
/* @__PURE__ */
|
|
3383
|
+
return /* @__PURE__ */ jsxs14(Stack11, { flex: 1, space: 1, children: [
|
|
3384
|
+
/* @__PURE__ */ jsx17(Text15, { weight: "semibold", children: data.tag ?? formatCardDate(data.completedAt) }),
|
|
3385
|
+
/* @__PURE__ */ jsx17(Text15, { muted: true, size: 1, children: segments.join(" \xB7 ") }),
|
|
3386
|
+
/* @__PURE__ */ jsx17(AreaTags, { areas: data.areas, targetDocuments: data.targetDocuments })
|
|
2883
3387
|
] });
|
|
2884
3388
|
}
|
|
2885
3389
|
|
|
2886
3390
|
// src/components/primitives/ScoreBadge.tsx
|
|
2887
|
-
import { Badge as
|
|
3391
|
+
import { Badge as Badge7 } from "@sanity/ui";
|
|
2888
3392
|
|
|
2889
3393
|
// src/lib/scoring.ts
|
|
2890
3394
|
var TONE_MAP = {
|
|
@@ -2916,11 +3420,11 @@ function rowBackground(index) {
|
|
|
2916
3420
|
}
|
|
2917
3421
|
|
|
2918
3422
|
// src/components/primitives/ScoreBadge.tsx
|
|
2919
|
-
import { jsx as
|
|
3423
|
+
import { jsx as jsx18 } from "react/jsx-runtime";
|
|
2920
3424
|
function ScoreBadge({ score, fontSize = 1 }) {
|
|
2921
3425
|
const rounded = Math.round(score);
|
|
2922
|
-
return /* @__PURE__ */
|
|
2923
|
-
|
|
3426
|
+
return /* @__PURE__ */ jsx18(
|
|
3427
|
+
Badge7,
|
|
2924
3428
|
{
|
|
2925
3429
|
fontSize,
|
|
2926
3430
|
style: { minWidth: 48, textAlign: "center" },
|
|
@@ -2931,18 +3435,18 @@ function ScoreBadge({ score, fontSize = 1 }) {
|
|
|
2931
3435
|
}
|
|
2932
3436
|
|
|
2933
3437
|
// src/components/primitives/StatusBadges.tsx
|
|
2934
|
-
import { Badge as
|
|
2935
|
-
import { jsxs as
|
|
3438
|
+
import { Badge as Badge8, Flex as Flex11 } from "@sanity/ui";
|
|
3439
|
+
import { jsxs as jsxs15 } from "react/jsx-runtime";
|
|
2936
3440
|
function StatusBadges({ regressed, improved }) {
|
|
2937
3441
|
const hasRegressed = regressed && regressed.length > 0;
|
|
2938
3442
|
const hasImproved = improved && improved.length > 0;
|
|
2939
3443
|
if (!hasRegressed && !hasImproved) return null;
|
|
2940
|
-
return /* @__PURE__ */
|
|
2941
|
-
hasRegressed && /* @__PURE__ */
|
|
3444
|
+
return /* @__PURE__ */ jsxs15(Flex11, { gap: 1, children: [
|
|
3445
|
+
hasRegressed && /* @__PURE__ */ jsxs15(Badge8, { fontSize: 0, tone: "critical", children: [
|
|
2942
3446
|
regressed.length,
|
|
2943
3447
|
" regressed"
|
|
2944
3448
|
] }),
|
|
2945
|
-
hasImproved && /* @__PURE__ */
|
|
3449
|
+
hasImproved && /* @__PURE__ */ jsxs15(Badge8, { fontSize: 0, tone: "positive", children: [
|
|
2946
3450
|
improved.length,
|
|
2947
3451
|
" improved"
|
|
2948
3452
|
] })
|
|
@@ -2950,38 +3454,38 @@ function StatusBadges({ regressed, improved }) {
|
|
|
2950
3454
|
}
|
|
2951
3455
|
|
|
2952
3456
|
// src/components/report-card/ReportCard.tsx
|
|
2953
|
-
import { jsx as
|
|
3457
|
+
import { jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
2954
3458
|
function ReportCard({ data, onSelectReport }) {
|
|
2955
|
-
const handleClick =
|
|
3459
|
+
const handleClick = useCallback7(() => {
|
|
2956
3460
|
onSelectReport(data.reportId);
|
|
2957
3461
|
}, [data.reportId, onSelectReport]);
|
|
2958
|
-
return /* @__PURE__ */
|
|
2959
|
-
|
|
3462
|
+
return /* @__PURE__ */ jsx19(
|
|
3463
|
+
Card9,
|
|
2960
3464
|
{
|
|
2961
3465
|
onClick: handleClick,
|
|
2962
3466
|
padding: 3,
|
|
2963
3467
|
radius: 2,
|
|
2964
3468
|
shadow: 1,
|
|
2965
3469
|
style: { cursor: "pointer" },
|
|
2966
|
-
children: /* @__PURE__ */
|
|
2967
|
-
/* @__PURE__ */
|
|
2968
|
-
/* @__PURE__ */
|
|
2969
|
-
data.comparisonDelta != null && /* @__PURE__ */
|
|
2970
|
-
/* @__PURE__ */
|
|
2971
|
-
/* @__PURE__ */
|
|
2972
|
-
data.trigger && /* @__PURE__ */
|
|
3470
|
+
children: /* @__PURE__ */ jsxs16(Flex12, { align: "center", gap: 3, children: [
|
|
3471
|
+
/* @__PURE__ */ jsx19(ScoreBadge, { score: data.overall }),
|
|
3472
|
+
/* @__PURE__ */ jsx19(ReportMeta, { data }),
|
|
3473
|
+
data.comparisonDelta != null && /* @__PURE__ */ jsx19(DeltaIndicator, { delta: data.comparisonDelta }),
|
|
3474
|
+
/* @__PURE__ */ jsx19(StatusBadges, { improved: data.improved, regressed: data.regressed }),
|
|
3475
|
+
/* @__PURE__ */ jsx19(Text16, { muted: true, size: 0, title: new Date(data.completedAt).toISOString(), children: formatRelativeTime(data.completedAt) }),
|
|
3476
|
+
data.trigger && /* @__PURE__ */ jsx19(Badge9, { fontSize: 0, tone: "default", children: data.trigger })
|
|
2973
3477
|
] })
|
|
2974
3478
|
}
|
|
2975
3479
|
);
|
|
2976
3480
|
}
|
|
2977
3481
|
|
|
2978
3482
|
// src/components/search-bar/SearchBar.tsx
|
|
2979
|
-
import { SearchIcon as
|
|
2980
|
-
import { Card as
|
|
3483
|
+
import { SearchIcon as SearchIcon4 } from "@sanity/icons";
|
|
3484
|
+
import { Card as Card11, Flex as Flex15, Text as Text19 } from "@sanity/ui";
|
|
2981
3485
|
import {
|
|
2982
|
-
useCallback as
|
|
2983
|
-
useEffect as
|
|
2984
|
-
useRef as
|
|
3486
|
+
useCallback as useCallback10,
|
|
3487
|
+
useEffect as useEffect5,
|
|
3488
|
+
useRef as useRef3,
|
|
2985
3489
|
useState as useState5
|
|
2986
3490
|
} from "react";
|
|
2987
3491
|
|
|
@@ -3122,21 +3626,21 @@ function filterAndExclude(values, query, dim, activeTokens) {
|
|
|
3122
3626
|
|
|
3123
3627
|
// src/components/search-bar/FilterBadge.tsx
|
|
3124
3628
|
import { CloseIcon } from "@sanity/icons";
|
|
3125
|
-
import { Badge as
|
|
3126
|
-
import { useCallback as
|
|
3127
|
-
import { jsx as
|
|
3629
|
+
import { Badge as Badge10, Flex as Flex13, Text as Text17 } from "@sanity/ui";
|
|
3630
|
+
import { useCallback as useCallback8 } from "react";
|
|
3631
|
+
import { jsx as jsx20, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
3128
3632
|
function FilterBadge({ token, onRemove }) {
|
|
3129
3633
|
const dim = DIMENSIONS.find((d) => d.key === token.dimension);
|
|
3130
3634
|
const tone = dim?.tone ?? "default";
|
|
3131
|
-
const handleRemove =
|
|
3635
|
+
const handleRemove = useCallback8(
|
|
3132
3636
|
(e) => {
|
|
3133
3637
|
e.stopPropagation();
|
|
3134
3638
|
onRemove(token.id);
|
|
3135
3639
|
},
|
|
3136
3640
|
[onRemove, token.id]
|
|
3137
3641
|
);
|
|
3138
|
-
return /* @__PURE__ */
|
|
3139
|
-
|
|
3642
|
+
return /* @__PURE__ */ jsx20(
|
|
3643
|
+
Badge10,
|
|
3140
3644
|
{
|
|
3141
3645
|
fontSize: 0,
|
|
3142
3646
|
style: {
|
|
@@ -3145,20 +3649,20 @@ function FilterBadge({ token, onRemove }) {
|
|
|
3145
3649
|
userSelect: "none"
|
|
3146
3650
|
},
|
|
3147
3651
|
tone,
|
|
3148
|
-
children: /* @__PURE__ */
|
|
3149
|
-
/* @__PURE__ */
|
|
3652
|
+
children: /* @__PURE__ */ jsxs17(Flex13, { align: "center", gap: 1, children: [
|
|
3653
|
+
/* @__PURE__ */ jsxs17(Text17, { size: 0, children: [
|
|
3150
3654
|
token.dimension,
|
|
3151
3655
|
":",
|
|
3152
3656
|
token.label
|
|
3153
3657
|
] }),
|
|
3154
|
-
/* @__PURE__ */
|
|
3155
|
-
|
|
3658
|
+
/* @__PURE__ */ jsx20(
|
|
3659
|
+
Text17,
|
|
3156
3660
|
{
|
|
3157
3661
|
muted: true,
|
|
3158
3662
|
onClick: handleRemove,
|
|
3159
3663
|
size: 0,
|
|
3160
3664
|
style: { cursor: "pointer", lineHeight: 1 },
|
|
3161
|
-
children: /* @__PURE__ */
|
|
3665
|
+
children: /* @__PURE__ */ jsx20(CloseIcon, {})
|
|
3162
3666
|
}
|
|
3163
3667
|
)
|
|
3164
3668
|
] })
|
|
@@ -3167,9 +3671,9 @@ function FilterBadge({ token, onRemove }) {
|
|
|
3167
3671
|
}
|
|
3168
3672
|
|
|
3169
3673
|
// src/components/search-bar/SuggestionList.tsx
|
|
3170
|
-
import { Badge as
|
|
3171
|
-
import { useCallback as
|
|
3172
|
-
import { jsx as
|
|
3674
|
+
import { Badge as Badge11, Card as Card10, Flex as Flex14, Stack as Stack12, Text as Text18 } from "@sanity/ui";
|
|
3675
|
+
import { useCallback as useCallback9 } from "react";
|
|
3676
|
+
import { jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
3173
3677
|
function SuggestionList({
|
|
3174
3678
|
suggestions,
|
|
3175
3679
|
activeIndex,
|
|
@@ -3178,8 +3682,8 @@ function SuggestionList({
|
|
|
3178
3682
|
if (suggestions.length === 0) return null;
|
|
3179
3683
|
const groups = groupByCategory(suggestions);
|
|
3180
3684
|
let globalIndex = -1;
|
|
3181
|
-
return /* @__PURE__ */
|
|
3182
|
-
|
|
3685
|
+
return /* @__PURE__ */ jsx21(
|
|
3686
|
+
Card10,
|
|
3183
3687
|
{
|
|
3184
3688
|
overflow: "auto",
|
|
3185
3689
|
radius: 2,
|
|
@@ -3192,9 +3696,9 @@ function SuggestionList({
|
|
|
3192
3696
|
top: "100%",
|
|
3193
3697
|
zIndex: 100
|
|
3194
3698
|
},
|
|
3195
|
-
children: /* @__PURE__ */
|
|
3196
|
-
/* @__PURE__ */
|
|
3197
|
-
|
|
3699
|
+
children: /* @__PURE__ */ jsx21(Stack12, { padding: 1, space: 1, children: groups.map(([category, items]) => /* @__PURE__ */ jsxs18(Stack12, { space: 0, children: [
|
|
3700
|
+
/* @__PURE__ */ jsx21(
|
|
3701
|
+
Text18,
|
|
3198
3702
|
{
|
|
3199
3703
|
muted: true,
|
|
3200
3704
|
size: 0,
|
|
@@ -3210,7 +3714,7 @@ function SuggestionList({
|
|
|
3210
3714
|
items.map((suggestion) => {
|
|
3211
3715
|
globalIndex++;
|
|
3212
3716
|
const isActive = globalIndex === activeIndex;
|
|
3213
|
-
return /* @__PURE__ */
|
|
3717
|
+
return /* @__PURE__ */ jsx21(
|
|
3214
3718
|
SuggestionItem,
|
|
3215
3719
|
{
|
|
3216
3720
|
active: isActive,
|
|
@@ -3232,20 +3736,20 @@ function SuggestionItem({
|
|
|
3232
3736
|
const dim = DIMENSIONS.find((d) => d.key === suggestion.dimension);
|
|
3233
3737
|
const tone = dim?.tone ?? "default";
|
|
3234
3738
|
const isHint = suggestion.category === "Filters";
|
|
3235
|
-
const handleClick =
|
|
3739
|
+
const handleClick = useCallback9(() => {
|
|
3236
3740
|
onSelect(suggestion);
|
|
3237
3741
|
}, [onSelect, suggestion]);
|
|
3238
|
-
return /* @__PURE__ */
|
|
3239
|
-
|
|
3742
|
+
return /* @__PURE__ */ jsx21(
|
|
3743
|
+
Card10,
|
|
3240
3744
|
{
|
|
3241
3745
|
onClick: handleClick,
|
|
3242
3746
|
padding: 2,
|
|
3243
3747
|
radius: 2,
|
|
3244
3748
|
style: { cursor: "pointer" },
|
|
3245
3749
|
tone: active ? "primary" : "default",
|
|
3246
|
-
children: /* @__PURE__ */
|
|
3247
|
-
!isHint && /* @__PURE__ */
|
|
3248
|
-
/* @__PURE__ */
|
|
3750
|
+
children: /* @__PURE__ */ jsxs18(Flex14, { align: "center", gap: 2, children: [
|
|
3751
|
+
!isHint && /* @__PURE__ */ jsx21(Badge11, { fontSize: 0, tone, children: suggestion.dimension }),
|
|
3752
|
+
/* @__PURE__ */ jsx21(Text18, { size: 1, children: suggestion.label })
|
|
3249
3753
|
] })
|
|
3250
3754
|
}
|
|
3251
3755
|
);
|
|
@@ -3260,7 +3764,7 @@ function groupByCategory(suggestions) {
|
|
|
3260
3764
|
}
|
|
3261
3765
|
|
|
3262
3766
|
// src/components/search-bar/SearchBar.tsx
|
|
3263
|
-
import { jsx as
|
|
3767
|
+
import { jsx as jsx22, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
3264
3768
|
function SearchBar({
|
|
3265
3769
|
tokens,
|
|
3266
3770
|
query,
|
|
@@ -3272,9 +3776,9 @@ function SearchBar({
|
|
|
3272
3776
|
}) {
|
|
3273
3777
|
const [focused, setFocused] = useState5(false);
|
|
3274
3778
|
const [activeIndex, setActiveIndex] = useState5(-1);
|
|
3275
|
-
const inputRef =
|
|
3276
|
-
const blurTimerRef =
|
|
3277
|
-
|
|
3779
|
+
const inputRef = useRef3(null);
|
|
3780
|
+
const blurTimerRef = useRef3(null);
|
|
3781
|
+
useEffect5(() => {
|
|
3278
3782
|
return () => {
|
|
3279
3783
|
if (blurTimerRef.current) {
|
|
3280
3784
|
clearTimeout(blurTimerRef.current);
|
|
@@ -3282,10 +3786,10 @@ function SearchBar({
|
|
|
3282
3786
|
};
|
|
3283
3787
|
}, []);
|
|
3284
3788
|
const suggestions = focused ? computeSuggestions({ query, activeTokens: tokens, models, areas }) : [];
|
|
3285
|
-
|
|
3789
|
+
useEffect5(() => {
|
|
3286
3790
|
setActiveIndex(-1);
|
|
3287
3791
|
}, [query, tokens.length]);
|
|
3288
|
-
const handleTokenRemove =
|
|
3792
|
+
const handleTokenRemove = useCallback10(
|
|
3289
3793
|
(id) => {
|
|
3290
3794
|
onTokenRemove(id);
|
|
3291
3795
|
requestAnimationFrame(() => {
|
|
@@ -3294,7 +3798,7 @@ function SearchBar({
|
|
|
3294
3798
|
},
|
|
3295
3799
|
[onTokenRemove]
|
|
3296
3800
|
);
|
|
3297
|
-
const handleSuggestionSelect =
|
|
3801
|
+
const handleSuggestionSelect = useCallback10(
|
|
3298
3802
|
(suggestion) => {
|
|
3299
3803
|
if (suggestion.category === "Filters") {
|
|
3300
3804
|
onQueryChange(suggestion.value);
|
|
@@ -3313,7 +3817,7 @@ function SearchBar({
|
|
|
3313
3817
|
},
|
|
3314
3818
|
[onTokenAdd, onQueryChange]
|
|
3315
3819
|
);
|
|
3316
|
-
const handleKeyDown =
|
|
3820
|
+
const handleKeyDown = useCallback10(
|
|
3317
3821
|
(e) => {
|
|
3318
3822
|
if (e.key === "ArrowDown") {
|
|
3319
3823
|
e.preventDefault();
|
|
@@ -3341,41 +3845,41 @@ function SearchBar({
|
|
|
3341
3845
|
handleSuggestionSelect
|
|
3342
3846
|
]
|
|
3343
3847
|
);
|
|
3344
|
-
const handleInputChange =
|
|
3848
|
+
const handleInputChange = useCallback10(
|
|
3345
3849
|
(e) => {
|
|
3346
3850
|
const value = e.target.value;
|
|
3347
3851
|
onQueryChange(value);
|
|
3348
3852
|
},
|
|
3349
3853
|
[onQueryChange]
|
|
3350
3854
|
);
|
|
3351
|
-
const handleBlur =
|
|
3855
|
+
const handleBlur = useCallback10(() => {
|
|
3352
3856
|
blurTimerRef.current = setTimeout(() => {
|
|
3353
3857
|
blurTimerRef.current = null;
|
|
3354
3858
|
setFocused(false);
|
|
3355
3859
|
}, 200);
|
|
3356
3860
|
}, []);
|
|
3357
|
-
const handleFocus =
|
|
3861
|
+
const handleFocus = useCallback10(() => {
|
|
3358
3862
|
if (blurTimerRef.current) {
|
|
3359
3863
|
clearTimeout(blurTimerRef.current);
|
|
3360
3864
|
blurTimerRef.current = null;
|
|
3361
3865
|
}
|
|
3362
3866
|
setFocused(true);
|
|
3363
3867
|
}, []);
|
|
3364
|
-
const handleBarClick =
|
|
3868
|
+
const handleBarClick = useCallback10(() => {
|
|
3365
3869
|
inputRef.current?.focus();
|
|
3366
3870
|
}, []);
|
|
3367
|
-
return /* @__PURE__ */
|
|
3368
|
-
/* @__PURE__ */
|
|
3369
|
-
|
|
3871
|
+
return /* @__PURE__ */ jsxs19("div", { style: { position: "relative" }, children: [
|
|
3872
|
+
/* @__PURE__ */ jsx22(
|
|
3873
|
+
Card11,
|
|
3370
3874
|
{
|
|
3371
3875
|
border: true,
|
|
3372
3876
|
onClick: handleBarClick,
|
|
3373
3877
|
padding: 2,
|
|
3374
3878
|
radius: 2,
|
|
3375
3879
|
style: { cursor: "text" },
|
|
3376
|
-
children: /* @__PURE__ */
|
|
3377
|
-
/* @__PURE__ */
|
|
3378
|
-
tokens.map((token) => /* @__PURE__ */
|
|
3880
|
+
children: /* @__PURE__ */ jsxs19(Flex15, { align: "center", gap: 1, wrap: "wrap", children: [
|
|
3881
|
+
/* @__PURE__ */ jsx22(Text19, { muted: true, size: 1, style: { flexShrink: 0, padding: "0 4px" }, children: /* @__PURE__ */ jsx22(SearchIcon4, {}) }),
|
|
3882
|
+
tokens.map((token) => /* @__PURE__ */ jsx22(
|
|
3379
3883
|
FilterBadge,
|
|
3380
3884
|
{
|
|
3381
3885
|
onRemove: handleTokenRemove,
|
|
@@ -3383,7 +3887,7 @@ function SearchBar({
|
|
|
3383
3887
|
},
|
|
3384
3888
|
token.id
|
|
3385
3889
|
)),
|
|
3386
|
-
/* @__PURE__ */
|
|
3890
|
+
/* @__PURE__ */ jsx22(
|
|
3387
3891
|
"input",
|
|
3388
3892
|
{
|
|
3389
3893
|
onBlur: handleBlur,
|
|
@@ -3410,7 +3914,7 @@ function SearchBar({
|
|
|
3410
3914
|
] })
|
|
3411
3915
|
}
|
|
3412
3916
|
),
|
|
3413
|
-
focused && suggestions.length > 0 && /* @__PURE__ */
|
|
3917
|
+
focused && suggestions.length > 0 && /* @__PURE__ */ jsx22(
|
|
3414
3918
|
SuggestionList,
|
|
3415
3919
|
{
|
|
3416
3920
|
activeIndex,
|
|
@@ -3422,7 +3926,7 @@ function SearchBar({
|
|
|
3422
3926
|
}
|
|
3423
3927
|
|
|
3424
3928
|
// src/components/LatestReports.tsx
|
|
3425
|
-
import { jsx as
|
|
3929
|
+
import { jsx as jsx23, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
3426
3930
|
var SORT_LABELS = {
|
|
3427
3931
|
date: "Date",
|
|
3428
3932
|
name: "Name",
|
|
@@ -3449,7 +3953,7 @@ function LatestReports({
|
|
|
3449
3953
|
});
|
|
3450
3954
|
const [availableModels, setAvailableModels] = useState6([]);
|
|
3451
3955
|
const [availableAreas, setAvailableAreas] = useState6([]);
|
|
3452
|
-
|
|
3956
|
+
useEffect6(() => {
|
|
3453
3957
|
setInitialLoading(true);
|
|
3454
3958
|
setHasMore(true);
|
|
3455
3959
|
client.fetch(latestReportsQuery, {
|
|
@@ -3467,7 +3971,7 @@ function LatestReports({
|
|
|
3467
3971
|
setInitialLoading(false);
|
|
3468
3972
|
});
|
|
3469
3973
|
}, [client, pageSize, mode, source]);
|
|
3470
|
-
const handleLoadMore =
|
|
3974
|
+
const handleLoadMore = useCallback11(() => {
|
|
3471
3975
|
if (loadingMore || !hasMore) return;
|
|
3472
3976
|
setLoadingMore(true);
|
|
3473
3977
|
const nextLimit = reports.length + pageSize;
|
|
@@ -3484,11 +3988,11 @@ function LatestReports({
|
|
|
3484
3988
|
setLoadingMore(false);
|
|
3485
3989
|
});
|
|
3486
3990
|
}, [client, hasMore, loadingMore, mode, pageSize, reports.length, source]);
|
|
3487
|
-
|
|
3991
|
+
useEffect6(() => {
|
|
3488
3992
|
client.fetch(distinctModelsQuery).then((data) => setAvailableModels((data ?? []).sort())).catch(() => setAvailableModels([]));
|
|
3489
3993
|
client.fetch(distinctAreasQuery).then((data) => setAvailableAreas((data ?? []).sort())).catch(() => setAvailableAreas([]));
|
|
3490
3994
|
}, [client]);
|
|
3491
|
-
const activeFilters =
|
|
3995
|
+
const activeFilters = useMemo5(() => {
|
|
3492
3996
|
const result = { models: [], areas: [], datePreset: null };
|
|
3493
3997
|
for (const token of filterTokens) {
|
|
3494
3998
|
switch (token.dimension) {
|
|
@@ -3505,7 +4009,7 @@ function LatestReports({
|
|
|
3505
4009
|
}
|
|
3506
4010
|
return result;
|
|
3507
4011
|
}, [filterTokens]);
|
|
3508
|
-
const filteredReports =
|
|
4012
|
+
const filteredReports = useMemo5(() => {
|
|
3509
4013
|
let result = reports;
|
|
3510
4014
|
if (searchQuery.trim()) {
|
|
3511
4015
|
const query = searchQuery.toLowerCase().trim();
|
|
@@ -3568,7 +4072,7 @@ function LatestReports({
|
|
|
3568
4072
|
});
|
|
3569
4073
|
return result;
|
|
3570
4074
|
}, [reports, searchQuery, activeFilters, documentSlug, perspective, sort]);
|
|
3571
|
-
const handleTokenAdd =
|
|
4075
|
+
const handleTokenAdd = useCallback11((token) => {
|
|
3572
4076
|
setFilterTokens((prev) => {
|
|
3573
4077
|
const dim = token.dimension;
|
|
3574
4078
|
const isMulti = dim === "area";
|
|
@@ -3578,38 +4082,38 @@ function LatestReports({
|
|
|
3578
4082
|
return [...prev, token];
|
|
3579
4083
|
});
|
|
3580
4084
|
}, []);
|
|
3581
|
-
const handleTokenRemove =
|
|
4085
|
+
const handleTokenRemove = useCallback11((id) => {
|
|
3582
4086
|
setFilterTokens((prev) => prev.filter((t) => t.id !== id));
|
|
3583
4087
|
}, []);
|
|
3584
|
-
const toggleSortDirection =
|
|
4088
|
+
const toggleSortDirection = useCallback11(() => {
|
|
3585
4089
|
setSort((prev) => ({
|
|
3586
4090
|
...prev,
|
|
3587
4091
|
direction: prev.direction === "asc" ? "desc" : "asc"
|
|
3588
4092
|
}));
|
|
3589
4093
|
}, []);
|
|
3590
|
-
const handleSortFieldChange =
|
|
4094
|
+
const handleSortFieldChange = useCallback11((field) => {
|
|
3591
4095
|
setSort(
|
|
3592
4096
|
(prev) => prev.field === field ? { ...prev, direction: prev.direction === "asc" ? "desc" : "asc" } : { direction: "desc", field }
|
|
3593
4097
|
);
|
|
3594
4098
|
}, []);
|
|
3595
4099
|
const hasActiveFilters = searchQuery.trim() !== "" || filterTokens.length > 0 || documentSlug.trim() !== "" || perspective.trim() !== "";
|
|
3596
|
-
const handleClearFilters =
|
|
4100
|
+
const handleClearFilters = useCallback11(() => {
|
|
3597
4101
|
setSearchQuery("");
|
|
3598
4102
|
setFilterTokens([]);
|
|
3599
4103
|
setDocumentSlug("");
|
|
3600
4104
|
setPerspective("");
|
|
3601
4105
|
}, []);
|
|
3602
4106
|
if (initialLoading) {
|
|
3603
|
-
return /* @__PURE__ */
|
|
4107
|
+
return /* @__PURE__ */ jsx23(Card12, { padding: 4, children: /* @__PURE__ */ jsx23(Text20, { muted: true, children: "Loading reports\u2026" }) });
|
|
3604
4108
|
}
|
|
3605
4109
|
if (reports.length === 0) {
|
|
3606
|
-
return /* @__PURE__ */
|
|
4110
|
+
return /* @__PURE__ */ jsx23(Card12, { padding: 4, children: /* @__PURE__ */ jsx23(Text20, { muted: true, children: "No reports found. Run the pipeline with --publish to create reports." }) });
|
|
3607
4111
|
}
|
|
3608
|
-
return /* @__PURE__ */
|
|
3609
|
-
/* @__PURE__ */
|
|
3610
|
-
/* @__PURE__ */
|
|
3611
|
-
/* @__PURE__ */
|
|
3612
|
-
/* @__PURE__ */
|
|
4112
|
+
return /* @__PURE__ */ jsxs20(Stack13, { space: 3, children: [
|
|
4113
|
+
/* @__PURE__ */ jsx23(Card12, { padding: 3, radius: 2, shadow: 1, children: /* @__PURE__ */ jsxs20(Stack13, { space: 3, children: [
|
|
4114
|
+
/* @__PURE__ */ jsxs20(Stack13, { space: 1, children: [
|
|
4115
|
+
/* @__PURE__ */ jsx23(Text20, { muted: true, size: 0, children: "Search & filter" }),
|
|
4116
|
+
/* @__PURE__ */ jsx23(
|
|
3613
4117
|
SearchBar,
|
|
3614
4118
|
{
|
|
3615
4119
|
areas: availableAreas,
|
|
@@ -3622,10 +4126,10 @@ function LatestReports({
|
|
|
3622
4126
|
}
|
|
3623
4127
|
)
|
|
3624
4128
|
] }),
|
|
3625
|
-
/* @__PURE__ */
|
|
3626
|
-
/* @__PURE__ */
|
|
3627
|
-
/* @__PURE__ */
|
|
3628
|
-
/* @__PURE__ */
|
|
4129
|
+
/* @__PURE__ */ jsxs20(Flex16, { gap: 2, children: [
|
|
4130
|
+
/* @__PURE__ */ jsx23(Box8, { flex: 1, children: /* @__PURE__ */ jsxs20(Stack13, { space: 1, children: [
|
|
4131
|
+
/* @__PURE__ */ jsx23(Text20, { muted: true, size: 0, children: "Document" }),
|
|
4132
|
+
/* @__PURE__ */ jsx23(
|
|
3629
4133
|
DocumentFilter,
|
|
3630
4134
|
{
|
|
3631
4135
|
onChange: setDocumentSlug,
|
|
@@ -3634,9 +4138,9 @@ function LatestReports({
|
|
|
3634
4138
|
}
|
|
3635
4139
|
)
|
|
3636
4140
|
] }) }),
|
|
3637
|
-
/* @__PURE__ */
|
|
3638
|
-
/* @__PURE__ */
|
|
3639
|
-
/* @__PURE__ */
|
|
4141
|
+
/* @__PURE__ */ jsx23(Box8, { flex: 1, children: /* @__PURE__ */ jsxs20(Stack13, { space: 1, children: [
|
|
4142
|
+
/* @__PURE__ */ jsx23(Text20, { muted: true, size: 0, children: "Content release" }),
|
|
4143
|
+
/* @__PURE__ */ jsx23(
|
|
3640
4144
|
PerspectiveFilter,
|
|
3641
4145
|
{
|
|
3642
4146
|
onChange: setPerspective,
|
|
@@ -3645,20 +4149,20 @@ function LatestReports({
|
|
|
3645
4149
|
)
|
|
3646
4150
|
] }) })
|
|
3647
4151
|
] }),
|
|
3648
|
-
(documentSlug.trim() || perspective.trim()) && /* @__PURE__ */
|
|
3649
|
-
documentSlug.trim() && /* @__PURE__ */
|
|
4152
|
+
(documentSlug.trim() || perspective.trim()) && /* @__PURE__ */ jsxs20(Flex16, { align: "center", gap: 1, children: [
|
|
4153
|
+
documentSlug.trim() && /* @__PURE__ */ jsxs20(Badge12, { fontSize: 0, tone: "primary", children: [
|
|
3650
4154
|
"Document: ",
|
|
3651
4155
|
documentSlug.trim()
|
|
3652
4156
|
] }),
|
|
3653
|
-
perspective.trim() && /* @__PURE__ */
|
|
4157
|
+
perspective.trim() && /* @__PURE__ */ jsxs20(Badge12, { fontSize: 0, tone: "primary", children: [
|
|
3654
4158
|
"Perspective: ",
|
|
3655
4159
|
perspective.trim()
|
|
3656
4160
|
] })
|
|
3657
4161
|
] })
|
|
3658
4162
|
] }) }),
|
|
3659
|
-
/* @__PURE__ */
|
|
3660
|
-
/* @__PURE__ */
|
|
3661
|
-
hasActiveFilters && /* @__PURE__ */
|
|
4163
|
+
/* @__PURE__ */ jsxs20(Flex16, { align: "center", gap: 2, paddingX: 1, wrap: "wrap", children: [
|
|
4164
|
+
/* @__PURE__ */ jsx23(Text20, { muted: true, size: 1, children: filteredReports.length === reports.length ? `${reports.length} reports` : `${filteredReports.length} of ${reports.length} reports` }),
|
|
4165
|
+
hasActiveFilters && /* @__PURE__ */ jsx23(
|
|
3662
4166
|
Button,
|
|
3663
4167
|
{
|
|
3664
4168
|
fontSize: 0,
|
|
@@ -3668,11 +4172,11 @@ function LatestReports({
|
|
|
3668
4172
|
tone: "critical"
|
|
3669
4173
|
}
|
|
3670
4174
|
),
|
|
3671
|
-
/* @__PURE__ */
|
|
3672
|
-
/* @__PURE__ */
|
|
4175
|
+
/* @__PURE__ */ jsxs20(Flex16, { align: "center", gap: 1, style: { marginLeft: "auto" }, children: [
|
|
4176
|
+
/* @__PURE__ */ jsx23(
|
|
3673
4177
|
MenuButton,
|
|
3674
4178
|
{
|
|
3675
|
-
button: /* @__PURE__ */
|
|
4179
|
+
button: /* @__PURE__ */ jsx23(
|
|
3676
4180
|
Button,
|
|
3677
4181
|
{
|
|
3678
4182
|
fontSize: 1,
|
|
@@ -3682,8 +4186,8 @@ function LatestReports({
|
|
|
3682
4186
|
}
|
|
3683
4187
|
),
|
|
3684
4188
|
id: "sort-menu",
|
|
3685
|
-
menu: /* @__PURE__ */
|
|
3686
|
-
/* @__PURE__ */
|
|
4189
|
+
menu: /* @__PURE__ */ jsxs20(Menu, { children: [
|
|
4190
|
+
/* @__PURE__ */ jsx23(
|
|
3687
4191
|
MenuItem,
|
|
3688
4192
|
{
|
|
3689
4193
|
onClick: () => handleSortFieldChange("date"),
|
|
@@ -3691,7 +4195,7 @@ function LatestReports({
|
|
|
3691
4195
|
text: "Date"
|
|
3692
4196
|
}
|
|
3693
4197
|
),
|
|
3694
|
-
/* @__PURE__ */
|
|
4198
|
+
/* @__PURE__ */ jsx23(
|
|
3695
4199
|
MenuItem,
|
|
3696
4200
|
{
|
|
3697
4201
|
onClick: () => handleSortFieldChange("score"),
|
|
@@ -3699,7 +4203,7 @@ function LatestReports({
|
|
|
3699
4203
|
text: "Score"
|
|
3700
4204
|
}
|
|
3701
4205
|
),
|
|
3702
|
-
/* @__PURE__ */
|
|
4206
|
+
/* @__PURE__ */ jsx23(
|
|
3703
4207
|
MenuItem,
|
|
3704
4208
|
{
|
|
3705
4209
|
onClick: () => handleSortFieldChange("name"),
|
|
@@ -3711,7 +4215,7 @@ function LatestReports({
|
|
|
3711
4215
|
popover: { portal: true }
|
|
3712
4216
|
}
|
|
3713
4217
|
),
|
|
3714
|
-
/* @__PURE__ */
|
|
4218
|
+
/* @__PURE__ */ jsx23(
|
|
3715
4219
|
Button,
|
|
3716
4220
|
{
|
|
3717
4221
|
fontSize: 1,
|
|
@@ -3723,9 +4227,9 @@ function LatestReports({
|
|
|
3723
4227
|
)
|
|
3724
4228
|
] })
|
|
3725
4229
|
] }),
|
|
3726
|
-
filteredReports.length === 0 ? /* @__PURE__ */
|
|
3727
|
-
/* @__PURE__ */
|
|
3728
|
-
/* @__PURE__ */
|
|
4230
|
+
filteredReports.length === 0 ? /* @__PURE__ */ jsx23(Card12, { padding: 4, radius: 2, shadow: 1, children: /* @__PURE__ */ jsxs20(Stack13, { space: 3, children: [
|
|
4231
|
+
/* @__PURE__ */ jsx23(Text20, { align: "center", muted: true, size: 2, children: "No reports match the current filters." }),
|
|
4232
|
+
/* @__PURE__ */ jsx23(Flex16, { justify: "center", children: /* @__PURE__ */ jsx23(
|
|
3729
4233
|
Button,
|
|
3730
4234
|
{
|
|
3731
4235
|
fontSize: 1,
|
|
@@ -3734,7 +4238,7 @@ function LatestReports({
|
|
|
3734
4238
|
text: "Clear all filters"
|
|
3735
4239
|
}
|
|
3736
4240
|
) })
|
|
3737
|
-
] }) }) : /* @__PURE__ */
|
|
4241
|
+
] }) }) : /* @__PURE__ */ jsx23(Stack13, { space: 2, children: filteredReports.map((report) => /* @__PURE__ */ jsx23(
|
|
3738
4242
|
ReportCard,
|
|
3739
4243
|
{
|
|
3740
4244
|
data: fromReportListItem(report),
|
|
@@ -3742,7 +4246,7 @@ function LatestReports({
|
|
|
3742
4246
|
},
|
|
3743
4247
|
report._id
|
|
3744
4248
|
)) }),
|
|
3745
|
-
hasMore && /* @__PURE__ */
|
|
4249
|
+
hasMore && /* @__PURE__ */ jsx23(Flex16, { justify: "center", paddingY: 3, children: /* @__PURE__ */ jsx23(
|
|
3746
4250
|
Button,
|
|
3747
4251
|
{
|
|
3748
4252
|
disabled: loadingMore,
|
|
@@ -3790,28 +4294,28 @@ function getDateThreshold(preset) {
|
|
|
3790
4294
|
|
|
3791
4295
|
// src/components/report-detail/ReportDetail.tsx
|
|
3792
4296
|
import { ArrowLeftIcon as ArrowLeftIcon2 } from "@sanity/icons";
|
|
3793
|
-
import { Box as
|
|
3794
|
-
import { useCallback as
|
|
4297
|
+
import { Box as Box14, Button as Button3, Stack as Stack22, Text as Text30, useToast } from "@sanity/ui";
|
|
4298
|
+
import { useCallback as useCallback12, useEffect as useEffect7, useState as useState8 } from "react";
|
|
3795
4299
|
import { useClient as useClient6 } from "sanity";
|
|
3796
4300
|
|
|
3797
4301
|
// src/components/report-detail/AreaScoreTable.tsx
|
|
3798
4302
|
import React from "react";
|
|
3799
|
-
import { Card as
|
|
4303
|
+
import { Card as Card14, Stack as Stack14, Text as Text22 } from "@sanity/ui";
|
|
3800
4304
|
|
|
3801
4305
|
// src/components/primitives/ScoreCell.tsx
|
|
3802
|
-
import { Card as
|
|
3803
|
-
import { jsx as
|
|
4306
|
+
import { Card as Card13, Text as Text21 } from "@sanity/ui";
|
|
4307
|
+
import { jsx as jsx24 } from "react/jsx-runtime";
|
|
3804
4308
|
function ScoreCell({ score, size = 1 }) {
|
|
3805
4309
|
const rounded = Math.round(score);
|
|
3806
|
-
return /* @__PURE__ */
|
|
4310
|
+
return /* @__PURE__ */ jsx24(Card13, { padding: 1, radius: 2, tone: scoreTone(rounded), children: /* @__PURE__ */ jsx24(Text21, { align: "center", size, weight: "medium", children: rounded }) });
|
|
3807
4311
|
}
|
|
3808
4312
|
|
|
3809
4313
|
// src/components/report-detail/AreaScoreTable.tsx
|
|
3810
|
-
import { jsx as
|
|
4314
|
+
import { jsx as jsx25, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
3811
4315
|
function AreaScoreTable({ scores }) {
|
|
3812
|
-
return /* @__PURE__ */
|
|
3813
|
-
/* @__PURE__ */
|
|
3814
|
-
/* @__PURE__ */
|
|
4316
|
+
return /* @__PURE__ */ jsx25(Card14, { overflow: "auto", padding: 4, radius: 2, shadow: 1, children: /* @__PURE__ */ jsxs21(Stack14, { space: 4, children: [
|
|
4317
|
+
/* @__PURE__ */ jsx25(Text22, { size: 2, weight: "semibold", children: "Per-Area Scores" }),
|
|
4318
|
+
/* @__PURE__ */ jsxs21(
|
|
3815
4319
|
"div",
|
|
3816
4320
|
{
|
|
3817
4321
|
style: {
|
|
@@ -3820,9 +4324,9 @@ function AreaScoreTable({ scores }) {
|
|
|
3820
4324
|
gridTemplateColumns: "2fr 1fr 1fr 1fr 1fr 1fr 1fr"
|
|
3821
4325
|
},
|
|
3822
4326
|
children: [
|
|
3823
|
-
/* @__PURE__ */
|
|
3824
|
-
/* @__PURE__ */
|
|
3825
|
-
/* @__PURE__ */
|
|
4327
|
+
/* @__PURE__ */ jsx25(ColumnHeader, { borderBottom: true, label: "Area" }),
|
|
4328
|
+
/* @__PURE__ */ jsx25(ColumnHeader, { borderBottom: true, label: "Score", tooltip: GLOSSARY.score }),
|
|
4329
|
+
/* @__PURE__ */ jsx25(
|
|
3826
4330
|
ColumnHeader,
|
|
3827
4331
|
{
|
|
3828
4332
|
borderBottom: true,
|
|
@@ -3830,7 +4334,7 @@ function AreaScoreTable({ scores }) {
|
|
|
3830
4334
|
tooltip: GLOSSARY.taskCompletion
|
|
3831
4335
|
}
|
|
3832
4336
|
),
|
|
3833
|
-
/* @__PURE__ */
|
|
4337
|
+
/* @__PURE__ */ jsx25(
|
|
3834
4338
|
ColumnHeader,
|
|
3835
4339
|
{
|
|
3836
4340
|
borderBottom: true,
|
|
@@ -3838,7 +4342,7 @@ function AreaScoreTable({ scores }) {
|
|
|
3838
4342
|
tooltip: GLOSSARY.codeCorrectness
|
|
3839
4343
|
}
|
|
3840
4344
|
),
|
|
3841
|
-
/* @__PURE__ */
|
|
4345
|
+
/* @__PURE__ */ jsx25(
|
|
3842
4346
|
ColumnHeader,
|
|
3843
4347
|
{
|
|
3844
4348
|
borderBottom: true,
|
|
@@ -3846,10 +4350,10 @@ function AreaScoreTable({ scores }) {
|
|
|
3846
4350
|
tooltip: GLOSSARY.docCoverage
|
|
3847
4351
|
}
|
|
3848
4352
|
),
|
|
3849
|
-
/* @__PURE__ */
|
|
3850
|
-
/* @__PURE__ */
|
|
3851
|
-
scores.map((score, i) => /* @__PURE__ */
|
|
3852
|
-
/* @__PURE__ */
|
|
4353
|
+
/* @__PURE__ */ jsx25(ColumnHeader, { borderBottom: true, label: "Lift", tooltip: GLOSSARY.docLift }),
|
|
4354
|
+
/* @__PURE__ */ jsx25(ColumnHeader, { borderBottom: true, label: "Tests", tooltip: GLOSSARY.tests }),
|
|
4355
|
+
scores.map((score, i) => /* @__PURE__ */ jsxs21(React.Fragment, { children: [
|
|
4356
|
+
/* @__PURE__ */ jsx25(
|
|
3853
4357
|
"div",
|
|
3854
4358
|
{
|
|
3855
4359
|
style: {
|
|
@@ -3857,14 +4361,14 @@ function AreaScoreTable({ scores }) {
|
|
|
3857
4361
|
borderRadius: 4,
|
|
3858
4362
|
padding: "8px 0 8px 4px"
|
|
3859
4363
|
},
|
|
3860
|
-
children: /* @__PURE__ */
|
|
4364
|
+
children: /* @__PURE__ */ jsx25(Text22, { size: 1, weight: "medium", children: score.feature })
|
|
3861
4365
|
}
|
|
3862
4366
|
),
|
|
3863
|
-
/* @__PURE__ */
|
|
3864
|
-
/* @__PURE__ */
|
|
3865
|
-
/* @__PURE__ */
|
|
3866
|
-
/* @__PURE__ */
|
|
3867
|
-
/* @__PURE__ */
|
|
4367
|
+
/* @__PURE__ */ jsx25("div", { style: { background: rowBackground(i), padding: "6px 0" }, children: /* @__PURE__ */ jsx25(ScoreCell, { score: score.totalScore }) }),
|
|
4368
|
+
/* @__PURE__ */ jsx25("div", { style: { background: rowBackground(i), padding: "6px 0" }, children: /* @__PURE__ */ jsx25(ScoreCell, { score: score.taskCompletion }) }),
|
|
4369
|
+
/* @__PURE__ */ jsx25("div", { style: { background: rowBackground(i), padding: "6px 0" }, children: /* @__PURE__ */ jsx25(ScoreCell, { score: score.codeCorrectness }) }),
|
|
4370
|
+
/* @__PURE__ */ jsx25("div", { style: { background: rowBackground(i), padding: "6px 0" }, children: /* @__PURE__ */ jsx25(ScoreCell, { score: score.docCoverage }) }),
|
|
4371
|
+
/* @__PURE__ */ jsx25(
|
|
3868
4372
|
"div",
|
|
3869
4373
|
{
|
|
3870
4374
|
style: {
|
|
@@ -3872,10 +4376,10 @@ function AreaScoreTable({ scores }) {
|
|
|
3872
4376
|
background: rowBackground(i),
|
|
3873
4377
|
display: "flex"
|
|
3874
4378
|
},
|
|
3875
|
-
children: /* @__PURE__ */
|
|
4379
|
+
children: /* @__PURE__ */ jsx25(Text22, { size: 1, children: formatDelta(score.docLift) })
|
|
3876
4380
|
}
|
|
3877
4381
|
),
|
|
3878
|
-
/* @__PURE__ */
|
|
4382
|
+
/* @__PURE__ */ jsx25(
|
|
3879
4383
|
"div",
|
|
3880
4384
|
{
|
|
3881
4385
|
style: {
|
|
@@ -3883,7 +4387,7 @@ function AreaScoreTable({ scores }) {
|
|
|
3883
4387
|
background: rowBackground(i),
|
|
3884
4388
|
display: "flex"
|
|
3885
4389
|
},
|
|
3886
|
-
children: /* @__PURE__ */
|
|
4390
|
+
children: /* @__PURE__ */ jsx25(Text22, { muted: true, size: 1, children: score.testCount })
|
|
3887
4391
|
}
|
|
3888
4392
|
)
|
|
3889
4393
|
] }, score.feature))
|
|
@@ -3894,13 +4398,13 @@ function AreaScoreTable({ scores }) {
|
|
|
3894
4398
|
}
|
|
3895
4399
|
|
|
3896
4400
|
// src/components/report-detail/ComparisonSummary.tsx
|
|
3897
|
-
import { Badge as
|
|
3898
|
-
import { jsx as
|
|
4401
|
+
import { Badge as Badge13, Box as Box9, Card as Card15, Flex as Flex17, Grid as Grid2, Stack as Stack15, Text as Text23, Tooltip as Tooltip3 } from "@sanity/ui";
|
|
4402
|
+
import { jsx as jsx26, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
3899
4403
|
function ComparisonSummary({ comparison }) {
|
|
3900
|
-
return /* @__PURE__ */
|
|
3901
|
-
/* @__PURE__ */
|
|
3902
|
-
/* @__PURE__ */
|
|
3903
|
-
/* @__PURE__ */
|
|
4404
|
+
return /* @__PURE__ */ jsx26(Card15, { padding: 4, radius: 2, shadow: 1, children: /* @__PURE__ */ jsxs22(Stack15, { space: 4, children: [
|
|
4405
|
+
/* @__PURE__ */ jsxs22(Flex17, { align: "center", gap: 3, wrap: "wrap", children: [
|
|
4406
|
+
/* @__PURE__ */ jsx26(Text23, { size: 2, weight: "semibold", children: "Comparison" }),
|
|
4407
|
+
/* @__PURE__ */ jsx26(
|
|
3904
4408
|
DeltaCard,
|
|
3905
4409
|
{
|
|
3906
4410
|
delta: comparison.deltas.overall,
|
|
@@ -3908,7 +4412,7 @@ function ComparisonSummary({ comparison }) {
|
|
|
3908
4412
|
tooltip: GLOSSARY.overallDelta
|
|
3909
4413
|
}
|
|
3910
4414
|
),
|
|
3911
|
-
comparison.deltas.actualDelta != null && /* @__PURE__ */
|
|
4415
|
+
comparison.deltas.actualDelta != null && /* @__PURE__ */ jsx26(
|
|
3912
4416
|
DeltaCard,
|
|
3913
4417
|
{
|
|
3914
4418
|
delta: comparison.deltas.actualDelta,
|
|
@@ -3916,7 +4420,7 @@ function ComparisonSummary({ comparison }) {
|
|
|
3916
4420
|
tooltip: GLOSSARY.actualDelta
|
|
3917
4421
|
}
|
|
3918
4422
|
),
|
|
3919
|
-
comparison.deltas.retrievalGapDelta != null && /* @__PURE__ */
|
|
4423
|
+
comparison.deltas.retrievalGapDelta != null && /* @__PURE__ */ jsx26(
|
|
3920
4424
|
DeltaCard,
|
|
3921
4425
|
{
|
|
3922
4426
|
delta: comparison.deltas.retrievalGapDelta,
|
|
@@ -3926,8 +4430,8 @@ function ComparisonSummary({ comparison }) {
|
|
|
3926
4430
|
}
|
|
3927
4431
|
)
|
|
3928
4432
|
] }),
|
|
3929
|
-
/* @__PURE__ */
|
|
3930
|
-
comparison.improved.length > 0 && /* @__PURE__ */
|
|
4433
|
+
/* @__PURE__ */ jsxs22(Grid2, { columns: [1, 1, 3], gap: 3, children: [
|
|
4434
|
+
comparison.improved.length > 0 && /* @__PURE__ */ jsx26(
|
|
3931
4435
|
AreaBadgeGroup,
|
|
3932
4436
|
{
|
|
3933
4437
|
areas: comparison.improved,
|
|
@@ -3935,7 +4439,7 @@ function ComparisonSummary({ comparison }) {
|
|
|
3935
4439
|
tone: "positive"
|
|
3936
4440
|
}
|
|
3937
4441
|
),
|
|
3938
|
-
comparison.regressed.length > 0 && /* @__PURE__ */
|
|
4442
|
+
comparison.regressed.length > 0 && /* @__PURE__ */ jsx26(
|
|
3939
4443
|
AreaBadgeGroup,
|
|
3940
4444
|
{
|
|
3941
4445
|
areas: comparison.regressed,
|
|
@@ -3943,7 +4447,7 @@ function ComparisonSummary({ comparison }) {
|
|
|
3943
4447
|
tone: "critical"
|
|
3944
4448
|
}
|
|
3945
4449
|
),
|
|
3946
|
-
comparison.unchanged.length > 0 && /* @__PURE__ */
|
|
4450
|
+
comparison.unchanged.length > 0 && /* @__PURE__ */ jsx26(
|
|
3947
4451
|
AreaBadgeGroup,
|
|
3948
4452
|
{
|
|
3949
4453
|
areas: comparison.unchanged,
|
|
@@ -3962,19 +4466,19 @@ function DeltaCard({
|
|
|
3962
4466
|
}) {
|
|
3963
4467
|
const isPositive = invertedPolarity ? delta < 0 : delta > 0;
|
|
3964
4468
|
const isNegative = invertedPolarity ? delta > 0 : delta < 0;
|
|
3965
|
-
return /* @__PURE__ */
|
|
4469
|
+
return /* @__PURE__ */ jsx26(
|
|
3966
4470
|
Tooltip3,
|
|
3967
4471
|
{
|
|
3968
|
-
content: /* @__PURE__ */
|
|
4472
|
+
content: /* @__PURE__ */ jsx26(Box9, { padding: 2, style: { maxWidth: 260 }, children: /* @__PURE__ */ jsx26(Text23, { size: 1, children: tooltip }) }),
|
|
3969
4473
|
placement: "bottom",
|
|
3970
4474
|
portal: true,
|
|
3971
|
-
children: /* @__PURE__ */
|
|
3972
|
-
|
|
4475
|
+
children: /* @__PURE__ */ jsx26(
|
|
4476
|
+
Card15,
|
|
3973
4477
|
{
|
|
3974
4478
|
padding: 2,
|
|
3975
4479
|
radius: 2,
|
|
3976
4480
|
tone: isPositive ? "positive" : isNegative ? "critical" : "default",
|
|
3977
|
-
children: /* @__PURE__ */
|
|
4481
|
+
children: /* @__PURE__ */ jsxs22(Text23, { size: 1, weight: "bold", children: [
|
|
3978
4482
|
formatDelta(delta),
|
|
3979
4483
|
" ",
|
|
3980
4484
|
label
|
|
@@ -3989,9 +4493,9 @@ function AreaBadgeGroup({
|
|
|
3989
4493
|
label,
|
|
3990
4494
|
tone
|
|
3991
4495
|
}) {
|
|
3992
|
-
return /* @__PURE__ */
|
|
3993
|
-
/* @__PURE__ */
|
|
3994
|
-
|
|
4496
|
+
return /* @__PURE__ */ jsxs22(Stack15, { space: 2, children: [
|
|
4497
|
+
/* @__PURE__ */ jsx26(
|
|
4498
|
+
Text23,
|
|
3995
4499
|
{
|
|
3996
4500
|
muted: true,
|
|
3997
4501
|
size: 0,
|
|
@@ -4000,21 +4504,21 @@ function AreaBadgeGroup({
|
|
|
4000
4504
|
children: label
|
|
4001
4505
|
}
|
|
4002
4506
|
),
|
|
4003
|
-
/* @__PURE__ */
|
|
4507
|
+
/* @__PURE__ */ jsx26(Flex17, { gap: 1, wrap: "wrap", children: areas.map((a) => /* @__PURE__ */ jsx26(Badge13, { tone, children: a }, a)) })
|
|
4004
4508
|
] });
|
|
4005
4509
|
}
|
|
4006
4510
|
|
|
4007
4511
|
// src/components/report-detail/JudgmentList.tsx
|
|
4008
4512
|
import { useState as useState7 } from "react";
|
|
4009
|
-
import { HelpCircleIcon as
|
|
4010
|
-
import { Badge as
|
|
4513
|
+
import { HelpCircleIcon as HelpCircleIcon4 } from "@sanity/icons";
|
|
4514
|
+
import { Badge as Badge14, Box as Box10, Card as Card16, Flex as Flex18, Stack as Stack16, Text as Text24, Tooltip as Tooltip4 } from "@sanity/ui";
|
|
4011
4515
|
|
|
4012
4516
|
// src/components/primitives/InlineCode.tsx
|
|
4013
|
-
import { Fragment as
|
|
4517
|
+
import { Fragment as Fragment4, jsx as jsx27 } from "react/jsx-runtime";
|
|
4014
4518
|
function InlineCode({ text }) {
|
|
4015
4519
|
const parts = text.split(/`([^`]+)`/);
|
|
4016
|
-
return /* @__PURE__ */
|
|
4017
|
-
(part, i) => i % 2 === 1 ? /* @__PURE__ */
|
|
4520
|
+
return /* @__PURE__ */ jsx27(Fragment4, { children: parts.map(
|
|
4521
|
+
(part, i) => i % 2 === 1 ? /* @__PURE__ */ jsx27(
|
|
4018
4522
|
"code",
|
|
4019
4523
|
{
|
|
4020
4524
|
style: {
|
|
@@ -4026,12 +4530,12 @@ function InlineCode({ text }) {
|
|
|
4026
4530
|
children: part
|
|
4027
4531
|
},
|
|
4028
4532
|
i
|
|
4029
|
-
) : /* @__PURE__ */
|
|
4533
|
+
) : /* @__PURE__ */ jsx27("span", { children: part }, i)
|
|
4030
4534
|
) });
|
|
4031
4535
|
}
|
|
4032
4536
|
|
|
4033
4537
|
// src/components/report-detail/JudgmentList.tsx
|
|
4034
|
-
import { jsx as
|
|
4538
|
+
import { jsx as jsx28, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
4035
4539
|
function groupByArea(judgments) {
|
|
4036
4540
|
const byArea = /* @__PURE__ */ new Map();
|
|
4037
4541
|
for (const j of judgments) {
|
|
@@ -4046,36 +4550,36 @@ var DIMENSION_LABELS = DIMENSION_LABELS_KEBAB;
|
|
|
4046
4550
|
function JudgmentList({ judgments }) {
|
|
4047
4551
|
if (judgments.length === 0) return null;
|
|
4048
4552
|
const grouped = groupByArea(judgments);
|
|
4049
|
-
return /* @__PURE__ */
|
|
4050
|
-
/* @__PURE__ */
|
|
4051
|
-
/* @__PURE__ */
|
|
4052
|
-
/* @__PURE__ */
|
|
4553
|
+
return /* @__PURE__ */ jsx28(Card16, { padding: 4, radius: 2, shadow: 1, children: /* @__PURE__ */ jsxs23(Stack16, { space: 4, children: [
|
|
4554
|
+
/* @__PURE__ */ jsxs23(Flex18, { align: "center", gap: 3, wrap: "wrap", children: [
|
|
4555
|
+
/* @__PURE__ */ jsx28(Text24, { size: 2, weight: "semibold", children: "Low-Scoring Judgments" }),
|
|
4556
|
+
/* @__PURE__ */ jsx28(
|
|
4053
4557
|
Tooltip4,
|
|
4054
4558
|
{
|
|
4055
|
-
content: /* @__PURE__ */
|
|
4559
|
+
content: /* @__PURE__ */ jsx28(Box10, { padding: 2, style: { maxWidth: 260 }, children: /* @__PURE__ */ jsx28(Text24, { size: 1, children: GLOSSARY.lowScoringJudgments }) }),
|
|
4056
4560
|
placement: "bottom",
|
|
4057
4561
|
portal: true,
|
|
4058
|
-
children: /* @__PURE__ */
|
|
4562
|
+
children: /* @__PURE__ */ jsx28(Text24, { muted: true, size: 0, children: /* @__PURE__ */ jsx28(HelpCircleIcon4, {}) })
|
|
4059
4563
|
}
|
|
4060
4564
|
),
|
|
4061
|
-
/* @__PURE__ */
|
|
4565
|
+
/* @__PURE__ */ jsx28(Card16, { padding: 2, radius: 2, tone: "critical", children: /* @__PURE__ */ jsxs23(Text24, { size: 1, weight: "bold", children: [
|
|
4062
4566
|
judgments.length,
|
|
4063
4567
|
" judgment",
|
|
4064
4568
|
judgments.length === 1 ? "" : "s",
|
|
4065
4569
|
" below 70"
|
|
4066
4570
|
] }) })
|
|
4067
4571
|
] }),
|
|
4068
|
-
grouped.map(([area, areaJudgments]) => /* @__PURE__ */
|
|
4069
|
-
/* @__PURE__ */
|
|
4572
|
+
grouped.map(([area, areaJudgments]) => /* @__PURE__ */ jsx28(Card16, { padding: 3, radius: 2, tone: "transparent", children: /* @__PURE__ */ jsxs23(Stack16, { space: 3, children: [
|
|
4573
|
+
/* @__PURE__ */ jsxs23(Text24, { size: 1, weight: "semibold", children: [
|
|
4070
4574
|
area,
|
|
4071
4575
|
" ",
|
|
4072
|
-
/* @__PURE__ */
|
|
4576
|
+
/* @__PURE__ */ jsxs23(Text24, { muted: true, size: 1, weight: "regular", as: "span", children: [
|
|
4073
4577
|
"(",
|
|
4074
4578
|
areaJudgments.length,
|
|
4075
4579
|
")"
|
|
4076
4580
|
] })
|
|
4077
4581
|
] }),
|
|
4078
|
-
areaJudgments.map((j, i) => /* @__PURE__ */
|
|
4582
|
+
areaJudgments.map((j, i) => /* @__PURE__ */ jsx28(JudgmentCard, { judgment: j }, `${area}-${i}`))
|
|
4079
4583
|
] }) }, area))
|
|
4080
4584
|
] }) });
|
|
4081
4585
|
}
|
|
@@ -4084,18 +4588,18 @@ function JudgmentCard({ judgment }) {
|
|
|
4084
4588
|
const dimLabel = DIMENSION_LABELS[judgment.dimension] ?? judgment.dimension;
|
|
4085
4589
|
const sep = judgment.taskId.indexOf(" - ");
|
|
4086
4590
|
const taskName = sep > 0 ? judgment.taskId.substring(sep + 3) : judgment.taskId;
|
|
4087
|
-
return /* @__PURE__ */
|
|
4088
|
-
|
|
4591
|
+
return /* @__PURE__ */ jsx28(
|
|
4592
|
+
Card16,
|
|
4089
4593
|
{
|
|
4090
4594
|
padding: 3,
|
|
4091
4595
|
radius: 2,
|
|
4092
4596
|
shadow: 1,
|
|
4093
4597
|
style: { cursor: "pointer" },
|
|
4094
4598
|
onClick: () => setExpanded(!expanded),
|
|
4095
|
-
children: /* @__PURE__ */
|
|
4096
|
-
/* @__PURE__ */
|
|
4097
|
-
/* @__PURE__ */
|
|
4098
|
-
|
|
4599
|
+
children: /* @__PURE__ */ jsxs23(Stack16, { space: 3, children: [
|
|
4600
|
+
/* @__PURE__ */ jsxs23(Flex18, { align: "center", gap: 2, wrap: "wrap", children: [
|
|
4601
|
+
/* @__PURE__ */ jsx28(Card16, { padding: 2, radius: 2, tone: scoreTone(judgment.score), children: /* @__PURE__ */ jsx28(
|
|
4602
|
+
Text24,
|
|
4099
4603
|
{
|
|
4100
4604
|
align: "center",
|
|
4101
4605
|
size: 1,
|
|
@@ -4104,32 +4608,32 @@ function JudgmentCard({ judgment }) {
|
|
|
4104
4608
|
children: judgment.score
|
|
4105
4609
|
}
|
|
4106
4610
|
) }),
|
|
4107
|
-
/* @__PURE__ */
|
|
4108
|
-
/* @__PURE__ */
|
|
4109
|
-
/* @__PURE__ */
|
|
4110
|
-
/* @__PURE__ */
|
|
4611
|
+
/* @__PURE__ */ jsx28(Badge14, { tone: "default", children: dimLabel }),
|
|
4612
|
+
/* @__PURE__ */ jsx28(Text24, { size: 1, weight: "medium", children: taskName }),
|
|
4613
|
+
/* @__PURE__ */ jsx28(Text24, { muted: true, size: 0, children: judgment.modelId }),
|
|
4614
|
+
/* @__PURE__ */ jsx28(Text24, { muted: true, size: 0, style: { marginLeft: "auto" }, children: expanded ? "\u25B2" : "\u25BC" })
|
|
4111
4615
|
] }),
|
|
4112
|
-
expanded && /* @__PURE__ */
|
|
4113
|
-
/* @__PURE__ */
|
|
4114
|
-
|
|
4616
|
+
expanded && /* @__PURE__ */ jsxs23(Stack16, { space: 3, children: [
|
|
4617
|
+
/* @__PURE__ */ jsx28(Card16, { padding: 3, radius: 2, tone: "transparent", children: /* @__PURE__ */ jsx28(
|
|
4618
|
+
Text24,
|
|
4115
4619
|
{
|
|
4116
4620
|
muted: true,
|
|
4117
4621
|
size: 1,
|
|
4118
4622
|
style: { lineHeight: 1.6, whiteSpace: "pre-wrap" },
|
|
4119
|
-
children: /* @__PURE__ */
|
|
4623
|
+
children: /* @__PURE__ */ jsx28(InlineCode, { text: judgment.reason })
|
|
4120
4624
|
}
|
|
4121
4625
|
) }),
|
|
4122
|
-
judgment.canonicalDocs && judgment.canonicalDocs.length > 0 && /* @__PURE__ */
|
|
4123
|
-
/* @__PURE__ */
|
|
4626
|
+
judgment.canonicalDocs && judgment.canonicalDocs.length > 0 && /* @__PURE__ */ jsxs23(Flex18, { align: "center", gap: 2, wrap: "wrap", children: [
|
|
4627
|
+
/* @__PURE__ */ jsx28(Text24, { muted: true, size: 0, children: "Docs:" }),
|
|
4124
4628
|
judgment.canonicalDocs.map((doc) => {
|
|
4125
|
-
const badge = /* @__PURE__ */
|
|
4126
|
-
return /* @__PURE__ */
|
|
4629
|
+
const badge = /* @__PURE__ */ jsx28(Badge14, { mode: "outline", tone: "primary", children: doc.slug });
|
|
4630
|
+
return /* @__PURE__ */ jsx28(
|
|
4127
4631
|
Tooltip4,
|
|
4128
4632
|
{
|
|
4129
|
-
content: /* @__PURE__ */
|
|
4633
|
+
content: /* @__PURE__ */ jsx28(Box10, { padding: 2, children: /* @__PURE__ */ jsx28(Text24, { size: 1, children: doc.title || doc.slug }) }),
|
|
4130
4634
|
placement: "bottom",
|
|
4131
4635
|
portal: true,
|
|
4132
|
-
children: doc.documentId ? /* @__PURE__ */
|
|
4636
|
+
children: doc.documentId ? /* @__PURE__ */ jsx28(
|
|
4133
4637
|
"a",
|
|
4134
4638
|
{
|
|
4135
4639
|
href: `/intent/edit/id=${doc.documentId}`,
|
|
@@ -4153,9 +4657,9 @@ function JudgmentCard({ judgment }) {
|
|
|
4153
4657
|
import { Grid as Grid3 } from "@sanity/ui";
|
|
4154
4658
|
|
|
4155
4659
|
// src/components/primitives/StatCard.tsx
|
|
4156
|
-
import { HelpCircleIcon as
|
|
4157
|
-
import { Box as
|
|
4158
|
-
import { Fragment as
|
|
4660
|
+
import { HelpCircleIcon as HelpCircleIcon5 } from "@sanity/icons";
|
|
4661
|
+
import { Box as Box11, Card as Card17, Stack as Stack17, Text as Text25, Tooltip as Tooltip5 } from "@sanity/ui";
|
|
4662
|
+
import { Fragment as Fragment5, jsx as jsx29, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
4159
4663
|
function StatCard({
|
|
4160
4664
|
label,
|
|
4161
4665
|
value,
|
|
@@ -4163,24 +4667,24 @@ function StatCard({
|
|
|
4163
4667
|
suffix,
|
|
4164
4668
|
tone = "default"
|
|
4165
4669
|
}) {
|
|
4166
|
-
return /* @__PURE__ */
|
|
4167
|
-
/* @__PURE__ */
|
|
4670
|
+
return /* @__PURE__ */ jsx29(Card17, { padding: 3, radius: 2, shadow: 1, tone, children: /* @__PURE__ */ jsxs24(Stack17, { space: 2, children: [
|
|
4671
|
+
/* @__PURE__ */ jsxs24(Text25, { muted: true, size: 1, children: [
|
|
4168
4672
|
label,
|
|
4169
|
-
tooltip && /* @__PURE__ */
|
|
4673
|
+
tooltip && /* @__PURE__ */ jsxs24(Fragment5, { children: [
|
|
4170
4674
|
" ",
|
|
4171
|
-
/* @__PURE__ */
|
|
4675
|
+
/* @__PURE__ */ jsx29(
|
|
4172
4676
|
Tooltip5,
|
|
4173
4677
|
{
|
|
4174
|
-
content: /* @__PURE__ */
|
|
4678
|
+
content: /* @__PURE__ */ jsx29(Box11, { padding: 2, children: /* @__PURE__ */ jsx29(Text25, { size: 1, children: tooltip }) }),
|
|
4175
4679
|
portal: true,
|
|
4176
|
-
children: /* @__PURE__ */
|
|
4680
|
+
children: /* @__PURE__ */ jsx29("span", { style: { cursor: "help" }, children: /* @__PURE__ */ jsx29(HelpCircleIcon5, {}) })
|
|
4177
4681
|
}
|
|
4178
4682
|
)
|
|
4179
4683
|
] })
|
|
4180
4684
|
] }),
|
|
4181
|
-
/* @__PURE__ */
|
|
4685
|
+
/* @__PURE__ */ jsxs24(Text25, { size: 3, weight: "bold", children: [
|
|
4182
4686
|
value,
|
|
4183
|
-
suffix && /* @__PURE__ */
|
|
4687
|
+
suffix && /* @__PURE__ */ jsxs24("span", { style: { fontSize: "0.6em", fontWeight: 400 }, children: [
|
|
4184
4688
|
" ",
|
|
4185
4689
|
suffix
|
|
4186
4690
|
] })
|
|
@@ -4189,7 +4693,7 @@ function StatCard({
|
|
|
4189
4693
|
}
|
|
4190
4694
|
|
|
4191
4695
|
// src/components/report-detail/OverviewStats.tsx
|
|
4192
|
-
import { jsx as
|
|
4696
|
+
import { jsx as jsx30, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
4193
4697
|
function OverviewStats({
|
|
4194
4698
|
overall,
|
|
4195
4699
|
durationMs,
|
|
@@ -4197,8 +4701,8 @@ function OverviewStats({
|
|
|
4197
4701
|
isFullMode
|
|
4198
4702
|
}) {
|
|
4199
4703
|
const overallTone = scoreTone(overall.avgScore);
|
|
4200
|
-
return /* @__PURE__ */
|
|
4201
|
-
/* @__PURE__ */
|
|
4704
|
+
return /* @__PURE__ */ jsxs25(Grid3, { columns: [1, 1, 2, isFullMode ? 4 : 4], gap: 3, children: [
|
|
4705
|
+
/* @__PURE__ */ jsx30(
|
|
4202
4706
|
StatCard,
|
|
4203
4707
|
{
|
|
4204
4708
|
label: "Overall Score",
|
|
@@ -4207,7 +4711,7 @@ function OverviewStats({
|
|
|
4207
4711
|
value: overall.avgScore.toFixed(1)
|
|
4208
4712
|
}
|
|
4209
4713
|
),
|
|
4210
|
-
/* @__PURE__ */
|
|
4714
|
+
/* @__PURE__ */ jsx30(
|
|
4211
4715
|
StatCard,
|
|
4212
4716
|
{
|
|
4213
4717
|
label: "Doc Lift",
|
|
@@ -4216,7 +4720,7 @@ function OverviewStats({
|
|
|
4216
4720
|
value: overall.avgDocLift.toFixed(1)
|
|
4217
4721
|
}
|
|
4218
4722
|
),
|
|
4219
|
-
isFullMode && overall.avgActualScore != null && /* @__PURE__ */
|
|
4723
|
+
isFullMode && overall.avgActualScore != null && /* @__PURE__ */ jsx30(
|
|
4220
4724
|
StatCard,
|
|
4221
4725
|
{
|
|
4222
4726
|
label: "Actual Score",
|
|
@@ -4225,7 +4729,7 @@ function OverviewStats({
|
|
|
4225
4729
|
value: overall.avgActualScore.toFixed(1)
|
|
4226
4730
|
}
|
|
4227
4731
|
),
|
|
4228
|
-
isFullMode && overall.avgRetrievalGap != null && /* @__PURE__ */
|
|
4732
|
+
isFullMode && overall.avgRetrievalGap != null && /* @__PURE__ */ jsx30(
|
|
4229
4733
|
StatCard,
|
|
4230
4734
|
{
|
|
4231
4735
|
label: "Retrieval Gap",
|
|
@@ -4235,7 +4739,7 @@ function OverviewStats({
|
|
|
4235
4739
|
value: overall.avgRetrievalGap.toFixed(1)
|
|
4236
4740
|
}
|
|
4237
4741
|
),
|
|
4238
|
-
isFullMode && overall.avgInfrastructureEfficiency != null && /* @__PURE__ */
|
|
4742
|
+
isFullMode && overall.avgInfrastructureEfficiency != null && /* @__PURE__ */ jsx30(
|
|
4239
4743
|
StatCard,
|
|
4240
4744
|
{
|
|
4241
4745
|
label: "Infra Efficiency",
|
|
@@ -4243,8 +4747,8 @@ function OverviewStats({
|
|
|
4243
4747
|
value: formatPercent(overall.avgInfrastructureEfficiency)
|
|
4244
4748
|
}
|
|
4245
4749
|
),
|
|
4246
|
-
/* @__PURE__ */
|
|
4247
|
-
/* @__PURE__ */
|
|
4750
|
+
/* @__PURE__ */ jsx30(StatCard, { label: "Duration", value: formatDuration(durationMs) }),
|
|
4751
|
+
/* @__PURE__ */ jsx30(
|
|
4248
4752
|
StatCard,
|
|
4249
4753
|
{
|
|
4250
4754
|
label: "Tests",
|
|
@@ -4256,31 +4760,31 @@ function OverviewStats({
|
|
|
4256
4760
|
}
|
|
4257
4761
|
|
|
4258
4762
|
// src/components/report-detail/ProvenanceCard.tsx
|
|
4259
|
-
import { Card as
|
|
4260
|
-
import { jsx as
|
|
4763
|
+
import { Card as Card18, Flex as Flex19, Grid as Grid4, Stack as Stack18, Text as Text26 } from "@sanity/ui";
|
|
4764
|
+
import { jsx as jsx31, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
4261
4765
|
var VIEWABLE_PROMPTFOO_MODES = /* @__PURE__ */ new Set(["agentic", "observed"]);
|
|
4262
4766
|
function ProvenanceCard({ provenance }) {
|
|
4263
|
-
return /* @__PURE__ */
|
|
4264
|
-
/* @__PURE__ */
|
|
4265
|
-
/* @__PURE__ */
|
|
4266
|
-
/* @__PURE__ */
|
|
4267
|
-
/* @__PURE__ */
|
|
4268
|
-
/* @__PURE__ */
|
|
4767
|
+
return /* @__PURE__ */ jsx31(Card18, { padding: 4, radius: 2, shadow: 1, children: /* @__PURE__ */ jsxs26(Stack18, { space: 4, children: [
|
|
4768
|
+
/* @__PURE__ */ jsx31(Text26, { size: 2, weight: "semibold", children: "Provenance" }),
|
|
4769
|
+
/* @__PURE__ */ jsxs26(Grid4, { columns: [1, 2, 3], gap: 4, children: [
|
|
4770
|
+
/* @__PURE__ */ jsx31(Field, { label: "Mode", value: provenance.mode }),
|
|
4771
|
+
/* @__PURE__ */ jsx31(Field, { label: "Source", value: provenance.source.name }),
|
|
4772
|
+
/* @__PURE__ */ jsx31(
|
|
4269
4773
|
Field,
|
|
4270
4774
|
{
|
|
4271
4775
|
label: "Trigger",
|
|
4272
4776
|
value: provenance.trigger.type + (provenance.trigger.workflow ? ` (${provenance.trigger.workflow})` : "")
|
|
4273
4777
|
}
|
|
4274
4778
|
),
|
|
4275
|
-
/* @__PURE__ */
|
|
4779
|
+
/* @__PURE__ */ jsx31(
|
|
4276
4780
|
Field,
|
|
4277
4781
|
{
|
|
4278
4782
|
label: "Models",
|
|
4279
4783
|
value: provenance.models.map((m) => m.label).join(", ")
|
|
4280
4784
|
}
|
|
4281
4785
|
),
|
|
4282
|
-
/* @__PURE__ */
|
|
4283
|
-
provenance.contextHash && /* @__PURE__ */
|
|
4786
|
+
/* @__PURE__ */ jsx31(Field, { label: "Grader Model", mono: true, value: provenance.graderModel }),
|
|
4787
|
+
provenance.contextHash && /* @__PURE__ */ jsx31(
|
|
4284
4788
|
Field,
|
|
4285
4789
|
{
|
|
4286
4790
|
label: "Context Hash",
|
|
@@ -4289,8 +4793,8 @@ function ProvenanceCard({ provenance }) {
|
|
|
4289
4793
|
}
|
|
4290
4794
|
)
|
|
4291
4795
|
] }),
|
|
4292
|
-
provenance.git && /* @__PURE__ */
|
|
4293
|
-
/* @__PURE__ */
|
|
4796
|
+
provenance.git && /* @__PURE__ */ jsx31(GitInfo, { git: provenance.git }),
|
|
4797
|
+
/* @__PURE__ */ jsx31(PromptfooLinks, { provenance })
|
|
4294
4798
|
] }) });
|
|
4295
4799
|
}
|
|
4296
4800
|
function Field({
|
|
@@ -4298,9 +4802,9 @@ function Field({
|
|
|
4298
4802
|
mono,
|
|
4299
4803
|
value
|
|
4300
4804
|
}) {
|
|
4301
|
-
return /* @__PURE__ */
|
|
4302
|
-
/* @__PURE__ */
|
|
4303
|
-
|
|
4805
|
+
return /* @__PURE__ */ jsxs26(Stack18, { space: 1, children: [
|
|
4806
|
+
/* @__PURE__ */ jsx31(
|
|
4807
|
+
Text26,
|
|
4304
4808
|
{
|
|
4305
4809
|
muted: true,
|
|
4306
4810
|
size: 0,
|
|
@@ -4309,19 +4813,19 @@ function Field({
|
|
|
4309
4813
|
children: label
|
|
4310
4814
|
}
|
|
4311
4815
|
),
|
|
4312
|
-
/* @__PURE__ */
|
|
4816
|
+
/* @__PURE__ */ jsx31(Text26, { size: 1, style: mono ? { fontFamily: "monospace" } : void 0, children: value })
|
|
4313
4817
|
] });
|
|
4314
4818
|
}
|
|
4315
4819
|
function GitInfo({ git }) {
|
|
4316
|
-
return /* @__PURE__ */
|
|
4317
|
-
/* @__PURE__ */
|
|
4318
|
-
/* @__PURE__ */
|
|
4820
|
+
return /* @__PURE__ */ jsx31(Card18, { border: true, padding: 3, radius: 2, tone: "transparent", children: /* @__PURE__ */ jsxs26(Flex19, { align: "center", gap: 3, wrap: "wrap", children: [
|
|
4821
|
+
/* @__PURE__ */ jsx31(Text26, { muted: true, size: 1, weight: "semibold", children: "Git" }),
|
|
4822
|
+
/* @__PURE__ */ jsxs26(Text26, { size: 1, children: [
|
|
4319
4823
|
git.repo,
|
|
4320
4824
|
" / ",
|
|
4321
4825
|
git.branch
|
|
4322
4826
|
] }),
|
|
4323
|
-
/* @__PURE__ */
|
|
4324
|
-
git.prNumber && /* @__PURE__ */
|
|
4827
|
+
/* @__PURE__ */ jsx31(Text26, { muted: true, size: 1, style: { fontFamily: "monospace" }, children: git.sha.slice(0, 12) }),
|
|
4828
|
+
git.prNumber && /* @__PURE__ */ jsx31(Text26, { size: 1, children: /* @__PURE__ */ jsxs26(
|
|
4325
4829
|
"a",
|
|
4326
4830
|
{
|
|
4327
4831
|
href: `https://github.com/${git.repo}/pull/${git.prNumber}`,
|
|
@@ -4344,14 +4848,14 @@ function PromptfooLinks({
|
|
|
4344
4848
|
(e) => VIEWABLE_PROMPTFOO_MODES.has(e.mode)
|
|
4345
4849
|
);
|
|
4346
4850
|
if (viewable.length === 0) return null;
|
|
4347
|
-
return /* @__PURE__ */
|
|
4851
|
+
return /* @__PURE__ */ jsx31(Flex19, { gap: 3, wrap: "wrap", children: viewable.map((entry) => /* @__PURE__ */ jsx31(Text26, { size: 1, children: /* @__PURE__ */ jsxs26("a", { href: entry.url, rel: "noopener noreferrer", target: "_blank", children: [
|
|
4348
4852
|
"View in Promptfoo (",
|
|
4349
4853
|
entry.mode,
|
|
4350
4854
|
") \u2192"
|
|
4351
4855
|
] }) }, entry.mode)) });
|
|
4352
4856
|
}
|
|
4353
4857
|
if (provenance.promptfooUrl && VIEWABLE_PROMPTFOO_MODES.has(provenance.mode)) {
|
|
4354
|
-
return /* @__PURE__ */
|
|
4858
|
+
return /* @__PURE__ */ jsx31(Text26, { size: 1, children: /* @__PURE__ */ jsx31(
|
|
4355
4859
|
"a",
|
|
4356
4860
|
{
|
|
4357
4861
|
href: provenance.promptfooUrl,
|
|
@@ -4366,32 +4870,32 @@ function PromptfooLinks({
|
|
|
4366
4870
|
|
|
4367
4871
|
// src/components/report-detail/RecommendationsSection.tsx
|
|
4368
4872
|
import React3 from "react";
|
|
4369
|
-
import { Badge as
|
|
4370
|
-
import { HelpCircleIcon as
|
|
4371
|
-
import { jsx as
|
|
4873
|
+
import { Badge as Badge15, Box as Box12, Card as Card19, Flex as Flex20, Stack as Stack19, Text as Text27, Tooltip as Tooltip6 } from "@sanity/ui";
|
|
4874
|
+
import { HelpCircleIcon as HelpCircleIcon6 } from "@sanity/icons";
|
|
4875
|
+
import { jsx as jsx32, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
4372
4876
|
function RecommendationsSection({
|
|
4373
4877
|
recommendations
|
|
4374
4878
|
}) {
|
|
4375
4879
|
if (recommendations.gaps.length === 0) return null;
|
|
4376
|
-
return /* @__PURE__ */
|
|
4377
|
-
/* @__PURE__ */
|
|
4378
|
-
/* @__PURE__ */
|
|
4379
|
-
/* @__PURE__ */
|
|
4880
|
+
return /* @__PURE__ */ jsx32(Card19, { padding: 4, radius: 2, shadow: 1, children: /* @__PURE__ */ jsxs27(Stack19, { space: 4, children: [
|
|
4881
|
+
/* @__PURE__ */ jsxs27(Flex20, { align: "center", gap: 3, wrap: "wrap", children: [
|
|
4882
|
+
/* @__PURE__ */ jsx32(Text27, { size: 2, weight: "semibold", children: "Recommendations" }),
|
|
4883
|
+
/* @__PURE__ */ jsx32(
|
|
4380
4884
|
Tooltip6,
|
|
4381
4885
|
{
|
|
4382
|
-
content: /* @__PURE__ */
|
|
4886
|
+
content: /* @__PURE__ */ jsx32(Box12, { padding: 2, style: { maxWidth: 260 }, children: /* @__PURE__ */ jsx32(Text27, { size: 1, children: GLOSSARY.recommendations }) }),
|
|
4383
4887
|
placement: "bottom",
|
|
4384
4888
|
portal: true,
|
|
4385
|
-
children: /* @__PURE__ */
|
|
4889
|
+
children: /* @__PURE__ */ jsx32(Text27, { muted: true, size: 0, children: /* @__PURE__ */ jsx32(HelpCircleIcon6, {}) })
|
|
4386
4890
|
}
|
|
4387
4891
|
),
|
|
4388
|
-
/* @__PURE__ */
|
|
4892
|
+
/* @__PURE__ */ jsx32(
|
|
4389
4893
|
Tooltip6,
|
|
4390
4894
|
{
|
|
4391
|
-
content: /* @__PURE__ */
|
|
4895
|
+
content: /* @__PURE__ */ jsx32(Box12, { padding: 2, style: { maxWidth: 260 }, children: /* @__PURE__ */ jsx32(Text27, { size: 1, children: GLOSSARY.totalPotentialLift }) }),
|
|
4392
4896
|
placement: "bottom",
|
|
4393
4897
|
portal: true,
|
|
4394
|
-
children: /* @__PURE__ */
|
|
4898
|
+
children: /* @__PURE__ */ jsx32(Card19, { padding: 2, radius: 2, tone: "positive", children: /* @__PURE__ */ jsxs27(Text27, { size: 1, weight: "bold", children: [
|
|
4395
4899
|
"+",
|
|
4396
4900
|
recommendations.totalPotentialLift.toFixed(1),
|
|
4397
4901
|
" pts potential lift"
|
|
@@ -4399,7 +4903,7 @@ function RecommendationsSection({
|
|
|
4399
4903
|
}
|
|
4400
4904
|
)
|
|
4401
4905
|
] }),
|
|
4402
|
-
/* @__PURE__ */
|
|
4906
|
+
/* @__PURE__ */ jsxs27(
|
|
4403
4907
|
"div",
|
|
4404
4908
|
{
|
|
4405
4909
|
style: {
|
|
@@ -4408,9 +4912,9 @@ function RecommendationsSection({
|
|
|
4408
4912
|
gridTemplateColumns: "auto 2fr 2fr 1fr 1fr 1fr"
|
|
4409
4913
|
},
|
|
4410
4914
|
children: [
|
|
4411
|
-
/* @__PURE__ */
|
|
4412
|
-
/* @__PURE__ */
|
|
4413
|
-
/* @__PURE__ */
|
|
4915
|
+
/* @__PURE__ */ jsx32(ColumnHeader, { borderBottom: true, label: "#" }),
|
|
4916
|
+
/* @__PURE__ */ jsx32(ColumnHeader, { borderBottom: true, label: "Area" }),
|
|
4917
|
+
/* @__PURE__ */ jsx32(
|
|
4414
4918
|
ColumnHeader,
|
|
4415
4919
|
{
|
|
4416
4920
|
borderBottom: true,
|
|
@@ -4418,8 +4922,8 @@ function RecommendationsSection({
|
|
|
4418
4922
|
tooltip: GLOSSARY.failureMode
|
|
4419
4923
|
}
|
|
4420
4924
|
),
|
|
4421
|
-
/* @__PURE__ */
|
|
4422
|
-
/* @__PURE__ */
|
|
4925
|
+
/* @__PURE__ */ jsx32(ColumnHeader, { borderBottom: true, label: "Action" }),
|
|
4926
|
+
/* @__PURE__ */ jsx32(
|
|
4423
4927
|
ColumnHeader,
|
|
4424
4928
|
{
|
|
4425
4929
|
borderBottom: true,
|
|
@@ -4427,7 +4931,7 @@ function RecommendationsSection({
|
|
|
4427
4931
|
tooltip: GLOSSARY.estimatedLift
|
|
4428
4932
|
}
|
|
4429
4933
|
),
|
|
4430
|
-
/* @__PURE__ */
|
|
4934
|
+
/* @__PURE__ */ jsx32(
|
|
4431
4935
|
ColumnHeader,
|
|
4432
4936
|
{
|
|
4433
4937
|
borderBottom: true,
|
|
@@ -4435,7 +4939,7 @@ function RecommendationsSection({
|
|
|
4435
4939
|
tooltip: GLOSSARY.confidence
|
|
4436
4940
|
}
|
|
4437
4941
|
),
|
|
4438
|
-
recommendations.gaps.map((gap, i) => /* @__PURE__ */
|
|
4942
|
+
recommendations.gaps.map((gap, i) => /* @__PURE__ */ jsx32(RecommendationRow, { gap, index: i }, `gap-${i}`))
|
|
4439
4943
|
]
|
|
4440
4944
|
}
|
|
4441
4945
|
)
|
|
@@ -4447,8 +4951,8 @@ function RecommendationRow({
|
|
|
4447
4951
|
}) {
|
|
4448
4952
|
const confIcon = gap.confidence === "high" ? "\u{1F7E2}" : gap.confidence === "medium" ? "\u{1F7E1}" : "\u{1F534}";
|
|
4449
4953
|
const bg = rowBackground(index);
|
|
4450
|
-
return /* @__PURE__ */
|
|
4451
|
-
/* @__PURE__ */
|
|
4954
|
+
return /* @__PURE__ */ jsxs27(React3.Fragment, { children: [
|
|
4955
|
+
/* @__PURE__ */ jsx32(
|
|
4452
4956
|
"div",
|
|
4453
4957
|
{
|
|
4454
4958
|
style: {
|
|
@@ -4458,10 +4962,10 @@ function RecommendationRow({
|
|
|
4458
4962
|
display: "flex",
|
|
4459
4963
|
padding: "8px 4px"
|
|
4460
4964
|
},
|
|
4461
|
-
children: /* @__PURE__ */
|
|
4965
|
+
children: /* @__PURE__ */ jsx32(Text27, { muted: true, size: 1, children: index + 1 })
|
|
4462
4966
|
}
|
|
4463
4967
|
),
|
|
4464
|
-
/* @__PURE__ */
|
|
4968
|
+
/* @__PURE__ */ jsx32(
|
|
4465
4969
|
"div",
|
|
4466
4970
|
{
|
|
4467
4971
|
style: {
|
|
@@ -4470,10 +4974,10 @@ function RecommendationRow({
|
|
|
4470
4974
|
display: "flex",
|
|
4471
4975
|
padding: "8px 0"
|
|
4472
4976
|
},
|
|
4473
|
-
children: /* @__PURE__ */
|
|
4977
|
+
children: /* @__PURE__ */ jsx32(Text27, { size: 1, weight: "medium", children: gap.area })
|
|
4474
4978
|
}
|
|
4475
4979
|
),
|
|
4476
|
-
/* @__PURE__ */
|
|
4980
|
+
/* @__PURE__ */ jsx32(
|
|
4477
4981
|
"div",
|
|
4478
4982
|
{
|
|
4479
4983
|
style: {
|
|
@@ -4482,8 +4986,8 @@ function RecommendationRow({
|
|
|
4482
4986
|
display: "flex",
|
|
4483
4987
|
padding: "8px 0"
|
|
4484
4988
|
},
|
|
4485
|
-
children: /* @__PURE__ */
|
|
4486
|
-
|
|
4989
|
+
children: /* @__PURE__ */ jsx32(
|
|
4990
|
+
Badge15,
|
|
4487
4991
|
{
|
|
4488
4992
|
tone: gap.failureMode === "missing-docs" ? "critical" : gap.failureMode === "incorrect-docs" ? "critical" : gap.failureMode === "outdated-docs" ? "caution" : "default",
|
|
4489
4993
|
children: gap.failureMode
|
|
@@ -4491,7 +4995,7 @@ function RecommendationRow({
|
|
|
4491
4995
|
)
|
|
4492
4996
|
}
|
|
4493
4997
|
),
|
|
4494
|
-
/* @__PURE__ */
|
|
4998
|
+
/* @__PURE__ */ jsx32(
|
|
4495
4999
|
"div",
|
|
4496
5000
|
{
|
|
4497
5001
|
style: {
|
|
@@ -4500,10 +5004,10 @@ function RecommendationRow({
|
|
|
4500
5004
|
display: "flex",
|
|
4501
5005
|
padding: "8px 0"
|
|
4502
5006
|
},
|
|
4503
|
-
children: /* @__PURE__ */
|
|
5007
|
+
children: /* @__PURE__ */ jsx32(Text27, { muted: true, size: 1, children: gap.remediation })
|
|
4504
5008
|
}
|
|
4505
5009
|
),
|
|
4506
|
-
/* @__PURE__ */
|
|
5010
|
+
/* @__PURE__ */ jsx32(
|
|
4507
5011
|
"div",
|
|
4508
5012
|
{
|
|
4509
5013
|
style: {
|
|
@@ -4512,13 +5016,13 @@ function RecommendationRow({
|
|
|
4512
5016
|
display: "flex",
|
|
4513
5017
|
padding: "8px 0"
|
|
4514
5018
|
},
|
|
4515
|
-
children: /* @__PURE__ */
|
|
5019
|
+
children: /* @__PURE__ */ jsx32(Card19, { padding: 2, radius: 2, tone: "positive", children: /* @__PURE__ */ jsxs27(Text27, { align: "center", size: 1, weight: "medium", children: [
|
|
4516
5020
|
"+",
|
|
4517
5021
|
gap.estimatedLift.toFixed(1)
|
|
4518
5022
|
] }) })
|
|
4519
5023
|
}
|
|
4520
5024
|
),
|
|
4521
|
-
/* @__PURE__ */
|
|
5025
|
+
/* @__PURE__ */ jsx32(
|
|
4522
5026
|
"div",
|
|
4523
5027
|
{
|
|
4524
5028
|
style: {
|
|
@@ -4527,7 +5031,7 @@ function RecommendationRow({
|
|
|
4527
5031
|
display: "flex",
|
|
4528
5032
|
padding: "8px 0"
|
|
4529
5033
|
},
|
|
4530
|
-
children: /* @__PURE__ */
|
|
5034
|
+
children: /* @__PURE__ */ jsxs27(Text27, { size: 1, children: [
|
|
4531
5035
|
confIcon,
|
|
4532
5036
|
" ",
|
|
4533
5037
|
gap.confidence
|
|
@@ -4540,16 +5044,16 @@ function RecommendationRow({
|
|
|
4540
5044
|
// src/components/report-detail/ReportHeader.tsx
|
|
4541
5045
|
import { ArrowLeftIcon, ClipboardIcon } from "@sanity/icons";
|
|
4542
5046
|
import {
|
|
4543
|
-
Badge as
|
|
4544
|
-
Box as
|
|
5047
|
+
Badge as Badge16,
|
|
5048
|
+
Box as Box13,
|
|
4545
5049
|
Button as Button2,
|
|
4546
|
-
Card as
|
|
4547
|
-
Flex as
|
|
4548
|
-
Stack as
|
|
4549
|
-
Text as
|
|
5050
|
+
Card as Card20,
|
|
5051
|
+
Flex as Flex21,
|
|
5052
|
+
Stack as Stack20,
|
|
5053
|
+
Text as Text28,
|
|
4550
5054
|
Tooltip as Tooltip7
|
|
4551
5055
|
} from "@sanity/ui";
|
|
4552
|
-
import { Fragment as
|
|
5056
|
+
import { Fragment as Fragment6, jsx as jsx33, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
4553
5057
|
function ReportHeader({
|
|
4554
5058
|
completedAt,
|
|
4555
5059
|
mode,
|
|
@@ -4562,9 +5066,9 @@ function ReportHeader({
|
|
|
4562
5066
|
const dateLabel = formatCardDate(completedAt);
|
|
4563
5067
|
const title = tag ?? dateLabel;
|
|
4564
5068
|
const hasTag = Boolean(tag);
|
|
4565
|
-
return /* @__PURE__ */
|
|
4566
|
-
/* @__PURE__ */
|
|
4567
|
-
/* @__PURE__ */
|
|
5069
|
+
return /* @__PURE__ */ jsxs28(Fragment6, { children: [
|
|
5070
|
+
/* @__PURE__ */ jsxs28(Flex21, { align: "center", gap: 3, children: [
|
|
5071
|
+
/* @__PURE__ */ jsx33(
|
|
4568
5072
|
Button2,
|
|
4569
5073
|
{
|
|
4570
5074
|
icon: ArrowLeftIcon,
|
|
@@ -4573,23 +5077,23 @@ function ReportHeader({
|
|
|
4573
5077
|
text: "Back"
|
|
4574
5078
|
}
|
|
4575
5079
|
),
|
|
4576
|
-
/* @__PURE__ */
|
|
4577
|
-
/* @__PURE__ */
|
|
4578
|
-
hasTag && /* @__PURE__ */
|
|
5080
|
+
/* @__PURE__ */ jsxs28(Stack20, { flex: 1, space: 1, children: [
|
|
5081
|
+
/* @__PURE__ */ jsx33(Text28, { size: 3, weight: "bold", children: title }),
|
|
5082
|
+
hasTag && /* @__PURE__ */ jsx33(Text28, { muted: true, size: 1, children: dateLabel })
|
|
4579
5083
|
] }),
|
|
4580
|
-
/* @__PURE__ */
|
|
4581
|
-
/* @__PURE__ */
|
|
4582
|
-
/* @__PURE__ */
|
|
5084
|
+
/* @__PURE__ */ jsxs28(Flex21, { gap: 2, children: [
|
|
5085
|
+
/* @__PURE__ */ jsx33(Badge16, { mode: "outline", tone: "default", children: sourceName }),
|
|
5086
|
+
/* @__PURE__ */ jsx33(Badge16, { tone: "primary", children: mode })
|
|
4583
5087
|
] })
|
|
4584
5088
|
] }),
|
|
4585
|
-
/* @__PURE__ */
|
|
5089
|
+
/* @__PURE__ */ jsx33(
|
|
4586
5090
|
Tooltip7,
|
|
4587
5091
|
{
|
|
4588
|
-
content: /* @__PURE__ */
|
|
5092
|
+
content: /* @__PURE__ */ jsx33(Box13, { padding: 2, children: /* @__PURE__ */ jsx33(Text28, { size: 1, children: "Click to copy report ID" }) }),
|
|
4589
5093
|
placement: "bottom",
|
|
4590
5094
|
portal: true,
|
|
4591
|
-
children: /* @__PURE__ */
|
|
4592
|
-
|
|
5095
|
+
children: /* @__PURE__ */ jsx33(
|
|
5096
|
+
Card20,
|
|
4593
5097
|
{
|
|
4594
5098
|
border: true,
|
|
4595
5099
|
onClick: onCopyId,
|
|
@@ -4597,9 +5101,9 @@ function ReportHeader({
|
|
|
4597
5101
|
radius: 2,
|
|
4598
5102
|
style: { cursor: "pointer" },
|
|
4599
5103
|
tone: "transparent",
|
|
4600
|
-
children: /* @__PURE__ */
|
|
4601
|
-
/* @__PURE__ */
|
|
4602
|
-
|
|
5104
|
+
children: /* @__PURE__ */ jsxs28(Flex21, { align: "center", gap: 3, children: [
|
|
5105
|
+
/* @__PURE__ */ jsx33(
|
|
5106
|
+
Text28,
|
|
4603
5107
|
{
|
|
4604
5108
|
muted: true,
|
|
4605
5109
|
size: 0,
|
|
@@ -4611,8 +5115,8 @@ function ReportHeader({
|
|
|
4611
5115
|
children: "Report ID"
|
|
4612
5116
|
}
|
|
4613
5117
|
),
|
|
4614
|
-
/* @__PURE__ */
|
|
4615
|
-
|
|
5118
|
+
/* @__PURE__ */ jsx33(
|
|
5119
|
+
Text28,
|
|
4616
5120
|
{
|
|
4617
5121
|
size: 1,
|
|
4618
5122
|
style: {
|
|
@@ -4622,7 +5126,7 @@ function ReportHeader({
|
|
|
4622
5126
|
children: reportId
|
|
4623
5127
|
}
|
|
4624
5128
|
),
|
|
4625
|
-
/* @__PURE__ */
|
|
5129
|
+
/* @__PURE__ */ jsx33(Box13, { style: { marginLeft: "auto" }, children: /* @__PURE__ */ jsx33(Text28, { muted: true, size: 1, children: /* @__PURE__ */ jsx33(ClipboardIcon, {}) }) })
|
|
4626
5130
|
] })
|
|
4627
5131
|
}
|
|
4628
5132
|
)
|
|
@@ -4633,18 +5137,18 @@ function ReportHeader({
|
|
|
4633
5137
|
|
|
4634
5138
|
// src/components/report-detail/ThreeLayerTable.tsx
|
|
4635
5139
|
import React4 from "react";
|
|
4636
|
-
import { Badge as
|
|
4637
|
-
import { jsx as
|
|
5140
|
+
import { Badge as Badge17, Card as Card21, Flex as Flex22, Stack as Stack21, Text as Text29 } from "@sanity/ui";
|
|
5141
|
+
import { jsx as jsx34, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
4638
5142
|
function ThreeLayerTable({ scores }) {
|
|
4639
5143
|
const filtered = scores.filter((s) => s.actualScore != null);
|
|
4640
5144
|
if (filtered.length === 0) return null;
|
|
4641
5145
|
const hasInverted = filtered.some((s) => s.invertedRetrievalGap);
|
|
4642
|
-
return /* @__PURE__ */
|
|
4643
|
-
/* @__PURE__ */
|
|
4644
|
-
/* @__PURE__ */
|
|
4645
|
-
/* @__PURE__ */
|
|
5146
|
+
return /* @__PURE__ */ jsx34(Card21, { overflow: "auto", padding: 4, radius: 2, shadow: 1, children: /* @__PURE__ */ jsxs29(Stack21, { space: 4, children: [
|
|
5147
|
+
/* @__PURE__ */ jsxs29(Flex22, { align: "center", gap: 3, children: [
|
|
5148
|
+
/* @__PURE__ */ jsx34(Text29, { size: 2, weight: "semibold", children: "Three-Layer Decomposition" }),
|
|
5149
|
+
/* @__PURE__ */ jsx34(Badge17, { tone: "primary", children: "full mode" })
|
|
4646
5150
|
] }),
|
|
4647
|
-
/* @__PURE__ */
|
|
5151
|
+
/* @__PURE__ */ jsxs29(
|
|
4648
5152
|
"div",
|
|
4649
5153
|
{
|
|
4650
5154
|
style: {
|
|
@@ -4653,9 +5157,9 @@ function ThreeLayerTable({ scores }) {
|
|
|
4653
5157
|
gridTemplateColumns: "2fr 1fr 1fr 1fr 1fr 1fr"
|
|
4654
5158
|
},
|
|
4655
5159
|
children: [
|
|
4656
|
-
/* @__PURE__ */
|
|
4657
|
-
/* @__PURE__ */
|
|
4658
|
-
/* @__PURE__ */
|
|
5160
|
+
/* @__PURE__ */ jsx34(ColumnHeader, { borderBottom: true, label: "Area" }),
|
|
5161
|
+
/* @__PURE__ */ jsx34(ColumnHeader, { borderBottom: true, label: "Floor", tooltip: GLOSSARY.floor }),
|
|
5162
|
+
/* @__PURE__ */ jsx34(
|
|
4659
5163
|
ColumnHeader,
|
|
4660
5164
|
{
|
|
4661
5165
|
borderBottom: true,
|
|
@@ -4663,8 +5167,8 @@ function ThreeLayerTable({ scores }) {
|
|
|
4663
5167
|
tooltip: GLOSSARY.ceiling
|
|
4664
5168
|
}
|
|
4665
5169
|
),
|
|
4666
|
-
/* @__PURE__ */
|
|
4667
|
-
/* @__PURE__ */
|
|
5170
|
+
/* @__PURE__ */ jsx34(ColumnHeader, { borderBottom: true, label: "Actual", tooltip: GLOSSARY.actual }),
|
|
5171
|
+
/* @__PURE__ */ jsx34(
|
|
4668
5172
|
ColumnHeader,
|
|
4669
5173
|
{
|
|
4670
5174
|
borderBottom: true,
|
|
@@ -4672,7 +5176,7 @@ function ThreeLayerTable({ scores }) {
|
|
|
4672
5176
|
tooltip: GLOSSARY.retGap
|
|
4673
5177
|
}
|
|
4674
5178
|
),
|
|
4675
|
-
/* @__PURE__ */
|
|
5179
|
+
/* @__PURE__ */ jsx34(
|
|
4676
5180
|
ColumnHeader,
|
|
4677
5181
|
{
|
|
4678
5182
|
borderBottom: true,
|
|
@@ -4680,8 +5184,8 @@ function ThreeLayerTable({ scores }) {
|
|
|
4680
5184
|
tooltip: GLOSSARY.efficiency
|
|
4681
5185
|
}
|
|
4682
5186
|
),
|
|
4683
|
-
filtered.map((score, i) => /* @__PURE__ */
|
|
4684
|
-
/* @__PURE__ */
|
|
5187
|
+
filtered.map((score, i) => /* @__PURE__ */ jsxs29(React4.Fragment, { children: [
|
|
5188
|
+
/* @__PURE__ */ jsx34(
|
|
4685
5189
|
"div",
|
|
4686
5190
|
{
|
|
4687
5191
|
style: {
|
|
@@ -4689,13 +5193,13 @@ function ThreeLayerTable({ scores }) {
|
|
|
4689
5193
|
borderRadius: 4,
|
|
4690
5194
|
padding: "8px 0 8px 4px"
|
|
4691
5195
|
},
|
|
4692
|
-
children: /* @__PURE__ */
|
|
5196
|
+
children: /* @__PURE__ */ jsx34(Text29, { size: 1, weight: "medium", children: score.feature })
|
|
4693
5197
|
}
|
|
4694
5198
|
),
|
|
4695
|
-
/* @__PURE__ */
|
|
4696
|
-
/* @__PURE__ */
|
|
4697
|
-
/* @__PURE__ */
|
|
4698
|
-
/* @__PURE__ */
|
|
5199
|
+
/* @__PURE__ */ jsx34("div", { style: { background: rowBackground(i), padding: "6px 0" }, children: /* @__PURE__ */ jsx34(ScoreCell, { score: score.floorScore ?? 0 }) }),
|
|
5200
|
+
/* @__PURE__ */ jsx34("div", { style: { background: rowBackground(i), padding: "6px 0" }, children: /* @__PURE__ */ jsx34(ScoreCell, { score: score.ceilingScore ?? score.totalScore }) }),
|
|
5201
|
+
/* @__PURE__ */ jsx34("div", { style: { background: rowBackground(i), padding: "6px 0" }, children: /* @__PURE__ */ jsx34(ScoreCell, { score: score.actualScore ?? 0 }) }),
|
|
5202
|
+
/* @__PURE__ */ jsx34(
|
|
4699
5203
|
"div",
|
|
4700
5204
|
{
|
|
4701
5205
|
style: {
|
|
@@ -4704,10 +5208,10 @@ function ThreeLayerTable({ scores }) {
|
|
|
4704
5208
|
display: "flex",
|
|
4705
5209
|
padding: "6px 0"
|
|
4706
5210
|
},
|
|
4707
|
-
children: /* @__PURE__ */
|
|
5211
|
+
children: /* @__PURE__ */ jsx34(Text29, { size: 1, children: score.retrievalGap != null ? score.retrievalGap.toFixed(1) : "\u2014" })
|
|
4708
5212
|
}
|
|
4709
5213
|
),
|
|
4710
|
-
/* @__PURE__ */
|
|
5214
|
+
/* @__PURE__ */ jsx34(
|
|
4711
5215
|
"div",
|
|
4712
5216
|
{
|
|
4713
5217
|
style: {
|
|
@@ -4716,7 +5220,7 @@ function ThreeLayerTable({ scores }) {
|
|
|
4716
5220
|
display: "flex",
|
|
4717
5221
|
padding: "6px 0"
|
|
4718
5222
|
},
|
|
4719
|
-
children: /* @__PURE__ */
|
|
5223
|
+
children: /* @__PURE__ */ jsxs29(Text29, { size: 1, children: [
|
|
4720
5224
|
formatPercent(score.infrastructureEfficiency),
|
|
4721
5225
|
score.invertedRetrievalGap && " \u26A0\uFE0F"
|
|
4722
5226
|
] })
|
|
@@ -4726,18 +5230,18 @@ function ThreeLayerTable({ scores }) {
|
|
|
4726
5230
|
]
|
|
4727
5231
|
}
|
|
4728
5232
|
),
|
|
4729
|
-
hasInverted && /* @__PURE__ */
|
|
5233
|
+
hasInverted && /* @__PURE__ */ jsx34(Text29, { muted: true, size: 0, children: GLOSSARY.invertedRetGap })
|
|
4730
5234
|
] }) });
|
|
4731
5235
|
}
|
|
4732
5236
|
|
|
4733
5237
|
// src/components/report-detail/ReportDetail.tsx
|
|
4734
|
-
import { jsx as
|
|
5238
|
+
import { jsx as jsx35, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
4735
5239
|
function ReportDetail({ onBack, reportId }) {
|
|
4736
5240
|
const client = useClient6({ apiVersion: API_VERSION });
|
|
4737
5241
|
const toast = useToast();
|
|
4738
5242
|
const [loading, setLoading] = useState8(true);
|
|
4739
5243
|
const [report, setReport] = useState8(null);
|
|
4740
|
-
|
|
5244
|
+
useEffect7(() => {
|
|
4741
5245
|
let cancelled = false;
|
|
4742
5246
|
setLoading(true);
|
|
4743
5247
|
client.fetch(reportDetailQuery, { reportId }).then((data) => {
|
|
@@ -4752,7 +5256,7 @@ function ReportDetail({ onBack, reportId }) {
|
|
|
4752
5256
|
cancelled = true;
|
|
4753
5257
|
};
|
|
4754
5258
|
}, [client, reportId]);
|
|
4755
|
-
const handleCopyReportId =
|
|
5259
|
+
const handleCopyReportId = useCallback12(() => {
|
|
4756
5260
|
if (!report) return;
|
|
4757
5261
|
navigator.clipboard.writeText(report.reportId).then(() => {
|
|
4758
5262
|
toast.push({
|
|
@@ -4769,11 +5273,11 @@ function ReportDetail({ onBack, reportId }) {
|
|
|
4769
5273
|
});
|
|
4770
5274
|
}, [report, toast]);
|
|
4771
5275
|
if (loading) {
|
|
4772
|
-
return /* @__PURE__ */
|
|
5276
|
+
return /* @__PURE__ */ jsx35(LoadingState, { message: "Loading report\u2026" });
|
|
4773
5277
|
}
|
|
4774
5278
|
if (!report) {
|
|
4775
|
-
return /* @__PURE__ */
|
|
4776
|
-
/* @__PURE__ */
|
|
5279
|
+
return /* @__PURE__ */ jsx35(Box14, { padding: 5, children: /* @__PURE__ */ jsxs30(Stack22, { space: 4, children: [
|
|
5280
|
+
/* @__PURE__ */ jsx35(
|
|
4777
5281
|
Button3,
|
|
4778
5282
|
{
|
|
4779
5283
|
icon: ArrowLeftIcon2,
|
|
@@ -4782,14 +5286,14 @@ function ReportDetail({ onBack, reportId }) {
|
|
|
4782
5286
|
text: "Back"
|
|
4783
5287
|
}
|
|
4784
5288
|
),
|
|
4785
|
-
/* @__PURE__ */
|
|
5289
|
+
/* @__PURE__ */ jsx35(Text30, { align: "center", muted: true, size: 2, children: "Report not found" })
|
|
4786
5290
|
] }) });
|
|
4787
5291
|
}
|
|
4788
5292
|
const { comparison, provenance, summary } = report;
|
|
4789
5293
|
const totalTests = summary.scores.reduce((n, s) => n + s.testCount, 0);
|
|
4790
5294
|
const isFullMode = summary.evaluationMode === "full" || summary.scores.some((s) => s.actualScore != null);
|
|
4791
|
-
return /* @__PURE__ */
|
|
4792
|
-
/* @__PURE__ */
|
|
5295
|
+
return /* @__PURE__ */ jsx35(Box14, { padding: 4, children: /* @__PURE__ */ jsxs30(Stack22, { space: 5, children: [
|
|
5296
|
+
/* @__PURE__ */ jsx35(
|
|
4793
5297
|
ReportHeader,
|
|
4794
5298
|
{
|
|
4795
5299
|
completedAt: report.completedAt,
|
|
@@ -4801,7 +5305,7 @@ function ReportDetail({ onBack, reportId }) {
|
|
|
4801
5305
|
tag: report.tag
|
|
4802
5306
|
}
|
|
4803
5307
|
),
|
|
4804
|
-
/* @__PURE__ */
|
|
5308
|
+
/* @__PURE__ */ jsx35(
|
|
4805
5309
|
OverviewStats,
|
|
4806
5310
|
{
|
|
4807
5311
|
durationMs: report.durationMs,
|
|
@@ -4810,20 +5314,20 @@ function ReportDetail({ onBack, reportId }) {
|
|
|
4810
5314
|
totalTests
|
|
4811
5315
|
}
|
|
4812
5316
|
),
|
|
4813
|
-
isFullMode && /* @__PURE__ */
|
|
4814
|
-
/* @__PURE__ */
|
|
4815
|
-
summary.recommendations && summary.recommendations.gaps.length > 0 && /* @__PURE__ */
|
|
4816
|
-
summary.lowScoringJudgments && summary.lowScoringJudgments.length > 0 && /* @__PURE__ */
|
|
4817
|
-
comparison && /* @__PURE__ */
|
|
4818
|
-
/* @__PURE__ */
|
|
5317
|
+
isFullMode && /* @__PURE__ */ jsx35(ThreeLayerTable, { scores: summary.scores }),
|
|
5318
|
+
/* @__PURE__ */ jsx35(AreaScoreTable, { scores: summary.scores }),
|
|
5319
|
+
summary.recommendations && summary.recommendations.gaps.length > 0 && /* @__PURE__ */ jsx35(RecommendationsSection, { recommendations: summary.recommendations }),
|
|
5320
|
+
summary.lowScoringJudgments && summary.lowScoringJudgments.length > 0 && /* @__PURE__ */ jsx35(JudgmentList, { judgments: summary.lowScoringJudgments }),
|
|
5321
|
+
comparison && /* @__PURE__ */ jsx35(ComparisonSummary, { comparison }),
|
|
5322
|
+
/* @__PURE__ */ jsx35(ProvenanceCard, { provenance })
|
|
4819
5323
|
] }) });
|
|
4820
5324
|
}
|
|
4821
5325
|
|
|
4822
5326
|
// src/components/ScoreTimeline.tsx
|
|
4823
|
-
import { Card as
|
|
4824
|
-
import { useCallback as
|
|
5327
|
+
import { Card as Card22, Flex as Flex23, Select as Select2, Stack as Stack23, Text as Text31 } from "@sanity/ui";
|
|
5328
|
+
import { useCallback as useCallback13, useEffect as useEffect8, useMemo as useMemo6, useState as useState9 } from "react";
|
|
4825
5329
|
import { useClient as useClient7 } from "sanity";
|
|
4826
|
-
import { jsx as
|
|
5330
|
+
import { jsx as jsx36, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
4827
5331
|
var CHART_HEIGHT = 220;
|
|
4828
5332
|
var CHART_WIDTH = 800;
|
|
4829
5333
|
var PAD_BOTTOM = 30;
|
|
@@ -4862,7 +5366,7 @@ function ScoreTimeline({ mode = null, source = null }) {
|
|
|
4862
5366
|
const [loading, setLoading] = useState9(true);
|
|
4863
5367
|
const [rangeDays, setRangeDays] = useState9(30);
|
|
4864
5368
|
const [selectedArea, setSelectedArea] = useState9(null);
|
|
4865
|
-
const areaNames =
|
|
5369
|
+
const areaNames = useMemo6(() => {
|
|
4866
5370
|
const names = /* @__PURE__ */ new Set();
|
|
4867
5371
|
for (const dp of dataPoints) {
|
|
4868
5372
|
for (const s of dp.scores) {
|
|
@@ -4871,7 +5375,7 @@ function ScoreTimeline({ mode = null, source = null }) {
|
|
|
4871
5375
|
}
|
|
4872
5376
|
return Array.from(names).sort();
|
|
4873
5377
|
}, [dataPoints]);
|
|
4874
|
-
const fetchData =
|
|
5378
|
+
const fetchData = useCallback13(async () => {
|
|
4875
5379
|
setLoading(true);
|
|
4876
5380
|
try {
|
|
4877
5381
|
const startDate = rangeDays ? daysAgo(rangeDays) : "1970-01-01T00:00:00Z";
|
|
@@ -4886,10 +5390,10 @@ function ScoreTimeline({ mode = null, source = null }) {
|
|
|
4886
5390
|
setLoading(false);
|
|
4887
5391
|
}
|
|
4888
5392
|
}, [client, mode, rangeDays, source]);
|
|
4889
|
-
|
|
5393
|
+
useEffect8(() => {
|
|
4890
5394
|
void fetchData();
|
|
4891
5395
|
}, [fetchData]);
|
|
4892
|
-
const chartPoints =
|
|
5396
|
+
const chartPoints = useMemo6(() => {
|
|
4893
5397
|
const pts = [];
|
|
4894
5398
|
const scored = dataPoints.map((dp) => ({
|
|
4895
5399
|
date: dp.completedAt,
|
|
@@ -4903,18 +5407,18 @@ function ScoreTimeline({ mode = null, source = null }) {
|
|
|
4903
5407
|
});
|
|
4904
5408
|
return pts;
|
|
4905
5409
|
}, [dataPoints, selectedArea]);
|
|
4906
|
-
const avgScore =
|
|
5410
|
+
const avgScore = useMemo6(() => {
|
|
4907
5411
|
if (chartPoints.length === 0) return 0;
|
|
4908
5412
|
return chartPoints.reduce((sum, p) => sum + p.score, 0) / chartPoints.length;
|
|
4909
5413
|
}, [chartPoints]);
|
|
4910
|
-
const handleRangeChange =
|
|
5414
|
+
const handleRangeChange = useCallback13(
|
|
4911
5415
|
(e) => {
|
|
4912
5416
|
const val = e.currentTarget.value;
|
|
4913
5417
|
setRangeDays(val === "all" ? null : Number(val));
|
|
4914
5418
|
},
|
|
4915
5419
|
[]
|
|
4916
5420
|
);
|
|
4917
|
-
const handleAreaChange =
|
|
5421
|
+
const handleAreaChange = useCallback13(
|
|
4918
5422
|
(e) => {
|
|
4919
5423
|
const val = e.currentTarget.value;
|
|
4920
5424
|
setSelectedArea(val || null);
|
|
@@ -4922,22 +5426,22 @@ function ScoreTimeline({ mode = null, source = null }) {
|
|
|
4922
5426
|
[]
|
|
4923
5427
|
);
|
|
4924
5428
|
const polylinePoints = chartPoints.map((p) => `${p.x},${p.y}`).join(" ");
|
|
4925
|
-
return /* @__PURE__ */
|
|
4926
|
-
/* @__PURE__ */
|
|
4927
|
-
/* @__PURE__ */
|
|
5429
|
+
return /* @__PURE__ */ jsxs31(Stack23, { space: 4, children: [
|
|
5430
|
+
/* @__PURE__ */ jsxs31(Flex23, { gap: 3, children: [
|
|
5431
|
+
/* @__PURE__ */ jsx36(
|
|
4928
5432
|
Select2,
|
|
4929
5433
|
{
|
|
4930
5434
|
onChange: handleRangeChange,
|
|
4931
5435
|
value: rangeDays?.toString() ?? "all",
|
|
4932
|
-
children: TIME_RANGES.map((r) => /* @__PURE__ */
|
|
5436
|
+
children: TIME_RANGES.map((r) => /* @__PURE__ */ jsx36("option", { value: r.days?.toString() ?? "all", children: r.label }, r.label))
|
|
4933
5437
|
}
|
|
4934
5438
|
),
|
|
4935
|
-
/* @__PURE__ */
|
|
4936
|
-
/* @__PURE__ */
|
|
4937
|
-
areaNames.map((name) => /* @__PURE__ */
|
|
5439
|
+
/* @__PURE__ */ jsxs31(Select2, { onChange: handleAreaChange, value: selectedArea ?? "", children: [
|
|
5440
|
+
/* @__PURE__ */ jsx36("option", { value: "", children: "Overall" }),
|
|
5441
|
+
areaNames.map((name) => /* @__PURE__ */ jsx36("option", { value: name, children: name }, name))
|
|
4938
5442
|
] })
|
|
4939
5443
|
] }),
|
|
4940
|
-
/* @__PURE__ */
|
|
5444
|
+
/* @__PURE__ */ jsx36(Card22, { padding: 3, radius: 2, shadow: 1, children: loading ? /* @__PURE__ */ jsx36(Flex23, { align: "center", justify: "center", style: { height: 200 }, children: /* @__PURE__ */ jsx36(Text31, { muted: true, size: 1, children: "Loading\u2026" }) }) : chartPoints.length === 0 ? /* @__PURE__ */ jsx36(Flex23, { align: "center", justify: "center", style: { height: 200 }, children: /* @__PURE__ */ jsx36(Text31, { muted: true, size: 1, children: "No reports found for this time range" }) }) : /* @__PURE__ */ jsxs31(
|
|
4941
5445
|
"svg",
|
|
4942
5446
|
{
|
|
4943
5447
|
style: { display: "block", width: "100%" },
|
|
@@ -4945,8 +5449,8 @@ function ScoreTimeline({ mode = null, source = null }) {
|
|
|
4945
5449
|
children: [
|
|
4946
5450
|
Y_TICKS.map((tick) => {
|
|
4947
5451
|
const y = PAD_TOP + PLOT_HEIGHT - tick / Y_MAX * PLOT_HEIGHT;
|
|
4948
|
-
return /* @__PURE__ */
|
|
4949
|
-
/* @__PURE__ */
|
|
5452
|
+
return /* @__PURE__ */ jsxs31("g", { children: [
|
|
5453
|
+
/* @__PURE__ */ jsx36(
|
|
4950
5454
|
"line",
|
|
4951
5455
|
{
|
|
4952
5456
|
stroke: "#ccc",
|
|
@@ -4957,7 +5461,7 @@ function ScoreTimeline({ mode = null, source = null }) {
|
|
|
4957
5461
|
y2: y
|
|
4958
5462
|
}
|
|
4959
5463
|
),
|
|
4960
|
-
/* @__PURE__ */
|
|
5464
|
+
/* @__PURE__ */ jsx36(
|
|
4961
5465
|
"text",
|
|
4962
5466
|
{
|
|
4963
5467
|
dominantBaseline: "middle",
|
|
@@ -4977,7 +5481,7 @@ function ScoreTimeline({ mode = null, source = null }) {
|
|
|
4977
5481
|
chartPoints.length - 1
|
|
4978
5482
|
].map((idx) => {
|
|
4979
5483
|
const p = chartPoints[idx];
|
|
4980
|
-
return /* @__PURE__ */
|
|
5484
|
+
return /* @__PURE__ */ jsx36(
|
|
4981
5485
|
"text",
|
|
4982
5486
|
{
|
|
4983
5487
|
fill: "#999",
|
|
@@ -4989,7 +5493,7 @@ function ScoreTimeline({ mode = null, source = null }) {
|
|
|
4989
5493
|
},
|
|
4990
5494
|
idx
|
|
4991
5495
|
);
|
|
4992
|
-
}) : chartPoints.map((p, idx) => /* @__PURE__ */
|
|
5496
|
+
}) : chartPoints.map((p, idx) => /* @__PURE__ */ jsx36(
|
|
4993
5497
|
"text",
|
|
4994
5498
|
{
|
|
4995
5499
|
fill: "#999",
|
|
@@ -5001,7 +5505,7 @@ function ScoreTimeline({ mode = null, source = null }) {
|
|
|
5001
5505
|
},
|
|
5002
5506
|
idx
|
|
5003
5507
|
)),
|
|
5004
|
-
/* @__PURE__ */
|
|
5508
|
+
/* @__PURE__ */ jsx36(
|
|
5005
5509
|
"polyline",
|
|
5006
5510
|
{
|
|
5007
5511
|
fill: "none",
|
|
@@ -5011,7 +5515,7 @@ function ScoreTimeline({ mode = null, source = null }) {
|
|
|
5011
5515
|
strokeWidth: 2.5
|
|
5012
5516
|
}
|
|
5013
5517
|
),
|
|
5014
|
-
chartPoints.map((p, idx) => /* @__PURE__ */
|
|
5518
|
+
chartPoints.map((p, idx) => /* @__PURE__ */ jsx36(
|
|
5015
5519
|
"circle",
|
|
5016
5520
|
{
|
|
5017
5521
|
cx: p.x,
|
|
@@ -5020,7 +5524,7 @@ function ScoreTimeline({ mode = null, source = null }) {
|
|
|
5020
5524
|
r: 4,
|
|
5021
5525
|
stroke: "#fff",
|
|
5022
5526
|
strokeWidth: 1.5,
|
|
5023
|
-
children: /* @__PURE__ */
|
|
5527
|
+
children: /* @__PURE__ */ jsxs31("title", { children: [
|
|
5024
5528
|
formatDate2(p.date),
|
|
5025
5529
|
": ",
|
|
5026
5530
|
Math.round(p.score)
|
|
@@ -5031,7 +5535,7 @@ function ScoreTimeline({ mode = null, source = null }) {
|
|
|
5031
5535
|
]
|
|
5032
5536
|
}
|
|
5033
5537
|
) }),
|
|
5034
|
-
/* @__PURE__ */
|
|
5538
|
+
/* @__PURE__ */ jsxs31(Text31, { muted: true, size: 1, children: [
|
|
5035
5539
|
chartPoints.length,
|
|
5036
5540
|
" data point",
|
|
5037
5541
|
chartPoints.length !== 1 ? "s" : ""
|
|
@@ -5041,7 +5545,7 @@ function ScoreTimeline({ mode = null, source = null }) {
|
|
|
5041
5545
|
var ScoreTimeline_default = ScoreTimeline;
|
|
5042
5546
|
|
|
5043
5547
|
// src/components/Dashboard.tsx
|
|
5044
|
-
import { jsx as
|
|
5548
|
+
import { jsx as jsx37, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
5045
5549
|
var VIEW_PARAM_MAP = {
|
|
5046
5550
|
compare: "compare",
|
|
5047
5551
|
timeline: "timeline"
|
|
@@ -5053,7 +5557,7 @@ function Dashboard() {
|
|
|
5053
5557
|
const reportId = routerState.reportId ?? null;
|
|
5054
5558
|
const isDetail = reportId !== null;
|
|
5055
5559
|
const activeTab = isDetail ? "latest" : VIEW_PARAM_MAP[routerState.view ?? ""] ?? "latest";
|
|
5056
|
-
const navigateToTab =
|
|
5560
|
+
const navigateToTab = useCallback14(
|
|
5057
5561
|
(tab) => {
|
|
5058
5562
|
if (tab === "latest") {
|
|
5059
5563
|
router.navigate({});
|
|
@@ -5063,58 +5567,58 @@ function Dashboard() {
|
|
|
5063
5567
|
},
|
|
5064
5568
|
[router]
|
|
5065
5569
|
);
|
|
5066
|
-
const handleSelectReport =
|
|
5570
|
+
const handleSelectReport = useCallback14(
|
|
5067
5571
|
(id) => {
|
|
5068
5572
|
router.navigate({ reportId: id });
|
|
5069
5573
|
},
|
|
5070
5574
|
[router]
|
|
5071
5575
|
);
|
|
5072
|
-
const handleBack =
|
|
5576
|
+
const handleBack = useCallback14(() => {
|
|
5073
5577
|
router.navigate({});
|
|
5074
5578
|
}, [router]);
|
|
5075
5579
|
const [source, setSource] = useState10(null);
|
|
5076
5580
|
const [mode, setMode] = useState10(null);
|
|
5077
5581
|
const [sources, setSources] = useState10([]);
|
|
5078
5582
|
const [modes, setModes] = useState10([]);
|
|
5079
|
-
|
|
5583
|
+
useEffect9(() => {
|
|
5080
5584
|
client.fetch(distinctSourcesQuery).then((data) => setSources(data ?? [])).catch(() => setSources([]));
|
|
5081
5585
|
client.fetch(distinctModesQuery).then((data) => setModes(data ?? [])).catch(() => setModes([]));
|
|
5082
5586
|
}, [client]);
|
|
5083
|
-
return /* @__PURE__ */
|
|
5084
|
-
/* @__PURE__ */
|
|
5085
|
-
/* @__PURE__ */
|
|
5086
|
-
/* @__PURE__ */
|
|
5087
|
-
/* @__PURE__ */
|
|
5587
|
+
return /* @__PURE__ */ jsx37(Container, { width: 2, children: /* @__PURE__ */ jsxs32(Stack24, { padding: 4, space: 4, children: [
|
|
5588
|
+
/* @__PURE__ */ jsxs32(Flex24, { align: "center", gap: 3, children: [
|
|
5589
|
+
/* @__PURE__ */ jsxs32(Stack24, { flex: 1, space: 1, children: [
|
|
5590
|
+
/* @__PURE__ */ jsx37(Text32, { size: 3, weight: "bold", children: "AI Literacy" }),
|
|
5591
|
+
/* @__PURE__ */ jsx37(Text32, { muted: true, size: 1, children: "Evaluation reports and score trends" })
|
|
5088
5592
|
] }),
|
|
5089
|
-
!isDetail && /* @__PURE__ */
|
|
5090
|
-
/* @__PURE__ */
|
|
5593
|
+
!isDetail && /* @__PURE__ */ jsxs32(Flex24, { gap: 2, children: [
|
|
5594
|
+
/* @__PURE__ */ jsxs32(
|
|
5091
5595
|
Select3,
|
|
5092
5596
|
{
|
|
5093
5597
|
fontSize: 1,
|
|
5094
5598
|
onChange: (e) => setSource(e.currentTarget.value || null),
|
|
5095
5599
|
value: source ?? "",
|
|
5096
5600
|
children: [
|
|
5097
|
-
/* @__PURE__ */
|
|
5098
|
-
sources.map((s) => /* @__PURE__ */
|
|
5601
|
+
/* @__PURE__ */ jsx37("option", { value: "", children: "All sources" }),
|
|
5602
|
+
sources.map((s) => /* @__PURE__ */ jsx37("option", { value: s, children: s }, s))
|
|
5099
5603
|
]
|
|
5100
5604
|
}
|
|
5101
5605
|
),
|
|
5102
|
-
/* @__PURE__ */
|
|
5606
|
+
/* @__PURE__ */ jsxs32(
|
|
5103
5607
|
Select3,
|
|
5104
5608
|
{
|
|
5105
5609
|
fontSize: 1,
|
|
5106
5610
|
onChange: (e) => setMode(e.currentTarget.value || null),
|
|
5107
5611
|
value: mode ?? "",
|
|
5108
5612
|
children: [
|
|
5109
|
-
/* @__PURE__ */
|
|
5110
|
-
modes.map((m) => /* @__PURE__ */
|
|
5613
|
+
/* @__PURE__ */ jsx37("option", { value: "", children: "All modes" }),
|
|
5614
|
+
modes.map((m) => /* @__PURE__ */ jsx37("option", { value: m, children: m }, m))
|
|
5111
5615
|
]
|
|
5112
5616
|
}
|
|
5113
5617
|
)
|
|
5114
5618
|
] })
|
|
5115
5619
|
] }),
|
|
5116
|
-
!isDetail && /* @__PURE__ */
|
|
5117
|
-
/* @__PURE__ */
|
|
5620
|
+
!isDetail && /* @__PURE__ */ jsxs32(TabList, { space: 1, children: [
|
|
5621
|
+
/* @__PURE__ */ jsx37(
|
|
5118
5622
|
Tab,
|
|
5119
5623
|
{
|
|
5120
5624
|
"aria-controls": "latest-panel",
|
|
@@ -5124,7 +5628,7 @@ function Dashboard() {
|
|
|
5124
5628
|
selected: activeTab === "latest"
|
|
5125
5629
|
}
|
|
5126
5630
|
),
|
|
5127
|
-
/* @__PURE__ */
|
|
5631
|
+
/* @__PURE__ */ jsx37(
|
|
5128
5632
|
Tab,
|
|
5129
5633
|
{
|
|
5130
5634
|
"aria-controls": "timeline-panel",
|
|
@@ -5134,7 +5638,7 @@ function Dashboard() {
|
|
|
5134
5638
|
selected: activeTab === "timeline"
|
|
5135
5639
|
}
|
|
5136
5640
|
),
|
|
5137
|
-
/* @__PURE__ */
|
|
5641
|
+
/* @__PURE__ */ jsx37(
|
|
5138
5642
|
Tab,
|
|
5139
5643
|
{
|
|
5140
5644
|
"aria-controls": "compare-panel",
|
|
@@ -5145,7 +5649,7 @@ function Dashboard() {
|
|
|
5145
5649
|
}
|
|
5146
5650
|
)
|
|
5147
5651
|
] }),
|
|
5148
|
-
!isDetail && activeTab === "latest" && /* @__PURE__ */
|
|
5652
|
+
!isDetail && activeTab === "latest" && /* @__PURE__ */ jsx37(TabPanel, { "aria-labelledby": "latest-tab", id: "latest-panel", children: /* @__PURE__ */ jsx37(
|
|
5149
5653
|
LatestReports,
|
|
5150
5654
|
{
|
|
5151
5655
|
mode,
|
|
@@ -5153,9 +5657,9 @@ function Dashboard() {
|
|
|
5153
5657
|
source
|
|
5154
5658
|
}
|
|
5155
5659
|
) }),
|
|
5156
|
-
!isDetail && activeTab === "timeline" && /* @__PURE__ */
|
|
5157
|
-
!isDetail && activeTab === "compare" && /* @__PURE__ */
|
|
5158
|
-
isDetail && reportId && /* @__PURE__ */
|
|
5660
|
+
!isDetail && activeTab === "timeline" && /* @__PURE__ */ jsx37(TabPanel, { "aria-labelledby": "timeline-tab", id: "timeline-panel", children: /* @__PURE__ */ jsx37(ScoreTimeline_default, { mode, source }) }),
|
|
5661
|
+
!isDetail && activeTab === "compare" && /* @__PURE__ */ jsx37(TabPanel, { "aria-labelledby": "compare-tab", id: "compare-panel", children: /* @__PURE__ */ jsx37(ComparisonView, {}) }),
|
|
5662
|
+
isDetail && reportId && /* @__PURE__ */ jsx37(ReportDetail, { onBack: handleBack, reportId })
|
|
5159
5663
|
] }) });
|
|
5160
5664
|
}
|
|
5161
5665
|
|
|
@@ -5176,9 +5680,9 @@ function ailfTool(options = {}) {
|
|
|
5176
5680
|
|
|
5177
5681
|
// src/actions/RunEvaluationAction.tsx
|
|
5178
5682
|
import { BarChartIcon as BarChartIcon2 } from "@sanity/icons";
|
|
5179
|
-
import { useCallback as
|
|
5683
|
+
import { useCallback as useCallback15, useEffect as useEffect10, useRef as useRef4, useState as useState11 } from "react";
|
|
5180
5684
|
import {
|
|
5181
|
-
getReleaseIdFromReleaseDocumentId as
|
|
5685
|
+
getReleaseIdFromReleaseDocumentId as getReleaseIdFromReleaseDocumentId4,
|
|
5182
5686
|
useClient as useClient9,
|
|
5183
5687
|
useCurrentUser,
|
|
5184
5688
|
useDataset,
|
|
@@ -5207,9 +5711,9 @@ function createRunEvaluationAction(options = {}) {
|
|
|
5207
5711
|
const projectId = useProjectId();
|
|
5208
5712
|
const currentUser = useCurrentUser();
|
|
5209
5713
|
const [state, setState] = useState11({ status: "loading" });
|
|
5210
|
-
const requestedAtRef =
|
|
5211
|
-
const perspectiveId =
|
|
5212
|
-
|
|
5714
|
+
const requestedAtRef = useRef4(null);
|
|
5715
|
+
const perspectiveId = getReleaseIdFromReleaseDocumentId4(release._id);
|
|
5716
|
+
useEffect10(() => {
|
|
5213
5717
|
let cancelled = false;
|
|
5214
5718
|
client.fetch(contentImpactQuery, buildReportQueryParams(perspectiveId)).then((results) => {
|
|
5215
5719
|
if (cancelled) return;
|
|
@@ -5232,7 +5736,7 @@ function createRunEvaluationAction(options = {}) {
|
|
|
5232
5736
|
cancelled = true;
|
|
5233
5737
|
};
|
|
5234
5738
|
}, [client, perspectiveId]);
|
|
5235
|
-
|
|
5739
|
+
useEffect10(() => {
|
|
5236
5740
|
if (state.status !== "requested" && state.status !== "polling") return;
|
|
5237
5741
|
const { requestId, startedAt } = state;
|
|
5238
5742
|
if (state.status === "requested") {
|
|
@@ -5282,7 +5786,7 @@ function createRunEvaluationAction(options = {}) {
|
|
|
5282
5786
|
}, POLL_INTERVAL_MS);
|
|
5283
5787
|
return () => clearInterval(interval);
|
|
5284
5788
|
}, [client, perspectiveId, state]);
|
|
5285
|
-
|
|
5789
|
+
useEffect10(() => {
|
|
5286
5790
|
if (state.status !== "error") return;
|
|
5287
5791
|
const timer = setTimeout(() => {
|
|
5288
5792
|
client.fetch(contentImpactQuery, buildReportQueryParams(perspectiveId)).then((results) => {
|
|
@@ -5302,7 +5806,7 @@ function createRunEvaluationAction(options = {}) {
|
|
|
5302
5806
|
}, 15e3);
|
|
5303
5807
|
return () => clearTimeout(timer);
|
|
5304
5808
|
}, [client, perspectiveId, state]);
|
|
5305
|
-
const handleRequest =
|
|
5809
|
+
const handleRequest = useCallback15(async () => {
|
|
5306
5810
|
const releaseTitle = release.metadata?.title ?? perspectiveId ?? "release";
|
|
5307
5811
|
const tag = `release-${slugify(releaseTitle)}-${dateStamp()}`;
|
|
5308
5812
|
const now = Date.now();
|
|
@@ -5424,9 +5928,12 @@ var ailfPlugin = definePlugin({
|
|
|
5424
5928
|
tools: [ailfTool()]
|
|
5425
5929
|
});
|
|
5426
5930
|
export {
|
|
5931
|
+
AssertionInput,
|
|
5932
|
+
CanonicalDocInput,
|
|
5427
5933
|
GLOSSARY,
|
|
5428
5934
|
GraduateToNativeAction,
|
|
5429
5935
|
MirrorBanner,
|
|
5936
|
+
ReleasePicker,
|
|
5430
5937
|
SyncStatusBadge,
|
|
5431
5938
|
ailfPlugin,
|
|
5432
5939
|
ailfTool,
|