Merge pull request #21779 from davelopez/add_upload_method_pending_badge

Add badges to upload methods with staged items count
This commit is contained in:
Ahmed Hamid Awan
2026-02-09 09:31:20 -06:00
committed by GitHub
3 changed files with 63 additions and 4 deletions
@@ -2,7 +2,9 @@
import { computed, ref } from "vue";
import { useRouter } from "vue-router/composables";
import type { CardBadge } from "@/components/Common/GCard.types";
import { useConfig } from "@/composables/config";
import { useUploadStagingCounts } from "@/composables/upload/useUploadStaging";
import type { UploadMethodConfig } from "./types";
import { useAllUploadMethods } from "./uploadMethodRegistry";
@@ -30,6 +32,7 @@ const query = ref("");
const searchInputClass = computed(() => (props.searchTeleportTarget ? "my-2" : props.inPanel ? "my-2" : "mb-3"));
const allUploadMethods = useAllUploadMethods();
const stagedCountsByMode = useUploadStagingCounts();
const availableMethods = computed(() => {
if (!isConfigLoaded.value) {
@@ -64,6 +67,23 @@ function selectUploadMethod(method: UploadMethodConfig) {
function updateQuery(newQuery: string) {
query.value = newQuery;
}
function getStagingBadges(method: UploadMethodConfig): CardBadge[] {
const count = stagedCountsByMode.value[method.id] ?? 0;
if (count === 0) {
return [];
}
return [
{
id: `staged-${method.id}`,
label: String(count),
title: `${count} upload item${count === 1 ? "" : "s"} staged and pending submission`,
variant: "primary",
type: "badge",
handler: () => selectUploadMethod(method),
},
];
}
</script>
<template>
@@ -95,6 +115,7 @@ function updateQuery(newQuery: string) {
:full-description="true"
:description="method.description"
:title-icon="{ icon: method.icon, class: 'text-primary', size: 'lg' }"
:badges="getStagingBadges(method)"
:data-method-id="method.id"
@click="selectUploadMethod(method)" />
</template>
@@ -1,7 +1,10 @@
import { onMounted, type Ref, watch } from "vue";
import { storeToRefs } from "pinia";
import { computed, onMounted, type Ref, watch } from "vue";
import type { UploadMethod } from "@/components/Panels/Upload/types";
import { type StagedUploadItem, useUploadStagingStore } from "@/stores/uploadStagingStore";
import type { PasteContentItem } from "@/components/Panels/Upload/types/uploadItem";
import type { StagedUploadItem } from "@/stores/uploadStagingStore";
import { useUploadStagingStore } from "@/stores/uploadStagingStore";
interface UseUploadStagingReturn {
clear: () => void;
@@ -46,3 +49,31 @@ export function useUploadStaging<T extends StagedUploadItem>(
clear,
};
}
export function useUploadStagingCounts() {
const { itemsByMode } = storeToRefs(useUploadStagingStore());
return computed<Partial<Record<UploadMethod, number>>>(() => {
const counts: Partial<Record<UploadMethod, number>> = {};
for (const [mode, items] of Object.entries(itemsByMode.value)) {
const uploadMode = mode as UploadMethod;
counts[uploadMode] = countStagedItems(uploadMode, items ?? []);
}
return counts;
});
}
function countStagedItems(mode: UploadMethod, items: StagedUploadItem[]): number {
if (mode == "paste-content") {
return items.filter(isNonEmptyPasteContentItem).length;
}
return items.length;
}
function isNonEmptyPasteContentItem(item: StagedUploadItem): item is PasteContentItem {
return isPasteContentItem(item) && item.content.trim().length > 0;
}
export function isPasteContentItem(item: StagedUploadItem): item is PasteContentItem {
return "content" in item;
}
+9 -2
View File
@@ -27,12 +27,19 @@ export const useUploadStagingStore = defineStore("uploadStagingStore", () => {
}
function setItems<T extends StagedUploadItem>(mode: UploadMethod, items: T[]) {
// always store a new array reference so reactivity triggers
// Ensure the key exists (Vue 2 key reactivity) with a one-time object replacement.
if (!(mode in itemsByMode.value)) {
itemsByMode.value = { ...itemsByMode.value, [mode]: [] };
}
// Always store a new array reference so reactivity triggers.
itemsByMode.value[mode] = [...items];
}
function clearItems(mode: UploadMethod) {
delete itemsByMode.value[mode];
if (!(mode in itemsByMode.value)) {
return;
}
itemsByMode.value[mode] = [];
}
return {