diff --git a/api/models/promotion.js b/api/models/promotion.js
index acd3706..c809bd7 100644
--- a/api/models/promotion.js
+++ b/api/models/promotion.js
@@ -13,15 +13,25 @@ const PromotionSchema = new Schema({
ref: 'AppUser',
required: true
},
- rankLvl: {
+ oldRankLvl: {
+ type: Number,
+ get: v => Math.round(v),
+ set: v => Math.round(v),
+ required: true
+ },
+ newRankLvl: {
type: Number,
get: v => Math.round(v),
set: v => Math.round(v),
required: true
},
confirmed: {
- type: Boolean,
- default: true
+ type: Number,
+ get: v => Math.round(v),
+ set: v => Math.round(v),
+ min: 0,
+ max: 2,
+ required: true
}
}, {
collection: 'promotion',
diff --git a/api/routes/authenticate.js b/api/routes/authenticate.js
index 955a0c4..1dfb8aa 100644
--- a/api/routes/authenticate.js
+++ b/api/routes/authenticate.js
@@ -47,7 +47,7 @@ authenticate.route('/')
let authCheck = (username, password, res) => {
const deferred = Q.defer();
- AppUserModel.findOne({username: username}, (err, user) => {
+ AppUserModel.findOne({username: username}).populate('squad').exec((err, user) => {
if (err) deferred.reject(err.name + ': ' + err.message);
const diff = 3 * 60 * 24; // time till expiration [minutes]
diff --git a/api/routes/request.js b/api/routes/request.js
index f2e09c3..e107734 100644
--- a/api/routes/request.js
+++ b/api/routes/request.js
@@ -10,7 +10,20 @@ const codes = require('./http-codes');
const routerHandling = require('../middleware/router-handling');
// Mongoose Model using mongoDB
+const UserModel = require('../models/user');
const AwardingModel = require('../models/awarding');
+const PromotionModel = require('../models/promotion');
+
+// result set for proposer(appUser) population
+const resultSet = {
+ '__v': 0,
+ 'updatedAt': 0,
+ 'timestamp': 0,
+ 'password': 0,
+ 'permission': 0,
+ 'secret': 0,
+ 'activated': 0
+};
const request = express.Router();
@@ -41,6 +54,51 @@ request.route('/award')
request.route('/promotion')
+ .get((req, res, next) => {
+ const squadFilter = req.query.squadId;
+ let userIds = [];
+ UserModel.find({squadId: squadFilter}, (err, items) => {
+ if (err) {
+ err.status = codes.servererror;
+ return next(err);
+ }
+ for (let item of items) {
+ userIds.push(item._id);
+ }
+ PromotionModel.find({userId: {"$in": userIds}}, {}, {sort: {timestamp: 'desc'}}).populate('userId').populate('proposer', resultSet).exec((err, items) => {
+ if (err) {
+ err.status = codes.servererror;
+ return next(err);
+ }
+
+ if (items && items.length > 0) {
+ res.locals.items = items;
+ } else {
+ res.locals.items = [];
+ }
+ res.locals.processed = true;
+ next();
+ })
+ });
+
+ })
+
+ .post((req, res, next) => {
+ const promotion = new PromotionModel(req.body);
+ promotion.confirmed = 0;
+ promotion.proposer = req.user._id;
+ // timestamp and default are set automatically by Mongoose Schema Validation
+ promotion.save((err) => {
+ if (err) {
+ err.status = codes.wrongrequest;
+ err.message += ' in fields: ' + Object.getOwnPropertyNames(err.errors);
+ return next(err);
+ }
+ res.status(codes.created);
+ res.locals.items = promotion;
+ next();
+ });
+ })
.all(
routerHandling.httpMethodNotAllowed
diff --git a/static/src/app/app.config.ts b/static/src/app/app.config.ts
index 0869196..4b41471 100644
--- a/static/src/app/app.config.ts
+++ b/static/src/app/app.config.ts
@@ -12,6 +12,7 @@ export class AppConfig {
public readonly apiSquadPath = '/squads/';
public readonly apiUserPath = '/users/';
public readonly apiOverviewPath = '/overview';
- public readonly apiRequestAwardPath = '/request/award'
+ public readonly apiRequestAwardPath = '/request/award';
+ public readonly apiPromotionPath = '/request/promotion';
}
diff --git a/static/src/app/app.module.ts b/static/src/app/app.module.ts
index ffd2f67..9db2858 100644
--- a/static/src/app/app.module.ts
+++ b/static/src/app/app.module.ts
@@ -29,6 +29,8 @@ import {ArmyService} from "./services/army-service/army.service";
import { ClipboardModule } from 'ngx-clipboard';
import {AppUserService} from "./services/app-user-service/app-user.service";
import {AppUserStore} from "./services/stores/app-user.store";
+import {PromotionService} from "./services/promotion-service/promotion.service";
+import {FilterRankPipe} from "./filter/filter.pipe";
@NgModule({
imports: [BrowserModule, FormsModule, ReactiveFormsModule, appRouting, HttpModule, ClipboardModule],
@@ -50,6 +52,7 @@ import {AppUserStore} from "./services/stores/app-user.store";
RankService,
RankStore,
AwardingService,
+ PromotionService,
AppConfig,
Title,
routingProviders,
@@ -61,6 +64,7 @@ import {AppUserStore} from "./services/stores/app-user.store";
DecorationComponent,
DecorationItemComponent,
RankItemComponent,
+ FilterRankPipe,
UserItemComponent,
SquadItemComponent,
ShowErrorComponent,
diff --git a/static/src/app/app.routing.ts b/static/src/app/app.routing.ts
index abafadb..462f7a2 100644
--- a/static/src/app/app.routing.ts
+++ b/static/src/app/app.routing.ts
@@ -10,6 +10,7 @@ import {armyRoutes, armyRoutingComponents} from "./army/army.routing";
import {SignupComponent} from "./login/signup.component";
import {AdminComponent} from "./admin/admin.component";
import {RequestAwardComponent} from "./request/award/req-award.component";
+import {RequestPromotionComponent} from "./request/promotion/req-promotion.component";
export const appRoutes: Routes = [
@@ -21,6 +22,7 @@ export const appRoutes: Routes = [
{path: 'signup', component: SignupComponent},
{path: 'request-award', component: RequestAwardComponent, canActivate: [LoginGuardSQL]},
+ {path: 'request-promotion', component: RequestPromotionComponent, canActivate: [LoginGuardSQL]},
{path: 'cc-users', children: usersRoutes, canActivate: [LoginGuardHL]},
{path: 'cc-squads', children: squadsRoutes, canActivate: [LoginGuardHL]},
@@ -36,7 +38,7 @@ export const appRoutes: Routes = [
export const appRouting = RouterModule.forRoot(appRoutes);
-export const routingComponents = [LoginComponent, SignupComponent, RequestAwardComponent, AdminComponent, ...armyRoutingComponents , NotFoundComponent, ...usersRoutingComponents,
+export const routingComponents = [LoginComponent, SignupComponent, RequestAwardComponent, RequestPromotionComponent, AdminComponent, ...armyRoutingComponents , NotFoundComponent, ...usersRoutingComponents,
...squadsRoutingComponents, ...decorationsRoutingComponents, ...ranksRoutingComponents];
export const routingProviders = [LoginGuardHL];
diff --git a/static/src/app/filter/filter.pipe.ts b/static/src/app/filter/filter.pipe.ts
new file mode 100644
index 0000000..1df80f1
--- /dev/null
+++ b/static/src/app/filter/filter.pipe.ts
@@ -0,0 +1,23 @@
+import {Pipe, PipeTransform} from "@angular/core";
+
+/**
+ * Filter Pipe to filter specific rank by level number in template
+ *
+ * @author: HardiReady
+ */
+
+@Pipe({name: 'rankfilter'})
+export class FilterRankPipe implements PipeTransform {
+
+ transform(items: any[], filter: any): any {
+ // filter items array, items which match and return true will be kept, false will be filtered out
+ let res = items.filter(item => item.level === filter);
+ if (res.length === 0) {
+ return [{name: '-'}];
+ }
+ else {
+ return res
+ }
+ }
+
+}
diff --git a/static/src/app/models/model-interfaces.ts b/static/src/app/models/model-interfaces.ts
index c0f82f2..d62821b 100644
--- a/static/src/app/models/model-interfaces.ts
+++ b/static/src/app/models/model-interfaces.ts
@@ -40,6 +40,12 @@ export interface Award {
confirmed?: boolean;
}
+export interface Promotion {
+ userId?: string
+ oldRankLvl: number,
+ newRankLvl: number
+}
+
export interface Decoration {
_id?: string;
name?: string;
diff --git a/static/src/app/request/award/req-award.component.css b/static/src/app/request/award/req-award.component.css
index 7e4bb1e..d9356a4 100644
--- a/static/src/app/request/award/req-award.component.css
+++ b/static/src/app/request/award/req-award.component.css
@@ -14,7 +14,7 @@
.table-container {
margin-top: 40px;
overflow-x: auto;
- width: 50%;
+ width: 65%;
}
/* enable scrolling for long list of awardings */
diff --git a/static/src/app/request/award/req-award.component.html b/static/src/app/request/award/req-award.component.html
index 0bac083..2304f51 100644
--- a/static/src/app/request/award/req-award.component.html
+++ b/static/src/app/request/award/req-award.component.html
@@ -8,9 +8,8 @@
id="user"
[(ngModel)]="user"
[compareWith]="equals"
- required
- (change)="toggleUser()"
- style="min-width: 200px;">
+ (change)="toggleUser(decoPreview, decoDescription)"
+ required>
@@ -18,99 +17,94 @@
-