version bump and frontend fixes

This commit is contained in:
peter
2020-04-02 09:51:46 +02:00
parent 1cd453b382
commit c888bf4514
49 changed files with 670 additions and 669 deletions
+33
View File
@@ -0,0 +1,33 @@
[2020-03-29T12:12:03.477] [DEBUG] Admin#makeKnex - Making new knex: {
client: 'sqlite3',
connection: {(node:1085628) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead.
Terminated
npm ERR! code ELIFECYCLE
npm ERR! errno 143
npm ERR! frontcraft@1.0.0 launch: `node lib/src/backend/Launcher.js > log.txt "-"`
npm ERR! Exit status 143
npm ERR!
npm ERR! Failed at the frontcraft@1.0.0 launch script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! /home/cake/.npm/_logs/2020-03-29T10_12_28_351Z-debug.log
s loaded
[2020-03-29T12:12:04.535] [INFO] Admin#startWebserver - Admin panel listening for HTTP on *8080
[2020-03-29T12:12:17.689] [DEBUG] UserManager#checkConnection - {
celinda: {
connections: { '59288': [Socket] },
auth: { token: [Object], user: [Object], port: 20001 },
user: {
id: 3,
username: 'celinda',
rank: 'Officer',
MC: 1,
BWL: 0,
ZG: 1,
AQ20: 1,
AQ40: 1,
Naxx: 1
}
}
} [ '1563eebe-9da2-4b31-b4ef-ef3aaa7e23b1' ]
+1 -1
View File
@@ -5,7 +5,7 @@
"scripts": { "scripts": {
"tsc": "tsc", "tsc": "tsc",
"knex": "knex", "knex": "knex",
"launch": "node lib/src/backend/Launcher.js", "launch": "node lib/src/backend/Launcher.js > log.txt",
"start": "npm run build && npm run launch", "start": "npm run build && npm run launch",
"start-backend": "npm run build-backend && npm run launch", "start-backend": "npm run build-backend && npm run launch",
"test": "rm -rf data && npm run build-backend && mocha lib/test/backendTest.js", "test": "rm -rf data && npm run build-backend && mocha lib/test/backendTest.js",
+1 -3
View File
@@ -19,7 +19,6 @@ import { RPCConfigLoader } from '../Components/RPCConfigLoader';
import { FrontworkComponent } from '../Types/FrontworkComponent'; import { FrontworkComponent } from '../Types/FrontworkComponent';
import { IAdmin } from './Interface'; import { IAdmin } from './Interface';
import { Injector } from '../Injector/Injector'; import { Injector } from '../Injector/Injector';
import { Shoutbox } from '../Components/Shoutbox/Shoutbox';
import { PubSub } from '../Components/PubSub/PubSub'; import { PubSub } from '../Components/PubSub/PubSub';
getLogger().level = 'debug' getLogger().level = 'debug'
@@ -32,7 +31,6 @@ getLogger().level = 'debug'
RaidManager, RaidManager,
CharacterManager, CharacterManager,
UserManager, UserManager,
Shoutbox,
PubSub PubSub
] ]
}) })
@@ -145,7 +143,7 @@ export class FrontworkAdmin
try { try {
const req = require(distFolder + "/server.js") const req = require(distFolder + "/server.js")
await req.attachExpress(this.express) await req.attachExpress(this.express, './dist', getLogger('angularSSR#'))
getLogger('Admin#startWebserver').info('Frontend from ' + ngExpressServer + " loaded") getLogger('Admin#startWebserver').info('Frontend from ' + ngExpressServer + " loaded")
} catch (e) { } catch (e) {
getLogger('Admin#startWebserver').error(e) getLogger('Admin#startWebserver').error(e)
+12 -2
View File
@@ -145,7 +145,7 @@ export class RaidManager
getRaids = async (): Promise<Raid[]> => { getRaids = async (): Promise<Raid[]> => {
const subQuery = this.admin const countSignups = this.admin
.knex('signups') .knex('signups')
.count('*') .count('*')
.where({ .where({
@@ -155,8 +155,18 @@ export class RaidManager
}) })
.as('signupcount') .as('signupcount')
const countBenches = this.admin
.knex('signups')
.count('*')
.where({
raidid: this.admin.knex.ref('raids.id'),
benched: true,
late: false
})
.as('benchcount')
return await this.admin.knex('raids') return await this.admin.knex('raids')
.select('*', subQuery) .select('*', countSignups, countBenches)
.orderBy('start', 'asc') .orderBy('start', 'asc')
} }
@@ -1,13 +0,0 @@
import { Raid, Signup, Character, RaidData } from "../../Types/Types"
export type ShoutMessage = {
message: string,
sender: string,
date: string
}
export class IShoutbox{
shout: (uuid:string, msg: ShoutMessage) => Promise<void>
getFeed: () => Promise<ShoutMessage[]>
subscribe: (callback) => Promise<string>
}
@@ -1,13 +0,0 @@
import { IShoutbox } from "./Interface"
export type ShoutboxIfc = {
Shoutbox:{
getFeed: IShoutbox['getFeed']
shout: IShoutbox['shout']
subscribe: IShoutbox['subscribe']
}
}
export type ShoutboxFeatureIfc = {
}
@@ -1,64 +0,0 @@
import { Injectable } from "../../Injector/ServiceDecorator";
import { ShoutboxFeatureIfc, ShoutboxIfc } from "./RPCInterface";
import { FrontworkComponent } from "../../Types/FrontworkComponent";
import { TableDefiniton } from "../../Types/Types";
import { IShoutbox, ShoutMessage } from "./Interface";
import * as CircularBuffer from "circular-buffer";
const uuid = require('uuid/v4')
@Injectable(IShoutbox)
export class Shoutbox
implements FrontworkComponent<ShoutboxIfc, ShoutboxFeatureIfc>, IShoutbox{
name = "Shoutbox" as "Shoutbox";
log: CircularBuffer = new CircularBuffer(500)
subs = {}
exportRPCs = () => [
this.shout,
this.getFeed,
{
name: 'subscribe' as 'subscribe',
hook: this.subscribe,
onClose: (subres, rpcName) => {
this.unsubscribe(subres.uuid)
}
}
]
exportRPCFeatures = () => []
getTableDefinitions(): TableDefiniton[] {
return []
}
shout = async (uuid:string, msg: ShoutMessage) : Promise<void> => {
if(!this.subs[uuid]) return
this.broadcast(uuid, msg)
this.log.push(msg)
}
private broadcast = async (uuid:string, msg: ShoutMessage) => {
await Promise.all(Object.values(this.subs).map(async (callback:any) => {
try{
await callback(msg)
}catch(e){
delete this.subs[uuid]
}
}))
}
getFeed = async () : Promise<ShoutMessage[]> => {
return this.log.toarray()
}
subscribe = async (callback) : Promise<string> => {
uuid()
this.subs[uuid] = callback
return uuid
}
unsubscribe = async (uuid: string) => {
delete this.subs[uuid]
}
}
@@ -404,6 +404,7 @@ export class UserManager
}, },
errorHandler: (socket, e, rpcName, args) => { errorHandler: (socket, e, rpcName, args) => {
getLogger('UserManager#errorHandler').error(rpcName, args, e); getLogger('UserManager#errorHandler').error(rpcName, args, e);
throw(new Error("RPC failed"))
}, },
sesame: (sesame) => this.checkToken(sesame), sesame: (sesame) => this.checkToken(sesame),
visibility: '0.0.0.0' visibility: '0.0.0.0'
+1 -2
View File
@@ -5,7 +5,6 @@ import { UserManagerIfc, UserManagerFeatureIfc } from "../Components/User/RPCInt
import { CharacterManagerIfc, CharacterManagerFeatureIfc } from "../Components/Character/RPCInterface"; import { CharacterManagerIfc, CharacterManagerFeatureIfc } from "../Components/Character/RPCInterface";
import { ItemManagerFeatureIfc, ItemManagerIfc } from "../Components/Item/RPCInterface"; import { ItemManagerFeatureIfc, ItemManagerIfc } from "../Components/Item/RPCInterface";
import { GuildManagerFeatureIfc, GuildManagerIfc } from "../Components/Guild/RPCInterface"; import { GuildManagerFeatureIfc, GuildManagerIfc } from "../Components/Guild/RPCInterface";
import { ShoutboxIfc } from "../Components/Shoutbox/RPCInterface";
import { Tiers } from "./Items"; import { Tiers } from "./Items";
import { PubSubIfc } from "../Components/PubSub/RPCInterface"; import { PubSubIfc } from "../Components/PubSub/RPCInterface";
@@ -14,7 +13,6 @@ export type FrontcraftIfc = RaidManagerIfc
& CharacterManagerIfc & CharacterManagerIfc
& ItemManagerIfc & ItemManagerIfc
& GuildManagerIfc & GuildManagerIfc
& ShoutboxIfc
& PubSubIfc & PubSubIfc
export type FrontcraftFeatureIfc = RaidManagerFeatureIfc export type FrontcraftFeatureIfc = RaidManagerFeatureIfc
@@ -155,6 +153,7 @@ export type Raid = {
description: string description: string
start: string start: string
signupcount?: number signupcount?: number
benchcount?: number
size: number size: number
tier: Tiers tier: Tiers
} }
+89 -45
View File
@@ -6288,6 +6288,11 @@
"assert-plus": "^1.0.0" "assert-plus": "^1.0.0"
} }
}, },
"date-format": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/date-format/-/date-format-3.0.0.tgz",
"integrity": "sha512-eyTcpKOcamdhWJXj56DpQMo1ylSQpcGtGKXcU0Tb97+K56/CF5amAqqqNj0+KvA0iw2ynxtHWFsPDSClCxe48w=="
},
"dateformat": { "dateformat": {
"version": "3.0.3", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz",
@@ -6298,7 +6303,6 @@
"version": "4.1.1", "version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"dev": true,
"requires": { "requires": {
"ms": "^2.1.1" "ms": "^2.1.1"
} }
@@ -8095,6 +8099,11 @@
} }
} }
}, },
"flatted": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz",
"integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg=="
},
"flatten": { "flatten": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.3.tgz", "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.3.tgz",
@@ -8131,6 +8140,11 @@
} }
} }
}, },
"font-awesome": {
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/font-awesome/-/font-awesome-4.7.0.tgz",
"integrity": "sha1-j6jPBBGhoxr9B7BtKQK7n8gVoTM="
},
"fontkit": { "fontkit": {
"version": "1.8.0", "version": "1.8.0",
"resolved": "https://registry.npmjs.org/fontkit/-/fontkit-1.8.0.tgz", "resolved": "https://registry.npmjs.org/fontkit/-/fontkit-1.8.0.tgz",
@@ -8324,7 +8338,6 @@
"version": "8.1.0", "version": "8.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
"integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
"dev": true,
"requires": { "requires": {
"graceful-fs": "^4.2.0", "graceful-fs": "^4.2.0",
"jsonfile": "^4.0.0", "jsonfile": "^4.0.0",
@@ -10435,7 +10448,6 @@
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
"integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
"dev": true,
"requires": { "requires": {
"graceful-fs": "^4.1.6" "graceful-fs": "^4.1.6"
} }
@@ -11327,6 +11339,12 @@
"kind-of": "^3.0.2" "kind-of": "^3.0.2"
} }
}, },
"isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
"dev": true
},
"kind-of": { "kind-of": {
"version": "3.2.2", "version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
@@ -11342,6 +11360,30 @@
"integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=",
"dev": true "dev": true
}, },
"log4js": {
"version": "0.6.38",
"resolved": "https://registry.npmjs.org/log4js/-/log4js-0.6.38.tgz",
"integrity": "sha1-LElBFmldb7JUgJQ9P8hy5mKlIv0=",
"dev": true,
"requires": {
"readable-stream": "~1.0.2",
"semver": "~4.3.3"
},
"dependencies": {
"readable-stream": {
"version": "1.0.34",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
"integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
"dev": true,
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.1",
"isarray": "0.0.1",
"string_decoder": "~0.10.x"
}
}
}
},
"micromatch": { "micromatch": {
"version": "2.3.11", "version": "2.3.11",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
@@ -11587,12 +11629,24 @@
} }
} }
}, },
"semver": {
"version": "4.3.6",
"resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz",
"integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=",
"dev": true
},
"source-map": { "source-map": {
"version": "0.5.7", "version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
"dev": true "dev": true
}, },
"string_decoder": {
"version": "0.10.31",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
"dev": true
},
"tmp": { "tmp": {
"version": "0.0.31", "version": "0.0.31",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.31.tgz", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.31.tgz",
@@ -12724,45 +12778,15 @@
} }
}, },
"log4js": { "log4js": {
"version": "0.6.38", "version": "6.1.2",
"resolved": "https://registry.npmjs.org/log4js/-/log4js-0.6.38.tgz", "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.1.2.tgz",
"integrity": "sha1-LElBFmldb7JUgJQ9P8hy5mKlIv0=", "integrity": "sha512-knS4Y30pC1e0n7rfx3VxcLOdBCsEo0o6/C7PVTGxdVK+5b1TYOSGQPn9FDcrhkoQBV29qwmA2mtkznPAQKnxQg==",
"dev": true,
"requires": { "requires": {
"readable-stream": "~1.0.2", "date-format": "^3.0.0",
"semver": "~4.3.3" "debug": "^4.1.1",
}, "flatted": "^2.0.1",
"dependencies": { "rfdc": "^1.1.4",
"isarray": { "streamroller": "^2.2.3"
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
"dev": true
},
"readable-stream": {
"version": "1.0.34",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
"integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
"dev": true,
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.1",
"isarray": "0.0.1",
"string_decoder": "~0.10.x"
}
},
"semver": {
"version": "4.3.6",
"resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz",
"integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=",
"dev": true
},
"string_decoder": {
"version": "0.10.31",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
"dev": true
}
} }
}, },
"loglevel": { "loglevel": {
@@ -13376,8 +13400,7 @@
"ms": { "ms": {
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
"dev": true
}, },
"multicast-dns": { "multicast-dns": {
"version": "6.2.3", "version": "6.2.3",
@@ -15717,6 +15740,11 @@
"integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=",
"dev": true "dev": true
}, },
"rfdc": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.4.tgz",
"integrity": "sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug=="
},
"rimraf": { "rimraf": {
"version": "2.6.1", "version": "2.6.1",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz",
@@ -17025,6 +17053,23 @@
"integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==",
"dev": true "dev": true
}, },
"streamroller": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/streamroller/-/streamroller-2.2.3.tgz",
"integrity": "sha512-AegmvQsscTRhHVO46PhCDerjIpxi7E+d2GxgUDu+nzw/HuLnUdxHWr6WQ+mVn/4iJgMKKFFdiUwFcFRDvcjCtw==",
"requires": {
"date-format": "^2.1.0",
"debug": "^4.1.1",
"fs-extra": "^8.1.0"
},
"dependencies": {
"date-format": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz",
"integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA=="
}
}
},
"strict-uri-encode": { "strict-uri-encode": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
@@ -18508,8 +18553,7 @@
"universalify": { "universalify": {
"version": "0.1.2", "version": "0.1.2",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="
"dev": true
}, },
"unix-crypt-td-js": { "unix-crypt-td-js": {
"version": "1.1.4", "version": "1.1.4",
+2
View File
@@ -62,10 +62,12 @@
"core-js": "2.5.1", "core-js": "2.5.1",
"echarts": "^4.0.2", "echarts": "^4.0.2",
"eva-icons": "^1.1.0", "eva-icons": "^1.1.0",
"font-awesome": "^4.7.0",
"intl": "1.2.5", "intl": "1.2.5",
"ionicons": "2.0.1", "ionicons": "2.0.1",
"js-cookie": "^2.2.1", "js-cookie": "^2.2.1",
"leaflet": "1.2.0", "leaflet": "1.2.0",
"log4js": "^6.1.2",
"nebular-icons": "1.1.0", "nebular-icons": "1.1.0",
"ng2-ckeditor": "^1.2.2", "ng2-ckeditor": "^1.2.2",
"ng2-completer": "2.0.8", "ng2-completer": "2.0.8",
+10 -3
View File
@@ -13,15 +13,22 @@ global['document'] = win.document;
global['alert'] = console.log global['alert'] = console.log
global['XMLHttpRequest'] = require('xmlhttprequest').XMLHttpRequest; global['XMLHttpRequest'] = require('xmlhttprequest').XMLHttpRequest;
export async function attachExpress(app, staticDir = "./dist", loggerService = console) { export async function attachExpress(app, staticDir = "./dist", logger = console) {
const STATIC_FOLDER = resolve(process.cwd(), staticDir); const STATIC_FOLDER = resolve(process.cwd(), staticDir);
enableProdMode(); enableProdMode();
const loggerService = {
warn: (...args) => logger.error(...args),
error: (...args) => logger.warn(...args),
log: (...args) => logger.info(...args),
table: (...args) => logger.info(...args),
collapsed: (msg, type, ...args) => loggerService[type](msg, ...args)
}
const bundle = require(staticDir + '/server/main'); const bundle = require(staticDir + '/server/main');
const ServerApiService = bundle.ServerApiService const ServerApiService = bundle.ServerApiService
const serviceObj = new ServerApiService(loggerService) const serviceObj = new ServerApiService(logger)
await serviceObj.initialize() await serviceObj.initialize()
app.set('view engine', 'html'); app.set('view engine', 'html');
@@ -1,46 +0,0 @@
import { Component } from '@angular/core';
import { ShoutMessage } from '../../../../../../backend/Components/Shoutbox/Interface';
import { IApiService } from '../../../frontcraft/services/ApiService';
@Component({
selector: 'chat',
template: `
<nb-chat title="Shoutbox" size="large" status="primary">
<nb-chat-message *ngFor="let msg of messages"
[type]="text"
[message]="msg.message"
[sender]="msg.sender"
[date]="msg.date"
[reply]="msg.reply">
</nb-chat-message>
<nb-chat-form
(send)="submit($event)"
[dropFiles]="false">
</nb-chat-form>
</nb-chat>
`,
styles: [`
nb-chat {
width: 600px;
margin: 0.5rem 0 2rem 2rem;
}`],
})
export class ChatComponent {
messages : ShoutMessage[] = []
history
constructor(
private api: IApiService
) {}
submit(event){
this.sendMessage({
date: ""+Date.now(),
message: event.message,
sender: this.api.getCurrentUser().username
})
}
sendMessage : (msg:ShoutMessage)=>Promise<void>
}
@@ -14,19 +14,6 @@
icon="settings-2-outline" icon="settings-2-outline"
link="/permissions"> link="/permissions">
</nb-action> </nb-action>
<nb-action
*ngIf="!newmessage"
icon="message-square-outline"
(click)="openChat()">
</nb-action>
<nb-action
*ngIf="newmessage"
icon="message-square-outline"
badgeText="new"
badgePosition="top right"
badgeStatus="info"
(click)="openChat()">
</nb-action>
<nb-action class="user-action"> <nb-action class="user-action">
<nb-user style="text-transform: capitalize;" <nb-user style="text-transform: capitalize;"
@@ -6,9 +6,7 @@ import { map, takeUntil } from 'rxjs/operators';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
import { User } from '../../../../../../backend/Types/Types'; import { User } from '../../../../../../backend/Types/Types';
import { Router, ActivatedRoute, NavigationEnd } from '@angular/router'; import { Router, ActivatedRoute, NavigationEnd } from '@angular/router';
import { ChatComponent } from './chat.component'; import { IApiService } from '../../../frontcraft/services/ApiService/ApiService';
import { ShoutMessage } from '../../../../../../backend/Components/Shoutbox/Interface';
import { IApiService } from '../../../frontcraft/services/ApiService';
@Component({ @Component({
selector: 'ngx-header', selector: 'ngx-header',
@@ -44,8 +42,6 @@ export class HeaderComponent implements OnInit, OnDestroy {
userMenu: NbMenuItem[] = []; userMenu: NbMenuItem[] = [];
sendMessage: any = console.log sendMessage: any = console.log
chatwindow: ChatComponent
chatlog: ShoutMessage[] = []
newmessage = false newmessage = false
lastmessage = "asdasd" lastmessage = "asdasd"
modifyPermissions modifyPermissions
@@ -56,8 +52,6 @@ export class HeaderComponent implements OnInit, OnDestroy {
private themeService: NbThemeService, private themeService: NbThemeService,
private layoutService: LayoutService, private layoutService: LayoutService,
private api: IApiService, private api: IApiService,
private dialogService: NbDialogService,
private route: ActivatedRoute
) { } ) { }
private setUserMenu = (redirect = this.router.url) => { private setUserMenu = (redirect = this.router.url) => {
@@ -89,29 +83,10 @@ export class HeaderComponent implements OnInit, OnDestroy {
} }
}) })
this.api.get('GuildManager').getGuildInfo().then(info => { this.api.get('GuildManager').getGuildInfo().then(info => {
this.title = info.name this.title = info.name
}) })
this.api.connectShoutbox((msg) => {
this.chatlog.push(msg)
msg['reply'] = false
if (msg.message != this.lastmessage) {
this.newmessage = true
msg['reply'] = true
}
if (this.chatwindow) this.chatwindow.messages.push(msg)
}).then(sendMsg => {
this.sendMessage = (msg) => {
sendMsg(msg)
this.lastmessage = msg.message
}
this.api.get('Shoutbox').getFeed().then(log => { this.chatlog = log })
})
this.themeService.onThemeChange() this.themeService.onThemeChange()
.pipe( .pipe(
map(({ name }) => name), map(({ name }) => name),
@@ -120,20 +95,6 @@ export class HeaderComponent implements OnInit, OnDestroy {
.subscribe(themeName => this.currentTheme = themeName); .subscribe(themeName => this.currentTheme = themeName);
} }
openChat() {
this.newmessage = false
const ref = this.dialogService.open(ChatComponent, {
context: {
sendMessage: this.sendMessage,
}
});
ref.onClose.subscribe(() => {
this.chatwindow = null
})
this.chatwindow = ref.componentRef.instance
this.chatwindow.messages.push(...this.chatlog)
}
ngOnDestroy() { ngOnDestroy() {
this.destroy$.next(); this.destroy$.next();
this.destroy$.complete(); this.destroy$.complete();
@@ -42,7 +42,6 @@ import { DEFAULT_THEME } from './styles/theme.default';
import { COSMIC_THEME } from './styles/theme.cosmic'; import { COSMIC_THEME } from './styles/theme.cosmic';
import { CORPORATE_THEME } from './styles/theme.corporate'; import { CORPORATE_THEME } from './styles/theme.corporate';
import { DARK_THEME } from './styles/theme.dark'; import { DARK_THEME } from './styles/theme.dark';
import { ChatComponent } from './components/header/chat.component';
const NB_MODULES = [ const NB_MODULES = [
NbLayoutModule, NbLayoutModule,
@@ -70,7 +69,6 @@ const COMPONENTS = [
ThreeColumnsLayoutComponent, ThreeColumnsLayoutComponent,
TwoColumnsLayoutComponent, TwoColumnsLayoutComponent,
OneColumnNoSidebarLayoutComponent, OneColumnNoSidebarLayoutComponent,
ChatComponent
]; ];
const PIPES = [ const PIPES = [
CapitalizePipe, CapitalizePipe,
@@ -85,7 +83,6 @@ const PIPES = [
exports: [CommonModule, ...PIPES, ...COMPONENTS], exports: [CommonModule, ...PIPES, ...COMPONENTS],
declarations: [...COMPONENTS, ...PIPES], declarations: [...COMPONENTS, ...PIPES],
entryComponents: [ entryComponents: [
ChatComponent
] ]
}) })
export class ThemeModule { export class ThemeModule {
+10 -3
View File
@@ -3,10 +3,17 @@
* Copyright Akveo. All Rights Reserved. * Copyright Akveo. All Rights Reserved.
* Licensed under the MIT License. See License.txt in the project root for license information. * Licensed under the MIT License. See License.txt in the project root for license information.
*/ */
import { Component, OnInit } from '@angular/core'; import { Component } from '@angular/core';
import { NbIconLibraries } from '@nebular/theme';
@Component({ @Component({
selector: 'ngx-app', selector: 'ngx-app',
template: '<router-outlet></router-outlet>', template: `<router-outlet></router-outlet>`,
styles: []
}) })
export class AppComponent { } export class AppComponent{
constructor(private iconLibraries: NbIconLibraries) {
this.iconLibraries.registerFontPack('font-awesome', { iconClassPrefix: 'fa' });
}
}
+2 -1
View File
@@ -23,6 +23,7 @@ import {
NbToastrModule, NbToastrModule,
NbWindowModule, NbWindowModule,
} from '@nebular/theme'; } from '@nebular/theme';
import { FlashService } from './frontcraft/services/flash-service';
@NgModule({ @NgModule({
declarations: [ declarations: [
@@ -49,7 +50,7 @@ import {
PermissionsModule PermissionsModule
], ],
bootstrap: [AppComponent], bootstrap: [AppComponent],
providers: [] providers: [FlashService]
}) })
export class FrontcraftAppModule { export class FrontcraftAppModule {
} }
@@ -1,23 +1,41 @@
import { Router, NavigationStart } from '@angular/router' import { Router, NavigationStart } from '@angular/router'
import { IApiService } from './services/ApiService' import { IApiService } from './services/ApiService/ApiService'
import { AnyFunction } from 'rpclibrary' import { AnyFunction } from 'rpclibrary'
import { LoggerService } from './services/logger.service' import { LoggerService } from './services/LoggerService/logger.service'
import { OnDestroy } from '@angular/core' import { OnDestroy, Inject, PLATFORM_ID, Injector } from '@angular/core'
import { isPlatformBrowser } from '@angular/common'
export abstract class UpdatingComponent implements OnDestroy { export abstract class UpdatingComponent implements OnDestroy {
private _uuid: string private _uuid: string
private _routerCancel: Function private _routerCancel: Function
private _router: Router
private _api: IApiService
private _logger: LoggerService
private platformId: Object
constructor( constructor(
private _router: Router, injector: Injector
private _api: IApiService, ) {
private _logger: LoggerService this._router = injector.get(Router)
) { } this._api = injector.get(IApiService)
this._logger = injector.get(LoggerService)
this.platformId = injector.get(PLATFORM_ID)
}
protected subscribe = ( protected subscribe = (
topic: string, topic: string,
callback: AnyFunction, callback: AnyFunction,
) => { ) => {
if (!topic
|| topic === "null"
|| topic === "undefined"
|| !callback
|| !isPlatformBrowser(this.platformId))
{
return
}
const sub = this._router.events.subscribe(event => { const sub = this._router.events.subscribe(event => {
if (event instanceof NavigationStart) { if (event instanceof NavigationStart) {
this.ngOnDestroy() this.ngOnDestroy()
@@ -1,6 +1,6 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router'; import { Router, ActivatedRoute } from '@angular/router';
import { IApiService } from '../../services/ApiService'; import { IApiService } from '../../services/ApiService/ApiService';
import { NbToastrService } from '@nebular/theme'; import { NbToastrService } from '@nebular/theme';
@Component({ @Component({
@@ -1,5 +1,5 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { IApiService } from '../../services/ApiService'; import { IApiService } from '../../services/ApiService/ApiService';
import { Router, ActivatedRoute } from '@angular/router'; import { Router, ActivatedRoute } from '@angular/router';
@Component({ @Component({
@@ -2,7 +2,7 @@ import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router'; import { Router, ActivatedRoute } from '@angular/router';
import { _Rank, _Class, Class, User, _Race } from '../../../../../../backend/Types/Types' import { _Rank, _Class, Class, User, _Race } from '../../../../../../backend/Types/Types'
import { specs } from '../../../../../../backend/Types/PlayerSpecs' import { specs } from '../../../../../../backend/Types/PlayerSpecs'
import { hash, IApiService } from '../../services/ApiService'; import { hash, IApiService } from '../../services/ApiService/ApiService';
@Component({ @Component({
@@ -2,7 +2,7 @@ import { Component, OnInit } from '@angular/core';
import { Item, Stats } from '../../../../../../backend/Types/Types'; import { Item, Stats } from '../../../../../../backend/Types/Types';
import { NbToastrService } from '@nebular/theme'; import { NbToastrService } from '@nebular/theme';
import { IApiService } from '../../services/ApiService'; import { IApiService } from '../../services/ApiService/ApiService';
@Component({ @Component({
selector: 'armory', selector: 'armory',
@@ -3,7 +3,7 @@ import { ActivatedRoute } from '@angular/router';
import { Spec, User, Character, Item } from '../../../../../../backend/Types/Types'; import { Spec, User, Character, Item } from '../../../../../../backend/Types/Types';
import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs'; import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
import { _Tiers } from '../../../../../../backend/Types/Items'; import { _Tiers } from '../../../../../../backend/Types/Items';
import { IApiService } from '../../services/ApiService'; import { IApiService } from '../../services/ApiService/ApiService';
@Component({ @Component({
selector: 'character', selector: 'character',
@@ -2,7 +2,7 @@ import { Component, AfterViewInit, OnDestroy } from '@angular/core';
import { NbThemeService } from '@nebular/theme'; import { NbThemeService } from '@nebular/theme';
import { _Class } from '../../../../../../backend/Types/Types'; import { _Class } from '../../../../../../backend/Types/Types';
import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs'; import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
import { IApiService } from '../../services/ApiService'; import { IApiService } from '../../services/ApiService/ApiService';
@Component({ @Component({
@@ -1,7 +1,7 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { NbMenuItem } from '@nebular/theme'; import { NbMenuItem } from '@nebular/theme';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { IApiService } from '../services/ApiService'; import { IApiService } from '../services/ApiService/ApiService';
@Component({ @Component({
@@ -1,8 +1,9 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router'; import { ActivatedRoute, Router } from '@angular/router';
import { RaidData } from '../../../../../../backend/Types/Types'; import { RaidData } from '../../../../../../backend/Types/Types';
import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs'; import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
import { IApiService } from '../../services/ApiService'; import { IApiService } from '../../services/ApiService/ApiService';
import { LoggerService } from '../../services/LoggerService/logger.service';
@Component({ @Component({
selector: 'archive', selector: 'archive',
@@ -40,6 +41,8 @@ export class FrontcraftArchiveComponent implements OnInit{
constructor( constructor(
private api: IApiService, private api: IApiService,
private route: ActivatedRoute, private route: ActivatedRoute,
private router: Router,
private logger: LoggerService
){ ){
} }
@@ -51,25 +54,31 @@ export class FrontcraftArchiveComponent implements OnInit{
const param = this.route.snapshot.paramMap.get('id'); const param = this.route.snapshot.paramMap.get('id');
const raidManager = this.api.get('RaidManager') const raidManager = this.api.get('RaidManager')
const raiddata = await raidManager.getArchiveRaid(parseInt(param)) try{
const raiddata = await raidManager.getArchiveRaid(parseInt(param))
if(!raiddata) throw new Error('Unable to get raid')
console.log(raiddata); this.raid = raiddata
this.isTier = raiddata.tier != null
this.tokens = raiddata.tokens
this.displayedtokens = this.tokens;
[
...raiddata.tanks,
...raiddata.healers,
...Object.values<any>(raiddata.participants).flat()
].forEach(p => {
p['color'] = getClassColor(p.class)
if(!p.timestamp)
p.before = 5.184e+8 //7 days
else
p['before'] = Number.parseInt(this.raid.start) - Date.parse(p.timestamp)
})
this.raid = raiddata this.changeSearch()
this.isTier = raiddata.tier != null }catch(e){
this.tokens = raiddata.tokens this.router.navigate(["/"])
this.displayedtokens = this.tokens; }
[
...raiddata.tanks,
...raiddata.healers,
...Object.values<any>(raiddata.participants).flat()
].forEach(p => {
p['color'] = getClassColor(p.class)
})
this.changeSearch()
} }
changeSearch(){ changeSearch(){
@@ -2,7 +2,7 @@ import { OnInit, Component } from '@angular/core';
import { NbToastrService, NbDialogRef } from '@nebular/theme'; import { NbToastrService, NbDialogRef } from '@nebular/theme';
import { RaidData, Character } from '../../../../../../backend/Types/Types'; import { RaidData, Character } from '../../../../../../backend/Types/Types';
import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs'; import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
import { IApiService } from '../../services/ApiService'; import { IApiService } from '../../services/ApiService/ApiService';
@Component({ @Component({
selector: 'characterpicker', selector: 'characterpicker',
@@ -86,17 +86,17 @@
style="white-space: pre-line; max-width: 50vw; word-wrap: break-word;"> style="white-space: pre-line; max-width: 50vw; word-wrap: break-word;">
{{participant.memo}} {{participant.memo}}
</p> </p>
{{participant.timestamp | date : 'HH:mm EEE MMM d'}} {{participant.timestamp | date : 'HH:mm EEE MMM d'}} ({{participant.before | date : 'dd'}} days before start)
</div> </div>
</ng-template> </ng-template>
<nb-icon *ngIf="participant.memo == null || participant.memo == ''" <nb-icon
[nbPopover]="template" nbPopoverTrigger="hover" [nbPopover]="template"
style="width: 0.75em; height: 0.75em;" icon="clock-outline"></nb-icon> nbPopoverTrigger="hover"
style="width: 0.75em; height: 0.75em;"
<nb-icon *ngIf="participant.memo != null && participant.memo != ''" [icon]="participant.memo != null && participant.memo != ''?'message-circle-outline':'clock-outline'"
[nbPopover]="template" nbPopoverTrigger="hover" [status]="participant.before>8.64e+7?(participant.before>2.592e+8?'success':'warning'):'danger'">
style="width: 0.75em; height: 0.75em;" icon="message-circle-outline" status="info">
</nb-icon> </nb-icon>
<span *ngIf="participant.rank=='Trial'" style="font-size: 9px;"> <span *ngIf="participant.rank=='Trial'" style="font-size: 9px;">
Trial Trial
</span> </span>
@@ -129,16 +129,15 @@
<p style="white-space: pre-line;"> <p style="white-space: pre-line;">
{{participant.memo}} {{participant.memo}}
</p> </p>
{{participant.timestamp | date : 'HH:mm EEE MMM d'}} {{participant.timestamp | date : 'HH:mm EEE MMM d'}} ({{participant.before | date : 'dd'}} days before start)
</div> </div>
</ng-template> </ng-template>
<nb-icon *ngIf="participant.memo == null || participant.memo == ''" <nb-icon
[nbPopover]="template" nbPopoverTrigger="hover" [nbPopover]="template"
style="width: 0.75em; height: 0.75em;" icon="clock-outline"></nb-icon> nbPopoverTrigger="hover"
style="width: 0.75em; height: 0.75em;"
<nb-icon *ngIf="participant.memo != null && participant.memo != ''" [icon]="participant.memo != null && participant.memo != ''?'message-circle-outline':'clock-outline'"
[nbPopover]="template" nbPopoverTrigger="hover" [status]="participant.before>8.64e+7?(participant.before>2.592e+8?'success':'warning'):'danger'">
style="width: 0.75em; height: 0.75em;" icon="message-circle-outline" status="info">
</nb-icon> </nb-icon>
<span *ngIf="participant.rank=='Trial'" style="font-size: 9px;"> <span *ngIf="participant.rank=='Trial'" style="font-size: 9px;">
Trial Trial
@@ -174,17 +173,17 @@
<p style="white-space: pre-line;"> <p style="white-space: pre-line;">
{{participant.memo}} {{participant.memo}}
</p> </p>
{{participant.timestamp | date : 'HH:mm EEE MMM d'}} {{participant.timestamp | date : 'HH:mm EEE MMM d'}} ({{participant.before | date : 'dd'}} days before start)
</div> </div>
</ng-template> </ng-template>
<nb-icon *ngIf="participant.memo == null || participant.memo == ''" <nb-icon
[nbPopover]="template" nbPopoverTrigger="hover" [nbPopover]="template"
style="width: 0.75em; height: 0.75em;" icon="clock-outline"></nb-icon> nbPopoverTrigger="hover"
style="width: 0.75em; height: 0.75em;"
<nb-icon *ngIf="participant.memo != null && participant.memo != ''" [icon]="participant.memo != null && participant.memo != ''?'message-circle-outline':'clock-outline'"
[nbPopover]="template" nbPopoverTrigger="hover" [status]="participant.before>8.64e+7?(participant.before>2.592e+8?'success':'warning'):'danger'">
style="width: 0.75em; height: 0.75em;" icon="message-circle-outline" status="info">
</nb-icon> </nb-icon>
<span *ngIf="participant.rank=='Trial'" style="font-size: 9px;"> <span *ngIf="participant.rank=='Trial'" style="font-size: 9px;">
Trial Trial
</span> </span>
@@ -213,7 +212,7 @@
<nb-list class=""> <nb-list class="">
<nb-list-item *ngFor="let item of displayedtokens | keyvalue"> <nb-list-item *ngFor="let item of displayedtokens | keyvalue">
<table> <table style="width: 100%;">
<tr> <tr>
<td> <td>
<wowhead [item]="item.value[0]"></wowhead><br /> <wowhead [item]="item.value[0]"></wowhead><br />
@@ -221,30 +220,29 @@
</td> </td>
</tr> </tr>
<tr> <tr>
<td> <td class="row">
<div class="row"> <div *ngFor="let token of item.value" class="col-12 col-md-6 col-xl-4"
<div *ngFor="let token of item.value" class="col-12 col-md-6 col-xl-4"> style="white-space: nowrap;">
<span <span
[ngStyle]="{'text-decoration': token.rank=='Trial'? 'line-through' : 'none currentcolor solid' }"> [ngStyle]="{'text-decoration': token.rank=='Trial'? 'line-through' : 'none currentcolor solid' }">
<span style="text-transform: capitalize; white-space: nowrap;"> <span style="text-transform: capitalize;">
[ {{token.level}} ]&nbsp; [ {{token.level}} ]&nbsp;
<a [routerLink]="'/frontcraft/character/'+token.charactername" <a [routerLink]="'/frontcraft/character/'+token.charactername"
[ngStyle]="{'color':token.level>=10?'#ff8000':token.level>=8?'#a335ee':token.level>=6?'#0070dd':token.level>=4?'#1eff00':token.level>=2?'#ffffff':'#9d9d9d'}"> [ngStyle]="{'color':token.level>=10?'#ff8000':token.level>=8?'#a335ee':token.level>=6?'#0070dd':token.level>=4?'#1eff00':token.level>=2?'#ffffff':'#9d9d9d'}">
{{token.charactername}} {{token.charactername}}
</a> </a>
</span>
</span> </span>
<ng-template #tooltip> </span>
<div style="color:white"> <ng-template #tooltip>
Becomes valid when promoted to Raider <div style="color:white">
</div> Becomes valid when promoted to Raider
</ng-template> </div>
<span *ngIf="token.rank=='Trial'" style="font-size: 9px;" </ng-template>
[nbPopover]="tooltip" nbPopoverTrigger="hover" <span *ngIf="token.rank=='Trial'" style="font-size: 9px;"
nbPopoverPlacement="top"> [nbPopover]="tooltip" nbPopoverTrigger="hover"
Trial nbPopoverPlacement="top">
</span><br /> &nbsp;Trial
</div> </span><br />
</div> </div>
</td> </td>
@@ -1,4 +1,4 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit, Injector } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute, Router } from '@angular/router';
import { RaidData, Raid, Signup, Character, Spec, Item, SRToken } from '../../../../../../backend/Types/Types'; import { RaidData, Raid, Signup, Character, Spec, Item, SRToken } from '../../../../../../backend/Types/Types';
import { NbToastrService, NbDialogService } from '@nebular/theme'; import { NbToastrService, NbDialogService } from '@nebular/theme';
@@ -6,202 +6,214 @@ import { FrontcraftCharacerpickerComponent } from './characterpicker.component';
import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs'; import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
import { FrontcraftBuyTokenComponent } from '../shop/buytoken.component'; import { FrontcraftBuyTokenComponent } from '../shop/buytoken.component';
import { allItems } from '../../../../../../backend/Types/Items'; import { allItems } from '../../../../../../backend/Types/Items';
import { IApiService } from '../../services/ApiService'; import { IApiService } from '../../services/ApiService/ApiService';
import { UpdatingComponent } from '../../UpdatingComponent'; import { UpdatingComponent } from '../../UpdatingComponent';
import { LoggerService } from '../../services/logger.service'; import { LoggerService } from '../../services/LoggerService/logger.service';
import { FlashService } from '../../services/flash-service';
@Component({ @Component({
selector: 'raid', selector: 'raid',
templateUrl: './raid.component.html', templateUrl: './raid.component.html',
}) })
export class FrontcraftRaidComponent export class FrontcraftRaidComponent
extends UpdatingComponent extends UpdatingComponent
implements OnInit{ implements OnInit {
canSignup = false now = Date.now()
isSignedup = false canSignup = false
islate = false isSignedup = false
isTier = false islate = false
reservesShown = true isTier = false
manageRaid reservesShown = true
mySignup: (Signup & Character & Spec) manageRaid
mySignup: (Signup & Character & Spec)
raid: RaidData = <any>{ raid: RaidData = <any>{
participants:{ participants: {
Druid: [], Druid: [],
Hunter: [], Hunter: [],
Mage: [], Mage: [],
Paladin: [], Paladin: [],
Priest: [], Priest: [],
Rogue: [], Rogue: [],
Shaman: [], Shaman: [],
Warlock: [], Warlock: [],
Warrior: [], Warrior: [],
}, },
tanks: [], tanks: [],
healers: [], healers: [],
tokens:{}, tokens: {},
tier: 'null' tier: 'null'
}
tokens: { [itemname in string]: (Character & SRToken & Item)[] } = {}
displayedtokens = {}
search = ""
constructor(
injector: Injector,
private api: IApiService,
private route: ActivatedRoute,
private router: Router,
private dialogService: NbDialogService,
private toast: NbToastrService,
private flash: FlashService,
private logger: LoggerService
) {
super(injector)
}
ngOnInit() {
this.manageRaid = this.api.get('manageRaid')
const signupFeature = this.api.get('signup')
if (signupFeature) {
this.canSignup = true
} }
tokens: {[itemname in string]: (Character & SRToken & Item)[]} = {} this.refresh().then(() => {
displayedtokens = {} this.subscribe(String(this.raid.id), (data: RaidData) => this.display(data).then(_ =>
search = "" this.flash.show()
))
})
}
constructor( itemSelect = async (item) => {
private api: IApiService, this.dialogService.open(FrontcraftBuyTokenComponent, {
private route: ActivatedRoute, context: {
private router: Router, item: item,
private dialogService : NbDialogService, signup: this.mySignup,
private toast: NbToastrService, tier: this.raid.tier,
logger: LoggerService characterName: this.mySignup.charactername
){
super(router, api, logger)
}
ngOnInit(){
this.manageRaid = this.api.get('manageRaid')
const signupFeature = this.api.get('signup')
if(signupFeature){
this.canSignup = true
} }
}).onClose.subscribe(() => {
this.refresh().then(() => { this.refresh().then(() => {
this.subscribe(String(this.raid.id), (data: RaidData) => this.display(data)) this.reservesShown = true
}) })
} })
}
itemSelect = async(item) => { signup = async () => {
this.dialogService.open(FrontcraftBuyTokenComponent, { const signupFeature = this.api.get('signup')
context: { if (!signupFeature) return
item: item,
signup: this.mySignup, this.dialogService.open(FrontcraftCharacerpickerComponent, {
tier: this.raid.tier, closeOnBackdropClick: true,
characterName: this.mySignup.charactername closeOnEsc: true,
} context: {
}).onClose.subscribe(() => { raid: this.raid,
this.refresh().then(()=>{ }
this.reservesShown = true }).onClose.subscribe(() => {
}) this.refresh().then(() => {
this.reservesShown = false
}) })
} })
}
signup = async () => { async archiveRaid(raid: Raid) {
const signupFeature = this.api.get('signup') await this.manageRaid!.archiveRaid(raid)
if(!signupFeature) return this.toast.show('Raid archived', 'Success', { status: 'success' })
this.router.navigateByUrl('/frontcraft/archive/' + raid.id)
}
this.dialogService.open(FrontcraftCharacerpickerComponent, { async startRaid(raid: Raid) {
closeOnBackdropClick: true, await this.manageRaid!.startRaid(raid)
closeOnEsc: true, this.toast.show('Raid started', 'Success', { status: 'success' })
context: { this.router.navigateByUrl('/frontcraft/archive/' + raid.id)
raid: this.raid, }
}
}).onClose.subscribe(() => {
this.refresh().then(()=>{
this.reservesShown = false
})
})
}
async archiveRaid(raid:Raid){ unsign = async () => {
await this.manageRaid!.archiveRaid(raid) const signupFeature = this.api.get('signup')
this.toast.show('Raid archived', 'Success', { status: 'success' }) if (!signupFeature) return
this.router.navigateByUrl('/frontcraft/archive/'+raid.id)
}
async startRaid(raid:Raid){ await signupFeature.unsign(this.api.getAuth().token.value, {
await this.manageRaid!.startRaid(raid) ...this.mySignup,
this.toast.show('Raid started', 'Success', { status: 'success' }) id: this.mySignup.characterid,
this.router.navigateByUrl('/frontcraft/archive/'+raid.id) }, this.raid)
} this.toast.show('Success', 'Unsigned', { status: 'success' })
}
unsign = async () => { setLate = async (value: boolean) => {
const signupFeature = this.api.get('signup') const auth = this.api.getAuth()
if(!signupFeature) return const signup = this.api.get('signup')
if (!signup) return
await signupFeature.unsign(this.api.getAuth().token.value, { await signup.sign(auth.token.value, {
...this.mySignup, ...this.mySignup,
id: this.mySignup.characterid, id: this.mySignup.characterid,
}, this.raid) }, this.raid, value, this.mySignup.memo)
this.toast.show('Success', 'Unsigned', { status: 'success' }) this.toast.show('Signup', 'Success', { status: 'success' })
} }
setLate = async (value:boolean) => { adminUnsign = async (character: Character) => {
const auth = this.api.getAuth() const manage = this.api.get('manageRaid')
const signup = this.api.get('signup') if (!manage) return
if(!signup) return await manage.adminUnsign({
...character,
id: character['characterid']
}, this.raid)
}
await signup.sign(auth.token.value, { refresh = async () => {
...this.mySignup, const param = this.route.snapshot.paramMap.get('id');
id: this.mySignup.characterid, const raidManager = this.api.get('RaidManager')
}, this.raid, value, this.mySignup.memo)
this.toast.show('Signup', 'Success', { status: 'success' })
}
adminUnsign = async(character:Character) => { try {
const manage = this.api.get('manageRaid')
if(!manage) return
await manage.adminUnsign({
...character,
id: character['characterid']
}, this.raid)
}
refresh = async () => {
const param = this.route.snapshot.paramMap.get('id');
const raidManager = this.api.get('RaidManager')
const raiddata = await raidManager.getRaidData(<any>{ const raiddata = await raidManager.getRaidData(<any>{
id: param id: param
}) })
this.display(raiddata) await this.display(raiddata)
} catch (e) {
this.router.navigate(["/"])
}
}
display = async (raiddata: RaidData) => {
this.logger.log(raiddata)
this.isTier = allItems[raiddata.tier] != null
this.raid = raiddata
this.tokens = raiddata.tokens;
[...raiddata.tanks, ...raiddata.healers, ...Object.values(raiddata.participants).flat()].forEach(p => {
p['color'] = getClassColor(p.class)
p['before'] = Number.parseInt(this.raid.start) - Date.parse(p.timestamp)
})
const user = this.api.getCurrentUser()
const matchingSignup = Object.values(raiddata.participants).flat().find(char => user && char.userid === user.id!)
if (matchingSignup) {
this.mySignup = matchingSignup
this.isSignedup = true
this.mySignup['status'] = matchingSignup['benched'] ? 'Bench' : matchingSignup['late'] ? 'Late' : 'Attending'
} else {
this.isSignedup = false
this.mySignup = null
} }
display = async (raiddata:RaidData) => { this.changeSearch()
this.isTier = allItems[raiddata.tier] != null }
this.raid = raiddata changeSearch() {
this.tokens = raiddata.tokens; if (!this.search || this.search == "") {
this.displayedtokens = this.tokens
[...raiddata.tanks, ...raiddata.healers, ...Object.values(raiddata.participants).flat()].forEach(p => { } else {
p['color'] = getClassColor(p.class) this.displayedtokens = {}
}) Object.entries(this.tokens).forEach((e: [string /*itemname*/, (Character & SRToken & Item)[]]) => {
const filteredTokens = e[1].filter(item => {
const user = this.api.getCurrentUser() return item.itemname.toLocaleLowerCase().includes(this.search.toLocaleLowerCase())
const matchingSignup = Object.values(raiddata.participants).flat().find(char => user && char.userid === user.id!)
if(matchingSignup){
this.mySignup = matchingSignup
this.isSignedup = true
this.mySignup['status'] = matchingSignup['benched']?'Bench':matchingSignup['late']?'Late':'Attending'
}else{
this.isSignedup = false
this.mySignup = null
}
this.changeSearch()
}
changeSearch(){
if(!this.search || this.search == ""){
this.displayedtokens = this.tokens
}else{
this.displayedtokens = {}
Object.entries(this.tokens).forEach((e: [string /*itemname*/, (Character & SRToken & Item)[]]) => {
const filteredTokens = e[1].filter(item => {
return item.itemname.toLocaleLowerCase().includes(this.search.toLocaleLowerCase())
})
if(filteredTokens.length > 0)
this.displayedtokens[e[0]] = filteredTokens
}) })
} if (filteredTokens.length > 0)
this.displayedtokens[e[0]] = filteredTokens
})
} }
}
setBench(signup:Signup){ setBench(signup: Signup) {
this.manageRaid.setBenched({ this.manageRaid.setBenched({
characterid: signup.characterid, characterid: signup.characterid,
raidid: signup.raidid, raidid: signup.raidid,
late: false, late: false,
benched: !signup.benched benched: !signup.benched
}).then(_ => this.refresh()) }).then(_ => this.refresh())
} }
} }
@@ -1,8 +1,8 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { Raid, RaidData } from '../../../../../../backend/Types/Types'; import { Raid, RaidData } from '../../../../../../backend/Types/Types';
import { NbDialogRef } from '@nebular/theme'; import { NbDialogRef, DARK_THEME } from '@nebular/theme';
import { Tiers, _Tiers } from '../../../../../../backend/Types/Items'; import { Tiers, _Tiers } from '../../../../../../backend/Types/Items';
import { IApiService } from '../../services/ApiService'; import { IApiService } from '../../services/ApiService/ApiService';
const ONE_MINUTE = 60000 const ONE_MINUTE = 60000
const ONE_HOUR = 60 * ONE_MINUTE const ONE_HOUR = 60 * ONE_MINUTE
@@ -34,7 +34,6 @@ export class FrontcraftCreateRaidsComponent implements OnInit {
} }
onTierSelect(){ onTierSelect(){
} }
onTemplateSelect(){ onTemplateSelect(){
@@ -62,7 +61,7 @@ export class FrontcraftCreateRaidsComponent implements OnInit {
const manage = this.api.get('manageRaid') const manage = this.api.get('manageRaid')
if(!manage) return if(!manage) return
await manage.createRaid(raid) const dbraid = await manage.createRaid(raid)
this.dialogRef.close() this.dialogRef.close()
} }
} }
@@ -6,30 +6,33 @@
<nb-list nbInfiniteList listenWindowScroll [threshold]="500"> <nb-list nbInfiniteList listenWindowScroll [threshold]="500">
<nb-list-item *ngFor="let raid of raids" class="raidlist"> <nb-list-item *ngFor="let raid of raids" class="raidlist">
<a [routerLink]="'/frontcraft/raid/'+raid.id"> <a [routerLink]="'/frontcraft/raid/'+raid.id">
<div class="row"> <table>
<table> <tr>
<tr> <td rowspan="2" style="padding-right: 20px;">
<td rowspan="2" style="padding-right: 20px;"> <img [src]="'/assets/images/'+(raid.tier || 'null').toLowerCase()+'.png'"
<img [src]="'/assets/images/'+(raid.tier || 'null').toLowerCase()+'.png'" style="max-width: 50px; object-fit: contain" />
style="max-width: 50px; object-fit: contain" /> </td>
</td> <td>
<h4> <h4>
{{raid.title}} {{raid.title}}
</h4> </h4>
</tr> </td>
<tr> </tr>
<td style="padding-right: 25px; white-space: nowrap; color: lightslategray;"> <tr class="row">
<nb-icon icon="checkmark-circle"></nb-icon>&nbsp;{{raid.signupcount}}&nbsp;/&nbsp;{{raid.size}}<br> <td class="col-3" style="padding-left:8px; padding-right: 25px; white-space: nowrap; color: lightslategray;">
</td> <nb-icon icon="checkmark-circle"></nb-icon>&nbsp;{{ raid.signupcount | number:'2.0' }}&nbsp;/&nbsp;{{raid.size}}
<td style="padding-right: 25px; white-space: nowrap; color: lightslategray;"> </td>
<nb-icon icon="clock-outline"></nb-icon>&nbsp;{{raid.start | date : 'HH:mm'}} <td class="col-3" style="padding-right: 25px; white-space: nowrap; color: lightslategray;">
</td> <nb-icon icon="person-remove-outline"></nb-icon>&nbsp;{{ raid.benchcount }}
<td style="padding-right: 25px; white-space: nowrap; color: lightslategray;"> </td>
<nb-icon icon="calendar-outline"></nb-icon>&nbsp;{{raid.start | date : 'EEE MMM d'}} <td class="col-3" style="padding-right: 25px; white-space: nowrap; color: lightslategray;">
</td> <nb-icon icon="clock-outline"></nb-icon>&nbsp;{{raid.start | date : 'HH:mm'}}
</tr> </td>
</table> <td class="col-3" style="padding-right: 25px; white-space: nowrap; color: lightslategray;">
</div> <nb-icon icon="calendar-outline"></nb-icon>&nbsp;{{raid.start | date : 'EEE MMM d'}}
</td>
</tr>
</table>
</a> </a>
</nb-list-item> </nb-list-item>
</nb-list> </nb-list>
@@ -40,30 +43,33 @@
<nb-list nbInfiniteList listenWindowScroll [threshold]="500"> <nb-list nbInfiniteList listenWindowScroll [threshold]="500">
<nb-list-item *ngFor="let raid of oldraids" [routerLink]="'/frontcraft/archive/'+raid.id"> <nb-list-item *ngFor="let raid of oldraids" [routerLink]="'/frontcraft/archive/'+raid.id">
<a [routerLink]="'/frontcraft/archive/'+raid.id"> <a [routerLink]="'/frontcraft/archive/'+raid.id">
<div class="row"> <table style="width: 100%;">
<table>
<tr> <tr>
<td rowspan="2" style="padding-right: 20px;"> <td rowspan="2" style="padding-right: 20px;">
<img [src]="'/assets/images/'+(raid.tier || 'null').toLowerCase()+'.png'" <img [src]="'/assets/images/'+(raid.tier || 'null').toLowerCase()+'.png'"
style="max-width: 50px;;object-fit: contain; filter: grayscale(75%)" /> style="max-width: 50px;;object-fit: contain; filter: grayscale(75%)" />
</td> </td>
<h4> <td>
{{raid.title}} <h4>
</h4> {{raid.title}}
</tr> </h4>
<tr>
<td style="padding-right: 25px; white-space: nowrap; color: lightslategray;">
<nb-icon icon="checkmark-circle"></nb-icon>&nbsp;{{raid.signupcount}}&nbsp;/&nbsp;{{raid.size}}<br>
</td> </td>
<td style="padding-right: 25px; white-space: nowrap; color: lightslategray;"> </tr>
<tr class="row">
<td class="col-3" style="padding-left:8px; padding-right: 25px; white-space: nowrap; color: lightslategray;">
<nb-icon icon="checkmark-circle"></nb-icon>&nbsp;{{ raid.signupcount | number:'2.0' }}&nbsp;/&nbsp;{{raid.size}}
</td>
<td class="col-3" style="padding-right: 25px; white-space: nowrap; color: lightslategray;">
<nb-icon icon="person-remove-outline"></nb-icon>&nbsp;{{ raid.participants.bench.length }}
</td>
<td class="col-3" style="padding-right: 25px; white-space: nowrap; color: lightslategray;">
<nb-icon icon="clock-outline"></nb-icon>&nbsp;{{raid.start | date : 'HH:mm'}} <nb-icon icon="clock-outline"></nb-icon>&nbsp;{{raid.start | date : 'HH:mm'}}
</td> </td>
<td style="padding-right: 25px; white-space: nowrap; color: lightslategray;"> <td class="col-3" style="padding-right: 25px; white-space: nowrap; color: lightslategray;">
<nb-icon icon="calendar-outline"></nb-icon>&nbsp;{{raid.start | date : 'EEE MMM d'}} <nb-icon icon="calendar-outline"></nb-icon>&nbsp;{{raid.start | date : 'EEE MMM d'}}
</td> </td>
</tr> </tr>
</table> </table>
</div>
</a> </a>
</nb-list-item> </nb-list-item>
</nb-list> </nb-list>
@@ -1,10 +1,11 @@
import { Component, OnInit, OnDestroy } from '@angular/core'; import { Component, OnInit, OnDestroy, Injector } from '@angular/core';
import { NbDialogService } from '@nebular/theme'; import { NbDialogService, NbToastrService } from '@nebular/theme';
import { FrontcraftCreateRaidsComponent } from './createraid.compontent'; import { FrontcraftCreateRaidsComponent } from './createraid.compontent';
import { Router, NavigationStart } from '@angular/router'; import { Router, NavigationStart } from '@angular/router';
import { IApiService } from '../../services/ApiService'; import { IApiService } from '../../services/ApiService/ApiService';
import { UpdatingComponent } from '../../UpdatingComponent'; import { UpdatingComponent } from '../../UpdatingComponent';
import { LoggerService } from '../../services/logger.service'; import { LoggerService } from '../../services/LoggerService/logger.service';
import { FlashService } from '../../services/flash-service';
@Component({ @Component({
selector: 'raids', selector: 'raids',
@@ -12,8 +13,8 @@ import { LoggerService } from '../../services/logger.service';
styleUrls: ['raids.component.scss'], styleUrls: ['raids.component.scss'],
}) })
export class FrontcraftRaidsComponent export class FrontcraftRaidsComponent
extends UpdatingComponent extends UpdatingComponent
implements OnInit { implements OnInit {
manageRaid manageRaid
@@ -22,20 +23,22 @@ implements OnInit {
pageSize = 10; pageSize = 10;
constructor( constructor(
injector: Injector,
private api: IApiService, private api: IApiService,
router: Router,
private dialogService: NbDialogService, private dialogService: NbDialogService,
logger: LoggerService private flash: FlashService,
) { ) {
super(router, api, logger) super(injector)
} }
ngOnDestroy(){ ngOnDestroy() {
super.ngOnDestroy() super.ngOnDestroy()
} }
async ngOnInit() { async ngOnInit() {
this.subscribe("raids", () => this.refresh()) this.subscribe("raids", () => this.refresh().then(_ =>
this.flash.show()
))
this.manageRaid = this.api.get('manageRaid') this.manageRaid = this.api.get('manageRaid')
this.refresh() this.refresh()
@@ -1,6 +1,6 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs'; import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
import { IApiService } from '../../services/ApiService'; import { IApiService } from '../../services/ApiService/ApiService';
@Component({ @Component({
selector: 'rules', selector: 'rules',
@@ -3,7 +3,7 @@ import { NbToastrService, NbDialogRef } from '@nebular/theme';
import { Item, Character, SRToken, Signup } from '../../../../../../backend/Types/Types'; import { Item, Character, SRToken, Signup } from '../../../../../../backend/Types/Types';
import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs'; import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
import { _Tiers, Tiers } from '../../../../../../backend/Types/Items'; import { _Tiers, Tiers } from '../../../../../../backend/Types/Items';
import { IApiService } from '../../services/ApiService'; import { IApiService } from '../../services/ApiService/ApiService';
@Component({ @Component({
selector: 'buyToken', selector: 'buyToken',
@@ -1,7 +1,7 @@
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import { ClientApiService } from '../../services/client-login-api'; import { ClientApiService } from '../../services/ApiService/client-login-api';
import { Item, Character } from '../../../../../../backend/Types/Types'; import { Item, Character } from '../../../../../../backend/Types/Types';
import { IApiService } from '../../services/ApiService'; import { IApiService } from '../../services/ApiService/ApiService';
@Component({ @Component({
selector: 'itemselect', selector: 'itemselect',
@@ -8,7 +8,7 @@ import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
template: ` template: `
<span *ngIf="tooltipHtml"> <span *ngIf="tooltipHtml">
<ng-template #tooltip> <ng-template #tooltip>
<div style="color:white" [innerHTML]="tooltipHtml"> <div style="color:white; background-color:black; padding: 7px" [innerHTML]="tooltipHtml">
</div> </div>
</ng-template> </ng-template>
<span <span
@@ -5,7 +5,7 @@ import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
import { _Tiers } from '../../../../../../backend/Types/Items'; import { _Tiers } from '../../../../../../backend/Types/Items';
import { _Rank } from '../../../../../../backend/Types/Types'; import { _Rank } from '../../../../../../backend/Types/Types';
import { NbToastrService } from '@nebular/theme'; import { NbToastrService } from '@nebular/theme';
import { hash, IApiService } from '../../services/ApiService'; import { hash, IApiService } from '../../services/ApiService/ApiService';
@Component({ @Component({
selector: 'user-component', selector: 'user-component',
@@ -1,7 +1,7 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { _Rank, _Class, _Race, RPCPermission } from '../../../../../../backend/Types/Types' import { _Rank, _Class, _Race, RPCPermission } from '../../../../../../backend/Types/Types'
import { NbToastrService } from '@nebular/theme'; import { NbToastrService } from '@nebular/theme';
import { IApiService } from '../../services/ApiService'; import { IApiService } from '../../services/ApiService/ApiService';
@Component({ @Component({
@@ -1,5 +1,5 @@
import { Auth, FrontcraftIfc, FrontcraftFeatureIfc, User, SomeOf } from '../../../../../backend/Types/Types'; import { Auth, FrontcraftIfc, FrontcraftFeatureIfc, User, SomeOf } from '../../../../../../backend/Types/Types';
import { saltedHash } from '../../../../../backend/Util/hash'; import { saltedHash } from '../../../../../../backend/Util/hash';
import { RPCSocket, ConnectedSocket } from 'rpclibrary'; import { RPCSocket, ConnectedSocket } from 'rpclibrary';
export class IApiService{ export class IApiService{
@@ -9,7 +9,6 @@ export class IApiService{
initialize: () => Promise<any> initialize: () => Promise<any>
getCurrentUser: () => User getCurrentUser: () => User
login: (username: string, password: string) => Promise<RPCSocket & SomeOf<FrontcraftFeatureIfc>> login: (username: string, password: string) => Promise<RPCSocket & SomeOf<FrontcraftFeatureIfc>>
connectShoutbox: (callback:Function) => Promise<Function>
kick: () => Promise<void> kick: () => Promise<void>
logout: () => Promise<void> logout: () => Promise<void>
get: <K extends (keyof FrontcraftIfc | keyof FrontcraftFeatureIfc)>(feature : K) => K extends keyof FrontcraftIfc get: <K extends (keyof FrontcraftIfc | keyof FrontcraftFeatureIfc)>(feature : K) => K extends keyof FrontcraftIfc
@@ -1,10 +1,9 @@
import { Injectable } from "@angular/core"; import { Injectable } from "@angular/core";
import { RPCSocket } from 'rpclibrary/js/src/Frontend' import { RPCSocket } from 'rpclibrary/js/src/Frontend'
import { ConnectedSocket } from "rpclibrary" import { ConnectedSocket } from "rpclibrary"
import { Auth, User, _Class, FrontcraftFeatureIfc, SomeOf, FrontcraftIfc, } from '../../../../../backend/Types/Types' import { Auth, User, _Class, FrontcraftFeatureIfc, SomeOf, FrontcraftIfc, } from '../../../../../../backend/Types/Types'
import { ShoutMessage } from '../../../../../backend/Components/Shoutbox/Interface';
import { hash, IApiService, GuestUser } from './ApiService'; import { hash, IApiService, GuestUser } from './ApiService';
import { LoggerService } from './logger.service'; import { LoggerService } from '../LoggerService/logger.service';
declare const Cookies declare const Cookies
@@ -12,7 +11,7 @@ declare const Cookies
export class ClientApiService implements IApiService{ export class ClientApiService implements IApiService{
private socket:ConnectedSocket<FrontcraftIfc> private socket:ConnectedSocket<FrontcraftIfc>
private auth:Auth private auth:Auth
private privSocket: RPCSocket<SomeOf<FrontcraftFeatureIfc>> private privSocket: ConnectedSocket<SomeOf<FrontcraftFeatureIfc>>
constructor( constructor(
private logger: LoggerService private logger: LoggerService
@@ -22,7 +21,7 @@ export class ClientApiService implements IApiService{
getUnprivilegedSocket = () : ConnectedSocket<FrontcraftIfc> => this.socket getUnprivilegedSocket = () : ConnectedSocket<FrontcraftIfc> => this.socket
private getPrivilegedSocket = async (auth:Auth) : Promise<RPCSocket<SomeOf<FrontcraftFeatureIfc>>> => { private getPrivilegedSocket = async (auth:Auth) : Promise<ConnectedSocket<SomeOf<FrontcraftFeatureIfc>>> => {
if(this.privSocket) { if(this.privSocket) {
return this.privSocket return this.privSocket
} }
@@ -105,11 +104,6 @@ export class ClientApiService implements IApiService{
return sock return sock
} }
async connectShoutbox(callback:Function) : Promise<Function>{
const uuid = await this.get('Shoutbox').subscribe(callback)
return async (msg: ShoutMessage) => await this.get('Shoutbox').shout(uuid, msg)
}
kick = async () => { kick = async () => {
await this.logout() await this.logout()
location.reload() location.reload()
@@ -1,45 +1,48 @@
import { Injectable } from "@angular/core"; import { Injectable } from "@angular/core";
import {RPCSocket} from 'rpclibrary/js/src/Frontend' import { RPCSocket } from 'rpclibrary/js/src/Frontend'
import { Auth, User, _Class, FrontcraftFeatureIfc, SomeOf, FrontcraftIfc, } from '../../../../../backend/Types/Types' import { Auth, User, _Class, FrontcraftFeatureIfc, SomeOf, FrontcraftIfc, } from '../../../../../../backend/Types/Types'
import { hash, IApiService, GuestUser } from './ApiService'; import { hash, IApiService, GuestUser } from './ApiService';
import { LoggerService } from './logger.service'; import { LoggerService } from '../LoggerService/logger.service';
import { ConnectedSocket } from 'rpclibrary'; import { ConnectedSocket } from 'rpclibrary';
import { async } from '@angular/core/testing';
declare const Cookies declare const Cookies
@Injectable() @Injectable()
export class ServerApiService implements IApiService{ export class ServerApiService implements IApiService {
private socket:ConnectedSocket<FrontcraftIfc> private socket: ConnectedSocket<FrontcraftIfc>
private auth:Auth private auth: Auth
private privSocket: RPCSocket & SomeOf<FrontcraftFeatureIfc> private privSocket: RPCSocket & SomeOf<FrontcraftFeatureIfc>
constructor( constructor(
private logger: LoggerService private logger: LoggerService
){} ) { }
getUnprivilegedSocket = () : ConnectedSocket<FrontcraftIfc> => this.socket getUnprivilegedSocket = (): ConnectedSocket<FrontcraftIfc> => this.socket
get = <K extends (keyof FrontcraftIfc | keyof FrontcraftFeatureIfc)>(feature: K):
K extends keyof FrontcraftIfc ? FrontcraftIfc[K] :
K extends keyof FrontcraftFeatureIfc ? (FrontcraftFeatureIfc[K] | void) :
never => {
get = <K extends (keyof FrontcraftIfc | keyof FrontcraftFeatureIfc)>(feature : K) : K extends keyof FrontcraftIfc?FrontcraftIfc[K]:
K extends keyof FrontcraftFeatureIfc?(FrontcraftFeatureIfc[K] | void):
never => {
//@ts-ignore //@ts-ignore
return this.socket[feature] return this.socket[feature]
} }
getCurrentUser = () : User => { getCurrentUser = (): User => {
return GuestUser return GuestUser
} }
login = async (username: string, password: string) : Promise<RPCSocket & SomeOf<FrontcraftFeatureIfc>> => { login = async (username: string, password: string): Promise<RPCSocket & SomeOf<FrontcraftFeatureIfc>> => {
const pwHash = await hash(password) const pwHash = await hash(password)
let auth let auth
try{ try {
auth = await this.socket.UserManager.login(username, pwHash) auth = await this.socket.UserManager.login(username, pwHash)
}catch(e){ } catch (e) {
return return
} }
if(!auth){ if (!auth) {
await this.logout() await this.logout()
throw new Error("Login failed") throw new Error("Login failed")
} }
@@ -51,7 +54,7 @@ export class ServerApiService implements IApiService{
} }
async connectShoutbox(callback:Function) : Promise<Function>{ async connectShoutbox(callback: Function): Promise<Function> {
return this.logger.log return this.logger.log
} }
@@ -60,32 +63,32 @@ export class ServerApiService implements IApiService{
logout = async () => { logout = async () => {
Cookies.remove('token') Cookies.remove('token')
if(this.auth){ if (this.auth) {
try{ try {
await this.socket.UserManager.logout(this.auth.user.username, this.auth.token.value) await this.socket.UserManager.logout(this.auth.user.username, this.auth.token.value)
}catch(e){ } catch (e) {
this.logger.warn(e); this.logger.warn(e);
} }
} }
if(this.privSocket) this.privSocket.destroy() if (this.privSocket) this.privSocket.destroy()
this.privSocket = null this.privSocket = null
this.auth = null this.auth = null
} }
initialize = async () : Promise<any> => { initialize = async (): Promise<any> => {
if(this.socket){ if (this.socket) {
this.socket.destroy() this.socket.destroy()
this.socket = null this.socket = null
} }
try{ try {
let conn = new RPCSocket<FrontcraftIfc>(20000, window.location.hostname) let conn = new RPCSocket<FrontcraftIfc>(20000, window.location.hostname)
conn.on('close', async () => { conn.on('close', async () => {
}) })
this.socket = await conn.connect() this.socket = await conn.connect()
}catch(e){ } catch (e) {
this.logger.log(e); this.logger.log(e);
throw new Error("Websocket cannot connect") throw new Error("Websocket cannot connect")
} }
@@ -93,10 +96,10 @@ export class ServerApiService implements IApiService{
getAuth = () => this.auth getAuth = () => this.auth
async checkLogin() : Promise<boolean>{ async checkLogin(): Promise<boolean> {
if(!this.auth) return false if (!this.auth) return false
const valid = this.socket.UserManager.checkToken(this.auth.token.value, this.auth.user.rank) const valid = this.socket.UserManager.checkToken(this.auth.token.value, this.auth.user.rank)
if(valid) return true if (valid) return true
await this.logout() await this.logout()
return false return false
} }
@@ -0,0 +1,10 @@
export interface ILoggerService {
log,
warn,
error,
table,
}
export interface ICollapsableLoggerService extends ILoggerService{
collapsed
}
@@ -0,0 +1,30 @@
import { Injectable, SkipSelf, Optional } from "@angular/core";
import { environment } from '../../../../environments/environment';
import { ICollapsableLoggerService, ILoggerService } from './LoggerService';
@Injectable()
export class LoggerService implements ICollapsableLoggerService {
private logger = console
constructor(
) { }
log = (...args) => { this.LOG('log', args) }
warn = (...args) => { this.LOG('warn', args) }
error = (...args) => { this.LOG('error', args) }
table = (...args) => { this.LOG('table', args) }
collapsed = (groupname: string, type: keyof ILoggerService, ...args) => {
if (!environment.production) {
console.groupCollapsed(groupname)
this[type].apply(this.logger, args)
console.groupEnd()
}
}
private LOG(type, ...args) {
if (!environment.production) {
this.logger[type].apply(this.logger, ...args)
}
}
}
@@ -0,0 +1,21 @@
import { Injectable, Inject } from '@angular/core';
import { DOCUMENT } from '@angular/common';
@Injectable()
export class FlashService {
private displaying = false
constructor(@Inject(DOCUMENT) private document: Document) { }
show(durationMs = 250) {
if (this.displaying) return
this.displaying = true
this.document.getElementById('glowbox').classList.toggle('glowing');
this.document.getElementById('glowbox').classList.toggle('not-glowing');
setTimeout(() => {
this.displaying = false
this.document.getElementById('glowbox').classList.toggle('glowing');
this.document.getElementById('glowbox').classList.toggle('not-glowing');
}, durationMs)
}
}
@@ -1,37 +0,0 @@
import { Injectable } from "@angular/core";
import { environment } from '../../../environments/environment';
interface ILoggerService{
log,
warn,
error,
table,
collapsed
}
@Injectable()
export class LoggerService implements ILoggerService {
constructor(
private logger = console
) { }
log = (...args) => { this.LOG('log', args) }
warn = (...args) => { this.LOG('warn', args) }
error = (...args) => { this.LOG('error', args) }
table = (...args) => { this.LOG('table', args) }
collapsed = (groupname: string, type: keyof ILoggerService, ...args) => {
if(type === "collapsed")
return this.log(args)
console.groupCollapsed(groupname)
this[type as any].apply(this.logger, args)
console.groupEnd()
}
private LOG(type, ...args) {
if (!environment.production) {
this.logger[type].apply(this.logger, ...args)
}
}
}
+48 -23
View File
@@ -1,35 +1,57 @@
<!doctype html> <!doctype html>
<html> <html>
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>Frontcraft</title> <title>Frontcraft</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Montserrat"> <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Montserrat">
<style> <style>
@import url('https://fonts.googleapis.com/css?family=Montserrat'); @import url('https://fonts.googleapis.com/css?family=Montserrat');
.loadTitle { .loadTitle {
font-family: 'Montserrat'; font-family: 'Montserrat';
text-align: center; text-align: center;
color: #FFF; color: #FFF;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
letter-spacing: 1px; letter-spacing: 1px;
padding-top: calc(50vh - 120px); padding-top: calc(50vh - 120px);
} }
.loadH { .loadH {
background-image: url('https://media.giphy.com/media/26BROrSHlmyzzHf3i/giphy.gif'); background-image: url('https://media.giphy.com/media/26BROrSHlmyzzHf3i/giphy.gif');
background-size: cover; background-size: cover;
color: transparent; color: transparent;
background-clip: text; background-clip: text;
-moz-background-clip: text; -moz-background-clip: text;
-webkit-background-clip: text; -webkit-background-clip: text;
text-transform: uppercase; text-transform: uppercase;
font-size: min(10vw, 120px); font-size: min(10vw, 120px);
margin: 10px 0; margin: 10px 0;
} }
#glowbox {
pointer-events: none;
z-index: 10000000;
position: absolute;
width: 100%;
height: 100%;
-webkit-box-shadow: inset 0px 33px 38px -30px rgba(255, 255, 255, 0.71);
-moz-box-shadow: inset 0px 33px 38px -30px rgba(255, 255, 255, 0.71);
box-shadow: inset 0px 33px 38px -30px rgba(255, 255, 255, 0.71);
}
#glowbox.not-glowing {
opacity: 0;
transition: opacity 0.25s;
}
#glowbox.glowing {
opacity: 1;
transition: opacity 0.25s;
}
</style> </style>
<base href="/"> <base href="/">
@@ -38,7 +60,9 @@
<link rel="icon" type="image/png" href="favicon.png"> <link rel="icon" type="image/png" href="favicon.png">
<link rel="icon" type="image/x-icon" href="favicon.ico"> <link rel="icon" type="image/x-icon" href="favicon.ico">
</head> </head>
<body> <body>
<div id="glowbox" class="not-glowing"></div>
<ngx-app></ngx-app> <ngx-app></ngx-app>
<div id="nb-global-spinner" class="spinner" style="background-color: #111; height: 100vh;"> <div id="nb-global-spinner" class="spinner" style="background-color: #111; height: 100vh;">
<div class="loadTitle"> <div class="loadTitle">
@@ -47,4 +71,5 @@
</div> </div>
</body> </body>
</html> </html>
+3 -3
View File
@@ -3,7 +3,7 @@ import { enableProdMode } from '@angular/core';
enableProdMode() enableProdMode()
export { AppServerModule } from './app/app.server.module'; export { AppServerModule } from './app/app.server.module';
import { IApiService } from './app/frontcraft/services/ApiService'; import { IApiService } from './app/frontcraft/services/ApiService/ApiService';
export { IApiService } export { IApiService }
export { ServerApiService } from './app/frontcraft/services/server-login-api'; export { ServerApiService } from './app/frontcraft/services/ApiService/server-login-api';
export { LoggerService } from './app/frontcraft/services/logger.service' export { LoggerService } from './app/frontcraft/services/LoggerService/logger.service'
+3 -3
View File
@@ -8,9 +8,9 @@ import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { FrontcraftAppModule } from './app/app.module'; import { FrontcraftAppModule } from './app/app.module';
import { environment } from './environments/environment'; import { environment } from './environments/environment';
import { IApiService } from "./app/frontcraft/services/ApiService" import { IApiService } from "./app/frontcraft/services/ApiService/ApiService"
import { ClientApiService } from './app/frontcraft/services/client-login-api'; import { ClientApiService } from './app/frontcraft/services/ApiService/client-login-api';
import { LoggerService } from './app/frontcraft/services/logger.service'; import { LoggerService } from './app/frontcraft/services/LoggerService/logger.service';
if (environment.production) { if (environment.production) {
enableProdMode(); enableProdMode();