From d2f4c63a9dc3136a3ce8f0b2c6aacbc05d46979a Mon Sep 17 00:00:00 2001 From: marlon-erler Date: Fri, 12 Jul 2024 00:43:58 +0200 Subject: [PATCH] add kanban --- dist/index.js | 321 ++++++++++-------- dist/styles.css | 4 + src/Tabs/messageTab.tsx | 4 +- src/Views/Objects/kanbanView.tsx | 73 ++++ src/Views/Objects/noteObjectsView.tsx | 1 - src/Views/Objects/objectGridView.tsx | 3 +- .../{chatObjectView.tsx => objectPane.tsx} | 13 +- src/translations.ts | 3 + 8 files changed, 268 insertions(+), 154 deletions(-) create mode 100644 src/Views/Objects/kanbanView.tsx rename src/Views/Objects/{chatObjectView.tsx => objectPane.tsx} (89%) diff --git a/dist/index.js b/dist/index.js index 4fa64b72..1da95fec 100644 --- a/dist/index.js +++ b/dist/index.js @@ -487,6 +487,7 @@ untitledObject: "Untitled Object", viewAll: "All", viewNotes: "Notes", + viewKanban: "Kanban", noObjects: "No objects", noNotes: "No notes", objectTitle: "Object title", @@ -573,6 +574,7 @@ untitledObject: "Sin T\xEDtulo", viewAll: "Todos", viewNotes: "Notas", + viewKanban: "Kanban", noObjects: "Sin objetos", noNotes: "Sin notas", objectTitle: "T\xEDtulo", @@ -657,6 +659,7 @@ untitledObject: "Unbenannt", viewAll: "Alle", viewNotes: "Notizen", + viewKanban: "Kanban", noObjects: "Keine Objekte", noNotes: "Keine Notizen", objectTitle: "Titel", @@ -1244,6 +1247,136 @@ connect(); } + // src/Views/Chat/chatOptionModal.tsx + function ChatOptionModal(chat, isPresented) { + function closeModal() { + isPresented.value = false; + } + function deleteChat() { + chat.deleteSelf(); + closeModal(); + closeChatView(); + } + const shouldShowKey = new State(false); + const inputType = createProxyState( + [shouldShowKey], + () => shouldShowKey.value == true ? "text" : "password" + ); + const secondaryChannelConverter = (secondaryChannel) => { + function remove() { + chat.removeSecondaryChannel(secondaryChannel); + } + return /* @__PURE__ */ createElement("div", { class: "tile width-input padding-0" }, /* @__PURE__ */ createElement("div", { class: "flex-row justify-apart align-center" }, /* @__PURE__ */ createElement("b", { class: "padding-h" }, secondaryChannel), /* @__PURE__ */ createElement( + "button", + { + class: "danger", + "aria-label": translation.removeSecondaryChannel, + "on:click": remove + }, + /* @__PURE__ */ createElement("span", { class: "icon" }, "delete") + ))); + }; + return /* @__PURE__ */ createElement("div", { class: "modal", "toggle:open": isPresented }, /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("main", null, /* @__PURE__ */ createElement("h2", null, translation.configureChatTitle), /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("label", { class: "tile" }, /* @__PURE__ */ createElement("span", { class: "icon" }, "forum"), /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("span", null, translation.primaryChannel), /* @__PURE__ */ createElement( + "input", + { + "bind:value": chat.primaryChannelInput, + placeholder: translation.primaryChannelPlaceholder, + "on:enter": chat.setChannel + } + ))), /* @__PURE__ */ createElement("div", { class: "flex-row width-input" }, /* @__PURE__ */ createElement( + "button", + { + "aria-label": translation.undoChanges, + class: "flex justify-center", + "on:click": chat.undoChannelChange, + "toggle:disabled": chat.cannotUndoChannel + }, + /* @__PURE__ */ createElement("span", { class: "icon" }, "undo") + ), /* @__PURE__ */ createElement( + "button", + { + "aria-label": translation.set, + class: "flex justify-center primary", + "on:click": chat.setChannel, + "toggle:disabled": chat.cannotSetChannel + }, + /* @__PURE__ */ createElement("span", { class: "icon" }, "check") + ))), /* @__PURE__ */ createElement("hr", null), /* @__PURE__ */ createElement("div", { class: "flex-row margin-bottom width-input" }, /* @__PURE__ */ createElement( + "input", + { + "aria-label": translation.secondaryChannel, + placeholder: translation.secondaryChannelPlaceholder, + "bind:value": chat.newSecondaryChannelName, + "on:enter": chat.addSecondaryChannel + } + ), /* @__PURE__ */ createElement( + "button", + { + class: "primary", + "toggle:disabled": chat.cannotAddSecondaryChannel, + "aria-label": translation.addSecondaryChannel, + "on:click": chat.addSecondaryChannel + }, + /* @__PURE__ */ createElement("span", { class: "icon" }, "add") + )), /* @__PURE__ */ createElement( + "div", + { + class: "flex-column gap", + "children:prepend": [ + chat.secondaryChannels, + secondaryChannelConverter + ] + } + ), /* @__PURE__ */ createElement("hr", null), /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("label", { class: "tile" }, /* @__PURE__ */ createElement("span", { class: "icon" }, "key"), /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("span", null, translation.encryptionKey), /* @__PURE__ */ createElement( + "input", + { + placeholder: translation.encryptionKeyPlaceholder, + "bind:value": chat.encryptionKey, + "set:type": inputType + } + ))), /* @__PURE__ */ createElement("label", { class: "inline margin-0" }, /* @__PURE__ */ createElement("input", { type: "checkbox", "bind:checked": shouldShowKey }), translation.showKey)), /* @__PURE__ */ createElement("hr", null), /* @__PURE__ */ createElement("div", { class: "flex-column gap width-input" }, /* @__PURE__ */ createElement("button", { "on:click": chat.resendObjects }, translation.resendObjects, /* @__PURE__ */ createElement("span", { class: "icon" }, "replay"))), /* @__PURE__ */ createElement("hr", null), /* @__PURE__ */ createElement("div", { class: "flex-column gap width-input" }, /* @__PURE__ */ createElement( + "button", + { + class: "danger", + "on:click": chat.clearObjects, + "toggle:disabled": chat.cannotClearObjects + }, + translation.clearObjects, + /* @__PURE__ */ createElement("span", { class: "icon" }, "deployed_code") + ), /* @__PURE__ */ createElement( + "button", + { + class: "danger", + "on:click": chat.clearMessages, + "toggle:disabled": chat.cannotClearMessages + }, + translation.clearChatMessages, + /* @__PURE__ */ createElement("span", { class: "icon" }, "chat_error") + ), /* @__PURE__ */ createElement("button", { class: "danger", "on:click": deleteChat }, translation.removeChat, /* @__PURE__ */ createElement("span", { class: "icon" }, "delete_forever")))), /* @__PURE__ */ createElement("button", { "on:click": closeModal }, translation.close, /* @__PURE__ */ createElement("span", { class: "icon" }, "close")))); + } + + // src/Views/Chat/messageComposer.tsx + function MessageComposer(chat) { + return /* @__PURE__ */ createElement("div", { class: "flex-row width-100" }, " ", /* @__PURE__ */ createElement( + "input", + { + class: "width-100 flex-1", + style: "max-width: unset", + placeholder: translation.composerPlaceholder, + "bind:value": chat.composingMessage, + "on:enter": chat.sendMessageFromComposer + } + ), /* @__PURE__ */ createElement( + "button", + { + class: "primary", + "on:click": chat.sendMessageFromComposer, + "toggle:disabled": chat.cannotSendMessage + }, + /* @__PURE__ */ createElement("span", { class: "icon" }, "send") + )); + } + // src/icons.ts var icons = { objectTitle: "label", @@ -1296,7 +1429,7 @@ return messageObjects.value.size == 0 ? /* @__PURE__ */ createElement("div", { class: "flex-column width-100 height-100 align-center justify-center secondary" }, placeholderText) : /* @__PURE__ */ createElement( "div", { - class: "grid gap padding", + class: "width-100 grid gap padding scroll-v", style: "grid-template-columns: repeat(auto-fill, minmax(170px, 1fr))", "children:prepend": [messageObjects, objectConverter] } @@ -1318,6 +1451,41 @@ return /* @__PURE__ */ createElement("div", { class: "width-100 height-100", "children:set": content }); } + // src/Views/Objects/kanbanView.tsx + function KanbanView(chat, selectedObject, isShowingObjectModal) { + const boards = new MapState(); + 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: [] }); + boards.value.get(boardTitle)?.items.push(messageObject); + }); + }); + const converter = (board) => KanbanBoardView(chat, board, selectedObject, isShowingObjectModal); + const content = createProxyState([chat.objects], () => /* @__PURE__ */ createElement( + "div", + { + class: "flex-row large-gap width-100 height-100 scroll-v scroll-h padding", + "children:append": [boards, converter] + } + )); + return /* @__PURE__ */ createElement("div", { class: "width-100 height-100 scroll-no", "children:set": content }); + } + function KanbanBoardView(chat, kanbanBoard, selectedObject, isShowingObjectModal) { + return /* @__PURE__ */ createElement("div", { class: "flex-column flex-no", style: "min-width: 280px" }, /* @__PURE__ */ createElement("b", { class: "flex-row width-100" }, kanbanBoard.title), /* @__PURE__ */ createElement("hr", null), /* @__PURE__ */ createElement("div", { class: "flex-column gap padding-bottom" }, ...kanbanBoard.items.map( + (messageObject) => ObjectEntryView( + chat, + messageObject, + selectedObject, + isShowingObjectModal + ) + ))); + } + // src/Views/Objects/noteObjectsView.tsx function NoteObjectsView(chat, selectedObject, isShowingObjectModal) { const notes = new ListState(); @@ -1448,12 +1616,13 @@ ))), /* @__PURE__ */ createElement("hr", null), /* @__PURE__ */ createElement("label", { class: "tile" }, /* @__PURE__ */ createElement("span", { class: "icon" }, icons.date), /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("span", null, translation.date), /* @__PURE__ */ createElement("input", { type: "date", "bind:value": editingDate }))), /* @__PURE__ */ createElement("label", { class: "tile" }, /* @__PURE__ */ createElement("span", { class: "icon" }, icons.time), /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("span", null, translation.time), /* @__PURE__ */ createElement("input", { type: "time", "bind:value": editingTime }))), /* @__PURE__ */ createElement("hr", null), /* @__PURE__ */ createElement("button", { class: "danger width-input", "on:click": deleteAndClose }, translation.deleteObject, /* @__PURE__ */ createElement("span", { class: "icon" }, "delete")))), /* @__PURE__ */ createElement("div", { class: "flex-row" }, /* @__PURE__ */ createElement("button", { class: "flex-1 width-100 danger", "on:click": closeModal }, translation.discard), /* @__PURE__ */ createElement("button", { class: "flex-1 width-100 primary", "on:click": saveAndClose }, translation.save, /* @__PURE__ */ createElement("span", { class: "icon" }, "save"))))); } - // src/Views/Objects/chatObjectView.tsx + // src/Views/Objects/objectPane.tsx var viewTypes = { all: [translation.viewAll, "grid_view"], - notes: [translation.viewNotes, icons.noteContent] + notes: [translation.viewNotes, icons.noteContent], + kanban: [translation.viewKanban, "view_kanban"] }; - function ChatObjectView(chat) { + function ObjectPane(chat) { const isShowingObjectModal = new State(false); const selectedObject = new State(void 0); const objectModal = createProxyState( @@ -1473,6 +1642,8 @@ switch (selectedViewType.value) { case "notes": return NoteObjectsView; + case "kanban": + return KanbanView; default: return AllObjectsView; } @@ -1485,7 +1656,7 @@ selectedObject.value = newObject; isShowingObjectModal.value = true; } - return /* @__PURE__ */ createElement("div", { class: "chat-object-view flex-column" }, /* @__PURE__ */ createElement("div", { class: "flex-row align-center border-bottom" }, /* @__PURE__ */ createElement( + return /* @__PURE__ */ createElement("div", { class: "chat-object-view flex-column scroll-no" }, /* @__PURE__ */ createElement("div", { class: "flex-row align-center border-bottom" }, /* @__PURE__ */ createElement( "button", { class: "primary height-100", @@ -1495,13 +1666,7 @@ /* @__PURE__ */ createElement("span", { class: "icon" }, "add") ), /* @__PURE__ */ createElement("div", { class: "padding-sm flex flex-row gap justify-center scroll-h width-100" }, ...Object.keys(viewTypes).map( (key) => ViewTypeToggle(key, selectedViewType) - )), /* @__PURE__ */ createElement("button", { class: "height-100", disabled: true }, /* @__PURE__ */ createElement("span", { class: "icon" }, "visibility"))), /* @__PURE__ */ createElement( - "div", - { - class: "width-100 height-100 flex-1 scroll-h", - "children:set": mainView - } - ), /* @__PURE__ */ createElement("div", { "children:set": objectModal })); + )), /* @__PURE__ */ createElement("button", { class: "height-100", disabled: true }, /* @__PURE__ */ createElement("span", { class: "icon" }, "visibility"))), /* @__PURE__ */ createElement("div", { class: "width-100 height-100 flex scroll-no", "children:set": mainView }), /* @__PURE__ */ createElement("div", { "children:set": objectModal })); } function ViewTypeToggle(key, selection) { const [label, icon] = viewTypes[key]; @@ -1515,136 +1680,6 @@ return /* @__PURE__ */ createElement("button", { "aria-label": label, "on:click": select, "toggle:selected": isSelected }, /* @__PURE__ */ createElement("span", { class: "icon" }, icon)); } - // src/Views/Chat/chatOptionModal.tsx - function ChatOptionModal(chat, isPresented) { - function closeModal() { - isPresented.value = false; - } - function deleteChat() { - chat.deleteSelf(); - closeModal(); - closeChatView(); - } - const shouldShowKey = new State(false); - const inputType = createProxyState( - [shouldShowKey], - () => shouldShowKey.value == true ? "text" : "password" - ); - const secondaryChannelConverter = (secondaryChannel) => { - function remove() { - chat.removeSecondaryChannel(secondaryChannel); - } - return /* @__PURE__ */ createElement("div", { class: "tile width-input padding-0" }, /* @__PURE__ */ createElement("div", { class: "flex-row justify-apart align-center" }, /* @__PURE__ */ createElement("b", { class: "padding-h" }, secondaryChannel), /* @__PURE__ */ createElement( - "button", - { - class: "danger", - "aria-label": translation.removeSecondaryChannel, - "on:click": remove - }, - /* @__PURE__ */ createElement("span", { class: "icon" }, "delete") - ))); - }; - return /* @__PURE__ */ createElement("div", { class: "modal", "toggle:open": isPresented }, /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("main", null, /* @__PURE__ */ createElement("h2", null, translation.configureChatTitle), /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("label", { class: "tile" }, /* @__PURE__ */ createElement("span", { class: "icon" }, "forum"), /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("span", null, translation.primaryChannel), /* @__PURE__ */ createElement( - "input", - { - "bind:value": chat.primaryChannelInput, - placeholder: translation.primaryChannelPlaceholder, - "on:enter": chat.setChannel - } - ))), /* @__PURE__ */ createElement("div", { class: "flex-row width-input" }, /* @__PURE__ */ createElement( - "button", - { - "aria-label": translation.undoChanges, - class: "flex justify-center", - "on:click": chat.undoChannelChange, - "toggle:disabled": chat.cannotUndoChannel - }, - /* @__PURE__ */ createElement("span", { class: "icon" }, "undo") - ), /* @__PURE__ */ createElement( - "button", - { - "aria-label": translation.set, - class: "flex justify-center primary", - "on:click": chat.setChannel, - "toggle:disabled": chat.cannotSetChannel - }, - /* @__PURE__ */ createElement("span", { class: "icon" }, "check") - ))), /* @__PURE__ */ createElement("hr", null), /* @__PURE__ */ createElement("div", { class: "flex-row margin-bottom width-input" }, /* @__PURE__ */ createElement( - "input", - { - "aria-label": translation.secondaryChannel, - placeholder: translation.secondaryChannelPlaceholder, - "bind:value": chat.newSecondaryChannelName, - "on:enter": chat.addSecondaryChannel - } - ), /* @__PURE__ */ createElement( - "button", - { - class: "primary", - "toggle:disabled": chat.cannotAddSecondaryChannel, - "aria-label": translation.addSecondaryChannel, - "on:click": chat.addSecondaryChannel - }, - /* @__PURE__ */ createElement("span", { class: "icon" }, "add") - )), /* @__PURE__ */ createElement( - "div", - { - class: "flex-column gap", - "children:prepend": [ - chat.secondaryChannels, - secondaryChannelConverter - ] - } - ), /* @__PURE__ */ createElement("hr", null), /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("label", { class: "tile" }, /* @__PURE__ */ createElement("span", { class: "icon" }, "key"), /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("span", null, translation.encryptionKey), /* @__PURE__ */ createElement( - "input", - { - placeholder: translation.encryptionKeyPlaceholder, - "bind:value": chat.encryptionKey, - "set:type": inputType - } - ))), /* @__PURE__ */ createElement("label", { class: "inline margin-0" }, /* @__PURE__ */ createElement("input", { type: "checkbox", "bind:checked": shouldShowKey }), translation.showKey)), /* @__PURE__ */ createElement("hr", null), /* @__PURE__ */ createElement("div", { class: "flex-column gap width-input" }, /* @__PURE__ */ createElement("button", { "on:click": chat.resendObjects }, translation.resendObjects, /* @__PURE__ */ createElement("span", { class: "icon" }, "replay"))), /* @__PURE__ */ createElement("hr", null), /* @__PURE__ */ createElement("div", { class: "flex-column gap width-input" }, /* @__PURE__ */ createElement( - "button", - { - class: "danger", - "on:click": chat.clearObjects, - "toggle:disabled": chat.cannotClearObjects - }, - translation.clearObjects, - /* @__PURE__ */ createElement("span", { class: "icon" }, "deployed_code") - ), /* @__PURE__ */ createElement( - "button", - { - class: "danger", - "on:click": chat.clearMessages, - "toggle:disabled": chat.cannotClearMessages - }, - translation.clearChatMessages, - /* @__PURE__ */ createElement("span", { class: "icon" }, "chat_error") - ), /* @__PURE__ */ createElement("button", { class: "danger", "on:click": deleteChat }, translation.removeChat, /* @__PURE__ */ createElement("span", { class: "icon" }, "delete_forever")))), /* @__PURE__ */ createElement("button", { "on:click": closeModal }, translation.close, /* @__PURE__ */ createElement("span", { class: "icon" }, "close")))); - } - - // src/Views/Chat/messageComposer.tsx - function MessageComposer(chat) { - return /* @__PURE__ */ createElement("div", { class: "flex-row width-100" }, " ", /* @__PURE__ */ createElement( - "input", - { - class: "width-100 flex-1", - style: "max-width: unset", - placeholder: translation.composerPlaceholder, - "bind:value": chat.composingMessage, - "on:enter": chat.sendMessageFromComposer - } - ), /* @__PURE__ */ createElement( - "button", - { - class: "primary", - "on:click": chat.sendMessageFromComposer, - "toggle:disabled": chat.cannotSendMessage - }, - /* @__PURE__ */ createElement("span", { class: "icon" }, "send") - )); - } - // src/Views/Chat/threadView.tsx function ThreadView(chat) { const messageConverter = (message) => { @@ -1759,7 +1794,7 @@ }, /* @__PURE__ */ createElement("span", { class: "icon" }, "tune") ))), - ChatObjectView(chat), + ObjectPane(chat), ThreadView(chat), /* @__PURE__ */ createElement("footer", null, MessageComposer(chat)), ChatOptionModal(chat, isShowingOptions) diff --git a/dist/styles.css b/dist/styles.css index 7aed375c..8c9b5c61 100644 --- a/dist/styles.css +++ b/dist/styles.css @@ -968,6 +968,10 @@ main, overflow: hidden; } +.scroll-no { + overflow: hidden !important; +} + article > div, .modal main { overflow: scroll; diff --git a/src/Tabs/messageTab.tsx b/src/Tabs/messageTab.tsx index dc04a5c7..8ec5961d 100644 --- a/src/Tabs/messageTab.tsx +++ b/src/Tabs/messageTab.tsx @@ -2,9 +2,9 @@ import * as React from "bloatless-react"; import { closeChatView, isShowingObjects, selectedChat, toggleChatTools } from "../Model/model"; -import { ChatObjectView } from "../Views/Objects/chatObjectView"; import { ChatOptionModal } from "../Views/Chat/chatOptionModal"; import { MessageComposer } from "../Views/Chat/messageComposer"; +import { ObjectPane } from "../Views/Objects/objectPane"; import { ThreadView } from "../Views/Chat/threadView"; import { translation } from "../translations"; @@ -50,7 +50,7 @@ export function MessageTab() { , - ChatObjectView(chat), + ObjectPane(chat), ThreadView(chat), , diff --git a/src/Views/Objects/kanbanView.tsx b/src/Views/Objects/kanbanView.tsx new file mode 100644 index 00000000..6e000e69 --- /dev/null +++ b/src/Views/Objects/kanbanView.tsx @@ -0,0 +1,73 @@ +import * as React from "bloatless-react"; + +import { Chat, MessageObject } from "../../Model/chatModel"; + +import { ObjectEntryView } from "./objectEntryView"; +import { ObjectGridView } from "./objectGridView"; +import { translation } from "../../translations"; + +interface KanbanBoard { + title: string; + items: MessageObject[]; +} + +export function KanbanView( + chat: Chat, + selectedObject: React.State, + isShowingObjectModal: React.State +) { + const boards = new React.MapState(); + + 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: [] }); + + boards.value.get(boardTitle)?.items.push(messageObject); + }); + }); + + const converter: React.StateItemConverter = (board) => + KanbanBoardView(chat, board, selectedObject, isShowingObjectModal); + + const content = React.createProxyState([chat.objects], () => ( +
+ )); + + return ( +
+ ); +} + +function KanbanBoardView( + chat: Chat, + kanbanBoard: KanbanBoard, + selectedObject: React.State, + isShowingObjectModal: React.State +) { + return ( +
+ {kanbanBoard.title} +
+
+ {...kanbanBoard.items.map((messageObject) => + ObjectEntryView( + chat, + messageObject, + selectedObject, + isShowingObjectModal + ) + )} +
+
+ ); +} diff --git a/src/Views/Objects/noteObjectsView.tsx b/src/Views/Objects/noteObjectsView.tsx index d7088cec..58a658d1 100644 --- a/src/Views/Objects/noteObjectsView.tsx +++ b/src/Views/Objects/noteObjectsView.tsx @@ -2,7 +2,6 @@ import * as React from "bloatless-react"; import { Chat, MessageObject } from "../../Model/chatModel"; -import { ObjectEntryView } from "./objectEntryView"; import { ObjectGridView } from "./objectGridView"; import { translation } from "../../translations"; diff --git a/src/Views/Objects/objectGridView.tsx b/src/Views/Objects/objectGridView.tsx index ac5f3632..3134cacf 100644 --- a/src/Views/Objects/objectGridView.tsx +++ b/src/Views/Objects/objectGridView.tsx @@ -3,7 +3,6 @@ import * as React from "bloatless-react"; import { Chat, MessageObject } from "../../Model/chatModel"; import { ObjectEntryView } from "./objectEntryView"; -import { icons } from "../../icons"; export function ObjectGridView( chat: Chat, @@ -31,7 +30,7 @@ export function ObjectGridView( ) : (
diff --git a/src/Views/Objects/chatObjectView.tsx b/src/Views/Objects/objectPane.tsx similarity index 89% rename from src/Views/Objects/chatObjectView.tsx rename to src/Views/Objects/objectPane.tsx index 78e2d75f..835a2cbb 100644 --- a/src/Views/Objects/chatObjectView.tsx +++ b/src/Views/Objects/objectPane.tsx @@ -3,6 +3,7 @@ import * as React from "bloatless-react"; import { Chat, MessageObject } from "../../Model/chatModel"; import { AllObjectsView } from "./allObjectsView"; +import { KanbanView } from "./kanbanView"; import { NoteObjectsView } from "./noteObjectsView"; import { ObjectDetailModal } from "./objectDetailModal"; import { icons } from "../../icons"; @@ -11,9 +12,10 @@ import { translation } from "../../translations"; export const viewTypes = { all: [translation.viewAll, "grid_view"], notes: [translation.viewNotes, icons.noteContent], + kanban: [translation.viewKanban, "view_kanban"], }; -export function ChatObjectView(chat: Chat) { +export function ObjectPane(chat: Chat) { // selection and modal const isShowingObjectModal = new React.State(false); const selectedObject = new React.State(undefined); @@ -37,6 +39,8 @@ export function ChatObjectView(chat: Chat) { switch (selectedViewType.value) { case "notes": return NoteObjectsView; + case "kanban": + return KanbanView; default: return AllObjectsView; } @@ -54,7 +58,7 @@ export function ChatObjectView(chat: Chat) { } return ( -
+
-
+
diff --git a/src/translations.ts b/src/translations.ts index 10c09126..664ab47b 100644 --- a/src/translations.ts +++ b/src/translations.ts @@ -88,6 +88,7 @@ const englishTranslations = { viewAll: "All", viewNotes: "Notes", + viewKanban: "Kanban", noObjects: "No objects", noNotes: "No notes", @@ -201,6 +202,7 @@ const allTranslations: { [key: string]: typeof englishTranslations } = { viewAll: "Todos", viewNotes: "Notas", + viewKanban: "Kanban", noObjects: "Sin objetos", noNotes: "Sin notas", @@ -311,6 +313,7 @@ const allTranslations: { [key: string]: typeof englishTranslations } = { viewAll: "Alle", viewNotes: "Notizen", + viewKanban: "Kanban", noObjects: "Keine Objekte", noNotes: "Keine Notizen",