Skip to content

Commit

Permalink
Use Tabs component for package status filter
Browse files Browse the repository at this point in the history
Refs #989.

Adapt the existing Tabs component to use it for filtering the package
list by status.

- Allow setting the package status filter by a "status" URL query
  parameter
- Update the "status" query parameter when clicking a filter tab
- Make the tab icons optional
- Include route parameters when checking if a tab is active
  • Loading branch information
djjuhasz committed Oct 30, 2024
1 parent f170662 commit 4239541
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 81 deletions.
60 changes: 0 additions & 60 deletions dashboard/src/components/PackageListTabFilters.vue

This file was deleted.

24 changes: 17 additions & 7 deletions dashboard/src/components/Tabs.vue
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
<script setup lang="ts">
import type { FunctionalComponent, SVGAttributes } from "vue";
import type { RouteLocationResolved } from "vue-router/auto";
import { useRoute } from "vue-router/auto";
import { isEqual } from "lodash-es";
const route = useRoute();
type Tab = {
icon?: FunctionalComponent<SVGAttributes, {}>;
text: string;
route: RouteLocationResolved;
show: boolean;
};
const { tabs } = defineProps<{
tabs: {
icon: FunctionalComponent<SVGAttributes, {}>;
text: string;
route: RouteLocationResolved;
show: boolean;
}[];
tabs: Tab[];
}>();
function isActive(tab: Tab): boolean {
return tab.route.path == route.path && isEqual(tab.route.query, route.query);
}
</script>

<template>
Expand All @@ -20,7 +30,7 @@ const { tabs } = defineProps<{
v-if="tab.show"
:to="tab.route"
class="nav-link text-primary text-nowrap d-flex align-items-center"
exact-active-class="active"
:class="{ active: isActive(tab) }"
>
<span v-html="tab.icon" class="me-2 text-dark" aria-hidden="true" />{{
tab.text
Expand Down
100 changes: 86 additions & 14 deletions dashboard/src/pages/packages/index.vue
Original file line number Diff line number Diff line change
@@ -1,44 +1,116 @@
<script setup lang="ts">
import PackageListTabFilters from "@/components/PackageListTabFilters.vue";
import type { PackageListStatusEnum } from "@/openapi-generator";
import PackageListLegend from "@/components/PackageListLegend.vue";
import PageLoadingAlert from "@/components/PageLoadingAlert.vue";
import StatusBadge from "@/components/StatusBadge.vue";
import Tabs from "@/components/Tabs.vue";
import Tooltip from "bootstrap/js/dist/tooltip";
import UUID from "@/components/UUID.vue";
import { onMounted } from "vue";
import { useAsyncState } from "@vueuse/core";
import { useAuthStore } from "@/stores/auth";
import { useLayoutStore } from "@/stores/layout";
import { usePackageStore } from "@/stores/package";
import { useAsyncState } from "@vueuse/core";
import Tooltip from "bootstrap/js/dist/tooltip";
import { onMounted } from "vue";
import { useRoute, useRouter } from "vue-router/auto";
import { watch } from "vue";
// General icons.
import IconInfoFill from "~icons/akar-icons/info-fill";
import IconBundleLine from "~icons/clarity/bundle-line";
// Pager icons.
import IconSkipEndFill from "~icons/bi/skip-end-fill";
import IconSkipStartFill from "~icons/bi/skip-start-fill";
import IconCaretRightFill from "~icons/bi/caret-right-fill";
import IconCaretLeftFill from "~icons/bi/caret-left-fill";
// Tab icons.
import RawIconCheckCircleLine from "~icons/clarity/check-circle-line?raw&font-size=20px";
import RawIconTimesCircleLine from "~icons/clarity/times-circle-line?raw&font-size=20px";
import RawIconPlayLine from "~icons/clarity/play-line?raw&font-size=20px";
import RawIconBarsLine from "~icons/clarity/bars-line?raw&font-size=20px";
const authStore = useAuthStore();
const layoutStore = useLayoutStore();
layoutStore.updateBreadcrumb([{ text: "Packages" }]);
const packageStore = usePackageStore();
const { execute, error } = useAsyncState(() => {
return packageStore.fetchPackages(1);
}, null);
const route = useRoute("/packages/");
const router = useRouter();
layoutStore.updateBreadcrumb([{ text: "Packages" }]);
const el = $ref<HTMLElement | null>(null);
let tooltip: Tooltip | null = null;
onMounted(() => {
if (el) tooltip = new Tooltip(el);
});
let showLegend = $ref(false);
const toggleLegend = () => {
showLegend = !showLegend;
if (tooltip) tooltip.hide();
};
onMounted(() => {
if (el) tooltip = new Tooltip(el);
packageStore.filters.status = <PackageListStatusEnum>route.query.status;
});
const tabs = [
{
text: "All",
route: router.resolve({
name: "/packages/",
}),
show: true,
},
{
icon: RawIconCheckCircleLine,
text: "Done",
route: router.resolve({
name: "/packages/",
query: { status: "done" },
}),
show: true,
},
{
icon: RawIconPlayLine,
text: "Error",
route: router.resolve({
name: "/packages/",
query: { status: "error" },
}),
show: true,
},
{
icon: RawIconTimesCircleLine,
text: "In progress",
route: router.resolve({
name: "/packages/",
query: { status: "in progress" },
}),
show: true,
},
{
icon: RawIconBarsLine,
text: "Queued",
route: router.resolve({
name: "/packages/",
query: { status: "queued" },
}),
show: true,
},
];
const { execute, error } = useAsyncState(() => {
return packageStore.fetchPackages(1);
}, null);
watch(
() => route.query.status,
(newStatus) => {
packageStore.filters.status = newStatus as PackageListStatusEnum;
return packageStore.fetchPackages(1);
},
);
</script>

<template>
Expand All @@ -53,10 +125,10 @@ const toggleLegend = () => {
{{ packageStore.page.total }}
</div>

<PackageListTabFilters />
<PageLoadingAlert :execute="execute" :error="error" />
<PackageListLegend v-model="showLegend" />

<Tabs :tabs="tabs" />
<div class="table-responsive mb-3">
<table class="table table-bordered mb-0">
<thead>
Expand Down

0 comments on commit 4239541

Please sign in to comment.