Add configurable levels

- Add Level table and gql type
- change level field on User
- add hook on user to update the level
pull/4/head
trivernis 5 years ago
parent 781ee274b8
commit 9328367bb5

@ -36,6 +36,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- delete handler for media to delete the corresponding file
- type for create post to know if it is a media or text post (media posts are invisible until a media file is uploaded)
- reports and mutations to report posts and create reasons to report
- level entity
### Removed
@ -51,6 +52,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- config behaviour to use all files that reside in the ./config directory with the .toml format
- default response timeout from 2 minutes to 30 seconds
- cluster api to start workers with a 2 second delay each to avoid race conditions
- levels to be configured in the backend
### Fixed
@ -60,6 +62,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- style issues
- graphql schema for denyRequest using the wrong parameters
- sendRequest allowing duplicates
- upload throwing an error when the old picture doesn't exist
## [0.9] - 2019-10-29

@ -67,12 +67,12 @@ namespace dataaccess {
models.Media,
models.Report,
models.ReportReason,
models.Level,
]);
} catch (err) {
globals.logger.error(err.message);
globals.logger.debug(err.stack);
}
await databaseCleanup();
setInterval(databaseCleanup, config.get<number>("database.cleanupInterval") * 1000);
}

@ -0,0 +1,33 @@
import * as sqz from "sequelize";
import {Column, Model, NotNull, Table, Unique} from "sequelize-typescript";
/**
* A level of the ranking system
*/
@Table({underscored: true})
export class Level extends Model<Level> {
/**
* The name of the level
*/
@NotNull
@Unique
@Column({allowNull: false, type: sqz.STRING(64), unique: true})
public name: string;
/**
* The number of the level
*/
@NotNull
@Unique
@Column({allowNull: false, unique: true})
public levelNumber: number;
/**
* The required points for the level
*/
@NotNull
@Unique
@Column({allowNull: false, unique: true})
public points: number;
}

@ -18,8 +18,10 @@ export class Media extends Model<Media> {
*/
@BeforeDestroy
public static async deleteMediaFile(instance: Media) {
if (await fsx.pathExists(instance.path)) {
await fsx.unlink(instance.path);
}
}
/**
* The api url for the media

@ -1,5 +1,6 @@
import * as sqz from "sequelize";
import {
BeforeUpdate,
BelongsTo,
BelongsToMany,
Column,
@ -24,6 +25,7 @@ import {Friendship} from "./Friendship";
import {Group} from "./Group";
import {GroupAdmin} from "./GroupAdmin";
import {GroupMember} from "./GroupMember";
import {Level} from "./Level";
import {Media} from "./Media";
import {Post} from "./Post";
import {PostVote} from "./PostVote";
@ -35,6 +37,19 @@ import {Request, RequestType} from "./Request";
@Table({underscored: true})
export class User extends Model<User> {
/**
* A function that is called before the user is updated.
* It assigns the corresponding level to the user
* @param instance
*/
@BeforeUpdate
public static async assignLevel(instance: User) {
const level = await Level.findOne({where: {points: {[sqz.Op.lte]: instance.rankpoints}}, order: [["levelNumber", "desc"]]}) as Level;
if (level) {
instance.$set("rLevel", level);
}
}
/**
* The name of the user
*/
@ -99,6 +114,13 @@ export class User extends Model<User> {
@Column({defaultValue: false, allowNull: false})
public isAdmin: boolean;
/**
* The level of the user
*/
@ForeignKey(() => Level)
@Column({allowNull: true})
public levelId: number;
/**
* The id of the media that is the users profile picture
*/
@ -106,6 +128,12 @@ export class User extends Model<User> {
@Column({allowNull: true})
public mediaId: number;
/**
* The level of the user
*/
@BelongsTo(() => Level)
public rLevel: Level;
/**
* The media of the user
*/
@ -220,8 +248,8 @@ export class User extends Model<User> {
/**
* The level of the user which is the points divided by 100
*/
public get level(): number {
return Math.ceil(this.getDataValue("rankpoints") / 100);
public async level(): Promise<Level> {
return await this.$get("rLevel") as Level;
}
/**

@ -16,3 +16,4 @@ export {BlacklistedPhrase} from "./BlacklistedPhrase";
export {Media} from "./Media";
export {Report} from "./Report";
export {ReportReason} from "./ReportReason";
export {Level} from "./Level";

@ -189,7 +189,7 @@ interface UserData {
points: Int!
"the levels of the user depending on the points"
level: Int!
level: Level
}
"represents a single user account"
@ -240,7 +240,7 @@ type User implements UserData{
eventCount: Int!
"the levels of the user depending on the points"
level: Int!
level: Level
}
type Profile implements UserData {
@ -311,7 +311,7 @@ type Profile implements UserData {
points: Int!
"the levels of the user depending on the points"
level: Int!
level: Level
"the custom settings for the frontend"
settings: String!
@ -571,6 +571,16 @@ type ReportReason {
description: String!
}
"A level of a user"
type Level {
"The name of the level"
name: String!
"The number of the level in the ranking"
levelNumber: String!
}
"represents the type of media"
enum MediaType {
VIDEO

Loading…
Cancel
Save