Merge pull request #2220 from urbit/ixv/publish/notebook-page

OS1: publish implement notebook page, changes to post page
This commit is contained in:
matildepark 2020-02-03 14:32:00 -05:00 committed by GitHub
commit 2df06777e6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 481 additions and 86 deletions

View File

@ -628,10 +628,12 @@
++ form-note
|= [note-name=@tas udon=@t]
^- note
=/ build=(each manx tang)
%- mule |.
^- manx
elm:(static:cram (ream udon))
=/ body=tape (slag (add 3 (need (find ";>" (trip udon)))) (trip udon))
=/ snippet=@t (of-wain:format (scag 1 (to-wain:format (crip body))))
:: =/ build=(each manx tang)
:: %- mule |.
:: ^- manx
:: elm:(static:cram (ream udon))
::
=/ meta=(each (map term knot) tang)
%- mule |.
@ -658,7 +660,7 @@
now.bol
%.n
udon
build
snippet
~
==
::

View File

@ -103,6 +103,7 @@
%- pairs
:~ title+s+title.book
date-created+(time date-created.book)
about+s+description.book
num-notes+(numb ~(wyt by notes.book))
num-unread+(numb (count-unread notes.book))
==
@ -113,6 +114,7 @@
=, enjs:format
%- pairs
:~ title+s+title.book
about+s+description.book
date-created+(time date-created.book)
num-notes+(numb ~(wyt by notes.book))
num-unread+(numb (count-unread notes.book))
@ -160,7 +162,7 @@
author+s+(scot %p author.note)
title+s+title.note
date-created+(time date-created.note)
build+(note-build-to-json build.note)
snippet+s+snippet.note
file+s+file.note
num-comments+(numb ~(wyt by comments.note))
comments+(comments-page comments.note 0 50)
@ -191,7 +193,7 @@
date-created+(time date-created.note)
num-comments+(numb ~(wyt by comments.note))
read+b+read.note
:: XX snippet
snippet+s+snippet.note
==
::
++ notes-page

View File

@ -40,7 +40,8 @@
last-edit=@da
read=?
file=@t
build=(each manx tang)
snippet=@t
:: build=(each manx tang)
comments=(map @da comment)
==
::

View File

