Split out into separate classes
This commit is contained in:
parent
40632935ee
commit
878fcbba39
@ -1,36 +1,42 @@
|
|||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
|
|
||||||
export default class ReactPanel {
|
export default class KanbnBoardPanel {
|
||||||
public static currentPanel: ReactPanel | undefined;
|
public static currentPanel: KanbnBoardPanel | undefined;
|
||||||
|
|
||||||
private static readonly viewType = 'react';
|
private static readonly viewType = 'react';
|
||||||
|
|
||||||
private readonly _panel: vscode.WebviewPanel;
|
private readonly _panel: vscode.WebviewPanel;
|
||||||
private readonly _extensionPath: string;
|
private readonly _extensionPath: string;
|
||||||
|
private readonly _workspacePath: string;
|
||||||
private _disposables: vscode.Disposable[] = [];
|
private _disposables: vscode.Disposable[] = [];
|
||||||
|
|
||||||
public static createOrShow(extensionPath: string) {
|
public static createOrShow(extensionPath: string, workspacePath: string) {
|
||||||
const column = vscode.window.activeTextEditor ? vscode.window.activeTextEditor.viewColumn : undefined;
|
const column = vscode.window.activeTextEditor ? vscode.window.activeTextEditor.viewColumn : undefined;
|
||||||
|
|
||||||
// If we already have a panel, show it.
|
// If we already have a panel, show it.
|
||||||
// Otherwise, create a new panel.
|
// Otherwise, create a new panel.
|
||||||
if (ReactPanel.currentPanel) {
|
if (KanbnBoardPanel.currentPanel) {
|
||||||
ReactPanel.currentPanel._panel.reveal(column);
|
KanbnBoardPanel.currentPanel._panel.reveal(column);
|
||||||
} else {
|
} else {
|
||||||
ReactPanel.currentPanel = new ReactPanel(extensionPath, column || vscode.ViewColumn.One);
|
KanbnBoardPanel.currentPanel = new KanbnBoardPanel(
|
||||||
|
extensionPath,
|
||||||
|
workspacePath,
|
||||||
|
column || vscode.ViewColumn.One
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private constructor(extensionPath: string, column: vscode.ViewColumn) {
|
private constructor(extensionPath: string, workspacePath: string, column: vscode.ViewColumn) {
|
||||||
this._extensionPath = extensionPath;
|
this._extensionPath = extensionPath;
|
||||||
|
this._workspacePath = workspacePath;
|
||||||
|
|
||||||
// Create and show a new webview panel
|
// Create and show a new webview panel
|
||||||
this._panel = vscode.window.createWebviewPanel(ReactPanel.viewType, "React", column, {
|
this._panel = vscode.window.createWebviewPanel(KanbnBoardPanel.viewType, "Kanbn Board", column, {
|
||||||
// Enable javascript in the webview
|
// Enable javascript in the webview
|
||||||
enableScripts: true,
|
enableScripts: true,
|
||||||
|
|
||||||
// And restric the webview to only loading content from our extension's `media` directory.
|
// Restrict the webview to only loading content from our extension's `media` directory.
|
||||||
localResourceRoots: [
|
localResourceRoots: [
|
||||||
vscode.Uri.file(path.join(this._extensionPath, 'build'))
|
vscode.Uri.file(path.join(this._extensionPath, 'build'))
|
||||||
]
|
]
|
||||||
@ -46,19 +52,15 @@ export default class ReactPanel {
|
|||||||
// Handle messages from the webview
|
// Handle messages from the webview
|
||||||
this._panel.webview.onDidReceiveMessage(message => {
|
this._panel.webview.onDidReceiveMessage(message => {
|
||||||
switch (message.command) {
|
switch (message.command) {
|
||||||
case 'alert':
|
case 'error':
|
||||||
vscode.window.showErrorMessage(message.text);
|
vscode.window.showErrorMessage(message.text);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}, null, this._disposables);
|
}, null, this._disposables);
|
||||||
}
|
}
|
||||||
|
|
||||||
public doRefactor() {
|
|
||||||
this._panel.webview.postMessage({ command: 'refactor' });
|
|
||||||
}
|
|
||||||
|
|
||||||
public dispose() {
|
public dispose() {
|
||||||
ReactPanel.currentPanel = undefined;
|
KanbnBoardPanel.currentPanel = undefined;
|
||||||
|
|
||||||
// Clean up our resources
|
// Clean up our resources
|
||||||
this._panel.dispose();
|
this._panel.dispose();
|
||||||
@ -90,16 +92,14 @@ export default class ReactPanel {
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no">
|
<meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no">
|
||||||
<meta name="theme-color" content="#000000">
|
<meta name="theme-color" content="#000000">
|
||||||
<title>React App</title>
|
<title>Kanbn Board</title>
|
||||||
<link rel="stylesheet" type="text/css" href="${styleUri}">
|
<link rel="stylesheet" type="text/css" href="${styleUri}">
|
||||||
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src vscode-resource: https:; script-src 'nonce-${nonce}';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}';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="${vscode.Uri.file(path.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>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|
||||||
<script nonce="${nonce}" src="${scriptUri}"></script>
|
<script nonce="${nonce}" src="${scriptUri}"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>`;
|
</html>`;
|
41
ext-src/KanbnStatusBarItem.ts
Normal file
41
ext-src/KanbnStatusBarItem.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import * as vscode from 'vscode';
|
||||||
|
|
||||||
|
export default class KanbnStatusBarItem {
|
||||||
|
statusBarItem: vscode.StatusBarItem;
|
||||||
|
|
||||||
|
constructor(context: vscode.ExtensionContext) {
|
||||||
|
this.statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 0);
|
||||||
|
context.subscriptions.push(this.statusBarItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
async update(kanbn: typeof import('@basementuniverse/kanbn/src/main')): Promise<void> {
|
||||||
|
if (this.statusBarItem === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (await kanbn.initialised()) {
|
||||||
|
const status = await kanbn.status(true);
|
||||||
|
const text = [
|
||||||
|
`$(project) ${status.tasks}`
|
||||||
|
];
|
||||||
|
const tooltip = [
|
||||||
|
`${status.tasks} task${status.tasks === 1 ? '' : 's'}`
|
||||||
|
];
|
||||||
|
if ('startedTasks' in status) {
|
||||||
|
text.push(`$(play) ${status.startedTasks}`);
|
||||||
|
tooltip.push(`${status.startedTasks} started task${status.startedTasks === 1 ? '' : 's'}`);
|
||||||
|
}
|
||||||
|
if ('completedTasks' in status) {
|
||||||
|
text.push(`$(check) ${status.completedTasks}`);
|
||||||
|
tooltip.push(`${status.completedTasks} completed task${status.completedTasks === 1 ? '' : 's'}`);
|
||||||
|
}
|
||||||
|
this.statusBarItem.text = text.join(' ');
|
||||||
|
this.statusBarItem.tooltip = tooltip.join('\n');
|
||||||
|
this.statusBarItem.command = 'kanbn.board';
|
||||||
|
} else {
|
||||||
|
this.statusBarItem.text = '$(project) Not initialised';
|
||||||
|
this.statusBarItem.tooltip = 'Click to initialise';
|
||||||
|
this.statusBarItem.command = 'kanbn.init';
|
||||||
|
}
|
||||||
|
this.statusBarItem.show();
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,8 @@
|
|||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import ReactPanel from './ReactPanel';
|
import KanbnStatusBarItem from './KanbnStatusBarItem';
|
||||||
|
import KanbnBoardPanel from './KanbnBoardPanel';
|
||||||
|
|
||||||
let statusBarItem: vscode.StatusBarItem;
|
let kanbnStatusBarItem: KanbnStatusBarItem;
|
||||||
|
|
||||||
export async function activate(context: vscode.ExtensionContext) {
|
export async function activate(context: vscode.ExtensionContext) {
|
||||||
|
|
||||||
@ -40,7 +41,7 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||||||
name: newProjectName
|
name: newProjectName
|
||||||
});
|
});
|
||||||
vscode.window.showInformationMessage(`Initialised kanbn project '${newProjectName}'.`);
|
vscode.window.showInformationMessage(`Initialised kanbn project '${newProjectName}'.`);
|
||||||
updateStatusBarItem(kanbn);
|
kanbnStatusBarItem.update(kanbn);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -60,7 +61,7 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||||||
|
|
||||||
// If kanbn is initialised, view the kanbn board
|
// If kanbn is initialised, view the kanbn board
|
||||||
if (await kanbn.initialised()) {
|
if (await kanbn.initialised()) {
|
||||||
ReactPanel.createOrShow(context.extensionPath);
|
KanbnBoardPanel.createOrShow(context.extensionPath, kanbn.getMainFolder());
|
||||||
} else {
|
} else {
|
||||||
vscode.window.showErrorMessage('You need to initialise kanbn before viewing the kanbn board.');
|
vscode.window.showErrorMessage('You need to initialise kanbn before viewing the kanbn board.');
|
||||||
}
|
}
|
||||||
@ -74,36 +75,15 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||||||
const kanbn = await import('@basementuniverse/kanbn/src/main');
|
const kanbn = await import('@basementuniverse/kanbn/src/main');
|
||||||
|
|
||||||
// Create status bar item
|
// Create status bar item
|
||||||
statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 0);
|
kanbnStatusBarItem = new KanbnStatusBarItem(context);
|
||||||
context.subscriptions.push(statusBarItem);
|
kanbnStatusBarItem.update(kanbn);
|
||||||
updateStatusBarItem(kanbn);
|
|
||||||
|
|
||||||
// Initialise file watcher
|
// Initialise file watcher
|
||||||
const uri = vscode.workspace.workspaceFolders[0].uri.fsPath;
|
const uri = vscode.workspace.workspaceFolders[0].uri.fsPath;
|
||||||
const fileWatcher = vscode.workspace.createFileSystemWatcher(new vscode.RelativePattern(uri, '.kanbn/*'));
|
const fileWatcher = vscode.workspace.createFileSystemWatcher(new vscode.RelativePattern(uri, '.kanbn/*'));
|
||||||
fileWatcher.onDidChange(() => {
|
fileWatcher.onDidChange(() => {
|
||||||
updateStatusBarItem(kanbn);
|
kanbnStatusBarItem.update(kanbn);
|
||||||
// TODO update kanbn board
|
// TODO refresh kanbn board
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function deactivate(): void {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
async function updateStatusBarItem(kanbn: typeof import('@basementuniverse/kanbn/src/main')): Promise<void> {
|
|
||||||
if (statusBarItem === undefined) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const initialised = await kanbn.initialised();
|
|
||||||
const text = initialised ? await getStatusBarText(kanbn) : 'Not initialised';
|
|
||||||
statusBarItem.text = `$(project) ${text}`;
|
|
||||||
statusBarItem.command = initialised ? 'kanbn.board' : 'kanbn.init';
|
|
||||||
statusBarItem.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getStatusBarText(kanbn: typeof import('@basementuniverse/kanbn/src/main')): Promise<string> {
|
|
||||||
const status = await kanbn.status(true);
|
|
||||||
return Object.values(status.columnTasks).join(' / ');
|
|
||||||
}
|
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
import * as React from 'react';
|
|
||||||
import * as ReactDOM from 'react-dom';
|
|
||||||
import App from './App';
|
|
||||||
|
|
||||||
it('renders without crashing', () => {
|
|
||||||
const div = document.createElement('div');
|
|
||||||
ReactDOM.render(<App />, div);
|
|
||||||
ReactDOM.unmountComponentAtNode(div);
|
|
||||||
});
|
|
168
src/App.tsx
168
src/App.tsx
@ -1,147 +1,37 @@
|
|||||||
import React, { useState } from "react";
|
// import * as vscode from 'vscode';
|
||||||
import { DragDropContext, Draggable, Droppable } from "react-beautiful-dnd";
|
import Board from './Board';
|
||||||
import uuid from "uuid/v4";
|
import Header from './Header';
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
|
||||||
const itemsFromBackend = [
|
function App(props) {
|
||||||
{ id: uuid(), content: "First task" },
|
// const [cwd, setCwd] = useState('initialcwd');
|
||||||
{ id: uuid(), content: "Second task" },
|
// const [index, setIndex] = useState({});
|
||||||
{ id: uuid(), content: "Third task" },
|
// const [tasks, setTasks] = useState([]);
|
||||||
{ id: uuid(), content: "Fourth task" },
|
|
||||||
{ id: uuid(), content: "Fifth task" }
|
|
||||||
];
|
|
||||||
|
|
||||||
const columnsFromBackend = {
|
// useEffect(() => {
|
||||||
[uuid()]: {
|
// // process.chdir(vscode!.workspace.workspaceFolders[0].uri.fsPath);
|
||||||
name: "Requested",
|
// import('@basementuniverse/kanbn/src/main').then(kanbn => {
|
||||||
items: itemsFromBackend
|
// vscode.postMessage({
|
||||||
},
|
// command: 'error',
|
||||||
[uuid()]: {
|
// text: 'hello!'
|
||||||
name: "To do",
|
// });
|
||||||
items: []
|
// });
|
||||||
},
|
// });
|
||||||
[uuid()]: {
|
// console.log(vscode!.workspace.workspaceFolders[0].uri.fsPath);
|
||||||
name: "In Progress",
|
|
||||||
items: []
|
|
||||||
},
|
|
||||||
[uuid()]: {
|
|
||||||
name: "Done",
|
|
||||||
items: []
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const onDragEnd = (result, columns, setColumns) => {
|
// window.addEventListener('message', event => {
|
||||||
if (!result.destination) return;
|
// const message = event.data; // The JSON data our extension sent
|
||||||
const { source, destination } = result;
|
// switch (message.command) {
|
||||||
|
// case 'test':
|
||||||
|
// setCwd(message.cwd);
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
if (source.droppableId !== destination.droppableId) {
|
|
||||||
const sourceColumn = columns[source.droppableId];
|
|
||||||
const destColumn = columns[destination.droppableId];
|
|
||||||
const sourceItems = [...sourceColumn.items];
|
|
||||||
const destItems = [...destColumn.items];
|
|
||||||
const [removed] = sourceItems.splice(source.index, 1);
|
|
||||||
destItems.splice(destination.index, 0, removed);
|
|
||||||
setColumns({
|
|
||||||
...columns,
|
|
||||||
[source.droppableId]: {
|
|
||||||
...sourceColumn,
|
|
||||||
items: sourceItems
|
|
||||||
},
|
|
||||||
[destination.droppableId]: {
|
|
||||||
...destColumn,
|
|
||||||
items: destItems
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
const column = columns[source.droppableId];
|
|
||||||
const copiedItems = [...column.items];
|
|
||||||
const [removed] = copiedItems.splice(source.index, 1);
|
|
||||||
copiedItems.splice(destination.index, 0, removed);
|
|
||||||
setColumns({
|
|
||||||
...columns,
|
|
||||||
[source.droppableId]: {
|
|
||||||
...column,
|
|
||||||
items: copiedItems
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
const [columns, setColumns] = useState(columnsFromBackend);
|
|
||||||
return (
|
return (
|
||||||
<div style={{ display: "flex", justifyContent: "center", height: "100%" }}>
|
<div>
|
||||||
<DragDropContext
|
<Header />
|
||||||
onDragEnd={result => onDragEnd(result, columns, setColumns)}
|
<Board />
|
||||||
>
|
|
||||||
{Object.entries(columns).map(([columnId, column], index) => {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
alignItems: "center"
|
|
||||||
}}
|
|
||||||
key={columnId}
|
|
||||||
>
|
|
||||||
<h2>{column.name}</h2>
|
|
||||||
<div style={{ margin: 8 }}>
|
|
||||||
<Droppable droppableId={columnId} key={columnId}>
|
|
||||||
{(provided, snapshot) => {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
{...provided.droppableProps}
|
|
||||||
ref={provided.innerRef}
|
|
||||||
style={{
|
|
||||||
background: snapshot.isDraggingOver
|
|
||||||
? "lightblue"
|
|
||||||
: "lightgrey",
|
|
||||||
padding: 4,
|
|
||||||
width: 250,
|
|
||||||
minHeight: 500
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{column.items.map((item, index) => {
|
|
||||||
return (
|
|
||||||
<Draggable
|
|
||||||
key={item.id}
|
|
||||||
draggableId={item.id}
|
|
||||||
index={index}
|
|
||||||
>
|
|
||||||
{(provided, snapshot) => {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
ref={provided.innerRef}
|
|
||||||
{...provided.draggableProps}
|
|
||||||
{...provided.dragHandleProps}
|
|
||||||
style={{
|
|
||||||
userSelect: "none",
|
|
||||||
padding: 16,
|
|
||||||
margin: "0 0 8px 0",
|
|
||||||
minHeight: "50px",
|
|
||||||
backgroundColor: snapshot.isDragging
|
|
||||||
? "#263B4A"
|
|
||||||
: "#456C86",
|
|
||||||
color: "white",
|
|
||||||
...provided.draggableProps.style
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{item.content}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
</Draggable>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
{provided.placeholder}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
</Droppable>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</DragDropContext>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
149
src/Board.tsx
Normal file
149
src/Board.tsx
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import { DragDropContext, Draggable, Droppable } from "react-beautiful-dnd";
|
||||||
|
import uuid from "uuid/v4";
|
||||||
|
|
||||||
|
const itemsFromBackend = [
|
||||||
|
{ id: uuid(), content: "First task" },
|
||||||
|
{ id: uuid(), content: "Second task" },
|
||||||
|
{ id: uuid(), content: "Third task" },
|
||||||
|
{ id: uuid(), content: "Fourth task" },
|
||||||
|
{ id: uuid(), content: "Fifth task" }
|
||||||
|
];
|
||||||
|
|
||||||
|
const columnsFromBackend = {
|
||||||
|
[uuid()]: {
|
||||||
|
name: "Requested",
|
||||||
|
items: itemsFromBackend
|
||||||
|
},
|
||||||
|
[uuid()]: {
|
||||||
|
name: "To do",
|
||||||
|
items: []
|
||||||
|
},
|
||||||
|
[uuid()]: {
|
||||||
|
name: "In Progress",
|
||||||
|
items: []
|
||||||
|
},
|
||||||
|
[uuid()]: {
|
||||||
|
name: "Done",
|
||||||
|
items: []
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDragEnd = (result, columns, setColumns) => {
|
||||||
|
if (!result.destination) return;
|
||||||
|
const { source, destination } = result;
|
||||||
|
|
||||||
|
if (source.droppableId !== destination.droppableId) {
|
||||||
|
const sourceColumn = columns[source.droppableId];
|
||||||
|
const destColumn = columns[destination.droppableId];
|
||||||
|
const sourceItems = [...sourceColumn.items];
|
||||||
|
const destItems = [...destColumn.items];
|
||||||
|
const [removed] = sourceItems.splice(source.index, 1);
|
||||||
|
destItems.splice(destination.index, 0, removed);
|
||||||
|
setColumns({
|
||||||
|
...columns,
|
||||||
|
[source.droppableId]: {
|
||||||
|
...sourceColumn,
|
||||||
|
items: sourceItems
|
||||||
|
},
|
||||||
|
[destination.droppableId]: {
|
||||||
|
...destColumn,
|
||||||
|
items: destItems
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const column = columns[source.droppableId];
|
||||||
|
const copiedItems = [...column.items];
|
||||||
|
const [removed] = copiedItems.splice(source.index, 1);
|
||||||
|
copiedItems.splice(destination.index, 0, removed);
|
||||||
|
setColumns({
|
||||||
|
...columns,
|
||||||
|
[source.droppableId]: {
|
||||||
|
...column,
|
||||||
|
items: copiedItems
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function Board() {
|
||||||
|
const [columns, setColumns] = useState(columnsFromBackend);
|
||||||
|
return (
|
||||||
|
<div style={{ display: "flex", justifyContent: "center", height: "100%" }}>
|
||||||
|
<DragDropContext
|
||||||
|
onDragEnd={result => onDragEnd(result, columns, setColumns)}
|
||||||
|
>
|
||||||
|
{Object.entries(columns).map(([columnId, column], index) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
alignItems: "center"
|
||||||
|
}}
|
||||||
|
key={columnId}
|
||||||
|
>
|
||||||
|
<h2>{column.name}</h2>
|
||||||
|
<div style={{ margin: 8 }}>
|
||||||
|
<Droppable droppableId={columnId} key={columnId}>
|
||||||
|
{(provided, snapshot) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
{...provided.droppableProps}
|
||||||
|
ref={provided.innerRef}
|
||||||
|
style={{
|
||||||
|
background: snapshot.isDraggingOver
|
||||||
|
? "lightblue"
|
||||||
|
: "lightgrey",
|
||||||
|
padding: 4,
|
||||||
|
width: 250,
|
||||||
|
minHeight: 500
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{column.items.map((item, index) => {
|
||||||
|
return (
|
||||||
|
<Draggable
|
||||||
|
key={item.id}
|
||||||
|
draggableId={item.id}
|
||||||
|
index={index}
|
||||||
|
>
|
||||||
|
{(provided, snapshot) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
ref={provided.innerRef}
|
||||||
|
{...provided.draggableProps}
|
||||||
|
{...provided.dragHandleProps}
|
||||||
|
style={{
|
||||||
|
userSelect: "none",
|
||||||
|
padding: 16,
|
||||||
|
margin: "0 0 8px 0",
|
||||||
|
minHeight: "50px",
|
||||||
|
backgroundColor: snapshot.isDragging
|
||||||
|
? "#263B4A"
|
||||||
|
: "#456C86",
|
||||||
|
color: "white",
|
||||||
|
...provided.draggableProps.style
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{item.content}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</Draggable>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
{provided.placeholder}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</Droppable>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</DragDropContext>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Board;
|
11
src/Header.tsx
Normal file
11
src/Header.tsx
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
|
||||||
|
function Header() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
Header
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Header;
|
Loading…
x
Reference in New Issue
Block a user