diff --git a/src/components/GoalsGroup.tsx b/src/components/GoalsGroup.tsx index c7e8869c9..6332885d4 100644 --- a/src/components/GoalsGroup.tsx +++ b/src/components/GoalsGroup.tsx @@ -1,15 +1,11 @@ import React, { MouseEventHandler } from 'react'; import styled from 'styled-components'; -import NextLink from 'next/link'; -import { Text, Link, nullable } from '@taskany/bricks'; import { gapM, gapS } from '@taskany/colors'; -import { routes } from '../hooks/router'; import { GoalByIdReturnType } from '../../trpc/inferredTypes'; import { GoalListItem } from './GoalListItem'; import { PageSep } from './PageSep'; -import { ProjectTitleList } from './ProjectTitleList'; import { TableFullWidthCell } from './Table'; interface GoalGroupProps { @@ -33,27 +29,6 @@ const GolasGroupSep = styled(PageSep)` margin: ${gapS} 0px; `; -interface GoalsGroupProjectTitleProps { - id: string; - title: string; - parent?: Array<{ id: string; title: string }>; -} - -export const GoalsGroupProjectTitle: React.FC = ({ id, title, parent }) => ( - - {Boolean(parent?.length) && - nullable(parent, (p) => ( - <> - - {' / '} - - ))} - - {title} - - -); - export const GoalsGroup: React.FC = React.memo( ({ goals, children, selectedResolver, onClickProvider, onTagClick }) => ( <> diff --git a/src/components/GoalsPage/GoalsPage.tsx b/src/components/GoalsPage/GoalsPage.tsx index 1e8a79bb0..52fbdbefd 100644 --- a/src/components/GoalsPage/GoalsPage.tsx +++ b/src/components/GoalsPage/GoalsPage.tsx @@ -3,7 +3,6 @@ import React, { MouseEventHandler, useCallback, useEffect, useState } from 'reac import dynamic from 'next/dynamic'; import { useRouter } from 'next/router'; import { nullable, Button } from '@taskany/bricks'; -import { Project } from '@prisma/client'; import { refreshInterval } from '../../utils/config'; import { ExternalPageProps } from '../../utils/declareSsrProps'; @@ -11,15 +10,17 @@ import { ModalEvent, dispatchModalEvent } from '../../utils/dispatchModal'; import { createFilterKeys } from '../../utils/hotkeys'; import { useUrlFilterParams } from '../../hooks/useUrlFilterParams'; import { useFilterResource } from '../../hooks/useFilterResource'; +import { routes } from '../../hooks/router'; import { Page, PageContent } from '../Page'; import { CommonHeader } from '../CommonHeader'; import { FiltersPanel } from '../FiltersPanel/FiltersPanel'; -import { GoalsGroup, GoalsGroupProjectTitle } from '../GoalsGroup'; +import { GoalsGroup } from '../GoalsGroup'; import { GoalsListContainer } from '../GoalListItem'; import { PageTitle } from '../PageTitle'; import { Nullish } from '../../types/void'; import { trpc } from '../../utils/trpcClient'; -import { FilterById, GoalByIdReturnType } from '../../../trpc/inferredTypes'; +import { FilterById, GoalByIdReturnType, ProjectByIdReturnType } from '../../../trpc/inferredTypes'; +import { ProjectItemStandalone } from '../ProjectListItem'; import { tr } from './GoalsPage.i18n'; @@ -74,8 +75,7 @@ export const GoalsPage = ({ user, ssrTime, locale }: ExternalPageProps) => { // eslint-disable-next-line no-spaced-func (goals as NonNullable[])?.reduce<{ [key: string]: { - // eslint-disable-next-line func-call-spacing - project?: (Project & { parent?: Project[] }) | null; + project?: ProjectByIdReturnType | null; goals: NonNullable[]; }; }>((r, g) => { @@ -235,10 +235,14 @@ export const GoalsPage = ({ user, ssrTime, locale }: ExternalPageProps) => { onClickProvider={onGoalPrewiewShow} onTagClick={setTagsFilterOutside} > - ), diff --git a/src/components/ProjectListItem.tsx b/src/components/ProjectListItem.tsx index e95bb3805..99bc73d8e 100644 --- a/src/components/ProjectListItem.tsx +++ b/src/components/ProjectListItem.tsx @@ -31,20 +31,18 @@ export const ProjectListItem: React.FC = ({ - + {title} + {nullable(owner, (o) => ( ))} - - {nullable(participants, (p) => ( - - ))} - + + {nullable(participants, (p) => (p.length ? : null))} {nullable(starred, () => ( @@ -60,3 +58,9 @@ export const ProjectListItem: React.FC = ({ ); + +export const ProjectItemStandalone: React.FC = (props) => ( + + + +); diff --git a/src/components/ProjectPage/ProjectPage.tsx b/src/components/ProjectPage/ProjectPage.tsx index 07ceda3bf..f97b980f6 100644 --- a/src/components/ProjectPage/ProjectPage.tsx +++ b/src/components/ProjectPage/ProjectPage.tsx @@ -3,7 +3,6 @@ import { MouseEventHandler, useCallback, useEffect, useState } from 'react'; import { useRouter as useNextRouter } from 'next/router'; import dynamic from 'next/dynamic'; import { Button, nullable } from '@taskany/bricks'; -import { Project } from '@prisma/client'; import { refreshInterval } from '../../utils/config'; import { ExternalPageProps } from '../../utils/declareSsrProps'; @@ -13,15 +12,17 @@ import { useUrlFilterParams } from '../../hooks/useUrlFilterParams'; import { useLocalStorage } from '../../hooks/useLocalStorage'; import { useFilterResource } from '../../hooks/useFilterResource'; import { useWillUnmount } from '../../hooks/useWillUnmount'; +import { routes } from '../../hooks/router'; import { ProjectPageLayout } from '../ProjectPageLayout/ProjectPageLayout'; import { Page, PageContent } from '../Page'; -import { GoalsGroup, GoalsGroupProjectTitle } from '../GoalsGroup'; +import { GoalsGroup } from '../GoalsGroup'; import { PageTitle } from '../PageTitle'; import { createFilterKeys } from '../../utils/hotkeys'; import { Nullish } from '../../types/void'; import { trpc } from '../../utils/trpcClient'; -import { FilterById, GoalByIdReturnType } from '../../../trpc/inferredTypes'; +import { FilterById, GoalByIdReturnType, ProjectByIdReturnType } from '../../../trpc/inferredTypes'; import { GoalsListContainer } from '../GoalListItem'; +import { ProjectItemStandalone } from '../ProjectListItem'; import { tr } from './ProjectPage.i18n'; @@ -82,8 +83,7 @@ export const ProjectPage = ({ user, locale, ssrTime, params: { id } }: ExternalP // eslint-disable-next-line no-spaced-func (projectDeepInfo?.goals as NonNullable[])?.reduce<{ [key: string]: { - // eslint-disable-next-line func-call-spacing - project?: (Project & { parent?: Project[] }) | null; + project?: ProjectByIdReturnType | null; goals: NonNullable[]; }; }>((r, g) => { @@ -273,10 +273,14 @@ export const ProjectPage = ({ user, locale, ssrTime, params: { id } }: ExternalP onClickProvider={onGoalPrewiewShow} onTagClick={setTagsFilterOutside} > - ), diff --git a/src/components/Table.tsx b/src/components/Table.tsx index bea74e822..98388a1e6 100644 --- a/src/components/Table.tsx +++ b/src/components/Table.tsx @@ -1,5 +1,6 @@ import styled from 'styled-components'; import { gapS, gapSm, gray4, radiusM, textColor } from '@taskany/colors'; +import React from 'react'; export const Table = styled.div<{ columns: number }>` display: grid; @@ -31,7 +32,7 @@ export const TableCell = styled.div<{ align?: 'center' | 'left' | 'right' }>` text-align: ${({ align = 'left' }) => align}; box-sizing: border-box; - padding: ${gapS} ${gapS}; + padding: ${({ children }) => (React.Children.count(children) ? gapS : 0)}; &:last-child { white-space: nowrap; diff --git a/trpc/queries/goals.ts b/trpc/queries/goals.ts index 69e3f6710..416769652 100644 --- a/trpc/queries/goals.ts +++ b/trpc/queries/goals.ts @@ -247,11 +247,39 @@ export const goalDeepQuery = { project: { include: { parent: true, + tags: true, flow: { include: { states: true, }, }, + activity: { + include: { + user: true, + ghost: true, + }, + }, + participants: { + include: { + user: true, + ghost: true, + }, + }, + stargizers: true, + watchers: true, + children: { + include: { + parent: true, + }, + }, + _count: { + select: { + stargizers: true, + watchers: true, + participants: true, + children: true, + }, + }, }, }, dependsOn: { diff --git a/trpc/router/goal.ts b/trpc/router/goal.ts index 7ead8ccee..b74061858 100644 --- a/trpc/router/goal.ts +++ b/trpc/router/goal.ts @@ -28,6 +28,8 @@ import { connectionMap } from '../queries/connections'; import { createGoal, changeGoalProject, getGoalHistory, findOrCreateEstimate } from '../../src/utils/db'; import { createEmailJob } from '../../src/utils/worker/create'; +import { addCalculatedProjectFields } from './project'; + export const goal = router({ suggestions: protectedProcedure.input(z.string()).query(async ({ input }) => { const splittedInput = input.split('-'); @@ -187,6 +189,7 @@ export const goal = router({ return { ...goal, ...addCalclulatedGoalsFields(goal, ctx.session.user.activityId), + project: goal.project ? addCalculatedProjectFields(goal.project, ctx.session.user.activityId) : null, estimate: getEstimateListFormJoin(goal), history, }; @@ -284,7 +287,9 @@ export const goal = router({ }, }, }), - prisma.goal.findMany({ + prisma.goal.findMany<{ + include: typeof goalDeepQuery; + }>({ ...goalsFilter(input, ctx.session.user.activityId, { ...userDashboardGoals, }), @@ -307,6 +312,7 @@ export const goal = router({ ...g, ...addCalclulatedGoalsFields(g, ctx.session.user.activityId), estimate: getEstimateListFormJoin(g), + project: g.project ? addCalculatedProjectFields(g.project, ctx.session.user.activityId) : null, })), meta: calcGoalsMeta(allUserGoals), }; @@ -481,6 +487,7 @@ export const goal = router({ return { ...goal, ...addCalclulatedGoalsFields(goal, ctx.session.user.activityId), + project: goal.project ? addCalculatedProjectFields(goal.project, ctx.session.user.activityId) : null, estimate: getEstimateListFormJoin(goal), }; diff --git a/trpc/router/project.ts b/trpc/router/project.ts index a72d31fa2..f2f492a0f 100644 --- a/trpc/router/project.ts +++ b/trpc/router/project.ts @@ -21,7 +21,9 @@ import { connectionMap } from '../queries/connections'; type WithId = { id: string }; -const addCalculatedProjectFields = ( +export const addCalculatedProjectFields = < + T extends { watchers?: WithId[]; stargizers?: WithId[]; activityId?: string }, +>( project: T, activityId: string, ): T & { @@ -31,7 +33,7 @@ const addCalculatedProjectFields = { const _isWatching = project.watchers?.some((watcher: any) => watcher.id === activityId); const _isStarred = project.stargizers?.some((stargizer: any) => stargizer.id === activityId); - const _isOwner = project.ownerId === activityId; + const _isOwner = project.activityId === activityId; return { ...project, @@ -211,7 +213,7 @@ export const project = router({ }, }, }), - prisma.goal.findMany({ + prisma.goal.findMany<{ include: typeof goalDeepQuery }>({ ...goalsFilter(input, ctx.session.user.activityId, { AND: { OR: [ @@ -247,6 +249,7 @@ export const project = router({ return { goals: filtredProjectGoals.map((g) => ({ ...g, + project: g.project ? addCalculatedProjectFields(g.project, ctx.session.user.activityId) : g.project, ...addCalclulatedGoalsFields(g, ctx.session.user.activityId), estimate: getEstimateListFormJoin(g), })),