Task #609: Per-user app enable/disable in Settings

- New `user_hidden_apps` table (userId+appId composite PK, cascade) in
  lib/db/src/schema/user-hidden-apps.ts; registered in schema index;
  pushed to dev DB via drizzle-kit.
- Backend (artifacts/api-server/src/routes/apps.ts):
  - GET /me/apps — returns every globally-active app visible to the
    user with a `hidden` flag.
  - PUT /me/apps/:appId/hidden — toggles a row in user_hidden_apps,
    gated by getVisibleAppsForUser + isActive so a user can't toggle
    apps they can't reach.
  - GET /apps (Home/Dock) now uses getVisibleNonHiddenAppsForUser so
    hidden apps disappear immediately.
- lib/appsVisibility.ts: added getHiddenAppIdsForUser and
  getVisibleNonHiddenAppsForUser helpers.
- OpenAPI: added /me/apps + /me/apps/{appId}/hidden, MyApp and
  UpdateMyAppHiddenBody schemas; regenerated api-zod + api-client-react.
- Frontend (settings-panel.tsx): added "My apps" accordion section as
  first GroupItem with MyAppsBody — Switch per app, optimistic update,
  invalidates getListMyAppsQueryKey + getListAppsQueryKey so Home/Dock
  refresh without reload.
- Translations: added settingsPanel.section.myApps + settingsPanel.myApps
  in ar.json + en.json.
- Code review fix: /me/apps and PUT gating filter isActive even for
  admins, so inactive apps don't appear in the Settings list.
- Proposed follow-up #611 (Playwright test that hidden apps disappear
  from Home and Dock).
This commit is contained in:
Riyadh
2026-05-19 11:06:21 +00:00
parent e3dc60b24b
commit d7d8ab3a2a
11 changed files with 637 additions and 3 deletions
+75
View File
@@ -633,6 +633,64 @@ paths:
schema:
$ref: "#/components/schemas/ErrorResponse"
/me/apps:
get:
operationId: listMyApps
tags: [apps]
summary: List apps for the current user with their per-user hidden state
description: |
Returns every globally active app (regardless of the per-user hidden
flag), each with a `hidden` boolean indicating whether the current
user has hidden it from their own Home/Dock via PUT /me/apps/{appId}/hidden.
Used by the per-user Settings panel; the Home and Dock continue to use
GET /apps which already filters out hidden apps server-side.
responses:
"200":
description: Apps visible to the current user, with per-user hidden state
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/MyApp"
/me/apps/{appId}/hidden:
put:
operationId: updateMyAppHidden
tags: [apps]
summary: Hide or show an app for the current user
parameters:
- name: appId
in: path
required: true
schema:
type: integer
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/UpdateMyAppHiddenBody"
responses:
"200":
description: Updated per-user app state
content:
application/json:
schema:
$ref: "#/components/schemas/MyApp"
"400":
description: Validation error
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: App not found or not visible to the current user
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
# Settings
/settings:
get:
@@ -4231,6 +4289,23 @@ components:
type: string
format: date-time
MyApp:
allOf:
- $ref: "#/components/schemas/App"
- type: object
required: [hidden]
properties:
hidden:
type: boolean
description: True when the current user has hidden this app from their Home/Dock.
UpdateMyAppHiddenBody:
type: object
required: [hidden]
properties:
hidden:
type: boolean
UpdateMyAppOrderBody:
type: object
required: [order]