diff --git a/src/App.js b/src/App.js
index 8b2b365..e2c44e9 100644
--- a/src/App.js
+++ b/src/App.js
@@ -1,6 +1,7 @@
import React, { Component } from 'react';
import amplitude from 'amplitude-js';
import {
+ Redirect,
Router,
Location,
LocationProvider
@@ -12,7 +13,6 @@ import {
Login,
Pricing,
Guide,
- Notifications,
NotificationsRedesign,
} from './pages';
@@ -41,6 +41,10 @@ function PageTracker ({location}) {
return null;
}
+function RedirectShell () {
+ return ;
+}
+
class App extends Component {
render() {
return (
@@ -54,8 +58,8 @@ class App extends Component {
-
-
+
+
diff --git a/src/pages/Home/Scene.js b/src/pages/Home/Scene.js
index c92d4b4..0fe2345 100644
--- a/src/pages/Home/Scene.js
+++ b/src/pages/Home/Scene.js
@@ -3,23 +3,29 @@
import React from 'react';
import styled from '@emotion/styled';
import {css, jsx} from '@emotion/core';
-import {navigate, Link as RouterLink} from '@reach/router';
+import {Link as RouterLink} from '@reach/router';
import {routes} from '../../constants';
-import Logo from '../../components/Logo';
-import ConfettiSection from '../../components/Confetti';
+import {
+ BasicPageWrapper,
+ forSmallScreens,
+ forMobile
+} from '../common';
+import WorkflowToggle from './WorkflowToggle';
-import headerPng from '../../images/safari-header.png';
-import pwaHeaderPng from '../../images/screenshots/pwa-demo.png';
-import regularScreenshotPng from '../../images/traditional-screenshot.png';
-import scoreScreenshotPng from '../../images/screenshots/screenshot-score.png';
-import iPhoneXMockupPng from '../../images/screenshots/iphone-x-mockup.png';
-import iPhoneScreenshotPng from '../../images/screenshots/iphone-x.png';
-import { ReactComponent as MentionSvg } from '../../images/svg/mention.svg';
-import { ReactComponent as GoodTeamSvg } from '../../images/svg/good-team.svg';
-import { ReactComponent as ProcessgSvg } from '../../images/svg/process.svg';
-import { ReactComponent as MobileSvg } from '../../images/svg/mobile.svg';
+import {ReactComponent as CloudOffSvg} from '../../images/svg/icons/cloud_off.svg'
+import {ReactComponent as NotificationsActiveSvg} from '../../images/svg/icons/notifications_active.svg'
+import {ReactComponent as PriorityHighSvg} from '../../images/svg/icons/priority_high.svg'
+import {ReactComponent as TuneSvg} from '../../images/svg/icons/tune.svg'
+import {ReactComponent as SpeedSvg} from '../../images/svg/icons/speed.svg'
+import {ReactComponent as GpsFixedSvg} from '../../images/svg/icons/gps_fixed.svg'
+import {ReactComponent as WbIridescentSvg} from '../../images/svg/icons/wb_iridescent.svg'
+import {ReactComponent as TimelineSvg} from '../../images/svg/icons/timeline.svg'
-import {InteractionMenu, Card} from '../NotificationsRedesign/redesign/ui';
+import ItemPng from '../../images/screenshots/item.png';
+import ItemTwoPng from '../../images/screenshots/item-2.png';
+import ScreenshotPng from '../../images/screenshots/new/dashboard.png';
+import ScoresPng from '../../images/screenshots/new/scores.png';
+import ReasonsPng from '../../images/screenshots/new/reasons.png';
import RobinLogo from '../../images/logos/robin-logo.png';
import ForwardLogo from '../../images/logos/forward-logo.png';
@@ -28,194 +34,285 @@ import FacebookLogo from '../../images/logos/facebook-logo.png';
import '../../styles/gradient.css';
import '../../styles/font.css';
-const hash = process.localEnv.GIT_HASH ? `#${process.localEnv.GIT_HASH}` : '';
-const version = require('../../../package.json').version + hash;
+const themeColor = '#27B768';
+const ALT_BACKGROUND_COLOR = '#f6f2ed';
-const themeColor = '#457cff';
+const ProductHuntButton = () => (
+
+
+
+);
-const WIDTH_FOR_MEDIUM_SCREENS = '1100px';
-const WIDTH_FOR_SMALL_SCREENS = '800px';
-
-const HomeInteractionMenu = styled(InteractionMenu)`
- position: fixed;
- z-index: 10;
- left: 86px !important;
- top: 86px !important;
-`;
-
-const PageContainer = styled('div')`
- overflow: hidden;
- background: #fcf8f3;
- position: relative;
- min-height: calc(100vh - 84px);
- height: 100%;
- width: 100%;
- display: block;
- overflow: hidden;
-`;
-
-const FixedContainer = styled('div')`
- position: fixed;
- top: 0;
- left: 0;
- right: 0;
- z-index: 10;
+const Outer = styled('div')`
+ background: ${p => p.alt ? ALT_BACKGROUND_COLOR : 'none'};
`;
const Container = styled('div')`
position: relative;
- background: rgb(252, 248, 243);
- width: 960px;
- margin: 0 auto;
- display: flex;
- justify-content: space-between;
- align-items: center;
box-sizing: border-box;
- padding: 12px 24px;
- @media (max-width: ${WIDTH_FOR_MEDIUM_SCREENS}) {
- width: 100%;
+ display: flex;
+ flex-direction: ${p => p.column ? 'column' : 'row'};
+ max-width: 1080px;
+ min-height: 100px;
+ margin: 0 auto;
+ padding: 1rem 0;
+ margin-bottom: 5rem;
+ ${forSmallScreens(`
+ padding-left: 2.5rem;
+ padding-right: 2.5rem;
+ `)}
+ ${forMobile(`
+ margin-bottom: 2.5rem;
+ `)}
+`;
+
+const FlexItem = styled('div')`
+ flex: ${(({flex = 1}) => flex)};
+ align-items: center;
+ display: flex;
+ flex-wrap: wrap;
+`;
+
+const Button = styled(RouterLink)`
+ cursor: pointer;
+ position: relative;
+ display: inline-block;
+ text-decoration: none;
+ font-weight: 400;
+ color: #333333;
+ text-align: center;
+ vertical-align: middle;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ background-color: transparent;
+ border: 0px solid transparent;
+ margin: 0rem 0.25rem;
+ width: max-content;
+ padding: 0.125rem 1rem;
+ font-size: 18px;
+ line-height: 1.75;
+ border-radius: 5px;
+ -webkit-transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
+ transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
+
+ &:hover {
+ background-color: #f4f4f4;
+ border-color: #f4f4f4;
+ }
+
+ &:active {
+ background-color: #eee;
+ border-color: #eee;
}
`;
-const NewTag = styled('span')`
- align-self: center;
- margin-bottom: 8px;
- padding: 1px 3px;
- background: rgb(235, 87, 87);
- color: white;
- border-radius: 3px;
- margin-left: 6px;
- margin-bottom: 6px;
- font-size: 9px;
- line-height: 1.3;
- vertical-align: text-top;
- text-transform: uppercase;
- font-weight: 600;
- letter-spacing: 0.5px;
+const MainButton = styled(Button)`
+ background-color: ${themeColor};
+ border-color: ${themeColor};
+ color: #fff;
+ font-size: 18px;
+
+ &:hover {
+ background-color: #249959;
+ border-color: #249959;
+ }
+
+ &:active {
+ background-color: #20894f;
+ border-color: #20894f;
+ }
`;
-const LogoTitle = styled('span')`
- display: inline-block;
- font-size: 16px;
- font-weight: 600;
- cursor: pointer;
- user-select: none;
+const HeroButton = styled(MainButton)`
+ font-size: 22px;
+ margin: -4px 8px 0;
+ margin-left: 0;
`;
-const Header = styled('h1')`
- position: relative;
- text-align: left;
- width: 680px;
- max-width: 680px;
- margin: 0;
- z-index: 2;
- font-size: 72px;
- line-height: 78px;
+const FlexBreak = styled('div')`
+ flex-basis: 100%;
+ height: 0;
+ min-height: ${p => p.height || 0}px;
+`;
+
+const HeroTitle = styled('h1')`
+ font-size: 68px;
+ line-height: 68px;
+ margin: 0 auto 6px;
+ font-family: medium-marketing-display-font,Georgia,Cambria,Times New Roman,Times,serif;
+ font-weight: 500;
+
+ ${forMobile(`
+ font-size: 52px;
+ line-height: 58px;
+ `)}
+`;
+
+const HeroSubtitle = styled('h1')`
+ color: #6c757d;
+ font-size: 24px;
+ line-height: 28px;
+ margin: 0 auto 16px;
+ width: 80%;
+ margin-left: 0;
+ font-family: medium-content-sans-serif-font, Inter UI, system-ui, sans-serif;
+ font-weight: 500;
+
+ ${forMobile(`
+ margin: 0 auto 32px;
+ font-size: 20px;
+ line-height: 24px;
+ `)}
+`;
+
+const Title = styled('h1')`
+ font-size: 38px;
+ line-height: 38px;
margin: 0 auto 12px;
font-family: medium-marketing-display-font,Georgia,Cambria,Times New Roman,Times,serif;
font-weight: 500;
- @media (max-width: ${WIDTH_FOR_SMALL_SCREENS}) {
- width: 100%;
- font-size: 4rem;
- line-height: 4.25rem;
- }
+ text-align: center;
`;
-const SubHeader = styled(Header)`
- hyphens: auto;
- font-size: 24px;
- line-height: 26px;
- font-weight: 600;
- width: 680px;
- max-width: 680px;
- margin: 0 auto;
+const Subtitle = styled('h1')`
+ color: #6c757d;
+ font-size: 20px;
+ line-height: 24px;
+ margin: 0 auto 16px;
font-family: medium-content-sans-serif-font, Inter UI, system-ui, sans-serif;
font-weight: 500;
- color: #b3b0a9;
- @media (max-width: ${WIDTH_FOR_SMALL_SCREENS}) {
+ max-width: 540px;
+ text-align: center;
+`;
+
+const ItemImage = styled('img')`
+ width: 847px;
+ box-shadow: rgba(84, 70, 35, 0) 0px 4px 18px, rgba(84, 70, 35, 0.15) 0px 2px 8px;
+ border-radius: 6px;
+ margin-left: ${props => props.left || 0}px;
+ margin-top: ${props => props.top || 0}px;
+ transform: rotate(${props => props.deg || 0}deg) scale(${props => props.scale || 1});
+`;
+
+const HeroLeft = styled(FlexItem)`
+ z-index: 1;
+ flex-grow: 1;
+ width: 50%;
+ ${forMobile(`
+ margin: 0 auto;
width: 100%;
- font-size: 20px;
- line-height: 26px;
- }
+ text-align: center;
+ `)}
`;
-const MainItemContainer = styled(Container)`
- margin: 88px auto 32px;
- align-items: flex-start;
- flex-direction: column;
- @media (max-width: ${WIDTH_FOR_SMALL_SCREENS}) {
- margin-top: 0;
- }
-`;
-
-const ItemWrapper = styled('div')`
- display: flex;
- justify-content: space-between;
- align-items: center;
- flex-direction: row;
- margin-bottom: 28px;
- width: inherit;
- @media (max-width: ${WIDTH_FOR_SMALL_SCREENS}) {
- flex-direction: column;
- flex-flow: column-reverse;
- }
-`;
-
-const ItemNumber = styled('span')`
- font-size: 11rem;
- font-weight: 500;
- @media (max-width: ${WIDTH_FOR_SMALL_SCREENS}) {
+const HeroRight = styled(FlexItem)`
+ flex-grow: 1;
+ width: 50%;
+ ${forMobile(`
display: none;
- }
+ `)}
`;
-const ItemContainer = styled('div')`
+const DotsBackground = styled('div')`
+ position: absolute;
+ height: 400px;
+ width: 100%;
+ margin-left: -60px;
+ background: radial-gradient(transparent 50%, #fffefd), \
+ url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAKElEQVQoU2NkIBIwEqmOgQ4KX715/x/mHDERQbiNGFZTXyGuUKC+rwHAcQwLu0IifQAAAABJRU5ErkJggg==) repeat;
+ ${forMobile(`
+ width: 90%;
+ margin: 0 auto;
+ `)}
+`;
+
+const FooterImageContainer = styled('div')`
position: relative;
- width: 540px;
- margin: 0;
+ height: 250px;
+ width: 100%;
+ text-align: center;
+ background: radial-gradient(transparent 50%, ${ALT_BACKGROUND_COLOR}), \
+ url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAKElEQVQoU2NkIBIwEqmOgQ4KX715/x/mHDERQbiNGFZTXyGuUKC+rwHAcQwLu0IifQAAAABJRU5ErkJggg==) repeat;
+ ${forMobile(`
+ display: none;
+ `)}
+`;
+
+const CompanyQuotesContainer = styled('div')`
display: flex;
justify-content: space-between;
align-items: center;
- padding: 12px 24px;
- flex-direction: column;
- @media (max-width: ${WIDTH_FOR_MEDIUM_SCREENS}) {
- width: 100%;
- }
+ margin-top: 4rem;
+ ${forMobile(`
+ flex-direction: column;
+ max-width: 300px;
+ margin: 0 auto;
+ `)}
`;
-const ItemHeader = styled(Header)`
- position: relative;
- text-align: left;
- width: inherit;
- margin: 0;
- z-index: 2;
- font-size: 62px;
- line-height: 64px;
- margin: 0 0 12px;
- font-family: medium-marketing-display-font,Georgia,Cambria,Times New Roman,Times,serif;
- font-weight: 500;
- @media (max-width: ${WIDTH_FOR_SMALL_SCREENS}) {
- margin-top: 16px;
- font-size: 42px;
- line-height: 48px;
- }
+const HorizontalFlexContainer = styled('div')`
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: space-between;
+ align-items: center;
+ margin-top: 4rem;
`;
-const ItemSubHeader = styled(SubHeader)`
- width: inherit;
-`;
-
-const HorizontalListItem = styled('div')`
+const FeatureItem = styled('div')(({color}) => `
flex: 1;
- border-right: ${props => props.last ? '0px' : '1px'} solid rgba(214, 212, 209, 0.3);
- padding: 0 32px;
- @media (max-width: ${WIDTH_FOR_SMALL_SCREENS}) {
- border-right: none;
- border-bottom: ${props => props.last ? '0px' : '1px'} solid rgba(214, 212, 209, 0.3);
- padding-bottom: 32px;
- margin-bottom: 32px;
+ ${forMobile(`
+ flex: 1 0 34%;
+ `)}
+ flex-direction: column;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-bottom: 4rem;
+ padding: 0 12px;
+
+ svg {
+ background: ${color}28;
+ fill: ${color};
+ border-radius: 100%;
+ padding: 12px;
+ height: 24px;
+ width: 24px;
}
-`;
+
+ h3 {
+ font-size: 24px;
+ line-height: 25px;
+ text-align: center;
+ margin: 18px auto 8px;
+ font-family: medium-marketing-display-font,Georgia,Cambria,Times New Roman,Times,serif;
+ font-weight: 500;
+ }
+
+ p {
+ font-size: 17px;
+ line-height: 22px;
+ margin: 0;
+ text-align: center;
+ }
+`);
+
+const HorizontalListItem = styled('div')(({last}) => `
+ flex: 1;
+ border-right: ${last ? '0px' : '1px'} solid rgba(214, 212, 209, 0.3);
+ padding: 0 32px;
+ ${forMobile(`
+ border-right: 0;
+ border-bottom: ${last ? '0px' : '1px'} solid rgba(214, 212, 209, 0.3);
+ padding: 32px 0;
+ `)}
+`);
const Quote = styled('p')`
margin: 0;
@@ -244,611 +341,212 @@ const CompanyPerson = styled('div')`
span {
display: block;
padding: 0 16px;
- font-size: 14px;
- line-height: 18px;
+ font-size: 16px;
+ line-height: 20px;
color: #37352f80;
}
`;
-const IconLink = styled('span')`
- position: relative;
- cursor: pointer;
- display: inline-flex;
- justify-content: center;
- align-items: center;
- z-index: 1;
- user-select: none;
- height: 40px;
- width: 40px;
- transition: all 150ms ease;
- i {
- font-size: 16px;
- color: inherit;
- }
- &:before {
- content: "";
- transition: all 150ms ease;
- background: #BFC5D122;
- border-radius: 100%;
- display: block;
- position: absolute;
- top: 0;
- bottom: 0;
- left: 0;
- right: 0;
- transform: scale(0);
- }
- &:hover:before {
- transform: scale(1);
- }
- &:active:before {
- background: #BFC5D144;
- }
-`;
-
-const DemoScreenshotHeader = styled('img')`
- background: #f7f6f3;
- width: 960px;
- max-width: 960px;
- display: block;
- box-shadow: rgba(0, 0, 0, 0.15) 0px 10px 20px, rgb(245, 245, 245) 0px -1px 0px;
- border-top-left-radius: 4px;
- border-top-right-radius: 4px;
- border-bottom-left-radius: 0;
- border-bottom-right-radius: 0;
- z-index: 3;
- @media (max-width: ${WIDTH_FOR_MEDIUM_SCREENS}) {
- width: 100%;
- }
-`;
-
-const DemoScreenshot = styled(DemoScreenshotHeader)`
- border-top-left-radius: 0;
- border-top-right-radius: 0;
- border-bottom-left-radius: 4px;
- border-bottom-right-radius: 4px;
-`;
-
-const IPhoneScreenshotContainer = styled('img')`
- position: absolute;
- bottom: -32px;
- right: -32px;
- width: 214px;
- max-width: 214px;
- min-width: 107px;
- display: block;
- background: none;
- z-index: 5;
- @media (max-width: ${WIDTH_FOR_MEDIUM_SCREENS}) {
- display: none;
- }
-`;
-
-const IPhoneScreenshot = styled(IPhoneScreenshotContainer)`
- bottom: -48px;
- z-index: 4;
- transform: scale(0.88);
-`;
-
-const SmallText = styled('p')`
- margin: 0;
- font-size: 12px;
- font-weight: 500;
- display: inline-block;
- color: #37352f;
- z-index: 2;
- @media (max-width: ${WIDTH_FOR_MEDIUM_SCREENS}) {
- display: none;
- }
-`;
-
-const SmallLink = styled('a')`
- margin: 0;
- font-size: 12px;
- font-weight: 600;
- display: inline-block;
- color: #37352f;
- z-index: 2;
- text-decoration: none;
- text-underline-position: initial;
- transition: all 200ms ease;
- &:hover {
- text-decoration: underline;
- }
- @media (max-width: ${WIDTH_FOR_MEDIUM_SCREENS}) {
- display: none;
- }
-`;
-
-export default function Scene ({loggedIn, onLogout, ...props}) {
- const [showBorder, setShowBorder] = React.useState(false);
- const [menu, openMenu] = React.useState(false);
-
- React.useEffect(() => {
- const body = window.document.querySelector('body');
- const hideMenu = () => openMenu(false);
- // For mobile `touchend`
- body.addEventListener('click', hideMenu);
- return () => body.removeEventListener('click', hideMenu);
- }, []);
-
- // React.useEffect(() => {
- // const PAGE_OFFSET = 100;
- // const onScroll = () => {
- // if (window.pageYOffset >= PAGE_OFFSET) {
- // setShowBorder(true);
- // } else if (window.pageYOffset < PAGE_OFFSET) {
- // setShowBorder(false);
- // }
- // };
- // window.addEventListener('scroll', onScroll);
- // return () => window.removeEventListener('scroll', onScroll);
- // }, []);
+export default function Scene (props) {
+ const baseItemOffset = {
+ scale: 0.1,
+ top: -185,
+ left: 20
+ };
return (
-
-
+
+ {/* Hero */}
+
-
+
+ {'Manage your notifications.'}
+ {'Meteorite helps organize, filter, and prioritize your\
+ GitHub notifications to make your life easier'}
+
-
- Meteorite
-
-
-
- {/* @TODO implement the menu */}
- openMenu(true)}>
-
-
-
-
-
-
-
-
-
-
- {loggedIn ? (
- <>
-
- Notifications
-
-
-
- Redesign
- new
-
-
-
- >
- ) : (
-
- Sign in
-
- )}
-
-
-
-
-
-
-
- {/* Header for larger devices */}
-
- {'Control your GitHub notifications'}
-
- {/* Header for small devices */}
-
- {'Control'} {'your GitHub notifications'}
-
-
-
-
- {'Prioritize the tasks that keep you and your team most productive by organizing your notifications'}
-
-
-
-
-
-
- {'View and contribute on GitHub'}
-
-
-
- {'Free and open sourced'}
-
-
-
+ width: 300px;
+ `)}
+ `}>
+
{'Login / Sign up'}
+
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
- {'Hear what folks have to say'}
-
-
- {'Loved by other human beings, just like you'}
-
-
-
- {`So good! I love the importance sorting!`}
-
-
-
- {'— Mike Grabowski'}
- {'Software Architect, React Native'}
-
-
-
-
- {`I've been using it for a bit and it's so useful, especially if you use GitHub for work.`}
-
-
-
- {'— Trevor Suarez'}
- {'Robin, Backend Software Engineer'}
-
-
-
-
- {`Awww sh*t, nice.`}
-
-
-
- {'— Chris Walker'}
- {'Forward, Software Engineer'}
-
-
-
-
-
+ {/* Testimonials */}
+
+
+ {'Hear what others are saying'}
+ {'Loved by other human beings, just like you'}
+
+
+ {`So good! I love the importance sorting!`}
+
+
+
+ {'— Mike Grabowski'}
+ {'Software Architect, React Native'}
+
+
+
+
+ {`I've been using it for a bit and it's so useful, especially if you use GitHub for work.`}
+
+
+
+ {'— Trevor Suarez'}
+ {'Robin, Backend Software Engineer'}
+
+
+
+
+ {`Awww sh*t, nice.`}
+
+
+
+ {'— Chris Walker'}
+ {'Forward, Software Engineer'}
+
+
+
+
-
-
- {1}
-
-
- {'An assistant for your GitHub notifications'}
-
-
- {'Do the same things you do everyday, just a whole lot easier'}
-
-
-
-
+ {/* Lifecycle */}
+
+
+
+ {'The Notification Lifecycle'}
+ {'GitHub notifications can actually be your friend – with a little bit of discipline.\
+ All we need to do is filter out the noise & organize things in a way that makes sense.'}
+
+
+ {'Start using Meteorite absolutely free'}
+ {'Login / Sign up'}
+
+
+
-
-
-
-
-
-
-
-
- {2}
-
-
- {'Your time matters, so things stay simple'}
-
-
- {'Simply sign in and start working — no complicated or weirdly intrusive set up needed'}
-
-
-
-
-
-
-
-
-
-
-
-
-
- {3}
-
-
- {'Work anywhere and everywhere'}
-
-
- {'You love accessibility and so does Meteorite — available on iOS, Android, web, and desktop as an installable PWA'}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ {/* Features */}
+
+
+ {'Features built for getting things done.'}
+ {'All of the features of Meteorite are specifically designed'}
+ {'for optimizing your workday'}
+
+
+
+ {'Serverless'}
+ {'Any notification scoring and storing is done completely offline.'}
+
+
+
+ {'Desktop Notifications'}
+ {'Get notified when we do – ability to turn on desktop notifications.'}
+
+
+
+ {'Auto Sorting'}
+ {'Keep your most important notifications at the top of the list.'}
+
+
+
+ {'Filter Noise'}
+ {'Any notifications that don\'t directly involve you are hidden.'}
+
+
+
+
+ {'Dead Simple'}
+ {'No integrations – just log in and start working.'}
+
+
+
+ {'Live Updates'}
+ {'All of your notifications are processed in real time.'}
+
+
+
+ {'Reasoning'}
+ {'We\'ll also tell you why you\'re getting each notification.'}
+
+
+
+ {'Statistics'}
+ {'Better understand how you work with data visualizations.'}
+
+
-
+ {/* Closer */}
+
+
+
+ {'Better notifications for everyone.'}
+
+ {'Login / Sign up'}
+
+
+
+
+
+
+
+
+
);
};
diff --git a/src/pages/Home/Scene.new.js b/src/pages/Home/Scene.new.js
deleted file mode 100644
index 0fe2345..0000000
--- a/src/pages/Home/Scene.new.js
+++ /dev/null
@@ -1,552 +0,0 @@
-/** @jsx jsx */
-
-import React from 'react';
-import styled from '@emotion/styled';
-import {css, jsx} from '@emotion/core';
-import {Link as RouterLink} from '@reach/router';
-import {routes} from '../../constants';
-import {
- BasicPageWrapper,
- forSmallScreens,
- forMobile
-} from '../common';
-import WorkflowToggle from './WorkflowToggle';
-
-import {ReactComponent as CloudOffSvg} from '../../images/svg/icons/cloud_off.svg'
-import {ReactComponent as NotificationsActiveSvg} from '../../images/svg/icons/notifications_active.svg'
-import {ReactComponent as PriorityHighSvg} from '../../images/svg/icons/priority_high.svg'
-import {ReactComponent as TuneSvg} from '../../images/svg/icons/tune.svg'
-import {ReactComponent as SpeedSvg} from '../../images/svg/icons/speed.svg'
-import {ReactComponent as GpsFixedSvg} from '../../images/svg/icons/gps_fixed.svg'
-import {ReactComponent as WbIridescentSvg} from '../../images/svg/icons/wb_iridescent.svg'
-import {ReactComponent as TimelineSvg} from '../../images/svg/icons/timeline.svg'
-
-import ItemPng from '../../images/screenshots/item.png';
-import ItemTwoPng from '../../images/screenshots/item-2.png';
-import ScreenshotPng from '../../images/screenshots/new/dashboard.png';
-import ScoresPng from '../../images/screenshots/new/scores.png';
-import ReasonsPng from '../../images/screenshots/new/reasons.png';
-
-import RobinLogo from '../../images/logos/robin-logo.png';
-import ForwardLogo from '../../images/logos/forward-logo.png';
-import FacebookLogo from '../../images/logos/facebook-logo.png';
-
-import '../../styles/gradient.css';
-import '../../styles/font.css';
-
-const themeColor = '#27B768';
-const ALT_BACKGROUND_COLOR = '#f6f2ed';
-
-const ProductHuntButton = () => (
-
-
-
-);
-
-const Outer = styled('div')`
- background: ${p => p.alt ? ALT_BACKGROUND_COLOR : 'none'};
-`;
-
-const Container = styled('div')`
- position: relative;
- box-sizing: border-box;
- display: flex;
- flex-direction: ${p => p.column ? 'column' : 'row'};
- max-width: 1080px;
- min-height: 100px;
- margin: 0 auto;
- padding: 1rem 0;
- margin-bottom: 5rem;
- ${forSmallScreens(`
- padding-left: 2.5rem;
- padding-right: 2.5rem;
- `)}
- ${forMobile(`
- margin-bottom: 2.5rem;
- `)}
-`;
-
-const FlexItem = styled('div')`
- flex: ${(({flex = 1}) => flex)};
- align-items: center;
- display: flex;
- flex-wrap: wrap;
-`;
-
-const Button = styled(RouterLink)`
- cursor: pointer;
- position: relative;
- display: inline-block;
- text-decoration: none;
- font-weight: 400;
- color: #333333;
- text-align: center;
- vertical-align: middle;
- -webkit-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none;
- background-color: transparent;
- border: 0px solid transparent;
- margin: 0rem 0.25rem;
- width: max-content;
- padding: 0.125rem 1rem;
- font-size: 18px;
- line-height: 1.75;
- border-radius: 5px;
- -webkit-transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
- transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
-
- &:hover {
- background-color: #f4f4f4;
- border-color: #f4f4f4;
- }
-
- &:active {
- background-color: #eee;
- border-color: #eee;
- }
-`;
-
-const MainButton = styled(Button)`
- background-color: ${themeColor};
- border-color: ${themeColor};
- color: #fff;
- font-size: 18px;
-
- &:hover {
- background-color: #249959;
- border-color: #249959;
- }
-
- &:active {
- background-color: #20894f;
- border-color: #20894f;
- }
-`;
-
-const HeroButton = styled(MainButton)`
- font-size: 22px;
- margin: -4px 8px 0;
- margin-left: 0;
-`;
-
-const FlexBreak = styled('div')`
- flex-basis: 100%;
- height: 0;
- min-height: ${p => p.height || 0}px;
-`;
-
-const HeroTitle = styled('h1')`
- font-size: 68px;
- line-height: 68px;
- margin: 0 auto 6px;
- font-family: medium-marketing-display-font,Georgia,Cambria,Times New Roman,Times,serif;
- font-weight: 500;
-
- ${forMobile(`
- font-size: 52px;
- line-height: 58px;
- `)}
-`;
-
-const HeroSubtitle = styled('h1')`
- color: #6c757d;
- font-size: 24px;
- line-height: 28px;
- margin: 0 auto 16px;
- width: 80%;
- margin-left: 0;
- font-family: medium-content-sans-serif-font, Inter UI, system-ui, sans-serif;
- font-weight: 500;
-
- ${forMobile(`
- margin: 0 auto 32px;
- font-size: 20px;
- line-height: 24px;
- `)}
-`;
-
-const Title = styled('h1')`
- font-size: 38px;
- line-height: 38px;
- margin: 0 auto 12px;
- font-family: medium-marketing-display-font,Georgia,Cambria,Times New Roman,Times,serif;
- font-weight: 500;
- text-align: center;
-`;
-
-const Subtitle = styled('h1')`
- color: #6c757d;
- font-size: 20px;
- line-height: 24px;
- margin: 0 auto 16px;
- font-family: medium-content-sans-serif-font, Inter UI, system-ui, sans-serif;
- font-weight: 500;
- max-width: 540px;
- text-align: center;
-`;
-
-const ItemImage = styled('img')`
- width: 847px;
- box-shadow: rgba(84, 70, 35, 0) 0px 4px 18px, rgba(84, 70, 35, 0.15) 0px 2px 8px;
- border-radius: 6px;
- margin-left: ${props => props.left || 0}px;
- margin-top: ${props => props.top || 0}px;
- transform: rotate(${props => props.deg || 0}deg) scale(${props => props.scale || 1});
-`;
-
-const HeroLeft = styled(FlexItem)`
- z-index: 1;
- flex-grow: 1;
- width: 50%;
- ${forMobile(`
- margin: 0 auto;
- width: 100%;
- text-align: center;
- `)}
-`;
-
-const HeroRight = styled(FlexItem)`
- flex-grow: 1;
- width: 50%;
- ${forMobile(`
- display: none;
- `)}
-`;
-
-const DotsBackground = styled('div')`
- position: absolute;
- height: 400px;
- width: 100%;
- margin-left: -60px;
- background: radial-gradient(transparent 50%, #fffefd), \
- url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAKElEQVQoU2NkIBIwEqmOgQ4KX715/x/mHDERQbiNGFZTXyGuUKC+rwHAcQwLu0IifQAAAABJRU5ErkJggg==) repeat;
- ${forMobile(`
- width: 90%;
- margin: 0 auto;
- `)}
-`;
-
-const FooterImageContainer = styled('div')`
- position: relative;
- height: 250px;
- width: 100%;
- text-align: center;
- background: radial-gradient(transparent 50%, ${ALT_BACKGROUND_COLOR}), \
- url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAKElEQVQoU2NkIBIwEqmOgQ4KX715/x/mHDERQbiNGFZTXyGuUKC+rwHAcQwLu0IifQAAAABJRU5ErkJggg==) repeat;
- ${forMobile(`
- display: none;
- `)}
-`;
-
-const CompanyQuotesContainer = styled('div')`
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-top: 4rem;
- ${forMobile(`
- flex-direction: column;
- max-width: 300px;
- margin: 0 auto;
- `)}
-`;
-
-const HorizontalFlexContainer = styled('div')`
- display: flex;
- flex-wrap: wrap;
- justify-content: space-between;
- align-items: center;
- margin-top: 4rem;
-`;
-
-const FeatureItem = styled('div')(({color}) => `
- flex: 1;
- ${forMobile(`
- flex: 1 0 34%;
- `)}
- flex-direction: column;
- display: flex;
- align-items: center;
- justify-content: center;
- margin-bottom: 4rem;
- padding: 0 12px;
-
- svg {
- background: ${color}28;
- fill: ${color};
- border-radius: 100%;
- padding: 12px;
- height: 24px;
- width: 24px;
- }
-
- h3 {
- font-size: 24px;
- line-height: 25px;
- text-align: center;
- margin: 18px auto 8px;
- font-family: medium-marketing-display-font,Georgia,Cambria,Times New Roman,Times,serif;
- font-weight: 500;
- }
-
- p {
- font-size: 17px;
- line-height: 22px;
- margin: 0;
- text-align: center;
- }
-`);
-
-const HorizontalListItem = styled('div')(({last}) => `
- flex: 1;
- border-right: ${last ? '0px' : '1px'} solid rgba(214, 212, 209, 0.3);
- padding: 0 32px;
- ${forMobile(`
- border-right: 0;
- border-bottom: ${last ? '0px' : '1px'} solid rgba(214, 212, 209, 0.3);
- padding: 32px 0;
- `)}
-`);
-
-const Quote = styled('p')`
- margin: 0;
- font-family: medium-content-title-font, Inter UI, sans-serif;
- font-size: 18px;
- font-weight: 400;
- &:before {
- content: open-quote;
- }
- &:after {
- content: close-quote;
- }
-`;
-
-const CompanyPerson = styled('div')`
- transform: scale(0.95);
- display: flex;
- padding: 8px 0;
- margin: 0;
- img {
- display: block;
- height: 30px;
- width: 30px;
- border-radius: 2px;
- }
- span {
- display: block;
- padding: 0 16px;
- font-size: 16px;
- line-height: 20px;
- color: #37352f80;
- }
-`;
-
-export default function Scene (props) {
- const baseItemOffset = {
- scale: 0.1,
- top: -185,
- left: 20
- };
-
- return (
-
-
- {/* Hero */}
-
-
- {'Manage your notifications.'}
- {'Meteorite helps organize, filter, and prioritize your\
- GitHub notifications to make your life easier'}
-
-
-
{'Login / Sign up'}
-
-
-
-
-
-
-
-
-
-
- {/* Testimonials */}
-
-
- {'Hear what others are saying'}
- {'Loved by other human beings, just like you'}
-
-
- {`So good! I love the importance sorting!`}
-
-
-
- {'— Mike Grabowski'}
- {'Software Architect, React Native'}
-
-
-
-
- {`I've been using it for a bit and it's so useful, especially if you use GitHub for work.`}
-
-
-
- {'— Trevor Suarez'}
- {'Robin, Backend Software Engineer'}
-
-
-
-
- {`Awww sh*t, nice.`}
-
-
-
- {'— Chris Walker'}
- {'Forward, Software Engineer'}
-
-
-
-
-
-
- {/* Lifecycle */}
-
-
-
- {'The Notification Lifecycle'}
- {'GitHub notifications can actually be your friend – with a little bit of discipline.\
- All we need to do is filter out the noise & organize things in a way that makes sense.'}
-
-
- {'Start using Meteorite absolutely free'}
- {'Login / Sign up'}
-
-
-
-
- {/* Features */}
-
-
- {'Features built for getting things done.'}
- {'All of the features of Meteorite are specifically designed'}
- {'for optimizing your workday'}
-
-
-
- {'Serverless'}
- {'Any notification scoring and storing is done completely offline.'}
-
-
-
- {'Desktop Notifications'}
- {'Get notified when we do – ability to turn on desktop notifications.'}
-
-
-
- {'Auto Sorting'}
- {'Keep your most important notifications at the top of the list.'}
-
-
-
- {'Filter Noise'}
- {'Any notifications that don\'t directly involve you are hidden.'}
-
-
-
-
- {'Dead Simple'}
- {'No integrations – just log in and start working.'}
-
-
-
- {'Live Updates'}
- {'All of your notifications are processed in real time.'}
-
-
-
- {'Reasoning'}
- {'We\'ll also tell you why you\'re getting each notification.'}
-
-
-
- {'Statistics'}
- {'Better understand how you work with data visualizations.'}
-
-
-
-
- {/* Closer */}
-
-
-
- {'Better notifications for everyone.'}
-
- {'Login / Sign up'}
-
-
-
-
-
-
-
-
-
- );
-};
diff --git a/src/pages/Home/index.js b/src/pages/Home/index.js
index 593f9e0..bce2e21 100644
--- a/src/pages/Home/index.js
+++ b/src/pages/Home/index.js
@@ -3,7 +3,7 @@ import { compose } from 'recompose';
import { withAuthProvider } from '../../providers/Auth';
import { withCookiesProvider } from '../../providers/Cookies';
import { OAUTH_TOKEN_COOKIE } from '../../constants/cookies';
-import Scene from './Scene.new';
+import Scene from './Scene';
class HomePage extends React.Component {
onLogout = () => {
diff --git a/src/pages/Login/index.js b/src/pages/Login/index.js
index 167f096..49f7b76 100644
--- a/src/pages/Login/index.js
+++ b/src/pages/Login/index.js
@@ -24,7 +24,7 @@ class LoginPage extends React.Component {
render () {
if (this.props.authApi.token) {
- return
+ return
}
return (
diff --git a/src/pages/Notifications/Scene.js b/src/pages/Notifications/Scene.js
deleted file mode 100644
index c471c10..0000000
--- a/src/pages/Notifications/Scene.js
+++ /dev/null
@@ -1,1286 +0,0 @@
-import React from 'react';
-import moment from 'moment';
-// import {VictoryPie, VictoryChart} from "victory";
-import {Link} from "@reach/router";
-import styled from 'react-emotion';
-import Icon from '../../components/Icon';
-import Logo from '../../components/Logo';
-import LoadingIcon from '../../components/LoadingIcon';
-import ErrorMessage from '../../components/ErrorMessage';
-import {routes} from '../../constants';
-import {Filters} from '../../constants/filters';
-import {withOnEnter, withTooltip} from '../../enhance';
-import {Status} from '../../constants/status';
-import {Reasons, Badges} from '../../constants/reasons';
-import '../../styles/gradient.css';
-
-/* eslint-disable jsx-a11y/anchor-is-valid */
-/* eslint-disable no-script-url */
-
-function getColorFromFilter (activeFilter) {
- switch (activeFilter) {
- case Filters.ASSIGNED:
- return '#f12c3f';
- case Filters.PARTICIPATING:
- return '#00d19a';
- case Filters.COMMENT:
- return '#24292e';
- case Filters.REVIEW_REQUESTED:
- return '#00A0F5';
- default:
- return '#24292e';
- }
-}
-
-function getWeekday (day) {
- switch (day) {
- case 0:
- return 'Sunday';
- case 1:
- return 'Monday';
- case 2:
- return 'Tuesday';
- case 3:
- return 'Wednesday';
- case 4:
- return 'Thursday';
- case 5:
- return 'Friday';
- case 6:
- return 'Saturday';
- }
-}
-
-function stringOfType (type) {
- switch (type) {
- case 'PullRequest':
- return 'pull request';
- case 'Issue':
- return 'issue';
- default:
- return 'task';
- }
-}
-
-export function getMessageFromReasons (reasons, type) {
- switch (reasons[reasons.length - 1].reason) {
- case Reasons.ASSIGN:
- return 'You were assigned this ' + stringOfType(type);
- case Reasons.AUTHOR:
- return 'There was activity on this thread you created';
- case Reasons.COMMENT:
- return 'Somebody left a comment';
- case Reasons.MENTION:
- return 'You were @mentioned';
- case Reasons.REVIEW_REQUESTED:
- return 'Your review was requested for this ' + stringOfType(type);
- case Reasons.SUBSCRIBED:
- return 'There was an update and you\'re subscribed';
- case Reasons.OTHER:
- default:
- return 'Something was updated';
- }
-}
-
-function getRelativeTime (time) {
- const currentTime = moment();
- const targetTime = moment(time);
- const diffMinutes = currentTime.diff(targetTime, 'minutes');
- if (diffMinutes < 1)
- return 'Just now';
- if (diffMinutes < 5)
- return 'Few minutes ago';
- if (diffMinutes < 60)
- return diffMinutes + ' minutes ago';
- if (diffMinutes < 60 * 24)
- return Math.floor(diffMinutes / 60) + ' hours ago';
-
- const diffDays = currentTime.diff(targetTime, 'days');
- if (diffDays === 1)
- return 'Yesterday';
- if (diffDays <= 7)
- return 'Last ' + targetTime.format('dddd');
- // @TODO implement longer diffs
- return 'Over a week ago';
-}
-
-const UnofficialReleaseTag = styled('span')({
- color: 'white',
- position: 'absolute',
- left: '21px',
- bottom: '0px',
- fontSize: '9px',
- background: '#f42839',
- fontWeight: '800',
- padding: '2px 4px',
- borderRadius: '4px',
- textTransform: 'uppercase',
-});
-
-const FixedContainer = styled('div')({
- height: '80%',
- maxWidth: 270,
- display: 'block',
- position: 'relative'
-});
-
-const InlineBlockContainer = styled('div')({
- 'div': {
- display: 'inline-block'
- }
-});
-
-const NotificationsContainer = styled('div')({
- position: 'relative',
- margin: '0 auto',
- padding: 0,
- width: '100%',
- display: 'flex',
- flexDirection: 'row',
- overflowX: 'hidden',
- boxSizing: 'border-box'
-});
-
-const NavigationContainer = styled('div')({
- position: 'fixed',
- top: 0,
- boxSizing: 'border-box',
- margin: '0 auto',
- width: '100%',
- height: 60,
- color: 'hsla(0,0%,100%,.75)',
- paddingBottom: '12px',
- paddingTop: '12px',
- zIndex: '100',
-});
-
-const GeneralOptionsContainer = styled(NavigationContainer)({
- position: 'relative',
- zIndex: '1',
- height: 'initial',
- minHeight: 60,
- width: '95%',
- margin: 0,
- padding: '8px 16px',
- paddingTop: 18,
- flex: '0 0 50px',
- 'button': {
- display: 'inline-flex',
- margin: 0
- }
-});
-
-const Sidebar = styled('div')({
- flex: '0 0 300px',
- padding: '32px 20px',
- paddingRight: 0,
- display: 'flex',
- justifyContent: 'center',
-});
-
-const SidebarLink = styled('a')({}, ({active, color}) => ({
- textAlign: 'left',
- userSelect: 'none',
- margin: '0 auto 5px',
- position: 'relative',
- cursor: 'pointer',
- borderRadius: 4,
- alignItems: 'center',
- padding: '0 14px',
- height: 40,
- width: 200,
- fontSize: '12px',
- fontWeight: 600,
- letterSpacing: 0.5,
- textTransform: 'capitalize',
- textDecoration: 'none',
- transition: 'background 0.12s ease-in-out',
- display: 'flex',
- background: active ? color : 'none',
- color: active ? '#fff' : '#202124',
- ':before': {
- content: '""',
- transition: 'all 150ms ease',
- background: 'rgba(190, 197, 208, 0.25)',
- borderRadius: 4,
- display: 'block',
- top: 0,
- bottom: 0,
- right: 0,
- left: 0,
- position: 'absolute',
- transform: 'scale(0)'
- },
- ':hover:before': {
- transform: active ? 'scale(0)' : 'scale(1)',
- },
- ':active:before': {
- background: 'rgba(190, 197, 208, 0.5)'
- },
- 'div': {
- marginRight: 5
- }
-}));
-
-const Notifications = styled('div')({
- flex: 1,
-});
-
-const NavTab = styled('a')({
- position: 'relative',
- textTransform: 'capitalize',
- userSelect: 'none',
- borderRadius: 4,
- textDecoration: 'none',
- fontWeight: '500',
- fontSize: '14px',
- textAlign: 'left',
- opacity: 0.6,
- padding: '20px 32px',
- paddingLeft: '16px',
- width: '150px',
- display: 'inline-block',
- margin: 0,
- transition: 'all 150ms ease',
- ':hover': {
- background: 'rgba(190, 197, 208, 0.25)',
- },
-}, ({ number }) => ({
- ':after': number > 0 && {
- content: `"${number}"`,
- color: '#ffffff',
- background: '#a8a8a9',
- fontSize: '10px',
- verticalAlign: 'text-top',
- padding: '1px 8px',
- borderRadius: '4px',
- marginLeft: '6px',
- display: 'inline-block',
- }
-}), ({ active, color, number }) => active && ({
- color,
- opacity: 1,
- ':before': {
- content: '""',
- position: 'absolute',
- background: color,
- height: '3px',
- width: '90%',
- bottom: '0',
- left: '5%',
- borderTopLeftRadius: '4px',
- borderTopRightRadius: '4px',
- },
- ':after': number > 0 && {
- content: `"${number}"`,
- color: '#ffffff',
- background: color,
- fontSize: '10px',
- verticalAlign: 'text-top',
- padding: '1px 8px',
- borderRadius: '4px',
- marginLeft: '6px',
- display: 'inline-block',
- }
-}));
-
-const Tab = styled('button')({
- position: 'relative',
- userSelect: 'none',
- cursor: 'pointer',
- border: 0,
- outline: 'none',
- background: 'none',
- height: 40,
- width: 40,
- borderRadius: '100%',
- margin: '0 auto',
- display: 'flex',
- justifyContent: 'center',
- alignItems: 'center',
- ':before': {
- content: "''",
- transition: 'all 150ms ease',
- background: 'rgba(190, 197, 208, 0.25)',
- borderRadius: '100%',
- display: 'block',
- height: 40,
- width: 40,
- position: 'absolute',
- transform: 'scale(0)'
- },
- ':hover:before': {
- transform: 'scale(1)',
- },
- ':active:before': {
- background: 'rgba(190, 197, 208, 0.5)'
- }
-}, ({disabled}) => disabled && ({
- background: 'none !important',
- opacity: 0.35,
- cursor: 'default',
- ':hover:before': {
- transform: 'scale(0) !important',
- },
- ':active:before': {
- background: 'none !important'
- }
-}));
-
-const SearchField = styled('div')({
- float: 'left',
- textAlign: 'left',
- width: '50%',
- boxShadow: '0 4px 6px rgba(50,50,93,.11), 0 1px 3px rgba(0,0,0,.08)',
- margin: '0 auto',
- background: 'hsla(0,0%,100%,.125)',
- borderRadius: '4px',
- alignItems: 'center',
- padding: 0,
- height: '36px',
- fontSize: '13px',
- textDecoration: 'none',
- transition: 'all 0.06s ease-in-out',
- display: 'inline-flex',
- ':focus-within': {
- background: '#fff'
- }
-});
-
-const Message = styled('div')({
- display: 'block',
- textAlign: 'center',
- marginTop: 24 * 5,
- 'p': {
- paddingTop: 24,
- userSelect: 'none',
- display: 'block',
- margin: 0
- }
-});
-
-const LoaderContainer = styled('div')({
- display: 'flex',
- justifyContent: 'center',
- alignItems: 'center',
- height: '100%'
-});
-
-const SearchInput = styled('input')({
- flex: 1,
- textAlign: 'left',
- margin: '0 auto',
- background: 'none',
- padding: 0,
- height: '36px',
- color: '#fff',
- fontSize: '13px',
- textDecoration: 'none',
- display: 'inline-flex',
- border: '0',
- outline: 'none',
- ':focus': {
- color: '#202124'
- }
-});
-const EnhancedSearchInput = withOnEnter(SearchInput);
-
-const NotificationRow = styled('tr')({
- position: 'relative',
- display: 'flex',
- alignItems: 'center',
- textAlign: 'left',
- width: '100%',
- borderRadius: 4,
- margin: '0 auto',
- padding: '8px 16px',
- transition: 'all 0.1s ease-in-out',
- boxSizing: 'border-box',
- ':hover': {
- background: '#f9f9f9',
- // boxShadow: '0 4px 6px rgba(50,50,93,.11), 0 1px 3px rgba(0,0,0,.08)',
- zIndex: 10
- }
-});
-
-const NotificationTab = styled(Tab)({
- display: 'inline-flex',
- margin: 0,
-});
-
-const Timestamp = styled('span')({
- position: 'relative',
- margin: 0,
- marginLeft: 10,
- fontSize: 11,
- opacity: 0.5,
-});
-
-const ReasonMessage = styled(Timestamp)({
-
-});
-
-const NotificationTitle = styled('span')({
- position: 'relative',
- display: 'block'
-}, ({img}) => img && ({
- paddingLeft: 20,
- '::before': {
- content: '""',
- position: 'absolute',
- display: 'block',
- background: `url(${img}) center center no-repeat`,
- backgroundSize: 'cover',
- left: 0,
- height: 20,
- width: 20,
- }
-}));
-
-const Repository = styled('span')({
- fontWeight: 500,
- marginLeft: 10,
- fontSize: 14
-});
-
-const PRIssue = styled(Repository)({
- fontWeight: 400,
-}, ({after}) => ({
- ':after': {
- content: `"#${after}"`,
- fontSize: 13,
- opacity: .3,
- marginLeft: 5
- }
-}));
-
-const Table = styled('table')({
- width: '96%',
- minWidth: 970,
- 'td': {
- display: 'inline-block'
- }
-});
-
-const TableItem = styled('td')({
- whiteSpace: 'nowrap',
- overflow: 'hidden',
- textOverflow: 'ellipsis',
-}, ({width, flex}) => ({
- width,
- flex
-}));
-
-const SmallLink = styled('a')({
- display: 'block',
- marginRight: 10,
- cursor: 'pointer',
- fontSize: 10,
- lineHeight: '20px',
- fontWeight: 400,
- textDecoration: 'underline',
- transition: 'all 0.12s ease-in-out',
- ':hover': {
- opacity: 0.75
- }
-});
-
-const BarGraphDiv = styled('div')({
- position: 'relative',
- height: 100,
- ':after': {
- content: `"Notifications Read"`,
- position: 'absolute',
- textAlign: 'left',
- fontSize: 16,
- top: -67,
- left: -23,
- fontWeight: 500
- }
-});
-
-const FauxGridLine = styled('div')({
- position: 'absolute',
- width: '100%',
- height: 1,
- background: '#f3f3f3',
-}, ({offsetY, tick, showDecimals}) => ({
- bottom: offsetY,
- ':after': tick !== false ? {
- content: showDecimals
- ? `"${tick.toFixed(2).replace('.00', '')}"`
- : `"${Math.round(tick)}"`,
- position: 'absolute',
- top: '-6px',
- left: '-30px',
- width: '20px',
- textAlign: 'right',
- } : {}
-}));
-
-const Legend = styled('div')({
- position: 'absolute',
- textAlign: 'left',
- top: -35,
- left: -23,
-});
-
-const LegendItem = styled('div')({
- position: 'relative',
- display: 'inline-block',
- fontSize: 12,
- marginRight: 15,
-}, ({color}) => ({
- ':before': {
- content: '" "',
- background: color,
- display: 'inline-block',
- height: 12,
- width: 12,
- borderRadius: 2,
- marginRight: 5,
- verticalAlign: 'middle'
- }
-}));
-
-function BarGraph ({children, numLines, max, ...props}) {
- const height = 100;
- const gapSize = height / (numLines - 1);
- const yAxisTickOffset = gapSize / 100 * max;
- // Only show decimals if we have to, e.g. the steps are under 1.
- const showDecimals = yAxisTickOffset * numLines < 2;
- return (
-
-
- Last week
- This week
-
- {new Array(numLines).fill(0).map((_, i) => (
- 0 || i === 0 ? (
- i % 2 === 0 ? i * yAxisTickOffset : false
- ) : (
- false
- )}
- />
- ))}
- {children}
-
- );
-}
-
-const Separator = styled('div')({
- position: 'relative',
- background: '#f3f3f3',
- width: '100%',
- height: 1,
- margin: '30px 0'
-});
-
-const BarContainer = styled('div')({
- position: 'absolute',
- display: 'flex',
- flexDirection: 'row',
- justifyContent: 'space-evenly',
- width: '100%',
- height: 100,
- alignItems: 'flex-end',
-}, ({opacity, hide}) => ({
- 'div': {
- background: opacity ? '#f2f9ff' : undefined,
- opacity: hide ? 0 : 1
- }
-}));
-
-const stripe_size = 3;
-const Bar = styled('div')({
- position: 'relative',
- width: 30,
- minHeight: 5,
- background: '#00d19a',
- borderRadius: 4,
-}, ({height, active, label, visible = true, bottomTick}) => ({
- height,
- background: !visible
- ? 'none'
- : active && false
- ? `repeating-linear-gradient(45deg, #28abf0, #28abf0 ${stripe_size}px, #28abf055 ${stripe_size}px, #28abf055 ${stripe_size * 2}px)`
- : '#28abf0',
- ':after': label ? {
- content: `"${label}"`,
- position: 'absolute',
- left: '-20px',
- width: '70px',
- textAlign: 'center',
- bottom: '-25px',
- color: '#3f464c',
- } : {},
- ':before': bottomTick ? {
- content: '" "',
- position: 'absolute',
- background: '#f3f3f3',
- width: '1px',
- height: '8px',
- bottom: '-8px',
- left: '14px',
- } : {},
-}));
-
-const PageCount = styled('div')({
- fontSize: 12,
- margin: '12px auto',
- width: '100%',
- textAlign: 'center',
- color: 'rgb(32, 33, 36)'
-});
-
-const NotificationIconWrapper = styled('div')({
- background: '#22303f',
- borderRadius: 4,
- transform: 'scale(.65)'
-});
-
-const EnhancedBar = withTooltip(Bar);
-const EnhancedTab = withTooltip(Tab);
-const EnhancedNavTab = withTooltip(NavTab);
-const EnhancedNotificationTab = withTooltip(NotificationTab);
-const EnhancedSidebarLink = withTooltip(SidebarLink);
-const EnhancedIconHot = withTooltip(Icon.Hot);
-const EnhancedIconTimer = withTooltip(Icon.Timer);
-const EnhancedIconConvo = withTooltip(Icon.Convo);
-
-// @TODO if GitHub ever fixes their API, we can use `reasons` to know when
-// a PR/Issue merges/closes/etc.
-function getPRIssueIcon (type, _reasons) {
- const scale = 1.0;
- switch (type) {
- case 'PullRequest':
- return (
-
-
-
- );
- case 'Issue':
- return (
-
-
-
- );
- default:
- return null;
- }
-}
-
-export default function Scene ({
- currentTime,
- stagedStatistics,
- isFirstTimeUser,
- notificationsPermission,
- queuedCount,
- stagedCount,
- closedCount,
- first,
- last,
- lastPage,
- page,
- notifications,
- query,
- activeStatus,
- allNotificationsCount,
- stagedTodayCount,
- onChangePage,
- onSetActiveStatus,
- onClearQuery,
- onLogout,
- onSearch,
- onMarkAsRead,
- onMarkAllAsStaged,
- onFetchNotifications,
- onStageThread,
- onRestoreThread,
- isSearching,
- isFetchingNotifications,
- onClearCache,
- fetchingNotificationsError,
- activeFilter,
- onSetActiveFilter,
- setNotificationsPermission
-}) {
- const loading = isSearching || isFetchingNotifications;
- const isFirstPage = page === 1;
- const isLastPage = page === lastPage;
-
- const NotificationsIcon = notificationsPermission === 'granted'
- ? Icon.NotificationsOn
- : Icon.NotificationsOff;
-
- if (isFirstTimeUser && notifications.length > 10) {
- // probably prompt to mark all as read to start out since they prob don't use notifs
- }
-
- stagedStatistics = stagedStatistics.map(n => parseInt(n, 10));
-
- const highestStagedCount = stagedStatistics.reduce((n, m) => Math.max(n, m), 0);
- let lastWeekStats = stagedStatistics.slice(0, 7);
- let thisWeekStats = stagedStatistics.slice(7);
-
- // Trim off the weekends.
- lastWeekStats = lastWeekStats.slice(1, -1);
- thisWeekStats = thisWeekStats.slice(1, -1);
-
- return (
-
-
-
-
{
- onSetActiveStatus(Status.QUEUED);
- onSetActiveFilter(Filters.PARTICIPATING);
- }}
- />
- beta
-
-
- event.target.select()}
- type="text"
- placeholder="Search for notifications"
- onEnter={onSearch}
- />
- {isSearching && }
-
-
-
home
-
- use new redesign
-
-
-
-
-
-
-
-
-
-
-
-
- {currentTime.format('h:mma')}
-
- {currentTime.format('dddd, MMMM Do')}
- You've triaged {stagedTodayCount} notifications today
-
- onSetActiveFilter(Filters.PARTICIPATING)}>
- {activeFilter === Filters.PARTICIPATING ? (
-
- ) : (
-
- )}
- all your updates
-
- onSetActiveFilter(Filters.REVIEW_REQUESTED)}>
- {activeFilter === Filters.REVIEW_REQUESTED ? (
-
- ) : (
-
- )}
- review requested
-
- onSetActiveFilter(Filters.ASSIGNED)}>
- {activeFilter === Filters.ASSIGNED ? (
-
- ) : (
-
- )}
- assigned
-
- onSetActiveFilter(Filters.COMMENT)}>
- {activeFilter === Filters.COMMENT ? (
-
- ) : (
-
- )}
- commented
-
-
-
-
- {/* Last week's statistics */}
-
- {lastWeekStats.map((dayStats, i) => (
-
- ))}
-
- {/* This week's ongoing statistics */}
-
- {thisWeekStats.map((dayStats, i) => (
- = i + 1}
- />
- ))}
-
- {/* Wrapper for tooltips */}
- {/*
- {thisWeekStats.map((dayStats, i) => (
-
- ))}
- */}
-
-
-
-
- Report bugs
- Submit feedback
- See source code
-
-
-
-
-
-
-
- onFetchNotifications()) : undefined}
- />
-
-
- {
- const response = window.confirm('Are you sure you want to mark all your notifications as read?');
- if (response) {
- onMarkAllAsStaged();
- }
- }) : undefined}
- />
-
-
- {
- const response = window.confirm('Are you sure you want to clear the cache?');
- if (response) {
- onClearCache();
- }
- }) : undefined}
- />
-
-
- {
- switch(notificationsPermission) {
- case 'granted':
- return setNotificationsPermission('denied');
- case 'denied':
- case 'default':
- default:
- Notification.requestPermission().then(result => {
- return setNotificationsPermission(result);
- });
- }
- }) : undefined}
- />
-
- {query ? (
-
-
-
- onClearQuery()) : undefined}
- />
-
-
- ) : null}
-
-
-
- onChangePage(page - 1)) : undefined}
- />
-
-
- onChangePage(page + 1)) : undefined}
- />
-
-
-
-
- onSetActiveStatus(Status.QUEUED)}
- href="javascript:void(0);">
- Unread
-
- onSetActiveStatus(Status.STAGED)}
- href="javascript:void(0);">
- Read
-
- onSetActiveStatus(Status.CLOSED)}
- href="javascript:void(0);">
- Archived
-
-
-
-
- {isFetchingNotifications ? (
-
-
-
- ) : fetchingNotificationsError ? (
-
-
- An error occurred when fetching notifications.
- onFetchNotifications()} href="#">Try again?
-
-
- ) : notifications.length <= 0 ? (
-
-
- No
- {activeStatus === Status.QUEUED ? (
- ' unread '
- ) : activeStatus === Status.STAGED ? (
- ' read '
- ) : (
- ' archived '
- )}
- notifications
-
-
- 🎉 You're all set here for the moment
-
- ) : (
-
-
-
- {notifications.map(n => (
-
-
-
- {getPRIssueIcon(n.type, n.reasons)}
-
-
- {
- window.open(n.url);
- onStageThread(n.id, n.repository)
- }}>
-
- {n.name}
-
-
- {getRelativeTime(n.updated_at)}
- {n.isAuthor && (
-
- )}
-
-
-
- {getMessageFromReasons(n.reasons, n.type)}
-
-
-
-
- {activeStatus === Status.QUEUED && n.badges.map(badge => {
- switch (badge) {
- case Badges.HOT:
- // lots of `reasons` within short time frame
- return (
-
- );
- case Badges.OLD:
- // old
- return (
-
- );
- case Badges.COMMENTS:
- // lots of `reasons`
- return (
-
- );
- default:
- return null;
- }
- })}
-
-
-
- window.open(n.repositoryUrl)}
- style={{cursor: 'pointer', userSelect: 'none'}}>
- {n.repository}
-
-
-
- +{n.score}
-
- {activeStatus === Status.QUEUED ? (
-
- onStageThread(n.id, n.repository)) : undefined}
- />
-
- ) : (
-
- onRestoreThread(n.id)) : undefined}
- />
-
- )}
- {activeStatus === Status.CLOSED ? (
-
-
-
- ) : (
-
- onMarkAsRead(n.id, n.repository)) : undefined}
- />
-
- )}
-
-
- ))}
-
-
- {!loading && Page {page} out of {lastPage} }
-
- )}
-
-
-
-
-
- );
-}
diff --git a/src/pages/Notifications/index.js b/src/pages/Notifications/index.js
deleted file mode 100644
index 61173cf..0000000
--- a/src/pages/Notifications/index.js
+++ /dev/null
@@ -1,466 +0,0 @@
-import React from 'react';
-import moment from 'moment';
-import { Redirect, navigate } from "@reach/router";
-import { compose } from 'recompose';
-import { withNotificationsProvider } from '../../providers/Notifications';
-import { withAuthProvider } from '../../providers/Auth';
-import { withCookiesProvider } from '../../providers/Cookies';
-import { withStorageProvider } from '../../providers/Storage';
-import { OAUTH_TOKEN_COOKIE } from '../../constants/cookies';
-import { routes } from '../../constants';
-import { Filters } from '../../constants/filters';
-import { Status } from '../../constants/status';
-import { Reasons, Badges } from '../../constants/reasons';
-import Scene, { getMessageFromReasons } from './Scene';
-import issueIcon from '../../images/issue-bg.png';
-import prIcon from '../../images/pr-bg.png';
-import tabIcon from '../../images/icon.png';
-import tabDotIcon from '../../images/iconDot.png';
-
-const PER_PAGE = 10;
-
-// @TODO Move these functions.
-
-/**
- * Given a notification, give it a score based on its importance.
- *
- * There are some interesting workarounds that go into this algorithm to account
- * for GitHub's broken notifications API -- but we will get to that later. First,
- * let's start off with the basics of scoring.
- *
- * There are a few "reasons" that we can be getting a notification, each having
- * an initial weight of importance:
- *
- * - MENTION -> 8
- * - ASSIGN -> 14
- * - REVIEW_REQUESTED -> 30
- * - SUBSCRIBED -> 3
- * - COMMENT -> 3
- * - AUTHOR -> 10
- * - OTHER -> 2
- *
- * There are some rules that go to giving out these scores, primarily being the
- * first time we see one of these unique reasons, we award the notification with
- * the respective score, but a reason that transitions into itself will be awarded
- * a degraded score of min(ceil(n/3), 2). For example:
- *
- * - null, MENTION, MENTION -> 0, 8, 3
- * - null, ASSIGN, ASSIGN, REVIEW_REQUESTED, -> 0, 14, 5, 20
- * - null, SUBSCRIBED, SUBSCRIBED, SUBSCRIBED -> 0, 3, 2, 2
- *
- * @param {Object} notification Some notification to score.
- * @return {number} The score.
- */
-function scoreOf (notification) {
- const {reasons} = notification;
- let score = 0;
- let prevReason = null;
- for (let i = 0; i < reasons.length; i++) {
- const reason = reasons[i].reason;
- if (prevReason && reason === prevReason) {
- const degradedScore = Math.ceil(scoreOfReason[reason] / 3);
- score += Math.max(degradedScore, 2);
- } else {
- score += scoreOfReason[reason];
- }
- prevReason = reason;
- }
- return score;
-};
-
-function badgesOf (notification) {
- const badges = [];
- const len = notification.reasons.length;
- const timeSinceLastUpdate = moment().diff(moment(notification.reasons[len - 1].time), 'minutes');
-
- // If there are more than 4 reasons, and the last 4 reasons have happened within
- // an hour of each other. The last update should be within the past 30 minutes.
- // The specific time frame and reasons count is subject to change.
- if (len >= 4 && timeSinceLastUpdate < 30) {
- const oldestReference = moment(notification.reasons[len - 4].time);
- const newestReference = moment(notification.reasons[len - 1].time);
- if (newestReference.diff(oldestReference, 'hours') <= 1) {
- badges.push(Badges.HOT);
- }
- }
- // If there's a lot of activity going on within the thread in general.
- // The specific nunmber should be relative to average number of thread lengths.
- // We can track a running statistic as we see notifications update.
- if (len > 6) {
- badges.push(Badges.COMMENTS);
- }
- // If you've been tagged in for review and the most recent update happened over
- // 4 hours ago, that specific time is subject to change.
- if (notification.reasons.some(r => r.reason === Reasons.REVIEW_REQUESTED) &&
- timeSinceLastUpdate > 60 * 4) {
- badges.push(Badges.OLD);
- }
- return badges;
-};
-
-const scoreOfReason = {
- [Reasons.ASSIGN]: 21,
- [Reasons.AUTHOR]: 11,
- [Reasons.MENTION]: 17,
- [Reasons.TEAM_MENTION]: 11,
- [Reasons.OTHER]: 4,
- [Reasons.REVIEW_REQUESTED]: 29,
- [Reasons.SUBSCRIBED]: 3,
- [Reasons.COMMENT]: 6,
- [Reasons.STATE_CHANGE]: 5,
-};
-
-const decorateWithScore = notification => ({
- ...notification,
- score: scoreOf(notification),
- badges: badgesOf(notification)
-});
-
-class NotificationsPage extends React.Component {
- constructor (props) {
- super(props);
-
- this.notificationSent = false;
- this.isUnreadTab = false;
- }
-
- state = {
- currentTime: moment(),
- error: null,
- notificationSent: false,
- isFirstTimeUser: false,
- isSearching: false,
- query: null,
- activeFilter: Filters.PARTICIPATING,
- activeStatus: Status.QUEUED,
- currentPage: 1
- }
-
- componentDidMount () {
- const isFirstTimeUser = !this.props.storageApi.getUserItem('hasOnboarded');
-
- // Harsh but fair.
- if (window.outerWidth < 1100) {
- navigate(routes.REDESIGN_NOTIFICATIONS);
- return;
- }
-
- if (isFirstTimeUser) {
- this.setState({isFirstTimeUser: true});
- // this.props.storageApi.setUserItem('hasOnboarded', true);
- }
-
- this.props.notificationsApi.fetchNotifications();
-
- this.tabSyncer = setInterval(() => {
- if (!document.hidden && this.isUnreadTab) {
- this.updateTabIcon(false);
- }
- }, 2000);
-
- this.syncer = setInterval(() => {
- this.props.notificationsApi.fetchNotificationsSync()
- .then(error => this.setState({error: null}))
- .catch(error => this.setState({error}));
- this.setState({currentTime: moment()});
- }, 8 * 1000);
- }
-
- shouldComponentUpdate (nextProps, nextState) {
- if (this.props.notificationsApi.newChanges !== nextProps.notificationsApi.newChanges) {
- this.notificationSent = false;
- }
- // The idea here is if we've just updated the prevNotifications state, then
- // we don't want to trigger a rerender.
- return nextState.prevNotifications === this.state.prevNotifications;
- }
-
- componentWillUnmount () {
- clearInterval(this.syncer);
- clearInterval(this.tabSyncer);
- }
-
- onChangePage = page => {
- this.setState({ currentPage: page });
- }
-
- onSetActiveFilter = filter => {
- this.setState({ activeFilter: filter, currentPage: 1 });
- }
-
- onSetActiveStatus = status => {
- this.setState({ activeStatus: status, currentPage: 1 });
- }
-
- onClearQuery = () => {
- this.setState({ query: null });
- }
-
- onLogout = () => {
- // Remove cookie and invalidate token on client.
- this.props.cookiesApi.removeCookie(OAUTH_TOKEN_COOKIE);
- this.props.authApi.invalidateToken();
- }
-
- onSearch = event => {
- const text = event.target.value;
-
- // Ignore empty queries.
- if (text.length <= 0) {
- return;
- }
-
- this.setState({ isSearching: true });
- setTimeout(() => {
- this.setState({
- query: text,
- isSearching: false
- });
- }, 500);
- }
-
- enhancedOnStageThread = (thread_id, repository) => {
- this.props.storageApi.incrStat('stagedCount');
- this.props.storageApi.incrStat(repository + '-stagedCount');
- this.props.notificationsApi.stageThread(thread_id);
- }
-
- enhancedOnMarkAsRead = (thread_id, repository) => {
- this.props.storageApi.incrStat('stagedCount');
- this.props.storageApi.incrStat(repository + '-stagedCount');
- this.props.notificationsApi.markAsRead(thread_id);
- }
-
- restoreThread = thread_id => {
- this.props.notificationsApi.restoreThread(thread_id);
- }
-
- setNotificationsPermission = (...args) => {
- this.props.notificationsApi.setNotificationsPermission(...args);
- }
-
- updateTabIcon (hasUnread = true) {
- this.isUnreadTab = hasUnread;
- var link = document.querySelector("link[rel*='icon']") || document.createElement('link');
- link.rel = 'shortcut icon';
- link.href = hasUnread ? tabDotIcon : tabIcon;
- document.getElementsByTagName('head')[0].appendChild(link);
- }
-
- sendWebNotification = newNotifcations => {
- if (this.notificationSent || newNotifcations.length === 0) {
- return;
- }
-
- // Only show these notifications and title change if the tab is out of focus.
- if (!document.hidden) {
- return;
- }
-
- // Set this even if we don't actually send the notification due to permissions.
- this.notificationSent = true;
- this.updateTabIcon();
-
- // No permission, no notification.
- if (this.props.notificationsApi.notificationsPermission !== 'granted') {
- return;
- }
-
- const n = newNotifcations[0];
- const reasonByline = getMessageFromReasons(n.reasons, n.type);
-
- const additionalInfo = newNotifcations.length > 1
- ? ` (+${newNotifcations.length} more)`
- : '';
-
- const notification = new Notification(n.name + additionalInfo, {
- body: reasonByline,
- icon: n.type === "Issue" ? issueIcon : prIcon,
- badge: n.type === "Issue" ? issueIcon : prIcon,
- requireInteraction: true,
- });
-
- notification.addEventListener('click', () => {
- this.updateTabIcon(false);
- this.enhancedOnStageThread(n.id, n.repository);
- window.open(n.url);
- })
-
- // Manually close for legacy browser support.
- setTimeout(notification.close.bind(notification), 10000);
- }
-
- getFilteredNotifications = () => {
- const {notifications} = this.props.notificationsApi;
-
- let filterMethod = () => true;
- switch (this.state.activeFilter) {
- case Filters.PARTICIPATING:
- filterMethod = n => (
- n.reasons.some(({ reason }) => (
- reason === Reasons.REVIEW_REQUESTED ||
- reason === Reasons.ASSIGN ||
- reason === Reasons.MENTION ||
- reason === Reasons.AUTHOR
- ))
- );
- break;
- case Filters.ASSIGNED:
- filterMethod = n => (
- n.reasons.some(({ reason }) => reason === Reasons.ASSIGN)
- );
- break;
- case Filters.REVIEW_REQUESTED:
- filterMethod = n => (
- n.reasons.some(({ reason }) => reason === Reasons.REVIEW_REQUESTED)
- );
- break;
- case Filters.COMMENT:
- filterMethod = n => (
- n.reasons.some(({ reason }) => reason === Reasons.COMMENT)
- );
- break;
- default:
- filterMethod = () => true;
- }
-
- const filteredNotifications = notifications.filter(filterMethod);
-
- const notificationsQueued = filteredNotifications.filter(n => n.status === Status.QUEUED);
- const notificationsStaged = filteredNotifications.filter(n => n.status === Status.STAGED);
- const notificationsClosed = filteredNotifications.filter(n => n.status === Status.CLOSED);
-
- let notificationsToRender = [];
- switch (this.state.activeStatus) {
- case Status.CLOSED:
- notificationsToRender = notificationsClosed;
- break;
- case Status.STAGED:
- notificationsToRender = notificationsStaged;
- break;
- case Status.QUEUED:
- default:
- notificationsToRender = notificationsQueued;
- }
-
- let scoredAndSortedNotifications = notificationsToRender
- .map(decorateWithScore)
- .sort((a, b) => b.score - a.score);
-
- // We gotta make sure to search notifications before we paginate.
- // Otherwise we'd just end up searching on the current page, which is bad.
- if (this.state.query) {
- scoredAndSortedNotifications = scoredAndSortedNotifications.filter(n => (
- n.name.toLowerCase().indexOf(this.state.query.toLowerCase()) > -1)
- )
- }
-
- if (this.props.notificationsApi.newChanges) {
- const filteredNewChanges = this.props.notificationsApi.newChanges.filter(n => (
- scoredAndSortedNotifications.some(fn => fn.id === n.id)
- ));
- if (filteredNewChanges.length > 0) {
- this.sendWebNotification(filteredNewChanges);
- }
- }
-
- return {
- notifications: scoredAndSortedNotifications,
- queuedCount: notificationsQueued.length,
- stagedCount: notificationsStaged.length,
- closedCount: notificationsClosed.length,
- };
- }
-
- render () {
- if (!this.props.authApi.token) {
- return
- }
-
- const {
- fetchNotifications,
- markAllAsStaged,
- clearCache,
- notificationsPermission,
- loading: isFetchingNotifications,
- error: fetchingNotificationsError,
- } = this.props.notificationsApi;
- const {
- notifications: scoredAndSortedNotifications,
- queuedCount,
- stagedCount,
- closedCount,
- } = this.getFilteredNotifications();
-
- let firstIndex = (this.state.currentPage - 1) * PER_PAGE;
- let lastIndex = (this.state.currentPage * PER_PAGE);
- let notificationsOnPage = scoredAndSortedNotifications.slice(firstIndex, lastIndex);
- let lastPage = Math.ceil(scoredAndSortedNotifications.length / PER_PAGE);
- let firstNumbered = firstIndex + 1;
- let lastNumbered = Math.min(lastIndex, scoredAndSortedNotifications.length);
-
- if (scoredAndSortedNotifications.length === 0) {
- firstIndex = 0;
- lastIndex = 0;
- notificationsOnPage = [];
- lastPage = 1;
- firstNumbered = 0;
- lastNumbered = 0;
- }
-
- const stagedTodayCount = this.props.storageApi.getStat('stagedCount')[0];
- const stagedStatistics = this.props.storageApi.getStat(
- 'stagedCount',
- this.state.currentTime.clone().startOf('week').subtract(1, 'week'),
- this.state.currentTime.clone().endOf('week')
- );
-
- return (
-
- );
- }
-};
-
-const enhance = compose(
- withStorageProvider,
- withAuthProvider,
- withCookiesProvider,
- withNotificationsProvider
-);
-
-export default enhance(NotificationsPage);
diff --git a/src/pages/common/index.js b/src/pages/common/index.js
index 58e3759..82322b4 100644
--- a/src/pages/common/index.js
+++ b/src/pages/common/index.js
@@ -255,7 +255,7 @@ export function BasicPageWrapper ({loggedIn, onLogout, children}) {
{'Guide'}
{'Pricing'}
-