Verified Commit 8b204c59 authored by Marek Veselý's avatar Marek Veselý
Browse files

feat: add export tokens as csv, stop wrapping tokens

parent 4c482680
Loading
Loading
Loading
Loading
+35 −9
Original line number Diff line number Diff line
import { Button, Collapse } from '@blueprintjs/core'
import { Button, ButtonGroup, Collapse } from '@blueprintjs/core'
import { css } from '@emotion/css'
import type { TeamTokenF } from '@inject/graphql'
import { ExerciseTokensQuery, useTypedQuery } from '@inject/graphql'
@@ -58,7 +58,7 @@ export const SandboxInfo: FC<ConfigInfoProps> = ({
    {
      id: 'token',
      name: t('exerciseInfo.token'),
      style: { width: '60%' },
      style: { width: '60%', whiteSpace: 'pre-wrap', wordBreak: 'break-word' },
      renderValue: teamToken => teamToken.token,
      className: verticallyCentered,
      sortingFunction: (a, b) => stringSortingFunction(a.token, b.token),
@@ -71,8 +71,30 @@ export const SandboxInfo: FC<ConfigInfoProps> = ({
      value: token,
    })) || []

  const exportAsCSV = () => {
    const header = ['teamIds', 'username', 'token'].join(',')
    const csvRows =
      data?.exerciseTokens.map(token => {
        const teamIds = `"${token.teamIds.join('|')}"`
        const username = `"${token.user.username}"`
        const tokenValue = `"${token.token}"`
        return [teamIds, username, tokenValue].join(',')
      }) || []
    const csvContent = [header, ...csvRows].join('\n')
    const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' })
    const link = document.createElement('a')
    const url = URL.createObjectURL(blob)
    link.setAttribute('href', url)
    link.setAttribute('download', `exercise_${exerciseId}_tokens.csv`)
    link.style.visibility = 'hidden'
    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)
  }

  return (
    <div className={className}>
      <ButtonGroup>
        <Button onClick={() => setOpen(!open)} active={open} loading={fetching}>
          {`${
            open
@@ -80,6 +102,10 @@ export const SandboxInfo: FC<ConfigInfoProps> = ({
              : t('exercisePanel.definitionManager.info.showTokens')
          } ${t('exercisePanel.definitionManager.info.tokens')}`}
        </Button>
        <Button onClick={exportAsCSV}>
          {t('exercisePanel.definitionManager.info.exportTokens')}
        </Button>
      </ButtonGroup>
      <Collapse isOpen={open}>
        <Table<TeamTokenF>
          columns={columns}
+0 −11
Original line number Diff line number Diff line
import { Navbar } from '@blueprintjs/core'
import { css } from '@emotion/css'
import type { IUser } from '@inject/graphql'
import {
@@ -200,16 +199,6 @@ const RouteComponent = () => {
          link={{ to: ExercisePanelRoute.to }}
          button={{ text: 'Exercise Panel', icon: 'panel', minimal: true }}
        />

        <Navbar.Divider
          className={css`
            align-self: center;
            display: none;
            @media (min-width: 75rem) {
              display: block;
            }
          `}
        />
      </PrependNavbar>
      <Sidebar position='right' className={sidebarClass} sections={sections} />
    </div>
+2 −1
Original line number Diff line number Diff line
@@ -737,7 +737,8 @@
        "showTokens": "Zobrazit",
        "tokens": "tokeny",
        "noTokensTitle": "Žádné tokeny",
        "noTokensDescription": "Žádní uživatelé nejsou k tomuto cvičení přiřazeni"
        "noTokensDescription": "Žádní uživatelé nejsou k tomuto cvičení přiřazeni",
        "exportTokens": "Exportovat tokeny do CSV"
      }
    },
    "exportImport": {
+2 −1
Original line number Diff line number Diff line
@@ -737,7 +737,8 @@
        "showTokens": "Show",
        "tokens": "tokens",
        "noTokensTitle": "No tokens",
        "noTokensDescription": "No users are assigned to this exercise yet"
        "noTokensDescription": "No users are assigned to this exercise yet",
        "exportTokens": "Export tokens as CSV"
      }
    },
    "exportImport": {