converting some things to choo/component

This commit is contained in:
Danny Coates 2018-11-12 11:13:31 -08:00
parent a576d54d64
commit 037c79730d
No known key found for this signature in database
GPG key ID: 4C442633C62E00CB
16 changed files with 270 additions and 381 deletions

View file

@ -1,5 +1,7 @@
import 'fast-text-encoding'; // MS Edge support
import 'fluent-intl-polyfill';
import choo from 'choo';
import nanotiming from 'nanotiming';
import routes from './routes';
import capabilities from './capabilities';
import locale from '../common/locales';
@ -14,7 +16,10 @@ import './main.css';
import User from './user';
(async function start() {
const app = routes();
const app = routes(choo());
if (process.env.NODE_ENV === 'production') {
nanotiming.disabled = true;
}
if (navigator.doNotTrack !== '1' && window.RAVEN_CONFIG) {
Raven.config(window.SENTRY_ID, window.RAVEN_CONFIG).install();
}

View file

@ -1,37 +1,8 @@
const choo = require('choo');
const html = require('choo/html');
const nanotiming = require('nanotiming');
const download = require('./ui/download');
const footer = require('./ui/footer');
const fxPromo = require('./ui/fxPromo');
const header = require('./ui/header');
const body = require('./ui/body');
nanotiming.disabled = true;
function banner(state, emit) {
if (state.promo && !state.route.startsWith('/unsupported/')) {
return fxPromo(state, emit);
}
}
function body(main) {
return function(state, emit) {
const b = html`<body class="flex flex-col items-center font-sans bg-blue-lightest md:h-screen md:bg-grey-lightest">
${banner(state, emit)}
${header(state, emit)}
${main(state, emit)}
${footer(state)}
</body>`;
if (state.layout) {
// server side only
return state.layout(state, b);
}
return b;
};
}
module.exports = function() {
const app = choo();
module.exports = function(app = choo()) {
app.route('/', body(require('./ui/home')));
app.route('/download/:id', body(download));
app.route('/download/:id/:key', body(download));

View file

@ -1,58 +1,101 @@
const html = require('choo/html');
const Component = require('choo/component');
module.exports = function(state, emit) {
if (!state.capabilities.account) {
return null;
class Account extends Component {
constructor(name, state, emit) {
super(name);
this.state = state;
this.emit = emit;
this.enabled = state.capabilities.account;
this.local = state.components[name] = {};
this.setState();
}
const user = state.user;
if (!user.loggedIn) {
return html`<button
class="p-2 border rounded border-white text-white hover:bg-white hover:text-blue md:text-blue md:border-blue md:hover:text-white md:hover:bg-blue"
onclick=${login}>
${state.translate('signInMenuOption')}
</button>`;
}
return html`<div class="relative h-8">
<input
type="image"
alt="${user.email}"
class="w-8 h-8 rounded-full text-white"
src="${user.avatar}"
onclick=${avatarClick}/>
<ul
id="accountMenu"
class="invisible list-reset absolute pin-t pin-r mt-10 pt-2 pb-2 bg-white shadow-md whitespace-no-wrap outline-none z-50"
onblur="${hideMenu}"
tabindex="-1">
<li class="p-2 text-grey-dark">${user.email}</li>
<li>
<a class="block px-4 py-2 text-grey-darkest hover:bg-blue hover:text-white cursor-pointer" onclick=${logout}>
${state.translate('logOut')}
</a>
</li>
</ul>
</div>`;
function avatarClick(event) {
avatarClick(event) {
event.preventDefault();
const menu = document.getElementById('accountMenu');
menu.classList.toggle('invisible');
menu.focus();
}
function hideMenu(event) {
hideMenu(event) {
event.stopPropagation();
const menu = document.getElementById('accountMenu');
menu.classList.add('invisible');
}
function login(event) {
login(event) {
event.preventDefault();
emit('login');
this.emit('login');
}
function logout(event) {
logout(event) {
event.preventDefault();
emit('logout');
this.emit('logout');
}
};
changed() {
return this.local.loggedIn !== this.state.user.loggedIn;
}
setState() {
const changed = this.changed();
if (changed) {
this.local.loggedIn = this.state.user.loggedIn;
}
return changed;
}
update() {
return this.setState();
}
createElement() {
if (!this.enabled) {
return null;
}
const user = this.state.user;
const translate = this.state.translate;
if (!this.local.loggedIn) {
return html`
<div>
<button
class="p-2 border rounded border-white text-white hover:bg-white hover:text-blue md:text-blue md:border-blue md:hover:text-white md:hover:bg-blue"
onclick="${e => this.login(e)}"
>
${translate('signInMenuOption')}
</button>
</div>
`;
}
return html`
<div class="relative h-8">
<input
type="image"
alt="${user.email}"
class="w-8 h-8 rounded-full text-white"
src="${user.avatar}"
onclick="${e => this.avatarClick(e)}"
/>
<ul
id="accountMenu"
class="invisible list-reset absolute pin-t pin-r mt-10 pt-2 pb-2 bg-white shadow-md whitespace-no-wrap outline-none z-50"
onblur="${e => this.hideMenu(e)}"
tabindex="-1"
>
<li class="p-2 text-grey-dark">${user.email}</li>
<li>
<a
class="block px-4 py-2 text-grey-darkest hover:bg-blue hover:text-white cursor-pointer"
onclick="${e => this.logout(e)}"
>
${translate('logOut')}
</a>
</li>
</ul>
</div>
`;
}
}
module.exports = Account;

28
app/ui/body.js Normal file
View file

@ -0,0 +1,28 @@
const html = require('choo/html');
const Promo = require('./promo');
const Header = require('./header');
const Footer = require('./footer');
function banner(state) {
if (state.promo && !state.route.startsWith('/unsupported/')) {
return state.cache(Promo, 'promo').render();
}
}
module.exports = function body(main) {
return function(state, emit) {
const b = html`
<body
class="flex flex-col items-center font-sans bg-blue-lightest md:h-screen md:bg-grey-lightest"
>
${banner(state, emit)} ${state.cache(Header, 'header').render()}
${main(state, emit)} ${state.cache(Footer, 'footer').render()}
</body>
`;
if (state.layout) {
// server side only
return state.layout(state, b);
}
return b;
};
};

View file

@ -1,52 +1,74 @@
const html = require('choo/html');
const Component = require('choo/component');
const version = require('../../package.json').version;
const { browserName } = require('../utils');
module.exports = function(state) {
const browser = browserName();
const feedbackUrl = `https://qsurvey.mozilla.com/s3/txp-firefox-send?ver=${version}&browser=${browser}`;
const footer = html`<footer class="flex flex-col md:flex-row items-start w-full flex-none self-start p-6 font-medium text-xs text-grey-dark md:items-center justify-between bg-grey-lightest">
<a class="mozilla-logo pb-10 md:pb-0 m-2"
href="https://www.mozilla.org/">
Mozilla
</a>
<ul class="list-reset flex flex-col md:flex-row items-start md:items-center md:justify-end">
<li class="m-2"><a
href="https://www.mozilla.org/about/legal">
${state.translate('footerLinkLegal')}
</a></li>
<li class="m-2"><a
href="/legal">
${state.translate('footerLinkTerms')}
</a></li>
<li class="m-2"><a
href="https://www.mozilla.org/privacy/websites/#cookies">
${state.translate('footerLinkCookies')}
</a></li>
<li class="m-2"><a
href="https://www.mozilla.org/about/legal/report-infringement/">
${state.translate('reportIPInfringement')}
</a></li>
<li class="m-2"><a
href="https://github.com/mozilla/send">GitHub
</a></li>
<li class="m-2"><a
href="https://twitter.com/FxTestPilot">Twitter
</a></li>
<li class="m-2"><a href="${feedbackUrl}"
rel="noreferrer noopener"
class="feedback-link"
alt="Feedback"
target="_blank">
${state.translate('siteFeedback')}
</a></li>
</ul>
</footer>`;
// HACK
// We only want to render this once because we
// toggle the targets of the links with utils/openLinksInNewTab
footer.isSameNode = function(target) {
return target && target.nodeName && target.nodeName === 'FOOTER';
};
return footer;
};
class Footer extends Component {
constructor(name, state) {
super(name);
this.state = state;
}
update() {
return false;
}
createElement() {
const translate = this.state.translate;
const browser = browserName();
const feedbackUrl = `https://qsurvey.mozilla.com/s3/txp-firefox-send?ver=${version}&browser=${browser}`;
return html`
<footer
class="flex flex-col md:flex-row items-start w-full flex-none self-start p-6 font-medium text-xs text-grey-dark md:items-center justify-between bg-grey-lightest"
>
<a
class="mozilla-logo pb-10 md:pb-0 m-2"
href="https://www.mozilla.org/"
>
Mozilla
</a>
<ul
class="list-reset flex flex-col md:flex-row items-start md:items-center md:justify-end"
>
<li class="m-2">
<a href="https://www.mozilla.org/about/legal">
${translate('footerLinkLegal')}
</a>
</li>
<li class="m-2">
<a href="/legal"> ${translate('footerLinkTerms')} </a>
</li>
<li class="m-2">
<a href="https://www.mozilla.org/privacy/websites/#cookies">
${translate('footerLinkCookies')}
</a>
</li>
<li class="m-2">
<a href="https://www.mozilla.org/about/legal/report-infringement/">
${translate('reportIPInfringement')}
</a>
</li>
<li class="m-2">
<a href="https://github.com/mozilla/send">GitHub </a>
</li>
<li class="m-2">
<a href="https://twitter.com/FxTestPilot">Twitter </a>
</li>
<li class="m-2">
<a
href="${feedbackUrl}"
rel="noreferrer noopener"
class="feedback-link"
alt="Feedback"
target="_blank"
>
${translate('siteFeedback')}
</a>
</li>
</ul>
</footer>
`;
}
}
module.exports = Footer;

View file

@ -1,19 +0,0 @@
const html = require('choo/html');
const assets = require('../../common/assets');
module.exports = function() {
return html`
<div class="w-full flex-none flex flex-row items-center content-center justify-center text-sm bg-grey-light leading-tight text-grey-darkest px-4 py-3">
<div class="flex items-center mx-auto">
<img
src="${assets.get('firefox_logo-only.svg')}"
class="w-6"
alt="Firefox"/>
<span class="ml-3">Send is brought to you by the all-new Firefox.
<a
class="text-blue"
href="https://www.mozilla.org/firefox/new/?utm_campaign=send-acquisition&utm_medium=referral&utm_source=send.firefox.com">Download Firefox now </a>
</span>
</div>
</div>`;
};

View file

@ -1,25 +1,34 @@
const html = require('choo/html');
const account = require('./account');
const Component = require('choo/component');
const Account = require('./account');
module.exports = function(state, emit) {
const header = html`
<header class="relative flex-none flex flex-row items-center justify-between bg-blue md:bg-white w-full px-6 h-16 md:shadow z-20">
<a
class="header-logo"
href="/">
<h1 class="text-white md:text-black font-normal">Firefox <b>Send</b></h1>
</a>
${account(state, emit)}
<div class="invisible absolute pin-t pin-l mt-12 w-full flex flex-col items-center pointer-events-none">
<div class="border rounded bg-grey-darkest text-white mt-2 p-2">Your upload has finished.<button class="border border-blue rounded-sm bg-blue text-white inline-block p-1 ml-2">Copy Link</button><button class="text-white inline-block p-1 ml-2"></button></div>
${state.toast ? state.toast() : ''}
</div>
</header>`;
// HACK
// We only want to render this once because we
// toggle the targets of the links with utils/openLinksInNewTab
// header.isSameNode = function(target) {
// return target && target.nodeName && target.nodeName === 'HEADER';
// };
return header;
};
class Header extends Component {
constructor(name, state, emit) {
super(name);
this.state = state;
this.emit = emit;
this.account = state.cache(Account, 'account');
}
update() {
this.account.render();
return false;
}
createElement() {
return html`
<header
class="relative flex-none flex flex-row items-center justify-between bg-blue md:bg-white w-full px-6 h-16 md:shadow z-20"
>
<a class="header-logo" href="/">
<h1 class="text-white md:text-black font-normal">
Firefox <b>Send</b>
</h1>
</a>
${this.account.render()}
</header>
`;
}
}
module.exports = Header;

39
app/ui/promo.js Normal file
View file

@ -0,0 +1,39 @@
const html = require('choo/html');
const Component = require('choo/component');
const assets = require('../../common/assets');
class Promo extends Component {
constructor(name) {
super(name);
}
update() {
return false;
}
createElement() {
return html`
<div
class="w-full flex-none flex flex-row items-center content-center justify-center text-sm bg-grey-light leading-tight text-grey-darkest px-4 py-3"
>
<div class="flex items-center mx-auto">
<img
src="${assets.get('firefox_logo-only.svg')}"
class="w-6"
alt="Firefox"
/>
<span class="ml-3"
>Send is brought to you by the all-new Firefox.
<a
class="text-blue"
href="https://www.mozilla.org/firefox/new/?utm_campaign=send-acquisition&utm_medium=referral&utm_source=send.firefox.com"
>Download Firefox now </a
>
</span>
</div>
</div>
`;
}
}
module.exports = Promo;