This is a start

This commit is contained in:
Gardient
2018-01-13 10:31:39 +02:00
parent 7adda9976f
commit 9fdba4c7bd
13 changed files with 23 additions and 189 deletions

View File

@@ -1,7 +1,7 @@
{ {
"$schema": "./node_modules/@angular/cli/lib/config/schema.json", "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"project": { "project": {
"name": "q-contacts" "name": "gsheets-2-vcf"
}, },
"apps": [ "apps": [
{ {

View File

@@ -1,6 +1,6 @@
import { AppPage } from './app.po'; import { AppPage } from './app.po';
describe('q-contacts App', () => { describe('gsheets-2-vcf App', () => {
let page: AppPage; let page: AppPage;
beforeEach(() => { beforeEach(() => {

View File

@@ -1,5 +1,5 @@
{ {
"name": "q-contacts", "name": "gsheets-2-vcf",
"version": "0.0.0", "version": "0.0.0",
"license": "MIT", "license": "MIT",
"scripts": { "scripts": {
@@ -29,10 +29,6 @@
"@angular/cli": "1.6.3", "@angular/cli": "1.6.3",
"@angular/compiler-cli": "^5.0.0", "@angular/compiler-cli": "^5.0.0",
"@angular/language-service": "^5.0.0", "@angular/language-service": "^5.0.0",
"@types/gapi": "^0.0.35",
"@types/gapi.auth2": "^0.0.46",
"@types/gapi.client": "^1.0.0",
"@types/gapi.client.sheets": "^4.0.0",
"@types/jasmine": "~2.5.53", "@types/jasmine": "~2.5.53",
"@types/jasminewd2": "~2.0.2", "@types/jasminewd2": "~2.0.2",
"@types/node": "~6.0.60", "@types/node": "~6.0.60",

View File

@@ -3,8 +3,6 @@ import { Routes, RouterModule } from '@angular/router';
import { HomeComponent } from './home/home.component'; import { HomeComponent } from './home/home.component';
import { AuthGuard } from './auth.guard';
const routes: Routes = [ const routes: Routes = [
{ {
path: '', path: '',

View File

@@ -1,4 +1,10 @@
<app-header></app-header> <nav class="navbar navbar-inverse navbar-top">
<div class="container">
<div class="navbar-header">
<app-header></app-header>
</div>
</div>
</nav>
<div class="container"> <div class="container">
<router-outlet></router-outlet> <router-outlet></router-outlet>
</div> </div>

View File

@@ -6,7 +6,6 @@ import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
import { HeaderComponent } from './header/header.component'; import { HeaderComponent } from './header/header.component';
import { HomeComponent } from './home/home.component'; import { HomeComponent } from './home/home.component';
import { GApiService } from './gapi.service';
@NgModule({ @NgModule({
@@ -19,7 +18,7 @@ import { GApiService } from './gapi.service';
BrowserModule, BrowserModule,
AppRoutingModule AppRoutingModule
], ],
providers: [GApiService], providers: [],
bootstrap: [AppComponent] bootstrap: [AppComponent]
}) })
export class AppModule { } export class AppModule { }

View File

@@ -1,15 +0,0 @@
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();
}));
});

View File

@@ -1,19 +0,0 @@
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

@@ -1,15 +0,0 @@
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();
}));
});

View File

@@ -1,84 +0,0 @@
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

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

View File

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

View File

@@ -185,26 +185,6 @@
version "0.0.11" version "0.0.11"
resolved "https://registry.yarnpkg.com/@schematics/schematics/-/schematics-0.0.11.tgz#c8f70f270ed38f29b2873248126fd59abd635862" resolved "https://registry.yarnpkg.com/@schematics/schematics/-/schematics-0.0.11.tgz#c8f70f270ed38f29b2873248126fd59abd635862"
"@types/gapi.auth2@^0.0.46":
version "0.0.46"
resolved "https://registry.yarnpkg.com/@types/gapi.auth2/-/gapi.auth2-0.0.46.tgz#5c929d3e66d74b84293c65aaa0ce12e0f8d4fb36"
dependencies:
"@types/gapi" "*"
"@types/gapi.client.sheets@^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/@types/gapi.client.sheets/-/gapi.client.sheets-4.0.0.tgz#bfc4f4f24a0292da3b4d7b561d6d67ded7b11ebb"
dependencies:
"@types/gapi.client" "*"
"@types/gapi.client@*", "@types/gapi.client@^1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@types/gapi.client/-/gapi.client-1.0.0.tgz#aa42501465fcf6440421050da70ec724d4c4c4df"
"@types/gapi@*", "@types/gapi@^0.0.35":
version "0.0.35"
resolved "https://registry.yarnpkg.com/@types/gapi/-/gapi-0.0.35.tgz#8e0d672d66d8c6ce8493f5e8e550344f7ff500dc"
"@types/jasmine@*": "@types/jasmine@*":
version "2.8.3" version "2.8.3"
resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-2.8.3.tgz#f910edc67d69393d562d10f8f3d205ea3f3306bf" resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-2.8.3.tgz#f910edc67d69393d562d10f8f3d205ea3f3306bf"