From 3fe37ac6e0adc7669cf26e968ac3656dce7f5d52 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Sun, 30 Jan 2022 19:40:33 +0100 Subject: [PATCH] Add support for creating items, add boolean support in list Also added subject controller --- backend/src/controllers/index.ts | 1 + backend/src/controllers/subject.controller.ts | 151 ++++++++++++++++++ .../edit/edit.component.html | 2 +- .../shared-components/edit/edit.component.ts | 15 +- .../list/list.component.html | 4 +- .../shared-components/list/list.component.ts | 5 + .../shared-components.module.ts | 28 ++-- .../table/table.component.html | 13 +- .../table/table.component.ts | 6 +- 9 files changed, 203 insertions(+), 22 deletions(-) create mode 100644 backend/src/controllers/subject.controller.ts diff --git a/backend/src/controllers/index.ts b/backend/src/controllers/index.ts index 94dd678..05dbaf4 100644 --- a/backend/src/controllers/index.ts +++ b/backend/src/controllers/index.ts @@ -6,3 +6,4 @@ export * from './course-user.controller'; export * from './user-course.controller'; export * from './course-requirement.controller'; export * from './course-requirement.controller'; +export * from './subject.controller'; diff --git a/backend/src/controllers/subject.controller.ts b/backend/src/controllers/subject.controller.ts new file mode 100644 index 0000000..6004f2f --- /dev/null +++ b/backend/src/controllers/subject.controller.ts @@ -0,0 +1,151 @@ +import { + Count, + CountSchema, + Filter, + FilterExcludingWhere, + repository, + Where, +} from '@loopback/repository'; +import { + post, + param, + get, + getModelSchemaRef, + patch, + put, + del, + requestBody, + response, +} from '@loopback/rest'; +import { Subject } from '../models'; +import { SubjectRepository } from '../repositories'; + +export class SubjectController { + constructor( + @repository(SubjectRepository) + public subjectRepository: SubjectRepository, + ) { + } + + @post('/subjects') + @response(200, { + description: 'Subject model instance', + content: {'application/json': {schema: getModelSchemaRef(Subject)}}, + }) + async create( + @requestBody({ + content: { + 'application/json': { + schema: getModelSchemaRef(Subject, { + title: 'NewSubject', + exclude: ['id'], + }), + }, + }, + }) + subject: Omit, + ): Promise { + return this.subjectRepository.create(subject); + } + + @get('/subjects/count') + @response(200, { + description: 'Subject model count', + content: {'application/json': {schema: CountSchema}}, + }) + async count( + @param.where(Subject) where?: Where, + ): Promise { + return this.subjectRepository.count(where); + } + + @get('/subjects') + @response(200, { + description: 'Array of Subject model instances', + content: { + 'application/json': { + schema: { + type: 'array', + items: getModelSchemaRef(Subject, {includeRelations: true}), + }, + }, + }, + }) + async find( + @param.filter(Subject) filter?: Filter, + ): Promise { + return this.subjectRepository.find(filter); + } + + @patch('/subjects') + @response(200, { + description: 'Subject PATCH success count', + content: {'application/json': {schema: CountSchema}}, + }) + async updateAll( + @requestBody({ + content: { + 'application/json': { + schema: getModelSchemaRef(Subject, {partial: true}), + }, + }, + }) + subject: Subject, + @param.where(Subject) where?: Where, + ): Promise { + return this.subjectRepository.updateAll(subject, where); + } + + @get('/subjects/{id}') + @response(200, { + description: 'Subject model instance', + content: { + 'application/json': { + schema: getModelSchemaRef(Subject, {includeRelations: true}), + }, + }, + }) + async findById( + @param.path.number('id') id: number, + @param.filter(Subject, {exclude: 'where'}) filter?: FilterExcludingWhere + ): Promise { + return this.subjectRepository.findById(id, filter); + } + + @patch('/subjects/{id}') + @response(204, { + description: 'Subject PATCH success', + }) + async updateById( + @param.path.number('id') id: number, + @requestBody({ + content: { + 'application/json': { + schema: getModelSchemaRef(Subject, {partial: true}), + }, + }, + }) + subject: Subject, + ): Promise { + await this.subjectRepository.updateById(id, subject); + } + + @put('/subjects/{id}') + @response(204, { + description: 'Subject PUT success', + }) + async replaceById( + @param.path.number('id') id: number, + @requestBody() subject: Subject, + ): Promise { + await this.subjectRepository.replaceById(id, subject); + } + + @del('/subjects/{id}') + @response(204, { + description: 'Subject DELETE success', + }) + async deleteById(@param.path.number('id') id: number): Promise { + await this.subjectRepository.deleteById(id); + } +} diff --git a/frontend/src/app/shared-components/edit/edit.component.html b/frontend/src/app/shared-components/edit/edit.component.html index fafa8dc..66f53ba 100644 --- a/frontend/src/app/shared-components/edit/edit.component.html +++ b/frontend/src/app/shared-components/edit/edit.component.html @@ -1,4 +1,4 @@ -
+
{{ field.title }} diff --git a/frontend/src/app/shared-components/edit/edit.component.ts b/frontend/src/app/shared-components/edit/edit.component.ts index bffc5ab..2f99dad 100644 --- a/frontend/src/app/shared-components/edit/edit.component.ts +++ b/frontend/src/app/shared-components/edit/edit.component.ts @@ -12,6 +12,7 @@ import { FormBuilder, FormControl, FormGroup } from '@angular/forms'; export class EditComponent implements OnInit { item?: T; + isLoading = true; @Input() apiPath: string; @Input() fields: { title: string, name: string }[]; @@ -23,16 +24,24 @@ export class EditComponent implements OnInit { async ngOnInit(): Promise { this.item = JSON.parse(window.localStorage.getItem(this.router.url)); window.localStorage.removeItem(this.router.url); - if (!this.item) { + const url = this.route.snapshot.url; + if (!this.item && url[url.length - 1].path !== 'new') { this.item = await this.api.request('get', this.apiPath + '/' + this.route.snapshot.url[this.route.snapshot.url.length - 1], {}); } this.formGroup = this.fb.group(this.fields.reduce((pv, cv) => Object.assign(pv, {[cv.name]: new FormControl()}), {})); - this.formGroup.patchValue(this.item); + if (this.item) { + this.formGroup.patchValue(this.item); + } + this.isLoading = false; } async submit(): Promise { try { - await this.api.request('patch', this.apiPath + '/' + this.item.id, this.formGroup.value); + if (this.item) { + await this.api.request('patch', this.apiPath + '/' + this.item.id, this.formGroup.value); + } else { + await this.api.request('post', this.apiPath, this.formGroup.value); + } } catch (e) { alert(e); } diff --git a/frontend/src/app/shared-components/list/list.component.html b/frontend/src/app/shared-components/list/list.component.html index e70c98b..c7b6146 100644 --- a/frontend/src/app/shared-components/list/list.component.html +++ b/frontend/src/app/shared-components/list/list.component.html @@ -1,4 +1,6 @@ +
+ +
- diff --git a/frontend/src/app/shared-components/list/list.component.ts b/frontend/src/app/shared-components/list/list.component.ts index c512af2..5ee2bcf 100644 --- a/frontend/src/app/shared-components/list/list.component.ts +++ b/frontend/src/app/shared-components/list/list.component.ts @@ -15,6 +15,7 @@ export class ListComponent implements OnInit { @Input() apiPath: string; @Input() itemType: Type; @Input() columns: { title: string, prop: keyof T }[]; + @Input() allowNew = false; paginationData: PaginationData = {}; items: T[] = []; @@ -48,4 +49,8 @@ export class ListComponent implements OnInit { window.localStorage.setItem(this.router.url + '/' + item.id, JSON.stringify(item)); await this.router.navigate([this.router.url, item.id]); } + + async newItem(): Promise { + await this.router.navigate([this.router.url, 'new']); + } } diff --git a/frontend/src/app/shared-components/shared-components.module.ts b/frontend/src/app/shared-components/shared-components.module.ts index 707f942..96c78cb 100644 --- a/frontend/src/app/shared-components/shared-components.module.ts +++ b/frontend/src/app/shared-components/shared-components.module.ts @@ -11,7 +11,7 @@ import { EditComponent } from './edit/edit.component'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { ReactiveFormsModule } from '@angular/forms'; import { MatInputModule } from '@angular/material/input'; - +import { MatCheckboxModule } from '@angular/material/checkbox'; @NgModule({ @@ -21,16 +21,18 @@ import { MatInputModule } from '@angular/material/input'; ListComponent, EditComponent ], - imports: [ - CommonModule, - MatProgressBarModule, - MatPaginatorModule, - MatTableModule, - MatButtonModule, - MatIconModule, - MatProgressSpinnerModule, - ReactiveFormsModule, - MatInputModule - ] + imports: [ + CommonModule, + MatProgressBarModule, + MatPaginatorModule, + MatTableModule, + MatButtonModule, + MatIconModule, + MatProgressSpinnerModule, + ReactiveFormsModule, + MatInputModule, + MatCheckboxModule + ] }) -export class SharedComponentsModule { } +export class SharedComponentsModule { +} diff --git a/frontend/src/app/shared-components/table/table.component.html b/frontend/src/app/shared-components/table/table.component.html index fa84a88..6e18b09 100644 --- a/frontend/src/app/shared-components/table/table.component.html +++ b/frontend/src/app/shared-components/table/table.component.html @@ -8,14 +8,21 @@ - - + + diff --git a/frontend/src/app/shared-components/table/table.component.ts b/frontend/src/app/shared-components/table/table.component.ts index eb6b62b..c874e36 100644 --- a/frontend/src/app/shared-components/table/table.component.ts +++ b/frontend/src/app/shared-components/table/table.component.ts @@ -1,4 +1,4 @@ -import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; import { PaginationData } from '../../utility/pagination-data'; import { PageEvent } from '@angular/material/paginator'; @@ -27,6 +27,10 @@ export class TableComponent implements OnInit { getPropNames(): string[] { return this.columns.map(col => col.prop).concat('actions'); } + + getType(itemElement: any): typeof itemElement { + return typeof itemElement; + } }
{{col.title}}{{ item[col.prop]}}{{ col.title }} + + + {{ item[col.prop] }} + + - +