feature: add ability to delete & update project labels
This commit is contained in:
@ -168,7 +168,9 @@ const Card = React.forwardRef(
|
||||
</ListCardBadges>
|
||||
<CardMembers>
|
||||
{members &&
|
||||
members.map(member => <Member taskID={taskID} member={member} onCardMemberClick={onCardMemberClick} />)}
|
||||
members.map(member => (
|
||||
<Member key={member.userID} taskID={taskID} member={member} onCardMemberClick={onCardMemberClick} />
|
||||
))}
|
||||
</CardMembers>
|
||||
</ListCardDetails>
|
||||
</ListCardInnerContainer>
|
||||
|
@ -74,8 +74,6 @@ const Lists: React.FC<Props> = ({
|
||||
}),
|
||||
);
|
||||
|
||||
console.log(beforeDropDraggables);
|
||||
console.log(destination);
|
||||
const afterDropDraggables = getAfterDropDraggableList(
|
||||
beforeDropDraggables,
|
||||
droppedDraggable,
|
||||
@ -83,19 +81,16 @@ const Lists: React.FC<Props> = ({
|
||||
isSameList,
|
||||
destination,
|
||||
);
|
||||
console.log(afterDropDraggables);
|
||||
const newPosition = getNewDraggablePosition(afterDropDraggables, destination.index);
|
||||
|
||||
if (isList) {
|
||||
const droppedList = columns[droppedDraggable.id];
|
||||
console.log(`is list ${droppedList}`);
|
||||
onListDrop({
|
||||
...droppedList,
|
||||
position: newPosition,
|
||||
});
|
||||
} else {
|
||||
const droppedCard = tasks[droppedDraggable.id];
|
||||
console.log(`is card ${droppedCard}`);
|
||||
const newCard = {
|
||||
...droppedCard,
|
||||
position: newPosition,
|
||||
@ -112,6 +107,7 @@ const Lists: React.FC<Props> = ({
|
||||
return { id: column.taskGroupID, position: column.position };
|
||||
}),
|
||||
);
|
||||
console.log(orderedColumns);
|
||||
|
||||
const [currentComposer, setCurrentComposer] = useState('');
|
||||
return (
|
||||
@ -134,7 +130,7 @@ const Lists: React.FC<Props> = ({
|
||||
name={column.name}
|
||||
onOpenComposer={id => setCurrentComposer(id)}
|
||||
isComposerOpen={currentComposer === column.taskGroupID}
|
||||
onSaveName={name => console.log(name)}
|
||||
onSaveName={name => {}}
|
||||
tasks={columnCards}
|
||||
ref={columnDragProvided.innerRef}
|
||||
wrapperProps={columnDragProvided.draggableProps}
|
||||
|
@ -23,7 +23,6 @@ import {
|
||||
const Login = ({ onSubmit }: LoginProps) => {
|
||||
const [isComplete, setComplete] = useState(true);
|
||||
const { register, handleSubmit, errors, setError, formState } = useForm<LoginFormData>();
|
||||
console.log(formState);
|
||||
const loginSubmit = (data: LoginFormData) => {
|
||||
setComplete(false);
|
||||
onSubmit(data, setComplete, setError);
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { useState } from 'react';
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import LabelColors from 'shared/constants/labelColors';
|
||||
import { Checkmark } from 'shared/icons';
|
||||
import { SaveButton, DeleteButton, LabelBox, EditLabelForm, FieldLabel, FieldName } from './Styles';
|
||||
@ -7,16 +7,25 @@ type Props = {
|
||||
labelColors: Array<LabelColor>;
|
||||
label: Label | null;
|
||||
onLabelEdit: (labelId: string | null, labelName: string, labelColor: LabelColor) => void;
|
||||
onLabelDelete?: (labelId: string) => void;
|
||||
};
|
||||
|
||||
const LabelManager = ({ labelColors, label, onLabelEdit }: Props) => {
|
||||
console.log(label);
|
||||
const LabelManager = ({ labelColors, label, onLabelEdit, onLabelDelete }: Props) => {
|
||||
const $fieldName = useRef<HTMLInputElement>(null);
|
||||
const [currentLabel, setCurrentLabel] = useState(label ? label.name : '');
|
||||
const [currentColor, setCurrentColor] = useState<LabelColor | null>(label ? label.labelColor : null);
|
||||
|
||||
useEffect(() => {
|
||||
if ($fieldName.current) {
|
||||
$fieldName.current.focus();
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<EditLabelForm>
|
||||
<FieldLabel>Name</FieldLabel>
|
||||
<FieldName
|
||||
ref={$fieldName}
|
||||
id="labelName"
|
||||
type="text"
|
||||
name="name"
|
||||
@ -29,6 +38,7 @@ const LabelManager = ({ labelColors, label, onLabelEdit }: Props) => {
|
||||
<div>
|
||||
{labelColors.map((labelColor: LabelColor) => (
|
||||
<LabelBox
|
||||
key={labelColor.id}
|
||||
color={labelColor.colorHex}
|
||||
onClick={() => {
|
||||
setCurrentColor(labelColor);
|
||||
@ -40,6 +50,8 @@ const LabelManager = ({ labelColors, label, onLabelEdit }: Props) => {
|
||||
</div>
|
||||
<div>
|
||||
<SaveButton
|
||||
value="Save"
|
||||
type="submit"
|
||||
onClick={e => {
|
||||
e.preventDefault();
|
||||
console.log(currentColor);
|
||||
@ -47,10 +59,17 @@ const LabelManager = ({ labelColors, label, onLabelEdit }: Props) => {
|
||||
onLabelEdit(label ? label.labelId : null, currentLabel, currentColor);
|
||||
}
|
||||
}}
|
||||
type="submit"
|
||||
value="Save"
|
||||
/>
|
||||
<DeleteButton type="submit" value="Delete" />
|
||||
{label && onLabelDelete && (
|
||||
<DeleteButton
|
||||
value="Delete"
|
||||
type="submit"
|
||||
onClick={e => {
|
||||
e.preventDefault();
|
||||
onLabelDelete(label.labelId);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</EditLabelForm>
|
||||
);
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { useState } from 'react';
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import { Pencil, Checkmark } from 'shared/icons';
|
||||
|
||||
import {
|
||||
@ -20,12 +20,19 @@ type Props = {
|
||||
onLabelCreate: () => void;
|
||||
};
|
||||
const LabelManager: React.FC<Props> = ({ labels, onLabelToggle, onLabelEdit, onLabelCreate }) => {
|
||||
const $fieldName = useRef<HTMLInputElement>(null);
|
||||
const [currentLabel, setCurrentLabel] = useState('');
|
||||
const [currentSearch, setCurrentSearch] = useState('');
|
||||
useEffect(() => {
|
||||
if ($fieldName.current) {
|
||||
$fieldName.current.focus();
|
||||
}
|
||||
}, []);
|
||||
return (
|
||||
<>
|
||||
<LabelSearch
|
||||
type="text"
|
||||
ref={$fieldName}
|
||||
placeholder="search labels..."
|
||||
onChange={e => {
|
||||
setCurrentSearch(e.currentTarget.value);
|
||||
|
@ -248,36 +248,47 @@ export const LabelBox = styled.span<{ color: string }>`
|
||||
`;
|
||||
|
||||
export const SaveButton = styled.input`
|
||||
cursor: pointer;
|
||||
background-color: #5aac44;
|
||||
background: rgb(115, 103, 240);
|
||||
box-shadow: none;
|
||||
border: none;
|
||||
color: #fff;
|
||||
padding-left: 24px;
|
||||
padding-right: 24px;
|
||||
ursor: pointer;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
font-weight: 400;
|
||||
line-height: 20px;
|
||||
margin: 8px 4px 0 0;
|
||||
margin-right: 4px;
|
||||
padding: 6px 12px;
|
||||
text-align: center;
|
||||
border-radius: 3px;
|
||||
`;
|
||||
|
||||
export const DeleteButton = styled.input`
|
||||
background-color: #cf513d;
|
||||
box-shadow: none;
|
||||
border: none;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
type="submit"font-weight: 400;
|
||||
line-height: 20px;
|
||||
margin: 8px 4px 0 0;
|
||||
padding: 6px 12px;
|
||||
text-align: center;
|
||||
border-radius: 3px;
|
||||
float: right;
|
||||
outline: none;
|
||||
border: none;
|
||||
line-height: 20px;
|
||||
padding: 6px 12px;
|
||||
background-color: transparent;
|
||||
text-align: center;
|
||||
color: #c2c6dc;
|
||||
font-weight: 400;
|
||||
line-height: 20px;
|
||||
cursor: pointer;
|
||||
|
||||
margin: 0 0 0 8px;
|
||||
|
||||
border-radius: 3px;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: transparent;
|
||||
border-image: initial;
|
||||
border-color: #414561;
|
||||
|
||||
&:hover {
|
||||
color: #fff;
|
||||
background: rgb(115, 103, 240);
|
||||
border-color: transparent;
|
||||
}
|
||||
`;
|
||||
|
||||
export const CreateLabelButton = styled.button`
|
||||
|
@ -18,6 +18,7 @@ type PopupContextState = {
|
||||
show: (target: RefObject<HTMLElement>, content: JSX.Element) => void;
|
||||
setTab: (newTab: number) => void;
|
||||
getCurrentTab: () => number;
|
||||
hide: () => void;
|
||||
};
|
||||
|
||||
type PopupProps = {
|
||||
@ -46,11 +47,12 @@ const PopupContext = createContext<PopupContextState>({
|
||||
show: () => {},
|
||||
setTab: () => {},
|
||||
getCurrentTab: () => 0,
|
||||
hide: () => {},
|
||||
});
|
||||
|
||||
export const usePopup = () => {
|
||||
const ctx = useContext<PopupContextState>(PopupContext);
|
||||
return { showPopup: ctx.show, setTab: ctx.setTab, getCurrentTab: ctx.getCurrentTab };
|
||||
return { showPopup: ctx.show, setTab: ctx.setTab, getCurrentTab: ctx.getCurrentTab, hidePopup: ctx.hide };
|
||||
};
|
||||
|
||||
type PopupState = {
|
||||
@ -80,11 +82,9 @@ const defaultState = {
|
||||
export const PopupProvider: React.FC = ({ children }) => {
|
||||
const [currentState, setState] = useState<PopupState>(defaultState);
|
||||
const show = (target: RefObject<HTMLElement>, content: JSX.Element) => {
|
||||
console.log(target);
|
||||
if (target && target.current) {
|
||||
const bounds = target.current.getBoundingClientRect();
|
||||
if (bounds.left + 304 + 30 > window.innerWidth) {
|
||||
console.log('open!');
|
||||
setState({
|
||||
isOpen: true,
|
||||
left: bounds.left + bounds.width,
|
||||
@ -95,7 +95,6 @@ export const PopupProvider: React.FC = ({ children }) => {
|
||||
content,
|
||||
});
|
||||
} else {
|
||||
console.log('open NOT INVERT!');
|
||||
setState({
|
||||
isOpen: true,
|
||||
left: bounds.left,
|
||||
@ -108,6 +107,17 @@ export const PopupProvider: React.FC = ({ children }) => {
|
||||
}
|
||||
}
|
||||
};
|
||||
const hide = () => {
|
||||
setState({
|
||||
isOpen: false,
|
||||
left: 0,
|
||||
top: 0,
|
||||
invert: true,
|
||||
currentTab: 0,
|
||||
previousTab: 0,
|
||||
content: null,
|
||||
});
|
||||
};
|
||||
const portalTarget = canUseDOM ? document.body : null; // appease flow
|
||||
|
||||
const setTab = (newTab: number) => {
|
||||
@ -125,7 +135,7 @@ export const PopupProvider: React.FC = ({ children }) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<Provider value={{ show, setTab, getCurrentTab }}>
|
||||
<Provider value={{ hide, show, setTab, getCurrentTab }}>
|
||||
{portalTarget &&
|
||||
currentState.isOpen &&
|
||||
createPortal(
|
||||
|
@ -146,6 +146,14 @@ export const TaskDetailsMarkdown = styled.div`
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
color: #c2c6dc;
|
||||
|
||||
p {
|
||||
margin: 0 0 8px;
|
||||
}
|
||||
|
||||
strong {
|
||||
font-weight: 700;
|
||||
}
|
||||
`;
|
||||
|
||||
export const TaskDetailsControls = styled.div`
|
||||
|
@ -1,6 +1,7 @@
|
||||
import React, { useState, useRef, useEffect } from 'react';
|
||||
import { Bin, Cross, Plus } from 'shared/icons';
|
||||
import useOnOutsideClick from 'shared/hooks/onOutsideClick';
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
import TaskAssignee from 'shared/components/TaskAssignee';
|
||||
|
||||
import {
|
||||
@ -48,7 +49,9 @@ const TaskContent: React.FC<TaskContentProps> = ({ description, onEditContent })
|
||||
return description === '' ? (
|
||||
<TaskDetailsAddDetailsButton onClick={onEditContent}>Add a more detailed description</TaskDetailsAddDetailsButton>
|
||||
) : (
|
||||
<TaskDetailsMarkdown onClick={onEditContent}>{description}</TaskDetailsMarkdown>
|
||||
<TaskDetailsMarkdown onClick={onEditContent}>
|
||||
<ReactMarkdown source={description} />
|
||||
</TaskDetailsMarkdown>
|
||||
);
|
||||
};
|
||||
|
||||
@ -142,7 +145,6 @@ const TaskDetails: React.FC<TaskDetailsProps> = ({
|
||||
const onAddLabel = () => {
|
||||
onOpenAddLabelPopup(task, $addLabelRef);
|
||||
};
|
||||
console.log(task);
|
||||
return (
|
||||
<>
|
||||
<TaskActions>
|
||||
|
@ -50,7 +50,6 @@ const NavBar: React.FC<NavBarProps> = ({
|
||||
}) => {
|
||||
const $profileRef: any = useRef(null);
|
||||
const handleProfileClick = () => {
|
||||
console.log('click');
|
||||
const boundingRect = $profileRef.current.getBoundingClientRect();
|
||||
onProfileClick(boundingRect.bottom, boundingRect.right);
|
||||
};
|
||||
@ -95,7 +94,7 @@ const NavBar: React.FC<NavBarProps> = ({
|
||||
{projectMembers && (
|
||||
<ProjectMembers>
|
||||
{projectMembers.map(member => (
|
||||
<TaskAssignee size={28} member={member} onMemberProfile={onMemberProfile} />
|
||||
<TaskAssignee key={member.userID} size={28} member={member} onMemberProfile={onMemberProfile} />
|
||||
))}
|
||||
<InviteButton>Invite</InviteButton>
|
||||
</ProjectMembers>
|
||||
|
Reference in New Issue
Block a user