From a13e72fcfa6f8cab5c48402da020ff6168646a5e Mon Sep 17 00:00:00 2001 From: Ben Christel <benchristel@khanacademy.org> Date: Thu, 16 Jan 2025 13:58:55 -0800 Subject: [PATCH 1/3] [benc/categorizer-options-type] Make 'values' optional on categorizer widget options --- packages/perseus-core/src/data-schema.ts | 2 +- .../perseus/src/util/extract-perseus-data.ts | 6 ++-- .../categorizer-widget.test.ts | 33 +++++++++++++++++++ .../perseus-parsers/categorizer-widget.ts | 2 +- .../src/widgets/categorizer/categorizer.tsx | 5 ++- 5 files changed, 40 insertions(+), 8 deletions(-) create mode 100644 packages/perseus/src/util/parse-perseus-json/perseus-parsers/categorizer-widget.test.ts diff --git a/packages/perseus-core/src/data-schema.ts b/packages/perseus-core/src/data-schema.ts index 32d5d3a03b..5bf5ac6c81 100644 --- a/packages/perseus-core/src/data-schema.ts +++ b/packages/perseus-core/src/data-schema.ts @@ -423,7 +423,7 @@ export type PerseusCategorizerWidgetOptions = { // Whether this widget is displayed with the results and immutable static: boolean; // The correct answers where index relates to the items and value relates to the category. e.g. [0, 1, 0, 1, 2] - values: ReadonlyArray<number>; + values?: ReadonlyArray<number>; // Whether we should highlight i18n linter errors found on this widget highlightLint?: boolean; // Internal editor configuration. Can be ignored by consumers. diff --git a/packages/perseus/src/util/extract-perseus-data.ts b/packages/perseus/src/util/extract-perseus-data.ts index 829bbf3032..43d4156259 100644 --- a/packages/perseus/src/util/extract-perseus-data.ts +++ b/packages/perseus/src/util/extract-perseus-data.ts @@ -59,9 +59,9 @@ function getAnswersFromWidgets( categorizer.options?.items && categorizer.options?.values ) { - const categories = categorizer.options?.categories; - const items = categorizer.options?.items; - const values = categorizer.options?.values; + const categories = categorizer.options.categories; + const items = categorizer.options.items; + const values = categorizer.options.values; answers.push( ...values.map( (value, index) => diff --git a/packages/perseus/src/util/parse-perseus-json/perseus-parsers/categorizer-widget.test.ts b/packages/perseus/src/util/parse-perseus-json/perseus-parsers/categorizer-widget.test.ts new file mode 100644 index 0000000000..93fb551747 --- /dev/null +++ b/packages/perseus/src/util/parse-perseus-json/perseus-parsers/categorizer-widget.test.ts @@ -0,0 +1,33 @@ +import { + CategorizerWidget, + PerseusLinterContext +} from "@khanacademy/perseus-core"; +import {parseCategorizerWidget} from "./categorizer-widget"; +import {success} from "../result"; +import {parse} from "../parse"; + +describe("parseCategorizerWidget", () => { + const baseWidget: CategorizerWidget = { + type: "categorizer", + version: {major: 0, minor: 0}, + graded: true, + options: { + items: [], + categories: [], + randomizeItems: false, + static: false, + } + } + + it("allows `values` to be undefined", () => { + const widget = { + ...baseWidget, + options: { + ...baseWidget.options, + values: undefined, + }, + }; + const result = parse(widget, parseCategorizerWidget); + expect(result).toEqual(success(widget)) + }); +}) diff --git a/packages/perseus/src/util/parse-perseus-json/perseus-parsers/categorizer-widget.ts b/packages/perseus/src/util/parse-perseus-json/perseus-parsers/categorizer-widget.ts index f436848306..2a649b0e78 100644 --- a/packages/perseus/src/util/parse-perseus-json/perseus-parsers/categorizer-widget.ts +++ b/packages/perseus/src/util/parse-perseus-json/perseus-parsers/categorizer-widget.ts @@ -21,7 +21,7 @@ export const parseCategorizerWidget: Parser<CategorizerWidget> = parseWidget( categories: array(string), randomizeItems: defaulted(boolean, () => false), static: defaulted(boolean, () => false), - values: array(defaulted(number, () => 0)), + values: optional(array(defaulted(number, () => 0))), highlightLint: optional(boolean), linterContext: optional( object({ diff --git a/packages/perseus/src/widgets/categorizer/categorizer.tsx b/packages/perseus/src/widgets/categorizer/categorizer.tsx index ab4c47e366..fd77de05c5 100644 --- a/packages/perseus/src/widgets/categorizer/categorizer.tsx +++ b/packages/perseus/src/widgets/categorizer/categorizer.tsx @@ -28,13 +28,13 @@ import type {CategorizerPromptJSON} from "../../widget-ai-utils/categorizer/cate import type {PerseusCategorizerWidgetOptions} from "@khanacademy/perseus-core"; type Props = WidgetProps<RenderProps, PerseusCategorizerScoringData> & { - values: ReadonlyArray<string>; + values: ReadonlyArray<number>; }; type DefaultProps = { items: Props["items"]; categories: Props["categories"]; - values: Props["values"]; + values: ReadonlyArray<number>; linterContext: Props["linterContext"]; }; @@ -79,7 +79,6 @@ export class Categorizer onChange(itemNum, catNum) { const values = [...this.props.values]; - // @ts-expect-error - TS2322 - Type 'number' is not assignable to type 'never'. values[itemNum] = catNum; this.change("values", values); this.props.trackInteraction(); From 780a8b87a4ae06f912575af74cb45c6b17607b77 Mon Sep 17 00:00:00 2001 From: Ben Christel <benchristel@khanacademy.org> Date: Thu, 16 Jan 2025 14:03:15 -0800 Subject: [PATCH 2/3] [benc/categorizer-options-type] docs(changeset): Make 'values' field optional on the PerseusCategorizerWidgetOptions type. This will allow us to remove ` --- .changeset/witty-suns-mate.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/witty-suns-mate.md diff --git a/.changeset/witty-suns-mate.md b/.changeset/witty-suns-mate.md new file mode 100644 index 0000000000..c2440edd67 --- /dev/null +++ b/.changeset/witty-suns-mate.md @@ -0,0 +1,6 @@ +--- +"@khanacademy/perseus": minor +"@khanacademy/perseus-core": minor +--- + +Make `values` field optional on the `PerseusCategorizerWidgetOptions` type. This will allow us to remove `values` (which represents the correct answer) from the data sent to the client. From e0885be884be1cafc01b63526960cc4b615a3523 Mon Sep 17 00:00:00 2001 From: Ben Christel <benchristel@khanacademy.org> Date: Thu, 16 Jan 2025 14:08:00 -0800 Subject: [PATCH 3/3] [benc/categorizer-options-type] Fix lint --- .../categorizer-widget.test.ts | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/packages/perseus/src/util/parse-perseus-json/perseus-parsers/categorizer-widget.test.ts b/packages/perseus/src/util/parse-perseus-json/perseus-parsers/categorizer-widget.test.ts index 93fb551747..9f04bd1116 100644 --- a/packages/perseus/src/util/parse-perseus-json/perseus-parsers/categorizer-widget.test.ts +++ b/packages/perseus/src/util/parse-perseus-json/perseus-parsers/categorizer-widget.test.ts @@ -1,10 +1,9 @@ -import { - CategorizerWidget, - PerseusLinterContext -} from "@khanacademy/perseus-core"; -import {parseCategorizerWidget} from "./categorizer-widget"; -import {success} from "../result"; import {parse} from "../parse"; +import {success} from "../result"; + +import {parseCategorizerWidget} from "./categorizer-widget"; + +import type {CategorizerWidget} from "@khanacademy/perseus-core"; describe("parseCategorizerWidget", () => { const baseWidget: CategorizerWidget = { @@ -16,8 +15,8 @@ describe("parseCategorizerWidget", () => { categories: [], randomizeItems: false, static: false, - } - } + }, + }; it("allows `values` to be undefined", () => { const widget = { @@ -28,6 +27,6 @@ describe("parseCategorizerWidget", () => { }, }; const result = parse(widget, parseCategorizerWidget); - expect(result).toEqual(success(widget)) + expect(result).toEqual(success(widget)); }); -}) +});