mirror of
https://github.com/urbit/shrub.git
synced 2024-11-30 22:15:47 +03:00
Merge branch 'mp/os1/publish-sidebar' into os1-rc
This commit is contained in:
commit
69fbf7f13f
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -167,7 +167,14 @@ a {
|
||||
outline: 0px solid transparent;
|
||||
}
|
||||
|
||||
|
||||
.dropdown::after {
|
||||
content: "⌃";
|
||||
transform: rotate(180deg);
|
||||
position: absolute;
|
||||
right: 8px;
|
||||
top: 16px;
|
||||
color: #7f7f7f;
|
||||
}
|
||||
.no-scrollbar {
|
||||
-ms-overflow-style: none;
|
||||
scrollbar-width: none;
|
||||
|
@ -1,13 +1,33 @@
|
||||
import React, { Component } from 'react';
|
||||
import { Route, Link } from 'react-router-dom';
|
||||
|
||||
//TODO take props and render entry in sidebar
|
||||
export class NotebookItem extends Component {
|
||||
render() {
|
||||
let { props } = this;
|
||||
|
||||
let selectedClass = (props.selected) ? "bg-gray5 b--gray4" : "b--gray4";
|
||||
|
||||
let postCount = (props.total === 1)
|
||||
? `${props.total} post` : `${props.total} posts`;
|
||||
|
||||
let unread = (props.unreadCount > 0)
|
||||
? `${props.unreadCount} unread` : "";
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
||||
</div>
|
||||
)
|
||||
<Link
|
||||
to={"/~publish/notebook/" + props.path}>
|
||||
<div className={"w-100 v-mid f9 pl4 bb " + selectedClass}>
|
||||
<p className="f9 pt1">{props.title}</p>
|
||||
<p className="f9 mono gray2">by {props.author}</p>
|
||||
<p className="f9 pb1">
|
||||
{postCount}
|
||||
<span className="green2 ml3">
|
||||
{unread}
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,62 +6,163 @@ export class Sidebar extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
sort: "oldest"
|
||||
sort: "oldest",
|
||||
sortedBooks: new Map()
|
||||
}
|
||||
this.sort = this.sort.bind(this);
|
||||
this.sortChange = this.sortChange.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.sort();
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
if ((prevState.sort !== this.state.sort) || (prevProps !== this.props)) {
|
||||
this.sort();
|
||||
}
|
||||
}
|
||||
|
||||
sort() {
|
||||
let { props, state } = this;
|
||||
let notebooks = new Map();
|
||||
Object.keys(props.notebooks).map(host => {
|
||||
Object.keys(props.notebooks[host]).map(notebook => {
|
||||
let title = `${host}/${notebook}`;
|
||||
notebooks.set(title, props.notebooks[host][notebook])
|
||||
})
|
||||
});
|
||||
switch (state.sort) {
|
||||
case "oldest":
|
||||
notebooks = new Map(
|
||||
[...notebooks.entries()].sort(
|
||||
(a, b) => {
|
||||
if ((a[1]) && (b[1])) {
|
||||
return a[1]["date-created"] - b[1]["date-created"]
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
break;
|
||||
case "newest":
|
||||
notebooks = new Map(
|
||||
[...notebooks.entries()].sort(
|
||||
(a, b) => {
|
||||
if ((a[1]) && (b[1])) {
|
||||
return b[1]["date-created"] - a[1]["date-created"]
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
break;
|
||||
case "alphabetical":
|
||||
notebooks = new Map(
|
||||
[...notebooks.entries()].sort((a, b) => {
|
||||
if ((a[1]) && (b[1])) {
|
||||
if (a[1]["title"].toLowerCase() < b[1]["title"].toLowerCase()) {
|
||||
return -1;
|
||||
}
|
||||
if (a[1]["title"].toLowerCase() > b[1]["title"].toLowerCase()) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
})
|
||||
);
|
||||
break;
|
||||
case "reverseAlphabetical":
|
||||
notebooks = new Map(
|
||||
[...notebooks.entries()].sort((a, b) => {
|
||||
if ((a[1]) && (b[1])) {
|
||||
if (a[1]["title"].toLowerCase() > b[1]["title"].toLowerCase()) {
|
||||
return -1;
|
||||
}
|
||||
if (a[1]["title"].toLowerCase() < b[1]["title"].toLowerCase()) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
})
|
||||
);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
this.setState({ sortedBooks: notebooks });
|
||||
}
|
||||
|
||||
sortChange(event) {
|
||||
this.setState({sort: event.target.value});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { props, state } = this;
|
||||
|
||||
let activeClasses = (this.props.active === "sidebar") ? " " : "dn-s ";
|
||||
|
||||
let activeClasses = (props.active === "sidebar") ? " " : "dn-s ";
|
||||
let hiddenClasses = true;
|
||||
|
||||
if (this.props.popout) {
|
||||
if (props.popout) {
|
||||
hiddenClasses = false;
|
||||
} else {
|
||||
hiddenClasses = this.props.sidebarShown;
|
||||
hiddenClasses = props.sidebarShown;
|
||||
};
|
||||
|
||||
//TODO render notebook list from state
|
||||
// (make a new array of all notebooks from {author: {notebook}}
|
||||
// prop.notebook obj, case-switch the sorting from this.state.sort, and map it)
|
||||
//TODO allow for user sorting of notebook list
|
||||
//
|
||||
//(reactive dropdown -> amends state -> sort by state prop)
|
||||
//
|
||||
let notebooks = <div></div>
|
||||
let notebookItems = [...state.sortedBooks].map(([path, book]) => {
|
||||
let selected = (props.path === path);
|
||||
let author = path.split("/")[0];
|
||||
return (
|
||||
<NotebookItem
|
||||
key={book.title}
|
||||
title={book.title}
|
||||
author={author}
|
||||
path={path}
|
||||
total={book["num-notes"]}
|
||||
unreadCount={book["num-unread"]}
|
||||
selected={selected}
|
||||
/>
|
||||
);
|
||||
})
|
||||
|
||||
let notebooks = <div>{notebookItems}</div>
|
||||
|
||||
return (
|
||||
<div className={`bn br-m br-l br-xl b--gray4 b--gray2-d lh-copy h-100
|
||||
flex-shrink-0 mw-300-ns pt3 pt0-m pt0-l pt0-xl
|
||||
relative ` + activeClasses + ((hiddenClasses)
|
||||
? "flex-basis-100-s flex-basis-30-ns"
|
||||
: "dn")}>
|
||||
<a className="db dn-m dn-l dn-xl f8 pb3 pl3" href="/">⟵ Landscape</a>
|
||||
<div className="w-100 pa4">
|
||||
<Link
|
||||
to="/~publish/new"
|
||||
className="green2 mr4 f9">
|
||||
New Notebook
|
||||
<div
|
||||
className={
|
||||
"bn br-m br-l br-xl b--gray4 b--gray2-d lh-copy h-100 " +
|
||||
"flex-shrink-0 mw-300-ns pt3 pt0-m pt0-l pt0-xl relative " +
|
||||
activeClasses +
|
||||
(hiddenClasses ? "flex-basis-100-s flex-basis-30-ns" : "dn")
|
||||
}>
|
||||
<a className="db dn-m dn-l dn-xl f8 pb3 pl3" href="/">
|
||||
⟵ Landscape
|
||||
</a>
|
||||
<div className="w-100">
|
||||
<Link to="/~publish/new" className="green2 mr4 f9 pl4 pt4 dib">
|
||||
New Notebook
|
||||
</Link>
|
||||
<Link
|
||||
to="/~publish/join"
|
||||
className="f9 gray2">
|
||||
Join Notebook
|
||||
<Link to="/~publish/join" className="f9 gray2">
|
||||
Join Notebook
|
||||
</Link>
|
||||
</div>
|
||||
<div className="overflow-y-scroll h-100">
|
||||
<h2 className={`f8 pt1 pr4 pb3 pl3 black c-default bb b--gray4 mb2
|
||||
<h2
|
||||
className={`f8 pt3 pr4 pb3 pl3 black c-default bb b--gray4 mb2
|
||||
dn-m dn-l dn-xl`}>
|
||||
Your Notebooks
|
||||
Your Notebooks
|
||||
</h2>
|
||||
{/*TODO Dropdown attached to this.state.sort */}
|
||||
{notebooks}
|
||||
<div className="dropdown relative bb b--gray4">
|
||||
<select
|
||||
style={{ WebkitAppearance: "none" }}
|
||||
className="pl4 pv6 f9 bg-white bg-black-d white-d bn w-100 inter"
|
||||
value={this.state.sort}
|
||||
onChange={this.sortChange}>
|
||||
<option value="oldest">Oldest Notebooks First</option>
|
||||
<option value="newest">Newest Notebooks First</option>
|
||||
<option value="alphabetical">Alphabetical A -> Z</option>
|
||||
<option value="reverseAlphabetical">Alphabetical Z -> A</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div className="overflow-y-scroll h-100">{notebooks}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Sidebar;
|
||||
export default Sidebar;
|
@ -78,14 +78,17 @@ export class Root extends Component {
|
||||
let ship = props.match.params.ship || "";
|
||||
let notebook = props.match.params.notebook || "";
|
||||
|
||||
let path = `${ship}/${notebook}`;
|
||||
|
||||
if (view === "new") {
|
||||
return (
|
||||
<Skeleton
|
||||
popout={false}
|
||||
active={"rightPanel"}
|
||||
rightPanelHide={false}
|
||||
sidebarShown={true}
|
||||
notebooks={state.notebooks}>
|
||||
popout={false}
|
||||
active={"rightPanel"}
|
||||
rightPanelHide={false}
|
||||
sidebarShown={true}
|
||||
notebooks={state.notebooks}
|
||||
path={path}>
|
||||
<NewPost
|
||||
notebooks={state.notebooks}
|
||||
ship={ship}
|
||||
@ -93,46 +96,51 @@ export class Root extends Component {
|
||||
{...props}
|
||||
/>
|
||||
</Skeleton>
|
||||
)
|
||||
);
|
||||
}
|
||||
else {
|
||||
return (
|
||||
<Skeleton
|
||||
popout={false}
|
||||
active={"rightPanel"}
|
||||
rightPanelHide={false}
|
||||
sidebarShown={true}
|
||||
notebooks={state.notebooks}>
|
||||
popout={false}
|
||||
active={"rightPanel"}
|
||||
rightPanelHide={false}
|
||||
sidebarShown={true}
|
||||
notebooks={state.notebooks}
|
||||
path={path}>
|
||||
<Notebook
|
||||
notebooks={state.notebooks}
|
||||
view={view}
|
||||
ship={ship}
|
||||
book={notebook}
|
||||
{...props}/>
|
||||
{...props}
|
||||
/>
|
||||
</Skeleton>
|
||||
)
|
||||
);
|
||||
}
|
||||
}}/>
|
||||
<Route exact path="/~publish/(popout)?/note/:ship/:notebook/:note"
|
||||
render={ (props) => {
|
||||
let ship = props.match.params.ship || "";
|
||||
let notebook = props.match.params.notebook || "";
|
||||
let path = `${ship}/${notebook}`
|
||||
let note = props.match.params.note || "";
|
||||
|
||||
return (
|
||||
<Skeleton
|
||||
popout={false}
|
||||
active={"rightPanel"}
|
||||
rightPanelHide={false}
|
||||
sidebarShown={true}
|
||||
notebooks={state.notebooks}>
|
||||
popout={false}
|
||||
active={"rightPanel"}
|
||||
rightPanelHide={false}
|
||||
sidebarShown={true}
|
||||
notebooks={state.notebooks}
|
||||
path={path}>
|
||||
<Note
|
||||
notebooks={state.notebooks}
|
||||
book={notebook}
|
||||
ship={ship}
|
||||
note={note}/>
|
||||
note={note}
|
||||
/>
|
||||
</Skeleton>
|
||||
)
|
||||
);
|
||||
}}/>
|
||||
</BrowserRouter>
|
||||
)
|
||||
|
@ -29,6 +29,7 @@ export class Skeleton extends Component {
|
||||
sidebarShown={props.sidebarShown}
|
||||
active={props.active}
|
||||
notebooks={props.notebooks}
|
||||
path={props.path}
|
||||
/>
|
||||
<div className={"h-100 w-100 overflow-container " + rightPanelHide} style={{
|
||||
flexGrow: 1,
|
||||
|
Loading…
Reference in New Issue
Block a user