Commit 9cdc64a5 authored by Filip Šenk's avatar Filip Šenk Committed by Marek Veselý
Browse files

Resolve "Chore: New version of Backend - v3.14.0"

parent 5282b1ea
Loading
Loading
Loading
Loading
Compare 2ee23f62 to e5a8728b
Original line number Diff line number Diff line
Subproject commit 2ee23f62b1883ee941f17f4192426ba4c589d884
Subproject commit e5a8728b30d506aec9c326673c077d1f4b98fc91
+1 −1
Original line number Diff line number Diff line
{
  "name": "@inject/codegen",
  "version": "3.13.0",
  "version": "3.14.0",
  "description": "GraphQL API Codegen Setup for the Inject Backend",
  "main": "index.js",
  "license": "MIT",
+1 −1
Original line number Diff line number Diff line
{
  "name": "@inject/frontend",
  "version": "3.13.0",
  "version": "3.14.0",
  "description": "Main wrapper for rendering INJECT Frontend",
  "main": "index.js",
  "license": "MIT",
+124 −0
Original line number Diff line number Diff line
import { Button } from '@blueprintjs/core'
import { css } from '@emotion/css'
import type { FileInfo } from '@inject/graphql'
import type { Column } from '@inject/shared'
import {
  dateSortingFunction,
  stringSortingFunction,
  Table,
  timedFormatter,
} from '@inject/shared'
import type { NavigateOptions } from '@tanstack/react-router'
import { useNavigate } from '@tanstack/react-router'
import type { FC } from 'react'
import { useMemo } from 'react'

type DriveProps = {
  fileInfos: FileInfo[]
  searchString: string
  getFileLink: (fileId: string) => NavigateOptions
}
const verticallyCentered = css`
  vertical-align: middle;
`

const DriveTable: FC<DriveProps> = ({
  fileInfos,
  searchString,
  getFileLink,
}) => {
  const nav = useNavigate()

  const handleClick = (
    e: React.MouseEvent<HTMLAnchorElement, MouseEvent>,
    link: NavigateOptions
  ) => {
    e.preventDefault()

    nav({
      ...link,
      state: {
        backButtonProps: {
          button: { text: 'Back', minimal: true, icon: 'chevron-left' },
          back: true,
        },
      },
    })
  }

  const columns: Column<FileInfo>[] = [
    {
      id: 'name',
      name: 'Name',
      style: { textAlign: 'left' },
      renderValue: file => file.fileName,
      sortingFunction: (a, b) => stringSortingFunction(a.fileName, b.fileName),
      className: verticallyCentered,
    },
    {
      id: 'uploaded',
      name: 'Uploaded',
      style: { textAlign: 'left', width: '20ch' },
      renderValue: file =>
        timedFormatter({ datetime: new Date(file.uploadedAt) }),
      sortingFunction: (a, b) =>
        dateSortingFunction(new Date(a.uploadedAt), new Date(b.uploadedAt)),
      className: verticallyCentered,
    },
    {
      id: 'actions',
      name: 'Actions',
      style: {
        textAlign: 'right',
        width: '14ch',
      },
      renderValue: file => {
        const link = getFileLink(file.id)

        return (
          <a href={link.href} onClick={e => handleClick(e, link)}>
            <Button icon='eye-open' title='Preview' />
          </a>
        )
      },
      className: verticallyCentered,
    },
  ]

  const filteredFiles = useMemo(
    () =>
      fileInfos.filter(oneFile =>
        oneFile.fileName.toLowerCase().includes(searchString.toLowerCase())
      ),
    [fileInfos, searchString]
  )

  const rows = useMemo(
    () =>
      filteredFiles
        .map(fileInfo => ({
          id: fileInfo.id,
          value: fileInfo,
        }))
        .sort((a, b) =>
          stringSortingFunction(a.value.fileName, b.value.fileName)
        ),
    [filteredFiles]
  )

  return (
    <Table<FileInfo>
      columns={columns}
      rows={rows}
      className={css`
        overflow-y: scroll;
      `}
      noDataStateProps={{
        title: 'No files',
        description: 'There are no files to display',
      }}
    />
  )
}

export default DriveTable
+63 −0
Original line number Diff line number Diff line
import { NonIdealState } from '@blueprintjs/core'
import { css } from '@emotion/css'
import { ExerciseDrive, useTypedQuery } from '@inject/graphql'
import { CenteredSpinner, Container } from '@inject/shared'
import type { NavigateOptions } from '@tanstack/react-router'
import type { FC } from 'react'
import { useState } from 'react'
import SearchInput from '../SearchInput'
import DriveTable from './DriveTable'

type DriveProps = {
  exerciseId: string
  getFileLink: (fileId: string) => NavigateOptions
}

const Drive: FC<DriveProps> = ({ exerciseId, getFileLink }) => {
  const [{ fetching: loading, data }] = useTypedQuery({
    query: ExerciseDrive,
    variables: {
      exerciseId,
    },
  })

  const [searchString, setSearchString] = useState('')

  if (loading) {
    return <CenteredSpinner />
  }

  if (!data || !data.exerciseDrive) {
    return (
      <NonIdealState
        icon='floppy-disk'
        title='No disk'
        description='There is no disk to display'
      />
    )
  }

  return (
    <Container
      className={css`
        overflow-y: hidden;
        display: flex;
        flex-direction: column;
        row-gap: 1rem;
        padding-top: 0.5rem;
      `}
    >
      <SearchInput
        searchString={searchString}
        setSearchString={setSearchString}
      />
      <DriveTable
        fileInfos={data.exerciseDrive}
        searchString={searchString}
        getFileLink={getFileLink}
      />
    </Container>
  )
}

export default Drive
Loading