Add column sorting

This commit is contained in:
Gordon 2021-06-06 01:16:18 +01:00
parent d79f216687
commit f53db52672
5 changed files with 139 additions and 17 deletions

View File

@ -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`

View File

@ -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(

View File

@ -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}

View File

@ -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}>

View File

@ -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 {