Add course alias and custom titles for components

This commit is contained in:
Norbi Peti 2022-03-13 00:06:31 +01:00
parent 9f78639690
commit 8cd769ff7f
No known key found for this signature in database
GPG key ID: DBA4C4549A927E56
10 changed files with 53 additions and 13 deletions

View file

@ -1,4 +1,4 @@
import { Entity, model, property, belongsTo, hasMany } from '@loopback/repository'; import { belongsTo, Entity, hasMany, model, property } from '@loopback/repository';
import { Subject } from './subject.model'; import { Subject } from './subject.model';
import { User } from './user.model'; import { User } from './user.model';
import { CourseUser } from './course-user.model'; import { CourseUser } from './course-user.model';
@ -19,6 +19,12 @@ export class Course extends Entity {
}) })
semester: string; semester: string;
@property({
type: 'string',
required: true,
})
alias: string;
@belongsTo(() => Subject) @belongsTo(() => Subject)
subjectId: number; subjectId: number;

View file

@ -35,7 +35,7 @@
</mat-toolbar> </mat-toolbar>
<div style="margin: 20px"> <div style="margin: 20px">
<!-- <mat-slider min="1" max="100" step="1" value="1"></mat-slider> --> <!-- <mat-slider min="1" max="100" step="1" value="1"></mat-slider> -->
<router-outlet></router-outlet> <router-outlet (activate)="routeActivated($event)"></router-outlet>
</div> </div>
</mat-sidenav-content> </mat-sidenav-content>
</mat-sidenav-container> </mat-sidenav-container>

View file

