diff --git a/api/apib/army-management/users.apib b/api/apib/army-management/users.apib index 6c4573e..a0c33fd 100644 --- a/api/apib/army-management/users.apib +++ b/api/apib/army-management/users.apib @@ -5,14 +5,17 @@ Get single army member information + Parameters + q: `hardi` (string, optional) - filter string which filters for partial username - + fractFilter: `BLUFOR` (enum[string], optional) - Field to filter by fraction + + fractFilter: `BLUFOR` (enum[string], optional) - Field to filter by fraction + Members + `BLUFOR` + `OPFOR` + `GLOBAL` + + squadId: `591470249e9fae286e008e31` (string, optional) - Field to filter by membership of certain squad + + + decorationId: `5abd3dff6e6a0334d95b8ba0` (string, optional) - Field to filter by ownership of certain decoration + + limit: 20 (number, optional) Maximum number of users to return diff --git a/api/routes/users.js b/api/routes/users.js index f83864f..30ffe94 100644 --- a/api/routes/users.js +++ b/api/routes/users.js @@ -29,40 +29,59 @@ users.get('/', offsetlimitMiddleware); // routes ********************** users.route('/') .get((req, res, next) => { + const finishFiltersAndExecute = () => { + // squad / fraction filter setup + if (req.query.fractFilter && req.query.fractFilter !== 'UNASSIGNED' && !req.query.squadId) { + SquadModel.find({'fraction': req.query.fractFilter}, {_id: 1}, (err, squads) => { + dbFilter['squadId'] = {$in: squads.map((squad) => squad.id)}; + userQuery(); + }); + } else { + if (req.query.fractFilter === 'UNASSIGNED') { + dbFilter['squadId'] = {$eq: null}; + } + userQuery(); + } + }; + const userQuery = () => { UserModel.find(dbFilter, res.locals.filter, res.locals.limitskip) .populate('squadId') .collation({locale: 'en', strength: 2}) // case insensitive order - .sort('username').exec((err, users) => { - if (err) return next(err); - if (users.length === 0) { - res.locals.items = users; - res.locals.processed = true; - return next(); - } - UserModel.count(dbFilter, (err, totalCount) => { - res.set('x-total-count', totalCount); - res.locals.items = users; - res.locals.processed = true; - return next(); - }); - }); + .sort('username') + .exec((err, users) => { + if (err) return next(err); + if (users.length === 0) { + res.locals.items = users; + res.locals.processed = true; + return next(); + } + + UserModel.count(dbFilter, (err, totalCount) => { + res.set('x-total-count', totalCount); + res.locals.items = users; + res.locals.processed = true; + return next(); + }); + }); }; - if (!req.query.q) req.query.q = ''; - const dbFilter = {username: {'$regex': req.query.q, '$options': 'i'}}; + const nameQuery = (!req.query.q) ? '' : req.query.q; + + const dbFilter = {username: {'$regex': nameQuery, '$options': 'i'}}; + if (req.query.squadId) dbFilter['squadId'] = {'$eq': req.query.squadId}; - // squad / fraction filter setup - if (req.query.fractFilter && req.query.fractFilter !== 'UNASSIGNED' && !req.query.squadId) { - SquadModel.find({'fraction': req.query.fractFilter}, {_id: 1}, (err, squads) => { - dbFilter['squadId'] = {$in: squads.map((squad) => squad.id)}; - userQuery(); + + // decoration filter + const queryDecoId = req.query.decorationId; + if (queryDecoId) { + AwardingModel.find({decorationId: queryDecoId}, (err, awards) => { + const userIds = [...new Set(awards.map((award) => award.userId))]; + dbFilter._id = {'$in': userIds}; + finishFiltersAndExecute(); }); } else { - if (req.query.fractFilter === 'UNASSIGNED') { - dbFilter['squadId'] = {$eq: null}; - } - userQuery(); + finishFiltersAndExecute(); } }) @@ -196,7 +215,6 @@ users.route('/:id') routerHandling.httpMethodNotAllowed ); - // this middleware function can be used, if you like or remove it // it looks for object(s) in res.locals.items and if they exist, they are send to the client as json users.use(routerHandling.emptyResponse); diff --git a/static/src/app/army/army-member/army-member.component.ts b/static/src/app/army/army-member/army-member.component.ts index a8d5124..430d236 100644 --- a/static/src/app/army/army-member/army-member.component.ts +++ b/static/src/app/army/army-member/army-member.component.ts @@ -51,7 +51,6 @@ export class ArmyMemberComponent implements OnInit, OnDestroy { this.awards = awards; })); }); - }; ngOnDestroy() { diff --git a/static/src/app/pub/trace-overview/trace-overview.component.css b/static/src/app/pub/trace-overview/trace-overview.component.css index 64ce27a..6061a78 100644 --- a/static/src/app/pub/trace-overview/trace-overview.component.css +++ b/static/src/app/pub/trace-overview/trace-overview.component.css @@ -4,7 +4,7 @@ min-width: 800px; position: relative; margin: auto auto 25px; - height: calc(100vh - 95px); + min-height: calc(100vh - 95px); } .show-panel { @@ -12,6 +12,10 @@ margin: inherit; } +:host /deep/ .show-panel mat-card { + cursor: default; +} + .decoration-show-panel { height: 250px; } diff --git a/static/src/app/pub/trace-overview/trace-overview.component.html b/static/src/app/pub/trace-overview/trace-overview.component.html index 2ad81fb..9ae31f3 100644 --- a/static/src/app/pub/trace-overview/trace-overview.component.html +++ b/static/src/app/pub/trace-overview/trace-overview.component.html @@ -23,7 +23,7 @@ Fraktion + [style.color]="element.squadId.fraction === 'BLUFOR' ? fraction.COLOR_BLUFOR :fraction.COLOR_OPFOR"> {{element.squadId.fraction === 'BLUFOR' ? fraction.BLUFOR : fraction.OPFOR}} diff --git a/static/src/app/pub/trace-overview/trace-overview.component.ts b/static/src/app/pub/trace-overview/trace-overview.component.ts index 96c8b64..7a94b87 100644 --- a/static/src/app/pub/trace-overview/trace-overview.component.ts +++ b/static/src/app/pub/trace-overview/trace-overview.component.ts @@ -44,18 +44,19 @@ export class TraceOverviewComponent implements OnInit, OnDestroy { if (this.router.url.includes('find/award/')) { // Award this.isRank = false; - console.log(itemId); this.decorationService.getDecoration(itemId).subscribe(decoration => { this.traceItem = decoration; - console.log(decoration) + this.userService.findUsers({decorationId: decoration._id}).subscribe(users => { + this.users = users.filter(user => user.squadId != null); + }); }); } else if (this.router.url.includes('find/rank/')) { // Rank this.isRank = true; this.rankService.getRank(itemId).subscribe(rank => { this.traceItem = rank; - this.userService.findUsers('', rank.fraction).subscribe(users => { - this.users = users.filter(user => user.rankLvl === rank.level); + this.userService.findUsers({fraction: rank.fraction}).subscribe(users => { + this.users = users.filter(user => user.squadId != null && user.rankLvl === rank.level); }); }); } diff --git a/static/src/app/request/award/req-award.component.ts b/static/src/app/request/award/req-award.component.ts index 999d598..d0de1fb 100644 --- a/static/src/app/request/award/req-award.component.ts +++ b/static/src/app/request/award/req-award.component.ts @@ -45,7 +45,7 @@ export class RequestAwardComponent implements OnInit { ngOnInit() { const currentUser = this.loginService.getCurrentUser(); - this.userService.findUsers('', undefined, currentUser.squad._id).subscribe(users => { + this.userService.findUsers({squadId: currentUser.squad._id}).subscribe(users => { this.users = users; }); this.decorationService.findDecorations('', currentUser.squad.fraction).subscribe(decorations => { diff --git a/static/src/app/request/promotion/req-promotion.component.ts b/static/src/app/request/promotion/req-promotion.component.ts index 90d091d..709119d 100644 --- a/static/src/app/request/promotion/req-promotion.component.ts +++ b/static/src/app/request/promotion/req-promotion.component.ts @@ -44,7 +44,7 @@ export class RequestPromotionComponent implements OnInit { ngOnInit() { const currentUser = this.loginService.getCurrentUser(); // show only current users squad members - this.userService.findUsers('', undefined, currentUser.squad._id).subscribe(users => { + this.userService.findUsers({squadId: currentUser.squad._id}).subscribe(users => { this.users = users; }); this.rankService.findRanks('', currentUser.squad.fraction).subscribe(ranks => { diff --git a/static/src/app/services/army-management/user.service.ts b/static/src/app/services/army-management/user.service.ts index 71cd488..5970781 100644 --- a/static/src/app/services/army-management/user.service.ts +++ b/static/src/app/services/army-management/user.service.ts @@ -19,15 +19,23 @@ export class UserService { this.users$ = userStore.items$; } - findUsers(query = '', fractionFilter?, squadFilter?, limit?, offset?, action = LOAD) { + findUsers(filter, limit?, offset?, action = LOAD) { const searchParams = new URLSearchParams(); - searchParams.append('q', query); - if (fractionFilter) { - searchParams.append('fractFilter', fractionFilter); + + searchParams.append('q', (filter && filter.query) ? filter.query : ''); + + if (filter && filter.fraction) { + searchParams.append('fractFilter', filter.fraction); } - if (squadFilter) { - searchParams.append('squadId', squadFilter); + + if (filter && filter.squadId) { + searchParams.append('squadId', filter.squadId); } + + if (filter && filter.decorationId) { + searchParams.append('decorationId', filter.decorationId); + } + searchParams.append('limit', limit); searchParams.append('offset', offset); this.http.get(this.config.apiUserPath, searchParams) diff --git a/static/src/app/users/user-list/user-list.component.ts b/static/src/app/users/user-list/user-list.component.ts index 37c90e0..31a7495 100644 --- a/static/src/app/users/user-list/user-list.component.ts +++ b/static/src/app/users/user-list/user-list.component.ts @@ -1,5 +1,4 @@ import {Component, OnInit} from '@angular/core'; -import {Location} from '@angular/common'; import {FormControl} from '@angular/forms'; import {ActivatedRoute, Router} from '@angular/router'; @@ -81,8 +80,10 @@ export class UserListComponent implements OnInit { this.limit = 20; } this.radioModel = UIHelpers.toggleReleaseButton(this.radioModel, group); - return this.users$ = this.userService.findUsers(this.searchTerm.value, this.radioModel, - null, this.limit, this.offset, action); + return this.users$ = this.userService.findUsers({ + query: this.searchTerm.value, + fraction: this.radioModel + }, this.limit, this.offset, action); } onScrollDown() {