Commit 1abbf4e1 authored by Marek Veselý's avatar Marek Veselý
Browse files

refactor/fix/feat: unify team selectors and labels, add role and exercise info

parent c67fb315
Loading
Loading
Loading
Loading
+9 −8
Original line number Diff line number Diff line
@@ -6,17 +6,17 @@ import {
  Section,
  SectionCard,
} from '@blueprintjs/core'
import { toggleTeam, unsetTeams, useTeams } from '../vars/teams'
import { toggleTeam, unsetTeams, useTeamStateMap } from '../vars/teams'

const InstructorTeams = () => {
  const teamsVar = useTeams()
  const teamStateMap = useTeamStateMap()
  const validator = useTeamStateValidator()

  return (
    <Section
      title={'Instructor Subscribed Teams'}
      subtitle={`Current amount of synchronized teams: ${
        Object.keys(teamsVar).length
        Object.keys(teamStateMap).length
      }`}
      rightElement={
        <div
@@ -48,7 +48,7 @@ const InstructorTeams = () => {
      }
    >
      <SectionCard>
        {Object.keys(teamsVar).length === 0 && (
        {Object.keys(teamStateMap).length === 0 && (
          <div style={{ padding: '1rem' }}>
            <NonIdealState
              icon='low-voltage-pole'
@@ -56,18 +56,19 @@ const InstructorTeams = () => {
            />
          </div>
        )}
        {Object.keys(teamsVar).length > 0 && (
        {Object.keys(teamStateMap).length > 0 && (
          <div style={{ padding: '0.25rem' }}>
            {Object.entries(teamsVar).map(([key, team]) => (
            {Object.entries(teamStateMap).map(([key, value]) => (
              <CheckboxCard
                key={key}
                checked={team.show}
                checked={value.show}
                onClick={e => {
                  e.preventDefault()
                  toggleTeam(key)
                }}
              >
                <span>{team.teamRole || `Team ${team.teamId}`}</span>
                {/* TODO: add role */}
                <span>{value.team.name}</span>
              </CheckboxCard>
            ))}
          </div>
+22 −21
Original line number Diff line number Diff line
import { makeVar, useReactiveVar } from '@inject/graphql/client/reactive'
import type { Team } from '@inject/graphql/fragments/Team.generated'

export interface Team {
  exerciseId: string
  teamRole: string
  teamId: string
export interface TeamState {
  team: Team
  show: boolean
  inactive: boolean
}

interface TeamState {
  [key: string]: Team
export interface TeamStateMap {
  [teamId: string]: TeamState
}

const key = 'team'
const initialSettings: TeamState = JSON.parse(localStorage.getItem(key) || '{}')
const key = 'teamStateMap'
const initialSettings: TeamStateMap = JSON.parse(
  localStorage.getItem(key) || '{}'
)

export const teams = makeVar<TeamState>(initialSettings)
export const useTeams = () => useReactiveVar(teams) as TeamState
export const teamStateMap = makeVar<TeamStateMap>(initialSettings)
export const useTeamStateMap = () => useReactiveVar(teamStateMap)

function change(value: TeamState) {
function change(value: TeamStateMap) {
  localStorage.setItem(key, JSON.stringify(value))
}

export const toggleTeam = (team: string) => {
  const prev = teams() as TeamState
  const chosenTeam = prev[team]
  teams({
export const toggleTeam = (teamId: string) => {
  const prev = teamStateMap() as TeamStateMap
  const chosenTeam = prev[teamId]
  teamStateMap({
    ...prev,
    [team]: {
    [teamId]: {
      ...chosenTeam,
      show: !chosenTeam.show,
    },
@@ -35,8 +36,8 @@ export const toggleTeam = (team: string) => {
}

export const unsetTeams = () => {
  const prev = teams() as TeamState
  teams(
  const prev = teamStateMap() as TeamStateMap
  teamStateMap(
    Object.fromEntries(
      Object.entries(prev).map(([key, value]) => [
        key,
@@ -46,7 +47,7 @@ export const unsetTeams = () => {
  )
}

teams.onNextChange(function onNext() {
  change(teams())
  teams.onNextChange(onNext)
teamStateMap.onNextChange(function onNext() {
  change(teamStateMap())
  teamStateMap.onNextChange(onNext)
})
+15 −2
Original line number Diff line number Diff line
@@ -28,14 +28,27 @@ const Status: FC<StatusProps> = ({
  team,
  hideLabel,
}) => (
  <div style={{ display: 'flex', flexDirection: 'column', gap: '0.5rem' }}>
  <div
    style={{
      display: 'flex',
      flexDirection: 'column',
      gap: '0.5rem',
      alignItems: 'center',
    }}
  >
    <div className={header}>
      {!small && (!exerciseRunning || !showTime) && <span>Backend:</span>}
      <HealthCheck />
      {exerciseRunning && showTime && <TimeLeft />}
    </div>
    {team && (
      <TeamLabel teamId={team.id} teamName={team.name} hideLabel={hideLabel} />
      <TeamLabel
        teamId={team.id}
        teamName={team.name}
        hideLabel={hideLabel}
        exerciseName={team.exercise.name}
        teamRole={team.role}
      />
    )}
  </div>
)
+74 −14
Original line number Diff line number Diff line
import { Classes, Tag } from '@blueprintjs/core'
import ColorBox from '@inject/shared/components/ColorBox'
import type { FC } from 'react'
import { useMemo, type FC } from 'react'

interface TeamLabelProps {
  hideLabel?: boolean
  teamId: string
  teamName: string
  teamRole?: string
  exerciseName?: string
  inactive?: boolean
}

const TeamLabel: FC<TeamLabelProps> = ({ hideLabel, teamId, teamName }) => (
const TeamLabel: FC<TeamLabelProps> = ({
  hideLabel,
  teamId,
  teamName,
  teamRole,
  exerciseName,
  inactive,
}) => {
  const label = useMemo(
    () => (
      <div>
        <div>{teamName}</div>
        {teamRole && (
          <div className={Classes.TEXT_MUTED}>{`role: ${teamRole}`}</div>
        )}
        {exerciseName && (
          <div
            className={Classes.TEXT_MUTED}
          >{`exercise: ${exerciseName}`}</div>
        )}
      </div>
    ),
    [exerciseName, teamName, teamRole]
  )

  const colorbox = useMemo(
    () => (
      <ColorBox
        style={{
          width: '16px',
          height: '16px',
          marginRight: hideLabel ? undefined : '7px',
        }}
        id={Number(teamId)}
      />
    ),
    [hideLabel, teamId]
  )

  const content = useMemo(() => {
    if (hideLabel) {
      return colorbox
    }

    return (
      <>
        {colorbox}
        {label}
        {inactive && (
          <Tag style={{ marginLeft: '1ch' }} minimal intent='warning'>
            inactive
          </Tag>
        )}
      </>
    )
  }, [colorbox, hideLabel, inactive, label])

  return (
    <div
      style={{
        display: 'flex',
      justifyContent: 'center',
        justifyContent: hideLabel ? 'center' : 'flex-start',
        alignItems: 'center',
      gap: '0.5rem',
      }}
    >
    {!hideLabel && <h3 style={{ fontSize: '1rem', margin: 0 }}>{teamName}</h3>}
    <ColorBox id={Number(teamId)} title={teamName} />
      {content}
    </div>
  )
}

export default TeamLabel
+0 −36
Original line number Diff line number Diff line
import type { Team } from '@/clientsettings/vars/teams'
import { Tag } from '@blueprintjs/core'
import ColorBox from '@inject/shared/components/ColorBox'
import type { FC } from 'react'

interface LabelElementProps {
  team: Team
  hideLabel?: boolean
}

const LabelElement: FC<LabelElementProps> = ({ team, hideLabel }) => (
  <div
    style={{
      display: 'flex',
      justifyContent: hideLabel ? 'center' : 'flex-start',
      alignItems: 'center',
    }}
  >
    <ColorBox
      style={{
        width: '16px',
        height: '16px',
        marginRight: hideLabel ? undefined : '7px',
      }}
      id={Number(team.teamId)}
    />
    {!hideLabel && (team.teamRole || `Team ${team.teamId}`)}
    {team.inactive && (
      <Tag style={{ marginLeft: '1ch' }} minimal intent='warning'>
        inactive
      </Tag>
    )}
  </div>
)

export default LabelElement
Loading