From bbe65d8110e1670761041a7a8ed5a130099c7fea Mon Sep 17 00:00:00 2001 From: Maksim Sviridov Date: Wed, 11 Sep 2024 13:59:31 +0300 Subject: [PATCH] feat(ExternalTask): view history changes --- .../HistoryRecord/HistoryRecord.i18n/en.json | 3 + .../HistoryRecord/HistoryRecord.i18n/ru.json | 3 + .../HistoryRecord/HistoryRecord.tsx | 88 +++++++++++++++---- trpc/queries/history.ts | 29 +++++- 4 files changed, 103 insertions(+), 20 deletions(-) diff --git a/src/components/HistoryRecord/HistoryRecord.i18n/en.json b/src/components/HistoryRecord/HistoryRecord.i18n/en.json index 2a1b4b295..583759f20 100644 --- a/src/components/HistoryRecord/HistoryRecord.i18n/en.json +++ b/src/components/HistoryRecord/HistoryRecord.i18n/en.json @@ -15,6 +15,7 @@ "dependencies": "dependencies", "criteria": "", "goal as criteria": "goal", + "task as criteria": "task", "marked criteria": "", "priority": "priority", "from": "from", @@ -25,6 +26,8 @@ "as criteria": "", "goal complete": "completed goal", "goal in progress": "returns goal to work", + "task complete": "completed task", + "task in progress": "returns task to work", "partner project": "", "author and more made changes in": "{author} and {count} more made changes in{space}{subject}", "author and the other author made changes in": "{author} and {oneMoreAuthor} made changes in{space}{subject}", diff --git a/src/components/HistoryRecord/HistoryRecord.i18n/ru.json b/src/components/HistoryRecord/HistoryRecord.i18n/ru.json index 121258e10..5d2e7cdcf 100644 --- a/src/components/HistoryRecord/HistoryRecord.i18n/ru.json +++ b/src/components/HistoryRecord/HistoryRecord.i18n/ru.json @@ -15,6 +15,7 @@ "dependencies": "зависимости", "criteria": "критерий", "goal as criteria": "цель", + "task as criteria": "задача", "marked criteria": "отметил(а) критерий", "priority": "приоритет", "from": "с", @@ -25,6 +26,8 @@ "as criteria": "как критерий", "goal complete": "выполнил(а) цель", "goal in progress": "вернул(а) цель в работу", + "task complete": "выполнил(а) задачу", + "task in progress": "вернул(а) задачу в работу", "partner project": "партнерский проект", "author and more made changes in": "{author} и еще {count} внесли изменения в{space}{subject}", "author and the other author made changes in": "{author} и {oneMoreAuthor} внесли изменения в{space}{subject}", diff --git a/src/components/HistoryRecord/HistoryRecord.tsx b/src/components/HistoryRecord/HistoryRecord.tsx index 820002094..7ea4483c2 100644 --- a/src/components/HistoryRecord/HistoryRecord.tsx +++ b/src/components/HistoryRecord/HistoryRecord.tsx @@ -9,6 +9,7 @@ import { Goal, Ghost, Priority, + ExternalTask, } from '@prisma/client'; import { nullable } from '@taskany/bricks'; import { @@ -31,6 +32,7 @@ import { getUserName, prepareUserDataFromActivity, safeUserData } from '../../ut import { UserBadge } from '../UserBadge/UserBadge'; import { ProjectBadge } from '../ProjectBadge'; import { getStateProps, GoalBadge } from '../GoalBadge'; +import { JiraTaskBadge } from '../JiraTaskBadge/JiraTaskBadge'; import { routes } from '../../hooks/router'; import { State } from '../State'; @@ -42,10 +44,13 @@ type WholeSubject = | 'estimate' | 'description' | 'priority' - | 'goalAsCriteria' | 'criteriaState' | 'goalComplete' | 'goalInProgress' + | 'goalAsCriteria' + | 'taskComplete' + | 'taskInProgress' + | 'taskAsCriteria' | keyof HistoryRecordSubject; interface HistoryRecordInnerProps { @@ -151,10 +156,13 @@ const useHistoryTranslates = () => { priority: tr('priority'), criteria: tr('criteria'), partnerProject: tr('partner project'), - goalAsCriteria: tr('goal as criteria'), criteriaState: tr('marked criteria'), + goalAsCriteria: tr('goal as criteria'), goalComplete: tr('goal complete'), goalInProgress: tr('goal in progress'), + taskAsCriteria: tr('task as criteria'), + taskComplete: tr('task complete'), + taskInProgress: tr('task in progress'), complete: '', uncomplete: '', }; @@ -402,21 +410,35 @@ const HistoryRecordParticipant: React.FC< type CriteriaItem = GoalAchieveCriteria & { criteriaGoal: (Goal & { state?: StateData }) | null; + externalTask: ExternalTask | null; strike?: boolean; }; -const HistoryRecordCriteriaItem: React.FC = ({ criteriaGoal, title, strike }) => { +const HistoryRecordCriteriaItem: React.FC = ({ criteriaGoal, externalTask, title, strike }) => { if (criteriaGoal) { return ( - <> - - + + ); + } + + if (externalTask) { + return ( + ); } @@ -427,6 +449,19 @@ const HistoryRecordCriteriaItem: React.FC = ({ criteriaGoal, title ); }; +const trKeyMap: Record<'criteriaGoal' | 'externalTask', Record<'default' | 'inProgress' | 'complete', WholeSubject>> = { + criteriaGoal: { + default: 'goalAsCriteria', + inProgress: 'goalInProgress', + complete: 'goalComplete', + }, + externalTask: { + default: 'taskAsCriteria', + inProgress: 'taskInProgress', + complete: 'taskComplete', + }, +}; + const HistoryRecordCriteria: React.FC< HistoryChangeProps & { action: HistoryRecordAction; @@ -440,14 +475,22 @@ const HistoryRecordCriteria: React.FC< useEffect(() => { recordCtx.setSubjectText((prev) => { const target = from || to; - if (target?.criteriaGoal != null) { + const translateMap = + // eslint-disable-next-line no-nested-ternary + target?.criteriaGoal != null + ? trKeyMap.criteriaGoal + : target?.externalTask != null + ? trKeyMap.externalTask + : null; + + if (translateMap) { if (isChangeAction) { if (action === 'complete') { - return 'goalComplete'; + return translateMap.complete; } - return 'goalInProgress'; + return translateMap.inProgress; } - return 'goalAsCriteria'; + return translateMap.default; } if (isChangeAction) { @@ -467,7 +510,7 @@ const HistoryRecordCriteria: React.FC< to={nullable(to, (val) => ( <> - {val?.criteriaGoal && {tr('as criteria')}} + {val?.criteriaGoal && {tr('as criteria')}} {nullable(isChangeAction, () => ( {' '} @@ -480,7 +523,16 @@ const HistoryRecordCriteria: React.FC< ); }; -type OuterSubjects = Exclude; +type BanSubjects = + | 'goalAsCriteria' + | 'criteriaState' + | 'goalComplete' + | 'goalInProgress' + | 'taskAsCriteria' + | 'taskComplete' + | 'taskInProgress'; + +type OuterSubjects = Exclude; /** * let it be like this, with `any` props annotation diff --git a/trpc/queries/history.ts b/trpc/queries/history.ts index 85d915827..8c9143d8e 100644 --- a/trpc/queries/history.ts +++ b/trpc/queries/history.ts @@ -2,7 +2,16 @@ import { sql } from 'kysely'; import { db } from '../connection/kysely'; import { ExtractTypeFromGenerated } from '../utils'; -import { Goal, GoalAchieveCriteria, GoalHistory, Priority, Project, State, Tag } from '../../generated/kysely/types'; +import { + Goal, + GoalAchieveCriteria, + GoalHistory, + Priority, + Project, + State, + Tag, + ExternalTask, +} from '../../generated/kysely/types'; import { Activity, getUserActivity } from './activity'; import { tagQuery } from './tag'; @@ -50,7 +59,8 @@ export interface HistoryRecordMeta { owner: Activity; participants: Activity; state: ExtractTypeFromGenerated; - criteria: ExtractTypeFromGenerated & { criteriaGoal: ExtendedGoal }; + criteria: ExtractTypeFromGenerated & + ({ criteriaGoal: ExtendedGoal } | { externalTask: ExtractTypeFromGenerated }); partnerProject: ExtractTypeFromGenerated; priority: ExtractTypeFromGenerated; title: string; @@ -180,6 +190,14 @@ export const extraDataForEachRecord = async ( () => goalBaseQuery().as('criteriaGoal'), (join) => join.onRef('GoalAchieveCriteria.criteriaGoalId', '=', 'criteriaGoal.id'), ) + .leftJoinLateral( + ({ selectFrom }) => + selectFrom('ExternalTask') + .selectAll() + .whereRef('GoalAchieveCriteria.externalTaskId', '=', 'ExternalTask.id') + .as('externalTask'), + (join) => join.onTrue(), + ) .selectAll('GoalAchieveCriteria') .select((eb) => [ eb @@ -189,6 +207,13 @@ export const extraDataForEachRecord = async ( .else(null) .end() .as('criteriaGoal'), + eb + .case() + .when('GoalAchieveCriteria.externalTaskId', 'is not', null) + .then(sql`to_json("externalTask")`) + .else(null) + .end() + .as('externalTask'), ]) .where('GoalAchieveCriteria.id', 'in', ids) .$castTo();