Skip to content

Commit

Permalink
Migrate inline js in EditRights to util.js
Browse files Browse the repository at this point in the history
Inline js doesn't fully work any more because of htmx changes. E.g. after
clicking "Save Changes", no right lists will show up. This commit refactors
it to make it work with htmx.
  • Loading branch information
sunnavy committed Jan 10, 2025
1 parent df11be5 commit 8c40b04
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 141 deletions.
143 changes: 2 additions & 141 deletions share/html/Admin/Elements/EditRights
Original file line number Diff line number Diff line change
Expand Up @@ -82,133 +82,8 @@ if ($anchor =~ /AddPrincipal/) {
%# The last value is a boolean determining if the value of DisplayColumn
%# should be loc()-ed before display.

<script type="text/javascript">
jQuery(function() {
function sync_anchor(hash) {
if (!hash.length) return;
window.location.hash = hash;
jQuery(".rights-editor input[name=Anchor]").val(hash);
}
sync_anchor(<% $anchor |n,j %>);

jQuery('.rights-editor .principal-tabs a[data-bs-toggle="tab"]').on('shown.bs.tab', function(e) {
var anchor = jQuery(this).attr('href').replace('#acl-', '#');
sync_anchor(anchor);
jQuery('.rights-editor .category-tabs a[data-bs-toggle="tab"]:visible:first').tab('show');
if ( anchor == '#AddPrincipal' ) {
jQuery('.rights-editor li.add-principal input').focus();
}
});

jQuery('li.add-principal input').focus(function() {
jQuery('.rights-editor .principal-tabs a[data-bs-toggle="tab"][href="#acl-AddPrincipal"]').tab('show');
});

var anchor = jQuery(".rights-editor input[name=Anchor]").val();
if ( anchor && jQuery('.rights-editor .principal-tabs a[data-bs-toggle="tab"][href="' + anchor.replace('#', '#acl-') + '"]' ).length ) {
jQuery('.rights-editor .principal-tabs a[data-bs-toggle="tab"][href="' + anchor.replace('#', '#acl-') + '"]' ).tab('show');
}
else {
jQuery('.rights-editor .principal-tabs a[data-bs-toggle="tab"]:first').tab('show');
}

jQuery('.rights-editor .category-tabs a[data-bs-toggle="tab"]').on('shown.bs.tab', function(e) {
createCookie('rights-category-tab', jQuery(this).attr('href'));
});

const category_tab = getCookie('rights-category-tab');
if ( category_tab && jQuery(category_tab).length ) {
jQuery('.rights-editor .category-tabs a[data-bs-toggle="tab"][href="' + category_tab + '"]' ).tab('show');
}
else {
jQuery('.rights-editor .category-tabs a[data-bs-toggle="tab"]:visible:first').tab('show');
};

// "rights" checkbox state cache...
var check_counts = {};

// Before page loads we need to initialize our "rights" checkbox state
// cache.
jQuery("div.category-tabs input[type=checkbox]").each(function(index, element) {
// Evaluating each checkbox and its current check state is the same
// as evaluating a check event once the page is loaded. However, we
// must indicate to the process_check_event that we are initializing
// the cache. That is, we musn't decrement values from count
// totals for checkboxes that aren't checked. That only happens when
// a user actually unchecks a box, not when we are initially counting
// checked or unchecked boxes.
process_check_event(element, true);
});

jQuery("div.category-tabs input[type=checkbox]").change(function() {
process_check_event(this, false);
});

// parameters:
// checkbox - DOM checkbox element that was checked
// initializing_cache - a boolean that defines whether or not this
// function was called with the purpose of
// initializing the contents of the check_counts
// cache.
function process_check_event(checkbox, initializing_cache) {
var category_tab = checkbox.getAttribute('data-category-tab');
var principal_tab = checkbox.getAttribute('data-principal-tab');

classify_tab(checkbox.checked, category_tab, initializing_cache);
classify_tab(checkbox.checked, principal_tab, initializing_cache);
}

function classify_tab(checked, tab_id, initializing_cache) {
if (typeof check_counts[tab_id] == 'undefined') {
check_counts[tab_id] = 0;
}

if (checked) {
check_counts[tab_id]++;
if (check_counts[tab_id] == 1) {
// Then this is the first check and we need to add a class
// to the tab.
jQuery('#' + tab_id).addClass("tab-aggregates-checked-rights");
}
}
else if (! initializing_cache) {
check_counts[tab_id]--;
if (check_counts[tab_id] == 0) {
// Then this is the last uncheck and we need to remove a
// class from the tab.
jQuery('#' + tab_id).removeClass("tab-aggregates-checked-rights");
}
}
}

var auto_set_own_dashboards;
jQuery('input[value="ModifySelf"]').change(function() {
var form = jQuery(this).closest('form');
if ( jQuery(this).is(':checked') ) {
if ( form.find('input[value$="OwnDashboard"]:visible:not(:checked)').length ) {
jQuery('#grant-own-dashboard-rights-modal').modal('show');
}
}
else {
if ( auto_set_own_dashboards ) {
form.find('input[value$="OwnDashboard"]:visible:checked').prop('checked', false);
auto_set_own_dashboards = false;
}
}
});

jQuery('#grant-own-dashboard-rights-confirm').click(function() {
var form = jQuery(this).closest('form');
form.find('input[value$="OwnSavedSearch"]:visible:not(:checked)').prop('checked', true);
form.find('input[value$="OwnDashboard"]:visible:not(:checked)').prop('checked', true);
jQuery('#grant-own-dashboard-rights-modal').modal('hide');
auto_set_own_dashboards = true;
});
});
</script>

<div class="rights-editor">
<input type="hidden" value="" name="Anchor" />
<div class="rights-editor" data-principal-type="<% $AddPrincipal %>">
<input type="hidden" value="<% $anchor %>" name="Anchor" />
<div class="row mt-2">
<div class="col-3">
<div class="principal-tabs">
Expand Down Expand Up @@ -238,20 +113,6 @@ for my $category (@$Principals) {
}
</%perl>
% if ( $AddPrincipal ) {

<script type="text/javascript">
jQuery(function() {
jQuery("#AddPrincipalForRights-"+<% lc $AddPrincipal |n,j%>).keyup(function(){
toggle_addprincipal_validity(this, true);
}).keydown(function(event){
event.stopPropagation() // Disable tabs keyboard nav
});

jQuery("#AddPrincipalForRights-"+<% lc $AddPrincipal |n,j%>).on("autocompleteselect", addprincipal_onselect);
jQuery("#AddPrincipalForRights-"+<% lc $AddPrincipal |n,j%>).on("autocompletechange", addprincipal_onchange);
});
</script>

<li class="add-principal nav-item">
<a href="#acl-AddPrincipal" class="nav-link" id="principal-tab-acl-AddPrincipal" data-bs-toggle="tab" role="tab" aria-controls="acl-AddPrincipal">
<input placeholder="<&|/l, loc($AddPrincipal) &>Add [_1]</&>" type="text" value="" class="form-control" data-autocomplete="<% lc $AddPrincipal eq 'user' ? 'Users' : 'Groups' %>"
Expand Down
135 changes: 135 additions & 0 deletions share/static/js/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -972,6 +972,141 @@ htmx.onLoad(function(elt) {
});
}

if ( elt.querySelector('.rights-editor') ) {
const editor = elt.querySelector('.rights-editor');
function sync_anchor(hash) {
if (!hash.length) return;
window.location.hash = hash;
editor.querySelector("input[name=Anchor]").value = hash;
}
sync_anchor(editor.querySelector("input[name=Anchor]").value);
jQuery(editor).find('.principal-tabs a[data-bs-toggle="tab"]').on('shown.bs.tab', function (e) {
const anchor = jQuery(this).attr('href').replace('#acl-', '#');
sync_anchor(anchor);
jQuery(editor).find('.category-tabs a[data-bs-toggle="tab"]:visible:first').tab('show');
if (anchor == '#AddPrincipal') {
jQuery(editor).find('li.add-principal input').focus();
}
});

jQuery(editor).find('li.add-principal input').focus(function () {
jQuery(editor).find('.principal-tabs a[data-bs-toggle="tab"][href="#acl-AddPrincipal"]').tab('show');
});

const anchor = editor.querySelector('input[name=Anchor]').value;
if (anchor && jQuery(editor).find('.principal-tabs a[data-bs-toggle="tab"][href="' + anchor.replace('#', '#acl-') + '"]').length) {
jQuery(editor).find('.principal-tabs a[data-bs-toggle="tab"][href="' + anchor.replace('#', '#acl-') + '"]').tab('show');
}
else {
jQuery(editor).find('.principal-tabs a[data-bs-toggle="tab"]:first').tab('show');
}

jQuery(editor).find('.category-tabs a[data-bs-toggle="tab"]').on('shown.bs.tab', function (e) {
createCookie('rights-category-tab', jQuery(this).attr('href'));
});

const category_tab = getCookie('rights-category-tab');
if (category_tab && jQuery(category_tab).length) {
jQuery(editor).find('.category-tabs a[data-bs-toggle="tab"][href="' + category_tab + '"]').tab('show');
}
else {
jQuery(editor).find('.category-tabs a[data-bs-toggle="tab"]:visible:first').tab('show');
};

// "rights" checkbox state cache...
const check_counts = {};

// Before page loads we need to initialize our "rights" checkbox state
// cache.
jQuery(editor).find("div.category-tabs input[type=checkbox]").each(function (index, element) {
// Evaluating each checkbox and its current check state is the same
// as evaluating a check event once the page is loaded. However, we
// must indicate to the process_check_event that we are initializing
// the cache. That is, we musn't decrement values from count
// totals for checkboxes that aren't checked. That only happens when
// a user actually unchecks a box, not when we are initially counting
// checked or unchecked boxes.
process_check_event(element, true);
});

jQuery("div.category-tabs input[type=checkbox]").change(function () {
process_check_event(this, false);
});

// parameters:
// checkbox - DOM checkbox element that was checked
// initializing_cache - a boolean that defines whether or not this
// function was called with the purpose of
// initializing the contents of the check_counts
// cache.
function process_check_event(checkbox, initializing_cache) {
var category_tab = checkbox.getAttribute('data-category-tab');
var principal_tab = checkbox.getAttribute('data-principal-tab');

classify_tab(checkbox.checked, category_tab, initializing_cache);
classify_tab(checkbox.checked, principal_tab, initializing_cache);
}

function classify_tab(checked, tab_id, initializing_cache) {
if (typeof check_counts[tab_id] == 'undefined') {
check_counts[tab_id] = 0;
}

if (checked) {
check_counts[tab_id]++;
if (check_counts[tab_id] == 1) {
// Then this is the first check and we need to add a class
// to the tab.
jQuery('#' + tab_id).addClass("tab-aggregates-checked-rights");
}
}
else if (!initializing_cache) {
check_counts[tab_id]--;
if (check_counts[tab_id] == 0) {
// Then this is the last uncheck and we need to remove a
// class from the tab.
jQuery('#' + tab_id).removeClass("tab-aggregates-checked-rights");
}
}
}

let auto_set_own_dashboards;
jQuery(editor).find('input[value="ModifySelf"]').change(function () {
var form = jQuery(this).closest('form');
if (jQuery(this).is(':checked')) {
if (form.find('input[value$="OwnDashboard"]:visible:not(:checked)').length) {
jQuery('#grant-own-dashboard-rights-modal').modal('show');
}
}
else {
if (auto_set_own_dashboards) {
form.find('input[value$="OwnDashboard"]:visible:checked').prop('checked', false);
auto_set_own_dashboards = false;
}
}
});

jQuery('#grant-own-dashboard-rights-confirm').click(function () {
var form = jQuery(this).closest('form');
form.find('input[value$="OwnSavedSearch"]:visible:not(:checked)').prop('checked', true);
form.find('input[value$="OwnDashboard"]:visible:not(:checked)').prop('checked', true);
jQuery('#grant-own-dashboard-rights-modal').modal('hide');
auto_set_own_dashboards = true;
});

const type = editor.getAttribute('data-add-principal');
if (type) {
jQuery(editor).find("#AddPrincipalForRights-" + type).keyup(function () {
toggle_addprincipal_validity(this, true);
}).keydown(function (event) {
event.stopPropagation() // Disable tabs keyboard nav
});

jQuery("#AddPrincipalForRights-" + type).on("autocompleteselect", addprincipal_onselect);
jQuery("#AddPrincipalForRights-" + type).on("autocompletechange", addprincipal_onchange);
}
}

// Automatically sync to set input values to ones in config files.
jQuery(elt).find('form[name=EditConfig] input[name$="-file"]').change(function (e) {
var file_input = jQuery(this);
Expand Down

0 comments on commit 8c40b04

Please sign in to comment.