Skip to content
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: simplify library home [FC-0062] #1443

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

DanielVZ96
Copy link
Contributor

@DanielVZ96 DanielVZ96 commented Oct 27, 2024

Description

Simplifies the library UI/UX and code by using the same grid for the home, components and collections tab, also unifying the query used for collections and the react component used to display library content grids.

image

Supporting Information

Implements: #1230
Private Ref: FAL-3918

Testing Instructions

  • Create a new Library

  • Inside the new library create a new component and collection.

    • Verify they both display in the "All Content" tab.
    • Verify that only the component appears in the "Components" tab
    • Verify that only the collection appears in the "Collections" tab
    • Verify that you can filter by the component type correctly
  • Now add dozens of components by copy and pasting them

    • Verify that after a certain number if you refresh the page they are loaded in an infinite scroll
    • Verify that you can sort them and filter them correctly.
  • Open the collection and verify you can both add new components and select components from the library by clicking "New" and "Existing Library Content"
    image

  • Click on the search modal on top and then try to find XBlocks that are used in courses (we have to test this because the search results typing had to be changed a bit, but there should be no issue here).
    image

  • Now navigate to http://apps.local.openedx.io:2001/authoring/library/component-picker and verify components and collections render correctly.

@openedx-webhooks openedx-webhooks added the open-source-contribution PR author is not from Axim or 2U label Oct 27, 2024
@openedx-webhooks
Copy link

openedx-webhooks commented Oct 27, 2024

Thanks for the pull request, @DanielVZ96!

What's next?

Please work through the following steps to get your changes ready for engineering review:

🔘 Get product approval

