diff --git a/www/graph.css b/www/graph.css index 6711213..ac71581 100644 --- a/www/graph.css +++ b/www/graph.css @@ -257,6 +257,46 @@ svg.zoomed.zoomed2 .node text.nodeTitle { opacity: 1 !important; } +.node.Institution.Institution-company path{ + fill: blue; +} +.node.Institution.Institution-government path{ + fill: orange; +} +.node.Institution.Institution-local-government path{ + fill: purple; +} +.node.Institution.Institution-law-enforcement path{ + fill: seagreen; +} +.node.Institution.Institution-ngo path{ + fill: yellow; +} +.node.Institution.Institution-university path{ + fill: pink; +} +.node.Institution.Institution-research path{ + fill: fuchsia; +} +.node.Institution.Institution-project path{ + fill: rgb(0, 255, 255); +} +.node.Institution.Institution-watchdog path{ + fill: rgb(145, 255, 0); +} +.node.Institution.Institution-expert-group path{ + fill: rgb(149, 87, 161); +} +.node.Institution.Institution-foundation path{ + fill: brown; +} +.node.Institution.Institution-international-organization path{ + fill: gray; +} +.node.Institution.Institution-art-project path{ + /* fill: blue; */ +} + /* .node.Person circle { fill: var(--color2) } diff --git a/www/graph.js b/www/graph.js index 075f06f..07302cb 100644 --- a/www/graph.js +++ b/www/graph.js @@ -4,7 +4,7 @@ const CONFIG = { 'subtitle': "A survey of the European Union", // 'nodeSize': 8, 'nodeRadius': 5, - 'nodeRepositionPadding': 10, + 'nodeRepositionPadding': 12, 'baseUrl': 'https://www.securityvision.io/wiki/index.php/', 'dataUrl': 'result2.json', 'preSimulate': false, // run simulation before starting, so we don't start with lines jumping around @@ -17,7 +17,74 @@ const CONFIG = { 'lonMax': 35, 'center': [11, 47], }, - "filters": ["Institution", "Deployments",/* "Technology", "Dataset"*/], + "filters": { + "Institution": { + "label": "Institution", + "type": "categories", + }, + "Law Enforcement": { + // "label": "Institution", + "type": "institution_types", + }, + "NGO": { + // "label": "Institution", + "type": "institution_types", + }, + "Government": { + // "label": "Institution", + "type": "institution_types", + }, + "Regional Government": { + // "label": "Institution", + "type": "institution_types", + }, + "Local Government": { + // "label": "Institution", + "type": "institution_types", + }, + "Company": { + // "label": "Institution", + "type": "institution_types", + }, + "Foundation": { + // "label": "Institution", + "type": "institution_types", + }, + "University": { + // "label": "Institution", + "type": "institution_types", + }, + "Research": { + // "label": "Institution", + "type": "institution_types", + }, + "Labour Union": { + // "label": "Institution", + "type": "institution_types", + }, + "Watchdog": { + // "label": "Institution", + "type": "institution_types", + }, + "Expert Group": { + // "label": "Institution", + "type": "institution_types", + }, + "International Organization": { + // "label": "Institution", + "type": "institution_types", + }, + "Art Project": { + // "label": "Institution", + "type": "institution_types", + }, + "Deployments": { + "label": "Deployment", + "type": "categories", + }, + + /* "Technology", "Dataset"*/ + }, "link_properties": [ "Clients", @@ -46,7 +113,7 @@ const CONFIG = { "Country": ["Country"], "City": ["City"], // ["Deployment type"], // TODO: select this - // ["Institution type"], // TODO: select this (local gov, etc.) + "Institution" : ["Institution Type"], // TODO: select this (local gov, etc.) "Dataset": ["Datasets used"], "Company": ["Managed by", "Provided by", "Developped by (institutions)"], "Tech": ["Technologies Used", "Software Deployed"], @@ -196,7 +263,16 @@ function getTitle(obj) { } function getCategories(obj) { // console.log(obj); - return obj.printouts['Category'].map(n => n.fulltext.split(':')[1]); + let cats = obj.printouts['Category'].map(n => n.fulltext.split(':')[1]); + if(obj.printouts.hasOwnProperty("Institution Type") && obj.printouts['Institution Type'].length) { + obj.printouts['Institution Type'].forEach(type => { + cats.push(getInstitutionClass(type.fulltext)); + }); + } + return cats; +} +function getInstitutionClass(name) { + return "Institution-"+ slugify(name); } function getClasses(obj) { const classes = getCategories(obj); @@ -1444,6 +1520,7 @@ class Store { this.filters = { 'categories': [], + 'institution_types': [], } @@ -1503,10 +1580,18 @@ class Store { }); } + isFiltered(node) { + if(this.filters.categories.includes(node.printouts['Category'][0].fulltext.split(':')[1])) + return true; + if(node.printouts['Institution Type'].length && this.filters.institution_types.includes(node.printouts['Institution Type'][0].fulltext)) + return true; + return false; + } + filter() { // add and remove nodes from data based on type filters this.nodes.forEach((n) => { - if (!this.filters.categories.includes(n.printouts['Category'][0].fulltext.split(':')[1])) { + if (!this.isFiltered(n)) { if (n.filtered || typeof n.filtered === 'undefined') { n.filtered = false; this.graph.nodes.push(n); @@ -1524,14 +1609,16 @@ class Store { // add and remove links from data based on availability of nodes this.links.forEach((l) => { - if (this.graph.nodes.includes(l.source) && this.graph.nodes.includes(l.target)) { + // if (this.graph.nodes.includes(l.source) && this.graph.nodes.includes(l.target)) { + if (!l.source.filtered && !l.target.filtered) { if (l.filtered || typeof l.filtered === 'undefined') this.graph.links.push(l); l.filtered = false; } else { if (l.filtered === false) { + console.log('filter', l.id); this.graph.links.forEach((d, i) => { - if (l.id === d.id) { + if (l.nr === d.nr) { this.graph.links.splice(i, 1); } }); @@ -1539,39 +1626,50 @@ class Store { l.filtered = true; } }); + + console.log(this.graph.nodes.length, this.graph.links.length) } render() { - CONFIG.filters.forEach(f => { + Object.keys(CONFIG.filters).forEach(f => { + const settings = CONFIG.filters[f]; + if(settings.type == 'institution_types') + // TODO; For now, skip + return; + + let categories = [f]; + if( settings.type == 'institution_types') + categories = ['Institution', getInstitutionClass(f)]; + let labelEl = document.createElement('label') let inputEl = document.createElement('input') let textEl = document.createElement('span'); let svg = d3.select(labelEl).append('svg') .attr("viewBox", [-12, -12, 24, 24]); svg.append('g') - .attr("class", "node " + f) + .attr("class", "node " + categories.join(' ')) .append('path') - .attr('d', getSymbolForCategories(f)()); + .attr('d', getSymbolForCategories(categories)()); inputEl.type = "checkbox"; textEl.innerText = f; labelEl.appendChild(inputEl); labelEl.appendChild(textEl); - if (!this.filters.categories.includes(f)) { + if (!this.filters[settings.type].includes(f)) { inputEl.checked = true; } inputEl.addEventListener('change', (e) => { if (e.target.checked) { - this.filters.categories.forEach((d, i) => { + this.filters[settings.type].forEach((d, i) => { if (d == f) { - this.filters.categories.splice(i, 1); + this.filters[settings.type].splice(i, 1); } }); } else { - if (!this.filters.categories.includes(f)) { - this.filters.categories.push(f); + if (!this.filters[settings.type].includes(f)) { + this.filters[settings.type].push(f); } } this.filter();