feature: add team creation & project deletion
This commit is contained in:
		
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -36,10 +36,29 @@ type CreateTaskChecklistItem struct {
 | 
				
			|||||||
	Position        float64   `json:"position"`
 | 
						Position        float64   `json:"position"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type CreateTeamMember struct {
 | 
				
			||||||
 | 
						UserID uuid.UUID `json:"userID"`
 | 
				
			||||||
 | 
						TeamID uuid.UUID `json:"teamID"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type CreateTeamMemberPayload struct {
 | 
				
			||||||
 | 
						Team       *pg.Team       `json:"team"`
 | 
				
			||||||
 | 
						TeamMember *ProjectMember `json:"teamMember"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type DeleteProject struct {
 | 
				
			||||||
 | 
						ProjectID uuid.UUID `json:"projectID"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type DeleteProjectLabel struct {
 | 
					type DeleteProjectLabel struct {
 | 
				
			||||||
	ProjectLabelID uuid.UUID `json:"projectLabelID"`
 | 
						ProjectLabelID uuid.UUID `json:"projectLabelID"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type DeleteProjectPayload struct {
 | 
				
			||||||
 | 
						Ok      bool        `json:"ok"`
 | 
				
			||||||
 | 
						Project *pg.Project `json:"project"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type DeleteTaskChecklistItem struct {
 | 
					type DeleteTaskChecklistItem struct {
 | 
				
			||||||
	TaskChecklistItemID uuid.UUID `json:"taskChecklistItemID"`
 | 
						TaskChecklistItemID uuid.UUID `json:"taskChecklistItemID"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -123,8 +142,8 @@ type NewTaskLocation struct {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type NewTeam struct {
 | 
					type NewTeam struct {
 | 
				
			||||||
	Name           string `json:"name"`
 | 
						Name           string    `json:"name"`
 | 
				
			||||||
	OrganizationID string `json:"organizationID"`
 | 
						OrganizationID uuid.UUID `json:"organizationID"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type NewUserAccount struct {
 | 
					type NewUserAccount struct {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -55,6 +55,7 @@ type Team {
 | 
				
			|||||||
  id: ID!
 | 
					  id: ID!
 | 
				
			||||||
  createdAt: Time!
 | 
					  createdAt: Time!
 | 
				
			||||||
  name: String!
 | 
					  name: String!
 | 
				
			||||||
 | 
					  members: [ProjectMember!]!
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Project {
 | 
					type Project {
 | 
				
			||||||
@@ -117,7 +118,13 @@ input FindTask {
 | 
				
			|||||||
  taskID: UUID!
 | 
					  taskID: UUID!
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Organization {
 | 
				
			||||||
 | 
					  id: ID!
 | 
				
			||||||
 | 
					  name: String!
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Query {
 | 
					type Query {
 | 
				
			||||||
 | 
					  organizations: [Organization!]!
 | 
				
			||||||
  users: [UserAccount!]!
 | 
					  users: [UserAccount!]!
 | 
				
			||||||
  findUser(input: FindUser!): UserAccount!
 | 
					  findUser(input: FindUser!): UserAccount!
 | 
				
			||||||
  findProject(input: FindProject!): Project!
 | 
					  findProject(input: FindProject!): Project!
 | 
				
			||||||
@@ -143,7 +150,7 @@ input NewUserAccount {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
input NewTeam {
 | 
					input NewTeam {
 | 
				
			||||||
  name: String!
 | 
					  name: String!
 | 
				
			||||||
  organizationID: String!
 | 
					  organizationID: UUID!
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
input NewProject {
 | 
					input NewProject {
 | 
				
			||||||
@@ -330,6 +337,25 @@ input UpdateTaskChecklistItemName {
 | 
				
			|||||||
  name: String!
 | 
					  name: String!
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					input CreateTeamMember {
 | 
				
			||||||
 | 
					  userID: UUID!
 | 
				
			||||||
 | 
					  teamID: UUID!
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type CreateTeamMemberPayload {
 | 
				
			||||||
 | 
					  team: Team!
 | 
				
			||||||
 | 
					  teamMember: ProjectMember!
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					input DeleteProject {
 | 
				
			||||||
 | 
					  projectID: UUID!
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type DeleteProjectPayload {
 | 
				
			||||||
 | 
					  ok: Boolean!
 | 
				
			||||||
 | 
					  project: Project!
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Mutation {
 | 
					type Mutation {
 | 
				
			||||||
  createRefreshToken(input: NewRefreshToken!): RefreshToken!
 | 
					  createRefreshToken(input: NewRefreshToken!): RefreshToken!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -338,7 +364,10 @@ type Mutation {
 | 
				
			|||||||
  createTeam(input: NewTeam!): Team!
 | 
					  createTeam(input: NewTeam!): Team!
 | 
				
			||||||
  clearProfileAvatar:  UserAccount!
 | 
					  clearProfileAvatar:  UserAccount!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  createTeamMember(input: CreateTeamMember!): CreateTeamMemberPayload!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  createProject(input: NewProject!): Project!
 | 
					  createProject(input: NewProject!): Project!
 | 
				
			||||||
 | 
					  deleteProject(input: DeleteProject!): DeleteProjectPayload!
 | 
				
			||||||
  updateProjectName(input: UpdateProjectName): Project!
 | 
					  updateProjectName(input: UpdateProjectName): Project!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  createProjectLabel(input: NewProjectLabel!): ProjectLabel!
 | 
					  createProjectLabel(input: NewProjectLabel!): ProjectLabel!
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -41,12 +41,8 @@ func (r *mutationResolver) CreateUserAccount(ctx context.Context, input NewUserA
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (r *mutationResolver) CreateTeam(ctx context.Context, input NewTeam) (*pg.Team, error) {
 | 
					func (r *mutationResolver) CreateTeam(ctx context.Context, input NewTeam) (*pg.Team, error) {
 | 
				
			||||||
	organizationID, err := uuid.Parse(input.OrganizationID)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return &pg.Team{}, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	createdAt := time.Now().UTC()
 | 
						createdAt := time.Now().UTC()
 | 
				
			||||||
	team, err := r.Repository.CreateTeam(ctx, pg.CreateTeamParams{organizationID, createdAt, input.Name})
 | 
						team, err := r.Repository.CreateTeam(ctx, pg.CreateTeamParams{input.OrganizationID, createdAt, input.Name})
 | 
				
			||||||
	return &team, err
 | 
						return &team, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -65,12 +61,49 @@ func (r *mutationResolver) ClearProfileAvatar(ctx context.Context) (*pg.UserAcco
 | 
				
			|||||||
	return &user, nil
 | 
						return &user, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (r *mutationResolver) CreateTeamMember(ctx context.Context, input CreateTeamMember) (*CreateTeamMemberPayload, error) {
 | 
				
			||||||
 | 
						addedDate := time.Now().UTC()
 | 
				
			||||||
 | 
						team, err := r.Repository.GetTeamByID(ctx, input.TeamID)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return &CreateTeamMemberPayload{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						_, err = r.Repository.CreateTeamMember(ctx, pg.CreateTeamMemberParams{TeamID: input.TeamID, UserID: input.UserID, Addeddate: addedDate})
 | 
				
			||||||
 | 
						user, err := r.Repository.GetUserAccountByID(ctx, input.UserID)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return &CreateTeamMemberPayload{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var url *string
 | 
				
			||||||
 | 
						if user.ProfileAvatarUrl.Valid {
 | 
				
			||||||
 | 
							url = &user.ProfileAvatarUrl.String
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						profileIcon := &ProfileIcon{url, &user.Initials, &user.ProfileBgColor}
 | 
				
			||||||
 | 
						return &CreateTeamMemberPayload{
 | 
				
			||||||
 | 
							Team: &team,
 | 
				
			||||||
 | 
							TeamMember: &ProjectMember{
 | 
				
			||||||
 | 
								ID:          user.UserID,
 | 
				
			||||||
 | 
								FullName:    user.FullName,
 | 
				
			||||||
 | 
								ProfileIcon: profileIcon,
 | 
				
			||||||
 | 
							}}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (r *mutationResolver) CreateProject(ctx context.Context, input NewProject) (*pg.Project, error) {
 | 
					func (r *mutationResolver) CreateProject(ctx context.Context, input NewProject) (*pg.Project, error) {
 | 
				
			||||||
	createdAt := time.Now().UTC()
 | 
						createdAt := time.Now().UTC()
 | 
				
			||||||
	project, err := r.Repository.CreateProject(ctx, pg.CreateProjectParams{input.UserID, input.TeamID, createdAt, input.Name})
 | 
						project, err := r.Repository.CreateProject(ctx, pg.CreateProjectParams{input.UserID, input.TeamID, createdAt, input.Name})
 | 
				
			||||||
	return &project, err
 | 
						return &project, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (r *mutationResolver) DeleteProject(ctx context.Context, input DeleteProject) (*DeleteProjectPayload, error) {
 | 
				
			||||||
 | 
						project, err := r.Repository.GetProjectByID(ctx, input.ProjectID)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return &DeleteProjectPayload{Ok: false}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						err = r.Repository.DeleteProjectByID(ctx, input.ProjectID)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return &DeleteProjectPayload{Ok: false}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &DeleteProjectPayload{Project: &project, Ok: true}, err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (r *mutationResolver) UpdateProjectName(ctx context.Context, input *UpdateProjectName) (*pg.Project, error) {
 | 
					func (r *mutationResolver) UpdateProjectName(ctx context.Context, input *UpdateProjectName) (*pg.Project, error) {
 | 
				
			||||||
	project, err := r.Repository.UpdateProjectNameByID(ctx, pg.UpdateProjectNameByIDParams{ProjectID: input.ProjectID, Name: input.Name})
 | 
						project, err := r.Repository.UpdateProjectNameByID(ctx, pg.UpdateProjectNameByIDParams{ProjectID: input.ProjectID, Name: input.Name})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@@ -409,6 +442,10 @@ func (r *mutationResolver) LogoutUser(ctx context.Context, input LogoutUser) (bo
 | 
				
			|||||||
	return true, err
 | 
						return true, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (r *organizationResolver) ID(ctx context.Context, obj *pg.Organization) (uuid.UUID, error) {
 | 
				
			||||||
 | 
						return obj.OrganizationID, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (r *projectResolver) ID(ctx context.Context, obj *pg.Project) (uuid.UUID, error) {
 | 
					func (r *projectResolver) ID(ctx context.Context, obj *pg.Project) (uuid.UUID, error) {
 | 
				
			||||||
	return obj.ProjectID, nil
 | 
						return obj.ProjectID, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -475,6 +512,10 @@ func (r *projectLabelResolver) Name(ctx context.Context, obj *pg.ProjectLabel) (
 | 
				
			|||||||
	return name, nil
 | 
						return name, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (r *queryResolver) Organizations(ctx context.Context) ([]pg.Organization, error) {
 | 
				
			||||||
 | 
						return r.Repository.GetAllOrganizations(ctx)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (r *queryResolver) Users(ctx context.Context) ([]pg.UserAccount, error) {
 | 
					func (r *queryResolver) Users(ctx context.Context) ([]pg.UserAccount, error) {
 | 
				
			||||||
	return r.Repository.GetAllUserAccounts(ctx)
 | 
						return r.Repository.GetAllUserAccounts(ctx)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -683,6 +724,31 @@ func (r *teamResolver) ID(ctx context.Context, obj *pg.Team) (uuid.UUID, error)
 | 
				
			|||||||
	return obj.TeamID, nil
 | 
						return obj.TeamID, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (r *teamResolver) Members(ctx context.Context, obj *pg.Team) ([]ProjectMember, error) {
 | 
				
			||||||
 | 
						teamMembers, err := r.Repository.GetTeamMembersForTeamID(ctx, obj.TeamID)
 | 
				
			||||||
 | 
						var projectMembers []ProjectMember
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return projectMembers, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, teamMember := range teamMembers {
 | 
				
			||||||
 | 
							user, err := r.Repository.GetUserAccountByID(ctx, teamMember.UserID)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return projectMembers, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							var url *string
 | 
				
			||||||
 | 
							if user.ProfileAvatarUrl.Valid {
 | 
				
			||||||
 | 
								url = &user.ProfileAvatarUrl.String
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							profileIcon := &ProfileIcon{url, &user.Initials, &user.ProfileBgColor}
 | 
				
			||||||
 | 
							projectMembers = append(projectMembers, ProjectMember{
 | 
				
			||||||
 | 
								ID:          user.UserID,
 | 
				
			||||||
 | 
								FullName:    user.FullName,
 | 
				
			||||||
 | 
								ProfileIcon: profileIcon,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return projectMembers, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (r *userAccountResolver) ID(ctx context.Context, obj *pg.UserAccount) (uuid.UUID, error) {
 | 
					func (r *userAccountResolver) ID(ctx context.Context, obj *pg.UserAccount) (uuid.UUID, error) {
 | 
				
			||||||
	return obj.UserID, nil
 | 
						return obj.UserID, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -702,6 +768,9 @@ func (r *Resolver) LabelColor() LabelColorResolver { return &labelColorResolver{
 | 
				
			|||||||
// Mutation returns MutationResolver implementation.
 | 
					// Mutation returns MutationResolver implementation.
 | 
				
			||||||
func (r *Resolver) Mutation() MutationResolver { return &mutationResolver{r} }
 | 
					func (r *Resolver) Mutation() MutationResolver { return &mutationResolver{r} }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Organization returns OrganizationResolver implementation.
 | 
				
			||||||
 | 
					func (r *Resolver) Organization() OrganizationResolver { return &organizationResolver{r} }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Project returns ProjectResolver implementation.
 | 
					// Project returns ProjectResolver implementation.
 | 
				
			||||||
func (r *Resolver) Project() ProjectResolver { return &projectResolver{r} }
 | 
					func (r *Resolver) Project() ProjectResolver { return &projectResolver{r} }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -737,6 +806,7 @@ func (r *Resolver) UserAccount() UserAccountResolver { return &userAccountResolv
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
type labelColorResolver struct{ *Resolver }
 | 
					type labelColorResolver struct{ *Resolver }
 | 
				
			||||||
type mutationResolver struct{ *Resolver }
 | 
					type mutationResolver struct{ *Resolver }
 | 
				
			||||||
 | 
					type organizationResolver struct{ *Resolver }
 | 
				
			||||||
type projectResolver struct{ *Resolver }
 | 
					type projectResolver struct{ *Resolver }
 | 
				
			||||||
type projectLabelResolver struct{ *Resolver }
 | 
					type projectLabelResolver struct{ *Resolver }
 | 
				
			||||||
type queryResolver struct{ *Resolver }
 | 
					type queryResolver struct{ *Resolver }
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										8
									
								
								api/migrations/0031_add-team-member-table.up.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								api/migrations/0031_add-team-member-table.up.sql
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					CREATE TABLE team_member (
 | 
				
			||||||
 | 
					  team_member_id uuid PRIMARY KEY DEFAULT uuid_generate_v4(),
 | 
				
			||||||
 | 
					  team_id uuid NOT NULL REFERENCES team(team_id) ON DELETE CASCADE,
 | 
				
			||||||
 | 
					  user_id uuid NOT NULL REFERENCES user_account(user_id) ON DELETE CASCADE,
 | 
				
			||||||
 | 
					  UNIQUE(team_id, user_id),
 | 
				
			||||||
 | 
					  addedDate timestamptz NOT NULL
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					ALTER TABLE project_label DROP CONSTRAINT project_label_project_id_fkey;
 | 
				
			||||||
 | 
					ALTER TABLE project_label
 | 
				
			||||||
 | 
					  ADD CONSTRAINT project_label_project_id_fkey
 | 
				
			||||||
 | 
					  FOREIGN KEY (project_id)
 | 
				
			||||||
 | 
					  REFERENCES project(project_id)
 | 
				
			||||||
 | 
					  ON DELETE CASCADE;
 | 
				
			||||||
@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					ALTER TABLE task_label DROP CONSTRAINT task_label_project_label_id_fkey;
 | 
				
			||||||
 | 
					ALTER TABLE task_label
 | 
				
			||||||
 | 
					  ADD CONSTRAINT task_label_project_label_id_fkey
 | 
				
			||||||
 | 
					  FOREIGN KEY (project_label_id)
 | 
				
			||||||
 | 
					  REFERENCES project_label(project_label_id)
 | 
				
			||||||
 | 
					  ON DELETE CASCADE;
 | 
				
			||||||
@@ -103,6 +103,13 @@ type Team struct {
 | 
				
			|||||||
	OrganizationID uuid.UUID `json:"organization_id"`
 | 
						OrganizationID uuid.UUID `json:"organization_id"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type TeamMember struct {
 | 
				
			||||||
 | 
						TeamMemberID uuid.UUID `json:"team_member_id"`
 | 
				
			||||||
 | 
						TeamID       uuid.UUID `json:"team_id"`
 | 
				
			||||||
 | 
						UserID       uuid.UUID `json:"user_id"`
 | 
				
			||||||
 | 
						Addeddate    time.Time `json:"addeddate"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type UserAccount struct {
 | 
					type UserAccount struct {
 | 
				
			||||||
	UserID           uuid.UUID      `json:"user_id"`
 | 
						UserID           uuid.UUID      `json:"user_id"`
 | 
				
			||||||
	CreatedAt        time.Time      `json:"created_at"`
 | 
						CreatedAt        time.Time      `json:"created_at"`
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,11 +7,17 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Repository interface {
 | 
					type Repository interface {
 | 
				
			||||||
 | 
						CreateTeamMember(ctx context.Context, arg CreateTeamMemberParams) (TeamMember, error)
 | 
				
			||||||
 | 
						DeleteTeamMemberByUserID(ctx context.Context, userID uuid.UUID) error
 | 
				
			||||||
 | 
						GetTeamMembersForTeamID(ctx context.Context, teamID uuid.UUID) ([]TeamMember, error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	CreateTeam(ctx context.Context, arg CreateTeamParams) (Team, error)
 | 
						CreateTeam(ctx context.Context, arg CreateTeamParams) (Team, error)
 | 
				
			||||||
	DeleteTeamByID(ctx context.Context, teamID uuid.UUID) error
 | 
						DeleteTeamByID(ctx context.Context, teamID uuid.UUID) error
 | 
				
			||||||
	GetTeamByID(ctx context.Context, teamID uuid.UUID) (Team, error)
 | 
						GetTeamByID(ctx context.Context, teamID uuid.UUID) (Team, error)
 | 
				
			||||||
	GetAllTeams(ctx context.Context) ([]Team, error)
 | 
						GetAllTeams(ctx context.Context) ([]Team, error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						DeleteProjectByID(ctx context.Context, projectID uuid.UUID) error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	CreateProject(ctx context.Context, arg CreateProjectParams) (Project, error)
 | 
						CreateProject(ctx context.Context, arg CreateProjectParams) (Project, error)
 | 
				
			||||||
	GetAllProjects(ctx context.Context) ([]Project, error)
 | 
						GetAllProjects(ctx context.Context) ([]Project, error)
 | 
				
			||||||
	GetAllProjectsForTeam(ctx context.Context, teamID uuid.UUID) ([]Project, error)
 | 
						GetAllProjectsForTeam(ctx context.Context, teamID uuid.UUID) ([]Project, error)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -39,6 +39,15 @@ func (q *Queries) CreateProject(ctx context.Context, arg CreateProjectParams) (P
 | 
				
			|||||||
	return i, err
 | 
						return i, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const deleteProjectByID = `-- name: DeleteProjectByID :exec
 | 
				
			||||||
 | 
					DELETE FROM project WHERE project_id = $1
 | 
				
			||||||
 | 
					`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (q *Queries) DeleteProjectByID(ctx context.Context, projectID uuid.UUID) error {
 | 
				
			||||||
 | 
						_, err := q.db.ExecContext(ctx, deleteProjectByID, projectID)
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const getAllProjects = `-- name: GetAllProjects :many
 | 
					const getAllProjects = `-- name: GetAllProjects :many
 | 
				
			||||||
SELECT project_id, team_id, created_at, name, owner FROM project
 | 
					SELECT project_id, team_id, created_at, name, owner FROM project
 | 
				
			||||||
`
 | 
					`
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,8 +21,10 @@ type Querier interface {
 | 
				
			|||||||
	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)
 | 
				
			||||||
 | 
						CreateTeamMember(ctx context.Context, arg CreateTeamMemberParams) (TeamMember, error)
 | 
				
			||||||
	CreateUserAccount(ctx context.Context, arg CreateUserAccountParams) (UserAccount, error)
 | 
						CreateUserAccount(ctx context.Context, arg CreateUserAccountParams) (UserAccount, error)
 | 
				
			||||||
	DeleteExpiredTokens(ctx context.Context) error
 | 
						DeleteExpiredTokens(ctx context.Context) error
 | 
				
			||||||
 | 
						DeleteProjectByID(ctx context.Context, projectID uuid.UUID) error
 | 
				
			||||||
	DeleteProjectLabelByID(ctx context.Context, projectLabelID uuid.UUID) error
 | 
						DeleteProjectLabelByID(ctx context.Context, projectLabelID uuid.UUID) error
 | 
				
			||||||
	DeleteRefreshTokenByID(ctx context.Context, tokenID uuid.UUID) error
 | 
						DeleteRefreshTokenByID(ctx context.Context, tokenID uuid.UUID) error
 | 
				
			||||||
	DeleteRefreshTokenByUserID(ctx context.Context, userID uuid.UUID) error
 | 
						DeleteRefreshTokenByUserID(ctx context.Context, userID uuid.UUID) error
 | 
				
			||||||
@@ -34,6 +36,7 @@ type Querier interface {
 | 
				
			|||||||
	DeleteTaskLabelForTaskByProjectLabelID(ctx context.Context, arg DeleteTaskLabelForTaskByProjectLabelIDParams) error
 | 
						DeleteTaskLabelForTaskByProjectLabelID(ctx context.Context, arg DeleteTaskLabelForTaskByProjectLabelIDParams) error
 | 
				
			||||||
	DeleteTasksByTaskGroupID(ctx context.Context, taskGroupID uuid.UUID) (int64, error)
 | 
						DeleteTasksByTaskGroupID(ctx context.Context, taskGroupID uuid.UUID) (int64, error)
 | 
				
			||||||
	DeleteTeamByID(ctx context.Context, teamID uuid.UUID) error
 | 
						DeleteTeamByID(ctx context.Context, teamID uuid.UUID) error
 | 
				
			||||||
 | 
						DeleteTeamMemberByUserID(ctx context.Context, userID uuid.UUID) error
 | 
				
			||||||
	GetAllOrganizations(ctx context.Context) ([]Organization, error)
 | 
						GetAllOrganizations(ctx context.Context) ([]Organization, error)
 | 
				
			||||||
	GetAllProjects(ctx context.Context) ([]Project, error)
 | 
						GetAllProjects(ctx context.Context) ([]Project, error)
 | 
				
			||||||
	GetAllProjectsForTeam(ctx context.Context, teamID uuid.UUID) ([]Project, error)
 | 
						GetAllProjectsForTeam(ctx context.Context, teamID uuid.UUID) ([]Project, error)
 | 
				
			||||||
@@ -59,6 +62,7 @@ type Querier interface {
 | 
				
			|||||||
	GetTaskLabelsForTaskID(ctx context.Context, taskID uuid.UUID) ([]TaskLabel, error)
 | 
						GetTaskLabelsForTaskID(ctx context.Context, taskID uuid.UUID) ([]TaskLabel, error)
 | 
				
			||||||
	GetTasksForTaskGroupID(ctx context.Context, taskGroupID uuid.UUID) ([]Task, error)
 | 
						GetTasksForTaskGroupID(ctx context.Context, taskGroupID uuid.UUID) ([]Task, error)
 | 
				
			||||||
	GetTeamByID(ctx context.Context, teamID uuid.UUID) (Team, error)
 | 
						GetTeamByID(ctx context.Context, teamID uuid.UUID) (Team, error)
 | 
				
			||||||
 | 
						GetTeamMembersForTeamID(ctx context.Context, teamID uuid.UUID) ([]TeamMember, error)
 | 
				
			||||||
	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)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										75
									
								
								api/pg/team_member.sql.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								api/pg/team_member.sql.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,75 @@
 | 
				
			|||||||
 | 
					// Code generated by sqlc. DO NOT EDIT.
 | 
				
			||||||
 | 
					// source: team_member.sql
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package pg
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/google/uuid"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const createTeamMember = `-- name: CreateTeamMember :one
 | 
				
			||||||
 | 
					INSERT INTO team_member (team_id, user_id, addedDate) VALUES ($1, $2, $3)
 | 
				
			||||||
 | 
					  RETURNING team_member_id, team_id, user_id, addeddate
 | 
				
			||||||
 | 
					`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type CreateTeamMemberParams struct {
 | 
				
			||||||
 | 
						TeamID    uuid.UUID `json:"team_id"`
 | 
				
			||||||
 | 
						UserID    uuid.UUID `json:"user_id"`
 | 
				
			||||||
 | 
						Addeddate time.Time `json:"addeddate"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (q *Queries) CreateTeamMember(ctx context.Context, arg CreateTeamMemberParams) (TeamMember, error) {
 | 
				
			||||||
 | 
						row := q.db.QueryRowContext(ctx, createTeamMember, arg.TeamID, arg.UserID, arg.Addeddate)
 | 
				
			||||||
 | 
						var i TeamMember
 | 
				
			||||||
 | 
						err := row.Scan(
 | 
				
			||||||
 | 
							&i.TeamMemberID,
 | 
				
			||||||
 | 
							&i.TeamID,
 | 
				
			||||||
 | 
							&i.UserID,
 | 
				
			||||||
 | 
							&i.Addeddate,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						return i, err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const deleteTeamMemberByUserID = `-- name: DeleteTeamMemberByUserID :exec
 | 
				
			||||||
 | 
					DELETE FROM team_member WHERE user_id = $1
 | 
				
			||||||
 | 
					`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (q *Queries) DeleteTeamMemberByUserID(ctx context.Context, userID uuid.UUID) error {
 | 
				
			||||||
 | 
						_, err := q.db.ExecContext(ctx, deleteTeamMemberByUserID, userID)
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const getTeamMembersForTeamID = `-- name: GetTeamMembersForTeamID :many
 | 
				
			||||||
 | 
					SELECT team_member_id, team_id, user_id, addeddate FROM team_member WHERE team_id = $1
 | 
				
			||||||
 | 
					`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (q *Queries) GetTeamMembersForTeamID(ctx context.Context, teamID uuid.UUID) ([]TeamMember, error) {
 | 
				
			||||||
 | 
						rows, err := q.db.QueryContext(ctx, getTeamMembersForTeamID, teamID)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer rows.Close()
 | 
				
			||||||
 | 
						var items []TeamMember
 | 
				
			||||||
 | 
						for rows.Next() {
 | 
				
			||||||
 | 
							var i TeamMember
 | 
				
			||||||
 | 
							if err := rows.Scan(
 | 
				
			||||||
 | 
								&i.TeamMemberID,
 | 
				
			||||||
 | 
								&i.TeamID,
 | 
				
			||||||
 | 
								&i.UserID,
 | 
				
			||||||
 | 
								&i.Addeddate,
 | 
				
			||||||
 | 
							); 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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -12,3 +12,6 @@ INSERT INTO project(owner, team_id, created_at, name) VALUES ($1, $2, $3, $4) RE
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
-- name: UpdateProjectNameByID :one
 | 
					-- name: UpdateProjectNameByID :one
 | 
				
			||||||
UPDATE project SET name = $2 WHERE project_id = $1 RETURNING *;
 | 
					UPDATE project SET name = $2 WHERE project_id = $1 RETURNING *;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- name: DeleteProjectByID :exec
 | 
				
			||||||
 | 
					DELETE FROM project WHERE project_id = $1;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										9
									
								
								api/query/team_member.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								api/query/team_member.sql
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					-- name: CreateTeamMember :one
 | 
				
			||||||
 | 
					INSERT INTO team_member (team_id, user_id, addedDate) VALUES ($1, $2, $3)
 | 
				
			||||||
 | 
					  RETURNING *;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- name: GetTeamMembersForTeamID :many
 | 
				
			||||||
 | 
					SELECT * FROM team_member WHERE team_id = $1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- name: DeleteTeamMemberByUserID :exec
 | 
				
			||||||
 | 
					DELETE FROM team_member WHERE user_id = $1;
 | 
				
			||||||
@@ -1,22 +1,47 @@
 | 
				
			|||||||
import React, { useState, useContext } from 'react';
 | 
					import React, { useState, useContext } from 'react';
 | 
				
			||||||
import TopNavbar from 'shared/components/TopNavbar';
 | 
					import TopNavbar from 'shared/components/TopNavbar';
 | 
				
			||||||
import DropdownMenu, { ProfileMenu } from 'shared/components/DropdownMenu';
 | 
					import DropdownMenu, { ProfileMenu } from 'shared/components/DropdownMenu';
 | 
				
			||||||
import ProjectSettings from 'shared/components/ProjectSettings';
 | 
					import ProjectSettings, { DeleteProject } from 'shared/components/ProjectSettings';
 | 
				
			||||||
import { useHistory } from 'react-router';
 | 
					import { useHistory } from 'react-router';
 | 
				
			||||||
import UserIDContext from 'App/context';
 | 
					import UserIDContext from 'App/context';
 | 
				
			||||||
import { useMeQuery } from 'shared/generated/graphql';
 | 
					import { useMeQuery, useDeleteProjectMutation, GetProjectsDocument } from 'shared/generated/graphql';
 | 
				
			||||||
import { usePopup, Popup } from 'shared/components/PopupMenu';
 | 
					import { usePopup, Popup } from 'shared/components/PopupMenu';
 | 
				
			||||||
 | 
					import produce from 'immer';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type GlobalTopNavbarProps = {
 | 
					type GlobalTopNavbarProps = {
 | 
				
			||||||
 | 
					  projectID: string | null;
 | 
				
			||||||
  name: string | null;
 | 
					  name: string | null;
 | 
				
			||||||
  projectMembers?: null | Array<TaskUser>;
 | 
					  projectMembers?: null | Array<TaskUser>;
 | 
				
			||||||
  onSaveProjectName?: (projectName: string) => void;
 | 
					  onSaveProjectName?: (projectName: string) => void;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
const GlobalTopNavbar: React.FC<GlobalTopNavbarProps> = ({ name, projectMembers, onSaveProjectName }) => {
 | 
					const GlobalTopNavbar: React.FC<GlobalTopNavbarProps> = ({ projectID, name, projectMembers, onSaveProjectName }) => {
 | 
				
			||||||
  const { loading, data } = useMeQuery();
 | 
					  const { loading, data } = useMeQuery();
 | 
				
			||||||
  const { showPopup, hidePopup } = usePopup();
 | 
					  const { showPopup, hidePopup, setTab } = usePopup();
 | 
				
			||||||
  const history = useHistory();
 | 
					  const history = useHistory();
 | 
				
			||||||
  const { userID, setUserID } = useContext(UserIDContext);
 | 
					  const { userID, setUserID } = useContext(UserIDContext);
 | 
				
			||||||
 | 
					  const [deleteProject] = useDeleteProjectMutation({
 | 
				
			||||||
 | 
					    update: (client, deleteData) => {
 | 
				
			||||||
 | 
					      const cacheData: any = client.readQuery({
 | 
				
			||||||
 | 
					        query: GetProjectsDocument,
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      console.log(cacheData);
 | 
				
			||||||
 | 
					      console.log(deleteData);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      const newData = produce(cacheData, (draftState: any) => {
 | 
				
			||||||
 | 
					        draftState.projects = draftState.projects.filter(
 | 
				
			||||||
 | 
					          (project: any) => project.id !== deleteData.data.deleteProject.project.id,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      client.writeQuery({
 | 
				
			||||||
 | 
					        query: GetProjectsDocument,
 | 
				
			||||||
 | 
					        data: {
 | 
				
			||||||
 | 
					          ...newData,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
  const onLogout = () => {
 | 
					  const onLogout = () => {
 | 
				
			||||||
    fetch('http://localhost:3333/auth/logout', {
 | 
					    fetch('http://localhost:3333/auth/logout', {
 | 
				
			||||||
      method: 'POST',
 | 
					      method: 'POST',
 | 
				
			||||||
@@ -49,9 +74,27 @@ const GlobalTopNavbar: React.FC<GlobalTopNavbarProps> = ({ name, projectMembers,
 | 
				
			|||||||
  const onOpenSettings = ($target: React.RefObject<HTMLElement>) => {
 | 
					  const onOpenSettings = ($target: React.RefObject<HTMLElement>) => {
 | 
				
			||||||
    showPopup(
 | 
					    showPopup(
 | 
				
			||||||
      $target,
 | 
					      $target,
 | 
				
			||||||
      <Popup title={null} tab={0}>
 | 
					      <>
 | 
				
			||||||
        <ProjectSettings />
 | 
					        <Popup title={null} tab={0}>
 | 
				
			||||||
      </Popup>,
 | 
					          <ProjectSettings
 | 
				
			||||||
 | 
					            onDeleteProject={() => {
 | 
				
			||||||
 | 
					              setTab(1, 325);
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					          />
 | 
				
			||||||
 | 
					        </Popup>
 | 
				
			||||||
 | 
					        <Popup title={`Delete the "${name}" project?`} tab={1}>
 | 
				
			||||||
 | 
					          <DeleteProject
 | 
				
			||||||
 | 
					            name={name ?? ''}
 | 
				
			||||||
 | 
					            onDeleteProject={() => {
 | 
				
			||||||
 | 
					              if (projectID) {
 | 
				
			||||||
 | 
					                deleteProject({ variables: { projectID } });
 | 
				
			||||||
 | 
					                hidePopup();
 | 
				
			||||||
 | 
					                history.push('/projects');
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					          />
 | 
				
			||||||
 | 
					        </Popup>
 | 
				
			||||||
 | 
					      </>,
 | 
				
			||||||
      185,
 | 
					      185,
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -50,7 +50,7 @@ const Projects = () => {
 | 
				
			|||||||
          }
 | 
					          }
 | 
				
			||||||
        }}
 | 
					        }}
 | 
				
			||||||
      />
 | 
					      />
 | 
				
			||||||
      <GlobalTopNavbar onSaveProjectName={() => {}} name={null} />
 | 
					      <GlobalTopNavbar projectID={null} onSaveProjectName={() => {}} name={null} />
 | 
				
			||||||
      {!loading && data && (
 | 
					      {!loading && data && (
 | 
				
			||||||
        <Settings
 | 
					        <Settings
 | 
				
			||||||
          profile={data.me.profileIcon}
 | 
					          profile={data.me.profileIcon}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -472,7 +472,7 @@ const Project = () => {
 | 
				
			|||||||
  if (loading) {
 | 
					  if (loading) {
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
      <>
 | 
					      <>
 | 
				
			||||||
        <GlobalTopNavbar onSaveProjectName={projectName => {}} name="" />
 | 
					        <GlobalTopNavbar onSaveProjectName={projectName => {}} name="" projectID={null} />
 | 
				
			||||||
      </>
 | 
					      </>
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -510,6 +510,7 @@ const Project = () => {
 | 
				
			|||||||
            updateProjectName({ variables: { projectID, name: projectName } });
 | 
					            updateProjectName({ variables: { projectID, name: projectName } });
 | 
				
			||||||
          }}
 | 
					          }}
 | 
				
			||||||
          projectMembers={data.findProject.members}
 | 
					          projectMembers={data.findProject.members}
 | 
				
			||||||
 | 
					          projectID={projectID}
 | 
				
			||||||
          name={data.findProject.name}
 | 
					          name={data.findProject.name}
 | 
				
			||||||
        />
 | 
					        />
 | 
				
			||||||
        <ProjectBar>
 | 
					        <ProjectBar>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,32 +1,183 @@
 | 
				
			|||||||
import React, { useState, useContext, useEffect } from 'react';
 | 
					import React, { useState, useContext, useEffect } from 'react';
 | 
				
			||||||
import styled from 'styled-components/macro';
 | 
					import styled from 'styled-components/macro';
 | 
				
			||||||
import GlobalTopNavbar from 'App/TopNavbar';
 | 
					import GlobalTopNavbar from 'App/TopNavbar';
 | 
				
			||||||
import { useGetProjectsQuery, useCreateProjectMutation, GetProjectsDocument } from 'shared/generated/graphql';
 | 
					import {
 | 
				
			||||||
 | 
					  useCreateTeamMutation,
 | 
				
			||||||
 | 
					  useGetProjectsQuery,
 | 
				
			||||||
 | 
					  useCreateProjectMutation,
 | 
				
			||||||
 | 
					  GetProjectsDocument,
 | 
				
			||||||
 | 
					} from 'shared/generated/graphql';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import ProjectGridItem, { AddProjectItem } from 'shared/components/ProjectGridItem';
 | 
					import ProjectGridItem, { AddProjectItem } from 'shared/components/ProjectGridItem';
 | 
				
			||||||
import { Link } from 'react-router-dom';
 | 
					import { Link } from 'react-router-dom';
 | 
				
			||||||
import Navbar from 'App/Navbar';
 | 
					import Navbar from 'App/Navbar';
 | 
				
			||||||
import NewProject from 'shared/components/NewProject';
 | 
					import NewProject from 'shared/components/NewProject';
 | 
				
			||||||
import UserIDContext from 'App/context';
 | 
					import UserIDContext from 'App/context';
 | 
				
			||||||
 | 
					import Button from 'shared/components/Button';
 | 
				
			||||||
 | 
					import { usePopup, Popup } from 'shared/components/PopupMenu';
 | 
				
			||||||
 | 
					import { useForm } from 'react-hook-form';
 | 
				
			||||||
 | 
					import Input from 'shared/components/Input';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const MainContent = styled.div`
 | 
					const CreateTeamButton = styled(Button)`
 | 
				
			||||||
  padding: 0 0 50px 80px;
 | 
					  width: 100%;
 | 
				
			||||||
  height: 100%;
 | 
					`;
 | 
				
			||||||
  background: #262c49;
 | 
					type CreateTeamData = { teamName: string };
 | 
				
			||||||
 | 
					type CreateTeamFormProps = {
 | 
				
			||||||
 | 
					  onCreateTeam: (teamName: string) => void;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					const CreateTeamFormContainer = styled.form``;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const CreateTeamForm: React.FC<CreateTeamFormProps> = ({ onCreateTeam }) => {
 | 
				
			||||||
 | 
					  const { register, handleSubmit, errors } = useForm<CreateTeamData>();
 | 
				
			||||||
 | 
					  const createTeam = (data: CreateTeamData) => {
 | 
				
			||||||
 | 
					    onCreateTeam(data.teamName);
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <CreateTeamFormContainer onSubmit={handleSubmit(createTeam)}>
 | 
				
			||||||
 | 
					      <Input
 | 
				
			||||||
 | 
					        width="100%"
 | 
				
			||||||
 | 
					        label="Team name"
 | 
				
			||||||
 | 
					        id="teamName"
 | 
				
			||||||
 | 
					        name="teamName"
 | 
				
			||||||
 | 
					        variant="alternate"
 | 
				
			||||||
 | 
					        ref={register({ required: 'Team name is required' })}
 | 
				
			||||||
 | 
					      />
 | 
				
			||||||
 | 
					      <CreateTeamButton type="submit">Create</CreateTeamButton>
 | 
				
			||||||
 | 
					    </CreateTeamFormContainer>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ProjectAddTile = styled.div`
 | 
				
			||||||
 | 
					  background-color: rgba(${props => props.theme.colors.bg.primary}, 0.4);
 | 
				
			||||||
 | 
					  background-size: cover;
 | 
				
			||||||
 | 
					  background-position: 50%;
 | 
				
			||||||
 | 
					  color: #fff;
 | 
				
			||||||
 | 
					  line-height: 20px;
 | 
				
			||||||
 | 
					  padding: 8px;
 | 
				
			||||||
 | 
					  position: relative;
 | 
				
			||||||
 | 
					  text-decoration: none;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  border-radius: 3px;
 | 
				
			||||||
 | 
					  display: block;
 | 
				
			||||||
`;
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ProjectTile = styled(Link)<{ color: string }>`
 | 
				
			||||||
 | 
					  background-color: ${props => props.color};
 | 
				
			||||||
 | 
					  background-size: cover;
 | 
				
			||||||
 | 
					  background-position: 50%;
 | 
				
			||||||
 | 
					  color: #fff;
 | 
				
			||||||
 | 
					  line-height: 20px;
 | 
				
			||||||
 | 
					  padding: 8px;
 | 
				
			||||||
 | 
					  position: relative;
 | 
				
			||||||
 | 
					  text-decoration: none;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  border-radius: 3px;
 | 
				
			||||||
 | 
					  display: block;
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ProjectTileFade = styled.div`
 | 
				
			||||||
 | 
					  background-color: rgba(0, 0, 0, 0.15);
 | 
				
			||||||
 | 
					  bottom: 0;
 | 
				
			||||||
 | 
					  left: 0;
 | 
				
			||||||
 | 
					  position: absolute;
 | 
				
			||||||
 | 
					  right: 0;
 | 
				
			||||||
 | 
					  top: 0;
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ProjectListItem = styled.li`
 | 
				
			||||||
 | 
					  width: 23.5%;
 | 
				
			||||||
 | 
					  padding: 0;
 | 
				
			||||||
 | 
					  margin: 0 2% 2% 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  box-sizing: border-box;
 | 
				
			||||||
 | 
					  position: relative;
 | 
				
			||||||
 | 
					  cursor: pointer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  &:hover ${ProjectTileFade} {
 | 
				
			||||||
 | 
					    background-color: rgba(0, 0, 0, 0.25);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ProjectList = styled.ul`
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  flex-wrap: wrap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  & ${ProjectListItem}:nth-of-type(4n) {
 | 
				
			||||||
 | 
					    margin-right: 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ProjectTileDetails = styled.div`
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  height: 80px;
 | 
				
			||||||
 | 
					  position: relative;
 | 
				
			||||||
 | 
					  flex-direction: column;
 | 
				
			||||||
 | 
					  justify-content: space-between;
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ProjectAddTileDetails = styled.div`
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  height: 80px;
 | 
				
			||||||
 | 
					  position: relative;
 | 
				
			||||||
 | 
					  flex-direction: column;
 | 
				
			||||||
 | 
					  align-items: center;
 | 
				
			||||||
 | 
					  justify-content: center;
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ProjectTileName = styled.div<{ centered?: boolean }>`
 | 
				
			||||||
 | 
					  flex: 0 0 auto;
 | 
				
			||||||
 | 
					  font-size: 16px;
 | 
				
			||||||
 | 
					  font-weight: 700;
 | 
				
			||||||
 | 
					  display: inline-block;
 | 
				
			||||||
 | 
					  overflow: hidden;
 | 
				
			||||||
 | 
					  max-height: 40px;
 | 
				
			||||||
 | 
					  width: 100%;
 | 
				
			||||||
 | 
					  word-wrap: break-word;
 | 
				
			||||||
 | 
					  ${props => props.centered && 'text-align: center;'}
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const Wrapper = styled.div`
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  flex-direction: row;
 | 
				
			||||||
 | 
					  align-items: flex-start;
 | 
				
			||||||
 | 
					  justify-content: center;
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ProjectSectionTitleWrapper = styled.div`
 | 
				
			||||||
 | 
					  align-items: center;
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  height: 32px;
 | 
				
			||||||
 | 
					  margin-bottom: 24px;
 | 
				
			||||||
 | 
					  padding: 8px 0;
 | 
				
			||||||
 | 
					  position: relative;
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ProjectSectionTitle = styled.h3`
 | 
				
			||||||
 | 
					  font-size: 16px;
 | 
				
			||||||
 | 
					  color: rgba(${props => props.theme.colors.text.primary});
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ProjectsContainer = styled.div`
 | 
				
			||||||
 | 
					  margin: 40px 16px 0;
 | 
				
			||||||
 | 
					  width: 100%;
 | 
				
			||||||
 | 
					  max-width: 825px;
 | 
				
			||||||
 | 
					  min-width: 288px;
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
const ProjectGrid = styled.div`
 | 
					const ProjectGrid = styled.div`
 | 
				
			||||||
  width: 60%;
 | 
					 | 
				
			||||||
  max-width: 780px;
 | 
					  max-width: 780px;
 | 
				
			||||||
  margin: 25px auto;
 | 
					 | 
				
			||||||
  display: grid;
 | 
					  display: grid;
 | 
				
			||||||
  grid-template-columns: 240px 240px 240px;
 | 
					  grid-template-columns: 240px 240px 240px;
 | 
				
			||||||
  gap: 20px 10px;
 | 
					  gap: 20px 10px;
 | 
				
			||||||
`;
 | 
					`;
 | 
				
			||||||
 | 
					const AddTeamButton = styled(Button)`
 | 
				
			||||||
 | 
					  padding: 6px 12px;
 | 
				
			||||||
 | 
					  float: right;
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const ProjectLink = styled(Link)``;
 | 
					const ProjectLink = styled(Link)``;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const Projects = () => {
 | 
					const Projects = () => {
 | 
				
			||||||
 | 
					  const { showPopup } = usePopup();
 | 
				
			||||||
  const { loading, data } = useGetProjectsQuery();
 | 
					  const { loading, data } = useGetProjectsQuery();
 | 
				
			||||||
  useEffect(() => {
 | 
					  useEffect(() => {
 | 
				
			||||||
    document.title = 'Citadel';
 | 
					    document.title = 'Citadel';
 | 
				
			||||||
@@ -53,6 +204,7 @@ const Projects = () => {
 | 
				
			|||||||
  });
 | 
					  });
 | 
				
			||||||
  const [showNewProject, setShowNewProject] = useState(false);
 | 
					  const [showNewProject, setShowNewProject] = useState(false);
 | 
				
			||||||
  const { userID, setUserID } = useContext(UserIDContext);
 | 
					  const { userID, setUserID } = useContext(UserIDContext);
 | 
				
			||||||
 | 
					  const [createTeam] = useCreateTeamMutation();
 | 
				
			||||||
  if (loading) {
 | 
					  if (loading) {
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
      <>
 | 
					      <>
 | 
				
			||||||
@@ -60,39 +212,91 @@ const Projects = () => {
 | 
				
			|||||||
      </>
 | 
					      </>
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const colors = ['#e362e3', '#7a6ff0', '#37c5ab', '#aa62e3', '#e8384f'];
 | 
				
			||||||
  if (data) {
 | 
					  if (data) {
 | 
				
			||||||
    const { projects, teams } = data;
 | 
					    const { projects, teams, organizations } = data;
 | 
				
			||||||
 | 
					    const organizationID = organizations[0].id ?? null;
 | 
				
			||||||
 | 
					    const projectTeams = teams.map(team => {
 | 
				
			||||||
 | 
					      return {
 | 
				
			||||||
 | 
					        id: team.id,
 | 
				
			||||||
 | 
					        name: team.name,
 | 
				
			||||||
 | 
					        projects: projects.filter(project => project.team.id === team.id),
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
      <>
 | 
					      <>
 | 
				
			||||||
        <GlobalTopNavbar onSaveProjectName={() => {}} name={null} />
 | 
					        <GlobalTopNavbar onSaveProjectName={() => {}} projectID={null} name={null} />
 | 
				
			||||||
        <ProjectGrid>
 | 
					        <Wrapper>
 | 
				
			||||||
          {projects.map(project => (
 | 
					          <ProjectsContainer>
 | 
				
			||||||
            <ProjectLink key={project.id} to={`/projects/${project.id}`}>
 | 
					            <AddTeamButton
 | 
				
			||||||
              <ProjectGridItem
 | 
					              variant="outline"
 | 
				
			||||||
                project={{ ...project, projectID: project.id, teamTitle: project.team.name, taskGroups: [] }}
 | 
					              onClick={$target => {
 | 
				
			||||||
 | 
					                showPopup(
 | 
				
			||||||
 | 
					                  $target,
 | 
				
			||||||
 | 
					                  <Popup title="Create team" tab={0}>
 | 
				
			||||||
 | 
					                    <CreateTeamForm
 | 
				
			||||||
 | 
					                      onCreateTeam={teamName => {
 | 
				
			||||||
 | 
					                        if (organizationID) {
 | 
				
			||||||
 | 
					                          createTeam({ variables: { name: teamName, organizationID } });
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                      }}
 | 
				
			||||||
 | 
					                    />
 | 
				
			||||||
 | 
					                  </Popup>,
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					              }}
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
 | 
					              Add Team
 | 
				
			||||||
 | 
					            </AddTeamButton>
 | 
				
			||||||
 | 
					            {projectTeams.map(team => {
 | 
				
			||||||
 | 
					              return (
 | 
				
			||||||
 | 
					                <div key={team.id}>
 | 
				
			||||||
 | 
					                  <ProjectSectionTitleWrapper>
 | 
				
			||||||
 | 
					                    <ProjectSectionTitle>{team.name}</ProjectSectionTitle>
 | 
				
			||||||
 | 
					                  </ProjectSectionTitleWrapper>
 | 
				
			||||||
 | 
					                  <ProjectList>
 | 
				
			||||||
 | 
					                    {team.projects.map((project, idx) => (
 | 
				
			||||||
 | 
					                      <ProjectListItem key={project.id}>
 | 
				
			||||||
 | 
					                        <ProjectTile color={colors[idx % 5]} to={`/projects/${project.id}`}>
 | 
				
			||||||
 | 
					                          <ProjectTileFade />
 | 
				
			||||||
 | 
					                          <ProjectTileDetails>
 | 
				
			||||||
 | 
					                            <ProjectTileName>{project.name}</ProjectTileName>
 | 
				
			||||||
 | 
					                          </ProjectTileDetails>
 | 
				
			||||||
 | 
					                        </ProjectTile>
 | 
				
			||||||
 | 
					                      </ProjectListItem>
 | 
				
			||||||
 | 
					                    ))}
 | 
				
			||||||
 | 
					                    <ProjectListItem>
 | 
				
			||||||
 | 
					                      <ProjectAddTile
 | 
				
			||||||
 | 
					                        onClick={() => {
 | 
				
			||||||
 | 
					                          setShowNewProject(true);
 | 
				
			||||||
 | 
					                        }}
 | 
				
			||||||
 | 
					                      >
 | 
				
			||||||
 | 
					                        <ProjectTileFade />
 | 
				
			||||||
 | 
					                        <ProjectAddTileDetails>
 | 
				
			||||||
 | 
					                          <ProjectTileName centered>Create new project</ProjectTileName>
 | 
				
			||||||
 | 
					                        </ProjectAddTileDetails>
 | 
				
			||||||
 | 
					                      </ProjectAddTile>
 | 
				
			||||||
 | 
					                    </ProjectListItem>
 | 
				
			||||||
 | 
					                  </ProjectList>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					              );
 | 
				
			||||||
 | 
					            })}
 | 
				
			||||||
 | 
					            {showNewProject && (
 | 
				
			||||||
 | 
					              <NewProject
 | 
				
			||||||
 | 
					                onCreateProject={(name, teamID) => {
 | 
				
			||||||
 | 
					                  if (userID) {
 | 
				
			||||||
 | 
					                    createProject({ variables: { teamID, name, userID } });
 | 
				
			||||||
 | 
					                    setShowNewProject(false);
 | 
				
			||||||
 | 
					                  }
 | 
				
			||||||
 | 
					                }}
 | 
				
			||||||
 | 
					                onClose={() => {
 | 
				
			||||||
 | 
					                  setShowNewProject(false);
 | 
				
			||||||
 | 
					                }}
 | 
				
			||||||
 | 
					                teams={teams}
 | 
				
			||||||
              />
 | 
					              />
 | 
				
			||||||
            </ProjectLink>
 | 
					            )}
 | 
				
			||||||
          ))}
 | 
					          </ProjectsContainer>
 | 
				
			||||||
          <AddProjectItem
 | 
					        </Wrapper>
 | 
				
			||||||
            onAddProject={() => {
 | 
					 | 
				
			||||||
              setShowNewProject(true);
 | 
					 | 
				
			||||||
            }}
 | 
					 | 
				
			||||||
          />
 | 
					 | 
				
			||||||
        </ProjectGrid>
 | 
					 | 
				
			||||||
        {showNewProject && (
 | 
					 | 
				
			||||||
          <NewProject
 | 
					 | 
				
			||||||
            onCreateProject={(name, teamID) => {
 | 
					 | 
				
			||||||
              if (userID) {
 | 
					 | 
				
			||||||
                createProject({ variables: { teamID, name, userID } });
 | 
					 | 
				
			||||||
                setShowNewProject(false);
 | 
					 | 
				
			||||||
              }
 | 
					 | 
				
			||||||
            }}
 | 
					 | 
				
			||||||
            onClose={() => {
 | 
					 | 
				
			||||||
              setShowNewProject(false);
 | 
					 | 
				
			||||||
            }}
 | 
					 | 
				
			||||||
            teams={teams}
 | 
					 | 
				
			||||||
          />
 | 
					 | 
				
			||||||
        )}
 | 
					 | 
				
			||||||
      </>
 | 
					      </>
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,7 +11,7 @@ const InputWrapper = styled.div<{ width: string }>`
 | 
				
			|||||||
  justify-content: center;
 | 
					  justify-content: center;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  margin-bottom: 2.2rem;
 | 
					  margin-bottom: 2.2rem;
 | 
				
			||||||
  margin-top: 17px;
 | 
					  margin-top: 24px;
 | 
				
			||||||
`;
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const InputLabel = styled.span<{ width: string }>`
 | 
					const InputLabel = styled.span<{ width: string }>`
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,5 @@
 | 
				
			|||||||
import styled from 'styled-components';
 | 
					import styled from 'styled-components';
 | 
				
			||||||
 | 
					import Button from 'shared/components/Button';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const Wrapper = styled.div`
 | 
					export const Wrapper = styled.div`
 | 
				
			||||||
  background: #eff2f7;
 | 
					  background: #eff2f7;
 | 
				
			||||||
@@ -70,21 +71,7 @@ export const FormError = styled.span`
 | 
				
			|||||||
  color: rgb(234, 84, 85);
 | 
					  color: rgb(234, 84, 85);
 | 
				
			||||||
`;
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const LoginButton = styled.input`
 | 
					export const LoginButton = styled(Button)``;
 | 
				
			||||||
  padding: 0.75rem 2rem;
 | 
					 | 
				
			||||||
  font-size: 1rem;
 | 
					 | 
				
			||||||
  border-radius: 6px;
 | 
					 | 
				
			||||||
  background: var(--color-button-background);
 | 
					 | 
				
			||||||
  outline: none;
 | 
					 | 
				
			||||||
  border: none;
 | 
					 | 
				
			||||||
  cursor: pointer;
 | 
					 | 
				
			||||||
  color: var(--color-button-text-hover);
 | 
					 | 
				
			||||||
  &:disabled {
 | 
					 | 
				
			||||||
    opacity: 0.5;
 | 
					 | 
				
			||||||
    cursor: default;
 | 
					 | 
				
			||||||
    pointer-events: none;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
`;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const ActionButtons = styled.div`
 | 
					export const ActionButtons = styled.div`
 | 
				
			||||||
  margin-top: 17.5px;
 | 
					  margin-top: 17.5px;
 | 
				
			||||||
@@ -92,15 +79,7 @@ export const ActionButtons = styled.div`
 | 
				
			|||||||
  justify-content: space-between;
 | 
					  justify-content: space-between;
 | 
				
			||||||
`;
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const RegisterButton = styled.button`
 | 
					export const RegisterButton = styled(Button)``;
 | 
				
			||||||
  padding: 0.679rem 2rem;
 | 
					 | 
				
			||||||
  border-radius: 6px;
 | 
					 | 
				
			||||||
  border: 1px solid rgb(115, 103, 240);
 | 
					 | 
				
			||||||
  background: transparent;
 | 
					 | 
				
			||||||
  font-size: 1rem;
 | 
					 | 
				
			||||||
  color: var(--color-primary);
 | 
					 | 
				
			||||||
  cursor: pointer;
 | 
					 | 
				
			||||||
`;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const LogoTitle = styled.div`
 | 
					export const LogoTitle = styled.div`
 | 
				
			||||||
  font-size: 24px;
 | 
					  font-size: 24px;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -72,8 +72,10 @@ const Login = ({ onSubmit }: LoginProps) => {
 | 
				
			|||||||
              {errors.password && <FormError>{errors.password.message}</FormError>}
 | 
					              {errors.password && <FormError>{errors.password.message}</FormError>}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
              <ActionButtons>
 | 
					              <ActionButtons>
 | 
				
			||||||
                <RegisterButton>Register</RegisterButton>
 | 
					                <RegisterButton variant="outline">Register</RegisterButton>
 | 
				
			||||||
                <LoginButton type="submit" value="Login" disabled={!isComplete} />
 | 
					                <LoginButton type="submit" disabled={!isComplete}>
 | 
				
			||||||
 | 
					                  Login
 | 
				
			||||||
 | 
					                </LoginButton>
 | 
				
			||||||
              </ActionButtons>
 | 
					              </ActionButtons>
 | 
				
			||||||
            </Form>
 | 
					            </Form>
 | 
				
			||||||
          </LoginFormContainer>
 | 
					          </LoginFormContainer>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,7 +16,7 @@ import {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
type PopupContextState = {
 | 
					type PopupContextState = {
 | 
				
			||||||
  show: (target: RefObject<HTMLElement>, content: JSX.Element, width?: string | number) => void;
 | 
					  show: (target: RefObject<HTMLElement>, content: JSX.Element, width?: string | number) => void;
 | 
				
			||||||
  setTab: (newTab: number) => void;
 | 
					  setTab: (newTab: number, width?: number | string) => void;
 | 
				
			||||||
  getCurrentTab: () => number;
 | 
					  getCurrentTab: () => number;
 | 
				
			||||||
  hide: () => void;
 | 
					  hide: () => void;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@@ -139,12 +139,14 @@ export const PopupProvider: React.FC = ({ children }) => {
 | 
				
			|||||||
  };
 | 
					  };
 | 
				
			||||||
  const portalTarget = canUseDOM ? document.body : null; // appease flow
 | 
					  const portalTarget = canUseDOM ? document.body : null; // appease flow
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const setTab = (newTab: number) => {
 | 
					  const setTab = (newTab: number, width?: number | string) => {
 | 
				
			||||||
 | 
					    let newWidth = width ?? currentState.width;
 | 
				
			||||||
    setState((prevState: PopupState) => {
 | 
					    setState((prevState: PopupState) => {
 | 
				
			||||||
      return {
 | 
					      return {
 | 
				
			||||||
        ...prevState,
 | 
					        ...prevState,
 | 
				
			||||||
        previousTab: currentState.currentTab,
 | 
					        previousTab: currentState.currentTab,
 | 
				
			||||||
        currentTab: newTab,
 | 
					        currentTab: newTab,
 | 
				
			||||||
 | 
					        width: newWidth,
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,7 @@
 | 
				
			|||||||
import React from 'react';
 | 
					import React from 'react';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import styled from 'styled-components';
 | 
					import styled from 'styled-components';
 | 
				
			||||||
 | 
					import Button from 'shared/components/Button';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const ListActionsWrapper = styled.ul`
 | 
					export const ListActionsWrapper = styled.ul`
 | 
				
			||||||
  list-style-type: none;
 | 
					  list-style-type: none;
 | 
				
			||||||
@@ -36,16 +37,64 @@ export const ListSeparator = styled.hr`
 | 
				
			|||||||
  width: 100%;
 | 
					  width: 100%;
 | 
				
			||||||
`;
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Props = {};
 | 
					type Props = {
 | 
				
			||||||
const ProjectSettings: React.FC<Props> = () => {
 | 
					  onDeleteProject: () => void;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					const ProjectSettings: React.FC<Props> = ({ onDeleteProject }) => {
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <>
 | 
					    <>
 | 
				
			||||||
      <ListActionsWrapper>
 | 
					      <ListActionsWrapper>
 | 
				
			||||||
        <ListActionItemWrapper onClick={() => {}}>
 | 
					        <ListActionItemWrapper onClick={() => onDeleteProject()}>
 | 
				
			||||||
          <ListActionItem>Delete Project</ListActionItem>
 | 
					          <ListActionItem>Delete Project</ListActionItem>
 | 
				
			||||||
        </ListActionItemWrapper>
 | 
					        </ListActionItemWrapper>
 | 
				
			||||||
      </ListActionsWrapper>
 | 
					      </ListActionsWrapper>
 | 
				
			||||||
    </>
 | 
					    </>
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ConfirmWrapper = styled.div``;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ConfirmSubTitle = styled.h3`
 | 
				
			||||||
 | 
					  font-size: 14px;
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ConfirmDescription = styled.div`
 | 
				
			||||||
 | 
					  font-size: 14px;
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const DeleteList = styled.ul`
 | 
				
			||||||
 | 
					  margin-bottom: 12px;
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					const DeleteListItem = styled.li`
 | 
				
			||||||
 | 
					  padding: 6px 0;
 | 
				
			||||||
 | 
					  list-style: disc;
 | 
				
			||||||
 | 
					  margin-left: 12px;
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ConfirmDeleteButton = styled(Button)`
 | 
				
			||||||
 | 
					  width: 100%;
 | 
				
			||||||
 | 
					  padding: 6px 12px;
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type DeleteProjectProps = {
 | 
				
			||||||
 | 
					  name: string;
 | 
				
			||||||
 | 
					  onDeleteProject: () => void;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					const DeleteProject: React.FC<DeleteProjectProps> = ({ name, onDeleteProject }) => {
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <ConfirmWrapper>
 | 
				
			||||||
 | 
					      <ConfirmDescription>
 | 
				
			||||||
 | 
					        Deleting the project will also delete the following:
 | 
				
			||||||
 | 
					        <DeleteList>
 | 
				
			||||||
 | 
					          <DeleteListItem>Task groups and tasks</DeleteListItem>
 | 
				
			||||||
 | 
					        </DeleteList>
 | 
				
			||||||
 | 
					      </ConfirmDescription>
 | 
				
			||||||
 | 
					      <ConfirmDeleteButton onClick={() => onDeleteProject()} color="danger">
 | 
				
			||||||
 | 
					        Delete
 | 
				
			||||||
 | 
					      </ConfirmDeleteButton>
 | 
				
			||||||
 | 
					    </ConfirmWrapper>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export { DeleteProject };
 | 
				
			||||||
export default ProjectSettings;
 | 
					export default ProjectSettings;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -78,6 +78,7 @@ export type Team = {
 | 
				
			|||||||
  id: Scalars['ID'];
 | 
					  id: Scalars['ID'];
 | 
				
			||||||
  createdAt: Scalars['Time'];
 | 
					  createdAt: Scalars['Time'];
 | 
				
			||||||
  name: Scalars['String'];
 | 
					  name: Scalars['String'];
 | 
				
			||||||
 | 
					  members: Array<ProjectMember>;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type Project = {
 | 
					export type Project = {
 | 
				
			||||||
@@ -145,8 +146,15 @@ export type FindTask = {
 | 
				
			|||||||
  taskID: Scalars['UUID'];
 | 
					  taskID: Scalars['UUID'];
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type Organization = {
 | 
				
			||||||
 | 
					   __typename?: 'Organization';
 | 
				
			||||||
 | 
					  id: Scalars['ID'];
 | 
				
			||||||
 | 
					  name: Scalars['String'];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type Query = {
 | 
					export type Query = {
 | 
				
			||||||
   __typename?: 'Query';
 | 
					   __typename?: 'Query';
 | 
				
			||||||
 | 
					  organizations: Array<Organization>;
 | 
				
			||||||
  users: Array<UserAccount>;
 | 
					  users: Array<UserAccount>;
 | 
				
			||||||
  findUser: UserAccount;
 | 
					  findUser: UserAccount;
 | 
				
			||||||
  findProject: Project;
 | 
					  findProject: Project;
 | 
				
			||||||
@@ -192,7 +200,7 @@ export type NewUserAccount = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
export type NewTeam = {
 | 
					export type NewTeam = {
 | 
				
			||||||
  name: Scalars['String'];
 | 
					  name: Scalars['String'];
 | 
				
			||||||
  organizationID: Scalars['String'];
 | 
					  organizationID: Scalars['UUID'];
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type NewProject = {
 | 
					export type NewProject = {
 | 
				
			||||||
@@ -390,13 +398,36 @@ export type UpdateTaskChecklistItemName = {
 | 
				
			|||||||
  name: Scalars['String'];
 | 
					  name: Scalars['String'];
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type CreateTeamMember = {
 | 
				
			||||||
 | 
					  userID: Scalars['UUID'];
 | 
				
			||||||
 | 
					  teamID: Scalars['UUID'];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type CreateTeamMemberPayload = {
 | 
				
			||||||
 | 
					   __typename?: 'CreateTeamMemberPayload';
 | 
				
			||||||
 | 
					  team: Team;
 | 
				
			||||||
 | 
					  teamMember: ProjectMember;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type DeleteProject = {
 | 
				
			||||||
 | 
					  projectID: Scalars['UUID'];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type DeleteProjectPayload = {
 | 
				
			||||||
 | 
					   __typename?: 'DeleteProjectPayload';
 | 
				
			||||||
 | 
					  ok: Scalars['Boolean'];
 | 
				
			||||||
 | 
					  project: Project;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type Mutation = {
 | 
					export type Mutation = {
 | 
				
			||||||
   __typename?: 'Mutation';
 | 
					   __typename?: 'Mutation';
 | 
				
			||||||
  createRefreshToken: RefreshToken;
 | 
					  createRefreshToken: RefreshToken;
 | 
				
			||||||
  createUserAccount: UserAccount;
 | 
					  createUserAccount: UserAccount;
 | 
				
			||||||
  createTeam: Team;
 | 
					  createTeam: Team;
 | 
				
			||||||
  clearProfileAvatar: UserAccount;
 | 
					  clearProfileAvatar: UserAccount;
 | 
				
			||||||
 | 
					  createTeamMember: CreateTeamMemberPayload;
 | 
				
			||||||
  createProject: Project;
 | 
					  createProject: Project;
 | 
				
			||||||
 | 
					  deleteProject: DeleteProjectPayload;
 | 
				
			||||||
  updateProjectName: Project;
 | 
					  updateProjectName: Project;
 | 
				
			||||||
  createProjectLabel: ProjectLabel;
 | 
					  createProjectLabel: ProjectLabel;
 | 
				
			||||||
  deleteProjectLabel: ProjectLabel;
 | 
					  deleteProjectLabel: ProjectLabel;
 | 
				
			||||||
@@ -443,11 +474,21 @@ export type MutationCreateTeamArgs = {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type MutationCreateTeamMemberArgs = {
 | 
				
			||||||
 | 
					  input: CreateTeamMember;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type MutationCreateProjectArgs = {
 | 
					export type MutationCreateProjectArgs = {
 | 
				
			||||||
  input: NewProject;
 | 
					  input: NewProject;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type MutationDeleteProjectArgs = {
 | 
				
			||||||
 | 
					  input: DeleteProject;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type MutationUpdateProjectNameArgs = {
 | 
					export type MutationUpdateProjectNameArgs = {
 | 
				
			||||||
  input?: Maybe<UpdateProjectName>;
 | 
					  input?: Maybe<UpdateProjectName>;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@@ -869,7 +910,10 @@ export type GetProjectsQueryVariables = {};
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
export type GetProjectsQuery = (
 | 
					export type GetProjectsQuery = (
 | 
				
			||||||
  { __typename?: 'Query' }
 | 
					  { __typename?: 'Query' }
 | 
				
			||||||
  & { teams: Array<(
 | 
					  & { organizations: Array<(
 | 
				
			||||||
 | 
					    { __typename?: 'Organization' }
 | 
				
			||||||
 | 
					    & Pick<Organization, 'id' | 'name'>
 | 
				
			||||||
 | 
					  )>, teams: Array<(
 | 
				
			||||||
    { __typename?: 'Team' }
 | 
					    { __typename?: 'Team' }
 | 
				
			||||||
    & Pick<Team, 'id' | 'name' | 'createdAt'>
 | 
					    & Pick<Team, 'id' | 'name' | 'createdAt'>
 | 
				
			||||||
  )>, projects: Array<(
 | 
					  )>, projects: Array<(
 | 
				
			||||||
@@ -897,6 +941,23 @@ export type MeQuery = (
 | 
				
			|||||||
  ) }
 | 
					  ) }
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type DeleteProjectMutationVariables = {
 | 
				
			||||||
 | 
					  projectID: Scalars['UUID'];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type DeleteProjectMutation = (
 | 
				
			||||||
 | 
					  { __typename?: 'Mutation' }
 | 
				
			||||||
 | 
					  & { deleteProject: (
 | 
				
			||||||
 | 
					    { __typename?: 'DeleteProjectPayload' }
 | 
				
			||||||
 | 
					    & Pick<DeleteProjectPayload, 'ok'>
 | 
				
			||||||
 | 
					    & { project: (
 | 
				
			||||||
 | 
					      { __typename?: 'Project' }
 | 
				
			||||||
 | 
					      & Pick<Project, 'id'>
 | 
				
			||||||
 | 
					    ) }
 | 
				
			||||||
 | 
					  ) }
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type CreateTaskChecklistItemMutationVariables = {
 | 
					export type CreateTaskChecklistItemMutationVariables = {
 | 
				
			||||||
  taskChecklistID: Scalars['UUID'];
 | 
					  taskChecklistID: Scalars['UUID'];
 | 
				
			||||||
  name: Scalars['String'];
 | 
					  name: Scalars['String'];
 | 
				
			||||||
@@ -985,6 +1046,20 @@ export type UpdateTaskGroupNameMutation = (
 | 
				
			|||||||
  ) }
 | 
					  ) }
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type CreateTeamMutationVariables = {
 | 
				
			||||||
 | 
					  name: Scalars['String'];
 | 
				
			||||||
 | 
					  organizationID: Scalars['UUID'];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type CreateTeamMutation = (
 | 
				
			||||||
 | 
					  { __typename?: 'Mutation' }
 | 
				
			||||||
 | 
					  & { createTeam: (
 | 
				
			||||||
 | 
					    { __typename?: 'Team' }
 | 
				
			||||||
 | 
					    & Pick<Team, 'id' | 'createdAt' | 'name'>
 | 
				
			||||||
 | 
					  ) }
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type ToggleTaskLabelMutationVariables = {
 | 
					export type ToggleTaskLabelMutationVariables = {
 | 
				
			||||||
  taskID: Scalars['UUID'];
 | 
					  taskID: Scalars['UUID'];
 | 
				
			||||||
  projectLabelID: Scalars['UUID'];
 | 
					  projectLabelID: Scalars['UUID'];
 | 
				
			||||||
@@ -1690,6 +1765,10 @@ export type FindTaskLazyQueryHookResult = ReturnType<typeof useFindTaskLazyQuery
 | 
				
			|||||||
export type FindTaskQueryResult = ApolloReactCommon.QueryResult<FindTaskQuery, FindTaskQueryVariables>;
 | 
					export type FindTaskQueryResult = ApolloReactCommon.QueryResult<FindTaskQuery, FindTaskQueryVariables>;
 | 
				
			||||||
export const GetProjectsDocument = gql`
 | 
					export const GetProjectsDocument = gql`
 | 
				
			||||||
    query getProjects {
 | 
					    query getProjects {
 | 
				
			||||||
 | 
					  organizations {
 | 
				
			||||||
 | 
					    id
 | 
				
			||||||
 | 
					    name
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
  teams {
 | 
					  teams {
 | 
				
			||||||
    id
 | 
					    id
 | 
				
			||||||
    name
 | 
					    name
 | 
				
			||||||
@@ -1768,6 +1847,41 @@ 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 DeleteProjectDocument = gql`
 | 
				
			||||||
 | 
					    mutation deleteProject($projectID: UUID!) {
 | 
				
			||||||
 | 
					  deleteProject(input: {projectID: $projectID}) {
 | 
				
			||||||
 | 
					    ok
 | 
				
			||||||
 | 
					    project {
 | 
				
			||||||
 | 
					      id
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					    `;
 | 
				
			||||||
 | 
					export type DeleteProjectMutationFn = ApolloReactCommon.MutationFunction<DeleteProjectMutation, DeleteProjectMutationVariables>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * __useDeleteProjectMutation__
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * To run a mutation, you first call `useDeleteProjectMutation` within a React component and pass it any options that fit your needs.
 | 
				
			||||||
 | 
					 * When your component renders, `useDeleteProjectMutation` 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 [deleteProjectMutation, { data, loading, error }] = useDeleteProjectMutation({
 | 
				
			||||||
 | 
					 *   variables: {
 | 
				
			||||||
 | 
					 *      projectID: // value for 'projectID'
 | 
				
			||||||
 | 
					 *   },
 | 
				
			||||||
 | 
					 * });
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export function useDeleteProjectMutation(baseOptions?: ApolloReactHooks.MutationHookOptions<DeleteProjectMutation, DeleteProjectMutationVariables>) {
 | 
				
			||||||
 | 
					        return ApolloReactHooks.useMutation<DeleteProjectMutation, DeleteProjectMutationVariables>(DeleteProjectDocument, baseOptions);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					export type DeleteProjectMutationHookResult = ReturnType<typeof useDeleteProjectMutation>;
 | 
				
			||||||
 | 
					export type DeleteProjectMutationResult = ApolloReactCommon.MutationResult<DeleteProjectMutation>;
 | 
				
			||||||
 | 
					export type DeleteProjectMutationOptions = ApolloReactCommon.BaseMutationOptions<DeleteProjectMutation, DeleteProjectMutationVariables>;
 | 
				
			||||||
export const CreateTaskChecklistItemDocument = gql`
 | 
					export const CreateTaskChecklistItemDocument = gql`
 | 
				
			||||||
    mutation createTaskChecklistItem($taskChecklistID: UUID!, $name: String!, $position: Float!) {
 | 
					    mutation createTaskChecklistItem($taskChecklistID: UUID!, $name: String!, $position: Float!) {
 | 
				
			||||||
  createTaskChecklistItem(input: {taskChecklistID: $taskChecklistID, name: $name, position: $position}) {
 | 
					  createTaskChecklistItem(input: {taskChecklistID: $taskChecklistID, name: $name, position: $position}) {
 | 
				
			||||||
@@ -1980,6 +2094,41 @@ export function useUpdateTaskGroupNameMutation(baseOptions?: ApolloReactHooks.Mu
 | 
				
			|||||||
export type UpdateTaskGroupNameMutationHookResult = ReturnType<typeof useUpdateTaskGroupNameMutation>;
 | 
					export type UpdateTaskGroupNameMutationHookResult = ReturnType<typeof useUpdateTaskGroupNameMutation>;
 | 
				
			||||||
export type UpdateTaskGroupNameMutationResult = ApolloReactCommon.MutationResult<UpdateTaskGroupNameMutation>;
 | 
					export type UpdateTaskGroupNameMutationResult = ApolloReactCommon.MutationResult<UpdateTaskGroupNameMutation>;
 | 
				
			||||||
export type UpdateTaskGroupNameMutationOptions = ApolloReactCommon.BaseMutationOptions<UpdateTaskGroupNameMutation, UpdateTaskGroupNameMutationVariables>;
 | 
					export type UpdateTaskGroupNameMutationOptions = ApolloReactCommon.BaseMutationOptions<UpdateTaskGroupNameMutation, UpdateTaskGroupNameMutationVariables>;
 | 
				
			||||||
 | 
					export const CreateTeamDocument = gql`
 | 
				
			||||||
 | 
					    mutation createTeam($name: String!, $organizationID: UUID!) {
 | 
				
			||||||
 | 
					  createTeam(input: {name: $name, organizationID: $organizationID}) {
 | 
				
			||||||
 | 
					    id
 | 
				
			||||||
 | 
					    createdAt
 | 
				
			||||||
 | 
					    name
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					    `;
 | 
				
			||||||
 | 
					export type CreateTeamMutationFn = ApolloReactCommon.MutationFunction<CreateTeamMutation, CreateTeamMutationVariables>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * __useCreateTeamMutation__
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * To run a mutation, you first call `useCreateTeamMutation` within a React component and pass it any options that fit your needs.
 | 
				
			||||||
 | 
					 * When your component renders, `useCreateTeamMutation` 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 [createTeamMutation, { data, loading, error }] = useCreateTeamMutation({
 | 
				
			||||||
 | 
					 *   variables: {
 | 
				
			||||||
 | 
					 *      name: // value for 'name'
 | 
				
			||||||
 | 
					 *      organizationID: // value for 'organizationID'
 | 
				
			||||||
 | 
					 *   },
 | 
				
			||||||
 | 
					 * });
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export function useCreateTeamMutation(baseOptions?: ApolloReactHooks.MutationHookOptions<CreateTeamMutation, CreateTeamMutationVariables>) {
 | 
				
			||||||
 | 
					        return ApolloReactHooks.useMutation<CreateTeamMutation, CreateTeamMutationVariables>(CreateTeamDocument, baseOptions);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					export type CreateTeamMutationHookResult = ReturnType<typeof useCreateTeamMutation>;
 | 
				
			||||||
 | 
					export type CreateTeamMutationResult = ApolloReactCommon.MutationResult<CreateTeamMutation>;
 | 
				
			||||||
 | 
					export type CreateTeamMutationOptions = ApolloReactCommon.BaseMutationOptions<CreateTeamMutation, CreateTeamMutationVariables>;
 | 
				
			||||||
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}) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,8 @@
 | 
				
			|||||||
query getProjects {
 | 
					query getProjects {
 | 
				
			||||||
 | 
					  organizations {
 | 
				
			||||||
 | 
					    id
 | 
				
			||||||
 | 
					    name
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
  teams {
 | 
					  teams {
 | 
				
			||||||
    id
 | 
					    id
 | 
				
			||||||
    name
 | 
					    name
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										14
									
								
								web/src/shared/graphql/project/deleteProject.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								web/src/shared/graphql/project/deleteProject.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					import gql from 'graphql-tag';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const DELETE_PROJECT_MUTATION = gql`
 | 
				
			||||||
 | 
					  mutation deleteProject($projectID: UUID!) {
 | 
				
			||||||
 | 
					    deleteProject(input: { projectID: $projectID }) {
 | 
				
			||||||
 | 
					      ok
 | 
				
			||||||
 | 
					      project {
 | 
				
			||||||
 | 
					        id
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default DELETE_PROJECT_MUTATION;
 | 
				
			||||||
							
								
								
									
										13
									
								
								web/src/shared/graphql/team/createTeam.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								web/src/shared/graphql/team/createTeam.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					import gql from 'graphql-tag';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const CREATE_TEAM_MUTATION = gql`
 | 
				
			||||||
 | 
					  mutation createTeam($name: String!, $organizationID: UUID!) {
 | 
				
			||||||
 | 
					    createTeam(input: { name: $name, organizationID: $organizationID }) {
 | 
				
			||||||
 | 
					      id
 | 
				
			||||||
 | 
					      createdAt
 | 
				
			||||||
 | 
					      name
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default CREATE_TEAM_MUTATION;
 | 
				
			||||||
		Reference in New Issue
	
	Block a user