From 81d75c92315fd030a5b97f586a8e531b160535f9 Mon Sep 17 00:00:00 2001 From: Alex Lewin Date: Wed, 5 Mar 2025 16:23:47 +0000 Subject: [PATCH 01/12] Move quiz filters to sidebar (phy) --- .../elements/layout/SidebarLayout.tsx | 27 ++- .../components/pages/quizzes/MyQuizzes.tsx | 170 +++++++++--------- 2 files changed, 115 insertions(+), 82 deletions(-) diff --git a/src/app/components/elements/layout/SidebarLayout.tsx b/src/app/components/elements/layout/SidebarLayout.tsx index 3644539eb8..7e10b5626b 100644 --- a/src/app/components/elements/layout/SidebarLayout.tsx +++ b/src/app/components/elements/layout/SidebarLayout.tsx @@ -3,7 +3,7 @@ import { Col, ColProps, RowProps, Input, Offcanvas, OffcanvasBody, OffcanvasHead import partition from "lodash/partition"; import classNames from "classnames"; import { AssignmentDTO, ContentSummaryDTO, IsaacConceptPageDTO, QuestionDTO, QuizAttemptDTO, RegisteredUserDTO } from "../../../../IsaacApiTypes"; -import { above, ACCOUNT_TAB, ACCOUNT_TABS, AUDIENCE_DISPLAY_FIELDS, below, BOARD_ORDER_NAMES, BoardCompletions, BoardCreators, BoardLimit, BoardSubjects, BoardViews, confirmThen, determineAudienceViews, filterAssignmentsByStatus, filterAudienceViewsByProperties, getDistinctAssignmentGroups, getDistinctAssignmentSetters, getThemeFromContextAndTags, HUMAN_STAGES, ifKeyIsEnter, isAda, isDefined, siteSpecific, useDeviceSize } from "../../../services"; +import { above, ACCOUNT_TAB, ACCOUNT_TABS, AUDIENCE_DISPLAY_FIELDS, below, BOARD_ORDER_NAMES, BoardCompletions, BoardCreators, BoardLimit, BoardSubjects, BoardViews, confirmThen, determineAudienceViews, filterAssignmentsByStatus, filterAudienceViewsByProperties, getDistinctAssignmentGroups, getDistinctAssignmentSetters, getThemeFromContextAndTags, HUMAN_STAGES, ifKeyIsEnter, isAda, isDefined, QuizStatus, siteSpecific, useDeviceSize } from "../../../services"; import { StageAndDifficultySummaryIcons } from "../StageAndDifficultySummaryIcons"; import { selectors, useAppSelector } from "../../../state"; import { Link, useHistory } from "react-router-dom"; @@ -16,6 +16,7 @@ import { Spacer } from "../Spacer"; import { StyledTabPicker } from "../inputs/StyledTabPicker"; import { GroupSelector } from "../../pages/Groups"; import { QuizRubricButton, SectionProgress } from "../quiz/QuizAttemptComponent"; +import { DisplayModeToggle, PastTestsToggle, QuizFilters } from "../../pages/quizzes/MyQuizzes"; export const SidebarLayout = (props: RowProps) => { const { className, ...rest } = props; @@ -633,3 +634,27 @@ export const SignupSidebar = ({activeTab} : {activeTab: number}) => { ; }; + +interface MyQuizzesSidebarProps extends SidebarProps { + showCompleted: boolean; + setShowCompleted: (show: boolean) => void; + setQuizCreator: (creator: string) => void; + setQuizTitleFilter: (title: string) => void; + quizStatuses: QuizStatus[]; + setQuizStatuses: React.Dispatch>; + displayMode: "table" | "cards"; + setDisplayMode: React.Dispatch>; +}; + +export const MyQuizzesSidebar = (props: MyQuizzesSidebarProps) => { + const { showCompleted, setShowCompleted, setQuizCreator, setQuizTitleFilter, quizStatuses, setQuizStatuses, displayMode, setDisplayMode } = props; + return +
+
Display mode
+ +
+
Search & Filter
+ + + ; +}; diff --git a/src/app/components/pages/quizzes/MyQuizzes.tsx b/src/app/components/pages/quizzes/MyQuizzes.tsx index 9a2986238b..17dd4d3a54 100644 --- a/src/app/components/pages/quizzes/MyQuizzes.tsx +++ b/src/app/components/pages/quizzes/MyQuizzes.tsx @@ -16,6 +16,7 @@ import { convertAttemptToQuiz, DisplayableQuiz, extractTeacherName, + isAda, isPhy, isTutorOrAbove, QuizStatus, @@ -33,10 +34,10 @@ import orderBy from "lodash/orderBy"; import classNames from "classnames"; import StyledToggle from "../../elements/inputs/StyledToggle"; import { TrLink } from "../../elements/tables/TableLinks"; -import { StyledDropdown } from "../../elements/inputs/DropdownInput"; import { StyledSelect } from "../../elements/inputs/StyledSelect"; import { CollapsibleContainer } from "../../elements/CollapsibleContainer"; import { FilterCount } from "../../elements/svg/FilterCount"; +import { MainContent, MyQuizzesSidebar, SidebarLayout } from "../../elements/layout/SidebarLayout"; export interface QuizzesPageProps extends RouteComponentProps { user: RegisteredUserDTO; @@ -212,7 +213,7 @@ interface QuizFiltersProps { showFilters: boolean; } -const QuizFilters = ({setShowCompleted, setQuizTitleFilter, setQuizCreator, quizStatuses, setQuizStatuses, showFilters}: QuizFiltersProps) => { +export const QuizFilters = ({setShowCompleted, setQuizTitleFilter, setQuizCreator, quizStatuses, setQuizStatuses, showFilters}: QuizFiltersProps) => { return @@ -248,6 +249,38 @@ const QuizFilters = ({setShowCompleted, setQuizTitleFilter, setQuizCreator, quiz ; }; + +export const DisplayModeToggle = ({displayMode, setDisplayMode}: {displayMode: "table" | "cards", setDisplayMode: React.Dispatch>}) => { + return
+ Display in +
+ setDisplayMode(d => d === "table" ? "cards" : "table")} + /> +
+
; +}; + +export const PastTestsToggle = ({showCompleted, setShowCompleted, setQuizStatuses}: {showCompleted: boolean, setShowCompleted: (show: boolean) => void, setQuizStatuses: React.Dispatch>}) => { + return
+ Past tests +
+ { + const target = !showCompleted; + setShowCompleted(target); + setQuizStatuses(s => target ? [...s, QuizStatus.Complete, QuizStatus.Overdue] : s.filter(status => ![QuizStatus.Complete, QuizStatus.Overdue].includes(status))); + }} + /> +
+
; +}; const MyQuizzesPageComponent = ({user}: QuizzesPageProps) => { @@ -315,43 +348,10 @@ const MyQuizzesPageComponent = ({user}: QuizzesPageProps) => { } }, [anchorMap]); - // TODO: revert to StyledToggle when the component is more widely used (post-redesign) - - // const displayModeToggle =
- // Display mode - // setDisplayMode(d => d === "table" ? "cards" : "table")} - // /> - const displayModeToggle =
- Display in - setDisplayMode(d => d === "table" ? "cards" : "table")}> - - - -
; - - const pastTestsToggle =
- Past tests -
- { - const target = !showCompleted; - setShowCompleted(target); - setQuizStatuses(s => target ? [...s, QuizStatus.Complete, QuizStatus.Overdue] : s.filter(status => ![QuizStatus.Complete, QuizStatus.Overdue].includes(status))); - }} - /> -
-
; - // +!! converts a string to 0 if null or empty and 1 otherwise const filterCount = +!!quizTitleFilter + +!!quizCreatorFilter + quizStatusFilter.length; + // Ada-only const filtersToggle =