diff --git a/internal/api/problem/search.go b/internal/api/problem/search.go index 5a312dd..eab7c03 100644 --- a/internal/api/problem/search.go +++ b/internal/api/problem/search.go @@ -7,7 +7,8 @@ import ( ) type searchRequest struct { - Search string `form:"search" json:"search"` + Keyword string `form:"keyword" json:"keyword"` + Tag string `form:"tag" json:"tag"` } // Search @@ -27,13 +28,13 @@ func (h *handler) Search(c *gin.Context) { } // TODO: pagination - if req.Search == "" { + if req.Keyword == "" { // TODO: query without LIKE - problems, status := h.problemService.QueryFuzz(req.Search, true, true) + problems, status := h.problemService.QueryFuzz(req.Keyword, req.Tag, true, true) e.Pong(c, status, problems) return } else { - problems, status := h.problemService.QueryFuzz(req.Search, true, true) + problems, status := h.problemService.QueryFuzz(req.Keyword, req.Tag, true, true) e.Pong(c, status, problems) return } diff --git a/internal/api/problem/update.go b/internal/api/problem/update.go index a45e9d4..4cb8f4c 100644 --- a/internal/api/problem/update.go +++ b/internal/api/problem/update.go @@ -6,13 +6,15 @@ import ( "git.0x7f.app/WOJ/woj-server/internal/service/problem" "git.0x7f.app/WOJ/woj-server/pkg/utils" "github.com/gin-gonic/gin" + "github.com/jackc/pgtype" ) type updateRequest struct { - Pid uint `form:"pid" json:"pid"` - Title string `form:"title" json:"title"` - Statement string `form:"statement" json:"statement"` - IsEnabled bool `form:"is_enabled" json:"is_enabled"` + Pid uint `form:"pid" json:"pid"` + Title string `form:"title" json:"title"` + Statement string `form:"statement" json:"statement"` + Tags []string `form:"tags" json:"tags"` + IsEnabled bool `form:"is_enabled" json:"is_enabled"` } // Update @@ -21,10 +23,11 @@ type updateRequest struct { // @Tags problem,admin // @Accept application/x-www-form-urlencoded // @Produce json -// @Param pid formData int false "problem id, 0 for create" -// @Param title formData string false "title" -// @Param statement formData string false "statement" -// @Param is_enabled formData bool false "is enabled" +// @Param pid formData int false "problem id, 0 for create" +// @Param title formData string false "title" +// @Param statement formData string false "statement" +// @Param tags formData []string false "tags" +// @Param is_enabled formData bool false "is enabled" // @Response 200 {object} e.Response[model.Problem] "problem info without provider information" // @Security Authentication // @Router /v1/problem/update [post] @@ -60,6 +63,7 @@ func (h *handler) Update(c *gin.Context) { createData := &problem.CreateData{ Title: req.Title, Statement: req.Statement, + Tags: req.Tags, ProviderID: uid, IsEnabled: false, } @@ -83,6 +87,11 @@ func (h *handler) Update(c *gin.Context) { // update problem p.Title = utils.If(req.Title != "", req.Title, p.Title) p.Statement = utils.If(req.Statement != "", req.Statement, p.Statement) + if len(req.Tags) != 0 { + tags := pgtype.TextArray{} + _ = tags.Set(req.Tags) + p.Tags = tags + } p.IsEnabled = req.IsEnabled p, status = h.problemService.Update(p) diff --git a/internal/model/Problem.go b/internal/model/Problem.go index c72b0b9..0b9dfa6 100644 --- a/internal/model/Problem.go +++ b/internal/model/Problem.go @@ -7,11 +7,12 @@ import ( type Problem struct { gorm.Model `json:"meta"` - Title string `json:"title" gorm:"not null"` - Statement string `json:"statement" gorm:"not null"` - ProviderID uint `json:"-" gorm:"not null;index"` - Provider User `json:"provider" gorm:"foreignKey:ProviderID"` - IsEnabled bool `json:"is_enabled" gorm:"not null;index"` + Title string `json:"title" gorm:"not null"` + Statement string `json:"statement" gorm:"not null"` + Tags pgtype.TextArray `json:"tags" gorm:"type:text[]"` + ProviderID uint `json:"-" gorm:"not null;index"` + Provider User `json:"provider" gorm:"foreignKey:ProviderID"` + IsEnabled bool `json:"is_enabled" gorm:"not null;index"` } type ProblemVersion struct { diff --git a/internal/service/problem/create.go b/internal/service/problem/create.go index 41568e1..27e7c29 100644 --- a/internal/service/problem/create.go +++ b/internal/service/problem/create.go @@ -3,20 +3,25 @@ package problem import ( "git.0x7f.app/WOJ/woj-server/internal/e" "git.0x7f.app/WOJ/woj-server/internal/model" + "github.com/jackc/pgtype" "go.uber.org/zap" ) type CreateData struct { Title string Statement string + Tags []string ProviderID uint IsEnabled bool } func (s *service) Create(data *CreateData) (*model.Problem, e.Status) { + tags := pgtype.TextArray{} + _ = tags.Set(data.Tags) problem := &model.Problem{ Title: data.Title, Statement: data.Statement, + Tags: tags, ProviderID: data.ProviderID, IsEnabled: data.IsEnabled, } diff --git a/internal/service/problem/createVersion.go b/internal/service/problem/createVersion.go deleted file mode 100644 index 15b6a28..0000000 --- a/internal/service/problem/createVersion.go +++ /dev/null @@ -1,29 +0,0 @@ -package problem - -import ( - "git.0x7f.app/WOJ/woj-server/internal/e" - "git.0x7f.app/WOJ/woj-server/internal/model" - "github.com/jackc/pgtype" - "go.uber.org/zap" -) - -type CreateVersionData struct { - ProblemID uint - StorageKey string -} - -func (s *service) CreateVersion(data *CreateVersionData) (*model.ProblemVersion, e.Status) { - problemVersion := &model.ProblemVersion{ - ProblemID: data.ProblemID, - Context: pgtype.JSON{Status: pgtype.Null}, - StorageKey: data.StorageKey, - } - - err := s.db.Get().Create(problemVersion).Error - if err != nil { - s.log.Warn("DatabaseError", zap.Error(err), zap.Any("problemVersion", problemVersion)) - return nil, e.DatabaseError - } - - return problemVersion, e.Success -} diff --git a/internal/service/problem/queryFuzz.go b/internal/service/problem/queryFuzz.go deleted file mode 100644 index 20f0149..0000000 --- a/internal/service/problem/queryFuzz.go +++ /dev/null @@ -1,30 +0,0 @@ -package problem - -import ( - "git.0x7f.app/WOJ/woj-server/internal/e" - "git.0x7f.app/WOJ/woj-server/internal/model" - "go.uber.org/zap" - "gorm.io/gorm/clause" -) - -func (s *service) QueryFuzz(search string, associations bool, shouldEnable bool) ([]*model.Problem, e.Status) { - problems := make([]*model.Problem, 0) - - query := s.db.Get() - if associations { - query = query.Preload(clause.Associations) - } - if shouldEnable { - query = query.Where("is_enabled = true") - } - query = query. - Where(s.db.Get().Where("title LIKE ?", "%"+search+"%"). - Or("statement LIKE ?", "%"+search+"%")) - err := query.Find(&problems).Error - if err != nil { - s.log.Warn("DatabaseError", zap.Error(err), zap.Any("search", search)) - return nil, e.DatabaseError - } - - return problems, e.Success -} diff --git a/internal/service/problem/queryLatestVersion.go b/internal/service/problem/queryLatestVersion.go deleted file mode 100644 index b040abd..0000000 --- a/internal/service/problem/queryLatestVersion.go +++ /dev/null @@ -1,29 +0,0 @@ -package problem - -import ( - "errors" - "git.0x7f.app/WOJ/woj-server/internal/e" - "git.0x7f.app/WOJ/woj-server/internal/model" - "go.uber.org/zap" - "gorm.io/gorm" -) - -func (s *service) QueryLatestVersion(pid uint) (*model.ProblemVersion, e.Status) { - problemVersion := &model.ProblemVersion{ - ProblemID: pid, - IsEnabled: true, - } - - err := s.db.Get(). - Where(problemVersion). - Last(&problemVersion).Error - if errors.Is(err, gorm.ErrRecordNotFound) { - return nil, e.ProblemVersionNotFound - } - if err != nil { - s.log.Warn("DatabaseError", zap.Error(err), zap.Any("problemVersion", problemVersion)) - return nil, e.DatabaseError - } - - return problemVersion, e.Success -} diff --git a/internal/service/problem/queryVersion.go b/internal/service/problem/queryVersion.go deleted file mode 100644 index 6ff6e59..0000000 --- a/internal/service/problem/queryVersion.go +++ /dev/null @@ -1,27 +0,0 @@ -package problem - -import ( - "errors" - "git.0x7f.app/WOJ/woj-server/internal/e" - "git.0x7f.app/WOJ/woj-server/internal/model" - "go.uber.org/zap" - "gorm.io/gorm" -) - -func (s *service) QueryVersion(pvid uint, shouldEnable bool) (*model.ProblemVersion, e.Status) { - problemVersion := new(model.ProblemVersion) - - err := s.db.Get().First(&problemVersion, pvid).Error - if errors.Is(err, gorm.ErrRecordNotFound) { - return nil, e.ProblemVersionNotFound - } - if err != nil { - s.log.Warn("DatabaseError", zap.Error(err), zap.Any("pvid", pvid)) - return nil, e.DatabaseError - } - - if shouldEnable && !problemVersion.IsEnabled { - return nil, e.ProblemVersionNotAvailable - } - return problemVersion, e.Success -} diff --git a/internal/service/problem/service.go b/internal/service/problem/service.go index f4be009..f3fb43e 100644 --- a/internal/service/problem/service.go +++ b/internal/service/problem/service.go @@ -15,7 +15,7 @@ type Service interface { Create(data *CreateData) (*model.Problem, e.Status) Update(problem *model.Problem) (*model.Problem, e.Status) Query(pid uint, associations bool, shouldEnable bool) (*model.Problem, e.Status) - QueryFuzz(search string, associations bool, shouldEnable bool) ([]*model.Problem, e.Status) + QueryFuzz(keyword string, tag string, associations bool, shouldEnable bool) ([]*model.Problem, e.Status) CreateVersion(data *CreateVersionData) (*model.ProblemVersion, e.Status) UpdateVersion(pvid uint, values interface{}) e.Status diff --git a/internal/service/problem/updateVersion.go b/internal/service/problem/updateVersion.go deleted file mode 100644 index 9442daf..0000000 --- a/internal/service/problem/updateVersion.go +++ /dev/null @@ -1,17 +0,0 @@ -package problem - -import ( - "git.0x7f.app/WOJ/woj-server/internal/e" - "git.0x7f.app/WOJ/woj-server/internal/model" - "go.uber.org/zap" -) - -func (s *service) UpdateVersion(pvid uint, values interface{}) e.Status { - err := s.db.Get().Model(&model.ProblemVersion{}).Where("id = ?", pvid).Updates(values).Error - if err != nil { - s.log.Warn("DatabaseError", zap.Error(err), zap.Any("pvid", pvid), zap.Any("values", values)) - return e.DatabaseError - } - - return e.Success -}