diff --git a/libfic/qa.go b/libfic/qa.go index 45087f7d..0042efe4 100644 --- a/libfic/qa.go +++ b/libfic/qa.go @@ -242,6 +242,17 @@ func (t *Team) NewQATodo(idExercice int64) (*QATodo, error) { } } +// Delete the comment in the database. +func (t *QATodo) Delete() (int64, error) { + if res, err := DBExec("DELETE FROM teams_qa_todo WHERE id_todo = ?", t.Id); err != nil { + return 0, err + } else if nb, err := res.RowsAffected(); err != nil { + return 0, err + } else { + return nb, err + } +} + // QAView func (t *Team) GetQAView() (res []*QATodo, err error) { diff --git a/qa/api/router.go b/qa/api/router.go index 5fc188ed..a59013b8 100644 --- a/qa/api/router.go +++ b/qa/api/router.go @@ -29,4 +29,5 @@ func DeclareRoutes(router *gin.RouterGroup) { })) declareTodoManagerRoutes(apiManagerRoutes) + declareTeamsRoutes(apiManagerRoutes) } diff --git a/qa/api/team.go b/qa/api/team.go new file mode 100644 index 00000000..0286c0c3 --- /dev/null +++ b/qa/api/team.go @@ -0,0 +1,53 @@ +package api + +import ( + "fmt" + "log" + "net/http" + "strconv" + + "srs.epita.fr/fic-server/libfic" + + "github.com/gin-gonic/gin" +) + +func declareTeamsRoutes(router *gin.RouterGroup) { + router.GET("/teams", listTeams) + + teamsRoutes := router.Group("/teams/:tid") + teamsRoutes.Use(teamHandler) + teamsRoutes.GET("", showTeam) + + declareTodoRoutes(teamsRoutes) + declareTodoManagerRoutes(teamsRoutes) +} + +func teamHandler(c *gin.Context) { + var team *fic.Team + if tid, err := strconv.ParseInt(string(c.Param("tid")), 10, 64); err != nil { + c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "Bad team identifier."}) + return + } else if team, err = fic.GetTeam(tid); err != nil { + c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "Team not found."}) + return + } + + c.Set("team", team) + + c.Next() +} + +func listTeams(c *gin.Context) { + teams, err := fic.GetTeams() + if err != nil { + log.Println("Unable to GetTeams: ", err.Error()) + c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": fmt.Sprintf("Unable to list teams: %s", err.Error())}) + return + } + + c.JSON(http.StatusOK, teams) +} + +func showTeam(c *gin.Context) { + c.JSON(http.StatusOK, c.MustGet("team")) +} diff --git a/qa/api/todo.go b/qa/api/todo.go index 75aab427..9a5ff270 100644 --- a/qa/api/todo.go +++ b/qa/api/todo.go @@ -2,6 +2,7 @@ package api import ( "net/http" + "strconv" "srs.epita.fr/fic-server/libfic" @@ -18,12 +19,22 @@ func declareTodoRoutes(router *gin.RouterGroup) { func declareTodoManagerRoutes(router *gin.RouterGroup) { router.POST("/qa_my_exercices.json", addQAView) router.POST("/qa_work.json", createQATodo) + + todosRoutes := router.Group("/todo/:wid") + todosRoutes.Use(todoHandler) + todosRoutes.GET("", showTodo) + todosRoutes.DELETE("", deleteQATodo) } type exerciceTested map[int64]string func getExerciceTested(c *gin.Context) { - teamid := c.MustGet("LoggedTeam").(int64) + var teamid int64 + if team, ok := c.Get("team"); ok { + teamid = team.(*fic.Team).Id + } else { + teamid = c.MustGet("LoggedTeam").(int64) + } team, err := fic.GetTeam(teamid) if err != nil { @@ -55,7 +66,12 @@ func getExerciceTested(c *gin.Context) { } func getQAView(c *gin.Context) { - teamid := c.MustGet("LoggedTeam").(int64) + var teamid int64 + if team, ok := c.Get("team"); ok { + teamid = team.(*fic.Team).Id + } else { + teamid = c.MustGet("LoggedTeam").(int64) + } team, err := fic.GetTeam(teamid) if err != nil { @@ -73,7 +89,12 @@ func getQAView(c *gin.Context) { } func getQAWork(c *gin.Context) { - teamid := c.MustGet("LoggedTeam").(int64) + var teamid int64 + if team, ok := c.Get("team"); ok { + teamid = team.(*fic.Team).Id + } else { + teamid = c.MustGet("LoggedTeam").(int64) + } team, err := fic.GetTeam(teamid) if err != nil { @@ -91,7 +112,12 @@ func getQAWork(c *gin.Context) { } func getQATodo(c *gin.Context) { - teamid := c.MustGet("LoggedTeam").(int64) + var teamid int64 + if team, ok := c.Get("team"); ok { + teamid = team.(*fic.Team).Id + } else { + teamid = c.MustGet("LoggedTeam").(int64) + } team, err := fic.GetTeam(teamid) if err != nil { @@ -167,3 +193,45 @@ func addQAView(c *gin.Context) { c.JSON(http.StatusOK, view) } + +func todoHandler(c *gin.Context) { + team := c.MustGet("team").(*fic.Team) + + var wid int64 + var todos []*fic.QATodo + var err error + + if wid, err = strconv.ParseInt(string(c.Param("wid")), 10, 64); err != nil { + c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "Bad todo identifier."}) + return + } + + if todos, err = team.GetQATodo(); err != nil { + c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "Todo not found."}) + return + } + + for _, t := range todos { + if t.Id == wid { + c.Set("todo", t) + c.Next() + return + } + } + + c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "Unable to find the requested QA Todo"}) +} + +func showTodo(c *gin.Context) { + c.JSON(http.StatusOK, c.MustGet("todo")) +} + +func deleteQATodo(c *gin.Context) { + todo := c.MustGet("todo").(*fic.QATodo) + + if _, err := todo.Delete(); err != nil { + c.AbortWithError(http.StatusInternalServerError, err) + } else { + c.Status(http.StatusOK) + } +} diff --git a/qa/static.go b/qa/static.go index f5c2170a..83507c3c 100644 --- a/qa/static.go +++ b/qa/static.go @@ -121,6 +121,8 @@ func declareStaticRoutes(router *gin.RouterGroup, baseURL string) { router.GET("/exercices", serveOrReverse("/", baseURL)) router.GET("/exercices/*_", serveOrReverse("/", baseURL)) router.GET("/export", serveOrReverse("/", baseURL)) + router.GET("/teams", serveOrReverse("/", baseURL)) + router.GET("/teams/*_", serveOrReverse("/", baseURL)) router.GET("/themes", serveOrReverse("/", baseURL)) router.GET("/themes/*_", serveOrReverse("/", baseURL)) router.GET("/_app/*_", serveOrReverse("", baseURL)) diff --git a/qa/ui/src/lib/components/MyExercices.svelte b/qa/ui/src/lib/components/MyExercices.svelte index cb4975d9..d6a11e87 100644 --- a/qa/ui/src/lib/components/MyExercices.svelte +++ b/qa/ui/src/lib/components/MyExercices.svelte @@ -9,11 +9,12 @@ import { getExerciceQA } from '$lib/qa'; import { exercicesIdx } from '$lib/stores/exercices'; import { themesIdx } from '$lib/stores/themes'; - import { todos } from '$lib/stores/todo'; export { className as class }; let className = ''; + export let team = null; + function show(id) { goto("exercices/" + id) } @@ -23,7 +24,7 @@ setInterval(() => my_exercicesP = update_exercices(), 62000); async function update_exercices() { - const view = await getQAView(); + const view = await getQAView(team); my_exercices = []; for (const v of view) { @@ -50,7 +51,13 @@ > ↻ -
+ +
++ {field} + | + {/each} +
---|
+ {team[field]} + | + {/each} +
Scénario | +Défi | +Act | +
---|---|---|
+ {#if $exercicesIdx.length == 0 && $themesIdx.length == 0}
+ |
+
+ {#if $exercicesIdx.length == 0}
+ |
+ + + | +
+ + | +||
+ + | +