Author: sskracic Date: 2005-12-20 18:51:16 +0100 (Tue, 20 Dec 2005) New Revision: 1069 Added: contrib/ccm-ldn-camden-consultation/trunk/src/com/arsdigita/camden/cms/contenttypes/ui/AlertRemoveForm.java contrib/ccm-ldn-camden-consultation/trunk/web/packages/consultations/www/alert-remove.jsp contrib/ccm-ldn-camden-consultation/trunk/web/packages/consultations/www/alert-sms-trigger.jsp Modified: contrib/ccm-ldn-camden-consultation/trunk/src/com/arsdigita/camden/cms/contenttypes/ConsultationAlert.java contrib/ccm-ldn-camden-consultation/trunk/src/com/arsdigita/camden/cms/contenttypes/ConsultationResources.properties contrib/ccm-ldn-camden-consultation/trunk/src/com/arsdigita/camden/cms/contenttypes/ConsultationUtil.java contrib/ccm-ldn-camden-consultation/trunk/src/com/arsdigita/camden/cms/contenttypes/ui/ConsultationAlertConfirm.java contrib/ccm-ldn-camden-consultation/trunk/src/com/arsdigita/camden/cms/contenttypes/ui/ConsultationAlertForm.java Log: Almost there. Implemented everything except admin page for bulk mobile number deletion. Modified: contrib/ccm-ldn-camden-consultation/trunk/src/com/arsdigita/camden/cms/contenttypes/ConsultationAlert.java =================================================================== --- contrib/ccm-ldn-camden-consultation/trunk/src/com/arsdigita/camden/cms/contenttypes/ConsultationAlert.java 2005-12-19 14:04:33 UTC (rev 1068) +++ contrib/ccm-ldn-camden-consultation/trunk/src/com/arsdigita/camden/cms/contenttypes/ConsultationAlert.java 2005-12-20 17:51:16 UTC (rev 1069) @@ -59,6 +59,8 @@ public final static String CONFIRM_PATH = "/alert.jsp"; public final static String CONFIRM_PARAMETER = "co"; public final static String CANCEL_PARAMETER = "ca"; + public final static String CANCEL_SMS_PARAMETER = "cs"; + public final static String REMOVAL_REQUEST_PARAMETER = "rr"; public ConsultationAlert() { this(BASE_DATA_OBJECT_TYPE); @@ -250,6 +252,28 @@ return result; } + public static String cancelSMS(String token) { + DataCollection alerts = + SessionManager.getSession().retrieve(BASE_DATA_OBJECT_TYPE); + alerts.addEqualsFilter(CANCELLATION_TOKEN, token); + + String result = null; + if (alerts.next()) { + ConsultationAlert alert = + new ConsultationAlert(alerts.getDataObject()); + alerts.close(); + + result = alert.getMobileNumber(); + alert.setMobileNumber(null); + alert.clearMobilePin(); + alert.setMobileConfirmed(Boolean.FALSE); + alert.save(); + } + + return result; + } + + public static ConsultationAlert findByEmail(String email) { DataCollection alerts = SessionManager.getSession().retrieve(BASE_DATA_OBJECT_TYPE); @@ -308,6 +332,9 @@ return; } + ConsultationApp app = ConsultationApp.retrieveApplication(); + String consultationURL = URL.there(app, "", null).getURL(); + // Compose the text of an SMS instance: DataCollection alerts = dbSession.retrieve(BASE_DATA_OBJECT_TYPE); @@ -317,13 +344,16 @@ String siteURL = URL.root().getURL(); String from = ConsultationUtil.getConfig().getAlertsSenderEmail(); - String[] args = { String.valueOf(itemCount), siteURL }; - String smsText = (String) ConsultationUtil.globalize("sms.alert.text", args).localize(locale); - // Not sure whether this gets through the gateway at all - String smsSubject = (String) ConsultationUtil.globalize("sms.alert.subject").localize(locale); + while (alerts.next()) { - while (alerts.next()) { ConsultationAlert alert = new ConsultationAlert(alerts.getDataObject()); + + String[] args = { String.valueOf(itemCount), siteURL, consultationURL, + alert.getEmail(), alert.getFirstNames(), alert.getLastName() }; + // Not sure whether the subject gets through the gateway at all, but just in case + String smsSubject = (String) ConsultationUtil.globalize("sms.alert.subject", args).localize(locale); + String smsText = (String) ConsultationUtil.globalize("sms.alert.text", args).localize(locale); + String mobile = alert.getMobileNumber(); // Convert mobile number to email2sms gateway address String smsEmail = ConsultationUtil.getConfig().getSMSProvider().getEmail(mobile); Modified: contrib/ccm-ldn-camden-consultation/trunk/src/com/arsdigita/camden/cms/contenttypes/ConsultationResources.properties =================================================================== --- contrib/ccm-ldn-camden-consultation/trunk/src/com/arsdigita/camden/cms/contenttypes/ConsultationResources.properties 2005-12-19 14:04:33 UTC (rev 1068) +++ contrib/ccm-ldn-camden-consultation/trunk/src/com/arsdigita/camden/cms/contenttypes/ConsultationResources.properties 2005-12-20 17:51:16 UTC (rev 1069) @@ -235,6 +235,12 @@ \ <p>You will no longer receive emails about new consultation items.</p> +# {0}: mobile number for which the SMS alert was requested +cancel_token_sms.success=\ +<p>The alert for {0} has been removed.</p>\ +\ +<p>You will no longer receive SMS alerts about new consultation items.</p> + verify_token.success=\ <p>Your request to alert {0} of newly published consultation \ items has been stored.</p>\ @@ -313,15 +319,23 @@ \n\ {3} -sms.pin.subject=PIN # {0}: PIN for mobile number verification # {1}: public URL of the server -sms.pin.text=Your PIN is {0}. Used for mob. number verification for {1} +# {2}: consultations URL +# {3}: user's email address (still not validated at this stage!) +# {4}: user's first name(s) +# {5}: user's last name +sms.pin.subject=PIN +sms.pin.text=Your PIN is {0}. Confirm your SMS subscriptionUsed for mob. number verification for {2} -sms.alert.subject=New consultations # {0}: number of newly published consultations # {1}: public URL of the server -sms.alert.text=Check {0} new consultations at {1} +# {2}: consultations URL +# {3}: user's email address +# {4}: user's first name(s) +# {5}: user's last name +sms.alert.subject=N +sms.alert.text=Check {0} new consultations at {2} -- \n{3} bulk_deletion=Bulk Deletion email_addresses=Email Addresses @@ -333,3 +347,57 @@ <p>The URL does not contain the count of deleted alerts.</p>\ \ <p>This is most likely an internal error.</p> + +remove_alert=Remove alert +remove_alert_help=To disable alerts about new consultations, please first enter the recipient email address +no_email=Email address is required +email_unknown=No alerts are being sent to this email address +request_removal=Send removal code + +# {0}: user's email address +removal_request.sent=\ +<p>Your request to disable alerts sent to {0} has been accepted.</p>\n\ +\n\ +<p>To ensure that this request was made by you, alerts will only be disabled\n\ +after you confirm the request. You will receive an email with further\n\ +instructions shortly.</p> + +# The substitutions for removal_request.subject, removal_request.body, removal_with_sms_request.subject and removal_request.with_sms.body +# are as follows: +# {0}: user's first name(s) +# {1}: user's last name +# {2}: user's email address +# {3}: public site URL +# {4}: consultation index URL +# {5}: URL for complete alert removal +# {6}: URL for disabling SMS alerts only, if set +# {7}: user's mobile number +removal_request.subject=Alert removal request for {3} +removal_request.body=\n\ + We have received a request to stop alerting {2}\n\ +of new consultation information published on {4}\n\ +\n\ + If you do not want to receive alerts for newly published content,\n\ +you can cancel them with the link below:\n\ +\n\ +{5}\n\ +\n\ + If you want to keep your alerts unchanged, no action is required. +removal_with_sms_request.subject=Alert removal request for {3} +removal_with_sms_request.body=\n\ + We have received a request to stop alerting {2}\n\ +of new consultation information published on {4}\n\ +\n\ + SMS alerts are also going to mobile number {7}.\n\ +\n\ + To disable SMS alerts, please click on the link below\n\ +(email alerts will still be active):\n\ +\n\ +{6}\n\ +\n\ + To completely cancel both SMS and email alerts, please\n\ +use this link:\n\ +\n\ +{5}\n\ +\n\ + If you want to keep your alerts unchanged, no action is required. Modified: contrib/ccm-ldn-camden-consultation/trunk/src/com/arsdigita/camden/cms/contenttypes/ConsultationUtil.java =================================================================== --- contrib/ccm-ldn-camden-consultation/trunk/src/com/arsdigita/camden/cms/contenttypes/ConsultationUtil.java 2005-12-19 14:04:33 UTC (rev 1068) +++ contrib/ccm-ldn-camden-consultation/trunk/src/com/arsdigita/camden/cms/contenttypes/ConsultationUtil.java 2005-12-20 17:51:16 UTC (rev 1069) @@ -31,6 +31,7 @@ import com.arsdigita.persistence.DataCollection; import com.arsdigita.persistence.SessionManager; import com.arsdigita.web.Application; +import com.arsdigita.web.ParameterMap; import com.arsdigita.web.URL; import java.math.BigDecimal; import java.util.Iterator; @@ -163,16 +164,19 @@ } - public static void sendPin(String mobileNumber, String pin) { + public static void sendPin(ConsultationAlert alert) { Locale locale = Locale.getDefault(); String siteURL = URL.root().getURL(); - String[] args = { pin, siteURL }; + ConsultationApp app = ConsultationApp.retrieveApplication(); + String consultationURL = URL.there(app, "", null).getURL(); + String[] args = { alert.getMobilePin(), siteURL, consultationURL, + alert.getEmail(), alert.getFirstNames(), alert.getLastName()}; String from = getConfig().getAlertsSenderEmail(); - String smsSubject = (String) globalize("sms.pin.subject").localize(locale); + String smsSubject = (String) globalize("sms.pin.subject", args).localize(locale); String smsText = (String) globalize("sms.pin.text", args).localize(locale); - String smsEmail = getConfig().getSMSProvider().getEmail(mobileNumber); + String smsEmail = getConfig().getSMSProvider().getEmail(alert.getMobileNumber()); try { - s_log.debug("About to send PIN to " + mobileNumber + " using email: " + smsEmail); + s_log.debug("About to send PIN to " + alert.getMobileNumber() + " using email: " + smsEmail); Mail.send(smsEmail, from, smsSubject, smsText); } catch (MessagingException ex) { s_log.warn("Exception while sending pin to " + @@ -181,4 +185,44 @@ } + public static void sendAlertRemovalLinks(ConsultationAlert alert) { + Locale locale = Locale.getDefault(); + String siteURL = URL.root().getURL(); + ConsultationApp app = ConsultationApp.retrieveApplication(); + String consultationURL = URL.there(app, "", null).getURL(); + String from = getConfig().getAlertsSenderEmail(); + String to = alert.getEmail(); + String subject; + String body; + ParameterMap parameters = new ParameterMap(); + parameters.setParameter(ConsultationAlert.CANCEL_PARAMETER, + alert.getCancellationToken()); + String alertRemovalURL = + URL.there(app, ConsultationAlert.CONFIRM_PATH, parameters).getURL(); + parameters = new ParameterMap(); + parameters.setParameter(ConsultationAlert.CANCEL_SMS_PARAMETER, + alert.getCancellationToken()); + String smsRemovalURL = + URL.there(app, ConsultationAlert.CONFIRM_PATH, parameters).getURL(); + + String[] args = { alert.getFirstNames(), alert.getLastName(), alert.getEmail(), + siteURL, consultationURL, alertRemovalURL, smsRemovalURL, + alert.getMobileNumber() }; + if (Boolean.TRUE.equals(alert.getMobileConfirmed())) { + subject = (String) globalize("removal_with_sms_request.subject", args).localize(locale); + body = (String) globalize("removal_with_sms_request.body", args).localize(locale); + } else { + subject = (String) globalize("removal_request.subject", args).localize(locale); + body = (String) globalize("removal_request.body", args).localize(locale); + } + try { + s_log.debug("Sending alert removal links to " + to); + Mail.send(to, from, subject, body); + } catch (MessagingException ex) { + s_log.warn("Exception while sending email to " + + to + ": " + ex.getMessage()); + } + } + + } Added: contrib/ccm-ldn-camden-consultation/trunk/src/com/arsdigita/camden/cms/contenttypes/ui/AlertRemoveForm.java =================================================================== --- contrib/ccm-ldn-camden-consultation/trunk/src/com/arsdigita/camden/cms/contenttypes/ui/AlertRemoveForm.java 2005-12-19 14:04:33 UTC (rev 1068) +++ contrib/ccm-ldn-camden-consultation/trunk/src/com/arsdigita/camden/cms/contenttypes/ui/AlertRemoveForm.java 2005-12-20 17:51:16 UTC (rev 1069) @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2005 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.camden.cms.contenttypes.ui; + +import com.arsdigita.bebop.FormData; +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.event.FormProcessListener; +import com.arsdigita.bebop.event.FormSectionEvent; +import com.arsdigita.bebop.event.ParameterEvent; +import com.arsdigita.bebop.event.ParameterListener; +import com.arsdigita.bebop.form.Submit; +import com.arsdigita.bebop.parameters.EmailValidationListener; +import com.arsdigita.bebop.parameters.ParameterData; +import com.arsdigita.camden.cms.contenttypes.ConsultationAlert; +import com.arsdigita.camden.cms.contenttypes.ConsultationUtil; +import com.arsdigita.cms.ui.BaseForm; +import com.arsdigita.globalization.GlobalizedMessage; +import com.arsdigita.persistence.DataCollection; +import com.arsdigita.persistence.SessionManager; +import com.arsdigita.web.ParameterMap; +import com.arsdigita.web.RedirectSignal; +import com.arsdigita.web.URL; + +/** + * <p>Allows user to disable either SMS or both email and SMS + * alerts. </p> + * + * @author Sebastian Skracic + * @version $Id$ + */ +public class AlertRemoveForm + extends BaseForm implements FormProcessListener { + + public final static String FORM_NAME = "remove"; + + public AlertRemoveForm() { + this(FORM_NAME, ConsultationUtil.globalize("remove_alert")); + } + + public AlertRemoveForm(String name, GlobalizedMessage heading) { + this(name, new Label(heading)); + } + + public AlertRemoveForm(String name, Label heading) { + super(name, heading); + + addWidgets(); + } + + private void addWidgets() { + + addComponent(new Label(ConsultationUtil.globalize("remove_alert_help"))); + + Name email = new Name(ConsultationAlert.EMAIL, 100, false); + + email.addValidationListener(new ParameterListener() { + + private EmailValidationListener m_emailValidation = + new EmailValidationListener(); + + public void validate(ParameterEvent e) throws FormProcessException { + PageState state = e.getPageState(); + ParameterData data = e.getParameterData(); + + if (isCancelled(state)) + return; + + m_emailValidation.validate(e); + if (!data.isValid()) + return; + + String email = ((String)data.getValue()).toLowerCase().trim(); + if (email.length() == 0) { + data.addError((String)ConsultationUtil. + globalize("no_email").localize()); + return; + } + + DataCollection alerts = + SessionManager.getSession(). + retrieve(ConsultationAlert.BASE_DATA_OBJECT_TYPE); + alerts.addEqualsFilter(ConsultationAlert.EMAIL, email); + alerts.addEqualsFilter(ConsultationAlert.EMAIL_CONFIRMED, Boolean.TRUE); + if (!alerts.next()) { + data.addError((String)ConsultationUtil. + globalize("email_unknown").localize()); + } + alerts.close(); + } + + }); + addField(ConsultationUtil.globalize("email"), email); + + addAction(new Submit(ConsultationUtil.globalize("request_removal"))); + addAction(new Cancel()); + + addProcessListener(this); + } + + public void process(FormSectionEvent event) throws FormProcessException { + FormData data = event.getFormData(); + PageState state = event.getPageState(); + + if (isCancelled(state)) { + URL target = URL.here(state.getRequest(), null); + throw new RedirectSignal(target, false); + } + + String email = + data.getString(ConsultationAlert.EMAIL).toLowerCase().trim(); + + DataCollection alerts = + SessionManager.getSession(). + retrieve(ConsultationAlert.BASE_DATA_OBJECT_TYPE); + alerts.addEqualsFilter(ConsultationAlert.EMAIL, email); + + if (!alerts.next()) { + alerts.close(); + throw new FormProcessException( (String)ConsultationUtil. + globalize("email_unknown").localize()); + } + ConsultationAlert alert = new ConsultationAlert(alerts.getDataObject()); + alerts.close(); + + // Send the email containing a link for SMS alert removal, if set. + // The email will also contain a link to remove all alerts. + ConsultationUtil.sendAlertRemovalLinks(alert); + + ParameterMap parameters = new ParameterMap(); + parameters.setParameter(ConsultationAlert.REMOVAL_REQUEST_PARAMETER, alert.getID()); + URL target = + URL.here(state.getRequest(), ConsultationAlert.CONFIRM_PATH, parameters); + throw new RedirectSignal(target, true); + } +} + Property changes on: contrib/ccm-ldn-camden-consultation/trunk/src/com/arsdigita/camden/cms/contenttypes/ui/AlertRemoveForm.java ___________________________________________________________________ Name: svn:keywords + Id Author URL Modified: contrib/ccm-ldn-camden-consultation/trunk/src/com/arsdigita/camden/cms/contenttypes/ui/ConsultationAlertConfirm.java =================================================================== --- contrib/ccm-ldn-camden-consultation/trunk/src/com/arsdigita/camden/cms/contenttypes/ui/ConsultationAlertConfirm.java 2005-12-19 14:04:33 UTC (rev 1068) +++ contrib/ccm-ldn-camden-consultation/trunk/src/com/arsdigita/camden/cms/contenttypes/ui/ConsultationAlertConfirm.java 2005-12-20 17:51:16 UTC (rev 1069) @@ -55,6 +55,18 @@ return; } + tokens = (String[])parameters.get(ConsultationAlert.CANCEL_SMS_PARAMETER); + if (tokens != null && tokens.length > 0) { + String mobile = ConsultationAlert.cancelSMS(tokens[0]); + if (mobile == null) { + target.setLabel(ConsultationUtil.globalize("cancel_token.invalid")); + return; + } + String[] args = {mobile}; + target.setLabel(ConsultationUtil.globalize("cancel_token_sms.success", args)); + return; + } + tokens = (String[])parameters.get(ConsultationAlert.CANCEL_PARAMETER); if (tokens != null && tokens.length > 0) { String email = ConsultationAlert.cancel(tokens[0]); @@ -68,6 +80,20 @@ return; } + tokens = (String[])parameters.get(ConsultationAlert.REMOVAL_REQUEST_PARAMETER); + if (tokens != null && tokens.length > 0) { + ConsultationAlert alert; + try { + alert = new ConsultationAlert(new BigDecimal(tokens[0])); + } catch (DataObjectNotFoundException ex) { + // This should not happen. + throw new RuntimeException(ex); + } + String[] args = {alert.getEmail()}; + target.setLabel(ConsultationUtil.globalize("removal_request.sent", args)); + return; + } + tokens = (String[])parameters.get(ConsultationAlert.ID); if (tokens != null && tokens.length > 0) { ConsultationAlert alert; @@ -77,7 +103,6 @@ // This should not happen. throw new RuntimeException(ex); } - String[] args = {alert.getEmail()}; target.setLabel(ConsultationUtil.globalize("verify_token.success", args)); return; Modified: contrib/ccm-ldn-camden-consultation/trunk/src/com/arsdigita/camden/cms/contenttypes/ui/ConsultationAlertForm.java =================================================================== --- contrib/ccm-ldn-camden-consultation/trunk/src/com/arsdigita/camden/cms/contenttypes/ui/ConsultationAlertForm.java 2005-12-19 14:04:33 UTC (rev 1068) +++ contrib/ccm-ldn-camden-consultation/trunk/src/com/arsdigita/camden/cms/contenttypes/ui/ConsultationAlertForm.java 2005-12-20 17:51:16 UTC (rev 1069) @@ -271,7 +271,7 @@ alert.save(); m_pinLabel.setVisible(state, true); m_pin.setVisible(state, true); - ConsultationUtil.sendPin(mobile, alert.getMobilePin()); + ConsultationUtil.sendPin(alert); return; } else { // clear the mobile number that might have been submitted previously Added: contrib/ccm-ldn-camden-consultation/trunk/web/packages/consultations/www/alert-remove.jsp =================================================================== --- contrib/ccm-ldn-camden-consultation/trunk/web/packages/consultations/www/alert-remove.jsp 2005-12-19 14:04:33 UTC (rev 1068) +++ contrib/ccm-ldn-camden-consultation/trunk/web/packages/consultations/www/alert-remove.jsp 2005-12-20 17:51:16 UTC (rev 1069) @@ -0,0 +1,36 @@ +<jsp:root + xmlns:jsp="http://java.sun.com/JSP/Page" + xmlns:define="/WEB-INF/bebop-define.tld" + xmlns:show="/WEB-INF/bebop-show.tld" + version="1.2"> + + <jsp:directive.page import="com.arsdigita.dispatcher.DispatcherHelper"/> + <jsp:directive.page import="com.arsdigita.camden.cms.contenttypes.ui.ConsultationsNavigationModel" /> + <jsp:directive.page import="com.arsdigita.london.navigation.Navigation"/> + <jsp:directive.page import="com.arsdigita.london.navigation.NavigationModel"/> + + <jsp:scriptlet> + DispatcherHelper.cacheDisable(response); + </jsp:scriptlet> + + <define:page name="alertNewPage" application="navigation" title="Remove Consultation Alert" cache="true"> + <define:component name="greetingItem" + classname="com.arsdigita.london.navigation.ui.GreetingItem"/> + <define:component name="categoryPath" + classname="com.arsdigita.london.navigation.ui.category.Path"/> + <define:component name="categoryMenu" + classname="com.arsdigita.london.navigation.ui.category.Menu"/> + <define:component name="alertForm" + classname="com.arsdigita.camden.cms.contenttypes.ui.AlertRemoveForm"/> + + <jsp:scriptlet> + NavigationModel navModel = ConsultationsNavigationModel.retrieve(); + ((com.arsdigita.london.navigation.ui.GreetingItem)greetingItem).setModel(navModel); + ((com.arsdigita.london.navigation.ui.category.Path)categoryPath).setModel(navModel); + ((com.arsdigita.london.navigation.ui.category.Menu)categoryMenu).setModel(navModel); + </jsp:scriptlet> + </define:page> + + <show:all/> +</jsp:root> + Added: contrib/ccm-ldn-camden-consultation/trunk/web/packages/consultations/www/alert-sms-trigger.jsp =================================================================== --- contrib/ccm-ldn-camden-consultation/trunk/web/packages/consultations/www/alert-sms-trigger.jsp 2005-12-19 14:04:33 UTC (rev 1068) +++ contrib/ccm-ldn-camden-consultation/trunk/web/packages/consultations/www/alert-sms-trigger.jsp 2005-12-20 17:51:16 UTC (rev 1069) @@ -0,0 +1,18 @@ +<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="1.2"> + + <jsp:directive.page extends="com.arsdigita.web.BaseJSP"/> + + <jsp:directive.page import="com.arsdigita.kernel.*"/> + <jsp:directive.page import="com.arsdigita.camden.cms.contenttypes.*"/> + <jsp:directive.page import="com.arsdigita.web.*"/> + + <jsp:scriptlet> + ConsultationAlert.sendSMSAlerts(); + </jsp:scriptlet> + + <p> + "<%= "success" %>"<br /> + </p> + +</jsp:root> + |