This commit is contained in:
Loïc Guibert
2022-09-30 20:02:02 +01:00
commit 66dafc36c3
2561 changed files with 454489 additions and 0 deletions

View File

@@ -0,0 +1,27 @@
<template>
<div>
<flex-filter-bar :store="store" />
<flex-content-loader :store="store" v-show="loading" />
<flex-table :store="store" v-model="loading" v-show="!loading" />
</div>
</template>
<script>
import FlexTable from './components/Table.vue';
import FlexFilterBar from './components/FilterBar.vue';
import FlexContentLoader from './components/ContentLoader.vue';
export default {
props: ['initialStore'],
components: {FlexTable, FlexFilterBar, FlexContentLoader},
data: () => ({
perPage: 10,
loading: true
}),
computed: {
store() {
return JSON.parse(this.initialStore || '{}');
}
}
}
</script>

View File

@@ -0,0 +1,29 @@
export default {
table: {
tableClass: 'table',
loadingClass: 'loading',
sortableIcon: '',
ascendingIcon: 'fa fa-fw fa-chevron-up',
descendingIcon: 'fa fa-fw fa-chevron-down',
ascendingClass: '',
descendingClass: '',
handleIcon: 'fa fa-fw fa-bars',
renderIcon: (classes, options) => `<i class="${classes.join(' ')}"></i>`
},
pagination: {
wrapperClass: 'flex-objects-pagination',
activeClass: 'button active',
disabledClass: 'button disabled',
pageClass: 'button page',
linkClass: 'button link',
icons: {
first: 'fa fa-fw fa-angle-double-left',
prev: 'fa fa-fw fa-chevron-left',
next: 'fa fa-fw fa-chevron-right',
last: 'fa fa-fw fa-angle-double-right'
}
},
paginationInfo: {
infoClass: ''
}
};

View File

@@ -0,0 +1,48 @@
<template>
<div>
<div :style="{ height: 300, width: '100%' }"></div>
<content-loader
:height="fixedAmount * count"
:width="1060"
:speed="2"
primaryColor="#d9d9d9"
secondaryColor="#ecebeb"
>
<template v-for="index in count">
<rect x="13" :y="fixedAmount * index + offset" rx="6" ry="6" :width="200 * random()" height="12" />
<rect x="533" :y="fixedAmount * index + offset" rx="6" ry="6" :width="63 * random()" height="12" />
<rect x="653" :y="fixedAmount * index + offset" rx="6" ry="6" :width="78 * random()" height="12" />
<rect x="755" :y="fixedAmount * index + offset" rx="6" ry="6" :width="117 * random()" height="12" />
<rect x="938" :y="fixedAmount * index + offset" rx="6" ry="6" :width="83 * random()" height="12" />
<rect x="0" :y="fixedAmount * index" rx="6" ry="6" width="1060" height=".3" />
</template>
</content-loader>
</div>
</template>
<script>
import { ContentLoader } from 'vue-content-loader';
export default {
props: ['store'],
data: () => ({
fixedAmount: 31,
offset: 10,
steps: [0.7, 0.8, 0.9, 1]
}),
computed: {
count() {
return this.store.perPage;
}
},
methods: {
random() {
return this.steps[Math.floor(Math.random() * this.steps.length)];
}
},
components: {
ContentLoader
}
}
</script>

View File

@@ -0,0 +1,66 @@
<template>
<div class="search-wrapper">
<input type="text" class="search" :placeholder="store.searchPlaceholder" v-model.trim="filterText" @input="doFilter">
<select class="filter-perPage" v-model="store.perPage" @change="changePerPage">
<option v-for="(value, title) in this.perPageOptions"
:value="value"
:selected="store.perPage === value">{{ title }}</option>
</select>
</div>
</template>
<script>
import debounce from 'lodash/debounce';
export default {
props: ['store'],
data: () => ({
filterText: '',
searchPlaceholder: 'Filter...',
selected: ''
}),
computed: {
perPageOptions() {
const options = {
'25': 25,
'50': 50,
'100': 100,
'200': 200,
'All': ''
};
if (!options[this.store.perPage]) {
options[this.store.perPage] = this.store.perPage;
}
return options;
}
},
created() {
this.doFilter = debounce(() => {
this.$events.fire('filter-set', this.filterText);
}, 250, { leading: false });
this.changePerPage = () => {
this.$events.fire('filter-perPage', this.store.perPage);
};
},
methods: {
resetFilter() {
this.filterText = '';
this.$events.fire('filter-reset');
}
}
}
</script>
<style scoped>
.search-wrapper {
display: flex;
}
.search-wrapper select {
margin-bottom: 0;
margin-left: 1rem;
}
</style>

