-
Notifications
You must be signed in to change notification settings - Fork 33
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
feat: Library Content Block Editor #411
Conversation
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.
Just some early feedback (I realize this is not fully ready for review yet.)
fetchLibraryProperty: ({ studioEndpointUrl, libraryId }) => get( | ||
urls.libraryProperty({ studioEndpointUrl, libraryId }), | ||
), | ||
fetchLibraryContent: ({ studioEndpointUrl, libraryId }) => get( |
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.
Hate to drop a confounding variable at this point in the process (so maybe it should be a fast follow to this PR). I think this will end up making the code much more simple and fast, but might be frustrating now:
In reading this, I realize I may have not gotten a particular point across. I attempted to explain that library content blocks copy content from the library into the course. This value is stored as the "children" of the library content block in the course. As this copy is now in the course, we can edit it, and the library remains unchanged.
Therefore, we don't want to be fetching the blocks from the library. Instead, we already have them stored in the library content block as the "children" values.
Does that make sense?
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.
What does the lifecycle of the library api methods look like? Do we only initialize them for library editors (I hope that is a yes). Just couldn't see that cleanly in the code.
You should be able to see these in the
|
Oof I left the description half finished. I'll update that in a bit and I'll make sure to add that screenshot. |
Yes, the |
fetchV2Libraries: 'fetchV2Libraries', | ||
fetchV2LibraryMetadata: 'fetchV2LibraryMetadata', | ||
fetchV2LibraryContent: 'fetchV2LibraryContent', | ||
fetchBlockContent: 'fetchBlockContent', |
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.
It looks like the api calls to fetchV2LibraryContent
fetchV2LibraryContent
is not made or used atm, right?
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.
fetchV2LibraryContent
is used but fetchV2LibraryMetadata
is not. This was originally for fetching v1 library metadata (before I renamed some things to v2). V1 library metadata is needed to get v1 library version. I'll need to put this back in.
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.
We acttually need none of:
fetchV2LibraryContent
fetchV2LibraryContent
as we shouldn't be getting the content from the library.
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.
fetchV2LibraryContent
points to the /api/libraries/v2/${libraryId}/blocks/
endpoint. We want this for library blocks right? Do I just need to rename this to fetchV2LibraryBlocks
or is there something else I'm missing?
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'm realizing there is more to this than I may have let on. from a UI perspective.
There are three-ish cases we need to consider here:
- A user clicks edit on a library block which already has a source library_id then either:
- they view their selected blocks in the library.
- they click on a new library.
- A user clicks edit on a library block which does not already have a souce library_id.
In theory, in the first case, we need to show the library content block's children (not the library's) to be available for selection.
the last two cases are a conundrum. We know that child blocks of a library and child blocks of a library content block have different ids. Therefore, it is fruitless to attempt to do block selection in those cases. How can we fix this? I think we should do this as a fast-follow, but definitely this is a blocker to rollout.
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.
Just checking to see if I understand this correctly... Is the library content block's children the candidates of what might be an older version of the selected library?
Hey -- it looks great but a couple of bugs from manual testing:
|
const { getByTestId } = renderComponent({ ...props, blockFinished: false }); | ||
expect(getByTestId('librarycontenteditor-loadingspinner')).toBeTruthy(); | ||
}); | ||
it('Renders as expected once loaded', () => { |
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.
Also on this component level, we need to consider what should happen if the loading has finished but the block fails. What should be rendered? Should child components be rendered if there is no block to render? Should we throw an error that NewRelic will pick up? - If we do still render child components, will child components throw unwanted errors?
I would include a test for it with the desired behavior, and probably the desired behavior warrants some thinking about what should happen.
- That's my first-glance take, maybe you already dealt with everything in the hook. It wouldn't hurt having an additional test here anyway, so we can see if a future change inside the component breaks something.
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 we want whatever is the most simple here in terms of behavior @rayzhou-bit , but +1 to having a unit test here.
library_key: 'v1id', | ||
}, | ||
]; | ||
it('should fetch v2 and v1 libraries when block finishes loading', () => { |
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.
A blank line between it
statements is somehow just essential for me. At some point I just start seeing a wall of text otherwise.
@@ -0,0 +1,97 @@ | |||
import { StrictDict } from '../../../utils'; |
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.
A lot here seems not covered by tests. Probably warrants a requests.test.js
file.
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 the previous logic was "These are a wrapper/middleware so the unit testing would essentially be "did any of the inputs change" which doesn't improve confidence.
I'm not getting a |
We will be implementing static reference without a wrapper block. For example, instead of a course library_content block wrapping a library problem block, we will have a course problem block with a pointer to the upstream_block. Randomized content will still need a wrapper block, which may be the library_content block, or may be a new block. Thanks for all your work on this, folks. I'll pass this PR along to the team working on the new library-reference frontends so that they have the opportunity to reuse some of this work. |
This PR adds a new editor for the
library_content
block.Initial Editor with no libraries selected:
Editor with a V2 Library selected:
Editor with a V1 Library selected:
Editor with random library blocks mode selection:
Testing Instructions:
This edx-platform PR is required: openedx/edx-platform#33977
Waffle flag needed:
new_core_editors.use_new_library_content_editor
a. Selecting a library should show one of the two screens above depending on if the library is v1 or v2.
a. Mode: User can select 'Show a number of components to display at random from the library.' or 'Show the selected blocks of the library to all users.'
If user chooses the first option, they should see a number input for the number of blocks to show the learner (for both v1 and v2 libraries).
If user chooses the second option, they should see a table with all the blocks in the selected library.
b. Show Reset