intermediate commit

This commit is contained in:
Gardient
2018-01-06 18:22:02 +02:00
parent 021b24ddad
commit 2abb968fc1
19 changed files with 295 additions and 25 deletions

View File

@@ -1,7 +1,16 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
const routes: Routes = [];
import { HomeComponent } from './home/home.component';
import { AuthGuard } from './auth.guard';
const routes: Routes = [
{
path: '',
component: HomeComponent
}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],

View File

@@ -1,21 +1,4 @@
<!--The content below is only a placeholder and can be replaced.-->
<div style="text-align:center">
<h1>
Welcome to {{ title }}!
</h1>
<img width="300" alt="Angular Logo" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg==">
<app-header></app-header>
<div class="container">
<router-outlet></router-outlet>
</div>
<h2>Here are some links to help you start: </h2>
<ul>
<li>
<h2><a target="_blank" rel="noopener" href="https://angular.io/tutorial">Tour of Heroes</a></h2>
</li>
<li>
<h2><a target="_blank" rel="noopener" href="https://github.com/angular/angular-cli/wiki">CLI Documentation</a></h2>
</li>
<li>
<h2><a target="_blank" rel="noopener" href="https://blog.angular.io/">Angular blog</a></h2>
</li>
</ul>
<router-outlet></router-outlet>

View File

@@ -4,17 +4,22 @@ import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HeaderComponent } from './header/header.component';
import { HomeComponent } from './home/home.component';
import { GApiService } from './gapi.service';
@NgModule({
declarations: [
AppComponent
AppComponent,
HeaderComponent,
HomeComponent
],
imports: [
BrowserModule,
AppRoutingModule
],
providers: [],
providers: [GApiService],
bootstrap: [AppComponent]
})
export class AppModule { }

View File

@@ -0,0 +1,15 @@
import { TestBed, async, inject } from '@angular/core/testing';
import { AuthGuard } from './auth.guard';
describe('AuthGuard', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [AuthGuard]
});
});
it('should ...', inject([AuthGuard], (guard: AuthGuard) => {
expect(guard).toBeTruthy();
}));
});

19
src/app/auth.guard.ts Normal file
View File

@@ -0,0 +1,19 @@
import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import { GApiService } from './gapi.service';
@Injectable()
export class AuthGuard implements CanActivate {
constructor (private gapiService: GApiService, private router: Router) { }
canActivate (
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
const authenticated = this.gapiService.isAuthenticated();
if (!authenticated) {
this.router.navigate(['/']);
}
return authenticated;
}
}

View File

@@ -0,0 +1,15 @@
import { TestBed, inject } from '@angular/core/testing';
import { GApiService } from './gapi.service';
describe('GapiService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [GApiService]
});
});
it('should be created', inject([GApiService], (service: GApiService) => {
expect(service).toBeTruthy();
}));
});

84
src/app/gapi.service.ts Normal file
View File

@@ -0,0 +1,84 @@
import { bindCallback } from 'rxjs/Observable/bindCallback';
import { fromPromise } from 'rxjs/Observable/fromPromise';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
const API_KEY = 'AIzaSyA9BX0C-ku3NBkTSeHY59DiJi02U-DbCe0';
const CLIENT_ID = '505888163689-q01h4puni0e74t36m04mcksr0g7pti5v.apps.googleusercontent.com';
const DISCOVERY_DOCS: string[] = ['https://sheets.googleapis.com/$discovery/rest?version=v4'];
const SCOPES = 'https://www.googleapis.com/auth/spreadsheets.readonly';
function gapiRequestToObservable<T>(request: gapi.client.Request<T>): Observable<T> {
return fromPromise<gapi.client.Response<T>>(request).map(res => res.result);
}
/**
* Takes a positive integer and returns the corresponding column name.
* @param {number} num The positive integer to convert to a column name.
* @return {string} The column name.
*/
function numberToColumnName(num: number): string {
let ret = '';
for (; num > 0; num = Math.floor(num % 26)) {
num--; // because nobody starts counting columns at 0 and A needs to be 1
ret = String.fromCharCode(Math.floor(num % 26) + 65) + ret;
}
return ret;
}
@Injectable()
export class GApiService {
private observableGetAuthInstance: () => Observable<boolean>;
private authInstance: gapi.auth2.GoogleAuth;
constructor () {
gapi.load('client:auth2', () => {
gapi.client.init({
apiKey: API_KEY,
clientId: CLIENT_ID,
discoveryDocs: DISCOVERY_DOCS,
scope: SCOPES
}).then(() => {
this.authInstance = gapi.auth2.getAuthInstance();
// Listen for sign-in state changes.
this.observableGetAuthInstance = bindCallback<boolean>(this.authInstance.isSignedIn.listen);
});
});
}
get authStatusChange(): Observable<boolean> { return this.observableGetAuthInstance(); }
isAuthenticated (): boolean {
return this.authInstance.isSignedIn.get();
}
signIn (): void {
gapi.auth2.getAuthInstance().signIn();
}
signOut (): void {
gapi.auth2.getAuthInstance().signOut();
}
getSpreadsheet (id: string): Observable<gapi.client.sheets.Spreadsheet> {
return gapiRequestToObservable<gapi.client.sheets.Spreadsheet>(gapi.client.spreadsheets.get({
spreadsheetId: id
}));
}
getDataOnSheet (spreadsheetId: string, sheet: gapi.client.sheets.Sheet) {
gapi.client.spreadsheets.values.get({
spreadsheetId,
range: sheet.properties.title + '!A1:1',
majorDimension: 'ROWS'
}).then(firstRowResponse => {
const firstRow = firstRowResponse.result.values[0];
gapi.client.spreadsheets.values.get({
spreadsheetId,
range: sheet.properties.title + '!A1:' + numberToColumnName(firstRow.length)
});
});
}
}

View File

View File

@@ -0,0 +1,11 @@
<nav class="navbar navbar-inverse navbar-top">
<div class="container">
<div class="navbar-header">
<a routerLink="/" class="navbar-brand">QContacts</a>
<ul class="nav navbar-nav">
<li><a routerLink="/">Home</a></li>
</ul>
<div class="navbar-right" *ngIf="loggedIn"></div>
</div>
</div>
</nav>

View File

@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { HeaderComponent } from './header.component';
describe('HeaderComponent', () => {
let component: HeaderComponent;
let fixture: ComponentFixture<HeaderComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ HeaderComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(HeaderComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,26 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { GApiService } from '../gapi.service';
import { Subscription } from 'rxjs/Subscription';
@Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit, OnDestroy {
private sub: Subscription;
constructor(private gapiService: GApiService) {
}
loggedIn = false;
ngOnInit(): void {
this.loggedIn = this.gapiService.isAuthenticated();
this.sub = this.gapiService.authStatusChange.subscribe(newValue => this.loggedIn = newValue);
}
ngOnDestroy(): void {
this.sub.unsubscribe();
}
}

View File

View File

@@ -0,0 +1,3 @@
<p>
home works!
</p>

View File

@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { HomeComponent } from './home.component';
describe('HomeComponent', () => {
let component: HomeComponent;
let fixture: ComponentFixture<HomeComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ HomeComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(HomeComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,15 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}