diff --git a/libfic/db.go b/libfic/db.go
index fc49decf..77005d9d 100644
--- a/libfic/db.go
+++ b/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_team) REFERENCES teams(id_team)
) 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 {
return err
}
diff --git a/libfic/qa.go b/libfic/qa.go
index 8586dd5b..7e60f18e 100644
--- a/libfic/qa.go
+++ b/libfic/qa.go
@@ -238,3 +238,34 @@ func (t Team) NewQATodo(idExercice int64) (QATodo, error) {
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
+ }
+}
diff --git a/qa/api/todo.go b/qa/api/todo.go
index 9aa7cbc8..2d46feef 100644
--- a/qa/api/todo.go
+++ b/qa/api/todo.go
@@ -12,6 +12,8 @@ import (
func init() {
router.GET("/api/qa_exercices.json", apiHandler(getExerciceTested))
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.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) {
if team, err := fic.GetTeam(u.TeamId); err != nil {
return nil, err
@@ -74,3 +84,20 @@ func createQATodo(u QAUser, ps httprouter.Params, body []byte) (interface{}, err
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)
+ }
+}
diff --git a/qa/static/js/qa.js b/qa/static/js/qa.js
index b4894d19..efd177ac 100644
--- a/qa/static/js/qa.js
+++ b/qa/static/js/qa.js
@@ -96,6 +96,9 @@ angular.module("FICApp")
.factory("TodoWorked", function($resource) {
return $resource("api/qa_mywork.json")
})
+ .factory("MyExercices", function($resource) {
+ return $resource("api/qa_myexercices.json")
+ })
.factory("ExercicesTested", function($resource) {
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) {
$scope.themes = Theme.query();
$scope.fields = ["name", "authors", "headline"];
@@ -322,7 +333,7 @@ angular.module("FICApp")
$scope.exercice = new ThemedExercice();
} else {
$scope.exercice = Exercice.get({ exerciceId: $routeParams.exerciceId });
- }
+ }
$http({
url: "api/themes.json",
method: "GET"
@@ -342,7 +353,27 @@ angular.module("FICApp")
})
.controller("ExerciceQAController", function($scope, $rootScope, ExerciceQA, $routeParams, $location, $http) {
- $scope.queries = ExerciceQA.query({ exerciceId: $routeParams.exerciceId });
+ if ($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.namedFields = {
"state": "État",
diff --git a/qa/static/views/home.html b/qa/static/views/home.html
index 29733a15..6cf7271c 100644
--- a/qa/static/views/home.html
+++ b/qa/static/views/home.html
@@ -1,25 +1,56 @@
-
-
Interface QA du challenge
+
-
-
-
-
- À tester
- |
-
- À commenter
- |
-
- Commenté mais pas testé
- |
-
- {{ mytheme.name }}
- |
-
- {{ myexercice.title }}
- |
-
+
+
Challenges à valider
+
+
+
+ Avancement |
+ Scénario |
+ Défi |
+
+
+
+
+
+ À tester
+ |
+
+ À commenter
+ |
+
+ Commenté mais pas testé
+ |
+
+ {{ mytheme.name }}
+ |
+
+ {{ myexercice.title }}
+ |
+
+
+
+
+
+
Vos challenges
+
+
+
+ Défi |
+ Requêtes |
+
+
+
+
+
+ {{ mytheme.name }} –
+ {{ myexercice.title }}
+ |
+
+ {{ queriesNSolved }} / {{ queriesNClosed }}
+ |
+
+