Skip to content

Commit

Permalink
[Locked Figure Labels] View locked function labels (#1658)
Browse files Browse the repository at this point in the history
## Summary:
- Add feature flag for locked function labels
- Add labels to LockedFunctionType
- update builder
- update stories and tests
  - add a story for all locked figure labels

Issue: https://khanacademy.atlassian.net/browse/LEMS-2351

## Test plan:
- Go to http://localhost:6006/?path=/story/perseuseditor-widgets-interactive-graph--mafs-with-locked-function-labels-flag
- Confirm that the visible label is on the locked function only
- Go to the other locked figures' stories and confirm that
  the locked function does not have a visible label (to make sure
  that the flags are separating the behaviors correctly)

<img width="492" alt="image" src="https://github.com/user-attachments/assets/4e673a9e-2ebc-4145-8f21-06364ead89ca">

Author: nishasy

Reviewers: benchristel, catandthemachines, anakaren-rojas

Required Reviewers:

Approved By: benchristel

Checks: ✅ Upload Coverage (ubuntu-latest, 20.x), ✅ Lint, Typecheck, Format, and Test (ubuntu-latest, 20.x), ✅ Publish npm snapshot (ubuntu-latest, 20.x), ✅ Jest Coverage (ubuntu-latest, 20.x), ✅ Check builds for changes in size (ubuntu-latest, 20.x), ✅ Cypress (ubuntu-latest, 20.x), ✅ Check for .changeset entries for all changed files (ubuntu-latest, 20.x), ✅ Publish Storybook to Chromatic (ubuntu-latest, 20.x), ✅ gerald

Pull Request URL: #1658
  • Loading branch information
nishasy authored Sep 24, 2024
1 parent 790e189 commit 20b3a24
Show file tree
Hide file tree
Showing 12 changed files with 141 additions and 2 deletions.
6 changes: 6 additions & 0 deletions .changeset/spotty-days-burn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@khanacademy/perseus": minor
"@khanacademy/perseus-editor": minor
---

[Locked Figure Labels] View locked function labels
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const flags = {
"locked-line-labels": true,
"locked-vector-labels": true,
"locked-ellipse-labels": true,
"locked-function-labels": true,
},
} satisfies APIOptions["flags"];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ export const MafsWithLockedFiguresCurrent = (): React.ReactElement => {
"locked-line-labels": false,
"locked-vector-labels": false,
"locked-ellipse-labels": false,
"locked-function-labels": false,
},
},
}}
Expand Down Expand Up @@ -185,6 +186,7 @@ export const MafsWithLockedLabelsFlag = (): React.ReactElement => {
"locked-line-labels": false,
"locked-vector-labels": false,
"locked-ellipse-labels": false,
"locked-function-labels": false,
},
},
}}
Expand All @@ -205,6 +207,7 @@ export const MafsWithLockedPointLabelsFlag = (): React.ReactElement => {
"locked-line-labels": false,
"locked-vector-labels": false,
"locked-ellipse-labels": false,
"locked-function-labels": false,
},
},
}}
Expand All @@ -225,6 +228,7 @@ export const MafsWithLockedLineLabelsFlag = (): React.ReactElement => {
"locked-line-labels": true,
"locked-vector-labels": false,
"locked-ellipse-labels": false,
"locked-function-labels": false,
},
},
}}
Expand All @@ -245,6 +249,7 @@ export const MafsWithLockedVectorLabelsFlag = (): React.ReactElement => {
"locked-line-labels": false,
"locked-vector-labels": true,
"locked-ellipse-labels": false,
"locked-function-labels": false,
},
},
}}
Expand All @@ -265,6 +270,7 @@ export const MafsWithLockedEllipseLabelsFlag = (): React.ReactElement => {
"locked-line-labels": false,
"locked-vector-labels": false,
"locked-ellipse-labels": true,
"locked-function-labels": false,
},
},
}}
Expand All @@ -273,6 +279,33 @@ export const MafsWithLockedEllipseLabelsFlag = (): React.ReactElement => {
);
};

export const MafsWithLockedFunctionLabelsFlag = (): React.ReactElement => {
return (
<EditorPageWithStorybookPreview
apiOptions={{
flags: {
mafs: {
...flags.mafs,
"interactive-graph-locked-features-labels": true,
"locked-point-labels": false,
"locked-line-labels": false,
"locked-vector-labels": false,
"locked-ellipse-labels": false,
"locked-function-labels": true,
},
},
}}
question={segmentWithLockedFigures}
/>
);
};

export const MafsWithLockedFigureLabelsAllFlags = (): React.ReactElement => {
return (
<EditorPageWithStorybookPreview question={segmentWithLockedFigures} />
);
};

