feat: add task details
This commit is contained in:
parent
a9a1576f46
commit
771d598c04
@ -59,6 +59,7 @@
|
|||||||
"react-router-dom": "^5.1.2",
|
"react-router-dom": "^5.1.2",
|
||||||
"react-scripts": "3.4.0",
|
"react-scripts": "3.4.0",
|
||||||
"react-select": "^3.1.0",
|
"react-select": "^3.1.0",
|
||||||
|
"rich-markdown-editor": "^10.6.5",
|
||||||
"styled-components": "^5.0.1",
|
"styled-components": "^5.0.1",
|
||||||
"typescript": "~3.7.2"
|
"typescript": "~3.7.2"
|
||||||
},
|
},
|
||||||
@ -95,10 +96,10 @@
|
|||||||
"@graphql-codegen/typescript-operations": "^1.13.2",
|
"@graphql-codegen/typescript-operations": "^1.13.2",
|
||||||
"@graphql-codegen/typescript-react-apollo": "^1.13.2",
|
"@graphql-codegen/typescript-react-apollo": "^1.13.2",
|
||||||
"@storybook/addon-actions": "^5.3.13",
|
"@storybook/addon-actions": "^5.3.13",
|
||||||
"@storybook/addon-links": "^5.3.13",
|
|
||||||
"@storybook/addon-backgrounds": "^5.3.17",
|
"@storybook/addon-backgrounds": "^5.3.17",
|
||||||
"@storybook/addon-docs": "^5.3.17",
|
"@storybook/addon-docs": "^5.3.17",
|
||||||
"@storybook/addon-knobs": "^5.3.17",
|
"@storybook/addon-knobs": "^5.3.17",
|
||||||
|
"@storybook/addon-links": "^5.3.13",
|
||||||
"@storybook/addon-storysource": "^5.3.17",
|
"@storybook/addon-storysource": "^5.3.17",
|
||||||
"@storybook/addon-viewport": "^5.3.17",
|
"@storybook/addon-viewport": "^5.3.17",
|
||||||
"@storybook/addons": "^5.3.13",
|
"@storybook/addons": "^5.3.13",
|
||||||
|
@ -298,13 +298,14 @@ const Details: React.FC<DetailsProps> = ({
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Modal
|
<Modal
|
||||||
width={768}
|
width={1070}
|
||||||
onClose={() => {
|
onClose={() => {
|
||||||
history.push(projectURL);
|
history.push(projectURL);
|
||||||
}}
|
}}
|
||||||
renderContent={() => {
|
renderContent={() => {
|
||||||
return (
|
return (
|
||||||
<TaskDetails
|
<TaskDetails
|
||||||
|
me={data.me.user}
|
||||||
task={data.findTask}
|
task={data.findTask}
|
||||||
onChecklistDrop={checklist => {
|
onChecklistDrop={checklist => {
|
||||||
updateTaskChecklistLocation({
|
updateTaskChecklistLocation({
|
||||||
|
@ -270,7 +270,17 @@ const Project = () => {
|
|||||||
updateTaskName({ variables: { taskID: updatedTask.id, name: newName } });
|
updateTaskName({ variables: { taskID: updatedTask.id, name: newName } });
|
||||||
}}
|
}}
|
||||||
onTaskDescriptionChange={(updatedTask, newDescription) => {
|
onTaskDescriptionChange={(updatedTask, newDescription) => {
|
||||||
updateTaskDescription({ variables: { taskID: updatedTask.id, description: newDescription } });
|
updateTaskDescription({
|
||||||
|
variables: { taskID: updatedTask.id, description: newDescription },
|
||||||
|
optimisticResponse: {
|
||||||
|
__typename: 'Mutation',
|
||||||
|
updateTaskDescription: {
|
||||||
|
__typename: 'Task',
|
||||||
|
id: updatedTask.id,
|
||||||
|
description: newDescription,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
onDeleteTask={deletedTask => {
|
onDeleteTask={deletedTask => {
|
||||||
deleteTask({ variables: { taskID: deletedTask.id } });
|
deleteTask({ variables: { taskID: deletedTask.id } });
|
||||||
|
@ -98,7 +98,7 @@ const AddList: React.FC<AddListProps> = ({ onSave }) => {
|
|||||||
) : (
|
) : (
|
||||||
<Placeholder>
|
<Placeholder>
|
||||||
<AddIconWrapper>
|
<AddIconWrapper>
|
||||||
<Plus size={12} color="#c2c6dc" />
|
<Plus width={12} height={12} />
|
||||||
</AddIconWrapper>
|
</AddIconWrapper>
|
||||||
Add another list
|
Add another list
|
||||||
</Placeholder>
|
</Placeholder>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { useRef } from 'react';
|
import React, { useRef } from 'react';
|
||||||
import styled, { css } from 'styled-components/macro';
|
import styled, { css } from 'styled-components/macro';
|
||||||
|
|
||||||
const Text = styled.span<{ fontSize: string; justifyTextContent: string }>`
|
const Text = styled.span<{ fontSize: string; justifyTextContent: string; hasIcon?: boolean }>`
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -9,6 +9,11 @@ const Text = styled.span<{ fontSize: string; justifyTextContent: string }>`
|
|||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
font-size: ${props => props.fontSize};
|
font-size: ${props => props.fontSize};
|
||||||
color: rgba(${props => props.theme.colors.text.secondary});
|
color: rgba(${props => props.theme.colors.text.secondary});
|
||||||
|
${props =>
|
||||||
|
props.hasIcon &&
|
||||||
|
css`
|
||||||
|
padding-left: 4px;
|
||||||
|
`}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Base = styled.button<{ color: string; disabled: boolean }>`
|
const Base = styled.button<{ color: string; disabled: boolean }>`
|
||||||
@ -18,6 +23,8 @@ const Base = styled.button<{ color: string; disabled: boolean }>`
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
padding: 0.75rem 2rem;
|
padding: 0.75rem 2rem;
|
||||||
border-radius: ${props => props.theme.borderRadius.alternate};
|
border-radius: ${props => props.theme.borderRadius.alternate};
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
${props =>
|
${props =>
|
||||||
props.disabled &&
|
props.disabled &&
|
||||||
@ -34,16 +41,28 @@ const Filled = styled(Base)`
|
|||||||
box-shadow: 0 8px 25px -8px rgba(${props => props.theme.colors[props.color]});
|
box-shadow: 0 8px 25px -8px rgba(${props => props.theme.colors[props.color]});
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
const Outline = styled(Base)`
|
const Outline = styled(Base)<{ invert: boolean }>`
|
||||||
border: 1px solid rgba(${props => props.theme.colors[props.color]});
|
border: 1px solid rgba(${props => props.theme.colors[props.color]});
|
||||||
background: transparent;
|
background: transparent;
|
||||||
|
${props =>
|
||||||
|
props.invert
|
||||||
|
? css`
|
||||||
|
background: rgba(${props.theme.colors[props.color]});
|
||||||
& ${Text} {
|
& ${Text} {
|
||||||
color: rgba(${props => props.theme.colors[props.color]});
|
color: rgba(${props.theme.colors.text.secondary});
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: rgba(${props => props.theme.colors[props.color]}, 0.08);
|
background: rgba(${props.theme.colors[props.color]}, 0.8);
|
||||||
}
|
}
|
||||||
|
`
|
||||||
|
: css`
|
||||||
|
& ${Text} {
|
||||||
|
color: rgba(${props.theme.colors[props.color]});
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
background: rgba(${props.theme.colors[props.color]}, 0.08);
|
||||||
|
}
|
||||||
|
`}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Flat = styled(Base)`
|
const Flat = styled(Base)`
|
||||||
@ -110,6 +129,8 @@ type ButtonProps = {
|
|||||||
color?: 'primary' | 'danger' | 'success' | 'warning' | 'dark';
|
color?: 'primary' | 'danger' | 'success' | 'warning' | 'dark';
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
type?: 'button' | 'submit';
|
type?: 'button' | 'submit';
|
||||||
|
icon?: JSX.Element;
|
||||||
|
invert?: boolean;
|
||||||
className?: string;
|
className?: string;
|
||||||
onClick?: ($target: React.RefObject<HTMLButtonElement>) => void;
|
onClick?: ($target: React.RefObject<HTMLButtonElement>) => void;
|
||||||
justifyTextContent?: string;
|
justifyTextContent?: string;
|
||||||
@ -118,10 +139,12 @@ type ButtonProps = {
|
|||||||
const Button: React.FC<ButtonProps> = ({
|
const Button: React.FC<ButtonProps> = ({
|
||||||
disabled = false,
|
disabled = false,
|
||||||
fontSize = '14px',
|
fontSize = '14px',
|
||||||
|
invert = false,
|
||||||
color = 'primary',
|
color = 'primary',
|
||||||
variant = 'filled',
|
variant = 'filled',
|
||||||
type = 'button',
|
type = 'button',
|
||||||
justifyTextContent = 'center',
|
justifyTextContent = 'center',
|
||||||
|
icon,
|
||||||
onClick,
|
onClick,
|
||||||
className,
|
className,
|
||||||
children,
|
children,
|
||||||
@ -136,7 +159,8 @@ const Button: React.FC<ButtonProps> = ({
|
|||||||
case 'filled':
|
case 'filled':
|
||||||
return (
|
return (
|
||||||
<Filled ref={$button} type={type} onClick={handleClick} className={className} disabled={disabled} color={color}>
|
<Filled ref={$button} type={type} onClick={handleClick} className={className} disabled={disabled} color={color}>
|
||||||
<Text justifyTextContent={justifyTextContent} fontSize={fontSize}>
|
{icon && icon}
|
||||||
|
<Text hasIcon={typeof icon !== 'undefined'} justifyTextContent={justifyTextContent} fontSize={fontSize}>
|
||||||
{children}
|
{children}
|
||||||
</Text>
|
</Text>
|
||||||
</Filled>
|
</Filled>
|
||||||
@ -145,6 +169,7 @@ const Button: React.FC<ButtonProps> = ({
|
|||||||
return (
|
return (
|
||||||
<Outline
|
<Outline
|
||||||
ref={$button}
|
ref={$button}
|
||||||
|
invert={invert}
|
||||||
type={type}
|
type={type}
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
className={className}
|
className={className}
|
||||||
|
@ -25,7 +25,7 @@ const WindowTitle = styled.div`
|
|||||||
|
|
||||||
const WindowTitleIcon = styled(CheckSquareOutline)`
|
const WindowTitleIcon = styled(CheckSquareOutline)`
|
||||||
top: 10px;
|
top: 10px;
|
||||||
left: -40px;
|
left: -32px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -102,7 +102,7 @@ const List = React.forwardRef(
|
|||||||
{children && children}
|
{children && children}
|
||||||
<AddCardContainer hidden={isComposerOpen}>
|
<AddCardContainer hidden={isComposerOpen}>
|
||||||
<AddCardButton onClick={() => onOpenComposer(id)}>
|
<AddCardButton onClick={() => onOpenComposer(id)}>
|
||||||
<Plus size={12} color="#c2c6dc" />
|
<Plus width={12} height={12} />
|
||||||
<AddCardButtonText>Add another card</AddCardButtonText>
|
<AddCardButtonText>Add another card</AddCardButtonText>
|
||||||
</AddCardButton>
|
</AddCardButton>
|
||||||
</AddCardContainer>
|
</AddCardContainer>
|
||||||
|
@ -4,10 +4,8 @@ export const Container = styled.div`
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
margin-bottom: 8px;
|
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
padding-bottom: 8px;
|
|
||||||
|
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
height: 10px;
|
height: 10px;
|
||||||
@ -35,10 +33,9 @@ export const BoardWrapper = styled.div`
|
|||||||
|
|
||||||
user-select: none;
|
user-select: none;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
margin-bottom: 8px;
|
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
padding-bottom: 8px;
|
padding-bottom: 4px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
|
@ -44,6 +44,7 @@ type MemberProps = {
|
|||||||
showName?: boolean;
|
showName?: boolean;
|
||||||
className?: string;
|
className?: string;
|
||||||
showCheckmark?: boolean;
|
showCheckmark?: boolean;
|
||||||
|
size?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
const CardMemberWrapper = styled.div<{ ref: any }>`
|
const CardMemberWrapper = styled.div<{ ref: any }>`
|
||||||
@ -63,6 +64,7 @@ const Member: React.FC<MemberProps> = ({
|
|||||||
showName,
|
showName,
|
||||||
showCheckmark = false,
|
showCheckmark = false,
|
||||||
className,
|
className,
|
||||||
|
size = 28,
|
||||||
}) => {
|
}) => {
|
||||||
const $targetRef = useRef<HTMLDivElement>();
|
const $targetRef = useRef<HTMLDivElement>();
|
||||||
return (
|
return (
|
||||||
@ -77,7 +79,7 @@ const Member: React.FC<MemberProps> = ({
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<TaskAssignee onMemberProfile={NOOP} size={28} member={member} />
|
<TaskAssignee onMemberProfile={NOOP} size={32} member={member} />
|
||||||
{showName && <CardMemberName>{member.fullName}</CardMemberName>}
|
{showName && <CardMemberName>{member.fullName}</CardMemberName>}
|
||||||
{showCheckmark && <CardCheckmark width={12} height={12} />}
|
{showCheckmark && <CardCheckmark width={12} height={12} />}
|
||||||
</CardMemberWrapper>
|
</CardMemberWrapper>
|
||||||
|
@ -15,18 +15,20 @@ export const ScrollOverlay = styled.div`
|
|||||||
export const ClickableOverlay = styled.div`
|
export const ClickableOverlay = styled.div`
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
background: rgba(0, 0, 0, 0.4);
|
background: rgba(0, 0, 0, 0.4);
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const StyledModal = styled.div<{ width: number }>`
|
export const StyledModal = styled.div<{ width: number; height: number }>`
|
||||||
display: inline-block;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
margin: 48px 0 80px;
|
width: ${props => props.width}px;
|
||||||
width: 100%;
|
height: ${props => props.height}px;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
top: 48px;
|
||||||
|
bottom: 16px;
|
||||||
|
margin: auto;
|
||||||
|
|
||||||
background: #262c49;
|
background: #262c49;
|
||||||
max-width: ${props => props.width}px;
|
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
border-radius: 3px;
|
border-radius: 6px;
|
||||||
${mixin.boxShadowMedium}
|
${mixin.boxShadowMedium}
|
||||||
`;
|
`;
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import React, { useRef } from 'react';
|
import React, { useRef, useEffect, useState } from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
|
|
||||||
import useOnOutsideClick from 'shared/hooks/onOutsideClick';
|
import useOnOutsideClick from 'shared/hooks/onOutsideClick';
|
||||||
import useOnEscapeKeyDown from 'shared/hooks/onEscapeKeyDown';
|
import useOnEscapeKeyDown from 'shared/hooks/onEscapeKeyDown';
|
||||||
|
import useWindowSize from 'shared/hooks/useWindowSize';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
import { Cross } from 'shared/icons';
|
||||||
import { ScrollOverlay, ClickableOverlay, StyledModal } from './Styles';
|
import { ScrollOverlay, ClickableOverlay, StyledModal } from './Styles';
|
||||||
|
|
||||||
const $root: HTMLElement = document.getElementById('root')!; // eslint-disable-line @typescript-eslint/no-non-null-assertion
|
const $root: HTMLElement = document.getElementById('root')!; // eslint-disable-line @typescript-eslint/no-non-null-assertion
|
||||||
@ -14,21 +15,50 @@ type ModalProps = {
|
|||||||
renderContent: () => JSX.Element;
|
renderContent: () => JSX.Element;
|
||||||
};
|
};
|
||||||
|
|
||||||
const Modal: React.FC<ModalProps> = ({ width, onClose: tellParentToClose, renderContent }) => {
|
function getAdjustedHeight(height: number) {
|
||||||
|
if (height >= 900) {
|
||||||
|
return height - 150;
|
||||||
|
}
|
||||||
|
if (height >= 800) {
|
||||||
|
return height - 125;
|
||||||
|
}
|
||||||
|
return height - 70;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CloseIcon = styled(Cross)`
|
||||||
|
position: absolute;
|
||||||
|
top: 16px;
|
||||||
|
right: -32px;
|
||||||
|
cursor: pointer;
|
||||||
|
fill: rgba(${props => props.theme.colors.text.primary});
|
||||||
|
&:hover {
|
||||||
|
fill: rgba(${props => props.theme.colors.text.secondary});
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const InnerModal: React.FC<ModalProps> = ({ width, onClose: tellParentToClose, renderContent }) => {
|
||||||
const $modalRef = useRef<HTMLDivElement>(null);
|
const $modalRef = useRef<HTMLDivElement>(null);
|
||||||
const $clickableOverlayRef = useRef<HTMLDivElement>(null);
|
const $clickableOverlayRef = useRef<HTMLDivElement>(null);
|
||||||
|
const [_width, height] = useWindowSize();
|
||||||
|
|
||||||
useOnOutsideClick($modalRef, true, tellParentToClose, $clickableOverlayRef);
|
useOnOutsideClick($modalRef, true, tellParentToClose, $clickableOverlayRef);
|
||||||
useOnEscapeKeyDown(true, tellParentToClose);
|
useOnEscapeKeyDown(true, tellParentToClose);
|
||||||
|
|
||||||
return ReactDOM.createPortal(
|
return (
|
||||||
<ScrollOverlay>
|
<ScrollOverlay>
|
||||||
<ClickableOverlay ref={$clickableOverlayRef}>
|
<ClickableOverlay ref={$clickableOverlayRef}>
|
||||||
<StyledModal width={width} ref={$modalRef}>
|
<StyledModal width={width} height={getAdjustedHeight(height)} ref={$modalRef}>
|
||||||
{renderContent()}
|
{renderContent()}
|
||||||
|
<CloseIcon onClick={() => tellParentToClose()} width={20} height={20} />
|
||||||
</StyledModal>
|
</StyledModal>
|
||||||
</ClickableOverlay>
|
</ClickableOverlay>
|
||||||
</ScrollOverlay>,
|
</ScrollOverlay>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const Modal: React.FC<ModalProps> = ({ width, onClose: tellParentToClose, renderContent }) => {
|
||||||
|
return ReactDOM.createPortal(
|
||||||
|
<InnerModal width={width} onClose={tellParentToClose} renderContent={renderContent} />,
|
||||||
$root,
|
$root,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -13,7 +13,7 @@ export const AddProjectItem: React.FC<AddProjectItemProps> = ({ onAddProject })
|
|||||||
onAddProject();
|
onAddProject();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Plus size={20} color="#c2c6dc" />
|
<Plus width={12} height={12} />
|
||||||
<AddProjectLabel>New Project</AddProjectLabel>
|
<AddProjectLabel>New Project</AddProjectLabel>
|
||||||
</AddProjectWrapper>
|
</AddProjectWrapper>
|
||||||
);
|
);
|
||||||
|
@ -1,288 +1,365 @@
|
|||||||
import styled from 'styled-components';
|
import styled, { css } from 'styled-components';
|
||||||
import TextareaAutosize from 'react-autosize-textarea/lib';
|
import TextareaAutosize from 'react-autosize-textarea';
|
||||||
import { mixin } from 'shared/utils/styles';
|
import { mixin } from 'shared/utils/styles';
|
||||||
import Button from 'shared/components/Button';
|
import Button from 'shared/components/Button';
|
||||||
import TaskAssignee from 'shared/components/TaskAssignee';
|
import TaskAssignee from 'shared/components/TaskAssignee';
|
||||||
|
import { User, Trash, Paperclip } from 'shared/icons';
|
||||||
|
import Member from 'shared/components/Member';
|
||||||
|
|
||||||
export const TaskHeader = styled.div`
|
export const Container = styled.div`
|
||||||
padding: 21px 30px 0px;
|
display: flex;
|
||||||
margin-right: 70px;
|
height: 100%;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const LeftSidebar = styled.div`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 300px;
|
||||||
|
background: #222740;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const MarkCompleteButton = styled.button<{ invert: boolean }>`
|
||||||
|
padding: 4px 8px;
|
||||||
|
position: relative;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: ${props => props.theme.borderRadius.alternate};
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
background: transparent;
|
||||||
|
& span {
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
${props =>
|
||||||
|
props.invert
|
||||||
|
? css`
|
||||||
|
background: rgba(${props.theme.colors.success});
|
||||||
|
& svg {
|
||||||
|
fill: rgba(${props.theme.colors.text.secondary});
|
||||||
|
}
|
||||||
|
& span {
|
||||||
|
color: rgba(${props.theme.colors.text.secondary});
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
background: rgba(${props.theme.colors.success}, 0.8);
|
||||||
|
}
|
||||||
|
`
|
||||||
|
: css`
|
||||||
|
background: none;
|
||||||
|
border: 1px solid rgba(${props.theme.colors.text.secondary});
|
||||||
|
& svg {
|
||||||
|
fill: rgba(${props.theme.colors.text.secondary});
|
||||||
|
}
|
||||||
|
& span {
|
||||||
|
color: rgba(${props.theme.colors.text.secondary});
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
background: rgba(${props.theme.colors.success}, 0.08);
|
||||||
|
border: 1px solid rgba(${props.theme.colors.success});
|
||||||
|
}
|
||||||
|
&:hover svg {
|
||||||
|
fill: rgba(${props.theme.colors.success});
|
||||||
|
}
|
||||||
|
&:hover span {
|
||||||
|
color: rgba(${props.theme.colors.success});
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const LeftSidebarContent = styled.div`
|
||||||
|
padding-top: 32px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const TaskMeta = styled.div`
|
export const LeftSidebarSection = styled.div`
|
||||||
position: relative;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding-left: 32px;
|
||||||
|
padding-right: 32px;
|
||||||
|
padding-bottom: 16px;
|
||||||
|
border-bottom: 1px solid #414561;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const SidebarTitle = styled.div`
|
||||||
|
font-size: 12px;
|
||||||
|
min-height: 24px;
|
||||||
|
margin-left: 8px;
|
||||||
|
color: rgba(${props => props.theme.colors.text.primary}, 0.75);
|
||||||
|
padding-top: 4px;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const SidebarButton = styled.div`
|
||||||
|
font-size: 14px;
|
||||||
|
color: rgba(${props => props.theme.colors.text.primary});
|
||||||
|
min-height: 32px;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
padding: 9px 8px 7px 8px;
|
||||||
|
border-color: transparent;
|
||||||
|
border-radius: 6px;
|
||||||
|
border-width: 1px;
|
||||||
|
border-style: solid;
|
||||||
|
|
||||||
|
display: inline-block;
|
||||||
|
outline: 0;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-size: 14px;
|
&:hover {
|
||||||
|
border-color: #414561;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const SidebarButtonText = styled.span`
|
||||||
|
min-height: 16px;
|
||||||
|
flex: 1 1 auto;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
justify-content: flex-start;
|
||||||
border-radius: 4px;
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const TaskGroupLabel = styled.span`
|
export const ContentContainer = styled.div`
|
||||||
color: #c2c6dc;
|
|
||||||
font-size: 14px;
|
|
||||||
`;
|
|
||||||
export const TaskGroupLabelName = styled.span`
|
|
||||||
color: #c2c6dc;
|
|
||||||
text-decoration: underline;
|
|
||||||
font-size: 14px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const TaskActions = styled.div`
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
padding: 21px 18px 0px;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
flex-direction: column;
|
||||||
`;
|
|
||||||
|
|
||||||
export const TaskAction = styled.button`
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
height: 32px;
|
|
||||||
cursor: pointer;
|
|
||||||
padding: 0px 9px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const TaskDetailsWrapper = styled.div`
|
|
||||||
display: flex;
|
|
||||||
padding: 0px 16px 60px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const TaskDetailsContent = styled.div`
|
|
||||||
flex: 1;
|
flex: 1;
|
||||||
padding-right: 8px;
|
padding-top: 32px;
|
||||||
|
overflow: auto;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const TaskDetailsSidebar = styled.div`
|
export const HeaderContainer = styled.div`
|
||||||
width: 168px;
|
flex: 0 0 auto;
|
||||||
padding-left: 8px;
|
padding: 0px 32px 0px 24px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const HeaderInnerContainer = styled.div`
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin: 0 0 0 0;
|
||||||
|
padding: 0 0 0 4px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const HeaderLeft = styled.div`
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-start;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const TaskDetailsTitleWrapper = styled.div`
|
export const TaskDetailsTitleWrapper = styled.div`
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: 0 0 0 -8px;
|
margin: 8px 0 4px 0;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const TaskDetailsTitle = styled(TextareaAutosize)`
|
export const TaskDetailsTitle = styled(TextareaAutosize)`
|
||||||
line-height: 1.28;
|
padding: 9px 8px 7px 8px;
|
||||||
resize: none;
|
border-color: transparent;
|
||||||
box-shadow: transparent 0px 0px 0px 1px;
|
border-radius: 6px;
|
||||||
font-size: 24px;
|
|
||||||
font-weight: 700;
|
|
||||||
padding: 4px;
|
|
||||||
background: #262c49;
|
|
||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
border-color: transparent;
|
|
||||||
border-image: initial;
|
|
||||||
transition: background 0.1s ease 0s;
|
|
||||||
overflow-y: hidden;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
color: #c2c6dc;
|
color: #c2c6dc;
|
||||||
&:focus {
|
display: inline-block;
|
||||||
box-shadow: rgb(115, 103, 240) 0px 0px 0px 1px;
|
outline: 0;
|
||||||
background: ${mixin.darken('#262c49', 0.15)};
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const TaskDetailsLabel = styled.div`
|
|
||||||
padding: 24px 0px 12px;
|
|
||||||
font-size: 15px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #c2c6dc;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const TaskDetailsAddDetailsButton = styled.div`
|
|
||||||
background: ${mixin.darken('#262c49', 0.15)};
|
|
||||||
box-shadow: none;
|
|
||||||
border: none;
|
|
||||||
border-radius: 3px;
|
|
||||||
display: block;
|
|
||||||
min-height: 56px;
|
|
||||||
padding: 8px 12px;
|
|
||||||
text-decoration: none;
|
|
||||||
font-size: 14px;
|
|
||||||
cursor: pointer;
|
|
||||||
color: #c2c6dc;
|
|
||||||
&:hover {
|
|
||||||
background: ${mixin.darken('#262c49', 0.25)};
|
|
||||||
box-shadow: none;
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const TaskDetailsEditorWrapper = styled.div`
|
|
||||||
display: block;
|
|
||||||
padding-bottom: 9px;
|
|
||||||
z-index: 50;
|
|
||||||
width: 100%;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const TaskDetailsEditor = styled(TextareaAutosize)`
|
|
||||||
width: 100%;
|
|
||||||
min-height: 108px;
|
|
||||||
color: #c2c6dc;
|
|
||||||
background: #262c49;
|
|
||||||
box-shadow: rgb(115, 103, 240) 0px 0px 0px 1px;
|
|
||||||
border-radius: 3px;
|
|
||||||
line-height: 20px;
|
|
||||||
padding: 8px 12px;
|
|
||||||
outline: none;
|
|
||||||
border: none;
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
box-shadow: rgb(115, 103, 240) 0px 0px 0px 1px;
|
|
||||||
background: ${mixin.darken('#262c49', 0.05)};
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const TaskDetailsMarkdown = styled.div`
|
|
||||||
width: 100%;
|
|
||||||
cursor: pointer;
|
|
||||||
color: #c2c6dc;
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
font-weight: 600;
|
|
||||||
line-height: 28px;
|
|
||||||
margin: 0 0 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
font-weight: 600;
|
|
||||||
font-size: 20px;
|
|
||||||
line-height: 24px;
|
|
||||||
margin: 16px 0 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
margin: 0 0 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
strong {
|
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
|
background: none;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: #414561;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
border-color: rgba(${props => props.theme.colors.primary});
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const DueDateTitle = styled.div`
|
||||||
|
font-size: 12px;
|
||||||
|
min-height: 24px;
|
||||||
|
margin-left: 8px;
|
||||||
|
color: rgba(${props => props.theme.colors.text.primary}, 0.75);
|
||||||
|
padding-top: 8px;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const AssignedUsersSection = styled.div`
|
||||||
|
padding-left: 32px;
|
||||||
|
padding-right: 32px;
|
||||||
|
padding-top: 24px;
|
||||||
|
padding-bottom: 24px;
|
||||||
|
border-bottom: 1px solid #414561;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const AssignUserIcon = styled.div`
|
||||||
|
cursor: pointer;
|
||||||
|
height: 32px;
|
||||||
|
width: 32px;
|
||||||
|
position: relative;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 1px dashed #414561;
|
||||||
|
margin-right: 8px;
|
||||||
|
display: flex;
|
||||||
|
flex-shrink: 0;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
&:hover {
|
||||||
|
border: 1px solid rgba(${props => props.theme.colors.text.secondary}, 0.75);
|
||||||
|
}
|
||||||
|
&:hover svg {
|
||||||
|
fill: rgba(${props => props.theme.colors.text.secondary}, 0.75);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const AssignUsersButton = styled.div`
|
||||||
|
cursor: pointer;
|
||||||
|
display: inline-flex;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
height: 40px;
|
||||||
|
padding: 4px 16px 4px 8px;
|
||||||
|
margin-left: -1px;
|
||||||
|
border-radius: 6px;
|
||||||
|
align-items: center;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
&:hover {
|
||||||
|
border: 1px solid ${mixin.darken('#414561', 0.15)};
|
||||||
|
}
|
||||||
|
&:hover ${AssignUserIcon} {
|
||||||
|
border: 1px solid #414561;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const AssignUserLabel = styled.span`
|
||||||
|
flex: 1 1 auto;
|
||||||
|
line-height: 15px;
|
||||||
|
color: rgba(${props => props.theme.colors.text.primary}, 0.75);
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const ExtraActionsSection = styled.div`
|
||||||
|
padding-left: 32px;
|
||||||
|
padding-right: 32px;
|
||||||
|
padding-top: 24px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const ActionButtonsTitle = styled.h3`
|
||||||
|
color: rgba(${props => props.theme.colors.text.primary});
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 500;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const ActionButton = styled(Button)`
|
||||||
|
margin-top: 8px;
|
||||||
|
margin-left: -10px;
|
||||||
|
padding: 8px 16px;
|
||||||
|
background: rgba(${props => props.theme.colors.bg.primary}, 0.5);
|
||||||
|
text-align: left;
|
||||||
|
transition: transform 0.2s ease;
|
||||||
|
& span {
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
box-shadow: none;
|
||||||
|
transform: translateX(4px);
|
||||||
|
background: rgba(${props => props.theme.colors.bg.primary}, 0.75);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const HeaderRight = styled.div`
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const HeaderActionIcon = styled.div`
|
||||||
|
padding: 4px 4px 4px 4px;
|
||||||
|
margin: 0 4px 0 4px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
cursor: pointer;
|
||||||
|
svg {
|
||||||
|
fill: rgba(${props => props.theme.colors.text.primary}, 0.75);
|
||||||
|
}
|
||||||
|
&:hover svg {
|
||||||
|
fill: rgba(${props => props.theme.colors.primary});
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const EditorContainer = styled.div`
|
||||||
|
margin-left: 32px;
|
||||||
|
margin-right: 32px;
|
||||||
|
|
||||||
|
padding: 9px 8px 7px 8px;
|
||||||
|
border-color: transparent;
|
||||||
|
border-radius: 6px;
|
||||||
|
border-width: 1px;
|
||||||
|
border-style: solid;
|
||||||
|
outline: 0;
|
||||||
|
background: none;
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
margin: 8px 0;
|
list-style-type: disc;
|
||||||
}
|
}
|
||||||
|
|
||||||
ul > li {
|
ul.checkbox_list input[type='checkbox'] {
|
||||||
margin: 8px 8px 8px 24px;
|
border-radius: 6px;
|
||||||
list-style: disc;
|
border-width: 1px;
|
||||||
}
|
border-style: solid;
|
||||||
|
border-color: #414561;
|
||||||
p a {
|
|
||||||
color: rgba(${props => props.theme.colors.primary});
|
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const TaskDetailsControls = styled.div`
|
export const InnerContentContainer = styled.div`
|
||||||
clear: both;
|
overflow: auto;
|
||||||
margin-top: 8px;
|
position: relative;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const DescriptionContainer = styled.div`
|
||||||
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const ConfirmSave = styled(Button)`
|
export const DescriptionActionButton = styled(Button)`
|
||||||
padding: 6px 12px;
|
padding: 8px 16px;
|
||||||
border-radius: 3px;
|
|
||||||
margin-right: 6px;
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const CancelEdit = styled.div`
|
export const Labels = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
padding-left: 9px;
|
||||||
justify-content: center;
|
margin: 0 0 8px 0;
|
||||||
height: 32px;
|
|
||||||
width: 32px;
|
|
||||||
cursor: pointer;
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const TaskDetailSectionTitle = styled.div`
|
export const MetaDetail = styled.div`
|
||||||
text-transform: uppercase;
|
|
||||||
color: #c2c6dc;
|
|
||||||
font-size: 12.5px;
|
|
||||||
font-weight: 600;
|
|
||||||
margin: 24px 0px 5px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const TaskDetailAssignees = styled.div`
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
align-items: center;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const TaskDetailAssignee = styled.div`
|
|
||||||
&:hover {
|
|
||||||
opacity: 0.8;
|
|
||||||
}
|
|
||||||
margin-right: 4px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const ProfileIcon = styled.div`
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
border-radius: 9999px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
color: #fff;
|
|
||||||
font-weight: 700;
|
|
||||||
background: rgb(115, 103, 240);
|
|
||||||
cursor: pointer;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const TaskDetailsAddMemberIcon = styled.div`
|
|
||||||
float: left;
|
|
||||||
height: 32px;
|
|
||||||
width: 32px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
border-radius: 100%;
|
|
||||||
background: ${mixin.darken('#262c49', 0.15)};
|
|
||||||
cursor: pointer;
|
|
||||||
&:hover {
|
|
||||||
opacity: 0.8;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const TaskDetailLabels = styled.div`
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const TaskDetailLabel = styled.div<{ color: string }>`
|
|
||||||
&:hover {
|
|
||||||
opacity: 0.8;
|
|
||||||
}
|
|
||||||
background-color: ${props => props.color};
|
|
||||||
color: #fff;
|
|
||||||
|
|
||||||
cursor: pointer;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
border-radius: 3px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
display: block;
|
display: block;
|
||||||
float: left;
|
float: left;
|
||||||
font-weight: 600;
|
margin: 0 16px 8px 0;
|
||||||
height: 32px;
|
max-width: 100%;
|
||||||
line-height: 32px;
|
|
||||||
margin: 0 4px 4px 0;
|
|
||||||
min-width: 40px;
|
|
||||||
padding: 0 12px;
|
|
||||||
width: auto;
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const MetaDetailTitle = styled.h3`
|
||||||
|
color: rgba(${props => props.theme.colors.text.primary});
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 500;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
margin-top: 16px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
display: block;
|
||||||
|
line-height: 20px;
|
||||||
|
margin: 0 8px 4px 0;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const MetaDetailContent = styled.div`
|
||||||
|
display: flex;
|
||||||
|
`;
|
||||||
export const TaskDetailsAddLabel = styled.div`
|
export const TaskDetailsAddLabel = styled.div`
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
background: ${mixin.darken('#262c49', 0.15)};
|
background: ${mixin.darken('#262c49', 0.15)};
|
||||||
@ -307,90 +384,204 @@ export const TaskDetailsAddLabelIcon = styled.div`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const NoDueDateLabel = styled.span`
|
export const ChecklistSection = styled.div`
|
||||||
color: rgb(137, 147, 164);
|
margin-top: 8px;
|
||||||
font-size: 14px;
|
padding: 0 24px;
|
||||||
cursor: pointer;
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const UnassignedLabel = styled.div`
|
export const TaskDetailLabel = styled.div<{ color: string }>`
|
||||||
color: rgb(137, 147, 164);
|
&:hover {
|
||||||
font-size: 14px;
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
background-color: ${props => props.color};
|
||||||
|
color: #fff;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
border-radius: 3px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: block;
|
||||||
|
float: left;
|
||||||
|
font-weight: 600;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
|
line-height: 32px;
|
||||||
|
margin: 0 4px 0 0;
|
||||||
|
min-width: 40px;
|
||||||
|
padding: 0 12px;
|
||||||
|
width: auto;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const ActionButtons = styled.div`
|
export const MemberList = styled.div`
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 4px 16px 4px 8px;
|
||||||
|
margin-left: -1px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const TaskMember = styled(TaskAssignee)`
|
||||||
|
margin-right: 4px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const ActionButtonIcon = styled.div``;
|
||||||
|
|
||||||
|
export const EditorActions = styled.div`
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
margin-left: 32px;
|
||||||
|
margin-right: 32px;
|
||||||
|
padding: 9px 8px 7px 8px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const CancelIcon = styled.div`
|
||||||
|
width: 32px;
|
||||||
|
height: 32p;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-left: 4px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const TabBarSection = styled.div`
|
||||||
|
margin-top: 2px;
|
||||||
|
padding-left: 23px;
|
||||||
|
display: flex;
|
||||||
|
text-transform: uppercase;
|
||||||
|
min-height: 35px;
|
||||||
|
border-bottom: 1px solid #414561;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const TabBarItem = styled.div`
|
||||||
|
box-shadow: inset 0 -2px rgba(216, 93, 216);
|
||||||
|
padding: 12px 7px 14px 7px;
|
||||||
|
margin-bottom: -1px;
|
||||||
|
margin-right: 36px;
|
||||||
|
color: rgba(${props => props.theme.colors.text.primary});
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const CommentContainer = styled.div`
|
||||||
|
flex: 0 0 auto;
|
||||||
|
margin-top: auto;
|
||||||
|
padding: 15px 26px;
|
||||||
|
background: #1f243e;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const CommentInnerWrapper = styled.div`
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const CommentEditorContainer = styled.div`
|
||||||
|
flex: 1;
|
||||||
|
border-radius: 6px;
|
||||||
|
border: 1px solid #414561;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
`;
|
`;
|
||||||
|
export const CommentProfile = styled(TaskAssignee)`
|
||||||
|
margin-right: 8px;
|
||||||
|
position: relative;
|
||||||
|
top: 0;
|
||||||
|
padding-top: 3px;
|
||||||
|
align-items: normal;
|
||||||
|
`;
|
||||||
|
|
||||||
export const ActionButtonsTitle = styled.h3`
|
export const CommentTextArea = styled(TextareaAutosize)`
|
||||||
|
width: 100%;
|
||||||
|
line-height: 28px;
|
||||||
|
padding: 4px 6px;
|
||||||
|
border-radius: 6px;
|
||||||
color: rgba(${props => props.theme.colors.text.primary});
|
color: rgba(${props => props.theme.colors.text.primary});
|
||||||
font-size: 12px;
|
background: #1f243e;
|
||||||
font-weight: 500;
|
border: none;
|
||||||
letter-spacing: 0.04em;
|
transition: max-height 200ms, height 200ms, min-height 200ms;
|
||||||
`;
|
min-height: 36px;
|
||||||
|
max-height: 36px;
|
||||||
export const ActionButton = styled(Button)`
|
&:not(:focus) {
|
||||||
margin-top: 8px;
|
height: 36px;
|
||||||
padding: 6px 12px;
|
|
||||||
background: rgba(${props => props.theme.colors.bg.primary}, 0.4);
|
|
||||||
text-align: left;
|
|
||||||
&:hover {
|
|
||||||
box-shadow: none;
|
|
||||||
background: rgba(${props => props.theme.colors.bg.primary}, 0.6);
|
|
||||||
}
|
}
|
||||||
`;
|
&:focus {
|
||||||
|
min-height: 80px;
|
||||||
export const MetaDetails = styled.div`
|
max-height: none;
|
||||||
margin-top: 8px;
|
|
||||||
display: flex;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const TaskDueDateButton = styled(Button)`
|
|
||||||
height: 32px;
|
|
||||||
padding: 6px 12px;
|
|
||||||
background: rgba(${props => props.theme.colors.bg.primary}, 0.4);
|
|
||||||
&:hover {
|
|
||||||
box-shadow: none;
|
|
||||||
background: rgba(${props => props.theme.colors.bg.primary}, 0.6);
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const MetaDetail = styled.div`
|
|
||||||
display: block;
|
|
||||||
float: left;
|
|
||||||
margin: 0 16px 8px 0;
|
|
||||||
max-width: 100%;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const TaskDetailsSection = styled.div`
|
|
||||||
display: block;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const MetaDetailTitle = styled.h3`
|
|
||||||
color: rgba(${props => props.theme.colors.text.primary});
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 500;
|
|
||||||
letter-spacing: 0.04em;
|
|
||||||
margin-top: 16px;
|
|
||||||
text-transform: uppercase;
|
|
||||||
display: block;
|
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
margin: 0 8px 4px 0;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
overflow: hidden;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const TaskMember = styled(TaskAssignee)``;
|
|
||||||
|
|
||||||
export const MetaDetailContent = styled.div`
|
|
||||||
display: flex;
|
|
||||||
& ${TaskMember} {
|
|
||||||
margin-right: 4px;
|
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const CommentEditorActions = styled.div<{ visible: boolean }>`
|
||||||
|
display: ${props => (props.visible ? 'flex' : 'none')};
|
||||||
|
align-items: center;
|
||||||
|
padding: 5px 5px 5px 9px;
|
||||||
|
border-top: 1px solid #414561;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const CommentEditorActionIcon = styled.div`
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const CommentEditorSaveButton = styled(Button)`
|
||||||
|
margin-left: auto;
|
||||||
|
padding: 8px 16px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const ActivitySection = styled.div`
|
||||||
|
overflow-x: hidden;
|
||||||
|
|
||||||
|
padding: 8px 26px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const ActivityItem = styled.div`
|
||||||
|
padding: 8px 0;
|
||||||
|
position: relative;
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
word-wrap: break-word;
|
||||||
|
word-break: break-word;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const ActivityItemHeader = styled.div`
|
||||||
|
display: flex;
|
||||||
|
`;
|
||||||
|
export const ActivityItemHeaderUser = styled(TaskAssignee)`
|
||||||
|
margin-right: 4px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const ActivityItemHeaderTitle = styled.div`
|
||||||
|
margin-left: 4px;
|
||||||
|
line-height: 18px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const ActivityItemHeaderTitleName = styled.span`
|
||||||
|
color: rgba(${props => props.theme.colors.text.primary});
|
||||||
|
font-weight: 500;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const ActivityItemTimestamp = styled.span<{ margin: number }>`
|
||||||
|
font-size: 12px;
|
||||||
|
color: rgba(${props => props.theme.colors.text.primary}, 0.65);
|
||||||
|
margin-left: ${props => props.margin}px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const ActivityItemDetails = styled.div`
|
||||||
|
margin-left: 32px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const ActivityItemComment = styled.div`
|
||||||
|
display: inline-flex;
|
||||||
|
border-radius: 3px;
|
||||||
|
${mixin.boxShadowCard}
|
||||||
|
position: relative;
|
||||||
|
color: rgba(${props => props.theme.colors.text.primary});
|
||||||
|
padding: 8px 12px;
|
||||||
|
margin: 4px 0;
|
||||||
|
background-color: ${mixin.darken('#262c49', 0.1)};
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const ActivityItemLog = styled.span`
|
||||||
|
margin-left: 2px;
|
||||||
|
color: rgba(${props => props.theme.colors.text.primary});
|
||||||
|
`;
|
||||||
|
@ -1,70 +1,76 @@
|
|||||||
import React, { useState, useRef, useEffect } from 'react';
|
import React, { useState, useRef } from 'react';
|
||||||
import { Bin, Cross, Plus } from 'shared/icons';
|
import {
|
||||||
import useOnOutsideClick from 'shared/hooks/onOutsideClick';
|
Plus,
|
||||||
import ReactMarkdown from 'react-markdown';
|
User,
|
||||||
|
Trash,
|
||||||
|
Paperclip,
|
||||||
|
Clone,
|
||||||
|
Share,
|
||||||
|
Tags,
|
||||||
|
Checkmark,
|
||||||
|
CheckSquareOutline,
|
||||||
|
At,
|
||||||
|
Smile,
|
||||||
|
} from 'shared/icons';
|
||||||
|
import Editor from 'rich-markdown-editor';
|
||||||
|
import dark from 'shared/utils/editorTheme';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
import {
|
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';
|
||||||
isPositionChanged,
|
|
||||||
getSortedDraggables,
|
|
||||||
getNewDraggablePosition,
|
|
||||||
getAfterDropDraggableList,
|
|
||||||
} from 'shared/utils/draggables';
|
|
||||||
import { DragDropContext, Droppable, Draggable, DropResult } from 'react-beautiful-dnd';
|
|
||||||
import TaskAssignee from 'shared/components/TaskAssignee';
|
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
|
||||||
|
import Task from 'shared/icons/Task';
|
||||||
import {
|
import {
|
||||||
TaskMember,
|
TaskDetailLabel,
|
||||||
NoDueDateLabel,
|
CommentContainer,
|
||||||
TaskDueDateButton,
|
MetaDetailContent,
|
||||||
UnassignedLabel,
|
|
||||||
TaskGroupLabel,
|
|
||||||
TaskGroupLabelName,
|
|
||||||
TaskDetailsSection,
|
|
||||||
TaskActions,
|
|
||||||
TaskDetailsAddLabel,
|
|
||||||
TaskDetailsAddLabelIcon,
|
TaskDetailsAddLabelIcon,
|
||||||
TaskAction,
|
|
||||||
TaskMeta,
|
|
||||||
ActionButtons,
|
|
||||||
ActionButton,
|
ActionButton,
|
||||||
ActionButtonsTitle,
|
AssignUserIcon,
|
||||||
TaskHeader,
|
AssignUserLabel,
|
||||||
ProfileIcon,
|
AssignUsersButton,
|
||||||
TaskDetailsContent,
|
AssignedUsersSection,
|
||||||
TaskDetailsWrapper,
|
DueDateTitle,
|
||||||
TaskDetailsSidebar,
|
Container,
|
||||||
|
LeftSidebar,
|
||||||
|
ContentContainer,
|
||||||
|
LeftSidebarContent,
|
||||||
|
LeftSidebarSection,
|
||||||
|
SidebarTitle,
|
||||||
|
SidebarButton,
|
||||||
|
SidebarButtonText,
|
||||||
|
MarkCompleteButton,
|
||||||
|
HeaderContainer,
|
||||||
|
HeaderLeft,
|
||||||
|
HeaderInnerContainer,
|
||||||
TaskDetailsTitleWrapper,
|
TaskDetailsTitleWrapper,
|
||||||
TaskDetailsTitle,
|
TaskDetailsTitle,
|
||||||
TaskDetailsLabel,
|
ExtraActionsSection,
|
||||||
TaskDetailsAddDetailsButton,
|
HeaderRight,
|
||||||
TaskDetailsEditor,
|
HeaderActionIcon,
|
||||||
TaskDetailsEditorWrapper,
|
EditorContainer,
|
||||||
TaskDetailsMarkdown,
|
InnerContentContainer,
|
||||||
TaskDetailsControls,
|
DescriptionContainer,
|
||||||
ConfirmSave,
|
Labels,
|
||||||
CancelEdit,
|
ChecklistSection,
|
||||||
TaskDetailSectionTitle,
|
MemberList,
|
||||||
TaskDetailLabel,
|
TaskMember,
|
||||||
TaskDetailLabels,
|
TabBarSection,
|
||||||
TaskDetailAssignee,
|
TabBarItem,
|
||||||
TaskDetailAssignees,
|
CommentTextArea,
|
||||||
TaskDetailsAddMemberIcon,
|
CommentEditorContainer,
|
||||||
MetaDetails,
|
CommentEditorActions,
|
||||||
MetaDetail,
|
CommentEditorActionIcon,
|
||||||
MetaDetailTitle,
|
CommentEditorSaveButton,
|
||||||
MetaDetailContent,
|
CommentProfile,
|
||||||
|
CommentInnerWrapper,
|
||||||
|
ActivitySection,
|
||||||
} from './Styles';
|
} from './Styles';
|
||||||
import Checklist, { ChecklistItem, ChecklistItems } from '../Checklist';
|
import Checklist, { ChecklistItem, ChecklistItems } from '../Checklist';
|
||||||
|
import onDragEnd from './onDragEnd';
|
||||||
|
|
||||||
const ChecklistContainer = styled.div``;
|
const ChecklistContainer = styled.div``;
|
||||||
|
|
||||||
type TaskContentProps = {
|
|
||||||
onEditContent: () => void;
|
|
||||||
description: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
type TaskLabelProps = {
|
type TaskLabelProps = {
|
||||||
label: TaskLabel;
|
label: TaskLabel;
|
||||||
onClick: ($target: React.RefObject<HTMLElement>) => void;
|
onClick: ($target: React.RefObject<HTMLElement>) => void;
|
||||||
@ -85,62 +91,15 @@ const TaskLabelItem: React.FC<TaskLabelProps> = ({ label, onClick }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const TaskContent: React.FC<TaskContentProps> = ({ description, onEditContent }) => {
|
|
||||||
return description === '' ? (
|
|
||||||
<TaskDetailsAddDetailsButton onClick={onEditContent}>Add a more detailed description</TaskDetailsAddDetailsButton>
|
|
||||||
) : (
|
|
||||||
<TaskDetailsMarkdown onClick={onEditContent}>
|
|
||||||
<ReactMarkdown source={description} />
|
|
||||||
</TaskDetailsMarkdown>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
type DetailsEditorProps = {
|
type DetailsEditorProps = {
|
||||||
description: string;
|
description: string;
|
||||||
onTaskDescriptionChange: (newDescription: string) => void;
|
onTaskDescriptionChange: (newDescription: string) => void;
|
||||||
onCancel: () => void;
|
onCancel: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const DetailsEditor: React.FC<DetailsEditorProps> = ({
|
|
||||||
description: initialDescription,
|
|
||||||
onTaskDescriptionChange,
|
|
||||||
onCancel,
|
|
||||||
}) => {
|
|
||||||
const [description, setDescription] = useState(initialDescription);
|
|
||||||
const $editorWrapperRef = useRef<HTMLDivElement>(null);
|
|
||||||
const $editorRef = useRef<HTMLTextAreaElement>(null);
|
|
||||||
const handleOutsideClick = () => {
|
|
||||||
onTaskDescriptionChange(description);
|
|
||||||
};
|
|
||||||
useEffect(() => {
|
|
||||||
if ($editorRef && $editorRef.current) {
|
|
||||||
$editorRef.current.focus();
|
|
||||||
$editorRef.current.select();
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useOnOutsideClick($editorWrapperRef, true, handleOutsideClick, null);
|
|
||||||
return (
|
|
||||||
<TaskDetailsEditorWrapper ref={$editorWrapperRef}>
|
|
||||||
<TaskDetailsEditor
|
|
||||||
ref={$editorRef}
|
|
||||||
value={description}
|
|
||||||
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => setDescription(e.currentTarget.value)}
|
|
||||||
/>
|
|
||||||
<TaskDetailsControls>
|
|
||||||
<ConfirmSave variant="relief" onClick={handleOutsideClick}>
|
|
||||||
Save
|
|
||||||
</ConfirmSave>
|
|
||||||
<CancelEdit onClick={onCancel}>
|
|
||||||
<Plus size={16} color="#c2c6dc" />
|
|
||||||
</CancelEdit>
|
|
||||||
</TaskDetailsControls>
|
|
||||||
</TaskDetailsEditorWrapper>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
type TaskDetailsProps = {
|
type TaskDetailsProps = {
|
||||||
task: Task;
|
task: Task;
|
||||||
|
me?: TaskUser | null;
|
||||||
onTaskNameChange: (task: Task, newName: string) => void;
|
onTaskNameChange: (task: Task, newName: string) => void;
|
||||||
onTaskDescriptionChange: (task: Task, newDescription: string) => void;
|
onTaskDescriptionChange: (task: Task, newDescription: string) => void;
|
||||||
onDeleteTask: (task: Task) => void;
|
onDeleteTask: (task: Task) => void;
|
||||||
@ -162,6 +121,7 @@ type TaskDetailsProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const TaskDetails: React.FC<TaskDetailsProps> = ({
|
const TaskDetails: React.FC<TaskDetailsProps> = ({
|
||||||
|
me,
|
||||||
task,
|
task,
|
||||||
onDeleteChecklist,
|
onDeleteChecklist,
|
||||||
onTaskNameChange,
|
onTaskNameChange,
|
||||||
@ -182,163 +142,152 @@ const TaskDetails: React.FC<TaskDetailsProps> = ({
|
|||||||
onToggleChecklistItem,
|
onToggleChecklistItem,
|
||||||
onMemberProfile,
|
onMemberProfile,
|
||||||
}) => {
|
}) => {
|
||||||
const [editorOpen, setEditorOpen] = useState(false);
|
|
||||||
const [description, setDescription] = useState(task.description ?? '');
|
|
||||||
const [taskName, setTaskName] = useState(task.name);
|
const [taskName, setTaskName] = useState(task.name);
|
||||||
const handleClick = () => {
|
const [editTaskDescription, setEditTaskDescription] = useState(() => {
|
||||||
setEditorOpen(!editorOpen);
|
if (task.description) {
|
||||||
};
|
if (task.description.trim() === '' || task.description.trim() === '\\') {
|
||||||
const handleDeleteTask = () => {
|
return true;
|
||||||
onDeleteTask(task);
|
|
||||||
};
|
|
||||||
const $title = useRef<HTMLTextAreaElement>(null);
|
|
||||||
const onKeyDown = (e: React.KeyboardEvent) => {
|
|
||||||
if (e.key === 'Enter') {
|
|
||||||
e.preventDefault();
|
|
||||||
onTaskNameChange(task, taskName);
|
|
||||||
if ($title && $title.current) {
|
|
||||||
$title.current.blur();
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
};
|
return true;
|
||||||
const $unassignedRef = useRef<HTMLDivElement>(null);
|
});
|
||||||
const $addMemberRef = useRef<HTMLDivElement>(null);
|
const [saveTimeout, setSaveTimeout] = useState<any>(null);
|
||||||
const onUnassignedClick = () => {
|
const [showCommentActions, setShowCommentActions] = useState(false);
|
||||||
onOpenAddMemberPopup(task, $unassignedRef);
|
const taskDescriptionRef = useRef(task.description ?? '');
|
||||||
};
|
const $noMemberBtn = useRef<HTMLDivElement>(null);
|
||||||
const onAddMember = ($target: React.RefObject<HTMLElement>) => {
|
const $addMemberBtn = useRef<HTMLDivElement>(null);
|
||||||
onOpenAddMemberPopup(task, $target);
|
const $dueDateBtn = useRef<HTMLDivElement>(null);
|
||||||
};
|
|
||||||
const onAddChecklist = ($target: React.RefObject<HTMLElement>) => {
|
|
||||||
onOpenAddChecklistPopup(task, $target);
|
|
||||||
};
|
|
||||||
const $dueDateLabel = useRef<HTMLDivElement>(null);
|
|
||||||
const $addLabelRef = useRef<HTMLDivElement>(null);
|
|
||||||
|
|
||||||
const onAddLabel = ($target: React.RefObject<HTMLElement>) => {
|
const saveDescription = () => {
|
||||||
onOpenAddLabelPopup(task, $target);
|
onTaskDescriptionChange(task, taskDescriptionRef.current);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onDragEnd = ({ draggableId, source, destination, type }: DropResult) => {
|
|
||||||
if (typeof destination === 'undefined') return;
|
|
||||||
if (!isPositionChanged(source, destination)) return;
|
|
||||||
|
|
||||||
const isChecklist = type === 'checklist';
|
|
||||||
const isSameChecklist = destination.droppableId === source.droppableId;
|
|
||||||
let droppedDraggable: DraggableElement | null = null;
|
|
||||||
let beforeDropDraggables: Array<DraggableElement> | null = null;
|
|
||||||
|
|
||||||
if (!task.checklists) return;
|
|
||||||
if (isChecklist) {
|
|
||||||
const droppedGroup = task.checklists.find(taskGroup => taskGroup.id === draggableId);
|
|
||||||
if (droppedGroup) {
|
|
||||||
droppedDraggable = {
|
|
||||||
id: draggableId,
|
|
||||||
position: droppedGroup.position,
|
|
||||||
};
|
|
||||||
beforeDropDraggables = getSortedDraggables(
|
|
||||||
task.checklists.map(checklist => {
|
|
||||||
return { id: checklist.id, position: checklist.position };
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
if (droppedDraggable === null || beforeDropDraggables === null) {
|
|
||||||
throw new Error('before drop draggables is null');
|
|
||||||
}
|
|
||||||
const afterDropDraggables = getAfterDropDraggableList(
|
|
||||||
beforeDropDraggables,
|
|
||||||
droppedDraggable,
|
|
||||||
isChecklist,
|
|
||||||
isSameChecklist,
|
|
||||||
destination,
|
|
||||||
);
|
|
||||||
const newPosition = getNewDraggablePosition(afterDropDraggables, destination.index);
|
|
||||||
onChecklistDrop({ ...droppedGroup, position: newPosition });
|
|
||||||
} else {
|
|
||||||
throw new Error('task group can not be found');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const targetChecklist = task.checklists.findIndex(
|
|
||||||
checklist => checklist.items.findIndex(item => item.id === draggableId) !== -1,
|
|
||||||
);
|
|
||||||
const droppedChecklistItem = task.checklists[targetChecklist].items.find(item => item.id === draggableId);
|
|
||||||
|
|
||||||
if (droppedChecklistItem) {
|
|
||||||
droppedDraggable = {
|
|
||||||
id: draggableId,
|
|
||||||
position: droppedChecklistItem.position,
|
|
||||||
};
|
|
||||||
beforeDropDraggables = getSortedDraggables(
|
|
||||||
task.checklists[targetChecklist].items.map(item => {
|
|
||||||
return { id: item.id, position: item.position };
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
if (droppedDraggable === null || beforeDropDraggables === null) {
|
|
||||||
throw new Error('before drop draggables is null');
|
|
||||||
}
|
|
||||||
const afterDropDraggables = getAfterDropDraggableList(
|
|
||||||
beforeDropDraggables,
|
|
||||||
droppedDraggable,
|
|
||||||
isChecklist,
|
|
||||||
isSameChecklist,
|
|
||||||
destination,
|
|
||||||
);
|
|
||||||
const newPosition = getNewDraggablePosition(afterDropDraggables, destination.index);
|
|
||||||
const newItem = {
|
|
||||||
...droppedChecklistItem,
|
|
||||||
position: newPosition,
|
|
||||||
};
|
|
||||||
onChecklistItemDrop(droppedChecklistItem.taskChecklistID, destination.droppableId, newItem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Container>
|
||||||
<TaskActions>
|
<LeftSidebar>
|
||||||
<TaskAction onClick={handleDeleteTask}>
|
<LeftSidebarContent>
|
||||||
<Bin size={20} color="#c2c6dc" />
|
<LeftSidebarSection>
|
||||||
</TaskAction>
|
<SidebarTitle>TASK GROUP</SidebarTitle>
|
||||||
<TaskAction onClick={onCloseModal}>
|
<SidebarButton>
|
||||||
<Cross width={16} height={16} />
|
<SidebarButtonText>Release 0.1.0</SidebarButtonText>
|
||||||
</TaskAction>
|
</SidebarButton>
|
||||||
</TaskActions>
|
<DueDateTitle>DUE DATE</DueDateTitle>
|
||||||
<TaskHeader>
|
<SidebarButton
|
||||||
|
ref={$dueDateBtn}
|
||||||
|
onClick={() => {
|
||||||
|
onOpenDueDatePopop(task, $dueDateBtn);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{task.dueDate ? (
|
||||||
|
<SidebarButtonText>{moment(task.dueDate).format('MMM D [at] h:mm A')}</SidebarButtonText>
|
||||||
|
) : (
|
||||||
|
<SidebarButtonText>No due date</SidebarButtonText>
|
||||||
|
)}
|
||||||
|
</SidebarButton>
|
||||||
|
</LeftSidebarSection>
|
||||||
|
<AssignedUsersSection>
|
||||||
|
<DueDateTitle>MEMBERS</DueDateTitle>
|
||||||
|
{task.assigned && task.assigned.length !== 0 ? (
|
||||||
|
<MemberList>
|
||||||
|
{task.assigned.map(m => (
|
||||||
|
<TaskMember
|
||||||
|
key={m.id}
|
||||||
|
member={m}
|
||||||
|
size={32}
|
||||||
|
onMemberProfile={$target => {
|
||||||
|
onMemberProfile($target, m.id);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
<AssignUserIcon
|
||||||
|
ref={$addMemberBtn}
|
||||||
|
onClick={() => {
|
||||||
|
onOpenAddMemberPopup(task, $addMemberBtn);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Plus width={16} height={16} />
|
||||||
|
</AssignUserIcon>
|
||||||
|
</MemberList>
|
||||||
|
) : (
|
||||||
|
<AssignUsersButton
|
||||||
|
ref={$noMemberBtn}
|
||||||
|
onClick={() => {
|
||||||
|
onOpenAddMemberPopup(task, $noMemberBtn);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<AssignUserIcon>
|
||||||
|
<User width={16} height={16} />
|
||||||
|
</AssignUserIcon>
|
||||||
|
<AssignUserLabel>No members</AssignUserLabel>
|
||||||
|
</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>
|
||||||
|
</LeftSidebarContent>
|
||||||
|
</LeftSidebar>
|
||||||
|
<ContentContainer>
|
||||||
|
<HeaderContainer>
|
||||||
|
<HeaderInnerContainer>
|
||||||
|
<HeaderLeft>
|
||||||
|
<MarkCompleteButton
|
||||||
|
invert={task.complete ?? false}
|
||||||
|
onClick={() => {
|
||||||
|
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>
|
||||||
|
</HeaderInnerContainer>
|
||||||
<TaskDetailsTitleWrapper>
|
<TaskDetailsTitleWrapper>
|
||||||
<TaskDetailsTitle
|
<TaskDetailsTitle
|
||||||
ref={$title}
|
|
||||||
value={taskName}
|
value={taskName}
|
||||||
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => setTaskName(e.currentTarget.value)}
|
onChange={e => {
|
||||||
onKeyDown={onKeyDown}
|
setTaskName(e.currentTarget.value);
|
||||||
|
}}
|
||||||
|
onBlur={() => {
|
||||||
|
if (taskName !== task.name) {
|
||||||
|
onTaskNameChange(task, taskName);
|
||||||
|
}
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</TaskDetailsTitleWrapper>
|
</TaskDetailsTitleWrapper>
|
||||||
<TaskMeta>
|
<Labels>
|
||||||
{task.taskGroup.name && (
|
|
||||||
<TaskGroupLabel>
|
|
||||||
{`in list ${(<TaskGroupLabelName>{task.taskGroup.name}</TaskGroupLabelName>)}`}
|
|
||||||
</TaskGroupLabel>
|
|
||||||
)}
|
|
||||||
</TaskMeta>
|
|
||||||
</TaskHeader>
|
|
||||||
<TaskDetailsWrapper>
|
|
||||||
<TaskDetailsContent>
|
|
||||||
<MetaDetails>
|
|
||||||
{task.assigned && task.assigned.length !== 0 && (
|
|
||||||
<MetaDetail>
|
|
||||||
<MetaDetailTitle>MEMBERS</MetaDetailTitle>
|
|
||||||
<MetaDetailContent>
|
|
||||||
{task.assigned &&
|
|
||||||
task.assigned.map(member => (
|
|
||||||
<TaskMember key={member.id} size={32} member={member} onMemberProfile={onMemberProfile} />
|
|
||||||
))}
|
|
||||||
<TaskDetailsAddMemberIcon ref={$addMemberRef} onClick={() => onAddMember($addMemberRef)}>
|
|
||||||
<Plus size={16} color="#c2c6dc" />
|
|
||||||
</TaskDetailsAddMemberIcon>
|
|
||||||
</MetaDetailContent>
|
|
||||||
</MetaDetail>
|
|
||||||
)}
|
|
||||||
{task.labels.length !== 0 && (
|
{task.labels.length !== 0 && (
|
||||||
<MetaDetail>
|
|
||||||
<MetaDetailTitle>LABELS</MetaDetailTitle>
|
|
||||||
<MetaDetailContent>
|
<MetaDetailContent>
|
||||||
{task.labels.map(label => {
|
{task.labels.map(label => {
|
||||||
return (
|
return (
|
||||||
@ -351,40 +300,40 @@ const TaskDetails: React.FC<TaskDetailsProps> = ({
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
<TaskDetailsAddLabelIcon ref={$addLabelRef} onClick={() => onAddLabel($addLabelRef)}>
|
<TaskDetailsAddLabelIcon>
|
||||||
<Plus size={16} color="#c2c6dc" />
|
<Plus width={12} height={12} />
|
||||||
</TaskDetailsAddLabelIcon>
|
</TaskDetailsAddLabelIcon>
|
||||||
</MetaDetailContent>
|
</MetaDetailContent>
|
||||||
</MetaDetail>
|
|
||||||
)}
|
)}
|
||||||
{task.dueDate && (
|
</Labels>
|
||||||
<MetaDetail>
|
</HeaderContainer>
|
||||||
<MetaDetailTitle>DUE DATE</MetaDetailTitle>
|
<InnerContentContainer>
|
||||||
<MetaDetailContent>
|
<DescriptionContainer>
|
||||||
<TaskDueDateButton>{moment(task.dueDate).format('MMM D [at] h:mm A')}</TaskDueDateButton>
|
<EditorContainer
|
||||||
</MetaDetailContent>
|
onClick={e => {
|
||||||
</MetaDetail>
|
if (!editTaskDescription) {
|
||||||
)}
|
setEditTaskDescription(true);
|
||||||
</MetaDetails>
|
}
|
||||||
|
|
||||||
<TaskDetailsSection>
|
|
||||||
<TaskDetailsLabel>Description</TaskDetailsLabel>
|
|
||||||
{editorOpen ? (
|
|
||||||
<DetailsEditor
|
|
||||||
description={description}
|
|
||||||
onTaskDescriptionChange={newDescription => {
|
|
||||||
setEditorOpen(false);
|
|
||||||
setDescription(newDescription);
|
|
||||||
onTaskDescriptionChange(task, newDescription);
|
|
||||||
}}
|
}}
|
||||||
onCancel={() => {
|
>
|
||||||
setEditorOpen(false);
|
<Editor
|
||||||
|
defaultValue={task.description ?? ''}
|
||||||
|
theme={dark}
|
||||||
|
readOnly={!editTaskDescription}
|
||||||
|
autoFocus
|
||||||
|
onChange={value => {
|
||||||
|
setSaveTimeout(() => {
|
||||||
|
clearTimeout(saveTimeout);
|
||||||
|
return setTimeout(saveDescription, 2000);
|
||||||
|
});
|
||||||
|
const text = value();
|
||||||
|
taskDescriptionRef.current = text;
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
) : (
|
</EditorContainer>
|
||||||
<TaskContent description={description} onEditContent={handleClick} />
|
</DescriptionContainer>
|
||||||
)}
|
<ChecklistSection>
|
||||||
<DragDropContext onDragEnd={onDragEnd}>
|
<DragDropContext onDragEnd={result => onDragEnd(result, task, onChecklistDrop, onChecklistItemDrop)}>
|
||||||
<Droppable direction="vertical" type="checklist" droppableId="root">
|
<Droppable direction="vertical" type="checklist" droppableId="root">
|
||||||
{dropProvided => (
|
{dropProvided => (
|
||||||
<ChecklistContainer {...dropProvided.droppableProps} ref={dropProvided.innerRef}>
|
<ChecklistContainer {...dropProvided.droppableProps} ref={dropProvided.innerRef}>
|
||||||
@ -463,32 +412,54 @@ const TaskDetails: React.FC<TaskDetailsProps> = ({
|
|||||||
)}
|
)}
|
||||||
</Droppable>
|
</Droppable>
|
||||||
</DragDropContext>
|
</DragDropContext>
|
||||||
</TaskDetailsSection>
|
</ChecklistSection>
|
||||||
</TaskDetailsContent>
|
<TabBarSection>
|
||||||
<TaskDetailsSidebar>
|
<TabBarItem>Activity</TabBarItem>
|
||||||
<ActionButtons>
|
</TabBarSection>
|
||||||
<ActionButtonsTitle>ADD TO CARD</ActionButtonsTitle>
|
<ActivitySection />
|
||||||
<ActionButton justifyTextContent="flex-start" onClick={() => onToggleTaskComplete(task)}>
|
</InnerContentContainer>
|
||||||
{task.complete ? 'Mark Incomplete' : 'Mark Complete'}
|
<CommentContainer>
|
||||||
</ActionButton>
|
{me && (
|
||||||
<ActionButton justifyTextContent="flex-start" onClick={$target => onAddMember($target)}>
|
<CommentInnerWrapper>
|
||||||
Members
|
<CommentProfile
|
||||||
</ActionButton>
|
member={me}
|
||||||
<ActionButton justifyTextContent="flex-start" onClick={$target => onAddLabel($target)}>
|
size={32}
|
||||||
Labels
|
onMemberProfile={$target => {
|
||||||
</ActionButton>
|
onMemberProfile($target, me.id);
|
||||||
<ActionButton justifyTextContent="flex-start" onClick={$target => onAddChecklist($target)}>
|
}}
|
||||||
Checklist
|
/>
|
||||||
</ActionButton>
|
<CommentEditorContainer>
|
||||||
<ActionButton justifyTextContent="flex-start" onClick={$target => onOpenDueDatePopop(task, $target)}>
|
<CommentTextArea
|
||||||
Due Date
|
disabled
|
||||||
</ActionButton>
|
placeholder="Write a comment..."
|
||||||
<ActionButton justifyTextContent="flex-start">Attachment</ActionButton>
|
onFocus={() => {
|
||||||
<ActionButton justifyTextContent="flex-start">Cover</ActionButton>
|
setShowCommentActions(true);
|
||||||
</ActionButtons>
|
}}
|
||||||
</TaskDetailsSidebar>
|
onBlur={() => {
|
||||||
</TaskDetailsWrapper>
|
setShowCommentActions(false);
|
||||||
</>
|
}}
|
||||||
|
/>
|
||||||
|
<CommentEditorActions visible={showCommentActions}>
|
||||||
|
<CommentEditorActionIcon>
|
||||||
|
<Paperclip width={12} height={12} />
|
||||||
|
</CommentEditorActionIcon>
|
||||||
|
<CommentEditorActionIcon>
|
||||||
|
<At width={12} height={12} />
|
||||||
|
</CommentEditorActionIcon>
|
||||||
|
<CommentEditorActionIcon>
|
||||||
|
<Smile width={12} height={12} />
|
||||||
|
</CommentEditorActionIcon>
|
||||||
|
<CommentEditorActionIcon>
|
||||||
|
<Task width={12} height={12} />
|
||||||
|
</CommentEditorActionIcon>
|
||||||
|
<CommentEditorSaveButton>Save</CommentEditorSaveButton>
|
||||||
|
</CommentEditorActions>
|
||||||
|
</CommentEditorContainer>
|
||||||
|
</CommentInnerWrapper>
|
||||||
|
)}
|
||||||
|
</CommentContainer>
|
||||||
|
</ContentContainer>
|
||||||
|
</Container>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
90
frontend/src/shared/components/TaskDetails/onDragEnd.ts
Normal file
90
frontend/src/shared/components/TaskDetails/onDragEnd.ts
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
import {
|
||||||
|
getSortedDraggables,
|
||||||
|
isPositionChanged,
|
||||||
|
getNewDraggablePosition,
|
||||||
|
getAfterDropDraggableList,
|
||||||
|
} from 'shared/utils/draggables';
|
||||||
|
import { DropResult } from 'react-beautiful-dnd';
|
||||||
|
|
||||||
|
type OnChecklistDropFn = (checklist: TaskChecklist) => void;
|
||||||
|
type OnChecklistItemDropFn = (prevChecklistID: string, checklistID: string, checklistItem: TaskChecklistItem) => void;
|
||||||
|
|
||||||
|
const onDragEnd = (
|
||||||
|
{ draggableId, source, destination, type }: DropResult,
|
||||||
|
task: Task,
|
||||||
|
onChecklistDrop: OnChecklistDropFn,
|
||||||
|
onChecklistItemDrop: OnChecklistItemDropFn,
|
||||||
|
) => {
|
||||||
|
if (typeof destination === 'undefined') return;
|
||||||
|
if (!isPositionChanged(source, destination)) return;
|
||||||
|
|
||||||
|
const isChecklist = type === 'checklist';
|
||||||
|
const isSameChecklist = destination.droppableId === source.droppableId;
|
||||||
|
let droppedDraggable: DraggableElement | null = null;
|
||||||
|
let beforeDropDraggables: Array<DraggableElement> | null = null;
|
||||||
|
|
||||||
|
if (!task.checklists) return;
|
||||||
|
if (isChecklist) {
|
||||||
|
const droppedGroup = task.checklists.find(taskGroup => taskGroup.id === draggableId);
|
||||||
|
if (droppedGroup) {
|
||||||
|
droppedDraggable = {
|
||||||
|
id: draggableId,
|
||||||
|
position: droppedGroup.position,
|
||||||
|
};
|
||||||
|
beforeDropDraggables = getSortedDraggables(
|
||||||
|
task.checklists.map(checklist => {
|
||||||
|
return { id: checklist.id, position: checklist.position };
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
if (droppedDraggable === null || beforeDropDraggables === null) {
|
||||||
|
throw new Error('before drop draggables is null');
|
||||||
|
}
|
||||||
|
const afterDropDraggables = getAfterDropDraggableList(
|
||||||
|
beforeDropDraggables,
|
||||||
|
droppedDraggable,
|
||||||
|
isChecklist,
|
||||||
|
isSameChecklist,
|
||||||
|
destination,
|
||||||
|
);
|
||||||
|
const newPosition = getNewDraggablePosition(afterDropDraggables, destination.index);
|
||||||
|
onChecklistDrop({ ...droppedGroup, position: newPosition });
|
||||||
|
} else {
|
||||||
|
throw new Error('task group can not be found');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const targetChecklist = task.checklists.findIndex(
|
||||||
|
checklist => checklist.items.findIndex(item => item.id === draggableId) !== -1,
|
||||||
|
);
|
||||||
|
const droppedChecklistItem = task.checklists[targetChecklist].items.find(item => item.id === draggableId);
|
||||||
|
|
||||||
|
if (droppedChecklistItem) {
|
||||||
|
droppedDraggable = {
|
||||||
|
id: draggableId,
|
||||||
|
position: droppedChecklistItem.position,
|
||||||
|
};
|
||||||
|
beforeDropDraggables = getSortedDraggables(
|
||||||
|
task.checklists[targetChecklist].items.map(item => {
|
||||||
|
return { id: item.id, position: item.position };
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
if (droppedDraggable === null || beforeDropDraggables === null) {
|
||||||
|
throw new Error('before drop draggables is null');
|
||||||
|
}
|
||||||
|
const afterDropDraggables = getAfterDropDraggableList(
|
||||||
|
beforeDropDraggables,
|
||||||
|
droppedDraggable,
|
||||||
|
isChecklist,
|
||||||
|
isSameChecklist,
|
||||||
|
destination,
|
||||||
|
);
|
||||||
|
const newPosition = getNewDraggablePosition(afterDropDraggables, destination.index);
|
||||||
|
const newItem = {
|
||||||
|
...droppedChecklistItem,
|
||||||
|
position: newPosition,
|
||||||
|
};
|
||||||
|
onChecklistItemDrop(droppedChecklistItem.taskChecklistID, destination.droppableId, newItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default onDragEnd;
|
@ -1185,6 +1185,16 @@ export type FindTaskQuery = (
|
|||||||
& Pick<ProfileIcon, 'url' | 'initials' | 'bgColor'>
|
& Pick<ProfileIcon, 'url' | 'initials' | 'bgColor'>
|
||||||
) }
|
) }
|
||||||
)> }
|
)> }
|
||||||
|
), me: (
|
||||||
|
{ __typename?: 'MePayload' }
|
||||||
|
& { user: (
|
||||||
|
{ __typename?: 'UserAccount' }
|
||||||
|
& Pick<UserAccount, 'id' | 'fullName'>
|
||||||
|
& { profileIcon: (
|
||||||
|
{ __typename?: 'ProfileIcon' }
|
||||||
|
& Pick<ProfileIcon, 'initials' | 'bgColor' | 'url'>
|
||||||
|
) }
|
||||||
|
) }
|
||||||
) }
|
) }
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -2513,6 +2523,17 @@ export const FindTaskDocument = gql`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
me {
|
||||||
|
user {
|
||||||
|
id
|
||||||
|
fullName
|
||||||
|
profileIcon {
|
||||||
|
initials
|
||||||
|
bgColor
|
||||||
|
url
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -52,4 +52,15 @@ query findTask($taskID: UUID!) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
me {
|
||||||
|
user {
|
||||||
|
id
|
||||||
|
fullName
|
||||||
|
profileIcon {
|
||||||
|
initials
|
||||||
|
bgColor
|
||||||
|
url
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
14
frontend/src/shared/hooks/useWindowSize.ts
Normal file
14
frontend/src/shared/hooks/useWindowSize.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { useLayoutEffect, useState } from 'react';
|
||||||
|
|
||||||
|
export default function useWindowSize() {
|
||||||
|
const [size, setSize] = useState([0, 0]);
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
function updateSize() {
|
||||||
|
setSize([window.innerWidth, window.innerHeight]);
|
||||||
|
}
|
||||||
|
window.addEventListener('resize', updateSize);
|
||||||
|
updateSize();
|
||||||
|
return () => window.removeEventListener('resize', updateSize);
|
||||||
|
}, []);
|
||||||
|
return size;
|
||||||
|
}
|
12
frontend/src/shared/icons/At.tsx
Normal file
12
frontend/src/shared/icons/At.tsx
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import Icon, { IconProps } from './Icon';
|
||||||
|
|
||||||
|
const At: React.FC<IconProps> = ({ width = '16px', height = '16px', className }) => {
|
||||||
|
return (
|
||||||
|
<Icon width={width} height={height} className={className} viewBox="0 0 512 512">
|
||||||
|
<path d="M256 8C118.941 8 8 118.919 8 256c0 137.059 110.919 248 248 248 48.154 0 95.342-14.14 135.408-40.223 12.005-7.815 14.625-24.288 5.552-35.372l-10.177-12.433c-7.671-9.371-21.179-11.667-31.373-5.129C325.92 429.757 291.314 440 256 440c-101.458 0-184-82.542-184-184S154.542 72 256 72c100.139 0 184 57.619 184 160 0 38.786-21.093 79.742-58.17 83.693-17.349-.454-16.91-12.857-13.476-30.024l23.433-121.11C394.653 149.75 383.308 136 368.225 136h-44.981a13.518 13.518 0 0 0-13.432 11.993l-.01.092c-14.697-17.901-40.448-21.775-59.971-21.775-74.58 0-137.831 62.234-137.831 151.46 0 65.303 36.785 105.87 96 105.87 26.984 0 57.369-15.637 74.991-38.333 9.522 34.104 40.613 34.103 70.71 34.103C462.609 379.41 504 307.798 504 232 504 95.653 394.023 8 256 8zm-21.68 304.43c-22.249 0-36.07-15.623-36.07-40.771 0-44.993 30.779-72.729 58.63-72.729 22.292 0 35.601 15.241 35.601 40.77 0 45.061-33.875 72.73-58.161 72.73z" />
|
||||||
|
</Icon>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default At;
|
12
frontend/src/shared/icons/Clone.tsx
Normal file
12
frontend/src/shared/icons/Clone.tsx
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import Icon, { IconProps } from './Icon';
|
||||||
|
|
||||||
|
const Clone: React.FC<IconProps> = ({ width = '16px', height = '16px', className }) => {
|
||||||
|
return (
|
||||||
|
<Icon width={width} height={height} className={className} viewBox="0 0 512 512">
|
||||||
|
<path d="M464 0c26.51 0 48 21.49 48 48v288c0 26.51-21.49 48-48 48H176c-26.51 0-48-21.49-48-48V48c0-26.51 21.49-48 48-48h288M176 416c-44.112 0-80-35.888-80-80V128H48c-26.51 0-48 21.49-48 48v288c0 26.51 21.49 48 48 48h288c26.51 0 48-21.49 48-48v-48H176z" />
|
||||||
|
</Icon>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Clone;
|
12
frontend/src/shared/icons/Paperclip.tsx
Normal file
12
frontend/src/shared/icons/Paperclip.tsx
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import Icon, { IconProps } from './Icon';
|
||||||
|
|
||||||
|
const Paperclip: React.FC<IconProps> = ({ width = '16px', height = '16px', className }) => {
|
||||||
|
return (
|
||||||
|
<Icon width={width} height={height} className={className} viewBox="0 0 448 512">
|
||||||
|
<path d="M43.246 466.142c-58.43-60.289-57.341-157.511 1.386-217.581L254.392 34c44.316-45.332 116.351-45.336 160.671 0 43.89 44.894 43.943 117.329 0 162.276L232.214 383.128c-29.855 30.537-78.633 30.111-107.982-.998-28.275-29.97-27.368-77.473 1.452-106.953l143.743-146.835c6.182-6.314 16.312-6.422 22.626-.241l22.861 22.379c6.315 6.182 6.422 16.312.241 22.626L171.427 319.927c-4.932 5.045-5.236 13.428-.648 18.292 4.372 4.634 11.245 4.711 15.688.165l182.849-186.851c19.613-20.062 19.613-52.725-.011-72.798-19.189-19.627-49.957-19.637-69.154 0L90.39 293.295c-34.763 35.56-35.299 93.12-1.191 128.313 34.01 35.093 88.985 35.137 123.058.286l172.06-175.999c6.177-6.319 16.307-6.433 22.626-.256l22.877 22.364c6.319 6.177 6.434 16.307.256 22.626l-172.06 175.998c-59.576 60.938-155.943 60.216-214.77-.485z" />
|
||||||
|
</Icon>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Paperclip;
|
@ -1,21 +1,12 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import Icon, { IconProps } from './Icon';
|
||||||
|
|
||||||
type Props = {
|
const Plus: React.FC<IconProps> = ({ width = '16px', height = '16px', className }) => {
|
||||||
size: number | string;
|
|
||||||
color: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
const Plus = ({ size, color }: Props) => {
|
|
||||||
return (
|
return (
|
||||||
<svg fill={color} xmlns="http://www.w3.org/2000/svg" width={size} height={size} viewBox="0 0 16 16">
|
<Icon width={width} height={height} className={className} viewBox="0 0 448 512">
|
||||||
<path d="M15.5 6h-5.5v-5.5c0-0.276-0.224-0.5-0.5-0.5h-3c-0.276 0-0.5 0.224-0.5 0.5v5.5h-5.5c-0.276 0-0.5 0.224-0.5 0.5v3c0 0.276 0.224 0.5 0.5 0.5h5.5v5.5c0 0.276 0.224 0.5 0.5 0.5h3c0.276 0 0.5-0.224 0.5-0.5v-5.5h5.5c0.276 0 0.5-0.224 0.5-0.5v-3c0-0.276-0.224-0.5-0.5-0.5z" />
|
<path d="M416 208H272V64c0-17.67-14.33-32-32-32h-32c-17.67 0-32 14.33-32 32v144H32c-17.67 0-32 14.33-32 32v32c0 17.67 14.33 32 32 32h144v144c0 17.67 14.33 32 32 32h32c17.67 0 32-14.33 32-32V304h144c17.67 0 32-14.33 32-32v-32c0-17.67-14.33-32-32-32z" />
|
||||||
</svg>
|
</Icon>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
Plus.defaultProps = {
|
|
||||||
size: 16,
|
|
||||||
color: '#000',
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Plus;
|
export default Plus;
|
||||||
|
12
frontend/src/shared/icons/Share.tsx
Normal file
12
frontend/src/shared/icons/Share.tsx
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import Icon, { IconProps } from './Icon';
|
||||||
|
|
||||||
|
const Share: React.FC<IconProps> = ({ width = '16px', height = '16px', className }) => {
|
||||||
|
return (
|
||||||
|
<Icon width={width} height={height} className={className} viewBox="0 0 512 512">
|
||||||
|
<path d="M503.691 189.836L327.687 37.851C312.281 24.546 288 35.347 288 56.015v80.053C127.371 137.907 0 170.1 0 322.326c0 61.441 39.581 122.309 83.333 154.132 13.653 9.931 33.111-2.533 28.077-18.631C66.066 312.814 132.917 274.316 288 272.085V360c0 20.7 24.3 31.453 39.687 18.164l176.004-152c11.071-9.562 11.086-26.753 0-36.328z" />
|
||||||
|
</Icon>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Share;
|
12
frontend/src/shared/icons/Smile.tsx
Normal file
12
frontend/src/shared/icons/Smile.tsx
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import Icon, { IconProps } from './Icon';
|
||||||
|
|
||||||
|
const Smile: React.FC<IconProps> = ({ width = '16px', height = '16px', className }) => {
|
||||||
|
return (
|
||||||
|
<Icon width={width} height={height} className={className} viewBox="0 0 496 512">
|
||||||
|
<path d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 448c-110.3 0-200-89.7-200-200S137.7 56 248 56s200 89.7 200 200-89.7 200-200 200zm-80-216c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm160 0c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm4 72.6c-20.8 25-51.5 39.4-84 39.4s-63.2-14.3-84-39.4c-8.5-10.2-23.7-11.5-33.8-3.1-10.2 8.5-11.5 23.6-3.1 33.8 30 36 74.1 56.6 120.9 56.6s90.9-20.6 120.9-56.6c8.5-10.2 7.1-25.3-3.1-33.8-10.1-8.4-25.3-7.1-33.8 3.1z" />
|
||||||
|
</Icon>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Smile;
|
12
frontend/src/shared/icons/Task.tsx
Normal file
12
frontend/src/shared/icons/Task.tsx
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import Icon, { IconProps } from './Icon';
|
||||||
|
|
||||||
|
const Task: React.FC<IconProps> = ({ width = '16px', height = '16px', className }) => {
|
||||||
|
return (
|
||||||
|
<Icon width={width} height={height} className={className} viewBox="0 0 512 512">
|
||||||
|
<path d="M139.61 35.5a12 12 0 0 0-17 0L58.93 98.81l-22.7-22.12a12 12 0 0 0-17 0L3.53 92.41a12 12 0 0 0 0 17l47.59 47.4a12.78 12.78 0 0 0 17.61 0l15.59-15.62L156.52 69a12.09 12.09 0 0 0 .09-17zm0 159.19a12 12 0 0 0-17 0l-63.68 63.72-22.7-22.1a12 12 0 0 0-17 0L3.53 252a12 12 0 0 0 0 17L51 316.5a12.77 12.77 0 0 0 17.6 0l15.7-15.69 72.2-72.22a12 12 0 0 0 .09-16.9zM64 368c-26.49 0-48.59 21.5-48.59 48S37.53 464 64 464a48 48 0 0 0 0-96zm432 16H208a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h288a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-320H208a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h288a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 160H208a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h288a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16z" />
|
||||||
|
</Icon>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Task;
|
@ -1,9 +1,15 @@
|
|||||||
import Cross from './Cross';
|
import Cross from './Cross';
|
||||||
import Cog from './Cog';
|
import Cog from './Cog';
|
||||||
|
import At from './At';
|
||||||
|
import Task from './Task';
|
||||||
|
import Smile from './Smile';
|
||||||
|
import Paperclip from './Paperclip';
|
||||||
import Calendar from './Calendar';
|
import Calendar from './Calendar';
|
||||||
|
import Clone from './Clone';
|
||||||
import Sort from './Sort';
|
import Sort from './Sort';
|
||||||
import Filter from './Filter';
|
import Filter from './Filter';
|
||||||
import DoubleChevronUp from './DoubleChevronUp';
|
import DoubleChevronUp from './DoubleChevronUp';
|
||||||
|
import Share from './Share';
|
||||||
import Crown from './Crown';
|
import Crown from './Crown';
|
||||||
import BarChart from './BarChart';
|
import BarChart from './BarChart';
|
||||||
import UserPlus from './UserPlus';
|
import UserPlus from './UserPlus';
|
||||||
@ -69,9 +75,14 @@ export {
|
|||||||
Square,
|
Square,
|
||||||
Filter,
|
Filter,
|
||||||
Sort,
|
Sort,
|
||||||
|
At,
|
||||||
|
Smile,
|
||||||
DoubleChevronUp,
|
DoubleChevronUp,
|
||||||
UserPlus,
|
UserPlus,
|
||||||
Crown,
|
Crown,
|
||||||
ToggleOn,
|
ToggleOn,
|
||||||
Calendar,
|
Calendar,
|
||||||
|
Clone,
|
||||||
|
Paperclip,
|
||||||
|
Share,
|
||||||
};
|
};
|
||||||
|
86
frontend/src/shared/utils/editorTheme.ts
Normal file
86
frontend/src/shared/utils/editorTheme.ts
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
import theme from 'App/ThemeStyles';
|
||||||
|
|
||||||
|
const colors = {
|
||||||
|
almostBlack: '#181A1B',
|
||||||
|
lightBlack: '#2F3336',
|
||||||
|
almostWhite: '#E6E6E6',
|
||||||
|
white: '#FFF',
|
||||||
|
white10: 'rgba(255, 255, 255, 0.1)',
|
||||||
|
black: '#000',
|
||||||
|
black10: 'rgba(0, 0, 0, 0.1)',
|
||||||
|
primary: '#1AB6FF',
|
||||||
|
greyLight: '#F4F7FA',
|
||||||
|
grey: '#E8EBED',
|
||||||
|
greyMid: '#C5CCD3',
|
||||||
|
greyDark: '#DAE1E9',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const base = {
|
||||||
|
...colors,
|
||||||
|
fontFamily: "'Droid Sans', sans-serif",
|
||||||
|
fontFamilyMono: "'SFMono-Regular',Consolas,'Liberation Mono', Menlo, Courier,monospace",
|
||||||
|
fontWeight: 400,
|
||||||
|
zIndex: 10000,
|
||||||
|
link: colors.primary,
|
||||||
|
placeholder: '#B1BECC',
|
||||||
|
textSecondary: '#4E5C6E',
|
||||||
|
textLight: colors.white,
|
||||||
|
textHighlight: '#b3e7ff',
|
||||||
|
selected: colors.primary,
|
||||||
|
codeComment: '#6a737d',
|
||||||
|
codePunctuation: '#5e6687',
|
||||||
|
codeNumber: '#d73a49',
|
||||||
|
codeProperty: '#c08b30',
|
||||||
|
codeTag: '#3d8fd1',
|
||||||
|
codeString: '#032f62',
|
||||||
|
codeSelector: '#6679cc',
|
||||||
|
codeAttr: '#c76b29',
|
||||||
|
codeEntity: '#22a2c9',
|
||||||
|
codeKeyword: '#d73a49',
|
||||||
|
codeFunction: '#6f42c1',
|
||||||
|
codeStatement: '#22a2c9',
|
||||||
|
codePlaceholder: '#3d8fd1',
|
||||||
|
codeInserted: '#202746',
|
||||||
|
codeImportant: '#c94922',
|
||||||
|
|
||||||
|
blockToolbarBackground: colors.white,
|
||||||
|
blockToolbarTrigger: colors.greyMid,
|
||||||
|
blockToolbarTriggerIcon: colors.white,
|
||||||
|
blockToolbarItem: colors.almostBlack,
|
||||||
|
blockToolbarText: colors.almostBlack,
|
||||||
|
blockToolbarHoverBackground: colors.greyLight,
|
||||||
|
blockToolbarDivider: colors.greyMid,
|
||||||
|
|
||||||
|
noticeInfoBackground: '#F5BE31',
|
||||||
|
noticeInfoText: colors.almostBlack,
|
||||||
|
noticeTipBackground: '#9E5CF7',
|
||||||
|
noticeTipText: colors.white,
|
||||||
|
noticeWarningBackground: '#FF5C80',
|
||||||
|
noticeWarningText: colors.white,
|
||||||
|
};
|
||||||
|
export const dark = {
|
||||||
|
...base,
|
||||||
|
background: 'transparent',
|
||||||
|
text: `rgba(${theme.colors.text.primary})`,
|
||||||
|
code: `rgba(${theme.colors.text.primary})`,
|
||||||
|
cursor: `rgba(${theme.colors.text.primary})`,
|
||||||
|
divider: '#4E5C6E',
|
||||||
|
placeholder: '#52657A',
|
||||||
|
|
||||||
|
toolbarBackground: colors.white,
|
||||||
|
toolbarInput: colors.black10,
|
||||||
|
toolbarItem: colors.lightBlack,
|
||||||
|
|
||||||
|
tableDivider: colors.lightBlack,
|
||||||
|
tableSelected: colors.primary,
|
||||||
|
tableSelectedBackground: '#002333',
|
||||||
|
|
||||||
|
quote: colors.greyDark,
|
||||||
|
codeBackground: colors.black,
|
||||||
|
codeBorder: colors.lightBlack,
|
||||||
|
codeString: '#3d8fd1',
|
||||||
|
horizontalRule: colors.lightBlack,
|
||||||
|
imageErrorBackground: 'rgba(0, 0, 0, 0.5)',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default dark;
|
@ -1534,6 +1534,13 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@emotion/memoize" "0.7.4"
|
"@emotion/memoize" "0.7.4"
|
||||||
|
|
||||||
|
"@emotion/is-prop-valid@^0.8.8":
|
||||||
|
version "0.8.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz#db28b1c4368a259b60a97311d6a952d4fd01ac1a"
|
||||||
|
integrity sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==
|
||||||
|
dependencies:
|
||||||
|
"@emotion/memoize" "0.7.4"
|
||||||
|
|
||||||
"@emotion/memoize@0.7.4":
|
"@emotion/memoize@0.7.4":
|
||||||
version "0.7.4"
|
version "0.7.4"
|
||||||
resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.4.tgz#19bf0f5af19149111c40d98bb0cf82119f5d9eeb"
|
resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.4.tgz#19bf0f5af19149111c40d98bb0cf82119f5d9eeb"
|
||||||
@ -3637,13 +3644,6 @@
|
|||||||
text-table "^0.2.0"
|
text-table "^0.2.0"
|
||||||
webpack-log "^1.1.2"
|
webpack-log "^1.1.2"
|
||||||
|
|
||||||
"@welldone-software/why-did-you-render@^4.2.2":
|
|
||||||
version "4.2.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/@welldone-software/why-did-you-render/-/why-did-you-render-4.2.2.tgz#720128a4f626997ece1ac455a7b13f9ef10dae0a"
|
|
||||||
integrity sha512-v08t2WXFQdnxkPodXzbPeho3FwgrlwzjwxasN+8A1LSZnkcxJpYvOF8/z+OySqehC44JT6oPB1KEnBVMrebHdw==
|
|
||||||
dependencies:
|
|
||||||
lodash "^4"
|
|
||||||
|
|
||||||
"@wry/context@^0.4.0":
|
"@wry/context@^0.4.0":
|
||||||
version "0.4.4"
|
version "0.4.4"
|
||||||
resolved "https://registry.yarnpkg.com/@wry/context/-/context-0.4.4.tgz#e50f5fa1d6cfaabf2977d1fda5ae91717f8815f8"
|
resolved "https://registry.yarnpkg.com/@wry/context/-/context-0.4.4.tgz#e50f5fa1d6cfaabf2977d1fda5ae91717f8815f8"
|
||||||
@ -3760,18 +3760,6 @@ adjust-sourcemap-loader@2.0.0:
|
|||||||
object-path "0.11.4"
|
object-path "0.11.4"
|
||||||
regex-parser "2.2.10"
|
regex-parser "2.2.10"
|
||||||
|
|
||||||
ag-grid-community@^23.2.0:
|
|
||||||
version "23.2.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/ag-grid-community/-/ag-grid-community-23.2.0.tgz#889f52e8eb91c167c2ac7477938cbf498a54f67c"
|
|
||||||
integrity sha512-aG7Ghfu79HeqOCd50GhFSeZUX1Tw9BVUX1VKMuglkAcwYPTQjuYvYT7QVQB5FGzfFjcVq4a1QFfcgdoAcZYJIA==
|
|
||||||
|
|
||||||
ag-grid-react@^23.2.0:
|
|
||||||
version "23.2.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/ag-grid-react/-/ag-grid-react-23.2.0.tgz#00a54cb4e83c0d35a49c202e5833e3bb20d8cfa8"
|
|
||||||
integrity sha512-lDGV+WX0Nj5biNOJRSErFehXG+nqkbuXPMS7YJxEDWJLJxtOF0INP5sL6dtxV12j/XHqXa+M2CgQBXZWZq+EWg==
|
|
||||||
dependencies:
|
|
||||||
prop-types "^15.6.2"
|
|
||||||
|
|
||||||
agent-base@4, agent-base@^4.3.0:
|
agent-base@4, agent-base@^4.3.0:
|
||||||
version "4.3.0"
|
version "4.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
|
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
|
||||||
@ -5852,6 +5840,11 @@ compression@^1.7.4:
|
|||||||
safe-buffer "5.1.2"
|
safe-buffer "5.1.2"
|
||||||
vary "~1.1.2"
|
vary "~1.1.2"
|
||||||
|
|
||||||
|
compute-scroll-into-view@^1.0.14:
|
||||||
|
version "1.0.14"
|
||||||
|
resolved "https://registry.yarnpkg.com/compute-scroll-into-view/-/compute-scroll-into-view-1.0.14.tgz#80e3ebb25d6aa89f42e533956cb4b16a04cfe759"
|
||||||
|
integrity sha512-mKDjINe3tc6hGelUMNDzuhorIUZ7kS7BwyY0r2wQd2HOH2tRuJykiC06iSEX8y1TuhNzvz4GcJnK16mM2J1NMQ==
|
||||||
|
|
||||||
computed-style@~0.1.3:
|
computed-style@~0.1.3:
|
||||||
version "0.1.4"
|
version "0.1.4"
|
||||||
resolved "https://registry.yarnpkg.com/computed-style/-/computed-style-0.1.4.tgz#7f344fd8584b2e425bedca4a1afc0e300bb05d74"
|
resolved "https://registry.yarnpkg.com/computed-style/-/computed-style-0.1.4.tgz#7f344fd8584b2e425bedca4a1afc0e300bb05d74"
|
||||||
@ -7003,6 +6996,11 @@ entities@^2.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4"
|
resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4"
|
||||||
integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw==
|
integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw==
|
||||||
|
|
||||||
|
entities@~2.0.0:
|
||||||
|
version "2.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.3.tgz#5c487e5742ab93c15abb5da22759b8590ec03b7f"
|
||||||
|
integrity sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==
|
||||||
|
|
||||||
env-ci@^2.1.0:
|
env-ci@^2.1.0:
|
||||||
version "2.6.0"
|
version "2.6.0"
|
||||||
resolved "https://registry.yarnpkg.com/env-ci/-/env-ci-2.6.0.tgz#3fc46537c972b4d3ab5f0b82d07dfc1491297662"
|
resolved "https://registry.yarnpkg.com/env-ci/-/env-ci-2.6.0.tgz#3fc46537c972b4d3ab5f0b82d07dfc1491297662"
|
||||||
@ -10464,6 +10462,13 @@ lines-and-columns@^1.1.6:
|
|||||||
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00"
|
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00"
|
||||||
integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=
|
integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=
|
||||||
|
|
||||||
|
linkify-it@^2.0.0:
|
||||||
|
version "2.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.2.0.tgz#e3b54697e78bf915c70a38acd78fd09e0058b1cf"
|
||||||
|
integrity sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==
|
||||||
|
dependencies:
|
||||||
|
uc.micro "^1.0.1"
|
||||||
|
|
||||||
listr-silent-renderer@^1.1.1:
|
listr-silent-renderer@^1.1.1:
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz#924b5a3757153770bf1a8e3fbf74b8bbf3f9242e"
|
resolved "https://registry.yarnpkg.com/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz#924b5a3757153770bf1a8e3fbf74b8bbf3f9242e"
|
||||||
@ -10684,7 +10689,7 @@ lodash.xorby@^4.7.0:
|
|||||||
resolved "https://registry.yarnpkg.com/lodash.xorby/-/lodash.xorby-4.7.0.tgz#9c19a6f9f063a6eb53dd03c1b6871799801463d7"
|
resolved "https://registry.yarnpkg.com/lodash.xorby/-/lodash.xorby-4.7.0.tgz#9c19a6f9f063a6eb53dd03c1b6871799801463d7"
|
||||||
integrity sha1-nBmm+fBjputT3QPBtocXmYAUY9c=
|
integrity sha1-nBmm+fBjputT3QPBtocXmYAUY9c=
|
||||||
|
|
||||||
lodash@4.17.15, "lodash@>=3.5 <5", lodash@^4, lodash@^4.0.1, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4, lodash@^4.17.5:
|
lodash@4.17.15, "lodash@>=3.5 <5", lodash@^4.0.1, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4, lodash@^4.17.5:
|
||||||
version "4.17.15"
|
version "4.17.15"
|
||||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
|
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
|
||||||
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
|
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
|
||||||
@ -10840,6 +10845,27 @@ markdown-escapes@^1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.4.tgz#c95415ef451499d7602b91095f3c8e8975f78535"
|
resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.4.tgz#c95415ef451499d7602b91095f3c8e8975f78535"
|
||||||
integrity sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==
|
integrity sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==
|
||||||
|
|
||||||
|
markdown-it-container@^3.0.0:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/markdown-it-container/-/markdown-it-container-3.0.0.tgz#1d19b06040a020f9a827577bb7dbf67aa5de9a5b"
|
||||||
|
integrity sha512-y6oKTq4BB9OQuY/KLfk/O3ysFhB3IMYoIWhGJEidXt1NQFocFK2sA2t0NYZAMyMShAGL6x5OPIbrmXPIqaN9rw==
|
||||||
|
|
||||||
|
markdown-it-mark@^3.0.0:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/markdown-it-mark/-/markdown-it-mark-3.0.0.tgz#27c3e39ef3cc310b2dde5375082c9fa912983cda"
|
||||||
|
integrity sha512-HqMWeKfMMOu4zBO0emmxsoMWmbf2cPKZY1wP6FsTbKmicFfp5y4L3KXAsNeO1rM6NTJVOrNlLKMPjWzriBGspw==
|
||||||
|
|
||||||
|
markdown-it@^10.0.0:
|
||||||
|
version "10.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-10.0.0.tgz#abfc64f141b1722d663402044e43927f1f50a8dc"
|
||||||
|
integrity sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==
|
||||||
|
dependencies:
|
||||||
|
argparse "^1.0.7"
|
||||||
|
entities "~2.0.0"
|
||||||
|
linkify-it "^2.0.0"
|
||||||
|
mdurl "^1.0.1"
|
||||||
|
uc.micro "^1.0.5"
|
||||||
|
|
||||||
markdown-to-jsx@^6.9.1, markdown-to-jsx@^6.9.3:
|
markdown-to-jsx@^6.9.1, markdown-to-jsx@^6.9.3:
|
||||||
version "6.11.0"
|
version "6.11.0"
|
||||||
resolved "https://registry.yarnpkg.com/markdown-to-jsx/-/markdown-to-jsx-6.11.0.tgz#a2e3f2bc781c3402d8bb0f8e0a12a186474623b0"
|
resolved "https://registry.yarnpkg.com/markdown-to-jsx/-/markdown-to-jsx-6.11.0.tgz#a2e3f2bc781c3402d8bb0f8e0a12a186474623b0"
|
||||||
@ -11717,6 +11743,11 @@ optionator@^0.8.1, optionator@^0.8.3:
|
|||||||
type-check "~0.3.2"
|
type-check "~0.3.2"
|
||||||
word-wrap "~1.2.3"
|
word-wrap "~1.2.3"
|
||||||
|
|
||||||
|
orderedmap@^1.1.0:
|
||||||
|
version "1.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/orderedmap/-/orderedmap-1.1.1.tgz#c618e77611b3b21d0fe3edc92586265e0059c789"
|
||||||
|
integrity sha512-3Ux8um0zXbVacKUkcytc0u3HgC0b0bBLT+I60r2J/En72cI0nZffqrA7Xtf2Hqs27j1g82llR5Mhbd0Z1XW4AQ==
|
||||||
|
|
||||||
original@^1.0.0:
|
original@^1.0.0:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/original/-/original-1.0.2.tgz#e442a61cffe1c5fd20a65f3261c26663b303f25f"
|
resolved "https://registry.yarnpkg.com/original/-/original-1.0.2.tgz#e442a61cffe1c5fd20a65f3261c26663b303f25f"
|
||||||
@ -11750,6 +11781,11 @@ os-tmpdir@~1.0.2:
|
|||||||
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
|
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
|
||||||
integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
|
integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
|
||||||
|
|
||||||
|
outline-icons@^1.21.0-3:
|
||||||
|
version "1.21.0-6"
|
||||||
|
resolved "https://registry.yarnpkg.com/outline-icons/-/outline-icons-1.21.0-6.tgz#bbf63fe6cc88ca2fe391e6ba6cc8b62a948607e3"
|
||||||
|
integrity sha512-iEVK2zTEZ3sLFLsko/V6z3AEiM2EAjEUyLIOzAT2cqRglIbaIWdyitotKVMb2hWZo66bSvHxA/Rdvv51sw5RhA==
|
||||||
|
|
||||||
p-defer@^1.0.0:
|
p-defer@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c"
|
resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c"
|
||||||
@ -12966,6 +13002,13 @@ prisma-yml@1.34.10:
|
|||||||
scuid "^1.0.2"
|
scuid "^1.0.2"
|
||||||
yaml-ast-parser "^0.0.40"
|
yaml-ast-parser "^0.0.40"
|
||||||
|
|
||||||
|
prismjs@^1.19.0:
|
||||||
|
version "1.21.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.21.0.tgz#36c086ec36b45319ec4218ee164c110f9fc015a3"
|
||||||
|
integrity sha512-uGdSIu1nk3kej2iZsLyDoJ7e9bnPzIgY0naW/HdknGj61zScaprVEVGHrPoXqI+M9sP0NDnTK2jpkvmldpuqDw==
|
||||||
|
optionalDependencies:
|
||||||
|
clipboard "^2.0.0"
|
||||||
|
|
||||||
prismjs@^1.8.4:
|
prismjs@^1.8.4:
|
||||||
version "1.19.0"
|
version "1.19.0"
|
||||||
resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.19.0.tgz#713afbd45c3baca4b321569f2df39e17e729d4dc"
|
resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.19.0.tgz#713afbd45c3baca4b321569f2df39e17e729d4dc"
|
||||||
@ -13071,6 +13114,129 @@ property-information@^5.0.0, property-information@^5.3.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
xtend "^4.0.0"
|
xtend "^4.0.0"
|
||||||
|
|
||||||
|
prosemirror-commands@^1.1.4:
|
||||||
|
version "1.1.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/prosemirror-commands/-/prosemirror-commands-1.1.4.tgz#991563e67623acab4f8c510fad1570f8b4693780"
|
||||||
|
integrity sha512-kj4Qi+8h3EpJtZuuEDwZ9h2/QNGWDsIX/CzjmClxi9GhxWyBUMVUvIFk0mgdqHyX20lLeGmOpc0TLA5aPzgpWg==
|
||||||
|
dependencies:
|
||||||
|
prosemirror-model "^1.0.0"
|
||||||
|
prosemirror-state "^1.0.0"
|
||||||
|
prosemirror-transform "^1.0.0"
|
||||||
|
|
||||||
|
prosemirror-dropcursor@^1.3.2:
|
||||||
|
version "1.3.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/prosemirror-dropcursor/-/prosemirror-dropcursor-1.3.2.tgz#28738c4ed7102e814d7a8a26d70018523fc7cd6d"
|
||||||
|
integrity sha512-4c94OUGyobGnwcQI70OXyMhE/9T4aTgjU+CHxkd5c7D+jH/J0mKM/lk+jneFVKt7+E4/M0D9HzRPifu8U28Thw==
|
||||||
|
dependencies:
|
||||||
|
prosemirror-state "^1.0.0"
|
||||||
|
prosemirror-transform "^1.1.0"
|
||||||
|
prosemirror-view "^1.1.0"
|
||||||
|
|
||||||
|
prosemirror-gapcursor@^1.1.5:
|
||||||
|
version "1.1.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/prosemirror-gapcursor/-/prosemirror-gapcursor-1.1.5.tgz#0c37fd6cbb1d7c46358c2e7397f8da9a8b5c6246"
|
||||||
|
integrity sha512-SjbUZq5pgsBDuV3hu8GqgIpZR5eZvGLM+gPQTqjVVYSMUCfKW3EGXTEYaLHEl1bGduwqNC95O3bZflgtAb4L6w==
|
||||||
|
dependencies:
|
||||||
|
prosemirror-keymap "^1.0.0"
|
||||||
|
prosemirror-model "^1.0.0"
|
||||||
|
prosemirror-state "^1.0.0"
|
||||||
|
prosemirror-view "^1.0.0"
|
||||||
|
|
||||||
|
prosemirror-history@^1.1.3:
|
||||||
|
version "1.1.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/prosemirror-history/-/prosemirror-history-1.1.3.tgz#4f76a1e71db4ef7cdf0e13dec6d8da2aeaecd489"
|
||||||
|
integrity sha512-zGDotijea+vnfnyyUGyiy1wfOQhf0B/b6zYcCouBV8yo6JmrE9X23M5q7Nf/nATywEZbgRLG70R4DmfSTC+gfg==
|
||||||
|
dependencies:
|
||||||
|
prosemirror-state "^1.2.2"
|
||||||
|
prosemirror-transform "^1.0.0"
|
||||||
|
rope-sequence "^1.3.0"
|
||||||
|
|
||||||
|
prosemirror-inputrules@^1.1.2:
|
||||||
|
version "1.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/prosemirror-inputrules/-/prosemirror-inputrules-1.1.2.tgz#487e46c763e1212a4577397aba7706139084f012"
|
||||||
|
integrity sha512-Ja5Z3BWestlHYGvtSGqyvxMeB8QEuBjlHM8YnKtLGUXMDp965qdDV4goV8lJb17kIWHk7e7JNj6Catuoa3302g==
|
||||||
|
dependencies:
|
||||||
|
prosemirror-state "^1.0.0"
|
||||||
|
prosemirror-transform "^1.0.0"
|
||||||
|
|
||||||
|
prosemirror-keymap@^1.0.0, prosemirror-keymap@^1.1.2, prosemirror-keymap@^1.1.4:
|
||||||
|
version "1.1.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/prosemirror-keymap/-/prosemirror-keymap-1.1.4.tgz#8b481bf8389a5ac40d38dbd67ec3da2c7eac6a6d"
|
||||||
|
integrity sha512-Al8cVUOnDFL4gcI5IDlG6xbZ0aOD/i3B17VT+1JbHWDguCgt/lBHVTHUBcKvvbSg6+q/W4Nj1Fu6bwZSca3xjg==
|
||||||
|
dependencies:
|
||||||
|
prosemirror-state "^1.0.0"
|
||||||
|
w3c-keyname "^2.2.0"
|
||||||
|
|
||||||
|
prosemirror-markdown@^1.4.4:
|
||||||
|
version "1.5.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/prosemirror-markdown/-/prosemirror-markdown-1.5.0.tgz#1c0129640c33e23217fbf80ebb24486a40a759c1"
|
||||||
|
integrity sha512-ugTyZfTu1l2E3EI6+DwD917mz2Sk5E4R01Nh67yMffGg4S9ZetC81g1VIKGCaak4jnoP4BMUIOUJyXAS6xFLaA==
|
||||||
|
dependencies:
|
||||||
|
markdown-it "^10.0.0"
|
||||||
|
prosemirror-model "^1.0.0"
|
||||||
|
|
||||||
|
prosemirror-model@^1.0.0, prosemirror-model@^1.1.0, prosemirror-model@^1.10.0, prosemirror-model@^1.8.1:
|
||||||
|
version "1.11.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/prosemirror-model/-/prosemirror-model-1.11.0.tgz#dc36cdb3ad6442b9f6325c7d89170c624f9dc520"
|
||||||
|
integrity sha512-GqoAz/mIYjdv8gVYJ8mWFKpHoTxn/lXq4tXJ6bTVxs+rem2LzMYXrNVXfucGtfsgqsJlRIgng/ByG9j7Q8XDrg==
|
||||||
|
dependencies:
|
||||||
|
orderedmap "^1.1.0"
|
||||||
|
|
||||||
|
prosemirror-schema-list@^1.1.2:
|
||||||
|
version "1.1.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/prosemirror-schema-list/-/prosemirror-schema-list-1.1.4.tgz#471f9caf2d2bed93641d2e490434c0d2d4330df1"
|
||||||
|
integrity sha512-pNTuZflacFOBlxrTcWSdWhjoB8BaucwfJVp/gJNxztOwaN3wQiC65axclXyplf6TKgXD/EkWfS/QAov3/Znadw==
|
||||||
|
dependencies:
|
||||||
|
prosemirror-model "^1.0.0"
|
||||||
|
prosemirror-transform "^1.0.0"
|
||||||
|
|
||||||
|
prosemirror-state@^1.0.0, prosemirror-state@^1.2.2, prosemirror-state@^1.3.1, prosemirror-state@^1.3.3:
|
||||||
|
version "1.3.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/prosemirror-state/-/prosemirror-state-1.3.3.tgz#b2862866b14dec2b3ae1ab18229f2bd337651a2c"
|
||||||
|
integrity sha512-PLXh2VJsIgvlgSTH6I2Yg6vk1CzPDp21DFreVpQtDMY2S6WaMmrQgDTLRcsrD8X38v8Yc873H7+ogdGzyIPn+w==
|
||||||
|
dependencies:
|
||||||
|
prosemirror-model "^1.0.0"
|
||||||
|
prosemirror-transform "^1.0.0"
|
||||||
|
|
||||||
|
prosemirror-tables@^1.0.0:
|
||||||
|
version "1.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/prosemirror-tables/-/prosemirror-tables-1.1.1.tgz#ad66300cc49500455cf1243bb129c9e7d883321e"
|
||||||
|
integrity sha512-LmCz4jrlqQZRsYRDzCRYf/pQ5CUcSOyqZlAj5kv67ZWBH1SVLP2U9WJEvQfimWgeRlIz0y0PQVqO1arRm1+woA==
|
||||||
|
dependencies:
|
||||||
|
prosemirror-keymap "^1.1.2"
|
||||||
|
prosemirror-model "^1.8.1"
|
||||||
|
prosemirror-state "^1.3.1"
|
||||||
|
prosemirror-transform "^1.2.1"
|
||||||
|
prosemirror-view "^1.13.3"
|
||||||
|
|
||||||
|
prosemirror-transform@1.2.5:
|
||||||
|
version "1.2.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/prosemirror-transform/-/prosemirror-transform-1.2.5.tgz#7a3e2c61fcdbaf1d0844a2a3bc34fc3524e9809c"
|
||||||
|
integrity sha512-eqeIaxWtUfOnpA1ERrXCuSIMzqIJtL9Qrs5uJMCjY5RMSaH5o4pc390SAjn/IDPeIlw6auh0hCCXs3wRvGnQug==
|
||||||
|
dependencies:
|
||||||
|
prosemirror-model "^1.0.0"
|
||||||
|
|
||||||
|
prosemirror-transform@^1.0.0, prosemirror-transform@^1.1.0, prosemirror-transform@^1.2.1:
|
||||||
|
version "1.2.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/prosemirror-transform/-/prosemirror-transform-1.2.8.tgz#4b86544fa43637fe381549fb7b019f4fb71fe65c"
|
||||||
|
integrity sha512-hKqceqv9ZmMQXNQkhFjr0KFGPvkhygaWND+uIM0GxRpALrKfxP97SsgHTBs3OpJhDmh5N+mB4D/CksB291Eavg==
|
||||||
|
dependencies:
|
||||||
|
prosemirror-model "^1.0.0"
|
||||||
|
|
||||||
|
prosemirror-utils@^0.9.6:
|
||||||
|
version "0.9.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/prosemirror-utils/-/prosemirror-utils-0.9.6.tgz#3d97bd85897e3b535555867dc95a51399116a973"
|
||||||
|
integrity sha512-UC+j9hQQ1POYfMc5p7UFxBTptRiGPR7Kkmbl3jVvU8VgQbkI89tR/GK+3QYC8n+VvBZrtAoCrJItNhWSxX3slA==
|
||||||
|
|
||||||
|
prosemirror-view@^1.0.0, prosemirror-view@^1.1.0, prosemirror-view@^1.13.3, prosemirror-view@^1.14.11:
|
||||||
|
version "1.15.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/prosemirror-view/-/prosemirror-view-1.15.5.tgz#02f447bfb938995b6e26c9376c36d03e8714fcb4"
|
||||||
|
integrity sha512-VpAP/Rh7a4l1udpR3lEym2FlTD93JZjWChHYgzLgiBI6alOapG4GEsyAEq0l8eUJd9Ujf55+5dlEuItxI3a9Mw==
|
||||||
|
dependencies:
|
||||||
|
prosemirror-model "^1.1.0"
|
||||||
|
prosemirror-state "^1.0.0"
|
||||||
|
prosemirror-transform "^1.1.0"
|
||||||
|
|
||||||
proxy-addr@~2.0.5:
|
proxy-addr@~2.0.5:
|
||||||
version "2.0.5"
|
version "2.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.5.tgz#34cbd64a2d81f4b1fd21e76f9f06c8a45299ee34"
|
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.5.tgz#34cbd64a2d81f4b1fd21e76f9f06c8a45299ee34"
|
||||||
@ -13639,6 +13805,11 @@ react-markdown@^4.3.1:
|
|||||||
unist-util-visit "^1.3.0"
|
unist-util-visit "^1.3.0"
|
||||||
xtend "^4.0.1"
|
xtend "^4.0.1"
|
||||||
|
|
||||||
|
react-medium-image-zoom@^3.0.16:
|
||||||
|
version "3.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-medium-image-zoom/-/react-medium-image-zoom-3.1.2.tgz#5ac4441f1d424bd9680a25bfc2591be3d7704a42"
|
||||||
|
integrity sha512-werjufn5o4ytdyvJNzfqXCilovDhMyREH0qeJhCjV5brNAyfV7anZmvpFc3FApbuVXwBkzHMuQkV2z/GyEQatg==
|
||||||
|
|
||||||
react-onclickoutside@^6.9.0:
|
react-onclickoutside@^6.9.0:
|
||||||
version "6.9.0"
|
version "6.9.0"
|
||||||
resolved "https://registry.yarnpkg.com/react-onclickoutside/-/react-onclickoutside-6.9.0.tgz#a54bc317ae8cf6131a5d78acea55a11067f37a1f"
|
resolved "https://registry.yarnpkg.com/react-onclickoutside/-/react-onclickoutside-6.9.0.tgz#a54bc317ae8cf6131a5d78acea55a11067f37a1f"
|
||||||
@ -13665,6 +13836,13 @@ react-popper@^1.3.4, react-popper@^1.3.6:
|
|||||||
typed-styles "^0.0.7"
|
typed-styles "^0.0.7"
|
||||||
warning "^4.0.2"
|
warning "^4.0.2"
|
||||||
|
|
||||||
|
react-portal@^4.2.1:
|
||||||
|
version "4.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-portal/-/react-portal-4.2.1.tgz#12c1599238c06fb08a9800f3070bea2a3f78b1a6"
|
||||||
|
integrity sha512-fE9kOBagwmTXZ3YGRYb4gcMy+kSA+yLO0xnPankjRlfBv4uCpFXqKPfkpsGQQR15wkZ9EssnvTOl1yMzbkxhPQ==
|
||||||
|
dependencies:
|
||||||
|
prop-types "^15.5.8"
|
||||||
|
|
||||||
react-redux@^7.1.1:
|
react-redux@^7.1.1:
|
||||||
version "7.2.0"
|
version "7.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.0.tgz#f970f62192b3981642fec46fd0db18a074fe879d"
|
resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.0.tgz#f970f62192b3981642fec46fd0db18a074fe879d"
|
||||||
@ -13990,7 +14168,7 @@ redux@^4.0.4:
|
|||||||
loose-envify "^1.4.0"
|
loose-envify "^1.4.0"
|
||||||
symbol-observable "^1.2.0"
|
symbol-observable "^1.2.0"
|
||||||
|
|
||||||
refractor@^2.4.1:
|
refractor@^2.10.1, refractor@^2.4.1:
|
||||||
version "2.10.1"
|
version "2.10.1"
|
||||||
resolved "https://registry.yarnpkg.com/refractor/-/refractor-2.10.1.tgz#166c32f114ed16fd96190ad21d5193d3afc7d34e"
|
resolved "https://registry.yarnpkg.com/refractor/-/refractor-2.10.1.tgz#166c32f114ed16fd96190ad21d5193d3afc7d34e"
|
||||||
integrity sha512-Xh9o7hQiQlDbxo5/XkOX6H+x/q8rmlmZKr97Ie1Q8ZM32IRRd3B/UxuA/yXDW79DBSXGWxm2yRTbcTVmAciJRw==
|
integrity sha512-Xh9o7hQiQlDbxo5/XkOX6H+x/q8rmlmZKr97Ie1Q8ZM32IRRd3B/UxuA/yXDW79DBSXGWxm2yRTbcTVmAciJRw==
|
||||||
@ -14474,6 +14652,39 @@ rgba-regex@^1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3"
|
resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3"
|
||||||
integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=
|
integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=
|
||||||
|
|
||||||
|
rich-markdown-editor@^10.6.5:
|
||||||
|
version "10.6.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/rich-markdown-editor/-/rich-markdown-editor-10.6.5.tgz#b74ae2e7d05eaa3c8ef34744e5cb0ed2dbdb0958"
|
||||||
|
integrity sha512-C/C+6L7BTXC4zSHgOYMljOQ3CvFt8zNCT829woKBHcDWSnXiUzpjgZZ4qEeNRlh/XJmqeFZYfqY+OzIMsVP2+Q==
|
||||||
|
dependencies:
|
||||||
|
copy-to-clipboard "^3.0.8"
|
||||||
|
lodash "^4.17.11"
|
||||||
|
markdown-it-container "^3.0.0"
|
||||||
|
markdown-it-mark "^3.0.0"
|
||||||
|
outline-icons "^1.21.0-3"
|
||||||
|
prismjs "^1.19.0"
|
||||||
|
prosemirror-commands "^1.1.4"
|
||||||
|
prosemirror-dropcursor "^1.3.2"
|
||||||
|
prosemirror-gapcursor "^1.1.5"
|
||||||
|
prosemirror-history "^1.1.3"
|
||||||
|
prosemirror-inputrules "^1.1.2"
|
||||||
|
prosemirror-keymap "^1.1.4"
|
||||||
|
prosemirror-markdown "^1.4.4"
|
||||||
|
prosemirror-model "^1.10.0"
|
||||||
|
prosemirror-schema-list "^1.1.2"
|
||||||
|
prosemirror-state "^1.3.3"
|
||||||
|
prosemirror-tables "^1.0.0"
|
||||||
|
prosemirror-transform "1.2.5"
|
||||||
|
prosemirror-utils "^0.9.6"
|
||||||
|
prosemirror-view "^1.14.11"
|
||||||
|
react-medium-image-zoom "^3.0.16"
|
||||||
|
react-portal "^4.2.1"
|
||||||
|
refractor "^2.10.1"
|
||||||
|
slugify "^1.4.0"
|
||||||
|
smooth-scroll-into-view-if-needed "^1.1.27"
|
||||||
|
styled-components "^5.1.0"
|
||||||
|
typescript "3.7.5"
|
||||||
|
|
||||||
right-align@^0.1.1:
|
right-align@^0.1.1:
|
||||||
version "0.1.3"
|
version "0.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef"
|
resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef"
|
||||||
@ -14503,6 +14714,11 @@ ripemd160@^2.0.0, ripemd160@^2.0.1:
|
|||||||
hash-base "^3.0.0"
|
hash-base "^3.0.0"
|
||||||
inherits "^2.0.1"
|
inherits "^2.0.1"
|
||||||
|
|
||||||
|
rope-sequence@^1.3.0:
|
||||||
|
version "1.3.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/rope-sequence/-/rope-sequence-1.3.2.tgz#a19e02d72991ca71feb6b5f8a91154e48e3c098b"
|
||||||
|
integrity sha512-ku6MFrwEVSVmXLvy3dYph3LAMNS0890K7fabn+0YIRQ2T96T9F4gkFf0vf0WW0JUraNWwGRtInEpH7yO4tbQZg==
|
||||||
|
|
||||||
rsvp@^4.8.4:
|
rsvp@^4.8.4:
|
||||||
version "4.8.5"
|
version "4.8.5"
|
||||||
resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734"
|
resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734"
|
||||||
@ -14643,6 +14859,13 @@ schema-utils@^2.0.1, schema-utils@^2.5.0, schema-utils@^2.6.0, schema-utils@^2.6
|
|||||||
ajv "^6.10.2"
|
ajv "^6.10.2"
|
||||||
ajv-keywords "^3.4.1"
|
ajv-keywords "^3.4.1"
|
||||||
|
|
||||||
|
scroll-into-view-if-needed@^2.2.25:
|
||||||
|
version "2.2.25"
|
||||||
|
resolved "https://registry.yarnpkg.com/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.25.tgz#117b7bc7c61bc7a2b7872a0984bc73a19bc6e961"
|
||||||
|
integrity sha512-C8RKJPq9lK7eubwGpLbUkw3lklcG3Ndjmea2PyauzrA0i4DPlzAmVMGxaZrBFqCrVLfvJmP80IyHnv4jxvg1OQ==
|
||||||
|
dependencies:
|
||||||
|
compute-scroll-into-view "^1.0.14"
|
||||||
|
|
||||||
scuid@^1.0.2:
|
scuid@^1.0.2:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/scuid/-/scuid-1.1.0.tgz#d3f9f920956e737a60f72d0e4ad280bf324d5dab"
|
resolved "https://registry.yarnpkg.com/scuid/-/scuid-1.1.0.tgz#d3f9f920956e737a60f72d0e4ad280bf324d5dab"
|
||||||
@ -14937,6 +15160,18 @@ slice-ansi@^2.1.0:
|
|||||||
astral-regex "^1.0.0"
|
astral-regex "^1.0.0"
|
||||||
is-fullwidth-code-point "^2.0.0"
|
is-fullwidth-code-point "^2.0.0"
|
||||||
|
|
||||||
|
slugify@^1.4.0:
|
||||||
|
version "1.4.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/slugify/-/slugify-1.4.5.tgz#a7517acf5f4c02a4df41e735354b660a4ed1efcf"
|
||||||
|
integrity sha512-WpECLAgYaxHoEAJ8Q1Lo8HOs1ngn7LN7QjXgOLbmmfkcWvosyk4ZTXkTzKyhngK640USTZUlgoQJfED1kz5fnQ==
|
||||||
|
|
||||||
|
smooth-scroll-into-view-if-needed@^1.1.27:
|
||||||
|
version "1.1.28"
|
||||||
|
resolved "https://registry.yarnpkg.com/smooth-scroll-into-view-if-needed/-/smooth-scroll-into-view-if-needed-1.1.28.tgz#70591d6723aa747114e0c0348379f8739701e4ba"
|
||||||
|
integrity sha512-VBxjAYySCfPix8JaiYKB+Rr4+1tFJ+aJ80caiVmsEA1cgQ3G/aFEfIRSpabJfX5o3FGm3IEttBLebe0uNtgURw==
|
||||||
|
dependencies:
|
||||||
|
scroll-into-view-if-needed "^2.2.25"
|
||||||
|
|
||||||
snapdragon-node@^2.0.1:
|
snapdragon-node@^2.0.1:
|
||||||
version "2.1.1"
|
version "2.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b"
|
resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b"
|
||||||
@ -15479,6 +15714,22 @@ styled-components@^5.0.1:
|
|||||||
shallowequal "^1.1.0"
|
shallowequal "^1.1.0"
|
||||||
supports-color "^5.5.0"
|
supports-color "^5.5.0"
|
||||||
|
|
||||||
|
styled-components@^5.1.0:
|
||||||
|
version "5.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-5.1.1.tgz#96dfb02a8025794960863b9e8e365e3b6be5518d"
|
||||||
|
integrity sha512-1ps8ZAYu2Husx+Vz8D+MvXwEwvMwFv+hqqUwhNlDN5ybg6A+3xyW1ECrAgywhvXapNfXiz79jJyU0x22z0FFTg==
|
||||||
|
dependencies:
|
||||||
|
"@babel/helper-module-imports" "^7.0.0"
|
||||||
|
"@babel/traverse" "^7.4.5"
|
||||||
|
"@emotion/is-prop-valid" "^0.8.8"
|
||||||
|
"@emotion/stylis" "^0.8.4"
|
||||||
|
"@emotion/unitless" "^0.7.4"
|
||||||
|
babel-plugin-styled-components ">= 1"
|
||||||
|
css-to-react-native "^3.0.0"
|
||||||
|
hoist-non-react-statics "^3.0.0"
|
||||||
|
shallowequal "^1.1.0"
|
||||||
|
supports-color "^5.5.0"
|
||||||
|
|
||||||
stylehacks@^4.0.0:
|
stylehacks@^4.0.0:
|
||||||
version "4.0.3"
|
version "4.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-4.0.3.tgz#6718fcaf4d1e07d8a1318690881e8d96726a71d5"
|
resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-4.0.3.tgz#6718fcaf4d1e07d8a1318690881e8d96726a71d5"
|
||||||
@ -15976,7 +16227,7 @@ typedarray@^0.0.6:
|
|||||||
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
|
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
|
||||||
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
|
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
|
||||||
|
|
||||||
typescript@~3.7.2:
|
typescript@3.7.5, typescript@~3.7.2:
|
||||||
version "3.7.5"
|
version "3.7.5"
|
||||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.5.tgz#0692e21f65fd4108b9330238aac11dd2e177a1ae"
|
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.5.tgz#0692e21f65fd4108b9330238aac11dd2e177a1ae"
|
||||||
integrity sha512-/P5lkRXkWHNAbcJIiHPfRoKqyd7bsyCma1hZNUGfn20qm64T6ZBlrzprymeu918H+mB/0rIg2gGK/BXkhhYgBw==
|
integrity sha512-/P5lkRXkWHNAbcJIiHPfRoKqyd7bsyCma1hZNUGfn20qm64T6ZBlrzprymeu918H+mB/0rIg2gGK/BXkhhYgBw==
|
||||||
@ -15986,6 +16237,11 @@ ua-parser-js@^0.7.18:
|
|||||||
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.21.tgz#853cf9ce93f642f67174273cc34565ae6f308777"
|
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.21.tgz#853cf9ce93f642f67174273cc34565ae6f308777"
|
||||||
integrity sha512-+O8/qh/Qj8CgC6eYBVBykMrNtp5Gebn4dlGD/kKXVkJNDwyrAwSIqwz8CDf+tsAIWVycKcku6gIXJ0qwx/ZXaQ==
|
integrity sha512-+O8/qh/Qj8CgC6eYBVBykMrNtp5Gebn4dlGD/kKXVkJNDwyrAwSIqwz8CDf+tsAIWVycKcku6gIXJ0qwx/ZXaQ==
|
||||||
|
|
||||||
|
uc.micro@^1.0.1, uc.micro@^1.0.5:
|
||||||
|
version "1.0.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac"
|
||||||
|
integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==
|
||||||
|
|
||||||
uglify-js@^2.6.1:
|
uglify-js@^2.6.1:
|
||||||
version "2.8.29"
|
version "2.8.29"
|
||||||
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd"
|
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd"
|
||||||
@ -16519,6 +16775,11 @@ w3c-hr-time@^1.0.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
browser-process-hrtime "^0.1.2"
|
browser-process-hrtime "^0.1.2"
|
||||||
|
|
||||||
|
w3c-keyname@^2.2.0:
|
||||||
|
version "2.2.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/w3c-keyname/-/w3c-keyname-2.2.4.tgz#4ade6916f6290224cdbd1db8ac49eab03d0eef6b"
|
||||||
|
integrity sha512-tOhfEwEzFLJzf6d1ZPkYfGj+FWhIpBux9ppoP3rlclw3Z0BZv3N7b7030Z1kYth+6rDuAsXUFr+d0VE6Ed1ikw==
|
||||||
|
|
||||||
w3c-xmlserializer@^1.1.2:
|
w3c-xmlserializer@^1.1.2:
|
||||||
version "1.1.2"
|
version "1.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-1.1.2.tgz#30485ca7d70a6fd052420a3d12fd90e6339ce794"
|
resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-1.1.2.tgz#30485ca7d70a6fd052420a3d12fd90e6339ce794"
|
||||||
|
Loading…
Reference in New Issue
Block a user