admin: redesign home page
This commit is contained in:
parent
4f237677e2
commit
cb97af2f8a
@ -26,6 +26,41 @@ const indextpl = `<!DOCTYPE html>
|
|||||||
.bg-wchoices {
|
.bg-wchoices {
|
||||||
background-color: #c07bdf !important;
|
background-color: #c07bdf !important;
|
||||||
}
|
}
|
||||||
|
.table th.frotated {
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
.table th.rotated {
|
||||||
|
height: 100px;
|
||||||
|
width: 40px;
|
||||||
|
min-width: 40px;
|
||||||
|
max-width: 40px;
|
||||||
|
position: relative;
|
||||||
|
vertical-align: bottom;
|
||||||
|
padding: 0;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 0.9;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
th.rotated > div {
|
||||||
|
position: relative;
|
||||||
|
top: 0px;
|
||||||
|
left: -50px;
|
||||||
|
height: 100%;
|
||||||
|
transform: skew(45deg,0deg);
|
||||||
|
overflow: hidden;
|
||||||
|
border: 1px solid #000;
|
||||||
|
}
|
||||||
|
th.rotated div a {
|
||||||
|
transform: skew(-45deg,0deg) rotate(45deg);
|
||||||
|
position: absolute;
|
||||||
|
bottom: 40px;
|
||||||
|
left: -35px;
|
||||||
|
display: inline-block;
|
||||||
|
width: 110px;
|
||||||
|
text-align: left;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
<base href="{{.urlbase}}">
|
<base href="{{.urlbase}}">
|
||||||
<script src="/js/d3.v3.min.js"></script>
|
<script src="/js/d3.v3.min.js"></script>
|
||||||
|
@ -63,6 +63,9 @@ func init() {
|
|||||||
api.Router().GET("/files/*_", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
api.Router().GET("/files/*_", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||||
http.ServeFile(w, r, path.Join(fic.FilesDir, strings.TrimPrefix(r.URL.Path, "/files")))
|
http.ServeFile(w, r, path.Join(fic.FilesDir, strings.TrimPrefix(r.URL.Path, "/files")))
|
||||||
})
|
})
|
||||||
|
api.Router().GET("/submissions/*_", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||||
|
http.ServeFile(w, r, path.Join(api.TimestampCheck, strings.TrimPrefix(r.URL.Path, "/submissions")))
|
||||||
|
})
|
||||||
api.Router().GET("/vids/*_", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
api.Router().GET("/vids/*_", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||||
if importer, ok := sync.GlobalImporter.(sync.LocalImporter); ok {
|
if importer, ok := sync.GlobalImporter.(sync.LocalImporter); ok {
|
||||||
http.ServeFile(w, r, path.Join(importer.Base, strings.TrimPrefix(r.URL.Path, "/vids")))
|
http.ServeFile(w, r, path.Join(importer.Base, strings.TrimPrefix(r.URL.Path, "/vids")))
|
||||||
|
@ -24,6 +24,41 @@
|
|||||||
.bg-wchoices {
|
.bg-wchoices {
|
||||||
background-color: #c07bdf !important;
|
background-color: #c07bdf !important;
|
||||||
}
|
}
|
||||||
|
.table th.frotated {
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
.table th.rotated {
|
||||||
|
height: 100px;
|
||||||
|
width: 40px;
|
||||||
|
min-width: 40px;
|
||||||
|
max-width: 40px;
|
||||||
|
position: relative;
|
||||||
|
vertical-align: bottom;
|
||||||
|
padding: 0;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 0.9;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
th.rotated > div {
|
||||||
|
position: relative;
|
||||||
|
top: 0px;
|
||||||
|
left: -50px;
|
||||||
|
height: 100%;
|
||||||
|
transform: skew(45deg,0deg);
|
||||||
|
overflow: hidden;
|
||||||
|
border: 1px solid #000;
|
||||||
|
}
|
||||||
|
th.rotated div a {
|
||||||
|
transform: skew(-45deg,0deg) rotate(45deg);
|
||||||
|
position: absolute;
|
||||||
|
bottom: 40px;
|
||||||
|
left: -35px;
|
||||||
|
display: inline-block;
|
||||||
|
width: 110px;
|
||||||
|
text-align: left;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
<base href="/admin/">
|
<base href="/admin/">
|
||||||
<script src="/js/d3.v3.min.js"></script>
|
<script src="/js/d3.v3.min.js"></script>
|
||||||
|
@ -2000,6 +2000,16 @@ angular.module("FICApp")
|
|||||||
solvedByThemesPie("#pieThemes", themes);
|
solvedByThemesPie("#pieThemes", themes);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
.controller("TeamsJSONController", function($scope, Teams) {
|
||||||
|
$scope.teams = Teams.get();
|
||||||
|
$scope.teams.$promise.then(function(teams) {
|
||||||
|
$scope.rank = [];
|
||||||
|
Object.keys(teams).forEach(function(team) {
|
||||||
|
$scope.teams[team].id = team;
|
||||||
|
$scope.rank.push($scope.teams[team]);
|
||||||
|
})
|
||||||
|
});
|
||||||
|
})
|
||||||
.controller("TeamExercicesController", function($scope, Teams, Themes, TeamMy, Exercice, $routeParams) {
|
.controller("TeamExercicesController", function($scope, Teams, Themes, TeamMy, Exercice, $routeParams) {
|
||||||
$scope.teams = Teams.get();
|
$scope.teams = Teams.get();
|
||||||
$scope.themes = Themes.get();
|
$scope.themes = Themes.get();
|
||||||
|
@ -6,19 +6,76 @@
|
|||||||
Version de l'API : {{ v.version }}
|
Version de l'API : {{ v.version }}
|
||||||
</p>
|
</p>
|
||||||
<p ng-controller="TimestampController">
|
<p ng-controller="TimestampController">
|
||||||
Latence frontend-backend : <ng-pluralize count="t.diffFB / 1000000000" when="{'one': '{} seconde', 'other': '{} secondes'}"></ng-pluralize><br>
|
Latence frontend-backend : <span ng-class="{'text-success': t.diffFB <= 1000000000, 'text-warning': t.diffFB > 1000000000, 'text-danger': t.diffFB > 1500000000}"><ng-pluralize count="t.diffFB / 1000000000" when="{'one': '{} seconde', 'other': '{} secondes'}"></ng-pluralize></span><br>
|
||||||
Dernière synchronisation du frontend : {{ t.frontend | date:"mediumTime" }}
|
Dernière synchronisation du frontend : {{ t.frontend | date:"mediumTime" }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col">
|
<div class="col">
|
||||||
|
Problèmes dans les fichiers :
|
||||||
<ul ng-controller="HealthController">
|
<ul ng-controller="HealthController">
|
||||||
|
<li ng-if="!health.length">Rien de problématique pour l'instant</li>
|
||||||
<li ng-repeat="heal in health">
|
<li ng-repeat="heal in health">
|
||||||
<a ng-href="teams/{{ heal.id_team }}" ng-if="heal.id_team">{{ heal.path }}</a>
|
<a ng-href="teams/{{ heal.id_team }}" ng-if="heal.id_team" class="text-warning">/{{ heal.path.split("/")[1] }}</a><a target="_blank" ng-href="submissions{{ heal.path }}" ng-if="heal.id_team">/{{ heal.path.split("/")[2] }}</a>
|
||||||
<span ng-if="!heal.id_team">{{ heal.path }}</span>
|
<a ng-href="submissions{{ heal.path }}" ng-if="!heal.id_team">{{ heal.path }}</a>
|
||||||
: {{ heal.error }}
|
: {{ heal.error }}
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="card-deck mb-3">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h4>Progression</h4>
|
||||||
|
</div>
|
||||||
|
<table class="table table-hover table-striped table-sm" ng-controller="ThemesListController">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="frotated"></th>
|
||||||
|
<th class="rotated" ng-repeat="(tid,th) in themes"><div><a ng-href="themes/{{ th.id }}">{{ th.name }}</a></div></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody class="table-bordered">
|
||||||
|
<tr ng-repeat="lvl in [1,2,3,4,5]">
|
||||||
|
<th class="text-center"><nobr>Challenge {{ lvl }}</nobr></th>
|
||||||
|
<td ng-repeat="(tid,theme) in themes" class="text-center text-bold" ng-controller="ExercicesStatsController">
|
||||||
|
<a ng-href="exercices/{{ exercice.id_exercice }}" ng-repeat="exercice in exercices" ng-if="$index == lvl-1 && (exercice.team_tries || lvl == 1)" ng-class="{'text-primary': exercice.solved_count == 0, 'text-success': exercice.solved_count >= 1, 'text-bold': exercice.solved_count >= 1, 'text-warning': exercice.solved_count == 0 && exercice.team_tries}">
|
||||||
|
<span ng-if="exercice.solved_count">{{ exercice.solved_count }}</span>
|
||||||
|
<span ng-if="!exercice.solved_count">{{ exercice.team_tries }}</span>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
<tfoot ng-if="s.params.total" ng-init="team={id:0}">
|
||||||
|
<tr ng-controller="TeamController">
|
||||||
|
<td class="text-right text-light">
|
||||||
|
<span ng-if="s.params.kind == 'levels'"><span class="badge badge-success"> </span> Résolus</span>
|
||||||
|
<span ng-if="s.params.kind == 'teams'">Total résolus</span><br>
|
||||||
|
<span class="badge badge-warning"> </span> Tentatives
|
||||||
|
</td>
|
||||||
|
<td class="table-bordered bg-dark" ng-repeat="(tid,th) in themes" class="text-center" ng-if="mystats && s.params.themes.indexOf(tid-0) !== -1">
|
||||||
|
<strong>{{ mystats.themes[tid].solved }}</strong><br>
|
||||||
|
{{ mystats.themes[tid].tries }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h4>Classement</h4>
|
||||||
|
</div>
|
||||||
|
<table class="table table-hover table-striped table-sm" ng-controller="TeamsJSONController">
|
||||||
|
<tbody>
|
||||||
|
<tr ng-repeat="team in rank | orderBy:'rank'" ng-if="team.rank">
|
||||||
|
<td>{{ team.rank }}</td>
|
||||||
|
<td><a ng-href="teams/{{ team.id }}">{{ team.name }}</td>
|
||||||
|
<td>{{ team.score | number:0 }}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user