← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 17905: Implemented web api endpoints for setting messageconversation followup. Cleaned up message.js cod...

 

Merge authors:
  Halvdan Hoem Grelland (halvdanhg)
------------------------------------------------------------
revno: 17905 [merge]
committer: Halvdan Hoem Grelland <halvdanhg@xxxxxxxxx>
branch nick: dhis2
timestamp: Wed 2015-01-07 14:34:50 +0100
message:
  Implemented web api endpoints for setting messageconversation followup. Cleaned up message.js code. Added batch followup to dashboard messaging. Minor fixes.
modified:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/message/MessageService.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/message/DefaultMessageService.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/message/hibernate/HibernateMessageConversationStore.java
  dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/message/MessageServiceTest.java
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/MessageConversationController.java
  dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/jQuery/jquery.dhisCheckboxMenu.js
  dhis-2/dhis-web/dhis-web-dashboard-integration/src/main/resources/org/hisp/dhis/dashboard/i18n_module.properties
  dhis-2/dhis-web/dhis-web-dashboard-integration/src/main/webapp/dhis-web-dashboard-integration/javascript/message.js
  dhis-2/dhis-web/dhis-web-dashboard-integration/src/main/webapp/dhis-web-dashboard-integration/message.vm


--
lp:dhis2
https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk

Your team DHIS 2 developers is subscribed to branch lp:dhis2.
To unsubscribe from this branch go to https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk/+edit-subscription
=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/message/MessageService.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/message/MessageService.java	2014-11-18 12:55:20 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/message/MessageService.java	2015-01-06 16:21:58 +0000
@@ -102,7 +102,7 @@
 
     List<MessageConversation> getMessageConversations( boolean followUpOnly, boolean unreadOnly, int first, int max );
 
-    Collection<MessageConversation> getMessageConversations( String[] messageConversationUids );
+    Collection<MessageConversation> getMessageConversations( User user, String[] messageConversationUids );
 
     int getMessageConversationCount();
 

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/message/DefaultMessageService.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/message/DefaultMessageService.java	2014-12-21 17:57:33 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/message/DefaultMessageService.java	2015-01-06 16:21:58 +0000
@@ -327,9 +327,20 @@
     }
 
     @Override
-    public Collection<MessageConversation> getMessageConversations( String[] messageConversationUids )
+    public Collection<MessageConversation> getMessageConversations( User user, String[] messageConversationUids )
     {
-        return messageConversationStore.getMessageConversations( messageConversationUids );
+        Collection<MessageConversation> conversations = messageConversationStore.getMessageConversations( messageConversationUids );
+
+        // Set transient properties
+        // TODO See getMessageConversation(String)
+
+        for ( MessageConversation mc : conversations )
+        {
+            mc.setFollowUp( mc.isFollowUp( user ) );
+            mc.setRead( mc.isRead( user ) );
+        }
+
+        return conversations;
     }
 
     @Override

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/message/hibernate/HibernateMessageConversationStore.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/message/hibernate/HibernateMessageConversationStore.java	2014-10-16 06:17:19 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/message/hibernate/HibernateMessageConversationStore.java	2015-01-07 12:59:57 +0000
@@ -29,6 +29,7 @@
  */
 
 import org.hibernate.Query;
+import org.hibernate.criterion.Restrictions;
 import org.hisp.dhis.common.hibernate.HibernateIdentifiableObjectStore;
 import org.hisp.dhis.jdbc.StatementBuilder;
 import org.hisp.dhis.message.MessageConversation;
@@ -40,6 +41,7 @@
 
 import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
 
@@ -128,15 +130,12 @@
     }
 
     @Override
-    @SuppressWarnings("unchecked")
-    public Collection<MessageConversation> getMessageConversations( String[] messageConversationUids )
+    @SuppressWarnings( "unchecked" )
+    public Collection<MessageConversation> getMessageConversations( String[] uids )
     {
-        String hql = ( "FROM MessageConversation where uid in :messageConversationUids" );
-
-        Query query = getQuery( hql );
-        query.setParameterList( "messageConversationUids", messageConversationUids );
-
-        return query.list();
+        return getSharingCriteria()
+            .add( Restrictions.in( "uid", uids ) )
+            .list();
     }
 
     @Override
@@ -259,4 +258,4 @@
 
         return recipients;
     }
-}
\ No newline at end of file
+}

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/message/MessageServiceTest.java'
--- dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/message/MessageServiceTest.java	2014-10-16 06:17:19 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/message/MessageServiceTest.java	2015-01-06 16:21:58 +0000
@@ -229,7 +229,7 @@
 
         String[] uids = { uidA, uidB };
 
-        Collection<MessageConversation> conversations = messageService.getMessageConversations( uids );
+        Collection<MessageConversation> conversations = messageService.getMessageConversations( sender, uids );
 
         assertTrue( conversations.contains( conversationA ) );
         assertTrue( conversations.contains( conversationB ) );

=== modified file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/MessageConversationController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/MessageConversationController.java	2014-12-30 17:28:02 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/MessageConversationController.java	2015-01-07 12:59:57 +0000
@@ -293,7 +293,7 @@
             throw new UpdateAccessDeniedException( "Not authorized to modify this object." );
         }
 
-        Collection<org.hisp.dhis.message.MessageConversation> messageConversations = messageService.getMessageConversations( uids );
+        Collection<org.hisp.dhis.message.MessageConversation> messageConversations = messageService.getMessageConversations( user, uids );
 
         if ( messageConversations.isEmpty() )
         {
@@ -344,7 +344,7 @@
             throw new UpdateAccessDeniedException( "Not authorized to modify this object." );
         }
 
-        Collection<org.hisp.dhis.message.MessageConversation> messageConversations = messageService.getMessageConversations( uids );
+        Collection<org.hisp.dhis.message.MessageConversation> messageConversations = messageService.getMessageConversations( user, uids );
 
         if ( messageConversations.isEmpty() )
         {
@@ -371,6 +371,110 @@
     }
 
     //--------------------------------------------------------------------------
+    // Mark conversations for follow up
+    //--------------------------------------------------------------------------
+
+    @RequestMapping( value = "followup", method = RequestMethod.POST, produces = { MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE } )
+    public @ResponseBody RootNode markMessageConversationFollowup(
+        @RequestParam( value = "user", required = false ) String userUid, @RequestBody String[] uids, HttpServletResponse response )
+    {
+        RootNode responseNode = new RootNode( "response" );
+
+        User currentUser = currentUserService.getCurrentUser();
+        User user = userUid != null ? userService.getUser( userUid ) : currentUser;
+
+        if ( user == null )
+        {
+            response.setStatus( HttpServletResponse.SC_NOT_FOUND );
+            responseNode.addChild( new SimpleNode( "message", "No user with uid: " + userUid ) );
+            return responseNode;
+        }
+
+        if ( !canModifyUserConversation( currentUser, user ) )
+        {
+            throw new UpdateAccessDeniedException( "Not authorized to modify this object." );
+        }
+
+        Collection<org.hisp.dhis.message.MessageConversation> messageConversations = messageService.getMessageConversations( user, uids );
+
+        if ( messageConversations.isEmpty() )
+        {
+            response.setStatus( HttpServletResponse.SC_NOT_FOUND );
+            responseNode.addChild( new SimpleNode( "message", "No MessageConversations found for the given UIDs" ) );
+            return responseNode;
+        }
+
+        CollectionNode marked = responseNode.addChild( new CollectionNode( "markedFollowup" ) );
+        marked.setWrapping( false );
+
+        for ( org.hisp.dhis.message.MessageConversation conversation : messageConversations )
+        {
+            if ( !conversation.isFollowUp() )
+            {
+                conversation.toggleFollowUp( user );
+                messageService.updateMessageConversation( conversation );
+            }
+            marked.addChild( new SimpleNode( "uid", conversation.getUid() ) );
+        }
+
+        response.setStatus( HttpServletResponse.SC_OK );
+
+        return responseNode;
+    }
+
+    //--------------------------------------------------------------------------
+    // Clear follow up
+    //--------------------------------------------------------------------------
+
+    @RequestMapping( value = "unfollowup", method = RequestMethod.POST, produces = { MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE } )
+    public @ResponseBody RootNode unmarkMessageConversationFollowup(
+        @RequestParam( value = "user", required = false ) String userUid, @RequestBody String[] uids, HttpServletResponse response )
+    {
+        RootNode responseNode = new RootNode( "response" );
+
+        User currentUser = currentUserService.getCurrentUser();
+        User user = userUid != null ? userService.getUser( userUid ) : currentUser;
+
+        if ( user == null )
+        {
+            response.setStatus( HttpServletResponse.SC_NOT_FOUND );
+            responseNode.addChild( new SimpleNode( "message", "No user with uid: " + userUid ) );
+            return responseNode;
+        }
+
+        if ( !canModifyUserConversation( currentUser, user ) )
+        {
+            throw new UpdateAccessDeniedException( "Not authorized to modify this object." );
+        }
+
+        Collection<org.hisp.dhis.message.MessageConversation> messageConversations = messageService.getMessageConversations( user, uids );
+
+        if ( messageConversations.isEmpty() )
+        {
+            response.setStatus( HttpServletResponse.SC_NOT_FOUND );
+            responseNode.addChild( new SimpleNode( "message", "No MessageConversations found for the given UIDs" ) );
+            return responseNode;
+        }
+
+        CollectionNode marked = responseNode.addChild( new CollectionNode( "unmarkedFollowup" ) );
+        marked.setWrapping( false );
+
+        for ( org.hisp.dhis.message.MessageConversation conversation : messageConversations )
+        {
+            if ( conversation.isFollowUp() )
+            {
+                conversation.toggleFollowUp( user );
+                messageService.updateMessageConversation( conversation );
+            }
+            marked.addChild( new SimpleNode( "uid", conversation.getUid() ) );
+        }
+
+        response.setStatus( HttpServletResponse.SC_OK );
+
+        return responseNode;
+    }
+
+    //--------------------------------------------------------------------------
     // Delete a MessageConversation (requires override auth)
     //--------------------------------------------------------------------------
 
@@ -465,7 +569,7 @@
             throw new DeleteAccessDeniedException( "Not authorized to modify user: " + user.getUid() );
         }
 
-        Collection<org.hisp.dhis.message.MessageConversation> messageConversations = messageService.getMessageConversations( mcUids );
+        Collection<org.hisp.dhis.message.MessageConversation> messageConversations = messageService.getMessageConversations( user, mcUids );
 
         if ( messageConversations.isEmpty() )
         {

=== modified file 'dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/jQuery/jquery.dhisCheckboxMenu.js'
--- dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/jQuery/jquery.dhisCheckboxMenu.js	2014-10-03 12:12:40 +0000
+++ dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/jQuery/jquery.dhisCheckboxMenu.js	2015-01-06 18:19:11 +0000
@@ -68,6 +68,16 @@
         return checked;
     }
 
+    function executeNamedFn(fnName, ctx ) {
+        var args = [].slice.call(arguments).splice(2);
+        var namespaces = fnName.split(".");
+        var func = namespaces.pop();
+        for( var i = 0; i < namespaces.length; i++ ) {
+            ctx = ctx[ namespaces[ i ] ];
+        }
+        return ctx[func].apply( this, args );
+    }
+
     var multiCheckboxMenu = $.fn.multiCheckboxMenu;
 
     $.fn.multiCheckboxMenu = function( $checkboxContainer, options ) {
@@ -130,7 +140,7 @@
             }
 
             el.click( function() {
-                return window[ el.action ]( getCheckedValues( $checkboxContainer ) );
+                return executeNamedFn( el.action, window, getCheckedValues( $checkboxContainer ) );
             });
         });
 

=== modified file 'dhis-2/dhis-web/dhis-web-dashboard-integration/src/main/resources/org/hisp/dhis/dashboard/i18n_module.properties'
--- dhis-2/dhis-web/dhis-web-dashboard-integration/src/main/resources/org/hisp/dhis/dashboard/i18n_module.properties	2014-12-18 11:41:20 +0000
+++ dhis-2/dhis-web/dhis-web-dashboard-integration/src/main/resources/org/hisp/dhis/dashboard/i18n_module.properties	2015-01-07 13:32:22 +0000
@@ -26,6 +26,8 @@
 recipients=Recipients
 mark_unread=Mark as unread
 mark_read=Mark as read
+mark_followup=Mark for followup
+clear_followup=Clear followup
 read=Read
 delete=Delete
 confirm_delete_message=Are you sure you want to delete the message?

=== modified file 'dhis-2/dhis-web/dhis-web-dashboard-integration/src/main/webapp/dhis-web-dashboard-integration/javascript/message.js'
--- dhis-2/dhis-web/dhis-web-dashboard-integration/src/main/webapp/dhis-web-dashboard-integration/javascript/message.js	2014-10-03 11:32:55 +0000
+++ dhis-2/dhis-web/dhis-web-dashboard-integration/src/main/webapp/dhis-web-dashboard-integration/javascript/message.js	2015-01-07 13:02:00 +0000
@@ -8,101 +8,6 @@
     removeItem( id, "", i18n_confirm_delete_message, "removeMessage.action" );
 }
 
