Skip to content

Commit

Permalink
feat(bulk-import): allow adding repositories (#1357)
Browse files Browse the repository at this point in the history
  • Loading branch information
debsmita1 authored Apr 11, 2024
1 parent 3497b4c commit 366a06d
Show file tree
Hide file tree
Showing 39 changed files with 2,264 additions and 21 deletions.
52 changes: 50 additions & 2 deletions plugins/bulk-import/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,54 @@

This plugin allows bulk import of multiple catalog entities into the catalog.

## Getting started
---

Coming soon.
**NOTE**

The plugin work is still work in progress

---

## For administrators

### Installation

#### Procedure

1. Install the Bulk import UI plugin using the following command:

```console
yarn workspace app add @janus-idp/backstage-plugin-bulk-import
```

2. Add Route in `packages/app/src/App.tsx`:

```tsx title="packages/app/src/App.tsx"
/* highlight-add-next-line */
import { BulkImportPage } from '@janus-idp/backstage-plugin-bulk-import’;

<Route
path="/bulk-import"
element={<Navigate to="repositories" />}
/>
<Route
path="/bulk-import/repositories"
element={<BulkImportPage />}
/>
```

3. Add **Bulk import** Sidebar Item in `packages/app/src/components/Root/Root.tsx`:

```tsx title="packages/app/src/components/Root/Root.tsx"
/* highlight-add-next-line */
import { BulkImportIcon } from '@janus-idp/backstage-plugin-bulk-import’;

export const Root = ({ children }: PropsWithChildren<{}>) => (
<SidebarPage>
<Sidebar>
...
<BulkImportIcon />
...
</SidebarPage>
);
```
2 changes: 1 addition & 1 deletion plugins/bulk-import/dev/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ createDevApp()
.addPage({
element: <BulkImportPage />,
title: 'Bulk import',
path: '/bulk-import',
path: '/bulk-import/repositories',
})
.render();
4 changes: 4 additions & 0 deletions plugins/bulk-import/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
"private": true,
"publishConfig": {
"access": "public",
"main": "dist/index.esm.js",
Expand Down Expand Up @@ -33,6 +34,9 @@
"@material-ui/icons": "^4.9.1",
"@material-ui/lab": "^4.0.0-alpha.61",
"@mui/icons-material": "5.14.11",
"@mui/material": "^5.12.2",
"lodash": "^4.17.21",
"formik": "^2.4.5",
"react-use": "^17.2.4"
},
"peerDependencies": {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import React from 'react';

import { makeStyles } from '@material-ui/core';
import HelpIcon from '@mui/icons-material/HelpOutline';
import FormControl from '@mui/material/FormControl';
import FormControlLabel from '@mui/material/FormControlLabel';
import Radio from '@mui/material/Radio';
import RadioGroup from '@mui/material/RadioGroup';
import Tooltip from '@mui/material/Tooltip';
import Typography from '@mui/material/Typography';
import { FormikErrors } from 'formik';

import { AddRepositoriesFormValues } from '../../types';
import { AddRepositoriesTable } from './AddRepositoriesTable';

const useStyles = makeStyles(theme => ({
body: {
marginBottom: '50px',
},
approvalTool: {
display: 'flex',
flexDirection: 'row',
justifyContent: 'left',
alignItems: 'center',
paddingTop: '24px',
paddingBottom: '24px',
paddingLeft: '16px',
backgroundColor: theme.palette.background.paper,
borderBottomStyle: 'groove',
border: theme.palette.divider,
},

approvalToolTooltip: {
paddingTop: '4px',
paddingRight: '24px',
paddingLeft: '5px',
},
}));

export const AddRepositoriesForm = ({
values,
setFieldValue,
setapprovalTool,
}: {
values: AddRepositoriesFormValues;
setFieldValue: (
field: string,
value: any,
shouldValidate?: boolean | undefined,
) => Promise<void> | Promise<FormikErrors<AddRepositoriesFormValues>>;
setapprovalTool: any;
}) => {
const styles = useStyles();

return (
<FormControl fullWidth>
<div className={styles.body}>
<span className={styles.approvalTool}>
<Typography fontSize="16px" fontWeight="500">
Approval tool
</Typography>
<Tooltip
placement="top"
title="When adding a new repository, it requires approval. Once the PR is approved or the ServiceNow ticket is closed, the repositories will be added to the Catalog page."
>
<span className={styles.approvalToolTooltip}>
<HelpIcon fontSize="small" />
</span>
</Tooltip>
<RadioGroup
id="approval-tool"
data-testid="approval-tool"
row
aria-labelledby="approval-tool"
name="approvalTool"
value={values.approvalTool}
onChange={(_event, value: string) => {
setapprovalTool(value);
setFieldValue('approvalTool', value);
}}
>
<FormControlLabel value="git" control={<Radio />} label="Git" />
<FormControlLabel
value="servicenow"
control={<Radio />}
label="ServiceNow"
/>
</RadioGroup>
</span>
<AddRepositoriesTable
title="Selected repositories"
selectedRepositoriesFormData={values}
setFieldValue={setFieldValue}
/>
</div>
<br />
</FormControl>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import React, { FormEvent } from 'react';

import { Link } from '@backstage/core-components';

import { makeStyles } from '@material-ui/core';
import Button from '@mui/material/Button';
import Tooltip from '@mui/material/Tooltip';

import { AddRepositoriesFormValues } from '../../types';
import { getRepositoriesSelected } from '../../utils/repository-utils';

const useStyles = makeStyles(theme => ({
createButton: {
marginRight: theme.spacing(1),
},
illustration: {
flexDirection: 'row',
display: 'flex',
justifyContent: 'space-around',
overflow: 'scroll',
},
tooltip: {
whiteSpace: 'nowrap',
},
footer: {
display: 'flex',
flexDirection: 'row',
justifyContent: 'left',
position: 'fixed',
bottom: 0,
paddingTop: '24px',
paddingBottom: '24px',
paddingLeft: '24px',
backgroundColor: theme.palette.background.paper,
width: '100%',
borderTopStyle: 'groove',
border: theme.palette.divider,
},
}));

export const AddRepositoriesFormFooter = ({
approvalTool,
values,
handleSubmit,
}: {
approvalTool: string;
values: AddRepositoriesFormValues;
handleSubmit: (e?: FormEvent<HTMLFormElement> | undefined) => void;
}) => {
const styles = useStyles();
const submitTitle =
(approvalTool === 'git'
? 'Create pull request'
: 'Create ServiceNow ticket') +
(getRepositoriesSelected(values) > 1 ? 's' : '');

return (
<div className={styles.footer}>
<Tooltip
classes={{ tooltip: styles.tooltip }}
title="Please wait until the catalog-info.yaml files are generated"
>
<span>
<Button
variant="contained"
onClick={handleSubmit as any}
className={styles.createButton}
disabled={getRepositoriesSelected(values) === 0}
>
{submitTitle}
</Button>
</span>
</Tooltip>
<Link to="/bulk-import/repositories">
<Button variant="outlined">Cancel</Button>
</Link>
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import React from 'react';

import { Content, Header, Page } from '@backstage/core-components';

import { makeStyles, useTheme } from '@material-ui/core';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import Accordion from '@mui/material/Accordion';
import AccordionDetails from '@mui/material/AccordionDetails';
import AccordionSummary from '@mui/material/AccordionSummary';
import Typography from '@mui/material/Typography';
import { useFormik } from 'formik';

import { AddRepositoriesFormValues } from '../../types';
import { AddRepositoriesForm } from './AddRepositoriesForm';
import { AddRepositoriesFormFooter } from './AddRepositoriesFormFooter';
import { Illustrations } from './Illustrations';

const useStyles = makeStyles(() => ({
illustration: {
flexDirection: 'row',
display: 'flex',
justifyContent: 'space-around',
overflow: 'scroll',
},
}));

export const AddRepositoriesPage = () => {
const styles = useStyles();
const theme = useTheme();
const [approvalTool, setApprovalTool] = React.useState<'git' | 'servicenow'>(
'git',
);
const initialValues: AddRepositoriesFormValues = {
repositoryType: 'repository',
repositories: [],
organizations: [],
approvalTool: 'git',
};

const formik = useFormik<AddRepositoriesFormValues>({
enableReinitialize: true,
initialValues,
onSubmit: async (_values: AddRepositoriesFormValues) => {},
});

return (
<Page themeId="tool">
<Header title="Add repositories" type="Bulk import" typeLink=".." />
<Content>
<Accordion defaultExpanded>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
id="add-repository-summary"
>
<Typography variant="h5">
Add repositories to Red Hat Developer Hub in 5 steps
</Typography>
</AccordionSummary>
<AccordionDetails
id="add-repository-illustrations"
className={styles.illustration}
>
<Illustrations
iconClassname={
theme.palette.type === 'dark'
? 'icon-approval-tool-white'
: 'icon-approval-tool-black'
}
iconText="Choose approval tool (git/ServiceNow) for PR/ticket creation"
/>
<Illustrations
iconClassname={
theme.palette.type === 'dark'
? 'icon-choose-repositories-white'
: 'icon-choose-repositories-black'
}
iconText="Choose repositories you want to add"
/>
<Illustrations
iconClassname={
theme.palette.type === 'dark'
? 'icon-generate-cataloginfo-white'
: 'icon-generate-cataloginfo-black'
}
iconText="Generate a catalog-info.yaml file for each repository"
/>
<Illustrations
iconClassname={
theme.palette.type === 'dark'
? 'icon-edit-pullrequest-white'
: 'icon-edit-pullrequest-black'
}
iconText="Edit the pull request details if needed"
/>
<Illustrations
iconClassname={
theme.palette.type === 'dark'
? 'icon-track-status-white'
: 'icon-track-status-black'
}
iconText="Track the approval status"
/>
</AccordionDetails>
</Accordion>
<br />
<AddRepositoriesForm
values={formik.values}
setFieldValue={formik.setFieldValue}
setapprovalTool={setApprovalTool}
/>
</Content>
<AddRepositoriesFormFooter
approvalTool={approvalTool}
handleSubmit={formik.handleSubmit}
values={formik.values}
/>
</Page>
);
};
Loading

0 comments on commit 366a06d

Please sign in to comment.