Skip to content

Commit 8970276

Browse files
authored
Merge pull request #1336 from isaacphysics/redesign/page/set-tests
Redesign Set Tests page
2 parents 8d9f338 + 3dc5e54 commit 8970276

File tree

12 files changed

+402
-205
lines changed

12 files changed

+402
-205
lines changed
Lines changed: 5 additions & 0 deletions
Loading
Lines changed: 5 additions & 0 deletions
Loading

src/app/components/elements/layout/SidebarLayout.tsx

Lines changed: 112 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React, { ChangeEvent, RefObject, useEffect, useRef, useState } from "react";
2-
import { Col, ColProps, RowProps, Input, Offcanvas, OffcanvasBody, OffcanvasHeader, Row } from "reactstrap";
2+
import { Col, ColProps, RowProps, Input, Offcanvas, OffcanvasBody, OffcanvasHeader, Row, DropdownItem, DropdownMenu, DropdownToggle, UncontrolledDropdown } from "reactstrap";
33
import partition from "lodash/partition";
44
import classNames from "classnames";
55
import { AssignmentDTO, ContentSummaryDTO, IsaacConceptPageDTO, QuestionDTO, QuizAttemptDTO, RegisteredUserDTO } from "../../../../IsaacApiTypes";
@@ -17,6 +17,7 @@ import { Spacer } from "../Spacer";
1717
import { StyledTabPicker } from "../inputs/StyledTabPicker";
1818
import { GroupSelector } from "../../pages/Groups";
1919
import { QuizRubricButton, SectionProgress } from "../quiz/QuizAttemptComponent";
20+
import { formatISODateOnly } from "../DateString";
2021

