@mndrk/agx 2.4.2 → 2.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cloud-runtime/standalone/apps/local/.next/BUILD_ID +1 -1
- package/cloud-runtime/standalone/apps/local/.next/app-path-routes-manifest.json +5 -0
- package/cloud-runtime/standalone/apps/local/.next/build-manifest.json +2 -2
- package/cloud-runtime/standalone/apps/local/.next/prerender-manifest.json +3 -3
- package/cloud-runtime/standalone/apps/local/.next/routes-manifest.json +41 -0
- package/cloud-runtime/standalone/apps/local/.next/server/app/_global-error.html +2 -2
- package/cloud-runtime/standalone/apps/local/.next/server/app/_global-error.rsc +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/_not-found.html +2 -2
- package/cloud-runtime/standalone/apps/local/.next/server/app/_not-found.rsc +2 -2
- package/cloud-runtime/standalone/apps/local/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
- package/cloud-runtime/standalone/apps/local/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
- package/cloud-runtime/standalone/apps/local/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/cloud-runtime/standalone/apps/local/.next/server/app/agents/[id]/page.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/agents/[id]/page_client-reference-manifest.js +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/agents/page.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/agents/page_client-reference-manifest.js +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/agents.html +2 -2
- package/cloud-runtime/standalone/apps/local/.next/server/app/agents.rsc +3 -3
- package/cloud-runtime/standalone/apps/local/.next/server/app/agents.segments/_full.segment.rsc +3 -3
- package/cloud-runtime/standalone/apps/local/.next/server/app/agents.segments/_head.segment.rsc +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/agents.segments/_index.segment.rsc +2 -2
- package/cloud-runtime/standalone/apps/local/.next/server/app/agents.segments/_tree.segment.rsc +2 -2
- package/cloud-runtime/standalone/apps/local/.next/server/app/agents.segments/agents/__PAGE__.segment.rsc +2 -2
- package/cloud-runtime/standalone/apps/local/.next/server/app/agents.segments/agents.segment.rsc +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/agent-specs/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/agents/[id]/profile/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/agents/export/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/chat/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/file-search/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/participants/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/projects/[id]/objectives/[objectiveId]/scheduled-tasks/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/projects/[id]/objectives/[objectiveId]/worker/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/projects/[id]/search/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/projects/[id]/teams/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/prompt-jobs/poll/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/providers/check/[id]/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/providers/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/queue/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/schedules/debug/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/schedules/poll/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/skills/assign/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/skills/available/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/skills/detail/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/skills/history/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/skills/learn/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/skills/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/skills/unlearn/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/status/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/summarize/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/tasks/[id]/comments/[commentId]/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/tasks/[id]/comments/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/tasks/[id]/nodes/[nodeId]/verify/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/tasks/[id]/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/tasks/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/threads/knowledge/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/threads/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/auth/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/callback/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/groups/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/items/[id]/activity/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/items/[id]/recap/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/items/[id]/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/items/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/labels/[id]/route/app-paths-manifest.json +3 -0
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/labels/[id]/route/build-manifest.json +11 -0
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/labels/[id]/route/server-reference-manifest.json +4 -0
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/labels/[id]/route.js +7 -0
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/labels/[id]/route.js.map +5 -0
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/labels/[id]/route.js.nft.json +1 -0
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/labels/[id]/route_client-reference-manifest.js +2 -0
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/labels/route/app-paths-manifest.json +3 -0
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/labels/route/build-manifest.json +11 -0
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/labels/route/server-reference-manifest.json +4 -0
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/labels/route.js +7 -0
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/labels/route.js.map +5 -0
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/labels/route.js.nft.json +1 -0
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/labels/route_client-reference-manifest.js +2 -0
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/mcp-setup/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/metadata/bulk/route/app-paths-manifest.json +3 -0
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/metadata/bulk/route/build-manifest.json +11 -0
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/metadata/bulk/route/server-reference-manifest.json +4 -0
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/metadata/bulk/route.js +7 -0
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/metadata/bulk/route.js.map +5 -0
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/metadata/bulk/route.js.nft.json +1 -0
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/metadata/bulk/route_client-reference-manifest.js +2 -0
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/metadata/route/app-paths-manifest.json +3 -0
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/metadata/route/build-manifest.json +11 -0
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/metadata/route/server-reference-manifest.json +4 -0
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/metadata/route.js +7 -0
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/metadata/route.js.map +5 -0
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/metadata/route.js.nft.json +1 -0
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/metadata/route_client-reference-manifest.js +2 -0
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/options/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/runs/[id]/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/runs/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/runs/scripted/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/stats/route/app-paths-manifest.json +3 -0
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/stats/route/build-manifest.json +11 -0
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/stats/route/server-reference-manifest.json +4 -0
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/stats/route.js +7 -0
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/stats/route.js.map +5 -0
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/stats/route.js.nft.json +1 -0
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/stats/route_client-reference-manifest.js +2 -0
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/status/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/token/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/token-receive/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/worker/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/api/update-check/route.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/index.html +2 -2
- package/cloud-runtime/standalone/apps/local/.next/server/app/index.rsc +2 -2
- package/cloud-runtime/standalone/apps/local/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/index.segments/_full.segment.rsc +2 -2
- package/cloud-runtime/standalone/apps/local/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/index.segments/_index.segment.rsc +2 -2
- package/cloud-runtime/standalone/apps/local/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/cloud-runtime/standalone/apps/local/.next/server/app/page_client-reference-manifest.js +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/automations/page/react-loadable-manifest.json +2 -2
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/automations/page.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/automations/page_client-reference-manifest.js +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/env-vars/page.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/env-vars/page_client-reference-manifest.js +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/folders/page.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/folders/page_client-reference-manifest.js +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/graph/[taskId]/page.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/graph/[taskId]/page_client-reference-manifest.js +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/objectives/[objectiveId]/page.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/objectives/[objectiveId]/page_client-reference-manifest.js +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/objectives/page.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/objectives/page_client-reference-manifest.js +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/page.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/page_client-reference-manifest.js +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/teams/[teamId]/agents/[agentId]/page.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/teams/[teamId]/agents/[agentId]/page_client-reference-manifest.js +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/teams/[teamId]/page.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/teams/[teamId]/page_client-reference-manifest.js +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/teams/adopt/page.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/teams/adopt/page_client-reference-manifest.js +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/teams/new/page.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/teams/new/page_client-reference-manifest.js +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/teams/page.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/teams/page_client-reference-manifest.js +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/teams/replace/page.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/teams/replace/page_client-reference-manifest.js +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/terminal/page.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/terminal/page_client-reference-manifest.js +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/thread/[threadId]/page.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/thread/[threadId]/page_client-reference-manifest.js +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/tracking/[tracker]/page/react-loadable-manifest.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/tracking/[tracker]/page.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/tracking/[tracker]/page_client-reference-manifest.js +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/tracking/connect/page.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/tracking/connect/page_client-reference-manifest.js +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/tracking/page/react-loadable-manifest.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/tracking/page.js.nft.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/tracking/page_client-reference-manifest.js +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects/page_client-reference-manifest.js +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects.html +2 -2
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects.rsc +2 -2
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects.segments/_full.segment.rsc +2 -2
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects.segments/_head.segment.rsc +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects.segments/_index.segment.rsc +2 -2
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects.segments/_tree.segment.rsc +2 -2
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects.segments/projects/__PAGE__.segment.rsc +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/projects.segments/projects.segment.rsc +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/setup/page_client-reference-manifest.js +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/setup.html +2 -2
- package/cloud-runtime/standalone/apps/local/.next/server/app/setup.rsc +2 -2
- package/cloud-runtime/standalone/apps/local/.next/server/app/setup.segments/_full.segment.rsc +2 -2
- package/cloud-runtime/standalone/apps/local/.next/server/app/setup.segments/_head.segment.rsc +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/setup.segments/_index.segment.rsc +2 -2
- package/cloud-runtime/standalone/apps/local/.next/server/app/setup.segments/_tree.segment.rsc +2 -2
- package/cloud-runtime/standalone/apps/local/.next/server/app/setup.segments/setup/__PAGE__.segment.rsc +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/setup.segments/setup.segment.rsc +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/status/page_client-reference-manifest.js +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/status.html +2 -2
- package/cloud-runtime/standalone/apps/local/.next/server/app/status.rsc +2 -2
- package/cloud-runtime/standalone/apps/local/.next/server/app/status.segments/_full.segment.rsc +2 -2
- package/cloud-runtime/standalone/apps/local/.next/server/app/status.segments/_head.segment.rsc +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/status.segments/_index.segment.rsc +2 -2
- package/cloud-runtime/standalone/apps/local/.next/server/app/status.segments/_tree.segment.rsc +2 -2
- package/cloud-runtime/standalone/apps/local/.next/server/app/status.segments/status/__PAGE__.segment.rsc +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app/status.segments/status.segment.rsc +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/app-paths-manifest.json +5 -0
- package/cloud-runtime/standalone/apps/local/.next/server/chunks/083c9_next-internal_server_app_api_trackers_[tracker]_metadata_route_actions_c83fcc1a.js +3 -0
- package/cloud-runtime/standalone/apps/local/.next/server/chunks/30bdd_server_app_api_trackers_[tracker]_labels_[id]_route_actions_2646388d.js +3 -0
- package/cloud-runtime/standalone/apps/local/.next/server/chunks/30bdd_server_app_api_trackers_[tracker]_metadata_bulk_route_actions_f43e6831.js +3 -0
- package/cloud-runtime/standalone/apps/local/.next/server/chunks/[root-of-the-server]__0e04eca4._.js +40 -0
- package/cloud-runtime/standalone/apps/local/.next/server/chunks/[root-of-the-server]__1d970ad0._.js +40 -0
- package/cloud-runtime/standalone/apps/local/.next/server/chunks/[root-of-the-server]__3b27260f._.js +23 -8
- package/cloud-runtime/standalone/apps/local/.next/server/chunks/[root-of-the-server]__580ddcca._.js +40 -0
- package/cloud-runtime/standalone/apps/local/.next/server/chunks/[root-of-the-server]__5da8d281._.js +129 -0
- package/cloud-runtime/standalone/apps/local/.next/server/chunks/[root-of-the-server]__76030d44._.js +40 -0
- package/cloud-runtime/standalone/apps/local/.next/server/chunks/[root-of-the-server]__7db7c421._.js +20 -5
- package/cloud-runtime/standalone/apps/local/.next/server/chunks/[root-of-the-server]__d8cc43c7._.js +22 -7
- package/cloud-runtime/standalone/apps/local/.next/server/chunks/[root-of-the-server]__f598d976._.js +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/chunks/[root-of-the-server]__f7a936d9._.js +21 -6
- package/cloud-runtime/standalone/apps/local/.next/server/chunks/apps_local_80b34b78._.js +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/chunks/apps_local_8f9f647d._.js +28 -13
- package/cloud-runtime/standalone/apps/local/.next/server/chunks/apps_local_d256aa32._.js +28 -25
- package/cloud-runtime/standalone/apps/local/.next/server/chunks/apps_local_lib_tracker_tracker-run-store_ts_5aa9592e._.js +22 -7
- package/cloud-runtime/standalone/apps/local/.next/server/chunks/ebff2__next-internal_server_app_api_trackers_[tracker]_labels_route_actions_8ba41152.js +3 -0
- package/cloud-runtime/standalone/apps/local/.next/server/chunks/ebff2__next-internal_server_app_api_trackers_[tracker]_stats_route_actions_7da4ccde.js +3 -0
- package/cloud-runtime/standalone/apps/local/.next/server/chunks/ssr/{[root-of-the-server]__799f4d13._.js → [root-of-the-server]__2af44092._.js} +2 -2
- package/cloud-runtime/standalone/apps/local/.next/server/chunks/ssr/[root-of-the-server]__452cb0f0._.js +3 -0
- package/cloud-runtime/standalone/apps/local/.next/server/chunks/ssr/[root-of-the-server]__489568b4._.js +3 -0
- package/cloud-runtime/standalone/apps/local/.next/server/chunks/ssr/[root-of-the-server]__4ec098a0._.js +3 -0
- package/cloud-runtime/standalone/apps/local/.next/server/chunks/ssr/[root-of-the-server]__53bd50df._.js +3 -0
- package/cloud-runtime/standalone/apps/local/.next/server/chunks/ssr/[root-of-the-server]__7774a40c._.js +3 -0
- package/cloud-runtime/standalone/apps/local/.next/server/chunks/ssr/[root-of-the-server]__b8484b0e._.js +7 -0
- package/cloud-runtime/standalone/apps/local/.next/server/chunks/ssr/{[root-of-the-server]__51edc9b6._.js → [root-of-the-server]__bd05ee09._.js} +2 -2
- package/cloud-runtime/standalone/apps/local/.next/server/chunks/ssr/_8c4beba9._.js +7 -0
- package/cloud-runtime/standalone/apps/local/.next/server/chunks/ssr/{apps_local_35d90b5d._.js → apps_local_bbb7b83b._.js} +2 -2
- package/cloud-runtime/standalone/apps/local/.next/server/chunks/ssr/apps_local_components_TrackerBoard_tsx_98970bab._.js +6 -6
- package/cloud-runtime/standalone/apps/local/.next/server/chunks/ssr/apps_local_components_chat-ui_f0554cb4._.js +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/functions-config-manifest.json +5 -0
- package/cloud-runtime/standalone/apps/local/.next/server/middleware-manifest.json +5 -5
- package/cloud-runtime/standalone/apps/local/.next/server/pages/404.html +2 -2
- package/cloud-runtime/standalone/apps/local/.next/server/pages/500.html +2 -2
- package/cloud-runtime/standalone/apps/local/.next/server/server-reference-manifest.js +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/server-reference-manifest.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/static/chunks/0243e7d015db440d.js +5 -0
- package/cloud-runtime/standalone/apps/local/.next/static/chunks/42a62b80b32a97f7.js +9 -0
- package/cloud-runtime/standalone/apps/local/.next/static/chunks/5d047fc7267a8f53.js +16 -0
- package/cloud-runtime/standalone/apps/local/.next/static/chunks/716e1716d526ded9.js +46 -0
- package/cloud-runtime/standalone/apps/local/.next/static/chunks/{77cea126364aab3c.js → 7353a3a1fcd5825c.js} +1 -1
- package/cloud-runtime/standalone/apps/local/.next/static/chunks/9acdd370e9daca0d.js +16 -0
- package/cloud-runtime/standalone/apps/local/.next/static/chunks/{6c777fe66e042eec.js → 9df45611d6c84e02.js} +1 -1
- package/cloud-runtime/standalone/apps/local/.next/static/chunks/a084c6475513e6fe.js +16 -0
- package/cloud-runtime/standalone/apps/local/.next/static/chunks/aa6db7c91c1ccd5f.js +16 -0
- package/cloud-runtime/standalone/apps/local/.next/static/chunks/cecf3e8c47c785f5.js +5 -0
- package/cloud-runtime/standalone/apps/local/.next/static/chunks/d5607ac80145f3b7.js +1 -0
- package/cloud-runtime/standalone/apps/local/.next/static/chunks/{d5b14e14665024a9.js → d5c307b52fd87861.js} +1 -1
- package/cloud-runtime/standalone/apps/local/.next/static/chunks/f4acf76cb6c82c73.js +16 -0
- package/cloud-runtime/standalone/apps/local/.next/static/chunks/f6d31036588ddfe4.css +1 -0
- package/cloud-runtime/standalone/apps/local/app/api/trackers/[tracker]/labels/[id]/route.ts +23 -0
- package/cloud-runtime/standalone/apps/local/app/api/trackers/[tracker]/labels/route.ts +41 -0
- package/cloud-runtime/standalone/apps/local/app/api/trackers/[tracker]/metadata/bulk/route.ts +68 -0
- package/cloud-runtime/standalone/apps/local/app/api/trackers/[tracker]/metadata/route.ts +31 -0
- package/cloud-runtime/standalone/apps/local/app/api/trackers/[tracker]/options/route.ts +1 -0
- package/cloud-runtime/standalone/apps/local/app/api/trackers/[tracker]/stats/route.ts +20 -0
- package/cloud-runtime/standalone/apps/local/components/TrackerBoard.tsx +609 -85
- package/cloud-runtime/standalone/apps/local/components/tracker/FibonacciPicker.tsx +41 -0
- package/cloud-runtime/standalone/apps/local/components/tracker/FolderRow.tsx +1 -1
- package/cloud-runtime/standalone/apps/local/components/tracker/LabelPicker.tsx +118 -0
- package/cloud-runtime/standalone/apps/local/components/tracker/LabelSettings.tsx +104 -0
- package/cloud-runtime/standalone/apps/local/components/tracker/PromptPopover.tsx +64 -0
- package/cloud-runtime/standalone/apps/local/components/tracker/SelectionBar.tsx +276 -23
- package/cloud-runtime/standalone/apps/local/components/tracker/StatusGroupRow.tsx +50 -0
- package/cloud-runtime/standalone/apps/local/components/tracker/TicketPanel.tsx +14 -2
- package/cloud-runtime/standalone/apps/local/components/tracker/TicketRow.tsx +147 -7
- package/cloud-runtime/standalone/apps/local/components/tracker/TrackerSettingsModal.tsx +14 -2
- package/cloud-runtime/standalone/apps/local/components/ui/ResizeHandle.tsx +15 -22
- package/cloud-runtime/standalone/apps/local/hooks/useTrackerIssueStats.ts +52 -0
- package/cloud-runtime/standalone/apps/local/hooks/useTrackerItemMetadata.ts +67 -0
- package/cloud-runtime/standalone/apps/local/hooks/useTrackerItemsMetadata.ts +51 -0
- package/cloud-runtime/standalone/apps/local/hooks/useTrackerLabels.ts +74 -0
- package/cloud-runtime/standalone/apps/local/hooks/useTrackerRuns.ts +5 -0
- package/cloud-runtime/standalone/apps/local/lib/tracker/adapters/jira/adapter.tsx +1 -0
- package/cloud-runtime/standalone/apps/local/lib/tracker/adapters/jira/issues.ts +1 -0
- package/cloud-runtime/standalone/apps/local/lib/tracker/adapters/linear/adapter.tsx +1 -0
- package/cloud-runtime/standalone/apps/local/lib/tracker/adapters/linear/client.ts +5 -0
- package/cloud-runtime/standalone/apps/local/lib/tracker/adapters/linear/issues.ts +1 -0
- package/cloud-runtime/standalone/apps/local/lib/tracker/tracker-adapter.ts +2 -0
- package/cloud-runtime/standalone/apps/local/lib/tracker/tracker-item-metadata-store.ts +262 -0
- package/cloud-runtime/standalone/apps/local/lib/tracker/tracker-item-store.ts +10 -3
- package/cloud-runtime/standalone/apps/local/lib/tracker/tracker-run-store.ts +42 -0
- package/cloud-runtime/standalone/apps/local/state/trackerBoardFilters.ts +4 -0
- package/cloud-runtime/standalone/apps/local/worker/index.js +0 -1
- package/package.json +1 -1
- package/cloud-runtime/standalone/apps/local/.next/server/chunks/ssr/[root-of-the-server]__30bf097e._.js +0 -3
- package/cloud-runtime/standalone/apps/local/.next/server/chunks/ssr/[root-of-the-server]__46ae9d33._.js +0 -3
- package/cloud-runtime/standalone/apps/local/.next/server/chunks/ssr/[root-of-the-server]__50fd8680._.js +0 -3
- package/cloud-runtime/standalone/apps/local/.next/server/chunks/ssr/[root-of-the-server]__8059a285._.js +0 -3
- package/cloud-runtime/standalone/apps/local/.next/server/chunks/ssr/[root-of-the-server]__886953ec._.js +0 -7
- package/cloud-runtime/standalone/apps/local/.next/server/chunks/ssr/[root-of-the-server]__97160565._.js +0 -3
- package/cloud-runtime/standalone/apps/local/.next/static/chunks/0876dfd6ce07abaf.js +0 -9
- package/cloud-runtime/standalone/apps/local/.next/static/chunks/1ec83777a9abd420.js +0 -16
- package/cloud-runtime/standalone/apps/local/.next/static/chunks/286758b0fd546c68.js +0 -16
- package/cloud-runtime/standalone/apps/local/.next/static/chunks/a72ed5cb3feb0d51.js +0 -5
- package/cloud-runtime/standalone/apps/local/.next/static/chunks/b02c180ad1d968eb.js +0 -16
- package/cloud-runtime/standalone/apps/local/.next/static/chunks/b048a4812b51f97a.js +0 -1
- package/cloud-runtime/standalone/apps/local/.next/static/chunks/c63d97c917d96f47.js +0 -46
- package/cloud-runtime/standalone/apps/local/.next/static/chunks/d3bf70e2fbdc0ae5.js +0 -5
- package/cloud-runtime/standalone/apps/local/.next/static/chunks/dd5a56eea2d4c067.js +0 -16
- package/cloud-runtime/standalone/apps/local/.next/static/chunks/dd7d7c382389b8b9.js +0 -16
- package/cloud-runtime/standalone/apps/local/.next/static/chunks/ec92e3bd6c2db6e6.css +0 -1
- package/cloud-runtime/standalone/apps/local/.next/static/chunks/ffcc32453866d0c2.js +0 -1
- /package/cloud-runtime/standalone/apps/local/.next/static/{QEldoF1LdgJqO0PgpmUmx → 4MnUE2NHztybGBWFbcBo5}/_buildManifest.js +0 -0
- /package/cloud-runtime/standalone/apps/local/.next/static/{QEldoF1LdgJqO0PgpmUmx → 4MnUE2NHztybGBWFbcBo5}/_clientMiddlewareManifest.json +0 -0
- /package/cloud-runtime/standalone/apps/local/.next/static/{QEldoF1LdgJqO0PgpmUmx → 4MnUE2NHztybGBWFbcBo5}/_ssgManifest.js +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
3
|
+
import React, { useCallback, useDeferredValue, useEffect, useMemo, useRef, useState } from "react";
|
|
4
4
|
import dynamic from "next/dynamic";
|
|
5
|
-
import { ArrowDown, ArrowUp, ChevronLeft, Clock, FileText, Play, Plus, RefreshCw, Search, Settings, User, X } from "lucide-react";
|
|
5
|
+
import { ArrowDown, ArrowUp, ChevronDown, ChevronLeft, ChevronRight, Clock, FileText, Play, Plus, RefreshCw, Search, Settings, User, X } from "lucide-react";
|
|
6
6
|
import { useUrlSelection } from "@/hooks/useUrlSelection";
|
|
7
7
|
import { useTrackerItems } from "@/hooks/useTrackerItems";
|
|
8
8
|
import type { TrackerItem, TrackerStatusCategory } from "@/lib/tracker/types";
|
|
@@ -56,12 +56,16 @@ import { TicketRow } from "@/components/tracker/TicketRow";
|
|
|
56
56
|
import { TicketPanel } from "@/components/tracker/TicketPanel";
|
|
57
57
|
import { useTrackerParticipants } from "@/hooks/useTrackerParticipants";
|
|
58
58
|
import { useTrackerActiveAgents } from "@/hooks/useTrackerActiveAgents";
|
|
59
|
+
import { useTrackerIssueStats } from "@/hooks/useTrackerIssueStats";
|
|
59
60
|
import { agentAvatarUrl } from "@/lib/tracker-board-utils";
|
|
60
61
|
import { useTaskGroups, type TaskGroup } from "@/hooks/useTaskGroups";
|
|
61
62
|
import { FolderRow } from "@/components/tracker/FolderRow";
|
|
62
63
|
import { GroupPanel } from "@/components/tracker/GroupPanel";
|
|
63
64
|
import { GroupNamePrompt, PENDING_GROUP_DROP_ID } from "@/components/tracker/GroupNamePrompt";
|
|
65
|
+
import { StatusGroupRow, STATUS_GROUP_PREFIX } from "@/components/tracker/StatusGroupRow";
|
|
64
66
|
import { SelectionBar } from "@/components/tracker/SelectionBar";
|
|
67
|
+
import { useTrackerItemsMetadata } from "@/hooks/useTrackerItemsMetadata";
|
|
68
|
+
import { useTrackerLabels } from "@/hooks/useTrackerLabels";
|
|
65
69
|
import {
|
|
66
70
|
DndContext,
|
|
67
71
|
DragOverlay,
|
|
@@ -89,6 +93,13 @@ function formatRunTime(iso: string): string {
|
|
|
89
93
|
});
|
|
90
94
|
}
|
|
91
95
|
|
|
96
|
+
const STATUS_CATEGORY_COLORS: Record<string, string> = {
|
|
97
|
+
todo: "bg-zinc-400",
|
|
98
|
+
in_progress: "bg-amber-400",
|
|
99
|
+
done: "bg-emerald-400",
|
|
100
|
+
cancelled: "bg-red-400",
|
|
101
|
+
};
|
|
102
|
+
|
|
92
103
|
interface GroupOption {
|
|
93
104
|
id: string;
|
|
94
105
|
name: string;
|
|
@@ -405,16 +416,20 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
|
|
|
405
416
|
const [selectedAssigneeIds, setSelectedAssigneeIds] = useState<string[]>([]);
|
|
406
417
|
const [selectedStatusCategories, setSelectedStatusCategories] = useState<string[]>([]);
|
|
407
418
|
const [groups, setGroups] = useState<GroupOption[]>([]);
|
|
419
|
+
const [groupLabel, setGroupLabel] = useState("Group");
|
|
408
420
|
const [selectedGroupId, setSelectedGroupId] = useState("");
|
|
409
421
|
const [selectedWorkspaceId, setSelectedWorkspaceId] = useState("");
|
|
410
422
|
const [sortBy, setSortBy] = useState<"activity" | "identifier" | "status" | "created">("activity");
|
|
411
423
|
const [sortDir, setSortDir] = useState<"asc" | "desc">("desc");
|
|
412
|
-
const [
|
|
424
|
+
const [selectedLabelNames, setSelectedLabelNames] = useState<string[]>([]);
|
|
413
425
|
const [pinnedItemIds, setPinnedItemIds] = useState<Set<string>>(() => loadPinnedTrackerItemIds(trackerType, projectSlug));
|
|
414
426
|
const [selectedItemFallback, setSelectedItemFallback] = useState<TrackerItem | null>(null);
|
|
415
427
|
const [updatingItemId, setUpdatingItemId] = useState<string | null>(null);
|
|
428
|
+
const [collapsedStatusGroups, setCollapsedStatusGroups] = useState<Set<string>>(new Set());
|
|
429
|
+
const groupByStatus = true;
|
|
416
430
|
const { participants } = useTrackerParticipants(trackerType, projectId);
|
|
417
431
|
const { issueActiveAgents } = useTrackerActiveAgents(trackerType, projectId);
|
|
432
|
+
const { issueStats } = useTrackerIssueStats(trackerType, projectId);
|
|
418
433
|
const [pickerItem, setPickerItem] = useState<TrackerItem | null>(null);
|
|
419
434
|
const [pickerAnchor, setPickerAnchor] = useState<{ top: number; left: number } | null>(null);
|
|
420
435
|
const [touchPanelTab, setTouchPanelTab] = useState<"runs" | "ticket">("runs");
|
|
@@ -480,6 +495,10 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
|
|
|
480
495
|
// hoisting issues (sortedItems is declared further down).
|
|
481
496
|
const sortedItemsRef = useRef<TrackerItem[]>([]);
|
|
482
497
|
|
|
498
|
+
// Ref to handleItemStatusChange so handleDragEnd can access it without
|
|
499
|
+
// hoisting issues (handleItemStatusChange is declared further down).
|
|
500
|
+
const handleItemStatusChangeRef = useRef<((item: TrackerItem, status: string, statusCategory?: TrackerStatusCategory) => Promise<void>) | null>(null);
|
|
501
|
+
|
|
483
502
|
const handleMultiSelectGroup = useCallback(() => {
|
|
484
503
|
const ids = Array.from(multiSelectedItemIds);
|
|
485
504
|
// Find the topmost selected item in the sorted list to position the prompt
|
|
@@ -550,6 +569,25 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
|
|
|
550
569
|
if (!over || active.id === over.id) return;
|
|
551
570
|
const overId = over.id as string;
|
|
552
571
|
|
|
572
|
+
// Dropped on a status group header → change status upstream
|
|
573
|
+
if (overId.startsWith(STATUS_GROUP_PREFIX)) {
|
|
574
|
+
const targetStatus = overId.slice(STATUS_GROUP_PREFIX.length);
|
|
575
|
+
const activeItem = sortedItemsRef.current.find((i) => i.id === activeItemId);
|
|
576
|
+
const targetCategory = sortedItemsRef.current.find((i) => i.status === targetStatus)?.statusCategory;
|
|
577
|
+
if (activeItem && activeItem.status !== targetStatus) {
|
|
578
|
+
await handleItemStatusChangeRef.current?.(activeItem, targetStatus, targetCategory);
|
|
579
|
+
}
|
|
580
|
+
return;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
// Dropped on a ticket in a different status group → change status
|
|
584
|
+
const activeItem = sortedItemsRef.current.find((i) => i.id === activeItemId);
|
|
585
|
+
const overItem = sortedItemsRef.current.find((i) => i.id === overId);
|
|
586
|
+
if (activeItem && overItem && activeItem.status !== overItem.status) {
|
|
587
|
+
await handleItemStatusChangeRef.current?.(activeItem, overItem.status, overItem.statusCategory);
|
|
588
|
+
return;
|
|
589
|
+
}
|
|
590
|
+
|
|
553
591
|
// Check if dropping on a folder
|
|
554
592
|
const targetGroup = taskGroups.find((g) => g.id === overId);
|
|
555
593
|
if (targetGroup) {
|
|
@@ -616,7 +654,7 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
|
|
|
616
654
|
setSelectedGroupId(storedFilters.groupIds?.[0] ?? "");
|
|
617
655
|
setSortBy(storedFilters.sortBy);
|
|
618
656
|
setSortDir(storedFilters.sortDir);
|
|
619
|
-
|
|
657
|
+
setSelectedLabelNames(storedFilters.labelNames ?? []);
|
|
620
658
|
setPinnedItemIds(loadPinnedTrackerItemIds(trackerType, projectSlug));
|
|
621
659
|
}, [trackerType, projectSlug]);
|
|
622
660
|
|
|
@@ -631,11 +669,12 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
|
|
|
631
669
|
assigneeIds: selectedAssigneeIds,
|
|
632
670
|
statusCategories: selectedStatusCategories,
|
|
633
671
|
groupIds: selectedGroupId ? [selectedGroupId] : [],
|
|
672
|
+
labelNames: selectedLabelNames,
|
|
634
673
|
sortBy,
|
|
635
674
|
sortDir,
|
|
636
|
-
hasActivity,
|
|
675
|
+
hasActivity: false,
|
|
637
676
|
});
|
|
638
|
-
}, [trackerType, projectSlug, search, selectedAssigneeIds, selectedStatusCategories, selectedWorkspaceId, selectedGroupId, sortBy, sortDir
|
|
677
|
+
}, [trackerType, projectSlug, search, selectedAssigneeIds, selectedStatusCategories, selectedWorkspaceId, selectedGroupId, selectedLabelNames, sortBy, sortDir]);
|
|
639
678
|
|
|
640
679
|
// Fetch filter options when connected
|
|
641
680
|
useEffect(() => {
|
|
@@ -657,7 +696,8 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
|
|
|
657
696
|
setAssignees(Array.isArray(data.assignees) ? data.assignees : []);
|
|
658
697
|
setStatusCategories(Array.isArray(data.statuses) ? data.statuses.map((s: { name: string; category: string }) => ({ value: s.name, label: s.name })) : []);
|
|
659
698
|
setWorkspaces(Array.isArray(data.teams) ? data.teams : []);
|
|
660
|
-
setGroups(Array.isArray(data.
|
|
699
|
+
setGroups(Array.isArray(data.groups) ? data.groups : []);
|
|
700
|
+
if (data.groupLabel) setGroupLabel(data.groupLabel);
|
|
661
701
|
setFilterOptionsLoaded(true);
|
|
662
702
|
})
|
|
663
703
|
.catch(() => {
|
|
@@ -731,9 +771,8 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
|
|
|
731
771
|
groupIds: selectedGroupId ? [selectedGroupId] : undefined,
|
|
732
772
|
sortBy,
|
|
733
773
|
sortDir,
|
|
734
|
-
hasActivity: hasActivity || undefined,
|
|
735
774
|
}),
|
|
736
|
-
[debouncedSearch, selectedAssigneeIds, selectedGroupId, selectedStatusCategories, statusCategories.length, sortBy, sortDir
|
|
775
|
+
[debouncedSearch, selectedAssigneeIds, selectedGroupId, selectedStatusCategories, statusCategories.length, sortBy, sortDir]
|
|
737
776
|
);
|
|
738
777
|
|
|
739
778
|
const {
|
|
@@ -746,6 +785,22 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
|
|
|
746
785
|
} = useTrackerItems(trackerType, filters, connected && filterOptionsLoaded && Boolean(projectId), {
|
|
747
786
|
projectId: projectId ?? "",
|
|
748
787
|
});
|
|
788
|
+
|
|
789
|
+
// Bulk metadata for visible items
|
|
790
|
+
const visibleIssueIds = useMemo(() => items.map((item) => item.id), [items]);
|
|
791
|
+
const {
|
|
792
|
+
metadataMap,
|
|
793
|
+
refresh: refreshMetadata,
|
|
794
|
+
} = useTrackerItemsMetadata(trackerType, projectId, visibleIssueIds);
|
|
795
|
+
|
|
796
|
+
// Labels
|
|
797
|
+
const {
|
|
798
|
+
labels: allLabels,
|
|
799
|
+
definitions: labelDefinitions,
|
|
800
|
+
refresh: refreshLabels,
|
|
801
|
+
createDefinition: createLabelDefinition,
|
|
802
|
+
} = useTrackerLabels(trackerType, projectId);
|
|
803
|
+
|
|
749
804
|
const selectedItemFromList = useMemo(
|
|
750
805
|
() => (selectedItemId ? items.find((item) => item.id === selectedItemId) ?? null : null),
|
|
751
806
|
[items, selectedItemId],
|
|
@@ -769,9 +824,45 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
|
|
|
769
824
|
}, [items, pinnedItemIds]);
|
|
770
825
|
sortedItemsRef.current = sortedItems;
|
|
771
826
|
|
|
827
|
+
const deferredLabelNames = useDeferredValue(selectedLabelNames);
|
|
828
|
+
const labelFilteredItems = useMemo(() => {
|
|
829
|
+
if (deferredLabelNames.length === 0) return sortedItems;
|
|
830
|
+
const filterSet = new Set(deferredLabelNames);
|
|
831
|
+
const result: TrackerItem[] = [];
|
|
832
|
+
for (const item of sortedItems) {
|
|
833
|
+
const labels = metadataMap.get(item.id)?.labels;
|
|
834
|
+
if (!labels) continue;
|
|
835
|
+
for (const l of labels) {
|
|
836
|
+
if (filterSet.has(l)) {
|
|
837
|
+
result.push(item);
|
|
838
|
+
break;
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
return result;
|
|
843
|
+
}, [sortedItems, deferredLabelNames, metadataMap]);
|
|
844
|
+
|
|
845
|
+
const statusGroups = useMemo(() => {
|
|
846
|
+
if (!groupByStatus) return [];
|
|
847
|
+
const map = new Map<string, { status: string; category: TrackerStatusCategory; items: TrackerItem[] }>();
|
|
848
|
+
for (const item of labelFilteredItems) {
|
|
849
|
+
let group = map.get(item.status);
|
|
850
|
+
if (!group) {
|
|
851
|
+
group = { status: item.status, category: item.statusCategory, items: [] };
|
|
852
|
+
map.set(item.status, group);
|
|
853
|
+
}
|
|
854
|
+
group.items.push(item);
|
|
855
|
+
}
|
|
856
|
+
const categoryOrder: Record<string, number> = { in_progress: 0, todo: 1, done: 2, cancelled: 3 };
|
|
857
|
+
return [...map.values()].sort(
|
|
858
|
+
(a, b) => (categoryOrder[a.category] ?? 1) - (categoryOrder[b.category] ?? 1)
|
|
859
|
+
);
|
|
860
|
+
}, [groupByStatus, labelFilteredItems]);
|
|
861
|
+
|
|
772
862
|
const {
|
|
773
863
|
runs,
|
|
774
864
|
loading: runsLoading,
|
|
865
|
+
loadedForIssueId: runsLoadedForIssueId,
|
|
775
866
|
createRun,
|
|
776
867
|
updateRun,
|
|
777
868
|
} = useTrackerRuns(trackerType, selectedItem?.id ?? null, projectId ?? null);
|
|
@@ -815,26 +906,64 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
|
|
|
815
906
|
);
|
|
816
907
|
const groupOptions = useMemo<FilterOption[]>(
|
|
817
908
|
() => [
|
|
818
|
-
{ value: "", label:
|
|
909
|
+
{ value: "", label: groupLabel },
|
|
819
910
|
...groups.map((group) => ({
|
|
820
911
|
value: group.id,
|
|
821
912
|
label: group.name,
|
|
822
913
|
})),
|
|
823
914
|
],
|
|
824
|
-
[groups]
|
|
915
|
+
[groups, groupLabel]
|
|
825
916
|
);
|
|
826
917
|
const showStatusFilter = statusOptions.length > 0;
|
|
827
918
|
const showGroupFilter = groupOptions.length > 1;
|
|
828
919
|
const showWorkspaceFilter = workspaceOptions.length > 2;
|
|
829
920
|
const activeSessionScriptLabel = activeScript?.name ?? "AGX default";
|
|
830
921
|
|
|
922
|
+
const labelFilterOptions = useMemo<FilterOption[]>(
|
|
923
|
+
() => allLabels.map((l) => ({ value: l.name, label: l.name })),
|
|
924
|
+
[allLabels]
|
|
925
|
+
);
|
|
926
|
+
|
|
927
|
+
const handleItemToggleLabel = useCallback(async (itemId: string, label: string) => {
|
|
928
|
+
if (!projectId) return;
|
|
929
|
+
const current = metadataMap.get(itemId)?.labels ?? [];
|
|
930
|
+
const has = current.includes(label);
|
|
931
|
+
const next = has ? current.filter((l) => l !== label) : [...current, label];
|
|
932
|
+
try {
|
|
933
|
+
await fetch(`/api/trackers/${trackerType}/metadata?projectId=${encodeURIComponent(projectId)}&issueId=${encodeURIComponent(itemId)}`, {
|
|
934
|
+
method: "PATCH",
|
|
935
|
+
headers: { "Content-Type": "application/json" },
|
|
936
|
+
body: JSON.stringify({ labels: next }),
|
|
937
|
+
});
|
|
938
|
+
void refreshMetadata();
|
|
939
|
+
void refreshLabels();
|
|
940
|
+
} catch {}
|
|
941
|
+
}, [projectId, trackerType, metadataMap, refreshMetadata, refreshLabels]);
|
|
942
|
+
|
|
943
|
+
const handleItemAddLabel = useCallback(async (name: string) => {
|
|
944
|
+
if (!projectId) return;
|
|
945
|
+
await createLabelDefinition(name);
|
|
946
|
+
}, [projectId, createLabelDefinition]);
|
|
947
|
+
|
|
831
948
|
const handleItemStatusChange = useCallback(
|
|
832
|
-
async (item: TrackerItem, status: string) => {
|
|
949
|
+
async (item: TrackerItem, status: string, statusCategory?: TrackerStatusCategory) => {
|
|
833
950
|
const nextStatus = status.trim();
|
|
834
951
|
if (!nextStatus || nextStatus === item.status || !projectId) {
|
|
835
952
|
return;
|
|
836
953
|
}
|
|
837
954
|
|
|
955
|
+
// Optimistic update — move the ticket to the new status immediately so
|
|
956
|
+
// the UI reflects the drop before the PATCH round-trip completes.
|
|
957
|
+
const optimisticItem: TrackerItem = {
|
|
958
|
+
...item,
|
|
959
|
+
status: nextStatus,
|
|
960
|
+
statusCategory: statusCategory ?? item.statusCategory,
|
|
961
|
+
};
|
|
962
|
+
updateItem(optimisticItem);
|
|
963
|
+
if (selectedItemId === item.id) {
|
|
964
|
+
setSelectedItemFallback(optimisticItem);
|
|
965
|
+
}
|
|
966
|
+
|
|
838
967
|
setUpdatingItemId(item.id);
|
|
839
968
|
try {
|
|
840
969
|
const response = await fetch(
|
|
@@ -861,6 +990,11 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
|
|
|
861
990
|
}
|
|
862
991
|
await refreshItems();
|
|
863
992
|
} catch (error) {
|
|
993
|
+
// Revert optimistic update on failure.
|
|
994
|
+
updateItem(item);
|
|
995
|
+
if (selectedItemId === item.id) {
|
|
996
|
+
setSelectedItemFallback(item);
|
|
997
|
+
}
|
|
864
998
|
if (error instanceof Error) {
|
|
865
999
|
window.alert(error.message);
|
|
866
1000
|
}
|
|
@@ -871,6 +1005,161 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
|
|
|
871
1005
|
[refreshItems, selectedItemId, updateItem, trackerType, projectId]
|
|
872
1006
|
);
|
|
873
1007
|
|
|
1008
|
+
// Update the ref whenever the callback changes
|
|
1009
|
+
handleItemStatusChangeRef.current = handleItemStatusChange;
|
|
1010
|
+
|
|
1011
|
+
const handleBulkRecap = useCallback(async () => {
|
|
1012
|
+
const ids = Array.from(multiSelectedItemIds);
|
|
1013
|
+
const selectedItems = ids
|
|
1014
|
+
.map((id) => items.find((item) => item.id === id))
|
|
1015
|
+
.filter(Boolean) as TrackerItem[];
|
|
1016
|
+
|
|
1017
|
+
if (selectedItems.length === 0 || participants.length === 0) return;
|
|
1018
|
+
const agent = participants[0];
|
|
1019
|
+
|
|
1020
|
+
for (const item of selectedItems) {
|
|
1021
|
+
try {
|
|
1022
|
+
await fetch(`/api/trackers/${trackerType}/runs/scripted`, {
|
|
1023
|
+
method: "POST",
|
|
1024
|
+
headers: { "Content-Type": "application/json" },
|
|
1025
|
+
body: JSON.stringify({
|
|
1026
|
+
projectId: projectId ?? undefined,
|
|
1027
|
+
projectSlug: projectSlug ?? undefined,
|
|
1028
|
+
issueId: item.id,
|
|
1029
|
+
issueIdentifier: item.identifier,
|
|
1030
|
+
issueTitle: item.title,
|
|
1031
|
+
issueStatus: item.status,
|
|
1032
|
+
issueAssignee: item.assignee?.name ?? null,
|
|
1033
|
+
agentId: agent.id,
|
|
1034
|
+
scriptName: "Recap",
|
|
1035
|
+
scriptPrompt: "Summarize recent activity and current state of this ticket. Focus on: what was done, what's outstanding, and any blockers.",
|
|
1036
|
+
}),
|
|
1037
|
+
});
|
|
1038
|
+
} catch (err) {
|
|
1039
|
+
console.error(`Failed to start recap for ${item.identifier}:`, err);
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
setMultiSelectedItemIds(new Set());
|
|
1043
|
+
}, [multiSelectedItemIds, items, participants, trackerType, projectId, projectSlug]);
|
|
1044
|
+
|
|
1045
|
+
const handleBulkPrompt = useCallback(async (prompt: string, agentId: string) => {
|
|
1046
|
+
const ids = Array.from(multiSelectedItemIds);
|
|
1047
|
+
const selectedItems = ids
|
|
1048
|
+
.map((id) => items.find((item) => item.id === id))
|
|
1049
|
+
.filter(Boolean) as TrackerItem[];
|
|
1050
|
+
|
|
1051
|
+
for (const item of selectedItems) {
|
|
1052
|
+
try {
|
|
1053
|
+
await fetch(`/api/trackers/${trackerType}/runs/scripted`, {
|
|
1054
|
+
method: "POST",
|
|
1055
|
+
headers: { "Content-Type": "application/json" },
|
|
1056
|
+
body: JSON.stringify({
|
|
1057
|
+
projectId: projectId ?? undefined,
|
|
1058
|
+
projectSlug: projectSlug ?? undefined,
|
|
1059
|
+
issueId: item.id,
|
|
1060
|
+
issueIdentifier: item.identifier,
|
|
1061
|
+
issueTitle: item.title,
|
|
1062
|
+
issueStatus: item.status,
|
|
1063
|
+
issueAssignee: item.assignee?.name ?? null,
|
|
1064
|
+
agentId,
|
|
1065
|
+
scriptPrompt: prompt,
|
|
1066
|
+
}),
|
|
1067
|
+
});
|
|
1068
|
+
} catch (err) {
|
|
1069
|
+
console.error(`Failed to send prompt for ${item.identifier}:`, err);
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
setMultiSelectedItemIds(new Set());
|
|
1073
|
+
}, [multiSelectedItemIds, items, trackerType, projectId, projectSlug]);
|
|
1074
|
+
|
|
1075
|
+
const handleBulkEstimate = useCallback(async (estimate: number | null) => {
|
|
1076
|
+
const ids = Array.from(multiSelectedItemIds);
|
|
1077
|
+
if (ids.length === 0 || !projectId) return;
|
|
1078
|
+
try {
|
|
1079
|
+
await fetch(`/api/trackers/${trackerType}/metadata/bulk`, {
|
|
1080
|
+
method: "POST",
|
|
1081
|
+
headers: { "Content-Type": "application/json" },
|
|
1082
|
+
body: JSON.stringify({
|
|
1083
|
+
projectId,
|
|
1084
|
+
issueIds: ids,
|
|
1085
|
+
action: "set_estimate",
|
|
1086
|
+
payload: { estimate },
|
|
1087
|
+
}),
|
|
1088
|
+
});
|
|
1089
|
+
void refreshMetadata();
|
|
1090
|
+
} catch {}
|
|
1091
|
+
setMultiSelectedItemIds(new Set());
|
|
1092
|
+
}, [multiSelectedItemIds, projectId, trackerType, refreshMetadata]);
|
|
1093
|
+
|
|
1094
|
+
const handleBulkAddLabel = useCallback(async (label: string) => {
|
|
1095
|
+
const ids = Array.from(multiSelectedItemIds);
|
|
1096
|
+
if (ids.length === 0 || !projectId) return;
|
|
1097
|
+
try {
|
|
1098
|
+
await fetch(`/api/trackers/${trackerType}/metadata/bulk`, {
|
|
1099
|
+
method: "POST",
|
|
1100
|
+
headers: { "Content-Type": "application/json" },
|
|
1101
|
+
body: JSON.stringify({
|
|
1102
|
+
projectId,
|
|
1103
|
+
issueIds: ids,
|
|
1104
|
+
action: "add_labels",
|
|
1105
|
+
payload: { labels: [label] },
|
|
1106
|
+
}),
|
|
1107
|
+
});
|
|
1108
|
+
void refreshMetadata();
|
|
1109
|
+
void refreshLabels();
|
|
1110
|
+
} catch {}
|
|
1111
|
+
}, [multiSelectedItemIds, projectId, trackerType, refreshMetadata, refreshLabels]);
|
|
1112
|
+
|
|
1113
|
+
const handleBulkRemoveLabel = useCallback(async (label: string) => {
|
|
1114
|
+
const ids = Array.from(multiSelectedItemIds);
|
|
1115
|
+
if (ids.length === 0 || !projectId) return;
|
|
1116
|
+
try {
|
|
1117
|
+
await fetch(`/api/trackers/${trackerType}/metadata/bulk`, {
|
|
1118
|
+
method: "POST",
|
|
1119
|
+
headers: { "Content-Type": "application/json" },
|
|
1120
|
+
body: JSON.stringify({
|
|
1121
|
+
projectId,
|
|
1122
|
+
issueIds: ids,
|
|
1123
|
+
action: "remove_label",
|
|
1124
|
+
payload: { label },
|
|
1125
|
+
}),
|
|
1126
|
+
});
|
|
1127
|
+
void refreshMetadata();
|
|
1128
|
+
void refreshLabels();
|
|
1129
|
+
} catch {}
|
|
1130
|
+
}, [multiSelectedItemIds, projectId, trackerType, refreshMetadata, refreshLabels]);
|
|
1131
|
+
|
|
1132
|
+
const [bulkStatusUpdating, setBulkStatusUpdating] = useState(false);
|
|
1133
|
+
|
|
1134
|
+
const handleBulkStatus = useCallback(async (status: string) => {
|
|
1135
|
+
const ids = Array.from(multiSelectedItemIds);
|
|
1136
|
+
const selectedItems = ids
|
|
1137
|
+
.map((id) => items.find((item) => item.id === id))
|
|
1138
|
+
.filter(Boolean) as TrackerItem[];
|
|
1139
|
+
|
|
1140
|
+
if (selectedItems.length === 0) return;
|
|
1141
|
+
setBulkStatusUpdating(true);
|
|
1142
|
+
for (const item of selectedItems) {
|
|
1143
|
+
await handleItemStatusChange(item, status);
|
|
1144
|
+
}
|
|
1145
|
+
setBulkStatusUpdating(false);
|
|
1146
|
+
setMultiSelectedItemIds(new Set());
|
|
1147
|
+
}, [multiSelectedItemIds, items, handleItemStatusChange]);
|
|
1148
|
+
|
|
1149
|
+
const handleCreateLabel = useCallback(async (name: string) => {
|
|
1150
|
+
if (!projectId) return;
|
|
1151
|
+
await createLabelDefinition(name);
|
|
1152
|
+
}, [projectId, createLabelDefinition]);
|
|
1153
|
+
|
|
1154
|
+
const selectedMetadata = useMemo(() => {
|
|
1155
|
+
const map = new Map<string, { labels: string[]; estimate: number | null }>();
|
|
1156
|
+
for (const id of multiSelectedItemIds) {
|
|
1157
|
+
const meta = metadataMap.get(id);
|
|
1158
|
+
map.set(id, meta ?? { labels: [], estimate: null });
|
|
1159
|
+
}
|
|
1160
|
+
return map;
|
|
1161
|
+
}, [multiSelectedItemIds, metadataMap]);
|
|
1162
|
+
|
|
874
1163
|
useEffect(() => {
|
|
875
1164
|
if (!selectedItemId || !projectId) {
|
|
876
1165
|
setSelectedItemFallback(null);
|
|
@@ -948,12 +1237,12 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
|
|
|
948
1237
|
}, [selectedItemId, selectedRunId]);
|
|
949
1238
|
|
|
950
1239
|
useEffect(() => {
|
|
951
|
-
if (!isAwaitingRestore || runsLoading ||
|
|
1240
|
+
if (!isAwaitingRestore || runsLoading || runsLoadedForIssueId !== selectedItemId) return;
|
|
952
1241
|
lastRestoredItemRef.current = selectedItemId;
|
|
953
1242
|
if (storedRunId && runs.some((r) => r.id === storedRunId)) {
|
|
954
1243
|
replaceSelection({ run: storedRunId });
|
|
955
1244
|
}
|
|
956
|
-
}, [isAwaitingRestore, storedRunId, selectedItemId, runs, runsLoading, replaceSelection]);
|
|
1245
|
+
}, [isAwaitingRestore, storedRunId, selectedItemId, runs, runsLoading, runsLoadedForIssueId, replaceSelection]);
|
|
957
1246
|
|
|
958
1247
|
useEffect(() => {
|
|
959
1248
|
if (!isTouchLayout) {
|
|
@@ -1156,6 +1445,16 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
|
|
|
1156
1445
|
onChange={setSelectedAssigneeIds}
|
|
1157
1446
|
emptyLabel="All assignees"
|
|
1158
1447
|
/>
|
|
1448
|
+
{labelFilterOptions.length > 0 && (
|
|
1449
|
+
<MultiFilterPopdown
|
|
1450
|
+
label="Label"
|
|
1451
|
+
values={selectedLabelNames}
|
|
1452
|
+
options={labelFilterOptions}
|
|
1453
|
+
activeClasses="border-pink-500/30 bg-pink-500/10 text-pink-400"
|
|
1454
|
+
onChange={setSelectedLabelNames}
|
|
1455
|
+
emptyLabel="All labels"
|
|
1456
|
+
/>
|
|
1457
|
+
)}
|
|
1159
1458
|
{showWorkspaceFilter ? (
|
|
1160
1459
|
<FilterSelect
|
|
1161
1460
|
label="Workspace"
|
|
@@ -1167,7 +1466,7 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
|
|
|
1167
1466
|
) : null}
|
|
1168
1467
|
{showGroupFilter ? (
|
|
1169
1468
|
<FilterSelect
|
|
1170
|
-
label=
|
|
1469
|
+
label={groupLabel}
|
|
1171
1470
|
value={selectedGroupId}
|
|
1172
1471
|
options={groupOptions}
|
|
1173
1472
|
activeClasses="border-purple-500/30 bg-purple-500/10 text-purple-400"
|
|
@@ -1178,10 +1477,10 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
|
|
|
1178
1477
|
label="Sort"
|
|
1179
1478
|
value={sortBy}
|
|
1180
1479
|
options={[
|
|
1181
|
-
{ value: "activity", label: "
|
|
1480
|
+
{ value: "activity", label: "Updated At" },
|
|
1182
1481
|
{ value: "identifier", label: "Ticket ID" },
|
|
1183
1482
|
{ value: "status", label: "Status" },
|
|
1184
|
-
{ value: "created", label: "Created" },
|
|
1483
|
+
{ value: "created", label: "Created At" },
|
|
1185
1484
|
]}
|
|
1186
1485
|
activeClasses="border-sky-500/30 bg-sky-500/10 text-sky-400"
|
|
1187
1486
|
onChange={(value) => setSortBy(value as typeof sortBy)}
|
|
@@ -1194,17 +1493,6 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
|
|
|
1194
1493
|
>
|
|
1195
1494
|
{sortDir === "desc" ? <ArrowDown size={12} /> : <ArrowUp size={12} />}
|
|
1196
1495
|
</button>
|
|
1197
|
-
<button
|
|
1198
|
-
type="button"
|
|
1199
|
-
className={`flex items-center gap-1 rounded-full border px-2.5 py-1 text-[11px] font-medium transition-colors ${
|
|
1200
|
-
hasActivity
|
|
1201
|
-
? "border-orange-500/30 bg-orange-500/10 text-orange-400"
|
|
1202
|
-
: "border-[var(--card-border)] text-[var(--muted-foreground)] hover:bg-[var(--card-bg)]"
|
|
1203
|
-
}`}
|
|
1204
|
-
onClick={() => setHasActivity((v) => !v)}
|
|
1205
|
-
>
|
|
1206
|
-
My activity
|
|
1207
|
-
</button>
|
|
1208
1496
|
</div>
|
|
1209
1497
|
</div>
|
|
1210
1498
|
|
|
@@ -1219,31 +1507,90 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
|
|
|
1219
1507
|
</div>
|
|
1220
1508
|
) : (
|
|
1221
1509
|
<>
|
|
1222
|
-
{
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
<
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1510
|
+
{groupByStatus ? (
|
|
1511
|
+
statusGroups.map((sg) => {
|
|
1512
|
+
const collapsed = collapsedStatusGroups.has(sg.status);
|
|
1513
|
+
return (
|
|
1514
|
+
<React.Fragment key={`sg-${sg.status}`}>
|
|
1515
|
+
<StatusGroupRow
|
|
1516
|
+
status={sg.status}
|
|
1517
|
+
categoryColor={STATUS_CATEGORY_COLORS[sg.category] ?? "bg-zinc-400"}
|
|
1518
|
+
count={sg.items.length}
|
|
1519
|
+
collapsed={collapsed}
|
|
1520
|
+
onToggle={() =>
|
|
1521
|
+
setCollapsedStatusGroups((prev) => {
|
|
1522
|
+
const next = new Set(prev);
|
|
1523
|
+
if (next.has(sg.status)) next.delete(sg.status);
|
|
1524
|
+
else next.add(sg.status);
|
|
1525
|
+
return next;
|
|
1526
|
+
})
|
|
1527
|
+
}
|
|
1528
|
+
/>
|
|
1529
|
+
{!collapsed &&
|
|
1530
|
+
sg.items.map((item) => (
|
|
1531
|
+
<TicketRow
|
|
1532
|
+
key={item.id}
|
|
1533
|
+
item={item}
|
|
1534
|
+
selected={selectedItem?.id === item.id}
|
|
1535
|
+
pinned={pinnedItemIds.has(item.id)}
|
|
1536
|
+
activeAgents={issueActiveAgents.get(item.id)}
|
|
1537
|
+
participants={participants}
|
|
1538
|
+
projectSlug={projectSlug}
|
|
1539
|
+
stats={issueStats.get(item.id)}
|
|
1540
|
+
hideStatus
|
|
1541
|
+
estimate={metadataMap.get(item.id)?.estimate}
|
|
1542
|
+
localLabels={metadataMap.get(item.id)?.labels}
|
|
1543
|
+
labelDefinitions={labelDefinitions}
|
|
1544
|
+
allLabels={allLabels}
|
|
1545
|
+
onToggleLabel={(label) => handleItemToggleLabel(item.id, label)}
|
|
1546
|
+
onAddLabel={handleItemAddLabel}
|
|
1547
|
+
onSelect={() => {
|
|
1548
|
+
setTouchPanelTab("runs");
|
|
1549
|
+
pushSelection({
|
|
1550
|
+
issue: item.id,
|
|
1551
|
+
run: null,
|
|
1552
|
+
});
|
|
1553
|
+
}}
|
|
1554
|
+
onTogglePin={() => togglePin(item.id)}
|
|
1555
|
+
/>
|
|
1556
|
+
))}
|
|
1557
|
+
</React.Fragment>
|
|
1558
|
+
);
|
|
1559
|
+
})
|
|
1560
|
+
) : (
|
|
1561
|
+
labelFilteredItems.map((item, idx) => (
|
|
1562
|
+
<React.Fragment key={item.id}>
|
|
1563
|
+
{pinnedItemIds.size > 0 &&
|
|
1564
|
+
!pinnedItemIds.has(item.id) &&
|
|
1565
|
+
(idx === 0 || pinnedItemIds.has(labelFilteredItems[idx - 1].id)) && (
|
|
1566
|
+
<div className="mx-4 border-t border-amber-500/20" />
|
|
1567
|
+
)}
|
|
1568
|
+
<TicketRow
|
|
1569
|
+
item={item}
|
|
1570
|
+
selected={selectedItem?.id === item.id}
|
|
1571
|
+
pinned={pinnedItemIds.has(item.id)}
|
|
1572
|
+
activeAgents={issueActiveAgents.get(item.id)}
|
|
1573
|
+
participants={participants}
|
|
1574
|
+
projectSlug={projectSlug}
|
|
1575
|
+
stats={issueStats.get(item.id)}
|
|
1576
|
+
estimate={metadataMap.get(item.id)?.estimate}
|
|
1577
|
+
localLabels={metadataMap.get(item.id)?.labels}
|
|
1578
|
+
labelDefinitions={labelDefinitions}
|
|
1579
|
+
allLabels={allLabels}
|
|
1580
|
+
onToggleLabel={(label) => handleItemToggleLabel(item.id, label)}
|
|
1581
|
+
onAddLabel={handleItemAddLabel}
|
|
1582
|
+
onSelect={() => {
|
|
1583
|
+
setTouchPanelTab("runs");
|
|
1584
|
+
pushSelection({
|
|
1585
|
+
issue: item.id,
|
|
1586
|
+
run: null,
|
|
1587
|
+
});
|
|
1588
|
+
}}
|
|
1589
|
+
onTogglePin={() => togglePin(item.id)}
|
|
1590
|
+
/>
|
|
1591
|
+
</React.Fragment>
|
|
1592
|
+
))
|
|
1593
|
+
)}
|
|
1247
1594
|
{hasMore ? (
|
|
1248
1595
|
<div
|
|
1249
1596
|
ref={sentinelRef}
|
|
@@ -1488,6 +1835,16 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
|
|
|
1488
1835
|
onChange={setSelectedAssigneeIds}
|
|
1489
1836
|
emptyLabel="All assignees"
|
|
1490
1837
|
/>
|
|
1838
|
+
{labelFilterOptions.length > 0 && (
|
|
1839
|
+
<MultiFilterPopdown
|
|
1840
|
+
label="Label"
|
|
1841
|
+
values={selectedLabelNames}
|
|
1842
|
+
options={labelFilterOptions}
|
|
1843
|
+
activeClasses="border-pink-500/30 bg-pink-500/10 text-pink-400"
|
|
1844
|
+
onChange={setSelectedLabelNames}
|
|
1845
|
+
emptyLabel="All labels"
|
|
1846
|
+
/>
|
|
1847
|
+
)}
|
|
1491
1848
|
{showWorkspaceFilter ? (
|
|
1492
1849
|
<FilterSelect
|
|
1493
1850
|
label="Workspace"
|
|
@@ -1499,7 +1856,7 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
|
|
|
1499
1856
|
) : null}
|
|
1500
1857
|
{showGroupFilter ? (
|
|
1501
1858
|
<FilterSelect
|
|
1502
|
-
label=
|
|
1859
|
+
label={groupLabel}
|
|
1503
1860
|
value={selectedGroupId}
|
|
1504
1861
|
options={groupOptions}
|
|
1505
1862
|
activeClasses="border-purple-500/30 bg-purple-500/10 text-purple-400"
|
|
@@ -1510,10 +1867,10 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
|
|
|
1510
1867
|
label="Sort"
|
|
1511
1868
|
value={sortBy}
|
|
1512
1869
|
options={[
|
|
1513
|
-
{ value: "activity", label: "
|
|
1870
|
+
{ value: "activity", label: "Updated At" },
|
|
1514
1871
|
{ value: "identifier", label: "Ticket ID" },
|
|
1515
1872
|
{ value: "status", label: "Status" },
|
|
1516
|
-
{ value: "created", label: "Created" },
|
|
1873
|
+
{ value: "created", label: "Created At" },
|
|
1517
1874
|
]}
|
|
1518
1875
|
activeClasses="border-sky-500/30 bg-sky-500/10 text-sky-400"
|
|
1519
1876
|
onChange={(value) => setSortBy(value as typeof sortBy)}
|
|
@@ -1526,17 +1883,6 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
|
|
|
1526
1883
|
>
|
|
1527
1884
|
{sortDir === "desc" ? <ArrowDown size={12} /> : <ArrowUp size={12} />}
|
|
1528
1885
|
</button>
|
|
1529
|
-
<button
|
|
1530
|
-
type="button"
|
|
1531
|
-
className={`flex items-center gap-1 rounded-full border px-2.5 py-0.5 text-[11px] font-medium transition-colors ${
|
|
1532
|
-
hasActivity
|
|
1533
|
-
? "border-orange-500/30 bg-orange-500/10 text-orange-400"
|
|
1534
|
-
: "border-[var(--card-border)] text-[var(--muted-foreground)] hover:bg-[var(--card-bg)]"
|
|
1535
|
-
}`}
|
|
1536
|
-
onClick={() => setHasActivity((v) => !v)}
|
|
1537
|
-
>
|
|
1538
|
-
My activity
|
|
1539
|
-
</button>
|
|
1540
1886
|
</div>
|
|
1541
1887
|
</div>
|
|
1542
1888
|
|
|
@@ -1557,33 +1903,188 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
|
|
|
1557
1903
|
</div>
|
|
1558
1904
|
) : (
|
|
1559
1905
|
<>
|
|
1560
|
-
{
|
|
1561
|
-
|
|
1906
|
+
{groupByStatus ? (
|
|
1907
|
+
/* ── Status-grouped view ── */
|
|
1908
|
+
statusGroups.map((sg) => {
|
|
1909
|
+
const collapsed = collapsedStatusGroups.has(sg.status);
|
|
1910
|
+
return (
|
|
1911
|
+
<React.Fragment key={`sg-${sg.status}`}>
|
|
1912
|
+
<StatusGroupRow
|
|
1913
|
+
status={sg.status}
|
|
1914
|
+
categoryColor={STATUS_CATEGORY_COLORS[sg.category] ?? "bg-zinc-400"}
|
|
1915
|
+
count={sg.items.length}
|
|
1916
|
+
collapsed={collapsed}
|
|
1917
|
+
onToggle={() =>
|
|
1918
|
+
setCollapsedStatusGroups((prev) => {
|
|
1919
|
+
const next = new Set(prev);
|
|
1920
|
+
if (next.has(sg.status)) next.delete(sg.status);
|
|
1921
|
+
else next.add(sg.status);
|
|
1922
|
+
return next;
|
|
1923
|
+
})
|
|
1924
|
+
}
|
|
1925
|
+
/>
|
|
1926
|
+
{!collapsed && (() => {
|
|
1927
|
+
const pendingSet = showGroupNamePrompt ? new Set(pendingGroupTaskIds) : null;
|
|
1928
|
+
const firstMemberToGroup = new Map<string, typeof taskGroups[number]>();
|
|
1929
|
+
for (const group of taskGroups) {
|
|
1930
|
+
const firstInStatus = sg.items.find((i) => group.task_ids.includes(i.id));
|
|
1931
|
+
if (firstInStatus) firstMemberToGroup.set(firstInStatus.id, group);
|
|
1932
|
+
}
|
|
1933
|
+
const pendingTickets = showGroupNamePrompt
|
|
1934
|
+
? pendingGroupTaskIds
|
|
1935
|
+
.map((id) => sg.items.find((i) => i.id === id))
|
|
1936
|
+
.filter(Boolean)
|
|
1937
|
+
.map((i) => ({ id: i!.id, identifier: i!.identifier, title: i!.title, status: STATUS_LABELS[i!.status] ?? i!.status }))
|
|
1938
|
+
: [];
|
|
1939
|
+
const renderedGroups = new Set<string>();
|
|
1940
|
+
|
|
1941
|
+
return sg.items.map((item) => {
|
|
1942
|
+
if (pendingSet?.has(item.id)) {
|
|
1943
|
+
if (item.id === pendingGroupTargetId && showGroupNamePrompt) {
|
|
1944
|
+
return (
|
|
1945
|
+
<GroupNamePrompt
|
|
1946
|
+
key="__pending-group__"
|
|
1947
|
+
tickets={pendingTickets}
|
|
1948
|
+
onConfirm={handleCreateGroup}
|
|
1949
|
+
onCancel={() => {
|
|
1950
|
+
setShowGroupNamePrompt(false);
|
|
1951
|
+
setPendingGroupTaskIds([]);
|
|
1952
|
+
setPendingGroupTargetId(null);
|
|
1953
|
+
}}
|
|
1954
|
+
/>
|
|
1955
|
+
);
|
|
1956
|
+
}
|
|
1957
|
+
return null;
|
|
1958
|
+
}
|
|
1959
|
+
|
|
1960
|
+
const group = firstMemberToGroup.get(item.id);
|
|
1961
|
+
if (group && !renderedGroups.has(group.id)) {
|
|
1962
|
+
renderedGroups.add(group.id);
|
|
1963
|
+
const groupItems = group.task_ids
|
|
1964
|
+
.map((id) => sg.items.find((i) => i.id === id))
|
|
1965
|
+
.filter(Boolean) as TrackerItem[];
|
|
1966
|
+
return (
|
|
1967
|
+
<React.Fragment key={`group-${group.id}`}>
|
|
1968
|
+
<FolderRow
|
|
1969
|
+
groupId={group.id}
|
|
1970
|
+
name={group.name}
|
|
1971
|
+
count={groupItems.length}
|
|
1972
|
+
collapsed={!!group.collapsed}
|
|
1973
|
+
selected={selectedGroupTaskGroupId === group.id}
|
|
1974
|
+
projectSlug={projectSlug}
|
|
1975
|
+
onToggleCollapse={() => updateGroup(group.id, { collapsed: !group.collapsed })}
|
|
1976
|
+
onSelect={() => pushSelection({ group: group.id, issue: null, run: null })}
|
|
1977
|
+
onUngroup={() => {
|
|
1978
|
+
void deleteGroup(group.id);
|
|
1979
|
+
if (selectedGroupTaskGroupId === group.id) {
|
|
1980
|
+
replaceSelection({ group: null });
|
|
1981
|
+
}
|
|
1982
|
+
}}
|
|
1983
|
+
/>
|
|
1984
|
+
{!group.collapsed &&
|
|
1985
|
+
groupItems.map((gi, giIdx) => (
|
|
1986
|
+
<TicketRow
|
|
1987
|
+
key={gi.id}
|
|
1988
|
+
item={gi}
|
|
1989
|
+
selected={selectedItem?.id === gi.id}
|
|
1990
|
+
pinned={pinnedItemIds.has(gi.id)}
|
|
1991
|
+
activeAgents={issueActiveAgents.get(gi.id)}
|
|
1992
|
+
participants={participants}
|
|
1993
|
+
draggable
|
|
1994
|
+
multiSelected={multiSelectedItemIds.has(gi.id)}
|
|
1995
|
+
treeConnector={giIdx === groupItems.length - 1 ? "last" : "mid"}
|
|
1996
|
+
projectSlug={projectSlug}
|
|
1997
|
+
stats={issueStats.get(gi.id)}
|
|
1998
|
+
hideStatus
|
|
1999
|
+
estimate={metadataMap.get(gi.id)?.estimate}
|
|
2000
|
+
localLabels={metadataMap.get(gi.id)?.labels}
|
|
2001
|
+
labelDefinitions={labelDefinitions}
|
|
2002
|
+
allLabels={allLabels}
|
|
2003
|
+
onToggleLabel={(label) => handleItemToggleLabel(gi.id, label)}
|
|
2004
|
+
onAddLabel={handleItemAddLabel}
|
|
2005
|
+
onSelect={(event) => {
|
|
2006
|
+
if (event && (event.metaKey || event.ctrlKey)) {
|
|
2007
|
+
toggleItemMultiSelect(gi.id);
|
|
2008
|
+
} else {
|
|
2009
|
+
pushSelection({
|
|
2010
|
+
issue: gi.id,
|
|
2011
|
+
run: null,
|
|
2012
|
+
group: null,
|
|
2013
|
+
});
|
|
2014
|
+
}
|
|
2015
|
+
}}
|
|
2016
|
+
onTogglePin={() => togglePin(gi.id)}
|
|
2017
|
+
/>
|
|
2018
|
+
))}
|
|
2019
|
+
</React.Fragment>
|
|
2020
|
+
);
|
|
2021
|
+
}
|
|
2022
|
+
|
|
2023
|
+
if (groupedItemIds.has(item.id)) {
|
|
2024
|
+
return null;
|
|
2025
|
+
}
|
|
2026
|
+
|
|
2027
|
+
return (
|
|
2028
|
+
<TicketRow
|
|
2029
|
+
key={item.id}
|
|
2030
|
+
item={item}
|
|
2031
|
+
selected={selectedItem?.id === item.id}
|
|
2032
|
+
pinned={pinnedItemIds.has(item.id)}
|
|
2033
|
+
activeAgents={issueActiveAgents.get(item.id)}
|
|
2034
|
+
participants={participants}
|
|
2035
|
+
draggable
|
|
2036
|
+
multiSelected={multiSelectedItemIds.has(item.id)}
|
|
2037
|
+
projectSlug={projectSlug}
|
|
2038
|
+
stats={issueStats.get(item.id)}
|
|
2039
|
+
hideStatus
|
|
2040
|
+
estimate={metadataMap.get(item.id)?.estimate}
|
|
2041
|
+
localLabels={metadataMap.get(item.id)?.labels}
|
|
2042
|
+
labelDefinitions={labelDefinitions}
|
|
2043
|
+
allLabels={allLabels}
|
|
2044
|
+
onToggleLabel={(label) => handleItemToggleLabel(item.id, label)}
|
|
2045
|
+
onAddLabel={handleItemAddLabel}
|
|
2046
|
+
onSelect={(event) => {
|
|
2047
|
+
if (event && (event.metaKey || event.ctrlKey)) {
|
|
2048
|
+
toggleItemMultiSelect(item.id);
|
|
2049
|
+
} else {
|
|
2050
|
+
pushSelection({
|
|
2051
|
+
issue: item.id,
|
|
2052
|
+
run: null,
|
|
2053
|
+
group: null,
|
|
2054
|
+
});
|
|
2055
|
+
}
|
|
2056
|
+
}}
|
|
2057
|
+
onTogglePin={() => togglePin(item.id)}
|
|
2058
|
+
/>
|
|
2059
|
+
);
|
|
2060
|
+
});
|
|
2061
|
+
})()}
|
|
2062
|
+
</React.Fragment>
|
|
2063
|
+
);
|
|
2064
|
+
})
|
|
2065
|
+
) : (
|
|
2066
|
+
/* ── Flat/folder view ── */
|
|
2067
|
+
(() => {
|
|
1562
2068
|
const pendingSet = showGroupNamePrompt ? new Set(pendingGroupTaskIds) : null;
|
|
1563
2069
|
|
|
1564
|
-
// Build a map: itemId → group (for the first member of each group)
|
|
1565
2070
|
const firstMemberToGroup = new Map<string, typeof taskGroups[number]>();
|
|
1566
2071
|
for (const group of taskGroups) {
|
|
1567
|
-
const firstInSort =
|
|
2072
|
+
const firstInSort = labelFilteredItems.find((i) => group.task_ids.includes(i.id));
|
|
1568
2073
|
if (firstInSort) firstMemberToGroup.set(firstInSort.id, group);
|
|
1569
2074
|
}
|
|
1570
2075
|
|
|
1571
|
-
// Pending group prompt: find insert position
|
|
1572
2076
|
const pendingTickets = showGroupNamePrompt
|
|
1573
2077
|
? pendingGroupTaskIds
|
|
1574
|
-
.map((id) =>
|
|
2078
|
+
.map((id) => labelFilteredItems.find((i) => i.id === id))
|
|
1575
2079
|
.filter(Boolean)
|
|
1576
2080
|
.map((i) => ({ id: i!.id, identifier: i!.identifier, title: i!.title, status: STATUS_LABELS[i!.status] ?? i!.status }))
|
|
1577
2081
|
: [];
|
|
1578
2082
|
|
|
1579
|
-
// Track which groups we've rendered
|
|
1580
2083
|
const renderedGroups = new Set<string>();
|
|
1581
2084
|
let looseIdx = 0;
|
|
1582
2085
|
|
|
1583
|
-
return
|
|
1584
|
-
// Skip pending tickets
|
|
2086
|
+
return labelFilteredItems.map((item) => {
|
|
1585
2087
|
if (pendingSet?.has(item.id)) {
|
|
1586
|
-
// Render prompt at target position
|
|
1587
2088
|
if (item.id === pendingGroupTargetId && showGroupNamePrompt) {
|
|
1588
2089
|
return (
|
|
1589
2090
|
<GroupNamePrompt
|
|
@@ -1601,12 +2102,11 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
|
|
|
1601
2102
|
return null;
|
|
1602
2103
|
}
|
|
1603
2104
|
|
|
1604
|
-
// If this item is the first member of a group, render the group here
|
|
1605
2105
|
const group = firstMemberToGroup.get(item.id);
|
|
1606
2106
|
if (group && !renderedGroups.has(group.id)) {
|
|
1607
2107
|
renderedGroups.add(group.id);
|
|
1608
2108
|
const groupItems = group.task_ids
|
|
1609
|
-
.map((id) =>
|
|
2109
|
+
.map((id) => labelFilteredItems.find((i) => i.id === id))
|
|
1610
2110
|
.filter(Boolean) as TrackerItem[];
|
|
1611
2111
|
return (
|
|
1612
2112
|
<React.Fragment key={`group-${group.id}`}>
|
|
@@ -1643,6 +2143,13 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
|
|
|
1643
2143
|
multiSelected={multiSelectedItemIds.has(gi.id)}
|
|
1644
2144
|
treeConnector={giIdx === groupItems.length - 1 ? "last" : "mid"}
|
|
1645
2145
|
projectSlug={projectSlug}
|
|
2146
|
+
stats={issueStats.get(gi.id)}
|
|
2147
|
+
estimate={metadataMap.get(gi.id)?.estimate}
|
|
2148
|
+
localLabels={metadataMap.get(gi.id)?.labels}
|
|
2149
|
+
labelDefinitions={labelDefinitions}
|
|
2150
|
+
allLabels={allLabels}
|
|
2151
|
+
onToggleLabel={(label) => handleItemToggleLabel(gi.id, label)}
|
|
2152
|
+
onAddLabel={handleItemAddLabel}
|
|
1646
2153
|
onSelect={(event) => {
|
|
1647
2154
|
if (event && (event.metaKey || event.ctrlKey)) {
|
|
1648
2155
|
toggleItemMultiSelect(gi.id);
|
|
@@ -1661,13 +2168,11 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
|
|
|
1661
2168
|
);
|
|
1662
2169
|
}
|
|
1663
2170
|
|
|
1664
|
-
// Skip grouped items (already rendered with their group)
|
|
1665
2171
|
if (groupedItemIds.has(item.id)) return null;
|
|
1666
2172
|
|
|
1667
|
-
// Loose ticket
|
|
1668
2173
|
const currentLooseIdx = looseIdx++;
|
|
1669
2174
|
const prevLoose = currentLooseIdx > 0
|
|
1670
|
-
?
|
|
2175
|
+
? labelFilteredItems.filter((i) => !groupedItemIds.has(i.id) && (!pendingSet || !pendingSet.has(i.id)))[currentLooseIdx - 1]
|
|
1671
2176
|
: null;
|
|
1672
2177
|
return (
|
|
1673
2178
|
<React.Fragment key={item.id}>
|
|
@@ -1685,6 +2190,13 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
|
|
|
1685
2190
|
draggable
|
|
1686
2191
|
multiSelected={multiSelectedItemIds.has(item.id)}
|
|
1687
2192
|
projectSlug={projectSlug}
|
|
2193
|
+
stats={issueStats.get(item.id)}
|
|
2194
|
+
estimate={metadataMap.get(item.id)?.estimate}
|
|
2195
|
+
localLabels={metadataMap.get(item.id)?.labels}
|
|
2196
|
+
labelDefinitions={labelDefinitions}
|
|
2197
|
+
allLabels={allLabels}
|
|
2198
|
+
onToggleLabel={(label) => handleItemToggleLabel(item.id, label)}
|
|
2199
|
+
onAddLabel={handleItemAddLabel}
|
|
1688
2200
|
onSelect={(event) => {
|
|
1689
2201
|
if (event && (event.metaKey || event.ctrlKey)) {
|
|
1690
2202
|
toggleItemMultiSelect(item.id);
|
|
@@ -1701,7 +2213,7 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
|
|
|
1701
2213
|
</React.Fragment>
|
|
1702
2214
|
);
|
|
1703
2215
|
});
|
|
1704
|
-
})()}
|
|
2216
|
+
})())}
|
|
1705
2217
|
{hasMore ? (
|
|
1706
2218
|
<div
|
|
1707
2219
|
ref={sentinelRef}
|
|
@@ -1716,11 +2228,23 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
|
|
|
1716
2228
|
count={multiSelectedItemIds.size}
|
|
1717
2229
|
onGroup={handleMultiSelectGroup}
|
|
1718
2230
|
onClear={() => setMultiSelectedItemIds(new Set())}
|
|
2231
|
+
onBulkRecap={handleBulkRecap}
|
|
2232
|
+
onBulkPrompt={handleBulkPrompt}
|
|
2233
|
+
onBulkEstimate={handleBulkEstimate}
|
|
2234
|
+
onBulkAddLabel={handleBulkAddLabel}
|
|
2235
|
+
onBulkRemoveLabel={handleBulkRemoveLabel}
|
|
2236
|
+
onBulkStatus={handleBulkStatus}
|
|
2237
|
+
statusOptions={itemStatusOptions}
|
|
2238
|
+
participants={participants}
|
|
2239
|
+
labels={allLabels}
|
|
2240
|
+
onCreateLabel={handleCreateLabel}
|
|
2241
|
+
selectedMetadata={selectedMetadata}
|
|
2242
|
+
statusUpdating={bulkStatusUpdating}
|
|
1719
2243
|
/>
|
|
1720
2244
|
</div>
|
|
1721
2245
|
<DragOverlay dropAnimation={null}>
|
|
1722
2246
|
{dragActiveId && (() => {
|
|
1723
|
-
const dragItem =
|
|
2247
|
+
const dragItem = sortedItemsRef.current.find((i) => i.id === dragActiveId);
|
|
1724
2248
|
if (!dragItem) return null;
|
|
1725
2249
|
return (
|
|
1726
2250
|
<div className="flex items-center gap-3 rounded-lg border border-[var(--primary)]/30 bg-[var(--card-bg)] px-4 py-2.5 text-sm shadow-xl backdrop-blur-sm">
|
|
@@ -1737,7 +2261,7 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
|
|
|
1737
2261
|
</DndContext>
|
|
1738
2262
|
</div>
|
|
1739
2263
|
|
|
1740
|
-
<ResizeHandle onResize={(delta) => setTicketPanelWidth((w) => { const next = Math.max(
|
|
2264
|
+
<ResizeHandle onResize={(delta) => setTicketPanelWidth((w) => { const next = Math.max(280, Math.min(960, w + delta)); persistLinearTicketPanelWidth(next); return next; })} />
|
|
1741
2265
|
|
|
1742
2266
|
{showRunScripts ? (
|
|
1743
2267
|
<div
|