Skip to content

Commit

Permalink
user list UI updates (#1348)
Browse files Browse the repository at this point in the history
* move create new list button to under the list of lists, remove the grid from the header

* move UserListCardTemplate to ol-components and rename it to UserListCardCondensed

* use routes instead of location hash for dashboard urls

* set up userlist detail route and list card href, remove standalone userlist page

* refactor active tab logic to match new route strategy

* fix typography import path on userlistcardcondensed

* default to dashboard home if tabValue ends up being something unexpected

* use proper syntax for checking the tabValue...

* get tests functioning again

* fix accessible title in UserListCardCondensed

* commit broken test

* make UserListCardCondensed the default export from that component

* fix link clicking test

* restyle dashboard user list view component

* Add button to go back to My Lists

* fix testing issues

* fix rebase issues with new settings tab

* hide UserListCardCondensed icon on mobile

* create new list button should be 100% width on mobile

* get rid of profile type check
  • Loading branch information
gumaerc authored Aug 5, 2024
1 parent 64cdc75 commit d08b2ae
Show file tree
Hide file tree
Showing 19 changed files with 559 additions and 607 deletions.
15 changes: 10 additions & 5 deletions frontends/mit-open/src/common/urls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,6 @@ export const LEARNINGPATH_LISTING = "/learningpaths/"
export const LEARNINGPATH_VIEW = "/learningpaths/:id"
export const learningPathsView = (id: number) =>
generatePath(LEARNINGPATH_VIEW, { id: String(id) })
export const USERLIST_LISTING = "/userlists/"
export const USERLIST_VIEW = "/userlists/:id"
export const userListView = (id: number) =>
generatePath(USERLIST_VIEW, { id: String(id) })
export const PROGRAMLETTER_VIEW = "/program_letter/:id/view/"
export const programLetterView = (id: string) =>
generatePath(PROGRAMLETTER_VIEW, { id: String(id) })
Expand Down Expand Up @@ -70,7 +66,16 @@ export const login = ({
return `${LOGIN}?next=${next}`
}

export const DASHBOARD = "/dashboard/"
export const DASHBOARD_HOME = "/dashboard/"

export const MY_LISTS = "/dashboard/my-lists/"
export const USERLIST_VIEW = "/dashboard/my-lists/:id"
export const userListView = (id: number) =>
generatePath(USERLIST_VIEW, { id: String(id) })

export const PROFILE = "/dashboard/profile/"

export const SETTINGS = "/dashboard/settings/"

export const SEARCH = "/search/"

Expand Down
2 changes: 1 addition & 1 deletion frontends/mit-open/src/page-components/Header/UserMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ const UserMenu: React.FC<UserMenuProps> = ({ variant }) => {
label: "Dashboard",
key: "dashboard",
allow: !!user?.is_authenticated,
href: urls.DASHBOARD,
href: urls.DASHBOARD_HOME,
},
{
label: "Learning Paths",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,11 @@
import React from "react"
import { Grid, Button, Typography, styled } from "ol-components"
import { RiPencilFill, RiArrowUpDownLine } from "@remixicon/react"
import { Grid, Button, Typography, styled, Link } from "ol-components"
import { RiArrowLeftLine, RiArrowUpDownLine } from "@remixicon/react"
import { useToggle, pluralize } from "ol-utilities"
import { GridColumn, GridContainer } from "@/components/GridLayout/GridLayout"
import ItemsListing from "./ItemsListing"
import type { LearningResourceListItem } from "./ItemsListing"

const Container = styled(GridContainer)`
margin-top: 30px;
margin-bottom: 100px;
`

const TitleContainer = styled(Grid)`
margin-top: 10px;
margin-bottom: 20px;
`
import { MY_LISTS } from "@/common/urls"

type OnEdit = () => void
type ListData = {
Expand All @@ -35,6 +26,48 @@ type ItemsListingComponentProps = {
condensed?: boolean
}

const HeaderText = styled.div(({ theme }) => ({
h3: {
...theme.typography.h3,
[theme.breakpoints.down("sm")]: {
marginBottom: "24px",
...theme.typography.h5,
},
},
}))

const DescriptionText = styled(Typography)(({ theme }) => ({
color: theme.custom.colors.silverGrayDark,
...theme.typography.body1,
[theme.breakpoints.down("sm")]: {
display: "none",
},
}))

const HeaderGrid = styled(Grid)(({ theme }) => ({
gap: "24px",
[theme.breakpoints.down("sm")]: {
width: "100%",
},
}))

const EditButton = styled(Button)(({ theme }) => ({
[theme.breakpoints.down("sm")]: {
width: "100%",
},
}))

const ReorderGrid = styled(Grid)(({ theme }) => ({
[theme.breakpoints.down("sm")]: {
display: "none",
},
}))

const CountText = styled(Typography)(({ theme }) => ({
color: theme.custom.colors.silverGrayDark,
...theme.typography.buttonSmall,
}))

const ItemsListingComponent: React.FC<ItemsListingComponentProps> = ({
listType,
list,
Expand All @@ -51,54 +84,71 @@ const ItemsListingComponent: React.FC<ItemsListingComponentProps> = ({
const count = list?.item_count

return (
<Container>
<GridContainer>
<GridColumn variant="single-full">
<Grid container>
<TitleContainer item xs={12}>
<Typography variant="h3" component="h1">
{list?.title}
</Typography>
{list?.description && <p>{list.description}</p>}
</TitleContainer>
<Grid
item
xs={6}
container
alignItems="center"
justifyContent="space-between"
marginBottom="24px"
>
{showSort && !!items.length && (
<Button
variant="text"
disabled={count === 0}
startIcon={isSorting ? undefined : <RiArrowUpDownLine />}
onClick={toggleIsSorting.toggle}
>
{isSorting ? "Done ordering" : "Reorder"}
</Button>
)}
{count !== undefined && count > 0
? `${count} ${pluralize("item", count)}`
: null}
<Grid item>
<Link href={MY_LISTS}>
<Button variant="tertiary" startIcon={<RiArrowLeftLine />}>
My Lists
</Button>
</Link>
</Grid>
</Grid>
<Grid
item
xs={6}
container
justifyContent="flex-end"
alignItems="center"
display="flex"
justifyContent="space-between"
marginBottom="24px"
>
{canEdit ? (
<Button
variant="text"
startIcon={<RiPencilFill />}
onClick={handleEdit}
>
Edit
</Button>
) : null}
<HeaderGrid item>
<HeaderText>
<Typography component="h3">{list?.title}</Typography>
</HeaderText>
{list?.description && (
<DescriptionText>{list.description}</DescriptionText>
)}
</HeaderGrid>
<HeaderGrid item alignSelf="flex-start">
{canEdit ? (
<EditButton variant="primary" onClick={handleEdit}>
Edit List
</EditButton>
) : null}
</HeaderGrid>
</Grid>
<ReorderGrid
item
container
alignItems="center"
justifyContent="space-between"
>
<Grid item>
{showSort && !!items.length && (
<Button
variant="text"
disabled={count === 0}
startIcon={isSorting ? undefined : <RiArrowUpDownLine />}
onClick={toggleIsSorting.toggle}
>
{isSorting ? "Done ordering" : "Reorder"}
</Button>
)}
</Grid>
<Grid item>
{count !== undefined && count > 0 ? (
<CountText>{`${count} ${pluralize("item", count)}`}</CountText>
) : null}
</Grid>
</ReorderGrid>
</Grid>
<ItemsListing
listType={listType}
Expand All @@ -110,7 +160,7 @@ const ItemsListingComponent: React.FC<ItemsListingComponentProps> = ({
condensed={condensed}
/>
</GridColumn>
</Container>
</GridContainer>
)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
import React from "react"
import { render, screen } from "@testing-library/react"
import UserListCardTemplate from "./UserListCardTemplate"
import { screen } from "@testing-library/react"
import UserListCardCondensed from "./UserListCardCondensed"
import * as factories from "api/test-utils/factories"
import { makeImgConfig } from "ol-utilities/test-utils/factories"
import { userListView } from "@/common/urls"
import { renderWithProviders } from "@/test-utils"

const userListFactory = factories.userLists

describe("UserListCard", () => {
it("renders title and cover image", () => {
const userList = userListFactory.userList()
const imgConfig = makeImgConfig()
render(
<UserListCardTemplate
variant="column"
renderWithProviders(
<UserListCardCondensed
href={userListView(userList.id)}
userList={userList}
imgConfig={imgConfig}
/>,
)
const heading = screen.getByRole("heading", { name: userList.title })
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import React from "react"
import { UserList } from "api"
import { pluralize } from "ol-utilities"
import { RiListCheck3 } from "@remixicon/react"
import { ListCardCondensed, styled, theme, Typography } from "ol-components"

const StyledCard = styled(ListCardCondensed)({
display: "flex",
alignItems: "center",
padding: "16px",
margin: "0",
gap: "16px",
width: "100%",
})

const TextContainer = styled.div({
display: "flex",
flexDirection: "column",
alignItems: "flex-start",
gap: "8px",
flex: "1 0 0",
})

const ItemsText = styled(Typography)(({ theme }) => ({
color: theme.custom.colors.silverGrayDark,
}))

const IconContainer = styled.div(({ theme }) => ({
display: "flex",
alignItems: "center",
gap: "8px",
borderRadius: "4px",
color: theme.custom.colors.silverGrayDark,
background: theme.custom.colors.lightGray1,
[theme.breakpoints.down("sm")]: {
display: "none",
},
}))

type UserListCardCondensedProps<U extends UserList = UserList> = {
userList: U
href?: string
className?: string
}

const UserListCardCondensed = <U extends UserList>({
userList,
href,
className,
}: UserListCardCondensedProps<U>) => {
return (
<StyledCard href={href} className={className}>
<ListCardCondensed.Content>
<TextContainer>
<Typography
variant="subtitle1"
color={theme.custom.colors.darkGray2}
component="h1"
>
{userList.title}
</Typography>
<ItemsText variant="body3">
{userList.item_count} {pluralize("item", userList.item_count)}
</ItemsText>
</TextContainer>
<IconContainer>
<RiListCheck3 size="48" />
</IconContainer>
</ListCardCondensed.Content>
</StyledCard>
)
}

export default UserListCardCondensed
export type { UserListCardCondensedProps }

This file was deleted.

Loading

0 comments on commit d08b2ae

Please sign in to comment.