diff --git a/dist/index.css b/dist/index.css index 05b158c4..5bdd86b2 100644 --- a/dist/index.css +++ b/dist/index.css @@ -43,13 +43,11 @@ left: unset; width: var(--split-thread-width); } -@media (max-width: 1300px) { - main:has([showingobjects][chatopen]) { - display: flex; - } - main:has([showingobjects][chatopen]) #settings-tab { - display: none; - } +main:has([showingobjects][chatopen]) { + display: flex; +} +main:has([showingobjects][chatopen]) #settings-tab { + display: none; } @media (max-width: 640px) { [showingobjects][chatvisible][chatopen] .chat-object-view { @@ -69,3 +67,44 @@ width: 100%; } } +:root { + --day-view-width: 400px; +} +.calendar-wrapper { + display: flex; + flex-direction: column; + width: 100%; + height: 100%; +} +.calendar-wrapper .month-grid { + border-bottom: 1px solid var(--border); +} +.calendar-wrapper > * { + width: 100%; + height: 100%; + flex: 1; +} +@media (min-width: 900px) { + .calendar-wrapper:not([chatvisible] *) { + flex-direction: row; + } + .calendar-wrapper:not([chatvisible] *) .month-grid { + border-bottom: none; + border-right: 1px solid var(--border); + } + .calendar-wrapper:not([chatvisible] *) .day-view { + max-width: var(--day-view-width); + } +} +@media (min-width: 1200px) { + .calendar-wrapper { + flex-direction: row; + } + .calendar-wrapper .month-grid { + border-bottom: none; + border-right: 1px solid var(--border); + } + .calendar-wrapper .day-view { + max-width: var(--day-view-width); + } +} diff --git a/dist/index.js b/dist/index.js index 5a92dcce..8679468e 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1007,7 +1007,6 @@ this.objects.set(messageObject.id, messageObject); } const latest = this.getMostRecentContent(messageObject); - if (!latest) return; if (latest.categoryName) usedObjectCategories.add(latest.categoryName); if (latest.status) usedObjectStatuses.add(latest.status); }; @@ -1302,6 +1301,7 @@ var isEncryptionAvailable = window.crypto.subtle != void 0; var senderName = restoreState("sender-name", ""); var pageZoom = restoreState("page-zoom", 100); + var dayInCalendar = restoreState("calendar-day", (/* @__PURE__ */ new Date()).toISOString().split("T")[0]); pageZoom.subscribe(() => { document.body.style.zoom = `${pageZoom.value}%`; document.body.style.webkitTextSizeAdjust = `${pageZoom.value}%`; @@ -1652,7 +1652,6 @@ ); messageObjects.handleAddition((messageObject) => { const latest = chat.getMostRecentContent(messageObject); - if (!latest) return; if (!latest.categoryName) return; const categoryName = latest.categoryName; if (!boards.value.has(categoryName)) { @@ -1753,7 +1752,6 @@ const notes = new ListState(); messageObjects.handleAddition((messageObject) => { const latest = chat.getMostRecentContent(messageObject); - if (!latest) return; if (!latest.noteContent) return; notes.add(messageObject); messageObjects.handleRemoval( @@ -1992,7 +1990,6 @@ function rename() { status.items.forEach((messageObject) => { const latest = chat.getMostRecentContent(messageObject); - if (!latest) return; latest.status = editingStatus.value; chat.addObject(messageObject); }); @@ -2066,20 +2063,49 @@ ); } + // src/Views/Objects/dayView.tsx + function DayView(chat, messageObjects, selectedObject, isShowingObjectModal) { + const objectsForDayView = new ListState(); + function processObject(messageObject) { + const latest = chat.getMostRecentContent(messageObject); + if (!latest.date || latest.date != dayInCalendar.value) return; + objectsForDayView.add(messageObject); + messageObjects.handleRemoval(messageObject, () => { + objectsForDayView.remove(messageObject); + }); + } + messageObjects.handleAddition(processObject); + dayInCalendar.subscribeSilent(() => { + objectsForDayView.clear(); + chat.objects.value.forEach(processObject); + }); + const objectConverter = (messageObject) => { + const latest = chat.getMostRecentContent(messageObject); + const timeString = latest.time ?? "00:00"; + const [hour, minute] = timeString.split(":"); + const hourInMinutes = parseInt(hour) * 60; + const minutesTotal = parseInt(minute) + hourInMinutes; + const view = ObjectEntryView( + chat, + messageObject, + selectedObject, + isShowingObjectModal + ); + view.style.order = minutesTotal; + return view; + }; + return /* @__PURE__ */ createElement( + "div", + { + class: "day-view padding flex-column gap", + "children:prepend": [objectsForDayView, objectConverter] + } + ); + } + // src/Views/Objects/calendarView.tsx function CalendarView(chat, messageObjects, selectedObject, isShowingObjectModal) { - const notes = new ListState(); - messageObjects.handleAddition((messageObject) => { - const latest = chat.getMostRecentContent(messageObject); - if (!latest) return; - if (!latest.date) return; - notes.add(messageObject); - messageObjects.handleRemoval( - messageObject, - () => notes.remove(messageObject) - ); - }); - return /* @__PURE__ */ createElement("div", { class: "width-100 height-100 scroll-v padding" }, ObjectGridView(chat, notes, selectedObject, isShowingObjectModal)); + return /* @__PURE__ */ createElement("div", { class: "calendar-wrapper" }, /* @__PURE__ */ createElement("div", { class: "month-grid" }, /* @__PURE__ */ createElement("input", { type: "date", "bind:value": dayInCalendar })), DayView(chat, messageObjects, selectedObject, isShowingObjectModal)); } // src/Views/Objects/objectPane.tsx diff --git a/src/Model/chatModel.ts b/src/Model/chatModel.ts index 3615d850..437385f6 100644 --- a/src/Model/chatModel.ts +++ b/src/Model/chatModel.ts @@ -381,7 +381,6 @@ export class Chat { } const latest = this.getMostRecentContent(messageObject); - if (!latest) return; if (latest.categoryName) usedObjectCategories.add(latest.categoryName); if (latest.status) usedObjectStatuses.add(latest.status); }; diff --git a/src/Model/model.ts b/src/Model/model.ts index 028f3423..f236fd12 100644 --- a/src/Model/model.ts +++ b/src/Model/model.ts @@ -151,6 +151,8 @@ export const isPresentingSettingsModal = new React.State(false); export const isEncryptionAvailable = window.crypto.subtle != undefined; export const senderName = React.restoreState("sender-name", ""); export const pageZoom = React.restoreState("page-zoom", 100); +export const dayInCalendar = React.restoreState("calendar-day", new Date().toISOString().split("T")[0]) + pageZoom.subscribe(() => { document.body.style.zoom = `${pageZoom.value}%`; document.body.style.webkitTextSizeAdjust = `${pageZoom.value}%`; diff --git a/src/Views/Objects/calendarView.tsx b/src/Views/Objects/calendarView.tsx index a2f5d43e..0aa2f45e 100644 --- a/src/Views/Objects/calendarView.tsx +++ b/src/Views/Objects/calendarView.tsx @@ -3,6 +3,8 @@ import * as React from "bloatless-react"; import { Chat, MessageObject } from "../../Model/chatModel"; import { ObjectGridView } from "./objectGridView"; +import { DayView } from "./dayView"; +import { dayInCalendar } from "../../Model/model"; export function CalendarView( chat: Chat, @@ -10,19 +12,10 @@ export function CalendarView( selectedObject: React.State, isShowingObjectModal: React.State ) { - const notes = new React.ListState(); - messageObjects.handleAddition((messageObject) => { - const latest = chat.getMostRecentContent(messageObject); - if (!latest) return; - if (!latest.date) return; - - notes.add(messageObject); - messageObjects.handleRemoval(messageObject, () => - notes.remove(messageObject) - ); - }); - - return
- {ObjectGridView(chat, notes, selectedObject, isShowingObjectModal)} -
; + return
+
+ +
+ {DayView(chat, messageObjects, selectedObject, isShowingObjectModal)} +
} diff --git a/src/Views/Objects/dayView.tsx b/src/Views/Objects/dayView.tsx new file mode 100644 index 00000000..e329385d --- /dev/null +++ b/src/Views/Objects/dayView.tsx @@ -0,0 +1,59 @@ +import * as React from "bloatless-react"; + +import { Chat, MessageObject } from "../../Model/chatModel"; + +import { ObjectEntryView } from "./objectEntryView"; +import { dayInCalendar } from "../../Model/model"; + +export function DayView( + chat: Chat, + messageObjects: + | React.ListState + | React.MapState, + selectedObject: React.State, + isShowingObjectModal: React.State +) { + const objectsForDayView = new React.ListState(); + + function processObject(messageObject: MessageObject) { + const latest = chat.getMostRecentContent(messageObject); + if (!latest.date || latest.date != dayInCalendar.value) return; + + objectsForDayView.add(messageObject); + messageObjects.handleRemoval(messageObject, () => { + objectsForDayView.remove(messageObject); + }) + } + + messageObjects.handleAddition(processObject); + dayInCalendar.subscribeSilent(() => { + objectsForDayView.clear(); + chat.objects.value.forEach(processObject); + }) + + const objectConverter: React.StateItemConverter = ( + messageObject + ) => { + const latest = chat.getMostRecentContent(messageObject); + const timeString = latest.time ?? "00:00"; + const [hour, minute] = timeString.split(":"); + const hourInMinutes = parseInt(hour) * 60; + const minutesTotal = parseInt(minute) + hourInMinutes; + + const view = ObjectEntryView( + chat, + messageObject, + selectedObject, + isShowingObjectModal + ); + view.style.order = minutesTotal; + return view; + }; + + return ( +
+ ); +} diff --git a/src/Views/Objects/kanbanView.tsx b/src/Views/Objects/kanbanView.tsx index 3cdf4413..605cfce1 100644 --- a/src/Views/Objects/kanbanView.tsx +++ b/src/Views/Objects/kanbanView.tsx @@ -30,7 +30,6 @@ export function KanbanView( messageObjects.handleAddition((messageObject) => { const latest = chat.getMostRecentContent(messageObject); - if (!latest) return; if (!latest.categoryName) return; const categoryName = latest.categoryName!; diff --git a/src/Views/Objects/noteObjectsView.tsx b/src/Views/Objects/noteObjectsView.tsx index ba2f6c1d..d6c23db8 100644 --- a/src/Views/Objects/noteObjectsView.tsx +++ b/src/Views/Objects/noteObjectsView.tsx @@ -13,7 +13,6 @@ export function NoteObjectsView( const notes = new React.ListState(); messageObjects.handleAddition((messageObject) => { const latest = chat.getMostRecentContent(messageObject); - if (!latest) return; if (!latest.noteContent) return; notes.add(messageObject); diff --git a/src/Views/Objects/statusView.tsx b/src/Views/Objects/statusView.tsx index 1fa0a58e..5fb386bc 100644 --- a/src/Views/Objects/statusView.tsx +++ b/src/Views/Objects/statusView.tsx @@ -145,7 +145,6 @@ function StatusHeaderView(chat: Chat, status: StatusData) { function rename() { status.items.forEach((messageObject) => { const latest = chat.getMostRecentContent(messageObject); - if (!latest) return; latest.status = editingStatus.value; chat.addObject(messageObject); diff --git a/src/styles.css b/src/styles.css index 6845e0ca..71df451c 100644 --- a/src/styles.css +++ b/src/styles.css @@ -60,14 +60,13 @@ width: var(--split-thread-width); } -@media (max-width: 1300px) { - main:has([showingobjects][chatopen]) { - display: flex; - } +/* hide settings tab */ +main:has([showingobjects][chatopen]) { + display: flex; +} - main:has([showingobjects][chatopen]) #settings-tab { - display: none; - } +main:has([showingobjects][chatopen]) #settings-tab { + display: none; } @media (max-width: 640px) { @@ -93,3 +92,57 @@ width: 100%; } } + +/* calendar */ +:root { + --day-view-width: 400px; +} + +.calendar-wrapper { + display: flex; + flex-direction: column; + + width: 100%; + height: 100%; +} + +.calendar-wrapper .month-grid { + border-bottom: 1px solid var(--border); +} + +.calendar-wrapper > * { + width: 100%; + height: 100%; + flex: 1; +} + +@media (min-width: 900px) { + .calendar-wrapper:not([chatvisible] *) { + flex-direction: row; + } + + .calendar-wrapper:not([chatvisible] *) .month-grid { + border-bottom: none; + border-right: 1px solid var(--border); + } + + .calendar-wrapper:not([chatvisible] *) .day-view { + max-width: var(--day-view-width); + } +} + + +@media (min-width: 1200px) { + .calendar-wrapper { + flex-direction: row; + } + + .calendar-wrapper .month-grid { + border-bottom: none; + border-right: 1px solid var(--border); + } + + .calendar-wrapper .day-view { + max-width: var(--day-view-width); + } +}