소스 검색

version bump and frontend fixes

master
peter 5 년 전
부모
커밋
c888bf4514
49개의 변경된 파일686개의 추가작업 그리고 685개의 파일을 삭제
  1. 33
    0
      log.txt
  2. 1
    1
      package.json
  3. 1
    3
      src/backend/Admin/Admin.ts
  4. 12
    2
      src/backend/Components/Raid/RaidManager.ts
  5. 0
    13
      src/backend/Components/Shoutbox/Interface.ts
  6. 0
    13
      src/backend/Components/Shoutbox/RPCInterface.ts
  7. 0
    64
      src/backend/Components/Shoutbox/Shoutbox.ts
  8. 1
    0
      src/backend/Components/User/UserManager.ts
  9. 1
    2
      src/backend/Types/Types.ts
  10. 89
    45
      src/frontend/package-lock.json
  11. 2
    0
      src/frontend/package.json
  12. 10
    3
      src/frontend/server.ts
  13. 0
    46
      src/frontend/src/app/@theme/components/header/chat.component.ts
  14. 0
    13
      src/frontend/src/app/@theme/components/header/header.component.html
  15. 1
    40
      src/frontend/src/app/@theme/components/header/header.component.ts
  16. 0
    3
      src/frontend/src/app/@theme/theme.module.ts
  17. 10
    3
      src/frontend/src/app/app.component.ts
  18. 2
    1
      src/frontend/src/app/app.module.ts
  19. 25
    7
      src/frontend/src/app/frontcraft/UpdatingComponent.ts
  20. 1
    1
      src/frontend/src/app/frontcraft/auth/login/login.component.ts
  21. 1
    1
      src/frontend/src/app/frontcraft/auth/logout/logout.component.ts
  22. 1
    1
      src/frontend/src/app/frontcraft/auth/register/register.component.ts
  23. 1
    1
      src/frontend/src/app/frontcraft/pages/armory/armory.component.ts
  24. 1
    1
      src/frontend/src/app/frontcraft/pages/character/character.component.ts
  25. 1
    1
      src/frontend/src/app/frontcraft/pages/characters/characters.component.ts
  26. 1
    1
      src/frontend/src/app/frontcraft/pages/pages-layout.component.ts
  27. 29
    20
      src/frontend/src/app/frontcraft/pages/raid/archive.component.ts
  28. 1
    1
      src/frontend/src/app/frontcraft/pages/raid/characterpicker.component.ts
  29. 46
    48
      src/frontend/src/app/frontcraft/pages/raid/raid.component.html
  30. 193
    181
      src/frontend/src/app/frontcraft/pages/raid/raid.component.ts
  31. 3
    4
      src/frontend/src/app/frontcraft/pages/raids/createraid.compontent.ts
  32. 38
    32
      src/frontend/src/app/frontcraft/pages/raids/raids.component.html
  33. 15
    12
      src/frontend/src/app/frontcraft/pages/raids/raids.component.ts
  34. 1
    1
      src/frontend/src/app/frontcraft/pages/rules/rules.component.ts
  35. 1
    1
      src/frontend/src/app/frontcraft/pages/shop/buytoken.component.ts
  36. 2
    2
      src/frontend/src/app/frontcraft/pages/shop/itemselector.component.ts
  37. 1
    1
      src/frontend/src/app/frontcraft/pages/shop/wowhead.component.ts
  38. 1
    1
      src/frontend/src/app/frontcraft/pages/user/user.component.ts
  39. 1
    1
      src/frontend/src/app/frontcraft/permissions/changePermissions/changePermissions.component.ts
  40. 2
    3
      src/frontend/src/app/frontcraft/services/ApiService/ApiService.ts
  41. 4
    10
      src/frontend/src/app/frontcraft/services/ApiService/client-login-api.ts
  42. 34
    31
      src/frontend/src/app/frontcraft/services/ApiService/server-login-api.ts
  43. 10
    0
      src/frontend/src/app/frontcraft/services/LoggerService/LoggerService.ts
  44. 30
    0
      src/frontend/src/app/frontcraft/services/LoggerService/logger.service.ts
  45. 21
    0
      src/frontend/src/app/frontcraft/services/flash-service.ts
  46. 0
    37
      src/frontend/src/app/frontcraft/services/logger.service.ts
  47. 52
    27
      src/frontend/src/index.html
  48. 3
    3
      src/frontend/src/main.server.ts
  49. 3
    3
      src/frontend/src/main.ts

+ 33
- 0
log.txt 파일 보기

1
+[2020-03-29T12:12:03.477] [DEBUG] Admin#makeKnex - Making new knex: {
2
+  client: 'sqlite3',
3
+  connection: {(node:1085628) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead.
4
+Terminated
5
+npm ERR! code ELIFECYCLE
6
+npm ERR! errno 143
7
+npm ERR! frontcraft@1.0.0 launch: `node lib/src/backend/Launcher.js > log.txt "-"`
8
+npm ERR! Exit status 143
9
+npm ERR! 
10
+npm ERR! Failed at the frontcraft@1.0.0 launch script.
11
+npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
12
+
13
+npm ERR! A complete log of this run can be found in:
14
+npm ERR!     /home/cake/.npm/_logs/2020-03-29T10_12_28_351Z-debug.log
15
+s loaded
16
+[2020-03-29T12:12:04.535] [INFO] Admin#startWebserver - Admin panel listening for HTTP on *8080
17
+[2020-03-29T12:12:17.689] [DEBUG] UserManager#checkConnection - {
18
+  celinda: {
19
+    connections: { '59288': [Socket] },
20
+    auth: { token: [Object], user: [Object], port: 20001 },
21
+    user: {
22
+      id: 3,
23
+      username: 'celinda',
24
+      rank: 'Officer',
25
+      MC: 1,
26
+      BWL: 0,
27
+      ZG: 1,
28
+      AQ20: 1,
29
+      AQ40: 1,
30
+      Naxx: 1
31
+    }
32
+  }
33
+} [ '1563eebe-9da2-4b31-b4ef-ef3aaa7e23b1' ]

+ 1
- 1
package.json 파일 보기

5
   "scripts": {
5
   "scripts": {
6
     "tsc": "tsc",
6
     "tsc": "tsc",
7
     "knex": "knex",
7
     "knex": "knex",
8
-    "launch": "node lib/src/backend/Launcher.js",
8
+    "launch": "node lib/src/backend/Launcher.js > log.txt",
9
     "start": "npm run build && npm run launch",
9
     "start": "npm run build && npm run launch",
10
     "start-backend": "npm run build-backend && npm run launch",
10
     "start-backend": "npm run build-backend && npm run launch",
11
     "test": "rm -rf data && npm run build-backend && mocha lib/test/backendTest.js",
11
     "test": "rm -rf data && npm run build-backend && mocha lib/test/backendTest.js",

+ 1
- 3
src/backend/Admin/Admin.ts 파일 보기

19
 import { FrontworkComponent } from '../Types/FrontworkComponent';
19
 import { FrontworkComponent } from '../Types/FrontworkComponent';
20
 import { IAdmin } from './Interface';
20
 import { IAdmin } from './Interface';
21
 import { Injector } from '../Injector/Injector';
21
 import { Injector } from '../Injector/Injector';
22
-import { Shoutbox } from '../Components/Shoutbox/Shoutbox';
23
 import { PubSub } from '../Components/PubSub/PubSub';
22
 import { PubSub } from '../Components/PubSub/PubSub';
24
 
23
 
25
 getLogger().level = 'debug'
24
 getLogger().level = 'debug'
32
         RaidManager,
31
         RaidManager,
33
         CharacterManager,
32
         CharacterManager,
34
         UserManager,
33
         UserManager,
35
-        Shoutbox,
36
         PubSub
34
         PubSub
37
     ]
35
     ]
38
 })
36
 })
145
 
143
 
146
         try {
144
         try {
147
             const req = require(distFolder + "/server.js")
145
             const req = require(distFolder + "/server.js")
148
-            await req.attachExpress(this.express)
146
+            await req.attachExpress(this.express, './dist', getLogger('angularSSR#'))
149
             getLogger('Admin#startWebserver').info('Frontend from ' + ngExpressServer + " loaded")
147
             getLogger('Admin#startWebserver').info('Frontend from ' + ngExpressServer + " loaded")
150
         } catch (e) {
148
         } catch (e) {
151
             getLogger('Admin#startWebserver').error(e)
149
             getLogger('Admin#startWebserver').error(e)

+ 12
- 2
src/backend/Components/Raid/RaidManager.ts 파일 보기

145
 
145
 
146
     getRaids = async (): Promise<Raid[]> => {
146
     getRaids = async (): Promise<Raid[]> => {
147
 
147
 
148
-        const subQuery = this.admin
148
+        const countSignups = this.admin
149
             .knex('signups')
149
             .knex('signups')
150
             .count('*')
150
             .count('*')
151
             .where({
151
             .where({
155
             })
155
             })
156
             .as('signupcount')
156
             .as('signupcount')
157
 
157
 
158
+        const countBenches = this.admin
159
+            .knex('signups')
160
+            .count('*')
161
+            .where({
162
+                raidid: this.admin.knex.ref('raids.id'),
163
+                benched: true,
164
+                late: false
165
+            })
166
+            .as('benchcount')
167
+
158
         return await this.admin.knex('raids')
168
         return await this.admin.knex('raids')
159
-            .select('*', subQuery)
169
+            .select('*', countSignups, countBenches)
160
             .orderBy('start', 'asc')
170
             .orderBy('start', 'asc')
161
     }
171
     }
162
 
172
 

+ 0
- 13
src/backend/Components/Shoutbox/Interface.ts 파일 보기

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

+ 0
- 13
src/backend/Components/Shoutbox/RPCInterface.ts 파일 보기

1
-import { IShoutbox } from "./Interface"
2
-
3
-export type ShoutboxIfc = {
4
-    Shoutbox:{
5
-        getFeed: IShoutbox['getFeed']
6
-        shout: IShoutbox['shout']
7
-        subscribe: IShoutbox['subscribe']
8
-    }
9
-}
10
-
11
-export type ShoutboxFeatureIfc = {
12
-    
13
-}

+ 0
- 64
src/backend/Components/Shoutbox/Shoutbox.ts 파일 보기

1
-import { Injectable } from "../../Injector/ServiceDecorator";
2
-import { ShoutboxFeatureIfc, ShoutboxIfc } from "./RPCInterface";
3
-import { FrontworkComponent } from "../../Types/FrontworkComponent";
4
-import { TableDefiniton } from "../../Types/Types";
5
-import { IShoutbox, ShoutMessage } from "./Interface";
6
-import * as  CircularBuffer from "circular-buffer";
7
-const uuid = require('uuid/v4')
8
-
9
-@Injectable(IShoutbox)
10
-export class Shoutbox
11
-implements FrontworkComponent<ShoutboxIfc, ShoutboxFeatureIfc>, IShoutbox{
12
-    name = "Shoutbox" as "Shoutbox";    
13
-
14
-    log: CircularBuffer = new CircularBuffer(500)
15
-    subs = {}
16
-
17
-    exportRPCs = () => [
18
-        this.shout,
19
-        this.getFeed,
20
-        {
21
-            name: 'subscribe' as 'subscribe',
22
-            hook: this.subscribe,
23
-            onClose: (subres, rpcName) => {
24
-                this.unsubscribe(subres.uuid)
25
-            }
26
-        }
27
-    ]
28
-
29
-    exportRPCFeatures = () => []
30
-    
31
-    getTableDefinitions(): TableDefiniton[] {
32
-        return []
33
-    }
34
-
35
-    shout = async (uuid:string, msg: ShoutMessage) : Promise<void> => {
36
-        if(!this.subs[uuid]) return
37
-        this.broadcast(uuid, msg)
38
-        this.log.push(msg)
39
-    }
40
-
41
-    private broadcast = async (uuid:string, msg: ShoutMessage) => {
42
-        await Promise.all(Object.values(this.subs).map(async (callback:any) => {
43
-            try{
44
-                await callback(msg)
45
-            }catch(e){
46
-                delete this.subs[uuid]
47
-            }
48
-        }))
49
-    }
50
-
51
-    getFeed = async () : Promise<ShoutMessage[]> => {
52
-        return this.log.toarray()
53
-    }
54
-
55
-    subscribe = async (callback) : Promise<string> => {
56
-        uuid()
57
-        this.subs[uuid] = callback
58
-        return uuid
59
-    }
60
-
61
-    unsubscribe = async (uuid: string) => {
62
-        delete this.subs[uuid]
63
-    }
64
-}

+ 1
- 0
src/backend/Components/User/UserManager.ts 파일 보기

404
             },
404
             },
