Skip to content

Commit

Permalink
Make preservation task cards expandable
Browse files Browse the repository at this point in the history
Fixes #1077.

- Show only the first line of a multi-line task note by default
- Show an icon on task cards with multi-line notes to toggle display of
  the subsequent lines of the note
- Add css animations for the expansion and contraction of the
  additional note content
  • Loading branch information
djjuhasz committed Jan 22, 2025
1 parent 00d95d8 commit 9953385
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 21 deletions.
90 changes: 69 additions & 21 deletions dashboard/src/components/PreservationActionCollapse.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
<script setup lang="ts">
import type { api } from "@/client";
import PackageReviewAlert from "@/components/PackageReviewAlert.vue";
import type { EnduroPackagePreservationTask } from "@/openapi-generator";
import StatusBadge from "@/components/StatusBadge.vue";
import { useAuthStore } from "@/stores/auth";
import { ref, toRefs } from "vue";
import { onMounted, ref, toRefs } from "vue";
import IconChevronDown from "~icons/bi/chevron-down";
import type { api } from "@/client";
import type { EnduroPackagePreservationTask } from "@/openapi-generator";
type card = EnduroPackagePreservationTask & {
isOpen: boolean;
more: string;
};
const cards = ref<card[]>([]);
const authStore = useAuthStore();
Expand All @@ -15,11 +25,30 @@ const props = defineProps<{
const { action, index } = toRefs(props);
onMounted(() => {
if (props.action.tasks) {
for (const task of props.action.tasks.reverse()) {
let card = <card>task;
if (card.note && card.note.includes("\n")) {
const lines = card.note.split("\n");
card.note = lines[0];
card.more = lines.slice(1).join("\n");
}
cards.value.push(card);
}
}
});
let expandCounter = ref<number>(0);
function isComplete(task: EnduroPackagePreservationTask) {
const isComplete = (task: EnduroPackagePreservationTask) => {
return task.status == "done" || task.status == "error";
}
};
const toggleCard = (card: card, ev: Event) => {
card.isOpen = !card.isOpen;
ev.preventDefault();
};
</script>

<template>
Expand Down Expand Up @@ -67,56 +96,75 @@ function isComplete(task: EnduroPackagePreservationTask) {
v-model:expandCounter="expandCounter"
v-if="authStore.checkAttributes(['package:review'])"
/>
<div
v-for="(task, index) in action.tasks.slice().reverse()"
:key="action.id"
class="card"
>
<div v-for="(card, index) in cards" :key="action.id" class="mb-2 card">
<div class="card-body">
<div class="d-flex flex-row align-start gap-3">
<div class="fd-flex">
<span
class="fs-6 badge rounded-pill border border-primary text-primary"
>
{{ action.tasks.length - index }}
{{ cards.length - index }}
</span>
</div>
<div
class="d-flex flex-column flex-grow-1 align-content-stretch min-w-0"
>
<div class="d-flex flex-wrap pt-1">
<div class="me-auto text-truncate fw-bold">
{{ task.name }}
{{ card.name }}
</div>
<div class="me-3">
<span
v-if="
!isComplete(task) &&
$filters.formatDateTime(task.startedAt)
!isComplete(card) &&
$filters.formatDateTime(card.startedAt)
"
>
Started:
{{ $filters.formatDateTime(task.startedAt) }}
{{ $filters.formatDateTime(card.startedAt) }}
</span>
<span
v-if="
isComplete(task) &&
$filters.formatDateTime(task.completedAt)
isComplete(card) &&
$filters.formatDateTime(card.completedAt)
"
>
Completed:
{{ $filters.formatDateTime(task.completedAt) }}
{{ $filters.formatDateTime(card.completedAt) }}
</span>
</div>
</div>
<div class="d-flex flex-row gap-4">
<div class="flex-grow-1 line-break">
{{ task.note }}
{{ card.note }}
<Transition name="fade">
<p v-show="card.isOpen" :id="'note-' + index + '-more'">
{{ card.more }}
</p>
</Transition>
</div>
</div>
</div>
<div class="d-flex pt-1">
<StatusBadge :status="task.status" />
<div class="d-flex flex-column pt-1">
<div>
<StatusBadge :status="card.status" />
</div>
<div class="align-self-end">
<a
v-if="card.more"
:href="'#note-' + index + '-more'"
@click="toggleCard(card, $event)"
aria-expanded="false"
role="button"
aria-label="Toggle display of additional notes"
:aria-controls="'note-' + index + '-more'"
>
<IconChevronDown
:class="card.isOpen ? 'expander open' : 'expander closed'"
:alt="card.isOpen ? 'Collapse note' : 'Expand note'"
/>
</a>
</div>
</div>
</div>
</div>
Expand Down
33 changes: 33 additions & 0 deletions dashboard/src/styles/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,36 @@ a:not(.btn),
.accordion-button.collapsed .h4 {
color: $dark;
}

.expander.closed {
transform: rotate(-180deg);
transition: $accordion-icon-transition;
}

.expander.open {
transition: $accordion-icon-transition;
}

@media (prefers-reduced-motion) {
.expander.open {
transition: none;
}
.expander.closed {
transition: none;
}
}

.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s ease;
}

.fade-enter-to,
.fade-leave-from {
opacity: 1;
}

.fade-enter-from,
.fade-leave-to {
opacity: 0;
}

0 comments on commit 9953385

Please sign in to comment.