1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
5 import * as React from 'react';
6 import { connect } from 'react-redux';
7 import { Grid, Typography, Button, Card, CardContent, TableBody, TableCell, TableHead, TableRow, Table, Tooltip, IconButton } from '@material-ui/core';
8 import { StyleRulesCallback, WithStyles, withStyles } from '@material-ui/core/styles';
9 import { ArvadosTheme } from '~/common/custom-theme';
10 import { Link } from 'react-router-dom';
11 import { Dispatch, compose } from 'redux';
12 import { RootState } from '~/store/store';
13 import { HelpIcon, AddIcon, MoreOptionsIcon } from '~/components/icon/icon';
14 import { loadRepositoriesData, openRepositoriesSampleGitDialog, openRepositoryCreateDialog } from '~/store/repositories/repositories-actions';
15 import { RepositoryResource } from '~/models/repositories';
16 import { openRepositoryContextMenu } from '~/store/context-menu/context-menu-actions';
17 import { Routes } from '~/routes/routes';
20 type CssRules = 'link' | 'button' | 'icon' | 'iconRow' | 'moreOptionsButton' | 'moreOptions' | 'cloneUrls';
22 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
24 textDecoration: 'none',
25 color: theme.palette.primary.main,
27 color: theme.palette.primary.dark,
28 transition: 'all 0.5s ease'
37 color: theme.palette.grey["500"],
39 color: theme.palette.common.black,
40 transition: 'all 0.5s ease'
44 paddingTop: theme.spacing.unit * 2,
57 whiteSpace: 'pre-wrap'
61 const mapStateToProps = (state: RootState) => {
63 repositories: state.repositories.items
67 const mapDispatchToProps = (dispatch: Dispatch): Pick<RepositoriesActionProps, 'onOptionsMenuOpen' | 'loadRepositories' | 'openRepositoriesSampleGitDialog' | 'openRepositoryCreateDialog'> => ({
68 loadRepositories: () => dispatch<any>(loadRepositoriesData()),
69 onOptionsMenuOpen: (event, repository) => {
70 dispatch<any>(openRepositoryContextMenu(event, repository));
72 openRepositoriesSampleGitDialog: () => dispatch<any>(openRepositoriesSampleGitDialog()),
73 openRepositoryCreateDialog: () => dispatch<any>(openRepositoryCreateDialog())
76 interface RepositoriesActionProps {
77 loadRepositories: () => void;
78 onOptionsMenuOpen: (event: React.MouseEvent<HTMLElement>, repository: RepositoryResource) => void;
79 openRepositoriesSampleGitDialog: () => void;
80 openRepositoryCreateDialog: () => void;
83 interface RepositoriesDataProps {
84 repositories: RepositoryResource[];
88 type RepositoriesProps = RepositoriesDataProps & RepositoriesActionProps & WithStyles<CssRules>;
90 export const RepositoriesPanel = compose(
92 connect(mapStateToProps, mapDispatchToProps))(
93 class extends React.Component<RepositoriesProps> {
95 this.props.loadRepositories();
98 const { classes, repositories, onOptionsMenuOpen, openRepositoriesSampleGitDialog, openRepositoryCreateDialog } = this.props;
102 <Grid container direction="row">
104 <Typography variant="body2">
105 When you are using an Arvados virtual machine, you should clone the https:// URLs. This will authenticate automatically using your API token. <br />
106 In order to clone git repositories using SSH, <Link to={Routes.SSH_KEYS_USER} className={classes.link}>add an SSH key to your account</Link> and clone the git@ URLs.
109 <Grid item xs={4} className={classes.button}>
110 <Button variant="contained" color="primary" onClick={openRepositoryCreateDialog}>
111 <AddIcon /> NEW REPOSITORY
116 <div className={classes.iconRow}>
117 <Tooltip title="Sample git quick start">
118 <IconButton className={classes.moreOptionsButton} onClick={openRepositoriesSampleGitDialog}>
119 <HelpIcon className={classes.icon} />
125 {repositories && <Table>
128 <TableCell>Name</TableCell>
129 <TableCell>URL</TableCell>
134 {repositories.map((repository, index) =>
135 <TableRow key={index}>
136 <TableCell>{repository.name}</TableCell>
137 <TableCell className={classes.cloneUrls}>{repository.cloneUrls.join("\n")}</TableCell>
138 <TableCell className={classes.moreOptions}>
139 <Tooltip title="More options" disableFocusListener>
140 <IconButton onClick={event => onOptionsMenuOpen(event, repository)} className={classes.moreOptionsButton}>