Compare commits
19 Commits
Author | SHA1 | Date | |
---|---|---|---|
494f302cc5 | |||
0493816dbe | |||
1825c5ffba | |||
a6a37539bd | |||
68653aaabe | |||
af2330d2fa | |||
d486268921 | |||
1482c7f862 | |||
62ec65ce53 | |||
f5bbf195f3 | |||
342b2efd1c | |||
48df3ecf7b | |||
62b193b04a | |||
bc7f771d25 | |||
ecf7db6a8f | |||
6f069832c0 | |||
4d6a61fa58 | |||
66082aaa45 | |||
22fc1a9b48 |
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,33 @@
|
||||
---
|
||||
categories:
|
||||
tout:
|
||||
name: Tout
|
||||
variant: info
|
||||
icon: file-invoice-dollar
|
||||
color: '#78e08f'
|
||||
words: []
|
||||
cash:
|
||||
name: Cash
|
||||
variant: info
|
||||
icon: money-bill-wave
|
||||
color: '#78e08f'
|
||||
words:
|
||||
- RETRAIT
|
||||
cb:
|
||||
name: CB
|
||||
variant: info
|
||||
icon: credit-card
|
||||
color: '#4a69bd'
|
||||
words:
|
||||
- PAIEMENT
|
||||
virements:
|
||||
name: Virements
|
||||
variant: info
|
||||
icon: directions
|
||||
invert: true
|
||||
color: '#f6b93b'
|
||||
words:
|
||||
- PAIEMENT
|
||||
- RETRAIT
|
||||
tags:
|
||||
cash:
|
||||
name: Cash
|
||||
@ -7,39 +36,22 @@ tags:
|
||||
color: '#78e08f'
|
||||
words:
|
||||
- RETRAIT
|
||||
|
||||
CB:
|
||||
name: CB
|
||||
variant: info
|
||||
icon: credit-card
|
||||
color: "#4a69bd"
|
||||
words:
|
||||
- PAIEMENT
|
||||
|
||||
- PAIEMENT CB 2404 ALIXAN CASH BIO CARTE 74142381
|
||||
- PAIEMENT CB 2404 SAINT MARCEL PRIMEUR DU CHANT CARTE 74142381
|
||||
virements:
|
||||
name: Virements
|
||||
variant: info
|
||||
icon: directions
|
||||
invert: true
|
||||
color: "#f6b93b"
|
||||
color: '#b0afaf'
|
||||
words:
|
||||
- PAIEMENT
|
||||
- RETRAIT
|
||||
|
||||
autoroute:
|
||||
name: Autoroute
|
||||
variant: danger
|
||||
icon: road
|
||||
color: "#eb2f06"
|
||||
words:
|
||||
- AUTOROUTE
|
||||
- APRR
|
||||
|
||||
essence:
|
||||
essence:
|
||||
name: Essence
|
||||
variant: danger
|
||||
icon: charging-station
|
||||
color: "#0c2461"
|
||||
color: '#0c2461'
|
||||
words:
|
||||
- CARBU
|
||||
- TOTAL
|
||||
@ -49,20 +61,26 @@ tags:
|
||||
- ESSO
|
||||
- BELLEGARDE SU CARREFOUR
|
||||
- ST CLAUDE CASINOCARB
|
||||
|
||||
- RUNGIS MAGASIN U
|
||||
- LES ROUSSES DAC ANGEDI
|
||||
- LES ROUSSES MARKET DAC
|
||||
- COMMUNAY RELAIS COMMUNAY
|
||||
- DORLISHEIM CORA
|
||||
- ALIXAN 838782 ELF
|
||||
- TENCE CLEAT DIS DAC
|
||||
- VALSERHONE CARREFOUR
|
||||
train:
|
||||
name: train
|
||||
name: Train
|
||||
variant: danger
|
||||
icon: train
|
||||
color: "#eb2f06"
|
||||
color: '#eb2f06'
|
||||
words:
|
||||
- SNCF
|
||||
|
||||
courses:
|
||||
courses:
|
||||
name: Courses
|
||||
variant: warning
|
||||
icon: shopping-cart
|
||||
color: "#665191"
|
||||
color: '#665191'
|
||||
words:
|
||||
- BIOCOOP
|
||||
- LA VIE CLAIRE
|
||||
@ -75,3 +93,104 @@ tags:
|
||||
- INTERMARCHE
|
||||
- LA FERME DU COIN
|
||||
- ARBENT GEANT
|
||||
- CHATILLON EN BIO VALSERINE
|
||||
- ST LAURENT EN BIO COOP GRANDVA
|
||||
- ST CLAUDE MAISON VIAL
|
||||
- OYONNAX OYONNAXIENNE
|
||||
- BOURG DE PEAG GEANT CG839
|
||||
- CHATILLON EN LE TRAM PAYSAN
|
||||
- BELLEGARDE SU PTIT CHEZ VILLE
|
||||
- VALSERHONE LE PETIT CHEZERY
|
||||
- VALSERHONE L'AIR DU LARGE
|
||||
- ST GERMAIN DE EPICERIE FAURAX
|
||||
vacances:
|
||||
color: '#ff8a00'
|
||||
icon: map-marked
|
||||
name: Vacances
|
||||
variant: ''
|
||||
words:
|
||||
- VACANCES
|
||||
- PRALOGNAN LA PETIT CASINO
|
||||
- PRALOGNAN LA AUGUSTE
|
||||
- PRALOGNAN LA CASINO SHOP
|
||||
resto-bar:
|
||||
color: '#6ea5fc'
|
||||
icon: utensils
|
||||
name: Resto-bar
|
||||
variant: ''
|
||||
words:
|
||||
- ALVEOLES
|
||||
- LYON FRITE ALORS !
|
||||
- OYONNAX CAFES PAT
|
||||
- BELLECOMBE LA GUIENETTE
|
||||
- MOUTIERS TARE LA PETITE FABRIQ
|
||||
- BELLEGARDE SU L'AIR DU LARGE
|
||||
- LYON ENGIMONO
|
||||
- OBERNAI LE CHEVAL BLANC
|
||||
- LA PESSE REFUGE BERBOIS
|
||||
- LA PESSE AUB LES ERABLES
|
||||
- LA PESSE LES TAVAILLONS
|
||||
- LEUTENHEIM BOEUF ROUGE
|
||||
voiture:
|
||||
color: '#0077c8'
|
||||
icon: car
|
||||
name: Voiture
|
||||
variant: ''
|
||||
words:
|
||||
- ARBENT A84 OYONNAX
|
||||
- ST CLAUDE ALAIN PNEU
|
||||
- VALEN2931212/ VALENHOTEVILAUTO
|
||||
- AUTOROUTE
|
||||
- APRR
|
||||
- MORBIER PE
|
||||
- DORLISHEIM EU VERT 067
|
||||
- 'ANNECY SUD A R E A '
|
||||
- '69 BRON CEDEX A R E A '
|
||||
culture:
|
||||
color: '#199c00'
|
||||
icon: book
|
||||
name: Culture
|
||||
variant: ''
|
||||
words:
|
||||
- LYON MOMIE MANGAS
|
||||
- ROMANS SUR IS LIBRAIRIE LA MAU
|
||||
- PREMANON ESP MONDES POL
|
||||
- VALSERHONE LIBR PAP BIGUET
|
||||
- BELLEGARDE SU LES ARTS FRONTIE
|
||||
enfant:
|
||||
color: '#fc00d5'
|
||||
icon: child
|
||||
name: Enfant
|
||||
variant: ''
|
||||
words:
|
||||
- Baby
|
||||
- ST MARCEL LES GEKA TISSUS
|
||||
- ST SAUVEUR DE ARDELAINE
|
||||
- LEZIGNAN CORB LES BABILLEUSES
|
||||
- NORTHAMPTON BAMBINO MIO LTD
|
||||
- PARIS PAYPLUG COM
|
||||
- PARIS HAMAC PARIS
|
||||
- ERGUE GABERIC JEUJOUETHIQUE
|
||||
- CHATILLON EN CHAUSS'EXPO
|
||||
- LONDON GLOBALE /FRUGI
|
||||
- NANTUA OPTIQUE PHOTO
|
||||
- LA PESSE SYLVAIN BOULARD
|
||||
- BOULOGNE-BILL AIGLE INTERNATIO
|
||||
- TROYES PETIT BATEAU
|
||||
- ST PIERREVILL ARDELAINE
|
||||
maison:
|
||||
color: '#f5ad61'
|
||||
icon: home
|
||||
name: Maison
|
||||
variant: ''
|
||||
words:
|
||||
- BRICOLAGE
|
||||
- CHATILLON EN BRICOMARCHE
|
||||
- VALSERHONE GAMM VERT
|
||||
- ROMANS SUR IS HOME COOK ROMANS
|
||||
- CHATILLON EN KILOUTOU
|
||||
- FR 34MONTPELL PG RIPATON
|
||||
- OSTHOFEN PROFOLIO GMBH
|
||||
- CHATILLON EN MR SAUSSAC J P
|
||||
- CHABEUIL WWW MATERIAUX-NA
|
||||
- 75017 PARIS MANOMANO
|
||||
|
@ -1,46 +0,0 @@
|
||||
backcall==0.1.0
|
||||
bleach==3.0.2
|
||||
cycler==0.10.0
|
||||
decorator==4.3.0
|
||||
defusedxml==0.5.0
|
||||
entrypoints==0.2.3
|
||||
ipykernel==5.1.0
|
||||
ipython==7.1.1
|
||||
ipython-genutils==0.2.0
|
||||
jedi==0.13.1
|
||||
Jinja2==2.10
|
||||
jsonschema==2.6.0
|
||||
jupyter-client==5.2.3
|
||||
jupyter-core==4.4.0
|
||||
jupyterlab==0.35.4
|
||||
jupyterlab-server==0.2.0
|
||||
kiwisolver==1.0.1
|
||||
MarkupSafe==1.1.0
|
||||
matplotlib==3.0.2
|
||||
mistune==0.8.4
|
||||
nbconvert==5.4.0
|
||||
nbformat==4.4.0
|
||||
notebook==5.7.2
|
||||
numpy==1.15.4
|
||||
pandas==0.23.4
|
||||
pandocfilters==1.4.2
|
||||
parso==0.3.1
|
||||
pexpect==4.6.0
|
||||
pickleshare==0.7.5
|
||||
prometheus-client==0.4.2
|
||||
prompt-toolkit==2.0.7
|
||||
ptyprocess==0.6.0
|
||||
Pygments==2.3.0
|
||||
pyparsing==2.3.0
|
||||
python-dateutil==2.7.5
|
||||
pytz==2018.7
|
||||
PyYAML==3.13
|
||||
pyzmq==17.1.2
|
||||
Send2Trash==1.5.0
|
||||
six==1.11.0
|
||||
terminado==0.8.1
|
||||
testpath==0.4.2
|
||||
tornado==5.1.1
|
||||
traitlets==4.3.2
|
||||
wcwidth==0.1.7
|
||||
webencodings==0.5.1
|
77
src/components/associate_tag_keyword.vue
Normal file
77
src/components/associate_tag_keyword.vue
Normal file
@ -0,0 +1,77 @@
|
||||
<template>
|
||||
<b-form @submit="saveExit">
|
||||
<b-form-group label="Mot clé"
|
||||
label-for="keyword"
|
||||
>
|
||||
<b-form-input v-model="keyword"
|
||||
id="keyword"
|
||||
type="text"
|
||||
required
|
||||
>
|
||||
</b-form-input>
|
||||
</b-form-group>
|
||||
<b-form-group label="Tag associé"
|
||||
label-for="tag"
|
||||
>
|
||||
<b-form-select v-model="tagName"
|
||||
id="tag"
|
||||
:options="tagsName"
|
||||
required
|
||||
>
|
||||
</b-form-select>
|
||||
</b-form-group>
|
||||
<b-btn type="submit" class="mt-3" variant="outline-success" block >Valider</b-btn>
|
||||
<b-btn class="mt-3" variant="outline-danger" block @click="discardExit">Annuler</b-btn>
|
||||
</b-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters, mapActions } from 'vuex'
|
||||
export default {
|
||||
name: 'associateTagKeyword',
|
||||
props: [
|
||||
'libelle'
|
||||
],
|
||||
data () {
|
||||
return {
|
||||
tagName: '',
|
||||
keyword: this.cleanLibelle(this.libelle)
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
'tags': 'config/tags'
|
||||
}),
|
||||
tagsName () {
|
||||
return Object.keys(this.tags)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions({
|
||||
'append_keywords': 'config/append_keywords'
|
||||
}),
|
||||
cleanLibelle (libelle) {
|
||||
var head = /PAIEMENT CB \d* /g
|
||||
var tail = / CARTE \d*/g
|
||||
return libelle.replace(head, '').replace(tail, '')
|
||||
},
|
||||
hideModal () {
|
||||
this.$root.$emit('bv::hide::modal', this.libelle)
|
||||
},
|
||||
saveExit () {
|
||||
this.append_keywords({
|
||||
tagName: this.tagName,
|
||||
keyword: this.keyword
|
||||
})
|
||||
this.hideModal()
|
||||
},
|
||||
discardExit () {
|
||||
this.hideModal()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
72
src/components/card_categorie.vue
Normal file
72
src/components/card_categorie.vue
Normal file
@ -0,0 +1,72 @@
|
||||
<template>
|
||||
<b-card v-if="categorie"
|
||||
:bg-variant="categorie.variant"
|
||||
text-variant="white"
|
||||
class="text-center">
|
||||
<div class="card-text">
|
||||
<div class="icon">
|
||||
<font-awesome-icon :icon="categorie.icon" class="fa-3x"/>
|
||||
</div>
|
||||
<div class="amount">
|
||||
<h3>{{ total() }}€</h3>
|
||||
{{ categorie.name }}
|
||||
</div>
|
||||
</div>
|
||||
</b-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import { total } from '../libs/data_processing'
|
||||
export default {
|
||||
name: 'cardCategorie',
|
||||
props: [
|
||||
'categoriename',
|
||||
'rows'
|
||||
],
|
||||
data () {
|
||||
return {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('config', [
|
||||
'categories'
|
||||
]),
|
||||
...mapGetters('datas', [
|
||||
'categorie_filter_rows'
|
||||
]),
|
||||
categorie () {
|
||||
return this.categories[this.categoriename.toLowerCase()]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
filter_rows () {
|
||||
return this.categorie_filter_rows([this.categorie.name])
|
||||
},
|
||||
total () {
|
||||
return total(this.filter_rows())
|
||||
},
|
||||
count () {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.card-body {
|
||||
padding: 10px;
|
||||
}
|
||||
.card-text {
|
||||
display: flex;
|
||||
}
|
||||
.icon {
|
||||
flex: 40%;
|
||||
align-self: center;
|
||||
}
|
||||
.amount {
|
||||
flex: 50%;
|
||||
text-align: right;
|
||||
margin-left: 10px;
|
||||
}
|
||||
</style>
|
@ -19,7 +19,7 @@
|
||||
import { mapGetters } from 'vuex'
|
||||
import { total } from '../libs/data_processing'
|
||||
export default {
|
||||
name: 'box',
|
||||
name: 'cardTag',
|
||||
props: [
|
||||
'tagname',
|
||||
'rows'
|
87
src/components/edit_tag.vue
Normal file
87
src/components/edit_tag.vue
Normal file
@ -0,0 +1,87 @@
|
||||
<template>
|
||||
<div class="tag">
|
||||
<div class="icon">
|
||||
<font-awesome-icon :style="{ color: value.color}" :icon="value.icon" class="fa-2x"/>
|
||||
</div>
|
||||
<div class="description">
|
||||
<div v-if="existing_tag">
|
||||
<h4>{{ value.name }}</h4>
|
||||
</div>
|
||||
<div v-else>
|
||||
<b-form-input type="text" v-model="value.name"></b-form-input>
|
||||
</div>
|
||||
<b-form-group horizontal
|
||||
label="Icône:"
|
||||
label-class="text-sm"
|
||||
label-for="icon">
|
||||
<b-form-input type="text" v-model="value.icon" id="icon"></b-form-input>
|
||||
</b-form-group>
|
||||
<b-form-group horizontal
|
||||
label="Couleur:"
|
||||
label-class="text-sm"
|
||||
label-for="color">
|
||||
<b-form-input type="color" v-model="value.color" id="color"></b-form-input>
|
||||
</b-form-group>
|
||||
<b-form-group horizontal
|
||||
label="Mots clés:"
|
||||
label-class="text-sm"
|
||||
label-for="keywords"
|
||||
description="Une expression clé par ligne">
|
||||
<b-form-textarea v-model="keywords" id="keywords"></b-form-textarea>
|
||||
</b-form-group>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters, mapActions } from 'vuex'
|
||||
export default {
|
||||
name: 'editTag',
|
||||
props: [
|
||||
'value'
|
||||
],
|
||||
data () {
|
||||
return {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
'tag': 'config/tag',
|
||||
}),
|
||||
keywords: {
|
||||
get: function () {
|
||||
return this.value.words.join('\n')
|
||||
},
|
||||
set: function (keywords) {
|
||||
var kwds = keywords.split('\n')
|
||||
this.value.words = kwds
|
||||
}
|
||||
},
|
||||
existing_tag () {
|
||||
return this.tag(this.value.name) ? true : false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.tag {
|
||||
text-align: left;
|
||||
align-self: center;
|
||||
display: flex;
|
||||
}
|
||||
.icon {
|
||||
flex: 10%;
|
||||
align-self: center;
|
||||
}
|
||||
.description {
|
||||
flex: 90%;
|
||||
text-align: left;
|
||||
align-self: center;
|
||||
}
|
||||
</style>
|
@ -1,6 +1,16 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<pie :chart-data="chartdata" :options="options" v-if="spendings[0] !== 0"></pie>
|
||||
<div>
|
||||
<div class="container">
|
||||
<pie :chart-data="chartdata" :options="options" v-if="spendings[0] !== 0"></pie>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<b-button-group size="sm">
|
||||
<b-button v-for="tag in selected_tags"
|
||||
:style="{'background-color': backgroundColor(tag)}">
|
||||
{{ tag }}
|
||||
</b-button>
|
||||
</b-button-group>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -16,19 +26,11 @@ export default {
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
selected_tags: [
|
||||
'virements',
|
||||
'cash',
|
||||
'autoroute',
|
||||
'train',
|
||||
'essence',
|
||||
'courses',
|
||||
'sans tags'
|
||||
],
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
legend: {
|
||||
display: false,
|
||||
position: 'left'
|
||||
}
|
||||
}
|
||||
@ -39,8 +41,14 @@ export default {
|
||||
'tag_filter_rows'
|
||||
]),
|
||||
...mapGetters('config', [
|
||||
'tag'
|
||||
'tag',
|
||||
'tags'
|
||||
]),
|
||||
selected_tags () {
|
||||
var sel = Object.keys(this.tags)
|
||||
sel.push('sans tags')
|
||||
return sel
|
||||
},
|
||||
chartdata () {
|
||||
return {
|
||||
labels: this.selected_tags,
|
||||
@ -49,11 +57,7 @@ export default {
|
||||
label: 'Dépenses',
|
||||
data: this.spendings,
|
||||
backgroundColor: this.selected_tags.map(t => {
|
||||
if (this.tag(t)) {
|
||||
return this.tag(t).color
|
||||
} else {
|
||||
return '#A9A9A9'
|
||||
}
|
||||
return this.backgroundColor(t)
|
||||
})
|
||||
}
|
||||
]
|
||||
@ -72,6 +76,13 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
backgroundColor (t) {
|
||||
if (this.tag(t)) {
|
||||
return this.tag(t).color
|
||||
} else {
|
||||
return '#A9A9A9'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,18 +17,22 @@ export default {
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
selected_tags: [
|
||||
'virements',
|
||||
'cash',
|
||||
'autoroute',
|
||||
'train',
|
||||
'essence',
|
||||
'courses',
|
||||
'sans tags'
|
||||
],
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
scales: {
|
||||
xAxes: [{
|
||||
type: 'time',
|
||||
time: {
|
||||
parser: 'MMMM YYYY',
|
||||
},
|
||||
scaleLabel: {
|
||||
display: true,
|
||||
format: 'MMMM YYYY',
|
||||
labelString: 'Date'
|
||||
}
|
||||
}]
|
||||
},
|
||||
legend: {
|
||||
position: 'left'
|
||||
}
|
||||
@ -41,8 +45,14 @@ export default {
|
||||
'tag_filter_rows': 'tag_filter_rows'
|
||||
}),
|
||||
...mapGetters('config', [
|
||||
'tag'
|
||||
'tag',
|
||||
'tags'
|
||||
]),
|
||||
selected_tags () {
|
||||
var sel = Object.keys(this.tags)
|
||||
sel.push('sans tags')
|
||||
return sel
|
||||
},
|
||||
datasets () {
|
||||
var datas = []
|
||||
this.selected_tags.forEach(t => {
|
||||
|
@ -1,17 +1,16 @@
|
||||
<template>
|
||||
<div>
|
||||
<div v-if="edit_mode" class="tag">
|
||||
<div v-if="edit_mode" class="categorie">
|
||||
<div class="icon">
|
||||
<font-awesome-icon :icon="edited_tag.icon" class="fa-2x"/>
|
||||
<font-awesome-icon :icon="edited_categorie.icon" class="fa-2x"/>
|
||||
<!--
|
||||
Icône inconnue
|
||||
-->
|
||||
|
||||
</div>
|
||||
<div class="description">
|
||||
<b-form-input type="text" v-model="edited_tag.name"></b-form-input>
|
||||
<b-form-input type="text" v-model="edited_tag.icon"></b-form-input>
|
||||
<b-form-input type="color" v-model="edited_tag.color"></b-form-input>
|
||||
<b-form-input type="text" v-model="edited_categorie.name"></b-form-input>
|
||||
<b-form-input type="text" v-model="edited_categorie.icon"></b-form-input>
|
||||
<b-form-input type="color" v-model="edited_categorie.color"></b-form-input>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<b-button-group vertical v-if="editable">
|
||||
@ -20,14 +19,15 @@
|
||||
</b-button-group>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="tag">
|
||||
<div class="icon">
|
||||
<font-awesome-icon :style="{ color: tag.color}" :icon="tag.icon" class="fa-2x"/>
|
||||
|
||||
<div v-else class="categorie">
|
||||
<div class="icon text-info">
|
||||
<font-awesome-icon :icon="categorie.icon" class="fa-2x"/>
|
||||
</div>
|
||||
<div class="description">
|
||||
<h4>{{ tag.name }}</h4>
|
||||
<h4>{{ categorie.name }}</h4>
|
||||
|
||||
Mots clés<span v-if="tag.invert"> (tout sauf)</span>: {{ tag.words.join(" - ") }}
|
||||
Mots clés<span v-if="categorie.invert"> (tout sauf)</span>: {{ categorie.words.length != 0 ? categorie.words.join(" - ") : 'Aucun' }}
|
||||
</div>
|
||||
<div class="actions">
|
||||
<!--
|
||||
@ -44,34 +44,34 @@
|
||||
<script>
|
||||
import { mapGetters, mapActions } from 'vuex'
|
||||
export default {
|
||||
name: 'tagConfig',
|
||||
name: 'categorieItem',
|
||||
props: [
|
||||
'tagname'
|
||||
'categoriename'
|
||||
],
|
||||
data () {
|
||||
return {
|
||||
default_tag: {
|
||||
default_categorie: {
|
||||
name: 'Tout',
|
||||
variant: 'info',
|
||||
icon: 'file-invoice-dollar'
|
||||
},
|
||||
edit_mode: false,
|
||||
edited_tag: {}
|
||||
edited_categorie: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('config', {
|
||||
getTag: 'tag'
|
||||
getcategorie: 'categorie'
|
||||
}),
|
||||
tag () {
|
||||
if (this.tagname) {
|
||||
return this.getTag(this.tagname)
|
||||
categorie () {
|
||||
if (this.categoriename) {
|
||||
return this.getcategorie(this.categoriename)
|
||||
} else {
|
||||
return this.default_tag
|
||||
return this.default_categorie
|
||||
}
|
||||
},
|
||||
editable () {
|
||||
if (this.tagname) {
|
||||
if (this.categoriename) {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
@ -80,14 +80,14 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
...mapActions('config', [
|
||||
'edit_tag'
|
||||
'edit_categorie'
|
||||
]),
|
||||
toggleEdit () {
|
||||
this.edited_tag = { ...this.tag }
|
||||
this.edited_categorie = { ...this.categorie }
|
||||
this.edit_mode = !this.edit_mode
|
||||
},
|
||||
save () {
|
||||
this.edit_tag(this.edited_tag)
|
||||
this.edit_categorie(this.edited_categorie)
|
||||
this.toggleEdit()
|
||||
}
|
||||
}
|
||||
@ -96,7 +96,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.tag {
|
||||
.categorie {
|
||||
display: flex;
|
||||
}
|
||||
.icon {
|
106
src/components/item_tag.vue
Normal file
106
src/components/item_tag.vue
Normal file
@ -0,0 +1,106 @@
|
||||
<template>
|
||||
<div class="item">
|
||||
<div v-if="edit_mode" class="tag">
|
||||
<edit-tag v-model="edited_tag"></edit-tag>
|
||||
</div>
|
||||
<div v-else class="tag">
|
||||
<div class="icon">
|
||||
<font-awesome-icon :style="{ color: tag.color}" :icon="tag.icon" class="fa-2x"/>
|
||||
</div>
|
||||
<div class="description">
|
||||
<h4>{{ tag.name }}</h4>
|
||||
Mots clés<span v-if="tag.invert"> (tout sauf)</span>: {{ tag.words.join(" - ") }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<b-button-group vertical>
|
||||
<div v-if="edit_mode">
|
||||
<b-button @click="save()">Sauver</b-button>
|
||||
<b-button @click="toggleEdit()">Annuler</b-button>
|
||||
<b-button @click="deleteIt()">Supprimer</b-button>
|
||||
</div>
|
||||
<div v-else>
|
||||
<b-button @click="toggleEdit()">Editer</b-button>
|
||||
</div>
|
||||
</b-button-group>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters, mapActions } from 'vuex'
|
||||
import editTag from './edit_tag'
|
||||
export default {
|
||||
name: 'tagItem',
|
||||
components: {
|
||||
editTag: editTag
|
||||
},
|
||||
props: [
|
||||
'tagname'
|
||||
],
|
||||
data () {
|
||||
return {
|
||||
edit_mode: false,
|
||||
edited_tag: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('config', {
|
||||
getTag: 'tag'
|
||||
}),
|
||||
tag () {
|
||||
return this.getTag(this.tagname)
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapActions('config', [
|
||||
'edit_tag',
|
||||
'delete_tag'
|
||||
]),
|
||||
toggleEdit () {
|
||||
// toggle edit mod for the tag
|
||||
this.edited_tag = { ...this.tag }
|
||||
this.edit_mode = !this.edit_mode
|
||||
},
|
||||
save () {
|
||||
// Save the edited tag
|
||||
this.edit_tag(this.edited_tag)
|
||||
this.toggleEdit()
|
||||
},
|
||||
deleteIt () {
|
||||
// Delete the edited tag
|
||||
this.delete_tag(this.edited_tag.name)
|
||||
this.toggleEdit()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.item {
|
||||
display: flex;
|
||||
}
|
||||
.tag {
|
||||
flex: 90%;
|
||||
text-align: left;
|
||||
align-self: center;
|
||||
display: flex;
|
||||
}
|
||||
.actions {
|
||||
flex: 10%;
|
||||
text-align: left;
|
||||
margin-left: 10px;
|
||||
align-self: center;
|
||||
}
|
||||
.icon {
|
||||
flex: 10%;
|
||||
align-self: center;
|
||||
}
|
||||
.description {
|
||||
flex: 90%;
|
||||
text-align: left;
|
||||
align-self: center;
|
||||
}
|
||||
</style>
|
92
src/components/new_tag.vue
Normal file
92
src/components/new_tag.vue
Normal file
@ -0,0 +1,92 @@
|
||||
<template>
|
||||
<div class="item">
|
||||
<div class="tag">
|
||||
<div v-if="!isNewTag">
|
||||
<b-button @click="toggle_new_tag" size="sm">
|
||||
<font-awesome-icon icon="plus" class="fa" /> Ajouter un tag
|
||||
</b-button>
|
||||
</div>
|
||||
<div class="description">
|
||||
<div v-if="isNewTag" class="tag">
|
||||
<edit-tag v-model="editedTag"></edit-tag>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<b-button-group vertical>
|
||||
<div v-if="isNewTag">
|
||||
<b-button @click="save()">Sauver</b-button>
|
||||
<b-button @click="toggle_new_tag()">Annuler</b-button>
|
||||
</div>
|
||||
</b-button-group>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters, mapActions } from 'vuex'
|
||||
import editTag from './edit_tag'
|
||||
export default {
|
||||
name: 'newTag',
|
||||
components: {
|
||||
editTag: editTag
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
isNewTag: false,
|
||||
emptyTag: {
|
||||
color: '',
|
||||
icon: 'question',
|
||||
name: '',
|
||||
variant: '',
|
||||
words: []
|
||||
},
|
||||
editedTag: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
},
|
||||
methods: {
|
||||
...mapActions('config', [
|
||||
'edit_tag'
|
||||
]),
|
||||
toggle_new_tag () {
|
||||
this.isNewTag = !this.isNewTag
|
||||
this.editedTag = { ...this.emptyTag }
|
||||
},
|
||||
save () {
|
||||
this.edit_tag(this.editedTag)
|
||||
this.toggle_new_tag()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.item {
|
||||
display: flex;
|
||||
}
|
||||
.tag {
|
||||
flex: 90%;
|
||||
text-align: left;
|
||||
align-self: center;
|
||||
display: flex;
|
||||
}
|
||||
.actions {
|
||||
flex: 10%;
|
||||
text-align: left;
|
||||
margin-left: 10px;
|
||||
align-self: center;
|
||||
}
|
||||
.icon {
|
||||
flex: 10%;
|
||||
align-self: center;
|
||||
}
|
||||
.description {
|
||||
flex: 90%;
|
||||
text-align: left;
|
||||
align-self: center;
|
||||
}
|
||||
</style>
|
@ -1,17 +1,17 @@
|
||||
import moment from 'moment'
|
||||
export function appendTag (row, keywords, field = 'Libellé') {
|
||||
// Append row.tag
|
||||
export function appendKeywordField (row, toField, keywords, fromField = 'Libellé') {
|
||||
// Append row[toField] base on keywords
|
||||
// if row.libellé contains one of words and not invert it gets tagged
|
||||
// if row.libellé contains no words and invert it gets tagged
|
||||
// according to keywords [{name: string, words: [], invert: bool}]
|
||||
row.tags = keywords.filter(k => {
|
||||
return strContains(row[field], k.words, k.invert)
|
||||
row[toField] = keywords.filter(k => {
|
||||
return strContains(row[fromField], k.words, k.invert)
|
||||
})
|
||||
}
|
||||
|
||||
function strContains (string, words, invert) {
|
||||
// Does a string contain one of words or the opposite
|
||||
if (!words) {
|
||||
if (words.length === 0) {
|
||||
return true
|
||||
}
|
||||
if (invert) {
|
||||
@ -35,19 +35,19 @@ export function total (rows, field = 'Montant') {
|
||||
return Math.round(sum)
|
||||
}
|
||||
|
||||
export function tagFilter (rows, tags, invert = false) {
|
||||
// filter rows by tags
|
||||
export function keywordFilter (rows, field, keywords, invert = false) {
|
||||
// filter rows by keywords in rows[field]
|
||||
// invert inverts the selection
|
||||
return rows.filter(row => {
|
||||
if (invert) {
|
||||
return tags.some(t => {
|
||||
return row.tags.map(t => t.name.toLowerCase())
|
||||
.indexOf(t.toLowerCase()) < 0
|
||||
return keywords.some(kwd => {
|
||||
return row[field].map(k => k.name.toLowerCase())
|
||||
.indexOf(kwd.toLowerCase()) < 0
|
||||
})
|
||||
} else {
|
||||
return tags.every(t => {
|
||||
return row.tags.map(t => t.name.toLowerCase())
|
||||
.indexOf(t.toLowerCase()) > -1
|
||||
return keywords.every(kwd => {
|
||||
return row[field].map(k => k.name.toLowerCase())
|
||||
.indexOf(kwd.toLowerCase()) > -1
|
||||
})
|
||||
}
|
||||
})
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { readFile } from 'fs'
|
||||
import { readFile, writeFile } from 'fs'
|
||||
import Vue from 'vue'
|
||||
import path from 'path'
|
||||
import yaml from 'js-yaml'
|
||||
|
||||
@ -8,7 +9,8 @@ export default {
|
||||
data_dir: '/home/lafrite/scripts/comptes/data/',
|
||||
config_dir: '/home/lafrite/scripts/comptes/config/',
|
||||
config_filename: 'config.yml',
|
||||
tags: {}
|
||||
tags: {},
|
||||
categories: {}
|
||||
},
|
||||
getters: {
|
||||
data_dir: (state) => {
|
||||
@ -24,17 +26,37 @@ export default {
|
||||
return state.tags
|
||||
},
|
||||
tag: (state) => (tagname) => {
|
||||
return state.tags[tagname.toLowerCase()]
|
||||
return state.tags[tagname.toLowerCase()]
|
||||
},
|
||||
categories: (state) => {
|
||||
return state.categories
|
||||
},
|
||||
categorie: (state) => (categorieName) => {
|
||||
return state.categories[categorieName.toLowerCase()]
|
||||
}
|
||||
},
|
||||
mutations: {
|
||||
SET_TAGS: (state, { tags }) => {
|
||||
state.tags = Object.keys(tags)
|
||||
.reduce((c, k) => (c[k.toLowerCase()] = tags[k], c), {})
|
||||
}
|
||||
// Set tags list
|
||||
state.tags = Object.keys(tags)
|
||||
.reduce((c, k) => (c[k.toLowerCase()] = tags[k], c), {})
|
||||
},
|
||||
APPEND_TAG: (state, { tag }) => {
|
||||
// Append or replace et tag
|
||||
Vue.set(state.tags, tag.name.toLowerCase(), tag)
|
||||
},
|
||||
DELETE_TAG: (state, { tagname }) => {
|
||||
// delete tag by its name
|
||||
Vue.delete(state.tags, tagname.toLowerCase())
|
||||
},
|
||||
SET_CATEGORIES: (state, { categories }) => {
|
||||
state.categories = Object.keys(categories)
|
||||
.reduce((c, k) => (c[k.toLowerCase()] = categories[k], c), {})
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
load (context) {
|
||||
// load config file
|
||||
readFile(path.join(context.getters.config_dir, context.getters.config_filename), 'utf8', (err, content) => {
|
||||
if (err) {
|
||||
console.log(err)
|
||||
@ -44,11 +66,37 @@ export default {
|
||||
}
|
||||
var parsed = yaml.safeLoad(content, parseConfig)
|
||||
context.commit('SET_TAGS', { tags: parsed.tags })
|
||||
context.commit('SET_CATEGORIES', { categories: parsed.categories })
|
||||
}
|
||||
})
|
||||
},
|
||||
save (context) {
|
||||
// save config file
|
||||
var config = {
|
||||
categories: context.state.categories,
|
||||
tags: context.state.tags
|
||||
}
|
||||
var yamlConfig = yaml.safeDump(config)
|
||||
writeFile(path.join(context.getters.config_dir, context.getters.config_filename), yamlConfig, (err) => {
|
||||
if (err) throw err
|
||||
console.log('The file has been saved!')
|
||||
})
|
||||
context.dispatch('datas/compute_tags', null, { root: true })
|
||||
},
|
||||
edit_tag (context, tag) {
|
||||
console.log(tag)
|
||||
// Edit or append a tag to config
|
||||
context.commit('APPEND_TAG', { tag: tag })
|
||||
context.dispatch('save')
|
||||
},
|
||||
delete_tag (context, tagname) {
|
||||
// Revome a tag from the config
|
||||
context.commit('DELETE_TAG', { tagname: tagname })
|
||||
context.dispatch('save')
|
||||
},
|
||||
append_keywords (context, { tagName, keyword }) {
|
||||
var tag = context.getters.tag(tagName)
|
||||
tag.words.push(keyword)
|
||||
context.dispatch('edit_tag', tag)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,13 +3,13 @@ import Vue from 'vue'
|
||||
import path from 'path'
|
||||
import Papa from 'papaparse'
|
||||
import moment from 'moment'
|
||||
import { appendTag, formatDate, tagFilter } from '../../libs/data_processing'
|
||||
import { appendKeywordField, formatDate, keywordFilter } from '../../libs/data_processing'
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state: {
|
||||
csv: {},
|
||||
month: moment()
|
||||
month: ''
|
||||
},
|
||||
getters: {
|
||||
csvs: (state) => {
|
||||
@ -48,9 +48,13 @@ export default {
|
||||
// return data with negatives 'Montant'
|
||||
return getters.rows.filter(x => x.Montant < 0)
|
||||
},
|
||||
month: (state) => {
|
||||
month: (state, getters) => {
|
||||
// month date
|
||||
return state.month
|
||||
if (state.month){
|
||||
return state.month
|
||||
} else {
|
||||
return moment(getters.months.slice(-1)[0], "MMMM YYYY")
|
||||
}
|
||||
},
|
||||
date_filter_rows: (state, getters) => {
|
||||
// return rows filtered by date
|
||||
@ -69,11 +73,33 @@ export default {
|
||||
rows = getters.spending_rows
|
||||
}
|
||||
if (tags.length > 0) {
|
||||
return tagFilter(rows, tags, invert)
|
||||
return keywordFilter(rows, 'tags', tags, invert)
|
||||
} else {
|
||||
if (invert) {
|
||||
return rows.filter(r => {
|
||||
return r.tags.map(t => t.name.toLowerCase()).toString() === ['cb'].toString()
|
||||
return r.tags.length === 0
|
||||
})
|
||||
} else {
|
||||
return rows
|
||||
}
|
||||
}
|
||||
},
|
||||
categorie_filter_rows: (state, getters) => (categories, invert, dateFilter = true) => {
|
||||
// return rows filtered by categories
|
||||
// by default it filters rows by date
|
||||
// to disable date filtering set date_filter to false
|
||||
var rows
|
||||
if (dateFilter) {
|
||||
rows = getters.date_filter_rows
|
||||
} else {
|
||||
rows = getters.spending_rows
|
||||
}
|
||||
if (categories.length > 0) {
|
||||
return keywordFilter(rows, 'categorie', categories, invert)
|
||||
} else {
|
||||
if (invert) {
|
||||
return rows.filter(r => {
|
||||
return r.categories.length === 0
|
||||
})
|
||||
} else {
|
||||
return rows
|
||||
@ -101,9 +127,10 @@ export default {
|
||||
},
|
||||
months: (state, getters) => {
|
||||
// Set of month
|
||||
return [...new Set(getters.rows.map(x => moment(x.Date).format('MMMM YYYY')))]
|
||||
return [...new Set(getters.rows.map(x => moment(x.Date).format('MMMM YYYY')))].sort((left, right) => {
|
||||
return moment(left, 'MMMM YYYY').diff(moment(right, 'MMMM YYYY'))
|
||||
})
|
||||
}
|
||||
|
||||
},
|
||||
mutations: {
|
||||
CLEAR_DATA: (state) => {
|
||||
@ -158,9 +185,11 @@ export default {
|
||||
},
|
||||
clean_store_data (context, { filename, parsed }) {
|
||||
var tags = Object.values(context.rootGetters['config/tags'])
|
||||
var categories = Object.values(context.rootGetters['config/categories'])
|
||||
parsed.data = parsed.data.filter(x => x.Libellé !== undefined)
|
||||
parsed.data.forEach(row => {
|
||||
appendTag(row, tags, 'Libellé')
|
||||
appendKeywordField(row, 'tags', tags, 'Libellé')
|
||||
appendKeywordField(row, 'categorie', categories, 'Libellé')
|
||||
formatDate(row, 'Date')
|
||||
})
|
||||
|
||||
@ -169,6 +198,19 @@ export default {
|
||||
{ filename: filename, data: parsed }
|
||||
)
|
||||
},
|
||||
compute_tags (context) {
|
||||
var tags = Object.values(context.rootGetters['config/tags'])
|
||||
var categories = Object.values(context.rootGetters['config/categories'])
|
||||
Object.values(context.state.csv).forEach(csv => {
|
||||
csv.data.forEach(row => {
|
||||
appendKeywordField(row, 'tags', tags, 'Libellé')
|
||||
appendKeywordField(row, 'categorie', categories, 'Libellé')
|
||||
})
|
||||
context.commit('SET_DATA',
|
||||
{ filename: csv.filename, data: csv }
|
||||
)
|
||||
})
|
||||
},
|
||||
next_month (context) {
|
||||
var next = moment(context.getters.month).add(1, 'months')
|
||||
context.commit('SET_MONTH', { month: next })
|
||||
@ -176,6 +218,9 @@ export default {
|
||||
prev_month (context) {
|
||||
var prev = moment(context.getters.month).subtract(1, 'months')
|
||||
context.commit('SET_MONTH', { month: prev })
|
||||
},
|
||||
set_month (context, month) {
|
||||
context.commit('SET_MONTH', { month: month })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,12 +2,14 @@
|
||||
<div class="tags">
|
||||
<h1>
|
||||
Fichiers CSV
|
||||
<b-button @click="reload_csvs">
|
||||
<font-awesome-icon icon="sync-alt" class="fa" />
|
||||
</b-button>
|
||||
</h1>
|
||||
<p>
|
||||
Les fichiers csv sont cherché dans <span class="datadir">{{ data_dir }}</span>
|
||||
<p>
|
||||
<b-button @click="reload_csvs" size="sm">
|
||||
<font-awesome-icon icon="sync-alt" class="fa" /> Recharger
|
||||
</b-button>
|
||||
</p>
|
||||
<p>
|
||||
Les fichiers csv sont cherchés dans <span class="dir">{{ data_dir }}</span>
|
||||
<!--
|
||||
<b-button variant="link" @click="open_filebrowser(data_dir)"> Ouvrir <font-awesome-icon icon="folder-open" class="fa"/></b-button>
|
||||
-->
|
||||
@ -24,10 +26,30 @@
|
||||
</b-list-group-item>
|
||||
</b-list-group>
|
||||
</p>
|
||||
<h1>Tags</h1>
|
||||
<h1>
|
||||
Config
|
||||
</h1>
|
||||
<p>
|
||||
<b-button @click="reload_config" size="sm">
|
||||
<font-awesome-icon icon="sync-alt" class="fa" /> Recharger
|
||||
</b-button>
|
||||
</p>
|
||||
<p>
|
||||
Le fichier configuration se trouve à <span class="dir">{{ config_dir + config_filename}}</span>
|
||||
</p>
|
||||
<h2>Tags</h2>
|
||||
<b-list-group>
|
||||
<b-list-group-item>
|
||||
<new-tag></new-tag>
|
||||
</b-list-group-item>
|
||||
<b-list-group-item v-for="tag in tags">
|
||||
<tag-config :tagname="tag.name"></tag-config>
|
||||
<tag-item :tagname="tag.name"></tag-item>
|
||||
</b-list-group-item>
|
||||
</b-list-group>
|
||||
<h2>Categories</h2>
|
||||
<b-list-group>
|
||||
<b-list-group-item v-for="categorie in categories">
|
||||
<categorie-item :categoriename="categorie.name"></categorie-item>
|
||||
</b-list-group-item>
|
||||
</b-list-group>
|
||||
</div>
|
||||
@ -35,31 +57,36 @@
|
||||
|
||||
<script>
|
||||
import { mapGetters, mapActions } from 'vuex'
|
||||
import { shell } from 'electron'
|
||||
import tagConfig from '../components/tag_config'
|
||||
import tagItem from '../components/item_tag'
|
||||
import tagEdit from '../components/edit_tag'
|
||||
import newTag from '../components/new_tag'
|
||||
import categorieItem from '../components/item_categorie'
|
||||
|
||||
export default {
|
||||
name: 'home',
|
||||
components: {
|
||||
'tag-config': tagConfig
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
file: ''
|
||||
}
|
||||
},
|
||||
mounted: function () {
|
||||
'tag-item': tagItem,
|
||||
'tag-edit': tagEdit,
|
||||
'new-tag': newTag,
|
||||
'categorie-item': categorieItem
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
'data_dir': 'config/data_dir',
|
||||
'config_dir': 'config/config_dir',
|
||||
'config_filename': 'config/config_filename',
|
||||
'csvs': 'datas/csvs',
|
||||
'tags': 'config/tags'
|
||||
'tags': 'config/tags',
|
||||
'categories': 'config/categories'
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
...mapActions('datas', {
|
||||
'reload_csvs': 'load_csvs'
|
||||
'reload_csvs': 'load_csvs'
|
||||
}),
|
||||
...mapActions('config', {
|
||||
'reload_config': 'load',
|
||||
'save_config': 'save'
|
||||
}),
|
||||
open_filebrowser (dir) {
|
||||
console.log("plop")
|
||||
@ -69,13 +96,13 @@ export default {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.datadir {
|
||||
.dir {
|
||||
font-weight: bold;
|
||||
}
|
||||
.left {
|
||||
float: left;
|
||||
float: left;
|
||||
}
|
||||
.right {
|
||||
float: right;
|
||||
float: right;
|
||||
}
|
||||
</style>
|
||||
|
@ -21,21 +21,35 @@
|
||||
</b-container>
|
||||
|
||||
<b-card-group deck class="mb-3">
|
||||
<box @click.native="set_tags_filter([])"></box>
|
||||
<box @click.native="set_tags_filter(['cash'])" tagname="cash"></box>
|
||||
<box @click.native="set_tags_filter(['cb'])" tagname="cb"></box>
|
||||
<box @click.native="set_tags_filter(['virements'])" tagname="virements"></box>
|
||||
<div v-for="categorie in categories">
|
||||
<card-categorie @click.native="set_categories_filter([categorie.name])" :categoriename="categorie.name"></card-categorie>
|
||||
</div>
|
||||
</b-card-group>
|
||||
|
||||
<tags-comparison></tags-comparison>
|
||||
|
||||
<b-table striped hover :items="filtered_rows" :fields='fields'>
|
||||
<template slot="tags" slot-scope="data">
|
||||
<div v-for="tag in data.item.tags" :key="tag.name">
|
||||
<div v-if="tag.name !== 'Tout'">
|
||||
<div v-if="data.item.tags.length > 0">
|
||||
<div v-for="tag in data.item.tags" :key="tag.name">
|
||||
<font-awesome-icon :icon="tag.icon" class="fa"/>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<b-btn v-b-modal="data.item.Libellé">
|
||||
<font-awesome-icon icon="plus" class="fa"/>
|
||||
</b-btn>
|
||||
|
||||
<!-- Modal Component -->
|
||||
<b-modal :id="data.item.Libellé"
|
||||
title="Tag pour le mot clé"
|
||||
hide-footer
|
||||
>
|
||||
<associate-tag-keyword
|
||||
:libelle="data.item.Libellé">
|
||||
</associate-tag-keyword>
|
||||
</b-modal>
|
||||
</div>
|
||||
</template>
|
||||
</b-table>
|
||||
</div>
|
||||
@ -56,9 +70,10 @@
|
||||
|
||||
<script>
|
||||
import { mapGetters, mapActions } from 'vuex'
|
||||
import box from '../components/box'
|
||||
import tagsComparison from '../components/tags_comparison'
|
||||
import cardCategorie from '../components/card_categorie'
|
||||
import tagsComparison from '../components/graph_tags_comparison'
|
||||
import graphTime from '../components/graph_time'
|
||||
import associateTagKeyword from '../components/associate_tag_keyword'
|
||||
import moment from 'moment'
|
||||
|
||||
moment.locale('fr')
|
||||
@ -66,9 +81,10 @@ moment.locale('fr')
|
||||
export default {
|
||||
name: 'home',
|
||||
components: {
|
||||
box: box,
|
||||
cardCategorie: cardCategorie,
|
||||
tagsComparison: tagsComparison,
|
||||
graphTime: graphTime
|
||||
graphTime: graphTime,
|
||||
associateTagKeyword: associateTagKeyword
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
@ -95,30 +111,35 @@ export default {
|
||||
variant: 'info',
|
||||
icon: 'file-invoice-dollar'
|
||||
},
|
||||
tags_filter: []
|
||||
categories_filter: [],
|
||||
keyword: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
'csvs': 'datas/csvs',
|
||||
'tag_filter_rows': 'datas/tag_filter_rows',
|
||||
'categorie_filter_rows': 'datas/categorie_filter_rows',
|
||||
'datas_present': 'datas/present',
|
||||
'month': 'datas/month',
|
||||
'months': 'datas/months',
|
||||
'tags': 'config/tags'
|
||||
'tags': 'config/tags',
|
||||
'categories': 'config/categories'
|
||||
}),
|
||||
filtered_rows () {
|
||||
return this.tag_filter_rows(this.tags_filter)
|
||||
},
|
||||
return this.categorie_filter_rows(this.categories_filter)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions('datas', [
|
||||
'next_month',
|
||||
'prev_month',
|
||||
'prev_month'
|
||||
]),
|
||||
set_tags_filter (tagnames) {
|
||||
this.tags_filter = tagnames
|
||||
set_categories_filter (categorienames) {
|
||||
this.categories_filter = categorienames
|
||||
},
|
||||
showModal (name) {
|
||||
console.log(name)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
Loading…
Reference in New Issue
Block a user