Verified Commit 3e256d68 authored by Marek Veselý's avatar Marek Veselý
Browse files

refactor: use cache for previous logs

parent 163f1dd1
Loading
Loading
Loading
Loading
+43 −13
Original line number Diff line number Diff line
import { Classes, Colors } from '@blueprintjs/core'
import { Classes, Colors, Spinner, SpinnerSize } from '@blueprintjs/core'
import { css } from '@emotion/css'
import type { IAnalystActionLogSimple } from '@inject/graphql'
import type { FC } from 'react'
import type { Client } from '@inject/graphql'
import { useClient, type IAnalystActionLogSimple } from '@inject/graphql'
import { useEffect, useState, type FC } from 'react'
import {
  getConfirmationTextForConfirmationLog,
  getInjectNameForConfirmationLog,
  getQuestionnaireNameForReviewLog,
  getQuestionnaireNameForSubmissionLog,
} from '../utilities'
} from '../getDetailsFromPreviousLog'

const activated = css`
  color: ${Colors.GREEN2};
@@ -23,31 +24,44 @@ const deactivated = css`
  }
`

interface ActionLogContentProps {
const getActionLogContent = async (
  client: Client,
  actionLog: IAnalystActionLogSimple
}

export const ActionLogContent: FC<ActionLogContentProps> = ({ actionLog }) => {
): Promise<JSX.Element> => {
  switch (actionLog.details.__typename) {
    case 'IToolDetailsType':
      return <>{actionLog.details.tool.displayName}</>
    case 'IInjectDetailsType':
      return <>{actionLog.details.inject.displayName}</>
    case 'IConfirmationDetailsType': {
      const injectName = getInjectNameForConfirmationLog(actionLog)
      const confirmationText = getConfirmationTextForConfirmationLog(actionLog)
      return `${injectName} confirmation${confirmationText ? `: "${confirmationText}"` : ''}`
      const injectName = await getInjectNameForConfirmationLog(
        client,
        actionLog
      )
      const confirmationText = await getConfirmationTextForConfirmationLog(
        client,
        actionLog
      )
      return (
        <>{`${injectName} confirmation${confirmationText ? `: "${confirmationText}"` : ''}`}</>
      )
    }
    case 'ICustomInjectDetailsType':
      return <>custom inject</>
    case 'IEmailType':
      return <>{actionLog.details.thread.subject}</>
    case 'IQuestionnaireReviewDetailsType': {
      const questionnaireName = getQuestionnaireNameForReviewLog(actionLog)
      const questionnaireName = await getQuestionnaireNameForReviewLog(
        client,
        actionLog
      )
      return <>{questionnaireName} reviewed</>
    }
    case 'IQuestionnaireSubmissionType': {
      const questionnaireName = getQuestionnaireNameForSubmissionLog(actionLog)
      const questionnaireName = await getQuestionnaireNameForSubmissionLog(
        client,
        actionLog
      )
      return <>{questionnaireName} submitted</>
    }
    case 'ITeamQuestionnaireStateType':
@@ -80,3 +94,19 @@ export const ActionLogContent: FC<ActionLogContentProps> = ({ actionLog }) => {
      return <>{actionLog.details.cmd}</>
  }
}

interface ActionLogContentProps {
  actionLog: IAnalystActionLogSimple
}

export const ActionLogContent: FC<ActionLogContentProps> = ({ actionLog }) => {
  const client = useClient()

  const [content, setContent] = useState<JSX.Element>()

  useEffect(() => {
    getActionLogContent(client, actionLog).then(setContent)
  }, [actionLog, client])

  return content ? content : <Spinner size={SpinnerSize.SMALL} />
}
+50 −14
Original line number Diff line number Diff line
import type { IAnalystActionLogSimple } from '@inject/graphql'
import type { FC } from 'react'
import { Spinner, SpinnerSize } from '@blueprintjs/core'
import {
  useClient,
  type Client,
  type IAnalystActionLogSimple,
} from '@inject/graphql'
import { useEffect, useState, type FC } from 'react'
import {
  getConfirmationTextForConfirmationLog,
  getInjectNameForConfirmationLog,
  getQuestionnaireNameForReviewLog,
  getQuestionnaireNameForSubmissionLog,
} from '../utilities'
} from '../getDetailsFromPreviousLog'

interface ActionLogDescriptionProps {
const getActionLogDescription = async (
  client: Client,
  actionLog: IAnalystActionLogSimple
}

export const ActionLogDescription: FC<ActionLogDescriptionProps> = ({
  actionLog,
}) => {
): Promise<JSX.Element> => {
  switch (actionLog.details.__typename) {
    case 'IToolDetailsType':
      return (
@@ -30,8 +32,14 @@ export const ActionLogDescription: FC<ActionLogDescriptionProps> = ({
        </>
      )
    case 'IConfirmationDetailsType': {
      const injectName = getInjectNameForConfirmationLog(actionLog)
      const confirmationText = getConfirmationTextForConfirmationLog(actionLog)
      const injectName = await getInjectNameForConfirmationLog(
        client,
        actionLog
      )
      const confirmationText = await getConfirmationTextForConfirmationLog(
        client,
        actionLog
      )
      return (
        <>
          The <b>{injectName}</b> inject was <b>confirmed</b> by a trainee
@@ -60,7 +68,10 @@ export const ActionLogDescription: FC<ActionLogDescriptionProps> = ({
      )
    }
    case 'IQuestionnaireReviewDetailsType': {
      const questionnaireName = getQuestionnaireNameForReviewLog(actionLog)
      const questionnaireName = await getQuestionnaireNameForReviewLog(
        client,
        actionLog
      )
      return (
        <>
          The <b>{questionnaireName}</b> was <b>reviewed</b> by an instructor
@@ -68,7 +79,10 @@ export const ActionLogDescription: FC<ActionLogDescriptionProps> = ({
      )
    }
    case 'IQuestionnaireSubmissionType': {
      const questionnaireName = getQuestionnaireNameForSubmissionLog(actionLog)
      const questionnaireName = await getQuestionnaireNameForSubmissionLog(
        client,
        actionLog
      )
      return (
        <>
          The <b>{questionnaireName}</b> was submitted by a trainee, the answers
@@ -153,7 +167,7 @@ export const ActionLogDescription: FC<ActionLogDescriptionProps> = ({
        )
      }

      return 'Milestones were modified'
      return <>Milestones were modified</>
    }
    case 'ISandboxLogDetailsType':
      return (
@@ -164,3 +178,25 @@ export const ActionLogDescription: FC<ActionLogDescriptionProps> = ({
      )
  }
}

interface ActionLogDescriptionProps {
  actionLog: IAnalystActionLogSimple
}

export const ActionLogDescription: FC<ActionLogDescriptionProps> = ({
  actionLog,
}) => {
  const client = useClient()

  const [description, setDescription] = useState<JSX.Element>()

  useEffect(() => {
    const fetchDescription = async () => {
      const description = await getActionLogDescription(client, actionLog)
      setDescription(description)
    }
    fetchDescription()
  }, [actionLog, client])

  return description ?? <Spinner size={SpinnerSize.SMALL} />
}
+102 −0
Original line number Diff line number Diff line
import type {
  Client,
  IAnalystActionLogSimple,
  IAnalystPreviousActionLog,
  LogType,
  ResultOf,
  VariablesOf,
} from '@inject/graphql'
import { AnalystPreviousActionLogQuery } from '@inject/graphql'

const getPreviousLog = async (client: Client, logId: string) => {
  const { data } = await client.query<
    ResultOf<typeof AnalystPreviousActionLogQuery>,
    VariablesOf<typeof AnalystPreviousActionLogQuery>
  >(AnalystPreviousActionLogQuery, {
    logId,
  })
  return data?.actionLog
}
const getDetailsFromPreviousLog = async ({
  client,
  actionLog,
  previousLogType,
  getDetails,
}: {
  client: Client
  actionLog: IAnalystActionLogSimple
  previousLogType: LogType
  getDetails: (previousLog: IAnalystPreviousActionLog) => string | undefined
}) => {
  const previousLogId = actionLog.previousLogs.find(
    log => log.logType === previousLogType
  )?.id
  if (!previousLogId) {
    throw new Error('getDetailsFromPreviousLog could not find previousLogId')
  }
  const previousLog = await getPreviousLog(client, previousLogId)
  if (!previousLog) {
    throw new Error('getDetailsFromPreviousLog could not find previousLog')
  }
  const details =
    previousLog?.__typename === 'IActionLogType'
      ? getDetails(previousLog)
      : undefined
  if (!details) {
    throw new Error('getDetailsFromPreviousLog could not find details')
  }
  return details
}

export const getInjectNameForConfirmationLog = (
  client: Client,
  actionLog: IAnalystActionLogSimple
) =>
  getDetailsFromPreviousLog({
    client,
    actionLog,
    previousLogType: 'INJECT',
    getDetails: previousLog =>
      previousLog.details.__typename === 'IInjectDetailsType'
        ? previousLog.details.inject.displayName
        : undefined,
  })
export const getConfirmationTextForConfirmationLog = (
  client: Client,
  actionLog: IAnalystActionLogSimple
) =>
  getDetailsFromPreviousLog({
    client,
    actionLog,
    previousLogType: 'INJECT',
    getDetails: previousLog =>
      previousLog.details.__typename === 'IInjectDetailsType'
        ? previousLog.details.confirmation?.text
        : undefined,
  })
export const getQuestionnaireNameForSubmissionLog = (
  client: Client,
  actionLog: IAnalystActionLogSimple
) =>
  getDetailsFromPreviousLog({
    client,
    actionLog,
    previousLogType: 'FORM',
    getDetails: previousLog =>
      previousLog.details.__typename === 'ITeamQuestionnaireStateType'
        ? previousLog.details.questionnaire.displayName
        : undefined,
  })
export const getQuestionnaireNameForReviewLog = (
  client: Client,
  actionLog: IAnalystActionLogSimple
) =>
  getDetailsFromPreviousLog({
    client,
    actionLog,
    previousLogType: 'FORM_SUBMISSION',
    getDetails: previousLog =>
      previousLog.details.__typename === 'IQuestionnaireSubmissionType'
        ? previousLog.details.teamQuestionnaireState.questionnaire.displayName
        : undefined,
  })
+0 −85
Original line number Diff line number Diff line
@@ -154,88 +154,3 @@ export const plotDataElement = css`
    opacity: 1;
  }
