Skip to content

Commit 31740a0

Browse files
authored
Application dates configurable (#124)
1 parent 0fe9532 commit 31740a0

13 files changed

Lines changed: 145 additions & 46 deletions

File tree

backend/src/controllers/dto.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import {
3434
EmailTemplateSize,
3535
FrontendSettings,
3636
Settings,
37+
ProjectSettings,
3738
} from "../entities/settings";
3839
import { User } from "../entities/user";
3940
import { UserRole } from "../entities/user-role";
@@ -91,6 +92,17 @@ export class ApplicationSettingsDTO implements DTO<ApplicationSettings> {
9192
@IsNumber()
9293
@Expose()
9394
public hoursToConfirm!: number;
95+
@Type(() => Date)
96+
@IsDate()
97+
@Expose()
98+
public acceptanceDeadline!: Date;
99+
@Type(() => Date)
100+
@IsDate()
101+
@Expose()
102+
public confirmSpotUntil!: Date;
103+
}
104+
105+
export class ProjectSettingsDTO implements DTO<ProjectSettings> {
94106
@IsBoolean()
95107
@Expose()
96108
public allowRatingProjects!: boolean;
@@ -166,6 +178,10 @@ export class SettingsDTO implements DTO<Omit<Settings, "updatedAt">> {
166178
@ValidateNested()
167179
@Expose()
168180
public email!: EmailSettingsDTO;
181+
@Type(() => ProjectSettingsDTO)
182+
@ValidateNested()
183+
@Expose()
184+
public project!: ProjectSettingsDTO;
169185
}
170186

171187
export abstract class QuestionConfigurationDTOBase {

backend/src/entities/application-settings.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ import { FormSettings } from "./form-settings";
1111
// TODO all other settings are part of the settings table, whereas ApplicationSettings
1212
// is a separate table. Move into settings table just like EmailSettings.
1313

14+
/**
15+
* Application as in "Peoples application for the event"
16+
*/
1417
@Entity()
1518
export class ApplicationSettings {
1619
@PrimaryGeneratedColumn()
@@ -29,6 +32,8 @@ export class ApplicationSettings {
2932
public allowProfileFormUntil!: Date;
3033
@Column()
3134
public hoursToConfirm!: number;
32-
@Column({ default: false })
33-
public allowRatingProjects!: boolean;
35+
@Column({ default: () => "CURRENT_TIMESTAMP" })
36+
public acceptanceDeadline!: Date;
37+
@Column({ default: () => "CURRENT_TIMESTAMP" })
38+
public confirmSpotUntil!: Date;
3439
}

backend/src/entities/settings.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ export class EmailSettings {
4848
public forgotPasswordEmail!: EmailTemplate;
4949
}
5050

51+
export class ProjectSettings {
52+
@Column({ default: false })
53+
public allowRatingProjects!: boolean;
54+
}
55+
5156
@Entity()
5257
export class Settings {
5358
@PrimaryGeneratedColumn()
@@ -64,6 +69,9 @@ export class Settings {
6469
@Type(() => EmailSettings)
6570
@Column(() => EmailSettings)
6671
public email!: EmailSettings;
72+
@Type(() => ProjectSettings)
73+
@Column(() => ProjectSettings)
74+
public project!: ProjectSettings;
6775
}
6876

6977
/**

backend/src/services/project-service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ export class ProjectService implements IProjectService {
7272
.map((team) => team.id);
7373

7474
const [settings] = await this._settings.find();
75-
const allowRatingProjects = settings.application.allowRatingProjects;
75+
const allowRatingProjects = settings.project.allowRatingProjects;
7676
const isAdmin = user.role === UserRole.Root;
7777

7878
const projects = await this._projects.find();

backend/src/services/rating-service.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -236,10 +236,8 @@ export class RatingService implements IRatingService {
236236
}
237237

238238
const settings = await this._settings.getSettings();
239-
if (!settings.application.allowRatingProjects) {
240-
throw new ForbiddenError(
241-
"Rating is not allowed due to application settings",
242-
);
239+
if (!settings.project.allowRatingProjects) {
240+
throw new ForbiddenError("Rating is not allowed due to settings");
243241
}
244242

245243
const project = await this._projects.findOneBy({ id: rating.project.id });

backend/src/services/settings-service.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
EmailTemplate,
1010
FrontendSettings,
1111
Settings,
12+
ProjectSettings,
1213
} from "../entities/settings";
1314
import {
1415
ConfigurationServiceToken,
@@ -102,6 +103,7 @@ export class SettingsService implements ISettingsService {
102103
settings.application = this.getDefaultApplicationSettings();
103104
settings.frontend = this.getDefaultFrontendSettings();
104105
settings.email = this.getDefaultEmailSettings();
106+
settings.project = this.getDefaultProjectSettings();
105107
return settings;
106108
}
107109

@@ -115,10 +117,20 @@ export class SettingsService implements ISettingsService {
115117
applicationSettings.allowProfileFormFrom = new Date();
116118
applicationSettings.allowProfileFormUntil = new Date();
117119
applicationSettings.hoursToConfirm = 24;
118-
applicationSettings.allowRatingProjects = false;
120+
applicationSettings.acceptanceDeadline = new Date();
121+
applicationSettings.confirmSpotUntil = new Date();
119122
return applicationSettings;
120123
}
121124

125+
/**
126+
* Creates a project settings object with default values.
127+
*/
128+
private getDefaultProjectSettings(): ProjectSettings {
129+
const projectSettings = new ProjectSettings();
130+
projectSettings.allowRatingProjects = false;
131+
return projectSettings;
132+
}
133+
122134
/**
123135
* Creates a form settings object with default values.
124136
*/

backend/test/services/mock/mock-settings-service.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,11 @@ export const defaultSettings = {
2525
},
2626
allowProfileFormFrom: new Date(),
2727
allowProfileFormUntil: new Date(),
28+
acceptanceDeadline: new Date(),
29+
confirmSpotUntil: new Date(),
2830
hoursToConfirm: 24,
31+
},
32+
project: {
2933
allowRatingProjects: false,
3034
},
3135
frontend: {

backend/test/services/project-service-get-all-projects.spec.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ describe(ProjectService.name, () => {
5656
await settingsRepo.save([
5757
{
5858
...defaultSettings,
59-
application: {
60-
...defaultSettings.application,
59+
project: {
60+
...defaultSettings.project,
6161
allowRatingProjects: false,
6262
},
6363
},
@@ -71,7 +71,7 @@ describe(ProjectService.name, () => {
7171
const allowRatingProjects = async (value: boolean): Promise<void> => {
7272
const settingsRepo = database.getRepository(Settings);
7373
const settings = {
74-
application: {
74+
project: {
7575
allowRatingProjects: value,
7676
},
7777
};

backend/test/services/rating-service.spec.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ describe("RatingService", () => {
121121
expect.assertions(1);
122122

123123
settingsService.mocks.getSettings.mockResolvedValue({
124-
application: { allowRatingProjects: false },
124+
project: { allowRatingProjects: false },
125125
} as any);
126126

127127
const rating = Object.assign(new Rating(), {
@@ -140,7 +140,7 @@ describe("RatingService", () => {
140140
expect.assertions(1);
141141

142142
settingsService.mocks.getSettings.mockResolvedValue({
143-
application: { allowRatingProjects: true },
143+
project: { allowRatingProjects: true },
144144
} as any);
145145

146146
const rating = Object.assign(new Rating(), {
@@ -159,7 +159,7 @@ describe("RatingService", () => {
159159
expect.assertions(1);
160160

161161
settingsService.mocks.getSettings.mockResolvedValue({
162-
application: { allowRatingProjects: true },
162+
project: { allowRatingProjects: true },
163163
} as any);
164164

165165
await projectRepo.update(mockProject.id, { allowRating: false });
@@ -181,7 +181,7 @@ describe("RatingService", () => {
181181
expect.assertions(1);
182182

183183
settingsService.mocks.getSettings.mockResolvedValue({
184-
application: { allowRatingProjects: true },
184+
project: { allowRatingProjects: true },
185185
} as any);
186186

187187
const rating = Object.assign(new Rating(), {
@@ -200,7 +200,7 @@ describe("RatingService", () => {
200200
expect.assertions(2);
201201

202202
settingsService.mocks.getSettings.mockResolvedValue({
203-
application: { allowRatingProjects: true },
203+
project: { allowRatingProjects: true },
204204
} as any);
205205

206206
const rating = Object.assign(new Rating(), {
@@ -220,7 +220,7 @@ describe("RatingService", () => {
220220
expect.assertions(1);
221221

222222
settingsService.mocks.getSettings.mockResolvedValue({
223-
application: { allowRatingProjects: true },
223+
project: { allowRatingProjects: true },
224224
} as any);
225225

226226
const rating = Object.assign(new Rating(), {

frontend/src/api/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,12 @@ export class ApiClient {
182182
allowProfileFormUntil: this.reviveDate(
183183
settings.application.allowProfileFormUntil,
184184
),
185+
acceptanceDeadline: this.reviveDate(
186+
settings.application.acceptanceDeadline,
187+
),
188+
confirmSpotUntil: this.reviveDate(
189+
settings.application.confirmSpotUntil,
190+
),
185191
},
186192
};
187193
}

0 commit comments

Comments
 (0)