Created
March 6, 2020 10:03
-
-
Save bubnenkoff/60254cc52b6a84ee821a3bd438d67047 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!doctype html> | |
| <html> | |
| <head> | |
| <title>Network</title> | |
| <meta charset="utf-8"> | |
| <script type="text/javascript" src="https://unpkg.com/vis-network/standalone/umd/vis-network.min.js"></script> | |
| <link rel="stylesheet" href="https://cdn.rawgit.com/Chalarangelo/mini.css/v3.0.1/dist/mini-default.min.css"> | |
| <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> | |
| <style type="text/css"> | |
| #mynetwork { | |
| width: 1600px; | |
| height: 1000px; | |
| border: 1px solid lightgray; | |
| } | |
| #legende | |
| { | |
| width: 190px; | |
| border: 1px solid lightgray; | |
| background-color: #fffef8; | |
| /*position: absolute;*/ | |
| } | |
| .MainContainer | |
| { | |
| display: flex; | |
| flex-direction: row; | |
| } | |
| .LeftSide | |
| { | |
| width: 350px; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div id="app"> | |
| <div class="MainContainer"> | |
| <div class="LeftSide"> | |
| <div id="legende" style="padding-top: 20px;"> | |
| <div style="width: 85px; height: 35; margin: 5px; border: 2px solid black; background: #ffeda5">Компания</div> | |
| <div style="width: 85px; height: 35; margin: 5px; border: 2px solid black; background: #cadbf9">Владелец</div> | |
| <div style="width: 85px; height: 35; margin: 5px; border: 2px solid black; background: #f9caca">Учредитель</div> | |
| </div> | |
| <div class="MenuLeftSide"> | |
| <div> | |
| <div class="input-group"> | |
| <label>ИНН:</label><input v-model="selected_inn" type="number" placeholder="ИНН" style="appearance:textfield;"> <button @click="add_inn" class="small">+</button> | |
| <div v-for="inn in inn_list" v-bind:value="inn.value" style="padding-left: 10px;"> | |
| {{ inn.inn }} | |
| <button @click="remove_inn(inn.id, inn.inn )">-</button> | |
| </div> | |
| </div> | |
| <button @click="get_data">Получить данные</button> | |
| <button @click="make_deps">Оставить связи</button> | |
| <button @click="add_test">test</button> | |
| </div> | |
| <div> | |
| <div v-if="not_found_inn_list && not_found_inn_list.length" style="padding-left: 10px;">Не найдены следующие ИНН:</div> | |
| <div v-for="inn in not_found_inn_list" style="padding-left: 10px;">{{inn}}</div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- {{nodes}} --> | |
| <!-- {{edges}} --> | |
| <div id="mynetwork"> | |
| </div> | |
| </div> | |
| </div> | |
| <script type="text/javascript"> | |
| window.base_url = "http://127.0.0.1:8000" | |
| var app = new Vue({ | |
| el: '#app', | |
| data: { | |
| nextINNId : 1, // для инкремента | |
| network: {}, | |
| selected_inn: null, | |
| // inn_list: [{id: 1, inn: 6670373697}, {id: 2, inn: 6670479929} ], // который ищем | |
| inn_list: [ ], // который ищем | |
| not_found_inn_list: [], // который не нашли после проверки на сервере | |
| nodes : [], | |
| options: { | |
| physics: { | |
| enabled: true, | |
| barnesHut: { | |
| // springLength: 140, | |
| // springConstant: 1, | |
| // avoidOverlap: 1 | |
| }, | |
| }, | |
| autoResize: true, | |
| edges: { | |
| font: { | |
| size: 12 | |
| }, | |
| widthConstraint: { | |
| maximum: 90 | |
| } | |
| }, | |
| nodes: { | |
| shape: "box", | |
| widthConstraint: { | |
| maximum: 200 | |
| } | |
| }}, | |
| container: '', | |
| edges : [] | |
| }, | |
| methods: | |
| { | |
| add_inn() | |
| { | |
| if(this.inn_list.some(a=>a['inn'] === this.selected_inn )) // предотвращаем повторное добавление одного и того же ИНН | |
| { | |
| console.log("inn is already added") | |
| } | |
| else | |
| { | |
| this.inn_list.push({id: this.nextINNId, inn: this.selected_inn}) | |
| this.nextINNId++; | |
| } | |
| }, | |
| remove_inn(id, inn ) | |
| { | |
| this.inn_list = this.inn_list.filter(item => item.id !== id) | |
| // this.nodes = this.nodes.filter(item => item.parent != "5904988746") | |
| this.nodes = this.nodes.filter(item => item.parent !== inn.toString()) | |
| this.edges = this.edges.filter(item => item.parent !== inn.toString()) | |
| this.not_found_inn_list = this.not_found_inn_list.filter(item => item !== inn) | |
| window.mynetwork.setData({ nodes: this.nodes, edges: this.edges}); | |
| }, | |
| make_deps() | |
| { | |
| function getPath(graph, from, to) { | |
| let queue = [ from ]; | |
| let p = {}; | |
| p[from] = -1; | |
| while (queue.length > 0) { | |
| let v = queue.shift(); | |
| if (v == to) { | |
| break; | |
| } | |
| graph[v].forEach(edge => { | |
| if (!(edge in p)) { | |
| p[edge] = v; | |
| queue.push(edge); | |
| } | |
| }); | |
| } | |
| let ans = []; | |
| while (to != -1) { | |
| ans.push(to); | |
| to = p[to]; | |
| } | |
| console.log(ans); | |
| return ans; | |
| } | |
| let graph = {}; | |
| console.log(graph); | |
| this.edges.forEach(edge => { | |
| if (!(edge['from'] in graph)) { | |
| graph[edge['from']] = []; | |
| } | |
| if (!(edge['to'] in graph)) { | |
| graph[edge['to']] = []; | |
| } | |
| graph[edge['from']].push(edge['to']); | |
| graph[edge['to']].push(edge['from']); | |
| }); | |
| var path = getPath(graph, 6670373697, 6670479929); | |
| this.nodes = this.nodes.filter(node => path.includes(node['id'])); | |
| this.edges = this.edges.filter(edge => path.includes(edge['from']) && path.includes(edge['to'])); | |
| this.nodes = new vis.DataSet(this.nodes); | |
| this.edges = new vis.DataSet(this.edges); | |
| window.mynetwork.setData({ nodes: this.nodes, edges: this.edges}); | |
| // у нод родителей нужно взять значения id_path которое ниже будет использовано в фильтре | |
| // ноды родители берем из списка введенных inn_list | |
| // из каждого уникального родетеля parent нужно собрать все id_path и потом для каждого из них найти пересечения. Пересечения и будут тем ИНН которое общее и там и тут | |
| // id_path_list.push(...root_inn) | |
| /* | |
| const uniq_parent = [...new Set(this.nodes.map(item => item.parent))]; // получаем список уникальных родителей | |
| let result = {}; // подготавливаем словарь\объект заполняя его INN родителя как ключами? | |
| for (let value of uniq_parent) { | |
| result[value] = []; | |
| } | |
| // теперь итерируемся по каждому чтобы собрать для него все id_path | |
| for(item of this.nodes) | |
| { | |
| // collect[item.parent].push(...id_path); | |
| result[item.parent].push(...item.id_path); | |
| } | |
| console.log(result) | |
| // теперь удалим дубликаты, чтобы было проще | |
| for([k,v] of Object.entries(result)) | |
| { | |
| result[k] = [...new Set(v.map(item => item))] | |
| // console.log('== ', v) | |
| } | |
| // теперь объединяем инн и ищем дубликаты | |
| var total_inn_list = [] | |
| for([k,v] of Object.entries(result)) | |
| { | |
| total_inn_list.push(...v) // полный список дочерних ИНН для каждого родителя объединяем в один список | |
| } | |
| var dublicates_inn = total_inn_list.filter((e, i, a) => a.indexOf(e) !== i) | |
| console.log("total_inn_list: ", total_inn_list) | |
| console.log("dublicates_inn: ", dublicates_inn) | |
| // теперь из каждого node нужно выкинуть значения до него | |
| // толко для теста!!! | |
| // for(q of dublicates_inn) | |
| // { | |
| // for (el of this.nodes) | |
| // { | |
| // this.nodes = this.nodes.filter(item => item.id != q); | |
| // } | |
| // } | |
| window.mynetwork.setData({ nodes: this.nodes, edges: this.edges}); | |
| console.log(result) | |
| */ | |
| /* | |
| var id_path_list = []; | |
| var root_inn = this.inn_list.map(a=>a.inn) // inn которые являются корневыми | |
| //root_inn.push(...dublicates_inn) // добавим сюда узлы из тех что были выше | |
| console.log("root_inn: ", root_inn) | |
| console.log("this.nodes: ", this.nodes) | |
| for(inn of this.nodes) // идем по всем нодам и ищем корневые (выделенные жирным инн компаний которые мы ищем) | |
| { | |
| // console.log(inn.id, " ", inn.label ) | |
| let isFounded = inn.id_path.some( ai => dublicates_inn.includes(ai) ); | |
| if(!isFounded) | |
| { | |
| console.log("!: ", inn) | |
| // this.nodes = this.nodes.filter(item => item.id != inn.id); | |
| } | |
| else | |
| { | |
| console.log("!----------: ", inn) | |
| // this.nodes = this.nodes.filter(item => item.id != inn.id); | |
| } | |
| } | |
| console.log("2this.nodes: ", this.nodes) | |
| window.mynetwork.setData({ nodes: this.nodes, edges: this.edges}); | |
| */ | |
| // console.log("id_path_list: ", id_path_list); | |
| // // var mylist = ["6671074509", "661216744697", "6670387322", "661202720696"] | |
| // var mylist = ["662333903600", "667324212394", "6670373697"] | |
| // for (el of mylist) | |
| // { | |
| // this.nodes = this.nodes.filter(item => item.id != el); | |
| // // console.log(this.nodes) | |
| // } | |
| // window.mynetwork.setData({ nodes: this.nodes, edges: this.edges}); | |
| var id_path_list = []; | |
| var root_inn = this.inn_list.map(a=>a.inn) // inn которые являются корневыми | |
| console.log("root_inn: ", root_inn) | |
| for(inn of this.nodes) // идем по всем нодам и ищем корневые (выделенные жирным инн компаний которые мы ищем) | |
| { | |
| console.log(inn.id, " ", inn.label ) | |
| if(root_inn.includes(inn.id.toString())) | |
| { | |
| id_path_list.push(...inn.id_path); // предотвращаем массив в массиве | |
| } | |
| } | |
| console.log("id_path_list: ", id_path_list); | |
| // var mylist = ["6671074509", "661216744697", "6670387322", "661202720696"] | |
| var mylist = ["662333903600", "667324212394", "6670373697"] | |
| for (el of mylist) | |
| { | |
| this.nodes = this.nodes.filter(item => item.id != el); | |
| // console.log(this.nodes) | |
| } | |
| window.mynetwork.setData({ nodes: this.nodes, edges: this.edges}); | |
| }, | |
| get_data() | |
| { | |
| if(this.selected_inn && this.selected_inn.length >= 8) // небольшое удобство - поиск ИНН без его добавления кнопкой плюса в интерфейсе | |
| { | |
| if(this.inn_list.some(a=>a['inn'] === this.selected_inn )) // предотвращаем повторное добавление одного и того же ИНН | |
| { | |
| console.log("inn is already added") | |
| } | |
| else | |
| { | |
| this.inn_list.push({id: this.nextINNId, inn: this.selected_inn}) | |
| this.nextINNId++; | |
| } | |
| } | |
| axios.post(base_url + '/graph', this.inn_list) | |
| .then((response) => { | |
| if ('data' in response.data) | |
| { | |
| this.nodes = response.data.data.nodes; | |
| this.edges = response.data.data.edges; | |
| window.mynetwork.setData({ nodes: app.$root._data.nodes, edges: app.$root._data.edges}); | |
| // в msg у нас лежит предупреждение о том что не всё было найдено в случае если такое произошло иначе msg отстутсвует | |
| // not_found_inn_list список того что не было найдено | |
| if ('msg' in response.data) | |
| { | |
| this.not_found_inn_list = response.data.not_found_inn_list; | |
| } | |
| } | |
| if ('error' in response.data) | |
| { | |
| Notification.requestPermission().then(function(result) { | |
| var notification = new Notification(response.data.error); | |
| }); | |
| } | |
| //var network = new vis.Network(container, { nodes: app.$root._data.nodes, edges: app.$root._data.edges }, options); | |
| }).catch((error) => { | |
| console.log(error); | |
| }); | |
| }, | |
| add_test() | |
| { | |
| _nodes = [ | |
| {id: 1, label: 'Company 0', group: "company", borderWidth: 4, color: { border: '#077eb8' }, font: { size: 16}, }, | |
| {id: 2, label: 'Foo1', group: "owner"}, | |
| {id: 3, label: 'Foo2', group: "founder"}, | |
| {id: 4, label: 'Company 1', group: "company"}, | |
| {id: 5, label: 'Company 2', group: "company"}, | |
| {id: 6, label: 'Company 3', group: "company"}, | |
| {id: 8, label: 'Company 4', group: "company"}, | |
| {id: 9, label: 'Company 5', group: "company"}, | |
| {id: 10, label: 'Company 6', group: "company", borderWidth: 4, color: { border: '#077eb8' }, font: { size: 16},}, | |
| {id: 11, label: 'Company 7', group: "company"} | |
| ]; | |
| // create an array with edges | |
| _edges = [ | |
| {from: 1, to: 2}, | |
| {from: 1, to: 3}, | |
| {from: 2, to: 11}, | |
| {from: 3, to: 4}, | |
| {from: 2, to: 8}, | |
| {from: 3, to: 6}, | |
| {from: 3, to: 5}, | |
| {from: 4, to: 9}, | |
| {from: 4, to: 10} | |
| ] | |
| // console.log(this.nodes) | |
| this.nodes.push(..._nodes) | |
| this.edges.push(..._edges) | |
| console.log(this.nodes) | |
| window.mynetwork.setData({ nodes: app.$root._data.nodes, edges: app.$root._data.edges}); | |
| } | |
| }, | |
| mounted() { | |
| this.container = document.getElementById('mynetwork'); | |
| var data = { | |
| nodes: this.nodes, | |
| edges: this.edges | |
| }; | |
| window.mynetwork = new vis.Network(this.container, data, this.options); | |
| } | |
| }) | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment