adds publish new post page

This commit is contained in:
Isaac Visintainer 2020-01-29 11:44:11 -08:00
parent d2ad5b143d
commit 12730ad0e7
6 changed files with 258 additions and 30 deletions

View File

@ -750,6 +750,11 @@
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
"dev": true
},
"codemirror": {
"version": "5.51.0",
"resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.51.0.tgz",
"integrity": "sha512-vyuYYRv3eXL0SCuZA4spRFlKNzQAewHcipRQCOKgRy7VNAvZxTKzbItdbCl4S5AgPZ5g3WkHp+ibWQwv9TLG7Q=="
},
"collect-stream": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/collect-stream/-/collect-stream-1.2.1.tgz",
@ -1791,7 +1796,8 @@
"ansi-regex": {
"version": "2.1.1",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"aproba": {
"version": "1.2.0",
@ -1812,12 +1818,14 @@
"balanced-match": {
"version": "1.0.0",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@ -1832,17 +1840,20 @@
"code-point-at": {
"version": "1.1.0",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"core-util-is": {
"version": "1.0.2",
@ -1959,7 +1970,8 @@
"inherits": {
"version": "2.0.3",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"ini": {
"version": "1.3.5",
@ -1971,6 +1983,7 @@
"version": "1.0.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@ -1985,6 +1998,7 @@
"version": "3.0.4",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@ -1992,12 +2006,14 @@
"minimist": {
"version": "0.0.8",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"minipass": {
"version": "2.3.5",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
@ -2016,6 +2032,7 @@
"version": "0.5.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"minimist": "0.0.8"
}
@ -2096,7 +2113,8 @@
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"object-assign": {
"version": "4.1.1",
@ -2108,6 +2126,7 @@
"version": "1.4.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"wrappy": "1"
}
@ -2193,7 +2212,8 @@
"safe-buffer": {
"version": "5.1.2",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"safer-buffer": {
"version": "2.1.2",
@ -2229,6 +2249,7 @@
"version": "1.0.2",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@ -2248,6 +2269,7 @@
"version": "3.0.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@ -2291,12 +2313,14 @@
"wrappy": {
"version": "1.0.2",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"yallist": {
"version": "3.0.3",
"bundled": true,
"dev": true
"dev": true,
"optional": true
}
}
},
@ -4535,6 +4559,11 @@
"scheduler": "^0.13.6"
}
},
"react-codemirror2": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/react-codemirror2/-/react-codemirror2-6.0.0.tgz",
"integrity": "sha512-D7y9qZ05FbUh9blqECaJMdDwKluQiO3A9xB+fssd5jKM7YAXucRuEOlX32mJQumUvHUkHRHqXIPBjm6g0FW0Ag=="
},
"react-dom": {
"version": "16.8.6",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.8.6.tgz",

View File

@ -26,10 +26,12 @@
},
"dependencies": {
"classnames": "^2.2.6",
"codemirror": "^5.51.0",
"del": "^5.1.0",
"lodash": "^4.17.11",
"moment": "^2.20.1",
"react": "^16.5.2",
"react-codemirror2": "^6.0.0",
"react-dom": "^16.8.6",
"react-router-dom": "^5.0.0",
"urbit-ob": "^4.1.2",

View File

@ -1,3 +1,10 @@
:root {
--dark-gray: #555555;
--gray: #7F7F7F;
--medium-gray: #CCCCCC;
--light-gray: rgba(0,0,0,0.08);
}
html, body {
height: 100%;
width: 100%;
@ -67,4 +74,82 @@ a {
.mw-300-ns {
max-width: 300px;
}
}
}
.NewPost {
width: 100%;
height: calc(100% - 103px);
display: flex;
padding-top: 8px;
}
.react-codemirror2 {
width: 100%;
}
.CodeMirror {
padding: 12px;
height: 100% !important;
max-width: 700px;
width: 100% !important;
cursor: text;
font-size: 12px;
line-height: 20px;
* {
font-family: 'Source Code Pro';
}
}
.CodeMirror-selected { background:#BAE3FE !important; }
.cm-s-tlon span { font-family: "Source Code Pro"}
.cm-s-tlon span.cm-meta { color: var(--gray); }
.cm-s-tlon span.cm-number { color: var(--gray); }
.cm-s-tlon span.cm-keyword { line-height: 1em; font-weight: bold; color: var(--gray); }
.cm-s-tlon span.cm-atom { font-weight: bold; color: var(--gray); }
.cm-s-tlon span.cm-def { color: black; }
.cm-s-tlon span.cm-variable { color: black; }
.cm-s-tlon span.cm-variable-2 { color: black; }
.cm-s-tlon span.cm-variable-3, .cm-s-tlon span.cm-type { color: black; }
.cm-s-tlon span.cm-property { color: black; }
.cm-s-tlon span.cm-operator { color: black; }
.cm-s-tlon span.cm-comment { color: black; background-color: var(--light-gray); padding:2px; border-radius: 2px;}
.cm-s-tlon span.cm-string { color: var(--dark-gray); }
.cm-s-tlon span.cm-string-2 { color: var(--gray); }
.cm-s-tlon span.cm-qualifier { color: #555; }
.cm-s-tlon span.cm-error { color: #FF0000; }
.cm-s-tlon span.cm-attribute { color: var(--gray); }
.cm-s-tlon span.cm-tag { color: var(--gray); }
.cm-s-tlon span.cm-link { color: var(--dark-gray); text-decoration: none;}
.cm-s-tlon .CodeMirror-activeline-background { background: var(--gray); }
.cm-s-tlon .CodeMirror-cursor {
border-left: 2px solid #3687FF;
}
.cm-s-tlon span.cm-builtin { color: var(--gray); }
.cm-s-tlon span.cm-bracket { color: var(--gray); }
/* .cm-s-tlon { font-family: Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, serif;} */
.cm-s-tlon .CodeMirror-matchingbracket { outline:1px solid grey; color:black !important; }
.CodeMirror-hints.tlon {
/* font-family: Menlo, Monaco, Consolas, 'Courier New', monospace; */
color: #616569;
background-color: #ebf3fd !important;
}
.CodeMirror-hints.tlon .CodeMirror-hint-active {
background-color: #a2b8c9 !important;
color: #5c6065 !important;
}
.title-input[placeholder]:empty:before {
content: attr(placeholder);
color: #7F7F7F;
}
[contenteditable]:focus {
outline: 0px solid transparent;
}

View File

@ -3,3 +3,5 @@
@import 'css/custom.css';
@import 'css/spinner.css';
@import '../node_modules/codemirror/lib/codemirror.css';
@import '../node_modules/codemirror/theme/material.css';

View File

@ -1,12 +1,103 @@
import React, { Component } from 'react'
import { Controlled as CodeMirror } from 'react-codemirror2'
import { dateToDa, stringToSymbol } from '/lib/util';
//TODO integrate codemirror work from GA
import 'codemirror/mode/markdown/markdown';
export class NewPost extends Component {
constructor(props) {
super(props);
this.state = {
body: "# Hello",
title: '',
submit: false,
awaiting: null,
}
this.postSubmit = this.postSubmit.bind(this);
this.titleChange = this.titleChange.bind(this);
this.bodyChange = this.bodyChange.bind(this);
}
postSubmit() {
let newNote = {
"new-note": {
who: this.props.host.slice(1),
book: this.props.notebookName,
note: stringToSymbol(this.state.title),
title: this.state.title,
body: this.state.body,
}
}
this.setState({
awaiting: newNote["new-note"].note
}, () => {
window.api.action("publish", "publish-action", newNote);
});
}
componentDidUpdate(prevProps, prevState) {
if (this.props.notebook.notes[this.state.awaiting]) {
let redirect =
`/~publish/note/${this.props.host}/${this.props.notebookName}/${this.state.awaiting}`;
this.props.history.push(redirect);
}
}
titleChange(evt) {
let submit = !(evt.target.value === '' || this.state.body === '');
this.setState({title: evt.target.value, submit: submit});
}
bodyChange(editor, data, value) {
let submit = !(value === '' || this.state.title === '');
this.setState({body: value, submit: submit});
}
render() {
const options = {
mode: 'markdown',
theme: 'tlon',
lineNumbers: false,
lineWrapping: true,
scrollbarStyle: null,
cursorHeight: 0.85
};
let date = dateToDa(new Date()).slice(1, -10);
let submitStyle = (this.state.submit)
? { color: '#2AA779', cursor: "pointer" }
: { color: '#B1B2B3', cursor: "auto" };
return (
<div>
<div className="center mw7 f9 h-100">
<div style={{padding: 16}} className="flex-col">
<div className="w-100 tl">
<button disabled={!this.state.submit} style={submitStyle}
onClick={this.postSubmit}>
Publish To {this.props.notebook.title}
</button>
</div>
<input type="text"
style={{paddingBottom: 8, paddingTop: 24}}
className="w-100"
onChange={this.titleChange}
placeholder="New Post" />
<div style={{color:'#7F7F7F'}}>{date}</div>
</div>
<div className="NewPost">
<CodeMirror
value={this.state.body}
options={options}
onBeforeChange={(e, d, v) => this.bodyChange(e, d, v)}
onChange={(editor, data, value) => {}}
/>
</div>
</div>
)
}

View File

@ -6,8 +6,8 @@ import { NewScreen } from '/components/lib/new';
import { JoinScreen } from '/components/lib/join';
import { Notebook } from '/components/lib/notebook';
import { Note } from '/components/lib/note';
import { NewPost } from '/components/lib/new-post';
//TODO add new note route
export class Root extends Component {
constructor(props) {
super(props);
@ -78,20 +78,39 @@ export class Root extends Component {
let ship = props.match.params.ship || "";
let notebook = props.match.params.notebook || "";
return (
<Skeleton
popout={false}
active={"rightPanel"}
rightPanelHide={false}
sidebarShown={true}
notebooks={state.notebooks}>
<Notebook
notebooks={state.notebooks}
view={view}
ship={ship}
book={notebook}/>
</Skeleton>
)
if (view === "new") {
return (
<Skeleton
popout={false}
active={"rightPanel"}
rightPanelHide={false}
sidebarShown={true}
notebooks={state.notebooks}>
<NewPost
notebook={state.notebooks[ship][notebook]}
host={ship}
notebookName={notebook}
{...props}
/>
</Skeleton>
)
}
else {
return (
<Skeleton
popout={false}
active={"rightPanel"}
rightPanelHide={false}
sidebarShown={true}
notebooks={state.notebooks}>
<Notebook
notebooks={state.notebooks}
view={view}
ship={ship}
book={notebook}/>
</Skeleton>
)
}
}}/>
<Route exact path="/~publish/(popout)?/note/:ship/:notebook/:note"
render={ (props) => {