Skip to content

Commit

Permalink
chore(ProjectListItemCollapsable): remove Goals button
Browse files Browse the repository at this point in the history
  • Loading branch information
asabotovich committed Aug 4, 2023
1 parent 02f06a8 commit 6651a4d
Show file tree
Hide file tree
Showing 12 changed files with 118 additions and 151 deletions.
45 changes: 29 additions & 16 deletions src/components/CollapsableItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const StyledCollapsableHeader = styled.div`

const StyledCollapsableItem = styled.div`
position: relative;
padding-bottom: 1px;
&:before {
content: '';
Expand All @@ -56,7 +57,7 @@ const StyledHeaderContent = styled.div<{ highlighted?: boolean }>`
`}
`;

const StyledCollapsableContainer = styled.div<{ collapsed: boolean; deep: number }>`
const StyledCollapsableContainer = styled.div<{ collapsed: boolean; deep: number; hasChild: boolean }>`
position: relative;
border-radius: ${radiusM};
Expand Down Expand Up @@ -85,8 +86,9 @@ const StyledCollapsableContainer = styled.div<{ collapsed: boolean; deep: number
padding-left: ${collapseOffset}px;
`}
${({ collapsed, deep }) =>
${({ collapsed, deep, hasChild }) =>
!collapsed &&
hasChild &&
css`
padding-left: ${collapseOffset}px;
margin-left: ${deep === 0 ? -collapseOffset : 0}px;
Expand Down Expand Up @@ -143,29 +145,40 @@ const StyledCollapsableContainer = styled.div<{ collapsed: boolean; deep: number
margin-left: -${collapseOffset}px;
}
> ${StyledCollapsableItem}:before {
/** show grey line for additional content section (for example goals list) if it's not last item. See design :) */
// TODO: Remove this here https://github.com/taskany-inc/issues/issues/1448
> ${StyledCollapsableItem}:not(:last-child):before {
display: block;
}
`}
`;

export const CollapsableContentItem: FC<{
children?: ReactNode;
className?: string;
}> = ({ children, className }) => <StyledCollapsableItem className={className}>{children}</StyledCollapsableItem>;

export const CollapsableItem: FC<{
children?: ReactNode;
onClick?: () => void;
header: ReactNode;
content: ReactNode;
deep?: number;
collapsed: boolean;
}> = ({ onClick, children, header, collapsed, deep = 0, content }) => (
<StyledCollapsableContainer collapsed={collapsed} deep={deep}>
<StyledCollapsableHeader onClick={onClick}>
<StyledParentDot />
<StyledDot />
<StyledHeaderContent highlighted={!!onClick && collapsed}>{header}</StyledHeaderContent>
</StyledCollapsableHeader>
{nullable(children, (ch) => (
<StyledCollapsableItem>{ch}</StyledCollapsableItem>
))}
{!collapsed ? content : null}
</StyledCollapsableContainer>
);
hasChild: boolean;
}> = ({ onClick, children, header, collapsed, deep = 0, hasChild, content }) => {
return (
<StyledCollapsableContainer collapsed={collapsed} deep={deep} hasChild={hasChild}>
<StyledCollapsableHeader onClick={onClick}>
<StyledParentDot />
<StyledDot />
<StyledHeaderContent highlighted={!!onClick && collapsed}>{header}</StyledHeaderContent>
</StyledCollapsableHeader>
{nullable(children, (ch) => (
<StyledCollapsableItem>{ch}</StyledCollapsableItem>
))}
{!collapsed ? content : null}
</StyledCollapsableContainer>
);
};
3 changes: 1 addition & 2 deletions src/components/CommonHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ interface CommonHeaderProps {
}

const StyledCommonHeader = styled(PageContent)`
display: grid;
grid-template-columns: 8fr 4fr;
width: calc(2 / 3 * 100%);
`;

const StyledCommonHeaderInfo = styled.div<{ align: 'left' | 'right' }>`
Expand Down
1 change: 1 addition & 0 deletions src/components/ProjectListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ interface ProjectListItemProps {
className?: string;
disabled?: boolean;
averageScore: number | null;
onClick?: (e: React.MouseEvent) => void;
}

const StyledTitleCell = styled(TableCell)`
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,68 +1,51 @@
import React, { MouseEvent, ReactNode, useCallback, useMemo } from 'react';
import NextLink from 'next/link';
import React, { MouseEvent, ReactNode, useMemo } from 'react';
import styled from 'styled-components';
import { Badge, Button, ExternalLinkIcon, Link, Text, nullable } from '@taskany/bricks';
import { gapS, gray7, gray4, radiusM } from '@taskany/colors';
import NextLink from 'next/link';
import { gapXs, gray4, radiusM } from '@taskany/colors';
import { Text, nullable } from '@taskany/bricks';
import { IconServersOutline } from '@taskany/icons';

import { ProjectByIdReturnType } from '../../../trpc/inferredTypes';
import { GoalsListContainer } from '../GoalListItem';
import { CollapsableItem, collapseOffset } from '../CollapsableItem';
import { CollapsableItem, CollapsableContentItem, collapseOffset } from '../CollapsableItem';
import { ProjectListContainer, ProjectListItem } from '../ProjectListItem';

import { tr } from './ProjectListItemCollapsable.i18n';

const StyledNoGoals = styled(Text)`
white-space: nowrap;
`;

const StyledProjectListItemActionsContainer = styled.div`
display: flex;
align-items: center;
`;

const StyledProjectListItemAction = styled.div<{ forceVisibility?: boolean }>`
visibility: ${({ forceVisibility }) => (forceVisibility ? 'visible' : 'hidden')};
margin-left: ${gapS};
&:first-child {
margin-left: 0;
}
`;

const StyledProjectListItem = styled(ProjectListItem)`
&:hover {
${StyledProjectListItemAction} {
visibility: visible;
}
}
`;

const StyledGoalsListContainer = styled(GoalsListContainer)`
background-color: ${gray4};
border-radius: ${radiusM};
margin: 0px;
padding: 0px;
`;

const StyledProjectIcons = styled.div`
display: flex;
align-items: center;
gap: ${gapXs};
`;

interface ProjectListItemCollapsableProps {
href?: string;
project: NonNullable<ProjectByIdReturnType>;
goals?: ReactNode;
children?: ReactNode;
collapsed: boolean;
collapsedGoals: boolean;
onClick?: () => void;
onGoalsClick?: () => void;
loading?: boolean;
deep?: number;
}

const onProjectClickHandler = (e: MouseEvent) => {
if (!e.metaKey && !e.ctrlKey) {
e.preventDefault();
} else {
e.stopPropagation();
}
};

export const ProjectListItemCollapsable: React.FC<ProjectListItemCollapsableProps> = ({
project,
collapsed = true,
collapsedGoals = true,
onClick,
onGoalsClick,
children,
goals,
loading = false,
Expand All @@ -71,69 +54,55 @@ export const ProjectListItemCollapsable: React.FC<ProjectListItemCollapsableProp
}) => {
const childs = useMemo(() => project.children.map(({ id }) => id), [project]);

const onClickEnabled = childs.length;
const contentHidden = !childs.length || collapsed || loading;
const contentHidden = collapsed || loading;

const offset = collapseOffset * (deep > 0 && contentHidden ? deep - 1 : deep);

const onGoalsButtonClick = useCallback(
(e: MouseEvent) => {
e.stopPropagation();

onGoalsClick?.();
},
[onGoalsClick],
const projectComponent = (
<ProjectListItem
as="a"
title={project.title}
owner={project.activity}
participants={project.participants}
starred={project._isStarred}
watching={project._isWatching}
averageScore={project.averageScore}
onClick={onProjectClickHandler}
>
{nullable(childs.length, (c) => (
<StyledProjectIcons>
<IconServersOutline size="xs" />
<Text size="xs">{c}</Text>
</StyledProjectIcons>
))}
</ProjectListItem>
);

const onExternalLinkClick = useCallback((e: MouseEvent) => {
e.stopPropagation();
}, []);

return (
<CollapsableItem
collapsed={contentHidden}
onClick={onClickEnabled ? onClick : undefined}
onClick={onClick}
hasChild={!!childs.length}
header={
<ProjectListContainer offset={offset}>
<StyledProjectListItem
title={project.title}
owner={project.activity}
participants={project.participants}
starred={project._isStarred}
watching={project._isWatching}
disabled={!onClickEnabled}
averageScore={project.averageScore}
>
<StyledProjectListItemActionsContainer>
<StyledProjectListItemAction forceVisibility={!collapsedGoals}>
{project._count.goals ? (
<Button
ghost={collapsedGoals}
onClick={onGoalsButtonClick}
text={tr('Goals')}
iconRight={<Badge size="s">{project._count.goals}</Badge>}
/>
) : (
<StyledNoGoals color={gray7}>{tr('No goals')}</StyledNoGoals>
)}
</StyledProjectListItemAction>
<StyledProjectListItemAction>
{nullable(href, (h) => (
<NextLink href={h} passHref legacyBehavior>
<Link inline target="_blank" onClick={onExternalLinkClick}>
<ExternalLinkIcon size="s" />
</Link>
</NextLink>
))}
</StyledProjectListItemAction>
</StyledProjectListItemActionsContainer>
</StyledProjectListItem>
{href ? (
<NextLink href={href} passHref legacyBehavior>
{projectComponent}
</NextLink>
) : (
projectComponent
)}
</ProjectListContainer>
}
content={children}
content={
<>
<CollapsableContentItem>
<StyledGoalsListContainer offset={offset}>{goals}</StyledGoalsListContainer>
</CollapsableContentItem>
{children}
</>
}
deep={deep}
>
{!collapsedGoals && <StyledGoalsListContainer offset={offset}>{goals}</StyledGoalsListContainer>}
</CollapsableItem>
></CollapsableItem>
);
};
16 changes: 6 additions & 10 deletions src/components/ProjectListItemConnected.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ export const ProjectListItemConnected: FC<{
selectedResolver?: (id: string) => boolean;
deep?: number;
collapsed?: boolean;
collapsedGoals?: boolean;
hasLink?: boolean;
}> = ({
hasLink = false,
Expand All @@ -28,18 +27,16 @@ export const ProjectListItemConnected: FC<{
selectedResolver,
deep = 0,
collapsed: defaultCollapsed = false,
collapsedGoals: defaultCollapsedGoals = false,
}) => {
const [collapsed, setIsCollapsed] = useState(defaultCollapsed);
const [collapsedGoals, setIsCollapsedGoals] = useState(defaultCollapsedGoals);

const { data: projectDeepInfo } = trpc.project.getDeepInfo.useQuery(
{
id: project.id,
goalsQuery: queryState,
},
{
enabled: !collapsedGoals,
enabled: !collapsed,
keepPreviousData: true,
staleTime: refreshInterval,
},
Expand All @@ -57,9 +54,11 @@ export const ProjectListItemConnected: FC<{
setIsCollapsed((value) => !value);
}, []);

const onGoalsClick = useCallback(() => {
setIsCollapsedGoals((value) => !value);
}, []);
// hide projects without goals

if (!project._count.goals) {
return null;
}

return (
<ProjectListItemCollapsable
Expand Down Expand Up @@ -91,9 +90,7 @@ export const ProjectListItemConnected: FC<{
))}
project={project}
collapsed={collapsed}
collapsedGoals={collapsedGoals}
onClick={onClick}
onGoalsClick={onGoalsClick}
loading={status === 'loading'}
deep={deep}
>
Expand All @@ -107,7 +104,6 @@ export const ProjectListItemConnected: FC<{
onTagClick={onTagClick}
onClickProvider={onClickProvider}
selectedResolver={selectedResolver}
collapsedGoals
collapsed
/>
))}
Expand Down
Loading

0 comments on commit 6651a4d

Please sign in to comment.