forked from cerc-io/snowballtools-base
Implement organization switcher and use slug in URL (#59)
* Implement dropdown for organizations switcher * Add dynamic route for organization id * Update routes for organization slug * Use organization slug for adding project * Refactor to fetch organizations at sidebar component * Update organization switcher based on searched project * Refactor types in frontend --------- Co-authored-by: neeraj <neeraj.rtly@gmail.com>
This commit is contained in:
@@ -56,6 +56,13 @@ export class Database {
|
||||
return updateResult.affected > 0;
|
||||
}
|
||||
|
||||
async getOrganization (options: FindOneOptions<Organization>): Promise<Organization | null> {
|
||||
const organizationRepository = this.dataSource.getRepository(Organization);
|
||||
const organization = await organizationRepository.findOne(options);
|
||||
|
||||
return organization;
|
||||
}
|
||||
|
||||
async getOrganizationsByUserId (userId: string): Promise<Organization[]> {
|
||||
const organizationRepository = this.dataSource.getRepository(Organization);
|
||||
|
||||
@@ -108,7 +115,7 @@ export class Database {
|
||||
return project;
|
||||
}
|
||||
|
||||
async getProjectsInOrganization (userId: string, organizationId: string): Promise<Project[]> {
|
||||
async getProjectsInOrganization (userId: string, organizationSlug: string): Promise<Project[]> {
|
||||
const projectRepository = this.dataSource.getRepository(Project);
|
||||
|
||||
const projects = await projectRepository
|
||||
@@ -116,9 +123,10 @@ export class Database {
|
||||
.leftJoinAndSelect('project.deployments', 'deployments', 'deployments.isCurrent = true')
|
||||
.leftJoinAndSelect('deployments.domain', 'domain')
|
||||
.leftJoin('project.projectMembers', 'projectMembers')
|
||||
.where('(project.ownerId = :userId OR projectMembers.userId = :userId) AND project.organizationId = :organizationId', {
|
||||
.leftJoin('project.organization', 'organization')
|
||||
.where('(project.ownerId = :userId OR projectMembers.userId = :userId) AND organization.slug = :organizationSlug', {
|
||||
userId,
|
||||
organizationId
|
||||
organizationSlug
|
||||
})
|
||||
.getMany();
|
||||
|
||||
@@ -297,7 +305,7 @@ export class Database {
|
||||
return Boolean(updateResult.affected);
|
||||
}
|
||||
|
||||
async addProject (userId: string, projectDetails: DeepPartial<Project>): Promise<Project> {
|
||||
async addProject (userId: string, organizationId: string, projectDetails: DeepPartial<Project>): Promise<Project> {
|
||||
const projectRepository = this.dataSource.getRepository(Project);
|
||||
|
||||
// TODO: Check if organization exists
|
||||
@@ -312,7 +320,7 @@ export class Database {
|
||||
});
|
||||
|
||||
newProject.organization = Object.assign(new Organization(), {
|
||||
id: projectDetails.organizationId
|
||||
id: organizationId
|
||||
});
|
||||
|
||||
newProject.subDomain = `${newProject.name}.${PROJECT_DOMAIN}`;
|
||||
|
||||
@@ -4,11 +4,13 @@ import {
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
UpdateDateColumn,
|
||||
OneToMany
|
||||
OneToMany,
|
||||
Unique
|
||||
} from 'typeorm';
|
||||
import { UserOrganization } from './UserOrganization';
|
||||
|
||||
@Entity()
|
||||
@Unique(['slug'])
|
||||
export class Organization {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id!: string;
|
||||
@@ -16,6 +18,9 @@ export class Organization {
|
||||
@Column('varchar', { length: 255 })
|
||||
name!: string;
|
||||
|
||||
@Column('varchar')
|
||||
slug!: string;
|
||||
|
||||
@CreateDateColumn()
|
||||
createdAt!: Date;
|
||||
|
||||
|
||||
@@ -29,8 +29,8 @@ export const createResolvers = async (db: Database, app: OAuthApp, service: Serv
|
||||
return service.getProjectById(projectId);
|
||||
},
|
||||
|
||||
projectsInOrganization: async (_: any, { organizationId }: {organizationId: string }, context: any) => {
|
||||
return service.getProjectsInOrganization(context.userId, organizationId);
|
||||
projectsInOrganization: async (_: any, { organizationSlug }: {organizationSlug: string }, context: any) => {
|
||||
return service.getProjectsInOrganization(context.userId, organizationSlug);
|
||||
},
|
||||
|
||||
deployments: async (_: any, { projectId }: { projectId: string }) => {
|
||||
@@ -130,9 +130,9 @@ export const createResolvers = async (db: Database, app: OAuthApp, service: Serv
|
||||
}
|
||||
},
|
||||
|
||||
addProject: async (_: any, { data }: { data: DeepPartial<Project> }, context: any) => {
|
||||
addProject: async (_: any, { organizationSlug, data }: { organizationSlug: string, data: DeepPartial<Project> }, context: any) => {
|
||||
try {
|
||||
return service.addProject(context.userId, data);
|
||||
return service.addProject(context.userId, organizationSlug, data);
|
||||
} catch (err) {
|
||||
log(err);
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ type User {
|
||||
type Organization {
|
||||
id: String!
|
||||
name: String!
|
||||
slug: String!
|
||||
projects: [Project!]
|
||||
createdAt: String!
|
||||
updatedAt: String!
|
||||
@@ -129,7 +130,6 @@ input AddEnvironmentVariableInput {
|
||||
}
|
||||
|
||||
input AddProjectInput {
|
||||
organizationId: String!
|
||||
name: String!
|
||||
repository: String!
|
||||
prodBranch: String!
|
||||
@@ -176,7 +176,7 @@ type Query {
|
||||
user: User!
|
||||
organizations: [Organization!]
|
||||
projects: [Project!]
|
||||
projectsInOrganization(organizationId: String!): [Project!]
|
||||
projectsInOrganization(organizationSlug: String!): [Project!]
|
||||
project(projectId: String!): Project
|
||||
deployments(projectId: String!): [Deployment!]
|
||||
environmentVariables(projectId: String!): [EnvironmentVariable!]
|
||||
@@ -193,7 +193,7 @@ type Mutation {
|
||||
updateEnvironmentVariable(environmentVariableId: String!, data: UpdateEnvironmentVariableInput!): Boolean!
|
||||
removeEnvironmentVariable(environmentVariableId: String!): Boolean!
|
||||
updateDeploymentToProd(deploymentId: String!): Boolean!
|
||||
addProject(data: AddProjectInput): Project!
|
||||
addProject(organizationSlug: String!, data: AddProjectInput): Project!
|
||||
updateProject(projectId: String!, projectDetails: UpdateProjectInput): Boolean!
|
||||
redeployToProd(deploymentId: String!): Boolean!
|
||||
deleteProject(projectId: String!): Boolean!
|
||||
|
||||
@@ -40,8 +40,8 @@ export class Service {
|
||||
return dbProject;
|
||||
}
|
||||
|
||||
async getProjectsInOrganization (userId:string, organizationId: string): Promise<Project[]> {
|
||||
const dbProjects = await this.db.getProjectsInOrganization(userId, organizationId);
|
||||
async getProjectsInOrganization (userId:string, organizationSlug: string): Promise<Project[]> {
|
||||
const dbProjects = await this.db.getProjectsInOrganization(userId, organizationSlug);
|
||||
return dbProjects;
|
||||
}
|
||||
|
||||
@@ -182,8 +182,17 @@ export class Service {
|
||||
return updateResult;
|
||||
}
|
||||
|
||||
async addProject (userId: string, data: DeepPartial<Project>): Promise<Project | undefined> {
|
||||
return this.db.addProject(userId, data);
|
||||
async addProject (userId: string, organizationSlug: string, data: DeepPartial<Project>): Promise<Project | undefined> {
|
||||
const organization = await this.db.getOrganization({
|
||||
where: {
|
||||
slug: organizationSlug
|
||||
}
|
||||
});
|
||||
if (!organization) {
|
||||
throw new Error('Organization does not exist');
|
||||
}
|
||||
|
||||
return this.db.addProject(userId, organization.id, data);
|
||||
}
|
||||
|
||||
async updateProject (projectId: string, data: DeepPartial<Project>): Promise<boolean> {
|
||||
|
||||
+4
-2
@@ -1,8 +1,10 @@
|
||||
[
|
||||
{
|
||||
"name": "Snowball Tools"
|
||||
"name": "Snowball Tools",
|
||||
"slug": "snowball-tools"
|
||||
},
|
||||
{
|
||||
"name": "AirFoil"
|
||||
"name": "AirFoil",
|
||||
"slug": "airfoil"
|
||||
}
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user