peter 5 роки тому
джерело
коміт
e3eb1f123c
29 змінених файлів з 374 додано та 88 видалено
  1. 1
    1
      src/backend/Admin/Admin.ts
  2. 2
    2
      src/backend/Components/Item/Interface.ts
  3. 20
    4
      src/backend/Components/Item/ItemManager.ts
  4. 1
    0
      src/backend/Components/Raid/Interface.ts
  5. 1
    0
      src/backend/Components/Raid/RPCInterface.ts
  6. 105
    15
      src/backend/Components/Raid/RaidManager.ts
  7. 2
    0
      src/backend/Types/Types.ts
  8. 5
    1
      src/frontend/src/app/@theme/components/header/header.component.ts
  9. 2
    0
      src/frontend/src/app/frontcraft/pages/character/character.component.html
  10. 4
    1
      src/frontend/src/app/frontcraft/pages/character/character.component.ts
  11. 2
    0
      src/frontend/src/app/frontcraft/pages/characters/characters.component.html
  12. 0
    4
      src/frontend/src/app/frontcraft/pages/pages-layout.component.ts
  13. 0
    4
      src/frontend/src/app/frontcraft/pages/pages-routing.module.ts
  14. 20
    13
      src/frontend/src/app/frontcraft/pages/raid/archive.component.ts
  15. 104
    14
      src/frontend/src/app/frontcraft/pages/raid/raid.component.html
  16. 61
    8
      src/frontend/src/app/frontcraft/pages/raid/raid.component.ts
  17. 1
    1
      src/frontend/src/app/frontcraft/pages/rules/rules.component.html
  18. 21
    17
      src/frontend/src/app/frontcraft/pages/shop/buytoken.component.ts
  19. BIN
      src/frontend/src/assets/images/dwarf.png
  20. BIN
      src/frontend/src/assets/images/dwarf_xs.gif
  21. BIN
      src/frontend/src/assets/images/gnome.png
  22. BIN
      src/frontend/src/assets/images/gnome_xs.gif
  23. BIN
      src/frontend/src/assets/images/human.png
  24. BIN
      src/frontend/src/assets/images/human_xs.gif
  25. BIN
      src/frontend/src/assets/images/night elf.png
  26. BIN
      src/frontend/src/assets/images/night elf_xs.gif
  27. BIN
      src/frontend/src/assets/images/team.png
  28. BIN
      src/frontend/src/assets/images/warlock.png
  29. 22
    3
      test/backendTest.ts

+ 1
- 1
src/backend/Admin/Admin.ts Переглянути файл

@@ -56,7 +56,7 @@ implements TableDefinitionExporter, IAdmin {
56 56
                         connection: {
57 57
                             filename: Path.join(__dirname, "data/frontworkAdmin.sqlite")
58 58
                         },
59
-                        useNullAsDefault: true
59
+                        useNullAsDefault: true,
60 60
                     }
61 61
                 }   
62 62
             }

+ 2
- 2
src/backend/Components/Item/Interface.ts Переглянути файл

@@ -7,8 +7,8 @@ export class IItemManager{
7 7
     setPriority: (itemname:string, priority: any) => Promise<void>
8 8
     calculatePriorities: (itemname: string, character:Character) => Promise<number>
9 9
     deletePriority: (priority:SRPriority) => Promise<void>
10
-    getTokens: (character:Character) => Promise<SRToken[]>
11
-    getToken: (character:Character, item:Item) => Promise<(SRToken & Character & Item) | void>
10
+    getTokens: (character:Character, valid?:boolean) => Promise<SRToken[]>
11
+    getToken: (character:Character, item:Item, valid?:boolean) => Promise<(SRToken & Character & Item) | void>
12 12
     getAllPriorities: () => Promise<(SRPriority & Spec & Item)[]>
13 13
     wipeCurrencyAndItems: () => Promise<void>
14 14
 }

+ 20
- 4
src/backend/Components/Item/ItemManager.ts Переглянути файл

@@ -146,18 +146,27 @@ implements FrontworkComponent<ItemManagerIfc, ItemManagerFeatureIfc>, TableDefin
146 146
             if(matchingtoken){
147 147
                 //update signupid and increment level
148 148
                 
149
-                console.log("delete shadow tokens");
149
+                
150 150
 
151 151
                 await this.admin
152 152
                 .knex('tokens')
153
+                .where({
154
+                    characterid: character.id,
155
+                    itemname: item.itemname
156
+                })
153 157
                 .update({
154 158
                     signupid: signup.id,
155 159
                     level: matchingtoken.level+1
156 160
                 })
161
+                
162
+                await this.admin
163
+                .knex('tokens')
157 164
                 .where({
158 165
                     characterid: character.id,
159
-                    itemname: item.itemname
160
-                })
166
+                    itemname: item.itemname,
167
+                    signupid: null
168
+                }).del()
169
+                
161 170
                 return await this.getToken(character, item)
162 171
             }
163 172
         }
@@ -248,7 +257,7 @@ implements FrontworkComponent<ItemManagerIfc, ItemManagerFeatureIfc>, TableDefin
248 257
         }).reduce((prev, curr) => prev+curr, 0)
249 258
     }
250 259
 
251
-    getToken = async (character:Character, item:Item): Promise<(SRToken & Character & Item) | void>=> {
260
+    getToken = async (character:Character, item:Item,valid=true): Promise<(SRToken & Character & Item) | void>=> {
252 261
         return await this.admin
253 262
         .knex('tokens as t')
254 263
         .select('*')
@@ -258,6 +267,13 @@ implements FrontworkComponent<ItemManagerIfc, ItemManagerFeatureIfc>, TableDefin
258 267
             characterid: character.id,
259 268
             "i.itemname": item.itemname
260 269
         })
