Skip to content

Commit

Permalink
Make whole preservation task card a button
Browse files Browse the repository at this point in the history
  • Loading branch information
djjuhasz committed Jan 23, 2025
1 parent 9953385 commit 8f6c16d
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 105 deletions.
129 changes: 25 additions & 104 deletions dashboard/src/components/PreservationActionCollapse.vue
Original file line number Diff line number Diff line change
@@ -1,21 +1,14 @@
<script setup lang="ts">
import PackageReviewAlert from "@/components/PackageReviewAlert.vue";
import PreservationTask from "@/components/PreservationTask.vue";
import StatusBadge from "@/components/StatusBadge.vue";
import { useAuthStore } from "@/stores/auth";
import { onMounted, ref, toRefs } from "vue";
import IconChevronDown from "~icons/bi/chevron-down";
import { onMounted, ref, toRefs, computed } from "vue";
import type { api } from "@/client";
import type { EnduroPackagePreservationTask } from "@/openapi-generator";
type card = EnduroPackagePreservationTask & {
isOpen: boolean;
more: string;
};
const cards = ref<card[]>([]);
import type { TaskCard } from "@/components/PreservationTask.vue";
const tasks = ref<TaskCard[]>([]);
const authStore = useAuthStore();
const props = defineProps<{
Expand All @@ -25,30 +18,28 @@ 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");
const taskCards = computed(() => {
const tasks = props.action.tasks || [];
return tasks
.slice()
.reverse()
.map((task, index) => {
const card = <TaskCard>task;
card.index = tasks.length - index;
if (card.note?.includes("\n")) {
const [firstLine, ...remainingLines] = card.note.split("\n");
card.note = firstLine;
card.more = remainingLines.join("\n");
}
cards.value.push(card);
}
}
return card;
});
});
let expandCounter = ref<number>(0);
const isComplete = (task: EnduroPackagePreservationTask) => {
return task.status == "done" || task.status == "error";
};
onMounted(() => {
tasks.value = taskCards.value;
});
const toggleCard = (card: card, ev: Event) => {
card.isOpen = !card.isOpen;
ev.preventDefault();
};
let expandCounter = ref<number>(0);
</script>

<template>
Expand Down Expand Up @@ -87,7 +78,7 @@ const toggleCard = (card: card, ev: Event) => {
<div
v-if="action.tasks"
:id="'pa-body-' + index"
class="accordion-collapse collapse bg-light"
class="accordion-collapse collapse"
:aria-labelledby="'pa-heading-' + index"
data-bs-parent="#preservation-actions"
>
Expand All @@ -96,78 +87,8 @@ const toggleCard = (card: card, ev: Event) => {
v-model:expandCounter="expandCounter"
v-if="authStore.checkAttributes(['package:review'])"
/>
<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"
>
{{ 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">
{{ card.name }}
</div>
<div class="me-3">
<span
v-if="
!isComplete(card) &&
$filters.formatDateTime(card.startedAt)
"
>
Started:
{{ $filters.formatDateTime(card.startedAt) }}
</span>
<span
v-if="
isComplete(card) &&
$filters.formatDateTime(card.completedAt)
"
>
Completed:
{{ $filters.formatDateTime(card.completedAt) }}
</span>
</div>
</div>
<div class="d-flex flex-row gap-4">
<div class="flex-grow-1 line-break">
{{ 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 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>
<div v-for="(task, index) in tasks" :key="action.id" class="mb-2 card">
<PreservationTask :task="task" />
</div>
</div>
</div>
Expand Down
99 changes: 99 additions & 0 deletions dashboard/src/components/PreservationTask.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<script setup lang="ts">
import StatusBadge from "@/components/StatusBadge.vue";
import { toRefs } from "vue";
import IconChevronDown from "~icons/bi/chevron-down";
import type { EnduroPackagePreservationTask } from "@/openapi-generator";
export type TaskCard = EnduroPackagePreservationTask & {
index: number;
isOpen: boolean;
more: string;
};
const props = defineProps<{
task: TaskCard;
}>();
const { task: card } = toRefs(props);
const isComplete = (task: EnduroPackagePreservationTask) => {
return task.status == "done" || task.status == "error";
};
const toggleCard = (card: TaskCard, ev: Event) => {
if (!card.more) {
return;
}
card.isOpen = !card.isOpen;
ev.preventDefault();
};
</script>

<template>
<button
:class="{ 'card-body': true, disabled: !task.more }"
:aria-controls="'note-' + card.index + '-more'"
aria-label="Toggle display of additional notes"
:aria-disabled="!task.more"
@click="toggleCard(task, $event)"
>
<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"
>
{{ card.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">
{{ card.name }}
</div>
<div class="me-3">
<span
v-if="
!isComplete(card) && $filters.formatDateTime(card.startedAt)
"
>
Started:
{{ $filters.formatDateTime(card.startedAt) }}
</span>
<span
v-if="
isComplete(card) && $filters.formatDateTime(card.completedAt)
"
>
Completed:
{{ $filters.formatDateTime(card.completedAt) }}
</span>
</div>
</div>
<div class="d-flex flex-row gap-4">
<div class="flex-grow-1 line-break text-start">
{{ card.note }}
<Transition name="fade">
<p v-show="card.isOpen" :id="'note-' + card.index + '-more'">
{{ card.more }}
</p>
</Transition>
</div>
</div>
</div>
<div class="d-flex flex-column pt-1">
<div>
<StatusBadge :status="card.status" />
</div>
<div class="align-self-end">
<IconChevronDown
v-if="card.more"
:class="card.isOpen ? 'expander open' : 'expander closed'"
:alt="card.isOpen ? 'Collapse note' : 'Expand note'"
/>
</div>
</div>
</div>
</button>
</template>
19 changes: 18 additions & 1 deletion dashboard/src/styles/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,23 @@ a:not(.btn),
}
}

button.card-body {
background-color: $light;
border: 0px solid $gray-500;
box-shadow: none;
}

button.card-body:hover:not(.disabled),
button.card-body:focus:not(.disabled) {
background-color: $primary-bg-subtle;
border-color: $primary;
border-width: 2px;

.expander {
color: $primary;
}
}

.font-monospace {
line-height: 1;
padding-top: 6px;
Expand Down Expand Up @@ -51,11 +68,11 @@ a:not(.btn),
}

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

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

Expand Down

0 comments on commit 8f6c16d

Please sign in to comment.