src/renderer/elements/GithubAccessTokenForm.tsx
import { track } from '@/renderer/infrastructure/analytics/AnalyticsTracking';
import * as dayjs from 'dayjs';
import { Formik, FormikActions } from 'formik';
import * as React from 'react';
import { connect } from 'react-redux';
import { withRouter } from 'react-router-dom';
import styled from 'styled-components';
import { Anchor } from '@/renderer/elements/Base';
import { FormContainer, HollowButtonPrimary, Input, Label } from '@/renderer/elements/Form';
import { themeConfig } from '@/renderer/infrastructure/styles/Theme';
interface Props {
accessToken: string;
handleSubmit(accessToken: string): void;
handleClear(): void;
}
interface FormValues {
accessToken: string;
}
export class GithubAccessTokenForm extends React.Component<Props> {
private readonly findWhiteSpace = /\s/g;
constructor(props: Props) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
this.handleClear = this.handleClear.bind(this);
}
handleClear() {
if (window.confirm('This will clear your token, you sure you want to do that?')) {
this.props.handleClear();
}
}
handleSubmit(values: FormValues, {setSubmitting}: FormikActions<FormValues>) {
const accessToken = values.accessToken.replace(this.findWhiteSpace, '');
this.props.handleSubmit(accessToken);
track.addGithubToken();
setTimeout(() => setSubmitting(false), 500);
}
private get githubLink() {
const dateString = dayjs().format('YYYY-MM-DD');
const description = encodeURIComponent(`Traverse ${dateString}`);
const scopes = [
'public_repo',
'read:user',
'user:email',
'user:follow',
];
return `https://github.com/settings/tokens/new?description=${description}&scopes=${scopes.join(',')}`;
}
render() {
const accessToken = this.props.accessToken ? this.props.accessToken : '';
const formValues: FormValues = {accessToken};
return <FormContainer>
<Formik
enableReinitialize
initialValues={formValues}
validate={(values: FormValues) => {
const errors: any = {};
if (!values.accessToken) {
errors.accessToken = 'Required';
} else if (this.findWhiteSpace.test(values.accessToken)) {
errors.accessToken = 'No Spaces';
}
return errors;
}}
onSubmit={this.handleSubmit}
>
{({
values,
errors,
touched,
handleChange,
handleBlur,
handleSubmit,
isSubmitting,
}) => (
<form onSubmit={handleSubmit}>
<Label htmlFor='accessToken' className='access-token-label'>
<h4>
Github Access Token
{accessToken ? (
<Clear onClick={this.handleClear}>×</Clear>
) : (
<SmallAnchor className='open-link-externally'
href={this.githubLink}
>Create a token</SmallAnchor>
)}
</h4>
<p>Easily see your starred repositories and enable 3x more API calls per minute.</p>
</Label>
<Input
type='text'
name='accessToken'
placeholder='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
disabled={!!accessToken}
onChange={handleChange}
onBlur={handleBlur}
value={values.accessToken}
/>
<Error>
{!accessToken && errors.accessToken && touched.accessToken && errors.accessToken}
</Error>
{accessToken ? null : (
<>
<HollowButtonPrimary type='submit' disabled={isSubmitting}>
Submit
</HollowButtonPrimary>
</>
)}
</form>
)}
</Formik>
</FormContainer>;
}
}
const SmallAnchor = styled(Anchor)`
font-size: 0.75rem;
margin-left: 0.5rem;
`;
const Error = styled.span`
float: right;
color: ${themeConfig.colors.red};
`;
const Clear = styled.span`
float: right;
border-color: ${themeConfig.colors.purple};
color: ${themeConfig.colors.purple};
&:hover {
border-color: ${themeConfig.colors.purpleDark};
color: ${themeConfig.colors.purpleDark};
}
`;