-
Notifications
You must be signed in to change notification settings - Fork 350
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Migrate PerseusWidgetsMap to use a merged interface to represent all available widgets #1936
Conversation
npm Snapshot: PublishedGood news!! We've packaged up the latest commit from this PR (6a590e7) and published it to npm. You Example: yarn add @khanacademy/perseus@PR1936 If you are working in Khan Academy's webapp, you can run: ./dev/tools/bump_perseus_version.sh -t PR1936 |
Size Change: +918 B (+0.07%) Total Size: 1.29 MB
ℹ️ View Unchanged
|
* | ||
* @see {@link https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation} | ||
*/ | ||
export interface PerseusWidgetTypes { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Although this looks like the same hard-coded list of widgets as PerseusWidgetsMap
is in the "before" state of this PR, the magic is that we can extend this interface from anywhere (even in our own Perseus unit tests if we want to work with a mock widget). Once we've added an entry to this interface, PerseusWidgetsMap automatically know's about that widget!
GeraldRequired Reviewers
Don't want to be involved in this pull request? Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is WAY better than our first attempt, thank you greatly for this work! This seems considerably more maintainable and readable. I'm not seeing anything that should cause any issues with the Extract Perseus Data logic, and if there's no type errors, this gets the all clear from me.
Thank you for adding some truly excellent comments as well. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Thanks for doing the due diligence to verify that this plan will work. I left a few documentation suggestions in the comments – nothing blocking. 🚢
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like a great improvement! Thanks Jeremy!!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool, thanks for digging into this more!
PerseusWidgetTypes, | ||
MultiItem, | ||
WidgetOptions, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you know that these will be used in Webapp or are we preemptively exporting them? If not, I wonder if it would be better to keep them internal until we have a use for them externally.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PerseusWidgetTypes
needs to be exported so that it can be extended from anywhere outside of Perseus. @kevinb-khan has already had a use case for this while building a hackathon widget inside of webapp.
WidgetOptions
is a very useful helper type for defining a widget's widget options structure.
Both are forward-looking, but it seemed reasonable to export them as part of this PR given the "widgets can be created outside of the @khanacademy/perseus" package nature.
Radio: RadioWidget; | ||
Sorter: SorterWidget; | ||
Table: TableWidget; | ||
Video: VideoWidget; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not related to your PR and no action needed: can we leverage this or something like this to get rid of basic-widgets
, extra-widgets
, and all-widgets
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think so. This interface is a registry of widget option types whereas the things you mentioned are the "runtime registries". We could certainly merge all those three items together though.
* | ||
* @see {@link https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation} | ||
*/ | ||
export interface PerseusWidgetTypes { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is a step in the right direction, I just wish we could get to a place where the Renderer-layer of Perseus is completely unaware of the Widget-layer data which would mean finding ways to eliminate these type of widget union/map things.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed! I've spent a decent amount of time thinking about how we could make the lower level types opaque to the Renderers, I don't have a solution yet.
This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated. # Releases ## @khanacademy/[email protected] ### Minor Changes - [#1901](#1901) [`051c50cf7`](051c50c) Thanks [@Myranae](https://github.com/Myranae)! - Introduces a validation function for the number line widget (extracted from the scoring function). - [#1936](#1936) [`d05272661`](d052726) Thanks [@jeremywiebe](https://github.com/jeremywiebe)! - Changes the PerseusWidgetsMap to be extensible so that widgets can be registered outside of Perseus and still have full type safety. - [#1832](#1832) [`e3062b3c8`](e3062b3) Thanks [@mark-fitzgerald](https://github.com/mark-fitzgerald)! - [Numeric Input] - Update the UI to match Expression widget ### Patch Changes - [#1937](#1937) [`3cdabf1a3`](3cdabf1) Thanks [@jeremywiebe](https://github.com/jeremywiebe)! - TypeScript fixes - [#1948](#1948) [`e21a3a39b`](e21a3a3) Thanks [@jeremywiebe](https://github.com/jeremywiebe)! - Refactor internally used object mapping utilities to use ES6 exports - [#1938](#1938) [`5e8d8468b`](5e8d846) Thanks [@jeremywiebe](https://github.com/jeremywiebe)! - Type fixes - [#1942](#1942) [`1d2b4e7bf`](1d2b4e7) Thanks [@SonicScrewdriver](https://github.com/SonicScrewdriver)! - Ensure that zoomed-in images retain alt text - [#1861](#1861) [`763a4ba38`](763a4ba) Thanks [@mark-fitzgerald](https://github.com/mark-fitzgerald)! - [Numeric Input] - Show format options as a list - [#1947](#1947) [`b8926e38a`](b8926e3) Thanks [@jeremywiebe](https://github.com/jeremywiebe)! - Minor refactoring of ServerItemRenderer's componentDidUpdate to reduce duplication - [#1946](#1946) [`f35512786`](f355127) Thanks [@jeremywiebe](https://github.com/jeremywiebe)! - Refactor scoring for `group` widget to follow the same pattern as all other widgets - [#1891](#1891) [`ef819ea95`](ef819ea) Thanks [@mark-fitzgerald](https://github.com/mark-fitzgerald)! - [Numeric Input] - Associate format options tooltip content with input field for assistive technologies - [#1945](#1945) [`e69ca3146`](e69ca31) Thanks [@nishasy](https://github.com/nishasy)! - Add global styles to reflect prod styling - [#1923](#1923) [`be8c06c75`](be8c06c) Thanks [@benchristel](https://github.com/benchristel)! - Internal: convert backgroundImage dimensions to numbers during parsing. - [#1934](#1934) [`129adebef`](129adeb) Thanks [@jeremywiebe](https://github.com/jeremywiebe)! - Improve comments on some Perseus types - [#1924](#1924) [`2d89ef87d`](2d89ef8) Thanks [@benchristel](https://github.com/benchristel)! - Internal: add and pass regression tests for PerseusItem parser's handling of legacy data ## @khanacademy/[email protected] ### Patch Changes - [#1938](#1938) [`5e8d8468b`](5e8d846) Thanks [@jeremywiebe](https://github.com/jeremywiebe)! - Type fixes - [#1937](#1937) [`3cdabf1a3`](3cdabf1) Thanks [@jeremywiebe](https://github.com/jeremywiebe)! - Ensure links opening to style guide (Google Docs) set `rel="noreferrer"` - [#1946](#1946) [`f35512786`](f355127) Thanks [@jeremywiebe](https://github.com/jeremywiebe)! - Remove debugging call in GraphSettings component - Updated dependencies \[[`3cdabf1a3`](3cdabf1), [`e21a3a39b`](e21a3a3), [`5e8d8468b`](5e8d846), [`1d2b4e7bf`](1d2b4e7), [`763a4ba38`](763a4ba), [`b8926e38a`](b8926e3), [`f35512786`](f355127), [`ef819ea95`](ef819ea), [`e69ca3146`](e69ca31), [`be8c06c75`](be8c06c), [`051c50cf7`](051c50c), [`129adebef`](129adeb), [`d05272661`](d052726), [`2d89ef87d`](2d89ef8), [`e3062b3c8`](e3062b3)]: - @khanacademy/[email protected] Author: khan-actions-bot Reviewers: mark-fitzgerald Required Reviewers: Approved By: mark-fitzgerald Checks: ⏭️ Publish npm snapshot, ✅ Check builds for changes in size (ubuntu-latest, 20.x), ✅ Lint, Typecheck, Format, and Test (ubuntu-latest, 20.x), ✅ Cypress (ubuntu-latest, 20.x), ✅ Check for .changeset entries for all changed files (ubuntu-latest, 20.x), ✅ gerald Pull Request URL: #1944
Summary:
Perseus is designed to be able to support widgets registered into it at runtime. These widgets can be built in a separate npm package or even in the hosting application. As a result, the way that we've defined the
widgets
prop ofPerseusRenderer
is too rigid and poses long-term maintenance issues.As I was working on slitting out the bits of validation from scoring that we'll still be able to do on the client-side, I faced the same challenge (we will have a map of widget IDs for validation).
Working with Kevin Barabash, we figured out a way to define an interface that represents all registered widgets and then use some TypeScript types to generate the
PerseusWidgetsMap
. This allows us to extend the "known set" of widgets from outside of Perseus.Although this is not an immediate concern, it will become more and more troublesome to build maps of widget information that are hard-coded to our current set of widgets.
Issue: "none"
Test plan:
yarn typecheck
yarn test
I'll import this npm snapshot into webapp to check that all types are fine there also.
EDIT: I installed the snapshot package in webapp and it type checks! ✅