Feat: Display tags in config and add colors to tag
This commit is contained in:
parent
877c269ee4
commit
bf788d2e9e
@ -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
|
||||||
|
@ -66,7 +66,6 @@ export default {
|
|||||||
<style scope>
|
<style scope>
|
||||||
.container {
|
.container {
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 40vh;
|
height: 420px;
|
||||||
width: 80vw;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -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') {
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
@ -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>
|
||||||
|
Loading…
Reference in New Issue
Block a user