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:
parent
c0cee2c57f
commit
6d1a48905a
@ -3,6 +3,6 @@ export const DEFAULT_CONFIG_FILE_PATH = 'environments/local.toml';
|
|||||||
export const DEFAULT_GQL_PATH = '/graphql';
|
export const DEFAULT_GQL_PATH = '/graphql';
|
||||||
|
|
||||||
// Note: temporary hardcoded user, later to be derived from auth token
|
// 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';
|
export const PROJECT_DOMAIN = 'snowball.xyz';
|
||||||
|
@ -48,15 +48,15 @@ export class Database {
|
|||||||
return user;
|
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 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);
|
assert(updateResult.affected);
|
||||||
|
|
||||||
return updateResult.affected > 0;
|
return updateResult.affected > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getOrganizationsByUserId (userId: number): Promise<Organization[]> {
|
async getOrganizationsByUserId (userId: string): Promise<Organization[]> {
|
||||||
const organizationRepository = this.dataSource.getRepository(Organization);
|
const organizationRepository = this.dataSource.getRepository(Organization);
|
||||||
|
|
||||||
const userOrgs = await organizationRepository.find({
|
const userOrgs = await organizationRepository.find({
|
||||||
@ -72,7 +72,7 @@ export class Database {
|
|||||||
return userOrgs;
|
return userOrgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getProjectsByOrganizationId (organizationId: number): Promise<Project[]> {
|
async getProjectsByOrganizationId (organizationId: string): Promise<Project[]> {
|
||||||
const projectRepository = this.dataSource.getRepository(Project);
|
const projectRepository = this.dataSource.getRepository(Project);
|
||||||
|
|
||||||
const projects = await projectRepository.find({
|
const projects = await projectRepository.find({
|
||||||
@ -203,7 +203,7 @@ export class Database {
|
|||||||
async removeProjectMemberById (projectMemberId: string): Promise<boolean> {
|
async removeProjectMemberById (projectMemberId: string): Promise<boolean> {
|
||||||
const projectMemberRepository = this.dataSource.getRepository(ProjectMember);
|
const projectMemberRepository = this.dataSource.getRepository(ProjectMember);
|
||||||
|
|
||||||
const deleteResult = await projectMemberRepository.delete({ id: Number(projectMemberId) });
|
const deleteResult = await projectMemberRepository.delete({ id: projectMemberId });
|
||||||
|
|
||||||
if (deleteResult.affected) {
|
if (deleteResult.affected) {
|
||||||
return deleteResult.affected > 0;
|
return deleteResult.affected > 0;
|
||||||
@ -214,7 +214,7 @@ export class Database {
|
|||||||
|
|
||||||
async updateProjectMemberById (projectMemberId: string, data: DeepPartial<ProjectMember>): Promise<boolean> {
|
async updateProjectMemberById (projectMemberId: string, data: DeepPartial<ProjectMember>): Promise<boolean> {
|
||||||
const projectMemberRepository = this.dataSource.getRepository(ProjectMember);
|
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);
|
return Boolean(updateResult.affected);
|
||||||
}
|
}
|
||||||
@ -235,14 +235,14 @@ export class Database {
|
|||||||
|
|
||||||
async updateEnvironmentVariable (environmentVariableId: string, update: DeepPartial<EnvironmentVariable>): Promise<boolean> {
|
async updateEnvironmentVariable (environmentVariableId: string, update: DeepPartial<EnvironmentVariable>): Promise<boolean> {
|
||||||
const environmentVariableRepository = this.dataSource.getRepository(EnvironmentVariable);
|
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);
|
return Boolean(updateResult.affected);
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteEnvironmentVariable (environmentVariableId: string): Promise<boolean> {
|
async deleteEnvironmentVariable (environmentVariableId: string): Promise<boolean> {
|
||||||
const environmentVariableRepository = this.dataSource.getRepository(EnvironmentVariable);
|
const environmentVariableRepository = this.dataSource.getRepository(EnvironmentVariable);
|
||||||
const deleteResult = await environmentVariableRepository.delete({ id: Number(environmentVariableId) });
|
const deleteResult = await environmentVariableRepository.delete({ id: environmentVariableId });
|
||||||
|
|
||||||
if (deleteResult.affected) {
|
if (deleteResult.affected) {
|
||||||
return deleteResult.affected > 0;
|
return deleteResult.affected > 0;
|
||||||
@ -262,7 +262,7 @@ export class Database {
|
|||||||
member: true
|
member: true
|
||||||
},
|
},
|
||||||
where: {
|
where: {
|
||||||
id: Number(projectMemberId)
|
id: projectMemberId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -274,7 +274,7 @@ export class Database {
|
|||||||
return projectMemberWithProject[0];
|
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 projectRepository = this.dataSource.getRepository(Project);
|
||||||
|
|
||||||
const projects = await projectRepository
|
const projects = await projectRepository
|
||||||
@ -308,11 +308,11 @@ export class Database {
|
|||||||
newProject.icon = '';
|
newProject.icon = '';
|
||||||
|
|
||||||
newProject.owner = Object.assign(new User(), {
|
newProject.owner = Object.assign(new User(), {
|
||||||
id: Number(userId)
|
id: userId
|
||||||
});
|
});
|
||||||
|
|
||||||
newProject.organization = Object.assign(new Organization(), {
|
newProject.organization = Object.assign(new Organization(), {
|
||||||
id: Number(projectDetails.organizationId)
|
id: projectDetails.organizationId
|
||||||
});
|
});
|
||||||
|
|
||||||
newProject.subDomain = `${newProject.name}.${PROJECT_DOMAIN}`;
|
newProject.subDomain = `${newProject.name}.${PROJECT_DOMAIN}`;
|
||||||
@ -346,7 +346,7 @@ export class Database {
|
|||||||
async deleteDomainById (domainId: string): Promise<boolean> {
|
async deleteDomainById (domainId: string): Promise<boolean> {
|
||||||
const domainRepository = this.dataSource.getRepository(Domain);
|
const domainRepository = this.dataSource.getRepository(Domain);
|
||||||
|
|
||||||
const deleteResult = await domainRepository.softDelete({ id: Number(domainId) });
|
const deleteResult = await domainRepository.softDelete({ id: domainId });
|
||||||
|
|
||||||
if (deleteResult.affected) {
|
if (deleteResult.affected) {
|
||||||
return deleteResult.affected > 0;
|
return deleteResult.affected > 0;
|
||||||
@ -371,7 +371,7 @@ export class Database {
|
|||||||
|
|
||||||
async updateDomainById (domainId: string, updates: DeepPartial<Domain>): Promise<boolean> {
|
async updateDomainById (domainId: string, updates: DeepPartial<Domain>): Promise<boolean> {
|
||||||
const domainRepository = this.dataSource.getRepository(Domain);
|
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);
|
return Boolean(updateResult.affected);
|
||||||
}
|
}
|
||||||
|
@ -18,8 +18,8 @@ export enum Status {
|
|||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export class Domain {
|
export class Domain {
|
||||||
@PrimaryGeneratedColumn()
|
@PrimaryGeneratedColumn('uuid')
|
||||||
id!: number;
|
id!: string;
|
||||||
|
|
||||||
@Column('varchar')
|
@Column('varchar')
|
||||||
projectId!: string;
|
projectId!: string;
|
||||||
@ -34,8 +34,8 @@ export class Domain {
|
|||||||
@Column('varchar', { length: 255 })
|
@Column('varchar', { length: 255 })
|
||||||
name!: string;
|
name!: string;
|
||||||
|
|
||||||
@Column('int', { nullable: true })
|
@Column('string', { nullable: true })
|
||||||
redirectToId!: number | null;
|
redirectToId!: string | null;
|
||||||
|
|
||||||
@ManyToOne(() => Domain)
|
@ManyToOne(() => Domain)
|
||||||
@JoinColumn({ name: 'redirectToId' })
|
@JoinColumn({ name: 'redirectToId' })
|
||||||
|
@ -18,8 +18,8 @@ enum Environment {
|
|||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export class EnvironmentVariable {
|
export class EnvironmentVariable {
|
||||||
@PrimaryGeneratedColumn()
|
@PrimaryGeneratedColumn('uuid')
|
||||||
id!: number;
|
id!: string;
|
||||||
|
|
||||||
@ManyToOne(() => Project, { onDelete: 'CASCADE' })
|
@ManyToOne(() => Project, { onDelete: 'CASCADE' })
|
||||||
@JoinColumn({ name: 'projectId' })
|
@JoinColumn({ name: 'projectId' })
|
||||||
|
@ -10,8 +10,8 @@ import { UserOrganization } from './UserOrganization';
|
|||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export class Organization {
|
export class Organization {
|
||||||
@PrimaryGeneratedColumn()
|
@PrimaryGeneratedColumn('uuid')
|
||||||
id!: number;
|
id!: string;
|
||||||
|
|
||||||
@Column('varchar', { length: 255 })
|
@Column('varchar', { length: 255 })
|
||||||
name!: string;
|
name!: string;
|
||||||
|
@ -28,8 +28,8 @@ export class Project {
|
|||||||
@JoinColumn({ name: 'organizationId' })
|
@JoinColumn({ name: 'organizationId' })
|
||||||
organization!: Organization | null;
|
organization!: Organization | null;
|
||||||
|
|
||||||
@Column('integer')
|
@Column('varchar')
|
||||||
organizationId!: number;
|
organizationId!: string;
|
||||||
|
|
||||||
@Column('varchar')
|
@Column('varchar')
|
||||||
name!: string;
|
name!: string;
|
||||||
|
@ -21,8 +21,8 @@ export enum Permission {
|
|||||||
@Entity()
|
@Entity()
|
||||||
@Unique(['project', 'member'])
|
@Unique(['project', 'member'])
|
||||||
export class ProjectMember {
|
export class ProjectMember {
|
||||||
@PrimaryGeneratedColumn()
|
@PrimaryGeneratedColumn('uuid')
|
||||||
id!: number;
|
id!: string;
|
||||||
|
|
||||||
@ManyToOne(() => User, (user) => user.projectMembers)
|
@ManyToOne(() => User, (user) => user.projectMembers)
|
||||||
@JoinColumn({ name: 'userId' })
|
@JoinColumn({ name: 'userId' })
|
||||||
|
@ -13,8 +13,8 @@ import { UserOrganization } from './UserOrganization';
|
|||||||
@Entity()
|
@Entity()
|
||||||
@Unique(['email'])
|
@Unique(['email'])
|
||||||
export class User {
|
export class User {
|
||||||
@PrimaryGeneratedColumn()
|
@PrimaryGeneratedColumn('uuid')
|
||||||
id!: number;
|
id!: string;
|
||||||
|
|
||||||
@Column('varchar', { length: 255, nullable: true })
|
@Column('varchar', { length: 255, nullable: true })
|
||||||
name!: string | null;
|
name!: string | null;
|
||||||
|
@ -20,8 +20,8 @@ enum Role {
|
|||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export class UserOrganization {
|
export class UserOrganization {
|
||||||
@PrimaryGeneratedColumn()
|
@PrimaryGeneratedColumn('uuid')
|
||||||
id!: number;
|
id!: string;
|
||||||
|
|
||||||
@ManyToOne(() => User)
|
@ManyToOne(() => User)
|
||||||
@JoinColumn({ name: 'userId' })
|
@JoinColumn({ name: 'userId' })
|
||||||
|
@ -169,6 +169,7 @@ input UpdateProjectMemberInput {
|
|||||||
|
|
||||||
input FilterDomainsInput {
|
input FilterDomainsInput {
|
||||||
branch: String
|
branch: String
|
||||||
|
status: DomainStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
type Query {
|
type Query {
|
||||||
|
@ -11,6 +11,7 @@ import { Organization } from './entity/Organization';
|
|||||||
import { Project } from './entity/Project';
|
import { Project } from './entity/Project';
|
||||||
import { Permission, ProjectMember } from './entity/ProjectMember';
|
import { Permission, ProjectMember } from './entity/ProjectMember';
|
||||||
import { User } from './entity/User';
|
import { User } from './entity/User';
|
||||||
|
import { PROJECT_DOMAIN } from './constants';
|
||||||
|
|
||||||
const nanoid = customAlphabet(lowercase + numbers, 8);
|
const nanoid = customAlphabet(lowercase + numbers, 8);
|
||||||
|
|
||||||
@ -21,7 +22,7 @@ export class Service {
|
|||||||
this.db = db;
|
this.db = db;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getUser (userId: number): Promise<User | null> {
|
async getUser (userId: string): Promise<User | null> {
|
||||||
return this.db.getUser({
|
return this.db.getUser({
|
||||||
where: {
|
where: {
|
||||||
id: userId
|
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);
|
const dbOrganizations = await this.db.getOrganizationsByUserId(userId);
|
||||||
return dbOrganizations;
|
return dbOrganizations;
|
||||||
}
|
}
|
||||||
@ -60,7 +61,7 @@ export class Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async searchProjects (userId: string, searchText: string): Promise<Project[]> {
|
async searchProjects (userId: string, searchText: string): Promise<Project[]> {
|
||||||
const dbProjects = await this.db.getProjectsBySearchText(Number(userId), searchText);
|
const dbProjects = await this.db.getProjectsBySearchText(userId, searchText);
|
||||||
return dbProjects;
|
return dbProjects;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,7 +197,7 @@ export class Service {
|
|||||||
async deleteDomain (domainId: string): Promise<boolean> {
|
async deleteDomain (domainId: string): Promise<boolean> {
|
||||||
const domainsRedirectedFrom = await this.db.getDomains({
|
const domainsRedirectedFrom = await this.db.getDomains({
|
||||||
where: {
|
where: {
|
||||||
redirectToId: Number(domainId)
|
redirectToId: domainId
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -229,12 +230,12 @@ export class Service {
|
|||||||
// TODO: Put isCurrent field in project
|
// TODO: Put isCurrent field in project
|
||||||
updatedDeployment.isCurrent = true;
|
updatedDeployment.isCurrent = true;
|
||||||
updatedDeployment.createdBy = Object.assign(new User(), {
|
updatedDeployment.createdBy = Object.assign(new User(), {
|
||||||
id: Number(userId)
|
id: userId
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
updatedDeployment.id = nanoid();
|
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 oldDeployment = await this.db.updateDeploymentById(deploymentId, { domain: null, isCurrent: false });
|
||||||
const newDeployement = await this.db.addDeployement(updatedDeployment);
|
const newDeployement = await this.db.addDeployement(updatedDeployment);
|
||||||
@ -302,7 +303,7 @@ export class Service {
|
|||||||
async updateDomain (domainId: string, domainDetails: DeepPartial<Domain>): Promise<boolean> {
|
async updateDomain (domainId: string, domainDetails: DeepPartial<Domain>): Promise<boolean> {
|
||||||
const domain = await this.db.getDomain({
|
const domain = await this.db.getDomain({
|
||||||
where: {
|
where: {
|
||||||
id: Number(domainId)
|
id: domainId
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -331,7 +332,7 @@ export class Service {
|
|||||||
if (domainDetails.redirectToId) {
|
if (domainDetails.redirectToId) {
|
||||||
const redirectedDomain = await this.db.getDomain({
|
const redirectedDomain = await this.db.getDomain({
|
||||||
where: {
|
where: {
|
||||||
id: Number(domainDetails.redirectToId)
|
id: domainDetails.redirectToId
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
20
packages/backend/test/fixtures/deployments.json
vendored
20
packages/backend/test/fixtures/deployments.json
vendored
@ -10,7 +10,7 @@
|
|||||||
"isCurrent": true,
|
"isCurrent": true,
|
||||||
"branch": "main",
|
"branch": "main",
|
||||||
"commitHash": "testXyz",
|
"commitHash": "testXyz",
|
||||||
"url": "testProject-ffhae3zq.testProject.snowball.xyz"
|
"url": "testProject-ffhae3zq.snowball.xyz"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"projectIndex": 0,
|
"projectIndex": 0,
|
||||||
@ -23,7 +23,7 @@
|
|||||||
"isCurrent": false,
|
"isCurrent": false,
|
||||||
"branch": "test",
|
"branch": "test",
|
||||||
"commitHash": "testXyz",
|
"commitHash": "testXyz",
|
||||||
"url": "testProject-vehagei8.testProject.snowball.xyz"
|
"url": "testProject-vehagei8.snowball.xyz"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"projectIndex": 0,
|
"projectIndex": 0,
|
||||||
@ -36,7 +36,7 @@
|
|||||||
"isCurrent": false,
|
"isCurrent": false,
|
||||||
"branch": "test",
|
"branch": "test",
|
||||||
"commitHash": "testXyz",
|
"commitHash": "testXyz",
|
||||||
"url": "testProject-qmgekyte.testProject.snowball.xyz"
|
"url": "testProject-qmgekyte.snowball.xyz"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"projectIndex": 0,
|
"projectIndex": 0,
|
||||||
@ -49,7 +49,7 @@
|
|||||||
"isCurrent": false,
|
"isCurrent": false,
|
||||||
"branch": "prod",
|
"branch": "prod",
|
||||||
"commitHash": "testXyz",
|
"commitHash": "testXyz",
|
||||||
"url": "testProject-f8wsyim6.testProject.snowball.xyz"
|
"url": "testProject-f8wsyim6.snowball.xyz"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"projectIndex": 1,
|
"projectIndex": 1,
|
||||||
@ -62,7 +62,7 @@
|
|||||||
"isCurrent": true,
|
"isCurrent": true,
|
||||||
"branch": "main",
|
"branch": "main",
|
||||||
"commitHash": "testXyz",
|
"commitHash": "testXyz",
|
||||||
"url": "testProject-2-eO8cckxk.testProject-2.snowball.xyz"
|
"url": "testProject-2-eO8cckxk.snowball.xyz"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"projectIndex": 1,
|
"projectIndex": 1,
|
||||||
@ -75,7 +75,7 @@
|
|||||||
"isCurrent": false,
|
"isCurrent": false,
|
||||||
"branch": "test",
|
"branch": "test",
|
||||||
"commitHash": "testXyz",
|
"commitHash": "testXyz",
|
||||||
"url": "testProject-2-yaq0t5yw.testProject-2.snowball.xyz"
|
"url": "testProject-2-yaq0t5yw.snowball.xyz"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"projectIndex": 1,
|
"projectIndex": 1,
|
||||||
@ -88,7 +88,7 @@
|
|||||||
"isCurrent": false,
|
"isCurrent": false,
|
||||||
"branch": "test",
|
"branch": "test",
|
||||||
"commitHash": "testXyz",
|
"commitHash": "testXyz",
|
||||||
"url": "testProject-2-hwwr6sbx.testProject-2.snowball.xyz"
|
"url": "testProject-2-hwwr6sbx.snowball.xyz"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"projectIndex": 2,
|
"projectIndex": 2,
|
||||||
@ -101,7 +101,7 @@
|
|||||||
"isCurrent": true,
|
"isCurrent": true,
|
||||||
"branch": "main",
|
"branch": "main",
|
||||||
"commitHash": "testXyz",
|
"commitHash": "testXyz",
|
||||||
"url": "iglootools-ndxje48a.iglootools.snowball.xyz"
|
"url": "iglootools-ndxje48a.snowball.xyz"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"projectIndex": 2,
|
"projectIndex": 2,
|
||||||
@ -114,7 +114,7 @@
|
|||||||
"isCurrent": false,
|
"isCurrent": false,
|
||||||
"branch": "test",
|
"branch": "test",
|
||||||
"commitHash": "testXyz",
|
"commitHash": "testXyz",
|
||||||
"url": "iglootools-gtgpgvei.iglootools.snowball.xyz"
|
"url": "iglootools-gtgpgvei.snowball.xyz"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"projectIndex": 2,
|
"projectIndex": 2,
|
||||||
@ -127,6 +127,6 @@
|
|||||||
"isCurrent": false,
|
"isCurrent": false,
|
||||||
"branch": "test",
|
"branch": "test",
|
||||||
"commitHash": "testXyz",
|
"commitHash": "testXyz",
|
||||||
"url": "iglootools-b4bpthjr.iglootools.snowball.xyz"
|
"url": "iglootools-b4bpthjr.snowball.xyz"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
3
packages/backend/test/fixtures/users.json
vendored
3
packages/backend/test/fixtures/users.json
vendored
@ -1,15 +1,18 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
|
"id": "59f4355d-9549-4aac-9b54-eeefceeabef0",
|
||||||
"name": "Saugat Yadav",
|
"name": "Saugat Yadav",
|
||||||
"email": "saugaty@airfoil.studio",
|
"email": "saugaty@airfoil.studio",
|
||||||
"isVerified": true
|
"isVerified": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"id": "e505b212-8da6-48b2-9614-098225dab34b",
|
||||||
"name": "Gideon Low",
|
"name": "Gideon Low",
|
||||||
"email": "gideonl@airfoil.studio",
|
"email": "gideonl@airfoil.studio",
|
||||||
"isVerified": true
|
"isVerified": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"id": "cd892fad-9138-4aa2-a62c-414a32776ea7",
|
||||||
"name": "Sushan Yadav",
|
"name": "Sushan Yadav",
|
||||||
"email": "sushany@airfoil.studio",
|
"email": "sushany@airfoil.studio",
|
||||||
"isVerified": true
|
"isVerified": true
|
||||||
|
@ -4,12 +4,9 @@ import { Tabs, TabsHeader, Tab } from '@material-tailwind/react';
|
|||||||
|
|
||||||
const ConnectAccountTabPanel = () => {
|
const ConnectAccountTabPanel = () => {
|
||||||
return (
|
return (
|
||||||
<Tabs
|
<Tabs className="grid bg-white h-32 p-2 m-4 rounded-md" value="import">
|
||||||
className="grid bg-white h-32 p-2 m-4 rounded-md"
|
|
||||||
value="git repository"
|
|
||||||
>
|
|
||||||
<TabsHeader className="grid grid-cols-2">
|
<TabsHeader className="grid grid-cols-2">
|
||||||
<Tab className="row-span-1" value="git repository">
|
<Tab className="row-span-1" value="import">
|
||||||
Import a repository
|
Import a repository
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab className="row-span-2" value="template">
|
<Tab className="row-span-2" value="template">
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { Project } from 'gql-client';
|
import { Domain, DomainStatus, Project } from 'gql-client';
|
||||||
|
|
||||||
import { Typography, Button, Chip } from '@material-tailwind/react';
|
import { Typography, Button, Chip } from '@material-tailwind/react';
|
||||||
|
|
||||||
@ -7,6 +7,7 @@ import ActivityCard from './ActivityCard';
|
|||||||
import { relativeTimeMs } from '../../../utils/time';
|
import { relativeTimeMs } from '../../../utils/time';
|
||||||
import { useOctokit } from '../../../context/OctokitContext';
|
import { useOctokit } from '../../../context/OctokitContext';
|
||||||
import { GitCommitDetails } from '../../../types/project';
|
import { GitCommitDetails } from '../../../types/project';
|
||||||
|
import { useGQLClient } from '../../../context/GQLClientContext';
|
||||||
|
|
||||||
const COMMITS_PER_PAGE = 4;
|
const COMMITS_PER_PAGE = 4;
|
||||||
|
|
||||||
@ -15,11 +16,13 @@ interface OverviewProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Check if any live domain is set for production branch
|
// TODO: Check if any live domain is set for production branch
|
||||||
const IS_DOMAIN_SETUP = false;
|
|
||||||
|
|
||||||
const OverviewTabPanel = ({ project }: OverviewProps) => {
|
const OverviewTabPanel = ({ project }: OverviewProps) => {
|
||||||
const { octokit } = useOctokit();
|
const { octokit } = useOctokit();
|
||||||
const [activities, setActivities] = useState<GitCommitDetails[]>([]);
|
const [activities, setActivities] = useState<GitCommitDetails[]>([]);
|
||||||
|
const [liveDomain, setLiveDomain] = useState<Domain>();
|
||||||
|
|
||||||
|
const client = useGQLClient();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!octokit) {
|
if (!octokit) {
|
||||||
@ -75,6 +78,23 @@ const OverviewTabPanel = ({ project }: OverviewProps) => {
|
|||||||
fetchRepoActivity();
|
fetchRepoActivity();
|
||||||
}, [octokit, project]);
|
}, [octokit, project]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchLiveProdDomain = async () => {
|
||||||
|
const { domains } = await client.getDomains(project.id, {
|
||||||
|
branch: project.prodBranch,
|
||||||
|
status: DomainStatus.Live,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (domains.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setLiveDomain(domains[0]);
|
||||||
|
};
|
||||||
|
|
||||||
|
fetchLiveProdDomain();
|
||||||
|
}, [project]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="grid grid-cols-5">
|
<div className="grid grid-cols-5">
|
||||||
<div className="col-span-3 p-2">
|
<div className="col-span-3 p-2">
|
||||||
@ -88,19 +108,8 @@ const OverviewTabPanel = ({ project }: OverviewProps) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between p-2 text-sm items-center">
|
<div className="flex justify-between p-2 text-sm items-center">
|
||||||
<div>
|
<div>^ Domain</div>
|
||||||
^ Domain
|
{liveDomain ? (
|
||||||
{!IS_DOMAIN_SETUP && (
|
|
||||||
<Chip
|
|
||||||
className="normal-case ml-6 inline font-normal"
|
|
||||||
size="sm"
|
|
||||||
value="Not connected"
|
|
||||||
icon="^"
|
|
||||||
color="orange"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
{IS_DOMAIN_SETUP ? (
|
|
||||||
<Chip
|
<Chip
|
||||||
className="normal-case ml-6 inline font-normal"
|
className="normal-case ml-6 inline font-normal"
|
||||||
size="sm"
|
size="sm"
|
||||||
@ -109,9 +118,22 @@ const OverviewTabPanel = ({ project }: OverviewProps) => {
|
|||||||
color="green"
|
color="green"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<Button className="normal-case rounded-full" color="blue" size="sm">
|
<div className="flex justify-between items-center w-full m-2">
|
||||||
|
<Chip
|
||||||
|
className="normal-case inline font-normal"
|
||||||
|
size="sm"
|
||||||
|
value="Not connected"
|
||||||
|
icon="^"
|
||||||
|
color="orange"
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
className="normal-case rounded-full"
|
||||||
|
color="blue"
|
||||||
|
size="sm"
|
||||||
|
>
|
||||||
Setup
|
Setup
|
||||||
</Button>
|
</Button>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{project.deployments.length !== 0 ? (
|
{project.deployments.length !== 0 ? (
|
||||||
@ -122,9 +144,7 @@ const OverviewTabPanel = ({ project }: OverviewProps) => {
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between p-2 text-sm">
|
<div className="flex justify-between p-2 text-sm">
|
||||||
<p>^ Deployment</p>
|
<p>^ Deployment</p>
|
||||||
<p className="text-blue-600">
|
<p className="text-blue-600">{liveDomain?.name}</p>
|
||||||
{project.deployments[0]?.domain?.name}
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between p-2 text-sm">
|
<div className="flex justify-between p-2 text-sm">
|
||||||
<p>^ Created</p>
|
<p>^ Created</p>
|
||||||
|
@ -113,7 +113,13 @@ const DeploymentDetailsCard = ({
|
|||||||
<button className="self-start">...</button>
|
<button className="self-start">...</button>
|
||||||
</MenuHandler>
|
</MenuHandler>
|
||||||
<MenuList>
|
<MenuList>
|
||||||
|
<a
|
||||||
|
href={'https://' + deployment.url}
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
<MenuItem>^ Visit</MenuItem>
|
<MenuItem>^ Visit</MenuItem>
|
||||||
|
</a>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
onClick={() => setAssignDomainDialog(!assignDomainDialog)}
|
onClick={() => setAssignDomainDialog(!assignDomainDialog)}
|
||||||
>
|
>
|
||||||
|
@ -71,8 +71,8 @@ export enum DomainStatus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface DomainDetails {
|
export interface DomainDetails {
|
||||||
id: number;
|
id: string;
|
||||||
projectid: number;
|
projectid: string;
|
||||||
name: string;
|
name: string;
|
||||||
status: DomainStatus;
|
status: DomainStatus;
|
||||||
record: {
|
record: {
|
||||||
|
@ -273,7 +273,8 @@ export type AddDomainInput = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type FilterDomainInput = {
|
export type FilterDomainInput = {
|
||||||
branch: string
|
branch?: string
|
||||||
|
status?: DomainStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
export type AddDomainResponse = {
|
export type AddDomainResponse = {
|
||||||
|
Loading…
Reference in New Issue
Block a user