Hermes 284313f908
Some checks are pending
Bidi Control Character Guard / bidi-control-guard (push) Waiting to run
Circular Dependency Check / Check for new circular dependencies (push) Waiting to run
Citus Migration Smoke / Combined migrations on single-node Citus (push) Waiting to run
E2E Fresh Install Tests / fresh-install-e2e (push) Waiting to run
ext-v2 guardrails / Run ext-v2 guard and ESLint (push) Waiting to run
Integration Tests / Check for relevant changes (push) Waiting to run
Integration Tests / ${{ (github.event_name == 'schedule' || github.event.inputs.suite == 'full') && 'Full integration suite' || 'Tier-1 integration subset' }} (push) Blocked by required conditions
Mobile checks / Mobile lint + typecheck (push) Waiting to run
Mobile checks / Mobile unit tests (push) Waiting to run
Mobile checks / Mobile dependency audit (report) (push) Waiting to run
Mobile checks / Mobile reproducibility checks (push) Waiting to run
Secrets guard (env backups) / Ensure no tracked env backup files (push) Waiting to run
Temporal Readiness / fast-readiness (push) Waiting to run
Temporal Readiness / docker-parity (push) Waiting to run
TypeScript Type Check / Nx affected typecheck (push) Waiting to run
Unit Tests / Skipped-test budget (push) Waiting to run
Unit Tests / Nx affected unit tests (push) Waiting to run
Unit Tests / Server unit coverage (informational) (push) Waiting to run
Validate Tenant Management Schema / Check for relevant changes (push) Waiting to run
Validate Tenant Management Schema / Validate Tenant Management Schema (push) Blocked by required conditions
EE Workflows Build Guard / ee-workflows-build-guard (push) Waiting to run
Initial import of AlgaPSA codebase from PSA server
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz

Source: /opt/alga-psa on psa.joliet.tech
2026-06-22 16:12:17 -05:00

545 lines
12 KiB
JSON

