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::
|
.. toctree::
|
||||||
:maxdepth: 1
|
:maxdepth: 2
|
||||||
:caption: Contents:
|
:caption: Contents:
|
||||||
|
|
||||||
Modules <src/modules>
|
Py <src/music>
|
||||||
src/music
|
Js <src/MusicTools>
|
||||||
src/music.api
|
All Modules <src/modules>
|
||||||
src/music.auth
|
|
||||||
src/music.cloud
|
|
||||||
src/music.db
|
|
||||||
src/music.model
|
|
||||||
src/music.tasks
|
|
||||||
src/MusicTools
|
|
||||||
|
|
||||||
`Music Tools <https://music.sarsoo.xyz>`_
|
`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.
|
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
|
.. 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:
|
:members:
|
||||||
:private-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
|
.. js:autoclass:: PlaylistsView
|
||||||
@ -32,14 +38,7 @@ New Playlist Card
|
|||||||
:members:
|
:members:
|
||||||
:private-members:
|
:private-members:
|
||||||
|
|
||||||
Playlist Router
|
View/Edit Card
|
||||||
------------------
|
|
||||||
|
|
||||||
.. js:autoclass:: PlaylistRouter.View
|
|
||||||
:members:
|
|
||||||
:private-members:
|
|
||||||
|
|
||||||
Playlist View
|
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
.. js:autoclass:: Edit
|
.. js:autoclass:: Edit
|
||||||
@ -52,7 +51,7 @@ Playlist View
|
|||||||
|
|
||||||
.. js:autofunction:: Edit.BlockGridItem
|
.. js:autofunction:: Edit.BlockGridItem
|
||||||
|
|
||||||
Playlist Stats View
|
Stats Card
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
.. js:autoclass:: Count
|
.. 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:
|
:members:
|
||||||
:private-members:
|
:private-members:
|
||||||
|
|
||||||
Tags List
|
Cards List
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
.. js:autoclass:: TagList
|
.. js:autoclass:: TagList
|
||||||
@ -28,3 +28,10 @@ New Tag Card
|
|||||||
:members:
|
:members:
|
||||||
:private-members:
|
:private-members:
|
||||||
|
|
||||||
|
View/Edit Tag
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
.. js:autoclass:: TagView
|
||||||
|
:members:
|
||||||
|
:private-members:
|
||||||
|
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
Music Tools React
|
React Frontend
|
||||||
===================
|
===================
|
||||||
|
|
||||||
Subpackages
|
|
||||||
-----------
|
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 4
|
:maxdepth: 4
|
||||||
|
|
||||||
MusicTools.MusicTools
|
|
||||||
MusicTools.Playlist
|
MusicTools.Playlist
|
||||||
MusicTools.Tag
|
MusicTools.Tag
|
||||||
|
MusicTools.Maths
|
||||||
|
MusicTools.Admin
|
||||||
|
MusicTools.Settings
|
||||||
|
|
||||||
|
.. js:autoclass:: MusicTools
|
||||||
|
:members:
|
||||||
|
:private-members:
|
@ -1,5 +1,5 @@
|
|||||||
music
|
Music Tools Modules
|
||||||
=====
|
======================
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 4
|
:maxdepth: 4
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
music
|
Flask Backend
|
||||||
=============
|
====================
|
||||||
|
|
||||||
Subpackages
|
|
||||||
-----------
|
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 4
|
:maxdepth: 4
|
||||||
@ -14,17 +11,14 @@ Subpackages
|
|||||||
music.model
|
music.model
|
||||||
music.tasks
|
music.tasks
|
||||||
|
|
||||||
Module contents
|
music Root Module
|
||||||
---------------
|
------------------
|
||||||
|
|
||||||
.. automodule:: music
|
.. automodule:: music
|
||||||
:members:
|
:members:
|
||||||
:undoc-members:
|
:undoc-members:
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
|
||||||
music.music module
|
|
||||||
------------------
|
|
||||||
|
|
||||||
.. automodule:: music.music
|
.. automodule:: music.music
|
||||||
:members:
|
:members:
|
||||||
:undoc-members:
|
:undoc-members:
|
||||||
|
@ -91,7 +91,7 @@ class Lock extends Component {
|
|||||||
/**
|
/**
|
||||||
* Grid of account cards with lock buttons
|
* Grid of account cards with lock buttons
|
||||||
* @param {*} props
|
* @param {*} props
|
||||||
* @returns
|
* @returns Card component wrapped in grid cell
|
||||||
*/
|
*/
|
||||||
function Row(props){
|
function Row(props){
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
|
@ -53,7 +53,7 @@ class Tasks extends Component {
|
|||||||
/**
|
/**
|
||||||
* Grid of task cards
|
* Grid of task cards
|
||||||
* @param {*} props
|
* @param {*} props
|
||||||
* @returns
|
* @returns Card compnent wrapped in grid cell
|
||||||
*/
|
*/
|
||||||
function TaskType(props) {
|
function TaskType(props) {
|
||||||
return (
|
return (
|
||||||
|
@ -3,6 +3,9 @@ import { Chart, BarElement, BarController, LinearScale, CategoryScale, Legend, T
|
|||||||
|
|
||||||
Chart.register(BarElement, BarController, LinearScale, CategoryScale, Legend, Title, Tooltip);
|
Chart.register(BarElement, BarController, LinearScale, CategoryScale, Legend, Title, Tooltip);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bar chart component using Chart.js
|
||||||
|
*/
|
||||||
class BarChart extends Component {
|
class BarChart extends Component {
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@ -10,6 +13,9 @@ class BarChart extends Component {
|
|||||||
this.chartRef = React.createRef();
|
this.chartRef = React.createRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load data from react properties
|
||||||
|
*/
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.chart = new Chart(this.chartRef.current, {
|
this.chart = new Chart(this.chartRef.current, {
|
||||||
type: 'bar',
|
type: 'bar',
|
||||||
@ -43,7 +49,7 @@ class BarChart extends Component {
|
|||||||
ticks: {
|
ticks: {
|
||||||
color: "#d8d8d8",
|
color: "#d8d8d8",
|
||||||
font: {
|
font: {
|
||||||
size: 20
|
size: 16
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -59,7 +65,10 @@ class BarChart extends Component {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Re-apply data to chart on update
|
||||||
|
*/
|
||||||
componentDidUpdate() {
|
componentDidUpdate() {
|
||||||
this.chart.data.labels = this.props.data.map(d => d.label);
|
this.chart.data.labels = this.props.data.map(d => d.label);
|
||||||
this.chart.data.datasets[0].data = this.props.data.map(d => d.value);
|
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, 31, 235)', //pink
|
||||||
'rgb(242, 164, 31)'];
|
'rgb(242, 164, 31)'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pie chart component using Chart.js
|
||||||
|
*/
|
||||||
class PieChart extends Component {
|
class PieChart extends Component {
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@ -18,6 +21,9 @@ class PieChart extends Component {
|
|||||||
this.chartRef = React.createRef();
|
this.chartRef = React.createRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load data from react properties
|
||||||
|
*/
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.chart = new Chart(this.chartRef.current, {
|
this.chart = new Chart(this.chartRef.current, {
|
||||||
type: 'doughnut',
|
type: 'doughnut',
|
||||||
@ -52,6 +58,9 @@ class PieChart extends Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Re-apply data to chart on update
|
||||||
|
*/
|
||||||
componentDidUpdate() {
|
componentDidUpdate() {
|
||||||
this.chart.data.labels = this.props.data.map(d => d.label);
|
this.chart.data.labels = this.props.data.map(d => d.label);
|
||||||
this.chart.data.datasets[0].data = this.props.data.map(d => d.value);
|
this.chart.data.datasets[0].data = this.props.data.map(d => d.value);
|
||||||
|
@ -129,7 +129,7 @@ function TagCard(props){
|
|||||||
{/* COUNT */}
|
{/* COUNT */}
|
||||||
{'count' in props.tag &&
|
{'count' in props.tag &&
|
||||||
<Typography variant="h6" style={{color: "#b3b3b3"}}>
|
<Typography variant="h6" style={{color: "#b3b3b3"}}>
|
||||||
{ props.tag.count }
|
{ props.tag.count.toLocaleString("en-GB") }
|
||||||
</Typography>
|
</Typography>
|
||||||
}
|
}
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
@ -20,7 +20,7 @@ const useStyles = makeStyles({
|
|||||||
/**
|
/**
|
||||||
* Tag View card
|
* Tag View card
|
||||||
*/
|
*/
|
||||||
class View extends Component{
|
class TagView extends Component{
|
||||||
|
|
||||||
constructor(props){
|
constructor(props){
|
||||||
super(props);
|
super(props);
|
||||||
@ -221,7 +221,7 @@ class View extends Component{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate input, make tag part add request of API
|
* Validate input, make tag part add request of API
|
||||||
* @returns
|
* @returns Nothing
|
||||||
*/
|
*/
|
||||||
handleAdd(){
|
handleAdd(){
|
||||||
|
|
||||||
@ -298,7 +298,7 @@ class View extends Component{
|
|||||||
|
|
||||||
var all = [...this.state.tag.artists, ...this.state.tag.albums, ...this.state.tag.tracks];
|
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 {
|
return {
|
||||||
"label": entry.name,
|
"label": entry.name,
|
||||||
"value": entry.count
|
"value": entry.count
|
||||||
@ -309,6 +309,17 @@ class View extends Component{
|
|||||||
return 0;
|
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 = (
|
const table = (
|
||||||
<div style={{maxWidth: '1000px', margin: 'auto', marginTop: '20px'}}>
|
<div style={{maxWidth: '1000px', margin: 'auto', marginTop: '20px'}}>
|
||||||
<Card align="center">
|
<Card align="center">
|
||||||
@ -394,13 +405,21 @@ class View extends Component{
|
|||||||
|
|
||||||
{/* PIE CHART */}
|
{/* PIE CHART */}
|
||||||
<Grid item xs={12}>
|
<Grid item xs={12}>
|
||||||
<PieChart data={data} padding={100}/>
|
<PieChart data={scrobbleData} padding={50}/>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
{/* BAR CHART */}
|
{/* SCROBBLE BAR CHART */}
|
||||||
<Grid item xs={12}>
|
<Grid item xs={12}>
|
||||||
<BarChart data={data} title='scrobbles' indexAxis='y'/>
|
<BarChart data={scrobbleData} title='plays (scrobbles)' indexAxis='y'/>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
|
{/* TIME BAR CHART */}
|
||||||
|
{ this.state.tag.time_objects &&
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<BarChart data={timeData} title='time listened (hours)' indexAxis='y'/>
|
||||||
|
</Grid>
|
||||||
|
}
|
||||||
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
{/* UPDATE BUTTON */}
|
{/* UPDATE BUTTON */}
|
||||||
@ -415,7 +434,7 @@ class View extends Component{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default View;
|
export default TagView;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Grid component for holding artist/album/track cards
|
* Grid component for holding artist/album/track cards
|
||||||
@ -462,7 +481,7 @@ function BlockGridItem (props) {
|
|||||||
{/* SCROBBLE COUNT */}
|
{/* SCROBBLE COUNT */}
|
||||||
{ 'count' in props.music_obj &&
|
{ 'count' in props.music_obj &&
|
||||||
<Grid item xs={8}>
|
<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>
|
</Grid>
|
||||||
}
|
}
|
||||||
{/* TIME */}
|
{/* TIME */}
|
||||||
@ -500,7 +519,7 @@ function StatsCard (props) {
|
|||||||
|
|
||||||
{/* SCROBBLE COUNT */}
|
{/* SCROBBLE COUNT */}
|
||||||
<Grid item xs={12}>
|
<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>
|
</Grid>
|
||||||
|
|
||||||
{/* PERCENT */}
|
{/* PERCENT */}
|
||||||
|
Loading…
Reference in New Issue
Block a user