Skip to content

Commit 917a0d0

Browse files
committed
types for data
1 parent e274c3f commit 917a0d0

8 files changed

Lines changed: 226 additions & 25 deletions

File tree

src/components/combatant.ts

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,19 @@ import { Component, Output, EventEmitter } from '@angular/core';
1111

1212
import { BattleService } from '../services/battleservice';
1313

14+
import { CombatantInfo } from '../types';
15+
1416
type CombatantMode = 'empty' | 'loading' | 'error' | 'data';
1517

1618
@Component({
1719
selector: 'combatant',
1820
template: `
19-
<div [class.winner]="winner">
20-
<input placeholder="Github user name" [(ngModel)]="field" (keyup.enter)="loadData()">
21-
<button (click)="loadData()" [disabled]="!canLoad">Load</button>
22-
<div *ngIf="mode === 'loading'">...loading...</div>
23-
<div *ngIf="mode === 'error'">Oh no, something wen't wrong :(</div>
24-
<div *ngIf="mode === 'data'">
25-
<combatantdetail [data]="data"></combatantdetail>
26-
</div>
21+
<input placeholder="Github user name" [(ngModel)]="field" (keyup.enter)="loadData()">
22+
<button (click)="loadData()" [disabled]="!canLoad">Load</button>
23+
<div *ngIf="mode === 'loading'">...loading...</div>
24+
<div *ngIf="mode === 'error'">Oh no, something wen't wrong :(</div>
25+
<div *ngIf="mode === 'data'">
26+
<combatantdetail [data]="data"></combatantdetail>
2727
</div>
2828
`,
2929
styles: [`
@@ -37,7 +37,7 @@ type CombatantMode = 'empty' | 'loading' | 'error' | 'data';
3737
export class CombatantComponent {
3838
mode: CombatantMode = 'empty'
3939
field = ""
40-
data = null
40+
data: CombatantInfo = null
4141
@Output() stars = new EventEmitter<any>()
4242
constructor(private battleService: BattleService){}
4343
get canLoad() {
@@ -55,7 +55,6 @@ export class CombatantComponent {
5555
this.field = '';
5656
},
5757
error => {
58-
console.log("WTF", error);
5958
this.mode = 'error';
6059
this.stars.emit(null);
6160
}

src/components/combatantdetail.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ Rendered by the Combatant component.
77

88
import { Component, Input } from '@angular/core';
99

10+
import { CombatantInfo } from '../types';
11+
1012
@Component({
1113
selector: 'combatantdetail',
1214
template: `
@@ -32,7 +34,7 @@ import { Component, Input } from '@angular/core';
3234
`
3335
})
3436
export class CombatantDetailComponent {
35-
@Input() data
37+
@Input() data: CombatantInfo
3638
get languageKeys(){
3739
let count = this.data.repos.languages;
3840
return Object.keys(count).sort((l1,l2)=> count[l1] > count[l2] ? -1 : 1 );
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { NgModule } from '@angular/core';
2+
3+
import { BrowserModule } from '@angular/platform-browser';
4+
import { HttpClientModule } from '@angular/common/http';
5+
import { FormsModule } from '@angular/forms';
6+
import { CommonModule } from '@angular/common';
7+
8+
import { AppComponent } from './app';
9+
import { BattleComponent } from './battle';
10+
import { CombatantComponent } from './combatant';
11+
import { CombatantDetailComponent } from './combatantdetail';
12+
13+
@NgModule({
14+
imports: [BrowserModule, HttpClientModule, FormsModule, CommonModule],
15+
declarations: [ AppComponent, CombatantComponent, CombatantDetailComponent, BattleComponent ],
16+
bootstrap: [ AppComponent ],
17+
})
18+
export class ComponentModule {}

src/services/authservice.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import { Injectable } from '@angular/core';
1212
import * as firebase from 'firebase/app';
1313
import 'firebase/auth';
1414

15+
import { AuthInfo } from '../types';
16+
1517
firebase.initializeApp({
1618
apiKey: "AIzaSyCDDwa9DrgySikEq7waBfXJK1wszeZVtDI",
1719
authDomain: "githubbattle-7edf6.firebaseapp.com",
@@ -32,11 +34,11 @@ export class AuthService {
3234
notifyListeners(){
3335
this.listeners.forEach(cb=> cb(this.authState));
3436
}
35-
listenToAuthChanges(callback){
37+
listenToAuthChanges(callback: (authInfo: AuthInfo) => any){
3638
this.listeners.push(callback);
3739
callback(this.authState);
3840
}
39-
get authState(){
41+
get authState(): AuthInfo {
4042
return {token: this.token,user: this.user, error: this.error};
4143
}
4244
signInWithPopup(){

src/services/battleservice.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,16 @@ import { Injectable } from '@angular/core';
1111

1212
import { GithubService } from './githubservice';
1313

14-
import { of, forkJoin } from 'rxjs';
14+
import { Observable, of, forkJoin } from 'rxjs';
1515
import { map } from 'rxjs/operators';
1616

17+
import { CombatantInfo, GithubRepo, CombatantRepoInfo } from '../types';
18+
1719
@Injectable()
1820
export class BattleService {
1921
cache = {}
2022
constructor(private githubService: GithubService){}
21-
battleInfoForUser(id){
23+
battleInfoForUser(id): Observable<CombatantInfo>{
2224
if (!this.cache[id]){
2325
let user$ = this.githubService.getUser(id);
2426
let repo$ = this.githubService.getRepoListPages(id);
@@ -29,7 +31,7 @@ export class BattleService {
2931
return of(this.cache[id]);
3032
}
3133
}
32-
private digestRepoList(list){
34+
private digestRepoList(list: GithubRepo[]){
3335
return list.reduce((mem, repo) => {
3436
mem.forks += repo.forks_count;
3537
mem.stars += repo.stargazers_count;
@@ -41,7 +43,7 @@ export class BattleService {
4143
if (repo.stargazers_count > mem.mostStarred.stargazers_count){
4244
mem.mostStarred = repo;
4345
}
44-
if (repo.watchers_count > mem.mostForked.watchers_count){
46+
if (repo.watchers_count > mem.mostForked.forks_count){
4547
mem.mostWatched = repo;
4648
}
4749
return mem;
@@ -54,6 +56,6 @@ export class BattleService {
5456
mostWatched: {watchers_count:0},
5557
mostForked: {forks_count:0},
5658
languages: {}
57-
});
59+
} as CombatantRepoInfo);
5860
}
5961
}

src/services/githubservice.ts

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,29 +8,30 @@ since the list from Github is paginated, hence the extra stream juggling.
88
*/
99

1010
import { Injectable } from '@angular/core';
11-
import { HttpClient, HttpResponse } from '@angular/common/http';
11+
import { HttpClient } from '@angular/common/http';
1212

1313
import { Observable, of } from 'rxjs';
1414
import { map, concat, flatMap, share, scan, filter, sample } from 'rxjs/operators';
1515

1616
import { UrlService } from './urlservice';
17+
import { GithubRepo, GithubUserFullInfo } from '../types';
1718

1819
@Injectable()
1920
export class GithubService {
2021
constructor(private http: HttpClient, private urls: UrlService){}
21-
getUser(id):Observable<any>{
22-
return this.http.get(this.urls.urlToUser(id))
22+
getUser(id) {
23+
return this.http.get<GithubUserFullInfo>(this.urls.urlToUser(id))
2324
}
24-
private getRepoListSinglePage(id,page=1):Observable<any>{
25-
return this.http.get(this.urls.urlToUserRepoListPage(id, page), { observe: 'response' }).pipe(
26-
map( (res:HttpResponse<any>)=> ({
25+
private getRepoListSinglePage(id,page=1) {
26+
return this.http.get<GithubRepo[]>(this.urls.urlToUserRepoListPage(id, page), { observe: 'response' }).pipe(
27+
map( (res) => ({
2728
repos: res.body,
2829
pageNumber: page,
2930
isLast: !(res.headers.get("link") || '').split(',')[0].match(/rel=["']next["']/)
3031
})
3132
));
3233
}
33-
private getRepoListPageStream(id,page=1): Observable<any> {
34+
private getRepoListPageStream(id,page=1): Observable<PageResponse> {
3435
return this.getRepoListSinglePage(id, page).pipe(
3536
flatMap((page)=>{
3637
let ret = of(page);
@@ -52,3 +53,9 @@ export class GithubService {
5253
return all$.pipe(sample(last$));
5354
}
5455
}
56+
57+
interface PageResponse {
58+
repos: GithubRepo[]
59+
pageNumber: number
60+
isLast: boolean
61+
}

src/services/services.module.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { NgModule } from '@angular/core';
2+
3+
import { UrlService } from './urlservice';
4+
import { GithubService } from './githubservice';
5+
import { BattleService } from './battleservice';
6+
import { AuthService } from './authservice';
7+
8+
@NgModule({
9+
providers: [ UrlService, GithubService, BattleService, AuthService ]
10+
})
11+
export class ServiceModule {}

src/types.ts

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
import * as firebase from 'firebase/app';
2+
import { User } from '@firebase/auth-types';
3+
4+
// ------- Types provided by our AuthService ------
5+
6+
export interface AuthInfo {
7+
token?: string
8+
user?: User | null
9+
error?: string
10+
}
11+
12+
// ------- Types for our internal data provided by BattleService and consumed by Combatant component --------
13+
14+
export interface CombatantInfo {
15+
user: GithubUserFullInfo
16+
repos: CombatantRepoInfo
17+
id: string
18+
}
19+
20+
export interface CombatantRepoInfo {
21+
repos: number
22+
forks: number
23+
stars: number
24+
watchers: number
25+
mostStarred: {
26+
stargazers_count: number
27+
name?: string
28+
}
29+
mostWatched: {
30+
watchers_count: number
31+
name?: string
32+
}
33+
mostForked: {
34+
forks_count: number
35+
name?: string
36+
}
37+
languages: {
38+
[idx: string]: number
39+
}
40+
}
41+
42+
// ------- Types for the return values from the Github API:s that we use --------
43+
44+
export interface GihubUserBasicInfo {
45+
"login": string
46+
"id": number
47+
"node_id": string,
48+
"avatar_url": string,
49+
"gravatar_id": string,
50+
"url": string,
51+
"html_url": string,
52+
"followers_url": string,
53+
"following_url": string,
54+
"gists_url": string,
55+
"starred_url": string,
56+
"subscriptions_url": string,
57+
"organizations_url": string,
58+
"repos_url": string,
59+
"events_url": string,
60+
"received_events_url": string,
61+
"type": "User",
62+
"site_admin": boolean,
63+
}
64+
65+
export interface GithubUserFullInfo extends GihubUserBasicInfo {
66+
"name": string
67+
"company": null | string
68+
"blog": null | string
69+
"location": string
70+
"email": null | string
71+
"hireable": null | string
72+
"bio": null | string
73+
"public_repos": number
74+
"public_gists": number
75+
"followers": number
76+
"following": number
77+
"created_at": string
78+
"updated_at": string
79+
}
80+
81+
export interface GithubRepo {
82+
"id": number
83+
"node_id": string
84+
"name": string
85+
"full_name": string
86+
"private": boolean
87+
"owner": GihubUserBasicInfo
88+
"html_url": string
89+
"description": string
90+
"fork": boolean
91+
"url": string
92+
"forks_url": string
93+
"keys_url": string
94+
"collaborators_url": string
95+
"teams_url": string
96+
"hooks_url": string
97+
"issue_events_url": string
98+
"events_url": string
99+
"assignees_url": string
100+
"branches_url": string
101+
"tags_url": string
102+
"blobs_url": string
103+
"git_tags_url": string
104+
"git_refs_url": string
105+
"trees_url": string
106+
"statuses_url": string
107+
"languages_url": string
108+
"stargazers_url": string
109+
"contributors_url": string
110+
"subscribers_url": string
111+
"subscription_url": string
112+
"commits_url": string
113+
"git_commits_url": string
114+
"comments_url": string
115+
"issue_comment_url": string
116+
"contents_url": string
117+
"compare_url": string
118+
"merges_url": string
119+
"archive_url": string
120+
"downloads_url": string
121+
"issues_url": string
122+
"pulls_url": string
123+
"milestones_url": string
124+
"notifications_url": string
125+
"labels_url": string
126+
"releases_url": string
127+
"deployments_url": string
128+
"created_at": string
129+
"updated_at": string
130+
"pushed_at": string
131+
"git_url": string
132+
"ssh_url": string
133+
"clone_url": string
134+
"svn_url": string
135+
"homepage": null | string
136+
"size": number
137+
"stargazers_count": number
138+
"watchers_count": number
139+
"language": null | string
140+
"has_issues": boolean
141+
"has_projects": boolean
142+
"has_downloads": boolean
143+
"has_wiki": boolean
144+
"has_pages": boolean
145+
"forks_count": number
146+
"mirror_url": null
147+
"archived": boolean
148+
"open_issues_count": number
149+
"license": {
150+
"key": string
151+
"name": string
152+
"spdx_id": string
153+
"url": string
154+
"node_id": string
155+
}
156+
"forks": number
157+
"open_issues": number
158+
"watchers": number
159+
"default_branch": string
160+
}

0 commit comments

Comments
 (0)