add project groups to backend.
This commit is contained in:
@@ -36,6 +36,10 @@ func (d *Database) Tasks() models.TaskRepository {
|
||||
return &taskRepository{db: d.db}
|
||||
}
|
||||
|
||||
func (d *Database) ProjectGroups() models.ProjectGroupRepository {
|
||||
return &projectGroupRepository{db: d.db}
|
||||
}
|
||||
|
||||
func Setup(ctx context.Context, connect string) (*Database, error) {
|
||||
db, err := sqlx.ConnectContext(ctx, "postgres", connect)
|
||||
if err != nil {
|
||||
|
||||
@@ -54,6 +54,11 @@ func (r *projectRepository) List(ctx context.Context, filter models.ProjectFilte
|
||||
if filter.Favorite != nil {
|
||||
sq = sq.Where(squirrel.Eq{"favorite": *filter.Favorite})
|
||||
}
|
||||
if filter.Ungrouped == true {
|
||||
sq = sq.Where("project_group_id is NULL")
|
||||
} else if filter.ProjectGroupIDs != nil {
|
||||
sq = sq.Where(squirrel.Eq{"project_group_id": filter.ProjectGroupIDs})
|
||||
}
|
||||
|
||||
sq = sq.OrderBy("active", "created_time DESC")
|
||||
|
||||
@@ -86,9 +91,9 @@ func (r *projectRepository) Insert(ctx context.Context, project models.Project)
|
||||
|
||||
_, err := r.db.NamedExecContext(ctx, `
|
||||
INSERT INTO project(
|
||||
project_id, user_id, name, description, icon, active, created_time, start_time, end_time, subtract_amount, status_tag, favorite, tags
|
||||
project_id, user_id, project_group_id, name, description, icon, active, created_time, start_time, end_time, subtract_amount, status_tag, favorite, tags
|
||||
) VALUES (
|
||||
:project_id, :user_id, :name, :description, :icon, :active, :created_time, :start_time, :end_time, :subtract_amount, :status_tag, :favorite, :tags
|
||||
:project_id, :user_id, :project_group_id, :name, :description, :icon, :active, :created_time, :start_time, :end_time, :subtract_amount, :status_tag, :favorite, :tags
|
||||
)
|
||||
`, toProjectDBO(project))
|
||||
if err != nil {
|
||||
@@ -107,6 +112,7 @@ func (r *projectRepository) Update(ctx context.Context, project models.Project)
|
||||
UPDATE project SET
|
||||
name = :name,
|
||||
description = :description,
|
||||
project_group_id = :project_group_id,
|
||||
icon = :icon,
|
||||
active = :active,
|
||||
start_time = :start_time,
|
||||
@@ -144,6 +150,7 @@ func (r *projectRepository) Delete(ctx context.Context, project models.Project)
|
||||
type projectDBO struct {
|
||||
ID string `json:"id" db:"project_id"`
|
||||
UserID string `json:"-" db:"user_id"`
|
||||
ProjectGroupID *string `json:"projectGroupID" db:"project_group_id"`
|
||||
Name string `json:"name" db:"name"`
|
||||
Description string `json:"description" db:"description"`
|
||||
Icon string `json:"icon" db:"icon"`
|
||||
@@ -161,6 +168,7 @@ func toProjectDBO(project models.Project) *projectDBO {
|
||||
return &projectDBO{
|
||||
ID: project.ID,
|
||||
UserID: project.UserID,
|
||||
ProjectGroupID: project.GroupID,
|
||||
Name: project.Name,
|
||||
Description: project.Description,
|
||||
Icon: project.Icon,
|
||||
@@ -179,6 +187,7 @@ func (d *projectDBO) ToProject() *models.Project {
|
||||
return &models.Project{
|
||||
ID: d.ID,
|
||||
UserID: d.UserID,
|
||||
GroupID: d.ProjectGroupID,
|
||||
Name: d.Name,
|
||||
Description: d.Description,
|
||||
Icon: d.Icon,
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"database/sql/driver"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/gissleh/stufflog/internal/slerrors"
|
||||
"github.com/gissleh/stufflog/models"
|
||||
"github.com/jmoiron/sqlx"
|
||||
)
|
||||
|
||||
type projectGroupRepository struct {
|
||||
db *sqlx.DB
|
||||
}
|
||||
|
||||
func (r *projectGroupRepository) Find(ctx context.Context, id string) (*models.ProjectGroup, error) {
|
||||
res := projectGroupDBO{}
|
||||
err := r.db.GetContext(ctx, &res, "SELECT * FROM project_group WHERE project_group_id=$1", id)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, slerrors.NotFound("Project group")
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return res.ToProjectGroup(), nil
|
||||
}
|
||||
|
||||
func (r *projectGroupRepository) List(ctx context.Context, filter models.ProjectGroupFilter) ([]*models.ProjectGroup, error) {
|
||||
res := make([]*projectGroupDBO, 0, 16)
|
||||
err := r.db.SelectContext(ctx, &res, "SELECT * FROM project_group WHERE user_id=$1", filter.UserID)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
return []*models.ProjectGroup{}, nil
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res2 := make([]*models.ProjectGroup, 0, len(res))
|
||||
for _, pdo := range res {
|
||||
res2 = append(res2, pdo.ToProjectGroup())
|
||||
}
|
||||
|
||||
return res2, nil
|
||||
}
|
||||
|
||||
func (r *projectGroupRepository) Insert(ctx context.Context, group models.ProjectGroup) error {
|
||||
_, err := r.db.NamedExecContext(ctx, `
|
||||
INSERT INTO project_group (
|
||||
project_group_id, user_id, name, abbreviation, description, category_names
|
||||
) VALUES (
|
||||
:project_group_id, :user_id, :name, :abbreviation, :description, :category_names
|
||||
)
|
||||
`, toProjectGroupDBO(group))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *projectGroupRepository) Update(ctx context.Context, group models.ProjectGroup) error {
|
||||
if group.CategoryNames == nil {
|
||||
group.CategoryNames = make(map[string]string)
|
||||
}
|
||||
|
||||
_, err := r.db.NamedExecContext(ctx, `
|
||||
UPDATE project_group SET
|
||||
name = :name,
|
||||
abbreviation = :abbreviation,
|
||||
description = :description,
|
||||
category_names = :category_names
|
||||
WHERE project_group_id = :project_group_id
|
||||
`, toProjectGroupDBO(group))
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *projectGroupRepository) Delete(ctx context.Context, group models.ProjectGroup) error {
|
||||
_, err := r.db.ExecContext(ctx, `DELETE FROM project_group WHERE project_group_id=$1`, group.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = r.db.ExecContext(ctx, "UPDATE project SET project_group_id=NULL where project_group_id=$1", group.ID)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type projectGroupDBO struct {
|
||||
ID string `db:"project_group_id"`
|
||||
UserID string `db:"user_id"`
|
||||
Name string `db:"name"`
|
||||
Description string `db:"description"`
|
||||
Abbreviation string `db:"abbreviation"`
|
||||
CategoryNames jsonMap `db:"category_names"`
|
||||
}
|
||||
|
||||
func (dbo *projectGroupDBO) ToProjectGroup() *models.ProjectGroup {
|
||||
return &models.ProjectGroup{
|
||||
ID: dbo.ID,
|
||||
UserID: dbo.UserID,
|
||||
Name: dbo.Name,
|
||||
Description: dbo.Description,
|
||||
Abbreviation: dbo.Abbreviation,
|
||||
CategoryNames: dbo.CategoryNames,
|
||||
}
|
||||
}
|
||||
|
||||
func toProjectGroupDBO(group models.ProjectGroup) projectGroupDBO {
|
||||
return projectGroupDBO{
|
||||
ID: group.ID,
|
||||
UserID: group.UserID,
|
||||
Name: group.Name,
|
||||
Description: group.Description,
|
||||
Abbreviation: group.Abbreviation,
|
||||
CategoryNames: group.CategoryNames,
|
||||
}
|
||||
}
|
||||
|
||||
type jsonMap map[string]string
|
||||
|
||||
func (m jsonMap) Value() (driver.Value, error) {
|
||||
return json.Marshal(m)
|
||||
}
|
||||
|
||||
func (m *jsonMap) Scan(value interface{}) error {
|
||||
b, ok := value.([]byte)
|
||||
if !ok {
|
||||
return errors.New("type assertion to []byte failed")
|
||||
}
|
||||
|
||||
return json.Unmarshal(b, m)
|
||||
}
|
||||
Reference in New Issue
Block a user