-
Notifications
You must be signed in to change notification settings - Fork 76
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: collections page [FC-0062] #1281
Changes from all commits
cdb633b
0f755d9
3f6a32e
ac6709d
bfd3e7d
5b2d734
6841d9d
626c06b
1b3754c
fd1aa85
347871b
0f4bad3
c8476d1
d510554
f9b2e52
5846b83
2ae6c98
26c0a9e
2c06446
3395c1e
2848746
d388335
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,54 +1,46 @@ | ||
import React, { useContext, useCallback } from 'react'; | ||
import { useParams } from 'react-router'; | ||
import { FormattedMessage } from '@edx/frontend-platform/i18n'; | ||
import type { MessageDescriptor } from 'react-intl'; | ||
import { | ||
Button, Stack, | ||
} from '@openedx/paragon'; | ||
import { Add } from '@openedx/paragon/icons'; | ||
import { ClearFiltersButton } from '../search-manager'; | ||
import messages from './messages'; | ||
import { LibraryContext } from './common/context'; | ||
import { useContentLibrary } from './data/apiHooks'; | ||
|
||
type NoSearchResultsProps = { | ||
searchType?: 'collection' | 'component', | ||
}; | ||
|
||
export const NoComponents = ({ searchType = 'component' }: NoSearchResultsProps) => { | ||
const { openAddContentSidebar, openCreateCollectionModal } = useContext(LibraryContext); | ||
export const NoComponents = ({ | ||
infoText = messages.noComponents, | ||
addBtnText = messages.addComponent, | ||
handleBtnClick, | ||
}: { | ||
infoText?: MessageDescriptor; | ||
addBtnText?: MessageDescriptor; | ||
handleBtnClick: () => void; | ||
}) => { | ||
const { libraryId } = useParams(); | ||
const { data: libraryData } = useContentLibrary(libraryId); | ||
const canEditLibrary = libraryData?.canEditLibrary ?? false; | ||
|
||
const handleOnClickButton = useCallback(() => { | ||
if (searchType === 'collection') { | ||
openCreateCollectionModal(); | ||
} else { | ||
openAddContentSidebar(); | ||
} | ||
}, [searchType]); | ||
|
||
return ( | ||
<Stack direction="horizontal" gap={3} className="mt-6 justify-content-center"> | ||
{searchType === 'collection' | ||
? <FormattedMessage {...messages.noCollections} /> | ||
: <FormattedMessage {...messages.noComponents} />} | ||
<FormattedMessage {...infoText} /> | ||
{canEditLibrary && ( | ||
<Button iconBefore={Add} onClick={handleOnClickButton}> | ||
{searchType === 'collection' | ||
? <FormattedMessage {...messages.addCollection} /> | ||
: <FormattedMessage {...messages.addComponent} />} | ||
<Button iconBefore={Add} onClick={handleBtnClick}> | ||
<FormattedMessage {...addBtnText} /> | ||
</Button> | ||
)} | ||
</Stack> | ||
); | ||
}; | ||
|
||
export const NoSearchResults = ({ searchType = 'component' }: NoSearchResultsProps) => ( | ||
export const NoSearchResults = ({ | ||
infoText = messages.noSearchResults, | ||
}: { | ||
infoText?: MessageDescriptor; | ||
}) => ( | ||
<Stack direction="horizontal" gap={3} className="my-6 justify-content-center"> | ||
{searchType === 'collection' | ||
? <FormattedMessage {...messages.noSearchResultsCollections} /> | ||
: <FormattedMessage {...messages.noSearchResults} />} | ||
<FormattedMessage {...infoText} /> | ||
<ClearFiltersButton variant="primary" size="md" /> | ||
</Stack> | ||
); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,3 +20,8 @@ | |
height: 100vh; | ||
overflow-y: auto; | ||
} | ||
|
||
// Reduce breadcrumb bottom margin | ||
ol.list-inline { | ||
margin-bottom: 0; | ||
} |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -13,6 +13,7 @@ | |||||
import { LibraryProvider } from './common/context'; | ||||||
import { CreateCollectionModal } from './create-collection'; | ||||||
import { invalidateComponentData } from './data/apiHooks'; | ||||||
import LibraryCollectionPage from './collections/LibraryCollectionPage'; | ||||||
|
||||||
const LibraryLayout = () => { | ||||||
const { libraryId } = useParams(); | ||||||
|
@@ -24,14 +25,20 @@ | |||||
} | ||||||
|
||||||
const navigate = useNavigate(); | ||||||
const goBack = React.useCallback(() => { | ||||||
// Go back to the library | ||||||
navigate(`/library/${libraryId}`); | ||||||
const goBack = React.useCallback((prevPath?: string) => { | ||||||
if (prevPath) { | ||||||
// Redirects back to the previous route like collection page or library page | ||||||
navigate(prevPath); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
If you want to go back, it's not necessary to pass For now I don't really care either way because what we really need to do is refactor this to display the editor as a modal, instead of navigating to a new URL for the editor and then going back. Obviously that will have to come in a dedicated PR though. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See my other comment. |
||||||
} else { | ||||||
// Go back to the library | ||||||
navigate(`/library/${libraryId}`); | ||||||
} | ||||||
}, []); | ||||||
const returnFunction = React.useCallback(() => { | ||||||
|
||||||
const returnFunction = React.useCallback((prevPath?: string) => { | ||||||
// When changes are cancelled, either onClose (goBack) or this returnFunction will be called. | ||||||
// When changes are saved, this returnFunction is called. | ||||||
goBack(); | ||||||
goBack(prevPath); | ||||||
return (args) => { | ||||||
if (args === undefined) { | ||||||
return; // Do nothing - the user cancelled the changes | ||||||
|
@@ -58,6 +65,10 @@ | |||||
</PageWrap> | ||||||
)} | ||||||
/> | ||||||
<Route | ||||||
path="collection/:collectionId" | ||||||
element={<LibraryCollectionPage />} | ||||||
/> | ||||||
<Route | ||||||
path="*" | ||||||
element={<LibraryAuthoringPage />} | ||||||
|
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.
See my other comment - I don't think it's necessary to pass
location.state?.from
here.Though it may actually solve @rpenido's concern about not going back to a different website.
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.
@bradenmacdonald Yes, my first solution was to use
navigate(-1)
but it goes back to other website if we directly use the URL and has no way of checking history before moving back, so I used this option of passing state where we can be sure that it goes back to libraries even if the user directly jumps to the url.