feat: projects can be set to public
This commit is contained in:
@ -58,12 +58,14 @@ type Props = {
|
||||
onCardTitleChange?: (name: string) => void;
|
||||
labelVariant?: CardLabelVariant;
|
||||
toggleLabels?: boolean;
|
||||
isPublic?: boolean;
|
||||
toggleDirection?: 'shrink' | 'expand';
|
||||
};
|
||||
|
||||
const Card = React.forwardRef(
|
||||
(
|
||||
{
|
||||
isPublic = false,
|
||||
wrapperProps,
|
||||
onContextMenu,
|
||||
taskID,
|
||||
@ -120,9 +122,11 @@ const Card = React.forwardRef(
|
||||
}
|
||||
};
|
||||
const onTaskContext = (e: React.MouseEvent) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
onOpenComposer();
|
||||
if (!isPublic) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
onOpenComposer();
|
||||
}
|
||||
};
|
||||
const onOperationClick = (e: React.MouseEvent<HTMLOrSVGElement>) => {
|
||||
e.preventDefault();
|
||||
@ -145,7 +149,7 @@ const Card = React.forwardRef(
|
||||
{...wrapperProps}
|
||||
>
|
||||
<ListCardInnerContainer ref={$innerCardRef}>
|
||||
{isActive && !editable && (
|
||||
{!isPublic && isActive && !editable && (
|
||||
<ListCardOperation
|
||||
onClick={e => {
|
||||
e.stopPropagation();
|
||||
|
@ -72,6 +72,9 @@ export const HeaderName = styled(TextareaAutosize)`
|
||||
box-shadow: none;
|
||||
font-weight: 600;
|
||||
margin: -4px 0;
|
||||
&:disabled {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
letter-spacing: normal;
|
||||
word-spacing: normal;
|
||||
|
@ -24,6 +24,7 @@ type Props = {
|
||||
onOpenComposer: (id: string) => void;
|
||||
wrapperProps?: any;
|
||||
headerProps?: any;
|
||||
isPublic: boolean;
|
||||
index?: number;
|
||||
onExtraMenuOpen: (taskGroupID: string, $targetRef: React.RefObject<HTMLElement>) => void;
|
||||
};
|
||||
@ -37,6 +38,7 @@ const List = React.forwardRef(
|
||||
isComposerOpen,
|
||||
onOpenComposer,
|
||||
children,
|
||||
isPublic,
|
||||
wrapperProps,
|
||||
headerProps,
|
||||
onExtraMenuOpen,
|
||||
@ -86,39 +88,37 @@ const List = React.forwardRef(
|
||||
<Container ref={$wrapperRef} {...wrapperProps}>
|
||||
<Wrapper>
|
||||
<Header {...headerProps} isEditing={isEditingTitle}>
|
||||
<HeaderEditTarget onClick={onClick} isHidden={isEditingTitle} />
|
||||
{!isPublic && <HeaderEditTarget onClick={onClick} isHidden={isEditingTitle} />}
|
||||
<HeaderName
|
||||
ref={$listNameRef}
|
||||
disabled={isPublic}
|
||||
onBlur={onBlur}
|
||||
onChange={onChange}
|
||||
onKeyDown={onKeyDown}
|
||||
spellCheck={false}
|
||||
value={listName}
|
||||
/>
|
||||
<ListExtraMenuButtonWrapper ref={$extraActionsRef} onClick={handleExtraMenuOpen}>
|
||||
<Ellipsis size={16} color="#c2c6dc" />
|
||||
</ListExtraMenuButtonWrapper>
|
||||
{!isPublic && (
|
||||
<ListExtraMenuButtonWrapper ref={$extraActionsRef} onClick={handleExtraMenuOpen}>
|
||||
<Ellipsis size={16} color="#c2c6dc" />
|
||||
</ListExtraMenuButtonWrapper>
|
||||
)}
|
||||
</Header>
|
||||
{children && children}
|
||||
<AddCardContainer hidden={isComposerOpen}>
|
||||
<AddCardButton onClick={() => onOpenComposer(id)}>
|
||||
<Plus width={12} height={12} />
|
||||
<AddCardButtonText>Add another card</AddCardButtonText>
|
||||
</AddCardButton>
|
||||
</AddCardContainer>
|
||||
{!isPublic && (
|
||||
<AddCardContainer hidden={isComposerOpen}>
|
||||
<AddCardButton onClick={() => onOpenComposer(id)}>
|
||||
<Plus width={12} height={12} />
|
||||
<AddCardButtonText>Add another card</AddCardButtonText>
|
||||
</AddCardButton>
|
||||
</AddCardContainer>
|
||||
)}
|
||||
</Wrapper>
|
||||
</Container>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
List.defaultProps = {
|
||||
children: null,
|
||||
isComposerOpen: false,
|
||||
wrapperProps: {},
|
||||
headerProps: {},
|
||||
};
|
||||
|
||||
List.displayName = 'List';
|
||||
export default List;
|
||||
|
||||
|
@ -151,6 +151,7 @@ interface SimpleProps {
|
||||
onCardMemberClick: OnCardMemberClick;
|
||||
onCardLabelClick: () => void;
|
||||
cardLabelVariant: CardLabelVariant;
|
||||
isPublic?: boolean;
|
||||
taskStatusFilter?: TaskStatusFilter;
|
||||
taskMetaFilters?: TaskMetaFilters;
|
||||
taskSorting?: TaskSorting;
|
||||
@ -188,6 +189,7 @@ const SimpleLists: React.FC<SimpleProps> = ({
|
||||
onExtraMenuOpen,
|
||||
onCardMemberClick,
|
||||
taskStatusFilter = initTaskStatusFilter,
|
||||
isPublic = false,
|
||||
taskMetaFilters = initTaskMetaFilters,
|
||||
taskSorting = initTaskSorting,
|
||||
}) => {
|
||||
@ -300,6 +302,7 @@ const SimpleLists: React.FC<SimpleProps> = ({
|
||||
onOpenComposer={id => setCurrentComposer(id)}
|
||||
isComposerOpen={currentComposer === taskGroup.id}
|
||||
onSaveName={name => onChangeTaskGroupName(taskGroup.id, name)}
|
||||
isPublic={isPublic}
|
||||
ref={columnDragProvided.innerRef}
|
||||
wrapperProps={columnDragProvided.draggableProps}
|
||||
headerProps={columnDragProvided.dragHandleProps}
|
||||
@ -328,6 +331,7 @@ const SimpleLists: React.FC<SimpleProps> = ({
|
||||
<Card
|
||||
toggleDirection={toggleDirection}
|
||||
toggleLabels={toggleLabels}
|
||||
isPublic={isPublic}
|
||||
labelVariant={cardLabelVariant}
|
||||
wrapperProps={{
|
||||
...taskProvided.draggableProps,
|
||||
@ -396,11 +400,13 @@ const SimpleLists: React.FC<SimpleProps> = ({
|
||||
)}
|
||||
</Droppable>
|
||||
</DragDropContext>
|
||||
<AddList
|
||||
onSave={listName => {
|
||||
onCreateTaskGroup(listName);
|
||||
}}
|
||||
/>
|
||||
{!isPublic && (
|
||||
<AddList
|
||||
onSave={listName => {
|
||||
onCreateTaskGroup(listName);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</BoardWrapper>
|
||||
</BoardContainer>
|
||||
);
|
||||
|
@ -38,12 +38,17 @@ export const ListSeparator = styled.hr`
|
||||
`;
|
||||
|
||||
type Props = {
|
||||
publicOn: null | string;
|
||||
onDeleteProject: () => void;
|
||||
onToggleProjectVisible: (visible: boolean) => void;
|
||||
};
|
||||
const ProjectSettings: React.FC<Props> = ({ onDeleteProject }) => {
|
||||
const ProjectSettings: React.FC<Props> = ({ publicOn, onDeleteProject, onToggleProjectVisible }) => {
|
||||
return (
|
||||
<>
|
||||
<ListActionsWrapper>
|
||||
<ListActionItemWrapper onClick={() => onToggleProjectVisible(publicOn === null)}>
|
||||
<ListActionItem>{`Make ${publicOn === null ? 'public' : 'private'}`}</ListActionItem>
|
||||
</ListActionItemWrapper>
|
||||
<ListActionItemWrapper onClick={() => onDeleteProject()}>
|
||||
<ListActionItem>Delete Project</ListActionItem>
|
||||
</ListActionItemWrapper>
|
||||
@ -127,5 +132,18 @@ const DeleteConfirm: React.FC<DeleteConfirmProps> = ({ description, deletedItems
|
||||
);
|
||||
};
|
||||
|
||||
export { DeleteConfirm };
|
||||
type PublicConfirmProps = {
|
||||
onConfirm: () => void;
|
||||
};
|
||||
|
||||
const PublicConfirm: React.FC<PublicConfirmProps> = ({ onConfirm }) => {
|
||||
return (
|
||||
<ConfirmWrapper>
|
||||
<ConfirmDescription>Public projects can be accessed by anyone with a link to the project.</ConfirmDescription>
|
||||
<ConfirmDeleteButton onClick={() => onConfirm()}>Make public</ConfirmDeleteButton>
|
||||
</ConfirmWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export { DeleteConfirm, PublicConfirm };
|
||||
export default ProjectSettings;
|
||||
|
@ -69,7 +69,7 @@ const CommentCreator: React.FC<CommentCreatorProps> = ({
|
||||
)}
|
||||
<CommentEditorContainer>
|
||||
<CommentTextArea
|
||||
showCommentActions={showCommentActions}
|
||||
$showCommentActions={showCommentActions}
|
||||
placeholder="Write a comment..."
|
||||
ref={$comment}
|
||||
disabled={disabled}
|
||||
|
@ -80,40 +80,44 @@ import {
|
||||
ActivityItemHeaderTitleName,
|
||||
ActivityItemComment,
|
||||
} from './Styles';
|
||||
import { useCurrentUser } from 'App/context';
|
||||
|
||||
type TaskDetailsProps = {};
|
||||
|
||||
const TaskDetailsLoading: React.FC<TaskDetailsProps> = () => {
|
||||
const { user } = useCurrentUser();
|
||||
return (
|
||||
<Container>
|
||||
<LeftSidebar>
|
||||
<LeftSidebarContent>
|
||||
<LeftSidebarSection>
|
||||
<SidebarTitle>TASK GROUP</SidebarTitle>
|
||||
<SidebarButton loading>
|
||||
<SidebarButton $loading>
|
||||
<SidebarSkeleton />
|
||||
</SidebarButton>
|
||||
<DueDateTitle>DUE DATE</DueDateTitle>
|
||||
<SidebarButton loading>
|
||||
<SidebarButton $loading>
|
||||
<SidebarSkeleton />
|
||||
</SidebarButton>
|
||||
</LeftSidebarSection>
|
||||
<AssignedUsersSection>
|
||||
<DueDateTitle>MEMBERS</DueDateTitle>
|
||||
<SidebarButton loading>
|
||||
<SidebarButton $loading>
|
||||
<SidebarSkeleton />
|
||||
</SidebarButton>
|
||||
</AssignedUsersSection>
|
||||
<ExtraActionsSection>
|
||||
<DueDateTitle>ACTIONS</DueDateTitle>
|
||||
<ActionButton disabled icon={<Tags width={12} height={12} />}>
|
||||
Labels
|
||||
</ActionButton>
|
||||
<ActionButton disabled icon={<CheckSquareOutline width={12} height={12} />}>
|
||||
Checklist
|
||||
</ActionButton>
|
||||
<ActionButton disabled>Cover</ActionButton>
|
||||
</ExtraActionsSection>
|
||||
{user && (
|
||||
<ExtraActionsSection>
|
||||
<DueDateTitle>ACTIONS</DueDateTitle>
|
||||
<ActionButton disabled icon={<Tags width={12} height={12} />}>
|
||||
Labels
|
||||
</ActionButton>
|
||||
<ActionButton disabled icon={<CheckSquareOutline width={12} height={12} />}>
|
||||
Checklist
|
||||
</ActionButton>
|
||||
<ActionButton disabled>Cover</ActionButton>
|
||||
</ExtraActionsSection>
|
||||
)}
|
||||
</LeftSidebarContent>
|
||||
</LeftSidebar>
|
||||
<ContentContainer>
|
||||
@ -125,23 +129,25 @@ const TaskDetailsLoading: React.FC<TaskDetailsProps> = () => {
|
||||
<span>Mark complete</span>
|
||||
</MarkCompleteButton>
|
||||
</HeaderLeft>
|
||||
<HeaderRight>
|
||||
<HeaderActionIcon>
|
||||
<Paperclip width={16} height={16} />
|
||||
</HeaderActionIcon>
|
||||
<HeaderActionIcon>
|
||||
<Clone width={16} height={16} />
|
||||
</HeaderActionIcon>
|
||||
<HeaderActionIcon>
|
||||
<Share width={16} height={16} />
|
||||
</HeaderActionIcon>
|
||||
<HeaderActionIcon>
|
||||
<Trash width={16} height={16} />
|
||||
</HeaderActionIcon>
|
||||
</HeaderRight>
|
||||
{user && (
|
||||
<HeaderRight>
|
||||
<HeaderActionIcon>
|
||||
<Paperclip width={16} height={16} />
|
||||
</HeaderActionIcon>
|
||||
<HeaderActionIcon>
|
||||
<Clone width={16} height={16} />
|
||||
</HeaderActionIcon>
|
||||
<HeaderActionIcon>
|
||||
<Share width={16} height={16} />
|
||||
</HeaderActionIcon>
|
||||
<HeaderActionIcon>
|
||||
<Trash width={16} height={16} />
|
||||
</HeaderActionIcon>
|
||||
</HeaderRight>
|
||||
)}
|
||||
</HeaderInnerContainer>
|
||||
<TaskDetailsTitleWrapper loading>
|
||||
<TaskDetailsTitle value="" disabled loading />
|
||||
<TaskDetailsTitleWrapper $loading>
|
||||
<TaskDetailsTitle value="" disabled $loading />
|
||||
</TaskDetailsTitleWrapper>
|
||||
</HeaderContainer>
|
||||
<InnerContentContainer>
|
||||
@ -151,9 +157,11 @@ const TaskDetailsLoading: React.FC<TaskDetailsProps> = () => {
|
||||
</TabBarSection>
|
||||
<ActivitySection />
|
||||
</InnerContentContainer>
|
||||
<CommentContainer>
|
||||
<CommentCreator disabled onCreateComment={() => null} onMemberProfile={() => null} />
|
||||
</CommentContainer>
|
||||
{user && (
|
||||
<CommentContainer>
|
||||
<CommentCreator disabled onCreateComment={() => null} onMemberProfile={() => null} />
|
||||
</CommentContainer>
|
||||
)}
|
||||
</ContentContainer>
|
||||
</Container>
|
||||
);
|
||||
|
@ -108,7 +108,7 @@ export const skeletonKeyframes = keyframes`
|
||||
}
|
||||
`;
|
||||
|
||||
export const SidebarButton = styled.div<{ loading?: boolean }>`
|
||||
export const SidebarButton = styled.div<{ $loading?: boolean }>`
|
||||
font-size: 14px;
|
||||
color: ${props => props.theme.colors.text.primary};
|
||||
min-height: 32px;
|
||||
@ -116,7 +116,7 @@ export const SidebarButton = styled.div<{ loading?: boolean }>`
|
||||
border-radius: 6px;
|
||||
|
||||
${props =>
|
||||
props.loading
|
||||
props.$loading
|
||||
? css`
|
||||
background: ${props.theme.colors.bg.primary};
|
||||
`
|
||||
@ -178,15 +178,15 @@ export const HeaderLeft = styled.div`
|
||||
justify-content: flex-start;
|
||||
`;
|
||||
|
||||
export const TaskDetailsTitleWrapper = styled.div<{ loading?: boolean }>`
|
||||
export const TaskDetailsTitleWrapper = styled.div<{ $loading?: boolean }>`
|
||||
width: 100%;
|
||||
margin: 8px 0 4px 0;
|
||||
display: flex;
|
||||
border-radius: 6px;
|
||||
${props => props.loading && `background: ${props.theme.colors.bg.primary};`}
|
||||
${props => props.$loading && `background: ${props.theme.colors.bg.primary};`}
|
||||
`;
|
||||
|
||||
export const TaskDetailsTitle = styled(TextareaAutosize)<{ loading?: boolean }>`
|
||||
export const TaskDetailsTitle = styled(TextareaAutosize)<{ $loading?: boolean }>`
|
||||
padding: 9px 8px 7px 8px;
|
||||
border-color: transparent;
|
||||
border-radius: 6px;
|
||||
@ -198,8 +198,11 @@ export const TaskDetailsTitle = styled(TextareaAutosize)<{ loading?: boolean }>`
|
||||
font-weight: 700;
|
||||
background: none;
|
||||
|
||||
&:disabled {
|
||||
opacity: 1;
|
||||
}
|
||||
${props =>
|
||||
props.loading
|
||||
props.$loading
|
||||
? css`
|
||||
background-image: linear-gradient(90deg, ${defaultBaseColor}, ${defaultHighlightColor}, ${defaultBaseColor});
|
||||
background-size: 200px 100%;
|
||||
@ -207,7 +210,7 @@ export const TaskDetailsTitle = styled(TextareaAutosize)<{ loading?: boolean }>`
|
||||
animation: ${skeletonKeyframes} 1.2s ease-in-out infinite;
|
||||
`
|
||||
: css`
|
||||
&:hover {
|
||||
&:not(:disabled):hover {
|
||||
border-color: #414561;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
@ -534,7 +537,7 @@ export const CommentProfile = styled(TaskAssignee)`
|
||||
align-items: normal;
|
||||
`;
|
||||
|
||||
export const CommentTextArea = styled(TextareaAutosize)<{ showCommentActions: boolean }>`
|
||||
export const CommentTextArea = styled(TextareaAutosize)<{ $showCommentActions: boolean }>`
|
||||
width: 100%;
|
||||
line-height: 28px;
|
||||
padding: 4px 6px;
|
||||
@ -546,7 +549,7 @@ export const CommentTextArea = styled(TextareaAutosize)<{ showCommentActions: bo
|
||||
min-height: 36px;
|
||||
max-height: 36px;
|
||||
${props =>
|
||||
props.showCommentActions
|
||||
props.$showCommentActions
|
||||
? css`
|
||||
min-height: 80px;
|
||||
max-height: none;
|
||||
|
@ -83,6 +83,7 @@ import Checklist, { ChecklistItem, ChecklistItems } from '../Checklist';
|
||||
import onDragEnd from './onDragEnd';
|
||||
import { plugin as em } from './remark';
|
||||
import ActivityMessage from './ActivityMessage';
|
||||
import { useCurrentUser } from 'App/context';
|
||||
|
||||
const parseEmojis = (value: string) => {
|
||||
const emojisArray = toArray(value);
|
||||
@ -277,6 +278,7 @@ const TaskDetails: React.FC<TaskDetailsProps> = ({
|
||||
onToggleChecklistItem,
|
||||
onMemberProfile,
|
||||
}) => {
|
||||
const { user } = useCurrentUser();
|
||||
const [taskName, setTaskName] = useState(task.name);
|
||||
const [editTaskDescription, setEditTaskDescription] = useState(() => {
|
||||
if (task.description) {
|
||||
@ -338,7 +340,9 @@ const TaskDetails: React.FC<TaskDetailsProps> = ({
|
||||
<SidebarButton
|
||||
ref={$dueDateBtn}
|
||||
onClick={() => {
|
||||
onOpenDueDatePopop(task, $dueDateBtn);
|
||||
if (user) {
|
||||
onOpenDueDatePopop(task, $dueDateBtn);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{task.dueDate ? (
|
||||
@ -360,14 +364,18 @@ const TaskDetails: React.FC<TaskDetailsProps> = ({
|
||||
member={m}
|
||||
size={32}
|
||||
onMemberProfile={$target => {
|
||||
onMemberProfile($target, m.id);
|
||||
if (user) {
|
||||
onMemberProfile($target, m.id);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
<AssignUserIcon
|
||||
ref={$addMemberBtn}
|
||||
onClick={() => {
|
||||
onOpenAddMemberPopup(task, $addMemberBtn);
|
||||
if (user) {
|
||||
onOpenAddMemberPopup(task, $addMemberBtn);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Plus width={16} height={16} />
|
||||
@ -377,7 +385,9 @@ const TaskDetails: React.FC<TaskDetailsProps> = ({
|
||||
<AssignUsersButton
|
||||
ref={$noMemberBtn}
|
||||
onClick={() => {
|
||||
onOpenAddMemberPopup(task, $noMemberBtn);
|
||||
if (user) {
|
||||
onOpenAddMemberPopup(task, $noMemberBtn);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<AssignUserIcon>
|
||||
@ -387,26 +397,28 @@ const TaskDetails: React.FC<TaskDetailsProps> = ({
|
||||
</AssignUsersButton>
|
||||
)}
|
||||
</AssignedUsersSection>
|
||||
<ExtraActionsSection>
|
||||
<DueDateTitle>ACTIONS</DueDateTitle>
|
||||
<ActionButton
|
||||
onClick={$target => {
|
||||
onOpenAddLabelPopup(task, $target);
|
||||
}}
|
||||
icon={<Tags width={12} height={12} />}
|
||||
>
|
||||
Labels
|
||||
</ActionButton>
|
||||
<ActionButton
|
||||
onClick={$target => {
|
||||
onOpenAddChecklistPopup(task, $target);
|
||||
}}
|
||||
icon={<CheckSquareOutline width={12} height={12} />}
|
||||
>
|
||||
Checklist
|
||||
</ActionButton>
|
||||
<ActionButton>Cover</ActionButton>
|
||||
</ExtraActionsSection>
|
||||
{user && (
|
||||
<ExtraActionsSection>
|
||||
<DueDateTitle>ACTIONS</DueDateTitle>
|
||||
<ActionButton
|
||||
onClick={$target => {
|
||||
onOpenAddLabelPopup(task, $target);
|
||||
}}
|
||||
icon={<Tags width={12} height={12} />}
|
||||
>
|
||||
Labels
|
||||
</ActionButton>
|
||||
<ActionButton
|
||||
onClick={$target => {
|
||||
onOpenAddChecklistPopup(task, $target);
|
||||
}}
|
||||
icon={<CheckSquareOutline width={12} height={12} />}
|
||||
>
|
||||
Checklist
|
||||
</ActionButton>
|
||||
<ActionButton>Cover</ActionButton>
|
||||
</ExtraActionsSection>
|
||||
)}
|
||||
</LeftSidebarContent>
|
||||
</LeftSidebar>
|
||||
<ContentContainer>
|
||||
@ -414,34 +426,40 @@ const TaskDetails: React.FC<TaskDetailsProps> = ({
|
||||
<HeaderInnerContainer>
|
||||
<HeaderLeft>
|
||||
<MarkCompleteButton
|
||||
disabled={user === null}
|
||||
invert={task.complete ?? false}
|
||||
onClick={() => {
|
||||
onToggleTaskComplete(task);
|
||||
if (user) {
|
||||
onToggleTaskComplete(task);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Checkmark width={8} height={8} />
|
||||
<span>{task.complete ? 'Completed' : 'Mark complete'}</span>
|
||||
</MarkCompleteButton>
|
||||
</HeaderLeft>
|
||||
<HeaderRight>
|
||||
<HeaderActionIcon>
|
||||
<Paperclip width={16} height={16} />
|
||||
</HeaderActionIcon>
|
||||
<HeaderActionIcon>
|
||||
<Clone width={16} height={16} />
|
||||
</HeaderActionIcon>
|
||||
<HeaderActionIcon>
|
||||
<Share width={16} height={16} />
|
||||
</HeaderActionIcon>
|
||||
<HeaderActionIcon onClick={() => onDeleteTask(task)}>
|
||||
<Trash width={16} height={16} />
|
||||
</HeaderActionIcon>
|
||||
</HeaderRight>
|
||||
{user && (
|
||||
<HeaderRight>
|
||||
<HeaderActionIcon>
|
||||
<Paperclip width={16} height={16} />
|
||||
</HeaderActionIcon>
|
||||
<HeaderActionIcon>
|
||||
<Clone width={16} height={16} />
|
||||
</HeaderActionIcon>
|
||||
<HeaderActionIcon>
|
||||
<Share width={16} height={16} />
|
||||
</HeaderActionIcon>
|
||||
<HeaderActionIcon onClick={() => onDeleteTask(task)}>
|
||||
<Trash width={16} height={16} />
|
||||
</HeaderActionIcon>
|
||||
</HeaderRight>
|
||||
)}
|
||||
</HeaderInnerContainer>
|
||||
<TaskDetailsTitleWrapper>
|
||||
<TaskDetailsTitle
|
||||
value={taskName}
|
||||
ref={$detailsTitle}
|
||||
disabled={user === null}
|
||||
onKeyDown={e => {
|
||||
if (e.keyCode === 13) {
|
||||
e.preventDefault();
|
||||
@ -496,7 +514,7 @@ const TaskDetails: React.FC<TaskDetailsProps> = ({
|
||||
<Editor
|
||||
defaultValue={task.description ?? ''}
|
||||
theme={dark}
|
||||
readOnly={!editTaskDescription}
|
||||
readOnly={user === null || !editTaskDescription}
|
||||
autoFocus
|
||||
onChange={value => {
|
||||
setSaveTimeout(() => {
|
||||
@ -612,15 +630,15 @@ const TaskDetails: React.FC<TaskDetailsProps> = ({
|
||||
)}
|
||||
</ActivitySection>
|
||||
</InnerContentContainer>
|
||||
<CommentContainer>
|
||||
{me && (
|
||||
{me && (
|
||||
<CommentContainer>
|
||||
<CommentCreator
|
||||
me={me}
|
||||
onCreateComment={message => onCreateComment(task, message)}
|
||||
onMemberProfile={onMemberProfile}
|
||||
/>
|
||||
)}
|
||||
</CommentContainer>
|
||||
</CommentContainer>
|
||||
)}
|
||||
</ContentContainer>
|
||||
</Container>
|
||||
);
|
||||
|
63
frontend/src/shared/components/TopNavbar/LoggedOut.tsx
Normal file
63
frontend/src/shared/components/TopNavbar/LoggedOut.tsx
Normal file
@ -0,0 +1,63 @@
|
||||
import React, { useRef, useState, useEffect } from 'react';
|
||||
import { Home, Star, Bell, AngleDown, BarChart, CheckCircle, ListUnordered } from 'shared/icons';
|
||||
import { RoleCode } from 'shared/generated/graphql';
|
||||
import * as S from './Styles';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
export type MenuItem = {
|
||||
name: string;
|
||||
link: string;
|
||||
};
|
||||
|
||||
type NavBarProps = {
|
||||
menuType?: Array<MenuItem> | null;
|
||||
name: string | null;
|
||||
};
|
||||
|
||||
const NavBar: React.FC<NavBarProps> = ({ menuType, name }) => {
|
||||
return (
|
||||
<S.NavbarWrapper>
|
||||
<S.NavbarHeader>
|
||||
<S.ProjectActions>
|
||||
<S.ProjectSwitch>
|
||||
<S.ProjectSwitchInner>
|
||||
<S.TaskcafeLogo innerColor="#9f46e4" outerColor="#000" width={32} height={32} />
|
||||
</S.ProjectSwitchInner>
|
||||
</S.ProjectSwitch>
|
||||
<S.ProjectInfo>
|
||||
<S.ProjectMeta>{name && <S.ProjectName>{name}</S.ProjectName>}</S.ProjectMeta>
|
||||
{name && (
|
||||
<S.ProjectTabs>
|
||||
{menuType &&
|
||||
menuType.map((menu, idx) => {
|
||||
return (
|
||||
<S.ProjectTab
|
||||
key={menu.name}
|
||||
to={menu.link}
|
||||
exact
|
||||
onClick={() => {
|
||||
// TODO
|
||||
}}
|
||||
>
|
||||
{menu.name}
|
||||
</S.ProjectTab>
|
||||
);
|
||||
})}
|
||||
</S.ProjectTabs>
|
||||
)}
|
||||
</S.ProjectInfo>
|
||||
</S.ProjectActions>
|
||||
<S.LogoContainer to="/">
|
||||
<S.TaskcafeTitle>Taskcafé</S.TaskcafeTitle>
|
||||
</S.LogoContainer>
|
||||
<S.GlobalActions>
|
||||
<Link to="/login">
|
||||
<S.SignIn>Sign In</S.SignIn>
|
||||
</Link>
|
||||
</S.GlobalActions>
|
||||
</S.NavbarHeader>
|
||||
</S.NavbarWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export default NavBar;
|
@ -297,6 +297,16 @@ export const ProjectFinder = styled(Button)`
|
||||
padding: 6px 12px;
|
||||
`;
|
||||
|
||||
export const SignUp = styled(Button)`
|
||||
margin-right: 8px;
|
||||
padding: 6px 12px;
|
||||
`;
|
||||
|
||||
export const SignIn = styled(Button)`
|
||||
margin-right: 20px;
|
||||
padding: 6px 12px;
|
||||
`;
|
||||
|
||||
export const NavSeparator = styled.div`
|
||||
width: 1px;
|
||||
background: ${props => props.theme.colors.border};
|
||||
|
Reference in New Issue
Block a user