Explorar el Código

migrations

master
peter hace 5 años
padre
commit
9ff98d92ae
Se han modificado 62 ficheros con 711 adiciones y 483 borrados
  1. BIN
      frontworkAdmin.sqlite
  2. BIN
      live_db/frontworkAdmin.sqlite
  3. 53
    35
      package-lock.json
  4. 3
    2
      package.json
  5. 71
    62
      src/backend/Admin/Admin.ts
  6. 2
    2
      src/backend/Components/Item/ItemManager.ts
  7. 2
    3
      src/backend/Components/PubSub/Interface.ts
  8. 6
    7
      src/backend/Components/PubSub/PubSub.ts
  9. 1
    1
      src/backend/Components/Raid/Interface.ts
  10. 26
    29
      src/backend/Components/Raid/RaidManager.ts
  11. 1
    2
      src/backend/Components/Shoutbox/Interface.ts
  12. 5
    5
      src/backend/Components/Shoutbox/Shoutbox.ts
  13. 7
    7
      src/backend/Components/User/UserManager.ts
  14. 0
    1
      src/backend/Injector/ServiceDecorator.ts
  15. 1
    0
      src/backend/Types/Constants.ts
  16. 4
    5
      src/backend/Types/FrontworkComponent.ts
  17. 1
    1
      src/backend/Types/Plugin.ts
  18. 2
    3
      src/backend/Types/PrivilegedRPCExporter.ts
  19. 2
    0
      src/backend/Types/Types.ts
  20. 3
    0
      src/frontend/angular.json
  21. 11
    3
      src/frontend/package-lock.json
  22. 3
    2
      src/frontend/package.json
  23. 8
    3
      src/frontend/server.ts
  24. 2
    1
      src/frontend/src/app/@theme/components/header/header.component.html
  25. 43
    20
      src/frontend/src/app/@theme/components/header/header.component.ts
  26. 1
    6
      src/frontend/src/app/app.component.ts
  27. 5
    5
      src/frontend/src/app/app.module.ts
  28. 1
    1
      src/frontend/src/app/app.server.module.ts
  29. 57
    0
      src/frontend/src/app/frontcraft/UpdatingComponent.ts
  30. 0
    2
      src/frontend/src/app/frontcraft/auth/auth-layout.component.ts
  31. 1
    1
      src/frontend/src/app/frontcraft/auth/login/login.component.html
  32. 6
    5
      src/frontend/src/app/frontcraft/auth/login/login.component.ts
  33. 1
    1
      src/frontend/src/app/frontcraft/auth/logout/logout.component.html
  34. 6
    3
      src/frontend/src/app/frontcraft/auth/logout/logout.component.ts
  35. 1
    1
      src/frontend/src/app/frontcraft/auth/register/register.component.html
  36. 8
    4
      src/frontend/src/app/frontcraft/auth/register/register.component.ts
  37. 0
    1
      src/frontend/src/app/frontcraft/pages/armory/armory.component.ts
  38. 1
    2
      src/frontend/src/app/frontcraft/pages/character/character.component.ts
  39. 3
    17
      src/frontend/src/app/frontcraft/pages/pages-layout.component.ts
  40. 0
    1
      src/frontend/src/app/frontcraft/pages/pages.module.ts
  41. 18
    5
      src/frontend/src/app/frontcraft/pages/raid/archive.component.ts
  42. 35
    28
      src/frontend/src/app/frontcraft/pages/raid/characterpicker.component.html
  43. 3
    3
      src/frontend/src/app/frontcraft/pages/raid/characterpicker.component.ts
  44. 92
    31
      src/frontend/src/app/frontcraft/pages/raid/raid.component.html
  45. 22
    34
      src/frontend/src/app/frontcraft/pages/raid/raid.component.ts
  46. 2
    3
      src/frontend/src/app/frontcraft/pages/raids/createraid.compontent.ts
  47. 53
    47
      src/frontend/src/app/frontcraft/pages/raids/raids.component.html
  48. 21
    31
      src/frontend/src/app/frontcraft/pages/raids/raids.component.ts
  49. 3
    5
      src/frontend/src/app/frontcraft/pages/shop/buytoken.component.ts
  50. 10
    2
      src/frontend/src/app/frontcraft/pages/shop/itemselector.component.ts
  51. 0
    2
      src/frontend/src/app/frontcraft/pages/shop/shop.component.ts
  52. 1
    1
      src/frontend/src/app/frontcraft/pages/user/user.component.html
  53. 0
    2
      src/frontend/src/app/frontcraft/permissions/changePermissions/changePermissions.component.ts
  54. 0
    1
      src/frontend/src/app/frontcraft/permissions/permissions-layout.component.ts
  55. 13
    6
      src/frontend/src/app/frontcraft/services/ApiService.ts
  56. 21
    16
      src/frontend/src/app/frontcraft/services/client-login-api.ts
  57. 37
    0
      src/frontend/src/app/frontcraft/services/logger.service.ts
  58. 16
    12
      src/frontend/src/app/frontcraft/services/server-login-api.ts
  59. 1
    1
      src/frontend/src/main.server.ts
  60. 7
    2
      src/frontend/src/main.ts
  61. 1
    0
      src/frontend/tsconfig.app.json
  62. 7
    7
      test/backendTest.ts

BIN
frontworkAdmin.sqlite Ver fichero


BIN
live_db/frontworkAdmin.sqlite Ver fichero


+ 53
- 35
package-lock.json Ver fichero

@@ -479,7 +479,8 @@
479 479
     "bluebird": {
480 480
       "version": "3.5.5",
481 481
       "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.5.tgz",
482
-      "integrity": "sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w=="
482
+      "integrity": "sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==",
483
+      "dev": true
483 484
     },
484 485
     "body-parser": {
485 486
       "version": "1.19.0",
@@ -835,9 +836,9 @@
835 836
       "dev": true
836 837
     },
837 838
     "colorette": {
838
-      "version": "1.0.8",
839
-      "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.0.8.tgz",
840
-      "integrity": "sha512-X6Ck90ReaF+EfKdVGB7vdIQ3dr651BbIrBwY5YBKg13fjH+940sTtp7/Pkx33C6ntYfQcRumOs/aUQhaRPpbTQ=="
839
+      "version": "1.1.0",
840
+      "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.1.0.tgz",
841
+      "integrity": "sha512-6S062WDQUXi6hOfkO/sBPVwE5ASXY4G2+b4atvhJfSsuUUhIaUKlkjLe9692Ipyt5/a+IPF5aVTu3V5gvXq5cg=="
841 842
     },
842 843
     "combined-stream": {
843 844
       "version": "1.0.8",
@@ -850,7 +851,8 @@
850 851
     "commander": {
851 852
       "version": "2.20.0",
852 853
       "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz",
853
-      "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ=="
854
+      "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==",
855
+      "dev": true
854 856
     },
855 857
     "commondir": {
856 858
       "version": "1.0.1",
@@ -2057,9 +2059,9 @@
2057 2059
       "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg="
2058 2060
     },
2059 2061
     "getopts": {
2060
-      "version": "2.2.4",
2061
-      "resolved": "https://registry.npmjs.org/getopts/-/getopts-2.2.4.tgz",
2062
-      "integrity": "sha512-Rz7DGyomZjrenu9Jx4qmzdlvJgvrEFHXHvjK0FcZtcTC1U5FmES7OdZHUwMuSnEE6QvBvwse1JODKj7TgbSEjQ=="
2062
+      "version": "2.2.5",
2063
+      "resolved": "https://registry.npmjs.org/getopts/-/getopts-2.2.5.tgz",
2064
+      "integrity": "sha512-9jb7AW5p3in+IiJWhQiZmmwkpLaR/ccTWdWQCtZM66HJcHHLegowh4q4tSD7gouUyeNvFWRavfK9GXosQHDpFA=="
2063 2065
     },
2064 2066
     "getpass": {
2065 2067
       "version": "0.1.7",
@@ -2139,6 +2141,16 @@
2139 2141
         }
2140 2142
       }
2141 2143
     },
2144
+    "global-modules": {
2145
+      "version": "1.0.0",
2146
+      "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz",
2147
+      "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==",
2148
+      "requires": {
2149
+        "global-prefix": "^1.0.1",
2150
+        "is-windows": "^1.0.1",
2151
+        "resolve-dir": "^1.0.0"
2152
+      }
2153
+    },
2142 2154
     "global-prefix": {
2143 2155
       "version": "1.0.2",
2144 2156
       "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz",
@@ -2731,27 +2743,37 @@
2731 2743
       "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA=="
2732 2744
     },
2733 2745
     "knex": {
2734
-      "version": "0.19.2",
2735
-      "resolved": "https://registry.npmjs.org/knex/-/knex-0.19.2.tgz",
2736
-      "integrity": "sha512-TVYvlp2esS4LjjJSz8XuE48bPJq4N3lWnETQVgJ3hXPEqjiDjxcTa3bCn6F5ipQuBaMAAaFHNrqsZm7BttogdA==",
2746
+      "version": "0.19.5",
2747
+      "resolved": "https://registry.npmjs.org/knex/-/knex-0.19.5.tgz",
2748
+      "integrity": "sha512-Hy258avCVircQq+oj3WBqPzl8jDIte438Qlq+8pt1i/TyLYVA4zPh2uKc7Bx0t+qOpa6D42HJ2jjtl2vagzilw==",
2737 2749
       "requires": {
2738
-        "bluebird": "^3.5.5",
2739
-        "colorette": "1.0.8",
2740
-        "commander": "^2.20.0",
2750
+        "bluebird": "^3.7.0",
2751
+        "colorette": "1.1.0",
2752
+        "commander": "^3.0.2",
2741 2753
         "debug": "4.1.1",
2742
-        "getopts": "2.2.4",
2754
+        "getopts": "2.2.5",
2743 2755
         "inherits": "~2.0.4",
2744 2756
         "interpret": "^1.2.0",
2745 2757
         "liftoff": "3.1.0",
2746 2758
         "lodash": "^4.17.15",
2747 2759
         "mkdirp": "^0.5.1",
2748
-        "pg-connection-string": "2.0.0",
2760
+        "pg-connection-string": "2.1.0",
2749 2761
         "tarn": "^2.0.0",
2750 2762
         "tildify": "2.0.0",
2751
-        "uuid": "^3.3.2",
2763
+        "uuid": "^3.3.3",
2752 2764
         "v8flags": "^3.1.3"
2753 2765
       },
2754 2766
       "dependencies": {
2767
+        "bluebird": {
2768
+          "version": "3.7.2",
2769
+          "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
2770
+          "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
2771
+        },
2772
+        "commander": {
2773
+          "version": "3.0.2",
2774
+          "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz",
2775
+          "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow=="
2776
+        },
2755 2777
         "inherits": {
2756 2778
           "version": "2.0.4",
2757 2779
           "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
@@ -3948,9 +3970,9 @@
3948 3970
       "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
3949 3971
     },
3950 3972
     "pg-connection-string": {
3951
-      "version": "2.0.0",
3952
-      "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.0.0.tgz",
3953
-      "integrity": "sha1-Pu/lmX4G2Ugh5NUC5CtqHHP434I="
3973
+      "version": "2.1.0",
3974
+      "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.1.0.tgz",
3975
+      "integrity": "sha512-bhlV7Eq09JrRIvo1eKngpwuqKtJnNhZdpdOlvrPrA4dxqXPjxSrbNrfnIDmTpwMyRszrcV4kU5ZA4mMsQUrjdg=="
3954 3976
     },
3955 3977
     "picomatch": {
3956 3978
       "version": "2.2.1",
@@ -4340,18 +4362,6 @@
4340 4362
       "requires": {
4341 4363
         "expand-tilde": "^2.0.0",
4342 4364
         "global-modules": "^1.0.0"
4343
-      },
4344
-      "dependencies": {
4345
-        "global-modules": {
4346
-          "version": "1.0.0",
4347
-          "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz",
4348
-          "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==",
4349
-          "requires": {
4350
-            "global-prefix": "^1.0.1",
4351
-            "is-windows": "^1.0.1",
4352
-            "resolve-dir": "^1.0.0"
4353
-          }
4354
-        }
4355 4365
       }
4356 4366
     },
4357 4367
     "resolve-url": {
@@ -4388,13 +4398,21 @@
4388 4398
       }
4389 4399
     },
4390 4400
     "rpclibrary": {
4391
-      "version": "1.9.2",
4392
-      "resolved": "https://registry.npmjs.org/rpclibrary/-/rpclibrary-1.9.2.tgz",
4393
-      "integrity": "sha512-MOtVm0IBRLryXag1IwkYNPVFegbvW10+MbCjhr3GptO3MA7nHZ545ammgoCWnREtGOgFeN4Jib/EBDOJ9Ep41Q==",
4401
+      "version": "1.10.2",
4402
+      "resolved": "https://registry.npmjs.org/rpclibrary/-/rpclibrary-1.10.2.tgz",
4403
+      "integrity": "sha512-uf4FtylK+tyVo1O8YVihxYxaI4KHnKBzq05SsLYe8ZPXdO8Hqrv7Je5cwv3bfx0FBCO1vVrSc8DT1P6ypGY6uQ==",
4394 4404
       "requires": {
4395 4405
         "bsock": "^0.1.9",
4406
+        "crypto-js": "^4.0.0",
4396 4407
         "http": "0.0.0",
4397 4408
         "uuid": "^3.3.3"
4409
+      },
4410
+      "dependencies": {
4411
+        "crypto-js": {
4412
+          "version": "4.0.0",
4413
+          "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.0.0.tgz",
4414
+          "integrity": "sha512-bzHZN8Pn+gS7DQA6n+iUmBfl0hO5DJq++QP3U6uTucDtk/0iGpXd/Gg7CGR0p8tJhofJyaKoWBuJI4eAO00BBg=="
4415
+        }
4398 4416
       }
4399 4417
     },
4400 4418
     "run-queue": {

+ 3
- 2
package.json Ver fichero

@@ -4,6 +4,7 @@
4 4
   "version": "1.0.0",
5 5
   "scripts": {
6 6
     "tsc": "tsc",
7
+    "knex": "knex",
7 8
     "launch": "node lib/src/backend/Launcher.js",
8 9
     "start": "npm run build && npm run launch",
9 10
     "start-backend": "npm run build-backend && npm run launch",
@@ -37,7 +38,6 @@
37 38
     "git-cherrypicker": "0.0.3",
38 39
     "git-describe": "^4.0.4",
39 40
     "http": "0.0.0",
40
-    "knex": "^0.19.2",
41 41
     "loadson": "^1.0.0",
42 42
     "log4js": "^4.5.1",
43 43
     "lowdb": "^1.0.0",
@@ -46,7 +46,7 @@
46 46
     "path": "^0.12.7",
47 47
     "reflect-metadata": "^0.1.13",
48 48
     "rimraf": "^3.0.0",
49
-    "rpclibrary": "^1.9.2",
49
+    "rpclibrary": "^1.10.2",
50 50
     "simple-git": "^1.124.0",
51 51
     "spawn-sync": "^2.0.0",
52 52
     "sqlite3": "^4.1.1",
@@ -58,6 +58,7 @@
58 58
     "xmlhttprequest": "^1.8.0"
59 59
   },
60 60
   "devDependencies": {
61
+    "knex": "^0.19.5",
61 62
     "madge": "^3.6.0",
62 63
     "mocha": "^7.1.0",
63 64
     "terser-webpack-plugin": "^1.4.1",

+ 71
- 62
src/backend/Admin/Admin.ts Ver fichero

@@ -4,7 +4,7 @@ import { getLogger, Logger, } from "log4js";
4 4
 import { promises as fs, mkdirSync } from "fs"
5 5
 import { RPCServer } from 'rpclibrary'
6 6
 import * as Path from 'path'
7
-import * as Knex from  'knex';
7
+import * as Knex from 'knex';
8 8
 import * as http from 'http';
9 9
 import * as express from 'express';
10 10
 import { GuildManager } from '../Components/Guild/GuildManager';
@@ -36,18 +36,18 @@ getLogger().level = 'debug'
36 36
         PubSub
37 37
     ]
38 38
 })