-function removeMessages( messages )
-{
-    if( typeof messages === "undefined" || messages.length < 1 )
-    {
-        return;
-    }
-
-    var confirmed = window.confirm( i18n_confirm_delete_all_selected_messages );
-
-    if( confirmed )
-    {
-        setHeaderWaitMessage( i18n_deleting );
-
-        $.ajax(
-            {
-                url: "../api/messageConversations?" + $.param( { mc: messages }, true ),
-                contentType: "application/json",
-                dataType: "json",
-                type: "DELETE",
-                success: function( response )
-                {
-                    for( var i = 0; i < response.removed.length; i++ )
-                    {
-                        $( "#messages" ).find( "[name='" + response.removed[i] + "']" ).remove();
-                    }
-                    setHeaderDelayMessage( i18n_messages_were_deleted );
-                },
-                error: function( response )
-                {
-                    showErrorMessage( response.message, 3 );
-                }
-        } );
-    }
-}
-
-function markMessagesRead( messages )
-{
-    if( messages.length < 1 )
-    {
-        return;
-    }
-
-    $.ajax(
-        {
-            url: "../api/messageConversations/read",
-            type: "POST",
-            data: JSON.stringify( messages ),
-            contentType: "application/json",
-            dataType: "json",
-            success: function( response )
-            {
-                toggleMessagesRead( response.markedRead );
-            },
-            error: function( response )
-            {
-                showErrorMessage( response.message, 3 );
-            }
-        } );
-}
-
-function markMessagesUnread( messages )
-{
-    if( messages.length < 1 )
-    {
-        return;
-    }
-
-    $.ajax(
-        {
-            url: "../api/messageConversations/unread",
-            type: "POST",
-            data: JSON.stringify( messages ),
-            contentType: "application/json",
-            dataType: "json",
-            success: function( response )
-            {
-                toggleMessagesRead( response.markedUnread );
-            },
-            error: function( response )
-            {
-                showErrorMessage( response.message, 3 );
-            }
-        } );
-}
-
-function toggleMessagesRead( messageUids )
-{
-    var messages = $( "#messages" );
-
-    for( var i = 0; i < messageUids.length; i++ )
-    {
-        messages.find( "[name='" + messageUids[i] + "']" ).toggleClass( "unread bold" );
-    }
-}
-
 function toggleRowSelected( element )
 {
     $( element ).closest( "tr" ).toggleClass( "list-row-selected", element.checked );
@@ -197,3 +102,119 @@
         return item.text;
     }
 }
