QA: add a list of team's exercices
This commit is contained in:
parent
911bcb032e
commit
ea334a8a2f
11
libfic/db.go
11
libfic/db.go
@ -457,6 +457,17 @@ CREATE TABLE IF NOT EXISTS teams_qa_todo(
|
|||||||
FOREIGN KEY(id_exercice) REFERENCES exercices(id_exercice),
|
FOREIGN KEY(id_exercice) REFERENCES exercices(id_exercice),
|
||||||
FOREIGN KEY(id_team) REFERENCES teams(id_team)
|
FOREIGN KEY(id_team) REFERENCES teams(id_team)
|
||||||
) DEFAULT CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
|
) DEFAULT CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
|
||||||
|
`); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := db.Exec(`
|
||||||
|
CREATE TABLE IF NOT EXISTS teams_qa_view(
|
||||||
|
id_view INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||||
|
id_team INTEGER NOT NULL,
|
||||||
|
id_exercice INTEGER NOT NULL,
|
||||||
|
FOREIGN KEY(id_exercice) REFERENCES exercices(id_exercice),
|
||||||
|
FOREIGN KEY(id_team) REFERENCES teams(id_team)
|
||||||
|
) DEFAULT CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
|
||||||
`); err != nil {
|
`); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
31
libfic/qa.go
31
libfic/qa.go
@ -238,3 +238,34 @@ func (t Team) NewQATodo(idExercice int64) (QATodo, error) {
|
|||||||
return QATodo{tid, t.Id, idExercice}, nil
|
return QATodo{tid, t.Id, idExercice}, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// QAView
|
||||||
|
|
||||||
|
func (t Team) GetQAView() (res []QATodo, err error) {
|
||||||
|
var rows *sql.Rows
|
||||||
|
if rows, err = DBQuery("SELECT id_view, id_exercice FROM teams_qa_view WHERE id_team = ?", t.Id); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
for rows.Next() {
|
||||||
|
var t QATodo
|
||||||
|
if err = rows.Scan(&t.Id, &t.IdExercice); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
res = append(res, t)
|
||||||
|
}
|
||||||
|
err = rows.Err()
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t Team) NewQAView(idExercice int64) (QATodo, error) {
|
||||||
|
if res, err := DBExec("INSERT INTO teams_qa_view (id_team, id_exercice) VALUES (?, ?)", t.Id, idExercice); err != nil {
|
||||||
|
return QATodo{}, err
|
||||||
|
} else if tid, err := res.LastInsertId(); err != nil {
|
||||||
|
return QATodo{}, err
|
||||||
|
} else {
|
||||||
|
return QATodo{tid, t.Id, idExercice}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -12,6 +12,8 @@ import (
|
|||||||
func init() {
|
func init() {
|
||||||
router.GET("/api/qa_exercices.json", apiHandler(getExerciceTested))
|
router.GET("/api/qa_exercices.json", apiHandler(getExerciceTested))
|
||||||
router.GET("/api/qa_mywork.json", apiHandler(getQAWork))
|
router.GET("/api/qa_mywork.json", apiHandler(getQAWork))
|
||||||
|
router.GET("/api/qa_myexercices.json", apiHandler(getQAView))
|
||||||
|
router.POST("/api/qa_my_exercices.json", apiHandler(addQAView))
|
||||||
router.GET("/api/qa_work.json", apiHandler(getQATodo))
|
router.GET("/api/qa_work.json", apiHandler(getQATodo))
|
||||||
router.POST("/api/qa_work.json", apiHandler(createQATodo))
|
router.POST("/api/qa_work.json", apiHandler(createQATodo))
|
||||||
}
|
}
|
||||||
@ -42,6 +44,14 @@ func getExerciceTested(u QAUser, ps httprouter.Params, body []byte) (interface{}
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getQAView(u QAUser, ps httprouter.Params, body []byte) (interface{}, error) {
|
||||||
|
if team, err := fic.GetTeam(u.TeamId); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
return team.GetQAView()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func getQAWork(u QAUser, ps httprouter.Params, body []byte) (interface{}, error) {
|
func getQAWork(u QAUser, ps httprouter.Params, body []byte) (interface{}, error) {
|
||||||
if team, err := fic.GetTeam(u.TeamId); err != nil {
|
if team, err := fic.GetTeam(u.TeamId); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -74,3 +84,20 @@ func createQATodo(u QAUser, ps httprouter.Params, body []byte) (interface{}, err
|
|||||||
return team.NewQATodo(ut.IdExercice)
|
return team.NewQATodo(ut.IdExercice)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func addQAView(u QAUser, ps httprouter.Params, body []byte) (interface{}, error) {
|
||||||
|
if u.User != "nemunaire" {
|
||||||
|
return nil, errors.New("Restricted")
|
||||||
|
}
|
||||||
|
|
||||||
|
var ut fic.QATodo
|
||||||
|
if err := json.Unmarshal(body, &ut); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if team, err := fic.GetTeam(ut.IdTeam); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
return team.NewQAView(ut.IdExercice)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -96,6 +96,9 @@ angular.module("FICApp")
|
|||||||
.factory("TodoWorked", function($resource) {
|
.factory("TodoWorked", function($resource) {
|
||||||
return $resource("api/qa_mywork.json")
|
return $resource("api/qa_mywork.json")
|
||||||
})
|
})
|
||||||
|
.factory("MyExercices", function($resource) {
|
||||||
|
return $resource("api/qa_myexercices.json")
|
||||||
|
})
|
||||||
.factory("ExercicesTested", function($resource) {
|
.factory("ExercicesTested", function($resource) {
|
||||||
return $resource("api/qa_exercices.json")
|
return $resource("api/qa_exercices.json")
|
||||||
})
|
})
|
||||||
@ -240,6 +243,14 @@ angular.module("FICApp")
|
|||||||
};
|
};
|
||||||
})
|
})
|
||||||
|
|
||||||
|
.controller("MyExercicesController", function($scope, MyExercices, $location) {
|
||||||
|
$scope.my_exercices = MyExercices.query();
|
||||||
|
|
||||||
|
$scope.show = function(id) {
|
||||||
|
$location.url("/exercices/" + id);
|
||||||
|
};
|
||||||
|
})
|
||||||
|
|
||||||
.controller("ThemesListController", function($scope, Theme, $location, $rootScope, $http) {
|
.controller("ThemesListController", function($scope, Theme, $location, $rootScope, $http) {
|
||||||
$scope.themes = Theme.query();
|
$scope.themes = Theme.query();
|
||||||
$scope.fields = ["name", "authors", "headline"];
|
$scope.fields = ["name", "authors", "headline"];
|
||||||
@ -342,7 +353,27 @@ angular.module("FICApp")
|
|||||||
})
|
})
|
||||||
|
|
||||||
.controller("ExerciceQAController", function($scope, $rootScope, ExerciceQA, $routeParams, $location, $http) {
|
.controller("ExerciceQAController", function($scope, $rootScope, ExerciceQA, $routeParams, $location, $http) {
|
||||||
|
if ($routeParams.exerciceId) {
|
||||||
$scope.queries = ExerciceQA.query({ exerciceId: $routeParams.exerciceId });
|
$scope.queries = ExerciceQA.query({ exerciceId: $routeParams.exerciceId });
|
||||||
|
} else {
|
||||||
|
$scope.queries = ExerciceQA.query({ exerciceId: $scope.todo.id_exercice });
|
||||||
|
}
|
||||||
|
$scope.queriesNSolved = "N/A"
|
||||||
|
$scope.queriesNClosed = "N/A"
|
||||||
|
$scope.queries.$promise.then(function (queries) {
|
||||||
|
var nbResolved = 0;
|
||||||
|
var nbClosed = 0;
|
||||||
|
queries.forEach(function(q) {
|
||||||
|
if (q.solved) {
|
||||||
|
nbResolved++;
|
||||||
|
}
|
||||||
|
if (q.closed) {
|
||||||
|
nbClosed++;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
$scope.queriesNSolved = queries.length - nbResolved
|
||||||
|
$scope.queriesNClosed = queries.length - nbClosed
|
||||||
|
})
|
||||||
$scope.fields = ["state", "subject", "user", "creation"];
|
$scope.fields = ["state", "subject", "user", "creation"];
|
||||||
$scope.namedFields = {
|
$scope.namedFields = {
|
||||||
"state": "État",
|
"state": "État",
|
||||||
|
@ -1,9 +1,17 @@
|
|||||||
<div class="jumbotron text-light bg-dark">
|
<div class="jumbotron">
|
||||||
<h1 class="display-5">Interface QA du challenge</h1>
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col" ng-controller="ToDoController">
|
<div class="col-6" ng-controller="ToDoController">
|
||||||
<table class="table table-stripped">
|
<h3>Challenges à valider</h3>
|
||||||
<tr ng-repeat="todo in todos" ng-controller="MyTodoExerciceController" ng-class="{'bg-dark': !tododone[todo.id_exercice] && !exo_done[todo.id_exercice], 'bg-warning': !tododone[todo.id_exercice] && exo_done[todo.id_exercice] == 'access', 'bg-info': !tododone[todo.id_exercice] && (exo_done[todo.id_exercice] == 'tried' || exo_done[todo.id_exercice] == 'solved'), 'bg-success': tododone[todo.id_exercice]}" ng-click="show(todo.id_exercice)">
|
<table class="table table-stripped table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Avancement</th>
|
||||||
|
<th>Scénario</th>
|
||||||
|
<th>Défi</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr ng-repeat="todo in todos" ng-controller="MyTodoExerciceController" ng-class="{'text-light': !tododone[todo.id_exercice] && !exo_done[todo.id_exercice], 'table-dark': !tododone[todo.id_exercice] && !exo_done[todo.id_exercice], 'table-warning': !tododone[todo.id_exercice] && exo_done[todo.id_exercice] == 'access', 'table-info': !tododone[todo.id_exercice] && (exo_done[todo.id_exercice] == 'tried' || exo_done[todo.id_exercice] == 'solved'), 'table-success': tododone[todo.id_exercice]}" ng-click="show(todo.id_exercice)">
|
||||||
<td ng-if="!tododone[todo.id_exercice] && (!exo_done[todo.id_exercice] || exo_done[todo.id_exercice] == 'access')">
|
<td ng-if="!tododone[todo.id_exercice] && (!exo_done[todo.id_exercice] || exo_done[todo.id_exercice] == 'access')">
|
||||||
À tester
|
À tester
|
||||||
</td>
|
</td>
|
||||||
@ -20,6 +28,29 @@
|
|||||||
{{ myexercice.title }}
|
{{ myexercice.title }}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="col-6" ng-controller="MyExercicesController">
|
||||||
|
<h3>Vos challenges</h3>
|
||||||
|
<table class="table table-stripped table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Défi</th>
|
||||||
|
<th>Requêtes</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr ng-repeat="todo in my_exercices" ng-controller="ExerciceQAController" ng-class="{'table-success': queries.length > 0, 'table-warning': queriesNSolved > 0}" ng-click="show(todo.id_exercice)">
|
||||||
|
<td ng-controller="MyTodoExerciceController">
|
||||||
|
<span ng-if="mytheme.name">{{ mytheme.name }} –</span>
|
||||||
|
{{ myexercice.title }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ queriesNSolved }} / {{ queriesNClosed }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user