This commit is contained in:
Med Mouine
2024-04-18 10:23:04 -04:00
parent aab6410176
commit 089a1cd890
19385 changed files with 147197 additions and 230 deletions

View File

@@ -17,6 +17,7 @@
"@backstage/app-defaults": "^1.5.3",
"@backstage/catalog-model": "^1.4.5",
"@backstage/cli": "^0.26.2",
"@backstage/config": "^1.2.0",
"@backstage/core-app-api": "^1.12.3",
"@backstage/core-components": "^0.14.3",
"@backstage/core-plugin-api": "^1.9.1",
@@ -28,19 +29,26 @@
"@backstage/plugin-catalog-import": "^0.10.9",
"@backstage/plugin-catalog-react": "^1.11.2",
"@backstage/plugin-github-actions": "^0.6.14",
"@backstage/plugin-github-deployments": "^0.1.64",
"@backstage/plugin-home": "^0.7.2",
"@backstage/plugin-org": "^0.6.23",
"@backstage/plugin-permission-react": "^0.4.21",
"@backstage/plugin-scaffolder": "^1.19.2",
"@backstage/plugin-search": "^1.4.9",
"@backstage/plugin-search-react": "^1.7.9",
"@backstage/plugin-tech-insights": "^0.3.25",
"@backstage/plugin-tech-radar": "^0.7.2",
"@backstage/plugin-techdocs": "^1.10.3",
"@backstage/plugin-techdocs-module-addons-contrib": "^1.1.8",
"@backstage/plugin-techdocs-react": "^1.2.2",
"@backstage/plugin-user-settings": "^0.8.4",
"@backstage/test-utils": "^1.5.3",
"@backstage/theme": "^0.5.2",
"@k-phoen/backstage-plugin-grafana": "^0.1.22",
"@material-ui/core": "^4.12.2",
"@material-ui/icons": "^4.9.1",
"@pagerduty/backstage-plugin": "^0.11.0",
"@roadiehq/backstage-plugin-argo-cd": "^2.6.4",
"@roadiehq/backstage-plugin-github-insights": "^2.3.28",
"@roadiehq/backstage-plugin-prometheus": "^2.8.7",
"@workm8/backstage-docker-tags": "^1.0.5",
"history": "^5.0.0",
"react": "^18.0.2",
"react-dom": "^18.0.2",
@@ -51,10 +59,10 @@
"devDependencies": {
"@backstage/test-utils": "^1.5.3",
"@playwright/test": "^1.32.3",
"@testing-library/dom": "^9.0.0",
"@testing-library/jest-dom": "^6.0.0",
"@testing-library/react": "^14.0.0",
"@testing-library/user-event": "^14.0.0",
"@testing-library/dom": "^9.0.0",
"@types/react-dom": "*",
"cross-env": "^7.0.0"
},

View File