39
-export class FrontworkAdmin 
40
-implements TableDefinitionExporter, IAdmin {
41
-    knex:Knex
39
+export class FrontworkAdmin
40
+    implements TableDefinitionExporter, IAdmin {
41
+    knex: Knex
42 42
     config: RPCConfigLoader<AdminConf>
43 43
     rpcServer: RPCServer
44 44
 
45 45
     private express
46 46
     private httpServer
47 47
 
48
-    constructor(private frontworkComponents: FrontworkComponent[] = []){
48
+    constructor(private frontworkComponents: FrontworkComponent[] = []) {
49 49
         this.config = new RPCConfigLoader<AdminConf>({
50
-            name: "FrontworkAdminConf", 
50
+            name: "FrontworkAdminConf",
51 51
             getDefaultConfig: () => {
52 52
                 return {
53 53
                     httpPort: 8080,
@@ -55,57 +55,61 @@ implements TableDefinitionExporter, IAdmin {
55 55
                     dbConf: {
56 56
                         client: 'sqlite3',
57 57
                         connection: {
58
-                            filename: Path.resolve(__dirname, '../../../..', "data/frontworkAdmin.sqlite")
58
+                            filename: Path.resolve(__dirname, '../../../..', "data/frontworkAdmin.sqlite"),
59
+                        },
60
+                        migrations: {
61
+                            directory: Path.resolve(__dirname, '../../../..', "migrations"),
62
+                            extension: 'ts'
59 63
                         },
60 64
                         useNullAsDefault: true,
61 65
                     }
62
-                }   
66
+                }
63 67
             }
64
-        }, './config', this.configChangeHandler) 
68
+        }, './config', this.configChangeHandler)
65 69
     }
66 70
 
67
-    async start(){
71
+    async start() {
68 72
         await this.makeKnex()
69 73
         this.startWebsocket()
70
-        await Promise.all( this.frontworkComponents.map(c => c.initialize?c.initialize():undefined ))
71
-        getLogger('Admin#start').debug(this.frontworkComponents.length+" components initialized")
74
+        await Promise.all(this.frontworkComponents.map(c => c.initialize ? c.initialize() : undefined))
75
+        getLogger('Admin#start').debug(this.frontworkComponents.length + " components initialized")
72 76
         await this.startWebserver()
73 77
     }
74 78
 
75
-    stop(){
76
-        Promise.all([ 
77
-            ...this.frontworkComponents.map(c => c.stop?c.stop():undefined ),
79
+    stop() {
80
+        Promise.all([
81
+            ...this.frontworkComponents.map(c => c.stop ? c.stop() : undefined),
78 82
         ])
79
-        .catch(e => getLogger('Admin#stop').warn(e))
80
-        .finally(() => { 
81
-            this.rpcServer.destroy()
82
-            process.exit(0)
83
-         })
83
+            .catch(e => getLogger('Admin#stop').warn(e))
84
+            .finally(() => {
85
+                this.rpcServer.destroy()
86
+                process.exit(0)
87
+            })
84 88
     }
85 89
 
86
-    protected configChangeHandler = (conf:AdminConf, key?:string) => {
87
-        if(key === 'dbConf'){
90
+    protected configChangeHandler = (conf: AdminConf, key?: string) => {
91
+        if (key === 'dbConf') {
88 92
             this.makeKnex()
89 93
         }
90 94
     }
91 95
 
92
-    getConfigKey(key:string){
96
+    getConfigKey(key: string) {
93 97
         return this.config.getConfigKey(key)
94 98
     }
95 99
 
96
-    setConfigKey(key:string, value:any){
100
+    setConfigKey(key: string, value: any) {
97 101
         return this.config.setConfigKey(key, value)
98 102
     }
99 103
 
100
-    getTableDefinitions(): TableDefiniton[]{
104
+    getTableDefinitions(): TableDefiniton[] {
101 105
         return [
102 106
             ...this.frontworkComponents
103 107
         ]
104
-        .filter(exp => exp.getTableDefinitions != null)
105
-        .flatMap(exp => exp.getTableDefinitions())
108
+            .filter(exp => exp.getTableDefinitions != null)
109
+            .flatMap(exp => exp.getTableDefinitions())
106 110
     }
107 111
 
108
-    private startWebsocket(){
112
+    private startWebsocket() {
109 113
         this.rpcServer = new RPCServer(20000, [
110 114
             ...this.frontworkComponents,
111 115
             {
@@ -121,40 +125,41 @@ implements TableDefinitionExporter, IAdmin {
121 125
         getLogger('Admin#startWebsocket').debug("Websocket up on", 20000)
122 126
     }
123 127
 
124
-    private async startWebserver(){
125
-        if(this.httpServer != null || this.express != null){
128
+    private async startWebserver() {
129
+        if (this.httpServer != null || this.express != null) {
126 130
             getLogger('Admin#startWebserver').warn("Webserver is already running")
127 131
             return
128 132
         }
129
-        
130
-        let port:number = this.config.getConfig().httpPort
133
+
134
+        let port: number = this.config.getConfig().httpPort
131 135
         this.express = express()
132 136
 
133 137
         const distFolder = "../../../../dist"
134 138
         const ngExpressServer = Path.join(__dirname, distFolder, 'server.js')
135 139
 
136
-        this.express.get('*.*', (req, res)=>{
140
+        this.express.get('*.*', (req, res) => {
137 141
             //console.log('*.*', req.path);
138
-            res.sendFile(Path.join(__dirname, distFolder,'browser',decodeURIComponent(req.path)))
142
+            res.sendFile(Path.join(__dirname, distFolder, 'browser', decodeURIComponent(req.path)))
143
+            res.status(200)
139 144
         })
140 145
 
141
-        try{
142
-            const req = require(distFolder+"/server.js")
146
+        try {
147
+            const req = require(distFolder + "/server.js")
143 148
             await req.attachExpress(this.express)
144
-            getLogger('Admin#startWebserver').info('Frontend from '+ngExpressServer+" loaded")
145
-        }catch(e){
149
+            getLogger('Admin#startWebserver').info('Frontend from ' + ngExpressServer + " loaded")
150
+        } catch (e) {
146 151
             getLogger('Admin#startWebserver').error(e)
147
-            getLogger('Admin#startWebserver').warn("No angular SSR module was provided in "+ngExpressServer)
148
-            getLogger('Admin#startWebserver').warn("This is not fatal, but your page will not render on *"+port)
152
+            getLogger('Admin#startWebserver').warn("No angular SSR module was provided in " + ngExpressServer)
153
+            getLogger('Admin#startWebserver').warn("This is not fatal, but your page will not render on *" + port)
149 154
         }
150 155
 
151 156
         this.express.listen(port, () => {
152
-            getLogger('Admin#startWebserver').info('Admin panel listening for HTTP on *'+port)
157
+            getLogger('Admin#startWebserver').info('Admin panel listening for HTTP on *' + port)
153 158
         })
154 159
     }
155 160
 
156
-    private stopWebserver(){
157
-        if(this.httpServer == null || this.express == null){
161
+    private stopWebserver() {
162
+        if (this.httpServer == null || this.express == null) {
158 163
             getLogger('Admin#stopWebserver').warn("Webserver is not running")
159 164
             return
160 165
         }
@@ -164,38 +169,42 @@ implements TableDefinitionExporter, IAdmin {
164 169
         getLogger('Admin#stopWebserver').info("Webserver stopped")
165 170
     }
166 171
 
167
-    async makeKnex():Promise<Knex>{
168
-        const conf:Knex.Config = this.config.getConfigKey("dbConf")
172
+    async makeKnex(): Promise<Knex> {
173
+        const conf: Knex.Config = this.config.getConfigKey("dbConf")
169 174
 
170
-        getLogger('Admin#makeKnex').debug("Making new knex:", conf)        
171
-        if(conf.client === 'sqlite3'){
172
-            mkdirSync(Path.dirname((<any>conf.connection).filename), {recursive: true})
175
+        getLogger('Admin#makeKnex').debug("Making new knex:", conf)
176
+        if (conf.client === 'sqlite3') {
177
+            mkdirSync(Path.dirname((<any>conf.connection).filename), { recursive: true })
173 178
         }
174 179
 
175 180
         this.knex = Knex(conf)
176
-        if(conf.client === 'sqlite3'){
181
+        if (conf.client === 'sqlite3') {
177 182
             await this.knex.raw('PRAGMA foreign_keys = ON');
178
-        
183
+
179 184
         }
180 185
 
181 186
         await Promise.all(
182 187
             this.getTableDefinitions()
183
-            //make unique by name
184
-            .filter((other, index, self) => index === self.findIndex(
185
-                (self) => self.name === other.name)
186
-            )
187
-            //create table if not exists
188
-            .map(async (def)=> {
189
-                const hasTable = await this.knex.schema.hasTable(def.name)
190
-                if(!hasTable)
191
-                    return await this.knex.schema.createTable(def.name, def.tableBuilder)
192
-            })
188
+                //make unique by name
189
+                .filter((other, index, self) => index === self.findIndex(
190
+                    (self) => self.name === other.name)
191
+                )
192
+                //create table if not exists
193
+                .map(async (def) => {
194
+                    const hasTable = await this.knex.schema.hasTable(def.name)
195
+                    if (!hasTable)
196
+                        return await this.knex.schema.createTable(def.name, def.tableBuilder)
197
+                })
193 198
         )
199
+        await this.knex.migrate.latest().catch(e => {
200
+            getLogger('Admin#makeKnex').error(e)
201
+            process.exit(-1)
202
+        })
194 203
         return this.knex
195 204
     }
196 205
 }
197 206
 
198
-process.on( 'SIGINT', function() {
199
-    getLogger('process#SIGINT').info("Shutting down from SIGINT (Ctrl-C)" );
207
+process.on('SIGINT', function () {
208
+    getLogger('process#SIGINT').info("Shutting down from SIGINT (Ctrl-C)");
200 209
     Injector.resolve<FrontworkAdmin>(FrontworkAdmin).stop()
201 210
 })

+ 2
- 2
src/backend/Components/Item/ItemManager.ts Ver fichero

@@ -3,7 +3,7 @@ import { Inject, Injectable } from "../../Injector/ServiceDecorator";
3 3
 import { ItemManagerFeatureIfc, ItemManagerIfc } from "./RPCInterface";
4 4
 import { FrontworkComponent } from "../../Types/FrontworkComponent";
5 5
 import { TableDefinitionExporter } from "../../Types/Interfaces";
6
-import { TableDefiniton, Item, User, Character, SRToken, SRPriority, Spec, Signup, Raid, Stats } from "../../Types/Types";
6
+import { TableDefiniton, Item, Character, SRToken, SRPriority, Spec, Signup, Raid, Stats } from "../../Types/Types";
7 7
 import { IAdmin } from "../../Admin/Interface";
8 8
 import { IItemManager } from "./Interface";
9 9
 import { IUserManager } from "../User/Interface";
@@ -171,7 +171,7 @@ export class ItemManager
171 171
                     table.boolean('hidden').defaultTo(false).notNullable()
172 172
                     table.string('tooltip').notNullable()
173 173
                     table.enu('tier', _Tiers).notNullable()
174
-                    table.json('stats').notNullable()
174
+                    table.json('stats')
175 175
                 }
176 176
             }]
177 177
     }

+ 2
- 3
src/backend/Components/PubSub/Interface.ts Ver fichero

@@ -1,7 +1,6 @@
1
-import { SubscriptionResponse } from "rpclibrary"
2 1
 
3 2
 export class IPubSub<UpdateType>{
4 3
     publish: (topic: string, p: UpdateType) => Promise<void>
5
-    subscribe: (topic:string, callback: (p:UpdateType)=>any) => Promise<SubscriptionResponse&{data:any}>
4
+    subscribe: (topic:string, callback: (p:UpdateType)=>any) => Promise<string>
6 5
     unsubscribe: (uuid: string) => Promise<void>
7
-}
6
+}

+ 6
- 7
src/backend/Components/PubSub/PubSub.ts Ver fichero

@@ -1,6 +1,7 @@
1 1
 import { Injectable } from "../../Injector/ServiceDecorator";
2
-import { SubscriptionResponse, makeSubResponse, RPCExporter } from "rpclibrary";
2
+import { RPCExporter } from "rpclibrary";
3 3
 import { IPubSub } from "./Interface";
4
+const uuidv4 = require('uuid/v4')
4 5
 
5 6
 @Injectable(IPubSub)
6 7
 export class PubSub<UpdateType = any>
@@ -34,13 +35,11 @@ implements RPCExporter{
34 35
         }))
35 36
     }
36 37
 
37
-    subscribe = async (topic:string, callback:(p:UpdateType)=>any) : Promise<SubscriptionResponse<{topic: string}>> => {
38
-        const resp = makeSubResponse({
39
-            topic: topic
40
-        })
38
+    subscribe = async (topic:string, callback:(p:UpdateType)=>any) : Promise<string> => {
39
+        const uuid = uuidv4()
41 40
         if(!this.subs[topic]) this.subs[topic] = {}
42
-        this.subs[topic][resp.uuid] = callback
43
-        return resp
41
+        this.subs[topic][uuid] = callback
42
+        return uuid
44 43
     }
45 44
 
46 45
     private unsubscribe = async (uuid: string) => {

+ 1
- 1
src/backend/Components/Raid/Interface.ts Ver fichero

@@ -6,7 +6,7 @@ export class IRaidManager{
6 6
     addSignup: (signup: Signup) => Promise<Signup>
7 7
     removeSignup: (signup: Signup) => Promise<any>    
8 8
     getSignups: (raid:Raid) => Promise<(Signup & Character & Spec & User)[]>
9
-    sign: (userToken: string, character:Character, raid:Raid, late:boolean) => Promise<any>
9
+    sign: (userToken: string, character:Character, raid:Raid, late:boolean, memo?: string) => Promise<any>
10 10
     unsign: (userToken: string, character:Character, raid:Raid,) => Promise<any>
11 11
     archiveRaid: (raid:Raid) => Promise<RaidData>
12 12
     getRaidData: (raid:Raid) => Promise<RaidData>

+ 26
- 29
src/backend/Components/Raid/RaidManager.ts Ver fichero

@@ -7,9 +7,11 @@ import { IRaidManager } from "./Interface";
7 7
 import { IUserManager } from "../User/Interface";
8 8
 import { ICharacterManager } from "../Character/Interface";
9 9
 import { _Tiers } from "../../Types/Items";
10
+import { MAX_MEMO_LENGTH } from "../../Types/Constants";
10 11
 import { IItemManager } from "../Item/Interface";
11 12
 import { ItemManager } from "../Item/ItemManager";
12 13
 import { IPubSub } from "../PubSub/Interface";
14
+import { getLogger } from "log4js";
13 15
 
14 16
 @Injectable(IRaidManager)
15 17
 export class RaidManager
@@ -89,6 +91,8 @@ export class RaidManager
89 91
                     table.foreign('characterid').references('id').inTable('characters').onDelete('CASCADE')
90 92
                     table.boolean('benched').defaultTo('false')
91 93
                     table.boolean('late')
94
+                    table.timestamp('timestamp').defaultTo(this.admin.knex.fn.now())
95
+                    table.string('memo').nullable()
92 96
                 }
93 97
             }
94 98
         ]
@@ -96,12 +100,20 @@ export class RaidManager
96 100
 
97 101
     notifyRaid = async (raid:Raid | {id:number}) => {
98 102
         const data = await this.getRaidData(<Raid>raid)
99
-        this.pubsub.publish(""+raid.id, data)
100
-        await this.notifyRaids()
103
+        try{
104
+            await this.pubsub.publish(String(raid.id), data)
105
+            await this.notifyRaids()
106
+        }catch(e){
107
+            getLogger('RaidManager#notifyRaid').debug(e);
108
+        }
101 109
     }
102 110
 
103 111
     notifyRaids = async () => {
104
-        this.pubsub.publish('raids', undefined)
112
+        try{
113
+            await this.pubsub.publish('raids', undefined)
114
+        }catch(e){
115
+            getLogger('RaidManager#notifyRaids').debug(e);
116
+        }
105 117
     }
106 118
 
107 119
     createRaid = async (raid: Raid): Promise<Raid> => {
@@ -158,7 +170,7 @@ export class RaidManager
158 170
 
159 171
         await Promise.all([
160 172
             ...archived.participants.bench.map(giveCurrency),
161
-            ...Object.values(archived.participants).flat().flatMap((b:Signup & Character & Spec) => giveCurrency(b))
173
+            ...Object.values(archived.participants).flat().map((b:Signup & Character & Spec) => giveCurrency(b))
162 174
         ])
163 175
 
164 176
         await this.notifyRaids()
@@ -169,10 +181,10 @@ export class RaidManager
169 181
     archiveRaid = async (raid: Raid): Promise<RaidData> => {
170 182
         const raidData = await this.getRaidData(raid)
171 183
 
172
-        //const tx = await this.admin.knex.transaction()
184
+        const tx = await this.admin.knex.transaction()
173 185
 
174 186
         await this.admin.knex('archive')
175
-            //.transacting(tx)
187
+            .transacting(tx)
176 188
             .insert({
177 189
                 id: raidData.id,
178 190
                 raiddata: JSON.stringify(raidData)
@@ -182,7 +194,7 @@ export class RaidManager
182 194
             Object.values(raidData.participants).flat().flatMap((p: (Signup & Character & Spec)) => 
183 195
                 this.admin
184 196
                 .knex(raid.tier + 'tokens')
185
-                //.transacting(tx)
197
+                .transacting(tx)
186 198
                 .where({
187 199
                     characterid: p.characterid,
188 200
                     signupid: null
@@ -191,10 +203,10 @@ export class RaidManager
191 203
             ))
192 204
 
193 205
         await this.admin.knex('raids')
194
-            //.transacting(tx)
206
+            .transacting(tx)
195 207
             .where('id', '=', raid.id)
196 208
             .del()
197
-        //await tx.commit()
209
+        await tx.commit()
198 210
 
199 211
 
200 212
         const row = await this.admin.knex('archive')
@@ -242,7 +254,6 @@ export class RaidManager
242 254
             healers: <(Signup & Character & Spec)[]>[],
243 255
             tanks: <(Signup & Character & Spec)[]>[]
244 256
         }
245
-        //const tx = await this.admin.knex.transaction()
246 257
 
247 258
         const subQuery = this.admin
248 259
             .knex('signups')
@@ -257,14 +268,12 @@ export class RaidManager
257 268
 
258 269
         const raidInDb: Raid = await this.admin.knex('raids')
259 270
             .select('*', subQuery)
260
-            //.transacting(tx)
261 271
             .where('id', '=', raid.id)
262 272
             .first()
263 273
 
264 274
         const characterData: (Signup & Character & Spec)[] = await this.admin
265 275
             .knex('signups as s')
266
-            //.transacting(tx)
267
-            .select('s.id as id', 'charactername', 'rank', 'class', 'specid', 'specname', 'race', 'userid', 'benched', 'late', 'raidid', 'characterid', 'specid')
276
+            .select('s.id as id', 'charactername', 'rank', 'class', 'specid', 'specname', 'race', 'userid', 'benched', 'late', 'raidid', 'characterid', 'specid', 'memo', 'timestamp')
268 277
             .join('raids as r', 's.raidid', '=', 'r.id')
269 278
             .join('characters as c', 's.characterid', '=', 'c.id')
270 279
             .join('users as u', 'c.userid', '=', 'u.id')
@@ -285,7 +294,6 @@ export class RaidManager
285 294
 
286 295
         const tokenData: (Character & SRToken & Item)[] = await this.admin
287 296
             .knex('signups as s')
288
-            //.transacting(tx)
289 297
             .select('*', 's.id as id')
290 298
             .join('raids as r', 's.raidid', '=', 'r.id')
291 299
             .join('characters as c', 's.characterid', '=', 'c.id')
@@ -300,8 +308,6 @@ export class RaidManager
300 308
                 this.whereNotNull('t.signupid')
301 309
             })
302 310
 
303
-        //await tx.commit()
304
-
305 311
         tokenData.forEach(data => {
306 312
             if (!raiddata.tokens[data.itemname])
307 313
                 raiddata.tokens[data.itemname] = []
@@ -338,16 +344,15 @@ export class RaidManager
338 344
         .select('*', 'si.id as id')
339 345
         .where('raidid', '=', raid.id!)
340 346
 
341
-    sign = async (usertoken: string, character: Character, raid: Raid, late: boolean) => {
347
+    sign = async (usertoken: string, character: Character, raid: Raid, late: boolean, memo?: string) => {
342 348
         const maybeUserRecord = this.userManager.getUserRecordByToken(usertoken)
343 349
         if (!maybeUserRecord || maybeUserRecord.user.id != character.userid) {
344 350
             throw new Error("Bad Usertoken")
345 351
         }
346
-        //const tx = await this.admin.knex.transaction()
347 352
 
353
+        if(memo) memo = memo.substring(0, MAX_MEMO_LENGTH)
348 354
         const exists = await this.admin
349 355
             .knex('signups')
350
-            //.transacting(tx)
351 356
             .select('*')
352 357
             .where({
353 358
                 raidid: raid.id!,
@@ -358,17 +363,16 @@ export class RaidManager
358 363
         if (!exists) {
359 364
             await this.admin
360 365
                 .knex('signups')
361
-                //.transacting(tx)
362 366
                 .insert({
363 367
                     raidid: raid.id!,
364 368
                     characterid: character.id!,
365 369
                     late: late,
366 370
                     benched: false,
371
+                    memo: memo
367 372
                 })
368 373
         } else {
369 374
             await this.admin
370 375
                 .knex('signups')
371
-                //.transacting(tx)
372 376
                 .where({
373 377
                     id: exists.id
374 378
                 })
@@ -377,9 +381,9 @@ export class RaidManager
377 381
                     characterid: character.id!,
378 382
                     late: late,
379 383
                     benched: false,
384
+                    memo: memo
380 385
                 })
381 386
         }
382
-        //await tx.commit()
383 387
 
384 388
         await this.notifyRaid(raid)
385 389
         
@@ -405,13 +409,6 @@ export class RaidManager
405 409
     adminUnsign = async (character: Character, raid: Raid) => {
406 410
 
407 411
         const user = await this.characterManager.getUserOfCharacter(character)
408
-
409
-        const signup = await this.admin.knex('signups as si')
410
-            .where({
411
-                "si.raidid": raid.id!,
412
-                "si.characterid": character.id!,
413
-            }).first()
414
-
415 412
         const tokens = await this.itemManager.getTokens(character, [raid.tier], true)
416 413
 
417 414
         //check if token has to be deleted

+ 1
- 2
src/backend/Components/Shoutbox/Interface.ts Ver fichero

@@ -1,5 +1,4 @@
1 1
 import { Raid, Signup, Character, RaidData } from "../../Types/Types"
2
-import { SubscriptionResponse } from "rpclibrary"
3 2
 
4 3
 export type ShoutMessage = {
5 4
     message: string,
@@ -10,5 +9,5 @@ export type ShoutMessage = {
10 9
 export class IShoutbox{
11 10
     shout: (uuid:string, msg: ShoutMessage) => Promise<void>
12 11
     getFeed: () => Promise<ShoutMessage[]>
13
-    subscribe: (callback) => Promise<SubscriptionResponse>
12
+    subscribe: (callback) => Promise<string>
14 13
 }

+ 5
- 5
src/backend/Components/Shoutbox/Shoutbox.ts Ver fichero

@@ -3,8 +3,8 @@ import { ShoutboxFeatureIfc, ShoutboxIfc } from "./RPCInterface";
3 3
 import { FrontworkComponent } from "../../Types/FrontworkComponent";
4 4
 import { TableDefiniton } from "../../Types/Types";
5 5
 import { IShoutbox, ShoutMessage } from "./Interface";
6
-import { SubscriptionResponse, makeSubResponse } from "rpclibrary";
7 6
 import * as  CircularBuffer from "circular-buffer";
7
+const uuid = require('uuid/v4')
8 8
 
9 9
 @Injectable(IShoutbox)
10 10
 export class Shoutbox
@@ -52,10 +52,10 @@ implements FrontworkComponent<ShoutboxIfc, ShoutboxFeatureIfc>, IShoutbox{
52 52
         return this.log.toarray()
53 53
     }
54 54
 
55
-    subscribe = async (callback) : Promise<SubscriptionResponse> => {
56
-        const resp = makeSubResponse({})
57
-        this.subs[resp.uuid] = callback
58
-        return resp
55
+    subscribe = async (callback) : Promise<string> => {
56
+        uuid()
57
+        this.subs[uuid] = callback
58
+        return uuid
59 59
     }
60 60
 
61 61
     unsubscribe = async (uuid: string) => {

+ 7
- 7
src/backend/Components/User/UserManager.ts Ver fichero

@@ -6,10 +6,10 @@ import { RaidManager } from "../Raid/RaidManager";
6 6
 import { CharacterManager } from "../Character/CharacterManager";
7 7
 import { UserManagerFeatureIfc, UserManagerIfc } from "./RPCInterface";
8 8
 import { FrontworkComponent } from "../../Types/FrontworkComponent";
9
-import { Rank, User, Auth, _Rank, TableDefiniton, RPCPermission, FrontcraftFeatureIfc, AnyRPCExporter, Token, UserRecord } from "../../Types/Types";
9
+import { Rank, User, Auth, _Rank, TableDefiniton, RPCPermission, FrontcraftFeatureIfc, Token, UserRecord } from "../../Types/Types";
10 10
 import { IAdmin } from "../../Admin/Interface";
11 11
 import { IUserManager } from "./Interface";
12
-import { getLogger, Logger } from "log4js";
12
+import { getLogger } from "log4js";
13 13
 import { saltedHash } from "../../Util/hash";
14 14
 import { _Tiers, Tiers } from "../../Types/Items";
15 15
 import { ICharacterManager } from "../Character/Interface";
@@ -24,8 +24,8 @@ const uuid = require('uuid/v4')
24 24
 const salt = "6pIbc6yjSN"
25 25
 const ONE_WEEK = 604800000
26 26
 
27
-type Serverstate<SubresT, InterfaceT extends RPCInterface> = {
28
-    server: RPCServer<SubresT, InterfaceT>,
27
+type Serverstate<InterfaceT extends RPCInterface> = {
28
+    server: RPCServer<InterfaceT>,
29 29
     port: number,
30 30
 };
31 31
 
@@ -51,7 +51,7 @@ export class UserManager
51 51
     private character: CharacterManager
52 52
 
53 53
     exporters: any[] = []
54
-    rankServer: Serverstate<{}, FrontcraftFeatureIfc>
54
+    rankServer: Serverstate<FrontcraftFeatureIfc>
55 55
     userLogins: { [username in string]: UserRecord } = {}
56 56
     allowed: string[] = []
57 57
 
@@ -376,12 +376,12 @@ export class UserManager
376 376
         return
377 377
     }
378 378
 
379
-    startRankServer = async (port: number): Promise<RPCServer<{}, FrontcraftFeatureIfc>> => {
379
+    startRankServer = async (port: number): Promise<RPCServer<FrontcraftFeatureIfc>> => {
380 380
         let rpcs = [
381 381
             ...this.exportRPCFeatures(),
382 382
             ...this.exporters.flatMap((exp) => exp.exportRPCFeatures())
383 383
         ]
384
-        let rpcServer = new RPCServer<{}, FrontcraftFeatureIfc>(port, rpcs, {
384
+        let rpcServer = new RPCServer<FrontcraftFeatureIfc>(port, rpcs, {
385 385
             accessFilter: async (sesame, exporter) => {
386 386
                 const record = this.getUserRecordByToken(sesame!)
387 387
                 if (!record) return false

+ 0
- 1
src/backend/Injector/ServiceDecorator.ts Ver fichero

@@ -1,6 +1,5 @@
1 1
 import { Injector } from "./Injector";
2 2
 import { Type, GenericClassDecorator } from "./Util";
3
-import { FrontworkComponent } from "../Types/FrontworkComponent";
4 3
 import { RPCExporter } from "rpclibrary";
5 4
 
6 5
 /**

+ 1
- 0
src/backend/Types/Constants.ts Ver fichero

@@ -0,0 +1 @@
1
+export const MAX_MEMO_LENGTH = 255

+ 4
- 5
src/backend/Types/FrontworkComponent.ts Ver fichero

@@ -1,4 +1,4 @@
1
-import { RPCInterface, RPCExporter, RPCInterfaceArray } from "rpclibrary";
1
+import { RPCInterface, RPCExporter, RPCDefinitions } from "rpclibrary";
2 2
 import { PrivilegedRPCExporter } from "./PrivilegedRPCExporter";
3 3
 import { TableDefinitionExporter } from "./Interfaces";
4 4
 import { TableDefiniton } from "./Types";
@@ -8,15 +8,14 @@ export interface FrontworkComponent<
8 8
     FeatureIfc extends RPCInterface = RPCInterface, 
9 9
     Name extends keyof Ifc = keyof Ifc, 
10 10
     FeatureName extends keyof FeatureIfc = keyof FeatureIfc, 
11
-    SubresT = {}
12 11
 > extends
13
-    PrivilegedRPCExporter<Ifc, FeatureIfc, Name, FeatureName, SubresT>,
12
+    PrivilegedRPCExporter<Ifc, FeatureIfc, Name, FeatureName>,
14 13
     TableDefinitionExporter
15 14
 {
16 15
     name: Name;
17 16
 
18
-    exportRPCFeatures(): RPCExporter<FeatureIfc, FeatureName, SubresT>[] 
19
-    exportRPCs(): RPCInterfaceArray<Ifc>[Name]
17
+    exportRPCFeatures(): RPCExporter<FeatureIfc, FeatureName>[] 
18
+    exportRPCs(): RPCDefinitions<Ifc>[Name]
20 19
     getTableDefinitions(): TableDefiniton[] 
21 20
 
22 21
     initialize?(): Promise<any>

+ 1
- 1
src/backend/Types/Plugin.ts Ver fichero

@@ -6,7 +6,7 @@ import { TableDefiniton } from "./Types"
6 6
 
7 7
 
8 8
 export abstract class Plugin<ConfType = {}> 
9
-implements ConfigExporter<ConfType>, RPCExporter<any,any,any>, TableDefinitionExporter{
9
+implements ConfigExporter<ConfType>, RPCExporter, TableDefinitionExporter{
10 10
     
11 11
     constructor (protected admin: FrontworkAdmin, public name:string){
12 12
         if(!this.getConfig()){

+ 2
- 3
src/backend/Types/PrivilegedRPCExporter.ts Ver fichero

@@ -1,11 +1,10 @@
1
-import { RPCExporter, RPCInterface, RPC, RPCInterfaceArray } from "rpclibrary";
1
+import { RPCExporter, RPCInterface } from "rpclibrary";
2 2
 
3 3
 export interface PrivilegedRPCExporter <
4 4
     Ifc extends RPCInterface = RPCInterface, 
5 5
     FeatureIfc extends RPCInterface = RPCInterface,
6 6
     Name extends keyof Ifc = keyof Ifc, 
7 7
     FeatureName extends keyof FeatureIfc = keyof FeatureIfc, 
8
-    SubresT = {}
9 8
 >extends RPCExporter<Ifc, Name>{
10
-    exportRPCFeatures() : RPCExporter<FeatureIfc, FeatureName, SubresT>[]
9
+    exportRPCFeatures() : RPCExporter<FeatureIfc, FeatureName>[]
11 10
 }

+ 2
- 0
src/backend/Types/Types.ts Ver fichero

@@ -165,6 +165,8 @@ export type Signup = {
165 165
     characterid: number
166 166
     benched: boolean
167 167
     late: boolean
168
+    timestamp: string
169
+    memo?: string
168 170
 }
169 171
 
170 172
 export type Character = {

+ 3
- 0
src/frontend/angular.json Ver fichero

@@ -58,6 +58,9 @@
58 58
           "configurations": {
59 59
             "production": {
60 60
               "aot": true,
61
+              "optimization": true,
62
+              "extractCss": true,
63
+              "sourceMap": true,
61 64
               "fileReplacements": [
62 65
                 {
63 66
                   "replace": "src/environments/environment.ts",

+ 11
- 3
src/frontend/package-lock.json Ver fichero

@@ -15742,13 +15742,21 @@
15742 15742
       "integrity": "sha512-ZYzRkETgBrdEGzL5JSKimvjI2CX7ioyZCkX2BpcfyjqI+079W0wHAyj5W4rIZMcDSOHgLZtgz1IdDi/vU77KEQ=="
15743 15743
     },
15744 15744
     "rpclibrary": {
15745
-      "version": "1.9.2",
15746
-      "resolved": "https://registry.npmjs.org/rpclibrary/-/rpclibrary-1.9.2.tgz",
15747
-      "integrity": "sha512-MOtVm0IBRLryXag1IwkYNPVFegbvW10+MbCjhr3GptO3MA7nHZ545ammgoCWnREtGOgFeN4Jib/EBDOJ9Ep41Q==",
15745
+      "version": "1.10.2",
15746
+      "resolved": "https://registry.npmjs.org/rpclibrary/-/rpclibrary-1.10.2.tgz",
15747
+      "integrity": "sha512-uf4FtylK+tyVo1O8YVihxYxaI4KHnKBzq05SsLYe8ZPXdO8Hqrv7Je5cwv3bfx0FBCO1vVrSc8DT1P6ypGY6uQ==",
15748 15748
       "requires": {
15749 15749
         "bsock": "^0.1.9",
15750
+        "crypto-js": "^4.0.0",
15750 15751
         "http": "0.0.0",
15751 15752
         "uuid": "^3.3.3"
15753
+      },
15754
+      "dependencies": {
15755
+        "crypto-js": {
15756
+          "version": "4.0.0",
15757
+          "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.0.0.tgz",
15758
+          "integrity": "sha512-bzHZN8Pn+gS7DQA6n+iUmBfl0hO5DJq++QP3U6uTucDtk/0iGpXd/Gg7CGR0p8tJhofJyaKoWBuJI4eAO00BBg=="
15759
+        }
15752 15760
       }
15753 15761
     },
15754 15762
     "run-async": {

+ 3
- 2
src/frontend/package.json Ver fichero

@@ -29,7 +29,8 @@
29 29
     "prepush": "npm run lint:ci",
30 30
     "release:changelog": "npm run conventional-changelog -- -p angular -i CHANGELOG.md -s",
31 31
     "add": "ng add @nguniversal/express-engine",
32
-    "tsc": "tsc --project src/tsconfig.server.json && webpack --config extra-webpack.config.js"
32
+    "tsc": "tsc --project src/tsconfig.server.json && webpack --config extra-webpack.config.js",
33
+    "knex": "knex"
33 34
   },
34 35
   "dependencies": {
35 36
     "@agm/core": "^1.0.0-beta.5",
@@ -75,7 +76,7 @@
75 76
     "normalize.css": "6.0.0",
76 77
     "pace-js": "1.0.2",
77 78
     "roboto-fontface": "0.8.0",
78
-    "rpclibrary": "^1.9.2",
79
+    "rpclibrary": "^1.10.2",
79 80
     "rxjs": "6.5.2",
80 81
     "rxjs-compat": "6.3.0",
81 82
     "socicon": "3.0.5",

+ 8
- 3
src/frontend/server.ts Ver fichero

@@ -13,7 +13,7 @@ global['document'] = win.document;
13 13
 global['alert'] = console.log
14 14
 global['XMLHttpRequest'] = require('xmlhttprequest').XMLHttpRequest;
15 15
 
16
-export async function attachExpress(app, staticDir = "./dist") {
16
+export async function attachExpress(app, staticDir = "./dist", loggerService = console) {
17 17
   const STATIC_FOLDER = resolve(process.cwd(), staticDir);
18 18
 
19 19
   enableProdMode();
@@ -21,7 +21,7 @@ export async function attachExpress(app, staticDir = "./dist") {
21 21
   const bundle = require(staticDir + '/server/main');
22 22
 
23 23
   const ServerApiService = bundle.ServerApiService
24
-  const serviceObj = new ServerApiService()
24
+  const serviceObj = new ServerApiService(loggerService)
25 25
   await serviceObj.initialize()
26 26
 
27 27
   app.set('view engine', 'html');
@@ -31,10 +31,15 @@ export async function attachExpress(app, staticDir = "./dist") {
31 31
       bootstrap: bundle.AppServerModuleNgFactory,
32 32
       providers: [
33 33
         provideModuleMap(bundle.LAZY_MODULE_MAP),
34
+        {
35
+          provide: bundle.LoggerService,
36
+          deps: [],
37
+          useValue: loggerService
38
+        },
34 39
         {
35 40
           provide: bundle.IApiService,
41
+          deps: [],
36 42
           useValue: serviceObj,
37
-          deps: []
38 43
         }
39 44
       ]
40 45
     })

+ 2
- 1
src/frontend/src/app/@theme/components/header/header.component.html Ver fichero

@@ -29,7 +29,8 @@
29 29
     </nb-action>
30 30
   
31 31
     <nb-action class="user-action">
32
-      <nb-user [nbContextMenu]="userMenu"
32
+      <nb-user style="text-transform: capitalize;"
33
+               [nbContextMenu]="userMenu"
33 34
                [onlyPicture]="false"
34 35
                [name]="user?.username">
35 36
       </nb-user>

+ 43
- 20
src/frontend/src/app/@theme/components/header/header.component.ts Ver fichero

@@ -5,7 +5,7 @@ import { LayoutService } from '../../../@core/utils';
5 5
 import { map, takeUntil } from 'rxjs/operators';
6 6
 import { Subject } from 'rxjs';
7 7
 import { User } from '../../../../../../backend/Types/Types';
8
-import { Router } from '@angular/router';
8
+import { Router, ActivatedRoute, NavigationEnd } from '@angular/router';
9 9
 import { ChatComponent } from './chat.component';
10 10
 import { ShoutMessage } from '../../../../../../backend/Components/Shoutbox/Interface';
11 11
 import { IApiService } from '../../../frontcraft/services/ApiService';
@@ -41,7 +41,7 @@ export class HeaderComponent implements OnInit, OnDestroy {
41 41
   ];
42 42
 
43 43
   currentTheme = 'default';
44
-  userMenu : NbMenuItem[] = [ { title: 'Log out', link: '/auth/logout' } ];
44
+  userMenu: NbMenuItem[] = [];
45 45
 
46 46
   sendMessage: any = console.log
47 47
   chatwindow: ChatComponent
@@ -50,13 +50,29 @@ export class HeaderComponent implements OnInit, OnDestroy {
50 50
   lastmessage = "asdasd"
51 51
   modifyPermissions
52 52
 
53
-  constructor(private sidebarService: NbSidebarService,
54
-              private router: Router,
55
-              private themeService: NbThemeService,
56
-              private layoutService: LayoutService,
57
-              private api: IApiService,
58
-              private dialogService : NbDialogService
59
-             ) {}
53
+  constructor(
54
+    private sidebarService: NbSidebarService,
55
+    private router: Router,
56
+    private themeService: NbThemeService,
57
+    private layoutService: LayoutService,
58
+    private api: IApiService,
59
+    private dialogService: NbDialogService,
60
+    private route: ActivatedRoute
61
+  ) { }
62
+
63
+  private setUserMenu = (redirect = this.router.url) => {
64
+    if (this.user.username === 'Guest' && this.user.rank === 'Guest'){
65
+      this.userMenu = [
66
+        { title: 'Login', link: '/auth/login', queryParams: { redirect: redirect } },
67
+        { title: 'Register', link: '/auth/register', queryParams: { redirect: redirect } },
68
+      ]
69
+    }else{
70
+      this.userMenu = [
71
+        { title: 'Profile', link: '/frontcraft/user/' + this.user.username },
72
+        { title: 'Log out', link: '/auth/logout', queryParams: { redirect: redirect } },
73
+      ]
74
+    }
75
+  }
60 76
 
61 77
   ngOnInit() {
62 78
     this.themeService.changeTheme("dark");
@@ -64,28 +80,36 @@ export class HeaderComponent implements OnInit, OnDestroy {
64 80
     this.currentTheme = this.themeService.currentTheme;
65 81
     this.modifyPermissions = this.api.get('modifyPermissions')
66 82
     this.user = this.api.getCurrentUser()
67
-    if(this.user)
68
-      this.userMenu.unshift({ title: 'Profile', link: '/frontcraft/user/'+this.user.username });
69
-   
83
+    
84
+    this.setUserMenu()
85
+
86
+    this.router.events.subscribe((val) => {
87
+      if(val instanceof NavigationEnd) {
88
+        this.setUserMenu(val.urlAfterRedirects)
89
+      }
90
+    })
91
+
92
+
93
+
70 94
     this.api.get('GuildManager').getGuildInfo().then(info => {
71 95
       this.title = info.name
72 96
     })
73 97
 
74 98
     this.api.connectShoutbox((msg) => {
75 99
       this.chatlog.push(msg)
76
-      msg['reply']=false
100
+      msg['reply'] = false
77 101
 
78
-      if(msg.message != this.lastmessage){
102
+      if (msg.message != this.lastmessage) {
79 103
         this.newmessage = true
80
-        msg['reply']=true
104
+        msg['reply'] = true
81 105
       }
82
-      if(this.chatwindow) this.chatwindow.messages.push(msg)
106
+      if (this.chatwindow) this.chatwindow.messages.push(msg)
83 107
     }).then(sendMsg => {
84 108
       this.sendMessage = (msg) => {
85 109
         sendMsg(msg)
86 110
         this.lastmessage = msg.message
87 111
       }
88
-      this.api.get('Shoutbox').getFeed().then(log => {this.chatlog = log})
112
+      this.api.get('Shoutbox').getFeed().then(log => { this.chatlog = log })
89 113
     })
90 114
 
91 115
     this.themeService.onThemeChange()
@@ -96,14 +120,14 @@ export class HeaderComponent implements OnInit, OnDestroy {
96 120
       .subscribe(themeName => this.currentTheme = themeName);
97 121
   }
98 122
 
99
-  openChat(){
123
+  openChat() {
100 124
     this.newmessage = false
101 125
     const ref = this.dialogService.open(ChatComponent, {
102 126
       context: {
103 127
         sendMessage: this.sendMessage,
104 128
       }
105 129
     });
106
-    ref.onClose.subscribe(()=>{
130
+    ref.onClose.subscribe(() => {
107 131
       this.chatwindow = null
108 132
     })
109 133
     this.chatwindow = ref.componentRef.instance
@@ -122,7 +146,6 @@ export class HeaderComponent implements OnInit, OnDestroy {
122 146
   toggleSidebar(): boolean {
123 147
     this.sidebarService.toggle(true, 'menu-sidebar');
124 148
     this.layoutService.changeLayoutSize();
125
-
126 149
     return false;
127 150
   }
128 151
 

+ 1
- 6
src/frontend/src/app/app.component.ts Ver fichero

@@ -9,9 +9,4 @@ import { Component, OnInit } from '@angular/core';
9 9
   selector: 'ngx-app',
10 10
   template: '<router-outlet></router-outlet>',
11 11
 })
12
-export class AppComponent implements OnInit {
13
-
14
-  constructor() {  }
15
-
16
-  ngOnInit(): void { }
17
-}
12
+export class AppComponent { }

+ 5
- 5
src/frontend/src/app/app.module.ts Ver fichero

@@ -5,11 +5,15 @@
5 5
  */
6 6
 import { BrowserModule } from '@angular/platform-browser';
7 7
 import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
8
-import { NgModule, APP_INITIALIZER, NgZone, Injector } from '@angular/core';
8
+import { NgModule } from '@angular/core';
9 9
 import { HttpClientModule } from '@angular/common/http';
10 10
 import { ThemeModule } from './@theme/theme.module';
11 11
 import { AppComponent } from './app.component';
12 12
 import { AppRoutingModule } from './app-routing.module';
13
+import { CoreModule } from './@core/core.module';
14
+import { FrontcraftPagesModule } from './frontcraft/pages/pages.module';
15
+import { MyAuthModule } from './frontcraft/auth/auth.module';
16
+import { PermissionsModule } from './frontcraft/permissions/permissions.module';
13 17
 import {
14 18
   NbChatModule,
15 19
   NbDatepickerModule,
@@ -19,10 +23,6 @@ import {
19 23
   NbToastrModule,
20 24
   NbWindowModule,
21 25
 } from '@nebular/theme';
22
-import { CoreModule } from './@core/core.module';
23
-import { FrontcraftPagesModule } from './frontcraft/pages/pages.module';
24
-import { MyAuthModule } from './frontcraft/auth/auth.module';
25
-import { PermissionsModule } from './frontcraft/permissions/permissions.module';
26 26
 
27 27
 @NgModule({
28 28
   declarations: [

+ 1
- 1
src/frontend/src/app/app.server.module.ts Ver fichero

@@ -1,5 +1,5 @@
1 1
 
2
-import { NgModule, APP_INITIALIZER } from '@angular/core';
2
+import { NgModule } from '@angular/core';
3 3
 import { ServerModule } from '@angular/platform-server';
4 4
 import { ModuleMapLoaderModule } from '@nguniversal/module-map-ngfactory-loader';
5 5
 

+ 57
- 0
src/frontend/src/app/frontcraft/UpdatingComponent.ts Ver fichero

@@ -0,0 +1,57 @@
1
+import { Router, NavigationStart } from '@angular/router'
2
+import { IApiService } from './services/ApiService'
3
+import { AnyFunction } from 'rpclibrary'
4
+import { LoggerService } from './services/logger.service'
5
+import { OnDestroy } from '@angular/core'
6
+
7
+export abstract class UpdatingComponent implements OnDestroy {
8
+    private _uuid: string
9
+    private _routerCancel: Function
10
+
11
+    constructor(
12
+        private _router: Router,
13
+        private _api: IApiService,
14
+        private _logger: LoggerService
15
+    ) { }
16
+
17
+    protected subscribe = (
18
+        topic: string,
19
+        callback: AnyFunction,
20
+    ) => {
21
+        const sub = this._router.events.subscribe(event => {
22
+            if (event instanceof NavigationStart) {
23
+                this.ngOnDestroy()
24
+            }
25
+        })
26
+        this._routerCancel = () => { sub.unsubscribe() }
27
+        this._api.get('PubSub').subscribe(topic, callback).then(uuid => {
28
+            this._logger.collapsed(`New subscription ${topic}`, "table", {
29
+                topic: topic,
30
+                uuid: uuid
31
+            })
32
+            this._uuid = uuid
33
+        }).catch(e => {
34
+            this._logger.warn(`Subscribe for ${topic} failed, ${String(e)}`)
35
+            delete this._uuid
36
+        })
37
+    }
38
+
39
+    //Note angular may call this function several times
40
+    ngOnDestroy() {
41
+        if (this._uuid) {
42
+            const id = this._uuid
43
+            delete this._uuid
44
+            this._api.get('PubSub').unsubscribe(id).then(() => {
45
+                this._logger.log(`Unsubscribed from ${id}`)
46
+            })
47
+        }
48
+        if (this._routerCancel) {
49
+            try {
50
+                this._routerCancel()
51
+            } catch (e) {
52
+                this._logger.warn(e)
53
+            }
54
+            delete this._routerCancel
55
+        }
56
+    }
57
+}

+ 0
- 2
src/frontend/src/app/frontcraft/auth/auth-layout.component.ts Ver fichero

@@ -1,6 +1,4 @@
1 1
 import { Component, OnInit } from '@angular/core';
2
-import { ClientApiService } from '../services/client-login-api';
3
-import { Router } from '@angular/router';
4 2
 
5 3
 @Component({
6 4
   selector: 'auth-layout',

+ 1
- 1
src/frontend/src/app/frontcraft/auth/login/login.component.html Ver fichero

@@ -48,5 +48,5 @@
48 48
 
49 49
 
50 50
 <section class="another-action" aria-label="Register">
51
-  Don't have an account? <a class="text-link" routerLink="/auth/register">Register</a>
51
+  Don't have an account? <a class="text-link" routerLink="/auth/register" [queryParams]="{redirect: '/frontcraft'}">Register</a>
52 52
 </section>

+ 6
- 5
src/frontend/src/app/frontcraft/auth/login/login.component.ts Ver fichero

@@ -1,6 +1,5 @@
1 1
 import { Component, OnInit } from '@angular/core';
2
-import { ClientApiService } from '../../services/client-login-api';
3
-import { Router } from '@angular/router';
2
+import { Router, ActivatedRoute } from '@angular/router';
4 3
 import { IApiService } from '../../services/ApiService';
5 4
 import { NbToastrService } from '@nebular/theme';
6 5
 
@@ -24,7 +23,8 @@ export class MyLoginComponent implements OnInit{
24 23
   constructor(
25 24
     private router : Router,  
26 25
     private api : IApiService,
27
-    private toastr: NbToastrService
26
+    private toastr: NbToastrService,
27
+    private route: ActivatedRoute
28 28
   ){}
29 29
 
30 30
   ngOnInit(){
@@ -41,8 +41,9 @@ export class MyLoginComponent implements OnInit{
41 41
       this.toastr.danger("Login failed", "Error")
42 42
       return
43 43
     }else{
44
-      window['r'] = this.router
45
-      this.router.navigate(["/froncraft"])
44
+      this.route.queryParamMap.subscribe(params => {
45
+        this.router.navigate([params.get('redirect')])        
46
+      })
46 47
     }
47 48
   }
48 49
 }

+ 1
- 1
src/frontend/src/app/frontcraft/auth/logout/logout.component.html Ver fichero

@@ -1 +1 @@
1
-You will be redirected shortly. If not click here <a href="/auth/login">click</a>
1
+You will be redirected shortly. If not click here <a routerLink="/auth/login" [queryParams]="{redirect: '/frontcraft'}">click</a>

+ 6
- 3
src/frontend/src/app/frontcraft/auth/logout/logout.component.ts Ver fichero

@@ -1,6 +1,6 @@
1 1
 import { Component, OnInit } from '@angular/core';
2 2
 import { IApiService } from '../../services/ApiService';
3
-import { Router } from '@angular/router';
3
+import { Router, ActivatedRoute } from '@angular/router';
4 4
 
5 5
 @Component({
6 6
   selector: 'mylogout',
@@ -10,12 +10,15 @@ export class LogoutComponent implements OnInit{
10 10
 
11 11
   constructor(
12 12
     private api : IApiService,
13
-    private router: Router
13
+    private router: Router,
14
+    private route: ActivatedRoute
14 15
   ){}
15 16
 
16 17
   ngOnInit(){
17 18
     this.api.logout().then(() => {
18
-      this.router.navigate(['/auth/login'])
19
+      this.route.queryParamMap.subscribe(params => {
20
+        this.router.navigate([params.get('redirect')])        
21
+      })
19 22
     })
20 23
   }
21 24
 }

+ 1
- 1
src/frontend/src/app/frontcraft/auth/register/register.component.html Ver fichero

@@ -92,5 +92,5 @@
92 92
 
93 93
 
94 94
 <section class="another-action" aria-label="Register">
95
-  Back to <a class="text-link" routerLink="auth/login">Login</a>
95
+  Go to <a class="text-link" routerLink="auth/login" [queryParams]="{redirect: '/frontcraft'}">Login</a>
96 96
 </section>

+ 8
- 4
src/frontend/src/app/frontcraft/auth/register/register.component.ts Ver fichero

@@ -1,9 +1,7 @@
1 1
 import { Component, OnInit } from '@angular/core';
2
-import { ClientApiService as ClientApiService } from '../../services/client-login-api';
3
-import { Router } from '@angular/router';
2
+import { Router, ActivatedRoute } from '@angular/router';
4 3
 import { _Rank, _Class, Class, User, _Race  } from '../../../../../../backend/Types/Types'
5 4
 import { specs  } from '../../../../../../backend/Types/PlayerSpecs'
6
-import { race } from 'rxjs';
7 5
 import { hash, IApiService } from '../../services/ApiService';
8 6
 
9 7
 
@@ -33,7 +31,8 @@ export class RegisterComponent implements OnInit{
33 31
   submitted = false
34 32
 
35 33
   constructor(
36
-    private router : Router,  
34
+    private router : Router,
35
+    private route : ActivatedRoute,
37 36
     private api : IApiService
38 37
   ){}
39 38
 
@@ -84,6 +83,11 @@ export class RegisterComponent implements OnInit{
84 83
         userid: this.api.getAuth().user.id!,
85 84
         race: char.race
86 85
       })
86
+
87
+      this.route.queryParamMap.subscribe(params => {
88
+        this.router.navigate([params.get('redirect')])        
89
+      })
90
+
87 91
     }catch(e){
88 92
       alert("Error creating character"+e)
89 93
       return

+ 0
- 1
src/frontend/src/app/frontcraft/pages/armory/armory.component.ts Ver fichero

@@ -2,7 +2,6 @@ import { Component, OnInit } from '@angular/core';
2 2
 import { Item, Stats } from '../../../../../../backend/Types/Types';
3 3
 
4 4
 import { NbToastrService } from '@nebular/theme';
5
-import { ClientApiService } from '../../services/client-login-api';
6 5
 import { IApiService } from '../../services/ApiService';
7 6
 
8 7
 @Component({

+ 1
- 2
src/frontend/src/app/frontcraft/pages/character/character.component.ts Ver fichero

@@ -1,6 +1,5 @@
1 1
 import { Component, OnInit, Input } from '@angular/core';
2
-import { ActivatedRoute, Router } from '@angular/router';
3
-import { ClientApiService as ClientApiService } from '../../services/client-login-api';
2
+import { ActivatedRoute } from '@angular/router';
4 3
 import { Spec, User, Character, Item } from '../../../../../../backend/Types/Types';
5 4
 import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
6 5
 import { _Tiers } from '../../../../../../backend/Types/Items';

+ 3
- 17
src/frontend/src/app/frontcraft/pages/pages-layout.component.ts Ver fichero

@@ -1,10 +1,8 @@
1
-import { Component, AfterContentInit, OnInit } from '@angular/core';
1
+import { Component, OnInit } from '@angular/core';
2 2
 import { NbMenuItem } from '@nebular/theme';
3
-import { ClientApiService } from '../services/client-login-api';
4 3
 import { Router } from '@angular/router';
5 4
 import { IApiService } from '../services/ApiService';
6 5
 
7
-declare const Cookies
8 6
 
9 7
 @Component({
10 8
   selector: 'page-layout',
@@ -16,7 +14,7 @@ declare const Cookies
16 14
     </ngx-one-column-layout>
17 15
   `,
18 16
 })
19
-export class PagesLayoutComponent implements OnInit{
17
+export class PagesLayoutComponent{
20 18
 
21 19
   menu:NbMenuItem[] = [{
22 20
     icon: 'image',
@@ -36,18 +34,6 @@ export class PagesLayoutComponent implements OnInit{
36 34
     link: '/frontcraft/armory'
37 35
   }]
38 36
   
39
-  constructor(
40
-    private api : IApiService,
41
-    private router : Router
42
-  ){}
37
+  constructor(){}
43 38
 
44
-  ngOnInit(): void {
45
-    /*
46
-    const u = this.api.getCurrentUser()
47
-    
48
-    if(!u){
49
-      this.router.navigate(['/auth/login'])
50
-    }
51
-    */
52
-  }
53 39
 }

+ 0
- 1
src/frontend/src/app/frontcraft/pages/pages.module.ts Ver fichero

@@ -9,7 +9,6 @@ import {
9 9
   NbInputModule,
10 10
   NbMenuModule,
11 11
   NbCardModule,
12
-  NbTreeGridModule,
13 12
   NbListModule,
14 13
   NbTabsetModule,
15 14
   NbIconModule,

+ 18
- 5
src/frontend/src/app/frontcraft/pages/raid/archive.component.ts Ver fichero

@@ -1,6 +1,5 @@
1 1
 import { Component, OnInit } from '@angular/core';
2 2
 import { ActivatedRoute } from '@angular/router';
3
-import { ClientApiService as ClientApiService } from '../../services/client-login-api';
4 3
 import { RaidData } from '../../../../../../backend/Types/Types';
5 4
 import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
6 5
 import { IApiService } from '../../services/ApiService';
@@ -34,7 +33,7 @@ export class FrontcraftArchiveComponent implements OnInit{
34 33
       tanks:[],
35 34
       healers: []
36 35
     }
37
-    tokens = {}
36
+    tokens: {[key in string]:any[]} = {}
38 37
     displayedtokens = {}
39 38
     search = ""
40 39
     
@@ -53,6 +52,10 @@ export class FrontcraftArchiveComponent implements OnInit{
53 52
 
54 53
       const raidManager = this.api.get('RaidManager')
55 54
       const raiddata = await raidManager.getArchiveRaid(parseInt(param))
55
+
56
+      console.log(raiddata);
57
+      
58
+
56 59
       this.raid = raiddata
57 60
       this.isTier = raiddata.tier != null
58 61
       this.tokens = raiddata.tokens
@@ -69,8 +72,18 @@ export class FrontcraftArchiveComponent implements OnInit{
69 72
       this.changeSearch()
70 73
     }
71 74
 
72
-    changeSearch = () => {
73
-      this.tokens = this.raid.tokens;
74
-      this.displayedtokens = this.raid.tokens;
75
+    changeSearch(){
76
+      if(!this.search || this.search == ""){
77
+        this.displayedtokens = this.tokens
78
+      }else{
79
+        this.displayedtokens = {}
80
+        Object.entries(this.tokens).forEach((e) => {
81
+          const filteredTokens = e[1].filter(item => {
82
+            return item.itemname.toLocaleLowerCase().includes(this.search.toLocaleLowerCase())
83
+          })
84
+          if(filteredTokens.length > 0)
85
+            this.displayedtokens[e[0]] = filteredTokens 
86
+        })
87
+      }
75 88
     }
76 89
 }

+ 35
- 28
src/frontend/src/app/frontcraft/pages/raid/characterpicker.component.html Ver fichero

@@ -3,34 +3,41 @@
3 3
       Pick Character
4 4
     </nb-card-header>
5 5
     <nb-card-body>
6
-        <div *ngFor="let character of characters">
7
-            <img [src]="'../../../../assets/images/'+character.class.toLowerCase()+'.png'" />
8
-            <span [ngStyle]="{'color': character.color}">
6
+        <textarea 
7
+            placeholder="Add a note (optional)"
8
+            rows="7" 
9
+            cols="50" 
10
+            nbInput style="white-space: pre-line;" 
11
+            [(ngModel)]="memo">
12
+        </textarea>
13
+        <br />
14
+        <br />
15
+        <nb-card *ngFor="let character of characters">
16
+            <nb-card-header [ngStyle]="{'color': character.color}">
17
+                <img [src]="'../../../../assets/images/'+character.class.toLowerCase()+'.png'" />
9 18
                 {{character.charactername}}
10
-            </span>
11
-            <br >
12
-            <br >
13
-            <br >
14
-
15
-            <button
16
-                (click)="signup(character, false)"
17
-                nbButton 
18
-                outline 
19
-                status="success" 
20
-                size="medium">
21
-                <nb-icon icon="checkmark-outline"></nb-icon> On Time
22
-            </button>
23
-            &nbsp;
24
-            &nbsp;
25
-            &nbsp;
26
-            <button
27
-                (click)="signup(character, true)"
28
-                nbButton 
29
-                outline 
30
-                status="warning" 
31
-                size="medium">
32
-                <nb-icon icon="clock-outline"></nb-icon> Late
33
-            </button>
34
-        </div>
19
+            </nb-card-header>
20
+            <nb-card-body>
21
+                <button
22
+                    (click)="signup(character, false)"
23
+                    nbButton 
24
+                    outline 
25
+                    status="success" 
26
+                    size="medium">
27
+                    <nb-icon icon="checkmark-outline"></nb-icon> On Time
28
+                </button>
29
+                &nbsp;
30
+                &nbsp;
31
+                &nbsp;
32
+                <button
33
+                    (click)="signup(character, true)"
34
+                    nbButton 
35
+                    outline 
36
+                    status="warning" 
37
+                    size="medium">
38
+                    <nb-icon icon="clock-outline"></nb-icon> Late
39
+                </button>
40
+            </nb-card-body>
41
+        </nb-card>
35 42
     </nb-card-body>
36 43
 </nb-card>

+ 3
- 3
src/frontend/src/app/frontcraft/pages/raid/characterpicker.component.ts Ver fichero

@@ -1,7 +1,6 @@
1 1
 import { OnInit, Component } from '@angular/core';
2
-import { NbWindowRef, NbToastrService, NbDialogRef } from '@nebular/theme';
2
+import { NbToastrService, NbDialogRef } from '@nebular/theme';
3 3
 import { RaidData, Character } from '../../../../../../backend/Types/Types';
4
-import { ClientApiService } from '../../services/client-login-api';
5 4
 import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
6 5
 import { IApiService } from '../../services/ApiService';
7 6
 
@@ -13,6 +12,7 @@ export class FrontcraftCharacerpickerComponent implements OnInit{
13 12
 
14 13
     raid : RaidData
15 14
     characters: Character[]
15
+    memo: string
16 16
 
17 17
     constructor(
18 18
         protected dialogRef: NbDialogRef<FrontcraftCharacerpickerComponent>,
@@ -25,7 +25,7 @@ export class FrontcraftCharacerpickerComponent implements OnInit{
25 25
         const signup = this.api.get('signup')
26 26
         if(!signup) return
27 27
 
28
-        await signup.sign(auth.token.value, character, this.raid, late)
28
+        await signup.sign(auth.token.value, character, this.raid, late, this.memo)
29 29
         this.toast.show('Signup', 'Success', { status: 'success' })
30 30
         this.dialogRef.close()
31 31
     }

+ 92
- 31
src/frontend/src/app/frontcraft/pages/raid/raid.component.html Ver fichero

@@ -5,34 +5,47 @@
5 5
                 <nb-tabset>
6 6
                     <nb-tab tabTitle="Info">
7 7
                         <h1>
8
-                            <img [src]="'../../../../assets/images/'+(raid.tier || 'null').toLowerCase()+'.png'"
8
+                            <img [src]="'/assets/images/'+(raid.tier || 'null').toLowerCase()+'.png'"
9 9
                                 style="height: 100px" />
10 10
                             {{raid.title}}
11 11
                         </h1>
12 12
                         <p>
13 13
                             {{raid.signupcount}} / {{raid.size}} signups
14 14
                         </p>
15
-                        <p>
15
+                        <p style="white-space: pre-line;">
16 16
                             {{raid.description}}
17 17
                         </p>
18 18
                         <div *ngIf="canSignup">
19
-                            <div *ngIf="isSignedup">
20
-
21
-                                <p>
22
-                                    You are signed as: {{mySignup.charactername}} ({{mySignup.race}}
23
-                                    {{mySignup.specname}}
24
-                                    {{mySignup.class}})<br />
25
-                                    Status: {{mySignup.status}}
19
+                            <div *ngIf="isSignedup" style="width: 100%;">
20
+                                <p style="white-space: pre-line;">
21
+                                    You are signed as: <span
22
+                                        style="text-transform: capitalize; word-break: keep-all;">{{mySignup.charactername}}</span>
23
+                                    ({{mySignup.race}} {{mySignup.specname}} {{mySignup.class}})
24
+                                    <br />
25
+                                    Status: {{mySignup.status}}<br /><br />
26
+                                    <textarea [status]="mySignup.status === 'Attending'?'success':'warning'"
27
+                                        placeholder="Add a note (optional)" rows="10" cols="50" nbInput
28
+                                        style="white-space: pre-line;" [(ngModel)]="mySignup.memo">
29
+                                    </textarea>
26 30
                                 </p>
27 31
 
28
-                                <button (click)="setLate(true)" *ngIf="mySignup.status !== 'Late'" nbButton outline
29
-                                    status="warning" size="medium">
30
-                                    <nb-icon icon="clock-outline"></nb-icon> Late
31
-                                </button>
32
-                                <button (click)="setLate(false)" *ngIf="mySignup.status === 'Late'" nbButton outline
32
+                                <button *ngIf="mySignup.status === 'Late'" (click)="setLate(false)" nbButton outline
33 33
                                     status="success" size="medium">
34 34
                                     <nb-icon icon="checkmark-outline"></nb-icon> On Time
35 35
                                 </button>
36
+                                <button *ngIf="mySignup.status === 'Attending'" (click)="setLate(false)" nbButton
37
+                                    outline status="success" size="medium">
38
+                                    <nb-icon icon="checkmark-outline"></nb-icon> Update
39
+                                </button>
40
+                                <button *ngIf="mySignup.status === 'Late'" (click)="setLate(true)" nbButton outline
41
+                                    status="warning" size="medium">
42
+                                    <nb-icon icon="clock-outline"></nb-icon> Update
43
+                                </button>
44
+                                <button *ngIf="mySignup.status === 'Attending'" (click)="setLate(true)" nbButton outline
45
+                                    status="warning" size="medium">
46
+                                    <nb-icon icon="clock-outline"></nb-icon> Late
47
+                                </button>
48
+
36 49
                                 <button (click)="unsign()" nbButton outline status="danger" size="medium">
37 50
                                     <nb-icon icon="close"></nb-icon>unsign
38 51
                                 </button>
@@ -46,7 +59,6 @@
46 59
                     </nb-tab>
47 60
                     <nb-tab tabTitle="Signups" [badgeText]="raid.signupcount" badgePosition="top right"
48 61
                         [badgeStatus]="raid.signupcount<40?'warning':'success'">
49
-
50 62
                         <div class="row">
51 63
                             <nb-card class="col-12 col-md-6" *ngIf="raid.tanks.length > 0">
52 64
                                 <nb-card-header>Tanks ({{raid.tanks.length}})</nb-card-header>
@@ -63,11 +75,28 @@
63 75
                                         <a [ngStyle]="{'color': participant.color}" style="text-transform: capitalize;"
64 76
                                             [routerLink]="'/frontcraft/character/'+participant.charactername">
65 77
                                             <img style="width:20px; height:20px"
66
-                                                [src]="'../../../../assets/images/'+participant.race.toLowerCase()+'_xs.gif'" />
78
+                                                [src]="'/assets/images/'+participant.race.toLowerCase()+'_xs.gif'" />
67 79
                                             <img style="width:20px; height:20px"
68
-                                                [src]="'../../../../assets/images/'+participant.class.toLowerCase()+'.png'" />
80
+                                                [src]="'/assets/images/'+participant.class.toLowerCase()+'.png'" />
69 81
                                             {{ participant.charactername }}
70 82
                                         </a>
83
+                                        <ng-template #template>
84
+                                            <div style="padding: 10px">
85
+                                                <p
86
+                                                    style="white-space: pre-line; max-width: 50vw; word-wrap: break-word;">
87
+                                                    {{participant.memo}}
88
+                                                </p>
89
+                                                {{participant.timestamp | date : 'HH:mm EEE MMM d'}}
90
+                                            </div>
91
+                                        </ng-template>
92
+                                        <nb-icon *ngIf="participant.memo == null || participant.memo == ''"
93
+                                            [nbPopover]="template" nbPopoverTrigger="hover"
94
+                                            style="width: 0.75em; height: 0.75em;" icon="clock-outline"></nb-icon>
95
+
96
+                                        <nb-icon *ngIf="participant.memo != null && participant.memo != ''"
97
+                                            [nbPopover]="template" nbPopoverTrigger="hover"
98
+                                            style="width: 0.75em; height: 0.75em;" icon="message-circle-outline" status="info">
99
+                                        </nb-icon>
71 100
                                         <span *ngIf="participant.rank=='Trial'" style="font-size: 9px;">
72 101
                                             Trial
73 102
                                         </span>
@@ -90,11 +119,27 @@
90 119
                                         <a [ngStyle]="{'color': participant.color}" style="text-transform: capitalize;"
91 120
                                             [routerLink]="'/frontcraft/character/'+participant.charactername">
92 121
                                             <img style="width:20px; height:20px"
93
-                                                [src]="'../../../../assets/images/'+participant.race.toLowerCase()+'_xs.gif'" />
122
+                                                [src]="'/assets/images/'+participant.race.toLowerCase()+'_xs.gif'" />
94 123
                                             <img style="width:20px; height:20px"
95
-                                                [src]="'../../../../assets/images/'+participant.class.toLowerCase()+'.png'" />
124
+                                                [src]="'/assets/images/'+participant.class.toLowerCase()+'.png'" />
96 125
                                             {{ participant.charactername }}
97 126
                                         </a>
127
+                                        <ng-template #template>
128
+                                            <div style="padding: 10px">
129
+                                                <p style="white-space: pre-line;">
130
+                                                    {{participant.memo}}
131
+                                                </p>
132
+                                                {{participant.timestamp | date : 'HH:mm EEE MMM d'}}
133
+                                            </div>
134
+                                        </ng-template>
135
+                                        <nb-icon *ngIf="participant.memo == null || participant.memo == ''"
136
+                                            [nbPopover]="template" nbPopoverTrigger="hover"
137
+                                            style="width: 0.75em; height: 0.75em;" icon="clock-outline"></nb-icon>
138
+
139
+                                        <nb-icon *ngIf="participant.memo != null && participant.memo != ''"
140
+                                            [nbPopover]="template" nbPopoverTrigger="hover"
141
+                                            style="width: 0.75em; height: 0.75em;" icon="message-circle-outline" status="info">
142
+                                        </nb-icon>
98 143
                                         <span *ngIf="participant.rank=='Trial'" style="font-size: 9px;">
99 144
                                             Trial
100 145
                                         </span>
@@ -119,11 +164,27 @@
119 164
                                                 style="text-transform: capitalize;"
120 165
                                                 [routerLink]="'/frontcraft/character/'+participant.charactername">
121 166
                                                 <img style="width:20px; height:20px"
122
-                                                    [src]="'../../../../assets/images/'+participant.race.toLowerCase()+'_xs.gif'" />
167
+                                                    [src]="'/assets/images/'+participant.race.toLowerCase()+'_xs.gif'" />
123 168
                                                 <img style="width:20px; height:20px"
124
-                                                    [src]="'../../../../assets/images/'+participant.class.toLowerCase()+'.png'" />
169
+                                                    [src]="'/assets/images/'+participant.class.toLowerCase()+'.png'" />
125 170
                                                 {{ participant.charactername }}
126 171
                                             </a>
172
+                                            <ng-template #template>
173
+                                                <div style="padding: 10px">
174
+                                                    <p style="white-space: pre-line;">
175
+                                                        {{participant.memo}}
176
+                                                    </p>
177
+                                                    {{participant.timestamp | date : 'HH:mm EEE MMM d'}}
178
+                                                </div>
179
+                                            </ng-template>
180
+                                            <nb-icon *ngIf="participant.memo == null || participant.memo == ''"
181
+                                                [nbPopover]="template" nbPopoverTrigger="hover"
182
+                                                style="width: 0.75em; height: 0.75em;" icon="clock-outline"></nb-icon>
183
+
184
+                                            <nb-icon *ngIf="participant.memo != null && participant.memo != ''"
185
+                                                [nbPopover]="template" nbPopoverTrigger="hover"
186
+                                                style="width: 0.75em; height: 0.75em;" icon="message-circle-outline" status="info">
187
+                                            </nb-icon>
127 188
                                             <span *ngIf="participant.rank=='Trial'" style="font-size: 9px;">
128 189
                                                 Trial
129 190
                                             </span>
@@ -147,7 +208,8 @@
147 208
             <nb-card-body>
148 209
                 <nb-tabset>
149 210
                     <nb-tab tabTitle="Reserves" [active]="reservesShown">
150
-                        <input type="text" nbInput [(ngModel)]="search" (change)="changeSearch()" placeholder="Search" fullWidth="true">
211
+                        <input type="text" nbInput [(ngModel)]="search" (change)="changeSearch()" placeholder="Search"
212
+                            fullWidth="true">
151 213
 
152 214
                         <nb-list class="">
153 215
                             <nb-list-item *ngFor="let item of displayedtokens | keyvalue">
@@ -161,15 +223,13 @@
161 223
                                     <tr>
162 224
                                         <td>
163 225
                                             <div class="row">
164
-                                                <div 
165
-                                                *ngFor="let token of item.value" 
166
-                                                class="col-12 col-md-6 col-xl-4">
226
+                                                <div *ngFor="let token of item.value" class="col-12 col-md-6 col-xl-4">
167 227
                                                     <span
168 228
                                                         [ngStyle]="{'text-decoration': token.rank=='Trial'? 'line-through' : 'none currentcolor solid' }">
169
-                                                        <span style="text-transform: capitalize;">
170
-                                                            [&nbsp;{{token.level}}&nbsp;]&nbsp;
229
+                                                        <span style="text-transform: capitalize; white-space: nowrap;">
230
+                                                            [ {{token.level}} ]&nbsp;
171 231
                                                             <a [routerLink]="'/frontcraft/character/'+token.charactername"
172
-                                                            [ngStyle]="{'color':token.level>=10?'#ff8000':token.level>=8?'#a335ee':token.level>=6?'#0070dd':token.level>=4?'#1eff00':token.level>=2?'#ffffff':'#9d9d9d'}">
232
+                                                                [ngStyle]="{'color':token.level>=10?'#ff8000':token.level>=8?'#a335ee':token.level>=6?'#0070dd':token.level>=4?'#1eff00':token.level>=2?'#ffffff':'#9d9d9d'}">
173 233
                                                                 {{token.charactername}}
174 234
                                                             </a>
175 235
                                                         </span>
@@ -179,13 +239,14 @@
179 239
                                                             Becomes valid when promoted to Raider
180 240
                                                         </div>
181 241
                                                     </ng-template>
182
-                                                    <span *ngIf="token.rank=='Trial'" style="font-size: 9px;" [nbPopover]="tooltip"
183
-                                                        nbPopoverTrigger="hover" nbPopoverPlacement="top">
242
+                                                    <span *ngIf="token.rank=='Trial'" style="font-size: 9px;"
243
+                                                        [nbPopover]="tooltip" nbPopoverTrigger="hover"
244
+                                                        nbPopoverPlacement="top">
184 245
                                                         Trial
185 246
                                                     </span><br />
186 247
                                                 </div>
187 248
                                             </div>
188
-            
249
+
189 250
                                         </td>
190 251
                                     </tr>
191 252
                                 </table>

+ 22
- 34
src/frontend/src/app/frontcraft/pages/raid/raid.component.ts Ver fichero

@@ -1,19 +1,22 @@
1
-import { Component, OnInit, OnDestroy } from '@angular/core';
2
-import { ActivatedRoute, Router, NavigationStart } from '@angular/router';
3
-import { ClientApiService as ClientApiService } from '../../services/client-login-api';
1
+import { Component, OnInit } from '@angular/core';
2
+import { ActivatedRoute, Router } from '@angular/router';
4 3
 import { RaidData, Raid, Signup, Character, Spec, Item, SRToken } from '../../../../../../backend/Types/Types';
5
-import { NbWindowService, NbToastrService, NbDialogService } from '@nebular/theme';
4
+import { NbToastrService, NbDialogService } from '@nebular/theme';
6 5
 import { FrontcraftCharacerpickerComponent } from './characterpicker.component';
7
-import { getClassColor, SpecT } from '../../../../../../backend/Types/PlayerSpecs';
6
+import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
8 7
 import { FrontcraftBuyTokenComponent } from '../shop/buytoken.component';
9 8
 import { allItems } from '../../../../../../backend/Types/Items';
10 9
 import { IApiService } from '../../services/ApiService';
10
+import { UpdatingComponent } from '../../UpdatingComponent';
11
+import { LoggerService } from '../../services/logger.service';
11 12
 
12 13
 @Component({
13 14
   selector: 'raid',
14 15
   templateUrl: './raid.component.html',
15 16
 })
16
-export class FrontcraftRaidComponent implements OnInit, OnDestroy{
17
+export class FrontcraftRaidComponent 
18
+extends UpdatingComponent
19
+implements OnInit{
17 20
 
18 21
     canSignup = false
19 22
     isSignedup = false
@@ -43,41 +46,28 @@ export class FrontcraftRaidComponent implements OnInit, OnDestroy{
43 46
     tokens: {[itemname in string]: (Character & SRToken & Item)[]} = {}
44 47
     displayedtokens = {}
45 48
     search = ""
46
-    uuid
47 49
 
48 50
     constructor(
49 51
       private api: IApiService,
50 52
       private route: ActivatedRoute,
51 53
       private router: Router,
52 54
       private dialogService : NbDialogService,
53
-      private toast: NbToastrService
55
+      private toast: NbToastrService,
56
+      logger: LoggerService
54 57
     ){
55
-      router.events.subscribe(event => {
56
-        if (event instanceof NavigationStart) {
57
-          this.ngOnDestroy()
58
-        }
59
-      })
60
-    }
61
-
62
-    ngOnDestroy = () => {
63
-      if(this.uuid)
64
-        this.api.get('PubSub').unsubscribe(this.uuid)
58
+      super(router, api, logger)
65 59
     }
66 60
 
67
-    async ngOnInit(){
68
-      
61
+    ngOnInit(){
69 62
       this.manageRaid = this.api.get('manageRaid')
70
-      
71 63
       const signupFeature = this.api.get('signup')
64
+      
72 65
       if(signupFeature){
73 66
         this.canSignup = true
74 67
       }
75
-      await this.refresh()
76
-
77
-      const res = await this.api.get('PubSub').subscribe(""+this.raid.id!, (data: RaidData) => {
78
-        this.display(data)
68
+      this.refresh().then(() => {
69
+        this.subscribe(String(this.raid.id), (data: RaidData) => this.display(data))
79 70
       })
80
-      this.uuid = res.uuid
81 71
     }
82 72
 
83 73
     itemSelect = async(item) => {
@@ -143,7 +133,7 @@ export class FrontcraftRaidComponent implements OnInit, OnDestroy{
143 133
       await signup.sign(auth.token.value, {
144 134
         ...this.mySignup,
145 135
         id: this.mySignup.characterid,
146
-      }, this.raid, value)
136
+      }, this.raid, value, this.mySignup.memo)
147 137
       this.toast.show('Signup', 'Success', { status: 'success' })
148 138
     }
149 139
 
@@ -163,9 +153,7 @@ export class FrontcraftRaidComponent implements OnInit, OnDestroy{
163 153
       const raiddata = await raidManager.getRaidData(<any>{
164 154
         id: param
165 155
       })
166
-      
167 156
       this.display(raiddata)
168
-      
169 157
     }
170 158
 
171 159
     display =  async (raiddata:RaidData)  => {
@@ -179,15 +167,17 @@ export class FrontcraftRaidComponent implements OnInit, OnDestroy{
179 167
       })
180 168
 
181 169
       const user = this.api.getCurrentUser()
182
-      const matchingSignup = Object.values(raiddata.participants).flat().find(char => user && char.userid === user.id!)
170
+      const matchingSignup = Object.values(raiddata.participants).flat().find(char => user && char.userid === user.id!)     
171
+      
183 172
       if(matchingSignup){       
184
-        this.isSignedup = true
185 173
         this.mySignup = matchingSignup
174
+        this.isSignedup = true        
186 175
         this.mySignup['status'] = matchingSignup['benched']?'Bench':matchingSignup['late']?'Late':'Attending'
187 176
       }else{
188 177
         this.isSignedup = false
189 178
         this.mySignup = null
190 179
       }
180
+
191 181
       this.changeSearch()
192 182
     }
193 183
 
@@ -202,9 +192,7 @@ export class FrontcraftRaidComponent implements OnInit, OnDestroy{
202 192
           })
203 193
           if(filteredTokens.length > 0)
204 194
             this.displayedtokens[e[0]] = filteredTokens 
205
-        })
206
-        console.log(this.displayedtokens);
207
-        
195
+        })        
208 196
       }
209 197
     }
210 198
 

+ 2
- 3
src/frontend/src/app/frontcraft/pages/raids/createraid.compontent.ts Ver fichero

@@ -1,7 +1,6 @@
1 1
 import { Component, OnInit } from '@angular/core';
2
-import { ClientApiService } from '../../services/client-login-api';
3 2
 import { Raid, RaidData } from '../../../../../../backend/Types/Types';
4
-import { NbWindowRef, NbDialogRef } from '@nebular/theme';
3
+import { NbDialogRef } from '@nebular/theme';
5 4
 import { Tiers, _Tiers } from '../../../../../../backend/Types/Items';
6 5
 import { IApiService } from '../../services/ApiService';
7 6
 
@@ -31,7 +30,7 @@ export class FrontcraftCreateRaidsComponent implements OnInit {
31 30
     private api: IApiService
32 31
   ) {}
33 32
 
34
-  loadNext(cardData) {
33
+  loadNext() {
35 34
   }
36 35
 
37 36
   onTierSelect(){

+ 53
- 47
src/frontend/src/app/frontcraft/pages/raids/raids.component.html Ver fichero

@@ -1,64 +1,70 @@
1 1
 <nb-card class="col-12 col-xl-9">
2 2
   <nb-card-header>
3 3
     Upcoming raids
4
-    <nb-icon 
5
-      style="color:orange"
6
-      *ngIf="manageRaid"
7
-      (click)="create()"
8
-      icon="plus-square-outline"></nb-icon>
4
+    <nb-icon style="color:orange" *ngIf="manageRaid" (click)="create()" icon="plus-square-outline"></nb-icon>
9 5
   </nb-card-header>
10
-  <nb-list
11
-    nbInfiniteList
12
-    listenWindowScroll
13
-    [threshold]="500">
14
-    <nb-list-item *ngFor="let raid of raids" 
15
-    [routerLink]="'/frontcraft/raid/'+raid.id" 
16
-    class="raidlist"
17
-    style="cursor: pointer;">
18
-      <div class="row">
19
-        <img [src]="'../../../../assets/images/'+(raid.tier || 'null').toLowerCase()+'.png'" 
20
-        style="object-fit: contain"
21
-        class="col-1 col-s-3" />
22
-
23
-        <div class="col-11 col-s-9" >
24
-          <div class="row">
25
-            <div class="col-12" style="padding-top: 5px">
6
+  <nb-list nbInfiniteList listenWindowScroll [threshold]="500">
7
+    <nb-list-item *ngFor="let raid of raids" class="raidlist">
8
+      <a [routerLink]="'/frontcraft/raid/'+raid.id">
9
+        <div class="row">
10
+          <table>
11
+            <tr>
12
+              <td rowspan="2" style="padding-right: 20px;">
13
+                <img [src]="'/assets/images/'+(raid.tier || 'null').toLowerCase()+'.png'"
14
+                  style="max-width: 50px; object-fit: contain" />
15
+              </td>
26 16
               <h4>
27 17
                 {{raid.title}}
28 18
               </h4>
29
-            </div>
30
-          </div>
31
-          <div class="row" style="padding-top: 5px; padding-bottom: 5px; color:darkgray">
32
-            <div class="col-6 col-md-3">
33
-              <nb-icon icon="checkmark-circle"></nb-icon> {{raid.signupcount}} / {{raid.size}}<br>
34
-            </div>
35
-    
36
-            <div class="col-6 col-md-3">
37
-              <nb-icon icon="clock-outline"></nb-icon> {{raid.start | date : 'HH:mm'}}
38
-            </div>
39
-    
40
-            <div class="col-12 col-md-6">
41
-              <nb-icon icon="calendar-outline"></nb-icon> {{raid.start | date : 'EEE MMM d'}}
42
-            </div>
43
-          </div>
19
+            </tr>
20
+            <tr>
21
+              <td style="padding-right: 25px; white-space: nowrap; color: lightslategray;">
22
+                <nb-icon icon="checkmark-circle"></nb-icon>&nbsp;{{raid.signupcount}}&nbsp;/&nbsp;{{raid.size}}<br>
23
+              </td>
24
+              <td style="padding-right: 25px; white-space: nowrap; color: lightslategray;">
25
+                <nb-icon icon="clock-outline"></nb-icon>&nbsp;{{raid.start | date : 'HH:mm'}}
26
+              </td>
27
+              <td style="padding-right: 25px; white-space: nowrap; color: lightslategray;">
28
+                <nb-icon icon="calendar-outline"></nb-icon>&nbsp;{{raid.start | date : 'EEE MMM d'}}
29
+              </td>
30
+            </tr>
31
+          </table>
44 32
         </div>
45
-      </div>
33
+      </a>
46 34
     </nb-list-item>
47 35
   </nb-list>
48 36
 </nb-card>
49 37
 
50 38
 <nb-card class="col-12 col-xl-9">
51 39
   <nb-card-header>Previous raids</nb-card-header>
52
-  <nb-list
53
-    nbInfiniteList
54
-    listenWindowScroll
55
-    [threshold]="500">
40
+  <nb-list nbInfiniteList listenWindowScroll [threshold]="500">
56 41
     <nb-list-item *ngFor="let raid of oldraids" [routerLink]="'/frontcraft/archive/'+raid.id">
57
-      <b>{{raid.title}}</b><br>
58
-      {{raid.signupcount}} / {{raid.size}}<br>
59
-      {{raid.start | date : 'EEEE d MMMM @ HH:mm'}}<br>
60
-      {{raid.description}}<br>
42
+      <a [routerLink]="'/frontcraft/archive/'+raid.id">
43
+        <div class="row">
44
+          <table>
45
+            <tr>
46
+              <td rowspan="2" style="padding-right: 20px;">
47
+                <img [src]="'/assets/images/'+(raid.tier || 'null').toLowerCase()+'.png'"
48
+                  style="max-width: 50px;;object-fit: contain; filter: grayscale(75%)" />
49
+              </td>
50
+              <h4>
51
+                {{raid.title}}
52
+              </h4>
53
+            </tr>
54
+            <tr>
55
+              <td style="padding-right: 25px; white-space: nowrap; color: lightslategray;">
56
+                <nb-icon icon="checkmark-circle"></nb-icon>&nbsp;{{raid.signupcount}}&nbsp;/&nbsp;{{raid.size}}<br>
57
+              </td>
58
+              <td style="padding-right: 25px; white-space: nowrap; color: lightslategray;">
59
+                <nb-icon icon="clock-outline"></nb-icon>&nbsp;{{raid.start | date : 'HH:mm'}}
60
+              </td>
61
+              <td style="padding-right: 25px; white-space: nowrap; color: lightslategray;">
62
+                <nb-icon icon="calendar-outline"></nb-icon>&nbsp;{{raid.start | date : 'EEE MMM d'}}
63
+              </td>
64
+            </tr>
65
+          </table>
66
+        </div>
67
+      </a>
61 68
     </nb-list-item>
62 69
   </nb-list>
63
-</nb-card>
64
-  
70
+</nb-card>

+ 21
- 31
src/frontend/src/app/frontcraft/pages/raids/raids.component.ts Ver fichero

@@ -1,69 +1,59 @@
1 1
 import { Component, OnInit, OnDestroy } from '@angular/core';
2
-import { ClientApiService } from '../../services/client-login-api';
3
-import { NbWindowService, NbDialogService } from '@nebular/theme';
2
+import { NbDialogService } from '@nebular/theme';
4 3
 import { FrontcraftCreateRaidsComponent } from './createraid.compontent';
5 4
 import { Router, NavigationStart } from '@angular/router';
6 5
 import { IApiService } from '../../services/ApiService';
6
+import { UpdatingComponent } from '../../UpdatingComponent';
7
+import { LoggerService } from '../../services/logger.service';
7 8
 
8 9
 @Component({
9 10
   selector: 'raids',
10 11
   templateUrl: 'raids.component.html',
11 12
   styleUrls: ['raids.component.scss'],
12 13
 })
13
-export class FrontcraftRaidsComponent implements OnInit, OnDestroy{
14
+export class FrontcraftRaidsComponent 
15
+extends UpdatingComponent
16
+implements OnInit {
14 17
 
15 18
 
16 19
   manageRaid
17 20
   raids = []
18 21
   oldraids = []
19 22
   pageSize = 10;
20
-  uuid
21 23
 
22 24
   constructor(
23 25
     private api: IApiService,
24
-    private router: Router,
25
-    private dialogService: NbDialogService
26
+    router: Router,
27
+    private dialogService: NbDialogService,
28
+    logger: LoggerService
26 29
   ) {
27
-    this.manageRaid = this.api.get('manageRaid')
28
-    router.events.subscribe(event => {
29
-      if (event instanceof NavigationStart) {
30
-        this.ngOnDestroy()
31
-      }
32
-    })
30
+    super(router, api, logger)
33 31
   }
34 32
 
35
-  ngOnDestroy = () => {
36
-    if(this.uuid)
37
-      this.api.get('PubSub').unsubscribe(this.uuid)
33
+  ngOnDestroy(){
34
+    super.ngOnDestroy()
38 35
   }
39 36
 
40 37
   async ngOnInit() {
41
-    const res = await this.api.get('PubSub').subscribe("raids", () => {
42
-      this.refresh()
43
-    })
44
-    this.uuid = res.uuid
38
+    this.subscribe("raids", () => this.refresh())
39
+
40
+    this.manageRaid = this.api.get('manageRaid')
45 41
     this.refresh()
46 42
   }
47 43
 
48
-  refresh() {
49
-    this.api.get('RaidManager').getRaids().then(raids => {
50
-      this.raids = raids
51
-    })
52
-
44
+  async refresh() {
45
+    this.raids = await this.api.get('RaidManager').getRaids()
53 46
     const raidManager = this.api.get('RaidManager')
54
-    raidManager.getPastRaids(10).then(raiddata => {
55
-      this.oldraids = raiddata
56
-    })
47
+    this.oldraids = await raidManager.getPastRaids(10)
57 48
   }
58 49
 
59
-  create(){
60
-    this.dialogService.open(FrontcraftCreateRaidsComponent, { 
50
+  create() {
51
+    this.dialogService.open(FrontcraftCreateRaidsComponent, {
61 52
       closeOnBackdropClick: true,
62 53
       closeOnEsc: true,
63 54
       context: {
64 55
         templates: this.oldraids
65
-      } 
56
+      }
66 57
     })
67
-
68 58
   }
69 59
 }

+ 3
- 5
src/frontend/src/app/frontcraft/pages/shop/buytoken.component.ts Ver fichero

@@ -1,10 +1,8 @@
1
-import { Component, OnInit, ContentChild, AfterContentInit, ViewChild, AfterViewInit, Input, Output, EventEmitter } from '@angular/core';
2
-import { ClientApiService as ClientApiService } from '../../services/client-login-api';
3
-import { FrontcraftItemSelectComponent } from './itemselector.component';
4
-import { NbWindowService, NbWindowRef, NbToastrService, NbDialogService, NbDialogRef } from '@nebular/theme';
1
+import { Component, OnInit, Input } from '@angular/core';
2
+import { NbToastrService, NbDialogRef } from '@nebular/theme';
5 3
 import { Item, Character, SRToken, Signup } from '../../../../../../backend/Types/Types';
6 4
 import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
7
-import { _Tiers, allItems, Tiers } from '../../../../../../backend/Types/Items';
5
+import { _Tiers, Tiers } from '../../../../../../backend/Types/Items';
8 6
 import { IApiService } from '../../services/ApiService';
9 7
 
10 8
 @Component({

+ 10
- 2
src/frontend/src/app/frontcraft/pages/shop/itemselector.component.ts Ver fichero

@@ -24,8 +24,16 @@ export class FrontcraftItemSelectComponent implements OnInit{
24 24
 
25 25
     async ngOnInit(){
26 26
         
27
-        Promise.all(this.items.map(itemname => 
28
-            this.api.get('ItemManager').getItem(itemname)
27
+        
28
+        
29
+
30
+        Promise.all(this.items.map(async itemname => {
31
+            try{
32
+                return await this.api.get('ItemManager').getItem(itemname)
33
+            }catch(e){
34
+                console.log(itemname);
35
+            }
36
+        }
29 37
         )).then(items => {
30 38
             this.allItems = items
31 39
             this.displayedItems = this.allItems

+ 0
- 2
src/frontend/src/app/frontcraft/pages/shop/shop.component.ts Ver fichero

@@ -1,6 +1,4 @@
1 1
 import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
2
-import { ClientApiService as ClientApiService } from '../../services/client-login-api';
3
-import { NbDialogService } from '@nebular/theme';
4 2
 import { Item, Character, Signup } from '../../../../../../backend/Types/Types';
5 3
 import { _Tiers, allItems } from '../../../../../../backend/Types/Items';
6 4
 

+ 1
- 1
src/frontend/src/app/frontcraft/pages/user/user.component.html Ver fichero

@@ -57,7 +57,7 @@ accent="info">
57 57
         </form>
58 58
         <br />
59 59
 
60
-        <h3>Avaiable Reserves</h3>
60
+        <h3>Available Reserves</h3>
61 61
         {{user.MC}} MC |
62 62
         {{user.BWL}} BWL |
63 63
         {{user.ZG}} ZG |

+ 0
- 2
src/frontend/src/app/frontcraft/permissions/changePermissions/changePermissions.component.ts Ver fichero

@@ -1,6 +1,4 @@
1 1
 import { Component, OnInit } from '@angular/core';
2
-import { ClientApiService as ClientApiService } from '../../services/client-login-api';
3
-import { Router } from '@angular/router';
4 2
 import { _Rank, _Class, _Race, RPCPermission  } from '../../../../../../backend/Types/Types'
5 3
 import { NbToastrService } from '@nebular/theme';
6 4
 import { IApiService } from '../../services/ApiService';

+ 0
- 1
src/frontend/src/app/frontcraft/permissions/permissions-layout.component.ts Ver fichero

@@ -1,5 +1,4 @@
1 1
 import { Component, OnInit } from '@angular/core';
2
-import { ClientApiService } from '../services/client-login-api';
3 2
 import { Router } from '@angular/router';
4 3
 
5 4
 @Component({

+ 13
- 6
src/frontend/src/app/frontcraft/services/ApiService.ts Ver fichero

@@ -1,23 +1,30 @@
1 1
 import { Auth, FrontcraftIfc, FrontcraftFeatureIfc, User, SomeOf } from '../../../../../backend/Types/Types';
2 2
 import { saltedHash } from '../../../../../backend/Util/hash';
3
-import { RPCSocket } from 'rpclibrary';
3
+import { RPCSocket, ConnectedSocket } from 'rpclibrary';
4 4
 
5 5
 export class IApiService{
6
-    getUnprivilegedSocket: () => RPCSocket & FrontcraftIfc
6
+    getUnprivilegedSocket: () => ConnectedSocket<FrontcraftIfc>
7 7
     getAuth: () => Auth | undefined
8 8
     checkLogin: () => Promise<boolean>
9 9
     initialize: () => Promise<any>
10
-    getCurrentUser: () => User | undefined
10
+    getCurrentUser: () => User
11 11
     login: (username: string, password: string) => Promise<RPCSocket & SomeOf<FrontcraftFeatureIfc>>
12 12
     connectShoutbox: (callback:Function) => Promise<Function>
13 13
     kick: () => Promise<void>
14 14
     logout: () => Promise<void>
15
-    get: <K extends (keyof FrontcraftIfc | keyof FrontcraftFeatureIfc)>(feature : K) => K extends keyof FrontcraftIfc?FrontcraftIfc[K]:
16
-                                                                                        K extends keyof FrontcraftFeatureIfc?(FrontcraftFeatureIfc[K] | void): 
17
-                                                                                        never
15
+    get: <K extends (keyof FrontcraftIfc | keyof FrontcraftFeatureIfc)>(feature : K) => K extends keyof FrontcraftIfc
16
+                                                                                      ? FrontcraftIfc[K]
17
+                                                                                      : K extends keyof FrontcraftFeatureIfc
18
+                                                                                      ? (FrontcraftFeatureIfc[K] | void)
19
+                                                                                      : never
18 20
 }
19 21
 
20 22
 export async function hash(value:string) : Promise<string>{
21 23
     return saltedHash(value, "")
22 24
 }
23 25
 
26
+export const GuestUser: User = {
27
+    username: 'Guest',
28
+    pwhash: '',
29
+    rank: 'Guest'
30
+}

+ 21
- 16
src/frontend/src/app/frontcraft/services/client-login-api.ts Ver fichero

@@ -1,24 +1,28 @@
1 1
 import { Injectable } from "@angular/core";
2
-import {RPCSocket} from 'rpclibrary/js/src/Frontend'
2
+import { RPCSocket } from 'rpclibrary/js/src/Frontend'
3
+import { ConnectedSocket } from "rpclibrary"
3 4
 import { Auth, User, _Class, FrontcraftFeatureIfc, SomeOf, FrontcraftIfc, } from '../../../../../backend/Types/Types'
4 5
 import { ShoutMessage } from '../../../../../backend/Components/Shoutbox/Interface';
5
-import { hash, IApiService } from './ApiService';
6
+import { hash, IApiService, GuestUser } from './ApiService';
7
+import { LoggerService } from './logger.service';
6 8
 
7 9
 declare const Cookies
8 10
 
9 11
 @Injectable()
10 12
 export class ClientApiService implements IApiService{
11
-    private socket:RPCSocket & FrontcraftIfc;
13
+    private socket:ConnectedSocket<FrontcraftIfc>
12 14
     private auth:Auth
13
-    private privSocket: RPCSocket & SomeOf<FrontcraftFeatureIfc>
15
+    private privSocket: RPCSocket<SomeOf<FrontcraftFeatureIfc>>
14 16
 
15
-    constructor(){
17
+    constructor(
18
+        private logger: LoggerService
19
+    ){
16 20
         window['s'] = this
17 21
     }
18 22
 
19
-    getUnprivilegedSocket = () : RPCSocket & FrontcraftIfc => this.socket
23
+    getUnprivilegedSocket = () : ConnectedSocket<FrontcraftIfc> => this.socket
20 24
 
21
-    private getPrivilegedSocket = async (auth:Auth) : Promise<RPCSocket & SomeOf<FrontcraftFeatureIfc>> => {
25
+    private getPrivilegedSocket = async (auth:Auth) : Promise<RPCSocket<SomeOf<FrontcraftFeatureIfc>>> => {
22 26
         if(this.privSocket) {
23 27
             return this.privSocket
24 28
         }
@@ -38,17 +42,17 @@ export class ClientApiService implements IApiService{
38 42
             sock.hook('getUserData', () => auth)
39 43
 
40 44
             sock.on('close', async () => {
41
-                console.log("priv#close");
45
+                this.logger.log("priv#close");
42 46
                 
43 47
                 //handled via unprivileged socket
44 48
             })
45 49
 
46 50
             sock.on('error', async (e) => {
47
-                console.log("priv#error", e);
51
+                this.logger.log("priv#error", e);
48 52
 
49 53
                 //handled via unprivileged socket
50 54
             })
51
-            const authSock = await sock.connect<RPCSocket & SomeOf<FrontcraftFeatureIfc>>(auth.token.value)
55
+            const authSock = await sock.connect(auth.token.value)
52 56
             
53 57
             this.auth = auth
54 58
             this.privSocket = authSock
@@ -74,8 +78,8 @@ export class ClientApiService implements IApiService{
74 78
         } 
75 79
     }
76 80
 
77
-    getCurrentUser = () : User | undefined => {
78
-        return this.auth?this.auth.user:undefined
81
+    getCurrentUser = () : User => {
82
+        return this.auth?this.auth.user:GuestUser
79 83
     }
80 84
 
81 85
     login = async (username: string, password: string) : Promise<RPCSocket & SomeOf<FrontcraftFeatureIfc>> => {
@@ -102,8 +106,8 @@ export class ClientApiService implements IApiService{
102 106
     }
103 107
 
104 108
     async connectShoutbox(callback:Function) : Promise<Function>{
105
-        const res = await this.get('Shoutbox').subscribe(callback)
106
-        return async (msg: ShoutMessage) => await this.get('Shoutbox').shout(res.uuid, msg)
109
+        const uuid = await this.get('Shoutbox').subscribe(callback)
110
+        return async (msg: ShoutMessage) => await this.get('Shoutbox').shout(uuid, msg)
107 111
     }
108 112
 
109 113
     kick = async () => {
@@ -113,6 +117,7 @@ export class ClientApiService implements IApiService{
113 117
 
114 118
     logout = async () => {
115 119
         Cookies.remove('token')
120
+        if(this.privSocket) this.privSocket.unhook('kick')
116 121
         if(this.auth){
117 122
             try{
118 123
                 await this.socket.UserManager.logout(this.auth.user.username, this.auth.token.value)
@@ -133,11 +138,11 @@ export class ClientApiService implements IApiService{
133 138
         }
134 139
 
135 140
         try{
136
-            let conn = new RPCSocket(20000, window.location.hostname)
141
+            let conn = new RPCSocket<FrontcraftIfc>(20000, window.location.hostname)
137 142
             conn.on('close', async () => {
138 143
             })                        
139 144
 
140
-            this.socket = await conn.connect<FrontcraftIfc>()
145
+            this.socket = await conn.connect()
141 146
         }catch(e){
142 147
             alert('Unable to connect. The server appears to be down.\nPress OK to refresh the page')
143 148
             location.reload()

+ 37
- 0
src/frontend/src/app/frontcraft/services/logger.service.ts Ver fichero

@@ -0,0 +1,37 @@
1
+import { Injectable } from "@angular/core";
2
+import { environment } from '../../../environments/environment';
3
+
4
+interface ILoggerService{
5
+    log,
6
+    warn,
7
+    error,
8
+    table,
9
+    collapsed
10
+}
11
+
12
+@Injectable()
13
+export class LoggerService implements ILoggerService {
14
+
15
+    constructor(
16
+        private logger = console
17
+    ) { }
18
+
19
+    log = (...args) => { this.LOG('log', args) }
20
+    warn = (...args) => { this.LOG('warn', args) }
21
+    error = (...args) => { this.LOG('error', args) }
22
+    table = (...args) => { this.LOG('table', args) }
23
+    collapsed = (groupname: string, type: keyof ILoggerService, ...args) => {
24
+        if(type === "collapsed")
25
+            return this.log(args)
26
+            
27
+        console.groupCollapsed(groupname)
28
+        this[type as any].apply(this.logger, args)
29
+        console.groupEnd() 
30
+    }
31
+
32
+    private LOG(type, ...args) {
33
+        if (!environment.production) {
34
+            this.logger[type].apply(this.logger, ...args)
35
+        }
36
+    }
37
+}

+ 16
- 12
src/frontend/src/app/frontcraft/services/server-login-api.ts Ver fichero

@@ -1,19 +1,23 @@
1 1
 import { Injectable } from "@angular/core";
2 2
 import {RPCSocket} from 'rpclibrary/js/src/Frontend'
3 3
 import { Auth, User, _Class, FrontcraftFeatureIfc, SomeOf, FrontcraftIfc, } from '../../../../../backend/Types/Types'
4
-import { hash, IApiService } from './ApiService';
4
+import { hash, IApiService, GuestUser } from './ApiService';
5
+import { LoggerService } from './logger.service';
6
+import { ConnectedSocket } from 'rpclibrary';
5 7
 
6 8
 declare const Cookies
7 9
 
8 10
 @Injectable()
9 11
 export class ServerApiService implements IApiService{
10
-    private socket:RPCSocket & FrontcraftIfc;
12
+    private socket:ConnectedSocket<FrontcraftIfc>
11 13
     private auth:Auth
12 14
     private privSocket: RPCSocket & SomeOf<FrontcraftFeatureIfc>
13 15
 
14
-    constructor(){}
16
+    constructor(
17
+        private logger: LoggerService
18
+    ){}
15 19
 
16
-    getUnprivilegedSocket = () : RPCSocket & FrontcraftIfc => this.socket
20
+    getUnprivilegedSocket = () : ConnectedSocket<FrontcraftIfc> => this.socket
17 21
 
18 22
     get = <K extends (keyof FrontcraftIfc | keyof FrontcraftFeatureIfc)>(feature : K) : K extends keyof FrontcraftIfc?FrontcraftIfc[K]:
19 23
                                                                                         K extends keyof FrontcraftFeatureIfc?(FrontcraftFeatureIfc[K] | void): 
@@ -22,8 +26,8 @@ export class ServerApiService implements IApiService{
22 26
         return this.socket[feature]
23 27
     }
24 28
 
25
-    getCurrentUser = () : User | undefined => {
26
-        return this.auth?this.auth.user:undefined
29
+    getCurrentUser = () : User => {
30
+        return GuestUser
27 31
     }
28 32
 
29 33
     login = async (username: string, password: string) : Promise<RPCSocket & SomeOf<FrontcraftFeatureIfc>> => {
@@ -42,13 +46,13 @@ export class ServerApiService implements IApiService{
42 46
 
43 47
         //attach error handler now so failed logins dont trigger reloads
44 48
         this.socket.on('error', async (err) => {
45
-            console.log(err);
49
+            this.logger.log(err);
46 50
         })
47 51
 
48 52
     }
49 53
 
50 54
     async connectShoutbox(callback:Function) : Promise<Function>{
51
-        return console.log
55
+        return this.logger.log
52 56
     }
53 57
 
54 58
     kick = async () => {
@@ -60,7 +64,7 @@ export class ServerApiService implements IApiService{
60 64
             try{
61 65
                 await this.socket.UserManager.logout(this.auth.user.username, this.auth.token.value)
62 66
             }catch(e){
63
-                console.warn(e);
67
+                this.logger.warn(e);
64 68
             }
65 69
         } 
66 70
 
@@ -76,13 +80,13 @@ export class ServerApiService implements IApiService{
76 80
         }
77 81
 
78 82
         try{
79
-            let conn = new RPCSocket(20000, window.location.hostname)
83
+            let conn = new RPCSocket<FrontcraftIfc>(20000, window.location.hostname)
80 84
             conn.on('close', async () => {
81 85
             })                        
82 86
 
83
-            this.socket = await conn.connect<FrontcraftIfc>()
87
+            this.socket = await conn.connect()
84 88
         }catch(e){
85
-            console.log(e);
89
+            this.logger.log(e);
86 90
             throw new Error("Websocket cannot connect")
87 91
         }
88 92
     }

+ 1
- 1
src/frontend/src/main.server.ts Ver fichero

@@ -6,4 +6,4 @@ export { AppServerModule } from './app/app.server.module';
6 6
 import { IApiService } from './app/frontcraft/services/ApiService';
7 7
 export { IApiService }
8 8
 export { ServerApiService } from './app/frontcraft/services/server-login-api';
9
-
9
+export { LoggerService } from './app/frontcraft/services/logger.service'

+ 7
- 2
src/frontend/src/main.ts Ver fichero

@@ -10,18 +10,23 @@ import { FrontcraftAppModule } from './app/app.module';
10 10
 import { environment } from './environments/environment';
11 11
 import { IApiService } from "./app/frontcraft/services/ApiService"
12 12
 import { ClientApiService } from './app/frontcraft/services/client-login-api';
13
+import { LoggerService } from './app/frontcraft/services/logger.service';
13 14
 
14 15
 if (environment.production) {
15 16
   enableProdMode();
16 17
 }
17
-
18
-const serviceObj = new ClientApiService()
18
+const loggerService = new LoggerService()
19
+const serviceObj = new ClientApiService(loggerService)
19 20
 serviceObj.initialize().then(_ => {
20 21
   platformBrowserDynamic([
21 22
     {
22 23
       provide: IApiService,
23 24
       deps: [],
24 25
       useValue: serviceObj
26
+    },{
27
+      provide: LoggerService,
28
+      deps: [],
29
+      useValue: loggerService
25 30
     }
26 31
   ]).bootstrapModule(FrontcraftAppModule)
27 32
     .catch(err => console.error(err));

+ 1
- 0
src/frontend/tsconfig.app.json Ver fichero

@@ -1,6 +1,7 @@
1 1
 {
2 2
   "extends": "./tsconfig.json",
3 3
   "compilerOptions": {
4
+    "strict": false,
4 5
     "outDir": "./out-tsc/app",
5 6
     "paths": {
6 7
       "@angular/*": [

+ 7
- 7
test/backendTest.ts Ver fichero

@@ -1,8 +1,8 @@
1 1
 import { Injector } from "../src/backend/Injector/Injector";
2 2
 import { FrontworkAdmin } from "../src/backend/Admin/Admin";
3
-import { T1, T2, Tiers } from "../src/backend/Types/Items";
3
+import { T2, Tiers } from "../src/backend/Types/Items";
4 4
 
5
-import { RPCSocket } from "rpclibrary";
5
+import { RPCSocket, ConnectedSocket } from "rpclibrary";
6 6
 import { FrontcraftIfc, Auth, User, FrontcraftFeatureIfc, Raid, Character, Rank, Class, Race, Spec, Signup } from "../src/backend/Types/Types";
7 7
 import { SpecT } from "../src/backend/Types/PlayerSpecs";
8 8
 
@@ -120,8 +120,8 @@ describe('Frontcraft', () => {
120 120
     let auth: Auth,
121 121
         adminUser: User,
122 122
         server: FrontworkAdmin,
123
-        client: RPCSocket & FrontcraftIfc,
124
-        adminClient: RPCSocket & FrontcraftFeatureIfc,
123
+        client: ConnectedSocket<FrontcraftIfc>,
124
+        adminClient: ConnectedSocket<FrontcraftFeatureIfc>,
125 125
         raids: Raid[] = [],
126 126
         users: { [username in string]: { account: User, character: Character, auth: Auth, signup?: Signup, item?: string } } = {}
127 127
 
@@ -168,12 +168,12 @@ describe('Frontcraft', () => {
168 168
                 }).then(adminUser => {
169 169
 
170 170
                     client.UserManager.login(adminUser.username, 'ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb').then(auth => {
171
-                        const sock = new RPCSocket(
171
+                        const sock = new RPCSocket<FrontcraftFeatureIfc>(
172 172
                             auth.port,
173 173
                             "localhost"
174 174
                         )
175 175
 
176
-                        sock.connect<any>(auth.token.value).then(cli => {
176
+                        sock.connect(auth.token.value).then(cli => {
177 177
                             adminClient = cli
178 178
                             sock.hook('kick', () => {
179 179
                                 console.log("I got kicked");
@@ -240,7 +240,7 @@ describe('Frontcraft', () => {
240 240
 
241 241
     it('should sign up', (done) => {
242 242
         Promise.all(Object.values(users).map((user) =>
243
-            adminClient.signup.sign(user.auth.token.value, user.character, raids[0], false).catch(done)
243
+            adminClient.signup.sign(user.auth.token.value, user.character, raids[0], false, ""+Math.floor(Math.random()*10000)).catch(done)
244 244
         )).then(x => {
245 245
             adminClient.signup.getSignups(raids[0]).then(s => {
246 246
                 if (s.length == testAccounts.length) {

Loading…
Cancelar
Guardar