From 539259effdd4f0980d21464ae1184aee21e5001a Mon Sep 17 00:00:00 2001 From: Jordan Knott Date: Wed, 27 May 2020 20:12:50 -0500 Subject: [PATCH] feature: add ability to delete & update project labels --- api/graph/generated.go | 433 ++++++++++++++++++ api/graph/models_gen.go | 20 + api/graph/schema.graphqls | 25 + api/graph/schema.resolvers.go | 24 + api/pg/pg.go | 4 + api/pg/project_label.sql.go | 76 +++ api/pg/querier.go | 4 + api/query/project_label.sql | 12 + web/package.json | 2 + web/src/App/Routes.tsx | 2 +- web/src/App/TopNavbar.tsx | 3 +- web/src/Projects/Project/Details/index.tsx | 3 - web/src/Projects/Project/index.tsx | 192 +++++--- web/src/Projects/index.tsx | 1 - web/src/index.tsx | 1 + web/src/shared/components/Card/index.tsx | 4 +- web/src/shared/components/Lists/index.tsx | 8 +- web/src/shared/components/Login/index.tsx | 1 - .../components/PopupMenu/LabelEditor.tsx | 31 +- .../components/PopupMenu/LabelManager.tsx | 9 +- web/src/shared/components/PopupMenu/Styles.ts | 45 +- web/src/shared/components/PopupMenu/index.tsx | 20 +- .../shared/components/TaskDetails/Styles.ts | 8 + .../shared/components/TaskDetails/index.tsx | 6 +- web/src/shared/components/TopNavbar/index.tsx | 3 +- web/src/shared/generated/graphql.tsx | 154 ++++++- .../graphql/createProjectLabel.graphqls | 2 + .../graphql/deleteProjectLabel.graphqls | 5 + .../graphql/updateProjectLabel.graphqls | 13 + web/src/shared/utils/draggables.ts | 12 - web/src/wdy.ts | 8 + web/yarn.lock | 151 +++++- 32 files changed, 1139 insertions(+), 143 deletions(-) create mode 100644 web/src/shared/graphql/deleteProjectLabel.graphqls create mode 100644 web/src/shared/graphql/updateProjectLabel.graphqls create mode 100644 web/src/wdy.ts diff --git a/api/graph/generated.go b/api/graph/generated.go index 28d4cf0..aac0788 100644 --- a/api/graph/generated.go +++ b/api/graph/generated.go @@ -81,11 +81,15 @@ type ComplexityRoot struct { CreateTaskGroup func(childComplexity int, input NewTaskGroup) int CreateTeam func(childComplexity int, input NewTeam) int CreateUserAccount func(childComplexity int, input NewUserAccount) int + DeleteProjectLabel func(childComplexity int, input DeleteProjectLabel) int DeleteTask func(childComplexity int, input DeleteTaskInput) int DeleteTaskGroup func(childComplexity int, input DeleteTaskGroupInput) int LogoutUser func(childComplexity int, input LogoutUser) int RemoveTaskLabel func(childComplexity int, input *RemoveTaskLabelInput) int UnassignTask func(childComplexity int, input *UnassignTaskInput) int + UpdateProjectLabel func(childComplexity int, input UpdateProjectLabel) int + UpdateProjectLabelColor func(childComplexity int, input UpdateProjectLabelColor) int + UpdateProjectLabelName func(childComplexity int, input UpdateProjectLabelName) int UpdateTaskDescription func(childComplexity int, input UpdateTaskDescriptionInput) int UpdateTaskGroupLocation func(childComplexity int, input NewTaskGroupLocation) int UpdateTaskLocation func(childComplexity int, input NewTaskLocation) int @@ -195,6 +199,10 @@ type MutationResolver interface { CreateTeam(ctx context.Context, input NewTeam) (*pg.Team, error) CreateProject(ctx context.Context, input NewProject) (*pg.Project, error) CreateProjectLabel(ctx context.Context, input NewProjectLabel) (*pg.ProjectLabel, error) + DeleteProjectLabel(ctx context.Context, input DeleteProjectLabel) (*pg.ProjectLabel, error) + UpdateProjectLabel(ctx context.Context, input UpdateProjectLabel) (*pg.ProjectLabel, error) + UpdateProjectLabelName(ctx context.Context, input UpdateProjectLabelName) (*pg.ProjectLabel, error) + UpdateProjectLabelColor(ctx context.Context, input UpdateProjectLabelColor) (*pg.ProjectLabel, error) CreateTaskGroup(ctx context.Context, input NewTaskGroup) (*pg.TaskGroup, error) UpdateTaskGroupLocation(ctx context.Context, input NewTaskGroupLocation) (*pg.TaskGroup, error) DeleteTaskGroup(ctx context.Context, input DeleteTaskGroupInput) (*DeleteTaskGroupPayload, error) @@ -445,6 +453,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Mutation.CreateUserAccount(childComplexity, args["input"].(NewUserAccount)), true + case "Mutation.deleteProjectLabel": + if e.complexity.Mutation.DeleteProjectLabel == nil { + break + } + + args, err := ec.field_Mutation_deleteProjectLabel_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.DeleteProjectLabel(childComplexity, args["input"].(DeleteProjectLabel)), true + case "Mutation.deleteTask": if e.complexity.Mutation.DeleteTask == nil { break @@ -505,6 +525,42 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Mutation.UnassignTask(childComplexity, args["input"].(*UnassignTaskInput)), true + case "Mutation.updateProjectLabel": + if e.complexity.Mutation.UpdateProjectLabel == nil { + break + } + + args, err := ec.field_Mutation_updateProjectLabel_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.UpdateProjectLabel(childComplexity, args["input"].(UpdateProjectLabel)), true + + case "Mutation.updateProjectLabelColor": + if e.complexity.Mutation.UpdateProjectLabelColor == nil { + break + } + + args, err := ec.field_Mutation_updateProjectLabelColor_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.UpdateProjectLabelColor(childComplexity, args["input"].(UpdateProjectLabelColor)), true + + case "Mutation.updateProjectLabelName": + if e.complexity.Mutation.UpdateProjectLabelName == nil { + break + } + + args, err := ec.field_Mutation_updateProjectLabelName_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.UpdateProjectLabelName(childComplexity, args["input"].(UpdateProjectLabelName)), true + case "Mutation.updateTaskDescription": if e.complexity.Mutation.UpdateTaskDescription == nil { break @@ -1277,6 +1333,26 @@ input NewProjectLabel { name: String } +input DeleteProjectLabel { + projectLabelID: UUID! +} + +input UpdateProjectLabelName { + projectLabelID: UUID! + name: String! +} + +input UpdateProjectLabel { + projectLabelID: UUID! + labelColorID: UUID! + name: String! +} + +input UpdateProjectLabelColor { + projectLabelID: UUID! + labelColorID: UUID! +} + type Mutation { createRefreshToken(input: NewRefreshToken!): RefreshToken! @@ -1285,7 +1361,12 @@ type Mutation { createTeam(input: NewTeam!): Team! createProject(input: NewProject!): Project! + createProjectLabel(input: NewProjectLabel!): ProjectLabel! + deleteProjectLabel(input: DeleteProjectLabel!): ProjectLabel! + updateProjectLabel(input: UpdateProjectLabel!): ProjectLabel! + updateProjectLabelName(input: UpdateProjectLabelName!): ProjectLabel! + updateProjectLabelColor(input: UpdateProjectLabelColor!): ProjectLabel! createTaskGroup(input: NewTaskGroup!): TaskGroup! updateTaskGroupLocation(input: NewTaskGroupLocation!): TaskGroup! @@ -1438,6 +1519,20 @@ func (ec *executionContext) field_Mutation_createUserAccount_args(ctx context.Co return args, nil } +func (ec *executionContext) field_Mutation_deleteProjectLabel_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 DeleteProjectLabel + if tmp, ok := rawArgs["input"]; ok { + arg0, err = ec.unmarshalNDeleteProjectLabel2githubᚗcomᚋjordanknottᚋprojectᚑcitadelᚋapiᚋgraphᚐDeleteProjectLabel(ctx, tmp) + if err != nil { + return nil, err + } + } + args["input"] = arg0 + return args, nil +} + func (ec *executionContext) field_Mutation_deleteTaskGroup_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -1508,6 +1603,48 @@ func (ec *executionContext) field_Mutation_unassignTask_args(ctx context.Context return args, nil } +func (ec *executionContext) field_Mutation_updateProjectLabelColor_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 UpdateProjectLabelColor + if tmp, ok := rawArgs["input"]; ok { + arg0, err = ec.unmarshalNUpdateProjectLabelColor2githubᚗcomᚋjordanknottᚋprojectᚑcitadelᚋapiᚋgraphᚐUpdateProjectLabelColor(ctx, tmp) + if err != nil { + return nil, err + } + } + args["input"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Mutation_updateProjectLabelName_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 UpdateProjectLabelName + if tmp, ok := rawArgs["input"]; ok { + arg0, err = ec.unmarshalNUpdateProjectLabelName2githubᚗcomᚋjordanknottᚋprojectᚑcitadelᚋapiᚋgraphᚐUpdateProjectLabelName(ctx, tmp) + if err != nil { + return nil, err + } + } + args["input"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Mutation_updateProjectLabel_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 UpdateProjectLabel + if tmp, ok := rawArgs["input"]; ok { + arg0, err = ec.unmarshalNUpdateProjectLabel2githubᚗcomᚋjordanknottᚋprojectᚑcitadelᚋapiᚋgraphᚐUpdateProjectLabel(ctx, tmp) + if err != nil { + return nil, err + } + } + args["input"] = arg0 + return args, nil +} + func (ec *executionContext) field_Mutation_updateTaskDescription_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -2147,6 +2284,170 @@ func (ec *executionContext) _Mutation_createProjectLabel(ctx context.Context, fi return ec.marshalNProjectLabel2ᚖgithubᚗcomᚋjordanknottᚋprojectᚑcitadelᚋapiᚋpgᚐProjectLabel(ctx, field.Selections, res) } +func (ec *executionContext) _Mutation_deleteProjectLabel(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Mutation_deleteProjectLabel_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Mutation().DeleteProjectLabel(rctx, args["input"].(DeleteProjectLabel)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*pg.ProjectLabel) + fc.Result = res + return ec.marshalNProjectLabel2ᚖgithubᚗcomᚋjordanknottᚋprojectᚑcitadelᚋapiᚋpgᚐProjectLabel(ctx, field.Selections, res) +} + +func (ec *executionContext) _Mutation_updateProjectLabel(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Mutation_updateProjectLabel_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Mutation().UpdateProjectLabel(rctx, args["input"].(UpdateProjectLabel)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*pg.ProjectLabel) + fc.Result = res + return ec.marshalNProjectLabel2ᚖgithubᚗcomᚋjordanknottᚋprojectᚑcitadelᚋapiᚋpgᚐProjectLabel(ctx, field.Selections, res) +} + +func (ec *executionContext) _Mutation_updateProjectLabelName(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Mutation_updateProjectLabelName_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Mutation().UpdateProjectLabelName(rctx, args["input"].(UpdateProjectLabelName)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*pg.ProjectLabel) + fc.Result = res + return ec.marshalNProjectLabel2ᚖgithubᚗcomᚋjordanknottᚋprojectᚑcitadelᚋapiᚋpgᚐProjectLabel(ctx, field.Selections, res) +} + +func (ec *executionContext) _Mutation_updateProjectLabelColor(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Mutation_updateProjectLabelColor_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Mutation().UpdateProjectLabelColor(rctx, args["input"].(UpdateProjectLabelColor)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*pg.ProjectLabel) + fc.Result = res + return ec.marshalNProjectLabel2ᚖgithubᚗcomᚋjordanknottᚋprojectᚑcitadelᚋapiᚋpgᚐProjectLabel(ctx, field.Selections, res) +} + func (ec *executionContext) _Mutation_createTaskGroup(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -5902,6 +6203,24 @@ func (ec *executionContext) unmarshalInputAssignTaskInput(ctx context.Context, o return it, nil } +func (ec *executionContext) unmarshalInputDeleteProjectLabel(ctx context.Context, obj interface{}) (DeleteProjectLabel, error) { + var it DeleteProjectLabel + var asMap = obj.(map[string]interface{}) + + for k, v := range asMap { + switch k { + case "projectLabelID": + var err error + it.ProjectLabelID, err = ec.unmarshalNUUID2githubᚗcomᚋgoogleᚋuuidᚐUUID(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + func (ec *executionContext) unmarshalInputDeleteTaskGroupInput(ctx context.Context, obj interface{}) (DeleteTaskGroupInput, error) { var it DeleteTaskGroupInput var asMap = obj.(map[string]interface{}) @@ -6334,6 +6653,84 @@ func (ec *executionContext) unmarshalInputUnassignTaskInput(ctx context.Context, return it, nil } +func (ec *executionContext) unmarshalInputUpdateProjectLabel(ctx context.Context, obj interface{}) (UpdateProjectLabel, error) { + var it UpdateProjectLabel + var asMap = obj.(map[string]interface{}) + + for k, v := range asMap { + switch k { + case "projectLabelID": + var err error + it.ProjectLabelID, err = ec.unmarshalNUUID2githubᚗcomᚋgoogleᚋuuidᚐUUID(ctx, v) + if err != nil { + return it, err + } + case "labelColorID": + var err error + it.LabelColorID, err = ec.unmarshalNUUID2githubᚗcomᚋgoogleᚋuuidᚐUUID(ctx, v) + if err != nil { + return it, err + } + case "name": + var err error + it.Name, err = ec.unmarshalNString2string(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputUpdateProjectLabelColor(ctx context.Context, obj interface{}) (UpdateProjectLabelColor, error) { + var it UpdateProjectLabelColor + var asMap = obj.(map[string]interface{}) + + for k, v := range asMap { + switch k { + case "projectLabelID": + var err error + it.ProjectLabelID, err = ec.unmarshalNUUID2githubᚗcomᚋgoogleᚋuuidᚐUUID(ctx, v) + if err != nil { + return it, err + } + case "labelColorID": + var err error + it.LabelColorID, err = ec.unmarshalNUUID2githubᚗcomᚋgoogleᚋuuidᚐUUID(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputUpdateProjectLabelName(ctx context.Context, obj interface{}) (UpdateProjectLabelName, error) { + var it UpdateProjectLabelName + var asMap = obj.(map[string]interface{}) + + for k, v := range asMap { + switch k { + case "projectLabelID": + var err error + it.ProjectLabelID, err = ec.unmarshalNUUID2githubᚗcomᚋgoogleᚋuuidᚐUUID(ctx, v) + if err != nil { + return it, err + } + case "name": + var err error + it.Name, err = ec.unmarshalNString2string(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + func (ec *executionContext) unmarshalInputUpdateTaskDescriptionInput(ctx context.Context, obj interface{}) (UpdateTaskDescriptionInput, error) { var it UpdateTaskDescriptionInput var asMap = obj.(map[string]interface{}) @@ -6545,6 +6942,26 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) if out.Values[i] == graphql.Null { invalids++ } + case "deleteProjectLabel": + out.Values[i] = ec._Mutation_deleteProjectLabel(ctx, field) + if out.Values[i] == graphql.Null { + invalids++ + } + case "updateProjectLabel": + out.Values[i] = ec._Mutation_updateProjectLabel(ctx, field) + if out.Values[i] == graphql.Null { + invalids++ + } + case "updateProjectLabelName": + out.Values[i] = ec._Mutation_updateProjectLabelName(ctx, field) + if out.Values[i] == graphql.Null { + invalids++ + } + case "updateProjectLabelColor": + out.Values[i] = ec._Mutation_updateProjectLabelColor(ctx, field) + if out.Values[i] == graphql.Null { + invalids++ + } case "createTaskGroup": out.Values[i] = ec._Mutation_createTaskGroup(ctx, field) if out.Values[i] == graphql.Null { @@ -7700,6 +8117,10 @@ func (ec *executionContext) marshalNBoolean2bool(ctx context.Context, sel ast.Se return res } +func (ec *executionContext) unmarshalNDeleteProjectLabel2githubᚗcomᚋjordanknottᚋprojectᚑcitadelᚋapiᚋgraphᚐDeleteProjectLabel(ctx context.Context, v interface{}) (DeleteProjectLabel, error) { + return ec.unmarshalInputDeleteProjectLabel(ctx, v) +} + func (ec *executionContext) unmarshalNDeleteTaskGroupInput2githubᚗcomᚋjordanknottᚋprojectᚑcitadelᚋapiᚋgraphᚐDeleteTaskGroupInput(ctx context.Context, v interface{}) (DeleteTaskGroupInput, error) { return ec.unmarshalInputDeleteTaskGroupInput(ctx, v) } @@ -8261,6 +8682,18 @@ func (ec *executionContext) marshalNUUID2githubᚗcomᚋgoogleᚋuuidᚐUUID(ctx return res } +func (ec *executionContext) unmarshalNUpdateProjectLabel2githubᚗcomᚋjordanknottᚋprojectᚑcitadelᚋapiᚋgraphᚐUpdateProjectLabel(ctx context.Context, v interface{}) (UpdateProjectLabel, error) { + return ec.unmarshalInputUpdateProjectLabel(ctx, v) +} + +func (ec *executionContext) unmarshalNUpdateProjectLabelColor2githubᚗcomᚋjordanknottᚋprojectᚑcitadelᚋapiᚋgraphᚐUpdateProjectLabelColor(ctx context.Context, v interface{}) (UpdateProjectLabelColor, error) { + return ec.unmarshalInputUpdateProjectLabelColor(ctx, v) +} + +func (ec *executionContext) unmarshalNUpdateProjectLabelName2githubᚗcomᚋjordanknottᚋprojectᚑcitadelᚋapiᚋgraphᚐUpdateProjectLabelName(ctx context.Context, v interface{}) (UpdateProjectLabelName, error) { + return ec.unmarshalInputUpdateProjectLabelName(ctx, v) +} + func (ec *executionContext) unmarshalNUpdateTaskDescriptionInput2githubᚗcomᚋjordanknottᚋprojectᚑcitadelᚋapiᚋgraphᚐUpdateTaskDescriptionInput(ctx context.Context, v interface{}) (UpdateTaskDescriptionInput, error) { return ec.unmarshalInputUpdateTaskDescriptionInput(ctx, v) } diff --git a/api/graph/models_gen.go b/api/graph/models_gen.go index 709bce8..a2f5972 100644 --- a/api/graph/models_gen.go +++ b/api/graph/models_gen.go @@ -17,6 +17,10 @@ type AssignTaskInput struct { UserID uuid.UUID `json:"userID"` } +type DeleteProjectLabel struct { + ProjectLabelID uuid.UUID `json:"projectLabelID"` +} + type DeleteTaskGroupInput struct { TaskGroupID uuid.UUID `json:"taskGroupID"` } @@ -130,6 +134,22 @@ type UnassignTaskInput struct { UserID uuid.UUID `json:"userID"` } +type UpdateProjectLabel struct { + ProjectLabelID uuid.UUID `json:"projectLabelID"` + LabelColorID uuid.UUID `json:"labelColorID"` + Name string `json:"name"` +} + +type UpdateProjectLabelColor struct { + ProjectLabelID uuid.UUID `json:"projectLabelID"` + LabelColorID uuid.UUID `json:"labelColorID"` +} + +type UpdateProjectLabelName struct { + ProjectLabelID uuid.UUID `json:"projectLabelID"` + Name string `json:"name"` +} + type UpdateTaskDescriptionInput struct { TaskID uuid.UUID `json:"taskID"` Description string `json:"description"` diff --git a/api/graph/schema.graphqls b/api/graph/schema.graphqls index 71b57b8..66b3b13 100644 --- a/api/graph/schema.graphqls +++ b/api/graph/schema.graphqls @@ -218,6 +218,26 @@ input NewProjectLabel { name: String } +input DeleteProjectLabel { + projectLabelID: UUID! +} + +input UpdateProjectLabelName { + projectLabelID: UUID! + name: String! +} + +input UpdateProjectLabel { + projectLabelID: UUID! + labelColorID: UUID! + name: String! +} + +input UpdateProjectLabelColor { + projectLabelID: UUID! + labelColorID: UUID! +} + type Mutation { createRefreshToken(input: NewRefreshToken!): RefreshToken! @@ -226,7 +246,12 @@ type Mutation { createTeam(input: NewTeam!): Team! createProject(input: NewProject!): Project! + createProjectLabel(input: NewProjectLabel!): ProjectLabel! + deleteProjectLabel(input: DeleteProjectLabel!): ProjectLabel! + updateProjectLabel(input: UpdateProjectLabel!): ProjectLabel! + updateProjectLabelName(input: UpdateProjectLabelName!): ProjectLabel! + updateProjectLabelColor(input: UpdateProjectLabelColor!): ProjectLabel! createTaskGroup(input: NewTaskGroup!): TaskGroup! updateTaskGroupLocation(input: NewTaskGroupLocation!): TaskGroup! diff --git a/api/graph/schema.resolvers.go b/api/graph/schema.resolvers.go index c943788..d1723bc 100644 --- a/api/graph/schema.resolvers.go +++ b/api/graph/schema.resolvers.go @@ -69,6 +69,30 @@ func (r *mutationResolver) CreateProjectLabel(ctx context.Context, input NewProj return &projectLabel, err } +func (r *mutationResolver) DeleteProjectLabel(ctx context.Context, input DeleteProjectLabel) (*pg.ProjectLabel, error) { + label, err := r.Repository.GetProjectLabelByID(ctx, input.ProjectLabelID) + if err != nil { + return &pg.ProjectLabel{}, err + } + err = r.Repository.DeleteProjectLabelByID(ctx, input.ProjectLabelID) + return &label, err +} + +func (r *mutationResolver) UpdateProjectLabel(ctx context.Context, input UpdateProjectLabel) (*pg.ProjectLabel, error) { + label, err := r.Repository.UpdateProjectLabel(ctx, pg.UpdateProjectLabelParams{ProjectLabelID: input.ProjectLabelID, LabelColorID: input.LabelColorID, Name: sql.NullString{String: input.Name, Valid: true}}) + return &label, err +} + +func (r *mutationResolver) UpdateProjectLabelName(ctx context.Context, input UpdateProjectLabelName) (*pg.ProjectLabel, error) { + label, err := r.Repository.UpdateProjectLabelName(ctx, pg.UpdateProjectLabelNameParams{ProjectLabelID: input.ProjectLabelID, Name: sql.NullString{String: input.Name, Valid: true}}) + return &label, err +} + +func (r *mutationResolver) UpdateProjectLabelColor(ctx context.Context, input UpdateProjectLabelColor) (*pg.ProjectLabel, error) { + label, err := r.Repository.UpdateProjectLabelColor(ctx, pg.UpdateProjectLabelColorParams{ProjectLabelID: input.ProjectLabelID, LabelColorID: input.LabelColorID}) + return &label, err +} + func (r *mutationResolver) CreateTaskGroup(ctx context.Context, input NewTaskGroup) (*pg.TaskGroup, error) { createdAt := time.Now().UTC() projectID, err := uuid.Parse(input.ProjectID) diff --git a/api/pg/pg.go b/api/pg/pg.go index a5bc575..3e826ec 100644 --- a/api/pg/pg.go +++ b/api/pg/pg.go @@ -25,6 +25,10 @@ type Repository interface { CreateProjectLabel(ctx context.Context, arg CreateProjectLabelParams) (ProjectLabel, error) GetProjectLabelsForProject(ctx context.Context, projectID uuid.UUID) ([]ProjectLabel, error) GetProjectLabelByID(ctx context.Context, projectLabelID uuid.UUID) (ProjectLabel, error) + DeleteProjectLabelByID(ctx context.Context, projectLabelID uuid.UUID) error + UpdateProjectLabelColor(ctx context.Context, arg UpdateProjectLabelColorParams) (ProjectLabel, error) + UpdateProjectLabelName(ctx context.Context, arg UpdateProjectLabelNameParams) (ProjectLabel, error) + UpdateProjectLabel(ctx context.Context, arg UpdateProjectLabelParams) (ProjectLabel, error) GetLabelColors(ctx context.Context) ([]LabelColor, error) CreateLabelColor(ctx context.Context, arg CreateLabelColorParams) (LabelColor, error) diff --git a/api/pg/project_label.sql.go b/api/pg/project_label.sql.go index 39a5758..8d5e5fb 100644 --- a/api/pg/project_label.sql.go +++ b/api/pg/project_label.sql.go @@ -41,6 +41,15 @@ func (q *Queries) CreateProjectLabel(ctx context.Context, arg CreateProjectLabel return i, err } +const deleteProjectLabelByID = `-- name: DeleteProjectLabelByID :exec +DELETE FROM project_label WHERE project_label_id = $1 +` + +func (q *Queries) DeleteProjectLabelByID(ctx context.Context, projectLabelID uuid.UUID) error { + _, err := q.db.ExecContext(ctx, deleteProjectLabelByID, projectLabelID) + return err +} + const getProjectLabelByID = `-- name: GetProjectLabelByID :one SELECT project_label_id, project_id, label_color_id, created_date, name FROM project_label WHERE project_label_id = $1 ` @@ -90,3 +99,70 @@ func (q *Queries) GetProjectLabelsForProject(ctx context.Context, projectID uuid } return items, nil } + +const updateProjectLabel = `-- name: UpdateProjectLabel :one +UPDATE project_label SET name = $2, label_color_id = $3 WHERE project_label_id = $1 RETURNING project_label_id, project_id, label_color_id, created_date, name +` + +type UpdateProjectLabelParams struct { + ProjectLabelID uuid.UUID `json:"project_label_id"` + Name sql.NullString `json:"name"` + LabelColorID uuid.UUID `json:"label_color_id"` +} + +func (q *Queries) UpdateProjectLabel(ctx context.Context, arg UpdateProjectLabelParams) (ProjectLabel, error) { + row := q.db.QueryRowContext(ctx, updateProjectLabel, arg.ProjectLabelID, arg.Name, arg.LabelColorID) + var i ProjectLabel + err := row.Scan( + &i.ProjectLabelID, + &i.ProjectID, + &i.LabelColorID, + &i.CreatedDate, + &i.Name, + ) + return i, err +} + +const updateProjectLabelColor = `-- name: UpdateProjectLabelColor :one +UPDATE project_label SET label_color_id = $2 WHERE project_label_id = $1 RETURNING project_label_id, project_id, label_color_id, created_date, name +` + +type UpdateProjectLabelColorParams struct { + ProjectLabelID uuid.UUID `json:"project_label_id"` + LabelColorID uuid.UUID `json:"label_color_id"` +} + +func (q *Queries) UpdateProjectLabelColor(ctx context.Context, arg UpdateProjectLabelColorParams) (ProjectLabel, error) { + row := q.db.QueryRowContext(ctx, updateProjectLabelColor, arg.ProjectLabelID, arg.LabelColorID) + var i ProjectLabel + err := row.Scan( + &i.ProjectLabelID, + &i.ProjectID, + &i.LabelColorID, + &i.CreatedDate, + &i.Name, + ) + return i, err +} + +const updateProjectLabelName = `-- name: UpdateProjectLabelName :one +UPDATE project_label SET name = $2 WHERE project_label_id = $1 RETURNING project_label_id, project_id, label_color_id, created_date, name +` + +type UpdateProjectLabelNameParams struct { + ProjectLabelID uuid.UUID `json:"project_label_id"` + Name sql.NullString `json:"name"` +} + +func (q *Queries) UpdateProjectLabelName(ctx context.Context, arg UpdateProjectLabelNameParams) (ProjectLabel, error) { + row := q.db.QueryRowContext(ctx, updateProjectLabelName, arg.ProjectLabelID, arg.Name) + var i ProjectLabel + err := row.Scan( + &i.ProjectLabelID, + &i.ProjectID, + &i.LabelColorID, + &i.CreatedDate, + &i.Name, + ) + return i, err +} diff --git a/api/pg/querier.go b/api/pg/querier.go index 62d566a..356afda 100644 --- a/api/pg/querier.go +++ b/api/pg/querier.go @@ -21,6 +21,7 @@ type Querier interface { CreateTeam(ctx context.Context, arg CreateTeamParams) (Team, error) CreateUserAccount(ctx context.Context, arg CreateUserAccountParams) (UserAccount, error) DeleteExpiredTokens(ctx context.Context) error + DeleteProjectLabelByID(ctx context.Context, projectLabelID uuid.UUID) error DeleteRefreshTokenByID(ctx context.Context, tokenID uuid.UUID) error DeleteRefreshTokenByUserID(ctx context.Context, userID uuid.UUID) error DeleteTaskAssignedByID(ctx context.Context, arg DeleteTaskAssignedByIDParams) (TaskAssigned, error) @@ -51,6 +52,9 @@ type Querier interface { GetTeamsForOrganization(ctx context.Context, organizationID uuid.UUID) ([]Team, error) GetUserAccountByID(ctx context.Context, userID uuid.UUID) (UserAccount, error) GetUserAccountByUsername(ctx context.Context, username string) (UserAccount, error) + UpdateProjectLabel(ctx context.Context, arg UpdateProjectLabelParams) (ProjectLabel, error) + UpdateProjectLabelColor(ctx context.Context, arg UpdateProjectLabelColorParams) (ProjectLabel, error) + UpdateProjectLabelName(ctx context.Context, arg UpdateProjectLabelNameParams) (ProjectLabel, error) UpdateTaskDescription(ctx context.Context, arg UpdateTaskDescriptionParams) (Task, error) UpdateTaskGroupLocation(ctx context.Context, arg UpdateTaskGroupLocationParams) (TaskGroup, error) UpdateTaskLocation(ctx context.Context, arg UpdateTaskLocationParams) (Task, error) diff --git a/api/query/project_label.sql b/api/query/project_label.sql index 110a593..196079e 100644 --- a/api/query/project_label.sql +++ b/api/query/project_label.sql @@ -7,3 +7,15 @@ SELECT * FROM project_label WHERE project_id = $1; -- name: GetProjectLabelByID :one SELECT * FROM project_label WHERE project_label_id = $1; + +-- name: DeleteProjectLabelByID :exec +DELETE FROM project_label WHERE project_label_id = $1; + +-- name: UpdateProjectLabelName :one +UPDATE project_label SET name = $2 WHERE project_label_id = $1 RETURNING *; + +-- name: UpdateProjectLabelColor :one +UPDATE project_label SET label_color_id = $2 WHERE project_label_id = $1 RETURNING *; + +-- name: UpdateProjectLabel :one +UPDATE project_label SET name = $2, label_color_id = $3 WHERE project_label_id = $1 RETURNING *; diff --git a/web/package.json b/web/package.json index 0b66fec..83460c1 100644 --- a/web/package.json +++ b/web/package.json @@ -30,6 +30,7 @@ "@types/react-router": "^5.1.4", "@types/react-router-dom": "^5.1.3", "@types/styled-components": "^5.0.0", + "@welldone-software/why-did-you-render": "^4.2.2", "apollo-cache-inmemory": "^1.6.5", "apollo-client": "^2.6.8", "apollo-link": "^1.2.13", @@ -52,6 +53,7 @@ "react-datepicker": "^2.14.1", "react-dom": "^16.12.0", "react-hook-form": "^5.2.0", + "react-markdown": "^4.3.1", "react-router": "^5.1.2", "react-router-dom": "^5.1.2", "react-scripts": "3.4.0", diff --git a/web/src/App/Routes.tsx b/web/src/App/Routes.tsx index 3906919..d28ef6b 100644 --- a/web/src/App/Routes.tsx +++ b/web/src/App/Routes.tsx @@ -16,7 +16,7 @@ const Routes = ({ history }: RoutesProps) => ( - + ); diff --git a/web/src/App/TopNavbar.tsx b/web/src/App/TopNavbar.tsx index d35bae2..6a5d4f2 100644 --- a/web/src/App/TopNavbar.tsx +++ b/web/src/App/TopNavbar.tsx @@ -41,7 +41,6 @@ const GlobalTopNavbar: React.FC = ({ name, projectMembers if (!userID) { return null; } - console.log(data); return ( <> = ({ name, projectMembers firstName={data ? data.me.firstName : ''} lastName={data ? data.me.lastName : ''} initials={!data ? '' : data.me.profileIcon.initials ?? ''} - onNotificationClick={() => console.log('beep')} + onNotificationClick={() => {}} projectMembers={projectMembers} onProfileClick={onProfileClick} /> diff --git a/web/src/Projects/Project/Details/index.tsx b/web/src/Projects/Project/Details/index.tsx index a47c196..52c50b3 100644 --- a/web/src/Projects/Project/Details/index.tsx +++ b/web/src/Projects/Project/Details/index.tsx @@ -106,7 +106,6 @@ const Details: React.FC = ({ ); }} onOpenAddMemberPopup={(task, $targetRef) => { - console.log(`task: ${task.taskID}`); showPopup( $targetRef, {}}> @@ -114,13 +113,11 @@ const Details: React.FC = ({ availableMembers={availableMembers} activeMembers={taskMembers} onMemberChange={(member, isActive) => { - console.log(`is active ${member.userID} - ${isActive}`); if (isActive) { assignTask({ variables: { taskID: data.findTask.id, userID: userID ?? '' } }); } else { unassignTask({ variables: { taskID: data.findTask.id, userID: userID ?? '' } }); } - console.log(member, isActive); }} /> , diff --git a/web/src/Projects/Project/index.tsx b/web/src/Projects/Project/index.tsx index 13f2c1c..365e326 100644 --- a/web/src/Projects/Project/index.tsx +++ b/web/src/Projects/Project/index.tsx @@ -8,7 +8,9 @@ import { useParams, Route, useRouteMatch, useHistory, RouteComponentProps } from import { useFindProjectQuery, useUpdateTaskNameMutation, + useUpdateProjectLabelMutation, useCreateTaskMutation, + useDeleteProjectLabelMutation, useDeleteTaskMutation, useUpdateTaskLocationMutation, useUpdateTaskGroupLocationMutation, @@ -31,8 +33,28 @@ import { mixin } from 'shared/utils/styles'; import LabelManager from 'shared/components/PopupMenu/LabelManager'; import LabelEditor from 'shared/components/PopupMenu/LabelEditor'; import produce from 'immer'; -import Details from './Details'; import MiniProfile from 'shared/components/MiniProfile'; +import Details from './Details'; + +const getCacheData = (client: any, projectID: string) => { + const cacheData: any = client.readQuery({ + query: FindProjectDocument, + variables: { + projectId: projectID, + }, + }); + return cacheData; +}; + +const writeCacheData = (client: any, projectID: string, cacheData: any, newData: any) => { + client.writeQuery({ + query: FindProjectDocument, + variables: { + projectId: projectID, + }, + data: { ...cacheData, findProject: newData }, + }); +}; type TaskRouteProps = { taskID: string; @@ -63,15 +85,37 @@ const ProjectMembers = styled.div` `; type LabelManagerEditorProps = { - labels: Array