diff --git a/frontend/src/Subscriber.js b/frontend/src/Subscriber.js index c840a6a..dde8f03 100644 --- a/frontend/src/Subscriber.js +++ b/frontend/src/Subscriber.js @@ -1,4 +1,5 @@ import React from "react" +import { Link } from "react-router-dom" import { Row, Col, @@ -156,6 +157,27 @@ class CreateFormDef extends React.PureComponent { }) } + handleSendOptinMail = record => { + this.props + .request(cs.Routes.SendSubscriberOptinMail, cs.MethodPost, { + id: record.id + }) + .then(r => { + notification["success"]({ + placement: cs.MsgPosition, + message: "Sent", + description: `Opt-in e-mail sentto ${record.email}` + }) + }) + .catch(e => { + notification["error"]({ + placement: cs.MsgPosition, + message: "Error", + description: e.message + }) + }) + } + render() { const { formType, record } = this.props const { getFieldDecorator } = this.props.form @@ -240,6 +262,24 @@ class CreateFormDef extends React.PureComponent { ))} )} + {record.lists && + record.lists.some(l => { + return ( + l.subscription_status === cs.SubscriptionStatusUnConfirmed + ) + }) && ( + + { + e.preventDefault() + this.handleSendOptinMail(record) + }} + to={`/`} + > + Send opt-in e-mail + + + )}
diff --git a/frontend/src/constants.js b/frontend/src/constants.js index 9b6c31d..f167e4d 100644 --- a/frontend/src/constants.js +++ b/frontend/src/constants.js @@ -83,6 +83,7 @@ export const Routes = { UpdateSubscriber: "/api/subscribers/:id", DeleteSubscriber: "/api/subscribers/:id", DeleteSubscribers: "/api/subscribers", + SendSubscriberOptinMail: "/api/subscribers/:id/optin", BlacklistSubscriber: "/api/subscribers/:id/blacklist", BlacklistSubscribers: "/api/subscribers/blacklist", AddSubscriberToLists: "/api/subscribers/lists/:id", diff --git a/handlers.go b/handlers.go index 52713e4..e462e4b 100644 --- a/handlers.go +++ b/handlers.go @@ -44,6 +44,7 @@ func registerHandlers(e *echo.Echo) { e.GET("/api/subscribers/:id/export", handleExportSubscriberData) e.POST("/api/subscribers", handleCreateSubscriber) e.PUT("/api/subscribers/:id", handleUpdateSubscriber) + e.POST("/api/subscribers/:id/optin", handleGetSubscriberSendOptin) e.PUT("/api/subscribers/blacklist", handleBlacklistSubscribers) e.PUT("/api/subscribers/:id/blacklist", handleBlacklistSubscribers) e.PUT("/api/subscribers/lists/:id", handleManageSubscriberLists) diff --git a/subscribers.go b/subscribers.go index e18c254..f2c9fdb 100644 --- a/subscribers.go +++ b/subscribers.go @@ -232,6 +232,36 @@ func handleUpdateSubscriber(c echo.Context) error { return handleGetSubscriber(c) } +// handleGetSubscriberSendOptin sends an optin confirmation e-mail to a subscriber. +func handleGetSubscriberSendOptin(c echo.Context) error { + var ( + app = c.Get("app").(*App) + id, _ = strconv.Atoi(c.Param("id")) + out models.Subscribers + ) + + if id < 1 { + return echo.NewHTTPError(http.StatusBadRequest, "Invalid subscriber ID.") + } + + // Fetch the subscriber. + err := app.Queries.GetSubscriber.Select(&out, id, nil) + if err != nil { + return echo.NewHTTPError(http.StatusInternalServerError, + fmt.Sprintf("Error fetching subscriber: %s", pqErrMsg(err))) + } + if len(out) == 0 { + return echo.NewHTTPError(http.StatusBadRequest, "Subscriber not found.") + } + + if err := sendOptinConfirmation(out[0], nil, app); err != nil { + return echo.NewHTTPError(http.StatusBadRequest, + "Error sending opt-in e-mail.") + } + + return c.JSON(http.StatusOK, okResp{true}) +} + // handleBlacklistSubscribers handles the blacklisting of one or more subscribers. // It takes either an ID in the URI, or a list of IDs in the request body. func handleBlacklistSubscribers(c echo.Context) error {