mirror of
https://github.com/nickzuber/meteorite.git
synced 2024-08-16 23:10:38 +03:00
More polish
This commit is contained in:
parent
76e518e4bc
commit
12b566ee51
13
src/components/ErrorMessage.js
Normal file
13
src/components/ErrorMessage.js
Normal file
@ -0,0 +1,13 @@
|
||||
import React from 'react';
|
||||
import styled from 'react-emotion';
|
||||
|
||||
const Message = styled('p')({
|
||||
color: '#eb3349',
|
||||
fontWeight: 500
|
||||
});
|
||||
|
||||
export default function ErrorMessage ({children, props}) {
|
||||
return (
|
||||
<Message {...props}>{children}</Message>
|
||||
);
|
||||
}
|
@ -3,7 +3,7 @@
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<g transform="translate(1 1)" stroke-width="2.6">
|
||||
<circle stroke-opacity=".5" cx="9" cy="9" r="9"/>
|
||||
<path stroke="#7247ff" d="M18,9 C18,4.03 13.97,0 9,0">
|
||||
<path stroke="#9065ff" d="M18,9 C18,4.03 13.97,0 9,0">
|
||||
<animateTransform
|
||||
attributeName="transform"
|
||||
type="rotate"
|
||||
|
Before Width: | Height: | Size: 714 B After Width: | Height: | Size: 714 B |
@ -4,8 +4,11 @@ const CLIENT_ID = '9478c90e57ef3d546ef0';
|
||||
const REDIRECT_URI = 'http://localhost:3000/login';
|
||||
const SCOPES = 'notifications';
|
||||
|
||||
const AuthenticationButton = () => (
|
||||
<a href={`https://github.com/login/oauth/authorize?client_id=${CLIENT_ID}&scope=${SCOPES}&redirect_uri=${REDIRECT_URI}`}>
|
||||
const AuthenticationButton = props => (
|
||||
<a
|
||||
href={`https://github.com/login/oauth/authorize?client_id=${CLIENT_ID}&scope=${SCOPES}&redirect_uri=${REDIRECT_URI}`}
|
||||
{...props}
|
||||
>
|
||||
Login with GitHub
|
||||
</a>
|
||||
);
|
||||
|
@ -8,13 +8,17 @@ import '../../styles/gradient.css';
|
||||
const Header = styled('h1')({
|
||||
color: '#fff',
|
||||
padding: '0 20px',
|
||||
margin: '0 auto 16px'
|
||||
margin: '0 auto 20px',
|
||||
letterSpacing: '-1.5px'
|
||||
});
|
||||
|
||||
const SubHeader = styled(Header)({
|
||||
fontWeight: 500,
|
||||
maxWidth: 550,
|
||||
color: '#fff',
|
||||
fontSize: 24
|
||||
fontSize: 24,
|
||||
marginBottom: 30,
|
||||
letterSpacing: '-1.0px'
|
||||
});
|
||||
|
||||
const LandingHeader = styled('div')({
|
||||
@ -34,8 +38,20 @@ const LandingMessage = styled(LandingHeader)({
|
||||
}
|
||||
});
|
||||
|
||||
const LinksContainer = styled('div')({
|
||||
const SmallLink = styled('a')({
|
||||
fontSize: '12px',
|
||||
fontWeight: 'bold',
|
||||
color: '#ffffff',
|
||||
textDecoration: 'none',
|
||||
':hover': {
|
||||
textDecoration: 'underline'
|
||||
}
|
||||
});
|
||||
|
||||
const BottomLinkContainer = styled(LandingHeader)({
|
||||
maxWidth: '390px',
|
||||
width: '100%',
|
||||
margin: '32px auto 0',
|
||||
});
|
||||
|
||||
const Logo = styled('div')({
|
||||
@ -55,22 +71,33 @@ export default function Scene ({loggedIn, onLogout, ...props}) {
|
||||
position: 'relative',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center'
|
||||
alignItems: 'center',
|
||||
overflowX: 'hidden',
|
||||
// background: 'radial-gradient(farthest-corner at -0% 100%, #9065ff 30%, #00ffbe 95%)'
|
||||
}}>
|
||||
<LandingHeader>
|
||||
<Logo />
|
||||
{loggedIn ? (
|
||||
<LinksContainer>
|
||||
<RouterLink to={routes.INBOX}>inbox</RouterLink>
|
||||
<LinkButton href="javascript:void(0);" onClick={onLogout}>logout</LinkButton>
|
||||
</LinksContainer>
|
||||
<div className="button-container">
|
||||
<RouterLink style={{marginRight: 15}} to={routes.INBOX}>notifications</RouterLink>
|
||||
<LinkButton style={{marginRight: 15}} href="#" onClick={onLogout}>logout</LinkButton>
|
||||
</div>
|
||||
) : (
|
||||
<RouterLink to={routes.LOGIN}>login</RouterLink>
|
||||
<div className="button-container">
|
||||
<RouterLink style={{marginRight: 15}} to={routes.LOGIN}>login</RouterLink>
|
||||
</div>
|
||||
)}
|
||||
</LandingHeader>
|
||||
<LandingMessage>
|
||||
<Header>Conquer your notifications</Header>
|
||||
<SubHeader>Take back control over your GitHub notifications</SubHeader>
|
||||
<Header>Manage your notifications</Header>
|
||||
<SubHeader>Stop manually sorting through GitHub notifications and start being productive.</SubHeader>
|
||||
<div className="button-container">
|
||||
<RouterLink to={routes.LOGIN}>let's get started</RouterLink>
|
||||
</div>
|
||||
<BottomLinkContainer>
|
||||
<SmallLink href="">View and contribute on GitHub</SmallLink>
|
||||
<SmallLink href="">View and contribute on GitHub</SmallLink>
|
||||
</BottomLinkContainer>
|
||||
</LandingMessage>
|
||||
<Curve />
|
||||
</div>
|
||||
|
@ -4,6 +4,7 @@ import styled from 'react-emotion';
|
||||
import { routes } from '../../constants';
|
||||
import { AuthenticationButton } from '../../components/buttons';
|
||||
import LoadingIcon from '../../components/LoadingIcon';
|
||||
import ErrorMessage from '../../components/ErrorMessage';
|
||||
import '../../styles/gradient.css';
|
||||
|
||||
const Container = styled('div')({
|
||||
@ -11,9 +12,8 @@ const Container = styled('div')({
|
||||
background: '#fff',
|
||||
borderRadius: 4,
|
||||
margin: '0 auto',
|
||||
padding: '24px 48px',
|
||||
width: 300,
|
||||
height: 300
|
||||
padding: '24px 48px 76px',
|
||||
width: 300
|
||||
});
|
||||
|
||||
const ButtonsContainer = styled('div')({
|
||||
@ -32,11 +32,8 @@ export default function Scene ({ loading, error, loggedOut, ...props }) {
|
||||
return (
|
||||
<div className="container-gradient" style={{
|
||||
width: '100%',
|
||||
height: 600,
|
||||
position: 'relative',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
height: '100vh',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
@ -44,12 +41,17 @@ export default function Scene ({ loading, error, loggedOut, ...props }) {
|
||||
}}>
|
||||
<Container>
|
||||
<h3>Authenticate with GitHub</h3>
|
||||
{error ? (
|
||||
{!error ? (
|
||||
<React.Fragment>
|
||||
<p>Log in with GitHub and we'll start organizing and sorting all of your notifications.</p>
|
||||
<ErrorMessage>Oops, looks like something went wrong. Try again?</ErrorMessage>
|
||||
<ButtonsContainer>
|
||||
<Link to={routes.HOME}>go back</Link>
|
||||
<AuthenticationButton />
|
||||
<div className="button-container">
|
||||
<Link style={{boxShadow: '0 0 0'}} to={routes.HOME}>go back</Link>
|
||||
</div>
|
||||
<div className="button-container">
|
||||
<AuthenticationButton style={{boxShadow: '0 0 0'}} />
|
||||
</div>
|
||||
</ButtonsContainer>
|
||||
</React.Fragment>
|
||||
) : loading ? (
|
||||
@ -58,8 +60,12 @@ export default function Scene ({ loading, error, loggedOut, ...props }) {
|
||||
<React.Fragment>
|
||||
<p>Log in with GitHub and we'll start organizing and sorting all of your notifications.</p>
|
||||
<ButtonsContainer>
|
||||
<Link to={routes.HOME}>go back</Link>
|
||||
<AuthenticationButton />
|
||||
<div className="button-container">
|
||||
<Link style={{boxShadow: '0 0 0'}} to={routes.HOME}>go back</Link>
|
||||
</div>
|
||||
<div className="button-container">
|
||||
<AuthenticationButton style={{boxShadow: '0 0 0'}} />
|
||||
</div>
|
||||
</ButtonsContainer>
|
||||
</React.Fragment>
|
||||
) : (
|
||||
|
@ -9,30 +9,59 @@ class NotificationsProvider extends React.Component {
|
||||
error: null
|
||||
}
|
||||
|
||||
getNotifications = () => {
|
||||
if (!this.props.token) {
|
||||
console.error('unauthenitcated!')
|
||||
return false;
|
||||
}
|
||||
|
||||
console.warn(this.props.token)
|
||||
|
||||
this.setState({ loading: true });
|
||||
fetch(`${BASE_GITHUB_API_URL}/notifications`, {
|
||||
requestPage = (page = 1) => {
|
||||
return fetch(`${BASE_GITHUB_API_URL}/notifications?page=${page}`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Authorization': `token ${this.props.token}`,
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json'
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}).then(response => response.json())
|
||||
.then(data => {
|
||||
console.warn(data);
|
||||
})
|
||||
})
|
||||
.then(response => {
|
||||
const entries = response.headers.entries();
|
||||
const headers = {};
|
||||
for (let [name, value] of entries) {
|
||||
headers[name] = value;
|
||||
}
|
||||
|
||||
const rawLinks = headers['link'];
|
||||
const links = {};
|
||||
|
||||
if (rawLinks) {
|
||||
rawLinks.split(',').forEach((p) => {
|
||||
const section = p.split(';');
|
||||
if (section.length !== 2) {
|
||||
throw new Error("section could not be split on ';'");
|
||||
}
|
||||
const url = section[0].replace(/<(.*)>/, '$1').trim();
|
||||
const page = section[0].match(/page=(\d)/)[1];
|
||||
const name = section[1].replace(/rel="(.*)"/, '$1').trim();
|
||||
links[name] = {url, page};
|
||||
})
|
||||
}
|
||||
// links.next.page
|
||||
|
||||
return response.json();
|
||||
});
|
||||
}
|
||||
|
||||
getNotifications = () => {
|
||||
if (!this.props.token) {
|
||||
console.error('Unauthenitcated, aborting request.')
|
||||
return false;
|
||||
}
|
||||
|
||||
this.setState({ loading: true });
|
||||
return this.requestPage(1)
|
||||
.then(notifications => this.processNotificationsChunk(notifications))
|
||||
.catch(error => this.setState({ error }))
|
||||
.finally(() => this.setState({ loading: false }));
|
||||
}
|
||||
|
||||
processNotificationsChunk = notifications => {
|
||||
console.log(notifications);
|
||||
}
|
||||
|
||||
render () {
|
||||
return this.props.children({
|
||||
...this.state,
|
||||
|
@ -1,16 +1,20 @@
|
||||
|
||||
.container-gradient {
|
||||
background: radial-gradient(farthest-corner at -0% 100%, #7247ff 30%, #00ffbe 95%);
|
||||
/* background: radial-gradient(farthest-corner at -0% 100%, #7247ff 30%, #00ffbe 95%); */
|
||||
background: radial-gradient(farthest-corner at -0% 100%, #9065ff 30%, #58fff7 95%);
|
||||
background-size: 400% 400%;
|
||||
|
||||
-webkit-animation: gradientTransition 30s ease infinite;
|
||||
-moz-animation: gradientTransition 30s ease infinite;
|
||||
animation: gradientTransition 30s ease infinite;
|
||||
-webkit-animation: gradientTransition 20s ease infinite;
|
||||
-moz-animation: gradientTransition 20s ease infinite;
|
||||
animation: gradientTransition 20s ease infinite;
|
||||
}
|
||||
|
||||
.container-gradient a {
|
||||
.button-container a {
|
||||
text-align: center;
|
||||
box-shadow: 0 1px 3px #4a4a4a5c;
|
||||
margin: 0 auto;
|
||||
cursor: pointer;
|
||||
color: #7247ff;
|
||||
color: #9065ff;
|
||||
background: #fff;
|
||||
border-radius: 4px;
|
||||
-webkit-align-items: center;
|
||||
@ -18,7 +22,6 @@
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
padding: 0 16px;
|
||||
margin-right: 15px;
|
||||
height: 48px;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
@ -32,11 +35,13 @@
|
||||
display: -ms-inline-flexbox;
|
||||
display: inline-flex;
|
||||
}
|
||||
.container-gradient a:hover {
|
||||
background: #f9f9f9
|
||||
.button-container a:hover {
|
||||
background: #f9f9f9;
|
||||
box-shadow: 0 2px 6px #4a4a4a5c;
|
||||
}
|
||||
.container-gradient a:active {
|
||||
background: #e4e4e4
|
||||
.button-container a:active {
|
||||
background: #e4e4e4;
|
||||
box-shadow: 0 0 0 #4a4a4a5c;
|
||||
}
|
||||
|
||||
@-webkit-keyframes gradientTransition {
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
::selection {
|
||||
color: #fff;
|
||||
background: #7247ff;
|
||||
background: #9065ff;
|
||||
}
|
||||
|
||||
body {
|
||||
@ -19,19 +19,21 @@ body {
|
||||
h1 {
|
||||
font-weight: 500;
|
||||
font-size: 48px;
|
||||
letter-spacing: -0.5px;
|
||||
letter-spacing: -0.05px;
|
||||
font-size: 52px;
|
||||
letter-spacing: -0.75px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-weight: 500;
|
||||
font-size: 38px;
|
||||
letter-spacing: -0.5px;
|
||||
letter-spacing: -0.05px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-weight: 500;
|
||||
font-size: 28px;
|
||||
letter-spacing: -0.5px;
|
||||
letter-spacing: -0.05px;
|
||||
margin: 10px 0 20px;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user