Commit 161e3295 authored by David's avatar David
Browse files

Can display a card of the staging document!

parent 4e5f4fa6
......@@ -127,5 +127,8 @@
}
}
},
"defaultProject": "frontend"
"defaultProject": "frontend",
"cli": {
"analytics": "b1071caa-ca8a-408c-8c60-405d1c88f3e1"
}
}
\ No newline at end of file
import {NgModule} from '@angular/core';
import {Routes, RouterModule} from '@angular/router';
import {LoginComponent} from "./login/login.component";
import {DocumentManagerComponent} from "./document-manager/document-manager.component";
import {AuthenticatedGuard} from "./authenticated.guard";
import {LoginComponent} from './login/login.component';
import {DocumentManagerComponent} from './document-manager/document-manager.component';
import {AuthenticatedGuard} from './authenticated.guard';
const routes: Routes = [
......
......@@ -5,20 +5,24 @@ import {AppRoutingModule} from './app-routing.module';
import {AppComponent} from './app.component';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {LoginComponent} from './login/login.component';
import {ReactiveFormsModule} from "@angular/forms";
import {MatFormFieldModule} from "@angular/material/form-field";
import {MatIconModule} from "@angular/material/icon";
import {MatInputModule} from "@angular/material/input";
import {MatButtonModule} from "@angular/material/button";
import {HttpClientModule} from "@angular/common/http";
import { StorageModule } from '@ngx-pwa/local-storage';
import { DocumentManagerComponent } from './document-manager/document-manager.component';
import {ReactiveFormsModule} from '@angular/forms';
import {MatFormFieldModule} from '@angular/material/form-field';
import {MatIconModule} from '@angular/material/icon';
import {MatInputModule} from '@angular/material/input';
import {MatButtonModule} from '@angular/material/button';
import {HTTP_INTERCEPTORS, HttpClientModule} from '@angular/common/http';
import {StorageModule} from '@ngx-pwa/local-storage';
import {DocumentManagerComponent} from './document-manager/document-manager.component';
import {TokenInterceptor} from './token-interceptor';
import { StagingDocumentComponent } from './document-manager/staging-document/staging-document.component';
import {MatCardModule} from '@angular/material/card';
@NgModule({
declarations: [
AppComponent,
LoginComponent,
DocumentManagerComponent
DocumentManagerComponent,
StagingDocumentComponent
],
imports: [
BrowserModule,
......@@ -30,9 +34,12 @@ import { DocumentManagerComponent } from './document-manager/document-manager.co
MatInputModule,
MatButtonModule,
HttpClientModule,
StorageModule.forRoot({ IDBNoWrap: true })
StorageModule.forRoot({IDBNoWrap: true}),
MatCardModule
],
providers: [
{provide: HTTP_INTERCEPTORS, useClass: TokenInterceptor, multi: true},
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {
......
import { Injectable } from '@angular/core';
import { CanActivate, CanActivateChild, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree } from '@angular/router';
import { Observable } from 'rxjs';
import {StorageMap} from "@ngx-pwa/local-storage";
import {Injectable} from '@angular/core';
import {CanActivate, CanActivateChild, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree, Router} from '@angular/router';
import {Observable} from 'rxjs';
import {LoginService} from './login/login.service';
import {map, tap} from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class AuthenticatedGuard implements CanActivate, CanActivateChild {
constructor(private readonly storageMap: StorageMap) {}
constructor(private readonly loginService: LoginService,
private readonly router: Router) {
}
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
//Check to see if we have an auth token in storage, and if it's valid somehow?
return true;
return this.validate();
}
canActivateChild(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
return true;
return this.validate();
}
private validate(): Observable<boolean | UrlTree> {
console.log('VALIDATING LOGIN');
return this.loginService.validateToken().pipe(
tap(result => console.log('result is', result)),
map(result => {
if (!result) {
// return a URL tree to login
return this.router.createUrlTree(['login']);
}
return result;
})
);
}
}
<p>document-manager works!</p>
<p>Staged Documents</p>
<div *ngIf="loading">
Loading...
</div>
<div *ngIf="!loading" class="staging-documents-list">
<div *ngFor="let stagingFile of (stagingFiles | async)">
<app-staging-document [stagingFolderFile]="stagingFile"></app-staging-document>
</div>
</div>
.staging-documents-list {
display: flex;
justify-content: left;
flex-direction: row;
}
import { Component, OnInit } from '@angular/core';
import {EMPTY, Observable, of, timer} from 'rxjs';
import {flatMap, tap} from 'rxjs/operators';
import {DocumentService} from './document.service';
import {StagingFolderFile} from '../mayan-api';
@Component({
selector: 'app-document-manager',
......@@ -7,9 +11,22 @@ import { Component, OnInit } from '@angular/core';
})
export class DocumentManagerComponent implements OnInit {
constructor() { }
loading = false;
stagingFiles: Observable<[StagingFolderFile]> = EMPTY;
constructor(private readonly documentService: DocumentService) { }
ngOnInit() {
// load staging documents, display them create a timer to update the list
timer(0, 5000).pipe(
tap( m => this.loading = true),
flatMap(m => this.documentService.loadStagingFiles()),
tap(stagingFiles => {
this.stagingFiles = of(stagingFiles);
this.loading = false;
})
).subscribe(); // todo, need the destroy, or do this differently
}
}
import { TestBed } from '@angular/core/testing';
import { DocumentService } from './document.service';
describe('DocumentServiceService', () => {
let service: DocumentService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(DocumentService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
import { Injectable } from '@angular/core';
import {Observable, of} from 'rxjs';
import {MayanResult, StagingFolder, StagingFolderFile} from '../mayan-api';
import {HttpClient} from '@angular/common/http';
import {environment} from '../../environments/environment';
import {flatMap, map} from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class DocumentService {
constructor(private readonly httpClient: HttpClient) { }
loadStagingFiles(page?: number ): Observable<[StagingFolderFile]> {
return this.httpClient.get<MayanResult<StagingFolder>>(`${environment.mayan}/staging_folders/`).pipe(
map(result => {
return result.results[0];
}),
flatMap(stagingFolder => of(stagingFolder.files))
);
}
}
<mat-card class="example-card">
<mat-card-header>
<div mat-card-avatar class="example-header-image"></div>
<mat-card-title>{{stagingFolderFile.filename}}</mat-card-title>
</mat-card-header>
<img mat-card-image src="{{stagingFolderFile.image_url}}" alt="Staging Document Preview">
<mat-card-actions>
<button mat-button>Import</button>
<button mat-button>Discard</button>
</mat-card-actions>
</mat-card>
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { StagingDocumentComponent } from './staging-document.component';
describe('StagingDocumentComponent', () => {
let component: StagingDocumentComponent;
let fixture: ComponentFixture<StagingDocumentComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ StagingDocumentComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(StagingDocumentComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import {Component, Input, OnInit} from '@angular/core';
import {StagingFolderFile} from '../../mayan-api';
@Component({
selector: 'app-staging-document',
templateUrl: './staging-document.component.html',
styleUrls: ['./staging-document.component.scss']
})
export class StagingDocumentComponent implements OnInit {
@Input() stagingFolderFile: StagingFolderFile;
constructor() { }
ngOnInit(): void {
}
}
import {Component, OnInit} from '@angular/core';
import {FormControl, FormGroup, Validators} from "@angular/forms";
import {environment} from "../../environments/environment";
import {LoginService} from "./login.service";
import {map} from "rxjs/operators";
import {FormControl, FormGroup, Validators} from '@angular/forms';
import {LoginService} from './login.service';
import {Router} from '@angular/router';
import {tap} from 'rxjs/operators';
@Component({
selector: 'app-login',
......@@ -17,18 +17,22 @@ export class LoginComponent implements OnInit {
password: new FormControl(''),
});
constructor(private readonly loginService: LoginService) {
constructor(private readonly loginService: LoginService,
private readonly router: Router) {
}
ngOnInit() {
}
doLogin() {
console.log("would post to mayan to do the needful", environment.mayan);
this.loginService.getAuthToken(this.loginForm.controls.username.value, this.loginForm.controls.password.value)
.subscribe( meh => {
//when it's complete, we need to navigate to the other thing
})
.pipe(
tap(what => console.log('login component', what)),
)
.subscribe(
something => {
// when it's complete, we need to navigate to the other thing
this.router.navigate(['/']);
});
}
}
import {Injectable} from '@angular/core';
import {HttpClient} from "@angular/common/http";
import {environment} from "../../environments/environment";
import {EMPTY, Observable} from "rxjs";
import {StorageMap} from "@ngx-pwa/local-storage";
import {flatMap, map} from "rxjs/operators";
import {HttpClient} from '@angular/common/http';
import {environment} from '../../environments/environment';
import {Observable} from 'rxjs';
import {StorageMap} from '@ngx-pwa/local-storage';
import {flatMap, map} from 'rxjs/operators';
import {User} from '../mayan-api';
@Injectable({
providedIn: 'root'
})
export class LoginService {
private AUTH_TOKEN = "authToken";
public static readonly AUTH_TOKEN = 'authToken';
constructor(private readonly httpClient: HttpClient,
private readonly storageMap: StorageMap) {
}
getAuthToken(username: String, password: String): Observable<undefined> {
getAuthToken(username: string, password: string): Observable<undefined> {
const request = {
username: username,
password: password
username,
password
} as LoginRequest;
return this.httpClient.post<TokenResponse>(`${environment.mayan}/auth/token/obtain/`, request).pipe(
flatMap(response => {
return this.storageMap.set(this.AUTH_TOKEN, response.token);
})
return this.storageMap.set(LoginService.AUTH_TOKEN, response.token);
}),
);
}
validateToken(): Observable<Boolean> {
this.storageMap.get(this.AUTH_TOKEN).pipe(
flatMap(
//Make HTTP call to validate token
)
validateToken(): Observable<boolean> {
return this.httpClient.get<User>(`${environment.mayan}/users/current/`).pipe(
map(results => results.id !== null ),
);
return EMPTY;
}
}
export interface LoginRequest {
username: String;
password: String;
username: string;
password: string;
}
export interface TokenResponse {
token: String;
token: string;
}
export interface MayanResult<T> {
count: number;
next: string;
previous: string;
results: [T];
}
export interface User {
first_name: string;
date_joined: string;
email: string;
groups: [any];
id: number;
is_active: boolean;
last_login: string;
last_name: string;
password: string;
url: string;
username: string;
}
export interface StagingFolder {
files: [StagingFolderFile];
}
export interface StagingFolderFile {
filename: string;
image_url: string;
url: string;
}
import {Injectable} from '@angular/core';
import {HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from '@angular/common/http';
import {Observable, of} from 'rxjs';
import {StorageMap} from '@ngx-pwa/local-storage';
import {LoginService} from './login/login.service';
import {environment} from '../environments/environment';
import {flatMap, map, tap} from 'rxjs/operators';
@Injectable()
export class TokenInterceptor implements HttpInterceptor {
constructor(private readonly storageMap: StorageMap) {
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// do not intercept logins
if (req.url === `${environment.mayan}/auth/token/obtain/`) {
return next.handle(req);
}
// Oof, remember to do observables right, dingus
return this.storageMap.has(LoginService.AUTH_TOKEN).pipe(
flatMap(has => {
if (has) {
return this.storageMap.get(LoginService.AUTH_TOKEN).pipe(
flatMap(authToken => {
const authReq = req.clone({ setHeaders: { Authorization: `Token ${authToken}` } });
return next.handle(authReq);
}),
);
} else {
return next.handle(req);
}
})
);
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment