peter 5 anni fa
parent
commit
9ff98d92ae
62 ha cambiato i file con 711 aggiunte e 483 eliminazioni
  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 Vedi File


BIN
live_db/frontworkAdmin.sqlite Vedi File


+ 53
- 35
package-lock.json Vedi File

479
     "bluebird": {
479
     "bluebird": {
480
       "version": "3.5.5",
480
       "version": "3.5.5",
481
       "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.5.tgz",
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
     "body-parser": {
485
     "body-parser": {
485
       "version": "1.19.0",
486
       "version": "1.19.0",
835
       "dev": true
836
       "dev": true
836
     },
837
     },
837
     "colorette": {
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
     "combined-stream": {
843
     "combined-stream": {
843
       "version": "1.0.8",
844
       "version": "1.0.8",
850
     "commander": {
851
     "commander": {
851
       "version": "2.20.0",
852
       "version": "2.20.0",
852
       "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz",
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
     "commondir": {
857
     "commondir": {
856
       "version": "1.0.1",
858
       "version": "1.0.1",
2057
       "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg="
2059
       "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg="
2058
     },
2060
     },
2059
     "getopts": {
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
     "getpass": {
2066
     "getpass": {
2065
       "version": "0.1.7",
2067
       "version": "0.1.7",
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
     "global-prefix": {
2154
     "global-prefix": {
2143
       "version": "1.0.2",
2155
       "version": "1.0.2",
2144
       "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz",
2156
       "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz",
2731
       "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA=="
2743
       "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA=="
2732
     },
2744
     },
2733
     "knex": {
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
       "requires": {
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
         "debug": "4.1.1",
2753
         "debug": "4.1.1",
2742
-        "getopts": "2.2.4",
2754
+        "getopts": "2.2.5",
2743
         "inherits": "~2.0.4",
2755
         "inherits": "~2.0.4",
2744
         "interpret": "^1.2.0",
2756
         "interpret": "^1.2.0",
2745
         "liftoff": "3.1.0",
2757
         "liftoff": "3.1.0",
2746
         "lodash": "^4.17.15",
2758
         "lodash": "^4.17.15",
2747
         "mkdirp": "^0.5.1",
2759
         "mkdirp": "^0.5.1",
2748
-        "pg-connection-string": "2.0.0",
2760
+        "pg-connection-string": "2.1.0",
2749
         "tarn": "^2.0.0",
2761
         "tarn": "^2.0.0",
2750
         "tildify": "2.0.0",
2762
         "tildify": "2.0.0",
2751
-        "uuid": "^3.3.2",
2763
+        "uuid": "^3.3.3",
2752
         "v8flags": "^3.1.3"
2764
         "v8flags": "^3.1.3"
2753
       },
2765
       },
2754
       "dependencies": {
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
         "inherits": {
2777
         "inherits": {
2756
           "version": "2.0.4",
2778
           "version": "2.0.4",
2757
           "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
2779
           "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
3948
       "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
3970
       "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
3949
     },
3971
     },
3950
     "pg-connection-string": {
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
     "picomatch": {
3977
     "picomatch": {
3956
       "version": "2.2.1",
3978
       "version": "2.2.1",
4340
       "requires": {
4362
       "requires": {
4341
         "expand-tilde": "^2.0.0",
4363
         "expand-tilde": "^2.0.0",
4342
         "global-modules": "^1.0.0"
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
     "resolve-url": {
4367
     "resolve-url": {
4388
       }
4398
       }
4389
     },
4399
     },
4390
     "rpclibrary": {
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
       "requires": {
4404
       "requires": {
4395
         "bsock": "^0.1.9",
4405
         "bsock": "^0.1.9",
4406
+        "crypto-js": "^4.0.0",
4396
         "http": "0.0.0",
4407
         "http": "0.0.0",
4397
         "uuid": "^3.3.3"
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
     "run-queue": {
4418
     "run-queue": {

+ 3
- 2
package.json Vedi File

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

+ 71
- 62
src/backend/Admin/Admin.ts Vedi File

4
 import { promises as fs, mkdirSync } from "fs"
4
 import { promises as fs, mkdirSync } from "fs"
5
 import { RPCServer } from 'rpclibrary'
5
 import { RPCServer } from 'rpclibrary'
6
 import * as Path from 'path'
6
 import * as Path from 'path'
7
-import * as Knex from  'knex';
7
+import * as Knex from 'knex';
8
 import * as http from 'http';
8
 import * as http from 'http';
9
 import * as express from 'express';
9
 import * as express from 'express';
10
 import { GuildManager } from '../Components/Guild/GuildManager';
10
 import { GuildManager } from '../Components/Guild/GuildManager';
36
         PubSub
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
     config: RPCConfigLoader<AdminConf>
42
     config: RPCConfigLoader<AdminConf>
43
     rpcServer: RPCServer
43
     rpcServer: RPCServer
44
 
44
 
45
     private express
45
     private express
46
     private httpServer
46
     private httpServer
47
 
47
 
48
-    constructor(private frontworkComponents: FrontworkComponent[] = []){
48
+    constructor(private frontworkComponents: FrontworkComponent[] = []) {
49
         this.config = new RPCConfigLoader<AdminConf>({
49
         this.config = new RPCConfigLoader<AdminConf>({
50
-            name: "FrontworkAdminConf", 
50
+            name: "FrontworkAdminConf",
51
             getDefaultConfig: () => {
51
             getDefaultConfig: () => {
52
                 return {
52
                 return {
53
                     httpPort: 8080,
53
                     httpPort: 8080,
55
                     dbConf: {
55
                     dbConf: {
56
                         client: 'sqlite3',
56
                         client: 'sqlite3',
57
                         connection: {
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
                         useNullAsDefault: true,
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
         await this.makeKnex()
72
         await this.makeKnex()
69
         this.startWebsocket()
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
         await this.startWebserver()
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
             this.makeKnex()
92
             this.makeKnex()
89
         }
93
         }
90
     }
94
     }
91
 
95
 
92
-    getConfigKey(key:string){
96
+    getConfigKey(key: string) {
93
         return this.config.getConfigKey(key)
97
         return this.config.getConfigKey(key)
94
     }
98
     }
95
 
99
 
96
-    setConfigKey(key:string, value:any){
100
+    setConfigKey(key: string, value: any) {
97
         return this.config.setConfigKey(key, value)
101
         return this.config.setConfigKey(key, value)
98
     }
102
     }
99
 
103
 
100
-    getTableDefinitions(): TableDefiniton[]{
104
+    getTableDefinitions(): TableDefiniton[] {
101
         return [
105
         return [
102
             ...this.frontworkComponents
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
         this.rpcServer = new RPCServer(20000, [
113
         this.rpcServer = new RPCServer(20000, [
110
             ...this.frontworkComponents,
114
             ...this.frontworkComponents,
111
             {
115
             {
121
         getLogger('Admin#startWebsocket').debug("Websocket up on", 20000)
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
             getLogger('Admin#startWebserver').warn("Webserver is already running")
130
             getLogger('Admin#startWebserver').warn("Webserver is already running")
127
             return
131
             return
128
         }
132
         }
129
-        
130
-        let port:number = this.config.getConfig().httpPort
133
+
134
+        let port: number = this.config.getConfig().httpPort
131
         this.express = express()
135
         this.express = express()
132
 
136
 
133
         const distFolder = "../../../../dist"
137
         const distFolder = "../../../../dist"
134
         const ngExpressServer = Path.join(__dirname, distFolder, 'server.js')
138
         const ngExpressServer = Path.join(__dirname, distFolder, 'server.js')
135
 
139
 
136
-        this.express.get('*.*', (req, res)=>{
140
+        this.express.get('*.*', (req, res) => {
137
             //console.log('*.*', req.path);
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
             await req.attachExpress(this.express)
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
             getLogger('Admin#startWebserver').error(e)
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
         this.express.listen(port, () => {
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
             getLogger('Admin#stopWebserver').warn("Webserver is not running")
163
             getLogger('Admin#stopWebserver').warn("Webserver is not running")
159
             return
164
             return
160
         }
165
         }
164
         getLogger('Admin#stopWebserver').info("Webserver stopped")
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
         this.knex = Knex(conf)
180
         this.knex = Knex(conf)
176
-        if(conf.client === 'sqlite3'){
181
+        if (conf.client === 'sqlite3') {
177
             await this.knex.raw('PRAGMA foreign_keys = ON');
182
             await this.knex.raw('PRAGMA foreign_keys = ON');
178
-        
183
+
179
         }
184
         }
180
 
185
 
181
         await Promise.all(
186
         await Promise.all(
182
             this.getTableDefinitions()
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
         return this.knex
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
     Injector.resolve<FrontworkAdmin>(FrontworkAdmin).stop()
209
     Injector.resolve<FrontworkAdmin>(FrontworkAdmin).stop()
201
 })
210
 })

+ 2
- 2
src/backend/Components/Item/ItemManager.ts Vedi File

3
 import { ItemManagerFeatureIfc, ItemManagerIfc } from "./RPCInterface";
3
 import { ItemManagerFeatureIfc, ItemManagerIfc } from "./RPCInterface";
4
 import { FrontworkComponent } from "../../Types/FrontworkComponent";
4
 import { FrontworkComponent } from "../../Types/FrontworkComponent";
5
 import { TableDefinitionExporter } from "../../Types/Interfaces";
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
 import { IAdmin } from "../../Admin/Interface";
7
 import { IAdmin } from "../../Admin/Interface";
8
 import { IItemManager } from "./Interface";
8
 import { IItemManager } from "./Interface";
9
 import { IUserManager } from "../User/Interface";
9
 import { IUserManager } from "../User/Interface";
171
                     table.boolean('hidden').defaultTo(false).notNullable()
171
                     table.boolean('hidden').defaultTo(false).notNullable()
172
                     table.string('tooltip').notNullable()
172
                     table.string('tooltip').notNullable()
173
                     table.enu('tier', _Tiers).notNullable()
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 Vedi File

1
-import { SubscriptionResponse } from "rpclibrary"
2
 
1
 
3
 export class IPubSub<UpdateType>{
2
 export class IPubSub<UpdateType>{
4
     publish: (topic: string, p: UpdateType) => Promise<void>
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
     unsubscribe: (uuid: string) => Promise<void>
5
     unsubscribe: (uuid: string) => Promise<void>
7
-}
6
+}

+ 6
- 7
src/backend/Components/PubSub/PubSub.ts Vedi File

1
 import { Injectable } from "../../Injector/ServiceDecorator";
1
 import { Injectable } from "../../Injector/ServiceDecorator";
2
-import { SubscriptionResponse, makeSubResponse, RPCExporter } from "rpclibrary";
2
+import { RPCExporter } from "rpclibrary";
3
 import { IPubSub } from "./Interface";
3
 import { IPubSub } from "./Interface";
4
+const uuidv4 = require('uuid/v4')
4
 
5
 
5
 @Injectable(IPubSub)
6
 @Injectable(IPubSub)
6
 export class PubSub<UpdateType = any>
7
 export class PubSub<UpdateType = any>
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
         if(!this.subs[topic]) this.subs[topic] = {}
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
     private unsubscribe = async (uuid: string) => {
45
     private unsubscribe = async (uuid: string) => {

+ 1
- 1
src/backend/Components/Raid/Interface.ts Vedi File

6
     addSignup: (signup: Signup) => Promise<Signup>
6
     addSignup: (signup: Signup) => Promise<Signup>
7
     removeSignup: (signup: Signup) => Promise<any>    
7
     removeSignup: (signup: Signup) => Promise<any>    
8
     getSignups: (raid:Raid) => Promise<(Signup & Character & Spec & User)[]>
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
     unsign: (userToken: string, character:Character, raid:Raid,) => Promise<any>
10
     unsign: (userToken: string, character:Character, raid:Raid,) => Promise<any>
11
     archiveRaid: (raid:Raid) => Promise<RaidData>
11
     archiveRaid: (raid:Raid) => Promise<RaidData>
12
     getRaidData: (raid:Raid) => Promise<RaidData>
12
     getRaidData: (raid:Raid) => Promise<RaidData>

+ 26
- 29
src/backend/Components/Raid/RaidManager.ts Vedi File

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

+ 1
- 2
src/backend/Components/Shoutbox/Interface.ts Vedi File

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

+ 5
- 5
src/backend/Components/Shoutbox/Shoutbox.ts Vedi File

3
 import { FrontworkComponent } from "../../Types/FrontworkComponent";
3
 import { FrontworkComponent } from "../../Types/FrontworkComponent";
4
 import { TableDefiniton } from "../../Types/Types";
4
 import { TableDefiniton } from "../../Types/Types";
5
 import { IShoutbox, ShoutMessage } from "./Interface";
5
 import { IShoutbox, ShoutMessage } from "./Interface";
6
-import { SubscriptionResponse, makeSubResponse } from "rpclibrary";
7
 import * as  CircularBuffer from "circular-buffer";
6
 import * as  CircularBuffer from "circular-buffer";
7
+const uuid = require('uuid/v4')
8
 
8
 
9
 @Injectable(IShoutbox)
9
 @Injectable(IShoutbox)
10
 export class Shoutbox
10
 export class Shoutbox
52
         return this.log.toarray()
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
     unsubscribe = async (uuid: string) => {
61
     unsubscribe = async (uuid: string) => {

+ 7
- 7
src/backend/Components/User/UserManager.ts Vedi File

6
 import { CharacterManager } from "../Character/CharacterManager";
6
 import { CharacterManager } from "../Character/CharacterManager";
7
 import { UserManagerFeatureIfc, UserManagerIfc } from "./RPCInterface";
7
 import { UserManagerFeatureIfc, UserManagerIfc } from "./RPCInterface";
8
 import { FrontworkComponent } from "../../Types/FrontworkComponent";
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
 import { IAdmin } from "../../Admin/Interface";
10
 import { IAdmin } from "../../Admin/Interface";
11
 import { IUserManager } from "./Interface";
11
 import { IUserManager } from "./Interface";
12
-import { getLogger, Logger } from "log4js";
12
+import { getLogger } from "log4js";
13
 import { saltedHash } from "../../Util/hash";
13
 import { saltedHash } from "../../Util/hash";
14
 import { _Tiers, Tiers } from "../../Types/Items";
14
 import { _Tiers, Tiers } from "../../Types/Items";
15
 import { ICharacterManager } from "../Character/Interface";
15
 import { ICharacterManager } from "../Character/Interface";
24
 const salt = "6pIbc6yjSN"
24
 const salt = "6pIbc6yjSN"
25
 const ONE_WEEK = 604800000
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
     port: number,
29
     port: number,
30
 };
30
 };
31
 
31
 
51
     private character: CharacterManager
51
     private character: CharacterManager
52
 
52
 
53
     exporters: any[] = []
53
     exporters: any[] = []
54
-    rankServer: Serverstate<{}, FrontcraftFeatureIfc>
54
+    rankServer: Serverstate<FrontcraftFeatureIfc>
55
     userLogins: { [username in string]: UserRecord } = {}
55
     userLogins: { [username in string]: UserRecord } = {}
56
     allowed: string[] = []
56
     allowed: string[] = []
57
 
57
 
376
         return
376
         return
377
     }
377
     }
378
 
378
 
379
-    startRankServer = async (port: number): Promise<RPCServer<{}, FrontcraftFeatureIfc>> => {
379
+    startRankServer = async (port: number): Promise<RPCServer<FrontcraftFeatureIfc>> => {
380
         let rpcs = [
380
         let rpcs = [
381
             ...this.exportRPCFeatures(),
381
             ...this.exportRPCFeatures(),
382
             ...this.exporters.flatMap((exp) => exp.exportRPCFeatures())
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
             accessFilter: async (sesame, exporter) => {
385
             accessFilter: async (sesame, exporter) => {
386
                 const record = this.getUserRecordByToken(sesame!)
386
                 const record = this.getUserRecordByToken(sesame!)
387
                 if (!record) return false
387
                 if (!record) return false

+ 0
- 1
src/backend/Injector/ServiceDecorator.ts Vedi File

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

+ 1
- 0
src/backend/Types/Constants.ts Vedi File

1
+export const MAX_MEMO_LENGTH = 255

+ 4
- 5
src/backend/Types/FrontworkComponent.ts Vedi File

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

+ 1
- 1
src/backend/Types/Plugin.ts Vedi File

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

+ 2
- 3
src/backend/Types/PrivilegedRPCExporter.ts Vedi File

1
-import { RPCExporter, RPCInterface, RPC, RPCInterfaceArray } from "rpclibrary";
1
+import { RPCExporter, RPCInterface } from "rpclibrary";
2
 
2
 
3
 export interface PrivilegedRPCExporter <
3
 export interface PrivilegedRPCExporter <
4
     Ifc extends RPCInterface = RPCInterface, 
4
     Ifc extends RPCInterface = RPCInterface, 
5
     FeatureIfc extends RPCInterface = RPCInterface,
5
     FeatureIfc extends RPCInterface = RPCInterface,
6
     Name extends keyof Ifc = keyof Ifc, 
6
     Name extends keyof Ifc = keyof Ifc, 
7
     FeatureName extends keyof FeatureIfc = keyof FeatureIfc, 
7
     FeatureName extends keyof FeatureIfc = keyof FeatureIfc, 
8
-    SubresT = {}
9
 >extends RPCExporter<Ifc, Name>{
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 Vedi File

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

+ 3
- 0
src/frontend/angular.json Vedi File

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

+ 11
- 3
src/frontend/package-lock.json Vedi File

15742
       "integrity": "sha512-ZYzRkETgBrdEGzL5JSKimvjI2CX7ioyZCkX2BpcfyjqI+079W0wHAyj5W4rIZMcDSOHgLZtgz1IdDi/vU77KEQ=="
15742
       "integrity": "sha512-ZYzRkETgBrdEGzL5JSKimvjI2CX7ioyZCkX2BpcfyjqI+079W0wHAyj5W4rIZMcDSOHgLZtgz1IdDi/vU77KEQ=="
15743
     },
15743
     },
15744
     "rpclibrary": {
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
       "requires": {
15748
       "requires": {
15749
         "bsock": "^0.1.9",
15749
         "bsock": "^0.1.9",
15750
+        "crypto-js": "^4.0.0",
15750
         "http": "0.0.0",
15751
         "http": "0.0.0",
15751
         "uuid": "^3.3.3"
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
     "run-async": {
15762
     "run-async": {

+ 3
- 2
src/frontend/package.json Vedi File

29
     "prepush": "npm run lint:ci",
29
     "prepush": "npm run lint:ci",
30
     "release:changelog": "npm run conventional-changelog -- -p angular -i CHANGELOG.md -s",
30
     "release:changelog": "npm run conventional-changelog -- -p angular -i CHANGELOG.md -s",
31
     "add": "ng add @nguniversal/express-engine",
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
   "dependencies": {
35
   "dependencies": {
35
     "@agm/core": "^1.0.0-beta.5",
36
     "@agm/core": "^1.0.0-beta.5",
75
     "normalize.css": "6.0.0",
76
     "normalize.css": "6.0.0",
76
     "pace-js": "1.0.2",
77
     "pace-js": "1.0.2",
77
     "roboto-fontface": "0.8.0",
78
     "roboto-fontface": "0.8.0",
78
-    "rpclibrary": "^1.9.2",
79
+    "rpclibrary": "^1.10.2",
79
     "rxjs": "6.5.2",
80
     "rxjs": "6.5.2",
80
     "rxjs-compat": "6.3.0",
81
     "rxjs-compat": "6.3.0",
81
     "socicon": "3.0.5",
82
     "socicon": "3.0.5",

+ 8
- 3
src/frontend/server.ts Vedi File

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

+ 2
- 1
src/frontend/src/app/@theme/components/header/header.component.html Vedi File

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

+ 43
- 20
src/frontend/src/app/@theme/components/header/header.component.ts Vedi File

5
 import { map, takeUntil } from 'rxjs/operators';
5
 import { map, takeUntil } from 'rxjs/operators';
6
 import { Subject } from 'rxjs';
6
 import { Subject } from 'rxjs';
7
 import { User } from '../../../../../../backend/Types/Types';
7
 import { User } from '../../../../../../backend/Types/Types';
8
-import { Router } from '@angular/router';
8
+import { Router, ActivatedRoute, NavigationEnd } from '@angular/router';
9
 import { ChatComponent } from './chat.component';
9
 import { ChatComponent } from './chat.component';
10
 import { ShoutMessage } from '../../../../../../backend/Components/Shoutbox/Interface';
10
 import { ShoutMessage } from '../../../../../../backend/Components/Shoutbox/Interface';
11
 import { IApiService } from '../../../frontcraft/services/ApiService';
11
 import { IApiService } from '../../../frontcraft/services/ApiService';
41
   ];
41
   ];
42
 
42
 
43
   currentTheme = 'default';
43
   currentTheme = 'default';
44
-  userMenu : NbMenuItem[] = [ { title: 'Log out', link: '/auth/logout' } ];
44
+  userMenu: NbMenuItem[] = [];
45
 
45
 
46
   sendMessage: any = console.log
46
   sendMessage: any = console.log
47
   chatwindow: ChatComponent
47
   chatwindow: ChatComponent
50
   lastmessage = "asdasd"
50
   lastmessage = "asdasd"
51
   modifyPermissions
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
   ngOnInit() {
77
   ngOnInit() {
62
     this.themeService.changeTheme("dark");
78
     this.themeService.changeTheme("dark");
64
     this.currentTheme = this.themeService.currentTheme;
80
     this.currentTheme = this.themeService.currentTheme;
65
     this.modifyPermissions = this.api.get('modifyPermissions')
81
     this.modifyPermissions = this.api.get('modifyPermissions')
66
     this.user = this.api.getCurrentUser()
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
     this.api.get('GuildManager').getGuildInfo().then(info => {
94
     this.api.get('GuildManager').getGuildInfo().then(info => {
71
       this.title = info.name
95
       this.title = info.name
72
     })
96
     })
73
 
97
 
74
     this.api.connectShoutbox((msg) => {
98
     this.api.connectShoutbox((msg) => {
75
       this.chatlog.push(msg)
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
         this.newmessage = true
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
     }).then(sendMsg => {
107
     }).then(sendMsg => {
84
       this.sendMessage = (msg) => {
108
       this.sendMessage = (msg) => {
85
         sendMsg(msg)
109
         sendMsg(msg)
86
         this.lastmessage = msg.message
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
     this.themeService.onThemeChange()
115
     this.themeService.onThemeChange()
96
       .subscribe(themeName => this.currentTheme = themeName);
120
       .subscribe(themeName => this.currentTheme = themeName);
97
   }
121
   }
98
 
122
 
99
-  openChat(){
123
+  openChat() {
100
     this.newmessage = false
124
     this.newmessage = false
101
     const ref = this.dialogService.open(ChatComponent, {
125
     const ref = this.dialogService.open(ChatComponent, {
102
       context: {
126
       context: {
103
         sendMessage: this.sendMessage,
127
         sendMessage: this.sendMessage,
104
       }
128
       }
105
     });
129
     });
106
-    ref.onClose.subscribe(()=>{
130
+    ref.onClose.subscribe(() => {
107
       this.chatwindow = null
131
       this.chatwindow = null
108
     })
132
     })
109
     this.chatwindow = ref.componentRef.instance
133
     this.chatwindow = ref.componentRef.instance
122
   toggleSidebar(): boolean {
146
   toggleSidebar(): boolean {
123
     this.sidebarService.toggle(true, 'menu-sidebar');
147
     this.sidebarService.toggle(true, 'menu-sidebar');
124
     this.layoutService.changeLayoutSize();
148
     this.layoutService.changeLayoutSize();
125
-
126
     return false;
149
     return false;
127
   }
150
   }
128
 
151
 

+ 1
- 6
src/frontend/src/app/app.component.ts Vedi File

9
   selector: 'ngx-app',
9
   selector: 'ngx-app',
10
   template: '<router-outlet></router-outlet>',
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 Vedi File

5
  */
5
  */
6
 import { BrowserModule } from '@angular/platform-browser';
6
 import { BrowserModule } from '@angular/platform-browser';
7
 import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
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
 import { HttpClientModule } from '@angular/common/http';
9
 import { HttpClientModule } from '@angular/common/http';
10
 import { ThemeModule } from './@theme/theme.module';
10
 import { ThemeModule } from './@theme/theme.module';
11
 import { AppComponent } from './app.component';
11
 import { AppComponent } from './app.component';
12
 import { AppRoutingModule } from './app-routing.module';
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
 import {
17
 import {
14
   NbChatModule,
18
   NbChatModule,
15
   NbDatepickerModule,
19
   NbDatepickerModule,
19
   NbToastrModule,
23
   NbToastrModule,
20
   NbWindowModule,
24
   NbWindowModule,
21
 } from '@nebular/theme';
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
 @NgModule({
27
 @NgModule({
28
   declarations: [
28
   declarations: [

+ 1
- 1
src/frontend/src/app/app.server.module.ts Vedi File

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

+ 57
- 0
src/frontend/src/app/frontcraft/UpdatingComponent.ts Vedi File

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 Vedi File

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

+ 1
- 1
src/frontend/src/app/frontcraft/auth/login/login.component.html Vedi File

48
 
48
 
49
 
49
 
50
 <section class="another-action" aria-label="Register">
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
 </section>
52
 </section>

+ 6
- 5
src/frontend/src/app/frontcraft/auth/login/login.component.ts Vedi File

1
 import { Component, OnInit } from '@angular/core';
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
 import { IApiService } from '../../services/ApiService';
3
 import { IApiService } from '../../services/ApiService';
5
 import { NbToastrService } from '@nebular/theme';
4
 import { NbToastrService } from '@nebular/theme';
6
 
5
 
24
   constructor(
23
   constructor(
25
     private router : Router,  
24
     private router : Router,  
26
     private api : IApiService,
25
     private api : IApiService,
27
-    private toastr: NbToastrService
26
+    private toastr: NbToastrService,
27
+    private route: ActivatedRoute
28
   ){}
28
   ){}
29
 
29
 
30
   ngOnInit(){
30
   ngOnInit(){
41
       this.toastr.danger("Login failed", "Error")
41
       this.toastr.danger("Login failed", "Error")
42
       return
42
       return
43
     }else{
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 Vedi File

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 Vedi File

1
 import { Component, OnInit } from '@angular/core';
1
 import { Component, OnInit } from '@angular/core';
2
 import { IApiService } from '../../services/ApiService';
2
 import { IApiService } from '../../services/ApiService';
3
-import { Router } from '@angular/router';
3
+import { Router, ActivatedRoute } from '@angular/router';
4
 
4
 
5
 @Component({
5
 @Component({
6
   selector: 'mylogout',
6
   selector: 'mylogout',
10
 
10
 
11
   constructor(
11
   constructor(
12
     private api : IApiService,
12
     private api : IApiService,
13
-    private router: Router
13
+    private router: Router,
14
+    private route: ActivatedRoute
14
   ){}
15
   ){}
15
 
16
 
16
   ngOnInit(){
17
   ngOnInit(){
17
     this.api.logout().then(() => {
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 Vedi File

92
 
92
 
93
 
93
 
94
 <section class="another-action" aria-label="Register">
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
 </section>
96
 </section>

+ 8
- 4
src/frontend/src/app/frontcraft/auth/register/register.component.ts Vedi File

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

+ 0
- 1
src/frontend/src/app/frontcraft/pages/armory/armory.component.ts Vedi File

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

+ 1
- 2
src/frontend/src/app/frontcraft/pages/character/character.component.ts Vedi File

1
 import { Component, OnInit, Input } from '@angular/core';
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
 import { Spec, User, Character, Item } from '../../../../../../backend/Types/Types';
3
 import { Spec, User, Character, Item } from '../../../../../../backend/Types/Types';
5
 import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
4
 import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
6
 import { _Tiers } from '../../../../../../backend/Types/Items';
5
 import { _Tiers } from '../../../../../../backend/Types/Items';

+ 3
- 17
src/frontend/src/app/frontcraft/pages/pages-layout.component.ts Vedi File

1
-import { Component, AfterContentInit, OnInit } from '@angular/core';
1
+import { Component, OnInit } from '@angular/core';
2
 import { NbMenuItem } from '@nebular/theme';
2
 import { NbMenuItem } from '@nebular/theme';
3
-import { ClientApiService } from '../services/client-login-api';
4
 import { Router } from '@angular/router';
3
 import { Router } from '@angular/router';
5
 import { IApiService } from '../services/ApiService';
4
 import { IApiService } from '../services/ApiService';
6
 
5
 
7
-declare const Cookies
8
 
6
 
9
 @Component({
7
 @Component({
10
   selector: 'page-layout',
8
   selector: 'page-layout',
16
     </ngx-one-column-layout>
14
     </ngx-one-column-layout>
17
   `,
15
   `,
18
 })
16
 })
19
-export class PagesLayoutComponent implements OnInit{
17
+export class PagesLayoutComponent{
20
 
18
 
21
   menu:NbMenuItem[] = [{
19
   menu:NbMenuItem[] = [{
22
     icon: 'image',
20
     icon: 'image',
36
     link: '/frontcraft/armory'
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 Vedi File

9
   NbInputModule,
9
   NbInputModule,
10
   NbMenuModule,
10
   NbMenuModule,
11
   NbCardModule,
11
   NbCardModule,
12
-  NbTreeGridModule,
13
   NbListModule,
12
   NbListModule,
14
   NbTabsetModule,
13
   NbTabsetModule,
15
   NbIconModule,
14
   NbIconModule,

+ 18
- 5
src/frontend/src/app/frontcraft/pages/raid/archive.component.ts Vedi File

1
 import { Component, OnInit } from '@angular/core';
1
 import { Component, OnInit } from '@angular/core';
2
 import { ActivatedRoute } from '@angular/router';
2
 import { ActivatedRoute } from '@angular/router';
3
-import { ClientApiService as ClientApiService } from '../../services/client-login-api';
4
 import { RaidData } from '../../../../../../backend/Types/Types';
3
 import { RaidData } from '../../../../../../backend/Types/Types';
5
 import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
4
 import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
6
 import { IApiService } from '../../services/ApiService';
5
 import { IApiService } from '../../services/ApiService';
34
       tanks:[],
33
       tanks:[],
35
       healers: []
34
       healers: []
36
     }
35
     }
37
-    tokens = {}
36
+    tokens: {[key in string]:any[]} = {}
38
     displayedtokens = {}
37
     displayedtokens = {}
39
     search = ""
38
     search = ""
40
     
39
     
53
 
52
 
54
       const raidManager = this.api.get('RaidManager')
53
       const raidManager = this.api.get('RaidManager')
55
       const raiddata = await raidManager.getArchiveRaid(parseInt(param))
54
       const raiddata = await raidManager.getArchiveRaid(parseInt(param))
55
+
56
+      console.log(raiddata);
57
+      
58
+
56
       this.raid = raiddata
59
       this.raid = raiddata
57
       this.isTier = raiddata.tier != null
60
       this.isTier = raiddata.tier != null
58
       this.tokens = raiddata.tokens
61
       this.tokens = raiddata.tokens
69
       this.changeSearch()
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 Vedi File

3
       Pick Character
3
       Pick Character
4
     </nb-card-header>
4
     </nb-card-header>
5
     <nb-card-body>
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
                 {{character.charactername}}
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
     </nb-card-body>
42
     </nb-card-body>
36
 </nb-card>
43
 </nb-card>

+ 3
- 3
src/frontend/src/app/frontcraft/pages/raid/characterpicker.component.ts Vedi File

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

+ 92
- 31
src/frontend/src/app/frontcraft/pages/raid/raid.component.html Vedi File

5
                 <nb-tabset>
5
                 <nb-tabset>
6
                     <nb-tab tabTitle="Info">
6
                     <nb-tab tabTitle="Info">
7
                         <h1>
7
                         <h1>
8
-                            <img [src]="'../../../../assets/images/'+(raid.tier || 'null').toLowerCase()+'.png'"
8
+                            <img [src]="'/assets/images/'+(raid.tier || 'null').toLowerCase()+'.png'"
9
                                 style="height: 100px" />
9
                                 style="height: 100px" />
10
                             {{raid.title}}
10
                             {{raid.title}}
11
                         </h1>
11
                         </h1>
12
                         <p>
12
                         <p>
13
                             {{raid.signupcount}} / {{raid.size}} signups
13
                             {{raid.signupcount}} / {{raid.size}} signups
14
                         </p>
14
                         </p>
15
-                        <p>
15
+                        <p style="white-space: pre-line;">
16
                             {{raid.description}}
16
                             {{raid.description}}
17
                         </p>
17
                         </p>
18
                         <div *ngIf="canSignup">
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
                                 </p>
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
                                     status="success" size="medium">
33
                                     status="success" size="medium">
34
                                     <nb-icon icon="checkmark-outline"></nb-icon> On Time
34
                                     <nb-icon icon="checkmark-outline"></nb-icon> On Time
35
                                 </button>
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
                                 <button (click)="unsign()" nbButton outline status="danger" size="medium">
49
                                 <button (click)="unsign()" nbButton outline status="danger" size="medium">
37
                                     <nb-icon icon="close"></nb-icon>unsign
50
                                     <nb-icon icon="close"></nb-icon>unsign
38
                                 </button>
51
                                 </button>
46
                     </nb-tab>
59
                     </nb-tab>
47
                     <nb-tab tabTitle="Signups" [badgeText]="raid.signupcount" badgePosition="top right"
60
                     <nb-tab tabTitle="Signups" [badgeText]="raid.signupcount" badgePosition="top right"
48
                         [badgeStatus]="raid.signupcount<40?'warning':'success'">
61
                         [badgeStatus]="raid.signupcount<40?'warning':'success'">
49
-
50
                         <div class="row">
62
                         <div class="row">
51
                             <nb-card class="col-12 col-md-6" *ngIf="raid.tanks.length > 0">
63
                             <nb-card class="col-12 col-md-6" *ngIf="raid.tanks.length > 0">
52
                                 <nb-card-header>Tanks ({{raid.tanks.length}})</nb-card-header>
64
                                 <nb-card-header>Tanks ({{raid.tanks.length}})</nb-card-header>
63
                                         <a [ngStyle]="{'color': participant.color}" style="text-transform: capitalize;"
75
                                         <a [ngStyle]="{'color': participant.color}" style="text-transform: capitalize;"
64
                                             [routerLink]="'/frontcraft/character/'+participant.charactername">
76
                                             [routerLink]="'/frontcraft/character/'+participant.charactername">
65
                                             <img style="width:20px; height:20px"
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
                                             <img style="width:20px; height:20px"
79
                                             <img style="width:20px; height:20px"
68
-                                                [src]="'../../../../assets/images/'+participant.class.toLowerCase()+'.png'" />
80
+                                                [src]="'/assets/images/'+participant.class.toLowerCase()+'.png'" />
69
                                             {{ participant.charactername }}
81
                                             {{ participant.charactername }}
70
                                         </a>
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
                                         <span *ngIf="participant.rank=='Trial'" style="font-size: 9px;">
100
                                         <span *ngIf="participant.rank=='Trial'" style="font-size: 9px;">
72
                                             Trial
101
                                             Trial
73
                                         </span>
102
                                         </span>
90
                                         <a [ngStyle]="{'color': participant.color}" style="text-transform: capitalize;"
119
                                         <a [ngStyle]="{'color': participant.color}" style="text-transform: capitalize;"
91
                                             [routerLink]="'/frontcraft/character/'+participant.charactername">
120
                                             [routerLink]="'/frontcraft/character/'+participant.charactername">
92
                                             <img style="width:20px; height:20px"
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
                                             <img style="width:20px; height:20px"
123
                                             <img style="width:20px; height:20px"
95
-                                                [src]="'../../../../assets/images/'+participant.class.toLowerCase()+'.png'" />
124
+                                                [src]="'/assets/images/'+participant.class.toLowerCase()+'.png'" />
96
                                             {{ participant.charactername }}
125
                                             {{ participant.charactername }}
97
                                         </a>
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
                                         <span *ngIf="participant.rank=='Trial'" style="font-size: 9px;">
143
                                         <span *ngIf="participant.rank=='Trial'" style="font-size: 9px;">
99
                                             Trial
144
                                             Trial
100
                                         </span>
145
                                         </span>
119
                                                 style="text-transform: capitalize;"
164
                                                 style="text-transform: capitalize;"
120
                                                 [routerLink]="'/frontcraft/character/'+participant.charactername">
165
                                                 [routerLink]="'/frontcraft/character/'+participant.charactername">
121
                                                 <img style="width:20px; height:20px"
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
                                                 <img style="width:20px; height:20px"
168
                                                 <img style="width:20px; height:20px"
124
-                                                    [src]="'../../../../assets/images/'+participant.class.toLowerCase()+'.png'" />
169
+                                                    [src]="'/assets/images/'+participant.class.toLowerCase()+'.png'" />
125
                                                 {{ participant.charactername }}
170
                                                 {{ participant.charactername }}
126
                                             </a>
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
                                             <span *ngIf="participant.rank=='Trial'" style="font-size: 9px;">
188
                                             <span *ngIf="participant.rank=='Trial'" style="font-size: 9px;">
128
                                                 Trial
189
                                                 Trial
129
                                             </span>
190
                                             </span>
147
             <nb-card-body>
208
             <nb-card-body>
148
                 <nb-tabset>
209
                 <nb-tabset>
149
                     <nb-tab tabTitle="Reserves" [active]="reservesShown">
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
                         <nb-list class="">
214
                         <nb-list class="">
153
                             <nb-list-item *ngFor="let item of displayedtokens | keyvalue">
215
                             <nb-list-item *ngFor="let item of displayedtokens | keyvalue">
161
                                     <tr>
223
                                     <tr>
162
                                         <td>
224
                                         <td>
163
                                             <div class="row">
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
                                                     <span
227
                                                     <span
168
                                                         [ngStyle]="{'text-decoration': token.rank=='Trial'? 'line-through' : 'none currentcolor solid' }">
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
                                                             <a [routerLink]="'/frontcraft/character/'+token.charactername"
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
                                                                 {{token.charactername}}
233
                                                                 {{token.charactername}}
174
                                                             </a>
234
                                                             </a>
175
                                                         </span>
235
                                                         </span>
179
                                                             Becomes valid when promoted to Raider
239
                                                             Becomes valid when promoted to Raider
180
                                                         </div>
240
                                                         </div>
181
                                                     </ng-template>
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
                                                         Trial
245
                                                         Trial
185
                                                     </span><br />
246
                                                     </span><br />
186
                                                 </div>
247
                                                 </div>
187
                                             </div>
248
                                             </div>
188
-            
249
+
189
                                         </td>
250
                                         </td>
190
                                     </tr>
251
                                     </tr>
191
                                 </table>
252
                                 </table>

+ 22
- 34
src/frontend/src/app/frontcraft/pages/raid/raid.component.ts Vedi File

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
 import { RaidData, Raid, Signup, Character, Spec, Item, SRToken } from '../../../../../../backend/Types/Types';
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
 import { FrontcraftCharacerpickerComponent } from './characterpicker.component';
5
 import { FrontcraftCharacerpickerComponent } from './characterpicker.component';
7
-import { getClassColor, SpecT } from '../../../../../../backend/Types/PlayerSpecs';
6
+import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
8
 import { FrontcraftBuyTokenComponent } from '../shop/buytoken.component';
7
 import { FrontcraftBuyTokenComponent } from '../shop/buytoken.component';
9
 import { allItems } from '../../../../../../backend/Types/Items';
8
 import { allItems } from '../../../../../../backend/Types/Items';
10
 import { IApiService } from '../../services/ApiService';
9
 import { IApiService } from '../../services/ApiService';
10
+import { UpdatingComponent } from '../../UpdatingComponent';
11
+import { LoggerService } from '../../services/logger.service';
11
 
12
 
12
 @Component({
13
 @Component({
13
   selector: 'raid',
14
   selector: 'raid',
14
   templateUrl: './raid.component.html',
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
     canSignup = false
21
     canSignup = false
19
     isSignedup = false
22
     isSignedup = false
43
     tokens: {[itemname in string]: (Character & SRToken & Item)[]} = {}
46
     tokens: {[itemname in string]: (Character & SRToken & Item)[]} = {}
44
     displayedtokens = {}
47
     displayedtokens = {}
45
     search = ""
48
     search = ""
46
-    uuid
47
 
49
 
48
     constructor(
50
     constructor(
49
       private api: IApiService,
51
       private api: IApiService,
50
       private route: ActivatedRoute,
52
       private route: ActivatedRoute,
51
       private router: Router,
53
       private router: Router,
52
       private dialogService : NbDialogService,
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
       this.manageRaid = this.api.get('manageRaid')
62
       this.manageRaid = this.api.get('manageRaid')
70
-      
71
       const signupFeature = this.api.get('signup')
63
       const signupFeature = this.api.get('signup')
64
+      
72
       if(signupFeature){
65
       if(signupFeature){
73
         this.canSignup = true
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
     itemSelect = async(item) => {
73
     itemSelect = async(item) => {
143
       await signup.sign(auth.token.value, {
133
       await signup.sign(auth.token.value, {
144
         ...this.mySignup,
134
         ...this.mySignup,
145
         id: this.mySignup.characterid,
135
         id: this.mySignup.characterid,
146
-      }, this.raid, value)
136
+      }, this.raid, value, this.mySignup.memo)
147
       this.toast.show('Signup', 'Success', { status: 'success' })
137
       this.toast.show('Signup', 'Success', { status: 'success' })
148
     }
138
     }
149
 
139
 
163
       const raiddata = await raidManager.getRaidData(<any>{
153
       const raiddata = await raidManager.getRaidData(<any>{
164
         id: param
154
         id: param
165
       })
155
       })
166
-      
167
       this.display(raiddata)
156
       this.display(raiddata)
168
-      
169
     }
157
     }
170
 
158
 
171
     display =  async (raiddata:RaidData)  => {
159
     display =  async (raiddata:RaidData)  => {
179
       })
167
       })
180
 
168
 
181
       const user = this.api.getCurrentUser()
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
       if(matchingSignup){       
172
       if(matchingSignup){       
184
-        this.isSignedup = true
185
         this.mySignup = matchingSignup
173
         this.mySignup = matchingSignup
174
+        this.isSignedup = true        
186
         this.mySignup['status'] = matchingSignup['benched']?'Bench':matchingSignup['late']?'Late':'Attending'
175
         this.mySignup['status'] = matchingSignup['benched']?'Bench':matchingSignup['late']?'Late':'Attending'
187
       }else{
176
       }else{
188
         this.isSignedup = false
177
         this.isSignedup = false
189
         this.mySignup = null
178
         this.mySignup = null
190
       }
179
       }
180
+
191
       this.changeSearch()
181
       this.changeSearch()
192
     }
182
     }
193
 
183
 
202
           })
192
           })
203
           if(filteredTokens.length > 0)
193
           if(filteredTokens.length > 0)
204
             this.displayedtokens[e[0]] = filteredTokens 
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 Vedi File

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

+ 53
- 47
src/frontend/src/app/frontcraft/pages/raids/raids.component.html Vedi File

1
 <nb-card class="col-12 col-xl-9">
1
 <nb-card class="col-12 col-xl-9">
2
   <nb-card-header>
2
   <nb-card-header>
3
     Upcoming raids
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
   </nb-card-header>
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
               <h4>
16
               <h4>
27
                 {{raid.title}}
17
                 {{raid.title}}
28
               </h4>
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
         </div>
32
         </div>
45
-      </div>
33
+      </a>
46
     </nb-list-item>
34
     </nb-list-item>
47
   </nb-list>
35
   </nb-list>
48
 </nb-card>
36
 </nb-card>
49
 
37
 
50
 <nb-card class="col-12 col-xl-9">
38
 <nb-card class="col-12 col-xl-9">
51
   <nb-card-header>Previous raids</nb-card-header>
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
     <nb-list-item *ngFor="let raid of oldraids" [routerLink]="'/frontcraft/archive/'+raid.id">
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
     </nb-list-item>
68
     </nb-list-item>
62
   </nb-list>
69
   </nb-list>
63
-</nb-card>
64
-  
70
+</nb-card>

+ 21
- 31
src/frontend/src/app/frontcraft/pages/raids/raids.component.ts Vedi File

1
 import { Component, OnInit, OnDestroy } from '@angular/core';
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
 import { FrontcraftCreateRaidsComponent } from './createraid.compontent';
3
 import { FrontcraftCreateRaidsComponent } from './createraid.compontent';
5
 import { Router, NavigationStart } from '@angular/router';
4
 import { Router, NavigationStart } from '@angular/router';
6
 import { IApiService } from '../../services/ApiService';
5
 import { IApiService } from '../../services/ApiService';
6
+import { UpdatingComponent } from '../../UpdatingComponent';
7
+import { LoggerService } from '../../services/logger.service';
7
 
8
 
8
 @Component({
9
 @Component({
9
   selector: 'raids',
10
   selector: 'raids',
10
   templateUrl: 'raids.component.html',
11
   templateUrl: 'raids.component.html',
11
   styleUrls: ['raids.component.scss'],
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
   manageRaid
19
   manageRaid
17
   raids = []
20
   raids = []
18
   oldraids = []
21
   oldraids = []
19
   pageSize = 10;
22
   pageSize = 10;
20
-  uuid
21
 
23
 
22
   constructor(
24
   constructor(
23
     private api: IApiService,
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
   async ngOnInit() {
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
     this.refresh()
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
     const raidManager = this.api.get('RaidManager')
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
       closeOnBackdropClick: true,
52
       closeOnBackdropClick: true,
62
       closeOnEsc: true,
53
       closeOnEsc: true,
63
       context: {
54
       context: {
64
         templates: this.oldraids
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 Vedi File

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
 import { Item, Character, SRToken, Signup } from '../../../../../../backend/Types/Types';
3
 import { Item, Character, SRToken, Signup } from '../../../../../../backend/Types/Types';
6
 import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
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
 import { IApiService } from '../../services/ApiService';
6
 import { IApiService } from '../../services/ApiService';
9
 
7
 
10
 @Component({
8
 @Component({

+ 10
- 2
src/frontend/src/app/frontcraft/pages/shop/itemselector.component.ts Vedi File

24
 
24
 
25
     async ngOnInit(){
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
         )).then(items => {
37
         )).then(items => {
30
             this.allItems = items
38
             this.allItems = items
31
             this.displayedItems = this.allItems
39
             this.displayedItems = this.allItems

+ 0
- 2
src/frontend/src/app/frontcraft/pages/shop/shop.component.ts Vedi File

1
 import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
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
 import { Item, Character, Signup } from '../../../../../../backend/Types/Types';
2
 import { Item, Character, Signup } from '../../../../../../backend/Types/Types';
5
 import { _Tiers, allItems } from '../../../../../../backend/Types/Items';
3
 import { _Tiers, allItems } from '../../../../../../backend/Types/Items';
6
 
4
 

+ 1
- 1
src/frontend/src/app/frontcraft/pages/user/user.component.html Vedi File

57
         </form>
57
         </form>
58
         <br />
58
         <br />
59
 
59
 
60
-        <h3>Avaiable Reserves</h3>
60
+        <h3>Available Reserves</h3>
61
         {{user.MC}} MC |
61
         {{user.MC}} MC |
62
         {{user.BWL}} BWL |
62
         {{user.BWL}} BWL |
63
         {{user.ZG}} ZG |
63
         {{user.ZG}} ZG |

+ 0
- 2
src/frontend/src/app/frontcraft/permissions/changePermissions/changePermissions.component.ts Vedi File

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

+ 0
- 1
src/frontend/src/app/frontcraft/permissions/permissions-layout.component.ts Vedi File

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

+ 13
- 6
src/frontend/src/app/frontcraft/services/ApiService.ts Vedi File

1
 import { Auth, FrontcraftIfc, FrontcraftFeatureIfc, User, SomeOf } from '../../../../../backend/Types/Types';
1
 import { Auth, FrontcraftIfc, FrontcraftFeatureIfc, User, SomeOf } from '../../../../../backend/Types/Types';
2
 import { saltedHash } from '../../../../../backend/Util/hash';
2
 import { saltedHash } from '../../../../../backend/Util/hash';
3
-import { RPCSocket } from 'rpclibrary';
3
+import { RPCSocket, ConnectedSocket } from 'rpclibrary';
4
 
4
 
5
 export class IApiService{
5
 export class IApiService{
6
-    getUnprivilegedSocket: () => RPCSocket & FrontcraftIfc
6
+    getUnprivilegedSocket: () => ConnectedSocket<FrontcraftIfc>
7
     getAuth: () => Auth | undefined
7
     getAuth: () => Auth | undefined
8
     checkLogin: () => Promise<boolean>
8
     checkLogin: () => Promise<boolean>
9
     initialize: () => Promise<any>
9
     initialize: () => Promise<any>
10
-    getCurrentUser: () => User | undefined
10
+    getCurrentUser: () => User
11
     login: (username: string, password: string) => Promise<RPCSocket & SomeOf<FrontcraftFeatureIfc>>
11
     login: (username: string, password: string) => Promise<RPCSocket & SomeOf<FrontcraftFeatureIfc>>
12
     connectShoutbox: (callback:Function) => Promise<Function>
12
     connectShoutbox: (callback:Function) => Promise<Function>
13
     kick: () => Promise<void>
13
     kick: () => Promise<void>
14
     logout: () => Promise<void>
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
 export async function hash(value:string) : Promise<string>{
22
 export async function hash(value:string) : Promise<string>{
21
     return saltedHash(value, "")
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 Vedi File

1
 import { Injectable } from "@angular/core";
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
 import { Auth, User, _Class, FrontcraftFeatureIfc, SomeOf, FrontcraftIfc, } from '../../../../../backend/Types/Types'
4
 import { Auth, User, _Class, FrontcraftFeatureIfc, SomeOf, FrontcraftIfc, } from '../../../../../backend/Types/Types'
4
 import { ShoutMessage } from '../../../../../backend/Components/Shoutbox/Interface';
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
 declare const Cookies
9
 declare const Cookies
8
 
10
 
9
 @Injectable()
11
 @Injectable()
10
 export class ClientApiService implements IApiService{
12
 export class ClientApiService implements IApiService{
11
-    private socket:RPCSocket & FrontcraftIfc;
13
+    private socket:ConnectedSocket<FrontcraftIfc>
12
     private auth:Auth
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
         window['s'] = this
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
         if(this.privSocket) {
26
         if(this.privSocket) {
23
             return this.privSocket
27
             return this.privSocket
24
         }
28
         }
38
             sock.hook('getUserData', () => auth)
42
             sock.hook('getUserData', () => auth)
39
 
43
 
40
             sock.on('close', async () => {
44
             sock.on('close', async () => {
41
-                console.log("priv#close");
45
+                this.logger.log("priv#close");
42
                 
46
                 
43
                 //handled via unprivileged socket
47
                 //handled via unprivileged socket
44
             })
48
             })
45
 
49
 
46
             sock.on('error', async (e) => {
50
             sock.on('error', async (e) => {
47
-                console.log("priv#error", e);
51
+                this.logger.log("priv#error", e);
48
 
52
 
49
                 //handled via unprivileged socket
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
             this.auth = auth
57
             this.auth = auth
54
             this.privSocket = authSock
58
             this.privSocket = authSock
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
     login = async (username: string, password: string) : Promise<RPCSocket & SomeOf<FrontcraftFeatureIfc>> => {
85
     login = async (username: string, password: string) : Promise<RPCSocket & SomeOf<FrontcraftFeatureIfc>> => {
102
     }
106
     }
103
 
107
 
104
     async connectShoutbox(callback:Function) : Promise<Function>{
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
     kick = async () => {
113
     kick = async () => {
113
 
117
 
114
     logout = async () => {
118
     logout = async () => {
115
         Cookies.remove('token')
119
         Cookies.remove('token')
120
+        if(this.privSocket) this.privSocket.unhook('kick')
116
         if(this.auth){
121
         if(this.auth){
117
             try{
122
             try{
118
                 await this.socket.UserManager.logout(this.auth.user.username, this.auth.token.value)
123
                 await this.socket.UserManager.logout(this.auth.user.username, this.auth.token.value)
133
         }
138
         }
134
 
139
 
135
         try{
140
         try{
136
-            let conn = new RPCSocket(20000, window.location.hostname)
141
+            let conn = new RPCSocket<FrontcraftIfc>(20000, window.location.hostname)
137
             conn.on('close', async () => {
142
             conn.on('close', async () => {
138
             })                        
143
             })                        
139
 
144
 
140
-            this.socket = await conn.connect<FrontcraftIfc>()
145
+            this.socket = await conn.connect()
141
         }catch(e){
146
         }catch(e){
142
             alert('Unable to connect. The server appears to be down.\nPress OK to refresh the page')
147
             alert('Unable to connect. The server appears to be down.\nPress OK to refresh the page')
143
             location.reload()
148
             location.reload()

+ 37
- 0
src/frontend/src/app/frontcraft/services/logger.service.ts Vedi File

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 Vedi File

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

+ 1
- 1
src/frontend/src/main.server.ts Vedi File

6
 import { IApiService } from './app/frontcraft/services/ApiService';
6
 import { IApiService } from './app/frontcraft/services/ApiService';
7
 export { IApiService }
7
 export { IApiService }
8
 export { ServerApiService } from './app/frontcraft/services/server-login-api';
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 Vedi File

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

+ 1
- 0
src/frontend/tsconfig.app.json Vedi File

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

+ 7
- 7
test/backendTest.ts Vedi File

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

Loading…
Annulla
Salva