From 783087d3ad4acc085c2c5ad1194bddc60fb5473f Mon Sep 17 00:00:00 2001 From: Markus Winter Date: Sat, 18 Nov 2023 02:12:49 +0100 Subject: [PATCH 1/3] use dialogs to add users and groups replace the browser built-in pop-ups with the new dialogs some minor UI fixes for templates --- pom.xml | 6 +- .../assign-roles.properties | 3 +- .../permission-templates.jelly | 5 +- src/main/webapp/js/tableAssign.js | 54 +++++++++--------- src/main/webapp/js/tableTemplates.js | 55 +++++++++---------- 5 files changed, 58 insertions(+), 65 deletions(-) diff --git a/pom.xml b/pom.xml index c6b4e03c..31db7eec 100644 --- a/pom.xml +++ b/pom.xml @@ -50,7 +50,7 @@ 999999-SNAPSHOT - 2.387.3 + 2.426.1 10.12.3 640 @@ -59,8 +59,8 @@ io.jenkins.tools.bom - bom-2.387.x - 2378.v3e03930028f2 + bom-2.426.x + 2571.vede9dc5a_2e23 pom import diff --git a/src/main/resources/com/michelin/cio/hudson/plugins/rolestrategy/RoleStrategyConfig/assign-roles.properties b/src/main/resources/com/michelin/cio/hudson/plugins/rolestrategy/RoleStrategyConfig/assign-roles.properties index b4fd4830..a2d51cec 100644 --- a/src/main/resources/com/michelin/cio/hudson/plugins/rolestrategy/RoleStrategyConfig/assign-roles.properties +++ b/src/main/resources/com/michelin/cio/hudson/plugins/rolestrategy/RoleStrategyConfig/assign-roles.properties @@ -23,9 +23,8 @@ migrate_user=Migrate ambiguous permissions assignment to user {0} migrate_group=Migrate ambiguous permissions assignment to group {0} -promptUser=User name: +promptUser=User ID: userExists=An entry for this user already exists -emptyUser=Please enter a user name promptGroup=Group name: groupExists=An entry for this group already exists diff --git a/src/main/resources/com/michelin/cio/hudson/plugins/rolestrategy/RoleStrategyConfig/permission-templates.jelly b/src/main/resources/com/michelin/cio/hudson/plugins/rolestrategy/RoleStrategyConfig/permission-templates.jelly index e97b5b22..29429ccd 100644 --- a/src/main/resources/com/michelin/cio/hudson/plugins/rolestrategy/RoleStrategyConfig/permission-templates.jelly +++ b/src/main/resources/com/michelin/cio/hudson/plugins/rolestrategy/RoleStrategyConfig/permission-templates.jelly @@ -48,7 +48,7 @@
- +
@@ -73,7 +73,7 @@
-
@@ -210,6 +210,7 @@ + diff --git a/src/main/webapp/js/tableAssign.js b/src/main/webapp/js/tableAssign.js index 75fab5b3..2a689fac 100644 --- a/src/main/webapp/js/tableAssign.js +++ b/src/main/webapp/js/tableAssign.js @@ -113,35 +113,33 @@ addButtonAction = function (e, template, table, tableHighlighter, tableId) { let dataReference = e.target; let type = dataReference.getAttribute('data-type'); let tbody = table.tBodies[0]; - - let name = prompt(dataReference.getAttribute('data-prompt')).trim(); - if (name=="") { - alert(dataReference.getAttribute('data-empty-message')); - return; - } - if (findElementsBySelector(table,"TR").find(function(n){return n.getAttribute("name")=='['+type+':'+name+']';})!=null) { - alert(dataReference.getAttribute('data-error-message')); - return; - } - - let copy = document.importNode(template,true); - copy.removeAttribute("id"); - copy.removeAttribute("style"); - - let children = copy.childNodes; - let tooltipDescription = "Group"; - if (type==="USER") { - tooltipDescription = "User"; - } - children.forEach(function(item){ - item.outerHTML= item.outerHTML.replace(/{{USER}}/g, doubleEscapeHTML(name)).replace(/{{USERGROUP}}/g, tooltipDescription); + + dialog.prompt(dataReference.getAttribute('data-prompt')).then( (name) => { + name = name.trim(); + if (findElementsBySelector(table,"TR").find(function(n){return n.getAttribute("name")=='['+type+':'+name+']';})!=null) { + dialog.alert(dataReference.getAttribute('data-error-message')) + return; + } + + let copy = document.importNode(template,true); + copy.removeAttribute("id"); + copy.removeAttribute("style"); + + let children = copy.childNodes; + let tooltipDescription = "Group"; + if (type==="USER") { + tooltipDescription = "User"; + } + children.forEach(function(item){ + item.outerHTML= item.outerHTML.replace(/{{USER}}/g, doubleEscapeHTML(name)).replace(/{{USERGROUP}}/g, tooltipDescription); + }); + + copy.childNodes[1].innerHTML = escapeHTML(name); + copy.setAttribute("name",'['+type+':'+name+']'); + tbody.appendChild(copy); + Behaviour.applySubtree(table, true); + tableHighlighter.scan(copy); }); - - copy.childNodes[1].innerHTML = escapeHTML(name); - copy.setAttribute("name",'['+type+':'+name+']'); - tbody.appendChild(copy); - Behaviour.applySubtree(table, true); - tableHighlighter.scan(copy); } diff --git a/src/main/webapp/js/tableTemplates.js b/src/main/webapp/js/tableTemplates.js index 813a412e..e0332efe 100644 --- a/src/main/webapp/js/tableTemplates.js +++ b/src/main/webapp/js/tableTemplates.js @@ -96,41 +96,36 @@ Behaviour.specify( addButtonAction = function (e, template, table, tableHighlighter, tableId) { let dataReference = e.target; let tbody = table.tBodies[0]; - let name = prompt(dataReference.getAttribute('data-prompt')); - if (name == null) { - return; - } - name = name.trim(); - if (name == "") { - alert("Please enter a template name"); - return; - } - if (findElementsBySelector(tbody,"TR").find(function(n){return n.getAttribute("name")=='['+name+']';})!=null) { - alert("Entry for '"+name+"' already exists"); - return; - } - let copy = document.importNode(template,true); - let child = copy.childNodes[1]; - child.textContent = escapeHTML(name); + dialog.prompt(dataReference.getAttribute('data-prompt')).then((name) => { + name = name.trim(); + if (findElementsBySelector(tbody,"TR").find(function(n){return n.getAttribute("name")=='['+name+']';})!=null) { + dialog.alert("Entry for '"+name+"' already exists"); + return; + } - let children = copy.getElementsByClassName("permissionInput"); - for (let child of children) { - if (child.hasAttribute('data-tooltip-template')) { - child.setAttribute("data-tooltip-template", child.getAttribute("data-tooltip-template").replace(/{{TEMPLATE}}/g, doubleEscapeHTML(name))); + let copy = document.importNode(template,true); + let child = copy.childNodes[1]; + child.textContent = escapeHTML(name); + + let children = copy.getElementsByClassName("permissionInput"); + for (let child of children) { + if (child.hasAttribute('data-tooltip-template')) { + child.setAttribute("data-tooltip-template", child.getAttribute("data-tooltip-template").replace(/{{TEMPLATE}}/g, doubleEscapeHTML(name))); + } } - } - if (tableId !== "permissionTemplates") { - spanElement = copy.childNodes[2].childNodes[0].childNodes[1]; - } + if (tableId !== "permissionTemplates") { + spanElement = copy.childNodes[2].childNodes[0].childNodes[1]; + } - copy.setAttribute("name",'['+name+']'); - tbody.appendChild(copy); - if (tableHighlighter != null) { - tableHighlighter.scan(copy); - } - Behaviour.applySubtree(findAncestor(copy,"TABLE"), true); + copy.setAttribute("name",'['+name+']'); + tbody.appendChild(copy); + if (tableHighlighter != null) { + tableHighlighter.scan(copy); + } + Behaviour.applySubtree(findAncestor(copy,"TABLE"), true); + }) } From 8fcdf9bfade34f5d59d2a0b462d4a886f101d08d Mon Sep 17 00:00:00 2001 From: Markus Winter Date: Sat, 18 Nov 2023 13:49:18 +0100 Subject: [PATCH 2/3] use modal for matching items/agents --- .../RoleStrategyConfig/index.jelly | 9 --- src/main/webapp/css/role-strategy.css | 55 ------------------- src/main/webapp/js/table.js | 2 +- src/main/webapp/js/tableAssign.js | 10 ++-- src/main/webapp/js/tableManage.js | 53 ++++-------------- src/main/webapp/js/tableTemplates.js | 14 ++--- 6 files changed, 25 insertions(+), 118 deletions(-) diff --git a/src/main/resources/com/michelin/cio/hudson/plugins/rolestrategy/RoleStrategyConfig/index.jelly b/src/main/resources/com/michelin/cio/hudson/plugins/rolestrategy/RoleStrategyConfig/index.jelly index e87a57a4..08c86608 100644 --- a/src/main/resources/com/michelin/cio/hudson/plugins/rolestrategy/RoleStrategyConfig/index.jelly +++ b/src/main/resources/com/michelin/cio/hudson/plugins/rolestrategy/RoleStrategyConfig/index.jelly @@ -242,15 +242,6 @@
-
diff --git a/src/main/webapp/css/role-strategy.css b/src/main/webapp/css/role-strategy.css index a3b4eebc..3dacd818 100644 --- a/src/main/webapp/css/role-strategy.css +++ b/src/main/webapp/css/role-strategy.css @@ -160,58 +160,3 @@ label.attach-previous { display: none; max-width: 500px; } - -.modal { - display: none; - flex-direction: column; - justify-content: center; - gap: 0.4rem; - min-width: 350px; - padding: 1.3rem; - min-height: 150px; - max-height: 400px; - position: fixed; - z-index: 2000; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - background-color: var(--background); - border: 1px solid #ddd; - border-radius: 15px; -} - -.modal .flex { - display: flex; - align-items: center; - justify-content: right; -} - -#modalmessage { - overflow-y: auto; -} - -.overlay { - position: fixed; - top: 0; - bottom: 0; - left: 0; - right: 0; - width: 100%; - height: 100%; - background: rgba(0, 0, 0, 0.5); - backdrop-filter: blur(3px); - z-index: 1999; -} - - -.btn-close { - transform: translate(10px, -10px); - padding: 0.4rem 0.6rem; - background: var(--btn-primary-bg); - border-radius: 50%; - color: var(--btn-text-color); - cursor: pointer; - border: none; - font-weight: 600; - font-family: sans-serif; -} \ No newline at end of file diff --git a/src/main/webapp/js/table.js b/src/main/webapp/js/table.js index db614dfe..75a23afb 100644 --- a/src/main/webapp/js/table.js +++ b/src/main/webapp/js/table.js @@ -59,7 +59,7 @@ class TableHighlighter { highlightRowOnly = e => { let enable = e.type === 'mouseenter'; - let tr = findAncestor(e.target, "TR") + let tr = e.target.closest("TR"); if (enable) { tr.classList.add('highlighted'); } else { diff --git a/src/main/webapp/js/tableAssign.js b/src/main/webapp/js/tableAssign.js index 2a689fac..b2df10f0 100644 --- a/src/main/webapp/js/tableAssign.js +++ b/src/main/webapp/js/tableAssign.js @@ -145,9 +145,9 @@ addButtonAction = function (e, template, table, tableHighlighter, tableId) { Behaviour.specify(".global-matrix-authorization-strategy-table .rsp-remove", 'RoleBasedAuthorizationStrategy', 0, function(e) { e.onclick = function() { - let table = findAncestor(this,"TABLE"); + let table = this.closest("TABLE"); let tableId = table.getAttribute("id"); - let tr = findAncestor(this,"TR"); + let tr = this.closest("TR"); parent = tr.parentNode; parent.removeChild(tr); if (parent.children.length < filterLimit) { @@ -185,7 +185,7 @@ Behaviour.specify(".global-matrix-authorization-strategy-table TR.permission-row */ Behaviour.specify(".global-matrix-authorization-strategy-table TD.stop .migrate", 'RoleBasedAuthorizationStrategy', 0, function(e) { e.onclick = function() { - let tr = findAncestor(this,"TR"); + let tr = this.closest("TR"); let name = tr.getAttribute('name'); let newName = name.replace('[EITHER:', '[USER:'); // migrate_user behavior @@ -193,7 +193,7 @@ Behaviour.specify(".global-matrix-authorization-strategy-table TD.stop .migrate" newName = name.replace('[EITHER:', '[GROUP:'); } - let table = findAncestor(this,"TABLE"); + let table = this.closest("TABLE"); let tableRows = table.getElementsByTagName('tr'); let newNameElement = null; for (let i = 0; i < tableRows.length; i++) { @@ -212,7 +212,7 @@ Behaviour.specify(".global-matrix-authorization-strategy-table TD.stop .migrate" tr.removeAttribute('data-checked'); // remove migration buttons from updated row - let buttonContainer = findAncestor(this, "TD"); + let buttonContainer = this.closest("TD"); let migrateButtons = buttonContainer.getElementsByClassName('migrate'); for (let i = migrateButtons.length - 1; i >= 0; i--) { migrateButtons[i].remove(); diff --git a/src/main/webapp/js/tableManage.js b/src/main/webapp/js/tableManage.js index 7c022ec4..2b468443 100644 --- a/src/main/webapp/js/tableManage.js +++ b/src/main/webapp/js/tableManage.js @@ -32,9 +32,6 @@ var projectTableHighlighter; var newItemRoleTemplate; var agentTableHighlighter; var newAgentRoleTemplate; -var modal; -var overlay; -var closeModalBtn; function filterRows(filter, table) { @@ -107,7 +104,7 @@ endPatternInput = function(span, cancel) { let div = span.childNodes[0]; let input = span.childNodes[1]; let pattern = input.value; - let table = findAncestor(span, "TABLE"); + let table = span.closest("TABLE"); input.type = "hidden"; div.style.display = "block"; span.setAttribute("data-edit", "false"); @@ -116,7 +113,7 @@ endPatternInput = function(span, cancel) { } else { div.setAttribute("data-pattern", pattern); div.textContent = '"' + pattern + '"' - let row = findAncestor(span, "TR"); + let row = span.closest("TR"); for (td of row.getElementsByClassName('permissionInput')) { updateTooltip(row, td, pattern); } @@ -257,15 +254,15 @@ addButtonAction = function(e, templateId, table, tableHighlighter, tableId) { } tbody.appendChild(copy); tableHighlighter.scan(copy); - Behaviour.applySubtree(findAncestor(copy, "TABLE"), true); + Behaviour.applySubtree(copy.closest("TABLE"), true); } Behaviour.specify(".global-matrix-authorization-strategy-table .rsp-remove", 'RoleBasedAuthorizationStrategy', 0, function(e) { e.onclick = function() { - let table = findAncestor(this, "TABLE"); + let table = this.closest("TABLE"); let tableId = table.getAttribute("id"); - let tr = findAncestor(this, "TR"); + let tr = this.closest("TR"); parent = tr.parentNode; parent.removeChild(tr); if (parent.children.length < filterLimit) { @@ -290,12 +287,12 @@ Behaviour.specify(".global-matrix-authorization-strategy-table .rsp-remove", 'Ro }); Behaviour.specify(".global-matrix-authorization-strategy-table td.permissionInput input", 'RoleBasedAuthorizationStrategy', 0, function(e) { - let row = findAncestor(e, "TR"); + let row = e.closest("TR"); let pattern = getPattern(row); - let td = findAncestor(e, "TD"); + let td = e.closest("TD"); updateTooltip(row, td, pattern); e.onchange = function() { - Behaviour.applySubtree(findAncestor(row, "TABLE"), true); + Behaviour.applySubtree(row.closest("TABLE"), true); return true; }; }); @@ -346,7 +343,7 @@ showItemsModal = function(items, itemCount, maxItems, pattern) { } showErrorMessageModal = function() { - alert('Unable to fetch matching Jobs.'); + dialog.alert('Unable to fetch matching Jobs.'); } bindListenerToPattern = function(elem) { @@ -398,34 +395,23 @@ showAgentsModal = function(agents, agentCount, maxAgents, pattern) { } showModal = function(title, itemlist) { - titleElement=document.getElementById("modaltitle"); - titleElement.textContent = title; - - messageElement=document.getElementById("modalmessage"); - messageElement.textContent = ""; + messageElement=document.createElement("div"); for (let item of itemlist) { line = document.createTextNode("- " + item); messageElement.appendChild(line); messageElement.appendChild(document.createElement("br")); } - - modal.style.display="flex"; - overlay.classList.remove("default-hidden"); + dialog.modal(messageElement, {title: title}); } showAgentErrorMessageModal = function() { - alert('Unable to fetch matching Agents.'); + dialogalert('Unable to fetch matching Agents.'); } bindAgentListenerToPattern = function(elem) { elem.addEventListener('click', showMatchingAgents); } -closeModal = function () { - modal.style.display="none"; - overlay.classList.add("default-hidden"); -}; - document.addEventListener('DOMContentLoaded', function() { // global roles initialization let globalRoleInputFilter = document.getElementById('globalRoleInputFilter'); @@ -463,19 +449,4 @@ document.addEventListener('DOMContentLoaded', function() { for (let pattern of agentPatterns) { bindAgentListenerToPattern(pattern); } - - // - modal = document.querySelector(".modal"); - - overlay = document.querySelector(".overlay"); - overlay.addEventListener("click", closeModal); - - closeModalBtn = document.querySelector(".btn-close"); - closeModalBtn.addEventListener("click", closeModal); - - document.addEventListener("keydown", function (e) { - if (e.key === "Escape" && !modal.classList.contains("hidden")) { - closeModal(); - } - }); }); \ No newline at end of file diff --git a/src/main/webapp/js/tableTemplates.js b/src/main/webapp/js/tableTemplates.js index e0332efe..e4dcfebb 100644 --- a/src/main/webapp/js/tableTemplates.js +++ b/src/main/webapp/js/tableTemplates.js @@ -124,7 +124,7 @@ addButtonAction = function (e, template, table, tableHighlighter, tableId) { if (tableHighlighter != null) { tableHighlighter.scan(copy); } - Behaviour.applySubtree(findAncestor(copy,"TABLE"), true); + Behaviour.applySubtree(copy.closest("TABLE"), true); }) } @@ -136,9 +136,9 @@ Behaviour.specify(".global-matrix-authorization-strategy-table .rsp-remove", 'Ro console.log("Not confirmed"); return; } - let table = findAncestor(this,"TABLE"); + let table = this.closest("TABLE"); let tableId = table.getAttribute("id"); - let tr = findAncestor(this,"TR"); + let tr = this.closest("TR"); parent = tr.parentNode; parent.removeChild(tr); if (parent.children.length < filterLimit) { @@ -161,16 +161,16 @@ Behaviour.specify(".global-matrix-authorization-strategy-table .rsp-remove", 'Ro }); Behaviour.specify(".global-matrix-authorization-strategy-table td.permissionInput input", 'RoleBasedAuthorizationStrategy', 0, function(e) { - let table = findAncestor(e, "TABLE"); + let table = e.closest("TABLE"); if (table.hasClassName('read-only')) { // if this is a read-only UI (ExtendedRead / SystemRead), do not enable checkboxes return; } - let row = findAncestor(e,"TR"); - let td = findAncestor(e,"TD"); + let row = e.closest("TR"); + let td = e.closest("TD"); updateTooltip(row, td); e.onchange = function() { - Behaviour.applySubtree(findAncestor(row,"TABLE"),true); + Behaviour.applySubtree(row.closest("TABLE"),true); return true; }; }); From 21b2f4b7f69b1497e44b6dd84b682ed6b27bd8d6 Mon Sep 17 00:00:00 2001 From: Markus Winter Date: Tue, 27 Feb 2024 19:30:07 +0100 Subject: [PATCH 3/3] update jenkins version and bom --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 31db7eec..ed34eeca 100644 --- a/pom.xml +++ b/pom.xml @@ -50,7 +50,7 @@ 999999-SNAPSHOT - 2.426.1 + 2.426.3 10.12.3 640 @@ -60,7 +60,7 @@ io.jenkins.tools.bom bom-2.426.x - 2571.vede9dc5a_2e23 + 2839.v003b_4d9d24fd pom import