Skip to content

Commit c5815af

Browse files
authored
Editable fields on step bundle instance [BIVS-3422] (#1663)
1 parent 922eae6 commit c5815af

File tree

13 files changed

+127
-93
lines changed

13 files changed

+127
-93
lines changed

source/javascripts/components/unified-editor/CreateEntityDialog/CreateEntityDialog.tsx

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,21 +31,24 @@ const Options = <T,>({ baseEntities }: { baseEntities: BaseEntityType<T>[] }) =>
3131

3232
type FormValues = {
3333
entityId: string;
34+
title?: string;
3435
baseEntityId: string;
3536
};
3637

3738
export type Props<T> = Omit<DialogProps, 'onCloseComplete' | 'title'> & {
3839
baseEntities: BaseEntityType<T>[];
3940
entityName: string;
41+
extraInputs?: 'title'[];
4042
onCloseComplete: (entityId: string) => void;
41-
onCreateEntity: (entityId: string, baseEntityId?: string) => void;
43+
onCreateEntity: (entityId: string, baseEntityId?: string, title?: string) => void;
4244
sanitizer: (value: string) => string;
4345
validator: (value: string) => string | boolean;
4446
};
4547

4648
const CreateEntityDialog = <T,>({
4749
baseEntities,
4850
entityName,
51+
extraInputs,
4952
onClose,
5053
onCloseComplete,
5154
onCreateEntity,
@@ -63,6 +66,7 @@ const CreateEntityDialog = <T,>({
6366
} = useForm<FormValues>({
6467
defaultValues: {
6568
entityId: '',
69+
title: '',
6670
baseEntityId: '',
6771
},
6872
});
@@ -75,8 +79,8 @@ const CreateEntityDialog = <T,>({
7579
});
7680
};
7781

78-
const handleCreate = handleSubmit(({ entityId, baseEntityId }) => {
79-
onCreateEntity(entityId, baseEntityId);
82+
const handleCreate = handleSubmit(({ entityId, baseEntityId, title }) => {
83+
onCreateEntity(entityId, baseEntityId, title || undefined);
8084
onClose();
8185
});
8286

@@ -94,15 +98,24 @@ const CreateEntityDialog = <T,>({
9498
<Input
9599
autoFocus
96100
isRequired
97-
label="Name"
98-
placeholder={`${entityName} name`}
101+
label="ID"
102+
placeholder={`${entityName} ID`}
99103
inputRef={(ref) => ref?.setAttribute('data-1p-ignore', '')}
100104
errorText={errors.entityId?.message}
101105
{...register('entityId', {
102106
onChange: handleNameChange,
103107
validate: validator,
104108
})}
105109
/>
110+
{extraInputs?.includes('title') && (
111+
<Input
112+
label="Title"
113+
placeholder={`${entityName} Title`}
114+
inputRef={(ref) => ref?.setAttribute('data-1p-ignore', '')}
115+
helperText="Human-readable name, overridable per instance."
116+
{...register('title')}
117+
/>
118+
)}
106119
<Select label="Based on" {...register('baseEntityId')}>
107120
<option key="" value="">
108121
An empty {entityName}

source/javascripts/components/unified-editor/CreateStepBundleDialog/CreateStepBundleDialog.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ type BaseEntityGroup = {
1515
};
1616

1717
type Props = Omit<DialogProps, 'title'> & {
18-
onCreateStepBundle: (stepBundleId: string, baseEntityId?: string) => void;
18+
onCreateStepBundle: (stepBundleId: string, baseEntityId?: string, title?: string) => void;
1919
};
2020

2121
const CreateStepBundleDialog = ({ onClose, onCloseComplete, onCreateStepBundle, ...props }: Props) => {
@@ -52,6 +52,7 @@ const CreateStepBundleDialog = ({ onClose, onCloseComplete, onCreateStepBundle,
5252
return (
5353
<CreateEntityDialog<StepBundleCreationSource>
5454
baseEntities={baseEntities}
55+
extraInputs={['title']}
5556
entityName="Step bundle"
5657
onClose={onClose}
5758
onCloseComplete={handleCloseComplete}

source/javascripts/components/unified-editor/StepBundleConfig/StepBundleConfigContent.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,17 @@ import StepBundlePropertiesTab from './StepBundlePropertiesTab';
55

66
type ConfigContentProps = {
77
onDelete?: () => void;
8-
onRename?: (name: string) => void;
8+
onChangeId?: (name: string) => void;
99
} & TabPanelProps;
1010

11-
const StepBundleConfigContent = ({ onDelete, onRename, ...rest }: ConfigContentProps) => {
11+
const StepBundleConfigContent = ({ onDelete, onChangeId, ...rest }: ConfigContentProps) => {
1212
return (
1313
<TabPanels {...rest}>
1414
<TabPanel height="100%">
1515
<StepBundleConfigurationTab />
1616
</TabPanel>
17-
<TabPanel>
18-
<StepBundlePropertiesTab onDelete={onDelete} onRename={onRename} />
17+
<TabPanel display="flex" flexDirection="column" gap="24">
18+
<StepBundlePropertiesTab onDelete={onDelete} onChangeId={onChangeId} />
1919
</TabPanel>
2020
</TabPanels>
2121
);

source/javascripts/components/unified-editor/StepBundleConfig/StepBundleConfigDrawer.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@ import StepBundleConfigContent from './StepBundleConfigContent';
1212
import StepBundleConfigHeader from './StepBundleConfigHeader';
1313

1414
type Props = Omit<FloatingDrawerProps, 'children'> & {
15-
onRename?: (name: string) => void;
15+
onChangeId?: (name: string) => void;
1616
stepBundleId?: string;
1717
parentWorkflowId?: string;
1818
parentStepBundleId?: string;
1919
stepIndex: number;
2020
};
2121

2222
const StepBundleConfigDrawer = ({
23-
onRename,
23+
onChangeId,
2424
stepBundleId,
2525
stepIndex,
2626
parentWorkflowId,
@@ -42,7 +42,7 @@ const StepBundleConfigDrawer = ({
4242
<StepBundleConfigHeader variant="drawer" />
4343
</FloatingDrawerHeader>
4444
<FloatingDrawerBody>
45-
<StepBundleConfigContent onRename={onRename} />
45+
<StepBundleConfigContent onChangeId={onChangeId} />
4646
</FloatingDrawerBody>
4747
</FloatingDrawerContent>
4848
</FloatingDrawer>

source/javascripts/components/unified-editor/StepBundleConfig/StepBundleConfigPanel.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ const StepBundleConfigPanel = ({ stepBundleId }: Props) => {
2424
overflow="auto"
2525
padding="24"
2626
onDelete={closeDialog}
27-
onRename={setSelectedStepBundle}
27+
onChangeId={setSelectedStepBundle}
2828
/>
2929
</Tabs>
3030
</StepBundleConfigProvider>

source/javascripts/components/unified-editor/StepBundleConfig/StepBundlePropertiesTab.tsx

Lines changed: 57 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,82 +1,89 @@
1-
import { Button, Textarea, useDisclosure } from '@bitrise/bitkit';
2-
import { ChangeEventHandler } from 'react';
1+
import { Button, Input, Textarea, useDisclosure } from '@bitrise/bitkit';
32

43
import EditableInput from '@/components/EditableInput/EditableInput';
54
import StepBundleService from '@/core/services/StepBundleService';
65
import { useStepBundles } from '@/hooks/useStepBundles';
76

87
import DeleteStepBundleDialog from '../DeleteStepBundleDialog/DeleteStepBundleDialog';
9-
import useRenameStepBundle from './hooks/useRenameStepBundle';
8+
import useChangeStepBundleId from './hooks/useChangeStepBundleId';
109
import { useStepBundleConfigContext } from './StepBundleConfig.context';
1110

1211
type StepBundlePropertiesTabProps = {
1312
onDelete?: () => void;
14-
onRename?: (newStepBundleId: string) => void;
13+
onChangeId?: (newStepBundleId: string) => void;
1514
};
1615

17-
const NameInput = ({ onRename }: Pick<StepBundlePropertiesTabProps, 'onRename'>) => {
18-
const value = useStepBundleConfigContext((s) => s.stepBundle?.id);
16+
const StepBundlePropertiesTab = ({ onDelete, onChangeId }: StepBundlePropertiesTabProps) => {
1917
const stepBundleIds = useStepBundles((s) => Object.keys(s));
20-
const rename = useRenameStepBundle(value, onRename);
18+
const contextData = useStepBundleConfigContext((s) => s);
19+
const id = contextData.stepBundle?.id || contextData.stepBundleId || '';
2120

22-
const handleNameChange = (newStepBundleId: string) => {
23-
if (newStepBundleId !== value) {
24-
rename(newStepBundleId);
25-
}
21+
const at = {
22+
cvs: contextData.stepBundle?.cvs || `bundle::${contextData.stepBundle?.id || contextData.stepBundleId}`,
23+
source: contextData.parentStepBundleId ? 'step_bundles' : ('workflows' as 'step_bundles' | 'workflows'),
24+
sourceId: contextData.parentStepBundleId || contextData.parentWorkflowId || '',
25+
stepIndex: contextData.stepIndex,
2626
};
2727

28-
return (
29-
<EditableInput
30-
isRequired
31-
name="name"
32-
label="Name"
33-
value={value}
34-
marginBlockEnd="16"
35-
sanitize={StepBundleService.sanitizeName}
36-
validate={(v) => StepBundleService.validateName(v, value || '', stepBundleIds)}
37-
onCommit={handleNameChange}
38-
/>
39-
);
40-
};
28+
const { isOpen: isDeleteDialogOpen, onOpen: openDeleteDialog, onClose: closeDeleteDialog } = useDisclosure();
4129

42-
const SummaryInput = () => {
43-
const id = useStepBundleConfigContext((s) => s.stepBundle?.id || '');
44-
const value = useStepBundleConfigContext((s) => s.stepBundle?.mergedValues.summary || '');
30+
const rename = useChangeStepBundleId(id, onChangeId);
4531

46-
const handleSummaryChange: ChangeEventHandler<HTMLTextAreaElement> = (e) => {
47-
StepBundleService.updateStepBundleField(id, 'summary', e.target.value);
32+
const handleIdChange = (newStepBundleId: string) => {
33+
if (newStepBundleId !== id) {
34+
rename(newStepBundleId);
35+
}
4836
};
4937

50-
return <Textarea label="Summary" value={value} onChange={handleSummaryChange} marginBlockEnd="16" />;
51-
};
52-
53-
const DescriptionInput = () => {
54-
const id = useStepBundleConfigContext((s) => s.stepBundle?.id || '');
55-
const value = useStepBundleConfigContext((s) => s.stepBundle?.mergedValues.description || '');
56-
57-
const handleDescriptionChange: ChangeEventHandler<HTMLTextAreaElement> = (e) => {
58-
StepBundleService.updateStepBundleField(id, 'description', e.target.value);
38+
const handleFieldChange = (field: 'description' | 'summary' | 'title', value: string) => {
39+
if (contextData.parentStepBundleId || contextData.parentWorkflowId) {
40+
StepBundleService.updateStepBundleInstanceField(field, value, at);
41+
} else {
42+
StepBundleService.updateStepBundleField(id, field, value);
43+
}
5944
};
6045

61-
return <Textarea label="Description" value={value} onChange={handleDescriptionChange} />;
62-
};
63-
64-
const StepBundlePropertiesTab = ({ onDelete, onRename }: StepBundlePropertiesTabProps) => {
65-
const id = useStepBundleConfigContext((s) => s.stepBundle?.id || '');
66-
const { isOpen: isDeleteDialogOpen, onOpen: openDeleteDialog, onClose: closeDeleteDialog } = useDisclosure();
67-
6846
return (
6947
<>
70-
<NameInput onRename={onRename} />
71-
<SummaryInput />
72-
<DescriptionInput />
48+
<EditableInput
49+
isRequired
50+
name="id"
51+
label="ID"
52+
value={contextData.stepBundle?.id}
53+
sanitize={StepBundleService.sanitizeName}
54+
validate={(v) => StepBundleService.validateName(v, contextData.stepBundle?.id || '', stepBundleIds)}
55+
onCommit={handleIdChange}
56+
/>
57+
<Input
58+
label="Title"
59+
size="md"
60+
onChange={(e) => handleFieldChange('title', e.target.value)}
61+
value={contextData.stepBundle?.mergedValues.title || ''}
62+
/>
63+
<Textarea
64+
label="Summary"
65+
value={contextData.stepBundle?.mergedValues.summary || ''}
66+
onChange={(e) => handleFieldChange('summary', e.target.value)}
67+
/>
68+
<Textarea
69+
label="Description"
70+
value={contextData.stepBundle?.mergedValues.description || ''}
71+
onChange={(e) => handleFieldChange('description', e.target.value)}
72+
/>
7373
{!!onDelete && (
7474
<>
75-
<Button leftIconName="Trash" variant="secondary" isDanger marginBlockStart="24" onClick={openDeleteDialog}>
75+
<Button
76+
leftIconName="Trash"
77+
size="md"
78+
variant="secondary"
79+
isDanger
80+
onClick={openDeleteDialog}
81+
width="fit-content"
82+
>
7683
Delete Step bundle
7784
</Button>
7885
<DeleteStepBundleDialog
79-
stepBundleId={id}
86+
stepBundleId={contextData.stepBundle?.id || ''}
8087
isOpen={isDeleteDialogOpen}
8188
onClose={closeDeleteDialog}
8289
onDeleteStepBundle={onDelete}
Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,18 @@ import { useCallback, useEffect, useState } from 'react';
33
import StepBundleService from '@/core/services/StepBundleService';
44
import useBitriseYmlStore from '@/hooks/useBitriseYmlStore';
55

6-
const useRenameStepBundle = (stepBundleId: string = '', onChange?: (newStepBundleId: string) => void) => {
6+
const useChangeStepBundleId = (stepBundleId: string = '', onChange?: (newStepBundleId: string) => void) => {
77
const stepBundleIdsInTheStore = useBitriseYmlStore((s) => Object.keys(s.yml.step_bundles ?? {}));
88

9-
const [isRenaming, setIsRenaming] = useState(false);
9+
const [isChanging, setIsChanging] = useState(false);
1010
const [nextStepBundleId, setNextStepBundleId] = useState(stepBundleId);
1111
const [prevStepBundleId, setPrevStepBundleId] = useState(stepBundleId);
1212

1313
const isNewStepBundlePersisted = stepBundleIdsInTheStore.includes(nextStepBundleId);
1414
const isNewStepBundleSelected = nextStepBundleId === stepBundleId;
1515

16-
const shouldRunOnChange = isRenaming && isNewStepBundlePersisted && !isNewStepBundleSelected;
17-
const shouldFinishRenaming = isRenaming && isNewStepBundlePersisted && isNewStepBundleSelected;
16+
const shouldRunOnChange = isChanging && isNewStepBundlePersisted && !isNewStepBundleSelected;
17+
const shouldFinishChanging = isChanging && isNewStepBundlePersisted && isNewStepBundleSelected;
1818

1919
useEffect(() => {
2020
if (shouldRunOnChange) {
@@ -23,18 +23,18 @@ const useRenameStepBundle = (stepBundleId: string = '', onChange?: (newStepBundl
2323
}, [onChange, shouldRunOnChange, nextStepBundleId]);
2424

2525
useEffect(() => {
26-
if (shouldFinishRenaming) {
27-
setIsRenaming(false);
26+
if (shouldFinishChanging) {
27+
setIsChanging(false);
2828
StepBundleService.deleteStepBundle(prevStepBundleId);
2929
}
30-
}, [shouldFinishRenaming, prevStepBundleId]);
30+
}, [shouldFinishChanging, prevStepBundleId]);
3131

3232
return useCallback(
3333
(newStepBundleId: string) => {
3434
if (stepBundleId) {
35-
setIsRenaming(true);
35+
setIsChanging(true);
3636

37-
StepBundleService.renameStepBundle(stepBundleId, newStepBundleId);
37+
StepBundleService.changeStepBundleId(stepBundleId, newStepBundleId);
3838
StepBundleService.createStepBundle(stepBundleId, { source: 'step_bundles', sourceId: newStepBundleId });
3939

4040
setNextStepBundleId(newStepBundleId);
@@ -45,4 +45,4 @@ const useRenameStepBundle = (stepBundleId: string = '', onChange?: (newStepBundl
4545
);
4646
};
4747

48-
export default useRenameStepBundle;
48+
export default useChangeStepBundleId;

0 commit comments

Comments
 (0)