Skip to content
This repository has been archived by the owner on Apr 12, 2021. It is now read-only.

Commit

Permalink
feat(admin): #1656 added webhook creation in admin page"
Browse files Browse the repository at this point in the history
  • Loading branch information
webkhushboo committed Jan 16, 2020
1 parent 98adb28 commit e6fdadc
Show file tree
Hide file tree
Showing 11 changed files with 252 additions and 4 deletions.
2 changes: 1 addition & 1 deletion firestore.rules
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ service cloud.firestore {
match /repositories/{repository} {
allow create: if false;
allow get: if resource.data.private == false;
allow list: if false;
allow list: if true;
allow update: if false;
allow delete: if false;
}
Expand Down
3 changes: 2 additions & 1 deletion functions/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { CallableContext } from 'firebase-functions/lib/providers/https';
import { DocumentSnapshot } from './client/firebase-admin';

// Dashboard repositories
import { onCreateGitWebhookRepository, CreateGitWebhookRepositoryInput } from './repository/create-git-webhook-repository';
import { onCreateGitWebhooks, onCreateGitWebhookRepository, CreateGitWebhooksInput, CreateGitWebhookRepositoryInput } from './repository/create-git-webhook-repository';
import { onCreateRepository } from './repository/create-repository';
import { onDeleteRepository } from './repository/delete-repository';
import { getRepositoryInfo, RepositoryInfoInput } from './repository/info';
Expand Down Expand Up @@ -39,6 +39,7 @@ export const findAllUserRepositories: HttpsFunction = functions.https.onCall((in
export const findAllUserEvents: HttpsFunction = functions.https.onCall((input: EventsInput, context: CallableContext) => getUserEvents(input.token, context.auth.uid, input.username));
export const findRepositoryInfo: HttpsFunction = functions.https.onCall((input: RepositoryInfoInput, context: CallableContext) => getRepositoryInfo(input.token, input.repository));
export const createGitWebhookRepository: HttpsFunction = functions.https.onCall((input: CreateGitWebhookRepositoryInput, context: CallableContext) => onCreateGitWebhookRepository(input.token, input.repositoryUid));
export const createGitWebhooks: HttpsFunction = functions.https.onCall((input: CreateGitWebhooksInput, context: CallableContext) => onCreateGitWebhooks(input.token, input.repositoryUids));
export const deleteGitWebhookRepository: HttpsFunction = functions.https.onCall((input: DeleteGitWebhookRepositoryInput, context: CallableContext) => onDeleteGitWebhookRepository(input.token, input.data));
export const responseGitWebhookRepository: HttpsFunction = onResponseGitWebhookRepository;
export const pingMonitor: HttpsFunction = functions.https.onCall((input: MonitorInfoInput, context: CallableContext) => ping(input.projectUid, input.monitorUid, input.type));
Expand Down
13 changes: 13 additions & 0 deletions functions/src/repository/create-git-webhook-repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ export interface CreateGitWebhookRepositoryInput {
repositoryUid: string;
}

export interface CreateGitWebhooksInput {
token: string;
repositoryUids: string[];
}

export const onCreateGitWebhookRepository: any = async (token: string, repositoryUid: string) => {
try {
const repositorySnapshot: DocumentReference = RepositoryModel.getRepositoryReference(repositoryUid);
Expand Down Expand Up @@ -80,3 +85,11 @@ export async function getWebhook(repositoryFullName: string, token: string): Pro
Logger.info('Webhook is creating');
return GitHubRepositoryWebhookMapper.import(await createWebhook(repositoryFullName, token));
}

export const onCreateGitWebhooks: any = async (token: string, repositoryUids: string[]) => {
const promises: Promise<any>[] = [];
repositoryUids.forEach((repoUid: string) =>
promises.push(onCreateGitWebhookRepository(token, repoUid))
);
await Promise.all(promises);
};
8 changes: 7 additions & 1 deletion web/src/app/admin/admin-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

// DashboardHub components
import { AdminGuard } from '@app/core/guards/admin.guard';
import { AdminGuard } from '@core/guards/admin.guard';
import { ConifgureWebhooksComponent } from './conifgure-webhooks/conifgure-webhooks.component';
import { UsersListComponent } from './users-list/users-list.component';

const routes: Routes = [
Expand All @@ -12,6 +13,11 @@ const routes: Routes = [
component: UsersListComponent,
canActivate: [AdminGuard],
},
{
path: 'configure-webhooks',
component: ConifgureWebhooksComponent,
canActivate: [AdminGuard],
},
];

@NgModule({
Expand Down
3 changes: 2 additions & 1 deletion web/src/app/admin/admin.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ import { NgModule } from '@angular/core';
// DashboardHub modules and components
import { SharedModule } from '@shared/shared.module';
import { AdminRoutingModule } from './admin-routing.module';
import { ConifgureWebhooksComponent } from './conifgure-webhooks/conifgure-webhooks.component';
import { UsersListComponent } from './users-list/users-list.component';

@NgModule({
declarations: [UsersListComponent],
declarations: [UsersListComponent, ConifgureWebhooksComponent],
imports: [
CommonModule,
SharedModule,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<div class="webhooks">
<div fxLayout="row" fxLayout.lt-lg="column" fxLayoutAlign.lt-lg="space-between scretch" fxLayoutAlign="space-between center">
<mat-card class="webhooks__webhooks-card" fxFlex="100%">
<mat-card-header>
<div class="webhooks__webhooks-card__header">
<mat-icon class="material-icons-outlined">dashboard</mat-icon>
</div>
<mat-card-title class="webhooks__webhooks-card__title"> Configure webhooks </mat-card-title>
<mat-card-subtitle class="webhooks__webhooks-card__title__subtitle"> Create webhooks </mat-card-subtitle>
</mat-card-header>

<mat-card-content class="webhooks__webhooks-card__content" *ngIf="repositories">
<table mat-table [dataSource]="repositories" class="webhooks__webhooks-card__content__table">

<ng-container matColumnDef="fullName">
<th mat-header-cell *matHeaderCellDef>Full Name</th>
<td mat-cell *matCellDef="let element">
<div fxLayout.xs="column" fxLayoutAlign.xs="start start" class="webhooks__webhooks-card__content__table__title">
{{element.fullName}}
</div>
</td>
</ng-container>

<ng-container matColumnDef="projectLength">
<th mat-header-cell *matHeaderCellDef>Project Count </th>
<td mat-cell *matCellDef="let element" class="webhooks__webhooks-card__content__table__description">
<div *ngIf="element.projects" class="webhooks__webhooks-card__content__table__description">
{{ element.projects.length }}
</div>
</td>
</ng-container>

<ng-container matColumnDef="webhookUpdatedOn">
<th mat-header-cell *matHeaderCellDef>Webhook last updated </th>
<td mat-cell *matCellDef="let element" class="webhooks__webhooks-card__content__table__description">
<div *ngIf="element.webhook" class="webhooks__webhooks-card__content__table__description">
{{ element.webhook.updatedOn.toDate() | timeAgo }}
</div>
</td>
</ng-container>


<ng-container matColumnDef="updatedAt">
<th mat-header-cell *matHeaderCellDef>Last updated </th>
<td mat-cell *matCellDef="let element" class="webhooks__webhooks-card__content__table__description">
<div *ngIf="element.updatedOn" class="webhooks__webhooks-card__content__table__description">
{{ element.updatedOn.toDate() | timeAgo }}
</div>
</td>
</ng-container>

<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef> Action </th>
<td mat-cell *matCellDef="let element" class="webhooks__webhooks-card__content__table__description">
<button mat-stroked-button type="submit" color="warn" (click)="createWebhooks([element.uid])">Create Webhook </button>
</td>
</ng-container>

<tr mat-header-row *matHeaderRowDef="displayedColumns;"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
</mat-card-content>
</mat-card>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
@import '../../../styles.scss';
@import '../../../assets/scss/variable';

.webhooks {
padding: 20px 30px;
@include pageContainer;

&__title {
@include pageHeader;
}

&__webhooks-card {
@include cardContainer;

&__header {
@include header-icon;
background-color: $purple-color;
box-shadow: 0px 3px 6px $purple-shadow;
}

&__title {
@include title;

&__subtitle {
@include subtitle;
}
}

&__content {
padding: 0;
display: block;
overflow: hidden;
@include tableContainer;

&__table {
width: 100%;
padding: 0;

&__avatar {
height: 35px;
border-radius: 50%;
object-fit: cover;
border: 1px solid $orange-color;
margin-right: 20px;
}

@media (max-width: $breakpoint-xs) {
&__avatar {
margin-right: 10px;
}
}

&__description {
margin-right: 5px;
}

&__title {
min-width: 5vw;
padding-right: 10px;
}

&__time {
color: $dark-grey-color;
font-size: 14px;
font-weight: lighter;
@include ellipsisText;
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Core modules
import { Component, OnInit } from '@angular/core';

// Third party modules
import { Subscription } from 'rxjs';

// DashboardHub Model and services
import { RepositoryService } from '@core/services/index.service';
import { RepositoryModel, IRepository } from '@shared/models/index.model';
import { take } from 'rxjs/operators';

/**
* Configure webhooks component
*/
@Component({
selector: 'dashboard-conifgure-webhooks',
templateUrl: './conifgure-webhooks.component.html',
styleUrls: ['./conifgure-webhooks.component.scss'],
})
export class ConifgureWebhooksComponent implements OnInit {

public displayedColumns: string[] = ['fullName', 'projectLength', 'webhookUpdatedOn', 'updatedAt', 'actions'];
public userSubscription: Subscription;
public repositories: RepositoryModel[];

/**
* Life cycle method
* @param repositoryService RepositoryService
*/
constructor(
private repositoryService: RepositoryService
) { }

/**
* Life cycle init method
*/
ngOnInit(): void {
this.repositoryService.findAllRepositories().subscribe((repositories: RepositoryModel[]) => this.repositories = repositories);
}

/**
* Create webhook
*/
createWebhooks(repos: IRepository[]): void {
this.repositoryService.createGitWebhooks(repos)
.pipe(take(1))
.subscribe();
}

}
5 changes: 5 additions & 0 deletions web/src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ export class AppComponent implements AfterViewInit, OnInit {
route: '/admin/users',
icon: 'person',
},
{
title: 'Configure webhooks',
route: '/admin/configure-webhooks',
icon: 'dashboard',
},
];
public version: string;
public isSmallScreen: boolean;
Expand Down
29 changes: 29 additions & 0 deletions web/src/app/core/services/repository.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,19 @@ export class RepositoryService {
return of(new RepositoryModel(callable({ repositoryUid: repo.uid, token: this.authService.profile.oauth.githubToken })));
}

/**
* Call cloud function create webhook manually
* @param repo repository
*/
public createGitWebhooks(repos: IRepository[]): Observable<RepositoryModel> {
const callable: any = this.fns.httpsCallable('createGitWebhooks');

return of(new RepositoryModel(callable({
repositoryUids: repos.map((repo: IRepository) => repo.uid),
token: this.authService.profile.oauth.githubToken,
})));
}

/**
* Call cloud function to delete webhook manually
* @param repo repository
Expand All @@ -93,4 +106,20 @@ export class RepositoryService {

return callable({ token: this.authService.profile.oauth.githubToken, repository: { fullName: fullName, ref: ref } });
}

/**
* Find all repositories
*/
public findAllRepositories(): Observable<RepositoryModel[]> {
return this.activityService
.start()
.pipe(
switchMap(() => this.afs
.collection<IRepository>(
'repositories'
)
.valueChanges()),
map((repositories: IRepository[]) => repositories.map((repository: IRepository) => new RepositoryModel(repository)))
);
}
}
7 changes: 7 additions & 0 deletions web/src/app/shared/models/repository.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { firestore } from 'firebase';

// DashboardHub models
import { ContributorModel } from './contributor.model';
import { ProjectModel } from './index.model';
import { IssueModel } from './issue.model';
import { MilestoneModel } from './milestone.model';
import { IModel, Model } from './model.model';
Expand Down Expand Up @@ -36,12 +37,14 @@ export interface IRepository extends IModel {
issues?: IssueModel[];
contributors?: ContributorModel[];
milestones?: MilestoneModel[];
projects?: ProjectModel[];
webhook?: WebhookModel;
url?: string;
forksCount?: number;
stargazersCount?: number;
watchersCount?: number;
lastUpdated?: firestore.Timestamp;
updatedOn?: firestore.Timestamp;
}

/**
Expand All @@ -66,6 +69,7 @@ export class RepositoryModel extends Model<IRepository> implements IRepository {
name: string;
};
pullRequests?: PullRequestModel[];
projects?: ProjectModel[];
events?: Event[];
releases?: ReleaseModel[];
issues?: IssueModel[];
Expand All @@ -77,6 +81,7 @@ export class RepositoryModel extends Model<IRepository> implements IRepository {
stargazersCount: number;
watchersCount: number;
lastUpdated: firestore.Timestamp;
updatedOn: firestore.Timestamp;

constructor(repository: IRepository) {
super();
Expand All @@ -94,6 +99,7 @@ export class RepositoryModel extends Model<IRepository> implements IRepository {
this.branch = repository.branch ? repository.branch : undefined;
this.license = repository.license ? repository.license : undefined;
this.pullRequests = repository.pullRequests ? repository.pullRequests : undefined;
this.projects = repository.projects ? repository.projects : undefined;
this.events = repository.events ? repository.events : undefined;
this.releases = repository.releases ? repository.releases : undefined;
this.issues = repository.issues ? repository.issues : undefined;
Expand All @@ -104,6 +110,7 @@ export class RepositoryModel extends Model<IRepository> implements IRepository {
this.forksCount = repository.forksCount ? repository.forksCount : undefined;
this.stargazersCount = repository.stargazersCount ? repository.stargazersCount : undefined;
this.lastUpdated = repository.lastUpdated ? repository.lastUpdated : undefined;
this.updatedOn = repository.updatedOn ? repository.updatedOn : undefined;
}

public calculateRating(): number {
Expand Down

0 comments on commit e6fdadc

Please sign in to comment.