From b40c664bce3aa17b18e5faadde279934f2af223e Mon Sep 17 00:00:00 2001 From: Florian Hartwich Date: Sat, 28 Apr 2018 11:55:58 +0200 Subject: [PATCH] add functional endpoint for update campaign and unhappy frontend processing --- api/apib/dredd/data/campaign.json | 1 + api/apib/statistics/campaigns.apib | 19 ++++++++++ api/routes/campaigns.js | 35 +++++++++++++++++-- .../src/app/services/logs/campaign.service.ts | 11 +++--- .../campaign-submit.component.ts | 6 +++- 5 files changed, 63 insertions(+), 9 deletions(-) diff --git a/api/apib/dredd/data/campaign.json b/api/apib/dredd/data/campaign.json index 2c31b97..51442c2 100644 --- a/api/apib/dredd/data/campaign.json +++ b/api/apib/dredd/data/campaign.json @@ -1,2 +1,3 @@ {"_id":{"$oid":"5abd55ea9e30a76bfef747d6"},"title":"Ein Kessel Buntes","timestamp":{"$date":"2018-03-29T21:08:58.123Z"},"updatedAt":{"$date":"2018-03-29T21:08:58.123Z"},"__v":0} {"_id":{"$oid":"5abd58989e30a76bfef747e6"},"title":"This Is The End","timestamp":{"$date":"2018-03-29T21:20:24.558Z"},"updatedAt":{"$date":"2018-03-29T21:20:24.558Z"},"__v":0} +{"_id":{"$oid":"5abd58es9e30a76bfef347e4"},"title":"Edit me","timestamp":{"$date":"2018-03-29T21:20:24.558Z"},"updatedAt":{"$date":"2018-03-29T21:20:24.558Z"},"__v":0} diff --git a/api/apib/statistics/campaigns.apib b/api/apib/statistics/campaigns.apib index 915aa26..7915294 100644 --- a/api/apib/statistics/campaigns.apib +++ b/api/apib/statistics/campaigns.apib @@ -24,6 +24,25 @@ Create a new campaign + Attributes (Campaign, fixed-type) +### Update Campaign [PUT /campaigns/{id}] + +Update a campaign, identified by its id + +**Permission: 3** + ++ Parameters + + id: `5abd58es9e30a76bfef347e4` (string, required) - unique id of campaign + ++ Request (application/json) + + + Attributes + + _id: `5abd58es9e30a76bfef347e4` (string, required) - unique id of campaign + + title: `Operation Pandora` (string, optional) - display name of the campaign + ++ Response 200 (application/json; charset=utf-8) + + + Attributes (Campaign, fixed-type) + ### Delete Campaign [DELETE /campaigns/{id}] Delete a campaign diff --git a/api/routes/campaigns.js b/api/routes/campaigns.js index 0cb9c85..f42bb4a 100644 --- a/api/routes/campaigns.js +++ b/api/routes/campaigns.js @@ -16,12 +16,10 @@ const idValidator = require('../middleware/validators').idValidator; const CampaignModel = require('../models/campaign'); const WarModel = require('../models/war'); - const campaigns = new express.Router(); // routes ********************** campaigns.route('/') - .post(apiAuthenticationMiddleware, checkMT, (req, res, next) => { const campaign = new CampaignModel(req.body); // timestamp and default are set automatically by Mongoose Schema Validation @@ -57,6 +55,37 @@ campaigns.route('/:id') }); }) + .patch(apiAuthenticationMiddleware, checkMT, (req, res, next) => { + if (!req.body || (req.body._id && req.body._id !== req.params.id)) { + // little bit different as in PUT. :id does not need to be in data, but if the _id and url id must match + const err = new Error('id of PATCH resource and send JSON body are not equal ' + req.params.id + ' ' + + req.body._id); + err.status = codes.notfound; + next(err); + return; // prevent node to process this function further after next() has finished. + } + + req.body.updatedAt = new Date(); + req.body.$inc = { __v: 1 }; + if (req.body.hasOwnProperty('__v')) { + delete req.body.__v; + } + + // PATCH is easier with mongoose than PUT. You simply update by all data that comes from outside. no need to + // reset attributes that are missing. + CampaignModel.findByIdAndUpdate(req.params.id, req.body, { new: true }, (err, item) => { + if (err) { + err.status = codes.wrongrequest; + } else if (!item) { + err = new Error('item not found'); + err.status = codes.notfound; + } else { + res.locals.items = item; + } + next(err); + }); + }) + .delete((req, res, next) => { CampaignModel.findByIdAndRemove(req.params.id, (err, item) => { if (err) { @@ -67,7 +96,7 @@ campaigns.route('/:id') err.status = codes.notfound; return next(err); } - WarModel.find({campaign: req.params.id}).remove().exec(); + WarModel.find({ campaign: req.params.id }).remove().exec(); // TODO: remove all the war logs from fs here!!! res.locals.processed = true; next(); diff --git a/static/src/app/services/logs/campaign.service.ts b/static/src/app/services/logs/campaign.service.ts index 6d4e806..d4cc7ef 100644 --- a/static/src/app/services/logs/campaign.service.ts +++ b/static/src/app/services/logs/campaign.service.ts @@ -14,27 +14,28 @@ export class CampaignService { getAllCampaigns() { return this.http.get(this.config.apiWarPath) - .map(res => res.json()); + .map(res => res.json()); } submitCampaign(campaign: Campaign) { if (campaign._id) { - return this.http.patch(this.config.apiCampaignPath + '/' + campaign._id, campaign); + return this.http.patch(this.config.apiCampaignPath + '/' + campaign._id, campaign) + .map(res => res.json()); } else { return this.http.post(this.config.apiCampaignPath, campaign) - .map(res => res.json()); + .map(res => res.json()); } } deleteCampaign(id: string) { return this.http.delete(this.config.apiCampaignPath + '/' + id) - .map(res => res.json()); + .map(res => res.json()); } getCampaign(id: string) { return this.http.get(this.config.apiCampaignPath + '/' + id) - .map(res => res.json()); + .map(res => res.json()); } } diff --git a/static/src/app/statistic/campaign-submit/campaign-submit.component.ts b/static/src/app/statistic/campaign-submit/campaign-submit.component.ts index 588a905..0d5d9f5 100644 --- a/static/src/app/statistic/campaign-submit/campaign-submit.component.ts +++ b/static/src/app/statistic/campaign-submit/campaign-submit.component.ts @@ -39,7 +39,11 @@ export class CampaignSubmitComponent { saveCampaign() { this.campaignService.submitCampaign(this.campaign) .subscribe(campaign => { - this.router.navigate(['../overview/' + campaign._id], {relativeTo: this.route}); + let redirectSuccessUrl = '../overview/'; + if (this.campaign._id) { + redirectSuccessUrl = '../' + redirectSuccessUrl + } + this.router.navigate([redirectSuccessUrl + campaign._id], {relativeTo: this.route}); }, error => { this.error = error._body.error.message;