mirror of
https://github.com/simon987/music-graph-ui.git
synced 2025-04-16 16:46:43 +00:00
Add loading indicator
This commit is contained in:
parent
f2760d8f3e
commit
3ab1e90638
@ -1,6 +1,5 @@
|
||||
import * as d3 from 'd3'
|
||||
import icons from './icons'
|
||||
import {MusicGraphApi} from './MusicGraphApi'
|
||||
import {fitCaptionIntoCircle} from './graphGeometry'
|
||||
|
||||
// TODO: export somewhere else
|
||||
@ -22,13 +21,13 @@ export function MusicGraph(data) {
|
||||
const width = window.innerWidth - 7
|
||||
const height = window.innerHeight - 7
|
||||
this._data = data
|
||||
this.api = this._data.api
|
||||
|
||||
this.nodeById = new Map()
|
||||
this.expandedNodes = new Set()
|
||||
this.nodes = []
|
||||
this.links = []
|
||||
this._originSet = false
|
||||
this.api = new MusicGraphApi()
|
||||
|
||||
this.simulation = d3.forceSimulation()
|
||||
.force('charge', d3.forceManyBody())
|
||||
@ -43,7 +42,9 @@ export function MusicGraph(data) {
|
||||
}
|
||||
|
||||
this.dismiss = () => {
|
||||
this.menu.remove()
|
||||
if (this.menu) {
|
||||
this.menu.remove()
|
||||
}
|
||||
const menuNode = this.nodes.find(d => d.menu)
|
||||
if (menuNode !== undefined) {
|
||||
menuNode.menu = null
|
||||
|
@ -52,22 +52,33 @@ const nodeUtils = {
|
||||
}
|
||||
}
|
||||
|
||||
export function MusicGraphApi() {
|
||||
export function MusicGraphApi(data) {
|
||||
this.url = window.location.protocol + '//' + window.location.hostname + '/api'
|
||||
this._data = data
|
||||
|
||||
let loadWrapper = (fn) => {
|
||||
return (...args) => {
|
||||
this._data.loading = true
|
||||
return fn(...args).then(x => {
|
||||
this._data.loading = false
|
||||
return x
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
this.resolveCoverUrl = function (mbid) {
|
||||
return this.url + '/cover/' + mbid
|
||||
}
|
||||
|
||||
this.getArtistDetails = function (mbid) {
|
||||
this.getArtistDetails = loadWrapper((mbid) => {
|
||||
return d3.json(this.url + '/artist/details/' + mbid)
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* Works in both directions
|
||||
* @returns {Promise<{newNodes: *, relations: *} | never>}
|
||||
*/
|
||||
this.getGroupMembers = function (mbid, originId) {
|
||||
this.getGroupMembers = loadWrapper((mbid, originId) => {
|
||||
return d3.json(this.url + '/artist/members/' + mbid)
|
||||
.then((r) => {
|
||||
return {
|
||||
@ -81,29 +92,9 @@ export function MusicGraphApi() {
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
this.getArtistReleases = function (mbid, originId) {
|
||||
return d3.json(this.url + '/artist/details/' + mbid)
|
||||
.then((r) => {
|
||||
const newNodes = r.releases
|
||||
.map(nodeUtils.fromRawDict)
|
||||
.filter(release => release.type === 'Album')
|
||||
|
||||
return {
|
||||
newNodes: newNodes,
|
||||
relations: newNodes.map(t => {
|
||||
return {
|
||||
source: originId,
|
||||
target: t.id,
|
||||
weight: 0.8
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
this.getArtistLabels = function (mbid, originId) {
|
||||
this.getArtistLabels = loadWrapper((mbid, originId) => {
|
||||
return d3.json(this.url + '/artist/details/' + mbid)
|
||||
.then((r) => {
|
||||
const newNodes = r.labels
|
||||
@ -124,25 +115,25 @@ export function MusicGraphApi() {
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
this._filterTags = function (tags) {
|
||||
this._filterTags = loadWrapper((tags) => {
|
||||
if (ONLY_GENRE_TAGS) {
|
||||
return tags.filter(tag => genres.has(tag.name))
|
||||
} else if (IGNORE_DATES_TAG) {
|
||||
return tags.filter(tag => isNaN(tag.name) && isNaN(tag.name.slice(0, -1)))
|
||||
}
|
||||
return tags
|
||||
}
|
||||
})
|
||||
|
||||
this._addTagLabel = function (objects) {
|
||||
this._addTagLabel = loadWrapper((objects) => {
|
||||
return objects.map(tag => {
|
||||
tag.labels = ['Tag']
|
||||
return tag
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
this.getArtistTags = function (mbid, originId) {
|
||||
this.getArtistTags = loadWrapper((mbid, originId) => {
|
||||
return d3.json(this.url + '/artist/details/' + mbid)
|
||||
.then((r) => {
|
||||
const tags = this._filterTags(r.tags)
|
||||
@ -158,9 +149,9 @@ export function MusicGraphApi() {
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
this.getRelatedTags = function (tagId) {
|
||||
this.getRelatedTags = loadWrapper((tagId) => {
|
||||
return d3.json(this.url + '/tag/tag/' + tagId)
|
||||
.then((r) => {
|
||||
const tags = this._filterTags(r.tags)
|
||||
@ -182,9 +173,9 @@ export function MusicGraphApi() {
|
||||
relations: directedRelations
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
this.getRelatedByMbid = function (mbid) {
|
||||
this.getRelatedByMbid = loadWrapper((mbid) => {
|
||||
return d3.json(this.url + '/artist/related/' + mbid)
|
||||
.then((r) => {
|
||||
let node = nodeUtils.fromRawDict(r.artists.find(a => a.mbid === mbid))
|
||||
@ -207,9 +198,9 @@ export function MusicGraphApi() {
|
||||
relations: directedRelations
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
this.getRelatedByTag = function (tagid) {
|
||||
this.getRelatedByTag = loadWrapper((tagid) => {
|
||||
return d3.json(this.url + '/tag/related/' + tagid)
|
||||
.then((r) => {
|
||||
return {
|
||||
@ -229,9 +220,9 @@ export function MusicGraphApi() {
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
this.getReleaseDetails = function (mbid, originId) {
|
||||
this.getReleaseDetails = loadWrapper((mbid, originId) => {
|
||||
return d3.json(this.url + '/release/details/' + mbid)
|
||||
.then((r) => {
|
||||
const tags = this._filterTags(r.tags)
|
||||
@ -247,12 +238,13 @@ export function MusicGraphApi() {
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
this.autoComplete = function (prefix) {
|
||||
prefix = prefix.replace(/[^\w.\-!?& ]/g, '_').toUpperCase()
|
||||
prefix = prefix.replace(/ /g, '+')
|
||||
this.autoComplete = loadWrapper((prefix) => {
|
||||
prefix = prefix
|
||||
.replace(/[^\w.\-!?& ]/g, '_').toUpperCase()
|
||||
.replace(/ /g, '+')
|
||||
|
||||
return d3.json(this.url + '/autocomplete/' + prefix)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -26,14 +26,12 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {MusicGraphApi} from '../MusicGraphApi'
|
||||
|
||||
export default {
|
||||
name: 'AlbumCarousel',
|
||||
props: ['releases', 'interval', 'alone'],
|
||||
props: ['releases', 'interval', 'alone', 'api'],
|
||||
data() {
|
||||
return {
|
||||
api: new MusicGraphApi(),
|
||||
current: '',
|
||||
index: 0
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
<AlbumCarousel
|
||||
style="float: right"
|
||||
:releases="artistInfo.releases"
|
||||
:api="api"
|
||||
interval="1250"/>
|
||||
<div>
|
||||
<p v-if="artistInfo.comment!==null"
|
||||
@ -31,13 +32,12 @@
|
||||
|
||||
<script>
|
||||
import AlbumCarousel from './AlbumCarousel'
|
||||
import {MusicGraphApi} from '../MusicGraphApi'
|
||||
import {genres} from '../genres'
|
||||
|
||||
export default {
|
||||
name: 'ArtistInfo',
|
||||
components: {AlbumCarousel},
|
||||
props: ['artist'],
|
||||
props: ['artist', 'api'],
|
||||
watch: {
|
||||
artist: function (a) {
|
||||
if (a !== undefined) {
|
||||
@ -49,8 +49,7 @@ export default {
|
||||
return {
|
||||
artistInfo: {
|
||||
releases: []
|
||||
},
|
||||
api: new MusicGraphApi()
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
@ -1,13 +1,19 @@
|
||||
<template>
|
||||
<div>
|
||||
<div id="mm"></div>
|
||||
<InputBar v-on:addArtist="onAddArtist($event)" v-on:addTag="onAddTag($event)"></InputBar>
|
||||
<InputBar
|
||||
v-on:addArtist="onAddArtist($event)"
|
||||
v-on:addTag="onAddTag($event)"
|
||||
:api="api"
|
||||
></InputBar>
|
||||
<ArtistInfo
|
||||
v-bind:artist="hoverArtist"
|
||||
v-on:addTag="onAddTag($event)"
|
||||
:api="api"
|
||||
/>
|
||||
<canvas id="textMeasurementCanvas"></canvas>
|
||||
<Watermark text="music-graph v1.0"/>
|
||||
<LoadingIndicator :loading="loading"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -16,14 +22,18 @@ import ArtistInfo from './ArtistInfo'
|
||||
import Watermark from './Watermark'
|
||||
import {MusicGraph} from '../MusicGraph'
|
||||
import InputBar from './InputBar'
|
||||
import LoadingIndicator from './LoadingIndicator'
|
||||
import {MusicGraphApi} from '../MusicGraphApi'
|
||||
|
||||
let data = {
|
||||
hoverArtist: undefined,
|
||||
mm: undefined
|
||||
mm: undefined,
|
||||
api: undefined,
|
||||
loading: undefined
|
||||
}
|
||||
|
||||
export default {
|
||||
components: {InputBar, ArtistInfo, Watermark},
|
||||
components: {LoadingIndicator, InputBar, ArtistInfo, Watermark},
|
||||
data() {
|
||||
return data
|
||||
},
|
||||
@ -36,6 +46,7 @@ export default {
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.api = new MusicGraphApi(data)
|
||||
this.mm = new MusicGraph(data)
|
||||
|
||||
this.$notify({
|
||||
|
@ -20,16 +20,15 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {MusicGraphApi} from '../MusicGraphApi'
|
||||
|
||||
export default {
|
||||
name: 'InputBar',
|
||||
data: () => {
|
||||
return {
|
||||
query: '',
|
||||
api: new MusicGraphApi()
|
||||
query: ''
|
||||
}
|
||||
},
|
||||
props: ['api'],
|
||||
methods: {
|
||||
onSubmit: function (line) {
|
||||
if (line.type === 'artist') {
|
||||
|
26
music_graph/src/components/LoadingIndicator.vue
Normal file
26
music_graph/src/components/LoadingIndicator.vue
Normal file
@ -0,0 +1,26 @@
|
||||
<template>
|
||||
<el-icon class="el-icon-loading" :class="{hidden: !loading}" id="loading"></el-icon>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: 'LoadingIndicator',
|
||||
props: ['loading']
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#loading {
|
||||
position: fixed;
|
||||
top: calc(100% - 90px);
|
||||
left: 75px;
|
||||
pointer-events: none;
|
||||
color: rgba(0, 0, 0, 0.67);
|
||||
font-size: 50px;
|
||||
}
|
||||
</style>
|
Loading…
x
Reference in New Issue
Block a user