diff --git a/src/app/components/content/IsaacNumericQuestion.tsx b/src/app/components/content/IsaacNumericQuestion.tsx index db1078d3d0..5c14af473b 100644 --- a/src/app/components/content/IsaacNumericQuestion.tsx +++ b/src/app/components/content/IsaacNumericQuestion.tsx @@ -14,7 +14,7 @@ import { Row, UncontrolledTooltip } from "reactstrap"; -import {above, isAda, isPhy, siteSpecific, useCurrentQuestionAttempt, useDeviceSize} from "../../services"; +import {above, below, isAda, isPhy, siteSpecific, useCurrentQuestionAttempt, useDeviceSize} from "../../services"; import {IsaacQuestionProps} from "../../../IsaacAppTypes"; import {Markup} from "../elements/markup"; import classNames from "classnames"; @@ -107,7 +107,7 @@ const IsaacNumericQuestion = ({doc, questionId, validationResponse, readonly}: I - +
Value @@ -129,7 +129,7 @@ const IsaacNumericQuestion = ({doc, questionId, validationResponse, readonly}: I {setIsOpen(!isOpen);}}> @@ -155,15 +155,13 @@ const IsaacNumericQuestion = ({doc, questionId, validationResponse, readonly}: I
} - {!readonly && isPhy && above['md'](deviceSize) && <> -
- -
+ {!readonly && isPhy && above['md'](deviceSize) && + {tooltip} - } + }
diff --git a/src/app/components/elements/Book.tsx b/src/app/components/elements/Book.tsx index 83c40ef7b1..403d9dc826 100644 --- a/src/app/components/elements/Book.tsx +++ b/src/app/components/elements/Book.tsx @@ -1,17 +1,19 @@ -import React, { useEffect, useState } from "react"; -import { Container } from "reactstrap"; -import { BookSidebar, MainContent, SidebarLayout } from "./layout/SidebarLayout"; -import { Markup } from "./markup"; -import { TitleAndBreadcrumb } from "./TitleAndBreadcrumb"; -import { useContextFromContentObjectTags } from "../../services"; -import { useHistory } from "react-router"; -import { useGetBookDetailPageQuery, useGetBookIndexPageQuery } from "../../state/slices/api/booksApi"; -import { BookPage } from "./BookPage"; -import { skipToken } from "@reduxjs/toolkit/query"; -import { ShowLoadingQuery } from "../handlers/ShowLoadingQuery"; -import { TeacherNotes } from "./TeacherNotes"; -import { EditContentButton } from "./EditContentButton"; - +import React, {useEffect, useState} from "react"; +import {Container} from "reactstrap"; +import {BookSidebar, MainContent, SidebarLayout} from "./layout/SidebarLayout"; +import {Markup} from "./markup"; +import {TitleAndBreadcrumb} from "./TitleAndBreadcrumb"; +import {useContextFromContentObjectTags} from "../../services"; +import {useHistory} from "react-router"; +import {useGetBookDetailPageQuery, useGetBookIndexPageQuery} from "../../state/slices/api/booksApi"; +import {BookPage} from "./BookPage"; +import {skipToken} from "@reduxjs/toolkit/query"; +import {ShowLoadingQuery} from "../handlers/ShowLoadingQuery"; +import {TeacherNotes} from "./TeacherNotes"; +import {IsaacContentValueOrChildren} from "../content/IsaacContentValueOrChildren"; +import {ContentDTO} from "../../../IsaacApiTypes"; +import {EditContentButton} from "./EditContentButton"; + interface BookProps { match: { params: { bookId: string } }; } @@ -19,7 +21,7 @@ interface BookProps { export const Book = ({match: {params: {bookId}}}: BookProps) => { const [pageId, setPageId] = useState(undefined); - + const bookIndexPageQuery = useGetBookIndexPageQuery({id: `book_${bookId}`}); const bookDetailPageQuery = useGetBookDetailPageQuery(pageId ? { id: pageId } : skipToken); @@ -44,7 +46,7 @@ export const Book = ({match: {params: {bookId}}}: BookProps) => { }, [book?.chapters, history.location]); return - @@ -55,8 +57,8 @@ export const Book = ({match: {params: {bookId}}}: BookProps) => { thenRender={(definedBookIndexPage) => { return <> - - {pageId + + {pageId ? { : <> -
-
+ {definedBookIndexPage.value &&
+
{definedBookIndexPage.title}
{definedBookIndexPage.value} -
+
} + {!!definedBookIndexPage.children?.length && <> +
+
+ +
+
+ {definedBookIndexPage.title} +
+
+ + {definedBookIndexPage.children.slice(1)} + + } } diff --git a/src/app/components/elements/BookPage.tsx b/src/app/components/elements/BookPage.tsx index a2cc7b51d9..d8214d3e4c 100644 --- a/src/app/components/elements/BookPage.tsx +++ b/src/app/components/elements/BookPage.tsx @@ -1,21 +1,23 @@ import React from "react"; -import { IsaacContentValueOrChildren } from "../content/IsaacContentValueOrChildren"; -import { ListView } from "./list-groups/ListView"; -import { IsaacBookDetailPageDTO } from "../../../IsaacApiTypes"; -import { TeacherNotes } from "./TeacherNotes"; -import { Markup } from "./markup"; -import { EditContentButton } from "./EditContentButton"; +import {IsaacContentValueOrChildren} from "../content/IsaacContentValueOrChildren"; +import {ListView} from "./list-groups/ListView"; +import {IsaacBookDetailPageDTO} from "../../../IsaacApiTypes"; +import {TeacherNotes} from "./TeacherNotes"; +import {EditContentButton} from "./EditContentButton"; export const BookPage = ({ page }: { page: IsaacBookDetailPageDTO }) => { - + return
<> +

+ {page.subtitle && {page.subtitle} } + {page.title} +

+ -

{page.title}

- {!!page.gameboards?.length && <>

Questions

diff --git a/src/app/components/elements/EditContentButton.tsx b/src/app/components/elements/EditContentButton.tsx index e69e2aa246..3f27f59cdd 100644 --- a/src/app/components/elements/EditContentButton.tsx +++ b/src/app/components/elements/EditContentButton.tsx @@ -13,11 +13,11 @@ export const EditContentButton = ({doc, className}: EditContentButtonProps) => { const {data: segueEnvironment} = useGetSegueEnvironmentQuery(); if (segueEnvironment === "DEV" && doc?.canonicalSourceFile) { return
-

+

{doc.published ? "Published" : "Unpublished"} ✎ -

+
; } else { return null; // does not render diff --git a/src/app/components/elements/Tabs.tsx b/src/app/components/elements/Tabs.tsx index adf4afa375..372fef95a5 100644 --- a/src/app/components/elements/Tabs.tsx +++ b/src/app/components/elements/Tabs.tsx @@ -100,7 +100,7 @@ const DropdownNavbar = ({children, activeTab, changeTab, tabTitleClass=""}: Tabs export const Tabs = (props: TabsProps) => { const { className="", tabContentClass="", children, activeTabOverride, onActiveTabChange, - deselectable=false, refreshHash, expandable, style="tabs" + deselectable=false, refreshHash, expandable, style=(siteSpecific("dropdowns", "tabs")), } = props; const [activeTab, setActiveTab] = useState(activeTabOverride || 1); diff --git a/src/app/components/elements/TeacherDashboard.tsx b/src/app/components/elements/TeacherDashboard.tsx index 930a78e44e..926abac982 100644 --- a/src/app/components/elements/TeacherDashboard.tsx +++ b/src/app/components/elements/TeacherDashboard.tsx @@ -2,7 +2,7 @@ import React, { ChangeEvent, useState } from 'react'; import { selectors, useAppSelector } from '../../state'; import { Button, Card, Col, Row } from 'reactstrap'; import { Link } from 'react-router-dom'; -import { BookInfo, extractTeacherName, ISAAC_BOOKS, isDefined, isOverdue, isTutor, sortUpcomingAssignments, Subject, useDeviceSize } from '../../services'; +import { BookInfo, extractTeacherName, ISAAC_BOOKS, isOverdue, isTutor, sortUpcomingAssignments, Subject, useDeviceSize } from '../../services'; import { AssignmentDTO, QuizAssignmentDTO, UserSummaryDTO } from '../../../IsaacApiTypes'; import StyledToggle from './inputs/StyledToggle'; import { AssignmentCard, StudentDashboard } from './StudentDashboard'; @@ -11,6 +11,7 @@ import { Spacer } from './Spacer'; import { AppGroup, UserSnapshot } from '../../../IsaacAppTypes'; import { useStatefulElementRef } from './markup/portals/utils'; import { ScrollShadows } from './ScrollShadows'; +import { ShowLoading } from '../handlers/ShowLoading'; interface GroupsPanelProps { groups: AppGroup[] | undefined; @@ -44,10 +45,6 @@ interface AssignmentsPanelProps { const AssignmentsPanel = ({ assignments, quizzes, groups }: AssignmentsPanelProps) => { const user = useAppSelector(selectors.user.orNull); - - if (!isDefined(assignments) || !isDefined(quizzes)) { - return
; - } const upcomingAssignments = assignments?.filter(a => !isOverdue(a)); // Filter out past assignments const sortedAssignments = upcomingAssignments ? sortUpcomingAssignments(upcomingAssignments) : []; @@ -63,15 +60,19 @@ const AssignmentsPanel = ({ assignments, quizzes, groups }: AssignmentsPanelProp return

View scheduled work

- {soonestDeadlines.length ? -
- {soonestDeadlines.map((assignment, i) => -
- -
)} -
- :
You have no assignments with upcoming due dates.
- } + { + return soonestDeadlines.length + ?
+ {soonestDeadlines.map((assignment, i) => +
+ +
)} +
+ :
You have no assignments with upcoming due dates.
; + }} + />
diff --git a/src/app/components/pages/AssignmentProgress.tsx b/src/app/components/pages/AssignmentProgress.tsx index e4b0652326..bfd0ad8aab 100644 --- a/src/app/components/pages/AssignmentProgress.tsx +++ b/src/app/components/pages/AssignmentProgress.tsx @@ -391,7 +391,7 @@ const GroupDetails = ({group, user}: {group: AppGroup, user: RegisteredUserDTO}) {/* Only full teachers can see the tests tab */} {pageSettings.isTeacher - ? + ? {{ [`Assignments (${assignments.length || 0})`]: assignmentTabComponents, [`Tests (${quizAssignments.length || 0})`]: quizTabComponents diff --git a/src/app/components/pages/MyProgress.tsx b/src/app/components/pages/MyProgress.tsx index 6434dd11a1..e44459eea6 100644 --- a/src/app/components/pages/MyProgress.tsx +++ b/src/app/components/pages/MyProgress.tsx @@ -120,7 +120,7 @@ const MyProgress = withRouter((props: MyProgressProps) => { - { + { const flush = tabRefs[tabIndex - 1].current; if (flush) { // Don't call the flush in an event handler that causes the render, that's too early. diff --git a/src/app/components/pages/Question.tsx b/src/app/components/pages/Question.tsx index 4fc6660075..fdc63c418f 100644 --- a/src/app/components/pages/Question.tsx +++ b/src/app/components/pages/Question.tsx @@ -107,8 +107,6 @@ export const Question = withRouter(({questionIdOverride, match, location, previe {!preview && } - -
{isAda && <> {pageContainsLLMFreeTextQuestion && } @@ -131,7 +129,7 @@ export const Question = withRouter(({questionIdOverride, match, location, previe
}
- + {isPhy && Subject & topics @@ -145,7 +143,7 @@ export const Question = withRouter(({questionIdOverride, match, location, previe Status - {allQuestionsCorrect + {allQuestionsCorrect ?
Correct
: anyQuestionAttempted ?
In Progress
@@ -154,12 +152,14 @@ export const Question = withRouter(({questionIdOverride, match, location, previe Stage & difficulty - +
} {isPhy && } + + @@ -198,6 +198,6 @@ export const Question = withRouter(({questionIdOverride, match, location, previe ;} - } + } />; }); diff --git a/src/app/components/pages/books_old/maths_book_gcse.tsx b/src/app/components/pages/books_old/maths_book_gcse.tsx index 54e875654b..a8122989a9 100644 --- a/src/app/components/pages/books_old/maths_book_gcse.tsx +++ b/src/app/components/pages/books_old/maths_book_gcse.tsx @@ -20,7 +20,7 @@ export const MathsBookGcse = () => {
- + {{ 'Boards for Class and Homework':

Chapters:

diff --git a/src/app/components/pages/books_old/phys_book_gcse.tsx b/src/app/components/pages/books_old/phys_book_gcse.tsx index b8f3110d93..393b723269 100644 --- a/src/app/components/pages/books_old/phys_book_gcse.tsx +++ b/src/app/components/pages/books_old/phys_book_gcse.tsx @@ -20,7 +20,7 @@ export const PhysBookGcse = () => {
- + {{ 'Boards for Class and Homework':

Chapters:

diff --git a/src/app/components/pages/quizzes/MyQuizzes.tsx b/src/app/components/pages/quizzes/MyQuizzes.tsx index 5c0a3ea580..943f80e68c 100644 --- a/src/app/components/pages/quizzes/MyQuizzes.tsx +++ b/src/app/components/pages/quizzes/MyQuizzes.tsx @@ -449,7 +449,7 @@ const MyQuizzesPageComponent = ({user}: QuizzesPageProps) => { setQuizStatusFilter={setQuizStatusFilter} activeTab={tabOverride ?? 1} displayMode={displayMode} setDisplayMode={setDisplayMode}/> } /> - { + { history.replace({...history.location, hash: tabAnchors[index - 1]}); setBoardOrder(index === 1 ? QuizzesBoardOrder.dueDate : QuizzesBoardOrder.title); }}> diff --git a/src/app/components/pages/quizzes/PracticeQuizzes.tsx b/src/app/components/pages/quizzes/PracticeQuizzes.tsx index 4d1c7b0a6f..c20959f00d 100644 --- a/src/app/components/pages/quizzes/PracticeQuizzes.tsx +++ b/src/app/components/pages/quizzes/PracticeQuizzes.tsx @@ -40,11 +40,12 @@ const PracticeQuizzesComponent = () => { contentAudience.stage?.map(s => STAGE_TO_LEARNING_STAGE[s]).includes(selectedStage as LearningStage); const showQuiz = (quiz: QuizSummaryDTO) => { - if (!user || !isLoggedIn(user)) return false; if (pageSubject && !quiz.tags?.includes(pageSubject)) return false; if (pageStage && !quiz.audience?.some(audienceMatch(pageStage))) return false; - switch (user.role) { + // Anonymous users can list student-visible quizzes + const userRole = user && isLoggedIn(user) ? user.role : "STUDENT"; + switch (userRole) { case "STUDENT": case "TUTOR": case "TEACHER": diff --git a/src/app/components/pages/quizzes/SetQuizzes.tsx b/src/app/components/pages/quizzes/SetQuizzes.tsx index ebbaebfe47..d21989feb3 100644 --- a/src/app/components/pages/quizzes/SetQuizzes.tsx +++ b/src/app/components/pages/quizzes/SetQuizzes.tsx @@ -394,7 +394,7 @@ const SetQuizzesPageComponent = ({user}: SetQuizzesPageProps) => { manageQuizzesGroupNameFilter={manageQuizzesGroupNameFilter} setManageQuizzesGroupNameFilter={setManageQuizzesGroupNameFilter}/>} - + {{ [siteSpecific("Set Tests", "Available tests")]: diff --git a/src/app/components/pages/subjectLandingPageComponents.ts b/src/app/components/pages/subjectLandingPageComponents.ts index 873b095691..f06b2a4220 100644 --- a/src/app/components/pages/subjectLandingPageComponents.ts +++ b/src/app/components/pages/subjectLandingPageComponents.ts @@ -68,7 +68,8 @@ const CoreSkillsCard = (context: NonNullable>): ListV }, icon: {type: "hex", icon: "icon-quiz"}, subject: context.subject, - linkTags: [{tag: "Practise a core skill", url: extendUrl(context, 'quick_quizzes')}] + linkTags: [{tag: "Practise a core skill", url: extendUrl(context, 'quick_quizzes')}], + state: AbstractListViewItemState.COMING_SOON, }); const GlossaryCard = (context: NonNullable>): ListViewCardProps => ({ diff --git a/src/app/components/site/ScrollToTop.tsx b/src/app/components/site/ScrollToTop.tsx index b05d764989..22a4c8ffba 100644 --- a/src/app/components/site/ScrollToTop.tsx +++ b/src/app/components/site/ScrollToTop.tsx @@ -1,7 +1,7 @@ import React, { useCallback, useEffect } from "react"; import classNames from "classnames"; import { siteSpecific } from "../../services"; -import { Button } from "reactstrap"; +import { IconButton } from "../elements/AffixButton"; export const ScrollToTop = ({mainContent}: {mainContent: React.MutableRefObject}) => { const [sticky, setSticky] = React.useState(false); @@ -18,16 +18,15 @@ export const ScrollToTop = ({mainContent}: {mainContent: React.MutableRefObject< }, [isSticky]); return siteSpecific( - , + />,