export const WithSaveWarnings = (): React.ReactElement => {
const [previewDevice, setPreviewDevice] =
React.useState<DeviceType>("phone");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ describe("getDefaultFigureForType", () => {
strokeStyle: "solid",
equation: "x^2",
directionalAxis: "x",
labels: [],
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ export function getDefaultFigureForType(type: LockedFigureType): LockedFigure {
strokeStyle: "solid",
equation: "x^2",
directionalAxis: "x",
labels: [],
};
case "label":
return {
Expand Down
1 change: 1 addition & 0 deletions packages/perseus/src/perseus-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -780,6 +780,7 @@ export type LockedFunctionType = {
equation: string; // This is the user-defined equation (as it was typed)
directionalAxis: "x" | "y";
domain?: Interval;
labels: LockedLabelType[];
};

// Not associated with a specific figure
Expand Down
5 changes: 5 additions & 0 deletions packages/perseus/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,11 @@ export const InteractiveGraphLockedFeaturesFlags = [
* updated Interactive Graph widget.
*/
"locked-ellipse-labels",
/**
* Enables/disables the labels associated with locked functions in the
* updated Interactive Graph widget.
*/
"locked-function-labels",
] as const;

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ export default function GraphLockedLabelsLayer(props: Props) {
figure.type === "vector") ||
// Ellipse flag + ellipse type
(flags?.["mafs"]?.["locked-ellipse-labels"] &&
figure.type === "ellipse")
figure.type === "ellipse") ||
// Function flag + function type
(flags?.["mafs"]?.["locked-function-labels"] &&
figure.type === "function")
) {
return (
<React.Fragment key={i}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1199,17 +1199,19 @@ describe("InteractiveGraphQuestionBuilder", () => {
color: "grayH",
strokeStyle: "solid",
directionalAxis: "x",
labels: [],
},
]);
});

it("adds a locked function with options", () => {
it("adds a locked function with options and minimal label", () => {
const question: PerseusRenderer = interactiveGraphQuestionBuilder()
.addLockedFunction("x^2", {
color: "green",
strokeStyle: "dashed",
directionalAxis: "y",
domain: [-5, 5],
labels: [{text: "a label"}],
})
.build();
const graph = question.widgets["interactive-graph 1"];
Expand All @@ -1222,6 +1224,43 @@ describe("InteractiveGraphQuestionBuilder", () => {
strokeStyle: "dashed",
directionalAxis: "y",
domain: [-5, 5],
labels: [
{
type: "label",
text: "a label",
coord: [0, 0],
color: "green",
size: "medium",
},
],
},
]);
});

it("adds a locked function with a specific label", () => {
const question: PerseusRenderer = interactiveGraphQuestionBuilder()
.addLockedFunction("x^2", {
labels: [{text: "a label", coord: [9, 9], size: "small"}],
})
.build();
const graph = question.widgets["interactive-graph 1"];

expect(graph.options.lockedFigures).toEqual([
{
type: "function",
equation: "x^2",
color: "grayH",
strokeStyle: "solid",
directionalAxis: "x",
labels: [
{
type: "label",
text: "a label",
coord: [9, 9],
color: "grayH",
size: "small",
},
],
},
]);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export type LockedFunctionOptions = {
strokeStyle?: LockedLineStyle;
directionalAxis?: "x" | "y";
domain?: Interval;
labels?: LockedFigureLabelOptions[];
};

type LockedFigureLabelOptions = {
Expand Down Expand Up @@ -437,6 +438,17 @@ class InteractiveGraphQuestionBuilder {
strokeStyle: "solid",
directionalAxis: "x",
...options,
labels:
options?.labels?.map(
(label) =>
({
type: "label",
coord: label.coord ?? [0, 0],
text: label.text,
color: options?.color ?? "grayH",
size: label.size ?? "medium",
}) satisfies LockedLabelType,
) ?? [],
};

this.addLockedFigure(lockedFunction);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
circleQuestion,
circleQuestionWithDefaultCorrect,
graphWithLabeledEllipse,
graphWithLabeledFunction,
graphWithLabeledLine,
graphWithLabeledPoint,
graphWithLabeledVector,
Expand Down Expand Up @@ -1098,6 +1099,34 @@ describe("locked layer", () => {
});
});

it("should render a locked label within a locked function", async () => {
// Arrange
const {container} = renderQuestion(graphWithLabeledFunction, {
flags: {
mafs: {
segment: true,
"interactive-graph-locked-features-labels": true,
"locked-function-labels": true,
},
},
});

// Act
// eslint-disable-next-line testing-library/no-container, testing-library/no-node-access
const labels = container.querySelectorAll(".locked-label");
const label = labels[0];

// Assert
expect(labels).toHaveLength(1);
expect(label).toHaveTextContent("E");
expect(label).toHaveStyle({
color: lockedFigureColors["grayH"],
fontSize: "16px",
left: "200px",
top: "200px",
});
});

it("should have an aria-label and description if they are provided", async () => {
// Arrange
const {container} = renderQuestion(interactiveGraphWithAriaLabel, {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -856,6 +856,7 @@ export const segmentWithLockedFigures: PerseusRenderer =
)
.addLockedFunction("sin(x)", {
color: "red",
labels: [{text: "E"}],
})
.addLockedLabel("\\sqrt{\\frac{1}{2}}", [6, -5])
.build();
Expand Down Expand Up @@ -989,3 +990,10 @@ export const graphWithLabeledEllipse: PerseusRenderer =
labels: [{text: "D"}],
})
.build();

export const graphWithLabeledFunction: PerseusRenderer =
interactiveGraphQuestionBuilder()
.addLockedFunction("sin(x)", {
labels: [{text: "E"}],
})
.build();

0 comments on commit 20b3a24

Please sign in to comment.