Feat: Display tags in config and add colors to tag

This commit is contained in:
Bertrand Benjamin 2018-12-04 18:37:28 +01:00
parent 877c269ee4
commit bf788d2e9e
7 changed files with 107 additions and 31 deletions

View File

@ -4,6 +4,7 @@ tags:
name: Cash name: Cash
variant: info variant: info
icon: money-bill-wave icon: money-bill-wave
color: '#78e08f'
words: words:
- RETRAIT - RETRAIT
@ -11,6 +12,7 @@ tags:
name: CB name: CB
variant: info variant: info
icon: credit-card icon: credit-card
color: "#4a69bd"
words: words:
- PAIEMENT - PAIEMENT
@ -19,6 +21,7 @@ tags:
variant: info variant: info
icon: directions icon: directions
invert: true invert: true
color: "#f6b93b"
words: words:
- PAIEMENT - PAIEMENT
- RETRAIT - RETRAIT
@ -27,6 +30,7 @@ tags:
name: Autoroute name: Autoroute
variant: danger variant: danger
icon: road icon: road
color: "#eb2f06"
words: words:
- AUTOROUTE - AUTOROUTE
- APRR - APRR
@ -35,6 +39,7 @@ tags:
name: Essence name: Essence
variant: danger variant: danger
icon: charging-station icon: charging-station
color: "#0c2461"
words: words:
- CARBU - CARBU
- TOTAL - TOTAL
@ -46,6 +51,7 @@ tags:
name: Courses name: Courses
variant: warning variant: warning
icon: shopping-cart icon: shopping-cart
color: "#665191"
words: words:
- BIOCOOP - BIOCOOP
- LA VIE CLAIRE - LA VIE CLAIRE

View File

@ -66,7 +66,6 @@ export default {
<style scope> <style scope>
.container { .container {
position: relative; position: relative;
height: 40vh; height: 420px;
width: 80vw;
} }
</style> </style>

View File

@ -4,7 +4,6 @@ export function appendTag (row, keywords, field = 'Libellé') {
// if row.libellé contains one of words and not invert it gets tagged // if row.libellé contains one of words and not invert it gets tagged
// if row.libellé contains no words and invert it gets tagged // if row.libellé contains no words and invert it gets tagged
// according to keywords [{name: string, words: [], invert: bool}] // according to keywords [{name: string, words: [], invert: bool}]
// row['tags'] =
row.tags = keywords.filter(k => { row.tags = keywords.filter(k => {
return strContains(row[field], k.words, k.invert) return strContains(row[field], k.words, k.invert)
}) })
@ -17,17 +16,17 @@ function strContains (string, words, invert) {
} }
if (invert) { if (invert) {
return words.every(v => { return words.every(v => {
return string.indexOf(v) < 0 return string.toLowerCase().indexOf(v.toLowerCase()) < 0
}) })
} else { } else {
return words.some(v => { return words.some(v => {
return string.indexOf(v) >= 0 return string.toLowerCase().indexOf(v.toLowerCase()) >= 0
}) })
} }
} }
export function formatDate (row, field = 'Date') { export function formatDate (row, field = 'Date') {
row[field] = moment(row[field], 'DD/MM/YYYY', true) row[field] = moment(row[field], 'DD/MM/YYYY', true)
} }
export function total (row, field = 'Montant') { export function total (row, field = 'Montant') {

View File

@ -22,11 +22,15 @@ export default {
}, },
tags: (state) => { tags: (state) => {
return state.tags return state.tags
},
tag: (state) => (tagname) => {
return state.tags[tagname.toLowerCase()]
} }
}, },
mutations: { mutations: {
SET_TAGS: (state, { tags }) => { SET_TAGS: (state, { tags }) => {
state.tags = tags state.tags = Object.keys(tags)
.reduce((c, k) => (c[k.toLowerCase()] = tags[k], c), {})
} }
}, },
actions: { actions: {
@ -42,6 +46,9 @@ export default {
context.commit('SET_TAGS', { tags: parsed.tags }) context.commit('SET_TAGS', { tags: parsed.tags })
} }
}) })
},
edit_tag (context, tag) {
console.log(tag)
} }
} }
} }

