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

View File

@ -66,7 +66,6 @@ export default {
<style scope>
.container {
position: relative;
height: 40vh;
width: 80vw;
height: 420px;
}
</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 no words and invert it gets tagged
// according to keywords [{name: string, words: [], invert: bool}]
// row['tags'] =
row.tags = keywords.filter(k => {
return strContains(row[field], k.words, k.invert)
})
@ -17,17 +16,17 @@ function strContains (string, words, invert) {
}
if (invert) {
return words.every(v => {
return string.indexOf(v) < 0
return string.toLowerCase().indexOf(v.toLowerCase()) < 0
})
} else {
return words.some(v => {
return string.indexOf(v) >= 0
return string.toLowerCase().indexOf(v.toLowerCase()) >= 0
})
}
}
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') {

View File

@ -22,11 +22,15 @@ export default {
},
tags: (state) => {
return state.tags
},
tag: (state) => (tagname) => {
return state.tags[tagname.toLowerCase()]
}
},
mutations: {
SET_TAGS: (state, { tags }) => {
state.tags = tags
state.tags = Object.keys(tags)
.reduce((c, k) => (c[k.toLowerCase()] = tags[k], c), {})
}
},
actions: {
@ -42,6 +46,9 @@ export default {
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 Vue from 'vue'
import path from 'path'
import Papa from 'papaparse'
import moment from 'moment'
@ -7,41 +8,45 @@ import { appendTag, formatDate } from '../../libs/data_processing'
export default {
namespaced: true,
state: {
csv_files: [],
rows: {
data: [],
meta: {
fields: []
}
},
csv: {},
start: moment().subtract(1, 'months'),
end: moment()
},
getters: {
csvs: (state) => {
return state.csv_files
// return array of csv filename
return Object.keys(state.csv)
},
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) => {
return state.rows.data.length > 0
present: (state, getters) => {
// is there any datas
return getters.rows.length > 0
},
spending_rows: (state, getters) => {
// return data with negatives 'Montant'
return getters.rows.filter(x => x.Montant < 0)
},
start: (state) => {
// Start date
return state.start.format(moment.HTML5_FMT.DATE)
},
end: (state) => {
// End date
return state.end.format(moment.HTML5_FMT.DATE)
},
date_filter_rows: (state, getters) => {
// return rows filtered by date
return getters.spending_rows.filter(x => {
return (x.Date >= state.start) & (x.Date < state.end)
})
},
tag_filter_rows: (state, getters) => (tags, invert) => {
// return rows filtered by date then by tags
if (tags) {
return getters.date_filter_rows.filter(row => {
if (invert) {
@ -65,6 +70,7 @@ export default {
}
},
libelle_filter_rows: (state, getters) => (words, invert) => {
// return rows filtered by present of words in 'Libellé'
if (!words) {
return getters.date_filter_rows
}
@ -87,11 +93,8 @@ export default {
SET_CSV_FILES: (state, { csvs }) => {
state.csv_files = csvs
},
SET_DATA: (state, { data }) => {
state.rows = data
},
APPEND_DATA: (state, { content }) => {
state.rows.push(content)
SET_DATA: (state, { filename, data }) => {
Vue.set(state.csv, filename, data)
},
SET_START: (state, { start }) => {
state.start = start
@ -129,11 +132,14 @@ export default {
header: true
}
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'])
parsed.data = parsed.data.filter(x => x.Libellé !== undefined)
parsed.data.forEach(row => {
@ -141,13 +147,15 @@ export default {
formatDate(row, 'Date')
})
context.commit('SET_DATA', { data: parsed })
context.commit('SET_DATA',
{ filename: filename, data: parsed }
)
},
set_start (context, start) {
context.commit('SET_START', { start: moment(start)})
context.commit('SET_START', { start: moment(start) })
},
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>
<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>
<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>
</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-row class="date-selector">
<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-col>
<b-col sm="1"><label for="end"> et </label></b-col>
@ -18,7 +18,7 @@
<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(['cb'])" tagname="cb"></box>
<box @click.native="set_tags_filter(['virements'])" tagname="virements"></box>
</b-card-group>
@ -26,7 +26,7 @@
<b-table striped hover :items="filtered_rows" :fields='fields'>
<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'">
<font-awesome-icon :icon="tag.icon" class="fa"/>
</div>