work
This commit is contained in:
Generated
+38
-19
@@ -714,9 +714,9 @@
|
|||||||
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
|
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
|
||||||
},
|
},
|
||||||
"aws4": {
|
"aws4": {
|
||||||
"version": "1.8.0",
|
"version": "1.9.1",
|
||||||
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz",
|
||||||
"integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ=="
|
"integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug=="
|
||||||
},
|
},
|
||||||
"balanced-match": {
|
"balanced-match": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
@@ -1166,6 +1166,11 @@
|
|||||||
"safe-buffer": "^5.0.1"
|
"safe-buffer": "^5.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"circular-buffer": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/circular-buffer/-/circular-buffer-1.0.2.tgz",
|
||||||
|
"integrity": "sha1-+g4VLtYp92/iTd+J5y69AHhsWm4="
|
||||||
|
},
|
||||||
"class-utils": {
|
"class-utils": {
|
||||||
"version": "0.3.6",
|
"version": "0.3.6",
|
||||||
"resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
|
"resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
|
||||||
@@ -1465,6 +1470,11 @@
|
|||||||
"randomfill": "^1.0.3"
|
"randomfill": "^1.0.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"crypto-js": {
|
||||||
|
"version": "3.1.9-1",
|
||||||
|
"resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.9-1.tgz",
|
||||||
|
"integrity": "sha1-/aGedh/Ad+Af+/3G6f38WeiAbNg="
|
||||||
|
},
|
||||||
"cyclist": {
|
"cyclist": {
|
||||||
"version": "0.2.2",
|
"version": "0.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz",
|
||||||
@@ -5031,17 +5041,26 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"npm-bundled": {
|
"npm-bundled": {
|
||||||
"version": "1.0.6",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz",
|
||||||
"integrity": "sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g=="
|
"integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==",
|
||||||
|
"requires": {
|
||||||
|
"npm-normalize-package-bin": "^1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"npm-normalize-package-bin": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA=="
|
||||||
},
|
},
|
||||||
"npm-packlist": {
|
"npm-packlist": {
|
||||||
"version": "1.4.6",
|
"version": "1.4.8",
|
||||||
"resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.6.tgz",
|
"resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz",
|
||||||
"integrity": "sha512-u65uQdb+qwtGvEJh/DgQgW1Xg7sqeNbmxYyrvlNznaVTjV3E5P6F/EFjM+BVHXl7JJlsdG8A64M0XI8FI/IOlg==",
|
"integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"ignore-walk": "^3.0.1",
|
"ignore-walk": "^3.0.1",
|
||||||
"npm-bundled": "^1.0.1"
|
"npm-bundled": "^1.0.1",
|
||||||
|
"npm-normalize-package-bin": "^1.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"npm-run-path": {
|
"npm-run-path": {
|
||||||
@@ -5752,9 +5771,9 @@
|
|||||||
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
|
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
|
||||||
},
|
},
|
||||||
"psl": {
|
"psl": {
|
||||||
"version": "1.4.0",
|
"version": "1.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/psl/-/psl-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/psl/-/psl-1.7.0.tgz",
|
||||||
"integrity": "sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw=="
|
"integrity": "sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ=="
|
||||||
},
|
},
|
||||||
"public-encrypt": {
|
"public-encrypt": {
|
||||||
"version": "4.0.3",
|
"version": "4.0.3",
|
||||||
@@ -6111,9 +6130,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rpclibrary": {
|
"rpclibrary": {
|
||||||
"version": "1.6.2",
|
"version": "1.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/rpclibrary/-/rpclibrary-1.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/rpclibrary/-/rpclibrary-1.7.0.tgz",
|
||||||
"integrity": "sha512-lQTU4XkB9CSHz7YgtAcpVfyR5XrmTRX4P4eQjK6DDUjqKSFvJb5ChXjHnt1BcaNWbJ2VqmhCNVbcoyunJ2u7Rg==",
|
"integrity": "sha512-HIL5YzFF53fACOWvI403hJZnGYoXLJGrGc0n1HYZH6rnnfEaBcogemZrCbyoOvnG204LH882e8VdpB+WBTEY/g==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"bsock": "^0.1.9",
|
"bsock": "^0.1.9",
|
||||||
"http": "0.0.0",
|
"http": "0.0.0",
|
||||||
@@ -6518,9 +6537,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"sqlite3": {
|
"sqlite3": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.1.1.tgz",
|
||||||
"integrity": "sha512-RvqoKxq+8pDHsJo7aXxsFR18i+dU2Wp5o12qAJOV5LNcDt+fgJsc2QKKg3sIRfXrN9ZjzY1T7SNe/DFVqAXjaw==",
|
"integrity": "sha512-CvT5XY+MWnn0HkbwVKJAyWEMfzpAPwnTiB3TobA5Mri44SrTovmmh499NPQP+gatkeOipqPlBLel7rn4E/PCQg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"nan": "^2.12.1",
|
"nan": "^2.12.1",
|
||||||
"node-pre-gyp": "^0.11.0",
|
"node-pre-gyp": "^0.11.0",
|
||||||
|
|||||||
+4
-2
@@ -26,6 +26,8 @@
|
|||||||
"bsert": "0.0.10",
|
"bsert": "0.0.10",
|
||||||
"bsock": "^0.1.9",
|
"bsock": "^0.1.9",
|
||||||
"child-process-promise": "^2.2.1",
|
"child-process-promise": "^2.2.1",
|
||||||
|
"circular-buffer": "^1.0.2",
|
||||||
|
"crypto-js": "^3.1.9-1",
|
||||||
"debug": "^4.1.1",
|
"debug": "^4.1.1",
|
||||||
"express": "^4.16.4",
|
"express": "^4.16.4",
|
||||||
"frontblock": "^0.15.2",
|
"frontblock": "^0.15.2",
|
||||||
@@ -41,10 +43,10 @@
|
|||||||
"path": "^0.12.7",
|
"path": "^0.12.7",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.0",
|
"rimraf": "^3.0.0",
|
||||||
"rpclibrary": "^1.6.2",
|
"rpclibrary": "^1.7.0",
|
||||||
"simple-git": "^1.124.0",
|
"simple-git": "^1.124.0",
|
||||||
"spawn-sync": "^2.0.0",
|
"spawn-sync": "^2.0.0",
|
||||||
"sqlite3": "^4.1.0",
|
"sqlite3": "^4.1.1",
|
||||||
"trash": "^6.0.0",
|
"trash": "^6.0.0",
|
||||||
"tsyringe": "^4.0.1",
|
"tsyringe": "^4.0.1",
|
||||||
"upgiter": "^1.0.4",
|
"upgiter": "^1.0.4",
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { GuildManager } from '../Components/Guild/GuildManager';
|
|||||||
import { ItemManager } from '../Components/Item/ItemManager';
|
import { ItemManager } from '../Components/Item/ItemManager';
|
||||||
import { RaidManager } from '../Components/Raid/RaidManager';
|
import { RaidManager } from '../Components/Raid/RaidManager';
|
||||||
import { CharacterManager } from '../Components/Character/CharacterManager';
|
import { CharacterManager } from '../Components/Character/CharacterManager';
|
||||||
import { LoginManager } from '../Components/Login/LoginManager';
|
import { UserManager } from '../Components/User/UserManager';
|
||||||
import { RootComponent } from '../Injector/ServiceDecorator';
|
import { RootComponent } from '../Injector/ServiceDecorator';
|
||||||
import { TableDefinitionExporter } from '../Types/Interfaces';
|
import { TableDefinitionExporter } from '../Types/Interfaces';
|
||||||
import { AdminConf, TableDefiniton } from '../Types/Types';
|
import { AdminConf, TableDefiniton } from '../Types/Types';
|
||||||
@@ -19,18 +19,20 @@ 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';
|
||||||
|
|
||||||
|
|
||||||
const logger = getLogger("admin", 'debug')
|
const logger = getLogger("admin", 'debug')
|
||||||
|
|
||||||
@RootComponent({
|
@RootComponent({
|
||||||
implements: IAdmin,
|
injectable: IAdmin,
|
||||||
imports: [
|
injects: [
|
||||||
GuildManager,
|
GuildManager,
|
||||||
ItemManager,
|
ItemManager,
|
||||||
RaidManager,
|
RaidManager,
|
||||||
CharacterManager,
|
CharacterManager,
|
||||||
LoginManager
|
UserManager,
|
||||||
|
Shoutbox
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class FrontworkAdmin
|
export class FrontworkAdmin
|
||||||
@@ -169,7 +171,11 @@ implements TableDefinitionExporter, IAdmin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.knex = Knex(conf)
|
this.knex = Knex(conf)
|
||||||
|
if(conf.client === 'sqlite3'){
|
||||||
|
await this.knex.raw('PRAGMA foreign_keys = ON');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
this.getTableDefinitions()
|
this.getTableDefinitions()
|
||||||
//make unique by name
|
//make unique by name
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { RPCConfigLoader } from "../Components/RPCConfigLoader"
|
import { RPCConfigLoader } from "../Components/RPCConfigLoader"
|
||||||
import { AdminConf } from "../Types/Types"
|
import { AdminConf } from "../Types/Types"
|
||||||
import { RPCServer } from "rpclibrary"
|
import { RPCServer } from "rpclibrary"
|
||||||
import Knex = require("knex")
|
import * as Knex from "knex"
|
||||||
|
|
||||||
export class IAdmin{
|
export class IAdmin{
|
||||||
knex: Knex
|
knex: Knex
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
import { RPCInterface } from "rpclibrary";
|
import { RPCInterface } from "rpclibrary";
|
||||||
import { Inject, Module } from "../../Injector/ServiceDecorator";
|
import { Inject, Injectable } from "../../Injector/ServiceDecorator";
|
||||||
import { TableDefiniton, Character, Spec, User } from "../../Types/Types";
|
import { TableDefiniton, Character, Spec, User, Class, _Rank, Rank } from "../../Types/Types";
|
||||||
import { CharacterManagerIfc } from "./RPCInterface";
|
import { CharacterManagerIfc } from "./RPCInterface";
|
||||||
import { FrontworkComponent } from "../../Types/FrontworkComponent";
|
import { FrontworkComponent } from "../../Types/FrontworkComponent";
|
||||||
import { getSpecTableData, SpecT } from "../../Types/PlayerSpecs";
|
import { getSpecTableData, SpecT } from "../../Types/PlayerSpecs";
|
||||||
import { IAdmin } from "../../Admin/Interface";
|
import { IAdmin } from "../../Admin/Interface";
|
||||||
import { ILoginManager } from "../Login/Interface";
|
import { IUserManager } from "../User/Interface";
|
||||||
import { ICharacterManager } from "./Interface";
|
import { ICharacterManager } from "./Interface";
|
||||||
import { getLogger } from "log4js";
|
|
||||||
|
|
||||||
@Module(ICharacterManager)
|
@Injectable(ICharacterManager)
|
||||||
export class CharacterManager
|
export class CharacterManager
|
||||||
implements FrontworkComponent<CharacterManagerIfc, RPCInterface>, ICharacterManager{
|
implements FrontworkComponent<CharacterManagerIfc, RPCInterface>, ICharacterManager{
|
||||||
name = "CharacterManager" as "CharacterManager";
|
name = "CharacterManager" as "CharacterManager";
|
||||||
@@ -17,35 +16,20 @@ implements FrontworkComponent<CharacterManagerIfc, RPCInterface>, ICharacterMana
|
|||||||
@Inject(IAdmin)
|
@Inject(IAdmin)
|
||||||
private admin: IAdmin
|
private admin: IAdmin
|
||||||
|
|
||||||
@Inject(ILoginManager)
|
@Inject(IUserManager)
|
||||||
private loginManager : ILoginManager
|
private loginManager : IUserManager
|
||||||
|
|
||||||
exportRPCs = () => [
|
exportRPCs = () => [
|
||||||
{
|
this.getSpecId,
|
||||||
name: 'getSpecId' as 'getSpecId',
|
this.getCharacterByName,
|
||||||
call: this.getSpecId
|
this.getCharacters,
|
||||||
},{
|
this.getCharactersOfUser,
|
||||||
name: 'getCharacterByName' as 'getCharacterByName',
|
this.createCharacter,
|
||||||
call: this.getCharacterByName
|
this.getUserOfCharacter,
|
||||||
},{
|
this.getHeadCount
|
||||||
name: 'getCharacters' as 'getCharacters',
|
|
||||||
call: this.getCharacters
|
|
||||||
},{
|
|
||||||
name: 'getCharactersOfUser' as 'getCharactersOfUser',
|
|
||||||
call: this.getCharactersOfUser
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
|
|
||||||
exportRPCFeatures = () => [
|
exportRPCFeatures = () => [
|
||||||
{
|
|
||||||
name: "createCharacter",
|
|
||||||
exportRPCs: () => [
|
|
||||||
{
|
|
||||||
name: 'createCharacter',
|
|
||||||
call: this.createCharacter
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
|
|
||||||
getTableDefinitions = (): TableDefiniton[] => [
|
getTableDefinitions = (): TableDefiniton[] => [
|
||||||
@@ -58,6 +42,8 @@ implements FrontworkComponent<CharacterManagerIfc, RPCInterface>, ICharacterMana
|
|||||||
table.foreign("specid").references("specs.id")
|
table.foreign("specid").references("specs.id")
|
||||||
table.integer("userid").notNullable()
|
table.integer("userid").notNullable()
|
||||||
table.foreign("userid").references("users.id")
|
table.foreign("userid").references("users.id")
|
||||||
|
table.string("race").notNullable()
|
||||||
|
table.boolean('alt').defaultTo(false)
|
||||||
}
|
}
|
||||||
},{
|
},{
|
||||||
name: 'specs',
|
name: 'specs',
|
||||||
@@ -87,13 +73,16 @@ implements FrontworkComponent<CharacterManagerIfc, RPCInterface>, ICharacterMana
|
|||||||
return char
|
return char
|
||||||
}catch(e){
|
}catch(e){
|
||||||
console.log(e);
|
console.log(e);
|
||||||
|
|
||||||
}
|
}
|
||||||
throw new Error('Unable to create character')
|
throw new Error('Unable to create character')
|
||||||
}
|
}
|
||||||
|
|
||||||
getCharacters = async() : Promise<Character[]> => {
|
getCharacters = async() : Promise<(Character & Spec & User)[]> => {
|
||||||
return this.admin.knex.select('*').from('characters')
|
return this.admin.knex
|
||||||
|
.select('*')
|
||||||
|
.from('characters as c')
|
||||||
|
.join('specs as sp', 'c.specid', 'sp.id')
|
||||||
|
.join('users as u', 'c.userid', 'u.id')
|
||||||
}
|
}
|
||||||
|
|
||||||
getCharacterByName = async(charactername: string) : Promise<(Character & User & Spec) | void> => {
|
getCharacterByName = async(charactername: string) : Promise<(Character & User & Spec) | void> => {
|
||||||
@@ -101,7 +90,7 @@ implements FrontworkComponent<CharacterManagerIfc, RPCInterface>, ICharacterMana
|
|||||||
return await this.admin.knex('characters as c')
|
return await this.admin.knex('characters as c')
|
||||||
.join('specs as s', 's.id', '=', 'c.specid')
|
.join('specs as s', 's.id', '=', 'c.specid')
|
||||||
.join('users as u', 'u.id', '=', 'c.userid')
|
.join('users as u', 'u.id', '=', 'c.userid')
|
||||||
.select('charactername', 'class', 'specname', 'username', 'rank', 'locked', )
|
.select('c.id as id', 'charactername', 'race', 'specid', 'class', 'specname', 'username', 'rank')
|
||||||
.where('charactername', '=', charactername)
|
.where('charactername', '=', charactername)
|
||||||
.first()
|
.first()
|
||||||
}
|
}
|
||||||
@@ -111,10 +100,16 @@ implements FrontworkComponent<CharacterManagerIfc, RPCInterface>, ICharacterMana
|
|||||||
return await this.admin.knex('characters as c')
|
return await this.admin.knex('characters as c')
|
||||||
.join('users as u', 'u.id', '=', 'c.userid')
|
.join('users as u', 'u.id', '=', 'c.userid')
|
||||||
.join('specs as s', 's.id', '=', 'c.specid')
|
.join('specs as s', 's.id', '=', 'c.specid')
|
||||||
.select('class', 'charactername', 'class', 'specname')
|
.select('class', 'charactername', 'class', 'race', 'specname', 'userid', 'c.id as id', 'specid')
|
||||||
.where('u.username', '=', username)
|
.where('u.username', '=', username)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getUserOfCharacter = async(character: Character) : Promise<User> => {
|
||||||
|
return await this.admin.knex('users').where({
|
||||||
|
id: character.userid
|
||||||
|
}).first()
|
||||||
|
}
|
||||||
|
|
||||||
getSpecId = async <c extends keyof SpecT>(clazz: c, name: SpecT[c]) => await this.admin.knex
|
getSpecId = async <c extends keyof SpecT>(clazz: c, name: SpecT[c]) => await this.admin.knex
|
||||||
.from('specs')
|
.from('specs')
|
||||||
.select('id')
|
.select('id')
|
||||||
@@ -125,4 +120,20 @@ implements FrontworkComponent<CharacterManagerIfc, RPCInterface>, ICharacterMana
|
|||||||
.first()
|
.first()
|
||||||
.then(spec => spec.id)
|
.then(spec => spec.id)
|
||||||
|
|
||||||
|
getHeadCount = async(c:Class):Promise<number> => {
|
||||||
|
const cnt = await this.admin
|
||||||
|
.knex('characters as c')
|
||||||
|
.join('users as u', 'c.userid', '=', 'u.id')
|
||||||
|
.join('specs as s', 'c.specid', '=', 's.id')
|
||||||
|
.where({
|
||||||
|
class: c
|
||||||
|
}).andWhere(function(){
|
||||||
|
this.whereNotIn('u.rank', <Rank[]>[
|
||||||
|
'Guest'
|
||||||
|
])
|
||||||
|
this.whereNot('c.alt', '1')
|
||||||
|
})
|
||||||
|
.count('*')
|
||||||
|
return cnt[0]['count(*)'] as number
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,13 @@
|
|||||||
import { Character, Spec, User } from "../../Types/Types"
|
import { Character, Spec, User, Class } from "../../Types/Types"
|
||||||
import { SpecT } from "../../Types/PlayerSpecs"
|
import { SpecT } from "../../Types/PlayerSpecs"
|
||||||
|
|
||||||
|
|
||||||
export class ICharacterManager{
|
export class ICharacterManager{
|
||||||
createCharacter: (usertoken: string, char : Character) => Promise<Character>
|
createCharacter: (usertoken: string, char : Character) => Promise<Character>
|
||||||
getSpecId: <c extends keyof SpecT>(clazz: c, name: SpecT[c]) => Promise<number>
|
getSpecId: <c extends keyof SpecT>(clazz: c, name: SpecT[c]) => Promise<number>
|
||||||
getCharacters: () => Promise<Character[]>
|
getCharacters: () => Promise<(Character & Spec & User)[]>
|
||||||
getCharacterByName: (charactername: string) => Promise<(Character & User & Spec) | void>
|
getCharacterByName: (charactername: string) => Promise<(Character & User & Spec) | void>
|
||||||
getCharactersOfUser: (username: string) => Promise<(Character & Spec)[]>
|
getCharactersOfUser: (username: string) => Promise<(Character & Spec)[]>
|
||||||
|
getUserOfCharacter: (character:Character) => Promise<User>
|
||||||
|
getHeadCount: (clazz: Class) => Promise<number>
|
||||||
}
|
}
|
||||||
@@ -7,11 +7,12 @@ export type CharacterManagerIfc = {
|
|||||||
getCharacters : ICharacterManager['getCharacters']
|
getCharacters : ICharacterManager['getCharacters']
|
||||||
getCharacterByName : ICharacterManager['getCharacterByName']
|
getCharacterByName : ICharacterManager['getCharacterByName']
|
||||||
getCharactersOfUser: ICharacterManager['getCharactersOfUser']
|
getCharactersOfUser: ICharacterManager['getCharactersOfUser']
|
||||||
|
createCharacter: ICharacterManager['createCharacter']
|
||||||
|
getUserOfCharacter: ICharacterManager['getUserOfCharacter']
|
||||||
|
getHeadCount: ICharacterManager['getHeadCount']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type CharacterManagerFeatureIfc = {
|
export type CharacterManagerFeatureIfc = {
|
||||||
createCharacter: {
|
|
||||||
createCharacter: ICharacterManager['createCharacter']
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
import { RPCExporter } from "rpclibrary"
|
|
||||||
import { FrontworkAdmin } from "../../Admin/Admin"
|
|
||||||
import { TableDefiniton } from "../../Types/Types"
|
|
||||||
import { PrivilegedRPCExporter } from "../../Types/PrivilegedRPCExporter"
|
|
||||||
import { FrontworkComponent } from "../../Types/FrontworkComponent"
|
|
||||||
|
|
||||||
export class Debugger
|
|
||||||
implements FrontworkComponent<any,any>{
|
|
||||||
public admin: FrontworkAdmin
|
|
||||||
name = "Debugger"
|
|
||||||
|
|
||||||
|
|
||||||
constructor(private exporters: PrivilegedRPCExporter[]){
|
|
||||||
}
|
|
||||||
|
|
||||||
exportRPCs(){
|
|
||||||
|
|
||||||
return [{
|
|
||||||
name: 'getTable',
|
|
||||||
call: async(table:string) => this.admin.knex.select('*').from(table)
|
|
||||||
},
|
|
||||||
...this.exporters.flatMap(e => e.exportRPCs()),
|
|
||||||
...this.exporters.flatMap(e => e.exportRPCFeatures().flatMap(e => e.exportRPCs()))]
|
|
||||||
}
|
|
||||||
|
|
||||||
exportRPCFeatures(): RPCExporter<any, any, {}>[] {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
|
|
||||||
getTableDefinitions(): TableDefiniton[] {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { ConfigLoader } from "loadson";
|
import { ConfigLoader } from "loadson";
|
||||||
import { Inject, Module } from "../../Injector/ServiceDecorator";
|
import { Inject, Injectable } from "../../Injector/ServiceDecorator";
|
||||||
import { GuildManagerFeatureIfc, GuildManagerIfc } from "./RPCInterface";
|
import { GuildManagerFeatureIfc, GuildManagerIfc } from "./RPCInterface";
|
||||||
import { FrontworkComponent } from "../../Types/FrontworkComponent";
|
import { FrontworkComponent } from "../../Types/FrontworkComponent";
|
||||||
import { _Rank, Rank } from "../../Types/Types";
|
import { _Rank, Rank } from "../../Types/Types";
|
||||||
@@ -10,9 +10,9 @@ export type Guild = {
|
|||||||
name: string
|
name: string
|
||||||
realm: string
|
realm: string
|
||||||
description: string
|
description: string
|
||||||
}
|
};
|
||||||
|
|
||||||
@Module(IGuildManager)
|
@Injectable(IGuildManager)
|
||||||
export class GuildManager
|
export class GuildManager
|
||||||
implements FrontworkComponent<GuildManagerIfc, GuildManagerFeatureIfc>, IGuildManager{
|
implements FrontworkComponent<GuildManagerIfc, GuildManagerFeatureIfc>, IGuildManager{
|
||||||
|
|
||||||
@@ -32,26 +32,18 @@ implements FrontworkComponent<GuildManagerIfc, GuildManagerFeatureIfc>, IGuildMa
|
|||||||
}
|
}
|
||||||
}, "./config")
|
}, "./config")
|
||||||
|
|
||||||
exportRPCs = () => [{
|
exportRPCs = () => [
|
||||||
name: 'getHeadCount' as 'getHeadCount',
|
this.getHeadCount,
|
||||||
call: this.getHeadCount
|
this.getGuildInfo
|
||||||
},{
|
]
|
||||||
name: 'getGuildInfo' as 'getGuildInfo',
|
|
||||||
call: this.getGuildInfo
|
|
||||||
}]
|
|
||||||
|
|
||||||
exportRPCFeatures = () => [{
|
exportRPCFeatures = () => [{
|
||||||
name: 'manageGuild' as 'manageGuild',
|
name: 'manageGuild' as 'manageGuild',
|
||||||
exportRPCs: () => [{
|
exportRPCs: () => [
|
||||||
name: 'setName' as 'setName',
|
this.setName,
|
||||||
call: this.setName
|
this.setRealm,
|
||||||
},{
|
this.setDescription
|
||||||
name: 'setRealm' as 'setRealm',
|
]
|
||||||
call: this.setRealm
|
|
||||||
}, {
|
|
||||||
name: 'setDescription' as 'setDescription',
|
|
||||||
call: this.setDescription
|
|
||||||
}]
|
|
||||||
}]
|
}]
|
||||||
|
|
||||||
getTableDefinitions = () => []
|
getTableDefinitions = () => []
|
||||||
|
|||||||
@@ -1,6 +1,14 @@
|
|||||||
import { Item } from "../../Types/Types"
|
import { Item, Character, SRToken, SRPriority, Spec } from "../../Types/Types"
|
||||||
|
|
||||||
export class IItemManager{
|
export class IItemManager{
|
||||||
getItems: () => Promise<Item[]>
|
getItems: () => Promise<Item[]>
|
||||||
getItem: (name:string) => Promise<Item>
|
fetchItem: (name:string) => Promise<Item>
|
||||||
|
buyToken: (usertoken: string, charactername:string, itemname:string) => Promise<(SRToken & Character & Item) | void>
|
||||||
|
setPriority: (itemname:string, priority: any) => Promise<void>
|
||||||
|
calculatePriorities: (itemname: string, character:Character) => Promise<number>
|
||||||
|
deletePriority: (priority:SRPriority) => Promise<void>
|
||||||
|
getTokens: (character:Character) => Promise<SRToken[]>
|
||||||
|
getToken: (character:Character, item:Item) => Promise<(SRToken & Character & Item) | void>
|
||||||
|
getAllPriorities: () => Promise<(SRPriority & Spec & Item)[]>
|
||||||
|
wipeCurrencyAndItems: () => Promise<void>
|
||||||
}
|
}
|
||||||
@@ -1,19 +1,21 @@
|
|||||||
import { T1 } from "../../Types/Items";
|
import { T1 } from "../../Types/Items";
|
||||||
import { RPC } from "rpclibrary";
|
import { Inject, Injectable } from "../../Injector/ServiceDecorator";
|
||||||
import { Inject, Module } from "../../Injector/ServiceDecorator";
|
|
||||||
import { ItemManagerFeatureIfc, ItemManagerIfc } from "./RPCInterface";
|
import { ItemManagerFeatureIfc, ItemManagerIfc } from "./RPCInterface";
|
||||||
import { FrontworkComponent } from "../../Types/FrontworkComponent";
|
import { FrontworkComponent } from "../../Types/FrontworkComponent";
|
||||||
import { TableDefinitionExporter } from "../../Types/Interfaces";
|
import { TableDefinitionExporter } from "../../Types/Interfaces";
|
||||||
import { TableDefiniton, Item } from "../../Types/Types";
|
import { TableDefiniton, Item, User, Character, SRToken, SRPriority, Spec } from "../../Types/Types";
|
||||||
import { IAdmin } from "../../Admin/Interface";
|
import { IAdmin } from "../../Admin/Interface";
|
||||||
import { IItemManager } from "./Interface";
|
import { IItemManager } from "./Interface";
|
||||||
import { getLogger } from "log4js";
|
import { getLogger } from "log4js";
|
||||||
|
import { IUserManager } from "../User/Interface";
|
||||||
|
import { ICharacterManager } from "../Character/Interface";
|
||||||
|
import { join } from "path";
|
||||||
|
|
||||||
const fetch = require('node-fetch')
|
const fetch = require('node-fetch')
|
||||||
const xml2js = require('xml2js');
|
const xml2js = require('xml2js');
|
||||||
const parser = new xml2js.Parser(/* options */);
|
const parser = new xml2js.Parser(/* options */);
|
||||||
|
|
||||||
@Module(IItemManager)
|
@Injectable(IItemManager)
|
||||||
export class ItemManager
|
export class ItemManager
|
||||||
implements FrontworkComponent<ItemManagerIfc, ItemManagerFeatureIfc>, TableDefinitionExporter, IItemManager{
|
implements FrontworkComponent<ItemManagerIfc, ItemManagerFeatureIfc>, TableDefinitionExporter, IItemManager{
|
||||||
name = "ItemManager" as "ItemManager";
|
name = "ItemManager" as "ItemManager";
|
||||||
@@ -21,23 +23,49 @@ implements FrontworkComponent<ItemManagerIfc, ItemManagerFeatureIfc>, TableDefin
|
|||||||
@Inject(IAdmin)
|
@Inject(IAdmin)
|
||||||
private admin: IAdmin
|
private admin: IAdmin
|
||||||
|
|
||||||
exportRPCs(): RPC<any, any>[]{
|
@Inject(IUserManager)
|
||||||
return [{
|
private userManager: IUserManager
|
||||||
name: 'getItems',
|
|
||||||
call: this.getItems
|
|
||||||
},{
|
|
||||||
name: 'getItem',
|
|
||||||
call: this.getItem
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
|
|
||||||
exportRPCFeatures() {
|
@Inject(ICharacterManager)
|
||||||
return []
|
private character: ICharacterManager
|
||||||
|
|
||||||
|
exportRPCs = () => [
|
||||||
|
this.getItems,
|
||||||
|
this.getItem,
|
||||||
|
this.buyToken,
|
||||||
|
this.calculatePriorities,
|
||||||
|
this.getToken,
|
||||||
|
this.getTokens,
|
||||||
|
this.getAllPriorities
|
||||||
|
]
|
||||||
|
|
||||||
|
exportRPCFeatures = () => [{
|
||||||
|
name: 'managePriorities' as 'managePriorities',
|
||||||
|
exportRPCs: () => [
|
||||||
|
this.setPriority,
|
||||||
|
this.deletePriority
|
||||||
|
],
|
||||||
|
},{
|
||||||
|
name: 'reset' as 'reset',
|
||||||
|
exportRPCs: () => [
|
||||||
|
this.wipeCurrencyAndItems
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
|
||||||
|
wipeCurrencyAndItems = async () => {
|
||||||
|
await Promise.all([
|
||||||
|
this.userManager.wipeCurrency(),
|
||||||
|
this.admin.knex('tokens').where(true).del()
|
||||||
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
getItems = async () :Promise<Item[]> => await this.admin.knex.select('*').from('items')
|
getItems = async () :Promise<Item[]> => await this.admin.knex.select('*').from('items')
|
||||||
|
|
||||||
getItem = async (name:string):Promise<Item> => {
|
getItem = async(name:string):Promise<Item> => {
|
||||||
|
return await this.admin.knex('items').select('*').where('itemname','=',name).first()
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchItem = async (name:string):Promise<Item> => {
|
||||||
const res = await fetch('https://classic.wowhead.com/item='+name+'&xml');
|
const res = await fetch('https://classic.wowhead.com/item='+name+'&xml');
|
||||||
const txt = await res.text();
|
const txt = await res.text();
|
||||||
const r = await parser.parseStringPromise(txt);
|
const r = await parser.parseStringPromise(txt);
|
||||||
@@ -60,11 +88,24 @@ implements FrontworkComponent<ItemManagerIfc, ItemManagerFeatureIfc>, TableDefin
|
|||||||
{
|
{
|
||||||
name: 'tokens',
|
name: 'tokens',
|
||||||
tableBuilder: (table) => {
|
tableBuilder: (table) => {
|
||||||
table.integer("characterid").primary()
|
table.primary(['characterid', 'itemid'])
|
||||||
|
table.integer("characterid")
|
||||||
table.foreign("characterid").references("id").inTable('characters')
|
table.foreign("characterid").references("id").inTable('characters')
|
||||||
table.integer("itemid").primary()
|
table.integer("itemid")
|
||||||
table.foreign("itemid").references("id").inTable('items')
|
table.foreign("itemid").references("id").inTable('items')
|
||||||
table.integer("level")
|
table.integer("level").defaultTo(1)
|
||||||
|
}
|
||||||
|
},{
|
||||||
|
name: 'priorities',
|
||||||
|
tableBuilder: (table) => {
|
||||||
|
table.increments('id').primary()
|
||||||
|
table.integer('itemid')
|
||||||
|
table.foreign('itemid').references('id').inTable('items')
|
||||||
|
table.string('race').nullable()
|
||||||
|
table.integer('specid').nullable()
|
||||||
|
table.foreign('specid').references('id').inTable('specs')
|
||||||
|
table.integer('modifier')
|
||||||
|
table.string('description').nullable()
|
||||||
}
|
}
|
||||||
},{
|
},{
|
||||||
name: 'items',
|
name: 'items',
|
||||||
@@ -79,6 +120,126 @@ implements FrontworkComponent<ItemManagerIfc, ItemManagerFeatureIfc>, TableDefin
|
|||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buyToken = async (usertoken: string, charactername:string, itemname:string): Promise<(SRToken & Character & Item) | void> => {
|
||||||
|
const record = this.userManager.getUserRecordByToken(usertoken)
|
||||||
|
const character = await this.character.getCharacterByName(charactername)
|
||||||
|
|
||||||
|
if(!record || !character || record.user.username !== character.username) return
|
||||||
|
|
||||||
|
const item = await this.getItem(itemname)
|
||||||
|
if(!item) return
|
||||||
|
|
||||||
|
const currency = await this.userManager.getCurrency(record.user)
|
||||||
|
if(currency < 1) return
|
||||||
|
|
||||||
|
const existingToken = await this.getToken(character, item)
|
||||||
|
|
||||||
|
await this.userManager.decrementCurrency(record.user, 1)
|
||||||
|
|
||||||
|
if(!existingToken){
|
||||||
|
const modifier = await this.calculatePriorities(itemname, character)
|
||||||
|
await this.admin.knex('tokens').insert({
|
||||||
|
characterid: character.id,
|
||||||
|
itemid: item.id,
|
||||||
|
level: 1+modifier
|
||||||
|
})
|
||||||
|
}else{
|
||||||
|
await this.admin.knex('tokens').where({
|
||||||
|
characterid: character.id,
|
||||||
|
itemid: item.id
|
||||||
|
}).increment('level')
|
||||||
|
}
|
||||||
|
|
||||||
|
return await this.getToken(character, item)
|
||||||
|
}
|
||||||
|
|
||||||
|
getAllPriorities = async() :Promise<(SRPriority & Spec & Item)[]> => this.admin
|
||||||
|
.knex('priorities as p')
|
||||||
|
.join('items as i', 'p.itemid', '=', 'i.id')
|
||||||
|
.leftJoin('specs as s', 'p.specid', '=', 's.id')
|
||||||
|
.select('*')
|
||||||
|
|
||||||
|
deletePriority = async(priority:SRPriority) : Promise<void> => {
|
||||||
|
await this.admin.knex('priorities')
|
||||||
|
.where(priority)
|
||||||
|
.del()
|
||||||
|
}
|
||||||
|
|
||||||
|
setPriority = async(itemname:string, priority: SRPriority) : Promise<void> => {
|
||||||
|
const item = await this.getItem(itemname)
|
||||||
|
|
||||||
|
await this.admin
|
||||||
|
.knex('priorities')
|
||||||
|
.insert(<SRPriority>{
|
||||||
|
itemid: item.id,
|
||||||
|
...priority
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
getPriorities = async(itemname:string) : Promise<SRPriority[]> => {
|
||||||
|
const item = await this.getItem(itemname)
|
||||||
|
|
||||||
|
return await this.admin.knex('priorities')
|
||||||
|
.where('itemid', '=', item.id)
|
||||||
|
.select('*')
|
||||||
|
}
|
||||||
|
|
||||||
|
calculatePriorities = async (itemname: string, character:Character):Promise<number>=> {
|
||||||
|
const rules : SRPriority[] = await this.admin.knex('priorities as p')
|
||||||
|
.select('*')
|
||||||
|
.join('items as i', 'i.id', '=', 'p.itemid')
|
||||||
|
.where('itemname', '=', itemname)
|
||||||
|
|
||||||
|
return rules.map(rule => {
|
||||||
|
if(rule.specid && rule.race){
|
||||||
|
if(rule.specid === character.specid && rule.race === character.race)
|
||||||
|
return rule.modifier
|
||||||
|
else
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if(rule.specid){
|
||||||
|
if(rule.specid === character.specid)
|
||||||
|
return rule.modifier
|
||||||
|
else
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if(rule.race){
|
||||||
|
if(rule.race === character.race)
|
||||||
|
return rule.modifier
|
||||||
|
else
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}).reduce((prev, curr) => prev+curr, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
getToken = async (character:Character, item:Item): Promise<(SRToken & Character & Item) | void>=> {
|
||||||
|
return await this.admin
|
||||||
|
.knex('tokens as t')
|
||||||
|
.select('*')
|
||||||
|
.join('characters as c', 'c.id', '=', 't.characterid')
|
||||||
|
.join('items as i', 'i.id', '=', 't.itemid')
|
||||||
|
.where({
|
||||||
|
characterid: character.id,
|
||||||
|
itemid: item.id
|
||||||
|
})
|
||||||
|
.first()
|
||||||
|
}
|
||||||
|
|
||||||
|
getTokens = async (character:Character) : Promise<(SRToken & Character & Item)[]> => {
|
||||||
|
return await this.admin
|
||||||
|
.knex('tokens as t')
|
||||||
|
.select('*')
|
||||||
|
.select('*')
|
||||||
|
.join('characters as c', 'c.id', '=', 't.characterid')
|
||||||
|
.join('items as i', 'i.id', '=', 't.itemid')
|
||||||
|
.where({
|
||||||
|
characterid: character.id,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
countItems = async() :Promise<number> => {
|
countItems = async() :Promise<number> => {
|
||||||
const count = await this.admin.knex('items').count('*');
|
const count = await this.admin.knex('items').count('*');
|
||||||
return <number>count[0]['count(*)']
|
return <number>count[0]['count(*)']
|
||||||
@@ -86,15 +247,15 @@ implements FrontworkComponent<ItemManagerIfc, ItemManagerFeatureIfc>, TableDefin
|
|||||||
|
|
||||||
private initialized = false
|
private initialized = false
|
||||||
initialize = async () => {
|
initialize = async () => {
|
||||||
if(!this.initialized)
|
if(this.initialized) return
|
||||||
this.initialized = true
|
this.initialized = true
|
||||||
|
|
||||||
const allItems = [...T1]
|
const allItems = [...T1]
|
||||||
getLogger('ItemManager').debug('Checking items')
|
getLogger('ItemManager').debug('Checking items')
|
||||||
|
|
||||||
const countCache = await this.countItems()
|
const countCache = await this.countItems()
|
||||||
if(countCache != allItems.length){
|
if(countCache != allItems.length){
|
||||||
const items:Item[] = await Promise.all(allItems.map((i) => this.getItem(i)))
|
const items:Item[] = await Promise.all(allItems.map((i) => this.fetchItem(i)))
|
||||||
try{
|
try{
|
||||||
await this.admin
|
await this.admin
|
||||||
.knex('items')
|
.knex('items')
|
||||||
|
|||||||
@@ -2,10 +2,22 @@ import { IItemManager } from "./Interface"
|
|||||||
|
|
||||||
export type ItemManagerIfc = {
|
export type ItemManagerIfc = {
|
||||||
ItemManager: {
|
ItemManager: {
|
||||||
getItem: IItemManager['getItem']
|
getItem: IItemManager['fetchItem']
|
||||||
getItems: IItemManager['getItems']
|
getItems: IItemManager['getItems']
|
||||||
|
buyToken: IItemManager['buyToken']
|
||||||
|
calculatePriorities: IItemManager['calculatePriorities']
|
||||||
|
getToken: IItemManager['getToken']
|
||||||
|
getTokens: IItemManager['getTokens']
|
||||||
|
getAllPriorities: IItemManager['getAllPriorities']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ItemManagerFeatureIfc = {
|
export type ItemManagerFeatureIfc = {
|
||||||
|
reset: {
|
||||||
|
wipeCurrencyAndItems: IItemManager['wipeCurrencyAndItems']
|
||||||
|
}
|
||||||
|
managePriorities: {
|
||||||
|
setPriority:IItemManager['setPriority']
|
||||||
|
deletePriorits: IItemManager['deletePriority']
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
import { ILoginManager } from "./Interface"
|
|
||||||
|
|
||||||
export type LoginManagerIfc = {
|
|
||||||
Authenticator: {
|
|
||||||
checkToken: ILoginManager['checkToken']
|
|
||||||
login: ILoginManager['login']
|
|
||||||
logout: ILoginManager['logout']
|
|
||||||
createUser: ILoginManager['createUser']
|
|
||||||
getAuth: ILoginManager['getAuth']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export type LoginManagerFeatureIfc = {
|
|
||||||
modifyPermissions: {
|
|
||||||
setPermission: ILoginManager['setPermission']
|
|
||||||
getPermissions: ILoginManager['getPermissions']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -18,25 +18,12 @@ implements RPCExporter<ConfigLoaderIfc<ConfT>, "Config">{
|
|||||||
|
|
||||||
name = "Config" as "Config"
|
name = "Config" as "Config"
|
||||||
|
|
||||||
exportRPCs() {
|
exportRPCs = () => [
|
||||||
return [{
|
this.getConfig,
|
||||||
name: "getConfig" as "getConfig",
|
this.resetConfig,
|
||||||
call: this.getConfig
|
this.setConfig,
|
||||||
},{
|
this.setConfigKey,
|
||||||
name: "resetConfig" as "resetConfig",
|
this.deleteConfigKey,
|
||||||
call: this.resetConfig
|
this.getConfigKey
|
||||||
},{
|
]
|
||||||
name: "setConfig" as "setConfig",
|
|
||||||
call: this.setConfig
|
|
||||||
},{
|
|
||||||
name: "setConfigKey" as "setConfigKey",
|
|
||||||
call: this.setConfigKey
|
|
||||||
},{
|
|
||||||
name: "deleteConfigKey" as "deleteConfigKey",
|
|
||||||
call: this.deleteConfigKey
|
|
||||||
},{
|
|
||||||
name: "getConfigKey" as "getConfigKey",
|
|
||||||
call: this.getConfigKey
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Raid, Signup, Character } from "../../Types/Types"
|
import { Raid, Signup, Character, RaidData } from "../../Types/Types"
|
||||||
|
|
||||||
export class IRaidManager{
|
export class IRaidManager{
|
||||||
getRaids: () => Promise<Raid[]>
|
getRaids: () => Promise<Raid[]>
|
||||||
@@ -6,5 +6,12 @@ export class IRaidManager{
|
|||||||
addSignup: (signup: Signup) => Promise<any>
|
addSignup: (signup: Signup) => Promise<any>
|
||||||
removeSignup: (signup: Signup) => Promise<any>
|
removeSignup: (signup: Signup) => Promise<any>
|
||||||
getSignups: (raid:Raid) => Promise<Signup[]>
|
getSignups: (raid:Raid) => Promise<Signup[]>
|
||||||
sign: (userToken: string, character:Character, raid:Raid, attending:boolean) => Promise<any>
|
sign: (userToken: string, character:Character, raid:Raid, late:boolean) => Promise<any>
|
||||||
|
unsign: (userToken: string, character:Character, raid:Raid,) => Promise<any>
|
||||||
|
archiveRaid: (raid:Raid) => Promise<RaidData>
|
||||||
|
getRaidData: (raid:Raid) => Promise<RaidData>
|
||||||
|
setBenched: (signup: Signup) => Promise<void>
|
||||||
|
getPastRaids: (limit: number) => Promise<RaidData[]>
|
||||||
|
getArchiveRaid: (id:number) => Promise<RaidData>
|
||||||
|
startRaid: (raid:Raid) => Promise<RaidData>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,9 @@ import { IRaidManager } from "./Interface"
|
|||||||
export type RaidManagerIfc = {
|
export type RaidManagerIfc = {
|
||||||
RaidManager:{
|
RaidManager:{
|
||||||
getRaids: IRaidManager['getRaids']
|
getRaids: IRaidManager['getRaids']
|
||||||
|
getRaidData: IRaidManager['getRaidData']
|
||||||
|
getPastRaids: IRaidManager['getPastRaids']
|
||||||
|
getArchiveRaid: IRaidManager['getArchiveRaid']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -11,9 +14,13 @@ export type RaidManagerFeatureIfc = {
|
|||||||
createRaid: IRaidManager['createRaid']
|
createRaid: IRaidManager['createRaid']
|
||||||
addSignup: IRaidManager['addSignup']
|
addSignup: IRaidManager['addSignup']
|
||||||
removeSignup: IRaidManager['removeSignup']
|
removeSignup: IRaidManager['removeSignup']
|
||||||
|
archiveRaid: IRaidManager['archiveRaid']
|
||||||
|
setBenched: IRaidManager['setBenched']
|
||||||
|
startRaid: IRaidManager['startRaid']
|
||||||
}
|
}
|
||||||
signup: {
|
signup: {
|
||||||
getSignups: IRaidManager['getSignups']
|
getSignups: IRaidManager['getSignups']
|
||||||
sign: IRaidManager['sign']
|
sign: IRaidManager['sign']
|
||||||
|
unsign: IRaidManager['unsign']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,13 @@
|
|||||||
import { Inject, Module } from "../../Injector/ServiceDecorator";
|
import { Inject, Injectable } from "../../Injector/ServiceDecorator";
|
||||||
import { RaidManagerIfc, RaidManagerFeatureIfc } from "./RPCInterface";
|
import { RaidManagerIfc, RaidManagerFeatureIfc } from "./RPCInterface";
|
||||||
import { FrontworkComponent } from "../../Types/FrontworkComponent";
|
import { FrontworkComponent } from "../../Types/FrontworkComponent";
|
||||||
import { TableDefiniton, Signup, Raid, User, Character } from "../../Types/Types";
|
import { TableDefiniton, Signup, Raid, Character, RaidData, Spec, SRToken, Item } from "../../Types/Types";
|
||||||
import { IAdmin } from "../../Admin/Interface";
|
import { IAdmin } from "../../Admin/Interface";
|
||||||
import { IRaidManager } from "./Interface";
|
import { IRaidManager } from "./Interface";
|
||||||
import { ILoginManager } from "../Login/Interface";
|
import { IUserManager } from "../User/Interface";
|
||||||
|
import { ICharacterManager } from "../Character/Interface";
|
||||||
|
|
||||||
@Module(IRaidManager)
|
@Injectable(IRaidManager)
|
||||||
export class RaidManager
|
export class RaidManager
|
||||||
implements FrontworkComponent<RaidManagerIfc, RaidManagerFeatureIfc>, IRaidManager{
|
implements FrontworkComponent<RaidManagerIfc, RaidManagerFeatureIfc>, IRaidManager{
|
||||||
name = "RaidManager" as "RaidManager";
|
name = "RaidManager" as "RaidManager";
|
||||||
@@ -14,37 +15,38 @@ implements FrontworkComponent<RaidManagerIfc, RaidManagerFeatureIfc>, IRaidManag
|
|||||||
@Inject(IAdmin)
|
@Inject(IAdmin)
|
||||||
private admin: IAdmin
|
private admin: IAdmin
|
||||||
|
|
||||||
@Inject(ILoginManager)
|
@Inject(IUserManager)
|
||||||
private login: ILoginManager
|
private userManager: IUserManager
|
||||||
|
|
||||||
exportRPCs = () => [{
|
@Inject(ICharacterManager)
|
||||||
name: 'getRaids' as 'getRaids',
|
private characterManager: ICharacterManager
|
||||||
call: this.getRaids
|
|
||||||
},]
|
exportRPCs = () => [
|
||||||
|
this.getRaids,
|
||||||
|
this.getRaidData,
|
||||||
|
this.getPastRaids,
|
||||||
|
this.getArchiveRaid
|
||||||
|
]
|
||||||
|
|
||||||
exportRPCFeatures() {
|
exportRPCFeatures() {
|
||||||
return [{
|
return [{
|
||||||
name: 'manageRaid' as 'manageRaid',
|
name: 'manageRaid' as 'manageRaid',
|
||||||
exportRPCs: () => [{
|
exportRPCs: () => [
|
||||||
name: 'createRaid' as 'createRaid',
|
this.createRaid,
|
||||||
call: this.createRaid
|
this.addSignup,
|
||||||
},{
|
this.removeSignup,
|
||||||
name: 'addSignup' as 'addSignup',
|
this.archiveRaid,
|
||||||
call: this.addSignup
|
this.setBenched,
|
||||||
},{
|
this.startRaid
|
||||||
name: 'removeSignup' as 'removeSignup',
|
]
|
||||||
call: this.removeSignup
|
|
||||||
}]
|
|
||||||
},{
|
},{
|
||||||
name: 'signup' as 'signup',
|
name: 'signup' as 'signup',
|
||||||
exportRPCs: () => [{
|
exportRPCs: () => [
|
||||||
name: 'getSignups' as 'getSignups',
|
this.getSignups,
|
||||||
call: this.getSignups
|
this.sign,
|
||||||
},{
|
this.unsign
|
||||||
name: 'sign' as 'sign',
|
]
|
||||||
call: this.sign
|
}]
|
||||||
}]
|
|
||||||
},]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getTableDefinitions(): TableDefiniton[] {
|
getTableDefinitions(): TableDefiniton[] {
|
||||||
@@ -56,16 +58,24 @@ implements FrontworkComponent<RaidManagerIfc, RaidManagerFeatureIfc>, IRaidManag
|
|||||||
table.dateTime('start').notNullable()
|
table.dateTime('start').notNullable()
|
||||||
table.string('description').notNullable()
|
table.string('description').notNullable()
|
||||||
table.string('title').notNullable()
|
table.string('title').notNullable()
|
||||||
table.integer('minrank').notNullable()
|
table.integer('size').defaultTo(40)
|
||||||
|
}
|
||||||
|
},{
|
||||||
|
name: 'archive',
|
||||||
|
tableBuilder: (table) => {
|
||||||
|
table.integer('id').primary()
|
||||||
|
table.json('raiddata').notNullable()
|
||||||
}
|
}
|
||||||
},{
|
},{
|
||||||
name: 'signups',
|
name: 'signups',
|
||||||
tableBuilder: (table) => {
|
tableBuilder: (table) => {
|
||||||
table.primary(['raidid', 'characterid'])
|
table.primary(['raidid', 'characterid'])
|
||||||
table.integer('raidid')
|
table.integer('raidid')
|
||||||
table.foreign('raidid').references('id').inTable('raids')
|
table.foreign('raidid').references('id').inTable('raids').onDelete('CASCADE')
|
||||||
table.integer('characterid')
|
table.integer('characterid')
|
||||||
table.foreign('characterid').references('id').inTable('characters')
|
table.foreign('characterid').references('id').inTable('characters').onDelete('CASCADE')
|
||||||
|
table.boolean('benched').defaultTo('false')
|
||||||
|
table.boolean('late')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -87,9 +97,154 @@ implements FrontworkComponent<RaidManagerIfc, RaidManagerFeatureIfc>, IRaidManag
|
|||||||
})
|
})
|
||||||
.delete()
|
.delete()
|
||||||
|
|
||||||
getRaids = async () : Promise<Raid[]> => await this.admin.knex
|
getRaids = async () : Promise<Raid[]> => {
|
||||||
.select('*')
|
|
||||||
.from('raids')
|
const subQuery = this.admin
|
||||||
|
.knex('signups')
|
||||||
|
.count('*')
|
||||||
|
.where({
|
||||||
|
raidid: this.admin.knex.ref('raids.id'),
|
||||||
|
benched: false,
|
||||||
|
late: false
|
||||||
|
})
|
||||||
|
.as('signupcount')
|
||||||
|
|
||||||
|
return await this.admin.knex('raids')
|
||||||
|
.select('*', subQuery)
|
||||||
|
.orderBy('start', 'asc')
|
||||||
|
}
|
||||||
|
|
||||||
|
startRaid = async (raid:Raid) : Promise<RaidData> => {
|
||||||
|
const archived = await this.archiveRaid(raid)
|
||||||
|
|
||||||
|
delete archived.participants.late
|
||||||
|
|
||||||
|
const giveCurrency = async (b: Character) => {
|
||||||
|
const usr = await this.characterManager.getUserOfCharacter(b)
|
||||||
|
await this.userManager.incrementCurrency(usr, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.all([
|
||||||
|
...archived.participants.bench.map(giveCurrency),
|
||||||
|
...Object.values(archived.participants).map((group: any) => group.map(giveCurrency))
|
||||||
|
])
|
||||||
|
|
||||||
|
return archived
|
||||||
|
}
|
||||||
|
|
||||||
|
archiveRaid = async (raid:Raid) : Promise<RaidData> => {
|
||||||
|
const raidData = await this.getRaidData(raid)
|
||||||
|
await this.admin.knex('archive')
|
||||||
|
.insert({
|
||||||
|
id:raidData.id,
|
||||||
|
raiddata: JSON.stringify(raidData)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
await this.admin.knex('raids')
|
||||||
|
.where('id', '=', raid.id)
|
||||||
|
.del()
|
||||||
|
|
||||||
|
const row = await this.admin.knex('archive')
|
||||||
|
.select('*')
|
||||||
|
.where({
|
||||||
|
id:raidData.id,
|
||||||
|
})
|
||||||
|
.first()
|
||||||
|
|
||||||
|
return JSON.parse(row.raiddata)
|
||||||
|
}
|
||||||
|
|
||||||
|
getArchiveRaid = async(id:number) : Promise<RaidData> => {
|
||||||
|
const data = await this.admin.knex('archive').select('raiddata').where({
|
||||||
|
id: id
|
||||||
|
}).first()
|
||||||
|
|
||||||
|
return JSON.parse(data.raiddata)
|
||||||
|
}
|
||||||
|
|
||||||
|
getPastRaids = async(limit: number) : Promise<RaidData[]> => {
|
||||||
|
const raids = await this.admin.knex('archive')
|
||||||
|
.select('*')
|
||||||
|
.orderBy('id', 'desc')
|
||||||
|
.limit(limit)
|
||||||
|
|
||||||
|
return raids.map(raid => JSON.parse(raid.raiddata))
|
||||||
|
}
|
||||||
|
|
||||||
|
getRaidData = async (raid:Raid) : Promise<RaidData> => {
|
||||||
|
const ret = {
|
||||||
|
participants:{
|
||||||
|
Druid: <(Character&Spec)[]>[],
|
||||||
|
Hunter: <(Character&Spec)[]>[],
|
||||||
|
Mage: <(Character&Spec)[]>[],
|
||||||
|
Paladin: <(Character&Spec)[]>[],
|
||||||
|
Priest: <(Character&Spec)[]>[],
|
||||||
|
Rogue: <(Character&Spec)[]>[],
|
||||||
|
Shaman: <(Character&Spec)[]>[],
|
||||||
|
Warlock: <(Character&Spec)[]>[],
|
||||||
|
Warrior: <(Character&Spec)[]>[],
|
||||||
|
late: <(Character&Spec)[]>[],
|
||||||
|
bench: <(Character&Spec)[]>[],
|
||||||
|
},
|
||||||
|
tokens:{}
|
||||||
|
}
|
||||||
|
|
||||||
|
const subQuery = this.admin
|
||||||
|
.knex('signups')
|
||||||
|
.count('*')
|
||||||
|
.where({
|
||||||
|
raidid: this.admin.knex.ref('raids.id'),
|
||||||
|
benched: false,
|
||||||
|
late: false
|
||||||
|
})
|
||||||
|
.as('signupcount')
|
||||||
|
|
||||||
|
const raidInDb: Raid = await this.admin.knex('raids')
|
||||||
|
.select('*', subQuery)
|
||||||
|
.where('id','=',raid.id)
|
||||||
|
.first()
|
||||||
|
|
||||||
|
const characterData: (Character & Spec & Signup)[] = await this.admin
|
||||||
|
.knex('signups as s')
|
||||||
|
.select('characterid as id', 'charactername', 'class', 'specname', 'race', 'userid', 'benched', 'late', 'raidid', 'characterid')
|
||||||
|
.join('raids as r', 's.raidid','=','r.id')
|
||||||
|
.join('characters as c', 's.characterid','=','c.id')
|
||||||
|
.join('users as u', 'c.userid','=','u.id')
|
||||||
|
.join('specs as sp', 'specid','=','sp.id')
|
||||||
|
.where('r.id','=',raid.id)
|
||||||
|
|
||||||
|
characterData.forEach(data => {
|
||||||
|
if(data.benched){
|
||||||
|
ret.participants.bench.push(data)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if(data.late){
|
||||||
|
ret.participants.late.push(data)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ret.participants[data.class].push(data)
|
||||||
|
})
|
||||||
|
|
||||||
|
const tokenData: (Character & SRToken & Item)[] = await this.admin
|
||||||
|
.knex('signups as s')
|
||||||
|
.select('*')
|
||||||
|
.join('raids as r', 's.raidid','=','r.id')
|
||||||
|
.where('r.id','=',raid.id)
|
||||||
|
.join('characters as c', 's.characterid','=','c.id')
|
||||||
|
.join('tokens as t', 't.characterid','=','c.id')
|
||||||
|
.join('items as i', 'i.id','=','t.itemid')
|
||||||
|
|
||||||
|
tokenData.forEach(data => {
|
||||||
|
if(!ret.tokens[data.itemname])
|
||||||
|
ret.tokens[data.itemname] = []
|
||||||
|
ret.tokens[data.itemname].push(data)
|
||||||
|
})
|
||||||
|
return {
|
||||||
|
...raidInDb,
|
||||||
|
...ret
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
getSignups = async (raid:Raid) : Promise<Signup[]> => await this.admin
|
getSignups = async (raid:Raid) : Promise<Signup[]> => await this.admin
|
||||||
.knex('signups')
|
.knex('signups')
|
||||||
@@ -99,17 +254,60 @@ implements FrontworkComponent<RaidManagerIfc, RaidManagerFeatureIfc>, IRaidManag
|
|||||||
.select('*')
|
.select('*')
|
||||||
.where('raidid', '=', raid.id!)
|
.where('raidid', '=', raid.id!)
|
||||||
|
|
||||||
sign = async (usertoken:string, character:Character, raid:Raid) => {
|
sign = async (usertoken:string, character:Character, raid:Raid, late:boolean) => {
|
||||||
const maybeUserRecord = this.login.getUserRecordByToken(usertoken)
|
const maybeUserRecord = this.userManager.getUserRecordByToken(usertoken)
|
||||||
if(!maybeUserRecord || maybeUserRecord.user.id != character.userid){
|
if(!maybeUserRecord || maybeUserRecord.user.id != character.userid){
|
||||||
throw new Error("Bad Usertoken")
|
throw new Error("Bad Usertoken")
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.admin
|
const exists = await this.admin
|
||||||
.knex('signups')
|
.knex('signups')
|
||||||
.insert({
|
.select('*')
|
||||||
|
.where({
|
||||||
raidid: raid.id!,
|
raidid: raid.id!,
|
||||||
characterid: character.id!
|
characterid: character.id!,
|
||||||
})
|
})
|
||||||
|
.first()
|
||||||
|
|
||||||
|
if(!exists){
|
||||||
|
await this.admin
|
||||||
|
.knex('signups')
|
||||||
|
.insert({
|
||||||
|
raidid: raid.id!,
|
||||||
|
characterid: character.id!,
|
||||||
|
late: late
|
||||||
|
})
|
||||||
|
}else{
|
||||||
|
await this.admin
|
||||||
|
.knex('signups')
|
||||||
|
.update({
|
||||||
|
raidid: raid.id!,
|
||||||
|
characterid: character.id!,
|
||||||
|
late: late
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsign = async (usertoken:string, character:Character, raid:Raid) => {
|
||||||
|
const maybeUserRecord = this.userManager.getUserRecordByToken(usertoken)
|
||||||
|
if(!maybeUserRecord || maybeUserRecord.user.id != character.userid){
|
||||||
|
throw new Error("Bad Usertoken")
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.admin.knex('signups')
|
||||||
|
.where({
|
||||||
|
raidid: raid.id!,
|
||||||
|
characterid: character.id!,
|
||||||
|
})
|
||||||
|
.del()
|
||||||
|
}
|
||||||
|
|
||||||
|
setBenched = async (signup: Signup) : Promise<void> => {
|
||||||
|
await this.admin.knex('signups')
|
||||||
|
.where({
|
||||||
|
raidid: signup.raidid,
|
||||||
|
characterid: signup.characterid
|
||||||
|
})
|
||||||
|
.update(signup)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import { Raid, Signup, Character, RaidData } from "../../Types/Types"
|
||||||
|
import { SubscriptionResponse } from "rpclibrary"
|
||||||
|
|
||||||
|
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<SubscriptionResponse>
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import { IShoutbox } from "./Interface"
|
||||||
|
|
||||||
|
export type ShoutboxIfc = {
|
||||||
|
Shoutbox:{
|
||||||
|
getFeed: IShoutbox['getFeed']
|
||||||
|
shout: IShoutbox['shout']
|
||||||
|
subscribe: IShoutbox['subscribe']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ShoutboxFeatureIfc = {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
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 { SubscriptionResponse, makeSubResponse } from "rpclibrary";
|
||||||
|
import * as CircularBuffer from "circular-buffer";
|
||||||
|
|
||||||
|
@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 = (uuid:string, msg: ShoutMessage) => {
|
||||||
|
Object.values(this.subs).forEach((cb:any) => {
|
||||||
|
try{
|
||||||
|
cb(msg)
|
||||||
|
}catch(e){
|
||||||
|
this.unsubscribe(uuid)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
getFeed = async () : Promise<ShoutMessage[]> => {
|
||||||
|
return this.log.toarray()
|
||||||
|
}
|
||||||
|
|
||||||
|
subscribe = async (callback) : Promise<SubscriptionResponse> => {
|
||||||
|
const resp = makeSubResponse({})
|
||||||
|
this.subs[resp.uuid] = callback
|
||||||
|
return resp
|
||||||
|
}
|
||||||
|
|
||||||
|
unsubscribe = async (uuid: string) => {
|
||||||
|
delete this.subs[uuid]
|
||||||
|
}
|
||||||
|
}
|
||||||
+9
-1
@@ -1,6 +1,6 @@
|
|||||||
import { Auth, Rank, User, RPCPermission, UserRecord } from "../../Types/Types"
|
import { Auth, Rank, User, RPCPermission, UserRecord } from "../../Types/Types"
|
||||||
|
|
||||||
export class ILoginManager{
|
export class IUserManager{
|
||||||
login: (username:string, pwHash:string) => Promise<Auth>
|
login: (username:string, pwHash:string) => Promise<Auth>
|
||||||
logout: (username: string, tokenValue :string) => Promise<void>
|
logout: (username: string, tokenValue :string) => Promise<void>
|
||||||
getAuth: (tokenValue: string) => Promise<Auth | void>
|
getAuth: (tokenValue: string) => Promise<Auth | void>
|
||||||
@@ -9,4 +9,12 @@ export class ILoginManager{
|
|||||||
getPermissions: () => Promise<RPCPermission[]>
|
getPermissions: () => Promise<RPCPermission[]>
|
||||||
checkToken: (token: string, rank: Rank) => boolean
|
checkToken: (token: string, rank: Rank) => boolean
|
||||||
getUserRecordByToken: (tokenValue: string) => UserRecord | void
|
getUserRecordByToken: (tokenValue: string) => UserRecord | void
|
||||||
|
getUser: (username: string) => Promise<User | void>
|
||||||
|
|
||||||
|
decrementCurrency: (user: User, value: number) => Promise<void>
|
||||||
|
incrementCurrency: (user: User, value: number) => Promise<void>
|
||||||
|
setCurrency: (user: User, value: number) => Promise<void>
|
||||||
|
getCurrency: (user:User) => Promise<number>
|
||||||
|
changeRank: (user:User, rank: Rank) => Promise<User>
|
||||||
|
wipeCurrency: () => Promise<void>
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import { IUserManager } from "./Interface"
|
||||||
|
|
||||||
|
export type UserManagerIfc = {
|
||||||
|
UserManager: {
|
||||||
|
checkToken: IUserManager['checkToken']
|
||||||
|
login: IUserManager['login']
|
||||||
|
logout: IUserManager['logout']
|
||||||
|
createUser: IUserManager['createUser']
|
||||||
|
getAuth: IUserManager['getAuth']
|
||||||
|
getUser: IUserManager['getUser']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export type UserManagerFeatureIfc = {
|
||||||
|
modifyPermissions: {
|
||||||
|
setPermission: IUserManager['setPermission']
|
||||||
|
getPermissions: IUserManager['getPermissions']
|
||||||
|
changeRank: IUserManager['changeRank']
|
||||||
|
}
|
||||||
|
|
||||||
|
softreserveCurrency: {
|
||||||
|
incrementCurrency: IUserManager['incrementCurrency']
|
||||||
|
decrementCurrency: IUserManager['decrementCurrency']
|
||||||
|
setCurrency: IUserManager['setCurrency']
|
||||||
|
}
|
||||||
|
}
|
||||||
+140
-65
@@ -1,32 +1,34 @@
|
|||||||
import { RPCServer, Socket } from "rpclibrary";
|
import { RPCServer, Socket } from "rpclibrary";
|
||||||
import { Inject, Module } from "../../Injector/ServiceDecorator";
|
import { Inject, Injectable } from "../../Injector/ServiceDecorator";
|
||||||
import { FrontworkAdmin } from "../../Admin/Admin";
|
import { FrontworkAdmin } from "../../Admin/Admin";
|
||||||
import { GuildManager } from "../Guild/GuildManager";
|
import { GuildManager } from "../Guild/GuildManager";
|
||||||
import { ItemManager } from "../Item/ItemManager";
|
import { ItemManager } from "../Item/ItemManager";
|
||||||
import { RaidManager } from "../Raid/RaidManager";
|
import { RaidManager } from "../Raid/RaidManager";
|
||||||
import { CharacterManager } from "../Character/CharacterManager";
|
import { CharacterManager } from "../Character/CharacterManager";
|
||||||
import { LoginManagerIfc, LoginManagerFeatureIfc } from "./RPCInterface";
|
import { UserManagerFeatureIfc, UserManagerIfc } from "./RPCInterface";
|
||||||
import { FrontworkComponent } from "../../Types/FrontworkComponent";
|
import { FrontworkComponent } from "../../Types/FrontworkComponent";
|
||||||
import { Rank, User, Auth, _Rank, TableDefiniton, RPCPermission, FrontcraftFeatureIfc, AnyRPCExporter, Token, UserRecord } from "../../Types/Types";
|
import { Rank, User, Auth, _Rank, TableDefiniton, RPCPermission, FrontcraftFeatureIfc, AnyRPCExporter, Token, UserRecord } from "../../Types/Types";
|
||||||
import { IAdmin } from "../../Admin/Interface";
|
import { IAdmin } from "../../Admin/Interface";
|
||||||
import { ILoginManager } from "./Interface";
|
import { IUserManager } from "./Interface";
|
||||||
import { getLogger, Logger } from "log4js";
|
import { getLogger, Logger } from "log4js";
|
||||||
|
import { saltedHash } from "../../Util/hash";
|
||||||
|
|
||||||
const uuid = require('uuid/v4')
|
const uuid = require('uuid/v4')
|
||||||
|
|
||||||
|
const salt = "6pIbc6yjSN"
|
||||||
const ONE_WEEK = 604800000
|
const ONE_WEEK = 604800000
|
||||||
|
|
||||||
type Serverstate = {
|
type Serverstate = {
|
||||||
server: RPCServer,
|
server: RPCServer,
|
||||||
port : number,
|
port : number,
|
||||||
allowed: string[]
|
allowed: string[]
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
@Module(ILoginManager)
|
@Injectable(IUserManager)
|
||||||
export class LoginManager
|
export class UserManager
|
||||||
implements FrontworkComponent<LoginManagerIfc, LoginManagerFeatureIfc>, ILoginManager{
|
implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManager{
|
||||||
name = "Authenticator" as "Authenticator";
|
name = "UserManager" as "UserManager"
|
||||||
|
|
||||||
@Inject(IAdmin)
|
@Inject(IAdmin)
|
||||||
private admin: FrontworkAdmin
|
private admin: FrontworkAdmin
|
||||||
@@ -48,37 +50,44 @@ implements FrontworkComponent<LoginManagerIfc, LoginManagerFeatureIfc>, ILoginMa
|
|||||||
userLogins : {[username in string] : UserRecord} = {}
|
userLogins : {[username in string] : UserRecord} = {}
|
||||||
|
|
||||||
exportRPCs = () => [
|
exportRPCs = () => [
|
||||||
{
|
this.login,
|
||||||
name: 'login' as 'login',
|
this.logout,
|
||||||
call: this.login
|
this.getAuth,
|
||||||
},{
|
this.checkToken,
|
||||||
name: 'logout' as 'logout',
|
this.createUser,
|
||||||
call: this.logout
|
this.getUser
|
||||||
},{
|
|
||||||
name: 'getAuth' as 'getAuth',
|
|
||||||
call: this.getAuth
|
|
||||||
},{
|
|
||||||
name: 'checkToken' as 'checkToken',
|
|
||||||
call: this.checkToken
|
|
||||||
},{
|
|
||||||
name: 'createUser' as 'createUser',
|
|
||||||
call: this.createUser
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
|
|
||||||
exportRPCFeatures = () => [
|
exportRPCFeatures = () => [{
|
||||||
{
|
name: 'modifyPermissions' as 'modifyPermissions',
|
||||||
name: 'modifyPermissions' as 'modifyPermissions',
|
exportRPCs: () => [
|
||||||
exportRPCs: () => [{
|
this.getPermissions,
|
||||||
name: 'getPermissions' as 'getPermissions',
|
this.setPermission
|
||||||
call: this.getPermissions
|
]
|
||||||
},{
|
},{
|
||||||
name: 'setPermission' as 'setPermission',
|
name: 'softreserveCurrency' as 'softreserveCurrency',
|
||||||
call: this.setPermission
|
exportRPCs: () => [
|
||||||
}]
|
this.incrementCurrency,
|
||||||
}
|
this.decrementCurrency,
|
||||||
]
|
this.setCurrency
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
|
||||||
|
changeRank = async (user:User, rank:Rank): Promise<User> => {
|
||||||
|
await this.admin
|
||||||
|
.knex('users')
|
||||||
|
.where({
|
||||||
|
user:user.username
|
||||||
|
}).update({
|
||||||
|
rank: rank
|
||||||
|
})
|
||||||
|
|
||||||
|
return await this.admin
|
||||||
|
.knex('users')
|
||||||
|
.where({
|
||||||
|
user: user.username
|
||||||
|
}).first()
|
||||||
|
}
|
||||||
|
|
||||||
getTableDefinitions = (): TableDefiniton[] => [
|
getTableDefinitions = (): TableDefiniton[] => [
|
||||||
{
|
{
|
||||||
@@ -89,7 +98,7 @@ implements FrontworkComponent<LoginManagerIfc, LoginManagerFeatureIfc>, ILoginMa
|
|||||||
table.string("pwhash").notNullable()
|
table.string("pwhash").notNullable()
|
||||||
table.string("rank").notNullable()
|
table.string("rank").notNullable()
|
||||||
table.string("email").nullable().unique()
|
table.string("email").nullable().unique()
|
||||||
table.boolean("locked").defaultTo(true)
|
table.integer("currency").defaultTo(1)
|
||||||
}
|
}
|
||||||
},{
|
},{
|
||||||
name: 'rpcpermissions',
|
name: 'rpcpermissions',
|
||||||
@@ -109,19 +118,19 @@ implements FrontworkComponent<LoginManagerIfc, LoginManagerFeatureIfc>, ILoginMa
|
|||||||
initialize = async () => {
|
initialize = async () => {
|
||||||
this.exporters = [this.guild, this.item, this.raid, this.character]
|
this.exporters = [this.guild, this.item, this.raid, this.character]
|
||||||
//set up permissions
|
//set up permissions
|
||||||
getLogger('LoginManager').debug('inserting permissions')
|
getLogger('UserManager').debug('inserting permissions')
|
||||||
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
[this, ...this.exporters].flatMap(exp => exp.exportRPCFeatures().map(async (feature) => {
|
[this, ...this.exporters].flatMap(exp => exp.exportRPCFeatures().map(async (feature) => {
|
||||||
try{
|
try{
|
||||||
await this.admin.knex.insert({ rpcname: feature.name }).into('rpcpermissions')
|
await this.admin.knex.insert({ rpcname: feature.name }).into('rpcpermissions')
|
||||||
}catch(e){
|
}catch(e){
|
||||||
console.log(e);
|
getLogger('UserManager').debug(feature.name);
|
||||||
}
|
}
|
||||||
})))
|
})))
|
||||||
|
|
||||||
//start rankServers
|
//start rankServers
|
||||||
getLogger('LoginManager').debug('Starting rank servers')
|
getLogger('UserManager').debug('Starting rank servers')
|
||||||
|
|
||||||
let rankServers = { } as any
|
let rankServers = { } as any
|
||||||
await Promise.all(_Rank.map(async (r,i) => {
|
await Promise.all(_Rank.map(async (r,i) => {
|
||||||
@@ -148,7 +157,7 @@ implements FrontworkComponent<LoginManagerIfc, LoginManagerFeatureIfc>, ILoginMa
|
|||||||
try{
|
try{
|
||||||
//return await state.server.destroy()
|
//return await state.server.destroy()
|
||||||
}catch(e){
|
}catch(e){
|
||||||
getLogger('LoginManager').warn(e)
|
getLogger('UserManager').warn(e)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@@ -171,7 +180,7 @@ implements FrontworkComponent<LoginManagerIfc, LoginManagerFeatureIfc>, ILoginMa
|
|||||||
while(!data){
|
while(!data){
|
||||||
tries ++
|
tries ++
|
||||||
if(tries === 5){
|
if(tries === 5){
|
||||||
getLogger('LoginManager').debug('Connection check failed for connection *'+socket.port)
|
getLogger('UserManager').debug('Connection check failed for connection *'+socket.port)
|
||||||
socket.destroy()
|
socket.destroy()
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -189,7 +198,7 @@ implements FrontworkComponent<LoginManagerIfc, LoginManagerFeatureIfc>, ILoginMa
|
|||||||
|
|
||||||
setPermission = async (permission: RPCPermission) => {
|
setPermission = async (permission: RPCPermission) => {
|
||||||
await this.admin.knex('rpcpermissions')
|
await this.admin.knex('rpcpermissions')
|
||||||
.where('rpcname', '=', permission.rpcnamename)
|
.where('rpcname', '=', permission.rpcname)
|
||||||
.update(permission)
|
.update(permission)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,13 +207,14 @@ implements FrontworkComponent<LoginManagerIfc, LoginManagerFeatureIfc>, ILoginMa
|
|||||||
}
|
}
|
||||||
|
|
||||||
getPermission = async (feature: keyof FrontcraftFeatureIfc, rank:Rank) : Promise<boolean> => {
|
getPermission = async (feature: keyof FrontcraftFeatureIfc, rank:Rank) : Promise<boolean> => {
|
||||||
const perm : RPCPermission[] = await this.admin.knex
|
const perm : RPCPermission = await this.admin.knex
|
||||||
.select(rank)
|
.select(rank)
|
||||||
.from('rpcpermissions')
|
.from('rpcpermissions')
|
||||||
.where('rpcname', '=', <string>feature)
|
.where('rpcname', '=', <string>feature)
|
||||||
|
.first()
|
||||||
|
|
||||||
if(perm.length === 0) return false
|
if(!perm) return false
|
||||||
return perm[0][rank]
|
return perm[rank]
|
||||||
}
|
}
|
||||||
|
|
||||||
getRPCForRank = async (rank: Rank): Promise<AnyRPCExporter[]> => {
|
getRPCForRank = async (rank: Rank): Promise<AnyRPCExporter[]> => {
|
||||||
@@ -231,32 +241,33 @@ implements FrontworkComponent<LoginManagerIfc, LoginManagerFeatureIfc>, ILoginMa
|
|||||||
if(admins.length > 0){
|
if(admins.length > 0){
|
||||||
return {} as User
|
return {} as User
|
||||||
}
|
}
|
||||||
|
|
||||||
user.locked = false
|
|
||||||
}
|
}
|
||||||
user.username = user.username.toLowerCase()
|
user.username = user.username.toLowerCase()
|
||||||
|
user.pwhash = await saltedHash(user.pwhash, salt)
|
||||||
|
|
||||||
await this.admin.knex('users')
|
await this.admin.knex('users')
|
||||||
.insert(user)
|
.insert(user)
|
||||||
|
|
||||||
const users = await this.admin.knex
|
const userRecord = await this.admin.knex
|
||||||
.select("*")
|
.select("*")
|
||||||
.from('users')
|
.from('users')
|
||||||
.where(user)
|
.where(user)
|
||||||
|
.first()
|
||||||
|
|
||||||
return users[0]
|
return userRecord
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getUser = async (username: string) : Promise<User | void> => await this.admin
|
||||||
|
.knex('users')
|
||||||
|
.select('*')
|
||||||
|
.where({
|
||||||
|
username: username.toLowerCase()
|
||||||
|
})
|
||||||
|
.first()
|
||||||
|
|
||||||
logout = async (username:string, tokenValue : string) : Promise<void> => {
|
logout = async (username:string, tokenValue : string) : Promise<void> => {
|
||||||
try{
|
try{
|
||||||
username = username.toLowerCase()
|
if(!this.checkTokenOwnedByUser(username, tokenValue)) return
|
||||||
const maybeRecord = this.getUserRecordByToken(tokenValue)
|
|
||||||
if(maybeRecord && maybeRecord.auth.user.username != username){
|
|
||||||
getLogger('LoginManager').warn(`Bad logout attempt
|
|
||||||
token by: ${maybeRecord.auth.user.username}
|
|
||||||
tried to logout: ${username}`)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if(this.userLogins[username]){
|
if(this.userLogins[username]){
|
||||||
await Promise.all (Object.values(this.userLogins[username].connections).map(async (sock) => {
|
await Promise.all (Object.values(this.userLogins[username].connections).map(async (sock) => {
|
||||||
@@ -275,15 +286,22 @@ implements FrontworkComponent<LoginManagerIfc, LoginManagerFeatureIfc>, ILoginMa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wipeCurrency = async () => {
|
||||||
|
await this.admin.knex('users')
|
||||||
|
.update({currency: 0})
|
||||||
|
}
|
||||||
|
|
||||||
login = async(username:string, pwHash:string) : Promise<Auth> => {
|
login = async(username:string, pwHash:string) : Promise<Auth> => {
|
||||||
username = username.toLowerCase()
|
username = username.toLowerCase()
|
||||||
const res:User[] = await this.admin.knex
|
const user:User = await this.admin.knex
|
||||||
.select('*')
|
.select('*')
|
||||||
.from('users')
|
.from('users')
|
||||||
.where({ username: username })
|
.where({ username: username })
|
||||||
|
.first()
|
||||||
|
|
||||||
|
const salted = await saltedHash(pwHash, salt)
|
||||||
|
|
||||||
if(res.length > 0 && pwHash === res[0].pwhash){
|
if(user && salted === user.pwhash){
|
||||||
const user:User = res[0]
|
|
||||||
delete user.pwhash
|
delete user.pwhash
|
||||||
|
|
||||||
//return existing auth
|
//return existing auth
|
||||||
@@ -339,11 +357,11 @@ implements FrontworkComponent<LoginManagerIfc, LoginManagerFeatureIfc>, ILoginMa
|
|||||||
}
|
}
|
||||||
}).catch((e) => {
|
}).catch((e) => {
|
||||||
socket.destroy();
|
socket.destroy();
|
||||||
getLogger('LoginManager').warn(e);
|
getLogger('UserManager').warn(e);
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
errorHandler: (socket, e, rpcName, args) => {
|
errorHandler: (socket, e, rpcName, args) => {
|
||||||
console.log(rpcName, args);
|
getLogger('UserManager').error(rpcName, args, e);
|
||||||
},
|
},
|
||||||
sesame: (sesame) => this.checkToken(sesame, rank)
|
sesame: (sesame) => this.checkToken(sesame, rank)
|
||||||
})
|
})
|
||||||
@@ -352,7 +370,7 @@ implements FrontworkComponent<LoginManagerIfc, LoginManagerFeatureIfc>, ILoginMa
|
|||||||
new Promise((res, rej) => setTimeout(res, 500))
|
new Promise((res, rej) => setTimeout(res, 500))
|
||||||
])
|
])
|
||||||
if(!rpcServer && n>1)
|
if(!rpcServer && n>1)
|
||||||
getLogger('LoginManager').warn("createServer retry nr.", n, 'port', port)
|
getLogger('UserManager').warn("createServer retry nr.", n, 'port', port)
|
||||||
}
|
}
|
||||||
return rpcServer
|
return rpcServer
|
||||||
}
|
}
|
||||||
@@ -360,6 +378,18 @@ implements FrontworkComponent<LoginManagerIfc, LoginManagerFeatureIfc>, ILoginMa
|
|||||||
checkToken = (token: string, rank: Rank) : boolean => this.rankServers[rank].allowed.includes(token)
|
checkToken = (token: string, rank: Rank) : boolean => this.rankServers[rank].allowed.includes(token)
|
||||||
&& Object.values(this.userLogins).find(login => login.auth.token.value === token)!.auth.token.created > Date.now() - ONE_WEEK
|
&& Object.values(this.userLogins).find(login => login.auth.token.value === token)!.auth.token.created > Date.now() - ONE_WEEK
|
||||||
|
|
||||||
|
checkTokenOwnedByUser = (username: string, tokenValue: string) => {
|
||||||
|
username = username.toLowerCase()
|
||||||
|
const maybeRecord = this.getUserRecordByToken(tokenValue)
|
||||||
|
if(!maybeRecord || maybeRecord.auth.user.username != username){
|
||||||
|
getLogger('UserManager').warn(`Bad logout attempt
|
||||||
|
token by: ${maybeRecord?maybeRecord.auth.user.username:tokenValue}
|
||||||
|
tried to logout: ${username}`)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
createToken = (user:User): Token => {
|
createToken = (user:User): Token => {
|
||||||
|
|
||||||
if(this.userLogins[user.username]){
|
if(this.userLogins[user.username]){
|
||||||
@@ -374,4 +404,49 @@ implements FrontworkComponent<LoginManagerIfc, LoginManagerFeatureIfc>, ILoginMa
|
|||||||
|
|
||||||
return token
|
return token
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getCurrency = async(user:User) : Promise<number> => {
|
||||||
|
const usr : User = await this.admin
|
||||||
|
.knex('users')
|
||||||
|
.where('username', '=', user.username)
|
||||||
|
.select('*')
|
||||||
|
.first()
|
||||||
|
|
||||||
|
return usr.currency!
|
||||||
|
}
|
||||||
|
|
||||||
|
decrementCurrency = async (user: User, value = 1) => {
|
||||||
|
if(value < 1) return
|
||||||
|
|
||||||
|
const usr : User = await this.admin
|
||||||
|
.knex('users')
|
||||||
|
.where('id', '=', user.id)
|
||||||
|
.select('*')
|
||||||
|
.first()
|
||||||
|
|
||||||
|
if(!usr || usr.currency! <= 0) return
|
||||||
|
|
||||||
|
await this.admin
|
||||||
|
.knex('users')
|
||||||
|
.where('id', '=', user.id)
|
||||||
|
.decrement('currency', value)
|
||||||
|
}
|
||||||
|
|
||||||
|
incrementCurrency = async (user: User, value = 1) => {
|
||||||
|
if(value < 1) return
|
||||||
|
await this.admin
|
||||||
|
.knex('users')
|
||||||
|
.where('id', '=', user.id)
|
||||||
|
.increment('currency', value)
|
||||||
|
}
|
||||||
|
|
||||||
|
setCurrency = async (user: User, value: number) => {
|
||||||
|
if(value < 0) return
|
||||||
|
await this.admin
|
||||||
|
.knex('users')
|
||||||
|
.where('id', '=', user.id)
|
||||||
|
.update('currency', value)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -51,8 +51,6 @@ export const Injector = new class {
|
|||||||
return rootobj
|
return rootobj
|
||||||
}
|
}
|
||||||
this.moduleObjs[target.name] = new target()
|
this.moduleObjs[target.name] = new target()
|
||||||
return this.moduleObjs[target.name] as any
|
return this.moduleObjs[target.name] as any
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ import { FrontworkComponent } from "../Types/FrontworkComponent";
|
|||||||
* @returns {GenericClassDecorator<Type<any>>}
|
* @returns {GenericClassDecorator<Type<any>>}
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
export const Module = (ifc?: Type<any>) : GenericClassDecorator<Type<any>> => {
|
export const Injectable = (_interface?: Type<any>) : GenericClassDecorator<Type<any>> => {
|
||||||
return (target: Type<any>) => {
|
return (target: Type<any>) => {
|
||||||
Injector.modules.push({
|
Injector.modules.push({
|
||||||
implements: ifc,
|
implements: _interface,
|
||||||
implementation: target
|
implementation: target
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -20,12 +20,12 @@ export const Module = (ifc?: Type<any>) : GenericClassDecorator<Type<any>> => {
|
|||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
export const RootComponent = (config : {
|
export const RootComponent = (config : {
|
||||||
implements : Type<any>
|
injectable : Type<any>
|
||||||
imports : Type<FrontworkComponent>[]
|
injects : Type<FrontworkComponent>[]
|
||||||
}) : GenericClassDecorator<Type<any>> => {
|
}) : GenericClassDecorator<Type<any>> => {
|
||||||
return (target: Type<any>) => {
|
return (target: Type<any>) => {
|
||||||
Injector.rootModules = config.imports
|
Injector.rootModules = config.injects
|
||||||
Injector.rootInterface = config.implements
|
Injector.rootInterface = config.injectable
|
||||||
Injector.root = target
|
Injector.root = target
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,24 @@
|
|||||||
import * as Knex from "knex"
|
import * as Knex from "knex"
|
||||||
import { RPCExporter, Socket } from "rpclibrary";
|
import { RPCExporter, Socket } from "rpclibrary";
|
||||||
import { RaidManagerIfc, RaidManagerFeatureIfc } from "../Components/Raid/RPCInterface";
|
import { RaidManagerIfc, RaidManagerFeatureIfc } from "../Components/Raid/RPCInterface";
|
||||||
import { LoginManagerIfc, LoginManagerFeatureIfc } from "../Components/Login/RPCInterface";
|
import { UserManagerIfc, UserManagerFeatureIfc } from "../Components/User/RPCInterface";
|
||||||
import { CharacterManagerIfc, CharacterManagerFeatureIfc } from "../Components/Character/RPCInterface";
|
import { CharacterManagerIfc, CharacterManagerFeatureIfc } from "../Components/Character/RPCInterface";
|
||||||
|
import { ItemManagerFeatureIfc, ItemManagerIfc } from "../Components/Item/RPCInterface";
|
||||||
|
import { GuildManagerFeatureIfc, GuildManagerIfc } from "../Components/Guild/RPCInterface";
|
||||||
|
import { ShoutboxIfc } from "../Components/Shoutbox/RPCInterface";
|
||||||
|
|
||||||
export type FrontcraftIfc = RaidManagerIfc
|
export type FrontcraftIfc = RaidManagerIfc
|
||||||
& LoginManagerIfc
|
& UserManagerIfc
|
||||||
& CharacterManagerIfc
|
& CharacterManagerIfc
|
||||||
|
& ItemManagerIfc
|
||||||
|
& GuildManagerIfc
|
||||||
|
& ShoutboxIfc
|
||||||
|
|
||||||
export type FrontcraftFeatureIfc = RaidManagerFeatureIfc
|
export type FrontcraftFeatureIfc = RaidManagerFeatureIfc
|
||||||
& LoginManagerFeatureIfc
|
& UserManagerFeatureIfc
|
||||||
& CharacterManagerFeatureIfc
|
& CharacterManagerFeatureIfc
|
||||||
|
& ItemManagerFeatureIfc
|
||||||
|
& GuildManagerFeatureIfc
|
||||||
|
|
||||||
export declare type NotificationSeverity = 'Info' | 'Important' | 'Error';
|
export declare type NotificationSeverity = 'Info' | 'Important' | 'Error';
|
||||||
|
|
||||||
@@ -25,6 +33,7 @@ export type TableDefiniton = {
|
|||||||
tableBuilder: (table: Knex.CreateTableBuilder) => void
|
tableBuilder: (table: Knex.CreateTableBuilder) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type Race = "Human" | "Gnome" | "Night Elf" | "Dwarf"
|
||||||
export type Rank = "ADMIN" | "Guildmaster" | "Officer" | "Classleader" | "Raider" | "Trial" | "Social" | "Guest"
|
export type Rank = "ADMIN" | "Guildmaster" | "Officer" | "Classleader" | "Raider" | "Trial" | "Social" | "Guest"
|
||||||
export const _Rank : Rank[] = ["ADMIN" , "Guildmaster" , "Officer" , "Classleader" , "Raider" , "Trial" , "Social" , "Guest"]
|
export const _Rank : Rank[] = ["ADMIN" , "Guildmaster" , "Officer" , "Classleader" , "Raider" , "Trial" , "Social" , "Guest"]
|
||||||
export type Class = "Warrior" | "Rogue" | "Hunter" | "Mage" | "Warlock" | "Priest" | "Shaman" | "Paladin" | "Druid"
|
export type Class = "Warrior" | "Rogue" | "Hunter" | "Mage" | "Warlock" | "Priest" | "Shaman" | "Paladin" | "Druid"
|
||||||
@@ -33,11 +42,38 @@ export const _Class : Class[] = ["Warrior" , "Rogue" , "Hunter" , "Mage" , "Warl
|
|||||||
export type AnyRPCExporter = RPCExporter<any,any>
|
export type AnyRPCExporter = RPCExporter<any,any>
|
||||||
|
|
||||||
export type RPCPermission = {
|
export type RPCPermission = {
|
||||||
rpcnamename: string
|
rpcname: string
|
||||||
} & {
|
} & {
|
||||||
[rank in Rank] : boolean
|
[rank in Rank] : boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type RaidData = Raid & {
|
||||||
|
participants: {
|
||||||
|
[clazz in Class] : (Character & Spec)[]
|
||||||
|
} & {
|
||||||
|
late: (Character & Spec)[]
|
||||||
|
bench: (Character & Spec)[]
|
||||||
|
}
|
||||||
|
tokens: {
|
||||||
|
[itemname in string]: (Character & SRToken & Item)[]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export type SRToken = {
|
||||||
|
characterid: number,
|
||||||
|
itemid: number,
|
||||||
|
level: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export type SRPriority = {
|
||||||
|
id?:number
|
||||||
|
race?:Race
|
||||||
|
specid?:number,
|
||||||
|
itemid?:number,
|
||||||
|
description?:string,
|
||||||
|
modifier:number
|
||||||
|
}
|
||||||
|
|
||||||
export type Item = {
|
export type Item = {
|
||||||
id?:number
|
id?:number
|
||||||
itemname:string
|
itemname:string
|
||||||
@@ -52,8 +88,7 @@ export type User = {
|
|||||||
username: string
|
username: string
|
||||||
pwhash: string
|
pwhash: string
|
||||||
rank: Rank
|
rank: Rank
|
||||||
email?: string
|
currency?: number
|
||||||
locked: boolean
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Raid = {
|
export type Raid = {
|
||||||
@@ -61,17 +96,21 @@ export type Raid = {
|
|||||||
title: string
|
title: string
|
||||||
description: string
|
description: string
|
||||||
start: string
|
start: string
|
||||||
minrank: Rank
|
signupcount?: number
|
||||||
|
size: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Signup = {
|
export type Signup = {
|
||||||
raidid: number
|
raidid: number
|
||||||
characterid: number
|
characterid: number
|
||||||
|
benched: boolean
|
||||||
|
late: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Character = {
|
export type Character = {
|
||||||
id? : number
|
id? : number
|
||||||
charactername : string
|
charactername : string
|
||||||
|
race: Race
|
||||||
specid : number
|
specid : number
|
||||||
userid : number
|
userid : number
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
const SHA256 = require("crypto-js/sha256");
|
||||||
|
const Hex = require('crypto-js/enc-hex');
|
||||||
|
|
||||||
|
export async function saltedHash(input: string, salt: string) {
|
||||||
|
const hash = await SHA256(input+salt)
|
||||||
|
return Hex.stringify(hash)
|
||||||
|
}
|
||||||
@@ -9,15 +9,15 @@ import {
|
|||||||
PlayerService,
|
PlayerService,
|
||||||
StateService,
|
StateService,
|
||||||
} from './utils';
|
} from './utils';
|
||||||
import { LoginApiService, initializeLoginSvc } from '../frontcraft/services/login-api';
|
import { ApiService, initializeLoginSvc } from '../frontcraft/services/login-api';
|
||||||
|
|
||||||
const DATA_SERVICES = [
|
const DATA_SERVICES = [
|
||||||
{provide: LoginApiService, useClass: LoginApiService},
|
{provide: ApiService, useClass: ApiService},
|
||||||
{provide: CookieService, useClass: CookieService},
|
{provide: CookieService, useClass: CookieService},
|
||||||
{
|
{
|
||||||
provide: APP_INITIALIZER,
|
provide: APP_INITIALIZER,
|
||||||
useFactory: initializeLoginSvc,
|
useFactory: initializeLoginSvc,
|
||||||
deps: [LoginApiService, CookieService],
|
deps: [ApiService, CookieService],
|
||||||
multi: true
|
multi: true
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { ApiService } from '../../../frontcraft/services/login-api';
|
||||||
|
import { ShoutMessage } from '../../../../../../backend/Components/Shoutbox/Interface';
|
||||||
|
|
||||||
|
@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">
|
||||||
|
</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: ApiService
|
||||||
|
) {}
|
||||||
|
|
||||||
|
submit(event){
|
||||||
|
this.sendMessage({
|
||||||
|
date: ""+Date.now(),
|
||||||
|
message: event.message,
|
||||||
|
sender: this.api.getCurrentUser().username
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
sendMessage : (msg:ShoutMessage)=>Promise<void>
|
||||||
|
}
|
||||||
@@ -3,16 +3,27 @@
|
|||||||
<a (click)="toggleSidebar()" href="#" class="sidebar-toggle">
|
<a (click)="toggleSidebar()" href="#" class="sidebar-toggle">
|
||||||
<nb-icon icon="menu-2-outline"></nb-icon>
|
<nb-icon icon="menu-2-outline"></nb-icon>
|
||||||
</a>
|
</a>
|
||||||
<a class="logo" href="#" (click)="navigateHome()">Frontcraft</a>
|
<a class="logo" href="#" (click)="navigateHome()">{{title}}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="header-container">
|
<div class="header-container">
|
||||||
<nb-actions size="small">
|
<nb-actions size="small">
|
||||||
|
|
||||||
<nb-action class="control-item" icon="message-square-outline"></nb-action>
|
<nb-action
|
||||||
<nb-action class="control-item" icon="bell-outline"></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 [nbContextMenu]="userMenu"
|
<nb-user [nbContextMenu]="userMenu"
|
||||||
[onlyPicture]="false"
|
[onlyPicture]="false"
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
import { Component, OnDestroy, OnInit } from '@angular/core';
|
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||||
import { NbMediaBreakpointsService, NbMenuService, NbSidebarService, NbThemeService, NbContextMenuComponent, NbMenuItem } from '@nebular/theme';
|
import { NbMediaBreakpointsService, NbSidebarService, NbThemeService, NbMenuItem, NbDialogService } from '@nebular/theme';
|
||||||
|
|
||||||
import { LayoutService } from '../../../@core/utils';
|
import { LayoutService } from '../../../@core/utils';
|
||||||
import { map, takeUntil } from 'rxjs/operators';
|
import { map, takeUntil } from 'rxjs/operators';
|
||||||
import { Subject } from 'rxjs';
|
import { Subject } from 'rxjs';
|
||||||
import { LoginApiService } from '../../../frontcraft/services/login-api';
|
import { ApiService } from '../../../frontcraft/services/login-api';
|
||||||
import { User } from '../../../../../../backend/Types/Types';
|
import { User } from '../../../../../../backend/Types/Types';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
import { ChatComponent } from './chat.component';
|
||||||
|
import { ShoutMessage } from '../../../../../../backend/Components/Shoutbox/Interface';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ngx-header',
|
selector: 'ngx-header',
|
||||||
@@ -15,8 +18,8 @@ import { User } from '../../../../../../backend/Types/Types';
|
|||||||
export class HeaderComponent implements OnInit, OnDestroy {
|
export class HeaderComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
private destroy$: Subject<void> = new Subject<void>();
|
private destroy$: Subject<void> = new Subject<void>();
|
||||||
userPictureOnly: boolean = false;
|
|
||||||
user: User;
|
user: User;
|
||||||
|
title = "Loading ... ";
|
||||||
|
|
||||||
themes = [
|
themes = [
|
||||||
{
|
{
|
||||||
@@ -38,37 +41,46 @@ export class HeaderComponent implements OnInit, OnDestroy {
|
|||||||
];
|
];
|
||||||
|
|
||||||
currentTheme = 'dark';
|
currentTheme = 'dark';
|
||||||
|
|
||||||
userMenu : NbMenuItem[] = [ { title: 'Log out', link: '/auth/logout' } ];
|
userMenu : NbMenuItem[] = [ { title: 'Log out', link: '/auth/logout' } ];
|
||||||
|
|
||||||
|
sendMessage: any = console.log
|
||||||
|
chatwindow: ChatComponent
|
||||||
|
chatlog: ShoutMessage[] = []
|
||||||
|
newmessage = false
|
||||||
|
lastmessage = "asdasd"
|
||||||
|
|
||||||
constructor(private sidebarService: NbSidebarService,
|
constructor(private sidebarService: NbSidebarService,
|
||||||
private menuService: NbMenuService,
|
private router: Router,
|
||||||
private themeService: NbThemeService,
|
private themeService: NbThemeService,
|
||||||
private layoutService: LayoutService,
|
private layoutService: LayoutService,
|
||||||
private breakpointService: NbMediaBreakpointsService,
|
private breakpointService: NbMediaBreakpointsService,
|
||||||
private loginService: LoginApiService,
|
private api: ApiService,
|
||||||
|
private dialogService : NbDialogService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.currentTheme = this.themeService.currentTheme;
|
this.currentTheme = this.themeService.currentTheme;
|
||||||
|
|
||||||
this.user = this.loginService.getCurrentUser()
|
this.user = this.api.getCurrentUser()
|
||||||
if(this.user)
|
if(this.user)
|
||||||
this.userMenu.unshift({ title: 'Profile', link: '/frontcraft/user/'+this.user.username });
|
this.userMenu.unshift({ title: 'Profile', link: '/frontcraft/user/'+this.user.username });
|
||||||
|
|
||||||
/*
|
|
||||||
this.userService.getUsers()
|
|
||||||
.pipe(takeUntil(this.destroy$))
|
|
||||||
.subscribe((users: any) => this.user = users.lee);
|
|
||||||
*/
|
|
||||||
|
|
||||||
const { xl } = this.breakpointService.getBreakpointsMap();
|
this.api.get('GuildManager').getGuildInfo().then(info => {
|
||||||
this.themeService.onMediaQueryChange()
|
this.title = info.name
|
||||||
.pipe(
|
})
|
||||||
map(([, currentBreakpoint]) => currentBreakpoint.width < xl),
|
|
||||||
takeUntil(this.destroy$),
|
this.api.connectShoutbox((msg) => {
|
||||||
)
|
this.chatlog.push(msg)
|
||||||
.subscribe((isLessThanXl: boolean) => this.userPictureOnly = isLessThanXl);
|
if(msg.message != this.lastmessage)
|
||||||
|
this.newmessage = 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(
|
||||||
@@ -78,6 +90,20 @@ 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();
|
||||||
@@ -95,11 +121,11 @@ export class HeaderComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logout() {
|
logout() {
|
||||||
this.loginService.logout()
|
this.api.logout()
|
||||||
}
|
}
|
||||||
|
|
||||||
navigateHome() {
|
navigateHome() {
|
||||||
this.menuService.navigateHome();
|
this.router.navigateByUrl('/')
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,9 @@ import {
|
|||||||
NbSelectModule,
|
NbSelectModule,
|
||||||
NbIconModule,
|
NbIconModule,
|
||||||
NbThemeModule,
|
NbThemeModule,
|
||||||
|
NbDialogModule,
|
||||||
|
NbChatModule,
|
||||||
|
NbCardModule,
|
||||||
} from '@nebular/theme';
|
} from '@nebular/theme';
|
||||||
import { NbEvaIconsModule } from '@nebular/eva-icons';
|
import { NbEvaIconsModule } from '@nebular/eva-icons';
|
||||||
import { NbSecurityModule } from '@nebular/security';
|
import { NbSecurityModule } from '@nebular/security';
|
||||||
@@ -39,6 +42,7 @@ 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,
|
||||||
@@ -53,6 +57,9 @@ const NB_MODULES = [
|
|||||||
NbSelectModule,
|
NbSelectModule,
|
||||||
NbIconModule,
|
NbIconModule,
|
||||||
NbEvaIconsModule,
|
NbEvaIconsModule,
|
||||||
|
NbChatModule,
|
||||||
|
NbCardModule,
|
||||||
|
NbDialogModule.forChild()
|
||||||
];
|
];
|
||||||
const COMPONENTS = [
|
const COMPONENTS = [
|
||||||
HeaderComponent,
|
HeaderComponent,
|
||||||
@@ -62,7 +69,8 @@ const COMPONENTS = [
|
|||||||
OneColumnLayoutComponent,
|
OneColumnLayoutComponent,
|
||||||
ThreeColumnsLayoutComponent,
|
ThreeColumnsLayoutComponent,
|
||||||
TwoColumnsLayoutComponent,
|
TwoColumnsLayoutComponent,
|
||||||
OneColumnNoSidebarLayoutComponent
|
OneColumnNoSidebarLayoutComponent,
|
||||||
|
ChatComponent
|
||||||
];
|
];
|
||||||
const PIPES = [
|
const PIPES = [
|
||||||
CapitalizePipe,
|
CapitalizePipe,
|
||||||
@@ -76,6 +84,9 @@ const PIPES = [
|
|||||||
imports: [CommonModule, ...NB_MODULES],
|
imports: [CommonModule, ...NB_MODULES],
|
||||||
exports: [CommonModule, ...PIPES, ...COMPONENTS],
|
exports: [CommonModule, ...PIPES, ...COMPONENTS],
|
||||||
declarations: [...COMPONENTS, ...PIPES],
|
declarations: [...COMPONENTS, ...PIPES],
|
||||||
|
entryComponents: [
|
||||||
|
ChatComponent
|
||||||
|
]
|
||||||
})
|
})
|
||||||
export class ThemeModule {
|
export class ThemeModule {
|
||||||
static forRoot(): ModuleWithProviders {
|
static forRoot(): ModuleWithProviders {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { AnalyticsService } from './@core/utils/analytics.service';
|
import { AnalyticsService } from './@core/utils/analytics.service';
|
||||||
import { LoginApiService } from './frontcraft/services/login-api';
|
import { ApiService } from './frontcraft/services/login-api';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ngx-app',
|
selector: 'ngx-app',
|
||||||
@@ -13,7 +13,7 @@ import { LoginApiService } from './frontcraft/services/login-api';
|
|||||||
})
|
})
|
||||||
export class AppComponent implements OnInit {
|
export class AppComponent implements OnInit {
|
||||||
|
|
||||||
constructor(private loginSvc: LoginApiService, private analytics: AnalyticsService) {
|
constructor(private loginSvc: ApiService, private analytics: AnalyticsService) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule, APP_INITIALIZER } from '@angular/core';
|
||||||
import { HttpClientModule } from '@angular/common/http';
|
import { HttpClientModule } from '@angular/common/http';
|
||||||
import { CoreModule } from './@core/core.module';
|
import { CoreModule } from './@core/core.module';
|
||||||
import { ThemeModule } from './@theme/theme.module';
|
import { ThemeModule } from './@theme/theme.module';
|
||||||
@@ -20,6 +20,8 @@ import {
|
|||||||
NbToastrModule,
|
NbToastrModule,
|
||||||
NbWindowModule,
|
NbWindowModule,
|
||||||
} from '@nebular/theme';
|
} from '@nebular/theme';
|
||||||
|
import { ApiService, initializeLoginSvc } from './frontcraft/services/login-api';
|
||||||
|
import { CookieService } from 'ngx-cookie-service';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [AppComponent],
|
declarations: [AppComponent],
|
||||||
@@ -42,7 +44,13 @@ import {
|
|||||||
],
|
],
|
||||||
bootstrap: [AppComponent],
|
bootstrap: [AppComponent],
|
||||||
providers: [
|
providers: [
|
||||||
|
ApiService,
|
||||||
|
{
|
||||||
|
provide: APP_INITIALIZER,
|
||||||
|
deps: [CookieService],
|
||||||
|
multi: true,
|
||||||
|
useFactory: initializeLoginSvc
|
||||||
|
},
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class AppModule {
|
export class AppModule {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { LoginApiService } from '../services/login-api';
|
import { ApiService } from '../services/login-api';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -13,7 +13,7 @@ import { Router } from '@angular/router';
|
|||||||
|
|
||||||
export class AuthComponent implements OnInit{
|
export class AuthComponent implements OnInit{
|
||||||
constructor(
|
constructor(
|
||||||
private loginSvc : LoginApiService,
|
private loginSvc : ApiService,
|
||||||
private router: Router
|
private router: Router
|
||||||
){}
|
){}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<form (ngSubmit)="login()" #form="ngForm" aria-labelledby="title">
|
<form (ngSubmit)="login()" #form="ngForm" aria-labelledby="title">
|
||||||
|
|
||||||
<div class="form-control-group">
|
<div class="form-control-group">
|
||||||
<label class="label" for="input-email">Email address:</label>
|
<label class="label" for="input-email">Username:</label>
|
||||||
<input nbInput
|
<input nbInput
|
||||||
fullWidth
|
fullWidth
|
||||||
[(ngModel)]="user.name"
|
[(ngModel)]="user.name"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { LoginApiService } from '../../services/login-api';
|
import { ApiService } from '../../services/login-api';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -21,7 +21,7 @@ export class MyLoginComponent implements OnInit{
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private router : Router,
|
private router : Router,
|
||||||
private loginApi : LoginApiService
|
private loginApi : ApiService
|
||||||
){}
|
){}
|
||||||
|
|
||||||
ngOnInit(){
|
ngOnInit(){
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { LoginApiService } from '../../services/login-api';
|
import { ApiService } from '../../services/login-api';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -9,11 +9,11 @@ import { Router } from '@angular/router';
|
|||||||
export class LogoutComponent implements OnInit{
|
export class LogoutComponent implements OnInit{
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private loginApi : LoginApiService
|
private api : ApiService
|
||||||
){}
|
){}
|
||||||
|
|
||||||
ngOnInit(){
|
ngOnInit(){
|
||||||
this.loginApi.logout()
|
this.api.logout()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -2,21 +2,6 @@
|
|||||||
|
|
||||||
<form (ngSubmit)="onSubmit()" #form="ngForm" aria-labelledby="title">
|
<form (ngSubmit)="onSubmit()" #form="ngForm" aria-labelledby="title">
|
||||||
|
|
||||||
<div class="form-control-group">
|
|
||||||
<label class="label" for="input-email">Email address:</label>
|
|
||||||
<input nbInput
|
|
||||||
fullWidth
|
|
||||||
[(ngModel)]="user.email"
|
|
||||||
#email="ngModel"
|
|
||||||
name="name"
|
|
||||||
id="input-email"
|
|
||||||
pattern=".+"
|
|
||||||
placeholder="Email Address"
|
|
||||||
fieldSize="giant"
|
|
||||||
autofocus
|
|
||||||
[required]="true">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-control-group">
|
<div class="form-control-group">
|
||||||
<label class="label" for="input-username">Username:</label>
|
<label class="label" for="input-username">Username:</label>
|
||||||
<input nbInput
|
<input nbInput
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { LoginApiService, hash } from '../../services/login-api';
|
import { ApiService as ApiService, hash } from '../../services/login-api';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { _Rank, _Class, Class, User } from '../../../../../../backend/Types/Types'
|
import { _Rank, _Class, Class, User } from '../../../../../../backend/Types/Types'
|
||||||
import { specs } from '../../../../../../backend/Types/PlayerSpecs'
|
import { specs } from '../../../../../../backend/Types/PlayerSpecs'
|
||||||
|
import { race } from 'rxjs';
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -20,7 +21,6 @@ export class RegisterComponent implements OnInit{
|
|||||||
spec : "Arms"
|
spec : "Arms"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ranks = _Rank
|
ranks = _Rank
|
||||||
classes = _Class
|
classes = _Class
|
||||||
selectedClass : Class = "Warrior"
|
selectedClass : Class = "Warrior"
|
||||||
@@ -30,11 +30,11 @@ export class RegisterComponent implements OnInit{
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private router : Router,
|
private router : Router,
|
||||||
private loginApi : LoginApiService
|
private api : ApiService
|
||||||
){}
|
){}
|
||||||
|
|
||||||
ngOnInit(){
|
ngOnInit(){
|
||||||
this.loginApi.checkLogin().then(loggedin => {
|
this.api.checkLogin().then(loggedin => {
|
||||||
if(loggedin){
|
if(loggedin){
|
||||||
this.router.navigateByUrl("/")
|
this.router.navigateByUrl("/")
|
||||||
}
|
}
|
||||||
@@ -60,27 +60,27 @@ export class RegisterComponent implements OnInit{
|
|||||||
this.character = {}
|
this.character = {}
|
||||||
|
|
||||||
try{
|
try{
|
||||||
const usr = await this.loginApi.getUnprivilegedSocket().Authenticator.createUser(user)
|
const usr = await this.api.get('UserManager').createUser(user)
|
||||||
}catch(e){
|
}catch(e){
|
||||||
alert("Error creating user"+e)
|
alert("Error creating user"+e)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
try{
|
try{
|
||||||
await this.loginApi.login(user.username, pw)
|
await this.api.login(user.username, pw)
|
||||||
await this.loginApi.getFeature('createCharacter').then(async feature => {
|
|
||||||
if(!feature) return
|
const characterManager = this.api.get('CharacterManager')
|
||||||
const specid = await this.loginApi.getUnprivilegedSocket().CharacterManager.getSpecId(char['class'], char['spec'])
|
|
||||||
await feature.createCharacter(this.loginApi.getAuth().token.value, {
|
const specid = await characterManager.getSpecId(char['class'], char['spec'])
|
||||||
charactername: char.name,
|
await characterManager.createCharacter(this.api.getAuth().token.value, {
|
||||||
specid: specid,
|
charactername: char.name,
|
||||||
userid: this.loginApi.getAuth().user.id!
|
specid: specid,
|
||||||
})
|
userid: this.api.getAuth().user.id!,
|
||||||
|
race: 'Human'
|
||||||
})
|
})
|
||||||
}catch(e){
|
}catch(e){
|
||||||
alert("Error creating character"+e)
|
alert("Error creating character"+e)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,23 @@
|
|||||||
<nb-card
|
<nb-card
|
||||||
|
class = "col-12 col-xl-9"
|
||||||
status="control">
|
status="control">
|
||||||
<nb-card-header [ngStyle]="{'color': color}" style="text-transform: capitalize;">
|
<nb-card-header [ngStyle]="{'color': color}" style="text-transform: capitalize;">
|
||||||
{{char.charactername}}
|
{{char.charactername}}
|
||||||
</nb-card-header>
|
</nb-card-header>
|
||||||
<nb-card-body>
|
<nb-card-body>
|
||||||
|
{{char.race}}<br />
|
||||||
{{char.specname}} {{char.class}}<br />
|
{{char.specname}} {{char.class}}<br />
|
||||||
Owned by <a [routerLink]="'/frontcraft/user/'+char.username"> {{char.username}} ({{char.rank}})</a>
|
Owned by <a [routerLink]="'/frontcraft/user/'+char.username"> {{char.username}} ({{char.rank}})</a>
|
||||||
|
<br/><br />
|
||||||
|
<span *ngFor="let token of tokens">
|
||||||
|
[ {{token.level}} ]
|
||||||
|
<a [ngStyle]="{'color':token.quality=='Epic'?'#a335ee':'#ff8000'}"
|
||||||
|
target="_blank"
|
||||||
|
[href]="token.url">
|
||||||
|
<img style="min-width: 25px; width: 2.25vw; max-width: 50px"
|
||||||
|
[src]="'https://wow.zamimg.com/images/wow/icons/large/'+token.iconname+'.jpg'" />
|
||||||
|
{{token.itemname}}
|
||||||
|
</a><br />
|
||||||
|
</span>
|
||||||
</nb-card-body>
|
</nb-card-body>
|
||||||
</nb-card>
|
</nb-card>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { LoginApiService } from '../../services/login-api';
|
import { ApiService as ApiService } from '../../services/login-api';
|
||||||
import { Spec, User, Character } from '../../../../../../backend/Types/Types';
|
import { Spec, User, Character } from '../../../../../../backend/Types/Types';
|
||||||
import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
|
import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
|
||||||
|
|
||||||
@@ -12,22 +12,24 @@ export class FrontcraftCharacterComponent implements OnInit{
|
|||||||
|
|
||||||
char : (Character & User & Spec) = {} as any
|
char : (Character & User & Spec) = {} as any
|
||||||
color : string
|
color : string
|
||||||
|
tokens
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private login: LoginApiService,
|
private api: ApiService,
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
private router: Router,
|
|
||||||
){}
|
){}
|
||||||
|
|
||||||
async ngOnInit(){
|
async ngOnInit(){
|
||||||
const param = this.route.snapshot.paramMap.get('name');
|
const param = this.route.snapshot.paramMap.get('name');
|
||||||
this.login.getUnprivilegedSocket()
|
this.api.get('CharacterManager')
|
||||||
.CharacterManager
|
|
||||||
.getCharacterByName(param)
|
.getCharacterByName(param)
|
||||||
.then((char) => {
|
.then((char) => {
|
||||||
if(char){
|
if(char){
|
||||||
this.color = getClassColor(char.class)
|
this.color = getClassColor(char.class)
|
||||||
this.char = char
|
this.char = char
|
||||||
|
this.api.get('ItemManager').getTokens(this.char).then(tokens => {
|
||||||
|
this.tokens = tokens
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
<nb-card class="col-12 col-xl-9">
|
||||||
|
<nb-card-body>
|
||||||
|
|
||||||
|
<div echarts [options]="options" class="echart" (chartClick)="onChartClick($event)"></div>
|
||||||
|
|
||||||
|
</nb-card-body>
|
||||||
|
</nb-card>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<nb-card class="col-12 col-xl-9">
|
||||||
|
<nb-card-body>
|
||||||
|
<input type="text" nbInput [(ngModel)]="search" (change)="changeSearch()" placeholder="Search" fullWidth="true" />
|
||||||
|
<table class="col-12">
|
||||||
|
<tr *ngFor="let character of displayedcharacters">
|
||||||
|
<td>
|
||||||
|
<a style="text-transform: capitalize;" [routerLink]="'/frontcraft/character/'+character.charactername" [ngStyle]="{'color': character.color}">
|
||||||
|
{{character.charactername}} <span *ngIf="character.alt">(Alt)</span>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{character.race}}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{character.specname}}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{character.class}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</nb-card-body>
|
||||||
|
</nb-card>
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
import { Component, OnInit, AfterViewInit, OnDestroy } from '@angular/core';
|
||||||
|
import { NbThemeService } from '@nebular/theme';
|
||||||
|
import { ApiService } from '../../services/login-api';
|
||||||
|
import { _Class } from '../../../../../../backend/Types/Types';
|
||||||
|
import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'characters',
|
||||||
|
templateUrl: './characters.component.html',
|
||||||
|
})
|
||||||
|
export class FrontcraftCharactersComponent implements AfterViewInit, OnDestroy{
|
||||||
|
options: any = {};
|
||||||
|
themeSubscription: any;
|
||||||
|
search = ""
|
||||||
|
|
||||||
|
allcharacters = []
|
||||||
|
displayedcharacters = []
|
||||||
|
|
||||||
|
constructor(private theme: NbThemeService, private api:ApiService) {
|
||||||
|
}
|
||||||
|
|
||||||
|
changeSearch(){
|
||||||
|
if(!this.search || this.search == "")
|
||||||
|
this.displayedcharacters = this.allcharacters
|
||||||
|
else{
|
||||||
|
const searchterm = this.search.toLocaleLowerCase()
|
||||||
|
this.displayedcharacters = this.allcharacters.filter(char =>
|
||||||
|
char.charactername.toLowerCase().includes(searchterm) ||
|
||||||
|
char.class.toLowerCase().includes(searchterm) ||
|
||||||
|
char.specname.toLowerCase().includes(searchterm) ||
|
||||||
|
char.race.toLowerCase().includes(searchterm)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onChartClick(event){
|
||||||
|
this.search = event.name
|
||||||
|
this.changeSearch()
|
||||||
|
}
|
||||||
|
|
||||||
|
ngAfterViewInit() {
|
||||||
|
this.themeSubscription = this.theme.getJsTheme().subscribe(async config => {
|
||||||
|
const data = {}
|
||||||
|
|
||||||
|
await this.api.get('CharacterManager').getCharacters().then(chars => {
|
||||||
|
chars.forEach(char => {
|
||||||
|
char['color'] = getClassColor(char.class)
|
||||||
|
})
|
||||||
|
this.allcharacters = chars
|
||||||
|
this.displayedcharacters = chars
|
||||||
|
this.search=""
|
||||||
|
})
|
||||||
|
|
||||||
|
await Promise.all(_Class.map(async cls => {
|
||||||
|
const c = await this.api.get('CharacterManager').getHeadCount(cls)
|
||||||
|
data[cls] = c
|
||||||
|
}))
|
||||||
|
|
||||||
|
const echarts: any = config.variables.echarts;
|
||||||
|
this.options = {
|
||||||
|
backgroundColor: echarts.bg,
|
||||||
|
color: [
|
||||||
|
"#FFF569",
|
||||||
|
"#C79C6E",
|
||||||
|
"#FFFFFF",
|
||||||
|
"#40C7EB",
|
||||||
|
"#A9D271",
|
||||||
|
"#F58CBA",
|
||||||
|
"#FF7D0A",
|
||||||
|
"#8787ED"
|
||||||
|
],
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'item',
|
||||||
|
formatter: '{b} : {c} ({d}%)',
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: 'Classes',
|
||||||
|
type: 'pie',
|
||||||
|
radius: '80%',
|
||||||
|
center: ['50%', '50%'],
|
||||||
|
data: [
|
||||||
|
{ value: data['Rogue'], name: 'Rogue' },
|
||||||
|
{ value: data['Warrior'], name: 'Warrior' },
|
||||||
|
{ value: data['Priest'], name: 'Priest' },
|
||||||
|
{ value: data['Mage'], name: 'Mage' },
|
||||||
|
{ value: data['Hunter'], name: 'Hunter' },
|
||||||
|
{ value: data['Paladin'], name: 'Paladin' },
|
||||||
|
{ value: data['Druid'], name: 'Druid' },
|
||||||
|
{ value: data['Warlock'], name: 'Warlock' },
|
||||||
|
],
|
||||||
|
itemStyle: {
|
||||||
|
emphasis: {
|
||||||
|
shadowBlur: 10,
|
||||||
|
shadowOffsetX: 0,
|
||||||
|
shadowColor: echarts.itemHoverShadowColor,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
normal: {
|
||||||
|
textStyle: {
|
||||||
|
color: echarts.textColor,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
labelLine: {
|
||||||
|
normal: {
|
||||||
|
lineStyle: {
|
||||||
|
color: echarts.axisLineColor,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
this.themeSubscription.unsubscribe();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
<nb-card>
|
|
||||||
<nb-card-body>
|
|
||||||
|
|
||||||
<label class="search-label" for="search">Search:</label>
|
|
||||||
<input nbInput [nbFilterInput]="dataSource" id="search" class="search-input">
|
|
||||||
|
|
||||||
<table [nbTreeGrid]="dataSource" [nbSort]="dataSource" (sort)="updateSort($event)">
|
|
||||||
|
|
||||||
<tr nbTreeGridHeaderRow *nbTreeGridHeaderRowDef="allColumns"></tr>
|
|
||||||
<tr nbTreeGridRow *nbTreeGridRowDef="let row; columns: allColumns"></tr>
|
|
||||||
|
|
||||||
<ng-container [nbTreeGridColumnDef]="customColumn">
|
|
||||||
<th nbTreeGridHeaderCell [nbSortHeader]="getSortDirection(customColumn)" *nbTreeGridHeaderCellDef>
|
|
||||||
{{customColumn}}
|
|
||||||
</th>
|
|
||||||
<td nbTreeGridCell *nbTreeGridCellDef="let row">
|
|
||||||
<nb-tree-grid-row-toggle
|
|
||||||
*ngIf="row.children && row.children.length">
|
|
||||||
</nb-tree-grid-row-toggle>
|
|
||||||
|
|
||||||
{{row.data[customColumn]}}
|
|
||||||
</td>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<ng-container *ngFor="let column of defaultColumns; let index = index"
|
|
||||||
[nbTreeGridColumnDef]="column"
|
|
||||||
[showOn]="getShowOn(index)">
|
|
||||||
<th nbTreeGridHeaderCell [nbSortHeader]="getSortDirection(column)" *nbTreeGridHeaderCellDef>
|
|
||||||
{{column}}
|
|
||||||
</th>
|
|
||||||
<td nbTreeGridCell *nbTreeGridCellDef="let row">{{row.data[column] || '-'}}</td>
|
|
||||||
</ng-container>
|
|
||||||
</table>
|
|
||||||
</nb-card-body>
|
|
||||||
</nb-card>
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
button[nbTreeGridRowToggle] {
|
|
||||||
background: transparent;
|
|
||||||
border: none;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-label {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
.search-input {
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nb-column-name {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (min-width: 400px) {
|
|
||||||
.nb-column-name,
|
|
||||||
.nb-column-size {
|
|
||||||
width: 50%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (min-width: 500px) {
|
|
||||||
.nb-column-name,
|
|
||||||
.nb-column-size,
|
|
||||||
.nb-column-kind {
|
|
||||||
width: 33.333%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (min-width: 600px) {
|
|
||||||
.nb-column-name {
|
|
||||||
width: 31%;
|
|
||||||
}
|
|
||||||
.nb-column-size,
|
|
||||||
.nb-column-kind,
|
|
||||||
.nb-column-items {
|
|
||||||
width: 23%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
import { Component } from '@angular/core';
|
|
||||||
import { NbSortDirection, NbSortRequest, NbTreeGridDataSourceBuilder, NbTreeGridDataSource } from '@nebular/theme';
|
|
||||||
|
|
||||||
interface TreeNode<T> {
|
|
||||||
data: T;
|
|
||||||
children?: TreeNode<T>[];
|
|
||||||
expanded?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Row {
|
|
||||||
name: string,
|
|
||||||
character: any,
|
|
||||||
SRC: any,
|
|
||||||
}
|
|
||||||
|
|
||||||
type TreeType = TreeNode<Row>
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'dashboard',
|
|
||||||
templateUrl: './dashboard.component.html',
|
|
||||||
styleUrls: ['./tree-grid-shared.scss', './dashboard.component.scss'],
|
|
||||||
})
|
|
||||||
export class FrontcraftDashboardComponent{
|
|
||||||
customColumn = 'name';
|
|
||||||
defaultColumns = [ 'character', 'SRC'/*, 'Profile'*/ ];
|
|
||||||
allColumns = [ this.customColumn, ...this.defaultColumns ];
|
|
||||||
|
|
||||||
dataSource: NbTreeGridDataSource<TreeType>;
|
|
||||||
|
|
||||||
sortColumn: string;
|
|
||||||
sortDirection: NbSortDirection = NbSortDirection.NONE;
|
|
||||||
|
|
||||||
constructor(private dataSourceBuilder: NbTreeGridDataSourceBuilder<TreeType>) {
|
|
||||||
this.dataSource = this.dataSourceBuilder.create(this.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateSort(sortRequest: NbSortRequest): void {
|
|
||||||
this.sortColumn = sortRequest.column;
|
|
||||||
this.sortDirection = sortRequest.direction;
|
|
||||||
}
|
|
||||||
|
|
||||||
getSortDirection(column: string): NbSortDirection {
|
|
||||||
if (this.sortColumn === column) {
|
|
||||||
return this.sortDirection;
|
|
||||||
}
|
|
||||||
return NbSortDirection.NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
private data: TreeType[] = [
|
|
||||||
{
|
|
||||||
data: {name: 'a', character: 2, SRC: 0},
|
|
||||||
children: [
|
|
||||||
{data: {name: 'a', character: 'Warrior', SRC: 'Arms'}}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
getShowOn(index: number) {
|
|
||||||
const minWithForMultipleColumns = 400;
|
|
||||||
const nextColumnStep = 100;
|
|
||||||
return minWithForMultipleColumns + (nextColumnStep * index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
::ng-deep {
|
|
||||||
body {
|
|
||||||
min-height: 20rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nb-tree-grid-header-cell,
|
|
||||||
.nb-tree-grid-header-cell button {
|
|
||||||
text-transform: capitalize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Component, AfterContentChecked, OnInit } from '@angular/core';
|
import { Component, AfterContentChecked, OnInit, AfterContentInit } from '@angular/core';
|
||||||
import { NbMenuItem } from '@nebular/theme';
|
import { NbMenuItem } from '@nebular/theme';
|
||||||
import { LoginApiService } from '../services/login-api';
|
import { ApiService } from '../services/login-api';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -9,35 +9,35 @@ import { Router } from '@angular/router';
|
|||||||
|
|
||||||
<ngx-one-column-layout>
|
<ngx-one-column-layout>
|
||||||
<nb-menu [items]="menu"></nb-menu>
|
<nb-menu [items]="menu"></nb-menu>
|
||||||
|
<router-outlet ></router-outlet>
|
||||||
<router-outlet></router-outlet>
|
|
||||||
</ngx-one-column-layout>
|
</ngx-one-column-layout>
|
||||||
`,
|
`,
|
||||||
})
|
})
|
||||||
export class PagesLayoutComponent implements OnInit{
|
export class PagesLayoutComponent implements AfterContentInit{
|
||||||
menu:NbMenuItem[] = [{
|
menu:NbMenuItem[] = [{
|
||||||
icon: 'people-outline',
|
icon: 'image',
|
||||||
title: 'People',
|
title: 'Raids',
|
||||||
link: '/frontcraft/people'
|
link: '/frontcraft/raids',
|
||||||
},{
|
},{
|
||||||
icon: 'clock-outline',
|
icon: 'people',
|
||||||
title: 'Raids'
|
title: 'Characters',
|
||||||
|
link: '/frontcraft/characters',
|
||||||
},{
|
},{
|
||||||
icon: 'clock-outline',
|
icon: 'shopping-cart',
|
||||||
title: 'character',
|
title: 'Token Shop',
|
||||||
link: '/frontcraft/character/a'
|
link: '/frontcraft/shop',
|
||||||
},{
|
},{
|
||||||
icon: 'clock-outline',
|
icon: 'book-open-outline',
|
||||||
title: 'user',
|
title: 'Loot Rules',
|
||||||
link: '/frontcraft/user/a'
|
link: '/frontcraft/rules',
|
||||||
}]
|
}]
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private loginSvc : LoginApiService,
|
private loginSvc : ApiService,
|
||||||
private router : Router
|
private router : Router
|
||||||
){}
|
){}
|
||||||
|
|
||||||
ngOnInit() : void {
|
ngAfterContentInit() : void {
|
||||||
this.loginSvc.checkLogin().then(loggedin => {
|
this.loginSvc.checkLogin().then(loggedin => {
|
||||||
if(!loggedin){
|
if(!loggedin){
|
||||||
this.router.navigateByUrl("/auth")
|
this.router.navigateByUrl("/auth")
|
||||||
|
|||||||
@@ -1,35 +1,55 @@
|
|||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { RouterModule, Routes } from '@angular/router';
|
import { RouterModule, Routes } from '@angular/router';
|
||||||
import { FrontcraftDashboardComponent } from './dashboard/dashboard.component';
|
|
||||||
import { PagesLayoutComponent } from './pages-layout.component';
|
import { PagesLayoutComponent } from './pages-layout.component';
|
||||||
import { FrontcraftCharacterComponent } from './character/character.component';
|
import { FrontcraftCharacterComponent } from './character/character.component';
|
||||||
import { FrontcraftUserComponent } from './user/user.component';
|
import { FrontcraftUserComponent } from './user/user.component';
|
||||||
import { FrontcraftPeopleComponent } from './people/people.component';
|
import { FrontcraftRaidsComponent } from './raids/raids.component';
|
||||||
|
import { FrontcraftRaidComponent } from './raid/raid.component';
|
||||||
|
import { FrontcraftArchiveComponent } from './raid/archive.component';
|
||||||
|
import { FrontcraftShopComponent } from './shop/shop.component';
|
||||||
|
import { FrontcraftRulesComponent } from './rules/rules.component';
|
||||||
|
import { FrontcraftCharactersComponent } from './characters/characters.component';
|
||||||
|
|
||||||
export const routes: Routes = [
|
export const routes: Routes = [
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
component: PagesLayoutComponent,
|
component: PagesLayoutComponent,
|
||||||
children: [
|
children: [
|
||||||
{
|
|
||||||
path: 'people',
|
|
||||||
component: FrontcraftPeopleComponent
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: 'user/:name',
|
path: 'user/:name',
|
||||||
component: FrontcraftUserComponent
|
component: FrontcraftUserComponent
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'raid/:id',
|
||||||
|
component: FrontcraftRaidComponent
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'archive/:id',
|
||||||
|
component: FrontcraftArchiveComponent
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'raids',
|
||||||
|
component: FrontcraftRaidsComponent
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'character/:name',
|
path: 'character/:name',
|
||||||
component: FrontcraftCharacterComponent
|
component: FrontcraftCharacterComponent
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'dashboard',
|
path: 'characters',
|
||||||
component: FrontcraftDashboardComponent,
|
component: FrontcraftCharactersComponent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'shop',
|
||||||
|
component: FrontcraftShopComponent
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'rules',
|
||||||
|
component: FrontcraftRulesComponent
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '**',
|
path: '**',
|
||||||
redirectTo: 'dashboard'
|
redirectTo: 'raids'
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import { CommonModule } from '@angular/common';
|
|||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
NbAlertModule,
|
NbAlertModule,
|
||||||
NbButtonModule,
|
NbButtonModule,
|
||||||
@@ -10,10 +9,16 @@ import {
|
|||||||
NbInputModule,
|
NbInputModule,
|
||||||
NbMenuModule,
|
NbMenuModule,
|
||||||
NbCardModule,
|
NbCardModule,
|
||||||
NbTreeGridModule
|
NbTreeGridModule,
|
||||||
|
NbListModule,
|
||||||
|
NbTabsetModule,
|
||||||
|
NbIconModule,
|
||||||
|
NbWindowModule,
|
||||||
|
NbPopoverModule,
|
||||||
|
NbDatepickerModule,
|
||||||
|
NbSelectModule
|
||||||
} from '@nebular/theme';
|
} from '@nebular/theme';
|
||||||
import { MyAuthRoutingModule } from './pages-routing.module';
|
import { MyAuthRoutingModule } from './pages-routing.module';
|
||||||
import { FrontcraftDashboardComponent } from './dashboard/dashboard.component';
|
|
||||||
import { PagesLayoutComponent } from './pages-layout.component';
|
import { PagesLayoutComponent } from './pages-layout.component';
|
||||||
import { ThemeModule } from '../../@theme/theme.module';
|
import { ThemeModule } from '../../@theme/theme.module';
|
||||||
import { DashboardModule } from '../../demo_pages/dashboard/dashboard.module';
|
import { DashboardModule } from '../../demo_pages/dashboard/dashboard.module';
|
||||||
@@ -21,7 +26,17 @@ import { ECommerceModule } from '../../demo_pages/e-commerce/e-commerce.module';
|
|||||||
import { MiscellaneousModule } from '../../demo_pages/miscellaneous/miscellaneous.module';
|
import { MiscellaneousModule } from '../../demo_pages/miscellaneous/miscellaneous.module';
|
||||||
import { FrontcraftCharacterComponent } from './character/character.component';
|
import { FrontcraftCharacterComponent } from './character/character.component';
|
||||||
import { FrontcraftUserComponent } from './user/user.component';
|
import { FrontcraftUserComponent } from './user/user.component';
|
||||||
import { FrontcraftPeopleComponent } from './people/people.component';
|
import { FrontcraftRaidsComponent } from './raids/raids.component';
|
||||||
|
import { FrontcraftCreateRaidsComponent } from './raids/createraid.compontent';
|
||||||
|
import { FrontcraftRaidComponent } from './raid/raid.component';
|
||||||
|
import { FrontcraftArchiveComponent } from './raid/archive.component';
|
||||||
|
import { NbEvaIconsModule } from '@nebular/eva-icons';
|
||||||
|
import { FrontcraftCharacerpickerComponent } from './raid/characterpicker.component';
|
||||||
|
import { FrontcraftShopComponent, FrontcraftBuyTokenComponent } from './shop/shop.component';
|
||||||
|
import { FrontcraftRulesComponent } from './rules/rules.component';
|
||||||
|
import { FrontcraftItemSelectComponent } from './shop/itemselector.component';
|
||||||
|
import { NgxEchartsModule } from 'ngx-echarts';
|
||||||
|
import { FrontcraftCharactersComponent } from './characters/characters.component';
|
||||||
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
@@ -35,21 +50,43 @@ import { FrontcraftPeopleComponent } from './people/people.component';
|
|||||||
NbInputModule,
|
NbInputModule,
|
||||||
NbButtonModule,
|
NbButtonModule,
|
||||||
NbCheckboxModule,
|
NbCheckboxModule,
|
||||||
|
NbTabsetModule,
|
||||||
ThemeModule,
|
ThemeModule,
|
||||||
NbMenuModule,
|
NbMenuModule,
|
||||||
DashboardModule,
|
DashboardModule,
|
||||||
ECommerceModule,
|
ECommerceModule,
|
||||||
MiscellaneousModule,
|
MiscellaneousModule,
|
||||||
NbCardModule,
|
NbCardModule,
|
||||||
|
NbListModule,
|
||||||
|
NbIconModule,
|
||||||
|
NbEvaIconsModule,
|
||||||
|
NbPopoverModule,
|
||||||
|
NbDatepickerModule,
|
||||||
|
NbSelectModule,
|
||||||
|
NgxEchartsModule,
|
||||||
|
NbWindowModule.forChild(),
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
FrontcraftPeopleComponent,
|
FrontcraftItemSelectComponent,
|
||||||
|
FrontcraftRaidComponent,
|
||||||
|
FrontcraftRaidsComponent,
|
||||||
FrontcraftUserComponent,
|
FrontcraftUserComponent,
|
||||||
FrontcraftCharacterComponent,
|
FrontcraftCharacterComponent,
|
||||||
PagesLayoutComponent,
|
PagesLayoutComponent,
|
||||||
FrontcraftDashboardComponent
|
FrontcraftCharactersComponent,
|
||||||
|
FrontcraftCharacerpickerComponent,
|
||||||
|
FrontcraftArchiveComponent,
|
||||||
|
FrontcraftShopComponent,
|
||||||
|
FrontcraftRulesComponent,
|
||||||
|
FrontcraftCreateRaidsComponent,
|
||||||
|
FrontcraftBuyTokenComponent,
|
||||||
],
|
],
|
||||||
|
entryComponents: [
|
||||||
|
FrontcraftItemSelectComponent,
|
||||||
|
FrontcraftCharacerpickerComponent,
|
||||||
|
FrontcraftCreateRaidsComponent,
|
||||||
|
FrontcraftBuyTokenComponent,
|
||||||
|
]
|
||||||
})
|
})
|
||||||
export class FrontcraftPagesModule {
|
export class FrontcraftPagesModule {
|
||||||
}
|
}
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
<nb-card>
|
|
||||||
<nb-card-body>
|
|
||||||
|
|
||||||
<label class="search-label" for="search">Search:</label>
|
|
||||||
<input nbInput [nbFilterInput]="dataSource" id="search" class="search-input">
|
|
||||||
|
|
||||||
<table [nbTreeGrid]="dataSource" [nbSort]="dataSource" (sort)="updateSort($event)">
|
|
||||||
|
|
||||||
<tr nbTreeGridHeaderRow *nbTreeGridHeaderRowDef="allColumns"></tr>
|
|
||||||
<tr nbTreeGridRow *nbTreeGridRowDef="let row; columns: allColumns"></tr>
|
|
||||||
|
|
||||||
<ng-container [nbTreeGridColumnDef]="customColumn">
|
|
||||||
<th nbTreeGridHeaderCell [nbSortHeader]="getSortDirection(customColumn)" *nbTreeGridHeaderCellDef>
|
|
||||||
{{customColumn}}
|
|
||||||
</th>
|
|
||||||
<td nbTreeGridCell *nbTreeGridCellDef="let row">
|
|
||||||
<nb-tree-grid-row-toggle
|
|
||||||
*ngIf="row.children && row.children.length">
|
|
||||||
</nb-tree-grid-row-toggle>
|
|
||||||
<span style="text-transform: capitalize;">
|
|
||||||
{{row.data[customColumn]}}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<ng-container *ngFor="let column of defaultColumns; let index = index"
|
|
||||||
[nbTreeGridColumnDef]="column"
|
|
||||||
[showOn]="getShowOn(index)">
|
|
||||||
<th nbTreeGridHeaderCell [nbSortHeader]="getSortDirection(column)" *nbTreeGridHeaderCellDef>
|
|
||||||
{{column}}
|
|
||||||
</th>
|
|
||||||
<td nbTreeGridCell *nbTreeGridCellDef="let row">{{row.data[column] || '-'}}</td>
|
|
||||||
</ng-container>
|
|
||||||
</table>
|
|
||||||
</nb-card-body>
|
|
||||||
</nb-card>
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
button[nbTreeGridRowToggle] {
|
|
||||||
background: transparent;
|
|
||||||
border: none;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-label {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
.search-input {
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nb-column-name {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (min-width: 400px) {
|
|
||||||
.nb-column-name,
|
|
||||||
.nb-column-size {
|
|
||||||
width: 50%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (min-width: 500px) {
|
|
||||||
.nb-column-name,
|
|
||||||
.nb-column-size,
|
|
||||||
.nb-column-kind {
|
|
||||||
width: 33.333%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (min-width: 600px) {
|
|
||||||
.nb-column-name {
|
|
||||||
width: 31%;
|
|
||||||
}
|
|
||||||
.nb-column-size,
|
|
||||||
.nb-column-kind,
|
|
||||||
.nb-column-items {
|
|
||||||
width: 23%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
import { Component } from '@angular/core';
|
|
||||||
import { NbSortDirection, NbSortRequest, NbTreeGridDataSourceBuilder, NbTreeGridDataSource } from '@nebular/theme';
|
|
||||||
|
|
||||||
interface TreeNode<T> {
|
|
||||||
data: T;
|
|
||||||
children?: TreeNode<T>[];
|
|
||||||
expanded?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Row {
|
|
||||||
name: string,
|
|
||||||
character: any,
|
|
||||||
SRC: any,
|
|
||||||
kind: 'Character' | 'Account'
|
|
||||||
}
|
|
||||||
|
|
||||||
type TreeType = TreeNode<Row>
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'people-component',
|
|
||||||
templateUrl: './people.component.html',
|
|
||||||
styleUrls: ['./tree-grid-shared.scss', './people.component.scss'],
|
|
||||||
})
|
|
||||||
export class FrontcraftPeopleComponent{
|
|
||||||
customColumn = 'name';
|
|
||||||
defaultColumns = [ 'character', 'SRC'/*, 'Profile'*/ ];
|
|
||||||
allColumns = [ this.customColumn, ...this.defaultColumns ];
|
|
||||||
|
|
||||||
dataSource: NbTreeGridDataSource<TreeType>;
|
|
||||||
|
|
||||||
sortColumn: string;
|
|
||||||
sortDirection: NbSortDirection = NbSortDirection.NONE;
|
|
||||||
|
|
||||||
constructor(private dataSourceBuilder: NbTreeGridDataSourceBuilder<TreeType>) {
|
|
||||||
this.dataSource = this.dataSourceBuilder.create(this.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateSort(sortRequest: NbSortRequest): void {
|
|
||||||
this.sortColumn = sortRequest.column;
|
|
||||||
this.sortDirection = sortRequest.direction;
|
|
||||||
}
|
|
||||||
|
|
||||||
getSortDirection(column: string): NbSortDirection {
|
|
||||||
if (this.sortColumn === column) {
|
|
||||||
return this.sortDirection;
|
|
||||||
}
|
|
||||||
return NbSortDirection.NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
private data: TreeType[] = [
|
|
||||||
{
|
|
||||||
data: {name: 'a', character: 2, SRC: 0, kind: 'Account'},
|
|
||||||
children: [
|
|
||||||
{data: {name: 'a', character: 'Warrior', SRC: 'Arms', kind: 'Character'}}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
getShowOn(index: number) {
|
|
||||||
const minWithForMultipleColumns = 400;
|
|
||||||
const nextColumnStep = 100;
|
|
||||||
return minWithForMultipleColumns + (nextColumnStep * index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
::ng-deep {
|
|
||||||
body {
|
|
||||||
min-height: 20rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nb-tree-grid-header-cell,
|
|
||||||
.nb-tree-grid-header-cell button {
|
|
||||||
text-transform: capitalize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
import { ApiService as ApiService } from '../../services/login-api';
|
||||||
|
import { RaidData } from '../../../../../../backend/Types/Types';
|
||||||
|
import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'archive',
|
||||||
|
templateUrl: './raid.component.html',
|
||||||
|
})
|
||||||
|
export class FrontcraftArchiveComponent implements OnInit{
|
||||||
|
|
||||||
|
canSignup = false
|
||||||
|
isSignedup = false
|
||||||
|
canManage = false
|
||||||
|
mySignup
|
||||||
|
|
||||||
|
raid: RaidData = <any>{
|
||||||
|
participants:{
|
||||||
|
Druid: [],
|
||||||
|
Hunter: [],
|
||||||
|
Mage: [],
|
||||||
|
Paladin: [],
|
||||||
|
Priest: [],
|
||||||
|
Rogue: [],
|
||||||
|
Shaman: [],
|
||||||
|
Warlock: [],
|
||||||
|
Warrior: [],
|
||||||
|
},
|
||||||
|
tokens:{}
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private api: ApiService,
|
||||||
|
private route: ActivatedRoute,
|
||||||
|
){
|
||||||
|
}
|
||||||
|
|
||||||
|
async ngOnInit(){
|
||||||
|
this.refresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
refresh = async () => {
|
||||||
|
const param = this.route.snapshot.paramMap.get('id');
|
||||||
|
|
||||||
|
const raidManager = this.api.get('RaidManager')
|
||||||
|
const raiddata = await raidManager.getArchiveRaid(parseInt(param))
|
||||||
|
this.raid = raiddata
|
||||||
|
|
||||||
|
Object.values(raiddata.participants).flat().forEach(p => {
|
||||||
|
p['color'] = getClassColor(p.class)
|
||||||
|
})
|
||||||
|
|
||||||
|
const matchingSignup = Object.values(raiddata.participants).flat().find(char => char.userid === this.api.getCurrentUser()!.id!)
|
||||||
|
if(matchingSignup){
|
||||||
|
this.isSignedup = true
|
||||||
|
this.mySignup = matchingSignup
|
||||||
|
this.mySignup.status = matchingSignup['benched']?'Bench':matchingSignup['late']?'Late':'Attending'
|
||||||
|
}else{
|
||||||
|
this.isSignedup = false
|
||||||
|
this.mySignup = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
<nb-card class="col-12 col-xl-9">
|
||||||
|
<nb-card-header>
|
||||||
|
Pick Character
|
||||||
|
</nb-card-header>
|
||||||
|
<nb-card-body>
|
||||||
|
<div *ngFor="let character of characters">
|
||||||
|
<button
|
||||||
|
(click)="signup(character, false)"
|
||||||
|
nbButton
|
||||||
|
outline
|
||||||
|
status="success"
|
||||||
|
size="tiny">
|
||||||
|
<nb-icon icon="checkmark-outline"></nb-icon>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
(click)="signup(character, true)"
|
||||||
|
nbButton
|
||||||
|
outline
|
||||||
|
status="warning"
|
||||||
|
size="tiny">
|
||||||
|
<nb-icon icon="clock-outline"></nb-icon>
|
||||||
|
</button>
|
||||||
|
<span [ngStyle]="{'color': character.color}">
|
||||||
|
{{character.charactername}}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</nb-card-body>
|
||||||
|
</nb-card>
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import { OnInit, Component } from '@angular/core';
|
||||||
|
import { NbWindowRef, NbToastrService, NbDialogRef } from '@nebular/theme';
|
||||||
|
import { RaidData, Character } from '../../../../../../backend/Types/Types';
|
||||||
|
import { ApiService } from '../../services/login-api';
|
||||||
|
import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'characterpicker',
|
||||||
|
templateUrl: './characterpicker.component.html',
|
||||||
|
})
|
||||||
|
export class FrontcraftCharacerpickerComponent implements OnInit{
|
||||||
|
|
||||||
|
raid : RaidData
|
||||||
|
characters: Character[]
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
protected dialogRef: NbDialogRef<FrontcraftCharacerpickerComponent>,
|
||||||
|
private api : ApiService,
|
||||||
|
private toast : NbToastrService
|
||||||
|
){}
|
||||||
|
|
||||||
|
signup = async (character: Character, late: boolean) => {
|
||||||
|
const auth = this.api.getAuth()
|
||||||
|
const signup = this.api.get('signup')
|
||||||
|
if(!signup) return
|
||||||
|
|
||||||
|
await signup.sign(auth.token.value, character, this.raid, late)
|
||||||
|
this.toast.show('Signup', 'Success', { status: 'success' })
|
||||||
|
this.dialogRef.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
const usr = this.api.getCurrentUser()
|
||||||
|
this.api.get('CharacterManager')
|
||||||
|
.getCharactersOfUser(usr.username)
|
||||||
|
.then(chars => {
|
||||||
|
chars.forEach(char => {
|
||||||
|
char['color'] = getClassColor(char.class)
|
||||||
|
})
|
||||||
|
this.characters = chars
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
<nb-card class="col-12 col-xl-9">
|
||||||
|
<nb-card-body>
|
||||||
|
<nb-tabset>
|
||||||
|
<nb-tab tabTitle="Info">
|
||||||
|
<h1>{{raid.title}}</h1>
|
||||||
|
<p>
|
||||||
|
{{raid.signupcount}} / {{raid.size}} signups
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
{{raid.description}}
|
||||||
|
</p>
|
||||||
|
<div *ngIf="canSignup">
|
||||||
|
<div *ngIf="isSignedup">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
You are signed as: {{mySignup.charactername}} ({{mySignup.race}} {{mySignup.specname}} {{mySignup.class}})<br />
|
||||||
|
Status: {{mySignup.status}}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<button
|
||||||
|
(click)="unsign()"
|
||||||
|
nbButton
|
||||||
|
outline
|
||||||
|
status="danger"
|
||||||
|
size="medium">
|
||||||
|
unsign
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="!isSignedup">
|
||||||
|
<button
|
||||||
|
(click)="signup()"
|
||||||
|
nbButton
|
||||||
|
outline
|
||||||
|
status="success"
|
||||||
|
size="medium">
|
||||||
|
signup
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nb-tab>
|
||||||
|
|
||||||
|
<nb-tab tabTitle="Signups"
|
||||||
|
[badgeText]="raid.signupcount"
|
||||||
|
badgePosition="top right"
|
||||||
|
[badgeStatus]="raid.signupcount<40?'warning':'success'">
|
||||||
|
<div class="row">
|
||||||
|
<ng-container *ngFor="let group of raid.participants | keyvalue">
|
||||||
|
<nb-card
|
||||||
|
class="col-12 col-md-6 col-xl-4"
|
||||||
|
*ngIf="group.value.length > 0">
|
||||||
|
<nb-card-header>{{group.key}} ({{group.value.length}})</nb-card-header>
|
||||||
|
<nb-card-body>
|
||||||
|
<div *ngFor="let participant of group.value">
|
||||||
|
<button
|
||||||
|
(click)="setBench(participant)"
|
||||||
|
*ngIf="manageRaid"
|
||||||
|
nbButton
|
||||||
|
outline
|
||||||
|
status="warning"
|
||||||
|
size="tiny">
|
||||||
|
B
|
||||||
|
</button>
|
||||||
|
<a [ngStyle]="{'color': participant.color}" style="text-transform: capitalize;"
|
||||||
|
[routerLink]="'/frontcraft/character/'+participant.charactername">
|
||||||
|
{{ participant.charactername }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</nb-card-body>
|
||||||
|
</nb-card>
|
||||||
|
|
||||||
|
</ng-container>
|
||||||
|
</div>
|
||||||
|
</nb-tab>
|
||||||
|
<nb-tab tabTitle="Reserves">
|
||||||
|
<nb-list>
|
||||||
|
<nb-list-item *ngFor="let item of raid.tokens | keyvalue">
|
||||||
|
|
||||||
|
<a [ngStyle]="{'color':item.value[0].quality=='Epic'?'#a335ee':'#ff8000'}"
|
||||||
|
target="_blank"
|
||||||
|
[href]="item.value[0].url">
|
||||||
|
<img style="min-width: 25px; width: 2.25vw; max-width: 50px"
|
||||||
|
[src]="'https://wow.zamimg.com/images/wow/icons/large/'+item.value[0].iconname+'.jpg'" />
|
||||||
|
|
||||||
|
{{item.key}}
|
||||||
|
</a><br />
|
||||||
|
<div class="row">
|
||||||
|
<div *ngFor="let token of item.value" class="col-12 col-md-6 col-xl-4">
|
||||||
|
[ {{token.level}} ]
|
||||||
|
<span style="text-transform: capitalize;" [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}}
|
||||||
|
</span><br />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nb-list-item>
|
||||||
|
</nb-list>
|
||||||
|
</nb-tab>
|
||||||
|
<nb-tab tabTitle="Admin" *ngIf="manageRaid">
|
||||||
|
<button
|
||||||
|
(click)="startRaid(raid)"
|
||||||
|
nbButton
|
||||||
|
outline
|
||||||
|
status="success"
|
||||||
|
size="medium">
|
||||||
|
start
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
(click)="archiveRaid(raid)"
|
||||||
|
nbButton
|
||||||
|
outline
|
||||||
|
status="danger"
|
||||||
|
size="medium">
|
||||||
|
archive
|
||||||
|
</button>
|
||||||
|
</nb-tab>
|
||||||
|
</nb-tabset>
|
||||||
|
</nb-card-body>
|
||||||
|
</nb-card>
|
||||||
|
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
|
import { ApiService as ApiService } from '../../services/login-api';
|
||||||
|
import { RaidData, Raid, Signup } from '../../../../../../backend/Types/Types';
|
||||||
|
import { NbWindowService, NbToastrService, NbDialogService } from '@nebular/theme';
|
||||||
|
import { FrontcraftCharacerpickerComponent } from './characterpicker.component';
|
||||||
|
import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'raid',
|
||||||
|
templateUrl: './raid.component.html',
|
||||||
|
})
|
||||||
|
export class FrontcraftRaidComponent implements OnInit{
|
||||||
|
|
||||||
|
canSignup = false
|
||||||
|
isSignedup = false
|
||||||
|
manageRaid
|
||||||
|
mySignup
|
||||||
|
|
||||||
|
raid: RaidData = <any>{
|
||||||
|
participants:{
|
||||||
|
Druid: [],
|
||||||
|
Hunter: [],
|
||||||
|
Mage: [],
|
||||||
|
Paladin: [],
|
||||||
|
Priest: [],
|
||||||
|
Rogue: [],
|
||||||
|
Shaman: [],
|
||||||
|
Warlock: [],
|
||||||
|
Warrior: [],
|
||||||
|
},
|
||||||
|
tokens:{}
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private api: ApiService,
|
||||||
|
private route: ActivatedRoute,
|
||||||
|
private router: Router,
|
||||||
|
private dialogService : NbDialogService,
|
||||||
|
private toast: NbToastrService
|
||||||
|
){
|
||||||
|
window['r'] = this
|
||||||
|
}
|
||||||
|
|
||||||
|
async ngOnInit(){
|
||||||
|
this.manageRaid = this.api.get('manageRaid')
|
||||||
|
|
||||||
|
const signupFeature = this.api.get('signup')
|
||||||
|
if(signupFeature){
|
||||||
|
this.canSignup = true
|
||||||
|
}
|
||||||
|
this.refresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
signup = async () => {
|
||||||
|
const signupFeature = this.api.get('signup')
|
||||||
|
if(!signupFeature) return
|
||||||
|
|
||||||
|
this.dialogService.open(FrontcraftCharacerpickerComponent, {
|
||||||
|
closeOnBackdropClick: true,
|
||||||
|
closeOnEsc: true,
|
||||||
|
context: {
|
||||||
|
'raid': this.raid,
|
||||||
|
}
|
||||||
|
}).onClose.subscribe(()=>{
|
||||||
|
this.refresh()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async archiveRaid(raid:Raid){
|
||||||
|
await this.manageRaid!.archiveRaid(raid)
|
||||||
|
this.toast.show('Raid archived', 'Success', { status: 'success' })
|
||||||
|
this.router.navigateByUrl('/frontcraft/archive/'+raid.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
async startRaid(raid:Raid){
|
||||||
|
await this.manageRaid!.startRaid(raid)
|
||||||
|
this.toast.show('Raid started', 'Success', { status: 'success' })
|
||||||
|
this.router.navigateByUrl('/frontcraft/archive/'+raid.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
unsign = async () => {
|
||||||
|
const signupFeature = this.api.get('signup')
|
||||||
|
if(!signupFeature) return
|
||||||
|
|
||||||
|
await signupFeature.unsign(this.api.getAuth().token.value, this.mySignup, this.raid)
|
||||||
|
this.toast.show('Success', 'Unsigned', { status: 'success' })
|
||||||
|
this.refresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
refresh = async () => {
|
||||||
|
const param = this.route.snapshot.paramMap.get('id');
|
||||||
|
|
||||||
|
const raidManager = this.api.get('RaidManager')
|
||||||
|
const raiddata = await raidManager.getRaidData(<any>{
|
||||||
|
id: param
|
||||||
|
})
|
||||||
|
this.raid = raiddata
|
||||||
|
|
||||||
|
Object.values(raiddata.participants).flat().forEach(p => {
|
||||||
|
p['color'] = getClassColor(p.class)
|
||||||
|
})
|
||||||
|
const user = this.api.getCurrentUser()
|
||||||
|
const matchingSignup = Object.values(raiddata.participants).flat().find(char => user && char.userid === user.id!)
|
||||||
|
if(matchingSignup){
|
||||||
|
this.isSignedup = true
|
||||||
|
this.mySignup = matchingSignup
|
||||||
|
this.mySignup.status = matchingSignup['benched']?'Bench':matchingSignup['late']?'Late':'Attending'
|
||||||
|
}else{
|
||||||
|
this.isSignedup = false
|
||||||
|
this.mySignup = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setBench(signup:Signup){
|
||||||
|
this.manageRaid.setBenched({
|
||||||
|
characterid: signup.characterid,
|
||||||
|
raidid: signup.raidid,
|
||||||
|
late: false,
|
||||||
|
benched: !signup.benched
|
||||||
|
}).then(_ => this.refresh())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
|
||||||
|
|
||||||
|
<nb-card class="col-12 col-xl-9">
|
||||||
|
<nb-card-header>
|
||||||
|
Create Raid
|
||||||
|
</nb-card-header>
|
||||||
|
<nb-select [(selected)]="template" placeholder="copy from" (selectedChange)="onTemplateSelect()">
|
||||||
|
<nb-option *ngFor="let template of templates" [value]="template">{{template.title}} {{template.start| date : 'd MMMM'}}</nb-option>
|
||||||
|
</nb-select>
|
||||||
|
|
||||||
|
<input type="text" nbInput [(ngModel)]="title" placeholder="Title" fullWidth="true">
|
||||||
|
<input type="number" nbInput [(ngModel)]="size" placeholder="size" fullWidth="true">
|
||||||
|
<textarea nbInput fullWidth [(ngModel)]="description" placeholder="description" fullWidth="true"></textarea>
|
||||||
|
<input [nbDatepicker]="datepicker" [(ngModel)]="startdate">
|
||||||
|
<nb-datepicker #datepicker></nb-datepicker>
|
||||||
|
|
||||||
|
<input type="number" nbInput [(ngModel)]="hour" placeholder="hour" fullWidth="true">
|
||||||
|
<input type="number" nbInput [(ngModel)]="minute" placeholder="minute" fullWidth="true">
|
||||||
|
|
||||||
|
<button
|
||||||
|
(click)="submit()"
|
||||||
|
nbButton
|
||||||
|
outline
|
||||||
|
status="success"
|
||||||
|
size="medium">
|
||||||
|
submit
|
||||||
|
</button>
|
||||||
|
</nb-card>
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { ApiService } from '../../services/login-api';
|
||||||
|
import { Raid, RaidData } from '../../../../../../backend/Types/Types';
|
||||||
|
import { NbWindowRef, NbDialogRef } from '@nebular/theme';
|
||||||
|
|
||||||
|
const ONE_MINUTE = 60000
|
||||||
|
const ONE_HOUR = 60 * ONE_MINUTE
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'createraid',
|
||||||
|
templateUrl: 'createraid.component.html',
|
||||||
|
})
|
||||||
|
export class FrontcraftCreateRaidsComponent implements OnInit {
|
||||||
|
|
||||||
|
templates :RaidData[]
|
||||||
|
template :RaidData
|
||||||
|
|
||||||
|
title = ""
|
||||||
|
startdate = new Date()
|
||||||
|
hour = 20
|
||||||
|
minute = 0
|
||||||
|
size = 40
|
||||||
|
description = ""
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
protected dialogRef: NbDialogRef<FrontcraftCreateRaidsComponent>,
|
||||||
|
private api: ApiService
|
||||||
|
) {}
|
||||||
|
|
||||||
|
loadNext(cardData) {
|
||||||
|
}
|
||||||
|
|
||||||
|
onTemplateSelect(){
|
||||||
|
const templateDate = new Date(this.template.start)
|
||||||
|
this.title = this.template.title
|
||||||
|
this.hour = templateDate.getHours()
|
||||||
|
this.minute = templateDate.getMinutes()
|
||||||
|
this.description = this.template.description
|
||||||
|
this.startdate = new Date(parseInt(this.template.start) - templateDate.getHours()*ONE_HOUR - templateDate.getMinutes()*ONE_MINUTE)
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async submit(){
|
||||||
|
const raid = <Raid>{
|
||||||
|
description: this.description,
|
||||||
|
size: this.size,
|
||||||
|
start: ""+new Date(this.startdate.getTime() + this.hour*ONE_HOUR + this.minute*ONE_MINUTE).getTime(),
|
||||||
|
title: this.title,
|
||||||
|
}
|
||||||
|
const manage = this.api.get('manageRaid')
|
||||||
|
if(!manage) return
|
||||||
|
|
||||||
|
await manage.createRaid(raid)
|
||||||
|
this.dialogRef.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
<nb-card class="col-12 col-xl-9">
|
||||||
|
<nb-card-header>
|
||||||
|
Upcoming raids
|
||||||
|
<nb-icon
|
||||||
|
style="color:orange"
|
||||||
|
*ngIf="manageRaid"
|
||||||
|
(click)="create()"
|
||||||
|
icon="plus-square-outline"></nb-icon>
|
||||||
|
</nb-card-header>
|
||||||
|
<nb-list
|
||||||
|
nbInfiniteList
|
||||||
|
listenWindowScroll
|
||||||
|
[threshold]="500">
|
||||||
|
<nb-list-item *ngFor="let raid of raids" [routerLink]="'/frontcraft/raid/'+raid.id">
|
||||||
|
<b>{{raid.title}}</b><br>
|
||||||
|
{{raid.signupcount}} / {{raid.size}}<br>
|
||||||
|
{{raid.start | date : 'EEEE d MMMM @ HH:mm'}}<br>
|
||||||
|
{{raid.description}}<br>
|
||||||
|
</nb-list-item>
|
||||||
|
</nb-list>
|
||||||
|
</nb-card>
|
||||||
|
|
||||||
|
<nb-card class="col-12 col-xl-9">
|
||||||
|
<nb-card-header>Previous raids</nb-card-header>
|
||||||
|
<nb-list
|
||||||
|
nbInfiniteList
|
||||||
|
listenWindowScroll
|
||||||
|
[threshold]="500">
|
||||||
|
<nb-list-item *ngFor="let raid of oldraids" [routerLink]="'/frontcraft/archive/'+raid.id">
|
||||||
|
<b>{{raid.title}}</b><br>
|
||||||
|
{{raid.signupcount}} / {{raid.size}}<br>
|
||||||
|
{{raid.start | date : 'EEEE d MMMM @ HH:mm'}}<br>
|
||||||
|
{{raid.description}}<br>
|
||||||
|
</nb-list-item>
|
||||||
|
</nb-list>
|
||||||
|
</nb-card>
|
||||||
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
.infinite-cards {
|
||||||
|
nb-card {
|
||||||
|
&.own-scroll {
|
||||||
|
height: 50vh;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { ApiService } from '../../services/login-api';
|
||||||
|
import { NbWindowService, NbDialogService } from '@nebular/theme';
|
||||||
|
import { FrontcraftCreateRaidsComponent } from './createraid.compontent';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'raids',
|
||||||
|
templateUrl: 'raids.component.html',
|
||||||
|
styleUrls: ['raids.component.scss'],
|
||||||
|
})
|
||||||
|
export class FrontcraftRaidsComponent implements OnInit{
|
||||||
|
|
||||||
|
|
||||||
|
manageRaid
|
||||||
|
raids = []
|
||||||
|
oldraids = []
|
||||||
|
pageSize = 10;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private api: ApiService,
|
||||||
|
private dialogService: NbDialogService
|
||||||
|
) {
|
||||||
|
this.manageRaid = this.api.get('manageRaid')
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.refresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
refresh() {
|
||||||
|
this.api.get('RaidManager').getRaids().then(raids => {
|
||||||
|
this.raids = raids
|
||||||
|
})
|
||||||
|
|
||||||
|
const raidManager = this.api.get('RaidManager')
|
||||||
|
raidManager.getPastRaids(10).then(raiddata => {
|
||||||
|
this.oldraids = raiddata
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
create(){
|
||||||
|
this.dialogService.open(FrontcraftCreateRaidsComponent, {
|
||||||
|
closeOnBackdropClick: true,
|
||||||
|
closeOnEsc: true,
|
||||||
|
context: {
|
||||||
|
templates: this.oldraids
|
||||||
|
}
|
||||||
|
}).onClose.subscribe(()=>{
|
||||||
|
this.refresh()
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<nb-card class="col-12 col-xl-9">
|
||||||
|
<nb-card-body>
|
||||||
|
<nb-tabset>
|
||||||
|
<nb-tab tabTitle="Info">
|
||||||
|
Smart text here
|
||||||
|
</nb-tab>
|
||||||
|
<nb-tab *ngIf="managePriorities" tabTitle="priorities">
|
||||||
|
<nb-list>
|
||||||
|
<nb-list-item *ngFor="let item of rules | keyvalue">
|
||||||
|
<a [ngStyle]="{'color':item.value[0].quality=='Epic'?'#a335ee':'#ff8000'}"
|
||||||
|
target="_blank"
|
||||||
|
[href]="item.value[0].url">
|
||||||
|
<img style="min-width: 25px; width: 2.25vw; max-width: 50px"
|
||||||
|
[src]="'https://wow.zamimg.com/images/wow/icons/large/'+item.value[0].iconname+'.jpg'" />
|
||||||
|
|
||||||
|
{{item.key}}
|
||||||
|
</a><br />
|
||||||
|
|
||||||
|
<span *ngFor="let rule of item.value" [nbPopover]="templateRef" nbPopoverTrigger="hover">
|
||||||
|
<ng-template #templateRef>
|
||||||
|
<span style="color:white">{{rule.description}}</span>
|
||||||
|
</ng-template>
|
||||||
|
+{{rule.modifier}} {{rule.race}} <span [ngStyle]="{'color':rule.color}">{{rule.specname}} {{rule.class}}</span> <br />
|
||||||
|
</span>
|
||||||
|
</nb-list-item>
|
||||||
|
</nb-list>
|
||||||
|
</nb-tab>
|
||||||
|
</nb-tabset>
|
||||||
|
</nb-card-body>
|
||||||
|
</nb-card>
|
||||||
|
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { ApiService as ApiService } from '../../services/login-api';
|
||||||
|
import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'rules',
|
||||||
|
templateUrl: './rules.component.html',
|
||||||
|
})
|
||||||
|
export class FrontcraftRulesComponent implements OnInit{
|
||||||
|
|
||||||
|
managePriorities
|
||||||
|
rules = {}
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private api: ApiService,
|
||||||
|
){
|
||||||
|
}
|
||||||
|
|
||||||
|
async ngOnInit(){
|
||||||
|
this.api.get('ItemManager').getAllPriorities().then(prios => prios.forEach(prio => {
|
||||||
|
if(!this.rules[prio.itemname]){
|
||||||
|
this.rules[prio.itemname] = []
|
||||||
|
}
|
||||||
|
prio['color'] = getClassColor(prio.class) || '#FFFFFF'
|
||||||
|
this.rules[prio.itemname].push(prio)
|
||||||
|
}))
|
||||||
|
|
||||||
|
const managePriorities = this.api.get('managePriorities')
|
||||||
|
this.managePriorities = managePriorities
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
|
||||||
|
<input type="text" nbInput [(ngModel)]="search" (change)="changeSearch()" placeholder="Search" fullWidth="true">
|
||||||
|
<nb-list
|
||||||
|
nbInfiniteList
|
||||||
|
listenWindowScroll>
|
||||||
|
<nb-list-item *ngFor="let item of displayedItems">
|
||||||
|
<button
|
||||||
|
(click)="select(item)"
|
||||||
|
nbButton
|
||||||
|
outline
|
||||||
|
status="info"
|
||||||
|
size="tiny">
|
||||||
|
select
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<a target="_blank" [href]="item.url">
|
||||||
|
<span [ngStyle]="{'color':item.quality=='Epic'?'#a335ee':'#ff8000'}">
|
||||||
|
<img style="min-width: 20px; width: 2.25vw; max-width: 35px"
|
||||||
|
[src]="'https://wow.zamimg.com/images/wow/icons/large/'+item.iconname+'.jpg'" />
|
||||||
|
|
||||||
|
{{item.itemname}}
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</nb-list-item>
|
||||||
|
</nb-list>
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { ApiService } from '../../services/login-api';
|
||||||
|
import { Item } from '../../../../../../backend/Types/Types';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'itemselect',
|
||||||
|
templateUrl: './itemselect.component.html',
|
||||||
|
})
|
||||||
|
export class FrontcraftItemSelectComponent implements OnInit{
|
||||||
|
|
||||||
|
selected: Item
|
||||||
|
search: string
|
||||||
|
items: any[]
|
||||||
|
displayedItems: any[]
|
||||||
|
|
||||||
|
callbacks = []
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private api: ApiService,
|
||||||
|
){
|
||||||
|
}
|
||||||
|
|
||||||
|
async ngOnInit(){
|
||||||
|
this.api.get('ItemManager').getItems().then(items => {
|
||||||
|
this.items = items
|
||||||
|
this.displayedItems = items
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
changeSearch(){
|
||||||
|
if(!this.search || this.search == "")
|
||||||
|
this.displayedItems = this.items
|
||||||
|
else
|
||||||
|
this.displayedItems = this.items.filter(it => it.itemname.toLowerCase().includes(this.search.toLowerCase()))
|
||||||
|
}
|
||||||
|
|
||||||
|
select(item: Item){
|
||||||
|
this.selected = item
|
||||||
|
this.callbacks.forEach(cb => cb(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
onselect(callback:Function){
|
||||||
|
this.callbacks.push(callback)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
|
||||||
|
<nb-card class="col-12 col-xl-9">
|
||||||
|
<nb-card-body>
|
||||||
|
<nb-tabset>
|
||||||
|
<nb-tab tabTitle="Items">
|
||||||
|
<itemselect></itemselect>
|
||||||
|
</nb-tab>
|
||||||
|
<nb-tab tabTitle="About">
|
||||||
|
</nb-tab>
|
||||||
|
</nb-tabset>
|
||||||
|
</nb-card-body>
|
||||||
|
</nb-card>
|
||||||
|
|
||||||
@@ -0,0 +1,135 @@
|
|||||||
|
import { Component, OnInit, ContentChild, AfterContentInit, ViewChild, AfterViewInit } from '@angular/core';
|
||||||
|
import { ApiService as ApiService } from '../../services/login-api';
|
||||||
|
import { FrontcraftItemSelectComponent } from './itemselector.component';
|
||||||
|
import { NbWindowService, NbWindowRef, NbToastrService, NbDialogService, NbDialogRef } from '@nebular/theme';
|
||||||
|
import { Item, Character, SRToken } from '../../../../../../backend/Types/Types';
|
||||||
|
import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'shop',
|
||||||
|
templateUrl: './shop.component.html',
|
||||||
|
})
|
||||||
|
export class FrontcraftShopComponent implements AfterViewInit{
|
||||||
|
|
||||||
|
@ViewChild(FrontcraftItemSelectComponent, {static: false})
|
||||||
|
itemselect !: FrontcraftItemSelectComponent
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private api: ApiService,
|
||||||
|
private dialogService : NbDialogService
|
||||||
|
|
||||||
|
){
|
||||||
|
window['shop'] = this
|
||||||
|
}
|
||||||
|
|
||||||
|
buy = (item) => {
|
||||||
|
|
||||||
|
this.dialogService.open(FrontcraftBuyTokenComponent, {
|
||||||
|
closeOnBackdropClick: true,
|
||||||
|
closeOnEsc: true,
|
||||||
|
context: {
|
||||||
|
item: item
|
||||||
|
}
|
||||||
|
}).onClose.subscribe(()=>{
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ngAfterViewInit(){
|
||||||
|
this.itemselect.onselect(this.buy)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'buyToken',
|
||||||
|
template: `
|
||||||
|
<nb-card class="col-12 col-xl-9">
|
||||||
|
<nb-card-header>
|
||||||
|
Buy {{item.itemname}}
|
||||||
|
</nb-card-header>
|
||||||
|
<nb-card-body>
|
||||||
|
<p>
|
||||||
|
You currently have {{currency}} softreserve currency
|
||||||
|
</p>
|
||||||
|
<div *ngIf="currency>0">
|
||||||
|
<div *ngFor="let kv of modifier | keyvalue">
|
||||||
|
<button
|
||||||
|
(click)="buyToken(kv.key)"
|
||||||
|
[disabled]="currency<=0"
|
||||||
|
nbButton
|
||||||
|
outline
|
||||||
|
status="success"
|
||||||
|
size="tiny">
|
||||||
|
buy
|
||||||
|
</button>
|
||||||
|
{{kv.key}} <span *ngIf="kv.value>0">(<b>+{{kv.value}}</b> from priorities)</span>
|
||||||
|
</div>
|
||||||
|
<div *ngFor="let token of ownedtokens">
|
||||||
|
<button
|
||||||
|
(click)="buyToken(token.charactername)"
|
||||||
|
nbButton
|
||||||
|
outline
|
||||||
|
status="success"
|
||||||
|
size="tiny">
|
||||||
|
buy
|
||||||
|
</button>
|
||||||
|
{{token.charactername}} [ {{token.level}} ] => [ {{token.level+1}} ]
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nb-card-body>
|
||||||
|
</nb-card>
|
||||||
|
|
||||||
|
`,
|
||||||
|
})
|
||||||
|
export class FrontcraftBuyTokenComponent implements OnInit{
|
||||||
|
|
||||||
|
item : Item
|
||||||
|
characters: Character[]
|
||||||
|
modifier = {}
|
||||||
|
currency: number = 0
|
||||||
|
ownedtokens: SRToken[] = []
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private toastr: NbToastrService,
|
||||||
|
protected dialogRef: NbDialogRef<FrontcraftBuyTokenComponent>,
|
||||||
|
private api : ApiService
|
||||||
|
){}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
const usr = this.api.getCurrentUser()
|
||||||
|
this.api.get('CharacterManager')
|
||||||
|
.getCharactersOfUser(usr.username)
|
||||||
|
.then(chars => {
|
||||||
|
chars.forEach(char => {
|
||||||
|
char['color'] = getClassColor(char.class)
|
||||||
|
this.api.get('ItemManager').getToken(char, this.item).then(token => {
|
||||||
|
if(token) this.ownedtokens.push(token)
|
||||||
|
else{
|
||||||
|
this.api.get('ItemManager').calculatePriorities(this.item.itemname, char).then(modifier => {
|
||||||
|
this.modifier[char.charactername] = modifier
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
this.characters = chars
|
||||||
|
})
|
||||||
|
this.api.get('UserManager').getUser(usr.username).then(u => {
|
||||||
|
if(!u) return
|
||||||
|
this.currency = u.currency
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
buyToken = async (charactername:string) => {
|
||||||
|
|
||||||
|
const src = this.api.get('ItemManager')
|
||||||
|
const token = await src.buyToken(this.api.getAuth().token.value, charactername, this.item.itemname)
|
||||||
|
|
||||||
|
|
||||||
|
if(token){
|
||||||
|
this.toastr.show(token.characterid+' now has a token for '+token.itemname+' of level '+token.level, 'Yay', {status: 'success'})
|
||||||
|
}else{
|
||||||
|
this.toastr.show('Error (something went wrong)', 'Oh no', {status: 'danger'})
|
||||||
|
}
|
||||||
|
this.dialogRef.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,11 +1,12 @@
|
|||||||
|
|
||||||
|
|
||||||
<nb-card
|
<nb-card class="col-xl-9"
|
||||||
accent="info">
|
accent="info">
|
||||||
<nb-card-header>
|
<nb-card-header>
|
||||||
<h2 style="text-transform: capitalize;">{{user.username}}</h2>
|
<h2 style="text-transform: capitalize;">{{user.username}}</h2>
|
||||||
</nb-card-header>
|
</nb-card-header>
|
||||||
<nb-card-body>
|
<nb-card-body>
|
||||||
|
{{user.currency}}
|
||||||
<nb-card
|
<nb-card
|
||||||
accent="control"
|
accent="control"
|
||||||
*ngFor="let char of characters">
|
*ngFor="let char of characters">
|
||||||
@@ -17,7 +18,20 @@ accent="info">
|
|||||||
</h4>
|
</h4>
|
||||||
</nb-card-header>
|
</nb-card-header>
|
||||||
<nb-card-body>
|
<nb-card-body>
|
||||||
{{char.specname}} {{char.class}}
|
{{char.race}}<br />
|
||||||
|
{{char.specname}} {{char.class}}
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<span *ngFor="let token of char.tokens">
|
||||||
|
[ {{token.level}} ]
|
||||||
|
<a [ngStyle]="{'color':token.quality=='Epic'?'#a335ee':'#ff8000'}"
|
||||||
|
target="_blank"
|
||||||
|
[href]="token.url">
|
||||||
|
<img style="min-width: 25px; width: 2.25vw; max-width: 50px"
|
||||||
|
[src]="'https://wow.zamimg.com/images/wow/icons/large/'+token.iconname+'.jpg'" />
|
||||||
|
{{token.itemname}}
|
||||||
|
</a><br />
|
||||||
|
</span>
|
||||||
</nb-card-body>
|
</nb-card-body>
|
||||||
</nb-card>
|
</nb-card>
|
||||||
</nb-card-body>
|
</nb-card-body>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { LoginApiService } from '../../services/login-api';
|
import { ApiService } from '../../services/login-api';
|
||||||
import { Router } from '@angular/router';
|
import { Router, ActivatedRoute } from '@angular/router';
|
||||||
import { User, Spec, Character } from '../../../../../../backend/Types/Types';
|
import { User, Spec, Character } from '../../../../../../backend/Types/Types';
|
||||||
import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
|
import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
|
||||||
|
|
||||||
@@ -14,25 +14,24 @@ export class FrontcraftUserComponent implements OnInit{
|
|||||||
characters : (Character & Spec)[] = []
|
characters : (Character & Spec)[] = []
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private router : Router,
|
private route: ActivatedRoute,
|
||||||
private loginApi : LoginApiService
|
private api : ApiService
|
||||||
){}
|
){}
|
||||||
|
|
||||||
ngOnInit(){
|
async ngOnInit(){
|
||||||
const auth = this.loginApi.getAuth()
|
const param = this.route.snapshot.paramMap.get('name');
|
||||||
if(!auth){
|
const usr = await this.api.get('UserManager').getUser(param)
|
||||||
this.router.navigateByUrl('/auth/login')
|
|
||||||
return
|
|
||||||
}
|
if(!usr) return
|
||||||
this.user = auth.user
|
this.user = usr
|
||||||
this.loginApi.getUnprivilegedSocket()
|
|
||||||
.CharacterManager
|
const characters = await this.api.get('CharacterManager').getCharactersOfUser(this.user.username)
|
||||||
.getCharactersOfUser(this.user.username)
|
characters.forEach(async c => {
|
||||||
.then((characters) => {
|
const tokens = await this.api.get('ItemManager').getTokens(c)
|
||||||
characters.forEach(c => {
|
c['tokens'] = tokens
|
||||||
c['color'] = getClassColor(c.class)
|
c['color'] = getClassColor(c.class)
|
||||||
})
|
})
|
||||||
this.characters = characters
|
this.characters = characters
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,13 @@
|
|||||||
import { Injectable, Injector, NgZone } from "@angular/core";
|
import { Injectable, Injector, NgZone } from "@angular/core";
|
||||||
import {RPCSocket} from 'rpclibrary/js/src/Frontend'
|
import {RPCSocket} from 'rpclibrary/js/src/Frontend'
|
||||||
|
|
||||||
import { Token, Auth, User, _Class, FrontcraftFeatureIfc, SomeOf, FrontcraftIfc, } from '../../../../../backend/Types/Types'
|
import { Auth, User, _Class, FrontcraftFeatureIfc, SomeOf, FrontcraftIfc, } from '../../../../../backend/Types/Types'
|
||||||
import { CookieService } from 'ngx-cookie-service';
|
import { CookieService } from 'ngx-cookie-service';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
|
import { ShoutMessage } from '../../../../../backend/Components/Shoutbox/Interface';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class LoginApiService{
|
export class ApiService{
|
||||||
private socket:RPCSocket & FrontcraftIfc;
|
private socket:RPCSocket & FrontcraftIfc;
|
||||||
private auth:Auth
|
private auth:Auth
|
||||||
private privSocket: RPCSocket & SomeOf<FrontcraftFeatureIfc>
|
private privSocket: RPCSocket & SomeOf<FrontcraftFeatureIfc>
|
||||||
@@ -37,7 +38,7 @@ export class LoginApiService{
|
|||||||
sock.hook('getUserData', () => auth)
|
sock.hook('getUserData', () => auth)
|
||||||
sock.hook('navigate', (where:string) => {
|
sock.hook('navigate', (where:string) => {
|
||||||
this.ngZone.run( () => {
|
this.ngZone.run( () => {
|
||||||
this.injector.get(Router).navigateByUrl('/')
|
this.injector.get(Router).navigateByUrl(where)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
sock.on('error', (e) => {
|
sock.on('error', (e) => {
|
||||||
@@ -55,13 +56,17 @@ export class LoginApiService{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getFeature = async <K extends keyof FrontcraftFeatureIfc>(feature : K) : Promise<void | FrontcraftFeatureIfc[K]> => {
|
get = <K extends (keyof FrontcraftIfc | keyof FrontcraftFeatureIfc)>(feature : K) : K extends keyof FrontcraftIfc?FrontcraftIfc[K]:
|
||||||
|
K extends keyof FrontcraftFeatureIfc?(FrontcraftFeatureIfc[K] | void):
|
||||||
|
never => {
|
||||||
try{
|
try{
|
||||||
const sock = await this.getPrivilegedSocket(this.auth)
|
//@ts-ignore
|
||||||
if(sock[feature]) return <FrontcraftFeatureIfc[K]> sock[feature]
|
if(this.socket && this.socket[feature]) return this.socket[feature]
|
||||||
|
//@ts-ignore
|
||||||
|
if(this.privSocket && this.privSocket[feature]) return this.privSocket[feature]
|
||||||
}catch(e){
|
}catch(e){
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getCurrentUser = () : User | undefined => {
|
getCurrentUser = () : User | undefined => {
|
||||||
@@ -70,7 +75,7 @@ export class LoginApiService{
|
|||||||
|
|
||||||
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)
|
||||||
const auth = await this.socket.Authenticator.login(username, pwHash)
|
const auth = await this.socket.UserManager.login(username, pwHash)
|
||||||
|
|
||||||
if(!auth){
|
if(!auth){
|
||||||
await this.logout()
|
await this.logout()
|
||||||
@@ -80,9 +85,14 @@ export class LoginApiService{
|
|||||||
return sock
|
return sock
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async connectShoutbox(handler) : Promise<Function>{
|
||||||
|
const res = await this.get('Shoutbox').subscribe(handler)
|
||||||
|
return async (msg: ShoutMessage) => await this.get('Shoutbox').shout(res.uuid, msg)
|
||||||
|
}
|
||||||
|
|
||||||
logout = async () => {
|
logout = async () => {
|
||||||
this.cookieSvc.set('token', undefined)
|
this.cookieSvc.set('token', undefined)
|
||||||
if(this.auth) await this.socket.Authenticator.logout(this.auth.user.username, this.auth.token.value)
|
if(this.auth) await this.socket.UserManager.logout(this.auth.user.username, this.auth.token.value)
|
||||||
if(this.privSocket) this.privSocket.destroy()
|
if(this.privSocket) this.privSocket.destroy()
|
||||||
this.privSocket = null
|
this.privSocket = null
|
||||||
this.auth = null
|
this.auth = null
|
||||||
@@ -91,15 +101,16 @@ export class LoginApiService{
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
initialize = async () : Promise<any> => {
|
initialize = async () : Promise<any> => {
|
||||||
const sock = await RPCSocket.makeSocket<FrontcraftIfc>(20000, window.location.hostname)
|
const sock = await RPCSocket.makeSocket<FrontcraftIfc>(20000, window.location.hostname)
|
||||||
|
|
||||||
this.socket = sock
|
this.socket = sock
|
||||||
try{
|
try{
|
||||||
const cookie = JSON.parse(this.cookieSvc.get('token'))
|
const cookie = JSON.parse(this.cookieSvc.get('token'))
|
||||||
|
|
||||||
if(cookie != null) {
|
if(cookie != null) {
|
||||||
try{
|
try{
|
||||||
const auth = await sock.Authenticator.getAuth(cookie.token.value)
|
const auth = await sock.UserManager.getAuth(cookie.token.value)
|
||||||
if(!auth) return sock
|
if(!auth) return sock
|
||||||
return await this.getPrivilegedSocket(auth)
|
return await this.getPrivilegedSocket(auth)
|
||||||
}catch(e){
|
}catch(e){
|
||||||
@@ -115,7 +126,7 @@ export class LoginApiService{
|
|||||||
|
|
||||||
async checkLogin() : Promise<boolean>{
|
async checkLogin() : Promise<boolean>{
|
||||||
if(!this.auth) return false
|
if(!this.auth) return false
|
||||||
const valid = await this.socket.Authenticator.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
|
||||||
@@ -126,7 +137,7 @@ function str2arraybuf(str:string): ArrayBuffer {
|
|||||||
return new Buffer(str)
|
return new Buffer(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
function buf2hex(buffer) { // buffer is an ArrayBuffer
|
function buf2hex(buffer: ArrayBuffer) {
|
||||||
return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join('');
|
return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join('');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,6 +148,6 @@ export async function hash(value:string) : Promise<string>{
|
|||||||
}
|
}
|
||||||
|
|
||||||
//angular depenency manager requires this
|
//angular depenency manager requires this
|
||||||
export function initializeLoginSvc(svc: LoginApiService): () => Promise<any> {
|
export function initializeLoginSvc(svc: ApiService): () => Promise<any> {
|
||||||
return svc.initialize
|
return ()=>svc.initialize?svc.initialize():undefined
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
"compileOnSave": false,
|
"compileOnSave": false,
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"importHelpers": true,
|
"importHelpers": true,
|
||||||
"module": "esnext",
|
"module": "commonjs",
|
||||||
"outDir": "./dist/out-tsc",
|
"outDir": "./dist/out-tsc",
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"declaration": false,
|
"declaration": false,
|
||||||
|
|||||||
Reference in New Issue
Block a user