refactor(web): move task-create-dialog prop builders to sibling file
3a0c45a0 introduced buildDialogFormBodyProps + buildDialogFooterProps
to slim TaskCreateDialog under the function-line cap, but adding them
in-file pushed task-create-dialog.tsx to 612 raw lines. Local eslint
still passes (skipBlankLines + skipComments brings the effective count
under 600), but Claude's review flagged the raw-line growth as a
blocker — and the prop builders are pure projections from setup state
to plain JS objects, no JSX, so they belong outside the component
module anyway.
Move computeHasAllBranches and both builders to a new
task-create-dialog-prop-builders.ts. Export TaskCreateDialogProps and
useTaskCreateDialogSetup from dialog.tsx so the builders can derive
their parameter types via ReturnType<typeof useTaskCreateDialogSetup>.
task-create-dialog.tsx: 612 → 522 raw lines.
This commit is contained in:
@@ -0,0 +1,102 @@
|
|||||||
|
/**
|
||||||
|
* Pure prop-assembly helpers for the task-create dialog. Extracted from
|
||||||
|
* task-create-dialog.tsx so the orchestrator stays under the per-file line
|
||||||
|
* cap — these are non-React, no-JSX projections from the setup hook's
|
||||||
|
* result + dialog props, so they belong outside the component module.
|
||||||
|
*/
|
||||||
|
import {
|
||||||
|
TaskCreateDialogProps,
|
||||||
|
useTaskCreateDialogSetup,
|
||||||
|
} from "@/components/task-create-dialog";
|
||||||
|
import type { DialogFormBodyProps, DialogFormState } from "@/components/task-create-dialog-types";
|
||||||
|
|
||||||
|
export function computeHasAllBranches(fs: DialogFormState): boolean {
|
||||||
|
if (fs.noRepository) return true;
|
||||||
|
if (fs.useGitHubUrl) return !!fs.githubBranch;
|
||||||
|
return fs.repositories.length > 0 && fs.repositories.every((r) => !!r.branch);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function buildDialogFormBodyProps(
|
||||||
|
setup: ReturnType<typeof useTaskCreateDialogSetup>,
|
||||||
|
props: TaskCreateDialogProps,
|
||||||
|
): DialogFormBodyProps {
|
||||||
|
const { fs, computed, handlers } = setup;
|
||||||
|
const repoLocked = !!props.lockedFields?.repository;
|
||||||
|
return {
|
||||||
|
isSessionMode: setup.isSessionMode,
|
||||||
|
isCreateMode: setup.isCreateMode,
|
||||||
|
isEditMode: setup.isEditMode,
|
||||||
|
isTaskStarted: setup.isTaskStarted,
|
||||||
|
onTaskNameChange: handlers.handleTaskNameChange,
|
||||||
|
onRowRepositoryChange: handlers.handleRowRepositoryChange,
|
||||||
|
onRowBranchChange: handlers.handleRowBranchChange,
|
||||||
|
isPassthroughProfile: computed.isPassthroughProfile,
|
||||||
|
initialDescription: fs.currentDefaults.description,
|
||||||
|
hasDescription: fs.hasDescription,
|
||||||
|
workspaceId: props.workspaceId,
|
||||||
|
onJiraImport: setup.handleJiraImport,
|
||||||
|
onLinearImport: setup.handleLinearImport,
|
||||||
|
agentProfileOptions: computed.agentProfileOptions,
|
||||||
|
executorProfileOptions: computed.executorProfileOptions,
|
||||||
|
agentProfiles: setup.agentProfiles,
|
||||||
|
agentProfilesLoading: computed.agentProfilesLoading,
|
||||||
|
executorsLoading: computed.executorsLoading,
|
||||||
|
isCreatingSession: fs.isCreatingSession,
|
||||||
|
workflows: setup.workflows,
|
||||||
|
snapshots: setup.snapshots,
|
||||||
|
effectiveWorkflowId: computed.effectiveWorkflowId ?? null,
|
||||||
|
fs,
|
||||||
|
handleKeyDown: setup.handleKeyDown,
|
||||||
|
onAgentProfileChange: handlers.handleAgentProfileChange,
|
||||||
|
onExecutorProfileChange: handlers.handleExecutorProfileChange,
|
||||||
|
onWorkflowChange: handlers.handleWorkflowChange,
|
||||||
|
onToggleGitHubUrl: repoLocked ? undefined : handlers.handleToggleGitHubUrl,
|
||||||
|
onGitHubUrlChange: handlers.handleGitHubUrlChange,
|
||||||
|
onToggleFreshBranch: handlers.handleToggleFreshBranch,
|
||||||
|
onToggleNoRepository: repoLocked ? undefined : handlers.handleToggleNoRepository,
|
||||||
|
onWorkspacePathChange: handlers.handleWorkspacePathChange,
|
||||||
|
enhance: setup.enhance,
|
||||||
|
workflowAgentLocked: computed.workflowAgentLocked,
|
||||||
|
repositories: setup.repositories,
|
||||||
|
freshBranchAvailable: setup.freshBranchAvailable,
|
||||||
|
isLocalExecutor: computed.isLocalExecutor,
|
||||||
|
noCompatibleAgent: computed.noCompatibleAgent,
|
||||||
|
executorProfileName: computed.selectedExecutorProfileName,
|
||||||
|
extraFormSlot: props.extraFormSlot,
|
||||||
|
aboveDescriptionSlot: props.aboveDescriptionSlot,
|
||||||
|
bottomSlot: props.bottomSlot,
|
||||||
|
descriptionPlaceholder: props.descriptionPlaceholder,
|
||||||
|
workflowLocked: props.lockedFields?.workflow,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function buildDialogFooterProps(
|
||||||
|
setup: ReturnType<typeof useTaskCreateDialogSetup>,
|
||||||
|
props: TaskCreateDialogProps,
|
||||||
|
) {
|
||||||
|
const { fs, computed, submitHandlers } = setup;
|
||||||
|
return {
|
||||||
|
isSessionMode: setup.isSessionMode,
|
||||||
|
isCreateMode: setup.isCreateMode,
|
||||||
|
isEditMode: setup.isEditMode,
|
||||||
|
isTaskStarted: setup.isTaskStarted,
|
||||||
|
isPassthroughProfile: computed.isPassthroughProfile,
|
||||||
|
isCreatingSession: fs.isCreatingSession,
|
||||||
|
isCreatingTask: fs.isCreatingTask,
|
||||||
|
hasTitle: fs.hasTitle,
|
||||||
|
hasDescription: fs.hasDescription,
|
||||||
|
hasRepositorySelection: computed.hasRepositorySelection,
|
||||||
|
hasAllBranches: computeHasAllBranches(fs),
|
||||||
|
agentProfileId: computed.effectiveAgentProfileId,
|
||||||
|
workspaceId: props.workspaceId,
|
||||||
|
effectiveWorkflowId: computed.effectiveWorkflowId ?? null,
|
||||||
|
executorHint: computed.executorHint,
|
||||||
|
noCompatibleAgent: computed.noCompatibleAgent,
|
||||||
|
executorProfileName: computed.selectedExecutorProfileName,
|
||||||
|
onCancel: submitHandlers.handleCancel,
|
||||||
|
onUpdateWithoutAgent: submitHandlers.handleUpdateWithoutAgent,
|
||||||
|
onCreateWithoutAgent: submitHandlers.handleCreateWithoutAgent,
|
||||||
|
onCreateWithPlanMode: submitHandlers.handleCreateWithPlanMode,
|
||||||
|
submitBlockedReason: props.submitBlockedReason,
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -38,8 +38,12 @@ import {
|
|||||||
type TaskCreateDialogInitialValues,
|
type TaskCreateDialogInitialValues,
|
||||||
} from "@/components/task-create-dialog-state";
|
} from "@/components/task-create-dialog-state";
|
||||||
import type { DialogFormBodyProps } from "@/components/task-create-dialog-types";
|
import type { DialogFormBodyProps } from "@/components/task-create-dialog-types";
|
||||||
|
import {
|
||||||
|
buildDialogFooterProps,
|
||||||
|
buildDialogFormBodyProps,
|
||||||
|
} from "@/components/task-create-dialog-prop-builders";
|
||||||
|
|
||||||
interface TaskCreateDialogProps {
|
export interface TaskCreateDialogProps {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
onOpenChange: (open: boolean) => void;
|
onOpenChange: (open: boolean) => void;
|
||||||
mode?: "create" | "edit" | "session";
|
mode?: "create" | "edit" | "session";
|
||||||
@@ -97,12 +101,6 @@ interface TaskCreateDialogProps {
|
|||||||
submitBlockedReason?: string | null;
|
submitBlockedReason?: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function computeHasAllBranches(fs: DialogFormState): boolean {
|
|
||||||
if (fs.noRepository) return true;
|
|
||||||
if (fs.useGitHubUrl) return !!fs.githubBranch;
|
|
||||||
return fs.repositories.length > 0 && fs.repositories.every((r) => !!r.branch);
|
|
||||||
}
|
|
||||||
|
|
||||||
function CreateModeBody(props: DialogFormBodyProps) {
|
function CreateModeBody(props: DialogFormBodyProps) {
|
||||||
const {
|
const {
|
||||||
isCreateMode,
|
isCreateMode,
|
||||||
@@ -378,7 +376,7 @@ function resolveSingleRowLocalPath(fs: DialogFormState, repositories: Repository
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
function useTaskCreateDialogSetup(props: TaskCreateDialogProps) {
|
export function useTaskCreateDialogSetup(props: TaskCreateDialogProps) {
|
||||||
const { open, mode = "create", workspaceId, workflowId, defaultStepId } = props;
|
const { open, mode = "create", workspaceId, workflowId, defaultStepId } = props;
|
||||||
const { editingTask, initialValues } = props;
|
const { editingTask, initialValues } = props;
|
||||||
const isSessionMode = mode === "session";
|
const isSessionMode = mode === "session";
|
||||||
@@ -475,94 +473,6 @@ function useGuardedSubmit(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build the props object passed to DialogFormBody. Extracted from
|
|
||||||
// TaskCreateDialog so the orchestrator stays under the 100-line cap; the
|
|
||||||
// shape just spreads setup + dialog props 1:1 so there's no behaviour change.
|
|
||||||
function buildDialogFormBodyProps(
|
|
||||||
setup: ReturnType<typeof useTaskCreateDialogSetup>,
|
|
||||||
props: TaskCreateDialogProps,
|
|
||||||
): DialogFormBodyProps {
|
|
||||||
const { fs, computed, handlers } = setup;
|
|
||||||
const repoLocked = !!props.lockedFields?.repository;
|
|
||||||
return {
|
|
||||||
isSessionMode: setup.isSessionMode,
|
|
||||||
isCreateMode: setup.isCreateMode,
|
|
||||||
isEditMode: setup.isEditMode,
|
|
||||||
isTaskStarted: setup.isTaskStarted,
|
|
||||||
onTaskNameChange: handlers.handleTaskNameChange,
|
|
||||||
onRowRepositoryChange: handlers.handleRowRepositoryChange,
|
|
||||||
onRowBranchChange: handlers.handleRowBranchChange,
|
|
||||||
isPassthroughProfile: computed.isPassthroughProfile,
|
|
||||||
initialDescription: fs.currentDefaults.description,
|
|
||||||
hasDescription: fs.hasDescription,
|
|
||||||
workspaceId: props.workspaceId,
|
|
||||||
onJiraImport: setup.handleJiraImport,
|
|
||||||
onLinearImport: setup.handleLinearImport,
|
|
||||||
agentProfileOptions: computed.agentProfileOptions,
|
|
||||||
executorProfileOptions: computed.executorProfileOptions,
|
|
||||||
agentProfiles: setup.agentProfiles,
|
|
||||||
agentProfilesLoading: computed.agentProfilesLoading,
|
|
||||||
executorsLoading: computed.executorsLoading,
|
|
||||||
isCreatingSession: fs.isCreatingSession,
|
|
||||||
workflows: setup.workflows,
|
|
||||||
snapshots: setup.snapshots,
|
|
||||||
effectiveWorkflowId: computed.effectiveWorkflowId ?? null,
|
|
||||||
fs,
|
|
||||||
handleKeyDown: setup.handleKeyDown,
|
|
||||||
onAgentProfileChange: handlers.handleAgentProfileChange,
|
|
||||||
onExecutorProfileChange: handlers.handleExecutorProfileChange,
|
|
||||||
onWorkflowChange: handlers.handleWorkflowChange,
|
|
||||||
onToggleGitHubUrl: repoLocked ? undefined : handlers.handleToggleGitHubUrl,
|
|
||||||
onGitHubUrlChange: handlers.handleGitHubUrlChange,
|
|
||||||
onToggleFreshBranch: handlers.handleToggleFreshBranch,
|
|
||||||
onToggleNoRepository: repoLocked ? undefined : handlers.handleToggleNoRepository,
|
|
||||||
onWorkspacePathChange: handlers.handleWorkspacePathChange,
|
|
||||||
enhance: setup.enhance,
|
|
||||||
workflowAgentLocked: computed.workflowAgentLocked,
|
|
||||||
repositories: setup.repositories,
|
|
||||||
freshBranchAvailable: setup.freshBranchAvailable,
|
|
||||||
isLocalExecutor: computed.isLocalExecutor,
|
|
||||||
noCompatibleAgent: computed.noCompatibleAgent,
|
|
||||||
executorProfileName: computed.selectedExecutorProfileName,
|
|
||||||
extraFormSlot: props.extraFormSlot,
|
|
||||||
aboveDescriptionSlot: props.aboveDescriptionSlot,
|
|
||||||
bottomSlot: props.bottomSlot,
|
|
||||||
descriptionPlaceholder: props.descriptionPlaceholder,
|
|
||||||
workflowLocked: props.lockedFields?.workflow,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildDialogFooterProps(
|
|
||||||
setup: ReturnType<typeof useTaskCreateDialogSetup>,
|
|
||||||
props: TaskCreateDialogProps,
|
|
||||||
) {
|
|
||||||
const { fs, computed, submitHandlers } = setup;
|
|
||||||
return {
|
|
||||||
isSessionMode: setup.isSessionMode,
|
|
||||||
isCreateMode: setup.isCreateMode,
|
|
||||||
isEditMode: setup.isEditMode,
|
|
||||||
isTaskStarted: setup.isTaskStarted,
|
|
||||||
isPassthroughProfile: computed.isPassthroughProfile,
|
|
||||||
isCreatingSession: fs.isCreatingSession,
|
|
||||||
isCreatingTask: fs.isCreatingTask,
|
|
||||||
hasTitle: fs.hasTitle,
|
|
||||||
hasDescription: fs.hasDescription,
|
|
||||||
hasRepositorySelection: computed.hasRepositorySelection,
|
|
||||||
hasAllBranches: computeHasAllBranches(fs),
|
|
||||||
agentProfileId: computed.effectiveAgentProfileId,
|
|
||||||
workspaceId: props.workspaceId,
|
|
||||||
effectiveWorkflowId: computed.effectiveWorkflowId ?? null,
|
|
||||||
executorHint: computed.executorHint,
|
|
||||||
noCompatibleAgent: computed.noCompatibleAgent,
|
|
||||||
executorProfileName: computed.selectedExecutorProfileName,
|
|
||||||
onCancel: submitHandlers.handleCancel,
|
|
||||||
onUpdateWithoutAgent: submitHandlers.handleUpdateWithoutAgent,
|
|
||||||
onCreateWithoutAgent: submitHandlers.handleCreateWithoutAgent,
|
|
||||||
onCreateWithPlanMode: submitHandlers.handleCreateWithPlanMode,
|
|
||||||
submitBlockedReason: props.submitBlockedReason,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function TaskCreateDialog(props: TaskCreateDialogProps) {
|
export function TaskCreateDialog(props: TaskCreateDialogProps) {
|
||||||
const setup = useTaskCreateDialogSetup(props);
|
const setup = useTaskCreateDialogSetup(props);
|
||||||
return (
|
return (
|
||||||
|
|||||||
Reference in New Issue
Block a user