Skip to content

Commit d9ed82f

Browse files
committed
feat: add search for assets
1 parent 56f6264 commit d9ed82f

File tree

2 files changed

+62
-25
lines changed

2 files changed

+62
-25
lines changed

packages/devtools/src/app/components/data/SearchPanel.vue

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type { FilterMatchRule } from '~/utils/icon'
33
import { useVModel } from '@vueuse/core'
44
import { withDefaults } from 'vue'
55
6-
interface ModelValue { search: string, selected: string[] | null }
6+
interface ModelValue { search: string, selected?: string[] | null }
77
88
const props = withDefaults(
99
defineProps<{
@@ -71,7 +71,7 @@ function unselectToggle() {
7171

7272
<template>
7373
<div flex="col gap-2" max-w-90vw min-w-30vw border="~ base rounded-xl" bg-glass>
74-
<div border="b base">
74+
<div>
7575
<input
7676
v-model="model.search"
7777
p2 px4
@@ -80,7 +80,7 @@ function unselectToggle() {
8080
placeholder="Search"
8181
>
8282
</div>
83-
<div flex="~ gap-2 wrap" p2>
83+
<div v-if="rules.length" flex="~ gap-2 wrap" p2 border="t base">
8484
<label
8585
v-for="rule of rules"
8686
:key="rule.name"

packages/devtools/src/app/pages/session/[session]/assets.vue

Lines changed: 59 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,19 @@
22
import type { SessionContext } from '~~/shared/types'
33
import type { ClientSettings } from '~/state/settings'
44
import { useRpc } from '#imports'
5-
import { useAsyncState } from '@vueuse/core'
5+
import { computedWithControl, useAsyncState } from '@vueuse/core'
6+
import Fuse from 'fuse.js'
7+
import { computed, ref } from 'vue'
68
import { settings } from '~/state/settings'
79
810
const props = defineProps<{
911
session: SessionContext
1012
}>()
1113
14+
const searchValue = ref<{ search: string }>({
15+
search: '',
16+
})
17+
1218
const assetViewTpyes = [
1319
{
1420
label: 'List',
@@ -36,34 +42,65 @@ const { state: assets, isLoading } = useAsyncState(
3642
null,
3743
)
3844
45+
const fuse = computedWithControl(
46+
() => assets.value,
47+
() => new Fuse(assets.value!, {
48+
includeScore: true,
49+
keys: ['filename'],
50+
ignoreLocation: true,
51+
threshold: 0.4,
52+
}),
53+
)
54+
55+
const searched = computed(() => {
56+
if (!searchValue.value.search) {
57+
return assets.value!
58+
}
59+
return fuse.value
60+
.search(searchValue.value.search)
61+
.map(r => r.item)
62+
})
63+
3964
function toggleDisplay(type: ClientSettings['assetViewType']) {
4065
settings.value.assetViewType = type
4166
}
4267
</script>
4368

4469
<template>
4570
<VisualLoading v-if="isLoading" />
46-
<div v-else p4 flex="~ col gap-4">
47-
<div flex="~ gap-2">
48-
<button
49-
v-for="viewType of assetViewTpyes"
50-
:key="viewType.value"
51-
btn-action
52-
:class="settings.assetViewType === viewType.value ? 'bg-active' : 'grayscale op50'"
53-
@click="toggleDisplay(viewType.value)"
54-
>
55-
<div :class="viewType.icon" />
56-
{{ viewType.label }}
57-
</button>
71+
<div v-else relative max-h-screen of-hidden>
72+
<div absolute left-4 top-4 z-panel-nav>
73+
<DataSearchPanel v-model="searchValue" :rules="[]">
74+
<div flex="~ gap-2 items-center" p2 border="t base">
75+
<span op50 pl2 text-sm>View as</span>
76+
<button
77+
v-for="viewType of assetViewTpyes"
78+
:key="viewType.value"
79+
btn-action
80+
:class="settings.assetViewType === viewType.value ? 'bg-active' : 'grayscale op50'"
81+
@click="toggleDisplay(viewType.value)"
82+
>
83+
<div :class="viewType.icon" />
84+
{{ viewType.label }}
85+
</button>
86+
</div>
87+
</DataSearchPanel>
88+
</div>
89+
<div of-auto h-screen flex="~ col gap-2" pt32>
90+
<template v-if="settings.assetViewType === 'list'">
91+
<AssetsList v-if="searched?.length" :assets="searched" :session="session" />
92+
</template>
93+
<template v-else-if="settings.assetViewType === 'folder'">
94+
<AssetsFolder v-if="searched?.length" :assets="searched" :session="session" />
95+
</template>
96+
<template v-else-if="settings.assetViewType === 'treemap'">
97+
<AssetsTreemap v-if="searched?.length" :assets="searched" :session="session" />
98+
</template>
99+
</div>
100+
<div
101+
absolute bottom-4 py-1 px-2 bg-glass left="1/2" translate-x="-1/2" border="~ base rounded-full" text="center xs"
102+
>
103+
<span op50>{{ searched.length }} of {{ assets?.length || 0 }}</span>
58104
</div>
59-
<template v-if="settings.assetViewType === 'list'">
60-
<AssetsList v-if="assets?.length" :assets="assets" :session="session" />
61-
</template>
62-
<template v-else-if="settings.assetViewType === 'folder'">
63-
<AssetsFolder v-if="assets?.length" :assets="assets" :session="session" />
64-
</template>
65-
<template v-else-if="settings.assetViewType === 'treemap'">
66-
<AssetsTreemap v-if="assets?.length" :assets="assets" :session="session" />
67-
</template>
68105
</div>
69106
</template>

0 commit comments

Comments
 (0)