Commit 639bf185 authored by Patrik Kotucek's avatar Patrik Kotucek
Browse files

feat: add new recipients tag and translation

parent 6199dc5d
Loading
Loading
Loading
Loading
+38 −0
Original line number Diff line number Diff line
import { Tag } from '@blueprintjs/core'
import { css, cx } from '@emotion/css'
import type { ITodoLogActionLog } from '@inject/graphql'
import { useTranslationFrontend } from '@inject/locale'
import type { FC } from 'react'

export const EmailRecipientsTag: FC<{
  actionLog: ITodoLogActionLog
  className?: string
}> = ({ actionLog, className }) => {
  const { t } = useTranslationFrontend()
  if (actionLog.details.__typename !== 'IEmailType') {
    return null
  }
  const { sender } = actionLog.details

  const recipients = actionLog.details.thread.participants.filter(
    participant => participant.address !== sender.address
  )

  return (
    <Tag
      className={cx(
        css`
          margin-right: 0.25rem;
          display: inline-flex;
          align-items: center;
          vertical-align: middle;
        `,
        className
      )}
      round
      icon='envelope'
    >
      {t('overview.todoList.email.recipients', { count: recipients.length })}
    </Tag>
  )
}
+60 −42
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@ import {
  useTypedMutation,
  useTypedQuery,
} from '@inject/graphql'
import { useTranslationFrontend } from '@inject/locale'
import type { LinkButtonProps } from '@inject/shared'
import { EmailSelection, LinkButton, Timestamp } from '@inject/shared'
import type { NavigateOptions } from '@tanstack/react-router'
@@ -19,8 +20,46 @@ import { InstructorToolChannelActionLogRoute } from '../../routes/_protected/ins
import { InstructorEmailThreadPageRoute } from '../../routes/_protected/instructor/$exerciseId/$teamId/email/$tab/$threadId'
import { canBeReviewed, getIcon } from '../../utils'
import { QuestionnaireStatus } from '../InstructorQuestionnaire/QuestionnaireStatus'
import { EmailRecipientsTag } from './EmailRecipientsTag'
import { OverviewPillNav } from './OverviewPillNav'

const recipientRow = css`
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 0.25rem 0.5rem;
  align-items: center;
  padding: 0.2rem 0.35rem;
  border-radius: 3px;
  background: rgba(255, 255, 255, 0.03);
`

const recipientAddress = css`
  font-weight: 600;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
`

const recipientMeta = css`
  display: inline-flex;
  gap: 0.25rem;
  flex-wrap: wrap;
  justify-content: flex-end;
`

const recipientDescription = css`
  grid-column: 1 / -1;
  font-size: 12px;
`

const topMetaRow = css`
  display: flex;
  align-items: center;
  gap: 0.3rem;
  flex-wrap: wrap;
`

