Add column sorting
This commit is contained in:
parent
d79f216687
commit
f53db52672
@ -27,7 +27,10 @@ Various Codicon icons have been used in this extension. Check [here](https://cod
|
|||||||
- `kanbn-column-{Column name in snake-case}`
|
- `kanbn-column-{Column name in snake-case}`
|
||||||
- `kanbn-column-name`
|
- `kanbn-column-name`
|
||||||
- `kanbn-column-count`
|
- `kanbn-column-count`
|
||||||
|
- `kanbn-column-button`
|
||||||
- `kanbn-create-task-button`
|
- `kanbn-create-task-button`
|
||||||
|
- `kanbn-sort-column-button`
|
||||||
|
- `kanbn-column-sorted`
|
||||||
- `kanbn-column-task-list-container`
|
- `kanbn-column-task-list-container`
|
||||||
- `kanbn-column-task-list`
|
- `kanbn-column-task-list`
|
||||||
- `kanbn-column-task-list.drag-over`
|
- `kanbn-column-task-list.drag-over`
|
||||||
|
@ -4,6 +4,21 @@ import getNonce from "./getNonce";
|
|||||||
import KanbnTaskPanel from "./KanbnTaskPanel";
|
import KanbnTaskPanel from "./KanbnTaskPanel";
|
||||||
import KanbnBurndownPanel from "./KanbnBurndownPanel";
|
import KanbnBurndownPanel from "./KanbnBurndownPanel";
|
||||||
|
|
||||||
|
const sortByFields: { [key: string]: string } = {
|
||||||
|
'Name': 'name',
|
||||||
|
'Created': 'created',
|
||||||
|
'Updated': 'updated',
|
||||||
|
'Started': 'started',
|
||||||
|
'Completed': 'completed',
|
||||||
|
'Due': 'due',
|
||||||
|
'Assigned': 'assigned',
|
||||||
|
'Count sub-tasks': 'countSubTasks',
|
||||||
|
'Count tags': 'countTags',
|
||||||
|
'Count relations': 'countRelations',
|
||||||
|
'Count comments': 'countComments',
|
||||||
|
'Workload': 'workload',
|
||||||
|
};
|
||||||
|
|
||||||
export default class KanbnBoardPanel {
|
export default class KanbnBoardPanel {
|
||||||
public static currentPanel: KanbnBoardPanel | undefined;
|
public static currentPanel: KanbnBoardPanel | undefined;
|
||||||
|
|
||||||
@ -63,6 +78,7 @@ export default class KanbnBoardPanel {
|
|||||||
hiddenColumns: index.options.hiddenColumns ?? [],
|
hiddenColumns: index.options.hiddenColumns ?? [],
|
||||||
startedColumns: index.options.startedColumns ?? [],
|
startedColumns: index.options.startedColumns ?? [],
|
||||||
completedColumns: index.options.completedColumns ?? [],
|
completedColumns: index.options.completedColumns ?? [],
|
||||||
|
columnSorting: index.options.columnSorting ?? {},
|
||||||
dateFormat: KanbnBoardPanel.currentPanel._kanbn.getDateFormat(index),
|
dateFormat: KanbnBoardPanel.currentPanel._kanbn.getDateFormat(index),
|
||||||
showBurndownButton: vscode.workspace.getConfiguration("kanbn").get("showBurndownButton"),
|
showBurndownButton: vscode.workspace.getConfiguration("kanbn").get("showBurndownButton"),
|
||||||
showSprintButton: vscode.workspace.getConfiguration("kanbn").get("showSprintButton"),
|
showSprintButton: vscode.workspace.getConfiguration("kanbn").get("showSprintButton"),
|
||||||
@ -157,6 +173,74 @@ export default class KanbnBoardPanel {
|
|||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Sort a column
|
||||||
|
case "kanbn.sortColumn":
|
||||||
|
// Load the index
|
||||||
|
const index = await this._kanbn.getIndex();
|
||||||
|
let customFields = [];
|
||||||
|
if ('customFields' in index.options) {
|
||||||
|
customFields = index.options.customFields.map(
|
||||||
|
(customField: { name: string, type: string }) => customField.name
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// Prompt for a task property to sort by
|
||||||
|
const sortBy: string = await vscode.window.showQuickPick(
|
||||||
|
[
|
||||||
|
'None',
|
||||||
|
...Object.keys(sortByFields),
|
||||||
|
...customFields,
|
||||||
|
],
|
||||||
|
{
|
||||||
|
placeHolder: 'Sort this column by...',
|
||||||
|
canPickMany: false,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (sortBy !== undefined) {
|
||||||
|
// Clear any saved sort settings for this column
|
||||||
|
if (sortBy === 'None') {
|
||||||
|
await this._kanbn.sort(message.columnName, [], false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prompt for sort direction and save settings
|
||||||
|
const sortDirection = await vscode.window.showQuickPick(
|
||||||
|
[
|
||||||
|
'Ascending',
|
||||||
|
'Descending',
|
||||||
|
],
|
||||||
|
{
|
||||||
|
placeHolder: 'Sort direction',
|
||||||
|
canPickMany: false,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (sortDirection !== undefined) {
|
||||||
|
const saveSort = await vscode.window.showQuickPick(
|
||||||
|
[
|
||||||
|
"Yes",
|
||||||
|
"No",
|
||||||
|
],
|
||||||
|
{
|
||||||
|
placeHolder: 'Save sort settings for this column?',
|
||||||
|
canPickMany: false,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (saveSort !== undefined) {
|
||||||
|
await this._kanbn.sort(
|
||||||
|
message.columnName,
|
||||||
|
[
|
||||||
|
{
|
||||||
|
field: sortBy in sortByFields ? sortByFields[sortBy] : sortBy,
|
||||||
|
order: sortDirection === 'Descending' ? 'descending' : 'ascending',
|
||||||
|
}
|
||||||
|
],
|
||||||
|
saveSort === 'Yes'
|
||||||
|
);
|
||||||
|
KanbnBoardPanel.update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
// Open a burndown chart
|
// Open a burndown chart
|
||||||
case "kanbn.burndown":
|
case "kanbn.burndown":
|
||||||
KanbnBurndownPanel.createOrShow(
|
KanbnBurndownPanel.createOrShow(
|
||||||
|
@ -17,6 +17,7 @@ function App() {
|
|||||||
const [hiddenColumns, setHiddenColumns] = useState([]);
|
const [hiddenColumns, setHiddenColumns] = useState([]);
|
||||||
const [startedColumns, setStartedColumns] = useState([]);
|
const [startedColumns, setStartedColumns] = useState([]);
|
||||||
const [completedColumns, setCompletedColumns] = useState([]);
|
const [completedColumns, setCompletedColumns] = useState([]);
|
||||||
|
const [columnSorting, setColumnSorting] = useState({});
|
||||||
const [dateFormat, setDateFormat] = useState('');
|
const [dateFormat, setDateFormat] = useState('');
|
||||||
const [task, setTask] = useState({});
|
const [task, setTask] = useState({});
|
||||||
const [tasks, setTasks] = useState({});
|
const [tasks, setTasks] = useState({});
|
||||||
@ -46,6 +47,7 @@ function App() {
|
|||||||
setHiddenColumns(event.data.hiddenColumns);
|
setHiddenColumns(event.data.hiddenColumns);
|
||||||
setStartedColumns(event.data.startedColumns);
|
setStartedColumns(event.data.startedColumns);
|
||||||
setCompletedColumns(event.data.completedColumns);
|
setCompletedColumns(event.data.completedColumns);
|
||||||
|
setColumnSorting(event.data.columnSorting);
|
||||||
setShowBurndownButton(event.data.showBurndownButton);
|
setShowBurndownButton(event.data.showBurndownButton);
|
||||||
setShowSprintButton(event.data.showSprintButton);
|
setShowSprintButton(event.data.showSprintButton);
|
||||||
|
|
||||||
@ -98,6 +100,7 @@ function App() {
|
|||||||
hiddenColumns={hiddenColumns}
|
hiddenColumns={hiddenColumns}
|
||||||
startedColumns={startedColumns}
|
startedColumns={startedColumns}
|
||||||
completedColumns={completedColumns}
|
completedColumns={completedColumns}
|
||||||
|
columnSorting={columnSorting}
|
||||||
dateFormat={dateFormat}
|
dateFormat={dateFormat}
|
||||||
showBurndownButton={showBurndownButton}
|
showBurndownButton={showBurndownButton}
|
||||||
showSprintButton={showSprintButton}
|
showSprintButton={showSprintButton}
|
||||||
|
@ -139,6 +139,7 @@ const Board = ({
|
|||||||
hiddenColumns,
|
hiddenColumns,
|
||||||
startedColumns,
|
startedColumns,
|
||||||
completedColumns,
|
completedColumns,
|
||||||
|
columnSorting,
|
||||||
dateFormat,
|
dateFormat,
|
||||||
showBurndownButton,
|
showBurndownButton,
|
||||||
showSprintButton,
|
showSprintButton,
|
||||||
@ -151,6 +152,7 @@ const Board = ({
|
|||||||
hiddenColumns: string[],
|
hiddenColumns: string[],
|
||||||
startedColumns: string[],
|
startedColumns: string[],
|
||||||
completedColumns: string[],
|
completedColumns: string[],
|
||||||
|
columnSorting: { [columnName: string]: { field: string, order: 'ascending' | 'descending' }[] },
|
||||||
dateFormat: string,
|
dateFormat: string,
|
||||||
showBurndownButton: boolean,
|
showBurndownButton: boolean,
|
||||||
showSprintButton: boolean,
|
showSprintButton: boolean,
|
||||||
@ -274,7 +276,7 @@ const Board = ({
|
|||||||
<span className="kanbn-column-count">{column.length || ''}</span>
|
<span className="kanbn-column-count">{column.length || ''}</span>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="kanbn-create-task-button"
|
className="kanbn-column-button kanbn-create-task-button"
|
||||||
title={`Create task in ${columnName}`}
|
title={`Create task in ${columnName}`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
vscode.postMessage({
|
vscode.postMessage({
|
||||||
@ -285,6 +287,30 @@ const Board = ({
|
|||||||
>
|
>
|
||||||
<i className="codicon codicon-add"></i>
|
<i className="codicon codicon-add"></i>
|
||||||
</button>
|
</button>
|
||||||
|
{((columnIsSorted, columnSortSettings) => (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={[
|
||||||
|
'kanbn-column-button',
|
||||||
|
'kanbn-sort-column-button',
|
||||||
|
columnIsSorted ? 'kanbn-column-sorted' : null
|
||||||
|
].filter(i => i).join(' ')}
|
||||||
|
title={`Sort ${columnName}${columnIsSorted
|
||||||
|
? `\nCurrently sorted by:\n${columnSortSettings.map(
|
||||||
|
sorter => `${sorter.field} (${sorter.order})`
|
||||||
|
).join('\n')}`
|
||||||
|
: ''
|
||||||
|
}`}
|
||||||
|
onClick={() => {
|
||||||
|
vscode.postMessage({
|
||||||
|
command: 'kanbn.sortColumn',
|
||||||
|
columnName
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<i className="codicon codicon-list-filter"></i>
|
||||||
|
</button>
|
||||||
|
))(columnName in columnSorting, columnSorting[columnName] || [])}
|
||||||
</h2>
|
</h2>
|
||||||
<div className="kanbn-column-task-list-container">
|
<div className="kanbn-column-task-list-container">
|
||||||
<Droppable droppableId={columnName} key={columnName}>
|
<Droppable droppableId={columnName} key={columnName}>
|
||||||
|
@ -117,36 +117,42 @@ Board styles
|
|||||||
margin-right: 0.5em;
|
margin-right: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.kanbn-create-task-button {
|
.kanbn-column-button {
|
||||||
position: relative;
|
position: relative;
|
||||||
top: -2px;
|
top: -2px;
|
||||||
left: -4px;
|
left: -4px;
|
||||||
float: right;
|
float: right;
|
||||||
border: 1px transparent solid;
|
|
||||||
outline: none;
|
outline: none;
|
||||||
color: var(--vscode-foreground);
|
border: 1px transparent solid;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
|
color: var(--vscode-button-foreground);
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
width: 16px;
|
width: 16px;
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
cursor: pointer;
|
|
||||||
border-radius: 1px;
|
border-radius: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.kanbn-create-task-button:focus {
|
.kanbn-column-button .codicon {
|
||||||
border-color: var(--vscode-foreground);
|
|
||||||
}
|
|
||||||
|
|
||||||
.kanbn-create-task-button:hover, .kanbn-create-task-button:active {
|
|
||||||
border: none;
|
|
||||||
outline: none;
|
|
||||||
color: var(--vscode-editor-background);
|
|
||||||
background-color: var(--vscode-foreground);
|
|
||||||
}
|
|
||||||
|
|
||||||
.kanbn-create-task-button .codicon {
|
|
||||||
font-size: 11px !important;
|
font-size: 11px !important;
|
||||||
|
font-weight: 900;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kanbn-column-button:focus {
|
||||||
|
border-color: var(--vscode-button-hoverBackground);
|
||||||
|
}
|
||||||
|
|
||||||
|
.kanbn-column-button:hover, .kanbn-column-button:active {
|
||||||
|
background-color: var(--vscode-button-hoverBackground);
|
||||||
|
}
|
||||||
|
|
||||||
|
.kanbn-column-button.kanbn-sort-column-button .codicon {
|
||||||
|
opacity: 0.5;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kanbn-column-button.kanbn-sort-column-button.kanbn-column-sorted .codicon {
|
||||||
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.kanbn-column-count {
|
.kanbn-column-count {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user