frontend: add players possibility to report problems with exercices

This commit is contained in:
nemunaire 2020-01-20 15:56:02 +01:00
commit 9186bbc229
13 changed files with 206 additions and 0 deletions

21
frontend/issue.go Normal file
View 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)
}
}

View file

@ -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}))

View file

@ -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;

View file

@ -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>

View file

@ -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&nbsp;:</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&nbsp;:</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>

View 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>