mirror of
https://github.com/simon987/music-graph-ui.git
synced 2025-04-19 10:06:42 +00:00
minimum viable UI. CAA-related scripts
This commit is contained in:
parent
85255c5dc1
commit
b588c0eb11
43
README.md
43
README.md
@ -5,3 +5,46 @@
|
|||||||
|
|
||||||
|
|
||||||
wip
|
wip
|
||||||
|
|
||||||
|
### Data import from MusicBrainz & Last.fm
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Download latest database dump
|
||||||
|
./get_musicbrainz_dump.sh
|
||||||
|
|
||||||
|
# Convert to .csv
|
||||||
|
python convert_mb.py
|
||||||
|
|
||||||
|
# Generate scraping tasks for task_tracker_drone (See notes)
|
||||||
|
python generate_scrape_tasks.py
|
||||||
|
|
||||||
|
# Apply last.fm data to artist.csv
|
||||||
|
python patch_artists_with_lastfm.py "/path/to/lasfm_data.db"
|
||||||
|
|
||||||
|
# Expose generated .csv data to the network
|
||||||
|
cd repo/
|
||||||
|
python -m http.server 9999
|
||||||
|
|
||||||
|
# On the machine where neo4j is installed:
|
||||||
|
./import.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### task_tracker setup:
|
||||||
|
|
||||||
|
Last.fm api calls are queued to [task_tracker](https://github.com/simon987/task_tracker/),
|
||||||
|
and results are gathered by a [task_tracker_drone](https://github.com/simon987/task_tracker_drone/)
|
||||||
|
([script](https://git.simon987.net/drone/last.fm/src/master/run)).
|
||||||
|
|
||||||
|
|
||||||
|
Project secret:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"apikey": "<Your Last.fm api key>",
|
||||||
|
"user": "<Your Last.fm username>"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Api setup
|
||||||
|
|
||||||
|
See [music-graph-api](https://github.com/simon987/music-graph-api) for setup instructions.
|
||||||
|
|
||||||
|
@ -11,8 +11,9 @@ wget -nc "http://ftp.musicbrainz.org/pub/musicbrainz/data/fullexport/${latest}/m
|
|||||||
tar -xjvf mbdump.tar.bz2 mbdump/area mbdump/artist mbdump/l_area_area mbdump/l_artist_artist \
|
tar -xjvf mbdump.tar.bz2 mbdump/area mbdump/artist mbdump/l_area_area mbdump/l_artist_artist \
|
||||||
mbdump/l_artist_release mbdump/l_artist_release_group mbdump/l_label_label mbdump/l_release_group_release_group \
|
mbdump/l_artist_release mbdump/l_artist_release_group mbdump/l_label_label mbdump/l_release_group_release_group \
|
||||||
mbdump/label mbdump/label_type mbdump/link mbdump/link_type mbdump/release mbdump/release_group \
|
mbdump/label mbdump/label_type mbdump/link mbdump/link_type mbdump/release mbdump/release_group \
|
||||||
mbdump/release_group_primary_type
|
mbdump/release_group_primary_type mbdump/artist_credit_name mbdump/release_status
|
||||||
tar -xjvf mbdump-derived.tar.bz2 mbdump/artist_tag mbdump/release_group_tag mbdump/tag mbdump/tag_relation
|
tar -xjvf mbdump-derived.tar.bz2 mbdump/artist_tag mbdump/release_group_tag mbdump/tag mbdump/tag_relation \
|
||||||
|
mbdump/release_group_meta
|
||||||
|
|
||||||
mv mbdump/* .
|
mv mbdump/* .
|
||||||
rm -r mbdump
|
rm -r mbdump
|
27
extract_covers.py
Normal file
27
extract_covers.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import sqlite3
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
with sqlite3.connect(sys.argv[1]) as conn:
|
||||||
|
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute("SELECT id from covers")
|
||||||
|
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute("SELECT id from covers")
|
||||||
|
|
||||||
|
def rows():
|
||||||
|
buf = list()
|
||||||
|
for row in cursor.fetchall():
|
||||||
|
buf.append(row[0])
|
||||||
|
if len(buf) > 30:
|
||||||
|
yield buf
|
||||||
|
buf.clear()
|
||||||
|
|
||||||
|
for batch in rows():
|
||||||
|
cursor.execute("SELECT cover from covers where id in (%s)" % (",".join(("'" + b + "'") for b in batch)))
|
||||||
|
covers = cursor.fetchall()
|
||||||
|
for i, cover in enumerate(covers):
|
||||||
|
with open("./tmpcovers/" + batch[i] + ".jpg", "wb") as out:
|
||||||
|
out.write(cover[0])
|
||||||
|
print(batch[i])
|
56
generate_caa_tasks.py
Normal file
56
generate_caa_tasks.py
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import json
|
||||||
|
from multiprocessing.pool import ThreadPool
|
||||||
|
|
||||||
|
from task_tracker_drone.src.tt_drone.api import TaskTrackerApi, Worker
|
||||||
|
|
||||||
|
TT_API_URL = "https://tt.simon987.net/api"
|
||||||
|
TT_PROJECT = 5
|
||||||
|
|
||||||
|
|
||||||
|
done = set()
|
||||||
|
# with sqlite3.connect(sys.argv[1]) as conn:
|
||||||
|
# cur = conn.cursor()
|
||||||
|
# cur.execute("SELECT id FROM covers")
|
||||||
|
# for mbid in cur.fetchall():
|
||||||
|
# done.add(mbid[0])
|
||||||
|
|
||||||
|
api = TaskTrackerApi(TT_API_URL)
|
||||||
|
|
||||||
|
worker = Worker.from_file(api)
|
||||||
|
if not worker:
|
||||||
|
worker = api.make_worker("caa scraper")
|
||||||
|
worker.dump_to_file()
|
||||||
|
worker.request_access(TT_PROJECT, True, True)
|
||||||
|
input("Give permission to " + worker.alias)
|
||||||
|
|
||||||
|
|
||||||
|
def mktask(mbids):
|
||||||
|
res = worker.submit_task(
|
||||||
|
project=TT_PROJECT,
|
||||||
|
recipe=json.dumps(mbids),
|
||||||
|
hash64=hash(mbids[0]),
|
||||||
|
max_assign_time=60 * 30,
|
||||||
|
priority=1,
|
||||||
|
unique_str=None,
|
||||||
|
verification_count=None,
|
||||||
|
max_retries=5,
|
||||||
|
)
|
||||||
|
print(res.text)
|
||||||
|
|
||||||
|
|
||||||
|
def lines():
|
||||||
|
with open("in/release") as f:
|
||||||
|
buf = list()
|
||||||
|
|
||||||
|
for line in f:
|
||||||
|
cols = line.split("\t")
|
||||||
|
|
||||||
|
buf.append(cols[1])
|
||||||
|
if len(buf) == 75:
|
||||||
|
a = list(buf)
|
||||||
|
buf.clear()
|
||||||
|
yield a
|
||||||
|
|
||||||
|
|
||||||
|
pool = ThreadPool(processes=20)
|
||||||
|
pool.map(func=mktask, iterable=lines())
|
48
generate_lastfm_tasks.py
Normal file
48
generate_lastfm_tasks.py
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import csv
|
||||||
|
import json
|
||||||
|
from multiprocessing.pool import ThreadPool
|
||||||
|
|
||||||
|
from task_tracker_drone.src.tt_drone.api import TaskTrackerApi, Worker
|
||||||
|
|
||||||
|
TT_API_URL = "https://tt.simon987.net/api"
|
||||||
|
TT_PROJECT = 1
|
||||||
|
|
||||||
|
api = TaskTrackerApi(TT_API_URL)
|
||||||
|
|
||||||
|
worker = Worker.from_file(api)
|
||||||
|
if not worker:
|
||||||
|
worker = api.make_worker("last.fm scraper")
|
||||||
|
worker.dump_to_file()
|
||||||
|
worker.request_access(TT_PROJECT, True, True)
|
||||||
|
input("Give permission to " + worker.alias)
|
||||||
|
|
||||||
|
with open("repo/artist.csv") as f:
|
||||||
|
reader = csv.reader(f)
|
||||||
|
|
||||||
|
def mktask(lines):
|
||||||
|
res = worker.submit_task(
|
||||||
|
project=TT_PROJECT,
|
||||||
|
recipe=json.dumps(
|
||||||
|
[{"mbid": line[0], "name": line[1]} for line in lines]
|
||||||
|
),
|
||||||
|
unique_str=lines[0][0],
|
||||||
|
max_assign_time=60 * 5,
|
||||||
|
)
|
||||||
|
print(res.text)
|
||||||
|
|
||||||
|
def lines():
|
||||||
|
line_batch = list()
|
||||||
|
|
||||||
|
for line in reader:
|
||||||
|
if "Group" in line[3]:
|
||||||
|
line_batch.append(line)
|
||||||
|
if len(line_batch) >= 30:
|
||||||
|
res = list(line_batch)
|
||||||
|
line_batch.clear()
|
||||||
|
yield res
|
||||||
|
|
||||||
|
tasks = list(lines())
|
||||||
|
|
||||||
|
pool = ThreadPool(processes=25)
|
||||||
|
pool.map(func=mktask, iterable=tasks)
|
||||||
|
|
@ -1,39 +0,0 @@
|
|||||||
import csv
|
|
||||||
import json
|
|
||||||
from multiprocessing.pool import ThreadPool
|
|
||||||
|
|
||||||
from task_tracker_drone.src.tt_drone.api import TaskTrackerApi, Worker
|
|
||||||
|
|
||||||
TT_API_URL = "https://tt.simon987.net/api"
|
|
||||||
TT_PROJECT = 1
|
|
||||||
|
|
||||||
api = TaskTrackerApi(TT_API_URL)
|
|
||||||
|
|
||||||
worker = Worker.from_file(api)
|
|
||||||
if not worker:
|
|
||||||
worker = api.make_worker("last.fm scraper")
|
|
||||||
worker.dump_to_file()
|
|
||||||
worker.request_access(TT_PROJECT, True, True)
|
|
||||||
|
|
||||||
input("Give permission to " + worker.alias)
|
|
||||||
|
|
||||||
with open("repo/artist.csv") as f:
|
|
||||||
reader = csv.reader(f)
|
|
||||||
|
|
||||||
def mktask(line):
|
|
||||||
res = worker.submit_task(
|
|
||||||
project=TT_PROJECT,
|
|
||||||
recipe=json.dumps({"mbid": line[0], "name": line[1]}),
|
|
||||||
unique_str=line[0],
|
|
||||||
max_assign_time=60 * 5,
|
|
||||||
)
|
|
||||||
print(res.text)
|
|
||||||
|
|
||||||
def lines():
|
|
||||||
for line in reader:
|
|
||||||
if "Group" in line[2]:
|
|
||||||
yield line
|
|
||||||
|
|
||||||
pool = ThreadPool(processes=60)
|
|
||||||
pool.map(func=mktask, iterable=lines())
|
|
||||||
|
|
@ -1 +1,4 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
git submodule init
|
||||||
|
git submodule update --remote
|
2
last.fm
2
last.fm
@ -1 +1 @@
|
|||||||
Subproject commit da0874207e2e214ee72be818233e2bf2d30ded19
|
Subproject commit 855df64c316930062ff4f7740492d0f039788498
|
@ -6,8 +6,12 @@ export DATABASE="graph.db"
|
|||||||
|
|
||||||
rm -rf "${NEO4J_HOME}/data/databases/${DATABASE}"
|
rm -rf "${NEO4J_HOME}/data/databases/${DATABASE}"
|
||||||
|
|
||||||
|
cp ${NEO4J_HOME}/conf/neo4j.conf ${NEO4J_HOME}/conf/neo4j.conf.bak
|
||||||
|
echo "dbms.security.auth_enabled=false" >> ${NEO4J_HOME}/conf/neo4j.conf
|
||||||
|
|
||||||
mkdir workspace 2> /dev/null
|
mkdir workspace 2> /dev/null
|
||||||
cd workspace
|
cd workspace
|
||||||
|
rm *.csv
|
||||||
|
|
||||||
wget ${REPOSITORY}/area.csv
|
wget ${REPOSITORY}/area.csv
|
||||||
wget ${REPOSITORY}/area_area.csv
|
wget ${REPOSITORY}/area_area.csv
|
31
make_release_to_rg_map.py
Normal file
31
make_release_to_rg_map.py
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import sqlite3
|
||||||
|
|
||||||
|
release_to_release_group_map = dict()
|
||||||
|
release_groups = dict()
|
||||||
|
|
||||||
|
with open("in/release_group") as f:
|
||||||
|
for line in f:
|
||||||
|
cols = line.split("\t")
|
||||||
|
release_groups[cols[0]] = cols[1]
|
||||||
|
|
||||||
|
with open("in/release") as f:
|
||||||
|
for line in f:
|
||||||
|
cols = line.split("\t")
|
||||||
|
release_to_release_group_map[cols[1]] = release_groups[cols[4]]
|
||||||
|
|
||||||
|
with sqlite3.connect("mapdb.db") as conn:
|
||||||
|
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute("CREATE TABLE map (release TEXT PRIMARY KEY , release_group TEXT)")
|
||||||
|
|
||||||
|
for k, v in release_to_release_group_map.items():
|
||||||
|
cursor.execute("INSERT INTO map (release, release_group) VALUES (?,?)", (k, v))
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
|
"""
|
||||||
|
CREATE TABLE covers (id TEXT primary key, cover BLOB);
|
||||||
|
ATTACH 'mapdb.db' AS map;
|
||||||
|
ATTACH '/mnt/Data8/caa_tn_only.db' AS source;
|
||||||
|
INSERT OR IGNORE INTO covers SELECT release_group, cover FROM source.covers INNER JOIN map.map ON id = map.release;
|
||||||
|
"""
|
||||||
|
|
@ -1,74 +0,0 @@
|
|||||||
import csv
|
|
||||||
import json
|
|
||||||
import sqlite3
|
|
||||||
import sys
|
|
||||||
|
|
||||||
|
|
||||||
def patch(lastfm_data):
|
|
||||||
with sqlite3.connect(lastfm_data) as conn:
|
|
||||||
cur = conn.cursor()
|
|
||||||
|
|
||||||
cur.execute("SELECT data FROM lastfmdata", )
|
|
||||||
data = cur.fetchall()
|
|
||||||
|
|
||||||
if data:
|
|
||||||
|
|
||||||
buffer = []
|
|
||||||
dup_buf = set()
|
|
||||||
artist_listeners = dict()
|
|
||||||
artists = set()
|
|
||||||
|
|
||||||
for row in data:
|
|
||||||
lastfm_data = json.loads(row[0])
|
|
||||||
|
|
||||||
for similar in [s for s in lastfm_data["similar"] if s["mbid"] is not None]:
|
|
||||||
if (similar["mbid"], lastfm_data["artist"]) not in dup_buf:
|
|
||||||
buffer.append((
|
|
||||||
similar["mbid"],
|
|
||||||
lastfm_data["artist"],
|
|
||||||
similar["match"]
|
|
||||||
))
|
|
||||||
dup_buf.add((similar["mbid"], lastfm_data["artist"]))
|
|
||||||
dup_buf.add((lastfm_data["artist"], similar["mbid"]))
|
|
||||||
|
|
||||||
artist_listeners[lastfm_data["artist"]] = (lastfm_data["listeners"], lastfm_data["playcount"])
|
|
||||||
|
|
||||||
del dup_buf
|
|
||||||
|
|
||||||
with open("repo/lastfm_artist.csv", "w") as out:
|
|
||||||
|
|
||||||
writer = csv.writer(out)
|
|
||||||
writer.writerow([
|
|
||||||
"id:ID(Artist)", "name", ":LABEL", "listeners:int", "playcount:int"
|
|
||||||
])
|
|
||||||
|
|
||||||
with open("repo/artist.csv") as f:
|
|
||||||
reader = csv.reader(f)
|
|
||||||
|
|
||||||
reader.__next__() # Skip header
|
|
||||||
for row in reader:
|
|
||||||
writer.writerow([
|
|
||||||
row[0],
|
|
||||||
row[1],
|
|
||||||
row[2],
|
|
||||||
row[3],
|
|
||||||
artist_listeners.get(row[0], (0, 0))[0],
|
|
||||||
artist_listeners.get(row[0], (0, 0))[1],
|
|
||||||
])
|
|
||||||
artists.add(row[0])
|
|
||||||
|
|
||||||
with open("repo/lastfm_artist_artist.csv", "w") as out:
|
|
||||||
out.write(",".join((
|
|
||||||
":START_ID(Artist)", ":END_ID(Artist)", "weight"
|
|
||||||
)) + "\n")
|
|
||||||
|
|
||||||
for x in buffer:
|
|
||||||
if x[0] not in artists:
|
|
||||||
continue
|
|
||||||
if x[1] not in artists:
|
|
||||||
continue
|
|
||||||
|
|
||||||
out.write(",".join(x) + "\n")
|
|
||||||
|
|
||||||
|
|
||||||
patch(sys.argv[1])
|
|
100
process_lastfm_data.py
Normal file
100
process_lastfm_data.py
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
import csv
|
||||||
|
import json
|
||||||
|
import sqlite3
|
||||||
|
from collections import defaultdict
|
||||||
|
import sys
|
||||||
|
|
||||||
|
artists = set()
|
||||||
|
|
||||||
|
|
||||||
|
def disambiguate(lfm_artist, artist_release_count, name, mbid):
|
||||||
|
existing_mbid = lfm_artist.get(name, None)
|
||||||
|
|
||||||
|
if existing_mbid and mbid != existing_mbid:
|
||||||
|
if artist_release_count[existing_mbid] < artist_release_count[mbid]:
|
||||||
|
|
||||||
|
lfm_artist[name] = mbid
|
||||||
|
|
||||||
|
print("Replacing %s (%s) with %s (%d) for %s" %
|
||||||
|
(existing_mbid, artist_release_count[existing_mbid],
|
||||||
|
mbid, artist_release_count[mbid],
|
||||||
|
name))
|
||||||
|
else:
|
||||||
|
lfm_artist[name] = mbid
|
||||||
|
|
||||||
|
|
||||||
|
def patch(lastfm_data):
|
||||||
|
|
||||||
|
artist_listeners = dict()
|
||||||
|
lastfm_artist_to_mbid = dict()
|
||||||
|
artist_release_count = defaultdict(int)
|
||||||
|
related = list()
|
||||||
|
|
||||||
|
with open("repo/artist_release.csv") as f:
|
||||||
|
for line in f:
|
||||||
|
cols = line.split(',')
|
||||||
|
artist_release_count[cols[0]] += 1
|
||||||
|
|
||||||
|
with sqlite3.connect(lastfm_data) as conn:
|
||||||
|
cur = conn.cursor()
|
||||||
|
cur.execute("SELECT data FROM lastfmdata", )
|
||||||
|
data = list(cur.fetchall())
|
||||||
|
|
||||||
|
# A lastfm artist name can refer to multiple MBIDs
|
||||||
|
# For RELATED_TO purposes, we assume that the MBID referring
|
||||||
|
# to the artist with the most official releases is the one
|
||||||
|
|
||||||
|
for row in data:
|
||||||
|
meta = json.loads(row[0])
|
||||||
|
|
||||||
|
disambiguate(lastfm_artist_to_mbid, artist_release_count, meta["name"], meta["artist"])
|
||||||
|
|
||||||
|
for similar in [s for s in meta["similar"] if s["mbid"] is not None]:
|
||||||
|
disambiguate(lastfm_artist_to_mbid, artist_release_count, similar["name"], similar["mbid"])
|
||||||
|
|
||||||
|
# Get related links & listener counts
|
||||||
|
for row in data:
|
||||||
|
meta = json.loads(row[0])
|
||||||
|
|
||||||
|
artist_listeners[lastfm_artist_to_mbid[meta["name"]]] = \
|
||||||
|
(meta["listeners"], meta["playcount"])
|
||||||
|
|
||||||
|
for similar in [s for s in meta["similar"] if s["mbid"] is not None]:
|
||||||
|
related.append((
|
||||||
|
lastfm_artist_to_mbid[similar["name"]],
|
||||||
|
lastfm_artist_to_mbid[meta["name"]],
|
||||||
|
similar["match"]
|
||||||
|
))
|
||||||
|
|
||||||
|
with open("repo/lastfm_artist.csv", "w") as out:
|
||||||
|
writer = csv.writer(out)
|
||||||
|
writer.writerow([
|
||||||
|
"id:ID(Artist)", "name", "year:short", ":LABEL", "listeners:int", "playcount:int"
|
||||||
|
])
|
||||||
|
|
||||||
|
with open("repo/artist.csv") as f:
|
||||||
|
reader = csv.reader(f)
|
||||||
|
|
||||||
|
reader.__next__() # Skip header
|
||||||
|
for row in reader:
|
||||||
|
writer.writerow([
|
||||||
|
row[0],
|
||||||
|
row[1],
|
||||||
|
row[2],
|
||||||
|
row[3],
|
||||||
|
artist_listeners.get(row[0], (0, 0))[0],
|
||||||
|
artist_listeners.get(row[0], (0, 0))[1],
|
||||||
|
])
|
||||||
|
artists.add(row[0])
|
||||||
|
|
||||||
|
with open("repo/lastfm_artist_artist.csv", "w") as out:
|
||||||
|
out.write(",".join((
|
||||||
|
":START_ID(Artist)", ":END_ID(Artist)", "weight:float"
|
||||||
|
)) + "\n")
|
||||||
|
|
||||||
|
for x in related:
|
||||||
|
if x[0] in artists and x[1] in artists:
|
||||||
|
out.write(",".join(x) + "\n")
|
||||||
|
|
||||||
|
|
||||||
|
patch(sys.argv[1])
|
@ -1,4 +1,5 @@
|
|||||||
import os
|
import os
|
||||||
|
from collections import defaultdict
|
||||||
|
|
||||||
links = dict()
|
links = dict()
|
||||||
link_types = dict()
|
link_types = dict()
|
||||||
@ -8,6 +9,7 @@ label_types = {
|
|||||||
"\\N": ""
|
"\\N": ""
|
||||||
}
|
}
|
||||||
release_groups = dict()
|
release_groups = dict()
|
||||||
|
release_statuses = dict()
|
||||||
release_to_release_group_map = dict()
|
release_to_release_group_map = dict()
|
||||||
release_types = {
|
release_types = {
|
||||||
"\\N": "",
|
"\\N": "",
|
||||||
@ -107,6 +109,7 @@ artist_artist_rel_map = {
|
|||||||
"subgroup": "IS_SUBGROUP_OF",
|
"subgroup": "IS_SUBGROUP_OF",
|
||||||
"founder": "IS_FOUNDER_OF",
|
"founder": "IS_FOUNDER_OF",
|
||||||
"involved with": "IS_INVOLVED_WITH",
|
"involved with": "IS_INVOLVED_WITH",
|
||||||
|
"named after": "IS_NAMED_AFTER",
|
||||||
}
|
}
|
||||||
|
|
||||||
label_label_rel_map = {
|
label_label_rel_map = {
|
||||||
@ -132,6 +135,11 @@ with open("in/link", "r") as f:
|
|||||||
cols = line.split("\t")
|
cols = line.split("\t")
|
||||||
links[cols[0]] = cols
|
links[cols[0]] = cols
|
||||||
|
|
||||||
|
with open("in/release_status", "r") as f:
|
||||||
|
for line in f:
|
||||||
|
cols = line.split("\t")
|
||||||
|
release_statuses[cols[0]] = cols
|
||||||
|
|
||||||
with open("in/link_type", "r") as f:
|
with open("in/link_type", "r") as f:
|
||||||
for line in f:
|
for line in f:
|
||||||
cols = line.split("\t")
|
cols = line.split("\t")
|
||||||
@ -187,7 +195,7 @@ for _, artist in artists.items():
|
|||||||
out_artist.write(",".join((
|
out_artist.write(",".join((
|
||||||
artist[1],
|
artist[1],
|
||||||
'"' + artist[2].replace("\"", "\"\"") + '"',
|
'"' + artist[2].replace("\"", "\"\"") + '"',
|
||||||
artist[4] if artist[4] != "\\N" else "",
|
artist[4] if artist[4] != "\\N" else "0",
|
||||||
"Artist" + (";Group\n" if artist[10] == "2" else "\n")
|
"Artist" + (";Group\n" if artist[10] == "2" else "\n")
|
||||||
)))
|
)))
|
||||||
|
|
||||||
@ -216,8 +224,14 @@ with open("in/release_group_primary_type") as f:
|
|||||||
cols = line.split("\t")
|
cols = line.split("\t")
|
||||||
release_types[cols[0]] = ";" + cols[1]
|
release_types[cols[0]] = ";" + cols[1]
|
||||||
|
|
||||||
|
release_group_year = dict()
|
||||||
|
with open("in/release_group_meta") as f:
|
||||||
|
for line in f:
|
||||||
|
cols = line.split("\t")
|
||||||
|
release_group_year[cols[0]] = cols[2] if cols[2] != "\\N" else "0"
|
||||||
|
|
||||||
with open("repo/release.csv", "w") as out:
|
with open("repo/release.csv", "w") as out:
|
||||||
out.write("id:ID(Release),name,:LABEL\n")
|
out.write("id:ID(Release),name,year:int,:LABEL\n")
|
||||||
|
|
||||||
with open("in/release_group") as f:
|
with open("in/release_group") as f:
|
||||||
for line in f:
|
for line in f:
|
||||||
@ -225,6 +239,7 @@ with open("repo/release.csv", "w") as out:
|
|||||||
out.write(",".join((
|
out.write(",".join((
|
||||||
cols[1],
|
cols[1],
|
||||||
'"' + cols[2].replace("\"", "\"\"") + '"',
|
'"' + cols[2].replace("\"", "\"\"") + '"',
|
||||||
|
release_group_year[cols[0]],
|
||||||
"Release" + release_types[cols[4]],
|
"Release" + release_types[cols[4]],
|
||||||
)) + "\n")
|
)) + "\n")
|
||||||
|
|
||||||
@ -233,20 +248,47 @@ with open("repo/release.csv", "w") as out:
|
|||||||
with open("in/release") as f:
|
with open("in/release") as f:
|
||||||
for line in f:
|
for line in f:
|
||||||
cols = line.split("\t")
|
cols = line.split("\t")
|
||||||
|
if cols[5] != '\\N' and release_statuses[cols[5]][1] == "Official":
|
||||||
release_to_release_group_map[cols[0]] = cols[4]
|
release_to_release_group_map[cols[0]] = cols[4]
|
||||||
|
|
||||||
|
credit_names = defaultdict(list)
|
||||||
|
|
||||||
|
with open("in/artist_credit_name") as f:
|
||||||
|
for line in f:
|
||||||
|
cols = line.split("\t")
|
||||||
|
credit_names[cols[0]].append(artists[cols[2]][1])
|
||||||
|
|
||||||
with open("tmp/tmp_artist_release.csv", "w") as out:
|
with open("tmp/tmp_artist_release.csv", "w") as out:
|
||||||
out.write(":START_ID(Artist),:END_ID(Release),:TYPE\n")
|
out.write(":START_ID(Artist),:END_ID(Release),:TYPE\n")
|
||||||
|
|
||||||
|
# Is this part really necessary?
|
||||||
with open("in/l_artist_release") as f:
|
with open("in/l_artist_release") as f:
|
||||||
for line in f:
|
for line in f:
|
||||||
cols = line.split("\t")
|
cols = line.split("\t")
|
||||||
|
if cols[3] in release_to_release_group_map:
|
||||||
out.write(",".join((
|
out.write(",".join((
|
||||||
artists[cols[2]][1],
|
artists[cols[2]][1],
|
||||||
release_groups[release_to_release_group_map[cols[3]]][1],
|
release_groups[release_to_release_group_map[cols[3]]][1],
|
||||||
artist_release_rel_map[link_types[links[cols[1]][1]][6]]
|
artist_release_rel_map[link_types[links[cols[1]][1]][6]]
|
||||||
)) + "\n")
|
)) + "\n")
|
||||||
|
|
||||||
|
# Artist credits
|
||||||
|
with open("in/release") as f:
|
||||||
|
for line in f:
|
||||||
|
cols = line.split("\t")
|
||||||
|
if cols[0] in release_to_release_group_map:
|
||||||
|
for credit in credit_names[cols[3]]:
|
||||||
|
out.write(",".join((
|
||||||
|
credit,
|
||||||
|
release_groups[release_to_release_group_map[cols[0]]][1],
|
||||||
|
"CREDITED_FOR"
|
||||||
|
)) + "\n")
|
||||||
|
|
||||||
|
# Remove dupes
|
||||||
|
os.system("(head -n 1 tmp/tmp_artist_release.csv && tail -n +2 tmp/tmp_artist_release.csv"
|
||||||
|
" | sort) | uniq > repo/artist_release.csv && rm tmp/tmp_artist_release.csv")
|
||||||
|
|
||||||
|
|
||||||
with open("repo/release_release.csv", "w") as out:
|
with open("repo/release_release.csv", "w") as out:
|
||||||
out.write(":START_ID(Release),:END_ID(Release),:TYPE\n")
|
out.write(":START_ID(Release),:END_ID(Release),:TYPE\n")
|
||||||
|
|
||||||
@ -259,12 +301,8 @@ with open("repo/release_release.csv", "w") as out:
|
|||||||
release_release_rel_map[link_types[links[cols[1]][1]][6]]
|
release_release_rel_map[link_types[links[cols[1]][1]][6]]
|
||||||
)) + "\n")
|
)) + "\n")
|
||||||
|
|
||||||
os.system("(head -n 1 tmp/tmp_artist_release.csv && tail -n +2 tmp/tmp_artist_release.csv"
|
|
||||||
" | sort) | uniq > repo/artist_release.csv && rm tmp/tmp_artist_release.csv")
|
|
||||||
|
|
||||||
# ---
|
# ---
|
||||||
|
|
||||||
|
|
||||||
with open("in/tag") as f:
|
with open("in/tag") as f:
|
||||||
with open("repo/tag.csv", "w") as out:
|
with open("repo/tag.csv", "w") as out:
|
||||||
out.write("id:ID(Tag),name\n")
|
out.write("id:ID(Tag),name\n")
|
||||||
@ -307,7 +345,7 @@ with open("repo/artist_tag.csv", "w") as out:
|
|||||||
)) + "\n")
|
)) + "\n")
|
||||||
|
|
||||||
with open("repo/tag_tag.csv", "w") as out:
|
with open("repo/tag_tag.csv", "w") as out:
|
||||||
out.write(":START_ID(Tag),:END_ID(Tag),weight\n")
|
out.write(":START_ID(Tag),:END_ID(Tag),weight:int\n")
|
||||||
|
|
||||||
with open("in/tag_relation") as f:
|
with open("in/tag_relation") as f:
|
||||||
for line in f:
|
for line in f:
|
2
seed.cypher
Normal file
2
seed.cypher
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
CREATE INDEX ON :Artist(id);
|
||||||
|
CREATE INDEX ON :Release(id);
|
5
seed_neo4j_db.sh
Executable file
5
seed_neo4j_db.sh
Executable file
@ -0,0 +1,5 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
export NEO4J_HOME="/home/drone/Downloads/neo4j-community-3.5.3"
|
||||||
|
|
||||||
|
cat seed.cypher | ${NEO4J_HOME}/bin/cypher-shell
|
@ -1 +1 @@
|
|||||||
Subproject commit 69af3ba908c3c3e1c838da3e95ff15f967086af0
|
Subproject commit e025596cf2ccfbe803f05cb848927ae36fe270a3
|
@ -25,10 +25,10 @@ module.exports = {
|
|||||||
'generator-star-spacing': 'off',
|
'generator-star-spacing': 'off',
|
||||||
// allow debugger during development
|
// allow debugger during development
|
||||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
||||||
|
"indent": ["error", 4, {SwitchCase: 1}],
|
||||||
"indent": "off",
|
|
||||||
"indent-legacy": ["error", 4],
|
|
||||||
"no-param-reassign": 0,
|
"no-param-reassign": 0,
|
||||||
"no-underscore-dangle": 0,
|
"no-underscore-dangle": 0,
|
||||||
|
"no-trailing-spaces": 0,
|
||||||
|
"space-before-function-paren": 0,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
363
ui/package-lock.json
generated
363
ui/package-lock.json
generated
@ -60,6 +60,35 @@
|
|||||||
"@babel/types": "7.0.0-beta.44"
|
"@babel/types": "7.0.0-beta.44"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@babel/helper-module-imports": {
|
||||||
|
"version": "7.0.0-beta.35",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0-beta.35.tgz",
|
||||||
|
"integrity": "sha512-vaC1KyIZSuyWb3Lj277fX0pxivyHwuDU4xZsofqgYAbkDxNieMg2vuhzP5AgMweMY7fCQUMTi+BgPqTLjkxXFg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@babel/types": "7.0.0-beta.35",
|
||||||
|
"lodash": "^4.2.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/types": {
|
||||||
|
"version": "7.0.0-beta.35",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.35.tgz",
|
||||||
|
"integrity": "sha512-y9XT11CozHDgjWcTdxmhSj13rJVXpa5ZXwjjOiTedjaM0ba5ItqdS02t31EhPl7HtOWxsZkYCCUNrSfrOisA6w==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"esutils": "^2.0.2",
|
||||||
|
"lodash": "^4.2.0",
|
||||||
|
"to-fast-properties": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"to-fast-properties": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
|
||||||
|
"integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"@babel/helper-split-export-declaration": {
|
"@babel/helper-split-export-declaration": {
|
||||||
"version": "7.0.0-beta.44",
|
"version": "7.0.0-beta.44",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.44.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.44.tgz",
|
||||||
@ -166,6 +195,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@sindresorhus/is": {
|
||||||
|
"version": "0.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz",
|
||||||
|
"integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow=="
|
||||||
|
},
|
||||||
"accepts": {
|
"accepts": {
|
||||||
"version": "1.3.5",
|
"version": "1.3.5",
|
||||||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz",
|
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz",
|
||||||
@ -439,6 +473,14 @@
|
|||||||
"integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==",
|
"integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"async-validator": {
|
||||||
|
"version": "1.8.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/async-validator/-/async-validator-1.8.5.tgz",
|
||||||
|
"integrity": "sha512-tXBM+1m056MAX0E8TL2iCjg8WvSyXu0Zc8LNtYqrVeyoL3+esHRZ4SieE9fKQyyU09uONjnMEjrNBMqT0mbvmA==",
|
||||||
|
"requires": {
|
||||||
|
"babel-runtime": "6.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
"atob": {
|
"atob": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
|
||||||
@ -731,8 +773,7 @@
|
|||||||
"babel-helper-vue-jsx-merge-props": {
|
"babel-helper-vue-jsx-merge-props": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-2.0.3.tgz",
|
||||||
"integrity": "sha512-gsLiKK7Qrb7zYJNgiXKpXblxbV5ffSwR0f5whkPAaBAR4fhi6bwRZxX9wBlIc5M/v8CCkXUbXZL4N/nSE97cqg==",
|
"integrity": "sha512-gsLiKK7Qrb7zYJNgiXKpXblxbV5ffSwR0f5whkPAaBAR4fhi6bwRZxX9wBlIc5M/v8CCkXUbXZL4N/nSE97cqg=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"babel-helpers": {
|
"babel-helpers": {
|
||||||
"version": "6.24.1",
|
"version": "6.24.1",
|
||||||
@ -773,6 +814,15 @@
|
|||||||
"babel-runtime": "^6.22.0"
|
"babel-runtime": "^6.22.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"babel-plugin-component": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/babel-plugin-component/-/babel-plugin-component-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-WUw887kJf2GH80Ng/ZMctKZ511iamHNqPhd9uKo14yzisvV7Wt1EckIrb8oq/uCz3B3PpAW7Xfl7AkTLDYT6ag==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@babel/helper-module-imports": "7.0.0-beta.35"
|
||||||
|
}
|
||||||
|
},
|
||||||
"babel-plugin-syntax-async-functions": {
|
"babel-plugin-syntax-async-functions": {
|
||||||
"version": "6.13.0",
|
"version": "6.13.0",
|
||||||
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz",
|
||||||
@ -1260,7 +1310,6 @@
|
|||||||
"version": "6.26.0",
|
"version": "6.26.0",
|
||||||
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
|
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
|
||||||
"integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
|
"integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"core-js": "^2.4.0",
|
"core-js": "^2.4.0",
|
||||||
"regenerator-runtime": "^0.11.0"
|
"regenerator-runtime": "^0.11.0"
|
||||||
@ -1690,6 +1739,60 @@
|
|||||||
"unset-value": "^1.0.0"
|
"unset-value": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"cacheable-request": {
|
||||||
|
"version": "2.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz",
|
||||||
|
"integrity": "sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0=",
|
||||||
|
"requires": {
|
||||||
|
"clone-response": "1.0.2",
|
||||||
|
"get-stream": "3.0.0",
|
||||||
|
"http-cache-semantics": "3.8.1",
|
||||||
|
"keyv": "3.0.0",
|
||||||
|
"lowercase-keys": "1.0.0",
|
||||||
|
"normalize-url": "2.0.1",
|
||||||
|
"responselike": "1.0.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"lowercase-keys": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY="
|
||||||
|
},
|
||||||
|
"normalize-url": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==",
|
||||||
|
"requires": {
|
||||||
|
"prepend-http": "^2.0.0",
|
||||||
|
"query-string": "^5.0.1",
|
||||||
|
"sort-keys": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"prepend-http": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz",
|
||||||
|
"integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc="
|
||||||
|
},
|
||||||
|
"query-string": {
|
||||||
|
"version": "5.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz",
|
||||||
|
"integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==",
|
||||||
|
"requires": {
|
||||||
|
"decode-uri-component": "^0.2.0",
|
||||||
|
"object-assign": "^4.1.0",
|
||||||
|
"strict-uri-encode": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sort-keys": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz",
|
||||||
|
"integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=",
|
||||||
|
"requires": {
|
||||||
|
"is-plain-obj": "^1.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"caller-path": {
|
"caller-path": {
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz",
|
||||||
@ -1964,6 +2067,14 @@
|
|||||||
"integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=",
|
"integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"clone-response": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz",
|
||||||
|
"integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=",
|
||||||
|
"requires": {
|
||||||
|
"mimic-response": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"co": {
|
"co": {
|
||||||
"version": "4.6.0",
|
"version": "4.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
|
||||||
@ -2220,14 +2331,12 @@
|
|||||||
"core-js": {
|
"core-js": {
|
||||||
"version": "2.6.5",
|
"version": "2.6.5",
|
||||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.5.tgz",
|
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.5.tgz",
|
||||||
"integrity": "sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A==",
|
"integrity": "sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"core-util-is": {
|
"core-util-is": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||||
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
|
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"cosmiconfig": {
|
"cosmiconfig": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
@ -2954,8 +3063,15 @@
|
|||||||
"decode-uri-component": {
|
"decode-uri-component": {
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
|
||||||
"integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
|
"integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU="
|
||||||
"dev": true
|
},
|
||||||
|
"decompress-response": {
|
||||||
|
"version": "3.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz",
|
||||||
|
"integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=",
|
||||||
|
"requires": {
|
||||||
|
"mimic-response": "^1.0.0"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"deep-equal": {
|
"deep-equal": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
@ -2969,6 +3085,11 @@
|
|||||||
"integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
|
"integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"deepmerge": {
|
||||||
|
"version": "1.5.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-1.5.2.tgz",
|
||||||
|
"integrity": "sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ=="
|
||||||
|
},
|
||||||
"define-properties": {
|
"define-properties": {
|
||||||
"version": "1.1.3",
|
"version": "1.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
|
||||||
@ -3215,6 +3336,11 @@
|
|||||||
"integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=",
|
"integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"duplexer3": {
|
||||||
|
"version": "0.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
|
||||||
|
"integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI="
|
||||||
|
},
|
||||||
"duplexify": {
|
"duplexify": {
|
||||||
"version": "3.7.1",
|
"version": "3.7.1",
|
||||||
"resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz",
|
"resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz",
|
||||||
@ -3245,6 +3371,19 @@
|
|||||||
"integrity": "sha512-glecGr/kFdfeXUHOHAWvGcXrxNU+1wSO/t5B23tT1dtlvYB26GY8aHzZSWD7HqhqC800Lr+w/hQul6C5AF542w==",
|
"integrity": "sha512-glecGr/kFdfeXUHOHAWvGcXrxNU+1wSO/t5B23tT1dtlvYB26GY8aHzZSWD7HqhqC800Lr+w/hQul6C5AF542w==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"element-ui": {
|
||||||
|
"version": "2.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/element-ui/-/element-ui-2.7.2.tgz",
|
||||||
|
"integrity": "sha512-Exh9QTkm9gwMMPzg1TyaTlBKyr3k4K9XcC5vl0A/mneDvJX//RsURGuOWsCNDVQMdhh5h9e+W5icosh+pKfbCg==",
|
||||||
|
"requires": {
|
||||||
|
"async-validator": "~1.8.1",
|
||||||
|
"babel-helper-vue-jsx-merge-props": "^2.0.0",
|
||||||
|
"deepmerge": "^1.2.0",
|
||||||
|
"normalize-wheel": "^1.0.1",
|
||||||
|
"resize-observer-polyfill": "^1.5.0",
|
||||||
|
"throttle-debounce": "^1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"elliptic": {
|
"elliptic": {
|
||||||
"version": "6.4.1",
|
"version": "6.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz",
|
||||||
@ -4311,7 +4450,6 @@
|
|||||||
"version": "2.3.0",
|
"version": "2.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz",
|
||||||
"integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=",
|
"integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"inherits": "^2.0.1",
|
"inherits": "^2.0.1",
|
||||||
"readable-stream": "^2.0.0"
|
"readable-stream": "^2.0.0"
|
||||||
@ -4910,8 +5048,7 @@
|
|||||||
"get-stream": {
|
"get-stream": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
|
||||||
"integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
|
"integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"get-value": {
|
"get-value": {
|
||||||
"version": "2.0.6",
|
"version": "2.0.6",
|
||||||
@ -4974,6 +5111,30 @@
|
|||||||
"slash": "^1.0.0"
|
"slash": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"got": {
|
||||||
|
"version": "8.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/got/-/got-8.3.2.tgz",
|
||||||
|
"integrity": "sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw==",
|
||||||
|
"requires": {
|
||||||
|
"@sindresorhus/is": "^0.7.0",
|
||||||
|
"cacheable-request": "^2.1.1",
|
||||||
|
"decompress-response": "^3.3.0",
|
||||||
|
"duplexer3": "^0.1.4",
|
||||||
|
"get-stream": "^3.0.0",
|
||||||
|
"into-stream": "^3.1.0",
|
||||||
|
"is-retry-allowed": "^1.1.0",
|
||||||
|
"isurl": "^1.0.0-alpha5",
|
||||||
|
"lowercase-keys": "^1.0.0",
|
||||||
|
"mimic-response": "^1.0.0",
|
||||||
|
"p-cancelable": "^0.4.0",
|
||||||
|
"p-timeout": "^2.0.1",
|
||||||
|
"pify": "^3.0.0",
|
||||||
|
"safe-buffer": "^5.1.1",
|
||||||
|
"timed-out": "^4.0.1",
|
||||||
|
"url-parse-lax": "^3.0.0",
|
||||||
|
"url-to-options": "^1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"graceful-fs": {
|
"graceful-fs": {
|
||||||
"version": "4.1.15",
|
"version": "4.1.15",
|
||||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz",
|
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz",
|
||||||
@ -5026,12 +5187,25 @@
|
|||||||
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
|
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"has-symbol-support-x": {
|
||||||
|
"version": "1.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz",
|
||||||
|
"integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw=="
|
||||||
|
},
|
||||||
"has-symbols": {
|
"has-symbols": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz",
|
||||||
"integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=",
|
"integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"has-to-string-tag-x": {
|
||||||
|
"version": "1.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz",
|
||||||
|
"integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==",
|
||||||
|
"requires": {
|
||||||
|
"has-symbol-support-x": "^1.4.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"has-value": {
|
"has-value": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
|
||||||
@ -5223,6 +5397,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"http-cache-semantics": {
|
||||||
|
"version": "3.8.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz",
|
||||||
|
"integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w=="
|
||||||
|
},
|
||||||
"http-deceiver": {
|
"http-deceiver": {
|
||||||
"version": "1.2.7",
|
"version": "1.2.7",
|
||||||
"resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz",
|
"resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz",
|
||||||
@ -5393,8 +5572,7 @@
|
|||||||
"inherits": {
|
"inherits": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
|
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"inquirer": {
|
"inquirer": {
|
||||||
"version": "3.3.0",
|
"version": "3.3.0",
|
||||||
@ -5450,6 +5628,15 @@
|
|||||||
"integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==",
|
"integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"into-stream": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz",
|
||||||
|
"integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=",
|
||||||
|
"requires": {
|
||||||
|
"from2": "^2.1.1",
|
||||||
|
"p-is-promise": "^1.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"invariant": {
|
"invariant": {
|
||||||
"version": "2.2.4",
|
"version": "2.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
|
||||||
@ -5604,6 +5791,11 @@
|
|||||||
"kind-of": "^3.0.2"
|
"kind-of": "^3.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"is-object": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz",
|
||||||
|
"integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA="
|
||||||
|
},
|
||||||
"is-path-cwd": {
|
"is-path-cwd": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz",
|
||||||
@ -5631,8 +5823,7 @@
|
|||||||
"is-plain-obj": {
|
"is-plain-obj": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
|
||||||
"integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=",
|
"integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"is-plain-object": {
|
"is-plain-object": {
|
||||||
"version": "2.0.4",
|
"version": "2.0.4",
|
||||||
@ -5664,6 +5855,11 @@
|
|||||||
"integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==",
|
"integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"is-retry-allowed": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz",
|
||||||
|
"integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ="
|
||||||
|
},
|
||||||
"is-stream": {
|
"is-stream": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
|
||||||
@ -5709,8 +5905,7 @@
|
|||||||
"isarray": {
|
"isarray": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||||
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
|
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"isexe": {
|
"isexe": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
@ -5724,6 +5919,15 @@
|
|||||||
"integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
|
"integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"isurl": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==",
|
||||||
|
"requires": {
|
||||||
|
"has-to-string-tag-x": "^1.2.0",
|
||||||
|
"is-object": "^1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"js-base64": {
|
"js-base64": {
|
||||||
"version": "2.5.1",
|
"version": "2.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.1.tgz",
|
||||||
@ -5752,6 +5956,11 @@
|
|||||||
"integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=",
|
"integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"json-buffer": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz",
|
||||||
|
"integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg="
|
||||||
|
},
|
||||||
"json-loader": {
|
"json-loader": {
|
||||||
"version": "0.5.7",
|
"version": "0.5.7",
|
||||||
"resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz",
|
"resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz",
|
||||||
@ -5788,6 +5997,14 @@
|
|||||||
"integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=",
|
"integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"keyv": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==",
|
||||||
|
"requires": {
|
||||||
|
"json-buffer": "3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"killable": {
|
"killable": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz",
|
||||||
@ -6023,6 +6240,11 @@
|
|||||||
"integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=",
|
"integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"lowercase-keys": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA=="
|
||||||
|
},
|
||||||
"lru-cache": {
|
"lru-cache": {
|
||||||
"version": "4.1.5",
|
"version": "4.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
|
||||||
@ -6288,6 +6510,11 @@
|
|||||||
"integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
|
"integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"mimic-response": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ=="
|
||||||
|
},
|
||||||
"minimalistic-assert": {
|
"minimalistic-assert": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
|
||||||
@ -6566,6 +6793,11 @@
|
|||||||
"sort-keys": "^1.0.0"
|
"sort-keys": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"normalize-wheel": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/normalize-wheel/-/normalize-wheel-1.0.1.tgz",
|
||||||
|
"integrity": "sha1-rsiGr/2wRQcNhWRH32Ls+GFG7EU="
|
||||||
|
},
|
||||||
"npm-run-path": {
|
"npm-run-path": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
|
||||||
@ -6599,8 +6831,7 @@
|
|||||||
"object-assign": {
|
"object-assign": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||||
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
|
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"object-copy": {
|
"object-copy": {
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
@ -6782,11 +7013,20 @@
|
|||||||
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
|
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"p-cancelable": {
|
||||||
|
"version": "0.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.4.1.tgz",
|
||||||
|
"integrity": "sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ=="
|
||||||
|
},
|
||||||
"p-finally": {
|
"p-finally": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
|
||||||
"integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=",
|
"integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4="
|
||||||
"dev": true
|
},
|
||||||
|
"p-is-promise": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz",
|
||||||
|
"integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4="
|
||||||
},
|
},
|
||||||
"p-limit": {
|
"p-limit": {
|
||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
@ -6812,6 +7052,14 @@
|
|||||||
"integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==",
|
"integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"p-timeout": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==",
|
||||||
|
"requires": {
|
||||||
|
"p-finally": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"p-try": {
|
"p-try": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
|
||||||
@ -6952,8 +7200,7 @@
|
|||||||
"pify": {
|
"pify": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
|
||||||
"integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
|
"integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"pinkie": {
|
"pinkie": {
|
||||||
"version": "2.0.4",
|
"version": "2.0.4",
|
||||||
@ -9113,8 +9360,7 @@
|
|||||||
"process-nextick-args": {
|
"process-nextick-args": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
|
||||||
"integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
|
"integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"progress": {
|
"progress": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
@ -9338,7 +9584,6 @@
|
|||||||
"version": "2.3.6",
|
"version": "2.3.6",
|
||||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
|
||||||
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
|
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"core-util-is": "~1.0.0",
|
"core-util-is": "~1.0.0",
|
||||||
"inherits": "~2.0.3",
|
"inherits": "~2.0.3",
|
||||||
@ -9424,8 +9669,7 @@
|
|||||||
"regenerator-runtime": {
|
"regenerator-runtime": {
|
||||||
"version": "0.11.1",
|
"version": "0.11.1",
|
||||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
|
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
|
||||||
"integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==",
|
"integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"regenerator-transform": {
|
"regenerator-transform": {
|
||||||
"version": "0.10.1",
|
"version": "0.10.1",
|
||||||
@ -9568,6 +9812,11 @@
|
|||||||
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
|
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"resize-observer-polyfill": {
|
||||||
|
"version": "1.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
|
||||||
|
"integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="
|
||||||
|
},
|
||||||
"resolve": {
|
"resolve": {
|
||||||
"version": "1.10.0",
|
"version": "1.10.0",
|
||||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz",
|
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz",
|
||||||
@ -9606,6 +9855,14 @@
|
|||||||
"integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=",
|
"integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"responselike": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz",
|
||||||
|
"integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=",
|
||||||
|
"requires": {
|
||||||
|
"lowercase-keys": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"restore-cursor": {
|
"restore-cursor": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
|
||||||
@ -9691,8 +9948,7 @@
|
|||||||
"safe-buffer": {
|
"safe-buffer": {
|
||||||
"version": "5.1.2",
|
"version": "5.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"safe-regex": {
|
"safe-regex": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
@ -10313,8 +10569,7 @@
|
|||||||
"strict-uri-encode": {
|
"strict-uri-encode": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
|
||||||
"integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=",
|
"integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"string-width": {
|
"string-width": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
@ -10347,7 +10602,6 @@
|
|||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||||
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"safe-buffer": "~5.1.0"
|
"safe-buffer": "~5.1.0"
|
||||||
}
|
}
|
||||||
@ -10458,6 +10712,11 @@
|
|||||||
"integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
|
"integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"throttle-debounce": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-XH8UiPCQcWNuk2LYePibW/4qL97+ZQ1AN3FNXwZRBNPPowo/NRU5fAlDCSNBJIYCKbioZfuYtMhG4quqoJhVzg=="
|
||||||
|
},
|
||||||
"through": {
|
"through": {
|
||||||
"version": "2.3.8",
|
"version": "2.3.8",
|
||||||
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
||||||
@ -10486,6 +10745,11 @@
|
|||||||
"integrity": "sha512-zxke8goJQpBeEgD82CXABeMh0LSJcj7CXEd0OHOg45HgcofF7pxNwZm9+RknpxpDhwN4gFpySkApKfFYfRQnUA==",
|
"integrity": "sha512-zxke8goJQpBeEgD82CXABeMh0LSJcj7CXEd0OHOg45HgcofF7pxNwZm9+RknpxpDhwN4gFpySkApKfFYfRQnUA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"timed-out": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz",
|
||||||
|
"integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8="
|
||||||
|
},
|
||||||
"timers-browserify": {
|
"timers-browserify": {
|
||||||
"version": "2.0.10",
|
"version": "2.0.10",
|
||||||
"resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz",
|
"resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz",
|
||||||
@ -10885,6 +11149,26 @@
|
|||||||
"requires-port": "^1.0.0"
|
"requires-port": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"url-parse-lax": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz",
|
||||||
|
"integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=",
|
||||||
|
"requires": {
|
||||||
|
"prepend-http": "^2.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"prepend-http": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz",
|
||||||
|
"integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"url-to-options": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz",
|
||||||
|
"integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k="
|
||||||
|
},
|
||||||
"use": {
|
"use": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
|
||||||
@ -10903,8 +11187,7 @@
|
|||||||
"util-deprecate": {
|
"util-deprecate": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
|
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"utila": {
|
"utila": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
@ -11059,6 +11342,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"vue-resource": {
|
||||||
|
"version": "1.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/vue-resource/-/vue-resource-1.5.1.tgz",
|
||||||
|
"integrity": "sha512-o6V4wNgeqP+9v9b2bPXrr20CGNQPEXjpbUWdZWq9GJhqVeAGcYoeTtn/D4q059ZiyN0DIrDv/ADrQUmlUQcsmg==",
|
||||||
|
"requires": {
|
||||||
|
"got": "^8.0.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"vue-router": {
|
"vue-router": {
|
||||||
"version": "3.0.2",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.0.2.tgz",
|
||||||
|
@ -13,7 +13,10 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"d3": "^5.9.2",
|
"d3": "^5.9.2",
|
||||||
"d3-force": "^2.0.1",
|
"d3-force": "^2.0.1",
|
||||||
|
"d3-path": "^1.0.7",
|
||||||
|
"element-ui": "^2.7.2",
|
||||||
"vue": "^2.6.10",
|
"vue": "^2.6.10",
|
||||||
|
"vue-resource": "^1.5.1",
|
||||||
"vue-router": "^3.0.2"
|
"vue-router": "^3.0.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@ -22,6 +25,7 @@
|
|||||||
"babel-eslint": "^8.2.1",
|
"babel-eslint": "^8.2.1",
|
||||||
"babel-helper-vue-jsx-merge-props": "^2.0.3",
|
"babel-helper-vue-jsx-merge-props": "^2.0.3",
|
||||||
"babel-loader": "^7.1.1",
|
"babel-loader": "^7.1.1",
|
||||||
|
"babel-plugin-component": "^1.1.1",
|
||||||
"babel-plugin-syntax-jsx": "^6.18.0",
|
"babel-plugin-syntax-jsx": "^6.18.0",
|
||||||
"babel-plugin-transform-runtime": "^6.22.0",
|
"babel-plugin-transform-runtime": "^6.22.0",
|
||||||
"babel-plugin-transform-vue-jsx": "^3.5.0",
|
"babel-plugin-transform-vue-jsx": "^3.5.0",
|
||||||
|
@ -11,12 +11,11 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
body {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
#app {
|
#app {
|
||||||
font-family: 'Avenir', Helvetica, Arial, sans-serif;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
text-align: center;
|
|
||||||
color: #2c3e50;
|
|
||||||
margin-top: 60px;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
54
ui/src/components/ArtistInfo.vue
Normal file
54
ui/src/components/ArtistInfo.vue
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
<template>
|
||||||
|
<el-card class="artist-info box-card" v-if="artist !== undefined">
|
||||||
|
<div slot="header">
|
||||||
|
<span>{{artist.name}}</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<ImageCarousel
|
||||||
|
v-bind:sources="artistInfo.covers"
|
||||||
|
interval="750" />
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Vue from 'vue'
|
||||||
|
import ImageCarousel from './ImageCarousel'
|
||||||
|
|
||||||
|
let data = {
|
||||||
|
artistInfo: {
|
||||||
|
releases: [],
|
||||||
|
covers: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function reloadInfo(artist) {
|
||||||
|
Vue.http.get('http://localhost:3030/artist/details/' + artist.mbid)
|
||||||
|
.then(response => {
|
||||||
|
response.json().then(info => {
|
||||||
|
info.covers = info.releases.map(mbid => 'http://localhost:3030/cover/' + mbid)
|
||||||
|
|
||||||
|
data.artistInfo = info
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'ArtistInfo',
|
||||||
|
components: {ImageCarousel},
|
||||||
|
props: ['artist'],
|
||||||
|
watch: {
|
||||||
|
artist: reloadInfo
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.artist-info {
|
||||||
|
margin: 1rem;
|
||||||
|
position: fixed;
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,12 +1,19 @@
|
|||||||
<template>
|
<template>
|
||||||
<div></div>
|
<div>
|
||||||
|
<ArtistInfo v-bind:artist="hoverArtist"/>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
import * as d3 from 'd3'
|
import * as d3 from 'd3'
|
||||||
|
import ArtistInfo from './ArtistInfo'
|
||||||
|
|
||||||
function getNodeType (labels) {
|
let data = {
|
||||||
|
hoverArtist: undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
const nodeUtils = {
|
||||||
|
getNodeType: function (labels) {
|
||||||
if (labels.find(l => l === 'Tag')) {
|
if (labels.find(l => l === 'Tag')) {
|
||||||
return 'Tag'
|
return 'Tag'
|
||||||
} else if (labels.find(l => l === 'Group')) {
|
} else if (labels.find(l => l === 'Group')) {
|
||||||
@ -15,182 +22,442 @@
|
|||||||
return 'Artist'
|
return 'Artist'
|
||||||
}
|
}
|
||||||
return undefined
|
return undefined
|
||||||
|
},
|
||||||
|
|
||||||
|
getRadius: function (node) {
|
||||||
|
if (expandedNodes.has(node.id)) {
|
||||||
|
return 40
|
||||||
}
|
}
|
||||||
|
|
||||||
let data = {}
|
|
||||||
d3.json('../static/data.json')
|
|
||||||
.then((r) => {
|
|
||||||
data = r
|
|
||||||
|
|
||||||
const links = data.map(row => ({
|
|
||||||
source: row._fields[1].start.low,
|
|
||||||
target: row._fields[1].end.low,
|
|
||||||
weight: row._fields[1].properties.weight.low
|
|
||||||
}))
|
|
||||||
const nodes = []
|
|
||||||
|
|
||||||
function addNode (node) {
|
|
||||||
if (nodes.find(n => n.id === node.id)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
nodes.push(node)
|
|
||||||
}
|
|
||||||
|
|
||||||
data.forEach((row) => {
|
|
||||||
addNode({
|
|
||||||
id: row._fields[0].identity.low,
|
|
||||||
name: row._fields[0].properties.name,
|
|
||||||
listeners: row._fields[0].properties.listeners.low,
|
|
||||||
type: getNodeType(row._fields[0].labels)
|
|
||||||
})
|
|
||||||
addNode({
|
|
||||||
id: row._fields[2].identity.low,
|
|
||||||
name: row._fields[2].properties.name,
|
|
||||||
type: 'Tag'
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
function getRadius (node) {
|
|
||||||
if (node.type === 'Tag') {
|
if (node.type === 'Tag') {
|
||||||
return 10
|
return 10
|
||||||
}
|
}
|
||||||
return Math.max(Math.sqrt(node.listeners / 5000), 15)
|
|
||||||
}
|
|
||||||
|
|
||||||
function getColor (node) {
|
return Math.max(Math.sqrt(node.listeners / 7000) * 1.4, 15)
|
||||||
switch (node.type) {
|
},
|
||||||
case 'Tag':
|
|
||||||
return '#e0e0e0'
|
getColor: function (node) {
|
||||||
case 'Artist':
|
if (expandedNodes.has(node.id)) {
|
||||||
return '#42c3f7'
|
return '#1cb3c8'
|
||||||
case 'Group':
|
}
|
||||||
return '#00a5e9'
|
return null
|
||||||
default:
|
|
||||||
return '#DEADFB'
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const width = window.innerWidth - 5
|
let originArtist
|
||||||
const height = window.innerHeight - 5
|
let originNode
|
||||||
|
let expandedNodes = new Set()
|
||||||
|
|
||||||
// ??
|
function MusicGraph() {
|
||||||
const simulation = d3.forceSimulation(nodes)
|
const width = window.innerWidth - 7
|
||||||
.force('link', d3.forceLink(links).id(d => d.id))
|
const height = window.innerHeight - 7
|
||||||
.force('charge', d3.forceManyBody())
|
|
||||||
.force('center', d3.forceCenter(width / 2, height / 2))
|
|
||||||
|
|
||||||
let container
|
this.nodeById = new Map()
|
||||||
|
this.nodes = []
|
||||||
|
this.links = []
|
||||||
|
this._originSet = false
|
||||||
|
|
||||||
function zoomed () {
|
this.svg = d3.select('body')
|
||||||
container.attr('transform', d3.event.transform)
|
.append('svg')
|
||||||
|
.attr('width', width)
|
||||||
|
.attr('height', height)
|
||||||
|
|
||||||
|
this.zoomed = () => {
|
||||||
|
this.container.attr('transform', d3.event.transform)
|
||||||
}
|
}
|
||||||
|
|
||||||
function nodeZoomed () {
|
this.svg.append('rect')
|
||||||
// TODO
|
.attr('width', width)
|
||||||
}
|
.attr('height', height)
|
||||||
|
.classed('pan-rect', true)
|
||||||
|
.style('fill', 'none')
|
||||||
|
.call(d3.zoom()
|
||||||
|
.scaleExtent([1 / 10, 5])
|
||||||
|
.on('zoom', this.zoomed))
|
||||||
|
|
||||||
function dragStarted (d) {
|
this.container = this.svg.append('g').attr('id', 'container')
|
||||||
|
|
||||||
|
this.container.append('g')
|
||||||
|
.attr('id', 'links')
|
||||||
|
this.container.append('g')
|
||||||
|
.attr('id', 'nodes')
|
||||||
|
this.container.append('g')
|
||||||
|
.attr('id', 'labels')
|
||||||
|
|
||||||
|
this.dragStarted = (d) => {
|
||||||
if (!d3.event.active) {
|
if (!d3.event.active) {
|
||||||
simulation.alphaTarget(0.3).restart()
|
this.simulation.alphaTarget(0.3).restart()
|
||||||
}
|
}
|
||||||
d.fx = d.x
|
d.fx = d.x
|
||||||
d.fy = d.y
|
d.fy = d.y
|
||||||
}
|
}
|
||||||
|
|
||||||
function dragged (d) {
|
this.dragged = (d) => {
|
||||||
d.fx = d3.event.x
|
d.fx = d3.event.x
|
||||||
d.fy = d3.event.y
|
d.fy = d3.event.y
|
||||||
}
|
}
|
||||||
|
|
||||||
function dragEnded (d) {
|
this.dragEnded = (d) => {
|
||||||
if (!d3.event.active) {
|
if (!d3.event.active) {
|
||||||
simulation.alphaTarget(0)
|
this.simulation.alphaTarget(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
d.fx = null
|
d.fx = null
|
||||||
d.fy = null
|
d.fy = null
|
||||||
}
|
}
|
||||||
|
|
||||||
const svg = d3.select('body')
|
this.nodeHover = (d) => {
|
||||||
.append('svg')
|
data.hoverArtist = d
|
||||||
.attr('width', width)
|
|
||||||
.attr('height', height)
|
|
||||||
|
|
||||||
svg.append('rect')
|
let srcLinks = this.links.filter(link => link.source.id === d.id)
|
||||||
.attr('width', width)
|
let targetLinks = this.links.filter(link => link.target.id === d.id)
|
||||||
.attr('height', height)
|
data.hoverLinks = srcLinks.map(l => {
|
||||||
.style('pointer-events', 'all')
|
return {
|
||||||
.style('fill', 'none')
|
match: (l.weight * 100).toFixed(2) + '%',
|
||||||
.call(d3.zoom()
|
other: l.target
|
||||||
.scaleExtent([1 / 3, 5])
|
}
|
||||||
.on('zoom', zoomed))
|
}).concat(targetLinks.map(l => {
|
||||||
|
return {
|
||||||
|
match: (l.weight * 100).toFixed(2) + '%',
|
||||||
|
other: l.source
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
console.log(data.hoverLinks)
|
||||||
|
|
||||||
document.body.setAttribute('style', 'background: #E7EDEB')
|
this.svg.classed('hover', true)
|
||||||
container = svg.append('g')
|
|
||||||
|
|
||||||
const link = container.append('g')
|
this.link.classed('selected', link =>
|
||||||
.attr('stroke', '#003a6b')
|
link.source.id === d.id || link.target.id === d.id)
|
||||||
.selectAll('line')
|
|
||||||
.data(links)
|
|
||||||
.join('line')
|
|
||||||
.attr('stroke-opacity', rel => rel.weight / 15)
|
|
||||||
.attr('stroke-width', rel => Math.sqrt(rel.weight) * 0.6)
|
|
||||||
|
|
||||||
const node = container.append('g')
|
this.node.classed('selected', n =>
|
||||||
.attr('stroke', '#ffffff')
|
n.sourceLinks.has(d.id) ||
|
||||||
.attr('stroke-width', 1.5)
|
n.targetLinks.has(d.id))
|
||||||
.selectAll('circle')
|
|
||||||
.data(nodes)
|
|
||||||
.join('circle')
|
|
||||||
.attr('r', d => getRadius(d))
|
|
||||||
.attr('fill', d => getColor(d))
|
|
||||||
.call(d3.drag()
|
|
||||||
.on('start', dragStarted)
|
|
||||||
.on('drag', dragged)
|
|
||||||
.on('end', dragEnded))
|
|
||||||
.on('wheel', nodeZoomed)
|
|
||||||
|
|
||||||
node.append('title')
|
this.label.classed('selected', n =>
|
||||||
.text(d => `${d.name} ${d.id}`)
|
n.sourceLinks.has(d.id) ||
|
||||||
|
n.targetLinks.has(d.id) ||
|
||||||
|
n.id === d.id)
|
||||||
|
|
||||||
simulation.on('tick', () => {
|
this.node.classed('hover', n => n.id === d.id)
|
||||||
link
|
}
|
||||||
|
|
||||||
|
this.nodeOut = () => {
|
||||||
|
this.svg.classed('hover', false)
|
||||||
|
this.label.classed('selected', false)
|
||||||
|
this.link.classed('selected', false)
|
||||||
|
this.node.classed('selected', false)
|
||||||
|
this.node.classed('hover', false)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.nodeDbClick = (d) => {
|
||||||
|
if (expandedNodes.has(d.id)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
expandedNodes.add(d.id)
|
||||||
|
expandArtist(d.mbid)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.simulation = d3.forceSimulation()
|
||||||
|
.force('charge', d3.forceManyBody())
|
||||||
|
.force('collide', d3.forceCollide()
|
||||||
|
.radius(50)
|
||||||
|
.strength(1))
|
||||||
|
.force('center', d3.forceCenter(width / 2, height / 2))
|
||||||
|
|
||||||
|
this.simulation.stop()
|
||||||
|
|
||||||
|
this.simulation.on('tick', () => {
|
||||||
|
this.link
|
||||||
.attr('x1', d => d.source.x)
|
.attr('x1', d => d.source.x)
|
||||||
.attr('y1', d => d.source.y)
|
.attr('y1', d => d.source.y)
|
||||||
.attr('x2', d => d.target.x)
|
.attr('x2', d => d.target.x)
|
||||||
.attr('y2', d => d.target.y)
|
.attr('y2', d => d.target.y)
|
||||||
node
|
this.node
|
||||||
.attr('cx', d => d.x)
|
.attr('cx', d => d.x)
|
||||||
.attr('cy', d => d.y)
|
.attr('cy', d => d.y)
|
||||||
|
this.label
|
||||||
|
.attr('x', d => d.x)
|
||||||
|
.attr('y', d => d.y)
|
||||||
})
|
})
|
||||||
})
|
|
||||||
export default {
|
/**
|
||||||
name: 'hello',
|
* Add nodes to the graph
|
||||||
data () {
|
*/
|
||||||
return {
|
this.addNodes = function (newNodes, relations, originId) {
|
||||||
msg: 'Welcome to Your Vue.js App'
|
// Update node map, ignore existing nodes
|
||||||
|
let nodesToAdd = []
|
||||||
|
newNodes.forEach(d => {
|
||||||
|
if (this.nodeById.has(d.id)) {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
this.nodeById.set(d.id, d)
|
||||||
|
|
||||||
|
if (this._originSet && originId) {
|
||||||
|
// Set new nodes initial position
|
||||||
|
let centerNode = this.nodeById.get(originId)
|
||||||
|
centerNode.fx = centerNode.x
|
||||||
|
centerNode.fy = centerNode.y
|
||||||
|
d.x = centerNode.x
|
||||||
|
d.y = centerNode.y
|
||||||
|
setTimeout(() => {
|
||||||
|
centerNode.fx = null
|
||||||
|
centerNode.fy = null
|
||||||
|
}, 600)
|
||||||
|
}
|
||||||
|
|
||||||
|
nodesToAdd.push(d)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Convert {id, id} relation to {node, node}
|
||||||
|
let linksToAdd = relations.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(...nodesToAdd)
|
||||||
|
this.links.push(...linksToAdd)
|
||||||
|
|
||||||
|
if (!this._originSet) {
|
||||||
|
this._setOrigin()
|
||||||
|
this._originSet = true
|
||||||
|
}
|
||||||
|
|
||||||
|
this._update()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove nodes from the graph
|
||||||
|
*/
|
||||||
|
this.removeNodes = function (idsToRemove) {
|
||||||
|
let idSetToRemove = new Set(idsToRemove)
|
||||||
|
|
||||||
|
idsToRemove.forEach(id => {
|
||||||
|
// Update targetLinks
|
||||||
|
Array.from(this.nodeById.get(id).sourceLinks)
|
||||||
|
.map(srcId => this.nodeById.get(srcId))
|
||||||
|
.forEach(target => {
|
||||||
|
target.targetLinks.delete(id)
|
||||||
|
})
|
||||||
|
|
||||||
|
this.nodeById.delete(id)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Remove links
|
||||||
|
this.links = this.links.filter(l =>
|
||||||
|
!idSetToRemove.has(l.target.id) &&
|
||||||
|
!idSetToRemove.has(l.source.id)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Remove nodes
|
||||||
|
this.nodes = this.nodes.filter(d => !idSetToRemove.has(d.id))
|
||||||
|
|
||||||
|
this._update()
|
||||||
|
}
|
||||||
|
|
||||||
|
this._update = function () {
|
||||||
|
this.simulation.nodes(this.nodes)
|
||||||
|
this.simulation
|
||||||
|
.force('link', d3.forceLink(this.links)
|
||||||
|
.id(d => d.id)
|
||||||
|
.strength(l => l.weight)
|
||||||
|
.distance(d => Math.min(
|
||||||
|
(1.2 / d.weight) * (94 * expandedNodes.size))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
this.simulation
|
||||||
|
.restart()
|
||||||
|
|
||||||
|
// Add new links
|
||||||
|
this.link = this.container.select('#links')
|
||||||
|
.selectAll('.link')
|
||||||
|
.data(this.links)
|
||||||
|
let linkEnter = this.link
|
||||||
|
.enter()
|
||||||
|
.append('line')
|
||||||
|
.classed('link', true)
|
||||||
|
this.link = linkEnter.merge(this.link)
|
||||||
|
|
||||||
|
// Add new nodes
|
||||||
|
this.node = this.container.select('#nodes')
|
||||||
|
.selectAll('.node')
|
||||||
|
.attr('stroke', d => nodeUtils.getColor(d))
|
||||||
|
.data(this.nodes)
|
||||||
|
let nodeEnter = this.node
|
||||||
|
.enter()
|
||||||
|
.append('circle')
|
||||||
|
.classed('node', true)
|
||||||
|
.attr('r', 35)
|
||||||
|
.attr('stroke', d => nodeUtils.getColor(d))
|
||||||
|
.call(d3.drag()
|
||||||
|
.on('start', this.dragStarted)
|
||||||
|
.on('drag', this.dragged)
|
||||||
|
.on('end', this.dragEnded))
|
||||||
|
.on('mouseover', this.nodeHover)
|
||||||
|
.on('mouseout', this.nodeOut)
|
||||||
|
.on('dblclick', this.nodeDbClick)
|
||||||
|
this.node = nodeEnter.merge(this.node)
|
||||||
|
|
||||||
|
// Add new labels
|
||||||
|
this.label = this.container.select('#labels')
|
||||||
|
.selectAll('.label')
|
||||||
|
.data(this.nodes)
|
||||||
|
let labelEnter = this.label
|
||||||
|
.enter()
|
||||||
|
.append('text')
|
||||||
|
.text(d => d.name)
|
||||||
|
.classed('label', true)
|
||||||
|
this.label = labelEnter.merge(this.label)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setupKeyBindings = function () {
|
||||||
|
document.body.onkeydown = (e) => {
|
||||||
|
let isPanMode = this.svg.classed('pan-mode')
|
||||||
|
|
||||||
|
if (e.key === 'q') {
|
||||||
|
this.svg.classed('pan-mode', !isPanMode)
|
||||||
|
} else if (e.key === 'Escape') {
|
||||||
|
this.svg.classed('pan-mode', false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this._setOrigin = function () {
|
||||||
|
// Set origin node in center
|
||||||
|
originNode = this.simulation.nodes().find(node => node.id === originArtist.id)
|
||||||
|
originNode.fx = width / 2
|
||||||
|
originNode.fy = height / 2
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
originNode.fx = null
|
||||||
|
originNode.fy = null
|
||||||
|
}, 500)
|
||||||
|
|
||||||
|
// Remember that we expanded origin node
|
||||||
|
expandedNodes.add(originNode.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
this._update()
|
||||||
|
this.setupKeyBindings()
|
||||||
|
}
|
||||||
|
|
||||||
|
let mm = new MusicGraph()
|
||||||
|
|
||||||
|
function expandArtist(mbid) {
|
||||||
|
d3.json('http://localhost:3030/artist/related/' + mbid)
|
||||||
|
.then((r) => {
|
||||||
|
originArtist = r.artists.find(a => a.mbid === mbid)
|
||||||
|
|
||||||
|
const nodes = r.artists.map((row) => {
|
||||||
|
return {
|
||||||
|
id: row.id,
|
||||||
|
mbid: row.mbid,
|
||||||
|
name: row.name,
|
||||||
|
listeners: row.listeners,
|
||||||
|
type: nodeUtils.getNodeType(row.labels),
|
||||||
|
sourceLinks: new Set(),
|
||||||
|
targetLinks: new Set()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
mm.addNodes(nodes, r.relations, originArtist.id)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
expandArtist('66fc5bf8-daa4-4241-b378-9bc9077939d2')
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {ArtistInfo},
|
||||||
|
data() {
|
||||||
|
return data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
<style>
|
||||||
<style scoped>
|
svg {
|
||||||
h1, h2 {
|
margin-top: 3px;
|
||||||
font-weight: normal;
|
margin-left: 3px;
|
||||||
|
|
||||||
|
-webkit-touch-callout: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-khtml-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
ul {
|
/* Pan mode */
|
||||||
list-style-type: none;
|
svg.pan-mode .node {
|
||||||
padding: 0;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
li {
|
svg.pan-mode {
|
||||||
display: inline-block;
|
cursor: move;
|
||||||
margin: 0 10px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
svg.pan-mode .pan-rect {
|
||||||
color: #42b983;
|
pointer-events: all;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg.pan-mode {
|
||||||
|
box-sizing: border-box;
|
||||||
|
border: 5px red solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Link */
|
||||||
|
svg .link.selected {
|
||||||
|
stroke-width: 2;
|
||||||
|
stroke-opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg .link {
|
||||||
|
stroke: orange;
|
||||||
|
pointer-events: none;
|
||||||
|
stroke-opacity: 0.7;
|
||||||
|
stroke-width: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg.hover .link:not(.selected) {
|
||||||
|
stroke-opacity: 0.2;
|
||||||
|
stroke-width: 0.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Node */
|
||||||
|
svg .node.selected {
|
||||||
|
stroke: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg .node.hover {
|
||||||
|
stroke: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg.hover .node:not(.selected):not(.hover) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg .node {
|
||||||
|
fill: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Label */
|
||||||
|
svg .label {
|
||||||
|
text-anchor: middle;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg.hover .label:not(.selected) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background: #E7EDEB;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
51
ui/src/components/ImageCarousel.vue
Normal file
51
ui/src/components/ImageCarousel.vue
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<img
|
||||||
|
alt=""
|
||||||
|
width="96"
|
||||||
|
height="96"
|
||||||
|
v-show="currentSrc === url"
|
||||||
|
v-bind:src="url"
|
||||||
|
v-bind:key="url"
|
||||||
|
v-for="url in sources"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
let data = {
|
||||||
|
currentSrc: '',
|
||||||
|
index: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'ImageCarousel',
|
||||||
|
props: ['sources', 'interval'],
|
||||||
|
data() {
|
||||||
|
return data
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
setInterval(() => {
|
||||||
|
this.tick()
|
||||||
|
}, Number(this.interval))
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
sources: () => {
|
||||||
|
data.index = 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
tick() {
|
||||||
|
if (data.index === this.sources.length - 1) {
|
||||||
|
data.index = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
data.index += 1
|
||||||
|
data.currentSrc = this.sources[data.index]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
</style>
|
@ -2,7 +2,12 @@ import Vue from 'vue'
|
|||||||
import App from './App'
|
import App from './App'
|
||||||
import router from './router'
|
import router from './router'
|
||||||
|
|
||||||
Vue.config.productionTip = false
|
import ElementUI from 'element-ui'
|
||||||
|
import VueResource from 'vue-resource'
|
||||||
|
import 'element-ui/lib/theme-chalk/index.css'
|
||||||
|
|
||||||
|
Vue.use(ElementUI)
|
||||||
|
Vue.use(VueResource)
|
||||||
|
|
||||||
/* eslint-disable no-new */
|
/* eslint-disable no-new */
|
||||||
new Vue({
|
new Vue({
|
||||||
@ -10,3 +15,5 @@ new Vue({
|
|||||||
router,
|
router,
|
||||||
render: h => h(App)
|
render: h => h(App)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Vue.config.productionTip = false
|
||||||
|
Loading…
x
Reference in New Issue
Block a user