@ -1835,7 +1835,8 @@
"ansi-regex": {
"version": "2.1.1",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"aproba": {
"version": "1.2.0",
@ -1856,12 +1857,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"
@ -1876,17 +1879,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",
@ -2003,7 +2009,8 @@
"inherits": {
"version": "2.0.3",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"ini": {
"version": "1.3.5",
@ -2015,6 +2022,7 @@
"version": "1.0.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@ -2029,6 +2037,7 @@
"version": "3.0.4",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@ -2036,12 +2045,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"
@ -2060,6 +2071,7 @@
"version": "0.5.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"minimist": "0.0.8"
}
@ -2140,7 +2152,8 @@
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"object-assign": {
"version": "4.1.1",
@ -2152,6 +2165,7 @@
"version": "1.4.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"wrappy": "1"
}
@ -2237,7 +2251,8 @@
"safe-buffer": {
"version": "5.1.2",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"safer-buffer": {
"version": "2.1.2",
@ -2273,6 +2288,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",
@ -2292,6 +2308,7 @@
"version": "3.0.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@ -2335,12 +2352,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
}
}
},

View File

@ -76,6 +76,20 @@ a {
}
}
.bg-light-green {
background: rgba(42, 167, 121, 0.1);
}
.NotebookButton {
padding: 8px 12px;
border-radius:2px;
cursor: pointer;
}
.NotebookTab {
padding: 16px 8px;
}
.NewPost {
width: 100%;
height: calc(100% - 103px);
@ -87,7 +101,6 @@ a {
width: 100%;
}
.CodeMirror {
padding: 12px;
height: 100% !important;
@ -153,3 +166,13 @@ a {
[contenteditable]:focus {
outline: 0px solid transparent;
}
.no-scrollbar {
-ms-overflow-style: none;
scrollbar-width: none;
}
.no-scrollbar::-webkit-scrollbar {
display: none;
}

View File

@ -6,9 +6,9 @@ import React, { Component } from 'react';
export class About extends Component {
render() {
return (
<div>
</div>
<p className="f8 lh-solid">
</p>
)
}
}

View File

@ -12,7 +12,6 @@ export class Comments extends Component {
this.commentChange = this.commentChange.bind(this);
}
commentSubmit(evt){
console.log ("this works")
let comment = {
"new-comment": {
who: this.props.ship.slice(1),

View File

@ -8,7 +8,7 @@ export class NewPost extends Component {
constructor(props) {
super(props);
this.state = {
body: "# Hello",
body: '',
title: '',
submit: false,
awaiting: null,
@ -23,7 +23,7 @@ export class NewPost extends Component {
let newNote = {
"new-note": {
who: this.props.host.slice(1),
book: this.props.notebookName,
book: this.props.book,
note: stringToSymbol(this.state.title),
title: this.state.title,
body: this.state.body,
@ -37,10 +37,15 @@ export class NewPost extends Component {
});
}
componentWillMount() {
window.api.fetchNotebook(this.props.ship, this.props.book);
}
componentDidUpdate(prevProps, prevState) {
if (this.props.notebook.notes[this.state.awaiting]) {
let notebook = this.props.notebooks[this.props.ship][this.props.book];
if (notebook.notes[this.state.awaiting]) {
let redirect =
`/~publish/note/${this.props.host}/${this.props.notebookName}/${this.state.awaiting}`;
`/~publish/note/${this.props.host}/${this.props.book}/${this.state.awaiting}`;
this.props.history.push(redirect);
}
}
@ -56,6 +61,8 @@ export class NewPost extends Component {
}
render() {
let notebook = this.props.notebooks[this.props.ship][this.props.book];
const options = {
mode: 'markdown',
theme: 'tlon',
@ -77,11 +84,11 @@ export class NewPost extends Component {
<div className="w-100 tl">
<button disabled={!this.state.submit} style={submitStyle}
onClick={this.postSubmit}>
Publish To {this.props.notebook.title}
Publish To {notebook.title}
</button>
</div>
<input type="text"
<input autoFocus type="text"
style={{paddingBottom: 8, paddingTop: 24}}
className="w-100"
onChange={this.titleChange}

View File

@ -6,7 +6,6 @@ import { Link } from 'react-router-dom';
export class NoteNavigation extends Component {
constructor(props) {
super(props)
console.log(props)
}
render() {
@ -16,10 +15,8 @@ export class NoteNavigation extends Component {
let prevUrl = ''
if (this.props.next && this.props.prev) {
console.log("both")
nextUrl = `/~publish/note/${this.props.ship}/${this.props.book}/${this.props.next.id}`;
prevUrl = `/~publish/note/${this.props.ship}/${this.props.book}/${this.props.prev.id}`;
console.log(this.props.prev.prevId);
nextComponent =
<Link to={nextUrl} className="di flex-column tr w-100 pv6 bt bb b--gray3">
<div className="f9 gray2 mb2">Next</div>
@ -35,8 +32,6 @@ export class NoteNavigation extends Component {
</Link>
} else if (this.props.prev) {
console.log("prev")
console.log(this.props.prev.prevId);
prevUrl = `/~publish/note/${this.props.ship}/${this.props.book}/${this.props.prev.id}`;
prevComponent =
<Link to={prevUrl} className="di flex-column w-100 pv6 bt bb b--gray3">
@ -44,9 +39,7 @@ export class NoteNavigation extends Component {
<div className="f9 mb1">{this.props.prev.title}</div>
<div className="f9 gray2">{this.props.prev.date}</div>
</Link>
console.log(prevComponent)
} else if (this.props.next) {
console.log("next")
nextUrl = `/~publish/note/${this.props.ship}/${this.props.book}/${this.props.next.id}`;
nextComponent =
<Link to={nextUrl} className="di flex-column tr w-100 pv6 bt bb b--gray3">
@ -57,9 +50,6 @@ console.log(prevComponent)
}
return (
<div className="flex mt4">
{prevComponent}

View File

@ -11,7 +11,6 @@ import ReactMarkdown from 'react-markdown'
export class Note extends Component {
constructor(props){
super(props);
console.log(this.props);
moment.updateLocale('en', {
relativeTime: {
past: function(input) {
@ -33,36 +32,99 @@ export class Note extends Component {
yy : '%d years',
}
});
this.scrollElement = React.createRef();
this.onScroll = this.onScroll.bind(this);
}
componentWillMount() {
window.api.fetchNote(this.props.ship, this.props.book, this.props.note);
}
componentDidUpdate(prevProps) {
if (!(this.props.notebooks[this.props.ship]) ||
!(this.props.notebooks[this.props.ship][this.props.book]) ||
!(this.props.notebooks[this.props.ship][this.props.book].notes[this.props.note]) ||
!(this.props.notebooks[this.props.ship][this.props.book].notes[this.props.note].file))
{
window.api.fetchNote(this.props.ship, this.props.book, this.props.note);
}
}
onScroll() {
let notebook = this.props.notebooks[this.props.ship][this.props.book];
let note = notebook.notes[this.props.note];
if (!note.comments) {
return;
}
let scrollTop = this.scrollElement.scrollTop;
let clientHeight = this.scrollElement.clientHeight;
let scrollHeight = this.scrollElement.scrollHeight;
let atBottom = false;
if (scrollHeight - scrollTop - clientHeight < 40) {
atBottom = true;
}
let loadedComments = note.comments.length;
let allComments = note["num-comments"];
let fullyLoaded = (loadedComments === allComments);
if (atBottom && !fullyLoaded) {
window.api.fetchCommentsPage(this.props.ship,
this.props.book, this.props.note, loadedComments, 30);
}
}
componentDidMount() {
if (!(this.props.notebooks[this.props.ship]) ||
!(this.props.notebooks[this.props.ship][this.props.book]) ||
!(this.props.notebooks[this.props.ship][this.props.book].notes[this.props.note]) ||
!(this.props.notebooks[this.props.ship][this.props.book].notes[this.props.note].file))
{
window.api.fetchNote(this.props.ship, this.props.book, this.props.note);
}
this.onScroll();
}
render() {
let comments = this.props.notebook.notes[this.props.note].comments;
let title = this.props.notebook.notes[this.props.note].title;
let author = this.props.notebook.notes[this.props.note].author;
let file = this.props.notebook.notes[this.props.note].file;
let date = moment(this.props.notebook.notes[this.props.note]["date-created"]).fromNow();
let notebook = this.props.notebooks[this.props.ship][this.props.book];
let comments = notebook.notes[this.props.note].comments;
let title = notebook.notes[this.props.note].title;
let author = notebook.notes[this.props.note].author;
let file = notebook.notes[this.props.note].file;
let date = moment(notebook.notes[this.props.note]["date-created"]).fromNow();
if (!file) {
return null;
}
let newfile = file.slice(file.indexOf(';>')+2);
let prevId = this.props.notebook.notes[this.props.note]["prev-note"];
let nextId = this.props.notebook.notes[this.props.note]["next-note"];
let prevId = notebook.notes[this.props.note]["prev-note"];
let nextId = notebook.notes[this.props.note]["next-note"];
let prev = (prevId === null)
? null
: {
id: prevId,
title: this.props.notebook.notes[prevId].title,
date: moment(this.props.notebook.notes[prevId]["date-created"]).fromNow()
title: notebook.notes[prevId].title,
date: moment(notebook.notes[prevId]["date-created"]).fromNow()
}
let next = (nextId === null)
? null
: {
id: nextId,
title: this.props.notebook.notes[nextId].title,
date: moment(this.props.notebook.notes[nextId]["date-created"]).fromNow()
title: notebook.notes[nextId].title,
date: moment(notebook.notes[nextId]["date-created"]).fromNow()
}
return (
<div className="h-100 overflow-container">
<div className="h-100 overflow-container no-scrollbar"
onScroll={this.onScroll}
ref={(el) => {this.scrollElement = el}}>
<div className="flex justify-center mt4 ph4 pb4">
<div className="w-100 mw6">
<div className="flex flex-column">
@ -79,8 +141,10 @@ export class Note extends Component {
next={next}
ship={this.props.ship}
book={this.props.book}/>
<Comments ship={this.props.ship} book={this.props.book} note={this.props.note} comments={comments}/>
<Comments ship={this.props.ship}
book={this.props.book}
note={this.props.note}
comments={comments}/>
</div>
</div>
</div>

View File

@ -0,0 +1,74 @@
import React, { Component } from 'react';
import moment from 'moment';
import { Link } from 'react-router-dom';
import ReactMarkdown from 'react-markdown'
export class NotebookPosts extends Component {
constructor(props){
super(props);
moment.updateLocale('en', {
relativeTime: {
past: function(input) {
return input === 'just now'
? input
: input + ' ago'
},
s : 'just now',
future : 'in %s',
m : '1m',
mm : '%dm',
h : '1h',
hh : '%dh',
d : '1d',
dd : '%dd',
M : '1 month',
MM : '%d months',
y : '1 year',
yy : '%d years',
}
});
}
render() {
let notes = [];
for (var i=0; i<this.props.list.length; i++) {
let noteId = this.props.list[i];
let note = this.props.notes[noteId];
if (!note) {
break;
}
let comment = "No Comments";
if (note["num-comments"] == 1) {
comment = "1 Comment";
} else if (note["num-comments"] > 1) {
comment = `${note["num-comments"]} Comments`;
}
let date = moment(note["date-created"]).fromNow();
let url = `/~publish/note/${this.props.host}/${this.props.notebookName}/${noteId}`
notes.push(
<Link key={i} to={url}>
<div className="mv6">
<div className="mb1">{note.title}</div>
<p className="mb1">{note.snippet}</p>
<div className="flex">
<div className="mono gray2 mr3">{note.author}</div>
<div className="gray2 mr3">{date}</div>
<div className="gray2">{comment}</div>
</div>
</div>
</Link>
)
}
return (
<div className="flex-col">
{notes}
</div>
);
}
}
export default NotebookPosts

View File

@ -1,27 +1,152 @@
import React, { Component } from 'react';
import { Link, Switch, Route } from 'react-router-dom';
import { NoteList } from './note-list';
import { NotebookPosts } from './notebook-posts';
import { About } from './about';
import { Subscribers } from './subscribers';
import { Settings } from './settings';
//TODO subcomponents for posts, subscribers, settings
//
//TODO props.view switch for which component to render
//pass props.notebook, contacts to each component
//TODO ask for notebook if we don't have it
//
//TODO initialise notebook obj if no props.notebook
//TODO component bar above the rendered component
//don't render settings if it's ours
//current component is black, others gray2 (see Chat's tab bar for an example)
//TODO subcomponent logic for subscribers, settings
export class Notebook extends Component {
render() {
return (
<div>
constructor(props){
super(props);
this.onScroll = this.onScroll.bind(this);
this.unsubscribe = this.unsubscribe.bind(this);
}
onScroll() {
let notebook = this.props.notebooks[this.props.ship][this.props.book];
let scrollTop = this.scrollElement.scrollTop;
let clientHeight = this.scrollElement.clientHeight;
let scrollHeight = this.scrollElement.scrollHeight;
let atBottom = false;
if (scrollHeight - scrollTop - clientHeight < 40) {
atBottom = true;
}
let loadedNotes = Object.keys(notebook.notes).length;
let allNotes = notebook["notes-by-date"].length;
let fullyLoaded = (loadedNotes === allNotes);
if (atBottom && !fullyLoaded) {
window.api.fetchNotesPage(this.props.ship, this.props.book, loadedNotes, 30);
}
}
componentWillMount(){
window.api.fetchNotebook(this.props.ship, this.props.book);
}
componentDidMount() {
if (this.props.notebooks[this.props.ship][this.props.book].notes) {
this.onScroll();
}
}
unsubscribe() {
let action = {
unsubscribe: {
who: this.props.ship.slice(1),
book: this.props.book,
}
}
window.api.action("publish", "publish-action", action);
this.props.history.push("/~publish");
}
render() {
let notebook = this.props.notebooks[this.props.ship][this.props.book];
let tabStyles = {
posts: "bb b--gray4 gray2 NotebookTab",
about: "bb b--gray4 gray2 NotebookTab",
// subscribers: "bb b--gray4 gray2 NotebookTab",
// settings: "bb b--gray4 pr2 gray2 NotebookTab",
}
tabStyles[this.props.view] = "bb b--black black NotebookTab";
let inner = null;
switch (this.props.view) {
case "posts":
let notesList = notebook["notes-by-date"] || [];
let notes = notebook.notes || null;
inner = <NotebookPosts notes={notes}
list={notesList}
host={this.props.ship}
notebookName={this.props.book}/>
break;
case "about":
inner = <p className="f8 lh-solid">{notebook.about}</p>
break;
// case "subscribers":
// inner = <Subscribers/>
// break;
// case "settings":
// inner = <Settings/>
// break;
default:
break;
}
let base = `/~publish/notebook/${this.props.ship}/${this.props.book}`;
let about = base + '/about';
let subs = base + '/subscribers';
let settings = base + '/settings';
let newUrl = base + '/new';
let newPost = !(window.ship === this.props.ship.slice(1))
// XX TODO check based on authorized writers instead
? null
: <Link to={newUrl} className="NotebookButton bg-light-green green2">
New Post
</Link>
let unsub = (window.ship === this.props.ship.slice(1))
? null
: <button onClick={this.unsubscribe}
className="NotebookButton bg-white black ba b--black ml3">
Unsubscribe
</button>
return (
<div className="center mw6 f9 h-100"
style={{paddingLeft:16, paddingRight:16}}>
<div className="h-100 overflow-container no-scrollbar"
onScroll={this.onScroll}
ref={(el) => {this.scrollElement = el}}>
<div className="flex justify-between"
style={{marginTop: 56, marginBottom: 32}}>
<div className="flex-col">
<div className="mb1">{notebook.title}</div>
<span><span className="gray3 mr1">by</span>
<span className="mono">
{this.props.ship}
</span>
</span>
</div>
<div className="flex">
{newPost}
{unsub}
</div>
</div>
<div className="flex" style={{marginBottom:24}}>
<Link to={base} className={tabStyles.posts}>
All Posts
</Link>
<Link to={about} className={tabStyles.about}>
About
</Link>
<div className="bb b--gray4 gray2 NotebookTab" style={{flexGrow:1}}>
</div>
</div>
<div style={{height:"calc(100% - 188px)"}} className="f9 lh-solid">
{inner}
</div>
</div>
</div>
)
}

View File

@ -5,8 +5,36 @@ export class Settings extends Component {
render() {
return (
<div>
<div className="flex flex-column mb8">
<label for="name" className="f9">Share</label>
<small id="name-desc" className="f9 mb2 gray3">Share a link to this notebook</small>
<div className="flex">
<input style={{flex: "1"}} id="name" placeholder="dopzod.arvo.network/4f5hsS" className="input-reset bt bl bb pa3 gray4" type="text" aria-describedby="name-desc"/>
<button className="bt br bb pa3 b--gray4">Copy</button>
</div>
</div>
<div className="flex flex-column mb8">
<label for="name" className="f9">Rename</label>
<small id="name-desc" className="f9 mb2 gray3">Change the name of this notebook</small>
<div className="flex">
<input style={{flex: "1"}} id="name" placeholder="Notebook Name" className="input-reset ba pa3 gray4" type="text" aria-describedby="name-desc"/>
</div>
</div>
<div className="flex flex-column">
<label for="name" className="f9">Export</label>
<small id="name-desc" className="f9 mb2 gray3">Change the name of this notebook</small>
<button className="bg-black white pa3">
<div className="flex justify-between">
<div>Export Notebook</div>
<div></div>
</div>
</button>
</div>
</div>
)
}
}

View File

@ -7,7 +7,47 @@ export class Subscribers extends Component {
render() {
return (
<div>
<div className="flex flex-column">
<div className="f9 gray2">Host</div>
<div className="flex justify-between mt3">
<div className="flex">
<div className="f9 mono mr2">~fabled-faster</div>
<div className="f9 gray2">Last active</div>
</div>
<div className="f9">Options </div>
</div>
</div>
<div className="flex flex-column">
<div className="f9 gray2 mt6">Participants (read and write access)</div>
<div className="f9 mt3">There are no paticipants in this notebook.</div>
<div className="flex justify-between mt3">
<div className="flex">
<div className="f9 mono mr2">~fabled-faster</div>
<div className="f9 gray2">Last active</div>
</div>
<div className="f9">Options </div>
</div>
</div>
<div className="flex flex-column">
<div className="f9 gray2 mt6 mb3">Subscribers (read access only)</div>
<div className="flex justify-between">
<div className="flex">
<div className="f9 mono mr2">~fabled-faster</div>
<div className="f9 gray2">Last active</div>
</div>
<div className="f9">Options </div>
</div>
</div>
<div className="flex flex-column">
<div className="f9 gray2 mt6 mb3">Banned</div>
<div className="flex justify-between">
<div className="flex">
<div className="f9 mono mr2">~fabled-faster</div>
<div className="f9 gray2">Last active</div>
</div>
<div className="f9">Options </div>
</div>
</div>
</div>
)
}

View File

@ -87,9 +87,9 @@ export class Root extends Component {
sidebarShown={true}
notebooks={state.notebooks}>
<NewPost
notebook={state.notebooks[ship][notebook]}
notebooks={state.notebooks}
host={ship}
notebookName={notebook}
book={notebook}
{...props}
/>
</Skeleton>
@ -104,10 +104,11 @@ export class Root extends Component {
sidebarShown={true}
notebooks={state.notebooks}>
<Notebook
notebooks={state.notebooks}
view={view}
ship={ship}
book={notebook}/>
notebooks={state.notebooks}
view={view}
ship={ship}
book={notebook}
{...props}/>
</Skeleton>
)
}
@ -126,10 +127,10 @@ export class Root extends Component {
sidebarShown={true}
notebooks={state.notebooks}>
<Note
notebook={state.notebooks[ship][notebook]}
book={notebook}
ship={ship}
note={note}/>
notebooks={state.notebooks}
book={notebook}
ship={ship}
note={note}/>
</Skeleton>
)
}}/>

View File

@ -2,7 +2,6 @@ import _ from 'lodash';
export class PrimaryReducer {
reduce(json, state){
console.log("primaryReducer", json);
switch(Object.keys(json)[0]){
case "add-book":
this.addBook(json["add-book"], state);

View File

@ -2,7 +2,6 @@ import _ from 'lodash';
export class ResponseReducer {
reduce(json, state) {
console.log("responseReducer", json);
switch(json.type) {
case "notebooks":
this.handleNotebooks(json, state);
@ -155,8 +154,30 @@ export class ResponseReducer {
state.notebooks[json.host][json.notebook].notes[json.note])
{
if (state.notebooks[json.host][json.notebook].notes[json.note].comments) {
state.notebooks[json.host][json.notebook].notes[json.note].comments
.concat(json.data);
json.data.forEach((val, i) => {
let newKey = Object.keys(val)[0];
let newDate = val[newKey]["date-created"]
let oldComments = state.notebooks[json.host][json.notebook].notes[json.note].comments;
let insertIdx = -1;
for (var j=0; j<oldComments.length; j++) {
let oldKey = Object.keys(oldComments[j])[0];
let oldDate = oldComments[j][oldKey]["date-created"];
if (oldDate === newDate) {
break;
} else if (oldDate < newDate) {
insertIdx = j;
} else if ((oldDate > newDate) &&
(j === oldComments.length-1)){
insertIdx = j+1;
}
}
if (insertIdx !== -1) {
state.notebooks[json.host][json.notebook].notes[json.note].comments
.splice(insertIdx, 0, val);
}
});
} else {
state.notebooks[json.host][json.notebook].notes[json.note].comments =
json.data;