From f2756c4c825ba73c76fafd84acc3663ea410858a Mon Sep 17 00:00:00 2001 From: Matthew Somerville Date: Thu, 9 Mar 2017 18:51:13 +0000 Subject: Move staff-only JavaScript to separate file. --- templates/web/base/common_scripts.html | 8 +- web/cobrands/fixmystreet/admin.js | 125 +++++++++++ web/cobrands/fixmystreet/fixmystreet.js | 358 ++------------------------------ web/cobrands/fixmystreet/staff.js | 342 ++++++++++++++++++++++++++++++ web/js/fixmystreet-admin.js | 125 ----------- 5 files changed, 487 insertions(+), 471 deletions(-) create mode 100644 web/cobrands/fixmystreet/admin.js create mode 100644 web/cobrands/fixmystreet/staff.js delete mode 100644 web/js/fixmystreet-admin.js diff --git a/templates/web/base/common_scripts.html b/templates/web/base/common_scripts.html index 1d53f1d51..42c04f11f 100644 --- a/templates/web/base/common_scripts.html +++ b/templates/web/base/common_scripts.html @@ -16,6 +16,12 @@ scripts.push( version('/cobrands/fixmystreet/fixmystreet.js'), ); +IF c.user_exists AND (c.user.from_body OR c.user.is_superuser); + scripts.push( + version('/cobrands/fixmystreet/staff.js') + ); +END; + FOR script IN map_js; scripts.push(script); END; @@ -28,7 +34,7 @@ scripts.push( IF admin; scripts.push( version('/js/jquery-ui/js/jquery-ui-1.10.3.custom.min.js'), - version('/js/fixmystreet-admin.js'), + version('/cobrands/fixmystreet/admin.js'), ); END; diff --git a/web/cobrands/fixmystreet/admin.js b/web/cobrands/fixmystreet/admin.js new file mode 100644 index 000000000..02eb30766 --- /dev/null +++ b/web/cobrands/fixmystreet/admin.js @@ -0,0 +1,125 @@ +$(function(){ + // available for admin pages + + // hide the open311_only section and reveal it only when send_method is relevant + function hide_or_show_open311(e, hide_fast) { + var $form = $(this).closest("form"); + var $open311_only = $form.find('.admin-open311-only'); + + var send_method = $(this).val(); + var show_open311 = false; + if ($form.find('[name=endpoint]').val()) { + show_open311 = true; // always show the form if there is an endpoint value + } else if (send_method && !send_method.match(/^(email|noop|refused)$/i)) { + show_open311 = true; + } + if (show_open311) { + $open311_only.slideDown(); + } else { + if (hide_fast) { + $open311_only.hide(); + } else { + $open311_only.slideUp(); + } + } + } + + if ($('.admin-open311-only').length) { + // Add handler to send_method dropdowns and set initial visibility + $('[name=send_method]').on('change', hide_or_show_open311).each(function() { + hide_or_show_open311.call(this, null, true); + }); + } + + // Some lists of checkboxes have 'select all/none' links at the top + $("a[data-select-none], a[data-select-all]").click(function(e) { + e.preventDefault(); + var checked = $(this).filter('[data-select-all]').length > 0; + $(this).closest("ul").find('input[type=checkbox]').prop('checked', checked); + }); + + + // admin hints: maybe better implemented as tooltips? + $(".admin-hint").on('click', function(){ + if ($(this).hasClass('admin-hint-show')) { + $(this).removeClass('admin-hint-show'); + } else { + $(this).addClass('admin-hint-show'); + } + }); + + // on a body's page, hide/show deleted contact categories + var $table_with_deleted_contacts = $('table tr.is-deleted td.contact-category').closest('table'); + if ($table_with_deleted_contacts.length == 1) { + var $toggle_deleted_btn = $(""); + $table_with_deleted_contacts.before($toggle_deleted_btn); + $toggle_deleted_btn.on('click', function(e){ + e.preventDefault(); + var $cols = $table_with_deleted_contacts.find('tr.is-deleted'); + if ($cols.first().is(':visible')) { + $cols.hide(); + $(this).prop("value", 'Show deleted contacts'); + } else { + $cols.show(); + $(this).prop("value", 'Hide deleted contacts'); + } + }); + } + + // On some cobrands the datepicker ends up beneath items in the header, e.g. + // the logo. + // This function sets an appropriate z-index when the datepicker is shown. + // Sadly there's no way to set the z-index when creating the datepicker, so + // we have to run this little helper using the datepicker beforeShow + // handler. + function fixZIndex() { + setTimeout(function() { + $('.ui-datepicker').css('z-index', 10); + }, 0); + } + + $( "#start_date" ).datepicker({ + defaultDate: "-1w", + changeMonth: true, + dateFormat: 'dd/mm/yy' , + // This sets the other fields minDate to our date + onClose: function( selectedDate ) { + $( "#end_date" ).datepicker( "option", "minDate", selectedDate ); + }, + beforeShow: fixZIndex + }); + $( "#end_date" ).datepicker({ + /// defaultDate: "+1w", + changeMonth: true, + dateFormat: 'dd/mm/yy' , + onClose: function( selectedDate ) { + $( "#start_date" ).datepicker( "option", "maxDate", selectedDate ); + }, + beforeShow: fixZIndex + }); + + // On user edit page, hide the area/categories fields if body changes + $("form#user_edit select#body").change(function() { + var show_area = $(this).val() == $(this).find("[data-originally-selected]").val(); + $("form#user_edit select#area_id").closest("li").toggle(show_area); + $("form#user_edit .js-user-categories").toggle(show_area); + }); + + // On category edit page, hide the reputation input if inspection isn't required + $("form#category_edit #inspection_required").change(function() { + var $p = $("form#category_edit #reputation_threshold").closest("p"); + var $hint = $p.prevUntil().first(); + if (this.checked) { + $p.removeClass("hidden"); + if ($hint.length) { + $hint.removeClass("hidden"); + } + } else { + $p.addClass("hidden"); + if ($hint.length) { + $hint.addClass("hidden"); + } + } + }); +}); + diff --git a/web/cobrands/fixmystreet/fixmystreet.js b/web/cobrands/fixmystreet/fixmystreet.js index a0d830a65..df8285942 100644 --- a/web/cobrands/fixmystreet/fixmystreet.js +++ b/web/cobrands/fixmystreet/fixmystreet.js @@ -222,6 +222,14 @@ fixmystreet.update_list_item_buttons = function($list) { $list.children(':last-child').find('[name="shortlist-down"]').prop('disabled', true); }; +// A tiny helper to call a function only if it exists (so we can +// call this with staff-only functions and they won't error). +fixmystreet.run = function(fn) { + if (fn) { + fn.call(this); + } +}; + fixmystreet.set_up = fixmystreet.set_up || {}; $.extend(fixmystreet.set_up, { basics: function() { @@ -406,199 +414,6 @@ $.extend(fixmystreet.set_up, { }); }, - manage_duplicates: function() { - // Deal with changes to report state by inspector/other staff, specifically - // displaying nearby reports if it's changed to 'duplicate'. - function refresh_duplicate_list() { - var report_id = $("#report_inspect_form .js-report-id").text(); - var args = { - filter_category: $("#report_inspect_form select#category").val(), - latitude: $('input[name="latitude"]').val(), - longitude: $('input[name="longitude"]').val() - }; - $("#js-duplicate-reports ul").html("
  • Loading...
  • "); - var nearby_url = '/report/'+report_id+'/nearby.json'; - $.getJSON(nearby_url, args, function(data) { - var duplicate_of = $("#report_inspect_form [name=duplicate_of]").val(); - var $reports = $(data.current) - .filter("li") - .not("[data-report-id="+report_id+"]") - .slice(0, 5); - $reports.filter("[data-report-id="+duplicate_of+"]").addClass("item-list--reports__item--selected"); - - (function() { - var timeout; - $reports.on('mouseenter', function(){ - clearTimeout(timeout); - fixmystreet.maps.markers_highlight(parseInt($(this).data('reportId'), 10)); - }).on('mouseleave', function(){ - timeout = setTimeout(fixmystreet.maps.markers_highlight, 50); - }); - })(); - - $("#js-duplicate-reports ul").empty().prepend($reports); - - $reports.find("a").click(function() { - var report_id = $(this).closest("li").data('reportId'); - $("#report_inspect_form [name=duplicate_of]").val(report_id); - $("#js-duplicate-reports ul li").removeClass("item-list--reports__item--selected"); - $(this).closest("li").addClass("item-list--reports__item--selected"); - return false; - }); - - show_nearby_pins(data, report_id); - }); - } - - function show_nearby_pins(data, report_id) { - var markers = fixmystreet.maps.markers_list( data.pins, true ); - // We're replacing all the features in the markers layer with the - // possible duplicates, but the list of pins from the server doesn't - // include the current report. So we need to extract the feature for - // the current report and include it in the list of features we're - // showing on the layer. - var report_marker = fixmystreet.maps.get_marker_by_id(parseInt(report_id, 10)); - if (report_marker) { - markers.unshift(report_marker); - } - fixmystreet.markers.removeAllFeatures(); - fixmystreet.markers.addFeatures( markers ); - } - - function state_change() { - // The duplicate report list only makes sense when state is 'duplicate' - if ($(this).val() !== "duplicate") { - $("#js-duplicate-reports").addClass("hidden"); - return; - } else { - $("#js-duplicate-reports").removeClass("hidden"); - } - // If this report is already marked as a duplicate of another, then - // there's no need to refresh the list of duplicate reports - var duplicate_of = $("#report_inspect_form [name=duplicate_of]").val(); - if (!!duplicate_of) { - return; - } - - refresh_duplicate_list(); - } - - $("#report_inspect_form").on("change.state", "select#state", state_change); - $("#js-change-duplicate-report").click(refresh_duplicate_list); - }, - - list_item_actions: function() { - function toggle_shortlist(btn, sw, id) { - btn.attr('class', 'item-list__item__shortlist-' + sw); - btn.attr('title', btn.data('label-' + sw)); - if (id) { - sw += '-' + id; - } - btn.attr('name', 'shortlist-' + sw); - } - - $('.item-list--reports').on('click', ':submit', function(e) { - e.preventDefault(); - - var $submitButton = $(this); - var whatUserWants = $submitButton.prop('name'); - var data; - var $item; - var $list; - var $hiddenInput; - var report_id; - if (fixmystreet.page === 'around') { - // Deal differently because one big form - var parts = whatUserWants.split('-'); - whatUserWants = parts[0] + '-' + parts[1]; - report_id = parts[2]; - var token = $('[name=token]').val(); - data = whatUserWants + '=1&token=' + token + '&id=' + report_id; - } else { - var $form = $(this).parents('form'); - $item = $form.parent('.item-list__item'); - $list = $item.parent('.item-list'); - - // The server expects to be told which button/input triggered the form - // submission. But $form.serialize() doesn't know that. So we inject a - // hidden input into the form, that can pass the name and value of the - // submit button to the server, as it expects. - $hiddenInput = $('').attr({ - type: 'hidden', - name: whatUserWants, - value: $submitButton.prop('value') - }).appendTo($form); - data = $form.serialize() + '&ajax=1'; - } - - // Update UI while the ajax request is sent in the background. - if ('shortlist-down' === whatUserWants) { - $item.insertAfter( $item.next() ); - } else if ('shortlist-up' === whatUserWants) { - $item.insertBefore( $item.prev() ); - } else if ('shortlist-remove' === whatUserWants) { - toggle_shortlist($submitButton, 'add', report_id); - } else if ('shortlist-add' === whatUserWants) { - toggle_shortlist($submitButton, 'remove', report_id); - } - - // Items have moved around. We need to make sure the "up" button on the - // first item, and the "down" button on the last item, are disabled. - fixmystreet.update_list_item_buttons($list); - - $.ajax({ - url: '/my/planned/change', - type: 'POST', - data: data - }).fail(function() { - // Undo the UI changes we made. - if ('shortlist-down' === whatUserWants) { - $item.insertBefore( $item.prev() ); - } else if ('shortlist-up' === whatUserWants) { - $item.insertAfter( $item.next() ); - } else if ('shortlist-remove' === whatUserWants) { - toggle_shortlist($submitButton, 'remove', report_id); - } else if ('shortlist-add' === whatUserWants) { - toggle_shortlist($submitButton, 'add', report_id); - } - fixmystreet.update_list_item_buttons($list); - }).complete(function() { - if ($hiddenInput) { - $hiddenInput.remove(); - } - }); - }); - }, - - contribute_as: function() { - $('.content').on('change', '.js-contribute-as', function(){ - var opt = this.options[this.selectedIndex], - val = opt.value, - txt = opt.text; - var $emailInput = $('input[name=email]').add('input[name=rznvy]'); - var $nameInput = $('input[name=name]'); - var $showNameCheckbox = $('input[name=may_show_name]'); - var $addAlertCheckbox = $('#form_add_alert'); - if (val === 'myself') { - $emailInput.val($emailInput.prop('defaultValue')).prop('disabled', true); - $nameInput.val($nameInput.prop('defaultValue')).prop('disabled', false); - $showNameCheckbox.prop('checked', false).prop('disabled', false); - $addAlertCheckbox.prop('checked', true).prop('disabled', false); - } else if (val === 'another_user') { - $emailInput.val('').prop('disabled', false); - $nameInput.val('').prop('disabled', false); - $showNameCheckbox.prop('checked', false).prop('disabled', true); - $addAlertCheckbox.prop('checked', true).prop('disabled', false); - } else if (val === 'body') { - $emailInput.val('-').prop('disabled', true); - $nameInput.val(txt).prop('disabled', true); - $showNameCheckbox.prop('checked', true).prop('disabled', true); - $addAlertCheckbox.prop('checked', false).prop('disabled', true); - } - }); - $('.js-contribute-as').change(); - }, - on_resize: function() { var last_type; $(window).on('resize', function() { @@ -737,86 +552,6 @@ $.extend(fixmystreet.set_up, { make_multi('filter_categories'); }, - report_page_inspect: function() { - if (!$('form#report_inspect_form').length) { - return; - } - - // Focus on form - $('html,body').scrollTop($('#report_inspect_form').offset().top); - - // On the manage/inspect report form, we already have all the extra inputs - // in the DOM, we just need to hide/show them as appropriate. - $('form#report_inspect_form [name=category]').change(function() { - var category = $(this).val(), - selector = "[data-category='" + category + "']"; - $("form#report_inspect_form [data-category]:not(" + selector + ")").addClass("hidden"); - $("form#report_inspect_form " + selector).removeClass("hidden"); - // And update the associated priority list - var priorities = $("form#report_inspect_form " + selector).data('priorities'); - var $select = $('#problem_priority'), - curr_pri = $select.val(); - $select.find('option:gt(0)').remove(); - $.each(priorities.split('&'), function(i, kv) { - if (!kv) { - return; - } - kv = kv.split('=', 2); - $select.append($('