Add stats about the library
This commit is contained in:
parent
dec9547152
commit
eb02ff2b46
57
src/internal/admins/stats.go
Normal file
57
src/internal/admins/stats.go
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
package admin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/web"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
moviesCountQuery = `SELECT COUNT(*) FROM movies;`
|
||||||
|
showsCountQuery = `SELECT COUNT(*) FROM shows;`
|
||||||
|
episodesCountQuery = `SELECT COUNT(*) FROM episodes;`
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetCount gets the count from a query
|
||||||
|
func GetCount(db *sqlx.DB, query string) (int, error) {
|
||||||
|
var count int
|
||||||
|
err := db.QueryRow(query).Scan(&count)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return count, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetStatsHandler returns the stats of the app
|
||||||
|
func GetStatsHandler(env *web.Env, w http.ResponseWriter, r *http.Request) error {
|
||||||
|
log := env.Log.WithFields(logrus.Fields{
|
||||||
|
"function": "admin.GetStatsHandler",
|
||||||
|
})
|
||||||
|
|
||||||
|
log.Debug("getting stats")
|
||||||
|
|
||||||
|
stats := struct {
|
||||||
|
MoviesCount int `json:"movies_count"`
|
||||||
|
ShowsCount int `json:"shows_count"`
|
||||||
|
EpisodesCount int `json:"episodes_count"`
|
||||||
|
}{}
|
||||||
|
|
||||||
|
for _, s := range []struct {
|
||||||
|
query string
|
||||||
|
ptr *int
|
||||||
|
}{
|
||||||
|
{moviesCountQuery, &stats.MoviesCount},
|
||||||
|
{showsCountQuery, &stats.ShowsCount},
|
||||||
|
{episodesCountQuery, &stats.EpisodesCount},
|
||||||
|
} {
|
||||||
|
var err error
|
||||||
|
*s.ptr, err = GetCount(env.Database, s.query)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return env.RenderJSON(w, stats)
|
||||||
|
}
|
@ -7,6 +7,13 @@ export function getUsers() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getStats() {
|
||||||
|
return request(
|
||||||
|
"ADMIN_GET_STATS",
|
||||||
|
configureAxios().get("/admins/stats")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
export function updateUser(data) {
|
export function updateUser(data) {
|
||||||
return request(
|
return request(
|
||||||
"ADMIN_UPDATE_USER",
|
"ADMIN_UPDATE_USER",
|
||||||
|
@ -4,10 +4,12 @@ import { bindActionCreators } from "redux"
|
|||||||
import { updateUser } from "../../actions/admins"
|
import { updateUser } from "../../actions/admins"
|
||||||
|
|
||||||
import UserList from "./users"
|
import UserList from "./users"
|
||||||
|
import Stats from "./stats"
|
||||||
|
|
||||||
function mapStateToProps(state) {
|
function mapStateToProps(state) {
|
||||||
return {
|
return {
|
||||||
users : state.adminStore.get("users"),
|
users : state.adminStore.get("users"),
|
||||||
|
stats : state.adminStore.get("stats"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
const mapDispatchToProps = (dipatch) =>
|
const mapDispatchToProps = (dipatch) =>
|
||||||
@ -15,10 +17,15 @@ const mapDispatchToProps = (dipatch) =>
|
|||||||
|
|
||||||
function AdminPanel(props) {
|
function AdminPanel(props) {
|
||||||
return (
|
return (
|
||||||
|
<div>
|
||||||
|
<Stats
|
||||||
|
stats={props.stats}
|
||||||
|
/>
|
||||||
<UserList
|
<UserList
|
||||||
users={props.users}
|
users={props.users}
|
||||||
updateUser={props.updateUser}
|
updateUser={props.updateUser}
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
27
src/public/js/components/admins/stats.js
Normal file
27
src/public/js/components/admins/stats.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import React from "react"
|
||||||
|
|
||||||
|
export default function Stats(props) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h2 className="hidden-xs">Stats</h2>
|
||||||
|
<Stat name="Movies" value={props.stats.get("movies_count")} />
|
||||||
|
<Stat name="Shows" value={props.stats.get("shows_count")} />
|
||||||
|
<Stat name="Episodes" value={props.stats.get("episodes_count")} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function Stat(props) {
|
||||||
|
return (
|
||||||
|
<div className="col-xs-4">
|
||||||
|
<div className="panel panel-default">
|
||||||
|
<div className="panel-heading">
|
||||||
|
<h3 className="panel-title">{props.name}</h3>
|
||||||
|
</div>
|
||||||
|
<div className="panel-body">
|
||||||
|
{props.value}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
@ -2,10 +2,12 @@ import { Map, List, fromJS } from "immutable"
|
|||||||
|
|
||||||
const defaultState = Map({
|
const defaultState = Map({
|
||||||
"users": List(),
|
"users": List(),
|
||||||
|
"stats": Map({}),
|
||||||
});
|
});
|
||||||
|
|
||||||
const handlers = {
|
const handlers = {
|
||||||
"ADMIN_LIST_USERS_FULFILLED": (state, action) => state.set("users", fromJS(action.payload.response.data)),
|
"ADMIN_LIST_USERS_FULFILLED": (state, action) => state.set("users", fromJS(action.payload.response.data)),
|
||||||
|
"ADMIN_GET_STATS_FULFILLED": (state, action) => state.set("stats", fromJS(action.payload.response.data)),
|
||||||
}
|
}
|
||||||
|
|
||||||
export default (state = defaultState, action) =>
|
export default (state = defaultState, action) =>
|
||||||
|
@ -12,7 +12,7 @@ import { fetchTorrents } from "./actions/torrents"
|
|||||||
import { userLogout, getUserInfos } from "./actions/users"
|
import { userLogout, getUserInfos } from "./actions/users"
|
||||||
import { fetchMovies, getMovieExploreOptions } from "./actions/movies"
|
import { fetchMovies, getMovieExploreOptions } from "./actions/movies"
|
||||||
import { fetchShows, fetchShowDetails, getShowExploreOptions } from "./actions/shows"
|
import { fetchShows, fetchShowDetails, getShowExploreOptions } from "./actions/shows"
|
||||||
import { getUsers } from "./actions/admins"
|
import { getUsers, getStats } from "./actions/admins"
|
||||||
|
|
||||||
import store from "./store"
|
import store from "./store"
|
||||||
|
|
||||||
@ -122,7 +122,7 @@ export default function getRoutes(App) {
|
|||||||
component: UserActivation,
|
component: UserActivation,
|
||||||
onEnter: function(nextState, replace, next) {
|
onEnter: function(nextState, replace, next) {
|
||||||
if (!isLoggedIn()) {
|
if (!isLoggedIn()) {
|
||||||
replace('/users/login');
|
replace("/users/login");
|
||||||
}
|
}
|
||||||
if (isActivated()) {
|
if (isActivated()) {
|
||||||
// User is already activated, redirect him to the default route
|
// User is already activated, redirect him to the default route
|
||||||
@ -254,6 +254,7 @@ export default function getRoutes(App) {
|
|||||||
onEnter: function(nextState, replace, next) {
|
onEnter: function(nextState, replace, next) {
|
||||||
adminCheck(nextState, replace, next, function() {
|
adminCheck(nextState, replace, next, function() {
|
||||||
store.dispatch(getUsers());
|
store.dispatch(getUsers());
|
||||||
|
store.dispatch(getStats());
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -61,4 +61,5 @@ func setupRoutes(env *web.Env) {
|
|||||||
// Admin routes
|
// Admin routes
|
||||||
env.Handle("/admins/users", admin.GetUsersHandler).WithRole(users.AdminRole).Methods("GET")
|
env.Handle("/admins/users", admin.GetUsersHandler).WithRole(users.AdminRole).Methods("GET")
|
||||||
env.Handle("/admins/users", admin.UpdateUserHandler).WithRole(users.AdminRole).Methods("POST")
|
env.Handle("/admins/users", admin.UpdateUserHandler).WithRole(users.AdminRole).Methods("POST")
|
||||||
|
env.Handle("/admins/stats", admin.GetStatsHandler).WithRole(users.AdminRole).Methods("GET")
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user