Compare commits
10 Commits
0aa5776af3
...
2ffd43908e
Author | SHA1 | Date | |
---|---|---|---|
2ffd43908e | |||
5cb3b39764 | |||
c0930f4780 | |||
|
f85619450f | ||
|
5fbfb0f740 | ||
|
abe249c20a | ||
|
c1f12c3ec0 | ||
|
58cf1eb003 | ||
|
0a7918732e | ||
|
026fbf95cd |
28
.kanbn/board.css
Normal file
28
.kanbn/board.css
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
.kanbn-column-wip .kanbn-column-task-list {
|
||||||
|
border-color: #6929c4;
|
||||||
|
}
|
||||||
|
.kanbn-column-next .kanbn-column-task-list {
|
||||||
|
border-color: #1192e8;
|
||||||
|
}
|
||||||
|
.kanbn-column-wait .kanbn-column-task-list {
|
||||||
|
border-color: #005d5d;
|
||||||
|
}
|
||||||
|
.kanbn-column-later .kanbn-column-task-list {
|
||||||
|
border-color: #9f1853;
|
||||||
|
}
|
||||||
|
.kanbn-column-maybe .kanbn-column-task-list {
|
||||||
|
border-color: #fa4d56;
|
||||||
|
}
|
||||||
|
.kanbn-column-friday .kanbn-column-task-list {
|
||||||
|
border-color: #570408;
|
||||||
|
}
|
||||||
|
.kanbn-column-done .kanbn-column-task-list {
|
||||||
|
border-color: #198038;
|
||||||
|
}
|
||||||
|
.kanbn-task-data-workload {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.kanbn-task-data-relation {
|
||||||
|
display: block;
|
||||||
|
color: #198038;
|
||||||
|
}
|
30
.kanbn/index.md
Normal file
30
.kanbn/index.md
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
---
|
||||||
|
startedColumns:
|
||||||
|
- 'In Progress'
|
||||||
|
completedColumns:
|
||||||
|
- Done
|
||||||
|
---
|
||||||
|
|
||||||
|
# VSCode-Kanbn
|
||||||
|
|
||||||
|
## Backlog
|
||||||
|
|
||||||
|
- [review-save-options](tasks/review-save-options.md)
|
||||||
|
- [can-this-run-in-the-browser](tasks/can-this-run-in-the-browser.md)
|
||||||
|
- [how-do-i-use-local-javascript-project-reference](tasks/how-do-i-use-local-javascript-project-reference.md)
|
||||||
|
|
||||||
|
## Todo
|
||||||
|
|
||||||
|
- [shrink-app-size](tasks/shrink-app-size.md)
|
||||||
|
|
||||||
|
## In Progress
|
||||||
|
|
||||||
|
## Done
|
||||||
|
|
||||||
|
- [add-link-to-raw-in-panel-view](tasks/add-link-to-raw-in-panel-view.md)
|
||||||
|
- [add-raw-button-in-create-new-task](tasks/add-raw-button-in-create-new-task.md)
|
||||||
|
- [make-tags-linkable](tasks/make-tags-linkable.md)
|
||||||
|
- [show-relations-on-the-item-card](tasks/show-relations-on-the-item-card.md)
|
||||||
|
- [understand-how-relations-work](tasks/understand-how-relations-work.md)
|
||||||
|
- [review-adding-more-on-item-card](tasks/review-adding-more-on-item-card.md)
|
||||||
|
- [remove-relations-in-form](tasks/remove-relations-in-form.md)
|
14
.kanbn/tasks/add-link-to-raw-in-panel-view.md
Normal file
14
.kanbn/tasks/add-link-to-raw-in-panel-view.md
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
created: 2023-05-25T04:00:46.616Z
|
||||||
|
updated: 2023-05-25T04:50:52.235Z
|
||||||
|
assigned: ""
|
||||||
|
progress: 0
|
||||||
|
tags: []
|
||||||
|
started: 2023-05-25T04:41:03.902Z
|
||||||
|
completed: 2023-05-25T04:50:44.587Z
|
||||||
|
---
|
||||||
|
|
||||||
|
# Add link to raw in panel view
|
||||||
|
|
||||||
|
- Double click event
|
||||||
|
- Extra button
|
11
.kanbn/tasks/add-raw-button-in-create-new-task.md
Normal file
11
.kanbn/tasks/add-raw-button-in-create-new-task.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
created: 2023-05-25T04:00:30.417Z
|
||||||
|
updated: 2023-05-25T04:50:46.136Z
|
||||||
|
assigned: ""
|
||||||
|
progress: 0
|
||||||
|
tags: []
|
||||||
|
started: 2023-05-22T00:00:00.000Z
|
||||||
|
completed: 2023-05-25T04:50:46.136Z
|
||||||
|
---
|
||||||
|
|
||||||
|
# Add raw button in Create new task
|
9
.kanbn/tasks/can-this-run-in-the-browser.md
Normal file
9
.kanbn/tasks/can-this-run-in-the-browser.md
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
created: 2023-05-25T04:04:06.760Z
|
||||||
|
updated: 2023-05-25T04:04:06.753Z
|
||||||
|
assigned: ""
|
||||||
|
progress: 0
|
||||||
|
tags: []
|
||||||
|
---
|
||||||
|
|
||||||
|
# Can this run in the browser?
|
19
.kanbn/tasks/fix-relations-bug.md
Normal file
19
.kanbn/tasks/fix-relations-bug.md
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
---
|
||||||
|
created: 2023-05-25T18:54:00.309Z
|
||||||
|
updated: 2023-05-25T18:55:32.671Z
|
||||||
|
assigned: ""
|
||||||
|
progress: 0
|
||||||
|
tags: []
|
||||||
|
started: 2023-05-25T18:55:32.671Z
|
||||||
|
---
|
||||||
|
|
||||||
|
# Fix relations bug
|
||||||
|
|
||||||
|
I started to look at th kanbn project all in javascript but I don't know how to reference it
|
||||||
|
|
||||||
|
## Comments
|
||||||
|
|
||||||
|
- date: 2023-05-25T18:54:44.808Z
|
||||||
|
```bash
|
||||||
|
node bin\kanbn add -n Mike
|
||||||
|
```
|
@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
created: 2023-05-26T03:47:27.942Z
|
||||||
|
updated: 2023-05-26T03:47:27.933Z
|
||||||
|
assigned: ""
|
||||||
|
progress: 0
|
||||||
|
tags: []
|
||||||
|
---
|
||||||
|
|
||||||
|
# How do I use local javascript project reference
|
9
.kanbn/tasks/make-tags-linkable.md
Normal file
9
.kanbn/tasks/make-tags-linkable.md
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
created: 2023-05-25T04:05:13.848Z
|
||||||
|
updated: 2023-05-25T04:05:33.759Z
|
||||||
|
assigned: ""
|
||||||
|
progress: 0
|
||||||
|
column: Backlog
|
||||||
|
---
|
||||||
|
|
||||||
|
# Make tags linkable
|
18
.kanbn/tasks/remove-relations-in-form.md
Normal file
18
.kanbn/tasks/remove-relations-in-form.md
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
created: 2023-05-30T18:38:37.231Z
|
||||||
|
updated: 2023-05-30T18:54:59.604Z
|
||||||
|
assigned: ""
|
||||||
|
progress: 1
|
||||||
|
tags: []
|
||||||
|
started: 2023-05-28T00:00:00.000Z
|
||||||
|
completed: 2023-05-30T00:00:00.000Z
|
||||||
|
---
|
||||||
|
|
||||||
|
# Remove relations in form
|
||||||
|
|
||||||
|
## Comments
|
||||||
|
|
||||||
|
- date: 2023-05-30T18:42:55.772Z
|
||||||
|
Added count to button title
|
||||||
|
Used false
|
||||||
|
see false && values.relations.length > 0 && values.relations.map((relation, index) =>
|
14
.kanbn/tasks/review-adding-more-on-item-card.md
Normal file
14
.kanbn/tasks/review-adding-more-on-item-card.md
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
created: 2023-05-25T04:01:15.185Z
|
||||||
|
updated: 2023-05-26T03:27:06.579Z
|
||||||
|
assigned: ""
|
||||||
|
progress: 0
|
||||||
|
tags:
|
||||||
|
- Maybe
|
||||||
|
completed: 2023-05-26T03:26:02.606Z
|
||||||
|
---
|
||||||
|
|
||||||
|
# Review adding more on item card
|
||||||
|
|
||||||
|
- Maybe not needed because that is what tags are meant for
|
||||||
|
- Buy maybe so because I don't like tags in the metadata
|
9
.kanbn/tasks/review-save-options.md
Normal file
9
.kanbn/tasks/review-save-options.md
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
created: 2023-05-25T04:01:05.154Z
|
||||||
|
updated: 2023-05-25T04:01:05.146Z
|
||||||
|
assigned: ""
|
||||||
|
progress: 0
|
||||||
|
tags: []
|
||||||
|
---
|
||||||
|
|
||||||
|
# Review save options
|
15
.kanbn/tasks/show-relations-on-the-item-card.md
Normal file
15
.kanbn/tasks/show-relations-on-the-item-card.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
created: 2023-05-25T04:59:37.306Z
|
||||||
|
updated: 2023-05-25T18:52:55.747Z
|
||||||
|
assigned: ""
|
||||||
|
progress: 0
|
||||||
|
tags: []
|
||||||
|
started: 2023-05-24T00:00:00.000Z
|
||||||
|
completed: 2023-05-25T18:52:55.747Z
|
||||||
|
---
|
||||||
|
|
||||||
|
# Show relations on the item card
|
||||||
|
|
||||||
|
## Sub-tasks
|
||||||
|
|
||||||
|
- [ ] make clickable
|
9
.kanbn/tasks/shrink-app-size.md
Normal file
9
.kanbn/tasks/shrink-app-size.md
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
created: 2023-05-25T04:03:54.530Z
|
||||||
|
updated: 2023-05-25T18:55:36.452Z
|
||||||
|
assigned: ""
|
||||||
|
progress: 0
|
||||||
|
tags: []
|
||||||
|
---
|
||||||
|
|
||||||
|
# Shrink app size
|
25
.kanbn/tasks/understand-how-relations-work.md
Normal file
25
.kanbn/tasks/understand-how-relations-work.md
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
---
|
||||||
|
created: 2023-05-25T18:54:00.309Z
|
||||||
|
updated: 2023-05-26T03:26:57.786Z
|
||||||
|
assigned: ""
|
||||||
|
progress: 0
|
||||||
|
tags: []
|
||||||
|
started: 2023-05-25T00:00:00.000Z
|
||||||
|
completed: 2023-05-26T03:25:48.979Z
|
||||||
|
---
|
||||||
|
|
||||||
|
# Understand how relations work
|
||||||
|
|
||||||
|
I started to look at th kanbn project all in javascript but I don't know how to reference it
|
||||||
|
|
||||||
|
## Relations
|
||||||
|
|
||||||
|
- [a b](b.md)
|
||||||
|
- [c d](d.md)
|
||||||
|
|
||||||
|
## Comments
|
||||||
|
|
||||||
|
- date: 2023-05-25T18:54:44.808Z
|
||||||
|
```bash
|
||||||
|
node bin\kanbn add -n Mike
|
||||||
|
```
|
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -8,5 +8,6 @@
|
|||||||
},
|
},
|
||||||
"typescript.tsdk": "./node_modules/typescript/lib", // we want to use the TS server from our node_modules folder to control its version
|
"typescript.tsdk": "./node_modules/typescript/lib", // we want to use the TS server from our node_modules folder to control its version
|
||||||
"typescript.tsc.autoDetect": "off",
|
"typescript.tsc.autoDetect": "off",
|
||||||
"todo-tree.tree.scanMode": "workspace only" // Turn off tsc task auto detection since we have the necessary task as npm scripts
|
"todo-tree.tree.scanMode": "workspace only",
|
||||||
|
"cSpell.enabled": false // Turn off tsc task auto detection since we have the necessary task as npm scripts
|
||||||
}
|
}
|
||||||
|
33
CHANGELOG.md
33
CHANGELOG.md
@ -1,10 +1,35 @@
|
|||||||
|
# 0.12.3
|
||||||
|
|
||||||
|
* See board ...
|
||||||
|
|
||||||
|
# 0.12.2
|
||||||
|
|
||||||
|
* See below
|
||||||
|
- [remove-relations-in-form](tasks/remove-relations-in-form.md)
|
||||||
|
|
||||||
|
# 0.12.1
|
||||||
|
|
||||||
|
* See below
|
||||||
|
- [understand-how-relations-work](tasks/understand-how-relations-work.md)
|
||||||
|
- [review-adding-more-on-item-card](tasks/review-adding-more-on-item-card.md)
|
||||||
|
|
||||||
|
# 0.12.0
|
||||||
|
|
||||||
|
* First release with the following changes
|
||||||
|
- [add-link-to-raw-in-panel-view](.kanbn/tasks/add-link-to-raw-in-panel-view.md)
|
||||||
|
- [add-raw-button-in-create-new-task](.kanbn/tasks/add-raw-button-in-create-new-task.md)
|
||||||
|
- [make-tags-linkable](.kanbn/tasks/make-tags-linkable.md)
|
||||||
|
- [show-relations-on-the-item-card](.kanbn/tasks/show-relations-on-the-item-card.md)
|
||||||
|
|
||||||
# 0.11.0
|
# 0.11.0
|
||||||
|
|
||||||
* Added KaTeX support to task markdown (description and comments) using `$$...$$` for blocks and `$...$` for inline
|
* KaTeX support in task markdown (description and comments) using `$$...$$` for blocks and `$...$` for inline
|
||||||
* Added syntax highlighting to code blocks in task markdown (description and comments)
|
* Syntax highlighting for code blocks in task markdown (description and comments)
|
||||||
* Added column sorting
|
* Columns can now be sorted, with the ability to optionally save sort settings per column
|
||||||
* Added relations and custom fields to task cards
|
* Added relations and custom fields to task cards
|
||||||
* Added task card customisation using `board.css`
|
* Task cards can be customised using `board.css`
|
||||||
|
* Custom fields can be modified using task editor
|
||||||
|
* Board can be filtered by custom field values
|
||||||
|
|
||||||
# 0.10.0
|
# 0.10.0
|
||||||
|
|
||||||
|
50
README.md
50
README.md
@ -1,7 +1,5 @@
|
|||||||
# Kanbn Extension for Visual Studio Code
|
# Kanbn Extension for Visual Studio Code
|
||||||
|
|
||||||
   [](https://opensource.org/licenses/MIT)
|
|
||||||
|
|
||||||
This extension adds a [Kanbn](https://www.npmjs.com/package/@basementuniverse/kanbn)-powered kanban board to Visual Studio Code.
|
This extension adds a [Kanbn](https://www.npmjs.com/package/@basementuniverse/kanbn)-powered kanban board to Visual Studio Code.
|
||||||
|
|
||||||

|

|
||||||
@ -32,20 +30,6 @@ Click on a task's title to open the task editor in a new tab. From here, you can
|
|||||||
|
|
||||||
You can also modify the index or task files directly, or by using Kanbn CLI commands, and the Kanbn board should update automatically to reflect these changes.
|
You can also modify the index or task files directly, or by using Kanbn CLI commands, and the Kanbn board should update automatically to reflect these changes.
|
||||||
|
|
||||||
## Filtering the Kanbn board
|
|
||||||
|
|
||||||
At the top-right of the Kanbn board there is a filter input. To filter visible tasks, enter a filter string and click the filter button (or press Enter).
|
|
||||||
|
|
||||||
### Filter string syntax
|
|
||||||
|
|
||||||
Text entered into the filter string input will be tested against each task's `id` and `name` fields. To filter on other fields, try the following:
|
|
||||||
|
|
||||||
- `overdue` will filter all tasks that have a due date in the past
|
|
||||||
- `description:search-string` will filter for tasks that contain `search-string` in their description or sub-tasks
|
|
||||||
- `assigned:search-string` will filter for tasks that contain `search-string` in their assigned user
|
|
||||||
- `tag:search-string` will filter for tasks that contain `search-string` in one of their tags
|
|
||||||
- `relation:search-string` will filter for tasks that contain `search-string` in one of their relations (either the relation type or related task id)
|
|
||||||
|
|
||||||
## Commands
|
## Commands
|
||||||
|
|
||||||
The following commands are available:
|
The following commands are available:
|
||||||
@ -66,6 +50,40 @@ The following configuration settings are available:
|
|||||||
- `kanbn.showSprintButton` when set to `true`, a 'Start sprint` button will will appear above the Kanbn board. This button will show the current sprint name if a sprint is currently active, and can be used to start a new sprint.
|
- `kanbn.showSprintButton` when set to `true`, a 'Start sprint` button will will appear above the Kanbn board. This button will show the current sprint name if a sprint is currently active, and can be used to start a new sprint.
|
||||||
- `kanbn.showBurndownButton` when set to `true`, a 'Show burndown chart` button will appear above the Kanbn board.
|
- `kanbn.showBurndownButton` when set to `true`, a 'Show burndown chart` button will appear above the Kanbn board.
|
||||||
|
|
||||||
|
## Filtering the Kanbn board
|
||||||
|
|
||||||
|
At the top-right of the Kanbn board there is a filter input. To filter visible tasks, enter a filter string and click the filter button (or press Enter).
|
||||||
|
|
||||||
|
### Filter string syntax
|
||||||
|
|
||||||
|
Text entered into the filter string input will be tested against each task's `id` and `name` fields. To filter on other fields, try the following:
|
||||||
|
|
||||||
|
- `overdue` will filter all tasks that have a due date in the past
|
||||||
|
- `description:search-string` will filter for tasks that contain `search-string` in their description or sub-tasks
|
||||||
|
- `assigned:search-string` will filter for tasks that contain `search-string` in their assigned user
|
||||||
|
- `tag:search-string` will filter for tasks that contain `search-string` in one of their tags
|
||||||
|
- `relation:search-string` will filter for tasks that contain `search-string` in one of their relations (either the relation type or related task id)
|
||||||
|
- `subtask:search-string` will filter for tasks that contain `search-string` in one of their sub-tasks
|
||||||
|
- `comment:search-string` will filter for tasks that contain `search-string` in one of their comments (either the comment author or text)
|
||||||
|
- `{custom field name}:search-string` will filter for tasks that have a custom field in their metadata that contains `search-string` in its value
|
||||||
|
- `{boolean custom field name}` will filter for tasks that have a boolean custom field in their metadata set to true
|
||||||
|
|
||||||
|
#### Examples
|
||||||
|
|
||||||
|
For these examples, assume we have a string custom field 'MyCustomField' and a boolean custom field 'MyCustomFlag' defined in the project options, i.e. `index.md` will contain:
|
||||||
|
```yaml
|
||||||
|
customFields:
|
||||||
|
- name: MyCustomField
|
||||||
|
type: string
|
||||||
|
- name: MyCustomFlag
|
||||||
|
type: boolean
|
||||||
|
```
|
||||||
|
|
||||||
|
(See https://github.com/basementuniverse/kanbn/blob/master/docs/index-structure.md for more information on custom fields)
|
||||||
|
|
||||||
|
- `assigned:testperson tag:large mycustomflag` will show tasks that are assigned to `testperson` and have a tag `Large` (search terms are case-insensitive) and have `MyCustomFlag` set to true
|
||||||
|
- `mycustomfield:test123 some title` will show tasks that have both `some` and `title` in their name/id and have a `MyCustomField` field that contains `test123`
|
||||||
|
|
||||||
## Styling the Kanbn board
|
## Styling the Kanbn board
|
||||||
|
|
||||||
This extension has been tested using various themes (light, dark and high-contrast), so it should always look somewhat presentable. However, if you'd like to set your own styles you can do so by creating a CSS file called `board.css` in the Kanbn directory. [Check here](docs/styles.md) for more information.
|
This extension has been tested using various themes (light, dark and high-contrast), so it should always look somewhat presentable. However, if you'd like to set your own styles you can do so by creating a CSS file called `board.css` in the Kanbn directory. [Check here](docs/styles.md) for more information.
|
||||||
|
@ -102,7 +102,7 @@ Here's an example of a task card style using some of the above features:
|
|||||||
- `kanbn-task-tag`
|
- `kanbn-task-tag`
|
||||||
- `kanbn-task-tag-{Tag name in param-case}`
|
- `kanbn-task-tag-{Tag name in param-case}`
|
||||||
- `kanbn-task-data-custom-field`
|
- `kanbn-task-data-custom-field`
|
||||||
- `kanbn-task-data-{Custom field name in param-case}
|
- `kanbn-task-data-{Custom field name in param-case}`
|
||||||
- `kanbn-task-data-assigned`
|
- `kanbn-task-data-assigned`
|
||||||
- `kanbn-task-data-created`
|
- `kanbn-task-data-created`
|
||||||
- `kanbn-task-data-updated`
|
- `kanbn-task-data-updated`
|
||||||
@ -129,6 +129,9 @@ Here's an example of a task card style using some of the above features:
|
|||||||
- `kanbn-task-editor-field-label`
|
- `kanbn-task-editor-field-label`
|
||||||
- `kanbn-task-editor-field-label-description`
|
- `kanbn-task-editor-field-label-description`
|
||||||
- `kanbn-task-editor-field-input`
|
- `kanbn-task-editor-field-input`
|
||||||
|
- `kanbn-task-editor-custom-field`
|
||||||
|
- `kanbn-task-editor-custom-field-{Custom field name in param-case}`
|
||||||
|
- `kanbn-task-editor-custom-checkbox`
|
||||||
- `kanbn-task-editor-id`
|
- `kanbn-task-editor-id`
|
||||||
- `kanbn-task-editor-description-preview`
|
- `kanbn-task-editor-description-preview`
|
||||||
- `kanbn-task-editor-button-edit-description`
|
- `kanbn-task-editor-button-edit-description`
|
||||||
@ -145,6 +148,7 @@ Here's an example of a task card style using some of the above features:
|
|||||||
- `kanbn-task-editor-button`
|
- `kanbn-task-editor-button`
|
||||||
- `kanbn-task-editor-button-delete`
|
- `kanbn-task-editor-button-delete`
|
||||||
- `kanbn-task-editor-buttons`
|
- `kanbn-task-editor-buttons`
|
||||||
|
- `kanbn-task-editor-main-buttons`
|
||||||
- `kanbn-task-editor-button-add`
|
- `kanbn-task-editor-button-add`
|
||||||
- `kanbn-task-editor-button-edit`
|
- `kanbn-task-editor-button-edit`
|
||||||
- `kanbn-task-editor-field-relations`
|
- `kanbn-task-editor-field-relations`
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import * as path from "path";
|
import { join } from "path";
|
||||||
import * as vscode from "vscode";
|
import { WebviewPanel, Disposable, window, ViewColumn, workspace, Uri, commands } from "vscode";
|
||||||
import getNonce from "./getNonce";
|
import getNonce from "./getNonce";
|
||||||
import KanbnTaskPanel from "./KanbnTaskPanel";
|
import KanbnTaskPanel from "./KanbnTaskPanel";
|
||||||
import KanbnBurndownPanel from "./KanbnBurndownPanel";
|
import KanbnBurndownPanel from "./KanbnBurndownPanel";
|
||||||
@ -24,12 +24,12 @@ export default class KanbnBoardPanel {
|
|||||||
|
|
||||||
private static readonly viewType = "react";
|
private static readonly viewType = "react";
|
||||||
|
|
||||||
private readonly _panel: vscode.WebviewPanel;
|
private readonly _panel: WebviewPanel;
|
||||||
private readonly _extensionPath: string;
|
private readonly _extensionPath: string;
|
||||||
private readonly _workspacePath: string;
|
private readonly _workspacePath: string;
|
||||||
private readonly _kanbn: typeof import("@basementuniverse/kanbn/src/main");
|
private readonly _kanbn: typeof import("@basementuniverse/kanbn/src/main");
|
||||||
private readonly _kanbnFolderName: string;
|
private readonly _kanbnFolderName: string;
|
||||||
private _disposables: vscode.Disposable[] = [];
|
private _disposables: Disposable[] = [];
|
||||||
|
|
||||||
public static createOrShow(
|
public static createOrShow(
|
||||||
extensionPath: string,
|
extensionPath: string,
|
||||||
@ -37,7 +37,7 @@ export default class KanbnBoardPanel {
|
|||||||
kanbn: typeof import("@basementuniverse/kanbn/src/main"),
|
kanbn: typeof import("@basementuniverse/kanbn/src/main"),
|
||||||
kanbnFolderName: string
|
kanbnFolderName: string
|
||||||
) {
|
) {
|
||||||
const column = vscode.window.activeTextEditor ? vscode.window.activeTextEditor.viewColumn : undefined;
|
const column = window.activeTextEditor ? window.activeTextEditor.viewColumn : undefined;
|
||||||
|
|
||||||
// If we already have a panel, show it, otherwise create a new panel
|
// If we already have a panel, show it, otherwise create a new panel
|
||||||
if (KanbnBoardPanel.currentPanel) {
|
if (KanbnBoardPanel.currentPanel) {
|
||||||
@ -46,7 +46,7 @@ export default class KanbnBoardPanel {
|
|||||||
KanbnBoardPanel.currentPanel = new KanbnBoardPanel(
|
KanbnBoardPanel.currentPanel = new KanbnBoardPanel(
|
||||||
extensionPath,
|
extensionPath,
|
||||||
workspacePath,
|
workspacePath,
|
||||||
column || vscode.ViewColumn.One,
|
column || ViewColumn.One,
|
||||||
kanbn,
|
kanbn,
|
||||||
kanbnFolderName
|
kanbnFolderName
|
||||||
);
|
);
|
||||||
@ -59,7 +59,7 @@ export default class KanbnBoardPanel {
|
|||||||
try {
|
try {
|
||||||
index = await KanbnBoardPanel.currentPanel._kanbn.getIndex();
|
index = await KanbnBoardPanel.currentPanel._kanbn.getIndex();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
vscode.window.showErrorMessage(error instanceof Error ? error.message : error);
|
window.showErrorMessage(error instanceof Error ? error.message : error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let tasks: any[];
|
let tasks: any[];
|
||||||
@ -68,7 +68,7 @@ export default class KanbnBoardPanel {
|
|||||||
KanbnBoardPanel.currentPanel!._kanbn.hydrateTask(index, task)
|
KanbnBoardPanel.currentPanel!._kanbn.hydrateTask(index, task)
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
vscode.window.showErrorMessage(error instanceof Error ? error.message : error);
|
window.showErrorMessage(error instanceof Error ? error.message : error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
KanbnBoardPanel.currentPanel._panel.webview.postMessage({
|
KanbnBoardPanel.currentPanel._panel.webview.postMessage({
|
||||||
@ -81,8 +81,8 @@ export default class KanbnBoardPanel {
|
|||||||
columnSorting: index.options.columnSorting ?? {},
|
columnSorting: index.options.columnSorting ?? {},
|
||||||
customFields: index.options.customFields ?? [],
|
customFields: index.options.customFields ?? [],
|
||||||
dateFormat: KanbnBoardPanel.currentPanel._kanbn.getDateFormat(index),
|
dateFormat: KanbnBoardPanel.currentPanel._kanbn.getDateFormat(index),
|
||||||
showBurndownButton: vscode.workspace.getConfiguration("kanbn").get("showBurndownButton"),
|
showBurndownButton: workspace.getConfiguration("kanbn").get("showBurndownButton"),
|
||||||
showSprintButton: vscode.workspace.getConfiguration("kanbn").get("showSprintButton"),
|
showSprintButton: workspace.getConfiguration("kanbn").get("showSprintButton"),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -90,7 +90,7 @@ export default class KanbnBoardPanel {
|
|||||||
private constructor(
|
private constructor(
|
||||||
extensionPath: string,
|
extensionPath: string,
|
||||||
workspacePath: string,
|
workspacePath: string,
|
||||||
column: vscode.ViewColumn,
|
column: ViewColumn,
|
||||||
kanbn: typeof import("@basementuniverse/kanbn/src/main"),
|
kanbn: typeof import("@basementuniverse/kanbn/src/main"),
|
||||||
kanbnFolderName: string
|
kanbnFolderName: string
|
||||||
) {
|
) {
|
||||||
@ -100,7 +100,7 @@ export default class KanbnBoardPanel {
|
|||||||
this._kanbnFolderName = kanbnFolderName;
|
this._kanbnFolderName = kanbnFolderName;
|
||||||
|
|
||||||
// Create and show a new webview panel
|
// Create and show a new webview panel
|
||||||
this._panel = vscode.window.createWebviewPanel(KanbnBoardPanel.viewType, "Kanbn Board", column, {
|
this._panel = window.createWebviewPanel(KanbnBoardPanel.viewType, "Kanbn Board", column, {
|
||||||
// Enable javascript in the webview
|
// Enable javascript in the webview
|
||||||
enableScripts: true,
|
enableScripts: true,
|
||||||
|
|
||||||
@ -109,14 +109,14 @@ export default class KanbnBoardPanel {
|
|||||||
|
|
||||||
// Restrict the webview to only loading content from allowed paths
|
// Restrict the webview to only loading content from allowed paths
|
||||||
localResourceRoots: [
|
localResourceRoots: [
|
||||||
vscode.Uri.file(path.join(this._extensionPath, "build")),
|
Uri.file(join(this._extensionPath, "build")),
|
||||||
vscode.Uri.file(path.join(this._workspacePath, this._kanbnFolderName)),
|
Uri.file(join(this._workspacePath, this._kanbnFolderName)),
|
||||||
vscode.Uri.file(path.join(this._extensionPath, "node_modules", "vscode-codicons", "dist")),
|
Uri.file(join(this._extensionPath, "node_modules", "vscode-codicons", "dist")),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
(this._panel as any).iconPath = {
|
(this._panel as any).iconPath = {
|
||||||
light: vscode.Uri.file(path.join(this._extensionPath, "resources", "project_light.svg")),
|
light: Uri.file(join(this._extensionPath, "resources", "project_light.svg")),
|
||||||
dark: vscode.Uri.file(path.join(this._extensionPath, "resources", "project_dark.svg")),
|
dark: Uri.file(join(this._extensionPath, "resources", "project_dark.svg")),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set the webview's title to the kanbn project name
|
// Set the webview's title to the kanbn project name
|
||||||
@ -138,7 +138,7 @@ export default class KanbnBoardPanel {
|
|||||||
|
|
||||||
// Display error message
|
// Display error message
|
||||||
case "error":
|
case "error":
|
||||||
vscode.window.showErrorMessage(message.text);
|
window.showErrorMessage(message.text);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Open a task in the editor
|
// Open a task in the editor
|
||||||
@ -153,12 +153,18 @@ export default class KanbnBoardPanel {
|
|||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Go to raw task in the editor
|
||||||
|
case "kanbn.goToRaw":
|
||||||
|
let uri = Uri.file(join(this._workspacePath, ".kanbn", "tasks", message.taskId + ".md"));
|
||||||
|
await commands.executeCommand('vscode.open', uri);
|
||||||
|
return;
|
||||||
|
|
||||||
// Move a task
|
// Move a task
|
||||||
case "kanbn.move":
|
case "kanbn.move":
|
||||||
try {
|
try {
|
||||||
await kanbn.moveTask(message.task, message.columnName, message.position);
|
await kanbn.moveTask(message.task, message.columnName, message.position);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
vscode.window.showErrorMessage(e.message);
|
window.showErrorMessage(e.message);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -185,7 +191,7 @@ export default class KanbnBoardPanel {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
// Prompt for a task property to sort by
|
// Prompt for a task property to sort by
|
||||||
const sortBy: string = await vscode.window.showQuickPick(
|
const sortBy = await window.showQuickPick(
|
||||||
[
|
[
|
||||||
'None',
|
'None',
|
||||||
...Object.keys(sortByFields),
|
...Object.keys(sortByFields),
|
||||||
@ -204,7 +210,7 @@ export default class KanbnBoardPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Prompt for sort direction and save settings
|
// Prompt for sort direction and save settings
|
||||||
const sortDirection = await vscode.window.showQuickPick(
|
const sortDirection = await window.showQuickPick(
|
||||||
[
|
[
|
||||||
'Ascending',
|
'Ascending',
|
||||||
'Descending',
|
'Descending',
|
||||||
@ -215,7 +221,7 @@ export default class KanbnBoardPanel {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
if (sortDirection !== undefined) {
|
if (sortDirection !== undefined) {
|
||||||
const saveSort = await vscode.window.showQuickPick(
|
const saveSort = await window.showQuickPick(
|
||||||
[
|
[
|
||||||
"Yes",
|
"Yes",
|
||||||
"No",
|
"No",
|
||||||
@ -256,7 +262,7 @@ export default class KanbnBoardPanel {
|
|||||||
// Start a new sprint
|
// Start a new sprint
|
||||||
case "kanbn.sprint":
|
case "kanbn.sprint":
|
||||||
// Prompt for a sprint name
|
// Prompt for a sprint name
|
||||||
const newSprintName = await vscode.window.showInputBox({
|
const newSprintName = await window.showInputBox({
|
||||||
placeHolder: "The sprint name.",
|
placeHolder: "The sprint name.",
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -265,7 +271,7 @@ export default class KanbnBoardPanel {
|
|||||||
try {
|
try {
|
||||||
await kanbn.sprint(newSprintName, "", new Date());
|
await kanbn.sprint(newSprintName, "", new Date());
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
vscode.window.showErrorMessage(e.message);
|
window.showErrorMessage(e.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
KanbnBurndownPanel.update();
|
KanbnBurndownPanel.update();
|
||||||
@ -291,20 +297,20 @@ export default class KanbnBoardPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _getHtmlForWebview() {
|
private _getHtmlForWebview() {
|
||||||
const manifest = require(path.join(this._extensionPath, "build", "asset-manifest.json"));
|
const manifest = require(join(this._extensionPath, "build", "asset-manifest.json"));
|
||||||
const mainScript = manifest["main.js"];
|
const mainScript = manifest["main.js"];
|
||||||
const mainStyle = manifest["main.css"];
|
const mainStyle = manifest["main.css"];
|
||||||
const scriptUri = vscode.Uri.file(path.join(this._extensionPath, "build", mainScript)).with({
|
const scriptUri = Uri.file(join(this._extensionPath, "build", mainScript)).with({
|
||||||
scheme: "vscode-resource",
|
scheme: "vscode-resource",
|
||||||
});
|
});
|
||||||
const styleUri = vscode.Uri.file(path.join(this._extensionPath, "build", mainStyle)).with({
|
const styleUri = Uri.file(join(this._extensionPath, "build", mainStyle)).with({
|
||||||
scheme: "vscode-resource",
|
scheme: "vscode-resource",
|
||||||
});
|
});
|
||||||
const customStyleUri = vscode.Uri.file(
|
const customStyleUri = Uri.file(
|
||||||
path.join(this._workspacePath, this._kanbnFolderName, "board.css")
|
join(this._workspacePath, this._kanbnFolderName, "board.css")
|
||||||
).with({ scheme: "vscode-resource" });
|
).with({ scheme: "vscode-resource" });
|
||||||
const codiconsUri = vscode.Uri.file(
|
const codiconsUri = Uri.file(
|
||||||
path.join(this._extensionPath, "node_modules", "vscode-codicons", "dist", "codicon.css")
|
join(this._extensionPath, "node_modules", "vscode-codicons", "dist", "codicon.css")
|
||||||
).with({ scheme: "vscode-resource" });
|
).with({ scheme: "vscode-resource" });
|
||||||
|
|
||||||
// Use a nonce to whitelist which scripts can be run
|
// Use a nonce to whitelist which scripts can be run
|
||||||
@ -321,7 +327,7 @@ export default class KanbnBoardPanel {
|
|||||||
<link rel="stylesheet" type="text/css" href="${customStyleUri}">
|
<link rel="stylesheet" type="text/css" href="${customStyleUri}">
|
||||||
<link rel="stylesheet" type="text/css" href="${codiconsUri}">
|
<link rel="stylesheet" type="text/css" href="${codiconsUri}">
|
||||||
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src vscode-resource: https:; script-src 'nonce-${nonce}'; font-src vscode-resource:; style-src vscode-resource: 'unsafe-inline' http: https: data:;">
|
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src vscode-resource: https:; script-src 'nonce-${nonce}'; font-src vscode-resource:; style-src vscode-resource: 'unsafe-inline' http: https: data:;">
|
||||||
<base href="${vscode.Uri.file(path.join(this._extensionPath, "build")).with({ scheme: "vscode-resource" })}/">
|
<base href="${Uri.file(join(this._extensionPath, "build")).with({ scheme: "vscode-resource" })}/">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import * as path from "path";
|
import { join } from "path";
|
||||||
import * as vscode from "vscode";
|
import { WebviewPanel, Disposable, window, ViewColumn, Uri } from "vscode";
|
||||||
import getNonce from "./getNonce";
|
import getNonce from "./getNonce";
|
||||||
|
|
||||||
export default class KanbnBurndownPanel {
|
export default class KanbnBurndownPanel {
|
||||||
@ -7,7 +7,7 @@ export default class KanbnBurndownPanel {
|
|||||||
|
|
||||||
private static readonly viewType = "react";
|
private static readonly viewType = "react";
|
||||||
|
|
||||||
private readonly _panel: vscode.WebviewPanel;
|
private readonly _panel: WebviewPanel;
|
||||||
private readonly _extensionPath: string;
|
private readonly _extensionPath: string;
|
||||||
private readonly _workspacePath: string;
|
private readonly _workspacePath: string;
|
||||||
private readonly _kanbn: typeof import("@basementuniverse/kanbn/src/main");
|
private readonly _kanbn: typeof import("@basementuniverse/kanbn/src/main");
|
||||||
@ -16,7 +16,7 @@ export default class KanbnBurndownPanel {
|
|||||||
private sprint: string = '';
|
private sprint: string = '';
|
||||||
private startDate: string = '';
|
private startDate: string = '';
|
||||||
private endDate: string = '';
|
private endDate: string = '';
|
||||||
private _disposables: vscode.Disposable[] = [];
|
private _disposables: Disposable[] = [];
|
||||||
|
|
||||||
public static async createOrShow(
|
public static async createOrShow(
|
||||||
extensionPath: string,
|
extensionPath: string,
|
||||||
@ -24,7 +24,7 @@ export default class KanbnBurndownPanel {
|
|||||||
kanbn: typeof import("@basementuniverse/kanbn/src/main"),
|
kanbn: typeof import("@basementuniverse/kanbn/src/main"),
|
||||||
kanbnFolderName: string
|
kanbnFolderName: string
|
||||||
) {
|
) {
|
||||||
const column = vscode.window.activeTextEditor ? vscode.window.activeTextEditor.viewColumn : undefined;
|
const column = window.activeTextEditor ? window.activeTextEditor.viewColumn : undefined;
|
||||||
|
|
||||||
// If we already have a panel, show it, otherwise create a new panel
|
// If we already have a panel, show it, otherwise create a new panel
|
||||||
if (KanbnBurndownPanel.currentPanel) {
|
if (KanbnBurndownPanel.currentPanel) {
|
||||||
@ -33,7 +33,7 @@ export default class KanbnBurndownPanel {
|
|||||||
KanbnBurndownPanel.currentPanel = new KanbnBurndownPanel(
|
KanbnBurndownPanel.currentPanel = new KanbnBurndownPanel(
|
||||||
extensionPath,
|
extensionPath,
|
||||||
workspacePath,
|
workspacePath,
|
||||||
column || vscode.ViewColumn.One,
|
column || ViewColumn.One,
|
||||||
kanbn,
|
kanbn,
|
||||||
kanbnFolderName
|
kanbnFolderName
|
||||||
);
|
);
|
||||||
@ -46,7 +46,7 @@ export default class KanbnBurndownPanel {
|
|||||||
try {
|
try {
|
||||||
index = await KanbnBurndownPanel.currentPanel._kanbn.getIndex();
|
index = await KanbnBurndownPanel.currentPanel._kanbn.getIndex();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
vscode.window.showErrorMessage(error instanceof Error ? error.message : error);
|
window.showErrorMessage(error instanceof Error ? error.message : error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
KanbnBurndownPanel.currentPanel._panel.webview.postMessage({
|
KanbnBurndownPanel.currentPanel._panel.webview.postMessage({
|
||||||
@ -78,7 +78,7 @@ export default class KanbnBurndownPanel {
|
|||||||
private constructor(
|
private constructor(
|
||||||
extensionPath: string,
|
extensionPath: string,
|
||||||
workspacePath: string,
|
workspacePath: string,
|
||||||
column: vscode.ViewColumn,
|
column: ViewColumn,
|
||||||
kanbn: typeof import("@basementuniverse/kanbn/src/main"),
|
kanbn: typeof import("@basementuniverse/kanbn/src/main"),
|
||||||
kanbnFolderName: string
|
kanbnFolderName: string
|
||||||
) {
|
) {
|
||||||
@ -88,7 +88,7 @@ export default class KanbnBurndownPanel {
|
|||||||
this._kanbnFolderName = kanbnFolderName;
|
this._kanbnFolderName = kanbnFolderName;
|
||||||
|
|
||||||
// Create and show a new webview panel
|
// Create and show a new webview panel
|
||||||
this._panel = vscode.window.createWebviewPanel(KanbnBurndownPanel.viewType, "Burndown Chart", column, {
|
this._panel = window.createWebviewPanel(KanbnBurndownPanel.viewType, "Burndown Chart", column, {
|
||||||
// Enable javascript in the webview
|
// Enable javascript in the webview
|
||||||
enableScripts: true,
|
enableScripts: true,
|
||||||
|
|
||||||
@ -97,14 +97,14 @@ export default class KanbnBurndownPanel {
|
|||||||
|
|
||||||
// Restrict the webview to only loading content from allowed paths
|
// Restrict the webview to only loading content from allowed paths
|
||||||
localResourceRoots: [
|
localResourceRoots: [
|
||||||
vscode.Uri.file(path.join(this._extensionPath, "build")),
|
Uri.file(join(this._extensionPath, "build")),
|
||||||
vscode.Uri.file(path.join(this._workspacePath, this._kanbnFolderName)),
|
Uri.file(join(this._workspacePath, this._kanbnFolderName)),
|
||||||
vscode.Uri.file(path.join(this._extensionPath, "node_modules", "vscode-codicons", "dist")),
|
Uri.file(join(this._extensionPath, "node_modules", "vscode-codicons", "dist")),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
(this._panel as any).iconPath = {
|
(this._panel as any).iconPath = {
|
||||||
light: vscode.Uri.file(path.join(this._extensionPath, "resources", "burndown_light.svg")),
|
light: Uri.file(join(this._extensionPath, "resources", "burndown_light.svg")),
|
||||||
dark: vscode.Uri.file(path.join(this._extensionPath, "resources", "burndown_dark.svg")),
|
dark: Uri.file(join(this._extensionPath, "resources", "burndown_dark.svg")),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set the webview's title to the kanbn project name
|
// Set the webview's title to the kanbn project name
|
||||||
@ -126,7 +126,7 @@ export default class KanbnBurndownPanel {
|
|||||||
|
|
||||||
// Display error message
|
// Display error message
|
||||||
case "error":
|
case "error":
|
||||||
vscode.window.showErrorMessage(message.text);
|
window.showErrorMessage(message.text);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Refresh the kanbn chart
|
// Refresh the kanbn chart
|
||||||
@ -158,20 +158,20 @@ export default class KanbnBurndownPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _getHtmlForWebview() {
|
private _getHtmlForWebview() {
|
||||||
const manifest = require(path.join(this._extensionPath, "build", "asset-manifest.json"));
|
const manifest = require(join(this._extensionPath, "build", "asset-manifest.json"));
|
||||||
const mainScript = manifest["main.js"];
|
const mainScript = manifest["main.js"];
|
||||||
const mainStyle = manifest["main.css"];
|
const mainStyle = manifest["main.css"];
|
||||||
const scriptUri = vscode.Uri.file(path.join(this._extensionPath, "build", mainScript)).with({
|
const scriptUri = Uri.file(join(this._extensionPath, "build", mainScript)).with({
|
||||||
scheme: "vscode-resource",
|
scheme: "vscode-resource",
|
||||||
});
|
});
|
||||||
const styleUri = vscode.Uri.file(path.join(this._extensionPath, "build", mainStyle)).with({
|
const styleUri = Uri.file(join(this._extensionPath, "build", mainStyle)).with({
|
||||||
scheme: "vscode-resource",
|
scheme: "vscode-resource",
|
||||||
});
|
});
|
||||||
const customStyleUri = vscode.Uri.file(
|
const customStyleUri = Uri.file(
|
||||||
path.join(this._workspacePath, this._kanbnFolderName, "board.css")
|
join(this._workspacePath, this._kanbnFolderName, "board.css")
|
||||||
).with({ scheme: "vscode-resource" });
|
).with({ scheme: "vscode-resource" });
|
||||||
const codiconsUri = vscode.Uri.file(
|
const codiconsUri = Uri.file(
|
||||||
path.join(this._extensionPath, "node_modules", "vscode-codicons", "dist", "codicon.css")
|
join(this._extensionPath, "node_modules", "vscode-codicons", "dist", "codicon.css")
|
||||||
).with({ scheme: "vscode-resource" });
|
).with({ scheme: "vscode-resource" });
|
||||||
|
|
||||||
// Use a nonce to whitelist which scripts can be run
|
// Use a nonce to whitelist which scripts can be run
|
||||||
@ -188,7 +188,7 @@ export default class KanbnBurndownPanel {
|
|||||||
<link rel="stylesheet" type="text/css" href="${customStyleUri}">
|
<link rel="stylesheet" type="text/css" href="${customStyleUri}">
|
||||||
<link rel="stylesheet" type="text/css" href="${codiconsUri}">
|
<link rel="stylesheet" type="text/css" href="${codiconsUri}">
|
||||||
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src vscode-resource: https:; script-src 'nonce-${nonce}'; font-src vscode-resource:; style-src vscode-resource: 'unsafe-inline' http: https: data:;">
|
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src vscode-resource: https:; script-src 'nonce-${nonce}'; font-src vscode-resource:; style-src vscode-resource: 'unsafe-inline' http: https: data:;">
|
||||||
<base href="${vscode.Uri.file(path.join(this._extensionPath, "build")).with({ scheme: "vscode-resource" })}/">
|
<base href="${Uri.file(join(this._extensionPath, "build")).with({ scheme: "vscode-resource" })}/">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
import { status } from '@basementuniverse/kanbn/src/main';
|
import { status } from '@basementuniverse/kanbn/src/main';
|
||||||
import * as vscode from 'vscode';
|
import { StatusBarItem, ExtensionContext, window, StatusBarAlignment, workspace } from 'vscode';
|
||||||
|
|
||||||
export default class KanbnStatusBarItem {
|
export default class KanbnStatusBarItem {
|
||||||
private readonly _statusBarItem: vscode.StatusBarItem;
|
private readonly _statusBarItem: StatusBarItem;
|
||||||
private readonly _kanbn: typeof import('@basementuniverse/kanbn/src/main');
|
private readonly _kanbn: typeof import('@basementuniverse/kanbn/src/main');
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
context: vscode.ExtensionContext,
|
context: ExtensionContext,
|
||||||
kanbn: typeof import('@basementuniverse/kanbn/src/main')
|
kanbn: typeof import('@basementuniverse/kanbn/src/main')
|
||||||
) {
|
) {
|
||||||
this._statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 0);
|
this._statusBarItem = window.createStatusBarItem(StatusBarAlignment.Left, 0);
|
||||||
context.subscriptions.push(this._statusBarItem);
|
context.subscriptions.push(this._statusBarItem);
|
||||||
this._kanbn = kanbn;
|
this._kanbn = kanbn;
|
||||||
}
|
}
|
||||||
@ -28,7 +28,7 @@ export default class KanbnStatusBarItem {
|
|||||||
const text = [
|
const text = [
|
||||||
`$(project) ${status.tasks}`
|
`$(project) ${status.tasks}`
|
||||||
];
|
];
|
||||||
let tooltip = [];
|
let tooltip: any = [];
|
||||||
if (status.tasks > 0) {
|
if (status.tasks > 0) {
|
||||||
tooltip = [
|
tooltip = [
|
||||||
`${status.tasks} task${status.tasks === 1 ? '' : 's'}`
|
`${status.tasks} task${status.tasks === 1 ? '' : 's'}`
|
||||||
@ -52,7 +52,7 @@ export default class KanbnStatusBarItem {
|
|||||||
this._statusBarItem.text = '$(project)';
|
this._statusBarItem.text = '$(project)';
|
||||||
this._statusBarItem.tooltip = 'Initialise Kanbn';
|
this._statusBarItem.tooltip = 'Initialise Kanbn';
|
||||||
this._statusBarItem.command = 'kanbn.init';
|
this._statusBarItem.command = 'kanbn.init';
|
||||||
if (vscode.workspace.getConfiguration('kanbn').get('showUninitialisedStatusBarItem')) {
|
if (workspace.getConfiguration('kanbn').get('showUninitialisedStatusBarItem')) {
|
||||||
this._statusBarItem.show();
|
this._statusBarItem.show();
|
||||||
} else {
|
} else {
|
||||||
this._statusBarItem.hide();
|
this._statusBarItem.hide();
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
import * as path from "path";
|
import { join } from "path";
|
||||||
import * as vscode from "vscode";
|
import { WebviewPanel, Disposable, window, ViewColumn, Uri, workspace, commands } from "vscode";
|
||||||
import getNonce from "./getNonce";
|
import getNonce from "./getNonce";
|
||||||
import { v4 as uuidv4 } from "uuid";
|
import { v4 as uuidv4 } from "uuid";
|
||||||
|
|
||||||
function transformTaskData(taskData: any) {
|
function transformTaskData(
|
||||||
|
taskData: any,
|
||||||
|
customFields: { name: string, type: 'boolean' | 'date' | 'number' | 'string' }[]
|
||||||
|
) {
|
||||||
const result = {
|
const result = {
|
||||||
id: taskData.id,
|
id: taskData.id,
|
||||||
name: taskData.name,
|
name: taskData.name,
|
||||||
@ -50,6 +53,17 @@ function transformTaskData(taskData: any) {
|
|||||||
result.metadata["completed"] = new Date(Date.parse(taskData.metadata.completed));
|
result.metadata["completed"] = new Date(Date.parse(taskData.metadata.completed));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add custom fields
|
||||||
|
for (let customField of customFields) {
|
||||||
|
if (customField.name in taskData.metadata && taskData.metadata[customField.name] !== null) {
|
||||||
|
if (customField.type === 'date') {
|
||||||
|
result.metadata[customField.name] = new Date(Date.parse(taskData.metadata[customField.name]));
|
||||||
|
} else {
|
||||||
|
result.metadata[customField.name] = taskData.metadata[customField.name];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,7 +71,7 @@ export default class KanbnTaskPanel {
|
|||||||
private static readonly viewType = "react";
|
private static readonly viewType = "react";
|
||||||
private static panels: Record<string, KanbnTaskPanel> = {};
|
private static panels: Record<string, KanbnTaskPanel> = {};
|
||||||
|
|
||||||
private readonly _panel: vscode.WebviewPanel;
|
private readonly _panel: WebviewPanel;
|
||||||
private readonly _extensionPath: string;
|
private readonly _extensionPath: string;
|
||||||
private readonly _workspacePath: string;
|
private readonly _workspacePath: string;
|
||||||
private readonly _kanbn: typeof import("@basementuniverse/kanbn/src/main");
|
private readonly _kanbn: typeof import("@basementuniverse/kanbn/src/main");
|
||||||
@ -65,7 +79,7 @@ export default class KanbnTaskPanel {
|
|||||||
private readonly _panelUuid: string;
|
private readonly _panelUuid: string;
|
||||||
private _taskId: string | null;
|
private _taskId: string | null;
|
||||||
private _columnName: string | null;
|
private _columnName: string | null;
|
||||||
private _disposables: vscode.Disposable[] = [];
|
private _disposables: Disposable[] = [];
|
||||||
|
|
||||||
public static async show(
|
public static async show(
|
||||||
extensionPath: string,
|
extensionPath: string,
|
||||||
@ -75,14 +89,14 @@ export default class KanbnTaskPanel {
|
|||||||
taskId: string | null,
|
taskId: string | null,
|
||||||
columnName: string | null
|
columnName: string | null
|
||||||
) {
|
) {
|
||||||
const column = vscode.window.activeTextEditor ? vscode.window.activeTextEditor.viewColumn : undefined;
|
const column = window.activeTextEditor ? window.activeTextEditor.viewColumn : undefined;
|
||||||
|
|
||||||
// Create a new panel
|
// Create a new panel
|
||||||
const panelUuid = uuidv4();
|
const panelUuid = uuidv4();
|
||||||
const taskPanel = new KanbnTaskPanel(
|
const taskPanel = new KanbnTaskPanel(
|
||||||
extensionPath,
|
extensionPath,
|
||||||
workspacePath,
|
workspacePath,
|
||||||
column || vscode.ViewColumn.One,
|
column || ViewColumn.One,
|
||||||
kanbn,
|
kanbn,
|
||||||
kanbnFolderName,
|
kanbnFolderName,
|
||||||
taskId,
|
taskId,
|
||||||
@ -96,7 +110,7 @@ export default class KanbnTaskPanel {
|
|||||||
private constructor(
|
private constructor(
|
||||||
extensionPath: string,
|
extensionPath: string,
|
||||||
workspacePath: string,
|
workspacePath: string,
|
||||||
column: vscode.ViewColumn,
|
column: ViewColumn,
|
||||||
kanbn: typeof import("@basementuniverse/kanbn/src/main"),
|
kanbn: typeof import("@basementuniverse/kanbn/src/main"),
|
||||||
kanbnFolderName: string,
|
kanbnFolderName: string,
|
||||||
taskId: string | null,
|
taskId: string | null,
|
||||||
@ -112,7 +126,7 @@ export default class KanbnTaskPanel {
|
|||||||
this._panelUuid = panelUuid;
|
this._panelUuid = panelUuid;
|
||||||
|
|
||||||
// Create and show a new webview panel
|
// Create and show a new webview panel
|
||||||
this._panel = vscode.window.createWebviewPanel(KanbnTaskPanel.viewType, "New task", column, {
|
this._panel = window.createWebviewPanel(KanbnTaskPanel.viewType, "New task", column, {
|
||||||
// Enable javascript in the webview
|
// Enable javascript in the webview
|
||||||
enableScripts: true,
|
enableScripts: true,
|
||||||
|
|
||||||
@ -121,14 +135,14 @@ export default class KanbnTaskPanel {
|
|||||||
|
|
||||||
// Restrict the webview to only loading content from allowed paths
|
// Restrict the webview to only loading content from allowed paths
|
||||||
localResourceRoots: [
|
localResourceRoots: [
|
||||||
vscode.Uri.file(path.join(this._extensionPath, "build")),
|
Uri.file(join(this._extensionPath, "build")),
|
||||||
vscode.Uri.file(path.join(this._workspacePath, this._kanbnFolderName)),
|
Uri.file(join(this._workspacePath, this._kanbnFolderName)),
|
||||||
vscode.Uri.file(path.join(this._extensionPath, "node_modules", "vscode-codicons", "dist")),
|
Uri.file(join(this._extensionPath, "node_modules", "vscode-codicons", "dist")),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
(this._panel as any).iconPath = {
|
(this._panel as any).iconPath = {
|
||||||
light: vscode.Uri.file(path.join(this._extensionPath, "resources", "task_light.svg")),
|
light: Uri.file(join(this._extensionPath, "resources", "task_light.svg")),
|
||||||
dark: vscode.Uri.file(path.join(this._extensionPath, "resources", "task_dark.svg")),
|
dark: Uri.file(join(this._extensionPath, "resources", "task_dark.svg")),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set the webview's title to the kanbn task name
|
// Set the webview's title to the kanbn task name
|
||||||
@ -152,7 +166,7 @@ export default class KanbnTaskPanel {
|
|||||||
|
|
||||||
// Display error message
|
// Display error message
|
||||||
case "error":
|
case "error":
|
||||||
vscode.window.showErrorMessage(message.text);
|
window.showErrorMessage(message.text);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Update the task webview panel title
|
// Update the task webview panel title
|
||||||
@ -162,49 +176,64 @@ export default class KanbnTaskPanel {
|
|||||||
|
|
||||||
// Create a task
|
// Create a task
|
||||||
case "kanbn.create":
|
case "kanbn.create":
|
||||||
await this._kanbn.createTask(transformTaskData(message.taskData), message.taskData.column);
|
await this._kanbn.createTask(
|
||||||
|
transformTaskData(message.taskData, message.customFields),
|
||||||
|
message.taskData.column
|
||||||
|
);
|
||||||
KanbnTaskPanel.panels[message.panelUuid]._taskId = message.taskData.id;
|
KanbnTaskPanel.panels[message.panelUuid]._taskId = message.taskData.id;
|
||||||
KanbnTaskPanel.panels[message.panelUuid]._columnName = message.taskData.column;
|
KanbnTaskPanel.panels[message.panelUuid]._columnName = message.taskData.column;
|
||||||
KanbnTaskPanel.panels[message.panelUuid].update();
|
KanbnTaskPanel.panels[message.panelUuid].update();
|
||||||
if (vscode.workspace.getConfiguration("kanbn").get("showTaskNotifications")) {
|
if (workspace.getConfiguration("kanbn").get("showTaskNotifications")) {
|
||||||
vscode.window.showInformationMessage(`Created task '${message.taskData.name}'.`);
|
window.showInformationMessage(`Created task '${message.taskData.name}'.`);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Update a task
|
// Update a task
|
||||||
case "kanbn.update":
|
case "kanbn.update":
|
||||||
await this._kanbn.updateTask(message.taskId, transformTaskData(message.taskData), message.taskData.column);
|
await this._kanbn.updateTask(
|
||||||
|
message.taskId,
|
||||||
|
transformTaskData(message.taskData, message.customFields),
|
||||||
|
message.taskData.column
|
||||||
|
);
|
||||||
KanbnTaskPanel.panels[message.panelUuid]._taskId = message.taskData.id;
|
KanbnTaskPanel.panels[message.panelUuid]._taskId = message.taskData.id;
|
||||||
KanbnTaskPanel.panels[message.panelUuid]._columnName = message.taskData.column;
|
KanbnTaskPanel.panels[message.panelUuid]._columnName = message.taskData.column;
|
||||||
KanbnTaskPanel.panels[message.panelUuid].update();
|
KanbnTaskPanel.panels[message.panelUuid].update();
|
||||||
if (vscode.workspace.getConfiguration("kanbn").get("showTaskNotifications")) {
|
if (workspace.getConfiguration("kanbn").get("showTaskNotifications")) {
|
||||||
vscode.window.showInformationMessage(`Updated task '${message.taskData.name}'.`);
|
window.showInformationMessage(`Updated task '${message.taskData.name}'.`);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Delete a task and close the webview panel
|
// Delete a task and close the webview panel
|
||||||
case "kanbn.delete":
|
case "kanbn.delete":
|
||||||
vscode.window
|
window
|
||||||
.showInformationMessage(`Delete task '${message.taskData.name}'?`, "Yes", "No")
|
.showInformationMessage(`Delete task '${message.taskData.name}'?`, "Yes", "No")
|
||||||
.then(async (value) => {
|
.then(async (value) => {
|
||||||
if (value === "Yes") {
|
if (value === "Yes") {
|
||||||
await this._kanbn.deleteTask(message.taskId, true);
|
await this._kanbn.deleteTask(message.taskId, true);
|
||||||
KanbnTaskPanel.panels[message.panelUuid].dispose();
|
KanbnTaskPanel.panels[message.panelUuid].dispose();
|
||||||
delete KanbnTaskPanel.panels[message.panelUuid];
|
delete KanbnTaskPanel.panels[message.panelUuid];
|
||||||
if (vscode.workspace.getConfiguration("kanbn").get("showTaskNotifications")) {
|
if (workspace.getConfiguration("kanbn").get("showTaskNotifications")) {
|
||||||
vscode.window.showInformationMessage(`Deleted task '${message.taskData.name}'.`);
|
window.showInformationMessage(`Deleted task '${message.taskData.name}'.`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Go to raw task and close the webview panel
|
||||||
|
case "kanbn.goToRaw":
|
||||||
|
KanbnTaskPanel.panels[message.panelUuid].dispose();
|
||||||
|
delete KanbnTaskPanel.panels[message.panelUuid];
|
||||||
|
let uri = Uri.file(join(this._workspacePath, ".kanbn", "tasks", message.taskId + ".md"));
|
||||||
|
await commands.executeCommand('vscode.open', uri);
|
||||||
|
return;
|
||||||
|
|
||||||
// Archive a task and close the webview panel
|
// Archive a task and close the webview panel
|
||||||
case 'kanbn.archive':
|
case 'kanbn.archive':
|
||||||
await this._kanbn.archiveTask(message.taskId);
|
await this._kanbn.archiveTask(message.taskId);
|
||||||
KanbnTaskPanel.panels[message.panelUuid].dispose();
|
KanbnTaskPanel.panels[message.panelUuid].dispose();
|
||||||
delete KanbnTaskPanel.panels[message.panelUuid];
|
delete KanbnTaskPanel.panels[message.panelUuid];
|
||||||
if (vscode.workspace.getConfiguration("kanbn").get("showTaskNotifications")) {
|
if (workspace.getConfiguration("kanbn").get("showTaskNotifications")) {
|
||||||
vscode.window.showInformationMessage(`Archived task '${message.taskData.name}'.`);
|
window.showInformationMessage(`Archived task '${message.taskData.name}'.`);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -229,7 +258,7 @@ export default class KanbnTaskPanel {
|
|||||||
try {
|
try {
|
||||||
index = await this._kanbn.getIndex();
|
index = await this._kanbn.getIndex();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
vscode.window.showErrorMessage(error instanceof Error ? error.message : error);
|
window.showErrorMessage(error instanceof Error ? error.message : error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let tasks: any[];
|
let tasks: any[];
|
||||||
@ -239,7 +268,7 @@ export default class KanbnTaskPanel {
|
|||||||
...this._kanbn.hydrateTask(index, task),
|
...this._kanbn.hydrateTask(index, task),
|
||||||
}));
|
}));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
vscode.window.showErrorMessage(error instanceof Error ? error.message : error);
|
window.showErrorMessage(error instanceof Error ? error.message : error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let task = null;
|
let task = null;
|
||||||
@ -258,6 +287,7 @@ export default class KanbnTaskPanel {
|
|||||||
index,
|
index,
|
||||||
task,
|
task,
|
||||||
tasks,
|
tasks,
|
||||||
|
customFields: index.options.customFields ?? [],
|
||||||
columnName: this._columnName,
|
columnName: this._columnName,
|
||||||
dateFormat: this._kanbn.getDateFormat(index),
|
dateFormat: this._kanbn.getDateFormat(index),
|
||||||
panelUuid: this._panelUuid,
|
panelUuid: this._panelUuid,
|
||||||
@ -265,20 +295,20 @@ export default class KanbnTaskPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _getHtmlForWebview() {
|
private _getHtmlForWebview() {
|
||||||
const manifest = require(path.join(this._extensionPath, "build", "asset-manifest.json"));
|
const manifest = require(join(this._extensionPath, "build", "asset-manifest.json"));
|
||||||
const mainScript = manifest["main.js"];
|
const mainScript = manifest["main.js"];
|
||||||
const mainStyle = manifest["main.css"];
|
const mainStyle = manifest["main.css"];
|
||||||
const scriptUri = vscode.Uri.file(path.join(this._extensionPath, "build", mainScript)).with({
|
const scriptUri = Uri.file(join(this._extensionPath, "build", mainScript)).with({
|
||||||
scheme: "vscode-resource",
|
scheme: "vscode-resource",
|
||||||
});
|
});
|
||||||
const styleUri = vscode.Uri.file(path.join(this._extensionPath, "build", mainStyle)).with({
|
const styleUri = Uri.file(join(this._extensionPath, "build", mainStyle)).with({
|
||||||
scheme: "vscode-resource",
|
scheme: "vscode-resource",
|
||||||
});
|
});
|
||||||
const customStyleUri = vscode.Uri.file(
|
const customStyleUri = Uri.file(
|
||||||
path.join(this._workspacePath, this._kanbnFolderName, "board.css")
|
join(this._workspacePath, this._kanbnFolderName, "board.css")
|
||||||
).with({ scheme: "vscode-resource" });
|
).with({ scheme: "vscode-resource" });
|
||||||
const codiconsUri = vscode.Uri.file(
|
const codiconsUri = Uri.file(
|
||||||
path.join(this._extensionPath, "node_modules", "vscode-codicons", "dist", "codicon.css")
|
join(this._extensionPath, "node_modules", "vscode-codicons", "dist", "codicon.css")
|
||||||
).with({ scheme: "vscode-resource" });
|
).with({ scheme: "vscode-resource" });
|
||||||
|
|
||||||
// Use a nonce to whitelist which scripts can be run
|
// Use a nonce to whitelist which scripts can be run
|
||||||
@ -295,7 +325,7 @@ export default class KanbnTaskPanel {
|
|||||||
<link rel="stylesheet" type="text/css" href="${customStyleUri}">
|
<link rel="stylesheet" type="text/css" href="${customStyleUri}">
|
||||||
<link rel="stylesheet" type="text/css" href="${codiconsUri}">
|
<link rel="stylesheet" type="text/css" href="${codiconsUri}">
|
||||||
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src vscode-resource: https:; script-src 'nonce-${nonce}'; font-src vscode-resource:; style-src vscode-resource: 'unsafe-inline' http: https: data:;">
|
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src vscode-resource: https:; script-src 'nonce-${nonce}'; font-src vscode-resource:; style-src vscode-resource: 'unsafe-inline' http: https: data:;">
|
||||||
<base href="${vscode.Uri.file(path.join(this._extensionPath, "build")).with({ scheme: "vscode-resource" })}/">
|
<base href="${Uri.file(join(this._extensionPath, "build")).with({ scheme: "vscode-resource" })}/">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import * as vscode from "vscode";
|
import { ExtensionContext, commands, workspace, window, RelativePattern } from "vscode";
|
||||||
import KanbnStatusBarItem from "./KanbnStatusBarItem";
|
import KanbnStatusBarItem from "./KanbnStatusBarItem";
|
||||||
import KanbnBoardPanel from "./KanbnBoardPanel";
|
import KanbnBoardPanel from "./KanbnBoardPanel";
|
||||||
import KanbnBurndownPanel from "./KanbnBurndownPanel";
|
import KanbnBurndownPanel from "./KanbnBurndownPanel";
|
||||||
@ -6,19 +6,19 @@ import KanbnTaskPanel from "./KanbnTaskPanel";
|
|||||||
|
|
||||||
let kanbnStatusBarItem: KanbnStatusBarItem;
|
let kanbnStatusBarItem: KanbnStatusBarItem;
|
||||||
|
|
||||||
export async function activate(context: vscode.ExtensionContext) {
|
export async function activate(context: ExtensionContext) {
|
||||||
// Register a command to initialise Kanbn in the current workspace. This command will be invoked when the status
|
// Register a command to initialise Kanbn in the current workspace. This command will be invoked when the status
|
||||||
// bar item is clicked in a workspace where Kanbn isn't already initialised.
|
// bar item is clicked in a workspace where Kanbn isn't already initialised.
|
||||||
context.subscriptions.push(
|
context.subscriptions.push(
|
||||||
vscode.commands.registerCommand("kanbn.init", async () => {
|
commands.registerCommand("kanbn.init", async () => {
|
||||||
// If no workspace folder is opened, we can't initialise kanbn
|
// If no workspace folder is opened, we can't initialise kanbn
|
||||||
if (vscode.workspace.workspaceFolders === undefined) {
|
if (workspace.workspaceFolders === undefined) {
|
||||||
vscode.window.showErrorMessage("You need to open a workspace before initialising Kanbn.");
|
window.showErrorMessage("You need to open a workspace before initialising Kanbn.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the node process directory and import kanbn
|
// Set the node process directory and import kanbn
|
||||||
process.chdir(vscode.workspace.workspaceFolders[0].uri.fsPath);
|
process.chdir(workspace.workspaceFolders[0].uri.fsPath);
|
||||||
const kanbn = await import("@basementuniverse/kanbn/src/main");
|
const kanbn = await import("@basementuniverse/kanbn/src/main");
|
||||||
|
|
||||||
// If kanbn is already initialised, get the project name
|
// If kanbn is already initialised, get the project name
|
||||||
@ -28,7 +28,7 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Prompt for a new project name
|
// Prompt for a new project name
|
||||||
const newProjectName = await vscode.window.showInputBox({
|
const newProjectName = await window.showInputBox({
|
||||||
value: projectName,
|
value: projectName,
|
||||||
placeHolder: "The project name.",
|
placeHolder: "The project name.",
|
||||||
validateInput: (text) => {
|
validateInput: (text) => {
|
||||||
@ -41,7 +41,7 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||||||
await kanbn.initialise({
|
await kanbn.initialise({
|
||||||
name: newProjectName,
|
name: newProjectName,
|
||||||
});
|
});
|
||||||
vscode.window.showInformationMessage(`Initialised Kanbn project '${newProjectName}'.`);
|
window.showInformationMessage(`Initialised Kanbn project '${newProjectName}'.`);
|
||||||
KanbnBoardPanel.update();
|
KanbnBoardPanel.update();
|
||||||
}
|
}
|
||||||
kanbnStatusBarItem.update();
|
kanbnStatusBarItem.update();
|
||||||
@ -51,28 +51,28 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||||||
// Register a command to open the kanbn board. This command will be invoked when the status bar item is clicked
|
// Register a command to open the kanbn board. This command will be invoked when the status bar item is clicked
|
||||||
// in a workspace where kanbn has already been initialised.
|
// in a workspace where kanbn has already been initialised.
|
||||||
context.subscriptions.push(
|
context.subscriptions.push(
|
||||||
vscode.commands.registerCommand("kanbn.board", async () => {
|
commands.registerCommand("kanbn.board", async () => {
|
||||||
// If no workspace folder is opened, we can't open the kanbn board
|
// If no workspace folder is opened, we can't open the kanbn board
|
||||||
if (vscode.workspace.workspaceFolders === undefined) {
|
if (workspace.workspaceFolders === undefined) {
|
||||||
vscode.window.showErrorMessage("You need to open a workspace before viewing the Kanbn board.");
|
window.showErrorMessage("You need to open a workspace before viewing the Kanbn board.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the node process directory and import kanbn
|
// Set the node process directory and import kanbn
|
||||||
process.chdir(vscode.workspace.workspaceFolders[0].uri.fsPath);
|
process.chdir(workspace.workspaceFolders[0].uri.fsPath);
|
||||||
const kanbn = await import("@basementuniverse/kanbn/src/main");
|
const kanbn = await import("@basementuniverse/kanbn/src/main");
|
||||||
|
|
||||||
// If kanbn is initialised, view the kanbn board
|
// If kanbn is initialised, view the kanbn board
|
||||||
if (await kanbn.initialised()) {
|
if (await kanbn.initialised()) {
|
||||||
KanbnBoardPanel.createOrShow(
|
KanbnBoardPanel.createOrShow(
|
||||||
context.extensionPath,
|
context.extensionPath,
|
||||||
vscode.workspace.workspaceFolders[0].uri.fsPath,
|
workspace.workspaceFolders[0].uri.fsPath,
|
||||||
kanbn,
|
kanbn,
|
||||||
await kanbn.getFolderName()
|
await kanbn.getFolderName()
|
||||||
);
|
);
|
||||||
KanbnBoardPanel.update();
|
KanbnBoardPanel.update();
|
||||||
} else {
|
} else {
|
||||||
vscode.window.showErrorMessage("You need to initialise Kanbn before viewing the Kanbn board.");
|
window.showErrorMessage("You need to initialise Kanbn before viewing the Kanbn board.");
|
||||||
}
|
}
|
||||||
kanbnStatusBarItem.update();
|
kanbnStatusBarItem.update();
|
||||||
})
|
})
|
||||||
@ -80,57 +80,57 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||||||
|
|
||||||
// Register a command to add a new kanbn task.
|
// Register a command to add a new kanbn task.
|
||||||
context.subscriptions.push(
|
context.subscriptions.push(
|
||||||
vscode.commands.registerCommand("kanbn.addTask", async () => {
|
commands.registerCommand("kanbn.addTask", async () => {
|
||||||
// If no workspace folder is opened, we can't add a new task
|
// If no workspace folder is opened, we can't add a new task
|
||||||
if (vscode.workspace.workspaceFolders === undefined) {
|
if (workspace.workspaceFolders === undefined) {
|
||||||
vscode.window.showErrorMessage("You need to open a workspace before adding a new task.");
|
window.showErrorMessage("You need to open a workspace before adding a new task.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the node process directory and import kanbn
|
// Set the node process directory and import kanbn
|
||||||
process.chdir(vscode.workspace.workspaceFolders[0].uri.fsPath);
|
process.chdir(workspace.workspaceFolders[0].uri.fsPath);
|
||||||
const kanbn = await import("@basementuniverse/kanbn/src/main");
|
const kanbn = await import("@basementuniverse/kanbn/src/main");
|
||||||
|
|
||||||
// If kanbn is initialised, open the task webview
|
// If kanbn is initialised, open the task webview
|
||||||
if (await kanbn.initialised()) {
|
if (await kanbn.initialised()) {
|
||||||
KanbnTaskPanel.show(
|
KanbnTaskPanel.show(
|
||||||
context.extensionPath,
|
context.extensionPath,
|
||||||
vscode.workspace.workspaceFolders[0].uri.fsPath,
|
workspace.workspaceFolders[0].uri.fsPath,
|
||||||
kanbn,
|
kanbn,
|
||||||
await kanbn.getFolderName(),
|
await kanbn.getFolderName(),
|
||||||
null,
|
null,
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
vscode.window.showErrorMessage("You need to initialise Kanbn before adding a new task.");
|
window.showErrorMessage("You need to initialise Kanbn before adding a new task.");
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
// Register a command to open a burndown chart.
|
// Register a command to open a burndown chart.
|
||||||
context.subscriptions.push(
|
context.subscriptions.push(
|
||||||
vscode.commands.registerCommand("kanbn.burndown", async () => {
|
commands.registerCommand("kanbn.burndown", async () => {
|
||||||
// If no workspace folder is opened, we can't open the burndown chart
|
// If no workspace folder is opened, we can't open the burndown chart
|
||||||
if (vscode.workspace.workspaceFolders === undefined) {
|
if (workspace.workspaceFolders === undefined) {
|
||||||
vscode.window.showErrorMessage("You need to open a workspace before viewing the burndown chart.");
|
window.showErrorMessage("You need to open a workspace before viewing the burndown chart.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the node process directory and import kanbn
|
// Set the node process directory and import kanbn
|
||||||
process.chdir(vscode.workspace.workspaceFolders[0].uri.fsPath);
|
process.chdir(workspace.workspaceFolders[0].uri.fsPath);
|
||||||
const kanbn = await import("@basementuniverse/kanbn/src/main");
|
const kanbn = await import("@basementuniverse/kanbn/src/main");
|
||||||
|
|
||||||
// If kanbn is initialised, view the burndown chart
|
// If kanbn is initialised, view the burndown chart
|
||||||
if (await kanbn.initialised()) {
|
if (await kanbn.initialised()) {
|
||||||
KanbnBurndownPanel.createOrShow(
|
KanbnBurndownPanel.createOrShow(
|
||||||
context.extensionPath,
|
context.extensionPath,
|
||||||
vscode.workspace.workspaceFolders[0].uri.fsPath,
|
workspace.workspaceFolders[0].uri.fsPath,
|
||||||
kanbn,
|
kanbn,
|
||||||
await kanbn.getFolderName()
|
await kanbn.getFolderName()
|
||||||
);
|
);
|
||||||
KanbnBurndownPanel.update();
|
KanbnBurndownPanel.update();
|
||||||
} else {
|
} else {
|
||||||
vscode.window.showErrorMessage("You need to initialise Kanbn before viewing the burndown chart.");
|
window.showErrorMessage("You need to initialise Kanbn before viewing the burndown chart.");
|
||||||
}
|
}
|
||||||
kanbnStatusBarItem.update();
|
kanbnStatusBarItem.update();
|
||||||
})
|
})
|
||||||
@ -138,15 +138,15 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||||||
|
|
||||||
// Register a command to archive tasks.
|
// Register a command to archive tasks.
|
||||||
context.subscriptions.push(
|
context.subscriptions.push(
|
||||||
vscode.commands.registerCommand("kanbn.archiveTasks", async () => {
|
commands.registerCommand("kanbn.archiveTasks", async () => {
|
||||||
// If no workspace folder is opened, we can't archive tasks
|
// If no workspace folder is opened, we can't archive tasks
|
||||||
if (vscode.workspace.workspaceFolders === undefined) {
|
if (workspace.workspaceFolders === undefined) {
|
||||||
vscode.window.showErrorMessage("You need to open a workspace before sending tasks to the archive.");
|
window.showErrorMessage("You need to open a workspace before sending tasks to the archive.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the node process directory and import kanbn
|
// Set the node process directory and import kanbn
|
||||||
process.chdir(vscode.workspace.workspaceFolders[0].uri.fsPath);
|
process.chdir(workspace.workspaceFolders[0].uri.fsPath);
|
||||||
const kanbn = await import("@basementuniverse/kanbn/src/main");
|
const kanbn = await import("@basementuniverse/kanbn/src/main");
|
||||||
|
|
||||||
// Get a list of tracked tasks
|
// Get a list of tracked tasks
|
||||||
@ -155,12 +155,12 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||||||
tasks = [...(await kanbn.findTrackedTasks())];
|
tasks = [...(await kanbn.findTrackedTasks())];
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
if (tasks.length === 0) {
|
if (tasks.length === 0) {
|
||||||
vscode.window.showInformationMessage("There are no tasks to archive.");
|
window.showInformationMessage("There are no tasks to archive.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prompt for a selection of tasks to archive
|
// Prompt for a selection of tasks to archive
|
||||||
const archiveTaskIds = await vscode.window.showQuickPick(
|
const archiveTaskIds = await window.showQuickPick(
|
||||||
tasks,
|
tasks,
|
||||||
{
|
{
|
||||||
placeHolder: 'Select tasks to archive...',
|
placeHolder: 'Select tasks to archive...',
|
||||||
@ -173,8 +173,8 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||||||
}
|
}
|
||||||
KanbnBoardPanel.update();
|
KanbnBoardPanel.update();
|
||||||
kanbnStatusBarItem.update();
|
kanbnStatusBarItem.update();
|
||||||
if (vscode.workspace.getConfiguration("kanbn").get("showTaskNotifications")) {
|
if (workspace.getConfiguration("kanbn").get("showTaskNotifications")) {
|
||||||
vscode.window.showInformationMessage(
|
window.showInformationMessage(
|
||||||
`Archived ${archiveTaskIds.length} task${archiveTaskIds.length === 1 ? '' : 's'}.`
|
`Archived ${archiveTaskIds.length} task${archiveTaskIds.length === 1 ? '' : 's'}.`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -184,15 +184,15 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||||||
|
|
||||||
// Register a command to restore a task from the archive.
|
// Register a command to restore a task from the archive.
|
||||||
context.subscriptions.push(
|
context.subscriptions.push(
|
||||||
vscode.commands.registerCommand("kanbn.restoreTasks", async () => {
|
commands.registerCommand("kanbn.restoreTasks", async () => {
|
||||||
// If no workspace folder is opened, we can't restore tasks from the archive
|
// If no workspace folder is opened, we can't restore tasks from the archive
|
||||||
if (vscode.workspace.workspaceFolders === undefined) {
|
if (workspace.workspaceFolders === undefined) {
|
||||||
vscode.window.showErrorMessage("You need to open a workspace before restoring tasks from the archive.");
|
window.showErrorMessage("You need to open a workspace before restoring tasks from the archive.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the node process directory and import kanbn
|
// Set the node process directory and import kanbn
|
||||||
process.chdir(vscode.workspace.workspaceFolders[0].uri.fsPath);
|
process.chdir(workspace.workspaceFolders[0].uri.fsPath);
|
||||||
const kanbn = await import("@basementuniverse/kanbn/src/main");
|
const kanbn = await import("@basementuniverse/kanbn/src/main");
|
||||||
|
|
||||||
// Get a list of archived tasks
|
// Get a list of archived tasks
|
||||||
@ -201,12 +201,12 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||||||
archivedTasks = await kanbn.listArchivedTasks();
|
archivedTasks = await kanbn.listArchivedTasks();
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
if (archivedTasks.length === 0) {
|
if (archivedTasks.length === 0) {
|
||||||
vscode.window.showInformationMessage("There are no archived tasks to restore.");
|
window.showInformationMessage("There are no archived tasks to restore.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prompt for a selection of tasks to restore
|
// Prompt for a selection of tasks to restore
|
||||||
const restoreTaskIds = await vscode.window.showQuickPick(
|
const restoreTaskIds = await window.showQuickPick(
|
||||||
archivedTasks,
|
archivedTasks,
|
||||||
{
|
{
|
||||||
placeHolder: 'Select tasks to restore...',
|
placeHolder: 'Select tasks to restore...',
|
||||||
@ -219,7 +219,7 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||||||
const index = await kanbn.getIndex();
|
const index = await kanbn.getIndex();
|
||||||
|
|
||||||
// Prompt for a column to restore the tasks into
|
// Prompt for a column to restore the tasks into
|
||||||
const restoreColumn = await vscode.window.showQuickPick(
|
const restoreColumn = await window.showQuickPick(
|
||||||
[
|
[
|
||||||
'None (use original)',
|
'None (use original)',
|
||||||
...Object.keys(index.columns)
|
...Object.keys(index.columns)
|
||||||
@ -234,8 +234,8 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||||||
}
|
}
|
||||||
KanbnBoardPanel.update();
|
KanbnBoardPanel.update();
|
||||||
kanbnStatusBarItem.update();
|
kanbnStatusBarItem.update();
|
||||||
if (vscode.workspace.getConfiguration("kanbn").get("showTaskNotifications")) {
|
if (workspace.getConfiguration("kanbn").get("showTaskNotifications")) {
|
||||||
vscode.window.showInformationMessage(
|
window.showInformationMessage(
|
||||||
`Restored ${restoreTaskIds.length} task${restoreTaskIds.length === 1 ? '' : 's'}.`
|
`Restored ${restoreTaskIds.length} task${restoreTaskIds.length === 1 ? '' : 's'}.`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -245,9 +245,9 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// If a workspace folder is open, add a status bar item and start watching for file changes
|
// If a workspace folder is open, add a status bar item and start watching for file changes
|
||||||
if (vscode.workspace.workspaceFolders !== undefined) {
|
if (workspace.workspaceFolders !== undefined) {
|
||||||
// Set the node process directory and import kanbn
|
// Set the node process directory and import kanbn
|
||||||
process.chdir(vscode.workspace.workspaceFolders[0].uri.fsPath);
|
process.chdir(workspace.workspaceFolders[0].uri.fsPath);
|
||||||
const kanbn = await import("@basementuniverse/kanbn/src/main");
|
const kanbn = await import("@basementuniverse/kanbn/src/main");
|
||||||
|
|
||||||
// Create status bar item
|
// Create status bar item
|
||||||
@ -256,10 +256,10 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||||||
KanbnBoardPanel.update();
|
KanbnBoardPanel.update();
|
||||||
|
|
||||||
// Initialise file watcher
|
// Initialise file watcher
|
||||||
const uri = vscode.workspace.workspaceFolders[0].uri.fsPath;
|
const uri = workspace.workspaceFolders[0].uri.fsPath;
|
||||||
const kanbnFolderName = await kanbn.getFolderName();
|
const kanbnFolderName = await kanbn.getFolderName();
|
||||||
const fileWatcher = vscode.workspace.createFileSystemWatcher(
|
const fileWatcher = workspace.createFileSystemWatcher(
|
||||||
new vscode.RelativePattern(uri, `${kanbnFolderName}/**.*`)
|
new RelativePattern(uri, `${kanbnFolderName}/**/*.md`)
|
||||||
);
|
);
|
||||||
fileWatcher.onDidChange(() => {
|
fileWatcher.onDidChange(() => {
|
||||||
kanbnStatusBarItem.update();
|
kanbnStatusBarItem.update();
|
||||||
@ -269,7 +269,7 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle configuration changes
|
// Handle configuration changes
|
||||||
vscode.workspace.onDidChangeConfiguration((e) => {
|
workspace.onDidChangeConfiguration((e) => {
|
||||||
kanbnStatusBarItem.update();
|
kanbnStatusBarItem.update();
|
||||||
KanbnBoardPanel.update();
|
KanbnBoardPanel.update();
|
||||||
});
|
});
|
||||||
|
32098
package-lock.json
generated
32098
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
13
package.json
13
package.json
@ -7,13 +7,13 @@
|
|||||||
"color": "#72abdd",
|
"color": "#72abdd",
|
||||||
"theme": "dark"
|
"theme": "dark"
|
||||||
},
|
},
|
||||||
"version": "0.10.0",
|
"version": "0.12.3",
|
||||||
"engines": {
|
"engines": {
|
||||||
"vscode": "^1.23.0"
|
"vscode": "^1.23.0"
|
||||||
},
|
},
|
||||||
"author": "Gordon Larrigan",
|
"author": "Gordon Larrigan",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"publisher": "gordonlarrigan",
|
"publisher": "phares",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"kanbn",
|
"kanbn",
|
||||||
"kanban",
|
"kanban",
|
||||||
@ -118,12 +118,15 @@
|
|||||||
"vscode-codicons": "^0.0.15"
|
"vscode-codicons": "^0.0.15"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"vscode:prepublish": "./scripts/build-non-split.js && tsc -p tsconfig.extension.json",
|
"vscode:prepublish": "node ./scripts/build-non-split.js && tsc -p tsconfig.extension.json",
|
||||||
"postinstall": "node ./node_modules/vscode/bin/install",
|
"postinstall": "node ./node_modules/vscode/bin/install",
|
||||||
"start": "react-scripts start",
|
"start": "react-scripts start",
|
||||||
"build": "./scripts/build-non-split.js && tsc -p tsconfig.extension.json",
|
"react:build": "node ./scripts/build-non-split.js",
|
||||||
|
"tsc:build": "tsc -p tsconfig.extension.json",
|
||||||
|
"build": "node ./scripts/build-non-split.js && tsc -p tsconfig.extension.json",
|
||||||
"test": "react-scripts test --env=jsdom",
|
"test": "react-scripts test --env=jsdom",
|
||||||
"eject": "react-scripts eject"
|
"eject": "react-scripts eject",
|
||||||
|
"vscode:package": "vsce package"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/dateformat": "^3.0.1",
|
"@types/dateformat": "^3.0.1",
|
||||||
|
@ -66,6 +66,7 @@ function App() {
|
|||||||
setTasks(tasks);
|
setTasks(tasks);
|
||||||
setColumnName(event.data.columnName);
|
setColumnName(event.data.columnName);
|
||||||
setColumnNames(Object.keys(event.data.index.columns));
|
setColumnNames(Object.keys(event.data.index.columns));
|
||||||
|
setCustomFields(event.data.customFields);
|
||||||
setPanelUuid(event.data.panelUuid);
|
setPanelUuid(event.data.panelUuid);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -118,6 +119,7 @@ function App() {
|
|||||||
tasks={tasks}
|
tasks={tasks}
|
||||||
columnName={columnName}
|
columnName={columnName}
|
||||||
columnNames={columnNames}
|
columnNames={columnNames}
|
||||||
|
customFields={customFields}
|
||||||
dateFormat={dateFormat}
|
dateFormat={dateFormat}
|
||||||
panelUuid={panelUuid}
|
panelUuid={panelUuid}
|
||||||
vscode={vscode}
|
vscode={vscode}
|
||||||
|
@ -70,12 +70,23 @@ const filterProperties = [
|
|||||||
'description',
|
'description',
|
||||||
'assigned',
|
'assigned',
|
||||||
'tag',
|
'tag',
|
||||||
'relation'
|
'relation',
|
||||||
|
'subtask',
|
||||||
|
'comment',
|
||||||
];
|
];
|
||||||
|
|
||||||
// Filter tasks according to the filter string
|
// Filter tasks according to the filter string
|
||||||
const filterTask = (task: KanbnTask, taskFilter: string) => {
|
const filterTask = (
|
||||||
|
task: KanbnTask,
|
||||||
|
taskFilter: string,
|
||||||
|
customFields: { name: string, type: 'boolean' | 'date' | 'number' | 'string' }[]
|
||||||
|
) => {
|
||||||
let result = true;
|
let result = true;
|
||||||
|
const customFieldMap = Object.fromEntries(customFields.map(customField => [
|
||||||
|
customField.name.toLowerCase(),
|
||||||
|
customField,
|
||||||
|
]));
|
||||||
|
const customFieldNames = Object.keys(customFieldMap);
|
||||||
taskFilter.split(' ').forEach(f => {
|
taskFilter.split(' ').forEach(f => {
|
||||||
const parts = f.split(':').map(p => p.toLowerCase());
|
const parts = f.split(':').map(p => p.toLowerCase());
|
||||||
|
|
||||||
@ -90,6 +101,17 @@ const filterTask = (task: KanbnTask, taskFilter: string) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Filter boolean custom fields
|
||||||
|
if (customFieldNames.includes(parts[0]) && customFieldMap[parts[0]].type === 'boolean') {
|
||||||
|
if (
|
||||||
|
!(customFieldMap[parts[0]].name in task.metadata) ||
|
||||||
|
!task.metadata[customFieldMap[parts[0]].name]
|
||||||
|
) {
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Filter task id or name
|
// Filter task id or name
|
||||||
if (
|
if (
|
||||||
!task.id.toLowerCase().includes(parts[0]) &&
|
!task.id.toLowerCase().includes(parts[0]) &&
|
||||||
@ -101,9 +123,14 @@ const filterTask = (task: KanbnTask, taskFilter: string) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If this filter section contains a property name and value, check the value against the property
|
// If this filter section contains a property name and value, check the value against the property
|
||||||
if (parts.length === 2 && filterProperties.indexOf(parts[0]) !== -1) {
|
if (
|
||||||
|
parts.length === 2 && (
|
||||||
|
filterProperties.includes(parts[0]) ||
|
||||||
|
customFieldNames.includes(parts[0])
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
|
||||||
// Filter by property value
|
// Fetch the value to filter by
|
||||||
let propertyValue = '';
|
let propertyValue = '';
|
||||||
switch (parts[0]) {
|
switch (parts[0]) {
|
||||||
case 'description':
|
case 'description':
|
||||||
@ -121,8 +148,24 @@ const filterTask = (task: KanbnTask, taskFilter: string) => {
|
|||||||
case 'relation':
|
case 'relation':
|
||||||
propertyValue = task.relations.map(relation => `${relation.type} ${relation.task}`).join(' ');
|
propertyValue = task.relations.map(relation => `${relation.type} ${relation.task}`).join(' ');
|
||||||
break;
|
break;
|
||||||
default: break;
|
case 'subtask':
|
||||||
|
propertyValue = task.subTasks.map(subTask => `${subTask.text}`).join(' ');
|
||||||
|
break;
|
||||||
|
case 'comment':
|
||||||
|
propertyValue = task.comments.map(comment => `${comment.author} ${comment.text}`).join(' ');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (
|
||||||
|
customFieldNames.includes(parts[0]) &&
|
||||||
|
customFieldMap[parts[0]].type !== 'boolean' &&
|
||||||
|
customFieldMap[parts[0]].name in task.metadata
|
||||||
|
) {
|
||||||
|
propertyValue = `${task.metadata[customFieldMap[parts[0]].name]}`;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check the search term against the value
|
||||||
if (!propertyValue.toLowerCase().includes(parts[1])) {
|
if (!propertyValue.toLowerCase().includes(parts[1])) {
|
||||||
result = false;
|
result = false;
|
||||||
}
|
}
|
||||||
@ -326,14 +369,16 @@ const Board = ({
|
|||||||
snapshot.isDraggingOver ? 'drag-over' : null
|
snapshot.isDraggingOver ? 'drag-over' : null
|
||||||
].filter(i => i).join(' ')}
|
].filter(i => i).join(' ')}
|
||||||
>
|
>
|
||||||
{column.filter(task => filterTask(task, taskFilter)).map((task, position) => <TaskItem
|
{column
|
||||||
task={task}
|
.filter(task => filterTask(task, taskFilter, customFields))
|
||||||
columnName={columnName}
|
.map((task, position) => <TaskItem
|
||||||
customFields={customFields}
|
task={task}
|
||||||
position={position}
|
columnName={columnName}
|
||||||
dateFormat={dateFormat}
|
customFields={customFields}
|
||||||
vscode={vscode}
|
position={position}
|
||||||
/>)}
|
dateFormat={dateFormat}
|
||||||
|
vscode={vscode}
|
||||||
|
/>)}
|
||||||
{provided.placeholder}
|
{provided.placeholder}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -71,10 +71,17 @@ const TaskItem = ({ task, columnName, customFields, position, dateFormat, vscode
|
|||||||
<div className="kanbn-task-data kanbn-task-data-tags">
|
<div className="kanbn-task-data kanbn-task-data-tags">
|
||||||
{task.metadata.tags!.map(tag => {
|
{task.metadata.tags!.map(tag => {
|
||||||
return (
|
return (
|
||||||
<span className={[
|
<span onClick={() => {
|
||||||
'kanbn-task-tag',
|
vscode.postMessage({
|
||||||
`kanbn-task-tag-${paramCase(tag)}`
|
command: 'kanbn.goToRaw',
|
||||||
].join(' ')}>
|
taskId: task.id,
|
||||||
|
columnName: task.column
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
className={[
|
||||||
|
'kanbn-task-tag',
|
||||||
|
`kanbn-task-tag-${paramCase(tag)}`
|
||||||
|
].join(' ')}>
|
||||||
{tag}
|
{tag}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
@ -102,7 +109,9 @@ const TaskItem = ({ task, columnName, customFields, position, dateFormat, vscode
|
|||||||
<>
|
<>
|
||||||
<i className="codicon codicon-json"></i>
|
<i className="codicon codicon-json"></i>
|
||||||
<span title={customField.name}>
|
<span title={customField.name}>
|
||||||
{task.metadata[customField.name]}
|
{customField.type === 'date'
|
||||||
|
? formatDate(task.metadata[customField.name], dateFormat)
|
||||||
|
: task.metadata[customField.name]}
|
||||||
</span>
|
</span>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
@ -166,16 +175,30 @@ const TaskItem = ({ task, columnName, customFields, position, dateFormat, vscode
|
|||||||
{
|
{
|
||||||
task.workload !== undefined &&
|
task.workload !== undefined &&
|
||||||
<div className="kanbn-task-data kanbn-task-data-workload">
|
<div className="kanbn-task-data kanbn-task-data-workload">
|
||||||
<i className="codicon codicon-run"></i>{task.workload}
|
<i className="codicon codicon-tools"
|
||||||
|
onClick={() => {
|
||||||
|
vscode.postMessage({
|
||||||
|
command: 'kanbn.goToRaw',
|
||||||
|
taskId: task.id,
|
||||||
|
columnName: task.column
|
||||||
|
});
|
||||||
|
}}></i>{task.workload}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
task.relations.length > 0 &&
|
task.relations.length > 0 &&
|
||||||
task.relations.map(relation => (
|
task.relations.map(relation => (
|
||||||
<div className={[
|
<div onClick={() => {
|
||||||
'kanbn-task-data kanbn-task-data-relation',
|
vscode.postMessage({
|
||||||
relation.type ? `kanbn-task-data-relation-${relation.type}` : null,
|
command: 'kanbn.goToRaw',
|
||||||
].join(' ')}>
|
taskId: task.id,
|
||||||
|
columnName: task.column
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
className={[
|
||||||
|
'kanbn-task-data kanbn-task-data-relation',
|
||||||
|
relation.type ? `kanbn-task-data-relation-${relation.type}` : null,
|
||||||
|
].join(' ')}>
|
||||||
<i className="codicon codicon-link"></i>
|
<i className="codicon codicon-link"></i>
|
||||||
<span className="kanbn-task-data-label">
|
<span className="kanbn-task-data-label">
|
||||||
{relation.type}
|
{relation.type}
|
||||||
|
@ -351,10 +351,9 @@ Task editor styles
|
|||||||
-----------------------------------------------------------------------------*/
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
.kanbn-task-editor-title {
|
.kanbn-task-editor-title {
|
||||||
|
display: inline-block;
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
padding-bottom: 0.5em;
|
|
||||||
border-bottom: 1px var(--vscode-activityBar-inactiveForeground) solid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.kanbn-task-editor-dirty {
|
.kanbn-task-editor-dirty {
|
||||||
@ -368,10 +367,12 @@ Task editor styles
|
|||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
float: right;
|
float: right;
|
||||||
|
margin: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.kanbn-task-editor-form {
|
.kanbn-task-editor-form {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
border-top: 1px solid var(--vscode-activityBar-inactiveForeground);
|
||||||
}
|
}
|
||||||
|
|
||||||
.kanbn-task-editor-field .kanbn-task-editor-title,
|
.kanbn-task-editor-field .kanbn-task-editor-title,
|
||||||
@ -439,6 +440,12 @@ body.vscode-dark .kanbn-task-editor-field-input[type="date"]::-webkit-calendar-p
|
|||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.kanbn-task-editor-main-buttons {
|
||||||
|
float: right;
|
||||||
|
position: relative;
|
||||||
|
top: -0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
.kanbn-task-editor-button {
|
.kanbn-task-editor-button {
|
||||||
outline: none;
|
outline: none;
|
||||||
border: 1px transparent solid;
|
border: 1px transparent solid;
|
||||||
@ -602,6 +609,14 @@ body.vscode-dark .kanbn-task-editor-field-input[type="date"]::-webkit-calendar-p
|
|||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.kanbn-task-editor-custom-checkbox {
|
||||||
|
float: left;
|
||||||
|
width: auto;
|
||||||
|
position: relative;
|
||||||
|
top: -.2em;
|
||||||
|
margin: .5em 1em .5em 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------
|
/*-----------------------------------------------------------------------------
|
||||||
Burndown chart styles
|
Burndown chart styles
|
||||||
-----------------------------------------------------------------------------*/
|
-----------------------------------------------------------------------------*/
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import * as ReactDOM from 'react-dom';
|
import { render } from 'react-dom';
|
||||||
import App from './App';
|
import App from './App';
|
||||||
import './index.css';
|
import './index.css';
|
||||||
|
|
||||||
ReactDOM.render(
|
render(
|
||||||
<App />,
|
<App />,
|
||||||
document.getElementById('root') as HTMLElement
|
document.getElementById('root') as HTMLElement
|
||||||
);
|
);
|
||||||
|
BIN
vscode-kanbn-0.12.0.vsix
Normal file
BIN
vscode-kanbn-0.12.0.vsix
Normal file
Binary file not shown.
BIN
vscode-kanbn-0.12.1.vsix
Normal file
BIN
vscode-kanbn-0.12.1.vsix
Normal file
Binary file not shown.
BIN
vscode-kanbn-0.12.2.vsix
Normal file
BIN
vscode-kanbn-0.12.2.vsix
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user