const getTitle = (actionLog: ITodoLogActionLog): string => {
  switch (actionLog.details.__typename) {
    case 'IEmailType':
@@ -251,40 +290,11 @@ const recipientList = css`
  }
`

const recipientRow = css`
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 0.25rem 0.5rem;
  align-items: center;
  padding: 0.2rem 0.35rem;
  border-radius: 3px;
  background: rgba(255, 255, 255, 0.03);
`

const recipientAddress = css`
  font-weight: 600;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
`

const recipientMeta = css`
  display: inline-flex;
  gap: 0.25rem;
  flex-wrap: wrap;
  justify-content: flex-end;
`

const recipientDescription = css`
  grid-column: 1 / -1;
  font-size: 12px;
`

const EmailLogItemContent: FC<{
  actionLog: ITodoLogActionLog
  milestoneStates: MilestoneState[]
}> = ({ actionLog, milestoneStates }) => {
  const { t } = useTranslationFrontend()
  if (actionLog.details.__typename !== 'IEmailType') {
    return null
  }
@@ -306,12 +316,17 @@ const EmailLogItemContent: FC<{
          <div key={recipient.address} className={recipientRow}>
            <div className={recipientAddress}>{recipient.address}</div>
            <div className={recipientMeta}>
              <Tag minimal>{`Templates: ${recipient.templateCount}`}</Tag>
              <Tag minimal>{`${t('overview.todoList.email.templates', {
                count: recipient.templateCount,
              })}`}</Tag>
              {recipient.totalMilestonesCount !== undefined && (
                <Tag
                  minimal
                  intent='primary'
                >{`Milestones: ${recipient.pendingMilestonesCount}/${recipient.totalMilestonesCount}`}</Tag>
                <Tag minimal intent='primary'>{`${t(
                  'overview.todoList.email.milestones',
                  {
                    count: recipient.pendingMilestonesCount,
                    total: recipient.totalMilestonesCount,
                  }
                )}`}</Tag>
              )}
            </div>
            {recipient.description && (
@@ -450,19 +465,22 @@ const LogItem: FC<LogItemProps> = ({
        >
          {getTitle(actionLog)}
        </h5>
        <div className={topMetaRow}>
          <OverviewPillNav actionLog={actionLog} />
        {questionnaireStatus && (
          <QuestionnaireStatus
            teamStateStatus={questionnaireStatus}
            canBeReviewed={canBeReviewed(actionLog.details)}
          />
        )}
          <EmailRecipientsTag actionLog={actionLog} />
          <Timestamp
            formatTimestampProps={{
              timestamp: actionLog.timestamp,
              inExerciseTime: actionLog.inExerciseTime,
            }}
          />
        </div>
        {questionnaireStatus && (
          <QuestionnaireStatus
            teamStateStatus={questionnaireStatus}
            canBeReviewed={canBeReviewed(actionLog.details)}
          />
        )}
        <LogItemContent
          actionLog={actionLog}
          milestoneStates={milestoneStates ?? []}
+12 −8
Original line number Diff line number Diff line
import { Tag } from '@blueprintjs/core'
import { css } from '@emotion/css'
import { css, cx } from '@emotion/css'
import type { ITodoLogActionLog } from '@inject/graphql'
import { getColorScheme } from '@inject/shared'
import { useNavigate } from '@tanstack/react-router'
@@ -8,16 +8,20 @@ import { InstructorTeamLandingPageRoute } from '../../routes/_protected/instruct

export const OverviewPillNav: FC<{
  actionLog: ITodoLogActionLog
}> = ({ actionLog }) => {
  className?: string
}> = ({ actionLog, className }) => {
  const nav = useNavigate()
  return (
    <Tag
      className={css`
      className={cx(
        css`
          margin-right: 0.25rem;
          &:hover {
            cursor: pointer;
          }
      `}
        `,
        className
      )}
      title='Click to enter team overview'
      onClick={() => {
        nav({
+6 −1
Original line number Diff line number Diff line
@@ -514,7 +514,12 @@
      "done": "Dokončeno",
      "notDone": "Nedokončeno",
      "notFoundTitle": "Žádné injecty",
      "notFoundDescription": "Nebyly nalezeny žádné injecty, které by mohly být zobrazeny v téhle kategorii. Prosím počkejte na nové"
      "notFoundDescription": "Nebyly nalezeny žádné injecty, které by mohly být zobrazeny v téhle kategorii. Prosím počkejte na nové",
      "email": {
        "templates": "Šablony: {{count}}",
        "milestones": "Milníky: {{count}}/{{total}}",
        "recipients": "Příjemci: {{count}}"
      }
    },
    "instructorComments": {
      "title": "Komentáře od instruktorů",
+6 −1
Original line number Diff line number Diff line
@@ -514,7 +514,12 @@
      "done": "Done",
      "notDone": "Not done",
      "notFoundTitle": "No inject items",
      "notFoundDescription": "There are no log items that can be shown in this category. Please await for new injects"
      "notFoundDescription": "There are no log items that can be shown in this category. Please await for new injects",
      "email": {
        "templates": "Templates: {{count}}",
        "milestones": "Milestones: {{count}}/{{total}}",
        "recipients": "Recipients: {{count}}"
      }
    },
    "instructorComments": {
      "title": "Instructor comments",