fix(scaffolder): Allow user to retry creating a new software without refreshing the page

This is more of a bug fix than a new feature. The commit fixes 2 problems mainly.

1. When user clicks the close button on the JobStatusModal, it does not set the `modalOpen` state of its parent component. Thus, even after closing, JobStatusModal still persists in DOM, and modalOpen is still set to true. That is why, retrying by clicking on "Submit" again does not open the modal.

2. The useJobPolling hook does not consider starting the timer again when Job changes. Even if jobId changes, the logic to set `shouldBeRunningInterval` still uses a previous value of `currentJob` since it was never reset since the timer stopped. Using a effect hook and having jobId as a dependency to reset currentJob is the way to fix this.
This commit is contained in:
Himanshu Mishra
2020-12-29 00:00:57 +01:00
parent ede29f55c7
commit 8e083f41f3
4 changed files with 37 additions and 8 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-scaffolder': patch
---
Bug fix: User can retry creating a new component if an error occurs, without having to reload the page.
@@ -23,18 +23,23 @@ import {
LinearProgress,
} from '@material-ui/core';
import React, { useCallback, useState } from 'react';
import React, { useCallback } from 'react';
import { Job } from '../../types';
import { JobStage } from '../JobStage/JobStage';
type Props = {
job: Job | null;
toCatalogLink?: string;
open: boolean;
setOpen: (newState: boolean) => void;
};
export const JobStatusModal = ({ job, toCatalogLink }: Props) => {
const [isOpen, setOpen] = useState(true);
export const JobStatusModal = ({
job,
toCatalogLink,
open,
setOpen,
}: Props) => {
const renderTitle = () => {
switch (job?.status) {
case 'COMPLETED':
@@ -47,16 +52,17 @@ export const JobStatusModal = ({ job, toCatalogLink }: Props) => {
};
const onClose = useCallback(() => {
setOpen(false);
if (!job) {
return;
}
if (job.status === 'COMPLETED' || job.status === 'FAILED') {
setOpen(false);
}
}, [job]);
}, [job, setOpen]);
return (
<Dialog open={isOpen} onClose={onClose} fullWidth>
<Dialog open={open} onClose={onClose} fullWidth>
<DialogTitle id="responsive-dialog-title">{renderTitle()}</DialogTitle>
<DialogContent>
{!job ? (
@@ -161,7 +161,12 @@ export const TemplatePage = () => {
/>
<Content>
{loading && <LinearProgress data-testid="loading-progress" />}
{modalOpen && <JobStatusModal job={job} toCatalogLink={catalogLink} />}
<JobStatusModal
job={job}
toCatalogLink={catalogLink}
open={modalOpen}
setOpen={setModalOpen}
/>
{template && (
<InfoCard title={template.metadata.title} noPadding>
<MultistepJsonForm
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { useState } from 'react';
import { useEffect, useState } from 'react';
import { Job } from '../../types';
import { useApi } from '@backstage/core';
import { scaffolderApiRef } from '../../api';
@@ -28,10 +28,23 @@ export const useJobPolling = (
) => {
const scaffolderApi = useApi(scaffolderApiRef);
const [currentJob, setCurrentJob] = useState<Job | null>(null);
useEffect(() => {
const resetCurrentJob = async () => {
if (jobId) {
const job = await scaffolderApi.getJob(jobId);
setCurrentJob(job);
}
};
resetCurrentJob();
}, [jobId, scaffolderApi]);
const shouldBeRunningInterval =
jobId &&
currentJob?.status !== 'COMPLETED' &&
currentJob?.status !== 'FAILED';
useInterval(
async () => {
if (jobId) {