@@ -11,9 +11,6 @@ describe('App', () => {
data: {
app: { title: 'Test' },
backend: { baseUrl: 'http://localhost:7007' },
techdocs: {
storageUrl: 'http://localhost:7007/api/techdocs/static/docs',
},
},
context: 'test',
},

View File

@@ -1,6 +1,8 @@
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 { HomepageCompositionRoot } from '@backstage/plugin-home';
import { HomePage } from './HomePage';
import {
CatalogEntityPage,
CatalogIndexPage,
@@ -14,13 +16,6 @@ import { ScaffolderPage, scaffolderPlugin } from '@backstage/plugin-scaffolder';
import { orgPlugin } from '@backstage/plugin-org';
import { SearchPage } from '@backstage/plugin-search';
import { TechRadarPage } from '@backstage/plugin-tech-radar';
import {
TechDocsIndexPage,
techdocsPlugin,
TechDocsReaderPage,
} from '@backstage/plugin-techdocs';
import { TechDocsAddons } from '@backstage/plugin-techdocs-react';
import { ReportIssue } from '@backstage/plugin-techdocs-module-addons-contrib';
import { UserSettingsPage } from '@backstage/plugin-user-settings';
import { apis } from './apis';
import { entityPage } from './components/catalog/EntityPage';
@@ -43,7 +38,6 @@ const app = createApp({
bindRoutes({ bind }) {
bind(catalogPlugin.externalRoutes, {
createComponent: scaffolderPlugin.routes.root,
viewTechDoc: techdocsPlugin.routes.docRoot,
createFromTemplate: scaffolderPlugin.routes.selectedTemplate,
});
bind(apiDocsPlugin.externalRoutes, {
@@ -51,7 +45,6 @@ const app = createApp({
});
bind(scaffolderPlugin.externalRoutes, {
registerComponent: catalogImportPlugin.routes.importPage,
viewTechDoc: techdocsPlugin.routes.docRoot,
});
bind(orgPlugin.externalRoutes, {
catalogIndex: catalogPlugin.routes.catalogIndex,
@@ -64,23 +57,16 @@ const app = createApp({
const routes = (
<FlatRoutes>
<Route path="/" element={<Navigate to="catalog" />} />
<Route path="/catalog" element={<CatalogIndexPage />} />
<Route path="/" element={<HomepageCompositionRoot />}>
<HomePage />
</Route>
<Route path="/catalog" element={<CatalogIndexPage />} />
<Route
path="/catalog/:namespace/:kind/:name"
element={<CatalogEntityPage />}
>
{entityPage}
</Route>
<Route path="/docs" element={<TechDocsIndexPage />} />
<Route
path="/docs/:namespace/:kind/:name/*"
element={<TechDocsReaderPage />}
>
<TechDocsAddons>
<ReportIssue />
</TechDocsAddons>
</Route>
<Route path="/create" element={<ScaffolderPage />} />
<Route path="/api-docs" element={<ApiExplorerPage />} />
<Route

View File

@@ -0,0 +1,86 @@
import {
HomePageToolkit,
HomePageCompanyLogo,
HomePageStarredEntities,
TemplateBackstageLogoIcon,
} from '@backstage/plugin-home';
import { Content, Page, InfoCard } from '@backstage/core-components';
import { HomePageSearchBar } from '@backstage/plugin-search';
import { SearchContextProvider } from '@backstage/plugin-search-react';
import { Grid, makeStyles } from '@material-ui/core';
import React from 'react';
import logoImg from './components/Root/Sreez_full.png';
const useStyles = makeStyles(theme => ({
searchBarInput: {
maxWidth: '60vw',
margin: 'auto',
backgroundColor: theme.palette.background.paper,
borderRadius: '50px',
boxShadow: theme.shadows[1],
},
searchBarOutline: {
borderStyle: 'none',
},
}));
const useLogoStyles = makeStyles(theme => ({
container: {
margin: theme.spacing(5, 0),
},
logo: {
width: 'auto',
height: 100,
},
}));
export const HomePage = () => {
const classes = useStyles();
const { container, logo } = useLogoStyles();
return (
<SearchContextProvider>
<Page themeId="home">
<Content>
<Grid container justifyContent="center" spacing={6}>
<HomePageCompanyLogo
className={container}
logo={<img src={logoImg} className={logo} alt="Sreez" />}
/>
<Grid container item xs={12} justifyContent="center">
<HomePageSearchBar
InputProps={{
classes: {
root: classes.searchBarInput,
notchedOutline: classes.searchBarOutline,
},
}}
placeholder="Search"
/>
</Grid>
<Grid container item xs={12}>
<Grid item xs={12} md={6}>
<HomePageStarredEntities />
</Grid>
<Grid item xs={12} md={6}>
<HomePageToolkit
tools={Array(8).fill({
url: '#',
label: 'link',
icon: <TemplateBackstageLogoIcon />,
})}
/>
</Grid>
<Grid item xs={12} md={6}>
<InfoCard title="Composable Section">
{/* placeholder for content */}
<div style={{ height: 370 }} />
</InfoCard>
</Grid>
</Grid>
</Grid>
</Content>
</Page>
</SearchContextProvider>
);
};

File diff suppressed because one or more lines are too long

View File

@@ -1,30 +1,19 @@
import React from 'react';
import { makeStyles } from '@material-ui/core';
import logoIcon from './sreez_logo.png';
const useStyles = makeStyles({
svg: {
img: {
width: 'auto',
height: 28,
},
path: {
fill: '#7df3e1',
},
});
const LogoIcon = () => {
const classes = useStyles();
return (
<svg
className={classes.svg}
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 337.46 428.5"
>
<path
className={classes.path}
d="M303,166.05a80.69,80.69,0,0,0,13.45-10.37c.79-.77,1.55-1.53,2.3-2.3a83.12,83.12,0,0,0,7.93-9.38A63.69,63.69,0,0,0,333,133.23a48.58,48.58,0,0,0,4.35-16.4c1.49-19.39-10-38.67-35.62-54.22L198.56,0,78.3,115.23,0,190.25l108.6,65.91a111.59,111.59,0,0,0,57.76,16.41c24.92,0,48.8-8.8,66.42-25.69,19.16-18.36,25.52-42.12,13.7-61.87a49.22,49.22,0,0,0-6.8-8.87A89.17,89.17,0,0,0,259,178.29h.15a85.08,85.08,0,0,0,31-5.79A80.88,80.88,0,0,0,303,166.05ZM202.45,225.86c-19.32,18.51-50.4,21.23-75.7,5.9L51.61,186.15l67.45-64.64,76.41,46.38C223,184.58,221.49,207.61,202.45,225.86Zm8.93-82.22-70.65-42.89L205.14,39,274.51,81.1c25.94,15.72,29.31,37,10.55,55A60.69,60.69,0,0,1,211.38,143.64Zm29.86,190c-19.57,18.75-46.17,29.09-74.88,29.09a123.73,123.73,0,0,1-64.1-18.2L0,282.52v24.67L108.6,373.1a111.6,111.6,0,0,0,57.76,16.42c24.92,0,48.8-8.81,66.42-25.69,12.88-12.34,20-27.13,19.68-41.49v-1.79A87.27,87.27,0,0,1,241.24,333.68Zm0-39c-19.57,18.75-46.17,29.08-74.88,29.08a123.81,123.81,0,0,1-64.1-18.19L0,243.53v24.68l108.6,65.91a111.6,111.6,0,0,0,57.76,16.42c24.92,0,48.8-8.81,66.42-25.69,12.88-12.34,20-27.13,19.68-41.5v-1.78A87.27,87.27,0,0,1,241.24,294.7Zm0-39c-19.57,18.76-46.17,29.09-74.88,29.09a123.81,123.81,0,0,1-64.1-18.19L0,204.55v24.68l108.6,65.91a111.59,111.59,0,0,0,57.76,16.41c24.92,0,48.8-8.8,66.42-25.68,12.88-12.35,20-27.13,19.68-41.5v-1.82A86.09,86.09,0,0,1,241.24,255.71Zm83.7,25.74a94.15,94.15,0,0,1-60.2,25.86h0V334a81.6,81.6,0,0,0,51.74-22.37c14-13.38,21.14-28.11,21-42.64v-2.19A94.92,94.92,0,0,1,324.94,281.45Zm-83.7,91.21c-19.57,18.76-46.17,29.09-74.88,29.09a123.73,123.73,0,0,1-64.1-18.2L0,321.5v24.68l108.6,65.9a111.6,111.6,0,0,0,57.76,16.42c24.92,0,48.8-8.8,66.42-25.69,12.88-12.34,20-27.13,19.68-41.49v-1.79A86.29,86.29,0,0,1,241.24,372.66ZM327,162.45c-.68.69-1.35,1.38-2.05,2.06a94.37,94.37,0,0,1-10.64,8.65,91.35,91.35,0,0,1-11.6,7,94.53,94.53,0,0,1-26.24,8.71,97.69,97.69,0,0,1-14.16,1.57c.5,1.61.9,3.25,1.25,4.9a53.27,53.27,0,0,1,1.14,12V217h.05a84.41,84.41,0,0,0,25.35-5.55,81,81,0,0,0,26.39-16.82c.8-.77,1.5-1.56,2.26-2.34a82.08,82.08,0,0,0,7.93-9.38A63.76,63.76,0,0,0,333,172.17a48.55,48.55,0,0,0,4.32-16.45c.09-1.23.2-2.47.19-3.7V150q-1.08,1.54-2.25,3.09A96.73,96.73,0,0,1,327,162.45Zm0,77.92c-.69.7-1.31,1.41-2,2.1a94.2,94.2,0,0,1-60.2,25.86h0l0,26.67h0a81.6,81.6,0,0,0,51.74-22.37A73.51,73.51,0,0,0,333,250.13a48.56,48.56,0,0,0,4.32-16.44c.09-1.24.2-2.47.19-3.71v-2.19c-.74,1.07-1.46,2.15-2.27,3.21A95.68,95.68,0,0,1,327,240.37Zm0-39c-.69.7-1.31,1.41-2,2.1a93.18,93.18,0,0,1-10.63,8.65,91.63,91.63,0,0,1-11.63,7,95.47,95.47,0,0,1-37.94,10.18h0V256h0a81.65,81.65,0,0,0,51.74-22.37c.8-.77,1.5-1.56,2.26-2.34a82.08,82.08,0,0,0,7.93-9.38A63.76,63.76,0,0,0,333,211.15a48.56,48.56,0,0,0,4.32-16.44c.09-1.24.2-2.48.19-3.71v-2.2c-.74,1.08-1.46,2.16-2.27,3.22A95.68,95.68,0,0,1,327,201.39Z"
/>
</svg>
<img src={logoIcon} alt='Sreez' className={classes.img}/>
);
};

View File

@@ -7,6 +7,7 @@ import LibraryBooks from '@material-ui/icons/LibraryBooks';
import CreateComponentIcon from '@material-ui/icons/AddCircleOutline';
import LogoFull from './LogoFull';
import LogoIcon from './LogoIcon';
import CategoryIcon from '@material-ui/icons/Category';
import {
Settings as SidebarSettings,
UserSettingsSignInAvatar,
@@ -65,7 +66,9 @@ 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={ExtensionIcon} to="api-docs" text="APIs" />
<SidebarItem icon={CategoryIcon} to="catalog" text="Catalog" />
<SidebarItem icon={ExtensionIcon} to="api-docs" text="APIs" />
<SidebarItem icon={LibraryBooks} to="docs" text="Docs" />
<SidebarItem icon={CreateComponentIcon} to="create" text="Create..." />

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

View File

@@ -1,5 +1,10 @@
import React from 'react';
import { Button, Grid } from '@material-ui/core';
import {
EntityGrafanaAlertsCard,
EntityGrafanaDashboardsCard,
EntityOverviewDashboardViewer
} from '@k-phoen/backstage-plugin-grafana';
import {
EntityApiDefinitionCard,
EntityConsumedApisCard,
@@ -38,7 +43,6 @@ import {
EntityMembersListCard,
EntityOwnershipCard,
} from '@backstage/plugin-org';
import { EntityTechdocsContent } from '@backstage/plugin-techdocs';
import { EmptyState } from '@backstage/core-components';
import {
Direction,
@@ -54,17 +58,28 @@ import {
RELATION_PART_OF,
RELATION_PROVIDES_API,
} from '@backstage/catalog-model';
import { TechDocsAddons } from '@backstage/plugin-techdocs-react';
import { ReportIssue } from '@backstage/plugin-techdocs-module-addons-contrib';
const techdocsContent = (
<EntityTechdocsContent>
<TechDocsAddons>
<ReportIssue />
</TechDocsAddons>
</EntityTechdocsContent>
);
import {
EntityTechInsightsScorecardCard,
EntityTechInsightsScorecardContent,
} from '@backstage/plugin-tech-insights';
import { DockerTagsTableWidget } from '@workm8/backstage-docker-tags';
import {
EntityGithubInsightsContent,
EntityGithubInsightsLanguagesCard,
EntityGithubInsightsReadmeCard,
EntityGithubInsightsReleasesCard,
isGithubInsightsAvailable,
} from '@roadiehq/backstage-plugin-github-insights';
import { EntityGithubDeploymentsCard } from '@backstage/plugin-github-deployments';
import { EntityPrometheusContent } from '@roadiehq/backstage-plugin-prometheus';
import {
EntityPrometheusAlertCard,
EntityPrometheusGraphCard,
} from '@roadiehq/backstage-plugin-prometheus';
import {
EntityArgoCDOverviewCard,
isArgocdAvailable,
} from '@roadiehq/backstage-plugin-argo-cd';
const cicdContent = (
// This is an example of how you can implement your company's logic in entity page.
@@ -121,22 +136,75 @@ const entityWarningContent = (
</>
);
const dockerTagsContent = (
<DockerTagsTableWidget
heading="Docker"
columns={['name', 'username', 'status']}
/>
);
const overviewContent = (
<Grid container spacing={3} alignItems="stretch">
{entityWarningContent}
<Grid item md={6}>
<EntityGrafanaAlertsCard />
</Grid>
<Grid item xs={12} sm={6} md={4}>
<EntityGithubDeploymentsCard />
</Grid>
<EntitySwitch.Case if={e => Boolean(isArgocdAvailable(e))}>
<Grid item sm={4}>
<EntityArgoCDOverviewCard />
</Grid>
</EntitySwitch.Case>
<Grid item md={6}>
<EntityGrafanaDashboardsCard />
</Grid>
<Grid item md={6}>
<EntityOverviewDashboardViewer />
</Grid>
<Grid item md={8}>
<EntityPrometheusAlertCard />
</Grid>
<Grid item md={6}>
<EntityPrometheusGraphCard />
</Grid>
<EntitySwitch>
<EntitySwitch.Case if={e => Boolean(isGithubInsightsAvailable(e))}>
<Grid item md={6}>
<EntityGithubInsightsLanguagesCard />
<EntityGithubInsightsReleasesCard />
</Grid>
<Grid item md={6}>
<EntityGithubInsightsReadmeCard maxHeight={350} />
</Grid>
</EntitySwitch.Case>
</EntitySwitch>
<Grid item md={6}>
<EntityAboutCard variant="gridItem" />
</Grid>
<Grid item md={6} xs={12}>
<EntityCatalogGraphCard variant="gridItem" height={400} />
</Grid>
<Grid item md={4} xs={12}>
{dockerTagsContent}
</Grid>
<Grid item md={4} xs={12}>
<EntityLinksCard />
</Grid>
<Grid item md={8} xs={12}>
<EntityHasSubcomponentsCard variant="gridItem" />
</Grid>
<Grid item md={8} xs={12}>
<EntityTechInsightsScorecardCard
title="Scoreboard"
checksId={['groupOwnerCheck', 'titleCheck']}
/>
</Grid>
</Grid>
);
@@ -145,11 +213,19 @@ const serviceEntityPage = (
<EntityLayout.Route path="/" title="Overview">
{overviewContent}
</EntityLayout.Route>
<EntityLayout.Route path="/prometheus" title="Prometheus">
<EntityPrometheusContent />
</EntityLayout.Route>
<EntityLayout.Route path="/ci-cd" title="CI/CD">
{cicdContent}
</EntityLayout.Route>
<EntityLayout.Route path="/github-actions" title="GitHub Actions">
<EntityGithubActionsContent view="cards" />
</EntityLayout.Route>
<EntityLayout.Route path="/code-insights" title="Code Insights">
<EntityGithubInsightsContent />
</EntityLayout.Route>
<EntityLayout.Route path="/api" title="API">
<Grid container spacing={3} alignItems="stretch">
<Grid item md={6}>
@@ -160,7 +236,12 @@ const serviceEntityPage = (
</Grid>
</Grid>
</EntityLayout.Route>
<EntityLayout.Route path="/tech-insights" title="Scorecards">
<EntityTechInsightsScorecardContent
title="Scoreboard"
checksId={['groupOwnerCheck', 'titleCheck']}
/>
</EntityLayout.Route>
<EntityLayout.Route path="/dependencies" title="Dependencies">
<Grid container spacing={3} alignItems="stretch">
<Grid item md={6}>
@@ -171,10 +252,6 @@ const serviceEntityPage = (
</Grid>
</Grid>
</EntityLayout.Route>
<EntityLayout.Route path="/docs" title="Docs">
{techdocsContent}
</EntityLayout.Route>
</EntityLayout>
);
@@ -198,10 +275,6 @@ const websiteEntityPage = (
</Grid>
</Grid>
</EntityLayout.Route>
<EntityLayout.Route path="/docs" title="Docs">
{techdocsContent}
</EntityLayout.Route>
</EntityLayout>
);
@@ -217,10 +290,6 @@ const defaultEntityPage = (
<EntityLayout.Route path="/" title="Overview">
{overviewContent}
</EntityLayout.Route>
<EntityLayout.Route path="/docs" title="Docs">
{techdocsContent}
</EntityLayout.Route>
</EntityLayout>
);

View File

@@ -2,11 +2,6 @@ import React from 'react';
import { makeStyles, Theme, Grid, Paper } from '@material-ui/core';
import { CatalogSearchResultListItem } from '@backstage/plugin-catalog';
import {
catalogApiRef,
CATALOG_FILTER_EXISTS,
} from '@backstage/plugin-catalog-react';
import { TechDocsSearchResultListItem } from '@backstage/plugin-techdocs';
import { SearchType } from '@backstage/plugin-search';
import {
@@ -14,16 +9,13 @@ import {
SearchFilter,
SearchResult,
SearchPagination,
useSearch,
} from '@backstage/plugin-search-react';
import {
CatalogIcon,
Content,
DocsIcon,
Header,
Page,
} from '@backstage/core-components';
import { useApi } from '@backstage/core-plugin-api';
const useStyles = makeStyles((theme: Theme) => ({
bar: {
@@ -42,8 +34,6 @@ const useStyles = makeStyles((theme: Theme) => ({
const SearchPage = () => {
const classes = useStyles();
const { types } = useSearch();
const catalogApi = useApi(catalogApiRef);
return (
<Page themeId="home">
@@ -65,35 +55,9 @@ const SearchPage = () => {
name: 'Software Catalog',
icon: <CatalogIcon />,
},
{
value: 'techdocs',
name: 'Documentation',
icon: <DocsIcon />,
},
]}
/>
<Paper className={classes.filters}>
{types.includes('techdocs') && (
<SearchFilter.Select
className={classes.filter}
label="Entity"
name="name"
values={async () => {
// Return a list of entities which are documented.
const { items } = await catalogApi.getEntities({
fields: ['metadata.name'],
filter: {
'metadata.annotations.backstage.io/techdocs-ref':
CATALOG_FILTER_EXISTS,
},
});
const names = items.map(entity => entity.metadata.name);
names.sort();
return names;
}}
/>
)}
<SearchFilter.Select
className={classes.filter}
label="Kind"
@@ -112,7 +76,6 @@ const SearchPage = () => {
<SearchPagination />
<SearchResult>
<CatalogSearchResultListItem icon={<CatalogIcon />} />
<TechDocsSearchResultListItem icon={<DocsIcon />} />
</SearchResult>
</Grid>
</Grid>

View File

@@ -0,0 +1 @@
export { argocdPlugin } from '@roadiehq/backstage-plugin-argo-cd';