@ -31,6 +31,8 @@ export class AppComponent implements OnInit {
pageTitle: string; pageTitle: string;
private activeRouteTitle: string;
constructor(private breakpointObserver: BreakpointObserver, public loginService: LoginService, private api: ApiService, constructor(private breakpointObserver: BreakpointObserver, public loginService: LoginService, private api: ApiService,
private router: Router, private login: LoginService, private activeRoute: ActivatedRoute, private router: Router, private login: LoginService, private activeRoute: ActivatedRoute,
private title: Title) { private title: Title) {
@ -102,7 +104,11 @@ export class AppComponent implements OnInit {
this.pageTitle = 'Szakdolgozat'; this.pageTitle = 'Szakdolgozat';
return this.title.setTitle('Szakdolgozat'); return this.title.setTitle('Szakdolgozat');
} }
let pageTitle = routeParts.reverse().map(part => part.title).reduce((partA, partI) => `${partA} > ${partI}`); const titleParts = routeParts.reverse().map(part => part.title);
if (this.activeRouteTitle) {
titleParts[titleParts.length - 1] = this.activeRouteTitle;
}
let pageTitle = titleParts.reduce((partA, partI) => `${partA} > ${partI}`);
this.pageTitle = pageTitle; this.pageTitle = pageTitle;
pageTitle += ` | Szakdolgozat`; pageTitle += ` | Szakdolgozat`;
this.title.setTitle(pageTitle); this.title.setTitle(pageTitle);
@ -117,7 +123,24 @@ export class AppComponent implements OnInit {
getMenuItems(): MenuItem[] { getMenuItems(): MenuItem[] {
return this.menu.filter(item => item.requiredRole === 'admin' ? this.login.user?.isAdmin : true); // TODO: Roles return this.menu.filter(item => item.requiredRole === 'admin' ? this.login.user?.isAdmin : true); // TODO: Roles
} }
routeActivated($event: any): void {
if (this.isCustomTitleComponent($event)) {
this.activeRouteTitle = $event.getPageTitle();
} else {
this.activeRouteTitle = null;
}
}
isCustomTitleComponent(obj: any): obj is CustomTitleComponent {
return obj?.getPageTitle instanceof Function;
}
} }
type MenuItem = { path: string, requiredRole: UserRole | 'admin', title?: string }; type MenuItem = { path: string, requiredRole: UserRole | 'admin', title?: string };
type RouteSegment = { title: string, url: string }; type RouteSegment = { title: string, url: string };
export interface CustomTitleComponent {
getPageTitle(): string;
}

View file

@ -3,4 +3,5 @@ import { Model } from './model';
export class Course extends Model { export class Course extends Model {
semester: string; semester: string;
subjectId: number; subjectId: number;
alias: string;
} }

View file

@ -37,10 +37,11 @@ export class ListComponent<T extends Model> implements OnInit {
async getItems(limit: number, page: number): Promise<void> { async getItems(limit: number, page: number): Promise<void> {
try { try {
this.loading = true; this.loading = true;
const total = await this.api.requestItemCount(this.apiPath); if (!this.paginationData.total) {
this.paginationData.total = await this.api.requestItemCount(this.apiPath);
}
this.paginationData.page = page; this.paginationData.page = page;
this.paginationData.limit = limit; this.paginationData.limit = limit;
this.paginationData.total = total;
this.items = await this.api.requestPage<T>(this.apiPath, limit, page); this.items = await this.api.requestPage<T>(this.apiPath, limit, page);
} finally { } finally {
this.loading = false; this.loading = false;
@ -53,6 +54,6 @@ export class ListComponent<T extends Model> implements OnInit {
} }
async newItem(): Promise<void> { async newItem(): Promise<void> {
await this.router.navigate([this.router.url, 'new']); await this.router.navigate([this.router.url, 'new']);
} }
} }

View file

@ -1,3 +1,4 @@
<app-edit #edit [itemType]="itemType" apiPath="/courses" [beforeSubmit]="beforeSubmit" [fields]="[ <app-edit #edit [itemType]="itemType" apiPath="/courses" [beforeSubmit]="beforeSubmit" [fields]="[
{title: 'Félév', name: 'semester'} {title: 'Félév', name: 'semester'},
{title: 'Név', name: 'alias'}
]"></app-edit> ]"></app-edit>

View file

@ -1,3 +1,4 @@
<app-list [apiPath]="'/subjects/'+subjectId+'/courses'" [itemType]="itemType" allowNew="true" [columns]="[ <app-list #list [apiPath]="'/subjects/'+subjectId+'/courses'" [itemType]="itemType" allowNew="true" [columns]="[
{prop: 'semester', title: 'Félév'} {prop: 'semester', title: 'Félév'},
{prop: 'alias', title: 'Név'}
]"></app-list> ]"></app-list>

View file

@ -1,15 +1,18 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit, ViewChild } from '@angular/core';
import { ActivatedRoute } from '@angular/router'; import { ActivatedRoute } from '@angular/router';
import { Course } from '../../../../model/course.model'; import { Course } from '../../../../model/course.model';
import { ListComponent } from '../../../../shared-components/list/list.component';
import { CustomTitleComponent } from '../../../../app.component';
@Component({ @Component({
selector: 'app-courses', selector: 'app-courses',
templateUrl: './course-list.component.html', templateUrl: './course-list.component.html',
styleUrls: ['./course-list.component.css'] styleUrls: ['./course-list.component.css']
}) })
export class CourseListComponent implements OnInit { export class CourseListComponent implements OnInit, CustomTitleComponent {
subjectId: string; subjectId: string;
itemType = Course; itemType = Course;
@ViewChild('list') list: ListComponent<Course>;
constructor(route: ActivatedRoute) { constructor(route: ActivatedRoute) {
this.subjectId = route.snapshot.params.subjectId; this.subjectId = route.snapshot.params.subjectId;
@ -18,4 +21,7 @@ export class CourseListComponent implements OnInit {
ngOnInit(): void { ngOnInit(): void {
} }
getPageTitle(): string {
return 'Custom title'; //TODO
}
} }

View file

@ -12,7 +12,7 @@ const routes: Routes = [
{path: '', component: SubjectListComponent, data: {title: 'Tárgyak'} as RouteData}, {path: '', component: SubjectListComponent, data: {title: 'Tárgyak'} as RouteData},
{path: ':id', component: SubjectEditComponent, data: {title: 'Szerkesztés'}}, {path: ':id', component: SubjectEditComponent, data: {title: 'Szerkesztés'}},
{ {
path: ':subjectId/courses', children: [ path: ':subjectId/courses', data: {title: 'Kurzusok'}, children: [
{path: ':id', component: CourseEditComponent, data: {title: 'Szerkesztés'} as RouteData}, {path: ':id', component: CourseEditComponent, data: {title: 'Szerkesztés'} as RouteData},
{path: '', component: CourseListComponent, data: {title: 'Kurzusok'}} {path: '', component: CourseListComponent, data: {title: 'Kurzusok'}}
] ]

View file

@ -70,7 +70,8 @@
], ],
"semicolon": { "semicolon": {
"options": [ "options": [
"always" "always",
"ignore-bound-class-methods"
] ]
}, },
"space-before-function-paren": { "space-before-function-paren": {