diff --git a/internal/web/handlers/taskarchive/taskarchive.go b/internal/web/handlers/taskarchive/taskarchive.go index 7e07844f..8f363b4c 100644 --- a/internal/web/handlers/taskarchive/taskarchive.go +++ b/internal/web/handlers/taskarchive/taskarchive.go @@ -1,9 +1,10 @@ package taskarchive import ( + "net/http" + "github.com/volatiletech/null/v8" "github.com/volatiletech/sqlboiler/v4/queries/qm" - "net/http" "github.com/mraron/njudge/internal/web/domain/problem" "github.com/mraron/njudge/internal/web/helpers" @@ -16,107 +17,116 @@ import ( ) type TaskArchive struct { - Roots []TreeNode + Roots []TreeNode `json:"categories"` } type TreeNode struct { - ID int - Type string - Name string - Link string - SolvedStatus problem.SolvedStatus - Children []TreeNode + ID int `json:"-"` + Type string `json:"type"` + Name string `json:"title"` + Link string `json:"link"` + SolvedStatus problem.SolvedStatus `json:"solvedStatus"` + Children []TreeNode `json:"children"` } -func Get(DB *sqlx.DB, problemStore problems.Store) echo.HandlerFunc { - return func(c echo.Context) error { - tr := c.Get(i18n.TranslatorContextKey).(i18n.Translator) +func MakeTaskArchive(c echo.Context, tr i18n.Translator, DB *sqlx.DB, problemStore problems.Store, u *models.User) (*TaskArchive, error) { + lst, err := models.ProblemCategories(models.ProblemCategoryWhere.ParentID.IsNull()).All(c.Request().Context(), DB) + if err != nil { + return nil, err + } - u := c.Get("user").(*models.User) + taskArchive := &TaskArchive{Roots: make([]TreeNode, 0)} + + var dfs func(category *models.ProblemCategory, node *TreeNode) error + id := 1000 - lst, err := models.ProblemCategories(models.ProblemCategoryWhere.ParentID.IsNull()).All(c.Request().Context(), DB) + dfs = func(root *models.ProblemCategory, tree *TreeNode) error { + problemList, err := models.ProblemRels(models.ProblemRelWhere.CategoryID.EQ(null.Int{ + Int: root.ID, + Valid: true, + }), qm.OrderBy("problem")).All(c.Request().Context(), DB) if err != nil { return err } - taskArchive := TaskArchive{Roots: make([]TreeNode, 0)} - - var dfs func(category *models.ProblemCategory, node *TreeNode) error - id := 1000 - - dfs = func(root *models.ProblemCategory, tree *TreeNode) error { - problemList, err := models.ProblemRels(models.ProblemRelWhere.CategoryID.EQ(null.Int{ - Int: root.ID, - Valid: true, - }), qm.OrderBy("problem")).All(c.Request().Context(), DB) - if err != nil { - return err + for _, p := range problemList { + elem := TreeNode{ + ID: id, + Type: "problem", + Name: tr.TranslateContent(problemStore.MustGet(p.Problem).Titles()).String(), + Link: c.Echo().Reverse("getProblemMain", p.Problemset, p.Problem), + Children: make([]TreeNode, 0), + SolvedStatus: -1, } - for _, p := range problemList { - elem := TreeNode{ - ID: id, - Type: "problem", - Name: tr.TranslateContent(problemStore.MustGet(p.Problem).Titles()).String(), - Link: c.Echo().Reverse("getProblemMain", p.Problemset, p.Problem), - Children: make([]TreeNode, 0), - SolvedStatus: -1, - } - - if u != nil { - elem.SolvedStatus, err = helpers.HasUserSolved(DB.DB, u.ID, p.Problemset, p.Problem) - if err != nil { - return err - } + if u != nil { + elem.SolvedStatus, err = helpers.HasUserSolved(DB.DB, u.ID, p.Problemset, p.Problem) + if err != nil { + return err } - - tree.Children = append(tree.Children, elem) - - id++ } - subCategories, err := models.ProblemCategories(models.ProblemCategoryWhere.ParentID.EQ(null.Int{ - Int: root.ID, - Valid: true, - }), qm.OrderBy("name")).All(c.Request().Context(), DB) + tree.Children = append(tree.Children, elem) - if err != nil { - return err - } + id++ + } - for _, cat := range subCategories { - tree.Children = append(tree.Children, TreeNode{ - ID: cat.ID, - Type: "category", - Name: cat.Name, - Link: "", - Children: make([]TreeNode, 0), - SolvedStatus: -1, - }) - - if err := dfs(cat, &tree.Children[len(tree.Children)-1]); err != nil { - return err - } - } + subCategories, err := models.ProblemCategories(models.ProblemCategoryWhere.ParentID.EQ(null.Int{ + Int: root.ID, + Valid: true, + }), qm.OrderBy("name")).All(c.Request().Context(), DB) - return nil + if err != nil { + return err } - for _, start := range lst { - taskArchive.Roots = append(taskArchive.Roots, TreeNode{ - ID: start.ID, + for _, cat := range subCategories { + tree.Children = append(tree.Children, TreeNode{ + ID: cat.ID, Type: "category", - Name: start.Name, + Name: cat.Name, Link: "", Children: make([]TreeNode, 0), SolvedStatus: -1, }) - if dfs(start, &taskArchive.Roots[len(taskArchive.Roots)-1]) != nil { + if err := dfs(cat, &tree.Children[len(tree.Children)-1]); err != nil { return err } } + return nil + } + + for _, start := range lst { + taskArchive.Roots = append(taskArchive.Roots, TreeNode{ + ID: start.ID, + Type: "category", + Name: start.Name, + Link: "", + Children: make([]TreeNode, 0), + SolvedStatus: -1, + }) + + if dfs(start, &taskArchive.Roots[len(taskArchive.Roots)-1]) != nil { + return nil, err + } + } + + return taskArchive, nil +} + +func Get(DB *sqlx.DB, problemStore problems.Store) echo.HandlerFunc { + return func(c echo.Context) error { + tr := c.Get(i18n.TranslatorContextKey).(i18n.Translator) + + u := c.Get("user").(*models.User) + + taskArchive, err := MakeTaskArchive(c, tr, DB, problemStore, u) + if err != err { + return err + } + c.Set("title", tr.Translate("Archive")) return c.Render(http.StatusOK, "task_archive.gohtml", taskArchive) } diff --git a/internal/web/routes.go b/internal/web/routes.go index c36d98f3..87f284b8 100644 --- a/internal/web/routes.go +++ b/internal/web/routes.go @@ -1,11 +1,13 @@ package web import ( - "github.com/labstack/echo/v4/middleware" - "github.com/mraron/njudge/internal/web/helpers/i18n" + "net/http" "strings" "time" + "github.com/labstack/echo/v4/middleware" + "github.com/mraron/njudge/internal/web/helpers/i18n" + "github.com/labstack/echo/v4" "github.com/mraron/njudge/internal/web/extmodels" "github.com/mraron/njudge/internal/web/handlers" @@ -85,7 +87,22 @@ func (s *Server) prepareRoutes(e *echo.Echo) { prs.POST("/change_password/", profile.PostSettingsChangePassword(s.DB)) prs.POST("/misc/", profile.PostSettingsMisc(s.DB)) - v1 := e.Group("/api/v1") + apiGroup := e.Group("/api") + + v2 := apiGroup.Group("/v2") + v2.GET("/archive", func(c echo.Context) error { + tr := c.Get(i18n.TranslatorContextKey).(i18n.Translator) + + u := c.Get("user").(*models.User) + + ta, err := taskarchive.MakeTaskArchive(c, tr, s.DB, s.ProblemStore, u) + if err != nil { + return err + } + return c.JSON(http.StatusOK, ta) + }) + + v1 := apiGroup.Group("/v1") problemRelDataProvider := api.ProblemRelDataProvider{DB: s.DB.DB} v1.GET("/problem_rels", api.GetList[models.ProblemRel](problemRelDataProvider))