From 6c93bfda1de7793e37d690a61935478d705219d2 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Sun, 3 Sep 2017 14:12:37 -0700 Subject: [PATCH 01/15] WIP --- frontend/scenes/Dashboard/Dashboard.js | 4 ++-- frontend/stores/DocumentsStore.js | 25 ++++++++++++++++++------- server/api/middlewares/pagination.js | 5 +++-- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/frontend/scenes/Dashboard/Dashboard.js b/frontend/scenes/Dashboard/Dashboard.js index da95a0f2b..f8adf4b03 100644 --- a/frontend/scenes/Dashboard/Dashboard.js +++ b/frontend/scenes/Dashboard/Dashboard.js @@ -28,8 +28,8 @@ type Props = { props: Props; componentDidMount() { - this.props.documents.fetchAll(); - this.props.documents.fetchRecentlyViewed(); + this.props.documents.fetchRecentlyModified({ limit: 5 }); + this.props.documents.fetchRecentlyViewed({ limit: 5 }); } get showPlaceholder() { diff --git a/frontend/stores/DocumentsStore.js b/frontend/stores/DocumentsStore.js index 3d839a1c9..444a47bbf 100644 --- a/frontend/stores/DocumentsStore.js +++ b/frontend/stores/DocumentsStore.js @@ -38,14 +38,17 @@ class DocumentsStore extends BaseStore { /* Computed */ @computed get recentlyViewed(): Array { - return _.filter(this.data.values(), ({ id }) => - this.recentlyViewedIds.includes(id) + return _.take( + _.filter(this.data.values(), ({ id }) => + this.recentlyViewedIds.includes(id) + ), + 5 ); } @computed get recentlyEdited(): Array { // $FlowIssue - return this.data.values(); + return _.take(this.data.values(), 5); } @computed get starred(): Array { @@ -60,11 +63,14 @@ class DocumentsStore extends BaseStore { /* Actions */ - @action fetchAll = async (request: string = 'list'): Promise<*> => { + @action fetchAll = async ( + request: string = 'list', + options: ?Object + ): Promise<*> => { this.isFetching = true; try { - const res = await client.post(`/documents.${request}`); + const res = await client.post(`/documents.${request}`, options); invariant(res && res.data, 'Document list not available'); const { data } = res; runInAction('DocumentsStore#fetchAll', () => { @@ -81,12 +87,17 @@ class DocumentsStore extends BaseStore { } }; - @action fetchRecentlyViewed = async (): Promise<*> => { - const data = await this.fetchAll('viewed'); + @action fetchRecentlyModified = async (options: ?Object): Promise<*> => { + return this.fetchAll('list', options); + }; + + @action fetchRecentlyViewed = async (options: ?Object): Promise<*> => { + const data = await this.fetchAll('viewed', options); runInAction('DocumentsStore#fetchRecentlyViewed', () => { this.recentlyViewedIds = _.map(data, 'id'); }); + return data; }; @action fetchStarred = async (): Promise<*> => { diff --git a/server/api/middlewares/pagination.js b/server/api/middlewares/pagination.js index 57ebf03a7..d0e94048b 100644 --- a/server/api/middlewares/pagination.js +++ b/server/api/middlewares/pagination.js @@ -10,8 +10,9 @@ export default function pagination(options) { }; let query = ctx.request.query; - let limit = parseInt(query.limit, 10); - let offset = parseInt(query.offset, 10); + let body = ctx.request.body; + let limit = parseInt(query.limit || body.limit, 10); + let offset = parseInt(query.offset || body.offset, 10); limit = isNaN(limit) ? opts.defaultLimit : limit; offset = isNaN(offset) ? 0 : offset; From a3f2ed73655616f5d79895e593fd4d9c4f6be77e Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Sun, 3 Sep 2017 14:20:39 -0700 Subject: [PATCH 02/15] :green_heart: --- frontend/utils/ApiClient.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/utils/ApiClient.js b/frontend/utils/ApiClient.js index 5abf98ef9..aff280e95 100644 --- a/frontend/utils/ApiClient.js +++ b/frontend/utils/ApiClient.js @@ -89,11 +89,11 @@ class ApiClient { }); }; - get = (path: string, data?: Object, options?: Object) => { + get = (path: string, data: ?Object, options?: Object) => { return this.fetch(path, 'GET', data, options); }; - post = (path: string, data?: Object, options?: Object) => { + post = (path: string, data: ?Object, options?: Object) => { return this.fetch(path, 'POST', data, options); }; From bdb7c46874477a177854e8baecd71c3d92348917 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Sun, 3 Sep 2017 15:45:25 -0700 Subject: [PATCH 03/15] Remove UserStore --- frontend/components/Layout/Layout.js | 7 +++--- frontend/index.js | 9 ++++---- frontend/stores/AuthStore.js | 12 ----------- frontend/stores/UserStore.js | 32 ---------------------------- 4 files changed, 7 insertions(+), 53 deletions(-) delete mode 100644 frontend/stores/UserStore.js diff --git a/frontend/components/Layout/Layout.js b/frontend/components/Layout/Layout.js index 9679eb833..284383a2e 100644 --- a/frontend/components/Layout/Layout.js +++ b/frontend/components/Layout/Layout.js @@ -27,7 +27,6 @@ import SidebarCollection from './components/SidebarCollection'; import SidebarCollectionList from './components/SidebarCollectionList'; import SidebarLink from './components/SidebarLink'; -import UserStore from 'stores/UserStore'; import AuthStore from 'stores/AuthStore'; import UiStore from 'stores/UiStore'; import CollectionsStore from 'stores/CollectionsStore'; @@ -40,7 +39,6 @@ type Props = { children?: ?React.Element, actions?: ?React.Element, title?: ?React.Element, - user: UserStore, auth: AuthStore, ui: UiStore, search: ?boolean, @@ -108,7 +106,8 @@ type Props = { }; render() { - const { user, auth, documents, collections, history, ui } = this.props; + const { auth, documents, collections, history, ui } = this.props; + const { user } = auth; return ( @@ -134,7 +133,7 @@ type Props = { Atlas - }> + }> Settings diff --git a/frontend/index.js b/frontend/index.js index d47f3774f..b783b4e76 100644 --- a/frontend/index.js +++ b/frontend/index.js @@ -51,23 +51,22 @@ type AuthProps = { }; const Auth = ({ children }: AuthProps) => { - if (stores.auth.authenticated && stores.auth.team) { + if (stores.auth.authenticated && stores.auth.team && stores.auth.user) { // Only initialize stores once. Kept in global scope // because otherwise they will get overriden on route // change if (!authenticatedStores) { // Stores for authenticated user - const user = stores.auth.getUserStore(); - const cache = new CacheStore(user.user.id); + const { user, team } = stores.auth; + const cache = new CacheStore(user.id); authenticatedStores = { - user, documents: new DocumentsStore({ ui: stores.ui, cache, }), collections: new CollectionsStore({ ui: stores.ui, - teamId: user.team.id, + teamId: team.id, cache, }), }; diff --git a/frontend/stores/AuthStore.js b/frontend/stores/AuthStore.js index dcc879c41..f5b77ecbe 100644 --- a/frontend/stores/AuthStore.js +++ b/frontend/stores/AuthStore.js @@ -2,7 +2,6 @@ import { observable, action, computed, autorunAsync } from 'mobx'; import invariant from 'invariant'; import { client } from 'utils/ApiClient'; -import UserStore from 'stores/UserStore'; import type { User, Team } from 'types'; const AUTH_STORE = 'AUTH_STORE'; @@ -72,17 +71,6 @@ class AuthStore { }; }; - getUserStore(): UserStore { - invariant( - this.user && this.team, - 'Tried to create a user store without data' - ); - return new UserStore({ - user: this.user, - team: this.team, - }); - } - constructor() { // Rehydrate const data = JSON.parse(localStorage.getItem(AUTH_STORE) || '{}'); diff --git a/frontend/stores/UserStore.js b/frontend/stores/UserStore.js deleted file mode 100644 index 7d368c934..000000000 --- a/frontend/stores/UserStore.js +++ /dev/null @@ -1,32 +0,0 @@ -// @flow -import { observable, computed } from 'mobx'; -import type { User, Team } from 'types'; - -type Options = { - user: User, - team: Team, -}; - -class UserStore { - @observable user: User; - @observable team: Team; - - @observable isLoading: boolean = false; - - /* Computed */ - - @computed get asJson(): string { - return JSON.stringify({ - user: this.user, - team: this.team, - }); - } - - constructor(options: Options) { - // Rehydrate - this.user = options.user; - this.team = options.team; - } -} - -export default UserStore; From 432b7afede344baf33ccecaf13d96450927d2ed1 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Sun, 3 Sep 2017 17:08:56 -0700 Subject: [PATCH 04/15] Refactor Slack signin codE --- frontend/components/Layout/Layout.js | 6 ++- server/api/auth.js | 59 +++++----------------------- server/slack.js | 34 ++++++++++++++++ 3 files changed, 48 insertions(+), 51 deletions(-) create mode 100644 server/slack.js diff --git a/frontend/components/Layout/Layout.js b/frontend/components/Layout/Layout.js index 284383a2e..b42b7426a 100644 --- a/frontend/components/Layout/Layout.js +++ b/frontend/components/Layout/Layout.js @@ -107,7 +107,7 @@ type Props = { render() { const { auth, documents, collections, history, ui } = this.props; - const { user } = auth; + const { user, team } = auth; return ( @@ -128,10 +128,12 @@ type Props = { {auth.authenticated && user && + team &&
- Atlas + {team.name} + {user.username} }> diff --git a/server/api/auth.js b/server/api/auth.js index 811055cf5..35ae88c14 100644 --- a/server/api/auth.js +++ b/server/api/auth.js @@ -1,11 +1,9 @@ // @flow import Router from 'koa-router'; -import apiError, { httpErrors } from '../errors'; -import fetch from 'isomorphic-fetch'; -import querystring from 'querystring'; - +import apiError from '../errors'; import { presentUser, presentTeam } from '../presenters'; import { User, Team } from '../models'; +import * as Slack from '../slack'; const router = new Router(); @@ -88,24 +86,7 @@ router.post('auth.slack', async ctx => { const { code } = ctx.body; ctx.assertPresent(code, 'code is required'); - const body = { - client_id: process.env.SLACK_KEY, - client_secret: process.env.SLACK_SECRET, - redirect_uri: `${process.env.URL || ''}/auth/slack`, - code, - }; - - let data; - try { - const response = await fetch( - `https://slack.com/api/oauth.access?${querystring.stringify(body)}` - ); - data = await response.json(); - } catch (e) { - throw httpErrors.BadRequest(); - } - - if (!data.ok) throw httpErrors.BadRequest(data.error); + const data = await Slack.oauthAccess(code); // Temp to block const allowedSlackDomains = (process.env.ALLOWED_SLACK_DOMAINS || '') @@ -118,22 +99,20 @@ router.post('auth.slack', async ctx => { ); } - // User let user = await User.findOne({ where: { slackId: data.user.id } }); - - // Team let team = await Team.findOne({ where: { slackId: data.team.id } }); const teamExisted = !!team; - if (!team) { + + if (team) { + team.name = data.team.name; + team.slackData = data.team; + await team.save(); + } else { team = await Team.create({ name: data.team.name, slackId: data.team.id, slackData: data.team, }); - } else { - team.name = data.team.name; - team.slackData = data.team; - team = await team.save(); } if (user) { @@ -143,7 +122,6 @@ router.post('auth.slack', async ctx => { } else { user = await User.create({ slackId: data.user.id, - username: data.user.name, name: data.user.name, email: data.user.email, teamId: team.id, @@ -169,24 +147,7 @@ router.post('auth.slackCommands', async ctx => { const { code } = ctx.body; ctx.assertPresent(code, 'code is required'); - const body = { - client_id: process.env.SLACK_KEY, - client_secret: process.env.SLACK_SECRET, - redirect_uri: `${process.env.URL || ''}/auth/slack/commands`, - code, - }; - - let data; - try { - const response = await fetch( - `https://slack.com/api/oauth.access?${querystring.stringify(body)}` - ); - data = await response.json(); - } catch (e) { - throw httpErrors.BadRequest(); - } - - if (!data.ok) throw httpErrors.BadRequest(data.error); + await Slack.oauthAccess(code, `${process.env.URL || ''}/auth/slack/commands`); }); export default router; diff --git a/server/slack.js b/server/slack.js new file mode 100644 index 000000000..62bb75eb5 --- /dev/null +++ b/server/slack.js @@ -0,0 +1,34 @@ +// @flow +import fetch from 'isomorphic-fetch'; +import querystring from 'querystring'; +import { httpErrors } from './errors'; + +const SLACK_API_URL = 'https://slack.com/api'; + +export async function request(endpoint: string, body: Object) { + let data; + try { + const response = await fetch( + `${SLACK_API_URL}/${endpoint}?${querystring.stringify(body)}` + ); + data = await response.json(); + } catch (e) { + throw httpErrors.BadRequest(); + } + console.log('DATA', data); + if (!data.ok) throw httpErrors.BadRequest(data.error); + + return data; +} + +export async function oauthAccess( + code: string, + redirect_uri: string = `${process.env.URL || ''}/auth/slack` +) { + return request('oauth.access', { + client_id: process.env.SLACK_KEY, + client_secret: process.env.SLACK_SECRET, + redirect_uri: `${process.env.URL || ''}/auth/slack`, + code, + }); +} From 1b52cb6c19d6acc57c64f990303fabd5d8d56339 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Sun, 3 Sep 2017 17:27:12 -0700 Subject: [PATCH 05/15] Refactor --- frontend/components/Layout/Layout.js | 37 ++++------------ .../Layout/components/HeaderBlock.js | 42 +++++++++++++++++++ 2 files changed, 51 insertions(+), 28 deletions(-) create mode 100644 frontend/components/Layout/components/HeaderBlock.js diff --git a/frontend/components/Layout/Layout.js b/frontend/components/Layout/Layout.js index b42b7426a..87ff7dd91 100644 --- a/frontend/components/Layout/Layout.js +++ b/frontend/components/Layout/Layout.js @@ -10,11 +10,11 @@ import keydown from 'react-keydown'; import Flex from 'components/Flex'; import { color, layout } from 'styles/constants'; import { documentEditUrl, homeUrl, searchUrl } from 'utils/routeHelpers'; - import { DropdownMenu, DropdownMenuItem } from 'components/DropdownMenu'; + +import Avatar from 'components/Avatar'; import { LoadingIndicatorBar } from 'components/LoadingIndicator'; import Scrollable from 'components/Scrollable'; -import Avatar from 'components/Avatar'; import Modal from 'components/Modal'; import AddIcon from 'components/Icon/AddIcon'; import MoreIcon from 'components/Icon/MoreIcon'; @@ -26,6 +26,7 @@ import Settings from 'scenes/Settings'; import SidebarCollection from './components/SidebarCollection'; import SidebarCollectionList from './components/SidebarCollectionList'; import SidebarLink from './components/SidebarLink'; +import HeaderBlock from './components/HeaderBlock'; import AuthStore from 'stores/AuthStore'; import UiStore from 'stores/UiStore'; @@ -130,11 +131,7 @@ type Props = { user && team && -
- - {team.name} - {user.username} - + }> Settings @@ -149,8 +146,7 @@ type Props = { Logout -
- + @@ -251,19 +247,6 @@ const Container = styled(Flex)` height: 100%; `; -const LogoLink = styled(Link)` - margin-top: 15px; - font-family: 'Atlas Grotesk'; - font-weight: bold; - color: ${color.text}; - text-decoration: none; - font-size: 16px; -`; - -const MenuLink = styled(Link)` - color: ${color.text}; -`; - const Content = styled(Flex)` overflow: scroll; position: absolute; @@ -274,6 +257,10 @@ const Content = styled(Flex)` transition: left 200ms ease-in-out; `; +const MenuLink = styled(Link)` + color: ${color.text}; +`; + const Sidebar = styled(Flex)` width: ${layout.sidebarWidth}; margin-left: ${props => (props.editMode ? `-${layout.sidebarWidth}` : 0)}; @@ -282,12 +269,6 @@ const Sidebar = styled(Flex)` transition: margin-left 200ms ease-in-out; `; -const Header = styled(Flex)` - flex-shrink: 0; - padding: ${layout.padding}; - padding-bottom: 10px; -`; - const LinkSection = styled(Flex)` flex-direction: column; padding: 10px 0; diff --git a/frontend/components/Layout/components/HeaderBlock.js b/frontend/components/Layout/components/HeaderBlock.js new file mode 100644 index 000000000..87aab5831 --- /dev/null +++ b/frontend/components/Layout/components/HeaderBlock.js @@ -0,0 +1,42 @@ +// @flow +import React from 'react'; +import styled from 'styled-components'; +import { Link } from 'react-router-dom'; +import { color, layout } from 'styles/constants'; +import type { User, Team } from 'types'; +import Flex from 'components/Flex'; + +type Props = { + user: User, + team: Team, + children?: React$Element, +}; + +function HeaderBlock({ user, team, children }: Props) { + return ( +
+ + {team.name} +

{user.username}

+
+ {children} +
+ ); +} + +const LogoLink = styled(Link)` + margin-top: 15px; + font-family: 'Atlas Grotesk'; + font-weight: bold; + color: ${color.text}; + text-decoration: none; + font-size: 16px; +`; + +const Header = styled(Flex)` + flex-shrink: 0; + padding: ${layout.padding}; + padding-bottom: 10px; +`; + +export default HeaderBlock; From c2c7f48d85ad40746ec1bac2a04d9a90bc1933a0 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Sun, 3 Sep 2017 23:03:49 -0700 Subject: [PATCH 06/15] Neaten --- .../components/DropdownMenu/DropdownMenu.js | 5 +- frontend/components/Layout/Layout.js | 49 ++++++++++--------- .../Layout/components/HeaderBlock.js | 29 +++++++++-- 3 files changed, 52 insertions(+), 31 deletions(-) diff --git a/frontend/components/DropdownMenu/DropdownMenu.js b/frontend/components/DropdownMenu/DropdownMenu.js index 36c560041..69874c0ad 100644 --- a/frontend/components/DropdownMenu/DropdownMenu.js +++ b/frontend/components/DropdownMenu/DropdownMenu.js @@ -22,6 +22,7 @@ const DropdownMenuItem = ({ onClick, children }: MenuItemProps) => { type DropdownMenuProps = { label: React.Element, children?: React.Element, + style?: Object, }; @observer class DropdownMenu extends React.Component { @@ -42,7 +43,7 @@ type DropdownMenuProps = { {this.menuOpen && - + {this.props.children} } @@ -65,9 +66,7 @@ const Label = styled(Flex).attrs({ })` cursor: pointer; z-index: 1000; - min-height: 43px; - margin: 0 5px; `; const MenuContainer = styled.div` diff --git a/frontend/components/Layout/Layout.js b/frontend/components/Layout/Layout.js index 87ff7dd91..a3d2d5093 100644 --- a/frontend/components/Layout/Layout.js +++ b/frontend/components/Layout/Layout.js @@ -131,29 +131,33 @@ type Props = { user && team && - - }> - - Settings - - - Keyboard shortcuts - - - API - - - Logout - - - + + + + } + > + + Settings + + + Keyboard shortcuts + + + API + + + Logout + + + - - Search - Home + Search Starred @@ -225,7 +229,7 @@ type Props = { const CollectionAction = styled.a` position: absolute; - top: 8px; + top: -2px; right: ${layout.hpadding}; svg { @@ -264,14 +268,13 @@ const MenuLink = styled(Link)` const Sidebar = styled(Flex)` width: ${layout.sidebarWidth}; margin-left: ${props => (props.editMode ? `-${layout.sidebarWidth}` : 0)}; - background: rgba(250, 251, 252, 0.71); - border-right: 1px solid #eceff3; + background: ${color.smoke}; transition: margin-left 200ms ease-in-out; `; const LinkSection = styled(Flex)` flex-direction: column; - padding: 10px 0; + margin: 24px 0; position: relative; `; diff --git a/frontend/components/Layout/components/HeaderBlock.js b/frontend/components/Layout/components/HeaderBlock.js index 87aab5831..cacecf10f 100644 --- a/frontend/components/Layout/components/HeaderBlock.js +++ b/frontend/components/Layout/components/HeaderBlock.js @@ -14,18 +14,21 @@ type Props = { function HeaderBlock({ user, team, children }: Props) { return ( -
- +
+ {team.name} -

{user.username}

+ {user.name}
{children}
); } +const Name = styled.div` + font-size: 13px; +`; + const LogoLink = styled(Link)` - margin-top: 15px; font-family: 'Atlas Grotesk'; font-weight: bold; color: ${color.text}; @@ -36,7 +39,23 @@ const LogoLink = styled(Link)` const Header = styled(Flex)` flex-shrink: 0; padding: ${layout.padding}; - padding-bottom: 10px; + position: relative; + cursor: pointer; + width: 100%; + + &:hover { + background: rgba(0,0,0,.05); + } + + &::after { + content: ""; + left: ${layout.hpadding}; + right: ${layout.hpadding}; + background: rgba(0,0,0,.075); + height: 1px; + position: absolute; + bottom: 0; + } `; export default HeaderBlock; From f4735246ade626281a38923c9237819b92b7a491 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Mon, 4 Sep 2017 08:32:31 -0700 Subject: [PATCH 07/15] Readability --- frontend/components/Editor/Editor.scss | 2 +- frontend/components/Layout/components/HeaderBlock.js | 10 +++++----- .../Layout/components/SidebarLink/SidebarLink.js | 1 + frontend/styles/base.scss | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/frontend/components/Editor/Editor.scss b/frontend/components/Editor/Editor.scss index a7694603d..ecc91bb28 100644 --- a/frontend/components/Editor/Editor.scss +++ b/frontend/components/Editor/Editor.scss @@ -1,7 +1,7 @@ .editor { font-weight: 400; font-size: 1em; - line-height: 1.5em; + line-height: 1.7em; width: 100%; color: #1b2631; diff --git a/frontend/components/Layout/components/HeaderBlock.js b/frontend/components/Layout/components/HeaderBlock.js index cacecf10f..8bf4fd57d 100644 --- a/frontend/components/Layout/components/HeaderBlock.js +++ b/frontend/components/Layout/components/HeaderBlock.js @@ -1,7 +1,6 @@ // @flow import React from 'react'; import styled from 'styled-components'; -import { Link } from 'react-router-dom'; import { color, layout } from 'styles/constants'; import type { User, Team } from 'types'; import Flex from 'components/Flex'; @@ -16,19 +15,19 @@ function HeaderBlock({ user, team, children }: Props) { return (
- {team.name} - {user.name} + {team.name} + {user.name} {children}
); } -const Name = styled.div` +const UserName = styled.div` font-size: 13px; `; -const LogoLink = styled(Link)` +const TeamName = styled.div` font-family: 'Atlas Grotesk'; font-weight: bold; color: ${color.text}; @@ -43,6 +42,7 @@ const Header = styled(Flex)` cursor: pointer; width: 100%; + &:active, &:hover { background: rgba(0,0,0,.05); } diff --git a/frontend/components/Layout/components/SidebarLink/SidebarLink.js b/frontend/components/Layout/components/SidebarLink/SidebarLink.js index 7df81e86c..d09f85c3f 100644 --- a/frontend/components/Layout/components/SidebarLink/SidebarLink.js +++ b/frontend/components/Layout/components/SidebarLink/SidebarLink.js @@ -17,6 +17,7 @@ const StyledNavLink = styled(NavLink)` display: block; padding: 5px ${layout.hpadding}; color: ${color.slateDark}; + font-size: 15px; &:hover { color: ${darken(0.1, color.slateDark)}; diff --git a/frontend/styles/base.scss b/frontend/styles/base.scss index 3fcc4acd2..66deb1946 100644 --- a/frontend/styles/base.scss +++ b/frontend/styles/base.scss @@ -21,7 +21,7 @@ html, body, .viewport { body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; - font-size: 15px; + font-size: 16px; line-height: 1.5; margin: 0; color: #617180; From 24686aac44dbd11d9a0bcc0bc87c24855cd4a101 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Mon, 4 Sep 2017 08:56:07 -0700 Subject: [PATCH 08/15] Fixes: Scroll to top behavior when changing pages Fixes: Different max-width on docs and other content --- .../CenteredContent/CenteredContent.js | 2 +- frontend/components/Editor/Editor.scss | 2 +- frontend/components/Layout/Layout.js | 16 +++++++--------- frontend/styles/base.scss | 5 ----- 4 files changed, 9 insertions(+), 16 deletions(-) diff --git a/frontend/components/CenteredContent/CenteredContent.js b/frontend/components/CenteredContent/CenteredContent.js index cfc4fe08b..b9f15975a 100644 --- a/frontend/components/CenteredContent/CenteredContent.js +++ b/frontend/components/CenteredContent/CenteredContent.js @@ -12,7 +12,7 @@ const Container = styled.div` `; const Content = styled.div` - max-width: 740px; + max-width: 50em; margin: 0 auto; `; diff --git a/frontend/components/Editor/Editor.scss b/frontend/components/Editor/Editor.scss index ecc91bb28..7508c6021 100644 --- a/frontend/components/Editor/Editor.scss +++ b/frontend/components/Editor/Editor.scss @@ -3,7 +3,7 @@ font-size: 1em; line-height: 1.7em; width: 100%; - color: #1b2631; + color: #1b2830; h1, h2, diff --git a/frontend/components/Layout/Layout.js b/frontend/components/Layout/Layout.js index a3d2d5093..c0a6121ee 100644 --- a/frontend/components/Layout/Layout.js +++ b/frontend/components/Layout/Layout.js @@ -252,13 +252,8 @@ const Container = styled(Flex)` `; const Content = styled(Flex)` - overflow: scroll; - position: absolute; - top: 0; - bottom: 0; - right: 0; - left: ${props => (props.editMode ? 0 : layout.sidebarWidth)}; - transition: left 200ms ease-in-out; + margin-left: ${props => (props.editMode ? 0 : layout.sidebarWidth)}; + transition: margin-left 200ms ease-in-out; `; const MenuLink = styled(Link)` @@ -266,10 +261,13 @@ const MenuLink = styled(Link)` `; const Sidebar = styled(Flex)` + position: fixed; + top: 0; + bottom: 0; + left: ${props => (props.editMode ? `-${layout.sidebarWidth}` : 0)}; width: ${layout.sidebarWidth}; - margin-left: ${props => (props.editMode ? `-${layout.sidebarWidth}` : 0)}; background: ${color.smoke}; - transition: margin-left 200ms ease-in-out; + transition: left 200ms ease-in-out; `; const LinkSection = styled(Flex)` diff --git a/frontend/styles/base.scss b/frontend/styles/base.scss index 66deb1946..cd822c1dc 100644 --- a/frontend/styles/base.scss +++ b/frontend/styles/base.scss @@ -27,11 +27,6 @@ body { color: #617180; background-color: #fff; display: flex; - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; -moz-osx-font-smoothing: grayscale; -webkit-font-smoothing: antialiased; From 3c9f69d4950aeeefb72481359a4954be577447d5 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Mon, 4 Sep 2017 12:14:18 -0700 Subject: [PATCH 09/15] Feather icons --- .../DocumentPreview/DocumentPreview.js | 15 ++++---- frontend/components/Layout/Layout.js | 37 +++++++++++-------- .../SidebarCollection/SidebarCollection.js | 4 +- .../SidebarCollectionList.js | 4 +- package.json | 1 + yarn.lock | 4 ++ 6 files changed, 37 insertions(+), 28 deletions(-) diff --git a/frontend/components/DocumentPreview/DocumentPreview.js b/frontend/components/DocumentPreview/DocumentPreview.js index 91d8bff18..ee33b6464 100644 --- a/frontend/components/DocumentPreview/DocumentPreview.js +++ b/frontend/components/DocumentPreview/DocumentPreview.js @@ -2,11 +2,11 @@ import React, { Component } from 'react'; import { observer } from 'mobx-react'; import { Link } from 'react-router-dom'; +import { Star as StarIcon } from 'react-feather'; import Document from 'models/Document'; import styled from 'styled-components'; import { color } from 'styles/constants'; import PublishingInfo from './components/PublishingInfo'; -import StarIcon from 'components/Icon/StarIcon'; type Props = { document: Document, @@ -21,11 +21,6 @@ const StyledStar = styled(StarIcon)` margin-left: 4px; opacity: ${props => (props.solid ? '1 !important' : 0)}; transition: opacity 100ms ease-in-out; - - svg { - width: 1em; - height: 1em; - } `; const DocumentLink = styled(Link)` @@ -87,8 +82,12 @@ const DocumentLink = styled(Link)`

{document.title} {document.starred - ? - : } + ? + + + : + + }

- Home - Search - Starred + + Home + + + Search + + + Starred + {collections.active ? - + : - + } {collections.active ? Date: Mon, 4 Sep 2017 12:26:00 -0700 Subject: [PATCH 10/15] Quick fixes from last PR --- frontend/components/Layout/components/HeaderBlock.js | 2 +- frontend/styles/base.scss | 1 + server/static/dev.html | 4 ++-- server/static/index.html | 4 ++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/frontend/components/Layout/components/HeaderBlock.js b/frontend/components/Layout/components/HeaderBlock.js index 8bf4fd57d..1038738e4 100644 --- a/frontend/components/Layout/components/HeaderBlock.js +++ b/frontend/components/Layout/components/HeaderBlock.js @@ -14,7 +14,7 @@ type Props = { function HeaderBlock({ user, team, children }: Props) { return (
- + {team.name} {user.name} diff --git a/frontend/styles/base.scss b/frontend/styles/base.scss index cd822c1dc..1e745df7f 100644 --- a/frontend/styles/base.scss +++ b/frontend/styles/base.scss @@ -16,6 +16,7 @@ html, body, .viewport { width: 100%; + min-height: 100vh; margin: 0; } diff --git a/server/static/dev.html b/server/static/dev.html index 1933c80b3..8eea6eee8 100644 --- a/server/static/dev.html +++ b/server/static/dev.html @@ -20,7 +20,7 @@ #root { flex: 1; - height: 100%; + min-height: 100vh; } @@ -30,4 +30,4 @@ - \ No newline at end of file + diff --git a/server/static/index.html b/server/static/index.html index 90df71b66..e79463d5b 100644 --- a/server/static/index.html +++ b/server/static/index.html @@ -18,7 +18,7 @@ #root { flex: 1; - height: 100%; + min-height: 100vh; } @@ -28,4 +28,4 @@ - \ No newline at end of file + From 3c378daa19f833e4a76a06f4b0223e9b8e260339 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Mon, 4 Sep 2017 13:23:20 -0700 Subject: [PATCH 11/15] Remove unused icons --- .../DocumentPreview/DocumentPreview.js | 15 ++++--- .../components/MoreIcon/MoreIcon.js | 16 ------- .../components/MoreIcon/MoreIcon.scss | 4 -- .../components/MoreIcon/assets/more.svg | 1 - .../DropdownMenu/components/MoreIcon/index.js | 3 -- frontend/components/DropdownMenu/index.js | 4 +- .../Toolbar/components/LinkToolbar.js | 4 +- frontend/components/Icon/AddIcon.js | 21 --------- frontend/components/Icon/CheckIcon.js | 21 --------- frontend/components/Icon/CloseIcon.js | 21 --------- frontend/components/Icon/Icon.js | 32 ++++++++++++-- frontend/components/Icon/Icon.scss | 9 ---- frontend/components/Icon/MoreIcon.js | 21 --------- frontend/components/Icon/QuoteIcon.js | 21 --------- frontend/components/Icon/StarIcon.js | 43 ------------------- frontend/components/Layout/Layout.js | 20 +++------ frontend/components/Modal/Modal.js | 7 +-- frontend/scenes/Document/components/Menu.js | 9 ++-- .../components/SearchField/SearchField.js | 29 ++++++------- 19 files changed, 68 insertions(+), 233 deletions(-) delete mode 100644 frontend/components/DropdownMenu/components/MoreIcon/MoreIcon.js delete mode 100644 frontend/components/DropdownMenu/components/MoreIcon/MoreIcon.scss delete mode 100644 frontend/components/DropdownMenu/components/MoreIcon/assets/more.svg delete mode 100644 frontend/components/DropdownMenu/components/MoreIcon/index.js delete mode 100644 frontend/components/Icon/AddIcon.js delete mode 100644 frontend/components/Icon/CheckIcon.js delete mode 100644 frontend/components/Icon/CloseIcon.js delete mode 100644 frontend/components/Icon/Icon.scss delete mode 100644 frontend/components/Icon/MoreIcon.js delete mode 100644 frontend/components/Icon/QuoteIcon.js delete mode 100644 frontend/components/Icon/StarIcon.js diff --git a/frontend/components/DocumentPreview/DocumentPreview.js b/frontend/components/DocumentPreview/DocumentPreview.js index ee33b6464..f82bb1424 100644 --- a/frontend/components/DocumentPreview/DocumentPreview.js +++ b/frontend/components/DocumentPreview/DocumentPreview.js @@ -2,10 +2,10 @@ import React, { Component } from 'react'; import { observer } from 'mobx-react'; import { Link } from 'react-router-dom'; -import { Star as StarIcon } from 'react-feather'; import Document from 'models/Document'; import styled from 'styled-components'; import { color } from 'styles/constants'; +import Icon from 'components/Icon'; import PublishingInfo from './components/PublishingInfo'; type Props = { @@ -15,9 +15,10 @@ type Props = { innerRef?: Function, }; -const StyledStar = styled(StarIcon)` - top: 2px; - position: relative; +const StyledStar = styled(Icon).attrs({ + type: 'Star', + color: color.text, +})` margin-left: 4px; opacity: ${props => (props.solid ? '1 !important' : 0)}; transition: opacity 100ms ease-in-out; @@ -41,7 +42,7 @@ const DocumentLink = styled(Link)` outline: none; ${StyledStar} { - opacity: .25; + opacity: .5; &:hover { opacity: 1; @@ -83,10 +84,10 @@ const DocumentLink = styled(Link)` {document.title} {document.starred ? - + : - + } { - return ( - More - ); -}; - -export default MoreIcon; diff --git a/frontend/components/DropdownMenu/components/MoreIcon/MoreIcon.scss b/frontend/components/DropdownMenu/components/MoreIcon/MoreIcon.scss deleted file mode 100644 index 328840769..000000000 --- a/frontend/components/DropdownMenu/components/MoreIcon/MoreIcon.scss +++ /dev/null @@ -1,4 +0,0 @@ -.icon { - width: 21px; - margin-top: 6px; -} diff --git a/frontend/components/DropdownMenu/components/MoreIcon/assets/more.svg b/frontend/components/DropdownMenu/components/MoreIcon/assets/more.svg deleted file mode 100644 index f6e12e971..000000000 --- a/frontend/components/DropdownMenu/components/MoreIcon/assets/more.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/frontend/components/DropdownMenu/components/MoreIcon/index.js b/frontend/components/DropdownMenu/components/MoreIcon/index.js deleted file mode 100644 index a4d1358e6..000000000 --- a/frontend/components/DropdownMenu/components/MoreIcon/index.js +++ /dev/null @@ -1,3 +0,0 @@ -// @flow -import MoreIcon from './MoreIcon'; -export default MoreIcon; diff --git a/frontend/components/DropdownMenu/index.js b/frontend/components/DropdownMenu/index.js index fd1562125..11e84f9cb 100644 --- a/frontend/components/DropdownMenu/index.js +++ b/frontend/components/DropdownMenu/index.js @@ -1,4 +1,2 @@ // @flow -import { DropdownMenu, DropdownMenuItem } from './DropdownMenu'; -import MoreIcon from './components/MoreIcon'; -export { DropdownMenu, DropdownMenuItem, MoreIcon }; +export { DropdownMenu, DropdownMenuItem } from './DropdownMenu'; diff --git a/frontend/components/Editor/components/Toolbar/components/LinkToolbar.js b/frontend/components/Editor/components/Toolbar/components/LinkToolbar.js index c02f727fe..badee913d 100644 --- a/frontend/components/Editor/components/Toolbar/components/LinkToolbar.js +++ b/frontend/components/Editor/components/Toolbar/components/LinkToolbar.js @@ -3,7 +3,7 @@ import React, { Component } from 'react'; import type { State } from '../../../types'; import keydown from 'react-keydown'; import styles from '../Toolbar.scss'; -import CloseIcon from 'components/Icon/CloseIcon'; +import Icon from 'components/Icon'; @keydown export default class LinkToolbar extends Component { @@ -58,7 +58,7 @@ export default class LinkToolbar extends Component { autoFocus /> ); diff --git a/frontend/components/Icon/AddIcon.js b/frontend/components/Icon/AddIcon.js deleted file mode 100644 index 688202cfc..000000000 --- a/frontend/components/Icon/AddIcon.js +++ /dev/null @@ -1,21 +0,0 @@ -// @flow -import React from 'react'; -import Icon from './Icon'; -import type { Props } from './Icon'; - -export default function AddIcon(props: Props) { - return ( - - - - - - - ); -} diff --git a/frontend/components/Icon/CheckIcon.js b/frontend/components/Icon/CheckIcon.js deleted file mode 100644 index ab6ea35e3..000000000 --- a/frontend/components/Icon/CheckIcon.js +++ /dev/null @@ -1,21 +0,0 @@ -// @flow -import React from 'react'; -import Icon from './Icon'; -import type { Props } from './Icon'; - -export default function CheckIcon(props: Props) { - return ( - - - - - - - ); -} diff --git a/frontend/components/Icon/CloseIcon.js b/frontend/components/Icon/CloseIcon.js deleted file mode 100644 index c93cc6bd3..000000000 --- a/frontend/components/Icon/CloseIcon.js +++ /dev/null @@ -1,21 +0,0 @@ -// @flow -import React from 'react'; -import Icon from './Icon'; -import type { Props } from './Icon'; - -export default function CloseIcon(props: Props) { - return ( - - - - - - - ); -} diff --git a/frontend/components/Icon/Icon.js b/frontend/components/Icon/Icon.js index 11e26a2d3..44811b1ec 100644 --- a/frontend/components/Icon/Icon.js +++ b/frontend/components/Icon/Icon.js @@ -1,9 +1,11 @@ // @flow import React from 'react'; import styled from 'styled-components'; +import * as Icons from 'react-feather'; export type Props = { className?: string, + type?: string, light?: boolean, }; @@ -11,16 +13,40 @@ type BaseProps = { children?: React$Element, }; -export default function Icon({ children, ...rest }: Props & BaseProps) { +export default function Icon({ + children, + light, + type, + ...rest +}: Props & BaseProps) { + if (type) { + children = React.createElement(Icons[type], { + size: '1em', + color: light ? '#FFFFFF' : undefined, + ...rest, + }); + + return ( + + {children} + + ); + } + return ( - + {children} ); } +const FeatherWrapper = styled.span` + position: relative; + top: .1em; +`; + const Wrapper = styled.span` svg { - fill: ${props => (props.light ? '#fff' : '#000')}; + fill: ${props => (props.light ? '#FFF' : '#000')} } `; diff --git a/frontend/components/Icon/Icon.scss b/frontend/components/Icon/Icon.scss deleted file mode 100644 index 7fd441749..000000000 --- a/frontend/components/Icon/Icon.scss +++ /dev/null @@ -1,9 +0,0 @@ -.icon { - -} - -.light { - svg { - fill: #fff; - } -} diff --git a/frontend/components/Icon/MoreIcon.js b/frontend/components/Icon/MoreIcon.js deleted file mode 100644 index 5e8126ff0..000000000 --- a/frontend/components/Icon/MoreIcon.js +++ /dev/null @@ -1,21 +0,0 @@ -// @flow -import React from 'react'; -import Icon from './Icon'; -import type { Props } from './Icon'; - -export default function MoreIcon(props: Props) { - return ( - - - - - - - ); -} diff --git a/frontend/components/Icon/QuoteIcon.js b/frontend/components/Icon/QuoteIcon.js deleted file mode 100644 index 6b80497a6..000000000 --- a/frontend/components/Icon/QuoteIcon.js +++ /dev/null @@ -1,21 +0,0 @@ -// @flow -import React from 'react'; -import Icon from './Icon'; -import type { Props } from './Icon'; - -export default function QuoteIcon(props: Props) { - return ( - - - - - - - ); -} diff --git a/frontend/components/Icon/StarIcon.js b/frontend/components/Icon/StarIcon.js deleted file mode 100644 index 9939785e9..000000000 --- a/frontend/components/Icon/StarIcon.js +++ /dev/null @@ -1,43 +0,0 @@ -// @flow -import React from 'react'; -import Icon from './Icon'; -import type { Props } from './Icon'; - -export default function StarIcon(props: Props & { solid?: boolean }) { - let icon; - - if (props.solid) { - icon = ( - - - - - - ); - } else { - icon = ( - - - - - ); - } - - return ( - - {icon} - - ); -} diff --git a/frontend/components/Layout/Layout.js b/frontend/components/Layout/Layout.js index db4e73c23..485926455 100644 --- a/frontend/components/Layout/Layout.js +++ b/frontend/components/Layout/Layout.js @@ -16,13 +16,7 @@ import Avatar from 'components/Avatar'; import { LoadingIndicatorBar } from 'components/LoadingIndicator'; import Scrollable from 'components/Scrollable'; import Modal from 'components/Modal'; -import { - Home as HomeIcon, - Search as SearchIcon, - Star as StarIcon, - PlusCircle as AddIcon, - MoreHorizontal as MoreIcon, -} from 'react-feather'; +import Icon from 'components/Icon'; import CollectionNew from 'scenes/CollectionNew'; import CollectionEdit from 'scenes/CollectionEdit'; import KeyboardShortcuts from 'scenes/KeyboardShortcuts'; @@ -162,22 +156,22 @@ type Props = { - Home + Home - Search + Search - Starred + Starred {collections.active ? - + : - + } {collections.active ? {title &&

{title}

} - + {children}
@@ -68,6 +68,7 @@ const Close = styled.a` top: 3rem; right: 3rem; opacity: .5; + color: ${color.text}; &:hover { opacity: 1; diff --git a/frontend/scenes/Document/components/Menu.js b/frontend/scenes/Document/components/Menu.js index ae315d82c..9bae6f0b8 100644 --- a/frontend/scenes/Document/components/Menu.js +++ b/frontend/scenes/Document/components/Menu.js @@ -5,11 +5,8 @@ import get from 'lodash/get'; import { withRouter } from 'react-router-dom'; import { observer } from 'mobx-react'; import Document from 'models/Document'; -import { - DropdownMenu, - DropdownMenuItem, - MoreIcon, -} from 'components/DropdownMenu'; +import Icon from 'components/Icon'; +import { DropdownMenu, DropdownMenuItem } from 'components/DropdownMenu'; type Props = { history: Object, @@ -65,7 +62,7 @@ type Props = { collection.documents.length > 1; return ( - }> + }> {collection &&
diff --git a/frontend/scenes/Search/components/SearchField/SearchField.js b/frontend/scenes/Search/components/SearchField/SearchField.js index 785a3a49f..6b2f6577d 100644 --- a/frontend/scenes/Search/components/SearchField/SearchField.js +++ b/frontend/scenes/Search/components/SearchField/SearchField.js @@ -1,8 +1,9 @@ // @flow import React, { Component } from 'react'; +import Icon from 'components/Icon'; import Flex from 'components/Flex'; +import { color } from 'styles/constants'; import styled from 'styled-components'; -import searchImg from 'assets/icons/search.svg'; const Field = styled.input` width: 100%; @@ -12,17 +13,10 @@ const Field = styled.input` outline: none; border: 0; - ::-webkit-input-placeholder { color: #ccc; } - :-moz-placeholder { color: #ccc; } - ::-moz-placeholder { color: #ccc; } - :-ms-input-placeholder { color: #ccc; } -`; - -const Icon = styled.img` - width: 38px; - margin-bottom: -5px; - margin-right: 10px; - opacity: 0.15; + ::-webkit-input-placeholder { color: ${color.slate}; } + :-moz-placeholder { color: ${color.slate}; } + ::-moz-placeholder { color: ${color.slate}; } + :-ms-input-placeholder { color: ${color.slate}; } `; class SearchField extends Component { @@ -45,13 +39,18 @@ class SearchField extends Component { render() { return ( - - + + From 7e82fd944e705ecf635a5cfc00ba13475ec215c3 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Mon, 4 Sep 2017 13:27:29 -0700 Subject: [PATCH 12/15] allow-null-username --- .../20170904202454-allow-null-username.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 server/migrations/20170904202454-allow-null-username.js diff --git a/server/migrations/20170904202454-allow-null-username.js b/server/migrations/20170904202454-allow-null-username.js new file mode 100644 index 000000000..399dc4e8c --- /dev/null +++ b/server/migrations/20170904202454-allow-null-username.js @@ -0,0 +1,15 @@ +module.exports = { + up: async function(queryInterface, Sequelize) { + await queryInterface.changeColumn('users', 'username', { + type: Sequelize.STRING, + allowNull: true, + }); + }, + + down: async function(queryInterface, Sequelize) { + await queryInterface.changeColumn('users', 'username', { + type: Sequelize.STRING, + allowNull: false, + }); + }, +}; From e72d33e4ece30e3a442fca5b0e5819cd23a5dc13 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Mon, 4 Sep 2017 14:23:08 -0700 Subject: [PATCH 13/15] Cleanup, document menu --- .../components/Collaborators/Collaborators.js | 1 - .../components/HeaderAction/HeaderAction.js | 16 -------- .../components/HeaderAction/HeaderAction.scss | 11 ------ .../Layout/components/HeaderAction/index.js | 3 -- frontend/components/Layout/index.js | 3 +- frontend/scenes/Document/Document.js | 38 +++++++++++++++---- 6 files changed, 31 insertions(+), 41 deletions(-) delete mode 100644 frontend/components/Layout/components/HeaderAction/HeaderAction.js delete mode 100644 frontend/components/Layout/components/HeaderAction/HeaderAction.scss delete mode 100644 frontend/components/Layout/components/HeaderAction/index.js diff --git a/frontend/components/Collaborators/Collaborators.js b/frontend/components/Collaborators/Collaborators.js index 487921fdd..ae62fd1b4 100644 --- a/frontend/components/Collaborators/Collaborators.js +++ b/frontend/components/Collaborators/Collaborators.js @@ -36,7 +36,6 @@ const Collaborators = function({ document }: { document: Document }) { const Avatars = styled(Flex)` flex-direction: row-reverse; - margin-right: 10px; height: 26px; `; diff --git a/frontend/components/Layout/components/HeaderAction/HeaderAction.js b/frontend/components/Layout/components/HeaderAction/HeaderAction.js deleted file mode 100644 index c49806c4a..000000000 --- a/frontend/components/Layout/components/HeaderAction/HeaderAction.js +++ /dev/null @@ -1,16 +0,0 @@ -// @flow -import React from 'react'; - -import styles from './HeaderAction.scss'; - -type Props = { onClick?: ?Function, children?: ?React.Element }; - -const HeaderAction = (props: Props) => { - return ( -
- {props.children} -
- ); -}; - -export default HeaderAction; diff --git a/frontend/components/Layout/components/HeaderAction/HeaderAction.scss b/frontend/components/Layout/components/HeaderAction/HeaderAction.scss deleted file mode 100644 index cc5013907..000000000 --- a/frontend/components/Layout/components/HeaderAction/HeaderAction.scss +++ /dev/null @@ -1,11 +0,0 @@ -.container { - display: flex; - justify-content: center; - align-items: center; - min-height: 43px; - padding: 0 0.5rem; - - a { - color: #171B35; - } -} diff --git a/frontend/components/Layout/components/HeaderAction/index.js b/frontend/components/Layout/components/HeaderAction/index.js deleted file mode 100644 index e231db11a..000000000 --- a/frontend/components/Layout/components/HeaderAction/index.js +++ /dev/null @@ -1,3 +0,0 @@ -// @flow -import HeaderAction from './HeaderAction'; -export default HeaderAction; diff --git a/frontend/components/Layout/index.js b/frontend/components/Layout/index.js index 38c7a426f..fb7b105d1 100644 --- a/frontend/components/Layout/index.js +++ b/frontend/components/Layout/index.js @@ -1,8 +1,7 @@ // @flow import Layout from './Layout'; import Title from './components/Title'; -import HeaderAction from './components/HeaderAction'; export default Layout; -export { Title, HeaderAction }; +export { Title }; diff --git a/frontend/scenes/Document/Document.js b/frontend/scenes/Document/Document.js index 531d289fd..dd7d78e05 100644 --- a/frontend/scenes/Document/Document.js +++ b/frontend/scenes/Document/Document.js @@ -5,7 +5,7 @@ import styled from 'styled-components'; import { observer, inject } from 'mobx-react'; import { withRouter, Prompt } from 'react-router'; import Flex from 'components/Flex'; -import { layout } from 'styles/constants'; +import { color, layout } from 'styles/constants'; import Document from 'models/Document'; import UiStore from 'stores/UiStore'; @@ -13,9 +13,10 @@ import DocumentsStore from 'stores/DocumentsStore'; import Menu from './components/Menu'; import SaveAction from './components/SaveAction'; import LoadingPlaceholder from 'components/LoadingPlaceholder'; +import Button from 'components/Button'; import Editor from 'components/Editor'; +import Icon from 'components/Icon'; import DropToImport from 'components/DropToImport'; -import { HeaderAction } from 'components/Layout'; import LoadingIndicator from 'components/LoadingIndicator'; import Collaborators from 'components/Collaborators'; import CenteredContent from 'components/CenteredContent'; @@ -215,13 +216,22 @@ type Props = { } isNew={!!isNew} /> - : Edit} + : + Edit + } + + + {isEditing + ? undefined + : + New + } + + + {isEditing + ? Cancel + : } - {isEditing && - - Cancel - } - {!isEditing && } @@ -231,6 +241,18 @@ type Props = { } } +const HeaderAction = styled(Flex)` + justify-content: center; + align-items: center; + min-height: 43px; + color: ${color.text}; + padding: 0 0 0 16px; + + a { + color: ${color.text}; + } +`; + const DropHere = styled(Flex)` pointer-events: none; position: fixed; From 73ff473b49944197319d4da6588a488c1e446db8 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Tue, 5 Sep 2017 20:37:46 -0700 Subject: [PATCH 14/15] Cleanup --- frontend/assets/icons/menu.svg | 1 - frontend/assets/icons/search.svg | 1 - frontend/components/Button/Button.js | 60 ++++++++++++++++--- .../components/DropdownMenu/DropdownMenu.js | 2 - frontend/scenes/Document/Document.js | 27 +++++---- 5 files changed, 66 insertions(+), 25 deletions(-) delete mode 100644 frontend/assets/icons/menu.svg delete mode 100644 frontend/assets/icons/search.svg diff --git a/frontend/assets/icons/menu.svg b/frontend/assets/icons/menu.svg deleted file mode 100644 index 4523b5a1b..000000000 --- a/frontend/assets/icons/menu.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/frontend/assets/icons/search.svg b/frontend/assets/icons/search.svg deleted file mode 100644 index f974b540a..000000000 --- a/frontend/assets/icons/search.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/components/Button/Button.js b/frontend/components/Button/Button.js index d0b3afffd..20ecb553c 100644 --- a/frontend/components/Button/Button.js +++ b/frontend/components/Button/Button.js @@ -1,17 +1,18 @@ // @flow import React from 'react'; import styled from 'styled-components'; -import { size, color } from 'styles/constants'; -import { darken } from 'polished'; +import { color } from 'styles/constants'; +import { darken, lighten } from 'polished'; const RealButton = styled.button` display: inline-block; - margin: 0 ${size.medium} ${size.large} 0; + margin: 0; padding: 0; border: 0; - background: ${props => (props.neutral ? color.slate : props.danger ? color.danger : color.primary)}; + background: ${color.primary}; color: ${color.white}; border-radius: 4px; + font-size: 15px; min-width: 32px; min-height: 32px; text-decoration: none; @@ -23,30 +24,70 @@ const RealButton = styled.button` border: 0; } &:hover { - background: ${props => darken(0.05, props.neutral ? color.slate : props.danger ? color.danger : color.primary)}; + background: ${darken(0.05, color.primary)}; } + + svg { + position: relative; + top: .05em; + } + + ${props => props.light && ` + color: ${color.text}; + background: ${lighten(0.08, color.slateLight)}; + + &:hover { + background: ${color.slateLight}; + } + `} + + ${props => props.neutral && ` + background: ${color.slate}; + + &:hover { + background: ${darken(0.05, color.slate)}; + } + `} + + ${props => props.danger && ` + background: ${color.danger}; + + &:hover { + background: ${darken(0.05, color.danger)}; + } + `} + &:disabled { background: ${color.slateLight}; } `; const Label = styled.span` - padding: 4px 16px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; - font-weight: 500; + + ${props => props.hasIcon && 'padding-left: 2px;'} `; const Inner = styled.span` + padding: 4px 16px; display: flex; line-height: 28px; justify-content: center; + align-items: center; + + ${props => props.small && ` + padding: 1px 10px; + `} + + ${props => props.hasIcon && (props.small ? 'padding-left: 6px;' : 'padding-left: 10px;')} `; export type Props = { type?: string, value?: string, + small?: boolean, icon?: React$Element, className?: string, children?: React$Element, @@ -56,6 +97,7 @@ export default function Button({ type = 'text', icon, children, + small, value, ...rest }: Props) { @@ -64,9 +106,9 @@ export default function Button({ return ( - + {hasIcon && icon} - {hasText && } + {hasText && } ); diff --git a/frontend/components/DropdownMenu/DropdownMenu.js b/frontend/components/DropdownMenu/DropdownMenu.js index 69874c0ad..0e1cd9c9b 100644 --- a/frontend/components/DropdownMenu/DropdownMenu.js +++ b/frontend/components/DropdownMenu/DropdownMenu.js @@ -64,9 +64,7 @@ const Label = styled(Flex).attrs({ justify: 'center', align: 'center', })` - cursor: pointer; z-index: 1000; - min-height: 43px; `; const MenuContainer = styled.div` diff --git a/frontend/scenes/Document/Document.js b/frontend/scenes/Document/Document.js index dd7d78e05..fafd5260a 100644 --- a/frontend/scenes/Document/Document.js +++ b/frontend/scenes/Document/Document.js @@ -216,21 +216,24 @@ type Props = { } isNew={!!isNew} /> - : - Edit - } - - - {isEditing - ? undefined - : - New - } + : } {isEditing ? Cancel - : } + : } @@ -246,7 +249,7 @@ const HeaderAction = styled(Flex)` align-items: center; min-height: 43px; color: ${color.text}; - padding: 0 0 0 16px; + padding: 0 0 0 10px; a { color: ${color.text}; From dcbad23cb1ff48ebd2ceaaf7fceea8181b0e0543 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Fri, 8 Sep 2017 22:06:47 -0700 Subject: [PATCH 15/15] Styling document actions more inline with medium --- .../components/DropdownMenu/DropdownMenu.js | 1 + .../SidebarCollection/SidebarCollection.js | 4 +- .../SidebarCollectionList.js | 8 ++-- .../components/SidebarLink/SidebarLink.js | 14 ++++--- frontend/scenes/Document/Document.js | 40 +++++++++++++------ frontend/styles/constants.js | 2 +- 6 files changed, 43 insertions(+), 26 deletions(-) diff --git a/frontend/components/DropdownMenu/DropdownMenu.js b/frontend/components/DropdownMenu/DropdownMenu.js index 0e1cd9c9b..20ecf1ce8 100644 --- a/frontend/components/DropdownMenu/DropdownMenu.js +++ b/frontend/components/DropdownMenu/DropdownMenu.js @@ -65,6 +65,7 @@ const Label = styled(Flex).attrs({ align: 'center', })` z-index: 1000; + cursor: pointer; `; const MenuContainer = styled.div` diff --git a/frontend/components/Layout/components/SidebarCollection/SidebarCollection.js b/frontend/components/Layout/components/SidebarCollection/SidebarCollection.js index af5910798..9d1cefdda 100644 --- a/frontend/components/Layout/components/SidebarCollection/SidebarCollection.js +++ b/frontend/components/Layout/components/SidebarCollection/SidebarCollection.js @@ -18,8 +18,8 @@ type Props = { }; const activeStyle = { - color: '#000', - background: '#E1E1E1', + color: color.black, + background: color.slateDark, }; @observer class SidebarCollection extends React.Component { diff --git a/frontend/components/Layout/components/SidebarCollectionList/SidebarCollectionList.js b/frontend/components/Layout/components/SidebarCollectionList/SidebarCollectionList.js index c763fceaf..9318e4370 100644 --- a/frontend/components/Layout/components/SidebarCollectionList/SidebarCollectionList.js +++ b/frontend/components/Layout/components/SidebarCollectionList/SidebarCollectionList.js @@ -3,7 +3,7 @@ import React from 'react'; import { observer, inject } from 'mobx-react'; import Flex from 'components/Flex'; import styled from 'styled-components'; -import { color, layout } from 'styles/constants'; +import { color, layout, fontWeight } from 'styles/constants'; import SidebarLink from '../SidebarLink'; import DropToImport from 'components/DropToImport'; @@ -16,8 +16,8 @@ type Props = { }; const activeStyle = { - color: '#000', - background: '#E1E1E1', + color: color.black, + background: color.slateDark, }; const SidebarCollectionList = observer(({ history, collections }: Props) => { @@ -42,7 +42,7 @@ const SidebarCollectionList = observer(({ history, collections }: Props) => { const Header = styled(Flex)` font-size: 11px; - font-weight: 500; + font-weight: ${fontWeight.semiBold}; text-transform: uppercase; color: ${color.slate}; letter-spacing: 0.04em; diff --git a/frontend/components/Layout/components/SidebarLink/SidebarLink.js b/frontend/components/Layout/components/SidebarLink/SidebarLink.js index d09f85c3f..cb6f2b0e1 100644 --- a/frontend/components/Layout/components/SidebarLink/SidebarLink.js +++ b/frontend/components/Layout/components/SidebarLink/SidebarLink.js @@ -1,26 +1,28 @@ // @flow import React from 'react'; import { NavLink } from 'react-router-dom'; -import { layout, color } from 'styles/constants'; -import { darken } from 'polished'; +import { layout, color, fontWeight } from 'styles/constants'; import styled from 'styled-components'; const activeStyle = { - color: '#000000', + color: color.black, + fontWeight: fontWeight.semiBold, }; function SidebarLink(props: Object) { - return ; + return ; } const StyledNavLink = styled(NavLink)` display: block; - padding: 5px ${layout.hpadding}; + overflow: hidden; + text-overflow: ellipsis; + margin: 5px ${layout.hpadding}; color: ${color.slateDark}; font-size: 15px; &:hover { - color: ${darken(0.1, color.slateDark)}; + color: ${color.text}; } `; diff --git a/frontend/scenes/Document/Document.js b/frontend/scenes/Document/Document.js index fafd5260a..24e48b9a5 100644 --- a/frontend/scenes/Document/Document.js +++ b/frontend/scenes/Document/Document.js @@ -13,9 +13,7 @@ import DocumentsStore from 'stores/DocumentsStore'; import Menu from './components/Menu'; import SaveAction from './components/SaveAction'; import LoadingPlaceholder from 'components/LoadingPlaceholder'; -import Button from 'components/Button'; import Editor from 'components/Editor'; -import Icon from 'components/Icon'; import DropToImport from 'components/DropToImport'; import LoadingIndicator from 'components/LoadingIndicator'; import Collaborators from 'components/Collaborators'; @@ -105,6 +103,11 @@ type Props = { this.props.history.push(url); }; + onClickNew = () => { + if (!this.document) return; + this.props.history.push(`${this.document.collection.url}/new`); + }; + onSave = async (redirect: boolean = false) => { if (this.document && !this.document.allowSave) return; let document = this.document; @@ -216,24 +219,21 @@ type Props = { } isNew={!!isNew} /> - : } + } {isEditing ? Cancel - : } + } @@ -244,15 +244,29 @@ type Props = { } } +const Separator = styled.div` + margin-left: 12px; + width: 1px; + height: 20px; + background: ${color.slateLight}; +`; + const HeaderAction = styled(Flex)` justify-content: center; align-items: center; min-height: 43px; color: ${color.text}; - padding: 0 0 0 10px; + padding: 0 0 0 14px; - a { + a, + svg { color: ${color.text}; + opacity: .8; + transition: opacity 100ms ease-in-out; + + &:hover { + opacity: 1; + } } `; diff --git a/frontend/styles/constants.js b/frontend/styles/constants.js index 56bf05aa1..bfdf50e50 100644 --- a/frontend/styles/constants.js +++ b/frontend/styles/constants.js @@ -31,7 +31,7 @@ export const fontWeight = { light: 300, regular: 400, medium: 500, - demiBold: 600, + semiBold: 600, bold: 700, heavy: 800, };