Skip to content

Commit

Permalink
feat(bulk-import): allow user to select repositories from side panel (j…
Browse files Browse the repository at this point in the history
…anus-idp#1430)

Signed-off-by: Yi Cai <[email protected]>
  • Loading branch information
ciiay authored Apr 18, 2024
1 parent 29ae1c3 commit ffcd101
Show file tree
Hide file tree
Showing 11 changed files with 1,116 additions and 195 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
import React, { useState } from 'react';

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

import {
Button,
Card,
Container,
Drawer,
IconButton,
makeStyles,
Typography,
} from '@material-ui/core';
import CloseIcon from '@material-ui/icons/Close';
import OpenInNewIcon from '@mui/icons-material/OpenInNew';

import { AddRepositoriesData, AddRepositoriesFormValues } from '../../types';
import { urlHelper } from '../../utils/repository-utils';
import { AddRepositoriesTableToolbar } from './AddRepositoriesTableToolbar';
import { RepositoriesTable } from './RepositoriesTable';

type AddRepositoriesDrawerProps = {
open: boolean;
onClose: () => void;
onSelect: (ids: number[], drawerOrgId: number) => void;
title: string;
data: AddRepositoriesData;
selectedRepositoriesFormData: AddRepositoriesFormValues;
checkedRepos: number[];
};

const useStyles = makeStyles(theme => ({
createButton: {
marginRight: theme.spacing(1),
},
sidePanelfooter: {
display: 'flex',
flexDirection: 'row',
justifyContent: 'right',
marginTop: theme.spacing(2),
position: 'fixed',
bottom: '20px',
},
drawerPaper: {
['@media (max-width: 960px)']: {
'& > div[class*="MuiDrawer-paper-"]': {
width: '-webkit-fill-available',
},
},
},
drawerContainer: {
padding: '20px',
height: '100%',
display: 'flex',
flexDirection: 'column',
},
}));

export const AddRepositoriesDrawer = ({
open,
onClose,
onSelect,
title,
data,
selectedRepositoriesFormData,
checkedRepos,
}: AddRepositoriesDrawerProps) => {
const classes = useStyles();
const [searchString, setSearchString] = useState<string>('');

const [selectedReposID, setSelectedReposID] =
useState<number[]>(checkedRepos);

const updateSelectedReposInDrawer = (ids: number[]) => {
setSelectedReposID(ids);
};

const handleSelectRepoFromDrawer = (selected: number[]) => {
onSelect(selected, data?.id);
onClose();
};

return (
<Drawer
anchor="right"
open={open}
variant="temporary"
className={classes.drawerPaper}
>
<Container className={classes.drawerContainer}>
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
<div>
<Typography variant="h5">{data?.name}</Typography>
<Link to={data?.url}>
{urlHelper(data?.url)}
<OpenInNewIcon
style={{ verticalAlign: 'sub', paddingTop: '7px' }}
/>
</Link>
</div>
<div>
<IconButton onClick={onClose} className="align-right">
<CloseIcon />
</IconButton>
</div>
</div>
<Card style={{ marginTop: '20px', marginBottom: '60px' }}>
<AddRepositoriesTableToolbar
title={title}
setSearchString={setSearchString}
selectedReposFromDrawer={selectedReposID}
selectedRepositoriesFormData={selectedRepositoriesFormData}
activeOrganization={data}
/>
<RepositoriesTable
searchString={searchString}
selectedOrgRepos={selectedReposID}
updateSelectedReposInDrawer={updateSelectedReposInDrawer}
drawerOrganization={data}
/>
</Card>
<div className={classes.sidePanelfooter}>
<span>
<Button
variant="contained"
color="primary"
onClick={() => handleSelectRepoFromDrawer(selectedReposID)}
className={classes.createButton}
aria-labelledby="select-from-drawer"
>
Select
</Button>
</span>
<span>
<Button
aria-labelledby="cancel-drawer-select"
variant="outlined"
onClick={onClose}
>
Cancel
</Button>
</span>
</div>
</Container>
</Drawer>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ import Toolbar from '@mui/material/Toolbar';
import Typography from '@mui/material/Typography';
import { FormikErrors } from 'formik';

import { AddRepositoriesFormValues } from '../../types';
import { getRepositoriesSelected } from '../../utils/repository-utils';
import { AddRepositoriesData, AddRepositoriesFormValues } from '../../types';
import { RepositoriesSearchBar } from './AddRepositoriesSearchBar';

export const AddRepositoriesTableToolbar = ({
Expand All @@ -16,24 +15,29 @@ export const AddRepositoriesTableToolbar = ({
selectedRepositoriesFormData,
setFieldValue,
onPageChange,
activeOrganization,
selectedReposFromDrawer,
}: {
title: string;
setSearchString: (str: string) => void;
selectedRepositoriesFormData: AddRepositoriesFormValues;
setFieldValue: (
setFieldValue?: (
field: string,
value: any,
shouldValidate?: boolean,
) => Promise<FormikErrors<AddRepositoriesFormValues>> | Promise<void>;
onPageChange: (page: number) => void;
onPageChange?: (page: number) => void;
activeOrganization?: AddRepositoriesData;
selectedReposFromDrawer?: number[];
}) => {
const [selection, setSelection] = React.useState('repository');
const [search, setSearch] = React.useState<string>('');
const [selectedReposNumber, setSelectedReposNumber] = React.useState(0);
const handleToggle = (
_event: React.MouseEvent<HTMLElement>,
type: string,
) => {
if (type) {
if (type && setFieldValue && onPageChange) {
setSelection(type);
setFieldValue('repositoryType', type);
onPageChange(0);
Expand All @@ -45,6 +49,23 @@ export const AddRepositoriesTableToolbar = ({
setSearch(filter);
};

React.useEffect(() => {
if (activeOrganization && selectedReposFromDrawer) {
const thisSelectedReposCount = activeOrganization.repositories?.filter(
repo => selectedReposFromDrawer.includes(repo.id) && repo.id > -1,
).length;
setSelectedReposNumber(thisSelectedReposCount || 0);
} else {
setSelectedReposNumber(
selectedRepositoriesFormData.repositories?.length || 0,
);
}
}, [
selectedReposFromDrawer,
selectedRepositoriesFormData,
activeOrganization,
]);

return (
<Toolbar
sx={{
Expand All @@ -54,19 +75,21 @@ export const AddRepositoriesTableToolbar = ({
}}
>
<Typography sx={{ flex: '1 1 100%' }} variant="h5" id={title}>
{`${title} (${getRepositoriesSelected(selectedRepositoriesFormData)})`}
{`${title} (${selectedReposNumber})`}
</Typography>
<ToggleButtonGroup
size="medium"
color="primary"
value={selection}
exclusive
onChange={handleToggle}
aria-label="repository-type"
>
<ToggleButton value="repository">Repositories</ToggleButton>
<ToggleButton value="organization">Organization</ToggleButton>
</ToggleButtonGroup>
{!activeOrganization && (
<ToggleButtonGroup
size="medium"
color="primary"
value={selection}
exclusive
onChange={handleToggle}
aria-label="repository-type"
>
<ToggleButton value="repository">Repositories</ToggleButton>
<ToggleButton value="organization">Organization</ToggleButton>
</ToggleButtonGroup>
)}
<RepositoriesSearchBar value={search} onChange={handleSearch} />
</Toolbar>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,32 +10,45 @@ import { AddRepositoriesData } from '../../types';
import {
getRepositoryStatusForOrg,
getSelectedRepositories,
urlHelper,
} from '../../utils/repository-utils';

const tableCellStyle = {
lineHeight: '1.5rem',
fontSize: '0.875rem',
padding: '15px 16px 15px 24px',
};

export const OrganizationTableRow = ({
onOrgRowSelected,
data,
alreadyAdded,
}: {
onOrgRowSelected: (org: AddRepositoriesData) => void;
data: AddRepositoriesData;
alreadyAdded: number;
}) => {
return (
<TableRow hover>
<TableCell component="th" scope="row" padding="none">
<TableCell component="th" scope="row" padding="none" sx={tableCellStyle}>
{data.name}
</TableCell>
<TableCell align="left">
<TableCell align="left" sx={tableCellStyle}>
<Link to={data.url}>
<>
{data.url}
{urlHelper(data.url)}
<OpenInNewIcon
style={{ verticalAlign: 'bottom', paddingTop: '7px' }}
style={{ verticalAlign: 'sub', paddingTop: '7px' }}
/>
</>
</Link>
</TableCell>
<TableCell align="left">
<>{getSelectedRepositories(data.selectedRepositories)}</>
<TableCell align="left" sx={tableCellStyle}>
{getSelectedRepositories(onOrgRowSelected, data, alreadyAdded)}
</TableCell>
<TableCell align="left" sx={tableCellStyle}>
{getRepositoryStatusForOrg(data, alreadyAdded)}
</TableCell>
<TableCell align="left">{getRepositoryStatusForOrg(data)}</TableCell>
</TableRow>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { TableColumn } from '@backstage/core-components';

export const ReposSelectDrawerColumnHeader: TableColumn[] = [
{
id: 'name',
title: 'Name',
field: 'name',
},
{
id: 'url',
title: 'URL',
field: 'url',
},
{
id: 'catalogInfoYaml',
title: '',
field: 'catalogInfoYaml',
},
];
Loading

0 comments on commit ffcd101

Please sign in to comment.