diff --git a/app/components/DocumentPreview/components/PublishingInfo.js b/app/components/DocumentPreview/components/PublishingInfo.js
index 34ed1105..11f2254a 100644
--- a/app/components/DocumentPreview/components/PublishingInfo.js
+++ b/app/components/DocumentPreview/components/PublishingInfo.js
@@ -24,7 +24,13 @@ type Props = {
};
function PublishingInfo({ collection, document }: Props) {
- const { modifiedSinceViewed, updatedAt, updatedBy, publishedAt } = document;
+ const {
+ modifiedSinceViewed,
+ updatedAt,
+ updatedBy,
+ publishedAt,
+ isDraft,
+ } = document;
return (
@@ -35,20 +41,20 @@ function PublishingInfo({ collection, document }: Props) {
) : (
{updatedBy.name}
- {publishedAt ? (
-
- modified ago
-
- ) : (
+ {isDraft ? (
saved ago
+ ) : (
+
+ modified ago
+
)}
)}
{collection && (
- in {collection.name}
+ in {isDraft ? 'Drafts' : collection.name}
)}
diff --git a/app/components/Sidebar/Main.js b/app/components/Sidebar/Main.js
index 1b126e0b..f56d29f7 100644
--- a/app/components/Sidebar/Main.js
+++ b/app/components/Sidebar/Main.js
@@ -56,7 +56,7 @@ class MainSidebar extends React.Component {
- }>
+ } exact={false}>
Home
}>
diff --git a/app/components/Sidebar/components/SidebarLink.js b/app/components/Sidebar/components/SidebarLink.js
index 0ca4c3c9..cd643e8d 100644
--- a/app/components/Sidebar/components/SidebarLink.js
+++ b/app/components/Sidebar/components/SidebarLink.js
@@ -52,6 +52,7 @@ type Props = {
iconColor?: string,
active?: boolean,
theme: Object,
+ exact?: boolean,
};
@observer
@@ -100,6 +101,7 @@ class SidebarLink extends React.Component {
menu,
menuOpen,
hideExpandToggle,
+ exact,
} = this.props;
const Component = to ? StyledNavLink : StyledDiv;
const showExpandIcon =
@@ -113,7 +115,7 @@ class SidebarLink extends React.Component {
style={active ? this.activeStyle : undefined}
onClick={onClick}
to={to}
- exact
+ exact={exact !== false}
>
{icon && {icon}}
{showExpandIcon && (
diff --git a/app/components/Tab.js b/app/components/Tab.js
new file mode 100644
index 00000000..fab0f010
--- /dev/null
+++ b/app/components/Tab.js
@@ -0,0 +1,26 @@
+// @flow
+import * as React from 'react';
+import styled, { withTheme } from 'styled-components';
+import { NavLink } from 'react-router-dom';
+
+const NavItem = styled(NavLink)`
+ display: inline-block;
+ font-size: 11px;
+ font-weight: 500;
+ text-transform: uppercase;
+ color: ${props => props.theme.slate};
+ letter-spacing: 0.04em;
+ margin-right: 20px;
+ padding-bottom: 8px;
+`;
+
+function Tab(props: *) {
+ const activeStyle = {
+ paddingBottom: '5px',
+ borderBottom: `3px solid ${props.theme.slateLight}`,
+ };
+
+ return ;
+}
+
+export default withTheme(Tab);
diff --git a/app/components/Tabs.js b/app/components/Tabs.js
new file mode 100644
index 00000000..78fd6312
--- /dev/null
+++ b/app/components/Tabs.js
@@ -0,0 +1,10 @@
+// @flow
+import styled from 'styled-components';
+
+const Tabs = styled.nav`
+ border-bottom: 1px solid ${props => props.theme.slateLight};
+ margin-top: 22px;
+ margin-bottom: 10px;
+`;
+
+export default Tabs;
diff --git a/app/index.js b/app/index.js
index 8a92ce64..3f9b7b27 100644
--- a/app/index.js
+++ b/app/index.js
@@ -3,54 +3,23 @@ import * as React from 'react';
import { render } from 'react-dom';
import { Provider } from 'mobx-react';
import { ThemeProvider } from 'styled-components';
-import {
- BrowserRouter as Router,
- Switch,
- Route,
- Redirect,
-} from 'react-router-dom';
+import { BrowserRouter as Router } from 'react-router-dom';
import stores from 'stores';
import theme from 'shared/styles/theme';
import globalStyles from 'shared/styles/globals';
import 'shared/styles/prism.css';
-import Home from 'scenes/Home';
-import Dashboard from 'scenes/Dashboard';
-import Starred from 'scenes/Starred';
-import Drafts from 'scenes/Drafts';
-import Collection from 'scenes/Collection';
-import Document from 'scenes/Document';
-import Search from 'scenes/Search';
-import Settings from 'scenes/Settings';
-import Details from 'scenes/Settings/Details';
-import People from 'scenes/Settings/People';
-import Slack from 'scenes/Settings/Slack';
-import Shares from 'scenes/Settings/Shares';
-import Tokens from 'scenes/Settings/Tokens';
-import Export from 'scenes/Settings/Export';
-import Error404 from 'scenes/Error404';
-
import ErrorBoundary from 'components/ErrorBoundary';
import ScrollToTop from 'components/ScrollToTop';
import ScrollToAnchor from 'components/ScrollToAnchor';
-import Layout from 'components/Layout';
-import Auth from 'components/Auth';
-import RouteSidebarHidden from 'components/RouteSidebarHidden';
-
-import { matchDocumentSlug } from 'utils/routeHelpers';
+import Routes from './routes';
let DevTools;
if (__DEV__) {
DevTools = require('mobx-react-devtools').default; // eslint-disable-line global-require
}
-const notFoundSearch = () => ;
-const DocumentNew = () => ;
-const RedirectDocument = ({ match }: { match: Object }) => (
-
-);
-
globalStyles();
const element = document.getElementById('root');
@@ -64,92 +33,7 @@ if (element) {
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
diff --git a/app/routes.js b/app/routes.js
new file mode 100644
index 00000000..b2be2b83
--- /dev/null
+++ b/app/routes.js
@@ -0,0 +1,78 @@
+// @flow
+import * as React from 'react';
+import { Switch, Route, Redirect } from 'react-router-dom';
+
+import Home from 'scenes/Home';
+import Dashboard from 'scenes/Dashboard';
+import Starred from 'scenes/Starred';
+import Drafts from 'scenes/Drafts';
+import Collection from 'scenes/Collection';
+import Document from 'scenes/Document';
+import Search from 'scenes/Search';
+import Settings from 'scenes/Settings';
+import Details from 'scenes/Settings/Details';
+import People from 'scenes/Settings/People';
+import Slack from 'scenes/Settings/Slack';
+import Shares from 'scenes/Settings/Shares';
+import Tokens from 'scenes/Settings/Tokens';
+import Export from 'scenes/Settings/Export';
+import Error404 from 'scenes/Error404';
+
+import Layout from 'components/Layout';
+import Auth from 'components/Auth';
+import RouteSidebarHidden from 'components/RouteSidebarHidden';
+import { matchDocumentSlug as slug } from 'utils/routeHelpers';
+
+const NotFound = () => ;
+const DocumentNew = () => ;
+const RedirectDocument = ({ match }: { match: Object }) => (
+
+);
+
+export default function Routes() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/app/scenes/Dashboard.js b/app/scenes/Dashboard.js
index 5b0a5ea0..d5ca3ddf 100644
--- a/app/scenes/Dashboard.js
+++ b/app/scenes/Dashboard.js
@@ -1,20 +1,25 @@
// @flow
import * as React from 'react';
+import { Switch, Route } from 'react-router-dom';
import { observable } from 'mobx';
import { observer, inject } from 'mobx-react';
import { NewDocumentIcon } from 'outline-icons';
import DocumentsStore from 'stores/DocumentsStore';
+import AuthStore from 'stores/AuthStore';
import NewDocumentMenu from 'menus/NewDocumentMenu';
import Actions, { Action } from 'components/Actions';
import CenteredContent from 'components/CenteredContent';
import DocumentList from 'components/DocumentList';
import PageTitle from 'components/PageTitle';
import Subheading from 'components/Subheading';
+import Tabs from 'components/Tabs';
+import Tab from 'components/Tab';
import { ListPlaceholder } from 'components/LoadingPlaceholder';
type Props = {
documents: DocumentsStore,
+ auth: AuthStore,
};
@observer
@@ -27,16 +32,20 @@ class Dashboard extends React.Component {
loadContent = async () => {
await Promise.all([
- this.props.documents.fetchRecentlyModified({ limit: 5 }),
- this.props.documents.fetchRecentlyViewed({ limit: 5 }),
+ this.props.documents.fetchRecentlyModified({ limit: 15 }),
+ this.props.documents.fetchRecentlyViewed({ limit: 15 }),
]);
this.isLoaded = true;
};
render() {
- const { documents } = this.props;
+ const { documents, auth } = this.props;
+ if (!auth.user) return;
+
const hasRecentlyViewed = documents.recentlyViewed.length > 0;
const hasRecentlyEdited = documents.recentlyEdited.length > 0;
+
+ const owned = documents.owned(auth.user.id);
const showContent =
this.isLoaded || (hasRecentlyViewed && hasRecentlyEdited);
@@ -44,28 +53,34 @@ class Dashboard extends React.Component {
Home
+
+
+ Recently edited
+
+
+ Recently viewed
+
+ Created by me
+
{showContent ? (
- {hasRecentlyViewed && (
-
- Recently viewed
+
+
-
- )}
- {hasRecentlyEdited && (
-
- Recently edited
+
+
+
+
+
-
- )}
+
+
} />
@@ -80,4 +95,4 @@ class Dashboard extends React.Component {
}
}
-export default inject('documents')(Dashboard);
+export default inject('documents', 'auth')(Dashboard);
diff --git a/app/stores/DocumentsStore.js b/app/stores/DocumentsStore.js
index dbe746f5..dea90d0e 100644
--- a/app/stores/DocumentsStore.js
+++ b/app/stores/DocumentsStore.js
@@ -29,10 +29,8 @@ class DocumentsStore extends BaseStore {
ui: UiStore;
- /* Computed */
-
@computed
- get recentlyViewed(): Array {
+ get recentlyViewed(): Document[] {
const docs = [];
this.recentlyViewedIds.forEach(id => {
const doc = this.getById(id);
@@ -51,6 +49,17 @@ class DocumentsStore extends BaseStore {
return docs;
}
+ owned(userId: string): Document[] {
+ return _.orderBy(
+ _.filter(
+ this.data.values(),
+ document => document.createdBy.id === userId
+ ),
+ 'updatedAt',
+ 'desc'
+ );
+ }
+
pinnedInCollection(collectionId: string): Document[] {
return _.filter(
this.recentlyEditedInCollection(collectionId),
@@ -152,6 +161,11 @@ class DocumentsStore extends BaseStore {
await this.fetchPage('pinned', options);
};
+ @action
+ fetchOwned = async (options: ?PaginationParams): Promise<*> => {
+ await this.fetchPage('owned', options);
+ };
+
@action
search = async (
query: string,