+
+var messageOperations = ( function() {
+
+    //
+    // Private
+    //
+
+    var removeMessages = function( messages ) {
+        if( typeof messages === "undefined" || messages.length < 1 ) {
+            return;
+        }
+
+        var confirmed = window.confirm( i18n_confirm_delete_all_selected_messages );
+
+        if( confirmed ) {
+            setHeaderWaitMessage( i18n_deleting );
+
+            $.ajax( {
+                    url: "../api/messageConversations?" + $.param( { mc: messages }, true ),
+                    contentType: "application/json",
+                    dataType: "json",
+                    type: "DELETE",
+                    success: function( response ) {
+                        for( var i = 0; i < response.removed.length; i++ ) {
+                            $( "#messages" ).find( "[name='" + response.removed[i] + "']" ).remove();
+                        }
+                        setHeaderDelayMessage( i18n_messages_were_deleted );
+                    },
+                    error: function( response ) {
+                        showErrorMessage( response.message, 3 );
+                    }
+            } );
+        }
+    };
+
+    var propertyRegExp = new RegExp( "[read|unread|followup|unfollowup]" );
+
+    /**
+     * Workhorse function to mark/unmark messages read, unread, followup or unfollowup.
+     *
+     * @param messages {array} UID of messages to mark
+     * @param property {string} property to mark. String values are read|unread|followup|unfollowup
+     */
+    var markMessages = function( messages, property ) {
+        if( typeof messages === "undefined" || messages.length < 1 ) {
+            return;
+        }
+
+        if( !_.isString( property ) || !propertyRegExp.test( property ) ) {
+            throw "Property string must be set.";
+        }
+
+        $.ajax( {
+            url: "../api/messageConversations/" + property,
+            type: "POST",
+            data: JSON.stringify( messages ),
+            contentType: "application/json",
+            dataType: "json",
+            success: function( response ) {
+                switch( property ) {
+                    case "read":
+                        toggleMessagesRead( response.markedRead );
+                        break;
+                    case "unread":
+                        toggleMessagesRead( response.markedUnread );
+                        break;
+                    case "followup":
+                        setFollowupIndicator( response.markedFollowup, true);
+                        break;
+                    case "unfollowup":
+                        setFollowupIndicator( response.unmarkedFollowup, false );
+                        break;
+                }
+            },
+            error: function( response ) {
+                showErrorMessage( response.message, 3);
+            }
+        } );
+    };
+
+    var setFollowupIndicator = function( messageUids, marked ) {
+        var messages = $( "#messages" );
+        var imgSrc = marked ? "../images/marked.png" : "../images/unmarked.png";
+
+        for( var i = 0; i < messageUids.length; i++ ) {
+            messages.find( "[name='" + messageUids[i] + "'] .followup-icon img" ).attr( "src", imgSrc );
+        }
+    };
+
+    var toggleMessagesRead = function( messageUids ) {
+        var messages = $( "#messages" );
+
+        for( var i = 0; i < messageUids.length; i++ ) {
+            messages.find( "[name='" + messageUids[i] + "']" ).toggleClass( "unread bold" );
+        }
+    };
+
+    //
+    // Public
+    //
+    return {
+        unmarkMessagesFollowup: function( messages ) {
+            return markMessages( messages, "unfollowup" );
+        },
+        markMessagesFollowup: function( messages) {
+            return markMessages( messages, "followup" );
+        },
+        markMessagesRead: function( messages ) {
+            return markMessages( messages, "read" );
+        },
+        markMessagesUnread: function( messages ) {
+            return markMessages( messages, "unread" );
+        },
+        removeMessages: removeMessages
+    };
+})( window );
\ No newline at end of file

=== modified file 'dhis-2/dhis-web/dhis-web-dashboard-integration/src/main/webapp/dhis-web-dashboard-integration/message.vm'
--- dhis-2/dhis-web/dhis-web-dashboard-integration/src/main/webapp/dhis-web-dashboard-integration/message.vm	2014-10-03 11:32:55 +0000
+++ dhis-2/dhis-web/dhis-web-dashboard-integration/src/main/webapp/dhis-web-dashboard-integration/message.vm	2015-01-07 13:32:22 +0000
@@ -12,9 +12,11 @@
             <div id="checkboxDropdown">
                 <div></div>
                 <ul>
-                    <li data-action="removeMessages">Delete</li>
-                    <li data-action="markMessagesRead">Mark read</li>
-                    <li data-action="markMessagesUnread">Mark unread</li>
+                    <li data-action="messageOperations.removeMessages">$i18n.getString( "delete" )</li>
+                    <li data-action="messageOperations.markMessagesRead">$i18n.getString( "mark_read")</li>
+                    <li data-action="messageOperations.markMessagesUnread">$i18n.getString( "mark_unread" )</li>
+                    <li data-action="messageOperations.markMessagesFollowup">$i18n.getString( "mark_followup")</li>
+                    <li data-action="messageOperations.unmarkMessagesFollowup">$i18n.getString( "clear_followup" )</li>
                 </ul>
             </div>
         </li>
@@ -43,7 +45,7 @@
                     <td style="width:20px;padding-left:5px;">
                         <input type="checkbox" value="${conversation.uid}" onchange="toggleRowSelected( this )"/>
                     </td>
-                    <td style="width:40px;padding-left:5px;" onclick="toggleFollowUp( '${conversation.id}' )">
+                    <td style="width:40px;padding-left:5px;" onclick="toggleFollowUp( '${conversation.id}' )" class="followup-icon">
                         <img id="followUp${conversation.id}" #if( $conversation.followUp ) src="../images/marked.png"#else src="../images/unmarked.png"#end></td>
                     <td style="width:200px" onclick="read( '${conversation.uid}' )">
                         #if( $conversation.lastSenderName )$!encoder.htmlEncode( $conversation.lastSenderName )#else $i18n.getString( "system_notification" )#end