admin: Better identify tries on exercice page
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
nemunaire 2025-03-30 15:20:11 +02:00
commit f6713c768b
6 changed files with 177 additions and 3 deletions

View file

@ -36,9 +36,16 @@ func declareExercicesRoutes(router *gin.RouterGroup) {
apiExercicesRoutes.POST("/diff-sync", APIDiffExerciceWithRemote)
apiExercicesRoutes.GET("/history.json", getExerciceHistory)
apiExercicesRoutes.GET("/stats.json", getExerciceStats)
apiExercicesRoutes.GET("/history.json", getExerciceHistory)
apiExercicesRoutes.GET("/tries", listTries)
apiTriesRoutes := apiExercicesRoutes.Group("/tries/:trid")
apiTriesRoutes.Use(ExerciceTryHandler)
apiTriesRoutes.GET("", getExerciceTry)
apiTriesRoutes.DELETE("", deleteExerciceTry)
apiHistoryRoutes := apiExercicesRoutes.Group("/history.json")
apiHistoryRoutes.Use(AssigneeCookieHandler)
@ -1619,3 +1626,58 @@ func APIDiffExerciceWithRemote(c *gin.Context) {
c.JSON(http.StatusOK, diffs)
}
func listTries(c *gin.Context) {
exercice := c.MustGet("exercice").(*fic.Exercice)
tries, err := exercice.TriesList()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"errmsg": err.Error()})
return
}
c.JSON(http.StatusOK, tries)
}
func ExerciceTryHandler(c *gin.Context) {
trid, err := strconv.ParseInt(string(c.Params.ByName("trid")), 10, 32)
if err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "Invalid try identifier"})
return
}
exercice := c.MustGet("exercice").(*fic.Exercice)
try, err := exercice.GetTry(trid)
if err != nil {
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "Try not found"})
return
}
c.Set("try", try)
c.Next()
}
func getExerciceTry(c *gin.Context) {
try := c.MustGet("try").(*fic.ExerciceTry)
err := try.FillDetails()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"errmsg": err.Error()})
return
}
c.JSON(http.StatusOK, try)
}
func deleteExerciceTry(c *gin.Context) {
try := c.MustGet("try").(*fic.ExerciceTry)
_, err := try.Delete()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"errmsg": err.Error()})
return
}
c.Status(http.StatusNoContent)
}

View file

@ -320,6 +320,9 @@ angular.module("FICApp")
.factory("ExerciceHistory", function ($resource) {
return $resource("api/exercices/:exerciceId/history.json", { exerciceId: '@id' })
})
.factory("ExerciceTries", function ($resource) {
return $resource("api/exercices/:exerciceId/tries/:tryId", { exerciceId: '@idExercice', tryId: '@id' })
})
.factory("ExercicesStats", function ($resource) {
return $resource("api/exercices_stats.json", { themeId: '@id' })
})
@ -2117,6 +2120,10 @@ angular.module("FICApp")
}
})
.controller("SearchTryController", function ($scope, ExerciceTries) {
$scope.tr = ExerciceTries.get({ exerciceId: $scope.exercice.id, tryId: $scope.row.secondary });
})
.controller("SubmissionsStatsController", function ($scope, $http, $interval) {
var refresh = function () {
$http({

View file

@ -83,6 +83,7 @@
<div ng-controller="ExerciceFlagStatsController" ng-init="init(flag)">
<strong>Statistiques</strong>
<ul>
<li>ID: {{ flag.id }}</li>
<li>Validés: {{ stats["completed"] }}</li>
<li>
Tentés: {{ stats["tries"] }}
@ -188,6 +189,7 @@
<div ng-controller="ExerciceMCQStatsController" ng-init="init(q)">
<strong>Statistiques</strong>
<ul>
<li>ID: {{ q.id }}</li>
<li>Validés: {{ stats["completed"] }}</li>
<li>
Tentés: {{ stats["tries"] }}

View file

@ -347,7 +347,8 @@
<a href="exercices/{{ row.primary }}#quizz-{{ row.secondary }}" ng-if="row.kind == 'mcq_found'">{{ row.secondary_title }}</a>
<a href="exercices/{{ row.primary }}#hint-{{ row.secondary }}" ng-if="row.kind == 'hint'">{{ row.secondary_title }}</a>
</span>
<span ng-if="!row.secondary_title && row.secondary && row.kind != 'solved'">: {{ row.secondary }}</span>
<span ng-if="!row.secondary_title && row.secondary && row.kind != 'solved' && row.kind != 'tries'">: {{ row.secondary }}</span>
<span ng-if="!row.secondary_title && row.secondary && row.kind == 'tries'" ng-controller="SearchTryController"><br><span ng-repeat="line in tr.details"><span ng-if="!$first">, </span>{{ line.kind }}<span ng-if="line.related">#{{ line.related }}</span></span></span>
</td>
<td style="vertical-align: middle; padding: 0; background-color: {{ row.team_color }}" ng-show="logged">
<button type="button" data-toggle="modal" data-target="#updHistory" ng-if="row.kind != 'flag_found' && row.kind != 'tries' && row.kind != 'mcq_found'" data-idteam="{{ row.team_id }}" data-kind="{{ row.kind }}" data-time="{{ row.time }}" data-secondary="{{ row.secondary }}" data-coeff="{{ row.coefficient }}" class="float-right btn btn-sm btn-info"><span class="glyphicon glyphicon-edit" aria-hidden="true"></span></button>