admin: improve claims with related exercices
This commit is contained in:
parent
2e3f7c6894
commit
32dc9c1a8c
@ -2,6 +2,7 @@ package api
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"srs.epita.fr/fic-server/libfic"
|
"srs.epita.fr/fic-server/libfic"
|
||||||
@ -11,9 +12,12 @@ import (
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
// Tasks
|
// Tasks
|
||||||
router.GET("/api/claims/", apiHandler(getClaims))
|
router.GET("/api/claims", apiHandler(getClaims))
|
||||||
router.POST("/api/claims/", apiHandler(newClaim))
|
router.POST("/api/claims", apiHandler(newClaim))
|
||||||
router.DELETE("/api/claims/", apiHandler(clearClaims))
|
router.DELETE("/api/claims", apiHandler(clearClaims))
|
||||||
|
router.GET("/api/teams/:tid/claims", apiHandler(teamHandler(getTeamClaims)))
|
||||||
|
router.GET("/api/exercices/:eid/claims", apiHandler(exerciceHandler(getExerciceClaims)))
|
||||||
|
router.GET("/api/themes/:thid/exercices/:eid/claims", apiHandler(exerciceHandler(getExerciceClaims)))
|
||||||
|
|
||||||
router.GET("/api/claims/:cid", apiHandler(claimHandler(showClaim)))
|
router.GET("/api/claims/:cid", apiHandler(claimHandler(showClaim)))
|
||||||
router.PUT("/api/claims/:cid", apiHandler(claimHandler(updateClaim)))
|
router.PUT("/api/claims/:cid", apiHandler(claimHandler(updateClaim)))
|
||||||
@ -21,8 +25,8 @@ func init() {
|
|||||||
router.DELETE("/api/claims/:cid", apiHandler(claimHandler(deleteClaim)))
|
router.DELETE("/api/claims/:cid", apiHandler(claimHandler(deleteClaim)))
|
||||||
|
|
||||||
// Assignees
|
// Assignees
|
||||||
router.GET("/api/claims-assignees/", apiHandler(getAssignees))
|
router.GET("/api/claims-assignees", apiHandler(getAssignees))
|
||||||
router.POST("/api/claims-assignees/", apiHandler(newAssignee))
|
router.POST("/api/claims-assignees", apiHandler(newAssignee))
|
||||||
|
|
||||||
router.GET("/api/claims-assignees/:aid", apiHandler(claimAssigneeHandler(showClaimAssignee)))
|
router.GET("/api/claims-assignees/:aid", apiHandler(claimAssigneeHandler(showClaimAssignee)))
|
||||||
router.PUT("/api/claims-assignees/:aid", apiHandler(claimAssigneeHandler(updateClaimAssignee)))
|
router.PUT("/api/claims-assignees/:aid", apiHandler(claimAssigneeHandler(updateClaimAssignee)))
|
||||||
@ -33,6 +37,14 @@ func getClaims(_ httprouter.Params, _ []byte) (interface{}, error) {
|
|||||||
return fic.GetClaims()
|
return fic.GetClaims()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getTeamClaims(team fic.Team, _ []byte) (interface{}, error) {
|
||||||
|
return team.GetClaims()
|
||||||
|
}
|
||||||
|
|
||||||
|
func getExerciceClaims(exercice fic.Exercice, _ []byte) (interface{}, error) {
|
||||||
|
return exercice.GetClaims()
|
||||||
|
}
|
||||||
|
|
||||||
type ClaimExported struct {
|
type ClaimExported struct {
|
||||||
Id int64 `json:"id"`
|
Id int64 `json:"id"`
|
||||||
Subject string `json:"subject"`
|
Subject string `json:"subject"`
|
||||||
@ -97,6 +109,10 @@ func newClaim(_ httprouter.Params, body []byte) (interface{}, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if uc.Subject == "" {
|
||||||
|
return nil, errors.New("Claim's subject cannot be empty.")
|
||||||
|
}
|
||||||
|
|
||||||
var t *fic.Team
|
var t *fic.Team
|
||||||
if uc.Team != nil {
|
if uc.Team != nil {
|
||||||
if team, err := fic.GetTeam(*uc.Team); err != nil {
|
if team, err := fic.GetTeam(*uc.Team); err != nil {
|
||||||
@ -130,6 +146,10 @@ func newClaim(_ httprouter.Params, body []byte) (interface{}, error) {
|
|||||||
a = nil
|
a = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if uc.Priority == "" {
|
||||||
|
uc.Priority = "medium"
|
||||||
|
}
|
||||||
|
|
||||||
return fic.NewClaim(uc.Subject, t, e, a, uc.Priority)
|
return fic.NewClaim(uc.Subject, t, e, a, uc.Priority)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,6 +229,9 @@ angular.module("FICApp")
|
|||||||
patch: {method: 'PATCH'}
|
patch: {method: 'PATCH'}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
.factory("ExerciceClaims", function($resource) {
|
||||||
|
return $resource("/api/exercices/:exerciceId/claims", { exerciceId: '@idExercice'})
|
||||||
|
})
|
||||||
.factory("ExerciceTags", function($resource) {
|
.factory("ExerciceTags", function($resource) {
|
||||||
return $resource("/api/exercices/:exerciceId/tags", { exerciceId: '@idExercice'}, {
|
return $resource("/api/exercices/:exerciceId/tags", { exerciceId: '@idExercice'}, {
|
||||||
update: {method: 'PUT'}
|
update: {method: 'PUT'}
|
||||||
@ -267,7 +270,7 @@ angular.module("FICApp")
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.filter("toColor", function() {
|
.filter("toColor", function() {
|
||||||
return function(input) {
|
return function(num) {
|
||||||
num >>>= 0;
|
num >>>= 0;
|
||||||
var b = num & 0xFF,
|
var b = num & 0xFF,
|
||||||
g = (num & 0xFF00) >>> 8,
|
g = (num & 0xFF00) >>> 8,
|
||||||
@ -1056,14 +1059,14 @@ angular.module("FICApp")
|
|||||||
$location.url("/claims/" + id);
|
$location.url("/claims/" + id);
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.controller("ClaimController", function($scope, Claim, ClaimAssignee, Teams, Exercice, $routeParams, $location, $http) {
|
.controller("ClaimController", function($scope, Claim, ClaimAssignee, Teams, Exercice, $routeParams, $location, $http, $rootScope) {
|
||||||
$scope.claim = Claim.get({ claimId: $routeParams.claimId }, function(v) {
|
$scope.claim = Claim.get({ claimId: $routeParams.claimId }, function(v) {
|
||||||
v.id_team = "" + v.id_team;
|
v.id_team = "" + v.id_team;
|
||||||
if (!v.priority)
|
if (!v.priority)
|
||||||
v.priority = "medium";
|
v.priority = "medium";
|
||||||
});
|
});
|
||||||
if ($routeParams.claimId == "new")
|
if ($routeParams.claimId == "new")
|
||||||
$scope.fields = ["id_team", "subject", "priority", "id_exercice", "id_assignee"];
|
$scope.fields = ["id_team", "id_exercice", "subject", "priority", "id_assignee"];
|
||||||
else
|
else
|
||||||
$scope.fields = ["state", "subject", "priority", "id_exercice", "id_assignee", "id_team", "creation"];
|
$scope.fields = ["state", "subject", "priority", "id_exercice", "id_assignee", "id_team", "creation"];
|
||||||
$scope.assignees = ClaimAssignee.query();
|
$scope.assignees = ClaimAssignee.query();
|
||||||
@ -1132,6 +1135,8 @@ angular.module("FICApp")
|
|||||||
if (!this.ndescription)
|
if (!this.ndescription)
|
||||||
this.ndescription = "Création de la tâche";
|
this.ndescription = "Création de la tâche";
|
||||||
$scope.saveDescription();
|
$scope.saveDescription();
|
||||||
|
}, function(response) {
|
||||||
|
$rootScope.newBox('danger', 'An error occurs when trying to save claim:', response.data.errmsg);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1362,6 +1367,22 @@ angular.module("FICApp")
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
.controller("ExerciceClaimsController", function($scope, ExerciceClaims, Team, ClaimAssignee, $routeParams, $location) {
|
||||||
|
$scope.claims = ExerciceClaims.query({ exerciceId: $routeParams.exerciceId });
|
||||||
|
$scope.assignees = ClaimAssignee.query();
|
||||||
|
|
||||||
|
$scope.claims.$promise.then(function(claims) {
|
||||||
|
claims.forEach(function(claim, cid) {
|
||||||
|
$scope.claims[cid].team = Team.get({ teamId: claim.id_team });
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
$scope.showClosed = false;
|
||||||
|
$scope.show = function(id) {
|
||||||
|
$location.url("/claims/" + id);
|
||||||
|
};
|
||||||
|
})
|
||||||
|
|
||||||
.controller("ExerciceTagsController", function($scope, ExerciceTags, $routeParams, $rootScope) {
|
.controller("ExerciceTagsController", function($scope, ExerciceTags, $routeParams, $rootScope) {
|
||||||
$scope.tags = ExerciceTags.query({ exerciceId: $routeParams.exerciceId });
|
$scope.tags = ExerciceTags.query({ exerciceId: $routeParams.exerciceId });
|
||||||
|
|
||||||
|
@ -9,8 +9,13 @@
|
|||||||
<input type="text" class="form-control form-control-sm" id="{{ field }}" ng-model="claim[field]" ng-if="field != 'state' && field != 'priority' && field != 'creation' && field != 'id_team' && field != 'id_exercice' && field != 'id_assignee' && field != 'description'">
|
<input type="text" class="form-control form-control-sm" id="{{ field }}" ng-model="claim[field]" ng-if="field != 'state' && field != 'priority' && field != 'creation' && field != 'id_team' && field != 'id_exercice' && field != 'id_assignee' && field != 'description'">
|
||||||
<input type="datetime" class="form-control form-control-sm" id="{{ field }}" ng-model="claim[field]" ng-if="field == 'creation' && claim.id">
|
<input type="datetime" class="form-control form-control-sm" id="{{ field }}" ng-model="claim[field]" ng-if="field == 'creation' && claim.id">
|
||||||
<select class="custom-select custom-select-sm" id="{{ field }}" ng-model="claim[field]" ng-options="k as v for (k, v) in states" ng-if="field == 'state'"></select>
|
<select class="custom-select custom-select-sm" id="{{ field }}" ng-model="claim[field]" ng-options="k as v for (k, v) in states" ng-if="field == 'state'"></select>
|
||||||
<select class="custom-select custom-select-sm" id="{{ field }}" ng-model="claim[field]" ng-options="k as v for (k, v) in priorities" ng-if="field == 'priority'"><option value="medium">Par défaut</option></select>
|
<select class="custom-select custom-select-sm" id="{{ field }}" ng-model="claim[field]" ng-options="k as v for (k, v) in priorities" ng-if="field == 'priority'"></select>
|
||||||
<select class="custom-select custom-select-sm" id="{{ field }}" ng-model="claim[field]" ng-options="ex.id as ex.title group by ex.path.split('/')[0] for ex in exercices" ng-if="field == 'id_exercice'"><option></option></select>
|
<div class="input-group" ng-if="field == 'id_exercice'">
|
||||||
|
<select class="custom-select custom-select-sm" id="{{ field }}" ng-model="claim[field]" ng-options="ex.id as ex.title group by ex.path.split('/')[0] for ex in exercices"><option></option></select>
|
||||||
|
<div class="input-group-append" ng-if="claim.id_exercice">
|
||||||
|
<a type="button" class="btn btn-sm btn-outline-secondary" ng-href="exercices/{{ claim.id_exercice }}">Aller au challenge</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<select class="custom-select custom-select-sm" id="{{ field }}" ng-model="claim[field]" ng-options="k as t.name for (k, t) in teams" ng-if="field == 'id_team' && !claim.id"><option></option></select>
|
<select class="custom-select custom-select-sm" id="{{ field }}" ng-model="claim[field]" ng-options="k as t.name for (k, t) in teams" ng-if="field == 'id_team' && !claim.id"><option></option></select>
|
||||||
<div class="input-group" ng-if="field == 'id_team' && claim.id">
|
<div class="input-group" ng-if="field == 'id_team' && claim.id">
|
||||||
<select class="custom-select custom-select-sm" id="{{ field }}" ng-model="claim[field]" ng-options="k as t.name for (k, t) in teams"><option></option></select>
|
<select class="custom-select custom-select-sm" id="{{ field }}" ng-model="claim[field]" ng-options="k as t.name for (k, t) in teams"><option></option></select>
|
||||||
|
@ -35,6 +35,20 @@
|
|||||||
</form>
|
</form>
|
||||||
|
|
||||||
<div class="col-md-4 accordion" ng-show="exercice.id" id="accordionExercice">
|
<div class="col-md-4 accordion" ng-show="exercice.id" id="accordionExercice">
|
||||||
|
|
||||||
|
<div class="mb-2" style="overflow-y: auto; max-height: 250px" ng-controller="ExerciceClaimsController" ng-show="claims.length">
|
||||||
|
<table class="table table-sm table-hover table-striped">
|
||||||
|
<tbody>
|
||||||
|
<tr ng-repeat="claim in claims | orderBy: 'priority'" ng-click="show(claim.id)" ng-class="{'table-info': claim.priority == 'medium', 'table-warning': claim.priority == 'high', 'table-danger': claim.priority == 'critical'}" ng-if="showClosed || (claim.state != 'closed' && claim.state != 'invalid')">
|
||||||
|
<td ng-bind="claim.subject"></td>
|
||||||
|
<td><a ng-href="teams/{{ claim.id_team}}" style="background-color: {{ claim.team.color | toColor }}" ng-bind="claim.team.name"></a></td>
|
||||||
|
<td ng-bind="claim.state"></td>
|
||||||
|
<td ng-repeat="assignee in assignees" ng-if="assignee.id == claim.id_assignee" ng-bind="assignee.name"></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="card border-secondary" ng-controller="ExerciceFilesController">
|
<div class="card border-secondary" ng-controller="ExerciceFilesController">
|
||||||
<div class="card-header bg-secondary text-light" type="button" data-toggle="collapse" data-target="#collapseFiles" aria-expanded="true" aria-controls="collapseFiles">
|
<div class="card-header bg-secondary text-light" type="button" data-toggle="collapse" data-target="#collapseFiles" aria-expanded="true" aria-controls="collapseFiles">
|
||||||
<h4 class="m-0"><small class="glyphicon glyphicon-chevron-right" aria-hidden="true"></small> Téléchargements</h4>
|
<h4 class="m-0"><small class="glyphicon glyphicon-chevron-right" aria-hidden="true"></small> Téléchargements</h4>
|
||||||
|
@ -46,7 +46,27 @@ func GetClaims() (res []Claim, err error) {
|
|||||||
// GetClaims returns a list of all Claim registered for the Team.
|
// GetClaims returns a list of all Claim registered for the Team.
|
||||||
func (t Team) GetClaims() (res []Claim, err error) {
|
func (t Team) GetClaims() (res []Claim, err error) {
|
||||||
var rows *sql.Rows
|
var rows *sql.Rows
|
||||||
if rows, err = DBQuery("SELECT id_claim, subject, id_team, id_exercice, id_assignee, creation, state, priority FROM claims WHERE IdTeam = ?", t.Id); err != nil {
|
if rows, err = DBQuery("SELECT id_claim, subject, id_team, id_exercice, id_assignee, creation, state, priority FROM claims WHERE id_team = ?", t.Id); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
for rows.Next() {
|
||||||
|
var c Claim
|
||||||
|
if err = rows.Scan(&c.Id, &c.Subject, &c.IdTeam, &c.IdExercice, &c.IdAssignee, &c.Creation, &c.State, &c.Priority); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
res = append(res, c)
|
||||||
|
}
|
||||||
|
err = rows.Err()
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetExercices returns a list of all Claim registered for the Exercice.
|
||||||
|
func (e Exercice) GetClaims() (res []Claim, err error) {
|
||||||
|
var rows *sql.Rows
|
||||||
|
if rows, err = DBQuery("SELECT id_claim, subject, id_team, id_exercice, id_assignee, creation, state, priority FROM claims WHERE id_exercice = ?", e.Id); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
|
Loading…
Reference in New Issue
Block a user