Forráskód Böngészése

Events list page prototype

Lukas Angerer 3 éve
szülő
commit
105f236227

+ 12 - 0
src/RunnersMeet.Client/src/app/app-routing.module.ts

@@ -1,7 +1,9 @@
 import { NgModule } from '@angular/core';
 import { RouterModule, Routes } from '@angular/router';
 import { AuthGuard } from '@auth0/auth0-angular';
+import { EditEventPageComponent } from './pages/edit-event-page/edit-event-page.component';
 import { EditTrackPageComponent } from './pages/edit-track-page/edit-track-page.component';
+import { EventsPageComponent } from './pages/events-page/events-page.component';
 import { HomePageComponent } from './pages/home-page/home-page.component';
 import { TracksPageComponent } from './pages/tracks-page/tracks-page.component';
 import { ViewTrackPageComponent } from './pages/view-track-page/view-track-page.component';
@@ -26,6 +28,16 @@ const routes: Routes = [
 		component: ViewTrackPageComponent,
 		canActivate: [AuthGuard],
 	},
+	{
+		path: 'events',
+		component: EventsPageComponent,
+		canActivate: [AuthGuard],
+	},
+	{
+		path: 'events/edit/:oid',
+		component: EditEventPageComponent,
+		canActivate: [AuthGuard],
+	},
 ];
 
 @NgModule({

+ 7 - 1
src/RunnersMeet.Client/src/app/app.module.ts

@@ -33,6 +33,9 @@ import { MatCardModule } from '@angular/material/card';
 import { MatCheckboxModule } from '@angular/material/checkbox';
 import { MatFormFieldModule } from '@angular/material/form-field';
 import { MatInputModule } from '@angular/material/input';
+import { EventsPageComponent } from './pages/events-page/events-page.component';
+import { EditEventPageComponent } from './pages/edit-event-page/edit-event-page.component';
+import { EventsApiService } from './events-api.service';
 
 @NgModule({
 	declarations: [
@@ -46,6 +49,8 @@ import { MatInputModule } from '@angular/material/input';
 		TrackViewComponent,
 		ViewTrackPageComponent,
 		MainMenuComponent,
+  EventsPageComponent,
+  EditEventPageComponent,
 	],
 	imports: [
 		BrowserModule,
@@ -80,7 +85,8 @@ import { MatInputModule } from '@angular/material/input';
 		},
 		UsersApiService,
 		PermissionService,
-		TracksApiService
+		TracksApiService,
+		EventsApiService,
 	],
 	bootstrap: [AppComponent]
 })

+ 26 - 0
src/RunnersMeet.Client/src/app/events-api.service.ts

@@ -0,0 +1,26 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+import { lastValueFrom } from 'rxjs';
+import { ConfigService } from './config.service';
+import { EventSearchParams } from './events/event-search-params';
+import { GroupEvent } from './events/group-event';
+import { ResultPage } from './result-page';
+
+@Injectable({
+	providedIn: 'root'
+})
+export class EventsApiService {
+
+	public constructor(
+		private readonly config: ConfigService,
+		private readonly http: HttpClient
+	) { }
+
+	public getEvents(searchParams: EventSearchParams): Promise<ResultPage<GroupEvent>> {
+		return lastValueFrom(this.http.get<ResultPage<GroupEvent>>(this.config.apiUri(`/api/events`), { params: searchParams.toHttpParams() }));
+	}
+
+	public createEvent(formData: FormData): Promise<GroupEvent> {
+		return lastValueFrom(this.http.post<GroupEvent>(this.config.apiUri(`/api/events`), formData));
+	}
+}

+ 19 - 0
src/RunnersMeet.Client/src/app/events/event-search-params.ts

@@ -0,0 +1,19 @@
+import { HttpParams } from "@angular/common/http";
+
+export class EventSearchParams {
+	public owner?: string;
+	public filter?: string;
+	public page: number = 0;
+
+	public toHttpParams(): HttpParams {
+		let result = new HttpParams();
+		if (this.owner) {
+			result = result.set('owner', this.owner);
+		}
+		if (this.filter) {
+			result = result.set('filter', this.filter);
+		}
+		result = result.set('page', this.page);
+		return result;
+	}
+}

+ 12 - 0
src/RunnersMeet.Client/src/app/events/group-event.ts

@@ -0,0 +1,12 @@
+import { Track } from "../tracks/track";
+import { UserProfile } from "../users/user-profile";
+
+export class GroupEvent {
+	public eventId: string = '';
+	public owner: UserProfile = new UserProfile();
+	public startTime?: Date;
+	public duration?: number = 0;
+	public title: string = '';
+	public description: string = '';
+	public track?: Track;
+}

+ 1 - 0
src/RunnersMeet.Client/src/app/pages/edit-event-page/edit-event-page.component.html

@@ -0,0 +1 @@
+<p>edit-event-page works!</p>

+ 0 - 0
src/RunnersMeet.Client/src/app/pages/edit-event-page/edit-event-page.component.scss


+ 23 - 0
src/RunnersMeet.Client/src/app/pages/edit-event-page/edit-event-page.component.spec.ts

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

+ 10 - 0
src/RunnersMeet.Client/src/app/pages/edit-event-page/edit-event-page.component.ts

@@ -0,0 +1,10 @@
+import { Component } from '@angular/core';
+
+@Component({
+  selector: 'app-edit-event-page',
+  templateUrl: './edit-event-page.component.html',
+  styleUrls: ['./edit-event-page.component.scss']
+})
+export class EditEventPageComponent {
+
+}

+ 22 - 0
src/RunnersMeet.Client/src/app/pages/events-page/events-page.component.html

@@ -0,0 +1,22 @@
+<h1>Events</h1>
+<a mat-icon-button [routerLink]="['/events/edit/new']"><mat-icon aria-hidden="false" aria-label="Create" fontIcon="add_circle"></mat-icon></a>
+
+<form class="vertical-form" (ngSubmit)="search($event)">
+	<mat-checkbox name="showMyEvents" [(ngModel)]="showMyEvents">
+		Show <em>my</em> events
+	</mat-checkbox>
+	<mat-form-field appearance="fill">
+		<mat-label>Event title</mat-label>
+		<input matInput name="titleFilter" [(ngModel)]="titleFilter">
+	</mat-form-field>
+
+	<div class="button-group">
+		<button type="submit" mat-raised-button color="accent">Search</button>
+	</div>
+</form>
+
+<ul>
+	<li *ngFor="let event of groupEvents | async">{{ event.title }}</li>
+</ul>
+
+<button mat-raised-button color="accent" [disabled]="!hasMore" (click)="loadMore()">More</button>

+ 0 - 0
src/RunnersMeet.Client/src/app/pages/events-page/events-page.component.scss


+ 23 - 0
src/RunnersMeet.Client/src/app/pages/events-page/events-page.component.spec.ts

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

+ 52 - 0
src/RunnersMeet.Client/src/app/pages/events-page/events-page.component.ts

@@ -0,0 +1,52 @@
+import { Component } from '@angular/core';
+import { Subject } from 'rxjs';
+import { EventsApiService } from 'src/app/events-api.service';
+import { EventSearchParams } from 'src/app/events/event-search-params';
+import { GroupEvent } from 'src/app/events/group-event';
+
+@Component({
+  selector: 'app-events-page',
+  templateUrl: './events-page.component.html',
+  styleUrls: ['./events-page.component.scss']
+})
+export class EventsPageComponent {
+	private _groupEvents: GroupEvent[] = [];
+	public groupEvents: Subject<GroupEvent[]> = new Subject<GroupEvent[]>();
+	public hasMore: boolean = false;
+
+	public showMyEvents: boolean = false;
+	public titleFilter: string = '';
+
+	private searchParams: EventSearchParams = new EventSearchParams();
+
+	public constructor(
+		private readonly eventsApi: EventsApiService
+	) {
+		this.updateEvents();
+	}
+
+	public search(event: SubmitEvent): void {
+		this.searchParams = new EventSearchParams();
+		this.searchParams.owner = this.showMyEvents ? 'me' : undefined;
+		this.searchParams.filter = this.titleFilter ? this.titleFilter : undefined;
+		this.updateEvents();
+	}
+
+	public loadMore(): void {
+		this.searchParams.page++;
+		this.updateEvents();
+	}
+
+	private updateEvents(): void {
+		this.eventsApi.getEvents(this.searchParams)
+			.then(eventsPage => {
+				if (this.searchParams.page === 0) {
+					this._groupEvents = eventsPage.items;
+				} else {
+					this._groupEvents.push(...eventsPage.items);
+				}
+				this.hasMore = eventsPage.hasMore;
+				this.groupEvents.next(this._groupEvents);
+			});
+	}
+}

+ 1 - 0
src/RunnersMeet.Client/src/app/shell/main-menu/main-menu.component.html

@@ -6,6 +6,7 @@
 			<a mat-list-item [routerLink]="['/']">Home</a>
 			<a mat-list-item [routerLink]="['/tracks']">Tracks</a>
 			<a mat-list-item [routerLink]="['/tracks/edit/new']">Create Track</a>
+			<a mat-list-item [routerLink]="['/events']">Events</a>
 			<a mat-list-item href="#" (click)="logout()">Logout</a>
 		</mat-nav-list>
 	</mat-sidenav>