add awarding request for sql
parent
aa96f49ae1
commit
609395febc
|
@ -10,5 +10,6 @@ module.exports = {
|
||||||
signatures: '/signatures',
|
signatures: '/signatures',
|
||||||
squads: '/squads',
|
squads: '/squads',
|
||||||
users: '/users',
|
users: '/users',
|
||||||
account: '/account'
|
account: '/account',
|
||||||
|
request: '/request'
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,6 +16,11 @@ const AwardingSchema = new Schema({
|
||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
|
proposer: {
|
||||||
|
type: mongoose.Schema.Types.ObjectId,
|
||||||
|
ref: 'AppUser',
|
||||||
|
required: true
|
||||||
|
},
|
||||||
confirmed: {
|
confirmed: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const mongoose = require('mongoose');
|
||||||
|
const Schema = mongoose.Schema;
|
||||||
|
|
||||||
|
const PromotionSchema = new Schema({
|
||||||
|
userId: {
|
||||||
|
type: mongoose.Schema.Types.ObjectId,
|
||||||
|
ref: 'User'
|
||||||
|
},
|
||||||
|
proposer: {
|
||||||
|
type: mongoose.Schema.Types.ObjectId,
|
||||||
|
ref: 'AppUser',
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
rankLvl: {
|
||||||
|
type: Number,
|
||||||
|
get: v => Math.round(v),
|
||||||
|
set: v => Math.round(v),
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
confirmed: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
collection: 'promotion',
|
||||||
|
timestamps: {createdAt: 'timestamp'}
|
||||||
|
});
|
||||||
|
// optional more indices
|
||||||
|
PromotionSchema.index({timestamp: 1});
|
||||||
|
|
||||||
|
module.exports = mongoose.model('Promotion', PromotionSchema);
|
|
@ -61,6 +61,7 @@ let authCheck = (username, password, res) => {
|
||||||
_id: user._id,
|
_id: user._id,
|
||||||
username: user.username,
|
username: user.username,
|
||||||
permission: user.permission,
|
permission: user.permission,
|
||||||
|
squad: user.squad,
|
||||||
token: jwt.sign({sub: user._id}, config.secret, {expiresIn: diff * 60}),
|
token: jwt.sign({sub: user._id}, config.secret, {expiresIn: diff * 60}),
|
||||||
tokenExpireDate: new Date(Date.now().valueOf() + diff * 60000 - 1000)
|
tokenExpireDate: new Date(Date.now().valueOf() + diff * 60000 - 1000)
|
||||||
});
|
});
|
||||||
|
|
|
@ -9,9 +9,23 @@ const codes = require('./http-codes');
|
||||||
|
|
||||||
const routerHandling = require('../middleware/router-handling');
|
const routerHandling = require('../middleware/router-handling');
|
||||||
|
|
||||||
|
const apiAuthenticationMiddleware = require('../middleware/auth-middleware');
|
||||||
|
const checkHl = require('../middleware/permission-check').checkHl;
|
||||||
|
|
||||||
// Mongoose Model using mongoDB
|
// Mongoose Model using mongoDB
|
||||||
const AwardingModel = require('../models/awarding');
|
const AwardingModel = require('../models/awarding');
|
||||||
|
|
||||||
|
// result set for proposer(appUser) population
|
||||||
|
const resultSet = {
|
||||||
|
'__v': 0,
|
||||||
|
'updatedAt': 0,
|
||||||
|
'timestamp': 0,
|
||||||
|
'password': 0,
|
||||||
|
'permission': 0,
|
||||||
|
'secret': 0,
|
||||||
|
'activated': 0
|
||||||
|
};
|
||||||
|
|
||||||
const awarding = express.Router();
|
const awarding = express.Router();
|
||||||
|
|
||||||
|
|
||||||
|
@ -39,7 +53,7 @@ awarding.route('/')
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
AwardingModel.find(filter, {}, {sort: {date: 'desc'}})
|
AwardingModel.find(filter, {}, {sort: {date: 'desc'}})
|
||||||
.populate('decorationId').exec((err, items) => {
|
.populate('decorationId').populate('proposer', resultSet).exec((err, items) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
err.status = codes.servererror;
|
err.status = codes.servererror;
|
||||||
return next(err);
|
return next(err);
|
||||||
|
@ -56,17 +70,18 @@ awarding.route('/')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
.post((req, res, next) => {
|
.post(apiAuthenticationMiddleware, checkHl, (req, res, next) => {
|
||||||
const rank = new AwardingModel(req.body);
|
const award = new AwardingModel(req.body);
|
||||||
|
award.proposer = req.user._id;
|
||||||
// timestamp and default are set automatically by Mongoose Schema Validation
|
// timestamp and default are set automatically by Mongoose Schema Validation
|
||||||
rank.save((err) => {
|
award.save((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
err.status = codes.wrongrequest;
|
err.status = codes.wrongrequest;
|
||||||
err.message += ' in fields: ' + Object.getOwnPropertyNames(err.errors);
|
err.message += ' in fields: ' + Object.getOwnPropertyNames(err.errors);
|
||||||
return next(err);
|
return next(err);
|
||||||
}
|
}
|
||||||
res.status(codes.created);
|
res.status(codes.created);
|
||||||
res.locals.items = rank;
|
res.locals.items = award;
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
@ -76,7 +91,7 @@ awarding.route('/')
|
||||||
);
|
);
|
||||||
|
|
||||||
awarding.route('/:id')
|
awarding.route('/:id')
|
||||||
.delete((req, res, next) => {
|
.delete(apiAuthenticationMiddleware, checkHl, (req, res, next) => {
|
||||||
AwardingModel.findByIdAndRemove(req.params.id, (err, item) => {
|
AwardingModel.findByIdAndRemove(req.params.id, (err, item) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
err.status = codes.wrongrequest;
|
err.status = codes.wrongrequest;
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
// modules
|
||||||
|
const express = require('express');
|
||||||
|
const logger = require('debug')('cc:awardings');
|
||||||
|
|
||||||
|
// HTTP status codes by name
|
||||||
|
const codes = require('./http-codes');
|
||||||
|
|
||||||
|
const routerHandling = require('../middleware/router-handling');
|
||||||
|
|
||||||
|
// Mongoose Model using mongoDB
|
||||||
|
const AwardingModel = require('../models/awarding');
|
||||||
|
|
||||||
|
const request = express.Router();
|
||||||
|
|
||||||
|
|
||||||
|
// routes **********************
|
||||||
|
request.route('/award')
|
||||||
|
|
||||||
|
.post((req, res, next) => {
|
||||||
|
const award = new AwardingModel(req.body);
|
||||||
|
award.confirmed = false;
|
||||||
|
award.proposer = req.user._id;
|
||||||
|
// timestamp and default are set automatically by Mongoose Schema Validation
|
||||||
|
award.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 = award;
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
.all(
|
||||||
|
routerHandling.httpMethodNotAllowed
|
||||||
|
);
|
||||||
|
|
||||||
|
request.route('/promotion')
|
||||||
|
|
||||||
|
|
||||||
|
.all(
|
||||||
|
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
|
||||||
|
request.use(routerHandling.emptyResponse);
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = request;
|
|
@ -42,8 +42,9 @@ users.route('/')
|
||||||
else {
|
else {
|
||||||
const nameQuery = req.query.q;
|
const nameQuery = req.query.q;
|
||||||
const fractionFilter = req.query.fractFilter;
|
const fractionFilter = req.query.fractFilter;
|
||||||
|
const squadFilter = req.query.squadId;
|
||||||
|
|
||||||
UserModel.find({}, res.locals.filter, res.locals.limitskip, (err, users) => {
|
UserModel.find({}, (err, users) => {
|
||||||
if (err) return next(err);
|
if (err) return next(err);
|
||||||
if (users.length === 0) {
|
if (users.length === 0) {
|
||||||
res.locals.items = users;
|
res.locals.items = users;
|
||||||
|
@ -56,8 +57,18 @@ users.route('/')
|
||||||
// filter by name
|
// filter by name
|
||||||
if (!nameQuery || (nameQuery && user.username.toLowerCase().includes(nameQuery.toLowerCase()))) {
|
if (!nameQuery || (nameQuery && user.username.toLowerCase().includes(nameQuery.toLowerCase()))) {
|
||||||
getExtendedUser(user, next, (extUser) => {
|
getExtendedUser(user, next, (extUser) => {
|
||||||
|
|
||||||
|
// filter by squad
|
||||||
|
if (squadFilter) {
|
||||||
|
if (extUser.squad && extUser.squad._id.toString() === squadFilter) {
|
||||||
|
resUsers.push(extUser);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rowsLength -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
// filter by fraction
|
// filter by fraction
|
||||||
if (!fractionFilter ||
|
else if (!fractionFilter ||
|
||||||
(fractionFilter && extUser.squad && extUser.squad.fraction.toLowerCase() === fractionFilter) ||
|
(fractionFilter && extUser.squad && extUser.squad.fraction.toLowerCase() === fractionFilter) ||
|
||||||
(fractionFilter && fractionFilter === 'unassigned' && !extUser.squad)) {
|
(fractionFilter && fractionFilter === 'unassigned' && !extUser.squad)) {
|
||||||
resUsers.push(extUser);
|
resUsers.push(extUser);
|
||||||
|
|
|
@ -15,7 +15,7 @@ const urls = require('./config/api-url');
|
||||||
const restAPIchecks = require('./middleware/request-checks.js');
|
const restAPIchecks = require('./middleware/request-checks.js');
|
||||||
const errorResponseWare = require('./middleware/error-response');
|
const errorResponseWare = require('./middleware/error-response');
|
||||||
const apiAuthenticationMiddleware = require('./middleware/auth-middleware');
|
const apiAuthenticationMiddleware = require('./middleware/auth-middleware');
|
||||||
const checkHl = require('./middleware/permission-check').checkHl;
|
const checkSql = require('./middleware/permission-check').checkSql;
|
||||||
const checkAdmin = require('./middleware/permission-check').checkAdmin;
|
const checkAdmin = require('./middleware/permission-check').checkAdmin;
|
||||||
const signatureCronJob = require('./cron-job/update-signatures');
|
const signatureCronJob = require('./cron-job/update-signatures');
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ const squadRouter = require('./routes/squads');
|
||||||
const rankRouter = require('./routes/ranks');
|
const rankRouter = require('./routes/ranks');
|
||||||
const decorationRouter = require('./routes/decorations');
|
const decorationRouter = require('./routes/decorations');
|
||||||
const awardingRouter = require('./routes/awardings');
|
const awardingRouter = require('./routes/awardings');
|
||||||
|
const requestRouter = require('./routes/request');
|
||||||
const signatureRouter = require('./routes/signatures');
|
const signatureRouter = require('./routes/signatures');
|
||||||
const commandRouter = require('./routes/command');
|
const commandRouter = require('./routes/command');
|
||||||
|
|
||||||
|
@ -72,7 +73,8 @@ app.use(urls.users, userRouter);
|
||||||
app.use(urls.squads, squadRouter);
|
app.use(urls.squads, squadRouter);
|
||||||
app.use(urls.ranks, rankRouter);
|
app.use(urls.ranks, rankRouter);
|
||||||
app.use(urls.decorations, decorationRouter);
|
app.use(urls.decorations, decorationRouter);
|
||||||
app.use(urls.awards, apiAuthenticationMiddleware, checkHl, awardingRouter);
|
app.use(urls.request, apiAuthenticationMiddleware, checkSql, requestRouter);
|
||||||
|
app.use(urls.awards, awardingRouter);
|
||||||
app.use(urls.command, apiAuthenticationMiddleware, checkAdmin, commandRouter);
|
app.use(urls.command, apiAuthenticationMiddleware, checkAdmin, commandRouter);
|
||||||
app.use(urls.account, apiAuthenticationMiddleware, checkAdmin, accountRouter);
|
app.use(urls.account, apiAuthenticationMiddleware, checkAdmin, accountRouter);
|
||||||
|
|
||||||
|
|
|
@ -12,5 +12,6 @@ export class AppConfig {
|
||||||
public readonly apiSquadPath = '/squads/';
|
public readonly apiSquadPath = '/squads/';
|
||||||
public readonly apiUserPath = '/users/';
|
public readonly apiUserPath = '/users/';
|
||||||
public readonly apiOverviewPath = '/overview';
|
public readonly apiOverviewPath = '/overview';
|
||||||
|
public readonly apiRequestAwardPath = '/request/award'
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import {Routes, RouterModule} from '@angular/router';
|
import {Routes, RouterModule} from '@angular/router';
|
||||||
import {LoginComponent} from './login/index';
|
import {LoginComponent} from './login/index';
|
||||||
import {NotFoundComponent} from './not-found/not-found.component';
|
import {NotFoundComponent} from './not-found/not-found.component';
|
||||||
import {LoginGuardAdmin, LoginGuardHL} from './login/login.guard';
|
import {LoginGuardAdmin, LoginGuardHL, LoginGuardSQL} from './login/login.guard';
|
||||||
import {usersRoutes, usersRoutingComponents} from "./users/users.routing";
|
import {usersRoutes, usersRoutingComponents} from "./users/users.routing";
|
||||||
import {squadsRoutes, squadsRoutingComponents} from "./squads/squads.routing";
|
import {squadsRoutes, squadsRoutingComponents} from "./squads/squads.routing";
|
||||||
import {decorationsRoutes, decorationsRoutingComponents} from "./decorations/decoration.routing";
|
import {decorationsRoutes, decorationsRoutingComponents} from "./decorations/decoration.routing";
|
||||||
|
@ -9,6 +9,7 @@ import {ranksRoutes, ranksRoutingComponents} from "./ranks/ranks.routing";
|
||||||
import {armyRoutes, armyRoutingComponents} from "./army/army.routing";
|
import {armyRoutes, armyRoutingComponents} from "./army/army.routing";
|
||||||
import {SignupComponent} from "./login/signup.component";
|
import {SignupComponent} from "./login/signup.component";
|
||||||
import {AdminComponent} from "./admin/admin.component";
|
import {AdminComponent} from "./admin/admin.component";
|
||||||
|
import {RequestAwardComponent} from "./request/award/req-award.component";
|
||||||
|
|
||||||
|
|
||||||
export const appRoutes: Routes = [
|
export const appRoutes: Routes = [
|
||||||
|
@ -18,6 +19,9 @@ export const appRoutes: Routes = [
|
||||||
|
|
||||||
{path: 'login', component: LoginComponent},
|
{path: 'login', component: LoginComponent},
|
||||||
{path: 'signup', component: SignupComponent},
|
{path: 'signup', component: SignupComponent},
|
||||||
|
|
||||||
|
{path: 'request-award', component: RequestAwardComponent, canActivate: [LoginGuardSQL]},
|
||||||
|
|
||||||
{path: 'cc-users', children: usersRoutes, canActivate: [LoginGuardHL]},
|
{path: 'cc-users', children: usersRoutes, canActivate: [LoginGuardHL]},
|
||||||
{path: 'cc-squads', children: squadsRoutes, canActivate: [LoginGuardHL]},
|
{path: 'cc-squads', children: squadsRoutes, canActivate: [LoginGuardHL]},
|
||||||
{path: 'cc-decorations', children: decorationsRoutes, canActivate: [LoginGuardHL]},
|
{path: 'cc-decorations', children: decorationsRoutes, canActivate: [LoginGuardHL]},
|
||||||
|
@ -32,7 +36,7 @@ export const appRoutes: Routes = [
|
||||||
|
|
||||||
export const appRouting = RouterModule.forRoot(appRoutes);
|
export const appRouting = RouterModule.forRoot(appRoutes);
|
||||||
|
|
||||||
export const routingComponents = [LoginComponent, SignupComponent, AdminComponent, ...armyRoutingComponents , NotFoundComponent, ...usersRoutingComponents,
|
export const routingComponents = [LoginComponent, SignupComponent, RequestAwardComponent, AdminComponent, ...armyRoutingComponents , NotFoundComponent, ...usersRoutingComponents,
|
||||||
...squadsRoutingComponents, ...decorationsRoutingComponents, ...ranksRoutingComponents];
|
...squadsRoutingComponents, ...decorationsRoutingComponents, ...ranksRoutingComponents];
|
||||||
|
|
||||||
export const routingProviders = [LoginGuardHL];
|
export const routingProviders = [LoginGuardHL];
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody *ngFor="let award of user.awards">
|
<tbody *ngFor="let award of user.awards">
|
||||||
<tr class="cell-outline">
|
<tr *ngIf="award.confirmed" class="cell-outline">
|
||||||
<td class="text-center" *ngIf="award.decorationId.isMedal">
|
<td class="text-center" *ngIf="award.decorationId.isMedal">
|
||||||
<img height="90px" src="resource/decoration/{{award.decorationId._id}}.png">
|
<img height="90px" src="resource/decoration/{{award.decorationId._id}}.png">
|
||||||
</td>
|
</td>
|
||||||
|
|
|
@ -35,6 +35,7 @@ export interface Award {
|
||||||
userId: string,
|
userId: string,
|
||||||
decorationId?: Decoration;
|
decorationId?: Decoration;
|
||||||
reason?: string;
|
reason?: string;
|
||||||
|
proposer?: AppUser;
|
||||||
date?: number; // since Date.now() returns a number
|
date?: number; // since Date.now() returns a number
|
||||||
confirmed?: boolean;
|
confirmed?: boolean;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
.decoration-preview {
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trash {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table {
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
table-layout: fixed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-container {
|
||||||
|
margin-top: 40px;
|
||||||
|
overflow-x: auto;
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* enable scrolling for long list of awardings */
|
||||||
|
.overview {
|
||||||
|
position: fixed;
|
||||||
|
overflow-y: scroll;
|
||||||
|
overflow-x: hidden;
|
||||||
|
width: 100%;
|
||||||
|
border-left: thin solid lightgrey;
|
||||||
|
padding: 20px 0 0 50px;
|
||||||
|
margin-left: 10px;
|
||||||
|
height: 100vh;
|
||||||
|
bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group {
|
||||||
|
width: 25%;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
margin: 80px 0 20px -20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
display: block;
|
||||||
|
}
|
|
@ -0,0 +1,116 @@
|
||||||
|
<form #form="ngForm" class="overview">
|
||||||
|
<h3>Auszeichnung beantragen</h3>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="user">Teilnehmer</label>
|
||||||
|
<select class="form-control"
|
||||||
|
name="user"
|
||||||
|
id="user"
|
||||||
|
[(ngModel)]="user"
|
||||||
|
[compareWith]="equals"
|
||||||
|
required
|
||||||
|
(change)="toggleUser()"
|
||||||
|
style="min-width: 200px;">
|
||||||
|
<option *ngFor="let user of users" [ngValue]="user">
|
||||||
|
{{user.username}}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div *ngIf="showForm">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="decoration">Auszeichnung</label>
|
||||||
|
<select class="form-control"
|
||||||
|
name="decoration"
|
||||||
|
id="decoration"
|
||||||
|
#decorationField
|
||||||
|
(change)="toggleDecoPreview(decoDescription, decorationField.value, decoPreview)"
|
||||||
|
[ngModel]="undefined"
|
||||||
|
required>
|
||||||
|
<option *ngFor="let deco of decorations" [value]="deco._id">
|
||||||
|
{{deco.fraction == 'BLUFOR'? 'NATO' : deco.fraction == 'OPFOR'? 'CSAT' : 'Global'}}: {{deco.name}}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<show-error text="Auszeichnung" path="decoration"></show-error>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="div-table-row" [style.display]="decoPreviewDisplay" style="margin-top: 5px; margin-bottom:10px">
|
||||||
|
<div class="col-sm-1 decoration-preview">
|
||||||
|
<img class="center-block" #decoPreview>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-2"
|
||||||
|
style="border-radius: 0px 15px 15px 0px; font-style: oblique" #decoDescription>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="reason">Begründung</label>
|
||||||
|
<textarea class="form-control center-block" name="reason" [ngModel]="undefined" required
|
||||||
|
id="reason" placeholder="Begründung eingeben..." rows="3" #awardTextArea></textarea>
|
||||||
|
<show-error text="Begründung" path="reason"></show-error>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button id="cancel"
|
||||||
|
(click)="cancel()"
|
||||||
|
class="btn btn-default">
|
||||||
|
Abbrechen
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button id="save"
|
||||||
|
(click)="addAwarding(decorationField, awardTextArea, decoPreview, decoDescription)"
|
||||||
|
class="btn btn-default"
|
||||||
|
[disabled]="!form.valid">
|
||||||
|
Bestätigen
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<span *ngIf="showSuccessLabel"
|
||||||
|
class="label label-success label-small"
|
||||||
|
style="margin-left: inherit">
|
||||||
|
Erfolgreich gespeichert
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<div class="table-container">
|
||||||
|
<table class="table table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="col-sm-1">Bild</th>
|
||||||
|
<th class="col-sm-2">Bezeichnung</th>
|
||||||
|
<th class="col-sm-2">Begründung</th>
|
||||||
|
<th class="col-sm-1 ">Antragsteller</th>
|
||||||
|
<th class="col-sm-1 text-right">Datum</th>
|
||||||
|
<th class="col-sm-1 text-center">Status</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody *ngFor="let award of awards">
|
||||||
|
<tr>
|
||||||
|
<td class="table-cell-id" *ngIf="award.decorationId.isMedal">
|
||||||
|
<img height="40px" src="resource/decoration/{{award.decorationId._id}}.png">
|
||||||
|
</td>
|
||||||
|
<td class="table-cell-id" *ngIf="!award.decorationId.isMedal">
|
||||||
|
<img width="60px" src="resource/decoration/{{award.decorationId._id}}.png">
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{award.decorationId.name}}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{award.reason}}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{award.proposer?.username}}
|
||||||
|
</td>
|
||||||
|
<td class="text-right">
|
||||||
|
<a class="small text-nowrap">{{award.date | date: 'dd.MM.yyyy'}}</a>
|
||||||
|
</td>
|
||||||
|
<td class="text-center">
|
||||||
|
{{award.confirmed? 'Bestätigt' : 'In Bearbeitung'}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
|
@ -0,0 +1,113 @@
|
||||||
|
import {Component, ViewChild} from "@angular/core";
|
||||||
|
import {ActivatedRoute, Router} from "@angular/router";
|
||||||
|
import {Award, Decoration, User} from "../../models/model-interfaces";
|
||||||
|
import {NgForm} from "@angular/forms";
|
||||||
|
import {AwardingService} from "../../services/awarding-service/awarding.service";
|
||||||
|
import {DecorationService} from "../../services/decoration-service/decoration.service";
|
||||||
|
import {UserService} from "../../services/user-service/user.service";
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
templateUrl: './req-award.component.html',
|
||||||
|
styleUrls: ['./req-award.component.css'],
|
||||||
|
})
|
||||||
|
export class RequestAwardComponent {
|
||||||
|
|
||||||
|
@ViewChild(NgForm) form: NgForm;
|
||||||
|
|
||||||
|
showForm = false;
|
||||||
|
|
||||||
|
showSuccessLabel = false;
|
||||||
|
|
||||||
|
user: User = {};
|
||||||
|
|
||||||
|
decorations: Decoration[];
|
||||||
|
|
||||||
|
awards: Award[];
|
||||||
|
|
||||||
|
users: User[];
|
||||||
|
|
||||||
|
decoPreviewDisplay = 'none';
|
||||||
|
|
||||||
|
constructor(private router: Router,
|
||||||
|
private route: ActivatedRoute,
|
||||||
|
private userService: UserService,
|
||||||
|
private awardingService: AwardingService,
|
||||||
|
private decorationService: DecorationService) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
let currentUser = JSON.parse(localStorage.getItem('currentUser'));
|
||||||
|
// show only current users squad members
|
||||||
|
this.userService.findUsers('', undefined, currentUser.squad).subscribe(users => {
|
||||||
|
this.users = users;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleUser() {
|
||||||
|
this.decorationService.findDecorations('', this.user.squad.fraction).subscribe(decorations => {
|
||||||
|
this.decorations = decorations;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.awardingService.getUserAwardings(this.user._id).subscribe(awards => {
|
||||||
|
this.awards = awards;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.showForm = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
toggleDecoPreview(descriptionField, decorationId, image) {
|
||||||
|
this.decoPreviewDisplay = 'flex'; // visible & keep same height for all children
|
||||||
|
|
||||||
|
const description = this.decorations.find(
|
||||||
|
decoration => decoration._id === decorationId
|
||||||
|
).description;
|
||||||
|
|
||||||
|
image.src = 'resource/decoration/' + decorationId + '.png';
|
||||||
|
descriptionField.innerHTML = description;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
addAwarding(decorationField, reasonField, previewImage, descriptionField) {
|
||||||
|
const decorationId = decorationField.value;
|
||||||
|
const reason = reasonField.value;
|
||||||
|
if (decorationId && reason.length > 0) {
|
||||||
|
const award = {
|
||||||
|
"userId": this.user._id,
|
||||||
|
"decorationId": decorationId,
|
||||||
|
"reason": reason,
|
||||||
|
"date": Date.now()
|
||||||
|
};
|
||||||
|
this.awardingService.requestAwarding(award).subscribe(() => {
|
||||||
|
this.awardingService.getUserAwardings(this.user._id)
|
||||||
|
.subscribe(awards => {
|
||||||
|
this.awards = awards;
|
||||||
|
console.log(awards[0])
|
||||||
|
this.decoPreviewDisplay = 'none';
|
||||||
|
decorationField.value = undefined;
|
||||||
|
reasonField.value = previewImage.src = descriptionField.innerHTML = '';
|
||||||
|
this.showSuccessLabel = true;
|
||||||
|
setTimeout(() => {
|
||||||
|
this.showSuccessLabel = false;
|
||||||
|
}, 2000)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cancel() {
|
||||||
|
this.router.navigate(['..'], {relativeTo: this.route});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* compare ngValue with ngModel to assign selected element
|
||||||
|
*/
|
||||||
|
equals(o1: User, o2: User) {
|
||||||
|
if (o1 && o2) {
|
||||||
|
return o1._id === o2._id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -27,6 +27,10 @@ export class AwardingService {
|
||||||
return this.http.post(this.config.apiUrl + this.config.apiAwardPath, award)
|
return this.http.post(this.config.apiUrl + this.config.apiAwardPath, award)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
requestAwarding(award) {
|
||||||
|
return this.http.post(this.config.apiUrl + this.config.apiRequestAwardPath, award)
|
||||||
|
}
|
||||||
|
|
||||||
deleteAwarding(awardingId) {
|
deleteAwarding(awardingId) {
|
||||||
return this.http.delete(this.config.apiUrl + this.config.apiAwardPath + awardingId)
|
return this.http.delete(this.config.apiUrl + this.config.apiAwardPath + awardingId)
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,12 +17,15 @@ export class UserService {
|
||||||
this.users$ = userStore.items$;
|
this.users$ = userStore.items$;
|
||||||
}
|
}
|
||||||
|
|
||||||
findUsers(query = '', fractionFilter?) {
|
findUsers(query = '', fractionFilter?, squadFilter?) {
|
||||||
const searchParams = new URLSearchParams();
|
const searchParams = new URLSearchParams();
|
||||||
searchParams.append('q', query);
|
searchParams.append('q', query);
|
||||||
if (fractionFilter) {
|
if (fractionFilter) {
|
||||||
searchParams.append('fractFilter', fractionFilter);
|
searchParams.append('fractFilter', fractionFilter);
|
||||||
}
|
}
|
||||||
|
if (squadFilter) {
|
||||||
|
searchParams.append('squadId', squadFilter);
|
||||||
|
}
|
||||||
this.http.get(this.config.apiUrl + this.config.apiUserPath, searchParams)
|
this.http.get(this.config.apiUrl + this.config.apiUserPath, searchParams)
|
||||||
.map(res => res.json())
|
.map(res => res.json())
|
||||||
.do((users) => {
|
.do((users) => {
|
||||||
|
|
|
@ -70,6 +70,7 @@
|
||||||
<th class="col-sm-2">Bezeichnung</th>
|
<th class="col-sm-2">Bezeichnung</th>
|
||||||
<th class="col-sm-2">Begründung</th>
|
<th class="col-sm-2">Begründung</th>
|
||||||
<th class="col-sm-1 text-right">Datum</th>
|
<th class="col-sm-1 text-right">Datum</th>
|
||||||
|
<th class="col-sm-1 text-center">Status</th>
|
||||||
<th class="col-sm-1 text-center"></th>
|
<th class="col-sm-1 text-center"></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
@ -90,6 +91,9 @@
|
||||||
<td class="text-right">
|
<td class="text-right">
|
||||||
<a class="small text-nowrap">{{award.date | date: 'dd.MM.yyyy'}}</a>
|
<a class="small text-nowrap">{{award.date | date: 'dd.MM.yyyy'}}</a>
|
||||||
</td>
|
</td>
|
||||||
|
<td class="text-center">
|
||||||
|
{{award.confirmed? 'Bestätigt' : 'In Bearbeitung'}}
|
||||||
|
</td>
|
||||||
<td class="text-center">
|
<td class="text-center">
|
||||||
<span class="glyphicon glyphicon-trash trash" title="Löschen" (click)="deleteAwarding(award._id)"></span>
|
<span class="glyphicon glyphicon-trash trash" title="Löschen" (click)="deleteAwarding(award._id)"></span>
|
||||||
</td>
|
</td>
|
||||||
|
|
Loading…
Reference in New Issue