Browse Source

Artist graph improvements

- title
- full artist name on multiple lines
- responsive and fit screen (#63)

Other:
- added creating db to README
- added script to update requirements
  - updated requirements
master
Kevin Mok 5 years ago
parent
commit
68c1c85ebd
Signed by: Kevin-Mok GPG Key ID: AEA75288DC135CF5
  1. 7
      .gitignore
  2. 16
      README.md
  3. 86
      graphs/static/graphs/scripts/artist_graph.js
  4. 2
      graphs/static/graphs/scripts/genre_graph.js
  5. 8
      graphs/templates/graphs/artist_graph.html
  6. 4
      graphs/templates/graphs/genre_graph.html
  7. 40
      requirements.txt
  8. 3
      scripts/update-history.sh
  9. 7
      todo.md
  10. 4
      upgrade-pip-reqs.sh

7
.gitignore

@ -4,11 +4,12 @@
media/history/*
spotifyvis/static/graphs/sass/*
*.pyc
*.log
*.bak
*.txt
*.log
*.map
*.orig
*.pyc
*.txt
api-keys.sh
db.sqlite3

16
README.md

@ -26,7 +26,11 @@ pip install --user pipenv
python3 -m venv /path/to/new/virtual/environment
```
3. `cd` into the directory you just created a virtual environment in, and clone the GitHub repo.
3. `cd` into the directory you just created a virtual environment in, and clone the GitHub repo:
```
git clone https://github.com/Kevin-Mok/spotify-lib-vis
```
4. Activate the virtual environment from the command line.
@ -40,16 +44,10 @@ source bin/activate
pip install -r requirements.txt
```
6. Run Django migrations.
```
manage.py migrate
```
7. Start the server.
6. Run `reset_db.sh` to create the database and start the server.
```
python manage.py runserver
cd src && ./reset_db.sh
```
<!--- }}} installation steps -->

86
graphs/static/graphs/scripts/artist_graph.js

@ -1,9 +1,81 @@
const log = console.log
const width = 1366
const height = 768
// const width = 1000
// const height = 500
/**
* Draws the artist count graph as a bubble chart, and appends it the a designated parent element
* @param artistData: the artist counts data as an array of objects, of the format {'name': artist name, 'num_songs': 50}
* @param parentElem: the DOM element to append the artist graph to (as a string)
*/
function drawArtistGraph(artistData, parentElem) {
// const color = d3.scaleOrdinal(d3.schemeCategory10);
const color = d3.scaleOrdinal().range(randomColor({//{{{
count: Object.keys(artistData.children).length,
luminosity: 'light',
}))//}}}
const svg = d3.select(parentElem)//{{{
// const svg = d3.select(DOM.svg(width, height))
.append("div")
.classed("svg-container", true) //container class to make it responsive
.append("svg")
//responsive SVG needs these 2 attributes and no width and height attr
.attr("preserveAspectRatio", "xMinYMin meet")
.attr("viewBox", `0 0 ${width} ${height}`)
//class to make it responsive
.classed("svg-content-responsive", true)
.style("width", "100%")
.style("height", "100%")
.attr("font-size", 12)
.attr("text-anchor", "middle")//}}}
const root = d3.pack()//{{{
.size([width - 2, height - 2])
.padding(3)
(d3.hierarchy(artistData)
.sum(d => d.num_songs))
const leaf = svg.selectAll("g")
.data(root.leaves())
.join("g")
.attr("transform", d => `translate(${d.x + 1},${d.y + 1})`);//}}}
leaf.append("circle")//{{{
.attr("r", d => d.r)
// .attr("fill-opacity", 0.9)
.attr("fill", (d, id) => color(id))//}}}
leaf.append("text")//{{{
.selectAll("tspan")
.data(d => d.data.name.split(/\s/g).concat([d.data.num_songs]))
.join("tspan")
.attr("x", 0)
.attr("y", (d, i, nodes) => `${i - nodes.length / 2 + 0.8}em`)
// .attr("fill", "white")
.text(d => d)//}}}
// hover text {{{ //
leaf.append("title")
.text(d => `${d.data.name}: ${d.data.num_songs}`)
// }}} hover text //
// graph title {{{ //
svg.append("text")
.attr('x', (width / 2.2))
.attr('y', 50)
.attr('fill', "white")
.attr('text-anchor', 'middle')
.attr("font-weight", "bold")
.attr("font-size", 28)
.text('Artists in Library');
// }}} graph title //
return svg.node();
}
function drawArtistGraphOld(artistData, parentElem) {//{{{
let margin = {top: 20, right: 30, bottom: 30, left: 40};
// let width = 1000 - margin.right - margin.left;
// let height = 1000 - margin.top - margin.bottom;
@ -36,7 +108,7 @@ function drawArtistGraph(artistData, parentElem) {
.append("svg")
//responsive SVG needs these 2 attributes and no width and height attr
.attr("preserveAspectRatio", "xMinYMin meet")
.attr("viewBox", "0 0 600 250")
.attr("viewBox", "0 0 1024 768")
//class to make it responsive
.classed("svg-content-responsive", true);
@ -61,9 +133,7 @@ function drawArtistGraph(artistData, parentElem) {
});
node.append("circle")
.attr("r", function(d) {
return d.r;
})
.attr("r", d => d.r)
.style("fill", function(d,i) {
return color(i);
});
@ -73,7 +143,8 @@ function drawArtistGraph(artistData, parentElem) {
.attr("dy", ".2em")
.style("text-anchor", "middle")
.text(function(d) {
return d.data.name.substring(0, d.r / 3);
return d.data.name.substring(0, d.r / 1.5);
// return formatArtistName(d.data.name)
})
.attr("font-family", "sans-serif")
.attr("font-size", function(d){
@ -97,7 +168,4 @@ function drawArtistGraph(artistData, parentElem) {
d3.select(self.frameElement)
// .style("height", height + "px");
.style("height", "100%")
}
}//}}}

2
graphs/static/graphs/scripts/genre_graph.js

@ -41,6 +41,8 @@ function create_genre_graph(data) {
// hue: '#00ced1',
hue: '#0099CC',
}));
// colorScale = d3.scaleOrdinal(d3.schemeCategory10);
// colorScale = d3.scaleOrdinal(d3.schemeDark2);
// }}} setup bar colors //

8
graphs/templates/graphs/artist_graph.html

@ -8,20 +8,22 @@
<link rel="stylesheet" href="{% sass_src 'scss/custom.scss' %}">
<link rel="stylesheet" href="{% sass_src 'graphs/sass/responsive_graph.scss' %}">
<link rel="stylesheet" href="{% sass_src 'graphs/sass/max-height.scss' %}">
{% comment %} <script type="text/javascript" src="http://livejs.com/live.js"></script> {% endcomment %}
<script src="https://d3js.org/d3.v5.js"></script>
<script src="{% static "graphs/scripts/artist_graph.js" %}"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/randomcolor/0.5.2/randomColor.min.js"></script>
</head>
<body>
<div class="container-fluid">
</div>
<script src="https://d3js.org/d3.v5.js"></script>
<script src="{% static "graphs/scripts/artist_graph.js" %}"></script>
<script>
d3.json("{% url "api:get_artist_data" user_secret %}").then(function(data) {
// this is the data format needed for bubble charts
data = {
children: data
};
{% comment %} drawArtistGraph(data, "body"); {% endcomment %}
drawArtistGraph(data, ".container-fluid");
{% comment %} drawArtistGraphOld(data, ".container-fluid"); {% endcomment %}
});
</script>
</body>

4
graphs/templates/graphs/genre_graph.html

@ -15,13 +15,13 @@
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="{% sass_src 'scss/custom.scss' %}">
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/randomcolor/0.5.2/randomColor.min.js"></script>
</head>
<!-- }}} header -->
<body>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/randomcolor/0.5.2/randomColor.min.js"></script>
{% load static %}
<script src="{% static "graphs/scripts/genre_graph.js" %}"></script>

