Files
CT/src/Views/Objects/kanbanView.tsx
T

143 lines
3.8 KiB
TypeScript
Raw Normal View History

2024-07-12 00:43:58 +02:00
import * as React from "bloatless-react";
import { Chat, MessageObject } from "../../Model/chatModel";
import { ObjectEntryView } from "./objectEntryView";
import { ObjectGridView } from "./objectGridView";
2024-07-12 01:19:16 +02:00
import { PlaceholderView } from "./placeholderView";
2024-07-12 00:43:58 +02:00
import { translation } from "../../translations";
interface KanbanBoard {
title: string;
2024-07-12 02:02:49 +02:00
items: KanbanBoardItem[];
}
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>();
chat.objects.subscribe(() => {
boards.clear();
chat.objects.value.forEach((messageObject) => {
const latest = chat.getMostRecentContent(messageObject);
if (!latest.categoryName) return;
const boardTitle = latest.categoryName;
if (!boards.value.has(boardTitle))
boards.set(boardTitle, { title: boardTitle, items: [] });
2024-07-12 02:02:49 +02:00
boards.value.get(boardTitle)?.items.push({
priority: latest.priority ?? 0,
messageObject,
});
2024-07-12 00:43:58 +02:00
});
});
2024-07-12 01:19:16 +02:00
const content = React.createProxyState([chat.objects], () =>
boards.value.size == 0 ? (
PlaceholderView()
) : (
<div class="flex-row large-gap width-100 height-100 scroll-v scroll-h padding">
{...[...boards.value.values()]
.sort((a, b) => a.title.localeCompare(b.title))
.map((board) =>
KanbanBoardView(chat, board, selectedObject, isShowingObjectModal)
)}
</div>
)
);
2024-07-12 00:43:58 +02:00
return (
<div class="width-100 height-100 scroll-no" children:set={content}></div>
);
}
function KanbanBoardView(
chat: Chat,
kanbanBoard: KanbanBoard,
selectedObject: React.State<MessageObject | undefined>,
isShowingObjectModal: React.State<boolean>
) {
2024-07-12 01:54:53 +02:00
const editingBoardTitle = new React.State(kanbanBoard.title);
const isEditing = new React.State(false);
const cannotRename = React.createProxyState(
[editingBoardTitle],
() =>
editingBoardTitle.value == kanbanBoard.title ||
editingBoardTitle.value == ""
);
function renameBoard() {
2024-07-12 02:02:49 +02:00
kanbanBoard.items.forEach((kanbanBoardItem) => {
const { messageObject } = kanbanBoardItem;
2024-07-12 01:54:53 +02:00
const latest = chat.getMostRecentContent(messageObject);
latest.categoryName = editingBoardTitle.value;
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);
latest.categoryName = kanbanBoard.title;
chat.addObjectAndSend(messageObject);
}
2024-07-12 01:54:53 +02:00
const titleInput = (
<input bind:value={editingBoardTitle} on:enter={renameBoard}></input>
);
2024-07-12 00:43:58 +02:00
return (
2024-07-12 01:05:00 +02:00
<div
class="flex-column flex-no"
style="min-width: 280px"
on:dragover={dragOver}
on:drop={drop}
>
2024-07-12 01:54:53 +02:00
<div class="flex-row align-center justify-apart">
{titleInput}
<button
class="primary"
aria-label={translation.rename}
on:click={renameBoard}
toggle:disabled={cannotRename}
>
<span class="icon">edit</span>
</button>
</div>
2024-07-12 00:43:58 +02:00
<hr></hr>
<div class="flex-column gap padding-bottom">
2024-07-12 02:02:49 +02:00
{...kanbanBoard.items
.sort((a, b) => b.priority - a.priority)
.map((kanbanBoardItem) =>
ObjectEntryView(
chat,
kanbanBoardItem.messageObject,
selectedObject,
isShowingObjectModal
)
)}
2024-07-12 00:43:58 +02:00
</div>
</div>
);
}