View File

@ -1,4 +1,5 @@
import { readdir, readFile } from 'fs' import { readdir, readFile } from 'fs'
import Vue from 'vue'
import path from 'path' import path from 'path'
import Papa from 'papaparse' import Papa from 'papaparse'
import moment from 'moment' import moment from 'moment'
@ -7,41 +8,45 @@ import { appendTag, formatDate } from '../../libs/data_processing'
export default { export default {
namespaced: true, namespaced: true,
state: { state: {
csv_files: [], csv: {},
rows: {
data: [],
meta: {
fields: []
}
},
start: moment().subtract(1, 'months'), start: moment().subtract(1, 'months'),
end: moment() end: moment()
}, },
getters: { getters: {
csvs: (state) => { csvs: (state) => {
return state.csv_files // return array of csv filename
return Object.keys(state.csv)
}, },
rows: (state) => { rows: (state) => {
return state.rows.data // return all data stored in csv
return [ ...new Set(Object.values(state.csv).map(csv => csv.data)
.reduce((acc, d) => acc.concat(d), [])
)]
}, },
present: (state) => { present: (state, getters) => {
return state.rows.data.length > 0 // is there any datas
return getters.rows.length > 0
}, },
spending_rows: (state, getters) => { spending_rows: (state, getters) => {
// return data with negatives 'Montant'
return getters.rows.filter(x => x.Montant < 0) return getters.rows.filter(x => x.Montant < 0)
}, },
start: (state) => { start: (state) => {
// Start date
return state.start.format(moment.HTML5_FMT.DATE) return state.start.format(moment.HTML5_FMT.DATE)
}, },
end: (state) => { end: (state) => {
// End date
return state.end.format(moment.HTML5_FMT.DATE) return state.end.format(moment.HTML5_FMT.DATE)
}, },
date_filter_rows: (state, getters) => { date_filter_rows: (state, getters) => {
// return rows filtered by date
return getters.spending_rows.filter(x => { return getters.spending_rows.filter(x => {
return (x.Date >= state.start) & (x.Date < state.end) return (x.Date >= state.start) & (x.Date < state.end)
}) })
}, },
tag_filter_rows: (state, getters) => (tags, invert) => { tag_filter_rows: (state, getters) => (tags, invert) => {
// return rows filtered by date then by tags
if (tags) { if (tags) {
return getters.date_filter_rows.filter(row => { return getters.date_filter_rows.filter(row => {
if (invert) { if (invert) {
@ -65,6 +70,7 @@ export default {
} }
}, },
libelle_filter_rows: (state, getters) => (words, invert) => { libelle_filter_rows: (state, getters) => (words, invert) => {
// return rows filtered by present of words in 'Libellé'
if (!words) { if (!words) {
return getters.date_filter_rows return getters.date_filter_rows
} }
@ -87,11 +93,8 @@ export default {
SET_CSV_FILES: (state, { csvs }) => { SET_CSV_FILES: (state, { csvs }) => {
state.csv_files = csvs state.csv_files = csvs
}, },
SET_DATA: (state, { data }) => { SET_DATA: (state, { filename, data }) => {
state.rows = data Vue.set(state.csv, filename, data)
},
APPEND_DATA: (state, { content }) => {
state.rows.push(content)
}, },
SET_START: (state, { start }) => { SET_START: (state, { start }) => {
state.start = start state.start = start
@ -129,11 +132,14 @@ export default {
header: true header: true
} }
var parsed = Papa.parse(content, parseConfig) var parsed = Papa.parse(content, parseConfig)
context.dispatch('clean_store_data', parsed) context.dispatch('clean_store_data', {
filename: csv,
parsed: parsed
})
} }
}) })
}, },
clean_store_data (context, parsed) { clean_store_data (context, { filename, parsed }) {
var tags = Object.values(context.rootGetters['config/tags']) var tags = Object.values(context.rootGetters['config/tags'])
parsed.data = parsed.data.filter(x => x.Libellé !== undefined) parsed.data = parsed.data.filter(x => x.Libellé !== undefined)
parsed.data.forEach(row => { parsed.data.forEach(row => {
@ -141,13 +147,15 @@ export default {
formatDate(row, 'Date') formatDate(row, 'Date')
}) })
context.commit('SET_DATA', { data: parsed }) context.commit('SET_DATA',
{ filename: filename, data: parsed }
)
}, },
set_start (context, start) { set_start (context, start) {
context.commit('SET_START', { start: moment(start)}) context.commit('SET_START', { start: moment(start) })
}, },
set_end (context, end) { set_end (context, end) {
context.commit('SET_END', { end: moment(end)}) context.commit('SET_END', { end: moment(end) })
} }
} }
} }

View File

@ -1,5 +1,62 @@
<template> <template>
<div class="tags"> <div class="tags">
<h1>Fichiers CSV</h1>
<p>
Les fichiers csv sont cherché dans <span class="datadir">{{ data_dir }}</span>
<!--
<b-button variant="link" @click="open_filebrowser(data_dir)"> Ouvrir <font-awesome-icon icon="folder-open" class="fa"/></b-button>
-->
<b-list-group>
<b-list-group-item v-for="csv in csvs">
{{ csv }}
</b-list-group-item>
</b-list-group>
</p>
<h1>Tags</h1> <h1>Tags</h1>
<b-list-group>
<b-list-group-item v-for="tag in tags">
<tag-config :tagname="tag.name"></tag-config>
</b-list-group-item>
</b-list-group>
</div> </div>
</template> </template>
<script>
import { mapGetters, mapActions } from 'vuex'
import { shell } from 'electron'
import tagConfig from '../components/tag_config'
export default {
name: 'home',
components: {
'tag-config': tagConfig
},
data () {
return {
file: ''
}
},
mounted: function () {
},
computed: {
...mapGetters({
'data_dir': 'config/data_dir',
'csvs': 'datas/csvs',
'tags': 'config/tags'
})
},
methods: {
...mapActions('datas', [
]),
open_filebrowser (dir) {
console.log("plop")
}
}
}
</script>
<style scoped>
.datadir {
font-weight: bold;
}
</style>

View File

@ -5,7 +5,7 @@
<b-container fluid> <b-container fluid>
<b-row class="date-selector"> <b-row class="date-selector">
<b-col sm="1"><label for="start"> Entre </label> </b-col> <b-col sm="1"><label for="start"> Entre </label> </b-col>
<b-col sm="4"> <b-col sm="3">
<b-form-input id="start" type="date" :value="start" @input="set_start"></b-form-input> <b-form-input id="start" type="date" :value="start" @input="set_start"></b-form-input>
</b-col> </b-col>
<b-col sm="1"><label for="end"> et </label></b-col> <b-col sm="1"><label for="end"> et </label></b-col>
@ -18,7 +18,7 @@
<b-card-group deck class="mb-3"> <b-card-group deck class="mb-3">
<box @click.native="set_tags_filter([])"></box> <box @click.native="set_tags_filter([])"></box>
<box @click.native="set_tags_filter(['cash'])" tagname="cash"></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(['cb'])" tagname="cb"></box>
<box @click.native="set_tags_filter(['virements'])" tagname="virements"></box> <box @click.native="set_tags_filter(['virements'])" tagname="virements"></box>
</b-card-group> </b-card-group>
@ -26,7 +26,7 @@
<b-table striped hover :items="filtered_rows" :fields='fields'> <b-table striped hover :items="filtered_rows" :fields='fields'>
<template slot="tags" slot-scope="data"> <template slot="tags" slot-scope="data">
<div v-for="tag in data.item.tags"> <div v-for="tag in data.item.tags" :key="tag.name">
<div v-if="tag.name !== 'Tout'"> <div v-if="tag.name !== 'Tout'">
<font-awesome-icon :icon="tag.icon" class="fa"/> <font-awesome-icon :icon="tag.icon" class="fa"/>
</div> </div>