Skip to content

Commit

Permalink
Merge branch 'main' into locked-vector-labels-editor
Browse files Browse the repository at this point in the history
  • Loading branch information
nishasy authored Sep 24, 2024
2 parents ed552a4 + 03cddb6 commit 09ae084
Show file tree
Hide file tree
Showing 44 changed files with 887 additions and 340 deletions.
5 changes: 5 additions & 0 deletions .changeset/eleven-elephants-trade.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@khanacademy/perseus": patch
---

Omit unused data from interactive graph onChange callback
6 changes: 0 additions & 6 deletions .changeset/few-moles-obey.md

This file was deleted.

6 changes: 0 additions & 6 deletions .changeset/good-foxes-allow.md

This file was deleted.

5 changes: 5 additions & 0 deletions .changeset/loud-parrots-run.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@khanacademy/perseus": patch
---

Move validation logic out of the sorter widget and add tests
5 changes: 0 additions & 5 deletions .changeset/modern-dancers-decide.md

This file was deleted.

5 changes: 0 additions & 5 deletions .changeset/smart-bottles-listen.md

This file was deleted.

6 changes: 0 additions & 6 deletions .changeset/swift-parrots-hear.md

This file was deleted.

5 changes: 0 additions & 5 deletions .changeset/violet-scissors-punch.md

This file was deleted.

107 changes: 79 additions & 28 deletions config/test/custom-matchers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,78 +18,128 @@ type PerseusRenderer = {
guessAndScore: () => [Array<any>, PerseusScore];
};

type Answerable = PerseusRenderer | PerseusScore;

function isRenderer(obj: Answerable): obj is PerseusRenderer {
// @ts-expect-error - TS(2339) - TS is annoying
return obj?.guessAndScore !== undefined;
}

function check(answerable: Answerable) {
let widgetState: string = "";
let score: PerseusScore;

if (isRenderer(answerable)) {
const result = answerable.guessAndScore();
widgetState = JSON.stringify(result[0]);
score = result[1];
} else {
score = answerable;
}

return {widgetState, score};
}

function maybeAddState(message: string, widgetState: string): string {
if (!widgetState) {
return message;
}

return message + `; widget state: ${widgetState}`;
}

