update ux
add pager
This commit is contained in:
parent
cadf25173f
commit
0de1c5dc2f
10 changed files with 130 additions and 46 deletions
|
|
@ -3,7 +3,7 @@
|
|||
<div class="d-flex justify-content-between p-3 mb-3">
|
||||
<h3>Comptes bancaires</h3>
|
||||
<BButtonToolbar key-nav>
|
||||
<BButton @click="doAdd">Ajouter</BButton>
|
||||
<BButton variant="primary" @click="doAdd">Ajouter</BButton>
|
||||
</BButtonToolbar>
|
||||
</div>
|
||||
<BTableSimple caption-top responsive v-if="data !== null">
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<div class="d-flex justify-content-between p-3 mb-3">
|
||||
<h3>Catégories</h3>
|
||||
<BButtonToolbar key-nav>
|
||||
<BButton @click="doAdd">Ajouter</BButton>
|
||||
<BButton variant="primary" @click="doAdd">Ajouter</BButton>
|
||||
</BButtonToolbar>
|
||||
</div>
|
||||
<BTableSimple caption-top responsive v-if="data !== null">
|
||||
|
|
|
|||
|
|
@ -1,31 +1,42 @@
|
|||
<template>
|
||||
<BContainer fluid class="p-0">
|
||||
<div class="d-flex justify-content-between p-3 mb-3">
|
||||
<h3>Transactions</h3>
|
||||
<div class="d-flex justify-content-between p-3">
|
||||
<h3 class="mb-0">Transactions</h3>
|
||||
<div v-if="data !== null" class="d-flex justify-content-between gap-2">
|
||||
<BPagination v-model="page" :per-page="limit" :total-rows="limit*pages" @page-click="updatePage" class="m-0" />
|
||||
<BFormSelect
|
||||
v-model="limit"
|
||||
:options="limits"
|
||||
@change="updateLimit"
|
||||
:required="true"
|
||||
/>
|
||||
</div>
|
||||
<BButtonToolbar key-nav>
|
||||
<BButton @click="doAdd">Importer</BButton>
|
||||
<BButton variant="primary" @click="doAdd">Importer</BButton>
|
||||
</BButtonToolbar>
|
||||
</div>
|
||||
<BTableSimple caption-top responsive v-if="data !== null">
|
||||
<BThead>
|
||||
<BTr>
|
||||
<BTh v-for="field in fields" :width="field.width" class="cursor" :class="field.classes" @click="doSort(field.key)">
|
||||
<SortButton :currentOrder="order" :currentSort="sort" :order="field.key" :label="field.label" />
|
||||
</BTh>
|
||||
</Btr>
|
||||
</BThead>
|
||||
<BTbody>
|
||||
<BTr v-for="row in data.rows">
|
||||
<BTd v-for="field in fields">
|
||||
<span v-if="field.key">
|
||||
<span v-if="field.render" v-html="field.render(row)"></span>
|
||||
<span v-else v-text="row[field.key]"></span>
|
||||
</span>
|
||||
<span v-else="field.render" v-html="field.render(row)"></span>
|
||||
</BTd>
|
||||
</Btr>
|
||||
</BTbody>
|
||||
</BTableSimple>
|
||||
<div class="crud-list">
|
||||
<BTableSimple caption-top v-if="data !== null">
|
||||
<BThead>
|
||||
<BTr>
|
||||
<BTh v-for="field in fields" :width="field.width" class="cursor" :class="field.thClasses" @click="doSort(field.key)">
|
||||
<SortButton :currentOrder="order" :currentSort="sort" :order="field.key" :label="field.label" />
|
||||
</BTh>
|
||||
</Btr>
|
||||
</BThead>
|
||||
<BTbody>
|
||||
<BTr v-for="row in data.rows">
|
||||
<BTd v-for="field in fields" :width="field.width" :class="field.tdClasses">
|
||||
<span v-if="field.key">
|
||||
<span v-if="field.render" v-html="field.render(row)"></span>
|
||||
<span v-else v-text="row[field.key]"></span>
|
||||
</span>
|
||||
<span v-else="field.render" v-html="field.render(row)"></span>
|
||||
</BTd>
|
||||
</Btr>
|
||||
</BTbody>
|
||||
</BTableSimple>
|
||||
</div>
|
||||
<BModal v-if="form !== null" v-model="formShow" :title="form?.label" @ok="doSave">
|
||||
<BAlert :model-value="form.error !== null" variant="danger" v-text="form.error"></BAlert>
|
||||
<BForm @submit="doSave">
|
||||
|
|
@ -90,6 +101,7 @@ import {
|
|||
BButtonToolbar,
|
||||
BFormSelect,
|
||||
BFormFile,
|
||||
BPagination,
|
||||
} from 'bootstrap-vue-next'
|
||||
|
||||
import SortButton from './../components/SortButton.vue'
|
||||
|
|
@ -100,11 +112,33 @@ const order = ref(null)
|
|||
const sort = ref(null)
|
||||
const page = ref(1)
|
||||
const pages = ref(null)
|
||||
const limit = ref(null)
|
||||
const limit = ref(10)
|
||||
const form = ref(null)
|
||||
const formShow = ref(false)
|
||||
const endpoint = `/api/transaction`
|
||||
|
||||
const defineLimits = () => {
|
||||
let v = []
|
||||
|
||||
for (let i of [10, 20, 50, 100]) {
|
||||
v.push({value: i, text: i})
|
||||
}
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
const limits = defineLimits()
|
||||
|
||||
const updatePage = (event, value) => {
|
||||
page.value = value
|
||||
refresh()
|
||||
}
|
||||
|
||||
const updateLimit = () => {
|
||||
page.value = 1
|
||||
refresh()
|
||||
}
|
||||
|
||||
const refresh = () => {
|
||||
fetch(`${endpoint}?${new URLSearchParams({
|
||||
order: order.value,
|
||||
|
|
@ -238,37 +272,53 @@ const fields = [
|
|||
{
|
||||
key: 'date',
|
||||
label: 'Date',
|
||||
width: '90px',
|
||||
render: (item) => renderDate(item.date),
|
||||
},
|
||||
{
|
||||
key: 'accounted_at',
|
||||
label: 'Comptabilisé',
|
||||
render: (item) => renderDate(item.accounted_at),
|
||||
},
|
||||
{
|
||||
key: 'short_label',
|
||||
label: 'Libelle simplifie',
|
||||
},
|
||||
{
|
||||
key: 'label',
|
||||
label: 'Libelle',
|
||||
},
|
||||
{
|
||||
key: 'information',
|
||||
label: 'Informations',
|
||||
width: '150px',
|
||||
label: 'Libellé',
|
||||
},
|
||||
{
|
||||
key: 'operation_type',
|
||||
width: '120px',
|
||||
label: 'Type',
|
||||
},
|
||||
{
|
||||
key: 'debit',
|
||||
label: 'Débit',
|
||||
width: '120px',
|
||||
thClasses: ['text-end'],
|
||||
tdClasses: ['text-end'],
|
||||
},
|
||||
{
|
||||
key: 'credit',
|
||||
label: 'Crédit',
|
||||
width: '120px',
|
||||
thClasses: ['text-end'],
|
||||
tdClasses: ['text-end'],
|
||||
},
|
||||
{
|
||||
key: 'category',
|
||||
label: 'Catégorie',
|
||||
width: '120px',
|
||||
render: (item) => {
|
||||
if (item.category !== null) {
|
||||
return item.category.label
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'bank_account',
|
||||
label: 'Compte',
|
||||
width: '120px',
|
||||
render: (item) => {
|
||||
if (item.bank_account !== null) {
|
||||
return item.bank_account.label
|
||||
}
|
||||
},
|
||||
}
|
||||
]
|
||||
|
||||
onMounted(() => {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<div class="d-flex justify-content-between p-3 mb-3">
|
||||
<h3>Utilisateurs</h3>
|
||||
<BButtonToolbar key-nav>
|
||||
<BButton @click="doAdd">Ajouter</BButton>
|
||||
<BButton variant="primary" @click="doAdd">Ajouter</BButton>
|
||||
</BButtonToolbar>
|
||||
</div>
|
||||
<BTableSimple caption-top responsive v-if="data !== null">
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#app, main {
|
||||
min-height: 100vh;
|
||||
max-height: 100vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
$nav-size: 300px;
|
||||
|
|
@ -25,6 +26,22 @@ $nav-size: 300px;
|
|||
width: $nav-size;
|
||||
}
|
||||
|
||||
.crud {
|
||||
&-list {
|
||||
width: calc(100vw - $nav-size);
|
||||
height: calc(100vh - 90px);
|
||||
overflow: auto;
|
||||
|
||||
thead th {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#body {
|
||||
width: calc(100vw - $nav-size);
|
||||
max-height: 100vh;
|
||||
overflow: scroll;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ func (ctrl *Controller) Config() crud.Configuration {
|
|||
Model: model.BankAccount{},
|
||||
Models: []model.BankAccount{},
|
||||
ValidOrders: []string{"id", "label"},
|
||||
ValidLimits: []int{20, 50, 100},
|
||||
DefaultLimit: 20,
|
||||
CreateModel: func() interface{} {
|
||||
return new(model.BankAccount)
|
||||
|
|
|
|||
|
|
@ -16,8 +16,7 @@ func (ctrl *Controller) Config() crud.Configuration {
|
|||
Model: model.Category{},
|
||||
Models: []model.Category{},
|
||||
ValidOrders: []string{"id", "label"},
|
||||
ValidLimits: []int{20, 50, 100},
|
||||
DefaultLimit: 20,
|
||||
DefaultLimit: 100,
|
||||
CreateModel: func() interface{} {
|
||||
return new(model.Category)
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package crud
|
||||
|
||||
import "gorm.io/gorm"
|
||||
|
||||
type Configuration struct {
|
||||
Model interface{}
|
||||
Models any
|
||||
|
|
@ -9,6 +11,7 @@ type Configuration struct {
|
|||
DefaultSort string
|
||||
DefaultLimit int
|
||||
CreateModel func() interface{}
|
||||
ListQuery func(*gorm.DB)
|
||||
}
|
||||
|
||||
func (c *Configuration) GetDefaultOrder() string {
|
||||
|
|
@ -27,6 +30,14 @@ func (c *Configuration) GetDefaultSort() string {
|
|||
return "asc"
|
||||
}
|
||||
|
||||
func (c *Configuration) GetValidLimits() []int {
|
||||
if len(c.ValidLimits) > 0 {
|
||||
return c.ValidLimits
|
||||
}
|
||||
|
||||
return []int{10, 20, 50, 100}
|
||||
}
|
||||
|
||||
func (c *Configuration) IsValidOrder(value string) bool {
|
||||
for _, v := range c.ValidOrders {
|
||||
if v == value {
|
||||
|
|
@ -38,7 +49,7 @@ func (c *Configuration) IsValidOrder(value string) bool {
|
|||
}
|
||||
|
||||
func (c *Configuration) IsValidLimit(value int) bool {
|
||||
for _, v := range c.ValidLimits {
|
||||
for _, v := range c.GetValidLimits() {
|
||||
if v == value {
|
||||
return true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,6 +50,10 @@ func (ctrl *Controller) List(c echo.Context) error {
|
|||
Desc: sort == "desc",
|
||||
})
|
||||
|
||||
if ctrl.Config.ListQuery != nil {
|
||||
ctrl.Config.ListQuery(db)
|
||||
}
|
||||
|
||||
data := ListData{
|
||||
Limit: ctrl.Config.DefaultLimit,
|
||||
Order: order,
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import (
|
|||
"gitnet.fr/deblan/budget/database/manager"
|
||||
"gitnet.fr/deblan/budget/database/model"
|
||||
"gitnet.fr/deblan/budget/web/controller/crud"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type Controller struct {
|
||||
|
|
@ -21,13 +22,16 @@ func (ctrl *Controller) Config() crud.Configuration {
|
|||
Model: model.Transaction{},
|
||||
Models: []model.Transaction{},
|
||||
ValidOrders: []string{"accounted_at", "short_label", "label", "reference", "information", "operation_type", "debit", "credit", "date"},
|
||||
ValidLimits: []int{20, 50, 100},
|
||||
DefaultLimit: 20,
|
||||
DefaultOrder: "date",
|
||||
DefaultSort: "desc",
|
||||
CreateModel: func() interface{} {
|
||||
return new(model.Transaction)
|
||||
},
|
||||
ListQuery: func(db *gorm.DB) {
|
||||
db.Joins("BankAccount")
|
||||
db.Joins("Category")
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue