Repository navigation
Task Issue 963 issuetracker Link Count Delete Gating
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)
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.
- 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/issuetrackerreturned both items WITHOUTlink_count. - Clicking trash on Bugzilla 963 → confirm →
DELETE /1→ HTTP 400Failure - 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.
BFF api/issuetracker/index.php:
-
trackerToJSON()exposeslink_count(int) andlinks(list of linked test-project names, viagetLinkSet(), so the UI can tell linked from free).
HTML gui/templates/issuetracker/issuetrackerView.html:
- Linked tracker (
link_count>0): toolbardeleteaction renders disabled (greyedcursor:not-allowed, noonclick), 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.
-
Linked tracker (Bugzilla 963): delete action greyed
disabled(cursor:not-allowed), noonclick; 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_viewrights only): the actions column and all delete/edit icons are hidden; table still renders. Matches legacyissueTrackerView.tplwhich gates the actions toolset oncanManage.
Modern row with a linked tracker — delete action disabled with linking-project tooltip:

Suite in docs/TLU_Test_Cases.md → "Suite 963", 6/6 PASS.
api/issuetracker/index.phpgui/templates/issuetracker/issuetrackerView.html-
gui/templates/i18n/*.json(10 bundles) -
docs/Task-Issue-963-issuetracker-Link-Count-Delete-Gating.md(this mirror)