diff options
-rw-r--r-- | templates/web/fixmybarangay/around/tabbed_lists.html | 68 | ||||
-rw-r--r-- | templates/web/fixmybarangay/header.html | 4 | ||||
-rw-r--r-- | templates/web/fixmybarangay/report/_message_manager.html | 137 | ||||
-rw-r--r-- | web/cobrands/fixmybarangay/message_manager.scss | 64 | ||||
-rw-r--r-- | web/cobrands/fixmybarangay/message_manager_client.js | 193 |
5 files changed, 346 insertions, 120 deletions
diff --git a/templates/web/fixmybarangay/around/tabbed_lists.html b/templates/web/fixmybarangay/around/tabbed_lists.html index 77ca84ee4..14461628c 100644 --- a/templates/web/fixmybarangay/around/tabbed_lists.html +++ b/templates/web/fixmybarangay/around/tabbed_lists.html @@ -14,71 +14,5 @@ IF allow_creation %] </ul> [% IF allow_creation %] -<ul id="message_manager" class="issue-list-a tab"> - <li id="message-control"> - <div id="mm-username-container">username: <span id="mm-received-username"></span></div> - <div id="mm-status-message-container"> - <div id="mm-status-message"></div> - </div> - <div id="mm-login-container"> - <div class="input text"> - <label for="mm-htauth-username">MM username</label> - <input name="mm-htauth-username" id="mm-htauth-username" type="text"/> - </div> - <div class="input password"> - <label for="mm-htauth-password">Password</label> - <input name="mm-htauth-password" id="mm-htauth-password" type="password"/> - </div> - <div class="submit"> - <input id="available-submit" type="submit" value="Get available messages"/> - </div> - </div> - </li> - <li> - <div id="mm-message-list" style="min-height:1em;"></div> - </li> -</ul> - -<script type="text/javascript"> - -$(document).ready(function() { - - var mm_url = "[% c.config.MESSAGE_MANAGER_URL %]"; // from config - - var mm_populate_list = function(data) { - $('#mm-status-message-container').text("Accessed message server as " + data['username']); - $('input[name=mm_text]').prop('checked', false); // uncheck all - } - - var mm_selected_message = function(data) { - var msg_text = ""; - var service_id = ""; - if (data['success']) { - // msg_text = $('#form_detail').val( $('input[name=mm_text]:checked').val() ); # == message data - msg_text = data['data']['Message']['message']; - service_id = data['data']['Message']['id']; - } else { - $('input[name=mm_text]').prop('checked', false); // uncheck all - } - $('#form_detail').val(msg_text); - $('#external_source_id').val(service_id); - } - - message_manager.config({url_root: mm_url}); - message_manager.setup_click_listener({callback:mm_selected_message}); - - // problem form hidden input "external_source_id": pass the MM id into FMS, if used - $('<input type="hidden"/>').attr({ - 'id': 'external_source_id', - 'name': 'external_source_id', - }).appendTo($('#problem_form')); - - $('#available-submit').click(function(e){ - e.preventDefault(); - message_manager.get_available_messages({callback:mm_populate_list}); - }); - $('#available-submit').click(); -}); - -</script> + [% TRY %][% INCLUDE 'report/_message_manager.html' %][% CATCH file %][% END %] [% END %] diff --git a/templates/web/fixmybarangay/header.html b/templates/web/fixmybarangay/header.html index 2b2f031e2..c3ddd154e 100644 --- a/templates/web/fixmybarangay/header.html +++ b/templates/web/fixmybarangay/header.html @@ -25,6 +25,10 @@ [% allow_creation = !c.cobrand.only_authed_can_create || (c.user && c.user.from_council); %] [% IF allow_creation %] + + <link rel="stylesheet" href="[% version('/js/fancybox/jquery.fancybox-1.3.4.css') %]"> + <script src="[% version('/js/fancybox/jquery.fancybox-1.3.4.pack.js') %]" charset="utf-8"></script> + <script src="[% version('/cobrands/fixmybarangay/message_manager_client.js') %]" charset="utf-8"></script> <script> $(document).ready(function() { diff --git a/templates/web/fixmybarangay/report/_message_manager.html b/templates/web/fixmybarangay/report/_message_manager.html index 2697e156c..9f3692f17 100644 --- a/templates/web/fixmybarangay/report/_message_manager.html +++ b/templates/web/fixmybarangay/report/_message_manager.html @@ -1,6 +1,9 @@ [% IF c.user && c.user.from_council %] -<input type="button" class="green-btn" value="Show Messages" id="show_messages"> +[% IF problem.id %] + <input type="button" class="green-btn" value="Show Messages" id="show_messages"> +[% END %] + <ul id="message_manager" class="issue-list-a tab" style="display: none"> <li id="message-control"> <div id="mm-username-container">username: <span id="mm-received-username"></span></div> @@ -8,16 +11,16 @@ <div id="mm-status-message"></div> </div> <div id="mm-login-container"> - <div class="input text"> - <label for="mm-htauth-username">MM username</label> + <div> + <label for="mm-htauth-username">Username:</label> <input name="mm-htauth-username" id="mm-htauth-username" type="text"/> </div> - <div class="input password"> - <label for="mm-htauth-password">Password</label> + <div> + <label for="mm-htauth-password">Password:</label> <input name="mm-htauth-password" id="mm-htauth-password" type="password"/> </div> <div class="submit"> - <input id="available-submit" type="submit" value="Get available messages"/> + <input id="available-submit" type="submit" value="Get available messages" class="green-btn"/> </div> </div> </li> @@ -25,15 +28,35 @@ <div id="mm-message-list" style="min-height:1em;"></div> </li> </ul> +<div style="display:none"> + <div id="reply-form-container"> + <form action="/" id="reply-form" onsubmit="event.returnValue = false; return false;" method="post" accept-charset="utf-8"> + <input type="hidden" name="message_id" id="reply_to_msg_id"/> + <div> + <label for="reply_text">Reply text:</label> + <textarea name="reply_text" id="reply_text"></textarea> + </div> + <div class="submit"> + <input id="reply-submit" type="submit" value="Send Reply" class="green-btn"/> + </div> + </form> + </div> +</div> <script type="text/javascript"> $(document).ready(function() { var mm_url = "[% c.config.MESSAGE_MANAGER_URL %]"; // from config - + var problem_id = "[% problem.id %]"; + var dummy_busy = false; + + function sanitise_id(css_id) { + return css_id.replace(/\D/g, ""); + } + var mm_populate_list = function(data) { - $('#mm-status-message-container').text("Accessed message server as " + data['username']); + $('#mm-status-message-container').text("Accessed Message Manager as " + data['username']); $('input[name=mm_text]').prop('checked', false); // uncheck all } @@ -50,6 +73,15 @@ $(document).ready(function() { $('#form_detail').val(msg_text); $('#external_source_id').val(service_id); } + + var dummy_reply_cleanup = function(data) { + $('#reply_text').val(''); + dummy_busy = false; + } + + var dummy_hide_cleanup = function(data) { + dummy_busy = false; + } message_manager.config({url_root: mm_url}); message_manager.setup_click_listener({callback:mm_selected_message}); @@ -66,29 +98,76 @@ $(document).ready(function() { }); $('#available-submit').click(); - $('<input type="button" value="Copy to update"/>').attr({ - 'id': 'add_support', - 'name': 'add_support', - 'class': 'green-btn' - }).appendTo($('#message_manager')); + $('#hide-button').click(function() { + if ($('#message_id').val()) { + message_manager.hide( + $('#message_id').val(), + {callback:dummy_hide_cleanup}); + } + }); + + $('#mm-message-list').on('mouseover', 'li.mm-msg', function(e){ + e.stopPropagation(); // because replies are nested + $('.mm-msg-action', $('#mm-message-list')).stop().fadeOut(200); + $(this).find('> .mm-msg-action').stop().show(); + console.log("clicked on: " + $(this).attr('id')); + }); + + $('#mm-message-list').on('click', '.mm-hide', function(e){ + var want_hide = + confirm('Are you sure you want to delete the following message?\n\n"' + + $('p', $(this).parent()).first().text() + '"\n'); + if (want_hide) { + message_manager.hide( + sanitise_id($(this).parent().attr('id')), + {callback:dummy_hide_cleanup}); + } + }); + + $('#mm-message-list').on('click', '.mm-rep', function(e){ + console.log("call message_manager.reply(" + $(this).parent().attr('id') + ", reply_text)"); + }); + + $('#reply-submit').click(function(e) { + e.preventDefault(); + if (! dummy_busy) { + dummy_busy = true; + console.log("sending reply to: " + $('#reply_to_msg_id').val()); + message_manager.reply( + $('#reply_to_msg_id').val(), + $('#reply_text').val(), + {callback:dummy_reply_cleanup}); + } + }); + + $("a#reply").fancybox({onClosed: function(){dummy_busy=false;}}); + + // only show on problem display page + if (problem_id) { + $('<input type="button" value="Copy to update"/>').attr({ + 'id': 'add_support', + 'name': 'add_support', + 'class': 'green-btn' + }).appendTo($('#message_manager')); + } $('#add_support').click(function(e){ - e.preventDefault(); - $('#mm-message-list input:checked').each( function(index) { - var id = $(this).attr('id'); - id = id.replace('mm_text_',''); - $('#external_source_id').val(id); - $('#form_update').val( $(this).val() ); - $('#form_update_form').on('submit', function(e) { - message_manager.assign_fms_id( $('#external_source_id').val(), [% problem.id %], { 'is_async': false } ); - }); - }); - }); - - $('#show_messages').on('click', function(e) { - $('#message_manager').toggle(); - $('#show_messages').val( $('#show_messages').val() == 'Show Messages' ? 'Hide Messages' : 'Show Messages' ); - } ); + e.preventDefault(); + $('#mm-message-list input:checked').each( function(index) { + var id = $(this).attr('id'); + id = id.replace('mm_text_',''); + $('#external_source_id').val(id); + $('#form_update').val( $(this).val() ); + $('#form_update_form').on('submit', function(e) { + message_manager.assign_fms_id( $('#external_source_id').val(), problem_id, { 'is_async': false } ); + }); + }); + }); + + $('#show_messages').on('click', function(e) { + $('#message_manager').toggle(); + $('#show_messages').val( $('#show_messages').val() == 'Show Messages' ? 'Hide Messages' : 'Show Messages' ); + }); }); </script> diff --git a/web/cobrands/fixmybarangay/message_manager.scss b/web/cobrands/fixmybarangay/message_manager.scss index 3133d3bbc..5b6d7bd62 100644 --- a/web/cobrands/fixmybarangay/message_manager.scss +++ b/web/cobrands/fixmybarangay/message_manager.scss @@ -1,6 +1,16 @@ $mm_status_message_color: #a66; $mm_border_color: #eee; +$color_reply_bg: #cccccc; +$color_bg_reply_0: #E8E8E8; +$color_bg_reply_1: #DEDEDE; +$color_bg_reply_2: #D6D6D6; +$color_bg_reply_3: #D1D1D1; +$color_bg_reply_4: #C9C9C9; +$color_bg_reply_5: #BFBFBF; +$color_bg_reply_6: #B8B8B8; +$color_bg_mm_list: #F6F6F6; + #message_manager { #message-control { @@ -38,14 +48,34 @@ $mm_border_color: #eee; list-style-type: none; padding: 0; margin: 0; - li { + li, ul.mm-reply-thread li { + position: relative; clear: both; margin: 4px 0 0 0; padding: 0; cursor: pointer; - background-color: #F6F6F6; + background-color: $color_bg_mm_list; p { background-color: inherit; + margin: 0.25em 0 0 0; + padding: 0.5em 1em; + &:hover { background-color: #efe;} + } + ul.mm-reply-thread { + li { + margin:0; + } + .mm-reply { + background-color: #ccc; + &:hover {background-color: #eef;} + } + .mm-reply-0 { margin-left: 0em; background-color: $color_bg_reply_0;} + .mm-reply-1 { margin-left: 1em; background-color: $color_bg_reply_1;} + .mm-reply-2 { margin-left: 2em; background-color: $color_bg_reply_2;} + .mm-reply-3 { margin-left: 3em; background-color: $color_bg_reply_3;} + .mm-reply-4 { margin-left: 4em; background-color: $color_bg_reply_4;} + .mm-reply-5 { margin-left: 5em; background-color: $color_bg_reply_5;} + .mm-reply-6 { margin-left: 6em; background-color: $color_bg_reply_6;} } &.msg-is-locked { background-color: #fdd;} &.msg-is-owned { background-color: #dfd;} @@ -64,6 +94,23 @@ $mm_border_color: #eee; font-weight: normal; margin: 0.1em 0 0.1em 4.5em; } + .mm-msg-action { + display: none; + padding: 0.2em 0.4em; + color: white; + text-align: center; + position: absolute; + top: 4px; + &:hover { background-color: black;} + } + .mm-hide { + right:0px; + background-color: red; + } + .mm-rep { + right:1.4em; + background-color: green; + } } } } @@ -71,3 +118,16 @@ $mm_border_color: #eee; margin: 1em; } } +#show_messages, #add_support { // COPY TO UPDATE button + margin: 1em; +} +#reply-form-container { + #reply-form{ + margin-top: 2em; + border: 1px solid $mm_border_color; + background-color: #ffdddd; + } + .submit { + margin: 1em 0; + } +} diff --git a/web/cobrands/fixmybarangay/message_manager_client.js b/web/cobrands/fixmybarangay/message_manager_client.js index 508286171..1614eff2d 100644 --- a/web/cobrands/fixmybarangay/message_manager_client.js +++ b/web/cobrands/fixmybarangay/message_manager_client.js @@ -14,6 +14,9 @@ * * msg_prefix all message <li> items have this as their ID prefix * + * mm_name name of Message Manager (used in error messages shown + * to user, e.g., "please log in to Message Manager" + * * *_selector these are the jQuery selects that will be used to find * the respective elements: * @@ -28,6 +31,8 @@ * message_manager.get_available_messages([options]) * message_manager.request_lock(msg_id, [options]) (default use: client code doesn't need to call this explicitly) * message_manager.assign_fms_id(msg_id, fms_id, [options]) + * message_manager.hide(msg_id, [options]) + * message_manager.reply(msg_id, reply_text, [options]) * * Note: options are {name:value, ...} hashes and often include "callback" which is a function that is executed on success * but see the docs (request_lock executes callback if the call is successful even if the lock was denied, for example). @@ -42,7 +47,9 @@ var message_manager = (function() { var _want_unique_locks = true; var _msg_prefix = "msg-"; var _username; - + var _mm_name = "Message Manager"; + var _use_fancybox = true; // note: currently *must* have fancybox! + // cached jQuery elements, populated by the (mandatory) call to config() var $message_list_element; var $status_element; @@ -77,6 +84,9 @@ var message_manager = (function() { selectors[sel] = settings[sel]; } } + if (typeof settings.mm_name === 'string') { + _mm_name = settings.mm_name; + } } $message_list_element = $(selectors.message_list_selector); $status_element = $(selectors.status_selector); @@ -131,6 +141,57 @@ var message_manager = (function() { } }; + var extract_replies = function(replies, depth) { + var $ul = ""; + if (replies && replies.length > 0) { + var indent = new Array( depth + 1 ).join(' '); + $ul = $('<ul class="mm-reply-thread"/>'); + for (var i=0; i<replies.length; i++) { + $ul.append(get_message_li(replies[i], depth)); + } + } + return $ul; + } + + var get_message_li = function(message_root, depth) { + var msg = message_root.Message; // or use label value + var lockkeeper = message_root.Lockkeeper.username; + var escaped_text = $('<div/>').text(msg.message).html(); + var $p = $('<p/>'); + var $hide_button = $('<span class="mm-msg-action mm-hide" id="mm-hide-' + msg.id + '">X</span>'); + var $reply_button = $('<a class="mm-msg-action mm-rep" id="mm-rep-' + msg.id + '" href="#reply-form-container">reply</a>'); + if (_use_fancybox) { + $reply_button.fancybox(); + } + if (depth == 0) { + var tag = (!msg.tag || msg.tag === 'null')? ' ' : msg.tag; + tag = $('<span class="msg-tag"/>').html(tag); + var radio = depth > 0? null : $('<input type="radio"/>').attr({ + 'id': 'mm_text_' + msg.id, + 'name': 'mm_text', + 'value': escaped_text + }).wrap('<p/>').parent().html(); + var label = $('<label/>', { + 'class': 'msg-text', + 'for': 'mm_text_' + msg.id + }).text(escaped_text).wrap('<p/>').parent().html(); + $p.append(tag).append(radio).append(label); + } else { + $p.text(escaped_text).addClass('mm-reply mm-reply-' + depth); + } + var $litem = $('<li id="' + _msg_prefix + msg.id + '" class="mm-msg">').append($p).append($hide_button) + if (msg.is_outbound != 1) { + $litem.append($reply_button); + }; + if (lockkeeper) { + $litem.addClass(lockkeeper == _username? 'msg-is-owned' : 'msg-is-locked'); + } + if (message_root.children) { + $litem.append(extract_replies(message_root.children, depth+1)); + } + return $litem; + } + var show_available_messages = function(data) { var messages = data.messages; _username = data.username; @@ -139,27 +200,9 @@ var message_manager = (function() { if (messages.length === 0) { $output.html('<p class="mm-empty">No messages available.</p>'); } else { - var $ul = $('<ul/>'); + var $ul = $('<ul class="mm-root"/>'); for(var i=0; i< messages.length; i++) { - var msg = messages[i].Message; // or use label value - var lockkeeper = messages[i].Lockkeeper.username; - var escaped_text = $('<div/>').text(msg.message).html(); - var tag = (!msg.tag || msg.tag === 'null')? ' ' : msg.tag; - tag = $('<span class="msg-tag"/>').html(tag); - var radio = $('<input type="radio"/>').attr({ - 'id': 'mm_text_' + msg.id, - 'name': 'mm_text', - 'value': escaped_text - }).wrap('<p/>').parent().html(); - var label = $('<label/>', { - 'class': 'msg-text', - 'for': 'mm_text_' + msg.id - }).text(escaped_text).wrap('<p/>').parent().html(); - var p = $('<p/>').append(tag).append(radio).append(label); - var litem = $('<li id="' + _msg_prefix + msg.id + '" class="mm-msg">').append(p); - if (lockkeeper) { - litem.addClass(lockkeeper == _username? 'msg-is-owned' : 'msg-is-locked'); - } + var litem = get_message_li(messages[i], 0); $ul.append(litem); } $output.empty().append($ul); @@ -185,6 +228,10 @@ var message_manager = (function() { } request_lock(id, options); }); + // clicking the reply button loads the id into the (modal/fancybox) reply form + $message_list_element.on('click', '.mm-rep', function(event) { + $('#reply_to_msg_id').val($(this).closest('li').attr('id').replace(_msg_prefix, '')); + }) }; // gets messages or else requests login @@ -217,7 +264,8 @@ var message_manager = (function() { error: function(jqXHR, textStatus, errorThrown) { var st = jqXHR.status; if (st == 401 || st == 403) { - var msg = (st == 401)? "Invalid username or password" : "Access denied: please log in"; + var msg = (st == 401 ? "Invalid username or password for" : "Access denied: please log in to") + + " " + _mm_name; say_status(msg); show_login_form(); } else { @@ -333,6 +381,105 @@ var message_manager = (function() { }); }; + var reply = function(msg_id, reply_text, options) { + if (_use_fancybox){ + $.fancybox.close(); + } + var check_li_exists = false; + if (options) { + if (typeof(options.callback) === 'function') { + callback = options.callback; + } + if (typeof(options.check_li_exists) !== undefined && options.check_li_exists !== undefined) { + check_li_exists = true; // MM dummy + } + } + var $li = $('#' + _msg_prefix + msg_id); + if (check_li_exists) { + if ($li.size() === 0) { + say_status("Couldn't find message with ID " + msg_id); + return; + } + } + reply_text = $.trim(reply_text); + if (reply_text === '') { + say_status("won't send empty reply"); + return; + } + $li.addClass('msg-is-busy'); + $.ajax({ + dataType:"json", + type:"post", + data: {reply_text: reply_text}, + url: _url_root +"messages/reply/" + msg_id + ".json", + beforeSend: function (xhr){ + xhr.setRequestHeader('Authorization', get_current_auth_credentials()); + xhr.withCredentials = true; + }, + success:function(data, textStatus) { + if (data.success) { + $li.removeClass('msg-is-busy msg-is-locked').addClass('msg-is-owned'); // no longer available + say_status("Reply sent OK"); + if (typeof(callback) === "function") { + callback.call($(this), data.data); // returned data['data'] is null but may change in future + } + } else { + $li.removeClass('msg-is-busy').addClass('msg-is-locked'); + say_status("failed: " + data.error); + } + }, + error: function(jqXHR, textStatus, errorThrown) { + say_status("error: " + textStatus + ": " + errorThrown); + $li.removeClass('msg-is-busy'); + } + }); + }; + + var hide = function(msg_id, options) { + var check_li_exists = false; + if (options) { + if (typeof(options.callback) === 'function') { + callback = options.callback; + } + if (typeof(options.check_li_exists) !== undefined && options.check_li_exists !== undefined) { + check_li_exists = true; // MM dummy + } + } + var $li = $('#' + _msg_prefix + msg_id); + if (check_li_exists) { + if ($li.size() === 0) { + say_status("Couldn't find message with ID " + msg_id); + return; + } + } + $li.addClass('msg-is-busy'); + $.ajax({ + dataType:"json", + type:"post", + url: _url_root +"messages/hide/" + msg_id + ".json", + beforeSend: function (xhr){ + xhr.setRequestHeader('Authorization', get_current_auth_credentials()); + xhr.withCredentials = true; + }, + success:function(data, textStatus) { + if (data.success) { + $li.removeClass('msg-is-busy msg-is-locked').addClass('msg-is-owned').fadeOut('slow'); // no longer available + say_status("Message hidden"); + if (typeof(callback) === "function") { + callback.call($(this), data.data); + } + } else { + $li.removeClass('msg-is-busy').addClass('msg-is-locked'); + say_status("failed: " + data.error); + } + }, + error: function(jqXHR, textStatus, errorThrown) { + say_status("error: " + textStatus + ": " + errorThrown); + $li.removeClass('msg-is-busy'); + } + }); + }; + // revealed public methods: return { config: config, @@ -340,6 +487,8 @@ var message_manager = (function() { get_available_messages: get_available_messages, request_lock: request_lock, assign_fms_id: assign_fms_id, + reply: reply, + hide: hide, sign_out: sign_out }; })(); |