270
+        .andWhere(function(){
271
+            if(valid){
272
+                this.whereNotNull('t.signupid')
273
+            }else{
274
+                this.whereNull('t.signupid')
275
+            }
276
+        })
261 277
         .first()
262 278
     }
263 279
 

+ 1
- 0
src/backend/Components/Raid/Interface.ts Переглянути файл

@@ -14,4 +14,5 @@ export class IRaidManager{
14 14
     getPastRaids: (limit: number) => Promise<RaidData[]>
15 15
     getArchiveRaid: (id:number) => Promise<RaidData>
16 16
     startRaid: (raid:Raid) => Promise<RaidData>
17
+    adminUnsign: (character:Character, raid:Raid) => Promise<any>
17 18
 }

+ 1
- 0
src/backend/Components/Raid/RPCInterface.ts Переглянути файл

@@ -17,6 +17,7 @@ export type RaidManagerFeatureIfc = {
17 17
         archiveRaid: IRaidManager['archiveRaid']
18 18
         setBenched: IRaidManager['setBenched']
19 19
         startRaid: IRaidManager['startRaid']
20
+        adminUnsign: IRaidManager['adminUnsign']
20 21
     }
21 22
     signup: {
22 23
         getSignups: IRaidManager['getSignups']

+ 105
- 15
src/backend/Components/Raid/RaidManager.ts Переглянути файл

@@ -7,6 +7,9 @@ import { IRaidManager } from "./Interface";
7 7
 import { IUserManager } from "../User/Interface";
8 8
 import { ICharacterManager } from "../Character/Interface";
9 9
 import { _Tiers } from "../../Types/Items";
10
+import { IItemManager } from "../Item/Interface";
11
+import { ItemManager } from "../Item/ItemManager";
12
+import { SpecT } from "../../Types/PlayerSpecs";
10 13
 
11 14
 @Injectable(IRaidManager)
12 15
 export class RaidManager
@@ -22,6 +25,9 @@ implements FrontworkComponent<RaidManagerIfc, RaidManagerFeatureIfc>, IRaidManag
22 25
     @Inject(ICharacterManager)
23 26
     private characterManager: ICharacterManager
24 27
 
28
+    @Inject(ItemManager)
29
+    private itemManager: IItemManager
30
+
25 31
     exportRPCs = () => [
26 32
         this.getRaids,
27 33
         this.getRaidData,
@@ -38,7 +44,8 @@ implements FrontworkComponent<RaidManagerIfc, RaidManagerFeatureIfc>, IRaidManag
38 44
                 this.removeSignup,
39 45
                 this.archiveRaid,
40 46
                 this.setBenched,
41
-                this.startRaid
47
+                this.startRaid,
48
+                this.adminUnsign
42 49
             ]
43 50
         },{
44 51
             name: 'signup' as 'signup',
@@ -136,15 +143,20 @@ implements FrontworkComponent<RaidManagerIfc, RaidManagerFeatureIfc>, IRaidManag
136 143
 
137 144
     archiveRaid = async (raid:Raid) : Promise<RaidData> => {
138 145
         const raidData = await this.getRaidData(raid)
146
+
147
+        const tx = await this.admin.knex.transaction()
148
+
139 149
         await this.admin.knex('archive')
150
+        .transacting(tx)
140 151
         .insert({
141 152
             id:raidData.id,
142 153
             raiddata: JSON.stringify(raidData)
143 154
         })       
144 155
 
145 156
         await Promise.all(
146
-            Object.values(raidData.participants).flat().flatMap((signup) =>  this.admin
157
+            Object.values(raidData.participants).flat().flatMap((signup) => this.admin
147 158
                 .knex('tokens')
159
+                .transacting(tx)
148 160
                 .where({
149 161
                     characterid: signup.characterid,
150 162
                     signupid: null
@@ -153,8 +165,11 @@ implements FrontworkComponent<RaidManagerIfc, RaidManagerFeatureIfc>, IRaidManag
153 165
         ))
154 166
 
155 167
         await this.admin.knex('raids')
168
+        .transacting(tx)
156 169
         .where('id', '=', raid.id)
157 170
         .del()
171
+        await tx.commit()
172
+
158 173
     
159 174
         const row = await this.admin.knex('archive')
160 175
         .select('*')
@@ -162,7 +177,6 @@ implements FrontworkComponent<RaidManagerIfc, RaidManagerFeatureIfc>, IRaidManag
162 177
             id:raidData.id,
163 178
         })
164 179
         .first()
165
-
166 180
         return JSON.parse(row.raiddata)
167 181
     }
168 182
 
@@ -184,7 +198,7 @@ implements FrontworkComponent<RaidManagerIfc, RaidManagerFeatureIfc>, IRaidManag
184 198
     }
185 199
 
186 200
     getRaidData = async (raid:Raid) : Promise<RaidData> => {
187
-        const ret = {
201
+        const raiddata = {
188 202
             participants:{
189 203
                 Druid: <(Signup&Character&Spec)[]>[],
190 204
                 Hunter: <(Signup&Character&Spec)[]>[],
@@ -198,8 +212,11 @@ implements FrontworkComponent<RaidManagerIfc, RaidManagerFeatureIfc>, IRaidManag
198 212
                 late: <(Signup&Character&Spec)[]>[],
199 213
                 bench: <(Signup&Character&Spec)[]>[],
200 214
             },
201
-            tokens:{}
215
+            tokens:{},
216
+            healers:<(Signup&Character&Spec)[]>[],
217
+            tanks:<(Signup&Character&Spec)[]>[]
202 218
         }
219
+        const tx = await this.admin.knex.transaction()
203 220
 
204 221
         const subQuery = this.admin
205 222
         .knex('signups')
@@ -211,14 +228,17 @@ implements FrontworkComponent<RaidManagerIfc, RaidManagerFeatureIfc>, IRaidManag
211 228
         })
212 229
         .as('signupcount')
213 230
 
231
+
214 232
         const raidInDb: Raid = await this.admin.knex('raids')
215 233
         .select('*', subQuery)
234
+        .transacting(tx)
216 235
         .where('id','=',raid.id)
217 236
         .first()
218 237
 
219 238
         const characterData: (Signup & Character & Spec)[] = await this.admin
220 239
         .knex('signups as s')
221
-        .select('s.id as id', 'charactername', 'class', 'specname', 'race', 'userid', 'benched', 'late', 'raidid', 'characterid')
240
+        .transacting(tx)
241
+        .select('s.id as id', 'charactername', 'class', 'specid', 'specname', 'race', 'userid', 'benched', 'late', 'raidid', 'characterid', 'specid')
222 242
         .join('raids as r', 's.raidid','=','r.id')
223 243
         .join('characters as c', 's.characterid','=','c.id')
224 244
         .join('users as u', 'c.userid','=','u.id')
@@ -227,18 +247,19 @@ implements FrontworkComponent<RaidManagerIfc, RaidManagerFeatureIfc>, IRaidManag
227 247
         
228 248
         characterData.forEach(data => {
229 249
             if(data.benched){
230
-                ret.participants.bench.push(data)
250
+                raiddata.participants.bench.push(data)
231 251
                 return
232 252
             }
233 253
             if(data.late){
234
-                ret.participants.late.push(data)
254
+                raiddata.participants.late.push(data)
235 255
                 return
236 256
             }
237
-            ret.participants[data.class].push(data)
257
+            raiddata.participants[data.class].push(data)
238 258
         })
239 259
 
240 260
         const tokenData: (Character & SRToken & Item)[] = await this.admin
241 261
         .knex('signups as s')
262
+        .transacting(tx)
242 263
         .select('*', 's.id as id')
243 264
         .join('raids as r', 's.raidid','=','r.id')
244 265
         .where('r.id','=',raid.id)
@@ -249,14 +270,33 @@ implements FrontworkComponent<RaidManagerIfc, RaidManagerFeatureIfc>, IRaidManag
249 270
         .join('tokens as t', 't.characterid','=','c.id')
250 271
         .join('items as i', 'i.itemname','=','t.itemname')
251 272
 
273
+        await tx.commit()
274
+
252 275
         tokenData.forEach(data => {
253
-            if(!ret.tokens[data.itemname])
254
-                ret.tokens[data.itemname] = []
255
-            ret.tokens[data.itemname].push(data)
276
+            if(!raiddata.tokens[data.itemname])
277
+                raiddata.tokens[data.itemname] = []
278
+            raiddata.tokens[data.itemname].push(data)
256 279
         })
280
+
281
+        raiddata.tanks = Object.values(raiddata.participants).flatMap(
282
+            (tanks:any[]) => tanks.filter((p:any) => 
283
+                !p.benched 
284
+                && !p.late 
285
+                && (p.specname==="Protection" 
286
+                    || p.specname==="Feral (Tank)"))
287
+        )
288
+        raiddata.healers = Object.values(raiddata.participants).flatMap(
289
+            (healers:any[]) => healers.filter((p:any) => 
290
+                !p.benched 
291
+                && !p.late 
292
+                && (p.specname==="Holy" 
293
+                    || p.specname==="Discipline" 
294
+                    || p.specname==="Restoration"))
295
+        )
296
+
257 297
         return {
258 298
             ...raidInDb,
259
-            ...ret
299
+            ...raiddata
260 300
         }
261 301
     }