405
             errorHandler: (socket, e, rpcName, args) => {
405
             errorHandler: (socket, e, rpcName, args) => {
406
                 getLogger('UserManager#errorHandler').error(rpcName, args, e);
406
                 getLogger('UserManager#errorHandler').error(rpcName, args, e);
407
+                throw(new Error("RPC failed"))
407
             },
408
             },
408
             sesame: (sesame) => this.checkToken(sesame),
409
             sesame: (sesame) => this.checkToken(sesame),
409
             visibility: '0.0.0.0'
410
             visibility: '0.0.0.0'

+ 1
- 2
src/backend/Types/Types.ts 파일 보기

5
 import { CharacterManagerIfc, CharacterManagerFeatureIfc } from "../Components/Character/RPCInterface";
5
 import { CharacterManagerIfc, CharacterManagerFeatureIfc } from "../Components/Character/RPCInterface";
6
 import { ItemManagerFeatureIfc, ItemManagerIfc } from "../Components/Item/RPCInterface";
6
 import { ItemManagerFeatureIfc, ItemManagerIfc } from "../Components/Item/RPCInterface";
7
 import { GuildManagerFeatureIfc, GuildManagerIfc } from "../Components/Guild/RPCInterface";
7
 import { GuildManagerFeatureIfc, GuildManagerIfc } from "../Components/Guild/RPCInterface";
8
-import { ShoutboxIfc } from "../Components/Shoutbox/RPCInterface";
9
 import { Tiers } from "./Items";
8
 import { Tiers } from "./Items";
10
 import { PubSubIfc } from "../Components/PubSub/RPCInterface";
9
 import { PubSubIfc } from "../Components/PubSub/RPCInterface";
11
 
10
 
14
                           & CharacterManagerIfc 
13
                           & CharacterManagerIfc 
15
                           & ItemManagerIfc
14
                           & ItemManagerIfc
16
                           & GuildManagerIfc
15
                           & GuildManagerIfc
17
-                          & ShoutboxIfc
18
                           & PubSubIfc
16
                           & PubSubIfc
19
 
17
 
20
 export type FrontcraftFeatureIfc = RaidManagerFeatureIfc 
18
 export type FrontcraftFeatureIfc = RaidManagerFeatureIfc 
155
     description: string
153
     description: string
156
     start: string
154
     start: string
157
     signupcount?: number
155
     signupcount?: number
156
+    benchcount?: number
158
     size: number
157
     size: number
159
     tier: Tiers
158
     tier: Tiers
160
 }
159
 }

+ 89
- 45
src/frontend/package-lock.json 파일 보기

6288
         "assert-plus": "^1.0.0"
6288
         "assert-plus": "^1.0.0"
6289
       }
6289
       }
6290
     },
6290
     },
6291
+    "date-format": {
6292
+      "version": "3.0.0",
6293
+      "resolved": "https://registry.npmjs.org/date-format/-/date-format-3.0.0.tgz",
6294
+      "integrity": "sha512-eyTcpKOcamdhWJXj56DpQMo1ylSQpcGtGKXcU0Tb97+K56/CF5amAqqqNj0+KvA0iw2ynxtHWFsPDSClCxe48w=="
6295
+    },
6291
     "dateformat": {
6296
     "dateformat": {
6292
       "version": "3.0.3",
6297
       "version": "3.0.3",
6293
       "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz",
6298
       "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz",
6298
       "version": "4.1.1",
6303
       "version": "4.1.1",
6299
       "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
6304
       "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
6300
       "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
6305
       "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
6301
-      "dev": true,
6302
       "requires": {
6306
       "requires": {
6303
         "ms": "^2.1.1"
6307
         "ms": "^2.1.1"
6304
       }
6308
       }
8095
         }
8099
         }
8096
       }
8100
       }
8097
     },
8101
     },
8102
+    "flatted": {
8103
+      "version": "2.0.1",
8104
+      "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz",
8105
+      "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg=="
8106
+    },
8098
     "flatten": {
8107
     "flatten": {
8099
       "version": "1.0.3",
8108
       "version": "1.0.3",
8100
       "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.3.tgz",
8109
       "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.3.tgz",
8131
         }
8140
         }
8132
       }
8141
       }
8133
     },
8142
     },
8143
+    "font-awesome": {
8144
+      "version": "4.7.0",
8145
+      "resolved": "https://registry.npmjs.org/font-awesome/-/font-awesome-4.7.0.tgz",
8146
+      "integrity": "sha1-j6jPBBGhoxr9B7BtKQK7n8gVoTM="
8147
+    },
8134
     "fontkit": {
8148
     "fontkit": {
8135
       "version": "1.8.0",
8149
       "version": "1.8.0",
8136
       "resolved": "https://registry.npmjs.org/fontkit/-/fontkit-1.8.0.tgz",
8150
       "resolved": "https://registry.npmjs.org/fontkit/-/fontkit-1.8.0.tgz",
8324
       "version": "8.1.0",
8338
       "version": "8.1.0",
8325
       "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
8339
       "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
8326
       "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
8340
       "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
8327
-      "dev": true,
8328
       "requires": {
8341
       "requires": {
8329
         "graceful-fs": "^4.2.0",
8342
         "graceful-fs": "^4.2.0",
8330
         "jsonfile": "^4.0.0",
8343
         "jsonfile": "^4.0.0",
10435
       "version": "4.0.0",
10448
       "version": "4.0.0",
10436
       "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
10449
       "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
10437
       "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
10450
       "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
10438
-      "dev": true,
10439
       "requires": {
10451
       "requires": {
10440
         "graceful-fs": "^4.1.6"
10452
         "graceful-fs": "^4.1.6"
10441
       }
10453
       }
11327
             "kind-of": "^3.0.2"
11339
             "kind-of": "^3.0.2"
11328
           }
11340
           }
11329
         },
11341
         },
11342
+        "isarray": {
11343
+          "version": "0.0.1",
11344
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
11345
+          "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
11346
+          "dev": true
11347
+        },
11330
         "kind-of": {
11348
         "kind-of": {
11331
           "version": "3.2.2",
11349
           "version": "3.2.2",
11332
           "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
11350
           "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
11342
           "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=",
11360
           "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=",
11343
           "dev": true
11361
           "dev": true
11344
         },
11362
         },
11363
+        "log4js": {
11364
+          "version": "0.6.38",
11365
+          "resolved": "https://registry.npmjs.org/log4js/-/log4js-0.6.38.tgz",
11366
+          "integrity": "sha1-LElBFmldb7JUgJQ9P8hy5mKlIv0=",
11367
+          "dev": true,
11368
+          "requires": {
11369
+            "readable-stream": "~1.0.2",
11370
+            "semver": "~4.3.3"
11371
+          },
11372
+          "dependencies": {
11373
+            "readable-stream": {
11374
+              "version": "1.0.34",
11375
+              "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
11376
+              "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
11377
+              "dev": true,
11378
+              "requires": {
11379
+                "core-util-is": "~1.0.0",
11380
+                "inherits": "~2.0.1",
11381
+                "isarray": "0.0.1",
11382
+                "string_decoder": "~0.10.x"
11383
+              }
11384
+            }
11385
+          }
11386
+        },
11345
         "micromatch": {
11387
         "micromatch": {
11346
           "version": "2.3.11",
11388
           "version": "2.3.11",
11347
           "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
11389
           "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
11587
             }
11629
             }
11588
           }
11630
           }
11589
         },
11631
         },
11632
+        "semver": {
11633
+          "version": "4.3.6",
11634
+          "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz",
11635
+          "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=",
11636
+          "dev": true
11637
+        },
11590
         "source-map": {
11638
         "source-map": {
11591
           "version": "0.5.7",
11639
           "version": "0.5.7",
11592
           "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
11640
           "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
11593
           "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
11641
           "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
11594
           "dev": true
11642
           "dev": true
11595
         },
11643
         },
11644
+        "string_decoder": {
11645
+          "version": "0.10.31",
11646
+          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
11647
+          "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
11648
+          "dev": true
11649
+        },
11596
         "tmp": {
11650
         "tmp": {
11597
           "version": "0.0.31",
11651
           "version": "0.0.31",
11598
           "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.31.tgz",
11652
           "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.31.tgz",
12724
       }
12778
       }
12725
     },
12779
     },
12726
     "log4js": {
12780
     "log4js": {
12727
-      "version": "0.6.38",
12728
-      "resolved": "https://registry.npmjs.org/log4js/-/log4js-0.6.38.tgz",
12729
-      "integrity": "sha1-LElBFmldb7JUgJQ9P8hy5mKlIv0=",
12730
-      "dev": true,
12781
+      "version": "6.1.2",
12782
+      "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.1.2.tgz",
12783
+      "integrity": "sha512-knS4Y30pC1e0n7rfx3VxcLOdBCsEo0o6/C7PVTGxdVK+5b1TYOSGQPn9FDcrhkoQBV29qwmA2mtkznPAQKnxQg==",
12731
       "requires": {
12784
       "requires": {
12732
-        "readable-stream": "~1.0.2",
12733
-        "semver": "~4.3.3"
12734
-      },
12735
-      "dependencies": {
12736
-        "isarray": {
12737
-          "version": "0.0.1",
12738
-          "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
12739
-          "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
12740
-          "dev": true
12741
-        },
12742
-        "readable-stream": {
12743
-          "version": "1.0.34",
12744
-          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
12745
-          "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
12746
-          "dev": true,
12747
-          "requires": {
12748
-            "core-util-is": "~1.0.0",
12749
-            "inherits": "~2.0.1",
12750
-            "isarray": "0.0.1",
12751
-            "string_decoder": "~0.10.x"
12752
-          }
12753
-        },
12754
-        "semver": {
12755
-          "version": "4.3.6",
12756
-          "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz",
12757
-          "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=",
12758
-          "dev": true
12759
-        },
12760
-        "string_decoder": {
12761
-          "version": "0.10.31",
12762
-          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
12763
-          "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
12764
-          "dev": true
12765
-        }
12785
+        "date-format": "^3.0.0",
12786
+        "debug": "^4.1.1",
12787
+        "flatted": "^2.0.1",
12788
+        "rfdc": "^1.1.4",
12789
+        "streamroller": "^2.2.3"
12766
       }
12790
       }
12767
     },
12791
     },
