Skip to content

Commit

Permalink
chore(dynamic-home-page): add plugin scaffold
Browse files Browse the repository at this point in the history
Signed-off-by: Christoph Jerolimov <jerolimov+git@redhat.com>
  • Loading branch information
christoph-jerolimov committed Nov 7, 2024
1 parent c81e0bd commit 31bc3ed
Show file tree
Hide file tree
Showing 20 changed files with 788 additions and 4 deletions.
1 change: 1 addition & 0 deletions workspaces/dynamic-home-page/packages/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"@backstage/theme": "^0.6.0",
"@material-ui/core": "^4.12.2",
"@material-ui/icons": "^4.9.1",
"@red-hat-developer-hub/backstage-plugin-dynamic-home-page": "workspace:^",
"react": "^18.0.2",
"react-dom": "^18.0.2",
"react-router": "^6.3.0",
Expand Down
5 changes: 3 additions & 2 deletions workspaces/dynamic-home-page/packages/app/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/
import React from 'react';
import { Navigate, Route } from 'react-router-dom';
import { Route } from 'react-router-dom';
import { apiDocsPlugin, ApiExplorerPage } from '@backstage/plugin-api-docs';
import {
CatalogEntityPage,
Expand Down Expand Up @@ -51,6 +51,7 @@ import { AppRouter, FlatRoutes } from '@backstage/core-app-api';
import { CatalogGraphPage } from '@backstage/plugin-catalog-graph';
import { RequirePermission } from '@backstage/plugin-permission-react';
import { catalogEntityCreatePermission } from '@backstage/plugin-catalog-common/alpha';
import { DynamicHomePagePage } from '@red-hat-developer-hub/backstage-plugin-dynamic-home-page';

const app = createApp({
apis,
Expand Down Expand Up @@ -78,7 +79,7 @@ const app = createApp({

const routes = (
<FlatRoutes>
<Route path="/" element={<Navigate to="catalog" />} />
<Route path="/" element={<DynamicHomePagePage />} />
<Route path="/catalog" element={<CatalogIndexPage />} />
<Route
path="/catalog/:namespace/:kind/:name"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* limitations under the License.
*/
import React, { PropsWithChildren } from 'react';
import { CatalogIcon } from '@backstage/core-components';
import { makeStyles } from '@material-ui/core';
import HomeIcon from '@material-ui/icons/Home';
import ExtensionIcon from '@material-ui/icons/Extension';
Expand Down Expand Up @@ -81,7 +82,8 @@ export const Root = ({ children }: PropsWithChildren<{}>) => (
<SidebarDivider />
<SidebarGroup label="Menu" icon={<MenuIcon />}>
{/* Global nav, not org-specific */}
<SidebarItem icon={HomeIcon} to="catalog" text="Home" />
<SidebarItem icon={HomeIcon} to="" text="Home" />
<SidebarItem icon={CatalogIcon} to="catalog" text="Catalog" />
<MyGroupsSidebarItem
singularTitle="My Group"
pluralTitle="My Groups"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('@backstage/cli/config/eslint-factory')(__dirname);
13 changes: 13 additions & 0 deletions workspaces/dynamic-home-page/plugins/dynamic-home-page/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# dynamic-home-page

Welcome to the dynamic-home-page plugin!

_This plugin was created through the Backstage CLI_

## Getting started

Your plugin has been added to the example app in this repository, meaning you'll be able to access it by running `yarn start` in the root directory, and then navigating to [/dynamic-home-page](http://localhost:3000/dynamic-home-page).

You can also serve the plugin in isolation by running `yarn start` in the plugin directory.
This method of serving the plugin provides quicker iteration speed and a faster startup and hot reloads.
It is only meant for local development, and the setup for it can be found inside the [/dev](./dev) directory.
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
## API Report File for "@red-hat-developer-hub/backstage-plugin-dynamic-home-page"

> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
```ts
/// <reference types="react" />

import { BackstagePlugin } from '@backstage/core-plugin-api';
import { JSX as JSX_2 } from 'react';
import { RouteRef } from '@backstage/core-plugin-api';

// @public (undocumented)
export const DynamicHomePagePage: () => JSX_2.Element;

// @public (undocumented)
export const dynamicHomePagePlugin: BackstagePlugin<
{
root: RouteRef<undefined>;
},
{},
{}
>;

// (No @packageDocumentation comment for this package)
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright 2024 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 React from 'react';
import { createDevApp } from '@backstage/dev-utils';
import { dynamicHomePagePlugin, DynamicHomePagePage } from '../src/plugin';

createDevApp()
.registerPlugin(dynamicHomePagePlugin)
.addPage({
element: <DynamicHomePagePage />,
title: 'Root Page',
path: '/dynamic-home-page',
})
.render();
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
{
"name": "@red-hat-developer-hub/backstage-plugin-dynamic-home-page",
"version": "0.1.0",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
"private": true,
"publishConfig": {
"access": "public",
"main": "dist/index.esm.js",
"types": "dist/index.d.ts"
},
"repository": {
"type": "git",
"url": "https://github.com/redhat-developer/rhdh-plugins",
"directory": "workspaces/dynamic-home-page/plugins/dynamic-home-page"
},
"backstage": {
"role": "frontend-plugin",
"pluginId": "dynamic-home-page",
"pluginPackages": [
"@red-hat-developer-hub/backstage-plugin-dynamic-home-page"
]
},
"sideEffects": false,
"scripts": {
"start": "backstage-cli package start",
"build": "backstage-cli package build",
"lint": "backstage-cli package lint",
"test": "backstage-cli package test",
"clean": "backstage-cli package clean",
"prepack": "backstage-cli package prepack",
"postpack": "backstage-cli package postpack"
},
"dependencies": {
"@backstage/core-components": "^0.15.1",
"@backstage/core-plugin-api": "^1.10.0",
"@backstage/theme": "^0.6.0",
"@material-ui/core": "^4.9.13",
"@material-ui/icons": "^4.9.1",
"@material-ui/lab": "^4.0.0-alpha.61",
"react-use": "^17.2.4"
},
"peerDependencies": {
"react": "^16.13.1 || ^17.0.0 || ^18.0.0"
},
"devDependencies": {
"@backstage/cli": "^0.28.0",
"@backstage/core-app-api": "^1.15.1",
"@backstage/dev-utils": "^1.1.2",
"@backstage/test-utils": "^1.7.0",
"@testing-library/jest-dom": "^6.0.0",
"@testing-library/react": "^14.0.0",
"@testing-library/user-event": "^14.0.0",
"msw": "^1.0.0",
"react": "^16.13.1 || ^17.0.0 || ^18.0.0"
},
"files": [
"dist"
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright 2024 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 React from 'react';
import { ExampleComponent } from './ExampleComponent';
import { rest } from 'msw';
import { setupServer } from 'msw/node';
import { screen } from '@testing-library/react';
import { registerMswTestHooks, renderInTestApp } from '@backstage/test-utils';

describe('ExampleComponent', () => {
const server = setupServer();
// Enable sane handlers for network requests
registerMswTestHooks(server);

// setup mock response
beforeEach(() => {
server.use(
rest.get('/*', (_, res, ctx) => res(ctx.status(200), ctx.json({}))),
);
});

it('should render', async () => {
await renderInTestApp(<ExampleComponent />);
expect(
screen.getByText('Welcome to dynamic-home-page!'),
).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright 2024 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 React from 'react';
import { Typography, Grid } from '@material-ui/core';
import {
InfoCard,
Header,
Page,
Content,
ContentHeader,
HeaderLabel,
SupportButton,
} from '@backstage/core-components';
import { ExampleFetchComponent } from '../ExampleFetchComponent';

export const ExampleComponent = () => (
<Page themeId="tool">
<Header title="Welcome to dynamic-home-page!" subtitle="Optional subtitle">
<HeaderLabel label="Owner" value="Team X" />
<HeaderLabel label="Lifecycle" value="Alpha" />
</Header>
<Content>
<ContentHeader title="Plugin title">
<SupportButton>A description of your plugin goes here.</SupportButton>
</ContentHeader>
<Grid container spacing={3} direction="column">
<Grid item>
<InfoCard title="Information card">
<Typography variant="body1">
All content should be wrapped in a card like this.
</Typography>
</InfoCard>
</Grid>
<Grid item>
<ExampleFetchComponent />
</Grid>
</Grid>
</Content>
</Page>
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* Copyright 2024 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.
*/
export { ExampleComponent } from './ExampleComponent';
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright 2024 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 React from 'react';
import { render, screen } from '@testing-library/react';
import { ExampleFetchComponent } from './ExampleFetchComponent';

describe('ExampleFetchComponent', () => {
it('renders the user table', async () => {
render(<ExampleFetchComponent />);

// Wait for the table to render
const table = await screen.findByRole('table');
const nationality = screen.getAllByText('GB');
// Assert that the table contains the expected user data
expect(table).toBeInTheDocument();
expect(screen.getByAltText('Carolyn')).toBeInTheDocument();
expect(screen.getByText('Carolyn Moore')).toBeInTheDocument();
expect(screen.getByText('carolyn.moore@example.com')).toBeInTheDocument();
expect(nationality[0]).toBeInTheDocument();
});
});
Loading

0 comments on commit 31bc3ed

Please sign in to comment.