// @flow import React from 'react'; import { Link, withRouter } from 'react-router-dom'; import Helmet from 'react-helmet'; import styled from 'styled-components'; import { observer, inject } from 'mobx-react'; import { observable } from 'mobx'; import _ from 'lodash'; 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 Modal from 'components/Modal'; import AddIcon from 'components/Icon/AddIcon'; import MoreIcon from 'components/Icon/MoreIcon'; import CollectionNew from 'scenes/CollectionNew'; import CollectionEdit from 'scenes/CollectionEdit'; import KeyboardShortcuts from 'scenes/KeyboardShortcuts'; 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'; import CollectionsStore from 'stores/CollectionsStore'; import DocumentsStore from 'stores/DocumentsStore'; type Props = { history: Object, collections: CollectionsStore, documents: DocumentsStore, children?: ?React.Element, actions?: ?React.Element, title?: ?React.Element, auth: AuthStore, ui: UiStore, search: ?boolean, notifications?: React.Element, }; @observer class Layout extends React.Component { props: Props; static defaultProps = { search: true, }; @observable modal = null; @keydown(['/', 't']) goToSearch(ev) { ev.preventDefault(); ev.stopPropagation(); this.props.history.push(searchUrl()); } @keydown('d') goToDashboard() { this.props.history.push(homeUrl()); } @keydown('e') goToEdit(ev) { const activeDocument = this.props.documents.active; if (!activeDocument) return; ev.preventDefault(); ev.stopPropagation(); this.props.history.push(documentEditUrl(activeDocument)); } handleLogout = () => { this.props.auth.logout(() => this.props.history.push('/')); }; @keydown('shift+/') goToOpenKeyboardShortcuts() { this.modal = 'keyboard-shortcuts'; } handleOpenKeyboardShortcuts = () => { this.goToOpenKeyboardShortcuts(); }; handleOpenSettings = () => { this.modal = 'settings'; }; handleCreateCollection = () => { this.modal = 'create-collection'; }; handleEditCollection = () => { this.modal = 'edit-collection'; }; handleCloseModal = () => { this.modal = null; }; render() { const { auth, documents, collections, history, ui } = this.props; const { user, team } = auth; return ( {this.props.ui.progressBarVisible && } {this.props.notifications} {auth.authenticated && user && team && } > Settings Keyboard shortcuts API Logout Home Search Starred {collections.active ? : } {collections.active ? : } } {this.props.children} {collections.active && } ); } } const CollectionAction = styled.a` position: absolute; top: -2px; right: ${layout.hpadding}; svg { opacity: .35; width: 16px; height: 16px; } &:hover { svg { opacity: 1; } } `; const Container = styled(Flex)` position: relative; width: 100%; height: 100%; `; const Content = styled(Flex)` margin-left: ${props => (props.editMode ? 0 : layout.sidebarWidth)}; transition: margin-left 200ms ease-in-out; `; const MenuLink = styled(Link)` color: ${color.text}; `; const Sidebar = styled(Flex)` position: fixed; top: 0; bottom: 0; left: ${props => (props.editMode ? `-${layout.sidebarWidth}` : 0)}; width: ${layout.sidebarWidth}; background: ${color.smoke}; transition: left 200ms ease-in-out; `; const LinkSection = styled(Flex)` flex-direction: column; margin: 24px 0; position: relative; `; export default withRouter( inject('user', 'auth', 'ui', 'documents', 'collections')(Layout) );