<!DOCTYPE html>
<html>

  <head>
    <title>angular2 playground</title>
    <link rel="stylesheet" href="style.css" />
    <script src="https://code.angularjs.org/2.0.0-beta.0/angular2-polyfills.js"></script>
    <script src="https://code.angularjs.org/tools/system.js"></script>
    <script src="https://code.angularjs.org/tools/typescript.js"></script>
    <script src="config.js"></script>
    <script src="https://code.angularjs.org/2.0.0-beta.0/Rx.js"></script>
    <script src="https://code.angularjs.org/2.0.0-beta.0/angular2.min.js"></script>
    <script src="https://code.angularjs.org/2.0.0-beta.0/http.min.js"></script>
    <script>
    System.import('app')
      .catch(console.error.bind(console));
  </script>
  </head>

  <body>
    <my-app>
    loading...
  </my-app>
  </body>

</html>
/* Styles go here */

### Angular2 GitHub Summarizer

This was built as part of a coding challenge at the MIT Libraries to build a simple visualizer for GitHub repositories using a javascript framework of our choosing. I selected Angular2.

The user supplies the user and name of a repository on GitHub, and the app queries the GitHub API for the number of open issues in that project. The user can remove items from the list as well.

Details of the challenge can be found at https://gist.github.com/JPrevost/74782c3c94f6e0d3423d
System.config({
  //use typescript for compilation
  transpiler: 'typescript',
  //typescript compiler options
  typescriptOptions: {
    emitDecoratorMetadata: true
  },
  //map tells the System loader where to look for things
  map: {
    app: "./src"
  },
  //packages defines our app package
  packages: {
    app: {
      main: './main.ts',
      defaultExtension: 'ts'
    }
  }
});
//main entry point
import {bootstrap} from 'angular2/platform/browser';
import {HTTP_PROVIDERS} from 'angular2/http';
import 'rxjs/add/operator/map';
import {App} from './app';
import {GithubService} from './github.service';

bootstrap(App, [
  HTTP_PROVIDERS,
  GithubService
])
  .catch(err => console.error(err));
//our root app component
import {Component} from 'angular2/core'
import {Http, Response} from 'angular2/http';
import 'rxjs/add/operator/map';
import {GithubService} from './github.service';
import {Repo} from './repo';
import {RepoList} from './repo_list';
import {RepoForm} from './repo_form';

@Component({
  selector: 'my-app',
  providers: [],
  template: `
    <h2>GitHub Repository Summarizer</h2>
    <repo-form (newRepo)="addRepo($event)"></repo-form>
    <repo-list [repos]="repos"></repo-list>
    <input type="button" (click)="archive()" value="Remove Inactive Repos">
  `,
  directives: [RepoList, RepoForm]
})
export class App {

  public repos = [];

  constructor(private _githubService: GithubService) {
    console.log('Constructor');
  }

  ngOnInit() {
    url = 'https://api.github.com/repos/matt-bernhardt/trapp';
    // this.getRepos(url);

    url = 'https://api.github.com/repos/matt-bernhardt/galaxy';
    // this.getRepos(url);

    url = 'https://api.github.com/repos/matt-bernhardt/asdf';
    // this.getRepos(url);
  }

  getRepos(url) {
    this._githubService.getRepoSimple(url).subscribe(
      data => {this.repos.push(data)},
      err => console.error(err),
      () => console.log('data loaded')
    );
  }
  
  archive(): void {
    var oldRepos = this.repos;
    this.repos = [];
    oldRepos.forEach((repo: Repo) => {
      if (repo.active) this.repos.push(repo);
    });
  }
  
  loadRepoData(repo) {
    console.log('loading data for repo');
    console.log(repo);
    url = 'https://api.github.com/repos/' + repo['name'];
    console.log(url);
    this._githubService.getRepoSimple(url).subscribe(
      data => this.loadRepoGood(repo, data),
      err => this.loadRepoError(repo, err),
      () => console.log('data loaded')
    );
  }

  loadRepoGood(repo, data) {
    console.log('Load Successful');
    repo['issues'] = data['open_issues'];
    repo['status'] = 'valid';
  }
  
  loadRepoError(repo, err) {
    console.log('Load Error');
    console.error(err);
    repo['status'] = 'error';
  }

  addRepo(repo: Repo) {
    console.log('adding repo from form submission');
    this.loadRepoData(repo);
    this.repos.push(repo);
  }
  
}
import {Injectable} from 'angular2/core';
import {Http, Response} from 'angular2/http';
import {Observable} from 'rxjs/Rx';

@Injectable()
export class GithubService {
  // This is borrowed heavily from 
  // https://github.com/kdechant/angular2-http-demo/blob/master/app/demo.service.ts

  constructor(private http:Http) { }

  // Uses http.get() to load an API
  getRepoSimple(url) {
    return this.http.get(url)
      .map((res:Response) => res.json());
  }
  
}
import {Component, Output, EventEmitter} from 'angular2/core';
import {Repo} from './repo';

@Component({
  selector: 'repo-form',
  template: `
  <form (ngSubmit)="addRepo()">
    <input type="text" [(ngModel)]="repo" size="30" placeholder="new user/repo">
    <input class="btn-primary" type="submit" value="add">
  </form>
  `
})
export class RepoForm {
  @Output() newRepo = new EventEmitter<Repo>();
  
  repo: string = '';
  
  addRepo() {
    if (this.repo) {
      this.newRepo.next({
        name: this.repo,
        issues: -1,
        active: true,
        status: 'tbd'
      });
    }
    this.repo = '';
  }
}
export interface Repo {
  name: string,
  issues: number,
  active: boolean,
  status: string
}
import {Component, Input} from 'angular2/core';
import {Repo} from './repo';

@Component({
  selector: 'repo-list',
  styles: [`
    table {
      border-collapse: collapse;
    }
    th {
      border-bottom: 1px solid black;
    }
    th, td {
      padding: 5px;
    }
    tr.active-true td {
      font-weight: bold;
    }
    tr.active-false td {
      font-weight: normal;
      text-decoration: line-through;
    }
    tr.status-tbd td {
      background-color: #ccc;
    }
    tr.status-error td {
      background-color: #fcc;
    }
    tr.status-valid td {
      background-color: #cfc;
    }
  `],
  template: `
  <table>
    <thead>
      <tr>
        <th scope="col">Activate</th>
        <th scope="col">Repository</th>
        <th scope="col">Issues</th>
        <th scope="col">Status</th>
      </tr>
    </thead>
    <tbody>
      <tr *ngFor="#repo of repos" class="active-{{repo.active}} status-{{repo.status}}">
        <td>
          <input type="checkbox" [(ngModel)]="repo.active">
        </td>
        <td>{{repo.name}}</td>
        <td>{{repo.issues}}</td>
        <td>{{repo.status}}</td>
      </tr>
    </tbody>
  </table>
  `
})
export class RepoList {
  @Input() repos: Repo[];
}