diff --git a/pkg/models/error.go b/pkg/models/error.go index 946bde87f10..77cde695513 100644 --- a/pkg/models/error.go +++ b/pkg/models/error.go @@ -416,7 +416,7 @@ func (err *ErrCannotArchiveDefaultProject) HTTPError() web.HTTPError { // Task errors // ============== -// ErrTaskCannotBeEmpty represents a "ErrProjectDoesNotExist" kind of error. Used if the project does not exist. +// ErrTaskCannotBeEmpty represents a "ErrTaskCannotBeEmpty" kind of error. type ErrTaskCannotBeEmpty struct{} // IsErrTaskCannotBeEmpty checks if an error is a ErrProjectDoesNotExist. @@ -426,7 +426,7 @@ func IsErrTaskCannotBeEmpty(err error) bool { } func (err ErrTaskCannotBeEmpty) Error() string { - return "Project task title cannot be empty." + return "Task title cannot be empty." } // ErrCodeTaskCannotBeEmpty holds the unique world-error code of this error @@ -434,7 +434,7 @@ const ErrCodeTaskCannotBeEmpty = 4001 // HTTPError holds the http error description func (err ErrTaskCannotBeEmpty) HTTPError() web.HTTPError { - return web.HTTPError{HTTPCode: http.StatusBadRequest, Code: ErrCodeTaskCannotBeEmpty, Message: "You must provide at least a project task title."} + return web.HTTPError{HTTPCode: http.StatusBadRequest, Code: ErrCodeTaskCannotBeEmpty, Message: "You must provide at least a task title."} } // ErrTaskDoesNotExist represents a "ErrProjectDoesNotExist" kind of error. Used if the project does not exist. diff --git a/pkg/models/label.go b/pkg/models/label.go index 01a9d278d12..ef234b79f84 100644 --- a/pkg/models/label.go +++ b/pkg/models/label.go @@ -20,6 +20,8 @@ import ( "time" "code.vikunja.io/api/pkg/user" + "code.vikunja.io/api/pkg/utils" + "code.vikunja.io/web" "xorm.io/xorm" ) @@ -32,8 +34,8 @@ type Label struct { Title string `xorm:"varchar(250) not null" json:"title" valid:"runelength(1|250)" minLength:"1" maxLength:"250"` // The label description. Description string `xorm:"longtext null" json:"description"` - // The color this label has - HexColor string `xorm:"varchar(6) null" json:"hex_color" valid:"runelength(0|6)" maxLength:"6"` + // The color this label has in hex format. + HexColor string `xorm:"varchar(6) null" json:"hex_color" valid:"runelength(0|7)" maxLength:"7"` CreatedByID int64 `xorm:"bigint not null" json:"-"` // The user who created this label @@ -71,6 +73,7 @@ func (l *Label) Create(s *xorm.Session, a web.Auth) (err error) { return } + l.HexColor = utils.NormalizeHex(l.HexColor) l.CreatedBy = u l.CreatedByID = u.ID @@ -94,6 +97,9 @@ func (l *Label) Create(s *xorm.Session, a web.Auth) (err error) { // @Failure 500 {object} models.Message "Internal error" // @Router /labels/{id} [put] func (l *Label) Update(s *xorm.Session, a web.Auth) (err error) { + + l.HexColor = utils.NormalizeHex(l.HexColor) + _, err = s. ID(l.ID). Cols( diff --git a/pkg/models/project.go b/pkg/models/project.go index 3dfeb98540e..41187c1481f 100644 --- a/pkg/models/project.go +++ b/pkg/models/project.go @@ -22,13 +22,14 @@ import ( "strings" "time" - "code.vikunja.io/api/pkg/db" - "code.vikunja.io/api/pkg/config" + "code.vikunja.io/api/pkg/db" "code.vikunja.io/api/pkg/events" "code.vikunja.io/api/pkg/files" "code.vikunja.io/api/pkg/log" "code.vikunja.io/api/pkg/user" + "code.vikunja.io/api/pkg/utils" + "code.vikunja.io/web" "xorm.io/builder" "xorm.io/xorm" @@ -45,7 +46,7 @@ type Project struct { // The unique project short identifier. Used to build task identifiers. Identifier string `xorm:"varchar(10) null" json:"identifier" valid:"runelength(0|10)" minLength:"0" maxLength:"10"` // The hex color of this project - HexColor string `xorm:"varchar(6) null" json:"hex_color" valid:"runelength(0|6)" maxLength:"6"` + HexColor string `xorm:"varchar(6) null" json:"hex_color" valid:"runelength(0|7)" maxLength:"7"` OwnerID int64 `xorm:"bigint INDEX not null" json:"-"` ParentProjectID int64 `xorm:"bigint INDEX null" json:"parent_project_id"` @@ -718,6 +719,8 @@ func CreateProject(s *xorm.Session, project *Project, auth web.Auth, createBackl return } + project.HexColor = utils.NormalizeHex(project.HexColor) + _, err = s.Insert(project) if err != nil { return @@ -831,6 +834,8 @@ func UpdateProject(s *xorm.Session, project *Project, auth web.Auth, updateProje } } + project.HexColor = utils.NormalizeHex(project.HexColor) + _, err = s. ID(project.ID). Cols(colsToUpdate...). diff --git a/pkg/models/tasks.go b/pkg/models/tasks.go index add027ecdf9..151b67de801 100644 --- a/pkg/models/tasks.go +++ b/pkg/models/tasks.go @@ -28,6 +28,7 @@ import ( "code.vikunja.io/api/pkg/events" "code.vikunja.io/api/pkg/log" "code.vikunja.io/api/pkg/user" + "code.vikunja.io/api/pkg/utils" "code.vikunja.io/web" "dario.cat/mergo" @@ -78,7 +79,7 @@ type Task struct { // An array of labels which are associated with this task. Labels []*Label `xorm:"-" json:"labels"` // The task color in hex - HexColor string `xorm:"varchar(6) null" json:"hex_color" valid:"runelength(0|6)" maxLength:"6"` + HexColor string `xorm:"varchar(6) null" json:"hex_color" valid:"runelength(0|7)" maxLength:"7"` // Determines how far a task is left from being done PercentDone float64 `xorm:"DOUBLE null" json:"percent_done"` @@ -731,7 +732,7 @@ func createTask(s *xorm.Session, t *Task, a web.Auth, updateAssignees bool) (err t.ID = 0 - // Check if we have at least a text + // Check if we have at least a title if t.Title == "" { return ErrTaskCannotBeEmpty{} } @@ -768,7 +769,11 @@ func createTask(s *xorm.Session, t *Task, a web.Auth, updateAssignees bool) (err // If no position was supplied, set a default one t.Position = calculateDefaultPosition(t.Index, t.Position) t.KanbanPosition = calculateDefaultPosition(t.Index, t.KanbanPosition) - if _, err = s.Insert(t); err != nil { + + t.HexColor = utils.NormalizeHex(t.HexColor) + + _, err = s.Insert(t) + if err != nil { return err } @@ -959,6 +964,8 @@ func (t *Task) Update(s *xorm.Session, a web.Auth) (err error) { return err } + t.HexColor = utils.NormalizeHex(t.HexColor) + ////// // Mergo does ignore nil values. Because of that, we need to check all parameters and set the updated to // nil/their nil value in the struct which is inserted. diff --git a/pkg/utils/normalize_hex.go b/pkg/utils/normalize_hex.go new file mode 100644 index 00000000000..83b7de3e5af --- /dev/null +++ b/pkg/utils/normalize_hex.go @@ -0,0 +1,27 @@ +// Vikunja is a to-do list application to facilitate your life. +// Copyright 2018-present Vikunja and contributors. All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public Licensee as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public Licensee for more details. +// +// You should have received a copy of the GNU Affero General Public Licensee +// along with this program. If not, see . + +package utils + +import "strings" + +func NormalizeHex(hex string) string { + if strings.HasPrefix(hex, "#") { + return strings.TrimPrefix(hex, "#") + } + + return hex +}