Skip to content

Commit 240f2a6

Browse files
authored
Merge pull request #12 from headlamp-k8s/app-catalog-fixes
App catalog fixes
2 parents 2d1db6a + afc0075 commit 240f2a6

File tree

3 files changed

+163
-114
lines changed

3 files changed

+163
-114
lines changed

app-catalog/src/components/charts/EditorDialog.tsx

Lines changed: 133 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -35,18 +35,23 @@ export function EditorDialog(props: {
3535
const { enqueueSnackbar } = useSnackbar();
3636
const [isFormSubmitting, setIsFormSubmitting] = useState(false);
3737
const [versions, setVersions] = useState<string[]>([]);
38+
const [chartInstallDescription, setChartInstallDescription] = useState('');
3839
const [selectedVersion, setSelectedVersion] = useState<{ value: string; title: string }>();
3940
const [selectedNamespace, setSelectedNamespace] = useState<{
4041
value: string;
4142
title: string;
42-
}>({ value: 'default', title: 'default' });
43+
}>();
4344
const [releaseName, setReleaseName] = useState('');
4445
const namespaceNames = namespaces?.map(namespace => ({
4546
value: namespace.metadata.name,
4647
title: namespace.metadata.name,
4748
}));
4849
const themeName = localStorage.getItem('headlampThemePreference');
4950

51+
useEffect(() => {
52+
setIsFormSubmitting(false);
53+
}, [openEditor]);
54+
5055
function handleChartValueFetch(chart: any) {
5156
const packageID = chart.package_id;
5257
const packageVersion = chart.version;
@@ -99,25 +104,35 @@ export function EditorDialog(props: {
99104
}, 2000);
100105
}
101106

102-
function installAndCreateReleaseHandler(
103-
chart: any,
104-
releaseName: string,
105-
releaseNamespace: string,
106-
chartValues: string
107-
) {
107+
function installAndCreateReleaseHandler() {
108108
setIsFormSubmitting(true);
109-
if (!validateReleaseNameFormField()) {
109+
if (!validateFormField(releaseName)) {
110110
enqueueSnackbar('Release name is required', {
111111
variant: 'error',
112112
});
113113
return;
114114
}
115-
if (!validateVersionFormField()) {
115+
116+
if (!validateFormField(selectedNamespace)) {
117+
enqueueSnackbar('Namespace is required', {
118+
variant: 'error',
119+
});
120+
return;
121+
}
122+
123+
if (!validateFormField(selectedVersion)) {
116124
enqueueSnackbar('Version is required', {
117125
variant: 'error',
118126
});
119127
return;
120128
}
129+
130+
if (!validateFormField(chartInstallDescription)) {
131+
enqueueSnackbar('Description is required', {
132+
variant: 'error',
133+
});
134+
return;
135+
}
121136
const repoName = chart.repository.name;
122137
const repoURL = chart.repository.url;
123138
const jsonChartValues = yamlToJSON(chartValues);
@@ -126,39 +141,50 @@ export function EditorDialog(props: {
126141
);
127142
setInstallLoading(true);
128143

129-
addRepository(repoName, repoURL).then(() => {
130-
createRelease(
131-
releaseName,
132-
releaseNamespace,
133-
btoa(unescape(encodeURIComponent(jsonToYAML(chartValuesDIFF)))),
134-
`${repoName}/${chart.name}`,
135-
selectedVersion.value,
136-
`Install ${chart.name} (${selectedVersion.value}) in ${releaseNamespace} namespace`
137-
)
138-
.then(() => {
139-
checkInstallStatus(releaseName);
140-
})
141-
.catch(error => {
142-
handleEditor(false);
143-
enqueueSnackbar(`Error creating release request ${error}`, {
144-
variant: 'error',
144+
addRepository(repoName, repoURL)
145+
.then(() => {
146+
createRelease(
147+
releaseName,
148+
selectedNamespace.value,
149+
btoa(unescape(encodeURIComponent(jsonToYAML(chartValuesDIFF)))),
150+
`${repoName}/${chart.name}`,
151+
selectedVersion.value,
152+
chartInstallDescription
153+
)
154+
.then(() => {
155+
enqueueSnackbar(`Installation request for ${releaseName} accepted`, {
156+
variant: 'info',
157+
});
158+
handleEditor(false);
159+
checkInstallStatus(releaseName);
160+
})
161+
.catch(error => {
162+
handleEditor(false);
163+
enqueueSnackbar(`Error creating release request ${error}`, {
164+
variant: 'error',
165+
});
145166
});
167+
})
168+
.catch(error => {
169+
handleEditor(false);
170+
enqueueSnackbar(`Error adding repository ${error}`, {
171+
variant: 'error',
146172
});
147-
});
148-
}
149-
150-
function validateReleaseNameFormField() {
151-
if (releaseName === '') {
152-
return false;
153-
}
154-
return true;
173+
});
155174
}
156175

157-
function validateVersionFormField() {
158-
if (!selectedVersion || selectedVersion.value === '') {
159-
return false;
176+
function validateFormField(fieldValue: { value: string; title: string } | null | string) {
177+
if (typeof fieldValue === 'string') {
178+
if (fieldValue === '') {
179+
return false;
180+
}
181+
return true;
182+
} else {
183+
if (!fieldValue || fieldValue.value === '') {
184+
return false;
185+
}
186+
return true;
160187
}
161-
return true;
162188
}
163189

164190
useEffect(() => {
@@ -180,66 +206,83 @@ export function EditorDialog(props: {
180206
}}
181207
>
182208
<DialogTitle>
183-
<Box display="flex">
184-
<Box mr={2}>
185-
<TextField
186-
id="release-name"
187-
error={isFormSubmitting && releaseName === ''}
188-
helperText={releaseName === '' ? 'Release name is required' : ''}
189-
style={{
190-
width: '20vw',
191-
}}
192-
label="Release Name"
193-
value={releaseName}
194-
placeholder="Enter a name for the release"
195-
onChange={event => {
196-
setReleaseName(event.target.value);
197-
}}
198-
/>
199-
</Box>
200-
<Box>
201-
{!error && namespaceNames && (
209+
{chartValuesLoading ? null : (
210+
<Box display="flex" justifyContent="space-evenly">
211+
<Box mr={2}>
212+
<TextField
213+
id="release-name"
214+
error={isFormSubmitting && !validateFormField(releaseName)}
215+
style={{
216+
width: '15vw',
217+
}}
218+
label="Release Name *"
219+
value={releaseName}
220+
placeholder="Enter a name for the release"
221+
onChange={event => {
222+
setReleaseName(event.target.value);
223+
}}
224+
/>
225+
</Box>
226+
<Box>
227+
{!error && namespaceNames && (
228+
<Autocomplete
229+
style={{
230+
width: '15vw',
231+
}}
232+
options={namespaceNames}
233+
getOptionLabel={option => option.title}
234+
value={selectedNamespace}
235+
// @ts-ignore
236+
onChange={(event, newValue: { value: string; title: string }) => {
237+
setSelectedNamespace(newValue);
238+
}}
239+
renderInput={params => (
240+
<TextField
241+
{...params}
242+
label="Namespaces *"
243+
placeholder="Select Namespace"
244+
error={isFormSubmitting && !validateFormField(selectedNamespace)}
245+
/>
246+
)}
247+
/>
248+
)}
249+
</Box>
250+
<Box ml={2}>
202251
<Autocomplete
203252
style={{
204-
width: '20vw',
253+
width: '15vw',
205254
}}
206-
options={namespaceNames}
255+
options={versions}
207256
getOptionLabel={option => option.title}
208-
defaultValue={namespaceNames[0]}
209-
value={selectedNamespace}
257+
value={selectedVersion}
210258
// @ts-ignore
211259
onChange={(event, newValue: { value: string; title: string }) => {
212-
setSelectedNamespace(newValue);
260+
setSelectedVersion(newValue);
213261
}}
214262
renderInput={params => (
215-
<TextField {...params} label="Namespaces" placeholder="Select Namespace" />
263+
<TextField
264+
{...params}
265+
label="Versions *"
266+
placeholder="Select Version"
267+
error={isFormSubmitting && !validateFormField(selectedVersion)}
268+
/>
216269
)}
217270
/>
218-
)}
219-
</Box>
220-
<Box ml={2}>
221-
<Autocomplete
222-
style={{
223-
width: '20vw',
224-
}}
225-
options={versions}
226-
getOptionLabel={option => option.title}
227-
value={selectedVersion}
228-
// @ts-ignore
229-
onChange={(event, newValue: { value: string; title: string }) => {
230-
setSelectedVersion(newValue);
231-
}}
232-
renderInput={params => (
233-
<TextField
234-
{...params}
235-
label="Versions"
236-
placeholder="Select Version"
237-
error={isFormSubmitting && !selectedVersion}
238-
/>
239-
)}
240-
/>
271+
</Box>
272+
<Box ml={2}>
273+
<TextField
274+
id="release-description"
275+
style={{
276+
width: '15vw',
277+
}}
278+
error={isFormSubmitting && !validateFormField(chartInstallDescription)}
279+
label="Release Description *"
280+
value={chartInstallDescription}
281+
onChange={event => setChartInstallDescription(event.target.value)}
282+
/>
283+
</Box>
241284
</Box>
242-
</Box>
285+
)}
243286
</DialogTitle>
244287
<DialogContent>
245288
<Box height="100%">
@@ -259,6 +302,9 @@ export function EditorDialog(props: {
259302
setInstallLoading(false);
260303
editor.focus();
261304
setReleaseName('');
305+
setSelectedVersion(null);
306+
setSelectedNamespace(null);
307+
setChartInstallDescription('');
262308
}}
263309
language="yaml"
264310
height="500px"
@@ -295,14 +341,7 @@ export function EditorDialog(props: {
295341
</>
296342
) : (
297343
<Button
298-
onClick={() => {
299-
installAndCreateReleaseHandler(
300-
chart,
301-
releaseName,
302-
selectedNamespace.value,
303-
chartValues
304-
);
305-
}}
344+
onClick={installAndCreateReleaseHandler}
306345
variant="contained"
307346
style={{
308347
backgroundColor: '#000',

app-catalog/src/components/releases/Detail.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,10 @@ export default function ReleaseDetail() {
106106
onClick={() => {
107107
deleteRelease(namespace, releaseName).then(() => {
108108
setIsDeleting(true);
109+
enqueueSnackbar(`Delete request for release ${releaseName} accepted`, {
110+
variant: 'info',
111+
});
112+
setOpenDeleteAlert(false);
109113
checkDeleteReleaseStatus(releaseName);
110114
});
111115
}}

app-catalog/src/components/releases/EditorDialog.tsx

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,10 @@ export function EditorDialog(props: {
171171
selectedVersion.version
172172
)
173173
.then(() => {
174+
enqueueSnackbar(`Upgrade request for release ${releaseName} sent successfully`, {
175+
variant: 'info',
176+
});
177+
handleEditor(false);
174178
checkUpgradeStatus();
175179
})
176180
.catch(() => {
@@ -257,26 +261,28 @@ export function EditorDialog(props: {
257261
</Box>
258262
<DialogContent>
259263
<Box pt={2} height="100%" my={1} p={1}>
260-
<MonacoEditor
261-
value={jsonToYAML(valuesToShow)}
262-
language="yaml"
263-
height="400px"
264-
options={{
265-
selectOnLineNumbers: true,
266-
}}
267-
onChange={value => {
268-
handleEditorChange(value);
269-
}}
270-
theme={themeName === 'dark' ? 'vs-dark' : 'light'}
271-
onMount={editor => {
272-
setReleaseUpdateDescription('');
273-
setIsUserValues(false);
274-
setValuesToShow(Object.assign({}, release.chart.values, release.config));
275-
if (!isUpdateRelease) {
276-
editor.updateOptions({ readOnly: true });
277-
}
278-
}}
279-
/>
264+
{openEditor && (
265+
<MonacoEditor
266+
value={jsonToYAML(valuesToShow)}
267+
language="yaml"
268+
height="400px"
269+
options={{
270+
selectOnLineNumbers: true,
271+
}}
272+
onChange={value => {
273+
handleEditorChange(value);
274+
}}
275+
theme={themeName === 'dark' ? 'vs-dark' : 'light'}
276+
onMount={editor => {
277+
setReleaseUpdateDescription('');
278+
setIsUserValues(false);
279+
setValuesToShow(Object.assign({}, release.chart.values, release.config));
280+
if (!isUpdateRelease) {
281+
editor.updateOptions({ readOnly: true });
282+
}
283+
}}
284+
/>
285+
)}
280286
</Box>
281287
</DialogContent>
282288
<DialogActions

0 commit comments

Comments
 (0)