Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 41 additions & 7 deletions frontends/mit-learn/src/pages/DashboardPage/SettingsPage.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,15 @@ const setupApis = ({
`${urls.userSubscription.check(subscriptionRequest)}`,
subscribeResponse,
)
const unsubscribeUrl = urls.userSubscription.delete(subscribeResponse[0]?.id)
setMockResponse.delete(unsubscribeUrl, subscribeResponse[0])
const unsubscribeUrls = []
for (const sub of subscribeResponse) {
const unsubscribeUrl = urls.userSubscription.delete(sub?.id)
unsubscribeUrls.push(unsubscribeUrl)
setMockResponse.delete(unsubscribeUrl, sub)
}

return {
unsubscribeUrl,
unsubscribeUrls,
}
}

Expand All @@ -46,21 +51,50 @@ describe("SettingsPage", () => {
})

test("Clicking 'Unfollow' removes the subscription", async () => {
const { unsubscribeUrl } = setupApis({
const { unsubscribeUrls } = setupApis({
isAuthenticated: true,
isSubscribed: true,
subscriptionRequest: {},
})
renderWithProviders(<SettingsPage />)

const followList = await screen.findByTestId("follow-list")
const unsubscribeButton = within(followList).getAllByText("Unfollow")[0]
await user.click(unsubscribeButton)
const unsubscribeLink = within(followList).getAllByText("Unfollow")[0]
await user.click(unsubscribeLink)

const unsubscribeButton = await screen.findByTestId("dialog-unfollow")
await user.click(unsubscribeButton)
expect(makeRequest).toHaveBeenCalledWith(
"delete",
unsubscribeUrl,
unsubscribeUrls[0],
undefined,
)
})

test("Clicking 'Unfollow All' removes all subscriptions", async () => {
const { unsubscribeUrls } = setupApis({
isAuthenticated: true,
isSubscribed: true,
subscriptionRequest: {},
})
renderWithProviders(<SettingsPage />)
const unsubscribeLink = await screen.findByTestId("unfollow-all")
await user.click(unsubscribeLink)

const unsubscribeButton = await screen.findByTestId("dialog-unfollow")
await user.click(unsubscribeButton)
for (const unsubUrl of unsubscribeUrls) {
expect(makeRequest).toHaveBeenCalledWith("delete", unsubUrl, undefined)
}
})
test("Unsubscribe from all is hidden if there are no subscriptions", async () => {
setupApis({
isAuthenticated: true,
isSubscribed: false,
subscriptionRequest: {},
})
renderWithProviders(<SettingsPage />)
const unfollowButton = screen.queryByText("Unfollow All")
expect(unfollowButton).not.toBeInTheDocument()
})
})
140 changes: 128 additions & 12 deletions frontends/mit-learn/src/pages/DashboardPage/SettingsPage.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,30 @@
import React from "react"
import { PlainList, Typography, Link, styled } from "ol-components"
import {
PlainList,
Typography,
Link,
styled,
Button,
Dialog,
DialogActions,
} from "ol-components"
import { useUserMe } from "api/hooks/user"
import {
useSearchSubscriptionDelete,
useSearchSubscriptionList,
} from "api/hooks/searchSubscription"

import * as NiceModal from "@ebay/nice-modal-react"
const SOURCE_LABEL_DISPLAY = {
topic: "Topic",
unit: "MIT Unit",
department: "MIT Academic Department",
saved_search: "Saved Search",
}

const Actions = styled(DialogActions)({
display: "flex",
"> *": { flex: 1 },
})
const FollowList = styled(PlainList)(({ theme }) => ({
borderRadius: "8px",
background: theme.custom.colors.white,
Expand All @@ -37,6 +49,29 @@ const SubTitleText = styled(Typography)(({ theme }) => ({
...theme.typography.body2,
}))

const SettingsHeader = styled.div(({ theme }) => ({
display: "flex",
alignItems: "center",
alignSelf: "stretch",
[theme.breakpoints.down("md")]: {
paddingBottom: "8px",
},
}))

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

const SettingsHeaderRight = styled.div(({ theme }) => ({
display: "flex",
[theme.breakpoints.down("md")]: {
display: "none",
},
}))

const ListItem = styled.li(({ theme }) => [
{
padding: "16px 32px",
Expand Down Expand Up @@ -83,22 +118,100 @@ const ListItemBody: React.FC<ListItemBodyProps> = ({
)
}

type UnfollowDialogProps = {
subscriptionIds?: number[]
subscriptionName?: string
}
const UnfollowDialog = NiceModal.create(
({ subscriptionIds, subscriptionName }: UnfollowDialogProps) => {
const modal = NiceModal.useModal()
const subscriptionDelete = useSearchSubscriptionDelete()
const unsubscribe = subscriptionDelete.mutate
return (
<Dialog
{...NiceModal.muiDialogV5(modal)}
title={subscriptionIds?.length === 1 ? "Unfollow" : "Unfollow All"}
actions={
<Actions>
<Button variant="secondary" onClick={() => modal.remove()}>
Cancel
</Button>

<Button
data-testid="dialog-unfollow"
onClick={async () =>
subscriptionIds?.map((subscriptionId) =>
unsubscribe(subscriptionId, {
onSuccess: () => {
modal.remove()
},
}),
)
}
>
{subscriptionIds?.length === 1
? "Yes, Unfollow"
: "Yes, Unfollow All"}
</Button>
</Actions>
}
>
{subscriptionIds?.length === 1 ? (
<>
Are you sure you want to unfollow <b>{subscriptionName}</b>?
</>
) : (
<>
Are you sure you want to <b>Unfollow All</b>? You will stop getting
emails for all topics, academic departments, and MIT units you are
following.
</>
)}
</Dialog>
)
},
)

const SettingsPage: React.FC = () => {
const { data: user } = useUserMe()
const subscriptionDelete = useSearchSubscriptionDelete()

const subscriptionList = useSearchSubscriptionList({
enabled: !!user?.is_authenticated,
})

const unsubscribe = subscriptionDelete.mutate
if (!user || subscriptionList.isLoading) return null

return (
<>
<TitleText>Following</TitleText>
<SubTitleText>
All topics, academic departments, and MIT units you are following.
</SubTitleText>
<SettingsHeader>
<SettingsHeaderLeft>
<TitleText>Following</TitleText>
<SubTitleText>
All topics, academic departments, and MIT units you are following.
</SubTitleText>
</SettingsHeaderLeft>
{subscriptionList?.data && subscriptionList?.data?.length > 1 ? (
<SettingsHeaderRight>
<Button
data-testid="unfollow-all"
variant="tertiary"
onClick={() =>
NiceModal.show(UnfollowDialog, {
subscriptionIds: subscriptionList?.data?.map(
(subscriptionItem) => subscriptionItem.id,
),
subscriptionName: "All",
id: "all",
})
}
>
Unfollow All
</Button>
</SettingsHeaderRight>
) : (
<></>
)}
</SettingsHeader>
<FollowList data-testid="follow-list">
{subscriptionList?.data?.map((subscriptionItem) => (
<ListItem key={subscriptionItem.id}>
Expand All @@ -111,10 +224,13 @@ const SettingsPage: React.FC = () => {
}
/>
<StyledLink
onClick={(event) => {
event.preventDefault()
unsubscribe(subscriptionItem.id)
}}
onClick={() =>
NiceModal.show(UnfollowDialog, {
subscriptionIds: [subscriptionItem.id],
subscriptionName: subscriptionItem.source_description,
id: subscriptionItem.id.toString(),
})
}
>
Unfollow
</StyledLink>
Expand Down
Loading