`

// TODO: add inject to confirmation log on BE instead?
export const getInjectNameForConfirmationLog = (
  actionLog: IAnalystActionLogSimple
) => {
  if (actionLog.details.__typename !== 'IConfirmationDetailsType') {
    throw new Error(
      'getInjectNameForConfirmationLog called with non-confirmation log'
    )
  }

  const prevLog = actionLog.previousLogs.find(
    prevLog =>
      prevLog.__typename === 'IActionLogType' &&
      prevLog.details.__typename === 'IInjectDetailsType'
  )
  return prevLog?.__typename === 'IActionLogType' &&
    prevLog.details.__typename === 'IInjectDetailsType'
    ? prevLog.details.inject.displayName
    : 'inject'
}
// TODO: add confirmation to confirmation log on BE instead?
export const getConfirmationTextForConfirmationLog = (
  actionLog: IAnalystActionLogSimple
) => {
  if (actionLog.details.__typename !== 'IConfirmationDetailsType') {
    throw new Error(
      'getConfirmationTextForConfirmationLog called with non-confirmation log'
    )
  }
  const prevLog = actionLog.previousLogs.find(
    prevLog =>
      prevLog.__typename === 'IActionLogType' &&
      prevLog.details.__typename === 'IInjectDetailsType'
  )
  return prevLog?.__typename === 'IActionLogType' &&
    prevLog.details.__typename === 'IInjectDetailsType'
    ? prevLog.details.confirmation?.text
    : undefined
}
// TODO: add questionnaire to review log on BE instead?
export const getQuestionnaireNameForSubmissionLog = (
  actionLog: IAnalystActionLogSimple
) => {
  if (actionLog.details.__typename !== 'IQuestionnaireSubmissionType') {
    throw new Error(
      'getQuestionnaireNameForSubmissionLog called with non-submission log'
    )
  }

  const prevLog = actionLog.previousLogs.find(
    prevLog =>
      prevLog.__typename === 'IActionLogType' &&
      prevLog.details.__typename === 'ITeamQuestionnaireStateType'
  )
  return prevLog?.__typename === 'IActionLogType' &&
    prevLog.details.__typename === 'ITeamQuestionnaireStateType'
    ? prevLog.details.questionnaire.displayName
    : 'questionnaire'
}
// TODO: add questionnaire to review log on BE instead?
export const getQuestionnaireNameForReviewLog = (
  actionLog: IAnalystActionLogSimple
) => {
  if (actionLog.details.__typename !== 'IQuestionnaireReviewDetailsType') {
    throw new Error(
      'getQuestionnaireNameForReviewLog called with non-review log'
    )
  }

  const prevLog = actionLog.previousLogs.find(
    prevLog =>
      prevLog.__typename === 'IActionLogType' &&
      prevLog.details.__typename === 'IQuestionnaireSubmissionType'
  )
  const prevPrevLog = prevLog?.previousLogs.find(
    prevPrevLog =>
      prevPrevLog.__typename === 'IActionLogType' &&
      prevPrevLog.details.__typename === 'ITeamQuestionnaireStateType'
  )
  return prevPrevLog?.__typename === 'IActionLogType' &&
    prevPrevLog.details.__typename === 'ITeamQuestionnaireStateType'
    ? prevPrevLog.details.questionnaire.displayName
    : 'questionnaire'
}
+2 −0
Original line number Diff line number Diff line
@@ -136,6 +136,8 @@ export type NoticeboardMessage = FragmentOf<typeof allFragments['NoticeboardMess
export type LLMAssessment = FragmentOf<typeof allFragments['LLMAssessment']>;
export type IAnalystActionLogSimple = FragmentOf<typeof allFragments['IAnalystActionLogSimple']>;
export type AnalystActionLogSimple = FragmentOf<typeof allFragments['AnalystActionLogSimple']>;
export type IAnalystPreviousActionLog = FragmentOf<typeof allFragments['IAnalystPreviousActionLog']>;
export type AnalystPreviousActionLog = FragmentOf<typeof allFragments['AnalystPreviousActionLog']>;
export type IAnalystActionLogTree = FragmentOf<typeof allFragments['IAnalystActionLogTree']>;
export type AnalystActionLogTree = FragmentOf<typeof allFragments['AnalystActionLogTree']>;
export type IAnalystToolUsageTool = FragmentOf<typeof allFragments['IAnalystToolUsageTool']>;
Loading