Browse Source

Newsletter (minus actually sending them)

pull/1/head
Rob Colbert 3 years ago
parent
commit
5e53c3cc79
  1. 36
      app/controllers/admin/newsletter.js
  2. 5
      app/services/newsletter.js
  3. 31
      app/views/admin/newsletter/index.pug
  4. 4
      app/views/components/button-icon.pug
  5. 2
      app/views/components/library.pug
  6. 25
      client/js/site-admin-host-stats-app.js

36
app/controllers/admin/newsletter.js

@ -7,7 +7,7 @@
const DTP_COMPONENT_NAME = 'admin:newsletter';
const express = require('express');
const { SiteController } = require('../../../lib/site-lib');
const { SiteController, SiteError } = require('../../../lib/site-lib');
class NewsletterController extends SiteController {
@ -33,6 +33,8 @@ class NewsletterController extends SiteController {
router.get('/', this.getIndex.bind(this));
router.delete('/:newsletterId', this.deleteNewsletter.bind(this));
return router;
}
@ -40,6 +42,9 @@ class NewsletterController extends SiteController {
const { newsletter: newsletterService } = this.dtp.services;
try {
res.locals.newsletter = await newsletterService.getById(newsletterId);
if (!res.locals.newsletter) {
throw new SiteError(404, 'Newsletter not found');
}
return next();
} catch (error) {
this.log.error('failed to populate newsletterId', { newsletterId, error });
@ -62,7 +67,7 @@ class NewsletterController extends SiteController {
const { newsletter: newsletterService } = this.dtp.services;
try {
const newsletter = await newsletterService.create(req.user, req.body);
res.redirect(`/admin/newsletter/${newsletter._id}`);
res.redirect('/admin/newsletter');
} catch (error) {
this.log.error('failed to update newsletter', { error });
return next(error);
@ -83,6 +88,33 @@ class NewsletterController extends SiteController {
return next(error);
}
}
async deleteNewsletter (req, res, next) {
const { newsletter: newsletterService, displayEngine: displayEngineService } = this.dtp.services;
try {
const displayList = displayEngineService.createDisplayList('delete-newsletter');
await newsletterService.deleteNewsletter(res.locals.newsletter);
displayList.removeElement(`li[data-newsletter-id="${res.locals.newsletter._id}"]`);
displayList.showNotification(
`Newsletter "${res.locals.newsletter.title}" deleted`,
'success',
'bottom-center',
3000,
);
res.status(200).json({ success: true, displayList });
} catch (error) {
this.log.error('failed to delete newsletter', {
newsletterId: res.local.newsletter._id,
error,
});
res.status(error.statusCode || 500).json({
success: false,
message: error.message,
});
}
}
}
module.exports = async (dtp) => {

5
app/services/newsletter.js

@ -109,6 +109,11 @@ class NewsletterService extends SiteService {
return recipient.toObject();
}
async deleteNewsletter (newsletter) {
this.log.info('deleting newsletter', { newsletterId: newsletter._id });
await Newsletter.deleteOne({ _id: newsletter._id });
}
}
module.exports = {

31
app/views/admin/newsletter/index.pug

@ -7,26 +7,33 @@ block content
h1.uk-text-truncate Newsletters
.uk-width-auto
a(href="/admin/newsletter/compose").uk-button.dtp-button-primary
span
i.fas.fa-plus
span(class="uk-visible@m").uk-margin-small-left New Newsletter
+renderButtonIcon('fa-plus', 'New Newsletter')
.uk-margin
if (Array.isArray(newsletters) && (newsletters.length > 0))
ul.uk-list
each newsletter in newsletters
li
li(data-newsletter-id= newsletter._id)
div(uk-grid).uk-grid-small.uk-flex-middle
.uk-width-expand
a(href=`/admin/newsletter/${newsletter._id}`).uk-display-block.uk-text-large.uk-text-truncate= newsletter.title
.uk-width-auto
button(type="button").uk-button.dtp-button-default
span
i.fas.fa-trash
span(class="uk-visible@m").uk-margin-small-left Delete
button(type="button").uk-button.dtp-button-default
span
i.fas.fa-paper-plane
span(class="uk-visible@m").uk-margin-small-left Send
div(uk-grid).uk-grid-small
.uk-width-auto
button(
type="button",
data-newsletter-id= newsletter._id,
data-newsletter-title= newsletter.title,
onclick="return dtp.adminApp.deleteNewsletter(event);",
).uk-button.dtp-button-danger
+renderButtonIcon('fa-trash', 'Delete')
.uk-width-auto
button(type="button").uk-button.dtp-button-default
+renderButtonIcon('fa-paper-plane', 'Send')
else
div There are no newsletters at this time.

4
app/views/components/button-icon.pug

@ -0,0 +1,4 @@
mixin renderButtonIcon (buttonClass, buttonLabel)
span
i(class=`fas ${buttonClass}`)
span(class="uk-visible@m").uk-margin-small-left= buttonLabel

2
app/views/components/library.pug

@ -1,5 +1,7 @@
//- common routines for all views everywhere
include button-icon
-
function formatCount(value) {
value = value || 0;

25
client/js/site-admin-host-stats-app.js

@ -22,6 +22,7 @@ const CHART_LINE_RX_SEC = 'rgb(6, 154, 240)';
import DtpApp from 'dtp/dtp-app.js';
import numeral from 'numeral';
import UIkit from 'uikit';
// import UIkit from 'uikit';
export default class DtpSiteAdminHostStatsApp extends DtpApp {
@ -200,6 +201,30 @@ export default class DtpSiteAdminHostStatsApp extends DtpApp {
this.charts.interfaces.push(chart);
});
}
async deleteNewsletter (event) {
const newsletterId = event.currentTarget.getAttribute('data-newsletter-id');
const newsletterTitle = event.currentTarget.getAttribute('data-newsletter-title');
console.log(newsletterId, newsletterTitle);
try {
await UIkit.modal.confirm(`Are you sure you want to delete "${newsletterTitle}"`);
} catch (error) {
this.log.info('deleteNewsletter', 'aborted');
return;
}
try {
const response = await fetch(`/admin/newsletter/${newsletterId}`, {
method: 'DELETE',
});
if (!response.ok) {
throw new Error('Failed to delete newsletter');
}
await this.processResponse(response);
} catch (error) {
this.log.error('deleteNewsletter', 'failed to delete newsletter', { newsletterId, newsletterTitle, error });
UIkit.modal.alert(`Failed to delete newsletter: ${error.message}`);
}
}
}
dtp.DtpSiteAdminHostStatsApp = DtpSiteAdminHostStatsApp;
Loading…
Cancel
Save