feat(manager): favorites filter as chip toggle box in filter panel
Move the favorites filter from a per-view checkbox field into a built-in "Quick filters" chip section in ModuleListView, styled identically to the extra-filter syntax chips (wp-chip--toggle). Clicking toggles the filled accent-tinted box state. Removes duplicated wp-fav-toggle label+Checkbox blocks from all six list views and cleans up the now-unused Checkbox imports. Updates the ModuleListView test to assert both the favorites chip and any extra-filter chips are present in the panel.
This commit is contained in:
@@ -119,9 +119,11 @@ describe("ModuleListView.vue", () => {
|
||||
await filtersBtn.trigger("click");
|
||||
await flushPromises();
|
||||
expect(wrap.find(".wp-filter-panel").exists()).toBe(true);
|
||||
// Extra filter chip is rendered inside.
|
||||
expect(wrap.find(".wp-chip--toggle").exists()).toBe(true);
|
||||
expect(wrap.find(".wp-chip--toggle").text()).toContain("Favorited");
|
||||
// Favorites quick-filter chip and extra-filter chips are both rendered.
|
||||
const toggleChips = wrap.findAll(".wp-chip--toggle");
|
||||
expect(toggleChips.length).toBeGreaterThanOrEqual(2);
|
||||
expect(toggleChips.some((c) => c.text().includes("Favorites only"))).toBe(true);
|
||||
expect(toggleChips.some((c) => c.text().includes("Favorited"))).toBe(true);
|
||||
});
|
||||
|
||||
it("paginates 20 items into pages of 10 then 10 when pageSize=10", async () => {
|
||||
|
||||
@@ -354,6 +354,19 @@ defineExpose({
|
||||
<Transition name="filter-collapse">
|
||||
<div v-if="filtersOpen" class="wp-filter-panel">
|
||||
<slot name="filter-panel" :filter="filter" :emit-fetch="emitFetch" />
|
||||
<div v-if="showFavorite" class="wp-filter-panel__extra">
|
||||
<span class="wp-filter-panel__extra-label">Quick filters</span>
|
||||
<div class="wp-filter-panel__extra-chips">
|
||||
<button
|
||||
type="button"
|
||||
class="wp-chip wp-chip--toggle"
|
||||
:data-active="filter.favorites ? '' : null"
|
||||
@click="filter.favorites = !filter.favorites; emitFetch()"
|
||||
>
|
||||
★ Favorites only
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="extraFilters?.length" class="wp-filter-panel__extra">
|
||||
<span class="wp-filter-panel__extra-label">Syntax</span>
|
||||
<div class="wp-filter-panel__extra-chips">
|
||||
|
||||
@@ -4,7 +4,6 @@ import { useRouter } from "vue-router";
|
||||
import { useToast } from "../composables/useToast";
|
||||
import ModuleListView from "../components/ModuleListView.vue";
|
||||
import Button from "../components/ui/Button.vue";
|
||||
import Checkbox from "../components/ui/Checkbox.vue";
|
||||
import Select from "../components/ui/Select.vue";
|
||||
import { useModuleStore } from "../stores/moduleStore";
|
||||
import { catChipStyle } from "../utils/catChip";
|
||||
@@ -152,16 +151,7 @@ function templateParts(row: ModuleRow): TemplatePart[] {
|
||||
@update:model-value="(v) => { filter.category = v as string | null; emitFetch(); }"
|
||||
/>
|
||||
</div>
|
||||
<div class="wp-field">
|
||||
<label class="wp-field__label">Favorites</label>
|
||||
<label class="wp-fav-toggle">
|
||||
<Checkbox
|
||||
:model-value="!!filter.favorites"
|
||||
@update:model-value="(v) => { filter.favorites = v; emitFetch(); }"
|
||||
/>
|
||||
<span>Favorites only</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="wp-field wp-field--full">
|
||||
<label class="wp-field__label">
|
||||
Tags{{ filter.tags?.length ? ` (${filter.tags.length})` : "" }}
|
||||
|
||||
@@ -4,7 +4,6 @@ import { useRouter } from "vue-router";
|
||||
import { useToast } from "../composables/useToast";
|
||||
import ModuleListView from "../components/ModuleListView.vue";
|
||||
import Button from "../components/ui/Button.vue";
|
||||
import Checkbox from "../components/ui/Checkbox.vue";
|
||||
import Select from "../components/ui/Select.vue";
|
||||
import { useModuleStore } from "../stores/moduleStore";
|
||||
import { catChipStyle } from "../utils/catChip";
|
||||
@@ -188,16 +187,7 @@ function formatFactor(f: number): string {
|
||||
@update:model-value="(v) => { filter.category = v as string | null; emitFetch(); }"
|
||||
/>
|
||||
</div>
|
||||
<div class="wp-field">
|
||||
<label class="wp-field__label">Favorites</label>
|
||||
<label class="wp-fav-toggle">
|
||||
<Checkbox
|
||||
:model-value="!!filter.favorites"
|
||||
@update:model-value="(v) => { filter.favorites = v; emitFetch(); }"
|
||||
/>
|
||||
<span>Favorites only</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="wp-field wp-field--full">
|
||||
<label class="wp-field__label">
|
||||
Tags{{ filter.tags?.length ? ` (${filter.tags.length})` : "" }}
|
||||
|
||||
@@ -4,7 +4,6 @@ import { useRouter } from "vue-router";
|
||||
import { useToast } from "../composables/useToast";
|
||||
import ModuleListView from "../components/ModuleListView.vue";
|
||||
import Button from "../components/ui/Button.vue";
|
||||
import Checkbox from "../components/ui/Checkbox.vue";
|
||||
import Select from "../components/ui/Select.vue";
|
||||
import { useModuleStore } from "../stores/moduleStore";
|
||||
import { catChipStyle } from "../utils/catChip";
|
||||
@@ -152,16 +151,7 @@ function actView(a: DerivationAction | undefined): { verb: string; target: strin
|
||||
@update:model-value="(v) => { filter.category = v as string | null; emitFetch(); }"
|
||||
/>
|
||||
</div>
|
||||
<div class="wp-field">
|
||||
<label class="wp-field__label">Favorites</label>
|
||||
<label class="wp-fav-toggle">
|
||||
<Checkbox
|
||||
:model-value="!!filter.favorites"
|
||||
@update:model-value="(v) => { filter.favorites = v; emitFetch(); }"
|
||||
/>
|
||||
<span>Favorites only</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="wp-field wp-field--full">
|
||||
<label class="wp-field__label">
|
||||
Tags{{ filter.tags?.length ? ` (${filter.tags.length})` : "" }}
|
||||
|
||||
@@ -4,7 +4,6 @@ import { useRouter } from "vue-router";
|
||||
import { useToast } from "../composables/useToast";
|
||||
import ModuleListView from "../components/ModuleListView.vue";
|
||||
import Button from "../components/ui/Button.vue";
|
||||
import Checkbox from "../components/ui/Checkbox.vue";
|
||||
import Select from "../components/ui/Select.vue";
|
||||
import { useModuleStore } from "../stores/moduleStore";
|
||||
import { catChipStyle } from "../utils/catChip";
|
||||
@@ -128,16 +127,7 @@ function topValues(row: ModuleRow): NamedValue[] { return values(row).slice(0, 4
|
||||
@update:model-value="(v) => { filter.category = v as string | null; emitFetch(); }"
|
||||
/>
|
||||
</div>
|
||||
<div class="wp-field">
|
||||
<label class="wp-field__label">Favorites</label>
|
||||
<label class="wp-fav-toggle">
|
||||
<Checkbox
|
||||
:model-value="!!filter.favorites"
|
||||
@update:model-value="(v) => { filter.favorites = v; emitFetch(); }"
|
||||
/>
|
||||
<span>Favorites only</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="wp-field wp-field--full">
|
||||
<label class="wp-field__label">
|
||||
Tags{{ filter.tags?.length ? ` (${filter.tags.length})` : "" }}
|
||||
|
||||
@@ -4,7 +4,6 @@ import { useRouter } from "vue-router";
|
||||
import { useToast } from "../composables/useToast";
|
||||
import ModuleListView from "../components/ModuleListView.vue";
|
||||
import Button from "../components/ui/Button.vue";
|
||||
import Checkbox from "../components/ui/Checkbox.vue";
|
||||
import Select from "../components/ui/Select.vue";
|
||||
import { useModuleStore } from "../stores/moduleStore";
|
||||
import { catChipStyle } from "../utils/catChip";
|
||||
@@ -198,16 +197,7 @@ function pad2(n: number): string { return String(n + 1).padStart(2, "0"); }
|
||||
@update:model-value="(v) => { filter.category = v as string | null; emitFetch(); }"
|
||||
/>
|
||||
</div>
|
||||
<div class="wp-field">
|
||||
<label class="wp-field__label">Favorites</label>
|
||||
<label class="wp-fav-toggle">
|
||||
<Checkbox
|
||||
:model-value="!!filter.favorites"
|
||||
@update:model-value="(v) => { filter.favorites = v; emitFetch(); }"
|
||||
/>
|
||||
<span>Favorites only</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="wp-field wp-field--full">
|
||||
<label class="wp-field__label">
|
||||
Tags{{ filter.tags?.length ? ` (${filter.tags.length})` : "" }}
|
||||
|
||||
@@ -5,7 +5,6 @@ import { useToast } from "../composables/useToast";
|
||||
import ModuleListView from "../components/ModuleListView.vue";
|
||||
import RichTextPreview from "../components/RichTextPreview.vue";
|
||||
import Button from "../components/ui/Button.vue";
|
||||
import Checkbox from "../components/ui/Checkbox.vue";
|
||||
import Select from "../components/ui/Select.vue";
|
||||
import { useModuleStore } from "../stores/moduleStore";
|
||||
import { catChipStyle } from "../utils/catChip";
|
||||
@@ -188,18 +187,7 @@ function isValid(row: ModuleRow): boolean {
|
||||
@update:model-value="(v) => { filter.category = v as string | null; emitFetch(); }"
|
||||
/>
|
||||
</div>
|
||||
<div class="wp-field">
|
||||
<label class="wp-field__label">
|
||||
Favorites
|
||||
</label>
|
||||
<label class="wp-fav-toggle">
|
||||
<Checkbox
|
||||
:model-value="!!filter.favorites"
|
||||
@update:model-value="(v) => { filter.favorites = v; emitFetch(); }"
|
||||
/>
|
||||
<span>Favorites only</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="wp-field wp-field--full">
|
||||
<label class="wp-field__label">
|
||||
Tags{{ filter.tags?.length ? ` (${filter.tags.length})` : "" }}
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
<link rel="icon" type="image/svg+xml" href="/wp/images/favicon.svg" />
|
||||
<link rel="apple-touch-icon" href="/wp/images/apple-touch-icon.png" />
|
||||
<link rel="manifest" href="/wp/images/site.webmanifest" />
|
||||
<script type="module" crossorigin src="/wp/assets/manager-D8EREGee.js"></script>
|
||||
<script type="module" crossorigin src="/wp/assets/manager-baYgQ7LG.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/wp/assets/manager-C6od6CgI.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
Reference in New Issue
Block a user