From f30149c4315450f6c70cd592754f77e612c2e278 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Guigal?= Date: Mon, 15 Oct 2018 11:58:47 +0200 Subject: [PATCH] Data export (#14) * show zoom widget only if the graph is not empty * remove Details, create TheButtonDownload * add kibana in comment in docker-compose.yml for debugging * Zip noeuds.csv, liens.csv and transactions.csv --- app/app.py | 16 +-- app/package-lock.json | 77 +++++++++++-- app/package.json | 1 + app/src/api.js | 2 +- app/src/components/App.vue | 16 ++- app/src/components/AppTable.vue | 137 ----------------------- app/src/components/DrawerLinksDetail.vue | 5 - app/src/components/Modal.vue | 39 ------- app/src/components/ModalLinksDetail.vue | 51 --------- app/src/components/TheButtonDownload.vue | 66 +++++++++++ app/src/components/ZoomWidget.vue | 35 +++--- app/src/mutation-types.js | 2 - app/src/store.js | 14 +-- app/src/utils.js | 17 +++ docker-compose.yml | 6 + 15 files changed, 195 insertions(+), 289 deletions(-) delete mode 100644 app/src/components/AppTable.vue delete mode 100644 app/src/components/Modal.vue delete mode 100644 app/src/components/ModalLinksDetail.vue create mode 100644 app/src/components/TheButtonDownload.vue diff --git a/app/app.py b/app/app.py index 17edf9d2..0cae8d14 100755 --- a/app/app.py +++ b/app/app.py @@ -45,17 +45,17 @@ def send_static(path): return send_from_directory('dist', path) -@application.route('/transactions') +@application.route('/transactions', methods=["POST"]) def get_transactions(): """ Returns all the transactions of a given entity """ - entity = request.args.get("node") + entities = request.get_json()['data']['entities'] query = { 'size': 200, 'query': { 'bool': { - 'should': [ - { 'term': { 'ben_entity_id': entity } }, - { 'term': { 'don_entity_id': entity } } + 'must': [ + { 'terms': { 'ben_entity_id': entities } }, + { 'terms': { 'don_entity_id': entities } } ] } } @@ -84,13 +84,13 @@ def get_transactions(): 'ben_pays_code', 'ben_code_postal', ] + rows = [] for transaction in transactions: - row = [transaction.get(column) for column in columns] + row = { k: v for (k, v) in transaction.items() if k in columns } rows.append(row) - response = {'columns': columns, 'rows': rows} - return jsonify(response) + return jsonify(rows) def format_properties(vp): for k in vp.keys(): diff --git a/app/package-lock.json b/app/package-lock.json index ed76a50d..d88271b9 100644 --- a/app/package-lock.json +++ b/app/package-lock.json @@ -1,6 +1,6 @@ { "name": "graph-explorer", - "version": "0.3.1", + "version": "0.4.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -2718,8 +2718,7 @@ "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, "cosmiconfig": { "version": "2.2.2", @@ -3569,6 +3568,11 @@ "event-emitter": "0.3.5" } }, + "es6-promise": { + "version": "3.0.2", + "resolved": "http://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz", + "integrity": "sha1-AQ1YWEI6XxGJeWZfRkhqlcbuK7Y=" + }, "es6-set": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", @@ -5392,6 +5396,11 @@ "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==", "dev": true }, + "immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=" + }, "import-local": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-1.0.0.tgz", @@ -5442,8 +5451,7 @@ "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "internal-ip": { "version": "1.2.0", @@ -5806,8 +5814,7 @@ "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "isexe": { "version": "2.0.0", @@ -5950,6 +5957,48 @@ } } }, + "jszip": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.1.5.tgz", + "integrity": "sha512-5W8NUaFRFRqTOL7ZDDrx5qWHJyBXy6velVudIzQUSoqAAYqzSh2Z7/m0Rf1QbmQJccegD0r+YZxBjzqoBiEeJQ==", + "requires": { + "core-js": "2.3.0", + "es6-promise": "3.0.2", + "lie": "3.1.1", + "pako": "1.0.6", + "readable-stream": "2.0.6" + }, + "dependencies": { + "core-js": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.3.0.tgz", + "integrity": "sha1-+rg/uwstjchfpjbEudNMdUIMbWU=" + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + }, + "readable-stream": { + "version": "2.0.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "0.10.31", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, "killable": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.0.tgz", @@ -5977,6 +6026,14 @@ "invert-kv": "1.0.0" } }, + "lie": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz", + "integrity": "sha1-mkNrLMd0bKWd56QfpGmz77dr2H4=", + "requires": { + "immediate": "3.0.6" + } + }, "load-json-file": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", @@ -6930,8 +6987,7 @@ "pako": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", - "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==", - "dev": true + "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==" }, "parse-asn1": { "version": "5.1.1", @@ -9465,8 +9521,7 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "utils-merge": { "version": "1.0.1", diff --git a/app/package.json b/app/package.json index 72fd4751..c58bd5fb 100644 --- a/app/package.json +++ b/app/package.json @@ -14,6 +14,7 @@ "axios": "^0.18.0", "d3": "^4.13.0", "jsnetworkx": "^0.3.4", + "jszip": "^3.1.5", "vue": "^2.5.11", "vue-material": "^1.0.0-beta-10.2", "vuex": "^3.0.1" diff --git a/app/src/api.js b/app/src/api.js index f1118a74..b1ac2903 100644 --- a/app/src/api.js +++ b/app/src/api.js @@ -18,7 +18,7 @@ export default { }) }, transactions(options, callback){ - axios.get(transactionsUrl, options).then(response => { + axios.post(transactionsUrl, options).then(response => { callback(response.data); }) } diff --git a/app/src/components/App.vue b/app/src/components/App.vue index 712be8c8..62d7cccc 100644 --- a/app/src/components/App.vue +++ b/app/src/components/App.vue @@ -4,10 +4,8 @@ - - - - + + @@ -18,20 +16,20 @@ import FilterList from "./FilterList.vue"; import Drawer from "./Drawer.vue"; import Graph from "./Graph.vue"; import ZoomWidget from "./ZoomWidget.vue"; -import Modal from "./Modal.vue"; -import ModalLinksDetail from "./ModalLinksDetail.vue"; +import TheButtonDownload from "./TheButtonDownload.vue"; import ProgressSpinner from "./ProgressSpinner"; -import { mapActions, mapState } from 'vuex'; +import { mapActions, mapState, mapGetters } from 'vuex'; export default { name: "app", - components: {Search, FilterList, Drawer, Graph, ZoomWidget, Modal, ModalLinksDetail, ProgressSpinner }, + components: {Search, FilterList, Drawer, Graph, ZoomWidget, TheButtonDownload, ProgressSpinner }, computed: { filter() { return this.$store.state.filter; }, - ...mapState(["showModal", "showProgressSpinner"]) + ...mapState(["showModal", "showProgressSpinner"]), + ...mapGetters(["showGraphWidgets"]) }, methods: { ...mapActions(['expand']) diff --git a/app/src/components/AppTable.vue b/app/src/components/AppTable.vue deleted file mode 100644 index 43b823d3..00000000 --- a/app/src/components/AppTable.vue +++ /dev/null @@ -1,137 +0,0 @@ - - - - - - diff --git a/app/src/components/DrawerLinksDetail.vue b/app/src/components/DrawerLinksDetail.vue index 9e046446..123f53a6 100644 --- a/app/src/components/DrawerLinksDetail.vue +++ b/app/src/components/DrawerLinksDetail.vue @@ -15,21 +15,16 @@ - DÉTAIL diff --git a/app/src/components/Modal.vue b/app/src/components/Modal.vue deleted file mode 100644 index f542d33d..00000000 --- a/app/src/components/Modal.vue +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - diff --git a/app/src/components/ModalLinksDetail.vue b/app/src/components/ModalLinksDetail.vue deleted file mode 100644 index 9023f08b..00000000 --- a/app/src/components/ModalLinksDetail.vue +++ /dev/null @@ -1,51 +0,0 @@ - - - - - diff --git a/app/src/components/TheButtonDownload.vue b/app/src/components/TheButtonDownload.vue new file mode 100644 index 00000000..a0976afc --- /dev/null +++ b/app/src/components/TheButtonDownload.vue @@ -0,0 +1,66 @@ + + + + + diff --git a/app/src/components/ZoomWidget.vue b/app/src/components/ZoomWidget.vue index c2838acb..61266ed8 100644 --- a/app/src/components/ZoomWidget.vue +++ b/app/src/components/ZoomWidget.vue @@ -29,12 +29,11 @@ export default { diff --git a/app/src/mutation-types.js b/app/src/mutation-types.js index 49c67b08..866002ad 100644 --- a/app/src/mutation-types.js +++ b/app/src/mutation-types.js @@ -1,7 +1,5 @@ export const UPDATE_FILTER = 'UPDATE_FILTER'; export const UPDATE_FOCUS_NODE = 'UPDATE_FOCUS_NODE'; export const UPDATE_GRAPH = 'UPDATE_GRAPH'; -export const SHOW_MODAL = 'SHOW_MODAL'; -export const HIDE_MODAL = 'HIDE_MODAL'; export const SHOW_PROGRESS_SPINNER = 'SHOW_PROGRESS_SPINNER'; export const HIDE_PROGRESS_SPINNER = 'HIDE_PROGRESS_SPINNER'; \ No newline at end of file diff --git a/app/src/store.js b/app/src/store.js index 9a7142be..0b4ab639 100644 --- a/app/src/store.js +++ b/app/src/store.js @@ -1,7 +1,7 @@ import Vue from 'vue'; import Vuex from 'vuex'; -import { UPDATE_FILTER, UPDATE_FOCUS_NODE, UPDATE_GRAPH, SHOW_MODAL, HIDE_MODAL, - SHOW_PROGRESS_SPINNER, HIDE_PROGRESS_SPINNER } from './mutation-types'; +import { UPDATE_FILTER, UPDATE_FOCUS_NODE, UPDATE_GRAPH, +SHOW_PROGRESS_SPINNER, HIDE_PROGRESS_SPINNER } from './mutation-types'; import api from './api'; import * as jsnx from 'jsnetworkx'; @@ -15,7 +15,6 @@ export default new Vuex.Store({ }, focusNodeEntity: null, G: new jsnx.MultiDiGraph(), - showModal: false, showProgressSpinner: false }, getters: { @@ -47,6 +46,9 @@ export default new Vuex.Store({ .find(n => n.entity == state.focusNodeEntity) } return null; + }, + showGraphWidgets(state) { + return state.G.numberOfNodes() > 0 ? true : false; } }, mutations: { @@ -61,12 +63,6 @@ export default new Vuex.Store({ [UPDATE_GRAPH] (state, payload) { state.G = payload; }, - [SHOW_MODAL] (state) { - state.showModal = true; - }, - [HIDE_MODAL] (state) { - state.showModal = false; - }, [SHOW_PROGRESS_SPINNER] (state) { state.showProgressSpinner = true; }, diff --git a/app/src/utils.js b/app/src/utils.js index 09e6b780..2055caba 100644 --- a/app/src/utils.js +++ b/app/src/utils.js @@ -91,4 +91,21 @@ function defer () { deferred.reject = reject }) return deferred +} + +export function json2csv(items){ + if (items.length === 0 ) { + return ''; + } + const replacer = (key, value) => value === null ? '' : value; + const header = Object.keys(items[0]); + let csv = items.map(row => { + return header.map(fieldName =>{ + return JSON.stringify(row[fieldName], replacer) + }).join(',') + } + ) + csv.unshift(header.join(',')); + csv = csv.join('\r\n'); + return csv; } \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index c0c41ef1..66976cf9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -63,5 +63,11 @@ services: context: ./logstash depends_on: - elasticsearch + # kibana: + # image: docker.elastic.co/kibana/kibana:6.0.1 + # depends_on: + # - elasticsearch + # ports: + # - "5601:5601"