This repository has been archived on 2024-07-22. You can view files and clone it, but cannot push or open issues or pull requests.
Zaimki/components/Table.vue

129 lines
4.7 KiB
Vue
Raw Normal View History

<template>
<section class="table-responsive">
2020-10-29 15:41:40 -07:00
<table :class="['table table-striped table-hover', fixed ? 'table-fixed-' + columns : '']">
<thead ref="thead">
2021-01-21 09:56:08 -08:00
<tr>
<td :colspan="columns + 1">
<nav v-if="pages > 1">
<ul class="pagination pagination-sm justify-content-center mb-0">
<li v-for="p in pagesRange" :class="['page-item', p.page === page ? 'active' : '', p.enabled ? '' : 'disabled']">
<a v-if="p.enabled" class="page-link" href="#" @click.prevent="page = p.page">
{{p.text}}
</a>
<span v-else class="page-link">
{{p.text}}
</span>
</li>
</ul>
</nav>
</td>
</tr>
2020-11-03 12:00:32 -08:00
<tr v-if="count">
<td :colspan="columns">
<T>table.count</T>:
<strong>{{ data.length }}</strong>
</td>
</tr>
<tr>
<slot name="header"></slot>
</tr>
</thead>
<tbody>
<template v-if="data.length">
<tr v-for="el in dataPage" :key="el[rowKey]" :class="{'marked': marked ? marked(el) : false}">
<slot name="row" v-bind:el="el"></slot>
</tr>
</template>
<template v-else>
<tr>
<td :colspan="columns" class="text-center">
<slot name="empty">
<Icon v="search"/>
<T>table.empty</T>
</slot>
</td>
</tr>
</template>
</tbody>
2020-11-03 12:00:32 -08:00
<tfoot>
<tr>
2021-01-21 09:56:08 -08:00
<td :colspan="columns + 1">
2020-11-03 12:00:32 -08:00
<nav v-if="pages > 1">
<ul class="pagination pagination-sm justify-content-center">
<li v-for="p in pagesRange" :class="['page-item', p.page === page ? 'active' : '', p.enabled ? '' : 'disabled']">
<a v-if="p.enabled" class="page-link" href="#" @click.prevent="page = p.page">
{{p.text}}
</a>
<span v-else class="page-link">
{{p.text}}
</span>
</li>
</ul>
</nav>
</td>
</tr>
</tfoot>
</table>
</section>
</template>
<script>
export default {
props: {
data: { required: true },
columns: { required: true },
perPage: { 'default': 30 },
rowKey: { 'default': 'id' },
marked: {},
2020-10-29 15:41:40 -07:00
fixed: { type: Boolean },
2020-11-03 12:00:32 -08:00
count: { type: Boolean },
},
data() {
return {
page: 0,
};
},
computed: {
dataPage() {
return this.data.slice(this.page * this.perPage, (this.page + 1) * this.perPage);
},
pages() {
return Math.ceil(this.data.length / this.perPage);
},
pagesRange() {
const vPages = [];
vPages.push({page: 0, text: '«', enabled: this.page > 0});
vPages.push({page: this.page - 1, text: '', enabled: this.page > 0});
for (let i = 0; i < this.pages; i++) {
if (i <= 4 || (this.page - 3 <= i && i <= this.page + 3) || i >= this.pages - 3) {
vPages.push({page: i, text: i + 1, enabled: true});
} else if (vPages[vPages.length - 1].text !== '…') {
vPages.push({text: '…', enabled: false});
}
}
vPages.push({page: this.page + 1, text: '', enabled: this.page < this.pages - 1});
vPages.push({page: this.pages - 1, text: '»', enabled: this.page < this.pages - 1});
return vPages;
},
},
methods: {
reset() {
this.page = 0;
},
focus() {
setTimeout(_ => {
this.$refs.thead.scrollIntoView();
}, 300);
},
},
}
</script>
<style lang="scss">
@import "assets/variables";
.marked {
border-left: 3px solid $primary;
}
</style>