View File

@@ -0,0 +1,94 @@
<template>
<div>
<vuetable ref="vuetable"
:css="css.table"
:fields="store.fields || []"
:searchFields="store.searchFields || []"
:sortOrder="store.sortOrder"
:multi-sort="true"
:api-mode="true"
:api-url="store.api"
:per-page="perPage"
:append-params="extraParams"
pagination-path="links.pagination"
:show-sort-icons="true"
@vuetable:pagination-data="onPaginationData"
@vuetable:loading="onVuetableLoading"
@vuetable:load-success="onVueTableLoadSuccess"
/>
<div class="flex-list-pagination">
<vuetable-pagination-info ref="paginationInfo"
:info-template="store.paginationInfo"
:info-no-data-template="store.emptyResult"
:css="css.paginationInfo"
/>
<vuetable-pagination ref="pagination"
:css="css.pagination"
@vuetable-pagination:change-page="onChangePage"
/>
</div>
</div>
</template>
<script>
import Vue from 'vue';
import Vuetable from 'vuetable-2/src/components/Vuetable.vue';
import VuetablePagination from "vuetable-2/src/components/VuetablePagination.vue";
import VuetablePaginationInfo from 'vuetable-2/src/components/VuetablePaginationInfo.vue';
import VuetableCssConfig from "../VuetableCssConfig.js";
import set from 'lodash/set';
import unset from 'lodash/unset';
export default {
props: ['store', 'value'],
components: {Vuetable, VuetablePagination, VuetablePaginationInfo},
data: () => ({
css: VuetableCssConfig,
perPage: 10,
data: [],
extraParams: {}
}),
created() {
this.perPage = this.store.perPage;
this.data = Object.values(this.store.data);
},
mounted() {
this.$refs.vuetable.setData(this.store.data);
this.$events.$on('filter-set', event => this.onFilterSet(event));
this.$events.$on('filter-reset', event => this.onFilterReset());
this.$events.$on('filter-perPage', event => this.onFilterPerPage(event));
},
methods: {
onPaginationData(paginationData) {
this.$refs.pagination.setPaginationData(paginationData);
this.$refs.paginationInfo.setPaginationData(paginationData);
},
onFilterSet (filterText) {
set(this.extraParams, 'filter', filterText);
Vue.nextTick(() => this.$refs.vuetable.refresh());
},
onFilterReset () {
unset(this.extraParams, 'filter');
Vue.nextTick(() => this.$refs.vuetable.refresh());
},
onFilterPerPage (limit) {
// console.log('onFilterPerPage', limit, this.store.data);
this.perPage = limit || this.$refs.paginationInfo.tablePagination.total;
// this.$refs.vuetable.perPage = limit;
Vue.nextTick(() => this.$refs.vuetable.refresh());
},
onChangePage(page) {
this.$refs.vuetable.changePage(page);
},
onVuetableLoading() {
this.$emit('input', true);
},
onVueTableLoadSuccess() {
this.$emit('input', false);
}
}
}
</script>

View File

@@ -0,0 +1,19 @@
import Vue from 'vue';
import VueEvents from 'vue-events';
import App from './App.vue';
Vue.use(VueEvents);
const ID = '#flex-objects-list';
const element = document.querySelector(ID);
if (element) {
const initialStore = element.dataset.initialStore;
new Vue({ // eslint-disable-line no-new
el: ID,
render: h => h(App, {
props: {initialStore}
})
});
}