Skip to content

Commit

Permalink
TechDocs Homepage (backstage#4401)
Browse files Browse the repository at this point in the history
* add tabs to homepage

Signed-off-by: Emma Indal <[email protected]>

* add new overview content component

Signed-off-by: Emma Indal <[email protected]>

* add new owned content component

Signed-off-by: Emma Indal <[email protected]>

* add types

Signed-off-by: Emma Indal <[email protected]>

* add test for owned content component

Signed-off-by: Emma Indal <[email protected]>

* add test for overview content

Signed-off-by: Emma Indal <[email protected]>

* document name to link and change copy to clipboard link

Signed-off-by: Emma Indal <[email protected]>

* add changeset

Signed-off-by: Emma Indal <[email protected]>

* rename changeset file

Signed-off-by: Emma Indal <[email protected]>

* fix types

Signed-off-by: Emma Indal <[email protected]>

* move home components out from reader dir to its own dir

Signed-off-by: Emma Indal <[email protected]>

* Update plugins/techdocs/src/reader/components/OverviewContent.tsx

Co-authored-by: Himanshu Mishra <[email protected]>
Signed-off-by: Emma Indal <[email protected]>

* enable search in table

Signed-off-by: Emma Indal <[email protected]>

* add docs icon to core icons

Signed-off-by: Emma Indal <[email protected]>

* add example TechDocs support button config

Signed-off-by: Emma Indal <[email protected]>

* use isOwnerOff and useOwnUser to see documents that are owned via group membership

Signed-off-by: Emma Indal <[email protected]>

* update tests

Signed-off-by: Emma Indal <[email protected]>

* cleanup imports

Signed-off-by: Emma Indal <[email protected]>

* leave techdocs support config out of this PR

Signed-off-by: Emma Indal <[email protected]>

* prettieeeeeer

Signed-off-by: Emma Indal <[email protected]>

* copy paste useOwnUser hook over to techdocs plugin

Signed-off-by: Emma Indal <[email protected]>

* add changeset

Signed-off-by: Emma Indal <[email protected]>

* delete unused package

Signed-off-by: Emma Indal <[email protected]>

Co-authored-by: Himanshu Mishra <[email protected]>
  • Loading branch information
emmaindal and OrkoHunter authored Mar 11, 2021
1 parent 3ece07e commit c8b54c3
Show file tree
Hide file tree
Showing 14 changed files with 482 additions and 40 deletions.
5 changes: 5 additions & 0 deletions .changeset/techdocs-tame-spies-kneel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@backstage/plugin-techdocs': patch
---

Extended TechDocs HomePage with owned documents
5 changes: 5 additions & 0 deletions .changeset/tender-keys-study.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@backstage/core-api': patch
---

Added new Docs Icon to Core Icons
4 changes: 4 additions & 0 deletions packages/core-api/src/icons/icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import MuiHelpIcon from '@material-ui/icons/Help';
import MuiPeopleIcon from '@material-ui/icons/People';
import MuiPersonIcon from '@material-ui/icons/Person';
import MuiWarningIcon from '@material-ui/icons/Warning';
import MuiDocsIcon from '@material-ui/icons/Description';

import React from 'react';
import { useApp } from '../app/AppContext';
import { IconComponent, IconComponentMap, SystemIconKey } from './types';
Expand All @@ -38,6 +40,7 @@ export const defaultSystemIcons: IconComponentMap = {
help: MuiHelpIcon,
user: MuiPersonIcon,
warning: MuiWarningIcon,
docs: MuiDocsIcon,
};

const overridableSystemIcon = (key: SystemIconKey): IconComponent => {
Expand All @@ -58,3 +61,4 @@ export const GroupIcon = overridableSystemIcon('group');
export const HelpIcon = overridableSystemIcon('help');
export const UserIcon = overridableSystemIcon('user');
export const WarningIcon = overridableSystemIcon('warning');
export const DocsIcon = overridableSystemIcon('docs');
3 changes: 2 additions & 1 deletion packages/core-api/src/icons/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ export type SystemIconKey =
| 'group'
| 'help'
| 'user'
| 'warning';
| 'warning'
| 'docs';

export type IconComponent = ComponentType<SvgIconProps>;
export type IconKey = SystemIconKey | string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ metadata:
spec:
type: service
lifecycle: experimental
owner: [email protected]
owner: user:guest
2 changes: 1 addition & 1 deletion plugins/techdocs/src/Router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {
rootDocsRouteRef,
rootCatalogDocsRouteRef,
} from './plugin';
import { TechDocsHome } from './reader/components/TechDocsHome';
import { TechDocsHome } from './home/components/TechDocsHome';
import { TechDocsPage } from './reader/components/TechDocsPage';
import { EntityPageDocs } from './EntityPageDocs';

Expand Down
62 changes: 62 additions & 0 deletions plugins/techdocs/src/home/components/OverviewContent.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright 2020 Spotify AB
*
* 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 { wrapInTestApp } from '@backstage/test-utils';
import { render } from '@testing-library/react';
import React from 'react';
import { OverviewContent } from './OverviewContent';

describe('TechDocs Overview Content', () => {
it('should render all TechDocs Documents', async () => {
const { findByText } = render(
wrapInTestApp(
<OverviewContent
entities={[
{
apiVersion: 'version',
kind: 'TestKind',
metadata: {
name: 'testName',
},
spec: {
owner: '[email protected]',
},
},
{
apiVersion: 'version',
kind: 'TestKind2',
metadata: {
name: 'testName2',
},
spec: {
owner: '[email protected]',
},
},
]}
/>,
),
);

expect(await findByText('Overview')).toBeInTheDocument();
expect(
await findByText(
/Explore your internal technical ecosystem through documentation./i,
),
).toBeInTheDocument();
expect(await findByText('testName')).toBeInTheDocument();
expect(await findByText('testName2')).toBeInTheDocument();
});
});
73 changes: 73 additions & 0 deletions plugins/techdocs/src/home/components/OverviewContent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Copyright 2020 Spotify AB
*
* 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 React from 'react';
import { generatePath } from 'react-router-dom';

import { Entity } from '@backstage/catalog-model';
import {
Button,
Content,
ContentHeader,
SupportButton,
ItemCardGrid,
ItemCardHeader,
} from '@backstage/core';
import { Card, CardActions, CardContent, CardMedia } from '@material-ui/core';

import { rootDocsRouteRef } from '../../plugin';

export const OverviewContent = ({
entities,
}: {
entities: Entity[] | undefined;
}) => {
if (!entities) return null;
return (
<Content>
<ContentHeader
title="Overview"
description="Explore your internal technical ecosystem through documentation."
>
<SupportButton>Discover documentation in your ecosystem.</SupportButton>
</ContentHeader>
<ItemCardGrid data-testid="docs-explore">
{!entities?.length
? null
: entities.map((entity, index: number) => (
<Card key={index}>
<CardMedia>
<ItemCardHeader title={entity.metadata.name} />
</CardMedia>
<CardContent>{entity.metadata.description}</CardContent>
<CardActions>
<Button
to={generatePath(rootDocsRouteRef.path, {
namespace: entity.metadata.namespace ?? 'default',
kind: entity.kind,
name: entity.metadata.name,
})}
color="primary"
>
Read Docs
</Button>
</CardActions>
</Card>
))}
</ItemCardGrid>
</Content>
);
};
109 changes: 109 additions & 0 deletions plugins/techdocs/src/home/components/OwnedContent.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
* Copyright 2020 Spotify AB
*
* 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 React from 'react';
import { render } from '@testing-library/react';
import { wrapInTestApp } from '@backstage/test-utils';
import { OwnedContent } from './OwnedContent';

jest.mock('../hooks', () => ({
useOwnUser: () => {
return {
value: {
apiVersion: 'version',
kind: 'User',
metadata: {
name: 'owned',
namespace: 'default',
},
relations: [
{
target: {
kind: 'TestKind',
name: 'testName',
},
type: 'ownerOf',
},
],
},
};
},
}));

describe('TechDocs Owned Content', () => {
it('should render TechDocs Owned Documents', async () => {
const { findByText, queryByText } = render(
wrapInTestApp(
<OwnedContent
entities={[
{
apiVersion: 'version',
kind: 'TestKind',
metadata: {
name: 'testName',
},
spec: {
owner: 'user:owned',
},
relations: [
{
target: {
kind: 'user',
namespace: 'default',
name: 'owned',
},
type: 'ownedBy',
},
],
},
{
apiVersion: 'version',
kind: 'TestKind2',
metadata: {
name: 'testName2',
},
spec: {
owner: '[email protected]',
},
relations: [
{
target: {
kind: 'user',
namespace: 'default',
name: 'not-owned',
},
type: 'ownedBy',
},
],
},
]}
/>,
),
);

expect(await findByText('Owned documents')).toBeInTheDocument();
expect(await findByText(/Access your documentation./i)).toBeInTheDocument();
expect(await findByText('testName')).toBeInTheDocument();
expect(await queryByText('testName2')).not.toBeInTheDocument();
});

it('should render empty state if no owned documents exist', async () => {
const { findByText } = render(
wrapInTestApp(<OwnedContent entities={[]} />),
);

expect(await findByText('No documents to show')).toBeInTheDocument();
});
});
Loading

0 comments on commit c8b54c3

Please sign in to comment.