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:
Norbi Peti 2022-05-13 20:46:17 +02:00
parent d076e0a013
commit 832cf07aa5
No known key found for this signature in database
GPG key ID: DBA4C4549A927E56
45 changed files with 546 additions and 1175 deletions

View file

@ -15,6 +15,8 @@ import { UserResolver } from './graphql-resolvers/user.resolver';
import { SzakdolgozatAuthChecker } from './szakdolgozat-auth-checker';
import { CourseResolver } from './graphql-resolvers/course.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 };
@ -36,6 +38,8 @@ export class SzakdolgozatBackendApplication extends BootMixin(
s.resolver(UserResolver);
s.resolver(CourseResolver);
s.resolver(SubjectResolver);
s.resolver(FulfillmentModeResolver);
s.resolver(RequirementResolver);
});
// Authentication

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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';

View file

@ -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),
};
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -2,9 +2,8 @@ import { repository } from '@loopback/repository';
import { CourseRepository, SubjectRepository, UserRepository } from '../repositories';
import { arg, ID, Int, mutation, query, resolver } from '@loopback/graphql';
import { Course } from '../models';
import { CourseUpdateInput } from '../graphql-types/input/course-update.input';
import { listResponse, ListResponse } from '../graphql-types/list';
import { CourseList } from '../graphql-types/course';
import { CourseList, CourseUpdateInput } from '../graphql-types/course';
@resolver(of => Course)
export class CourseResolver {
@ -35,4 +34,10 @@ export class CourseResolver {
await this.courseRepo.updateById(input.id, input);
return true;
}
@mutation(returns => Boolean)
async courseCreate(@arg('course') input: CourseUpdateInput): Promise<boolean> {
await this.courseRepo.create(input);
return true;
}
}

View 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;
}
}

View 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;
}
}

View file

@ -3,8 +3,7 @@ import { Subject } from '../models';
import { SubjectRepository } from '../repositories';
import { repository } from '@loopback/repository';
import { listResponse, ListResponse } from '../graphql-types/list';
import { SubjectList } from '../graphql-types/subject';
import { SubjectUpdateInput } from '../graphql-types/input/subject-update.input';
import { SubjectList, SubjectUpdateInput } from '../graphql-types/subject';
@resolver(of => Subject)
export class SubjectResolver {
@ -26,4 +25,10 @@ export class SubjectResolver {
await this.subjectRepo.updateById(input.id, input);
return true;
}
@mutation(returns => Boolean)
async subjectCreate(@arg('subject') input: SubjectUpdateInput): Promise<boolean> {
await this.subjectRepo.create(input);
return true;
}
}

View file

@ -8,10 +8,8 @@ import { TokenServiceBindings, UserServiceBindings } from '@loopback/authenticat
import { TokenService } from '@loopback/authentication';
import { SecurityBindings, UserProfile } from '@loopback/security';
import { genSalt, hash } from 'bcryptjs';
import { UserRegisterInput } from '../graphql-types/input/user-register.input';
import { validated } from '../helpers';
import { LoginResult, UserList } from '../graphql-types/user';
import { UserUpdateInput } from '../graphql-types/input/user-update.input';
import { LoginResult, UserList, UserRegisterInput, UserUpdateInput } from '../graphql-types/user';
import { SzakdolgozatBindings } from '../bindings';
import { listResponse } from '../graphql-types/list';

View file