40
requirements.txt

@ -0,0 +1,40 @@
astroid==2.2.5
backports.csv==1.0.7
certifi==2019.3.9
chardet==3.0.4
defusedxml==0.5.0
Django==2.2
django-appconf==1.0.3
django-compressor==2.2
django-crispy-forms==1.7.2
django-filter==2.1.0
django-sass-processor==0.7.3
django-tables2==2.0.6
djangorestframework==3.9.2
et-xmlfile==1.0.1
idna==2.8
isort==4.3.17
jdcal==1.4
lazy-object-proxy==1.3.1
libsass==0.18.0
mccabe==0.6.1
odfpy==1.4.0
openpyxl==2.6.2
psycopg2==2.8.2
psycopg2-binary==2.8.2
pylint==2.3.1
python-dateutil==2.8.0
pytz==2019.1
PyYAML==5.1
rcssmin==1.0.6
requests==2.21.0
rjsmin==1.0.12
six==1.12.0
sqlparse==0.3.0
tablib==0.13.0
typed-ast==1.3.1
unicodecsv==0.14.1
urllib3==1.24.1
wrapt==1.11.1
xlrd==1.2.0
xlwt==1.3.0

3
scripts/update-history.sh

@ -1,3 +1,4 @@
#!/bin/bash
/home/kevin/coding/spotify-lib-vis/bin/python /home/kevin/coding/spotify-lib-vis/src/manage.py update-history >> /home/kevin/coding/spotify-lib-vis/src/api/management/commands/update-history.log
# /home/kevin/coding/spotify-lib-vis/bin/python /home/kevin/coding/spotify-lib-vis/src/manage.py update-history >> /home/kevin/coding/spotify-lib-vis/src/api/management/commands/update-history.log 2>&1
python /home/kevin/coding/spotify-lib-vis/src/manage.py update-history >> /home/kevin/coding/spotify-lib-vis/src/api/management/commands/update-history.log 2>&1

7
todo.md

@ -0,0 +1,7 @@
- genre graph
- convert to bar graph
- sizing
- ordering
- loading/progress indicator
- change js tabs to 2 spaces
- Heroku?

4
upgrade-pip-reqs.sh

@ -0,0 +1,4 @@
#!/bin/bash
pip list --outdated --format=freeze | grep -v '^\-e' | cut -d = -f 1 | xargs -n1 pip install -U
pip freeze --local > requirements.txt
Loading…
Cancel
Save