bugfix: fix user checklist item toggle completion

This commit is contained in:
Jordan Knott 2020-07-13 16:21:37 -05:00
parent d8daa60729
commit 1e9813601e
4 changed files with 551 additions and 525 deletions

View File

@ -1,9 +1,9 @@
import React, {useState, useContext, useEffect} from 'react'; import React, { useState, useContext, useEffect } from 'react';
import Modal from 'shared/components/Modal'; import Modal from 'shared/components/Modal';
import TaskDetails from 'shared/components/TaskDetails'; import TaskDetails from 'shared/components/TaskDetails';
import PopupMenu, {Popup, usePopup} from 'shared/components/PopupMenu'; import PopupMenu, { Popup, usePopup } from 'shared/components/PopupMenu';
import MemberManager from 'shared/components/MemberManager'; import MemberManager from 'shared/components/MemberManager';
import {useRouteMatch, useHistory} from 'react-router'; import { useRouteMatch, useHistory } from 'react-router';
import { import {
useDeleteTaskChecklistMutation, useDeleteTaskChecklistMutation,
useUpdateTaskChecklistNameMutation, useUpdateTaskChecklistNameMutation,
@ -29,7 +29,7 @@ import produce from 'immer';
import styled from 'styled-components'; import styled from 'styled-components';
import Button from 'shared/components/Button'; import Button from 'shared/components/Button';
import Input from 'shared/components/Input'; import Input from 'shared/components/Input';
import {useForm} from 'react-hook-form'; import { useForm } from 'react-hook-form';
import updateApolloCache from 'shared/utils/cache'; import updateApolloCache from 'shared/utils/cache';
const calculateChecklistBadge = (checklists: Array<TaskChecklist>) => { const calculateChecklistBadge = (checklists: Array<TaskChecklist>) => {
@ -49,7 +49,7 @@ const calculateChecklistBadge = (checklists: Array<TaskChecklist>) => {
}, 0), }, 0),
0, 0,
); );
return {total, complete}; return { total, complete };
}; };
const DeleteChecklistButton = styled(Button)` const DeleteChecklistButton = styled(Button)`
@ -82,8 +82,8 @@ const InputError = styled.span`
type CreateChecklistPopupProps = { type CreateChecklistPopupProps = {
onCreateChecklist: (data: CreateChecklistData) => void; onCreateChecklist: (data: CreateChecklistData) => void;
}; };
const CreateChecklistPopup: React.FC<CreateChecklistPopupProps> = ({onCreateChecklist}) => { const CreateChecklistPopup: React.FC<CreateChecklistPopupProps> = ({ onCreateChecklist }) => {
const {register, handleSubmit, errors} = useForm<CreateChecklistData>(); const { register, handleSubmit, errors } = useForm<CreateChecklistData>();
const createUser = (data: CreateChecklistData) => { const createUser = (data: CreateChecklistData) => {
onCreateChecklist(data); onCreateChecklist(data);
}; };
@ -98,7 +98,7 @@ const CreateChecklistPopup: React.FC<CreateChecklistPopupProps> = ({onCreateChec
id="name" id="name"
name="name" name="name"
variant="alternate" variant="alternate"
ref={register({required: 'Checklist name is required'})} ref={register({ required: 'Checklist name is required' })}
/> />
<CreateChecklistButton type="submit">Create</CreateChecklistButton> <CreateChecklistButton type="submit">Create</CreateChecklistButton>
</CreateChecklistForm> </CreateChecklistForm>
@ -116,7 +116,7 @@ type DetailsProps = {
refreshCache: () => void; refreshCache: () => void;
}; };
const initialMemberPopupState = {taskID: '', isOpen: false, top: 0, left: 0}; const initialMemberPopupState = { taskID: '', isOpen: false, top: 0, left: 0 };
const Details: React.FC<DetailsProps> = ({ const Details: React.FC<DetailsProps> = ({
projectURL, projectURL,
@ -128,8 +128,8 @@ const Details: React.FC<DetailsProps> = ({
availableMembers, availableMembers,
refreshCache, refreshCache,
}) => { }) => {
const {userID} = useContext(UserIDContext); const { userID } = useContext(UserIDContext);
const {showPopup, hidePopup} = usePopup(); const { showPopup, hidePopup } = usePopup();
const history = useHistory(); const history = useHistory();
const match = useRouteMatch(); const match = useRouteMatch();
const [currentMemberTask, setCurrentMemberTask] = useState(''); const [currentMemberTask, setCurrentMemberTask] = useState('');
@ -142,7 +142,7 @@ const Details: React.FC<DetailsProps> = ({
FindTaskDocument, FindTaskDocument,
cache => cache =>
produce(cache, draftCache => { produce(cache, draftCache => {
const {prevChecklistID, checklistID, checklistItem} = response.data.updateTaskChecklistItemLocation; const { prevChecklistID, checklistID, checklistItem } = response.data.updateTaskChecklistItemLocation;
console.log(`${checklistID} !== ${prevChecklistID}`); console.log(`${checklistID} !== ${prevChecklistID}`);
if (checklistID !== prevChecklistID) { if (checklistID !== prevChecklistID) {
const oldIdx = cache.findTask.checklists.findIndex(c => c.id === prevChecklistID); const oldIdx = cache.findTask.checklists.findIndex(c => c.id === prevChecklistID);
@ -164,7 +164,7 @@ const Details: React.FC<DetailsProps> = ({
} }
} }
}), }),
{taskID}, { taskID },
); );
}, },
}); });
@ -175,14 +175,14 @@ const Details: React.FC<DetailsProps> = ({
FindTaskDocument, FindTaskDocument,
cache => cache =>
produce(cache, draftCache => { produce(cache, draftCache => {
const {complete, total} = calculateChecklistBadge(draftCache.findTask.checklists); const { complete, total } = calculateChecklistBadge(draftCache.findTask.checklists);
draftCache.findTask.badges.checklist = { draftCache.findTask.badges.checklist = {
__typename: 'ChecklistBadge', __typename: 'ChecklistBadge',
complete, complete,
total, total,
}; };
}), }),
{taskID}, { taskID },
); );
}, },
}); });
@ -193,10 +193,10 @@ const Details: React.FC<DetailsProps> = ({
FindTaskDocument, FindTaskDocument,
cache => cache =>
produce(cache, draftCache => { produce(cache, draftCache => {
const {checklists} = cache.findTask; const { checklists } = cache.findTask;
console.log(deleteData) console.log(deleteData)
draftCache.findTask.checklists = checklists.filter(c => c.id !== deleteData.data.deleteTaskChecklist.taskChecklist.id); draftCache.findTask.checklists = checklists.filter(c => c.id !== deleteData.data.deleteTaskChecklist.taskChecklist.id);
const {complete, total} = calculateChecklistBadge(draftCache.findTask.checklists); const { complete, total } = calculateChecklistBadge(draftCache.findTask.checklists);
draftCache.findTask.badges.checklist = { draftCache.findTask.badges.checklist = {
__typename: 'ChecklistBadge', __typename: 'ChecklistBadge',
complete, complete,
@ -206,7 +206,7 @@ const Details: React.FC<DetailsProps> = ({
draftCache.findTask.badges.checklist = null; draftCache.findTask.badges.checklist = null;
} }
}), }),
{taskID}, { taskID },
); );
}, },
}); });
@ -219,9 +219,9 @@ const Details: React.FC<DetailsProps> = ({
cache => cache =>
produce(cache, draftCache => { produce(cache, draftCache => {
const item = createData.data.createTaskChecklist; const item = createData.data.createTaskChecklist;
draftCache.findTask.checklists.push({...item}); draftCache.findTask.checklists.push({ ...item });
}), }),
{taskID}, { taskID },
); );
}, },
}); });
@ -238,14 +238,14 @@ const Details: React.FC<DetailsProps> = ({
if (targetIdx > -1) { if (targetIdx > -1) {
draftCache.findTask.checklists[targetIdx].items = cache.findTask.checklists[targetIdx].items.filter(c => item.id !== c.id); draftCache.findTask.checklists[targetIdx].items = cache.findTask.checklists[targetIdx].items.filter(c => item.id !== c.id);
} }
const {complete, total} = calculateChecklistBadge(draftCache.findTask.checklists); const { complete, total } = calculateChecklistBadge(draftCache.findTask.checklists);
draftCache.findTask.badges.checklist = { draftCache.findTask.badges.checklist = {
__typename: 'ChecklistBadge', __typename: 'ChecklistBadge',
complete, complete,
total, total,
}; };
}), }),
{taskID}, { taskID },
); );
}, },
}); });
@ -257,11 +257,11 @@ const Details: React.FC<DetailsProps> = ({
cache => cache =>
produce(cache, draftCache => { produce(cache, draftCache => {
const item = newTaskItem.data.createTaskChecklistItem; const item = newTaskItem.data.createTaskChecklistItem;
const {checklists} = cache.findTask; const { checklists } = cache.findTask;
const idx = checklists.findIndex(c => c.id === item.taskChecklistID); const idx = checklists.findIndex(c => c.id === item.taskChecklistID);
if (idx !== -1) { if (idx !== -1) {
draftCache.findTask.checklists[idx].items.push({...item}); draftCache.findTask.checklists[idx].items.push({ ...item });
const {complete, total} = calculateChecklistBadge(draftCache.findTask.checklists); const { complete, total } = calculateChecklistBadge(draftCache.findTask.checklists);
draftCache.findTask.badges.checklist = { draftCache.findTask.badges.checklist = {
__typename: 'ChecklistBadge', __typename: 'ChecklistBadge',
complete, complete,
@ -269,11 +269,11 @@ const Details: React.FC<DetailsProps> = ({
}; };
} }
}), }),
{taskID}, { taskID },
); );
}, },
}); });
const {loading, data, refetch} = useFindTaskQuery({variables: {taskID}}); const { loading, data, refetch } = useFindTaskQuery({ variables: { taskID } });
const [setTaskComplete] = useSetTaskCompleteMutation(); const [setTaskComplete] = useSetTaskCompleteMutation();
const [updateTaskDueDate] = useUpdateTaskDueDateMutation({ const [updateTaskDueDate] = useUpdateTaskDueDateMutation({
onCompleted: () => { onCompleted: () => {
@ -312,7 +312,7 @@ const Details: React.FC<DetailsProps> = ({
task={data.findTask} task={data.findTask}
onChecklistDrop={checklist => { onChecklistDrop={checklist => {
updateTaskChecklistLocation({ updateTaskChecklistLocation({
variables: {checklistID: checklist.id, position: checklist.position}, variables: { checklistID: checklist.id, position: checklist.position },
optimisticResponse: { optimisticResponse: {
__typename: 'Mutation', __typename: 'Mutation',
@ -329,7 +329,7 @@ const Details: React.FC<DetailsProps> = ({
}} }}
onChecklistItemDrop={(prevChecklistID, checklistID, checklistItem) => { onChecklistItemDrop={(prevChecklistID, checklistID, checklistItem) => {
updateTaskChecklistItemLocation({ updateTaskChecklistItemLocation({
variables: {checklistID, checklistItemID: checklistItem.id, position: checklistItem.position}, variables: { checklistID, checklistItemID: checklistItem.id, position: checklistItem.position },
optimisticResponse: { optimisticResponse: {
__typename: 'Mutation', __typename: 'Mutation',
@ -350,22 +350,36 @@ const Details: React.FC<DetailsProps> = ({
onTaskNameChange={onTaskNameChange} onTaskNameChange={onTaskNameChange}
onTaskDescriptionChange={onTaskDescriptionChange} onTaskDescriptionChange={onTaskDescriptionChange}
onToggleTaskComplete={task => { onToggleTaskComplete={task => {
setTaskComplete({variables: {taskID: task.id, complete: !task.complete}}); setTaskComplete({ variables: { taskID: task.id, complete: !task.complete } });
}} }}
onDeleteTask={onDeleteTask} onDeleteTask={onDeleteTask}
onChangeItemName={(itemID, itemName) => { onChangeItemName={(itemID, itemName) => {
updateTaskChecklistItemName({variables: {taskChecklistItemID: itemID, name: itemName}}); updateTaskChecklistItemName({ variables: { taskChecklistItemID: itemID, name: itemName } });
}} }}
onCloseModal={() => history.push(projectURL)} onCloseModal={() => history.push(projectURL)}
onChangeChecklistName={(checklistID, newName) => { onChangeChecklistName={(checklistID, newName) => {
updateTaskChecklistName({variables: {taskChecklistID: checklistID, name: newName}}); updateTaskChecklistName({ variables: { taskChecklistID: checklistID, name: newName } });
}} }}
onDeleteItem={itemID => { onDeleteItem={(checklistID, itemID) => {
deleteTaskChecklistItem({variables: {taskChecklistItemID: itemID}}); deleteTaskChecklistItem({
variables: { taskChecklistItemID: itemID },
optimisticResponse: {
__typename: 'Mutation',
deleteTaskChecklistItem: {
__typename: 'DeleteTaskChecklistItemPayload',
ok: true,
taskChecklistItem: {
__typename: 'TaskChecklistItem',
id: itemID,
taskChecklistID: checklistID,
}
}
}
});
}} }}
onToggleChecklistItem={(itemID, complete) => { onToggleChecklistItem={(itemID, complete) => {
setTaskChecklistItemComplete({ setTaskChecklistItemComplete({
variables: {taskChecklistItemID: itemID, complete}, variables: { taskChecklistItemID: itemID, complete },
optimisticResponse: { optimisticResponse: {
__typename: 'Mutation', __typename: 'Mutation',
setTaskChecklistItemComplete: { setTaskChecklistItemComplete: {
@ -377,19 +391,19 @@ const Details: React.FC<DetailsProps> = ({
}); });
}} }}
onAddItem={(taskChecklistID, name, position) => { onAddItem={(taskChecklistID, name, position) => {
createTaskChecklistItem({variables: {taskChecklistID, name, position}}); createTaskChecklistItem({ variables: { taskChecklistID, name, position } });
}} }}
onMemberProfile={($targetRef, memberID) => { onMemberProfile={($targetRef, memberID) => {
const member = data.findTask.assigned.find(m => m.id === memberID); const member = data.findTask.assigned.find(m => m.id === memberID);
if (member) { if (member) {
showPopup( showPopup(
$targetRef, $targetRef,
<Popup title={null} onClose={() => {}} tab={0}> <Popup title={null} onClose={() => { }} tab={0}>
<MiniProfile <MiniProfile
user={member} user={member}
bio="None" bio="None"
onRemoveFromTask={() => { onRemoveFromTask={() => {
unassignTask({variables: {taskID: data.findTask.id, userID: userID ?? ''}}); unassignTask({ variables: { taskID: data.findTask.id, userID: userID ?? '' } });
}} }}
/> />
</Popup>, </Popup>,
@ -399,15 +413,15 @@ const Details: React.FC<DetailsProps> = ({
onOpenAddMemberPopup={(task, $targetRef) => { onOpenAddMemberPopup={(task, $targetRef) => {
showPopup( showPopup(
$targetRef, $targetRef,
<Popup title="Members" tab={0} onClose={() => {}}> <Popup title="Members" tab={0} onClose={() => { }}>
<MemberManager <MemberManager
availableMembers={availableMembers} availableMembers={availableMembers}
activeMembers={data.findTask.assigned} activeMembers={data.findTask.assigned}
onMemberChange={(member, isActive) => { onMemberChange={(member, isActive) => {
if (isActive) { if (isActive) {
assignTask({variables: {taskID: data.findTask.id, userID: userID ?? ''}}); assignTask({ variables: { taskID: data.findTask.id, userID: userID ?? '' } });
} else { } else {
unassignTask({variables: {taskID: data.findTask.id, userID: userID ?? ''}}); unassignTask({ variables: { taskID: data.findTask.id, userID: userID ?? '' } });
} }
}} }}
/> />
@ -457,7 +471,7 @@ const Details: React.FC<DetailsProps> = ({
<DeleteChecklistButton <DeleteChecklistButton
color="danger" color="danger"
onClick={() => { onClick={() => {
deleteTaskChecklist({variables: {taskChecklistID: checklistID}}); deleteTaskChecklist({ variables: { taskChecklistID: checklistID } });
hidePopup(); hidePopup();
}} }}
> >
@ -479,14 +493,14 @@ const Details: React.FC<DetailsProps> = ({
<DueDateManager <DueDateManager
task={task} task={task}
onRemoveDueDate={t => { onRemoveDueDate={t => {
updateTaskDueDate({variables: {taskID: t.id, dueDate: null}}); updateTaskDueDate({ variables: { taskID: t.id, dueDate: null } });
hidePopup(); hidePopup();
}} }}
onDueDateChange={(t, newDueDate) => { onDueDateChange={(t, newDueDate) => {
updateTaskDueDate({variables: {taskID: t.id, dueDate: newDueDate}}); updateTaskDueDate({ variables: { taskID: t.id, dueDate: newDueDate } });
hidePopup(); hidePopup();
}} }}
onCancel={() => {}} onCancel={() => { }}
/> />
</Popup>, </Popup>,
); );

View File

@ -1,19 +1,19 @@
import React, { useState } from 'react'; import React, {useState} from 'react';
import { action } from '@storybook/addon-actions'; import {action} from '@storybook/addon-actions';
import BaseStyles from 'App/BaseStyles'; import BaseStyles from 'App/BaseStyles';
import NormalizeStyles from 'App/NormalizeStyles'; import NormalizeStyles from 'App/NormalizeStyles';
import { theme } from 'App/ThemeStyles'; import {theme} from 'App/ThemeStyles';
import produce from 'immer'; import produce from 'immer';
import styled, { ThemeProvider } from 'styled-components'; import styled, {ThemeProvider} from 'styled-components';
import Checklist, { ChecklistItem } from '.'; import Checklist, {ChecklistItem} from '.';
export default { export default {
component: Checklist, component: Checklist,
title: 'Checklist', title: 'Checklist',
parameters: { parameters: {
backgrounds: [ backgrounds: [
{ name: 'gray', value: '#f8f8f8', default: true }, {name: 'gray', value: '#f8f8f8', default: true},
{ name: 'white', value: '#ffffff' }, {name: 'white', value: '#ffffff'},
], ],
}, },
}; };
@ -138,6 +138,7 @@ export const Default = () => {
key={item.id} key={item.id}
wrapperProps={{}} wrapperProps={{}}
handleProps={{}} handleProps={{}}
checklistID='id'
itemID={item.id} itemID={item.id}
name={item.name} name={item.name}
complete={item.complete} complete={item.complete}

View File

@ -1,7 +1,7 @@
import React, { useState, useRef, useEffect } from 'react'; import React, {useState, useRef, useEffect} from 'react';
import styled from 'styled-components'; import styled from 'styled-components';
import { CheckSquare, Trash, Square, CheckSquareOutline, Clock, Cross, AccountPlus } from 'shared/icons'; import {CheckSquare, Trash, Square, CheckSquareOutline, Clock, Cross, AccountPlus} from 'shared/icons';
import { DragDropContext, Droppable, Draggable, DropResult } from 'react-beautiful-dnd'; import {DragDropContext, Droppable, Draggable, DropResult} from 'react-beautiful-dnd';
import { import {
isPositionChanged, isPositionChanged,
getSortedDraggables, getSortedDraggables,
@ -81,7 +81,7 @@ const ChecklistProgressBar = styled.div`
overflow: hidden; overflow: hidden;
position: relative; position: relative;
`; `;
const ChecklistProgressBarCurrent = styled.div<{ width: number }>` const ChecklistProgressBarCurrent = styled.div<{width: number}>`
width: ${props => props.width}%; width: ${props => props.width}%;
background: rgba(${props => (props.width === 100 ? props.theme.colors.success : props.theme.colors.primary)}); background: rgba(${props => (props.width === 100 ? props.theme.colors.success : props.theme.colors.primary)});
bottom: 0; bottom: 0;
@ -129,9 +129,10 @@ const ChecklistItemTextControls = styled.div`
padding: 6px 0; padding: 6px 0;
width: 100%; width: 100%;
display: inline-flex; display: inline-flex;
align-items: center;
`; `;
const ChecklistItemText = styled.span<{ complete: boolean }>` const ChecklistItemText = styled.span<{complete: boolean}>`
color: ${props => (props.complete ? '#5e6c84' : `rgba(${props.theme.colors.text.primary})`)}; color: ${props => (props.complete ? '#5e6c84' : `rgba(${props.theme.colors.text.primary})`)};
${props => props.complete && 'text-decoration: line-through;'} ${props => props.complete && 'text-decoration: line-through;'}
line-height: 20px; line-height: 20px;
@ -155,6 +156,11 @@ const ControlButton = styled.div`
padding: 4px 6px; padding: 4px 6px;
border-radius: 6px; border-radius: 6px;
background-color: rgba(${props => props.theme.colors.bg.primary}, 0.8); background-color: rgba(${props => props.theme.colors.bg.primary}, 0.8);
display: flex;
width: 32px;
height: 32px;
align-items: center;
justify-content: center;
&:hover { &:hover {
background-color: rgba(${props => props.theme.colors.primary}, 1); background-color: rgba(${props => props.theme.colors.primary}, 1);
} }
@ -206,7 +212,7 @@ const TrashButton = styled(Trash)`
fill: rgba(${props => props.theme.colors.text.primary}); fill: rgba(${props => props.theme.colors.text.primary});
`; `;
const ChecklistItemWrapper = styled.div<{ ref: any }>` const ChecklistItemWrapper = styled.div<{ref: any}>`
user-select: none; user-select: none;
clear: both; clear: both;
padding-left: 40px; padding-left: 40px;
@ -216,6 +222,9 @@ const ChecklistItemWrapper = styled.div<{ ref: any }>`
transition-property: transform, opacity, height, padding, margin; transition-property: transform, opacity, height, padding, margin;
transition-duration: 0.14s; transition-duration: 0.14s;
transition-timing-function: ease-in; transition-timing-function: ease-in;
& ${ControlButton}:last-child {
margin-right: 4px;
}
&:hover { &:hover {
background-color: rgba(${props => props.theme.colors.bg.primary}, 0.4); background-color: rgba(${props => props.theme.colors.bg.primary}, 0.4);
@ -274,18 +283,19 @@ const ChecklistNewItem = styled.div`
type ChecklistItemProps = { type ChecklistItemProps = {
itemID: string; itemID: string;
checklistID: string;
complete: boolean; complete: boolean;
name: string; name: string;
onChangeName: (itemID: string, currentName: string) => void; onChangeName: (itemID: string, currentName: string) => void;
wrapperProps: any; wrapperProps: any;
handleProps: any; handleProps: any;
onToggleItem: (itemID: string, complete: boolean) => void; onToggleItem: (itemID: string, complete: boolean) => void;
onDeleteItem: (itemID: string) => void; onDeleteItem: (checklistIDID: string, itemID: string) => void;
}; };
export const ChecklistItem = React.forwardRef( export const ChecklistItem = React.forwardRef(
( (
{ itemID, complete, name, wrapperProps, handleProps, onChangeName, onToggleItem, onDeleteItem }: ChecklistItemProps, {itemID, checklistID, complete, name, wrapperProps, handleProps, onChangeName, onToggleItem, onDeleteItem}: ChecklistItemProps,
$item, $item,
) => { ) => {
const $editor = useRef<HTMLTextAreaElement>(null); const $editor = useRef<HTMLTextAreaElement>(null);
@ -352,7 +362,7 @@ export const ChecklistItem = React.forwardRef(
onClick={e => { onClick={e => {
e.stopPropagation(); e.stopPropagation();
setEditting(false); setEditting(false);
onDeleteItem(itemID); onDeleteItem(checklistID, itemID);
}} }}
> >
<Trash width={16} height={16} /> <Trash width={16} height={16} />
@ -378,7 +388,7 @@ export const ChecklistItem = React.forwardRef(
<ControlButton <ControlButton
onClick={e => { onClick={e => {
e.stopPropagation(); e.stopPropagation();
onDeleteItem(itemID); onDeleteItem(checklistID, itemID);
}} }}
> >
<TrashButton width={14} height={14} /> <TrashButton width={14} height={14} />
@ -397,7 +407,7 @@ type AddNewItemProps = {
onAddItem: (name: string) => void; onAddItem: (name: string) => void;
}; };
const AddNewItem: React.FC<AddNewItemProps> = ({ onAddItem }) => { const AddNewItem: React.FC<AddNewItemProps> = ({onAddItem}) => {
const $editor = useRef<HTMLTextAreaElement>(null); const $editor = useRef<HTMLTextAreaElement>(null);
const $wrapper = useRef<HTMLDivElement>(null); const $wrapper = useRef<HTMLDivElement>(null);
const [currentName, setCurrentName] = useState(''); const [currentName, setCurrentName] = useState('');
@ -467,7 +477,7 @@ type ChecklistTitleEditorProps = {
}; };
const ChecklistTitleEditor = React.forwardRef( const ChecklistTitleEditor = React.forwardRef(
({ name, onChangeName, onCancel }: ChecklistTitleEditorProps, $name: any) => { ({name, onChangeName, onCancel}: ChecklistTitleEditorProps, $name: any) => {
const [currentName, setCurrentName] = useState(name); const [currentName, setCurrentName] = useState(name);
return ( return (
<> <>
@ -515,7 +525,7 @@ type ChecklistProps = {
onChangeItemName: (itemID: string, currentName: string) => void; onChangeItemName: (itemID: string, currentName: string) => void;
wrapperProps: any; wrapperProps: any;
handleProps: any; handleProps: any;
onDeleteItem: (itemID: string) => void; onDeleteItem: (checklistID: string, itemID: string) => void;
onAddItem: (itemName: string) => void; onAddItem: (itemName: string) => void;
items: Array<TaskChecklistItem>; items: Array<TaskChecklistItem>;
}; };

View File

@ -1,5 +1,5 @@
import React, { useState, useRef, useEffect } from 'react'; import React, {useState, useRef, useEffect} from 'react';
import { Bin, Cross, Plus } from 'shared/icons'; import {Bin, Cross, Plus} from 'shared/icons';
import useOnOutsideClick from 'shared/hooks/onOutsideClick'; import useOnOutsideClick from 'shared/hooks/onOutsideClick';
import ReactMarkdown from 'react-markdown'; import ReactMarkdown from 'react-markdown';
@ -9,7 +9,7 @@ import {
getNewDraggablePosition, getNewDraggablePosition,
getAfterDropDraggableList, getAfterDropDraggableList,
} from 'shared/utils/draggables'; } from 'shared/utils/draggables';
import { DragDropContext, Droppable, Draggable, DropResult } from 'react-beautiful-dnd'; import {DragDropContext, Droppable, Draggable, DropResult} from 'react-beautiful-dnd';
import TaskAssignee from 'shared/components/TaskAssignee'; import TaskAssignee from 'shared/components/TaskAssignee';
import moment from 'moment'; import moment from 'moment';
@ -54,7 +54,7 @@ import {
MetaDetailTitle, MetaDetailTitle,
MetaDetailContent, MetaDetailContent,
} from './Styles'; } from './Styles';
import Checklist, { ChecklistItem, ChecklistItems } from '../Checklist'; import Checklist, {ChecklistItem, ChecklistItems} from '../Checklist';
import styled from 'styled-components'; import styled from 'styled-components';
const ChecklistContainer = styled.div``; const ChecklistContainer = styled.div``;
@ -69,7 +69,7 @@ type TaskLabelProps = {
onClick: ($target: React.RefObject<HTMLElement>) => void; onClick: ($target: React.RefObject<HTMLElement>) => void;
}; };
const TaskLabelItem: React.FC<TaskLabelProps> = ({ label, onClick }) => { const TaskLabelItem: React.FC<TaskLabelProps> = ({label, onClick}) => {
const $label = useRef<HTMLDivElement>(null); const $label = useRef<HTMLDivElement>(null);
return ( return (
<TaskDetailLabel <TaskDetailLabel
@ -84,7 +84,7 @@ const TaskLabelItem: React.FC<TaskLabelProps> = ({ label, onClick }) => {
); );
}; };
const TaskContent: React.FC<TaskContentProps> = ({ description, onEditContent }) => { const TaskContent: React.FC<TaskContentProps> = ({description, onEditContent}) => {
return description === '' ? ( return description === '' ? (
<TaskDetailsAddDetailsButton onClick={onEditContent}>Add a more detailed description</TaskDetailsAddDetailsButton> <TaskDetailsAddDetailsButton onClick={onEditContent}>Add a more detailed description</TaskDetailsAddDetailsButton>
) : ( ) : (
@ -144,7 +144,7 @@ type TaskDetailsProps = {
onTaskDescriptionChange: (task: Task, newDescription: string) => void; onTaskDescriptionChange: (task: Task, newDescription: string) => void;
onDeleteTask: (task: Task) => void; onDeleteTask: (task: Task) => void;
onAddItem: (checklistID: string, name: string, position: number) => void; onAddItem: (checklistID: string, name: string, position: number) => void;
onDeleteItem: (itemID: string) => void; onDeleteItem: (checklistID: string, itemID: string) => void;
onChangeItemName: (itemID: string, itemName: string) => void; onChangeItemName: (itemID: string, itemName: string) => void;
onToggleTaskComplete: (task: Task) => void; onToggleTaskComplete: (task: Task) => void;
onToggleChecklistItem: (itemID: string, complete: boolean) => void; onToggleChecklistItem: (itemID: string, complete: boolean) => void;
@ -214,7 +214,7 @@ const TaskDetails: React.FC<TaskDetailsProps> = ({
onOpenAddLabelPopup(task, $target); onOpenAddLabelPopup(task, $target);
}; };
const onDragEnd = ({ draggableId, source, destination, type }: DropResult) => { const onDragEnd = ({draggableId, source, destination, type}: DropResult) => {
if (typeof destination === 'undefined') return; if (typeof destination === 'undefined') return;
if (!isPositionChanged(source, destination)) return; if (!isPositionChanged(source, destination)) return;
@ -233,7 +233,7 @@ const TaskDetails: React.FC<TaskDetailsProps> = ({
}; };
beforeDropDraggables = getSortedDraggables( beforeDropDraggables = getSortedDraggables(
task.checklists.map(checklist => { task.checklists.map(checklist => {
return { id: checklist.id, position: checklist.position }; return {id: checklist.id, position: checklist.position};
}), }),
); );
if (droppedDraggable === null || beforeDropDraggables === null) { if (droppedDraggable === null || beforeDropDraggables === null) {
@ -249,9 +249,9 @@ const TaskDetails: React.FC<TaskDetailsProps> = ({
const newPosition = getNewDraggablePosition(afterDropDraggables, destination.index); const newPosition = getNewDraggablePosition(afterDropDraggables, destination.index);
console.log(droppedGroup); console.log(droppedGroup);
console.log(`positiion: ${newPosition}`); console.log(`positiion: ${newPosition}`);
onChecklistDrop({ ...droppedGroup, position: newPosition }); onChecklistDrop({...droppedGroup, position: newPosition});
} else { } else {
throw { error: 'task group can not be found' }; throw {error: 'task group can not be found'};
} }
} else { } else {
const targetChecklist = task.checklists.findIndex( const targetChecklist = task.checklists.findIndex(
@ -266,7 +266,7 @@ const TaskDetails: React.FC<TaskDetailsProps> = ({
}; };
beforeDropDraggables = getSortedDraggables( beforeDropDraggables = getSortedDraggables(
task.checklists[targetChecklist].items.map(item => { task.checklists[targetChecklist].items.map(item => {
return { id: item.id, position: item.position }; return {id: item.id, position: item.position};
}), }),
); );
if (droppedDraggable === null || beforeDropDraggables === null) { if (droppedDraggable === null || beforeDropDraggables === null) {
@ -430,6 +430,7 @@ const TaskDetails: React.FC<TaskDetailsProps> = ({
<ChecklistItem <ChecklistItem
key={item.id} key={item.id}
itemID={item.id} itemID={item.id}
checklistID={item.taskChecklistID}
ref={itemDrop.innerRef} ref={itemDrop.innerRef}
wrapperProps={itemDrop.draggableProps} wrapperProps={itemDrop.draggableProps}
handleProps={itemDrop.dragHandleProps} handleProps={itemDrop.dragHandleProps}
@ -437,7 +438,7 @@ const TaskDetails: React.FC<TaskDetailsProps> = ({
complete={item.complete} complete={item.complete}
onDeleteItem={onDeleteItem} onDeleteItem={onDeleteItem}
onChangeName={onChangeItemName} onChangeName={onChangeItemName}
onToggleItem={() => {}} onToggleItem={(itemID, complete) => onToggleChecklistItem(item.id, complete)}
/> />
)} )}
</Draggable> </Draggable>