From 484d9f9a237258b754eefbd00aeffedc1bd9cc4b Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 3 Dec 2019 11:06:08 -0500 Subject: [PATCH] wip --- jenkins/Jenkinsfile | 8 +- jenkins/deploy.sh | 2 +- music_graph/index.html | 2 +- music_graph/package-lock.json | 3 +- music_graph/src/MusicGraph.js | 90 +++++++++++++---------- music_graph/src/MusicGraphApi.js | 17 ++++- music_graph/src/components/ArtistInfo.vue | 6 +- music_graph/src/components/MainPage.vue | 6 +- music_graph/src/genres.js | 9 ++- music_graph/src/icons.js | 3 +- 10 files changed, 91 insertions(+), 55 deletions(-) diff --git a/jenkins/Jenkinsfile b/jenkins/Jenkinsfile index 01d439d..2c48cd7 100644 --- a/jenkins/Jenkinsfile +++ b/jenkins/Jenkinsfile @@ -34,10 +34,10 @@ pipeline { steps { node('master') { unstash 'webdist' - sshCommand remote: remote, command: "cd music-graph && rm -rf webroot/* deploy.sh" - sshPut remote: remote, from: 'webroot/', into: 'music-graph' - sshPut remote: remote, from: 'jenkins/deploy.sh', into: 'music-graph/' - sshCommand remote: remote, command: 'chmod +x music-graph/deploy.sh && ./music-graph/deploy.sh' + sshCommand remote: remote, command: "cd /srv/music-graph && rm -rf /srv/webroot/* deploy.sh" + sshPut remote: remote, from: 'webroot/', into: '/srv/music-graph' + sshPut remote: remote, from: 'jenkins/deploy.sh', into: '/srv/music-graph/' + sshCommand remote: remote, command: 'chmod +x /srv/music-graph/deploy.sh && /srv/music-graph/deploy.sh' } } } diff --git a/jenkins/deploy.sh b/jenkins/deploy.sh index 8b56473..9e60385 100755 --- a/jenkins/deploy.sh +++ b/jenkins/deploy.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -export MGROOT="music-graph" +export MGROOT="/srv/music-graph" chmod 755 -R "${MGROOT}/webroot" diff --git a/music_graph/index.html b/music_graph/index.html index 60ed5c5..034f255 100644 --- a/music_graph/index.html +++ b/music_graph/index.html @@ -5,7 +5,7 @@ - music-graph v1.1 + music-graph v1.2
diff --git a/music_graph/package-lock.json b/music_graph/package-lock.json index 06411a1..5cc0ee9 100644 --- a/music_graph/package-lock.json +++ b/music_graph/package-lock.json @@ -6657,7 +6657,8 @@ }, "js-yaml": { "version": "3.7.0", - "resolved": "", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.7.0.tgz", + "integrity": "sha1-XJZ93YN6m/3KXy3oQlOr6KHAO4A=", "dev": true, "requires": { "argparse": "^1.0.7", diff --git a/music_graph/src/MusicGraph.js b/music_graph/src/MusicGraph.js index 75ffbc8..195fc53 100644 --- a/music_graph/src/MusicGraph.js +++ b/music_graph/src/MusicGraph.js @@ -91,9 +91,12 @@ export function MusicGraph(data) { .style('fill', 'none') .call(d3.zoom() .scaleExtent([1 / 10, 5]) - .on('zoom', this.zoomed)) + .on('zoom', this.zoomed) + ) + .on('click', this.dismiss) - this.container = this.svg.append('g').attr('id', 'container') + this.container = this.svg.append('g') + .attr('id', 'container') this.container.append('g').attr('id', 'links') this.container.append('g').attr('id', 'nodes') @@ -175,7 +178,7 @@ export function MusicGraph(data) { this.makeMenu = function (d) { let items = [] let i = 0 - if ((d.type === 'Group' || d.type === 'Artist')) { + if (d.type === 'Group' || d.type === 'Artist') { items.push({ idx: i++, icon: icons.guitar, @@ -188,6 +191,22 @@ export function MusicGraph(data) { } }) } + if ((d.type === 'Group' || d.type === 'Artist') && + this._data.hoverArtist !== undefined && this._data.hoverArtist.id !== d.id) { + items.push({ + idx: i++, + icon: icons.path, + title: 'Path to here', + fn: (d) => { + this.api.getPath(this._data.hoverArtist.mbid, d.mbid) + .then(data => { + if (data.newNodes.length > 0) { + this.addNodes(data.newNodes, data.relations) + } + }) + } + }) + } if ((d.type === 'Group' || d.type === 'Artist')) { items.push({ idx: i++, @@ -332,6 +351,7 @@ export function MusicGraph(data) { } this.nodeClick = (d) => { + this.dismiss() if (d.type === 'Group' || d.type === 'Artist') { // Toggle artistInfo this.nodes.forEach(x => { @@ -347,45 +367,21 @@ export function MusicGraph(data) { } } - this.addNode = function (newNode, relations) { - // Convert {id, id} relation to {node, node} - if (this.nodeById.has(newNode.id)) { - // Node already exists, select it + this.addNodes = function (newNodes, relations, originId) { + // Update node map, ignore existing nodes + let nodesToAdd = [] + + // If we're adding a single node and it already exists, select it + if (newNodes.length === 1 && this.nodeById.has(newNodes[0].id)) { this.nodes.forEach(x => { x.hover = false }) - this._data.hoverArtist = this.nodeById.get(newNode.id) + this._data.hoverArtist = this.nodeById.get(newNodes[0].id) this._data.hoverArtist.hover = true this._update() return } - this.nodeById.set(newNode.id, newNode) - newNode.x = width / 2 - newNode.y = height / 2 - let linksToAdd = relations - .filter(rel => this.nodeById.has(rel.source) && this.nodeById.has(rel.target)) - .map(({weight, source, target}) => ({ - source: this.nodeById.get(source), - target: this.nodeById.get(target), - weight: weight - })) - - // Update source/targetLinks - for (const {source, target} of linksToAdd) { - source.sourceLinks.add(target.id) - target.targetLinks.add(source.id) - } - - this.nodes.push(newNode) - this.links.push(...linksToAdd) - - this._update() - } - - this.addNodes = function (newNodes, relations, originId) { - // Update node map, ignore existing nodes - let nodesToAdd = [] newNodes.forEach(d => { if (this.nodeById.has(d.id)) { return @@ -403,6 +399,9 @@ export function MusicGraph(data) { centerNode.fx = null centerNode.fy = null }, 600) + } else { + d.x = width / 2 + d.y = height / 2 } nodesToAdd.push(d) @@ -499,7 +498,7 @@ export function MusicGraph(data) { .force('link', d3.forceLink(this.links) .id(d => d.id) .strength(l => l.weight) - .distance(d => (1.12 / d.weight) * 40 * (this.graphSize)) + .distance(d => (1.12 / d.weight) * 30 * (this.graphSize)) ) this.simulation.alphaTarget(0.03).restart() @@ -514,6 +513,7 @@ export function MusicGraph(data) { .append('line') .merge(this.link) .classed('link', true) + .attr('stroke', d => this._getLinkColor(d)) // Add new nodes this.node = this.container.select('#nodes') @@ -597,10 +597,14 @@ export function MusicGraph(data) { return null } + this._getLinkColor = function (node) { + return '#FF0000' + } + this.addArtistByMbid = function (mbid) { this.api.getRelatedByMbid(mbid) .then(data => { - this.addNode(data.node, data.relations) + this.addNodes([data.node], data.relations) }) } @@ -610,7 +614,19 @@ export function MusicGraph(data) { } this.api.getRelatedByTag(tagid) .then(data => { - this.addNode(data.node, data.relations) + // Force tag->artist direction + const relations = data.relations.map(rel => { + if (rel.source === data.node.id) { + return { + weight: rel.weight, + source: rel.target, + target: rel.source + } + } else { + return rel + } + }) + this.addNodes([data.node], relations) }) } diff --git a/music_graph/src/MusicGraphApi.js b/music_graph/src/MusicGraphApi.js index 2b66763..e8b9d11 100644 --- a/music_graph/src/MusicGraphApi.js +++ b/music_graph/src/MusicGraphApi.js @@ -1,5 +1,5 @@ import * as d3 from 'd3' -import {genres} from './genres' +import {isGenreTag} from './genres' const IGNORE_DATES_TAG = true const ONLY_GENRE_TAGS = false @@ -54,6 +54,7 @@ const nodeUtils = { export function MusicGraphApi(data) { this.url = window.location.protocol + '//' + window.location.hostname + '/api' + // this.url = window.location.protocol + '//' + window.location.hostname + ':3030' this._data = data let loadWrapper = (fn) => { @@ -119,7 +120,7 @@ export function MusicGraphApi(data) { this._filterTags = tags => { if (ONLY_GENRE_TAGS) { - return tags.filter(tag => genres.has(tag.name)) + return tags.filter(tag => isGenreTag(tag.name, tag.tagid)) } else if (IGNORE_DATES_TAG) { return tags.filter(tag => isNaN(tag.name) && isNaN(tag.name.slice(0, -1))) } @@ -215,7 +216,7 @@ export function MusicGraphApi(data) { return { source: rel.target, target: rel.source, - weight: rel.weight + weight: Math.min(Math.max(rel.weight * 1.5, 0.2), 1) } }) } @@ -240,6 +241,16 @@ export function MusicGraphApi(data) { }) }) + this.getPath = loadWrapper((idFrom, idTo) => { + return d3.json(this.url + '/artist/path/' + idFrom + '/' + idTo) + .then((r) => { + return { + newNodes: r.artists.map(nodeUtils.fromRawDict), + relations: r.relations + } + }) + }) + this.autoComplete = loadWrapper((prefix) => { prefix = prefix .replace(/[^\w.\-!?& ]/g, '_').toUpperCase() diff --git a/music_graph/src/components/ArtistInfo.vue b/music_graph/src/components/ArtistInfo.vue index 0c63c1e..bc3a1f8 100644 --- a/music_graph/src/components/ArtistInfo.vue +++ b/music_graph/src/components/ArtistInfo.vue @@ -63,7 +63,7 @@