Initial import: shopdb-flask multi-site asset platform
Flask + Vue rewrite of the classic-ASP shopdb, built as a plugin framework so sister GE Aerospace sites can adopt it. Product version 0.7.0-pre-0.8.0, plugin contract 0.11.0, 966 backend tests. Key entry points: - docs/INSTALL-WINDOWS-IIS.md - tested Windows + IIS install runbook (own-site and subpath deployment methods) - docs/PILOT-DEPLOY.md - production pilot: stand up + import + verify - docs/IMPORT-API.md - schema-agnostic legacy data import contract - scripts/site_imports/wjf/ - West Jefferson reference import loader - docs/adr/ - twelve accepted architecture decision records
This commit is contained in:
83
frontend/src/components/PaginationBar.vue
Normal file
83
frontend/src/components/PaginationBar.vue
Normal file
@@ -0,0 +1,83 @@
|
||||
<template>
|
||||
<div class="pagination-bar" v-if="totalPages > 1 || showPerPage">
|
||||
<div class="pagination-info">
|
||||
<select
|
||||
v-if="showPerPage"
|
||||
:value="perPage"
|
||||
class="perpage-select"
|
||||
@change="$emit('update:perPage', Number($event.target.value))"
|
||||
>
|
||||
<option v-for="opt in perPageOptions" :key="opt" :value="opt">
|
||||
{{ opt }} per page
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="pagination" v-if="totalPages > 1">
|
||||
<button :disabled="page === 1" @click="$emit('update:page', page - 1)">
|
||||
Prev
|
||||
</button>
|
||||
|
||||
<button
|
||||
v-for="p in visiblePages"
|
||||
:key="p"
|
||||
:class="{ active: p === page, ellipsis: p === '...' }"
|
||||
:disabled="p === '...'"
|
||||
@click="p !== '...' && $emit('update:page', p)"
|
||||
>
|
||||
{{ p }}
|
||||
</button>
|
||||
|
||||
<button :disabled="page === totalPages" @click="$emit('update:page', page + 1)">
|
||||
Next
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
page: { type: Number, required: true },
|
||||
totalPages: { type: Number, required: true },
|
||||
perPage: { type: Number, default: 20 },
|
||||
showPerPage: { type: Boolean, default: true }
|
||||
})
|
||||
|
||||
defineEmits(['update:page', 'update:perPage'])
|
||||
|
||||
const perPageOptions = [10, 20, 50, 100]
|
||||
|
||||
const visiblePages = computed(() => {
|
||||
const total = props.totalPages
|
||||
const current = props.page
|
||||
const pages = []
|
||||
|
||||
if (total <= 7) {
|
||||
for (let i = 1; i <= total; i++) pages.push(i)
|
||||
return pages
|
||||
}
|
||||
|
||||
pages.push(1)
|
||||
|
||||
if (current > 3) {
|
||||
pages.push('...')
|
||||
}
|
||||
|
||||
const start = Math.max(2, current - 1)
|
||||
const end = Math.min(total - 1, current + 1)
|
||||
|
||||
for (let i = start; i <= end; i++) {
|
||||
pages.push(i)
|
||||
}
|
||||
|
||||
if (current < total - 2) {
|
||||
pages.push('...')
|
||||
}
|
||||
|
||||
pages.push(total)
|
||||
|
||||
return pages
|
||||
})
|
||||
</script>
|
||||
Reference in New Issue
Block a user