template storing

This commit is contained in:
Julian Krauser 2024-12-22 10:29:42 +01:00
parent 98477eafde
commit 160d82459d
12 changed files with 386 additions and 1 deletions

View file

@ -0,0 +1,18 @@
export interface CreateTemplateCommand {
template: string;
description: string | null;
}
export interface UpdateTemplateCommand {
id: number;
template: string;
description: string | null;
design: object;
headerHTML: string;
bodyHTML: string;
footerHTML: string;
}
export interface DeleteTemplateCommand {
id: number;
}

View file

@ -0,0 +1,72 @@
import { dataSource } from "../data-source";
import { template } from "../entity/template";
import InternalException from "../exceptions/internalException";
import { CreateTemplateCommand, DeleteTemplateCommand, UpdateTemplateCommand } from "./templateCommand";
export default abstract class TemplateCommandHandler {
/**
* @description create template
* @param CreateTemplateCommand
* @returns {Promise<number>}
*/
static async create(createTemplate: CreateTemplateCommand): Promise<number> {
return await dataSource
.createQueryBuilder()
.insert()
.into(template)
.values({
template: createTemplate.template,
description: createTemplate.description,
})
.execute()
.then((result) => {
return result.identifiers[0].id;
})
.catch((err) => {
throw new InternalException("Failed creating template", err);
});
}
/**
* @description update template
* @param UpdateTemplateCommand
* @returns {Promise<void>}
*/
static async update(updateTemplate: UpdateTemplateCommand): Promise<void> {
return await dataSource
.createQueryBuilder()
.update(template)
.set({
template: updateTemplate.template,
description: updateTemplate.description,
design: updateTemplate.design,
headerHTML: updateTemplate.headerHTML,
bodyHTML: updateTemplate.bodyHTML,
footerHTML: updateTemplate.footerHTML,
})
.where("id = :id", { id: updateTemplate.id })
.execute()
.then(() => {})
.catch((err) => {
throw new InternalException("Failed updating template", err);
});
}
/**
* @description delete template
* @param DeleteTemplateCommand
* @returns {Promise<void>}
*/
static async delete(deletTemplate: DeleteTemplateCommand): Promise<void> {
return await dataSource
.createQueryBuilder()
.delete()
.from(template)
.where("id = :id", { id: deletTemplate.id })
.execute()
.then(() => {})
.catch((err) => {
throw new InternalException("Failed deleting template", err);
});
}
}

View file

