refactor: Extract AssetsSidebarTab template and improve UI structure

- Extract sidebar template into reusable AssetSidebarTemplate component
  - Replace PrimeVue Tabs with TextButton for better visual consistency
  - Add i18n key for "Back to all assets" button
  - Improve job detail view header layout with better spacing
  - Maintain existing functionality while cleaning up template structure
This commit is contained in:
Jin Yi
2025-10-20 23:01:56 +09:00
parent 8682ca3e5c
commit 39dad98d87
3 changed files with 75 additions and 34 deletions

View File

@@ -0,0 +1,33 @@
<template>
<div
class="flex h-full flex-col bg-white dark-theme:bg-zinc-900"
:class="props.class"
>
<div>
<div
v-if="slots.top"
class="flex min-h-12 items-center border-b border-zinc-200 px-4 py-2 dark-theme:border-zinc-700"
>
<slot name="top" />
</div>
<div v-if="slots.header" class="px-4">
<slot name="header" />
</div>
</div>
<!-- h-0 to force scrollpanel to grow -->
<ScrollPanel class="h-0 grow">
<slot name="body" />
</ScrollPanel>
</div>
</template>
<script setup lang="ts">
import ScrollPanel from 'primevue/scrollpanel'
import { useSlots } from 'vue'
const props = defineProps<{
class?: string
}>()
const slots = useSlots()
</script>

View File

