Edit relations and sub-tasks
This commit is contained in:
parent
be9daf1e42
commit
6efe282b81
@ -42,12 +42,19 @@ export default class KanbnBoardPanel {
|
||||
vscode.window.showErrorMessage(error instanceof Error ? error.message : error);
|
||||
return;
|
||||
}
|
||||
let tasks: any[];
|
||||
try {
|
||||
tasks = (await KanbnBoardPanel.currentPanel._kanbn.loadAllTrackedTasks(index)).map(
|
||||
task => KanbnBoardPanel.currentPanel!._kanbn.hydrateTask(index, task)
|
||||
);
|
||||
} catch (error) {
|
||||
vscode.window.showErrorMessage(error instanceof Error ? error.message : error);
|
||||
return;
|
||||
}
|
||||
KanbnBoardPanel.currentPanel._panel.webview.postMessage({
|
||||
type: 'index',
|
||||
index,
|
||||
tasks: (await KanbnBoardPanel.currentPanel._kanbn.loadAllTrackedTasks(index)).map(
|
||||
task => KanbnBoardPanel.currentPanel!._kanbn.hydrateTask(index, task)
|
||||
),
|
||||
tasks,
|
||||
startedColumns: index.options.startedColumns ?? [],
|
||||
completedColumns: index.options.completedColumns ?? [],
|
||||
dateFormat: KanbnBoardPanel.currentPanel._kanbn.getDateFormat(index)
|
||||
|
@ -1,5 +1,6 @@
|
||||
import * as path from 'path';
|
||||
import * as vscode from 'vscode';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
export default class KanbnTaskPanel {
|
||||
private static readonly viewType = 'react';
|
||||
@ -28,14 +29,21 @@ export default class KanbnTaskPanel {
|
||||
vscode.window.showErrorMessage(error instanceof Error ? error.message : error);
|
||||
return;
|
||||
}
|
||||
let task: any = null;
|
||||
let tasks: any[];
|
||||
try {
|
||||
tasks = (await kanbn.loadAllTrackedTasks(index)).map(
|
||||
task => ({
|
||||
uuid: uuidv4(),
|
||||
...kanbn.hydrateTask(index, task)
|
||||
})
|
||||
);
|
||||
} catch (error) {
|
||||
vscode.window.showErrorMessage(error instanceof Error ? error.message : error);
|
||||
return;
|
||||
}
|
||||
let task = null;
|
||||
if (taskId) {
|
||||
try {
|
||||
task = await kanbn.hydrateTask(index, await kanbn.getTask(taskId));
|
||||
} catch (error) {
|
||||
vscode.window.showErrorMessage(error instanceof Error ? error.message : error);
|
||||
return;
|
||||
}
|
||||
task = tasks.find(t => t.id === taskId) ?? null;
|
||||
}
|
||||
|
||||
// If no columnName is specified, use the first column
|
||||
@ -60,7 +68,7 @@ export default class KanbnTaskPanel {
|
||||
index,
|
||||
task,
|
||||
columnName: taskPanel._columnName,
|
||||
tasks: await kanbn.loadAllTrackedTasks(index),
|
||||
tasks,
|
||||
dateFormat: kanbn.getDateFormat(index)
|
||||
});
|
||||
}
|
||||
|
41
package-lock.json
generated
41
package-lock.json
generated
@ -3355,6 +3355,12 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/dateformat/-/dateformat-3.0.1.tgz",
|
||||
"integrity": "sha512-KlPPdikagvL6ELjWsljbyDIPzNCeliYkqRpI+zea99vBBbCIA5JNshZAwQKTON139c87y9qvTFVgkFd14rtS4g=="
|
||||
},
|
||||
"@types/git-user-name": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/git-user-name/-/git-user-name-2.0.0.tgz",
|
||||
"integrity": "sha512-bZhPykkyyPdHW2wMc30aLIWntMIMO49jWKGQipPg3RQNGq2LdAnW7OCinHew+M8EpZ5qHNyFynIiou+UyxOfww==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/jest": {
|
||||
"version": "23.3.14",
|
||||
"resolved": "https://registry.npmjs.org/@types/jest/-/jest-23.3.14.tgz",
|
||||
@ -3417,6 +3423,12 @@
|
||||
"integrity": "sha512-42zEJkBpNfMEAvWR5WlwtTH22oDzcMjFsL9gDGExwF8X8WvAiw7Vwop7hPw03QT8TKfec83LwbHj6SvpqM4ELQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/uuid": {
|
||||
"version": "8.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.0.tgz",
|
||||
"integrity": "sha512-eQ9qFW/fhfGJF8WKHGEHZEyVWfZxrT+6CLIJGBcZPfxUh/+BnEj+UCGYMlr9qZuX/2AltsvwrGqp0LhEW8D0zQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@webassemblyjs/ast": {
|
||||
"version": "1.7.11",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.7.11.tgz",
|
||||
@ -17478,6 +17490,14 @@
|
||||
"tough-cookie": "~2.5.0",
|
||||
"tunnel-agent": "^0.6.0",
|
||||
"uuid": "^3.3.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"uuid": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"request-promise-core": {
|
||||
@ -18859,6 +18879,12 @@
|
||||
"requires": {
|
||||
"websocket-driver": ">=0.5.1"
|
||||
}
|
||||
},
|
||||
"uuid": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -20076,10 +20102,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"uuid": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
|
||||
"dev": true
|
||||
"version": "8.3.2",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
|
||||
},
|
||||
"validate-npm-package-license": {
|
||||
"version": "3.0.4",
|
||||
@ -20913,6 +20938,14 @@
|
||||
"requires": {
|
||||
"ansi-colors": "^3.0.0",
|
||||
"uuid": "^3.3.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"uuid": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"webpack-manifest-plugin": {
|
||||
|
@ -39,6 +39,7 @@
|
||||
"react-beautiful-dnd": "12.2.0",
|
||||
"react-dom": "^16.3.2",
|
||||
"terser": "3.14.1",
|
||||
"uuid": "^8.3.2",
|
||||
"vscode": "^1.1.37",
|
||||
"vscode-codicons": "^0.0.15"
|
||||
},
|
||||
@ -51,11 +52,13 @@
|
||||
"eject": "react-scripts eject"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/git-user-name": "^2.0.0",
|
||||
"@types/jest": "^23.3.14",
|
||||
"@types/lodash": "^4.14.168",
|
||||
"@types/node": "^10.17.56",
|
||||
"@types/react": "^16.14.5",
|
||||
"@types/react-dom": "^16.9.12",
|
||||
"@types/uuid": "^8.3.0",
|
||||
"react-scripts": "^2.1.8",
|
||||
"rewire": "^4.0.1",
|
||||
"typescript": "^4.0.2"
|
||||
|
@ -18,13 +18,14 @@ function App() {
|
||||
const [completedColumns, setCompletedColumns] = useState([]);
|
||||
const [dateFormat, setDateFormat] = useState('');
|
||||
const [task, setTask] = useState({});
|
||||
const [tasks, setTasks] = useState({});
|
||||
const [columnName, setColumnName] = useState('');
|
||||
const [columnNames, setColumnNames] = useState([] as string[]);
|
||||
|
||||
window.addEventListener('message', event => {
|
||||
const tasks = Object.fromEntries(event.data.tasks.map(task => [task.id, task]));
|
||||
switch (event.data.type) {
|
||||
case 'index':
|
||||
const tasks = Object.fromEntries(event.data.tasks.map(task => [task.id, task]));
|
||||
setName(event.data.index.name);
|
||||
setDescription(event.data.index.description);
|
||||
setColumns(Object.fromEntries(
|
||||
@ -39,6 +40,7 @@ function App() {
|
||||
|
||||
case 'task':
|
||||
setTask(event.data.task);
|
||||
setTasks(tasks);
|
||||
setColumnName(event.data.columnName);
|
||||
setColumnNames(Object.keys(event.data.index.columns));
|
||||
break;
|
||||
@ -69,6 +71,7 @@ function App() {
|
||||
type === 'task' &&
|
||||
<TaskEditor
|
||||
task={task as KanbnTask|null}
|
||||
tasks={tasks}
|
||||
columnName={columnName}
|
||||
columnNames={columnNames}
|
||||
dateFormat={dateFormat}
|
||||
|
@ -64,12 +64,7 @@ const Board = ({ columns, startedColumns, completedColumns, dateFormat, vscode }
|
||||
}) => {
|
||||
const [, setColumns] = useState(columns);
|
||||
return (
|
||||
<div
|
||||
className="kanbn-board"
|
||||
style={{
|
||||
display: "flex"
|
||||
}}
|
||||
>
|
||||
<div className="kanbn-board">
|
||||
<DragDropContext
|
||||
onDragEnd={result => onDragEnd(result, columns, setColumns, vscode)}
|
||||
>
|
||||
@ -80,9 +75,6 @@ const Board = ({ columns, startedColumns, completedColumns, dateFormat, vscode }
|
||||
'kanbn-column',
|
||||
`kanbn-column-${paramCase(columnName)}`
|
||||
].join(' ')}
|
||||
style={{
|
||||
flex: 1
|
||||
}}
|
||||
key={columnName}
|
||||
>
|
||||
<h2 className="kanbn-column-name">
|
||||
|
1
src/KanbnTask.d.ts
vendored
1
src/KanbnTask.d.ts
vendored
@ -1,4 +1,5 @@
|
||||
declare type KanbnTask = {
|
||||
uuid?: string,
|
||||
id: string,
|
||||
name: string,
|
||||
description: string,
|
||||
|
@ -1,12 +1,13 @@
|
||||
import React from 'react';
|
||||
import { Formik } from 'formik';
|
||||
import { Formik, Form, Field, ErrorMessage, FieldArray } from 'formik';
|
||||
import formatDate from 'dateformat';
|
||||
import VSCodeApi from './VSCodeApi';
|
||||
import { paramCase } from 'param-case';
|
||||
import * as gitUsername from 'git-user-name';
|
||||
import gitUsername from 'git-user-name';
|
||||
|
||||
const TaskEditor = ({ task, columnName, columnNames, dateFormat, vscode }: {
|
||||
const TaskEditor = ({ task, tasks, columnName, columnNames, dateFormat, vscode }: {
|
||||
task: KanbnTask|null,
|
||||
tasks: Record<string, KanbnTask>,
|
||||
columnName: string,
|
||||
columnNames: string[],
|
||||
dateFormat: string,
|
||||
@ -32,6 +33,7 @@ const TaskEditor = ({ task, columnName, columnNames, dateFormat, vscode }: {
|
||||
<h1 className="kanbn-task-editor-title">{editing ? 'Update task' : 'Create new task'}</h1>
|
||||
<Formik
|
||||
initialValues={{
|
||||
uuid: task ? task.uuid : '',
|
||||
id: task ? task.id : '',
|
||||
name: task ? task.name : '',
|
||||
description: task ? task.description : '',
|
||||
@ -39,22 +41,23 @@ const TaskEditor = ({ task, columnName, columnNames, dateFormat, vscode }: {
|
||||
progress: task ? task.progress : 0,
|
||||
metadata: {
|
||||
due: (task && 'due' in task.metadata) ? formatDate(new Date(task.metadata.due!), 'yyyy-mm-dd') : '',
|
||||
assigned: (task && 'assigned' in task.metadata) ? task.metadata.assigned : gitUsername(),
|
||||
assigned: (task && 'assigned' in task.metadata) ? task.metadata.assigned : (gitUsername() || ''),
|
||||
tags: (task && 'tags' in task.metadata) ? task.metadata.tags : []
|
||||
},
|
||||
relations: [],
|
||||
subTasks: [],
|
||||
comments: []
|
||||
relations: task ? task.relations : [],
|
||||
subTasks: task ? task.subTasks : [],
|
||||
comments: task ? task.comments : []
|
||||
}}
|
||||
validate={values => {
|
||||
const errors: { name?: string } = {};
|
||||
// if (!values.email) {
|
||||
// errors.email = 'Required';
|
||||
// } else if (
|
||||
// !/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(values.email)
|
||||
// ) {
|
||||
// errors.email = 'Invalid email address';
|
||||
// }
|
||||
if (!values.name) {
|
||||
errors.name = 'Task name is required.';
|
||||
}
|
||||
|
||||
// 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.';
|
||||
}
|
||||
return errors;
|
||||
}}
|
||||
onSubmit={(values, { setSubmitting }) => {
|
||||
@ -73,125 +76,246 @@ const TaskEditor = ({ task, columnName, columnNames, dateFormat, vscode }: {
|
||||
>
|
||||
{({
|
||||
values,
|
||||
errors,
|
||||
touched,
|
||||
handleChange,
|
||||
handleBlur,
|
||||
handleSubmit,
|
||||
isSubmitting
|
||||
}) => (
|
||||
<form onSubmit={handleSubmit}>
|
||||
<div
|
||||
style={{
|
||||
display: "flex"
|
||||
}}
|
||||
>
|
||||
<Form>
|
||||
<div style={{ display: "flex" }}>
|
||||
<div className="kanbn-task-editor-column-left">
|
||||
<div className="kanbn-task-field kanbn-task-field-name">
|
||||
<label className="kanbn-task-field-label">
|
||||
<div className="kanbn-task-editor-field kanbn-task-editor-field-name">
|
||||
<label className="kanbn-task-editor-field-label">
|
||||
<p>Name</p>
|
||||
<input
|
||||
className="kanbn-task-field-input"
|
||||
placeholder="Name"
|
||||
<Field
|
||||
className="kanbn-task-editor-field-input"
|
||||
name="name"
|
||||
value={values.name}
|
||||
placeholder="Name"
|
||||
onChange={e => {
|
||||
handleChange(e);
|
||||
handleUpdateName(e, values);
|
||||
}}
|
||||
onBlur={handleBlur}
|
||||
></input>
|
||||
/>
|
||||
</label>
|
||||
{errors.name && touched.name && errors.name}
|
||||
<span className="kanbn-task-id">{values.id}</span>
|
||||
<div className="kanbn-task-editor-id">{values.id}</div>
|
||||
<ErrorMessage
|
||||
className="kanbn-task-editor-field-errors"
|
||||
component="div"
|
||||
name="name"
|
||||
/>
|
||||
</div>
|
||||
<div className="kanbn-task-field kanbn-task-field-description">
|
||||
<label className="kanbn-task-field-label">
|
||||
<div className="kanbn-task-editor-field kanbn-task-editor-field-description">
|
||||
<label className="kanbn-task-editor-field-label">
|
||||
<p>Description</p>
|
||||
<textarea
|
||||
className="kanbn-task-field-textarea"
|
||||
placeholder="Description"
|
||||
<Field
|
||||
className="kanbn-task-editor-field-textarea"
|
||||
as="textarea"
|
||||
name="description"
|
||||
value={values.description}
|
||||
onChange={handleChange}
|
||||
onBlur={handleBlur}
|
||||
></textarea>
|
||||
/>
|
||||
</label>
|
||||
<ErrorMessage
|
||||
className="kanbn-task-editor-field-errors"
|
||||
component="div"
|
||||
name="description"
|
||||
/>
|
||||
</div>
|
||||
<div className="kanbn-task-editor-field kanbn-task-editor-field-relations">
|
||||
<h2 className="kanbn-task-editor-title">Relations</h2>
|
||||
<FieldArray name="relations">
|
||||
{({ insert, remove, push }) => (
|
||||
<div>
|
||||
{values.relations.length > 0 && values.relations.map((relation, index) => (
|
||||
<div className="kanbn-task-editor-row kanbn-task-editor-row-relation" key={index}>
|
||||
<div className="kanbn-task-editor-column kanbn-task-editor-field-relation-type">
|
||||
<Field
|
||||
className="kanbn-task-editor-field-input"
|
||||
name={`relations.${index}.type`}
|
||||
placeholder="Relation type"
|
||||
/>
|
||||
<ErrorMessage
|
||||
className="kanbn-task-editor-field-errors"
|
||||
component="div"
|
||||
name={`relations.${index}.type`}
|
||||
/>
|
||||
</div>
|
||||
<div className="kanbn-task-editor-column kanbn-task-editor-field-relation-task">
|
||||
<Field
|
||||
className="kanbn-task-editor-field-select"
|
||||
as="select"
|
||||
name={`relations.${index}.task`}
|
||||
>
|
||||
{Object.keys(tasks).map(t => <option value={t}>{t}</option>)}
|
||||
</Field>
|
||||
<ErrorMessage
|
||||
className="kanbn-task-editor-field-errors"
|
||||
component="div"
|
||||
name={`relations.${index}.task`}
|
||||
/>
|
||||
</div>
|
||||
<div className="kanbn-task-editor-column kanbn-task-editor-column-buttons">
|
||||
<button
|
||||
type="button"
|
||||
className="kanbn-task-editor-button kanbn-task-editor-button-delete"
|
||||
onClick={() => remove(index)}
|
||||
>
|
||||
<i className="codicon codicon-trash"></i>Delete
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
<div className="kanbn-task-editor-buttons">
|
||||
<button
|
||||
type="button"
|
||||
className="kanbn-task-editor-button kanbn-task-editor-button-add"
|
||||
onClick={() => push({ type: '', task: '' })}
|
||||
>
|
||||
<i className="codicon codicon-plus"></i>Add relation
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</FieldArray>
|
||||
</div>
|
||||
<div className="kanbn-task-editor-field kanbn-task-editor-field-subtasks">
|
||||
<h2 className="kanbn-task-editor-title">Sub-tasks</h2>
|
||||
<FieldArray name="subTasks">
|
||||
{({ insert, remove, push }) => (
|
||||
<div>
|
||||
{values.subTasks.length > 0 && values.subTasks.map((subTask, index) => (
|
||||
<div className="kanbn-task-editor-row kanbn-task-editor-row-subtask" key={index}>
|
||||
<div className="kanbn-task-editor-column kanbn-task-editor-field-subtask-completed">
|
||||
<Field
|
||||
className="kanbn-task-editor-field-checkbox"
|
||||
type="checkbox"
|
||||
name={`subTasks.${index}.completed`}
|
||||
/>
|
||||
<ErrorMessage
|
||||
className="kanbn-task-editor-field-errors"
|
||||
component="div"
|
||||
name={`subTasks.${index}.completed`}
|
||||
/>
|
||||
</div>
|
||||
<div className="kanbn-task-editor-column kanbn-task-editor-field-subtask-text">
|
||||
<Field
|
||||
className="kanbn-task-editor-field-input"
|
||||
name={`subTasks.${index}.text`}
|
||||
placeholder="Sub-task text"
|
||||
/>
|
||||
<ErrorMessage
|
||||
className="kanbn-task-editor-field-errors"
|
||||
component="div"
|
||||
name={`subTasks.${index}.text`}
|
||||
/>
|
||||
</div>
|
||||
<div className="kanbn-task-editor-column kanbn-task-editor-column-buttons">
|
||||
<button
|
||||
type="button"
|
||||
className="kanbn-task-editor-button kanbn-task-editor-button-delete"
|
||||
onClick={() => remove(index)}
|
||||
>
|
||||
<i className="codicon codicon-trash"></i>Delete
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
<div className="kanbn-task-editor-buttons">
|
||||
<button
|
||||
type="button"
|
||||
className="kanbn-task-editor-button kanbn-task-editor-button-add"
|
||||
onClick={() => push({ completed: false, text: '' })}
|
||||
>
|
||||
<i className="codicon codicon-plus"></i>Add sub-task
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</FieldArray>
|
||||
</div>
|
||||
</div>
|
||||
<div className="kanbn-task-editor-column-right">
|
||||
<div>
|
||||
<div className="kanbn-task-editor-buttons">
|
||||
{editing && <button
|
||||
type="button"
|
||||
className="kanbn-task-editor-button kanbn-task-editor-button-delete"
|
||||
title="Delete"
|
||||
>
|
||||
<i className="codicon codicon-trash"></i>Delete
|
||||
</button>}
|
||||
<button
|
||||
type="submit"
|
||||
className="kanbn-task-editor-button kanbn-task-editor-button-submit"
|
||||
title="Save"
|
||||
disabled={isSubmitting}
|
||||
>Save</button>
|
||||
<button
|
||||
type="button"
|
||||
className="kanbn-task-editor-button kanbn-task-editor-button-delete"
|
||||
title="Delete"
|
||||
>Delete</button>
|
||||
>
|
||||
<i className="codicon codicon-save"></i>Save
|
||||
</button>
|
||||
</div>
|
||||
<div className="kanbn-task-field kanbn-task-field-column">
|
||||
<label className="kanbn-task-field-label">
|
||||
<div className="kanbn-task-editor-field kanbn-task-editor-field-column">
|
||||
<label className="kanbn-task-editor-field-label">
|
||||
<p>Column</p>
|
||||
<select
|
||||
className="kanbn-task-field-select"
|
||||
<Field
|
||||
className="kanbn-task-editor-field-select"
|
||||
as="select"
|
||||
name="column"
|
||||
value={values.column}
|
||||
onChange={handleChange}
|
||||
onBlur={handleBlur}
|
||||
>
|
||||
{columnNames.map(c => <option value={c}>{c}</option>)}
|
||||
</select>
|
||||
</Field>
|
||||
</label>
|
||||
<ErrorMessage
|
||||
className="kanbn-task-editor-field-errors"
|
||||
component="div"
|
||||
name="column"
|
||||
/>
|
||||
</div>
|
||||
<div className="kanbn-task-field kanbn-task-field-assigned">
|
||||
<label className="kanbn-task-field-label">
|
||||
<div className="kanbn-task-editor-field kanbn-task-editor-field-assigned">
|
||||
<label className="kanbn-task-editor-field-label">
|
||||
<p>Assigned to</p>
|
||||
<input
|
||||
className="kanbn-task-field-input"
|
||||
placeholder="Assigned to"
|
||||
<Field
|
||||
className="kanbn-task-editor-field-input"
|
||||
name="metadata.assigned"
|
||||
value={values.metadata.assigned}
|
||||
onChange={handleChange}
|
||||
onBlur={handleBlur}
|
||||
></input>
|
||||
placeholder="Assigned to"
|
||||
/>
|
||||
</label>
|
||||
<ErrorMessage
|
||||
className="kanbn-task-editor-field-errors"
|
||||
component="div"
|
||||
name="metadata.assigned"
|
||||
/>
|
||||
</div>
|
||||
<div className="kanbn-task-field kanbn-task-field-due">
|
||||
<label className="kanbn-task-field-label">
|
||||
<div className="kanbn-task-editor-field kanbn-task-editor-field-due">
|
||||
<label className="kanbn-task-editor-field-label">
|
||||
<p>Due date</p>
|
||||
<input
|
||||
<Field
|
||||
className="kanbn-task-editor-field-input"
|
||||
type="date"
|
||||
className="kanbn-task-field-input"
|
||||
name="metadata.due"
|
||||
value={values.metadata.due}
|
||||
onChange={handleChange}
|
||||
onBlur={handleBlur}
|
||||
></input>
|
||||
/>
|
||||
</label>
|
||||
<ErrorMessage
|
||||
className="kanbn-task-editor-field-errors"
|
||||
component="div"
|
||||
name="metadata.due"
|
||||
/>
|
||||
</div>
|
||||
<div className="kanbn-task-field kanbn-task-field-progress">
|
||||
<label className="kanbn-task-field-label">
|
||||
<div className="kanbn-task-editor-field kanbn-task-editor-field-progress">
|
||||
<label className="kanbn-task-editor-field-label">
|
||||
<p>Progress</p>
|
||||
<input
|
||||
<Field
|
||||
className="kanbn-task-editor-field-input"
|
||||
type="number"
|
||||
className="kanbn-task-field-input"
|
||||
name="progress"
|
||||
value={values.progress}
|
||||
onChange={handleChange}
|
||||
onBlur={handleBlur}
|
||||
min="0"
|
||||
max="1"
|
||||
step="0.05"
|
||||
></input>
|
||||
/>
|
||||
</label>
|
||||
<ErrorMessage
|
||||
className="kanbn-task-editor-field-errors"
|
||||
component="div"
|
||||
name="progress"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
)}
|
||||
</Formik>
|
||||
</div>
|
||||
|
110
src/index.css
110
src/index.css
@ -13,6 +13,14 @@ body {
|
||||
border-bottom: 1px var(--vscode-activityBar-inactiveForeground) solid;
|
||||
}
|
||||
|
||||
.kanbn-board {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.kanbn-column {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.kanbn-column-name {
|
||||
color: var(--vscode-editor-foreground);
|
||||
font-size: 0.8em;
|
||||
@ -152,7 +160,7 @@ body {
|
||||
position: relative;
|
||||
top: 1px;
|
||||
font-size: 0.9em !important;
|
||||
margin-right: 4px;
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
|
||||
.kanbn-task-tag {
|
||||
@ -167,7 +175,7 @@ body {
|
||||
}
|
||||
|
||||
.kanbn-task-tag-Nothing {
|
||||
background-color: #aab;
|
||||
background-color: #6bf;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
@ -212,6 +220,12 @@ body {
|
||||
border-bottom: 1px var(--vscode-activityBar-inactiveForeground) solid;
|
||||
}
|
||||
|
||||
.kanbn-task-editor-field .kanbn-task-editor-title {
|
||||
font-size: 1.1em;
|
||||
padding: 0.5em 0;
|
||||
border-bottom: 1px var(--vscode-activityBar-inactiveForeground) solid;
|
||||
}
|
||||
|
||||
.kanbn-task-editor-column-left {
|
||||
width: 70%;
|
||||
padding-right: 1em;
|
||||
@ -221,11 +235,11 @@ body {
|
||||
width: 30%;
|
||||
}
|
||||
|
||||
.kanbn-task-field {
|
||||
.kanbn-task-editor-field {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.kanbn-task-field-label p {
|
||||
.kanbn-task-editor-field-label p {
|
||||
color: var(--vscode-editor-foreground);
|
||||
font-size: 0.8em;
|
||||
letter-spacing: 0.1em;
|
||||
@ -234,13 +248,14 @@ body {
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
body.vscode-dark .kanbn-task-field-input[type="date"]::-webkit-calendar-picker-indicator {
|
||||
body.vscode-dark .kanbn-task-editor-field-input[type="date"]::-webkit-calendar-picker-indicator {
|
||||
filter: invert(1);
|
||||
}
|
||||
|
||||
.kanbn-task-field-input,
|
||||
.kanbn-task-field-select,
|
||||
.kanbn-task-field-textarea {
|
||||
.kanbn-task-editor-field-input,
|
||||
.kanbn-task-editor-field-select,
|
||||
.kanbn-task-editor-field-checkbox,
|
||||
.kanbn-task-editor-field-textarea {
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
width: 100%;
|
||||
@ -251,16 +266,89 @@ body.vscode-dark .kanbn-task-field-input[type="date"]::-webkit-calendar-picker-i
|
||||
border: 1px transparent solid;
|
||||
}
|
||||
|
||||
.kanbn-task-field-textarea {
|
||||
.kanbn-task-editor-field-select {
|
||||
padding-bottom: 7px;
|
||||
}
|
||||
|
||||
.kanbn-task-editor-field-textarea {
|
||||
min-height: 200px;
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
.kanbn-task-field-input:hover, .kanbn-task-field-input:focus {
|
||||
.kanbn-task-editor-field-input:hover, .kanbn-task-editor-field-input:focus {
|
||||
border-color: var(--vscode-input-border);
|
||||
}
|
||||
|
||||
.kanbn-task-id {
|
||||
.kanbn-task-editor-buttons {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.kanbn-task-editor-button {
|
||||
outline: none;
|
||||
border: none;
|
||||
background-color: var(--vscode-button-background);
|
||||
color: var(--vscode-button-foreground);
|
||||
padding: 9px 1em;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.kanbn-task-editor-button .codicon {
|
||||
font-size: 11px !important;
|
||||
margin-right: 0.5em;
|
||||
position: relative;
|
||||
top: 1px;
|
||||
}
|
||||
|
||||
.kanbn-task-editor-button:hover, .kanbn-task-editor-button:focus {
|
||||
background-color: var(--vscode-button-hoverBackground);
|
||||
}
|
||||
|
||||
.kanbn-task-editor-button-delete:hover, .kanbn-task-editor-button-delete:focus {
|
||||
background-color: #f42;
|
||||
}
|
||||
|
||||
.kanbn-task-editor-field-errors {
|
||||
font-weight: bold;
|
||||
color: #f42;
|
||||
}
|
||||
|
||||
.kanbn-task-editor-id {
|
||||
margin-bottom: 8px;
|
||||
font-style: italic;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.kanbn-task-editor-row {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.kanbn-task-editor-column {
|
||||
flex: 1;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.kanbn-task-editor-column:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.kanbn-task-editor-field-relation-task {
|
||||
flex: 2;
|
||||
}
|
||||
|
||||
.kanbn-task-editor-field-subtask-completed {
|
||||
flex: 0 0 2em;
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
.kanbn-task-editor-column-buttons {
|
||||
white-space: nowrap;
|
||||
flex: 0;
|
||||
}
|
||||
|
||||
.kanbn-task-editor-field .kanbn-task-editor-buttons {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.kanbn-task-editor-column-buttons .kanbn-task-editor-button {
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user