chore: moved across the work from previous branch

Signed-off-by: blam <ben@blam.sh>
This commit is contained in:
blam
2023-01-16 17:02:15 +01:00
parent 77bfbdcc05
commit ab2c12fa1d
7 changed files with 183 additions and 8 deletions
@@ -25,7 +25,7 @@ import {
import { useApi } from '@backstage/core-plugin-api';
import { Subscription } from '@backstage/types';
type Step = {
export type Step = {
id: string;
status: ScaffolderTaskStatus;
endedAt?: string;
+13 -1
View File
@@ -28,7 +28,14 @@ import {
import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common';
import { TemplateGroupFilter } from '../TemplateListPage/TemplateGroups';
import { DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS } from '../../extensions/default';
import { nextSelectedTemplateRouteRef } from '../routes';
import { FormProps } from '../types';
import {
nextScaffolderTaskRouteRef,
nextSelectedTemplateRouteRef,
} from '../routes';
import { ErrorPage } from '@backstage/core-components';
import { TaskPage } from '../TaskPage';
/**
* The Props for the Scaffolder Router
@@ -91,6 +98,11 @@ export const Router = (props: PropsWithChildren<NextRouterProps>) => {
</SecretsContextProvider>
}
/>
<Route path={nextScaffolderTaskRouteRef.path} element={<TaskPage />} />
<Route
path="*"
element={<ErrorPage status="404" statusMessage="Page not found" />}
/>
</Routes>
);
};
@@ -0,0 +1,63 @@
/*
* Copyright 2023 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { useMemo } from 'react';
import { Page, Header, Content } from '@backstage/core-components';
import { useTaskEventStream } from '../../components/hooks/useEventStream';
import { useParams } from 'react-router-dom';
import { Box, LinearProgress, Paper } from '@material-ui/core';
import { TaskSteps } from './TaskSteps';
export const TaskPage = () => {
const { taskId } = useParams();
// check that task Id actually exists, and that it's valid. otherwise redirect to something more useful.
const taskStream = useTaskEventStream(taskId!);
const steps = useMemo(
() =>
taskStream.task?.spec.steps.map(step => ({
...step,
...taskStream?.steps?.[step.id],
})) ?? [],
[taskStream],
);
const activeStep = React.useMemo(() => {
for (let i = steps.length - 1; i >= 0; i--) {
if (steps[i].status !== 'open') {
return i;
}
}
return 0;
}, [steps]);
return (
<Page themeId="website">
<Header
pageTitleOverride="Task ID"
title="View Task"
subtitle="View the status of a task"
/>
<Content>
<Paper style={{ position: 'relative', overflow: 'hidden' }}>
<LinearProgress variant="indeterminate" value={100} />
<Box padding={2}>
<TaskSteps steps={steps} activeStep={activeStep} />
</Box>
</Paper>
</Content>
</Page>
);
};
@@ -0,0 +1,63 @@
/*
* Copyright 2022 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react';
import {
Stepper as MuiStepper,
Step as MuiStep,
StepButton as MuiStepButton,
StepLabel as MuiStepLabel,
} from '@material-ui/core';
import { TaskStep } from '@backstage/plugin-scaffolder-common';
import { Step } from '../../../components/hooks/useEventStream';
interface StepperProps {
steps: (TaskStep & Step)[];
activeStep?: number;
setActiveStep?: (step: number) => void;
}
export const TaskSteps = (props: StepperProps) => {
return (
<MuiStepper
activeStep={props.activeStep}
alternativeLabel
variant="elevation"
>
{props.steps.map((step, index) => {
const isCompleted = step.status === 'completed';
const isFailed = step.status === 'failed';
const isActive = step.status === 'processing';
const isSkipped = step.status === 'skipped';
return (
<MuiStep key={index}>
<MuiStepButton>
<MuiStepLabel
StepIconProps={{
completed: isCompleted,
error: isFailed,
active: isActive,
}}
>
{step.name}
</MuiStepLabel>
</MuiStepButton>
</MuiStep>
);
})}
</MuiStepper>
);
};
@@ -0,0 +1,16 @@
/*
* Copyright 2023 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export { TaskSteps } from './TaskSteps';
@@ -0,0 +1,16 @@
/*
* Copyright 2023 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export { TaskPage } from './TaskPage';
@@ -28,12 +28,17 @@ import {
Workflow,
type LayoutOptions,
} from '@backstage/plugin-scaffolder-react';
import { NextFieldExtensionOptions } from '@backstage/plugin-scaffolder-react';
import {
NextFieldExtensionOptions,
FormProps,
} from '@backstage/plugin-scaffolder-react';
import { JsonValue } from '@backstage/types';
import { type FormProps } from '../types';
import { nextRouteRef } from '../routes';
import { scaffolderTaskRouteRef, selectedTemplateRouteRef } from '../../routes';
import { Header, Page } from '@backstage/core-components';
import {
nextRouteRef,
nextScaffolderTaskRouteRef,
nextSelectedTemplateRouteRef,
} from '../routes';
export type TemplateWizardPageProps = {
customFieldExtensions: NextFieldExtensionOptions<any, any>[];
@@ -43,12 +48,12 @@ export type TemplateWizardPageProps = {
export const TemplateWizardPage = (props: TemplateWizardPageProps) => {
const rootRef = useRouteRef(nextRouteRef);
const taskRoute = useRouteRef(scaffolderTaskRouteRef);
const taskRoute = useRouteRef(nextScaffolderTaskRouteRef);
const { secrets } = useTemplateSecrets();
const scaffolderApi = useApi(scaffolderApiRef);
const navigate = useNavigate();
const { templateName, namespace } = useRouteRefParams(
selectedTemplateRouteRef,
nextSelectedTemplateRouteRef,
);
const templateRef = stringifyEntityRef({