diff --git a/ext-src/KanbnTaskPanel.ts b/ext-src/KanbnTaskPanel.ts index da364b8..8026216 100644 --- a/ext-src/KanbnTaskPanel.ts +++ b/ext-src/KanbnTaskPanel.ts @@ -137,21 +137,29 @@ export default class KanbnTaskPanel { // Create a task case 'kanbn.create': - // TODO create task - vscode.window.showInformationMessage('create task'); + // TODO convert dates + // await this._kanbn.createTask(message.taskData, message.taskData.column); + vscode.window.showInformationMessage(`Created task ${message.taskData.name}.`); return; // Update a task case 'kanbn.update': - // TODO update task - vscode.window.showInformationMessage('update task'); + // TODO convert dates + // await this._kanbn.updateTask(message.taskData.id, message.taskData, message.taskData.column); + vscode.window.showInformationMessage(`Updated task ${message.taskData.name}.`); return; // Delete a task case 'kanbn.delete': - // TODO delete task - // TODO add yes/no confirmation buttons to information message, then delete task and close task panel - vscode.window.showInformationMessage('delete task'); + vscode.window.showInformationMessage(`Delete task ${message.taskData.name}?`, 'Yes', 'No').then( + async value => { + if (value === 'Yes') { + // await this._kanbn.deleteTask(message.taskId, true); + vscode.window.showInformationMessage(`Deleted task ${message.taskData.name}.`); + // TODO close panel, will need to generate uuid for each panel + } + } + ); return; } }, null, this._disposables); diff --git a/src/App.tsx b/src/App.tsx index b79afc3..f14deee 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,4 +1,3 @@ -import Header from './Header'; import Board from './Board'; import TaskEditor from './TaskEditor'; import React, { useState } from "react"; @@ -53,19 +52,15 @@ function App() { { type === 'index' && - -
- - + } { type === 'task' && diff --git a/src/Board.tsx b/src/Board.tsx index aefca01..90b5c08 100644 --- a/src/Board.tsx +++ b/src/Board.tsx @@ -55,7 +55,9 @@ const onDragEnd = (result, columns, setColumns, vscode: VSCodeApi) => { }); }; -const Board = ({ columns, startedColumns, completedColumns, dateFormat, vscode }: { +const Board = ({ name, description, columns, startedColumns, completedColumns, dateFormat, vscode }: { + name: string, + description: string, columns: Record, startedColumns: string[], completedColumns: string[], @@ -63,74 +65,102 @@ const Board = ({ columns, startedColumns, completedColumns, dateFormat, vscode } vscode: VSCodeApi }) => { const [, setColumns] = useState(columns); + + const filterTasks = () => { + console.log(); + }; + return ( -
- onDragEnd(result, columns, setColumns, vscode)} - > - {Object.entries(columns).map(([columnName, column]) => { - return ( -
+
+

+

{name}

+
+ + -

-
- - {(provided, snapshot) => { - return ( -
i).join(' ')} - > - {column.map((task, position) => )} - {provided.placeholder} -
- ); - }} -
+ + +
+ +

+ {description} +

+
+
+ onDragEnd(result, columns, setColumns, vscode)} + > + {Object.entries(columns).map(([columnName, column]) => { + return ( +
+

+ { + startedColumns.indexOf(columnName) > -1 && + + } + { + completedColumns.indexOf(columnName) > -1 && + + } + {columnName} + {column.length || ''} + +

+
+ + {(provided, snapshot) => { + return ( +
i).join(' ')} + > + {column.map((task, position) => )} + {provided.placeholder} +
+ ); + }} +
+
-
- ); - })} - -
+ ); + })} +
+
+ ); }; diff --git a/src/Header.tsx b/src/Header.tsx deleted file mode 100644 index 82fe5e8..0000000 --- a/src/Header.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import React from "react"; - -const Header = ({ name, description }: { name: string, description: string }) => { - return ( -
-

{name}

-

- {description} -

-
- ); -} - -export default Header; diff --git a/src/TaskEditor.tsx b/src/TaskEditor.tsx index e848ef9..e9d2204 100644 --- a/src/TaskEditor.tsx +++ b/src/TaskEditor.tsx @@ -46,11 +46,27 @@ const TaskEditor = ({ task, tasks, columnName, columnNames, dateFormat, vscode } }); }; + // Called when the form is submitted + const handleSubmit = values => { + if (editing) { + vscode.postMessage({ + command: 'kanbn.update', + taskData: values + }); + } else { + vscode.postMessage({ + command: 'kanbn.create', + taskData: values + }); + } + }; + // Called when the delete task button is clicked - const handleRemoveTask = () => { + const handleRemoveTask = values => { vscode.postMessage({ command: 'kanbn.delete', - taskId: task!.id + taskId: task!.id, + taskData: values }); }; @@ -94,7 +110,8 @@ const TaskEditor = ({ task, tasks, columnName, columnNames, dateFormat, vscode } subTasks: task ? task.subTasks : [], comments: task ? task.comments : [] }} - validate={(values: KanbnTaskValidationInput): KanbnTaskValidationOutput => { + validate={(values: KanbnTaskValidationInput): KanbnTaskValidationOutput|{} => { + let hasErrors = false; const errors: KanbnTaskValidationOutput = { name: '', metadata: { @@ -107,17 +124,20 @@ const TaskEditor = ({ task, tasks, columnName, columnNames, dateFormat, vscode } // Task name cannot be empty if (!values.name) { errors.name = 'Task name is required.'; + hasErrors = true; } // Check if the id is already in use if (values.id in tasks && tasks[values.id].uuid !== values.uuid) { errors.name = 'There is already a task with the same name or id.'; + hasErrors = true; } // Tag names cannot be empty for (let i = 0; i < values.metadata.tags.length; i++) { if (!values.metadata.tags[i]) { errors.metadata.tags[i] = 'Tag cannot be empty.'; + hasErrors = true; } } @@ -127,6 +147,7 @@ const TaskEditor = ({ task, tasks, columnName, columnNames, dateFormat, vscode } errors.subTasks[i] = { text: 'Sub-task text cannot be empty.' }; + hasErrors = true; } } @@ -136,22 +157,14 @@ const TaskEditor = ({ task, tasks, columnName, columnNames, dateFormat, vscode } errors.comments[i] = { text: 'Comment text cannot be empty.' }; + hasErrors = true; } } - return errors; + return hasErrors ? errors : {}; }} onSubmit={(values, { setSubmitting }) => { - if (editing) { - vscode.postMessage({ - command: 'kanbn.update' - }); - } else { - vscode.postMessage({ - command: 'kanbn.create' - }); - } - console.log(values); + handleSubmit(values); setSubmitting(false); }} > @@ -385,7 +398,9 @@ const TaskEditor = ({ task, tasks, columnName, columnNames, dateFormat, vscode } type="button" className="kanbn-task-editor-button kanbn-task-editor-button-delete" title="Delete task" - onClick={handleRemoveTask} + onClick={() => { + handleRemoveTask(values); + }} > Delete } diff --git a/src/index.css b/src/index.css index ea5cc96..7cc75b9 100644 --- a/src/index.css +++ b/src/index.css @@ -12,6 +12,51 @@ body { margin-top: 0; padding-bottom: 0.5em; border-bottom: 1px var(--vscode-activityBar-inactiveForeground) solid; + display: flex; +} + +.kanbn-header-name p { + display: inline-block; + flex: 1; + margin: 0; + padding: 4px 0; +} + +.kanbn-filter { + flex: 1; + text-align: right; +} + +.kanbn-filter-input { + box-sizing: border-box; + width: 80%; + padding: 8px; + background-color: var(--vscode-input-background); + color: var(--vscode-input-foreground); + border: 1px transparent solid; +} + +.kanbn-filter-input:hover, .kanbn-filter-input:focus { + border-color: var(--vscode-input-border); +} + +.kanbn-filter-button { + outline: none; + border: none; + background-color: var(--vscode-button-background); + color: var(--vscode-button-foreground); + padding: 9px 1em; + margin-left: 8px; +} + +.kanbn-filter-button .codicon { + font-size: 11px !important; + position: relative; + top: 1px; +} + +.kanbn-filter-button:hover, .kanbn-filter-button:focus { + background-color: var(--vscode-button-hoverBackground); } .kanbn-board {