2024-07-12 00:43:58 +02:00
|
|
|
import * as React from "bloatless-react";
|
|
|
|
|
|
|
|
|
|
import { Chat, MessageObject } from "../../Model/chatModel";
|
|
|
|
|
|
|
|
|
|
import { ObjectEntryView } from "./objectEntryView";
|
2024-07-12 01:19:16 +02:00
|
|
|
import { PlaceholderView } from "./placeholderView";
|
2024-07-12 14:30:30 +02:00
|
|
|
import { RenameView } from "../renameView";
|
2024-07-12 00:43:58 +02:00
|
|
|
|
|
|
|
|
interface KanbanBoard {
|
2024-07-12 14:30:30 +02:00
|
|
|
category: string;
|
2024-07-12 19:04:57 +02:00
|
|
|
items: React.ListState<KanbanBoardItem>;
|
2024-07-12 02:02:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
interface KanbanBoardItem {
|
|
|
|
|
priority: number;
|
|
|
|
|
messageObject: MessageObject;
|
2024-07-12 00:43:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function KanbanView(
|
|
|
|
|
chat: Chat,
|
|
|
|
|
selectedObject: React.State<MessageObject | undefined>,
|
|
|
|
|
isShowingObjectModal: React.State<boolean>
|
|
|
|
|
) {
|
|
|
|
|
const boards = new React.MapState<KanbanBoard>();
|
2024-07-12 19:04:57 +02:00
|
|
|
const sortedBoardNames = React.createProxyState([boards], () =>
|
|
|
|
|
[...boards.value.values()]
|
|
|
|
|
.map((board) => board.category)
|
|
|
|
|
.sort((a, b) => a.localeCompare(b))
|
|
|
|
|
);
|
2024-07-12 00:43:58 +02:00
|
|
|
|
2024-07-12 19:04:57 +02:00
|
|
|
chat.objects.handleAddition((messageObject) => {
|
|
|
|
|
const latest = chat.getMostRecentContent(messageObject);
|
|
|
|
|
if (!latest) return;
|
|
|
|
|
if (!latest.categoryName) return;
|
|
|
|
|
|
|
|
|
|
const categoryName = latest.categoryName!;
|
|
|
|
|
if (!boards.value.has(categoryName)) {
|
|
|
|
|
const listState = new React.ListState<KanbanBoardItem>();
|
|
|
|
|
listState.subscribeSilent(() => {
|
|
|
|
|
if (listState.value.size != 0) return;
|
|
|
|
|
boards.remove(categoryName);
|
|
|
|
|
});
|
2024-07-12 00:43:58 +02:00
|
|
|
|
2024-07-12 19:04:57 +02:00
|
|
|
boards.set(categoryName, {
|
|
|
|
|
category: categoryName,
|
|
|
|
|
items: listState,
|
|
|
|
|
});
|
|
|
|
|
}
|
2024-07-12 00:43:58 +02:00
|
|
|
|
2024-07-12 19:04:57 +02:00
|
|
|
const boardItem: KanbanBoardItem = {
|
|
|
|
|
priority: latest.priority ?? 0,
|
|
|
|
|
messageObject,
|
|
|
|
|
};
|
|
|
|
|
boards.value.get(categoryName)?.items.add(boardItem);
|
2024-07-12 00:43:58 +02:00
|
|
|
|
2024-07-12 19:04:57 +02:00
|
|
|
chat.objects.handleRemoval(messageObject, () => {
|
|
|
|
|
boards.value.get(categoryName)?.items.remove(boardItem);
|
2024-07-12 00:43:58 +02:00
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
2024-07-12 19:04:57 +02:00
|
|
|
const boardToBoardView: React.StateItemConverter<KanbanBoard> = (board) => {
|
|
|
|
|
const view = KanbanBoardView(
|
|
|
|
|
chat,
|
|
|
|
|
board,
|
|
|
|
|
selectedObject,
|
|
|
|
|
isShowingObjectModal
|
|
|
|
|
);
|
|
|
|
|
sortedBoardNames.subscribe((sortedBoardNames) => {
|
|
|
|
|
view.style.order = sortedBoardNames.indexOf(board.category);
|
|
|
|
|
});
|
|
|
|
|
return view;
|
|
|
|
|
};
|
2024-07-12 00:43:58 +02:00
|
|
|
|
|
|
|
|
return (
|
2024-07-12 19:04:57 +02:00
|
|
|
<div
|
|
|
|
|
class="flex-row large-gap width-100 height-100 scroll-v scroll-h padding"
|
|
|
|
|
children:append={[boards, boardToBoardView]}
|
|
|
|
|
></div>
|
2024-07-12 00:43:58 +02:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function KanbanBoardView(
|
|
|
|
|
chat: Chat,
|
|
|
|
|
kanbanBoard: KanbanBoard,
|
|
|
|
|
selectedObject: React.State<MessageObject | undefined>,
|
|
|
|
|
isShowingObjectModal: React.State<boolean>
|
|
|
|
|
) {
|
2024-07-12 14:30:30 +02:00
|
|
|
const editingCategory = new React.State(kanbanBoard.category);
|
2024-07-12 01:54:53 +02:00
|
|
|
|
|
|
|
|
function renameBoard() {
|
2024-07-12 19:04:57 +02:00
|
|
|
kanbanBoard.items.value.forEach((kanbanBoardItem) => {
|
2024-07-12 02:02:49 +02:00
|
|
|
const { messageObject } = kanbanBoardItem;
|
2024-07-12 01:54:53 +02:00
|
|
|
const latest = chat.getMostRecentContent(messageObject);
|
2024-07-12 14:30:30 +02:00
|
|
|
latest.categoryName = editingCategory.value;
|
2024-07-12 01:54:53 +02:00
|
|
|
chat.addObjectAndSend(messageObject);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-12 01:05:00 +02:00
|
|
|
function dragOver(event: DragEvent) {
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function drop(event: DragEvent) {
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
var id = event.dataTransfer?.getData("text");
|
|
|
|
|
if (!id) return;
|
|
|
|
|
|
|
|
|
|
const messageObject = chat.objects.value.get(id);
|
|
|
|
|
if (!messageObject) return;
|
|
|
|
|
|
|
|
|
|
const latest = chat.getMostRecentContent(messageObject);
|
2024-07-12 14:30:30 +02:00
|
|
|
latest.categoryName = kanbanBoard.category;
|
2024-07-12 01:05:00 +02:00
|
|
|
chat.addObjectAndSend(messageObject);
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-12 19:04:57 +02:00
|
|
|
const itemToViewEntry: React.StateItemConverter<KanbanBoardItem> = (
|
|
|
|
|
kanbanBoardItem
|
|
|
|
|
) => {
|
|
|
|
|
const view = ObjectEntryView(
|
|
|
|
|
chat,
|
|
|
|
|
kanbanBoardItem.messageObject,
|
|
|
|
|
selectedObject,
|
|
|
|
|
isShowingObjectModal
|
|
|
|
|
);
|
|
|
|
|
view.style.order = kanbanBoardItem.priority * -1;
|
|
|
|
|
return view;
|
|
|
|
|
};
|
|
|
|
|
|
2024-07-12 00:43:58 +02:00
|
|
|
return (
|
2024-07-12 01:05:00 +02:00
|
|
|
<div
|
2024-07-12 14:30:30 +02:00
|
|
|
class="flex-column flex-no object-entry-wide"
|
2024-07-12 01:05:00 +02:00
|
|
|
on:dragover={dragOver}
|
|
|
|
|
on:drop={drop}
|
|
|
|
|
>
|
2024-07-12 14:30:30 +02:00
|
|
|
{RenameView(editingCategory, kanbanBoard.category, renameBoard)}
|
2024-07-12 00:43:58 +02:00
|
|
|
<hr></hr>
|
2024-07-12 19:04:57 +02:00
|
|
|
<div
|
|
|
|
|
class="flex-column gap padding-bottom"
|
|
|
|
|
children:append={[kanbanBoard.items, itemToViewEntry]}
|
|
|
|
|
></div>
|
2024-07-12 00:43:58 +02:00
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|