12768
     "loglevel": {
12792
     "loglevel": {
13376
     "ms": {
13400
     "ms": {
13377
       "version": "2.1.2",
13401
       "version": "2.1.2",
13378
       "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
13402
       "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
13379
-      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
13380
-      "dev": true
13403
+      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
13381
     },
13404
     },
13382
     "multicast-dns": {
13405
     "multicast-dns": {
13383
       "version": "6.2.3",
13406
       "version": "6.2.3",
15717
       "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=",
15740
       "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=",
15718
       "dev": true
15741
       "dev": true
15719
     },
15742
     },
15743
+    "rfdc": {
15744
+      "version": "1.1.4",
15745
+      "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.4.tgz",
15746
+      "integrity": "sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug=="
15747
+    },
15720
     "rimraf": {
15748
     "rimraf": {
15721
       "version": "2.6.1",
15749
       "version": "2.6.1",
15722
       "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz",
15750
       "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz",
17025
       "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==",
17053
       "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==",
17026
       "dev": true
17054
       "dev": true
17027
     },
17055
     },
17056
+    "streamroller": {
17057
+      "version": "2.2.3",
17058
+      "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-2.2.3.tgz",
17059
+      "integrity": "sha512-AegmvQsscTRhHVO46PhCDerjIpxi7E+d2GxgUDu+nzw/HuLnUdxHWr6WQ+mVn/4iJgMKKFFdiUwFcFRDvcjCtw==",
17060
+      "requires": {
17061
+        "date-format": "^2.1.0",
17062
+        "debug": "^4.1.1",
17063
+        "fs-extra": "^8.1.0"
17064
+      },
17065
+      "dependencies": {
17066
+        "date-format": {
17067
+          "version": "2.1.0",
17068
+          "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz",
17069
+          "integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA=="
17070
+        }
17071
+      }
17072
+    },
17028
     "strict-uri-encode": {
17073
     "strict-uri-encode": {
17029
       "version": "1.1.0",
17074
       "version": "1.1.0",
17030
       "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
17075
       "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
18508
     "universalify": {
18553
     "universalify": {
18509
       "version": "0.1.2",
18554
       "version": "0.1.2",
18510
       "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
18555
       "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
18511
-      "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
18512
-      "dev": true
18556
+      "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="
18513
     },
18557
     },
18514
     "unix-crypt-td-js": {
18558
     "unix-crypt-td-js": {
18515
       "version": "1.1.4",
18559
       "version": "1.1.4",

+ 2
- 0
src/frontend/package.json 파일 보기

62
     "core-js": "2.5.1",
62
     "core-js": "2.5.1",
63
     "echarts": "^4.0.2",
63
     "echarts": "^4.0.2",
64
     "eva-icons": "^1.1.0",
64
     "eva-icons": "^1.1.0",
65
+    "font-awesome": "^4.7.0",
65
     "intl": "1.2.5",
66
     "intl": "1.2.5",
66
     "ionicons": "2.0.1",
67
     "ionicons": "2.0.1",
67
     "js-cookie": "^2.2.1",
68
     "js-cookie": "^2.2.1",
68
     "leaflet": "1.2.0",
69
     "leaflet": "1.2.0",
70
+    "log4js": "^6.1.2",
69
     "nebular-icons": "1.1.0",
71
     "nebular-icons": "1.1.0",
70
     "ng2-ckeditor": "^1.2.2",
72
     "ng2-ckeditor": "^1.2.2",
71
     "ng2-completer": "2.0.8",
73
     "ng2-completer": "2.0.8",

+ 10
- 3
src/frontend/server.ts 파일 보기

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", loggerService = console) {
16
+export async function attachExpress(app, staticDir = "./dist", logger = console) {
17
   const STATIC_FOLDER = resolve(process.cwd(), staticDir);
17
   const STATIC_FOLDER = resolve(process.cwd(), staticDir);
18
-
19
   enableProdMode();
18
   enableProdMode();
20
 
19
 
20
+  const loggerService = {
21
+    warn: (...args) => logger.error(...args),
22
+    error: (...args) => logger.warn(...args),
23
+    log: (...args) => logger.info(...args),
24
+    table: (...args) => logger.info(...args),
25
+    collapsed: (msg, type, ...args) => loggerService[type](msg, ...args)
26
+  }
27
+
21
   const bundle = require(staticDir + '/server/main');
28
   const bundle = require(staticDir + '/server/main');
22
 
29
 
23
   const ServerApiService = bundle.ServerApiService
30
   const ServerApiService = bundle.ServerApiService
24
-  const serviceObj = new ServerApiService(loggerService)
31
+  const serviceObj = new ServerApiService(logger)
25
   await serviceObj.initialize()
32
   await serviceObj.initialize()
26
 
33
 
27
   app.set('view engine', 'html');
34
   app.set('view engine', 'html');

+ 0
- 46
src/frontend/src/app/@theme/components/header/chat.component.ts 파일 보기

1
-import { Component } from '@angular/core';
2
-import { ShoutMessage } from '../../../../../../backend/Components/Shoutbox/Interface';
3
-import { IApiService } from '../../../frontcraft/services/ApiService';
4
-
5
-@Component({
6
-  selector: 'chat',
7
-  template: `
8
-        <nb-chat title="Shoutbox" size="large" status="primary">
9
-          <nb-chat-message *ngFor="let msg of messages"
10
-                           [type]="text"
11
-                           [message]="msg.message"
12
-                           [sender]="msg.sender"
13
-                           [date]="msg.date"
14
-                           [reply]="msg.reply">
15
-          </nb-chat-message>
16
-          <nb-chat-form 
17
-          (send)="submit($event)" 
18
-          [dropFiles]="false">
19
-          </nb-chat-form>
20
-        </nb-chat>
21
-  `, 
22
-  styles: [`
23
-  nb-chat {
24
-    width: 600px;
25
-    margin: 0.5rem 0 2rem 2rem;
26
-  }`],
27
-})
28
-export class ChatComponent {
29
-
30
-  messages : ShoutMessage[] = []
31
-  history
32
-
33
-  constructor(
34
-    private api: IApiService
35
-  ) {}
36
-
37
-  submit(event){
38
-    this.sendMessage({
39
-      date: ""+Date.now(),
40
-      message: event.message,
41
-      sender: this.api.getCurrentUser().username
42
-    })
43
-  }
44
-
45
-  sendMessage : (msg:ShoutMessage)=>Promise<void>
46
-}

+ 0
- 13
src/frontend/src/app/@theme/components/header/header.component.html 파일 보기

14
       icon="settings-2-outline" 
14
       icon="settings-2-outline" 
15
       link="/permissions">
15
       link="/permissions">
16
     </nb-action>
16
     </nb-action>
17
-    <nb-action 
18
-      *ngIf="!newmessage"
19
-      icon="message-square-outline" 
20
-      (click)="openChat()">
21
-    </nb-action>
22
-    <nb-action 
23
-      *ngIf="newmessage"
24
-      icon="message-square-outline"
25
-      badgeText="new"
26
-      badgePosition="top right"
27
-      badgeStatus="info"
28
-      (click)="openChat()">
29
-    </nb-action>
30
   
17
   
31
     <nb-action class="user-action">
18
     <nb-action class="user-action">
32
       <nb-user style="text-transform: capitalize;"
19
       <nb-user style="text-transform: capitalize;"

+ 1
- 40
src/frontend/src/app/@theme/components/header/header.component.ts 파일 보기

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, ActivatedRoute, NavigationEnd } from '@angular/router';
8
 import { Router, ActivatedRoute, NavigationEnd } from '@angular/router';
9
-import { ChatComponent } from './chat.component';
10
-import { ShoutMessage } from '../../../../../../backend/Components/Shoutbox/Interface';
11
-import { IApiService } from '../../../frontcraft/services/ApiService';
9
+import { IApiService } from '../../../frontcraft/services/ApiService/ApiService';
12
 
10
 
13
 @Component({
11
 @Component({
14
   selector: 'ngx-header',
12
   selector: 'ngx-header',
44
   userMenu: NbMenuItem[] = [];
42
   userMenu: NbMenuItem[] = [];
45
 
43
 
46
   sendMessage: any = console.log
44
   sendMessage: any = console.log
47
-  chatwindow: ChatComponent
48
-  chatlog: ShoutMessage[] = []
49
   newmessage = false
45
   newmessage = false
50
   lastmessage = "asdasd"
46
   lastmessage = "asdasd"
51
   modifyPermissions
47
   modifyPermissions
56
     private themeService: NbThemeService,
52
     private themeService: NbThemeService,
57
     private layoutService: LayoutService,
53
     private layoutService: LayoutService,
58
     private api: IApiService,
54
     private api: IApiService,
59
-    private dialogService: NbDialogService,
60
-    private route: ActivatedRoute
61
   ) { }
55
   ) { }
62
 
56
 
63
   private setUserMenu = (redirect = this.router.url) => {
57
   private setUserMenu = (redirect = this.router.url) => {
89
       }
83
       }
90
     })
84
     })
91
 
85
 
92
-
93
-
94
     this.api.get('GuildManager').getGuildInfo().then(info => {
86
     this.api.get('GuildManager').getGuildInfo().then(info => {
95
       this.title = info.name
87
       this.title = info.name
96
     })
88
     })
97
 
89
 
98
-    this.api.connectShoutbox((msg) => {
99
-      this.chatlog.push(msg)
100
-      msg['reply'] = false
101
-
102
-      if (msg.message != this.lastmessage) {
103
-        this.newmessage = true
104
-        msg['reply'] = true
105
-      }
106
-      if (this.chatwindow) this.chatwindow.messages.push(msg)
107
-    }).then(sendMsg => {
108
-      this.sendMessage = (msg) => {
109
-        sendMsg(msg)
110
-        this.lastmessage = msg.message
111
-      }
112
-      this.api.get('Shoutbox').getFeed().then(log => { this.chatlog = log })
113
-    })
114
-
115
     this.themeService.onThemeChange()
90
     this.themeService.onThemeChange()
116
       .pipe(
91
       .pipe(
117
         map(({ name }) => name),
92
         map(({ name }) => name),
120
       .subscribe(themeName => this.currentTheme = themeName);
95
       .subscribe(themeName => this.currentTheme = themeName);
121
   }
96
   }
122
 
97
 
123
-  openChat() {
124
-    this.newmessage = false
125
-    const ref = this.dialogService.open(ChatComponent, {
126
-      context: {
127
-        sendMessage: this.sendMessage,
128
-      }
129
-    });
130
-    ref.onClose.subscribe(() => {
131
-      this.chatwindow = null
132
-    })
133
-    this.chatwindow = ref.componentRef.instance
134
-    this.chatwindow.messages.push(...this.chatlog)
135
-  }
136
-
137
   ngOnDestroy() {
98
   ngOnDestroy() {
138
     this.destroy$.next();
99
     this.destroy$.next();
139
     this.destroy$.complete();
100
     this.destroy$.complete();

+ 0
- 3
src/frontend/src/app/@theme/theme.module.ts 파일 보기

42
 import { COSMIC_THEME } from './styles/theme.cosmic';
42
 import { COSMIC_THEME } from './styles/theme.cosmic';
43
 import { CORPORATE_THEME } from './styles/theme.corporate';
43
 import { CORPORATE_THEME } from './styles/theme.corporate';
44
 import { DARK_THEME } from './styles/theme.dark';
44
 import { DARK_THEME } from './styles/theme.dark';
45
-import { ChatComponent } from './components/header/chat.component';
46
 
45
 
47
 const NB_MODULES = [
46
 const NB_MODULES = [
48
   NbLayoutModule,
47
   NbLayoutModule,
70
   ThreeColumnsLayoutComponent,
69
   ThreeColumnsLayoutComponent,
71
   TwoColumnsLayoutComponent,
70
   TwoColumnsLayoutComponent,
72
   OneColumnNoSidebarLayoutComponent,
71
   OneColumnNoSidebarLayoutComponent,
73
-  ChatComponent
74
 ];
72
 ];
75
 const PIPES = [
73
 const PIPES = [
76
   CapitalizePipe,
74
   CapitalizePipe,
85
   exports: [CommonModule, ...PIPES, ...COMPONENTS],
83
   exports: [CommonModule, ...PIPES, ...COMPONENTS],
86
   declarations: [...COMPONENTS, ...PIPES],
84
   declarations: [...COMPONENTS, ...PIPES],
87
   entryComponents: [
85
   entryComponents: [
88
-    ChatComponent
89
   ]
86
   ]
90
 })
87
 })
91
 export class ThemeModule {
88
 export class ThemeModule {

+ 10
- 3
src/frontend/src/app/app.component.ts 파일 보기

3
  * Copyright Akveo. All Rights Reserved.
3
  * Copyright Akveo. All Rights Reserved.
4
  * Licensed under the MIT License. See License.txt in the project root for license information.
4
  * Licensed under the MIT License. See License.txt in the project root for license information.
5
  */
5
  */
6
-import { Component, OnInit } from '@angular/core';
6
+import { Component } from '@angular/core';
7
+import { NbIconLibraries } from '@nebular/theme';
8
+
7
 
9
 
8
 @Component({
10
 @Component({
9
   selector: 'ngx-app',
11
   selector: 'ngx-app',
10
-  template: '<router-outlet></router-outlet>',
12
+  template: `<router-outlet></router-outlet>`,
13
+  styles: []
11
 })
14
 })
12
-export class AppComponent { }
15
+export class AppComponent{
16
+  constructor(private iconLibraries: NbIconLibraries) {
17
+    this.iconLibraries.registerFontPack('font-awesome', { iconClassPrefix: 'fa' });
18
+  }
19
+}

+ 2
- 1
src/frontend/src/app/app.module.ts 파일 보기

23
   NbToastrModule,
23
   NbToastrModule,
24
   NbWindowModule,
24
   NbWindowModule,
25
 } from '@nebular/theme';
25
 } from '@nebular/theme';
26
+import { FlashService } from './frontcraft/services/flash-service';
26
 
27
 
27
 @NgModule({
28
 @NgModule({
28
   declarations: [
29
   declarations: [
49
     PermissionsModule
50
     PermissionsModule
50
   ],
51
   ],
51
   bootstrap: [AppComponent],
52
   bootstrap: [AppComponent],
52
-  providers: []
53
+  providers: [FlashService]
53
 })
54
 })
54
 export class FrontcraftAppModule {
55
 export class FrontcraftAppModule {
55
 }
56
 }

+ 25
- 7
src/frontend/src/app/frontcraft/UpdatingComponent.ts 파일 보기

1
 import { Router, NavigationStart } from '@angular/router'
1
 import { Router, NavigationStart } from '@angular/router'
2
-import { IApiService } from './services/ApiService'
2
+import { IApiService } from './services/ApiService/ApiService'
3
 import { AnyFunction } from 'rpclibrary'
3
 import { AnyFunction } from 'rpclibrary'
4
-import { LoggerService } from './services/logger.service'
5
-import { OnDestroy } from '@angular/core'
4
+import { LoggerService } from './services/LoggerService/logger.service'
5
+import { OnDestroy, Inject, PLATFORM_ID, Injector } from '@angular/core'
6
+import { isPlatformBrowser } from '@angular/common'
6
 
7
 
7
 export abstract class UpdatingComponent implements OnDestroy {
8
 export abstract class UpdatingComponent implements OnDestroy {
9
+
8
     private _uuid: string
10
     private _uuid: string
9
     private _routerCancel: Function
11
     private _routerCancel: Function
12
+    private _router: Router
13
+    private _api: IApiService
14
+    private _logger: LoggerService
15
+    private platformId: Object
10
 
16
 
11
     constructor(
17
     constructor(
12
-        private _router: Router,
13
-        private _api: IApiService,
14
-        private _logger: LoggerService
15
-    ) { }
18
+        injector: Injector
19
+    ) {
20
+        this._router = injector.get(Router)
21
+        this._api = injector.get(IApiService)
22
+        this._logger = injector.get(LoggerService)
23
+        this.platformId = injector.get(PLATFORM_ID)
24
+    }
16
 
25
 
17
     protected subscribe = (
26
     protected subscribe = (
18
         topic: string,
27
         topic: string,
19
         callback: AnyFunction,
28
         callback: AnyFunction,
20
     ) => {
29
     ) => {
30
+        if (!topic
31
+        || topic === "null"
32
+        || topic === "undefined"
33
+        || !callback
34
+        || !isPlatformBrowser(this.platformId)) 
35
+        {
36
+            return
37
+        }
38
+
21
         const sub = this._router.events.subscribe(event => {
39
         const sub = this._router.events.subscribe(event => {
22
             if (event instanceof NavigationStart) {
40
             if (event instanceof NavigationStart) {
23
                 this.ngOnDestroy()
41
                 this.ngOnDestroy()

+ 1
- 1
src/frontend/src/app/frontcraft/auth/login/login.component.ts 파일 보기

1
 import { Component, OnInit } from '@angular/core';
1
 import { Component, OnInit } from '@angular/core';
2
 import { Router, ActivatedRoute } from '@angular/router';
2
 import { Router, ActivatedRoute } from '@angular/router';
3
-import { IApiService } from '../../services/ApiService';
3
+import { IApiService } from '../../services/ApiService/ApiService';
4
 import { NbToastrService } from '@nebular/theme';
4
 import { NbToastrService } from '@nebular/theme';
5
 
5
 
6
 @Component({
6
 @Component({

+ 1
- 1
src/frontend/src/app/frontcraft/auth/logout/logout.component.ts 파일 보기

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/ApiService';
3
 import { Router, ActivatedRoute } from '@angular/router';
3
 import { Router, ActivatedRoute } from '@angular/router';
4
 
4
 
5
 @Component({
5
 @Component({

+ 1
- 1
src/frontend/src/app/frontcraft/auth/register/register.component.ts 파일 보기

2
 import { Router, ActivatedRoute } from '@angular/router';
2
 import { Router, ActivatedRoute } from '@angular/router';
3
 import { _Rank, _Class, Class, User, _Race  } from '../../../../../../backend/Types/Types'
3
 import { _Rank, _Class, Class, User, _Race  } from '../../../../../../backend/Types/Types'
4
 import { specs  } from '../../../../../../backend/Types/PlayerSpecs'
4
 import { specs  } from '../../../../../../backend/Types/PlayerSpecs'
5
-import { hash, IApiService } from '../../services/ApiService';
5
+import { hash, IApiService } from '../../services/ApiService/ApiService';
6
 
6
 
7
 
7
 
8
 @Component({
8
 @Component({

+ 1
- 1
src/frontend/src/app/frontcraft/pages/armory/armory.component.ts 파일 보기

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 { IApiService } from '../../services/ApiService';
5
+import { IApiService } from '../../services/ApiService/ApiService';
6
 
6
 
7
 @Component({
7
 @Component({
8
   selector: 'armory',
8
   selector: 'armory',

+ 1
- 1
src/frontend/src/app/frontcraft/pages/character/character.component.ts 파일 보기

3
 import { Spec, User, Character, Item } from '../../../../../../backend/Types/Types';
3
 import { Spec, User, Character, Item } from '../../../../../../backend/Types/Types';
4
 import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
4
 import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
5
 import { _Tiers } from '../../../../../../backend/Types/Items';
5
 import { _Tiers } from '../../../../../../backend/Types/Items';
6
-import { IApiService } from '../../services/ApiService';
6
+import { IApiService } from '../../services/ApiService/ApiService';
7
 
7
 
8
 @Component({
8
 @Component({
9
   selector: 'character',
9
   selector: 'character',

+ 1
- 1
src/frontend/src/app/frontcraft/pages/characters/characters.component.ts 파일 보기

2
 import { NbThemeService } from '@nebular/theme';
2
 import { NbThemeService } from '@nebular/theme';
3
 import { _Class } from '../../../../../../backend/Types/Types';
3
 import { _Class } from '../../../../../../backend/Types/Types';
4
 import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
4
 import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
5
-import { IApiService } from '../../services/ApiService';
5
+import { IApiService } from '../../services/ApiService/ApiService';
6
 
6
 
7
 
7
 
8
 @Component({
8
 @Component({

+ 1
- 1
src/frontend/src/app/frontcraft/pages/pages-layout.component.ts 파일 보기

1
 import { Component, 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 { Router } from '@angular/router';
3
 import { Router } from '@angular/router';
4
-import { IApiService } from '../services/ApiService';
4
+import { IApiService } from '../services/ApiService/ApiService';
5
 
5
 
6
 
6
 
7
 @Component({
7
 @Component({

+ 29
- 20
src/frontend/src/app/frontcraft/pages/raid/archive.component.ts 파일 보기

1
 import { Component, OnInit } from '@angular/core';
1
 import { Component, OnInit } from '@angular/core';
2
-import { ActivatedRoute } from '@angular/router';
2
+import { ActivatedRoute, Router } from '@angular/router';
3
 import { RaidData } from '../../../../../../backend/Types/Types';
3
 import { RaidData } from '../../../../../../backend/Types/Types';
4
 import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
4
 import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
5
-import { IApiService } from '../../services/ApiService';
5
+import { IApiService } from '../../services/ApiService/ApiService';
6
+import { LoggerService } from '../../services/LoggerService/logger.service';
6
 
7
 
7
 @Component({
8
 @Component({
8
   selector: 'archive',
9
   selector: 'archive',
40
     constructor(
41
     constructor(
41
       private api: IApiService,
42
       private api: IApiService,
42
       private route: ActivatedRoute,
43
       private route: ActivatedRoute,
44
+      private router: Router,
45
+      private logger: LoggerService
43
     ){
46
     ){
44
     }
47
     }
45
 
48
 
51
       const param = this.route.snapshot.paramMap.get('id');
54
       const param = this.route.snapshot.paramMap.get('id');
52
 
55
 
53
       const raidManager = this.api.get('RaidManager')
56
       const raidManager = this.api.get('RaidManager')
54
-      const raiddata = await raidManager.getArchiveRaid(parseInt(param))
57
+      try{
58
+        const raiddata = await raidManager.getArchiveRaid(parseInt(param))
59
+        if(!raiddata) throw new Error('Unable to get raid')
55
 
60
 
56
-      console.log(raiddata);
57
-      
58
-
59
-      this.raid = raiddata
60
-      this.isTier = raiddata.tier != null
61
-      this.tokens = raiddata.tokens
62
-      this.displayedtokens = this.tokens;
63
-
64
-      [
65
-        ...raiddata.tanks, 
66
-        ...raiddata.healers, 
67
-        ...Object.values<any>(raiddata.participants).flat()
68
-      ].forEach(p => {
69
-        p['color'] = getClassColor(p.class)
70
-      })
71
-
72
-      this.changeSearch()
61
+        this.raid = raiddata
62
+        this.isTier = raiddata.tier != null
63
+        this.tokens = raiddata.tokens
64
+        this.displayedtokens = this.tokens;
65
+  
66
+        [
67
+          ...raiddata.tanks, 
68
+          ...raiddata.healers, 
69
+          ...Object.values<any>(raiddata.participants).flat()
70
+        ].forEach(p => {
71
+          p['color'] = getClassColor(p.class)
72
+          if(!p.timestamp)
73
+            p.before = 5.184e+8 //7 days
74
+          else
75
+            p['before'] = Number.parseInt(this.raid.start) - Date.parse(p.timestamp)
76
+        })
77
+  
78
+        this.changeSearch()
79
+      }catch(e){
80
+        this.router.navigate(["/"])
81
+      }
73
     }
82
     }
74
 
83
 
75
     changeSearch(){
84
     changeSearch(){

+ 1
- 1
src/frontend/src/app/frontcraft/pages/raid/characterpicker.component.ts 파일 보기

2
 import { 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 { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
4
 import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
5
-import { IApiService } from '../../services/ApiService';
5
+import { IApiService } from '../../services/ApiService/ApiService';
6
 
6
 
7
 @Component({
7
 @Component({
8
     selector: 'characterpicker',
8
     selector: 'characterpicker',

+ 46
- 48
src/frontend/src/app/frontcraft/pages/raid/raid.component.html 파일 보기

86
                                                     style="white-space: pre-line; max-width: 50vw; word-wrap: break-word;">
86
                                                     style="white-space: pre-line; max-width: 50vw; word-wrap: break-word;">
87
                                                     {{participant.memo}}
87
                                                     {{participant.memo}}
88
                                                 </p>
88
                                                 </p>
89
-                                                {{participant.timestamp | date : 'HH:mm EEE MMM d'}}
89
+                                                {{participant.timestamp | date : 'HH:mm EEE MMM d'}} ({{participant.before | date : 'dd'}} days before start)
90
                                             </div>
90
                                             </div>
91
                                         </ng-template>
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">
92
+                                        <nb-icon
93
+                                        [nbPopover]="template" 
94
+                                        nbPopoverTrigger="hover"
95
+                                        style="width: 0.75em; height: 0.75em;" 
96
+                                        [icon]="participant.memo != null && participant.memo != ''?'message-circle-outline':'clock-outline'"
97
+                                        [status]="participant.before>8.64e+7?(participant.before>2.592e+8?'success':'warning'):'danger'">
99
                                         </nb-icon>
98
                                         </nb-icon>
99
+
100
                                         <span *ngIf="participant.rank=='Trial'" style="font-size: 9px;">
100
                                         <span *ngIf="participant.rank=='Trial'" style="font-size: 9px;">
101
                                             Trial
101
                                             Trial
102
                                         </span>
102
                                         </span>
129
                                                 <p style="white-space: pre-line;">
129
                                                 <p style="white-space: pre-line;">
130
                                                     {{participant.memo}}
130
                                                     {{participant.memo}}
131
                                                 </p>
131
                                                 </p>
132
-                                                {{participant.timestamp | date : 'HH:mm EEE MMM d'}}
132
+                                                {{participant.timestamp | date : 'HH:mm EEE MMM d'}} ({{participant.before | date : 'dd'}} days before start)
133
                                             </div>
133
                                             </div>
134
                                         </ng-template>
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">
135
+                                        <nb-icon
136
+                                            [nbPopover]="template" 
137
+                                            nbPopoverTrigger="hover"
138
+                                            style="width: 0.75em; height: 0.75em;" 
139
+                                            [icon]="participant.memo != null && participant.memo != ''?'message-circle-outline':'clock-outline'"
140
+                                            [status]="participant.before>8.64e+7?(participant.before>2.592e+8?'success':'warning'):'danger'">
142
                                         </nb-icon>
141
                                         </nb-icon>
143
                                         <span *ngIf="participant.rank=='Trial'" style="font-size: 9px;">
142
                                         <span *ngIf="participant.rank=='Trial'" style="font-size: 9px;">
144
                                             Trial
143
                                             Trial
174
                                                     <p style="white-space: pre-line;">
173
                                                     <p style="white-space: pre-line;">
175
                                                         {{participant.memo}}
174
                                                         {{participant.memo}}
176
                                                     </p>
175
                                                     </p>
177
-                                                    {{participant.timestamp | date : 'HH:mm EEE MMM d'}}
176
+                                                    {{participant.timestamp | date : 'HH:mm EEE MMM d'}} ({{participant.before | date : 'dd'}} days before start)
178
                                                 </div>
177
                                                 </div>
179
                                             </ng-template>
178
                                             </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">
179
+                                            <nb-icon
180
+                                                [nbPopover]="template" 
181
+                                                nbPopoverTrigger="hover"
182
+                                                style="width: 0.75em; height: 0.75em;" 
183
+                                                [icon]="participant.memo != null && participant.memo != ''?'message-circle-outline':'clock-outline'"
184
+                                                [status]="participant.before>8.64e+7?(participant.before>2.592e+8?'success':'warning'):'danger'">
187
                                             </nb-icon>
185
                                             </nb-icon>
186
+
188
                                             <span *ngIf="participant.rank=='Trial'" style="font-size: 9px;">
187
                                             <span *ngIf="participant.rank=='Trial'" style="font-size: 9px;">
189
                                                 Trial
188
                                                 Trial
190
                                             </span>
189
                                             </span>
213
 
212
 
214
                         <nb-list class="">
213
                         <nb-list class="">
215
                             <nb-list-item *ngFor="let item of displayedtokens | keyvalue">
214
                             <nb-list-item *ngFor="let item of displayedtokens | keyvalue">
216
-                                <table>
215
+                                <table style="width: 100%;">
217
                                     <tr>
216
                                     <tr>
218
                                         <td>
217
                                         <td>
219
                                             <wowhead [item]="item.value[0]"></wowhead><br />
218
                                             <wowhead [item]="item.value[0]"></wowhead><br />
221
                                         </td>
220
                                         </td>
222
                                     </tr>
221
                                     </tr>
223
                                     <tr>
222
                                     <tr>
224
-                                        <td>
225
-                                            <div class="row">
226
-                                                <div *ngFor="let token of item.value" class="col-12 col-md-6 col-xl-4">
227
-                                                    <span
228
-                                                        [ngStyle]="{'text-decoration': token.rank=='Trial'? 'line-through' : 'none currentcolor solid' }">
229
-                                                        <span style="text-transform: capitalize; white-space: nowrap;">
230
-                                                            [ {{token.level}} ]&nbsp;
231
-                                                            <a [routerLink]="'/frontcraft/character/'+token.charactername"
232
-                                                                [ngStyle]="{'color':token.level>=10?'#ff8000':token.level>=8?'#a335ee':token.level>=6?'#0070dd':token.level>=4?'#1eff00':token.level>=2?'#ffffff':'#9d9d9d'}">
233
-                                                                {{token.charactername}}
234
-                                                            </a>
235
-                                                        </span>
223
+                                        <td class="row">
224
+                                            <div *ngFor="let token of item.value" class="col-12 col-md-6 col-xl-4"
225
+                                                style="white-space: nowrap;">
226
+                                                <span
227
+                                                    [ngStyle]="{'text-decoration': token.rank=='Trial'? 'line-through' : 'none currentcolor solid' }">
228
+                                                    <span style="text-transform: capitalize;">
229
+                                                        [ {{token.level}} ]&nbsp;
230
+                                                        <a [routerLink]="'/frontcraft/character/'+token.charactername"
231
+                                                            [ngStyle]="{'color':token.level>=10?'#ff8000':token.level>=8?'#a335ee':token.level>=6?'#0070dd':token.level>=4?'#1eff00':token.level>=2?'#ffffff':'#9d9d9d'}">
232
+                                                            {{token.charactername}}
233
+                                                        </a>
236
                                                     </span>
234
                                                     </span>
237
-                                                    <ng-template #tooltip>
238
-                                                        <div style="color:white">
239
-                                                            Becomes valid when promoted to Raider
240
-                                                        </div>
241
-                                                    </ng-template>
242
-                                                    <span *ngIf="token.rank=='Trial'" style="font-size: 9px;"
243
-                                                        [nbPopover]="tooltip" nbPopoverTrigger="hover"
244
-                                                        nbPopoverPlacement="top">
245
-                                                        Trial
246
-                                                    </span><br />
247
-                                                </div>
235
+                                                </span>
236
+                                                <ng-template #tooltip>
237
+                                                    <div style="color:white">
238
+                                                        Becomes valid when promoted to Raider
239
+                                                    </div>
240
+                                                </ng-template>
241
+                                                <span *ngIf="token.rank=='Trial'" style="font-size: 9px;"
242
+                                                    [nbPopover]="tooltip" nbPopoverTrigger="hover"
243
+                                                    nbPopoverPlacement="top">
244
+                                                    &nbsp;Trial
245
+                                                </span><br />
248
                                             </div>
246
                                             </div>
249
 
247
 
250
                                         </td>
248
                                         </td>

+ 193
- 181
src/frontend/src/app/frontcraft/pages/raid/raid.component.ts 파일 보기

1
-import { Component, OnInit } from '@angular/core';
1
+import { Component, OnInit, Injector } from '@angular/core';
2
 import { ActivatedRoute, Router } from '@angular/router';
2
 import { ActivatedRoute, Router } from '@angular/router';
3
 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';
4
 import { NbToastrService, NbDialogService } from '@nebular/theme';
4
 import { NbToastrService, NbDialogService } from '@nebular/theme';
6
 import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
6
 import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
7
 import { FrontcraftBuyTokenComponent } from '../shop/buytoken.component';
7
 import { FrontcraftBuyTokenComponent } from '../shop/buytoken.component';
8
 import { allItems } from '../../../../../../backend/Types/Items';
8
 import { allItems } from '../../../../../../backend/Types/Items';
9
-import { IApiService } from '../../services/ApiService';
9
+import { IApiService } from '../../services/ApiService/ApiService';
10
 import { UpdatingComponent } from '../../UpdatingComponent';
10
 import { UpdatingComponent } from '../../UpdatingComponent';
11
-import { LoggerService } from '../../services/logger.service';
11
+import { LoggerService } from '../../services/LoggerService/logger.service';
12
+import { FlashService } from '../../services/flash-service';
12
 
13
 
13
 @Component({
14
 @Component({
14
   selector: 'raid',
15
   selector: 'raid',
15
   templateUrl: './raid.component.html',
16
   templateUrl: './raid.component.html',
16
 })
17
 })
17
-export class FrontcraftRaidComponent 
18
-extends UpdatingComponent
19
-implements OnInit{
20
-
21
-    canSignup = false
22
-    isSignedup = false
23
-    islate = false
24
-    isTier = false
25
-    reservesShown = true
26
-    manageRaid
27
-    mySignup: (Signup & Character & Spec)
28
-
29
-    raid: RaidData = <any>{
30
-      participants:{
31
-          Druid: [],
32
-          Hunter: [],
33
-          Mage: [],
34
-          Paladin: [],
35
-          Priest: [],
36
-          Rogue: [],
37
-          Shaman: [],
38
-          Warlock: [],
39
-          Warrior: [],
40
-      },
41
-      tanks: [],
42
-      healers: [],
43
-      tokens:{},
44
-      tier: 'null'
18
+export class FrontcraftRaidComponent
19
+  extends UpdatingComponent
20
+  implements OnInit {
21
+
22
+  now = Date.now()
23
+  canSignup = false
24
+  isSignedup = false
25
+  islate = false
26
+  isTier = false
27
+  reservesShown = true
28
+  manageRaid
29
+  mySignup: (Signup & Character & Spec)
30
+
31
+  raid: RaidData = <any>{
32
+    participants: {
33
+      Druid: [],
34
+      Hunter: [],
35
+      Mage: [],
36
+      Paladin: [],
37
+      Priest: [],
38
+      Rogue: [],
39
+      Shaman: [],
40
+      Warlock: [],
41
+      Warrior: [],
42
+    },
43
+    tanks: [],
44
+    healers: [],
45
+    tokens: {},
46
+    tier: 'null'
47
+  }
48
+  tokens: { [itemname in string]: (Character & SRToken & Item)[] } = {}
49
+  displayedtokens = {}
50
+  search = ""
51
+
52
+  constructor(
53
+    injector: Injector,
54
+    private api: IApiService,
55
+    private route: ActivatedRoute,
56
+    private router: Router,
57
+    private dialogService: NbDialogService,
58
+    private toast: NbToastrService,
59
+    private flash: FlashService,
60
+    private logger: LoggerService
61
+  ) {
62
+    super(injector)
63
+  }
64
+
65
+  ngOnInit() {
66
+    this.manageRaid = this.api.get('manageRaid')
67
+    const signupFeature = this.api.get('signup')
68
+
69
+    if (signupFeature) {
70
+      this.canSignup = true
45
     }
71
     }
46
-    tokens: {[itemname in string]: (Character & SRToken & Item)[]} = {}
47
-    displayedtokens = {}
48
-    search = ""
49
-
50
-    constructor(
51
-      private api: IApiService,
52
-      private route: ActivatedRoute,
53
-      private router: Router,
54
-      private dialogService : NbDialogService,
55
-      private toast: NbToastrService,
56
-      logger: LoggerService
57
-    ){
58
-      super(router, api, logger)
59
-    }
60
-
61
-    ngOnInit(){
62
-      this.manageRaid = this.api.get('manageRaid')
63
-      const signupFeature = this.api.get('signup')
64
-      
65
-      if(signupFeature){
66
-        this.canSignup = true
72
+    this.refresh().then(() => {
73
+      this.subscribe(String(this.raid.id), (data: RaidData) => this.display(data).then(_ =>
74
+        this.flash.show()
75
+      ))
76
+    })
77
+  }
78
+
79
+  itemSelect = async (item) => {
80
+    this.dialogService.open(FrontcraftBuyTokenComponent, {
81
+      context: {
82
+        item: item,
83
+        signup: this.mySignup,
84
+        tier: this.raid.tier,
85
+        characterName: this.mySignup.charactername
67
       }
86
       }
87
+    }).onClose.subscribe(() => {
68
       this.refresh().then(() => {
88
       this.refresh().then(() => {
69
-        this.subscribe(String(this.raid.id), (data: RaidData) => this.display(data))
70
-      })
71
-    }
72
-
73
-    itemSelect = async(item) => {
74
-      this.dialogService.open(FrontcraftBuyTokenComponent, {
75
-        context: {
76
-          item: item,
77
-          signup: this.mySignup,
78
-          tier: this.raid.tier,
79
-          characterName: this.mySignup.charactername
80
-        }
81
-      }).onClose.subscribe(() => {
82
-        this.refresh().then(()=>{
83
-          this.reservesShown = true
84
-        })
89
+        this.reservesShown = true
85
       })
90
       })
86
-    }
87
-
88
-    signup = async () => {
89
-      const signupFeature = this.api.get('signup')
90
-      if(!signupFeature) return
91
-
92
-      this.dialogService.open(FrontcraftCharacerpickerComponent, { 
93
-        closeOnBackdropClick: true,
94
-        closeOnEsc: true,
95
-        context: {
96
-          raid: this.raid,
97
-        } 
98
-      }).onClose.subscribe(() => {
99
-        this.refresh().then(()=>{
100
-          this.reservesShown = false
101
-        })
91
+    })
92
+  }
93
+
94
+  signup = async () => {
95
+    const signupFeature = this.api.get('signup')
96
+    if (!signupFeature) return
97
+
98
+    this.dialogService.open(FrontcraftCharacerpickerComponent, {
99
+      closeOnBackdropClick: true,
100
+      closeOnEsc: true,
101
+      context: {
102
+        raid: this.raid,
103
+      }
104
+    }).onClose.subscribe(() => {
105
+      this.refresh().then(() => {
106
+        this.reservesShown = false
102
       })
107
       })
103
-    }
104
-
105
-    async archiveRaid(raid:Raid){
106
-      await this.manageRaid!.archiveRaid(raid)
107
-      this.toast.show('Raid archived', 'Success', { status: 'success' })
108
-      this.router.navigateByUrl('/frontcraft/archive/'+raid.id)
109
-    }
110
-
111
-    async startRaid(raid:Raid){
112
-      await this.manageRaid!.startRaid(raid)
113
-      this.toast.show('Raid started', 'Success', { status: 'success' })
114
-      this.router.navigateByUrl('/frontcraft/archive/'+raid.id)
115
-    }
116
-
117
-    unsign = async () => {
118
-      const signupFeature = this.api.get('signup')
119
-      if(!signupFeature) return
120
-
121
-      await signupFeature.unsign(this.api.getAuth().token.value, {
122
-        ...this.mySignup,
123
-        id: this.mySignup.characterid, 
124
-      }, this.raid)
125
-      this.toast.show('Success', 'Unsigned', { status: 'success' })
126
-    }
127
-
128
-    setLate = async (value:boolean) => {
129
-      const auth = this.api.getAuth()
130
-      const signup = this.api.get('signup')
131
-      if(!signup) return
132
-
133
-      await signup.sign(auth.token.value, {
134
-        ...this.mySignup,
135
-        id: this.mySignup.characterid,
136
-      }, this.raid, value, this.mySignup.memo)
137
-      this.toast.show('Signup', 'Success', { status: 'success' })
138
-    }
139
-
140
-    adminUnsign = async(character:Character) => {
141
-      const manage =  this.api.get('manageRaid')
142
-      if(!manage) return
143
-      await manage.adminUnsign({
144
-        ...character,
145
-        id: character['characterid']
146
-      }, this.raid)
147
-    }
148
-
149
-    refresh = async () => {
150
-      const param = this.route.snapshot.paramMap.get('id');
151
-
152
-      const raidManager = this.api.get('RaidManager')
108
+    })
109
+  }
110
+
111
+  async archiveRaid(raid: Raid) {
112
+    await this.manageRaid!.archiveRaid(raid)
113
+    this.toast.show('Raid archived', 'Success', { status: 'success' })
114
+    this.router.navigateByUrl('/frontcraft/archive/' + raid.id)
115
+  }
116
+
117
+  async startRaid(raid: Raid) {
118
+    await this.manageRaid!.startRaid(raid)
119
+    this.toast.show('Raid started', 'Success', { status: 'success' })
120
+    this.router.navigateByUrl('/frontcraft/archive/' + raid.id)
121
+  }
122
+
123
+  unsign = async () => {
124
+    const signupFeature = this.api.get('signup')
125
+    if (!signupFeature) return
126
+
127
+    await signupFeature.unsign(this.api.getAuth().token.value, {
128
+      ...this.mySignup,
129
+      id: this.mySignup.characterid,
130
+    }, this.raid)
131
+    this.toast.show('Success', 'Unsigned', { status: 'success' })
132
+  }
133
+
134
+  setLate = async (value: boolean) => {
135
+    const auth = this.api.getAuth()
136
+    const signup = this.api.get('signup')
137
+    if (!signup) return
138
+
139
+    await signup.sign(auth.token.value, {
140
+      ...this.mySignup,
141
+      id: this.mySignup.characterid,
142
+    }, this.raid, value, this.mySignup.memo)
143
+    this.toast.show('Signup', 'Success', { status: 'success' })
144
+  }
145
+
146
+  adminUnsign = async (character: Character) => {
147
+    const manage = this.api.get('manageRaid')
148
+    if (!manage) return
149
+    await manage.adminUnsign({
150
+      ...character,
151
+      id: character['characterid']
152
+    }, this.raid)
153
+  }
154
+
155
+  refresh = async () => {
156
+    const param = this.route.snapshot.paramMap.get('id');
157
+    const raidManager = this.api.get('RaidManager')
158
+
159
+    try {
153
       const raiddata = await raidManager.getRaidData(<any>{
160
       const raiddata = await raidManager.getRaidData(<any>{
154
         id: param
161
         id: param
155
       })
162
       })
156
-      this.display(raiddata)
163
+      await this.display(raiddata)
164
+    } catch (e) {
165
+      this.router.navigate(["/"])
157
     }
166
     }
158
-
159
-    display =  async (raiddata:RaidData)  => {
160
-      this.isTier = allItems[raiddata.tier] != null
161
-
162
-      this.raid = raiddata
163
-      this.tokens = raiddata.tokens;
164
-
165
-      [...raiddata.tanks, ...raiddata.healers, ...Object.values(raiddata.participants).flat()].forEach(p => {
166
-        p['color'] = getClassColor(p.class)
167
-      })
168
-
169
-      const user = this.api.getCurrentUser()
170
-      const matchingSignup = Object.values(raiddata.participants).flat().find(char => user && char.userid === user.id!)     
171
-      
172
-      if(matchingSignup){       
173
-        this.mySignup = matchingSignup
174
-        this.isSignedup = true        
175
-        this.mySignup['status'] = matchingSignup['benched']?'Bench':matchingSignup['late']?'Late':'Attending'
176
-      }else{
177
-        this.isSignedup = false
178
-        this.mySignup = null
179
-      }
180
-
181
-      this.changeSearch()
167
+  }
168
+
169
+  display = async (raiddata: RaidData) => {
170
+    this.logger.log(raiddata)
171
+    this.isTier = allItems[raiddata.tier] != null
172
+
173
+    this.raid = raiddata
174
+    this.tokens = raiddata.tokens;
175
+
176
+    [...raiddata.tanks, ...raiddata.healers, ...Object.values(raiddata.participants).flat()].forEach(p => {
177
+      p['color'] = getClassColor(p.class)
178
+      p['before'] = Number.parseInt(this.raid.start) - Date.parse(p.timestamp)
179
+    })
180
+
181
+    const user = this.api.getCurrentUser()
182
+    const matchingSignup = Object.values(raiddata.participants).flat().find(char => user && char.userid === user.id!)
183
+
184
+    if (matchingSignup) {
185
+      this.mySignup = matchingSignup
186
+      this.isSignedup = true
187
+      this.mySignup['status'] = matchingSignup['benched'] ? 'Bench' : matchingSignup['late'] ? 'Late' : 'Attending'
188
+    } else {
189
+      this.isSignedup = false
190
+      this.mySignup = null
182
     }
191
     }
183
 
192
 
184
-    changeSearch(){
185
-      if(!this.search || this.search == ""){
186
-        this.displayedtokens = this.tokens
187
-      }else{
188
-        this.displayedtokens = {}
189
-        Object.entries(this.tokens).forEach((e: [string /*itemname*/, (Character & SRToken & Item)[]]) => {
190
-          const filteredTokens = e[1].filter(item => {
191
-            return item.itemname.toLocaleLowerCase().includes(this.search.toLocaleLowerCase())
192
-          })
193
-          if(filteredTokens.length > 0)
194
-            this.displayedtokens[e[0]] = filteredTokens 
195
-        })        
196
-      }
197
-    }
198
-
199
-    setBench(signup:Signup){
200
-      this.manageRaid.setBenched({
201
-        characterid: signup.characterid,
202
-        raidid: signup.raidid,
203
-        late: false,
204
-        benched: !signup.benched
205
-      }).then(_ => this.refresh())
193
+    this.changeSearch()
194
+  }
195
+
196
+  changeSearch() {
197
+    if (!this.search || this.search == "") {
198
+      this.displayedtokens = this.tokens
199
+    } else {
200
+      this.displayedtokens = {}
201
+      Object.entries(this.tokens).forEach((e: [string /*itemname*/, (Character & SRToken & Item)[]]) => {
202
+        const filteredTokens = e[1].filter(item => {
203
+          return item.itemname.toLocaleLowerCase().includes(this.search.toLocaleLowerCase())
204
+        })
205
+        if (filteredTokens.length > 0)
206
+          this.displayedtokens[e[0]] = filteredTokens
207
+      })
206
     }
208
     }
209
+  }
210
+
211
+  setBench(signup: Signup) {
212
+    this.manageRaid.setBenched({
213
+      characterid: signup.characterid,
214
+      raidid: signup.raidid,
215
+      late: false,
216
+      benched: !signup.benched
217
+    }).then(_ => this.refresh())
218
+  }
207
 }
219
 }

+ 3
- 4
src/frontend/src/app/frontcraft/pages/raids/createraid.compontent.ts 파일 보기

1
 import { Component, OnInit } from '@angular/core';
1
 import { Component, OnInit } from '@angular/core';
2
 import { Raid, RaidData } from '../../../../../../backend/Types/Types';
2
 import { Raid, RaidData } from '../../../../../../backend/Types/Types';
3
-import { NbDialogRef } from '@nebular/theme';
3
+import { NbDialogRef, DARK_THEME } from '@nebular/theme';
4
 import { Tiers, _Tiers } from '../../../../../../backend/Types/Items';
4
 import { Tiers, _Tiers } from '../../../../../../backend/Types/Items';
5
-import { IApiService } from '../../services/ApiService';
5
+import { IApiService } from '../../services/ApiService/ApiService';
6
 
6
 
7
 const ONE_MINUTE = 60000
7
 const ONE_MINUTE = 60000
8
 const ONE_HOUR = 60 * ONE_MINUTE
8
 const ONE_HOUR = 60 * ONE_MINUTE
34
   }
34
   }
35
 
35
 
36
   onTierSelect(){
36
   onTierSelect(){
37
-    
38
   }
37
   }
39
 
38
 
40
   onTemplateSelect(){
39
   onTemplateSelect(){
62
     const manage = this.api.get('manageRaid')
61
     const manage = this.api.get('manageRaid')
63
     if(!manage) return
62
     if(!manage) return
64
 
63
 
65
-    await manage.createRaid(raid)
64
+    const dbraid = await manage.createRaid(raid)
66
     this.dialogRef.close()
65
     this.dialogRef.close()
67
   }
66
   }
68
 }
67
 }

+ 38
- 32
src/frontend/src/app/frontcraft/pages/raids/raids.component.html 파일 보기

6
   <nb-list nbInfiniteList listenWindowScroll [threshold]="500">
6
   <nb-list nbInfiniteList listenWindowScroll [threshold]="500">
7
     <nb-list-item *ngFor="let raid of raids" class="raidlist">
7
     <nb-list-item *ngFor="let raid of raids" class="raidlist">
8
       <a [routerLink]="'/frontcraft/raid/'+raid.id">
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>
9
+        <table>
10
+          <tr>
11
+            <td rowspan="2" style="padding-right: 20px;">
12
+              <img [src]="'/assets/images/'+(raid.tier || 'null').toLowerCase()+'.png'"
13
+                style="max-width: 50px; object-fit: contain" />
14
+            </td>
15
+            <td>
16
               <h4>
16
               <h4>
17
                 {{raid.title}}
17
                 {{raid.title}}
18
               </h4>
18
               </h4>
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>
32
-        </div>
19
+            </td>
20
+          </tr>
21
+          <tr class="row">
22
+            <td class="col-3" style="padding-left:8px; padding-right: 25px; white-space: nowrap; color: lightslategray;">
23
+              <nb-icon icon="checkmark-circle"></nb-icon>&nbsp;{{ raid.signupcount | number:'2.0' }}&nbsp;/&nbsp;{{raid.size}}
24
+            </td>
25
+            <td class="col-3" style="padding-right: 25px; white-space: nowrap; color: lightslategray;">
26
+              <nb-icon icon="person-remove-outline"></nb-icon>&nbsp;{{ raid.benchcount }}
27
+            </td>
28
+            <td class="col-3" style="padding-right: 25px; white-space: nowrap; color: lightslategray;">
29
+              <nb-icon icon="clock-outline"></nb-icon>&nbsp;{{raid.start | date : 'HH:mm'}}
30
+            </td>
31
+            <td class="col-3" style="padding-right: 25px; white-space: nowrap; color: lightslategray;">
32
+              <nb-icon icon="calendar-outline"></nb-icon>&nbsp;{{raid.start | date : 'EEE MMM d'}}
33
+            </td>
34
+          </tr>
35
+        </table>
33
       </a>
36
       </a>
34
     </nb-list-item>
37
     </nb-list-item>
35
   </nb-list>
38
   </nb-list>
40
   <nb-list nbInfiniteList listenWindowScroll [threshold]="500">
43
   <nb-list nbInfiniteList listenWindowScroll [threshold]="500">
41
     <nb-list-item *ngFor="let raid of oldraids" [routerLink]="'/frontcraft/archive/'+raid.id">
44
     <nb-list-item *ngFor="let raid of oldraids" [routerLink]="'/frontcraft/archive/'+raid.id">
42
       <a [routerLink]="'/frontcraft/archive/'+raid.id">
45
       <a [routerLink]="'/frontcraft/archive/'+raid.id">
43
-        <div class="row">
44
-          <table>
46
+          <table style="width: 100%;">
45
             <tr>
47
             <tr>
46
               <td rowspan="2" style="padding-right: 20px;">
48
               <td rowspan="2" style="padding-right: 20px;">
47
                 <img [src]="'/assets/images/'+(raid.tier || 'null').toLowerCase()+'.png'"
49
                 <img [src]="'/assets/images/'+(raid.tier || 'null').toLowerCase()+'.png'"
48
                   style="max-width: 50px;;object-fit: contain; filter: grayscale(75%)" />
50
                   style="max-width: 50px;;object-fit: contain; filter: grayscale(75%)" />
49
               </td>
51
               </td>
50
-              <h4>
51
-                {{raid.title}}
52
-              </h4>
52
+              <td>
53
+                <h4>
54
+                  {{raid.title}}
55
+                </h4>
56
+              </td>
53
             </tr>
57
             </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>
58
+            <tr class="row">
59
+              <td class="col-3" style="padding-left:8px; padding-right: 25px; white-space: nowrap; color: lightslategray;">
60
+                <nb-icon icon="checkmark-circle"></nb-icon>&nbsp;{{ raid.signupcount | number:'2.0' }}&nbsp;/&nbsp;{{raid.size}}
61
+              </td>
62
+              <td class="col-3" style="padding-right: 25px; white-space: nowrap; color: lightslategray;">
63
+                <nb-icon icon="person-remove-outline"></nb-icon>&nbsp;{{ raid.participants.bench.length }}
57
               </td>
64
               </td>
58
-              <td style="padding-right: 25px; white-space: nowrap; color: lightslategray;">
65
+              <td class="col-3" style="padding-right: 25px; white-space: nowrap; color: lightslategray;">
59
                 <nb-icon icon="clock-outline"></nb-icon>&nbsp;{{raid.start | date : 'HH:mm'}}
66
                 <nb-icon icon="clock-outline"></nb-icon>&nbsp;{{raid.start | date : 'HH:mm'}}
60
               </td>
67
               </td>
61
-              <td style="padding-right: 25px; white-space: nowrap; color: lightslategray;">
68
+              <td class="col-3" style="padding-right: 25px; white-space: nowrap; color: lightslategray;">
62
                 <nb-icon icon="calendar-outline"></nb-icon>&nbsp;{{raid.start | date : 'EEE MMM d'}}
69
                 <nb-icon icon="calendar-outline"></nb-icon>&nbsp;{{raid.start | date : 'EEE MMM d'}}
63
               </td>
70
               </td>
64
             </tr>
71
             </tr>
65
           </table>
72
           </table>
66
-        </div>
67
       </a>
73
       </a>
68
     </nb-list-item>
74
     </nb-list-item>
69
   </nb-list>
75
   </nb-list>

+ 15
- 12
src/frontend/src/app/frontcraft/pages/raids/raids.component.ts 파일 보기

1
-import { Component, OnInit, OnDestroy } from '@angular/core';
2
-import { NbDialogService } from '@nebular/theme';
1
+import { Component, OnInit, OnDestroy, Injector } from '@angular/core';
2
+import { NbDialogService, NbToastrService } from '@nebular/theme';
3
 import { FrontcraftCreateRaidsComponent } from './createraid.compontent';
3
 import { FrontcraftCreateRaidsComponent } from './createraid.compontent';
4
 import { Router, NavigationStart } from '@angular/router';
4
 import { Router, NavigationStart } from '@angular/router';
5
-import { IApiService } from '../../services/ApiService';
5
+import { IApiService } from '../../services/ApiService/ApiService';
6
 import { UpdatingComponent } from '../../UpdatingComponent';
6
 import { UpdatingComponent } from '../../UpdatingComponent';
7
-import { LoggerService } from '../../services/logger.service';
7
+import { LoggerService } from '../../services/LoggerService/logger.service';
8
+import { FlashService } from '../../services/flash-service';
8
 
9
 
9
 @Component({
10
 @Component({
10
   selector: 'raids',
11
   selector: 'raids',
11
   templateUrl: 'raids.component.html',
12
   templateUrl: 'raids.component.html',
12
   styleUrls: ['raids.component.scss'],
13
   styleUrls: ['raids.component.scss'],
13
 })
14
 })
14
-export class FrontcraftRaidsComponent 
15
-extends UpdatingComponent
16
-implements OnInit {
15
+export class FrontcraftRaidsComponent
16
+  extends UpdatingComponent
17
+  implements OnInit {
17
 
18
 
18
 
19
 
19
   manageRaid
20
   manageRaid
22
   pageSize = 10;
23
   pageSize = 10;
23
 
24
 
24
   constructor(
25
   constructor(
26
+    injector: Injector,
25
     private api: IApiService,
27
     private api: IApiService,
26
-    router: Router,
27
     private dialogService: NbDialogService,
28
     private dialogService: NbDialogService,
28
-    logger: LoggerService
29
+    private flash: FlashService,
29
   ) {
30
   ) {
30
-    super(router, api, logger)
31
+    super(injector)
31
   }
32
   }
32
 
33
 
33
-  ngOnDestroy(){
34
+  ngOnDestroy() {
34
     super.ngOnDestroy()
35
     super.ngOnDestroy()
35
   }
36
   }
36
 
37
 
37
   async ngOnInit() {
38
   async ngOnInit() {
38
-    this.subscribe("raids", () => this.refresh())
39
+    this.subscribe("raids", () => this.refresh().then(_ =>
40
+      this.flash.show()
41
+    ))
39
 
42
 
40
     this.manageRaid = this.api.get('manageRaid')
43
     this.manageRaid = this.api.get('manageRaid')
41
     this.refresh()
44
     this.refresh()

+ 1
- 1
src/frontend/src/app/frontcraft/pages/rules/rules.component.ts 파일 보기

1
 import { Component, OnInit } from '@angular/core';
1
 import { Component, OnInit } from '@angular/core';
2
 import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
2
 import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
3
-import { IApiService } from '../../services/ApiService';
3
+import { IApiService } from '../../services/ApiService/ApiService';
4
 
4
 
5
 @Component({
5
 @Component({
6
   selector: 'rules',
6
   selector: 'rules',

+ 1
- 1
src/frontend/src/app/frontcraft/pages/shop/buytoken.component.ts 파일 보기

3
 import { Item, Character, SRToken, Signup } from '../../../../../../backend/Types/Types';
3
 import { Item, Character, SRToken, Signup } from '../../../../../../backend/Types/Types';
4
 import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
4
 import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
5
 import { _Tiers, Tiers } from '../../../../../../backend/Types/Items';
5
 import { _Tiers, Tiers } from '../../../../../../backend/Types/Items';
6
-import { IApiService } from '../../services/ApiService';
6
+import { IApiService } from '../../services/ApiService/ApiService';
7
 
7
 
8
 @Component({
8
 @Component({
9
     selector: 'buyToken',
9
     selector: 'buyToken',

+ 2
- 2
src/frontend/src/app/frontcraft/pages/shop/itemselector.component.ts 파일 보기

1
 import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
1
 import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
2
-import { ClientApiService } from '../../services/client-login-api';
2
+import { ClientApiService } from '../../services/ApiService/client-login-api';
3
 import { Item, Character } from '../../../../../../backend/Types/Types';
3
 import { Item, Character } from '../../../../../../backend/Types/Types';
4
-import { IApiService } from '../../services/ApiService';
4
+import { IApiService } from '../../services/ApiService/ApiService';
5
 
5
 
6
 @Component({
6
 @Component({
7
   selector: 'itemselect',
7
   selector: 'itemselect',

+ 1
- 1
src/frontend/src/app/frontcraft/pages/shop/wowhead.component.ts 파일 보기

8
   template: `
8
   template: `
9
     <span *ngIf="tooltipHtml">
9
     <span *ngIf="tooltipHtml">
10
       <ng-template #tooltip>
10
       <ng-template #tooltip>
11
-        <div style="color:white" [innerHTML]="tooltipHtml">
11
+        <div style="color:white; background-color:black; padding: 7px" [innerHTML]="tooltipHtml">
12
         </div>
12
         </div>
13
       </ng-template>
13
       </ng-template>
14
       <span 
14
       <span 

+ 1
- 1
src/frontend/src/app/frontcraft/pages/user/user.component.ts 파일 보기

5
 import { _Tiers } from '../../../../../../backend/Types/Items';
5
 import { _Tiers } from '../../../../../../backend/Types/Items';
6
 import { _Rank } from '../../../../../../backend/Types/Types';
6
 import { _Rank } from '../../../../../../backend/Types/Types';
7
 import { NbToastrService } from '@nebular/theme';
7
 import { NbToastrService } from '@nebular/theme';
8
-import { hash, IApiService } from '../../services/ApiService';
8
+import { hash, IApiService } from '../../services/ApiService/ApiService';
9
 
9
 
10
 @Component({
10
 @Component({
11
   selector: 'user-component',
11
   selector: 'user-component',

+ 1
- 1
src/frontend/src/app/frontcraft/permissions/changePermissions/changePermissions.component.ts 파일 보기

1
 import { Component, OnInit } from '@angular/core';
1
 import { Component, OnInit } from '@angular/core';
2
 import { _Rank, _Class, _Race, RPCPermission  } from '../../../../../../backend/Types/Types'
2
 import { _Rank, _Class, _Race, RPCPermission  } from '../../../../../../backend/Types/Types'
3
 import { NbToastrService } from '@nebular/theme';
3
 import { NbToastrService } from '@nebular/theme';
4
-import { IApiService } from '../../services/ApiService';
4
+import { IApiService } from '../../services/ApiService/ApiService';
5
 
5
 
6
 
6
 
7
 @Component({
7
 @Component({

src/frontend/src/app/frontcraft/services/ApiService.ts → src/frontend/src/app/frontcraft/services/ApiService/ApiService.ts 파일 보기

1
-import { Auth, FrontcraftIfc, FrontcraftFeatureIfc, User, SomeOf } from '../../../../../backend/Types/Types';
2
-import { saltedHash } from '../../../../../backend/Util/hash';
1
+import { Auth, FrontcraftIfc, FrontcraftFeatureIfc, User, SomeOf } from '../../../../../../backend/Types/Types';
2
+import { saltedHash } from '../../../../../../backend/Util/hash';
3
 import { RPCSocket, ConnectedSocket } from 'rpclibrary';
3
 import { RPCSocket, ConnectedSocket } from 'rpclibrary';
4
 
4
 
5
 export class IApiService{
5
 export class IApiService{
9
     initialize: () => Promise<any>
9
     initialize: () => Promise<any>
10
     getCurrentUser: () => User
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>
13
     kick: () => Promise<void>
12
     kick: () => Promise<void>
14
     logout: () => Promise<void>
13
     logout: () => Promise<void>
15
     get: <K extends (keyof FrontcraftIfc | keyof FrontcraftFeatureIfc)>(feature : K) => K extends keyof FrontcraftIfc
14
     get: <K extends (keyof FrontcraftIfc | keyof FrontcraftFeatureIfc)>(feature : K) => K extends keyof FrontcraftIfc

src/frontend/src/app/frontcraft/services/client-login-api.ts → src/frontend/src/app/frontcraft/services/ApiService/client-login-api.ts 파일 보기

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 { ConnectedSocket } from "rpclibrary"
4
-import { Auth, User, _Class, FrontcraftFeatureIfc, SomeOf, FrontcraftIfc, } from '../../../../../backend/Types/Types'
5
-import { ShoutMessage } from '../../../../../backend/Components/Shoutbox/Interface';
4
+import { Auth, User, _Class, FrontcraftFeatureIfc, SomeOf, FrontcraftIfc, } from '../../../../../../backend/Types/Types'
6
 import { hash, IApiService, GuestUser } from './ApiService';
5
 import { hash, IApiService, GuestUser } from './ApiService';
7
-import { LoggerService } from './logger.service';
6
+import { LoggerService } from '../LoggerService/logger.service';
8
 
7
 
9
 declare const Cookies
8
 declare const Cookies
10
 
9
 
12
 export class ClientApiService implements IApiService{
11
 export class ClientApiService implements IApiService{
13
     private socket:ConnectedSocket<FrontcraftIfc>
12
     private socket:ConnectedSocket<FrontcraftIfc>
14
     private auth:Auth
13
     private auth:Auth
15
-    private privSocket: RPCSocket<SomeOf<FrontcraftFeatureIfc>>
14
+    private privSocket: ConnectedSocket<SomeOf<FrontcraftFeatureIfc>>
16
 
15
 
17
     constructor(
16
     constructor(
18
         private logger: LoggerService
17
         private logger: LoggerService
22
 
21
 
23
     getUnprivilegedSocket = () : ConnectedSocket<FrontcraftIfc> => this.socket
22
     getUnprivilegedSocket = () : ConnectedSocket<FrontcraftIfc> => this.socket
24
 
23
 
25
-    private getPrivilegedSocket = async (auth:Auth) : Promise<RPCSocket<SomeOf<FrontcraftFeatureIfc>>> => {
24
+    private getPrivilegedSocket = async (auth:Auth) : Promise<ConnectedSocket<SomeOf<FrontcraftFeatureIfc>>> => {
26
         if(this.privSocket) {
25
         if(this.privSocket) {
27
             return this.privSocket
26
             return this.privSocket
28
         }
27
         }
105
         return sock
104
         return sock
106
     }
105
     }
107
 
106
 
108
-    async connectShoutbox(callback:Function) : Promise<Function>{
109
-        const uuid = await this.get('Shoutbox').subscribe(callback)
110
-        return async (msg: ShoutMessage) => await this.get('Shoutbox').shout(uuid, msg)
111
-    }
112
-
113
     kick = async () => {
107
     kick = async () => {
114
         await this.logout()
108
         await this.logout()
115
         location.reload()
109
         location.reload()

src/frontend/src/app/frontcraft/services/server-login-api.ts → src/frontend/src/app/frontcraft/services/ApiService/server-login-api.ts 파일 보기

1
 import { Injectable } from "@angular/core";
1
 import { Injectable } from "@angular/core";
2
-import {RPCSocket} from 'rpclibrary/js/src/Frontend'
3
-import { Auth, User, _Class, FrontcraftFeatureIfc, SomeOf, FrontcraftIfc, } from '../../../../../backend/Types/Types'
2
+import { RPCSocket } from 'rpclibrary/js/src/Frontend'
3
+import { Auth, User, _Class, FrontcraftFeatureIfc, SomeOf, FrontcraftIfc, } from '../../../../../../backend/Types/Types'
4
 import { hash, IApiService, GuestUser } from './ApiService';
4
 import { hash, IApiService, GuestUser } from './ApiService';
5
-import { LoggerService } from './logger.service';
5
+import { LoggerService } from '../LoggerService/logger.service';
6
 import { ConnectedSocket } from 'rpclibrary';
6
 import { ConnectedSocket } from 'rpclibrary';
7
+import { async } from '@angular/core/testing';
7
 
8
 
8
 declare const Cookies
9
 declare const Cookies
9
 
10
 
10
 @Injectable()
11
 @Injectable()
11
-export class ServerApiService implements IApiService{
12
-    private socket:ConnectedSocket<FrontcraftIfc>
13
-    private auth:Auth
12
+export class ServerApiService implements IApiService {
13
+    private socket: ConnectedSocket<FrontcraftIfc>
14
+    private auth: Auth
14
     private privSocket: RPCSocket & SomeOf<FrontcraftFeatureIfc>
15
     private privSocket: RPCSocket & SomeOf<FrontcraftFeatureIfc>
15
 
16
 
16
     constructor(
17
     constructor(
17
         private logger: LoggerService
18
         private logger: LoggerService
18
-    ){}
19
+    ) { }
19
 
20
 
20
-    getUnprivilegedSocket = () : ConnectedSocket<FrontcraftIfc> => this.socket
21
+    getUnprivilegedSocket = (): ConnectedSocket<FrontcraftIfc> => this.socket
22
+
23
+    get = <K extends (keyof FrontcraftIfc | keyof FrontcraftFeatureIfc)>(feature: K):
24
+        K extends keyof FrontcraftIfc ? FrontcraftIfc[K] :
25
+        K extends keyof FrontcraftFeatureIfc ? (FrontcraftFeatureIfc[K] | void) :
26
+        never => {
21
 
27
 
22
-    get = <K extends (keyof FrontcraftIfc | keyof FrontcraftFeatureIfc)>(feature : K) : K extends keyof FrontcraftIfc?FrontcraftIfc[K]:
23
-                                                                                        K extends keyof FrontcraftFeatureIfc?(FrontcraftFeatureIfc[K] | void): 
24
-                                                                                        never => {
25
         //@ts-ignore
28
         //@ts-ignore
26
         return this.socket[feature]
29
         return this.socket[feature]
27
     }
30
     }
28
 
31
 
29
-    getCurrentUser = () : User => {
32
+    getCurrentUser = (): User => {
30
         return GuestUser
33
         return GuestUser
31
     }
34
     }
32
 
35
 
33
-    login = async (username: string, password: string) : Promise<RPCSocket & SomeOf<FrontcraftFeatureIfc>> => {
36
+    login = async (username: string, password: string): Promise<RPCSocket & SomeOf<FrontcraftFeatureIfc>> => {
34
         const pwHash = await hash(password)
37
         const pwHash = await hash(password)
35
         let auth
38
         let auth
36
-        try{
39
+        try {
37
             auth = await this.socket.UserManager.login(username, pwHash)
40
             auth = await this.socket.UserManager.login(username, pwHash)
38
-        }catch(e){
41
+        } catch (e) {
39
             return
42
             return
40
         }
43
         }
41
 
44
 
42
-        if(!auth){ 
45
+        if (!auth) {
43
             await this.logout()
46
             await this.logout()
44
             throw new Error("Login failed")
47
             throw new Error("Login failed")
45
         }
48
         }
51
 
54
 
52
     }
55
     }
53
 
56
 
54
-    async connectShoutbox(callback:Function) : Promise<Function>{
57
+    async connectShoutbox(callback: Function): Promise<Function> {
55
         return this.logger.log
58
         return this.logger.log
56
     }
59
     }
57
 
60
 
60
 
63
 
61
     logout = async () => {
64
     logout = async () => {
62
         Cookies.remove('token')
65
         Cookies.remove('token')
63
-        if(this.auth){
64
-            try{
66
+        if (this.auth) {
67
+            try {
65
                 await this.socket.UserManager.logout(this.auth.user.username, this.auth.token.value)
68
                 await this.socket.UserManager.logout(this.auth.user.username, this.auth.token.value)
66
-            }catch(e){
69
+            } catch (e) {
67
                 this.logger.warn(e);
70
                 this.logger.warn(e);
68
             }
71
             }
69
-        } 
72
+        }
70
 
73
 
71
-        if(this.privSocket) this.privSocket.destroy()
74
+        if (this.privSocket) this.privSocket.destroy()
72
         this.privSocket = null
75
         this.privSocket = null
73
-        this.auth  = null
76
+        this.auth = null
74
     }
77
     }
75
 
78
 
76
-    initialize = async () : Promise<any> => {
77
-        if(this.socket){
79
+    initialize = async (): Promise<any> => {
80
+        if (this.socket) {
78
             this.socket.destroy()
81
             this.socket.destroy()
79
             this.socket = null
82
             this.socket = null
80
         }
83
         }
81
 
84
 
82
-        try{
85
+        try {
83
             let conn = new RPCSocket<FrontcraftIfc>(20000, window.location.hostname)
86
             let conn = new RPCSocket<FrontcraftIfc>(20000, window.location.hostname)
84
             conn.on('close', async () => {
87
             conn.on('close', async () => {
85
-            })                        
88
+            })
86
 
89
 
87
             this.socket = await conn.connect()
90
             this.socket = await conn.connect()
88
-        }catch(e){
91
+        } catch (e) {
89
             this.logger.log(e);
92
             this.logger.log(e);
90
             throw new Error("Websocket cannot connect")
93
             throw new Error("Websocket cannot connect")
91
         }
94
         }
93
 
96
 
94
     getAuth = () => this.auth
97
     getAuth = () => this.auth
95
 
98
 
96
-    async checkLogin() : Promise<boolean>{
97
-        if(!this.auth) return false
99
+    async checkLogin(): Promise<boolean> {
100
+        if (!this.auth) return false
98
         const valid = this.socket.UserManager.checkToken(this.auth.token.value, this.auth.user.rank)
101
         const valid = this.socket.UserManager.checkToken(this.auth.token.value, this.auth.user.rank)
99
-        if(valid) return true
102
+        if (valid) return true
100
         await this.logout()
103
         await this.logout()
101
         return false
104
         return false
102
     }
105
     }

+ 10
- 0
src/frontend/src/app/frontcraft/services/LoggerService/LoggerService.ts 파일 보기

1
+export interface ILoggerService {
2
+    log,
3
+    warn,
4
+    error,
5
+    table,
6
+}
7
+
8
+export interface ICollapsableLoggerService extends ILoggerService{
9
+    collapsed
10
+}

+ 30
- 0
src/frontend/src/app/frontcraft/services/LoggerService/logger.service.ts 파일 보기

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

+ 21
- 0
src/frontend/src/app/frontcraft/services/flash-service.ts 파일 보기

1
+import { Injectable, Inject } from '@angular/core';
2
+import { DOCUMENT } from '@angular/common';
3
+
4
+@Injectable()
5
+export class FlashService {
6
+    private displaying = false
7
+    constructor(@Inject(DOCUMENT) private document: Document) { }
8
+
9
+    show(durationMs = 250) {
10
+        if (this.displaying) return
11
+        this.displaying = true
12
+        this.document.getElementById('glowbox').classList.toggle('glowing');
13
+        this.document.getElementById('glowbox').classList.toggle('not-glowing');
14
+
15
+        setTimeout(() => {
16
+            this.displaying = false
17
+            this.document.getElementById('glowbox').classList.toggle('glowing');
18
+            this.document.getElementById('glowbox').classList.toggle('not-glowing');
19
+        }, durationMs)
20
+    }
21
+}

+ 0
- 37
src/frontend/src/app/frontcraft/services/logger.service.ts 파일 보기

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
-}

+ 52
- 27
src/frontend/src/index.html 파일 보기

1
 <!doctype html>
1
 <!doctype html>
2
 <html>
2
 <html>
3
+
3
 <head>
4
 <head>
4
   <meta charset="utf-8">
5
   <meta charset="utf-8">
5
   <title>Frontcraft</title>
6
   <title>Frontcraft</title>
6
   <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Montserrat">
7
   <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Montserrat">
7
   <style>
8
   <style>
8
-  @import url('https://fonts.googleapis.com/css?family=Montserrat');
9
-
10
-  .loadTitle {
11
-    font-family: 'Montserrat';
12
-    text-align: center;
13
-    color: #FFF;
14
-    display: flex;
15
-    flex-direction: column;
16
-    align-items: center;
17
-    justify-content: center;
18
-    letter-spacing: 1px;
19
-    padding-top: calc(50vh - 120px);
20
-  }
21
-
22
-  .loadH {
23
-    background-image: url('https://media.giphy.com/media/26BROrSHlmyzzHf3i/giphy.gif');
24
-    background-size: cover;
25
-    color: transparent;
26
-    background-clip: text;
27
-    -moz-background-clip: text;
28
-    -webkit-background-clip: text;
29
-    text-transform: uppercase;
30
-    font-size: min(10vw, 120px);
31
-    margin: 10px 0;
32
-  }
9
+    @import url('https://fonts.googleapis.com/css?family=Montserrat');
10
+
11
+    .loadTitle {
12
+      font-family: 'Montserrat';
13
+      text-align: center;
14
+      color: #FFF;
15
+      display: flex;
16
+      flex-direction: column;
17
+      align-items: center;
18
+      justify-content: center;
19
+      letter-spacing: 1px;
20
+      padding-top: calc(50vh - 120px);
21
+    }
22
+
23
+    .loadH {
24
+      background-image: url('https://media.giphy.com/media/26BROrSHlmyzzHf3i/giphy.gif');
25
+      background-size: cover;
26
+      color: transparent;
27
+      background-clip: text;
28
+      -moz-background-clip: text;
29
+      -webkit-background-clip: text;
30
+      text-transform: uppercase;
31
+      font-size: min(10vw, 120px);
32
+      margin: 10px 0;
33
+    }
34
+
35
+    #glowbox {
36
+      pointer-events: none;
37
+      z-index: 10000000;
38
+      position: absolute;
39
+      width: 100%;
40
+      height: 100%;
41
+      -webkit-box-shadow: inset 0px 33px 38px -30px rgba(255, 255, 255, 0.71);
42
+      -moz-box-shadow: inset 0px 33px 38px -30px rgba(255, 255, 255, 0.71);
43
+      box-shadow: inset 0px 33px 38px -30px rgba(255, 255, 255, 0.71);
44
+    }
45
+
46
+    #glowbox.not-glowing {
47
+      opacity: 0;
48
+      transition: opacity 0.25s; 
49
+    }
50
+
51
+    #glowbox.glowing {
52
+      opacity: 1;
53
+      transition: opacity 0.25s; 
54
+    }
33
   </style>
55
   </style>
34
 
56
 
35
   <base href="/">
57
   <base href="/">
38
   <link rel="icon" type="image/png" href="favicon.png">
60
   <link rel="icon" type="image/png" href="favicon.png">
39
   <link rel="icon" type="image/x-icon" href="favicon.ico">
61
   <link rel="icon" type="image/x-icon" href="favicon.ico">
40
 </head>
62
 </head>
63
+
41
 <body>
64
 <body>
65
+  <div id="glowbox" class="not-glowing"></div>
42
   <ngx-app></ngx-app>
66
   <ngx-app></ngx-app>
43
   <div id="nb-global-spinner" class="spinner" style="background-color: #111; height: 100vh;">
67
   <div id="nb-global-spinner" class="spinner" style="background-color: #111; height: 100vh;">
44
     <div class="loadTitle">
68
     <div class="loadTitle">
45
       <h1 class="loadH">Tranquil</h1>
69
       <h1 class="loadH">Tranquil</h1>
46
     </div>
70
     </div>
47
   </div>
71
   </div>
48
-  
72
+
49
 </body>
73
 </body>
50
-</html>
74
+
75
+</html>

+ 3
- 3
src/frontend/src/main.server.ts 파일 보기

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

+ 3
- 3
src/frontend/src/main.ts 파일 보기

8
 
8
 
9
 import { FrontcraftAppModule } from './app/app.module';
9
 import { FrontcraftAppModule } from './app/app.module';
10
 import { environment } from './environments/environment';
10
 import { environment } from './environments/environment';
11
-import { IApiService } from "./app/frontcraft/services/ApiService"
12
-import { ClientApiService } from './app/frontcraft/services/client-login-api';
13
-import { LoggerService } from './app/frontcraft/services/logger.service';
11
+import { IApiService } from "./app/frontcraft/services/ApiService/ApiService"
12
+import { ClientApiService } from './app/frontcraft/services/ApiService/client-login-api';
13
+import { LoggerService } from './app/frontcraft/services/LoggerService/logger.service';
14
 
14
 
15
 if (environment.production) {
15
 if (environment.production) {
16
   enableProdMode();
16
   enableProdMode();

Loading…
취소
저장