Commit 15ccf130 authored by Filip Šenk's avatar Filip Šenk
Browse files

Create own page for instructor comments

parent a03445ea
Loading
Loading
Loading
Loading
+29 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import { Route as ProtectedNavbarTraineeIndexImport } from './routes/_protected/
import { Route as ProtectedNavbarPlatformConfigIndexImport } from './routes/_protected/_navbar/platform-config/index'
import { Route as ProtectedNavbarExercisePanelIndexImport } from './routes/_protected/_navbar/exercise-panel/index'
import { Route as ProtectedInstructorExerciseIdSelectImport } from './routes/_protected/instructor/$exerciseId/select'
import { Route as ProtectedInstructorExerciseIdInstructorNotesImport } from './routes/_protected/instructor/$exerciseId/instructor-notes'
import { Route as ProtectedInstructorExerciseIdDriveImport } from './routes/_protected/instructor/$exerciseId/drive'
import { Route as ProtectedNavbarUsersUserIdImport } from './routes/_protected/_navbar/users/$userId'
import { Route as ProtectedNavbarTraineeExerciseIdImport } from './routes/_protected/_navbar/trainee/$exerciseId'
@@ -217,6 +218,13 @@ const ProtectedInstructorExerciseIdSelectRoute =
    getParentRoute: () => ProtectedInstructorExerciseIdRouteRoute,
  } as any)

const ProtectedInstructorExerciseIdInstructorNotesRoute =
  ProtectedInstructorExerciseIdInstructorNotesImport.update({
    id: '/instructor-notes',
    path: '/instructor-notes',
    getParentRoute: () => ProtectedInstructorExerciseIdRouteRoute,
  } as any)

