diff --git a/CHANGELOG.md b/CHANGELOG.md index e11f198980578968df7259845f21b8188ac631e0..4c27eecf2bb022a6cd0f4ea0fbebe874ce797bc8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added ### +* `navbar.hideElementforRoles` function that hides a given element for certain + roles. + ### Changed ### ### Deprecated ### diff --git a/src/core/js/webcaosdb.js b/src/core/js/webcaosdb.js index 1d6d5c8326d3f7dc0f311404f825206c9303462f..b622a1c879f3cf8aa53378e32f0a15f666ea7689 100644 --- a/src/core/js/webcaosdb.js +++ b/src/core/js/webcaosdb.js @@ -41,10 +41,10 @@ var globalError = function (error) { // ignore this particular error. It is caused by bootstrap-select which is // probably misusing the bootstrap 5 API. if (error.toString().startsWith("TypeError: this._element is undefined")) { - if (error && error.stack) - stack = "" + error.stack; + if (error && error.stack) + stack = "" + error.stack; if (stack.indexOf("dataApiKeydownHandler") > 0) { - return; + return; } } @@ -306,6 +306,27 @@ this.navbar = new function () { } } + /** + * Hide the given element for certain roles + * + * @param {string|object} element - The HTML element to hide. May be either + * a string to be used in a jquery, or the result of a jquery. + * @param {array} roles - List of roles for which the given element is + * hidden. + */ + this.hideElementForRoles = function (element, roles) { + var elt = element; + if (typeof (element) === "string") { + elt = $(elt); + } + const userRoles = getUserRoles(); + if (userRoles.some(role => roles.includes(role))) { + elt.addClass("d-none"); + } else { + elt.removeClass("d-none"); + } + } + } diff --git a/test/core/js/modules/webcaosdb.js.js b/test/core/js/modules/webcaosdb.js.js index 534dc86c485ccfac184bb05bac17d595addaa3d6..b43af58d4fef57aafd7d5d46998fc1a13725e868 100644 --- a/test/core/js/modules/webcaosdb.js.js +++ b/test/core/js/modules/webcaosdb.js.js @@ -1212,7 +1212,7 @@ QUnit.test("bindOnClick", function (assert) { $("body").append(form); $(form).append(submitButton); submitButton.click(); - assert.equal(storage(), `FIND RECORD WHICH HAS A PROPERTY LIKE '*with double*' AND A PROPERTY LIKE '*and single*' AND A PROPERTY LIKE '*what\\'s wrong?*' AND A PROPERTY LIKE '*\\'*' AND A PROPERTY LIKE '*nothin\\'*' AND A PROPERTY LIKE '*"\\'bla*'`, "after5: stuff with quotation marks"); + assert.equal(storage(), `FIND RECORD WHICH HAS A PROPERTY LIKE '*with double*' AND A PROPERTY LIKE '*and single*' AND A PROPERTY LIKE '*what\\'s wrong?*' AND A PROPERTY LIKE '*\\'*' AND A PROPERTY LIKE '*nothin\\'*' AND A PROPERTY LIKE '*"\\'bla*'`, "after5: stuff with quotation marks"); // ... then with empty quotation marks. this will not trigger the query execution at all storage("not triggered"); @@ -1228,16 +1228,17 @@ QUnit.test("bindOnClick", function (assert) { QUnit.test("splitSearchTerms", function (assert) { assert.ok(queryForm.splitSearchTerms, "available"); const cases = [ - ["", []], - ['"', ['"']], - ["a", ["a"]], - ["a b", ["a", "b"]], - ["'a b'", ["a b"]], - ['"a b"', ["a b"]], - [`"with double" 'and single' "what's wrong?" ' "nothin'" "'bla`, - ["with double", "and single", "what's wrong?", "'", "nothin'", `"'bla`]], + ["", []], + ['"', ['"']], + ["a", ["a"]], + ["a b", ["a", "b"]], + ["'a b'", ["a b"]], + ['"a b"', ["a b"]], + [`"with double" 'and single' "what's wrong?" ' "nothin'" "'bla`, + ["with double", "and single", "what's wrong?", "'", "nothin'", `"'bla`] + ], ]; - for(let testCase of cases) { + for (let testCase of cases) { assert.deepEqual(queryForm.splitSearchTerms(testCase[0]), testCase[1], `test case ${testCase[0]}`); } }); @@ -1245,7 +1246,7 @@ QUnit.test("splitSearchTerms", function (assert) { QUnit.test("initFreeSearch", function (assert) { const form = $('<form></form>'); const inputGroup = $('<div class="input-group"></div>'); - const textArea = $( '<textarea class="caosdb-f-query-textarea" name="query"></textarea>'); + const textArea = $('<textarea class="caosdb-f-query-textarea" name="query"></textarea>'); const submitButton = $('<input class="caosdb-search-btn" type="submit">'); inputGroup.append(textArea); form.append(inputGroup).append(submitButton); @@ -1885,6 +1886,35 @@ QUnit.test("toolbox example", function (assert) { assert.equal($('.caosdb-f-navbar-toolbox[data-toolbox-name="Tools"] button').length, 3, "three 'Tools' buttons"); }); +QUnit.test("hide elements for roles", function (assert) { + navbar.add_button("TestButton1"); + navbar.add_button("TestButton2"); + + // mock user role + $("#top-navbar").append(`<div class="caosdb-user-role">someRole</div>`); + navbar.hideElementForRoles($("button:contains('TestButton1')"), ["someOtherRole"]); + navbar.hideElementForRoles("button:contains('TestButton2')", ["someOtherRole"]); + // I don't have the role, so nothing is hidden: + assert.notOk($("button:contains('TestButton1')").hasClass("d-none")); + assert.notOk($("button:contains('TestButton2')").hasClass("d-none")); + + // Add second role + $("#top-navbar").append(`<div class="caosdb-user-role second-role">someOtherRole</div>`); + // now I do + navbar.hideElementForRoles($("button:contains('TestButton1')"), ["someOtherRole"]); + navbar.hideElementForRoles("button:contains('TestButton2')", ["someOtherRole"]); + assert.ok($("button:contains('TestButton1')").hasClass("d-none")); + assert.ok($("button:contains('TestButton2')").hasClass("d-none")); + + // Remove second role again + $(".second-role").remove(); + // now I don't any more + navbar.hideElementForRoles($("button:contains('TestButton1')"), ["someOtherRole"]); + navbar.hideElementForRoles("button:contains('TestButton2')", ["someOtherRole"]); + assert.notOk($("button:contains('TestButton1')").hasClass("d-none")); + assert.notOk($("button:contains('TestButton2')").hasClass("d-none")); +}); + QUnit.module("webcaosdb.js - version_history", { before: function (assert) { connection._init();