Skip to content

Commit f1479be

Browse files
committed
AXON-762: refactoring: move start work logic to a separate hook
1 parent 623ab00 commit f1479be

File tree

2 files changed

+184
-174
lines changed

2 files changed

+184
-174
lines changed

src/react/atlascode/startwork/v3/StartWorkPageV3.tsx

Lines changed: 13 additions & 174 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,8 @@
1-
import { emptyTransition, Transition } from '@atlassianlabs/jira-pi-common-models';
21
import { Box, Button, CircularProgress, Typography } from '@material-ui/core';
3-
import React, { useCallback, useContext, useEffect, useState } from 'react';
2+
import React from 'react';
43
import { AnalyticsView } from 'src/analyticsTypes';
54

6-
import { StartWorkActionType } from '../../../../lib/ipc/fromUI/startWork';
7-
import { RepoData } from '../../../../lib/ipc/toUI/startWork';
8-
import { Branch } from '../../../../typings/git';
95
import { AtlascodeErrorBoundary } from '../../common/ErrorBoundary';
10-
import { ErrorControllerContext } from '../../common/errorController';
116
import { ErrorDisplay } from '../../common/ErrorDisplay';
127
import { StartWorkControllerContext, useStartWorkController } from '../startWorkController';
138
import {
@@ -17,178 +12,22 @@ import {
1712
TaskInfoSection,
1813
UpdateStatusSection,
1914
} from './components';
20-
import { generateBranchName, getDefaultSourceBranch } from './utils/branchUtils';
15+
import { useStartWorkFormState } from './hooks/useStartWorkFormState';
2116

2217
const StartWorkPageV3: React.FunctionComponent = () => {
2318
const [state, controller] = useStartWorkController();
24-
const errorController = useContext(ErrorControllerContext);
25-
const [pushBranchEnabled, setPushBranchEnabled] = useState(true);
26-
const [localBranch, setLocalBranch] = useState('');
27-
const [sourceBranch, setSourceBranch] = useState<Branch>({ type: 0, name: '' });
28-
const [selectedRepository, setSelectedRepository] = useState<RepoData | undefined>(state.repoData[0]);
29-
const [selectedBranchType, setSelectedBranchType] = useState<{ kind: string; prefix: string }>({
30-
kind: '',
31-
prefix: '',
32-
});
33-
const [upstream, setUpstream] = useState('');
34-
const [transitionIssueEnabled, setTransitionIssueEnabled] = useState(true);
35-
const [selectedTransition, setSelectedTransition] = useState<Transition>(emptyTransition);
36-
const [branchSetupEnabled, setBranchSetupEnabled] = useState(true);
37-
const [submitState, setSubmitState] = useState<'initial' | 'submitting' | 'submit-success'>('initial');
38-
const [submitResponse, setSubmitResponse] = useState<{
39-
transistionStatus?: string;
40-
branch?: string;
41-
upstream?: string;
42-
}>({});
43-
const [snackbarOpen, setSnackbarOpen] = useState(false);
4419

45-
// Initialize form with default values
46-
useEffect(() => {
47-
if (state.repoData.length > 0) {
48-
const defaultRepo = state.repoData[0];
49-
setSelectedRepository(defaultRepo);
50-
const defaultSourceBranch = getDefaultSourceBranch(defaultRepo);
51-
setSourceBranch(defaultSourceBranch);
52-
53-
// Set default branch type
54-
if (defaultRepo.branchTypes && defaultRepo.branchTypes.length > 0) {
55-
setSelectedBranchType(defaultRepo.branchTypes[0]);
56-
}
57-
58-
if (!upstream) {
59-
setUpstream(defaultRepo.workspaceRepo.mainSiteRemote.remote.name);
60-
}
61-
}
62-
}, [state.repoData, upstream]);
63-
64-
// Generate branch name when dependencies change
65-
useEffect(() => {
66-
if (selectedRepository && selectedBranchType.prefix) {
67-
const generatedName = generateBranchName(
68-
selectedRepository,
69-
selectedBranchType,
70-
state.issue,
71-
state.customTemplate,
72-
);
73-
setLocalBranch(generatedName);
74-
}
75-
}, [selectedRepository, selectedBranchType, state.issue, state.customTemplate]);
76-
77-
const handleRepositoryChange = useCallback(
78-
(repository: RepoData) => {
79-
setSelectedRepository(repository);
80-
const defaultSourceBranch = getDefaultSourceBranch(repository);
81-
setSourceBranch(defaultSourceBranch);
82-
83-
if (repository.branchTypes && repository.branchTypes.length > 0) {
84-
setSelectedBranchType(repository.branchTypes[0]);
85-
}
86-
87-
if (!upstream) {
88-
setUpstream(repository.workspaceRepo.mainSiteRemote.remote.name);
89-
}
90-
},
91-
[upstream],
92-
);
93-
94-
const handleBranchTypeChange = useCallback((branchType: { kind: string; prefix: string }) => {
95-
setSelectedBranchType(branchType);
96-
}, []);
97-
98-
const handleUpstreamChange = useCallback((newUpstream: string) => {
99-
setUpstream(newUpstream);
100-
}, []);
101-
102-
const handleTransitionIssueEnabledChange = useCallback((enabled: boolean) => {
103-
setTransitionIssueEnabled(enabled);
104-
}, []);
105-
106-
const handleSelectedTransitionChange = useCallback((transition: Transition) => {
107-
setSelectedTransition(transition);
108-
}, []);
109-
110-
const handleBranchSetupEnabledChange = useCallback((enabled: boolean) => {
111-
setBranchSetupEnabled(enabled);
112-
}, []);
113-
114-
const handleSnackbarClose = useCallback(() => {
115-
setSnackbarOpen(false);
116-
}, []);
117-
118-
const handleCreateBranch = useCallback(async () => {
119-
setSubmitState('submitting');
120-
121-
try {
122-
if (!selectedRepository) {
123-
throw new Error('No repository selected');
124-
}
125-
126-
const response = await controller.startWork(
127-
transitionIssueEnabled,
128-
selectedTransition,
129-
branchSetupEnabled,
130-
selectedRepository.workspaceRepo,
131-
sourceBranch,
132-
localBranch,
133-
upstream,
134-
pushBranchEnabled,
135-
);
136-
137-
// Send message to refresh tree views after successful start work
138-
controller.postMessage({
139-
type: StartWorkActionType.RefreshTreeViews,
140-
});
141-
142-
setSubmitResponse(response);
143-
setSubmitState('submit-success');
144-
setSnackbarOpen(true);
145-
} catch (error) {
146-
console.error('Error creating branch:', error);
147-
errorController.showError(error);
148-
setSubmitState('initial');
149-
}
150-
}, [
151-
selectedRepository,
152-
controller,
153-
transitionIssueEnabled,
154-
selectedTransition,
155-
branchSetupEnabled,
156-
sourceBranch,
157-
localBranch,
158-
upstream,
159-
pushBranchEnabled,
160-
errorController,
161-
]);
162-
163-
const formState = {
164-
pushBranchEnabled,
165-
localBranch,
166-
sourceBranch,
167-
selectedRepository,
168-
selectedBranchType,
169-
upstream,
170-
branchSetupEnabled,
171-
};
172-
173-
const formActions = {
174-
onPushBranchChange: setPushBranchEnabled,
175-
onLocalBranchChange: setLocalBranch,
176-
onSourceBranchChange: setSourceBranch,
177-
onRepositoryChange: handleRepositoryChange,
178-
onBranchTypeChange: handleBranchTypeChange,
179-
onUpstreamChange: handleUpstreamChange,
180-
onBranchSetupEnabledChange: handleBranchSetupEnabledChange,
181-
};
182-
183-
const updateStatusFormState = {
184-
transitionIssueEnabled,
185-
selectedTransition,
186-
};
187-
188-
const updateStatusFormActions = {
189-
onTransitionIssueEnabledChange: handleTransitionIssueEnabledChange,
190-
onSelectedTransitionChange: handleSelectedTransitionChange,
191-
};
20+
const {
21+
formState,
22+
formActions,
23+
updateStatusFormState,
24+
updateStatusFormActions,
25+
handleCreateBranch,
26+
handleSnackbarClose,
27+
submitState,
28+
submitResponse,
29+
snackbarOpen,
30+
} = useStartWorkFormState(state, controller);
19231

19332
return (
19433
<StartWorkControllerContext.Provider value={controller}>
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
import { emptyTransition, Transition } from '@atlassianlabs/jira-pi-common-models';
2+
import { useCallback, useContext, useEffect, useState } from 'react';
3+
4+
import { StartWorkActionType } from '../../../../../lib/ipc/fromUI/startWork';
5+
import { RepoData } from '../../../../../lib/ipc/toUI/startWork';
6+
import { Branch } from '../../../../../typings/git';
7+
import { ErrorControllerContext } from '../../../common/errorController';
8+
import { useStartWorkController } from '../../startWorkController';
9+
import { generateBranchName, getDefaultSourceBranch } from '../utils/branchUtils';
10+
11+
export function useStartWorkFormState(
12+
state: ReturnType<typeof useStartWorkController>[0],
13+
controller: ReturnType<typeof useStartWorkController>[1],
14+
) {
15+
const errorController = useContext(ErrorControllerContext);
16+
17+
const [pushBranchEnabled, setPushBranchEnabled] = useState(true);
18+
const [localBranch, setLocalBranch] = useState('');
19+
const [sourceBranch, setSourceBranch] = useState<Branch>({ type: 0, name: '' });
20+
const [selectedRepository, setSelectedRepository] = useState<RepoData | undefined>(state.repoData[0]);
21+
const [selectedBranchType, setSelectedBranchType] = useState<{ kind: string; prefix: string }>({
22+
kind: '',
23+
prefix: '',
24+
});
25+
const [upstream, setUpstream] = useState('');
26+
const [transitionIssueEnabled, setTransitionIssueEnabled] = useState(true);
27+
const [selectedTransition, setSelectedTransition] = useState<Transition>(emptyTransition);
28+
const [branchSetupEnabled, setBranchSetupEnabled] = useState(true);
29+
const [submitState, setSubmitState] = useState<'initial' | 'submitting' | 'submit-success'>('initial');
30+
const [submitResponse, setSubmitResponse] = useState<{
31+
transistionStatus?: string;
32+
branch?: string;
33+
upstream?: string;
34+
}>({});
35+
const [snackbarOpen, setSnackbarOpen] = useState(false);
36+
37+
// useEffect: default values
38+
useEffect(() => {
39+
if (state.repoData.length > 0) {
40+
const defaultRepo = state.repoData[0];
41+
setSelectedRepository(defaultRepo);
42+
setSourceBranch(getDefaultSourceBranch(defaultRepo));
43+
if (defaultRepo.branchTypes?.length > 0) {
44+
setSelectedBranchType(defaultRepo.branchTypes[0]);
45+
}
46+
if (!upstream) {
47+
setUpstream(defaultRepo.workspaceRepo.mainSiteRemote.remote.name);
48+
}
49+
}
50+
}, [state.repoData, upstream]);
51+
52+
// useEffect: auto-generate branch name
53+
useEffect(() => {
54+
if (selectedRepository && selectedBranchType.prefix) {
55+
setLocalBranch(
56+
generateBranchName(selectedRepository, selectedBranchType, state.issue, state.customTemplate),
57+
);
58+
}
59+
}, [selectedRepository, selectedBranchType, state.issue, state.customTemplate]);
60+
61+
const handleRepositoryChange = useCallback(
62+
(repository: RepoData) => {
63+
setSelectedRepository(repository);
64+
setSourceBranch(getDefaultSourceBranch(repository));
65+
if (repository.branchTypes?.length > 0) {
66+
setSelectedBranchType(repository.branchTypes[0]);
67+
}
68+
if (!upstream) {
69+
setUpstream(repository.workspaceRepo.mainSiteRemote.remote.name);
70+
}
71+
},
72+
[upstream],
73+
);
74+
75+
const handleBranchTypeChange = useCallback((branchType: { kind: string; prefix: string }) => {
76+
setSelectedBranchType(branchType);
77+
}, []);
78+
79+
const handleUpstreamChange = useCallback((newUpstream: string) => {
80+
setUpstream(newUpstream);
81+
}, []);
82+
83+
const handleTransitionIssueEnabledChange = useCallback((enabled: boolean) => {
84+
setTransitionIssueEnabled(enabled);
85+
}, []);
86+
87+
const handleSelectedTransitionChange = useCallback((transition: Transition) => {
88+
setSelectedTransition(transition);
89+
}, []);
90+
91+
const handleBranchSetupEnabledChange = useCallback((enabled: boolean) => {
92+
setBranchSetupEnabled(enabled);
93+
}, []);
94+
95+
const handleSnackbarClose = useCallback(() => {
96+
setSnackbarOpen(false);
97+
}, []);
98+
99+
const handleCreateBranch = useCallback(async () => {
100+
setSubmitState('submitting');
101+
102+
try {
103+
if (!selectedRepository) {
104+
throw new Error('No repository selected');
105+
}
106+
107+
const response = await controller.startWork(
108+
transitionIssueEnabled,
109+
selectedTransition,
110+
branchSetupEnabled,
111+
selectedRepository.workspaceRepo,
112+
sourceBranch,
113+
localBranch,
114+
upstream,
115+
pushBranchEnabled,
116+
);
117+
118+
controller.postMessage({ type: StartWorkActionType.RefreshTreeViews });
119+
setSubmitResponse(response);
120+
setSubmitState('submit-success');
121+
setSnackbarOpen(true);
122+
} catch (error) {
123+
console.error(error);
124+
errorController.showError(error);
125+
setSubmitState('initial');
126+
}
127+
}, [
128+
selectedRepository,
129+
controller,
130+
transitionIssueEnabled,
131+
selectedTransition,
132+
branchSetupEnabled,
133+
sourceBranch,
134+
localBranch,
135+
upstream,
136+
pushBranchEnabled,
137+
errorController,
138+
]);
139+
140+
return {
141+
controller,
142+
formState: {
143+
pushBranchEnabled,
144+
localBranch,
145+
sourceBranch,
146+
selectedRepository,
147+
selectedBranchType,
148+
upstream,
149+
branchSetupEnabled,
150+
},
151+
formActions: {
152+
onPushBranchChange: setPushBranchEnabled,
153+
onLocalBranchChange: setLocalBranch,
154+
onSourceBranchChange: setSourceBranch,
155+
onRepositoryChange: handleRepositoryChange,
156+
onBranchTypeChange: handleBranchTypeChange,
157+
onUpstreamChange: handleUpstreamChange,
158+
onBranchSetupEnabledChange: handleBranchSetupEnabledChange,
159+
},
160+
updateStatusFormState: { transitionIssueEnabled, selectedTransition },
161+
updateStatusFormActions: {
162+
onTransitionIssueEnabledChange: handleTransitionIssueEnabledChange,
163+
onSelectedTransitionChange: handleSelectedTransitionChange,
164+
},
165+
handleCreateBranch,
166+
handleSnackbarClose,
167+
submitState,
168+
submitResponse,
169+
snackbarOpen,
170+
};
171+
}

0 commit comments

Comments
 (0)