feature: add labels & remove old types
This commit is contained in:
parent
539259effd
commit
2a59cddadb
@ -86,10 +86,12 @@ type ComplexityRoot struct {
|
|||||||
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
|
||||||
|
ToggleTaskLabel func(childComplexity int, input ToggleTaskLabelInput) int
|
||||||
UnassignTask func(childComplexity int, input *UnassignTaskInput) int
|
UnassignTask func(childComplexity int, input *UnassignTaskInput) int
|
||||||
UpdateProjectLabel func(childComplexity int, input UpdateProjectLabel) int
|
UpdateProjectLabel func(childComplexity int, input UpdateProjectLabel) int
|
||||||
UpdateProjectLabelColor func(childComplexity int, input UpdateProjectLabelColor) int
|
UpdateProjectLabelColor func(childComplexity int, input UpdateProjectLabelColor) int
|
||||||
UpdateProjectLabelName func(childComplexity int, input UpdateProjectLabelName) int
|
UpdateProjectLabelName func(childComplexity int, input UpdateProjectLabelName) int
|
||||||
|
UpdateProjectName func(childComplexity int, input *UpdateProjectName) 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
|
||||||
@ -167,10 +169,8 @@ type ComplexityRoot struct {
|
|||||||
|
|
||||||
TaskLabel struct {
|
TaskLabel struct {
|
||||||
AssignedDate func(childComplexity int) int
|
AssignedDate func(childComplexity int) int
|
||||||
ColorHex func(childComplexity int) int
|
|
||||||
ID func(childComplexity int) int
|
ID func(childComplexity int) int
|
||||||
Name func(childComplexity int) int
|
ProjectLabel func(childComplexity int) int
|
||||||
ProjectLabelID func(childComplexity int) int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Team struct {
|
Team struct {
|
||||||
@ -179,6 +179,11 @@ type ComplexityRoot struct {
|
|||||||
Name func(childComplexity int) int
|
Name func(childComplexity int) int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ToggleTaskLabelPayload struct {
|
||||||
|
Active func(childComplexity int) int
|
||||||
|
Task func(childComplexity int) int
|
||||||
|
}
|
||||||
|
|
||||||
UserAccount struct {
|
UserAccount struct {
|
||||||
CreatedAt func(childComplexity int) int
|
CreatedAt func(childComplexity int) int
|
||||||
Email func(childComplexity int) int
|
Email func(childComplexity int) int
|
||||||
@ -198,6 +203,7 @@ type MutationResolver interface {
|
|||||||
CreateUserAccount(ctx context.Context, input NewUserAccount) (*pg.UserAccount, error)
|
CreateUserAccount(ctx context.Context, input NewUserAccount) (*pg.UserAccount, error)
|
||||||
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)
|
||||||
|
UpdateProjectName(ctx context.Context, input *UpdateProjectName) (*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)
|
DeleteProjectLabel(ctx context.Context, input DeleteProjectLabel) (*pg.ProjectLabel, error)
|
||||||
UpdateProjectLabel(ctx context.Context, input UpdateProjectLabel) (*pg.ProjectLabel, error)
|
UpdateProjectLabel(ctx context.Context, input UpdateProjectLabel) (*pg.ProjectLabel, error)
|
||||||
@ -208,6 +214,7 @@ type MutationResolver interface {
|
|||||||
DeleteTaskGroup(ctx context.Context, input DeleteTaskGroupInput) (*DeleteTaskGroupPayload, error)
|
DeleteTaskGroup(ctx context.Context, input DeleteTaskGroupInput) (*DeleteTaskGroupPayload, error)
|
||||||
AddTaskLabel(ctx context.Context, input *AddTaskLabelInput) (*pg.Task, error)
|
AddTaskLabel(ctx context.Context, input *AddTaskLabelInput) (*pg.Task, error)
|
||||||
RemoveTaskLabel(ctx context.Context, input *RemoveTaskLabelInput) (*pg.Task, error)
|
RemoveTaskLabel(ctx context.Context, input *RemoveTaskLabelInput) (*pg.Task, error)
|
||||||
|
ToggleTaskLabel(ctx context.Context, input ToggleTaskLabelInput) (*ToggleTaskLabelPayload, error)
|
||||||
CreateTask(ctx context.Context, input NewTask) (*pg.Task, error)
|
CreateTask(ctx context.Context, input NewTask) (*pg.Task, error)
|
||||||
UpdateTaskDescription(ctx context.Context, input UpdateTaskDescriptionInput) (*pg.Task, error)
|
UpdateTaskDescription(ctx context.Context, input UpdateTaskDescriptionInput) (*pg.Task, error)
|
||||||
UpdateTaskLocation(ctx context.Context, input NewTaskLocation) (*pg.Task, error)
|
UpdateTaskLocation(ctx context.Context, input NewTaskLocation) (*pg.Task, error)
|
||||||
@ -261,9 +268,7 @@ type TaskGroupResolver interface {
|
|||||||
}
|
}
|
||||||
type TaskLabelResolver interface {
|
type TaskLabelResolver interface {
|
||||||
ID(ctx context.Context, obj *pg.TaskLabel) (uuid.UUID, error)
|
ID(ctx context.Context, obj *pg.TaskLabel) (uuid.UUID, error)
|
||||||
|
ProjectLabel(ctx context.Context, obj *pg.TaskLabel) (*pg.ProjectLabel, error)
|
||||||
ColorHex(ctx context.Context, obj *pg.TaskLabel) (string, error)
|
|
||||||
Name(ctx context.Context, obj *pg.TaskLabel) (*string, error)
|
|
||||||
}
|
}
|
||||||
type TeamResolver interface {
|
type TeamResolver interface {
|
||||||
ID(ctx context.Context, obj *pg.Team) (uuid.UUID, error)
|
ID(ctx context.Context, obj *pg.Team) (uuid.UUID, error)
|
||||||
@ -513,6 +518,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
|||||||
|
|
||||||
return e.complexity.Mutation.RemoveTaskLabel(childComplexity, args["input"].(*RemoveTaskLabelInput)), true
|
return e.complexity.Mutation.RemoveTaskLabel(childComplexity, args["input"].(*RemoveTaskLabelInput)), true
|
||||||
|
|
||||||
|
case "Mutation.toggleTaskLabel":
|
||||||
|
if e.complexity.Mutation.ToggleTaskLabel == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
args, err := ec.field_Mutation_toggleTaskLabel_args(context.TODO(), rawArgs)
|
||||||
|
if err != nil {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.complexity.Mutation.ToggleTaskLabel(childComplexity, args["input"].(ToggleTaskLabelInput)), true
|
||||||
|
|
||||||
case "Mutation.unassignTask":
|
case "Mutation.unassignTask":
|
||||||
if e.complexity.Mutation.UnassignTask == nil {
|
if e.complexity.Mutation.UnassignTask == nil {
|
||||||
break
|
break
|
||||||
@ -561,6 +578,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
|||||||
|
|
||||||
return e.complexity.Mutation.UpdateProjectLabelName(childComplexity, args["input"].(UpdateProjectLabelName)), true
|
return e.complexity.Mutation.UpdateProjectLabelName(childComplexity, args["input"].(UpdateProjectLabelName)), true
|
||||||
|
|
||||||
|
case "Mutation.updateProjectName":
|
||||||
|
if e.complexity.Mutation.UpdateProjectName == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
args, err := ec.field_Mutation_updateProjectName_args(context.TODO(), rawArgs)
|
||||||
|
if err != nil {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.complexity.Mutation.UpdateProjectName(childComplexity, args["input"].(*UpdateProjectName)), true
|
||||||
|
|
||||||
case "Mutation.updateTaskDescription":
|
case "Mutation.updateTaskDescription":
|
||||||
if e.complexity.Mutation.UpdateTaskDescription == nil {
|
if e.complexity.Mutation.UpdateTaskDescription == nil {
|
||||||
break
|
break
|
||||||
@ -951,13 +980,6 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
|||||||
|
|
||||||
return e.complexity.TaskLabel.AssignedDate(childComplexity), true
|
return e.complexity.TaskLabel.AssignedDate(childComplexity), true
|
||||||
|
|
||||||
case "TaskLabel.colorHex":
|
|
||||||
if e.complexity.TaskLabel.ColorHex == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
return e.complexity.TaskLabel.ColorHex(childComplexity), true
|
|
||||||
|
|
||||||
case "TaskLabel.id":
|
case "TaskLabel.id":
|
||||||
if e.complexity.TaskLabel.ID == nil {
|
if e.complexity.TaskLabel.ID == nil {
|
||||||
break
|
break
|
||||||
@ -965,19 +987,12 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
|||||||
|
|
||||||
return e.complexity.TaskLabel.ID(childComplexity), true
|
return e.complexity.TaskLabel.ID(childComplexity), true
|
||||||
|
|
||||||
case "TaskLabel.name":
|
case "TaskLabel.projectLabel":
|
||||||
if e.complexity.TaskLabel.Name == nil {
|
if e.complexity.TaskLabel.ProjectLabel == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
return e.complexity.TaskLabel.Name(childComplexity), true
|
return e.complexity.TaskLabel.ProjectLabel(childComplexity), true
|
||||||
|
|
||||||
case "TaskLabel.projectLabelID":
|
|
||||||
if e.complexity.TaskLabel.ProjectLabelID == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
return e.complexity.TaskLabel.ProjectLabelID(childComplexity), true
|
|
||||||
|
|
||||||
case "Team.createdAt":
|
case "Team.createdAt":
|
||||||
if e.complexity.Team.CreatedAt == nil {
|
if e.complexity.Team.CreatedAt == nil {
|
||||||
@ -1000,6 +1015,20 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
|||||||
|
|
||||||
return e.complexity.Team.Name(childComplexity), true
|
return e.complexity.Team.Name(childComplexity), true
|
||||||
|
|
||||||
|
case "ToggleTaskLabelPayload.active":
|
||||||
|
if e.complexity.ToggleTaskLabelPayload.Active == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.complexity.ToggleTaskLabelPayload.Active(childComplexity), true
|
||||||
|
|
||||||
|
case "ToggleTaskLabelPayload.task":
|
||||||
|
if e.complexity.ToggleTaskLabelPayload.Task == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.complexity.ToggleTaskLabelPayload.Task(childComplexity), true
|
||||||
|
|
||||||
case "UserAccount.createdAt":
|
case "UserAccount.createdAt":
|
||||||
if e.complexity.UserAccount.CreatedAt == nil {
|
if e.complexity.UserAccount.CreatedAt == nil {
|
||||||
break
|
break
|
||||||
@ -1132,10 +1161,8 @@ type LabelColor {
|
|||||||
|
|
||||||
type TaskLabel {
|
type TaskLabel {
|
||||||
id: ID!
|
id: ID!
|
||||||
projectLabelID: UUID!
|
projectLabel: ProjectLabel!
|
||||||
assignedDate: Time!
|
assignedDate: Time!
|
||||||
colorHex: String!
|
|
||||||
name: String
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProfileIcon {
|
type ProfileIcon {
|
||||||
@ -1319,11 +1346,10 @@ input UpdateTaskDescriptionInput {
|
|||||||
|
|
||||||
input AddTaskLabelInput {
|
input AddTaskLabelInput {
|
||||||
taskID: UUID!
|
taskID: UUID!
|
||||||
labelColorID: UUID!
|
projectLabelID: UUID!
|
||||||
}
|
}
|
||||||
|
|
||||||
input RemoveTaskLabelInput {
|
input RemoveTaskLabelInput {
|
||||||
taskID: UUID!
|
|
||||||
taskLabelID: UUID!
|
taskLabelID: UUID!
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1353,6 +1379,21 @@ input UpdateProjectLabelColor {
|
|||||||
labelColorID: UUID!
|
labelColorID: UUID!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input ToggleTaskLabelInput {
|
||||||
|
taskID: UUID!
|
||||||
|
projectLabelID: UUID!
|
||||||
|
}
|
||||||
|
|
||||||
|
type ToggleTaskLabelPayload {
|
||||||
|
active: Boolean!
|
||||||
|
task: Task!
|
||||||
|
}
|
||||||
|
|
||||||
|
input UpdateProjectName {
|
||||||
|
projectID: UUID!
|
||||||
|
name: String!
|
||||||
|
}
|
||||||
|
|
||||||
type Mutation {
|
type Mutation {
|
||||||
createRefreshToken(input: NewRefreshToken!): RefreshToken!
|
createRefreshToken(input: NewRefreshToken!): RefreshToken!
|
||||||
|
|
||||||
@ -1361,6 +1402,7 @@ type Mutation {
|
|||||||
createTeam(input: NewTeam!): Team!
|
createTeam(input: NewTeam!): Team!
|
||||||
|
|
||||||
createProject(input: NewProject!): Project!
|
createProject(input: NewProject!): Project!
|
||||||
|
updateProjectName(input: UpdateProjectName): Project!
|
||||||
|
|
||||||
createProjectLabel(input: NewProjectLabel!): ProjectLabel!
|
createProjectLabel(input: NewProjectLabel!): ProjectLabel!
|
||||||
deleteProjectLabel(input: DeleteProjectLabel!): ProjectLabel!
|
deleteProjectLabel(input: DeleteProjectLabel!): ProjectLabel!
|
||||||
@ -1374,6 +1416,7 @@ type Mutation {
|
|||||||
|
|
||||||
addTaskLabel(input: AddTaskLabelInput): Task!
|
addTaskLabel(input: AddTaskLabelInput): Task!
|
||||||
removeTaskLabel(input: RemoveTaskLabelInput): Task!
|
removeTaskLabel(input: RemoveTaskLabelInput): Task!
|
||||||
|
toggleTaskLabel(input: ToggleTaskLabelInput!): ToggleTaskLabelPayload!
|
||||||
|
|
||||||
createTask(input: NewTask!): Task!
|
createTask(input: NewTask!): Task!
|
||||||
updateTaskDescription(input: UpdateTaskDescriptionInput!): Task!
|
updateTaskDescription(input: UpdateTaskDescriptionInput!): Task!
|
||||||
@ -1589,6 +1632,20 @@ func (ec *executionContext) field_Mutation_removeTaskLabel_args(ctx context.Cont
|
|||||||
return args, nil
|
return args, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) field_Mutation_toggleTaskLabel_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
|
||||||
|
var err error
|
||||||
|
args := map[string]interface{}{}
|
||||||
|
var arg0 ToggleTaskLabelInput
|
||||||
|
if tmp, ok := rawArgs["input"]; ok {
|
||||||
|
arg0, err = ec.unmarshalNToggleTaskLabelInput2githubᚗcomᚋjordanknottᚋprojectᚑcitadelᚋapiᚋgraphᚐToggleTaskLabelInput(ctx, tmp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
args["input"] = arg0
|
||||||
|
return args, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (ec *executionContext) field_Mutation_unassignTask_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
|
func (ec *executionContext) field_Mutation_unassignTask_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{}{}
|
||||||
@ -1645,6 +1702,20 @@ func (ec *executionContext) field_Mutation_updateProjectLabel_args(ctx context.C
|
|||||||
return args, nil
|
return args, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) field_Mutation_updateProjectName_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
|
||||||
|
var err error
|
||||||
|
args := map[string]interface{}{}
|
||||||
|
var arg0 *UpdateProjectName
|
||||||
|
if tmp, ok := rawArgs["input"]; ok {
|
||||||
|
arg0, err = ec.unmarshalOUpdateProjectName2ᚖgithubᚗcomᚋjordanknottᚋprojectᚑcitadelᚋapiᚋgraphᚐUpdateProjectName(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{}{}
|
||||||
@ -2243,6 +2314,47 @@ func (ec *executionContext) _Mutation_createProject(ctx context.Context, field g
|
|||||||
return ec.marshalNProject2ᚖgithubᚗcomᚋjordanknottᚋprojectᚑcitadelᚋapiᚋpgᚐProject(ctx, field.Selections, res)
|
return ec.marshalNProject2ᚖgithubᚗcomᚋjordanknottᚋprojectᚑcitadelᚋapiᚋpgᚐProject(ctx, field.Selections, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) _Mutation_updateProjectName(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_updateProjectName_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().UpdateProjectName(rctx, args["input"].(*UpdateProjectName))
|
||||||
|
})
|
||||||
|
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.Project)
|
||||||
|
fc.Result = res
|
||||||
|
return ec.marshalNProject2ᚖgithubᚗcomᚋjordanknottᚋprojectᚑcitadelᚋapiᚋpgᚐProject(ctx, field.Selections, res)
|
||||||
|
}
|
||||||
|
|
||||||
func (ec *executionContext) _Mutation_createProjectLabel(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
func (ec *executionContext) _Mutation_createProjectLabel(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
@ -2653,6 +2765,47 @@ func (ec *executionContext) _Mutation_removeTaskLabel(ctx context.Context, field
|
|||||||
return ec.marshalNTask2ᚖgithubᚗcomᚋjordanknottᚋprojectᚑcitadelᚋapiᚋpgᚐTask(ctx, field.Selections, res)
|
return ec.marshalNTask2ᚖgithubᚗcomᚋjordanknottᚋprojectᚑcitadelᚋapiᚋpgᚐTask(ctx, field.Selections, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) _Mutation_toggleTaskLabel(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_toggleTaskLabel_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().ToggleTaskLabel(rctx, args["input"].(ToggleTaskLabelInput))
|
||||||
|
})
|
||||||
|
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.(*ToggleTaskLabelPayload)
|
||||||
|
fc.Result = res
|
||||||
|
return ec.marshalNToggleTaskLabelPayload2ᚖgithubᚗcomᚋjordanknottᚋprojectᚑcitadelᚋapiᚋgraphᚐToggleTaskLabelPayload(ctx, field.Selections, res)
|
||||||
|
}
|
||||||
|
|
||||||
func (ec *executionContext) _Mutation_createTask(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
func (ec *executionContext) _Mutation_createTask(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
@ -4627,7 +4780,7 @@ func (ec *executionContext) _TaskLabel_id(ctx context.Context, field graphql.Col
|
|||||||
return ec.marshalNID2githubᚗcomᚋgoogleᚋuuidᚐUUID(ctx, field.Selections, res)
|
return ec.marshalNID2githubᚗcomᚋgoogleᚋuuidᚐUUID(ctx, field.Selections, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ec *executionContext) _TaskLabel_projectLabelID(ctx context.Context, field graphql.CollectedField, obj *pg.TaskLabel) (ret graphql.Marshaler) {
|
func (ec *executionContext) _TaskLabel_projectLabel(ctx context.Context, field graphql.CollectedField, obj *pg.TaskLabel) (ret graphql.Marshaler) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
ec.Error(ctx, ec.Recover(ctx, r))
|
ec.Error(ctx, ec.Recover(ctx, r))
|
||||||
@ -4638,13 +4791,13 @@ func (ec *executionContext) _TaskLabel_projectLabelID(ctx context.Context, field
|
|||||||
Object: "TaskLabel",
|
Object: "TaskLabel",
|
||||||
Field: field,
|
Field: field,
|
||||||
Args: nil,
|
Args: nil,
|
||||||
IsMethod: false,
|
IsMethod: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx = graphql.WithFieldContext(ctx, fc)
|
ctx = graphql.WithFieldContext(ctx, fc)
|
||||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||||
ctx = rctx // use context from middleware stack in children
|
ctx = rctx // use context from middleware stack in children
|
||||||
return obj.ProjectLabelID, nil
|
return ec.resolvers.TaskLabel().ProjectLabel(rctx, obj)
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ec.Error(ctx, err)
|
ec.Error(ctx, err)
|
||||||
@ -4656,9 +4809,9 @@ func (ec *executionContext) _TaskLabel_projectLabelID(ctx context.Context, field
|
|||||||
}
|
}
|
||||||
return graphql.Null
|
return graphql.Null
|
||||||
}
|
}
|
||||||
res := resTmp.(uuid.UUID)
|
res := resTmp.(*pg.ProjectLabel)
|
||||||
fc.Result = res
|
fc.Result = res
|
||||||
return ec.marshalNUUID2githubᚗcomᚋgoogleᚋuuidᚐUUID(ctx, field.Selections, res)
|
return ec.marshalNProjectLabel2ᚖgithubᚗcomᚋjordanknottᚋprojectᚑcitadelᚋapiᚋpgᚐProjectLabel(ctx, field.Selections, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ec *executionContext) _TaskLabel_assignedDate(ctx context.Context, field graphql.CollectedField, obj *pg.TaskLabel) (ret graphql.Marshaler) {
|
func (ec *executionContext) _TaskLabel_assignedDate(ctx context.Context, field graphql.CollectedField, obj *pg.TaskLabel) (ret graphql.Marshaler) {
|
||||||
@ -4695,71 +4848,6 @@ func (ec *executionContext) _TaskLabel_assignedDate(ctx context.Context, field g
|
|||||||
return ec.marshalNTime2timeᚐTime(ctx, field.Selections, res)
|
return ec.marshalNTime2timeᚐTime(ctx, field.Selections, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ec *executionContext) _TaskLabel_colorHex(ctx context.Context, field graphql.CollectedField, obj *pg.TaskLabel) (ret graphql.Marshaler) {
|
|
||||||
defer func() {
|
|
||||||
if r := recover(); r != nil {
|
|
||||||
ec.Error(ctx, ec.Recover(ctx, r))
|
|
||||||
ret = graphql.Null
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
fc := &graphql.FieldContext{
|
|
||||||
Object: "TaskLabel",
|
|
||||||
Field: field,
|
|
||||||
Args: nil,
|
|
||||||
IsMethod: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx = graphql.WithFieldContext(ctx, fc)
|
|
||||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
|
||||||
ctx = rctx // use context from middleware stack in children
|
|
||||||
return ec.resolvers.TaskLabel().ColorHex(rctx, obj)
|
|
||||||
})
|
|
||||||
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.(string)
|
|
||||||
fc.Result = res
|
|
||||||
return ec.marshalNString2string(ctx, field.Selections, res)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ec *executionContext) _TaskLabel_name(ctx context.Context, field graphql.CollectedField, obj *pg.TaskLabel) (ret graphql.Marshaler) {
|
|
||||||
defer func() {
|
|
||||||
if r := recover(); r != nil {
|
|
||||||
ec.Error(ctx, ec.Recover(ctx, r))
|
|
||||||
ret = graphql.Null
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
fc := &graphql.FieldContext{
|
|
||||||
Object: "TaskLabel",
|
|
||||||
Field: field,
|
|
||||||
Args: nil,
|
|
||||||
IsMethod: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx = graphql.WithFieldContext(ctx, fc)
|
|
||||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
|
||||||
ctx = rctx // use context from middleware stack in children
|
|
||||||
return ec.resolvers.TaskLabel().Name(rctx, obj)
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
ec.Error(ctx, err)
|
|
||||||
return graphql.Null
|
|
||||||
}
|
|
||||||
if resTmp == nil {
|
|
||||||
return graphql.Null
|
|
||||||
}
|
|
||||||
res := resTmp.(*string)
|
|
||||||
fc.Result = res
|
|
||||||
return ec.marshalOString2ᚖstring(ctx, field.Selections, res)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ec *executionContext) _Team_id(ctx context.Context, field graphql.CollectedField, obj *pg.Team) (ret graphql.Marshaler) {
|
func (ec *executionContext) _Team_id(ctx context.Context, field graphql.CollectedField, obj *pg.Team) (ret graphql.Marshaler) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
@ -4862,6 +4950,74 @@ func (ec *executionContext) _Team_name(ctx context.Context, field graphql.Collec
|
|||||||
return ec.marshalNString2string(ctx, field.Selections, res)
|
return ec.marshalNString2string(ctx, field.Selections, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) _ToggleTaskLabelPayload_active(ctx context.Context, field graphql.CollectedField, obj *ToggleTaskLabelPayload) (ret graphql.Marshaler) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
ec.Error(ctx, ec.Recover(ctx, r))
|
||||||
|
ret = graphql.Null
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
fc := &graphql.FieldContext{
|
||||||
|
Object: "ToggleTaskLabelPayload",
|
||||||
|
Field: field,
|
||||||
|
Args: nil,
|
||||||
|
IsMethod: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = graphql.WithFieldContext(ctx, fc)
|
||||||
|
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||||
|
ctx = rctx // use context from middleware stack in children
|
||||||
|
return obj.Active, nil
|
||||||
|
})
|
||||||
|
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.(bool)
|
||||||
|
fc.Result = res
|
||||||
|
return ec.marshalNBoolean2bool(ctx, field.Selections, res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) _ToggleTaskLabelPayload_task(ctx context.Context, field graphql.CollectedField, obj *ToggleTaskLabelPayload) (ret graphql.Marshaler) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
ec.Error(ctx, ec.Recover(ctx, r))
|
||||||
|
ret = graphql.Null
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
fc := &graphql.FieldContext{
|
||||||
|
Object: "ToggleTaskLabelPayload",
|
||||||
|
Field: field,
|
||||||
|
Args: nil,
|
||||||
|
IsMethod: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = graphql.WithFieldContext(ctx, fc)
|
||||||
|
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||||
|
ctx = rctx // use context from middleware stack in children
|
||||||
|
return obj.Task, nil
|
||||||
|
})
|
||||||
|
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.Task)
|
||||||
|
fc.Result = res
|
||||||
|
return ec.marshalNTask2ᚖgithubᚗcomᚋjordanknottᚋprojectᚑcitadelᚋapiᚋpgᚐTask(ctx, field.Selections, res)
|
||||||
|
}
|
||||||
|
|
||||||
func (ec *executionContext) _UserAccount_id(ctx context.Context, field graphql.CollectedField, obj *pg.UserAccount) (ret graphql.Marshaler) {
|
func (ec *executionContext) _UserAccount_id(ctx context.Context, field graphql.CollectedField, obj *pg.UserAccount) (ret graphql.Marshaler) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
@ -6167,9 +6323,9 @@ func (ec *executionContext) unmarshalInputAddTaskLabelInput(ctx context.Context,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return it, err
|
return it, err
|
||||||
}
|
}
|
||||||
case "labelColorID":
|
case "projectLabelID":
|
||||||
var err error
|
var err error
|
||||||
it.LabelColorID, err = ec.unmarshalNUUID2githubᚗcomᚋgoogleᚋuuidᚐUUID(ctx, v)
|
it.ProjectLabelID, err = ec.unmarshalNUUID2githubᚗcomᚋgoogleᚋuuidᚐUUID(ctx, v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return it, err
|
return it, err
|
||||||
}
|
}
|
||||||
@ -6609,6 +6765,24 @@ func (ec *executionContext) unmarshalInputRemoveTaskLabelInput(ctx context.Conte
|
|||||||
var it RemoveTaskLabelInput
|
var it RemoveTaskLabelInput
|
||||||
var asMap = obj.(map[string]interface{})
|
var asMap = obj.(map[string]interface{})
|
||||||
|
|
||||||
|
for k, v := range asMap {
|
||||||
|
switch k {
|
||||||
|
case "taskLabelID":
|
||||||
|
var err error
|
||||||
|
it.TaskLabelID, err = ec.unmarshalNUUID2githubᚗcomᚋgoogleᚋuuidᚐUUID(ctx, v)
|
||||||
|
if err != nil {
|
||||||
|
return it, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return it, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) unmarshalInputToggleTaskLabelInput(ctx context.Context, obj interface{}) (ToggleTaskLabelInput, error) {
|
||||||
|
var it ToggleTaskLabelInput
|
||||||
|
var asMap = obj.(map[string]interface{})
|
||||||
|
|
||||||
for k, v := range asMap {
|
for k, v := range asMap {
|
||||||
switch k {
|
switch k {
|
||||||
case "taskID":
|
case "taskID":
|
||||||
@ -6617,9 +6791,9 @@ func (ec *executionContext) unmarshalInputRemoveTaskLabelInput(ctx context.Conte
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return it, err
|
return it, err
|
||||||
}
|
}
|
||||||
case "taskLabelID":
|
case "projectLabelID":
|
||||||
var err error
|
var err error
|
||||||
it.TaskLabelID, err = ec.unmarshalNUUID2githubᚗcomᚋgoogleᚋuuidᚐUUID(ctx, v)
|
it.ProjectLabelID, err = ec.unmarshalNUUID2githubᚗcomᚋgoogleᚋuuidᚐUUID(ctx, v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return it, err
|
return it, err
|
||||||
}
|
}
|
||||||
@ -6731,6 +6905,30 @@ func (ec *executionContext) unmarshalInputUpdateProjectLabelName(ctx context.Con
|
|||||||
return it, nil
|
return it, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) unmarshalInputUpdateProjectName(ctx context.Context, obj interface{}) (UpdateProjectName, error) {
|
||||||
|
var it UpdateProjectName
|
||||||
|
var asMap = obj.(map[string]interface{})
|
||||||
|
|
||||||
|
for k, v := range asMap {
|
||||||
|
switch k {
|
||||||
|
case "projectID":
|
||||||
|
var err error
|
||||||
|
it.ProjectID, 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{})
|
||||||
@ -6937,6 +7135,11 @@ 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 "updateProjectName":
|
||||||
|
out.Values[i] = ec._Mutation_updateProjectName(ctx, field)
|
||||||
|
if out.Values[i] == graphql.Null {
|
||||||
|
invalids++
|
||||||
|
}
|
||||||
case "createProjectLabel":
|
case "createProjectLabel":
|
||||||
out.Values[i] = ec._Mutation_createProjectLabel(ctx, field)
|
out.Values[i] = ec._Mutation_createProjectLabel(ctx, field)
|
||||||
if out.Values[i] == graphql.Null {
|
if out.Values[i] == graphql.Null {
|
||||||
@ -6987,6 +7190,11 @@ 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 "toggleTaskLabel":
|
||||||
|
out.Values[i] = ec._Mutation_toggleTaskLabel(ctx, field)
|
||||||
|
if out.Values[i] == graphql.Null {
|
||||||
|
invalids++
|
||||||
|
}
|
||||||
case "createTask":
|
case "createTask":
|
||||||
out.Values[i] = ec._Mutation_createTask(ctx, field)
|
out.Values[i] = ec._Mutation_createTask(ctx, field)
|
||||||
if out.Values[i] == graphql.Null {
|
if out.Values[i] == graphql.Null {
|
||||||
@ -7691,17 +7899,7 @@ func (ec *executionContext) _TaskLabel(ctx context.Context, sel ast.SelectionSet
|
|||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
})
|
})
|
||||||
case "projectLabelID":
|
case "projectLabel":
|
||||||
out.Values[i] = ec._TaskLabel_projectLabelID(ctx, field, obj)
|
|
||||||
if out.Values[i] == graphql.Null {
|
|
||||||
atomic.AddUint32(&invalids, 1)
|
|
||||||
}
|
|
||||||
case "assignedDate":
|
|
||||||
out.Values[i] = ec._TaskLabel_assignedDate(ctx, field, obj)
|
|
||||||
if out.Values[i] == graphql.Null {
|
|
||||||
atomic.AddUint32(&invalids, 1)
|
|
||||||
}
|
|
||||||
case "colorHex":
|
|
||||||
field := field
|
field := field
|
||||||
out.Concurrently(i, func() (res graphql.Marshaler) {
|
out.Concurrently(i, func() (res graphql.Marshaler) {
|
||||||
defer func() {
|
defer func() {
|
||||||
@ -7709,23 +7907,17 @@ func (ec *executionContext) _TaskLabel(ctx context.Context, sel ast.SelectionSet
|
|||||||
ec.Error(ctx, ec.Recover(ctx, r))
|
ec.Error(ctx, ec.Recover(ctx, r))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
res = ec._TaskLabel_colorHex(ctx, field, obj)
|
res = ec._TaskLabel_projectLabel(ctx, field, obj)
|
||||||
if res == graphql.Null {
|
if res == graphql.Null {
|
||||||
atomic.AddUint32(&invalids, 1)
|
atomic.AddUint32(&invalids, 1)
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
})
|
})
|
||||||
case "name":
|
case "assignedDate":
|
||||||
field := field
|
out.Values[i] = ec._TaskLabel_assignedDate(ctx, field, obj)
|
||||||
out.Concurrently(i, func() (res graphql.Marshaler) {
|
if out.Values[i] == graphql.Null {
|
||||||
defer func() {
|
atomic.AddUint32(&invalids, 1)
|
||||||
if r := recover(); r != nil {
|
|
||||||
ec.Error(ctx, ec.Recover(ctx, r))
|
|
||||||
}
|
}
|
||||||
}()
|
|
||||||
res = ec._TaskLabel_name(ctx, field, obj)
|
|
||||||
return res
|
|
||||||
})
|
|
||||||
default:
|
default:
|
||||||
panic("unknown field " + strconv.Quote(field.Name))
|
panic("unknown field " + strconv.Quote(field.Name))
|
||||||
}
|
}
|
||||||
@ -7783,6 +7975,38 @@ func (ec *executionContext) _Team(ctx context.Context, sel ast.SelectionSet, obj
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var toggleTaskLabelPayloadImplementors = []string{"ToggleTaskLabelPayload"}
|
||||||
|
|
||||||
|
func (ec *executionContext) _ToggleTaskLabelPayload(ctx context.Context, sel ast.SelectionSet, obj *ToggleTaskLabelPayload) graphql.Marshaler {
|
||||||
|
fields := graphql.CollectFields(ec.OperationContext, sel, toggleTaskLabelPayloadImplementors)
|
||||||
|
|
||||||
|
out := graphql.NewFieldSet(fields)
|
||||||
|
var invalids uint32
|
||||||
|
for i, field := range fields {
|
||||||
|
switch field.Name {
|
||||||
|
case "__typename":
|
||||||
|
out.Values[i] = graphql.MarshalString("ToggleTaskLabelPayload")
|
||||||
|
case "active":
|
||||||
|
out.Values[i] = ec._ToggleTaskLabelPayload_active(ctx, field, obj)
|
||||||
|
if out.Values[i] == graphql.Null {
|
||||||
|
invalids++
|
||||||
|
}
|
||||||
|
case "task":
|
||||||
|
out.Values[i] = ec._ToggleTaskLabelPayload_task(ctx, field, obj)
|
||||||
|
if out.Values[i] == graphql.Null {
|
||||||
|
invalids++
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
panic("unknown field " + strconv.Quote(field.Name))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out.Dispatch()
|
||||||
|
if invalids > 0 {
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
var userAccountImplementors = []string{"UserAccount"}
|
var userAccountImplementors = []string{"UserAccount"}
|
||||||
|
|
||||||
func (ec *executionContext) _UserAccount(ctx context.Context, sel ast.SelectionSet, obj *pg.UserAccount) graphql.Marshaler {
|
func (ec *executionContext) _UserAccount(ctx context.Context, sel ast.SelectionSet, obj *pg.UserAccount) graphql.Marshaler {
|
||||||
@ -8668,6 +8892,24 @@ func (ec *executionContext) marshalNTime2timeᚐTime(ctx context.Context, sel as
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) unmarshalNToggleTaskLabelInput2githubᚗcomᚋjordanknottᚋprojectᚑcitadelᚋapiᚋgraphᚐToggleTaskLabelInput(ctx context.Context, v interface{}) (ToggleTaskLabelInput, error) {
|
||||||
|
return ec.unmarshalInputToggleTaskLabelInput(ctx, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) marshalNToggleTaskLabelPayload2githubᚗcomᚋjordanknottᚋprojectᚑcitadelᚋapiᚋgraphᚐToggleTaskLabelPayload(ctx context.Context, sel ast.SelectionSet, v ToggleTaskLabelPayload) graphql.Marshaler {
|
||||||
|
return ec._ToggleTaskLabelPayload(ctx, sel, &v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) marshalNToggleTaskLabelPayload2ᚖgithubᚗcomᚋjordanknottᚋprojectᚑcitadelᚋapiᚋgraphᚐToggleTaskLabelPayload(ctx context.Context, sel ast.SelectionSet, v *ToggleTaskLabelPayload) graphql.Marshaler {
|
||||||
|
if v == nil {
|
||||||
|
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
|
||||||
|
ec.Errorf(ctx, "must not be null")
|
||||||
|
}
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
return ec._ToggleTaskLabelPayload(ctx, sel, v)
|
||||||
|
}
|
||||||
|
|
||||||
func (ec *executionContext) unmarshalNUUID2githubᚗcomᚋgoogleᚋuuidᚐUUID(ctx context.Context, v interface{}) (uuid.UUID, error) {
|
func (ec *executionContext) unmarshalNUUID2githubᚗcomᚋgoogleᚋuuidᚐUUID(ctx context.Context, v interface{}) (uuid.UUID, error) {
|
||||||
return UnmarshalUUID(v)
|
return UnmarshalUUID(v)
|
||||||
}
|
}
|
||||||
@ -9085,6 +9327,18 @@ func (ec *executionContext) unmarshalOUnassignTaskInput2ᚖgithubᚗcomᚋjordan
|
|||||||
return &res, err
|
return &res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) unmarshalOUpdateProjectName2githubᚗcomᚋjordanknottᚋprojectᚑcitadelᚋapiᚋgraphᚐUpdateProjectName(ctx context.Context, v interface{}) (UpdateProjectName, error) {
|
||||||
|
return ec.unmarshalInputUpdateProjectName(ctx, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) unmarshalOUpdateProjectName2ᚖgithubᚗcomᚋjordanknottᚋprojectᚑcitadelᚋapiᚋgraphᚐUpdateProjectName(ctx context.Context, v interface{}) (*UpdateProjectName, error) {
|
||||||
|
if v == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
res, err := ec.unmarshalOUpdateProjectName2githubᚗcomᚋjordanknottᚋprojectᚑcitadelᚋapiᚋgraphᚐUpdateProjectName(ctx, v)
|
||||||
|
return &res, err
|
||||||
|
}
|
||||||
|
|
||||||
func (ec *executionContext) marshalO__EnumValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.EnumValue) graphql.Marshaler {
|
func (ec *executionContext) marshalO__EnumValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.EnumValue) graphql.Marshaler {
|
||||||
if v == nil {
|
if v == nil {
|
||||||
return graphql.Null
|
return graphql.Null
|
||||||
|
@ -9,7 +9,7 @@ import (
|
|||||||
|
|
||||||
type AddTaskLabelInput struct {
|
type AddTaskLabelInput struct {
|
||||||
TaskID uuid.UUID `json:"taskID"`
|
TaskID uuid.UUID `json:"taskID"`
|
||||||
LabelColorID uuid.UUID `json:"labelColorID"`
|
ProjectLabelID uuid.UUID `json:"projectLabelID"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type AssignTaskInput struct {
|
type AssignTaskInput struct {
|
||||||
@ -125,10 +125,19 @@ type ProjectsFilter struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type RemoveTaskLabelInput struct {
|
type RemoveTaskLabelInput struct {
|
||||||
TaskID uuid.UUID `json:"taskID"`
|
|
||||||
TaskLabelID uuid.UUID `json:"taskLabelID"`
|
TaskLabelID uuid.UUID `json:"taskLabelID"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ToggleTaskLabelInput struct {
|
||||||
|
TaskID uuid.UUID `json:"taskID"`
|
||||||
|
ProjectLabelID uuid.UUID `json:"projectLabelID"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ToggleTaskLabelPayload struct {
|
||||||
|
Active bool `json:"active"`
|
||||||
|
Task *pg.Task `json:"task"`
|
||||||
|
}
|
||||||
|
|
||||||
type UnassignTaskInput struct {
|
type UnassignTaskInput struct {
|
||||||
TaskID uuid.UUID `json:"taskID"`
|
TaskID uuid.UUID `json:"taskID"`
|
||||||
UserID uuid.UUID `json:"userID"`
|
UserID uuid.UUID `json:"userID"`
|
||||||
@ -150,6 +159,11 @@ type UpdateProjectLabelName struct {
|
|||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UpdateProjectName struct {
|
||||||
|
ProjectID uuid.UUID `json:"projectID"`
|
||||||
|
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"`
|
||||||
|
@ -17,10 +17,8 @@ type LabelColor {
|
|||||||
|
|
||||||
type TaskLabel {
|
type TaskLabel {
|
||||||
id: ID!
|
id: ID!
|
||||||
projectLabelID: UUID!
|
projectLabel: ProjectLabel!
|
||||||
assignedDate: Time!
|
assignedDate: Time!
|
||||||
colorHex: String!
|
|
||||||
name: String
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProfileIcon {
|
type ProfileIcon {
|
||||||
@ -204,11 +202,10 @@ input UpdateTaskDescriptionInput {
|
|||||||
|
|
||||||
input AddTaskLabelInput {
|
input AddTaskLabelInput {
|
||||||
taskID: UUID!
|
taskID: UUID!
|
||||||
labelColorID: UUID!
|
projectLabelID: UUID!
|
||||||
}
|
}
|
||||||
|
|
||||||
input RemoveTaskLabelInput {
|
input RemoveTaskLabelInput {
|
||||||
taskID: UUID!
|
|
||||||
taskLabelID: UUID!
|
taskLabelID: UUID!
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,6 +235,21 @@ input UpdateProjectLabelColor {
|
|||||||
labelColorID: UUID!
|
labelColorID: UUID!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input ToggleTaskLabelInput {
|
||||||
|
taskID: UUID!
|
||||||
|
projectLabelID: UUID!
|
||||||
|
}
|
||||||
|
|
||||||
|
type ToggleTaskLabelPayload {
|
||||||
|
active: Boolean!
|
||||||
|
task: Task!
|
||||||
|
}
|
||||||
|
|
||||||
|
input UpdateProjectName {
|
||||||
|
projectID: UUID!
|
||||||
|
name: String!
|
||||||
|
}
|
||||||
|
|
||||||
type Mutation {
|
type Mutation {
|
||||||
createRefreshToken(input: NewRefreshToken!): RefreshToken!
|
createRefreshToken(input: NewRefreshToken!): RefreshToken!
|
||||||
|
|
||||||
@ -246,6 +258,7 @@ type Mutation {
|
|||||||
createTeam(input: NewTeam!): Team!
|
createTeam(input: NewTeam!): Team!
|
||||||
|
|
||||||
createProject(input: NewProject!): Project!
|
createProject(input: NewProject!): Project!
|
||||||
|
updateProjectName(input: UpdateProjectName): Project!
|
||||||
|
|
||||||
createProjectLabel(input: NewProjectLabel!): ProjectLabel!
|
createProjectLabel(input: NewProjectLabel!): ProjectLabel!
|
||||||
deleteProjectLabel(input: DeleteProjectLabel!): ProjectLabel!
|
deleteProjectLabel(input: DeleteProjectLabel!): ProjectLabel!
|
||||||
@ -259,6 +272,7 @@ type Mutation {
|
|||||||
|
|
||||||
addTaskLabel(input: AddTaskLabelInput): Task!
|
addTaskLabel(input: AddTaskLabelInput): Task!
|
||||||
removeTaskLabel(input: RemoveTaskLabelInput): Task!
|
removeTaskLabel(input: RemoveTaskLabelInput): Task!
|
||||||
|
toggleTaskLabel(input: ToggleTaskLabelInput!): ToggleTaskLabelPayload!
|
||||||
|
|
||||||
createTask(input: NewTask!): Task!
|
createTask(input: NewTask!): Task!
|
||||||
updateTaskDescription(input: UpdateTaskDescriptionInput!): Task!
|
updateTaskDescription(input: UpdateTaskDescriptionInput!): Task!
|
||||||
|
@ -49,6 +49,14 @@ func (r *mutationResolver) CreateProject(ctx context.Context, input NewProject)
|
|||||||
return &project, err
|
return &project, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *mutationResolver) UpdateProjectName(ctx context.Context, input *UpdateProjectName) (*pg.Project, error) {
|
||||||
|
project, err := r.Repository.UpdateProjectNameByID(ctx, pg.UpdateProjectNameByIDParams{ProjectID: input.ProjectID, Name: input.Name})
|
||||||
|
if err != nil {
|
||||||
|
return &pg.Project{}, err
|
||||||
|
}
|
||||||
|
return &project, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (r *mutationResolver) CreateProjectLabel(ctx context.Context, input NewProjectLabel) (*pg.ProjectLabel, error) {
|
func (r *mutationResolver) CreateProjectLabel(ctx context.Context, input NewProjectLabel) (*pg.ProjectLabel, error) {
|
||||||
createdAt := time.Now().UTC()
|
createdAt := time.Now().UTC()
|
||||||
|
|
||||||
@ -130,7 +138,7 @@ func (r *mutationResolver) DeleteTaskGroup(ctx context.Context, input DeleteTask
|
|||||||
|
|
||||||
func (r *mutationResolver) AddTaskLabel(ctx context.Context, input *AddTaskLabelInput) (*pg.Task, error) {
|
func (r *mutationResolver) AddTaskLabel(ctx context.Context, input *AddTaskLabelInput) (*pg.Task, error) {
|
||||||
assignedDate := time.Now().UTC()
|
assignedDate := time.Now().UTC()
|
||||||
_, err := r.Repository.CreateTaskLabelForTask(ctx, pg.CreateTaskLabelForTaskParams{input.TaskID, input.LabelColorID, assignedDate})
|
_, err := r.Repository.CreateTaskLabelForTask(ctx, pg.CreateTaskLabelForTaskParams{input.TaskID, input.ProjectLabelID, assignedDate})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &pg.Task{}, err
|
return &pg.Task{}, err
|
||||||
}
|
}
|
||||||
@ -139,7 +147,56 @@ func (r *mutationResolver) AddTaskLabel(ctx context.Context, input *AddTaskLabel
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *mutationResolver) RemoveTaskLabel(ctx context.Context, input *RemoveTaskLabelInput) (*pg.Task, error) {
|
func (r *mutationResolver) RemoveTaskLabel(ctx context.Context, input *RemoveTaskLabelInput) (*pg.Task, error) {
|
||||||
panic(fmt.Errorf("not implemented"))
|
taskLabel, err := r.Repository.GetTaskLabelByID(ctx, input.TaskLabelID)
|
||||||
|
if err != nil {
|
||||||
|
return &pg.Task{}, err
|
||||||
|
}
|
||||||
|
task, err := r.Repository.GetTaskByID(ctx, taskLabel.TaskID)
|
||||||
|
if err != nil {
|
||||||
|
return &pg.Task{}, err
|
||||||
|
}
|
||||||
|
err = r.Repository.DeleteTaskLabelByID(ctx, input.TaskLabelID)
|
||||||
|
return &task, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *mutationResolver) ToggleTaskLabel(ctx context.Context, input ToggleTaskLabelInput) (*ToggleTaskLabelPayload, error) {
|
||||||
|
task, err := r.Repository.GetTaskByID(ctx, input.TaskID)
|
||||||
|
if err != nil {
|
||||||
|
return &ToggleTaskLabelPayload{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = r.Repository.GetTaskLabelForTaskByProjectLabelID(ctx, pg.GetTaskLabelForTaskByProjectLabelIDParams{TaskID: input.TaskID, ProjectLabelID: input.ProjectLabelID})
|
||||||
|
createdAt := time.Now().UTC()
|
||||||
|
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
log.WithFields(log.Fields{"err": err}).Warning("no rows")
|
||||||
|
_, err := r.Repository.CreateTaskLabelForTask(ctx, pg.CreateTaskLabelForTaskParams{
|
||||||
|
TaskID: input.TaskID,
|
||||||
|
ProjectLabelID: input.ProjectLabelID,
|
||||||
|
AssignedDate: createdAt,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return &ToggleTaskLabelPayload{}, err
|
||||||
|
}
|
||||||
|
payload := ToggleTaskLabelPayload{Active: true, Task: &task}
|
||||||
|
return &payload, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return &ToggleTaskLabelPayload{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = r.Repository.DeleteTaskLabelForTaskByProjectLabelID(ctx, pg.DeleteTaskLabelForTaskByProjectLabelIDParams{
|
||||||
|
TaskID: input.TaskID,
|
||||||
|
ProjectLabelID: input.ProjectLabelID,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return &ToggleTaskLabelPayload{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
payload := ToggleTaskLabelPayload{Active: false, Task: &task}
|
||||||
|
return &payload, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *mutationResolver) CreateTask(ctx context.Context, input NewTask) (*pg.Task, error) {
|
func (r *mutationResolver) CreateTask(ctx context.Context, input NewTask) (*pg.Task, error) {
|
||||||
@ -434,28 +491,9 @@ func (r *taskLabelResolver) ID(ctx context.Context, obj *pg.TaskLabel) (uuid.UUI
|
|||||||
return obj.TaskLabelID, nil
|
return obj.TaskLabelID, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *taskLabelResolver) ColorHex(ctx context.Context, obj *pg.TaskLabel) (string, error) {
|
func (r *taskLabelResolver) ProjectLabel(ctx context.Context, obj *pg.TaskLabel) (*pg.ProjectLabel, error) {
|
||||||
projectLabel, err := r.Repository.GetProjectLabelByID(ctx, obj.ProjectLabelID)
|
projectLabel, err := r.Repository.GetProjectLabelByID(ctx, obj.ProjectLabelID)
|
||||||
if err != nil {
|
return &projectLabel, err
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
labelColor, err := r.Repository.GetLabelColorByID(ctx, projectLabel.LabelColorID)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return labelColor.ColorHex, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *taskLabelResolver) Name(ctx context.Context, obj *pg.TaskLabel) (*string, error) {
|
|
||||||
projectLabel, err := r.Repository.GetProjectLabelByID(ctx, obj.ProjectLabelID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
name := projectLabel.Name
|
|
||||||
if !name.Valid {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &name.String, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *teamResolver) ID(ctx context.Context, obj *pg.Team) (uuid.UUID, error) {
|
func (r *teamResolver) ID(ctx context.Context, obj *pg.Team) (uuid.UUID, error) {
|
||||||
@ -523,6 +561,28 @@ type userAccountResolver struct{ *Resolver }
|
|||||||
// - When renaming or deleting a resolver the old code will be put in here. You can safely delete
|
// - When renaming or deleting a resolver the old code will be put in here. You can safely delete
|
||||||
// it when you're done.
|
// it when you're done.
|
||||||
// - You have helper methods in this file. Move them out to keep these resolver files clean.
|
// - You have helper methods in this file. Move them out to keep these resolver files clean.
|
||||||
|
func (r *taskLabelResolver) ColorHex(ctx context.Context, obj *pg.TaskLabel) (string, error) {
|
||||||
|
projectLabel, err := r.Repository.GetProjectLabelByID(ctx, obj.ProjectLabelID)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
labelColor, err := r.Repository.GetLabelColorByID(ctx, projectLabel.LabelColorID)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return labelColor.ColorHex, nil
|
||||||
|
}
|
||||||
|
func (r *taskLabelResolver) Name(ctx context.Context, obj *pg.TaskLabel) (*string, error) {
|
||||||
|
projectLabel, err := r.Repository.GetProjectLabelByID(ctx, obj.ProjectLabelID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
name := projectLabel.Name
|
||||||
|
if !name.Valid {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &name.String, err
|
||||||
|
}
|
||||||
func (r *projectLabelResolver) ColorHex(ctx context.Context, obj *pg.ProjectLabel) (string, error) {
|
func (r *projectLabelResolver) ColorHex(ctx context.Context, obj *pg.ProjectLabel) (string, error) {
|
||||||
labelColor, err := r.Repository.GetLabelColorByID(ctx, obj.LabelColorID)
|
labelColor, err := r.Repository.GetLabelColorByID(ctx, obj.LabelColorID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE task_label ADD UNIQUE (project_label_id, task_id);
|
@ -22,6 +22,13 @@ type Repository interface {
|
|||||||
GetUserAccountByUsername(ctx context.Context, username string) (UserAccount, error)
|
GetUserAccountByUsername(ctx context.Context, username string) (UserAccount, error)
|
||||||
GetAllUserAccounts(ctx context.Context) ([]UserAccount, error)
|
GetAllUserAccounts(ctx context.Context) ([]UserAccount, error)
|
||||||
|
|
||||||
|
GetTaskLabelByID(ctx context.Context, taskLabelID uuid.UUID) (TaskLabel, error)
|
||||||
|
|
||||||
|
DeleteTaskLabelForTaskByProjectLabelID(ctx context.Context, arg DeleteTaskLabelForTaskByProjectLabelIDParams) error
|
||||||
|
GetTaskLabelForTaskByProjectLabelID(ctx context.Context, arg GetTaskLabelForTaskByProjectLabelIDParams) (TaskLabel, error)
|
||||||
|
UpdateProjectNameByID(ctx context.Context, arg UpdateProjectNameByIDParams) (Project, error)
|
||||||
|
|
||||||
|
DeleteTaskLabelByID(ctx context.Context, taskLabelID uuid.UUID) error
|
||||||
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)
|
||||||
|
@ -121,3 +121,25 @@ func (q *Queries) GetProjectByID(ctx context.Context, projectID uuid.UUID) (Proj
|
|||||||
)
|
)
|
||||||
return i, err
|
return i, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const updateProjectNameByID = `-- name: UpdateProjectNameByID :one
|
||||||
|
UPDATE project SET name = $2 WHERE project_id = $1 RETURNING project_id, team_id, created_at, name, owner
|
||||||
|
`
|
||||||
|
|
||||||
|
type UpdateProjectNameByIDParams struct {
|
||||||
|
ProjectID uuid.UUID `json:"project_id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) UpdateProjectNameByID(ctx context.Context, arg UpdateProjectNameByIDParams) (Project, error) {
|
||||||
|
row := q.db.QueryRowContext(ctx, updateProjectNameByID, arg.ProjectID, arg.Name)
|
||||||
|
var i Project
|
||||||
|
err := row.Scan(
|
||||||
|
&i.ProjectID,
|
||||||
|
&i.TeamID,
|
||||||
|
&i.CreatedAt,
|
||||||
|
&i.Name,
|
||||||
|
&i.Owner,
|
||||||
|
)
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
|
@ -27,6 +27,8 @@ type Querier interface {
|
|||||||
DeleteTaskAssignedByID(ctx context.Context, arg DeleteTaskAssignedByIDParams) (TaskAssigned, error)
|
DeleteTaskAssignedByID(ctx context.Context, arg DeleteTaskAssignedByIDParams) (TaskAssigned, error)
|
||||||
DeleteTaskByID(ctx context.Context, taskID uuid.UUID) error
|
DeleteTaskByID(ctx context.Context, taskID uuid.UUID) error
|
||||||
DeleteTaskGroupByID(ctx context.Context, taskGroupID uuid.UUID) (int64, error)
|
DeleteTaskGroupByID(ctx context.Context, taskGroupID uuid.UUID) (int64, error)
|
||||||
|
DeleteTaskLabelByID(ctx context.Context, taskLabelID uuid.UUID) error
|
||||||
|
DeleteTaskLabelForTaskByProjectLabelID(ctx context.Context, arg DeleteTaskLabelForTaskByProjectLabelIDParams) error
|
||||||
DeleteTasksByTaskGroupID(ctx context.Context, taskGroupID uuid.UUID) (int64, error)
|
DeleteTasksByTaskGroupID(ctx context.Context, taskGroupID uuid.UUID) (int64, error)
|
||||||
DeleteTeamByID(ctx context.Context, teamID uuid.UUID) error
|
DeleteTeamByID(ctx context.Context, teamID uuid.UUID) error
|
||||||
GetAllOrganizations(ctx context.Context) ([]Organization, error)
|
GetAllOrganizations(ctx context.Context) ([]Organization, error)
|
||||||
@ -46,6 +48,8 @@ type Querier interface {
|
|||||||
GetTaskByID(ctx context.Context, taskID uuid.UUID) (Task, error)
|
GetTaskByID(ctx context.Context, taskID uuid.UUID) (Task, error)
|
||||||
GetTaskGroupByID(ctx context.Context, taskGroupID uuid.UUID) (TaskGroup, error)
|
GetTaskGroupByID(ctx context.Context, taskGroupID uuid.UUID) (TaskGroup, error)
|
||||||
GetTaskGroupsForProject(ctx context.Context, projectID uuid.UUID) ([]TaskGroup, error)
|
GetTaskGroupsForProject(ctx context.Context, projectID uuid.UUID) ([]TaskGroup, error)
|
||||||
|
GetTaskLabelByID(ctx context.Context, taskLabelID uuid.UUID) (TaskLabel, error)
|
||||||
|
GetTaskLabelForTaskByProjectLabelID(ctx context.Context, arg GetTaskLabelForTaskByProjectLabelIDParams) (TaskLabel, error)
|
||||||
GetTaskLabelsForTaskID(ctx context.Context, taskID uuid.UUID) ([]TaskLabel, error)
|
GetTaskLabelsForTaskID(ctx context.Context, taskID uuid.UUID) ([]TaskLabel, error)
|
||||||
GetTasksForTaskGroupID(ctx context.Context, taskGroupID uuid.UUID) ([]Task, error)
|
GetTasksForTaskGroupID(ctx context.Context, taskGroupID uuid.UUID) ([]Task, error)
|
||||||
GetTeamByID(ctx context.Context, teamID uuid.UUID) (Team, error)
|
GetTeamByID(ctx context.Context, teamID uuid.UUID) (Team, error)
|
||||||
@ -55,6 +59,7 @@ type Querier interface {
|
|||||||
UpdateProjectLabel(ctx context.Context, arg UpdateProjectLabelParams) (ProjectLabel, error)
|
UpdateProjectLabel(ctx context.Context, arg UpdateProjectLabelParams) (ProjectLabel, error)
|
||||||
UpdateProjectLabelColor(ctx context.Context, arg UpdateProjectLabelColorParams) (ProjectLabel, error)
|
UpdateProjectLabelColor(ctx context.Context, arg UpdateProjectLabelColorParams) (ProjectLabel, error)
|
||||||
UpdateProjectLabelName(ctx context.Context, arg UpdateProjectLabelNameParams) (ProjectLabel, error)
|
UpdateProjectLabelName(ctx context.Context, arg UpdateProjectLabelNameParams) (ProjectLabel, error)
|
||||||
|
UpdateProjectNameByID(ctx context.Context, arg UpdateProjectNameByIDParams) (Project, 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)
|
||||||
|
@ -33,6 +33,66 @@ func (q *Queries) CreateTaskLabelForTask(ctx context.Context, arg CreateTaskLabe
|
|||||||
return i, err
|
return i, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const deleteTaskLabelByID = `-- name: DeleteTaskLabelByID :exec
|
||||||
|
DELETE FROM task_label WHERE task_label_id = $1
|
||||||
|
`
|
||||||
|
|
||||||
|
func (q *Queries) DeleteTaskLabelByID(ctx context.Context, taskLabelID uuid.UUID) error {
|
||||||
|
_, err := q.db.ExecContext(ctx, deleteTaskLabelByID, taskLabelID)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
const deleteTaskLabelForTaskByProjectLabelID = `-- name: DeleteTaskLabelForTaskByProjectLabelID :exec
|
||||||
|
DELETE FROM task_label WHERE project_label_id = $2 AND task_id = $1
|
||||||
|
`
|
||||||
|
|
||||||
|
type DeleteTaskLabelForTaskByProjectLabelIDParams struct {
|
||||||
|
TaskID uuid.UUID `json:"task_id"`
|
||||||
|
ProjectLabelID uuid.UUID `json:"project_label_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) DeleteTaskLabelForTaskByProjectLabelID(ctx context.Context, arg DeleteTaskLabelForTaskByProjectLabelIDParams) error {
|
||||||
|
_, err := q.db.ExecContext(ctx, deleteTaskLabelForTaskByProjectLabelID, arg.TaskID, arg.ProjectLabelID)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
const getTaskLabelByID = `-- name: GetTaskLabelByID :one
|
||||||
|
SELECT task_label_id, task_id, project_label_id, assigned_date FROM task_label WHERE task_label_id = $1
|
||||||
|
`
|
||||||
|
|
||||||
|
func (q *Queries) GetTaskLabelByID(ctx context.Context, taskLabelID uuid.UUID) (TaskLabel, error) {
|
||||||
|
row := q.db.QueryRowContext(ctx, getTaskLabelByID, taskLabelID)
|
||||||
|
var i TaskLabel
|
||||||
|
err := row.Scan(
|
||||||
|
&i.TaskLabelID,
|
||||||
|
&i.TaskID,
|
||||||
|
&i.ProjectLabelID,
|
||||||
|
&i.AssignedDate,
|
||||||
|
)
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
|
|
||||||
|
const getTaskLabelForTaskByProjectLabelID = `-- name: GetTaskLabelForTaskByProjectLabelID :one
|
||||||
|
SELECT task_label_id, task_id, project_label_id, assigned_date FROM task_label WHERE task_id = $1 AND project_label_id = $2
|
||||||
|
`
|
||||||
|
|
||||||
|
type GetTaskLabelForTaskByProjectLabelIDParams struct {
|
||||||
|
TaskID uuid.UUID `json:"task_id"`
|
||||||
|
ProjectLabelID uuid.UUID `json:"project_label_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) GetTaskLabelForTaskByProjectLabelID(ctx context.Context, arg GetTaskLabelForTaskByProjectLabelIDParams) (TaskLabel, error) {
|
||||||
|
row := q.db.QueryRowContext(ctx, getTaskLabelForTaskByProjectLabelID, arg.TaskID, arg.ProjectLabelID)
|
||||||
|
var i TaskLabel
|
||||||
|
err := row.Scan(
|
||||||
|
&i.TaskLabelID,
|
||||||
|
&i.TaskID,
|
||||||
|
&i.ProjectLabelID,
|
||||||
|
&i.AssignedDate,
|
||||||
|
)
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
|
|
||||||
const getTaskLabelsForTaskID = `-- name: GetTaskLabelsForTaskID :many
|
const getTaskLabelsForTaskID = `-- name: GetTaskLabelsForTaskID :many
|
||||||
SELECT task_label_id, task_id, project_label_id, assigned_date FROM task_label WHERE task_id = $1
|
SELECT task_label_id, task_id, project_label_id, assigned_date FROM task_label WHERE task_id = $1
|
||||||
`
|
`
|
||||||
|
@ -9,3 +9,6 @@ SELECT * FROM project WHERE project_id = $1;
|
|||||||
|
|
||||||
-- name: CreateProject :one
|
-- name: CreateProject :one
|
||||||
INSERT INTO project(owner, team_id, created_at, name) VALUES ($1, $2, $3, $4) RETURNING *;
|
INSERT INTO project(owner, team_id, created_at, name) VALUES ($1, $2, $3, $4) RETURNING *;
|
||||||
|
|
||||||
|
-- name: UpdateProjectNameByID :one
|
||||||
|
UPDATE project SET name = $2 WHERE project_id = $1 RETURNING *;
|
||||||
|
@ -4,3 +4,15 @@ INSERT INTO task_label (task_id, project_label_id, assigned_date)
|
|||||||
|
|
||||||
-- name: GetTaskLabelsForTaskID :many
|
-- name: GetTaskLabelsForTaskID :many
|
||||||
SELECT * FROM task_label WHERE task_id = $1;
|
SELECT * FROM task_label WHERE task_id = $1;
|
||||||
|
|
||||||
|
-- name: GetTaskLabelByID :one
|
||||||
|
SELECT * FROM task_label WHERE task_label_id = $1;
|
||||||
|
|
||||||
|
-- name: DeleteTaskLabelByID :exec
|
||||||
|
DELETE FROM task_label WHERE task_label_id = $1;
|
||||||
|
|
||||||
|
-- name: GetTaskLabelForTaskByProjectLabelID :one
|
||||||
|
SELECT * FROM task_label WHERE task_id = $1 AND project_label_id = $2;
|
||||||
|
|
||||||
|
-- name: DeleteTaskLabelForTaskByProjectLabelID :exec
|
||||||
|
DELETE FROM task_label WHERE project_label_id = $2 AND task_id = $1;
|
||||||
|
@ -8,8 +8,9 @@ import { useMeQuery } from 'shared/generated/graphql';
|
|||||||
type GlobalTopNavbarProps = {
|
type GlobalTopNavbarProps = {
|
||||||
name: string;
|
name: string;
|
||||||
projectMembers?: null | Array<TaskUser>;
|
projectMembers?: null | Array<TaskUser>;
|
||||||
|
onSaveProjectName?: (projectName: string) => void;
|
||||||
};
|
};
|
||||||
const GlobalTopNavbar: React.FC<GlobalTopNavbarProps> = ({ name, projectMembers }) => {
|
const GlobalTopNavbar: React.FC<GlobalTopNavbarProps> = ({ name, projectMembers, onSaveProjectName }) => {
|
||||||
const { loading, data } = useMeQuery();
|
const { loading, data } = useMeQuery();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const { userID, setUserID } = useContext(UserIDContext);
|
const { userID, setUserID } = useContext(UserIDContext);
|
||||||
@ -52,6 +53,7 @@ const GlobalTopNavbar: React.FC<GlobalTopNavbarProps> = ({ name, projectMembers
|
|||||||
onNotificationClick={() => {}}
|
onNotificationClick={() => {}}
|
||||||
projectMembers={projectMembers}
|
projectMembers={projectMembers}
|
||||||
onProfileClick={onProfileClick}
|
onProfileClick={onProfileClick}
|
||||||
|
onSaveProjectName={onSaveProjectName}
|
||||||
/>
|
/>
|
||||||
{menu.isOpen && (
|
{menu.isOpen && (
|
||||||
<DropdownMenu
|
<DropdownMenu
|
||||||
|
@ -56,17 +56,6 @@ const Details: React.FC<DetailsProps> = ({
|
|||||||
if (!data) {
|
if (!data) {
|
||||||
return <div>loading</div>;
|
return <div>loading</div>;
|
||||||
}
|
}
|
||||||
const taskMembers = data.findTask.assigned.map(assigned => {
|
|
||||||
return {
|
|
||||||
userID: assigned.id,
|
|
||||||
displayName: `${assigned.firstName} ${assigned.lastName}`,
|
|
||||||
profileIcon: {
|
|
||||||
url: null,
|
|
||||||
initials: assigned.profileIcon.initials ?? null,
|
|
||||||
bgColor: assigned.profileIcon.bgColor ?? null,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
});
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Modal
|
<Modal
|
||||||
@ -77,24 +66,19 @@ const Details: React.FC<DetailsProps> = ({
|
|||||||
renderContent={() => {
|
renderContent={() => {
|
||||||
return (
|
return (
|
||||||
<TaskDetails
|
<TaskDetails
|
||||||
task={{
|
task={data.findTask}
|
||||||
...data.findTask,
|
|
||||||
taskID: data.findTask.id,
|
|
||||||
taskGroup: { taskGroupID: data.findTask.taskGroup.id },
|
|
||||||
members: taskMembers,
|
|
||||||
description: data.findTask.description ?? '',
|
|
||||||
labels: [],
|
|
||||||
}}
|
|
||||||
onTaskNameChange={onTaskNameChange}
|
onTaskNameChange={onTaskNameChange}
|
||||||
onTaskDescriptionChange={onTaskDescriptionChange}
|
onTaskDescriptionChange={onTaskDescriptionChange}
|
||||||
onDeleteTask={onDeleteTask}
|
onDeleteTask={onDeleteTask}
|
||||||
onCloseModal={() => history.push(projectURL)}
|
onCloseModal={() => history.push(projectURL)}
|
||||||
onMemberProfile={($targetRef, memberID) => {
|
onMemberProfile={($targetRef, memberID) => {
|
||||||
|
const member = data.findTask.assigned.find(m => m.id === memberID);
|
||||||
|
const profileIcon = member ? member.profileIcon : null;
|
||||||
showPopup(
|
showPopup(
|
||||||
$targetRef,
|
$targetRef,
|
||||||
<Popup title={null} onClose={() => {}} tab={0}>
|
<Popup title={null} onClose={() => {}} tab={0}>
|
||||||
<MiniProfile
|
<MiniProfile
|
||||||
profileIcon={taskMembers[0].profileIcon}
|
profileIcon={profileIcon}
|
||||||
displayName="Jordan Knott"
|
displayName="Jordan Knott"
|
||||||
username="@jordanthedev"
|
username="@jordanthedev"
|
||||||
bio="None"
|
bio="None"
|
||||||
@ -111,7 +95,7 @@ const Details: React.FC<DetailsProps> = ({
|
|||||||
<Popup title="Members" tab={0} onClose={() => {}}>
|
<Popup title="Members" tab={0} onClose={() => {}}>
|
||||||
<MemberManager
|
<MemberManager
|
||||||
availableMembers={availableMembers}
|
availableMembers={availableMembers}
|
||||||
activeMembers={taskMembers}
|
activeMembers={data.findTask.assigned}
|
||||||
onMemberChange={(member, isActive) => {
|
onMemberChange={(member, isActive) => {
|
||||||
if (isActive) {
|
if (isActive) {
|
||||||
assignTask({ variables: { taskID: data.findTask.id, userID: userID ?? '' } });
|
assignTask({ variables: { taskID: data.findTask.id, userID: userID ?? '' } });
|
||||||
|
@ -5,7 +5,6 @@ import Lists from 'shared/components/Lists';
|
|||||||
import { Board } from './Styles';
|
import { Board } from './Styles';
|
||||||
|
|
||||||
type KanbanBoardProps = {
|
type KanbanBoardProps = {
|
||||||
listsData: BoardState;
|
|
||||||
onOpenListActionsPopup: ($targetRef: React.RefObject<HTMLElement>, taskGroupID: string) => void;
|
onOpenListActionsPopup: ($targetRef: React.RefObject<HTMLElement>, taskGroupID: string) => void;
|
||||||
onCardDrop: (task: Task) => void;
|
onCardDrop: (task: Task) => void;
|
||||||
onListDrop: (taskGroup: TaskGroup) => void;
|
onListDrop: (taskGroup: TaskGroup) => void;
|
||||||
@ -16,7 +15,6 @@ type KanbanBoardProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const KanbanBoard: React.FC<KanbanBoardProps> = ({
|
const KanbanBoard: React.FC<KanbanBoardProps> = ({
|
||||||
listsData,
|
|
||||||
onOpenListActionsPopup,
|
onOpenListActionsPopup,
|
||||||
onQuickEditorOpen,
|
onQuickEditorOpen,
|
||||||
onCardCreate,
|
onCardCreate,
|
||||||
@ -27,25 +25,7 @@ const KanbanBoard: React.FC<KanbanBoardProps> = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const match = useRouteMatch();
|
const match = useRouteMatch();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
return (
|
return <Board></Board>;
|
||||||
<Board>
|
|
||||||
<Lists
|
|
||||||
onCardClick={task => {
|
|
||||||
history.push(`${match.url}/c/${task.taskID}`);
|
|
||||||
}}
|
|
||||||
onExtraMenuOpen={(taskGroupID, $targetRef) => {
|
|
||||||
onOpenListActionsPopup($targetRef, taskGroupID);
|
|
||||||
}}
|
|
||||||
onQuickEditorOpen={onQuickEditorOpen}
|
|
||||||
onCardCreate={onCardCreate}
|
|
||||||
onCardDrop={onCardDrop}
|
|
||||||
onListDrop={onListDrop}
|
|
||||||
{...listsData}
|
|
||||||
onCreateList={onCreateList}
|
|
||||||
onCardMemberClick={onCardMemberClick}
|
|
||||||
/>
|
|
||||||
</Board>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default KanbanBoard;
|
export default KanbanBoard;
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import React, { useState, useRef } from 'react';
|
import React, { useState, useRef } from 'react';
|
||||||
import * as BoardStateUtils from 'shared/utils/boardState';
|
|
||||||
import GlobalTopNavbar from 'App/TopNavbar';
|
import GlobalTopNavbar from 'App/TopNavbar';
|
||||||
import styled from 'styled-components/macro';
|
import styled from 'styled-components/macro';
|
||||||
import { Bolt, ToggleOn, Tags } from 'shared/icons';
|
import { Bolt, ToggleOn, Tags } from 'shared/icons';
|
||||||
import { usePopup, Popup } from 'shared/components/PopupMenu';
|
import { usePopup, Popup } from 'shared/components/PopupMenu';
|
||||||
import { useParams, Route, useRouteMatch, useHistory, RouteComponentProps } from 'react-router-dom';
|
import { useParams, Route, useRouteMatch, useHistory, RouteComponentProps } from 'react-router-dom';
|
||||||
import {
|
import {
|
||||||
|
useToggleTaskLabelMutation,
|
||||||
|
useUpdateProjectNameMutation,
|
||||||
useFindProjectQuery,
|
useFindProjectQuery,
|
||||||
useUpdateTaskNameMutation,
|
useUpdateTaskNameMutation,
|
||||||
useUpdateProjectLabelMutation,
|
useUpdateProjectLabelMutation,
|
||||||
@ -29,12 +30,14 @@ import ListActions from 'shared/components/ListActions';
|
|||||||
import MemberManager from 'shared/components/MemberManager';
|
import MemberManager from 'shared/components/MemberManager';
|
||||||
import { LabelsPopup } from 'shared/components/PopupMenu/PopupMenu.stories';
|
import { LabelsPopup } from 'shared/components/PopupMenu/PopupMenu.stories';
|
||||||
import KanbanBoard from 'Projects/Project/KanbanBoard';
|
import KanbanBoard from 'Projects/Project/KanbanBoard';
|
||||||
|
import SimpleLists from 'shared/components/Lists';
|
||||||
import { mixin } from 'shared/utils/styles';
|
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 MiniProfile from 'shared/components/MiniProfile';
|
import MiniProfile from 'shared/components/MiniProfile';
|
||||||
import Details from './Details';
|
import Details from './Details';
|
||||||
|
import { useApolloClient } from '@apollo/react-hooks';
|
||||||
|
|
||||||
const getCacheData = (client: any, projectID: string) => {
|
const getCacheData = (client: any, projectID: string) => {
|
||||||
const cacheData: any = client.readQuery({
|
const cacheData: any = client.readQuery({
|
||||||
@ -85,12 +88,20 @@ const ProjectMembers = styled.div`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
type LabelManagerEditorProps = {
|
type LabelManagerEditorProps = {
|
||||||
labels: React.RefObject<Array<Label>>;
|
labels: React.RefObject<Array<ProjectLabel>>;
|
||||||
|
taskLabels: null | React.RefObject<Array<TaskLabel>>;
|
||||||
projectID: string;
|
projectID: string;
|
||||||
labelColors: Array<LabelColor>;
|
labelColors: Array<LabelColor>;
|
||||||
|
onLabelToggle?: (labelId: string) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const LabelManagerEditor: React.FC<LabelManagerEditorProps> = ({ labels: labelsRef, projectID, labelColors }) => {
|
const LabelManagerEditor: React.FC<LabelManagerEditorProps> = ({
|
||||||
|
labels: labelsRef,
|
||||||
|
projectID,
|
||||||
|
labelColors,
|
||||||
|
onLabelToggle,
|
||||||
|
taskLabels: taskLabelsRef,
|
||||||
|
}) => {
|
||||||
const [currentLabel, setCurrentLabel] = useState('');
|
const [currentLabel, setCurrentLabel] = useState('');
|
||||||
const [createProjectLabel] = useCreateProjectLabelMutation({
|
const [createProjectLabel] = useCreateProjectLabelMutation({
|
||||||
update: (client, newLabelData) => {
|
update: (client, newLabelData) => {
|
||||||
@ -116,12 +127,16 @@ const LabelManagerEditor: React.FC<LabelManagerEditorProps> = ({ labels: labelsR
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
const labels = labelsRef.current ? labelsRef.current : [];
|
const labels = labelsRef.current ? labelsRef.current : [];
|
||||||
|
const taskLabels = taskLabelsRef && taskLabelsRef.current ? taskLabelsRef.current : [];
|
||||||
|
const [currentTaskLabels, setCurrentTaskLabels] = useState(taskLabels);
|
||||||
|
console.log(taskLabels);
|
||||||
const { setTab } = usePopup();
|
const { setTab } = usePopup();
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Popup title="Labels" tab={0} onClose={() => {}}>
|
<Popup title="Labels" tab={0} onClose={() => {}}>
|
||||||
<LabelManager
|
<LabelManager
|
||||||
labels={labels}
|
labels={labels}
|
||||||
|
taskLabels={currentTaskLabels}
|
||||||
onLabelCreate={() => {
|
onLabelCreate={() => {
|
||||||
setTab(2);
|
setTab(2);
|
||||||
}}
|
}}
|
||||||
@ -130,18 +145,34 @@ const LabelManagerEditor: React.FC<LabelManagerEditorProps> = ({ labels: labelsR
|
|||||||
setTab(1);
|
setTab(1);
|
||||||
}}
|
}}
|
||||||
onLabelToggle={labelId => {
|
onLabelToggle={labelId => {
|
||||||
|
if (onLabelToggle) {
|
||||||
|
if (currentTaskLabels.find(t => t.projectLabel.id === labelId)) {
|
||||||
|
setCurrentTaskLabels(currentTaskLabels.filter(t => t.projectLabel.id !== labelId));
|
||||||
|
} else {
|
||||||
|
const newProjectLabel = labels.find(l => l.id === labelId);
|
||||||
|
if (newProjectLabel) {
|
||||||
|
setCurrentTaskLabels([
|
||||||
|
...currentTaskLabels,
|
||||||
|
{ id: '', assignedDate: '', projectLabel: { ...newProjectLabel } },
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setCurrentLabel(labelId);
|
||||||
|
onLabelToggle(labelId);
|
||||||
|
} else {
|
||||||
setCurrentLabel(labelId);
|
setCurrentLabel(labelId);
|
||||||
setTab(1);
|
setTab(1);
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Popup>
|
</Popup>
|
||||||
<Popup onClose={() => {}} title="Edit label" tab={1}>
|
<Popup onClose={() => {}} title="Edit label" tab={1}>
|
||||||
<LabelEditor
|
<LabelEditor
|
||||||
labelColors={labelColors}
|
labelColors={labelColors}
|
||||||
label={labels.find(label => label.labelId === currentLabel) ?? null}
|
label={labels.find(label => label.id === currentLabel) ?? null}
|
||||||
onLabelEdit={(projectLabelID, name, color) => {
|
onLabelEdit={(projectLabelID, name, color) => {
|
||||||
if (projectLabelID) {
|
if (projectLabelID) {
|
||||||
updateProjectLabel({ variables: { projectLabelID, labelColorID: color.id, name } });
|
updateProjectLabel({ variables: { projectLabelID, labelColorID: color.id, name: name ?? '' } });
|
||||||
}
|
}
|
||||||
setTab(0);
|
setTab(0);
|
||||||
}}
|
}}
|
||||||
@ -156,7 +187,7 @@ const LabelManagerEditor: React.FC<LabelManagerEditorProps> = ({ labels: labelsR
|
|||||||
labelColors={labelColors}
|
labelColors={labelColors}
|
||||||
label={null}
|
label={null}
|
||||||
onLabelEdit={(_labelId, name, color) => {
|
onLabelEdit={(_labelId, name, color) => {
|
||||||
createProjectLabel({ variables: { projectID, labelColorID: color.id, name } });
|
createProjectLabel({ variables: { projectID, labelColorID: color.id, name: name ?? '' } });
|
||||||
setTab(0);
|
setTab(0);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@ -169,10 +200,7 @@ interface ProjectParams {
|
|||||||
projectID: string;
|
projectID: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialState: BoardState = { tasks: {}, columns: {} };
|
|
||||||
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 initialTaskDetailsState = { isOpen: false, taskID: '' };
|
|
||||||
|
|
||||||
const ProjectBar = styled.div`
|
const ProjectBar = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -209,18 +237,16 @@ const ProjectActionText = styled.span`
|
|||||||
|
|
||||||
const Project = () => {
|
const Project = () => {
|
||||||
const { projectID } = useParams<ProjectParams>();
|
const { projectID } = useParams<ProjectParams>();
|
||||||
|
const history = useHistory();
|
||||||
const match = useRouteMatch();
|
const match = useRouteMatch();
|
||||||
|
|
||||||
const [updateTaskDescription] = useUpdateTaskDescriptionMutation();
|
const [updateTaskDescription] = useUpdateTaskDescriptionMutation();
|
||||||
const [listsData, setListsData] = useState(initialState);
|
|
||||||
const [quickCardEditor, setQuickCardEditor] = useState(initialQuickCardEditorState);
|
const [quickCardEditor, setQuickCardEditor] = useState(initialQuickCardEditorState);
|
||||||
const [updateTaskLocation] = useUpdateTaskLocationMutation();
|
const [updateTaskLocation] = useUpdateTaskLocationMutation();
|
||||||
const [updateTaskGroupLocation] = useUpdateTaskGroupLocationMutation();
|
const [updateTaskGroupLocation] = useUpdateTaskGroupLocationMutation({});
|
||||||
|
|
||||||
const [deleteTaskGroup] = useDeleteTaskGroupMutation({
|
const [deleteTaskGroup] = useDeleteTaskGroupMutation({
|
||||||
onCompleted: deletedTaskGroupData => {
|
onCompleted: deletedTaskGroupData => {},
|
||||||
setListsData(BoardStateUtils.deleteTaskGroup(listsData, deletedTaskGroupData.deleteTaskGroup.taskGroup.id));
|
|
||||||
},
|
|
||||||
update: (client, deletedTaskGroupData) => {
|
update: (client, deletedTaskGroupData) => {
|
||||||
const cacheData = getCacheData(client, projectID);
|
const cacheData = getCacheData(client, projectID);
|
||||||
const newData = {
|
const newData = {
|
||||||
@ -235,14 +261,7 @@ const Project = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const [createTaskGroup] = useCreateTaskGroupMutation({
|
const [createTaskGroup] = useCreateTaskGroupMutation({
|
||||||
onCompleted: newTaskGroupData => {
|
onCompleted: newTaskGroupData => {},
|
||||||
const newTaskGroup = {
|
|
||||||
taskGroupID: newTaskGroupData.createTaskGroup.id,
|
|
||||||
tasks: [],
|
|
||||||
...newTaskGroupData.createTaskGroup,
|
|
||||||
};
|
|
||||||
setListsData(BoardStateUtils.addTaskGroup(listsData, newTaskGroup));
|
|
||||||
},
|
|
||||||
update: (client, newTaskGroupData) => {
|
update: (client, newTaskGroupData) => {
|
||||||
const cacheData = getCacheData(client, projectID);
|
const cacheData = getCacheData(client, projectID);
|
||||||
const newData = {
|
const newData = {
|
||||||
@ -255,15 +274,7 @@ const Project = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const [createTask] = useCreateTaskMutation({
|
const [createTask] = useCreateTaskMutation({
|
||||||
onCompleted: newTaskData => {
|
onCompleted: newTaskData => {},
|
||||||
const newTask = {
|
|
||||||
...newTaskData.createTask,
|
|
||||||
taskID: newTaskData.createTask.id,
|
|
||||||
taskGroup: { taskGroupID: newTaskData.createTask.taskGroup.id },
|
|
||||||
labels: [],
|
|
||||||
};
|
|
||||||
setListsData(BoardStateUtils.addTask(listsData, newTask));
|
|
||||||
},
|
|
||||||
update: (client, newTaskData) => {
|
update: (client, newTaskData) => {
|
||||||
const cacheData = getCacheData(client, projectID);
|
const cacheData = getCacheData(client, projectID);
|
||||||
const newTaskGroups = produce(cacheData.findProject.taskGroups, (draftState: any) => {
|
const newTaskGroups = produce(cacheData.findProject.taskGroups, (draftState: any) => {
|
||||||
@ -284,26 +295,27 @@ const Project = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const [deleteTask] = useDeleteTaskMutation({
|
const [deleteTask] = useDeleteTaskMutation({
|
||||||
onCompleted: deletedTask => {
|
onCompleted: deletedTask => {},
|
||||||
setListsData(BoardStateUtils.deleteTask(listsData, deletedTask.deleteTask.taskID));
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const [updateTaskName] = useUpdateTaskNameMutation({
|
const [updateTaskName] = useUpdateTaskNameMutation({
|
||||||
onCompleted: newTaskData => {
|
onCompleted: newTaskData => {},
|
||||||
setListsData(
|
});
|
||||||
BoardStateUtils.updateTaskName(listsData, newTaskData.updateTaskName.id, newTaskData.updateTaskName.name),
|
const [toggleTaskLabel] = useToggleTaskLabelMutation({
|
||||||
);
|
onCompleted: newTaskLabel => {
|
||||||
|
taskLabelsRef.current = newTaskLabel.toggleTaskLabel.task.labels;
|
||||||
|
console.log(taskLabelsRef.current);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const { loading, data, refetch } = useFindProjectQuery({
|
const { loading, data, refetch } = useFindProjectQuery({
|
||||||
variables: { projectId: projectID },
|
variables: { projectId: projectID },
|
||||||
|
onCompleted: newData => {},
|
||||||
});
|
});
|
||||||
|
|
||||||
const onCardCreate = (taskGroupID: string, name: string) => {
|
const onCardCreate = (taskGroupID: string, name: string) => {
|
||||||
const taskGroupTasks = Object.values(listsData.tasks).filter(
|
if (data) {
|
||||||
(task: Task) => task.taskGroup.taskGroupID === taskGroupID,
|
const taskGroupTasks = data.findProject.taskGroups.filter(t => t.id === taskGroupID);
|
||||||
);
|
if (taskGroupTasks) {
|
||||||
let position = 65535;
|
let position = 65535;
|
||||||
if (taskGroupTasks.length !== 0) {
|
if (taskGroupTasks.length !== 0) {
|
||||||
const [lastTask] = taskGroupTasks.sort((a: any, b: any) => a.position - b.position).slice(-1);
|
const [lastTask] = taskGroupTasks.sort((a: any, b: any) => a.position - b.position).slice(-1);
|
||||||
@ -311,131 +323,116 @@ const Project = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
createTask({ variables: { taskGroupID, name, position } });
|
createTask({ variables: { taskGroupID, name, position } });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onCreateTask = (taskGroupID: string, name: string) => {
|
||||||
|
if (data) {
|
||||||
|
const taskGroup = data.findProject.taskGroups.find(t => t.id === taskGroupID);
|
||||||
|
console.log(`taskGroup ${taskGroup}`);
|
||||||
|
if (taskGroup) {
|
||||||
|
let position = 65535;
|
||||||
|
if (taskGroup.tasks.length !== 0) {
|
||||||
|
const [lastTask] = taskGroup.tasks.sort((a: any, b: any) => a.position - b.position).slice(-1);
|
||||||
|
position = Math.ceil(lastTask.position) * 2 + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`position ${position}`);
|
||||||
|
createTask({ variables: { taskGroupID, name, position } });
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onCardDrop = (droppedTask: Task) => {
|
const onCardDrop = (droppedTask: Task) => {
|
||||||
updateTaskLocation({
|
updateTaskLocation({
|
||||||
variables: {
|
variables: {
|
||||||
taskID: droppedTask.taskID,
|
taskID: droppedTask.id,
|
||||||
taskGroupID: droppedTask.taskGroup.taskGroupID,
|
taskGroupID: droppedTask.taskGroup.id,
|
||||||
position: droppedTask.position,
|
position: droppedTask.position,
|
||||||
},
|
},
|
||||||
optimisticResponse: {
|
optimisticResponse: {
|
||||||
updateTaskLocation: {
|
updateTaskLocation: {
|
||||||
name: droppedTask.name,
|
name: droppedTask.name,
|
||||||
id: droppedTask.taskID,
|
id: droppedTask.id,
|
||||||
position: droppedTask.position,
|
position: droppedTask.position,
|
||||||
createdAt: '',
|
createdAt: '',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
setListsData(BoardStateUtils.updateTask(listsData, droppedTask));
|
|
||||||
};
|
};
|
||||||
const onListDrop = (droppedColumn: TaskGroup) => {
|
const onListDrop = (droppedColumn: TaskGroup) => {
|
||||||
console.log(`list drop ${droppedColumn.taskGroupID}`);
|
console.log(`list drop ${droppedColumn.id}`);
|
||||||
|
const cacheData = getCacheData(client, projectID);
|
||||||
|
const newData = produce(cacheData, (draftState: any) => {
|
||||||
|
const taskGroupIdx = cacheData.findProject.taskGroups.findIndex((t: any) => t.id === droppedColumn.id);
|
||||||
|
cacheData.findProject.taskGroups[taskGroupIdx].position = droppedColumn.position;
|
||||||
|
});
|
||||||
|
writeCacheData(client, projectID, cacheData, newData);
|
||||||
updateTaskGroupLocation({
|
updateTaskGroupLocation({
|
||||||
variables: { taskGroupID: droppedColumn.taskGroupID, position: droppedColumn.position },
|
variables: { taskGroupID: droppedColumn.id, position: droppedColumn.position },
|
||||||
optimisticResponse: {
|
optimisticResponse: {
|
||||||
updateTaskGroupLocation: {
|
updateTaskGroupLocation: {
|
||||||
id: droppedColumn.taskGroupID,
|
id: droppedColumn.id,
|
||||||
position: droppedColumn.position,
|
position: droppedColumn.position,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
// setListsData(BoardStateUtils.updateTaskGroup(listsData, droppedColumn));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const onCreateList = (listName: string) => {
|
const onCreateList = (listName: string) => {
|
||||||
const [lastColumn] = Object.values(listsData.columns)
|
if (data) {
|
||||||
.sort((a, b) => a.position - b.position)
|
const [lastColumn] = data.findProject.taskGroups.sort((a, b) => a.position - b.position).slice(-1);
|
||||||
.slice(-1);
|
|
||||||
let position = 65535;
|
let position = 65535;
|
||||||
if (lastColumn) {
|
if (lastColumn) {
|
||||||
position = lastColumn.position * 2 + 1;
|
position = lastColumn.position * 2 + 1;
|
||||||
}
|
}
|
||||||
createTaskGroup({ variables: { projectID, name: listName, position } });
|
createTaskGroup({ variables: { projectID, name: listName, position } });
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const [assignTask] = useAssignTaskMutation();
|
const [assignTask] = useAssignTaskMutation();
|
||||||
|
|
||||||
|
const [updateProjectName] = useUpdateProjectNameMutation();
|
||||||
|
|
||||||
|
const client = useApolloClient();
|
||||||
|
|
||||||
const { showPopup, hidePopup } = usePopup();
|
const { showPopup, hidePopup } = usePopup();
|
||||||
const $labelsRef = useRef<HTMLDivElement>(null);
|
const $labelsRef = useRef<HTMLDivElement>(null);
|
||||||
const labelsRef = useRef<Array<Label>>([]);
|
const labelsRef = useRef<Array<ProjectLabel>>([]);
|
||||||
|
const taskLabelsRef = useRef<Array<TaskLabel>>([]);
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<GlobalTopNavbar name="Project" />
|
<GlobalTopNavbar onSaveProjectName={projectName => {}} name="Loading..." />
|
||||||
<Title>Error Loading</Title>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (data) {
|
if (data) {
|
||||||
console.log(data);
|
|
||||||
const currentListsData: BoardState = { tasks: {}, columns: {} };
|
|
||||||
data.findProject.taskGroups.forEach(taskGroup => {
|
|
||||||
currentListsData.columns[taskGroup.id] = {
|
|
||||||
taskGroupID: taskGroup.id,
|
|
||||||
name: taskGroup.name,
|
|
||||||
position: taskGroup.position,
|
|
||||||
tasks: [],
|
|
||||||
};
|
|
||||||
taskGroup.tasks.forEach(task => {
|
|
||||||
const taskMembers = task.assigned.map(assigned => {
|
|
||||||
return {
|
|
||||||
userID: assigned.id,
|
|
||||||
displayName: `${assigned.firstName} ${assigned.lastName}`,
|
|
||||||
profileIcon: {
|
|
||||||
url: null,
|
|
||||||
initials: assigned.profileIcon.initials ?? '',
|
|
||||||
bgColor: assigned.profileIcon.bgColor ?? '#7367F0',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
});
|
|
||||||
currentListsData.tasks[task.id] = {
|
|
||||||
taskID: task.id,
|
|
||||||
taskGroup: {
|
|
||||||
taskGroupID: taskGroup.id,
|
|
||||||
},
|
|
||||||
name: task.name,
|
|
||||||
labels: [],
|
|
||||||
position: task.position,
|
|
||||||
description: task.description ?? undefined,
|
|
||||||
members: taskMembers,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
});
|
|
||||||
const availableMembers = data.findProject.members.map(member => {
|
|
||||||
return {
|
|
||||||
displayName: `${member.firstName} ${member.lastName}`,
|
|
||||||
profileIcon: {
|
|
||||||
url: null,
|
|
||||||
initials: member.profileIcon.initials ?? null,
|
|
||||||
bgColor: member.profileIcon.bgColor ?? null,
|
|
||||||
},
|
|
||||||
userID: member.id,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
const onQuickEditorOpen = (e: ContextMenuEvent) => {
|
const onQuickEditorOpen = (e: ContextMenuEvent) => {
|
||||||
const currentTask = Object.values(currentListsData.tasks).find(task => task.taskID === e.taskID);
|
const taskGroup = data.findProject.taskGroups.find(t => t.id === e.taskGroupID);
|
||||||
|
const currentTask = taskGroup ? taskGroup.tasks.find(t => t.id === e.taskID) : null;
|
||||||
|
if (currentTask) {
|
||||||
setQuickCardEditor({
|
setQuickCardEditor({
|
||||||
top: e.top,
|
top: e.top,
|
||||||
left: e.left,
|
left: e.left,
|
||||||
isOpen: true,
|
isOpen: true,
|
||||||
task: currentTask,
|
task: currentTask,
|
||||||
});
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
labelsRef.current = data.findProject.labels.map(label => {
|
labelsRef.current = data.findProject.labels;
|
||||||
return {
|
|
||||||
labelId: label.id,
|
|
||||||
name: label.name ?? '',
|
|
||||||
labelColor: label.labelColor,
|
|
||||||
active: false,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<GlobalTopNavbar projectMembers={availableMembers} name={data.findProject.name} />
|
<GlobalTopNavbar
|
||||||
|
onSaveProjectName={projectName => {
|
||||||
|
updateProjectName({ variables: { projectID, name: projectName } });
|
||||||
|
}}
|
||||||
|
projectMembers={data.findProject.members}
|
||||||
|
name={data.findProject.name}
|
||||||
|
/>
|
||||||
<ProjectBar>
|
<ProjectBar>
|
||||||
<ProjectActions>
|
<ProjectActions>
|
||||||
<ProjectAction
|
<ProjectAction
|
||||||
@ -443,7 +440,12 @@ const Project = () => {
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
showPopup(
|
showPopup(
|
||||||
$labelsRef,
|
$labelsRef,
|
||||||
<LabelManagerEditor labelColors={data.labelColors} labels={labelsRef} projectID={projectID} />,
|
<LabelManagerEditor
|
||||||
|
taskLabels={null}
|
||||||
|
labelColors={data.labelColors}
|
||||||
|
labels={labelsRef}
|
||||||
|
projectID={projectID}
|
||||||
|
/>,
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@ -460,18 +462,53 @@ const Project = () => {
|
|||||||
</ProjectAction>
|
</ProjectAction>
|
||||||
</ProjectActions>
|
</ProjectActions>
|
||||||
</ProjectBar>
|
</ProjectBar>
|
||||||
<KanbanBoard
|
<SimpleLists
|
||||||
listsData={currentListsData}
|
onTaskClick={task => {
|
||||||
onCardDrop={onCardDrop}
|
history.push(`${match.url}/c/${task.id}`);
|
||||||
onListDrop={onListDrop}
|
}}
|
||||||
onCardCreate={onCardCreate}
|
onTaskDrop={droppedTask => {
|
||||||
onCreateList={onCreateList}
|
updateTaskLocation({
|
||||||
|
variables: {
|
||||||
|
taskID: droppedTask.id,
|
||||||
|
taskGroupID: droppedTask.taskGroup.id,
|
||||||
|
position: droppedTask.position,
|
||||||
|
},
|
||||||
|
optimisticResponse: {
|
||||||
|
__typename: 'Mutation',
|
||||||
|
updateTaskLocation: {
|
||||||
|
name: droppedTask.name,
|
||||||
|
id: droppedTask.id,
|
||||||
|
position: droppedTask.position,
|
||||||
|
createdAt: '',
|
||||||
|
__typename: 'Task',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
onTaskGroupDrop={droppedTaskGroup => {
|
||||||
|
updateTaskGroupLocation({
|
||||||
|
variables: { taskGroupID: droppedTaskGroup.id, position: droppedTaskGroup.position },
|
||||||
|
optimisticResponse: {
|
||||||
|
__typename: 'Mutation',
|
||||||
|
updateTaskGroupLocation: {
|
||||||
|
id: droppedTaskGroup.id,
|
||||||
|
position: droppedTaskGroup.position,
|
||||||
|
__typename: 'TaskGroup',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
taskGroups={data.findProject.taskGroups}
|
||||||
|
onCreateTask={onCreateTask}
|
||||||
|
onCreateTaskGroup={onCreateList}
|
||||||
onCardMemberClick={($targetRef, taskID, memberID) => {
|
onCardMemberClick={($targetRef, taskID, memberID) => {
|
||||||
|
const member = data.findProject.members.find(m => m.id === memberID);
|
||||||
|
const profileIcon = member ? member.profileIcon : null;
|
||||||
showPopup(
|
showPopup(
|
||||||
$targetRef,
|
$targetRef,
|
||||||
<Popup title={null} onClose={() => {}} tab={0}>
|
<Popup title={null} onClose={() => {}} tab={0}>
|
||||||
<MiniProfile
|
<MiniProfile
|
||||||
profileIcon={availableMembers[0].profileIcon}
|
profileIcon={profileIcon}
|
||||||
displayName="Jordan Knott"
|
displayName="Jordan Knott"
|
||||||
username="@jordanthedev"
|
username="@jordanthedev"
|
||||||
bio="None"
|
bio="None"
|
||||||
@ -483,7 +520,7 @@ const Project = () => {
|
|||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
onQuickEditorOpen={onQuickEditorOpen}
|
onQuickEditorOpen={onQuickEditorOpen}
|
||||||
onOpenListActionsPopup={($targetRef, taskGroupID) => {
|
onExtraMenuOpen={(taskGroupID: string, $targetRef: any) => {
|
||||||
showPopup(
|
showPopup(
|
||||||
$targetRef,
|
$targetRef,
|
||||||
<Popup title="List actions" tab={0} onClose={() => {}}>
|
<Popup title="List actions" tab={0} onClose={() => {}}>
|
||||||
@ -501,8 +538,8 @@ const Project = () => {
|
|||||||
{quickCardEditor.isOpen && (
|
{quickCardEditor.isOpen && (
|
||||||
<QuickCardEditor
|
<QuickCardEditor
|
||||||
isOpen
|
isOpen
|
||||||
taskID={quickCardEditor.task ? quickCardEditor.task.taskID : ''}
|
taskID={quickCardEditor.task ? quickCardEditor.task.id : ''}
|
||||||
taskGroupID={quickCardEditor.task ? quickCardEditor.task.taskGroup.taskGroupID : ''}
|
taskGroupID={quickCardEditor.task ? quickCardEditor.task.taskGroup.id : ''}
|
||||||
cardTitle={quickCardEditor.task ? quickCardEditor.task.name : ''}
|
cardTitle={quickCardEditor.task ? quickCardEditor.task.name : ''}
|
||||||
onCloseEditor={() => setQuickCardEditor(initialQuickCardEditorState)}
|
onCloseEditor={() => setQuickCardEditor(initialQuickCardEditorState)}
|
||||||
onEditCard={(_listId: string, cardId: string, cardName: string) => {
|
onEditCard={(_listId: string, cardId: string, cardName: string) => {
|
||||||
@ -537,19 +574,33 @@ const Project = () => {
|
|||||||
render={(routeProps: RouteComponentProps<TaskRouteProps>) => (
|
render={(routeProps: RouteComponentProps<TaskRouteProps>) => (
|
||||||
<Details
|
<Details
|
||||||
refreshCache={() => {}}
|
refreshCache={() => {}}
|
||||||
availableMembers={availableMembers}
|
availableMembers={data.findProject.members}
|
||||||
projectURL={match.url}
|
projectURL={match.url}
|
||||||
taskID={routeProps.match.params.taskID}
|
taskID={routeProps.match.params.taskID}
|
||||||
onTaskNameChange={(updatedTask, newName) => {
|
onTaskNameChange={(updatedTask, newName) => {
|
||||||
updateTaskName({ variables: { taskID: updatedTask.taskID, name: newName } });
|
updateTaskName({ variables: { taskID: updatedTask.id, name: newName } });
|
||||||
}}
|
}}
|
||||||
onTaskDescriptionChange={(updatedTask, newDescription) => {
|
onTaskDescriptionChange={(updatedTask, newDescription) => {
|
||||||
updateTaskDescription({ variables: { taskID: updatedTask.taskID, description: newDescription } });
|
updateTaskDescription({ variables: { taskID: updatedTask.id, description: newDescription } });
|
||||||
}}
|
}}
|
||||||
onDeleteTask={deletedTask => {
|
onDeleteTask={deletedTask => {
|
||||||
deleteTask({ variables: { taskID: deletedTask.taskID } });
|
deleteTask({ variables: { taskID: deletedTask.id } });
|
||||||
|
}}
|
||||||
|
onOpenAddLabelPopup={(task, $targetRef) => {
|
||||||
|
taskLabelsRef.current = task.labels;
|
||||||
|
showPopup(
|
||||||
|
$targetRef,
|
||||||
|
<LabelManagerEditor
|
||||||
|
onLabelToggle={labelID => {
|
||||||
|
toggleTaskLabel({ variables: { taskID: task.id, projectLabelID: labelID } });
|
||||||
|
}}
|
||||||
|
labelColors={data.labelColors}
|
||||||
|
labels={labelsRef}
|
||||||
|
taskLabels={taskLabelsRef}
|
||||||
|
projectID={projectID}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
onOpenAddLabelPopup={(task, $targetRef) => {}}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
@ -41,7 +41,7 @@ const Projects = () => {
|
|||||||
const { projects } = data;
|
const { projects } = data;
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<GlobalTopNavbar name="Projects" />
|
<GlobalTopNavbar onSaveProjectName={() => {}} name="Projects" />
|
||||||
<ProjectGrid>
|
<ProjectGrid>
|
||||||
{projects.map(project => (
|
{projects.map(project => (
|
||||||
<ProjectLink key={project.id} to={`/projects/${project.id}`}>
|
<ProjectLink key={project.id} to={`/projects/${project.id}`}>
|
||||||
|
79
web/src/citadel.d.ts
vendored
79
web/src/citadel.d.ts
vendored
@ -3,18 +3,6 @@ interface JWTToken {
|
|||||||
iat: string;
|
iat: string;
|
||||||
exp: string;
|
exp: string;
|
||||||
}
|
}
|
||||||
interface ColumnState {
|
|
||||||
[key: string]: TaskGroup;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface TaskState {
|
|
||||||
[key: string]: Task;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface BoardState {
|
|
||||||
columns: ColumnState;
|
|
||||||
tasks: TaskState;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface DraggableElement {
|
interface DraggableElement {
|
||||||
id: string;
|
id: string;
|
||||||
@ -28,66 +16,13 @@ type ContextMenuEvent = {
|
|||||||
taskGroupID: string;
|
taskGroupID: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
type InnerTaskGroup = {
|
|
||||||
taskGroupID: string;
|
|
||||||
name?: string;
|
|
||||||
position?: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
type ProfileIcon = {
|
|
||||||
url: string | null;
|
|
||||||
initials: string | null;
|
|
||||||
bgColor: string | null;
|
|
||||||
};
|
|
||||||
|
|
||||||
type TaskUser = {
|
type TaskUser = {
|
||||||
userID: string;
|
id: string;
|
||||||
displayName: string;
|
firstName: string;
|
||||||
|
lastName: string;
|
||||||
profileIcon: ProfileIcon;
|
profileIcon: ProfileIcon;
|
||||||
};
|
};
|
||||||
|
|
||||||
type Task = {
|
|
||||||
taskID: string;
|
|
||||||
taskGroup: InnerTaskGroup;
|
|
||||||
name: string;
|
|
||||||
position: number;
|
|
||||||
labels: Label[];
|
|
||||||
description?: string | null;
|
|
||||||
members?: Array<TaskUser>;
|
|
||||||
};
|
|
||||||
|
|
||||||
type TaskGroup = {
|
|
||||||
taskGroupID: string;
|
|
||||||
name: string;
|
|
||||||
position: number;
|
|
||||||
tasks: Task[];
|
|
||||||
};
|
|
||||||
|
|
||||||
type Project = {
|
|
||||||
projectID: string;
|
|
||||||
name: string;
|
|
||||||
color?: string;
|
|
||||||
teamTitle?: string;
|
|
||||||
taskGroups: TaskGroup[];
|
|
||||||
};
|
|
||||||
|
|
||||||
type Organization = {
|
|
||||||
name: string;
|
|
||||||
teams: Team[];
|
|
||||||
};
|
|
||||||
|
|
||||||
type Team = {
|
|
||||||
name: string;
|
|
||||||
projects: Project[];
|
|
||||||
};
|
|
||||||
|
|
||||||
type Label = {
|
|
||||||
labelId: string;
|
|
||||||
name: string;
|
|
||||||
labelColor: LabelColor;
|
|
||||||
active: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
type RefreshTokenResponse = {
|
type RefreshTokenResponse = {
|
||||||
accessToken: string;
|
accessToken: string;
|
||||||
};
|
};
|
||||||
@ -117,17 +52,9 @@ type ElementSize = {
|
|||||||
height: number;
|
height: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
type LabelColor = {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
colorHex: string;
|
|
||||||
position: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
type OnCardMemberClick = ($targetRef: RefObject<HTMLElement>, taskID: string, memberID: string) => void;
|
type OnCardMemberClick = ($targetRef: RefObject<HTMLElement>, taskID: string, memberID: string) => void;
|
||||||
|
|
||||||
type ElementBounds = {
|
type ElementBounds = {
|
||||||
size: ElementSize;
|
size: ElementSize;
|
||||||
position: ElementPosition;
|
position: ElementPosition;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
66
web/src/projects.d.ts
vendored
Normal file
66
web/src/projects.d.ts
vendored
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
type ProfileIcon = {
|
||||||
|
url?: string | null;
|
||||||
|
initials?: string | null;
|
||||||
|
bgColor?: string | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
type TaskGroup = {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
position: number;
|
||||||
|
tasks: Task[];
|
||||||
|
};
|
||||||
|
|
||||||
|
type LabelColor = {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
colorHex: string;
|
||||||
|
position: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
type InnerTaskGroup = {
|
||||||
|
id: string;
|
||||||
|
name?: string;
|
||||||
|
position?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
type TaskLabel = {
|
||||||
|
id: string;
|
||||||
|
assignedDate: string;
|
||||||
|
projectLabel: ProjectLabel;
|
||||||
|
};
|
||||||
|
|
||||||
|
type Task = {
|
||||||
|
id: string;
|
||||||
|
taskGroup: InnerTaskGroup;
|
||||||
|
name: string;
|
||||||
|
position: number;
|
||||||
|
labels: TaskLabel[];
|
||||||
|
description?: string | null;
|
||||||
|
assigned?: Array<TaskUser>;
|
||||||
|
};
|
||||||
|
|
||||||
|
type Project = {
|
||||||
|
projectID: string;
|
||||||
|
name: string;
|
||||||
|
color?: string;
|
||||||
|
teamTitle?: string;
|
||||||
|
taskGroups: TaskGroup[];
|
||||||
|
};
|
||||||
|
|
||||||
|
type Organization = {
|
||||||
|
name: string;
|
||||||
|
teams: Team[];
|
||||||
|
};
|
||||||
|
|
||||||
|
type Team = {
|
||||||
|
name: string;
|
||||||
|
projects: Project[];
|
||||||
|
};
|
||||||
|
|
||||||
|
type ProjectLabel = {
|
||||||
|
id: string;
|
||||||
|
createdDate: string;
|
||||||
|
name?: string | null;
|
||||||
|
labelColor: LabelColor;
|
||||||
|
};
|
@ -14,28 +14,17 @@ export default {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const labelData = [
|
const labelData: Array<ProjectLabel> = [
|
||||||
{
|
{
|
||||||
labelId: 'development',
|
id: 'development',
|
||||||
name: 'Development',
|
name: 'Development',
|
||||||
|
createdDate: new Date().toString(),
|
||||||
labelColor: {
|
labelColor: {
|
||||||
id: '1',
|
id: '1',
|
||||||
colorHex: LabelColors.BLUE,
|
colorHex: LabelColors.BLUE,
|
||||||
name: 'blue',
|
name: 'blue',
|
||||||
position: 1,
|
position: 1,
|
||||||
},
|
},
|
||||||
active: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
labelId: 'general',
|
|
||||||
name: 'General',
|
|
||||||
labelColor: {
|
|
||||||
id: '2',
|
|
||||||
colorHex: LabelColors.PINK,
|
|
||||||
name: 'pink',
|
|
||||||
position: 2,
|
|
||||||
},
|
|
||||||
active: false,
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -47,10 +47,10 @@ const Member: React.FC<MemberProps> = ({ onCardMemberClick, taskID, member }) =>
|
|||||||
onClick={e => {
|
onClick={e => {
|
||||||
if (onCardMemberClick) {
|
if (onCardMemberClick) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
onCardMemberClick($targetRef, taskID, member.userID);
|
onCardMemberClick($targetRef, taskID, member.id);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
key={member.userID}
|
key={member.id}
|
||||||
bgColor={member.profileIcon.bgColor ?? '#7367F0'}
|
bgColor={member.profileIcon.bgColor ?? '#7367F0'}
|
||||||
>
|
>
|
||||||
<CardMemberInitials>{member.profileIcon.initials}</CardMemberInitials>
|
<CardMemberInitials>{member.profileIcon.initials}</CardMemberInitials>
|
||||||
@ -68,7 +68,7 @@ type Props = {
|
|||||||
dueDate?: DueDate;
|
dueDate?: DueDate;
|
||||||
checklists?: Checklist;
|
checklists?: Checklist;
|
||||||
watched?: boolean;
|
watched?: boolean;
|
||||||
labels?: Label[];
|
labels?: Array<ProjectLabel>;
|
||||||
wrapperProps?: any;
|
wrapperProps?: any;
|
||||||
members?: Array<TaskUser> | null;
|
members?: Array<TaskUser> | null;
|
||||||
onCardMemberClick?: OnCardMemberClick;
|
onCardMemberClick?: OnCardMemberClick;
|
||||||
@ -136,7 +136,7 @@ const Card = React.forwardRef(
|
|||||||
<ListCardLabels>
|
<ListCardLabels>
|
||||||
{labels &&
|
{labels &&
|
||||||
labels.map(label => (
|
labels.map(label => (
|
||||||
<ListCardLabel color={label.labelColor.colorHex} key={label.name}>
|
<ListCardLabel color={label.labelColor.colorHex} key={label.id}>
|
||||||
{label.name}
|
{label.name}
|
||||||
</ListCardLabel>
|
</ListCardLabel>
|
||||||
))}
|
))}
|
||||||
@ -169,7 +169,7 @@ const Card = React.forwardRef(
|
|||||||
<CardMembers>
|
<CardMembers>
|
||||||
{members &&
|
{members &&
|
||||||
members.map(member => (
|
members.map(member => (
|
||||||
<Member key={member.userID} taskID={taskID} member={member} onCardMemberClick={onCardMemberClick} />
|
<Member key={member.id} taskID={taskID} member={member} onCardMemberClick={onCardMemberClick} />
|
||||||
))}
|
))}
|
||||||
</CardMembers>
|
</CardMembers>
|
||||||
</ListCardDetails>
|
</ListCardDetails>
|
||||||
|
@ -17,21 +17,35 @@ export const Default = () => {
|
|||||||
return (
|
return (
|
||||||
<DueDateManager
|
<DueDateManager
|
||||||
task={{
|
task={{
|
||||||
taskID: '1',
|
id: '1',
|
||||||
taskGroup: { name: 'General', taskGroupID: '1' },
|
taskGroup: { name: 'General', id: '1', position: 1 },
|
||||||
name: 'Hello, world',
|
name: 'Hello, world',
|
||||||
position: 1,
|
position: 1,
|
||||||
labels: [
|
labels: [
|
||||||
{
|
{
|
||||||
labelId: 'soft-skills',
|
id: 'soft-skills',
|
||||||
labelColor: { id: '1', colorHex: '#fff', name: 'white', position: 1 },
|
assignedDate: new Date().toString(),
|
||||||
active: true,
|
projectLabel: {
|
||||||
|
createdDate: new Date().toString(),
|
||||||
|
id: 'label-soft-skills',
|
||||||
name: 'Soft Skills',
|
name: 'Soft Skills',
|
||||||
|
labelColor: {
|
||||||
|
id: '1',
|
||||||
|
name: 'white',
|
||||||
|
colorHex: '#fff',
|
||||||
|
position: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
description: 'hello!',
|
description: 'hello!',
|
||||||
members: [
|
assigned: [
|
||||||
{ userID: '1', profileIcon: { url: null, initials: null, bgColor: null }, displayName: 'Jordan Knott' },
|
{
|
||||||
|
id: '1',
|
||||||
|
profileIcon: { url: null, initials: null, bgColor: null },
|
||||||
|
firstName: 'Jordan',
|
||||||
|
lastName: 'Knott',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}}
|
}}
|
||||||
onCancel={action('cancel')}
|
onCancel={action('cancel')}
|
||||||
|
@ -16,28 +16,17 @@ export default {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const labelData = [
|
const labelData: Array<ProjectLabel> = [
|
||||||
{
|
{
|
||||||
labelId: 'development',
|
id: 'development',
|
||||||
name: 'Development',
|
name: 'Development',
|
||||||
|
createdDate: new Date().toString(),
|
||||||
labelColor: {
|
labelColor: {
|
||||||
id: '1',
|
id: '1',
|
||||||
colorHex: LabelColors.BLUE,
|
colorHex: LabelColors.BLUE,
|
||||||
name: 'blue',
|
name: 'blue',
|
||||||
position: 1,
|
position: 1,
|
||||||
},
|
},
|
||||||
active: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
labelId: 'general',
|
|
||||||
name: 'General',
|
|
||||||
labelColor: {
|
|
||||||
id: '2',
|
|
||||||
colorHex: LabelColors.PINK,
|
|
||||||
name: 'pink',
|
|
||||||
position: 2,
|
|
||||||
},
|
|
||||||
active: false,
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -68,7 +57,6 @@ export const Default = () => {
|
|||||||
isComposerOpen={false}
|
isComposerOpen={false}
|
||||||
onSaveName={action('on save name')}
|
onSaveName={action('on save name')}
|
||||||
onOpenComposer={action('on open composer')}
|
onOpenComposer={action('on open composer')}
|
||||||
tasks={[]}
|
|
||||||
onExtraMenuOpen={action('extra menu open')}
|
onExtraMenuOpen={action('extra menu open')}
|
||||||
>
|
>
|
||||||
<ListCards>
|
<ListCards>
|
||||||
@ -94,7 +82,6 @@ export const WithCardComposer = () => {
|
|||||||
isComposerOpen
|
isComposerOpen
|
||||||
onSaveName={action('on save name')}
|
onSaveName={action('on save name')}
|
||||||
onOpenComposer={action('on open composer')}
|
onOpenComposer={action('on open composer')}
|
||||||
tasks={[]}
|
|
||||||
onExtraMenuOpen={action('extra menu open')}
|
onExtraMenuOpen={action('extra menu open')}
|
||||||
>
|
>
|
||||||
<ListCards>
|
<ListCards>
|
||||||
@ -121,7 +108,6 @@ export const WithCard = () => {
|
|||||||
isComposerOpen={false}
|
isComposerOpen={false}
|
||||||
onSaveName={action('on save name')}
|
onSaveName={action('on save name')}
|
||||||
onOpenComposer={action('on open composer')}
|
onOpenComposer={action('on open composer')}
|
||||||
tasks={[]}
|
|
||||||
onExtraMenuOpen={action('extra menu open')}
|
onExtraMenuOpen={action('extra menu open')}
|
||||||
>
|
>
|
||||||
<ListCards>
|
<ListCards>
|
||||||
@ -160,7 +146,6 @@ export const WithCardAndComposer = () => {
|
|||||||
isComposerOpen
|
isComposerOpen
|
||||||
onSaveName={action('on save name')}
|
onSaveName={action('on save name')}
|
||||||
onOpenComposer={action('on open composer')}
|
onOpenComposer={action('on open composer')}
|
||||||
tasks={[]}
|
|
||||||
onExtraMenuOpen={action('extra menu open')}
|
onExtraMenuOpen={action('extra menu open')}
|
||||||
>
|
>
|
||||||
<ListCards>
|
<ListCards>
|
||||||
|
@ -97,9 +97,7 @@ export const Header = styled.div<{ isEditing: boolean }>`
|
|||||||
props.isEditing &&
|
props.isEditing &&
|
||||||
css`
|
css`
|
||||||
& ${HeaderName} {
|
& ${HeaderName} {
|
||||||
background: #fff;
|
box-shadow: rgb(115, 103, 240) 0px 0px 0px 1px;
|
||||||
border: none;
|
|
||||||
box-shadow: inset 0 0 0 2px #0079bf;
|
|
||||||
}
|
}
|
||||||
`}
|
`}
|
||||||
`;
|
`;
|
||||||
|
@ -22,7 +22,6 @@ type Props = {
|
|||||||
onSaveName: (name: string) => void;
|
onSaveName: (name: string) => void;
|
||||||
isComposerOpen: boolean;
|
isComposerOpen: boolean;
|
||||||
onOpenComposer: (id: string) => void;
|
onOpenComposer: (id: string) => void;
|
||||||
tasks: Task[];
|
|
||||||
wrapperProps?: any;
|
wrapperProps?: any;
|
||||||
headerProps?: any;
|
headerProps?: any;
|
||||||
index?: number;
|
index?: number;
|
||||||
|
@ -70,14 +70,12 @@ export const Default = () => {
|
|||||||
...listsData,
|
...listsData,
|
||||||
tasks: {
|
tasks: {
|
||||||
...listsData.tasks,
|
...listsData.tasks,
|
||||||
[droppedTask.taskID]: droppedTask,
|
[droppedTask.id]: droppedTask,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
console.log(newState);
|
|
||||||
setListsData(newState);
|
setListsData(newState);
|
||||||
};
|
};
|
||||||
const onListDrop = (droppedColumn: any) => {
|
const onListDrop = (droppedColumn: any) => {
|
||||||
console.log(droppedColumn);
|
|
||||||
const newState = {
|
const newState = {
|
||||||
...listsData,
|
...listsData,
|
||||||
columns: {
|
columns: {
|
||||||
@ -85,44 +83,9 @@ export const Default = () => {
|
|||||||
[droppedColumn.taskGroupID]: droppedColumn,
|
[droppedColumn.taskGroupID]: droppedColumn,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
console.log(newState);
|
|
||||||
setListsData(newState);
|
setListsData(newState);
|
||||||
};
|
};
|
||||||
return (
|
return <span />;
|
||||||
<Lists
|
|
||||||
{...listsData}
|
|
||||||
onCardClick={action('card click')}
|
|
||||||
onExtraMenuOpen={action('extra menu open')}
|
|
||||||
onQuickEditorOpen={action('card composer open')}
|
|
||||||
onCardDrop={onCardDrop}
|
|
||||||
onListDrop={onListDrop}
|
|
||||||
onCardMemberClick={action('card member click')}
|
|
||||||
onCardCreate={action('card create')}
|
|
||||||
onCreateList={listName => {
|
|
||||||
const [lastColumn] = Object.values(listsData.columns)
|
|
||||||
.sort((a, b) => a.position - b.position)
|
|
||||||
.slice(-1);
|
|
||||||
let position = 1;
|
|
||||||
if (lastColumn) {
|
|
||||||
position = lastColumn.position + 1;
|
|
||||||
}
|
|
||||||
const taskGroupID = Math.random().toString();
|
|
||||||
const newListsData = {
|
|
||||||
...listsData,
|
|
||||||
columns: {
|
|
||||||
...listsData.columns,
|
|
||||||
[taskGroupID]: {
|
|
||||||
taskGroupID,
|
|
||||||
name: listName,
|
|
||||||
position,
|
|
||||||
tasks: [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
setListsData(newListsData);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const createColumn = (id: any, name: any, position: any) => {
|
const createColumn = (id: any, name: any, position: any) => {
|
||||||
@ -202,13 +165,13 @@ export const ListsWithManyList = () => {
|
|||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<Lists
|
<Lists
|
||||||
{...listsData}
|
taskGroups={[]}
|
||||||
onCardClick={action('card click')}
|
onTaskClick={action('card click')}
|
||||||
onQuickEditorOpen={action('card composer open')}
|
onQuickEditorOpen={action('card composer open')}
|
||||||
onCardCreate={action('card create')}
|
onCreateTask={action('card create')}
|
||||||
onCardDrop={onCardDrop}
|
onTaskDrop={onCardDrop}
|
||||||
onListDrop={onListDrop}
|
onTaskGroupDrop={onListDrop}
|
||||||
onCreateList={action('create list')}
|
onCreateTaskGroup={action('create list')}
|
||||||
onExtraMenuOpen={action('extra menu open')}
|
onExtraMenuOpen={action('extra menu open')}
|
||||||
onCardMemberClick={action('card member click')}
|
onCardMemberClick={action('card member click')}
|
||||||
/>
|
/>
|
||||||
|
@ -11,5 +11,7 @@ export const Container = styled.div`
|
|||||||
|
|
||||||
export const BoardWrapper = styled.div`
|
export const BoardWrapper = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
|
margin-top: 12px;
|
||||||
|
margin-left: 8px;
|
||||||
`;
|
`;
|
||||||
export default Container;
|
export default Container;
|
||||||
|
@ -13,37 +13,29 @@ import {
|
|||||||
|
|
||||||
import { Container, BoardWrapper } from './Styles';
|
import { Container, BoardWrapper } from './Styles';
|
||||||
|
|
||||||
interface Columns {
|
interface SimpleProps {
|
||||||
[key: string]: TaskGroup;
|
taskGroups: Array<TaskGroup>;
|
||||||
}
|
onTaskDrop: (task: Task) => void;
|
||||||
interface Tasks {
|
onTaskGroupDrop: (taskGroup: TaskGroup) => void;
|
||||||
[key: string]: Task;
|
|
||||||
}
|
|
||||||
|
|
||||||
type Props = {
|
onTaskClick: (task: Task) => void;
|
||||||
columns: Columns;
|
onCreateTask: (taskGroupID: string, name: string) => void;
|
||||||
tasks: Tasks;
|
|
||||||
onCardClick: (task: Task) => void;
|
|
||||||
onCardDrop: (task: Task) => void;
|
|
||||||
onListDrop: (taskGroup: TaskGroup) => void;
|
|
||||||
onCardCreate: (taskGroupID: string, name: string) => void;
|
|
||||||
onQuickEditorOpen: (e: ContextMenuEvent) => void;
|
onQuickEditorOpen: (e: ContextMenuEvent) => void;
|
||||||
onCreateList: (listName: string) => void;
|
onCreateTaskGroup: (listName: string) => void;
|
||||||
onExtraMenuOpen: (taskGroupID: string, $targetRef: React.RefObject<HTMLElement>) => void;
|
onExtraMenuOpen: (taskGroupID: string, $targetRef: React.RefObject<HTMLElement>) => void;
|
||||||
onCardMemberClick: OnCardMemberClick;
|
onCardMemberClick: OnCardMemberClick;
|
||||||
};
|
}
|
||||||
|
|
||||||
const Lists: React.FC<Props> = ({
|
const SimpleLists: React.FC<SimpleProps> = ({
|
||||||
columns,
|
taskGroups,
|
||||||
tasks,
|
onTaskDrop,
|
||||||
onCardClick,
|
onTaskGroupDrop,
|
||||||
onCardDrop,
|
onTaskClick,
|
||||||
onListDrop,
|
onCreateTask,
|
||||||
onCardCreate,
|
|
||||||
onQuickEditorOpen,
|
onQuickEditorOpen,
|
||||||
onCreateList,
|
onCreateTaskGroup,
|
||||||
onCardMemberClick,
|
|
||||||
onExtraMenuOpen,
|
onExtraMenuOpen,
|
||||||
|
onCardMemberClick,
|
||||||
}) => {
|
}) => {
|
||||||
const onDragEnd = ({ draggableId, source, destination, type }: DropResult) => {
|
const onDragEnd = ({ draggableId, source, destination, type }: DropResult) => {
|
||||||
if (typeof destination === 'undefined') return;
|
if (typeof destination === 'undefined') return;
|
||||||
@ -51,29 +43,24 @@ const Lists: React.FC<Props> = ({
|
|||||||
|
|
||||||
const isList = type === 'column';
|
const isList = type === 'column';
|
||||||
const isSameList = destination.droppableId === source.droppableId;
|
const isSameList = destination.droppableId === source.droppableId;
|
||||||
const droppedDraggable: DraggableElement = isList
|
let droppedDraggable: DraggableElement | null = null;
|
||||||
? {
|
let beforeDropDraggables: Array<DraggableElement> | null = null;
|
||||||
|
|
||||||
|
if (isList) {
|
||||||
|
const droppedGroup = taskGroups.find(taskGroup => taskGroup.id === draggableId);
|
||||||
|
if (droppedGroup) {
|
||||||
|
droppedDraggable = {
|
||||||
id: draggableId,
|
id: draggableId,
|
||||||
position: columns[draggableId].position,
|
position: droppedGroup.position,
|
||||||
}
|
|
||||||
: {
|
|
||||||
id: draggableId,
|
|
||||||
position: tasks[draggableId].position,
|
|
||||||
};
|
};
|
||||||
const beforeDropDraggables = isList
|
beforeDropDraggables = getSortedDraggables(
|
||||||
? getSortedDraggables(
|
taskGroups.map(taskGroup => {
|
||||||
Object.values(columns).map(column => {
|
return { id: taskGroup.id, position: taskGroup.position };
|
||||||
return { id: column.taskGroupID, position: column.position };
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
: getSortedDraggables(
|
|
||||||
Object.values(tasks)
|
|
||||||
.filter((t: any) => t.taskGroup.taskGroupID === destination.droppableId)
|
|
||||||
.map(task => {
|
|
||||||
return { id: task.taskID, position: task.position };
|
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
if (droppedDraggable === null || beforeDropDraggables === null) {
|
||||||
|
throw new Error('before drop draggables is null');
|
||||||
|
}
|
||||||
const afterDropDraggables = getAfterDropDraggableList(
|
const afterDropDraggables = getAfterDropDraggableList(
|
||||||
beforeDropDraggables,
|
beforeDropDraggables,
|
||||||
droppedDraggable,
|
droppedDraggable,
|
||||||
@ -82,32 +69,51 @@ const Lists: React.FC<Props> = ({
|
|||||||
destination,
|
destination,
|
||||||
);
|
);
|
||||||
const newPosition = getNewDraggablePosition(afterDropDraggables, destination.index);
|
const newPosition = getNewDraggablePosition(afterDropDraggables, destination.index);
|
||||||
|
onTaskGroupDrop({
|
||||||
if (isList) {
|
...droppedGroup,
|
||||||
const droppedList = columns[droppedDraggable.id];
|
|
||||||
onListDrop({
|
|
||||||
...droppedList,
|
|
||||||
position: newPosition,
|
position: newPosition,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
const droppedCard = tasks[droppedDraggable.id];
|
throw { error: 'task group can not be found' };
|
||||||
const newCard = {
|
|
||||||
...droppedCard,
|
|
||||||
position: newPosition,
|
|
||||||
taskGroup: {
|
|
||||||
taskGroupID: destination.droppableId,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
onCardDrop(newCard);
|
|
||||||
}
|
}
|
||||||
};
|
} else {
|
||||||
|
const targetGroup = taskGroups.findIndex(
|
||||||
|
taskGroup => taskGroup.tasks.findIndex(task => task.id === draggableId) !== -1,
|
||||||
|
);
|
||||||
|
const droppedTask = taskGroups[targetGroup].tasks.find(task => task.id === draggableId);
|
||||||
|
|
||||||
const orderedColumns = getSortedDraggables(
|
if (droppedTask) {
|
||||||
Object.values(columns).map(column => {
|
droppedDraggable = {
|
||||||
return { id: column.taskGroupID, position: column.position };
|
id: draggableId,
|
||||||
|
position: droppedTask.position,
|
||||||
|
};
|
||||||
|
beforeDropDraggables = getSortedDraggables(
|
||||||
|
taskGroups[targetGroup].tasks.map(task => {
|
||||||
|
return { id: task.id, position: task.position };
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
console.log(orderedColumns);
|
if (droppedDraggable === null || beforeDropDraggables === null) {
|
||||||
|
throw new Error('before drop draggables is null');
|
||||||
|
}
|
||||||
|
const afterDropDraggables = getAfterDropDraggableList(
|
||||||
|
beforeDropDraggables,
|
||||||
|
droppedDraggable,
|
||||||
|
isList,
|
||||||
|
isSameList,
|
||||||
|
destination,
|
||||||
|
);
|
||||||
|
const newPosition = getNewDraggablePosition(afterDropDraggables, destination.index);
|
||||||
|
const newTask = {
|
||||||
|
...droppedTask,
|
||||||
|
position: newPosition,
|
||||||
|
taskGroup: {
|
||||||
|
id: destination.droppableId,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
onTaskDrop(newTask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const [currentComposer, setCurrentComposer] = useState('');
|
const [currentComposer, setCurrentComposer] = useState('');
|
||||||
return (
|
return (
|
||||||
@ -116,34 +122,35 @@ const Lists: React.FC<Props> = ({
|
|||||||
<Droppable direction="horizontal" type="column" droppableId="root">
|
<Droppable direction="horizontal" type="column" droppableId="root">
|
||||||
{provided => (
|
{provided => (
|
||||||
<Container {...provided.droppableProps} ref={provided.innerRef}>
|
<Container {...provided.droppableProps} ref={provided.innerRef}>
|
||||||
{orderedColumns.map((columnDraggable, index: number) => {
|
{taskGroups
|
||||||
const column = columns[columnDraggable.id];
|
.slice()
|
||||||
const columnCards = Object.values(tasks)
|
.sort((a: any, b: any) => a.position - b.position)
|
||||||
.filter((t: Task) => t.taskGroup.taskGroupID === column.taskGroupID)
|
.map((taskGroup: TaskGroup, index: number) => {
|
||||||
.sort((a, b) => a.position - b.position);
|
|
||||||
return (
|
return (
|
||||||
<Draggable draggableId={column.taskGroupID} key={column.taskGroupID} index={index}>
|
<Draggable draggableId={taskGroup.id} key={taskGroup.id} index={index}>
|
||||||
{columnDragProvided => (
|
{columnDragProvided => (
|
||||||
<Droppable type="tasks" droppableId={column.taskGroupID}>
|
<Droppable type="tasks" droppableId={taskGroup.id}>
|
||||||
{(columnDropProvided, snapshot) => (
|
{(columnDropProvided, snapshot) => (
|
||||||
<List
|
<List
|
||||||
name={column.name}
|
name={taskGroup.name}
|
||||||
onOpenComposer={id => setCurrentComposer(id)}
|
onOpenComposer={id => setCurrentComposer(id)}
|
||||||
isComposerOpen={currentComposer === column.taskGroupID}
|
isComposerOpen={currentComposer === taskGroup.id}
|
||||||
onSaveName={name => {}}
|
onSaveName={name => {}}
|
||||||
tasks={columnCards}
|
|
||||||
ref={columnDragProvided.innerRef}
|
ref={columnDragProvided.innerRef}
|
||||||
wrapperProps={columnDragProvided.draggableProps}
|
wrapperProps={columnDragProvided.draggableProps}
|
||||||
headerProps={columnDragProvided.dragHandleProps}
|
headerProps={columnDragProvided.dragHandleProps}
|
||||||
onExtraMenuOpen={onExtraMenuOpen}
|
onExtraMenuOpen={onExtraMenuOpen}
|
||||||
id={column.taskGroupID}
|
id={taskGroup.id}
|
||||||
key={column.taskGroupID}
|
key={taskGroup.id}
|
||||||
index={index}
|
index={index}
|
||||||
>
|
>
|
||||||
<ListCards ref={columnDropProvided.innerRef} {...columnDropProvided.droppableProps}>
|
<ListCards ref={columnDropProvided.innerRef} {...columnDropProvided.droppableProps}>
|
||||||
{columnCards.map((task: Task, taskIndex: any) => {
|
{taskGroup.tasks
|
||||||
|
.slice()
|
||||||
|
.sort((a: any, b: any) => a.position - b.position)
|
||||||
|
.map((task: Task, taskIndex: any) => {
|
||||||
return (
|
return (
|
||||||
<Draggable key={task.taskID} draggableId={task.taskID} index={taskIndex}>
|
<Draggable key={task.id} draggableId={task.id} index={taskIndex}>
|
||||||
{taskProvided => {
|
{taskProvided => {
|
||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
@ -152,13 +159,15 @@ const Lists: React.FC<Props> = ({
|
|||||||
...taskProvided.dragHandleProps,
|
...taskProvided.dragHandleProps,
|
||||||
}}
|
}}
|
||||||
ref={taskProvided.innerRef}
|
ref={taskProvided.innerRef}
|
||||||
taskID={task.taskID}
|
taskID={task.id}
|
||||||
taskGroupID={column.taskGroupID}
|
taskGroupID={taskGroup.id}
|
||||||
description=""
|
description=""
|
||||||
|
labels={task.labels.map(label => label.projectLabel)}
|
||||||
title={task.name}
|
title={task.name}
|
||||||
labels={task.labels}
|
members={task.assigned}
|
||||||
members={task.members}
|
onClick={() => {
|
||||||
onClick={() => onCardClick(task)}
|
onTaskClick(task);
|
||||||
|
}}
|
||||||
onCardMemberClick={onCardMemberClick}
|
onCardMemberClick={onCardMemberClick}
|
||||||
onContextMenu={onQuickEditorOpen}
|
onContextMenu={onQuickEditorOpen}
|
||||||
/>
|
/>
|
||||||
@ -168,13 +177,13 @@ const Lists: React.FC<Props> = ({
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
{columnDropProvided.placeholder}
|
{columnDropProvided.placeholder}
|
||||||
{currentComposer === column.taskGroupID && (
|
{currentComposer === taskGroup.id && (
|
||||||
<CardComposer
|
<CardComposer
|
||||||
onClose={() => {
|
onClose={() => {
|
||||||
setCurrentComposer('');
|
setCurrentComposer('');
|
||||||
}}
|
}}
|
||||||
onCreateCard={name => {
|
onCreateCard={name => {
|
||||||
onCardCreate(column.taskGroupID, name);
|
onCreateTask(taskGroup.id, name);
|
||||||
}}
|
}}
|
||||||
isOpen
|
isOpen
|
||||||
/>
|
/>
|
||||||
@ -192,9 +201,13 @@ const Lists: React.FC<Props> = ({
|
|||||||
)}
|
)}
|
||||||
</Droppable>
|
</Droppable>
|
||||||
</DragDropContext>
|
</DragDropContext>
|
||||||
<AddList onSave={onCreateList} />
|
<AddList
|
||||||
|
onSave={listName => {
|
||||||
|
onCreateTaskGroup(listName);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</BoardWrapper>
|
</BoardWrapper>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Lists;
|
export default SimpleLists;
|
||||||
|
@ -39,16 +39,18 @@ const MemberManager: React.FC<MemberManagerProps> = ({
|
|||||||
<BoardMembersList>
|
<BoardMembersList>
|
||||||
{availableMembers
|
{availableMembers
|
||||||
.filter(
|
.filter(
|
||||||
member => currentSearch === '' || member.displayName.toLowerCase().startsWith(currentSearch.toLowerCase()),
|
member =>
|
||||||
|
currentSearch === '' ||
|
||||||
|
`${member.firstName} ${member.lastName}`.toLowerCase().startsWith(currentSearch.toLowerCase()),
|
||||||
)
|
)
|
||||||
.map(member => {
|
.map(member => {
|
||||||
return (
|
return (
|
||||||
<BoardMembersListItem key={member.userID}>
|
<BoardMembersListItem key={member.id}>
|
||||||
<BoardMemberListItemContent
|
<BoardMemberListItemContent
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const isActive = activeMembers.findIndex(m => m.userID === member.userID) !== -1;
|
const isActive = activeMembers.findIndex(m => m.id === member.id) !== -1;
|
||||||
if (isActive) {
|
if (isActive) {
|
||||||
setActiveMembers(activeMembers.filter(m => m.userID !== member.userID));
|
setActiveMembers(activeMembers.filter(m => m.id !== member.id));
|
||||||
} else {
|
} else {
|
||||||
setActiveMembers([...activeMembers, member]);
|
setActiveMembers([...activeMembers, member]);
|
||||||
}
|
}
|
||||||
@ -56,8 +58,8 @@ const MemberManager: React.FC<MemberManagerProps> = ({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ProfileIcon>JK</ProfileIcon>
|
<ProfileIcon>JK</ProfileIcon>
|
||||||
<MemberName>{member.displayName}</MemberName>
|
<MemberName>{`${member.firstName} ${member.lastName}`}</MemberName>
|
||||||
{activeMembers.findIndex(m => m.userID === member.userID) !== -1 && (
|
{activeMembers.findIndex(m => m.id === member.id) !== -1 && (
|
||||||
<ActiveIconWrapper>
|
<ActiveIconWrapper>
|
||||||
<Checkmark size={16} color="#42526e" />
|
<Checkmark size={16} color="#42526e" />
|
||||||
</ActiveIconWrapper>
|
</ActiveIconWrapper>
|
||||||
|
@ -16,14 +16,14 @@ type MiniProfileProps = {
|
|||||||
displayName: string;
|
displayName: string;
|
||||||
username: string;
|
username: string;
|
||||||
bio: string;
|
bio: string;
|
||||||
profileIcon: ProfileIcon;
|
profileIcon: ProfileIcon | null;
|
||||||
onRemoveFromTask: () => void;
|
onRemoveFromTask: () => void;
|
||||||
};
|
};
|
||||||
const MiniProfile: React.FC<MiniProfileProps> = ({ displayName, username, bio, profileIcon, onRemoveFromTask }) => {
|
const MiniProfile: React.FC<MiniProfileProps> = ({ displayName, username, bio, profileIcon, onRemoveFromTask }) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Profile>
|
<Profile>
|
||||||
<ProfileIcon bgColor={profileIcon.bgColor ?? ''}>{profileIcon.initials}</ProfileIcon>
|
{profileIcon && <ProfileIcon bgColor={profileIcon.bgColor ?? ''}>{profileIcon.initials}</ProfileIcon>}
|
||||||
<ProfileInfo>
|
<ProfileInfo>
|
||||||
<InfoTitle>{displayName}</InfoTitle>
|
<InfoTitle>{displayName}</InfoTitle>
|
||||||
<InfoUsername>{username}</InfoUsername>
|
<InfoUsername>{username}</InfoUsername>
|
||||||
|
@ -5,7 +5,7 @@ import { SaveButton, DeleteButton, LabelBox, EditLabelForm, FieldLabel, FieldNam
|
|||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
labelColors: Array<LabelColor>;
|
labelColors: Array<LabelColor>;
|
||||||
label: Label | null;
|
label: ProjectLabel | null;
|
||||||
onLabelEdit: (labelId: string | null, labelName: string, labelColor: LabelColor) => void;
|
onLabelEdit: (labelId: string | null, labelName: string, labelColor: LabelColor) => void;
|
||||||
onLabelDelete?: (labelId: string) => void;
|
onLabelDelete?: (labelId: string) => void;
|
||||||
};
|
};
|
||||||
@ -32,7 +32,7 @@ const LabelManager = ({ labelColors, label, onLabelEdit, onLabelDelete }: Props)
|
|||||||
onChange={e => {
|
onChange={e => {
|
||||||
setCurrentLabel(e.currentTarget.value);
|
setCurrentLabel(e.currentTarget.value);
|
||||||
}}
|
}}
|
||||||
value={currentLabel}
|
value={currentLabel ?? ''}
|
||||||
/>
|
/>
|
||||||
<FieldLabel>Select a color</FieldLabel>
|
<FieldLabel>Select a color</FieldLabel>
|
||||||
<div>
|
<div>
|
||||||
@ -56,7 +56,7 @@ const LabelManager = ({ labelColors, label, onLabelEdit, onLabelDelete }: Props)
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
console.log(currentColor);
|
console.log(currentColor);
|
||||||
if (currentColor) {
|
if (currentColor) {
|
||||||
onLabelEdit(label ? label.labelId : null, currentLabel, currentColor);
|
onLabelEdit(label ? label.id : null, currentLabel ?? '', currentColor);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@ -66,7 +66,7 @@ const LabelManager = ({ labelColors, label, onLabelEdit, onLabelDelete }: Props)
|
|||||||
type="submit"
|
type="submit"
|
||||||
onClick={e => {
|
onClick={e => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
onLabelDelete(label.labelId);
|
onLabelDelete(label.id);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
@ -14,12 +14,14 @@ import {
|
|||||||
} from './Styles';
|
} from './Styles';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
labels?: Label[];
|
labels?: Array<ProjectLabel>;
|
||||||
|
taskLabels?: Array<TaskLabel>;
|
||||||
onLabelToggle: (labelId: string) => void;
|
onLabelToggle: (labelId: string) => void;
|
||||||
onLabelEdit: (labelId: string) => void;
|
onLabelEdit: (labelId: string) => void;
|
||||||
onLabelCreate: () => void;
|
onLabelCreate: () => void;
|
||||||
};
|
};
|
||||||
const LabelManager: React.FC<Props> = ({ labels, onLabelToggle, onLabelEdit, onLabelCreate }) => {
|
|
||||||
|
const LabelManager: React.FC<Props> = ({ labels, taskLabels, onLabelToggle, onLabelEdit, onLabelCreate }) => {
|
||||||
const $fieldName = useRef<HTMLInputElement>(null);
|
const $fieldName = useRef<HTMLInputElement>(null);
|
||||||
const [currentLabel, setCurrentLabel] = useState('');
|
const [currentLabel, setCurrentLabel] = useState('');
|
||||||
const [currentSearch, setCurrentSearch] = useState('');
|
const [currentSearch, setCurrentSearch] = useState('');
|
||||||
@ -44,27 +46,31 @@ const LabelManager: React.FC<Props> = ({ labels, onLabelToggle, onLabelEdit, onL
|
|||||||
<Labels>
|
<Labels>
|
||||||
{labels &&
|
{labels &&
|
||||||
labels
|
labels
|
||||||
.filter(label => currentSearch === '' || label.name.toLowerCase().startsWith(currentSearch.toLowerCase()))
|
.filter(
|
||||||
|
label =>
|
||||||
|
currentSearch === '' ||
|
||||||
|
(label.name && label.name.toLowerCase().startsWith(currentSearch.toLowerCase())),
|
||||||
|
)
|
||||||
.map(label => (
|
.map(label => (
|
||||||
<Label key={label.labelId}>
|
<Label key={label.id}>
|
||||||
<LabelIcon
|
<LabelIcon
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
onLabelEdit(label.labelId);
|
onLabelEdit(label.id);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Pencil color="#c2c6dc" />
|
<Pencil color="#c2c6dc" />
|
||||||
</LabelIcon>
|
</LabelIcon>
|
||||||
<CardLabel
|
<CardLabel
|
||||||
key={label.labelId}
|
key={label.id}
|
||||||
color={label.labelColor.colorHex}
|
color={label.labelColor.colorHex}
|
||||||
active={currentLabel === label.labelId}
|
active={currentLabel === label.id}
|
||||||
onMouseEnter={() => {
|
onMouseEnter={() => {
|
||||||
setCurrentLabel(label.labelId);
|
setCurrentLabel(label.id);
|
||||||
}}
|
}}
|
||||||
onClick={() => onLabelToggle(label.labelId)}
|
onClick={() => onLabelToggle(label.id)}
|
||||||
>
|
>
|
||||||
{label.name}
|
{label.name}
|
||||||
{label.active && (
|
{taskLabels && taskLabels.find(t => t.projectLabel.id === label.id) && (
|
||||||
<ActiveIcon>
|
<ActiveIcon>
|
||||||
<Checkmark color="#fff" />
|
<Checkmark color="#fff" />
|
||||||
</ActiveIcon>
|
</ActiveIcon>
|
||||||
|
@ -7,12 +7,13 @@ import ListActions from 'shared/components/ListActions';
|
|||||||
import MemberManager from 'shared/components/MemberManager';
|
import MemberManager from 'shared/components/MemberManager';
|
||||||
import DueDateManager from 'shared/components/DueDateManager';
|
import DueDateManager from 'shared/components/DueDateManager';
|
||||||
import MiniProfile from 'shared/components/MiniProfile';
|
import MiniProfile from 'shared/components/MiniProfile';
|
||||||
import styled from 'styled-components';
|
|
||||||
|
|
||||||
import PopupMenu, { PopupProvider, usePopup, Popup } from '.';
|
import styled from 'styled-components';
|
||||||
|
import produce from 'immer';
|
||||||
import NormalizeStyles from 'App/NormalizeStyles';
|
import NormalizeStyles from 'App/NormalizeStyles';
|
||||||
import BaseStyles from 'App/BaseStyles';
|
import BaseStyles from 'App/BaseStyles';
|
||||||
import produce from 'immer';
|
|
||||||
|
import PopupMenu, { PopupProvider, usePopup, Popup } from '.';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
component: PopupMenu,
|
component: PopupMenu,
|
||||||
@ -24,28 +25,17 @@ export default {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const labelData = [
|
const labelData: Array<ProjectLabel> = [
|
||||||
{
|
{
|
||||||
labelId: 'development',
|
id: 'development',
|
||||||
name: 'Development',
|
name: 'Development',
|
||||||
|
createdDate: new Date().toString(),
|
||||||
labelColor: {
|
labelColor: {
|
||||||
id: '1',
|
id: '1',
|
||||||
name: 'white',
|
|
||||||
colorHex: LabelColors.BLUE,
|
colorHex: LabelColors.BLUE,
|
||||||
|
name: 'blue',
|
||||||
position: 1,
|
position: 1,
|
||||||
},
|
},
|
||||||
active: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
labelId: 'general',
|
|
||||||
name: 'General',
|
|
||||||
labelColor: {
|
|
||||||
id: '1',
|
|
||||||
name: 'white',
|
|
||||||
colorHex: LabelColors.PINK,
|
|
||||||
position: 1,
|
|
||||||
},
|
|
||||||
active: false,
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -74,9 +64,9 @@ const LabelManagerEditor = () => {
|
|||||||
onLabelToggle={labelId => {
|
onLabelToggle={labelId => {
|
||||||
setLabels(
|
setLabels(
|
||||||
produce(labels, draftState => {
|
produce(labels, draftState => {
|
||||||
const idx = labels.findIndex(label => label.labelId === labelId);
|
const idx = labels.findIndex(label => label.id === labelId);
|
||||||
if (idx !== -1) {
|
if (idx !== -1) {
|
||||||
draftState[idx] = { ...draftState[idx], active: !labels[idx].active };
|
draftState[idx] = { ...draftState[idx] };
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
@ -86,13 +76,21 @@ const LabelManagerEditor = () => {
|
|||||||
<Popup onClose={action('on close')} title="Edit label" tab={1}>
|
<Popup onClose={action('on close')} title="Edit label" tab={1}>
|
||||||
<LabelEditor
|
<LabelEditor
|
||||||
labelColors={[{ id: '1', colorHex: '#c2c6dc', position: 1, name: 'gray' }]}
|
labelColors={[{ id: '1', colorHex: '#c2c6dc', position: 1, name: 'gray' }]}
|
||||||
label={labels.find(label => label.labelId === currentLabel) ?? null}
|
label={labels.find(label => label.id === currentLabel) ?? null}
|
||||||
onLabelEdit={(_labelId, name, color) => {
|
onLabelEdit={(_labelId, name, color) => {
|
||||||
setLabels(
|
setLabels(
|
||||||
produce(labels, draftState => {
|
produce(labels, draftState => {
|
||||||
const idx = labels.findIndex(label => label.labelId === currentLabel);
|
const idx = labels.findIndex(label => label.id === currentLabel);
|
||||||
if (idx !== -1) {
|
if (idx !== -1) {
|
||||||
draftState[idx] = { ...draftState[idx], name, labelColor: color };
|
draftState[idx] = {
|
||||||
|
...draftState[idx],
|
||||||
|
name,
|
||||||
|
labelColor: {
|
||||||
|
...draftState[idx].labelColor,
|
||||||
|
name: color.name ?? '',
|
||||||
|
colorHex: color.colorHex,
|
||||||
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
@ -105,7 +103,20 @@ const LabelManagerEditor = () => {
|
|||||||
label={null}
|
label={null}
|
||||||
labelColors={[{ id: '1', colorHex: '#c2c6dc', position: 1, name: 'gray' }]}
|
labelColors={[{ id: '1', colorHex: '#c2c6dc', position: 1, name: 'gray' }]}
|
||||||
onLabelEdit={(_labelId, name, color) => {
|
onLabelEdit={(_labelId, name, color) => {
|
||||||
setLabels([...labels, { labelId: name, name, labelColor: color, active: false }]);
|
setLabels([
|
||||||
|
...labels,
|
||||||
|
{
|
||||||
|
id: name,
|
||||||
|
name,
|
||||||
|
createdDate: new Date().toString(),
|
||||||
|
labelColor: {
|
||||||
|
id: color.id,
|
||||||
|
colorHex: color.colorHex,
|
||||||
|
name: color.name ?? '',
|
||||||
|
position: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
setTab(0);
|
setTab(0);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@ -214,7 +225,12 @@ export const MemberManagerPopup = () => {
|
|||||||
<PopupMenu title="Members" top={popupData.top} onClose={() => setPopupData(initalState)} left={popupData.left}>
|
<PopupMenu title="Members" top={popupData.top} onClose={() => setPopupData(initalState)} left={popupData.left}>
|
||||||
<MemberManager
|
<MemberManager
|
||||||
availableMembers={[
|
availableMembers={[
|
||||||
{ userID: '1', displayName: 'Jordan Knott', profileIcon: { bgColor: null, url: null, initials: null } },
|
{
|
||||||
|
id: '1',
|
||||||
|
firstName: 'Jordan',
|
||||||
|
lastName: 'Knott',
|
||||||
|
profileIcon: { bgColor: null, url: null, initials: null },
|
||||||
|
},
|
||||||
]}
|
]}
|
||||||
activeMembers={[]}
|
activeMembers={[]}
|
||||||
onMemberChange={action('member change')}
|
onMemberChange={action('member change')}
|
||||||
@ -251,26 +267,35 @@ export const DueDateManagerPopup = () => {
|
|||||||
<PopupMenu title="Due Date" top={popupData.top} onClose={() => setPopupData(initalState)} left={popupData.left}>
|
<PopupMenu title="Due Date" top={popupData.top} onClose={() => setPopupData(initalState)} left={popupData.left}>
|
||||||
<DueDateManager
|
<DueDateManager
|
||||||
task={{
|
task={{
|
||||||
taskID: '1',
|
id: '1',
|
||||||
taskGroup: { name: 'General', taskGroupID: '1' },
|
taskGroup: { name: 'General', id: '1', position: 1 },
|
||||||
name: 'Hello, world',
|
name: 'Hello, world',
|
||||||
position: 1,
|
position: 1,
|
||||||
labels: [
|
labels: [
|
||||||
{
|
{
|
||||||
labelId: 'soft-skills',
|
id: 'soft-skills',
|
||||||
|
assignedDate: new Date().toString(),
|
||||||
|
projectLabel: {
|
||||||
|
createdDate: new Date().toString(),
|
||||||
|
id: 'label-soft-skills',
|
||||||
|
name: 'Soft Skills',
|
||||||
labelColor: {
|
labelColor: {
|
||||||
id: '1',
|
id: '1',
|
||||||
name: 'white',
|
name: 'white',
|
||||||
colorHex: '#fff',
|
colorHex: '#fff',
|
||||||
position: 1,
|
position: 1,
|
||||||
},
|
},
|
||||||
active: true,
|
},
|
||||||
name: 'Soft Skills',
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
description: 'hello!',
|
description: 'hello!',
|
||||||
members: [
|
assigned: [
|
||||||
{ userID: '1', profileIcon: { bgColor: null, url: null, initials: null }, displayName: 'Jordan Knott' },
|
{
|
||||||
|
id: '1',
|
||||||
|
profileIcon: { bgColor: null, url: null, initials: null },
|
||||||
|
firstName: 'Jordan',
|
||||||
|
lastName: 'Knott',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}}
|
}}
|
||||||
onCancel={action('cancel')}
|
onCancel={action('cancel')}
|
||||||
|
@ -17,28 +17,17 @@ export default {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const labelData = [
|
const labelData: Array<ProjectLabel> = [
|
||||||
{
|
{
|
||||||
labelId: 'development',
|
id: 'development',
|
||||||
name: 'Development',
|
name: 'Development',
|
||||||
|
createdDate: 'date',
|
||||||
labelColor: {
|
labelColor: {
|
||||||
id: '1',
|
id: 'label-color-blue',
|
||||||
name: 'white',
|
|
||||||
colorHex: LabelColors.BLUE,
|
colorHex: LabelColors.BLUE,
|
||||||
|
name: 'blue',
|
||||||
position: 1,
|
position: 1,
|
||||||
},
|
},
|
||||||
active: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
labelId: 'general',
|
|
||||||
name: 'General',
|
|
||||||
labelColor: {
|
|
||||||
id: '1',
|
|
||||||
name: 'white',
|
|
||||||
colorHex: LabelColors.PINK,
|
|
||||||
position: 1,
|
|
||||||
},
|
|
||||||
active: false,
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -70,7 +59,6 @@ export const Default = () => {
|
|||||||
isComposerOpen={false}
|
isComposerOpen={false}
|
||||||
onSaveName={action('on save name')}
|
onSaveName={action('on save name')}
|
||||||
onOpenComposer={action('on open composer')}
|
onOpenComposer={action('on open composer')}
|
||||||
tasks={[]}
|
|
||||||
onExtraMenuOpen={(taskGroupID, $targetRef) => console.log(taskGroupID, $targetRef)}
|
onExtraMenuOpen={(taskGroupID, $targetRef) => console.log(taskGroupID, $targetRef)}
|
||||||
>
|
>
|
||||||
<ListCards>
|
<ListCards>
|
||||||
|
@ -22,7 +22,7 @@ type Props = {
|
|||||||
onEditCard: (taskGroupID: string, taskID: string, cardName: string) => void;
|
onEditCard: (taskGroupID: string, taskID: string, cardName: string) => void;
|
||||||
onOpenPopup: (popupType: number, top: number, left: number) => void;
|
onOpenPopup: (popupType: number, top: number, left: number) => void;
|
||||||
onArchiveCard: (taskGroupID: string, taskID: string) => void;
|
onArchiveCard: (taskGroupID: string, taskID: string) => void;
|
||||||
labels?: Label[];
|
labels?: Array<ProjectLabel>;
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
top: number;
|
top: number;
|
||||||
left: number;
|
left: number;
|
||||||
@ -72,7 +72,7 @@ const QuickCardEditor = ({
|
|||||||
<ListCardLabels>
|
<ListCardLabels>
|
||||||
{labels &&
|
{labels &&
|
||||||
labels.map(label => (
|
labels.map(label => (
|
||||||
<ListCardLabel color={label.labelColor.colorHex} key={label.name}>
|
<ListCardLabel color={label.labelColor.colorHex} key={label.id}>
|
||||||
{label.name}
|
{label.name}
|
||||||
</ListCardLabel>
|
</ListCardLabel>
|
||||||
))}
|
))}
|
||||||
|
@ -31,7 +31,7 @@ type TaskAssigneeProps = {
|
|||||||
const TaskAssignee: React.FC<TaskAssigneeProps> = ({ member, onMemberProfile, size }) => {
|
const TaskAssignee: React.FC<TaskAssigneeProps> = ({ member, onMemberProfile, size }) => {
|
||||||
const $memberRef = useRef<HTMLDivElement>(null);
|
const $memberRef = useRef<HTMLDivElement>(null);
|
||||||
return (
|
return (
|
||||||
<TaskDetailAssignee ref={$memberRef} onClick={() => onMemberProfile($memberRef, member.userID)} key={member.userID}>
|
<TaskDetailAssignee ref={$memberRef} onClick={() => onMemberProfile($memberRef, member.id)} key={member.id}>
|
||||||
<ProfileIcon size={size}>{member.profileIcon.initials ?? ''}</ProfileIcon>
|
<ProfileIcon size={size}>{member.profileIcon.initials ?? ''}</ProfileIcon>
|
||||||
</TaskDetailAssignee>
|
</TaskDetailAssignee>
|
||||||
);
|
);
|
||||||
|
@ -244,11 +244,11 @@ export const TaskDetailLabels = styled.div`
|
|||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const TaskDetailLabel = styled.div`
|
export const TaskDetailLabel = styled.div<{ color: string }>`
|
||||||
&:hover {
|
&:hover {
|
||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
}
|
}
|
||||||
background-color: #00c2e0;
|
background-color: ${props => props.color};
|
||||||
color: #fff;
|
color: #fff;
|
||||||
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
@ -29,29 +29,34 @@ export const Default = () => {
|
|||||||
return (
|
return (
|
||||||
<TaskDetails
|
<TaskDetails
|
||||||
task={{
|
task={{
|
||||||
taskID: '1',
|
id: '1',
|
||||||
taskGroup: { name: 'General', taskGroupID: '1' },
|
taskGroup: { name: 'General', id: '1' },
|
||||||
name: 'Hello, world',
|
name: 'Hello, world',
|
||||||
position: 1,
|
position: 1,
|
||||||
labels: [
|
labels: [
|
||||||
{
|
{
|
||||||
labelId: 'soft-skills',
|
id: 'soft-skills',
|
||||||
|
assignedDate: new Date().toString(),
|
||||||
|
projectLabel: {
|
||||||
|
createdDate: new Date().toString(),
|
||||||
|
id: 'label-soft-skills',
|
||||||
|
name: 'Soft Skills',
|
||||||
labelColor: {
|
labelColor: {
|
||||||
id: '1',
|
id: '1',
|
||||||
name: 'white',
|
name: 'white',
|
||||||
colorHex: '#fff',
|
colorHex: '#fff',
|
||||||
position: 1,
|
position: 1,
|
||||||
},
|
},
|
||||||
active: true,
|
},
|
||||||
name: 'Soft Skills',
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
description,
|
description,
|
||||||
members: [
|
assigned: [
|
||||||
{
|
{
|
||||||
userID: '1',
|
id: '1',
|
||||||
profileIcon: { bgColor: null, url: null, initials: null },
|
profileIcon: { bgColor: null, url: null, initials: null },
|
||||||
displayName: 'Jordan Knott',
|
firstName: 'Jordan',
|
||||||
|
lastName: 'Knott',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}}
|
}}
|
||||||
|
@ -193,15 +193,15 @@ const TaskDetails: React.FC<TaskDetailsProps> = ({
|
|||||||
<TaskDetailsSidebar>
|
<TaskDetailsSidebar>
|
||||||
<TaskDetailSectionTitle>Assignees</TaskDetailSectionTitle>
|
<TaskDetailSectionTitle>Assignees</TaskDetailSectionTitle>
|
||||||
<TaskDetailAssignees>
|
<TaskDetailAssignees>
|
||||||
{task.members && task.members.length === 0 ? (
|
{task.assigned && task.assigned.length === 0 ? (
|
||||||
<UnassignedLabel ref={$unassignedRef} onClick={onUnassignedClick}>
|
<UnassignedLabel ref={$unassignedRef} onClick={onUnassignedClick}>
|
||||||
Unassigned
|
Unassigned
|
||||||
</UnassignedLabel>
|
</UnassignedLabel>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
{task.members &&
|
{task.assigned &&
|
||||||
task.members.map(member => (
|
task.assigned.map(member => (
|
||||||
<TaskAssignee size={32} member={member} onMemberProfile={onMemberProfile} />
|
<TaskAssignee key={member.id} size={32} member={member} onMemberProfile={onMemberProfile} />
|
||||||
))}
|
))}
|
||||||
<TaskDetailsAddMember ref={$addMemberRef} onClick={onAddMember}>
|
<TaskDetailsAddMember ref={$addMemberRef} onClick={onAddMember}>
|
||||||
<TaskDetailsAddMemberIcon>
|
<TaskDetailsAddMemberIcon>
|
||||||
@ -214,7 +214,11 @@ const TaskDetails: React.FC<TaskDetailsProps> = ({
|
|||||||
<TaskDetailSectionTitle>Labels</TaskDetailSectionTitle>
|
<TaskDetailSectionTitle>Labels</TaskDetailSectionTitle>
|
||||||
<TaskDetailLabels>
|
<TaskDetailLabels>
|
||||||
{task.labels.map(label => {
|
{task.labels.map(label => {
|
||||||
return <TaskDetailLabel>{label.name}</TaskDetailLabel>;
|
return (
|
||||||
|
<TaskDetailLabel key={label.projectLabel.id} color={label.projectLabel.labelColor.colorHex}>
|
||||||
|
{label.projectLabel.name}
|
||||||
|
</TaskDetailLabel>
|
||||||
|
);
|
||||||
})}
|
})}
|
||||||
<TaskDetailsAddLabel ref={$addLabelRef} onClick={onAddLabel}>
|
<TaskDetailsAddLabel ref={$addLabelRef} onClick={onAddLabel}>
|
||||||
<TaskDetailsAddLabelIcon>
|
<TaskDetailsAddLabelIcon>
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import styled, { css } from 'styled-components';
|
import styled, { css } from 'styled-components';
|
||||||
|
import TextareaAutosize from 'react-autosize-textarea';
|
||||||
import { mixin } from 'shared/utils/styles';
|
import { mixin } from 'shared/utils/styles';
|
||||||
|
|
||||||
export const NavbarWrapper = styled.div`
|
export const NavbarWrapper = styled.div`
|
||||||
@ -135,7 +136,36 @@ export const ProjectName = styled.h1`
|
|||||||
color: #c2c6dc;
|
color: #c2c6dc;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
padding: 6px 10px 6px 8px;
|
padding: 3px 10px 3px 8px;
|
||||||
|
font-family: 'Droid Sans';
|
||||||
|
margin: -4px 0;
|
||||||
|
`;
|
||||||
|
export const ProjectNameTextarea = styled(TextareaAutosize)`
|
||||||
|
font-family: 'Droid Sans';
|
||||||
|
border: none;
|
||||||
|
resize: none;
|
||||||
|
overflow: hidden;
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
background: transparent;
|
||||||
|
border-radius: 3px;
|
||||||
|
box-shadow: none;
|
||||||
|
margin: -4px 0;
|
||||||
|
|
||||||
|
letter-spacing: normal;
|
||||||
|
word-spacing: normal;
|
||||||
|
text-transform: none;
|
||||||
|
text-indent: 0px;
|
||||||
|
text-shadow: none;
|
||||||
|
flex-direction: column;
|
||||||
|
text-align: start;
|
||||||
|
|
||||||
|
color: #c2c6dc;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 20px;
|
||||||
|
padding: 3px 10px 3px 8px;
|
||||||
|
&:focus {
|
||||||
|
box-shadow: rgb(115, 103, 240) 0px 0px 0px 1px;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const ProjectSwitcher = styled.button`
|
export const ProjectSwitcher = styled.button`
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import React, { useRef } from 'react';
|
import React, { useRef, useState, useEffect } from 'react';
|
||||||
import { Star, Bell, Cog, AngleDown } from 'shared/icons';
|
import { Star, Ellipsis, Bell, Cog, AngleDown } from 'shared/icons';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
NotificationContainer,
|
NotificationContainer,
|
||||||
|
ProjectNameTextarea,
|
||||||
InviteButton,
|
InviteButton,
|
||||||
GlobalActions,
|
GlobalActions,
|
||||||
ProjectActions,
|
ProjectActions,
|
||||||
@ -28,9 +29,72 @@ import TaskAssignee from 'shared/components/TaskAssignee';
|
|||||||
import { usePopup, Popup } from 'shared/components/PopupMenu';
|
import { usePopup, Popup } from 'shared/components/PopupMenu';
|
||||||
import MiniProfile from 'shared/components/MiniProfile';
|
import MiniProfile from 'shared/components/MiniProfile';
|
||||||
|
|
||||||
|
type ProjectHeadingProps = {
|
||||||
|
projectName: string;
|
||||||
|
onSaveProjectName?: (projectName: string) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
const ProjectHeading: React.FC<ProjectHeadingProps> = ({ projectName: initialProjectName, onSaveProjectName }) => {
|
||||||
|
const [isEditProjectName, setEditProjectName] = useState(false);
|
||||||
|
const [projectName, setProjectName] = useState(initialProjectName);
|
||||||
|
const $projectName = useRef<HTMLTextAreaElement>(null);
|
||||||
|
useEffect(() => {
|
||||||
|
if (isEditProjectName && $projectName && $projectName.current) {
|
||||||
|
$projectName.current.focus();
|
||||||
|
$projectName.current.select();
|
||||||
|
}
|
||||||
|
}, [isEditProjectName]);
|
||||||
|
useEffect(() => {
|
||||||
|
setProjectName(initialProjectName);
|
||||||
|
}, [initialProjectName]);
|
||||||
|
|
||||||
|
const onProjectNameChange = (event: React.FormEvent<HTMLTextAreaElement>): void => {
|
||||||
|
setProjectName(event.currentTarget.value);
|
||||||
|
};
|
||||||
|
const onProjectNameBlur = () => {
|
||||||
|
if (onSaveProjectName) {
|
||||||
|
onSaveProjectName(projectName);
|
||||||
|
}
|
||||||
|
setEditProjectName(false);
|
||||||
|
};
|
||||||
|
const onProjectNameKeyDown = (e: React.KeyboardEvent) => {
|
||||||
|
if (e.key === 'Enter') {
|
||||||
|
e.preventDefault();
|
||||||
|
if ($projectName && $projectName.current) {
|
||||||
|
$projectName.current.blur();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Separator>»</Separator>
|
||||||
|
{isEditProjectName ? (
|
||||||
|
<ProjectNameTextarea
|
||||||
|
ref={$projectName}
|
||||||
|
onChange={onProjectNameChange}
|
||||||
|
onKeyDown={onProjectNameKeyDown}
|
||||||
|
onBlur={onProjectNameBlur}
|
||||||
|
spellCheck={false}
|
||||||
|
value={projectName}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<ProjectName
|
||||||
|
onClick={() => {
|
||||||
|
setEditProjectName(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{projectName}
|
||||||
|
</ProjectName>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
type NavBarProps = {
|
type NavBarProps = {
|
||||||
projectName: string;
|
projectName: string;
|
||||||
onProfileClick: (bottom: number, right: number) => void;
|
onProfileClick: (bottom: number, right: number) => void;
|
||||||
|
onSaveProjectName?: (projectName: string) => void;
|
||||||
onNotificationClick: () => void;
|
onNotificationClick: () => void;
|
||||||
bgColor: string;
|
bgColor: string;
|
||||||
firstName: string;
|
firstName: string;
|
||||||
@ -38,8 +102,10 @@ type NavBarProps = {
|
|||||||
initials: string;
|
initials: string;
|
||||||
projectMembers?: Array<TaskUser> | null;
|
projectMembers?: Array<TaskUser> | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const NavBar: React.FC<NavBarProps> = ({
|
const NavBar: React.FC<NavBarProps> = ({
|
||||||
projectName,
|
projectName,
|
||||||
|
onSaveProjectName,
|
||||||
onProfileClick,
|
onProfileClick,
|
||||||
onNotificationClick,
|
onNotificationClick,
|
||||||
firstName,
|
firstName,
|
||||||
@ -68,14 +134,14 @@ const NavBar: React.FC<NavBarProps> = ({
|
|||||||
</Popup>,
|
</Popup>,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NavbarWrapper>
|
<NavbarWrapper>
|
||||||
<NavbarHeader>
|
<NavbarHeader>
|
||||||
<ProjectActions>
|
<ProjectActions>
|
||||||
<ProjectMeta>
|
<ProjectMeta>
|
||||||
<ProjectSwitcher>Projects</ProjectSwitcher>
|
<ProjectSwitcher>Projects</ProjectSwitcher>
|
||||||
<Separator>»</Separator>
|
<ProjectHeading projectName={projectName} onSaveProjectName={onSaveProjectName} />
|
||||||
<ProjectName>{projectName}</ProjectName>
|
|
||||||
<ProjectSettingsButton>
|
<ProjectSettingsButton>
|
||||||
<AngleDown color="#c2c6dc" />
|
<AngleDown color="#c2c6dc" />
|
||||||
</ProjectSettingsButton>
|
</ProjectSettingsButton>
|
||||||
@ -94,7 +160,7 @@ const NavBar: React.FC<NavBarProps> = ({
|
|||||||
{projectMembers && (
|
{projectMembers && (
|
||||||
<ProjectMembers>
|
<ProjectMembers>
|
||||||
{projectMembers.map(member => (
|
{projectMembers.map(member => (
|
||||||
<TaskAssignee key={member.userID} size={28} member={member} onMemberProfile={onMemberProfile} />
|
<TaskAssignee key={member.id} size={28} member={member} onMemberProfile={onMemberProfile} />
|
||||||
))}
|
))}
|
||||||
<InviteButton>Invite</InviteButton>
|
<InviteButton>Invite</InviteButton>
|
||||||
</ProjectMembers>
|
</ProjectMembers>
|
||||||
@ -104,9 +170,7 @@ const NavBar: React.FC<NavBarProps> = ({
|
|||||||
</NotificationContainer>
|
</NotificationContainer>
|
||||||
<ProfileContainer>
|
<ProfileContainer>
|
||||||
<ProfileNameWrapper>
|
<ProfileNameWrapper>
|
||||||
<ProfileNamePrimary>
|
<ProfileNamePrimary>{`${firstName} ${lastName}`}</ProfileNamePrimary>
|
||||||
{firstName} {lastName}
|
|
||||||
</ProfileNamePrimary>
|
|
||||||
<ProfileNameSecondary>Manager</ProfileNameSecondary>
|
<ProfileNameSecondary>Manager</ProfileNameSecondary>
|
||||||
</ProfileNameWrapper>
|
</ProfileNameWrapper>
|
||||||
<ProfileIcon ref={$profileRef} onClick={handleProfileClick} bgColor={bgColor}>
|
<ProfileIcon ref={$profileRef} onClick={handleProfileClick} bgColor={bgColor}>
|
||||||
|
@ -34,10 +34,8 @@ export type LabelColor = {
|
|||||||
export type TaskLabel = {
|
export type TaskLabel = {
|
||||||
__typename?: 'TaskLabel';
|
__typename?: 'TaskLabel';
|
||||||
id: Scalars['ID'];
|
id: Scalars['ID'];
|
||||||
projectLabelID: Scalars['UUID'];
|
projectLabel: ProjectLabel;
|
||||||
assignedDate: Scalars['Time'];
|
assignedDate: Scalars['Time'];
|
||||||
colorHex: Scalars['String'];
|
|
||||||
name?: Maybe<Scalars['String']>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ProfileIcon = {
|
export type ProfileIcon = {
|
||||||
@ -255,11 +253,10 @@ export type UpdateTaskDescriptionInput = {
|
|||||||
|
|
||||||
export type AddTaskLabelInput = {
|
export type AddTaskLabelInput = {
|
||||||
taskID: Scalars['UUID'];
|
taskID: Scalars['UUID'];
|
||||||
labelColorID: Scalars['UUID'];
|
projectLabelID: Scalars['UUID'];
|
||||||
};
|
};
|
||||||
|
|
||||||
export type RemoveTaskLabelInput = {
|
export type RemoveTaskLabelInput = {
|
||||||
taskID: Scalars['UUID'];
|
|
||||||
taskLabelID: Scalars['UUID'];
|
taskLabelID: Scalars['UUID'];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -289,12 +286,29 @@ export type UpdateProjectLabelColor = {
|
|||||||
labelColorID: Scalars['UUID'];
|
labelColorID: Scalars['UUID'];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type ToggleTaskLabelInput = {
|
||||||
|
taskID: Scalars['UUID'];
|
||||||
|
projectLabelID: Scalars['UUID'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ToggleTaskLabelPayload = {
|
||||||
|
__typename?: 'ToggleTaskLabelPayload';
|
||||||
|
active: Scalars['Boolean'];
|
||||||
|
task: Task;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type UpdateProjectName = {
|
||||||
|
projectID: Scalars['UUID'];
|
||||||
|
name: Scalars['String'];
|
||||||
|
};
|
||||||
|
|
||||||
export type Mutation = {
|
export type Mutation = {
|
||||||
__typename?: 'Mutation';
|
__typename?: 'Mutation';
|
||||||
createRefreshToken: RefreshToken;
|
createRefreshToken: RefreshToken;
|
||||||
createUserAccount: UserAccount;
|
createUserAccount: UserAccount;
|
||||||
createTeam: Team;
|
createTeam: Team;
|
||||||
createProject: Project;
|
createProject: Project;
|
||||||
|
updateProjectName: Project;
|
||||||
createProjectLabel: ProjectLabel;
|
createProjectLabel: ProjectLabel;
|
||||||
deleteProjectLabel: ProjectLabel;
|
deleteProjectLabel: ProjectLabel;
|
||||||
updateProjectLabel: ProjectLabel;
|
updateProjectLabel: ProjectLabel;
|
||||||
@ -305,6 +319,7 @@ export type Mutation = {
|
|||||||
deleteTaskGroup: DeleteTaskGroupPayload;
|
deleteTaskGroup: DeleteTaskGroupPayload;
|
||||||
addTaskLabel: Task;
|
addTaskLabel: Task;
|
||||||
removeTaskLabel: Task;
|
removeTaskLabel: Task;
|
||||||
|
toggleTaskLabel: ToggleTaskLabelPayload;
|
||||||
createTask: Task;
|
createTask: Task;
|
||||||
updateTaskDescription: Task;
|
updateTaskDescription: Task;
|
||||||
updateTaskLocation: Task;
|
updateTaskLocation: Task;
|
||||||
@ -336,6 +351,11 @@ export type MutationCreateProjectArgs = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationUpdateProjectNameArgs = {
|
||||||
|
input?: Maybe<UpdateProjectName>;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
export type MutationCreateProjectLabelArgs = {
|
export type MutationCreateProjectLabelArgs = {
|
||||||
input: NewProjectLabel;
|
input: NewProjectLabel;
|
||||||
};
|
};
|
||||||
@ -386,6 +406,11 @@ export type MutationRemoveTaskLabelArgs = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationToggleTaskLabelArgs = {
|
||||||
|
input: ToggleTaskLabelInput;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
export type MutationCreateTaskArgs = {
|
export type MutationCreateTaskArgs = {
|
||||||
input: NewTask;
|
input: NewTask;
|
||||||
};
|
};
|
||||||
@ -476,8 +501,19 @@ export type CreateTaskMutation = (
|
|||||||
& Pick<Task, 'id' | 'name' | 'position' | 'description'>
|
& Pick<Task, 'id' | 'name' | 'position' | 'description'>
|
||||||
& { taskGroup: (
|
& { taskGroup: (
|
||||||
{ __typename?: 'TaskGroup' }
|
{ __typename?: 'TaskGroup' }
|
||||||
& Pick<TaskGroup, 'id'>
|
& Pick<TaskGroup, 'id' | 'name' | 'position'>
|
||||||
), assigned: Array<(
|
), labels: Array<(
|
||||||
|
{ __typename?: 'TaskLabel' }
|
||||||
|
& Pick<TaskLabel, 'id' | 'assignedDate'>
|
||||||
|
& { projectLabel: (
|
||||||
|
{ __typename?: 'ProjectLabel' }
|
||||||
|
& Pick<ProjectLabel, 'id' | 'name' | 'createdDate'>
|
||||||
|
& { labelColor: (
|
||||||
|
{ __typename?: 'LabelColor' }
|
||||||
|
& Pick<LabelColor, 'id' | 'colorHex' | 'position' | 'name'>
|
||||||
|
) }
|
||||||
|
) }
|
||||||
|
)>, assigned: Array<(
|
||||||
{ __typename?: 'ProjectMember' }
|
{ __typename?: 'ProjectMember' }
|
||||||
& Pick<ProjectMember, 'id' | 'firstName' | 'lastName'>
|
& Pick<ProjectMember, 'id' | 'firstName' | 'lastName'>
|
||||||
& { profileIcon: (
|
& { profileIcon: (
|
||||||
@ -580,7 +616,21 @@ export type FindProjectQuery = (
|
|||||||
& { tasks: Array<(
|
& { tasks: Array<(
|
||||||
{ __typename?: 'Task' }
|
{ __typename?: 'Task' }
|
||||||
& Pick<Task, 'id' | 'name' | 'position' | 'description'>
|
& Pick<Task, 'id' | 'name' | 'position' | 'description'>
|
||||||
& { assigned: Array<(
|
& { taskGroup: (
|
||||||
|
{ __typename?: 'TaskGroup' }
|
||||||
|
& Pick<TaskGroup, 'id' | 'name' | 'position'>
|
||||||
|
), labels: Array<(
|
||||||
|
{ __typename?: 'TaskLabel' }
|
||||||
|
& Pick<TaskLabel, 'id' | 'assignedDate'>
|
||||||
|
& { projectLabel: (
|
||||||
|
{ __typename?: 'ProjectLabel' }
|
||||||
|
& Pick<ProjectLabel, 'id' | 'name' | 'createdDate'>
|
||||||
|
& { labelColor: (
|
||||||
|
{ __typename?: 'LabelColor' }
|
||||||
|
& Pick<LabelColor, 'id' | 'colorHex' | 'position' | 'name'>
|
||||||
|
) }
|
||||||
|
) }
|
||||||
|
)>, assigned: Array<(
|
||||||
{ __typename?: 'ProjectMember' }
|
{ __typename?: 'ProjectMember' }
|
||||||
& Pick<ProjectMember, 'id' | 'firstName' | 'lastName'>
|
& Pick<ProjectMember, 'id' | 'firstName' | 'lastName'>
|
||||||
& { profileIcon: (
|
& { profileIcon: (
|
||||||
@ -609,7 +659,18 @@ export type FindTaskQuery = (
|
|||||||
& { taskGroup: (
|
& { taskGroup: (
|
||||||
{ __typename?: 'TaskGroup' }
|
{ __typename?: 'TaskGroup' }
|
||||||
& Pick<TaskGroup, 'id'>
|
& Pick<TaskGroup, 'id'>
|
||||||
), assigned: Array<(
|
), labels: Array<(
|
||||||
|
{ __typename?: 'TaskLabel' }
|
||||||
|
& Pick<TaskLabel, 'id' | 'assignedDate'>
|
||||||
|
& { projectLabel: (
|
||||||
|
{ __typename?: 'ProjectLabel' }
|
||||||
|
& Pick<ProjectLabel, 'id' | 'name' | 'createdDate'>
|
||||||
|
& { labelColor: (
|
||||||
|
{ __typename?: 'LabelColor' }
|
||||||
|
& Pick<LabelColor, 'id' | 'colorHex' | 'position' | 'name'>
|
||||||
|
) }
|
||||||
|
) }
|
||||||
|
)>, assigned: Array<(
|
||||||
{ __typename?: 'ProjectMember' }
|
{ __typename?: 'ProjectMember' }
|
||||||
& Pick<ProjectMember, 'id' | 'firstName' | 'lastName'>
|
& Pick<ProjectMember, 'id' | 'firstName' | 'lastName'>
|
||||||
& { profileIcon: (
|
& { profileIcon: (
|
||||||
@ -650,6 +711,36 @@ export type MeQuery = (
|
|||||||
) }
|
) }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export type ToggleTaskLabelMutationVariables = {
|
||||||
|
taskID: Scalars['UUID'];
|
||||||
|
projectLabelID: Scalars['UUID'];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type ToggleTaskLabelMutation = (
|
||||||
|
{ __typename?: 'Mutation' }
|
||||||
|
& { toggleTaskLabel: (
|
||||||
|
{ __typename?: 'ToggleTaskLabelPayload' }
|
||||||
|
& Pick<ToggleTaskLabelPayload, 'active'>
|
||||||
|
& { task: (
|
||||||
|
{ __typename?: 'Task' }
|
||||||
|
& Pick<Task, 'id'>
|
||||||
|
& { labels: Array<(
|
||||||
|
{ __typename?: 'TaskLabel' }
|
||||||
|
& Pick<TaskLabel, 'id' | 'assignedDate'>
|
||||||
|
& { projectLabel: (
|
||||||
|
{ __typename?: 'ProjectLabel' }
|
||||||
|
& Pick<ProjectLabel, 'id' | 'createdDate' | 'name'>
|
||||||
|
& { labelColor: (
|
||||||
|
{ __typename?: 'LabelColor' }
|
||||||
|
& Pick<LabelColor, 'id' | 'colorHex' | 'name' | 'position'>
|
||||||
|
) }
|
||||||
|
) }
|
||||||
|
)> }
|
||||||
|
) }
|
||||||
|
) }
|
||||||
|
);
|
||||||
|
|
||||||
export type UnassignTaskMutationVariables = {
|
export type UnassignTaskMutationVariables = {
|
||||||
taskID: Scalars['UUID'];
|
taskID: Scalars['UUID'];
|
||||||
userID: Scalars['UUID'];
|
userID: Scalars['UUID'];
|
||||||
@ -687,6 +778,20 @@ export type UpdateProjectLabelMutation = (
|
|||||||
) }
|
) }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export type UpdateProjectNameMutationVariables = {
|
||||||
|
projectID: Scalars['UUID'];
|
||||||
|
name: Scalars['String'];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type UpdateProjectNameMutation = (
|
||||||
|
{ __typename?: 'Mutation' }
|
||||||
|
& { updateProjectName: (
|
||||||
|
{ __typename?: 'Project' }
|
||||||
|
& Pick<Project, 'id' | 'name'>
|
||||||
|
) }
|
||||||
|
);
|
||||||
|
|
||||||
export type UpdateTaskDescriptionMutationVariables = {
|
export type UpdateTaskDescriptionMutationVariables = {
|
||||||
taskID: Scalars['UUID'];
|
taskID: Scalars['UUID'];
|
||||||
description: Scalars['String'];
|
description: Scalars['String'];
|
||||||
@ -834,6 +939,23 @@ export const CreateTaskDocument = gql`
|
|||||||
description
|
description
|
||||||
taskGroup {
|
taskGroup {
|
||||||
id
|
id
|
||||||
|
name
|
||||||
|
position
|
||||||
|
}
|
||||||
|
labels {
|
||||||
|
id
|
||||||
|
assignedDate
|
||||||
|
projectLabel {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
createdDate
|
||||||
|
labelColor {
|
||||||
|
id
|
||||||
|
colorHex
|
||||||
|
position
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
assigned {
|
assigned {
|
||||||
id
|
id
|
||||||
@ -1032,13 +1154,13 @@ export const FindProjectDocument = gql`
|
|||||||
labels {
|
labels {
|
||||||
id
|
id
|
||||||
createdDate
|
createdDate
|
||||||
|
name
|
||||||
labelColor {
|
labelColor {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
colorHex
|
colorHex
|
||||||
position
|
position
|
||||||
}
|
}
|
||||||
name
|
|
||||||
}
|
}
|
||||||
taskGroups {
|
taskGroups {
|
||||||
id
|
id
|
||||||
@ -1049,6 +1171,26 @@ export const FindProjectDocument = gql`
|
|||||||
name
|
name
|
||||||
position
|
position
|
||||||
description
|
description
|
||||||
|
taskGroup {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
position
|
||||||
|
}
|
||||||
|
labels {
|
||||||
|
id
|
||||||
|
assignedDate
|
||||||
|
projectLabel {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
createdDate
|
||||||
|
labelColor {
|
||||||
|
id
|
||||||
|
colorHex
|
||||||
|
position
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
assigned {
|
assigned {
|
||||||
id
|
id
|
||||||
firstName
|
firstName
|
||||||
@ -1106,6 +1248,21 @@ export const FindTaskDocument = gql`
|
|||||||
taskGroup {
|
taskGroup {
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
labels {
|
||||||
|
id
|
||||||
|
assignedDate
|
||||||
|
projectLabel {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
createdDate
|
||||||
|
labelColor {
|
||||||
|
id
|
||||||
|
colorHex
|
||||||
|
position
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
assigned {
|
assigned {
|
||||||
id
|
id
|
||||||
firstName
|
firstName
|
||||||
@ -1219,6 +1376,57 @@ export function useMeLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptio
|
|||||||
export type MeQueryHookResult = ReturnType<typeof useMeQuery>;
|
export type MeQueryHookResult = ReturnType<typeof useMeQuery>;
|
||||||
export type MeLazyQueryHookResult = ReturnType<typeof useMeLazyQuery>;
|
export type MeLazyQueryHookResult = ReturnType<typeof useMeLazyQuery>;
|
||||||
export type MeQueryResult = ApolloReactCommon.QueryResult<MeQuery, MeQueryVariables>;
|
export type MeQueryResult = ApolloReactCommon.QueryResult<MeQuery, MeQueryVariables>;
|
||||||
|
export const ToggleTaskLabelDocument = gql`
|
||||||
|
mutation toggleTaskLabel($taskID: UUID!, $projectLabelID: UUID!) {
|
||||||
|
toggleTaskLabel(input: {taskID: $taskID, projectLabelID: $projectLabelID}) {
|
||||||
|
active
|
||||||
|
task {
|
||||||
|
id
|
||||||
|
labels {
|
||||||
|
id
|
||||||
|
assignedDate
|
||||||
|
projectLabel {
|
||||||
|
id
|
||||||
|
createdDate
|
||||||
|
labelColor {
|
||||||
|
id
|
||||||
|
colorHex
|
||||||
|
name
|
||||||
|
position
|
||||||
|
}
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
export type ToggleTaskLabelMutationFn = ApolloReactCommon.MutationFunction<ToggleTaskLabelMutation, ToggleTaskLabelMutationVariables>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __useToggleTaskLabelMutation__
|
||||||
|
*
|
||||||
|
* To run a mutation, you first call `useToggleTaskLabelMutation` within a React component and pass it any options that fit your needs.
|
||||||
|
* When your component renders, `useToggleTaskLabelMutation` 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 [toggleTaskLabelMutation, { data, loading, error }] = useToggleTaskLabelMutation({
|
||||||
|
* variables: {
|
||||||
|
* taskID: // value for 'taskID'
|
||||||
|
* projectLabelID: // value for 'projectLabelID'
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
export function useToggleTaskLabelMutation(baseOptions?: ApolloReactHooks.MutationHookOptions<ToggleTaskLabelMutation, ToggleTaskLabelMutationVariables>) {
|
||||||
|
return ApolloReactHooks.useMutation<ToggleTaskLabelMutation, ToggleTaskLabelMutationVariables>(ToggleTaskLabelDocument, baseOptions);
|
||||||
|
}
|
||||||
|
export type ToggleTaskLabelMutationHookResult = ReturnType<typeof useToggleTaskLabelMutation>;
|
||||||
|
export type ToggleTaskLabelMutationResult = ApolloReactCommon.MutationResult<ToggleTaskLabelMutation>;
|
||||||
|
export type ToggleTaskLabelMutationOptions = ApolloReactCommon.BaseMutationOptions<ToggleTaskLabelMutation, ToggleTaskLabelMutationVariables>;
|
||||||
export const UnassignTaskDocument = gql`
|
export const UnassignTaskDocument = gql`
|
||||||
mutation unassignTask($taskID: UUID!, $userID: UUID!) {
|
mutation unassignTask($taskID: UUID!, $userID: UUID!) {
|
||||||
unassignTask(input: {taskID: $taskID, userID: $userID}) {
|
unassignTask(input: {taskID: $taskID, userID: $userID}) {
|
||||||
@ -1299,6 +1507,40 @@ export function useUpdateProjectLabelMutation(baseOptions?: ApolloReactHooks.Mut
|
|||||||
export type UpdateProjectLabelMutationHookResult = ReturnType<typeof useUpdateProjectLabelMutation>;
|
export type UpdateProjectLabelMutationHookResult = ReturnType<typeof useUpdateProjectLabelMutation>;
|
||||||
export type UpdateProjectLabelMutationResult = ApolloReactCommon.MutationResult<UpdateProjectLabelMutation>;
|
export type UpdateProjectLabelMutationResult = ApolloReactCommon.MutationResult<UpdateProjectLabelMutation>;
|
||||||
export type UpdateProjectLabelMutationOptions = ApolloReactCommon.BaseMutationOptions<UpdateProjectLabelMutation, UpdateProjectLabelMutationVariables>;
|
export type UpdateProjectLabelMutationOptions = ApolloReactCommon.BaseMutationOptions<UpdateProjectLabelMutation, UpdateProjectLabelMutationVariables>;
|
||||||
|
export const UpdateProjectNameDocument = gql`
|
||||||
|
mutation updateProjectName($projectID: UUID!, $name: String!) {
|
||||||
|
updateProjectName(input: {projectID: $projectID, name: $name}) {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
export type UpdateProjectNameMutationFn = ApolloReactCommon.MutationFunction<UpdateProjectNameMutation, UpdateProjectNameMutationVariables>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __useUpdateProjectNameMutation__
|
||||||
|
*
|
||||||
|
* To run a mutation, you first call `useUpdateProjectNameMutation` within a React component and pass it any options that fit your needs.
|
||||||
|
* When your component renders, `useUpdateProjectNameMutation` 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 [updateProjectNameMutation, { data, loading, error }] = useUpdateProjectNameMutation({
|
||||||
|
* variables: {
|
||||||
|
* projectID: // value for 'projectID'
|
||||||
|
* name: // value for 'name'
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
export function useUpdateProjectNameMutation(baseOptions?: ApolloReactHooks.MutationHookOptions<UpdateProjectNameMutation, UpdateProjectNameMutationVariables>) {
|
||||||
|
return ApolloReactHooks.useMutation<UpdateProjectNameMutation, UpdateProjectNameMutationVariables>(UpdateProjectNameDocument, baseOptions);
|
||||||
|
}
|
||||||
|
export type UpdateProjectNameMutationHookResult = ReturnType<typeof useUpdateProjectNameMutation>;
|
||||||
|
export type UpdateProjectNameMutationResult = ApolloReactCommon.MutationResult<UpdateProjectNameMutation>;
|
||||||
|
export type UpdateProjectNameMutationOptions = ApolloReactCommon.BaseMutationOptions<UpdateProjectNameMutation, UpdateProjectNameMutationVariables>;
|
||||||
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}) {
|
||||||
|
@ -6,6 +6,23 @@ mutation createTask($taskGroupID: String!, $name: String!, $position: Float!) {
|
|||||||
description
|
description
|
||||||
taskGroup {
|
taskGroup {
|
||||||
id
|
id
|
||||||
|
name
|
||||||
|
position
|
||||||
|
}
|
||||||
|
labels {
|
||||||
|
id
|
||||||
|
assignedDate
|
||||||
|
projectLabel {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
createdDate
|
||||||
|
labelColor {
|
||||||
|
id
|
||||||
|
colorHex
|
||||||
|
position
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
assigned {
|
assigned {
|
||||||
id
|
id
|
||||||
|
@ -14,13 +14,13 @@ query findProject($projectId: String!) {
|
|||||||
labels {
|
labels {
|
||||||
id
|
id
|
||||||
createdDate
|
createdDate
|
||||||
|
name
|
||||||
labelColor {
|
labelColor {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
colorHex
|
colorHex
|
||||||
position
|
position
|
||||||
}
|
}
|
||||||
name
|
|
||||||
}
|
}
|
||||||
taskGroups {
|
taskGroups {
|
||||||
id
|
id
|
||||||
@ -31,6 +31,26 @@ query findProject($projectId: String!) {
|
|||||||
name
|
name
|
||||||
position
|
position
|
||||||
description
|
description
|
||||||
|
taskGroup {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
position
|
||||||
|
}
|
||||||
|
labels {
|
||||||
|
id
|
||||||
|
assignedDate
|
||||||
|
projectLabel {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
createdDate
|
||||||
|
labelColor {
|
||||||
|
id
|
||||||
|
colorHex
|
||||||
|
position
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
assigned {
|
assigned {
|
||||||
id
|
id
|
||||||
firstName
|
firstName
|
||||||
|
@ -7,6 +7,21 @@ query findTask($taskID: UUID!) {
|
|||||||
taskGroup {
|
taskGroup {
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
labels {
|
||||||
|
id
|
||||||
|
assignedDate
|
||||||
|
projectLabel {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
createdDate
|
||||||
|
labelColor {
|
||||||
|
id
|
||||||
|
colorHex
|
||||||
|
position
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
assigned {
|
assigned {
|
||||||
id
|
id
|
||||||
firstName
|
firstName
|
||||||
|
29
web/src/shared/graphql/toggleTaskLabel.graphqls
Normal file
29
web/src/shared/graphql/toggleTaskLabel.graphqls
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
mutation toggleTaskLabel($taskID: UUID!, $projectLabelID: UUID!) {
|
||||||
|
toggleTaskLabel(
|
||||||
|
input: {
|
||||||
|
taskID: $taskID,
|
||||||
|
projectLabelID: $projectLabelID
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
active
|
||||||
|
task {
|
||||||
|
id
|
||||||
|
labels {
|
||||||
|
id
|
||||||
|
assignedDate
|
||||||
|
projectLabel {
|
||||||
|
id
|
||||||
|
createdDate
|
||||||
|
labelColor {
|
||||||
|
id
|
||||||
|
colorHex
|
||||||
|
name
|
||||||
|
position
|
||||||
|
}
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
6
web/src/shared/graphql/updateProjectName.graphqls
Normal file
6
web/src/shared/graphql/updateProjectName.graphqls
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
mutation updateProjectName($projectID: UUID!, $name: String!) {
|
||||||
|
updateProjectName(input: {projectID: $projectID, name: $name}) {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
@ -3,9 +3,17 @@ import React from 'react';
|
|||||||
type Props = {
|
type Props = {
|
||||||
size: number | string;
|
size: number | string;
|
||||||
color: string;
|
color: string;
|
||||||
|
vertical: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const Ellipsis = ({ size, color }: Props) => {
|
const Ellipsis = ({ size, color, vertical }: Props) => {
|
||||||
|
if (vertical) {
|
||||||
|
return (
|
||||||
|
<svg fill={color} xmlns="http://www.w3.org/2000/svg" width={size} height={size} viewBox="0 0 192 512">
|
||||||
|
<path d="M96 184c39.8 0 72 32.2 72 72s-32.2 72-72 72-72-32.2-72-72 32.2-72 72-72zM24 80c0 39.8 32.2 72 72 72s72-32.2 72-72S135.8 8 96 8 24 40.2 24 80zm0 352c0 39.8 32.2 72 72 72s72-32.2 72-72-32.2-72-72-72-72 32.2-72 72z" />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<svg fill={color} xmlns="http://www.w3.org/2000/svg" width={size} height={size} viewBox="0 0 512 512">
|
<svg fill={color} xmlns="http://www.w3.org/2000/svg" width={size} height={size} viewBox="0 0 512 512">
|
||||||
<path d="M328 256c0 39.8-32.2 72-72 72s-72-32.2-72-72 32.2-72 72-72 72 32.2 72 72zm104-72c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72zm-352 0c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72z" />
|
<path d="M328 256c0 39.8-32.2 72-72 72s-72-32.2-72-72 32.2-72 72-72 72 32.2 72 72zm104-72c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72zm-352 0c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72z" />
|
||||||
@ -16,6 +24,7 @@ const Ellipsis = ({ size, color }: Props) => {
|
|||||||
Ellipsis.defaultProps = {
|
Ellipsis.defaultProps = {
|
||||||
size: 16,
|
size: 16,
|
||||||
color: '#000',
|
color: '#000',
|
||||||
|
vertical: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Ellipsis;
|
export default Ellipsis;
|
||||||
|
@ -1,50 +0,0 @@
|
|||||||
import produce from 'immer';
|
|
||||||
|
|
||||||
export const addTask = (currentState: BoardState, newTask: Task) => {
|
|
||||||
return produce(currentState, (draftState: BoardState) => {
|
|
||||||
draftState.tasks[newTask.taskID] = newTask;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const deleteTask = (currentState: BoardState, taskID: string) => {
|
|
||||||
return produce(currentState, (draftState: BoardState) => {
|
|
||||||
delete draftState.tasks[taskID];
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const addTaskGroup = (currentState: BoardState, newTaskGroup: TaskGroup) => {
|
|
||||||
return produce(currentState, (draftState: BoardState) => {
|
|
||||||
draftState.columns[newTaskGroup.taskGroupID] = newTaskGroup;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const updateTaskGroup = (currentState: BoardState, newTaskGroup: TaskGroup) => {
|
|
||||||
return produce(currentState, (draftState: BoardState) => {
|
|
||||||
draftState.columns[newTaskGroup.taskGroupID] = newTaskGroup;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const updateTask = (currentState: BoardState, newTask: Task) => {
|
|
||||||
return produce(currentState, (draftState: BoardState) => {
|
|
||||||
draftState.tasks[newTask.taskID] = newTask;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const deleteTaskGroup = (currentState: BoardState, deletedTaskGroupID: string) => {
|
|
||||||
return produce(currentState, (draftState: BoardState) => {
|
|
||||||
delete draftState.columns[deletedTaskGroupID];
|
|
||||||
const filteredTasks = Object.keys(currentState.tasks)
|
|
||||||
.filter(taskID => currentState.tasks[taskID].taskGroup.taskGroupID !== deletedTaskGroupID)
|
|
||||||
.reduce((obj: TaskState, key: string) => {
|
|
||||||
obj[key] = currentState.tasks[key];
|
|
||||||
return obj;
|
|
||||||
}, {});
|
|
||||||
draftState.tasks = filteredTasks;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const updateTaskName = (currentState: BoardState, taskID: string, newName: string) => {
|
|
||||||
return produce(currentState, (draftState: BoardState) => {
|
|
||||||
draftState.tasks[taskID].name = newName;
|
|
||||||
});
|
|
||||||
};
|
|
Loading…
Reference in New Issue
Block a user