Add search/filter to collections and fuzzy search to files
This commit is contained in:
parent
57aaa96a59
commit
477ebddcd3
|
|
@ -60,6 +60,13 @@
|
|||
</button>
|
||||
</div>
|
||||
|
||||
<input
|
||||
v-model="searchQuery"
|
||||
type="text"
|
||||
placeholder="Search..."
|
||||
class="w-full mb-4 px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-black"
|
||||
/>
|
||||
|
||||
<div class="bg-white rounded-lg shadow overflow-hidden mb-8">
|
||||
<table class="w-full">
|
||||
<thead class="bg-gray-50">
|
||||
|
|
@ -69,7 +76,7 @@
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="item in items" :key="item.id" class="border-t hover:bg-gray-50">
|
||||
<tr v-for="item in filteredItems" :key="item.id" class="border-t hover:bg-gray-50">
|
||||
<td class="px-4 py-3">{{ getTitle(item) }}</td>
|
||||
<td class="px-4 py-3 space-x-2">
|
||||
<button @click="viewRawJson(item)" class="text-green-600 hover:text-green-800">JSON</button>
|
||||
|
|
@ -91,6 +98,13 @@
|
|||
</label>
|
||||
</div>
|
||||
|
||||
<input
|
||||
v-model="fileSearchQuery"
|
||||
type="text"
|
||||
placeholder="Search files..."
|
||||
class="w-full mb-4 px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-black"
|
||||
/>
|
||||
|
||||
<div class="bg-white rounded-lg shadow overflow-hidden">
|
||||
<table class="w-full">
|
||||
<thead class="bg-gray-50">
|
||||
|
|
@ -101,7 +115,7 @@
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="file in files" :key="file.name" class="border-t hover:bg-gray-50">
|
||||
<tr v-for="file in filteredFiles" :key="file.name" class="border-t hover:bg-gray-50">
|
||||
<td class="px-4 py-3">{{ file.name }}</td>
|
||||
<td class="px-4 py-3 text-gray-500">{{ (file.size / 1024).toFixed(1) }} KB</td>
|
||||
<td class="px-4 py-3 space-x-2">
|
||||
|
|
@ -134,7 +148,7 @@
|
|||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch } from 'vue'
|
||||
import { ref, watch, computed } from 'vue'
|
||||
import { collections } from '@/admin/schemas'
|
||||
|
||||
const password = ref('')
|
||||
|
|
@ -147,6 +161,40 @@ const files = ref([])
|
|||
const rawJsonItem = ref(null)
|
||||
const rawJsonContent = ref('')
|
||||
const isUploading = ref(false)
|
||||
const searchQuery = ref('')
|
||||
const fileSearchQuery = ref('')
|
||||
|
||||
const searchFields = {
|
||||
works: ['title', 'type', 'instrument_tags'],
|
||||
publications: ['entryTags.title', 'entryTags.year', 'citationKey'],
|
||||
events: ['venue.name', 'venue.city', 'start_date'],
|
||||
releases: ['title', 'year'],
|
||||
talks: ['title', 'location', 'date']
|
||||
}
|
||||
|
||||
const filteredItems = computed(() => {
|
||||
if (!searchQuery.value.trim()) return items.value
|
||||
const query = searchQuery.value.toLowerCase()
|
||||
const fields = searchFields[selectedCollection.value] || []
|
||||
|
||||
return items.value.filter(item => {
|
||||
for (const field of fields) {
|
||||
const value = field.split('.').reduce((obj, key) => obj?.[key], item)
|
||||
if (value && String(value).toLowerCase().includes(query)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
})
|
||||
})
|
||||
|
||||
const filteredFiles = computed(() => {
|
||||
if (!fileSearchQuery.value.trim()) return files.value
|
||||
const normalize = (str) => str.toLowerCase().replace(/[\s_-]+/g, '')
|
||||
const query = normalize(fileSearchQuery.value)
|
||||
|
||||
return files.value.filter(file => normalize(file.name).includes(query))
|
||||
})
|
||||
|
||||
const fileFolders = [
|
||||
{ key: 'scores', label: 'Scores' },
|
||||
|
|
|
|||
Loading…
Reference in a new issue