Skip to content

Commit

Permalink
#104 added modal for connection to GitHub.
Browse files Browse the repository at this point in the history
  • Loading branch information
artzub committed Mar 13, 2023
1 parent 0d86578 commit 4776cc1
Show file tree
Hide file tree
Showing 12 changed files with 219 additions and 70 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "github-visualizer",
"fullname": "GitHub Visualizer",
"name": "visgit",
"fullname": "Git Visualization",
"version": "1.0.0",
"description": "The service for visualizing github users activity and repositories history.",
"main": "build/main.js",
Expand Down
22 changes: 0 additions & 22 deletions src/components/Settings/Auth/index.jsx

This file was deleted.

4 changes: 2 additions & 2 deletions src/components/Settings/Collection/Group.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Item from './Item';

const GroupHeader = (props) => (
<ListSubheader
component="li"
component="div"
disableSticky
{...props}
/>
Expand Down Expand Up @@ -36,7 +36,7 @@ const Group = (props) => {

Group.propTypes = {
items: PropTypes.arrayOf(PropTypes.shape()).isRequired,
title: PropTypes.string.isRequired,
title: PropTypes.node.isRequired,
};

export default Group;
31 changes: 19 additions & 12 deletions src/components/Settings/Collection/Item.jsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
import PropTypes from 'prop-types';

import styled from 'styled-components';
import styled, { css } from 'styled-components';

import ListItemOrigin from '@mui/material/ListItem';
import ListItemText from '@mui/material/ListItemText';

const ListItem = styled(ListItemOrigin)`
cursor: pointer;
transition: background 0.3s;
&:hover {
background: rgba(255, 255, 255, 0.1);
}
&:active {
background: rgba(255, 255, 255, 0.2);
}
${({ $isInteractive }) => ($isInteractive ?? true)
&& css`
cursor: pointer;
&:hover {
background: rgba(255, 255, 255, 0.1);
}
&:active {
background: rgba(255, 255, 255, 0.2);
}
`}
`;

const Item = (props) => {
Expand All @@ -22,13 +26,16 @@ const Item = (props) => {
return (
<ListItem
key={key}
component="div"
{...tail}
>
{body}
<ListItemText
primary={primary}
secondary={secondary}
/>
{primary || secondary ? (
<ListItemText
primary={primary}
secondary={secondary}
/>
) : null}
</ListItem>
);
};
Expand Down
4 changes: 3 additions & 1 deletion src/components/Settings/Collection/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import RouteModal from '@/shared/components/RouteModal';

import Group from './Group';

export const Collection = (props) => {
const Collection = (props) => {
const { items, ...tail } = props;

return <RouteModal {...tail}>{items.map(Group)}</RouteModal>;
Expand All @@ -13,3 +13,5 @@ export const Collection = (props) => {
Collection.propTypes = {
items: PropTypes.arrayOf(PropTypes.shape()).isRequired,
};

export default Collection;
137 changes: 137 additions & 0 deletions src/components/Settings/Connection/GitHub.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import { Fragment, useState } from 'react';
import { useLocalStorage } from 'react-use';

import styled from 'styled-components';

import { Box, Button, TextField, Link } from '@mui/material';
import useEventCallback from '@mui/material/utils/useEventCallback';

import GithubIcon from 'mdi-react/GithubIcon';
import OpenInNewIconOrigin from 'mdi-react/OpenInNewIcon';

import Group from '@/components/Settings/Collection/Group';
import RouteModal from '@/shared/components/RouteModal';
import { appNameVersion } from '@/shared/utils';

const Title = styled.div`
display: flex;
align-items: center;
gap: 8px;
`;

const OpenInNewIcon = styled(OpenInNewIconOrigin)`
margin-top: -4px;
`;

const GenerateButton = styled(Button)`
display: flex;
align-items: center;
gap: 5px;
`;

const Row = styled(Box)`
display: flex;
gap: 10px;
align-items: center;
`;

const Space = styled.div`
flex: 1;
`;

const title = (
<Title>
<GithubIcon />
<span>GitHub Connection</span>
</Title>
);

const queryParams = new URLSearchParams(
`description=${appNameVersion}&scopes=repo,read:user,user:email`,
);
const linkToGithub = `https://github.com/settings/tokens/new?${queryParams}`;

const Form = () => {
const [token, setToken, removeToken] = useLocalStorage('githubToken', '', {
raw: true,
});
const [newToken, setNewToken] = useState(token);

const onChange = useEventCallback((event) => {
setNewToken(event.target.value);
});

const onSave = useEventCallback(() => {
if (newToken) {
setToken(newToken);
}
});

const onClear = useEventCallback(() => {
removeToken();
setNewToken('');
});

return (
<Fragment>
<Row>
<TextField
label="GitHub token"
placeholder="Insert your GitHub token"
onChange={onChange}
value={newToken}
autoComplete="off"
/>
<GenerateButton
component={Link}
href={linkToGithub}
target="_blank"
>
<span>Generate</span>
<OpenInNewIcon size={16} />
</GenerateButton>
</Row>
<Row>
<Button
variant="contained"
disabled={!newToken || newToken === token}
onClick={onSave}
>
Save
</Button>
<Space />
<Button
onClick={onClear}
disabled={!token}
>
Clear
</Button>
</Row>
</Fragment>
);
};

const items = [
{
key: 'token',
body: <Form />,
sx: {
paddingTop: '20px',
flexDirection: 'column',
gap: '10px',
alignItems: 'flex-start',
},
$isInteractive: false,
},
];

const GitHub = (props) => (
<RouteModal {...props}>
<Group
title={title}
items={items}
/>
</RouteModal>
);

export default GitHub;
58 changes: 36 additions & 22 deletions src/components/Settings/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,29 @@ import { Outlet, Route, Routes } from 'react-router-dom';
import ListItemAvatar from '@mui/material/ListItemAvatar';

import GithubIcon from 'mdi-react/GithubIcon';
import GitIcon from 'mdi-react/GitIcon';
import GitlabIcon from 'mdi-react/GitlabIcon';

import NavLink from '@/shared/components/NavLink';

import Auth from './Auth';
import { Collection } from './Collection';
import Collection from './Collection';
import GitHub from './Connection/GitHub';

const sxStyle = {
alignItems: 'center',
display: 'flex',
justifyContent: 'center',
};
const getConnectionItem = ({ key, title, icon }) => ({
key,
title,
alignItems: 'center',
body: <ListItemAvatar sx={sxStyle}>{icon}</ListItemAvatar>,
component: NavLink,
to: `./connection/${key}`,
tabIndex: 0,
primary: title,
});

const items = [
{
Expand All @@ -18,26 +36,21 @@ const items = [
{
title: 'API Connections',
items: [
{
getConnectionItem({
key: 'github',
title: 'GitHub',
alignItems: 'center',
body: (
<ListItemAvatar
sx={{
alignItems: 'center',
display: 'flex',
justifyContent: 'center',
}}
>
<GithubIcon />
</ListItemAvatar>
),
component: NavLink,
to: './auth/github',
tabIndex: 0,
primary: 'GitHub',
},
icon: <GithubIcon />,
}),
getConnectionItem({
key: 'gitlab',
title: 'GitLab',
icon: <GitlabIcon />,
}),
getConnectionItem({
key: 'bitbucket',
title: 'Bitbucket',
icon: <GitIcon />,
}),
],
},
];
Expand All @@ -63,9 +76,10 @@ const Settings = () => {
element={<Body />}
>
<Route
path="auth/*"
element={<Auth path="." />}
path="connection/github"
element={<GitHub path="." />}
/>
<Route path="*" />
</Route>
</Routes>
);
Expand Down
6 changes: 4 additions & 2 deletions src/redux/api/github/getClient.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
import { Octokit } from '@octokit/rest';

import { appNameVersion } from '@/shared/utils';

let instance;
let lastToken;

// TODO Add WebFlow Auth

const getClient = () => {
const token = localStorage.getItem('user_token');
const token = localStorage.getItem('githubToken');

if (!instance || token !== lastToken) {
lastToken = token || process.env.REACT_APP_PERSONAL_TOKEN;
instance = new Octokit({
userAgent: 'visgit/v1.0.0',
userAgent: appNameVersion,
auth: lastToken || process.env.REACT_APP_PERSONAL_TOKEN,
});
}
Expand Down
Loading

0 comments on commit 4776cc1

Please sign in to comment.