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() 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 export
async function requestPackageInfo (pkg) { async function requestPackageInfo (pkg) {
return await (await fetch(`${__API_BASE__}/api/${pkg}.json`)).json() return await (await fetch(`${__API_BASE__}/api/${pkg}.json`)).json()

View file

@ -1,10 +1,14 @@
<script setup> <script setup>
import { ref, watch } from 'vue'; import { ref, watch } from 'vue';
import PackageListItem from './PackageListItem.vue'
import { displayPackages } from '@/state' 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 currentDisplay = ref([])
const count = ref(0) const count = ref(0)
@ -28,10 +32,6 @@ function displayPage() {
function pageUp() { if (currentPage > 1) { --currentPage; displayPage(); } } function pageUp() { if (currentPage > 1) { --currentPage; displayPage(); } }
function pageDown() { if (currentPage < pages) { ++currentPage; displayPage(); } } function pageDown() { if (currentPage < pages) { ++currentPage; displayPage(); } }
function navigatorToItem(pkg) {
router.push(`/${pkg}`)
}
watch( watch(
displayPackages, displayPackages,
async newVal => { async newVal => {
@ -50,20 +50,26 @@ watch(
</div> </div>
</div> </div>
<table id="index-table"> <div class="table-scroll-wrapper">
<thead> <table id="index-table">
<tr> <thead>
<td>Name</td> <tr>
<td>Version</td> <td v-for="head in tableHeaders">{{ head.text }}</td>
<td>Description</td> </tr>
<td>Last Build</td> </thead>
</tr>
</thead> <tbody>
<!-- <PackageListItem :pkgname="pkg.name" @click="navigatorToItem(pkg.name)"></PackageListItem> -->
<tbody v-for="pkg in currentDisplay" :key="pkg"> <tr v-for="pkg in currentDisplay" :key="pkg.name">
<PackageListItem :pkgname="pkg" @click="navigatorToItem(pkg)"></PackageListItem> <td v-for="heading in tableHeaders">
</tbody> <router-link v-if="heading.field == 'name'" :to="`/${pkg.name}`">{{pkg.name}}</router-link>
</table> <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;"> <div style="display: flex;">
<p>{{ count }} packages. page {{ currentPage }} of {{ pages }}.</p> <p>{{ count }} packages. page {{ currentPage }} of {{ pages }}.</p>
@ -73,9 +79,3 @@ watch(
</div> </div>
</div> </div>
</template> </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; margin: .5em 0;
} }
// search bar
.search {
width: 100%;
margin: 15px 0;
font-size: 15px;
padding: .5em .5em;
}
.box { .box {
border: 1px solid #bcd; border: 1px solid #bcd;
padding: .5em; padding: .5em;
background: var(--box-bg); background: var(--box-bg);
} }
table#index-table thead { .table-scroll-wrapper {
border-bottom: 1px solid var(--index-thead-border); 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 { 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 Index from 'flexsearch/dist/module/index'
import { requestPackageInfo, requestPackageList } from '../api' import { requestPackageIndex } from '../api'
import { displayPackages } from '@/state' import { displayPackages } from '@/state'
let packageList = null let packageIndex = null
const searchIndex = new Index({ tokenize: 'forward' }) const searchIndex = new Index({ tokenize: 'forward' })
let searchInput = ref("") let searchInput = ref("")
function updateSearchIndex(pkglist) { function updateSearchIndex(pkglist) {
pkglist.forEach((content, index) => { pkglist.forEach((content, index) => {
searchIndex.add(index, content) searchIndex.add(index, content.name)
}) })
} }
requestPackageList() requestPackageIndex()
.then((obj) => { .then((obj) => {
packageList = obj packageIndex = obj
displayPackages.value = obj displayPackages.value = obj
updateSearchIndex(obj) updateSearchIndex(obj)
}) })
watch(searchInput, async(newVal, oldVal) => { watch(searchInput, async(newVal, oldVal) => {
if (searchInput.value.length === 0) { if (searchInput.value.length === 0) {
displayPackages.value = packageList displayPackages.value = packageIndex
} }
else { else {
const searchResult = searchIndex.search(searchInput.value) const searchResult = searchIndex.search(searchInput.value)
const finalResult = [] const finalResult = []
searchResult.forEach((elem) => { searchResult.forEach((idx) => {
finalResult.push(packageList[elem]) finalResult.push(packageIndex[idx])
}) })
displayPackages.value = finalResult displayPackages.value = finalResult
} }
@ -49,14 +49,3 @@ watch(searchInput, async(newVal, oldVal) => {
<PackageList></PackageList> <PackageList></PackageList>
</div> </div>
</template> </template>
<style>
.search {
width: 100%;
margin: 15px 0;
font-size: 15px;
padding: .5em .5em;
}
</style>