refactor index page table implementation

- using new index.json without huge number network request and without huge number of reflow
- move style to stylesheet
- remove PackageListItem.vue
This commit is contained in:
sinsong 2023-07-03 22:15:28 +08:00
parent b742ad5f0b
commit 92cf8ea2c7
5 changed files with 66 additions and 81 deletions

View file

@ -3,6 +3,11 @@ async function requestPackageList () {
return await (await fetch(`${__API_BASE__}/api/pkglist.json`)).json()
}
export
async function requestPackageIndex () {
return await (await fetch(`${__API_BASE__}/api/index.json`)).json()
}
export
async function requestPackageInfo (pkg) {
return await (await fetch(`${__API_BASE__}/api/${pkg}.json`)).json()

View file

@ -1,10 +1,14 @@
<script setup>
import { ref, watch } from 'vue';
import PackageListItem from './PackageListItem.vue'
import { displayPackages } from '@/state'
import { useRouter } from 'vue-router'
import moment from 'moment'
const router = useRouter()
const tableHeaders = [
{ text: 'Name', field: 'name' },
{ text: 'Version', field: 'version' },
{ text: 'Description', field: 'desc' },
{ text: 'Last Build', field: 'builddate' },
]
const currentDisplay = ref([])
const count = ref(0)
@ -28,10 +32,6 @@ function displayPage() {
function pageUp() { if (currentPage > 1) { --currentPage; displayPage(); } }
function pageDown() { if (currentPage < pages) { ++currentPage; displayPage(); } }
function navigatorToItem(pkg) {
router.push(`/${pkg}`)
}
watch(
displayPackages,
async newVal => {
@ -50,20 +50,26 @@ watch(
</div>
</div>
<table id="index-table">
<thead>
<tr>
<td>Name</td>
<td>Version</td>
<td>Description</td>
<td>Last Build</td>
</tr>
</thead>
<tbody v-for="pkg in currentDisplay" :key="pkg">
<PackageListItem :pkgname="pkg" @click="navigatorToItem(pkg)"></PackageListItem>
</tbody>
</table>
<div class="table-scroll-wrapper">
<table id="index-table">
<thead>
<tr>
<td v-for="head in tableHeaders">{{ head.text }}</td>
</tr>
</thead>
<tbody>
<!-- <PackageListItem :pkgname="pkg.name" @click="navigatorToItem(pkg.name)"></PackageListItem> -->
<tr v-for="pkg in currentDisplay" :key="pkg.name">
<td v-for="heading in tableHeaders">
<router-link v-if="heading.field == 'name'" :to="`/${pkg.name}`">{{pkg.name}}</router-link>
<time v-else-if="heading.field == 'builddate'" :datetime="moment.unix(pkg.builddate).format()">{{ moment.unix(pkg.builddate).format('YYYY-MM-DD') }}</time>
<span v-else>{{ pkg[heading.field] }}</span>
</td>
</tr>
</tbody>
</table>
</div>
<div style="display: flex;">
<p>{{ count }} packages. page {{ currentPage }} of {{ pages }}.</p>
@ -73,9 +79,3 @@ watch(
</div>
</div>
</template>
<style>
#index-table {
width: 100%;
}
</style>

View file

@ -1,33 +0,0 @@
<script setup>
import { requestPackageInfo } from '@/api'
import { ref } from 'vue'
import moment from 'moment'
const props = defineProps({
pkgname: String
})
let info_name = ref("...")
let info_version = ref("...")
let info_desc = ref("...")
let info_date = ref("...")
// https://bioarchlinux.org/api/abacas.json
requestPackageInfo(props.pkgname)
.then(obj => {
info_name.value = obj.name
info_version.value = obj.version
info_desc.value = obj.desc
info_date.value = moment.unix(obj.builddate).format('YYYY-MM-DD')
})
</script>
<template>
<tr class="index-item">
<td>{{ info_name }}</td>
<td>{{ info_version }}</td>
<td>{{ info_desc }}</td>
<td>{{ info_date }}</td>
</tr>
</template>

View file

@ -18,14 +18,38 @@ table {
margin: .5em 0;
}
// search bar
.search {
width: 100%;
margin: 15px 0;
font-size: 15px;
padding: .5em .5em;
}
.box {
border: 1px solid #bcd;
padding: .5em;
background: var(--box-bg);
}
table#index-table thead {
border-bottom: 1px solid var(--index-thead-border);
.table-scroll-wrapper {
overflow-x: auto;
}
table#index-table {
width: 100%;
thead {
border-bottom: 1px solid var(--index-thead-border);
}
tbody {
td {
white-space: nowrap;
}
}
}
tr.index-item:hover {

View file

@ -4,37 +4,37 @@ import PackageList from '@/components/Index/PackageList.vue'
import Index from 'flexsearch/dist/module/index'
import { requestPackageInfo, requestPackageList } from '../api'
import { requestPackageIndex } from '../api'
import { displayPackages } from '@/state'
let packageList = null
let packageIndex = null
const searchIndex = new Index({ tokenize: 'forward' })
let searchInput = ref("")
function updateSearchIndex(pkglist) {
pkglist.forEach((content, index) => {
searchIndex.add(index, content)
searchIndex.add(index, content.name)
})
}
requestPackageList()
requestPackageIndex()
.then((obj) => {
packageList = obj
packageIndex = obj
displayPackages.value = obj
updateSearchIndex(obj)
})
watch(searchInput, async(newVal, oldVal) => {
if (searchInput.value.length === 0) {
displayPackages.value = packageList
displayPackages.value = packageIndex
}
else {
const searchResult = searchIndex.search(searchInput.value)
const finalResult = []
searchResult.forEach((elem) => {
finalResult.push(packageList[elem])
searchResult.forEach((idx) => {
finalResult.push(packageIndex[idx])
})
displayPackages.value = finalResult
}
@ -49,14 +49,3 @@ watch(searchInput, async(newVal, oldVal) => {
<PackageList></PackageList>
</div>
</template>
<style>
.search {
width: 100%;
margin: 15px 0;
font-size: 15px;
padding: .5em .5em;
}
</style>