diff --git a/.gradle/3.5/fileContent/fileContent.lock b/.gradle/3.5/fileContent/fileContent.lock index 29862e68f..b7184fb42 100644 Binary files a/.gradle/3.5/fileContent/fileContent.lock and b/.gradle/3.5/fileContent/fileContent.lock differ diff --git a/.gradle/3.5/taskHistory/fileHashes.bin b/.gradle/3.5/taskHistory/fileHashes.bin index bf9667487..39f69a035 100644 Binary files a/.gradle/3.5/taskHistory/fileHashes.bin and b/.gradle/3.5/taskHistory/fileHashes.bin differ diff --git a/.gradle/3.5/taskHistory/fileSnapshots.bin b/.gradle/3.5/taskHistory/fileSnapshots.bin index 0a9d051b4..36fd67434 100644 Binary files a/.gradle/3.5/taskHistory/fileSnapshots.bin and b/.gradle/3.5/taskHistory/fileSnapshots.bin differ diff --git a/.gradle/3.5/taskHistory/taskHistory.bin b/.gradle/3.5/taskHistory/taskHistory.bin index a8b90ced0..9e51e9d76 100644 Binary files a/.gradle/3.5/taskHistory/taskHistory.bin and b/.gradle/3.5/taskHistory/taskHistory.bin differ diff --git a/.gradle/3.5/taskHistory/taskHistory.lock b/.gradle/3.5/taskHistory/taskHistory.lock index f369fb0d3..48f807efc 100644 Binary files a/.gradle/3.5/taskHistory/taskHistory.lock and b/.gradle/3.5/taskHistory/taskHistory.lock differ diff --git a/grails-app/assets/javascripts/notification.js b/grails-app/assets/javascripts/notification.js index cbf592c3b..a8ebd831f 100644 --- a/grails-app/assets/javascripts/notification.js +++ b/grails-app/assets/javascripts/notification.js @@ -1,53 +1,54 @@ function notification_get( get_not_url, dismiss_url, forSection ) { - $.get( get_not_url, { forSection: forSection }, 'json') - .done(function(data) { - //console.log(data); - - var new_nts_count = data.filter(function(sts) { return sts.status == 'new'; }).length; - - if (new_nts_count > 0) - { - $('#top-notifications-menu > a').append(''+ new_nts_count +''); - } - - notifications = ''; - $.each( data, function( i, nstatus ) { - - // TODO: add class="dismissed" to the LIs of notifications that were dismissed - if (nstatus.status == 'new') - $('#top-notifications-menu .drop-content').append('
  • '+ nstatus.notification.text +'
    '+ nstatus.notification.dateCreated +'
  • '); - else - $('#top-notifications-menu .drop-content').append('
  • '+ nstatus.notification.text +'
    '+ nstatus.notification.dateCreated +'
  • '); - }); - - - $('.dismiss').on('click', function (evn) { - //console.log('id', $(this).data('id')); - - // dismiss with the new notifications on the menu - var notif_dom = $(this).closest('li'); - - $.get( dismiss_url, { id: $(this).data('id') }, 'json') - .done(function(data) { - console.log(data); - // TODO: update the DOM adding the dismissed class to the LI - console.log(notif_dom); - notif_dom.addClass('dismissed'); - }) - .fail(function() { - //alert( "error" ); - }) - .always(function() { - //alert( "finished" ); - }); - }); - }) - .fail(function() { - //alert( "error" ); - }) - .always(function() { - //alert( "finished" ); + // why are we sending the section if the section is null for remote notifications? + $.get(get_not_url, { forSection: forSection }, 'json') + .done(function(data) { + //console.log(data); + + var new_nts_count = data.filter(function(sts) { return sts.status == 'new'; }).length; + + if (new_nts_count > 0) + { + $('#top-notifications-menu > a').append(''+ new_nts_count +''); + } + + notifications = ''; + $.each( data, function( i, nstatus ) { + + // TODO: add class="dismissed" to the LIs of notifications that were dismissed + if (nstatus.status == 'new') + $('#top-notifications-menu .drop-content').append('
  • '+ nstatus.notification.text +'
    '+ nstatus.notification.timestamp +'
  • '); + else + $('#top-notifications-menu .drop-content').append('
  • '+ nstatus.notification.text +'
    '+ nstatus.notification.timestamp +'
  • '); }); + + + $('.dismiss').on('click', function (evn) { + //console.log('id', $(this).data('id')); + + // dismiss with the new notifications on the menu + var notif_dom = $(this).closest('li'); + + $.get( dismiss_url, { id: $(this).data('id') }, 'json') + .done(function(data) { + console.log(data); + // TODO: update the DOM adding the dismissed class to the LI + console.log(notif_dom); + notif_dom.addClass('dismissed'); + }) + .fail(function() { + //alert( "error" ); + }) + .always(function() { + //alert( "finished" ); + }); + }); + }) + .fail(function() { + //alert( "error" ); + }) + .always(function() { + //alert( "finished" ); + }); } diff --git a/grails-app/conf/logback.groovy b/grails-app/conf/logback.groovy index 300ce8fc6..908024d5c 100644 --- a/grails-app/conf/logback.groovy +++ b/grails-app/conf/logback.groovy @@ -41,3 +41,4 @@ logger("com.cabolabs.security.stateless", DEBUG) logger("com.cabolabs.ehrserver.i18n", DEBUG) logger("com.cabolabs.ehrserver.indexing", INFO) logger("com.cabolabs.ehrserver.account", INFO) +logger("com.cabolabs.ehrserver.notification", INFO) diff --git a/grails-app/controllers/com/cabolabs/ehrserver/notification/NotificationController.groovy b/grails-app/controllers/com/cabolabs/ehrserver/notification/NotificationController.groovy index e9c3c3b8a..b953769ca 100644 --- a/grails-app/controllers/com/cabolabs/ehrserver/notification/NotificationController.groovy +++ b/grails-app/controllers/com/cabolabs/ehrserver/notification/NotificationController.groovy @@ -90,7 +90,7 @@ class NotificationController { // List def notifications = Notification.lastNotifications(forSection, session.organization.uid, loggedInUser.uid, session.lang) - notifications = notifications.collect{ [status: it.status, notification: [text: it.notification.text, dateCreated: it.notification.dateCreated, id: it.notification.id]] } + notifications = notifications.collect{ [status: it.status, notification: [text: it.notification.text, timestamp: it.notification.timestamp, id: it.notification.id]] } render (contentType: "application/json", text: notifications as JSON, encoding:"UTF-8") } diff --git a/grails-app/controllers/com/cabolabs/security/AuthController.groovy b/grails-app/controllers/com/cabolabs/security/AuthController.groovy index 07c5988f2..0c3e640cf 100644 --- a/grails-app/controllers/com/cabolabs/security/AuthController.groovy +++ b/grails-app/controllers/com/cabolabs/security/AuthController.groovy @@ -62,7 +62,13 @@ class AuthController { def notifications = remoteNotificationsService.getNotifications('ehrserver', session.lang, from) notifications.each { notification -> - new Notification(name:'remote', language:session.lang, text:notification.nt, forUser:User.findByEmail(email).id).save() + new Notification( + name: 'remote', + language: session.lang, + text: notification.nt, + forUser: User.findByEmail(email).id, + timestamp: Date.parse("yyyy-MM-dd'T'HH:mm:ss'Z'", notification.ts) + ).save() } // Mark current read of the remote notifications diff --git a/grails-app/domain/com/cabolabs/ehrserver/notification/Notification.groovy b/grails-app/domain/com/cabolabs/ehrserver/notification/Notification.groovy index 3b75080fd..7b2fc311e 100644 --- a/grails-app/domain/com/cabolabs/ehrserver/notification/Notification.groovy +++ b/grails-app/domain/com/cabolabs/ehrserver/notification/Notification.groovy @@ -33,7 +33,7 @@ class Notification { String forOrganization String forUser // user.uid - Date dateCreated + Date timestamp = new Date() boolean sent = false // used by the job that creates the notification statuses @@ -53,8 +53,14 @@ class Notification { } if (forUser) { - user { - eq('uid', forUser) + or + { + user { + eq('uid', forUser) + } + notification { + isNull('forUser') + } } } if (forOrganization) // forOrganization alwas comes, but it should match also when it is null on the notification @@ -81,7 +87,7 @@ class Notification { } maxResults(last) notification { - order("dateCreated", "desc") + order("timestamp", "desc") } } @@ -98,8 +104,14 @@ class Notification { } if (forUser) { - user { - eq('uid', forUser) + or + { + user { + eq('uid', forUser) + } + notification { + isNull('forUser') + } } } if (forOrganization) // forOrganization alwas comes, but it should match also when it is null on the notification diff --git a/grails-app/jobs/com/cabolabs/ehrserver/notification/NotificationJob.groovy b/grails-app/jobs/com/cabolabs/ehrserver/notification/NotificationJob.groovy new file mode 100644 index 000000000..db1f54a92 --- /dev/null +++ b/grails-app/jobs/com/cabolabs/ehrserver/notification/NotificationJob.groovy @@ -0,0 +1,60 @@ +package com.cabolabs.ehrserver.notification + +import com.cabolabs.security.User +import com.cabolabs.security.UserRole + +class NotificationJob { + + static concurrent = false + + static triggers = { + simple repeatInterval: 60000l, startDelay: 120000l // execute job once in 5 seconds + } + + def execute() + { + log.info "Notification Job Executing" + + Notification.findAllBySent(false).each { notificationInstance -> + + //println "send notification "+ notificationInstance.id + + def statuses = [] + if (!notificationInstance.forUser) + { + def users + if (notificationInstance.forOrganization) + { + def urs = UserRole.withCriteria { + organization { + eq('uid', notificationInstance.forOrganization) + } + user { + eq('isVirtual', false) + } + } + users = urs.user.unique() // unique avoids the same notif to go to a user that has 2 roles in the same org + } + else + { + users = User.list() + } + + users.each { user -> + statuses << new NotificationStatus(user:user, notification:notificationInstance) + } + } + else + { + statuses << new NotificationStatus(user:User.get(notificationInstance.forUser), notification:notificationInstance) + } + + statuses.each { status -> + status.save(failOnError: true) + } + + notificationInstance.sent = true + notificationInstance.save(failOnError: true) + } + } +} diff --git a/grails-app/views/notification/index.gsp b/grails-app/views/notification/index.gsp index cb11b39ae..2f24bc2f9 100644 --- a/grails-app/views/notification/index.gsp +++ b/grails-app/views/notification/index.gsp @@ -37,7 +37,7 @@ - +