262 302
     
@@ -273,9 +313,11 @@ implements FrontworkComponent<RaidManagerIfc, RaidManagerFeatureIfc>, IRaidManag
273 313
         if(!maybeUserRecord || maybeUserRecord.user.id != character.userid){
274 314
             throw new Error("Bad Usertoken")
275 315
         }
316
+        const tx = await this.admin.knex.transaction()
276 317
 
277 318
         const exists = await this.admin
278 319
         .knex('signups')
320
+        .transacting(tx)
279 321
         .select('*')
280 322
         .where({
281 323
             raidid: raid.id!,
@@ -286,20 +328,28 @@ implements FrontworkComponent<RaidManagerIfc, RaidManagerFeatureIfc>, IRaidManag
286 328
         if(!exists){
287 329
             await this.admin
288 330
             .knex('signups')
331
+            .transacting(tx)
289 332
             .insert({
290 333
                 raidid: raid.id!,
291 334
                 characterid: character.id!,
292
-                late: late
335
+                late: late,
336
+                benched: false,
293 337
             })
294 338
         }else{
295 339
             await this.admin
296 340
             .knex('signups')
341
+            .transacting(tx)
342
+            .where({
343
+                id: exists.id 
344
+            })
297 345
             .update({
298 346
                 raidid: raid.id!,
299 347
                 characterid: character.id!,
300
-                late: late
348
+                late: late,
349
+                benched: false,
301 350
             })
302 351
         }
352
+        await tx.commit()
303 353
 
304 354
         return await this.admin
305 355
         .knex('signups')
@@ -317,6 +367,46 @@ implements FrontworkComponent<RaidManagerIfc, RaidManagerFeatureIfc>, IRaidManag
317 367
             throw new Error("Bad Usertoken")
318 368
         }
319 369
 
370
+        return await this.adminUnsign(character, raid)       
371
+    }
372
+
373
+    adminUnsign = async (character:Character, raid:Raid) => {
374
+        
375
+        const user = await this.characterManager.getUserOfCharacter(character)
376
+
377
+        const signup = await this.admin.knex('signups as si')
378
+        .where({
379
+            "si.raidid": raid.id!,
380
+            "si.characterid": character.id!,
381
+        }).first()
382
+
383
+        const tokens = await this.admin.knex('tokens as t')
384
+        .where('t.signupid', signup.id)
385
+        
386
+        //check if token has to be deleted
387
+        Promise.all(
388
+            tokens.map(async token => {
389
+                await this.userManager.incrementCurrency(user, 1)       
390
+                const prio = await this.itemManager.calculatePriorities(token.itemname, character)
391
+                if(token.level <= prio+1){
392
+                    await this.admin.knex('tokens')
393
+                    .where({
394
+                        characterid: character.id,
395
+                        itemname: token.itemname
396
+                    }).del()
397
+                }else{
398
+                    await this.admin.knex('tokens')
399
+                    .where({
400
+                        characterid: character.id,
401
+                        itemname: token.itemname
402
+                    }).update({
403
+                        signupid: null,
404
+                        level: token.level-1
405
+                    })
406
+                }
407
+            })
408
+        )
409
+
320 410
         await this.admin.knex('signups')
321 411
         .where({
322 412
             raidid: raid.id!,

+ 2
- 0
src/backend/Types/Types.ts Переглянути файл

@@ -58,6 +58,8 @@ export type RaidData = Raid & {
58 58
     tokens: {
59 59
         [itemname in string]: (Character & SRToken & Item)[]
60 60
     }
61
+    tanks: (Signup & Character & Spec)[] 
62
+    healers: (Signup & Character & Spec)[] 
61 63
 }
62 64
 
63 65
 export type SRToken = {

+ 5
- 1
src/frontend/src/app/@theme/components/header/header.component.ts Переглянути файл

@@ -73,8 +73,12 @@ export class HeaderComponent implements OnInit, OnDestroy {
73 73
 
74 74
     this.api.connectShoutbox((msg) => {
75 75
       this.chatlog.push(msg)
76
-      if(msg.message != this.lastmessage)
76
+      msg['reply']=false
77
+
78
+      if(msg.message != this.lastmessage){
77 79
         this.newmessage = true
80
+        msg['reply']=true
81
+      }
78 82
       if(this.chatwindow) this.chatwindow.messages.push(msg)
79 83
     }).then(sendMsg => {
80 84
       this.sendMessage = (msg) => {

+ 2
- 0
src/frontend/src/app/frontcraft/pages/character/character.component.html Переглянути файл

@@ -15,7 +15,9 @@ status="control">
15 15
     </nb-card-header>
16 16
 
17 17
     <nb-card-body>
18
+        <img style="width:20px; height:20px" [src]="'../../../../assets/images/'+char.race.toLowerCase()+'_xs.gif'" />
18 19
         {{char.race}}<br />
20
+        <img style="width:20px; height:20px" [src]="'../../../../assets/images/'+char.class.toLowerCase()+'.png'" />
19 21
         {{char.specname}} {{char.class}}<br />
20 22
         <span *ngIf="link === 'owner'">
21 23
             Owned by <a [routerLink]="'/frontcraft/user/'+char.username"> {{char.username}} ({{char.rank}})</a>

+ 4
- 1
src/frontend/src/app/frontcraft/pages/character/character.component.ts Переглянути файл

@@ -13,7 +13,10 @@ export class FrontcraftCharacterComponent implements OnInit{
13 13
     @Input() name?: string
14 14
     @Input() link?: "owner" | "character" = 'owner'
15 15
 
16
-    char : (Character & User & Spec) = {} as any
16
+    char : (Character & User & Spec) = {
17
+      race: 'Human',
18
+      class: 'Warrior'
19
+    } as any
17 20
     color : string
18 21
     tokens
19 22
 

+ 2
- 0
src/frontend/src/app/frontcraft/pages/characters/characters.component.html Переглянути файл

@@ -17,12 +17,14 @@
17 17
                         </a>
18 18
                     </td>
19 19
                     <td>
20
+                        <img style="width:20px; height:20px" [src]="'../../../../assets/images/'+character.race.toLowerCase()+'_xs.gif'" />
20 21
                         {{character.race}}
21 22
                     </td>
22 23
                     <td>
23 24
                         {{character.specname}}
24 25
                     </td>
25 26
                     <td>
27
+                        <img style="width:20px; height:20px" [src]="'../../../../assets/images/'+character.class.toLowerCase()+'.png'" />
26 28
                         {{character.class}}
27 29
                     </td>
28 30
                 </tr>

+ 0
- 4
src/frontend/src/app/frontcraft/pages/pages-layout.component.ts Переглянути файл

@@ -22,10 +22,6 @@ export class PagesLayoutComponent implements AfterContentInit{
22 22
     icon: 'people',
23 23
     title: 'Characters',
24 24
     link: '/frontcraft/characters',
25
-  },{
26
-    icon: 'shopping-cart',
27
-    title: 'Token Shop',
28
-    link: '/frontcraft/shop',
29 25
   },{
30 26
     icon: 'book-open-outline',
31 27
     title: 'Loot Rules',

+ 0
- 4
src/frontend/src/app/frontcraft/pages/pages-routing.module.ts Переглянути файл

@@ -39,10 +39,6 @@ export const routes: Routes = [
39 39
                 path: 'characters',
40 40
                 component: FrontcraftCharactersComponent,
41 41
             },
42
-            {
43
-                path: 'shop',
44
-                component: FrontcraftShopComponent
45
-            },
46 42
             {
47 43
                 path: 'rules',
48 44
                 component: FrontcraftRulesComponent

+ 20
- 13
src/frontend/src/app/frontcraft/pages/raid/archive.component.ts Переглянути файл

@@ -27,8 +27,13 @@ export class FrontcraftArchiveComponent implements OnInit{
27 27
           Warlock: [],
28 28
           Warrior: [],
29 29
       },
30
-      tokens:{}
30
+      tokens:{},
31
+      tanks:[],
32
+      healers: []
31 33
     }
34
+    tokens = {}
35
+    displayedtokens = {}
36
+    search = ""
32 37
     
33 38
     constructor(
34 39
       private api: ApiService,
@@ -46,19 +51,21 @@ export class FrontcraftArchiveComponent implements OnInit{
46 51
       const raidManager = this.api.get('RaidManager')
47 52
       const raiddata = await raidManager.getArchiveRaid(parseInt(param))
48 53
       this.raid = raiddata
54
+      this.tokens = raiddata.tokens;
49 55
 
50
-      Object.values(raiddata.participants).flat().forEach(p => {
56
+      [
57
+        ...raiddata.tanks, 
58
+        ...raiddata.healers, 
59
+        ...Object.values(raiddata.participants).flat()
60
+      ].forEach(p => {
51 61
         p['color'] = getClassColor(p.class)
52 62
       })
53
-      
54
-      const matchingSignup = Object.values(raiddata.participants).flat().find(char => char.userid === this.api.getCurrentUser()!.id!)
55
-      if(matchingSignup){
56
-        this.isSignedup = true
57
-        this.mySignup = matchingSignup
58
-        this.mySignup.status = matchingSignup['benched']?'Bench':matchingSignup['late']?'Late':'Attending'
59
-      }else{
60
-        this.isSignedup = false
61
-        this.mySignup = null
62
-      }
63
-    } 
63
+
64
+      this.changeSearch()
65
+    }
66
+
67
+    changeSearch = () => {
68
+      this.tokens = this.raid.tokens;
69
+      this.displayedtokens = this.raid.tokens;
70
+    }
64 71
 }

+ 104
- 14
src/frontend/src/app/frontcraft/pages/raid/raid.component.html Переглянути файл

@@ -17,14 +17,32 @@
17 17
                             Status: {{mySignup.status}}
18 18
                         </p>
19 19
                         
20
+                        <button
21
+                            (click)="setLate(true)"
22
+                            *ngIf="mySignup.status !== 'Late'"
23
+                            nbButton 
24
+                            outline 
25
+                            status="warning" 
26
+                            size="medium">
27
+                            <nb-icon icon="clock-outline"></nb-icon> Late
28
+                        </button>        
29
+                        <button
30
+                            (click)="setLate(false)"
31
+                            *ngIf="mySignup.status === 'Late'"
32
+                            nbButton 
33
+                            outline 
34
+                            status="success" 
35
+                            size="medium">
36
+                            <nb-icon icon="checkmark-outline"></nb-icon> On Time
37
+                        </button>  
20 38
                         <button
21 39
                             (click)="unsign()"
22 40
                             nbButton 
23 41
                             outline 
24 42
                             status="danger" 
25 43
                             size="medium">
26
-                            unsign
27
-                        </button>                    
44
+                            <nb-icon icon="close"></nb-icon>unsign
45
+                        </button>               
28 46
                     </div>
29 47
                     <div *ngIf="!isSignedup">
30 48
                         <button
@@ -33,7 +51,7 @@
33 51
                             outline 
34 52
                             status="success" 
35 53
                             size="medium">
36
-                            signup
54
+                            <nb-icon icon="person-done-outline"></nb-icon> sign up
37 55
                         </button>                     
38 56
                     </div>
39 57
                 </div>
@@ -44,6 +62,74 @@
44 62
               badgePosition="top right"
45 63
               [badgeStatus]="raid.signupcount<40?'warning':'success'">
46 64
                 <div class="row">
65
+                    <nb-card
66
+                    class="col-12 col-md-6" 
67
+                    *ngIf="raid.tanks.length > 0">
68
+                        <nb-card-header>Tanks ({{raid.tanks.length}})</nb-card-header>
69
+                        <nb-card-body>
70
+                            <div *ngFor="let participant of raid.tanks">
71
+                                <button
72
+                                    (click)="setBench(participant)"
73
+                                    *ngIf="manageRaid" 
74
+                                    nbButton 
75
+                                    outline 
76
+                                    status="warning" 
77
+                                    size="tiny">
78
+                                    B
79
+                                </button>
80
+                                <button
81
+                                    (click)="adminUnsign(participant)"
82
+                                    *ngIf="manageRaid" 
83
+                                    nbButton 
84
+                                    outline 
85
+                                    status="danger" 
86
+                                    size="tiny">
87
+                                    X
88
+                                </button>
89
+                                <a [ngStyle]="{'color': participant.color}" style="text-transform: capitalize;" 
90
+                                [routerLink]="'/frontcraft/character/'+participant.charactername">
91
+                                <img style="width:20px; height:20px" [src]="'../../../../assets/images/'+participant.race.toLowerCase()+'_xs.gif'" />
92
+                                <img style="width:20px; height:20px" [src]="'../../../../assets/images/'+participant.class.toLowerCase()+'.png'" />
93
+                                {{ participant.charactername }}
94
+                                </a>
95
+                            </div>
96
+                        </nb-card-body>
97
+                    </nb-card>
98
+
99
+                    <nb-card
100
+                    class="col-12 col-md-6" 
101
+                    *ngIf="raid.tanks.length > 0">
102
+                        <nb-card-header>Healers ({{raid.healers.length}})</nb-card-header>
103
+                        <nb-card-body>
104
+                            <div *ngFor="let participant of raid.healers">
105
+                                <button
106
+                                    (click)="setBench(participant)"
107
+                                    *ngIf="manageRaid" 
108
+                                    nbButton 
109
+                                    outline 
110
+                                    status="warning" 
111
+                                    size="tiny">
112
+                                    B
113
+                                </button>
114
+                                <button
115
+                                    (click)="adminUnsign(participant)"
116
+                                    *ngIf="manageRaid" 
117
+                                    nbButton 
118
+                                    outline 
119
+                                    status="danger" 
120
+                                    size="tiny">
121
+                                    X
122
+                                </button>
123
+                                <a [ngStyle]="{'color': participant.color}" style="text-transform: capitalize;" 
124
+                                [routerLink]="'/frontcraft/character/'+participant.charactername">
125
+                                <img style="width:20px; height:20px" [src]="'../../../../assets/images/'+participant.race.toLowerCase()+'_xs.gif'" />
126
+                                <img style="width:20px; height:20px" [src]="'../../../../assets/images/'+participant.class.toLowerCase()+'.png'" />
127
+                                {{ participant.charactername }}
128
+                                </a>
129
+                            </div>
130
+                        </nb-card-body>
131
+                    </nb-card>
132
+
47 133
                     <ng-container *ngFor="let group of raid.participants | keyvalue">
48 134
                         <nb-card
49 135
                         class="col-12 col-md-6 col-xl-4" 
@@ -60,8 +146,19 @@
60 146
                                         size="tiny">
61 147
                                         B
62 148
                                     </button>
149
+                                    <button
150
+                                        (click)="adminUnsign(participant)"
151
+                                        *ngIf="manageRaid" 
152
+                                        nbButton 
153
+                                        outline 
154
+                                        status="danger" 
155
+                                        size="tiny">
156
+                                        X
157
+                                    </button>
63 158
                                     <a [ngStyle]="{'color': participant.color}" style="text-transform: capitalize;" 
64 159
                                     [routerLink]="'/frontcraft/character/'+participant.charactername">
160
+                                    <img style="width:20px; height:20px" [src]="'../../../../assets/images/'+participant.race.toLowerCase()+'_xs.gif'" />
161
+                                    <img style="width:20px; height:20px" [src]="'../../../../assets/images/'+participant.class.toLowerCase()+'.png'" />
65 162
                                     {{ participant.charactername }}
66 163
                                     </a>
67 164
                                 </div>
@@ -70,12 +167,14 @@
70 167
                     </ng-container>
71 168
                 </div>
72 169
             </nb-tab>
73
-            <nb-tab tabTitle="Shop">
170
+            <nb-tab tabTitle="Shop" *ngIf="isSignedup">
74 171
                 <shop (onSelect)="itemSelect($event)"></shop>
75 172
             </nb-tab>
76 173
             <nb-tab tabTitle="Reserves">
174
+                <input type="text" nbInput [(ngModel)]="search" (change)="changeSearch()" placeholder="Search" fullWidth="true">
175
+
77 176
                 <nb-list>
78
-                    <nb-list-item *ngFor="let item of raid.tokens | keyvalue">
177
+                    <nb-list-item *ngFor="let item of displayedtokens | keyvalue">
79 178
                         <a [ngStyle]="{'color':item.value[0].quality=='Epic'?'#a335ee':'#ff8000'}" 
80 179
                            target="_blank" 
81 180
                            [href]="item.value[0].url">
@@ -104,15 +203,6 @@
104 203
                     size="medium">
105 204
                     start
106 205
                 </button>
107
-
108
-                <button
109
-                    (click)="archiveRaid(raid)"
110
-                    nbButton 
111
-                    outline 
112
-                    status="danger" 
113
-                    size="medium">
114
-                    archive
115
-                </button>
116 206
             </nb-tab>
117 207
         </nb-tabset>
118 208
     </nb-card-body>

+ 61
- 8
src/frontend/src/app/frontcraft/pages/raid/raid.component.ts Переглянути файл

@@ -1,10 +1,10 @@
1 1
 import { Component, OnInit } from '@angular/core';
2 2
 import { ActivatedRoute, Router } from '@angular/router';
3 3
 import { ApiService as ApiService } from '../../services/login-api';
4
-import { RaidData, Raid, Signup } from '../../../../../../backend/Types/Types';
4
+import { RaidData, Raid, Signup, Character, Spec, Item, SRToken } from '../../../../../../backend/Types/Types';
5 5
 import { NbWindowService, NbToastrService, NbDialogService } from '@nebular/theme';
6 6
 import { FrontcraftCharacerpickerComponent } from './characterpicker.component';
7
-import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
7
+import { getClassColor, SpecT } from '../../../../../../backend/Types/PlayerSpecs';
8 8
 import { FrontcraftBuyTokenComponent } from '../shop/buytoken.component';
9 9
 
10 10
 @Component({
@@ -15,8 +15,9 @@ export class FrontcraftRaidComponent implements OnInit{
15 15
 
16 16
     canSignup = false
17 17
     isSignedup = false
18
+    islate = false
18 19
     manageRaid
19
-    mySignup
20
+    mySignup: (Signup & Character & Spec)
20 21
 
21 22
     raid: RaidData = <any>{
22 23
       participants:{
@@ -30,9 +31,14 @@ export class FrontcraftRaidComponent implements OnInit{
30 31
           Warlock: [],
31 32
           Warrior: [],
32 33
       },
34
+      tanks: [],
35
+      healers: [],
33 36
       tokens:{}
34 37
     }
35
-    
38
+    tokens = {}
39
+    displayedtokens = {}
40
+    search = ""
41
+
36 42
     constructor(
37 43
       private api: ApiService,
38 44
       private route: ActivatedRoute,
@@ -93,11 +99,40 @@ export class FrontcraftRaidComponent implements OnInit{
93 99
       const signupFeature = this.api.get('signup')
94 100
       if(!signupFeature) return
95 101
 
96
-      await signupFeature.unsign(this.api.getAuth().token.value, <any>{id: this.mySignup.characterid, userid: this.mySignup.userid}, this.raid)
102
+      await signupFeature.unsign(this.api.getAuth().token.value, {
103
+        ...this.mySignup,
104
+        id: this.mySignup.characterid, 
105
+      }, this.raid)
97 106
       this.toast.show('Success', 'Unsigned', { status: 'success' })
98 107
       this.refresh()
99 108
     }
100 109
 
110
+    setLate = async (value:boolean) => {
111
+      const auth = this.api.getAuth()
112
+      const signup = this.api.get('signup')
113
+      if(!signup) return
114
+
115
+      console.log("setlate");
116
+      
117
+
118
+      await signup.sign(auth.token.value, {
119
+        ...this.mySignup,
120
+        id: this.mySignup.characterid,
121
+      }, this.raid, value)
122
+      this.toast.show('Signup', 'Success', { status: 'success' })
123
+      this.refresh()
124
+    }
125
+
126
+    adminUnsign = async() => {
127
+      const manage =  this.api.get('manageRaid')
128
+      if(!manage) return
129
+      await manage.adminUnsign({
130
+        ...this.mySignup,
131
+        id: this.mySignup.characterid, 
132
+      }, this.raid)
133
+      this.refresh()
134
+    }
135
+
101 136
     refresh = async () => {
102 137
       const param = this.route.snapshot.paramMap.get('id');
103 138
 
@@ -105,22 +140,40 @@ export class FrontcraftRaidComponent implements OnInit{
105 140
       const raiddata = await raidManager.getRaidData(<any>{
106 141
         id: param
107 142
       })
143
+        
108 144
       this.raid = raiddata
145
+      this.tokens = raiddata.tokens;
109 146
 
110
-      Object.values(raiddata.participants).flat().forEach(p => {
147
+      [...raiddata.tanks, ...raiddata.healers, ...Object.values(raiddata.participants).flat()].forEach(p => {
111 148
         p['color'] = getClassColor(p.class)
112 149
       })
150
+
113 151
       const user = this.api.getCurrentUser()
114 152
       const matchingSignup = Object.values(raiddata.participants).flat().find(char => user && char.userid === user.id!)
115 153
       if(matchingSignup){       
116
-
117 154
         this.isSignedup = true
118 155
         this.mySignup = matchingSignup
119
-        this.mySignup.status = matchingSignup['benched']?'Bench':matchingSignup['late']?'Late':'Attending'
156
+        this.mySignup['status'] = matchingSignup['benched']?'Bench':matchingSignup['late']?'Late':'Attending'
120 157
       }else{
121 158
         this.isSignedup = false
122 159
         this.mySignup = null
123 160
       }
161
+      this.changeSearch()
162
+    }
163
+
164
+    changeSearch(){
165
+      if(!this.search || this.search == ""){
166
+        this.displayedtokens = this.tokens
167
+      }else{
168
+        this.displayedtokens = {}
169
+        Object.entries(this.tokens).forEach((e: [string, (Character & SRToken & Item)[]]) => {
170
+          const filteredTokens = e[1].filter(item => {
171
+            return item.itemname.toLocaleLowerCase().includes(this.search.toLocaleLowerCase())
172
+          })
173
+          if(filteredTokens.length > 0)
174
+            this.displayedtokens[e[0]] = filteredTokens 
175
+        })
176
+      }
124 177
     }
125 178
 
126 179
     setBench(signup:Signup){

+ 1
- 1
src/frontend/src/app/frontcraft/pages/rules/rules.component.html Переглянути файл

@@ -20,7 +20,7 @@
20 20
                             <ng-template #templateRef>
21 21
                                 <span style="color:white">{{rule.description}}</span>
22 22
                             </ng-template>
23
-                            +{{rule.modifier}} {{rule.race}} <span [ngStyle]="{'color':rule.color}">{{rule.specname}} {{rule.class}}</span> <br />
23
+                            <span *ngIf="rule.modifier>0">+</span>{{rule.modifier}} {{rule.race}} <span [ngStyle]="{'color':rule.color}">{{rule.specname}} {{rule.class}}</span> <br />
24 24
                         </span>
25 25
                     </nb-list-item>
26 26
                 </nb-list>

+ 21
- 17
src/frontend/src/app/frontcraft/pages/shop/buytoken.component.ts Переглянути файл

@@ -72,13 +72,18 @@ import { _Tiers, allItems, Tiers } from '../../../../../../backend/Types/Items';
72 72
         .then(chars => {
73 73
             chars.forEach(char => {
74 74
                 char['color'] = getClassColor(char.class)
75
-                this.api.get('ItemManager').getToken(char, this.item).then(token => {
76
-                  if(token) this.ownedtokens.push(token)
77
-                  else{
78
-                    this.api.get('ItemManager').calculatePriorities(this.item.itemname, char).then(modifier => {
79
-                      this.modifier[char.charactername] = modifier
80
-                    })
81
-                  }
75
+                this.api.get('ItemManager').getToken(char, this.item, false).then(token => {
76
+                    if(token) this.ownedtokens.push(token)
77
+                    else{
78
+                        this.api.get('ItemManager').getToken(char, this.item, true).then(tokken => {
79
+                            if(tokken) this.ownedtokens.push(tokken)
80
+                            else{
81
+                                this.api.get('ItemManager').calculatePriorities(this.item.itemname, char).then(modifier => {
82
+                                    this.modifier[char.charactername] = modifier
83
+                                })
84
+                            }
85
+                        })
86
+                    }
82 87
                 })
83 88
             })
84 89
             this.characters = chars
@@ -90,15 +95,14 @@ import { _Tiers, allItems, Tiers } from '../../../../../../backend/Types/Items';
90 95
     }
91 96
   
92 97
     buyToken = async (charactername:string) => {
93
-
94
-    const src = this.api.get('ItemManager')
95
-    const token = await src.buyToken(this.api.getAuth().token.value, charactername, this.item.itemname, this.signup)
96
-  
97
-    if(token){
98
-      this.toastr.show(token.characterid+' now has a token for '+token.itemname+' of level '+token.level, 'Yay', {status: 'success'})
99
-    }else{
100
-      this.toastr.show('Error (something went wrong)', 'Oh no', {status: 'danger'})
101
-    }
102
-    this.dialogRef.close()
98
+        const src = this.api.get('ItemManager')
99
+        const token = await src.buyToken(this.api.getAuth().token.value, charactername, this.item.itemname, this.signup)
100
+    
101
+        if(token){
102
+        this.toastr.show(token.characterid+' now has a token for '+token.itemname+' of level '+token.level, 'Yay', {status: 'success'})
103
+        }else{
104
+        this.toastr.show('Error (something went wrong)', 'Oh no', {status: 'danger'})
105
+        }
106
+        this.dialogRef.close()
103 107
     }
104 108
   }

BIN
src/frontend/src/assets/images/dwarf.png Переглянути файл


BIN
src/frontend/src/assets/images/dwarf_xs.gif Переглянути файл


BIN
src/frontend/src/assets/images/gnome.png Переглянути файл


BIN
src/frontend/src/assets/images/gnome_xs.gif Переглянути файл


BIN
src/frontend/src/assets/images/human.png Переглянути файл


BIN
src/frontend/src/assets/images/human_xs.gif Переглянути файл


BIN
src/frontend/src/assets/images/night elf.png Переглянути файл


BIN
src/frontend/src/assets/images/night elf_xs.gif Переглянути файл


BIN
src/frontend/src/assets/images/team.png Переглянути файл


BIN
src/frontend/src/assets/images/warlock.png Переглянути файл


+ 22
- 3
test/backendTest.ts Переглянути файл

@@ -79,7 +79,7 @@ const testAccounts : protoAccount[] = [
79 79
         spec: 'Fury',
80 80
         rank: 'Classleader'
81 81
     },{
82
-        name: 'Teenieweenie',
82
+        name: 'Teeniweeni',
83 83
         class: 'Warlock',
84 84
         race: 'Gnome',
85 85
         spec: 'Demonology',
@@ -276,10 +276,30 @@ describe('Frontcraft', () => {
276 276
                 undefined, 1, "hit bias"
277 277
             ),
278 278
 
279
+            makePrio(
280
+                'Maladath, Runed Blade of the Black Flight', 
281
+                undefined,
282
+                "Human", -2, "(1) Non-Human"
283
+            ),
284
+            makePrio(
285
+                'Maladath, Runed Blade of the Black Flight', 
286
+                {class:'Rogue', specname:'Subtlety'}, 
287
+                undefined, 2, "...Rogues (weapon skill bias)"
288
+            ),
289
+            makePrio(
290
+                'Maladath, Runed Blade of the Black Flight', 
291
+                {class:'Rogue', specname:'Combat'}, 
292
+                undefined, 2, "...Rogues (weapon skill bias)"
293
+            ),
294
+            makePrio(
295
+                'Maladath, Runed Blade of the Black Flight', 
296
+                {class:'Rogue', specname:'Assassination'}, 
297
+                undefined, 2, "...Rogues (weapon skill bias)"
298
+            ),
279 299
             makePrio(
280 300
                 'Maladath, Runed Blade of the Black Flight', 
281 301
                 {class:'Warrior', specname:'Fury'}, 
282
-                'Human', 2, "weapon skill bias"
302
+                'Human', 4, "+2 Fury Warrior (weapon skill bias), +2 to offset (1)"
283 303
             ),
284 304
 
285 305
             makePrio(
@@ -556,7 +576,6 @@ describe('Frontcraft', () => {
556 576
                         }
557 577
                         else{
558 578
                             console.log("Bad user currency", dbUser);
559
-                            
560 579
                         }
561 580
                     })
562 581
                 }

Завантаження…
Відмінити
Зберегти