feature: add ability to delete & update project labels

This commit is contained in:
Jordan Knott 2020-05-27 20:12:50 -05:00
parent cbcd8c5f82
commit 539259effd
32 changed files with 1139 additions and 143 deletions

View File

@ -81,11 +81,15 @@ type ComplexityRoot struct {
CreateTaskGroup func(childComplexity int, input NewTaskGroup) int CreateTaskGroup func(childComplexity int, input NewTaskGroup) int
CreateTeam func(childComplexity int, input NewTeam) int CreateTeam func(childComplexity int, input NewTeam) int
CreateUserAccount func(childComplexity int, input NewUserAccount) int CreateUserAccount func(childComplexity int, input NewUserAccount) int
DeleteProjectLabel func(childComplexity int, input DeleteProjectLabel) int
DeleteTask func(childComplexity int, input DeleteTaskInput) int DeleteTask func(childComplexity int, input DeleteTaskInput) int
DeleteTaskGroup func(childComplexity int, input DeleteTaskGroupInput) int DeleteTaskGroup func(childComplexity int, input DeleteTaskGroupInput) int
LogoutUser func(childComplexity int, input LogoutUser) int LogoutUser func(childComplexity int, input LogoutUser) int
RemoveTaskLabel func(childComplexity int, input *RemoveTaskLabelInput) int RemoveTaskLabel func(childComplexity int, input *RemoveTaskLabelInput) int
UnassignTask func(childComplexity int, input *UnassignTaskInput) 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 UpdateTaskDescription func(childComplexity int, input UpdateTaskDescriptionInput) int
UpdateTaskGroupLocation func(childComplexity int, input NewTaskGroupLocation) int UpdateTaskGroupLocation func(childComplexity int, input NewTaskGroupLocation) int
UpdateTaskLocation func(childComplexity int, input NewTaskLocation) int UpdateTaskLocation func(childComplexity int, input NewTaskLocation) int
@ -195,6 +199,10 @@ type MutationResolver interface {
CreateTeam(ctx context.Context, input NewTeam) (*pg.Team, error) CreateTeam(ctx context.Context, input NewTeam) (*pg.Team, error)
CreateProject(ctx context.Context, input NewProject) (*pg.Project, error) CreateProject(ctx context.Context, input NewProject) (*pg.Project, error)
CreateProjectLabel(ctx context.Context, input NewProjectLabel) (*pg.ProjectLabel, 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) CreateTaskGroup(ctx context.Context, input NewTaskGroup) (*pg.TaskGroup, error)
UpdateTaskGroupLocation(ctx context.Context, input NewTaskGroupLocation) (*pg.TaskGroup, error) UpdateTaskGroupLocation(ctx context.Context, input NewTaskGroupLocation) (*pg.TaskGroup, error)
DeleteTaskGroup(ctx context.Context, input DeleteTaskGroupInput) (*DeleteTaskGroupPayload, 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 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": case "Mutation.deleteTask":
if e.complexity.Mutation.DeleteTask == nil { if e.complexity.Mutation.DeleteTask == nil {
break break
@ -505,6 +525,42 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.Mutation.UnassignTask(childComplexity, args["input"].(*UnassignTaskInput)), true 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": case "Mutation.updateTaskDescription":
if e.complexity.Mutation.UpdateTaskDescription == nil { if e.complexity.Mutation.UpdateTaskDescription == nil {
break break
@ -1277,6 +1333,26 @@ input NewProjectLabel {
name: String 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 { type Mutation {
createRefreshToken(input: NewRefreshToken!): RefreshToken! createRefreshToken(input: NewRefreshToken!): RefreshToken!
@ -1285,7 +1361,12 @@ type Mutation {
createTeam(input: NewTeam!): Team! createTeam(input: NewTeam!): Team!
createProject(input: NewProject!): Project! createProject(input: NewProject!): Project!
createProjectLabel(input: NewProjectLabel!): ProjectLabel! createProjectLabel(input: NewProjectLabel!): ProjectLabel!
deleteProjectLabel(input: DeleteProjectLabel!): ProjectLabel!
updateProjectLabel(input: UpdateProjectLabel!): ProjectLabel!
updateProjectLabelName(input: UpdateProjectLabelName!): ProjectLabel!
updateProjectLabelColor(input: UpdateProjectLabelColor!): ProjectLabel!
createTaskGroup(input: NewTaskGroup!): TaskGroup! createTaskGroup(input: NewTaskGroup!): TaskGroup!
updateTaskGroupLocation(input: NewTaskGroupLocation!): TaskGroup! updateTaskGroupLocation(input: NewTaskGroupLocation!): TaskGroup!
@ -1438,6 +1519,20 @@ func (ec *executionContext) field_Mutation_createUserAccount_args(ctx context.Co
return args, nil 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) { func (ec *executionContext) field_Mutation_deleteTaskGroup_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
var err error var err error
args := map[string]interface{}{} args := map[string]interface{}{}
@ -1508,6 +1603,48 @@ func (ec *executionContext) field_Mutation_unassignTask_args(ctx context.Context
return args, nil 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) { func (ec *executionContext) field_Mutation_updateTaskDescription_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
var err error var err error
args := map[string]interface{}{} 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) 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) { func (ec *executionContext) _Mutation_createTaskGroup(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
@ -5902,6 +6203,24 @@ func (ec *executionContext) unmarshalInputAssignTaskInput(ctx context.Context, o
return it, nil 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) { func (ec *executionContext) unmarshalInputDeleteTaskGroupInput(ctx context.Context, obj interface{}) (DeleteTaskGroupInput, error) {
var it DeleteTaskGroupInput var it DeleteTaskGroupInput
var asMap = obj.(map[string]interface{}) var asMap = obj.(map[string]interface{})
@ -6334,6 +6653,84 @@ func (ec *executionContext) unmarshalInputUnassignTaskInput(ctx context.Context,
return it, nil 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) { func (ec *executionContext) unmarshalInputUpdateTaskDescriptionInput(ctx context.Context, obj interface{}) (UpdateTaskDescriptionInput, error) {
var it UpdateTaskDescriptionInput var it UpdateTaskDescriptionInput
var asMap = obj.(map[string]interface{}) 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 { if out.Values[i] == graphql.Null {
invalids++ 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": case "createTaskGroup":
out.Values[i] = ec._Mutation_createTaskGroup(ctx, field) out.Values[i] = ec._Mutation_createTaskGroup(ctx, field)
if out.Values[i] == graphql.Null { if out.Values[i] == graphql.Null {
@ -7700,6 +8117,10 @@ func (ec *executionContext) marshalNBoolean2bool(ctx context.Context, sel ast.Se
return res 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) { func (ec *executionContext) unmarshalNDeleteTaskGroupInput2githubᚗcomᚋjordanknottᚋprojectᚑcitadelᚋapiᚋgraphᚐDeleteTaskGroupInput(ctx context.Context, v interface{}) (DeleteTaskGroupInput, error) {
return ec.unmarshalInputDeleteTaskGroupInput(ctx, v) return ec.unmarshalInputDeleteTaskGroupInput(ctx, v)
} }
@ -8261,6 +8682,18 @@ func (ec *executionContext) marshalNUUID2githubᚗcomᚋgoogleᚋuuidᚐUUID(ctx
return res 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) { func (ec *executionContext) unmarshalNUpdateTaskDescriptionInput2githubᚗcomᚋjordanknottᚋprojectᚑcitadelᚋapiᚋgraphᚐUpdateTaskDescriptionInput(ctx context.Context, v interface{}) (UpdateTaskDescriptionInput, error) {
return ec.unmarshalInputUpdateTaskDescriptionInput(ctx, v) return ec.unmarshalInputUpdateTaskDescriptionInput(ctx, v)
} }

View File

@ -17,6 +17,10 @@ type AssignTaskInput struct {
UserID uuid.UUID `json:"userID"` UserID uuid.UUID `json:"userID"`
} }
type DeleteProjectLabel struct {
ProjectLabelID uuid.UUID `json:"projectLabelID"`
}
type DeleteTaskGroupInput struct { type DeleteTaskGroupInput struct {
TaskGroupID uuid.UUID `json:"taskGroupID"` TaskGroupID uuid.UUID `json:"taskGroupID"`
} }
@ -130,6 +134,22 @@ type UnassignTaskInput struct {
UserID uuid.UUID `json:"userID"` 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 { type UpdateTaskDescriptionInput struct {
TaskID uuid.UUID `json:"taskID"` TaskID uuid.UUID `json:"taskID"`
Description string `json:"description"` Description string `json:"description"`

View File

@ -218,6 +218,26 @@ input NewProjectLabel {
name: String 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 { type Mutation {
createRefreshToken(input: NewRefreshToken!): RefreshToken! createRefreshToken(input: NewRefreshToken!): RefreshToken!
@ -226,7 +246,12 @@ type Mutation {
createTeam(input: NewTeam!): Team! createTeam(input: NewTeam!): Team!
createProject(input: NewProject!): Project! createProject(input: NewProject!): Project!
createProjectLabel(input: NewProjectLabel!): ProjectLabel! createProjectLabel(input: NewProjectLabel!): ProjectLabel!
deleteProjectLabel(input: DeleteProjectLabel!): ProjectLabel!
updateProjectLabel(input: UpdateProjectLabel!): ProjectLabel!
updateProjectLabelName(input: UpdateProjectLabelName!): ProjectLabel!
updateProjectLabelColor(input: UpdateProjectLabelColor!): ProjectLabel!
createTaskGroup(input: NewTaskGroup!): TaskGroup! createTaskGroup(input: NewTaskGroup!): TaskGroup!
updateTaskGroupLocation(input: NewTaskGroupLocation!): TaskGroup! updateTaskGroupLocation(input: NewTaskGroupLocation!): TaskGroup!

View File

@ -69,6 +69,30 @@ func (r *mutationResolver) CreateProjectLabel(ctx context.Context, input NewProj
return &projectLabel, err 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) { func (r *mutationResolver) CreateTaskGroup(ctx context.Context, input NewTaskGroup) (*pg.TaskGroup, error) {
createdAt := time.Now().UTC() createdAt := time.Now().UTC()
projectID, err := uuid.Parse(input.ProjectID) projectID, err := uuid.Parse(input.ProjectID)

View File

@ -25,6 +25,10 @@ type Repository interface {
CreateProjectLabel(ctx context.Context, arg CreateProjectLabelParams) (ProjectLabel, error) CreateProjectLabel(ctx context.Context, arg CreateProjectLabelParams) (ProjectLabel, error)
GetProjectLabelsForProject(ctx context.Context, projectID uuid.UUID) ([]ProjectLabel, error) GetProjectLabelsForProject(ctx context.Context, projectID uuid.UUID) ([]ProjectLabel, error)
GetProjectLabelByID(ctx context.Context, projectLabelID 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) GetLabelColors(ctx context.Context) ([]LabelColor, error)
CreateLabelColor(ctx context.Context, arg CreateLabelColorParams) (LabelColor, error) CreateLabelColor(ctx context.Context, arg CreateLabelColorParams) (LabelColor, error)

View File

@ -41,6 +41,15 @@ func (q *Queries) CreateProjectLabel(ctx context.Context, arg CreateProjectLabel
return i, err 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 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 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 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
}

View File

@ -21,6 +21,7 @@ type Querier interface {
CreateTeam(ctx context.Context, arg CreateTeamParams) (Team, error) CreateTeam(ctx context.Context, arg CreateTeamParams) (Team, error)
CreateUserAccount(ctx context.Context, arg CreateUserAccountParams) (UserAccount, error) CreateUserAccount(ctx context.Context, arg CreateUserAccountParams) (UserAccount, error)
DeleteExpiredTokens(ctx context.Context) error DeleteExpiredTokens(ctx context.Context) error
DeleteProjectLabelByID(ctx context.Context, projectLabelID uuid.UUID) error
DeleteRefreshTokenByID(ctx context.Context, tokenID uuid.UUID) error DeleteRefreshTokenByID(ctx context.Context, tokenID uuid.UUID) error
DeleteRefreshTokenByUserID(ctx context.Context, userID uuid.UUID) error DeleteRefreshTokenByUserID(ctx context.Context, userID uuid.UUID) error
DeleteTaskAssignedByID(ctx context.Context, arg DeleteTaskAssignedByIDParams) (TaskAssigned, 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) GetTeamsForOrganization(ctx context.Context, organizationID uuid.UUID) ([]Team, error)
GetUserAccountByID(ctx context.Context, userID uuid.UUID) (UserAccount, error) GetUserAccountByID(ctx context.Context, userID uuid.UUID) (UserAccount, error)
GetUserAccountByUsername(ctx context.Context, username string) (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) UpdateTaskDescription(ctx context.Context, arg UpdateTaskDescriptionParams) (Task, error)
UpdateTaskGroupLocation(ctx context.Context, arg UpdateTaskGroupLocationParams) (TaskGroup, error) UpdateTaskGroupLocation(ctx context.Context, arg UpdateTaskGroupLocationParams) (TaskGroup, error)
UpdateTaskLocation(ctx context.Context, arg UpdateTaskLocationParams) (Task, error) UpdateTaskLocation(ctx context.Context, arg UpdateTaskLocationParams) (Task, error)

View File

@ -7,3 +7,15 @@ SELECT * FROM project_label WHERE project_id = $1;
-- name: GetProjectLabelByID :one -- name: GetProjectLabelByID :one
SELECT * FROM project_label WHERE project_label_id = $1; 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 *;

View File

@ -30,6 +30,7 @@
"@types/react-router": "^5.1.4", "@types/react-router": "^5.1.4",
"@types/react-router-dom": "^5.1.3", "@types/react-router-dom": "^5.1.3",
"@types/styled-components": "^5.0.0", "@types/styled-components": "^5.0.0",
"@welldone-software/why-did-you-render": "^4.2.2",
"apollo-cache-inmemory": "^1.6.5", "apollo-cache-inmemory": "^1.6.5",
"apollo-client": "^2.6.8", "apollo-client": "^2.6.8",
"apollo-link": "^1.2.13", "apollo-link": "^1.2.13",
@ -52,6 +53,7 @@
"react-datepicker": "^2.14.1", "react-datepicker": "^2.14.1",
"react-dom": "^16.12.0", "react-dom": "^16.12.0",
"react-hook-form": "^5.2.0", "react-hook-form": "^5.2.0",
"react-markdown": "^4.3.1",
"react-router": "^5.1.2", "react-router": "^5.1.2",
"react-router-dom": "^5.1.2", "react-router-dom": "^5.1.2",
"react-scripts": "3.4.0", "react-scripts": "3.4.0",

View File

@ -16,7 +16,7 @@ const Routes = ({ history }: RoutesProps) => (
<Route exact path="/login" component={Login} /> <Route exact path="/login" component={Login} />
<Route exact path="/" component={Dashboard} /> <Route exact path="/" component={Dashboard} />
<Route exact path="/projects" component={Projects} /> <Route exact path="/projects" component={Projects} />
<Route path="/projects/:projectId" component={Project} /> <Route path="/projects/:projectID" component={Project} />
</Switch> </Switch>
); );

View File

@ -41,7 +41,6 @@ const GlobalTopNavbar: React.FC<GlobalTopNavbarProps> = ({ name, projectMembers
if (!userID) { if (!userID) {
return null; return null;
} }
console.log(data);
return ( return (
<> <>
<TopNavbar <TopNavbar
@ -50,7 +49,7 @@ const GlobalTopNavbar: React.FC<GlobalTopNavbarProps> = ({ name, projectMembers
firstName={data ? data.me.firstName : ''} firstName={data ? data.me.firstName : ''}
lastName={data ? data.me.lastName : ''} lastName={data ? data.me.lastName : ''}
initials={!data ? '' : data.me.profileIcon.initials ?? ''} initials={!data ? '' : data.me.profileIcon.initials ?? ''}
onNotificationClick={() => console.log('beep')} onNotificationClick={() => {}}
projectMembers={projectMembers} projectMembers={projectMembers}
onProfileClick={onProfileClick} onProfileClick={onProfileClick}
/> />

View File

@ -106,7 +106,6 @@ const Details: React.FC<DetailsProps> = ({
); );
}} }}
onOpenAddMemberPopup={(task, $targetRef) => { onOpenAddMemberPopup={(task, $targetRef) => {
console.log(`task: ${task.taskID}`);
showPopup( showPopup(
$targetRef, $targetRef,
<Popup title="Members" tab={0} onClose={() => {}}> <Popup title="Members" tab={0} onClose={() => {}}>
@ -114,13 +113,11 @@ const Details: React.FC<DetailsProps> = ({
availableMembers={availableMembers} availableMembers={availableMembers}
activeMembers={taskMembers} activeMembers={taskMembers}
onMemberChange={(member, isActive) => { onMemberChange={(member, isActive) => {
console.log(`is active ${member.userID} - ${isActive}`);
if (isActive) { if (isActive) {
assignTask({ variables: { taskID: data.findTask.id, userID: userID ?? '' } }); assignTask({ variables: { taskID: data.findTask.id, userID: userID ?? '' } });
} else { } else {
unassignTask({ variables: { taskID: data.findTask.id, userID: userID ?? '' } }); unassignTask({ variables: { taskID: data.findTask.id, userID: userID ?? '' } });
} }
console.log(member, isActive);
}} }}
/> />
</Popup>, </Popup>,

View File

@ -8,7 +8,9 @@ import { useParams, Route, useRouteMatch, useHistory, RouteComponentProps } from
import { import {
useFindProjectQuery, useFindProjectQuery,
useUpdateTaskNameMutation, useUpdateTaskNameMutation,
useUpdateProjectLabelMutation,
useCreateTaskMutation, useCreateTaskMutation,
useDeleteProjectLabelMutation,
useDeleteTaskMutation, useDeleteTaskMutation,
useUpdateTaskLocationMutation, useUpdateTaskLocationMutation,
useUpdateTaskGroupLocationMutation, useUpdateTaskGroupLocationMutation,
@ -31,8 +33,28 @@ import { mixin } from 'shared/utils/styles';
import LabelManager from 'shared/components/PopupMenu/LabelManager'; import LabelManager from 'shared/components/PopupMenu/LabelManager';
import LabelEditor from 'shared/components/PopupMenu/LabelEditor'; import LabelEditor from 'shared/components/PopupMenu/LabelEditor';
import produce from 'immer'; import produce from 'immer';
import Details from './Details';
import MiniProfile from 'shared/components/MiniProfile'; 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 = { type TaskRouteProps = {
taskID: string; taskID: string;
@ -63,15 +85,37 @@ const ProjectMembers = styled.div`
`; `;
type LabelManagerEditorProps = { type LabelManagerEditorProps = {
labels: Array<Label>; labels: React.RefObject<Array<Label>>;
projectID: string; projectID: string;
labelColors: Array<LabelColor>; labelColors: Array<LabelColor>;
}; };
const LabelManagerEditor: React.FC<LabelManagerEditorProps> = ({ labels: initialLabels, projectID, labelColors }) => { const LabelManagerEditor: React.FC<LabelManagerEditorProps> = ({ labels: labelsRef, projectID, labelColors }) => {
const [labels, setLabels] = useState<Array<Label>>(initialLabels);
const [currentLabel, setCurrentLabel] = useState(''); const [currentLabel, setCurrentLabel] = useState('');
const [createProjectLabel] = useCreateProjectLabelMutation(); const [createProjectLabel] = useCreateProjectLabelMutation({
update: (client, newLabelData) => {
const cacheData = getCacheData(client, projectID);
const newData = {
...cacheData.findProject,
labels: [...cacheData.findProject.labels, { ...newLabelData.data.createProjectLabel }],
};
writeCacheData(client, projectID, cacheData, newData);
},
});
const [updateProjectLabel] = useUpdateProjectLabelMutation();
const [deleteProjectLabel] = useDeleteProjectLabelMutation({
update: (client, newLabelData) => {
const cacheData = getCacheData(client, projectID);
const newData = {
...cacheData.findProject,
labels: cacheData.findProject.labels.filter(
(label: any) => label.id !== newLabelData.data.deleteProjectLabel.id,
),
};
writeCacheData(client, projectID, cacheData, newData);
},
});
const labels = labelsRef.current ? labelsRef.current : [];
const { setTab } = usePopup(); const { setTab } = usePopup();
return ( return (
<> <>
@ -95,15 +139,14 @@ const LabelManagerEditor: React.FC<LabelManagerEditorProps> = ({ labels: initial
<LabelEditor <LabelEditor
labelColors={labelColors} labelColors={labelColors}
label={labels.find(label => label.labelId === currentLabel) ?? null} label={labels.find(label => label.labelId === currentLabel) ?? null}
onLabelEdit={(_labelId, name, color) => { onLabelEdit={(projectLabelID, name, color) => {
setLabels( if (projectLabelID) {
produce(labels, draftState => { updateProjectLabel({ variables: { projectLabelID, labelColorID: color.id, name } });
const idx = labels.findIndex(label => label.labelId === currentLabel); }
if (idx !== -1) { setTab(0);
draftState[idx] = { ...draftState[idx], name, labelColor: color }; }}
} onLabelDelete={labelID => {
}), deleteProjectLabel({ variables: { projectLabelID: labelID } });
);
setTab(0); setTab(0);
}} }}
/> />
@ -113,8 +156,6 @@ const LabelManagerEditor: React.FC<LabelManagerEditorProps> = ({ labels: initial
labelColors={labelColors} labelColors={labelColors}
label={null} label={null}
onLabelEdit={(_labelId, name, color) => { onLabelEdit={(_labelId, name, color) => {
console.log(name, color);
setLabels([...labels, { labelId: name, name, labelColor: color, active: false }]);
createProjectLabel({ variables: { projectID, labelColorID: color.id, name } }); createProjectLabel({ variables: { projectID, labelColorID: color.id, name } });
setTab(0); setTab(0);
}} }}
@ -125,13 +166,12 @@ const LabelManagerEditor: React.FC<LabelManagerEditorProps> = ({ labels: initial
}; };
interface ProjectParams { interface ProjectParams {
projectId: string; projectID: string;
} }
const initialState: BoardState = { tasks: {}, columns: {} }; const initialState: BoardState = { tasks: {}, columns: {} };
const initialPopupState = { left: 0, top: 0, isOpen: false, taskGroupID: '' }; const initialPopupState = { left: 0, top: 0, isOpen: false, taskGroupID: '' };
const initialQuickCardEditorState: QuickCardEditorState = { isOpen: false, top: 0, left: 0 }; const initialQuickCardEditorState: QuickCardEditorState = { isOpen: false, top: 0, left: 0 };
const initialLabelsPopupState = { taskID: '', isOpen: false, top: 0, left: 0 };
const initialTaskDetailsState = { isOpen: false, taskID: '' }; const initialTaskDetailsState = { isOpen: false, taskID: '' };
const ProjectBar = styled.div` const ProjectBar = styled.div`
@ -168,14 +208,11 @@ const ProjectActionText = styled.span`
`; `;
const Project = () => { const Project = () => {
const { projectId } = useParams<ProjectParams>(); const { projectID } = useParams<ProjectParams>();
const match = useRouteMatch(); const match = useRouteMatch();
const history = useHistory();
const [updateTaskDescription] = useUpdateTaskDescriptionMutation(); const [updateTaskDescription] = useUpdateTaskDescriptionMutation();
const [listsData, setListsData] = useState(initialState); const [listsData, setListsData] = useState(initialState);
const [popupData, setPopupData] = useState(initialPopupState);
const [taskDetails, setTaskDetails] = useState(initialTaskDetailsState);
const [quickCardEditor, setQuickCardEditor] = useState(initialQuickCardEditorState); const [quickCardEditor, setQuickCardEditor] = useState(initialQuickCardEditorState);
const [updateTaskLocation] = useUpdateTaskLocationMutation(); const [updateTaskLocation] = useUpdateTaskLocationMutation();
const [updateTaskGroupLocation] = useUpdateTaskGroupLocationMutation(); const [updateTaskGroupLocation] = useUpdateTaskGroupLocationMutation();
@ -184,6 +221,17 @@ const Project = () => {
onCompleted: deletedTaskGroupData => { onCompleted: deletedTaskGroupData => {
setListsData(BoardStateUtils.deleteTaskGroup(listsData, deletedTaskGroupData.deleteTaskGroup.taskGroup.id)); setListsData(BoardStateUtils.deleteTaskGroup(listsData, deletedTaskGroupData.deleteTaskGroup.taskGroup.id));
}, },
update: (client, deletedTaskGroupData) => {
const cacheData = getCacheData(client, projectID);
const newData = {
...cacheData.findProject,
taskGroups: cacheData.findProject.taskGroups.filter(
(taskGroup: any) => taskGroup.id !== deletedTaskGroupData.data.deleteTaskGroup.taskGroup.id,
),
};
writeCacheData(client, projectID, cacheData, newData);
},
}); });
const [createTaskGroup] = useCreateTaskGroupMutation({ const [createTaskGroup] = useCreateTaskGroupMutation({
@ -195,6 +243,15 @@ const Project = () => {
}; };
setListsData(BoardStateUtils.addTaskGroup(listsData, newTaskGroup)); setListsData(BoardStateUtils.addTaskGroup(listsData, newTaskGroup));
}, },
update: (client, newTaskGroupData) => {
const cacheData = getCacheData(client, projectID);
const newData = {
...cacheData.findProject,
taskGroups: [...cacheData.findProject.taskGroups, { ...newTaskGroupData.data.createTaskGroup, tasks: [] }],
};
writeCacheData(client, projectID, cacheData, newData);
},
}); });
const [createTask] = useCreateTaskMutation({ const [createTask] = useCreateTaskMutation({
@ -208,14 +265,7 @@ const Project = () => {
setListsData(BoardStateUtils.addTask(listsData, newTask)); setListsData(BoardStateUtils.addTask(listsData, newTask));
}, },
update: (client, newTaskData) => { update: (client, newTaskData) => {
const cacheData: any = client.readQuery({ const cacheData = getCacheData(client, projectID);
query: FindProjectDocument,
variables: {
projectId: projectId,
},
});
console.log(cacheData);
console.log(newTaskData);
const newTaskGroups = produce(cacheData.findProject.taskGroups, (draftState: any) => { const newTaskGroups = produce(cacheData.findProject.taskGroups, (draftState: any) => {
const targetIndex = draftState.findIndex( const targetIndex = draftState.findIndex(
(taskGroup: any) => taskGroup.id === newTaskData.data.createTask.taskGroup.id, (taskGroup: any) => taskGroup.id === newTaskData.data.createTask.taskGroup.id,
@ -225,18 +275,11 @@ const Project = () => {
tasks: [...draftState[targetIndex].tasks, { ...newTaskData.data.createTask }], tasks: [...draftState[targetIndex].tasks, { ...newTaskData.data.createTask }],
}; };
}); });
console.log(newTaskGroups);
const newData = { const newData = {
...cacheData.findProject, ...cacheData.findProject,
taskGroups: newTaskGroups, taskGroups: newTaskGroups,
}; };
client.writeQuery({ writeCacheData(client, projectID, cacheData, newData);
query: FindProjectDocument,
variables: {
projectId: projectId,
},
data: { findProject: newData },
});
}, },
}); });
@ -254,9 +297,8 @@ const Project = () => {
}, },
}); });
const { loading, data, refetch } = useFindProjectQuery({ const { loading, data, refetch } = useFindProjectQuery({
variables: { projectId }, variables: { projectId: projectID },
}); });
console.log(`loading ${loading} - ${data}`);
const onCardCreate = (taskGroupID: string, name: string) => { const onCardCreate = (taskGroupID: string, name: string) => {
const taskGroupTasks = Object.values(listsData.tasks).filter( const taskGroupTasks = Object.values(listsData.tasks).filter(
@ -278,14 +320,29 @@ const Project = () => {
taskGroupID: droppedTask.taskGroup.taskGroupID, taskGroupID: droppedTask.taskGroup.taskGroupID,
position: droppedTask.position, position: droppedTask.position,
}, },
optimisticResponse: {
updateTaskLocation: {
name: droppedTask.name,
id: droppedTask.taskID,
position: droppedTask.position,
createdAt: '',
},
},
}); });
setListsData(BoardStateUtils.updateTask(listsData, droppedTask)); setListsData(BoardStateUtils.updateTask(listsData, droppedTask));
}; };
const onListDrop = (droppedColumn: TaskGroup) => { const onListDrop = (droppedColumn: TaskGroup) => {
console.log(`list drop ${droppedColumn.taskGroupID}`);
updateTaskGroupLocation({ updateTaskGroupLocation({
variables: { taskGroupID: droppedColumn.taskGroupID, position: droppedColumn.position }, variables: { taskGroupID: droppedColumn.taskGroupID, position: droppedColumn.position },
optimisticResponse: {
updateTaskGroupLocation: {
id: droppedColumn.taskGroupID,
position: droppedColumn.position,
},
},
}); });
setListsData(BoardStateUtils.updateTaskGroup(listsData, droppedColumn)); // setListsData(BoardStateUtils.updateTaskGroup(listsData, droppedColumn));
}; };
const onCreateList = (listName: string) => { const onCreateList = (listName: string) => {
@ -296,13 +353,14 @@ const Project = () => {
if (lastColumn) { if (lastColumn) {
position = lastColumn.position * 2 + 1; position = lastColumn.position * 2 + 1;
} }
createTaskGroup({ variables: { projectID: projectId, name: listName, position } }); createTaskGroup({ variables: { projectID, name: listName, position } });
}; };
const [assignTask] = useAssignTaskMutation(); const [assignTask] = useAssignTaskMutation();
const { showPopup } = usePopup(); const { showPopup, hidePopup } = usePopup();
const $labelsRef = useRef<HTMLDivElement>(null); const $labelsRef = useRef<HTMLDivElement>(null);
const labelsRef = useRef<Array<Label>>([]);
if (loading) { if (loading) {
return ( return (
<> <>
@ -312,6 +370,7 @@ const Project = () => {
); );
} }
if (data) { if (data) {
console.log(data);
const currentListsData: BoardState = { tasks: {}, columns: {} }; const currentListsData: BoardState = { tasks: {}, columns: {} };
data.findProject.taskGroups.forEach(taskGroup => { data.findProject.taskGroups.forEach(taskGroup => {
currentListsData.columns[taskGroup.id] = { currentListsData.columns[taskGroup.id] = {
@ -358,7 +417,6 @@ const Project = () => {
}); });
const onQuickEditorOpen = (e: ContextMenuEvent) => { const onQuickEditorOpen = (e: ContextMenuEvent) => {
const currentTask = Object.values(currentListsData.tasks).find(task => task.taskID === e.taskID); const currentTask = Object.values(currentListsData.tasks).find(task => task.taskID === e.taskID);
console.log(`currentTask: ${currentTask?.taskID}`);
setQuickCardEditor({ setQuickCardEditor({
top: e.top, top: e.top,
left: e.left, left: e.left,
@ -367,6 +425,14 @@ const Project = () => {
}); });
}; };
labelsRef.current = data.findProject.labels.map(label => {
return {
labelId: label.id,
name: label.name ?? '',
labelColor: label.labelColor,
active: false,
};
});
return ( return (
<> <>
<GlobalTopNavbar projectMembers={availableMembers} name={data.findProject.name} /> <GlobalTopNavbar projectMembers={availableMembers} name={data.findProject.name} />
@ -377,18 +443,7 @@ const Project = () => {
onClick={() => { onClick={() => {
showPopup( showPopup(
$labelsRef, $labelsRef,
<LabelManagerEditor <LabelManagerEditor labelColors={data.labelColors} labels={labelsRef} projectID={projectID} />,
labelColors={data.labelColors}
labels={data.findProject.labels.map(label => {
return {
labelId: label.id,
name: label.name ?? '',
labelColor: label.labelColor,
active: false,
};
})}
projectID={projectId}
/>,
); );
}} }}
> >
@ -436,7 +491,7 @@ const Project = () => {
taskGroupID={taskGroupID} taskGroupID={taskGroupID}
onArchiveTaskGroup={tgID => { onArchiveTaskGroup={tgID => {
deleteTaskGroup({ variables: { taskGroupID: tgID } }); deleteTaskGroup({ variables: { taskGroupID: tgID } });
setPopupData(initialPopupState); hidePopup();
}} }}
/> />
</Popup>, </Popup>,
@ -453,17 +508,12 @@ const Project = () => {
onEditCard={(_listId: string, cardId: string, cardName: string) => { onEditCard={(_listId: string, cardId: string, cardName: string) => {
updateTaskName({ variables: { taskID: cardId, name: cardName } }); updateTaskName({ variables: { taskID: cardId, name: cardName } });
}} }}
onOpenPopup={() => console.log()} onOpenPopup={() => {}}
onArchiveCard={(_listId: string, cardId: string) => onArchiveCard={(_listId: string, cardId: string) =>
deleteTask({ deleteTask({
variables: { taskID: cardId }, variables: { taskID: cardId },
update: client => { update: client => {
const cacheData: any = client.readQuery({ const cacheData = getCacheData(client, projectID);
query: FindProjectDocument,
variables: {
projectId: projectId,
},
});
const newData = { const newData = {
...cacheData.findProject, ...cacheData.findProject,
taskGroups: cacheData.findProject.taskGroups.map((taskGroup: any) => { taskGroups: cacheData.findProject.taskGroups.map((taskGroup: any) => {
@ -473,13 +523,7 @@ const Project = () => {
}; };
}), }),
}; };
client.writeQuery({ writeCacheData(client, projectID, cacheData, newData);
query: FindProjectDocument,
variables: {
projectId: projectId,
},
data: { findProject: newData },
});
}, },
}) })
} }
@ -492,10 +536,7 @@ const Project = () => {
path={`${match.path}/c/:taskID`} path={`${match.path}/c/:taskID`}
render={(routeProps: RouteComponentProps<TaskRouteProps>) => ( render={(routeProps: RouteComponentProps<TaskRouteProps>) => (
<Details <Details
refreshCache={() => { refreshCache={() => {}}
console.log('beep 2!');
// refetch();
}}
availableMembers={availableMembers} availableMembers={availableMembers}
projectURL={match.url} projectURL={match.url}
taskID={routeProps.match.params.taskID} taskID={routeProps.match.params.taskID}
@ -506,7 +547,6 @@ const Project = () => {
updateTaskDescription({ variables: { taskID: updatedTask.taskID, description: newDescription } }); updateTaskDescription({ variables: { taskID: updatedTask.taskID, description: newDescription } });
}} }}
onDeleteTask={deletedTask => { onDeleteTask={deletedTask => {
setTaskDetails(initialTaskDetailsState);
deleteTask({ variables: { taskID: deletedTask.taskID } }); deleteTask({ variables: { taskID: deletedTask.taskID } });
}} }}
onOpenAddLabelPopup={(task, $targetRef) => {}} onOpenAddLabelPopup={(task, $targetRef) => {}}

View File

@ -30,7 +30,6 @@ const ProjectLink = styled(Link)`
const Projects = () => { const Projects = () => {
const { loading, data } = useGetProjectsQuery(); const { loading, data } = useGetProjectsQuery();
console.log(loading, data);
if (loading) { if (loading) {
return ( return (
<> <>

View File

@ -1,4 +1,5 @@
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import { ApolloProvider } from '@apollo/react-hooks'; import { ApolloProvider } from '@apollo/react-hooks';
import { ApolloClient } from 'apollo-client'; import { ApolloClient } from 'apollo-client';

View File

@ -168,7 +168,9 @@ const Card = React.forwardRef(
</ListCardBadges> </ListCardBadges>
<CardMembers> <CardMembers>
{members && {members &&
members.map(member => <Member taskID={taskID} member={member} onCardMemberClick={onCardMemberClick} />)} members.map(member => (
<Member key={member.userID} taskID={taskID} member={member} onCardMemberClick={onCardMemberClick} />
))}
</CardMembers> </CardMembers>
</ListCardDetails> </ListCardDetails>
</ListCardInnerContainer> </ListCardInnerContainer>

View File

@ -74,8 +74,6 @@ const Lists: React.FC<Props> = ({
}), }),
); );
console.log(beforeDropDraggables);
console.log(destination);
const afterDropDraggables = getAfterDropDraggableList( const afterDropDraggables = getAfterDropDraggableList(
beforeDropDraggables, beforeDropDraggables,
droppedDraggable, droppedDraggable,
@ -83,19 +81,16 @@ const Lists: React.FC<Props> = ({
isSameList, isSameList,
destination, destination,
); );
console.log(afterDropDraggables);
const newPosition = getNewDraggablePosition(afterDropDraggables, destination.index); const newPosition = getNewDraggablePosition(afterDropDraggables, destination.index);
if (isList) { if (isList) {
const droppedList = columns[droppedDraggable.id]; const droppedList = columns[droppedDraggable.id];
console.log(`is list ${droppedList}`);
onListDrop({ onListDrop({
...droppedList, ...droppedList,
position: newPosition, position: newPosition,
}); });
} else { } else {
const droppedCard = tasks[droppedDraggable.id]; const droppedCard = tasks[droppedDraggable.id];
console.log(`is card ${droppedCard}`);
const newCard = { const newCard = {
...droppedCard, ...droppedCard,
position: newPosition, position: newPosition,
@ -112,6 +107,7 @@ const Lists: React.FC<Props> = ({
return { id: column.taskGroupID, position: column.position }; return { id: column.taskGroupID, position: column.position };
}), }),
); );
console.log(orderedColumns);
const [currentComposer, setCurrentComposer] = useState(''); const [currentComposer, setCurrentComposer] = useState('');
return ( return (
@ -134,7 +130,7 @@ const Lists: React.FC<Props> = ({
name={column.name} name={column.name}
onOpenComposer={id => setCurrentComposer(id)} onOpenComposer={id => setCurrentComposer(id)}
isComposerOpen={currentComposer === column.taskGroupID} isComposerOpen={currentComposer === column.taskGroupID}
onSaveName={name => console.log(name)} onSaveName={name => {}}
tasks={columnCards} tasks={columnCards}
ref={columnDragProvided.innerRef} ref={columnDragProvided.innerRef}
wrapperProps={columnDragProvided.draggableProps} wrapperProps={columnDragProvided.draggableProps}

View File

@ -23,7 +23,6 @@ import {
const Login = ({ onSubmit }: LoginProps) => { const Login = ({ onSubmit }: LoginProps) => {
const [isComplete, setComplete] = useState(true); const [isComplete, setComplete] = useState(true);
const { register, handleSubmit, errors, setError, formState } = useForm<LoginFormData>(); const { register, handleSubmit, errors, setError, formState } = useForm<LoginFormData>();
console.log(formState);
const loginSubmit = (data: LoginFormData) => { const loginSubmit = (data: LoginFormData) => {
setComplete(false); setComplete(false);
onSubmit(data, setComplete, setError); onSubmit(data, setComplete, setError);

View File

@ -1,4 +1,4 @@
import React, { useState } from 'react'; import React, { useState, useEffect, useRef } from 'react';
import LabelColors from 'shared/constants/labelColors'; import LabelColors from 'shared/constants/labelColors';
import { Checkmark } from 'shared/icons'; import { Checkmark } from 'shared/icons';
import { SaveButton, DeleteButton, LabelBox, EditLabelForm, FieldLabel, FieldName } from './Styles'; import { SaveButton, DeleteButton, LabelBox, EditLabelForm, FieldLabel, FieldName } from './Styles';
@ -7,16 +7,25 @@ type Props = {
labelColors: Array<LabelColor>; labelColors: Array<LabelColor>;
label: Label | null; label: Label | null;
onLabelEdit: (labelId: string | null, labelName: string, labelColor: LabelColor) => void; onLabelEdit: (labelId: string | null, labelName: string, labelColor: LabelColor) => void;
onLabelDelete?: (labelId: string) => void;
}; };
const LabelManager = ({ labelColors, label, onLabelEdit }: Props) => { const LabelManager = ({ labelColors, label, onLabelEdit, onLabelDelete }: Props) => {
console.log(label); const $fieldName = useRef<HTMLInputElement>(null);
const [currentLabel, setCurrentLabel] = useState(label ? label.name : ''); const [currentLabel, setCurrentLabel] = useState(label ? label.name : '');
const [currentColor, setCurrentColor] = useState<LabelColor | null>(label ? label.labelColor : null); const [currentColor, setCurrentColor] = useState<LabelColor | null>(label ? label.labelColor : null);
useEffect(() => {
if ($fieldName.current) {
$fieldName.current.focus();
}
}, []);
return ( return (
<EditLabelForm> <EditLabelForm>
<FieldLabel>Name</FieldLabel> <FieldLabel>Name</FieldLabel>
<FieldName <FieldName
ref={$fieldName}
id="labelName" id="labelName"
type="text" type="text"
name="name" name="name"
@ -29,6 +38,7 @@ const LabelManager = ({ labelColors, label, onLabelEdit }: Props) => {
<div> <div>
{labelColors.map((labelColor: LabelColor) => ( {labelColors.map((labelColor: LabelColor) => (
<LabelBox <LabelBox
key={labelColor.id}
color={labelColor.colorHex} color={labelColor.colorHex}
onClick={() => { onClick={() => {
setCurrentColor(labelColor); setCurrentColor(labelColor);
@ -40,6 +50,8 @@ const LabelManager = ({ labelColors, label, onLabelEdit }: Props) => {
</div> </div>
<div> <div>
<SaveButton <SaveButton
value="Save"
type="submit"
onClick={e => { onClick={e => {
e.preventDefault(); e.preventDefault();
console.log(currentColor); console.log(currentColor);
@ -47,10 +59,17 @@ const LabelManager = ({ labelColors, label, onLabelEdit }: Props) => {
onLabelEdit(label ? label.labelId : null, currentLabel, currentColor); onLabelEdit(label ? label.labelId : null, currentLabel, currentColor);
} }
}} }}
type="submit"
value="Save"
/> />
<DeleteButton type="submit" value="Delete" /> {label && onLabelDelete && (
<DeleteButton
value="Delete"
type="submit"
onClick={e => {
e.preventDefault();
onLabelDelete(label.labelId);
}}
/>
)}
</div> </div>
</EditLabelForm> </EditLabelForm>
); );

View File

@ -1,4 +1,4 @@
import React, { useState } from 'react'; import React, { useState, useEffect, useRef } from 'react';
import { Pencil, Checkmark } from 'shared/icons'; import { Pencil, Checkmark } from 'shared/icons';
import { import {
@ -20,12 +20,19 @@ type Props = {
onLabelCreate: () => void; onLabelCreate: () => void;
}; };
const LabelManager: React.FC<Props> = ({ labels, onLabelToggle, onLabelEdit, onLabelCreate }) => { const LabelManager: React.FC<Props> = ({ labels, onLabelToggle, onLabelEdit, onLabelCreate }) => {
const $fieldName = useRef<HTMLInputElement>(null);
const [currentLabel, setCurrentLabel] = useState(''); const [currentLabel, setCurrentLabel] = useState('');
const [currentSearch, setCurrentSearch] = useState(''); const [currentSearch, setCurrentSearch] = useState('');
useEffect(() => {
if ($fieldName.current) {
$fieldName.current.focus();
}
}, []);
return ( return (
<> <>
<LabelSearch <LabelSearch
type="text" type="text"
ref={$fieldName}
placeholder="search labels..." placeholder="search labels..."
onChange={e => { onChange={e => {
setCurrentSearch(e.currentTarget.value); setCurrentSearch(e.currentTarget.value);

View File

@ -248,36 +248,47 @@ export const LabelBox = styled.span<{ color: string }>`
`; `;
export const SaveButton = styled.input` export const SaveButton = styled.input`
cursor: pointer; background: rgb(115, 103, 240);
background-color: #5aac44;
box-shadow: none; box-shadow: none;
border: none; border: none;
color: #fff; color: #fff;
padding-left: 24px; cursor: pointer;
padding-right: 24px;
ursor: pointer;
display: inline-block; display: inline-block;
font-weight: 400; font-weight: 400;
line-height: 20px; line-height: 20px;
margin: 8px 4px 0 0; margin-right: 4px;
padding: 6px 12px; padding: 6px 12px;
text-align: center; text-align: center;
border-radius: 3px; border-radius: 3px;
`; `;
export const DeleteButton = styled.input` export const DeleteButton = styled.input`
background-color: #cf513d;
box-shadow: none;
border: none;
color: #fff;
cursor: pointer;
type="submit"font-weight: 400;
line-height: 20px;
margin: 8px 4px 0 0;
padding: 6px 12px;
text-align: center;
border-radius: 3px;
float: right; float: right;
outline: none;
border: none;
line-height: 20px;
padding: 6px 12px;
background-color: transparent;
text-align: center;
color: #c2c6dc;
font-weight: 400;
line-height: 20px;
cursor: pointer;
margin: 0 0 0 8px;
border-radius: 3px;
border-width: 1px;
border-style: solid;
border-color: transparent;
border-image: initial;
border-color: #414561;
&:hover {
color: #fff;
background: rgb(115, 103, 240);
border-color: transparent;
}
`; `;
export const CreateLabelButton = styled.button` export const CreateLabelButton = styled.button`

View File

@ -18,6 +18,7 @@ type PopupContextState = {
show: (target: RefObject<HTMLElement>, content: JSX.Element) => void; show: (target: RefObject<HTMLElement>, content: JSX.Element) => void;
setTab: (newTab: number) => void; setTab: (newTab: number) => void;
getCurrentTab: () => number; getCurrentTab: () => number;
hide: () => void;
}; };
type PopupProps = { type PopupProps = {
@ -46,11 +47,12 @@ const PopupContext = createContext<PopupContextState>({
show: () => {}, show: () => {},
setTab: () => {}, setTab: () => {},
getCurrentTab: () => 0, getCurrentTab: () => 0,
hide: () => {},
}); });
export const usePopup = () => { export const usePopup = () => {
const ctx = useContext<PopupContextState>(PopupContext); const ctx = useContext<PopupContextState>(PopupContext);
return { showPopup: ctx.show, setTab: ctx.setTab, getCurrentTab: ctx.getCurrentTab }; return { showPopup: ctx.show, setTab: ctx.setTab, getCurrentTab: ctx.getCurrentTab, hidePopup: ctx.hide };
}; };
type PopupState = { type PopupState = {
@ -80,11 +82,9 @@ const defaultState = {
export const PopupProvider: React.FC = ({ children }) => { export const PopupProvider: React.FC = ({ children }) => {
const [currentState, setState] = useState<PopupState>(defaultState); const [currentState, setState] = useState<PopupState>(defaultState);
const show = (target: RefObject<HTMLElement>, content: JSX.Element) => { const show = (target: RefObject<HTMLElement>, content: JSX.Element) => {
console.log(target);
if (target && target.current) { if (target && target.current) {
const bounds = target.current.getBoundingClientRect(); const bounds = target.current.getBoundingClientRect();
if (bounds.left + 304 + 30 > window.innerWidth) { if (bounds.left + 304 + 30 > window.innerWidth) {
console.log('open!');
setState({ setState({
isOpen: true, isOpen: true,
left: bounds.left + bounds.width, left: bounds.left + bounds.width,
@ -95,7 +95,6 @@ export const PopupProvider: React.FC = ({ children }) => {
content, content,
}); });
} else { } else {
console.log('open NOT INVERT!');
setState({ setState({
isOpen: true, isOpen: true,
left: bounds.left, left: bounds.left,
@ -108,6 +107,17 @@ export const PopupProvider: React.FC = ({ children }) => {
} }
} }
}; };
const hide = () => {
setState({
isOpen: false,
left: 0,
top: 0,
invert: true,
currentTab: 0,
previousTab: 0,
content: null,
});
};
const portalTarget = canUseDOM ? document.body : null; // appease flow const portalTarget = canUseDOM ? document.body : null; // appease flow
const setTab = (newTab: number) => { const setTab = (newTab: number) => {
@ -125,7 +135,7 @@ export const PopupProvider: React.FC = ({ children }) => {
}; };
return ( return (
<Provider value={{ show, setTab, getCurrentTab }}> <Provider value={{ hide, show, setTab, getCurrentTab }}>
{portalTarget && {portalTarget &&
currentState.isOpen && currentState.isOpen &&
createPortal( createPortal(

View File

@ -146,6 +146,14 @@ export const TaskDetailsMarkdown = styled.div`
width: 100%; width: 100%;
cursor: pointer; cursor: pointer;
color: #c2c6dc; color: #c2c6dc;
p {
margin: 0 0 8px;
}
strong {
font-weight: 700;
}
`; `;
export const TaskDetailsControls = styled.div` export const TaskDetailsControls = styled.div`

View File

@ -1,6 +1,7 @@
import React, { useState, useRef, useEffect } from 'react'; import React, { useState, useRef, useEffect } from 'react';
import { Bin, Cross, Plus } from 'shared/icons'; import { Bin, Cross, Plus } from 'shared/icons';
import useOnOutsideClick from 'shared/hooks/onOutsideClick'; import useOnOutsideClick from 'shared/hooks/onOutsideClick';
import ReactMarkdown from 'react-markdown';
import TaskAssignee from 'shared/components/TaskAssignee'; import TaskAssignee from 'shared/components/TaskAssignee';
import { import {
@ -48,7 +49,9 @@ const TaskContent: React.FC<TaskContentProps> = ({ description, onEditContent })
return description === '' ? ( return description === '' ? (
<TaskDetailsAddDetailsButton onClick={onEditContent}>Add a more detailed description</TaskDetailsAddDetailsButton> <TaskDetailsAddDetailsButton onClick={onEditContent}>Add a more detailed description</TaskDetailsAddDetailsButton>
) : ( ) : (
<TaskDetailsMarkdown onClick={onEditContent}>{description}</TaskDetailsMarkdown> <TaskDetailsMarkdown onClick={onEditContent}>
<ReactMarkdown source={description} />
</TaskDetailsMarkdown>
); );
}; };
@ -142,7 +145,6 @@ const TaskDetails: React.FC<TaskDetailsProps> = ({
const onAddLabel = () => { const onAddLabel = () => {
onOpenAddLabelPopup(task, $addLabelRef); onOpenAddLabelPopup(task, $addLabelRef);
}; };
console.log(task);
return ( return (
<> <>
<TaskActions> <TaskActions>

View File

@ -50,7 +50,6 @@ const NavBar: React.FC<NavBarProps> = ({
}) => { }) => {
const $profileRef: any = useRef(null); const $profileRef: any = useRef(null);
const handleProfileClick = () => { const handleProfileClick = () => {
console.log('click');
const boundingRect = $profileRef.current.getBoundingClientRect(); const boundingRect = $profileRef.current.getBoundingClientRect();
onProfileClick(boundingRect.bottom, boundingRect.right); onProfileClick(boundingRect.bottom, boundingRect.right);
}; };
@ -95,7 +94,7 @@ const NavBar: React.FC<NavBarProps> = ({
{projectMembers && ( {projectMembers && (
<ProjectMembers> <ProjectMembers>
{projectMembers.map(member => ( {projectMembers.map(member => (
<TaskAssignee size={28} member={member} onMemberProfile={onMemberProfile} /> <TaskAssignee key={member.userID} size={28} member={member} onMemberProfile={onMemberProfile} />
))} ))}
<InviteButton>Invite</InviteButton> <InviteButton>Invite</InviteButton>
</ProjectMembers> </ProjectMembers>

View File

@ -269,6 +269,26 @@ export type NewProjectLabel = {
name?: Maybe<Scalars['String']>; name?: Maybe<Scalars['String']>;
}; };
export type DeleteProjectLabel = {
projectLabelID: Scalars['UUID'];
};
export type UpdateProjectLabelName = {
projectLabelID: Scalars['UUID'];
name: Scalars['String'];
};
export type UpdateProjectLabel = {
projectLabelID: Scalars['UUID'];
labelColorID: Scalars['UUID'];
name: Scalars['String'];
};
export type UpdateProjectLabelColor = {
projectLabelID: Scalars['UUID'];
labelColorID: Scalars['UUID'];
};
export type Mutation = { export type Mutation = {
__typename?: 'Mutation'; __typename?: 'Mutation';
createRefreshToken: RefreshToken; createRefreshToken: RefreshToken;
@ -276,6 +296,10 @@ export type Mutation = {
createTeam: Team; createTeam: Team;
createProject: Project; createProject: Project;
createProjectLabel: ProjectLabel; createProjectLabel: ProjectLabel;
deleteProjectLabel: ProjectLabel;
updateProjectLabel: ProjectLabel;
updateProjectLabelName: ProjectLabel;
updateProjectLabelColor: ProjectLabel;
createTaskGroup: TaskGroup; createTaskGroup: TaskGroup;
updateTaskGroupLocation: TaskGroup; updateTaskGroupLocation: TaskGroup;
deleteTaskGroup: DeleteTaskGroupPayload; deleteTaskGroup: DeleteTaskGroupPayload;
@ -317,6 +341,26 @@ export type MutationCreateProjectLabelArgs = {
}; };
export type MutationDeleteProjectLabelArgs = {
input: DeleteProjectLabel;
};
export type MutationUpdateProjectLabelArgs = {
input: UpdateProjectLabel;
};
export type MutationUpdateProjectLabelNameArgs = {
input: UpdateProjectLabelName;
};
export type MutationUpdateProjectLabelColorArgs = {
input: UpdateProjectLabelColor;
};
export type MutationCreateTaskGroupArgs = { export type MutationCreateTaskGroupArgs = {
input: NewTaskGroup; input: NewTaskGroup;
}; };
@ -413,7 +457,7 @@ export type CreateProjectLabelMutation = (
& Pick<ProjectLabel, 'id' | 'createdDate' | 'name'> & Pick<ProjectLabel, 'id' | 'createdDate' | 'name'>
& { labelColor: ( & { labelColor: (
{ __typename?: 'LabelColor' } { __typename?: 'LabelColor' }
& Pick<LabelColor, 'id' | 'colorHex'> & Pick<LabelColor, 'id' | 'colorHex' | 'name' | 'position'>
) } ) }
) } ) }
); );
@ -459,6 +503,19 @@ export type CreateTaskGroupMutation = (
) } ) }
); );
export type DeleteProjectLabelMutationVariables = {
projectLabelID: Scalars['UUID'];
};
export type DeleteProjectLabelMutation = (
{ __typename?: 'Mutation' }
& { deleteProjectLabel: (
{ __typename?: 'ProjectLabel' }
& Pick<ProjectLabel, 'id'>
) }
);
export type DeleteTaskMutationVariables = { export type DeleteTaskMutationVariables = {
taskID: Scalars['String']; taskID: Scalars['String'];
}; };
@ -611,6 +668,25 @@ export type UnassignTaskMutation = (
) } ) }
); );
export type UpdateProjectLabelMutationVariables = {
projectLabelID: Scalars['UUID'];
labelColorID: Scalars['UUID'];
name: Scalars['String'];
};
export type UpdateProjectLabelMutation = (
{ __typename?: 'Mutation' }
& { updateProjectLabel: (
{ __typename?: 'ProjectLabel' }
& Pick<ProjectLabel, 'id' | 'createdDate' | 'name'>
& { labelColor: (
{ __typename?: 'LabelColor' }
& Pick<LabelColor, 'id' | 'colorHex' | 'name' | 'position'>
) }
) }
);
export type UpdateTaskDescriptionMutationVariables = { export type UpdateTaskDescriptionMutationVariables = {
taskID: Scalars['UUID']; taskID: Scalars['UUID'];
description: Scalars['String']; description: Scalars['String'];
@ -715,6 +791,8 @@ export const CreateProjectLabelDocument = gql`
labelColor { labelColor {
id id
colorHex colorHex
name
position
} }
name name
} }
@ -833,6 +911,38 @@ export function useCreateTaskGroupMutation(baseOptions?: ApolloReactHooks.Mutati
export type CreateTaskGroupMutationHookResult = ReturnType<typeof useCreateTaskGroupMutation>; export type CreateTaskGroupMutationHookResult = ReturnType<typeof useCreateTaskGroupMutation>;
export type CreateTaskGroupMutationResult = ApolloReactCommon.MutationResult<CreateTaskGroupMutation>; export type CreateTaskGroupMutationResult = ApolloReactCommon.MutationResult<CreateTaskGroupMutation>;
export type CreateTaskGroupMutationOptions = ApolloReactCommon.BaseMutationOptions<CreateTaskGroupMutation, CreateTaskGroupMutationVariables>; export type CreateTaskGroupMutationOptions = ApolloReactCommon.BaseMutationOptions<CreateTaskGroupMutation, CreateTaskGroupMutationVariables>;
export const DeleteProjectLabelDocument = gql`
mutation deleteProjectLabel($projectLabelID: UUID!) {
deleteProjectLabel(input: {projectLabelID: $projectLabelID}) {
id
}
}
`;
export type DeleteProjectLabelMutationFn = ApolloReactCommon.MutationFunction<DeleteProjectLabelMutation, DeleteProjectLabelMutationVariables>;
/**
* __useDeleteProjectLabelMutation__
*
* To run a mutation, you first call `useDeleteProjectLabelMutation` within a React component and pass it any options that fit your needs.
* When your component renders, `useDeleteProjectLabelMutation` returns a tuple that includes:
* - A mutate function that you can call at any time to execute the mutation
* - An object with fields that represent the current status of the mutation's execution
*
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
*
* @example
* const [deleteProjectLabelMutation, { data, loading, error }] = useDeleteProjectLabelMutation({
* variables: {
* projectLabelID: // value for 'projectLabelID'
* },
* });
*/
export function useDeleteProjectLabelMutation(baseOptions?: ApolloReactHooks.MutationHookOptions<DeleteProjectLabelMutation, DeleteProjectLabelMutationVariables>) {
return ApolloReactHooks.useMutation<DeleteProjectLabelMutation, DeleteProjectLabelMutationVariables>(DeleteProjectLabelDocument, baseOptions);
}
export type DeleteProjectLabelMutationHookResult = ReturnType<typeof useDeleteProjectLabelMutation>;
export type DeleteProjectLabelMutationResult = ApolloReactCommon.MutationResult<DeleteProjectLabelMutation>;
export type DeleteProjectLabelMutationOptions = ApolloReactCommon.BaseMutationOptions<DeleteProjectLabelMutation, DeleteProjectLabelMutationVariables>;
export const DeleteTaskDocument = gql` export const DeleteTaskDocument = gql`
mutation deleteTask($taskID: String!) { mutation deleteTask($taskID: String!) {
deleteTask(input: {taskID: $taskID}) { deleteTask(input: {taskID: $taskID}) {
@ -1147,6 +1257,48 @@ export function useUnassignTaskMutation(baseOptions?: ApolloReactHooks.MutationH
export type UnassignTaskMutationHookResult = ReturnType<typeof useUnassignTaskMutation>; export type UnassignTaskMutationHookResult = ReturnType<typeof useUnassignTaskMutation>;
export type UnassignTaskMutationResult = ApolloReactCommon.MutationResult<UnassignTaskMutation>; export type UnassignTaskMutationResult = ApolloReactCommon.MutationResult<UnassignTaskMutation>;
export type UnassignTaskMutationOptions = ApolloReactCommon.BaseMutationOptions<UnassignTaskMutation, UnassignTaskMutationVariables>; export type UnassignTaskMutationOptions = ApolloReactCommon.BaseMutationOptions<UnassignTaskMutation, UnassignTaskMutationVariables>;
export const UpdateProjectLabelDocument = gql`
mutation updateProjectLabel($projectLabelID: UUID!, $labelColorID: UUID!, $name: String!) {
updateProjectLabel(input: {projectLabelID: $projectLabelID, labelColorID: $labelColorID, name: $name}) {
id
createdDate
labelColor {
id
colorHex
name
position
}
name
}
}
`;
export type UpdateProjectLabelMutationFn = ApolloReactCommon.MutationFunction<UpdateProjectLabelMutation, UpdateProjectLabelMutationVariables>;
/**
* __useUpdateProjectLabelMutation__
*
* To run a mutation, you first call `useUpdateProjectLabelMutation` within a React component and pass it any options that fit your needs.
* When your component renders, `useUpdateProjectLabelMutation` returns a tuple that includes:
* - A mutate function that you can call at any time to execute the mutation
* - An object with fields that represent the current status of the mutation's execution
*
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
*
* @example
* const [updateProjectLabelMutation, { data, loading, error }] = useUpdateProjectLabelMutation({
* variables: {
* projectLabelID: // value for 'projectLabelID'
* labelColorID: // value for 'labelColorID'
* name: // value for 'name'
* },
* });
*/
export function useUpdateProjectLabelMutation(baseOptions?: ApolloReactHooks.MutationHookOptions<UpdateProjectLabelMutation, UpdateProjectLabelMutationVariables>) {
return ApolloReactHooks.useMutation<UpdateProjectLabelMutation, UpdateProjectLabelMutationVariables>(UpdateProjectLabelDocument, baseOptions);
}
export type UpdateProjectLabelMutationHookResult = ReturnType<typeof useUpdateProjectLabelMutation>;
export type UpdateProjectLabelMutationResult = ApolloReactCommon.MutationResult<UpdateProjectLabelMutation>;
export type UpdateProjectLabelMutationOptions = ApolloReactCommon.BaseMutationOptions<UpdateProjectLabelMutation, UpdateProjectLabelMutationVariables>;
export const UpdateTaskDescriptionDocument = gql` export const UpdateTaskDescriptionDocument = gql`
mutation updateTaskDescription($taskID: UUID!, $description: String!) { mutation updateTaskDescription($taskID: UUID!, $description: String!) {
updateTaskDescription(input: {taskID: $taskID, description: $description}) { updateTaskDescription(input: {taskID: $taskID, description: $description}) {

View File

@ -5,6 +5,8 @@ mutation createProjectLabel($projectID: UUID!, $labelColorID: UUID!, $name: Stri
labelColor { labelColor {
id id
colorHex colorHex
name
position
} }
name name
} }

View File

@ -0,0 +1,5 @@
mutation deleteProjectLabel($projectLabelID: UUID!) {
deleteProjectLabel(input: { projectLabelID:$projectLabelID }) {
id
}
}

View File

@ -0,0 +1,13 @@
mutation updateProjectLabel($projectLabelID: UUID!, $labelColorID: UUID!, $name: String!) {
updateProjectLabel(input:{projectLabelID:$projectLabelID, labelColorID: $labelColorID, name: $name}) {
id
createdDate
labelColor {
id
colorHex
name
position
}
name
}
}

View File

@ -9,9 +9,7 @@ export const moveItemWithinArray = (arr: Array<DraggableElement>, item: Draggabl
export const insertItemIntoArray = (arr: Array<DraggableElement>, item: DraggableElement, index: number) => { export const insertItemIntoArray = (arr: Array<DraggableElement>, item: DraggableElement, index: number) => {
const arrClone = [...arr]; const arrClone = [...arr];
console.log(arrClone, index, item);
arrClone.splice(index, 0, item); arrClone.splice(index, 0, item);
console.log(arrClone);
return arrClone; return arrClone;
}; };
@ -32,21 +30,12 @@ export const getNewDraggablePosition = (afterDropDraggables: Array<DraggableElem
return 65535; return 65535;
} }
if (!prevDraggable) { if (!prevDraggable) {
console.log(
`in front of list [n/a : ${nextDraggable.id}]: ${nextDraggable.position} / 2.0 = ${nextDraggable.position / 2.0}`,
);
return nextDraggable.position / 2.0; return nextDraggable.position / 2.0;
} }
if (!nextDraggable) { if (!nextDraggable) {
console.log(
`end of list [${prevDraggable.id} : n/a] : ${prevDraggable.position} * 2.0 = ${prevDraggable.position * 2.0}`,
);
return prevDraggable.position * 2.0; return prevDraggable.position * 2.0;
} }
const newPos = (prevDraggable.position + nextDraggable.position) / 2.0; const newPos = (prevDraggable.position + nextDraggable.position) / 2.0;
console.log(
`middle of two cards [${prevDraggable.id} : ${nextDraggable.id}] : ${prevDraggable.position} + ${nextDraggable.position} / 2.0 = ${newPos}`,
);
return newPos; return newPos;
}; };
@ -58,7 +47,6 @@ export const isPositionChanged = (source: DraggableLocation, destination: Dragga
if (!destination) return false; if (!destination) return false;
const isSameList = destination.droppableId === source.droppableId; const isSameList = destination.droppableId === source.droppableId;
const isSamePosition = destination.index === source.index; const isSamePosition = destination.index === source.index;
console.log(`isSameList: ${isSameList} : isSamePosition: ${isSamePosition}`);
return !isSameList || !isSamePosition; return !isSameList || !isSamePosition;
}; };

8
web/src/wdy.ts Normal file
View File

@ -0,0 +1,8 @@
import React from 'react';
if (process.env.NODE_ENV === 'development') {
const whyDidYouRender = require('@welldone-software/why-did-you-render');
whyDidYouRender(React, {
trackAllPureComponents: true,
});
}

View File

@ -3592,6 +3592,13 @@
text-table "^0.2.0" text-table "^0.2.0"
webpack-log "^1.1.2" webpack-log "^1.1.2"
"@welldone-software/why-did-you-render@^4.2.2":
version "4.2.2"
resolved "https://registry.yarnpkg.com/@welldone-software/why-did-you-render/-/why-did-you-render-4.2.2.tgz#720128a4f626997ece1ac455a7b13f9ef10dae0a"
integrity sha512-v08t2WXFQdnxkPodXzbPeho3FwgrlwzjwxasN+8A1LSZnkcxJpYvOF8/z+OySqehC44JT6oPB1KEnBVMrebHdw==
dependencies:
lodash "^4"
"@wry/context@^0.4.0": "@wry/context@^0.4.0":
version "0.4.4" version "0.4.4"
resolved "https://registry.yarnpkg.com/@wry/context/-/context-0.4.4.tgz#e50f5fa1d6cfaabf2977d1fda5ae91717f8815f8" resolved "https://registry.yarnpkg.com/@wry/context/-/context-0.4.4.tgz#e50f5fa1d6cfaabf2977d1fda5ae91717f8815f8"
@ -6645,7 +6652,7 @@ dom-helpers@^5.0.1:
"@babel/runtime" "^7.6.3" "@babel/runtime" "^7.6.3"
csstype "^2.6.7" csstype "^2.6.7"
dom-serializer@0: dom-serializer@0, dom-serializer@^0.2.1:
version "0.2.2" version "0.2.2"
resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51"
integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g== integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==
@ -6687,6 +6694,13 @@ domhandler@^2.3.0:
dependencies: dependencies:
domelementtype "1" domelementtype "1"
domhandler@^3.0, domhandler@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-3.0.0.tgz#51cd13efca31da95bbb0c5bee3a48300e333b3e9"
integrity sha512-eKLdI5v9m67kbXQbJSNn1zjh0SDzvzWVWtX+qEI3eMjZw8daH9k8rlj1FZY9memPwjiskQFbe7vHVVJIAqoEhw==
dependencies:
domelementtype "^2.0.1"
domutils@1.5.1: domutils@1.5.1:
version "1.5.1" version "1.5.1"
resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf"
@ -6703,6 +6717,15 @@ domutils@^1.5.1, domutils@^1.7.0:
dom-serializer "0" dom-serializer "0"
domelementtype "1" domelementtype "1"
domutils@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.1.0.tgz#7ade3201af43703fde154952e3a868eb4b635f16"
integrity sha512-CD9M0Dm1iaHfQ1R/TI+z3/JWp/pgub0j4jIQKH89ARR4ATAV2nbaOQS5XxU9maJP5jHaPdDDQSEHuE2UmpUTKg==
dependencies:
dom-serializer "^0.2.1"
domelementtype "^2.0.1"
domhandler "^3.0.0"
dot-case@^3.0.3: dot-case@^3.0.3:
version "3.0.3" version "3.0.3"
resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.3.tgz#21d3b52efaaba2ea5fda875bb1aa8124521cf4aa" resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.3.tgz#21d3b52efaaba2ea5fda875bb1aa8124521cf4aa"
@ -8596,6 +8619,16 @@ html-tags@^3.1.0:
resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.1.0.tgz#7b5e6f7e665e9fb41f30007ed9e0d41e97fb2140" resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.1.0.tgz#7b5e6f7e665e9fb41f30007ed9e0d41e97fb2140"
integrity sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg== integrity sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg==
html-to-react@^1.3.4:
version "1.4.3"
resolved "https://registry.yarnpkg.com/html-to-react/-/html-to-react-1.4.3.tgz#1430a1cb581ef29533892ec70a2fdc4554b17ffd"
integrity sha512-txe09A3vxW8yEZGJXJ1is5gGDfBEVACmZDSgwDyH5EsfRdOubBwBCg63ZThZP0xBn0UE4FyvMXZXmohusCxDcg==
dependencies:
domhandler "^3.0"
htmlparser2 "^4.1.0"
lodash.camelcase "^4.3.0"
ramda "^0.27"
html-void-elements@^1.0.0: html-void-elements@^1.0.0:
version "1.0.5" version "1.0.5"
resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-1.0.5.tgz#ce9159494e86d95e45795b166c2021c2cfca4483" resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-1.0.5.tgz#ce9159494e86d95e45795b166c2021c2cfca4483"
@ -8625,6 +8658,16 @@ htmlparser2@^3.3.0:
inherits "^2.0.1" inherits "^2.0.1"
readable-stream "^3.1.1" readable-stream "^3.1.1"
htmlparser2@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-4.1.0.tgz#9a4ef161f2e4625ebf7dfbe6c0a2f52d18a59e78"
integrity sha512-4zDq1a1zhE4gQso/c5LP1OtrhYTncXNSpvJYtWJBtXAETPlMfi3IFNjGuQbYLuVY4ZR0QMqRVvo4Pdy9KLyP8Q==
dependencies:
domelementtype "^2.0.1"
domhandler "^3.0.0"
domutils "^2.0.0"
entities "^2.0.0"
http-deceiver@^1.2.7: http-deceiver@^1.2.7:
version "1.2.7" version "1.2.7"
resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87"
@ -9067,7 +9110,7 @@ is-binary-path@~2.1.0:
dependencies: dependencies:
binary-extensions "^2.0.0" binary-extensions "^2.0.0"
is-buffer@^1.0.2, is-buffer@^1.1.5: is-buffer@^1.0.2, is-buffer@^1.1.4, is-buffer@^1.1.5:
version "1.1.6" version "1.1.6"
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
@ -9302,7 +9345,7 @@ is-path-inside@^2.1.0:
dependencies: dependencies:
path-is-inside "^1.0.2" path-is-inside "^1.0.2"
is-plain-obj@^1.0.0: is-plain-obj@^1.0.0, is-plain-obj@^1.1.0:
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4=
@ -10465,6 +10508,11 @@ lodash._reinterpolate@^3.0.0:
resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=
lodash.camelcase@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"
integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY=
lodash.debounce@^4.0.8: lodash.debounce@^4.0.8:
version "4.0.8" version "4.0.8"
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
@ -10555,7 +10603,7 @@ lodash.xorby@^4.7.0:
resolved "https://registry.yarnpkg.com/lodash.xorby/-/lodash.xorby-4.7.0.tgz#9c19a6f9f063a6eb53dd03c1b6871799801463d7" resolved "https://registry.yarnpkg.com/lodash.xorby/-/lodash.xorby-4.7.0.tgz#9c19a6f9f063a6eb53dd03c1b6871799801463d7"
integrity sha1-nBmm+fBjputT3QPBtocXmYAUY9c= integrity sha1-nBmm+fBjputT3QPBtocXmYAUY9c=
lodash@4.17.15, "lodash@>=3.5 <5", lodash@^4.0.1, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4, lodash@^4.17.5: lodash@4.17.15, "lodash@>=3.5 <5", lodash@^4, lodash@^4.0.1, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4, lodash@^4.17.5:
version "4.17.15" version "4.17.15"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
@ -10733,6 +10781,13 @@ md5.js@^1.3.4:
inherits "^2.0.1" inherits "^2.0.1"
safe-buffer "^5.1.2" safe-buffer "^5.1.2"
mdast-add-list-metadata@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/mdast-add-list-metadata/-/mdast-add-list-metadata-1.0.1.tgz#95e73640ce2fc1fa2dcb7ec443d09e2bfe7db4cf"
integrity sha512-fB/VP4MJ0LaRsog7hGPxgOrSL3gE/2uEdZyDuSEnKCv/8IkYHiDkIQSbChiJoHyxZZXZ9bzckyRk+vNxFzh8rA==
dependencies:
unist-util-visit-parents "1.1.2"
mdast-squeeze-paragraphs@^3.0.0: mdast-squeeze-paragraphs@^3.0.0:
version "3.0.5" version "3.0.5"
resolved "https://registry.yarnpkg.com/mdast-squeeze-paragraphs/-/mdast-squeeze-paragraphs-3.0.5.tgz#f428b6b944f8faef454db9b58f170c4183cb2e61" resolved "https://registry.yarnpkg.com/mdast-squeeze-paragraphs/-/mdast-squeeze-paragraphs-3.0.5.tgz#f428b6b944f8faef454db9b58f170c4183cb2e61"
@ -13183,6 +13238,11 @@ ramda@^0.21.0:
resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.21.0.tgz#a001abedb3ff61077d4ff1d577d44de77e8d0a35" resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.21.0.tgz#a001abedb3ff61077d4ff1d577d44de77e8d0a35"
integrity sha1-oAGr7bP/YQd9T/HVd9RN536NCjU= integrity sha1-oAGr7bP/YQd9T/HVd9RN536NCjU=
ramda@^0.27:
version "0.27.0"
resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.27.0.tgz#915dc29865c0800bf3f69b8fd6c279898b59de43"
integrity sha512-pVzZdDpWwWqEVVLshWUHjNwuVP7SfcmPraYuqocJp1yo2U1R7P+5QAfDhdItkuoGqIBnBYrtPp7rEPqDn9HlZA==
randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5:
version "2.1.0" version "2.1.0"
resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
@ -13462,7 +13522,7 @@ react-inspector@^4.0.0:
prop-types "^15.6.1" prop-types "^15.6.1"
storybook-chromatic "^2.2.2" storybook-chromatic "^2.2.2"
react-is@^16.6.0: react-is@^16.6.0, react-is@^16.8.6:
version "16.13.1" version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
@ -13477,6 +13537,20 @@ react-lifecycles-compat@^3.0.4:
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
react-markdown@^4.3.1:
version "4.3.1"
resolved "https://registry.yarnpkg.com/react-markdown/-/react-markdown-4.3.1.tgz#39f0633b94a027445b86c9811142d05381300f2f"
integrity sha512-HQlWFTbDxTtNY6bjgp3C3uv1h2xcjCSi1zAEzfBW9OwJJvENSYiLXWNXN5hHLsoqai7RnZiiHzcnWdXk2Splzw==
dependencies:
html-to-react "^1.3.4"
mdast-add-list-metadata "1.0.1"
prop-types "^15.7.2"
react-is "^16.8.6"
remark-parse "^5.0.0"
unified "^6.1.5"
unist-util-visit "^1.3.0"
xtend "^4.0.1"
react-onclickoutside@^6.9.0: react-onclickoutside@^6.9.0:
version "6.9.0" version "6.9.0"
resolved "https://registry.yarnpkg.com/react-onclickoutside/-/react-onclickoutside-6.9.0.tgz#a54bc317ae8cf6131a5d78acea55a11067f37a1f" resolved "https://registry.yarnpkg.com/react-onclickoutside/-/react-onclickoutside-6.9.0.tgz#a54bc317ae8cf6131a5d78acea55a11067f37a1f"
@ -14041,6 +14115,27 @@ remark-parse@7.0.2:
vfile-location "^2.0.0" vfile-location "^2.0.0"
xtend "^4.0.1" xtend "^4.0.1"
remark-parse@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-5.0.0.tgz#4c077f9e499044d1d5c13f80d7a98cf7b9285d95"
integrity sha512-b3iXszZLH1TLoyUzrATcTQUZrwNl1rE70rVdSruJFlDaJ9z5aMkhrG43Pp68OgfHndL/ADz6V69Zow8cTQu+JA==
dependencies:
collapse-white-space "^1.0.2"
is-alphabetical "^1.0.0"
is-decimal "^1.0.0"
is-whitespace-character "^1.0.0"
is-word-character "^1.0.0"
markdown-escapes "^1.0.0"
parse-entities "^1.1.0"
repeat-string "^1.5.4"
state-toggle "^1.0.0"
trim "0.0.1"
trim-trailing-lines "^1.0.0"
unherit "^1.0.4"
unist-util-remove-position "^1.0.0"
vfile-location "^2.0.0"
xtend "^4.0.1"
remark-slug@^5.1.2: remark-slug@^5.1.2:
version "5.1.2" version "5.1.2"
resolved "https://registry.yarnpkg.com/remark-slug/-/remark-slug-5.1.2.tgz#715ecdef8df1226786204b1887d31ab16aa24609" resolved "https://registry.yarnpkg.com/remark-slug/-/remark-slug-5.1.2.tgz#715ecdef8df1226786204b1887d31ab16aa24609"
@ -15870,6 +15965,18 @@ unified@8.4.2:
trough "^1.0.0" trough "^1.0.0"
vfile "^4.0.0" vfile "^4.0.0"
unified@^6.1.5:
version "6.2.0"
resolved "https://registry.yarnpkg.com/unified/-/unified-6.2.0.tgz#7fbd630f719126d67d40c644b7e3f617035f6dba"
integrity sha512-1k+KPhlVtqmG99RaTbAv/usu85fcSRu3wY8X+vnsEhIxNP5VbVIDiXnLqyKIG+UMdyTg0ZX9EI6k2AfjJkHPtA==
dependencies:
bail "^1.0.0"
extend "^3.0.0"
is-plain-obj "^1.1.0"
trough "^1.0.0"
vfile "^2.0.0"
x-is-string "^0.1.0"
union-value@^1.0.0: union-value@^1.0.0:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847"
@ -15943,6 +16050,11 @@ unist-util-remove@^1.0.0:
dependencies: dependencies:
unist-util-is "^3.0.0" unist-util-is "^3.0.0"
unist-util-stringify-position@^1.0.0, unist-util-stringify-position@^1.1.1:
version "1.1.2"
resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz#3f37fcf351279dcbca7480ab5889bb8a832ee1c6"
integrity sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ==
unist-util-stringify-position@^2.0.0: unist-util-stringify-position@^2.0.0:
version "2.0.3" version "2.0.3"
resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz#cce3bfa1cdf85ba7375d1d5b17bdc4cada9bd9da" resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz#cce3bfa1cdf85ba7375d1d5b17bdc4cada9bd9da"
@ -15950,6 +16062,11 @@ unist-util-stringify-position@^2.0.0:
dependencies: dependencies:
"@types/unist" "^2.0.2" "@types/unist" "^2.0.2"
unist-util-visit-parents@1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-1.1.2.tgz#f6e3afee8bdbf961c0e6f028ea3c0480028c3d06"
integrity sha512-yvo+MMLjEwdc3RhhPYSximset7rwjMrdt9E41Smmvg25UQIenzrN83cRnF1JMzoMi9zZOQeYXHSDf7p+IQkW3Q==
unist-util-visit-parents@^2.0.0: unist-util-visit-parents@^2.0.0:
version "2.1.2" version "2.1.2"
resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz#25e43e55312166f3348cae6743588781d112c1e9" resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz#25e43e55312166f3348cae6743588781d112c1e9"
@ -15974,7 +16091,7 @@ unist-util-visit@2.0.2, unist-util-visit@^2.0.0:
unist-util-is "^4.0.0" unist-util-is "^4.0.0"
unist-util-visit-parents "^3.0.0" unist-util-visit-parents "^3.0.0"
unist-util-visit@^1.0.0, unist-util-visit@^1.1.0, unist-util-visit@^1.4.0: unist-util-visit@^1.0.0, unist-util-visit@^1.1.0, unist-util-visit@^1.3.0, unist-util-visit@^1.4.0:
version "1.4.1" version "1.4.1"
resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-1.4.1.tgz#4724aaa8486e6ee6e26d7ff3c8685960d560b1e3" resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-1.4.1.tgz#4724aaa8486e6ee6e26d7ff3c8685960d560b1e3"
integrity sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw== integrity sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==
@ -16192,6 +16309,13 @@ vfile-location@^2.0.0:
resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-2.0.6.tgz#8a274f39411b8719ea5728802e10d9e0dff1519e" resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-2.0.6.tgz#8a274f39411b8719ea5728802e10d9e0dff1519e"
integrity sha512-sSFdyCP3G6Ka0CEmN83A2YCMKIieHx0EDaj5IDP4g1pa5ZJ4FJDvpO0WODLxo4LUX4oe52gmSCK7Jw4SBghqxA== integrity sha512-sSFdyCP3G6Ka0CEmN83A2YCMKIieHx0EDaj5IDP4g1pa5ZJ4FJDvpO0WODLxo4LUX4oe52gmSCK7Jw4SBghqxA==
vfile-message@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-1.1.1.tgz#5833ae078a1dfa2d96e9647886cd32993ab313e1"
integrity sha512-1WmsopSGhWt5laNir+633LszXvZ+Z/lxveBf6yhGsqnQIhlhzooZae7zV6YVM1Sdkw68dtAW3ow0pOdPANugvA==
dependencies:
unist-util-stringify-position "^1.1.1"
vfile-message@^2.0.0: vfile-message@^2.0.0:
version "2.0.3" version "2.0.3"
resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-2.0.3.tgz#0dd4f6879fb240a8099b22bd3755536c92e59ba5" resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-2.0.3.tgz#0dd4f6879fb240a8099b22bd3755536c92e59ba5"
@ -16200,6 +16324,16 @@ vfile-message@^2.0.0:
"@types/unist" "^2.0.0" "@types/unist" "^2.0.0"
unist-util-stringify-position "^2.0.0" unist-util-stringify-position "^2.0.0"
vfile@^2.0.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/vfile/-/vfile-2.3.0.tgz#e62d8e72b20e83c324bc6c67278ee272488bf84a"
integrity sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w==
dependencies:
is-buffer "^1.1.4"
replace-ext "1.0.0"
unist-util-stringify-position "^1.0.0"
vfile-message "^1.0.0"
vfile@^4.0.0: vfile@^4.0.0:
version "4.0.3" version "4.0.3"
resolved "https://registry.yarnpkg.com/vfile/-/vfile-4.0.3.tgz#1e50b824fb5e5affd718e225c7bb1af6d97d4408" resolved "https://registry.yarnpkg.com/vfile/-/vfile-4.0.3.tgz#1e50b824fb5e5affd718e225c7bb1af6d97d4408"
@ -16854,6 +16988,11 @@ ws@^6.1.2, ws@^6.2.1:
dependencies: dependencies:
async-limiter "~1.0.0" async-limiter "~1.0.0"
x-is-string@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/x-is-string/-/x-is-string-0.1.0.tgz#474b50865af3a49a9c4657f05acd145458f77d82"
integrity sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI=
xml-name-validator@^3.0.0: xml-name-validator@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a"