Remove old controllers, add fulfillment mode, fix relations, add missing GraphQL queries and mutations
Added create mutations for the models
This commit is contained in:
parent
d076e0a013
commit
832cf07aa5
45 changed files with 546 additions and 1175 deletions
|
@ -15,6 +15,8 @@ import { UserResolver } from './graphql-resolvers/user.resolver';
|
||||||
import { SzakdolgozatAuthChecker } from './szakdolgozat-auth-checker';
|
import { SzakdolgozatAuthChecker } from './szakdolgozat-auth-checker';
|
||||||
import { CourseResolver } from './graphql-resolvers/course.resolver';
|
import { CourseResolver } from './graphql-resolvers/course.resolver';
|
||||||
import { SubjectResolver } from './graphql-resolvers/subject.resolver';
|
import { SubjectResolver } from './graphql-resolvers/subject.resolver';
|
||||||
|
import { FulfillmentModeResolver } from './graphql-resolvers/fulfillment-mode.resolver';
|
||||||
|
import { RequirementResolver } from './graphql-resolvers/requirement.resolver';
|
||||||
|
|
||||||
export { ApplicationConfig };
|
export { ApplicationConfig };
|
||||||
|
|
||||||
|
@ -36,6 +38,8 @@ export class SzakdolgozatBackendApplication extends BootMixin(
|
||||||
s.resolver(UserResolver);
|
s.resolver(UserResolver);
|
||||||
s.resolver(CourseResolver);
|
s.resolver(CourseResolver);
|
||||||
s.resolver(SubjectResolver);
|
s.resolver(SubjectResolver);
|
||||||
|
s.resolver(FulfillmentModeResolver);
|
||||||
|
s.resolver(RequirementResolver);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Authentication
|
// Authentication
|
||||||
|
|
|
@ -1,111 +0,0 @@
|
||||||
import {
|
|
||||||
Count,
|
|
||||||
CountSchema,
|
|
||||||
Filter,
|
|
||||||
repository,
|
|
||||||
Where,
|
|
||||||
} from '@loopback/repository';
|
|
||||||
import {
|
|
||||||
del,
|
|
||||||
get,
|
|
||||||
getModelSchemaRef,
|
|
||||||
getWhereSchemaFor,
|
|
||||||
param,
|
|
||||||
patch,
|
|
||||||
post,
|
|
||||||
requestBody,
|
|
||||||
} from '@loopback/rest';
|
|
||||||
import {
|
|
||||||
Course,
|
|
||||||
Requirement,
|
|
||||||
} from '../models';
|
|
||||||
import { CourseRepository } from '../repositories';
|
|
||||||
|
|
||||||
export class CourseRequirementController {
|
|
||||||
constructor(
|
|
||||||
@repository(CourseRepository) protected courseRepository: CourseRepository,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@get('/courses/{id}/requirements', {
|
|
||||||
responses: {
|
|
||||||
'200': {
|
|
||||||
description: 'Array of Course has many Requirement',
|
|
||||||
content: {
|
|
||||||
'application/json': {
|
|
||||||
schema: {type: 'array', items: getModelSchemaRef(Requirement)},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
async find(
|
|
||||||
@param.path.number('id') id: number,
|
|
||||||
@param.query.object('filter') filter?: Filter<Requirement>,
|
|
||||||
): Promise<Requirement[]> {
|
|
||||||
return this.courseRepository.requirements(id).find(filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
@post('/courses/{id}/requirements', {
|
|
||||||
responses: {
|
|
||||||
'200': {
|
|
||||||
description: 'Course model instance',
|
|
||||||
content: {'application/json': {schema: getModelSchemaRef(Requirement)}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
async create(
|
|
||||||
@param.path.number('id') id: typeof Course.prototype.id,
|
|
||||||
@requestBody({
|
|
||||||
content: {
|
|
||||||
'application/json': {
|
|
||||||
schema: getModelSchemaRef(Requirement, {
|
|
||||||
title: 'NewRequirementInCourse',
|
|
||||||
exclude: ['id'],
|
|
||||||
optional: ['courseId']
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}) requirement: Omit<Requirement, 'id'>,
|
|
||||||
): Promise<Requirement> {
|
|
||||||
return this.courseRepository.requirements(id).create(requirement);
|
|
||||||
}
|
|
||||||
|
|
||||||
@patch('/courses/{id}/requirements', {
|
|
||||||
responses: {
|
|
||||||
'200': {
|
|
||||||
description: 'Course.Requirement PATCH success count',
|
|
||||||
content: {'application/json': {schema: CountSchema}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
async patch(
|
|
||||||
@param.path.number('id') id: number,
|
|
||||||
@requestBody({
|
|
||||||
content: {
|
|
||||||
'application/json': {
|
|
||||||
schema: getModelSchemaRef(Requirement, {partial: true}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
requirement: Partial<Requirement>,
|
|
||||||
@param.query.object('where', getWhereSchemaFor(Requirement)) where?: Where<Requirement>,
|
|
||||||
): Promise<Count> {
|
|
||||||
return this.courseRepository.requirements(id).patch(requirement, where);
|
|
||||||
}
|
|
||||||
|
|
||||||
@del('/courses/{id}/requirements', {
|
|
||||||
responses: {
|
|
||||||
'200': {
|
|
||||||
description: 'Course.Requirement DELETE success count',
|
|
||||||
content: {'application/json': {schema: CountSchema}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
async delete(
|
|
||||||
@param.path.number('id') id: number,
|
|
||||||
@param.query.object('where', getWhereSchemaFor(Requirement)) where?: Where<Requirement>,
|
|
||||||
): Promise<Count> {
|
|
||||||
return this.courseRepository.requirements(id).delete(where);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
import {
|
|
||||||
repository,
|
|
||||||
} from '@loopback/repository';
|
|
||||||
import {
|
|
||||||
param,
|
|
||||||
get,
|
|
||||||
getModelSchemaRef,
|
|
||||||
} from '@loopback/rest';
|
|
||||||
import {
|
|
||||||
Course,
|
|
||||||
Subject,
|
|
||||||
} from '../models';
|
|
||||||
import { CourseRepository } from '../repositories';
|
|
||||||
|
|
||||||
export class CourseSubjectController {
|
|
||||||
constructor(
|
|
||||||
@repository(CourseRepository)
|
|
||||||
public courseRepository: CourseRepository,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@get('/courses/{id}/subject', {
|
|
||||||
responses: {
|
|
||||||
'200': {
|
|
||||||
description: 'Subject belonging to Course',
|
|
||||||
content: {
|
|
||||||
'application/json': {
|
|
||||||
schema: {type: 'array', items: getModelSchemaRef(Subject)},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
async getSubject(
|
|
||||||
@param.path.number('id') id: typeof Course.prototype.id,
|
|
||||||
): Promise<Subject> {
|
|
||||||
return this.courseRepository.subject(id);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,110 +0,0 @@
|
||||||
import {
|
|
||||||
Count,
|
|
||||||
CountSchema,
|
|
||||||
Filter,
|
|
||||||
repository,
|
|
||||||
Where,
|
|
||||||
} from '@loopback/repository';
|
|
||||||
import {
|
|
||||||
del,
|
|
||||||
get,
|
|
||||||
getModelSchemaRef,
|
|
||||||
getWhereSchemaFor,
|
|
||||||
param,
|
|
||||||
patch,
|
|
||||||
post,
|
|
||||||
requestBody,
|
|
||||||
} from '@loopback/rest';
|
|
||||||
import {
|
|
||||||
Course,
|
|
||||||
User,
|
|
||||||
} from '../models';
|
|
||||||
import { CourseRepository } from '../repositories';
|
|
||||||
|
|
||||||
export class CourseUserController {
|
|
||||||
constructor(
|
|
||||||
@repository(CourseRepository) protected courseRepository: CourseRepository,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@get('/courses/{id}/users', {
|
|
||||||
responses: {
|
|
||||||
'200': {
|
|
||||||
description: 'Array of Course has many User through CourseUser',
|
|
||||||
content: {
|
|
||||||
'application/json': {
|
|
||||||
schema: {type: 'array', items: getModelSchemaRef(User)},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
async find(
|
|
||||||
@param.path.number('id') id: number,
|
|
||||||
@param.query.object('filter') filter?: Filter<User>,
|
|
||||||
): Promise<User[]> {
|
|
||||||
return this.courseRepository.users(id).find(filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
@post('/courses/{id}/users', {
|
|
||||||
responses: {
|
|
||||||
'200': {
|
|
||||||
description: 'create a User model instance',
|
|
||||||
content: {'application/json': {schema: getModelSchemaRef(User)}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
async create(
|
|
||||||
@param.path.number('id') id: typeof Course.prototype.id,
|
|
||||||
@requestBody({
|
|
||||||
content: {
|
|
||||||
'application/json': {
|
|
||||||
schema: getModelSchemaRef(User, {
|
|
||||||
title: 'NewUserInCourse',
|
|
||||||
exclude: ['id'],
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}) user: Omit<User, 'id'>,
|
|
||||||
): Promise<User> {
|
|
||||||
return this.courseRepository.users(id).create(user);
|
|
||||||
}
|
|
||||||
|
|
||||||
@patch('/courses/{id}/users', {
|
|
||||||
responses: {
|
|
||||||
'200': {
|
|
||||||
description: 'Course.User PATCH success count',
|
|
||||||
content: {'application/json': {schema: CountSchema}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
async patch(
|
|
||||||
@param.path.number('id') id: number,
|
|
||||||
@requestBody({
|
|
||||||
content: {
|
|
||||||
'application/json': {
|
|
||||||
schema: getModelSchemaRef(User, {partial: true}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
user: Partial<User>,
|
|
||||||
@param.query.object('where', getWhereSchemaFor(User)) where?: Where<User>,
|
|
||||||
): Promise<Count> {
|
|
||||||
return this.courseRepository.users(id).patch(user, where);
|
|
||||||
}
|
|
||||||
|
|
||||||
@del('/courses/{id}/users', {
|
|
||||||
responses: {
|
|
||||||
'200': {
|
|
||||||
description: 'Course.User DELETE success count',
|
|
||||||
content: {'application/json': {schema: CountSchema}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
async delete(
|
|
||||||
@param.path.number('id') id: number,
|
|
||||||
@param.query.object('where', getWhereSchemaFor(User)) where?: Where<User>,
|
|
||||||
): Promise<Count> {
|
|
||||||
return this.courseRepository.users(id).delete(where);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,134 +0,0 @@
|
||||||
import { Count, CountSchema, Filter, FilterExcludingWhere, repository, Where, } from '@loopback/repository';
|
|
||||||
import { del, get, getModelSchemaRef, param, patch, post, put, requestBody, response, } from '@loopback/rest';
|
|
||||||
import { Course } from '../models';
|
|
||||||
import { CourseRepository } from '../repositories';
|
|
||||||
|
|
||||||
export class CourseController {
|
|
||||||
constructor(
|
|
||||||
@repository(CourseRepository)
|
|
||||||
public courseRepository: CourseRepository,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@post('/courses')
|
|
||||||
@response(200, {
|
|
||||||
description: 'Course model instance',
|
|
||||||
content: {'application/json': {schema: getModelSchemaRef(Course)}},
|
|
||||||
})
|
|
||||||
async create(
|
|
||||||
@requestBody({
|
|
||||||
content: {
|
|
||||||
'application/json': {
|
|
||||||
schema: getModelSchemaRef(Course, {
|
|
||||||
title: 'NewCourse',
|
|
||||||
exclude: ['id'],
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
course: Omit<Course, 'id'>,
|
|
||||||
): Promise<Course> {
|
|
||||||
return this.courseRepository.create(course);
|
|
||||||
}
|
|
||||||
|
|
||||||
@get('/courses/count')
|
|
||||||
@response(200, {
|
|
||||||
description: 'Course model count',
|
|
||||||
content: {'application/json': {schema: CountSchema}},
|
|
||||||
})
|
|
||||||
async count(
|
|
||||||
@param.where(Course) where?: Where<Course>,
|
|
||||||
): Promise<Count> {
|
|
||||||
return this.courseRepository.count(where);
|
|
||||||
}
|
|
||||||
|
|
||||||
@get('/courses')
|
|
||||||
@response(200, {
|
|
||||||
description: 'Array of Course model instances',
|
|
||||||
content: {
|
|
||||||
'application/json': {
|
|
||||||
schema: {
|
|
||||||
type: 'array',
|
|
||||||
items: getModelSchemaRef(Course, {includeRelations: true}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
async find(
|
|
||||||
@param.filter(Course) filter?: Filter<Course>,
|
|
||||||
): Promise<Course[]> {
|
|
||||||
return this.courseRepository.find(filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
@patch('/courses')
|
|
||||||
@response(200, {
|
|
||||||
description: 'Course PATCH success count',
|
|
||||||
content: {'application/json': {schema: CountSchema}},
|
|
||||||
})
|
|
||||||
async updateAll(
|
|
||||||
@requestBody({
|
|
||||||
content: {
|
|
||||||
'application/json': {
|
|
||||||
schema: getModelSchemaRef(Course, {partial: true}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
course: Course,
|
|
||||||
@param.where(Course) where?: Where<Course>,
|
|
||||||
): Promise<Count> {
|
|
||||||
return this.courseRepository.updateAll(course, where);
|
|
||||||
}
|
|
||||||
|
|
||||||
@get('/courses/{id}')
|
|
||||||
@response(200, {
|
|
||||||
description: 'Course model instance',
|
|
||||||
content: {
|
|
||||||
'application/json': {
|
|
||||||
schema: getModelSchemaRef(Course, {includeRelations: true}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
async findById(
|
|
||||||
@param.path.number('id') id: number,
|
|
||||||
@param.filter(Course, {exclude: 'where'}) filter?: FilterExcludingWhere<Course>
|
|
||||||
): Promise<Course> {
|
|
||||||
return this.courseRepository.findById(id, filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
@patch('/courses/{id}')
|
|
||||||
@response(204, {
|
|
||||||
description: 'Course PATCH success',
|
|
||||||
})
|
|
||||||
async updateById(
|
|
||||||
@param.path.number('id') id: number,
|
|
||||||
@requestBody({
|
|
||||||
content: {
|
|
||||||
'application/json': {
|
|
||||||
schema: getModelSchemaRef(Course, {partial: true}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
course: Course,
|
|
||||||
): Promise<void> {
|
|
||||||
await this.courseRepository.updateById(id, course);
|
|
||||||
}
|
|
||||||
|
|
||||||
@put('/courses/{id}')
|
|
||||||
@response(204, {
|
|
||||||
description: 'Course PUT success',
|
|
||||||
})
|
|
||||||
async replaceById(
|
|
||||||
@param.path.number('id') id: number,
|
|
||||||
@requestBody() course: Course,
|
|
||||||
): Promise<void> {
|
|
||||||
await this.courseRepository.replaceById(id, course);
|
|
||||||
}
|
|
||||||
|
|
||||||
@del('/courses/{id}')
|
|
||||||
@response(204, {
|
|
||||||
description: 'Course DELETE success',
|
|
||||||
})
|
|
||||||
async deleteById(@param.path.number('id') id: number): Promise<void> {
|
|
||||||
await this.courseRepository.deleteById(id);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
export * from './ping.controller';
|
|
||||||
export * from './user.controller';
|
|
||||||
export * from './subject-course.controller';
|
|
||||||
export * from './course-subject.controller';
|
|
||||||
export * from './course-user.controller';
|
|
||||||
export * from './user-course.controller';
|
|
||||||
export * from './course-requirement.controller';
|
|
||||||
export * from './course-requirement.controller';
|
|
||||||
export * from './subject.controller';
|
|
||||||
export * from './course.controller';
|
|
|
@ -1,55 +0,0 @@
|
||||||
import {inject} from '@loopback/core';
|
|
||||||
import {
|
|
||||||
Request,
|
|
||||||
RestBindings,
|
|
||||||
get,
|
|
||||||
response,
|
|
||||||
ResponseObject,
|
|
||||||
} from '@loopback/rest';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* OpenAPI response for ping()
|
|
||||||
*/
|
|
||||||
const PING_RESPONSE: ResponseObject = {
|
|
||||||
description: 'Ping Response',
|
|
||||||
content: {
|
|
||||||
'application/json': {
|
|
||||||
schema: {
|
|
||||||
type: 'object',
|
|
||||||
title: 'PingResponse',
|
|
||||||
properties: {
|
|
||||||
greeting: {type: 'string'},
|
|
||||||
date: {type: 'string'},
|
|
||||||
url: {type: 'string'},
|
|
||||||
headers: {
|
|
||||||
type: 'object',
|
|
||||||
properties: {
|
|
||||||
'Content-Type': {type: 'string'},
|
|
||||||
},
|
|
||||||
additionalProperties: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A simple controller to bounce back http requests
|
|
||||||
*/
|
|
||||||
export class PingController {
|
|
||||||
constructor(@inject(RestBindings.Http.REQUEST) private req: Request) {}
|
|
||||||
|
|
||||||
// Map to `GET /ping`
|
|
||||||
@get('/ping')
|
|
||||||
@response(200, PING_RESPONSE)
|
|
||||||
ping(): object {
|
|
||||||
// Reply with a greeting, the current time, the url, and request headers
|
|
||||||
return {
|
|
||||||
greeting: 'Hello from LoopBack',
|
|
||||||
date: new Date(),
|
|
||||||
url: this.req.url,
|
|
||||||
headers: Object.assign({}, this.req.headers),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,105 +0,0 @@
|
||||||
import { Count, CountSchema, Filter, repository, Where, } from '@loopback/repository';
|
|
||||||
import { del, get, getModelSchemaRef, getWhereSchemaFor, param, patch, post, requestBody, response, } from '@loopback/rest';
|
|
||||||
import { Course, Subject, } from '../models';
|
|
||||||
import { SubjectRepository } from '../repositories';
|
|
||||||
|
|
||||||
export class SubjectCourseController {
|
|
||||||
constructor(
|
|
||||||
@repository(SubjectRepository) protected subjectRepository: SubjectRepository,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@get('/subjects/{id}/courses', {
|
|
||||||
responses: {
|
|
||||||
'200': {
|
|
||||||
description: 'Array of Subject has many Course',
|
|
||||||
content: {
|
|
||||||
'application/json': {
|
|
||||||
schema: {type: 'array', items: getModelSchemaRef(Course)},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
async find(
|
|
||||||
@param.path.number('id') id: number,
|
|
||||||
@param.query.object('filter') filter?: Filter<Course>,
|
|
||||||
): Promise<Course[]> {
|
|
||||||
return this.subjectRepository.courses(id).find(filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
@get('/subjects/{id}/courses/count')
|
|
||||||
@response(200, {
|
|
||||||
description: 'Course model count',
|
|
||||||
content: {'application/json': {schema: CountSchema}},
|
|
||||||
})
|
|
||||||
async count(
|
|
||||||
@param.path.number('id') id: number,
|
|
||||||
@param.where(Course) where?: Where<Course>,
|
|
||||||
): Promise<Count> {
|
|
||||||
return this.subjectRepository.courses(id).count(where);
|
|
||||||
}
|
|
||||||
|
|
||||||
@post('/subjects/{id}/courses', {
|
|
||||||
responses: {
|
|
||||||
'200': {
|
|
||||||
description: 'Subject model instance',
|
|
||||||
content: {'application/json': {schema: getModelSchemaRef(Course)}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
async create(
|
|
||||||
@param.path.number('id') id: typeof Subject.prototype.id,
|
|
||||||
@requestBody({
|
|
||||||
content: {
|
|
||||||
'application/json': {
|
|
||||||
schema: getModelSchemaRef(Course, {
|
|
||||||
title: 'NewCourseInSubject',
|
|
||||||
exclude: ['id'],
|
|
||||||
optional: ['subjectId']
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}) course: Omit<Course, 'id'>,
|
|
||||||
): Promise<Course> {
|
|
||||||
return this.subjectRepository.courses(id).create(course);
|
|
||||||
}
|
|
||||||
|
|
||||||
@patch('/subjects/{id}/courses', {
|
|
||||||
responses: {
|
|
||||||
'200': {
|
|
||||||
description: 'Subject.Course PATCH success count',
|
|
||||||
content: {'application/json': {schema: CountSchema}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
async patch(
|
|
||||||
@param.path.number('id') id: number,
|
|
||||||
@requestBody({
|
|
||||||
content: {
|
|
||||||
'application/json': {
|
|
||||||
schema: getModelSchemaRef(Course, {partial: true}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
course: Partial<Course>,
|
|
||||||
@param.query.object('where', getWhereSchemaFor(Course)) where?: Where<Course>,
|
|
||||||
): Promise<Count> {
|
|
||||||
return this.subjectRepository.courses(id).patch(course, where);
|
|
||||||
}
|
|
||||||
|
|
||||||
@del('/subjects/{id}/courses', {
|
|
||||||
responses: {
|
|
||||||
'200': {
|
|
||||||
description: 'Subject.Course DELETE success count',
|
|
||||||
content: {'application/json': {schema: CountSchema}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
async delete(
|
|
||||||
@param.path.number('id') id: number,
|
|
||||||
@param.query.object('where', getWhereSchemaFor(Course)) where?: Where<Course>,
|
|
||||||
): Promise<Count> {
|
|
||||||
return this.subjectRepository.courses(id).delete(where);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,151 +0,0 @@
|
||||||
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<Subject, 'id'>,
|
|
||||||
): Promise<Subject> {
|
|
||||||
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<Subject>,
|
|
||||||
): Promise<Count> {
|
|
||||||
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<Subject>,
|
|
||||||
): Promise<Subject[]> {
|
|
||||||
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<Subject>,
|
|
||||||
): Promise<Count> {
|
|
||||||
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<Subject>
|
|
||||||
): Promise<Subject> {
|
|
||||||
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<void> {
|
|
||||||
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<void> {
|
|
||||||
await this.subjectRepository.replaceById(id, subject);
|
|
||||||
}
|
|
||||||
|
|
||||||
@del('/subjects/{id}')
|
|
||||||
@response(204, {
|
|
||||||
description: 'Subject DELETE success',
|
|
||||||
})
|
|
||||||
async deleteById(@param.path.number('id') id: number): Promise<void> {
|
|
||||||
await this.subjectRepository.deleteById(id);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,110 +0,0 @@
|
||||||
import {
|
|
||||||
Count,
|
|
||||||
CountSchema,
|
|
||||||
Filter,
|
|
||||||
repository,
|
|
||||||
Where,
|
|
||||||
} from '@loopback/repository';
|
|
||||||
import {
|
|
||||||
del,
|
|
||||||
get,
|
|
||||||
getModelSchemaRef,
|
|
||||||
getWhereSchemaFor,
|
|
||||||
param,
|
|
||||||
patch,
|
|
||||||
post,
|
|
||||||
requestBody,
|
|
||||||
} from '@loopback/rest';
|
|
||||||
import {
|
|
||||||
User,
|
|
||||||
Course,
|
|
||||||
} from '../models';
|
|
||||||
import { UserRepository } from '../repositories';
|
|
||||||
|
|
||||||
export class UserCourseController {
|
|
||||||
constructor(
|
|
||||||
@repository(UserRepository) protected userRepository: UserRepository,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@get('/users/{id}/courses', {
|
|
||||||
responses: {
|
|
||||||
'200': {
|
|
||||||
description: 'Array of User has many Course through CourseUser',
|
|
||||||
content: {
|
|
||||||
'application/json': {
|
|
||||||
schema: {type: 'array', items: getModelSchemaRef(Course)},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
async find(
|
|
||||||
@param.path.number('id') id: number,
|
|
||||||
@param.query.object('filter') filter?: Filter<Course>,
|
|
||||||
): Promise<Course[]> {
|
|
||||||
return this.userRepository.courses(id).find(filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
@post('/users/{id}/courses', {
|
|
||||||
responses: {
|
|
||||||
'200': {
|
|
||||||
description: 'create a Course model instance',
|
|
||||||
content: {'application/json': {schema: getModelSchemaRef(Course)}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
async create(
|
|
||||||
@param.path.number('id') id: typeof User.prototype.id,
|
|
||||||
@requestBody({
|
|
||||||
content: {
|
|
||||||
'application/json': {
|
|
||||||
schema: getModelSchemaRef(Course, {
|
|
||||||
title: 'NewCourseInUser',
|
|
||||||
exclude: ['id'],
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}) course: Omit<Course, 'id'>,
|
|
||||||
): Promise<Course> {
|
|
||||||
return this.userRepository.courses(id).create(course);
|
|
||||||
}
|
|
||||||
|
|
||||||
@patch('/users/{id}/courses', {
|
|
||||||
responses: {
|
|
||||||
'200': {
|
|
||||||
description: 'User.Course PATCH success count',
|
|
||||||
content: {'application/json': {schema: CountSchema}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
async patch(
|
|
||||||
@param.path.number('id') id: number,
|
|
||||||
@requestBody({
|
|
||||||
content: {
|
|
||||||
'application/json': {
|
|
||||||
schema: getModelSchemaRef(Course, {partial: true}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
course: Partial<Course>,
|
|
||||||
@param.query.object('where', getWhereSchemaFor(Course)) where?: Where<Course>,
|
|
||||||
): Promise<Count> {
|
|
||||||
return this.userRepository.courses(id).patch(course, where);
|
|
||||||
}
|
|
||||||
|
|
||||||
@del('/users/{id}/courses', {
|
|
||||||
responses: {
|
|
||||||
'200': {
|
|
||||||
description: 'User.Course DELETE success count',
|
|
||||||
content: {'application/json': {schema: CountSchema}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
async delete(
|
|
||||||
@param.path.number('id') id: number,
|
|
||||||
@param.query.object('where', getWhereSchemaFor(Course)) where?: Where<Course>,
|
|
||||||
): Promise<Count> {
|
|
||||||
return this.userRepository.courses(id).delete(where);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,217 +0,0 @@
|
||||||
import { Count, CountSchema, Filter, FilterExcludingWhere, repository, Where, } from '@loopback/repository';
|
|
||||||
import { del, get, getModelSchemaRef, HttpErrors, param, patch, post, Request, requestBody, response, RestBindings, } from '@loopback/rest';
|
|
||||||
import { User } from '../models';
|
|
||||||
import { UserRepository } from '../repositories';
|
|
||||||
import {
|
|
||||||
TokenServiceBindings,
|
|
||||||
UserServiceBindings
|
|
||||||
} from '@loopback/authentication-jwt';
|
|
||||||
import { inject } from '@loopback/core';
|
|
||||||
import { authenticate, TokenService } from '@loopback/authentication';
|
|
||||||
import { SecurityBindings, UserProfile } from '@loopback/security';
|
|
||||||
import { genSalt, hash } from 'bcryptjs';
|
|
||||||
import { SzakdolgozatUserService } from '../services';
|
|
||||||
|
|
||||||
export class UserController {
|
|
||||||
constructor(
|
|
||||||
@inject(TokenServiceBindings.TOKEN_SERVICE)
|
|
||||||
public jwtService: TokenService,
|
|
||||||
@inject(UserServiceBindings.USER_SERVICE)
|
|
||||||
public userService: SzakdolgozatUserService,
|
|
||||||
@inject(SecurityBindings.USER, {optional: true})
|
|
||||||
public user: UserProfile,
|
|
||||||
@repository(UserRepository)
|
|
||||||
public userRepository: UserRepository,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@post('/users')
|
|
||||||
@response(200, {
|
|
||||||
description: 'User model instance',
|
|
||||||
content: {'application/json': {schema: getModelSchemaRef(User, {exclude: ['password']})}},
|
|
||||||
})
|
|
||||||
async register(
|
|
||||||
@requestBody({
|
|
||||||
content: {
|
|
||||||
'application/json': {
|
|
||||||
schema: getModelSchemaRef(User, {
|
|
||||||
title: 'Registration request',
|
|
||||||
exclude: ['id', 'isAdmin']
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
request: Pick<User, 'email' | 'name' | 'password'>,
|
|
||||||
): Promise<User> {
|
|
||||||
const password = await hash(request.password, await genSalt());
|
|
||||||
const user = {
|
|
||||||
email: request.email,
|
|
||||||
name: request.name,
|
|
||||||
password: password,
|
|
||||||
isAdmin: false
|
|
||||||
} as User;
|
|
||||||
return this.userRepository.create(user);
|
|
||||||
}
|
|
||||||
|
|
||||||
@post('/users/login', {
|
|
||||||
responses: {
|
|
||||||
'200': {
|
|
||||||
description: 'Token',
|
|
||||||
content: {
|
|
||||||
'application/json': {
|
|
||||||
schema: {
|
|
||||||
type: 'object',
|
|
||||||
properties: {
|
|
||||||
token: {
|
|
||||||
type: 'string',
|
|
||||||
},
|
|
||||||
user: getModelSchemaRef(User, {exclude: ['id', 'password']})
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
async login(
|
|
||||||
@requestBody({
|
|
||||||
description: 'The input of login function',
|
|
||||||
required: true,
|
|
||||||
content: {
|
|
||||||
'application/json': {
|
|
||||||
schema: getModelSchemaRef(User, {exclude: ['id', 'isAdmin', 'name']})
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}) credentials: Pick<User, 'email' | 'password'>,
|
|
||||||
): Promise<{ token: string, user: Omit<User, 'id' | 'password'> }> {
|
|
||||||
// ensure the user exists, and the password is correct
|
|
||||||
const user = await this.userService.verifyCredentials(credentials);
|
|
||||||
// convert a User object into a UserProfile object (reduced set of properties)
|
|
||||||
const userProfile = this.userService.convertToUserProfile(user);
|
|
||||||
|
|
||||||
// create a JSON Web Token based on the user profile
|
|
||||||
const token = await this.jwtService.generateToken(userProfile);
|
|
||||||
return {token, user};
|
|
||||||
}
|
|
||||||
|
|
||||||
@post('/users/logout', {
|
|
||||||
responses: {
|
|
||||||
'204': {
|
|
||||||
description: 'Logged out',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
@authenticate('jwt')
|
|
||||||
async logout(@inject(RestBindings.Http.REQUEST) request: Request): Promise<void> {
|
|
||||||
const split = request.headers.authorization?.split(' ');
|
|
||||||
if (split && split.length > 1) {
|
|
||||||
if (this.jwtService.revokeToken) {
|
|
||||||
await this.jwtService.revokeToken(split[1]);
|
|
||||||
} else {
|
|
||||||
console.error('Cannot revoke token');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@get('/users/count')
|
|
||||||
@response(200, {
|
|
||||||
description: 'User model count',
|
|
||||||
content: {'application/json': {schema: CountSchema}},
|
|
||||||
})
|
|
||||||
@authenticate('jwt')
|
|
||||||
async count(
|
|
||||||
@param.where(User) where?: Where<User>,
|
|
||||||
): Promise<Count> {
|
|
||||||
return this.userRepository.count(where);
|
|
||||||
}
|
|
||||||
|
|
||||||
@get('/users')
|
|
||||||
@response(200, {
|
|
||||||
description: 'Array of User model instances',
|
|
||||||
content: {
|
|
||||||
'application/json': {
|
|
||||||
schema: {
|
|
||||||
type: 'array',
|
|
||||||
items: getModelSchemaRef(User, {includeRelations: true}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
@authenticate('jwt')
|
|
||||||
async find(
|
|
||||||
@param.filter(User) filter?: Filter<User>,
|
|
||||||
): Promise<User[]> {
|
|
||||||
return this.userRepository.find(filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
@patch('/users')
|
|
||||||
@response(200, {
|
|
||||||
description: 'User PATCH success count',
|
|
||||||
content: {'application/json': {schema: CountSchema}},
|
|
||||||
})
|
|
||||||
@authenticate('jwt')
|
|
||||||
async updateAll(
|
|
||||||
@requestBody({
|
|
||||||
content: {
|
|
||||||
'application/json': {
|
|
||||||
schema: getModelSchemaRef(User, {partial: true}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
user: User,
|
|
||||||
@param.where(User) where?: Where<User>,
|
|
||||||
): Promise<Count> {
|
|
||||||
return this.userRepository.updateAll(user, where);
|
|
||||||
}
|
|
||||||
|
|
||||||
@get('/users/{id}')
|
|
||||||
@response(200, {
|
|
||||||
description: 'User model instance',
|
|
||||||
content: {
|
|
||||||
'application/json': {
|
|
||||||
schema: getModelSchemaRef(User, {includeRelations: true}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
@authenticate('jwt')
|
|
||||||
async findById(
|
|
||||||
@param.path.number('id') id: number,
|
|
||||||
@param.filter(User, {exclude: 'where'}) filter?: FilterExcludingWhere<User>
|
|
||||||
): Promise<User> {
|
|
||||||
return this.userRepository.findById(id, filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
@patch('/users/{id}')
|
|
||||||
@response(204, {
|
|
||||||
description: 'User PATCH success',
|
|
||||||
})
|
|
||||||
@authenticate('jwt')
|
|
||||||
async updateById(
|
|
||||||
@param.path.number('id') id: number,
|
|
||||||
@requestBody({
|
|
||||||
content: {
|
|
||||||
'application/json': {
|
|
||||||
schema: getModelSchemaRef(User, {partial: true}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
user: User,
|
|
||||||
): Promise<void> {
|
|
||||||
if (id === +this.user.id) {
|
|
||||||
const loggedInUser = await this.userService.findUserById(this.user.id);
|
|
||||||
if (user.isAdmin !== undefined && loggedInUser.isAdmin !== user.isAdmin) {
|
|
||||||
throw new HttpErrors.BadRequest('Cannot change admin status of self');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
await this.userRepository.updateById(id, user);
|
|
||||||
}
|
|
||||||
|
|
||||||
@del('/users/{id}')
|
|
||||||
@response(204, {
|
|
||||||
description: 'User DELETE success',
|
|
||||||
})
|
|
||||||
@authenticate('jwt')
|
|
||||||
async deleteById(@param.path.number('id') id: number): Promise<void> {
|
|
||||||
await this.userRepository.deleteById(id);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,9 +2,8 @@ import { repository } from '@loopback/repository';
|
||||||
import { CourseRepository, SubjectRepository, UserRepository } from '../repositories';
|
import { CourseRepository, SubjectRepository, UserRepository } from '../repositories';
|
||||||
import { arg, ID, Int, mutation, query, resolver } from '@loopback/graphql';
|
import { arg, ID, Int, mutation, query, resolver } from '@loopback/graphql';
|
||||||
import { Course } from '../models';
|
import { Course } from '../models';
|
||||||
import { CourseUpdateInput } from '../graphql-types/input/course-update.input';
|
|
||||||
import { listResponse, ListResponse } from '../graphql-types/list';
|
import { listResponse, ListResponse } from '../graphql-types/list';
|
||||||
import { CourseList } from '../graphql-types/course';
|
import { CourseList, CourseUpdateInput } from '../graphql-types/course';
|
||||||
|
|
||||||
@resolver(of => Course)
|
@resolver(of => Course)
|
||||||
export class CourseResolver {
|
export class CourseResolver {
|
||||||
|
@ -35,4 +34,10 @@ export class CourseResolver {
|
||||||
await this.courseRepo.updateById(input.id, input);
|
await this.courseRepo.updateById(input.id, input);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@mutation(returns => Boolean)
|
||||||
|
async courseCreate(@arg('course') input: CourseUpdateInput): Promise<boolean> {
|
||||||
|
await this.courseRepo.create(input);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
38
backend/src/graphql-resolvers/fulfillment-mode.resolver.ts
Normal file
38
backend/src/graphql-resolvers/fulfillment-mode.resolver.ts
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
import { repository } from '@loopback/repository';
|
||||||
|
import { CourseRepository, FulfillmentModeRepository, UserRepository } from '../repositories';
|
||||||
|
import { arg, ID, Int, mutation, query, resolver } from '@loopback/graphql';
|
||||||
|
import { FulfillmentMode } from '../models';
|
||||||
|
import { listResponse, ListResponse } from '../graphql-types/list';
|
||||||
|
import { FulfillmentModeList, FulfillmentModeUpdateInput } from '../graphql-types/fulfillment-mode';
|
||||||
|
|
||||||
|
@resolver(of => FulfillmentMode)
|
||||||
|
export class FulfillmentModeResolver {
|
||||||
|
constructor(
|
||||||
|
@repository('CourseRepository') private courseRepo: CourseRepository,
|
||||||
|
@repository('FulfillmentModeRepository') private fulfillmentModeRepo: FulfillmentModeRepository,
|
||||||
|
@repository('UserRepository') private userRepo: UserRepository
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@query(returns => FulfillmentModeList)
|
||||||
|
async fulfillmentModes(@arg('course', returns => ID) course: number, @arg('offset', returns => Int) offset: number, @arg('limit', returns => Int) limit: number): Promise<ListResponse<FulfillmentMode>> {
|
||||||
|
return listResponse(this.courseRepo.fulfillmentModes(course), offset, limit, FulfillmentModeList);
|
||||||
|
}
|
||||||
|
|
||||||
|
@query(returns => FulfillmentMode)
|
||||||
|
async fulfillmentMode(@arg('id', returns => ID) id: number): Promise<FulfillmentMode> {
|
||||||
|
return await this.fulfillmentModeRepo.findById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@mutation(returns => Boolean)
|
||||||
|
async fulfillmentModeUpdate(@arg('input') input: FulfillmentModeUpdateInput): Promise<boolean> {
|
||||||
|
await this.fulfillmentModeRepo.updateById(input.id, input);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@mutation(returns => Boolean)
|
||||||
|
async fulfillmentModeCreate(@arg('input') input: FulfillmentModeUpdateInput): Promise<boolean> {
|
||||||
|
await this.fulfillmentModeRepo.create(input);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
38
backend/src/graphql-resolvers/requirement.resolver.ts
Normal file
38
backend/src/graphql-resolvers/requirement.resolver.ts
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
import { repository } from '@loopback/repository';
|
||||||
|
import { FulfillmentModeRepository, RequirementRepository, UserRepository } from '../repositories';
|
||||||
|
import { arg, ID, Int, mutation, query, resolver } from '@loopback/graphql';
|
||||||
|
import { Requirement } from '../models';
|
||||||
|
import { listResponse, ListResponse } from '../graphql-types/list';
|
||||||
|
import { RequirementList, RequirementUpdateInput } from '../graphql-types/requirement';
|
||||||
|
|
||||||
|
@resolver(of => Requirement)
|
||||||
|
export class RequirementResolver {
|
||||||
|
constructor(
|
||||||
|
@repository('FulfillmentModeRepository') private modeRepo: FulfillmentModeRepository,
|
||||||
|
@repository('RequirementRepository') private requirementRepo: RequirementRepository,
|
||||||
|
@repository('UserRepository') private userRepo: UserRepository
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@query(returns => RequirementList)
|
||||||
|
async requirements(@arg('mode', returns => ID) mode: number, @arg('offset', returns => Int) offset: number, @arg('limit', returns => Int) limit: number): Promise<ListResponse<Requirement>> {
|
||||||
|
return listResponse(this.modeRepo.requirements(mode), offset, limit, RequirementList);
|
||||||
|
}
|
||||||
|
|
||||||
|
@query(returns => Requirement)
|
||||||
|
async requirement(@arg('id', returns => ID) id: number): Promise<Requirement> {
|
||||||
|
return await this.requirementRepo.findById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@mutation(returns => Boolean)
|
||||||
|
async requirementUpdate(@arg('requirement') input: RequirementUpdateInput): Promise<boolean> {
|
||||||
|
await this.requirementRepo.updateById(input.id, input);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@mutation(returns => Boolean)
|
||||||
|
async requirementCreate(@arg('requirement') input: RequirementUpdateInput): Promise<boolean> {
|
||||||
|
await this.requirementRepo.create(input);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,8 +3,7 @@ import { Subject } from '../models';
|
||||||
import { SubjectRepository } from '../repositories';
|
import { SubjectRepository } from '../repositories';
|
||||||
import { repository } from '@loopback/repository';
|
import { repository } from '@loopback/repository';
|
||||||
import { listResponse, ListResponse } from '../graphql-types/list';
|
import { listResponse, ListResponse } from '../graphql-types/list';
|
||||||
import { SubjectList } from '../graphql-types/subject';
|
import { SubjectList, SubjectUpdateInput } from '../graphql-types/subject';
|
||||||
import { SubjectUpdateInput } from '../graphql-types/input/subject-update.input';
|
|
||||||
|
|
||||||
@resolver(of => Subject)
|
@resolver(of => Subject)
|
||||||
export class SubjectResolver {
|
export class SubjectResolver {
|
||||||
|
@ -26,4 +25,10 @@ export class SubjectResolver {
|
||||||
await this.subjectRepo.updateById(input.id, input);
|
await this.subjectRepo.updateById(input.id, input);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@mutation(returns => Boolean)
|
||||||
|
async subjectCreate(@arg('subject') input: SubjectUpdateInput): Promise<boolean> {
|
||||||
|
await this.subjectRepo.create(input);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,10 +8,8 @@ import { TokenServiceBindings, UserServiceBindings } from '@loopback/authenticat
|
||||||
import { TokenService } from '@loopback/authentication';
|
import { TokenService } from '@loopback/authentication';
|
||||||
import { SecurityBindings, UserProfile } from '@loopback/security';
|
import { SecurityBindings, UserProfile } from '@loopback/security';
|
||||||
import { genSalt, hash } from 'bcryptjs';
|
import { genSalt, hash } from 'bcryptjs';
|
||||||
import { UserRegisterInput } from '../graphql-types/input/user-register.input';
|
|
||||||
import { validated } from '../helpers';
|
import { validated } from '../helpers';
|
||||||
import { LoginResult, UserList } from '../graphql-types/user';
|
import { LoginResult, UserList, UserRegisterInput, UserUpdateInput } from '../graphql-types/user';
|
||||||
import { UserUpdateInput } from '../graphql-types/input/user-update.input';
|
|
||||||
import { SzakdolgozatBindings } from '../bindings';
|
import { SzakdolgozatBindings } from '../bindings';
|
||||||
import { listResponse } from '../graphql-types/list';
|
import { listResponse } from '../graphql-types/list';
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { ListResponse } from './list';
|
import { ListResponse } from './list';
|
||||||
import { Course } from '../models';
|
import { Course } from '../models';
|
||||||
import { field, Int, objectType } from '@loopback/graphql';
|
import { field, ID, inputType, Int, objectType } from '@loopback/graphql';
|
||||||
|
import { DataObject } from '@loopback/repository';
|
||||||
|
|
||||||
@objectType()
|
@objectType()
|
||||||
export class CourseList implements ListResponse<Course> {
|
export class CourseList implements ListResponse<Course> {
|
||||||
|
@ -9,3 +10,15 @@ export class CourseList implements ListResponse<Course> {
|
||||||
@field(returns => [Course])
|
@field(returns => [Course])
|
||||||
list: Course[];
|
list: Course[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@inputType()
|
||||||
|
export class CourseUpdateInput implements Pick<DataObject<Course>, 'id' | 'semester' | 'alias' | 'subjectId'> {
|
||||||
|
@field(returns => ID)
|
||||||
|
id: number;
|
||||||
|
@field()
|
||||||
|
semester?: string;
|
||||||
|
@field()
|
||||||
|
alias?: string;
|
||||||
|
@field()
|
||||||
|
subjectId?: number;
|
||||||
|
}
|
||||||
|
|
28
backend/src/graphql-types/fulfillment-mode.ts
Normal file
28
backend/src/graphql-types/fulfillment-mode.ts
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
import { ListResponse } from './list';
|
||||||
|
import { FulfillmentMode } from '../models';
|
||||||
|
import { field, inputType, Int, objectType } from '@loopback/graphql';
|
||||||
|
import { DataObject } from '@loopback/repository';
|
||||||
|
|
||||||
|
@objectType()
|
||||||
|
export class FulfillmentModeList implements ListResponse<FulfillmentMode> {
|
||||||
|
@field(returns => Int)
|
||||||
|
count: number;
|
||||||
|
@field(returns => [FulfillmentMode])
|
||||||
|
list: FulfillmentMode[];
|
||||||
|
}
|
||||||
|
|
||||||
|
@inputType()
|
||||||
|
export class FulfillmentModeUpdateInput implements Omit<DataObject<FulfillmentMode>, 'requirements' | 'courseId'> {
|
||||||
|
@field(returns => Int)
|
||||||
|
id: number;
|
||||||
|
@field()
|
||||||
|
name: string;
|
||||||
|
@field()
|
||||||
|
threshold2: number;
|
||||||
|
@field()
|
||||||
|
threshold3: number;
|
||||||
|
@field()
|
||||||
|
threshold4: number;
|
||||||
|
@field()
|
||||||
|
threshold5: number;
|
||||||
|
}
|
|
@ -1,15 +0,0 @@
|
||||||
import { field, ID, inputType } from '@loopback/graphql';
|
|
||||||
import { Course } from '../../models';
|
|
||||||
import { DataObject } from '@loopback/repository';
|
|
||||||
|
|
||||||
@inputType()
|
|
||||||
export class CourseUpdateInput implements Pick<DataObject<Course>, 'id' | 'semester' | 'alias' | 'subjectId'> {
|
|
||||||
@field(returns => ID)
|
|
||||||
id: number;
|
|
||||||
@field()
|
|
||||||
semester?: string;
|
|
||||||
@field()
|
|
||||||
alias?: string;
|
|
||||||
@field()
|
|
||||||
subjectId?: number;
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
import { field, ID, inputType } from '@loopback/graphql';
|
|
||||||
import { DataObject } from '@loopback/repository';
|
|
||||||
import { Subject } from '../../models';
|
|
||||||
|
|
||||||
@inputType()
|
|
||||||
export class SubjectUpdateInput implements Pick<DataObject<Subject>, 'id' | 'name' | 'description'> {
|
|
||||||
@field(returns => ID)
|
|
||||||
id: number;
|
|
||||||
@field()
|
|
||||||
name?: string;
|
|
||||||
@field()
|
|
||||||
description?: string;
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
import { field, inputType } from '@loopback/graphql';
|
|
||||||
import { User } from '../../models';
|
|
||||||
import { model, property } from '@loopback/repository';
|
|
||||||
import { UserProperties } from '../user';
|
|
||||||
|
|
||||||
@model()
|
|
||||||
@inputType()
|
|
||||||
export class UserRegisterInput implements Pick<User, 'email' | 'name' | 'password'> {
|
|
||||||
@property(UserProperties.email)
|
|
||||||
@field()
|
|
||||||
email: string;
|
|
||||||
@property(UserProperties.name)
|
|
||||||
@field()
|
|
||||||
name: string;
|
|
||||||
@property(UserProperties.password)
|
|
||||||
@field()
|
|
||||||
password: string;
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
import { User } from '../../models';
|
|
||||||
import { field, ID, inputType } from '@loopback/graphql';
|
|
||||||
import { UserProperties } from '../user';
|
|
||||||
import { property } from '@loopback/repository';
|
|
||||||
|
|
||||||
@inputType()
|
|
||||||
export class UserUpdateInput implements Partial<Pick<User, 'id' | 'name' | 'email' | 'password' | 'isAdmin'>> {
|
|
||||||
@field(returns => ID)
|
|
||||||
id: number;
|
|
||||||
@field({nullable: true})
|
|
||||||
@property(UserProperties.email)
|
|
||||||
email?: string;
|
|
||||||
@field({nullable: true})
|
|
||||||
@property(UserProperties.name)
|
|
||||||
name?: string;
|
|
||||||
@field({nullable: true})
|
|
||||||
@property(UserProperties.password)
|
|
||||||
password?: string;
|
|
||||||
@field({nullable: true})
|
|
||||||
isAdmin?: boolean;
|
|
||||||
}
|
|
28
backend/src/graphql-types/requirement.ts
Normal file
28
backend/src/graphql-types/requirement.ts
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
import { ListResponse } from './list';
|
||||||
|
import { Requirement } from '../models';
|
||||||
|
import { field, inputType, Int, objectType } from '@loopback/graphql';
|
||||||
|
import { DataObject } from '@loopback/repository';
|
||||||
|
|
||||||
|
@objectType()
|
||||||
|
export class RequirementList implements ListResponse<Requirement> {
|
||||||
|
@field(returns => Int)
|
||||||
|
count: number;
|
||||||
|
@field(returns => [Requirement])
|
||||||
|
list: Requirement[];
|
||||||
|
}
|
||||||
|
|
||||||
|
@inputType()
|
||||||
|
export class RequirementUpdateInput implements Pick<DataObject<Requirement>, 'id' | 'name' | 'description' | 'deadline' | 'minPoints' | 'maxPoints'> {
|
||||||
|
@field(returns => Int)
|
||||||
|
id: number;
|
||||||
|
@field()
|
||||||
|
deadline: Date;
|
||||||
|
@field()
|
||||||
|
name: string;
|
||||||
|
@field()
|
||||||
|
description: string;
|
||||||
|
@field()
|
||||||
|
minPoints: number;
|
||||||
|
@field()
|
||||||
|
maxPoints: number;
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
import { ListResponse } from './list';
|
import { ListResponse } from './list';
|
||||||
import { Subject } from '../models';
|
import { Subject } from '../models';
|
||||||
import { field, Int, objectType } from '@loopback/graphql';
|
import { field, ID, inputType, Int, objectType } from '@loopback/graphql';
|
||||||
|
import { DataObject } from '@loopback/repository';
|
||||||
|
|
||||||
@objectType()
|
@objectType()
|
||||||
export class SubjectList implements ListResponse<Subject> {
|
export class SubjectList implements ListResponse<Subject> {
|
||||||
|
@ -9,3 +10,13 @@ export class SubjectList implements ListResponse<Subject> {
|
||||||
@field(returns => [Subject])
|
@field(returns => [Subject])
|
||||||
list: Subject[];
|
list: Subject[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@inputType()
|
||||||
|
export class SubjectUpdateInput implements Pick<DataObject<Subject>, 'id' | 'name' | 'description'> {
|
||||||
|
@field(returns => ID)
|
||||||
|
id: number;
|
||||||
|
@field()
|
||||||
|
name?: string;
|
||||||
|
@field()
|
||||||
|
description?: string;
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { User } from '../models';
|
import { User } from '../models';
|
||||||
import { field, Int, objectType } from '@loopback/graphql';
|
import { field, ID, inputType, Int, objectType } from '@loopback/graphql';
|
||||||
import { ListResponse } from './list';
|
import { ListResponse } from './list';
|
||||||
|
import { model, property } from '@loopback/repository';
|
||||||
|
|
||||||
@objectType()
|
@objectType()
|
||||||
export class UserResult implements Pick<User, 'id' | 'email' | 'name' | 'isAdmin'> {
|
export class UserResult implements Pick<User, 'id' | 'email' | 'name' | 'isAdmin'> {
|
||||||
|
@ -60,3 +61,34 @@ export const UserProperties = {
|
||||||
hidden: true
|
hidden: true
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@model()
|
||||||
|
@inputType()
|
||||||
|
export class UserRegisterInput implements Pick<User, 'email' | 'name' | 'password'> {
|
||||||
|
@property(UserProperties.email)
|
||||||
|
@field()
|
||||||
|
email: string;
|
||||||
|
@property(UserProperties.name)
|
||||||
|
@field()
|
||||||
|
name: string;
|
||||||
|
@property(UserProperties.password)
|
||||||
|
@field()
|
||||||
|
password: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
@inputType()
|
||||||
|
export class UserUpdateInput implements Partial<Pick<User, 'id' | 'name' | 'email' | 'password' | 'isAdmin'>> {
|
||||||
|
@field(returns => ID)
|
||||||
|
id: number;
|
||||||
|
@field({nullable: true})
|
||||||
|
@property(UserProperties.email)
|
||||||
|
email?: string;
|
||||||
|
@field({nullable: true})
|
||||||
|
@property(UserProperties.name)
|
||||||
|
name?: string;
|
||||||
|
@field({nullable: true})
|
||||||
|
@property(UserProperties.password)
|
||||||
|
password?: string;
|
||||||
|
@field({nullable: true})
|
||||||
|
isAdmin?: boolean;
|
||||||
|
}
|
||||||
|
|
|
@ -2,8 +2,8 @@ import { belongsTo, Entity, hasMany, model, property } from '@loopback/repositor
|
||||||
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';
|
||||||
import { Requirement } from './requirement.model';
|
|
||||||
import { field, objectType } from '@loopback/graphql';
|
import { field, objectType } from '@loopback/graphql';
|
||||||
|
import { FulfillmentMode } from './fulfillment-mode.model';
|
||||||
|
|
||||||
@model()
|
@model()
|
||||||
@objectType()
|
@objectType()
|
||||||
|
@ -37,8 +37,8 @@ export class Course extends Entity {
|
||||||
@hasMany(() => User, {through: {model: () => CourseUser}})
|
@hasMany(() => User, {through: {model: () => CourseUser}})
|
||||||
users: User[];
|
users: User[];
|
||||||
|
|
||||||
@hasMany(() => Requirement)
|
@hasMany(() => FulfillmentMode)
|
||||||
requirements: Requirement[];
|
fulfillmentModes: FulfillmentMode[];
|
||||||
|
|
||||||
constructor(data?: Partial<Course>) {
|
constructor(data?: Partial<Course>) {
|
||||||
super(data);
|
super(data);
|
||||||
|
|
68
backend/src/models/fulfillment-mode.model.ts
Normal file
68
backend/src/models/fulfillment-mode.model.ts
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
import { Entity, hasMany, model, property } from '@loopback/repository';
|
||||||
|
import { Requirement } from './requirement.model';
|
||||||
|
import { field, ID, objectType } from '@loopback/graphql';
|
||||||
|
|
||||||
|
@model()
|
||||||
|
@objectType()
|
||||||
|
export class FulfillmentMode extends Entity {
|
||||||
|
@property({
|
||||||
|
type: 'number',
|
||||||
|
id: true,
|
||||||
|
generated: true,
|
||||||
|
})
|
||||||
|
@field(returns => ID)
|
||||||
|
id?: number;
|
||||||
|
|
||||||
|
@property({
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
})
|
||||||
|
@field()
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
@property({
|
||||||
|
type: 'number',
|
||||||
|
required: true,
|
||||||
|
})
|
||||||
|
@field()
|
||||||
|
threshold2: number;
|
||||||
|
|
||||||
|
@property({
|
||||||
|
type: 'number',
|
||||||
|
required: true,
|
||||||
|
})
|
||||||
|
@field()
|
||||||
|
threshold3: number;
|
||||||
|
|
||||||
|
@property({
|
||||||
|
type: 'number',
|
||||||
|
required: true,
|
||||||
|
})
|
||||||
|
@field()
|
||||||
|
threshold4: number;
|
||||||
|
|
||||||
|
@property({
|
||||||
|
type: 'number',
|
||||||
|
required: true,
|
||||||
|
})
|
||||||
|
@field()
|
||||||
|
threshold5: number;
|
||||||
|
|
||||||
|
@property({
|
||||||
|
type: 'number',
|
||||||
|
})
|
||||||
|
courseId?: number;
|
||||||
|
|
||||||
|
@hasMany(() => Requirement)
|
||||||
|
requirements: Requirement[];
|
||||||
|
|
||||||
|
constructor(data?: Partial<FulfillmentMode>) {
|
||||||
|
super(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FulfillmentModeRelations {
|
||||||
|
// describe navigational properties here
|
||||||
|
}
|
||||||
|
|
||||||
|
export type FulfillmentModeWithRelations = FulfillmentMode & FulfillmentModeRelations;
|
|
@ -4,3 +4,5 @@ export * from './requirement.model';
|
||||||
export * from './course.model';
|
export * from './course.model';
|
||||||
export * from './course-user.model';
|
export * from './course-user.model';
|
||||||
export * from './rev-token.model';
|
export * from './rev-token.model';
|
||||||
|
export * from './fulfillment-mode.model';
|
||||||
|
export * from './user-fulfill-requirement.model';
|
||||||
|
|
|
@ -1,40 +1,60 @@
|
||||||
import { Entity, model, property } from '@loopback/repository';
|
import { Entity, model, property } from '@loopback/repository';
|
||||||
|
import { field, ID, Int, objectType } from '@loopback/graphql';
|
||||||
|
|
||||||
@model()
|
@model()
|
||||||
|
@objectType()
|
||||||
export class Requirement extends Entity {
|
export class Requirement extends Entity {
|
||||||
@property({
|
@property({
|
||||||
type: 'number',
|
type: 'number',
|
||||||
id: true,
|
id: true,
|
||||||
generated: true,
|
generated: true,
|
||||||
})
|
})
|
||||||
id?: number;
|
@field(returns => ID)
|
||||||
|
id?: number;
|
||||||
|
|
||||||
@property({
|
@property({
|
||||||
type: 'string',
|
type: 'string',
|
||||||
required: true,
|
required: true,
|
||||||
})
|
})
|
||||||
name: string;
|
@field()
|
||||||
|
name: string;
|
||||||
|
|
||||||
@property({
|
@property({
|
||||||
type: 'number',
|
type: 'string',
|
||||||
required: true,
|
required: true,
|
||||||
})
|
})
|
||||||
maxPoints: number;
|
@field()
|
||||||
|
description: string;
|
||||||
|
|
||||||
@property({
|
@property({
|
||||||
type: 'string',
|
type: 'number',
|
||||||
required: true,
|
required: true,
|
||||||
})
|
})
|
||||||
type: string;
|
@field(returns => Int)
|
||||||
|
minPoints: number;
|
||||||
|
|
||||||
@property({
|
@property({
|
||||||
type: 'number',
|
type: 'number',
|
||||||
})
|
required: true,
|
||||||
courseId?: number;
|
})
|
||||||
|
@field(returns => Int)
|
||||||
|
maxPoints: number;
|
||||||
|
|
||||||
constructor(data?: Partial<Requirement>) {
|
@property({
|
||||||
super(data);
|
type: 'date',
|
||||||
}
|
required: true,
|
||||||
|
})
|
||||||
|
@field()
|
||||||
|
deadline: Date;
|
||||||
|
|
||||||
|
@property({
|
||||||
|
type: 'number',
|
||||||
|
})
|
||||||
|
fulfillmentModeId?: number;
|
||||||
|
|
||||||
|
constructor(data?: Partial<Requirement>) {
|
||||||
|
super(data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RequirementRelations {
|
export interface RequirementRelations {
|
||||||
|
|
43
backend/src/models/user-fulfill-requirement.model.ts
Normal file
43
backend/src/models/user-fulfill-requirement.model.ts
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
import { Entity, model, property } from '@loopback/repository';
|
||||||
|
|
||||||
|
@model()
|
||||||
|
export class UserFulfillRequirement extends Entity {
|
||||||
|
@property({
|
||||||
|
type: 'number',
|
||||||
|
id: true,
|
||||||
|
generated: true,
|
||||||
|
})
|
||||||
|
id?: number;
|
||||||
|
|
||||||
|
@property({
|
||||||
|
type: 'number',
|
||||||
|
required: true,
|
||||||
|
})
|
||||||
|
points: number;
|
||||||
|
|
||||||
|
@property({
|
||||||
|
type: 'date',
|
||||||
|
required: true,
|
||||||
|
})
|
||||||
|
dateTime: string;
|
||||||
|
|
||||||
|
@property({
|
||||||
|
type: 'number',
|
||||||
|
})
|
||||||
|
userId?: number;
|
||||||
|
|
||||||
|
@property({
|
||||||
|
type: 'number',
|
||||||
|
})
|
||||||
|
requirementId?: number;
|
||||||
|
|
||||||
|
constructor(data?: Partial<UserFulfillRequirement>) {
|
||||||
|
super(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UserFulfillRequirementRelations {
|
||||||
|
// describe navigational properties here
|
||||||
|
}
|
||||||
|
|
||||||
|
export type UserFulfillRequirementWithRelations = UserFulfillRequirement & UserFulfillRequirementRelations;
|
|
@ -3,6 +3,8 @@ import { Course } from './course.model';
|
||||||
import { CourseUser } from './course-user.model';
|
import { CourseUser } from './course-user.model';
|
||||||
import { field, objectType } from '@loopback/graphql';
|
import { field, objectType } from '@loopback/graphql';
|
||||||
import { UserProperties } from '../graphql-types/user';
|
import { UserProperties } from '../graphql-types/user';
|
||||||
|
import { Requirement } from './requirement.model';
|
||||||
|
import { UserFulfillRequirement } from './user-fulfill-requirement.model';
|
||||||
|
|
||||||
@model()
|
@model()
|
||||||
@objectType()
|
@objectType()
|
||||||
|
@ -34,6 +36,9 @@ export class User extends Entity {
|
||||||
//@field()
|
//@field()
|
||||||
courses: Course[];
|
courses: Course[];
|
||||||
|
|
||||||
|
@hasMany(() => Requirement, {through: {model: () => UserFulfillRequirement}})
|
||||||
|
completedRequirements: Requirement[];
|
||||||
|
|
||||||
constructor(data?: Partial<User>) {
|
constructor(data?: Partial<User>) {
|
||||||
super(data);
|
super(data);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,37 +1,36 @@
|
||||||
import { inject, Getter } from '@loopback/core';
|
import { Getter, inject } from '@loopback/core';
|
||||||
import {
|
import { BelongsToAccessor, repository } from '@loopback/repository';
|
||||||
DefaultCrudRepository,
|
|
||||||
repository,
|
|
||||||
BelongsToAccessor,
|
|
||||||
HasManyThroughRepositoryFactory,
|
|
||||||
HasManyRepositoryFactory
|
|
||||||
} from '@loopback/repository';
|
|
||||||
import { DatabaseDataSource } from '../datasources';
|
import { DatabaseDataSource } from '../datasources';
|
||||||
import { Course, CourseRelations, Subject, User, CourseUser, Requirement } from '../models';
|
import { Course, CourseRelations, CourseUser, FulfillmentMode, Subject, User } from '../models';
|
||||||
import { SubjectRepository } from './subject.repository';
|
import { SubjectRepository } from './subject.repository';
|
||||||
import { CourseUserRepository } from './course-user.repository';
|
import { CourseUserRepository } from './course-user.repository';
|
||||||
import { UserRepository } from './user.repository';
|
import { UserRepository } from './user.repository';
|
||||||
import { RequirementRepository } from './requirement.repository';
|
import { FulfillmentModeRepository } from './fulfillment-mode.repository';
|
||||||
|
import { CustomCrudRepository, CustomHasManyRepositoryFactory, CustomHasManyThroughRepositoryFactory } from './custom-has-many-repository';
|
||||||
|
|
||||||
export class CourseRepository extends DefaultCrudRepository<Course,
|
export class CourseRepository extends CustomCrudRepository<Course,
|
||||||
typeof Course.prototype.id,
|
typeof Course.prototype.id,
|
||||||
CourseRelations> {
|
CourseRelations> {
|
||||||
|
|
||||||
public readonly subject: BelongsToAccessor<Subject, typeof Course.prototype.id>;
|
public readonly subject: BelongsToAccessor<Subject, typeof Course.prototype.id>;
|
||||||
|
|
||||||
public readonly users: HasManyThroughRepositoryFactory<User, typeof User.prototype.id,
|
public readonly users: CustomHasManyThroughRepositoryFactory<User, typeof User.prototype.id,
|
||||||
CourseUser,
|
CourseUser,
|
||||||
typeof Course.prototype.id>;
|
typeof Course.prototype.id>;
|
||||||
|
|
||||||
public readonly requirements: HasManyRepositoryFactory<Requirement, typeof Course.prototype.id>;
|
public readonly fulfillmentModes: CustomHasManyRepositoryFactory<FulfillmentMode, typeof Course.prototype.id>;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@inject('datasources.database') dataSource: DatabaseDataSource, @repository.getter('SubjectRepository') protected subjectRepositoryGetter: Getter<SubjectRepository>, @repository.getter('CourseUserRepository') protected courseUserRepositoryGetter: Getter<CourseUserRepository>, @repository.getter('UserRepository') protected userRepositoryGetter: Getter<UserRepository>, @repository.getter('RequirementRepository') protected requirementRepositoryGetter: Getter<RequirementRepository>,
|
@inject('datasources.database') dataSource: DatabaseDataSource,
|
||||||
|
@repository.getter('SubjectRepository') protected subjectRepositoryGetter: Getter<SubjectRepository>,
|
||||||
|
@repository.getter('CourseUserRepository') protected courseUserRepositoryGetter: Getter<CourseUserRepository>,
|
||||||
|
@repository.getter('UserRepository') protected userRepositoryGetter: Getter<UserRepository>,
|
||||||
|
@repository.getter('FulfillmentModeRepository') protected fulfillmentModeRepositoryGetter: Getter<FulfillmentModeRepository>,
|
||||||
) {
|
) {
|
||||||
super(Course, dataSource);
|
super(Course, dataSource);
|
||||||
this.requirements = this.createHasManyRepositoryFactoryFor('requirements', requirementRepositoryGetter,);
|
this.fulfillmentModes = this.createCustomHasManyRepositoryFactoryFor('fulfillmentModes', fulfillmentModeRepositoryGetter, 'courseId');
|
||||||
this.registerInclusionResolver('requirements', this.requirements.inclusionResolver);
|
this.registerInclusionResolver('fulfillmentModes', this.fulfillmentModes.inclusionResolver);
|
||||||
this.users = this.createHasManyThroughRepositoryFactoryFor('users', userRepositoryGetter, courseUserRepositoryGetter,);
|
this.users = this.createCustomHasManyThroughFactoryFor('users', userRepositoryGetter, courseUserRepositoryGetter, 'courseId', 'userId');
|
||||||
this.registerInclusionResolver('users', this.users.inclusionResolver);
|
this.registerInclusionResolver('users', this.users.inclusionResolver);
|
||||||
this.subject = this.createBelongsToAccessorFor('subject', subjectRepositoryGetter,);
|
this.subject = this.createBelongsToAccessorFor('subject', subjectRepositoryGetter,);
|
||||||
this.registerInclusionResolver('subject', this.subject.inclusionResolver);
|
this.registerInclusionResolver('subject', this.subject.inclusionResolver);
|
||||||
|
|
21
backend/src/repositories/fulfillment-mode.repository.ts
Normal file
21
backend/src/repositories/fulfillment-mode.repository.ts
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import { Getter, inject } from '@loopback/core';
|
||||||
|
import { repository } from '@loopback/repository';
|
||||||
|
import { DatabaseDataSource } from '../datasources';
|
||||||
|
import { FulfillmentMode, FulfillmentModeRelations, Requirement } from '../models';
|
||||||
|
import { RequirementRepository } from './requirement.repository';
|
||||||
|
import { CustomCrudRepository, CustomHasManyRepositoryFactory } from './custom-has-many-repository';
|
||||||
|
|
||||||
|
export class FulfillmentModeRepository extends CustomCrudRepository<FulfillmentMode,
|
||||||
|
typeof FulfillmentMode.prototype.id,
|
||||||
|
FulfillmentModeRelations> {
|
||||||
|
|
||||||
|
public readonly requirements: CustomHasManyRepositoryFactory<Requirement, typeof FulfillmentMode.prototype.id>;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
@inject('datasources.database') dataSource: DatabaseDataSource, @repository.getter('RequirementRepository') protected requirementRepositoryGetter: Getter<RequirementRepository>,
|
||||||
|
) {
|
||||||
|
super(FulfillmentMode, dataSource);
|
||||||
|
this.requirements = this.createCustomHasManyRepositoryFactoryFor('requirements', requirementRepositoryGetter, 'fulfillmentModeId');
|
||||||
|
this.registerInclusionResolver('requirements', this.requirements.inclusionResolver);
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,3 +4,5 @@ export * from './requirement.repository';
|
||||||
export * from './course.repository';
|
export * from './course.repository';
|
||||||
export * from './course-user.repository';
|
export * from './course-user.repository';
|
||||||
export * from './rev-token.repository';
|
export * from './rev-token.repository';
|
||||||
|
export * from './fulfillment-mode.repository';
|
||||||
|
export * from './user-fulfill-requirement.repository';
|
||||||
|
|
|
@ -6,9 +6,9 @@ import { RevToken, RevTokenRelations } from '../models';
|
||||||
export class RevTokenRepository extends DefaultCrudRepository<RevToken,
|
export class RevTokenRepository extends DefaultCrudRepository<RevToken,
|
||||||
typeof RevToken.prototype.token,
|
typeof RevToken.prototype.token,
|
||||||
RevTokenRelations> {
|
RevTokenRelations> {
|
||||||
constructor(
|
constructor(
|
||||||
@inject('datasources.database') dataSource: DatabaseDataSource,
|
@inject('datasources.database') dataSource: DatabaseDataSource,
|
||||||
) {
|
) {
|
||||||
super(RevToken, dataSource);
|
super(RevToken, dataSource);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
import { inject } from '@loopback/core';
|
||||||
|
import { DatabaseDataSource } from '../datasources';
|
||||||
|
import { UserFulfillRequirement, UserFulfillRequirementRelations } from '../models';
|
||||||
|
import { CustomCrudRepository } from './custom-has-many-repository';
|
||||||
|
|
||||||
|
export class UserFulfillRequirementRepository extends CustomCrudRepository<UserFulfillRequirement,
|
||||||
|
typeof UserFulfillRequirement.prototype.id,
|
||||||
|
UserFulfillRequirementRelations> {
|
||||||
|
constructor(
|
||||||
|
@inject('datasources.database') dataSource: DatabaseDataSource,
|
||||||
|
) {
|
||||||
|
super(UserFulfillRequirement, dataSource);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,11 +1,13 @@
|
||||||
import { Getter, inject } from '@loopback/core';
|
import { Getter, inject } from '@loopback/core';
|
||||||
import { repository } from '@loopback/repository';
|
import { HasManyThroughRepositoryFactory, repository } from '@loopback/repository';
|
||||||
import { DatabaseDataSource } from '../datasources';
|
import { DatabaseDataSource } from '../datasources';
|
||||||
import { Course, CourseUser, User, UserRelations } from '../models';
|
import { Course, CourseUser, Requirement, User, UserFulfillRequirement, UserRelations } from '../models';
|
||||||
import { SubjectRepository } from './subject.repository';
|
import { SubjectRepository } from './subject.repository';
|
||||||
import { CourseUserRepository } from './course-user.repository';
|
import { CourseUserRepository } from './course-user.repository';
|
||||||
import { CourseRepository } from './course.repository';
|
import { CourseRepository } from './course.repository';
|
||||||
import { CustomCrudRepository, CustomHasManyThroughRepositoryFactory } from './custom-has-many-repository';
|
import { CustomCrudRepository, CustomHasManyThroughRepositoryFactory } from './custom-has-many-repository';
|
||||||
|
import { UserFulfillRequirementRepository } from './user-fulfill-requirement.repository';
|
||||||
|
import { RequirementRepository } from './requirement.repository';
|
||||||
|
|
||||||
export class UserRepository extends CustomCrudRepository<User,
|
export class UserRepository extends CustomCrudRepository<User,
|
||||||
typeof User.prototype.id,
|
typeof User.prototype.id,
|
||||||
|
@ -15,10 +17,16 @@ export class UserRepository extends CustomCrudRepository<User,
|
||||||
CourseUser,
|
CourseUser,
|
||||||
typeof User.prototype.id>;
|
typeof User.prototype.id>;
|
||||||
|
|
||||||
|
public readonly completedRequirements: HasManyThroughRepositoryFactory<Requirement, typeof Requirement.prototype.id,
|
||||||
|
UserFulfillRequirement,
|
||||||
|
typeof User.prototype.id>;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@inject('datasources.database') dataSource: DatabaseDataSource, @repository.getter('SubjectRepository') protected subjectRepositoryGetter: Getter<SubjectRepository>, @repository.getter('CourseUserRepository') protected courseUserRepositoryGetter: Getter<CourseUserRepository>, @repository.getter('CourseRepository') protected courseRepositoryGetter: Getter<CourseRepository>,
|
@inject('datasources.database') dataSource: DatabaseDataSource, @repository.getter('SubjectRepository') protected subjectRepositoryGetter: Getter<SubjectRepository>, @repository.getter('CourseUserRepository') protected courseUserRepositoryGetter: Getter<CourseUserRepository>, @repository.getter('CourseRepository') protected courseRepositoryGetter: Getter<CourseRepository>, @repository.getter('UserFulfillRequirementRepository') protected userFulfillRequirementRepositoryGetter: Getter<UserFulfillRequirementRepository>, @repository.getter('RequirementRepository') protected requirementRepositoryGetter: Getter<RequirementRepository>,
|
||||||
) {
|
) {
|
||||||
super(User, dataSource);
|
super(User, dataSource);
|
||||||
|
this.completedRequirements = this.createHasManyThroughRepositoryFactoryFor('completedRequirements', requirementRepositoryGetter, userFulfillRequirementRepositoryGetter,);
|
||||||
|
this.registerInclusionResolver('completedRequirements', this.completedRequirements.inclusionResolver);
|
||||||
this.courses = this.createCustomHasManyThroughFactoryFor('courses', courseRepositoryGetter, courseUserRepositoryGetter, 'userId', 'courseId');
|
this.courses = this.createCustomHasManyThroughFactoryFor('courses', courseRepositoryGetter, courseUserRepositoryGetter, 'userId', 'courseId');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,3 +31,7 @@ query Course($id: ID!) {
|
||||||
mutation EditCourse($input: CourseUpdateInput!) {
|
mutation EditCourse($input: CourseUpdateInput!) {
|
||||||
courseUpdate(course: $input)
|
courseUpdate(course: $input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutation CreateCourse($input: CourseUpdateInput!) {
|
||||||
|
courseCreate(course: $input)
|
||||||
|
}
|
||||||
|
|
32
frontend/src/app/graphql/requirement.graphql
Normal file
32
frontend/src/app/graphql/requirement.graphql
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
query RequirementList($mode: ID!, $limit: Int!, $offset: Int!) {
|
||||||
|
requirements(mode: $mode, limit: $limit, offset: $offset) {
|
||||||
|
count
|
||||||
|
list {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
description
|
||||||
|
deadline
|
||||||
|
minPoints
|
||||||
|
maxPoints
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
query Requirement($id: ID!) {
|
||||||
|
requirement(id: $id) {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
description
|
||||||
|
deadline
|
||||||
|
minPoints
|
||||||
|
maxPoints
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mutation EditRequirement($input: RequirementUpdateInput!) {
|
||||||
|
requirementUpdate(requirement: $input)
|
||||||
|
}
|
||||||
|
|
||||||
|
mutation CreateRequirement($input: RequirementUpdateInput!) {
|
||||||
|
requirementCreate(requirement: $input)
|
||||||
|
}
|
|
@ -20,3 +20,7 @@ query Subject($id: ID!) {
|
||||||
mutation EditSubject($input: SubjectUpdateInput!) {
|
mutation EditSubject($input: SubjectUpdateInput!) {
|
||||||
subjectUpdate(subject: $input)
|
subjectUpdate(subject: $input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutation CreateSubject($input: SubjectUpdateInput!) {
|
||||||
|
subjectCreate(subject: $input)
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
<app-list [gql]="listGQL"></app-list>
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { RequirementListComponent } from './requirement-list.component';
|
||||||
|
|
||||||
|
describe('RequirementsListComponent', () => {
|
||||||
|
let component: RequirementListComponent;
|
||||||
|
let fixture: ComponentFixture<RequirementListComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [RequirementListComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(RequirementListComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,17 @@
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { RequirementListGQL } from '../../services/graphql';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-requirement-list',
|
||||||
|
templateUrl: './requirement-list.component.html',
|
||||||
|
styleUrls: ['./requirement-list.component.css']
|
||||||
|
})
|
||||||
|
export class RequirementListComponent implements OnInit {
|
||||||
|
|
||||||
|
constructor(public listGQL: RequirementListGQL) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
15
frontend/src/app/requirements/requirements.module.ts
Normal file
15
frontend/src/app/requirements/requirements.module.ts
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { RequirementListComponent } from './requirement-list/requirement-list.component';
|
||||||
|
import { SharedComponentsModule } from '../shared-components/shared-components.module';
|
||||||
|
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [RequirementListComponent],
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
SharedComponentsModule
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class RequirementsModule {
|
||||||
|
}
|
Loading…
Reference in a new issue