From b4ae9e5a95cdf81286d69d4d644414b1e475c62b Mon Sep 17 00:00:00 2001 From: Eli Ribble Date: Wed, 20 May 2026 23:49:59 +0000 Subject: [PATCH] Move communication workbench to use resource store Because it's getting better all the time, including by adding the ability to get new resources when they get created over SSE. --- ts/components/CommunicationColumnAction.vue | 2 +- ts/components/CommunicationColumnDetail.vue | 2 +- ts/components/CommunicationColumnList.vue | 2 +- ts/store/communication.ts | 69 --------------------- ts/store/resource.ts | 24 ++++++- ts/view/Communication.vue | 67 ++++++++------------ 6 files changed, 50 insertions(+), 116 deletions(-) delete mode 100644 ts/store/communication.ts diff --git a/ts/components/CommunicationColumnAction.vue b/ts/components/CommunicationColumnAction.vue index 883d3629..3e444a9b 100644 --- a/ts/components/CommunicationColumnAction.vue +++ b/ts/components/CommunicationColumnAction.vue @@ -174,7 +174,7 @@ interface Emits { } interface Props { isLoading: boolean; - selectedCommunication: Communication | null; + selectedCommunication: Communication | undefined; selectedReport: PublicReport | undefined; } const emit = defineEmits(); diff --git a/ts/components/CommunicationColumnDetail.vue b/ts/components/CommunicationColumnDetail.vue index 706eca37..e77e38bd 100644 --- a/ts/components/CommunicationColumnDetail.vue +++ b/ts/components/CommunicationColumnDetail.vue @@ -110,7 +110,7 @@ interface Props { loading: boolean; mapBounds?: LngLatBounds; mapMarkers: Marker[]; - selectedCommunication: Communication | null; + selectedCommunication: Communication | undefined; selectedReport: PublicReport | undefined; } diff --git a/ts/components/CommunicationColumnList.vue b/ts/components/CommunicationColumnList.vue index 49b3ab88..95a31d21 100644 --- a/ts/components/CommunicationColumnList.vue +++ b/ts/components/CommunicationColumnList.vue @@ -206,7 +206,7 @@ import ListCardCommunication from "@/components/ListCardCommunication.vue"; import { Communication, LogEntry, PublicReport } from "@/type/api"; interface Props { - all: Communication[] | null; + all: Communication[] | undefined; loading: boolean; selectedID?: string; } diff --git a/ts/store/communication.ts b/ts/store/communication.ts deleted file mode 100644 index fb63ee0d..00000000 --- a/ts/store/communication.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { defineStore } from "pinia"; -import { ref } from "vue"; - -import { apiClient } from "@/client"; -import { SSEManager, SSEMessageResource } from "@/SSEManager"; -import { useSessionStore } from "@/store/session"; -import { Communication, CommunicationDTO } from "@/type/api"; - -export const useCommunicationStore = defineStore("communication", () => { - // State - const all = ref(null); - const loading = ref(false); - const error = ref(null); - - // Subscription - SSEManager.subscribe((msg: SSEMessageResource) => { - if ( - msg.resource.startsWith("sync:communication") && - msg.type == "updated" - ) { - fetchOne(msg.uri); - } - }); - // Actions - async function fetchAll(): Promise { - const session = useSessionStore(); - if (session.urls == null) { - throw new Error("can't fetch without user URL data"); - } - - loading.value = true; - error.value = null; - try { - const params = new URLSearchParams(); - params.append("sort", "-created"); - //if (typeFilter.value) params.append("type", typeFilter.value); - - const url = `${session.urls.api.communication}?${params}`; - const data = (await apiClient.JSONGet(url)) as CommunicationDTO[]; - - all.value = data.map((c: CommunicationDTO) => Communication.fromJSON(c)); - return all.value; - } catch (err) { - console.error("Error loading communications:", err); - throw err; - } finally { - loading.value = false; - } - } - async function fetchOne(uri: string) { - const data = (await apiClient.JSONGet(uri)) as CommunicationDTO; - if (!all.value) { - return; - } - for (var i = 0; i < all.value.length; i++) { - const c = all.value[i]; - if (c.uri == data.uri) { - all.value[i] = Communication.fromJSON(data); - } - } - } - return { - // State - all, - loading, - // Actions - fetchAll, - }; -}); diff --git a/ts/store/resource.ts b/ts/store/resource.ts index 9be889f2..f6ef8021 100644 --- a/ts/store/resource.ts +++ b/ts/store/resource.ts @@ -31,8 +31,12 @@ function createResourceStore( // Subscription SSEManager.subscribe((msg: SSEMessageResource) => { - if (msg.resource.startsWith(resource_name) && msg.type == "updated") { - fetchByURI(msg.uri); + if (msg.resource.startsWith(resource_name)) { + if (msg.type == "created") { + fetchByURI(msg.uri); + } else if (msg.type == "updated") { + fetchByURI(msg.uri); + } } }); @@ -92,10 +96,22 @@ function createResourceStore( throw err; } } + function getAll(): full[] | null { + if (_resourceFetchAll) { + return Array.from(_resourceByURI.value.values()); + } + return null; + } + function hasAll(): boolean { + return !!_resourceFetchAll.value; + } function loadingAll(): boolean { return !!_resourceFetchAll.value; } - function loadingURI(uri: string): boolean { + function loadingURI(uri: string | undefined): boolean { + if (uri === undefined) { + return false; + } return !!_resourceFetchByURI.value.get(uri); } function uriFromID(id: string): string { @@ -108,6 +124,8 @@ function createResourceStore( fetchAll, fetchByID, fetchByURI, + getAll, + hasAll, loadingAll, loadingURI, }; diff --git a/ts/view/Communication.vue b/ts/view/Communication.vue index fd0a29f2..f3760834 100644 --- a/ts/view/Communication.vue +++ b/ts/view/Communication.vue @@ -16,14 +16,17 @@