add filter modal, implement search

This commit is contained in:
marlon-erler
2024-07-13 17:13:59 +02:00
parent 61ddb4e32c
commit af67144a6c
7 changed files with 237 additions and 40 deletions
+7 -1
View File
@@ -7,6 +7,7 @@ import { translation } from "../../translations";
export function AllObjectsView(
chat: Chat,
messageObjects: React.MapState<MessageObject>,
selectedObject: React.State<MessageObject | undefined>,
isShowingObjectModal: React.State<boolean>
) {
@@ -21,7 +22,12 @@ export function AllObjectsView(
{translation.objectsInTotal}{" "}
<span subscribe:innerText={objectCount}></span>
</b>
{ObjectGridView(chat, chat.objects, selectedObject, isShowingObjectModal)}
{ObjectGridView(
chat,
messageObjects,
selectedObject,
isShowingObjectModal
)}
</div>
);
}
+3 -3
View File
@@ -3,7 +3,6 @@ import * as React from "bloatless-react";
import { Chat, MessageObject } from "../../Model/chatModel";
import { ObjectEntryView } from "./objectEntryView";
import { PlaceholderView } from "./placeholderView";
import { RenameView } from "../renameView";
interface KanbanBoard {
@@ -18,6 +17,7 @@ interface KanbanBoardItem {
export function KanbanView(
chat: Chat,
messageObjects: React.MapState<MessageObject>,
selectedObject: React.State<MessageObject | undefined>,
isShowingObjectModal: React.State<boolean>
) {
@@ -28,7 +28,7 @@ export function KanbanView(
.sort((a, b) => a.localeCompare(b))
);
chat.objects.handleAddition((messageObject) => {
messageObjects.handleAddition((messageObject) => {
const latest = chat.getMostRecentContent(messageObject);
if (!latest) return;
if (!latest.categoryName) return;
@@ -53,7 +53,7 @@ export function KanbanView(
};
boards.value.get(categoryName)?.items.add(boardItem);
chat.objects.handleRemoval(messageObject, () => {
messageObjects.handleRemoval(messageObject, () => {
boards.value.get(categoryName)?.items.remove(boardItem);
});
});
+3 -2
View File
@@ -6,17 +6,18 @@ import { ObjectGridView } from "./objectGridView";
export function NoteObjectsView(
chat: Chat,
messageObjects: React.MapState<MessageObject>,
selectedObject: React.State<MessageObject | undefined>,
isShowingObjectModal: React.State<boolean>
) {
const notes = new React.ListState<MessageObject>();
chat.objects.handleAddition((messageObject) => {
messageObjects.handleAddition((messageObject) => {
const latest = chat.getMostRecentContent(messageObject);
if (!latest) return;
if (!latest.noteContent) return;
notes.add(messageObject);
chat.objects.handleRemoval(messageObject, () =>
messageObjects.handleRemoval(messageObject, () =>
notes.remove(messageObject)
);
});
+103 -12
View File
@@ -20,7 +20,58 @@ export const viewTypes = {
export function ObjectPane(chat: Chat) {
// selection and modal
const isShowingObjectModal = new React.State(false);
const isShowingFilterModel = new React.State(false);
const selectedObject = new React.State<MessageObject | undefined>(undefined);
// methods
function createObject() {
const newObject = chat.createObjectFromTitle("");
chat.addObjectAndSend(newObject);
selectedObject.value = newObject;
isShowingObjectModal.value = true;
}
function showFilters() {
isShowingFilterModel.value = true;
}
function closeFilters() {
isShowingFilterModel.value = false;
}
// filter
const filterInput = new React.State("");
const appliedFilter = new React.State("");
const resultCount = new React.State(0);
const resultText = React.createProxyState([appliedFilter, resultCount], () =>
translation.searchTitleText(appliedFilter.value, resultCount.value)
);
const messageObjects = new React.MapState<MessageObject>();
const cannotReset = React.createProxyState(
[appliedFilter],
() => appliedFilter.value == ""
);
function resetFilter() {
filterInput.value = "";
applyFilter();
}
function applyFilter() {
appliedFilter.value = filterInput.value;
}
appliedFilter.subscribe((filterTerm) => {
const allObjects = [...chat.objects.value.entries()];
const matchingObjects = allObjects.filter(
(entry) => entry[1].title.indexOf(filterTerm) != -1
);
resultCount.value = matchingObjects.length;
messageObjects.clear();
matchingObjects.forEach((entry) => messageObjects.set(...entry));
});
// view
const objectModal = React.createProxyState(
[chat.objects, selectedObject],
() => {
@@ -34,7 +85,6 @@ export function ObjectPane(chat: Chat) {
}
);
// view type
const mainView = React.createProxyState([chat.viewType], () => {
function getViewFunction() {
switch (chat.viewType.value) {
@@ -49,17 +99,14 @@ export function ObjectPane(chat: Chat) {
}
}
return getViewFunction()(chat, selectedObject, isShowingObjectModal);
return getViewFunction()(
chat,
messageObjects,
selectedObject,
isShowingObjectModal
);
});
// methods
function createObject() {
const newObject = chat.createObjectFromTitle("");
chat.addObjectAndSend(newObject);
selectedObject.value = newObject;
isShowingObjectModal.value = true;
}
return (
<div class="chat-object-view flex-column scroll-no padding-0">
<div class="flex-row align-center border-bottom">
@@ -77,8 +124,12 @@ export function ObjectPane(chat: Chat) {
)}
</div>
<button class="height-100" disabled>
<span class="icon">visibility</span>
<button
class="height-100"
aria-label={translation.filterObjects}
on:click={showFilters}
>
<span class="icon">filter_list</span>
</button>
</div>
@@ -88,6 +139,46 @@ export function ObjectPane(chat: Chat) {
></div>
<div children:set={objectModal}></div>
<div class="modal" toggle:open={isShowingFilterModel}>
<div>
<main>
<h2>{translation.filterObjects}</h2>
<label class="tile">
<span class="icon">search</span>
<div>
<span>{translation.searchByTitle}</span>
<input
bind:value={filterInput}
on:enter={applyFilter}
placeholder={translation.searchByTitlePlaceholder}
></input>
</div>
</label>
<div class="flex-row width-input">
<button
class="width-50 flex"
on:click={resetFilter}
toggle:disabled={cannotReset}
>
{translation.reset}
</button>
<button class="width-50 flex primary" on:click={applyFilter}>
{translation.search}
<span class="icon">arrow_forward</span>
</button>
</div>
<hr></hr>
<span class="secondary" subscribe:innerText={resultText}></span>
</main>
<button on:click={closeFilters}>
{translation.close}
<span class="icon">close</span>
</button>
</div>
</div>
</div>
);
}
+3 -2
View File
@@ -29,6 +29,7 @@ interface StatusData {
export function StatusView(
chat: Chat,
messageObjects: React.MapState<MessageObject>,
selectedObject: React.State<MessageObject | undefined>,
isShowingObjectModal: React.State<boolean>
) {
@@ -45,12 +46,12 @@ export function StatusView(
.sort((a, b) => a.localeCompare(b))
);
chat.objects.subscribe(() => {
messageObjects.subscribe(() => {
rows.clear();
statuses.clear();
// add items
chat.objects.value.forEach((messageObject) => {
messageObjects.value.forEach((messageObject) => {
const latest = chat.getMostRecentContent(messageObject);
if (!latest.categoryName || !latest.status) return;