diff --git a/plugins/scaffolder/src/next/OngoingTask/Outputs/DefaultOutputs.tsx b/plugins/scaffolder-react/src/next/components/TemplateOutputs/DefaultTemplateOutputs.tsx similarity index 81% rename from plugins/scaffolder/src/next/OngoingTask/Outputs/DefaultOutputs.tsx rename to plugins/scaffolder-react/src/next/components/TemplateOutputs/DefaultTemplateOutputs.tsx index 39bf89e4c5..5fbd3a5142 100644 --- a/plugins/scaffolder/src/next/OngoingTask/Outputs/DefaultOutputs.tsx +++ b/plugins/scaffolder-react/src/next/components/TemplateOutputs/DefaultTemplateOutputs.tsx @@ -14,11 +14,18 @@ * limitations under the License. */ import React from 'react'; -import { ScaffolderTaskOutput } from '@backstage/plugin-scaffolder-react'; import { Box, Paper } from '@material-ui/core'; import { LinkOutputs } from './LinkOutputs'; +import { ScaffolderTaskOutput } from '../../../api'; -export const DefaultOutputs = (props: { output?: ScaffolderTaskOutput }) => { +/** + * The DefaultOutputs renderer for the scaffolder task output + * + * @alpha + */ +export const DefaultTemplateOutputs = (props: { + output?: ScaffolderTaskOutput; +}) => { if (!props.output?.links) { return null; } diff --git a/plugins/scaffolder/src/next/OngoingTask/Outputs/LinkOutputs.tsx b/plugins/scaffolder-react/src/next/components/TemplateOutputs/LinkOutputs.tsx similarity index 96% rename from plugins/scaffolder/src/next/OngoingTask/Outputs/LinkOutputs.tsx rename to plugins/scaffolder-react/src/next/components/TemplateOutputs/LinkOutputs.tsx index d7c5ad0b67..d172aa9cb3 100644 --- a/plugins/scaffolder/src/next/OngoingTask/Outputs/LinkOutputs.tsx +++ b/plugins/scaffolder-react/src/next/components/TemplateOutputs/LinkOutputs.tsx @@ -15,12 +15,12 @@ */ import { IconComponent, useApp, useRouteRef } from '@backstage/core-plugin-api'; import { entityRouteRef } from '@backstage/plugin-catalog-react'; -import { ScaffolderTaskOutput } from '@backstage/plugin-scaffolder-react'; import { Button, makeStyles } from '@material-ui/core'; import React from 'react'; import WebIcon from '@material-ui/icons/Web'; import { parseEntityRef } from '@backstage/catalog-model'; import { Link } from '@backstage/core-components'; +import { ScaffolderTaskOutput } from '../../../api'; const useStyles = makeStyles({ root: { diff --git a/plugins/scaffolder/src/next/OngoingTask/Outputs/index.ts b/plugins/scaffolder-react/src/next/components/TemplateOutputs/index.ts similarity index 90% rename from plugins/scaffolder/src/next/OngoingTask/Outputs/index.ts rename to plugins/scaffolder-react/src/next/components/TemplateOutputs/index.ts index 647f1eebb2..1c998eb1b9 100644 --- a/plugins/scaffolder/src/next/OngoingTask/Outputs/index.ts +++ b/plugins/scaffolder-react/src/next/components/TemplateOutputs/index.ts @@ -13,4 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { DefaultOutputs } from './DefaultOutputs'; +export { DefaultTemplateOutputs } from './DefaultTemplateOutputs'; diff --git a/plugins/scaffolder-react/src/next/components/index.ts b/plugins/scaffolder-react/src/next/components/index.ts index babe3b4dcb..05e5a1105a 100644 --- a/plugins/scaffolder-react/src/next/components/index.ts +++ b/plugins/scaffolder-react/src/next/components/index.ts @@ -18,3 +18,4 @@ export * from './TemplateCard'; export * from './ReviewState'; export * from './TemplateGroup'; export * from './Workflow'; +export * from './TemplateOutputs'; diff --git a/plugins/scaffolder/src/next/OngoingTask/OngoingTask.tsx b/plugins/scaffolder/src/next/OngoingTask/OngoingTask.tsx index e166a96dd7..a68df01ed5 100644 --- a/plugins/scaffolder/src/next/OngoingTask/OngoingTask.tsx +++ b/plugins/scaffolder/src/next/OngoingTask/OngoingTask.tsx @@ -24,8 +24,11 @@ import { TaskLogStream } from './TaskLogStream'; import { nextSelectedTemplateRouteRef } from '../routes'; import { useRouteRef } from '@backstage/core-plugin-api'; import qs from 'qs'; -import { DefaultOutputs } from './Outputs'; import { ContextMenu } from './ContextMenu'; +import { + DefaultTemplateOutputs, + ScaffolderTaskOutput, +} from '@backstage/plugin-scaffolder-react'; const useStyles = makeStyles({ contentWrapper: { @@ -34,7 +37,11 @@ const useStyles = makeStyles({ }, }); -export const OngoingTask = () => { +export const OngoingTask = (props: { + TemplateOutputsComponent?: React.ComponentType<{ + output?: ScaffolderTaskOutput; + }>; +}) => { // todo(blam): check that task Id actually exists, and that it's valid. otherwise redirect to something more useful. const { taskId } = useParams(); const templateRouteRef = useRouteRef(nextSelectedTemplateRouteRef); @@ -92,6 +99,8 @@ export const OngoingTask = () => { templateRouteRef, ]); + const Outputs = props.TemplateOutputsComponent ?? DefaultTemplateOutputs; + const templateName = taskStream.task?.spec.templateInfo?.entity?.metadata.name; @@ -134,7 +143,7 @@ export const OngoingTask = () => { - + {logsVisible ? ( diff --git a/plugins/scaffolder/src/next/Router/Router.tsx b/plugins/scaffolder/src/next/Router/Router.tsx index b9c18f9d02..6ac8bbff65 100644 --- a/plugins/scaffolder/src/next/Router/Router.tsx +++ b/plugins/scaffolder/src/next/Router/Router.tsx @@ -19,6 +19,7 @@ import { TemplateListPage } from '../TemplateListPage'; import { TemplateWizardPage } from '../TemplateWizardPage'; import { NextFieldExtensionOptions, + ScaffolderTaskOutput, SecretsContextProvider, useCustomFieldExtensions, useCustomLayouts, @@ -47,9 +48,21 @@ export type NextRouterProps = { template: TemplateEntityV1beta3; }>; TaskPageComponent?: React.ComponentType<{}>; + TemplateOutputsComponent?: React.ComponentType<{ + output?: ScaffolderTaskOutput; + }>; }; groups?: TemplateGroupFilter[]; + // todo(blam): rename this to formProps FormProps?: FormProps; + contextMenu?: { + /** Whether to show a link to the template editor */ + editor?: boolean; + /** Whether to show a link to the actions documentation */ + actions?: boolean; + /** Whether to show a link to the tasks page */ + tasks?: boolean; + }; }; /** @@ -58,10 +71,13 @@ export type NextRouterProps = { * @alpha */ export const Router = (props: PropsWithChildren) => { - const { components: { TemplateCardComponent } = {} } = props; + const { + components: { TemplateCardComponent, TemplateOutputsComponent } = {}, + } = props; const outlet = useOutlet() || props.children; const customFieldExtensions = useCustomFieldExtensions(outlet); + const fieldExtensions = [ ...customFieldExtensions, ...DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS.filter( @@ -81,6 +97,7 @@ export const Router = (props: PropsWithChildren) => { element={ } @@ -97,7 +114,12 @@ export const Router = (props: PropsWithChildren) => { } /> - } /> + + } + /> } diff --git a/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.tsx b/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.tsx index 4eae84b866..3097bd98be 100644 --- a/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.tsx +++ b/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.tsx @@ -37,12 +37,18 @@ import { RegisterExistingButton } from './RegisterExistingButton'; import { useRouteRef } from '@backstage/core-plugin-api'; import { TemplateGroupFilter, TemplateGroups } from './TemplateGroups'; import { registerComponentRouteRef } from '../../routes'; +import { ScaffolderPageContextMenu } from '../../components/ScaffolderPage/ScaffolderPageContextMenu'; export type TemplateListPageProps = { TemplateCardComponent?: React.ComponentType<{ template: TemplateEntityV1beta3; }>; groups?: TemplateGroupFilter[]; + contextMenu?: { + editor?: boolean; + actions?: boolean; + tasks?: boolean; + }; }; const defaultGroup: TemplateGroupFilter = { @@ -61,7 +67,9 @@ export const TemplateListPage = (props: TemplateListPageProps) => { pageTitleOverride="Create a new component" title="Create a new component" subtitle="Create new software components using standard templates in your organization" - /> + > + +