diff --git a/.changeset/yellow-rings-invent.md b/.changeset/yellow-rings-invent.md new file mode 100644 index 0000000000..f0335ff492 --- /dev/null +++ b/.changeset/yellow-rings-invent.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +MissingAnnotationEmptyState component can now dynamically generate a YAML example based off the current entity being used. diff --git a/packages/core-components/package.json b/packages/core-components/package.json index d8cc5057ff..e68320ad0c 100644 --- a/packages/core-components/package.json +++ b/packages/core-components/package.json @@ -33,9 +33,11 @@ "start": "backstage-cli package start" }, "dependencies": { + "@backstage/catalog-model": "workspace:^", "@backstage/config": "workspace:^", "@backstage/core-plugin-api": "workspace:^", "@backstage/errors": "workspace:^", + "@backstage/plugin-catalog-react": "workspace:^", "@backstage/theme": "workspace:^", "@backstage/version-bridge": "workspace:^", "@date-io/core": "^1.3.13", diff --git a/packages/core-components/src/components/EmptyState/MissingAnnotationEmptyState.tsx b/packages/core-components/src/components/EmptyState/MissingAnnotationEmptyState.tsx index 9fc9eee959..c89129670a 100644 --- a/packages/core-components/src/components/EmptyState/MissingAnnotationEmptyState.tsx +++ b/packages/core-components/src/components/EmptyState/MissingAnnotationEmptyState.tsx @@ -25,23 +25,8 @@ import { CodeSnippet } from '../CodeSnippet'; import { Link } from '../Link'; import { EmptyState } from './EmptyState'; -const COMPONENT_YAML_TEMPLATE = `apiVersion: backstage.io/v1alpha1 -kind: Component -metadata: - name: example - description: example.com - annotations: - ANNOTATION: value -spec: - type: website - lifecycle: production - owner: user:guest`; - -const ANNOTATION_REGEXP = /^.*ANNOTATION.*$/m; -const ANNOTATION_YAML = COMPONENT_YAML_TEMPLATE.match(ANNOTATION_REGEXP)![0]; -const ANNOTATION_LINE = COMPONENT_YAML_TEMPLATE.split('\n').findIndex(line => - ANNOTATION_REGEXP.test(line), -); +import { useEntity } from '@backstage/plugin-catalog-react'; +import { Entity } from '@backstage/catalog-model'; type Props = { annotation: string | string[]; @@ -62,19 +47,38 @@ const useStyles = makeStyles( { name: 'BackstageMissingAnnotationEmptyState' }, ); -function generateLineNumbers(lineCount: number) { - return Array.from(Array(lineCount + 1).keys(), i => i + ANNOTATION_LINE); +function generateYamlExample( + annotations: string[], + entity?: Entity, +): { yamlText: string; lineNumbers: number[] } { + const kind = entity?.kind || 'Component'; + const name = entity?.metadata.name || 'example'; + const type = entity?.spec?.type || 'website'; + const owner = entity?.spec?.owner || 'user:default/guest'; + + const yamlText = `apiVersion: backstage.io/v1alpha1 +kind: ${kind} +metadata: + name: ${name} + annotations:${annotations.map(ann => `\n ${ann}: value`).join('')} +spec: + type: ${type} + owner: ${owner}`; + + let line = 6; // Line 6 is the line number that annotations are added to. + const lineNumbers: number[] = []; + annotations.forEach(() => { + lineNumbers.push(line); + line++; + }); + + return { + yamlText, + lineNumbers, + }; } -function generateComponentYaml(annotations: string[]) { - const annotationYaml = annotations - .map(ann => ANNOTATION_YAML.replace('ANNOTATION', ann)) - .join('\n'); - - return COMPONENT_YAML_TEMPLATE.replace(ANNOTATION_YAML, annotationYaml); -} - -function generateDescription(annotations: string[]) { +function generateDescription(annotations: string[], entityKind = 'Component') { const isSingular = annotations.length <= 1; return ( <> @@ -87,13 +91,21 @@ function generateDescription(annotations: string[]) { ))}{' '} {isSingular ? 'is' : 'are'} missing. You need to add the{' '} - {isSingular ? 'annotation' : 'annotations'} to your component if you want - to enable this tool. + {isSingular ? 'annotation' : 'annotations'} to your {entityKind} if you + want to enable this tool. ); } export function MissingAnnotationEmptyState(props: Props) { + let entity: Entity | undefined; + try { + const entityContext = useEntity(); + entity = entityContext.entity; + } catch (err) { + // ignore when entity context doesnt exist + } + const { annotation, readMoreUrl } = props; const annotations = Array.isArray(annotation) ? annotation : [annotation]; const url = @@ -101,23 +113,25 @@ export function MissingAnnotationEmptyState(props: Props) { 'https://backstage.io/docs/features/software-catalog/well-known-annotations'; const classes = useStyles(); + const entityKind = entity?.kind || 'Component'; + const { yamlText, lineNumbers } = generateYamlExample(annotations, entity); return ( - Add the annotation to your component YAML as shown in the + Add the annotation to your {entityKind} YAML as shown in the highlighted example below: diff --git a/plugins/vault/src/components/EntityVaultCard/EntityVaultCard.test.tsx b/plugins/vault/src/components/EntityVaultCard/EntityVaultCard.test.tsx index f46aa1e4c2..9450ddc41d 100644 --- a/plugins/vault/src/components/EntityVaultCard/EntityVaultCard.test.tsx +++ b/plugins/vault/src/components/EntityVaultCard/EntityVaultCard.test.tsx @@ -46,7 +46,7 @@ describe('EntityVaultCard', () => { , ); expect( - rendered.getByText(/Add the annotation to your component YAML/), + rendered.getByText(/Add the annotation to your Component YAML/), ).toBeInTheDocument(); }); }); diff --git a/yarn.lock b/yarn.lock index a1c2c0c308..3badc585b4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3973,11 +3973,13 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/core-components@workspace:packages/core-components" dependencies: + "@backstage/catalog-model": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" "@backstage/core-app-api": "workspace:^" "@backstage/core-plugin-api": "workspace:^" "@backstage/errors": "workspace:^" + "@backstage/plugin-catalog-react": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/theme": "workspace:^" "@backstage/version-bridge": "workspace:^"