feature: add checklist
This commit is contained in:
		
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -19,10 +19,36 @@ type AssignTaskInput struct {
 | 
				
			|||||||
	UserID uuid.UUID `json:"userID"`
 | 
						UserID uuid.UUID `json:"userID"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ChecklistBadge struct {
 | 
				
			||||||
 | 
						Complete int `json:"complete"`
 | 
				
			||||||
 | 
						Total    int `json:"total"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type CreateTaskChecklist struct {
 | 
				
			||||||
 | 
						TaskID   uuid.UUID `json:"taskID"`
 | 
				
			||||||
 | 
						Name     string    `json:"name"`
 | 
				
			||||||
 | 
						Position float64   `json:"position"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type CreateTaskChecklistItem struct {
 | 
				
			||||||
 | 
						TaskChecklistID uuid.UUID `json:"taskChecklistID"`
 | 
				
			||||||
 | 
						Name            string    `json:"name"`
 | 
				
			||||||
 | 
						Position        float64   `json:"position"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type DeleteProjectLabel struct {
 | 
					type DeleteProjectLabel struct {
 | 
				
			||||||
	ProjectLabelID uuid.UUID `json:"projectLabelID"`
 | 
						ProjectLabelID uuid.UUID `json:"projectLabelID"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type DeleteTaskChecklistItem struct {
 | 
				
			||||||
 | 
						TaskChecklistItemID uuid.UUID `json:"taskChecklistItemID"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type DeleteTaskChecklistItemPayload struct {
 | 
				
			||||||
 | 
						Ok                bool                  `json:"ok"`
 | 
				
			||||||
 | 
						TaskChecklistItem *pg.TaskChecklistItem `json:"taskChecklistItem"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type DeleteTaskGroupInput struct {
 | 
					type DeleteTaskGroupInput struct {
 | 
				
			||||||
	TaskGroupID uuid.UUID `json:"taskGroupID"`
 | 
						TaskGroupID uuid.UUID `json:"taskGroupID"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -129,6 +155,20 @@ type RemoveTaskLabelInput struct {
 | 
				
			|||||||
	TaskLabelID uuid.UUID `json:"taskLabelID"`
 | 
						TaskLabelID uuid.UUID `json:"taskLabelID"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type SetTaskChecklistItemComplete struct {
 | 
				
			||||||
 | 
						TaskChecklistItemID uuid.UUID `json:"taskChecklistItemID"`
 | 
				
			||||||
 | 
						Complete            bool      `json:"complete"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type SetTaskComplete struct {
 | 
				
			||||||
 | 
						TaskID   uuid.UUID `json:"taskID"`
 | 
				
			||||||
 | 
						Complete bool      `json:"complete"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type TaskBadges struct {
 | 
				
			||||||
 | 
						Checklist *ChecklistBadge `json:"checklist"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type ToggleTaskLabelInput struct {
 | 
					type ToggleTaskLabelInput struct {
 | 
				
			||||||
	TaskID         uuid.UUID `json:"taskID"`
 | 
						TaskID         uuid.UUID `json:"taskID"`
 | 
				
			||||||
	ProjectLabelID uuid.UUID `json:"projectLabelID"`
 | 
						ProjectLabelID uuid.UUID `json:"projectLabelID"`
 | 
				
			||||||
@@ -165,6 +205,11 @@ type UpdateProjectName struct {
 | 
				
			|||||||
	Name      string    `json:"name"`
 | 
						Name      string    `json:"name"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type UpdateTaskChecklistItemName struct {
 | 
				
			||||||
 | 
						TaskChecklistItemID uuid.UUID `json:"taskChecklistItemID"`
 | 
				
			||||||
 | 
						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"`
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -77,6 +77,15 @@ type TaskGroup {
 | 
				
			|||||||
  tasks: [Task!]!
 | 
					  tasks: [Task!]!
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ChecklistBadge {
 | 
				
			||||||
 | 
					  complete: Int!
 | 
				
			||||||
 | 
					  total: Int!
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type TaskBadges {
 | 
				
			||||||
 | 
					  checklist: ChecklistBadge
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Task {
 | 
					type Task {
 | 
				
			||||||
  id: ID!
 | 
					  id: ID!
 | 
				
			||||||
  taskGroup: TaskGroup!
 | 
					  taskGroup: TaskGroup!
 | 
				
			||||||
@@ -85,8 +94,11 @@ type Task {
 | 
				
			|||||||
  position: Float!
 | 
					  position: Float!
 | 
				
			||||||
  description: String
 | 
					  description: String
 | 
				
			||||||
  dueDate: Time
 | 
					  dueDate: Time
 | 
				
			||||||
 | 
					  complete: Boolean!
 | 
				
			||||||
  assigned: [ProjectMember!]!
 | 
					  assigned: [ProjectMember!]!
 | 
				
			||||||
  labels: [TaskLabel!]!
 | 
					  labels: [TaskLabel!]!
 | 
				
			||||||
 | 
					  checklists: [TaskChecklist!]!
 | 
				
			||||||
 | 
					  badges: TaskBadges!
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
input ProjectsFilter {
 | 
					input ProjectsFilter {
 | 
				
			||||||
@@ -188,6 +200,27 @@ type DeleteTaskGroupPayload {
 | 
				
			|||||||
  taskGroup: TaskGroup!
 | 
					  taskGroup: TaskGroup!
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type DeleteTaskChecklistItemPayload {
 | 
				
			||||||
 | 
					  ok: Boolean!
 | 
				
			||||||
 | 
					  taskChecklistItem: TaskChecklistItem!
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type TaskChecklistItem {
 | 
				
			||||||
 | 
					  id: ID!
 | 
				
			||||||
 | 
					  name: String!
 | 
				
			||||||
 | 
					  taskChecklistID: UUID!
 | 
				
			||||||
 | 
					  complete: Boolean!
 | 
				
			||||||
 | 
					  position: Float!
 | 
				
			||||||
 | 
					  dueDate: Time!
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type TaskChecklist {
 | 
				
			||||||
 | 
					  id: ID!
 | 
				
			||||||
 | 
					  name: String!
 | 
				
			||||||
 | 
					  position: Float!
 | 
				
			||||||
 | 
					  items: [TaskChecklistItem!]!
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
input AssignTaskInput {
 | 
					input AssignTaskInput {
 | 
				
			||||||
  taskID: UUID!
 | 
					  taskID: UUID!
 | 
				
			||||||
  userID: UUID!
 | 
					  userID: UUID!
 | 
				
			||||||
@@ -267,6 +300,36 @@ input UpdateTaskDueDate  {
 | 
				
			|||||||
  dueDate: Time
 | 
					  dueDate: Time
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					input SetTaskComplete {
 | 
				
			||||||
 | 
					  taskID: UUID!
 | 
				
			||||||
 | 
					  complete: Boolean!
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					input CreateTaskChecklist {
 | 
				
			||||||
 | 
					  taskID: UUID!
 | 
				
			||||||
 | 
					  name: String!
 | 
				
			||||||
 | 
					  position: Float!
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					input CreateTaskChecklistItem {
 | 
				
			||||||
 | 
					  taskChecklistID: UUID!
 | 
				
			||||||
 | 
					  name: String!
 | 
				
			||||||
 | 
					  position: Float!
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					input SetTaskChecklistItemComplete {
 | 
				
			||||||
 | 
					  taskChecklistItemID: UUID!
 | 
				
			||||||
 | 
					  complete: Boolean!
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					input DeleteTaskChecklistItem {
 | 
				
			||||||
 | 
					  taskChecklistItemID: UUID!
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					input UpdateTaskChecklistItemName {
 | 
				
			||||||
 | 
					  taskChecklistItemID: UUID!
 | 
				
			||||||
 | 
					  name: String!
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Mutation {
 | 
					type Mutation {
 | 
				
			||||||
  createRefreshToken(input: NewRefreshToken!): RefreshToken!
 | 
					  createRefreshToken(input: NewRefreshToken!): RefreshToken!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -293,10 +356,17 @@ type Mutation {
 | 
				
			|||||||
  removeTaskLabel(input: RemoveTaskLabelInput): Task!
 | 
					  removeTaskLabel(input: RemoveTaskLabelInput): Task!
 | 
				
			||||||
  toggleTaskLabel(input: ToggleTaskLabelInput!): ToggleTaskLabelPayload!
 | 
					  toggleTaskLabel(input: ToggleTaskLabelInput!): ToggleTaskLabelPayload!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  createTaskChecklist(input: CreateTaskChecklist!): TaskChecklist!
 | 
				
			||||||
 | 
					  createTaskChecklistItem(input: CreateTaskChecklistItem!): TaskChecklistItem!
 | 
				
			||||||
 | 
					  updateTaskChecklistItemName(input: UpdateTaskChecklistItemName!): TaskChecklistItem!
 | 
				
			||||||
 | 
					  setTaskChecklistItemComplete(input: SetTaskChecklistItemComplete!): TaskChecklistItem!
 | 
				
			||||||
 | 
					  deleteTaskChecklistItem(input: DeleteTaskChecklistItem!): DeleteTaskChecklistItemPayload!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  createTask(input: NewTask!): Task!
 | 
					  createTask(input: NewTask!): Task!
 | 
				
			||||||
  updateTaskDescription(input: UpdateTaskDescriptionInput!): Task!
 | 
					  updateTaskDescription(input: UpdateTaskDescriptionInput!): Task!
 | 
				
			||||||
  updateTaskLocation(input: NewTaskLocation!): UpdateTaskLocationPayload!
 | 
					  updateTaskLocation(input: NewTaskLocation!): UpdateTaskLocationPayload!
 | 
				
			||||||
  updateTaskName(input: UpdateTaskName!): Task!
 | 
					  updateTaskName(input: UpdateTaskName!): Task!
 | 
				
			||||||
 | 
					  setTaskComplete(input: SetTaskComplete!): Task!
 | 
				
			||||||
  updateTaskDueDate(input: UpdateTaskDueDate!): Task!
 | 
					  updateTaskDueDate(input: UpdateTaskDueDate!): Task!
 | 
				
			||||||
  deleteTask(input: DeleteTaskInput!): DeleteTaskPayload!
 | 
					  deleteTask(input: DeleteTaskInput!): DeleteTaskPayload!
 | 
				
			||||||
  assignTask(input: AssignTaskInput): Task!
 | 
					  assignTask(input: AssignTaskInput): Task!
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -143,7 +143,11 @@ func (r *mutationResolver) UpdateTaskGroupLocation(ctx context.Context, input Ne
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (r *mutationResolver) UpdateTaskGroupName(ctx context.Context, input UpdateTaskGroupName) (*pg.TaskGroup, error) {
 | 
					func (r *mutationResolver) UpdateTaskGroupName(ctx context.Context, input UpdateTaskGroupName) (*pg.TaskGroup, error) {
 | 
				
			||||||
	panic(fmt.Errorf("not implemented"))
 | 
						taskGroup, err := r.Repository.SetTaskGroupName(ctx, pg.SetTaskGroupNameParams{TaskGroupID: input.TaskGroupID, Name: input.Name})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return &pg.TaskGroup{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &taskGroup, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (r *mutationResolver) DeleteTaskGroup(ctx context.Context, input DeleteTaskGroupInput) (*DeleteTaskGroupPayload, error) {
 | 
					func (r *mutationResolver) DeleteTaskGroup(ctx context.Context, input DeleteTaskGroupInput) (*DeleteTaskGroupPayload, error) {
 | 
				
			||||||
@@ -225,6 +229,75 @@ func (r *mutationResolver) ToggleTaskLabel(ctx context.Context, input ToggleTask
 | 
				
			|||||||
	return &payload, nil
 | 
						return &payload, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (r *mutationResolver) CreateTaskChecklist(ctx context.Context, input CreateTaskChecklist) (*pg.TaskChecklist, error) {
 | 
				
			||||||
 | 
						createdAt := time.Now().UTC()
 | 
				
			||||||
 | 
						taskChecklist, err := r.Repository.CreateTaskChecklist(ctx, pg.CreateTaskChecklistParams{
 | 
				
			||||||
 | 
							TaskID:    input.TaskID,
 | 
				
			||||||
 | 
							CreatedAt: createdAt,
 | 
				
			||||||
 | 
							Name:      input.Name,
 | 
				
			||||||
 | 
							Position:  input.Position,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return &pg.TaskChecklist{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &taskChecklist, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (r *mutationResolver) CreateTaskChecklistItem(ctx context.Context, input CreateTaskChecklistItem) (*pg.TaskChecklistItem, error) {
 | 
				
			||||||
 | 
						createdAt := time.Now().UTC()
 | 
				
			||||||
 | 
						taskChecklistItem, err := r.Repository.CreateTaskChecklistItem(ctx, pg.CreateTaskChecklistItemParams{
 | 
				
			||||||
 | 
							TaskChecklistID: input.TaskChecklistID,
 | 
				
			||||||
 | 
							CreatedAt:       createdAt,
 | 
				
			||||||
 | 
							Name:            input.Name,
 | 
				
			||||||
 | 
							Position:        input.Position,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return &pg.TaskChecklistItem{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &taskChecklistItem, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (r *mutationResolver) UpdateTaskChecklistItemName(ctx context.Context, input UpdateTaskChecklistItemName) (*pg.TaskChecklistItem, error) {
 | 
				
			||||||
 | 
						task, err := r.Repository.UpdateTaskChecklistItemName(ctx, pg.UpdateTaskChecklistItemNameParams{TaskChecklistItemID: input.TaskChecklistItemID,
 | 
				
			||||||
 | 
							Name: input.Name,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return &pg.TaskChecklistItem{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &task, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (r *mutationResolver) SetTaskChecklistItemComplete(ctx context.Context, input SetTaskChecklistItemComplete) (*pg.TaskChecklistItem, error) {
 | 
				
			||||||
 | 
						item, err := r.Repository.SetTaskChecklistItemComplete(ctx, pg.SetTaskChecklistItemCompleteParams{TaskChecklistItemID: input.TaskChecklistItemID, Complete: input.Complete})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return &pg.TaskChecklistItem{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &item, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (r *mutationResolver) DeleteTaskChecklistItem(ctx context.Context, input DeleteTaskChecklistItem) (*DeleteTaskChecklistItemPayload, error) {
 | 
				
			||||||
 | 
						item, err := r.Repository.GetTaskChecklistItemByID(ctx, input.TaskChecklistItemID)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return &DeleteTaskChecklistItemPayload{
 | 
				
			||||||
 | 
								Ok:                false,
 | 
				
			||||||
 | 
								TaskChecklistItem: &pg.TaskChecklistItem{},
 | 
				
			||||||
 | 
							}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						err = r.Repository.DeleteTaskChecklistItem(ctx, input.TaskChecklistItemID)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return &DeleteTaskChecklistItemPayload{
 | 
				
			||||||
 | 
								Ok:                false,
 | 
				
			||||||
 | 
								TaskChecklistItem: &pg.TaskChecklistItem{},
 | 
				
			||||||
 | 
							}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &DeleteTaskChecklistItemPayload{
 | 
				
			||||||
 | 
							Ok:                true,
 | 
				
			||||||
 | 
							TaskChecklistItem: &item,
 | 
				
			||||||
 | 
						}, err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (r *mutationResolver) CreateTask(ctx context.Context, input NewTask) (*pg.Task, error) {
 | 
					func (r *mutationResolver) CreateTask(ctx context.Context, input NewTask) (*pg.Task, error) {
 | 
				
			||||||
	taskGroupID, err := uuid.Parse(input.TaskGroupID)
 | 
						taskGroupID, err := uuid.Parse(input.TaskGroupID)
 | 
				
			||||||
	createdAt := time.Now().UTC()
 | 
						createdAt := time.Now().UTC()
 | 
				
			||||||
@@ -260,6 +333,14 @@ func (r *mutationResolver) UpdateTaskName(ctx context.Context, input UpdateTaskN
 | 
				
			|||||||
	return &task, err
 | 
						return &task, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (r *mutationResolver) SetTaskComplete(ctx context.Context, input SetTaskComplete) (*pg.Task, error) {
 | 
				
			||||||
 | 
						task, err := r.Repository.SetTaskComplete(ctx, pg.SetTaskCompleteParams{TaskID: input.TaskID, Complete: input.Complete})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return &pg.Task{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &task, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (r *mutationResolver) UpdateTaskDueDate(ctx context.Context, input UpdateTaskDueDate) (*pg.Task, error) {
 | 
					func (r *mutationResolver) UpdateTaskDueDate(ctx context.Context, input UpdateTaskDueDate) (*pg.Task, error) {
 | 
				
			||||||
	var dueDate sql.NullTime
 | 
						var dueDate sql.NullTime
 | 
				
			||||||
	if input.DueDate == nil {
 | 
						if input.DueDate == nil {
 | 
				
			||||||
@@ -531,6 +612,51 @@ func (r *taskResolver) Labels(ctx context.Context, obj *pg.Task) ([]pg.TaskLabel
 | 
				
			|||||||
	return r.Repository.GetTaskLabelsForTaskID(ctx, obj.TaskID)
 | 
						return r.Repository.GetTaskLabelsForTaskID(ctx, obj.TaskID)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (r *taskResolver) Checklists(ctx context.Context, obj *pg.Task) ([]pg.TaskChecklist, error) {
 | 
				
			||||||
 | 
						return r.Repository.GetTaskChecklistsForTask(ctx, obj.TaskID)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (r *taskResolver) Badges(ctx context.Context, obj *pg.Task) (*TaskBadges, error) {
 | 
				
			||||||
 | 
						checklists, err := r.Repository.GetTaskChecklistsForTask(ctx, obj.TaskID)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return &TaskBadges{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(checklists) == 0 {
 | 
				
			||||||
 | 
							return &TaskBadges{Checklist: nil}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						complete := 0
 | 
				
			||||||
 | 
						total := 0
 | 
				
			||||||
 | 
						for _, checklist := range checklists {
 | 
				
			||||||
 | 
							items, err := r.Repository.GetTaskChecklistItemsForTaskChecklist(ctx, checklist.TaskChecklistID)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return &TaskBadges{}, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							for _, item := range items {
 | 
				
			||||||
 | 
								total += 1
 | 
				
			||||||
 | 
								if item.Complete {
 | 
				
			||||||
 | 
									complete += 1
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &TaskBadges{Checklist: &ChecklistBadge{Total: total, Complete: complete}}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (r *taskChecklistResolver) ID(ctx context.Context, obj *pg.TaskChecklist) (uuid.UUID, error) {
 | 
				
			||||||
 | 
						return obj.TaskChecklistID, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (r *taskChecklistResolver) Items(ctx context.Context, obj *pg.TaskChecklist) ([]pg.TaskChecklistItem, error) {
 | 
				
			||||||
 | 
						return r.Repository.GetTaskChecklistItemsForTaskChecklist(ctx, obj.TaskChecklistID)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (r *taskChecklistItemResolver) ID(ctx context.Context, obj *pg.TaskChecklistItem) (uuid.UUID, error) {
 | 
				
			||||||
 | 
						return obj.TaskChecklistItemID, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (r *taskChecklistItemResolver) DueDate(ctx context.Context, obj *pg.TaskChecklistItem) (*time.Time, error) {
 | 
				
			||||||
 | 
						panic(fmt.Errorf("not implemented"))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (r *taskGroupResolver) ID(ctx context.Context, obj *pg.TaskGroup) (uuid.UUID, error) {
 | 
					func (r *taskGroupResolver) ID(ctx context.Context, obj *pg.TaskGroup) (uuid.UUID, error) {
 | 
				
			||||||
	return obj.TaskGroupID, nil
 | 
						return obj.TaskGroupID, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -591,6 +717,12 @@ func (r *Resolver) RefreshToken() RefreshTokenResolver { return &refreshTokenRes
 | 
				
			|||||||
// Task returns TaskResolver implementation.
 | 
					// Task returns TaskResolver implementation.
 | 
				
			||||||
func (r *Resolver) Task() TaskResolver { return &taskResolver{r} }
 | 
					func (r *Resolver) Task() TaskResolver { return &taskResolver{r} }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TaskChecklist returns TaskChecklistResolver implementation.
 | 
				
			||||||
 | 
					func (r *Resolver) TaskChecklist() TaskChecklistResolver { return &taskChecklistResolver{r} }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TaskChecklistItem returns TaskChecklistItemResolver implementation.
 | 
				
			||||||
 | 
					func (r *Resolver) TaskChecklistItem() TaskChecklistItemResolver { return &taskChecklistItemResolver{r} }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TaskGroup returns TaskGroupResolver implementation.
 | 
					// TaskGroup returns TaskGroupResolver implementation.
 | 
				
			||||||
func (r *Resolver) TaskGroup() TaskGroupResolver { return &taskGroupResolver{r} }
 | 
					func (r *Resolver) TaskGroup() TaskGroupResolver { return &taskGroupResolver{r} }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -610,6 +742,8 @@ type projectLabelResolver struct{ *Resolver }
 | 
				
			|||||||
type queryResolver struct{ *Resolver }
 | 
					type queryResolver struct{ *Resolver }
 | 
				
			||||||
type refreshTokenResolver struct{ *Resolver }
 | 
					type refreshTokenResolver struct{ *Resolver }
 | 
				
			||||||
type taskResolver struct{ *Resolver }
 | 
					type taskResolver struct{ *Resolver }
 | 
				
			||||||
 | 
					type taskChecklistResolver struct{ *Resolver }
 | 
				
			||||||
 | 
					type taskChecklistItemResolver struct{ *Resolver }
 | 
				
			||||||
type taskGroupResolver struct{ *Resolver }
 | 
					type taskGroupResolver struct{ *Resolver }
 | 
				
			||||||
type taskLabelResolver struct{ *Resolver }
 | 
					type taskLabelResolver struct{ *Resolver }
 | 
				
			||||||
type teamResolver struct{ *Resolver }
 | 
					type teamResolver struct{ *Resolver }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					ALTER TABLE task_label DROP CONSTRAINT task_label_task_id_fkey;
 | 
				
			||||||
 | 
					ALTER TABLE task_label
 | 
				
			||||||
 | 
					  ADD CONSTRAINT task_label_task_id_fkey
 | 
				
			||||||
 | 
					  FOREIGN KEY (task_id)
 | 
				
			||||||
 | 
					  REFERENCES task(task_id)
 | 
				
			||||||
 | 
					  ON DELETE CASCADE;
 | 
				
			||||||
@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					ALTER TABLE task_assigned DROP CONSTRAINT task_assigned_task_id_fkey;
 | 
				
			||||||
 | 
					ALTER TABLE task_assigned
 | 
				
			||||||
 | 
					  ADD CONSTRAINT task_assigned_task_id_fkey
 | 
				
			||||||
 | 
					  FOREIGN KEY (task_id)
 | 
				
			||||||
 | 
					  REFERENCES task(task_id)
 | 
				
			||||||
 | 
					  ON DELETE CASCADE;
 | 
				
			||||||
@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					ALTER TABLE task DROP CONSTRAINT task_task_group_id_fkey;
 | 
				
			||||||
 | 
					ALTER TABLE task
 | 
				
			||||||
 | 
					  ADD CONSTRAINT task_task_group_id_fkey
 | 
				
			||||||
 | 
					  FOREIGN KEY (task_group_id)
 | 
				
			||||||
 | 
					  REFERENCES task_group(task_group_id)
 | 
				
			||||||
 | 
					  ON DELETE CASCADE;
 | 
				
			||||||
@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					ALTER TABLE task ADD COLUMN complete boolean NOT NULL DEFAULT FALSE;
 | 
				
			||||||
							
								
								
									
										7
									
								
								api/migrations/0029_add-task_checklist.up.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								api/migrations/0029_add-task_checklist.up.sql
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					CREATE TABLE task_checklist (
 | 
				
			||||||
 | 
					  task_checklist_id uuid PRIMARY KEY DEFAULT uuid_generate_v4(),
 | 
				
			||||||
 | 
					  task_id uuid NOT NULL REFERENCES task(task_id) ON DELETE CASCADE,
 | 
				
			||||||
 | 
					  created_at timestamptz NOT NULL,
 | 
				
			||||||
 | 
					  name text NOT NULL,
 | 
				
			||||||
 | 
					  position float NOT NULL
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
							
								
								
									
										9
									
								
								api/migrations/0030_add-task_checklist_item.up.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								api/migrations/0030_add-task_checklist_item.up.sql
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					CREATE TABLE task_checklist_item (
 | 
				
			||||||
 | 
					  task_checklist_item_id uuid PRIMARY KEY DEFAULT uuid_generate_v4(),
 | 
				
			||||||
 | 
					  task_checklist_id uuid NOT NULL REFERENCES task_checklist(task_checklist_id) ON DELETE CASCADE,
 | 
				
			||||||
 | 
					  created_at timestamptz NOT NULL,
 | 
				
			||||||
 | 
					  complete boolean NOT NULL DEFAULT false,
 | 
				
			||||||
 | 
					  name text NOT NULL,
 | 
				
			||||||
 | 
					  position float NOT NULL,
 | 
				
			||||||
 | 
					  due_date timestamptz
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
@@ -53,6 +53,7 @@ type Task struct {
 | 
				
			|||||||
	Position    float64        `json:"position"`
 | 
						Position    float64        `json:"position"`
 | 
				
			||||||
	Description sql.NullString `json:"description"`
 | 
						Description sql.NullString `json:"description"`
 | 
				
			||||||
	DueDate     sql.NullTime   `json:"due_date"`
 | 
						DueDate     sql.NullTime   `json:"due_date"`
 | 
				
			||||||
 | 
						Complete    bool           `json:"complete"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type TaskAssigned struct {
 | 
					type TaskAssigned struct {
 | 
				
			||||||
@@ -62,6 +63,24 @@ type TaskAssigned struct {
 | 
				
			|||||||
	AssignedDate   time.Time `json:"assigned_date"`
 | 
						AssignedDate   time.Time `json:"assigned_date"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type TaskChecklist struct {
 | 
				
			||||||
 | 
						TaskChecklistID uuid.UUID `json:"task_checklist_id"`
 | 
				
			||||||
 | 
						TaskID          uuid.UUID `json:"task_id"`
 | 
				
			||||||
 | 
						CreatedAt       time.Time `json:"created_at"`
 | 
				
			||||||
 | 
						Name            string    `json:"name"`
 | 
				
			||||||
 | 
						Position        float64   `json:"position"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type TaskChecklistItem struct {
 | 
				
			||||||
 | 
						TaskChecklistItemID uuid.UUID    `json:"task_checklist_item_id"`
 | 
				
			||||||
 | 
						TaskChecklistID     uuid.UUID    `json:"task_checklist_id"`
 | 
				
			||||||
 | 
						CreatedAt           time.Time    `json:"created_at"`
 | 
				
			||||||
 | 
						Complete            bool         `json:"complete"`
 | 
				
			||||||
 | 
						Name                string       `json:"name"`
 | 
				
			||||||
 | 
						Position            float64      `json:"position"`
 | 
				
			||||||
 | 
						DueDate             sql.NullTime `json:"due_date"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type TaskGroup struct {
 | 
					type TaskGroup struct {
 | 
				
			||||||
	TaskGroupID uuid.UUID `json:"task_group_id"`
 | 
						TaskGroupID uuid.UUID `json:"task_group_id"`
 | 
				
			||||||
	ProjectID   uuid.UUID `json:"project_id"`
 | 
						ProjectID   uuid.UUID `json:"project_id"`
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										12
									
								
								api/pg/pg.go
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								api/pg/pg.go
									
									
									
									
									
								
							@@ -17,7 +17,17 @@ type Repository interface {
 | 
				
			|||||||
	GetAllProjectsForTeam(ctx context.Context, teamID uuid.UUID) ([]Project, error)
 | 
						GetAllProjectsForTeam(ctx context.Context, teamID uuid.UUID) ([]Project, error)
 | 
				
			||||||
	GetProjectByID(ctx context.Context, projectID uuid.UUID) (Project, error)
 | 
						GetProjectByID(ctx context.Context, projectID uuid.UUID) (Project, error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						UpdateTaskChecklistItemName(ctx context.Context, arg UpdateTaskChecklistItemNameParams) (TaskChecklistItem, error)
 | 
				
			||||||
 | 
						GetTaskChecklistItemByID(ctx context.Context, taskChecklistItemID uuid.UUID) (TaskChecklistItem, error)
 | 
				
			||||||
 | 
						CreateTaskChecklist(ctx context.Context, arg CreateTaskChecklistParams) (TaskChecklist, error)
 | 
				
			||||||
 | 
						CreateTaskChecklistItem(ctx context.Context, arg CreateTaskChecklistItemParams) (TaskChecklistItem, error)
 | 
				
			||||||
 | 
						GetTaskChecklistItemsForTaskChecklist(ctx context.Context, taskChecklistID uuid.UUID) ([]TaskChecklistItem, error)
 | 
				
			||||||
 | 
						GetTaskChecklistsForTask(ctx context.Context, taskID uuid.UUID) ([]TaskChecklist, error)
 | 
				
			||||||
 | 
						SetTaskChecklistItemComplete(ctx context.Context, arg SetTaskChecklistItemCompleteParams) (TaskChecklistItem, error)
 | 
				
			||||||
 | 
						DeleteTaskChecklistItem(ctx context.Context, taskChecklistItemID uuid.UUID) error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	UpdateUserAccountProfileAvatarURL(ctx context.Context, arg UpdateUserAccountProfileAvatarURLParams) (UserAccount, error)
 | 
						UpdateUserAccountProfileAvatarURL(ctx context.Context, arg UpdateUserAccountProfileAvatarURLParams) (UserAccount, error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	CreateUserAccount(ctx context.Context, arg CreateUserAccountParams) (UserAccount, error)
 | 
						CreateUserAccount(ctx context.Context, arg CreateUserAccountParams) (UserAccount, error)
 | 
				
			||||||
	GetUserAccountByID(ctx context.Context, userID uuid.UUID) (UserAccount, error)
 | 
						GetUserAccountByID(ctx context.Context, userID uuid.UUID) (UserAccount, error)
 | 
				
			||||||
	GetUserAccountByUsername(ctx context.Context, username string) (UserAccount, error)
 | 
						GetUserAccountByUsername(ctx context.Context, username string) (UserAccount, error)
 | 
				
			||||||
@@ -25,6 +35,7 @@ type Repository interface {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	GetTaskLabelByID(ctx context.Context, taskLabelID uuid.UUID) (TaskLabel, error)
 | 
						GetTaskLabelByID(ctx context.Context, taskLabelID uuid.UUID) (TaskLabel, error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						SetTaskComplete(ctx context.Context, arg SetTaskCompleteParams) (Task, error)
 | 
				
			||||||
	DeleteTaskLabelForTaskByProjectLabelID(ctx context.Context, arg DeleteTaskLabelForTaskByProjectLabelIDParams) error
 | 
						DeleteTaskLabelForTaskByProjectLabelID(ctx context.Context, arg DeleteTaskLabelForTaskByProjectLabelIDParams) error
 | 
				
			||||||
	GetTaskLabelForTaskByProjectLabelID(ctx context.Context, arg GetTaskLabelForTaskByProjectLabelIDParams) (TaskLabel, error)
 | 
						GetTaskLabelForTaskByProjectLabelID(ctx context.Context, arg GetTaskLabelForTaskByProjectLabelIDParams) (TaskLabel, error)
 | 
				
			||||||
	UpdateProjectNameByID(ctx context.Context, arg UpdateProjectNameByIDParams) (Project, error)
 | 
						UpdateProjectNameByID(ctx context.Context, arg UpdateProjectNameByIDParams) (Project, error)
 | 
				
			||||||
@@ -47,6 +58,7 @@ type Repository interface {
 | 
				
			|||||||
	DeleteRefreshTokenByID(ctx context.Context, tokenID uuid.UUID) error
 | 
						DeleteRefreshTokenByID(ctx context.Context, tokenID uuid.UUID) error
 | 
				
			||||||
	DeleteRefreshTokenByUserID(ctx context.Context, userID uuid.UUID) error
 | 
						DeleteRefreshTokenByUserID(ctx context.Context, userID uuid.UUID) error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						SetTaskGroupName(ctx context.Context, arg SetTaskGroupNameParams) (TaskGroup, error)
 | 
				
			||||||
	DeleteTaskGroupByID(ctx context.Context, taskGroupID uuid.UUID) (int64, error)
 | 
						DeleteTaskGroupByID(ctx context.Context, taskGroupID uuid.UUID) (int64, error)
 | 
				
			||||||
	DeleteTasksByTaskGroupID(ctx context.Context, taskGroupID uuid.UUID) (int64, error)
 | 
						DeleteTasksByTaskGroupID(ctx context.Context, taskGroupID uuid.UUID) (int64, error)
 | 
				
			||||||
	UpdateTaskGroupLocation(ctx context.Context, arg UpdateTaskGroupLocationParams) (TaskGroup, error)
 | 
						UpdateTaskGroupLocation(ctx context.Context, arg UpdateTaskGroupLocationParams) (TaskGroup, error)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,6 +16,8 @@ type Querier interface {
 | 
				
			|||||||
	CreateRefreshToken(ctx context.Context, arg CreateRefreshTokenParams) (RefreshToken, error)
 | 
						CreateRefreshToken(ctx context.Context, arg CreateRefreshTokenParams) (RefreshToken, error)
 | 
				
			||||||
	CreateTask(ctx context.Context, arg CreateTaskParams) (Task, error)
 | 
						CreateTask(ctx context.Context, arg CreateTaskParams) (Task, error)
 | 
				
			||||||
	CreateTaskAssigned(ctx context.Context, arg CreateTaskAssignedParams) (TaskAssigned, error)
 | 
						CreateTaskAssigned(ctx context.Context, arg CreateTaskAssignedParams) (TaskAssigned, error)
 | 
				
			||||||
 | 
						CreateTaskChecklist(ctx context.Context, arg CreateTaskChecklistParams) (TaskChecklist, error)
 | 
				
			||||||
 | 
						CreateTaskChecklistItem(ctx context.Context, arg CreateTaskChecklistItemParams) (TaskChecklistItem, error)
 | 
				
			||||||
	CreateTaskGroup(ctx context.Context, arg CreateTaskGroupParams) (TaskGroup, error)
 | 
						CreateTaskGroup(ctx context.Context, arg CreateTaskGroupParams) (TaskGroup, error)
 | 
				
			||||||
	CreateTaskLabelForTask(ctx context.Context, arg CreateTaskLabelForTaskParams) (TaskLabel, error)
 | 
						CreateTaskLabelForTask(ctx context.Context, arg CreateTaskLabelForTaskParams) (TaskLabel, error)
 | 
				
			||||||
	CreateTeam(ctx context.Context, arg CreateTeamParams) (Team, error)
 | 
						CreateTeam(ctx context.Context, arg CreateTeamParams) (Team, error)
 | 
				
			||||||
@@ -26,6 +28,7 @@ type Querier interface {
 | 
				
			|||||||
	DeleteRefreshTokenByUserID(ctx context.Context, userID uuid.UUID) error
 | 
						DeleteRefreshTokenByUserID(ctx context.Context, userID uuid.UUID) error
 | 
				
			||||||
	DeleteTaskAssignedByID(ctx context.Context, arg DeleteTaskAssignedByIDParams) (TaskAssigned, error)
 | 
						DeleteTaskAssignedByID(ctx context.Context, arg DeleteTaskAssignedByIDParams) (TaskAssigned, error)
 | 
				
			||||||
	DeleteTaskByID(ctx context.Context, taskID uuid.UUID) error
 | 
						DeleteTaskByID(ctx context.Context, taskID uuid.UUID) error
 | 
				
			||||||
 | 
						DeleteTaskChecklistItem(ctx context.Context, taskChecklistItemID 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
 | 
						DeleteTaskLabelByID(ctx context.Context, taskLabelID uuid.UUID) error
 | 
				
			||||||
	DeleteTaskLabelForTaskByProjectLabelID(ctx context.Context, arg DeleteTaskLabelForTaskByProjectLabelIDParams) error
 | 
						DeleteTaskLabelForTaskByProjectLabelID(ctx context.Context, arg DeleteTaskLabelForTaskByProjectLabelIDParams) error
 | 
				
			||||||
@@ -46,6 +49,9 @@ type Querier interface {
 | 
				
			|||||||
	GetProjectLabelsForProject(ctx context.Context, projectID uuid.UUID) ([]ProjectLabel, error)
 | 
						GetProjectLabelsForProject(ctx context.Context, projectID uuid.UUID) ([]ProjectLabel, error)
 | 
				
			||||||
	GetRefreshTokenByID(ctx context.Context, tokenID uuid.UUID) (RefreshToken, error)
 | 
						GetRefreshTokenByID(ctx context.Context, tokenID uuid.UUID) (RefreshToken, error)
 | 
				
			||||||
	GetTaskByID(ctx context.Context, taskID uuid.UUID) (Task, error)
 | 
						GetTaskByID(ctx context.Context, taskID uuid.UUID) (Task, error)
 | 
				
			||||||
 | 
						GetTaskChecklistItemByID(ctx context.Context, taskChecklistItemID uuid.UUID) (TaskChecklistItem, error)
 | 
				
			||||||
 | 
						GetTaskChecklistItemsForTaskChecklist(ctx context.Context, taskChecklistID uuid.UUID) ([]TaskChecklistItem, error)
 | 
				
			||||||
 | 
						GetTaskChecklistsForTask(ctx context.Context, taskID uuid.UUID) ([]TaskChecklist, 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)
 | 
						GetTaskLabelByID(ctx context.Context, taskLabelID uuid.UUID) (TaskLabel, error)
 | 
				
			||||||
@@ -56,11 +62,14 @@ type Querier interface {
 | 
				
			|||||||
	GetTeamsForOrganization(ctx context.Context, organizationID uuid.UUID) ([]Team, error)
 | 
						GetTeamsForOrganization(ctx context.Context, organizationID uuid.UUID) ([]Team, error)
 | 
				
			||||||
	GetUserAccountByID(ctx context.Context, userID uuid.UUID) (UserAccount, error)
 | 
						GetUserAccountByID(ctx context.Context, userID uuid.UUID) (UserAccount, error)
 | 
				
			||||||
	GetUserAccountByUsername(ctx context.Context, username string) (UserAccount, error)
 | 
						GetUserAccountByUsername(ctx context.Context, username string) (UserAccount, error)
 | 
				
			||||||
 | 
						SetTaskChecklistItemComplete(ctx context.Context, arg SetTaskChecklistItemCompleteParams) (TaskChecklistItem, error)
 | 
				
			||||||
 | 
						SetTaskComplete(ctx context.Context, arg SetTaskCompleteParams) (Task, error)
 | 
				
			||||||
	SetTaskGroupName(ctx context.Context, arg SetTaskGroupNameParams) (TaskGroup, error)
 | 
						SetTaskGroupName(ctx context.Context, arg SetTaskGroupNameParams) (TaskGroup, error)
 | 
				
			||||||
	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)
 | 
						UpdateProjectNameByID(ctx context.Context, arg UpdateProjectNameByIDParams) (Project, error)
 | 
				
			||||||
 | 
						UpdateTaskChecklistItemName(ctx context.Context, arg UpdateTaskChecklistItemNameParams) (TaskChecklistItem, error)
 | 
				
			||||||
	UpdateTaskDescription(ctx context.Context, arg UpdateTaskDescriptionParams) (Task, error)
 | 
						UpdateTaskDescription(ctx context.Context, arg UpdateTaskDescriptionParams) (Task, error)
 | 
				
			||||||
	UpdateTaskDueDate(ctx context.Context, arg UpdateTaskDueDateParams) (Task, error)
 | 
						UpdateTaskDueDate(ctx context.Context, arg UpdateTaskDueDateParams) (Task, error)
 | 
				
			||||||
	UpdateTaskGroupLocation(ctx context.Context, arg UpdateTaskGroupLocationParams) (TaskGroup, error)
 | 
						UpdateTaskGroupLocation(ctx context.Context, arg UpdateTaskGroupLocationParams) (TaskGroup, error)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,7 +13,7 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const createTask = `-- name: CreateTask :one
 | 
					const createTask = `-- name: CreateTask :one
 | 
				
			||||||
INSERT INTO task (task_group_id, created_at, name, position)
 | 
					INSERT INTO task (task_group_id, created_at, name, position)
 | 
				
			||||||
  VALUES($1, $2, $3, $4) RETURNING task_id, task_group_id, created_at, name, position, description, due_date
 | 
					  VALUES($1, $2, $3, $4) RETURNING task_id, task_group_id, created_at, name, position, description, due_date, complete
 | 
				
			||||||
`
 | 
					`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type CreateTaskParams struct {
 | 
					type CreateTaskParams struct {
 | 
				
			||||||
@@ -39,6 +39,7 @@ func (q *Queries) CreateTask(ctx context.Context, arg CreateTaskParams) (Task, e
 | 
				
			|||||||
		&i.Position,
 | 
							&i.Position,
 | 
				
			||||||
		&i.Description,
 | 
							&i.Description,
 | 
				
			||||||
		&i.DueDate,
 | 
							&i.DueDate,
 | 
				
			||||||
 | 
							&i.Complete,
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
	return i, err
 | 
						return i, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -65,7 +66,7 @@ func (q *Queries) DeleteTasksByTaskGroupID(ctx context.Context, taskGroupID uuid
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const getAllTasks = `-- name: GetAllTasks :many
 | 
					const getAllTasks = `-- name: GetAllTasks :many
 | 
				
			||||||
SELECT task_id, task_group_id, created_at, name, position, description, due_date FROM task
 | 
					SELECT task_id, task_group_id, created_at, name, position, description, due_date, complete FROM task
 | 
				
			||||||
`
 | 
					`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (q *Queries) GetAllTasks(ctx context.Context) ([]Task, error) {
 | 
					func (q *Queries) GetAllTasks(ctx context.Context) ([]Task, error) {
 | 
				
			||||||
@@ -85,6 +86,7 @@ func (q *Queries) GetAllTasks(ctx context.Context) ([]Task, error) {
 | 
				
			|||||||
			&i.Position,
 | 
								&i.Position,
 | 
				
			||||||
			&i.Description,
 | 
								&i.Description,
 | 
				
			||||||
			&i.DueDate,
 | 
								&i.DueDate,
 | 
				
			||||||
 | 
								&i.Complete,
 | 
				
			||||||
		); err != nil {
 | 
							); err != nil {
 | 
				
			||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -100,7 +102,7 @@ func (q *Queries) GetAllTasks(ctx context.Context) ([]Task, error) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const getTaskByID = `-- name: GetTaskByID :one
 | 
					const getTaskByID = `-- name: GetTaskByID :one
 | 
				
			||||||
SELECT task_id, task_group_id, created_at, name, position, description, due_date FROM task WHERE task_id = $1
 | 
					SELECT task_id, task_group_id, created_at, name, position, description, due_date, complete FROM task WHERE task_id = $1
 | 
				
			||||||
`
 | 
					`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (q *Queries) GetTaskByID(ctx context.Context, taskID uuid.UUID) (Task, error) {
 | 
					func (q *Queries) GetTaskByID(ctx context.Context, taskID uuid.UUID) (Task, error) {
 | 
				
			||||||
@@ -114,12 +116,13 @@ func (q *Queries) GetTaskByID(ctx context.Context, taskID uuid.UUID) (Task, erro
 | 
				
			|||||||
		&i.Position,
 | 
							&i.Position,
 | 
				
			||||||
		&i.Description,
 | 
							&i.Description,
 | 
				
			||||||
		&i.DueDate,
 | 
							&i.DueDate,
 | 
				
			||||||
 | 
							&i.Complete,
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
	return i, err
 | 
						return i, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const getTasksForTaskGroupID = `-- name: GetTasksForTaskGroupID :many
 | 
					const getTasksForTaskGroupID = `-- name: GetTasksForTaskGroupID :many
 | 
				
			||||||
SELECT task_id, task_group_id, created_at, name, position, description, due_date FROM task WHERE task_group_id = $1
 | 
					SELECT task_id, task_group_id, created_at, name, position, description, due_date, complete FROM task WHERE task_group_id = $1
 | 
				
			||||||
`
 | 
					`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (q *Queries) GetTasksForTaskGroupID(ctx context.Context, taskGroupID uuid.UUID) ([]Task, error) {
 | 
					func (q *Queries) GetTasksForTaskGroupID(ctx context.Context, taskGroupID uuid.UUID) ([]Task, error) {
 | 
				
			||||||
@@ -139,6 +142,7 @@ func (q *Queries) GetTasksForTaskGroupID(ctx context.Context, taskGroupID uuid.U
 | 
				
			|||||||
			&i.Position,
 | 
								&i.Position,
 | 
				
			||||||
			&i.Description,
 | 
								&i.Description,
 | 
				
			||||||
			&i.DueDate,
 | 
								&i.DueDate,
 | 
				
			||||||
 | 
								&i.Complete,
 | 
				
			||||||
		); err != nil {
 | 
							); err != nil {
 | 
				
			||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -153,8 +157,33 @@ func (q *Queries) GetTasksForTaskGroupID(ctx context.Context, taskGroupID uuid.U
 | 
				
			|||||||
	return items, nil
 | 
						return items, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const setTaskComplete = `-- name: SetTaskComplete :one
 | 
				
			||||||
 | 
					UPDATE task SET complete = $2 WHERE task_id = $1 RETURNING task_id, task_group_id, created_at, name, position, description, due_date, complete
 | 
				
			||||||
 | 
					`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type SetTaskCompleteParams struct {
 | 
				
			||||||
 | 
						TaskID   uuid.UUID `json:"task_id"`
 | 
				
			||||||
 | 
						Complete bool      `json:"complete"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (q *Queries) SetTaskComplete(ctx context.Context, arg SetTaskCompleteParams) (Task, error) {
 | 
				
			||||||
 | 
						row := q.db.QueryRowContext(ctx, setTaskComplete, arg.TaskID, arg.Complete)
 | 
				
			||||||
 | 
						var i Task
 | 
				
			||||||
 | 
						err := row.Scan(
 | 
				
			||||||
 | 
							&i.TaskID,
 | 
				
			||||||
 | 
							&i.TaskGroupID,
 | 
				
			||||||
 | 
							&i.CreatedAt,
 | 
				
			||||||
 | 
							&i.Name,
 | 
				
			||||||
 | 
							&i.Position,
 | 
				
			||||||
 | 
							&i.Description,
 | 
				
			||||||
 | 
							&i.DueDate,
 | 
				
			||||||
 | 
							&i.Complete,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						return i, err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const updateTaskDescription = `-- name: UpdateTaskDescription :one
 | 
					const updateTaskDescription = `-- name: UpdateTaskDescription :one
 | 
				
			||||||
UPDATE task SET description = $2 WHERE task_id = $1 RETURNING task_id, task_group_id, created_at, name, position, description, due_date
 | 
					UPDATE task SET description = $2 WHERE task_id = $1 RETURNING task_id, task_group_id, created_at, name, position, description, due_date, complete
 | 
				
			||||||
`
 | 
					`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type UpdateTaskDescriptionParams struct {
 | 
					type UpdateTaskDescriptionParams struct {
 | 
				
			||||||
@@ -173,12 +202,13 @@ func (q *Queries) UpdateTaskDescription(ctx context.Context, arg UpdateTaskDescr
 | 
				
			|||||||
		&i.Position,
 | 
							&i.Position,
 | 
				
			||||||
		&i.Description,
 | 
							&i.Description,
 | 
				
			||||||
		&i.DueDate,
 | 
							&i.DueDate,
 | 
				
			||||||
 | 
							&i.Complete,
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
	return i, err
 | 
						return i, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const updateTaskDueDate = `-- name: UpdateTaskDueDate :one
 | 
					const updateTaskDueDate = `-- name: UpdateTaskDueDate :one
 | 
				
			||||||
UPDATE task SET due_date = $2 WHERE task_id = $1 RETURNING task_id, task_group_id, created_at, name, position, description, due_date
 | 
					UPDATE task SET due_date = $2 WHERE task_id = $1 RETURNING task_id, task_group_id, created_at, name, position, description, due_date, complete
 | 
				
			||||||
`
 | 
					`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type UpdateTaskDueDateParams struct {
 | 
					type UpdateTaskDueDateParams struct {
 | 
				
			||||||
@@ -197,12 +227,13 @@ func (q *Queries) UpdateTaskDueDate(ctx context.Context, arg UpdateTaskDueDatePa
 | 
				
			|||||||
		&i.Position,
 | 
							&i.Position,
 | 
				
			||||||
		&i.Description,
 | 
							&i.Description,
 | 
				
			||||||
		&i.DueDate,
 | 
							&i.DueDate,
 | 
				
			||||||
 | 
							&i.Complete,
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
	return i, err
 | 
						return i, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const updateTaskLocation = `-- name: UpdateTaskLocation :one
 | 
					const updateTaskLocation = `-- name: UpdateTaskLocation :one
 | 
				
			||||||
UPDATE task SET task_group_id = $2, position = $3 WHERE task_id = $1 RETURNING task_id, task_group_id, created_at, name, position, description, due_date
 | 
					UPDATE task SET task_group_id = $2, position = $3 WHERE task_id = $1 RETURNING task_id, task_group_id, created_at, name, position, description, due_date, complete
 | 
				
			||||||
`
 | 
					`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type UpdateTaskLocationParams struct {
 | 
					type UpdateTaskLocationParams struct {
 | 
				
			||||||
@@ -222,12 +253,13 @@ func (q *Queries) UpdateTaskLocation(ctx context.Context, arg UpdateTaskLocation
 | 
				
			|||||||
		&i.Position,
 | 
							&i.Position,
 | 
				
			||||||
		&i.Description,
 | 
							&i.Description,
 | 
				
			||||||
		&i.DueDate,
 | 
							&i.DueDate,
 | 
				
			||||||
 | 
							&i.Complete,
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
	return i, err
 | 
						return i, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const updateTaskName = `-- name: UpdateTaskName :one
 | 
					const updateTaskName = `-- name: UpdateTaskName :one
 | 
				
			||||||
UPDATE task SET name = $2 WHERE task_id = $1 RETURNING task_id, task_group_id, created_at, name, position, description, due_date
 | 
					UPDATE task SET name = $2 WHERE task_id = $1 RETURNING task_id, task_group_id, created_at, name, position, description, due_date, complete
 | 
				
			||||||
`
 | 
					`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type UpdateTaskNameParams struct {
 | 
					type UpdateTaskNameParams struct {
 | 
				
			||||||
@@ -246,6 +278,7 @@ func (q *Queries) UpdateTaskName(ctx context.Context, arg UpdateTaskNameParams)
 | 
				
			|||||||
		&i.Position,
 | 
							&i.Position,
 | 
				
			||||||
		&i.Description,
 | 
							&i.Description,
 | 
				
			||||||
		&i.DueDate,
 | 
							&i.DueDate,
 | 
				
			||||||
 | 
							&i.Complete,
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
	return i, err
 | 
						return i, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										219
									
								
								api/pg/task_checklist.sql.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										219
									
								
								api/pg/task_checklist.sql.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,219 @@
 | 
				
			|||||||
 | 
					// Code generated by sqlc. DO NOT EDIT.
 | 
				
			||||||
 | 
					// source: task_checklist.sql
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package pg
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/google/uuid"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const createTaskChecklist = `-- name: CreateTaskChecklist :one
 | 
				
			||||||
 | 
					INSERT INTO task_checklist (task_id, created_at, name, position) VALUES ($1, $2, $3, $4)
 | 
				
			||||||
 | 
					  RETURNING task_checklist_id, task_id, created_at, name, position
 | 
				
			||||||
 | 
					`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type CreateTaskChecklistParams struct {
 | 
				
			||||||
 | 
						TaskID    uuid.UUID `json:"task_id"`
 | 
				
			||||||
 | 
						CreatedAt time.Time `json:"created_at"`
 | 
				
			||||||
 | 
						Name      string    `json:"name"`
 | 
				
			||||||
 | 
						Position  float64   `json:"position"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (q *Queries) CreateTaskChecklist(ctx context.Context, arg CreateTaskChecklistParams) (TaskChecklist, error) {
 | 
				
			||||||
 | 
						row := q.db.QueryRowContext(ctx, createTaskChecklist,
 | 
				
			||||||
 | 
							arg.TaskID,
 | 
				
			||||||
 | 
							arg.CreatedAt,
 | 
				
			||||||
 | 
							arg.Name,
 | 
				
			||||||
 | 
							arg.Position,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						var i TaskChecklist
 | 
				
			||||||
 | 
						err := row.Scan(
 | 
				
			||||||
 | 
							&i.TaskChecklistID,
 | 
				
			||||||
 | 
							&i.TaskID,
 | 
				
			||||||
 | 
							&i.CreatedAt,
 | 
				
			||||||
 | 
							&i.Name,
 | 
				
			||||||
 | 
							&i.Position,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						return i, err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const createTaskChecklistItem = `-- name: CreateTaskChecklistItem :one
 | 
				
			||||||
 | 
					INSERT INTO task_checklist_item (task_checklist_id, created_at, name, position, complete, due_date) VALUES ($1, $2, $3, $4, false, null)
 | 
				
			||||||
 | 
					  RETURNING task_checklist_item_id, task_checklist_id, created_at, complete, name, position, due_date
 | 
				
			||||||
 | 
					`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type CreateTaskChecklistItemParams struct {
 | 
				
			||||||
 | 
						TaskChecklistID uuid.UUID `json:"task_checklist_id"`
 | 
				
			||||||
 | 
						CreatedAt       time.Time `json:"created_at"`
 | 
				
			||||||
 | 
						Name            string    `json:"name"`
 | 
				
			||||||
 | 
						Position        float64   `json:"position"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (q *Queries) CreateTaskChecklistItem(ctx context.Context, arg CreateTaskChecklistItemParams) (TaskChecklistItem, error) {
 | 
				
			||||||
 | 
						row := q.db.QueryRowContext(ctx, createTaskChecklistItem,
 | 
				
			||||||
 | 
							arg.TaskChecklistID,
 | 
				
			||||||
 | 
							arg.CreatedAt,
 | 
				
			||||||
 | 
							arg.Name,
 | 
				
			||||||
 | 
							arg.Position,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						var i TaskChecklistItem
 | 
				
			||||||
 | 
						err := row.Scan(
 | 
				
			||||||
 | 
							&i.TaskChecklistItemID,
 | 
				
			||||||
 | 
							&i.TaskChecklistID,
 | 
				
			||||||
 | 
							&i.CreatedAt,
 | 
				
			||||||
 | 
							&i.Complete,
 | 
				
			||||||
 | 
							&i.Name,
 | 
				
			||||||
 | 
							&i.Position,
 | 
				
			||||||
 | 
							&i.DueDate,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						return i, err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const deleteTaskChecklistItem = `-- name: DeleteTaskChecklistItem :exec
 | 
				
			||||||
 | 
					DELETE FROM task_checklist_item WHERE task_checklist_item_id = $1
 | 
				
			||||||
 | 
					`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (q *Queries) DeleteTaskChecklistItem(ctx context.Context, taskChecklistItemID uuid.UUID) error {
 | 
				
			||||||
 | 
						_, err := q.db.ExecContext(ctx, deleteTaskChecklistItem, taskChecklistItemID)
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const getTaskChecklistItemByID = `-- name: GetTaskChecklistItemByID :one
 | 
				
			||||||
 | 
					SELECT task_checklist_item_id, task_checklist_id, created_at, complete, name, position, due_date FROM task_checklist_item WHERE task_checklist_item_id = $1
 | 
				
			||||||
 | 
					`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (q *Queries) GetTaskChecklistItemByID(ctx context.Context, taskChecklistItemID uuid.UUID) (TaskChecklistItem, error) {
 | 
				
			||||||
 | 
						row := q.db.QueryRowContext(ctx, getTaskChecklistItemByID, taskChecklistItemID)
 | 
				
			||||||
 | 
						var i TaskChecklistItem
 | 
				
			||||||
 | 
						err := row.Scan(
 | 
				
			||||||
 | 
							&i.TaskChecklistItemID,
 | 
				
			||||||
 | 
							&i.TaskChecklistID,
 | 
				
			||||||
 | 
							&i.CreatedAt,
 | 
				
			||||||
 | 
							&i.Complete,
 | 
				
			||||||
 | 
							&i.Name,
 | 
				
			||||||
 | 
							&i.Position,
 | 
				
			||||||
 | 
							&i.DueDate,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						return i, err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const getTaskChecklistItemsForTaskChecklist = `-- name: GetTaskChecklistItemsForTaskChecklist :many
 | 
				
			||||||
 | 
					SELECT task_checklist_item_id, task_checklist_id, created_at, complete, name, position, due_date FROM task_checklist_item WHERE task_checklist_id = $1
 | 
				
			||||||
 | 
					`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (q *Queries) GetTaskChecklistItemsForTaskChecklist(ctx context.Context, taskChecklistID uuid.UUID) ([]TaskChecklistItem, error) {
 | 
				
			||||||
 | 
						rows, err := q.db.QueryContext(ctx, getTaskChecklistItemsForTaskChecklist, taskChecklistID)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer rows.Close()
 | 
				
			||||||
 | 
						var items []TaskChecklistItem
 | 
				
			||||||
 | 
						for rows.Next() {
 | 
				
			||||||
 | 
							var i TaskChecklistItem
 | 
				
			||||||
 | 
							if err := rows.Scan(
 | 
				
			||||||
 | 
								&i.TaskChecklistItemID,
 | 
				
			||||||
 | 
								&i.TaskChecklistID,
 | 
				
			||||||
 | 
								&i.CreatedAt,
 | 
				
			||||||
 | 
								&i.Complete,
 | 
				
			||||||
 | 
								&i.Name,
 | 
				
			||||||
 | 
								&i.Position,
 | 
				
			||||||
 | 
								&i.DueDate,
 | 
				
			||||||
 | 
							); err != nil {
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							items = append(items, i)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := rows.Close(); err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := rows.Err(); err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return items, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const getTaskChecklistsForTask = `-- name: GetTaskChecklistsForTask :many
 | 
				
			||||||
 | 
					SELECT task_checklist_id, task_id, created_at, name, position FROM task_checklist WHERE task_id = $1
 | 
				
			||||||
 | 
					`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (q *Queries) GetTaskChecklistsForTask(ctx context.Context, taskID uuid.UUID) ([]TaskChecklist, error) {
 | 
				
			||||||
 | 
						rows, err := q.db.QueryContext(ctx, getTaskChecklistsForTask, taskID)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer rows.Close()
 | 
				
			||||||
 | 
						var items []TaskChecklist
 | 
				
			||||||
 | 
						for rows.Next() {
 | 
				
			||||||
 | 
							var i TaskChecklist
 | 
				
			||||||
 | 
							if err := rows.Scan(
 | 
				
			||||||
 | 
								&i.TaskChecklistID,
 | 
				
			||||||
 | 
								&i.TaskID,
 | 
				
			||||||
 | 
								&i.CreatedAt,
 | 
				
			||||||
 | 
								&i.Name,
 | 
				
			||||||
 | 
								&i.Position,
 | 
				
			||||||
 | 
							); err != nil {
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							items = append(items, i)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := rows.Close(); err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := rows.Err(); err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return items, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const setTaskChecklistItemComplete = `-- name: SetTaskChecklistItemComplete :one
 | 
				
			||||||
 | 
					UPDATE task_checklist_item SET complete = $2 WHERE task_checklist_item_id = $1
 | 
				
			||||||
 | 
					  RETURNING task_checklist_item_id, task_checklist_id, created_at, complete, name, position, due_date
 | 
				
			||||||
 | 
					`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type SetTaskChecklistItemCompleteParams struct {
 | 
				
			||||||
 | 
						TaskChecklistItemID uuid.UUID `json:"task_checklist_item_id"`
 | 
				
			||||||
 | 
						Complete            bool      `json:"complete"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (q *Queries) SetTaskChecklistItemComplete(ctx context.Context, arg SetTaskChecklistItemCompleteParams) (TaskChecklistItem, error) {
 | 
				
			||||||
 | 
						row := q.db.QueryRowContext(ctx, setTaskChecklistItemComplete, arg.TaskChecklistItemID, arg.Complete)
 | 
				
			||||||
 | 
						var i TaskChecklistItem
 | 
				
			||||||
 | 
						err := row.Scan(
 | 
				
			||||||
 | 
							&i.TaskChecklistItemID,
 | 
				
			||||||
 | 
							&i.TaskChecklistID,
 | 
				
			||||||
 | 
							&i.CreatedAt,
 | 
				
			||||||
 | 
							&i.Complete,
 | 
				
			||||||
 | 
							&i.Name,
 | 
				
			||||||
 | 
							&i.Position,
 | 
				
			||||||
 | 
							&i.DueDate,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						return i, err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const updateTaskChecklistItemName = `-- name: UpdateTaskChecklistItemName :one
 | 
				
			||||||
 | 
					UPDATE task_checklist_item SET name = $2 WHERE task_checklist_item_id = $1
 | 
				
			||||||
 | 
					  RETURNING task_checklist_item_id, task_checklist_id, created_at, complete, name, position, due_date
 | 
				
			||||||
 | 
					`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type UpdateTaskChecklistItemNameParams struct {
 | 
				
			||||||
 | 
						TaskChecklistItemID uuid.UUID `json:"task_checklist_item_id"`
 | 
				
			||||||
 | 
						Name                string    `json:"name"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (q *Queries) UpdateTaskChecklistItemName(ctx context.Context, arg UpdateTaskChecklistItemNameParams) (TaskChecklistItem, error) {
 | 
				
			||||||
 | 
						row := q.db.QueryRowContext(ctx, updateTaskChecklistItemName, arg.TaskChecklistItemID, arg.Name)
 | 
				
			||||||
 | 
						var i TaskChecklistItem
 | 
				
			||||||
 | 
						err := row.Scan(
 | 
				
			||||||
 | 
							&i.TaskChecklistItemID,
 | 
				
			||||||
 | 
							&i.TaskChecklistID,
 | 
				
			||||||
 | 
							&i.CreatedAt,
 | 
				
			||||||
 | 
							&i.Complete,
 | 
				
			||||||
 | 
							&i.Name,
 | 
				
			||||||
 | 
							&i.Position,
 | 
				
			||||||
 | 
							&i.DueDate,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						return i, err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -28,3 +28,6 @@ DELETE FROM task where task_group_id = $1;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
-- name: UpdateTaskDueDate :one
 | 
					-- name: UpdateTaskDueDate :one
 | 
				
			||||||
UPDATE task SET due_date = $2 WHERE task_id = $1 RETURNING *;
 | 
					UPDATE task SET due_date = $2 WHERE task_id = $1 RETURNING *;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- name: SetTaskComplete :one
 | 
				
			||||||
 | 
					UPDATE task SET complete = $2 WHERE task_id = $1 RETURNING *;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										27
									
								
								api/query/task_checklist.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								api/query/task_checklist.sql
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					-- name: CreateTaskChecklist :one
 | 
				
			||||||
 | 
					INSERT INTO task_checklist (task_id, created_at, name, position) VALUES ($1, $2, $3, $4)
 | 
				
			||||||
 | 
					  RETURNING *;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- name: GetTaskChecklistsForTask :many
 | 
				
			||||||
 | 
					SELECT * FROM task_checklist WHERE task_id = $1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- name: CreateTaskChecklistItem :one
 | 
				
			||||||
 | 
					INSERT INTO task_checklist_item (task_checklist_id, created_at, name, position, complete, due_date) VALUES ($1, $2, $3, $4, false, null)
 | 
				
			||||||
 | 
					  RETURNING *;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- name: GetTaskChecklistItemsForTaskChecklist :many
 | 
				
			||||||
 | 
					SELECT * FROM task_checklist_item WHERE task_checklist_id = $1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- name: SetTaskChecklistItemComplete :one
 | 
				
			||||||
 | 
					UPDATE task_checklist_item SET complete = $2 WHERE task_checklist_item_id = $1
 | 
				
			||||||
 | 
					  RETURNING *;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- name: DeleteTaskChecklistItem :exec
 | 
				
			||||||
 | 
					DELETE FROM task_checklist_item WHERE task_checklist_item_id = $1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- name: GetTaskChecklistItemByID :one
 | 
				
			||||||
 | 
					SELECT * FROM task_checklist_item WHERE task_checklist_item_id = $1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- name: UpdateTaskChecklistItemName :one
 | 
				
			||||||
 | 
					UPDATE task_checklist_item SET name = $2 WHERE task_checklist_item_id = $1
 | 
				
			||||||
 | 
					  RETURNING *;
 | 
				
			||||||
							
								
								
									
										1
									
								
								api/trello.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								api/trello.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@@ -1,7 +1,9 @@
 | 
				
			|||||||
overwrite: true
 | 
					overwrite: true
 | 
				
			||||||
schema:
 | 
					schema:
 | 
				
			||||||
  - '../api/graph/schema.graphqls'
 | 
					  - '../api/graph/schema.graphqls'
 | 
				
			||||||
documents: 'src/shared/graphql/*.graphqls'
 | 
					documents:
 | 
				
			||||||
 | 
					  - 'src/shared/graphql/*.graphqls'
 | 
				
			||||||
 | 
					  - 'src/shared/graphql/**/*.ts'
 | 
				
			||||||
generates:
 | 
					generates:
 | 
				
			||||||
  src/shared/generated/graphql.tsx:
 | 
					  src/shared/generated/graphql.tsx:
 | 
				
			||||||
    plugins:
 | 
					    plugins:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -112,7 +112,7 @@ export default createGlobalStyle`
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   ::-webkit-scrollbar {
 | 
					   ::-webkit-scrollbar {
 | 
				
			||||||
    width: 12px;
 | 
					    width: 10px;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   ::-webkit-scrollbar-track {
 | 
					   ::-webkit-scrollbar-track {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,9 +10,12 @@ import Profile from 'Profile';
 | 
				
			|||||||
import styled from 'styled-components';
 | 
					import styled from 'styled-components';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const MainContent = styled.div`
 | 
					const MainContent = styled.div`
 | 
				
			||||||
  padding: 0 0 50px 80px;
 | 
					  padding: 0 0 0 80px;
 | 
				
			||||||
  background: #262c49;
 | 
					  background: #262c49;
 | 
				
			||||||
  height: 100%;
 | 
					  height: 100%;
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  flex-direction: column;
 | 
				
			||||||
 | 
					  flex-grow: 1;
 | 
				
			||||||
`;
 | 
					`;
 | 
				
			||||||
type RoutesProps = {
 | 
					type RoutesProps = {
 | 
				
			||||||
  history: H.History;
 | 
					  history: H.History;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,23 +26,3 @@ const theme: DefaultTheme = {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export { theme };
 | 
					export { theme };
 | 
				
			||||||
 | 
					 | 
				
			||||||
export default createGlobalStyle`
 | 
					 | 
				
			||||||
  :root {
 | 
					 | 
				
			||||||
    --color-text: #c2c6dc;
 | 
					 | 
				
			||||||
    --color-text-hover: #fff;
 | 
					 | 
				
			||||||
    --color-primary: rgba(115, 103, 240);
 | 
					 | 
				
			||||||
    --color-button-text: #c2c6dc;
 | 
					 | 
				
			||||||
    --color-button-text-hover: #fff;
 | 
					 | 
				
			||||||
    --color-button-background: rgba(115, 103, 240);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    --color-background: #262c49;
 | 
					 | 
				
			||||||
    --color-background-dark: #10163a;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    --color-input-text: #c2c6dc;
 | 
					 | 
				
			||||||
    --color-input-text-focus: #fff;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    --color-icon: #c2c6dc;
 | 
					 | 
				
			||||||
    --color-active-icon: rgba(115, 103, 240);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
`;
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,7 +5,7 @@ import { setAccessToken } from 'shared/utils/accessToken';
 | 
				
			|||||||
import styled, { ThemeProvider } from 'styled-components';
 | 
					import styled, { ThemeProvider } from 'styled-components';
 | 
				
			||||||
import NormalizeStyles from './NormalizeStyles';
 | 
					import NormalizeStyles from './NormalizeStyles';
 | 
				
			||||||
import BaseStyles from './BaseStyles';
 | 
					import BaseStyles from './BaseStyles';
 | 
				
			||||||
import ThemeStyles, { theme } from './ThemeStyles';
 | 
					import { theme } from './ThemeStyles';
 | 
				
			||||||
import Routes from './Routes';
 | 
					import Routes from './Routes';
 | 
				
			||||||
import { UserIDContext } from './context';
 | 
					import { UserIDContext } from './context';
 | 
				
			||||||
import Navbar from './Navbar';
 | 
					import Navbar from './Navbar';
 | 
				
			||||||
@@ -44,7 +44,6 @@ const App = () => {
 | 
				
			|||||||
          <PopupProvider>
 | 
					          <PopupProvider>
 | 
				
			||||||
            <NormalizeStyles />
 | 
					            <NormalizeStyles />
 | 
				
			||||||
            <BaseStyles />
 | 
					            <BaseStyles />
 | 
				
			||||||
            <ThemeStyles />
 | 
					 | 
				
			||||||
            <Router history={history}>
 | 
					            <Router history={history}>
 | 
				
			||||||
              {loading ? (
 | 
					              {loading ? (
 | 
				
			||||||
                <div>loading</div>
 | 
					                <div>loading</div>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,10 +9,16 @@ import {
 | 
				
			|||||||
  useUpdateTaskDueDateMutation,
 | 
					  useUpdateTaskDueDateMutation,
 | 
				
			||||||
  useAssignTaskMutation,
 | 
					  useAssignTaskMutation,
 | 
				
			||||||
  useUnassignTaskMutation,
 | 
					  useUnassignTaskMutation,
 | 
				
			||||||
 | 
					  useSetTaskChecklistItemCompleteMutation,
 | 
				
			||||||
 | 
					  useDeleteTaskChecklistItemMutation,
 | 
				
			||||||
 | 
					  useUpdateTaskChecklistItemNameMutation,
 | 
				
			||||||
 | 
					  useCreateTaskChecklistItemMutation,
 | 
				
			||||||
 | 
					  FindTaskDocument,
 | 
				
			||||||
} from 'shared/generated/graphql';
 | 
					} from 'shared/generated/graphql';
 | 
				
			||||||
import UserIDContext from 'App/context';
 | 
					import UserIDContext from 'App/context';
 | 
				
			||||||
import MiniProfile from 'shared/components/MiniProfile';
 | 
					import MiniProfile from 'shared/components/MiniProfile';
 | 
				
			||||||
import DueDateManager from 'shared/components/DueDateManager';
 | 
					import DueDateManager from 'shared/components/DueDateManager';
 | 
				
			||||||
 | 
					import produce from 'immer';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type DetailsProps = {
 | 
					type DetailsProps = {
 | 
				
			||||||
  taskID: string;
 | 
					  taskID: string;
 | 
				
			||||||
@@ -43,6 +49,64 @@ const Details: React.FC<DetailsProps> = ({
 | 
				
			|||||||
  const match = useRouteMatch();
 | 
					  const match = useRouteMatch();
 | 
				
			||||||
  const [currentMemberTask, setCurrentMemberTask] = useState('');
 | 
					  const [currentMemberTask, setCurrentMemberTask] = useState('');
 | 
				
			||||||
  const [memberPopupData, setMemberPopupData] = useState(initialMemberPopupState);
 | 
					  const [memberPopupData, setMemberPopupData] = useState(initialMemberPopupState);
 | 
				
			||||||
 | 
					  const [setTaskChecklistItemComplete] = useSetTaskChecklistItemCompleteMutation();
 | 
				
			||||||
 | 
					  const [updateTaskChecklistItemName] = useUpdateTaskChecklistItemNameMutation();
 | 
				
			||||||
 | 
					  const [deleteTaskChecklistItem] = useDeleteTaskChecklistItemMutation({
 | 
				
			||||||
 | 
					    update: (client, deleteData) => {
 | 
				
			||||||
 | 
					      const cacheData: any = client.readQuery({
 | 
				
			||||||
 | 
					        query: FindTaskDocument,
 | 
				
			||||||
 | 
					        variables: { taskID },
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					      console.log(deleteData);
 | 
				
			||||||
 | 
					      const newData = produce(cacheData.findTask, (draftState: any) => {
 | 
				
			||||||
 | 
					        const idx = draftState.checklists.findIndex(
 | 
				
			||||||
 | 
					          (checklist: TaskChecklist) =>
 | 
				
			||||||
 | 
					            checklist.id === deleteData.data.deleteTaskChecklistItem.taskChecklistItem.taskChecklistID,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        console.log(`idx ${idx}`);
 | 
				
			||||||
 | 
					        if (idx !== -1) {
 | 
				
			||||||
 | 
					          draftState.checklists[idx].items = cacheData.findTask.checklists[idx].items.filter(
 | 
				
			||||||
 | 
					            (item: any) => item.id !== deleteData.data.deleteTaskChecklistItem.taskChecklistItem.id,
 | 
				
			||||||
 | 
					          );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					      client.writeQuery({
 | 
				
			||||||
 | 
					        query: FindTaskDocument,
 | 
				
			||||||
 | 
					        variables: { taskID },
 | 
				
			||||||
 | 
					        data: {
 | 
				
			||||||
 | 
					          findTask: newData,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					  const [createTaskChecklistItem] = useCreateTaskChecklistItemMutation({
 | 
				
			||||||
 | 
					    update: (client, newTaskItem) => {
 | 
				
			||||||
 | 
					      const cacheData: any = client.readQuery({
 | 
				
			||||||
 | 
					        query: FindTaskDocument,
 | 
				
			||||||
 | 
					        variables: { taskID },
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					      console.log(cacheData);
 | 
				
			||||||
 | 
					      console.log(newTaskItem);
 | 
				
			||||||
 | 
					      const newData = produce(cacheData.findTask, (draftState: any) => {
 | 
				
			||||||
 | 
					        const idx = draftState.checklists.findIndex(
 | 
				
			||||||
 | 
					          (checklist: TaskChecklist) => checklist.id === newTaskItem.data.createTaskChecklistItem.taskChecklistID,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        if (idx !== -1) {
 | 
				
			||||||
 | 
					          draftState.checklists[idx].items = [
 | 
				
			||||||
 | 
					            ...cacheData.findTask.checklists[idx].items,
 | 
				
			||||||
 | 
					            { ...newTaskItem.data.createTaskChecklistItem },
 | 
				
			||||||
 | 
					          ];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					      client.writeQuery({
 | 
				
			||||||
 | 
					        query: FindTaskDocument,
 | 
				
			||||||
 | 
					        variables: { taskID },
 | 
				
			||||||
 | 
					        data: {
 | 
				
			||||||
 | 
					          findTask: newData,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
  const { loading, data, refetch } = useFindTaskQuery({ variables: { taskID } });
 | 
					  const { loading, data, refetch } = useFindTaskQuery({ variables: { taskID } });
 | 
				
			||||||
  const [updateTaskDueDate] = useUpdateTaskDueDateMutation({
 | 
					  const [updateTaskDueDate] = useUpdateTaskDueDateMutation({
 | 
				
			||||||
    onCompleted: () => {
 | 
					    onCompleted: () => {
 | 
				
			||||||
@@ -83,7 +147,19 @@ const Details: React.FC<DetailsProps> = ({
 | 
				
			|||||||
              onTaskNameChange={onTaskNameChange}
 | 
					              onTaskNameChange={onTaskNameChange}
 | 
				
			||||||
              onTaskDescriptionChange={onTaskDescriptionChange}
 | 
					              onTaskDescriptionChange={onTaskDescriptionChange}
 | 
				
			||||||
              onDeleteTask={onDeleteTask}
 | 
					              onDeleteTask={onDeleteTask}
 | 
				
			||||||
 | 
					              onChangeItemName={(itemID, itemName) => {
 | 
				
			||||||
 | 
					                updateTaskChecklistItemName({ variables: { taskChecklistItemID: itemID, name: itemName } });
 | 
				
			||||||
 | 
					              }}
 | 
				
			||||||
              onCloseModal={() => history.push(projectURL)}
 | 
					              onCloseModal={() => history.push(projectURL)}
 | 
				
			||||||
 | 
					              onDeleteItem={itemID => {
 | 
				
			||||||
 | 
					                deleteTaskChecklistItem({ variables: { taskChecklistItemID: itemID } });
 | 
				
			||||||
 | 
					              }}
 | 
				
			||||||
 | 
					              onToggleChecklistItem={(itemID, complete) => {
 | 
				
			||||||
 | 
					                setTaskChecklistItemComplete({ variables: { taskChecklistItemID: itemID, complete } });
 | 
				
			||||||
 | 
					              }}
 | 
				
			||||||
 | 
					              onAddItem={(taskChecklistID, name, position) => {
 | 
				
			||||||
 | 
					                createTaskChecklistItem({ variables: { taskChecklistID, name, position } });
 | 
				
			||||||
 | 
					              }}
 | 
				
			||||||
              onMemberProfile={($targetRef, memberID) => {
 | 
					              onMemberProfile={($targetRef, memberID) => {
 | 
				
			||||||
                const member = data.findTask.assigned.find(m => m.id === memberID);
 | 
					                const member = data.findTask.assigned.find(m => m.id === memberID);
 | 
				
			||||||
                const profileIcon = member ? member.profileIcon : null;
 | 
					                const profileIcon = member ? member.profileIcon : null;
 | 
				
			||||||
@@ -124,7 +200,6 @@ const Details: React.FC<DetailsProps> = ({
 | 
				
			|||||||
              onOpenDueDatePopop={(task, $targetRef) => {
 | 
					              onOpenDueDatePopop={(task, $targetRef) => {
 | 
				
			||||||
                showPopup(
 | 
					                showPopup(
 | 
				
			||||||
                  $targetRef,
 | 
					                  $targetRef,
 | 
				
			||||||
 | 
					 | 
				
			||||||
                  <Popup
 | 
					                  <Popup
 | 
				
			||||||
                    title={'Change Due Date'}
 | 
					                    title={'Change Due Date'}
 | 
				
			||||||
                    tab={0}
 | 
					                    tab={0}
 | 
				
			||||||
@@ -134,8 +209,11 @@ const Details: React.FC<DetailsProps> = ({
 | 
				
			|||||||
                  >
 | 
					                  >
 | 
				
			||||||
                    <DueDateManager
 | 
					                    <DueDateManager
 | 
				
			||||||
                      task={task}
 | 
					                      task={task}
 | 
				
			||||||
 | 
					                      onRemoveDueDate={t => {
 | 
				
			||||||
 | 
					                        updateTaskDueDate({ variables: { taskID: t.id, dueDate: null } });
 | 
				
			||||||
 | 
					                        hidePopup();
 | 
				
			||||||
 | 
					                      }}
 | 
				
			||||||
                      onDueDateChange={(t, newDueDate) => {
 | 
					                      onDueDateChange={(t, newDueDate) => {
 | 
				
			||||||
                        console.log(`${newDueDate}`);
 | 
					 | 
				
			||||||
                        updateTaskDueDate({ variables: { taskID: t.id, dueDate: newDueDate } });
 | 
					                        updateTaskDueDate({ variables: { taskID: t.id, dueDate: newDueDate } });
 | 
				
			||||||
                        hidePopup();
 | 
					                        hidePopup();
 | 
				
			||||||
                      }}
 | 
					                      }}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,9 +5,11 @@ 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 {
 | 
				
			||||||
 | 
					  useSetTaskCompleteMutation,
 | 
				
			||||||
  useToggleTaskLabelMutation,
 | 
					  useToggleTaskLabelMutation,
 | 
				
			||||||
  useUpdateProjectNameMutation,
 | 
					  useUpdateProjectNameMutation,
 | 
				
			||||||
  useFindProjectQuery,
 | 
					  useFindProjectQuery,
 | 
				
			||||||
 | 
					  useUpdateTaskGroupNameMutation,
 | 
				
			||||||
  useUpdateTaskNameMutation,
 | 
					  useUpdateTaskNameMutation,
 | 
				
			||||||
  useUpdateProjectLabelMutation,
 | 
					  useUpdateProjectLabelMutation,
 | 
				
			||||||
  useCreateTaskMutation,
 | 
					  useCreateTaskMutation,
 | 
				
			||||||
@@ -23,6 +25,7 @@ import {
 | 
				
			|||||||
  FindProjectDocument,
 | 
					  FindProjectDocument,
 | 
				
			||||||
  useCreateProjectLabelMutation,
 | 
					  useCreateProjectLabelMutation,
 | 
				
			||||||
  useUnassignTaskMutation,
 | 
					  useUnassignTaskMutation,
 | 
				
			||||||
 | 
					  useUpdateTaskDueDateMutation,
 | 
				
			||||||
} from 'shared/generated/graphql';
 | 
					} from 'shared/generated/graphql';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import TaskAssignee from 'shared/components/TaskAssignee';
 | 
					import TaskAssignee from 'shared/components/TaskAssignee';
 | 
				
			||||||
@@ -40,6 +43,7 @@ import MiniProfile from 'shared/components/MiniProfile';
 | 
				
			|||||||
import Details from './Details';
 | 
					import Details from './Details';
 | 
				
			||||||
import { useApolloClient } from '@apollo/react-hooks';
 | 
					import { useApolloClient } from '@apollo/react-hooks';
 | 
				
			||||||
import UserIDContext from 'App/context';
 | 
					import UserIDContext from 'App/context';
 | 
				
			||||||
 | 
					import DueDateManager from 'shared/components/DueDateManager';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const getCacheData = (client: any, projectID: string) => {
 | 
					const getCacheData = (client: any, projectID: string) => {
 | 
				
			||||||
  const cacheData: any = client.readQuery({
 | 
					  const cacheData: any = client.readQuery({
 | 
				
			||||||
@@ -69,6 +73,7 @@ interface QuickCardEditorState {
 | 
				
			|||||||
  isOpen: boolean;
 | 
					  isOpen: boolean;
 | 
				
			||||||
  left: number;
 | 
					  left: number;
 | 
				
			||||||
  top: number;
 | 
					  top: number;
 | 
				
			||||||
 | 
					  width: number;
 | 
				
			||||||
  taskID: string | null;
 | 
					  taskID: string | null;
 | 
				
			||||||
  taskGroupID: string | null;
 | 
					  taskGroupID: string | null;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -209,6 +214,7 @@ const initialQuickCardEditorState: QuickCardEditorState = {
 | 
				
			|||||||
  isOpen: false,
 | 
					  isOpen: false,
 | 
				
			||||||
  top: 0,
 | 
					  top: 0,
 | 
				
			||||||
  left: 0,
 | 
					  left: 0,
 | 
				
			||||||
 | 
					  width: 272,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const ProjectBar = styled.div`
 | 
					const ProjectBar = styled.div`
 | 
				
			||||||
@@ -367,12 +373,36 @@ const Project = () => {
 | 
				
			|||||||
      if (taskGroup) {
 | 
					      if (taskGroup) {
 | 
				
			||||||
        let position = 65535;
 | 
					        let position = 65535;
 | 
				
			||||||
        if (taskGroup.tasks.length !== 0) {
 | 
					        if (taskGroup.tasks.length !== 0) {
 | 
				
			||||||
          const [lastTask] = taskGroup.tasks.sort((a: any, b: any) => a.position - b.position).slice(-1);
 | 
					          const [lastTask] = taskGroup.tasks
 | 
				
			||||||
 | 
					            .slice()
 | 
				
			||||||
 | 
					            .sort((a: any, b: any) => a.position - b.position)
 | 
				
			||||||
 | 
					            .slice(-1);
 | 
				
			||||||
          position = Math.ceil(lastTask.position) * 2 + 1;
 | 
					          position = Math.ceil(lastTask.position) * 2 + 1;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        console.log(`position ${position}`);
 | 
					        console.log(`position ${position}`);
 | 
				
			||||||
        createTask({ variables: { taskGroupID, name, position } });
 | 
					        createTask({
 | 
				
			||||||
 | 
					          variables: { taskGroupID, name, position },
 | 
				
			||||||
 | 
					          optimisticResponse: {
 | 
				
			||||||
 | 
					            __typename: 'Mutation',
 | 
				
			||||||
 | 
					            createTask: {
 | 
				
			||||||
 | 
					              __typename: 'Task',
 | 
				
			||||||
 | 
					              id: '' + Math.round(Math.random() * -1000000),
 | 
				
			||||||
 | 
					              name: name,
 | 
				
			||||||
 | 
					              taskGroup: {
 | 
				
			||||||
 | 
					                __typename: 'TaskGroup',
 | 
				
			||||||
 | 
					                id: taskGroup.id,
 | 
				
			||||||
 | 
					                name: taskGroup.name,
 | 
				
			||||||
 | 
					                position: taskGroup.position,
 | 
				
			||||||
 | 
					              },
 | 
				
			||||||
 | 
					              position: position,
 | 
				
			||||||
 | 
					              dueDate: null,
 | 
				
			||||||
 | 
					              description: null,
 | 
				
			||||||
 | 
					              labels: [],
 | 
				
			||||||
 | 
					              assigned: [],
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
@@ -410,6 +440,10 @@ const Project = () => {
 | 
				
			|||||||
  const [assignTask] = useAssignTaskMutation();
 | 
					  const [assignTask] = useAssignTaskMutation();
 | 
				
			||||||
  const [unassignTask] = useUnassignTaskMutation();
 | 
					  const [unassignTask] = useUnassignTaskMutation();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const [updateTaskGroupName] = useUpdateTaskGroupNameMutation({});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const [updateTaskDueDate] = useUpdateTaskDueDateMutation();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const [updateProjectName] = useUpdateProjectNameMutation({
 | 
					  const [updateProjectName] = useUpdateProjectNameMutation({
 | 
				
			||||||
    update: (client, newName) => {
 | 
					    update: (client, newName) => {
 | 
				
			||||||
      const cacheData = getCacheData(client, projectID);
 | 
					      const cacheData = getCacheData(client, projectID);
 | 
				
			||||||
@@ -421,6 +455,8 @@ const Project = () => {
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const [setTaskComplete] = useSetTaskCompleteMutation();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const client = useApolloClient();
 | 
					  const client = useApolloClient();
 | 
				
			||||||
  const { userID } = useContext(UserIDContext);
 | 
					  const { userID } = useContext(UserIDContext);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -441,6 +477,7 @@ const Project = () => {
 | 
				
			|||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (data) {
 | 
					  if (data) {
 | 
				
			||||||
 | 
					    console.log(data.findProject);
 | 
				
			||||||
    const onQuickEditorOpen = (e: ContextMenuEvent) => {
 | 
					    const onQuickEditorOpen = (e: ContextMenuEvent) => {
 | 
				
			||||||
      const taskGroup = data.findProject.taskGroups.find(t => t.id === e.taskGroupID);
 | 
					      const taskGroup = data.findProject.taskGroups.find(t => t.id === e.taskGroupID);
 | 
				
			||||||
      const currentTask = taskGroup ? taskGroup.tasks.find(t => t.id === e.taskID) : null;
 | 
					      const currentTask = taskGroup ? taskGroup.tasks.find(t => t.id === e.taskID) : null;
 | 
				
			||||||
@@ -448,6 +485,7 @@ const Project = () => {
 | 
				
			|||||||
        setQuickCardEditor({
 | 
					        setQuickCardEditor({
 | 
				
			||||||
          top: e.top,
 | 
					          top: e.top,
 | 
				
			||||||
          left: e.left,
 | 
					          left: e.left,
 | 
				
			||||||
 | 
					          width: e.width,
 | 
				
			||||||
          isOpen: true,
 | 
					          isOpen: true,
 | 
				
			||||||
          taskID: currentTask.id,
 | 
					          taskID: currentTask.id,
 | 
				
			||||||
          taskGroupID: currentTask.taskGroup.id,
 | 
					          taskGroupID: currentTask.taskGroup.id,
 | 
				
			||||||
@@ -567,7 +605,9 @@ const Project = () => {
 | 
				
			|||||||
              </Popup>,
 | 
					              </Popup>,
 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
          }}
 | 
					          }}
 | 
				
			||||||
          onChangeTaskGroupName={(taskGroupID, name) => {}}
 | 
					          onChangeTaskGroupName={(taskGroupID, name) => {
 | 
				
			||||||
 | 
					            updateTaskGroupName({ variables: { taskGroupID, name } });
 | 
				
			||||||
 | 
					          }}
 | 
				
			||||||
          onQuickEditorOpen={onQuickEditorOpen}
 | 
					          onQuickEditorOpen={onQuickEditorOpen}
 | 
				
			||||||
          onExtraMenuOpen={(taskGroupID: string, $targetRef: any) => {
 | 
					          onExtraMenuOpen={(taskGroupID: string, $targetRef: any) => {
 | 
				
			||||||
            showPopup(
 | 
					            showPopup(
 | 
				
			||||||
@@ -660,8 +700,37 @@ const Project = () => {
 | 
				
			|||||||
                },
 | 
					                },
 | 
				
			||||||
              })
 | 
					              })
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            onOpenDueDatePopup={($targetRef, task) => {
 | 
				
			||||||
 | 
					              showPopup(
 | 
				
			||||||
 | 
					                $targetRef,
 | 
				
			||||||
 | 
					                <Popup
 | 
				
			||||||
 | 
					                  title={'Change Due Date'}
 | 
				
			||||||
 | 
					                  tab={0}
 | 
				
			||||||
 | 
					                  onClose={() => {
 | 
				
			||||||
 | 
					                    hidePopup();
 | 
				
			||||||
 | 
					                  }}
 | 
				
			||||||
 | 
					                >
 | 
				
			||||||
 | 
					                  <DueDateManager
 | 
				
			||||||
 | 
					                    task={task}
 | 
				
			||||||
 | 
					                    onRemoveDueDate={t => {
 | 
				
			||||||
 | 
					                      updateTaskDueDate({ variables: { taskID: t.id, dueDate: null } });
 | 
				
			||||||
 | 
					                      hidePopup();
 | 
				
			||||||
 | 
					                    }}
 | 
				
			||||||
 | 
					                    onDueDateChange={(t, newDueDate) => {
 | 
				
			||||||
 | 
					                      updateTaskDueDate({ variables: { taskID: t.id, dueDate: newDueDate } });
 | 
				
			||||||
 | 
					                      hidePopup();
 | 
				
			||||||
 | 
					                    }}
 | 
				
			||||||
 | 
					                    onCancel={() => {}}
 | 
				
			||||||
 | 
					                  />
 | 
				
			||||||
 | 
					                </Popup>,
 | 
				
			||||||
 | 
					              );
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					            onToggleComplete={task => {
 | 
				
			||||||
 | 
					              setTaskComplete({ variables: { taskID: task.id, complete: !task.complete } });
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
            top={quickCardEditor.top}
 | 
					            top={quickCardEditor.top}
 | 
				
			||||||
            left={quickCardEditor.left}
 | 
					            left={quickCardEditor.left}
 | 
				
			||||||
 | 
					            width={quickCardEditor.width}
 | 
				
			||||||
          />
 | 
					          />
 | 
				
			||||||
        )}
 | 
					        )}
 | 
				
			||||||
        <Route
 | 
					        <Route
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1
									
								
								web/src/citadel.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								web/src/citadel.d.ts
									
									
									
									
										vendored
									
									
								
							@@ -12,6 +12,7 @@ interface DraggableElement {
 | 
				
			|||||||
type ContextMenuEvent = {
 | 
					type ContextMenuEvent = {
 | 
				
			||||||
  left: number;
 | 
					  left: number;
 | 
				
			||||||
  top: number;
 | 
					  top: number;
 | 
				
			||||||
 | 
					  width: number;
 | 
				
			||||||
  taskID: string;
 | 
					  taskID: string;
 | 
				
			||||||
  taskGroupID: string;
 | 
					  taskGroupID: string;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										19
									
								
								web/src/projects.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										19
									
								
								web/src/projects.d.ts
									
									
									
									
										vendored
									
									
								
							@@ -30,15 +30,34 @@ type TaskLabel = {
 | 
				
			|||||||
  projectLabel: ProjectLabel;
 | 
					  projectLabel: ProjectLabel;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type TaskChecklist = {
 | 
				
			||||||
 | 
					  id: string;
 | 
				
			||||||
 | 
					  position: number;
 | 
				
			||||||
 | 
					  name: string;
 | 
				
			||||||
 | 
					  items: Array<TaskChecklistItem>;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type TaskChecklistItem = {
 | 
				
			||||||
 | 
					  id: string;
 | 
				
			||||||
 | 
					  complete: boolean;
 | 
				
			||||||
 | 
					  position: number;
 | 
				
			||||||
 | 
					  name: string;
 | 
				
			||||||
 | 
					  taskChecklistID: string;
 | 
				
			||||||
 | 
					  assigned?: null | TaskUser;
 | 
				
			||||||
 | 
					  dueDate?: null | string;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Task = {
 | 
					type Task = {
 | 
				
			||||||
  id: string;
 | 
					  id: string;
 | 
				
			||||||
  taskGroup: InnerTaskGroup;
 | 
					  taskGroup: InnerTaskGroup;
 | 
				
			||||||
  name: string;
 | 
					  name: string;
 | 
				
			||||||
  position: number;
 | 
					  position: number;
 | 
				
			||||||
  dueDate?: string;
 | 
					  dueDate?: string;
 | 
				
			||||||
 | 
					  complete?: boolean;
 | 
				
			||||||
  labels: TaskLabel[];
 | 
					  labels: TaskLabel[];
 | 
				
			||||||
  description?: string | null;
 | 
					  description?: string | null;
 | 
				
			||||||
  assigned?: Array<TaskUser>;
 | 
					  assigned?: Array<TaskUser>;
 | 
				
			||||||
 | 
					  checklists?: Array<TaskChecklist> | null;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Project = {
 | 
					type Project = {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,7 +3,15 @@ import TextareaAutosize from 'react-autosize-textarea/lib';
 | 
				
			|||||||
import { mixin } from 'shared/utils/styles';
 | 
					import { mixin } from 'shared/utils/styles';
 | 
				
			||||||
import Button from 'shared/components/Button';
 | 
					import Button from 'shared/components/Button';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const Container = styled.div``;
 | 
					export const Container = styled.div`
 | 
				
			||||||
 | 
					  width: 272px;
 | 
				
			||||||
 | 
					  margin: 0 4px;
 | 
				
			||||||
 | 
					  height: 100%;
 | 
				
			||||||
 | 
					  box-sizing: border-box;
 | 
				
			||||||
 | 
					  display: inline-block;
 | 
				
			||||||
 | 
					  vertical-align: top;
 | 
				
			||||||
 | 
					  white-space: nowrap;
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const Wrapper = styled.div<{ editorOpen: boolean }>`
 | 
					export const Wrapper = styled.div<{ editorOpen: boolean }>`
 | 
				
			||||||
  display: inline-block;
 | 
					  display: inline-block;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -62,7 +62,7 @@ const NameEditor: React.FC<NameEditorProps> = ({ onSave, onCancel }) => {
 | 
				
			|||||||
          Save
 | 
					          Save
 | 
				
			||||||
        </AddListButton>
 | 
					        </AddListButton>
 | 
				
			||||||
        <CancelAdd onClick={() => onCancel()}>
 | 
					        <CancelAdd onClick={() => onCancel()}>
 | 
				
			||||||
          <Cross color="#c2c6dc" />
 | 
					          <Cross width={16} height={16} />
 | 
				
			||||||
        </CancelAdd>
 | 
					        </CancelAdd>
 | 
				
			||||||
      </ListAddControls>
 | 
					      </ListAddControls>
 | 
				
			||||||
    </>
 | 
					    </>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,7 @@ import styled, { css } from 'styled-components';
 | 
				
			|||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 | 
					import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 | 
				
			||||||
import { mixin } from 'shared/utils/styles';
 | 
					import { mixin } from 'shared/utils/styles';
 | 
				
			||||||
import TextareaAutosize from 'react-autosize-textarea';
 | 
					import TextareaAutosize from 'react-autosize-textarea';
 | 
				
			||||||
 | 
					import { CheckCircle } from 'shared/icons';
 | 
				
			||||||
import { RefObject } from 'react';
 | 
					import { RefObject } from 'react';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const ClockIcon = styled(FontAwesomeIcon)``;
 | 
					export const ClockIcon = styled(FontAwesomeIcon)``;
 | 
				
			||||||
@@ -20,9 +21,9 @@ export const EditorTextarea = styled(TextareaAutosize)`
 | 
				
			|||||||
  max-height: 162px;
 | 
					  max-height: 162px;
 | 
				
			||||||
  min-height: 54px;
 | 
					  min-height: 54px;
 | 
				
			||||||
  padding: 0;
 | 
					  padding: 0;
 | 
				
			||||||
  font-size: 16px;
 | 
					  font-size: 14px;
 | 
				
			||||||
  line-height: 20px;
 | 
					  line-height: 16px;
 | 
				
			||||||
  color: rgba(${props => props.theme.colors.text.secondary});
 | 
					  color: rgba(${props => props.theme.colors.text.primary});
 | 
				
			||||||
  &:focus {
 | 
					  &:focus {
 | 
				
			||||||
    border: none;
 | 
					    border: none;
 | 
				
			||||||
    outline: none;
 | 
					    outline: none;
 | 
				
			||||||
@@ -92,11 +93,13 @@ export const ListCardInnerContainer = styled.div`
 | 
				
			|||||||
  height: 100%;
 | 
					  height: 100%;
 | 
				
			||||||
`;
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const ListCardDetails = styled.div`
 | 
					export const ListCardDetails = styled.div<{ complete: boolean }>`
 | 
				
			||||||
  overflow: hidden;
 | 
					  overflow: hidden;
 | 
				
			||||||
  padding: 6px 8px 2px;
 | 
					  padding: 6px 8px 2px;
 | 
				
			||||||
  position: relative;
 | 
					  position: relative;
 | 
				
			||||||
  z-index: 10;
 | 
					  z-index: 10;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ${props => props.complete && 'opacity: 0.6;'}
 | 
				
			||||||
`;
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const ListCardLabels = styled.div`
 | 
					export const ListCardLabels = styled.div`
 | 
				
			||||||
@@ -140,15 +143,28 @@ export const ListCardOperation = styled.span`
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
export const CardTitle = styled.span`
 | 
					export const CardTitle = styled.span`
 | 
				
			||||||
  clear: both;
 | 
					  clear: both;
 | 
				
			||||||
  display: block;
 | 
					 | 
				
			||||||
  margin: 0 0 4px;
 | 
					  margin: 0 0 4px;
 | 
				
			||||||
  overflow: hidden;
 | 
					  overflow: hidden;
 | 
				
			||||||
  text-decoration: none;
 | 
					  text-decoration: none;
 | 
				
			||||||
  word-wrap: break-word;
 | 
					  word-wrap: break-word;
 | 
				
			||||||
 | 
					  line-height: 16px;
 | 
				
			||||||
 | 
					  font-size: 14px;
 | 
				
			||||||
  color: rgba(${props => props.theme.colors.text.primary});
 | 
					  color: rgba(${props => props.theme.colors.text.primary});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  align-items: center;
 | 
				
			||||||
`;
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const CardMembers = styled.div`
 | 
					export const CardMembers = styled.div`
 | 
				
			||||||
  float: right;
 | 
					  float: right;
 | 
				
			||||||
  margin: 0 -2px 4px 0;
 | 
					  margin: 0 -2px 4px 0;
 | 
				
			||||||
`;
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const CompleteIcon = styled(CheckCircle)`
 | 
				
			||||||
 | 
					  fill: rgba(${props => props.theme.colors.success});
 | 
				
			||||||
 | 
					  margin-right: 4px;
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const EditorContent = styled.div`
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,6 +5,8 @@ import { faPencilAlt, faList } from '@fortawesome/free-solid-svg-icons';
 | 
				
			|||||||
import { faClock, faCheckSquare, faEye } from '@fortawesome/free-regular-svg-icons';
 | 
					import { faClock, faCheckSquare, faEye } from '@fortawesome/free-regular-svg-icons';
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  EditorTextarea,
 | 
					  EditorTextarea,
 | 
				
			||||||
 | 
					  EditorContent,
 | 
				
			||||||
 | 
					  CompleteIcon,
 | 
				
			||||||
  DescriptionBadge,
 | 
					  DescriptionBadge,
 | 
				
			||||||
  DueDateCardBadge,
 | 
					  DueDateCardBadge,
 | 
				
			||||||
  ListCardBadges,
 | 
					  ListCardBadges,
 | 
				
			||||||
@@ -35,6 +37,7 @@ type Props = {
 | 
				
			|||||||
  title: string;
 | 
					  title: string;
 | 
				
			||||||
  taskID: string;
 | 
					  taskID: string;
 | 
				
			||||||
  taskGroupID: string;
 | 
					  taskGroupID: string;
 | 
				
			||||||
 | 
					  complete?: boolean;
 | 
				
			||||||
  onContextMenu?: (e: ContextMenuEvent) => void;
 | 
					  onContextMenu?: (e: ContextMenuEvent) => void;
 | 
				
			||||||
  onClick?: (e: React.MouseEvent<HTMLDivElement>) => void;
 | 
					  onClick?: (e: React.MouseEvent<HTMLDivElement>) => void;
 | 
				
			||||||
  description?: null | string;
 | 
					  description?: null | string;
 | 
				
			||||||
@@ -57,6 +60,7 @@ const Card = React.forwardRef(
 | 
				
			|||||||
      onContextMenu,
 | 
					      onContextMenu,
 | 
				
			||||||
      taskID,
 | 
					      taskID,
 | 
				
			||||||
      taskGroupID,
 | 
					      taskGroupID,
 | 
				
			||||||
 | 
					      complete,
 | 
				
			||||||
      onClick,
 | 
					      onClick,
 | 
				
			||||||
      labels,
 | 
					      labels,
 | 
				
			||||||
      title,
 | 
					      title,
 | 
				
			||||||
@@ -101,6 +105,7 @@ const Card = React.forwardRef(
 | 
				
			|||||||
        const pos = $innerCardRef.current.getBoundingClientRect();
 | 
					        const pos = $innerCardRef.current.getBoundingClientRect();
 | 
				
			||||||
        if (onContextMenu) {
 | 
					        if (onContextMenu) {
 | 
				
			||||||
          onContextMenu({
 | 
					          onContextMenu({
 | 
				
			||||||
 | 
					            width: pos.width,
 | 
				
			||||||
            top: pos.top,
 | 
					            top: pos.top,
 | 
				
			||||||
            left: pos.left,
 | 
					            left: pos.left,
 | 
				
			||||||
            taskGroupID,
 | 
					            taskGroupID,
 | 
				
			||||||
@@ -140,7 +145,7 @@ const Card = React.forwardRef(
 | 
				
			|||||||
              <FontAwesomeIcon onClick={onOperationClick} color="#c2c6dc" size="xs" icon={faPencilAlt} />
 | 
					              <FontAwesomeIcon onClick={onOperationClick} color="#c2c6dc" size="xs" icon={faPencilAlt} />
 | 
				
			||||||
            </ListCardOperation>
 | 
					            </ListCardOperation>
 | 
				
			||||||
          )}
 | 
					          )}
 | 
				
			||||||
          <ListCardDetails>
 | 
					          <ListCardDetails complete={complete ?? false}>
 | 
				
			||||||
            <ListCardLabels>
 | 
					            <ListCardLabels>
 | 
				
			||||||
              {labels &&
 | 
					              {labels &&
 | 
				
			||||||
                labels.map(label => (
 | 
					                labels.map(label => (
 | 
				
			||||||
@@ -150,22 +155,28 @@ const Card = React.forwardRef(
 | 
				
			|||||||
                ))}
 | 
					                ))}
 | 
				
			||||||
            </ListCardLabels>
 | 
					            </ListCardLabels>
 | 
				
			||||||
            {editable ? (
 | 
					            {editable ? (
 | 
				
			||||||
              <EditorTextarea
 | 
					              <EditorContent>
 | 
				
			||||||
                onChange={e => {
 | 
					                {complete && <CompleteIcon width={16} height={16} />}
 | 
				
			||||||
                  setCardTitle(e.currentTarget.value);
 | 
					                <EditorTextarea
 | 
				
			||||||
                  if (onCardTitleChange) {
 | 
					                  onChange={e => {
 | 
				
			||||||
                    onCardTitleChange(e.currentTarget.value);
 | 
					                    setCardTitle(e.currentTarget.value);
 | 
				
			||||||
                  }
 | 
					                    if (onCardTitleChange) {
 | 
				
			||||||
                }}
 | 
					                      onCardTitleChange(e.currentTarget.value);
 | 
				
			||||||
                onClick={e => {
 | 
					                    }
 | 
				
			||||||
                  e.stopPropagation();
 | 
					                  }}
 | 
				
			||||||
                }}
 | 
					                  onClick={e => {
 | 
				
			||||||
                onKeyDown={handleKeyDown}
 | 
					                    e.stopPropagation();
 | 
				
			||||||
                value={currentCardTitle}
 | 
					                  }}
 | 
				
			||||||
                ref={$editorRef}
 | 
					                  onKeyDown={handleKeyDown}
 | 
				
			||||||
              />
 | 
					                  value={currentCardTitle}
 | 
				
			||||||
 | 
					                  ref={$editorRef}
 | 
				
			||||||
 | 
					                />
 | 
				
			||||||
 | 
					              </EditorContent>
 | 
				
			||||||
            ) : (
 | 
					            ) : (
 | 
				
			||||||
              <CardTitle>{title}</CardTitle>
 | 
					              <CardTitle>
 | 
				
			||||||
 | 
					                {complete && <CompleteIcon width={16} height={16} />}
 | 
				
			||||||
 | 
					                {title}
 | 
				
			||||||
 | 
					              </CardTitle>
 | 
				
			||||||
            )}
 | 
					            )}
 | 
				
			||||||
            <ListCardBadges>
 | 
					            <ListCardBadges>
 | 
				
			||||||
              {watched && (
 | 
					              {watched && (
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										138
									
								
								web/src/shared/components/Checklist/Checklist.stories.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										138
									
								
								web/src/shared/components/Checklist/Checklist.stories.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,138 @@
 | 
				
			|||||||
 | 
					import React, { useState } from 'react';
 | 
				
			||||||
 | 
					import { action } from '@storybook/addon-actions';
 | 
				
			||||||
 | 
					import BaseStyles from 'App/BaseStyles';
 | 
				
			||||||
 | 
					import NormalizeStyles from 'App/NormalizeStyles';
 | 
				
			||||||
 | 
					import { theme } from 'App/ThemeStyles';
 | 
				
			||||||
 | 
					import produce from 'immer';
 | 
				
			||||||
 | 
					import styled, { ThemeProvider } from 'styled-components';
 | 
				
			||||||
 | 
					import Checklist from '.';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default {
 | 
				
			||||||
 | 
					  component: Checklist,
 | 
				
			||||||
 | 
					  title: 'Checklist',
 | 
				
			||||||
 | 
					  parameters: {
 | 
				
			||||||
 | 
					    backgrounds: [
 | 
				
			||||||
 | 
					      { name: 'gray', value: '#f8f8f8', default: true },
 | 
				
			||||||
 | 
					      { name: 'white', value: '#ffffff' },
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const Container = styled.div`
 | 
				
			||||||
 | 
					  width: 552px;
 | 
				
			||||||
 | 
					  margin: 25px;
 | 
				
			||||||
 | 
					  border: 1px solid rgba(${props => props.theme.colors.bg.primary});
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const defaultItems = [
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    id: '1',
 | 
				
			||||||
 | 
					    position: 1,
 | 
				
			||||||
 | 
					    taskChecklistID: '1',
 | 
				
			||||||
 | 
					    complete: false,
 | 
				
			||||||
 | 
					    name: 'Tasks',
 | 
				
			||||||
 | 
					    assigned: null,
 | 
				
			||||||
 | 
					    dueDate: null,
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    id: '2',
 | 
				
			||||||
 | 
					    taskChecklistID: '1',
 | 
				
			||||||
 | 
					    position: 2,
 | 
				
			||||||
 | 
					    complete: false,
 | 
				
			||||||
 | 
					    name: 'Projects',
 | 
				
			||||||
 | 
					    assigned: null,
 | 
				
			||||||
 | 
					    dueDate: null,
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    id: '3',
 | 
				
			||||||
 | 
					    position: 3,
 | 
				
			||||||
 | 
					    taskChecklistID: '1',
 | 
				
			||||||
 | 
					    complete: false,
 | 
				
			||||||
 | 
					    name: 'Teams',
 | 
				
			||||||
 | 
					    assigned: null,
 | 
				
			||||||
 | 
					    dueDate: null,
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    id: '4',
 | 
				
			||||||
 | 
					    position: 4,
 | 
				
			||||||
 | 
					    complete: false,
 | 
				
			||||||
 | 
					    taskChecklistID: '1',
 | 
				
			||||||
 | 
					    name: 'Organizations',
 | 
				
			||||||
 | 
					    assigned: null,
 | 
				
			||||||
 | 
					    dueDate: null,
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const Default = () => {
 | 
				
			||||||
 | 
					  const [checklistName, setChecklistName] = useState('Checklist');
 | 
				
			||||||
 | 
					  const [items, setItems] = useState(defaultItems);
 | 
				
			||||||
 | 
					  const onToggleItem = (itemID: string, complete: boolean) => {
 | 
				
			||||||
 | 
					    setItems(
 | 
				
			||||||
 | 
					      produce(items, draftState => {
 | 
				
			||||||
 | 
					        const idx = items.findIndex(item => item.id === itemID);
 | 
				
			||||||
 | 
					        if (idx !== -1) {
 | 
				
			||||||
 | 
					          draftState[idx] = {
 | 
				
			||||||
 | 
					            ...draftState[idx],
 | 
				
			||||||
 | 
					            complete,
 | 
				
			||||||
 | 
					          };
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <>
 | 
				
			||||||
 | 
					      <BaseStyles />
 | 
				
			||||||
 | 
					      <NormalizeStyles />
 | 
				
			||||||
 | 
					      <ThemeProvider theme={theme}>
 | 
				
			||||||
 | 
					        <Container>
 | 
				
			||||||
 | 
					          <Checklist
 | 
				
			||||||
 | 
					            name={checklistName}
 | 
				
			||||||
 | 
					            checklistID="checklist-one"
 | 
				
			||||||
 | 
					            items={items}
 | 
				
			||||||
 | 
					            onDeleteChecklist={action('delete checklist')}
 | 
				
			||||||
 | 
					            onChangeName={currentName => {
 | 
				
			||||||
 | 
					              setChecklistName(currentName);
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					            onAddItem={itemName => {
 | 
				
			||||||
 | 
					              let position = 1;
 | 
				
			||||||
 | 
					              const lastItem = items[-1];
 | 
				
			||||||
 | 
					              if (lastItem) {
 | 
				
			||||||
 | 
					                position = lastItem.position * 2 + 1;
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					              setItems([
 | 
				
			||||||
 | 
					                ...items,
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                  id: `${Math.random()}`,
 | 
				
			||||||
 | 
					                  name: itemName,
 | 
				
			||||||
 | 
					                  complete: false,
 | 
				
			||||||
 | 
					                  assigned: null,
 | 
				
			||||||
 | 
					                  dueDate: null,
 | 
				
			||||||
 | 
					                  position,
 | 
				
			||||||
 | 
					                  taskChecklistID: '1',
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					              ]);
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					            onDeleteItem={itemID => {
 | 
				
			||||||
 | 
					              console.log(`itemID ${itemID}`);
 | 
				
			||||||
 | 
					              setItems(items.filter(item => item.id !== itemID));
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					            onChangeItemName={(itemID, currentName) => {
 | 
				
			||||||
 | 
					              setItems(
 | 
				
			||||||
 | 
					                produce(items, draftState => {
 | 
				
			||||||
 | 
					                  const idx = items.findIndex(item => item.id === itemID);
 | 
				
			||||||
 | 
					                  if (idx !== -1) {
 | 
				
			||||||
 | 
					                    draftState[idx] = {
 | 
				
			||||||
 | 
					                      ...draftState[idx],
 | 
				
			||||||
 | 
					                      name: currentName,
 | 
				
			||||||
 | 
					                    };
 | 
				
			||||||
 | 
					                  }
 | 
				
			||||||
 | 
					                }),
 | 
				
			||||||
 | 
					              );
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					            onToggleItem={onToggleItem}
 | 
				
			||||||
 | 
					          />
 | 
				
			||||||
 | 
					        </Container>
 | 
				
			||||||
 | 
					      </ThemeProvider>
 | 
				
			||||||
 | 
					    </>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										596
									
								
								web/src/shared/components/Checklist/index.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										596
									
								
								web/src/shared/components/Checklist/index.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,596 @@
 | 
				
			|||||||
 | 
					import React, { useState, useRef, useEffect } from 'react';
 | 
				
			||||||
 | 
					import styled from 'styled-components';
 | 
				
			||||||
 | 
					import { CheckSquare, Trash, Square, CheckSquareOutline, Clock, Cross, AccountPlus } from 'shared/icons';
 | 
				
			||||||
 | 
					import Button from 'shared/components/Button';
 | 
				
			||||||
 | 
					import TextareaAutosize from 'react-autosize-textarea';
 | 
				
			||||||
 | 
					import Control from 'react-select/src/components/Control';
 | 
				
			||||||
 | 
					import useOnOutsideClick from 'shared/hooks/onOutsideClick';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const Wrapper = styled.div`
 | 
				
			||||||
 | 
					  margin-bottom: 24px;
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const WindowTitle = styled.div`
 | 
				
			||||||
 | 
					  padding: 8px 0;
 | 
				
			||||||
 | 
					  position: relative;
 | 
				
			||||||
 | 
					  margin: 0 0 4px 40px;
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const WindowTitleIcon = styled(CheckSquareOutline)`
 | 
				
			||||||
 | 
					  top: 10px;
 | 
				
			||||||
 | 
					  left: -40px;
 | 
				
			||||||
 | 
					  position: absolute;
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const WindowChecklistTitle = styled.div`
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  justify-content: space-between;
 | 
				
			||||||
 | 
					  align-items: center;
 | 
				
			||||||
 | 
					  flex-flow: row wrap;
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const WindowTitleText = styled.h3`
 | 
				
			||||||
 | 
					  cursor: pointer;
 | 
				
			||||||
 | 
					  color: rgba(${props => props.theme.colors.text.primary});
 | 
				
			||||||
 | 
					  margin: 6px 0;
 | 
				
			||||||
 | 
					  display: inline-block;
 | 
				
			||||||
 | 
					  width: auto;
 | 
				
			||||||
 | 
					  min-height: 18px;
 | 
				
			||||||
 | 
					  font-size: 16px;
 | 
				
			||||||
 | 
					  line-height: 20px;
 | 
				
			||||||
 | 
					  min-width: 40px;
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const WindowOptions = styled.div`
 | 
				
			||||||
 | 
					  margin: 0 2px 0 auto;
 | 
				
			||||||
 | 
					  float: right;
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const DeleteButton = styled(Button)`
 | 
				
			||||||
 | 
					  padding: 6px 12px;
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ChecklistProgress = styled.div`
 | 
				
			||||||
 | 
					  margin-bottom: 6px;
 | 
				
			||||||
 | 
					  position: relative;
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					const ChecklistProgressPercent = styled.span`
 | 
				
			||||||
 | 
					  color: #5e6c84;
 | 
				
			||||||
 | 
					  font-size: 11px;
 | 
				
			||||||
 | 
					  line-height: 10px;
 | 
				
			||||||
 | 
					  position: absolute;
 | 
				
			||||||
 | 
					  left: 5px;
 | 
				
			||||||
 | 
					  top: -1px;
 | 
				
			||||||
 | 
					  text-align: center;
 | 
				
			||||||
 | 
					  width: 32px;
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ChecklistProgressBar = styled.div`
 | 
				
			||||||
 | 
					  background: rgba(${props => props.theme.colors.bg.primary});
 | 
				
			||||||
 | 
					  border-radius: 4px;
 | 
				
			||||||
 | 
					  clear: both;
 | 
				
			||||||
 | 
					  height: 8px;
 | 
				
			||||||
 | 
					  margin: 0 0 0 40px;
 | 
				
			||||||
 | 
					  overflow: hidden;
 | 
				
			||||||
 | 
					  position: relative;
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					const ChecklistProgressBarCurrent = styled.div<{ width: number }>`
 | 
				
			||||||
 | 
					  width: ${props => props.width}%;
 | 
				
			||||||
 | 
					  background: rgba(${props => (props.width === 100 ? props.theme.colors.success : props.theme.colors.primary)});
 | 
				
			||||||
 | 
					  bottom: 0;
 | 
				
			||||||
 | 
					  left: 0;
 | 
				
			||||||
 | 
					  position: absolute;
 | 
				
			||||||
 | 
					  top: 0;
 | 
				
			||||||
 | 
					  transition: width 0.14s ease-in, background 0.14s ease-in;
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ChecklistItems = styled.div`
 | 
				
			||||||
 | 
					  min-height: 8px;
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ChecklistItemUncheckedIcon = styled(Square)``;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ChecklistIcon = styled.div`
 | 
				
			||||||
 | 
					  cursor: pointer;
 | 
				
			||||||
 | 
					  position: absolute;
 | 
				
			||||||
 | 
					  left: 0;
 | 
				
			||||||
 | 
					  top: 0;
 | 
				
			||||||
 | 
					  margin: 10px;
 | 
				
			||||||
 | 
					  text-align: center;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  &:hover {
 | 
				
			||||||
 | 
					    opacity: 0.8;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ChecklistItemCheckedIcon = styled(CheckSquare)`
 | 
				
			||||||
 | 
					  fill: rgba(${props => props.theme.colors.primary});
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ChecklistItemDetails = styled.div`
 | 
				
			||||||
 | 
					  word-break: break-word;
 | 
				
			||||||
 | 
					  word-wrap: break-word;
 | 
				
			||||||
 | 
					  overflow-wrap: break-word;
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					const ChecklistItemRow = styled.div`
 | 
				
			||||||
 | 
					  cursor: pointer;
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  flex-direction: row;
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ChecklistItemTextControls = styled.div`
 | 
				
			||||||
 | 
					  padding: 6px 0;
 | 
				
			||||||
 | 
					  width: 100%;
 | 
				
			||||||
 | 
					  display: inline-flex;
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ChecklistItemText = styled.span<{ complete: boolean }>`
 | 
				
			||||||
 | 
					  color: ${props => (props.complete ? '#5e6c84' : `rgba(${props.theme.colors.text.primary})`)};
 | 
				
			||||||
 | 
					  ${props => props.complete && 'text-decoration: line-through;'}
 | 
				
			||||||
 | 
					  line-height: 20px;
 | 
				
			||||||
 | 
					  font-size: 16px;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  min-height: 20px;
 | 
				
			||||||
 | 
					  margin-bottom: 0;
 | 
				
			||||||
 | 
					  align-self: center;
 | 
				
			||||||
 | 
					  flex: 1;
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ChecklistControls = styled.div`
 | 
				
			||||||
 | 
					  display: inline-flex;
 | 
				
			||||||
 | 
					  flex-direction: row;
 | 
				
			||||||
 | 
					  float: right;
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ControlButton = styled.div`
 | 
				
			||||||
 | 
					  opacity: 0;
 | 
				
			||||||
 | 
					  margin-left: 4px;
 | 
				
			||||||
 | 
					  padding: 4px 6px;
 | 
				
			||||||
 | 
					  border-radius: 6px;
 | 
				
			||||||
 | 
					  background-color: rgba(${props => props.theme.colors.bg.primary}, 0.8);
 | 
				
			||||||
 | 
					  &:hover {
 | 
				
			||||||
 | 
					    background-color: rgba(${props => props.theme.colors.primary}, 1);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ChecklistNameEditorWrapper = styled.div`
 | 
				
			||||||
 | 
					  display: block;
 | 
				
			||||||
 | 
					  float: left;
 | 
				
			||||||
 | 
					  padding-top: 6px;
 | 
				
			||||||
 | 
					  padding-bottom: 8px;
 | 
				
			||||||
 | 
					  z-index: 50;
 | 
				
			||||||
 | 
					  width: 100%;
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					export const ChecklistNameEditor = styled(TextareaAutosize)`
 | 
				
			||||||
 | 
					  overflow: hidden;
 | 
				
			||||||
 | 
					  overflow-wrap: break-word;
 | 
				
			||||||
 | 
					  resize: none;
 | 
				
			||||||
 | 
					  height: 54px;
 | 
				
			||||||
 | 
					  width: 100%;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  background: none;
 | 
				
			||||||
 | 
					  border: none;
 | 
				
			||||||
 | 
					  box-shadow: none;
 | 
				
			||||||
 | 
					  max-height: 162px;
 | 
				
			||||||
 | 
					  min-height: 54px;
 | 
				
			||||||
 | 
					  padding: 8px 12px;
 | 
				
			||||||
 | 
					  font-size: 16px;
 | 
				
			||||||
 | 
					  line-height: 20px;
 | 
				
			||||||
 | 
					  border: 1px solid rgba(${props => props.theme.colors.primary});
 | 
				
			||||||
 | 
					  border-radius: 3px;
 | 
				
			||||||
 | 
					  color: rgba(${props => props.theme.colors.text.primary});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  border-color: rgba(${props => props.theme.colors.border});
 | 
				
			||||||
 | 
					  background-color: rgba(${props => props.theme.colors.bg.primary}, 0.4);
 | 
				
			||||||
 | 
					  &:focus {
 | 
				
			||||||
 | 
					    border-color: rgba(${props => props.theme.colors.primary});
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const AssignUserButton = styled(AccountPlus)`
 | 
				
			||||||
 | 
					  fill: rgba(${props => props.theme.colors.text.primary});
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ClockButton = styled(Clock)`
 | 
				
			||||||
 | 
					  fill: rgba(${props => props.theme.colors.text.primary});
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const TrashButton = styled(Trash)`
 | 
				
			||||||
 | 
					  fill: rgba(${props => props.theme.colors.text.primary});
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ChecklistItemWrapper = styled.div`
 | 
				
			||||||
 | 
					  user-select: none;
 | 
				
			||||||
 | 
					  clear: both;
 | 
				
			||||||
 | 
					  padding-left: 40px;
 | 
				
			||||||
 | 
					  position: relative;
 | 
				
			||||||
 | 
					  border-radius: 6px;
 | 
				
			||||||
 | 
					  transform-origin: left bottom;
 | 
				
			||||||
 | 
					  transition-property: transform, opacity, height, padding, margin;
 | 
				
			||||||
 | 
					  transition-duration: 0.14s;
 | 
				
			||||||
 | 
					  transition-timing-function: ease-in;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  &:hover {
 | 
				
			||||||
 | 
					    background-color: rgba(${props => props.theme.colors.bg.primary}, 0.4);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  &:hover ${ControlButton} {
 | 
				
			||||||
 | 
					    opacity: 1;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const EditControls = styled.div`
 | 
				
			||||||
 | 
					  clear: both;
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  padding-bottom: 9px;
 | 
				
			||||||
 | 
					  flex-direction: row;
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const SaveButton = styled(Button)`
 | 
				
			||||||
 | 
					  margin-right: 4px;
 | 
				
			||||||
 | 
					  padding: 6px 12px;
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					const CancelButton = styled.div`
 | 
				
			||||||
 | 
					  cursor: pointer;
 | 
				
			||||||
 | 
					  margin: 5px;
 | 
				
			||||||
 | 
					  & svg {
 | 
				
			||||||
 | 
					    fill: rgba(${props => props.theme.colors.text.primary});
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  &:hover svg {
 | 
				
			||||||
 | 
					    fill: rgba(${props => props.theme.colors.text.secondary});
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const Spacer = styled.div`
 | 
				
			||||||
 | 
					  flex: 1;
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const EditableDeleteButton = styled.button`
 | 
				
			||||||
 | 
					  cursor: pointer;
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  margin: 0 2px;
 | 
				
			||||||
 | 
					  padding: 6px 8px;
 | 
				
			||||||
 | 
					  border-radius: 3px;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  &:hover {
 | 
				
			||||||
 | 
					    background: rgba(${props => props.theme.colors.primary}, 0.8);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const NewItemButton = styled(Button)`
 | 
				
			||||||
 | 
					  padding: 6px 8px;
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ChecklistNewItem = styled.div`
 | 
				
			||||||
 | 
					  margin: 8px 0;
 | 
				
			||||||
 | 
					  margin-left: 40px;
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ChecklistItemProps = {
 | 
				
			||||||
 | 
					  itemID: string;
 | 
				
			||||||
 | 
					  complete: boolean;
 | 
				
			||||||
 | 
					  name: string;
 | 
				
			||||||
 | 
					  onChangeName: (itemID: string, currentName: string) => void;
 | 
				
			||||||
 | 
					  onToggleItem: (itemID: string, complete: boolean) => void;
 | 
				
			||||||
 | 
					  onDeleteItem: (itemID: string) => void;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ChecklistItem: React.FC<ChecklistItemProps> = ({
 | 
				
			||||||
 | 
					  itemID,
 | 
				
			||||||
 | 
					  complete,
 | 
				
			||||||
 | 
					  name,
 | 
				
			||||||
 | 
					  onChangeName,
 | 
				
			||||||
 | 
					  onToggleItem,
 | 
				
			||||||
 | 
					  onDeleteItem,
 | 
				
			||||||
 | 
					}) => {
 | 
				
			||||||
 | 
					  const $item = useRef<HTMLDivElement>(null);
 | 
				
			||||||
 | 
					  const $editor = useRef<HTMLTextAreaElement>(null);
 | 
				
			||||||
 | 
					  const [editting, setEditting] = useState(false);
 | 
				
			||||||
 | 
					  const [currentName, setCurrentName] = useState(name);
 | 
				
			||||||
 | 
					  useEffect(() => {
 | 
				
			||||||
 | 
					    if (editting && $editor && $editor.current) {
 | 
				
			||||||
 | 
					      $editor.current.focus();
 | 
				
			||||||
 | 
					      $editor.current.select();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }, [editting]);
 | 
				
			||||||
 | 
					  useOnOutsideClick($item, true, () => setEditting(false), null);
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <ChecklistItemWrapper ref={$item}>
 | 
				
			||||||
 | 
					      <ChecklistIcon
 | 
				
			||||||
 | 
					        onClick={e => {
 | 
				
			||||||
 | 
					          e.stopPropagation();
 | 
				
			||||||
 | 
					          onToggleItem(itemID, !complete);
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					        {complete ? (
 | 
				
			||||||
 | 
					          <ChecklistItemCheckedIcon width={20} height={20} />
 | 
				
			||||||
 | 
					        ) : (
 | 
				
			||||||
 | 
					          <ChecklistItemUncheckedIcon width={20} height={20} />
 | 
				
			||||||
 | 
					        )}
 | 
				
			||||||
 | 
					      </ChecklistIcon>
 | 
				
			||||||
 | 
					      {editting ? (
 | 
				
			||||||
 | 
					        <>
 | 
				
			||||||
 | 
					          <ChecklistNameEditorWrapper>
 | 
				
			||||||
 | 
					            <ChecklistNameEditor
 | 
				
			||||||
 | 
					              ref={$editor}
 | 
				
			||||||
 | 
					              onKeyDown={e => {
 | 
				
			||||||
 | 
					                if (e.key === 'Enter') {
 | 
				
			||||||
 | 
					                  onChangeName(itemID, currentName);
 | 
				
			||||||
 | 
					                  setEditting(false);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					              }}
 | 
				
			||||||
 | 
					              onChange={e => {
 | 
				
			||||||
 | 
					                setCurrentName(e.currentTarget.value);
 | 
				
			||||||
 | 
					              }}
 | 
				
			||||||
 | 
					              value={currentName}
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					          </ChecklistNameEditorWrapper>
 | 
				
			||||||
 | 
					          <EditControls>
 | 
				
			||||||
 | 
					            <SaveButton
 | 
				
			||||||
 | 
					              onClick={() => {
 | 
				
			||||||
 | 
					                onChangeName(itemID, currentName);
 | 
				
			||||||
 | 
					                setEditting(false);
 | 
				
			||||||
 | 
					              }}
 | 
				
			||||||
 | 
					              variant="relief"
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
 | 
					              Save
 | 
				
			||||||
 | 
					            </SaveButton>
 | 
				
			||||||
 | 
					            <CancelButton
 | 
				
			||||||
 | 
					              onClick={e => {
 | 
				
			||||||
 | 
					                e.stopPropagation();
 | 
				
			||||||
 | 
					                setEditting(false);
 | 
				
			||||||
 | 
					              }}
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
 | 
					              <Cross width={20} height={20} />
 | 
				
			||||||
 | 
					            </CancelButton>
 | 
				
			||||||
 | 
					            <Spacer />
 | 
				
			||||||
 | 
					            <EditableDeleteButton
 | 
				
			||||||
 | 
					              onClick={e => {
 | 
				
			||||||
 | 
					                e.stopPropagation();
 | 
				
			||||||
 | 
					                setEditting(false);
 | 
				
			||||||
 | 
					                onDeleteItem(itemID);
 | 
				
			||||||
 | 
					              }}
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
 | 
					              <Trash width={16} height={16} />
 | 
				
			||||||
 | 
					            </EditableDeleteButton>
 | 
				
			||||||
 | 
					          </EditControls>
 | 
				
			||||||
 | 
					        </>
 | 
				
			||||||
 | 
					      ) : (
 | 
				
			||||||
 | 
					        <ChecklistItemDetails
 | 
				
			||||||
 | 
					          onClick={() => {
 | 
				
			||||||
 | 
					            setEditting(true);
 | 
				
			||||||
 | 
					          }}
 | 
				
			||||||
 | 
					        >
 | 
				
			||||||
 | 
					          <ChecklistItemRow>
 | 
				
			||||||
 | 
					            <ChecklistItemTextControls>
 | 
				
			||||||
 | 
					              <ChecklistItemText complete={complete}>{name}</ChecklistItemText>
 | 
				
			||||||
 | 
					              <ChecklistControls>
 | 
				
			||||||
 | 
					                <ControlButton>
 | 
				
			||||||
 | 
					                  <AssignUserButton width={14} height={14} />
 | 
				
			||||||
 | 
					                </ControlButton>
 | 
				
			||||||
 | 
					                <ControlButton>
 | 
				
			||||||
 | 
					                  <ClockButton width={14} height={14} />
 | 
				
			||||||
 | 
					                </ControlButton>
 | 
				
			||||||
 | 
					                <ControlButton
 | 
				
			||||||
 | 
					                  onClick={e => {
 | 
				
			||||||
 | 
					                    e.stopPropagation();
 | 
				
			||||||
 | 
					                    onDeleteItem(itemID);
 | 
				
			||||||
 | 
					                  }}
 | 
				
			||||||
 | 
					                >
 | 
				
			||||||
 | 
					                  <TrashButton width={14} height={14} />
 | 
				
			||||||
 | 
					                </ControlButton>
 | 
				
			||||||
 | 
					              </ChecklistControls>
 | 
				
			||||||
 | 
					            </ChecklistItemTextControls>
 | 
				
			||||||
 | 
					          </ChecklistItemRow>
 | 
				
			||||||
 | 
					        </ChecklistItemDetails>
 | 
				
			||||||
 | 
					      )}
 | 
				
			||||||
 | 
					    </ChecklistItemWrapper>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type AddNewItemProps = {
 | 
				
			||||||
 | 
					  onAddItem: (name: string) => void;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const AddNewItem: React.FC<AddNewItemProps> = ({ onAddItem }) => {
 | 
				
			||||||
 | 
					  const $editor = useRef<HTMLTextAreaElement>(null);
 | 
				
			||||||
 | 
					  const $wrapper = useRef<HTMLDivElement>(null);
 | 
				
			||||||
 | 
					  const [currentName, setCurrentName] = useState('');
 | 
				
			||||||
 | 
					  const [editting, setEditting] = useState(false);
 | 
				
			||||||
 | 
					  useEffect(() => {
 | 
				
			||||||
 | 
					    if (editting && $editor && $editor.current) {
 | 
				
			||||||
 | 
					      $editor.current.focus();
 | 
				
			||||||
 | 
					      $editor.current.select();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }, [editting]);
 | 
				
			||||||
 | 
					  useOnOutsideClick($wrapper, true, () => setEditting(false), null);
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <ChecklistNewItem ref={$wrapper}>
 | 
				
			||||||
 | 
					      {editting ? (
 | 
				
			||||||
 | 
					        <>
 | 
				
			||||||
 | 
					          <ChecklistNameEditorWrapper>
 | 
				
			||||||
 | 
					            <ChecklistNameEditor
 | 
				
			||||||
 | 
					              ref={$editor}
 | 
				
			||||||
 | 
					              onKeyDown={e => {
 | 
				
			||||||
 | 
					                if (e.key === 'Enter') {
 | 
				
			||||||
 | 
					                  e.preventDefault();
 | 
				
			||||||
 | 
					                  onAddItem(currentName);
 | 
				
			||||||
 | 
					                  setCurrentName('');
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					              }}
 | 
				
			||||||
 | 
					              onChange={e => {
 | 
				
			||||||
 | 
					                setCurrentName(e.currentTarget.value);
 | 
				
			||||||
 | 
					              }}
 | 
				
			||||||
 | 
					              value={currentName}
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					          </ChecklistNameEditorWrapper>
 | 
				
			||||||
 | 
					          <EditControls>
 | 
				
			||||||
 | 
					            <SaveButton
 | 
				
			||||||
 | 
					              onClick={() => {
 | 
				
			||||||
 | 
					                onAddItem(currentName);
 | 
				
			||||||
 | 
					                setCurrentName('');
 | 
				
			||||||
 | 
					                if (editting && $editor && $editor.current) {
 | 
				
			||||||
 | 
					                  $editor.current.focus();
 | 
				
			||||||
 | 
					                  $editor.current.select();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					              }}
 | 
				
			||||||
 | 
					              variant="relief"
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
 | 
					              Save
 | 
				
			||||||
 | 
					            </SaveButton>
 | 
				
			||||||
 | 
					            <CancelButton
 | 
				
			||||||
 | 
					              onClick={e => {
 | 
				
			||||||
 | 
					                e.stopPropagation();
 | 
				
			||||||
 | 
					                setEditting(false);
 | 
				
			||||||
 | 
					              }}
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
 | 
					              <Cross width={20} height={20} />
 | 
				
			||||||
 | 
					            </CancelButton>
 | 
				
			||||||
 | 
					          </EditControls>
 | 
				
			||||||
 | 
					        </>
 | 
				
			||||||
 | 
					      ) : (
 | 
				
			||||||
 | 
					        <NewItemButton onClick={() => setEditting(true)}>Add an item</NewItemButton>
 | 
				
			||||||
 | 
					      )}
 | 
				
			||||||
 | 
					    </ChecklistNewItem>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ChecklistTitleEditorProps = {
 | 
				
			||||||
 | 
					  name: string;
 | 
				
			||||||
 | 
					  onChangeName: (item: string) => void;
 | 
				
			||||||
 | 
					  onCancel: () => void;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ChecklistTitleEditor = React.forwardRef(
 | 
				
			||||||
 | 
					  ({ name, onChangeName, onCancel }: ChecklistTitleEditorProps, $name: any) => {
 | 
				
			||||||
 | 
					    const [currentName, setCurrentName] = useState(name);
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					      <>
 | 
				
			||||||
 | 
					        <ChecklistNameEditor
 | 
				
			||||||
 | 
					          ref={$name}
 | 
				
			||||||
 | 
					          value={currentName}
 | 
				
			||||||
 | 
					          onChange={e => {
 | 
				
			||||||
 | 
					            setCurrentName(e.currentTarget.value);
 | 
				
			||||||
 | 
					          }}
 | 
				
			||||||
 | 
					          onKeyDown={e => {
 | 
				
			||||||
 | 
					            if (e.key === 'Enter') {
 | 
				
			||||||
 | 
					              onChangeName(currentName);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          }}
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					        <EditControls>
 | 
				
			||||||
 | 
					          <SaveButton
 | 
				
			||||||
 | 
					            onClick={() => {
 | 
				
			||||||
 | 
					              onChangeName(currentName);
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					            variant="relief"
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            Save
 | 
				
			||||||
 | 
					          </SaveButton>
 | 
				
			||||||
 | 
					          <CancelButton
 | 
				
			||||||
 | 
					            onClick={e => {
 | 
				
			||||||
 | 
					              e.stopPropagation();
 | 
				
			||||||
 | 
					              onCancel();
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            <Cross width={20} height={20} />
 | 
				
			||||||
 | 
					          </CancelButton>
 | 
				
			||||||
 | 
					        </EditControls>
 | 
				
			||||||
 | 
					      </>
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					type ChecklistProps = {
 | 
				
			||||||
 | 
					  checklistID: string;
 | 
				
			||||||
 | 
					  onDeleteChecklist: (checklistID: string) => void;
 | 
				
			||||||
 | 
					  name: string;
 | 
				
			||||||
 | 
					  onChangeName: (item: string) => void;
 | 
				
			||||||
 | 
					  onToggleItem: (taskID: string, complete: boolean) => void;
 | 
				
			||||||
 | 
					  onChangeItemName: (itemID: string, currentName: string) => void;
 | 
				
			||||||
 | 
					  onDeleteItem: (itemID: string) => void;
 | 
				
			||||||
 | 
					  onAddItem: (itemName: string) => void;
 | 
				
			||||||
 | 
					  items: Array<TaskChecklistItem>;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const Checklist: React.FC<ChecklistProps> = ({
 | 
				
			||||||
 | 
					  checklistID,
 | 
				
			||||||
 | 
					  onDeleteChecklist,
 | 
				
			||||||
 | 
					  name,
 | 
				
			||||||
 | 
					  items,
 | 
				
			||||||
 | 
					  onToggleItem,
 | 
				
			||||||
 | 
					  onAddItem,
 | 
				
			||||||
 | 
					  onChangeItemName,
 | 
				
			||||||
 | 
					  onChangeName,
 | 
				
			||||||
 | 
					  onDeleteItem,
 | 
				
			||||||
 | 
					}) => {
 | 
				
			||||||
 | 
					  const $name = useRef<HTMLTextAreaElement>(null);
 | 
				
			||||||
 | 
					  const complete = items.reduce((prev, item) => prev + (item.complete ? 1 : 0), 0);
 | 
				
			||||||
 | 
					  const percent = items.length === 0 ? 0 : Math.floor((complete / items.length) * 100);
 | 
				
			||||||
 | 
					  const [editting, setEditting] = useState(false);
 | 
				
			||||||
 | 
					  // useOnOutsideClick($name, true, () => setEditting(false), null);
 | 
				
			||||||
 | 
					  useEffect(() => {
 | 
				
			||||||
 | 
					    if (editting && $name && $name.current) {
 | 
				
			||||||
 | 
					      $name.current.focus();
 | 
				
			||||||
 | 
					      $name.current.select();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }, [editting]);
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <Wrapper>
 | 
				
			||||||
 | 
					      <WindowTitle>
 | 
				
			||||||
 | 
					        <WindowTitleIcon width={24} height={24} />
 | 
				
			||||||
 | 
					        {editting ? (
 | 
				
			||||||
 | 
					          <ChecklistTitleEditor
 | 
				
			||||||
 | 
					            ref={$name}
 | 
				
			||||||
 | 
					            name={name}
 | 
				
			||||||
 | 
					            onChangeName={currentName => {
 | 
				
			||||||
 | 
					              onChangeName(currentName);
 | 
				
			||||||
 | 
					              setEditting(false);
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					            onCancel={() => {
 | 
				
			||||||
 | 
					              setEditting(false);
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					          />
 | 
				
			||||||
 | 
					        ) : (
 | 
				
			||||||
 | 
					          <WindowChecklistTitle>
 | 
				
			||||||
 | 
					            <WindowTitleText onClick={() => setEditting(true)}>{name}</WindowTitleText>
 | 
				
			||||||
 | 
					            <WindowOptions>
 | 
				
			||||||
 | 
					              <DeleteButton
 | 
				
			||||||
 | 
					                onClick={() => {
 | 
				
			||||||
 | 
					                  onDeleteChecklist(checklistID);
 | 
				
			||||||
 | 
					                }}
 | 
				
			||||||
 | 
					                color="danger"
 | 
				
			||||||
 | 
					                variant="outline"
 | 
				
			||||||
 | 
					              >
 | 
				
			||||||
 | 
					                Delete
 | 
				
			||||||
 | 
					              </DeleteButton>
 | 
				
			||||||
 | 
					            </WindowOptions>
 | 
				
			||||||
 | 
					          </WindowChecklistTitle>
 | 
				
			||||||
 | 
					        )}
 | 
				
			||||||
 | 
					      </WindowTitle>
 | 
				
			||||||
 | 
					      <ChecklistProgress>
 | 
				
			||||||
 | 
					        <ChecklistProgressPercent>{`${percent}%`}</ChecklistProgressPercent>
 | 
				
			||||||
 | 
					        <ChecklistProgressBar>
 | 
				
			||||||
 | 
					          <ChecklistProgressBarCurrent width={percent} />
 | 
				
			||||||
 | 
					        </ChecklistProgressBar>
 | 
				
			||||||
 | 
					      </ChecklistProgress>
 | 
				
			||||||
 | 
					      <ChecklistItems>
 | 
				
			||||||
 | 
					        {items
 | 
				
			||||||
 | 
					          .slice()
 | 
				
			||||||
 | 
					          .sort((a, b) => a.position - b.position)
 | 
				
			||||||
 | 
					          .map(item => (
 | 
				
			||||||
 | 
					            <ChecklistItem
 | 
				
			||||||
 | 
					              key={item.id}
 | 
				
			||||||
 | 
					              itemID={item.id}
 | 
				
			||||||
 | 
					              name={item.name}
 | 
				
			||||||
 | 
					              complete={item.complete}
 | 
				
			||||||
 | 
					              onDeleteItem={onDeleteItem}
 | 
				
			||||||
 | 
					              onChangeName={onChangeItemName}
 | 
				
			||||||
 | 
					              onToggleItem={onToggleItem}
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					          ))}
 | 
				
			||||||
 | 
					      </ChecklistItems>
 | 
				
			||||||
 | 
					      <AddNewItem onAddItem={onAddItem} />
 | 
				
			||||||
 | 
					    </Wrapper>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Checklist;
 | 
				
			||||||
@@ -64,6 +64,7 @@ export const Default = () => {
 | 
				
			|||||||
              }}
 | 
					              }}
 | 
				
			||||||
              onCancel={action('cancel')}
 | 
					              onCancel={action('cancel')}
 | 
				
			||||||
              onDueDateChange={action('due date change')}
 | 
					              onDueDateChange={action('due date change')}
 | 
				
			||||||
 | 
					              onRemoveDueDate={action('remove due date')}
 | 
				
			||||||
            />
 | 
					            />
 | 
				
			||||||
          </Popup>
 | 
					          </Popup>
 | 
				
			||||||
        </PopupWrapper>
 | 
					        </PopupWrapper>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -102,11 +102,15 @@ export const DueDatePickerWrapper = styled.div`
 | 
				
			|||||||
`;
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const ConfirmAddDueDate = styled(Button)`
 | 
					export const ConfirmAddDueDate = styled(Button)`
 | 
				
			||||||
  float: left;
 | 
					 | 
				
			||||||
  margin: 0 4px 0 0;
 | 
					  margin: 0 4px 0 0;
 | 
				
			||||||
  padding: 6px 12px;
 | 
					  padding: 6px 12px;
 | 
				
			||||||
`;
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const RemoveDueDate = styled(Button)`
 | 
				
			||||||
 | 
					  padding: 6px 12px;
 | 
				
			||||||
 | 
					  margin: 0 0 0 4px;
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const CancelDueDate = styled.div`
 | 
					export const CancelDueDate = styled.div`
 | 
				
			||||||
  display: flex;
 | 
					  display: flex;
 | 
				
			||||||
  align-items: center;
 | 
					  align-items: center;
 | 
				
			||||||
@@ -126,4 +130,5 @@ export const ActionWrapper = styled.div`
 | 
				
			|||||||
  padding-top: 8px;
 | 
					  padding-top: 8px;
 | 
				
			||||||
  width: 100%;
 | 
					  width: 100%;
 | 
				
			||||||
  display: flex;
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  justify-content: space-between;
 | 
				
			||||||
`;
 | 
					`;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,7 +5,15 @@ import DatePicker from 'react-datepicker';
 | 
				
			|||||||
import { Cross } from 'shared/icons';
 | 
					import { Cross } from 'shared/icons';
 | 
				
			||||||
import _ from 'lodash';
 | 
					import _ from 'lodash';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Wrapper, ActionWrapper, DueDateInput, DueDatePickerWrapper, ConfirmAddDueDate, CancelDueDate } from './Styles';
 | 
					import {
 | 
				
			||||||
 | 
					  Wrapper,
 | 
				
			||||||
 | 
					  ActionWrapper,
 | 
				
			||||||
 | 
					  RemoveDueDate,
 | 
				
			||||||
 | 
					  DueDateInput,
 | 
				
			||||||
 | 
					  DueDatePickerWrapper,
 | 
				
			||||||
 | 
					  ConfirmAddDueDate,
 | 
				
			||||||
 | 
					  CancelDueDate,
 | 
				
			||||||
 | 
					} from './Styles';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import 'react-datepicker/dist/react-datepicker.css';
 | 
					import 'react-datepicker/dist/react-datepicker.css';
 | 
				
			||||||
import { getYear, getMonth } from 'date-fns';
 | 
					import { getYear, getMonth } from 'date-fns';
 | 
				
			||||||
@@ -14,6 +22,7 @@ import { useForm } from 'react-hook-form';
 | 
				
			|||||||
type DueDateManagerProps = {
 | 
					type DueDateManagerProps = {
 | 
				
			||||||
  task: Task;
 | 
					  task: Task;
 | 
				
			||||||
  onDueDateChange: (task: Task, newDueDate: Date) => void;
 | 
					  onDueDateChange: (task: Task, newDueDate: Date) => void;
 | 
				
			||||||
 | 
					  onRemoveDueDate: (task: Task) => void;
 | 
				
			||||||
  onCancel: () => void;
 | 
					  onCancel: () => void;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -109,7 +118,7 @@ const HeaderActions = styled.div`
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
`;
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const DueDateManager: React.FC<DueDateManagerProps> = ({ task, onDueDateChange, onCancel }) => {
 | 
					const DueDateManager: React.FC<DueDateManagerProps> = ({ task, onDueDateChange, onRemoveDueDate, onCancel }) => {
 | 
				
			||||||
  const now = moment();
 | 
					  const now = moment();
 | 
				
			||||||
  const [textStartDate, setTextStartDate] = useState(now.format('YYYY-MM-DD'));
 | 
					  const [textStartDate, setTextStartDate] = useState(now.format('YYYY-MM-DD'));
 | 
				
			||||||
  const [startDate, setStartDate] = useState(new Date());
 | 
					  const [startDate, setStartDate] = useState(new Date());
 | 
				
			||||||
@@ -260,19 +269,18 @@ const DueDateManager: React.FC<DueDateManagerProps> = ({ task, onDueDateChange,
 | 
				
			|||||||
          />
 | 
					          />
 | 
				
			||||||
        </DueDatePickerWrapper>
 | 
					        </DueDatePickerWrapper>
 | 
				
			||||||
        <ActionWrapper>
 | 
					        <ActionWrapper>
 | 
				
			||||||
          <ConfirmAddDueDate
 | 
					          <ConfirmAddDueDate type="submit" onClick={() => {}}>
 | 
				
			||||||
            type="submit"
 | 
					 | 
				
			||||||
            onClick={() => {
 | 
					 | 
				
			||||||
              // const newDate = moment(startDate).format('YYYY-MM-DD');
 | 
					 | 
				
			||||||
              // const newTime = moment(endTime).format('h:mm A');
 | 
					 | 
				
			||||||
              // onDueDateChange(task, moment(`${newDate} ${newTime}`, 'YYYY-MM-DD h:mm A').toDate());
 | 
					 | 
				
			||||||
            }}
 | 
					 | 
				
			||||||
          >
 | 
					 | 
				
			||||||
            Save
 | 
					            Save
 | 
				
			||||||
          </ConfirmAddDueDate>
 | 
					          </ConfirmAddDueDate>
 | 
				
			||||||
          <CancelDueDate onClick={onCancel}>
 | 
					          <RemoveDueDate
 | 
				
			||||||
            <Cross size={16} color="#c2c6dc" />
 | 
					            variant="outline"
 | 
				
			||||||
          </CancelDueDate>
 | 
					            color="danger"
 | 
				
			||||||
 | 
					            onClick={() => {
 | 
				
			||||||
 | 
					              onRemoveDueDate(task);
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            Remove
 | 
				
			||||||
 | 
					          </RemoveDueDate>
 | 
				
			||||||
        </ActionWrapper>
 | 
					        </ActionWrapper>
 | 
				
			||||||
      </Form>
 | 
					      </Form>
 | 
				
			||||||
    </Wrapper>
 | 
					    </Wrapper>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,11 +7,41 @@ export const Container = styled.div`
 | 
				
			|||||||
  overflow-x: auto;
 | 
					  overflow-x: auto;
 | 
				
			||||||
  overflow-y: hidden;
 | 
					  overflow-y: hidden;
 | 
				
			||||||
  padding-bottom: 8px;
 | 
					  padding-bottom: 8px;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ::-webkit-scrollbar {
 | 
				
			||||||
 | 
					    height: 10px;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  ::-webkit-scrollbar-thumb {
 | 
				
			||||||
 | 
					    background: #7367f0;
 | 
				
			||||||
 | 
					    border-radius: 6px;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ::-webkit-scrollbar-track {
 | 
				
			||||||
 | 
					    background: #10163a;
 | 
				
			||||||
 | 
					    border-radius: 6px;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const BoardContainer = styled.div`
 | 
				
			||||||
 | 
					  position: relative;
 | 
				
			||||||
 | 
					  overflow-y: auto;
 | 
				
			||||||
 | 
					  outline: none;
 | 
				
			||||||
 | 
					  flex-grow: 1;
 | 
				
			||||||
`;
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const BoardWrapper = styled.div`
 | 
					export const BoardWrapper = styled.div`
 | 
				
			||||||
  display: flex;
 | 
					  display: flex;
 | 
				
			||||||
  margin-top: 12px;
 | 
					
 | 
				
			||||||
  margin-left: 8px;
 | 
					  user-select: none;
 | 
				
			||||||
 | 
					  white-space: nowrap;
 | 
				
			||||||
 | 
					  margin-bottom: 8px;
 | 
				
			||||||
 | 
					  overflow-x: auto;
 | 
				
			||||||
 | 
					  overflow-y: hidden;
 | 
				
			||||||
 | 
					  padding-bottom: 8px;
 | 
				
			||||||
 | 
					  position: absolute;
 | 
				
			||||||
 | 
					  top: 0;
 | 
				
			||||||
 | 
					  right: 0;
 | 
				
			||||||
 | 
					  bottom: 0;
 | 
				
			||||||
 | 
					  left: 0;
 | 
				
			||||||
`;
 | 
					`;
 | 
				
			||||||
export default Container;
 | 
					export default Container;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,10 +10,10 @@ import {
 | 
				
			|||||||
  getNewDraggablePosition,
 | 
					  getNewDraggablePosition,
 | 
				
			||||||
  getAfterDropDraggableList,
 | 
					  getAfterDropDraggableList,
 | 
				
			||||||
} from 'shared/utils/draggables';
 | 
					} from 'shared/utils/draggables';
 | 
				
			||||||
 | 
					 | 
				
			||||||
import { Container, BoardWrapper } from './Styles';
 | 
					 | 
				
			||||||
import moment from 'moment';
 | 
					import moment from 'moment';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { Container, BoardContainer, BoardWrapper } from './Styles';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface SimpleProps {
 | 
					interface SimpleProps {
 | 
				
			||||||
  taskGroups: Array<TaskGroup>;
 | 
					  taskGroups: Array<TaskGroup>;
 | 
				
			||||||
  onTaskDrop: (task: Task, previousTaskGroupID: string) => void;
 | 
					  onTaskDrop: (task: Task, previousTaskGroupID: string) => void;
 | 
				
			||||||
@@ -120,104 +120,107 @@ const SimpleLists: React.FC<SimpleProps> = ({
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  const [currentComposer, setCurrentComposer] = useState('');
 | 
					  const [currentComposer, setCurrentComposer] = useState('');
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <BoardWrapper>
 | 
					    <BoardContainer>
 | 
				
			||||||
      <DragDropContext onDragEnd={onDragEnd}>
 | 
					      <BoardWrapper>
 | 
				
			||||||
        <Droppable direction="horizontal" type="column" droppableId="root">
 | 
					        <DragDropContext onDragEnd={onDragEnd}>
 | 
				
			||||||
          {provided => (
 | 
					          <Droppable direction="horizontal" type="column" droppableId="root">
 | 
				
			||||||
            <Container {...provided.droppableProps} ref={provided.innerRef}>
 | 
					            {provided => (
 | 
				
			||||||
              {taskGroups
 | 
					              <Container {...provided.droppableProps} ref={provided.innerRef}>
 | 
				
			||||||
                .slice()
 | 
					                {taskGroups
 | 
				
			||||||
                .sort((a: any, b: any) => a.position - b.position)
 | 
					                  .slice()
 | 
				
			||||||
                .map((taskGroup: TaskGroup, index: number) => {
 | 
					                  .sort((a: any, b: any) => a.position - b.position)
 | 
				
			||||||
                  return (
 | 
					                  .map((taskGroup: TaskGroup, index: number) => {
 | 
				
			||||||
                    <Draggable draggableId={taskGroup.id} key={taskGroup.id} index={index}>
 | 
					                    return (
 | 
				
			||||||
                      {columnDragProvided => (
 | 
					                      <Draggable draggableId={taskGroup.id} key={taskGroup.id} index={index}>
 | 
				
			||||||
                        <Droppable type="tasks" droppableId={taskGroup.id}>
 | 
					                        {columnDragProvided => (
 | 
				
			||||||
                          {(columnDropProvided, snapshot) => (
 | 
					                          <Droppable type="tasks" droppableId={taskGroup.id}>
 | 
				
			||||||
                            <List
 | 
					                            {(columnDropProvided, snapshot) => (
 | 
				
			||||||
                              name={taskGroup.name}
 | 
					                              <List
 | 
				
			||||||
                              onOpenComposer={id => setCurrentComposer(id)}
 | 
					                                name={taskGroup.name}
 | 
				
			||||||
                              isComposerOpen={currentComposer === taskGroup.id}
 | 
					                                onOpenComposer={id => setCurrentComposer(id)}
 | 
				
			||||||
                              onSaveName={name => onChangeTaskGroupName(taskGroup.id, name)}
 | 
					                                isComposerOpen={currentComposer === taskGroup.id}
 | 
				
			||||||
                              ref={columnDragProvided.innerRef}
 | 
					                                onSaveName={name => onChangeTaskGroupName(taskGroup.id, name)}
 | 
				
			||||||
                              wrapperProps={columnDragProvided.draggableProps}
 | 
					                                ref={columnDragProvided.innerRef}
 | 
				
			||||||
                              headerProps={columnDragProvided.dragHandleProps}
 | 
					                                wrapperProps={columnDragProvided.draggableProps}
 | 
				
			||||||
                              onExtraMenuOpen={onExtraMenuOpen}
 | 
					                                headerProps={columnDragProvided.dragHandleProps}
 | 
				
			||||||
                              id={taskGroup.id}
 | 
					                                onExtraMenuOpen={onExtraMenuOpen}
 | 
				
			||||||
                              key={taskGroup.id}
 | 
					                                id={taskGroup.id}
 | 
				
			||||||
                              index={index}
 | 
					                                key={taskGroup.id}
 | 
				
			||||||
                            >
 | 
					                                index={index}
 | 
				
			||||||
                              <ListCards ref={columnDropProvided.innerRef} {...columnDropProvided.droppableProps}>
 | 
					                              >
 | 
				
			||||||
                                {taskGroup.tasks
 | 
					                                <ListCards ref={columnDropProvided.innerRef} {...columnDropProvided.droppableProps}>
 | 
				
			||||||
                                  .slice()
 | 
					                                  {taskGroup.tasks
 | 
				
			||||||
                                  .sort((a: any, b: any) => a.position - b.position)
 | 
					                                    .slice()
 | 
				
			||||||
                                  .map((task: Task, taskIndex: any) => {
 | 
					                                    .sort((a: any, b: any) => a.position - b.position)
 | 
				
			||||||
                                    return (
 | 
					                                    .map((task: Task, taskIndex: any) => {
 | 
				
			||||||
                                      <Draggable key={task.id} draggableId={task.id} index={taskIndex}>
 | 
					                                      return (
 | 
				
			||||||
                                        {taskProvided => {
 | 
					                                        <Draggable key={task.id} draggableId={task.id} index={taskIndex}>
 | 
				
			||||||
                                          return (
 | 
					                                          {taskProvided => {
 | 
				
			||||||
                                            <Card
 | 
					                                            return (
 | 
				
			||||||
                                              wrapperProps={{
 | 
					                                              <Card
 | 
				
			||||||
                                                ...taskProvided.draggableProps,
 | 
					                                                wrapperProps={{
 | 
				
			||||||
                                                ...taskProvided.dragHandleProps,
 | 
					                                                  ...taskProvided.draggableProps,
 | 
				
			||||||
                                              }}
 | 
					                                                  ...taskProvided.dragHandleProps,
 | 
				
			||||||
                                              ref={taskProvided.innerRef}
 | 
					                                                }}
 | 
				
			||||||
                                              taskID={task.id}
 | 
					                                                ref={taskProvided.innerRef}
 | 
				
			||||||
                                              taskGroupID={taskGroup.id}
 | 
					                                                taskID={task.id}
 | 
				
			||||||
                                              description=""
 | 
					                                                complete={task.complete ?? false}
 | 
				
			||||||
                                              labels={task.labels.map(label => label.projectLabel)}
 | 
					                                                taskGroupID={taskGroup.id}
 | 
				
			||||||
                                              dueDate={
 | 
					                                                description=""
 | 
				
			||||||
                                                task.dueDate
 | 
					                                                labels={task.labels.map(label => label.projectLabel)}
 | 
				
			||||||
                                                  ? {
 | 
					                                                dueDate={
 | 
				
			||||||
                                                      isPastDue: false,
 | 
					                                                  task.dueDate
 | 
				
			||||||
                                                      formattedDate: moment(task.dueDate).format('MMM D, YYYY'),
 | 
					                                                    ? {
 | 
				
			||||||
                                                    }
 | 
					                                                        isPastDue: false,
 | 
				
			||||||
                                                  : undefined
 | 
					                                                        formattedDate: moment(task.dueDate).format('MMM D, YYYY'),
 | 
				
			||||||
                                              }
 | 
					                                                      }
 | 
				
			||||||
                                              title={task.name}
 | 
					                                                    : undefined
 | 
				
			||||||
                                              members={task.assigned}
 | 
					                                                }
 | 
				
			||||||
                                              onClick={() => {
 | 
					                                                title={task.name}
 | 
				
			||||||
                                                onTaskClick(task);
 | 
					                                                members={task.assigned}
 | 
				
			||||||
                                              }}
 | 
					                                                onClick={() => {
 | 
				
			||||||
                                              onCardMemberClick={onCardMemberClick}
 | 
					                                                  onTaskClick(task);
 | 
				
			||||||
                                              onContextMenu={onQuickEditorOpen}
 | 
					                                                }}
 | 
				
			||||||
                                            />
 | 
					                                                onCardMemberClick={onCardMemberClick}
 | 
				
			||||||
                                          );
 | 
					                                                onContextMenu={onQuickEditorOpen}
 | 
				
			||||||
                                        }}
 | 
					                                              />
 | 
				
			||||||
                                      </Draggable>
 | 
					                                            );
 | 
				
			||||||
                                    );
 | 
					                                          }}
 | 
				
			||||||
                                  })}
 | 
					                                        </Draggable>
 | 
				
			||||||
                                {columnDropProvided.placeholder}
 | 
					                                      );
 | 
				
			||||||
                                {currentComposer === taskGroup.id && (
 | 
					                                    })}
 | 
				
			||||||
                                  <CardComposer
 | 
					                                  {columnDropProvided.placeholder}
 | 
				
			||||||
                                    onClose={() => {
 | 
					                                  {currentComposer === taskGroup.id && (
 | 
				
			||||||
                                      setCurrentComposer('');
 | 
					                                    <CardComposer
 | 
				
			||||||
                                    }}
 | 
					                                      onClose={() => {
 | 
				
			||||||
                                    onCreateCard={name => {
 | 
					                                        setCurrentComposer('');
 | 
				
			||||||
                                      onCreateTask(taskGroup.id, name);
 | 
					                                      }}
 | 
				
			||||||
                                    }}
 | 
					                                      onCreateCard={name => {
 | 
				
			||||||
                                    isOpen
 | 
					                                        onCreateTask(taskGroup.id, name);
 | 
				
			||||||
                                  />
 | 
					                                      }}
 | 
				
			||||||
                                )}
 | 
					                                      isOpen
 | 
				
			||||||
                              </ListCards>
 | 
					                                    />
 | 
				
			||||||
                            </List>
 | 
					                                  )}
 | 
				
			||||||
                          )}
 | 
					                                </ListCards>
 | 
				
			||||||
                        </Droppable>
 | 
					                              </List>
 | 
				
			||||||
                      )}
 | 
					                            )}
 | 
				
			||||||
                    </Draggable>
 | 
					                          </Droppable>
 | 
				
			||||||
                  );
 | 
					                        )}
 | 
				
			||||||
                })}
 | 
					                      </Draggable>
 | 
				
			||||||
              {provided.placeholder}
 | 
					                    );
 | 
				
			||||||
            </Container>
 | 
					                  })}
 | 
				
			||||||
          )}
 | 
					                <AddList
 | 
				
			||||||
        </Droppable>
 | 
					                  onSave={listName => {
 | 
				
			||||||
      </DragDropContext>
 | 
					                    onCreateTaskGroup(listName);
 | 
				
			||||||
      <AddList
 | 
					                  }}
 | 
				
			||||||
        onSave={listName => {
 | 
					                />
 | 
				
			||||||
          onCreateTaskGroup(listName);
 | 
					                {provided.placeholder}
 | 
				
			||||||
        }}
 | 
					              </Container>
 | 
				
			||||||
      />
 | 
					            )}
 | 
				
			||||||
    </BoardWrapper>
 | 
					          </Droppable>
 | 
				
			||||||
 | 
					        </DragDropContext>
 | 
				
			||||||
 | 
					      </BoardWrapper>
 | 
				
			||||||
 | 
					    </BoardContainer>
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -59,7 +59,7 @@ const MemberManager: React.FC<MemberManagerProps> = ({
 | 
				
			|||||||
                  <MemberName>{member.fullName}</MemberName>
 | 
					                  <MemberName>{member.fullName}</MemberName>
 | 
				
			||||||
                  {activeMembers.findIndex(m => m.id === member.id) !== -1 && (
 | 
					                  {activeMembers.findIndex(m => m.id === member.id) !== -1 && (
 | 
				
			||||||
                    <ActiveIconWrapper>
 | 
					                    <ActiveIconWrapper>
 | 
				
			||||||
                      <Checkmark size={16} color="#42526e" />
 | 
					                      <Checkmark width={16} height={16} />
 | 
				
			||||||
                    </ActiveIconWrapper>
 | 
					                    </ActiveIconWrapper>
 | 
				
			||||||
                  )}
 | 
					                  )}
 | 
				
			||||||
                </BoardMemberListItemContent>
 | 
					                </BoardMemberListItemContent>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -232,7 +232,7 @@ const NewProject: React.FC<NewProjectProps> = ({ teams, onClose, onCreateProject
 | 
				
			|||||||
              onClose();
 | 
					              onClose();
 | 
				
			||||||
            }}
 | 
					            }}
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
            <Cross color="#c2c6dc" />
 | 
					            <Cross width={16} height={16} />
 | 
				
			||||||
          </HeaderRight>
 | 
					          </HeaderRight>
 | 
				
			||||||
        </Header>
 | 
					        </Header>
 | 
				
			||||||
        <Container>
 | 
					        <Container>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -44,7 +44,7 @@ const LabelManager = ({ labelColors, label, onLabelEdit, onLabelDelete }: Props)
 | 
				
			|||||||
              setCurrentColor(labelColor);
 | 
					              setCurrentColor(labelColor);
 | 
				
			||||||
            }}
 | 
					            }}
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
            {currentColor && labelColor.id === currentColor.id && <Checkmark color="#fff" size={12} />}
 | 
					            {currentColor && labelColor.id === currentColor.id && <Checkmark width={12} height={12} />}
 | 
				
			||||||
          </LabelBox>
 | 
					          </LabelBox>
 | 
				
			||||||
        ))}
 | 
					        ))}
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -72,7 +72,7 @@ const LabelManager: React.FC<Props> = ({ labels, taskLabels, onLabelToggle, onLa
 | 
				
			|||||||
                    {label.name}
 | 
					                    {label.name}
 | 
				
			||||||
                    {taskLabels && taskLabels.find(t => t.projectLabel.id === label.id) && (
 | 
					                    {taskLabels && taskLabels.find(t => t.projectLabel.id === label.id) && (
 | 
				
			||||||
                      <ActiveIcon>
 | 
					                      <ActiveIcon>
 | 
				
			||||||
                        <Checkmark color="#fff" />
 | 
					                        <Checkmark width={16} height={16} />
 | 
				
			||||||
                      </ActiveIcon>
 | 
					                      </ActiveIcon>
 | 
				
			||||||
                    )}
 | 
					                    )}
 | 
				
			||||||
                  </CardLabel>
 | 
					                  </CardLabel>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -265,6 +265,7 @@ export const DueDateManagerPopup = () => {
 | 
				
			|||||||
      {popupData.isOpen && (
 | 
					      {popupData.isOpen && (
 | 
				
			||||||
        <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
 | 
				
			||||||
 | 
					            onRemoveDueDate={action('remove due date')}
 | 
				
			||||||
            task={{
 | 
					            task={{
 | 
				
			||||||
              id: '1',
 | 
					              id: '1',
 | 
				
			||||||
              taskGroup: { name: 'General', id: '1', position: 1 },
 | 
					              taskGroup: { name: 'General', id: '1', position: 1 },
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
import React, { useRef, createContext, RefObject, useState, useContext } from 'react';
 | 
					import React, { useRef, createContext, RefObject, useState, useContext, useEffect } from 'react';
 | 
				
			||||||
import { Cross, AngleLeft } from 'shared/icons';
 | 
					import { Cross, AngleLeft } from 'shared/icons';
 | 
				
			||||||
import useOnOutsideClick from 'shared/hooks/onOutsideClick';
 | 
					import useOnOutsideClick from 'shared/hooks/onOutsideClick';
 | 
				
			||||||
import { createPortal } from 'react-dom';
 | 
					import { createPortal } from 'react-dom';
 | 
				
			||||||
@@ -36,10 +36,19 @@ type PopupContainerProps = {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const PopupContainer: React.FC<PopupContainerProps> = ({ width, top, left, onClose, children, invert }) => {
 | 
					const PopupContainer: React.FC<PopupContainerProps> = ({ width, top, left, onClose, children, invert }) => {
 | 
				
			||||||
  const $containerRef = useRef();
 | 
					  const $containerRef = useRef<HTMLDivElement>(null);
 | 
				
			||||||
 | 
					  const [currentTop, setCurrentTop] = useState(top);
 | 
				
			||||||
  useOnOutsideClick($containerRef, true, onClose, null);
 | 
					  useOnOutsideClick($containerRef, true, onClose, null);
 | 
				
			||||||
 | 
					  useEffect(() => {
 | 
				
			||||||
 | 
					    if ($containerRef && $containerRef.current) {
 | 
				
			||||||
 | 
					      const bounding = $containerRef.current.getBoundingClientRect();
 | 
				
			||||||
 | 
					      if (bounding.bottom > (window.innerHeight || document.documentElement.clientHeight)) {
 | 
				
			||||||
 | 
					        setCurrentTop(44);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }, []);
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <Container width={width ?? 316} left={left} top={top} ref={$containerRef} invert={invert}>
 | 
					    <Container width={width ?? 316} left={left} top={currentTop} ref={$containerRef} invert={invert}>
 | 
				
			||||||
      {children}
 | 
					      {children}
 | 
				
			||||||
    </Container>
 | 
					    </Container>
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
@@ -91,11 +100,12 @@ export const PopupProvider: React.FC = ({ children }) => {
 | 
				
			|||||||
  const show = (target: RefObject<HTMLElement>, content: JSX.Element, width?: number | string) => {
 | 
					  const show = (target: RefObject<HTMLElement>, content: JSX.Element, width?: number | string) => {
 | 
				
			||||||
    if (target && target.current) {
 | 
					    if (target && target.current) {
 | 
				
			||||||
      const bounds = target.current.getBoundingClientRect();
 | 
					      const bounds = target.current.getBoundingClientRect();
 | 
				
			||||||
 | 
					      const top = bounds.top + bounds.height;
 | 
				
			||||||
      if (bounds.left + 304 + 30 > window.innerWidth) {
 | 
					      if (bounds.left + 304 + 30 > window.innerWidth) {
 | 
				
			||||||
        setState({
 | 
					        setState({
 | 
				
			||||||
          isOpen: true,
 | 
					          isOpen: true,
 | 
				
			||||||
          left: bounds.left + bounds.width,
 | 
					          left: bounds.left + bounds.width,
 | 
				
			||||||
          top: bounds.top + bounds.height,
 | 
					          top,
 | 
				
			||||||
          invert: true,
 | 
					          invert: true,
 | 
				
			||||||
          currentTab: 0,
 | 
					          currentTab: 0,
 | 
				
			||||||
          previousTab: 0,
 | 
					          previousTab: 0,
 | 
				
			||||||
@@ -106,7 +116,7 @@ export const PopupProvider: React.FC = ({ children }) => {
 | 
				
			|||||||
        setState({
 | 
					        setState({
 | 
				
			||||||
          isOpen: true,
 | 
					          isOpen: true,
 | 
				
			||||||
          left: bounds.left,
 | 
					          left: bounds.left,
 | 
				
			||||||
          top: bounds.top + bounds.height,
 | 
					          top,
 | 
				
			||||||
          invert: false,
 | 
					          invert: false,
 | 
				
			||||||
          currentTab: 0,
 | 
					          currentTab: 0,
 | 
				
			||||||
          previousTab: 0,
 | 
					          previousTab: 0,
 | 
				
			||||||
@@ -176,7 +186,7 @@ type Props = {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const PopupMenu: React.FC<Props> = ({ width, title, top, left, onClose, noHeader, children, onPrevious }) => {
 | 
					const PopupMenu: React.FC<Props> = ({ width, title, top, left, onClose, noHeader, children, onPrevious }) => {
 | 
				
			||||||
  const $containerRef = useRef();
 | 
					  const $containerRef = useRef<HTMLDivElement>(null);
 | 
				
			||||||
  useOnOutsideClick($containerRef, true, onClose, null);
 | 
					  useOnOutsideClick($containerRef, true, onClose, null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
@@ -189,13 +199,13 @@ const PopupMenu: React.FC<Props> = ({ width, title, top, left, onClose, noHeader
 | 
				
			|||||||
        )}
 | 
					        )}
 | 
				
			||||||
        {noHeader ? (
 | 
					        {noHeader ? (
 | 
				
			||||||
          <CloseButton onClick={() => onClose()}>
 | 
					          <CloseButton onClick={() => onClose()}>
 | 
				
			||||||
            <Cross color="#c2c6dc" />
 | 
					            <Cross width={16} height={16} />
 | 
				
			||||||
          </CloseButton>
 | 
					          </CloseButton>
 | 
				
			||||||
        ) : (
 | 
					        ) : (
 | 
				
			||||||
          <Header>
 | 
					          <Header>
 | 
				
			||||||
            <HeaderTitle>{title}</HeaderTitle>
 | 
					            <HeaderTitle>{title}</HeaderTitle>
 | 
				
			||||||
            <CloseButton onClick={() => onClose()}>
 | 
					            <CloseButton onClick={() => onClose()}>
 | 
				
			||||||
              <Cross color="#c2c6dc" />
 | 
					              <Cross width={16} height={16} />
 | 
				
			||||||
            </CloseButton>
 | 
					            </CloseButton>
 | 
				
			||||||
          </Header>
 | 
					          </Header>
 | 
				
			||||||
        )}
 | 
					        )}
 | 
				
			||||||
@@ -230,7 +240,7 @@ export const Popup: React.FC<PopupProps> = ({ title, onClose, tab, children }) =
 | 
				
			|||||||
        )}
 | 
					        )}
 | 
				
			||||||
        {onClose && (
 | 
					        {onClose && (
 | 
				
			||||||
          <CloseButton onClick={() => onClose()}>
 | 
					          <CloseButton onClick={() => onClose()}>
 | 
				
			||||||
            <Cross color="#c2c6dc" />
 | 
					            <Cross width={16} height={16} />
 | 
				
			||||||
          </CloseButton>
 | 
					          </CloseButton>
 | 
				
			||||||
        )}
 | 
					        )}
 | 
				
			||||||
        <Content>{children}</Content>
 | 
					        <Content>{children}</Content>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -57,7 +57,9 @@ export const Default = () => {
 | 
				
			|||||||
          onCloseEditor={() => setEditorOpen(false)}
 | 
					          onCloseEditor={() => setEditorOpen(false)}
 | 
				
			||||||
          onEditCard={action('edit card')}
 | 
					          onEditCard={action('edit card')}
 | 
				
			||||||
          onOpenLabelsPopup={action('open popup')}
 | 
					          onOpenLabelsPopup={action('open popup')}
 | 
				
			||||||
 | 
					          onOpenDueDatePopup={action('open popup')}
 | 
				
			||||||
          onOpenMembersPopup={action('open popup')}
 | 
					          onOpenMembersPopup={action('open popup')}
 | 
				
			||||||
 | 
					          onToggleComplete={action('complete')}
 | 
				
			||||||
          onArchiveCard={action('archive card')}
 | 
					          onArchiveCard={action('archive card')}
 | 
				
			||||||
          top={top}
 | 
					          top={top}
 | 
				
			||||||
          left={left}
 | 
					          left={left}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,9 +14,9 @@ export const Wrapper = styled.div<{ open: boolean }>`
 | 
				
			|||||||
  visibility: ${props => (props.open ? 'show' : 'hidden')};
 | 
					  visibility: ${props => (props.open ? 'show' : 'hidden')};
 | 
				
			||||||
`;
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const Container = styled.div<{ top: number; left: number }>`
 | 
					export const Container = styled.div<{ width: number; top: number; left: number }>`
 | 
				
			||||||
  position: absolute;
 | 
					  position: absolute;
 | 
				
			||||||
  width: 256px;
 | 
					  width: ${props => props.width}px;
 | 
				
			||||||
  top: ${props => props.top}px;
 | 
					  top: ${props => props.top}px;
 | 
				
			||||||
  left: ${props => props.left}px;
 | 
					  left: ${props => props.left}px;
 | 
				
			||||||
`;
 | 
					`;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,12 +14,15 @@ type Props = {
 | 
				
			|||||||
  task: Task;
 | 
					  task: Task;
 | 
				
			||||||
  onCloseEditor: () => void;
 | 
					  onCloseEditor: () => void;
 | 
				
			||||||
  onEditCard: (taskGroupID: string, taskID: string, cardName: string) => void;
 | 
					  onEditCard: (taskGroupID: string, taskID: string, cardName: string) => void;
 | 
				
			||||||
 | 
					  onToggleComplete: (task: Task) => void;
 | 
				
			||||||
  onOpenLabelsPopup: ($targetRef: React.RefObject<HTMLElement>, task: Task) => void;
 | 
					  onOpenLabelsPopup: ($targetRef: React.RefObject<HTMLElement>, task: Task) => void;
 | 
				
			||||||
  onOpenMembersPopup: ($targetRef: React.RefObject<HTMLElement>, task: Task) => void;
 | 
					  onOpenMembersPopup: ($targetRef: React.RefObject<HTMLElement>, task: Task) => void;
 | 
				
			||||||
 | 
					  onOpenDueDatePopup: ($targetRef: React.RefObject<HTMLElement>, task: Task) => void;
 | 
				
			||||||
  onArchiveCard: (taskGroupID: string, taskID: string) => void;
 | 
					  onArchiveCard: (taskGroupID: string, taskID: string) => void;
 | 
				
			||||||
  onCardMemberClick?: OnCardMemberClick;
 | 
					  onCardMemberClick?: OnCardMemberClick;
 | 
				
			||||||
  top: number;
 | 
					  top: number;
 | 
				
			||||||
  left: number;
 | 
					  left: number;
 | 
				
			||||||
 | 
					  width?: number;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const QuickCardEditor = ({
 | 
					const QuickCardEditor = ({
 | 
				
			||||||
@@ -27,14 +30,18 @@ const QuickCardEditor = ({
 | 
				
			|||||||
  onCloseEditor,
 | 
					  onCloseEditor,
 | 
				
			||||||
  onOpenLabelsPopup,
 | 
					  onOpenLabelsPopup,
 | 
				
			||||||
  onOpenMembersPopup,
 | 
					  onOpenMembersPopup,
 | 
				
			||||||
 | 
					  onOpenDueDatePopup,
 | 
				
			||||||
 | 
					  onToggleComplete,
 | 
				
			||||||
  onCardMemberClick,
 | 
					  onCardMemberClick,
 | 
				
			||||||
  onArchiveCard,
 | 
					  onArchiveCard,
 | 
				
			||||||
  onEditCard,
 | 
					  onEditCard,
 | 
				
			||||||
 | 
					  width = 272,
 | 
				
			||||||
  top,
 | 
					  top,
 | 
				
			||||||
  left,
 | 
					  left,
 | 
				
			||||||
}: Props) => {
 | 
					}: Props) => {
 | 
				
			||||||
  const [currentCardTitle, setCardTitle] = useState(task.name);
 | 
					  const [currentCardTitle, setCardTitle] = useState(task.name);
 | 
				
			||||||
  const $labelsRef: any = useRef();
 | 
					  const $labelsRef: any = useRef();
 | 
				
			||||||
 | 
					  const $dueDate: any = useRef();
 | 
				
			||||||
  const $membersRef: any = useRef();
 | 
					  const $membersRef: any = useRef();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const handleCloseEditor = (e: any) => {
 | 
					  const handleCloseEditor = (e: any) => {
 | 
				
			||||||
@@ -45,9 +52,9 @@ const QuickCardEditor = ({
 | 
				
			|||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <Wrapper onClick={handleCloseEditor} open>
 | 
					    <Wrapper onClick={handleCloseEditor} open>
 | 
				
			||||||
      <CloseButton onClick={handleCloseEditor}>
 | 
					      <CloseButton onClick={handleCloseEditor}>
 | 
				
			||||||
        <Cross size={16} color="#000" />
 | 
					        <Cross width={16} height={16} />
 | 
				
			||||||
      </CloseButton>
 | 
					      </CloseButton>
 | 
				
			||||||
      <Container left={left} top={top}>
 | 
					      <Container width={width} left={left} top={top}>
 | 
				
			||||||
        <Card
 | 
					        <Card
 | 
				
			||||||
          editable
 | 
					          editable
 | 
				
			||||||
          onCardMemberClick={onCardMemberClick}
 | 
					          onCardMemberClick={onCardMemberClick}
 | 
				
			||||||
@@ -56,6 +63,7 @@ const QuickCardEditor = ({
 | 
				
			|||||||
            onEditCard(taskGroupID, taskID, name);
 | 
					            onEditCard(taskGroupID, taskID, name);
 | 
				
			||||||
            onCloseEditor();
 | 
					            onCloseEditor();
 | 
				
			||||||
          }}
 | 
					          }}
 | 
				
			||||||
 | 
					          complete={task.complete ?? false}
 | 
				
			||||||
          members={task.assigned}
 | 
					          members={task.assigned}
 | 
				
			||||||
          taskID={task.id}
 | 
					          taskID={task.id}
 | 
				
			||||||
          taskGroupID={task.taskGroup.id}
 | 
					          taskGroupID={task.taskGroup.id}
 | 
				
			||||||
@@ -63,6 +71,14 @@ const QuickCardEditor = ({
 | 
				
			|||||||
        />
 | 
					        />
 | 
				
			||||||
        <SaveButton onClick={() => onEditCard(task.taskGroup.id, task.id, currentCardTitle)}>Save</SaveButton>
 | 
					        <SaveButton onClick={() => onEditCard(task.taskGroup.id, task.id, currentCardTitle)}>Save</SaveButton>
 | 
				
			||||||
        <EditorButtons>
 | 
					        <EditorButtons>
 | 
				
			||||||
 | 
					          <EditorButton
 | 
				
			||||||
 | 
					            onClick={e => {
 | 
				
			||||||
 | 
					              e.stopPropagation();
 | 
				
			||||||
 | 
					              onToggleComplete(task);
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            {task.complete ? 'Mark Incomplete' : 'Mark Complete'}
 | 
				
			||||||
 | 
					          </EditorButton>
 | 
				
			||||||
          <EditorButton
 | 
					          <EditorButton
 | 
				
			||||||
            ref={$membersRef}
 | 
					            ref={$membersRef}
 | 
				
			||||||
            onClick={e => {
 | 
					            onClick={e => {
 | 
				
			||||||
@@ -72,6 +88,15 @@ const QuickCardEditor = ({
 | 
				
			|||||||
          >
 | 
					          >
 | 
				
			||||||
            Edit Assigned
 | 
					            Edit Assigned
 | 
				
			||||||
          </EditorButton>
 | 
					          </EditorButton>
 | 
				
			||||||
 | 
					          <EditorButton
 | 
				
			||||||
 | 
					            ref={$dueDate}
 | 
				
			||||||
 | 
					            onClick={e => {
 | 
				
			||||||
 | 
					              e.stopPropagation();
 | 
				
			||||||
 | 
					              onOpenDueDatePopup($labelsRef, task);
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            Edit Due Date
 | 
				
			||||||
 | 
					          </EditorButton>
 | 
				
			||||||
          <EditorButton
 | 
					          <EditorButton
 | 
				
			||||||
            ref={$labelsRef}
 | 
					            ref={$labelsRef}
 | 
				
			||||||
            onClick={e => {
 | 
					            onClick={e => {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -148,6 +148,20 @@ export const TaskDetailsMarkdown = styled.div`
 | 
				
			|||||||
  cursor: pointer;
 | 
					  cursor: pointer;
 | 
				
			||||||
  color: #c2c6dc;
 | 
					  color: #c2c6dc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  h1 {
 | 
				
			||||||
 | 
					    font-size: 24px;
 | 
				
			||||||
 | 
					    font-weight: 600;
 | 
				
			||||||
 | 
					    line-height: 28px;
 | 
				
			||||||
 | 
					    margin: 0 0 12px;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  h2 {
 | 
				
			||||||
 | 
					    font-weight: 600;
 | 
				
			||||||
 | 
					    font-size: 20px;
 | 
				
			||||||
 | 
					    line-height: 24px;
 | 
				
			||||||
 | 
					    margin: 16px 0 8px;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  p {
 | 
					  p {
 | 
				
			||||||
    margin: 0 0 8px;
 | 
					    margin: 0 0 8px;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -155,6 +169,15 @@ export const TaskDetailsMarkdown = styled.div`
 | 
				
			|||||||
  strong {
 | 
					  strong {
 | 
				
			||||||
    font-weight: 700;
 | 
					    font-weight: 700;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ul {
 | 
				
			||||||
 | 
					    margin: 8px 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ul > li {
 | 
				
			||||||
 | 
					    margin: 8px 8px 8px 24px;
 | 
				
			||||||
 | 
					    list-style: disc;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
`;
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const TaskDetailsControls = styled.div`
 | 
					export const TaskDetailsControls = styled.div`
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,6 +28,8 @@ export const Default = () => {
 | 
				
			|||||||
        renderContent={() => {
 | 
					        renderContent={() => {
 | 
				
			||||||
          return (
 | 
					          return (
 | 
				
			||||||
            <TaskDetails
 | 
					            <TaskDetails
 | 
				
			||||||
 | 
					              onDeleteItem={action('delete item')}
 | 
				
			||||||
 | 
					              onChangeItemName={action('change item name')}
 | 
				
			||||||
              task={{
 | 
					              task={{
 | 
				
			||||||
                id: '1',
 | 
					                id: '1',
 | 
				
			||||||
                taskGroup: { name: 'General', id: '1' },
 | 
					                taskGroup: { name: 'General', id: '1' },
 | 
				
			||||||
@@ -65,6 +67,8 @@ export const Default = () => {
 | 
				
			|||||||
              onCloseModal={action('close modal')}
 | 
					              onCloseModal={action('close modal')}
 | 
				
			||||||
              onMemberProfile={action('profile')}
 | 
					              onMemberProfile={action('profile')}
 | 
				
			||||||
              onOpenAddMemberPopup={action('open add member popup')}
 | 
					              onOpenAddMemberPopup={action('open add member popup')}
 | 
				
			||||||
 | 
					              onAddItem={action('add item')}
 | 
				
			||||||
 | 
					              onToggleChecklistItem={action('toggle checklist item')}
 | 
				
			||||||
              onOpenAddLabelPopup={action('open add label popup')}
 | 
					              onOpenAddLabelPopup={action('open add label popup')}
 | 
				
			||||||
              onOpenDueDatePopop={action('open due date popup')}
 | 
					              onOpenDueDatePopop={action('open due date popup')}
 | 
				
			||||||
            />
 | 
					            />
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,6 +3,7 @@ import { Bin, Cross, Plus } from 'shared/icons';
 | 
				
			|||||||
import useOnOutsideClick from 'shared/hooks/onOutsideClick';
 | 
					import useOnOutsideClick from 'shared/hooks/onOutsideClick';
 | 
				
			||||||
import ReactMarkdown from 'react-markdown';
 | 
					import ReactMarkdown from 'react-markdown';
 | 
				
			||||||
import TaskAssignee from 'shared/components/TaskAssignee';
 | 
					import TaskAssignee from 'shared/components/TaskAssignee';
 | 
				
			||||||
 | 
					import moment from 'moment';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  NoDueDateLabel,
 | 
					  NoDueDateLabel,
 | 
				
			||||||
@@ -37,15 +38,33 @@ import {
 | 
				
			|||||||
  TaskDetailAssignees,
 | 
					  TaskDetailAssignees,
 | 
				
			||||||
  TaskDetailsAddMemberIcon,
 | 
					  TaskDetailsAddMemberIcon,
 | 
				
			||||||
} from './Styles';
 | 
					} from './Styles';
 | 
				
			||||||
 | 
					import Checklist from '../Checklist';
 | 
				
			||||||
import convertDivElementRefToBounds from 'shared/utils/boundingRect';
 | 
					 | 
				
			||||||
import moment from 'moment';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
type TaskContentProps = {
 | 
					type TaskContentProps = {
 | 
				
			||||||
  onEditContent: () => void;
 | 
					  onEditContent: () => void;
 | 
				
			||||||
  description: string;
 | 
					  description: string;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type TaskLabelProps = {
 | 
				
			||||||
 | 
					  label: TaskLabel;
 | 
				
			||||||
 | 
					  onClick: ($target: React.RefObject<HTMLElement>) => void;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const TaskLabelItem: React.FC<TaskLabelProps> = ({ label, onClick }) => {
 | 
				
			||||||
 | 
					  const $label = useRef<HTMLDivElement>(null);
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <TaskDetailLabel
 | 
				
			||||||
 | 
					      onClick={() => {
 | 
				
			||||||
 | 
					        onClick($label);
 | 
				
			||||||
 | 
					      }}
 | 
				
			||||||
 | 
					      ref={$label}
 | 
				
			||||||
 | 
					      color={label.projectLabel.labelColor.colorHex}
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					      {label.projectLabel.name}
 | 
				
			||||||
 | 
					    </TaskDetailLabel>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const TaskContent: React.FC<TaskContentProps> = ({ description, onEditContent }) => {
 | 
					const TaskContent: React.FC<TaskContentProps> = ({ description, onEditContent }) => {
 | 
				
			||||||
  return description === '' ? (
 | 
					  return description === '' ? (
 | 
				
			||||||
    <TaskDetailsAddDetailsButton onClick={onEditContent}>Add a more detailed description</TaskDetailsAddDetailsButton>
 | 
					    <TaskDetailsAddDetailsButton onClick={onEditContent}>Add a more detailed description</TaskDetailsAddDetailsButton>
 | 
				
			||||||
@@ -105,6 +124,10 @@ type TaskDetailsProps = {
 | 
				
			|||||||
  onTaskNameChange: (task: Task, newName: string) => void;
 | 
					  onTaskNameChange: (task: Task, newName: string) => void;
 | 
				
			||||||
  onTaskDescriptionChange: (task: Task, newDescription: string) => void;
 | 
					  onTaskDescriptionChange: (task: Task, newDescription: string) => void;
 | 
				
			||||||
  onDeleteTask: (task: Task) => void;
 | 
					  onDeleteTask: (task: Task) => void;
 | 
				
			||||||
 | 
					  onAddItem: (checklistID: string, name: string, position: number) => void;
 | 
				
			||||||
 | 
					  onDeleteItem: (itemID: string) => void;
 | 
				
			||||||
 | 
					  onChangeItemName: (itemID: string, itemName: string) => void;
 | 
				
			||||||
 | 
					  onToggleChecklistItem: (itemID: string, complete: boolean) => void;
 | 
				
			||||||
  onOpenAddMemberPopup: (task: Task, $targetRef: React.RefObject<HTMLElement>) => void;
 | 
					  onOpenAddMemberPopup: (task: Task, $targetRef: React.RefObject<HTMLElement>) => void;
 | 
				
			||||||
  onOpenAddLabelPopup: (task: Task, $targetRef: React.RefObject<HTMLElement>) => void;
 | 
					  onOpenAddLabelPopup: (task: Task, $targetRef: React.RefObject<HTMLElement>) => void;
 | 
				
			||||||
  onOpenDueDatePopop: (task: Task, $targetRef: React.RefObject<HTMLElement>) => void;
 | 
					  onOpenDueDatePopop: (task: Task, $targetRef: React.RefObject<HTMLElement>) => void;
 | 
				
			||||||
@@ -116,11 +139,15 @@ const TaskDetails: React.FC<TaskDetailsProps> = ({
 | 
				
			|||||||
  task,
 | 
					  task,
 | 
				
			||||||
  onTaskNameChange,
 | 
					  onTaskNameChange,
 | 
				
			||||||
  onTaskDescriptionChange,
 | 
					  onTaskDescriptionChange,
 | 
				
			||||||
 | 
					  onChangeItemName,
 | 
				
			||||||
 | 
					  onDeleteItem,
 | 
				
			||||||
  onDeleteTask,
 | 
					  onDeleteTask,
 | 
				
			||||||
  onCloseModal,
 | 
					  onCloseModal,
 | 
				
			||||||
  onOpenAddMemberPopup,
 | 
					  onOpenAddMemberPopup,
 | 
				
			||||||
  onOpenAddLabelPopup,
 | 
					  onOpenAddLabelPopup,
 | 
				
			||||||
  onOpenDueDatePopop,
 | 
					  onOpenDueDatePopop,
 | 
				
			||||||
 | 
					  onAddItem,
 | 
				
			||||||
 | 
					  onToggleChecklistItem,
 | 
				
			||||||
  onMemberProfile,
 | 
					  onMemberProfile,
 | 
				
			||||||
}) => {
 | 
					}) => {
 | 
				
			||||||
  const [editorOpen, setEditorOpen] = useState(false);
 | 
					  const [editorOpen, setEditorOpen] = useState(false);
 | 
				
			||||||
@@ -158,7 +185,7 @@ const TaskDetails: React.FC<TaskDetailsProps> = ({
 | 
				
			|||||||
          <Bin size={20} color="#c2c6dc" />
 | 
					          <Bin size={20} color="#c2c6dc" />
 | 
				
			||||||
        </TaskAction>
 | 
					        </TaskAction>
 | 
				
			||||||
        <TaskAction onClick={onCloseModal}>
 | 
					        <TaskAction onClick={onCloseModal}>
 | 
				
			||||||
          <Cross size={20} color="#c2c6dc" />
 | 
					          <Cross width={16} height={16} />
 | 
				
			||||||
        </TaskAction>
 | 
					        </TaskAction>
 | 
				
			||||||
      </TaskActions>
 | 
					      </TaskActions>
 | 
				
			||||||
      <TaskHeader>
 | 
					      <TaskHeader>
 | 
				
			||||||
@@ -195,6 +222,33 @@ const TaskDetails: React.FC<TaskDetailsProps> = ({
 | 
				
			|||||||
          ) : (
 | 
					          ) : (
 | 
				
			||||||
            <TaskContent description={description} onEditContent={handleClick} />
 | 
					            <TaskContent description={description} onEditContent={handleClick} />
 | 
				
			||||||
          )}
 | 
					          )}
 | 
				
			||||||
 | 
					          {task.checklists &&
 | 
				
			||||||
 | 
					            task.checklists
 | 
				
			||||||
 | 
					              .slice()
 | 
				
			||||||
 | 
					              .sort((a, b) => a.position - b.position)
 | 
				
			||||||
 | 
					              .map(checklist => (
 | 
				
			||||||
 | 
					                <Checklist
 | 
				
			||||||
 | 
					                  key={checklist.id}
 | 
				
			||||||
 | 
					                  name={checklist.name}
 | 
				
			||||||
 | 
					                  checklistID={checklist.id}
 | 
				
			||||||
 | 
					                  items={checklist.items}
 | 
				
			||||||
 | 
					                  onDeleteChecklist={() => {}}
 | 
				
			||||||
 | 
					                  onChangeName={() => {}}
 | 
				
			||||||
 | 
					                  onToggleItem={onToggleChecklistItem}
 | 
				
			||||||
 | 
					                  onDeleteItem={onDeleteItem}
 | 
				
			||||||
 | 
					                  onAddItem={n => {
 | 
				
			||||||
 | 
					                    if (task.checklists) {
 | 
				
			||||||
 | 
					                      let position = 1;
 | 
				
			||||||
 | 
					                      const lastChecklist = task.checklists.sort((a, b) => a.position - b.position)[-1];
 | 
				
			||||||
 | 
					                      if (lastChecklist) {
 | 
				
			||||||
 | 
					                        position = lastChecklist.position * 2 + 1;
 | 
				
			||||||
 | 
					                      }
 | 
				
			||||||
 | 
					                      onAddItem(checklist.id, n, position);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                  }}
 | 
				
			||||||
 | 
					                  onChangeItemName={onChangeItemName}
 | 
				
			||||||
 | 
					                />
 | 
				
			||||||
 | 
					              ))}
 | 
				
			||||||
        </TaskDetailsContent>
 | 
					        </TaskDetailsContent>
 | 
				
			||||||
        <TaskDetailsSidebar>
 | 
					        <TaskDetailsSidebar>
 | 
				
			||||||
          <TaskDetailSectionTitle>Assignees</TaskDetailSectionTitle>
 | 
					          <TaskDetailSectionTitle>Assignees</TaskDetailSectionTitle>
 | 
				
			||||||
@@ -221,9 +275,13 @@ const TaskDetails: React.FC<TaskDetailsProps> = ({
 | 
				
			|||||||
          <TaskDetailLabels>
 | 
					          <TaskDetailLabels>
 | 
				
			||||||
            {task.labels.map(label => {
 | 
					            {task.labels.map(label => {
 | 
				
			||||||
              return (
 | 
					              return (
 | 
				
			||||||
                <TaskDetailLabel key={label.projectLabel.id} color={label.projectLabel.labelColor.colorHex}>
 | 
					                <TaskLabelItem
 | 
				
			||||||
                  {label.projectLabel.name}
 | 
					                  key={label.projectLabel.id}
 | 
				
			||||||
                </TaskDetailLabel>
 | 
					                  label={label}
 | 
				
			||||||
 | 
					                  onClick={$target => {
 | 
				
			||||||
 | 
					                    onOpenAddLabelPopup(task, $target);
 | 
				
			||||||
 | 
					                  }}
 | 
				
			||||||
 | 
					                />
 | 
				
			||||||
              );
 | 
					              );
 | 
				
			||||||
            })}
 | 
					            })}
 | 
				
			||||||
            <TaskDetailsAddLabel ref={$addLabelRef} onClick={onAddLabel}>
 | 
					            <TaskDetailsAddLabel ref={$addLabelRef} onClick={onAddLabel}>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -111,8 +111,10 @@ export type Task = {
 | 
				
			|||||||
  position: Scalars['Float'];
 | 
					  position: Scalars['Float'];
 | 
				
			||||||
  description?: Maybe<Scalars['String']>;
 | 
					  description?: Maybe<Scalars['String']>;
 | 
				
			||||||
  dueDate?: Maybe<Scalars['Time']>;
 | 
					  dueDate?: Maybe<Scalars['Time']>;
 | 
				
			||||||
 | 
					  complete: Scalars['Boolean'];
 | 
				
			||||||
  assigned: Array<ProjectMember>;
 | 
					  assigned: Array<ProjectMember>;
 | 
				
			||||||
  labels: Array<TaskLabel>;
 | 
					  labels: Array<TaskLabel>;
 | 
				
			||||||
 | 
					  checklists: Array<TaskChecklist>;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type ProjectsFilter = {
 | 
					export type ProjectsFilter = {
 | 
				
			||||||
@@ -239,6 +241,30 @@ export type DeleteTaskGroupPayload = {
 | 
				
			|||||||
  taskGroup: TaskGroup;
 | 
					  taskGroup: TaskGroup;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type DeleteTaskChecklistItemPayload = {
 | 
				
			||||||
 | 
					   __typename?: 'DeleteTaskChecklistItemPayload';
 | 
				
			||||||
 | 
					  ok: Scalars['Boolean'];
 | 
				
			||||||
 | 
					  taskChecklistItem: TaskChecklistItem;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type TaskChecklistItem = {
 | 
				
			||||||
 | 
					   __typename?: 'TaskChecklistItem';
 | 
				
			||||||
 | 
					  id: Scalars['ID'];
 | 
				
			||||||
 | 
					  name: Scalars['String'];
 | 
				
			||||||
 | 
					  taskChecklistID: Scalars['UUID'];
 | 
				
			||||||
 | 
					  complete: Scalars['Boolean'];
 | 
				
			||||||
 | 
					  position: Scalars['Float'];
 | 
				
			||||||
 | 
					  dueDate: Scalars['Time'];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type TaskChecklist = {
 | 
				
			||||||
 | 
					   __typename?: 'TaskChecklist';
 | 
				
			||||||
 | 
					  id: Scalars['ID'];
 | 
				
			||||||
 | 
					  name: Scalars['String'];
 | 
				
			||||||
 | 
					  position: Scalars['Float'];
 | 
				
			||||||
 | 
					  items: Array<TaskChecklistItem>;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type AssignTaskInput = {
 | 
					export type AssignTaskInput = {
 | 
				
			||||||
  taskID: Scalars['UUID'];
 | 
					  taskID: Scalars['UUID'];
 | 
				
			||||||
  userID: Scalars['UUID'];
 | 
					  userID: Scalars['UUID'];
 | 
				
			||||||
@@ -321,6 +347,37 @@ export type UpdateTaskDueDate = {
 | 
				
			|||||||
  dueDate?: Maybe<Scalars['Time']>;
 | 
					  dueDate?: Maybe<Scalars['Time']>;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type SetTaskComplete = {
 | 
				
			||||||
 | 
					  taskID: Scalars['UUID'];
 | 
				
			||||||
 | 
					  complete: Scalars['Boolean'];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type CreateTaskChecklist = {
 | 
				
			||||||
 | 
					  taskID: Scalars['UUID'];
 | 
				
			||||||
 | 
					  name: Scalars['String'];
 | 
				
			||||||
 | 
					  position: Scalars['Float'];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type CreateTaskChecklistItem = {
 | 
				
			||||||
 | 
					  taskChecklistID: Scalars['UUID'];
 | 
				
			||||||
 | 
					  name: Scalars['String'];
 | 
				
			||||||
 | 
					  position: Scalars['Float'];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type SetTaskChecklistItemComplete = {
 | 
				
			||||||
 | 
					  taskChecklistItemID: Scalars['UUID'];
 | 
				
			||||||
 | 
					  complete: Scalars['Boolean'];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type DeleteTaskChecklistItem = {
 | 
				
			||||||
 | 
					  taskChecklistItemID: Scalars['UUID'];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type UpdateTaskChecklistItemName = {
 | 
				
			||||||
 | 
					  taskChecklistItemID: Scalars['UUID'];
 | 
				
			||||||
 | 
					  name: Scalars['String'];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type Mutation = {
 | 
					export type Mutation = {
 | 
				
			||||||
   __typename?: 'Mutation';
 | 
					   __typename?: 'Mutation';
 | 
				
			||||||
  createRefreshToken: RefreshToken;
 | 
					  createRefreshToken: RefreshToken;
 | 
				
			||||||
@@ -341,10 +398,16 @@ export type Mutation = {
 | 
				
			|||||||
  addTaskLabel: Task;
 | 
					  addTaskLabel: Task;
 | 
				
			||||||
  removeTaskLabel: Task;
 | 
					  removeTaskLabel: Task;
 | 
				
			||||||
  toggleTaskLabel: ToggleTaskLabelPayload;
 | 
					  toggleTaskLabel: ToggleTaskLabelPayload;
 | 
				
			||||||
 | 
					  createTaskChecklist: TaskChecklist;
 | 
				
			||||||
 | 
					  createTaskChecklistItem: TaskChecklistItem;
 | 
				
			||||||
 | 
					  updateTaskChecklistItemName: TaskChecklistItem;
 | 
				
			||||||
 | 
					  setTaskChecklistItemComplete: TaskChecklistItem;
 | 
				
			||||||
 | 
					  deleteTaskChecklistItem: DeleteTaskChecklistItemPayload;
 | 
				
			||||||
  createTask: Task;
 | 
					  createTask: Task;
 | 
				
			||||||
  updateTaskDescription: Task;
 | 
					  updateTaskDescription: Task;
 | 
				
			||||||
  updateTaskLocation: UpdateTaskLocationPayload;
 | 
					  updateTaskLocation: UpdateTaskLocationPayload;
 | 
				
			||||||
  updateTaskName: Task;
 | 
					  updateTaskName: Task;
 | 
				
			||||||
 | 
					  setTaskComplete: Task;
 | 
				
			||||||
  updateTaskDueDate: Task;
 | 
					  updateTaskDueDate: Task;
 | 
				
			||||||
  deleteTask: DeleteTaskPayload;
 | 
					  deleteTask: DeleteTaskPayload;
 | 
				
			||||||
  assignTask: Task;
 | 
					  assignTask: Task;
 | 
				
			||||||
@@ -438,6 +501,31 @@ export type MutationToggleTaskLabelArgs = {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type MutationCreateTaskChecklistArgs = {
 | 
				
			||||||
 | 
					  input: CreateTaskChecklist;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type MutationCreateTaskChecklistItemArgs = {
 | 
				
			||||||
 | 
					  input: CreateTaskChecklistItem;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type MutationUpdateTaskChecklistItemNameArgs = {
 | 
				
			||||||
 | 
					  input: UpdateTaskChecklistItemName;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type MutationSetTaskChecklistItemCompleteArgs = {
 | 
				
			||||||
 | 
					  input: SetTaskChecklistItemComplete;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type MutationDeleteTaskChecklistItemArgs = {
 | 
				
			||||||
 | 
					  input: DeleteTaskChecklistItem;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type MutationCreateTaskArgs = {
 | 
					export type MutationCreateTaskArgs = {
 | 
				
			||||||
  input: NewTask;
 | 
					  input: NewTask;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@@ -458,6 +546,11 @@ export type MutationUpdateTaskNameArgs = {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type MutationSetTaskCompleteArgs = {
 | 
				
			||||||
 | 
					  input: SetTaskComplete;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type MutationUpdateTaskDueDateArgs = {
 | 
					export type MutationUpdateTaskDueDateArgs = {
 | 
				
			||||||
  input: UpdateTaskDueDate;
 | 
					  input: UpdateTaskDueDate;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@@ -564,7 +657,7 @@ export type CreateTaskMutation = (
 | 
				
			|||||||
  { __typename?: 'Mutation' }
 | 
					  { __typename?: 'Mutation' }
 | 
				
			||||||
  & { createTask: (
 | 
					  & { createTask: (
 | 
				
			||||||
    { __typename?: 'Task' }
 | 
					    { __typename?: 'Task' }
 | 
				
			||||||
    & Pick<Task, 'id' | 'name' | 'position' | 'description'>
 | 
					    & Pick<Task, 'id' | 'name' | 'position' | 'description' | 'dueDate'>
 | 
				
			||||||
    & { taskGroup: (
 | 
					    & { taskGroup: (
 | 
				
			||||||
      { __typename?: 'TaskGroup' }
 | 
					      { __typename?: 'TaskGroup' }
 | 
				
			||||||
      & Pick<TaskGroup, 'id' | 'name' | 'position'>
 | 
					      & Pick<TaskGroup, 'id' | 'name' | 'position'>
 | 
				
			||||||
@@ -681,29 +774,7 @@ export type FindProjectQuery = (
 | 
				
			|||||||
      & Pick<TaskGroup, 'id' | 'name' | 'position'>
 | 
					      & Pick<TaskGroup, 'id' | 'name' | 'position'>
 | 
				
			||||||
      & { tasks: Array<(
 | 
					      & { tasks: Array<(
 | 
				
			||||||
        { __typename?: 'Task' }
 | 
					        { __typename?: 'Task' }
 | 
				
			||||||
        & Pick<Task, 'id' | 'name' | 'position' | 'description' | 'dueDate'>
 | 
					        & TaskFieldsFragment
 | 
				
			||||||
        & { 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' }
 | 
					 | 
				
			||||||
          & Pick<ProjectMember, 'id' | 'fullName'>
 | 
					 | 
				
			||||||
          & { profileIcon: (
 | 
					 | 
				
			||||||
            { __typename?: 'ProfileIcon' }
 | 
					 | 
				
			||||||
            & Pick<ProfileIcon, 'url' | 'initials' | 'bgColor'>
 | 
					 | 
				
			||||||
          ) }
 | 
					 | 
				
			||||||
        )> }
 | 
					 | 
				
			||||||
      )> }
 | 
					      )> }
 | 
				
			||||||
    )> }
 | 
					    )> }
 | 
				
			||||||
  ), labelColors: Array<(
 | 
					  ), labelColors: Array<(
 | 
				
			||||||
@@ -725,7 +796,14 @@ export type FindTaskQuery = (
 | 
				
			|||||||
    & { taskGroup: (
 | 
					    & { taskGroup: (
 | 
				
			||||||
      { __typename?: 'TaskGroup' }
 | 
					      { __typename?: 'TaskGroup' }
 | 
				
			||||||
      & Pick<TaskGroup, 'id'>
 | 
					      & Pick<TaskGroup, 'id'>
 | 
				
			||||||
    ), labels: Array<(
 | 
					    ), checklists: Array<(
 | 
				
			||||||
 | 
					      { __typename?: 'TaskChecklist' }
 | 
				
			||||||
 | 
					      & Pick<TaskChecklist, 'id' | 'name' | 'position'>
 | 
				
			||||||
 | 
					      & { items: Array<(
 | 
				
			||||||
 | 
					        { __typename?: 'TaskChecklistItem' }
 | 
				
			||||||
 | 
					        & Pick<TaskChecklistItem, 'id' | 'name' | 'taskChecklistID' | 'complete' | 'position'>
 | 
				
			||||||
 | 
					      )> }
 | 
				
			||||||
 | 
					    )>, labels: Array<(
 | 
				
			||||||
      { __typename?: 'TaskLabel' }
 | 
					      { __typename?: 'TaskLabel' }
 | 
				
			||||||
      & Pick<TaskLabel, 'id' | 'assignedDate'>
 | 
					      & Pick<TaskLabel, 'id' | 'assignedDate'>
 | 
				
			||||||
      & { projectLabel: (
 | 
					      & { projectLabel: (
 | 
				
			||||||
@@ -747,6 +825,33 @@ export type FindTaskQuery = (
 | 
				
			|||||||
  ) }
 | 
					  ) }
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type TaskFieldsFragment = (
 | 
				
			||||||
 | 
					  { __typename?: 'Task' }
 | 
				
			||||||
 | 
					  & Pick<Task, 'id' | 'name' | 'description' | 'dueDate' | 'complete' | 'position'>
 | 
				
			||||||
 | 
					  & { taskGroup: (
 | 
				
			||||||
 | 
					    { __typename?: 'TaskGroup' }
 | 
				
			||||||
 | 
					    & Pick<TaskGroup, 'id'>
 | 
				
			||||||
 | 
					  ), 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' }
 | 
				
			||||||
 | 
					    & Pick<ProjectMember, 'id' | 'fullName'>
 | 
				
			||||||
 | 
					    & { profileIcon: (
 | 
				
			||||||
 | 
					      { __typename?: 'ProfileIcon' }
 | 
				
			||||||
 | 
					      & Pick<ProfileIcon, 'url' | 'initials' | 'bgColor'>
 | 
				
			||||||
 | 
					    ) }
 | 
				
			||||||
 | 
					  )> }
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type GetProjectsQueryVariables = {};
 | 
					export type GetProjectsQueryVariables = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -780,6 +885,94 @@ export type MeQuery = (
 | 
				
			|||||||
  ) }
 | 
					  ) }
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type CreateTaskChecklistItemMutationVariables = {
 | 
				
			||||||
 | 
					  taskChecklistID: Scalars['UUID'];
 | 
				
			||||||
 | 
					  name: Scalars['String'];
 | 
				
			||||||
 | 
					  position: Scalars['Float'];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type CreateTaskChecklistItemMutation = (
 | 
				
			||||||
 | 
					  { __typename?: 'Mutation' }
 | 
				
			||||||
 | 
					  & { createTaskChecklistItem: (
 | 
				
			||||||
 | 
					    { __typename?: 'TaskChecklistItem' }
 | 
				
			||||||
 | 
					    & Pick<TaskChecklistItem, 'id' | 'name' | 'taskChecklistID' | 'position' | 'complete'>
 | 
				
			||||||
 | 
					  ) }
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type DeleteTaskChecklistItemMutationVariables = {
 | 
				
			||||||
 | 
					  taskChecklistItemID: Scalars['UUID'];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type DeleteTaskChecklistItemMutation = (
 | 
				
			||||||
 | 
					  { __typename?: 'Mutation' }
 | 
				
			||||||
 | 
					  & { deleteTaskChecklistItem: (
 | 
				
			||||||
 | 
					    { __typename?: 'DeleteTaskChecklistItemPayload' }
 | 
				
			||||||
 | 
					    & Pick<DeleteTaskChecklistItemPayload, 'ok'>
 | 
				
			||||||
 | 
					    & { taskChecklistItem: (
 | 
				
			||||||
 | 
					      { __typename?: 'TaskChecklistItem' }
 | 
				
			||||||
 | 
					      & Pick<TaskChecklistItem, 'id' | 'taskChecklistID'>
 | 
				
			||||||
 | 
					    ) }
 | 
				
			||||||
 | 
					  ) }
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type SetTaskChecklistItemCompleteMutationVariables = {
 | 
				
			||||||
 | 
					  taskChecklistItemID: Scalars['UUID'];
 | 
				
			||||||
 | 
					  complete: Scalars['Boolean'];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type SetTaskChecklistItemCompleteMutation = (
 | 
				
			||||||
 | 
					  { __typename?: 'Mutation' }
 | 
				
			||||||
 | 
					  & { setTaskChecklistItemComplete: (
 | 
				
			||||||
 | 
					    { __typename?: 'TaskChecklistItem' }
 | 
				
			||||||
 | 
					    & Pick<TaskChecklistItem, 'id' | 'name' | 'taskChecklistID' | 'complete' | 'position'>
 | 
				
			||||||
 | 
					  ) }
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type SetTaskCompleteMutationVariables = {
 | 
				
			||||||
 | 
					  taskID: Scalars['UUID'];
 | 
				
			||||||
 | 
					  complete: Scalars['Boolean'];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type SetTaskCompleteMutation = (
 | 
				
			||||||
 | 
					  { __typename?: 'Mutation' }
 | 
				
			||||||
 | 
					  & { setTaskComplete: (
 | 
				
			||||||
 | 
					    { __typename?: 'Task' }
 | 
				
			||||||
 | 
					    & TaskFieldsFragment
 | 
				
			||||||
 | 
					  ) }
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type UpdateTaskChecklistItemNameMutationVariables = {
 | 
				
			||||||
 | 
					  taskChecklistItemID: Scalars['UUID'];
 | 
				
			||||||
 | 
					  name: Scalars['String'];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type UpdateTaskChecklistItemNameMutation = (
 | 
				
			||||||
 | 
					  { __typename?: 'Mutation' }
 | 
				
			||||||
 | 
					  & { updateTaskChecklistItemName: (
 | 
				
			||||||
 | 
					    { __typename?: 'TaskChecklistItem' }
 | 
				
			||||||
 | 
					    & Pick<TaskChecklistItem, 'id' | 'name'>
 | 
				
			||||||
 | 
					  ) }
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type UpdateTaskGroupNameMutationVariables = {
 | 
				
			||||||
 | 
					  taskGroupID: Scalars['UUID'];
 | 
				
			||||||
 | 
					  name: Scalars['String'];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type UpdateTaskGroupNameMutation = (
 | 
				
			||||||
 | 
					  { __typename?: 'Mutation' }
 | 
				
			||||||
 | 
					  & { updateTaskGroupName: (
 | 
				
			||||||
 | 
					    { __typename?: 'TaskGroup' }
 | 
				
			||||||
 | 
					    & Pick<TaskGroup, 'id' | 'name'>
 | 
				
			||||||
 | 
					  ) }
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type ToggleTaskLabelMutationVariables = {
 | 
					export type ToggleTaskLabelMutationVariables = {
 | 
				
			||||||
  taskID: Scalars['UUID'];
 | 
					  taskID: Scalars['UUID'];
 | 
				
			||||||
  projectLabelID: Scalars['UUID'];
 | 
					  projectLabelID: Scalars['UUID'];
 | 
				
			||||||
@@ -940,7 +1133,43 @@ export type UpdateTaskNameMutation = (
 | 
				
			|||||||
  ) }
 | 
					  ) }
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const TaskFieldsFragmentDoc = gql`
 | 
				
			||||||
 | 
					    fragment TaskFields on Task {
 | 
				
			||||||
 | 
					  id
 | 
				
			||||||
 | 
					  name
 | 
				
			||||||
 | 
					  description
 | 
				
			||||||
 | 
					  dueDate
 | 
				
			||||||
 | 
					  complete
 | 
				
			||||||
 | 
					  position
 | 
				
			||||||
 | 
					  taskGroup {
 | 
				
			||||||
 | 
					    id
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  labels {
 | 
				
			||||||
 | 
					    id
 | 
				
			||||||
 | 
					    assignedDate
 | 
				
			||||||
 | 
					    projectLabel {
 | 
				
			||||||
 | 
					      id
 | 
				
			||||||
 | 
					      name
 | 
				
			||||||
 | 
					      createdDate
 | 
				
			||||||
 | 
					      labelColor {
 | 
				
			||||||
 | 
					        id
 | 
				
			||||||
 | 
					        colorHex
 | 
				
			||||||
 | 
					        position
 | 
				
			||||||
 | 
					        name
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  assigned {
 | 
				
			||||||
 | 
					    id
 | 
				
			||||||
 | 
					    fullName
 | 
				
			||||||
 | 
					    profileIcon {
 | 
				
			||||||
 | 
					      url
 | 
				
			||||||
 | 
					      initials
 | 
				
			||||||
 | 
					      bgColor
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					    `;
 | 
				
			||||||
export const AssignTaskDocument = gql`
 | 
					export const AssignTaskDocument = gql`
 | 
				
			||||||
    mutation assignTask($taskID: UUID!, $userID: UUID!) {
 | 
					    mutation assignTask($taskID: UUID!, $userID: UUID!) {
 | 
				
			||||||
  assignTask(input: {taskID: $taskID, userID: $userID}) {
 | 
					  assignTask(input: {taskID: $taskID, userID: $userID}) {
 | 
				
			||||||
@@ -1103,6 +1332,7 @@ export const CreateTaskDocument = gql`
 | 
				
			|||||||
    name
 | 
					    name
 | 
				
			||||||
    position
 | 
					    position
 | 
				
			||||||
    description
 | 
					    description
 | 
				
			||||||
 | 
					    dueDate
 | 
				
			||||||
    taskGroup {
 | 
					    taskGroup {
 | 
				
			||||||
      id
 | 
					      id
 | 
				
			||||||
      name
 | 
					      name
 | 
				
			||||||
@@ -1331,40 +1561,7 @@ export const FindProjectDocument = gql`
 | 
				
			|||||||
      name
 | 
					      name
 | 
				
			||||||
      position
 | 
					      position
 | 
				
			||||||
      tasks {
 | 
					      tasks {
 | 
				
			||||||
        id
 | 
					        ...TaskFields
 | 
				
			||||||
        name
 | 
					 | 
				
			||||||
        position
 | 
					 | 
				
			||||||
        description
 | 
					 | 
				
			||||||
        dueDate
 | 
					 | 
				
			||||||
        taskGroup {
 | 
					 | 
				
			||||||
          id
 | 
					 | 
				
			||||||
          name
 | 
					 | 
				
			||||||
          position
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        labels {
 | 
					 | 
				
			||||||
          id
 | 
					 | 
				
			||||||
          assignedDate
 | 
					 | 
				
			||||||
          projectLabel {
 | 
					 | 
				
			||||||
            id
 | 
					 | 
				
			||||||
            name
 | 
					 | 
				
			||||||
            createdDate
 | 
					 | 
				
			||||||
            labelColor {
 | 
					 | 
				
			||||||
              id
 | 
					 | 
				
			||||||
              colorHex
 | 
					 | 
				
			||||||
              position
 | 
					 | 
				
			||||||
              name
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        assigned {
 | 
					 | 
				
			||||||
          id
 | 
					 | 
				
			||||||
          fullName
 | 
					 | 
				
			||||||
          profileIcon {
 | 
					 | 
				
			||||||
            url
 | 
					 | 
				
			||||||
            initials
 | 
					 | 
				
			||||||
            bgColor
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -1375,7 +1572,7 @@ export const FindProjectDocument = gql`
 | 
				
			|||||||
    name
 | 
					    name
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
    `;
 | 
					    ${TaskFieldsFragmentDoc}`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * __useFindProjectQuery__
 | 
					 * __useFindProjectQuery__
 | 
				
			||||||
@@ -1413,6 +1610,18 @@ export const FindTaskDocument = gql`
 | 
				
			|||||||
    taskGroup {
 | 
					    taskGroup {
 | 
				
			||||||
      id
 | 
					      id
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    checklists {
 | 
				
			||||||
 | 
					      id
 | 
				
			||||||
 | 
					      name
 | 
				
			||||||
 | 
					      position
 | 
				
			||||||
 | 
					      items {
 | 
				
			||||||
 | 
					        id
 | 
				
			||||||
 | 
					        name
 | 
				
			||||||
 | 
					        taskChecklistID
 | 
				
			||||||
 | 
					        complete
 | 
				
			||||||
 | 
					        position
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    labels {
 | 
					    labels {
 | 
				
			||||||
      id
 | 
					      id
 | 
				
			||||||
      assignedDate
 | 
					      assignedDate
 | 
				
			||||||
@@ -1546,6 +1755,218 @@ 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 CreateTaskChecklistItemDocument = gql`
 | 
				
			||||||
 | 
					    mutation createTaskChecklistItem($taskChecklistID: UUID!, $name: String!, $position: Float!) {
 | 
				
			||||||
 | 
					  createTaskChecklistItem(input: {taskChecklistID: $taskChecklistID, name: $name, position: $position}) {
 | 
				
			||||||
 | 
					    id
 | 
				
			||||||
 | 
					    name
 | 
				
			||||||
 | 
					    taskChecklistID
 | 
				
			||||||
 | 
					    position
 | 
				
			||||||
 | 
					    complete
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					    `;
 | 
				
			||||||
 | 
					export type CreateTaskChecklistItemMutationFn = ApolloReactCommon.MutationFunction<CreateTaskChecklistItemMutation, CreateTaskChecklistItemMutationVariables>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * __useCreateTaskChecklistItemMutation__
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * To run a mutation, you first call `useCreateTaskChecklistItemMutation` within a React component and pass it any options that fit your needs.
 | 
				
			||||||
 | 
					 * When your component renders, `useCreateTaskChecklistItemMutation` 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 [createTaskChecklistItemMutation, { data, loading, error }] = useCreateTaskChecklistItemMutation({
 | 
				
			||||||
 | 
					 *   variables: {
 | 
				
			||||||
 | 
					 *      taskChecklistID: // value for 'taskChecklistID'
 | 
				
			||||||
 | 
					 *      name: // value for 'name'
 | 
				
			||||||
 | 
					 *      position: // value for 'position'
 | 
				
			||||||
 | 
					 *   },
 | 
				
			||||||
 | 
					 * });
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export function useCreateTaskChecklistItemMutation(baseOptions?: ApolloReactHooks.MutationHookOptions<CreateTaskChecklistItemMutation, CreateTaskChecklistItemMutationVariables>) {
 | 
				
			||||||
 | 
					        return ApolloReactHooks.useMutation<CreateTaskChecklistItemMutation, CreateTaskChecklistItemMutationVariables>(CreateTaskChecklistItemDocument, baseOptions);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					export type CreateTaskChecklistItemMutationHookResult = ReturnType<typeof useCreateTaskChecklistItemMutation>;
 | 
				
			||||||
 | 
					export type CreateTaskChecklistItemMutationResult = ApolloReactCommon.MutationResult<CreateTaskChecklistItemMutation>;
 | 
				
			||||||
 | 
					export type CreateTaskChecklistItemMutationOptions = ApolloReactCommon.BaseMutationOptions<CreateTaskChecklistItemMutation, CreateTaskChecklistItemMutationVariables>;
 | 
				
			||||||
 | 
					export const DeleteTaskChecklistItemDocument = gql`
 | 
				
			||||||
 | 
					    mutation deleteTaskChecklistItem($taskChecklistItemID: UUID!) {
 | 
				
			||||||
 | 
					  deleteTaskChecklistItem(input: {taskChecklistItemID: $taskChecklistItemID}) {
 | 
				
			||||||
 | 
					    ok
 | 
				
			||||||
 | 
					    taskChecklistItem {
 | 
				
			||||||
 | 
					      id
 | 
				
			||||||
 | 
					      taskChecklistID
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					    `;
 | 
				
			||||||
 | 
					export type DeleteTaskChecklistItemMutationFn = ApolloReactCommon.MutationFunction<DeleteTaskChecklistItemMutation, DeleteTaskChecklistItemMutationVariables>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * __useDeleteTaskChecklistItemMutation__
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * To run a mutation, you first call `useDeleteTaskChecklistItemMutation` within a React component and pass it any options that fit your needs.
 | 
				
			||||||
 | 
					 * When your component renders, `useDeleteTaskChecklistItemMutation` 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 [deleteTaskChecklistItemMutation, { data, loading, error }] = useDeleteTaskChecklistItemMutation({
 | 
				
			||||||
 | 
					 *   variables: {
 | 
				
			||||||
 | 
					 *      taskChecklistItemID: // value for 'taskChecklistItemID'
 | 
				
			||||||
 | 
					 *   },
 | 
				
			||||||
 | 
					 * });
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export function useDeleteTaskChecklistItemMutation(baseOptions?: ApolloReactHooks.MutationHookOptions<DeleteTaskChecklistItemMutation, DeleteTaskChecklistItemMutationVariables>) {
 | 
				
			||||||
 | 
					        return ApolloReactHooks.useMutation<DeleteTaskChecklistItemMutation, DeleteTaskChecklistItemMutationVariables>(DeleteTaskChecklistItemDocument, baseOptions);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					export type DeleteTaskChecklistItemMutationHookResult = ReturnType<typeof useDeleteTaskChecklistItemMutation>;
 | 
				
			||||||
 | 
					export type DeleteTaskChecklistItemMutationResult = ApolloReactCommon.MutationResult<DeleteTaskChecklistItemMutation>;
 | 
				
			||||||
 | 
					export type DeleteTaskChecklistItemMutationOptions = ApolloReactCommon.BaseMutationOptions<DeleteTaskChecklistItemMutation, DeleteTaskChecklistItemMutationVariables>;
 | 
				
			||||||
 | 
					export const SetTaskChecklistItemCompleteDocument = gql`
 | 
				
			||||||
 | 
					    mutation setTaskChecklistItemComplete($taskChecklistItemID: UUID!, $complete: Boolean!) {
 | 
				
			||||||
 | 
					  setTaskChecklistItemComplete(input: {taskChecklistItemID: $taskChecklistItemID, complete: $complete}) {
 | 
				
			||||||
 | 
					    id
 | 
				
			||||||
 | 
					    name
 | 
				
			||||||
 | 
					    taskChecklistID
 | 
				
			||||||
 | 
					    complete
 | 
				
			||||||
 | 
					    position
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					    `;
 | 
				
			||||||
 | 
					export type SetTaskChecklistItemCompleteMutationFn = ApolloReactCommon.MutationFunction<SetTaskChecklistItemCompleteMutation, SetTaskChecklistItemCompleteMutationVariables>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * __useSetTaskChecklistItemCompleteMutation__
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * To run a mutation, you first call `useSetTaskChecklistItemCompleteMutation` within a React component and pass it any options that fit your needs.
 | 
				
			||||||
 | 
					 * When your component renders, `useSetTaskChecklistItemCompleteMutation` 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 [setTaskChecklistItemCompleteMutation, { data, loading, error }] = useSetTaskChecklistItemCompleteMutation({
 | 
				
			||||||
 | 
					 *   variables: {
 | 
				
			||||||
 | 
					 *      taskChecklistItemID: // value for 'taskChecklistItemID'
 | 
				
			||||||
 | 
					 *      complete: // value for 'complete'
 | 
				
			||||||
 | 
					 *   },
 | 
				
			||||||
 | 
					 * });
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export function useSetTaskChecklistItemCompleteMutation(baseOptions?: ApolloReactHooks.MutationHookOptions<SetTaskChecklistItemCompleteMutation, SetTaskChecklistItemCompleteMutationVariables>) {
 | 
				
			||||||
 | 
					        return ApolloReactHooks.useMutation<SetTaskChecklistItemCompleteMutation, SetTaskChecklistItemCompleteMutationVariables>(SetTaskChecklistItemCompleteDocument, baseOptions);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					export type SetTaskChecklistItemCompleteMutationHookResult = ReturnType<typeof useSetTaskChecklistItemCompleteMutation>;
 | 
				
			||||||
 | 
					export type SetTaskChecklistItemCompleteMutationResult = ApolloReactCommon.MutationResult<SetTaskChecklistItemCompleteMutation>;
 | 
				
			||||||
 | 
					export type SetTaskChecklistItemCompleteMutationOptions = ApolloReactCommon.BaseMutationOptions<SetTaskChecklistItemCompleteMutation, SetTaskChecklistItemCompleteMutationVariables>;
 | 
				
			||||||
 | 
					export const SetTaskCompleteDocument = gql`
 | 
				
			||||||
 | 
					    mutation setTaskComplete($taskID: UUID!, $complete: Boolean!) {
 | 
				
			||||||
 | 
					  setTaskComplete(input: {taskID: $taskID, complete: $complete}) {
 | 
				
			||||||
 | 
					    ...TaskFields
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					    ${TaskFieldsFragmentDoc}`;
 | 
				
			||||||
 | 
					export type SetTaskCompleteMutationFn = ApolloReactCommon.MutationFunction<SetTaskCompleteMutation, SetTaskCompleteMutationVariables>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * __useSetTaskCompleteMutation__
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * To run a mutation, you first call `useSetTaskCompleteMutation` within a React component and pass it any options that fit your needs.
 | 
				
			||||||
 | 
					 * When your component renders, `useSetTaskCompleteMutation` 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 [setTaskCompleteMutation, { data, loading, error }] = useSetTaskCompleteMutation({
 | 
				
			||||||
 | 
					 *   variables: {
 | 
				
			||||||
 | 
					 *      taskID: // value for 'taskID'
 | 
				
			||||||
 | 
					 *      complete: // value for 'complete'
 | 
				
			||||||
 | 
					 *   },
 | 
				
			||||||
 | 
					 * });
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export function useSetTaskCompleteMutation(baseOptions?: ApolloReactHooks.MutationHookOptions<SetTaskCompleteMutation, SetTaskCompleteMutationVariables>) {
 | 
				
			||||||
 | 
					        return ApolloReactHooks.useMutation<SetTaskCompleteMutation, SetTaskCompleteMutationVariables>(SetTaskCompleteDocument, baseOptions);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					export type SetTaskCompleteMutationHookResult = ReturnType<typeof useSetTaskCompleteMutation>;
 | 
				
			||||||
 | 
					export type SetTaskCompleteMutationResult = ApolloReactCommon.MutationResult<SetTaskCompleteMutation>;
 | 
				
			||||||
 | 
					export type SetTaskCompleteMutationOptions = ApolloReactCommon.BaseMutationOptions<SetTaskCompleteMutation, SetTaskCompleteMutationVariables>;
 | 
				
			||||||
 | 
					export const UpdateTaskChecklistItemNameDocument = gql`
 | 
				
			||||||
 | 
					    mutation updateTaskChecklistItemName($taskChecklistItemID: UUID!, $name: String!) {
 | 
				
			||||||
 | 
					  updateTaskChecklistItemName(input: {taskChecklistItemID: $taskChecklistItemID, name: $name}) {
 | 
				
			||||||
 | 
					    id
 | 
				
			||||||
 | 
					    name
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					    `;
 | 
				
			||||||
 | 
					export type UpdateTaskChecklistItemNameMutationFn = ApolloReactCommon.MutationFunction<UpdateTaskChecklistItemNameMutation, UpdateTaskChecklistItemNameMutationVariables>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * __useUpdateTaskChecklistItemNameMutation__
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * To run a mutation, you first call `useUpdateTaskChecklistItemNameMutation` within a React component and pass it any options that fit your needs.
 | 
				
			||||||
 | 
					 * When your component renders, `useUpdateTaskChecklistItemNameMutation` 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 [updateTaskChecklistItemNameMutation, { data, loading, error }] = useUpdateTaskChecklistItemNameMutation({
 | 
				
			||||||
 | 
					 *   variables: {
 | 
				
			||||||
 | 
					 *      taskChecklistItemID: // value for 'taskChecklistItemID'
 | 
				
			||||||
 | 
					 *      name: // value for 'name'
 | 
				
			||||||
 | 
					 *   },
 | 
				
			||||||
 | 
					 * });
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export function useUpdateTaskChecklistItemNameMutation(baseOptions?: ApolloReactHooks.MutationHookOptions<UpdateTaskChecklistItemNameMutation, UpdateTaskChecklistItemNameMutationVariables>) {
 | 
				
			||||||
 | 
					        return ApolloReactHooks.useMutation<UpdateTaskChecklistItemNameMutation, UpdateTaskChecklistItemNameMutationVariables>(UpdateTaskChecklistItemNameDocument, baseOptions);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					export type UpdateTaskChecklistItemNameMutationHookResult = ReturnType<typeof useUpdateTaskChecklistItemNameMutation>;
 | 
				
			||||||
 | 
					export type UpdateTaskChecklistItemNameMutationResult = ApolloReactCommon.MutationResult<UpdateTaskChecklistItemNameMutation>;
 | 
				
			||||||
 | 
					export type UpdateTaskChecklistItemNameMutationOptions = ApolloReactCommon.BaseMutationOptions<UpdateTaskChecklistItemNameMutation, UpdateTaskChecklistItemNameMutationVariables>;
 | 
				
			||||||
 | 
					export const UpdateTaskGroupNameDocument = gql`
 | 
				
			||||||
 | 
					    mutation updateTaskGroupName($taskGroupID: UUID!, $name: String!) {
 | 
				
			||||||
 | 
					  updateTaskGroupName(input: {taskGroupID: $taskGroupID, name: $name}) {
 | 
				
			||||||
 | 
					    id
 | 
				
			||||||
 | 
					    name
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					    `;
 | 
				
			||||||
 | 
					export type UpdateTaskGroupNameMutationFn = ApolloReactCommon.MutationFunction<UpdateTaskGroupNameMutation, UpdateTaskGroupNameMutationVariables>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * __useUpdateTaskGroupNameMutation__
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * To run a mutation, you first call `useUpdateTaskGroupNameMutation` within a React component and pass it any options that fit your needs.
 | 
				
			||||||
 | 
					 * When your component renders, `useUpdateTaskGroupNameMutation` 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 [updateTaskGroupNameMutation, { data, loading, error }] = useUpdateTaskGroupNameMutation({
 | 
				
			||||||
 | 
					 *   variables: {
 | 
				
			||||||
 | 
					 *      taskGroupID: // value for 'taskGroupID'
 | 
				
			||||||
 | 
					 *      name: // value for 'name'
 | 
				
			||||||
 | 
					 *   },
 | 
				
			||||||
 | 
					 * });
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export function useUpdateTaskGroupNameMutation(baseOptions?: ApolloReactHooks.MutationHookOptions<UpdateTaskGroupNameMutation, UpdateTaskGroupNameMutationVariables>) {
 | 
				
			||||||
 | 
					        return ApolloReactHooks.useMutation<UpdateTaskGroupNameMutation, UpdateTaskGroupNameMutationVariables>(UpdateTaskGroupNameDocument, baseOptions);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					export type UpdateTaskGroupNameMutationHookResult = ReturnType<typeof useUpdateTaskGroupNameMutation>;
 | 
				
			||||||
 | 
					export type UpdateTaskGroupNameMutationResult = ApolloReactCommon.MutationResult<UpdateTaskGroupNameMutation>;
 | 
				
			||||||
 | 
					export type UpdateTaskGroupNameMutationOptions = ApolloReactCommon.BaseMutationOptions<UpdateTaskGroupNameMutation, UpdateTaskGroupNameMutationVariables>;
 | 
				
			||||||
export const ToggleTaskLabelDocument = gql`
 | 
					export const ToggleTaskLabelDocument = gql`
 | 
				
			||||||
    mutation toggleTaskLabel($taskID: UUID!, $projectLabelID: UUID!) {
 | 
					    mutation toggleTaskLabel($taskID: UUID!, $projectLabelID: UUID!) {
 | 
				
			||||||
  toggleTaskLabel(input: {taskID: $taskID, projectLabelID: $projectLabelID}) {
 | 
					  toggleTaskLabel(input: {taskID: $taskID, projectLabelID: $projectLabelID}) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,6 +4,7 @@ mutation createTask($taskGroupID: String!, $name: String!, $position: Float!) {
 | 
				
			|||||||
    name
 | 
					    name
 | 
				
			||||||
    position
 | 
					    position
 | 
				
			||||||
    description
 | 
					    description
 | 
				
			||||||
 | 
					    dueDate
 | 
				
			||||||
    taskGroup {
 | 
					    taskGroup {
 | 
				
			||||||
      id
 | 
					      id
 | 
				
			||||||
      name
 | 
					      name
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,72 +0,0 @@
 | 
				
			|||||||
query findProject($projectId: String!) {
 | 
					 | 
				
			||||||
  findProject(input: { projectId: $projectId }) {
 | 
					 | 
				
			||||||
    name
 | 
					 | 
				
			||||||
    members {
 | 
					 | 
				
			||||||
      id
 | 
					 | 
				
			||||||
      fullName
 | 
					 | 
				
			||||||
      profileIcon {
 | 
					 | 
				
			||||||
        url
 | 
					 | 
				
			||||||
        initials
 | 
					 | 
				
			||||||
        bgColor
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    labels {
 | 
					 | 
				
			||||||
      id
 | 
					 | 
				
			||||||
      createdDate
 | 
					 | 
				
			||||||
      name
 | 
					 | 
				
			||||||
      labelColor {
 | 
					 | 
				
			||||||
        id
 | 
					 | 
				
			||||||
        name
 | 
					 | 
				
			||||||
        colorHex
 | 
					 | 
				
			||||||
        position
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    taskGroups {
 | 
					 | 
				
			||||||
      id
 | 
					 | 
				
			||||||
      name
 | 
					 | 
				
			||||||
      position
 | 
					 | 
				
			||||||
      tasks {
 | 
					 | 
				
			||||||
        id
 | 
					 | 
				
			||||||
        name
 | 
					 | 
				
			||||||
        position
 | 
					 | 
				
			||||||
        description
 | 
					 | 
				
			||||||
        dueDate
 | 
					 | 
				
			||||||
        taskGroup {
 | 
					 | 
				
			||||||
          id
 | 
					 | 
				
			||||||
          name
 | 
					 | 
				
			||||||
          position
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        labels {
 | 
					 | 
				
			||||||
          id
 | 
					 | 
				
			||||||
          assignedDate
 | 
					 | 
				
			||||||
          projectLabel {
 | 
					 | 
				
			||||||
            id
 | 
					 | 
				
			||||||
            name
 | 
					 | 
				
			||||||
            createdDate
 | 
					 | 
				
			||||||
            labelColor {
 | 
					 | 
				
			||||||
              id
 | 
					 | 
				
			||||||
              colorHex
 | 
					 | 
				
			||||||
              position
 | 
					 | 
				
			||||||
              name
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        assigned {
 | 
					 | 
				
			||||||
          id
 | 
					 | 
				
			||||||
          fullName
 | 
					 | 
				
			||||||
          profileIcon {
 | 
					 | 
				
			||||||
            url
 | 
					 | 
				
			||||||
            initials
 | 
					 | 
				
			||||||
            bgColor
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  labelColors {
 | 
					 | 
				
			||||||
    id
 | 
					 | 
				
			||||||
    position
 | 
					 | 
				
			||||||
    colorHex
 | 
					 | 
				
			||||||
    name
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										45
									
								
								web/src/shared/graphql/findProject.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								web/src/shared/graphql/findProject.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
				
			|||||||
 | 
					import gql from 'graphql-tag';
 | 
				
			||||||
 | 
					import TASK_FRAGMENT from './fragments/task';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const FIND_PROJECT_QUERY = gql`
 | 
				
			||||||
 | 
					query findProject($projectId: String!) {
 | 
				
			||||||
 | 
					  findProject(input: { projectId: $projectId }) {
 | 
				
			||||||
 | 
					    name
 | 
				
			||||||
 | 
					    members {
 | 
				
			||||||
 | 
					      id
 | 
				
			||||||
 | 
					      fullName
 | 
				
			||||||
 | 
					      profileIcon {
 | 
				
			||||||
 | 
					        url
 | 
				
			||||||
 | 
					        initials
 | 
				
			||||||
 | 
					        bgColor
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    labels {
 | 
				
			||||||
 | 
					      id
 | 
				
			||||||
 | 
					      createdDate
 | 
				
			||||||
 | 
					      name
 | 
				
			||||||
 | 
					      labelColor {
 | 
				
			||||||
 | 
					        id
 | 
				
			||||||
 | 
					        name
 | 
				
			||||||
 | 
					        colorHex
 | 
				
			||||||
 | 
					        position
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    taskGroups {
 | 
				
			||||||
 | 
					      id
 | 
				
			||||||
 | 
					      name
 | 
				
			||||||
 | 
					      position
 | 
				
			||||||
 | 
					      tasks {
 | 
				
			||||||
 | 
					        ...TaskFields
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  labelColors {
 | 
				
			||||||
 | 
					    id
 | 
				
			||||||
 | 
					    position
 | 
				
			||||||
 | 
					    colorHex
 | 
				
			||||||
 | 
					    name
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  ${TASK_FRAGMENT}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
@@ -8,6 +8,18 @@ query findTask($taskID: UUID!) {
 | 
				
			|||||||
    taskGroup {
 | 
					    taskGroup {
 | 
				
			||||||
      id
 | 
					      id
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    checklists {
 | 
				
			||||||
 | 
					      id
 | 
				
			||||||
 | 
					      name
 | 
				
			||||||
 | 
					      position
 | 
				
			||||||
 | 
					      items {
 | 
				
			||||||
 | 
					        id
 | 
				
			||||||
 | 
					        name
 | 
				
			||||||
 | 
					        taskChecklistID
 | 
				
			||||||
 | 
					        complete
 | 
				
			||||||
 | 
					        position
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    labels {
 | 
					    labels {
 | 
				
			||||||
      id
 | 
					      id
 | 
				
			||||||
      assignedDate
 | 
					      assignedDate
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										41
									
								
								web/src/shared/graphql/fragments/task.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								web/src/shared/graphql/fragments/task.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
				
			|||||||
 | 
					import gql from 'graphql-tag';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const TASK_FRAGMENT = gql`
 | 
				
			||||||
 | 
					  fragment TaskFields on Task {
 | 
				
			||||||
 | 
					    id
 | 
				
			||||||
 | 
					    name
 | 
				
			||||||
 | 
					    description
 | 
				
			||||||
 | 
					    dueDate
 | 
				
			||||||
 | 
					    complete
 | 
				
			||||||
 | 
					    position
 | 
				
			||||||
 | 
					    taskGroup {
 | 
				
			||||||
 | 
					      id
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    labels {
 | 
				
			||||||
 | 
					      id
 | 
				
			||||||
 | 
					      assignedDate
 | 
				
			||||||
 | 
					      projectLabel {
 | 
				
			||||||
 | 
					        id
 | 
				
			||||||
 | 
					        name
 | 
				
			||||||
 | 
					        createdDate
 | 
				
			||||||
 | 
					        labelColor {
 | 
				
			||||||
 | 
					          id
 | 
				
			||||||
 | 
					          colorHex
 | 
				
			||||||
 | 
					          position
 | 
				
			||||||
 | 
					          name
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    assigned {
 | 
				
			||||||
 | 
					      id
 | 
				
			||||||
 | 
					      fullName
 | 
				
			||||||
 | 
					      profileIcon {
 | 
				
			||||||
 | 
					        url
 | 
				
			||||||
 | 
					        initials
 | 
				
			||||||
 | 
					        bgColor
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default TASK_FRAGMENT;
 | 
				
			||||||
							
								
								
									
										13
									
								
								web/src/shared/graphql/task/createTaskChecklistItem.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								web/src/shared/graphql/task/createTaskChecklistItem.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					import gql from 'graphql-tag';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const CREATE_TASK_CHECKLIST_ITEM = gql`
 | 
				
			||||||
 | 
					  mutation createTaskChecklistItem($taskChecklistID: UUID!, $name: String!, $position: Float!) {
 | 
				
			||||||
 | 
					    createTaskChecklistItem(input: { taskChecklistID: $taskChecklistID, name: $name, position: $position }) {
 | 
				
			||||||
 | 
					      id
 | 
				
			||||||
 | 
					      name
 | 
				
			||||||
 | 
					      taskChecklistID
 | 
				
			||||||
 | 
					      position
 | 
				
			||||||
 | 
					      complete
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
							
								
								
									
										13
									
								
								web/src/shared/graphql/task/deleteTaskChecklistItem.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								web/src/shared/graphql/task/deleteTaskChecklistItem.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					import gql from 'graphql-tag';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const DELETE_TASK_CHECKLIST_ITEM = gql`
 | 
				
			||||||
 | 
					  mutation deleteTaskChecklistItem($taskChecklistItemID: UUID!) {
 | 
				
			||||||
 | 
					    deleteTaskChecklistItem(input: { taskChecklistItemID: $taskChecklistItemID }) {
 | 
				
			||||||
 | 
					      ok
 | 
				
			||||||
 | 
					      taskChecklistItem {
 | 
				
			||||||
 | 
					        id
 | 
				
			||||||
 | 
					        taskChecklistID
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
							
								
								
									
										13
									
								
								web/src/shared/graphql/task/setTaskChecklistItemComplete.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								web/src/shared/graphql/task/setTaskChecklistItemComplete.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					import gql from 'graphql-tag';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const SET_TASK_CHECKLIST_ITEM_COMPLETE = gql`
 | 
				
			||||||
 | 
					  mutation setTaskChecklistItemComplete($taskChecklistItemID: UUID!, $complete: Boolean!) {
 | 
				
			||||||
 | 
					    setTaskChecklistItemComplete(input: { taskChecklistItemID: $taskChecklistItemID, complete: $complete }) {
 | 
				
			||||||
 | 
					      id
 | 
				
			||||||
 | 
					      name
 | 
				
			||||||
 | 
					      taskChecklistID
 | 
				
			||||||
 | 
					      complete
 | 
				
			||||||
 | 
					      position
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
							
								
								
									
										11
									
								
								web/src/shared/graphql/task/setTaskComplete.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								web/src/shared/graphql/task/setTaskComplete.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					import gql from 'graphql-tag';
 | 
				
			||||||
 | 
					import TASK_FRAGMENT from '../fragments/task';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const UPDATE_TASK_GROUP_NAME_MUTATION = gql`
 | 
				
			||||||
 | 
					mutation setTaskComplete($taskID: UUID!, $complete: Boolean!) {
 | 
				
			||||||
 | 
					  setTaskComplete(input: { taskID: $taskID, complete: $complete }) {
 | 
				
			||||||
 | 
					    ...TaskFields
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  ${TASK_FRAGMENT}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
							
								
								
									
										10
									
								
								web/src/shared/graphql/task/updateTaskChecklistItemName.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								web/src/shared/graphql/task/updateTaskChecklistItemName.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					import gql from 'graphql-tag';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const UPDATE_TASK_CHECKLIST_ITEM_NAME = gql`
 | 
				
			||||||
 | 
					  mutation updateTaskChecklistItemName($taskChecklistItemID: UUID!, $name: String!) {
 | 
				
			||||||
 | 
					    updateTaskChecklistItemName(input: { taskChecklistItemID: $taskChecklistItemID, name: $name }) {
 | 
				
			||||||
 | 
					      id
 | 
				
			||||||
 | 
					      name
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
							
								
								
									
										12
									
								
								web/src/shared/graphql/taskGroup/updateTaskGroupName.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								web/src/shared/graphql/taskGroup/updateTaskGroupName.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					import gql from 'graphql-tag';
 | 
				
			||||||
 | 
					import TASK_FRAGMENT from '../fragments/task';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const UPDATE_TASK_GROUP_NAME_MUTATION = gql`
 | 
				
			||||||
 | 
					mutation updateTaskGroupName($taskGroupID: UUID!, $name: String!) {
 | 
				
			||||||
 | 
					  updateTaskGroupName(input:{taskGroupID:$taskGroupID, name:$name}) {
 | 
				
			||||||
 | 
					    id
 | 
				
			||||||
 | 
					    name
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  ${TASK_FRAGMENT}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
							
								
								
									
										12
									
								
								web/src/shared/icons/AccountPlus.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								web/src/shared/icons/AccountPlus.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					import React from 'react';
 | 
				
			||||||
 | 
					import Icon, { IconProps } from './Icon';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const AccountPlus: React.FC<IconProps> = ({ width = '16px', height = '16px', className }) => {
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <Icon width={width} height={height} className={className} viewBox="0 0 640 512">
 | 
				
			||||||
 | 
					      <path d="M224 256c70.7 0 128-57.3 128-128S294.7 0 224 0 96 57.3 96 128s57.3 128 128 128zm89.6 32h-16.7c-22.2 10.2-46.9 16-72.9 16s-50.6-5.8-72.9-16h-16.7C60.2 288 0 348.2 0 422.4V464c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48v-41.6c0-74.2-60.2-134.4-134.4-134.4zm323-128.4l-27.8-28.1c-4.6-4.7-12.1-4.7-16.8-.1l-104.8 104-45.5-45.8c-4.6-4.7-12.1-4.7-16.8-.1l-28.1 27.9c-4.7 4.6-4.7 12.1-.1 16.8l81.7 82.3c4.6 4.7 12.1 4.7 16.8.1l141.3-140.2c4.6-4.7 4.7-12.2.1-16.8z" />
 | 
				
			||||||
 | 
					    </Icon>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default AccountPlus;
 | 
				
			||||||
							
								
								
									
										12
									
								
								web/src/shared/icons/CheckCircle.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								web/src/shared/icons/CheckCircle.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					import React from 'react';
 | 
				
			||||||
 | 
					import Icon, { IconProps } from './Icon';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const CheckCircle: React.FC<IconProps> = ({ width = '16px', height = '16px', className }) => {
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <Icon width={width} height={height} className={className} viewBox="0 0 512 512">
 | 
				
			||||||
 | 
					      <path d="M504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zM227.314 387.314l184-184c6.248-6.248 6.248-16.379 0-22.627l-22.627-22.627c-6.248-6.249-16.379-6.249-22.628 0L216 308.118l-70.059-70.059c-6.248-6.248-16.379-6.248-22.628 0l-22.627 22.627c-6.248 6.248-6.248 16.379 0 22.627l104 104c6.249 6.249 16.379 6.249 22.628.001z" />
 | 
				
			||||||
 | 
					    </Icon>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default CheckCircle;
 | 
				
			||||||
							
								
								
									
										12
									
								
								web/src/shared/icons/CheckSquare.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								web/src/shared/icons/CheckSquare.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					import React from 'react';
 | 
				
			||||||
 | 
					import Icon, { IconProps } from './Icon';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const CheckSquare: React.FC<IconProps> = ({ width = '16px', height = '16px', onClick, className }) => {
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <Icon width={width} onClick={onClick} height={height} className={className} viewBox="0 0 448 512">
 | 
				
			||||||
 | 
					      <path d="M400 480H48c-26.51 0-48-21.49-48-48V80c0-26.51 21.49-48 48-48h352c26.51 0 48 21.49 48 48v352c0 26.51-21.49 48-48 48zm-204.686-98.059l184-184c6.248-6.248 6.248-16.379 0-22.627l-22.627-22.627c-6.248-6.248-16.379-6.249-22.628 0L184 302.745l-70.059-70.059c-6.248-6.248-16.379-6.248-22.628 0l-22.627 22.627c-6.248 6.248-6.248 16.379 0 22.627l104 104c6.249 6.25 16.379 6.25 22.628.001z" />
 | 
				
			||||||
 | 
					    </Icon>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default CheckSquare;
 | 
				
			||||||
							
								
								
									
										12
									
								
								web/src/shared/icons/CheckSquareOutline.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								web/src/shared/icons/CheckSquareOutline.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					import React from 'react';
 | 
				
			||||||
 | 
					import Icon, { IconProps } from './Icon';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const CheckSquareOutline: React.FC<IconProps> = ({ width = '16px', height = '16px', className }) => {
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <Icon width={width} height={height} className={className} viewBox="0 0 448 512">
 | 
				
			||||||
 | 
					      <path d="M400 32H48C21.49 32 0 53.49 0 80v352c0 26.51 21.49 48 48 48h352c26.51 0 48-21.49 48-48V80c0-26.51-21.49-48-48-48zm0 400H48V80h352v352zm-35.864-241.724L191.547 361.48c-4.705 4.667-12.303 4.637-16.97-.068l-90.781-91.516c-4.667-4.705-4.637-12.303.069-16.971l22.719-22.536c4.705-4.667 12.303-4.637 16.97.069l59.792 60.277 141.352-140.216c4.705-4.667 12.303-4.637 16.97.068l22.536 22.718c4.667 4.706 4.637 12.304-.068 16.971z" />
 | 
				
			||||||
 | 
					    </Icon>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default CheckSquareOutline;
 | 
				
			||||||
@@ -1,21 +1,12 @@
 | 
				
			|||||||
import React from 'react';
 | 
					import React from 'react';
 | 
				
			||||||
 | 
					import Icon, { IconProps } from './Icon';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Props = {
 | 
					const Checkmark: React.FC<IconProps> = ({ width = '16px', height = '16px', className }) => {
 | 
				
			||||||
  size: number | string;
 | 
					 | 
				
			||||||
  color: string;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const Checkmark = ({ size, color }: Props) => {
 | 
					 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <svg fill={color} xmlns="http://www.w3.org/2000/svg" width={size} height={size} viewBox="0 0 16 16">
 | 
					    <Icon width={width} height={height} className={className} viewBox="0 0 16 16">
 | 
				
			||||||
      <path d="M13.5 2l-7.5 7.5-3.5-3.5-2.5 2.5 6 6 10-10z" />
 | 
					      <path d="M13.5 2l-7.5 7.5-3.5-3.5-2.5 2.5 6 6 10-10z" />
 | 
				
			||||||
    </svg>
 | 
					    </Icon>
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Checkmark.defaultProps = {
 | 
					 | 
				
			||||||
  size: 16,
 | 
					 | 
				
			||||||
  color: '#000',
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export default Checkmark;
 | 
					export default Checkmark;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										12
									
								
								web/src/shared/icons/Clock.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								web/src/shared/icons/Clock.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					import React from 'react';
 | 
				
			||||||
 | 
					import Icon, { IconProps } from './Icon';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const Clock: React.FC<IconProps> = ({ width = '16px', height = '16px', className }) => {
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <Icon width={width} height={height} className={className} viewBox="0 0 512 512">
 | 
				
			||||||
 | 
					      <path d="M256,8C119,8,8,119,8,256S119,504,256,504,504,393,504,256,393,8,256,8Zm92.49,313h0l-20,25a16,16,0,0,1-22.49,2.5h0l-67-49.72a40,40,0,0,1-15-31.23V112a16,16,0,0,1,16-16h32a16,16,0,0,1,16,16V256l58,42.5A16,16,0,0,1,348.49,321Z" />
 | 
				
			||||||
 | 
					    </Icon>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Clock;
 | 
				
			||||||
@@ -1,21 +1,12 @@
 | 
				
			|||||||
import React from 'react';
 | 
					import React from 'react';
 | 
				
			||||||
 | 
					import Icon, { IconProps } from './Icon';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Props = {
 | 
					const Cross: React.FC<IconProps> = ({ width = '16px', height = '16px', className, onClick }) => {
 | 
				
			||||||
  size: number | string;
 | 
					 | 
				
			||||||
  color: string;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const Cross = ({ size, color }: Props) => {
 | 
					 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <svg fill={color} width={size} height={size} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 352 512">
 | 
					    <Icon width={width} height={height} onClick={onClick} className={className} viewBox="0 0 352 512">
 | 
				
			||||||
      <path d="M242.72 256l100.07-100.07c12.28-12.28 12.28-32.19 0-44.48l-22.24-22.24c-12.28-12.28-32.19-12.28-44.48 0L176 189.28 75.93 89.21c-12.28-12.28-32.19-12.28-44.48 0L9.21 111.45c-12.28 12.28-12.28 32.19 0 44.48L109.28 256 9.21 356.07c-12.28 12.28-12.28 32.19 0 44.48l22.24 22.24c12.28 12.28 32.2 12.28 44.48 0L176 322.72l100.07 100.07c12.28 12.28 32.2 12.28 44.48 0l22.24-22.24c12.28-12.28 12.28-32.19 0-44.48L242.72 256z" />
 | 
					      <path d="M242.72 256l100.07-100.07c12.28-12.28 12.28-32.19 0-44.48l-22.24-22.24c-12.28-12.28-32.19-12.28-44.48 0L176 189.28 75.93 89.21c-12.28-12.28-32.19-12.28-44.48 0L9.21 111.45c-12.28 12.28-12.28 32.19 0 44.48L109.28 256 9.21 356.07c-12.28 12.28-12.28 32.19 0 44.48l22.24 22.24c12.28 12.28 32.2 12.28 44.48 0L176 322.72l100.07 100.07c12.28 12.28 32.2 12.28 44.48 0l22.24-22.24c12.28-12.28 12.28-32.19 0-44.48L242.72 256z" />
 | 
				
			||||||
    </svg>
 | 
					    </Icon>
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Cross.defaultProps = {
 | 
					 | 
				
			||||||
  size: 16,
 | 
					 | 
				
			||||||
  color: '#000',
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export default Cross;
 | 
					export default Cross;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,6 +4,8 @@ import styled from 'styled-components/macro';
 | 
				
			|||||||
export type IconProps = {
 | 
					export type IconProps = {
 | 
				
			||||||
  width: number | string;
 | 
					  width: number | string;
 | 
				
			||||||
  height: number | string;
 | 
					  height: number | string;
 | 
				
			||||||
 | 
					  className?: string;
 | 
				
			||||||
 | 
					  onClick?: () => void;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Props = {
 | 
					type Props = {
 | 
				
			||||||
@@ -11,15 +13,27 @@ type Props = {
 | 
				
			|||||||
  height: number | string;
 | 
					  height: number | string;
 | 
				
			||||||
  viewBox: string;
 | 
					  viewBox: string;
 | 
				
			||||||
  className?: string;
 | 
					  className?: string;
 | 
				
			||||||
 | 
					  onClick?: () => void;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const Svg = styled.svg`
 | 
					const Svg = styled.svg`
 | 
				
			||||||
  fill: rgba(${props => props.theme.colors.text.primary});
 | 
					  fill: rgba(${props => props.theme.colors.text.primary});
 | 
				
			||||||
`;
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const Icon: React.FC<Props> = ({ width, height, viewBox, className, children }) => {
 | 
					const Icon: React.FC<Props> = ({ width, height, viewBox, className, onClick, children }) => {
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <Svg className={className} width={width} height={height} xmlns="http://www.w3.org/2000/svg" viewBox={viewBox}>
 | 
					    <Svg
 | 
				
			||||||
 | 
					      onClick={e => {
 | 
				
			||||||
 | 
					        if (onClick) {
 | 
				
			||||||
 | 
					          onClick();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }}
 | 
				
			||||||
 | 
					      className={className}
 | 
				
			||||||
 | 
					      width={width}
 | 
				
			||||||
 | 
					      height={height}
 | 
				
			||||||
 | 
					      xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
					      viewBox={viewBox}
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
      {children}
 | 
					      {children}
 | 
				
			||||||
    </Svg>
 | 
					    </Svg>
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										12
									
								
								web/src/shared/icons/Square.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								web/src/shared/icons/Square.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					import React from 'react';
 | 
				
			||||||
 | 
					import Icon, { IconProps } from './Icon';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const Square: React.FC<IconProps> = ({ width = '16px', height = '16px', className, onClick }) => {
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <Icon onClick={onClick} width={width} height={height} className={className} viewBox="0 0 448 512">
 | 
				
			||||||
 | 
					      <path d="M400 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zm-6 400H54c-3.3 0-6-2.7-6-6V86c0-3.3 2.7-6 6-6h340c3.3 0 6 2.7 6 6v340c0 3.3-2.7 6-6 6z" />
 | 
				
			||||||
 | 
					    </Icon>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Square;
 | 
				
			||||||
							
								
								
									
										12
									
								
								web/src/shared/icons/Trash.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								web/src/shared/icons/Trash.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					import React from 'react';
 | 
				
			||||||
 | 
					import Icon, { IconProps } from './Icon';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const Trash: React.FC<IconProps> = ({ width = '16px', height = '16px', className }) => {
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <Icon width={width} height={height} className={className} viewBox="0 0 448 512">
 | 
				
			||||||
 | 
					      <path d="M432 32H312l-9.4-18.7A24 24 0 0 0 281.1 0H166.8a23.72 23.72 0 0 0-21.4 13.3L136 32H16A16 16 0 0 0 0 48v32a16 16 0 0 0 16 16h416a16 16 0 0 0 16-16V48a16 16 0 0 0-16-16zM53.2 467a48 48 0 0 0 47.9 45h245.8a48 48 0 0 0 47.9-45L416 128H32z" />
 | 
				
			||||||
 | 
					    </Icon>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Trash;
 | 
				
			||||||
@@ -1,6 +1,13 @@
 | 
				
			|||||||
import Cross from './Cross';
 | 
					import Cross from './Cross';
 | 
				
			||||||
import Cog from './Cog';
 | 
					import Cog from './Cog';
 | 
				
			||||||
 | 
					import Trash from './Trash';
 | 
				
			||||||
 | 
					import CheckCircle from './CheckCircle';
 | 
				
			||||||
 | 
					import Clock from './Clock';
 | 
				
			||||||
 | 
					import AccountPlus from './AccountPlus';
 | 
				
			||||||
 | 
					import CheckSquare from './CheckSquare';
 | 
				
			||||||
import ArrowLeft from './ArrowLeft';
 | 
					import ArrowLeft from './ArrowLeft';
 | 
				
			||||||
 | 
					import CheckSquareOutline from './CheckSquareOutline';
 | 
				
			||||||
 | 
					import Square from './Square';
 | 
				
			||||||
import Bolt from './Bolt';
 | 
					import Bolt from './Bolt';
 | 
				
			||||||
import Plus from './Plus';
 | 
					import Plus from './Plus';
 | 
				
			||||||
import Bell from './Bell';
 | 
					import Bell from './Bell';
 | 
				
			||||||
@@ -42,8 +49,15 @@ export {
 | 
				
			|||||||
  Citadel,
 | 
					  Citadel,
 | 
				
			||||||
  Checkmark,
 | 
					  Checkmark,
 | 
				
			||||||
  User,
 | 
					  User,
 | 
				
			||||||
 | 
					  Trash,
 | 
				
			||||||
  Users,
 | 
					  Users,
 | 
				
			||||||
  Lock,
 | 
					  Lock,
 | 
				
			||||||
  ArrowLeft,
 | 
					  ArrowLeft,
 | 
				
			||||||
 | 
					  CheckCircle,
 | 
				
			||||||
 | 
					  AccountPlus,
 | 
				
			||||||
 | 
					  Clock,
 | 
				
			||||||
 | 
					  CheckSquareOutline,
 | 
				
			||||||
 | 
					  CheckSquare,
 | 
				
			||||||
 | 
					  Square,
 | 
				
			||||||
  ToggleOn,
 | 
					  ToggleOn,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user