@ -0,0 +1,95 @@
import { Request, Response } from "express";
import TemplateService from "../../service/templateService";
import TemplateFactory from "../../factory/admin/template";
import { CreateTemplateCommand, DeleteTemplateCommand, UpdateTemplateCommand } from "../../command/templateCommand";
import TemplateCommandHandler from "../../command/templateCommandHandler";
/**
* @description get all templates
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function getAllTemplates(req: Request, res: Response): Promise<any> {
let templates = await TemplateService.getAll();
res.json(TemplateFactory.mapToBase(templates));
}
/**
* @description get template by id
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function getTemplateById(req: Request, res: Response): Promise<any> {
const id = parseInt(req.params.id);
let template = await TemplateService.getById(id);
res.json(TemplateFactory.mapToSingle(template));
}
/**
* @description create new template
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function createTemplate(req: Request, res: Response): Promise<any> {
const template = req.body.template;
const description = req.body.description;
let createTemplate: CreateTemplateCommand = {
template: template,
description: description,
};
let id = await TemplateCommandHandler.create(createTemplate);
res.status(200).send(id);
}
/**
* @description update template
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function updateTemplate(req: Request, res: Response): Promise<any> {
const id = parseInt(req.params.id);
const template = req.body.template;
const description = req.body.description;
const design = req.body.design;
const headerHTML = req.body.headerHTML;
const bodyHTML = req.body.bodyHTML;
const footerHTML = req.body.footerHTML;
let updateTemplate: UpdateTemplateCommand = {
id: id,
template: template,
description: description,
design: design,
headerHTML: headerHTML,
bodyHTML: bodyHTML,
footerHTML: footerHTML,
};
await TemplateCommandHandler.update(updateTemplate);
res.sendStatus(204);
}
/**
* @description delete template
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function deleteTemplate(req: Request, res: Response): Promise<any> {
const id = parseInt(req.params.id);
let deleteTemplate: DeleteTemplateCommand = {
id: id,
};
await TemplateCommandHandler.delete(deleteTemplate);
res.sendStatus(204);
}

View file

@ -51,6 +51,8 @@ import { memberExecutivePositionsView } from "./views/memberExecutivePositionVie
import { memberQualificationsView } from "./views/memberQualificationsView";
import { membershipView } from "./views/membershipsView";
import { MemberDataViews1734520998539 } from "./migrations/1734520998539-memberDataViews";
import { template } from "./entity/template";
import { Template1734854680201 } from "./migrations/1734854680201-template";
const dataSource = new DataSource({
type: DB_TYPE as any,
@ -90,6 +92,7 @@ const dataSource = new DataSource({
calendar,
calendarType,
query,
template,
memberView,
memberExecutivePositionsView,
memberQualificationsView,
@ -112,6 +115,7 @@ const dataSource = new DataSource({
SecuringCalendarType1733249553766,
QueryStore1734187754677,
MemberDataViews1734520998539,
Template1734854680201,
],
migrationsRun: true,
migrationsTransactionMode: "each",

36
src/entity/template.ts Normal file
View file

@ -0,0 +1,36 @@
import { Column, Entity, PrimaryColumn } from "typeorm";
@Entity()
export class template {
@PrimaryColumn({ generated: "increment", type: "int" })
id: number;
@Column({ type: "varchar", length: 255 })
template: string;
@Column({ type: "varchar", length: 255, nullable: true })
description?: string;
@Column({
type: "text",
default: "{}",
transformer: {
to(value: object) {
return JSON.stringify(value);
},
from(value: string) {
return JSON.parse(value);
},
},
})
design: object;
@Column({ type: "text", default: "" })
headerHTML: string;
@Column({ type: "text", default: "" })
bodyHTML: string;
@Column({ type: "text", default: "" })
footerHTML: string;
}

View file

@ -0,0 +1,30 @@
import { template } from "../../entity/template";
import { TemplateViewModel } from "../../viewmodel/admin/template.models";
export default abstract class TemplateFactory {
/**
* @description map record to template
* @param {template} record
* @returns {TemplateViewModel}
*/
public static mapToSingle(record: template): TemplateViewModel {
return {
id: record.id,
template: record.template,
description: record.description,
design: record.design,
headerHTML: record.headerHTML,
bodyHTML: record.bodyHTML,
footerHTML: record.footerHTML,
};
}
/**
* @description map records to template
* @param {Array<template>} records
* @returns {Array<TemplateViewModel>}
*/
public static mapToBase(records: Array<template>): Array<TemplateViewModel> {
return records.map((r) => this.mapToSingle(r));
}
}

View file