const ProtectedInstructorExerciseIdDriveRoute =
  ProtectedInstructorExerciseIdDriveImport.update({
    id: '/drive',
@@ -644,6 +652,13 @@ declare module '@tanstack/react-router' {
      preLoaderRoute: typeof ProtectedInstructorExerciseIdDriveImport
      parentRoute: typeof ProtectedInstructorExerciseIdRouteImport
    }
    '/_protected/instructor/$exerciseId/instructor-notes': {
      id: '/_protected/instructor/$exerciseId/instructor-notes'
      path: '/instructor-notes'
      fullPath: '/instructor/$exerciseId/instructor-notes'
      preLoaderRoute: typeof ProtectedInstructorExerciseIdInstructorNotesImport
      parentRoute: typeof ProtectedInstructorExerciseIdRouteImport
    }
    '/_protected/instructor/$exerciseId/select': {
      id: '/_protected/instructor/$exerciseId/select'
      path: '/select'
@@ -1115,6 +1130,7 @@ const ProtectedInstructorExerciseIdTeamIdRouteRouteWithChildren =
interface ProtectedInstructorExerciseIdRouteRouteChildren {
  ProtectedInstructorExerciseIdTeamIdRouteRoute: typeof ProtectedInstructorExerciseIdTeamIdRouteRouteWithChildren
  ProtectedInstructorExerciseIdDriveRoute: typeof ProtectedInstructorExerciseIdDriveRoute
  ProtectedInstructorExerciseIdInstructorNotesRoute: typeof ProtectedInstructorExerciseIdInstructorNotesRoute
  ProtectedInstructorExerciseIdSelectRoute: typeof ProtectedInstructorExerciseIdSelectRoute
  ProtectedInstructorExerciseIdIndexRoute: typeof ProtectedInstructorExerciseIdIndexRoute
  ProtectedInstructorExerciseIdFileFileIdRoute: typeof ProtectedInstructorExerciseIdFileFileIdRoute
@@ -1126,6 +1142,8 @@ const ProtectedInstructorExerciseIdRouteRouteChildren: ProtectedInstructorExerci
      ProtectedInstructorExerciseIdTeamIdRouteRouteWithChildren,
    ProtectedInstructorExerciseIdDriveRoute:
      ProtectedInstructorExerciseIdDriveRoute,
    ProtectedInstructorExerciseIdInstructorNotesRoute:
      ProtectedInstructorExerciseIdInstructorNotesRoute,
    ProtectedInstructorExerciseIdSelectRoute:
      ProtectedInstructorExerciseIdSelectRoute,
    ProtectedInstructorExerciseIdIndexRoute:
@@ -1301,6 +1319,7 @@ export interface FileRoutesByFullPath {
  '/trainee/$exerciseId/$teamId': typeof ProtectedTraineeExerciseIdTeamIdRouteRouteWithChildren
  '/users/$userId': typeof ProtectedNavbarUsersUserIdRoute
  '/instructor/$exerciseId/drive': typeof ProtectedInstructorExerciseIdDriveRoute
  '/instructor/$exerciseId/instructor-notes': typeof ProtectedInstructorExerciseIdInstructorNotesRoute
  '/instructor/$exerciseId/select': typeof ProtectedInstructorExerciseIdSelectRoute
  '/exercise-panel/': typeof ProtectedNavbarExercisePanelIndexRoute
  '/platform-config/': typeof ProtectedNavbarPlatformConfigIndexRoute
@@ -1357,6 +1376,7 @@ export interface FileRoutesByTo {
  '/': typeof ProtectedNavbarIndexRoute
  '/users/$userId': typeof ProtectedNavbarUsersUserIdRoute
  '/instructor/$exerciseId/drive': typeof ProtectedInstructorExerciseIdDriveRoute
  '/instructor/$exerciseId/instructor-notes': typeof ProtectedInstructorExerciseIdInstructorNotesRoute
  '/instructor/$exerciseId/select': typeof ProtectedInstructorExerciseIdSelectRoute
  '/exercise-panel': typeof ProtectedNavbarExercisePanelIndexRoute
  '/platform-config': typeof ProtectedNavbarPlatformConfigIndexRoute
@@ -1415,6 +1435,7 @@ export interface FileRoutesById {
  '/_protected/_navbar/trainee/$exerciseId': typeof ProtectedNavbarTraineeExerciseIdRoute
  '/_protected/_navbar/users/$userId': typeof ProtectedNavbarUsersUserIdRoute
  '/_protected/instructor/$exerciseId/drive': typeof ProtectedInstructorExerciseIdDriveRoute
  '/_protected/instructor/$exerciseId/instructor-notes': typeof ProtectedInstructorExerciseIdInstructorNotesRoute
  '/_protected/instructor/$exerciseId/select': typeof ProtectedInstructorExerciseIdSelectRoute
  '/_protected/_navbar/exercise-panel/': typeof ProtectedNavbarExercisePanelIndexRoute
  '/_protected/_navbar/platform-config/': typeof ProtectedNavbarPlatformConfigIndexRoute
@@ -1478,6 +1499,7 @@ export interface FileRouteTypes {
    | '/trainee/$exerciseId/$teamId'
    | '/users/$userId'
    | '/instructor/$exerciseId/drive'
    | '/instructor/$exerciseId/instructor-notes'
    | '/instructor/$exerciseId/select'
    | '/exercise-panel/'
    | '/platform-config/'
@@ -1533,6 +1555,7 @@ export interface FileRouteTypes {
    | '/'
    | '/users/$userId'
    | '/instructor/$exerciseId/drive'
    | '/instructor/$exerciseId/instructor-notes'
    | '/instructor/$exerciseId/select'
    | '/exercise-panel'
    | '/platform-config'
@@ -1589,6 +1612,7 @@ export interface FileRouteTypes {
    | '/_protected/_navbar/trainee/$exerciseId'
    | '/_protected/_navbar/users/$userId'
    | '/_protected/instructor/$exerciseId/drive'
    | '/_protected/instructor/$exerciseId/instructor-notes'
    | '/_protected/instructor/$exerciseId/select'
    | '/_protected/_navbar/exercise-panel/'
    | '/_protected/_navbar/platform-config/'
@@ -1714,6 +1738,7 @@ export const routeTree = rootRoute
      "children": [
        "/_protected/instructor/$exerciseId/$teamId",
        "/_protected/instructor/$exerciseId/drive",
        "/_protected/instructor/$exerciseId/instructor-notes",
        "/_protected/instructor/$exerciseId/select",
        "/_protected/instructor/$exerciseId/",
        "/_protected/instructor/$exerciseId/file/$fileId"
@@ -1784,6 +1809,10 @@ export const routeTree = rootRoute
      "filePath": "_protected/instructor/$exerciseId/drive.tsx",
      "parent": "/_protected/instructor/$exerciseId"
    },
    "/_protected/instructor/$exerciseId/instructor-notes": {
      "filePath": "_protected/instructor/$exerciseId/instructor-notes.tsx",
      "parent": "/_protected/instructor/$exerciseId"
    },
    "/_protected/instructor/$exerciseId/select": {
      "filePath": "_protected/instructor/$exerciseId/select.tsx",
      "parent": "/_protected/instructor/$exerciseId"
+62 −0
Original line number Diff line number Diff line
import { NonIdealState } from '@blueprintjs/core'
import { css } from '@emotion/css'
import { GetInstructorNotes, useTypedQuery } from '@inject/graphql'
import { Container } from '@inject/shared'
import { createFileRoute } from '@tanstack/react-router'
import ContentComponent from '../../../../components/ContentComponent'
import { InstructorFilePageRoute } from './file.$fileId'

const InstructorNotesPage = () => {
  const { exerciseId } = Route.useParams()

  const [{ data: instructorNotesData }] = useTypedQuery({
    query: GetInstructorNotes,
    variables: { exerciseId: exerciseId || '' },
  })

  const instructorNotes = instructorNotesData?.exerciseId.config.instructorNotes
  if (
    !instructorNotes ||
    (!instructorNotes.rendered && !instructorNotes.attachments)
  ) {
    return (
      <NonIdealState
        className={css`
          padding-top: 0.5rem;
        `}
        icon='book'
        title='Instructor notes were not provided'
      />
    )
  }

  return (
    <Container
      className={css`
        padding-top: 0.5rem;
      `}
    >
      <h3>Instructor notes:</h3>
      <ContentComponent
        content={instructorNotes}
        exerciseId={exerciseId}
        inInstructor
        getFileLink={fileId => ({
          to: InstructorFilePageRoute.to,
          params: {
            exerciseId,
            fileId,
          },
        })}
      />
    </Container>
  )
}

export const Route = createFileRoute(
  '/_protected/instructor/$exerciseId/instructor-notes'
)({
  component: InstructorNotesPage,
})

export const InstructorNotesRoute = Route
+0 −62
Original line number Diff line number Diff line
import { Button, Dialog, DialogBody } from '@blueprintjs/core'
import { cx } from '@emotion/css'

import type { Content } from '@inject/graphql'
import { dialog, dialogBody } from '@inject/shared'
import { type FC, useState } from 'react'
import ContentComponent from '../../components/ContentComponent'
import { InstructorFilePageRoute } from '../../routes/_protected/instructor/$exerciseId/file.$fileId'

type InstructorNotesProps = {
  content: Content
  exerciseId: string
  hideLabel?: boolean
}

const InstructorNotes: FC<InstructorNotesProps> = ({
  content,
  exerciseId,
  hideLabel,
}) => {
  const [isOpen, setIsOpen] = useState(false)
  return (
    <>
      <Button
        fill
        minimal
        alignText='left'
        title='Instructor notes'
        icon='book'
        text={hideLabel ? undefined : 'Instructor notes'}
        onClick={() => setIsOpen(prev => !prev)}
      />

      <Dialog
        className={cx(dialog)}
        isOpen={isOpen}
        onClose={() => {
          setIsOpen(false)
        }}
        title='Instructor notes'
        icon='book'
      >
        <DialogBody className={dialogBody}>
          <ContentComponent
            content={content}
            exerciseId={exerciseId}
            inInstructor
            getFileLink={fileId => ({
              to: InstructorFilePageRoute.to,
              params: {
                exerciseId,
                fileId,
              },
            })}
          />
        </DialogBody>
      </Dialog>
    </>
  )
}

export default InstructorNotes
+26 −0
Original line number Diff line number Diff line
import { LinkButton } from '@inject/shared'
import type { NavigateOptions } from '@tanstack/react-router'
import type { FC } from 'react'

type InstructorNotesButtonProps = {
  link: NavigateOptions
  hideLabel?: boolean
}

export const InstructorNotesButton: FC<InstructorNotesButtonProps> = ({
  link,
  hideLabel,
}) => (
  <LinkButton
    link={link}
    button={{
      icon: 'book',
      alignText: 'left',
      fill: true,
      minimal: true,
      title: 'Instructor notes',
      text: !hideLabel && 'Instructor notes',
    }}
    end
  />
)
+22 −27
Original line number Diff line number Diff line
@@ -30,10 +30,11 @@ import { RootRoute } from '../../routes/__root'
import { InstructorLandingPageRoute } from '../../routes/_protected/instructor/$exerciseId'
import { InstructorEmailThreadPageRoute } from '../../routes/_protected/instructor/$exerciseId/$teamId/email/$tab/$threadId'
import { InstructorDriveRoute } from '../../routes/_protected/instructor/$exerciseId/drive'
import { InstructorNotesRoute } from '../../routes/_protected/instructor/$exerciseId/instructor-notes'
import { InstructorSelectTeamRoute } from '../../routes/_protected/instructor/$exerciseId/select'
import { synchronousExerciseState } from '../../utils'
import ChannelButton from '../ChannelButton'
import InstructorNotes from './InstructorNotes'
import { InstructorNotesButton } from './InstructorNotesButton'
import MilestonesButton from './MilestoneButton'
import { OverviewButton } from './OverviewButton'
import TeamOverviewButton from './TeamOverviewButton'
@@ -58,15 +59,8 @@ export const InstructorView: FC<InstructorViewProps> = ({
  })
  const { running } = useLoopStatus({ teamId })

  const {
    loading,
    error,
    channels,
    emailsEnabled,
    instructorNotes,
    exerciseStatus,
    teamState,
  } = useInstructorViewData({
  const { loading, error, channels, emailsEnabled, exerciseStatus, teamState } =
    useInstructorViewData({
      exerciseId,
      teamId,
    })
@@ -129,13 +123,6 @@ export const InstructorView: FC<InstructorViewProps> = ({
              hideLabel={hideLeftBar}
            />
          )}
          {exerciseId && instructorNotes && (
            <InstructorNotes
              content={instructorNotes}
              exerciseId={exerciseId}
              hideLabel={hideLeftBar}
            />
          )}

          <InstructorInject
            teamId={teamId}
@@ -165,6 +152,7 @@ export const InstructorView: FC<InstructorViewProps> = ({
    {
      id: 'Documents',
      node: (
        <>
          <DriveButton
            link={{
              to: InstructorDriveRoute.to,
@@ -172,6 +160,13 @@ export const InstructorView: FC<InstructorViewProps> = ({
            }}
            hideLabel={hideLeftBar}
          />
          <InstructorNotesButton
            link={{
              to: InstructorNotesRoute.to,
              params: { exerciseId },
            }}
          />
        </>
      ),
    },
    ...(exerciseId && teamId
Loading