added current tasks view
This commit is contained in:
parent
f22eb5d8bd
commit
c3d1f9e9b0
@ -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
43
music/api/admin.py
Normal 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
|
@ -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('/')
|
||||||
|
@ -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>
|
||||||
);
|
);
|
||||||
|
@ -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
71
src/js/Admin/Tasks.js
Normal 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;
|
Loading…
Reference in New Issue
Block a user