chore: resolve conflicts
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@backstage/plugin-techdocs",
|
||||
"version": "0.1.1-alpha.23",
|
||||
"version": "0.1.1-alpha.24",
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
"license": "Apache-2.0",
|
||||
@@ -22,12 +22,12 @@
|
||||
"clean": "backstage-cli clean"
|
||||
},
|
||||
"dependencies": {
|
||||
"@backstage/catalog-model": "^0.1.1-alpha.23",
|
||||
"@backstage/core": "^0.1.1-alpha.23",
|
||||
"@backstage/core-api": "^0.1.1-alpha.23",
|
||||
"@backstage/plugin-catalog": "^0.1.1-alpha.23",
|
||||
"@backstage/test-utils": "^0.1.1-alpha.23",
|
||||
"@backstage/theme": "^0.1.1-alpha.23",
|
||||
"@backstage/catalog-model": "^0.1.1-alpha.24",
|
||||
"@backstage/core": "^0.1.1-alpha.24",
|
||||
"@backstage/core-api": "^0.1.1-alpha.24",
|
||||
"@backstage/plugin-catalog": "^0.1.1-alpha.24",
|
||||
"@backstage/test-utils": "^0.1.1-alpha.24",
|
||||
"@backstage/theme": "^0.1.1-alpha.24",
|
||||
"@material-ui/core": "^4.11.0",
|
||||
"@material-ui/icons": "^4.9.1",
|
||||
"@material-ui/lab": "4.0.0-alpha.45",
|
||||
@@ -40,8 +40,8 @@
|
||||
"sanitize-html": "^1.27.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.1.1-alpha.23",
|
||||
"@backstage/dev-utils": "^0.1.1-alpha.23",
|
||||
"@backstage/cli": "^0.1.1-alpha.24",
|
||||
"@backstage/dev-utils": "^0.1.1-alpha.24",
|
||||
"@testing-library/jest-dom": "^5.10.1",
|
||||
"@testing-library/react": "^10.4.1",
|
||||
"@testing-library/user-event": "^12.0.7",
|
||||
|
||||
@@ -23,7 +23,7 @@ export const EntityPageDocs = ({ entity }: { entity: Entity }) => {
|
||||
<Reader
|
||||
entityId={{
|
||||
kind: entity.kind,
|
||||
namespace: entity.metadata.namespace,
|
||||
namespace: entity.metadata.namespace ?? 'default',
|
||||
name: entity.metadata.name,
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -17,8 +17,7 @@
|
||||
import React from 'react';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { Route, Routes } from 'react-router-dom';
|
||||
import { WarningPanel } from '@backstage/core';
|
||||
|
||||
import { MissingAnnotationEmptyState } from '@backstage/core';
|
||||
import {
|
||||
rootRouteRef,
|
||||
rootDocsRouteRef,
|
||||
@@ -43,15 +42,7 @@ export const EmbeddedDocsRouter = ({ entity }: { entity: Entity }) => {
|
||||
const projectId = entity.metadata.annotations?.[TECHDOCS_ANNOTATION];
|
||||
|
||||
if (!projectId) {
|
||||
return (
|
||||
<WarningPanel title="Techdocs plugin:">
|
||||
<pre>{TECHDOCS_ANNOTATION}</pre> annotation is missing on the entity.
|
||||
<br />
|
||||
<a href="https://backstage.io/docs/features/techdocs/creating-and-publishing">
|
||||
Getting Started
|
||||
</a>
|
||||
</WarningPanel>
|
||||
);
|
||||
return <MissingAnnotationEmptyState annotation={TECHDOCS_ANNOTATION} />;
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -28,7 +28,7 @@ describe('TechDocsStorageApi', () => {
|
||||
const storageApi = new TechDocsStorageApi({ apiOrigin: DOC_STORAGE_URL });
|
||||
|
||||
expect(storageApi.getBaseUrl('test.js', mockEntity, '')).toEqual(
|
||||
`${DOC_STORAGE_URL}/docs/${mockEntity.kind}/${mockEntity.namespace}/${mockEntity.name}/test.js`,
|
||||
`${DOC_STORAGE_URL}/docs/${mockEntity.namespace}/${mockEntity.kind}/${mockEntity.name}/test.js`,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -36,7 +36,7 @@ describe('TechDocsStorageApi', () => {
|
||||
const storageApi = new TechDocsStorageApi({ apiOrigin: DOC_STORAGE_URL });
|
||||
|
||||
expect(storageApi.getBaseUrl('test/', mockEntity, '')).toEqual(
|
||||
`${DOC_STORAGE_URL}/docs/${mockEntity.kind}/${mockEntity.namespace}/${mockEntity.name}/test/`,
|
||||
`${DOC_STORAGE_URL}/docs/${mockEntity.namespace}/${mockEntity.kind}/${mockEntity.name}/test/`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -51,9 +51,7 @@ export class TechDocsApi implements TechDocs {
|
||||
async getMetadata(metadataType: string, entityId: ParsedEntityId) {
|
||||
const { kind, namespace, name } = entityId;
|
||||
|
||||
const requestUrl = `${this.apiOrigin}/metadata/${metadataType}/${kind}/${
|
||||
namespace ? namespace : 'default'
|
||||
}/${name}`;
|
||||
const requestUrl = `${this.apiOrigin}/metadata/${metadataType}/${namespace}/${kind}/${name}`;
|
||||
|
||||
const request = await fetch(`${requestUrl}`);
|
||||
const res = await request.json();
|
||||
@@ -72,9 +70,7 @@ export class TechDocsStorageApi implements TechDocsStorage {
|
||||
async getEntityDocs(entityId: ParsedEntityId, path: string) {
|
||||
const { kind, namespace, name } = entityId;
|
||||
|
||||
const url = `${this.apiOrigin}/docs/${kind}/${
|
||||
namespace ? namespace : 'default'
|
||||
}/${name}/${path}`;
|
||||
const url = `${this.apiOrigin}/docs/${namespace}/${kind}/${name}/${path}`;
|
||||
|
||||
const request = await fetch(
|
||||
`${url.endsWith('/') ? url : `${url}/`}index.html`,
|
||||
@@ -96,9 +92,7 @@ export class TechDocsStorageApi implements TechDocsStorage {
|
||||
|
||||
return new URL(
|
||||
oldBaseUrl,
|
||||
`${this.apiOrigin}/docs/${kind}/${
|
||||
namespace ? namespace : 'default'
|
||||
}/${name}/${path}`,
|
||||
`${this.apiOrigin}/docs/${namespace}/${kind}/${name}/${path}`,
|
||||
).toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ export const rootRouteRef = createRouteRef({
|
||||
});
|
||||
|
||||
export const rootDocsRouteRef = createRouteRef({
|
||||
path: ':entityId/*',
|
||||
path: ':namespace/:kind/:name/*',
|
||||
title: 'Docs',
|
||||
});
|
||||
|
||||
|
||||
@@ -116,6 +116,7 @@ export const Reader = ({ entityId, onReady }: Props) => {
|
||||
return dom;
|
||||
},
|
||||
addLinkClickListener({
|
||||
baseUrl: window.location.origin,
|
||||
onClick: (_: MouseEvent, url: string) => {
|
||||
const parsedUrl = new URL(url);
|
||||
navigate(`${parsedUrl.pathname}${parsedUrl.hash}`);
|
||||
|
||||
@@ -97,9 +97,9 @@ export const TechDocsHome = () => {
|
||||
onClick={() =>
|
||||
navigate(
|
||||
generatePath(rootDocsRouteRef.path, {
|
||||
entityId: `${entity.kind}:${
|
||||
entity.metadata.namespace ?? ''
|
||||
}:${entity.metadata.name}`,
|
||||
namespace: entity.metadata.namespace ?? 'default',
|
||||
kind: entity.kind,
|
||||
name: entity.metadata.name,
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -27,8 +27,7 @@ import { techdocsApiRef } from '../../api';
|
||||
export const TechDocsPage = () => {
|
||||
const backstageTheme = useTheme<BackstageTheme>();
|
||||
const [documentReady, setDocumentReady] = useState<boolean>(false);
|
||||
const { entityId } = useParams();
|
||||
const [kind, namespace, name] = entityId.split(':');
|
||||
const { namespace, kind, name } = useParams();
|
||||
|
||||
const techDocsApi = useApi(techdocsApiRef);
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ describe('<TechDocsPageHeader />', () => {
|
||||
),
|
||||
);
|
||||
expect(rendered.container.innerHTML).toContain('header');
|
||||
expect(rendered.getByText('test-site-name')).toBeDefined();
|
||||
expect(rendered.getAllByText('test-site-name')).toHaveLength(2);
|
||||
expect(rendered.getByText('test-site-desc')).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -48,12 +48,14 @@ export const TechDocsPageHeader = ({
|
||||
spec: { owner, lifecycle },
|
||||
} = entityMetadataValues || { spec: {} };
|
||||
|
||||
const componentLink = `/catalog/${kind}/${name}`;
|
||||
|
||||
const labels = (
|
||||
<>
|
||||
<HeaderLabel
|
||||
label="Component"
|
||||
value={
|
||||
<Link style={{ color: '#fff' }} to={`/catalog/${kind}/${name}`}>
|
||||
<Link style={{ color: '#fff' }} to={componentLink}>
|
||||
{name}
|
||||
</Link>
|
||||
}
|
||||
@@ -66,7 +68,11 @@ export const TechDocsPageHeader = ({
|
||||
<HeaderLabel
|
||||
label=""
|
||||
value={
|
||||
<a href={locationMetadata.target} target="_blank">
|
||||
<a
|
||||
href={locationMetadata.target}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<GitHubIcon style={{ marginTop: '-25px', fill: '#fff' }} />
|
||||
</a>
|
||||
}
|
||||
@@ -81,6 +87,8 @@ export const TechDocsPageHeader = ({
|
||||
subtitle={
|
||||
siteDescription && siteDescription !== 'None' ? siteDescription : ''
|
||||
}
|
||||
type={name}
|
||||
typeLink={componentLink}
|
||||
>
|
||||
{labels}
|
||||
</Header>
|
||||
|
||||
@@ -14,23 +14,61 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { createTestShadowDom, FIXTURES } from '../../test-utils';
|
||||
import { createTestShadowDom } from '../../test-utils';
|
||||
import { addLinkClickListener } from '.';
|
||||
|
||||
describe('addLinkClickListener', () => {
|
||||
it('calls onClick when a link has been clicked', () => {
|
||||
const fn = jest.fn();
|
||||
const shadowDom = createTestShadowDom(FIXTURES.FIXTURE_STANDARD_PAGE, {
|
||||
preTransformers: [],
|
||||
postTransformers: [
|
||||
addLinkClickListener({
|
||||
onClick: fn,
|
||||
}),
|
||||
],
|
||||
});
|
||||
const shadowDom = createTestShadowDom(
|
||||
`
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<a href="http://localhost:3000/docs/test">Link</a>
|
||||
</body>
|
||||
</html>
|
||||
`,
|
||||
{
|
||||
preTransformers: [],
|
||||
postTransformers: [
|
||||
addLinkClickListener({
|
||||
baseUrl: 'http://localhost:3000',
|
||||
onClick: fn,
|
||||
}),
|
||||
],
|
||||
},
|
||||
);
|
||||
|
||||
shadowDom.querySelector('a')?.click();
|
||||
|
||||
expect(fn).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('does not call onClick when a link links to another baseUrl', () => {
|
||||
const fn = jest.fn();
|
||||
const shadowDom = createTestShadowDom(
|
||||
`
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<a href="http://example.com/docs/test">Link</a>
|
||||
</body>
|
||||
</html>
|
||||
`,
|
||||
{
|
||||
preTransformers: [],
|
||||
postTransformers: [
|
||||
addLinkClickListener({
|
||||
baseUrl: 'http://localhost:3000',
|
||||
onClick: fn,
|
||||
}),
|
||||
],
|
||||
},
|
||||
);
|
||||
|
||||
shadowDom.querySelector('a')?.click();
|
||||
|
||||
expect(fn).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -17,10 +17,12 @@
|
||||
import type { Transformer } from './index';
|
||||
|
||||
type AddLinkClickListenerOptions = {
|
||||
baseUrl: string;
|
||||
onClick: (e: MouseEvent, newUrl: string) => void;
|
||||
};
|
||||
|
||||
export const addLinkClickListener = ({
|
||||
baseUrl,
|
||||
onClick,
|
||||
}: AddLinkClickListenerOptions): Transformer => {
|
||||
return dom => {
|
||||
@@ -28,8 +30,9 @@ export const addLinkClickListener = ({
|
||||
elem.addEventListener('click', (e: MouseEvent) => {
|
||||
const target = e.target as HTMLAnchorElement;
|
||||
const href = target?.getAttribute('href');
|
||||
|
||||
if (!href) return;
|
||||
if (!href.match(/^https?:\/\//i)) {
|
||||
if (href.startsWith(baseUrl)) {
|
||||
e.preventDefault();
|
||||
onClick(e, target.getAttribute('href')!);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user