[
{
"id": "T082",
"description": "Migration adds 'team' to document_associations entity_type CHECK constraint without error",
"implemented": true,
"featureIds": [
"F051"
]
},
{
"id": "T083",
"description": "Migration uses `exports.config = { transaction: false }` for Citus compliance",
"implemented": true,
"featureIds": [
"F051"
]
},
{
"id": "T084",
"description": "Migration down restores original constraint without 'team'",
"implemented": true,
"featureIds": [
"F051"
]
},
{
"id": "T085",
"description": "EntityType in media avatarUtils includes 'team'",
"implemented": true,
"featureIds": [
"F052"
]
},
{
"id": "T086",
"description": "EntityType in users avatarUtils includes 'team'",
"implemented": true,
"featureIds": [
"F053"
]
},
{
"id": "T087",
"description": "EntityType in formatting avatarUtils includes 'team'",
"implemented": true,
"featureIds": [
"F054"
]
},
{
"id": "T088",
"description": "EntityType in EntityImageUpload includes 'team'",
"implemented": true,
"featureIds": [
"F055"
]
},
{
"id": "T089",
"description": "`getTeamAvatarUrl()` calls `getEntityImageUrl('team', ...)` and returns URL or null",
"implemented": true,
"featureIds": [
"F056"
]
},
{
"id": "T090",
"description": "TeamAvatar component renders EntityAvatar with correct props (entityId=teamId, entityName=teamName)",
"implemented": true,
"featureIds": [
"F057"
]
},
{
"id": "T091",
"description": "TeamAvatar shows colored initials when avatarUrl is null",
"implemented": true,
"featureIds": [
"F057"
]
},
{
"id": "T092",
"description": "TeamAvatar shows uploaded image when avatarUrl is provided",
"implemented": true,
"featureIds": [
"F057"
]
},
{
"id": "T093",
"description": "`uploadTeamAvatar` action stores file via `uploadEntityImage('team', ...)` and returns avatarUrl",
"implemented": true,
"featureIds": [
"F058"
]
},
{
"id": "T094",
"description": "`uploadTeamAvatar` rejects when team not found",
"implemented": true,
"featureIds": [
"F058"
]
},
{
"id": "T095",
"description": "`uploadTeamAvatar` rejects when no file provided",
"implemented": true,
"featureIds": [
"F058"
]
},
{
"id": "T096",
"description": "`deleteTeamAvatar` action deletes via `deleteEntityImage('team', ...)`",
"implemented": true,
"featureIds": [
"F059"
]
},
{
"id": "T097",
"description": "`deleteTeamAvatar` rejects when team not found",
"implemented": true,
"featureIds": [
"F059"
]
},
{
"id": "T098",
"description": "`getTeamAvatarUrlAction` returns URL string for existing team avatar",
"implemented": true,
"featureIds": [
"F060"
]
},
{
"id": "T099",
"description": "`getTeamAvatarUrlAction` returns null when no avatar exists",
"implemented": true,
"featureIds": [
"F060"
]
},
{
"id": "T100",
"description": "`getTeamAvatarUrlsBatchAction` returns Map with URLs for multiple teams",
"implemented": true,
"featureIds": [
"F061"
]
},
{
"id": "T101",
"description": "Avatar actions are exported from teams package actions barrel",
"implemented": true,
"featureIds": [
"F062"
]
},
{
"id": "T102",
"description": "Teams package.json includes @alga-psa/media, @alga-psa/auth, and swr dependencies",
"implemented": true,
"featureIds": [
"F063"
]
},
{
"id": "T103",
"description": "`useTeamAvatar` hook returns `{ avatarUrl, refreshAvatar, isLoading }` via SWR",
"implemented": true,
"featureIds": [
"F064"
]
},
{
"id": "T104",
"description": "`useTeamAvatar` returns null avatarUrl when teamId is undefined",
"implemented": true,
"featureIds": [
"F064"
]
},
{
"id": "T105",
"description": "`invalidateTeamAvatar` triggers SWR cache invalidation",
"implemented": true,
"featureIds": [
"F064"
]
},
{
"id": "T106",
"description": "`useTeamAvatar` is exported from teams hooks barrel",
"implemented": true,
"featureIds": [
"F065"
]
},
{
"id": "T107",
"description": "TeamDetails shows avatar upload area above team name field",
"implemented": true,
"featureIds": [
"F066"
]
},
{
"id": "T108",
"description": "TeamDetails avatar upload successfully uploads an image and displays it",
"implemented": true,
"featureIds": [
"F066",
"F067"
]
},
{
"id": "T109",
"description": "TeamDetails avatar updates after successful upload without page reload",
"implemented": true,
"featureIds": [
"F067"
]
},
{
"id": "T110",
"description": "OrgChartNode renders UserAvatar, user name, and role text",
"implemented": true,
"featureIds": [
"F068"
]
},
{
"id": "T111",
"description": "OrgChartNode shows inactive badge for inactive users",
"implemented": true,
"featureIds": [
"F068"
]
},
{
"id": "T112",
"description": "OrgChartNode has top (target) and bottom (source) ReactFlow handles",
"implemented": true,
"featureIds": [
"F068"
]
},
{
"id": "T113",
"description": "OrgChart component renders inside ReactFlowProvider without SSR errors",
"implemented": true,
"featureIds": [
"F069",
"F075"
]
},
{
"id": "T114",
"description": "OrgChart builds tree from users with `reports_to` relationships",
"implemented": true,
"featureIds": [
"F070"
]
},
{
"id": "T115",
"description": "OrgChart places root nodes (reports_to=null) at top level",
"implemented": true,
"featureIds": [
"F070"
]
},
{
"id": "T116",
"description": "OrgChart positions child nodes below their parent with appropriate spacing",
"implemented": true,
"featureIds": [
"F070"
]
},
{
"id": "T117",
"description": "OrgChart creates smoothstep edges between connected nodes",
"implemented": true,
"featureIds": [
"F071"
]
},
{
"id": "T118",
"description": "OrgChart calls `fitView` on initial render to show all nodes",
"implemented": true,
"featureIds": [
"F072"
]
},
{
"id": "T119",
"description": "OrgChart supports zoom and pan interactions",
"implemented": true,
"featureIds": [
"F072"
]
},
{
"id": "T120",
"description": "OrgChart nodes are not draggable",
"implemented": true,
"featureIds": [
"F072"
]
},
{
"id": "T121",
"description": "Clicking an OrgChart node opens UserDetails drawer with correct userId",
"implemented": true,
"featureIds": [
"F073"
]
},
{
"id": "T122",
"description": "Closing UserDetails drawer from OrgChart returns to the chart view",
"implemented": true,
"featureIds": [
"F073"
]
},
{
"id": "T123",
"description": "OrgChart nodes show user avatars (fetched in batch)",
"implemented": true,
"featureIds": [
"F074"
]
},
{
"id": "T124",
"description": "ReactFlow is dynamically imported with `ssr: false` \u2014 no window/document errors during SSR",
"implemented": true,
"featureIds": [
"F075"
]
},
{
"id": "T125",
"description": "CardHeader shows both ViewSwitchers in one row: [List|Structure] and [MSP|Client Portal]",
"implemented": true,
"featureIds": [
"F076"
]
},
{
"id": "T126",
"description": "Structure toggle is hidden when `teams-v2` is disabled",
"implemented": true,
"featureIds": [
"F076",
"F082"
]
},
{
"id": "T127",
"description": "Structure toggle is hidden when portal type is 'client'",
"implemented": true,
"featureIds": [
"F076"
]
},
{
"id": "T128",
"description": "No ViewSwitcher for list/org appears in the list view toolbar area",
"implemented": true,
"featureIds": [
"F077"
]
},
{
"id": "T129",
"description": "No ViewSwitcher for list/org appears above the org chart content",
"implemented": true,
"featureIds": [
"F078"
]
},
{
"id": "T130",
"description": "ViewSwitcher option label reads 'Structure' not 'Org Chart'",
"implemented": true,
"featureIds": [
"F079"
]
},
{
"id": "T131",
"description": "Switching to 'Structure' view renders the ReactFlow OrgChart instead of nested list",
"implemented": true,
"featureIds": [
"F080"
]
},
{
"id": "T132",
"description": "No `buildOrgTree` or `renderOrgNode` functions remain in UserManagement.tsx",
"implemented": true,
"featureIds": [
"F081"
]
},
{
"id": "T133",
"description": "Structure view and toggle are invisible when `teams-v2` flag is off",
"implemented": true,
"featureIds": [
"F082"
]
},
{
"id": "T134",
"description": "UserAndTeamPicker: teams show TeamAvatar instead of gray circle with TeamIcon",
"implemented": true,
"featureIds": [
"F083"
]
},
{
"id": "T135",
"description": "UserAndTeamPicker: TeamAvatar shows colored initials when no image is uploaded",
"implemented": true,
"featureIds": [
"F083",
"F090"
]
},
{
"id": "T136",
"description": "UserAndTeamPicker: TeamAvatar shows uploaded image when available",
"implemented": true,
"featureIds": [
"F083",
"F085"
]
},
{
"id": "T137",
"description": "UserAndTeamPicker: `getTeamAvatarUrlsBatch` prop is optional \u2014 component works without it",
"implemented": true,
"featureIds": [
"F084"
]
},
{
"id": "T138",
"description": "UserAndTeamPicker: avatar URLs are batch-fetched when dropdown opens",
"implemented": true,
"featureIds": [
"F085"
]
},
{
"id": "T139",
"description": "MultiUserAndTeamPicker: teams show TeamAvatar in all 4 display contexts (summary single, summary multi, chip, dropdown)",
"implemented": true,
"featureIds": [
"F086",
"F087"
]
},
{
"id": "T140",
"description": "MultiUserAndTeamPicker: accepts teams prop, teamFilterFn, and all team-related props from original MultiUserPicker",
"implemented": true,
"featureIds": [
"F086"
]
},
{
"id": "T141",
"description": "MultiUserAndTeamPicker: `getTeamAvatarUrlsBatch` prop is optional \u2014 component works without it (falls back to colored initials)",
"implemented": true,
"featureIds": [
"F088"
]
},
{
"id": "T142",
"description": "MultiUserAndTeamPicker: avatar URLs are batch-fetched when dropdown opens",
"implemented": true,
"featureIds": [
"F088"
]
},
{
"id": "T143",
"description": "MultiUserPicker: no team-related props remain (teams, teamFilterFn, etc.)",
"implemented": true,
"featureIds": [
"F089"
]
},
{
"id": "T144",
"description": "MultiUserPicker: renders only users \u2014 no team sections, no TeamIcon, no team chips",
"implemented": true,
"featureIds": [
"F089"
]
},
{
"id": "T145",
"description": "Call sites render `MultiUserAndTeamPicker` when `teams-v2` flag is enabled, `MultiUserPicker` when disabled",
"implemented": true,
"featureIds": [
"F090"
]
},
{
"id": "T146",
"description": "Ticket detail picker passes `getTeamAvatarUrlsBatchAction` to UserAndTeamPicker",
"implemented": true,
"featureIds": [
"F091"
]
},
{
"id": "T147",
"description": "Ticket list filter passes `getTeamAvatarUrlsBatchAction` to MultiUserAndTeamPicker",
"implemented": true,
"featureIds": [
"F091"
]
},
{
"id": "T148",
"description": "No gray circles with generic TeamIcon remain in picker components when teams are displayed",
"implemented": true,
"featureIds": [
"F092"
]
}
]