WIP: Overrides
This commit is contained in:
parent
d26b4025ad
commit
c1b59f77d2
19 changed files with 628 additions and 90 deletions
|
@ -20,6 +20,10 @@ import UserService from "../services/UserService";
|
|||
import Controller from "./Controller";
|
||||
import UserBadgeListItem from "../entities/list/UserBadgeListItem";
|
||||
import AdminRemoveUserBadgeModel from "../models/admin/AdminRemoveUserBadgeModel";
|
||||
import OverrideService from "../services/OverrideService";
|
||||
import AdminOverridesViewModel from "../models/admin/AdminOverridesViewModel";
|
||||
import AdminOverrideViewModel from "../models/admin/AdminOverrideViewModel";
|
||||
import OverrideType from "../enums/OverrideType";
|
||||
|
||||
export default class AdminController_Auth$Admin extends Controller {
|
||||
public async Index_Get() {
|
||||
|
@ -215,4 +219,39 @@ export default class AdminController_Auth$Admin extends Controller {
|
|||
|
||||
return this.redirectToAction("userbadges");
|
||||
}
|
||||
|
||||
public async Overrides_Get() {
|
||||
const adminOverridesViewModel: AdminOverridesViewModel = {
|
||||
overrides: await OverrideService.GetOverrides()
|
||||
}
|
||||
|
||||
return this.view(adminOverridesViewModel);
|
||||
}
|
||||
|
||||
public async Override_Get(adminOverrideViewModel: AdminOverrideViewModel) {
|
||||
const override = adminOverrideViewModel.id ? await OverrideService.GetOverride(parseInt(adminOverrideViewModel.id)) : null;
|
||||
if (typeof(adminOverrideViewModel.id) !== "undefined" && override) {
|
||||
adminOverrideViewModel.overrideTypeId = override.OverrideType.toString();
|
||||
adminOverrideViewModel.name = override.Name;
|
||||
adminOverrideViewModel.forUrl = override.ForURL;
|
||||
adminOverrideViewModel.cssQuery = override.CSSQuery;
|
||||
} else {
|
||||
adminOverrideViewModel.overrideTypeId = OverrideType.Unknown.toString();
|
||||
adminOverrideViewModel.name = "";
|
||||
adminOverrideViewModel.forUrl = "";
|
||||
adminOverrideViewModel.cssQuery = "";
|
||||
}
|
||||
|
||||
return this.view(adminOverrideViewModel);
|
||||
}
|
||||
|
||||
public async Override_Post(adminOverrideViewModel: AdminOverrideViewModel) {
|
||||
if (typeof(adminOverrideViewModel.id) === "undefined") {
|
||||
return this.badRequest();
|
||||
}
|
||||
|
||||
await OverrideService.SaveOverride(this.session.userId, parseInt(adminOverrideViewModel.id), parseInt(adminOverrideViewModel.overrideTypeId), adminOverrideViewModel.name, adminOverrideViewModel.forUrl, adminOverrideViewModel.cssQuery);
|
||||
|
||||
return this.redirectToAction("badges");
|
||||
}
|
||||
}
|
|
@ -63,4 +63,8 @@ export default class ApiController extends Controller {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
public async GetOverrides_Get_AllowAnonymous() {
|
||||
return this.ok("test");
|
||||
}
|
||||
}
|
16
server/entities/Override.ts
Normal file
16
server/entities/Override.ts
Normal file
|
@ -0,0 +1,16 @@
|
|||
import OverrideType from "../enums/OverrideType";
|
||||
|
||||
export default class Override {
|
||||
public Id: number = Number.MIN_VALUE;
|
||||
public OverrideType: OverrideType = OverrideType.Unknown;
|
||||
public Name: string = "";
|
||||
public ForURL: string = "";
|
||||
public CSSQuery: string = "";
|
||||
public CreatedByUserId: number = Number.MIN_VALUE;
|
||||
public CreatedDatetime: Date = new Date();
|
||||
public LastModifiedByUserId?: number;
|
||||
public LastModifiedDatetime?: Date;
|
||||
public DeletedByUserId?: number;
|
||||
public DeletedDatetime?: Date;
|
||||
public IsDeleted: boolean = false;
|
||||
}
|
15
server/entities/OverrideField.ts
Normal file
15
server/entities/OverrideField.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
import OverrideType from "../enums/OverrideType";
|
||||
|
||||
export default class OverrideField {
|
||||
public Id: number = Number.MIN_VALUE;
|
||||
public OverrideId: number = Number.MIN_VALUE;
|
||||
public FieldName: string = "";
|
||||
public FieldValue: string = "";
|
||||
public CreatedByUserId: number = Number.MIN_VALUE;
|
||||
public CreatedDatetime: Date = new Date();
|
||||
public LastModifiedByUserId?: number;
|
||||
public LastModifiedDatetime?: Date;
|
||||
public DeletedByUserId?: number;
|
||||
public DeletedDatetime?: Date;
|
||||
public IsDeleted: boolean = false;
|
||||
}
|
31
server/enums/OverrideType.ts
Normal file
31
server/enums/OverrideType.ts
Normal file
|
@ -0,0 +1,31 @@
|
|||
enum OverrideType {
|
||||
Unknown = 0,
|
||||
AddHtml = 10,
|
||||
AddLink = 20,
|
||||
ReplaceText = 30,
|
||||
ReplaceImage = 40,
|
||||
AddStyles = 50,
|
||||
ReplaceStyles = 60
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
OverrideType.ToDescription = (overrideType: OverrideType) => {
|
||||
switch (overrideType) {
|
||||
case OverrideType.Unknown:
|
||||
return "Please Select...";
|
||||
case OverrideType.AddHtml:
|
||||
return "Add HTML";
|
||||
case OverrideType.AddLink:
|
||||
return "Add Link";
|
||||
case OverrideType.ReplaceText:
|
||||
return "Replace Text";
|
||||
case OverrideType.ReplaceImage:
|
||||
return "Replace Image";
|
||||
case OverrideType.AddStyles:
|
||||
return "Add Styles";
|
||||
case OverrideType.ReplaceStyles:
|
||||
return "Replace Styles";
|
||||
}
|
||||
};
|
||||
|
||||
export default OverrideType;
|
9
server/models/admin/AdminOverrideViewModel.ts
Normal file
9
server/models/admin/AdminOverrideViewModel.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
import OverrideType from "../../enums/OverrideType";
|
||||
|
||||
export default interface AdminOverrideViewModel {
|
||||
id?: string;
|
||||
overrideTypeId: string;
|
||||
name: string;
|
||||
forUrl: string;
|
||||
cssQuery: string;
|
||||
}
|
5
server/models/admin/AdminOverridesViewModel.ts
Normal file
5
server/models/admin/AdminOverridesViewModel.ts
Normal file
|
@ -0,0 +1,5 @@
|
|||
import Override from "../../entities/Override";
|
||||
|
||||
export default interface AdminOverridesViewModel {
|
||||
overrides: Override[]
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
import { Console } from "hsconsole";
|
||||
import { createPool, Pool, RowDataPacket } from "mysql2";
|
||||
|
||||
export type DBInDataType = string | number | null | undefined;
|
||||
export type DBInDataType = string | number | Date | null | undefined;
|
||||
|
||||
export default class Database {
|
||||
private connectionPool:Pool;
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import { FastifyReply, FastifyRequest } from "fastify";
|
||||
import SessionUser from "./SessionUser";
|
||||
import { UserLevel } from "../enums/UserLevel";
|
||||
import SelectUtility from "../utilities/SelectUtility";
|
||||
import OverrideType from "../enums/OverrideType";
|
||||
|
||||
export default class RequestCtx {
|
||||
public controllerName:string;
|
||||
|
@ -30,8 +32,14 @@ export default class RequestCtx {
|
|||
}
|
||||
// @ts-ignore inject session
|
||||
viewModel["session"] = this.session;
|
||||
|
||||
// @ts-ignore inject enums
|
||||
viewModel["UserLevel"] = UserLevel;
|
||||
// @ts-ignore
|
||||
viewModel["OverrideType"] = OverrideType;
|
||||
|
||||
// @ts-ignore inject methods
|
||||
viewModel["SelectUtility"] = SelectUtility;
|
||||
return this.res.view(`views/${this.controllerName}/${viewName}.ejs`, viewModel);
|
||||
}
|
||||
|
||||
|
|
221
server/package-lock.json
generated
221
server/package-lock.json
generated
|
@ -9,29 +9,29 @@
|
|||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@fastify/cookie": "^11.0.1",
|
||||
"@fastify/formbody": "^8.0.1",
|
||||
"@fastify/static": "^8.0.3",
|
||||
"@fastify/view": "^10.0.1",
|
||||
"@fastify/cookie": "^11.0.2",
|
||||
"@fastify/formbody": "^8.0.2",
|
||||
"@fastify/static": "^8.1.1",
|
||||
"@fastify/view": "^11.0.0",
|
||||
"bufferstuff": "^1.8.0",
|
||||
"ejs": "^3.1.10",
|
||||
"fastify": "^5.2.0",
|
||||
"hsconsole": "^1.0.2",
|
||||
"mysql2": "^3.11.5",
|
||||
"fastify": "^5.3.2",
|
||||
"hsconsole": "^1.1.0",
|
||||
"mysql2": "^3.14.0",
|
||||
"simple-prom": "^1.0.1",
|
||||
"ultimate-ws": "^1.0.13"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/ejs": "^3.1.5",
|
||||
"@types/node": "^22.10.2",
|
||||
"@types/node": "^22.14.0",
|
||||
"@vercel/ncc": "^0.38.3",
|
||||
"check-outdated": "^2.12.0",
|
||||
"check-outdated": "^2.13.0",
|
||||
"node": "^22.12.0",
|
||||
"nodemon": "^3.1.9",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"terser": "^5.37.0",
|
||||
"terser": "^5.39.0",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.7.2"
|
||||
"typescript": "^5.8.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@cspotcode/source-map-support": {
|
||||
|
@ -64,9 +64,19 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@fastify/cookie": {
|
||||
"version": "11.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@fastify/cookie/-/cookie-11.0.1.tgz",
|
||||
"integrity": "sha512-n1Ooz4bgQ5LcOlJQboWPfsMNxIrGV0SgU85UkctdpTlCQE0mtA3rlspOPUdqk9ubiiZn053ucnia4DjTquI4/g==",
|
||||
"version": "11.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@fastify/cookie/-/cookie-11.0.2.tgz",
|
||||
"integrity": "sha512-GWdwdGlgJxyvNv+QcKiGNevSspMQXncjMZ1J8IvuDQk0jvkzgWWZFNC2En3s+nHndZBGV8IbLwOI/sxCZw/mzA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/fastify"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/fastify"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cookie": "^1.0.0",
|
||||
|
@ -98,15 +108,31 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@fastify/formbody": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@fastify/formbody/-/formbody-8.0.1.tgz",
|
||||
"integrity": "sha512-LPrcadSIK8TrQk510Zdj56fnw7cyHq0/PW0YHGGM8ycGL4X7XAex+FKcwpzB4i5lF9eykc71a4EtcO9AEoByqw==",
|
||||
"version": "8.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@fastify/formbody/-/formbody-8.0.2.tgz",
|
||||
"integrity": "sha512-84v5J2KrkXzjgBpYnaNRPqwgMsmY7ZDjuj0YVuMR3NXCJRCgKEZy/taSP1wUYGn0onfxJpLyRGDLa+NMaDJtnA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/fastify"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/fastify"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fast-querystring": "^1.1.2",
|
||||
"fastify-plugin": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@fastify/forwarded": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@fastify/forwarded/-/forwarded-3.0.0.tgz",
|
||||
"integrity": "sha512-kJExsp4JCms7ipzg7SJ3y8DwmePaELHxKYtg+tZow+k0znUTf3cb+npgyqm8+ATZOdmfgfydIebPDWM172wfyA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@fastify/merge-json-schemas": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@fastify/merge-json-schemas/-/merge-json-schemas-0.1.1.tgz",
|
||||
|
@ -116,6 +142,16 @@
|
|||
"fast-deep-equal": "^3.1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@fastify/proxy-addr": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@fastify/proxy-addr/-/proxy-addr-5.0.0.tgz",
|
||||
"integrity": "sha512-37qVVA1qZ5sgH7KpHkkC4z9SK6StIsIcOmpjvMPXNb3vx2GQxhZocogVYbr2PbbeLCQxYIPDok307xEvRZOzGA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@fastify/forwarded": "^3.0.0",
|
||||
"ipaddr.js": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@fastify/send": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@fastify/send/-/send-3.3.0.tgz",
|
||||
|
@ -130,9 +166,19 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@fastify/static": {
|
||||
"version": "8.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@fastify/static/-/static-8.0.3.tgz",
|
||||
"integrity": "sha512-GHSoOVDIxEYEeVR5l044bRCuAKDErD/+9VE+Z9fnaTRr+DDz0Avrm4kKai1mHbPx6C0U7BVNthjd/gcMquZZUA==",
|
||||
"version": "8.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@fastify/static/-/static-8.1.1.tgz",
|
||||
"integrity": "sha512-TW9eyVHJLytZNpBlSIqd0bl1giJkEaRaPZG+5AT3L/OBKq9U8D7g/OYmc2NPQZnzPURGhMt3IAWuyVkvd2nOkQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/fastify"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/fastify"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@fastify/accept-negotiator": "^2.0.0",
|
||||
|
@ -144,9 +190,19 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@fastify/view": {
|
||||
"version": "10.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@fastify/view/-/view-10.0.1.tgz",
|
||||
"integrity": "sha512-rXtBN0oVDmoRZAS7lelrCIahf+qFtlMOOas8VPdA7JvrJ9ChcF7e36pIUPU0Vbs3KmHxESUb7XatavUZEe/k5Q==",
|
||||
"version": "11.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@fastify/view/-/view-11.0.0.tgz",
|
||||
"integrity": "sha512-uMNwZoY88uUMP6hidJYHT0/7bXzLrWgo/X5kjKdKPi3bj69kSkuNKmcG5KEU2sDF91n+IiLAnqx3dkldFfz5hQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/fastify"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/fastify"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fastify-plugin": "^5.0.0",
|
||||
|
@ -288,13 +344,13 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "22.10.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz",
|
||||
"integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==",
|
||||
"version": "22.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.14.1.tgz",
|
||||
"integrity": "sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~6.20.0"
|
||||
"undici-types": "~6.21.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@vercel/ncc": {
|
||||
|
@ -642,10 +698,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/check-outdated": {
|
||||
"version": "2.12.0",
|
||||
"resolved": "https://registry.npmjs.org/check-outdated/-/check-outdated-2.12.0.tgz",
|
||||
"integrity": "sha512-kWThJFiqxAE09XSNJLLD4hWNvLhWdxFLKxOHhxB+XhGlZGyeELXP8V6R/dRrZ5vbjmp9VmoTYe0vp6egftKz7Q==",
|
||||
"version": "2.13.0",
|
||||
"resolved": "https://registry.npmjs.org/check-outdated/-/check-outdated-2.13.0.tgz",
|
||||
"integrity": "sha512-TXmXp/IcnV2WnF8B+LBuFLXy5zNAlv46tdN3O/2ag3Hn+CZrUzIGI/hN0EdXMq9liiD8aWJDI5/ZBqYrqgxbSw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"check-outdated": "check-outdated.js"
|
||||
},
|
||||
|
@ -1136,9 +1193,9 @@
|
|||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fastify": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/fastify/-/fastify-5.2.0.tgz",
|
||||
"integrity": "sha512-3s+Qt5S14Eq5dCpnE0FxTp3z4xKChI83ZnMv+k0FwX+VUoZrgCFoLAxpfdi/vT4y6Mk+g7aAMt9pgXDoZmkefQ==",
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fastify/-/fastify-5.3.2.tgz",
|
||||
"integrity": "sha512-AIPqBgtqBAwkOkrnwesEE+dOyU30dQ4kh7udxeGVR05CRGwubZx+p2H8P0C4cRnQT0+EPK4VGea2DTL2RtWttg==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
|
@ -1154,16 +1211,16 @@
|
|||
"@fastify/ajv-compiler": "^4.0.0",
|
||||
"@fastify/error": "^4.0.0",
|
||||
"@fastify/fast-json-stringify-compiler": "^5.0.0",
|
||||
"@fastify/proxy-addr": "^5.0.0",
|
||||
"abstract-logging": "^2.0.1",
|
||||
"avvio": "^9.0.0",
|
||||
"fast-json-stringify": "^6.0.0",
|
||||
"find-my-way": "^9.0.0",
|
||||
"light-my-request": "^6.0.0",
|
||||
"pino": "^9.0.0",
|
||||
"process-warning": "^4.0.0",
|
||||
"proxy-addr": "^2.0.7",
|
||||
"process-warning": "^5.0.0",
|
||||
"rfdc": "^1.3.1",
|
||||
"secure-json-parse": "^3.0.1",
|
||||
"secure-json-parse": "^4.0.0",
|
||||
"semver": "^7.6.0",
|
||||
"toad-cache": "^3.7.0"
|
||||
}
|
||||
|
@ -1174,6 +1231,22 @@
|
|||
"integrity": "sha512-0725fmH/yYi8ugsjszLci+lLnGBK6cG+WSxM7edY2OXJEU7gr2JiGBoieL2h9mhTych1vFsEfXsAsGGDJ/Rd5w==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fastify/node_modules/process-warning": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/process-warning/-/process-warning-5.0.0.tgz",
|
||||
"integrity": "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/fastify"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/fastify"
|
||||
}
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fastq": {
|
||||
"version": "1.17.1",
|
||||
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
|
||||
|
@ -1321,14 +1394,6 @@
|
|||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/forwarded": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
|
||||
"integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||
|
@ -1609,9 +1674,10 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/hsconsole": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/hsconsole/-/hsconsole-1.0.2.tgz",
|
||||
"integrity": "sha512-st+jaSpNw3uoIhE5vl2lVN8Op8yQF2FyLRdBG68s8vqjduJdKUGtoEXd8Zxe6du1zzpFHHRcU3zJbAq8BOmYQA==",
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/hsconsole/-/hsconsole-1.1.0.tgz",
|
||||
"integrity": "sha512-nQtnapTLf/d090AloKJkVbf15yXNaISYYHC21cwOLClF7hlJs2rlHF3JLaltspK/O2uhz6WcRMsE+2Yn6D8UEw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"dyetty": "^1.0.1"
|
||||
}
|
||||
|
@ -1690,11 +1756,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/ipaddr.js": {
|
||||
"version": "1.9.1",
|
||||
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
|
||||
"integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz",
|
||||
"integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.10"
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/is-array-buffer": {
|
||||
|
@ -2212,9 +2279,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/mysql2": {
|
||||
"version": "3.11.5",
|
||||
"resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.11.5.tgz",
|
||||
"integrity": "sha512-0XFu8rUmFN9vC0ME36iBvCUObftiMHItrYFhlCRvFWbLgpNqtC4Br/NmZX1HNCszxT0GGy5QtP+k3Q3eCJPaYA==",
|
||||
"version": "3.14.0",
|
||||
"resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.14.0.tgz",
|
||||
"integrity": "sha512-8eMhmG6gt/hRkU1G+8KlGOdQi2w+CgtNoD1ksXZq9gQfkfDsX4LHaBwTe1SY0Imx//t2iZA03DFnyYKPinxSRw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"aws-ssl-profiles": "^1.1.1",
|
||||
|
@ -2590,18 +2657,6 @@
|
|||
"integrity": "sha512-/MyYDxttz7DfGMMHiysAsFE4qF+pQYAA8ziO/3NcRVrQ5fSk+Mns4QZA/oRPFzvcqNoVJXQNWNAsdwBXLUkQKw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/proxy-addr": {
|
||||
"version": "2.0.7",
|
||||
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
|
||||
"integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
|
||||
"dependencies": {
|
||||
"forwarded": "0.2.0",
|
||||
"ipaddr.js": "1.9.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/pstree.remy": {
|
||||
"version": "1.1.8",
|
||||
"resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz",
|
||||
|
@ -2813,9 +2868,19 @@
|
|||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||
},
|
||||
"node_modules/secure-json-parse": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-3.0.1.tgz",
|
||||
"integrity": "sha512-9QR7G96th4QJ2+dJwvZB+JoXyt8PN+DbEjOr6kL2/JU4KH8Eb2sFdU+gt8EDdzWDWoWH0uocDdfCoFzdVSixUA==",
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-4.0.0.tgz",
|
||||
"integrity": "sha512-dxtLJO6sc35jWidmLxo7ij+Eg48PM/kleBsxpC8QJE0qJICe+KawkDQmvCMZUr9u7WKVHgMW6vy3fQ7zMiFZMA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/fastify"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/fastify"
|
||||
}
|
||||
],
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/semver": {
|
||||
|
@ -3254,9 +3319,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/terser": {
|
||||
"version": "5.37.0",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.37.0.tgz",
|
||||
"integrity": "sha512-B8wRRkmre4ERucLM/uXx4MOV5cbnOlVAqUst+1+iLKPI0dOgFO28f84ptoQt9HEI537PMzfYa/d+GEPKTRXmYA==",
|
||||
"version": "5.39.0",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.39.0.tgz",
|
||||
"integrity": "sha512-LBAhFyLho16harJoWMg/nZsQYgTrg5jXOn2nCYjRUcZZEdE3qa2zb8QEDRUGVZBW4rlazf2fxkg8tztybTaqWw==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
|
@ -3446,9 +3511,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.7.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz",
|
||||
"integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==",
|
||||
"version": "5.8.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
|
||||
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
|
@ -3492,9 +3557,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "6.20.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
|
||||
"integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==",
|
||||
"version": "6.21.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
|
||||
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
|
|
|
@ -12,28 +12,28 @@
|
|||
"author": "tgpholly",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@fastify/cookie": "^11.0.1",
|
||||
"@fastify/formbody": "^8.0.1",
|
||||
"@fastify/static": "^8.0.3",
|
||||
"@fastify/view": "^10.0.1",
|
||||
"@fastify/cookie": "^11.0.2",
|
||||
"@fastify/formbody": "^8.0.2",
|
||||
"@fastify/static": "^8.1.1",
|
||||
"@fastify/view": "^11.0.0",
|
||||
"bufferstuff": "^1.8.0",
|
||||
"ejs": "^3.1.10",
|
||||
"fastify": "^5.2.0",
|
||||
"hsconsole": "^1.0.2",
|
||||
"mysql2": "^3.11.5",
|
||||
"fastify": "^5.3.2",
|
||||
"hsconsole": "^1.1.0",
|
||||
"mysql2": "^3.14.0",
|
||||
"simple-prom": "^1.0.1",
|
||||
"ultimate-ws": "^1.0.13"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/ejs": "^3.1.5",
|
||||
"@types/node": "^22.10.2",
|
||||
"@types/node": "^22.14.0",
|
||||
"@vercel/ncc": "^0.38.3",
|
||||
"check-outdated": "^2.12.0",
|
||||
"check-outdated": "^2.13.0",
|
||||
"node": "^22.12.0",
|
||||
"nodemon": "^3.1.9",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"terser": "^5.37.0",
|
||||
"terser": "^5.39.0",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.7.2"
|
||||
"typescript": "^5.8.3"
|
||||
}
|
||||
}
|
||||
|
|
69
server/repos/OverrideFieldRepo.ts
Normal file
69
server/repos/OverrideFieldRepo.ts
Normal file
|
@ -0,0 +1,69 @@
|
|||
import Database from "../objects/Database";
|
||||
import OverrideField from "../entities/OverrideField";
|
||||
|
||||
export default class OverrideFieldRepo {
|
||||
public static async selectAll() {
|
||||
const dbOverride = await Database.Instance.query("SELECT * FROM OverrideField WHERE IsDeleted = 0");
|
||||
const users = new Array<OverrideField>();
|
||||
|
||||
for (const row of dbOverride) {
|
||||
const override = new OverrideField();
|
||||
populateOverrideFromDB(override, row);
|
||||
users.push(override);
|
||||
}
|
||||
|
||||
return users;
|
||||
}
|
||||
|
||||
public static async selectById(id:number) {
|
||||
const dbOverride = await Database.Instance.query("SELECT * FROM OverrideField WHERE Id = ? LIMIT 1", [id]);
|
||||
if (dbOverride == null || dbOverride.length === 0) {
|
||||
return null;
|
||||
} else {
|
||||
const override = new OverrideField();
|
||||
populateOverrideFromDB(override, dbOverride[0]);
|
||||
return override;
|
||||
}
|
||||
}
|
||||
|
||||
public static async selectByOverrideId(id: number) {
|
||||
const dbOverride = await Database.Instance.query("SELECT * FROM OverrideField WHERE IsDeleted = 0 AND OverrideId = ?", [id]);
|
||||
const users = new Array<OverrideField>();
|
||||
|
||||
for (const row of dbOverride) {
|
||||
const override = new OverrideField();
|
||||
populateOverrideFromDB(override, row);
|
||||
users.push(override);
|
||||
}
|
||||
|
||||
return users;
|
||||
}
|
||||
|
||||
public static async insertUpdate(overrideField:OverrideField) {
|
||||
if (overrideField.Id === Number.MIN_VALUE) {
|
||||
overrideField.Id = (await Database.Instance.query("INSERT OverrideField (OverrideId, FieldName, FieldValue, CreatedByUserId, CreatedDatetime, LastModifiedByUserId, LastModifiedDatetime, DeletedByUserId, DeletedDatetime, IsDeleted) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING Id;", [
|
||||
overrideField.OverrideId, overrideField.FieldName, overrideField.FieldValue, overrideField.CreatedByUserId, overrideField.CreatedDatetime.getTime(), overrideField.LastModifiedByUserId ?? null, overrideField.LastModifiedDatetime ?? null, overrideField.DeletedByUserId ?? null, overrideField.DeletedDatetime ?? null, Number(overrideField.IsDeleted)
|
||||
]))[0]["Id"];
|
||||
} else {
|
||||
await Database.Instance.query(`UPDATE OverrideField SET OverrideId = ?, FieldName = ?, FieldValue = ?, CreatedByUserId = ?, CreatedDatetime = ?, LastModifiedByUserId = ?, LastModifiedDatetime = ?, DeletedByUserId = ?, DeletedDatetime = ?, IsDeleted = ? WHERE Id = ?`, [
|
||||
overrideField.OverrideId, overrideField.FieldName, overrideField.FieldValue, overrideField.CreatedByUserId, overrideField.CreatedDatetime.getTime(), overrideField.LastModifiedByUserId ?? null, overrideField.LastModifiedDatetime ?? null, overrideField.DeletedByUserId ?? null, overrideField.DeletedDatetime ?? null, Number(overrideField.IsDeleted), overrideField.Id
|
||||
]);
|
||||
}
|
||||
|
||||
return overrideField;
|
||||
}
|
||||
}
|
||||
|
||||
function populateOverrideFromDB(overrideField:OverrideField, dbOverrideField:any) {
|
||||
overrideField.Id = dbOverrideField.Id;
|
||||
overrideField.OverrideId = dbOverrideField.OverrideId;
|
||||
overrideField.FieldName = dbOverrideField.FieldName;
|
||||
overrideField.FieldValue = dbOverrideField.FieldValue;
|
||||
overrideField.CreatedByUserId = dbOverrideField.CreatedByUserId;
|
||||
overrideField.CreatedDatetime = dbOverrideField.CreatedDatetime;
|
||||
overrideField.LastModifiedByUserId = dbOverrideField.LastModifiedByUserId;
|
||||
overrideField.LastModifiedDatetime = dbOverrideField.LastModifiedDatetime;
|
||||
overrideField.DeletedByUserId = dbOverrideField.DeletedByUserId;
|
||||
overrideField.DeletedDatetime = dbOverrideField.DeletedDatetime;
|
||||
overrideField.IsDeleted = dbOverrideField.IsDeleted[0] === 1;
|
||||
}
|
57
server/repos/OverrideRepo.ts
Normal file
57
server/repos/OverrideRepo.ts
Normal file
|
@ -0,0 +1,57 @@
|
|||
import Database from "../objects/Database";
|
||||
import Override from "../entities/Override";
|
||||
|
||||
export default class OverrideRepo {
|
||||
public static async selectAll() {
|
||||
const dbOverride = await Database.Instance.query("SELECT * FROM Override WHERE IsDeleted = 0");
|
||||
const users = new Array<Override>();
|
||||
|
||||
for (const row of dbOverride) {
|
||||
const override = new Override();
|
||||
populateOverrideFromDB(override, row);
|
||||
users.push(override);
|
||||
}
|
||||
|
||||
return users;
|
||||
}
|
||||
|
||||
public static async selectById(id:number) {
|
||||
const dbOverride = await Database.Instance.query("SELECT * FROM Override WHERE Id = ? LIMIT 1", [id]);
|
||||
if (dbOverride == null || dbOverride.length === 0) {
|
||||
return null;
|
||||
} else {
|
||||
const override = new Override();
|
||||
populateOverrideFromDB(override, dbOverride[0]);
|
||||
return override;
|
||||
}
|
||||
}
|
||||
|
||||
public static async insertUpdate(override:Override) {
|
||||
if (override.Id === Number.MIN_VALUE) {
|
||||
override.Id = (await Database.Instance.query("INSERT Override (OverrideTypeId, Name, ForURL, CSSQuery, CreatedByUserId, CreatedDatetime, LastModifiedByUserId, LastModifiedDatetime, DeletedByUserId, DeletedDatetime, IsDeleted) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING Id;", [
|
||||
override.OverrideType, override.Name, override.ForURL, override.CSSQuery, override.CreatedByUserId, override.CreatedDatetime.getTime(), override.LastModifiedByUserId ?? null, override.LastModifiedDatetime ?? null, override.DeletedByUserId ?? null, override.DeletedDatetime ?? null, Number(override.IsDeleted)
|
||||
]))[0]["Id"];
|
||||
} else {
|
||||
await Database.Instance.query(`UPDATE Override SET OverrideTypeId = ?, Name = ?, ForURL = ?, CSSQuery = ?, CreatedByUserId = ?, CreatedDatetime = ?, LastModifiedByUserId = ?, LastModifiedDatetime = ?, DeletedByUserId = ?, DeletedDatetime = ?, IsDeleted = ? WHERE Id = ?`, [
|
||||
override.OverrideType, override.Name, override.ForURL, override.CSSQuery, override.CreatedByUserId, override.CreatedDatetime.getTime(), override.LastModifiedByUserId ?? null, override.LastModifiedDatetime ?? null, override.DeletedByUserId ?? null, override.DeletedDatetime ?? null, Number(override.IsDeleted), override.Id
|
||||
]);
|
||||
}
|
||||
|
||||
return override;
|
||||
}
|
||||
}
|
||||
|
||||
function populateOverrideFromDB(override:Override, dbOverride:any) {
|
||||
override.Id = dbOverride.Id;
|
||||
override.OverrideType = dbOverride.OverrideTypeId;
|
||||
override.Name = dbOverride.Name;
|
||||
override.ForURL = dbOverride.ForURL;
|
||||
override.CSSQuery = dbOverride.CSSQuery;
|
||||
override.CreatedByUserId = dbOverride.CreatedByUserId;
|
||||
override.CreatedDatetime = dbOverride.CreatedDatetime;
|
||||
override.LastModifiedByUserId = dbOverride.LastModifiedByUserId;
|
||||
override.LastModifiedDatetime = dbOverride.LastModifiedDatetime;
|
||||
override.DeletedByUserId = dbOverride.DeletedByUserId;
|
||||
override.DeletedDatetime = dbOverride.DeletedDatetime;
|
||||
override.IsDeleted = dbOverride.IsDeleted[0] === 1;
|
||||
}
|
95
server/services/OverrideService.ts
Normal file
95
server/services/OverrideService.ts
Normal file
|
@ -0,0 +1,95 @@
|
|||
import { Console } from "hsconsole";
|
||||
import OverrideRepo from "../repos/OverrideRepo";
|
||||
import Override from "../entities/Override";
|
||||
import OverrideType from "../enums/OverrideType";
|
||||
import OverrideFieldRepo from "../repos/OverrideFieldRepo";
|
||||
import OverrideField from "../entities/OverrideField";
|
||||
|
||||
export default abstract class OverrideService {
|
||||
public static async GetOverride(id: number) {
|
||||
try {
|
||||
return await OverrideRepo.selectById(id);
|
||||
} catch (e) {
|
||||
Console.printError(`MultiProbe server service error:\n${e}`);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public static async GetOverrides() {
|
||||
try {
|
||||
return await OverrideRepo.selectAll();
|
||||
} catch (e) {
|
||||
Console.printError(`MultiProbe server service error:\n${e}`);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public static async SaveOverride(currentUserId:number, id:number | undefined, overrideType: OverrideType, name: string, forUrl: string, cssQuery: string) {
|
||||
try {
|
||||
let override = id ? await OverrideRepo.selectById(id) : null;
|
||||
if (override === null) {
|
||||
override = new Override();
|
||||
override.CreatedByUserId = currentUserId;
|
||||
override.CreatedDatetime = new Date();
|
||||
} else {
|
||||
override.LastModifiedByUserId = currentUserId;
|
||||
override.LastModifiedDatetime = new Date();
|
||||
}
|
||||
|
||||
override.OverrideType = overrideType;
|
||||
override.Name = name;
|
||||
override.ForURL = forUrl;
|
||||
override.CSSQuery = cssQuery;
|
||||
|
||||
override = await OverrideRepo.insertUpdate(override);
|
||||
|
||||
return override;
|
||||
} catch (e) {
|
||||
Console.printError(`MultiProbe server service error:\n${e}`);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public static async GetOverrideField(id: number) {
|
||||
try {
|
||||
return await OverrideFieldRepo.selectById(id);
|
||||
} catch (e) {
|
||||
Console.printError(`MultiProbe server service error:\n${e}`);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public static async GetOverrideFields(overrideId: number) {
|
||||
try {
|
||||
return await OverrideFieldRepo.selectById(overrideId);
|
||||
} catch (e) {
|
||||
Console.printError(`MultiProbe server service error:\n${e}`);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public static async SaveOverrideField(currentUserId:number, id:number | undefined, overrideId: number, fieldName: string, fieldValue: string) {
|
||||
try {
|
||||
let overrideField = id ? await OverrideFieldRepo.selectById(id) : null;
|
||||
if (overrideField === null) {
|
||||
overrideField = new OverrideField();
|
||||
overrideField.CreatedByUserId = currentUserId;
|
||||
overrideField.CreatedDatetime = new Date();
|
||||
} else {
|
||||
overrideField.LastModifiedByUserId = currentUserId;
|
||||
overrideField.LastModifiedDatetime = new Date();
|
||||
}
|
||||
|
||||
overrideField.OverrideId = overrideId;
|
||||
overrideField.FieldName = fieldName;
|
||||
overrideField.FieldValue = fieldValue;
|
||||
|
||||
overrideField = await OverrideFieldRepo.insertUpdate(overrideField);
|
||||
|
||||
return overrideField;
|
||||
} catch (e) {
|
||||
Console.printError(`MultiProbe server service error:\n${e}`);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
17
server/utilities/SelectUtility.ts
Normal file
17
server/utilities/SelectUtility.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
import OverrideType from "../enums/OverrideType";
|
||||
|
||||
export default abstract class SelectUtility {
|
||||
public static EnumToSelectList(enumToList: any, selected?: any) {
|
||||
const keys = Object.keys(enumToList);
|
||||
let output: string = "";
|
||||
for (const key of keys) {
|
||||
const keyN = parseInt(key);
|
||||
if (!isNaN(keyN)) {
|
||||
// @ts-ignore
|
||||
output += `<option value="${keyN}"${selected && selected === keyN ? " selected" : ""}>${OverrideType.ToDescription(keyN)}</option>`;
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
3
server/views/admin/_addhtml.ejs
Normal file
3
server/views/admin/_addhtml.ejs
Normal file
|
@ -0,0 +1,3 @@
|
|||
<div id="overrideFields">
|
||||
|
||||
</div>
|
|
@ -49,6 +49,7 @@
|
|||
<a class="btn btn-primary btn-lg me-2 mb-3" href="/admin/parties">Manage Parties</a>
|
||||
<a class="btn btn-primary btn-lg me-2 mb-3" href="/admin/badges">Manage Badges</a>
|
||||
<a class="btn btn-primary btn-lg me-2 mb-3" href="/admin/userbadges">Manage Unlocked Badges</a>
|
||||
<a class="btn btn-primary btn-lg me-2 mb-3" href="/admin/overrides">Manage Overrides</a>
|
||||
<a class="btn btn-primary btn-lg me-2 mb-3" href="/admin/websessions">Web Sessions</a>
|
||||
<a class="btn btn-primary btn-lg me-2 mb-3" href="/admin/wssessions">Websocket Sessions</a>
|
||||
</div>
|
||||
|
|
59
server/views/admin/override.ejs
Normal file
59
server/views/admin/override.ejs
Normal file
|
@ -0,0 +1,59 @@
|
|||
<%- include("../base/header", { title: typeof(id) === "undefined" ? "Add Override" : `Edit ${name}`, userId: session.userId, isAdmin: true }) %>
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<nav aria-label="breadcrumb">
|
||||
<ol class="breadcrumb">
|
||||
<li class="breadcrumb-item"><a href="/admin">Admin</a></li>
|
||||
<li class="breadcrumb-item"><a href="/admin/overrides">Override Management</a></li>
|
||||
<li class="breadcrumb-item active"><a><%= typeof(id) === "undefined" ? "Add Override" : `Edit ${name}` %></a></li>
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h1><%= typeof(id) === "undefined" ? "Add Override" : `Edit ${name}` %></h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form method="post" class="needs-validation" novalidate>
|
||||
<input type="hidden" name="id" value="<%= typeof(id) === "undefined" ? "" : id %>" />
|
||||
|
||||
<div class="row mt-5 mb-3">
|
||||
<div class="col">
|
||||
<label for="name" class="form-label">Name</label>
|
||||
<input class="form-control" id="name" name="name" value="<%= typeof(name) === "undefined" ? "" : name %>" required maxlength="255" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col">
|
||||
<label for="forUrl" class="form-label">Type</label>
|
||||
<select class="form-select" id="overrideType" name="overrideType" required>
|
||||
<%- SelectUtility.EnumToSelectList(OverrideType, overrideType) %>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col">
|
||||
<label for="forUrl" class="form-label">For URL</label>
|
||||
<input class="form-control" id="forUrl" name="forUrl" value="<%= typeof(forUrl) === "undefined" ? "" : forUrl %>" required />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<% if (overrideType === OverrideType.AddHtml) { %>
|
||||
<%- include("./_addhtml") %>
|
||||
<% } else { %>
|
||||
<div id="overrideFields"></div>
|
||||
<% } %>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col text-center">
|
||||
<button type="submit" class="btn btn-primary">Save</button>
|
||||
<a type="submit" class="btn btn-danger" href="/admin/">Cancel</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<%- include("../base/footer", { apiKey: session.apiKey, username: session.username }) %>
|
45
server/views/admin/overrides.ejs
Normal file
45
server/views/admin/overrides.ejs
Normal file
|
@ -0,0 +1,45 @@
|
|||
<%- include("../base/header", { title: "Badge Management", userId: session.userId, isAdmin: true }) %>
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<nav aria-label="breadcrumb">
|
||||
<ol class="breadcrumb">
|
||||
<li class="breadcrumb-item"><a href="/admin">Admin</a></li>
|
||||
<li class="breadcrumb-item active"><a>Override Management</a></li>
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h1>Override Management</h1>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<a class="btn btn-primary btn-lg me-2" href="/admin/override">Add Override</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row my-5">
|
||||
<div class="col">
|
||||
<table class="table table-striped" style="word-break:break-word">
|
||||
<thead>
|
||||
<th>Name</th>
|
||||
<th> </th>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% for (const override of overrides) { %>
|
||||
<tr>
|
||||
<td class="align-middle"><%= override.Name %></td>
|
||||
<td class="text-end text-nowrap align-middle">
|
||||
<a class="btn btn-sm btn-primary" href="/admin/override?id=<%= override.Id %>">Edit</a>
|
||||
<a class="btn btn-sm btn-danger" href="/admin/deleteoverride?id=<%= override.Id %>" onclick="return confirm(`Are you sure you want to delete '<%= override.Name %>'?`)">Delete</a>
|
||||
</td>
|
||||
</tr>
|
||||
<% } %>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%- include("../base/footer", { apiKey: session.apiKey, username: session.username }) %>
|
Loading…
Add table
Reference in a new issue