Edit travel y AuthService

This commit is contained in:
Eneko Nieto
2021-02-09 20:55:23 +01:00
parent 8afe477620
commit e9d5ce4d8e
13 changed files with 95 additions and 41 deletions

View File

@@ -23,6 +23,7 @@ import { NewTravelComponent } from './pages/new-travel/new-travel.component';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { NgxMatMomentModule } from '@angular-material-components/moment-adapter';
import { AppRouterModule } from './router.module';
import { AvailablePlacesPipe } from './pipes/available-places.pipe';
// We need a factory, since localStorage is not available during AOT build time.
export function storageFactory(): OAuthStorage {
@@ -57,7 +58,8 @@ export function storageFactory(): OAuthStorage {
HeaderComponent,
ListComponent,
TravelFormComponent,
NewTravelComponent
NewTravelComponent,
AvailablePlacesPipe
],
providers: [
{ provide: OAuthStorage, useFactory: storageFactory }

View File

@@ -1,12 +1,12 @@
import { UserInfo } from './user-info';
import { User } from './user';
export type TravelId = number;
export class Travel {
constructor(
public id: TravelId = -1,
public driverInfo: UserInfo = null,
public travelersInfo: UserInfo[] = [],
public driverInfo: User = null,
public travelersInfo: User[] = [],
public departureDate: string = '',
public origin: string = '',
public destination: string = '',
@@ -14,4 +14,8 @@ export class Travel {
public matrixRoomId: string = '',
public description?: string
) { }
availablePlaces(): number {
return this.places - this.travelersInfo.length;
}
}

View File

@@ -1,8 +0,0 @@
export type UserId = string;
export interface UserInfo {
id: UserId;
username: string;
matrixId?: string;
name: string;
}

View File

@@ -1,8 +1,24 @@
export type UserId = string;
export interface User {
id: UserId;
username: string;
matrixId?: string;
name: string;
export class User {
constructor(
public id: UserId,
public username: string,
public matrixId: string = null,
public name: string,
public admin: boolean = false
) { }
static fromClaims(claims: object): User {
if (claims == null) {
return null;
}
return new User(
claims["sub"].toString(),
claims["preferred_username"].toString(),
claims["preferred_username"] + ':fosil.eu',
claims["name"].toString(),
claims["admin"] === true
);
}
}

View File

@@ -1,4 +1,5 @@
<div>
<h1>Editar viaje</h1>
<app-travel-form (travelSubmitted)="editTravel($event)" (travelCanceled)="cancel()" [travel]="travel" [acceptButtonText]="acceptButtonText"></app-travel-form>
<app-travel-form (travelSubmitted)="editTravel($event)" (travelCanceled)="cancel()" [travel]="travel"
[acceptButtonText]="acceptButtonText"></app-travel-form>
</div>

View File

@@ -13,4 +13,4 @@
</mat-card>
<button mat-raised-button class="btn btn-default" (click)="goBack()">Back</button>
<button *ngIf="logged" mat-raised-button class="btn btn-default" (click)="edit()">Edit</button>
<button *ngIf="canEdit" mat-raised-button class="btn btn-default" (click)="edit()">Edit</button>

View File

@@ -1,6 +1,6 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { OAuthService } from 'angular-oauth2-oidc';
import { AuthService } from 'src/app/services/auth.service';
import { Travel, TravelId } from '../../entities/travel';
import { ApiService } from '../../services/api.service';
@@ -16,7 +16,7 @@ export class TravelComponent implements OnInit {
constructor(
private router: Router,
private oauthService: OAuthService,
private authService: AuthService,
private apiService: ApiService,
private route: ActivatedRoute
) { }
@@ -45,8 +45,7 @@ export class TravelComponent implements OnInit {
this.router.navigateByUrl(`/travel/${this.travelId}/edit`);
}
get logged(): boolean {
return this.oauthService.getIdentityClaims() != null;
// return this.oauthService.hasValidIdToken() && this.oauthService.hasValidAccessToken();
get canEdit(): boolean {
return this.authService.canEditTravel(this.travel);
}
}

View File

@@ -0,0 +1,9 @@
import { Pipe, PipeTransform } from '@angular/core';
import { Travel } from '../entities/travel';
@Pipe({ name: 'availablePlaces' })
export class AvailablePlacesPipe implements PipeTransform {
transform(travel: Travel): number {
return travel.places - travel.travelersInfo.length;
}
}

View File

@@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';
import { AuthService } from './auth.service';
describe('AuthService', () => {
let service: AuthService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(AuthService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});

View File

@@ -0,0 +1,26 @@
import { Injectable } from '@angular/core';
import { OAuthService } from 'angular-oauth2-oidc';
import { Travel } from '../entities/travel';
import { User } from '../entities/user';
@Injectable({
providedIn: 'root'
})
export class AuthService {
constructor(private oauthService: OAuthService) { }
currentUser(): User {
const claims = this.oauthService.getIdentityClaims();
return User.fromClaims(claims);
}
canEditTravel(travel: Travel): boolean {
const user = this.currentUser();
if (user == null) {
return false;
}
return user.admin || (user.id === travel.driverInfo.id);
}
}

View File

@@ -4,19 +4,8 @@
margin: 0 auto;
}
.description-cell {
.mat-cell {
text-align: left;
margin: 10px auto;
}
.duration-cell {
text-align: center;
}
.duration-cell mat-icon {
display: inline-block;
vertical-align: middle;
font-size: 20px;
}
.spinner-container {
@@ -26,8 +15,8 @@
}
.travel-table {
min-height: 150px;
margin-top: 10px;
min-height: 100px;
margin: 10px;
}
.spinner-container mat-spinner {

View File

@@ -7,7 +7,7 @@
<mat-spinner></mat-spinner>
</div>
<mat-table class="travel-table mat-elevation-z8" [dataSource]="dataSource" matSort matSortActive="driver"
<mat-table class="travel-table mat-elevation-z8" [dataSource]="dataSource" matSort matSortActive="departureDate"
matSortDirection="asc" matSortDisableClear>
<ng-container matColumnDef="departureDate">
<mat-header-cell *matHeaderCellDef mat-sort-header>Departure date</mat-header-cell>
@@ -32,7 +32,7 @@
<ng-container matColumnDef="availablePlaces">
<mat-header-cell *matHeaderCellDef mat-sort-header>Available places</mat-header-cell>
<mat-cell *matCellDef="let travel">{{ travel.places - travel.travelersInfo.length }}</mat-cell>
<mat-cell *matCellDef="let travel">{{ travel | availablePlaces }}</mat-cell>
</ng-container>
<ng-container matColumnDef="driver">

View File

@@ -4,5 +4,5 @@ html, body { height: 100%; }
body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }
.mat-card {
margin: 20px;
margin: 40px;
}