added current tasks view

This commit is contained in:
aj 2019-10-20 21:07:13 +01:00
parent f22eb5d8bd
commit c3d1f9e9b0
6 changed files with 140 additions and 1 deletions

View File

@ -3,3 +3,4 @@ from .player import blueprint as player_blueprint
from .fm import blueprint as fm_blueprint from .fm import blueprint as fm_blueprint
from .spotfm import blueprint as spotfm_blueprint from .spotfm import blueprint as spotfm_blueprint
from .spotify import blueprint as spotify_blueprint from .spotify import blueprint as spotify_blueprint
from .admin import blueprint as admin_blueprint

43
music/api/admin.py Normal file
View File

@ -0,0 +1,43 @@
from flask import Blueprint, jsonify
import logging
from datetime import datetime
from google.cloud import firestore
from google.cloud import tasks_v2
from music.api.decorators import login_or_basic_auth, admin_required
blueprint = Blueprint('admin-api', __name__)
db = firestore.Client()
tasker = tasks_v2.CloudTasksClient()
task_path = tasker.queue_path('sarsooxyz', 'europe-west2', 'spotify-executions')
logger = logging.getLogger(__name__)
@blueprint.route('/tasks', methods=['GET'])
@login_or_basic_auth
@admin_required
def get_tasks(username=None):
tasks = [i for i in tasker.list_tasks(task_path)]
urls = {}
for task in tasks:
if urls.get(task.app_engine_http_request.relative_uri):
urls[task.app_engine_http_request.relative_uri] += 1
else:
urls[task.app_engine_http_request.relative_uri] = 1
response = {
'tasks': [{
'url': i,
'count': j,
'scheduled_times': [datetime.fromtimestamp(k.schedule_time.seconds) for k in tasks
if k.app_engine_http_request.relative_uri == i]
} for i, j in urls.items()],
'total_tasks': len(tasks),
}
return jsonify(response), 200

View File

@ -4,7 +4,8 @@ from google.cloud import firestore
import os import os
from music.auth import auth_blueprint from music.auth import auth_blueprint
from music.api import api_blueprint, player_blueprint, fm_blueprint, spotfm_blueprint, spotify_blueprint from music.api import api_blueprint, player_blueprint, fm_blueprint, \
spotfm_blueprint, spotify_blueprint, admin_blueprint
db = firestore.Client() db = firestore.Client()
@ -16,6 +17,7 @@ app.register_blueprint(player_blueprint, url_prefix='/api/player')
app.register_blueprint(fm_blueprint, url_prefix='/api/fm') app.register_blueprint(fm_blueprint, url_prefix='/api/fm')
app.register_blueprint(spotfm_blueprint, url_prefix='/api/spotfm') app.register_blueprint(spotfm_blueprint, url_prefix='/api/spotfm')
app.register_blueprint(spotify_blueprint, url_prefix='/api/spotify') app.register_blueprint(spotify_blueprint, url_prefix='/api/spotify')
app.register_blueprint(admin_blueprint, url_prefix='/api/admin')
@app.route('/') @app.route('/')

View File

@ -4,6 +4,7 @@ const axios = require('axios');
import Lock from "./Lock.js"; import Lock from "./Lock.js";
import Functions from "./Functions.js"; import Functions from "./Functions.js";
import Tasks from "./Tasks.js";
class Admin extends Component { class Admin extends Component {
render(){ render(){
@ -12,10 +13,12 @@ class Admin extends Component {
<ul className="navbar" style={{width: "100%"}}> <ul className="navbar" style={{width: "100%"}}>
<li><Link to={`${this.props.match.url}/lock`}>lock accounts</Link></li> <li><Link to={`${this.props.match.url}/lock`}>lock accounts</Link></li>
<li><Link to={`${this.props.match.url}/functions`}>functions</Link></li> <li><Link to={`${this.props.match.url}/functions`}>functions</Link></li>
<li><Link to={`${this.props.match.url}/tasks`}>tasks</Link></li>
</ul> </ul>
<Route path={`${this.props.match.url}/lock`} component={Lock} /> <Route path={`${this.props.match.url}/lock`} component={Lock} />
<Route path={`${this.props.match.url}/functions`} component={Functions} /> <Route path={`${this.props.match.url}/functions`} component={Functions} />
<Route path={`${this.props.match.url}/tasks`} component={Tasks} />
</div> </div>
); );

View File

@ -9,10 +9,24 @@ class Functions extends Component {
super(props); super(props);
this.runAllUsers = this.runAllUsers.bind(this); this.runAllUsers = this.runAllUsers.bind(this);
this.runStats = this.runStats.bind(this);
} }
runAllUsers(event){ runAllUsers(event){
axios.get('/api/playlist/run/users') axios.get('/api/playlist/run/users')
.then((response) => {
showMessage('users run');
})
.catch((error) => {
showMessage(`error running all users (${error.response.status})`);
});
}
runStats(event){
axios.get('/api/spotfm/playlist/refresh/users')
.then((response) => {
showMessage('stats run');
})
.catch((error) => { .catch((error) => {
showMessage(`error running all users (${error.response.status})`); showMessage(`error running all users (${error.response.status})`);
}); });
@ -34,6 +48,11 @@ class Functions extends Component {
<button className="full-width button" onClick={this.runAllUsers}>run all users</button> <button className="full-width button" onClick={this.runAllUsers}>run all users</button>
</td> </td>
</tr> </tr>
<tr>
<td>
<button className="full-width button" onClick={this.runStats}>run stats</button>
</td>
</tr>
</tbody> </tbody>
</table>); </table>);
} }

71
src/js/Admin/Tasks.js Normal file
View File

@ -0,0 +1,71 @@
import React, { Component } from "react";
const axios = require('axios');
import showMessage from "../Toast.js"
class Tasks extends Component {
constructor(props){
super(props);
this.state = {
total_tasks: 0,
tasks: [],
schedule_times: []
}
this.getTasks();
}
getTasks(){
var self = this;
axios.get('/api/admin/tasks')
.then((response) => {
self.setState({
total_tasks: response.data.total_tasks,
tasks: response.data.tasks
});
})
.catch((error) => {
showMessage(`error getting tasks (${error.response.status})`);
});
}
render () {
return (
<table className="app-table max-width">
<thead>
<tr>
<th>
<h1 className="text-no-select full-width center-text ui-text">running tasks</h1>
</th>
</tr>
</thead>
{ this.state.tasks.map((entry) => <TaskType url={entry.url} count={entry.count} times={entry.scheduled_times} key={entry.url}/>)}
<tbody>
<tr>
<td className="text-no-select full-width center-text ui-text" colSpan='2'>
<b>{this.state.total_tasks}</b> running tasks
</td>
</tr>
</tbody>
</table>);
}
}
function TaskType(props) {
return (
<tbody>
<tr>
<td className="text-no-select full-width center-text ui-text" colSpan='2'>
{props.url}: {props.count}
</td>
</tr>
{props.times.map((entry) => <tr key={entry}>
<td colSpan='2' className="text-no-select full-width center-text ui-text">
{entry}
</td>
</tr>)}
</tbody>
);
}
export default Tasks;