@@ -1,45 +1,52 @@
<template> <template>
<SidebarTabTemplate <AssetsSidebarTemplate>
:title="isInFolderView ? '' : $t('sideToolbar.mediaAssets')" <template #top>
> <span v-if="!isInFolderView" class="font-bold">
<template v-if="isInFolderView" #tool-buttons> {{ $t('sideToolbar.mediaAssets') }}
<div class="flex w-full items-center gap-2"> </span>
<span class="font-medium" <div v-else class="flex w-full items-center justify-between gap-2">
>Job ID: {{ folderPromptId?.substring(0, 8) }}</span <div class="flex items-center gap-2">
> <span class="font-bold">{{ $t('Job ID') }}:</span>
<button <span class="text-sm">{{ folderPromptId?.substring(0, 8) }}</span>
class="rounded p-1 transition-colors hover:bg-neutral-100 dark-theme:hover:bg-neutral-700" <i class="mb-1 icon-[lucide--copy] text-sm" @click="copyJobId"></i>
:title="$t('g.copy')" </div>
@click="copyJobId" <div>
> <span>{{ formattedExecutionTime }}</span>
<i class="icon-[lucide--copy] size-4" /> </div>
</button>
<span class="ml-auto text-sm text-neutral-500">
{{ formattedExecutionTime }}
</span>
</div> </div>
</template> </template>
<template #header> <template #header>
<!-- Job Detail View Header --> <!-- Job Detail View Header -->
<div <div v-if="isInFolderView" class="pt-4 pb-1">
v-if="isInFolderView" <IconTextButton
class="border-b border-neutral-300 px-4 pt-2 pb-3 dark-theme:border-neutral-700" :label="$t('sideToolbar.backToAssets')"
> type="secondary"
<button
class="flex items-center gap-2 rounded bg-neutral-100 px-3 py-1.5 text-sm transition-colors hover:bg-neutral-200 dark-theme:bg-neutral-700 dark-theme:hover:bg-neutral-600"
@click="exitFolderView" @click="exitFolderView"
> >
<i class="icon-[lucide--arrow-left] size-4" /> <template #icon>
<span>Back to all assets</span> <i class="icon-[lucide--arrow-left] size-4" />
</button> </template>
</IconTextButton>
</div> </div>
<!-- Normal Tab View --> <!-- Normal Tab View -->
<Tabs v-model:value="activeTab" class="w-full"> <div v-else class="flex items-center gap-2 pt-4 pb-1">
<TextButton
:label="$t('sideToolbar.labels.imported')"
:type="activeTab === 'input' ? 'secondary' : 'transparent'"
@click.stop="activeTab = 'input'"
/>
<TextButton
:label="$t('sideToolbar.labels.generated')"
:type="activeTab === 'output' ? 'secondary' : 'transparent'"
@click.stop="activeTab = 'output'"
/>
</div>
<!-- <Tabs v-else v-model:value="activeTab" class="w-full">
<TabList class="border-b border-neutral-300"> <TabList class="border-b border-neutral-300">
<Tab value="input">{{ $t('sideToolbar.labels.imported') }}</Tab> <Tab value="input">{{ $t('sideToolbar.labels.imported') }}</Tab>
<Tab value="output">{{ $t('sideToolbar.labels.generated') }}</Tab> <Tab value="output">{{ $t('sideToolbar.labels.generated') }}</Tab>
</TabList> </TabList>
</Tabs> </Tabs> -->
</template> </template>
<template #body> <template #body>
<VirtualGrid <VirtualGrid
@@ -87,7 +94,7 @@
/> />
</div> </div>
</template> </template>
</SidebarTabTemplate> </AssetsSidebarTemplate>
<ResultGallery <ResultGallery
v-model:active-index="galleryActiveIndex" v-model:active-index="galleryActiveIndex"
:all-gallery-items="galleryItems" :all-gallery-items="galleryItems"
@@ -96,15 +103,13 @@
<script setup lang="ts"> <script setup lang="ts">
import ProgressSpinner from 'primevue/progressspinner' import ProgressSpinner from 'primevue/progressspinner'
import Tab from 'primevue/tab'
import TabList from 'primevue/tablist'
import Tabs from 'primevue/tabs'
import { useToast } from 'primevue/usetoast' import { useToast } from 'primevue/usetoast'
import { computed, onMounted, ref, watch } from 'vue' import { computed, onMounted, ref, watch } from 'vue'
import IconTextButton from '@/components/button/IconTextButton.vue'
import TextButton from '@/components/button/TextButton.vue'
import NoResultsPlaceholder from '@/components/common/NoResultsPlaceholder.vue' import NoResultsPlaceholder from '@/components/common/NoResultsPlaceholder.vue'
import VirtualGrid from '@/components/common/VirtualGrid.vue' import VirtualGrid from '@/components/common/VirtualGrid.vue'
import SidebarTabTemplate from '@/components/sidebar/tabs/SidebarTabTemplate.vue'
import ResultGallery from '@/components/sidebar/tabs/queue/ResultGallery.vue' import ResultGallery from '@/components/sidebar/tabs/queue/ResultGallery.vue'
import MediaAssetCard from '@/platform/assets/components/MediaAssetCard.vue' import MediaAssetCard from '@/platform/assets/components/MediaAssetCard.vue'
import { useMediaAssets } from '@/platform/assets/composables/useMediaAssets' import { useMediaAssets } from '@/platform/assets/composables/useMediaAssets'
@@ -115,6 +120,8 @@ import {
getMediaTypeFromFilenamePlural getMediaTypeFromFilenamePlural
} from '@/utils/formatUtil' } from '@/utils/formatUtil'
import AssetsSidebarTemplate from './AssetSidebarTemplate.vue'
const activeTab = ref<'input' | 'output'>('input') const activeTab = ref<'input' | 'output'>('input')
const mediaAssets = ref<AssetItem[]>([]) const mediaAssets = ref<AssetItem[]>([])
const selectedAsset = ref<AssetItem | null>(null) const selectedAsset = ref<AssetItem | null>(null)

View File

@@ -597,6 +597,7 @@
"templates": "Templates", "templates": "Templates",
"assets": "Assets", "assets": "Assets",
"mediaAssets": "Media Assets", "mediaAssets": "Media Assets",
"backToAssets": "Back to all assets",
"labels": { "labels": {
"queue": "Queue", "queue": "Queue",
"nodes": "Nodes", "nodes": "Nodes",