Files
ComfyUI_frontend/src/components/maintenance/TaskCard.vue
Alexander Brown 85017dbba0 Upgrade: Tailwind v4 (#5246)
* temp: move tailwind calls out of the layer

* temp: ts tailwind config

* upgrade: Tailwind v4
This got a little out of hand.
Had to add a relative reference to the stylesheet in any component that uses @apply instead of the utility classes directly.

* upgrade: bg-opacity is now a modifier

* fix: Classic menu buttons assume a border

* Update test expectations [skip ci]

* fix: New preflight removal pattern

* fix: Skeletons don't have skin

* Update test expectations [skip ci]

* fix: Missing @reference

* [auto-fix] Apply ESLint and Prettier fixes

---------

Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: GitHub Action <action@github.com>
2025-09-03 12:37:43 -07:00

134 lines
3.1 KiB
Vue

<template>
<div
class="task-div max-w-48 min-h-52 grid relative"
:class="{ 'opacity-75': isLoading }"
>
<Card
class="max-w-48 relative h-full overflow-hidden"
:class="{ 'opacity-65': runner.state !== 'error' }"
v-bind="(({ onClick, ...rest }) => rest)($attrs)"
>
<template #header>
<i
v-if="runner.state === 'error'"
class="pi pi-exclamation-triangle text-red-500 absolute m-2 top-0 -right-14 opacity-15"
style="font-size: 10rem"
/>
<img
v-if="task.headerImg"
:src="task.headerImg"
class="object-contain w-full h-full opacity-25 pt-4 px-4"
/>
</template>
<template #title>
{{ task.name }}
</template>
<template #content>
{{ description }}
</template>
<template #footer>
<div class="flex gap-4 mt-1">
<Button
:icon="task.button?.icon"
:label="task.button?.text"
class="w-full"
raised
icon-pos="right"
:loading="isExecuting"
@click="(event) => $emit('execute', event)"
/>
</div>
</template>
</Card>
<i
v-if="!isLoading && runner.state === 'OK'"
class="task-card-ok pi pi-check"
/>
</div>
</template>
<script setup lang="ts">
import Button from 'primevue/button'
import Card from 'primevue/card'
import { computed } from 'vue'
import { useMaintenanceTaskStore } from '@/stores/maintenanceTaskStore'
import type { MaintenanceTask } from '@/types/desktop/maintenanceTypes'
import { useMinLoadingDurationRef } from '@/utils/refUtil'
const taskStore = useMaintenanceTaskStore()
const runner = computed(() => taskStore.getRunner(props.task))
// Properties
const props = defineProps<{
task: MaintenanceTask
}>()
// Events
defineEmits<{
execute: [event: MouseEvent]
}>()
// Bindings
const description = computed(() =>
runner.value.state === 'error'
? props.task.errorDescription ?? props.task.shortDescription
: props.task.shortDescription
)
// Use a minimum run time to ensure tasks "feel" like they have run
const reactiveLoading = computed(() => !!runner.value.refreshing)
const reactiveExecuting = computed(() => !!runner.value.executing)
const isLoading = useMinLoadingDurationRef(reactiveLoading, 250)
const isExecuting = useMinLoadingDurationRef(reactiveExecuting, 250)
</script>
<style scoped>
@reference '../../assets/css/style.css';
.task-card-ok {
@apply text-green-500 absolute -right-4 -bottom-4 opacity-100 row-span-full col-span-full transition-opacity;
font-size: 4rem;
text-shadow: 0.25rem 0 0.5rem black;
z-index: 10;
}
.p-card {
@apply transition-opacity;
--p-card-background: var(--p-button-secondary-background);
opacity: 0.9;
&.opacity-65 {
opacity: 0.4;
}
&:hover {
opacity: 1;
}
}
:deep(.p-card-header) {
z-index: 0;
}
:deep(.p-card-body) {
z-index: 1;
flex-grow: 1;
justify-content: space-between;
}
.task-div {
> i {
pointer-events: none;
}
&:hover > i {
opacity: 0.2;
}
}
</style>