added time bar chart, included all Js docs in sphinx
This commit is contained in:
parent
4fc4676041
commit
e64d0e2cd8
@ -2,18 +2,12 @@ Music Tools
|
||||
=======================================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:maxdepth: 2
|
||||
:caption: Contents:
|
||||
|
||||
Modules <src/modules>
|
||||
src/music
|
||||
src/music.api
|
||||
src/music.auth
|
||||
src/music.cloud
|
||||
src/music.db
|
||||
src/music.model
|
||||
src/music.tasks
|
||||
src/MusicTools
|
||||
Py <src/music>
|
||||
Js <src/MusicTools>
|
||||
All Modules <src/modules>
|
||||
|
||||
`Music Tools <https://music.sarsoo.xyz>`_
|
||||
----------------------------------------------
|
||||
@ -22,7 +16,7 @@ Music Tools
|
||||
|
||||
Music Tools is a web app for creating smart Spotify playlists. The app is based on `spotframework <https://github.com/Sarsoo/spotframework>`_ and `fmframework <https://github.com/Sarsoo/pyfmframework>`_ for interfacing with Spotify and Last.fm. The app is currently hosted on Google's Cloud Platform.
|
||||
|
||||
The system is composed of a Flask web server with a Fireo ORM layer and longer tasks dispatched to Cloud Tasks or Functions.
|
||||
The backend is composed of a Flask web server with a Fireo ORM layer and longer tasks dispatched to Cloud Tasks or Functions. The frontend is a React app with material UI components and Axios for HTTP requests.
|
||||
|
||||
.. image:: Playlists.png
|
||||
|
||||
|
34
docs/src/MusicTools.Admin.rst
Normal file
34
docs/src/MusicTools.Admin.rst
Normal file
@ -0,0 +1,34 @@
|
||||
Admin
|
||||
=================
|
||||
|
||||
Router
|
||||
--------
|
||||
|
||||
.. js:autoclass:: Admin
|
||||
:members:
|
||||
:private-members:
|
||||
|
||||
Lock
|
||||
------------------
|
||||
|
||||
.. js:autoclass:: Lock
|
||||
:members:
|
||||
:private-members:
|
||||
|
||||
.. js:autofunction:: Row
|
||||
|
||||
Functions
|
||||
--------------------
|
||||
|
||||
.. js:autoclass:: Functions
|
||||
:members:
|
||||
:private-members:
|
||||
|
||||
Tasks
|
||||
--------------------
|
||||
|
||||
.. js:autoclass:: Tasks
|
||||
:members:
|
||||
:private-members:
|
||||
|
||||
.. js:autofunction:: TaskType
|
17
docs/src/MusicTools.Maths.rst
Normal file
17
docs/src/MusicTools.Maths.rst
Normal file
@ -0,0 +1,17 @@
|
||||
Maths
|
||||
=================
|
||||
|
||||
Bar Chart
|
||||
-----------------
|
||||
|
||||
.. js:autoclass:: BarChart
|
||||
:members:
|
||||
:private-members:
|
||||
|
||||
Pie Chart
|
||||
------------------
|
||||
|
||||
.. js:autoclass:: PieChart
|
||||
:members:
|
||||
:private-members:
|
||||
|
@ -1,6 +0,0 @@
|
||||
MusicTools
|
||||
=================
|
||||
|
||||
.. js:autoclass:: MusicTools
|
||||
:members:
|
||||
:private-members:
|
@ -8,7 +8,13 @@ Router
|
||||
:members:
|
||||
:private-members:
|
||||
|
||||
Playlists List
|
||||
For managing playlists list pages for diverting to new playlist page
|
||||
|
||||
.. js:autoclass:: PlaylistRouter.View
|
||||
:members:
|
||||
:private-members:
|
||||
|
||||
Cards List
|
||||
------------------
|
||||
|
||||
.. js:autoclass:: PlaylistsView
|
||||
@ -32,14 +38,7 @@ New Playlist Card
|
||||
:members:
|
||||
:private-members:
|
||||
|
||||
Playlist Router
|
||||
------------------
|
||||
|
||||
.. js:autoclass:: PlaylistRouter.View
|
||||
:members:
|
||||
:private-members:
|
||||
|
||||
Playlist View
|
||||
View/Edit Card
|
||||
------------------
|
||||
|
||||
.. js:autoclass:: Edit
|
||||
@ -52,7 +51,7 @@ Playlist View
|
||||
|
||||
.. js:autofunction:: Edit.BlockGridItem
|
||||
|
||||
Playlist Stats View
|
||||
Stats Card
|
||||
-----------------------
|
||||
|
||||
.. js:autoclass:: Count
|
||||
|
34
docs/src/MusicTools.Settings.rst
Normal file
34
docs/src/MusicTools.Settings.rst
Normal file
@ -0,0 +1,34 @@
|
||||
Settings
|
||||
=================
|
||||
|
||||
Router
|
||||
--------
|
||||
|
||||
.. js:autoclass:: Settings
|
||||
:members:
|
||||
:private-members:
|
||||
|
||||
Change Password
|
||||
------------------
|
||||
|
||||
.. js:autoclass:: ChangePassword
|
||||
:members:
|
||||
:private-members:
|
||||
|
||||
Spotify Link
|
||||
------------------
|
||||
|
||||
.. js:autoclass:: SpotifyLink
|
||||
:members:
|
||||
:private-members:
|
||||
|
||||
.. js:autofunction:: AuthButton
|
||||
|
||||
.. js:autofunction:: DeAuthButton
|
||||
|
||||
Last.fm Username
|
||||
------------------
|
||||
|
||||
.. js:autoclass:: LastFM
|
||||
:members:
|
||||
:private-members:
|
@ -8,7 +8,7 @@ Router
|
||||
:members:
|
||||
:private-members:
|
||||
|
||||
Tags List
|
||||
Cards List
|
||||
------------------
|
||||
|
||||
.. js:autoclass:: TagList
|
||||
@ -28,3 +28,10 @@ New Tag Card
|
||||
:members:
|
||||
:private-members:
|
||||
|
||||
View/Edit Tag
|
||||
--------------------
|
||||
|
||||
.. js:autoclass:: TagView
|
||||
:members:
|
||||
:private-members:
|
||||
|
||||
|
@ -1,13 +1,15 @@
|
||||
Music Tools React
|
||||
React Frontend
|
||||
===================
|
||||
|
||||
Subpackages
|
||||
-----------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 4
|
||||
|
||||
MusicTools.MusicTools
|
||||
MusicTools.Playlist
|
||||
MusicTools.Tag
|
||||
MusicTools.Maths
|
||||
MusicTools.Admin
|
||||
MusicTools.Settings
|
||||
|
||||
.. js:autoclass:: MusicTools
|
||||
:members:
|
||||
:private-members:
|
@ -1,5 +1,5 @@
|
||||
music
|
||||
=====
|
||||
Music Tools Modules
|
||||
======================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 4
|
||||
|
@ -1,8 +1,5 @@
|
||||
music
|
||||
=============
|
||||
|
||||
Subpackages
|
||||
-----------
|
||||
Flask Backend
|
||||
====================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 4
|
||||
@ -14,17 +11,14 @@ Subpackages
|
||||
music.model
|
||||
music.tasks
|
||||
|
||||
Module contents
|
||||
---------------
|
||||
music Root Module
|
||||
------------------
|
||||
|
||||
.. automodule:: music
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
music.music module
|
||||
------------------
|
||||
|
||||
.. automodule:: music.music
|
||||
:members:
|
||||
:undoc-members:
|
||||
|
@ -91,7 +91,7 @@ class Lock extends Component {
|
||||
/**
|
||||
* Grid of account cards with lock buttons
|
||||
* @param {*} props
|
||||
* @returns
|
||||
* @returns Card component wrapped in grid cell
|
||||
*/
|
||||
function Row(props){
|
||||
const classes = useStyles();
|
||||
|
@ -53,7 +53,7 @@ class Tasks extends Component {
|
||||
/**
|
||||
* Grid of task cards
|
||||
* @param {*} props
|
||||
* @returns
|
||||
* @returns Card compnent wrapped in grid cell
|
||||
*/
|
||||
function TaskType(props) {
|
||||
return (
|
||||
|
@ -3,6 +3,9 @@ import { Chart, BarElement, BarController, LinearScale, CategoryScale, Legend, T
|
||||
|
||||
Chart.register(BarElement, BarController, LinearScale, CategoryScale, Legend, Title, Tooltip);
|
||||
|
||||
/**
|
||||
* Bar chart component using Chart.js
|
||||
*/
|
||||
class BarChart extends Component {
|
||||
|
||||
constructor(props) {
|
||||
@ -10,6 +13,9 @@ class BarChart extends Component {
|
||||
this.chartRef = React.createRef();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load data from react properties
|
||||
*/
|
||||
componentDidMount() {
|
||||
this.chart = new Chart(this.chartRef.current, {
|
||||
type: 'bar',
|
||||
@ -43,7 +49,7 @@ class BarChart extends Component {
|
||||
ticks: {
|
||||
color: "#d8d8d8",
|
||||
font: {
|
||||
size: 20
|
||||
size: 16
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -59,7 +65,10 @@ class BarChart extends Component {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Re-apply data to chart on update
|
||||
*/
|
||||
componentDidUpdate() {
|
||||
this.chart.data.labels = this.props.data.map(d => d.label);
|
||||
this.chart.data.datasets[0].data = this.props.data.map(d => d.value);
|
||||
|
@ -11,6 +11,9 @@ var pieColours = ['rgb(55, 61, 255)', //blue
|
||||
'rgb(242, 31, 235)', //pink
|
||||
'rgb(242, 164, 31)'];
|
||||
|
||||
/**
|
||||
* Pie chart component using Chart.js
|
||||
*/
|
||||
class PieChart extends Component {
|
||||
|
||||
constructor(props) {
|
||||
@ -18,6 +21,9 @@ class PieChart extends Component {
|
||||
this.chartRef = React.createRef();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load data from react properties
|
||||
*/
|
||||
componentDidMount() {
|
||||
this.chart = new Chart(this.chartRef.current, {
|
||||
type: 'doughnut',
|
||||
@ -52,6 +58,9 @@ class PieChart extends Component {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-apply data to chart on update
|
||||
*/
|
||||
componentDidUpdate() {
|
||||
this.chart.data.labels = this.props.data.map(d => d.label);
|
||||
this.chart.data.datasets[0].data = this.props.data.map(d => d.value);
|
||||
|
@ -129,7 +129,7 @@ function TagCard(props){
|
||||
{/* COUNT */}
|
||||
{'count' in props.tag &&
|
||||
<Typography variant="h6" style={{color: "#b3b3b3"}}>
|
||||
{ props.tag.count }
|
||||
{ props.tag.count.toLocaleString("en-GB") }
|
||||
</Typography>
|
||||
}
|
||||
</CardContent>
|
||||
|
@ -20,7 +20,7 @@ const useStyles = makeStyles({
|
||||
/**
|
||||
* Tag View card
|
||||
*/
|
||||
class View extends Component{
|
||||
class TagView extends Component{
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
@ -221,7 +221,7 @@ class View extends Component{
|
||||
|
||||
/**
|
||||
* Validate input, make tag part add request of API
|
||||
* @returns
|
||||
* @returns Nothing
|
||||
*/
|
||||
handleAdd(){
|
||||
|
||||
@ -298,7 +298,7 @@ class View extends Component{
|
||||
|
||||
var all = [...this.state.tag.artists, ...this.state.tag.albums, ...this.state.tag.tracks];
|
||||
|
||||
var data = all.map((entry) => {
|
||||
var scrobbleData = all.map((entry) => {
|
||||
return {
|
||||
"label": entry.name,
|
||||
"value": entry.count
|
||||
@ -309,6 +309,17 @@ class View extends Component{
|
||||
return 0;
|
||||
});
|
||||
|
||||
var timeData = all.map((entry) => {
|
||||
return {
|
||||
"label": entry.name,
|
||||
"value": entry.time_ms / (1000 * 60 * 60)
|
||||
};
|
||||
}).sort((a, b) => {
|
||||
if(a.value < b.value) { return 1; }
|
||||
if(a.value > b.value) { return -1; }
|
||||
return 0;
|
||||
});
|
||||
|
||||
const table = (
|
||||
<div style={{maxWidth: '1000px', margin: 'auto', marginTop: '20px'}}>
|
||||
<Card align="center">
|
||||
@ -394,13 +405,21 @@ class View extends Component{
|
||||
|
||||
{/* PIE CHART */}
|
||||
<Grid item xs={12}>
|
||||
<PieChart data={data} padding={100}/>
|
||||
<PieChart data={scrobbleData} padding={50}/>
|
||||
</Grid>
|
||||
|
||||
{/* BAR CHART */}
|
||||
{/* SCROBBLE BAR CHART */}
|
||||
<Grid item xs={12}>
|
||||
<BarChart data={data} title='scrobbles' indexAxis='y'/>
|
||||
<BarChart data={scrobbleData} title='plays (scrobbles)' indexAxis='y'/>
|
||||
</Grid>
|
||||
|
||||
{/* TIME BAR CHART */}
|
||||
{ this.state.tag.time_objects &&
|
||||
<Grid item xs={12}>
|
||||
<BarChart data={timeData} title='time listened (hours)' indexAxis='y'/>
|
||||
</Grid>
|
||||
}
|
||||
|
||||
</Grid>
|
||||
</CardContent>
|
||||
{/* UPDATE BUTTON */}
|
||||
@ -415,7 +434,7 @@ class View extends Component{
|
||||
}
|
||||
}
|
||||
|
||||
export default View;
|
||||
export default TagView;
|
||||
|
||||
/**
|
||||
* Grid component for holding artist/album/track cards
|
||||
@ -462,7 +481,7 @@ function BlockGridItem (props) {
|
||||
{/* SCROBBLE COUNT */}
|
||||
{ 'count' in props.music_obj &&
|
||||
<Grid item xs={8}>
|
||||
<Typography variant="h4" color="textPrimary" className={classes.root}>📈 { props.music_obj.count }</Typography>
|
||||
<Typography variant="h4" color="textPrimary" className={classes.root}>📈 { props.music_obj.count.toLocaleString("en-GB") }</Typography>
|
||||
</Grid>
|
||||
}
|
||||
{/* TIME */}
|
||||
@ -500,7 +519,7 @@ function StatsCard (props) {
|
||||
|
||||
{/* SCROBBLE COUNT */}
|
||||
<Grid item xs={12}>
|
||||
<Typography variant="h1" color="textPrimary" className={classes.root}>📈 { props.count }</Typography>
|
||||
<Typography variant="h1" color="textPrimary" className={classes.root}>📈 { props.count.toLocaleString("en-GB") }</Typography>
|
||||
</Grid>
|
||||
|
||||
{/* PERCENT */}
|
||||
|
Loading…
Reference in New Issue
Block a user