diff --git a/notification-portlet-api/src/main/java/org/jasig/portlet/notice/NotificationAction.java b/notification-portlet-api/src/main/java/org/jasig/portlet/notice/NotificationAction.java index 5217bcdb..ef81f0a5 100644 --- a/notification-portlet-api/src/main/java/org/jasig/portlet/notice/NotificationAction.java +++ b/notification-portlet-api/src/main/java/org/jasig/portlet/notice/NotificationAction.java @@ -19,9 +19,11 @@ package org.jasig.portlet.notice; +import java.io.IOException; import java.io.Serializable; import javax.portlet.ActionRequest; +import javax.portlet.ActionResponse; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; @@ -76,8 +78,8 @@ public final void setLabel(String label) { /** * Perform this action on the notification to which it is attached. */ - public abstract void invoke(ActionRequest req); - + public abstract void invoke(ActionRequest req, ActionResponse res) throws IOException; + /** * Implements deep-copy clone. * diff --git a/notification-portlet-webapp/src/main/java/org/jasig/portlet/notice/action/favorite/FavoriteAction.java b/notification-portlet-webapp/src/main/java/org/jasig/portlet/notice/action/favorite/FavoriteAction.java index 363d3d5f..b2e4f633 100644 --- a/notification-portlet-webapp/src/main/java/org/jasig/portlet/notice/action/favorite/FavoriteAction.java +++ b/notification-portlet-webapp/src/main/java/org/jasig/portlet/notice/action/favorite/FavoriteAction.java @@ -19,10 +19,12 @@ package org.jasig.portlet.notice.action.favorite; +import java.io.IOException; import java.util.HashSet; import java.util.Set; import javax.portlet.ActionRequest; +import javax.portlet.ActionResponse; import javax.portlet.PortletPreferences; import javax.portlet.PortletRequest; @@ -70,7 +72,7 @@ public static final FavoriteAction createUnfavoriteInstance() { * Invoking a FavoriteAction toggles it. */ @Override - public void invoke(final ActionRequest req) { + public void invoke(final ActionRequest req, final ActionResponse res) throws IOException { final NotificationEntry entry = getTarget(); final String notificationId = entry.getId(); final Set favoriteNotices = this.getFavoriteNotices(req); diff --git a/notification-portlet-webapp/src/main/java/org/jasig/portlet/notice/action/hide/HideAction.java b/notification-portlet-webapp/src/main/java/org/jasig/portlet/notice/action/hide/HideAction.java index db0cc406..02c7496e 100644 --- a/notification-portlet-webapp/src/main/java/org/jasig/portlet/notice/action/hide/HideAction.java +++ b/notification-portlet-webapp/src/main/java/org/jasig/portlet/notice/action/hide/HideAction.java @@ -19,10 +19,12 @@ package org.jasig.portlet.notice.action.hide; +import java.io.IOException; import java.util.HashMap; import java.util.Map; import javax.portlet.ActionRequest; +import javax.portlet.ActionResponse; import javax.portlet.PortletPreferences; import javax.portlet.PortletRequest; @@ -70,7 +72,7 @@ public HideAction() { * Invoking a HideAction toggles it. */ @Override - public void invoke(final ActionRequest req) { + public void invoke(final ActionRequest req, final ActionResponse res) throws IOException { final NotificationEntry entry = getTarget(); final String notificationId = entry.getId(); final Map hiddenNoticesMap = this.getHiddenNoticesMap(req); diff --git a/notification-portlet-webapp/src/main/java/org/jasig/portlet/notice/action/read/ReadAction.java b/notification-portlet-webapp/src/main/java/org/jasig/portlet/notice/action/read/ReadAction.java index c8d4545c..39d93496 100644 --- a/notification-portlet-webapp/src/main/java/org/jasig/portlet/notice/action/read/ReadAction.java +++ b/notification-portlet-webapp/src/main/java/org/jasig/portlet/notice/action/read/ReadAction.java @@ -19,10 +19,12 @@ package org.jasig.portlet.notice.action.read; +import java.io.IOException; import java.util.HashSet; import java.util.Set; import javax.portlet.ActionRequest; +import javax.portlet.ActionResponse; import javax.portlet.PortletPreferences; import javax.portlet.PortletRequest; @@ -75,7 +77,7 @@ public static final ReadAction createUnReadInstance() { * Invoking a ReadAction toggles it. */ @Override - public void invoke(final ActionRequest req) { + public void invoke(final ActionRequest req, final ActionResponse res) throws IOException { final NotificationEntry entry = getTarget(); final String notificationId = entry.getId(); final Set readNotices = this.getReadNotices(req); diff --git a/notification-portlet-webapp/src/main/java/org/jasig/portlet/notice/action/stateChange/StateChangeAction.java b/notification-portlet-webapp/src/main/java/org/jasig/portlet/notice/action/stateChange/StateChangeAction.java new file mode 100644 index 00000000..e6617774 --- /dev/null +++ b/notification-portlet-webapp/src/main/java/org/jasig/portlet/notice/action/stateChange/StateChangeAction.java @@ -0,0 +1,66 @@ +/** + * Licensed to Jasig under one or more contributor license + * agreements. See the NOTICE file distributed with this work + * for additional information regarding copyright ownership. + * Jasig licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a + * copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.jasig.portlet.notice.action.stateChange; + +import java.io.IOException; +import java.util.Date; +import java.util.Map; +import javax.portlet.ActionRequest; +import javax.portlet.ActionResponse; +import javax.portlet.PortletPreferences; +import org.jasig.portlet.notice.NotificationAction; +import org.jasig.portlet.notice.NotificationEntry; +import org.jasig.portlet.notice.NotificationState; +import org.jasig.portlet.notice.service.jpa.JpaNotificationService; +import org.jasig.portlet.notice.util.SpringContext; + +/** + * + * @author mglazier + */ +public class StateChangeAction extends NotificationAction { + + @Override + public void invoke(final ActionRequest req, final ActionResponse res) throws IOException { + JpaNotificationService jpaService = (JpaNotificationService) SpringContext.getApplicationContext().getBean("jpaNotificationService"); + + final PortletPreferences prefs = req.getPreferences(); + final String clickedState = prefs.getValue("applyStateWhenClicked", "COMPLETED"); + NotificationState notificationState = NotificationState.valueOf(clickedState); + + boolean completedStateFound = false; + + final NotificationEntry entry = getTarget(); + Map stateMap = entry.getStates(); + if (stateMap != null && stateMap.size() > 0) { + for ( NotificationState state: stateMap.keySet()) { + if (state == notificationState) { + completedStateFound = true; + } + } + } + + if (!completedStateFound) { + jpaService.updateEntryState(req, entry.getId(), notificationState); + } + + res.sendRedirect(entry.getUrl()); + } +} diff --git a/notification-portlet-webapp/src/main/java/org/jasig/portlet/notice/action/stateChange/StateChangeNotificationServiceDecorator.java b/notification-portlet-webapp/src/main/java/org/jasig/portlet/notice/action/stateChange/StateChangeNotificationServiceDecorator.java new file mode 100644 index 00000000..5a82a3e7 --- /dev/null +++ b/notification-portlet-webapp/src/main/java/org/jasig/portlet/notice/action/stateChange/StateChangeNotificationServiceDecorator.java @@ -0,0 +1,107 @@ +/** + * Licensed to Jasig under one or more contributor license + * agreements. See the NOTICE file distributed with this work + * for additional information regarding copyright ownership. + * Jasig licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a + * copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.jasig.portlet.notice.action.stateChange; + +import java.util.ArrayList; +import java.util.List; +import javax.portlet.ActionRequest; +import javax.portlet.ActionResponse; +import javax.portlet.EventRequest; +import javax.portlet.EventResponse; +import javax.portlet.PortletPreferences; +import javax.portlet.PortletRequest; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jasig.portlet.notice.INotificationService; +import org.jasig.portlet.notice.NotificationAction; +import org.jasig.portlet.notice.NotificationCategory; +import org.jasig.portlet.notice.NotificationEntry; +import org.jasig.portlet.notice.NotificationResponse; + +/** + * + * @author mglazier + */ +public class StateChangeNotificationServiceDecorator implements INotificationService { + + public static final String STATE_CHANGE_ENABLED_PREFERENCE = "autoApplyStateWhenClicked"; + public static final String DEFAULT_STATE_CHANGE_BEHAVIOR = "false"; // The feature is disabled by default + + // Instance members + private INotificationService enclosedNotificationService; + private final Log log = LogFactory.getLog(getClass()); + + public void setEnclosedNotificationService(INotificationService enclosedNotificationService) { + this.enclosedNotificationService = enclosedNotificationService; + } + + @Override + public String getName() { + return enclosedNotificationService.getName(); + } + + @Override + public void invoke(ActionRequest req, ActionResponse res, boolean refresh) { + enclosedNotificationService.invoke(req, res, refresh); + } + + @Override + public void collect(EventRequest req, EventResponse res) { + enclosedNotificationService.collect(req, res); + } + + @Override + public NotificationResponse fetch(PortletRequest req) { + // Just pass through the enclosed collection if this feature is disabled + if (!stateChangeEnabled(req)) { + return enclosedNotificationService.fetch(req); + } + + // Build a fresh NotificationResponse based on a deep-copy of the one we enclose + final NotificationResponse sourceResponse = enclosedNotificationService.fetch(req); + NotificationResponse rslt = sourceResponse.cloneIfNotCloned(); + + for (NotificationCategory category : rslt.getCategories()) { + for (NotificationEntry entry : category.getEntries()) { + final List currentList = entry.getAvailableActions(); + + if (StringUtils.isNotBlank(entry.getId())) { + if (StringUtils.isNotBlank(entry.getId())) { + final List replacementList = new ArrayList<>(currentList); + replacementList.add( new StateChangeAction()); + entry.setAvailableActions( replacementList); + } + } + } + } + return rslt; + } + + @Override + public boolean isValid(PortletRequest req, NotificationResponse previousResponse) { + return enclosedNotificationService.isValid(req, previousResponse); + } + + private boolean stateChangeEnabled(PortletRequest request) { + PortletPreferences prefs = request.getPreferences(); + return Boolean.valueOf(prefs.getValue(STATE_CHANGE_ENABLED_PREFERENCE, DEFAULT_STATE_CHANGE_BEHAVIOR)); + } +} diff --git a/notification-portlet-webapp/src/main/java/org/jasig/portlet/notice/controller/NotificationLifecycleController.java b/notification-portlet-webapp/src/main/java/org/jasig/portlet/notice/controller/NotificationLifecycleController.java index 34a39781..692be333 100644 --- a/notification-portlet-webapp/src/main/java/org/jasig/portlet/notice/controller/NotificationLifecycleController.java +++ b/notification-portlet-webapp/src/main/java/org/jasig/portlet/notice/controller/NotificationLifecycleController.java @@ -182,7 +182,7 @@ public void invokeNotificationService(final ActionRequest req, final ActionRespo @ActionMapping public void invokeUserAction(final ActionRequest req, final ActionResponse res, @RequestParam("notificationId") final String notificationId, - @RequestParam("actionId") final String actionId) { + @RequestParam("actionId") final String actionId) throws IOException { // Prime the pump notificationService.invoke(req, res, false); @@ -204,7 +204,7 @@ public void invokeUserAction(final ActionRequest req, final ActionResponse res, // We must have a target to proceed if (target != null) { - target.invoke(req); + target.invoke(req, res); } else { String msg = "Target action not found for notificationId='" + notificationId + "' and actionId='" + actionId + "'"; diff --git a/notification-portlet-webapp/src/main/java/org/jasig/portlet/notice/service/jpa/INotificationDao.java b/notification-portlet-webapp/src/main/java/org/jasig/portlet/notice/service/jpa/INotificationDao.java index d1e48306..4b493c1e 100644 --- a/notification-portlet-webapp/src/main/java/org/jasig/portlet/notice/service/jpa/INotificationDao.java +++ b/notification-portlet-webapp/src/main/java/org/jasig/portlet/notice/service/jpa/INotificationDao.java @@ -47,4 +47,5 @@ Set getEntriesByRecipientByStatus(String username, */ List getEvents(long entryId, String username); + JpaEvent createOrUpdateEvent(JpaEvent event); } diff --git a/notification-portlet-webapp/src/main/java/org/jasig/portlet/notice/service/jpa/JpaNotificationDao.java b/notification-portlet-webapp/src/main/java/org/jasig/portlet/notice/service/jpa/JpaNotificationDao.java index c48a79b2..0d6d4509 100644 --- a/notification-portlet-webapp/src/main/java/org/jasig/portlet/notice/service/jpa/JpaNotificationDao.java +++ b/notification-portlet-webapp/src/main/java/org/jasig/portlet/notice/service/jpa/JpaNotificationDao.java @@ -116,4 +116,12 @@ public List getEvents(long entryId, String username) { return rslt; } + @Override + @Transactional + public JpaEvent createOrUpdateEvent(JpaEvent event) { + Validate.notNull(event, "Argument 'event' cannot be null"); + + JpaEvent rslt = entityManager.merge(event); + return rslt; + } } diff --git a/notification-portlet-webapp/src/main/java/org/jasig/portlet/notice/service/jpa/JpaNotificationService.java b/notification-portlet-webapp/src/main/java/org/jasig/portlet/notice/service/jpa/JpaNotificationService.java index 411d2474..48b85d43 100644 --- a/notification-portlet-webapp/src/main/java/org/jasig/portlet/notice/service/jpa/JpaNotificationService.java +++ b/notification-portlet-webapp/src/main/java/org/jasig/portlet/notice/service/jpa/JpaNotificationService.java @@ -19,6 +19,7 @@ package org.jasig.portlet.notice.service.jpa; +import java.sql.Timestamp; import java.util.ArrayList; import java.util.Collections; import java.util.Date; @@ -94,7 +95,26 @@ public NotificationResponse fetch(PortletRequest req) { return rslt; } - + + public void updateEntryState(PortletRequest req, String entryId, NotificationState state) { + if (usernameFinder.isAuthenticated(req)) { + final String username = usernameFinder.findUsername(req); + + String idStr = entryId.replaceAll(ID_PREFIX, ""); // remove the prefix + + JpaEntry jpaEntry = notificationDao.getEntry(Long.parseLong(idStr)); + if (jpaEntry != null) { + JpaEvent event = new JpaEvent(); + event.setEntry(jpaEntry); + event.setState(state); + event.setTimestamp(new Timestamp(new Date().getTime())); + event.setUsername(username); + + notificationDao.createOrUpdateEvent(event); + } + } + } + /* * Implementation */ diff --git a/notification-portlet-webapp/src/main/java/org/jasig/portlet/notice/util/SpringContext.java b/notification-portlet-webapp/src/main/java/org/jasig/portlet/notice/util/SpringContext.java new file mode 100644 index 00000000..f1c44985 --- /dev/null +++ b/notification-portlet-webapp/src/main/java/org/jasig/portlet/notice/util/SpringContext.java @@ -0,0 +1,43 @@ +/** + * Licensed to Jasig under one or more contributor license + * agreements. See the NOTICE file distributed with this work + * for additional information regarding copyright ownership. + * Jasig licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a + * copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.jasig.portlet.notice.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; + +/** + * + * @author mglazier + */ +public class SpringContext implements ApplicationContextAware { + + private static ApplicationContext context; + + @Override + public void setApplicationContext(ApplicationContext context) throws BeansException { + SpringContext.context = context; + } + + public static ApplicationContext getApplicationContext() { + return context; + } + +} diff --git a/notification-portlet-webapp/src/main/webapp/WEB-INF/context/applicationContext.xml b/notification-portlet-webapp/src/main/webapp/WEB-INF/context/applicationContext.xml index 0f723d99..a77f64a9 100644 --- a/notification-portlet-webapp/src/main/webapp/WEB-INF/context/applicationContext.xml +++ b/notification-portlet-webapp/src/main/webapp/WEB-INF/context/applicationContext.xml @@ -184,4 +184,6 @@ + + diff --git a/notification-portlet-webapp/src/main/webapp/WEB-INF/context/portlet/notification.xml b/notification-portlet-webapp/src/main/webapp/WEB-INF/context/portlet/notification.xml index 8fdb8f7d..d46c76fc 100644 --- a/notification-portlet-webapp/src/main/webapp/WEB-INF/context/portlet/notification.xml +++ b/notification-portlet-webapp/src/main/webapp/WEB-INF/context/portlet/notification.xml @@ -44,6 +44,9 @@ | defined in the parent applicationContext. +--> + + + diff --git a/notification-portlet-webapp/src/main/webapp/WEB-INF/jsp/icon.jsp b/notification-portlet-webapp/src/main/webapp/WEB-INF/jsp/icon.jsp index 581db6ea..43f51c9a 100644 --- a/notification-portlet-webapp/src/main/webapp/WEB-INF/jsp/icon.jsp +++ b/notification-portlet-webapp/src/main/webapp/WEB-INF/jsp/icon.jsp @@ -31,7 +31,7 @@ - + " type="text/css" media="screen" /> diff --git a/notification-portlet-webapp/src/main/webapp/WEB-INF/jsp/simple-list.jsp b/notification-portlet-webapp/src/main/webapp/WEB-INF/jsp/simple-list.jsp index 39444e1f..0e20a655 100644 --- a/notification-portlet-webapp/src/main/webapp/WEB-INF/jsp/simple-list.jsp +++ b/notification-portlet-webapp/src/main/webapp/WEB-INF/jsp/simple-list.jsp @@ -33,7 +33,7 @@ - + "/> diff --git a/notification-portlet-webapp/src/main/webapp/WEB-INF/jsp/state-change-list.jsp b/notification-portlet-webapp/src/main/webapp/WEB-INF/jsp/state-change-list.jsp new file mode 100644 index 00000000..a725b4c5 --- /dev/null +++ b/notification-portlet-webapp/src/main/webapp/WEB-INF/jsp/state-change-list.jsp @@ -0,0 +1,79 @@ +<%-- + + Licensed to Jasig under one or more contributor license + agreements. See the NOTICE file distributed with this work + for additional information regarding copyright ownership. + Jasig licenses this file to you under the Apache License, + Version 2.0 (the "License"); you may not use this file + except in compliance with the License. You may obtain a + copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on + an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + +--%> + + + + + + + + + + + + + + + + + +"/> + + + + + + + diff --git a/notification-portlet-webapp/src/main/webapp/WEB-INF/portlet.xml b/notification-portlet-webapp/src/main/webapp/WEB-INF/portlet.xml index 87fb36e3..72fdbf09 100644 --- a/notification-portlet-webapp/src/main/webapp/WEB-INF/portlet.xml +++ b/notification-portlet-webapp/src/main/webapp/WEB-INF/portlet.xml @@ -120,7 +120,20 @@ usePortalJsLibs false - + + + + autoApplyStateWhenClicked + true + + + + + applyStateWhenClicked + COMPLETED + x:NotificationResult diff --git a/notification-portlet-webapp/src/main/webapp/scripts/jquery.state-change.notice.js b/notification-portlet-webapp/src/main/webapp/scripts/jquery.state-change.notice.js new file mode 100644 index 00000000..15b875ca --- /dev/null +++ b/notification-portlet-webapp/src/main/webapp/scripts/jquery.state-change.notice.js @@ -0,0 +1,193 @@ +/* + * Licensed to Jasig under one or more contributor license + * agreements. See the NOTICE file distributed with this work + * for additional information regarding copyright ownership. + * Jasig licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a + * copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* + * This file offers a simple, flexible widget for displaying notifications. It + * is possible to use this script with multiple, different markup approaches. + */ + +var upStateNotice = upStateNotice || {}; + +if (!upStateNotice.init) { + + upStateNotice.init = true; + + (function() { + + var defaults = { + selectors: { + template: '.template', + title: '.title', + body: '.body', + link: '.link', + actions: '.notification-actions', + actionTemplate: '.action-template', + summaryTemplate: '.summary-template', + completedBadge: '.completed-badge' + }, + readyCallback: function() {} + }; + + // First 'prime-the-pump' with an ActionURL + function initNotices($, settings, callback) { + $.ajax({ + type: 'POST', + url: settings.invokeNotificationServiceUrl, + async: false, + success: function() { + fetchNotices($, settings, callback); + } + }); + } + + // Then fetch the notifications with a ResourceURL + function fetchNotices($, settings, callback) { + $.ajax({ + url : settings.getNotificationsUrl, + type : 'POST', + dataType : 'json', + success: function (data) { + feed = data.feed; + callback(feed); + }, + error: function () { + container.html(" ").text("AJAX failed. ~ THE END ~"); + } + }); + + } + + upStateNotice.show = function ($, container, options) { + + var settings = $.extend({}, defaults, options); + var template = container.find(settings.selectors.template); + var summaryTemplate = container.find(settings.selectors.summaryTemplate); + + var drawActions = function(element, actionsContainer, alert) { + + var availableActions = alert.availableActions; + var actionTemplate = actionsContainer.find(settings.selectors.actionTemplate); + + for (var i=0; i < availableActions.length; i++) { + var action = availableActions[i]; + + var actionUrl = settings.invokeActionUrlTemplate + .replace('NOTIFICATIONID', alert.id) + .replace('ACTIONID', action.id); + + var actionElement = actionTemplate.clone(); + actionElement.removeClass('action-template'); + actionElement.toggleClass('hidden'); + if( action.label) { + actionElement.find('a').attr('href', actionUrl).html(action.label + " "); + } + else if( action.id == 'StateChangeAction') { + element.find(settings.selectors.link).attr('href', actionUrl); + } + + actionElement.appendTo(actionsContainer); + } + + actionsContainer.toggleClass('hidden'); + + }; + + var drawNotices = function(feed) { + + // Do we have any notices to show? + if (feed && feed.length != 0) { + + // Iterate the notices + var len = feed.length; + if (settings.numberToDisplay != undefined && settings.numberToDisplay < feed.length) { + len = settings.numberToDisplay; + } + for (var i=0; i < len; i++) { + var alert = feed[i]; + + // Prepare an element + var element = template.clone(); + element.removeClass('template'); + element.toggleClass('hidden'); + + // Insert context + element.find(settings.selectors.title).html(alert.title); + if (alert.body) { + element.find(settings.selectors.body).html(alert.body); + } + if (alert.url) { + var linkText = alert.linkText || alert.url; + //element.find(settings.selectors.link).attr('href', alert.url).html(linkText); + } + + // Are actions available? + if (alert.availableActions && alert.availableActions.length != 0) { + var actionsContainer = element.find(settings.selectors.actions); + if (actionsContainer) { + drawActions(element, actionsContainer, alert); + } + } + + // Are there states to apply? + if (alert.states && alert.states.length != 0) { + var states = ""; + for (var prop in alert.states) { + if (alert.states.hasOwnProperty(prop)) { + if (states.length != 0) states += " "; + states += prop.toLowerCase(); + } + } + + element.find(settings.selectors.completedBadge).addClass( states); + } + + element.appendTo(template.parent()); + } + + // is there a summary section? + if(summaryTemplate) { + var showing = summaryTemplate.find('.showing'); + showing.text(len); + + var total = summaryTemplate.find('.total'); + total.text(feed.length); + } + + // Invoke the specified callback function, if any + settings.readyCallback(); + + container.slideDown('slow'); + + } + + }; + + // Invoke notifications + initNotices($, settings, drawNotices); + + }; + + upStateNotice.pullFeed = function ($, options, callback) { + var settings = $.extend({}, defaults, options); + initNotices($, settings, callback); + }; + + })(); + +} diff --git a/notification-portlet-webapp/src/main/webapp/simpleListLocalResources.xml b/notification-portlet-webapp/src/main/webapp/simpleListLocalResources.xml new file mode 100644 index 00000000..bdcf7815 --- /dev/null +++ b/notification-portlet-webapp/src/main/webapp/simpleListLocalResources.xml @@ -0,0 +1,28 @@ + + + + + + scripts/jquery.notice.js + scripts/jquery.notice.min.js + + diff --git a/notification-portlet-webapp/src/main/webapp/stateChangeListLocalResources.xml b/notification-portlet-webapp/src/main/webapp/stateChangeListLocalResources.xml new file mode 100644 index 00000000..256e1dc0 --- /dev/null +++ b/notification-portlet-webapp/src/main/webapp/stateChangeListLocalResources.xml @@ -0,0 +1,28 @@ + + + + + + scripts/jquery.state-change.notice.js + scripts/jquery.state-change.notice.min.js + + diff --git a/notification-portlet-webapp/src/main/webapp/styles/simple-list.css b/notification-portlet-webapp/src/main/webapp/styles/simple-list.css index 7b3cfafa..9b8ad0e8 100644 --- a/notification-portlet-webapp/src/main/webapp/styles/simple-list.css +++ b/notification-portlet-webapp/src/main/webapp/styles/simple-list.css @@ -37,3 +37,7 @@ list-style-type: none; } +div.notification-text span:not(.completed).completed-badge { + display: none; +} +