Skip to content

Commit

Permalink
Merge pull request #3372 from cloudfoundry-incubator/autocomplete-git…
Browse files Browse the repository at this point in the history
…-reponame

Autocomplete git repository name
  • Loading branch information
KlapTrap authored Feb 14, 2019
2 parents 75af566 + d252631 commit 6465845
Show file tree
Hide file tree
Showing 12 changed files with 116 additions and 83 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ import { generateTestEntityServiceProvider } from '../../../../test-framework/en
import { createBasicStoreModule } from '../../../../test-framework/store-test-helper';
import { ApplicationEnvVarsHelper } from './../application-tabs-base/tabs/build-tab/application-env-vars.service';
import { ApplicationTabsBaseComponent } from './application-tabs-base.component';
import { HttpModule, Http, ConnectionBackend } from '@angular/http';
import { MockBackend } from '@angular/http/testing';
import { GITHUB_API_URL, getGitHubAPIURL } from '../../../../core/github.helpers';
import { HttpClientModule } from '@angular/common/http';
import { HttpClientTestingModule } from '@angular/common/http/testing';

describe('ApplicationTabsBaseComponent', () => {
let component: ApplicationTabsBaseComponent;
Expand All @@ -38,7 +38,8 @@ describe('ApplicationTabsBaseComponent', () => {
RouterTestingModule,
MDAppModule,
createBasicStoreModule(),
HttpModule
HttpClientModule,
HttpClientTestingModule
],
providers: [
generateTestEntityServiceProvider(
Expand All @@ -49,11 +50,6 @@ describe('ApplicationTabsBaseComponent', () => {
generateTestApplicationServiceProvider(cfId, appId),
ApplicationStateService,
ApplicationEnvVarsHelper,
Http,
{
provide: ConnectionBackend,
useClass: MockBackend
},
{ provide: GITHUB_API_URL, useFactory: getGitHubAPIURL }
]
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ import { ApplicationService } from '../../../../application.service';
import { ApplicationEnvVarsHelper } from './application-env-vars.service';
import { BuildTabComponent } from './build-tab.component';
import { ViewBuildpackComponent } from './view-buildpack/view-buildpack.component';
import { HttpModule, Http, ConnectionBackend } from '@angular/http';
import { MockBackend } from '@angular/http/testing';
import { GITHUB_API_URL, getGitHubAPIURL } from '../../../../../../core/github.helpers';
import { GITHUB_API_URL } from '../../../../../../core/github.helpers';
import { HttpClientModule } from '@angular/common/http';
import { HttpClientTestingModule } from '@angular/common/http/testing';

describe('BuildTabComponent', () => {
let component: BuildTabComponent;
Expand All @@ -41,18 +41,14 @@ describe('BuildTabComponent', () => {
initialState
}
),
HttpModule
HttpClientModule,
HttpClientTestingModule
],
providers: [
{ provide: ApplicationService, useClass: ApplicationServiceMock },
AppStoreModule,
ApplicationStateService,
ApplicationEnvVarsHelper,
Http,
{
provide: ConnectionBackend,
useClass: MockBackend
},
{ provide: GITHUB_API_URL, useValue: null }
]
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import { GitSCMTabComponent } from './gitscm-tab.component';
import { DatePipe } from '@angular/common';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { GITHUB_API_URL, getGitHubAPIURL } from '../../../../../../core/github.helpers';
import { HttpModule, Http, ConnectionBackend } from '@angular/http';
import { MockBackend } from '@angular/http/testing';
import { HttpClientModule } from '@angular/common/http';
import { HttpClientTestingModule } from '@angular/common/http/testing';

describe('GitSCMTabComponent', () => {
let component: GitSCMTabComponent;
Expand All @@ -34,17 +34,13 @@ describe('GitSCMTabComponent', () => {
}
),
NoopAnimationsModule,
HttpModule
HttpClientModule,
HttpClientTestingModule
],
providers: [
{ provide: ApplicationService, useClass: ApplicationServiceMock },
{ provide: GITHUB_API_URL, useFactory: getGitHubAPIURL },
DatePipe,
Http,
{
provide: ConnectionBackend,
useClass: MockBackend
}
]
})
.compileComponents();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import { CommonModule, DatePipe } from '@angular/common';
import { CoreModule } from '../../../../../core/core.module';
import { SharedModule } from '../../../../../shared/shared.module';
import { createBasicStoreModule } from '../../../../../test-framework/store-test-helper';
import { HttpModule, Http, ConnectionBackend } from '@angular/http';
import { GITHUB_API_URL, getGitHubAPIURL } from '../../../../../core/github.helpers';
import { MockBackend } from '@angular/http/testing';
import { HttpClientModule } from '@angular/common/http';
import { HttpClientTestingModule } from '@angular/common/http/testing';

describe('CommitListWrapperComponent', () => {
let component: CommitListWrapperComponent;
Expand All @@ -21,16 +21,12 @@ describe('CommitListWrapperComponent', () => {
CoreModule,
SharedModule,
createBasicStoreModule(),
HttpModule
HttpClientModule,
HttpClientTestingModule
],
providers: [
DatePipe,
{ provide: GITHUB_API_URL, useFactory: getGitHubAPIURL },
Http,
{
provide: ConnectionBackend,
useClass: MockBackend
}
]
})
.compileComponents();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@
<div class="github-project-details">
<div>
<mat-form-field>
<input matInput [disabled]="isRedeploy" [(ngModel)]="repository" placeholder="Project" name="projectName" [appGithubProjectExists]="sourceType.id" required>
<input type="text" matInput [matAutocomplete]="auto" [disabled]="isRedeploy" [(ngModel)]="repository" placeholder="Project" name="projectName" [appGithubProjectExists]="sourceType.id" required>
<!-- Repository auto complete helper -->
<mat-autocomplete autoActiveFirstOption #auto="matAutocomplete">
<mat-option *ngFor="let repo of suggestedRepos$ | async" [value]="repo">{{repo}}</mat-option>
</mat-autocomplete>

<mat-error *ngIf="sourceSelectionForm.controls.projectName?.errors?.githubProjectDoesNotExist && !sourceSelectionForm.controls.projectName?.errors?.githubProjectError">
Project does not exist
</mat-error>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
import { GitSCMService } from './../../../../shared/data-services/scm/scm.service';
import { CoreModule } from '../../../../core/core.module';
import { SharedModule } from '../../../../shared/shared.module';
import { inject, TestBed, ComponentFixture, async, fakeAsync, tick } from '@angular/core/testing';
import { Store, StoreModule } from '@ngrx/store';
import { TestBed, ComponentFixture, async } from '@angular/core/testing';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

import { createBasicStoreModule } from '../../../../test-framework/store-test-helper';
import { RouterTestingModule } from '@angular/router/testing';
import { MatDialogModule } from '@angular/material';

import { DeployApplicationStep2Component } from './deploy-application-step2.component';
import { DeployApplicationFsComponent } from './deploy-application-fs/deploy-application-fs.component';
import { GITHUB_API_URL, getGitHubAPIURL } from '../../../../core/github.helpers';
import { HttpModule, Http, ConnectionBackend } from '@angular/http';
import { MockBackend } from '@angular/http/testing';
import { GithubProjectExistsDirective } from '../github-project-exists.directive';
import { HttpClientModule } from '@angular/common/http';
import { HttpClientTestingModule } from '@angular/common/http/testing';

describe('DeployApplicationStep2Component', () => {
let component: DeployApplicationStep2Component;
Expand All @@ -33,15 +31,11 @@ describe('DeployApplicationStep2Component', () => {
RouterTestingModule,
createBasicStoreModule(),
BrowserAnimationsModule,
HttpModule
HttpClientModule,
HttpClientTestingModule
],
providers: [
{ provide: GITHUB_API_URL, useFactory: getGitHubAPIURL },
Http,
{
provide: ConnectionBackend,
useClass: MockBackend
},
GitSCMService
]
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { AfterContentInit, Component, Inject, Input, OnDestroy, OnInit, ViewChil
import { NgForm } from '@angular/forms';
import { ActivatedRoute } from '@angular/router';
import { Store } from '@ngrx/store';
import { combineLatest as observableCombineLatest, Observable, of as observableOf, Subscription } from 'rxjs';
import { filter, map, take, tap, withLatestFrom } from 'rxjs/operators';
import { combineLatest as observableCombineLatest, Observable, timer as observableTimer, of as observableOf, Subscription } from 'rxjs';
import { filter, map, take, tap, withLatestFrom, switchMap, startWith, pairwise, catchError } from 'rxjs/operators';

import { EntityServiceFactory } from '../../../../core/entity-service-factory.service';
import { StepOnNextFunction } from '../../../../shared/components/stepper/step/step.component';
Expand Down Expand Up @@ -76,6 +76,11 @@ export class DeployApplicationStep2Component

scm: GitSCM;

// We don't have any repositories to suggest initially - need user to start typing
suggestedRepos$: Observable<string[]>;

cachedSuggestions = {};

// Local FS data when file or folder upload
// @Input('fsSourceData') fsSourceData;

Expand Down Expand Up @@ -274,6 +279,32 @@ export class DeployApplicationStep2Component
this.subscriptions.push(setInitialSourceType$.subscribe());
this.subscriptions.push(setSourceTypeModel$.subscribe());
this.subscriptions.push(setProjectName.subscribe());

this.suggestedRepos$ = this.sourceSelectionForm.valueChanges.pipe(
map(form => form.projectName),
startWith(''),
pairwise(),
filter(([oldName, newName]) => oldName !== newName),
switchMap(([oldName, newName]) => this.updateSuggestedRepositories(newName))
);
}

updateSuggestedRepositories(name: string): Observable<string[]> {
if (!name || name.length < 3) {
return observableOf([] as string[]);
}

const cacheName = this.scm.getType() + ':' + name;
if (this.cachedSuggestions[cacheName]) {
return observableOf(this.cachedSuggestions[cacheName]);
}

return observableTimer(500).pipe(
take(1),
switchMap(() => this.scm.getMatchingRepositories(name)),
catchError(_e => observableOf(null)),
tap(suggestions => this.cachedSuggestions[cacheName] = suggestions)
);
}

setSourceType = event => this.store.dispatch(new SetAppSourceDetails(event));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { HttpModule } from '@angular/http';
import { HttpClientModule } from '@angular/common/http';
import { Store } from '@ngrx/store';
import { inject, TestBed } from '@angular/core/testing';
import { CommonModule } from '@angular/common';
Expand All @@ -9,6 +9,7 @@ import { AppState } from '../../../store/app-state';
import { GitSCMService } from '../../../shared/data-services/scm/scm.service';
import { GithubProjectExistsDirective } from './github-project-exists.directive';
import { GITHUB_API_URL, getGitHubAPIURL } from '../../../core/github.helpers';
import { HttpClientTestingModule } from '@angular/common/http/testing';


describe('GithubProjectExistsDirective', () => {
Expand All @@ -19,7 +20,8 @@ describe('GithubProjectExistsDirective', () => {
CoreModule,
SharedModule,
createBasicStoreModule(),
HttpModule
HttpClientModule,
HttpClientTestingModule
],
providers: [
{ provide: GITHUB_API_URL, useFactory: getGitHubAPIURL }
Expand Down
36 changes: 21 additions & 15 deletions src/frontend/app/shared/data-services/scm/github-scm.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { GitSCM, SCMIcon } from './scm';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { Http } from '@angular/http';
import { map, filter } from 'rxjs/operators';
import { HttpClient } from '@angular/common/http';
import { GitSCMType } from './scm.service';
import { GitRepo, GitCommit, GitBranch } from '../../../store/types/git.types';

export class GitHubSCM implements GitSCM {

constructor(public http: Http, public gitHubURL: string) {}
constructor(public httpClient: HttpClient, public gitHubURL: string) {}

getType(): GitSCMType {
return 'github';
Expand All @@ -25,27 +25,19 @@ export class GitHubSCM implements GitSCM {
}

getRepository(projectName: string): Observable<GitRepo> {
return this.http.get(`${this.gitHubURL}/repos/${projectName}`).pipe(
map(response => response.json())
);
return this.httpClient.get(`${this.gitHubURL}/repos/${projectName}`) as Observable<GitRepo>;
}

getBranches(projectName: string): Observable<GitBranch[]> {
return this.http.get(`${this.gitHubURL}/repos/${projectName}/branches`).pipe(
map(response => response.json())
);
return this.httpClient.get(`${this.gitHubURL}/repos/${projectName}/branches`) as Observable<GitBranch[]>;
}

getCommit(projectName: string, commitSha: string): Observable<GitCommit> {
return this.http.get(`${this.gitHubURL}/repos/${projectName}/commits/${commitSha}`).pipe(
map(response => response.json())
);
return this.httpClient.get(`${this.gitHubURL}/repos/${projectName}/commits/${commitSha}`) as Observable<GitCommit>;
}

getCommits(projectName: string, commitSha: string): Observable<GitCommit[]> {
return this.http.get(`${this.gitHubURL}/repos/${projectName}/commits?sha=${commitSha}`).pipe(
map(response => response.json())
);
return this.httpClient.get(`${this.gitHubURL}/repos/${projectName}/commits?sha=${commitSha}`) as Observable<GitCommit[]>;
}

getCloneURL(projectName: string): string {
Expand All @@ -60,4 +52,18 @@ export class GitHubSCM implements GitSCM {
return `https://github.com/${projectName}/compare/${commitSha1}...${commitSha2}`;
}

getMatchingRepositories(projectName: string): Observable<string[]> {
const prjParts = projectName.split('/');
let url = `${this.gitHubURL}/search/repositories?q=${projectName}+in:name`;
if (prjParts.length > 1) {
url = `${this.gitHubURL}/search/repositories?q=${prjParts[1]}+in:name+user:${prjParts[0]}`;
}
return this.httpClient.get(url).pipe(
filter((repos: any) => !!repos.items),
map(repos => {
return repos.items.map(item => item.full_name);
})
);
}

}
Loading

0 comments on commit 6465845

Please sign in to comment.