Merge pull request #28711 from drodil/task_title
feat(scaffolder): use template title for header
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder': patch
|
||||
---
|
||||
|
||||
Use template title for ongoing task page header
|
||||
@@ -17,9 +17,9 @@
|
||||
import { OngoingTask } from './OngoingTask';
|
||||
import React from 'react';
|
||||
import {
|
||||
mockApis,
|
||||
renderInTestApp,
|
||||
TestApiProvider,
|
||||
mockApis,
|
||||
} from '@backstage/test-utils';
|
||||
import { scaffolderApiRef } from '@backstage/plugin-scaffolder-react';
|
||||
import { act, fireEvent, waitFor, within } from '@testing-library/react';
|
||||
@@ -30,6 +30,7 @@ import {
|
||||
import { rootRouteRef } from '../../routes';
|
||||
import { AuthorizeResult } from '@backstage/plugin-permission-common';
|
||||
import { SWRConfig } from 'swr';
|
||||
import { entityPresentationApiRef } from '@backstage/plugin-catalog-react';
|
||||
|
||||
jest.mock('react-router-dom', () => ({
|
||||
...jest.requireActual('react-router-dom'),
|
||||
@@ -47,7 +48,10 @@ jest.mock('@backstage/plugin-scaffolder-react', () => ({
|
||||
task: {
|
||||
spec: {
|
||||
steps: [],
|
||||
templateInfo: { entity: { metadata: { name: 'my-template' } } },
|
||||
templateInfo: {
|
||||
entityRef: 'template:default/my-template',
|
||||
entity: { metadata: { name: 'my-template' } },
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
@@ -59,6 +63,12 @@ describe('OngoingTask', () => {
|
||||
getTask: jest.fn().mockImplementation(async () => {}),
|
||||
};
|
||||
|
||||
const mockEntityPresentationApi = {
|
||||
forEntity: jest.fn().mockReturnValue({
|
||||
promise: new Promise(resolve => resolve({ primaryTitle: 'My template' })),
|
||||
}),
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
@@ -71,6 +81,7 @@ describe('OngoingTask', () => {
|
||||
apis={[
|
||||
[scaffolderApiRef, mockScaffolderApi],
|
||||
[permissionApiRef, permissionApi || mockApis.permission()],
|
||||
[entityPresentationApiRef, mockEntityPresentationApi],
|
||||
]}
|
||||
>
|
||||
<OngoingTask />
|
||||
@@ -79,6 +90,12 @@ describe('OngoingTask', () => {
|
||||
{ mountedRoutes: { '/': rootRouteRef } },
|
||||
);
|
||||
};
|
||||
|
||||
it('should render title', async () => {
|
||||
const rendered = await render();
|
||||
expect(rendered.getByText('My template')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should trigger cancel api on "Cancel" click in context menu', async () => {
|
||||
const rendered = await render();
|
||||
const cancelOptionLabel = 'Cancel';
|
||||
|
||||
@@ -21,8 +21,8 @@ import Button from '@material-ui/core/Button';
|
||||
import Paper from '@material-ui/core/Paper';
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
import {
|
||||
ScaffolderTaskOutput,
|
||||
scaffolderApiRef,
|
||||
ScaffolderTaskOutput,
|
||||
useTaskEventStream,
|
||||
} from '@backstage/plugin-scaffolder-react';
|
||||
import { selectedTemplateRouteRef } from '../../routes';
|
||||
@@ -38,11 +38,13 @@ import { useAsync } from '@react-hookz/web';
|
||||
import { usePermission } from '@backstage/plugin-permission-react';
|
||||
import {
|
||||
taskCancelPermission,
|
||||
taskReadPermission,
|
||||
taskCreatePermission,
|
||||
taskReadPermission,
|
||||
} from '@backstage/plugin-scaffolder-common/alpha';
|
||||
import { useTranslationRef } from '@backstage/core-plugin-api/alpha';
|
||||
import { scaffolderTranslationRef } from '../../translation';
|
||||
import { entityPresentationApiRef } from '@backstage/plugin-catalog-react';
|
||||
import { default as reactUseAsync } from 'react-use/esm/useAsync';
|
||||
|
||||
const useStyles = makeStyles(theme => ({
|
||||
contentWrapper: {
|
||||
@@ -79,6 +81,7 @@ export const OngoingTask = (props: {
|
||||
const navigate = useNavigate();
|
||||
const analytics = useAnalytics();
|
||||
const scaffolderApi = useApi(scaffolderApiRef);
|
||||
const entityPresentationApi = useApi(entityPresentationApiRef);
|
||||
const taskStream = useTaskEventStream(taskId!);
|
||||
const classes = useStyles();
|
||||
const steps = useMemo(
|
||||
@@ -123,6 +126,14 @@ export const OngoingTask = (props: {
|
||||
}
|
||||
}, [taskStream.error, taskStream.completed]);
|
||||
|
||||
const { value: presentation } = reactUseAsync(async () => {
|
||||
const templateEntityRef = taskStream.task?.spec.templateInfo?.entityRef;
|
||||
if (!templateEntityRef) {
|
||||
return undefined;
|
||||
}
|
||||
return entityPresentationApi.forEntity(templateEntityRef).promise;
|
||||
}, [entityPresentationApi, taskStream.task?.spec.templateInfo?.entityRef]);
|
||||
|
||||
const activeStep = useMemo(() => {
|
||||
for (let i = steps.length - 1; i >= 0; i--) {
|
||||
if (steps[i].status !== 'open') {
|
||||
@@ -184,22 +195,22 @@ export const OngoingTask = (props: {
|
||||
|
||||
const Outputs = props.TemplateOutputsComponent ?? DefaultTemplateOutputs;
|
||||
|
||||
const templateName =
|
||||
taskStream.task?.spec.templateInfo?.entity?.metadata.name || '';
|
||||
|
||||
const cancelEnabled = !(taskStream.cancelled || taskStream.completed);
|
||||
|
||||
return (
|
||||
<Page themeId="website">
|
||||
<Header
|
||||
pageTitleOverride={
|
||||
templateName
|
||||
? t('ongoingTask.pageTitle.hasTemplateName', { templateName })
|
||||
presentation
|
||||
? t('ongoingTask.pageTitle.hasTemplateName', {
|
||||
templateName: presentation.primaryTitle,
|
||||
})
|
||||
: t('ongoingTask.pageTitle.noTemplateName')
|
||||
}
|
||||
title={
|
||||
<div>
|
||||
{t('ongoingTask.title')} <code>{templateName}</code>
|
||||
{t('ongoingTask.title')}{' '}
|
||||
<code>{presentation ? presentation.primaryTitle : ''}</code>
|
||||
</div>
|
||||
}
|
||||
subtitle={t('ongoingTask.subtitle', { taskId: taskId as string })}
|
||||
|
||||
Reference in New Issue
Block a user