If you haven't already, check this list to see if your contribution needs to go through the product review process.

  • If it does, you'll need to submit a product proposal for your contribution, and have it reviewed by the Product Working Group.
    • This process (including the steps you'll need to take) is documented here.
  • If it doesn't, simply proceed with the next step.

🔘 Provide context

To help your reviewers and other members of the community understand the purpose and larger context of your changes, feel free to add as much of the following information to the PR description as you can:

  • Dependencies

    This PR must be merged before / after / at the same time as ...

  • Blockers

    This PR is waiting for OEP-1234 to be accepted.

  • Timeline information

    This PR must be merged by XX date because ...

  • Partner information

    This is for a course on edx.org.

  • Supporting documentation
  • Relevant Open edX discussion forum threads

🔘 Get a green build

If one or more checks are failing, continue working on your changes until this is no longer the case and your build turns green.

🔘 Let us know that your PR is ready for review:

Who will review my changes?

This repository is currently maintained by @openedx/2u-tnl. Tag them in a comment and let them know that your changes are ready for review.

Where can I find more information?

If you'd like to get more details on all aspects of the review process for open source pull requests (OSPRs), check out the following resources:

When can I expect my changes to be merged?

Our goal is to get community contributions seen and reviewed as efficiently as possible.

However, the amount of time that it takes to review and merge a PR can vary significantly based on factors such as:

  • The size and impact of the changes that it introduces
  • The need for product review
  • Maintenance status of the parent repository

💡 As a result it may take up to several weeks or months to complete a review and merge your PR.

@DanielVZ96 DanielVZ96 force-pushed the dvz/simplify-home branch 3 times, most recently from 3ee85ce to 2cef883 Compare October 27, 2024 19:58
@bradenmacdonald bradenmacdonald changed the title feat: simplify library home feat: simplify library home [FC-0062] Oct 29, 2024
@bradenmacdonald bradenmacdonald added the FC Relates to an Axim Funded Contribution project label Oct 29, 2024
@@ -0,0 +1,86 @@
import { useEffect } from 'react';
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replaced LibraryHome, LibraryCollections and Library Components with this single file that does the same based on the content prop.

Copy link

codecov bot commented Nov 3, 2024

Codecov Report

Attention: Patch coverage is 97.91667% with 1 line in your changes missing coverage. Please review.

Project coverage is 93.23%. Comparing base (949e4ac) to head (9165f01).
Report is 4 commits behind head on master.

Files with missing lines Patch % Lines
src/search-manager/data/api.ts 80.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1443      +/-   ##
==========================================
- Coverage   93.27%   93.23%   -0.04%     
==========================================
  Files        1052     1048       -4     
  Lines       20462    20401      -61     
  Branches     4298     4286      -12     
==========================================
- Hits        19086    19021      -65     
- Misses       1316     1320       +4     
  Partials       60       60              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@DanielVZ96 DanielVZ96 marked this pull request as ready for review November 3, 2024 05:59
@DanielVZ96 DanielVZ96 requested a review from a team as a code owner November 3, 2024 05:59
@DanielVZ96
Copy link
Contributor Author

DanielVZ96 commented Nov 3, 2024

Coverage went down due to removed previously covered code.

Copy link
Contributor

@bradenmacdonald bradenmacdonald left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, this looks great! I only tested it briefly but it seems to be working well. Will let @rpenido test it fully.

Comment on lines +362 to +363
// ['', 'type = "course_block"', 'context_key = "course-v1:org+test+123"']
return (requestedFilter?.length === 3);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the first empty string '' necessary?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure why it is there. It was like that before but I can check.

Copy link
Contributor

@rpenido rpenido Nov 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The first '' is probably from the empty search query.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not a big deal. I think it's an artifact of this:

// To filter normal block types and problem types as 'OR' query
const typeFilters = [[
...blockTypesFilterFormatted,
...problemTypesFilterFormatted,
].flat()];

If there are no filters set, this still adds an empty array [] to the filters list. It doesn't cause any problems.

*/

type LibraryContentProps = {
content: string;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
content: string;
content: TabList;

Can you give this a more specific type than string? Maybe use the same enum we already have defined, but rename it from TabList to ContentType ?

Or even better, get rid of the content prop and just add an emptyState: React.ReactNode component. Then, below, you can do something like this:

  if (totalHits === 0) {
    if (props.emptyState) {
      return <>{props.emptyState}</>;
    }
    return isFiltered ? <NoSearchResults /> : <NoComponents handleBtnClick={openAddContentSidebar} />;
  }

@@ -558,7 +526,7 @@ export async function fetchTagsThatMatchKeyword({
* Fetch single document by its id
*/
/* istanbul ignore next */
export async function fetchDocumentById({ client, indexName, id } : {
export async function fetchDocumentById({ client, indexName, id }: {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I think this fetchDocumentById function as well as useGetSingleDocument are unused. You can just remove them while you're at it if you want.

Copy link
Contributor

@rpenido rpenido left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work here, @DanielVZ96!
This is a really big change, and you handled it graciously!

There is a small bug with the Manage Collections feature. It is an easy fix.
I left some suggestions on the review, but feel free to skip the ones you don't think are relevant.

Also, if you have more time, could you take a look at the LibraryAuthoringPage and the LibraryCollectionPage components?
They are a level above the new LibraryContent component and share a lot of code.
We can also merge them, so if we implement a new filter or add the Units tab, we could do it in one place. If you think it is a complicated merge, we can do this on another task.

@@ -116,7 +116,7 @@ const AddToCollectionsDrawer = ({ usageKey, collections, onClose }: CollectionsD
components: { limit: 0 },
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Manage Collections feature is not showing any hits.
image

Removing the line below fix it:

Suggested change
components: { limit: 0 },

Comment on lines -189 to -191
if (overrideQueries?.collections) {
newQueries[2] = { ...overrideQueries.collections, indexUid: queries[2].indexUid };
}
Copy link
Contributor

@rpenido rpenido Nov 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also remove the collections property from the OverrideQueries type.

Edit: Maybe rename the components as the query brings components and collections.

@@ -28,7 +28,7 @@ const SearchResults: React.FC<Record<never, never>> = () => {

return (
<>
{hits.map((hit) => <SearchResult key={hit.id} hit={hit} />)}
{hits.filter(hit => hit.type !== 'collection').map((hit) => <SearchResult key={hit.id} hit={hit as ContentHit} />)}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we make the types more specific (bellow diff) we can do better type inference

diff --git a/src/search-manager/data/api.ts b/src/search-manager/data/api.ts
index 8d1679ec..7f8c8a21 100644
--- a/src/search-manager/data/api.ts
+++ b/src/search-manager/data/api.ts
@@ -119,6 +119,7 @@ interface BaseContentHit {
  * Defined in edx-platform/openedx/core/djangoapps/content/search/documents.py
  */
 export interface ContentHit extends BaseContentHit {
+  type: 'course_block' | 'library_block';
   /** The block_type part of the usage key. What type of XBlock this is. */
   blockType: string;
   /**
@@ -149,6 +150,7 @@ export interface ContentPublishedData {
  * Defined in edx-platform/openedx/core/djangoapps/content/search/documents.py
  */
 export interface CollectionHit extends BaseContentHit {
+  type: 'collection';
   description: string;
   numChildren?: number;
 }
Suggested change
{hits.filter(hit => hit.type !== 'collection').map((hit) => <SearchResult key={hit.id} hit={hit as ContentHit} />)}
{hits.filter((hit): hit is ContentHit => hit.type !== 'collection').map(
(hit) => <SearchResult key={hit.id} hit={hit} />,
)}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!!

Comment on lines 70 to 80
contentHit.type === 'collection' ? (
<CollectionCard
key={contentHit.id}
collectionHit={contentHit as CollectionHit}
/>
) : (
<ComponentCard
key={contentHit.id}
contentHit={contentHit as ContentHit}
/>
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, with the change above, the contentHit.type === 'collection' becomes a type guard

Suggested change
contentHit.type === 'collection' ? (
<CollectionCard
key={contentHit.id}
collectionHit={contentHit as CollectionHit}
/>
) : (
<ComponentCard
key={contentHit.id}
contentHit={contentHit as ContentHit}
/>
)
contentHit.type === 'collection' ? (
<CollectionCard
key={contentHit.id}
collectionHit={contentHit}
/>
) : (
<ComponentCard
key={contentHit.id}
contentHit={contentHit}
/>
)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not related to this change, but there are a lot of places where we are breaking the feature boundaries and using:

import { SomeComponent } from './components/SomeComponent'
import { AnotherComponent } from './components/AnotherComponent'

Instead of

import { SomeComponent, AnotherComponent } from './components'

Could you check if this is easy to fix?
If not, just remove this index.ts and directly import the ComponentMenu when used.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a policy on this? Personally I always use the first approach because it's less likely to cause circular dependencies and it's slightly faster during code analysis and builds.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have this: https://github.com/openedx/frontend-template-application/blob/master/docs/decisions/0002-feature-based-application-organization.rst
But I'm not sure that our "features" are decoupled enough to follow it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
FC Relates to an Axim Funded Contribution project open-source-contribution PR author is not from Axim or 2U
Projects
Status: Waiting on Author
Development

Successfully merging this pull request may close these issues.

4 participants