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
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz Source: /opt/alga-psa on psa.joliet.tech
545 lines
12 KiB
JSON
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"
|
|
]
|
|
}
|
|
]
|