@ -1,6 +1,7 @@
import { ListResponse } from './list';
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()
export class CourseList implements ListResponse<Course> {
@ -9,3 +10,15 @@ export class CourseList implements ListResponse<Course> {
@field(returns => [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;
}

View 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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View 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;
}

View file

@ -1,6 +1,7 @@
import { ListResponse } from './list';
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()
export class SubjectList implements ListResponse<Subject> {
@ -9,3 +10,13 @@ export class SubjectList implements ListResponse<Subject> {
@field(returns => [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;
}

View file

@ -1,6 +1,7 @@
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 { model, property } from '@loopback/repository';
@objectType()
export class UserResult implements Pick<User, 'id' | 'email' | 'name' | 'isAdmin'> {
@ -60,3 +61,34 @@ export const UserProperties = {
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;
}

View file

@ -2,8 +2,8 @@ import { belongsTo, Entity, hasMany, model, property } from '@loopback/repositor
import { Subject } from './subject.model';
import { User } from './user.model';
import { CourseUser } from './course-user.model';
import { Requirement } from './requirement.model';
import { field, objectType } from '@loopback/graphql';
import { FulfillmentMode } from './fulfillment-mode.model';
@model()
@objectType()
@ -37,8 +37,8 @@ export class Course extends Entity {
@hasMany(() => User, {through: {model: () => CourseUser}})
users: User[];
@hasMany(() => Requirement)
requirements: Requirement[];
@hasMany(() => FulfillmentMode)
fulfillmentModes: FulfillmentMode[];
constructor(data?: Partial<Course>) {
super(data);

View 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;

View file

@ -4,3 +4,5 @@ export * from './requirement.model';
export * from './course.model';
export * from './course-user.model';
export * from './rev-token.model';
export * from './fulfillment-mode.model';
export * from './user-fulfill-requirement.model';

View file

@ -1,40 +1,60 @@
import { Entity, model, property } from '@loopback/repository';
import { field, ID, Int, objectType } from '@loopback/graphql';
@model()
@objectType()
export class Requirement extends Entity {
@property({
type: 'number',
id: true,
generated: true,
})
id?: number;
@property({
type: 'number',
id: true,
generated: true,
})
@field(returns => ID)
id?: number;
@property({
type: 'string',
required: true,
})
name: string;
@property({
type: 'string',
required: true,
})
@field()
name: string;
@property({
type: 'number',
required: true,
})
maxPoints: number;
@property({
type: 'string',
required: true,
})
@field()
description: string;
@property({
type: 'string',
required: true,
})
type: string;
@property({
type: 'number',
required: true,
})
@field(returns => Int)
minPoints: number;
@property({
type: 'number',
})
courseId?: number;
@property({
type: 'number',
required: true,
})
@field(returns => Int)
maxPoints: number;
constructor(data?: Partial<Requirement>) {
super(data);
}
@property({
type: 'date',
required: true,
})
@field()
deadline: Date;
@property({
type: 'number',
})
fulfillmentModeId?: number;
constructor(data?: Partial<Requirement>) {
super(data);
}
}
export interface RequirementRelations {

View 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;

View file

@ -3,6 +3,8 @@ import { Course } from './course.model';
import { CourseUser } from './course-user.model';
import { field, objectType } from '@loopback/graphql';
import { UserProperties } from '../graphql-types/user';
import { Requirement } from './requirement.model';
import { UserFulfillRequirement } from './user-fulfill-requirement.model';
@model()
@objectType()
@ -34,6 +36,9 @@ export class User extends Entity {
//@field()
courses: Course[];
@hasMany(() => Requirement, {through: {model: () => UserFulfillRequirement}})
completedRequirements: Requirement[];
constructor(data?: Partial<User>) {
super(data);
}

View file

@ -1,37 +1,36 @@
import { inject, Getter } from '@loopback/core';
import {
DefaultCrudRepository,
repository,
BelongsToAccessor,
HasManyThroughRepositoryFactory,
HasManyRepositoryFactory
} from '@loopback/repository';
import { Getter, inject } from '@loopback/core';
import { BelongsToAccessor, repository } from '@loopback/repository';
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 { CourseUserRepository } from './course-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,
CourseRelations> {
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,
typeof Course.prototype.id>;
public readonly requirements: HasManyRepositoryFactory<Requirement, typeof Course.prototype.id>;
public readonly fulfillmentModes: CustomHasManyRepositoryFactory<FulfillmentMode, typeof Course.prototype.id>;
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);
this.requirements = this.createHasManyRepositoryFactoryFor('requirements', requirementRepositoryGetter,);
this.registerInclusionResolver('requirements', this.requirements.inclusionResolver);
this.users = this.createHasManyThroughRepositoryFactoryFor('users', userRepositoryGetter, courseUserRepositoryGetter,);
this.fulfillmentModes = this.createCustomHasManyRepositoryFactoryFor('fulfillmentModes', fulfillmentModeRepositoryGetter, 'courseId');
this.registerInclusionResolver('fulfillmentModes', this.fulfillmentModes.inclusionResolver);
this.users = this.createCustomHasManyThroughFactoryFor('users', userRepositoryGetter, courseUserRepositoryGetter, 'courseId', 'userId');
this.registerInclusionResolver('users', this.users.inclusionResolver);
this.subject = this.createBelongsToAccessorFor('subject', subjectRepositoryGetter,);
this.registerInclusionResolver('subject', this.subject.inclusionResolver);

View 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);
}
}

View file

@ -4,3 +4,5 @@ export * from './requirement.repository';
export * from './course.repository';
export * from './course-user.repository';
export * from './rev-token.repository';
export * from './fulfillment-mode.repository';
export * from './user-fulfill-requirement.repository';

View file

@ -6,9 +6,9 @@ import { RevToken, RevTokenRelations } from '../models';
export class RevTokenRepository extends DefaultCrudRepository<RevToken,
typeof RevToken.prototype.token,
RevTokenRelations> {
constructor(
@inject('datasources.database') dataSource: DatabaseDataSource,
) {
super(RevToken, dataSource);
}
constructor(
@inject('datasources.database') dataSource: DatabaseDataSource,
) {
super(RevToken, dataSource);
}
}

View file

@ -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);
}
}

View file

@ -1,11 +1,13 @@
import { Getter, inject } from '@loopback/core';
import { repository } from '@loopback/repository';
import { HasManyThroughRepositoryFactory, repository } from '@loopback/repository';
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 { CourseUserRepository } from './course-user.repository';
import { CourseRepository } from './course.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,
typeof User.prototype.id,
@ -15,10 +17,16 @@ export class UserRepository extends CustomCrudRepository<User,
CourseUser,
typeof User.prototype.id>;
public readonly completedRequirements: HasManyThroughRepositoryFactory<Requirement, typeof Requirement.prototype.id,
UserFulfillRequirement,
typeof User.prototype.id>;
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);
this.completedRequirements = this.createHasManyThroughRepositoryFactoryFor('completedRequirements', requirementRepositoryGetter, userFulfillRequirementRepositoryGetter,);
this.registerInclusionResolver('completedRequirements', this.completedRequirements.inclusionResolver);
this.courses = this.createCustomHasManyThroughFactoryFor('courses', courseRepositoryGetter, courseUserRepositoryGetter, 'userId', 'courseId');
}
}

View file

@ -31,3 +31,7 @@ query Course($id: ID!) {
mutation EditCourse($input: CourseUpdateInput!) {
courseUpdate(course: $input)
}
mutation CreateCourse($input: CourseUpdateInput!) {
courseCreate(course: $input)
}

View 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)
}

View file

@ -20,3 +20,7 @@ query Subject($id: ID!) {
mutation EditSubject($input: SubjectUpdateInput!) {
subjectUpdate(subject: $input)
}
mutation CreateSubject($input: SubjectUpdateInput!) {
subjectCreate(subject: $input)
}

View file

@ -0,0 +1 @@
<app-list [gql]="listGQL"></app-list>

View file

@ -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();
});
});

View file

@ -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 {
}
}

View 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 {
}