4
0
mirror of https://github.com/AzuraCast/AzuraCast.git synced 2024-06-26 19:07:05 +00:00
AzuraCast/web/static/vue/components/DataTable.vue

271 lines
8.7 KiB
Vue
Raw Normal View History

2019-10-06 05:49:22 +00:00
<template>
2019-10-06 09:16:25 +00:00
<div>
2019-10-07 03:14:54 +00:00
<div class="d-flex align-items-center mb-2" v-if="showToolbar">
<div class="flex-fill">
<b-pagination v-model="currentPage" :total-rows="totalRows" :per-page="perPage"
2019-10-07 03:14:54 +00:00
class="mb-0" v-if="showPagination">
</b-pagination>
2019-10-07 03:14:54 +00:00
</div>
<div class="flex-shrink-1 pl-3">
<div class="input-group">
<span class="icon glyphicon input-group-addon search"></span>
<input type="text" v-model="filter" class="search-field form-control" placeholder="Search">
2019-10-06 05:49:22 +00:00
</div>
2019-10-07 03:14:54 +00:00
</div>
<div class="flex-shrink-1 pl-3 pr-3">
<b-btn-group class="actions">
<b-button variant="default" title="Refresh" @click="onClickRefresh" v-b-tooltip.hover
:title="langRefreshTooltip">
2019-10-06 09:16:25 +00:00
<i class="material-icons">refresh</i>
</b-button>
<b-dropdown variant="default" :text="perPageLabel" v-b-tooltip.hover :title="langPerPageTooltip">
<b-dropdown-item v-for="pageOption in pageOptions" :key="pageOption"
:active="(pageOption === perPage)" @click="setPerPage(pageOption)">
{{ getPerPageLabel(pageOption) }}
</b-dropdown-item>
</b-dropdown>
<b-dropdown variant="default" v-if="selectFields" v-b-tooltip.hover
:title="langSelectFieldsTooltip">
<template v-slot:button-content>
<i class="material-icons" aria-hidden="true">filter_list</i>
2019-10-06 09:16:25 +00:00
<span class="caret"></span>
</template>
<b-dropdown-form class="pt-3">
<div v-for="field in selectableFields" class="form-group">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input"
v-bind:id="'chk_field_' + field.key" name="is_field_visible"
v-model="field.visible" @change="storeSettings">
<label class="custom-control-label" v-bind:for="'chk_field_'+field.key">
{{ field.label }}
</label>
</div>
</div>
</b-dropdown-form>
</b-dropdown>
</b-btn-group>
2019-10-07 03:14:54 +00:00
</div>
</div>
2019-10-06 05:49:22 +00:00
<b-table ref="table" show-empty striped hover :selectable="selectable" :api-url="apiUrl" :per-page="perPage"
:current-page="currentPage" @row-selected="onRowSelected" :items="loadItems" :fields="visibleFields"
tbody-tr-class="align-middle" selected-variant=""
:filter="filter" :filter-debounce="200" @filtered="onFiltered">
2019-10-06 09:16:25 +00:00
<template v-slot:cell(selected)="{ rowSelected }">
<div class="custom-control custom-checkbox pl-0">
<input type="checkbox" class="custom-control-input position-static" :checked="rowSelected">
<label class="custom-control-label"></label>
</div>
2019-10-06 05:49:22 +00:00
</template>
2019-10-06 09:16:25 +00:00
<slot v-for="(_, name) in $slots" :name="name" :slot="name"/>
<template v-for="(_, name) in $scopedSlots" :slot="name" slot-scope="slotData">
<slot :name="name" v-bind="slotData"/>
2019-10-06 05:49:22 +00:00
</template>
2019-10-06 09:16:25 +00:00
</b-table>
2019-10-06 05:49:22 +00:00
<b-pagination v-model="currentPage" :total-rows="totalRows" :per-page="perPage"
2019-10-07 03:14:54 +00:00
class="mb-0 mt-2" v-if="showPagination">
</b-pagination>
2019-10-06 09:16:25 +00:00
</div>
2019-10-06 05:49:22 +00:00
</template>
<style lang="scss">
table.b-table-selectable {
tr > td:nth-child(1) {
padding-right: 0.75rem;
}
tr > td:nth-child(2) {
padding-left: 0.5rem;
}
}
</style>
2019-10-06 05:49:22 +00:00
<script>
import axios from 'axios'
import store from 'store'
import _ from 'lodash'
2019-10-06 05:49:22 +00:00
export default {
name: 'DataTable',
props: {
id: String,
apiUrl: String,
paginated: {
type: Boolean,
default: false
},
showToolbar: {
type: Boolean,
default: true
},
defaultPerPage: {
type: Number,
default: 10
},
2019-10-06 05:49:22 +00:00
fields: Array,
selectable: {
type: Boolean,
default: false
},
selectFields: {
type: Boolean,
default: false
},
2019-10-06 05:49:22 +00:00
requestConfig: Function,
requestProcess: Function
},
data () {
return {
selected: [],
storeKey: 'datatable_' + this.id + '_settings',
2019-10-06 05:49:22 +00:00
filter: null,
perPage: (this.paginated) ? this.defaultPerPage : 0,
2019-10-07 03:14:54 +00:00
pageOptions: [10, 25, 50, 0],
2019-10-06 05:49:22 +00:00
currentPage: 1,
totalRows: 0,
flushCache: false
}
},
mounted () {
this.loadStoredSettings()
2019-10-06 05:49:22 +00:00
},
computed: {
langRefreshTooltip () {
return this.$gettext('Refresh rows')
},
langPerPageTooltip () {
return this.$gettext('Rows per page')
},
langSelectFieldsTooltip () {
return this.$gettext('Select displayed fields')
},
visibleFields () {
if (!this.selectFields) {
return this.fields
}
return _.filter(this.fields, (field) => {
let isSelectable = _.defaultTo(field.selectable, false)
if (!isSelectable) {
return true
}
return _.defaultTo(field.visible, true)
})
},
selectableFields () {
return _.filter(this.fields, (field) => {
return _.defaultTo(field.selectable, false)
})
},
2019-10-07 03:14:54 +00:00
showPagination () {
return this.paginated && this.perPage !== 0
},
2019-10-06 05:49:22 +00:00
perPageLabel () {
return this.getPerPageLabel(this.perPage)
}
},
methods: {
loadStoredSettings () {
if (store.enabled && store.get(this.storeKey) !== undefined) {
let settings = store.get(this.storeKey)
this.perPage = _.defaultTo(settings.perPage, this.defaultPerPage)
_.forEach(this.selectableFields, (field) => {
field.visible = _.includes(settings.visibleFields, field.key)
})
}
},
storeSettings () {
if (!store.enabled) {
return
}
let settings = {
'perPage': this.perPage,
'visibleFields': _.map(this.visibleFields, 'key')
}
store.set(this.storeKey, settings)
},
2019-10-06 05:49:22 +00:00
getPerPageLabel (num) {
return (num === 0) ? 'All' : num.toString()
2019-10-06 05:49:22 +00:00
},
setPerPage (num) {
this.perPage = num
this.storeSettings()
2019-10-06 05:49:22 +00:00
},
onClickRefresh (e) {
if (e.shiftKey) {
this.list()
} else {
this.refresh()
}
},
2019-10-06 05:49:22 +00:00
refresh () {
this.$refs.table.refresh()
},
list () {
this.filter = null
this.currentPage = 1
this.flushCache = true
this.refresh()
},
setFilter (newTerm) {
2019-10-06 05:49:22 +00:00
this.filter = newTerm
},
loadItems (ctx, callback) {
let queryParams = {}
if (this.paginated) {
queryParams.rowCount = ctx.perPage
queryParams.current = ctx.currentPage
2019-10-06 05:49:22 +00:00
}
if (this.flushCache) {
queryParams.flushCache = true
}
if (typeof ctx.filter === 'string') {
queryParams.searchPhrase = ctx.filter
2019-10-06 05:49:22 +00:00
}
if ('' !== ctx.sortBy) {
2019-10-07 03:14:54 +00:00
queryParams.sort = ctx.sortBy
queryParams.sortOrder = (ctx.sortDesc) ? 'DESC' : 'ASC'
2019-10-06 05:49:22 +00:00
}
let requestConfig = { params: queryParams }
if (typeof this.requestConfig === 'function') {
requestConfig = this.requestConfig(requestConfig)
}
axios.get(ctx.apiUrl, requestConfig).then((resp) => {
this.flushCache = false
this.totalRows = resp.data.total
let rows = resp.data.rows
if (typeof this.requestProcess === 'function') {
rows = this.requestProcess(rows)
}
callback(rows)
}).catch((err) => {
this.flushCache = false
this.totalRows = 0
console.error(err.data.message)
callback([])
})
},
onRowSelected (items) {
this.selected = items
this.$emit('row-selected', items)
},
onFiltered (filter) {
this.$emit('filtered', filter)
2019-10-06 05:49:22 +00:00
}
}
}
</script>