expect.extend({
toHaveBeenAnsweredCorrectly(renderer: PerseusRenderer) {
const [widgetState, score] = renderer.guessAndScore();
toHaveBeenAnsweredCorrectly(answerable: Answerable) {
const {widgetState, score} = check(answerable);

if (score.type === "invalid") {
const errMessage = maybeAddState(
`Invalid answer: ${score.message || "(no message)"}`,
widgetState,
);

return {
pass: false,
message: () =>
`Invalid answer: ${
score.message || "(no message)"
}; widget state ${JSON.stringify(widgetState)}`,
message: () => errMessage,
};
}

if (score.type !== "points") {
return {
pass: false,
message: () => `Problem was not fully answered`,
};
}

if (score.earned !== score.total) {
const errMessage = maybeAddState(
"Problem was answered incorrectly",
widgetState,
);

return {
pass: false,
message: () =>
`Problem was answered incorrectly. Widget state: ${JSON.stringify(
widgetState,
)}`,
message: () => errMessage,
};
}

return {pass: true, message: () => ""};
},

toHaveInvalidInput(renderer: PerseusRenderer, message: string | null) {
const [widgetState, score] = renderer.guessAndScore();
toHaveInvalidInput(answerable: Answerable, message: string | null) {
const {widgetState, score} = check(answerable);

if (score.type !== "invalid") {
const errMessage = maybeAddState(
`Answer state is not invalid. Score: ${JSON.stringify(score)}`,
widgetState,
);

return {
pass: false,
message: () =>
`Answer state is not invalid. Score: ${JSON.stringify(
score,
)}; ${JSON.stringify(widgetState)}`,
message: () => errMessage,
};
}

if (message && (!score.message || !score.message.includes(message))) {
const errMessage = maybeAddState(
`Message shown for invalid input did not include "${message}": ${
score.message || "(no message)"
}. Score: ${JSON.stringify(score)}`,
widgetState,
);

return {
pass: false,
message: () =>
`Message shown for invalid input did not include "${message}": ${
score.message || "(no message)"
}. ${JSON.stringify(score)} - ${JSON.stringify(
widgetState,
)}`,
message: () => errMessage,
};
}

return {pass: true, message: () => ""};
},

toHaveBeenAnsweredIncorrectly(renderer: PerseusRenderer) {
const [widgetState, score] = renderer.guessAndScore();
toHaveBeenAnsweredIncorrectly(answerable: Answerable) {
const {widgetState, score} = check(answerable);

if (score.type === "invalid") {
const errMessage = maybeAddState(
`Invalid answer: ${score.message || "(no message)"}`,
widgetState,
);

return {
pass: false,
message: () =>
`Invalid answer: ${
score.message || "(no message)"
}; widget state ${JSON.stringify(widgetState)}`,
message: () => errMessage,
};
}

if (score.type !== "points") {
return {
pass: false,
message: () => `Problem was not fully answered`,
};
}

if (score.earned !== 0) {
return {
pass: false,
Expand All @@ -99,6 +149,7 @@ expect.extend({
)}`,
};
}

return {pass: true, message: () => ""};
},

Expand Down
17 changes: 17 additions & 0 deletions packages/perseus-editor/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
# @khanacademy/perseus-editor

## 14.4.0

### Minor Changes

- [#1642](https://github.com/Khan/perseus/pull/1642) [`75e19c557`](https://github.com/Khan/perseus/commit/75e19c557a0439b6645d09c3a0586d7f09d06539) Thanks [@nishasy](https://github.com/nishasy)! - [Locked Figure Labels] View locked line labels

* [#1647](https://github.com/Khan/perseus/pull/1647) [`49bf45573`](https://github.com/Khan/perseus/commit/49bf4557313c7d69d5a287095991cf11cbc81752) Thanks [@nishasy](https://github.com/nishasy)! - [Locked Figure Labels] Add labels to locked lines' defining points in the graph and editor

- [#1644](https://github.com/Khan/perseus/pull/1644) [`136b6e54c`](https://github.com/Khan/perseus/commit/136b6e54cf6ab1a8514533bad03ac7f752532084) Thanks [@nishasy](https://github.com/nishasy)! - [Locked Figure Labels] Add/edit/delete locked line labels

* [#1643](https://github.com/Khan/perseus/pull/1643) [`2950ec33f`](https://github.com/Khan/perseus/commit/2950ec33ff6bcea92ffc3bf035fff6fdffa22804) Thanks [@anniegallagher](https://github.com/anniegallagher)! - Make widget editors expanded by default. Add ability to expand/collapse all widget editors on a page externally.

### Patch Changes

- Updated dependencies [[`7822ea63c`](https://github.com/Khan/perseus/commit/7822ea63c9f91adebe2b6ea0841db1ae62c9d088), [`75e19c557`](https://github.com/Khan/perseus/commit/75e19c557a0439b6645d09c3a0586d7f09d06539), [`49bf45573`](https://github.com/Khan/perseus/commit/49bf4557313c7d69d5a287095991cf11cbc81752), [`1080a628b`](https://github.com/Khan/perseus/commit/1080a628bd77139be91987763153273318dd8792), [`d766b33dd`](https://github.com/Khan/perseus/commit/d766b33dd70d63e2441fa1655ca30230432a6418), [`25d45af95`](https://github.com/Khan/perseus/commit/25d45af95aaacf302a7ea0cceae9d4c0cf1cab0b), [`b5594e81d`](https://github.com/Khan/perseus/commit/b5594e81d81bbc9dcd100bfc35dbca98c2241c51), [`f5ceabb7d`](https://github.com/Khan/perseus/commit/f5ceabb7dbdfc984d08eed0ea55cf4202ca276e2), [`136b6e54c`](https://github.com/Khan/perseus/commit/136b6e54cf6ab1a8514533bad03ac7f752532084), [`64bcde0a1`](https://github.com/Khan/perseus/commit/64bcde0a1f98b4232e5347a06f4c8cad7265d006)]:
- @khanacademy/perseus@34.1.0

## 14.3.0

### Minor Changes
Expand Down
4 changes: 2 additions & 2 deletions packages/perseus-editor/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"description": "Perseus editors",
"author": "Khan Academy",
"license": "MIT",
"version": "14.3.0",
"version": "14.4.0",
"publishConfig": {
"access": "public"
},
Expand Down Expand Up @@ -38,7 +38,7 @@
"@khanacademy/keypad-context": "^1.0.1",
"@khanacademy/kmath": "^0.1.13",
"@khanacademy/math-input": "^21.0.2",
"@khanacademy/perseus": "^34.0.0",
"@khanacademy/perseus": "^34.1.0",
"@khanacademy/perseus-core": "1.5.0",
"mafs": "^0.19.0"
},
Expand Down
10 changes: 9 additions & 1 deletion packages/perseus-editor/src/components/widget-editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ type WidgetEditorProps = {
) => unknown;
onRemove: () => unknown;
apiOptions: APIOptions;
widgetIsOpen?: boolean;
} & Omit<PerseusWidget, "key">;

type WidgetEditorState = {
Expand Down Expand Up @@ -59,7 +60,7 @@ class WidgetEditor extends React.Component<
constructor(props: WidgetEditorProps) {
super(props);
this.state = {
showWidget: false,
showWidget: props.widgetIsOpen ?? true,
widgetInfo: _upgradeWidgetInfo(props),
};
this.widget = React.createRef();
Expand All @@ -68,6 +69,13 @@ class WidgetEditor extends React.Component<
// eslint-disable-next-line react/no-unsafe
UNSAFE_componentWillReceiveProps(nextProps: WidgetEditorProps) {
this.setState({widgetInfo: _upgradeWidgetInfo(nextProps)});
// user can update internal state while the widget is handled globally
if (
nextProps.widgetIsOpen != null &&
nextProps.widgetIsOpen !== this.props.widgetIsOpen
) {
this.setState({showWidget: nextProps.widgetIsOpen});
}
}

_toggleWidget = (e: React.SyntheticEvent) => {
Expand Down
5 changes: 5 additions & 0 deletions packages/perseus-editor/src/editor-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ type Props = {
onChange: ChangeHandler;
onPreviewDeviceChange: (arg1: DeviceType) => unknown;
previewDevice: DeviceType;
// A global control to expand/collapse all widget editors on a page.
widgetsAreOpen?: boolean;
// Initial value of the question being edited
question?: any;
// URL of the route to show on initial load of the preview frames.
Expand All @@ -59,6 +61,7 @@ type State = {
gradeMessage: string;
wasAnswered: boolean;
highlightLint: boolean;
widgetsAreOpen: boolean;
};

class EditorPage extends React.Component<Props, State> {
Expand Down Expand Up @@ -93,6 +96,7 @@ class EditorPage extends React.Component<Props, State> {
gradeMessage: "",
wasAnswered: false,
highlightLint: true,
widgetsAreOpen: this.props.widgetsAreOpen ?? true,
};

this._isMounted = false;
Expand Down Expand Up @@ -299,6 +303,7 @@ class EditorPage extends React.Component<Props, State> {
wasAnswered={this.state.wasAnswered}
gradeMessage={this.state.gradeMessage}
deviceType={this.props.previewDevice}
widgetIsOpen={this.state.widgetsAreOpen}
apiOptions={deviceBasedApiOptions}
previewURL={this.props.previewURL}
/>
Expand Down
2 changes: 2 additions & 0 deletions packages/perseus-editor/src/editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ type Props = Readonly<{
showWordCount: boolean;
warnNoPrompt: boolean;
warnNoWidgets: boolean;
widgetIsOpen?: boolean;
imageUploader?: ImageUploader;
onChange: ChangeHandler;
}>;
Expand Down Expand Up @@ -262,6 +263,7 @@ class Editor extends React.Component<Props, State> {
// eslint-disable-next-line react/jsx-no-bind
onRemove={this._handleWidgetEditorRemove.bind(this, id)}
apiOptions={this.props.apiOptions}
widgetIsOpen={this.props.widgetIsOpen}
{...this.props.widgets[id]}
/>
);
Expand Down
2 changes: 2 additions & 0 deletions packages/perseus-editor/src/item-editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const ITEM_DATA_VERSION = itemDataVersion;
type Props = {
apiOptions?: APIOptions;
deviceType?: DeviceType;
widgetIsOpen?: boolean;
gradeMessage?: string;
imageUploader?: ImageUploader;
wasAnswered?: boolean;
Expand Down Expand Up @@ -110,6 +111,7 @@ class ItemEditor extends React.Component<Props> {
onChange={this.handleEditorChange}
apiOptions={this.props.apiOptions}
showWordCount={true}
widgetIsOpen={this.props.widgetIsOpen}
{...this.props.question}
/>
</div>
Expand Down
26 changes: 26 additions & 0 deletions packages/perseus/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,31 @@
# @khanacademy/perseus

## 34.1.0

### Minor Changes

- [#1642](https://github.com/Khan/perseus/pull/1642) [`75e19c557`](https://github.com/Khan/perseus/commit/75e19c557a0439b6645d09c3a0586d7f09d06539) Thanks [@nishasy](https://github.com/nishasy)! - [Locked Figure Labels] View locked line labels

* [#1647](https://github.com/Khan/perseus/pull/1647) [`49bf45573`](https://github.com/Khan/perseus/commit/49bf4557313c7d69d5a287095991cf11cbc81752) Thanks [@nishasy](https://github.com/nishasy)! - [Locked Figure Labels] Add labels to locked lines' defining points in the graph and editor

- [#1644](https://github.com/Khan/perseus/pull/1644) [`136b6e54c`](https://github.com/Khan/perseus/commit/136b6e54cf6ab1a8514533bad03ac7f752532084) Thanks [@nishasy](https://github.com/nishasy)! - [Locked Figure Labels] Add/edit/delete locked line labels

### Patch Changes

- [#1646](https://github.com/Khan/perseus/pull/1646) [`7822ea63c`](https://github.com/Khan/perseus/commit/7822ea63c9f91adebe2b6ea0841db1ae62c9d088) Thanks [@nicolecomputer](https://github.com/nicolecomputer)! - Keyboard support for unlimited point graphs

* [#1651](https://github.com/Khan/perseus/pull/1651) [`1080a628b`](https://github.com/Khan/perseus/commit/1080a628bd77139be91987763153273318dd8792) Thanks [@handeyeco](https://github.com/handeyeco)! - Consolidate Measurer and DeprecatedStandin to use noopValidator

- [#1640](https://github.com/Khan/perseus/pull/1640) [`d766b33dd`](https://github.com/Khan/perseus/commit/d766b33dd70d63e2441fa1655ca30230432a6418) Thanks [@Myranae](https://github.com/Myranae)! - Move validation logic out of the Input Number widget

* [#1657](https://github.com/Khan/perseus/pull/1657) [`25d45af95`](https://github.com/Khan/perseus/commit/25d45af95aaacf302a7ea0cceae9d4c0cf1cab0b) Thanks [@benchristel](https://github.com/benchristel)! - Internal: delete an outdated comment

- [#1649](https://github.com/Khan/perseus/pull/1649) [`b5594e81d`](https://github.com/Khan/perseus/commit/b5594e81d81bbc9dcd100bfc35dbca98c2241c51) Thanks [@handeyeco](https://github.com/handeyeco)! - Custom Jest matchers for PerseusScore

* [#1641](https://github.com/Khan/perseus/pull/1641) [`f5ceabb7d`](https://github.com/Khan/perseus/commit/f5ceabb7dbdfc984d08eed0ea55cf4202ca276e2) Thanks [@Myranae](https://github.com/Myranae)! - Move validation logic out of the Categorizer widget

- [#1636](https://github.com/Khan/perseus/pull/1636) [`64bcde0a1`](https://github.com/Khan/perseus/commit/64bcde0a1f98b4232e5347a06f4c8cad7265d006) Thanks [@handeyeco](https://github.com/handeyeco)! - Small tweak to validation logic for non-interactive widgets

## 34.0.0

### Major Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/perseus/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"description": "Core Perseus API (includes renderers and widgets)",
"author": "Khan Academy",
"license": "MIT",
"version": "34.0.0",
"version": "34.1.0",
"publishConfig": {
"access": "public"
},
Expand Down
Loading

0 comments on commit 09ae084

Please sign in to comment.