chore: move the routeRefs back into the scaffolder plugin for now, maybe it makes sense to move them later.

Signed-off-by: blam <ben@blam.sh>
This commit is contained in:
blam
2023-01-04 23:20:28 +01:00
parent 3053e582fc
commit 912bd110f2
31 changed files with 169 additions and 135 deletions
-1
View File
@@ -14,7 +14,6 @@
* limitations under the License.
*/
export * from './routes';
export * from './extensions';
export * from './types';
export * from './secrets';
@@ -13,11 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {
useAnalytics,
useApiHolder,
useRouteRefParams,
} from '@backstage/core-plugin-api';
import { useAnalytics, useApiHolder } from '@backstage/core-plugin-api';
import { JsonValue } from '@backstage/types';
import {
Stepper as MuiStepper,
@@ -35,7 +31,7 @@ import { createAsyncValidators } from './createAsyncValidators';
import { useTemplateSchema } from '../../hooks/useTemplateSchema';
import { ReviewState } from '../ReviewState';
import validator from '@rjsf/validator-ajv6';
import { selectedTemplateRouteRef } from '../../../routes';
import { useFormData } from '../../hooks/useFormData';
import { FormProps } from '../../types';
@@ -61,8 +57,10 @@ const useStyles = makeStyles(theme => ({
export type StepperProps = {
manifest: TemplateParameterSchema;
extensions: NextFieldExtensionOptions<any, any>[];
onComplete: (values: Record<string, JsonValue>) => Promise<void>;
templateName?: string;
FormProps?: FormProps;
onComplete: (values: Record<string, JsonValue>) => Promise<void>;
};
// TODO(blam): We require here, as the types in this package depend on @rjsf/core explicitly
@@ -75,7 +73,6 @@ const Form = withTheme(require('@rjsf/material-ui-v5').Theme);
* @alpha
*/
export const Stepper = (props: StepperProps) => {
const { templateName } = useRouteRefParams(selectedTemplateRouteRef);
const analytics = useAnalytics();
const { steps } = useTemplateSchema(props.manifest);
const apiHolder = useApiHolder();
@@ -204,7 +201,7 @@ export const Stepper = (props: StepperProps) => {
: undefined;
analytics.captureEvent(
'create',
name || `new ${templateName}`,
name ?? props.templateName ?? 'unknown',
);
}}
>
@@ -27,7 +27,6 @@ import { TemplateCard } from './TemplateCard';
import React from 'react';
import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common';
import { RELATION_OWNED_BY } from '@backstage/catalog-model';
import { nextRouteRef } from '../../routes';
describe('TemplateCard', () => {
it('should render the card title', async () => {
@@ -54,7 +53,6 @@ describe('TemplateCard', () => {
>
<TemplateCard template={mockTemplate} />
</TestApiProvider>,
{ mountedRoutes: { '/': nextRouteRef } },
);
expect(getByText('bob')).toBeInTheDocument();
@@ -84,7 +82,6 @@ describe('TemplateCard', () => {
>
<TemplateCard template={mockTemplate} />
</TestApiProvider>,
{ mountedRoutes: { '/': nextRouteRef } },
);
const description = getByText('hello');
@@ -115,7 +112,6 @@ describe('TemplateCard', () => {
>
<TemplateCard template={mockTemplate} />
</TestApiProvider>,
{ mountedRoutes: { '/': nextRouteRef } },
);
expect(getByText('No description')).toBeInTheDocument();
@@ -145,7 +141,6 @@ describe('TemplateCard', () => {
>
<TemplateCard template={mockTemplate} />
</TestApiProvider>,
{ mountedRoutes: { '/': nextRouteRef } },
);
for (const tag of mockTemplate.metadata.tags!) {
@@ -185,7 +180,6 @@ describe('TemplateCard', () => {
</TestApiProvider>,
{
mountedRoutes: {
'/': nextRouteRef,
'/catalog/:kind/:namespace/:name': entityRouteRef,
},
},
@@ -224,7 +218,6 @@ describe('TemplateCard', () => {
</TestApiProvider>,
{
mountedRoutes: {
'/': nextRouteRef,
'/catalog/:kind/:namespace/:name': entityRouteRef,
},
},
@@ -13,14 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {
DEFAULT_NAMESPACE,
parseEntityRef,
RELATION_OWNED_BY,
stringifyEntityRef,
} from '@backstage/catalog-model';
import { Button, MarkdownContent, UserIcon } from '@backstage/core-components';
import { IconComponent, useApp, useRouteRef } from '@backstage/core-plugin-api';
import { RELATION_OWNED_BY } from '@backstage/catalog-model';
import { MarkdownContent, UserIcon } from '@backstage/core-components';
import { IconComponent, useApp } from '@backstage/core-plugin-api';
import {
EntityRefLinks,
getEntityRelations,
@@ -34,13 +29,12 @@ import {
CardContent,
Chip,
Divider,
Button,
Grid,
makeStyles,
} from '@material-ui/core';
import LanguageIcon from '@material-ui/icons/Language';
import React from 'react';
import { nextSelectedTemplateRouteRef } from '../../routes';
import { viewTechDocRouteRef } from '../../../routes';
import { CardHeader } from './CardHeader';
import { CardLink } from './CardLink';
@@ -86,7 +80,13 @@ const useStyles = makeStyles<BackstageTheme>(theme => ({
*/
export interface TemplateCardProps {
template: TemplateEntityV1beta3;
deprecated?: boolean;
additionalLinks?: {
icon: IconComponent;
text: string;
url: string;
}[];
onSelected?: (template: TemplateEntityV1beta3) => void;
}
/**
@@ -97,32 +97,10 @@ export const TemplateCard = (props: TemplateCardProps) => {
const { template } = props;
const styles = useStyles();
const ownedByRelations = getEntityRelations(template, RELATION_OWNED_BY);
const templateRoute = useRouteRef(nextSelectedTemplateRouteRef);
const { name, namespace } = parseEntityRef(
stringifyEntityRef(props.template),
);
const href = templateRoute({
templateName: name,
namespace: namespace,
});
const app = useApp();
const iconResolver = (key?: string): IconComponent =>
key ? app.getSystemIcon(key) ?? LanguageIcon : LanguageIcon;
// TechDocs Link
const viewTechDoc = useRouteRef(viewTechDocRouteRef);
const viewTechDocsAnnotation =
template.metadata.annotations?.['backstage.io/techdocs-ref'];
const viewTechDocsLink =
!!viewTechDocsAnnotation &&
!!viewTechDoc &&
viewTechDoc({
namespace: template.metadata.namespace || DEFAULT_NAMESPACE,
kind: template.kind,
name: template.metadata.name,
});
return (
<Card>
<CardHeader template={template} />
@@ -157,22 +135,18 @@ export const TemplateCard = (props: TemplateCardProps) => {
</Grid>
</>
)}
{(!!viewTechDocsLink || template.metadata.links?.length) && (
{(props.additionalLinks || template.metadata.links?.length) && (
<>
<Grid item xs={12}>
<Divider />
</Grid>
<Grid item xs={12}>
<Grid container spacing={2}>
{viewTechDocsLink && (
{props.additionalLinks?.map(({ icon, text, url }) => (
<Grid className={styles.linkText} item xs={6}>
<CardLink
icon={iconResolver('docs')}
text="View TechDocs"
url={viewTechDocsLink}
/>
<CardLink icon={icon} text={text} url={url} />
</Grid>
)}
))}
{template.metadata.links?.map(({ url, icon, title }) => (
<Grid className={styles.linkText} item xs={6}>
<CardLink
@@ -202,7 +176,12 @@ export const TemplateCard = (props: TemplateCardProps) => {
</>
)}
</div>
<Button size="small" variant="outlined" color="primary" to={href}>
<Button
size="small"
variant="outlined"
color="primary"
onClick={() => props.onSelected?.(template)}
>
Choose
</Button>
</div>
@@ -24,13 +24,22 @@ import {
import { Typography } from '@material-ui/core';
import { stringifyEntityRef } from '@backstage/catalog-model';
import { TemplateCardProps, TemplateCard } from '../TemplateCard';
import { IconComponent } from '@backstage/core-plugin-api';
/**
* The props for the {@link TemplateGroup} component.
* @alpha
*/
export interface TemplateGroupProps {
templates: TemplateEntityV1beta3[];
templates: {
template: TemplateEntityV1beta3;
additionalLinks?: {
icon: IconComponent;
text: string;
url: string;
}[];
}[];
onSelected: (template: TemplateEntityV1beta3) => void;
title: React.ReactNode;
components?: {
CardComponent?: React.ComponentType<TemplateCardProps>;
@@ -42,7 +51,12 @@ export interface TemplateGroupProps {
* @alpha
*/
export const TemplateGroup = (props: TemplateGroupProps) => {
const { templates, title, components: { CardComponent } = {} } = props;
const {
templates,
title,
components: { CardComponent } = {},
onSelected,
} = props;
const titleComponent =
typeof title === 'string' ? <ContentHeader title={title} /> : title;
@@ -67,8 +81,13 @@ export const TemplateGroup = (props: TemplateGroupProps) => {
<Content>
{titleComponent}
<ItemCardGrid>
{templates.map(template => (
<Card key={stringifyEntityRef(template)} template={template} />
{templates.map(({ template, additionalLinks }) => (
<Card
key={stringifyEntityRef(template)}
additionalLinks={additionalLinks}
template={template}
onSelected={onSelected}
/>
))}
</ItemCardGrid>
</Content>
@@ -18,4 +18,3 @@ export * from './extensions';
export * from './types';
export * from './lib';
export * from './hooks';
export * from './routes';
@@ -1,36 +0,0 @@
/*
* 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 { createRouteRef, createSubRouteRef } from '@backstage/core-plugin-api';
/** @alpha */
export const nextRouteRef = createRouteRef({
id: 'scaffolder/next',
});
/** @alpha */
export const nextSelectedTemplateRouteRef = createSubRouteRef({
id: 'scaffolder/next/selected-template',
parent: nextRouteRef,
path: '/templates/:namespace/:templateName',
});
/** @alpha */
export const nextScaffolderTaskRouteRef = createSubRouteRef({
id: 'scaffolder/next/task',
parent: nextRouteRef,
path: '/tasks/:taskId',
});
-83
View File
@@ -1,83 +0,0 @@
/*
* Copyright 2020 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 {
createExternalRouteRef,
createRouteRef,
createSubRouteRef,
} from '@backstage/core-plugin-api';
/** @public */
export const registerComponentRouteRef = createExternalRouteRef({
id: 'register-component',
optional: true,
});
/** @public */
export const viewTechDocRouteRef = createExternalRouteRef({
id: 'view-techdoc',
optional: true,
params: ['namespace', 'kind', 'name'],
});
/** @public */
export const rootRouteRef = createRouteRef({
id: 'scaffolder',
});
/**
* @deprecated This is the old template route, can be deleted before next major release
* @public
*/
export const legacySelectedTemplateRouteRef = createSubRouteRef({
id: 'scaffolder/legacy/selected-template',
parent: rootRouteRef,
path: '/templates/:templateName',
});
/** @public */
export const selectedTemplateRouteRef = createSubRouteRef({
id: 'scaffolder/selected-template',
parent: rootRouteRef,
path: '/templates/:namespace/:templateName',
});
/** @public */
export const scaffolderTaskRouteRef = createSubRouteRef({
id: 'scaffolder/task',
parent: rootRouteRef,
path: '/tasks/:taskId',
});
/** @public */
export const scaffolderListTaskRouteRef = createSubRouteRef({
id: 'scaffolder/list-tasks',
parent: rootRouteRef,
path: '/tasks',
});
/** @public */
export const actionsRouteRef = createSubRouteRef({
id: 'scaffolder/actions',
parent: rootRouteRef,
path: '/actions',
});
/** @public */
export const editRouteRef = createSubRouteRef({
id: 'scaffolder/edit',
parent: rootRouteRef,
path: '/edit',
});