Task Issue 1609 Assign Project Roles Access Type Indicator - sebiboga/testlink-upgraded GitHub Wiki

Task 1609 — public/private access-type indicator on Assign Test Project Roles (gap vs legacy)

Issue: #1609 Status: IMPLEMENTED & VERIFIED — branch task/issue-1609 (the issue is closed by the same run, after the branch was pushed) Related: #1643 (the identical indicator on the plan twin usersAssignPlan.html — landed there, this issue closed the project side), #1612, #1613, #1620, #1621, #930

After the fix — amber lock next to the Test Project label, private project Before the fix — bare Test Project label

The gap

Legacy rendered an access-type icon right next to the Test Project label:

{* gui/templates/dashio/usermanagement/usersAssign.tpl:159-162 *}
<td class="labelHolder" style="{$styleLH}">{$labels.TestProject}{$gui->accessTypeImg}</td>

lib/usermanagement/usersAssign.php:117-135 (deleted under #947, readable at ab387af72^) built $gui->accessTypeImg with three states:

state when icon (tlsmarty.inc.php:379,451) tooltip
public selected id ∈ assignable set and is_public fa-globe lang_get('access_public')
private selected id ∈ assignable set and !is_public fa-lock lang_get('access_private')
vorsicht set is non-empty but the selected id is not in it (legacy kept the requested featureID regardless — usersAssign.php:307-315) fa-exclamation-triangle lang_get('access_vorsicht')
(none) assignable set is empty — $gui->accessTypeImg stayed '' — —

The assignable set is $gui->features from getTestProjectEffectiveRoles() (usersAssign.php:285-305) — only projects whose caller's effective role may assign roles.

2.0.1 rendered <label data-i18n="assign.testProject">Test Project:</label> immediately followed by <select id="projectSelect">: no indicator element at all, and the strings access/isPublic appeared nowhere in usersAssignProject.html. The BFF already read testprojects.is_public (api/roles/index.php:770-779) and returned it as isPublic, but only for the effective-role computation — the UI dropped it.

Why it matters: on a private project every non-admin collapses to <no rights> (getTprojectEffectiveRoleMap(), api/roles/index.php:215-232). A manager overwriting role assignments could not tell which of the two semantics applied.

What was restored

BFF — api/roles/index.php

  • getAssignableProjects() now emits per-option isPublic (the map_of_map_full projection already selects TPROJ.*, testproject.class.php:561) → the indicator follows the combo with no extra round-trip.

  • GET /meta/tproject-roles returns a resolved tri-state accessType: 1 public / 0 private / -1 vorsicht / null = nothing selected or the set is empty. Purely additive — isPublic and every other field are untouched.

    The resolution deliberately stays server-side: isPublic alone is read through get_by_id(), so a requested-but-not-assignable project would be reported public/private where legacy showed vorsicht.

Screen — gui/templates/usermanagement/usersAssignProject.html

  • .access-icon CSS states — teal #4ECDC4 globe / amber #f0ad4e lock / red #e6605e triangle, the same block as the plan screen (#1643) so both screens match.
  • <span id="projectAccessIcon"> between the label and the combo, exactly where legacy put it.
  • renderAccessIcon(isPublic) maps the tri-state to icon + title/aria-label tooltip.

Wiring — five points

site behaviour
loadProjects() entry clears icon + access map synchronously, before the request leaves
loadProjects() .done rebuilds the map from the combo payload, paints right after sel.val(pid)
#projectSelect change repaints synchronously (globe/lock flips before the XHR leaves); cleared on the placeholder
loadUsers() .done repaints from the authoritative server-resolved accessType
showSessionExpired() / showDisabled() / showNoAccess() renderAccessIcon(null) — legacy rendered no icon without an assignable context

i18n

No new keys needed — assign.accessPublic / assign.accessPrivate / assign.accessVorsicht already ship in all 10 bundles (de en es fr it ja pt ro ru zh) from #1643, worded identically to legacy $TLS_access_public / $TLS_access_private (locale/*/strings.txt: "Public" / "Private - User need specific role assignment"). A locale switch re-navigates (gui/templates/i18n/i18n.js:249-253), so the tooltip re-renders in the new language too.

Verification

  • Browser (chrome-devtools MCP, admin): private lock + private tooltip, public globe, synchronous flip on combo change (2→1→2), cleared combo, vorsicht for an out-of-set id, showSessionExpired(), deep link without tproject_id (session-project precedence #1613), ro locale tooltip → 10/10 PASS (suite in tmp/TLU_Test_Cases.md).
  • tmp/verify_1609.sh — 14/14 PASS (BFF tri-state, additive payload, per-project isPublic, markup/CSS/helper/wiring, all-10-bundle key presence, legacy wording).
  • php -l api/roles/index.php clean, node --check on the extracted inline script clean, 0 console errors, Event Viewer: 3 rows after the run, all log_level=16 LOGIN audit — 0 ERROR, 0 WARNING.
  • Docs mirror: docs/Assign_Test_Project_Roles-1609.md; CHANGELOG entry under ## 2.0.1 (in-progress) → Gap closed — Assign Test Project Roles … (Fixes #1609).
⚠️ **GitHub.com Fallback** ⚠️