Skip to content

Task Issue 963 issuetracker Link Count Delete Gating

TestLink Upgraded CI edited this page Sep 24, 2026 · 1 revision

Task 963 — Restore link-count delete gating for linked trackers in the Issue Trackers screen (gap vs legacy)

Issue: #963 Status: IMPLEMENTED & VERIFIED (2026-09-24)

The gap

Legacy issueTrackerView.tpl:78-83 renders the per-row delete icon ONLY when the row is NOT linked to any test project:

{if $gui->canManage != "" && $item_def.link_count == 0}
  <i ... onclick="delete_confirmation({$item_def.id},...);"></i>
{/if}

link_count is filled by tlIssueTracker::getAll() (output=add_link_count, lib/functions/tlIssueTracker.class.php:591-623) with a COUNT(0) GROUP BY id over testproject_issuetracker. Deleting a linked tracker is additionally double-guarded in the model (tlIssueTracker::delete(), tlIssueTracker.class.php:291-335) with Failure - id %s is linked to: testproject '%s' with id %s.

The modern screen dropped this UI gate: the BFF requested getAll(output=add_link_count) but trackerToJSON() silently dropped link_count, and the HTML always rendered an active trash button on every row. So a linked tracker kept a live delete button that ALWAYS failed with the model's linked-message guard (HTTP 400) — worse than legacy, which hid it.

Investigation (measured)

  • admin/admin against a fresh import: tracker Bugzilla 963 is linked to test project TC963-prj (link_count=1); tracker Free 963 is unlinked (link_count=0).
  • GET /api/issuetracker returned both items WITHOUT link_count.
  • Clicking trash on Bugzilla 963 → confirm → DELETE /1 → HTTP 400 Failure - id 1 is linked to: testproject 'TC963-prj' with id 1 — record NOT removed.
  • Clicking trash on Free 963 → confirm → delete → record IS removed (SELECT confirms the row is gone).
  • Legacy hides the icon entirely for linked trackers; modern showed an always failing button.

Fix

BFF api/issuetracker/index.php:

  • trackerToJSON() exposes link_count (int) and links (list of linked test-project names, via getLinkSet(), so the UI can tell linked from free).

HTML gui/templates/issuetracker/issuetrackerView.html:

  • Linked tracker (link_count>0): toolbar delete action renders disabled (greyed cursor:not-allowed, no onclick), with a localized tooltip listing the linking test projects.
  • Unlinked tracker: active delete action (with confirm dialog) as before.

i18n — new key it.msg.cannotDeleteLinked in all 10 locale bundles (gui/templates/i18n/{en,de,es,fr,it,ja,pt,ro,ru,zh}.json), e.g. Romanian "Nu se poate șterge – încă legat de proiecte de test". All bundles validated with python3 -m json.tool.

Verification (browser, admin + view-only user)

  • Linked tracker (Bugzilla 963): delete action greyed disabled (cursor:not-allowed), no onclick; clicking triggers NO confirm; record stays in DB. Matches legacy (which hides the icon entirely when link_count>0).
  • Unlinked tracker (Free 963): delete action active; confirm → accept → row removed and gone from DB; confirm → dismiss → row kept.
  • View-only user (issuetracker_view rights only): the actions column and all delete/edit icons are hidden; table still renders. Matches legacy issueTrackerView.tpl which gates the actions toolset on canManage.

Screenshots

Modern row with a linked tracker — delete action disabled with linking-project tooltip:

Linked tracker delete gated, unlinked tracker deletable

Test cases

Suite in docs/TLU_Test_Cases.md → "Suite 963", 6/6 PASS.

Files

  • api/issuetracker/index.php
  • gui/templates/issuetracker/issuetrackerView.html
  • gui/templates/i18n/*.json (10 bundles)
  • docs/Task-Issue-963-issuetracker-Link-Count-Delete-Gating.md (this mirror)

Clone this wiki locally