2122
export const SidebarLayout = (props: RowProps) => {
2223
const { className, ...rest } = props;
@@ -674,3 +675,113 @@ export const SignupSidebar = ({activeTab} : {activeTab: number}) => {
674675
<StyledTabPicker checkboxTitle={"Preferences"} checked={activeTab === 3} disabled={activeTab !== 3}/>
675676
</ContentSidebar>;
676677
};
678+
679+
interface SetQuizzesSidebarProps extends SidebarProps {
680+
titleFilter?: string;
681+
setTitleFilter: React.Dispatch<React.SetStateAction<string | undefined>>;
682+
};
683+
684+
export const SetQuizzesSidebar = (props: SetQuizzesSidebarProps) => {
685+
const { titleFilter, setTitleFilter } = props;
686+
const deviceSize = useDeviceSize();
687+
688+
return <ContentSidebar buttonTitle="Search & Filter">
689+
{above["lg"](deviceSize) && <div className="section-divider mt-5"/>}
690+
<h5>Search &amp; Filter</h5>
691+
<span className="quiz-filter-date-span mt-2">Title</span>
692+
<Input
693+
id="available-quizzes-title-filter" type="search"
694+
value={titleFilter} onChange={event => setTitleFilter(event.target.value)}
695+
placeholder="Search by title" aria-label="Search by title"
696+
/>
697+
</ContentSidebar>;
698+
};
699+
700+
interface ManageQuizzesSidebarProps extends SidebarProps {
701+
manageQuizzesTitleFilter: string;
702+
setManageQuizzesTitleFilter: React.Dispatch<React.SetStateAction<string>>;
703+
quizStartDate: Date | undefined;
704+
setQuizStartDate: React.Dispatch<React.SetStateAction<Date | undefined>>;
705+
quizSetDateFilterType: string;
706+
setQuizSetDateFilterType: React.Dispatch<React.SetStateAction<string>>;
707+
quizDueDate: Date | undefined;
708+
setQuizDueDate: React.Dispatch<React.SetStateAction<Date | undefined>>;
709+
quizDueDateFilterType: string;
710+
setQuizDueDateFilterType: React.Dispatch<React.SetStateAction<string>>;
711+
manageQuizzesGroupNameFilter: string;
712+
setManageQuizzesGroupNameFilter: React.Dispatch<React.SetStateAction<string>>;
713+
};
714+
715+
export const ManageQuizzesSidebar = (props: ManageQuizzesSidebarProps) => {
716+
const { manageQuizzesTitleFilter, setManageQuizzesTitleFilter, quizStartDate, setQuizStartDate,
717+
quizSetDateFilterType, setQuizSetDateFilterType, quizDueDate, setQuizDueDate, quizDueDateFilterType,
718+
setQuizDueDateFilterType, manageQuizzesGroupNameFilter, setManageQuizzesGroupNameFilter} = props;
719+
720+
const deviceSize = useDeviceSize();
721+
722+
const dateFilterTypeSelector = (dateFilterType: string, setDateFilterType: React.Dispatch<React.SetStateAction<string>>) => <UncontrolledDropdown>
723+
<DropdownToggle className="bg-transparent border-0 px-2" caret>{dateFilterType}</DropdownToggle>
724+
<DropdownMenu>
725+
<DropdownItem onClick={() => setDateFilterType('after')}>
726+
after
727+
</DropdownItem>
728+
<DropdownItem onClick={() => setDateFilterType('before')}>
729+
before
730+
</DropdownItem>
731+
<DropdownItem onClick={() => setDateFilterType('on')}>
732+
on
733+
</DropdownItem>
734+
</DropdownMenu>
735+
</UncontrolledDropdown>;
736+
737+
const titleFilterInput = <div className="my-2">
738+
<span className="quiz-filter-date-span">Title</span>
739+
<Input
740+
id="manage-quizzes-title-filter" type="search"
741+
value={manageQuizzesTitleFilter} onChange={event => setManageQuizzesTitleFilter(event.target.value)}
742+
placeholder="Search by title" aria-label="Search by title"
743+
/>
744+
</div>;
745+
746+
const groupFilterInput = <div className="my-2">
747+
<span className="quiz-filter-date-span">Group</span>
748+
<Input
749+
id="manage-quizzes-group-name-filter" type="search"
750+
value={manageQuizzesGroupNameFilter} onChange={event => setManageQuizzesGroupNameFilter(event.target.value)}
751+
placeholder="Search by group" aria-label="Search by group"
752+
/>
753+
</div>;
754+
755+
const setDateFilterInput = <div className="my-2">
756+
<div className="d-flex align-items-center">
757+
<span className="quiz-filter-date-span">Starting</span>
758+
{dateFilterTypeSelector(quizSetDateFilterType, setQuizSetDateFilterType)}
759+
</div>
760+
<Input
761+
id="manage-quizzes-set-date-filter" type="date" className="quiz-filter-date-input"
762+
value={quizStartDate && !isNaN(quizStartDate.valueOf()) ? formatISODateOnly(quizStartDate) : undefined} onChange={event => setQuizStartDate(new Date(event.target.value))}
763+
placeholder="Filter by set date" aria-label="Filter by set date"
764+
/>
765+
</div>;
766+
767+
const dueDateFilterInput = <div className="my-2">
768+
<div className="d-flex align-items-center">
769+
<span className="quiz-filter-date-span">Due</span>
770+
{dateFilterTypeSelector(quizDueDateFilterType, setQuizDueDateFilterType)}
771+
</div>
772+
<Input
773+
id="manage-quizzes-due-date-filter" type="date" className="quiz-filter-date-input"
774+
value={quizDueDate && !isNaN(quizDueDate.valueOf()) ? formatISODateOnly(quizDueDate) : undefined} onChange={event => setQuizDueDate(new Date(event.target.value))}
775+
placeholder="Filter by due date" aria-label="Filter by due date"
776+
/>
777+
</div>;
778+
779+
return <ContentSidebar buttonTitle="Search & Filter">
780+
{above["lg"](deviceSize) && <div className="section-divider mt-5"/>}
781+
<h5>Search & Filter</h5>
782+
{titleFilterInput}
783+
{groupFilterInput}
784+
{setDateFilterInput}
785+
{dueDateFilterInput}
786+
</ContentSidebar>;
787+
};

src/app/components/elements/list-groups/ListView.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ export const QuizListViewItem = ({item, isQuizSetter, ...rest}: {item: QuizSumma
9595
</AffixButton>;
9696

9797
return <AbstractListViewItem
98-
icon={{type: "hex", icon: "list-icon-lessons", size: "sm"}}
98+
icon={{type: "hex", icon: "list-icon-quiz", size: "sm"}}
9999
title={item.title ?? ""}
100100
subject={itemSubject}
101101
previewQuizUrl={`/test/preview/${item.id}`}

0 commit comments

Comments
 (0)