diff --git a/client/src/api/index.ts b/client/src/api/index.ts index 720c5dd8f34..3e887c69f4f 100644 --- a/client/src/api/index.ts +++ b/client/src/api/index.ts @@ -8,12 +8,22 @@ import { components } from "@/api/schema"; export type HistorySummary = components["schemas"]["HistorySummary"]; /** - * Contains additional details about the contents and owner of a History. - * This is used by the client API to simplify the handling of History objects. + * Contains minimal information about a History with additional content stats. + * This is a subset of information that can be relatively frequently updated after + * certain actions are performed on the history. */ -export interface HistorySummaryExtended extends HistorySummary { +export interface HistoryContentsStats { + id: string; + update_time: string; size: number; contents_active: components["schemas"]["HistoryActiveContentCounts"]; +} + +/** + * Contains summary information plus additional details about the contents and owner of a History. + * This is used by the client API to simplify the handling of History objects. + */ +export interface HistorySummaryExtended extends HistorySummary, HistoryContentsStats { user_id: string; } diff --git a/client/src/components/History/CurrentHistory/HistoryPanel.vue b/client/src/components/History/CurrentHistory/HistoryPanel.vue index 3c3d2c6638a..b458c6f9967 100644 --- a/client/src/components/History/CurrentHistory/HistoryPanel.vue +++ b/client/src/components/History/CurrentHistory/HistoryPanel.vue @@ -294,6 +294,7 @@ async function onDelete(item: HistoryItem, recursive = false) { try { await deleteContent(item, { recursive: recursive }); + updateContentStats(); } finally { isLoading.value = false; } @@ -315,6 +316,7 @@ async function onUndelete(item: HistoryItem) { try { await updateContentFields(item, { deleted: false }); + updateContentStats(); } finally { isLoading.value = false; } @@ -326,11 +328,16 @@ async function onUnhide(item: HistoryItem) { try { await updateContentFields(item, { visible: true }); + updateContentStats(); } finally { isLoading.value = false; } } +function updateContentStats() { + historyStore.updateContentStats(props.history.id); +} + function reloadContents() { startWatchingHistory(); } diff --git a/client/src/composables/historyContentStats.ts b/client/src/composables/historyContentStats.ts index 40bc09407e8..31a12fcc3b7 100644 --- a/client/src/composables/historyContentStats.ts +++ b/client/src/composables/historyContentStats.ts @@ -1,8 +1,8 @@ import { computed, type Ref } from "vue"; -import { type HistorySummaryExtended } from "@/api"; +import { type HistoryContentsStats } from "@/api"; -export function useHistoryContentStats(history: Ref) { +export function useHistoryContentStats(history: Ref) { const historySize = computed(() => history.value?.size ?? 0); const numItemsActive = computed(() => history.value?.contents_active?.active ?? 0); const numItemsDeleted = computed(() => history.value?.contents_active?.deleted ?? 0); diff --git a/client/src/stores/historyStore.ts b/client/src/stores/historyStore.ts index 8286c20fd97..5178a8c35e1 100644 --- a/client/src/stores/historyStore.ts +++ b/client/src/stores/historyStore.ts @@ -1,7 +1,14 @@ import { defineStore } from "pinia"; import { computed, del, ref, set } from "vue"; -import type { AnyHistory, HistoryDevDetailed, HistorySummary, HistorySummaryExtended } from "@/api"; +import type { + AnyHistory, + HistoryContentsStats, + HistoryDevDetailed, + HistorySummary, + HistorySummaryExtended, +} from "@/api"; +import { historyFetcher } from "@/api/histories"; import { archiveHistory, unarchiveHistory } from "@/api/histories.archived"; import { HistoryFilters } from "@/components/History/HistoryFilters"; import { useUserLocalStorage } from "@/composables/userLocalStorage"; @@ -21,6 +28,7 @@ import { sortByObjectProp } from "@/utils/sorting"; const PAGINATION_LIMIT = 10; const isLoadingHistory = new Set(); +const CONTENT_STATS_KEYS = ["size", "contents_active", "update_time"] as const; export const useHistoryStore = defineStore("historyStore", () => { const historiesLoading = ref(false); @@ -100,7 +108,7 @@ export const useHistoryStore = defineStore("historyStore", () => { set(storedFilterTexts.value, historyId, filterText); } - function setHistory(history: AnyHistory) { + function setHistory(history: AnyHistory | HistoryContentsStats) { if (storedHistories.value[history.id] !== undefined) { // Merge the incoming history with existing one to keep additional information Object.assign(storedHistories.value[history.id]!, history); @@ -301,6 +309,20 @@ export const useHistoryStore = defineStore("historyStore", () => { setHistory(savedHistory); } + async function updateContentStats(historyId: string) { + try { + const { data } = await historyFetcher({ + history_id: historyId, + keys: CONTENT_STATS_KEYS.join(","), + }); + const contentStats = { id: historyId, ...data } as HistoryContentsStats; + setHistory(contentStats); + return contentStats; + } catch (error) { + console.error(error); + } + } + return { histories, currentHistory, @@ -331,5 +353,6 @@ export const useHistoryStore = defineStore("historyStore", () => { historiesLoading, historiesOffset, totalHistoryCount, + updateContentStats, }; });