c0cf2115dd
Goal: make the admin delete dialog show its dependency warning on
the FIRST click (matching the existing Groups UX), instead of
needing a 409 round-trip from the DELETE endpoint to populate the
warning.
Changes:
- lib/api-spec/openapi.yaml: added optional count fields to App
(groupCount, restrictionCount, openCount), Service (orderCount),
and UserProfile (noteCount, orderCount, conversationCount,
messageCount).
- artifacts/api-server/src/routes/apps.ts: GET /admin/apps now
batch-loads groupCount/restrictionCount/openCount via grouped
COUNT queries on group_apps, app_permissions, and app_opens.
- artifacts/api-server/src/routes/services.ts: GET /services now
batch-loads orderCount from service_orders.
- artifacts/api-server/src/routes/users.ts: GET /users now batch-
loads noteCount/orderCount/conversationCount/messageCount from
notes, service_orders, conversations.created_by, and
messages.sender_id.
- artifacts/tx-os/src/pages/admin.tsx: Apps, Services, and Users
delete buttons pre-populate their conflict-state from the row's
count fields so the DeletionWarningDialog shows the warning on
the first click. The lazy 409 fallback still works as a safety
net for any caller without counts.
- replit.md: documented the new admin-panel delete UX.
Tests:
- Added artifacts/api-server/tests/list-dependency-counts.test.mjs
with 6 tests verifying each list endpoint exposes the new count
fields with the expected non-zero values when dependents exist
AND zero values when they do not (apps, services, users).
- Existing artifacts/api-server/tests/delete-force-warnings.test.mjs
(9 tests) still passes — DELETE behavior unchanged.
- Verified end-to-end with a Playwright browser test: clicking the
service delete icon ONCE opens the confirmation modal with the
dependency warning ("orders", count >= 1) immediately.
Notes / drift:
- Count fields were added to the shared App/Service/UserProfile
schemas (not list-only sub-schemas) so the same shape is returned
from list and detail endpoints. Code review flagged this as
acceptable but broader than strictly necessary; left as is to
keep the API consistent.
Out of scope (already pre-existing on main, tracked as follow-ups):
- artifacts/api-server/tests/apps-open.test.mjs has a syntax error.
- artifacts/api-server/tests/app-permissions-unique.test.mjs has
two failing assertions about the composite primary key.
- artifacts/api-server/src/routes/executive-meetings.ts has 3 pre-
existing typecheck errors around the font-settings scope column.
- The `test` workflow exits with ECONNREFUSED when the api-server
isn't already up — needs a readiness check.
Replit-Task-Id: bd14fe73-9961-431b-ab5a-ab70f116e8c7