@ -0,0 +1,30 @@
import { MigrationInterface, QueryRunner, Table } from "typeorm";
import { DB_TYPE } from "../env.defaults";
export class Template1734854680201 implements MigrationInterface {
name = "Template1734854680201";
public async up(queryRunner: QueryRunner): Promise<void> {
const variableType_int = DB_TYPE == "mysql" ? "int" : "integer";
await queryRunner.createTable(
new Table({
name: "template",
columns: [
{ name: "id", type: variableType_int, isPrimary: true, isGenerated: true, generationStrategy: "increment" },
{ name: "template", type: "varchar", length: "255", isNullable: false },
{ name: "description", type: "varchar", length: "255", isNullable: true },
{ name: "design", type: "text", isNullable: false, default: "'{}'" },
{ name: "headerHTML", type: "text", isNullable: false, default: "''" },
{ name: "bodyHTML", type: "text", isNullable: false, default: "''" },
{ name: "footerHTML", type: "text", isNullable: false, default: "''" },
],
}),
true
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.dropTable("template");
}
}

View file

@ -8,6 +8,7 @@ import membershipStatus from "./membershipStatus";
import qualification from "./qualification";
import calendarType from "./calendarType";
import queryStore from "./queryStore";
import template from "./template";
import member from "./member";
import protocol from "./protocol";
@ -39,6 +40,7 @@ router.use(
router.use("/qualification", PermissionHelper.passCheckMiddleware("read", "settings", "qualification"), qualification);
router.use("/calendartype", PermissionHelper.passCheckMiddleware("read", "settings", "calendar_type"), calendarType);
router.use("/querystore", PermissionHelper.passCheckMiddleware("read", "settings", "query_store"), queryStore);
router.use("/template", PermissionHelper.passCheckMiddleware("read", "settings", "template"), template);
router.use("/member", PermissionHelper.passCheckMiddleware("read", "club", "member"), member);
router.use("/protocol", PermissionHelper.passCheckMiddleware("read", "club", "protocol"), protocol);

View file

@ -0,0 +1,45 @@
import express, { Request, Response } from "express";
import {
createTemplate,
deleteTemplate,
getAllTemplates,
getTemplateById,
updateTemplate,
} from "../../controller/admin/templateController";
import PermissionHelper from "../../helpers/permissionHelper";
var router = express.Router({ mergeParams: true });
router.get("/", async (req: Request, res: Response) => {
await getAllTemplates(req, res);
});
router.get("/:id", async (req: Request, res: Response) => {
await getTemplateById(req, res);
});
router.post(
"/",
PermissionHelper.passCheckMiddleware("create", "settings", "template"),
async (req: Request, res: Response) => {
await createTemplate(req, res);
}
);
router.patch(
"/:id",
PermissionHelper.passCheckMiddleware("update", "settings", "template"),
async (req: Request, res: Response) => {
await updateTemplate(req, res);
}
);
router.delete(
"/:id",
PermissionHelper.passCheckMiddleware("delete", "settings", "template"),
async (req: Request, res: Response) => {
await deleteTemplate(req, res);
}
);
export default router;

View file

@ -0,0 +1,41 @@
import { dataSource } from "../data-source";
import { template } from "../entity/template";
import { member } from "../entity/member";
import InternalException from "../exceptions/internalException";
export default abstract class TemplateService {
/**
* @description get all templates
* @returns {Promise<Array<template>>}
*/
static async getAll(): Promise<Array<template>> {
return await dataSource
.getRepository(template)
.createQueryBuilder("template")
.getMany()
.then((res) => {
return res;
})
.catch((err) => {
throw new InternalException("templates not found", err);
});
}
/**
* @description get template by id
* @returns {Promise<template>}
*/
static async getById(id: number): Promise<template> {
return await dataSource
.getRepository(template)
.createQueryBuilder("template")
.where("template.id = :id", { id: id })
.getOneOrFail()
.then((res) => {
return res;
})
.catch((err) => {
throw new InternalException("template not found by id", err);
});
}
}

View file

@ -14,7 +14,8 @@ export type PermissionModule =
| "user"
| "role"
| "query"
| "query_store";
| "query_store"
| "template";
export type PermissionType = "read" | "create" | "update" | "delete";
@ -53,6 +54,7 @@ export const permissionModules: Array<PermissionModule> = [
"role",
"query",
"query_store",
"template",
];
export const permissionTypes: Array<PermissionType> = ["read", "create", "update", "delete"];
export const sectionsAndModules: SectionsAndModulesObject = {
@ -65,6 +67,7 @@ export const sectionsAndModules: SectionsAndModulesObject = {
"membership_status",
"calendar_type",
"query_store",
"template",
],
user: ["user", "role"],
};

View file

@ -0,0 +1,9 @@
export interface TemplateViewModel {
id: number;
template: string;
description: string | null;
design: object;
headerHTML: string;
bodyHTML: string;
footerHTML: string;
}