Show domain connected status in overview tab (#58)

* Implement functionality to visit deployment

* Check and display domain details in overview tab for production branch

* Update fixtures to remove project name from deployment url

* Refactor and add uuid to typeorm entities

* Fix deployment url

* Display live domain details in project overview

* Use database query to fetch live production domain
This commit is contained in:
2024-02-06 19:11:53 +05:30
committed by GitHub
parent c0cee2c57f
commit 6d1a48905a
18 changed files with 109 additions and 80 deletions
+1 -1
View File
@@ -3,6 +3,6 @@ export const DEFAULT_CONFIG_FILE_PATH = 'environments/local.toml';
export const DEFAULT_GQL_PATH = '/graphql';
// Note: temporary hardcoded user, later to be derived from auth token
export const USER_ID = 1;
export const USER_ID = '59f4355d-9549-4aac-9b54-eeefceeabef0';
export const PROJECT_DOMAIN = 'snowball.xyz';
+14 -14
View File
@@ -48,15 +48,15 @@ export class Database {
return user;
}
async updateUser (userId: number, data: DeepPartial<User>): Promise<boolean> {
async updateUser (userId: string, data: DeepPartial<User>): Promise<boolean> {
const userRepository = this.dataSource.getRepository(User);
const updateResult = await userRepository.update({ id: Number(userId) }, data);
const updateResult = await userRepository.update({ id: userId }, data);
assert(updateResult.affected);
return updateResult.affected > 0;
}
async getOrganizationsByUserId (userId: number): Promise<Organization[]> {
async getOrganizationsByUserId (userId: string): Promise<Organization[]> {
const organizationRepository = this.dataSource.getRepository(Organization);
const userOrgs = await organizationRepository.find({
@@ -72,7 +72,7 @@ export class Database {
return userOrgs;
}
async getProjectsByOrganizationId (organizationId: number): Promise<Project[]> {
async getProjectsByOrganizationId (organizationId: string): Promise<Project[]> {
const projectRepository = this.dataSource.getRepository(Project);
const projects = await projectRepository.find({
@@ -203,7 +203,7 @@ export class Database {
async removeProjectMemberById (projectMemberId: string): Promise<boolean> {
const projectMemberRepository = this.dataSource.getRepository(ProjectMember);
const deleteResult = await projectMemberRepository.delete({ id: Number(projectMemberId) });
const deleteResult = await projectMemberRepository.delete({ id: projectMemberId });
if (deleteResult.affected) {
return deleteResult.affected > 0;
@@ -214,7 +214,7 @@ export class Database {
async updateProjectMemberById (projectMemberId: string, data: DeepPartial<ProjectMember>): Promise<boolean> {
const projectMemberRepository = this.dataSource.getRepository(ProjectMember);
const updateResult = await projectMemberRepository.update({ id: Number(projectMemberId) }, data);
const updateResult = await projectMemberRepository.update({ id: projectMemberId }, data);
return Boolean(updateResult.affected);
}
@@ -235,14 +235,14 @@ export class Database {
async updateEnvironmentVariable (environmentVariableId: string, update: DeepPartial<EnvironmentVariable>): Promise<boolean> {
const environmentVariableRepository = this.dataSource.getRepository(EnvironmentVariable);
const updateResult = await environmentVariableRepository.update({ id: Number(environmentVariableId) }, update);
const updateResult = await environmentVariableRepository.update({ id: environmentVariableId }, update);
return Boolean(updateResult.affected);
}
async deleteEnvironmentVariable (environmentVariableId: string): Promise<boolean> {
const environmentVariableRepository = this.dataSource.getRepository(EnvironmentVariable);
const deleteResult = await environmentVariableRepository.delete({ id: Number(environmentVariableId) });
const deleteResult = await environmentVariableRepository.delete({ id: environmentVariableId });
if (deleteResult.affected) {
return deleteResult.affected > 0;
@@ -262,7 +262,7 @@ export class Database {
member: true
},
where: {
id: Number(projectMemberId)
id: projectMemberId
}
}
);
@@ -274,7 +274,7 @@ export class Database {
return projectMemberWithProject[0];
}
async getProjectsBySearchText (userId: number, searchText: string): Promise<Project[]> {
async getProjectsBySearchText (userId: string, searchText: string): Promise<Project[]> {
const projectRepository = this.dataSource.getRepository(Project);
const projects = await projectRepository
@@ -308,11 +308,11 @@ export class Database {
newProject.icon = '';
newProject.owner = Object.assign(new User(), {
id: Number(userId)
id: userId
});
newProject.organization = Object.assign(new Organization(), {
id: Number(projectDetails.organizationId)
id: projectDetails.organizationId
});
newProject.subDomain = `${newProject.name}.${PROJECT_DOMAIN}`;
@@ -346,7 +346,7 @@ export class Database {
async deleteDomainById (domainId: string): Promise<boolean> {
const domainRepository = this.dataSource.getRepository(Domain);
const deleteResult = await domainRepository.softDelete({ id: Number(domainId) });
const deleteResult = await domainRepository.softDelete({ id: domainId });
if (deleteResult.affected) {
return deleteResult.affected > 0;
@@ -371,7 +371,7 @@ export class Database {
async updateDomainById (domainId: string, updates: DeepPartial<Domain>): Promise<boolean> {
const domainRepository = this.dataSource.getRepository(Domain);
const updateResult = await domainRepository.update({ id: Number(domainId) }, updates);
const updateResult = await domainRepository.update({ id: domainId }, updates);
return Boolean(updateResult.affected);
}
+4 -4
View File
@@ -18,8 +18,8 @@ export enum Status {
@Entity()
export class Domain {
@PrimaryGeneratedColumn()
id!: number;
@PrimaryGeneratedColumn('uuid')
id!: string;
@Column('varchar')
projectId!: string;
@@ -34,8 +34,8 @@ export class Domain {
@Column('varchar', { length: 255 })
name!: string;
@Column('int', { nullable: true })
redirectToId!: number | null;
@Column('string', { nullable: true })
redirectToId!: string | null;
@ManyToOne(() => Domain)
@JoinColumn({ name: 'redirectToId' })
@@ -18,8 +18,8 @@ enum Environment {
@Entity()
export class EnvironmentVariable {
@PrimaryGeneratedColumn()
id!: number;
@PrimaryGeneratedColumn('uuid')
id!: string;
@ManyToOne(() => Project, { onDelete: 'CASCADE' })
@JoinColumn({ name: 'projectId' })
+2 -2
View File
@@ -10,8 +10,8 @@ import { UserOrganization } from './UserOrganization';
@Entity()
export class Organization {
@PrimaryGeneratedColumn()
id!: number;
@PrimaryGeneratedColumn('uuid')
id!: string;
@Column('varchar', { length: 255 })
name!: string;
+2 -2
View File
@@ -28,8 +28,8 @@ export class Project {
@JoinColumn({ name: 'organizationId' })
organization!: Organization | null;
@Column('integer')
organizationId!: number;
@Column('varchar')
organizationId!: string;
@Column('varchar')
name!: string;
+2 -2
View File
@@ -21,8 +21,8 @@ export enum Permission {
@Entity()
@Unique(['project', 'member'])
export class ProjectMember {
@PrimaryGeneratedColumn()
id!: number;
@PrimaryGeneratedColumn('uuid')
id!: string;
@ManyToOne(() => User, (user) => user.projectMembers)
@JoinColumn({ name: 'userId' })
+2 -2
View File
@@ -13,8 +13,8 @@ import { UserOrganization } from './UserOrganization';
@Entity()
@Unique(['email'])
export class User {
@PrimaryGeneratedColumn()
id!: number;
@PrimaryGeneratedColumn('uuid')
id!: string;
@Column('varchar', { length: 255, nullable: true })
name!: string | null;
@@ -20,8 +20,8 @@ enum Role {
@Entity()
export class UserOrganization {
@PrimaryGeneratedColumn()
id!: number;
@PrimaryGeneratedColumn('uuid')
id!: string;
@ManyToOne(() => User)
@JoinColumn({ name: 'userId' })
+1
View File
@@ -169,6 +169,7 @@ input UpdateProjectMemberInput {
input FilterDomainsInput {
branch: String
status: DomainStatus
}
type Query {
+10 -9
View File
@@ -11,6 +11,7 @@ import { Organization } from './entity/Organization';
import { Project } from './entity/Project';
import { Permission, ProjectMember } from './entity/ProjectMember';
import { User } from './entity/User';
import { PROJECT_DOMAIN } from './constants';
const nanoid = customAlphabet(lowercase + numbers, 8);
@@ -21,7 +22,7 @@ export class Service {
this.db = db;
}
async getUser (userId: number): Promise<User | null> {
async getUser (userId: string): Promise<User | null> {
return this.db.getUser({
where: {
id: userId
@@ -29,7 +30,7 @@ export class Service {
});
}
async getOrganizationsByUserId (userId: number): Promise<Organization[]> {
async getOrganizationsByUserId (userId: string): Promise<Organization[]> {
const dbOrganizations = await this.db.getOrganizationsByUserId(userId);
return dbOrganizations;
}
@@ -59,8 +60,8 @@ export class Service {
return dbProjectMembers;
}
async searchProjects (userId:string, searchText: string): Promise<Project[]> {
const dbProjects = await this.db.getProjectsBySearchText(Number(userId), searchText);
async searchProjects (userId: string, searchText: string): Promise<Project[]> {
const dbProjects = await this.db.getProjectsBySearchText(userId, searchText);
return dbProjects;
}
@@ -196,7 +197,7 @@ export class Service {
async deleteDomain (domainId: string): Promise<boolean> {
const domainsRedirectedFrom = await this.db.getDomains({
where: {
redirectToId: Number(domainId)
redirectToId: domainId
}
});
@@ -229,12 +230,12 @@ export class Service {
// TODO: Put isCurrent field in project
updatedDeployment.isCurrent = true;
updatedDeployment.createdBy = Object.assign(new User(), {
id: Number(userId)
id: userId
});
}
updatedDeployment.id = nanoid();
updatedDeployment.url = `${updatedDeployment.id}-${updatedDeployment.project.subDomain}`;
updatedDeployment.url = `${updatedDeployment.project.name}-${updatedDeployment.id}.${PROJECT_DOMAIN}`;
const oldDeployment = await this.db.updateDeploymentById(deploymentId, { domain: null, isCurrent: false });
const newDeployement = await this.db.addDeployement(updatedDeployment);
@@ -302,7 +303,7 @@ export class Service {
async updateDomain (domainId: string, domainDetails: DeepPartial<Domain>): Promise<boolean> {
const domain = await this.db.getDomain({
where: {
id: Number(domainId)
id: domainId
}
});
@@ -331,7 +332,7 @@ export class Service {
if (domainDetails.redirectToId) {
const redirectedDomain = await this.db.getDomain({
where: {
id: Number(domainDetails.redirectToId)
id: domainDetails.redirectToId
}
});
+10 -10
View File
@@ -10,7 +10,7 @@
"isCurrent": true,
"branch": "main",
"commitHash": "testXyz",
"url": "testProject-ffhae3zq.testProject.snowball.xyz"
"url": "testProject-ffhae3zq.snowball.xyz"
},
{
"projectIndex": 0,
@@ -23,7 +23,7 @@
"isCurrent": false,
"branch": "test",
"commitHash": "testXyz",
"url": "testProject-vehagei8.testProject.snowball.xyz"
"url": "testProject-vehagei8.snowball.xyz"
},
{
"projectIndex": 0,
@@ -36,7 +36,7 @@
"isCurrent": false,
"branch": "test",
"commitHash": "testXyz",
"url": "testProject-qmgekyte.testProject.snowball.xyz"
"url": "testProject-qmgekyte.snowball.xyz"
},
{
"projectIndex": 0,
@@ -49,7 +49,7 @@
"isCurrent": false,
"branch": "prod",
"commitHash": "testXyz",
"url": "testProject-f8wsyim6.testProject.snowball.xyz"
"url": "testProject-f8wsyim6.snowball.xyz"
},
{
"projectIndex": 1,
@@ -62,7 +62,7 @@
"isCurrent": true,
"branch": "main",
"commitHash": "testXyz",
"url": "testProject-2-eO8cckxk.testProject-2.snowball.xyz"
"url": "testProject-2-eO8cckxk.snowball.xyz"
},
{
"projectIndex": 1,
@@ -75,7 +75,7 @@
"isCurrent": false,
"branch": "test",
"commitHash": "testXyz",
"url": "testProject-2-yaq0t5yw.testProject-2.snowball.xyz"
"url": "testProject-2-yaq0t5yw.snowball.xyz"
},
{
"projectIndex": 1,
@@ -88,7 +88,7 @@
"isCurrent": false,
"branch": "test",
"commitHash": "testXyz",
"url": "testProject-2-hwwr6sbx.testProject-2.snowball.xyz"
"url": "testProject-2-hwwr6sbx.snowball.xyz"
},
{
"projectIndex": 2,
@@ -101,7 +101,7 @@
"isCurrent": true,
"branch": "main",
"commitHash": "testXyz",
"url": "iglootools-ndxje48a.iglootools.snowball.xyz"
"url": "iglootools-ndxje48a.snowball.xyz"
},
{
"projectIndex": 2,
@@ -114,7 +114,7 @@
"isCurrent": false,
"branch": "test",
"commitHash": "testXyz",
"url": "iglootools-gtgpgvei.iglootools.snowball.xyz"
"url": "iglootools-gtgpgvei.snowball.xyz"
},
{
"projectIndex": 2,
@@ -127,6 +127,6 @@
"isCurrent": false,
"branch": "test",
"commitHash": "testXyz",
"url": "iglootools-b4bpthjr.iglootools.snowball.xyz"
"url": "iglootools-b4bpthjr.snowball.xyz"
}
]
+3
View File
@@ -1,15 +1,18 @@
[
{
"id": "59f4355d-9549-4aac-9b54-eeefceeabef0",
"name": "Saugat Yadav",
"email": "saugaty@airfoil.studio",
"isVerified": true
},
{
"id": "e505b212-8da6-48b2-9614-098225dab34b",
"name": "Gideon Low",
"email": "gideonl@airfoil.studio",
"isVerified": true
},
{
"id": "cd892fad-9138-4aa2-a62c-414a32776ea7",
"name": "Sushan Yadav",
"email": "sushany@airfoil.studio",
"isVerified": true