From 7fc167505290b76db1d81e27aeca89d64598d112 Mon Sep 17 00:00:00 2001 From: Bertrand Benjamin Date: Sun, 27 Jan 2019 07:18:50 +0100 Subject: [PATCH] Feat(home): over time tag spending comparison --- src/components/charjs_line.vue | 17 +++++++ src/components/graph_time.vue | 85 +++++++++++++++++++++++++++++++++ src/libs/data_processing.js | 44 ++++++++++++++++- src/store/modules/datas.js | 41 ++++++++-------- src/views/home.vue | 87 ++++++++++++++++++---------------- 5 files changed, 213 insertions(+), 61 deletions(-) create mode 100644 src/components/charjs_line.vue create mode 100644 src/components/graph_time.vue diff --git a/src/components/charjs_line.vue b/src/components/charjs_line.vue new file mode 100644 index 0000000..0bf2a20 --- /dev/null +++ b/src/components/charjs_line.vue @@ -0,0 +1,17 @@ + + + diff --git a/src/components/graph_time.vue b/src/components/graph_time.vue new file mode 100644 index 0000000..0dd98cc --- /dev/null +++ b/src/components/graph_time.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/src/libs/data_processing.js b/src/libs/data_processing.js index cf66b11..ccb7e16 100644 --- a/src/libs/data_processing.js +++ b/src/libs/data_processing.js @@ -29,8 +29,48 @@ export function formatDate (row, field = 'Date') { row[field] = moment(row[field], 'DD/MM/YYYY', true) } -export function total (row, field = 'Montant') { - var sum = row.map(x => parseFloat(x[field])) +export function total (rows, field = 'Montant') { + var sum = rows.map(x => parseFloat(x[field])) .reduce((sum, x) => sum + x, 0) return Math.round(sum) } + +export function tag_filter (rows, tags, invert=false) { + // filter rows by tags + // 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 + }) + } else { + return tags.every(t => { + return row.tags.map(t => t.name.toLowerCase()) + .indexOf(t.toLowerCase()) > -1 + }) + } + }) +} + +function objectMap (object, mapFn) { + // map a function on object value + return Object.keys(object).reduce(function(result, key) { + result[key] = mapFn(object[key]) + return result + }, {}) +} + +export function groupBy (rows, grouping, agg) { + // Group rows by field then apply agg + var groups = rows.reduce((stock, row) => { + var group = grouping(row) + if (stock[group]) { + stock[group].push(row) + } else { + stock[group] = [row] + } + return stock + }, {}) + return objectMap(groups, group => agg(group)) +} diff --git a/src/store/modules/datas.js b/src/store/modules/datas.js index 3eb8250..de99c4c 100644 --- a/src/store/modules/datas.js +++ b/src/store/modules/datas.js @@ -3,7 +3,7 @@ import Vue from 'vue' import path from 'path' import Papa from 'papaparse' import moment from 'moment' -import { appendTag, formatDate } from '../../libs/data_processing' +import { appendTag, formatDate, tag_filter } from '../../libs/data_processing' export default { namespaced: true, @@ -57,27 +57,25 @@ export default { return moment(x.Date).isSame(state.month, 'month') }) }, - 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) { - return tags.some(t => { - return row.tags.map(t => t.name.toLowerCase()) - .indexOf(t.toLowerCase()) < 0 - }) - } else { - return tags.every(t => { - return row.tags.map(t => t.name.toLowerCase()) - .indexOf(t.toLowerCase()) > -1 - }) - } - }) + tag_filter_rows: (state, getters) => (tags, invert, dateFilter = true) => { + // return rows filtered by tags + // 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 (tags.length > 0) { + return tag_filter(rows, tags, invert) } else { if (invert) { - return [] + return rows.filter(r => { + return r.tags.map(t => t.name.toLowerCase()).toString() === ["cb"].toString() + }) } else { - return getters.date_filter_rows + return rows } } }, @@ -99,7 +97,12 @@ export default { }) }) } + }, + months: (state, getters) => { + // Set of month + return [... new Set(getters.rows.map(x => moment(x.Date).format('MMMM YYYY')))] } + }, mutations: { CLEAR_DATA: (state) => { diff --git a/src/views/home.vue b/src/views/home.vue index ef5c80b..0015de0 100644 --- a/src/views/home.vue +++ b/src/views/home.vue @@ -2,50 +2,54 @@

Analyse

- - - - - - - {{ month.format('MMMM YYYY') }} - - - - - - +

Sur le temps

+ - - - - - - +

Par mois

+ + + + + + + {{ month.format('MMMM YYYY') }} + + + + + + - + + + + + + - - - + + + + +
-
-

- - Pas de données - -

-

- Penser à en importer! -

-
+
+

+ + Pas de données + +

+

+ Penser à en importer! +

+
@@ -54,6 +58,7 @@ import { mapGetters, mapActions } from 'vuex' import box from '../components/box' import tagsComparison from '../components/tags_comparison' +import graphTime from '../components/graph_time' import moment from 'moment' moment.locale('fr') @@ -62,7 +67,8 @@ export default { name: 'home', components: { box: box, - tagsComparison: tagsComparison + tagsComparison: tagsComparison, + graphTime: graphTime }, data () { return { @@ -98,6 +104,7 @@ export default { 'tag_filter_rows': 'datas/tag_filter_rows', 'datas_present': 'datas/present', 'month': 'datas/month', + 'months': 'datas/months', 'tags': 'config/tags' }), filtered_rows () {