taskcafe/web/src/Projects/Project/index.tsx

835 lines
28 KiB
TypeScript
Raw Normal View History

// LOC830
2020-06-13 00:21:58 +02:00
import React, { useState, useRef, useContext, useEffect } from 'react';
import { MENU_TYPES } from 'shared/components/TopNavbar';
import updateApolloCache from 'shared/utils/cache';
import GlobalTopNavbar, { ProjectPopup } from 'App/TopNavbar';
2020-06-24 03:46:45 +02:00
import styled, { css } from 'styled-components/macro';
import { Bolt, ToggleOn, Tags, CheckCircle, Sort, Filter } from 'shared/icons';
2020-05-27 02:53:31 +02:00
import { usePopup, Popup } from 'shared/components/PopupMenu';
import { useParams, Route, useRouteMatch, useHistory, RouteComponentProps } from 'react-router-dom';
import {
2020-06-19 01:12:15 +02:00
useSetTaskCompleteMutation,
2020-05-31 06:11:19 +02:00
useToggleTaskLabelMutation,
useUpdateProjectNameMutation,
useFindProjectQuery,
2020-06-19 01:12:15 +02:00
useUpdateTaskGroupNameMutation,
useUpdateTaskNameMutation,
useUpdateProjectLabelMutation,
useCreateTaskMutation,
useDeleteProjectLabelMutation,
useDeleteTaskMutation,
useUpdateTaskLocationMutation,
useUpdateTaskGroupLocationMutation,
useCreateTaskGroupMutation,
2020-04-11 21:24:45 +02:00
useDeleteTaskGroupMutation,
2020-04-20 05:02:55 +02:00
useUpdateTaskDescriptionMutation,
useAssignTaskMutation,
2020-05-27 02:53:31 +02:00
DeleteTaskDocument,
FindProjectDocument,
2020-05-27 23:18:50 +02:00
useCreateProjectLabelMutation,
useUnassignTaskMutation,
2020-06-19 01:12:15 +02:00
useUpdateTaskDueDateMutation,
FindProjectQuery,
} from 'shared/generated/graphql';
2020-04-10 04:40:22 +02:00
2020-05-27 23:18:50 +02:00
import TaskAssignee from 'shared/components/TaskAssignee';
2020-04-10 04:40:22 +02:00
import QuickCardEditor from 'shared/components/QuickCardEditor';
import ListActions from 'shared/components/ListActions';
2020-04-13 00:45:51 +02:00
import MemberManager from 'shared/components/MemberManager';
import { LabelsPopup } from 'shared/components/PopupMenu/PopupMenu.stories';
import KanbanBoard from 'Projects/Project/KanbanBoard';
2020-05-31 06:11:19 +02:00
import SimpleLists from 'shared/components/Lists';
2020-05-27 02:53:31 +02:00
import { mixin } from 'shared/utils/styles';
import LabelManager from 'shared/components/PopupMenu/LabelManager';
import LabelEditor from 'shared/components/PopupMenu/LabelEditor';
import produce from 'immer';
2020-05-27 23:18:50 +02:00
import MiniProfile from 'shared/components/MiniProfile';
import Details from './Details';
2020-05-31 06:11:19 +02:00
import { useApolloClient } from '@apollo/react-hooks';
import UserIDContext from 'App/context';
2020-06-19 01:12:15 +02:00
import DueDateManager from 'shared/components/DueDateManager';
const getCacheData = (client: any, projectID: string) => {
const cacheData: FindProjectQuery = client.readQuery({
query: FindProjectDocument,
variables: {
projectId: projectID,
},
});
return cacheData;
};
const writeCacheData = (client: any, projectID: string, cacheData: any, newData: any) => {
client.writeQuery({
query: FindProjectDocument,
variables: {
projectId: projectID,
},
data: { ...cacheData, findProject: newData },
});
};
2020-04-10 04:40:22 +02:00
type TaskRouteProps = {
taskID: string;
};
2020-04-10 04:40:22 +02:00
interface QuickCardEditorState {
isOpen: boolean;
target: React.RefObject<HTMLElement> | null;
2020-05-31 06:51:22 +02:00
taskID: string | null;
taskGroupID: string | null;
2020-04-10 04:40:22 +02:00
}
2020-04-10 18:31:29 +02:00
const TitleWrapper = styled.div`
margin-left: 38px;
margin-bottom: 15px;
`;
2020-04-10 04:40:22 +02:00
const Title = styled.span`
text-align: center;
font-size: 24px;
color: #fff;
`;
2020-05-27 23:18:50 +02:00
const ProjectMembers = styled.div`
display: flex;
padding-left: 4px;
padding-top: 4px;
align-items: center;
`;
2020-04-10 04:40:22 +02:00
2020-05-27 02:53:31 +02:00
type LabelManagerEditorProps = {
2020-05-31 06:11:19 +02:00
labels: React.RefObject<Array<ProjectLabel>>;
taskLabels: null | React.RefObject<Array<TaskLabel>>;
2020-05-27 23:18:50 +02:00
projectID: string;
labelColors: Array<LabelColor>;
2020-05-31 06:11:19 +02:00
onLabelToggle?: (labelId: string) => void;
2020-05-27 02:53:31 +02:00
};
2020-05-31 06:11:19 +02:00
const LabelManagerEditor: React.FC<LabelManagerEditorProps> = ({
labels: labelsRef,
projectID,
labelColors,
onLabelToggle,
taskLabels: taskLabelsRef,
}) => {
2020-05-27 02:53:31 +02:00
const [currentLabel, setCurrentLabel] = useState('');
const [createProjectLabel] = useCreateProjectLabelMutation({
update: (client, newLabelData) => {
updateApolloCache<FindProjectQuery>(
client,
FindProjectDocument,
cache =>
produce(cache, draftCache => {
draftCache.findProject.labels.push({ ...newLabelData.data.createProjectLabel });
}),
{
projectId: projectID,
},
);
},
});
const [updateProjectLabel] = useUpdateProjectLabelMutation();
const [deleteProjectLabel] = useDeleteProjectLabelMutation({
update: (client, newLabelData) => {
updateApolloCache<FindProjectQuery>(
client,
FindProjectDocument,
cache =>
produce(cache, draftCache => {
draftCache.findProject.labels = cache.findProject.labels.filter(
label => label.id !== newLabelData.data.deleteProjectLabel.id,
);
}),
{ projectId: projectID },
);
},
});
const labels = labelsRef.current ? labelsRef.current : [];
2020-05-31 06:11:19 +02:00
const taskLabels = taskLabelsRef && taskLabelsRef.current ? taskLabelsRef.current : [];
const [currentTaskLabels, setCurrentTaskLabels] = useState(taskLabels);
console.log(taskLabels);
const { setTab, hidePopup } = usePopup();
2020-05-27 02:53:31 +02:00
return (
<>
<Popup title="Labels" tab={0} onClose={() => hidePopup()}>
2020-05-27 02:53:31 +02:00
<LabelManager
labels={labels}
2020-05-31 06:11:19 +02:00
taskLabels={currentTaskLabels}
2020-05-27 02:53:31 +02:00
onLabelCreate={() => {
setTab(2);
}}
onLabelEdit={labelId => {
setCurrentLabel(labelId);
setTab(1);
}}
onLabelToggle={labelId => {
2020-05-31 06:11:19 +02:00
if (onLabelToggle) {
if (currentTaskLabels.find(t => t.projectLabel.id === labelId)) {
setCurrentTaskLabels(currentTaskLabels.filter(t => t.projectLabel.id !== labelId));
} else {
const newProjectLabel = labels.find(l => l.id === labelId);
if (newProjectLabel) {
setCurrentTaskLabels([
...currentTaskLabels,
{ id: '', assignedDate: '', projectLabel: { ...newProjectLabel } },
]);
}
}
setCurrentLabel(labelId);
onLabelToggle(labelId);
} else {
setCurrentLabel(labelId);
setTab(1);
}
2020-05-27 02:53:31 +02:00
}}
/>
</Popup>
<Popup onClose={() => hidePopup()} title="Edit label" tab={1}>
2020-05-27 02:53:31 +02:00
<LabelEditor
2020-05-27 23:18:50 +02:00
labelColors={labelColors}
2020-05-31 06:11:19 +02:00
label={labels.find(label => label.id === currentLabel) ?? null}
onLabelEdit={(projectLabelID, name, color) => {
if (projectLabelID) {
2020-05-31 06:11:19 +02:00
updateProjectLabel({ variables: { projectLabelID, labelColorID: color.id, name: name ?? '' } });
}
setTab(0);
}}
onLabelDelete={labelID => {
deleteProjectLabel({ variables: { projectLabelID: labelID } });
2020-05-27 02:53:31 +02:00
setTab(0);
}}
/>
</Popup>
<Popup onClose={() => hidePopup()} title="Create new label" tab={2}>
2020-05-27 02:53:31 +02:00
<LabelEditor
2020-05-27 23:18:50 +02:00
labelColors={labelColors}
2020-05-27 02:53:31 +02:00
label={null}
onLabelEdit={(_labelId, name, color) => {
2020-05-31 06:11:19 +02:00
createProjectLabel({ variables: { projectID, labelColorID: color.id, name: name ?? '' } });
2020-05-27 02:53:31 +02:00
setTab(0);
}}
/>
</Popup>
</>
);
};
2020-04-10 04:40:22 +02:00
interface ProjectParams {
projectID: string;
2020-04-10 04:40:22 +02:00
}
2020-05-31 06:51:22 +02:00
const initialQuickCardEditorState: QuickCardEditorState = {
taskID: null,
taskGroupID: null,
isOpen: false,
target: null,
2020-05-31 06:51:22 +02:00
};
2020-04-10 04:40:22 +02:00
2020-05-27 23:18:50 +02:00
const ProjectBar = styled.div`
2020-05-27 02:53:31 +02:00
display: flex;
align-items: center;
justify-content: space-between;
2020-05-27 02:53:31 +02:00
height: 40px;
padding: 0 12px;
`;
2020-05-27 23:18:50 +02:00
const ProjectActions = styled.div`
display: flex;
align-items: center;
`;
2020-06-24 03:46:45 +02:00
const ProjectAction = styled.div<{ disabled?: boolean }>`
2020-05-27 02:53:31 +02:00
cursor: pointer;
display: flex;
align-items: center;
font-size: 15px;
2020-06-16 00:36:59 +02:00
color: rgba(${props => props.theme.colors.text.primary});
2020-05-27 02:53:31 +02:00
&:not(:last-child) {
margin-right: 16px;
}
&:hover {
2020-06-16 00:36:59 +02:00
color: rgba(${props => props.theme.colors.text.secondary});
2020-05-27 02:53:31 +02:00
}
2020-06-24 03:46:45 +02:00
${props =>
props.disabled &&
css`
opacity: 0.5;
cursor: default;
pointer-events: none;
`}
2020-05-27 02:53:31 +02:00
`;
const ProjectActionText = styled.span`
padding-left: 4px;
`;
2020-04-10 04:40:22 +02:00
const Project = () => {
const { projectID } = useParams<ProjectParams>();
2020-05-31 06:11:19 +02:00
const history = useHistory();
const match = useRouteMatch();
2020-04-20 05:02:55 +02:00
const [updateTaskDescription] = useUpdateTaskDescriptionMutation();
2020-04-10 04:40:22 +02:00
const [quickCardEditor, setQuickCardEditor] = useState(initialQuickCardEditorState);
const [updateTaskLocation] = useUpdateTaskLocationMutation({
update: (client, newTask) => {
updateApolloCache<FindProjectQuery>(
client,
FindProjectDocument,
cache =>
produce(cache, draftCache => {
const { previousTaskGroupID, task } = newTask.data.updateTaskLocation;
if (previousTaskGroupID !== task.taskGroup.id) {
const { taskGroups } = cache.findProject;
const oldTaskGroupIdx = taskGroups.findIndex((t: TaskGroup) => t.id === previousTaskGroupID);
const newTaskGroupIdx = taskGroups.findIndex((t: TaskGroup) => t.id === task.taskGroup.id);
if (oldTaskGroupIdx !== -1 && newTaskGroupIdx !== -1) {
draftCache.findProject.taskGroups[oldTaskGroupIdx].tasks = taskGroups[oldTaskGroupIdx].tasks.filter(
(t: Task) => t.id !== task.id,
);
draftCache.findProject.taskGroups[newTaskGroupIdx].tasks = [
...taskGroups[newTaskGroupIdx].tasks,
{ ...task },
];
}
}
}),
{ projectId: projectID },
);
},
});
2020-05-31 06:11:19 +02:00
const [updateTaskGroupLocation] = useUpdateTaskGroupLocationMutation({});
2020-04-11 21:24:45 +02:00
const [deleteTaskGroup] = useDeleteTaskGroupMutation({
2020-05-31 06:11:19 +02:00
onCompleted: deletedTaskGroupData => {},
update: (client, deletedTaskGroupData) => {
updateApolloCache<FindProjectQuery>(
client,
FindProjectDocument,
cache =>
produce(cache, draftCache => {
draftCache.findProject.taskGroups = draftCache.findProject.taskGroups.filter(
(taskGroup: TaskGroup) => taskGroup.id !== deletedTaskGroupData.data.deleteTaskGroup.taskGroup.id,
);
}),
{ projectId: projectID },
);
},
2020-04-11 21:24:45 +02:00
});
const [createTaskGroup] = useCreateTaskGroupMutation({
2020-05-31 06:11:19 +02:00
onCompleted: newTaskGroupData => {},
update: (client, newTaskGroupData) => {
updateApolloCache<FindProjectQuery>(
client,
FindProjectDocument,
cache => {
console.log(cache);
return produce(cache, draftCache => {
draftCache.findProject.taskGroups.push({ ...newTaskGroupData.data.createTaskGroup, tasks: [] });
});
},
{ projectId: projectID },
);
},
});
const [createTask] = useCreateTaskMutation({
2020-05-31 06:11:19 +02:00
onCompleted: newTaskData => {},
2020-05-27 02:53:31 +02:00
update: (client, newTaskData) => {
updateApolloCache<FindProjectQuery>(
client,
FindProjectDocument,
cache =>
produce(cache, draftCache => {
const { taskGroups } = cache.findProject;
const idx = taskGroups.findIndex(taskGroup => taskGroup.id === newTaskData.data.createTask.taskGroup.id);
if (idx !== -1) {
draftCache.findProject.taskGroups[idx].tasks.push({ ...newTaskData.data.createTask });
}
}),
{ projectId: projectID },
);
2020-05-27 02:53:31 +02:00
},
2020-04-10 04:40:22 +02:00
});
const [deleteTask] = useDeleteTaskMutation({
2020-05-31 06:11:19 +02:00
onCompleted: deletedTask => {},
2020-04-10 04:40:22 +02:00
});
const [updateTaskName] = useUpdateTaskNameMutation({
2020-05-31 06:11:19 +02:00
onCompleted: newTaskData => {},
});
const [toggleTaskLabel] = useToggleTaskLabelMutation({
onCompleted: newTaskLabel => {
taskLabelsRef.current = newTaskLabel.toggleTaskLabel.task.labels;
console.log(taskLabelsRef.current);
2020-04-10 04:40:22 +02:00
},
});
2020-04-21 01:04:27 +02:00
const { loading, data, refetch } = useFindProjectQuery({
variables: { projectId: projectID },
2020-05-31 06:11:19 +02:00
onCompleted: newData => {},
2020-04-10 04:40:22 +02:00
});
2020-04-10 04:40:22 +02:00
const onCardCreate = (taskGroupID: string, name: string) => {
2020-05-31 06:11:19 +02:00
if (data) {
const taskGroupTasks = data.findProject.taskGroups.filter(t => t.id === taskGroupID);
if (taskGroupTasks) {
let position = 65535;
if (taskGroupTasks.length !== 0) {
const [lastTask] = taskGroupTasks.sort((a: any, b: any) => a.position - b.position).slice(-1);
position = Math.ceil(lastTask.position) * 2 + 1;
}
createTask({ variables: { taskGroupID, name, position } });
}
2020-04-10 04:40:22 +02:00
}
2020-05-31 06:11:19 +02:00
};
2020-04-10 04:40:22 +02:00
2020-05-31 06:11:19 +02:00
const onCreateTask = (taskGroupID: string, name: string) => {
if (data) {
const taskGroup = data.findProject.taskGroups.find(t => t.id === taskGroupID);
console.log(`taskGroup ${taskGroup}`);
if (taskGroup) {
let position = 65535;
if (taskGroup.tasks.length !== 0) {
2020-06-19 01:12:15 +02:00
const [lastTask] = taskGroup.tasks
.slice()
.sort((a: any, b: any) => a.position - b.position)
.slice(-1);
2020-05-31 06:11:19 +02:00
position = Math.ceil(lastTask.position) * 2 + 1;
}
console.log(`position ${position}`);
2020-06-19 01:12:15 +02:00
createTask({
variables: { taskGroupID, name, position },
optimisticResponse: {
__typename: 'Mutation',
createTask: {
__typename: 'Task',
id: '' + Math.round(Math.random() * -1000000),
name,
complete: false,
2020-06-19 01:12:15 +02:00
taskGroup: {
__typename: 'TaskGroup',
id: taskGroup.id,
name: taskGroup.name,
position: taskGroup.position,
},
badges: {
checklist: null,
},
position,
2020-06-19 01:12:15 +02:00
dueDate: null,
description: null,
labels: [],
assigned: [],
},
},
});
2020-05-31 06:11:19 +02:00
}
}
2020-04-10 04:40:22 +02:00
};
const onListDrop = (droppedColumn: TaskGroup) => {
2020-05-31 06:11:19 +02:00
console.log(`list drop ${droppedColumn.id}`);
updateApolloCache<FindProjectQuery>(
client,
FindProjectDocument,
cache =>
produce(cache, draftCache => {
const taskGroupIdx = cache.findProject.taskGroups.findIndex(t => t.id === droppedColumn.id);
if (taskGroupIdx !== -1) {
draftCache.findProject.taskGroups[taskGroupIdx].position = droppedColumn.position;
}
}),
{
projectId: projectID,
},
);
updateTaskGroupLocation({
2020-05-31 06:11:19 +02:00
variables: { taskGroupID: droppedColumn.id, position: droppedColumn.position },
optimisticResponse: {
updateTaskGroupLocation: {
2020-05-31 06:11:19 +02:00
id: droppedColumn.id,
position: droppedColumn.position,
},
},
});
};
const onCreateList = (listName: string) => {
2020-05-31 06:11:19 +02:00
if (data) {
const [lastColumn] = data.findProject.taskGroups.sort((a, b) => a.position - b.position).slice(-1);
let position = 65535;
if (lastColumn) {
position = lastColumn.position * 2 + 1;
}
createTaskGroup({ variables: { projectID, name: listName, position } });
}
};
2020-04-10 04:40:22 +02:00
2020-04-20 05:02:55 +02:00
const [assignTask] = useAssignTaskMutation();
const [unassignTask] = useUnassignTaskMutation();
2020-04-20 05:02:55 +02:00
2020-06-19 01:12:15 +02:00
const [updateTaskGroupName] = useUpdateTaskGroupNameMutation({});
const [updateTaskDueDate] = useUpdateTaskDueDateMutation();
const [updateProjectName] = useUpdateProjectNameMutation({
update: (client, newName) => {
updateApolloCache<FindProjectQuery>(
client,
FindProjectDocument,
cache =>
produce(cache, draftCache => {
draftCache.findProject.name = newName.data.updateProjectName.name;
}),
{ projectId: projectID },
);
},
});
2020-05-31 06:11:19 +02:00
2020-06-19 01:12:15 +02:00
const [setTaskComplete] = useSetTaskCompleteMutation();
2020-05-31 06:11:19 +02:00
const client = useApolloClient();
const { userID } = useContext(UserIDContext);
2020-05-31 06:11:19 +02:00
const { showPopup, hidePopup } = usePopup();
2020-05-27 02:53:31 +02:00
const $labelsRef = useRef<HTMLDivElement>(null);
2020-05-31 06:11:19 +02:00
const labelsRef = useRef<Array<ProjectLabel>>([]);
const taskLabelsRef = useRef<Array<TaskLabel>>([]);
2020-06-13 00:21:58 +02:00
useEffect(() => {
if (data) {
document.title = `${data.findProject.name} | Citadel`;
}
}, [data]);
2020-04-10 04:40:22 +02:00
if (loading) {
2020-05-27 02:53:31 +02:00
return (
<>
<GlobalTopNavbar onSaveProjectName={projectName => {}} name="" projectID={null} />
2020-05-27 02:53:31 +02:00
</>
);
2020-04-10 04:40:22 +02:00
}
if (data) {
2020-06-19 01:12:15 +02:00
console.log(data.findProject);
const onQuickEditorOpen = ($target: React.RefObject<HTMLElement>, taskID: string, taskGroupID: string) => {
if ($target && $target.current) {
const pos = $target.current.getBoundingClientRect();
const height = 120;
if (window.innerHeight - pos.bottom < height) {
}
}
const taskGroup = data.findProject.taskGroups.find(t => t.id === taskGroupID);
const currentTask = taskGroup ? taskGroup.tasks.find(t => t.id === taskID) : null;
2020-05-31 06:11:19 +02:00
if (currentTask) {
setQuickCardEditor({
target: $target,
2020-05-31 06:11:19 +02:00
isOpen: true,
2020-05-31 06:51:22 +02:00
taskID: currentTask.id,
taskGroupID: currentTask.taskGroup.id,
2020-05-31 06:11:19 +02:00
});
}
2020-05-27 02:53:31 +02:00
};
2020-05-27 23:18:50 +02:00
2020-05-31 06:11:19 +02:00
labelsRef.current = data.findProject.labels;
2020-05-31 06:51:22 +02:00
let currentQuickTask = null;
if (quickCardEditor.taskID && quickCardEditor.taskGroupID) {
const targetGroup = data.findProject.taskGroups.find(t => t.id === quickCardEditor.taskGroupID);
if (targetGroup) {
currentQuickTask = targetGroup.tasks.find(t => t.id === quickCardEditor.taskID);
}
}
2020-04-10 04:40:22 +02:00
return (
<>
2020-05-31 06:11:19 +02:00
<GlobalTopNavbar
onSaveProjectName={projectName => {
updateProjectName({ variables: { projectID, name: projectName } });
}}
popupContent={<ProjectPopup history={history} name={data.findProject.name} projectID={projectID} />}
menuType={MENU_TYPES.PROJECT_MENU}
initialTab={0}
2020-05-31 06:11:19 +02:00
projectMembers={data.findProject.members}
projectID={projectID}
2020-05-31 06:11:19 +02:00
name={data.findProject.name}
/>
2020-05-27 23:18:50 +02:00
<ProjectBar>
<ProjectActions>
2020-06-24 03:46:45 +02:00
<ProjectAction disabled>
<CheckCircle width={13} height={13} />
<ProjectActionText>All Tasks</ProjectActionText>
</ProjectAction>
2020-06-24 03:46:45 +02:00
<ProjectAction disabled>
<Filter width={13} height={13} />
<ProjectActionText>Filter</ProjectActionText>
</ProjectAction>
2020-06-24 03:46:45 +02:00
<ProjectAction disabled>
<Sort width={13} height={13} />
<ProjectActionText>Sort</ProjectActionText>
</ProjectAction>
</ProjectActions>
2020-05-27 23:18:50 +02:00
<ProjectActions>
<ProjectAction
ref={$labelsRef}
onClick={() => {
showPopup(
$labelsRef,
2020-05-31 06:11:19 +02:00
<LabelManagerEditor
taskLabels={null}
labelColors={data.labelColors}
labels={labelsRef}
projectID={projectID}
/>,
2020-05-27 23:18:50 +02:00
);
}}
>
2020-06-16 00:36:59 +02:00
<Tags width={13} height={13} />
2020-05-27 23:18:50 +02:00
<ProjectActionText>Labels</ProjectActionText>
</ProjectAction>
2020-06-24 03:46:45 +02:00
<ProjectAction disabled>
2020-06-16 00:36:59 +02:00
<ToggleOn width={13} height={13} />
2020-05-27 23:18:50 +02:00
<ProjectActionText>Fields</ProjectActionText>
</ProjectAction>
2020-06-24 03:46:45 +02:00
<ProjectAction disabled>
2020-06-16 00:36:59 +02:00
<Bolt width={13} height={13} />
2020-05-27 23:18:50 +02:00
<ProjectActionText>Rules</ProjectActionText>
</ProjectAction>
</ProjectActions>
</ProjectBar>
2020-05-31 06:11:19 +02:00
<SimpleLists
onTaskClick={task => {
history.push(`${match.url}/c/${task.id}`);
}}
onTaskDrop={(droppedTask, previousTaskGroupID) => {
2020-05-31 06:11:19 +02:00
updateTaskLocation({
variables: {
taskID: droppedTask.id,
taskGroupID: droppedTask.taskGroup.id,
position: droppedTask.position,
},
optimisticResponse: {
__typename: 'Mutation',
updateTaskLocation: {
previousTaskGroupID,
task: {
name: droppedTask.name,
id: droppedTask.id,
position: droppedTask.position,
taskGroup: {
id: droppedTask.taskGroup.id,
__typename: 'TaskGroup',
},
createdAt: '',
__typename: 'Task',
},
2020-05-31 06:11:19 +02:00
},
},
});
}}
onTaskGroupDrop={droppedTaskGroup => {
updateTaskGroupLocation({
variables: { taskGroupID: droppedTaskGroup.id, position: droppedTaskGroup.position },
optimisticResponse: {
__typename: 'Mutation',
updateTaskGroupLocation: {
id: droppedTaskGroup.id,
position: droppedTaskGroup.position,
__typename: 'TaskGroup',
},
},
});
}}
taskGroups={data.findProject.taskGroups}
onCreateTask={onCreateTask}
onCreateTaskGroup={onCreateList}
2020-05-27 23:18:50 +02:00
onCardMemberClick={($targetRef, taskID, memberID) => {
2020-05-31 06:11:19 +02:00
const member = data.findProject.members.find(m => m.id === memberID);
const profileIcon = member ? member.profileIcon : null;
2020-05-27 23:18:50 +02:00
showPopup(
$targetRef,
<Popup
title={null}
onClose={() => {
hidePopup();
}}
tab={0}
>
2020-05-27 23:18:50 +02:00
<MiniProfile
2020-05-31 06:11:19 +02:00
profileIcon={profileIcon}
2020-05-27 23:18:50 +02:00
displayName="Jordan Knott"
username="@jordanthedev"
bio="None"
onRemoveFromTask={() => {
/* unassignTask({ variables: { taskID: data.findTask.id, userID: userID ?? '' } }); */
}}
/>
</Popup>,
);
}}
2020-06-19 01:12:15 +02:00
onChangeTaskGroupName={(taskGroupID, name) => {
updateTaskGroupName({ variables: { taskGroupID, name } });
}}
2020-04-20 05:02:55 +02:00
onQuickEditorOpen={onQuickEditorOpen}
2020-05-31 06:11:19 +02:00
onExtraMenuOpen={(taskGroupID: string, $targetRef: any) => {
2020-05-27 02:53:31 +02:00
showPopup(
$targetRef,
<Popup title="List actions" tab={0} onClose={() => hidePopup()}>
2020-05-27 02:53:31 +02:00
<ListActions
taskGroupID={taskGroupID}
onArchiveTaskGroup={tgID => {
deleteTaskGroup({ variables: { taskGroupID: tgID } });
hidePopup();
2020-05-27 02:53:31 +02:00
}}
/>
</Popup>,
);
2020-04-20 05:02:55 +02:00
}}
/>
{quickCardEditor.isOpen && currentQuickTask && quickCardEditor.target && (
<QuickCardEditor
2020-05-31 06:51:22 +02:00
task={currentQuickTask}
onCloseEditor={() => setQuickCardEditor(initialQuickCardEditorState)}
onEditCard={(_taskGroupID: string, taskID: string, cardName: string) => {
updateTaskName({ variables: { taskID, name: cardName } });
2020-04-13 00:45:51 +02:00
}}
onOpenMembersPopup={($targetRef, task) => {
showPopup(
$targetRef,
<Popup title="Members" tab={0} onClose={() => hidePopup()}>
<MemberManager
availableMembers={data.findProject.members}
activeMembers={task.assigned ?? []}
onMemberChange={(member, isActive) => {
if (isActive) {
assignTask({ variables: { taskID: task.id, userID: userID ?? '' } });
} else {
unassignTask({ variables: { taskID: task.id, userID: userID ?? '' } });
}
}}
/>
</Popup>,
);
}}
onCardMemberClick={($targetRef, taskID, memberID) => {
const member = data.findProject.members.find(m => m.id === memberID);
const profileIcon = member ? member.profileIcon : null;
showPopup(
$targetRef,
<Popup title={null} onClose={() => hidePopup()} tab={0}>
<MiniProfile
profileIcon={profileIcon}
displayName="Jordan Knott"
username="@jordanthedev"
bio="None"
onRemoveFromTask={() => {
/* unassignTask({ variables: { taskID: data.findTask.id, userID: userID ?? '' } }); */
}}
/>
</Popup>,
);
}}
2020-05-31 06:51:22 +02:00
onOpenLabelsPopup={($targetRef, task) => {
taskLabelsRef.current = task.labels;
showPopup(
$targetRef,
<LabelManagerEditor
onLabelToggle={labelID => {
toggleTaskLabel({ variables: { taskID: task.id, projectLabelID: labelID } });
}}
labelColors={data.labelColors}
labels={labelsRef}
taskLabels={taskLabelsRef}
projectID={projectID}
/>,
);
}}
2020-05-27 02:53:31 +02:00
onArchiveCard={(_listId: string, cardId: string) =>
deleteTask({
variables: { taskID: cardId },
update: () => {
updateApolloCache<FindProjectQuery>(
client,
FindProjectDocument,
cache =>
produce(cache, draftCache => {
draftCache.findProject.taskGroups = cache.findProject.taskGroups.map(taskGroup => ({
...taskGroup,
tasks: taskGroup.tasks.filter(t => t.id !== cardId),
}));
}),
{ projectId: projectID },
);
2020-05-27 02:53:31 +02:00
},
})
}
2020-06-19 01:12:15 +02:00
onOpenDueDatePopup={($targetRef, task) => {
showPopup(
$targetRef,
<Popup title={'Change Due Date'} tab={0} onClose={() => hidePopup()}>
2020-06-19 01:12:15 +02:00
<DueDateManager
task={task}
onRemoveDueDate={t => {
updateTaskDueDate({ variables: { taskID: t.id, dueDate: null } });
hidePopup();
}}
onDueDateChange={(t, newDueDate) => {
updateTaskDueDate({ variables: { taskID: t.id, dueDate: newDueDate } });
hidePopup();
}}
onCancel={() => {}}
/>
</Popup>,
);
}}
onToggleComplete={task => {
setTaskComplete({ variables: { taskID: task.id, complete: !task.complete } });
}}
target={quickCardEditor.target}
2020-04-13 00:45:51 +02:00
/>
)}
<Route
path={`${match.path}/c/:taskID`}
render={(routeProps: RouteComponentProps<TaskRouteProps>) => (
2020-04-20 05:02:55 +02:00
<Details
refreshCache={() => {}}
2020-05-31 06:11:19 +02:00
availableMembers={data.findProject.members}
2020-04-20 05:02:55 +02:00
projectURL={match.url}
taskID={routeProps.match.params.taskID}
onTaskNameChange={(updatedTask, newName) => {
2020-05-31 06:11:19 +02:00
updateTaskName({ variables: { taskID: updatedTask.id, name: newName } });
2020-04-20 05:02:55 +02:00
}}
onTaskDescriptionChange={(updatedTask, newDescription) => {
2020-05-31 06:11:19 +02:00
updateTaskDescription({ variables: { taskID: updatedTask.id, description: newDescription } });
}}
2020-04-20 05:02:55 +02:00
onDeleteTask={deletedTask => {
2020-05-31 06:11:19 +02:00
deleteTask({ variables: { taskID: deletedTask.id } });
}}
onOpenAddLabelPopup={(task, $targetRef) => {
taskLabelsRef.current = task.labels;
showPopup(
$targetRef,
<LabelManagerEditor
onLabelToggle={labelID => {
toggleTaskLabel({ variables: { taskID: task.id, projectLabelID: labelID } });
}}
labelColors={data.labelColors}
labels={labelsRef}
taskLabels={taskLabelsRef}
projectID={projectID}
/>,
);
}}
/>
)}
/>
2020-04-10 04:40:22 +02:00
</>
);
}
2020-04-20 05:02:55 +02:00
return <div>Error</div>;
2020-04-10 04:40:22 +02:00
};
export default Project;