Beginning of travel form

This commit is contained in:
Eneko Nieto
2021-01-30 00:34:07 +01:00
parent e02c4987d6
commit dd379be164
27 changed files with 215 additions and 40 deletions

View File

@@ -3,20 +3,24 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';
import { OAuthModule } from 'angular-oauth2-oidc';
import { HttpClientModule } from '@angular/common/http';
import { RouterModule, ExtraOptions } from '@angular/router';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { AppComponent } from './app.component';
import { APP_ROUTES } from './app.routes';
import { USER_API_URL, TRAVEL_API_URL } from './app.config';
import { HomeComponent } from './home/home.component';
import { TravelComponent } from './travel/travel.component';
import { SharedModule } from './shared/shared.module';
import { RouterModule, ExtraOptions } from '@angular/router';
import { useHash } from '../flags';
import { HeaderComponent } from './header/header.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { ListComponent } from './list/list.component';
import { MaterialModule } from './material/material.module';
import { HomeComponent } from './pages/home/home.component';
import { TravelComponent } from './pages/travel/travel.component';
import { EditTravelComponent } from './pages/edit-travel/edit-travel.component';
import { HeaderComponent } from './views/header/header.component';
import { ListComponent } from './views/list/list.component';
import { TravelFormComponent } from './views/travel-form/travel-form.component';
const ROUTING_OPTIONS: ExtraOptions = {
// preloadingStrategy: CustomPreloadingStrategy,
useHash,
@@ -44,8 +48,10 @@ const ROUTING_OPTIONS: ExtraOptions = {
AppComponent,
HomeComponent,
TravelComponent,
EditTravelComponent,
HeaderComponent,
ListComponent
ListComponent,
TravelFormComponent
],
providers: [
// (useHash) ? { provide: LocationStrategy, useClass: HashLocationStrategy } : [],

View File

@@ -1,6 +1,7 @@
import { Routes } from '@angular/router';
import { HomeComponent } from './home/home.component';
import { TravelComponent } from './travel/travel.component';
import { EditTravelComponent } from './pages/edit-travel/edit-travel.component';
import { HomeComponent } from './pages/home/home.component';
import { TravelComponent } from './pages/travel/travel.component';
export let APP_ROUTES: Routes = [
{
@@ -16,6 +17,14 @@ export let APP_ROUTES: Routes = [
path: 'travel/:id',
component: TravelComponent
},
{
path: 'travel/new',
component: EditTravelComponent
},
{
path: 'travel/:id/edit',
component: EditTravelComponent
},
{
path: '**',
redirectTo: 'home'

View File

@@ -37,7 +37,7 @@ export const authConfig: AuthConfig = {
useSilentRefresh: useSilentRefreshForCodeFlow,
showDebugInformation: true,
showDebugInformation: false,
sessionChecksEnabled: true,
sessionCheckIntervall: 10000,

View File

@@ -1,15 +1,15 @@
import { User } from './user';
import { UserInfo } from './user-info';
export type TravelId = number;
export interface Travel {
id: Travel;
driver: User;
travelers: User[];
driverInfo: UserInfo;
travelersInfo: UserInfo[];
departureDate: string;
origin: string;
destination: string;
availablePlaces: number;
places: number;
description?: string;
matrixRoomId: string;
}

View File

@@ -1,6 +1,6 @@
export type UserId = string;
export interface User {
export interface UserInfo {
id: UserId;
matrixId?: string;
name: string;

View File

@@ -0,0 +1,4 @@
<div>
<h1>Editar</h1>
</div>

View File

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

View File

@@ -0,0 +1,35 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { PUBLIC_API_URL } from '../../app.config';
import { Travel, TravelId } from '../../entities/travel';
import { ApiService } from '../../services/api.service';
@Component({
selector: 'app-edit-travel',
templateUrl: './edit-travel.component.html',
styleUrls: ['./edit-travel.component.css']
})
export class EditTravelComponent implements OnInit {
travel: Travel;
constructor(
private apiService: ApiService,
private route: ActivatedRoute
) { }
ngOnInit(): void {
this.route.queryParams.subscribe(params => {
const travelId = this.route.snapshot.paramMap.get('id') as unknown as TravelId;
this.apiService.call<Travel>(PUBLIC_API_URL + '/travel', { travelId })
.subscribe(res => {
if (res.success) {
this.travel = res.data;
}
else {
console.error('Error getting travel ' + travelId + ': ' + res.error);
}
});
});
}
}

View File

@@ -1,8 +1,8 @@
import { Component, OnInit } from '@angular/core';
import { OAuthService } from 'angular-oauth2-oidc';
import { ActivatedRoute, Router } from '@angular/router';
import { ApiService } from '../services/api.service';
import { Travel } from '../entities/travel';
import { ApiService } from '../../services/api.service';
import { Travel } from '../../entities/travel';
@Component({
templateUrl: './home.component.html',

View File

@@ -3,11 +3,11 @@
{{ travel.origin }} - {{ travel.destination }}
</mat-card-title>
<mat-card-subtitle>
{{ travel.departureDate }} Plazas libres: {{ travel.availablePlaces }}
{{ travel.departureDate }} Plazas: {{ travel.places - travel.travelersInfo.length }}/{{ travel.places }}
</mat-card-subtitle>
<mat-card-content>
<p>ID: {{ travel.id }}</p>
<p>Conductor: {{ travel.driver.name }}</p><br>
<p>Conductor: {{ travel.driverInfo.name }}</p><br>
<p>{{ travel.description }}</p>
</mat-card-content>
</mat-card>

View File

@@ -1,8 +1,8 @@
import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRoute, ParamMap } from '@angular/router';
import { PUBLIC_API_URL } from '../app.config';
import { Travel, TravelId } from '../entities/travel';
import { ApiService } from '../services/api.service';
import { PUBLIC_API_URL } from '../../app.config';
import { Travel, TravelId } from '../../entities/travel';
import { ApiService } from '../../services/api.service';
@Component({
selector: 'app-travel',

View File

@@ -1,6 +1,6 @@
import { Component, OnInit } from '@angular/core';
import { OAuthService } from 'angular-oauth2-oidc';
import { authConfig } from '../auth.config';
import { authConfig } from '../../auth.config';
@Component({
selector: 'app-header',

View File

@@ -13,7 +13,7 @@ import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { debounceTime, distinctUntilChanged, tap } from 'rxjs/operators';
import { merge, fromEvent, Observable, Subscriber } from 'rxjs';
import { ApiService } from '../services/api.service';
import { ApiService } from '../../services/api.service';
import { ListDataSource } from './list.datasource';
import { emit } from 'process';

View File

@@ -1,9 +1,9 @@
import { CollectionViewer, DataSource } from '@angular/cdk/collections';
import { Observable, BehaviorSubject, of } from 'rxjs';
import { Observable, BehaviorSubject, of, throwError } from 'rxjs';
import { catchError, finalize } from 'rxjs/operators';
import { ApiResponse } from '../entities/api-response';
import { ListDto } from '../entities/list-dto';
import { ApiService } from '../services/api.service';
import { ApiResponse } from '../../entities/api-response';
import { ListDto } from '../../entities/list-dto';
import { ApiService } from '../../services/api.service';
export class ListDataSource<T> implements DataSource<T> {
private listSubject = new BehaviorSubject<T[]>([]);
@@ -11,7 +11,7 @@ export class ListDataSource<T> implements DataSource<T> {
public loading$ = this.loadingSubject.asObservable();
public total = 0;
constructor(private apiService: ApiService, private url: string) {}
constructor(private apiService: ApiService, private url: string) { }
load(
filter: string,
@@ -23,21 +23,27 @@ export class ListDataSource<T> implements DataSource<T> {
this.loadingSubject.next(true);
this.apiService.call<ListDto<T>>(this.url, {
filter,
sortColumn,
sortAscending,
pageIndex,
pageSize,
})
filter,
sortColumn,
sortAscending,
pageIndex,
pageSize,
})
.pipe(
catchError(() => of([])),
catchError(() => throwError('Error al obtener datos de la lista.')),
finalize(() => this.loadingSubject.next(false))
)
.subscribe((res) => {
const listDto = (res as ApiResponse<ListDto<T>>).data;
const list = listDto.list;
this.total = listDto.total;
this.listSubject.next(list);
const apiResponse = res as ApiResponse<ListDto<T>>;
if (apiResponse.success) {
const listDto = (res as ApiResponse<ListDto<T>>).data;
const list = listDto.list;
this.total = listDto.total;
this.listSubject.next(list);
}
else {
console.error('Error en list.datasource.ts: ' + apiResponse.error.code + ' ' + apiResponse.error.msg);
}
});
}

View File

@@ -0,0 +1,44 @@
<form (ngSubmit)="onSubmit()" #travelForm="ngForm">
<div>
<label for="origin">Origen</label>
<input type="text" id="origin" required [(ngModel)]="travel.origin" name="origin" #origin="ngModel">
<div [hidden]="origin.valid || origin.pristine" class="alert alert-danger">
El origen es obligatorio
</div>
</div>
<div>
<label for="destination">Destino</label>
<input type="text" id="destination" required [(ngModel)]="travel.destination" name="destination" #destination="ngModel">
<div [hidden]="destination.valid || destination.pristine" class="alert alert-danger">
El destino es obligatorio
</div>
</div>
<div>
<label for="places">Plazas</label>
<input type="number" id="places" required [(ngModel)]="travel.places" name="places" #places="ngModel">
<div [hidden]="places.valid || places.pristine" class="alert alert-danger">
El destino es obligatorio
</div>
</div>
<div>
<label for="description">Descripción</label>
<input type="text" id="description" required [(ngModel)]="travel.description" name="description" #description="ngModel">
</div>
<!-- <div>
<label for="power">Hero Power</label>
<select id="power" required [(ngModel)]="model.power" name="power" #power="ngModel">
<option *ngFor="let pow of powers" [value]="pow">{{pow}}</option>
</select>
<div [hidden]="power.valid || power.pristine" class="alert alert-danger">
Power is required
</div>
</div> -->
<button type="submit" class="btn btn-success" [disabled]="!travelForm.form.valid">Submit</button>
</form>

View File

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

View File

@@ -0,0 +1,21 @@
import { Component, OnInit } from '@angular/core';
import { Travel } from 'src/app/entities/travel';
@Component({
selector: 'app-travel-form',
templateUrl: './travel-form.component.html',
styleUrls: ['./travel-form.component.css']
})
export class TravelFormComponent implements OnInit {
travel: Travel;
submitted = false;
constructor() { }
ngOnInit(): void {
}
onSubmit(): void {
this.submitted = true;
}
}