Created
July 26, 2018 12:50
-
-
Save warlord0/82209b928dbe7f2057d04eb6518d6084 to your computer and use it in GitHub Desktop.
vuetables-2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<div id="users"> | |
<div class="row"> | |
<vuetable-filter-bar | |
class="col-sm-6" | |
/> | |
<!-- Api call should return standard Laravel paginate() json --> | |
<vuetable-pagination | |
ref="pagination" | |
class="col-sm-6" | |
@vuetable-pagination:change-page="onChangePage" | |
/> | |
</div> | |
<!-- Generate the table based on the default api call --> | |
<vuetable | |
ref="vuetable" | |
:fields="fields" | |
:css="css" | |
:sort-order="sortOrder" | |
:append-params="moreParams" | |
:http-fetch="getUsers" | |
class="table-striped table-hover" | |
api-url="/admin/users" | |
pagination-path="" | |
@vuetable:pagination-data="onPaginationData" | |
> | |
<template | |
slot="roles" | |
slot-scope="props" | |
> | |
<!-- Iterate the roles and build the buttons --> | |
<button | |
v-for="role in props.rowData.roles" | |
:key="role.name" | |
class="btn btn-sm btn-primary mr-1 mb-1" | |
> | |
{{ role.name }}<!-- <i class="fas fa-times"/>--> | |
</button> | |
<!-- add role button fires the modal --> | |
<button | |
class="btn btn-sm btn-default text-dark mr-1 mb-1" | |
@click="addRoles(props.rowData)" | |
> | |
<i class="fas fa-pencil-alt"/> | |
</button> | |
</template> | |
</vuetable> | |
<div class="row"> | |
<!-- Api call should return standard Laravel paginate() json --> | |
<vuetable-pagination-dropdown | |
ref="paginationDropdown" | |
class="offset-sm-6 col-sm-6" | |
@vuetable-pagination:change-page="onChangePage" | |
/> | |
</div> | |
<!-- Modal for the updating the current users roles --> | |
<div | |
id="rolesModal" | |
class="modal fade" | |
tabindex="-1" | |
role="dialog" | |
> | |
<div | |
class="modal-dialog modal-dialog-centered" | |
role="document" | |
> | |
<div class="modal-content"> | |
<form | |
name="rolesForm" | |
action="" | |
method="put" | |
@submit.prevent="saveRoles" | |
> | |
<input | |
type="hidden" | |
name="_method" | |
value="put" | |
> | |
<input | |
:value="user.username" | |
name="user" | |
type="hidden" | |
> | |
<div class="modal-header"> | |
<h5 class="modal-title">Roles for User "{{ user.name }}"</h5> | |
<button | |
type="button" | |
class="close" | |
data-dismiss="modal" | |
aria-label="Close"> | |
<span aria-hidden="true">×</span> | |
</button> | |
</div> | |
<div class="modal-body"> | |
<div class="row"> | |
<div | |
v-for="role in roles" | |
:key="role.name" | |
class="col-sm-4" | |
> | |
<!-- | |
Checkboxes are bound to a non-indexed array where the id | |
is the value of the array item | |
--> | |
<div class="form-group"> | |
<label :for="role.name"> | |
<input | |
:id="role.name" | |
:value="role.name" | |
v-model="newRoles" | |
type="checkbox" | |
> | |
{{ role.name }} | |
</label> | |
</div> | |
</div> | |
</div> | |
</div> | |
<div class="modal-footer"> | |
<button | |
type="button" | |
class="btn btn-default" | |
data-dismiss="modal" | |
> | |
Close <i class="fas fa-times"/> | |
</button> | |
<button | |
type="button" | |
class="btn btn-danger" | |
@click="newRoles = []" | |
> | |
None <i class="fas fa-trash-alt"/> | |
</button> | |
<button | |
type="submit" | |
class="btn btn-primary" | |
> | |
Save <i class="fas fa-save"/> | |
</button> | |
</div> | |
</form> | |
</div> | |
</div> | |
</div> | |
</div> | |
</template> | |
<script> | |
import Vuetable from 'vuetable-2' | |
// Bootstrap 4 style pagination | |
import VuetablePagination from '../Vuetable/VuetablePaginationBootstrap' | |
import VuetablePaginationDropdown from '../Vuetable//VuetablePaginationDropdownBootstrap' | |
import VuetableCss from '../Vuetable/VuetableCss' | |
import fieldsDef from './usersFieldsDef' | |
import VuetableFilterBar from '../Vuetable/VuetableFilterBarBootstrap' | |
export default { | |
components: { | |
Vuetable, // The vuetable | |
VuetablePagination, // nav/button based pagination | |
VuetablePaginationDropdown, // select based pagination | |
VuetableFilterBar // Search | |
}, | |
data () { | |
return { | |
css: VuetableCss, // Reusable Css | |
fields: fieldsDef, // Field Definitions / rendering | |
sortOrder: [{ | |
field: 'name', | |
direction: 'asc' | |
}], | |
data: [], // Table data | |
user: {}, // Current user | |
roles: {}, // All of the available roles | |
newRoles: [], // List of roles to be synced when submitted | |
moreParams: {} // Sends the filter with the other params | |
} | |
}, | |
mounted () { | |
// Listen for the filter events from VuetableFilterBar | |
this.$events.$on('filter-set', eventData => this.onFilterSet(eventData)) | |
this.$events.$on('filter-reset', e => this.onFilterReset()) // eslint-disable-line no-unused-vars | |
this.getRoles() // Get all the available roles | |
}, | |
methods: { | |
/* Search Filter Handling */ | |
onFilterSet (filterText) { | |
// console.log('filter-set', filterText) | |
this.moreParams = { | |
filter: filterText | |
} | |
// console.log(this.$refs.vuetable) | |
Vue.nextTick( () => this.$refs.vuetable.refresh() ) // eslint-disable-line no-undef | |
}, | |
onFilterReset () { | |
// console.log('filter-reset') | |
this.moreParams = {} | |
Vue.nextTick( () => this.$refs.vuetable.refresh() ) // eslint-disable-line | |
}, | |
// Show the modal with the roles of the current user | |
addRoles(user) { | |
this.user = user | |
// Create the non-indexed array "newRoles" | |
this.newRoles = this.user.roles.map((role) => { | |
return role.name | |
}) | |
$('#rolesModal').modal('show') // eslint-disable-line no-undef | |
}, | |
// Fetch all of the avilable roles that can be used | |
getRoles: function() { | |
this.axios.get('/admin/roles') // eslint-disable-line no-undef | |
.then(({ data }) => { | |
this.roles = data.data | |
}) | |
}, | |
// replaces the vuetales own call to api-url to handle jwt auth | |
getUsers(apiUrl, httpOptions) { | |
return this.$http.get(apiUrl, httpOptions) | |
}, | |
// Save the response from the modal form using Laravel resource controller | |
saveRoles: function() { | |
axios.put('/admin/users/'+this.user.id, { // eslint-disable-line no-undef | |
params: { | |
query: { | |
user: this.user, | |
roles: this.newRoles | |
} | |
} | |
}).then(() => { | |
// Reload the table and hide the modal | |
this.$refs.vuetable.reload() // Reload keeps the current page number | |
$('#rolesModal').modal('hide') // eslint-disable-line no-undef | |
}) // Do we need a catch? | |
}, | |
// Trigger the pagination changes | |
onPaginationData (paginationData) { | |
this.$refs.pagination.setPaginationData(paginationData) | |
this.$refs.paginationDropdown.setPaginationData(paginationData) | |
}, | |
onChangePage (page) { | |
this.$refs.vuetable.changePage(page) | |
} | |
} | |
} | |
</script> | |
<style> | |
/* .vuetable-th-checkbox-id { | |
width: 2%; | |
} | |
.vuetable-th-id { | |
width: 8%; | |
} */ | |
.vuetable-th-username { | |
width: 20%; | |
} | |
.vuetable-th-name { | |
width: 20%; | |
} | |
.vuetable-th-email { | |
width: 15%; | |
} | |
.vuetable-th-slot-roles { | |
width: 65%; | |
} | |
.vuetable-pagination nav { | |
float: right; | |
} | |
.vuetable-pagination-dropdown nav { | |
float: right; | |
} | |
</style> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Deals with the sort icons using fontawesome | |
export default { | |
tableClass: 'table', | |
loadingClass: 'loading', | |
ascendingIcon: 'fas fa-arrow-down', | |
descendingIcon: 'fas fa-arrow-up', | |
detailRowClass: 'vuetable-detail-row', | |
handleIcon: 'fas fa-bars', | |
sortableIcon: '', //fas fa-sort-amount-up', // since v1.7 | |
ascendingClass: 'sorted-asc', // since v1.7 | |
descendingClass: 'sorted-desc' // since v1.7 | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<div class="vuetable-filter-bar"> | |
<div class="form-inline"> | |
<div class="form-group"> | |
<label class="sr-only">Search for: </label> | |
<div class="input-group"> | |
<div class="input-group-prepend"> | |
<span class="input-group-btn"> | |
<button | |
class="btn btn-primary" | |
type="button" | |
@click="doFilter" | |
> | |
<i class="fas fa-search"/> | |
</button> | |
</span> | |
</div> | |
<input | |
v-model="filterText" | |
class="form-control" | |
placeholder="Search string" | |
type="text" | |
@keyup.enter="doFilter" | |
> | |
<div class="input-group-append"> | |
<span class="input-group-btn"> | |
<button | |
class="btn btn-default" | |
type="button" | |
@click="resetFilter" | |
> | |
<i class="fas fa-times"/> | |
</button> | |
</span> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</template> | |
<script> | |
export default { | |
data () { | |
return { | |
filterText: '' | |
} | |
}, | |
methods: { | |
doFilter () { | |
this.$events.fire('filter-set', this.filterText) | |
}, | |
resetFilter () { | |
this.filterText = '' | |
this.$events.fire('filter-reset') | |
} | |
} | |
} | |
</script> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<div class="vuetable-pagination"> | |
<nav aria-label="Table Navigation"> | |
<ul class="pagination"> | |
<li | |
:class="{'disabled': isOnFirstPage}" | |
class="page-item"> | |
<a | |
class="page-link" | |
href="#" | |
@click.prevent="loadPage(1)"> | |
<span><i class="fas fa-angle-double-left"/></span> | |
</a> | |
</li> | |
<li | |
:class="{'disabled': isOnFirstPage}" | |
class="page-item"> | |
<a | |
class="page-link" | |
href="#" | |
@click.prevent="loadPage('prev')"> | |
<span><i class="fas fa-angle-left"/></span> | |
</a> | |
</li> | |
<template v-if="notEnoughPages"> | |
<li | |
v-for="n in totalPage" | |
:key="n" | |
:class="{'active': isCurrentPage(n)}" | |
class="page-item" | |
> | |
<a | |
class="page-link" | |
@click.prevent="loadPage(n)" | |
v-html="n"/> | |
</li> | |
</template> | |
<template v-else> | |
<li | |
v-for="n in windowSize" | |
:key="n" | |
:class="{'active': isCurrentPage(windowStart+n-1)}" | |
class="page-item" | |
> | |
<a | |
class="page-link" | |
@click.prevent="loadPage(windowStart+n-1)" | |
v-html="windowStart+n-1"/> | |
</li> | |
</template> | |
<li | |
:class="{'disabled': isOnLastPage}" | |
class="page-item" | |
> | |
<a | |
class="page-link" | |
href="" | |
@click.prevent="loadPage('next')"> | |
<span><i class="fas fa-angle-right"/></span> | |
</a> | |
</li> | |
<li | |
:class="{'disabled': isOnLastPage}" | |
class="page-item" | |
> | |
<a | |
class="page-link" | |
href="" | |
@click.prevent="loadPage(totalPage)"> | |
<span><i class="fas fa-angle-double-right"/></span> | |
</a> | |
</li> | |
</ul> | |
</nav> | |
</div> | |
</template> | |
<script> | |
import { VuetablePaginationMixin } from 'vuetable-2' | |
export default { | |
mixins: [VuetablePaginationMixin] | |
} | |
</script> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<div class="vuetable-pagination-dropdown"> | |
<nav aria-label="Table Navigation"> | |
<ul class="pagination"> | |
<li | |
:class="{'disabled': isOnFirstPage}" | |
class="page-item"> | |
<a | |
class="page-link" | |
href="#" | |
@click.prevent="loadPage(1)"> | |
<span><i class="fas fa-angle-double-left"/></span> | |
</a> | |
</li> | |
<li | |
:class="{'disabled': isOnFirstPage}" | |
class="page-item"> | |
<a | |
class="page-link" | |
href="#" | |
@click.prevent="loadPage('prev')"> | |
<span><i class="fas fa-angle-left"/></span> | |
</a> | |
</li> | |
<div class="form-group mr-1 ml-1"> | |
<select | |
id="paginationDropdown" | |
class="form-control" | |
@change="loadPage($event.target.selectedIndex+1)" | |
> | |
<template | |
v-for="k in totalPage" | |
> | |
<option | |
:key="k" | |
:value="k" | |
:selected="isCurrentPage(k)" | |
> | |
Page {{ k }} | |
</option> | |
</template> | |
</select> | |
</div> | |
<li | |
:class="{'disabled': isOnLastPage}" | |
class="page-item" | |
> | |
<a | |
class="page-link" | |
href="" | |
@click.prevent="loadPage('next')"> | |
<span><i class="fas fa-angle-right"/></span> | |
</a> | |
</li> | |
<li | |
:class="{'disabled': isOnLastPage}" | |
class="page-item" | |
> | |
<a | |
class="page-link" | |
href="" | |
@click.prevent="loadPage(totalPage)"> | |
<span><i class="fas fa-angle-double-right"/></span> | |
</a> | |
</li> | |
</ul> | |
</nav> | |
</div> | |
</template> | |
<script> | |
import { VuetablePaginationMixin } from 'vuetable-2' | |
export default { | |
mixins: [VuetablePaginationMixin] | |
} | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment