frontend: add players possibility to report problems with exercices
This commit is contained in:
parent
32dc9c1a8c
commit
9186bbc229
13 changed files with 206 additions and 0 deletions
21
frontend/issue.go
Normal file
21
frontend/issue.go
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"path"
|
||||
)
|
||||
|
||||
var acceptNewIssues bool = true
|
||||
|
||||
func IssueHandler(w http.ResponseWriter, r *http.Request, team string, sURL []string) {
|
||||
if !acceptNewIssues {
|
||||
log.Printf("UNHANDELED %s issue request from %s: %s [%s]\n", r.Method, r.RemoteAddr, r.URL.Path, r.UserAgent())
|
||||
http.Error(w, "{\"errmsg\":\"Il n'est pas possible de rapporter d'anomalie.\"}", http.StatusForbidden)
|
||||
} else if len(sURL) != 0 {
|
||||
http.Error(w, "{\"errmsg\":\"Arguments manquants.\"}", http.StatusBadRequest)
|
||||
} else if saveTeamFile(path.Join(team, "issue"), w, r) {
|
||||
// File enqueued for backend treatment
|
||||
http.Error(w, "{\"errmsg\":\"Anomalie signalée avec succès. Merci de votre patience...\"}", http.StatusAccepted)
|
||||
}
|
||||
}
|
||||
|
|
@ -47,6 +47,7 @@ func main() {
|
|||
|
||||
// Register handlers
|
||||
http.Handle(fmt.Sprintf("%s/chname/", *prefix), http.StripPrefix(fmt.Sprintf("%s/chname/", *prefix), submissionTeamChecker{"name change", ChNameHandler, *teamsDir}))
|
||||
http.Handle(fmt.Sprintf("%s/issue/", *prefix), http.StripPrefix(fmt.Sprintf("%s/issue/", *prefix), submissionTeamChecker{"issue", IssueHandler, *teamsDir}))
|
||||
http.Handle(fmt.Sprintf("%s/openhint/", *prefix), http.StripPrefix(fmt.Sprintf("%s/openhint/", *prefix), submissionTeamChecker{"opening hint", HintHandler, *teamsDir}))
|
||||
http.Handle(fmt.Sprintf("%s/wantchoices/", *prefix), http.StripPrefix(fmt.Sprintf("%s/wantchoices/", *prefix), submissionTeamChecker{"wantint choices", WantChoicesHandler, *teamsDir}))
|
||||
http.Handle(fmt.Sprintf("%s/registration/", *prefix), http.StripPrefix(fmt.Sprintf("%s/registration/", *prefix), submissionChecker{"registration", RegistrationHandler}))
|
||||
|
|
|
|||
|
|
@ -57,6 +57,14 @@ angular.module("FICApp", ["ngRoute", "ngSanitize"])
|
|||
controller: "MyTeamController",
|
||||
templateUrl: "views/team-edit.html"
|
||||
})
|
||||
.when("/issue", {
|
||||
controller: "IssueController",
|
||||
templateUrl: "views/issue.html"
|
||||
})
|
||||
.when("/issue/:eid", {
|
||||
controller: "IssueController",
|
||||
templateUrl: "views/issue.html"
|
||||
})
|
||||
.when("/rank", {
|
||||
controller: "RankController",
|
||||
templateUrl: "views/rank.html"
|
||||
|
|
@ -636,6 +644,42 @@ angular.module("FICApp", ["ngRoute", "ngSanitize"])
|
|||
});
|
||||
}
|
||||
})
|
||||
.controller("IssueController", function($scope, $http, $rootScope, $routeParams) {
|
||||
$rootScope.current_tag = undefined;
|
||||
$rootScope.current_exercice = $routeParams.eid;
|
||||
|
||||
$scope.issue = {
|
||||
id_exercice: parseInt($routeParams.eid, 10),
|
||||
subject: "",
|
||||
description: "",
|
||||
}
|
||||
|
||||
$scope.isubmit = function() {
|
||||
$rootScope.sberr = "";
|
||||
if ($scope.issue.subject.length < 3) {
|
||||
$rootScope.messageClass = {"text-danger": true};
|
||||
$rootScope.sberr = "L'object de votre rapport d'anomalie est trop court !";
|
||||
return false;
|
||||
}
|
||||
|
||||
$http({
|
||||
url: "submit/issue",
|
||||
method: "POST",
|
||||
data: $scope.issue
|
||||
}).then(function(response) {
|
||||
$rootScope.messageClass = {"text-success": true};
|
||||
$rootScope.message = response.data.errmsg;
|
||||
$scope.issue.subject = "";
|
||||
$scope.issue.description = "";
|
||||
}, function(response) {
|
||||
$rootScope.messageClass = {"text-danger": true};
|
||||
$rootScope.message = response.data.errmsg;
|
||||
if (response.status != 402) {
|
||||
$rootScope.sberr = "Une erreur est survenue lors de l'envoi. Veuillez réessayer dans quelques instants.";
|
||||
}
|
||||
});
|
||||
};
|
||||
})
|
||||
.controller("MyTeamController", function($scope, $http, $rootScope, $timeout, $location) {
|
||||
$rootScope.current_theme = 0;
|
||||
$rootScope.current_exercice = 0;
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
<p class="text-justify" ng-bind-html="themes[current_theme].intro"></p>
|
||||
</div>
|
||||
<div class="jumbotron niceborder text-indent mt-3" ng-if="(my.exercices[current_exercice])">
|
||||
<a ng-if="settings.acceptNewIssue" class="float-right btn btn-sm btn-warning" ng-href="issue/{{ current_exercice }}"><span class="glyphicon glyphicon-warning-sign" aria-hidden="true"></span> Rapporter une anomalie sur cet exercice</a>
|
||||
<h3 class="display-4">{{ themes[current_theme].exercices[current_exercice].title }}</h3>
|
||||
<a ng-href="tags/{{tag}}" class="badge badge-pill badge-secondary mr-2 mb-2" ng-repeat="tag in themes[current_theme].exercices[current_exercice].tags">#{{ tag }}</a>
|
||||
<p class="lead text-justify" ng-bind-html="my.exercices[current_exercice].statement"></p>
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
<p class="lead text-justify" ng-bind-html="my.exercices[current_exercice].statement"></p>
|
||||
<div class="alert alert-{{my.exercices[current_exercice].issuekind}}" ng-if="my.exercices[current_exercice].issue" ng-bind-html="my.exercices[current_exercice].issue"></div>
|
||||
<hr class="my-3">
|
||||
<a ng-if="settings.acceptNewIssue" class="float-right btn btn-sm btn-warning" ng-href="issue/{{ current_exercice }}"><span class="glyphicon glyphicon-warning-sign" aria-hidden="true"></span> Rapporter une anomalie sur cet exercice</a>
|
||||
<ul>
|
||||
<li><strong>Gain :</strong> <ng-pluralize count="themes[current_theme].exercices[current_exercice].gain" when="{'one': '{} point', 'other': '{} points'}"></ng-pluralize> <em ng-if="settings.firstBlood && themes[current_theme].exercices[current_exercice].solved < 1">{{ 1 + settings.firstBlood | coeff }} prem's</em> <em ng-if="themes[current_theme].exercices[current_exercice].curcoeff != 1.0 || settings.exerciceCurrentCoefficient != 1.0">{{ themes[current_theme].exercices[current_exercice].curcoeff * settings.exerciceCurrentCoefficient | coeff }} bonus</em></li>
|
||||
<li ng-if="themes[current_theme].exercices[current_exercice].tried"><strong>Tenté par :</strong> <ng-pluralize count="themes[current_theme].exercices[current_exercice].tried" when="{'0': 'aucune équipe', 'one': '{} équipe', 'other': '{} équipes'}"></ng-pluralize> <span ng-if="my.exercices[current_exercice].total_tries">(cumulant <ng-pluralize count="my.exercices[current_exercice].total_tries" when="{'one': '{} tentative', 'other': '{} tentatives'}"></ng-pluralize>)</span></li>
|
||||
|
|
|
|||
41
frontend/static/views/issue.html
Normal file
41
frontend/static/views/issue.html
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
<div class="card border-warning mt-3" ng-if="!settings.acceptNewIssue">
|
||||
<div class="card-header bg-warning text-light">Rapporter une anomalie sur un exercice</div>
|
||||
<div class="card-body">
|
||||
<p class="card-text">Rapprochez-vous d'un membre de l'équipe serveur afin d'obtenir de l'aide.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card border-warning mt-3 mb-4" ng-if="settings.acceptNewIssue">
|
||||
<div class="card-header bg-warning text-light">Rapporter une anomalie <span ng-if="issue.id_exercice">sur un exercice</span></div>
|
||||
<div class="card-body">
|
||||
<p ng-class="messageClass" ng-if="message || sberr"><strong ng-if="!sberr">Votre rapport a bien été envoyé !</strong><strong ng-if="sberr">{{ sberr }}</strong> {{ message }}</p>
|
||||
<form ng-submit="isubmit()">
|
||||
|
||||
<div class="form-group row" ng-if="issue.id_exercice">
|
||||
<label for="idExercice" class="col-sm-2 col-form-label">Exercice</label>
|
||||
<div class="col-sm-10" ng-if="current_theme">
|
||||
<input type="text" readonly class="form-control-plaintext" id="idExercice" value="{{ themes[current_theme].exercices[issue.id_exercice].title }}">
|
||||
</div>
|
||||
<div class="col-sm-10" ng-if="!current_theme">
|
||||
<input type="text" readonly class="form-control-plaintext" id="idExercice" value="{{ issue.id_exercice }}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label for="subject" class="col col-form-label">Objet</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="subject" ng-model="issue.subject" placeholder="Intitulé succinct">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label for="description" class="col col-form-label">Description</label>
|
||||
<div class="col-sm-10">
|
||||
<textarea class="form-control" id="description" ng-model="issue.description" placeholder="Décrivez en détail votre problème ici. Si nécessaire, incluez un lien vers une capture d'écran montrant votre problème."></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="float-right btn btn-warning">Envoyer le rapport</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
Reference in a new issue