Skip to content

Commit

Permalink
fix(Kanban,GoalTableList): data mapping to props
Browse files Browse the repository at this point in the history
  • Loading branch information
LamaEats committed Aug 12, 2024
1 parent a004ce3 commit 06c3588
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 174 deletions.
66 changes: 19 additions & 47 deletions src/components/DashboardPage/DashboardPage.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { ComponentProps, useCallback, useEffect, useMemo } from 'react';
import React, { useCallback, useEffect, useMemo } from 'react';
import { nullable } from '@taskany/bricks';
import { ListView, TreeViewElement } from '@taskany/bricks/harmony';

Expand All @@ -9,7 +9,6 @@ import { useUrlFilterParams } from '../../hooks/useUrlFilterParams';
import { useFiltersPreset } from '../../hooks/useFiltersPreset';
import { GoalByIdReturnType } from '../../../trpc/inferredTypes';
import { trpc } from '../../utils/trpcClient';
import { buildKanban } from '../../utils/kanban';
import { getPageTitle } from '../../utils/getPageTitle';
import { Page } from '../Page/Page';
import { useGoalPreview } from '../GoalPreview/GoalPreviewProvider';
Expand All @@ -18,10 +17,10 @@ import { LoadMoreButton } from '../LoadMoreButton/LoadMoreButton';
import { InlineCreateGoalControl } from '../InlineCreateGoalControl/InlineCreateGoalControl';
import { ProjectListItemCollapsable } from '../ProjectListItemCollapsable/ProjectListItemCollapsable';
import { routes } from '../../hooks/router';
import { GoalTableList } from '../GoalTableList/GoalTableList';
import { GoalTableList, mapToRenderProps } from '../GoalTableList/GoalTableList';
import { PresetModals } from '../PresetModals';
import { FiltersPanel } from '../FiltersPanel/FiltersPanel';
import { Kanban } from '../Kanban/Kanban';
import { Kanban, buildKanban } from '../Kanban/Kanban';
import { safeUserData } from '../../utils/getUserName';

import { tr } from './DashboardPage.i18n';
Expand Down Expand Up @@ -55,8 +54,14 @@ export const DashboardPage = ({ user, ssrTime, defaultPresetFallback }: External
return acc;
}, []);

