feature(Project): add ability to create new task groups
This commit is contained in:
parent
e022e7914a
commit
bd73717deb
@ -7,12 +7,15 @@ import {
|
|||||||
useCreateTaskMutation,
|
useCreateTaskMutation,
|
||||||
useDeleteTaskMutation,
|
useDeleteTaskMutation,
|
||||||
useUpdateTaskLocationMutation,
|
useUpdateTaskLocationMutation,
|
||||||
|
useCreateTaskGroupMutation,
|
||||||
} from 'shared/generated/graphql';
|
} from 'shared/generated/graphql';
|
||||||
|
|
||||||
import Navbar from 'App/Navbar';
|
import Navbar from 'App/Navbar';
|
||||||
import TopNavbar from 'App/TopNavbar';
|
import TopNavbar from 'App/TopNavbar';
|
||||||
import Lists from 'shared/components/Lists';
|
import Lists from 'shared/components/Lists';
|
||||||
import QuickCardEditor from 'shared/components/QuickCardEditor';
|
import QuickCardEditor from 'shared/components/QuickCardEditor';
|
||||||
|
import PopupMenu from 'shared/components/PopupMenu';
|
||||||
|
import ListActions from 'shared/components/ListActions';
|
||||||
|
|
||||||
interface ColumnState {
|
interface ColumnState {
|
||||||
[key: string]: TaskGroup;
|
[key: string]: TaskGroup;
|
||||||
@ -65,13 +68,32 @@ interface ProjectParams {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const initialState: State = { tasks: {}, columns: {} };
|
const initialState: State = { tasks: {}, columns: {} };
|
||||||
|
const initialPopupState = { left: 0, top: 0, isOpen: false, taskGroupID: '' };
|
||||||
const initialQuickCardEditorState: QuickCardEditorState = { isOpen: false, top: 0, left: 0 };
|
const initialQuickCardEditorState: QuickCardEditorState = { isOpen: false, top: 0, left: 0 };
|
||||||
|
|
||||||
const Project = () => {
|
const Project = () => {
|
||||||
const { projectId } = useParams<ProjectParams>();
|
const { projectId } = useParams<ProjectParams>();
|
||||||
const [listsData, setListsData] = useState(initialState);
|
const [listsData, setListsData] = useState(initialState);
|
||||||
|
const [popupData, setPopupData] = useState(initialPopupState);
|
||||||
const [quickCardEditor, setQuickCardEditor] = useState(initialQuickCardEditorState);
|
const [quickCardEditor, setQuickCardEditor] = useState(initialQuickCardEditorState);
|
||||||
const [updateTaskLocation] = useUpdateTaskLocationMutation();
|
const [updateTaskLocation] = useUpdateTaskLocationMutation();
|
||||||
|
const [createTaskGroup] = useCreateTaskGroupMutation({
|
||||||
|
onCompleted: newTaskGroupData => {
|
||||||
|
const newListsData = {
|
||||||
|
...listsData,
|
||||||
|
columns: {
|
||||||
|
...listsData.columns,
|
||||||
|
[newTaskGroupData.createTaskGroup.taskGroupID]: {
|
||||||
|
taskGroupID: newTaskGroupData.createTaskGroup.taskGroupID,
|
||||||
|
name: newTaskGroupData.createTaskGroup.name,
|
||||||
|
position: newTaskGroupData.createTaskGroup.position,
|
||||||
|
tasks: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
setListsData(newListsData);
|
||||||
|
},
|
||||||
|
});
|
||||||
const [createTask] = useCreateTaskMutation({
|
const [createTask] = useCreateTaskMutation({
|
||||||
onCompleted: newTaskData => {
|
onCompleted: newTaskData => {
|
||||||
const newListsData = {
|
const newListsData = {
|
||||||
@ -79,7 +101,9 @@ const Project = () => {
|
|||||||
tasks: {
|
tasks: {
|
||||||
...listsData.tasks,
|
...listsData.tasks,
|
||||||
[newTaskData.createTask.taskID]: {
|
[newTaskData.createTask.taskID]: {
|
||||||
taskGroupID: newTaskData.createTask.taskGroupID,
|
taskGroup: {
|
||||||
|
taskGroupID: newTaskData.createTask.taskGroup.taskGroupID,
|
||||||
|
},
|
||||||
taskID: newTaskData.createTask.taskID,
|
taskID: newTaskData.createTask.taskID,
|
||||||
name: newTaskData.createTask.name,
|
name: newTaskData.createTask.name,
|
||||||
position: newTaskData.createTask.position,
|
position: newTaskData.createTask.position,
|
||||||
@ -119,17 +143,19 @@ const Project = () => {
|
|||||||
variables: { projectId },
|
variables: { projectId },
|
||||||
onCompleted: newData => {
|
onCompleted: newData => {
|
||||||
const newListsData: State = { tasks: {}, columns: {} };
|
const newListsData: State = { tasks: {}, columns: {} };
|
||||||
newData.findProject.taskGroups.forEach((taskGroup: TaskGroup) => {
|
newData.findProject.taskGroups.forEach(taskGroup => {
|
||||||
newListsData.columns[taskGroup.taskGroupID] = {
|
newListsData.columns[taskGroup.taskGroupID] = {
|
||||||
taskGroupID: taskGroup.taskGroupID,
|
taskGroupID: taskGroup.taskGroupID,
|
||||||
name: taskGroup.name,
|
name: taskGroup.name,
|
||||||
position: taskGroup.position,
|
position: taskGroup.position,
|
||||||
tasks: [],
|
tasks: [],
|
||||||
};
|
};
|
||||||
taskGroup.tasks.forEach((task: Task) => {
|
taskGroup.tasks.forEach(task => {
|
||||||
newListsData.tasks[task.taskID] = {
|
newListsData.tasks[task.taskID] = {
|
||||||
taskID: task.taskID,
|
taskID: task.taskID,
|
||||||
taskGroupID: taskGroup.taskGroupID,
|
taskGroup: {
|
||||||
|
taskGroupID: taskGroup.taskGroupID,
|
||||||
|
},
|
||||||
name: task.name,
|
name: task.name,
|
||||||
position: task.position,
|
position: task.position,
|
||||||
labels: [],
|
labels: [],
|
||||||
@ -163,7 +189,9 @@ const Project = () => {
|
|||||||
setListsData(newState);
|
setListsData(newState);
|
||||||
};
|
};
|
||||||
const onCardCreate = (taskGroupID: string, name: string) => {
|
const onCardCreate = (taskGroupID: string, name: string) => {
|
||||||
const taskGroupTasks = Object.values(listsData.tasks).filter((task: Task) => task.taskGroupID === taskGroupID);
|
const taskGroupTasks = Object.values(listsData.tasks).filter(
|
||||||
|
(task: Task) => task.taskGroup.taskGroupID === taskGroupID,
|
||||||
|
);
|
||||||
let position = 65535;
|
let position = 65535;
|
||||||
if (taskGroupTasks.length !== 0) {
|
if (taskGroupTasks.length !== 0) {
|
||||||
const [lastTask] = taskGroupTasks.sort((a: any, b: any) => a.position - b.position).slice(-1);
|
const [lastTask] = taskGroupTasks.sort((a: any, b: any) => a.position - b.position).slice(-1);
|
||||||
@ -201,6 +229,16 @@ const Project = () => {
|
|||||||
{...listsData}
|
{...listsData}
|
||||||
onCardDrop={onCardDrop}
|
onCardDrop={onCardDrop}
|
||||||
onListDrop={onListDrop}
|
onListDrop={onListDrop}
|
||||||
|
onCreateList={listName => {
|
||||||
|
const [lastColumn] = Object.values(listsData.columns)
|
||||||
|
.sort((a, b) => a.position - b.position)
|
||||||
|
.slice(-1);
|
||||||
|
let position = 65535;
|
||||||
|
if (lastColumn) {
|
||||||
|
position = lastColumn.position * 2 + 1;
|
||||||
|
}
|
||||||
|
createTaskGroup({ variables: { projectID: projectId, name: listName, position } });
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</Board>
|
</Board>
|
||||||
</MainContent>
|
</MainContent>
|
||||||
@ -208,7 +246,7 @@ const Project = () => {
|
|||||||
<QuickCardEditor
|
<QuickCardEditor
|
||||||
isOpen
|
isOpen
|
||||||
taskID={quickCardEditor.task ? quickCardEditor.task.taskID : ''}
|
taskID={quickCardEditor.task ? quickCardEditor.task.taskID : ''}
|
||||||
taskGroupID={quickCardEditor.task ? quickCardEditor.task.taskGroupID : ''}
|
taskGroupID={quickCardEditor.task ? quickCardEditor.task.taskGroup.taskGroupID : ''}
|
||||||
cardTitle={quickCardEditor.task ? quickCardEditor.task.name : ''}
|
cardTitle={quickCardEditor.task ? quickCardEditor.task.name : ''}
|
||||||
onCloseEditor={() => setQuickCardEditor(initialQuickCardEditorState)}
|
onCloseEditor={() => setQuickCardEditor(initialQuickCardEditorState)}
|
||||||
onEditCard={(_listId: string, cardId: string, cardName: string) => {
|
onEditCard={(_listId: string, cardId: string, cardName: string) => {
|
||||||
@ -221,6 +259,16 @@ const Project = () => {
|
|||||||
left={quickCardEditor.left}
|
left={quickCardEditor.left}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
{popupData.isOpen && (
|
||||||
|
<PopupMenu
|
||||||
|
title="List Actions"
|
||||||
|
top={popupData.top}
|
||||||
|
onClose={() => setPopupData(initialPopupState)}
|
||||||
|
left={popupData.left}
|
||||||
|
>
|
||||||
|
<ListActions taskGroupID={popupData.taskGroupID} />
|
||||||
|
</PopupMenu>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
22
web/src/citadel.d.ts
vendored
22
web/src/citadel.d.ts
vendored
@ -5,9 +5,15 @@ type ContextMenuEvent = {
|
|||||||
taskGroupID: string;
|
taskGroupID: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type InnerTaskGroup = {
|
||||||
|
taskGroupID: string;
|
||||||
|
name?: string;
|
||||||
|
position?: number;
|
||||||
|
};
|
||||||
|
|
||||||
type Task = {
|
type Task = {
|
||||||
taskID: string;
|
taskID: string;
|
||||||
taskGroupID: string;
|
taskGroup: InnerTaskGroup;
|
||||||
name: string;
|
name: string;
|
||||||
position: number;
|
position: number;
|
||||||
labels: Label[];
|
labels: Label[];
|
||||||
@ -18,7 +24,7 @@ type TaskGroup = {
|
|||||||
taskGroupID: string;
|
taskGroupID: string;
|
||||||
name: string;
|
name: string;
|
||||||
position: number;
|
position: number;
|
||||||
tasks: RemoteTask[];
|
tasks: Task[];
|
||||||
};
|
};
|
||||||
|
|
||||||
type Project = {
|
type Project = {
|
||||||
@ -62,3 +68,15 @@ type LoginProps = {
|
|||||||
setError: (field: string, eType: string, message: string) => void,
|
setError: (field: string, eType: string, message: string) => void,
|
||||||
) => void;
|
) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type ElementPosition = {
|
||||||
|
top: number;
|
||||||
|
left: number;
|
||||||
|
right: number;
|
||||||
|
bottom: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
type ElementSize = {
|
||||||
|
width: number;
|
||||||
|
height: number;
|
||||||
|
};
|
||||||
|
19
web/src/shared/components/AddList/AddList.stories.tsx
Normal file
19
web/src/shared/components/AddList/AddList.stories.tsx
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { action } from '@storybook/addon-actions';
|
||||||
|
import AddList from '.';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
component: AddList,
|
||||||
|
title: 'AddList',
|
||||||
|
parameters: {
|
||||||
|
backgrounds: [
|
||||||
|
{ name: 'gray', value: '#262c49', default: true },
|
||||||
|
{ name: 'white', value: '#ffffff' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Default = () => {
|
||||||
|
return <AddList onSave={action('on save')} />;
|
||||||
|
};
|
||||||
|
|
98
web/src/shared/components/AddList/Styles.ts
Normal file
98
web/src/shared/components/AddList/Styles.ts
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
import styled, { css } from 'styled-components';
|
||||||
|
import TextareaAutosize from 'react-autosize-textarea/lib';
|
||||||
|
|
||||||
|
export const Wrapper = styled.div<{ editorOpen: boolean }>`
|
||||||
|
display: inline-block;
|
||||||
|
background-color: hsla(0, 0%, 100%, 0.24);
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 3px;
|
||||||
|
height: auto;
|
||||||
|
min-height: 32px;
|
||||||
|
padding: 4px;
|
||||||
|
transition: background 85ms ease-in, opacity 40ms ease-in, border-color 85ms ease-in;
|
||||||
|
width: 272px;
|
||||||
|
margin: 0 4px;
|
||||||
|
margin-right: 8px;
|
||||||
|
|
||||||
|
${props =>
|
||||||
|
!props.editorOpen &&
|
||||||
|
css`
|
||||||
|
&:hover {
|
||||||
|
background-color: hsla(0, 0%, 100%, 0.32);
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
|
||||||
|
${props =>
|
||||||
|
props.editorOpen &&
|
||||||
|
css`
|
||||||
|
background-color: #ebecf0;
|
||||||
|
border-radius: 3px;
|
||||||
|
height: auto;
|
||||||
|
min-height: 32px;
|
||||||
|
padding: 4px;
|
||||||
|
transition: background 85ms ease-in, opacity 40ms ease-in, border-color 85ms ease-in;
|
||||||
|
`}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const Placeholder = styled.span`
|
||||||
|
color: #c2c6dc;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 6px 8px;
|
||||||
|
transition: color 85ms ease-in;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const AddIconWrapper = styled.div`
|
||||||
|
color: #fff;
|
||||||
|
margin-right: 6px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const ListNameEditorWrapper = styled.div`
|
||||||
|
display: flex;
|
||||||
|
`;
|
||||||
|
export const ListNameEditor = styled(TextareaAutosize)`
|
||||||
|
background: #fff;
|
||||||
|
border: none;
|
||||||
|
box-shadow: inset 0 0 0 2px #0079bf;
|
||||||
|
display: block;
|
||||||
|
margin: 0;
|
||||||
|
transition: margin 85ms ease-in, background 85ms ease-in;
|
||||||
|
width: 100%;
|
||||||
|
line-height: 20px;
|
||||||
|
padding: 8px 12px;
|
||||||
|
font-size: 14px;
|
||||||
|
outline: none;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const ListAddControls = styled.div`
|
||||||
|
height: 32px;
|
||||||
|
transition: margin 85ms ease-in, height 85ms ease-in;
|
||||||
|
overflow: hidden;
|
||||||
|
margin: 4px 0 0;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const AddListButton = styled.button`
|
||||||
|
background-color: #5aac44;
|
||||||
|
box-shadow: none;
|
||||||
|
border: none;
|
||||||
|
color: #fff;
|
||||||
|
float: left;
|
||||||
|
margin: 0 4px 0 0;
|
||||||
|
cursor: pointer;
|
||||||
|
display: inline-block;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 20px;
|
||||||
|
padding: 6px 12px;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 3px;
|
||||||
|
font-size: 14px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const CancelAdd = styled.div`
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 32px;
|
||||||
|
width: 32px;
|
||||||
|
cursor: pointer;
|
||||||
|
`;
|
105
web/src/shared/components/AddList/index.tsx
Normal file
105
web/src/shared/components/AddList/index.tsx
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
import React, { useState, useRef, useEffect } from 'react';
|
||||||
|
import { Plus, Cross } from 'shared/icons';
|
||||||
|
import useOnOutsideClick from 'shared/hooks/onOutsideClick';
|
||||||
|
|
||||||
|
import {
|
||||||
|
Wrapper,
|
||||||
|
Placeholder,
|
||||||
|
AddIconWrapper,
|
||||||
|
ListNameEditor,
|
||||||
|
ListAddControls,
|
||||||
|
CancelAdd,
|
||||||
|
AddListButton,
|
||||||
|
ListNameEditorWrapper,
|
||||||
|
} from './Styles';
|
||||||
|
|
||||||
|
type NameEditorProps = {
|
||||||
|
onSave: (listName: string) => void;
|
||||||
|
onCancel: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
const NameEditor: React.FC<NameEditorProps> = ({ onSave, onCancel }) => {
|
||||||
|
const $editorRef = useRef<HTMLTextAreaElement>(null);
|
||||||
|
const [listName, setListName] = useState('');
|
||||||
|
useEffect(() => {
|
||||||
|
if ($editorRef && $editorRef.current) {
|
||||||
|
$editorRef.current.focus();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const onKeyDown = (e: React.KeyboardEvent) => {
|
||||||
|
if (e.key === 'Enter') {
|
||||||
|
e.preventDefault();
|
||||||
|
onSave(listName);
|
||||||
|
setListName('');
|
||||||
|
if ($editorRef && $editorRef.current) {
|
||||||
|
$editorRef.current.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ListNameEditorWrapper>
|
||||||
|
<ListNameEditor
|
||||||
|
ref={$editorRef}
|
||||||
|
onKeyDown={onKeyDown}
|
||||||
|
value={listName}
|
||||||
|
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => setListName(e.currentTarget.value)}
|
||||||
|
/>
|
||||||
|
</ListNameEditorWrapper>
|
||||||
|
<ListAddControls>
|
||||||
|
<AddListButton
|
||||||
|
onClick={() => {
|
||||||
|
onSave(listName);
|
||||||
|
setListName('');
|
||||||
|
if ($editorRef && $editorRef.current) {
|
||||||
|
$editorRef.current.focus();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Save
|
||||||
|
</AddListButton>
|
||||||
|
<CancelAdd onClick={() => onCancel()}>
|
||||||
|
<Cross />
|
||||||
|
</CancelAdd>
|
||||||
|
</ListAddControls>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
type AddListProps = {
|
||||||
|
onSave: (listName: string) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
const AddList: React.FC<AddListProps> = ({ onSave }) => {
|
||||||
|
const [editorOpen, setEditorOpen] = useState(false);
|
||||||
|
const $wrapperRef = useRef<HTMLDivElement>(null);
|
||||||
|
const onOutsideClick = () => {
|
||||||
|
setEditorOpen(false);
|
||||||
|
};
|
||||||
|
useOnOutsideClick($wrapperRef, editorOpen, onOutsideClick, null);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Wrapper
|
||||||
|
ref={$wrapperRef}
|
||||||
|
editorOpen={editorOpen}
|
||||||
|
onClick={() => {
|
||||||
|
if (!editorOpen) {
|
||||||
|
setEditorOpen(true);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{editorOpen ? (
|
||||||
|
<NameEditor onCancel={() => setEditorOpen(false)} onSave={onSave} />
|
||||||
|
) : (
|
||||||
|
<Placeholder>
|
||||||
|
<AddIconWrapper>
|
||||||
|
<Plus size={12} color="#c2c6dc" />
|
||||||
|
</AddIconWrapper>
|
||||||
|
Add another list
|
||||||
|
</Placeholder>
|
||||||
|
)}
|
||||||
|
</Wrapper>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AddList;
|
@ -25,20 +25,17 @@ type Props = {
|
|||||||
const CardComposer = ({ isOpen, onCreateCard, onClose }: Props) => {
|
const CardComposer = ({ isOpen, onCreateCard, onClose }: Props) => {
|
||||||
const [cardName, setCardName] = useState('');
|
const [cardName, setCardName] = useState('');
|
||||||
const $cardEditor: any = useRef(null);
|
const $cardEditor: any = useRef(null);
|
||||||
const onClick = () => {
|
const handleCreateCard = () => {
|
||||||
onCreateCard(cardName);
|
onCreateCard(cardName);
|
||||||
|
setCardName('');
|
||||||
|
if ($cardEditor && $cardEditor.current) {
|
||||||
|
$cardEditor.current.focus();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
const onKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
const onKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
||||||
if (e.key === 'Enter') {
|
if (e.key === 'Enter') {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
onCreateCard(cardName);
|
handleCreateCard();
|
||||||
}
|
|
||||||
};
|
|
||||||
const onBlur = () => {
|
|
||||||
if (cardName === '') {
|
|
||||||
onClose();
|
|
||||||
} else {
|
|
||||||
onCreateCard(cardName);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
useOnEscapeKeyDown(isOpen, onClose);
|
useOnEscapeKeyDown(isOpen, onClose);
|
||||||
@ -63,7 +60,7 @@ const CardComposer = ({ isOpen, onCreateCard, onClose }: Props) => {
|
|||||||
</ListCard>
|
</ListCard>
|
||||||
<ComposerControls>
|
<ComposerControls>
|
||||||
<ComposerControlsSaveSection>
|
<ComposerControlsSaveSection>
|
||||||
<AddCardButton onClick={onClick}>Add Card</AddCardButton>
|
<AddCardButton onClick={handleCreateCard}>Add Card</AddCardButton>
|
||||||
<CancelIcon onClick={onClose} icon={faTimes} color="#42526e" />
|
<CancelIcon onClick={onClose} icon={faTimes} color="#42526e" />
|
||||||
</ComposerControlsSaveSection>
|
</ComposerControlsSaveSection>
|
||||||
<ComposerControlsActionsSection />
|
<ComposerControlsActionsSection />
|
||||||
|
@ -59,6 +59,7 @@ export const Default = () => {
|
|||||||
onSaveName={action('on save name')}
|
onSaveName={action('on save name')}
|
||||||
onOpenComposer={action('on open composer')}
|
onOpenComposer={action('on open composer')}
|
||||||
tasks={[]}
|
tasks={[]}
|
||||||
|
onExtraMenuOpen={action('extra menu open')}
|
||||||
>
|
>
|
||||||
<ListCards>
|
<ListCards>
|
||||||
<CardComposer
|
<CardComposer
|
||||||
@ -84,6 +85,7 @@ export const WithCardComposer = () => {
|
|||||||
onSaveName={action('on save name')}
|
onSaveName={action('on save name')}
|
||||||
onOpenComposer={action('on open composer')}
|
onOpenComposer={action('on open composer')}
|
||||||
tasks={[]}
|
tasks={[]}
|
||||||
|
onExtraMenuOpen={action('extra menu open')}
|
||||||
>
|
>
|
||||||
<ListCards>
|
<ListCards>
|
||||||
<CardComposer
|
<CardComposer
|
||||||
@ -110,6 +112,7 @@ export const WithCard = () => {
|
|||||||
onSaveName={action('on save name')}
|
onSaveName={action('on save name')}
|
||||||
onOpenComposer={action('on open composer')}
|
onOpenComposer={action('on open composer')}
|
||||||
tasks={[]}
|
tasks={[]}
|
||||||
|
onExtraMenuOpen={action('extra menu open')}
|
||||||
>
|
>
|
||||||
<ListCards>
|
<ListCards>
|
||||||
<Card
|
<Card
|
||||||
@ -148,6 +151,7 @@ export const WithCardAndComposer = () => {
|
|||||||
onSaveName={action('on save name')}
|
onSaveName={action('on save name')}
|
||||||
onOpenComposer={action('on open composer')}
|
onOpenComposer={action('on open composer')}
|
||||||
tasks={[]}
|
tasks={[]}
|
||||||
|
onExtraMenuOpen={action('extra menu open')}
|
||||||
>
|
>
|
||||||
<ListCards>
|
<ListCards>
|
||||||
<Card
|
<Card
|
||||||
|
@ -117,3 +117,12 @@ export const ListCards = styled.div`
|
|||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const ListExtraMenuButtonWrapper = styled.div`
|
||||||
|
cursor: pointer;
|
||||||
|
position: absolute;
|
||||||
|
right: 4px;
|
||||||
|
top: 4px;
|
||||||
|
z-index: 1;
|
||||||
|
padding: 6px;
|
||||||
|
`;
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import React, { useState, useRef } from 'react';
|
import React, { useState, useRef } from 'react';
|
||||||
import useOnEscapeKeyDown from 'shared/hooks/onEscapeKeyDown';
|
import useOnEscapeKeyDown from 'shared/hooks/onEscapeKeyDown';
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { Plus, Ellipsis } from 'shared/icons';
|
||||||
import { faPlus } from '@fortawesome/free-solid-svg-icons';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Container,
|
Container,
|
||||||
@ -13,6 +12,7 @@ import {
|
|||||||
AddCardButton,
|
AddCardButton,
|
||||||
AddCardButtonText,
|
AddCardButtonText,
|
||||||
ListCards,
|
ListCards,
|
||||||
|
ListExtraMenuButtonWrapper,
|
||||||
} from './Styles';
|
} from './Styles';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@ -26,20 +26,32 @@ type Props = {
|
|||||||
wrapperProps?: any;
|
wrapperProps?: any;
|
||||||
headerProps?: any;
|
headerProps?: any;
|
||||||
index?: number;
|
index?: number;
|
||||||
|
onExtraMenuOpen: (taskGroupID: string, pos: ElementPosition, size: ElementSize) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const List = React.forwardRef(
|
const List = React.forwardRef(
|
||||||
(
|
(
|
||||||
{ id, name, onSaveName, isComposerOpen, onOpenComposer, children, wrapperProps, headerProps }: Props,
|
{
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
onSaveName,
|
||||||
|
isComposerOpen,
|
||||||
|
onOpenComposer,
|
||||||
|
children,
|
||||||
|
wrapperProps,
|
||||||
|
headerProps,
|
||||||
|
onExtraMenuOpen,
|
||||||
|
}: Props,
|
||||||
$wrapperRef: any,
|
$wrapperRef: any,
|
||||||
) => {
|
) => {
|
||||||
const [listName, setListName] = useState(name);
|
const [listName, setListName] = useState(name);
|
||||||
const [isEditingTitle, setEditingTitle] = useState(false);
|
const [isEditingTitle, setEditingTitle] = useState(false);
|
||||||
const $listNameRef: any = useRef<HTMLTextAreaElement>();
|
const $listNameRef = useRef<HTMLTextAreaElement>(null);
|
||||||
|
const $extraActionsRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
const onClick = () => {
|
const onClick = () => {
|
||||||
setEditingTitle(true);
|
setEditingTitle(true);
|
||||||
if ($listNameRef) {
|
if ($listNameRef && $listNameRef.current) {
|
||||||
$listNameRef.current.select();
|
$listNameRef.current.select();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -48,7 +60,9 @@ const List = React.forwardRef(
|
|||||||
onSaveName(listName);
|
onSaveName(listName);
|
||||||
};
|
};
|
||||||
const onEscape = () => {
|
const onEscape = () => {
|
||||||
$listNameRef.current.blur();
|
if ($listNameRef && $listNameRef.current) {
|
||||||
|
$listNameRef.current.blur();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
const onChange = (event: React.FormEvent<HTMLTextAreaElement>): void => {
|
const onChange = (event: React.FormEvent<HTMLTextAreaElement>): void => {
|
||||||
setListName(event.currentTarget.value);
|
setListName(event.currentTarget.value);
|
||||||
@ -56,7 +70,28 @@ const List = React.forwardRef(
|
|||||||
const onKeyDown = (e: React.KeyboardEvent) => {
|
const onKeyDown = (e: React.KeyboardEvent) => {
|
||||||
if (e.key === 'Enter') {
|
if (e.key === 'Enter') {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
$listNameRef.current.blur();
|
if ($listNameRef && $listNameRef.current) {
|
||||||
|
$listNameRef.current.blur();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleExtraMenuOpen = () => {
|
||||||
|
if ($extraActionsRef && $extraActionsRef.current) {
|
||||||
|
const pos = $extraActionsRef.current.getBoundingClientRect();
|
||||||
|
onExtraMenuOpen(
|
||||||
|
id,
|
||||||
|
{
|
||||||
|
top: pos.top,
|
||||||
|
left: pos.left,
|
||||||
|
right: pos.right,
|
||||||
|
bottom: pos.bottom,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: pos.width,
|
||||||
|
height: pos.height,
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
useOnEscapeKeyDown(isEditingTitle, onEscape);
|
useOnEscapeKeyDown(isEditingTitle, onEscape);
|
||||||
@ -74,11 +109,14 @@ const List = React.forwardRef(
|
|||||||
spellCheck={false}
|
spellCheck={false}
|
||||||
value={listName}
|
value={listName}
|
||||||
/>
|
/>
|
||||||
|
<ListExtraMenuButtonWrapper ref={$extraActionsRef} onClick={handleExtraMenuOpen}>
|
||||||
|
<Ellipsis size={16} color="#c2c6dc" />
|
||||||
|
</ListExtraMenuButtonWrapper>
|
||||||
</Header>
|
</Header>
|
||||||
{children && children}
|
{children && children}
|
||||||
<AddCardContainer hidden={isComposerOpen}>
|
<AddCardContainer hidden={isComposerOpen}>
|
||||||
<AddCardButton onClick={() => onOpenComposer(id)}>
|
<AddCardButton onClick={() => onOpenComposer(id)}>
|
||||||
<FontAwesomeIcon icon={faPlus} size="xs" color="#42526e" />
|
<Plus size={12} color="#42526e" />
|
||||||
<AddCardButtonText>Add another card</AddCardButtonText>
|
<AddCardButtonText>Add another card</AddCardButtonText>
|
||||||
</AddCardButton>
|
</AddCardButton>
|
||||||
</AddCardContainer>
|
</AddCardContainer>
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import ListActions from '.';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
component: ListActions,
|
||||||
|
title: 'ListActions',
|
||||||
|
parameters: {
|
||||||
|
backgrounds: [
|
||||||
|
{ name: 'white', value: '#ffffff', default: true },
|
||||||
|
{ name: 'gray', value: '#f8f8f8' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Default = () => {
|
||||||
|
return <ListActions taskGroupID="1" />;
|
||||||
|
};
|
35
web/src/shared/components/ListActions/Styles.ts
Normal file
35
web/src/shared/components/ListActions/Styles.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
export const ListActionsWrapper = styled.ul`
|
||||||
|
list-style-type: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const ListActionItemWrapper = styled.li`
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
`;
|
||||||
|
export const ListActionItem = styled.span`
|
||||||
|
cursor: pointer;
|
||||||
|
display: block;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #172b4d;
|
||||||
|
font-weight: 400;
|
||||||
|
padding: 6px 12px;
|
||||||
|
position: relative;
|
||||||
|
margin: 0 -12px;
|
||||||
|
text-decoration: none;
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba(9, 30, 66, 0.04);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const ListSeparator = styled.hr`
|
||||||
|
background-color: rgba(9, 30, 66, 0.13);
|
||||||
|
border: 0;
|
||||||
|
height: 1px;
|
||||||
|
margin: 8px 0;
|
||||||
|
padding: 0;
|
||||||
|
width: 100%;
|
||||||
|
`;
|
48
web/src/shared/components/ListActions/index.tsx
Normal file
48
web/src/shared/components/ListActions/index.tsx
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { ListActionsWrapper, ListActionItemWrapper, ListActionItem, ListSeparator } from './Styles';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
taskGroupID: string;
|
||||||
|
};
|
||||||
|
const LabelManager = ({ taskGroupID }: Props) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ListActionsWrapper>
|
||||||
|
<ListActionItemWrapper>
|
||||||
|
<ListActionItem>Add card...</ListActionItem>
|
||||||
|
</ListActionItemWrapper>
|
||||||
|
<ListActionItemWrapper>
|
||||||
|
<ListActionItem>Copy List...</ListActionItem>
|
||||||
|
</ListActionItemWrapper>
|
||||||
|
<ListActionItemWrapper>
|
||||||
|
<ListActionItem>Move card...</ListActionItem>
|
||||||
|
</ListActionItemWrapper>
|
||||||
|
<ListActionItemWrapper>
|
||||||
|
<ListActionItem>Watch</ListActionItem>
|
||||||
|
</ListActionItemWrapper>
|
||||||
|
</ListActionsWrapper>
|
||||||
|
<ListSeparator />
|
||||||
|
<ListActionsWrapper>
|
||||||
|
<ListActionItemWrapper>
|
||||||
|
<ListActionItem>Sort By...</ListActionItem>
|
||||||
|
</ListActionItemWrapper>
|
||||||
|
</ListActionsWrapper>
|
||||||
|
<ListSeparator />
|
||||||
|
<ListActionsWrapper>
|
||||||
|
<ListActionItemWrapper>
|
||||||
|
<ListActionItem>Move All Cards in This List...</ListActionItem>
|
||||||
|
</ListActionItemWrapper>
|
||||||
|
<ListActionItemWrapper>
|
||||||
|
<ListActionItem>Archive All Cards in This List...</ListActionItem>
|
||||||
|
</ListActionItemWrapper>
|
||||||
|
</ListActionsWrapper>
|
||||||
|
<ListSeparator />
|
||||||
|
<ListActionsWrapper>
|
||||||
|
<ListActionItemWrapper>
|
||||||
|
<ListActionItem>Archive This List</ListActionItem>
|
||||||
|
</ListActionItemWrapper>
|
||||||
|
</ListActionsWrapper>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default LabelManager;
|
@ -7,8 +7,8 @@ export default {
|
|||||||
title: 'Lists',
|
title: 'Lists',
|
||||||
parameters: {
|
parameters: {
|
||||||
backgrounds: [
|
backgrounds: [
|
||||||
{ name: 'white', value: '#ffffff', default: true },
|
{ name: 'gray', value: '#262c49', default: true },
|
||||||
{ name: 'gray', value: '#f8f8f8' },
|
{ name: 'white', value: '#ffffff' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -33,28 +33,28 @@ const initialListsData = {
|
|||||||
tasks: {
|
tasks: {
|
||||||
'task-1': {
|
'task-1': {
|
||||||
taskID: 'task-1',
|
taskID: 'task-1',
|
||||||
taskGroupID: 'column-1',
|
taskGroup: { taskGroupID: 'column-1' },
|
||||||
name: 'Create roadmap',
|
name: 'Create roadmap',
|
||||||
position: 2,
|
position: 2,
|
||||||
labels: [],
|
labels: [],
|
||||||
},
|
},
|
||||||
'task-2': {
|
'task-2': {
|
||||||
taskID: 'task-2',
|
taskID: 'task-2',
|
||||||
taskGroupID: 'column-1',
|
taskGroup: { taskGroupID: 'column-1' },
|
||||||
position: 1,
|
position: 1,
|
||||||
name: 'Create authentication',
|
name: 'Create authentication',
|
||||||
labels: [],
|
labels: [],
|
||||||
},
|
},
|
||||||
'task-3': {
|
'task-3': {
|
||||||
taskID: 'task-3',
|
taskID: 'task-3',
|
||||||
taskGroupID: 'column-1',
|
taskGroup: { taskGroupID: 'column-1' },
|
||||||
position: 3,
|
position: 3,
|
||||||
name: 'Create login',
|
name: 'Create login',
|
||||||
labels: [],
|
labels: [],
|
||||||
},
|
},
|
||||||
'task-4': {
|
'task-4': {
|
||||||
taskID: 'task-4',
|
taskID: 'task-4',
|
||||||
taskGroupID: 'column-1',
|
taskGroup: { taskGroupID: 'column-1' },
|
||||||
position: 4,
|
position: 4,
|
||||||
name: 'Create plugins',
|
name: 'Create plugins',
|
||||||
labels: [],
|
labels: [],
|
||||||
@ -93,6 +93,29 @@ export const Default = () => {
|
|||||||
onCardDrop={onCardDrop}
|
onCardDrop={onCardDrop}
|
||||||
onListDrop={onListDrop}
|
onListDrop={onListDrop}
|
||||||
onCardCreate={action('card create')}
|
onCardCreate={action('card create')}
|
||||||
|
onCreateList={listName => {
|
||||||
|
const [lastColumn] = Object.values(listsData.columns)
|
||||||
|
.sort((a, b) => a.position - b.position)
|
||||||
|
.slice(-1);
|
||||||
|
let position = 1;
|
||||||
|
if (lastColumn) {
|
||||||
|
position = lastColumn.position + 1;
|
||||||
|
}
|
||||||
|
const taskGroupID = Math.random().toString();
|
||||||
|
const newListsData = {
|
||||||
|
...listsData,
|
||||||
|
columns: {
|
||||||
|
...listsData.columns,
|
||||||
|
[taskGroupID]: {
|
||||||
|
taskGroupID,
|
||||||
|
name: listName,
|
||||||
|
position,
|
||||||
|
tasks: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
setListsData(newListsData);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -121,28 +144,28 @@ const initialListsDataLarge = {
|
|||||||
tasks: {
|
tasks: {
|
||||||
'task-1': {
|
'task-1': {
|
||||||
taskID: 'task-1',
|
taskID: 'task-1',
|
||||||
taskGroupID: 'column-1',
|
taskGroup: { taskGroupID: 'column-1' },
|
||||||
name: 'Create roadmap',
|
name: 'Create roadmap',
|
||||||
position: 2,
|
position: 2,
|
||||||
labels: [],
|
labels: [],
|
||||||
},
|
},
|
||||||
'task-2': {
|
'task-2': {
|
||||||
taskID: 'task-2',
|
taskID: 'task-2',
|
||||||
taskGroupID: 'column-1',
|
taskGroup: { taskGroupID: 'column-1' },
|
||||||
position: 1,
|
position: 1,
|
||||||
name: 'Create authentication',
|
name: 'Create authentication',
|
||||||
labels: [],
|
labels: [],
|
||||||
},
|
},
|
||||||
'task-3': {
|
'task-3': {
|
||||||
taskID: 'task-3',
|
taskID: 'task-3',
|
||||||
taskGroupID: 'column-1',
|
taskGroup: { taskGroupID: 'column-1' },
|
||||||
position: 3,
|
position: 3,
|
||||||
name: 'Create login',
|
name: 'Create login',
|
||||||
labels: [],
|
labels: [],
|
||||||
},
|
},
|
||||||
'task-4': {
|
'task-4': {
|
||||||
taskID: 'task-4',
|
taskID: 'task-4',
|
||||||
taskGroupID: 'column-1',
|
taskGroup: { taskGroupID: 'column-1' },
|
||||||
position: 4,
|
position: 4,
|
||||||
name: 'Create plugins',
|
name: 'Create plugins',
|
||||||
labels: [],
|
labels: [],
|
||||||
@ -179,6 +202,7 @@ export const ListsWithManyList = () => {
|
|||||||
onCardCreate={action('card create')}
|
onCardCreate={action('card create')}
|
||||||
onCardDrop={onCardDrop}
|
onCardDrop={onCardDrop}
|
||||||
onListDrop={onListDrop}
|
onListDrop={onListDrop}
|
||||||
|
onCreateList={action('create list')}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -3,6 +3,7 @@ import { DragDropContext, Droppable, Draggable, DropResult } from 'react-beautif
|
|||||||
import List, { ListCards } from 'shared/components/List';
|
import List, { ListCards } from 'shared/components/List';
|
||||||
import Card from 'shared/components/Card';
|
import Card from 'shared/components/Card';
|
||||||
import CardComposer from 'shared/components/CardComposer';
|
import CardComposer from 'shared/components/CardComposer';
|
||||||
|
import AddList from 'shared/components/AddList';
|
||||||
import {
|
import {
|
||||||
isPositionChanged,
|
isPositionChanged,
|
||||||
getSortedDraggables,
|
getSortedDraggables,
|
||||||
@ -26,9 +27,10 @@ type Props = {
|
|||||||
onListDrop: any;
|
onListDrop: any;
|
||||||
onCardCreate: (taskGroupID: string, name: string) => void;
|
onCardCreate: (taskGroupID: string, name: string) => void;
|
||||||
onQuickEditorOpen: (e: ContextMenuEvent) => void;
|
onQuickEditorOpen: (e: ContextMenuEvent) => void;
|
||||||
|
onCreateList: (listName: string) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const Lists = ({ columns, tasks, onCardDrop, onListDrop, onCardCreate, onQuickEditorOpen }: Props) => {
|
const Lists = ({ columns, tasks, onCardDrop, onListDrop, onCardCreate, onQuickEditorOpen, onCreateList }: Props) => {
|
||||||
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;
|
||||||
@ -74,7 +76,7 @@ const Lists = ({ columns, tasks, onCardDrop, onListDrop, onCardCreate, onQuickEd
|
|||||||
<Container {...provided.droppableProps} ref={provided.innerRef}>
|
<Container {...provided.droppableProps} ref={provided.innerRef}>
|
||||||
{orderedColumns.map((column: TaskGroup, index: number) => {
|
{orderedColumns.map((column: TaskGroup, index: number) => {
|
||||||
const columnCards = getSortedDraggables(
|
const columnCards = getSortedDraggables(
|
||||||
Object.values(tasks).filter((t: any) => t.taskGroupID === column.taskGroupID),
|
Object.values(tasks).filter((t: Task) => t.taskGroup.taskGroupID === column.taskGroupID),
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
<Draggable draggableId={column.taskGroupID} key={column.taskGroupID} index={index}>
|
<Draggable draggableId={column.taskGroupID} key={column.taskGroupID} index={index}>
|
||||||
@ -91,6 +93,7 @@ const Lists = ({ columns, tasks, onCardDrop, onListDrop, onCardCreate, onQuickEd
|
|||||||
ref={columnDragProvided.innerRef}
|
ref={columnDragProvided.innerRef}
|
||||||
wrapperProps={columnDragProvided.draggableProps}
|
wrapperProps={columnDragProvided.draggableProps}
|
||||||
headerProps={columnDragProvided.dragHandleProps}
|
headerProps={columnDragProvided.dragHandleProps}
|
||||||
|
onExtraMenuOpen={(taskGroupID, pos, size) => console.log(taskGroupID, pos, size)}
|
||||||
>
|
>
|
||||||
<Droppable type="tasks" droppableId={column.taskGroupID}>
|
<Droppable type="tasks" droppableId={column.taskGroupID}>
|
||||||
{columnDropProvided => (
|
{columnDropProvided => (
|
||||||
@ -127,7 +130,6 @@ const Lists = ({ columns, tasks, onCardDrop, onListDrop, onCardCreate, onQuickEd
|
|||||||
setCurrentComposer('');
|
setCurrentComposer('');
|
||||||
}}
|
}}
|
||||||
onCreateCard={name => {
|
onCreateCard={name => {
|
||||||
setCurrentComposer('');
|
|
||||||
onCardCreate(column.taskGroupID, name);
|
onCardCreate(column.taskGroupID, name);
|
||||||
}}
|
}}
|
||||||
isOpen
|
isOpen
|
||||||
@ -142,6 +144,7 @@ const Lists = ({ columns, tasks, onCardDrop, onListDrop, onCardCreate, onQuickEd
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
{provided.placeholder}
|
{provided.placeholder}
|
||||||
|
<AddList onSave={onCreateList} />
|
||||||
</Container>
|
</Container>
|
||||||
)}
|
)}
|
||||||
</Droppable>
|
</Droppable>
|
||||||
|
@ -8,7 +8,7 @@ type Props = {
|
|||||||
onLabelToggle: (labelId: string) => void;
|
onLabelToggle: (labelId: string) => void;
|
||||||
onLabelEdit: (labelId: string, labelName: string, color: string) => void;
|
onLabelEdit: (labelId: string, labelName: string, color: string) => void;
|
||||||
};
|
};
|
||||||
const LabelManager = ({ labels, onLabelToggle, onLabelEdit }: Props) => {
|
const LabelManager: React.FC<Props> = ({ labels, onLabelToggle, onLabelEdit }) => {
|
||||||
const [currentLabel, setCurrentLabel] = useState('');
|
const [currentLabel, setCurrentLabel] = useState('');
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState, useRef } from 'react';
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
import LabelColors from 'shared/constants/labelColors';
|
import LabelColors from 'shared/constants/labelColors';
|
||||||
import MenuTypes from 'shared/constants/menuTypes';
|
import LabelManager from 'shared/components/PopupMenu/LabelManager';
|
||||||
|
import LabelEditor from 'shared/components/PopupMenu/LabelEditor';
|
||||||
|
import ListActions from 'shared/components/ListActions';
|
||||||
|
|
||||||
import PopupMenu from '.';
|
import PopupMenu from '.';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@ -34,16 +37,9 @@ export const LabelsPopup = () => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{isPopupOpen && (
|
{isPopupOpen && (
|
||||||
<PopupMenu
|
<PopupMenu title="Label" top={10} onClose={() => setPopupOpen(false)} left={10}>
|
||||||
title="Label"
|
<LabelManager labels={labelData} onLabelToggle={action('label toggle')} onLabelEdit={action('label edit')} />
|
||||||
menuType={MenuTypes.LABEL_MANAGER}
|
</PopupMenu>
|
||||||
top={10}
|
|
||||||
onClose={() => setPopupOpen(false)}
|
|
||||||
left={10}
|
|
||||||
onLabelEdit={action('label edit')}
|
|
||||||
onLabelToggle={action('label toggle')}
|
|
||||||
labels={labelData}
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
<button type="submit" onClick={() => setPopupOpen(true)}>
|
<button type="submit" onClick={() => setPopupOpen(true)}>
|
||||||
Open
|
Open
|
||||||
@ -57,16 +53,9 @@ export const LabelsLabelEditor = () => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{isPopupOpen && (
|
{isPopupOpen && (
|
||||||
<PopupMenu
|
<PopupMenu title="Change Label" top={10} onClose={() => setPopupOpen(false)} left={10}>
|
||||||
title="Change Label"
|
<LabelEditor label={labelData[0]} onLabelEdit={action('label edit')} />
|
||||||
menuType={MenuTypes.LABEL_EDITOR}
|
</PopupMenu>
|
||||||
top={10}
|
|
||||||
onClose={() => setPopupOpen(false)}
|
|
||||||
left={10}
|
|
||||||
onLabelEdit={action('label edit')}
|
|
||||||
onLabelToggle={action('label toggle')}
|
|
||||||
labels={labelData}
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
<button type="submit" onClick={() => setPopupOpen(true)}>
|
<button type="submit" onClick={() => setPopupOpen(true)}>
|
||||||
Open
|
Open
|
||||||
@ -74,3 +63,39 @@ export const LabelsLabelEditor = () => {
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
const initalState = { left: 0, top: 0, isOpen: false };
|
||||||
|
|
||||||
|
export const ListActionsPopup = () => {
|
||||||
|
const $buttonRef = useRef<HTMLButtonElement>(null);
|
||||||
|
const [popupData, setPopupData] = useState(initalState);
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{popupData.isOpen && (
|
||||||
|
<PopupMenu
|
||||||
|
title="List Actions"
|
||||||
|
top={popupData.top}
|
||||||
|
onClose={() => setPopupData(initalState)}
|
||||||
|
left={popupData.left}
|
||||||
|
>
|
||||||
|
<ListActions taskGroupID="1" />
|
||||||
|
</PopupMenu>
|
||||||
|
)}
|
||||||
|
<button
|
||||||
|
ref={$buttonRef}
|
||||||
|
type="submit"
|
||||||
|
onClick={() => {
|
||||||
|
if ($buttonRef && $buttonRef.current) {
|
||||||
|
const pos = $buttonRef.current.getBoundingClientRect();
|
||||||
|
setPopupData({
|
||||||
|
isOpen: true,
|
||||||
|
left: pos.left,
|
||||||
|
top: pos.top + pos.height + 10,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Open
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
@ -1,25 +1,16 @@
|
|||||||
import React, { useRef } from 'react';
|
import React, { useRef } from 'react';
|
||||||
import { Cross } from 'shared/icons';
|
import { Cross } from 'shared/icons';
|
||||||
import useOnOutsideClick from 'shared/hooks/onOutsideClick';
|
import useOnOutsideClick from 'shared/hooks/onOutsideClick';
|
||||||
import MenuTypes from 'shared/constants/menuTypes';
|
import { Container, Header, HeaderTitle, Content, CloseButton } from './Styles';
|
||||||
import LabelColors from 'shared/constants/labelColors';
|
|
||||||
import LabelManager from './LabelManager';
|
|
||||||
import LabelEditor from './LabelEditor';
|
|
||||||
import { Container, Header, HeaderTitle, Content, Label, CloseButton } from './Styles';
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
title: string;
|
title: string;
|
||||||
top: number;
|
top: number;
|
||||||
left: number;
|
left: number;
|
||||||
menuType: number;
|
|
||||||
labels?: Label[];
|
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
|
|
||||||
onLabelToggle: (labelId: string) => void;
|
|
||||||
onLabelEdit: (labelId: string, labelName: string, color: string) => void;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const PopupMenu = ({ title, menuType, labels, top, left, onClose, onLabelToggle, onLabelEdit }: Props) => {
|
const PopupMenu: React.FC<Props> = ({ title, top, left, onClose, children }) => {
|
||||||
const $containerRef = useRef();
|
const $containerRef = useRef();
|
||||||
useOnOutsideClick($containerRef, true, onClose, null);
|
useOnOutsideClick($containerRef, true, onClose, null);
|
||||||
|
|
||||||
@ -31,17 +22,7 @@ const PopupMenu = ({ title, menuType, labels, top, left, onClose, onLabelToggle,
|
|||||||
<Cross />
|
<Cross />
|
||||||
</CloseButton>
|
</CloseButton>
|
||||||
</Header>
|
</Header>
|
||||||
<Content>
|
<Content>{children}</Content>
|
||||||
{menuType === MenuTypes.LABEL_MANAGER && (
|
|
||||||
<LabelManager onLabelEdit={onLabelEdit} onLabelToggle={onLabelToggle} labels={labels} />
|
|
||||||
)}
|
|
||||||
{menuType === MenuTypes.LABEL_EDITOR && (
|
|
||||||
<LabelEditor
|
|
||||||
onLabelEdit={onLabelEdit}
|
|
||||||
label={{ active: false, color: LabelColors.GREEN, name: 'General', labelId: 'general' }}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Content>
|
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -61,6 +61,7 @@ export const Default = () => {
|
|||||||
onSaveName={action('on save name')}
|
onSaveName={action('on save name')}
|
||||||
onOpenComposer={action('on open composer')}
|
onOpenComposer={action('on open composer')}
|
||||||
tasks={[]}
|
tasks={[]}
|
||||||
|
onExtraMenuOpen={(taskGroupID, pos, size) => console.log(taskGroupID, pos, size)}
|
||||||
>
|
>
|
||||||
<ListCards>
|
<ListCards>
|
||||||
<Card
|
<Card
|
||||||
|
@ -30,13 +30,15 @@ export const Default = () => {
|
|||||||
<TaskDetails
|
<TaskDetails
|
||||||
task={{
|
task={{
|
||||||
taskID: '1',
|
taskID: '1',
|
||||||
taskGroupID: '1',
|
taskGroup: { taskGroupID: '1' },
|
||||||
name: 'Hello, world',
|
name: 'Hello, world',
|
||||||
position: 1,
|
position: 1,
|
||||||
labels: [],
|
labels: [],
|
||||||
description,
|
description,
|
||||||
}}
|
}}
|
||||||
onTaskDescriptionChange={(_task, desc) => setDescription(desc)}
|
onTaskDescriptionChange={(_task, desc) => setDescription(desc)}
|
||||||
|
onDeleteTask={action('delete task')}
|
||||||
|
onCloseModal={action('close modal')}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
|
@ -68,7 +68,7 @@ const DetailsEditor: React.FC<DetailsEditorProps> = ({
|
|||||||
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => setDescription(e.currentTarget.value)}
|
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => setDescription(e.currentTarget.value)}
|
||||||
/>
|
/>
|
||||||
<TaskDetailsControls>
|
<TaskDetailsControls>
|
||||||
<ConfirmSave>Save</ConfirmSave>
|
<ConfirmSave onClick={handleOutsideClick}>Save</ConfirmSave>
|
||||||
<CancelEdit onClick={onCancel}>
|
<CancelEdit onClick={onCancel}>
|
||||||
<Cross size={16} />
|
<Cross size={16} />
|
||||||
</CancelEdit>
|
</CancelEdit>
|
||||||
@ -80,22 +80,27 @@ const DetailsEditor: React.FC<DetailsEditorProps> = ({
|
|||||||
type TaskDetailsProps = {
|
type TaskDetailsProps = {
|
||||||
task: Task;
|
task: Task;
|
||||||
onTaskDescriptionChange: (task: Task, newDescription: string) => void;
|
onTaskDescriptionChange: (task: Task, newDescription: string) => void;
|
||||||
|
onDeleteTask: (task: Task) => void;
|
||||||
|
onCloseModal: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const TaskDetails: React.FC<TaskDetailsProps> = ({ task, onTaskDescriptionChange }) => {
|
const TaskDetails: React.FC<TaskDetailsProps> = ({ task, onTaskDescriptionChange, onDeleteTask, onCloseModal }) => {
|
||||||
const [editorOpen, setEditorOpen] = useState(false);
|
const [editorOpen, setEditorOpen] = useState(false);
|
||||||
const handleClick = () => {
|
const handleClick = () => {
|
||||||
setEditorOpen(!editorOpen);
|
setEditorOpen(!editorOpen);
|
||||||
};
|
};
|
||||||
|
const handleDeleteTask = () => {
|
||||||
|
onDeleteTask(task);
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<TaskHeader>
|
<TaskHeader>
|
||||||
<TaskMeta />
|
<TaskMeta />
|
||||||
<TaskActions>
|
<TaskActions>
|
||||||
<TaskAction>
|
<TaskAction onClick={handleDeleteTask}>
|
||||||
<Bin size={20} />
|
<Bin size={20} />
|
||||||
</TaskAction>
|
</TaskAction>
|
||||||
<TaskAction>
|
<TaskAction onClick={onCloseModal}>
|
||||||
<Cross size={20} />
|
<Cross size={20} />
|
||||||
</TaskAction>
|
</TaskAction>
|
||||||
</TaskActions>
|
</TaskActions>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
const MenuTypes = {
|
const MenuTypes = {
|
||||||
LABEL_MANAGER: 1,
|
LABEL_MANAGER: 1,
|
||||||
LABEL_EDITOR: 2,
|
LABEL_EDITOR: 2,
|
||||||
|
LIST_ACTIONS: 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default MenuTypes;
|
export default MenuTypes;
|
||||||
|
@ -13,8 +13,10 @@ export type Scalars = {
|
|||||||
UUID: string;
|
UUID: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export type RefreshToken = {
|
export type RefreshToken = {
|
||||||
__typename?: 'RefreshToken';
|
__typename?: 'RefreshToken';
|
||||||
tokenId: Scalars['ID'];
|
tokenId: Scalars['ID'];
|
||||||
userId: Scalars['UUID'];
|
userId: Scalars['UUID'];
|
||||||
expiresAt: Scalars['Time'];
|
expiresAt: Scalars['Time'];
|
||||||
@ -22,7 +24,7 @@ export type RefreshToken = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type UserAccount = {
|
export type UserAccount = {
|
||||||
__typename?: 'UserAccount';
|
__typename?: 'UserAccount';
|
||||||
userID: Scalars['ID'];
|
userID: Scalars['ID'];
|
||||||
email: Scalars['String'];
|
email: Scalars['String'];
|
||||||
createdAt: Scalars['Time'];
|
createdAt: Scalars['Time'];
|
||||||
@ -31,7 +33,7 @@ export type UserAccount = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type Organization = {
|
export type Organization = {
|
||||||
__typename?: 'Organization';
|
__typename?: 'Organization';
|
||||||
organizationID: Scalars['ID'];
|
organizationID: Scalars['ID'];
|
||||||
createdAt: Scalars['Time'];
|
createdAt: Scalars['Time'];
|
||||||
name: Scalars['String'];
|
name: Scalars['String'];
|
||||||
@ -39,7 +41,7 @@ export type Organization = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type Team = {
|
export type Team = {
|
||||||
__typename?: 'Team';
|
__typename?: 'Team';
|
||||||
teamID: Scalars['ID'];
|
teamID: Scalars['ID'];
|
||||||
createdAt: Scalars['Time'];
|
createdAt: Scalars['Time'];
|
||||||
name: Scalars['String'];
|
name: Scalars['String'];
|
||||||
@ -47,7 +49,7 @@ export type Team = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type Project = {
|
export type Project = {
|
||||||
__typename?: 'Project';
|
__typename?: 'Project';
|
||||||
projectID: Scalars['ID'];
|
projectID: Scalars['ID'];
|
||||||
teamID: Scalars['String'];
|
teamID: Scalars['String'];
|
||||||
createdAt: Scalars['Time'];
|
createdAt: Scalars['Time'];
|
||||||
@ -56,7 +58,7 @@ export type Project = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type TaskGroup = {
|
export type TaskGroup = {
|
||||||
__typename?: 'TaskGroup';
|
__typename?: 'TaskGroup';
|
||||||
taskGroupID: Scalars['ID'];
|
taskGroupID: Scalars['ID'];
|
||||||
projectID: Scalars['String'];
|
projectID: Scalars['String'];
|
||||||
createdAt: Scalars['Time'];
|
createdAt: Scalars['Time'];
|
||||||
@ -66,9 +68,9 @@ export type TaskGroup = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type Task = {
|
export type Task = {
|
||||||
__typename?: 'Task';
|
__typename?: 'Task';
|
||||||
taskID: Scalars['ID'];
|
taskID: Scalars['ID'];
|
||||||
taskGroupID: Scalars['String'];
|
taskGroup: TaskGroup;
|
||||||
createdAt: Scalars['Time'];
|
createdAt: Scalars['Time'];
|
||||||
name: Scalars['String'];
|
name: Scalars['String'];
|
||||||
position: Scalars['Float'];
|
position: Scalars['Float'];
|
||||||
@ -87,7 +89,7 @@ export type FindProject = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type Query = {
|
export type Query = {
|
||||||
__typename?: 'Query';
|
__typename?: 'Query';
|
||||||
organizations: Array<Organization>;
|
organizations: Array<Organization>;
|
||||||
users: Array<UserAccount>;
|
users: Array<UserAccount>;
|
||||||
findUser: UserAccount;
|
findUser: UserAccount;
|
||||||
@ -97,14 +99,17 @@ export type Query = {
|
|||||||
taskGroups: Array<TaskGroup>;
|
taskGroups: Array<TaskGroup>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export type QueryFindUserArgs = {
|
export type QueryFindUserArgs = {
|
||||||
input: FindUser;
|
input: FindUser;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export type QueryFindProjectArgs = {
|
export type QueryFindProjectArgs = {
|
||||||
input: FindProject;
|
input: FindProject;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export type QueryProjectsArgs = {
|
export type QueryProjectsArgs = {
|
||||||
input?: Maybe<ProjectsFilter>;
|
input?: Maybe<ProjectsFilter>;
|
||||||
};
|
};
|
||||||
@ -161,7 +166,7 @@ export type DeleteTaskInput = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type DeleteTaskPayload = {
|
export type DeleteTaskPayload = {
|
||||||
__typename?: 'DeleteTaskPayload';
|
__typename?: 'DeleteTaskPayload';
|
||||||
taskID: Scalars['String'];
|
taskID: Scalars['String'];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -171,7 +176,7 @@ export type UpdateTaskName = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type Mutation = {
|
export type Mutation = {
|
||||||
__typename?: 'Mutation';
|
__typename?: 'Mutation';
|
||||||
createRefreshToken: RefreshToken;
|
createRefreshToken: RefreshToken;
|
||||||
createUserAccount: UserAccount;
|
createUserAccount: UserAccount;
|
||||||
createOrganization: Organization;
|
createOrganization: Organization;
|
||||||
@ -185,46 +190,57 @@ export type Mutation = {
|
|||||||
deleteTask: DeleteTaskPayload;
|
deleteTask: DeleteTaskPayload;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export type MutationCreateRefreshTokenArgs = {
|
export type MutationCreateRefreshTokenArgs = {
|
||||||
input: NewRefreshToken;
|
input: NewRefreshToken;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export type MutationCreateUserAccountArgs = {
|
export type MutationCreateUserAccountArgs = {
|
||||||
input: NewUserAccount;
|
input: NewUserAccount;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export type MutationCreateOrganizationArgs = {
|
export type MutationCreateOrganizationArgs = {
|
||||||
input: NewOrganization;
|
input: NewOrganization;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export type MutationCreateTeamArgs = {
|
export type MutationCreateTeamArgs = {
|
||||||
input: NewTeam;
|
input: NewTeam;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export type MutationCreateProjectArgs = {
|
export type MutationCreateProjectArgs = {
|
||||||
input: NewProject;
|
input: NewProject;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export type MutationCreateTaskGroupArgs = {
|
export type MutationCreateTaskGroupArgs = {
|
||||||
input: NewTaskGroup;
|
input: NewTaskGroup;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export type MutationCreateTaskArgs = {
|
export type MutationCreateTaskArgs = {
|
||||||
input: NewTask;
|
input: NewTask;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export type MutationUpdateTaskLocationArgs = {
|
export type MutationUpdateTaskLocationArgs = {
|
||||||
input: NewTaskLocation;
|
input: NewTaskLocation;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export type MutationLogoutUserArgs = {
|
export type MutationLogoutUserArgs = {
|
||||||
input: LogoutUser;
|
input: LogoutUser;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export type MutationUpdateTaskNameArgs = {
|
export type MutationUpdateTaskNameArgs = {
|
||||||
input: UpdateTaskName;
|
input: UpdateTaskName;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export type MutationDeleteTaskArgs = {
|
export type MutationDeleteTaskArgs = {
|
||||||
input: DeleteTaskInput;
|
input: DeleteTaskInput;
|
||||||
};
|
};
|
||||||
@ -235,45 +251,86 @@ export type CreateTaskMutationVariables = {
|
|||||||
position: Scalars['Float'];
|
position: Scalars['Float'];
|
||||||
};
|
};
|
||||||
|
|
||||||
export type CreateTaskMutation = { __typename?: 'Mutation' } & {
|
|
||||||
createTask: { __typename?: 'Task' } & Pick<Task, 'taskID' | 'taskGroupID' | 'name' | 'position'>;
|
export type CreateTaskMutation = (
|
||||||
|
{ __typename?: 'Mutation' }
|
||||||
|
& { createTask: (
|
||||||
|
{ __typename?: 'Task' }
|
||||||
|
& Pick<Task, 'taskID' | 'name' | 'position'>
|
||||||
|
& { taskGroup: (
|
||||||
|
{ __typename?: 'TaskGroup' }
|
||||||
|
& Pick<TaskGroup, 'taskGroupID'>
|
||||||
|
) }
|
||||||
|
) }
|
||||||
|
);
|
||||||
|
|
||||||
|
export type CreateTaskGroupMutationVariables = {
|
||||||
|
projectID: Scalars['String'];
|
||||||
|
name: Scalars['String'];
|
||||||
|
position: Scalars['Float'];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type CreateTaskGroupMutation = (
|
||||||
|
{ __typename?: 'Mutation' }
|
||||||
|
& { createTaskGroup: (
|
||||||
|
{ __typename?: 'TaskGroup' }
|
||||||
|
& Pick<TaskGroup, 'taskGroupID' | 'name' | 'position'>
|
||||||
|
) }
|
||||||
|
);
|
||||||
|
|
||||||
export type DeleteTaskMutationVariables = {
|
export type DeleteTaskMutationVariables = {
|
||||||
taskID: Scalars['String'];
|
taskID: Scalars['String'];
|
||||||
};
|
};
|
||||||
|
|
||||||
export type DeleteTaskMutation = { __typename?: 'Mutation' } & {
|
|
||||||
deleteTask: { __typename?: 'DeleteTaskPayload' } & Pick<DeleteTaskPayload, 'taskID'>;
|
export type DeleteTaskMutation = (
|
||||||
};
|
{ __typename?: 'Mutation' }
|
||||||
|
& { deleteTask: (
|
||||||
|
{ __typename?: 'DeleteTaskPayload' }
|
||||||
|
& Pick<DeleteTaskPayload, 'taskID'>
|
||||||
|
) }
|
||||||
|
);
|
||||||
|
|
||||||
export type FindProjectQueryVariables = {
|
export type FindProjectQueryVariables = {
|
||||||
projectId: Scalars['String'];
|
projectId: Scalars['String'];
|
||||||
};
|
};
|
||||||
|
|
||||||
export type FindProjectQuery = { __typename?: 'Query' } & {
|
|
||||||
findProject: { __typename?: 'Project' } & Pick<Project, 'name'> & {
|
export type FindProjectQuery = (
|
||||||
taskGroups: Array<
|
{ __typename?: 'Query' }
|
||||||
{ __typename?: 'TaskGroup' } & Pick<TaskGroup, 'taskGroupID' | 'name' | 'position'> & {
|
& { findProject: (
|
||||||
tasks: Array<{ __typename?: 'Task' } & Pick<Task, 'taskID' | 'name' | 'position'>>;
|
{ __typename?: 'Project' }
|
||||||
}
|
& Pick<Project, 'name'>
|
||||||
>;
|
& { taskGroups: Array<(
|
||||||
};
|
{ __typename?: 'TaskGroup' }
|
||||||
};
|
& Pick<TaskGroup, 'taskGroupID' | 'name' | 'position'>
|
||||||
|
& { tasks: Array<(
|
||||||
|
{ __typename?: 'Task' }
|
||||||
|
& Pick<Task, 'taskID' | 'name' | 'position'>
|
||||||
|
)> }
|
||||||
|
)> }
|
||||||
|
) }
|
||||||
|
);
|
||||||
|
|
||||||
export type GetProjectsQueryVariables = {};
|
export type GetProjectsQueryVariables = {};
|
||||||
|
|
||||||
export type GetProjectsQuery = { __typename?: 'Query' } & {
|
|
||||||
organizations: Array<
|
export type GetProjectsQuery = (
|
||||||
{ __typename?: 'Organization' } & Pick<Organization, 'name'> & {
|
{ __typename?: 'Query' }
|
||||||
teams: Array<
|
& { organizations: Array<(
|
||||||
{ __typename?: 'Team' } & Pick<Team, 'name'> & {
|
{ __typename?: 'Organization' }
|
||||||
projects: Array<{ __typename?: 'Project' } & Pick<Project, 'name' | 'projectID'>>;
|
& Pick<Organization, 'name'>
|
||||||
}
|
& { teams: Array<(
|
||||||
>;
|
{ __typename?: 'Team' }
|
||||||
}
|
& Pick<Team, 'name'>
|
||||||
>;
|
& { projects: Array<(
|
||||||
};
|
{ __typename?: 'Project' }
|
||||||
|
& Pick<Project, 'name' | 'projectID'>
|
||||||
|
)> }
|
||||||
|
)> }
|
||||||
|
)> }
|
||||||
|
);
|
||||||
|
|
||||||
export type UpdateTaskLocationMutationVariables = {
|
export type UpdateTaskLocationMutationVariables = {
|
||||||
taskID: Scalars['String'];
|
taskID: Scalars['String'];
|
||||||
@ -281,29 +338,42 @@ export type UpdateTaskLocationMutationVariables = {
|
|||||||
position: Scalars['Float'];
|
position: Scalars['Float'];
|
||||||
};
|
};
|
||||||
|
|
||||||
export type UpdateTaskLocationMutation = { __typename?: 'Mutation' } & {
|
|
||||||
updateTaskLocation: { __typename?: 'Task' } & Pick<Task, 'taskID' | 'createdAt' | 'name' | 'position'>;
|
export type UpdateTaskLocationMutation = (
|
||||||
};
|
{ __typename?: 'Mutation' }
|
||||||
|
& { updateTaskLocation: (
|
||||||
|
{ __typename?: 'Task' }
|
||||||
|
& Pick<Task, 'taskID' | 'createdAt' | 'name' | 'position'>
|
||||||
|
) }
|
||||||
|
);
|
||||||
|
|
||||||
export type UpdateTaskNameMutationVariables = {
|
export type UpdateTaskNameMutationVariables = {
|
||||||
taskID: Scalars['String'];
|
taskID: Scalars['String'];
|
||||||
name: Scalars['String'];
|
name: Scalars['String'];
|
||||||
};
|
};
|
||||||
|
|
||||||
export type UpdateTaskNameMutation = { __typename?: 'Mutation' } & {
|
|
||||||
updateTaskName: { __typename?: 'Task' } & Pick<Task, 'taskID' | 'name' | 'position'>;
|
export type UpdateTaskNameMutation = (
|
||||||
};
|
{ __typename?: 'Mutation' }
|
||||||
|
& { updateTaskName: (
|
||||||
|
{ __typename?: 'Task' }
|
||||||
|
& Pick<Task, 'taskID' | 'name' | 'position'>
|
||||||
|
) }
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
export const CreateTaskDocument = gql`
|
export const CreateTaskDocument = gql`
|
||||||
mutation createTask($taskGroupID: String!, $name: String!, $position: Float!) {
|
mutation createTask($taskGroupID: String!, $name: String!, $position: Float!) {
|
||||||
createTask(input: { taskGroupID: $taskGroupID, name: $name, position: $position }) {
|
createTask(input: {taskGroupID: $taskGroupID, name: $name, position: $position}) {
|
||||||
taskID
|
taskID
|
||||||
|
taskGroup {
|
||||||
taskGroupID
|
taskGroupID
|
||||||
name
|
|
||||||
position
|
|
||||||
}
|
}
|
||||||
|
name
|
||||||
|
position
|
||||||
}
|
}
|
||||||
`;
|
}
|
||||||
|
`;
|
||||||
export type CreateTaskMutationFn = ApolloReactCommon.MutationFunction<CreateTaskMutation, CreateTaskMutationVariables>;
|
export type CreateTaskMutationFn = ApolloReactCommon.MutationFunction<CreateTaskMutation, CreateTaskMutationVariables>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -325,24 +395,55 @@ export type CreateTaskMutationFn = ApolloReactCommon.MutationFunction<CreateTask
|
|||||||
* },
|
* },
|
||||||
* });
|
* });
|
||||||
*/
|
*/
|
||||||
export function useCreateTaskMutation(
|
export function useCreateTaskMutation(baseOptions?: ApolloReactHooks.MutationHookOptions<CreateTaskMutation, CreateTaskMutationVariables>) {
|
||||||
baseOptions?: ApolloReactHooks.MutationHookOptions<CreateTaskMutation, CreateTaskMutationVariables>,
|
return ApolloReactHooks.useMutation<CreateTaskMutation, CreateTaskMutationVariables>(CreateTaskDocument, baseOptions);
|
||||||
) {
|
}
|
||||||
return ApolloReactHooks.useMutation<CreateTaskMutation, CreateTaskMutationVariables>(CreateTaskDocument, baseOptions);
|
|
||||||
}
|
|
||||||
export type CreateTaskMutationHookResult = ReturnType<typeof useCreateTaskMutation>;
|
export type CreateTaskMutationHookResult = ReturnType<typeof useCreateTaskMutation>;
|
||||||
export type CreateTaskMutationResult = ApolloReactCommon.MutationResult<CreateTaskMutation>;
|
export type CreateTaskMutationResult = ApolloReactCommon.MutationResult<CreateTaskMutation>;
|
||||||
export type CreateTaskMutationOptions = ApolloReactCommon.BaseMutationOptions<
|
export type CreateTaskMutationOptions = ApolloReactCommon.BaseMutationOptions<CreateTaskMutation, CreateTaskMutationVariables>;
|
||||||
CreateTaskMutation,
|
export const CreateTaskGroupDocument = gql`
|
||||||
CreateTaskMutationVariables
|
mutation createTaskGroup($projectID: String!, $name: String!, $position: Float!) {
|
||||||
>;
|
createTaskGroup(input: {projectID: $projectID, name: $name, position: $position}) {
|
||||||
export const DeleteTaskDocument = gql`
|
taskGroupID
|
||||||
mutation deleteTask($taskID: String!) {
|
name
|
||||||
deleteTask(input: { taskID: $taskID }) {
|
position
|
||||||
taskID
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
`;
|
}
|
||||||
|
`;
|
||||||
|
export type CreateTaskGroupMutationFn = ApolloReactCommon.MutationFunction<CreateTaskGroupMutation, CreateTaskGroupMutationVariables>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __useCreateTaskGroupMutation__
|
||||||
|
*
|
||||||
|
* To run a mutation, you first call `useCreateTaskGroupMutation` within a React component and pass it any options that fit your needs.
|
||||||
|
* When your component renders, `useCreateTaskGroupMutation` returns a tuple that includes:
|
||||||
|
* - A mutate function that you can call at any time to execute the mutation
|
||||||
|
* - An object with fields that represent the current status of the mutation's execution
|
||||||
|
*
|
||||||
|
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const [createTaskGroupMutation, { data, loading, error }] = useCreateTaskGroupMutation({
|
||||||
|
* variables: {
|
||||||
|
* projectID: // value for 'projectID'
|
||||||
|
* name: // value for 'name'
|
||||||
|
* position: // value for 'position'
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
export function useCreateTaskGroupMutation(baseOptions?: ApolloReactHooks.MutationHookOptions<CreateTaskGroupMutation, CreateTaskGroupMutationVariables>) {
|
||||||
|
return ApolloReactHooks.useMutation<CreateTaskGroupMutation, CreateTaskGroupMutationVariables>(CreateTaskGroupDocument, baseOptions);
|
||||||
|
}
|
||||||
|
export type CreateTaskGroupMutationHookResult = ReturnType<typeof useCreateTaskGroupMutation>;
|
||||||
|
export type CreateTaskGroupMutationResult = ApolloReactCommon.MutationResult<CreateTaskGroupMutation>;
|
||||||
|
export type CreateTaskGroupMutationOptions = ApolloReactCommon.BaseMutationOptions<CreateTaskGroupMutation, CreateTaskGroupMutationVariables>;
|
||||||
|
export const DeleteTaskDocument = gql`
|
||||||
|
mutation deleteTask($taskID: String!) {
|
||||||
|
deleteTask(input: {taskID: $taskID}) {
|
||||||
|
taskID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
export type DeleteTaskMutationFn = ApolloReactCommon.MutationFunction<DeleteTaskMutation, DeleteTaskMutationVariables>;
|
export type DeleteTaskMutationFn = ApolloReactCommon.MutationFunction<DeleteTaskMutation, DeleteTaskMutationVariables>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -362,34 +463,29 @@ export type DeleteTaskMutationFn = ApolloReactCommon.MutationFunction<DeleteTask
|
|||||||
* },
|
* },
|
||||||
* });
|
* });
|
||||||
*/
|
*/
|
||||||
export function useDeleteTaskMutation(
|
export function useDeleteTaskMutation(baseOptions?: ApolloReactHooks.MutationHookOptions<DeleteTaskMutation, DeleteTaskMutationVariables>) {
|
||||||
baseOptions?: ApolloReactHooks.MutationHookOptions<DeleteTaskMutation, DeleteTaskMutationVariables>,
|
return ApolloReactHooks.useMutation<DeleteTaskMutation, DeleteTaskMutationVariables>(DeleteTaskDocument, baseOptions);
|
||||||
) {
|
}
|
||||||
return ApolloReactHooks.useMutation<DeleteTaskMutation, DeleteTaskMutationVariables>(DeleteTaskDocument, baseOptions);
|
|
||||||
}
|
|
||||||
export type DeleteTaskMutationHookResult = ReturnType<typeof useDeleteTaskMutation>;
|
export type DeleteTaskMutationHookResult = ReturnType<typeof useDeleteTaskMutation>;
|
||||||
export type DeleteTaskMutationResult = ApolloReactCommon.MutationResult<DeleteTaskMutation>;
|
export type DeleteTaskMutationResult = ApolloReactCommon.MutationResult<DeleteTaskMutation>;
|
||||||
export type DeleteTaskMutationOptions = ApolloReactCommon.BaseMutationOptions<
|
export type DeleteTaskMutationOptions = ApolloReactCommon.BaseMutationOptions<DeleteTaskMutation, DeleteTaskMutationVariables>;
|
||||||
DeleteTaskMutation,
|
|
||||||
DeleteTaskMutationVariables
|
|
||||||
>;
|
|
||||||
export const FindProjectDocument = gql`
|
export const FindProjectDocument = gql`
|
||||||
query findProject($projectId: String!) {
|
query findProject($projectId: String!) {
|
||||||
findProject(input: { projectId: $projectId }) {
|
findProject(input: {projectId: $projectId}) {
|
||||||
|
name
|
||||||
|
taskGroups {
|
||||||
|
taskGroupID
|
||||||
name
|
name
|
||||||
taskGroups {
|
position
|
||||||
taskGroupID
|
tasks {
|
||||||
|
taskID
|
||||||
name
|
name
|
||||||
position
|
position
|
||||||
tasks {
|
|
||||||
taskID
|
|
||||||
name
|
|
||||||
position
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __useFindProjectQuery__
|
* __useFindProjectQuery__
|
||||||
@ -407,33 +503,29 @@ export const FindProjectDocument = gql`
|
|||||||
* },
|
* },
|
||||||
* });
|
* });
|
||||||
*/
|
*/
|
||||||
export function useFindProjectQuery(
|
export function useFindProjectQuery(baseOptions?: ApolloReactHooks.QueryHookOptions<FindProjectQuery, FindProjectQueryVariables>) {
|
||||||
baseOptions?: ApolloReactHooks.QueryHookOptions<FindProjectQuery, FindProjectQueryVariables>,
|
return ApolloReactHooks.useQuery<FindProjectQuery, FindProjectQueryVariables>(FindProjectDocument, baseOptions);
|
||||||
) {
|
}
|
||||||
return ApolloReactHooks.useQuery<FindProjectQuery, FindProjectQueryVariables>(FindProjectDocument, baseOptions);
|
export function useFindProjectLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions<FindProjectQuery, FindProjectQueryVariables>) {
|
||||||
}
|
return ApolloReactHooks.useLazyQuery<FindProjectQuery, FindProjectQueryVariables>(FindProjectDocument, baseOptions);
|
||||||
export function useFindProjectLazyQuery(
|
}
|
||||||
baseOptions?: ApolloReactHooks.LazyQueryHookOptions<FindProjectQuery, FindProjectQueryVariables>,
|
|
||||||
) {
|
|
||||||
return ApolloReactHooks.useLazyQuery<FindProjectQuery, FindProjectQueryVariables>(FindProjectDocument, baseOptions);
|
|
||||||
}
|
|
||||||
export type FindProjectQueryHookResult = ReturnType<typeof useFindProjectQuery>;
|
export type FindProjectQueryHookResult = ReturnType<typeof useFindProjectQuery>;
|
||||||
export type FindProjectLazyQueryHookResult = ReturnType<typeof useFindProjectLazyQuery>;
|
export type FindProjectLazyQueryHookResult = ReturnType<typeof useFindProjectLazyQuery>;
|
||||||
export type FindProjectQueryResult = ApolloReactCommon.QueryResult<FindProjectQuery, FindProjectQueryVariables>;
|
export type FindProjectQueryResult = ApolloReactCommon.QueryResult<FindProjectQuery, FindProjectQueryVariables>;
|
||||||
export const GetProjectsDocument = gql`
|
export const GetProjectsDocument = gql`
|
||||||
query getProjects {
|
query getProjects {
|
||||||
organizations {
|
organizations {
|
||||||
|
name
|
||||||
|
teams {
|
||||||
name
|
name
|
||||||
teams {
|
projects {
|
||||||
name
|
name
|
||||||
projects {
|
projectID
|
||||||
name
|
|
||||||
projectID
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __useGetProjectsQuery__
|
* __useGetProjectsQuery__
|
||||||
@ -450,33 +542,26 @@ export const GetProjectsDocument = gql`
|
|||||||
* },
|
* },
|
||||||
* });
|
* });
|
||||||
*/
|
*/
|
||||||
export function useGetProjectsQuery(
|
export function useGetProjectsQuery(baseOptions?: ApolloReactHooks.QueryHookOptions<GetProjectsQuery, GetProjectsQueryVariables>) {
|
||||||
baseOptions?: ApolloReactHooks.QueryHookOptions<GetProjectsQuery, GetProjectsQueryVariables>,
|
return ApolloReactHooks.useQuery<GetProjectsQuery, GetProjectsQueryVariables>(GetProjectsDocument, baseOptions);
|
||||||
) {
|
}
|
||||||
return ApolloReactHooks.useQuery<GetProjectsQuery, GetProjectsQueryVariables>(GetProjectsDocument, baseOptions);
|
export function useGetProjectsLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions<GetProjectsQuery, GetProjectsQueryVariables>) {
|
||||||
}
|
return ApolloReactHooks.useLazyQuery<GetProjectsQuery, GetProjectsQueryVariables>(GetProjectsDocument, baseOptions);
|
||||||
export function useGetProjectsLazyQuery(
|
}
|
||||||
baseOptions?: ApolloReactHooks.LazyQueryHookOptions<GetProjectsQuery, GetProjectsQueryVariables>,
|
|
||||||
) {
|
|
||||||
return ApolloReactHooks.useLazyQuery<GetProjectsQuery, GetProjectsQueryVariables>(GetProjectsDocument, baseOptions);
|
|
||||||
}
|
|
||||||
export type GetProjectsQueryHookResult = ReturnType<typeof useGetProjectsQuery>;
|
export type GetProjectsQueryHookResult = ReturnType<typeof useGetProjectsQuery>;
|
||||||
export type GetProjectsLazyQueryHookResult = ReturnType<typeof useGetProjectsLazyQuery>;
|
export type GetProjectsLazyQueryHookResult = ReturnType<typeof useGetProjectsLazyQuery>;
|
||||||
export type GetProjectsQueryResult = ApolloReactCommon.QueryResult<GetProjectsQuery, GetProjectsQueryVariables>;
|
export type GetProjectsQueryResult = ApolloReactCommon.QueryResult<GetProjectsQuery, GetProjectsQueryVariables>;
|
||||||
export const UpdateTaskLocationDocument = gql`
|
export const UpdateTaskLocationDocument = gql`
|
||||||
mutation updateTaskLocation($taskID: String!, $taskGroupID: String!, $position: Float!) {
|
mutation updateTaskLocation($taskID: String!, $taskGroupID: String!, $position: Float!) {
|
||||||
updateTaskLocation(input: { taskID: $taskID, taskGroupID: $taskGroupID, position: $position }) {
|
updateTaskLocation(input: {taskID: $taskID, taskGroupID: $taskGroupID, position: $position}) {
|
||||||
taskID
|
taskID
|
||||||
createdAt
|
createdAt
|
||||||
name
|
name
|
||||||
position
|
position
|
||||||
}
|
|
||||||
}
|
}
|
||||||
`;
|
}
|
||||||
export type UpdateTaskLocationMutationFn = ApolloReactCommon.MutationFunction<
|
`;
|
||||||
UpdateTaskLocationMutation,
|
export type UpdateTaskLocationMutationFn = ApolloReactCommon.MutationFunction<UpdateTaskLocationMutation, UpdateTaskLocationMutationVariables>;
|
||||||
UpdateTaskLocationMutationVariables
|
|
||||||
>;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __useUpdateTaskLocationMutation__
|
* __useUpdateTaskLocationMutation__
|
||||||
@ -497,33 +582,22 @@ export type UpdateTaskLocationMutationFn = ApolloReactCommon.MutationFunction<
|
|||||||
* },
|
* },
|
||||||
* });
|
* });
|
||||||
*/
|
*/
|
||||||
export function useUpdateTaskLocationMutation(
|
export function useUpdateTaskLocationMutation(baseOptions?: ApolloReactHooks.MutationHookOptions<UpdateTaskLocationMutation, UpdateTaskLocationMutationVariables>) {
|
||||||
baseOptions?: ApolloReactHooks.MutationHookOptions<UpdateTaskLocationMutation, UpdateTaskLocationMutationVariables>,
|
return ApolloReactHooks.useMutation<UpdateTaskLocationMutation, UpdateTaskLocationMutationVariables>(UpdateTaskLocationDocument, baseOptions);
|
||||||
) {
|
}
|
||||||
return ApolloReactHooks.useMutation<UpdateTaskLocationMutation, UpdateTaskLocationMutationVariables>(
|
|
||||||
UpdateTaskLocationDocument,
|
|
||||||
baseOptions,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
export type UpdateTaskLocationMutationHookResult = ReturnType<typeof useUpdateTaskLocationMutation>;
|
export type UpdateTaskLocationMutationHookResult = ReturnType<typeof useUpdateTaskLocationMutation>;
|
||||||
export type UpdateTaskLocationMutationResult = ApolloReactCommon.MutationResult<UpdateTaskLocationMutation>;
|
export type UpdateTaskLocationMutationResult = ApolloReactCommon.MutationResult<UpdateTaskLocationMutation>;
|
||||||
export type UpdateTaskLocationMutationOptions = ApolloReactCommon.BaseMutationOptions<
|
export type UpdateTaskLocationMutationOptions = ApolloReactCommon.BaseMutationOptions<UpdateTaskLocationMutation, UpdateTaskLocationMutationVariables>;
|
||||||
UpdateTaskLocationMutation,
|
|
||||||
UpdateTaskLocationMutationVariables
|
|
||||||
>;
|
|
||||||
export const UpdateTaskNameDocument = gql`
|
export const UpdateTaskNameDocument = gql`
|
||||||
mutation updateTaskName($taskID: String!, $name: String!) {
|
mutation updateTaskName($taskID: String!, $name: String!) {
|
||||||
updateTaskName(input: { taskID: $taskID, name: $name }) {
|
updateTaskName(input: {taskID: $taskID, name: $name}) {
|
||||||
taskID
|
taskID
|
||||||
name
|
name
|
||||||
position
|
position
|
||||||
}
|
|
||||||
}
|
}
|
||||||
`;
|
}
|
||||||
export type UpdateTaskNameMutationFn = ApolloReactCommon.MutationFunction<
|
`;
|
||||||
UpdateTaskNameMutation,
|
export type UpdateTaskNameMutationFn = ApolloReactCommon.MutationFunction<UpdateTaskNameMutation, UpdateTaskNameMutationVariables>;
|
||||||
UpdateTaskNameMutationVariables
|
|
||||||
>;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __useUpdateTaskNameMutation__
|
* __useUpdateTaskNameMutation__
|
||||||
@ -543,17 +617,9 @@ export type UpdateTaskNameMutationFn = ApolloReactCommon.MutationFunction<
|
|||||||
* },
|
* },
|
||||||
* });
|
* });
|
||||||
*/
|
*/
|
||||||
export function useUpdateTaskNameMutation(
|
export function useUpdateTaskNameMutation(baseOptions?: ApolloReactHooks.MutationHookOptions<UpdateTaskNameMutation, UpdateTaskNameMutationVariables>) {
|
||||||
baseOptions?: ApolloReactHooks.MutationHookOptions<UpdateTaskNameMutation, UpdateTaskNameMutationVariables>,
|
return ApolloReactHooks.useMutation<UpdateTaskNameMutation, UpdateTaskNameMutationVariables>(UpdateTaskNameDocument, baseOptions);
|
||||||
) {
|
}
|
||||||
return ApolloReactHooks.useMutation<UpdateTaskNameMutation, UpdateTaskNameMutationVariables>(
|
|
||||||
UpdateTaskNameDocument,
|
|
||||||
baseOptions,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
export type UpdateTaskNameMutationHookResult = ReturnType<typeof useUpdateTaskNameMutation>;
|
export type UpdateTaskNameMutationHookResult = ReturnType<typeof useUpdateTaskNameMutation>;
|
||||||
export type UpdateTaskNameMutationResult = ApolloReactCommon.MutationResult<UpdateTaskNameMutation>;
|
export type UpdateTaskNameMutationResult = ApolloReactCommon.MutationResult<UpdateTaskNameMutation>;
|
||||||
export type UpdateTaskNameMutationOptions = ApolloReactCommon.BaseMutationOptions<
|
export type UpdateTaskNameMutationOptions = ApolloReactCommon.BaseMutationOptions<UpdateTaskNameMutation, UpdateTaskNameMutationVariables>;
|
||||||
UpdateTaskNameMutation,
|
|
||||||
UpdateTaskNameMutationVariables
|
|
||||||
>;
|
|
@ -1,7 +1,9 @@
|
|||||||
mutation createTask($taskGroupID: String!, $name: String!, $position: Float!) {
|
mutation createTask($taskGroupID: String!, $name: String!, $position: Float!) {
|
||||||
createTask(input: { taskGroupID: $taskGroupID, name: $name, position: $position }) {
|
createTask(input: { taskGroupID: $taskGroupID, name: $name, position: $position }) {
|
||||||
taskID
|
taskID
|
||||||
taskGroupID
|
taskGroup {
|
||||||
|
taskGroupID
|
||||||
|
}
|
||||||
name
|
name
|
||||||
position
|
position
|
||||||
}
|
}
|
||||||
|
9
web/src/shared/graphql/createTaskGroup.graphqls
Normal file
9
web/src/shared/graphql/createTaskGroup.graphqls
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
mutation createTaskGroup( $projectID: String!, $name: String!, $position: Float! ) {
|
||||||
|
createTaskGroup(
|
||||||
|
input: { projectID: $projectID, name: $name, position: $position }
|
||||||
|
) {
|
||||||
|
taskGroupID
|
||||||
|
name
|
||||||
|
position
|
||||||
|
}
|
||||||
|
}
|
21
web/src/shared/icons/Ellipsis.tsx
Normal file
21
web/src/shared/icons/Ellipsis.tsx
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
size: number | string;
|
||||||
|
color: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const Ellipsis = ({ size, color }: Props) => {
|
||||||
|
return (
|
||||||
|
<svg fill={color} xmlns="http://www.w3.org/2000/svg" width={size} height={size} viewBox="0 0 512 512">
|
||||||
|
<path d="M328 256c0 39.8-32.2 72-72 72s-72-32.2-72-72 32.2-72 72-72 72 32.2 72 72zm104-72c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72zm-352 0c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72z" />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
Ellipsis.defaultProps = {
|
||||||
|
size: 16,
|
||||||
|
color: '#000',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Ellipsis;
|
21
web/src/shared/icons/Plus.tsx
Normal file
21
web/src/shared/icons/Plus.tsx
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
size: number | string;
|
||||||
|
color: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const Plus = ({ size, color }: Props) => {
|
||||||
|
return (
|
||||||
|
<svg fill={color} xmlns="http://www.w3.org/2000/svg" width={size} height={size} viewBox="0 0 16 16">
|
||||||
|
<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" />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
Plus.defaultProps = {
|
||||||
|
size: 16,
|
||||||
|
color: '#000',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Plus;
|
@ -1,4 +1,5 @@
|
|||||||
import Cross from './Cross';
|
import Cross from './Cross';
|
||||||
|
import Plus from './Plus';
|
||||||
import Bell from './Bell';
|
import Bell from './Bell';
|
||||||
import Bin from './Bin';
|
import Bin from './Bin';
|
||||||
import Pencil from './Pencil';
|
import Pencil from './Pencil';
|
||||||
@ -11,5 +12,6 @@ import Home from './Home';
|
|||||||
import Stack from './Stack';
|
import Stack from './Stack';
|
||||||
import Question from './Question';
|
import Question from './Question';
|
||||||
import Exit from './Exit';
|
import Exit from './Exit';
|
||||||
|
import Ellipsis from './Ellipsis';
|
||||||
|
|
||||||
export { Cross, Bell, Bin, Exit, Pencil, Stack, Question, Home, Citadel, Checkmark, User, Users, Lock };
|
export { Cross, Plus, Bell, Ellipsis, Bin, Exit, Pencil, Stack, Question, Home, Citadel, Checkmark, User, Users, Lock };
|
||||||
|
Loading…
Reference in New Issue
Block a user