const canbans = gr.reduce<Record<string, ComponentProps<typeof Kanban>['value']>>((acum, project) => {
acum[project.id] = buildKanban(project.goals ?? []);
const canbans = gr.reduce<Record<string, React.ComponentProps<typeof Kanban>['value']>>((acum, project) => {
acum[project.id] = buildKanban(project.goals ?? [], (goal) => ({
...goal,
shortId: goal._shortId,
id: goal.id,
commentsCount: goal._count.comments ?? 0,
progress: goal._achivedCriteriaWeight,
}));

return acum;
}, {});
Expand Down Expand Up @@ -125,47 +130,14 @@ export const DashboardPage = ({ user, ssrTime, defaultPresetFallback }: External
nullable(goals, (g) => (
<TreeViewElement>
<GoalTableList
goals={g.map(
({
_shortId,
_counts,
_achivedCriteriaWeight,
title,
id,
participants,
owner,
tags,
state,
updatedAt,
priority,
partnershipProjects,
estimate,
estimateType,
projectId,
project: parent,
}) => ({
title,
id,
shortId: _shortId,
commentsCount: _counts?.comments,
tags,
updatedAt,
owner: safeUserData(owner),
participants: participants?.map(safeUserData),
state,
estimate: estimate
? {
value: estimate,
type: estimateType,
}
: null,
priority: priority.title,
achievedCriteriaWeight: _achivedCriteriaWeight,
partnershipProjects,
isInPartnerProject: project.id !== projectId,
project: parent,
}),
)}
goals={mapToRenderProps(g, (goal) => ({
...goal,
shortId: goal._shortId,
commentsCount: goal._count.comments,
owner: safeUserData(goal.owner),
participants: goal.participants?.map(safeUserData),
achievedCriteriaWeight: goal._achivedCriteriaWeight,
}))}
/>
</TreeViewElement>
)),
Expand Down
47 changes: 10 additions & 37 deletions src/components/FlatGoalList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import { useUrlFilterParams } from '../hooks/useUrlFilterParams';
import { trpc } from '../utils/trpcClient';
import { refreshInterval } from '../utils/config';
import { useFMPMetric } from '../utils/telemetry';
import { GoalByIdReturnType } from '../../trpc/inferredTypes';
import { FilterById, GoalByIdReturnType } from '../../trpc/inferredTypes';
import { safeUserData } from '../utils/getUserName';

import { GoalTableList } from './GoalTableList/GoalTableList';
import { GoalTableList, mapToRenderProps } from './GoalTableList/GoalTableList';
import { useGoalPreview } from './GoalPreview/GoalPreviewProvider';
import { LoadMoreButton } from './LoadMoreButton/LoadMoreButton';

Expand Down Expand Up @@ -74,41 +74,14 @@ export const FlatGoalList: React.FC<GoalListProps> = ({ filterPreset }) => {
<ListView onKeyboardClick={handleItemEnter}>
{nullable(goalsOnScreen, (goals) => (
<GoalTableList
goals={goals.map(
({
_shortId,
_count,
_achivedCriteriaWeight,
title,
id,
participants,
owner,
tags,
state,
updatedAt,
priority,
estimate,
estimateType,
}) => ({
title,
id,
shortId: _shortId,
commentsCount: _count?.comments,
tags,
updatedAt,
owner: safeUserData(owner),
participants: participants?.map(safeUserData),
state,
estimate: estimate
? {
value: estimate,
type: estimateType,
}
: null,
priority: priority?.title,
achievedCriteriaWeight: _achivedCriteriaWeight,
}),
)}
goals={mapToRenderProps(goals, (goal) => ({
...goal,
owner: safeUserData(goal.owner),
participants: goal.participants?.map(safeUserData),
shortId: goal._shortId,
commentsCount: goal._count.comments,
achievedCriteriaWeight: goal._achivedCriteriaWeight,
}))}
onTagClick={setTagsFilterOutside}
/>
))}
Expand Down
26 changes: 26 additions & 0 deletions src/components/GoalTableList/GoalTableList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { MouseEventHandler, useCallback, useEffect, useMemo } from 'react';
import { nullable } from '@taskany/bricks';
import { IconGitBranchOutline, IconMessageTextOutline } from '@taskany/icons';

import { DateType } from '../../../generated/kysely/types';
import { State as StateType } from '../../../trpc/inferredTypes';
import { TableListItem, TableListItemElement } from '../TableListItem/TableListItem';
import { safeUserData } from '../../utils/getUserName';
Expand Down Expand Up @@ -234,3 +235,28 @@ export const GoalTableList = <T extends GoalTableListItem>({
</Table>
);
};

type GoalSource = IdentifierRecord & {
priority: IdentifierRecord | null;
estimate: Date | null;
estimateType: DateType | null;
[key: string]: unknown;
};

export function mapToRenderProps<T extends GoalSource>(
goals: T[],
mapper: <T1 extends T>(val: T1 & Pick<GoalTableListItem, 'priority' | 'estimate'>) => GoalTableListItem,
): GoalTableListItem[] {
return goals.map((v) =>
mapper({
...v,
priority: v.priority?.title,
estimate: v.estimate
? {
value: v.estimate,
type: v.estimateType,
}
: null,
}),
);
}
2 changes: 1 addition & 1 deletion src/components/GoalsKanbanCard/GoalsKanbanCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ interface GoalsKanbanCardProps extends HTMLAttributes<HTMLDivElement> {
owner?: ActivityByIdReturnType | null;
estimate?: Date | null;
estimateType?: DateType | null;
tags?: TagObject[];
tags?: TagObject[] | null;
onTagClick?: (tag: { id: string }) => MouseEventHandler<HTMLDivElement>;
priority?: Priority | null;
progress: number | null;
Expand Down
66 changes: 42 additions & 24 deletions src/components/Kanban/Kanban.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { MouseEventHandler, useCallback } from 'react';
import React, { MouseEventHandler, useCallback } from 'react';
import { KanbanColumn, KanbanContainer } from '@taskany/bricks/harmony';

import { trpc } from '../../utils/trpcClient';
import { FilterById, DashboardGoal } from '../../../trpc/inferredTypes';
import { FilterById } from '../../../trpc/inferredTypes';
import { useUrlFilterParams } from '../../hooks/useUrlFilterParams';
import { NextLink } from '../NextLink';
import { State as KanbanState } from '../State';
Expand All @@ -12,12 +12,17 @@ import { routes } from '../../hooks/router';

import s from './Kanban.module.css';

interface KanbanProps<T> {
value: Record<string, T[]>;
type KanbanItemProps = Omit<
React.ComponentProps<typeof GoalsKanbanCard>,
keyof React.HTMLAttributes<HTMLDivElement>
> & { id: string; shortId: string; title: string };

interface KanbanProps {
value: Record<string, KanbanItemProps[]>;
filterPreset?: FilterById;
}

export const Kanban = <T extends NonNullable<DashboardGoal>>({ value, filterPreset }: KanbanProps<T>) => {
export const Kanban = ({ value, filterPreset }: KanbanProps) => {
const { data: states = [] } = trpc.state.all.useQuery();

const { queryState, setTagsFilterOutside } = useUrlFilterParams({
Expand Down Expand Up @@ -54,30 +59,18 @@ export const Kanban = <T extends NonNullable<DashboardGoal>>({ value, filterPres
<KanbanColumn key={state.id}>
<KanbanState className={s.KanbanState} state={state} />

{goals.map((g) => {
const { project: _, ...goal } = g;

{goals.map((goal) => {
return (
<NextLink
key={goal.id}
href={routes.goal(goal._shortId)}
onClick={onGoalPreviewShow(goal)}
href={routes.goal(goal.shortId)}
onClick={onGoalPreviewShow({
_shortId: goal.shortId,
title: goal.title,
})}
className={s.KanbanLink}
>
<GoalsKanbanCard
id={goal.id}
key={goal.id}
commentsCount={goal._count.comments || 0}
title={goal.title}
updatedAt={goal.updatedAt}
owner={goal.owner}
estimate={goal.estimate}
estimateType={goal.estimateType}
tags={goal.tags}
onTagClick={setTagsFilterOutside}
priority={goal.priority}
progress={goal._achivedCriteriaWeight}
/>
<GoalsKanbanCard {...goal} onTagClick={setTagsFilterOutside} />
</NextLink>
);
})}
Expand All @@ -87,3 +80,28 @@ export const Kanban = <T extends NonNullable<DashboardGoal>>({ value, filterPres
</KanbanContainer>
);
};

type StateIdRecord = Record<'stateId', string>;

type NullableStateId = StateIdRecord | Record<'stateId', null>;

export const buildKanban = <T extends NullableStateId, M extends (val: T) => KanbanItemProps>(
goals: T[],
mapper: M,
): Record<StateIdRecord['stateId'], KanbanItemProps[]> => {
return goals.reduce<Record<StateIdRecord['stateId'], KanbanItemProps[]>>((acum, goal) => {
const stateKey = goal.stateId;

if (!stateKey) {
return acum;
}

if (!acum[stateKey]) {
acum[stateKey] = [];
}

acum[stateKey].push(mapper(goal));

return acum;
}, {});
};
Loading

0 comments on commit 06c3588

Please sign in to comment.