added js reducers

This commit is contained in:
Isaac Visintainer 2019-12-18 14:45:37 -08:00
parent e807e6c223
commit d4ae9dbcc8
12 changed files with 712 additions and 492 deletions

View File

@ -42,7 +42,6 @@
$: our-paths=(list path)
books=(map @tas notebook)
subs=(map [@p @tas] notebook)
unread=(set [@p @tas @tas])
==
--
::
@ -273,9 +272,9 @@
=/ comment-date (slaw %da i.t.t.t.t.t.pax)
?~ comment-date
[~ state]
=/ book-name i.t.t.t.pax
=/ note-name i.t.t.t.t.pax
=/ new-comment !<(comment q.r.u.rot)
=/ book-name i.t.t.t.pax
=/ note-name i.t.t.t.t.pax
=/ new-comment !<(comment q.r.u.rot)
=/ rif=riff:clay [q.byk.bol `[%next %x [%da now.bol] pax]]
=/ delta=notebook-delta
[%edit-comment our.bol book-name note-name u.comment-date new-comment]
@ -508,6 +507,7 @@
note-name
now.bol
now.bol
%.n
udon
build
~
@ -701,9 +701,9 @@
writers-path
subscribers-path
==
=/ pax=path /app/publish/notebooks/[book.act]
=/ pax=path /app/publish/notebooks/[book.act]/publish-info
:_ state
[(write-file pax %publish-info !>(notebook-info)) cards]
[(write-file pax %publish-info !>(new-info)) cards]
::
%edit-note
?: &(=(src.bol our.bol) !=(our.bol who.act))
@ -765,8 +765,11 @@
%unsubscribe
?> (team:title our.bol src.bol)
=/ wir=wire /subscribe/(scot %p who.act)/[book.act]
=/ del=primary-delta [%del-book who.act book.act]
:_ state(subs (~(del by subs) who.act book.act))
[%pass wir %agent [who.act %publish] %leave ~]~
:~ [%pass wir %agent [who.act %publish] %leave ~]
[%give %fact `/primary %publish-primary-delta !>(del)]
==
==
::
++ get-notebook
@ -799,6 +802,7 @@
(get-notebook host.del book.del)
?~ book
[~ state]
=. read.data.del =(our.bol author.data.del)
=. notes.u.book (~(put by notes.u.book) note.del data.del)
(emit-updates-and-state host.del book.del u.book del)
::
@ -824,7 +828,6 @@
date-created date-created.u.old-book
notes notes.u.old-book
order order.u.old-book
pinned pinned.u.old-book
==
(emit-updates-and-state host.del book.del new-book del)
::
@ -840,6 +843,7 @@
%= data.del
date-created date-created.u.old-note
comments comments.u.old-note
read read.u.old-note
==
=. notes.u.book (~(put by notes.u.book) note.del new-note)
(emit-updates-and-state host.del book.del u.book del)
@ -915,7 +919,7 @@
[[[~ %json] [%'~publish' %notebooks ~]] ~]
%- json-response:gen
%- json-to-octs
(notebooks-list-json our.bol books subs)
(notebooks-map-json our.bol books subs)
::
:: notes pagination
[[[~ %json] [%'~publish' %notes @ @ @ @ ~]] ~]
@ -937,6 +941,7 @@
not-found:gen
%- json-response:gen
%- json-to-octs
:- %o
(notes-page notes.u.book u.start u.length)
::
:: comments pagination
@ -965,15 +970,52 @@
%- json-to-octs
(comments-page comments.u.note u.start u.length)
::
:: single notebook with initial 50 notes in short form, as json
[[[~ %json] [%'~publish' @ @ ~]] ~]
=, enjs:format
=/ host=(unit @p) (slaw %p i.t.site.url)
?~ host
not-found:gen
=/ book-name i.t.t.site.url
=/ book=(unit notebook)
?: =(our.bol u.host)
(~(get by books) book-name)
(~(get by subs) u.host book-name)
?~ book
not-found:gen
=/ notebook-json (notebook-full-json u.host book-name u.book)
?> ?=(%o -.notebook-json)
=. p.notebook-json
(~(uni by p.notebook-json) (notes-page notes.u.book 0 50))
=/ jon=json (pairs notebook+notebook-json ~)
(json-response:gen (json-to-octs jon))
::
:: single note, with initial 50 comments, as json
[[[~ %json] [%'~publish' @ @ @ ~]] ~]
=, enjs:format
=/ host=(unit @p) (slaw %p i.t.site.url)
?~ host
not-found:gen
=/ book-name i.t.t.site.url
=/ book=(unit notebook)
?: =(our.bol u.host)
(~(get by books) book-name)
(~(get by subs) u.host book-name)
?~ book
not-found:gen
=/ note-name i.t.t.t.site.url
=/ note=(unit note) (~(get by notes.u.book) note-name)
?~ note
not-found:gen
=/ jon=json o+(note-presentation-json u.book note-name u.note)
(json-response:gen (json-to-octs jon))
::
:: presentation endpoints
::
:: all notebooks, short form, wrapped in html
[[~ [%'~publish' ~]] ~]
=, enjs:format
=/ jon=json
%- pairs
:~ notebooks+(notebooks-list-json our.bol books subs)
==
=/ jon=json (pairs notebooks+(notebooks-map-json our.bol books subs) ~)
(manx-response:gen (index jon))
::
:: single notebook, with initial 50 notes in short form, wrapped in html
@ -989,12 +1031,18 @@
(~(get by subs) u.host book-name)
?~ book
not-found:gen
=/ jon=json
%- pairs
:~ notebooks+(notebooks-list-json our.bol books subs)
notebook+(notebook-full-json u.host book-name u.book)
notes+(notes-page notes.u.book 0 50)
==
=/ notebook-json (notebook-full-json u.host book-name u.book)
?> ?=(%o -.notebook-json)
=. p.notebook-json
(~(uni by p.notebook-json) (notes-page notes.u.book 0 50))
=/ notebooks-json (notebooks-map-json our.bol books subs)
?> ?=(%o -.notebooks-json)
=/ host-books-json (~(got by p.notebooks-json) (scot %p u.host))
?> ?=(%o -.host-books-json)
=. p.host-books-json (~(put by p.host-books-json) book-name notebook-json)
=. p.notebooks-json
(~(put by p.notebooks-json) (scot %p u.host) host-books-json)
=/ jon=json (pairs notebooks+notebooks-json ~)
(manx-response:gen (index jon))
::
:: single note, with initial 50 comments, wrapped in html
@ -1014,14 +1062,18 @@
=/ note=(unit note) (~(get by notes.u.book) note-name)
?~ note
not-found:gen
=/ jon=json
%- pairs
:~ notebooks+(notebooks-list-json our.bol books subs)
notebook+(notebook-full-json u.host book-name u.book)
notes+(notes-page notes.u.book 0 50)
note+(note-full-json u.host book-name note-name u.note)
comments+(comments-page comments.u.note 0 50)
==
=/ notebook-json (notebook-full-json u.host book-name u.book)
?> ?=(%o -.notebook-json)
=/ note-json (note-presentation-json u.book note-name u.note)
=. p.notebook-json (~(uni by p.notebook-json) note-json)
=/ notebooks-json (notebooks-map-json our.bol books subs)
?> ?=(%o -.notebooks-json)
=/ host-books-json (~(got by p.notebooks-json) (scot %p u.host))
?> ?=(%o -.host-books-json)
=. p.host-books-json (~(put by p.host-books-json) book-name notebook-json)
=. p.notebooks-json
(~(put by p.notebooks-json) (scot %p u.host) host-books-json)
=/ jon=json (pairs notebooks+notebooks-json ~)
(manx-response:gen (index jon))
==
::

View File

@ -37,6 +37,15 @@
result+(tang-to-json p.build)
==
::
++ count-unread
|= notes=(map @tas note)
^- @ud
%- ~(rep by notes)
|= [[key=@tas val=note] count=@ud]
?: read.val
count
+(count)
::
++ notebooks-list-json
|= [our=@p books=(map @tas notebook) subs=(map [@p @tas] notebook)]
^- json
@ -45,92 +54,164 @@
%+ weld
%+ turn ~(tap by books)
|= [name=@tas book=notebook]
(notebook-short-json our name book)
(notebook-short-json book)
%+ turn ~(tap by subs)
|= [[host=@p name=@tas] book=notebook]
(notebook-short-json host name book)
(notebook-short-json book)
::
++ notebooks-map-json
|= [our=@p books=(map @tas notebook) subs=(map [@p @tas] notebook)]
^- json
=, enjs:format
=/ subs-notebooks-map=json
%- ~(rep by subs)
|= [[[host=@p book-name=@tas] book=notebook] out=json]
^- json
=/ host-ta (scot %p host)
?~ out
(frond host-ta (frond book-name (notebook-short-json book)))
?> ?=(%o -.out)
=/ books (~(get by p.out) host-ta)
?~ books
:- %o
(~(put by p.out) host-ta (frond book-name (notebook-short-json book)))
?> ?=(%o -.u.books)
=. p.u.books (~(put by p.u.books) book-name (notebook-short-json book))
:- %o
(~(put by p.out) host-ta u.books)
=? subs-notebooks-map ?=(~ subs-notebooks-map)
[%o ~]
=/ our-notebooks-map=json
%- ~(rep by books)
|= [[book-name=@tas book=notebook] out=json]
^- json
?~ out
(frond book-name (notebook-short-json book))
?> ?=(%o -.out)
:- %o
(~(put by p.out) book-name (notebook-short-json book))
?~ our-notebooks-map
subs-notebooks-map
?> ?=(%o -.subs-notebooks-map)
:- %o
(~(put by p.subs-notebooks-map) (scot %p our) our-notebooks-map)
::
++ notebook-short-json
|= book=notebook
^- json
=, enjs:format
%- pairs
:~ title+s+title.book
date-created+(time date-created.book)
num-notes+(numb ~(wyt by notes.book))
num-unread+(numb (count-unread notes.book))
==
::
++ notebook-full-json
|= [host=@p book-name=@tas book=notebook]
^- json
=, enjs:format
%- pairs
:~ host+(ship host)
id+s+book-name
title+s+title.book
:~ title+s+title.book
date-created+(time date-created.book)
num-notes+(numb ~(wyt by notes.book))
num-unread+(numb (count-unread notes.book))
notes-by-date+(notes-by-date notes.book)
:: XX settings stuff, subscribers
==
::
++ notebook-full-json
|= [host=@p name=@tas book=notebook]
^- json
++ note-presentation-json
|= [book=notebook note-name=@tas not=note]
^- (map @t json)
=, enjs:format
%- pairs
:~ host+(ship host)
id+s+name
title+s+title.book
date-created+(time date-created.book)
:: subscribers
:: notes
==
::
++ note-short-json
|= [host=@p book-name=@tas note-name=@tas =note]
^- json
=, enjs:format
%- pairs
:~ host+(ship host)
book-id+s+book-name
note-id+s+note-name
author+(ship author.note)
title+s+title.note
date-created+(time date-created.note)
num-comments+(numb ~(wyt by comments.note))
=/ notes-list=(list [@tas note])
%+ sort ~(tap by notes.book)
|= [[@tas n1=note] [@tas n2=note]]
(gte date-created.n1 date-created.n2)
=/ idx=@ (need (find [note-name not]~ notes-list))
=/ next=(unit [name=@tas not=note])
?: =(idx 0) ~
`(snag (dec idx) notes-list)
=/ prev=(unit [name=@tas not=note])
?: =(+(idx) (lent notes-list)) ~
`(snag +(idx) notes-list)
=/ current=json (note-full-json note-name not)
?> ?=(%o -.current)
=. p.current (~(put by p.current) %prev-note ?~(prev ~ s+name.u.prev))
=. p.current (~(put by p.current) %next-note ?~(next ~ s+name.u.next))
=/ notes=(list [@t json]) [note-name current]~
=? notes ?=(^ prev)
[[name.u.prev (note-short-json name.u.prev not.u.prev)] notes]
=? notes ?=(^ next)
[[name.u.next (note-short-json name.u.next not.u.next)] notes]
%- my
:~ notes+(pairs notes)
notes-by-date+a+(turn notes-list |=([name=@tas *] s+name))
==
::
++ note-full-json
|= [host=@p book-name=@tas note-name=@tas =note]
|= [note-name=@tas =note]
^- json
=, enjs:format
%- pairs
:~ host+(ship host)
book-id+s+book-name
note-id+s+note-name
author+(ship author.note)
:~ note-id+s+note-name
author+s+(scot %p author.note)
title+s+title.note
date-created+(time date-created.note)
build+(note-build-to-json build.note)
file+s+file.note
num-comments+(numb ~(wyt by comments.note))
comments+(comments-page comments.note 0 50)
read+b+read.note
==
::
++ notes-page
|= [notes=(map @tas note) start=@ud length=@ud]
++ notes-by-date
|= notes=(map @tas note)
^- json
=/ notes-list=(list [@tas note])
%+ sort ~(tap by notes)
|= [[@tas n1=note] [@tas n2=note]]
(gte date-created.n1 date-created.n2)
%- notes-list-json
(scag length (slag start notes-list))
::
++ notes-list-json
|= notes=(list [@tas note])
^- json
=, enjs:format
:- %a
%+ turn notes
%+ turn notes-list
|= [name=@tas note]
^- json
[%s name]
::
++ note-short-json
|= [note-name=@tas =note]
^- json
=, enjs:format
%- pairs
:~ note-id+s+note-name
author+(ship author.note)
author+s+(scot %p author.note)
title+s+title.note
date-created+(time date-created.note)
num-comments+(numb ~(wyt by comments.note))
:: snippet
read+b+read.note
:: XX snippet
==
::
++ notes-page
|= [notes=(map @tas note) start=@ud length=@ud]
^- (map @t json)
=/ notes-list=(list [@tas note])
%+ sort ~(tap by notes)
|= [[@tas n1=note] [@tas n2=note]]
(gte date-created.n1 date-created.n2)
%- my
:~ notes-by-date+a+(turn notes-list |=([name=@tas *] s+name))
notes+o+(notes-list-json (scag length (slag start notes-list)))
==
::
++ notes-list-json
|= notes=(list [@tas note])
^- (map @t json)
%+ roll notes
|= [[name=@tas not=note] out-map=(map @t json)]
^- (map @t json)
(~(put by out-map) name (note-short-json name not))
::
++ comments-page
|= [comments=(map @da comment) start=@ud end=@ud]
^- json
@ -155,7 +236,7 @@
%+ frond:enjs:format
(scot %da date)
%- pairs
:~ author+(ship author.com)
:~ author+s+(scot %p author.com)
date-created+(time date-created.com)
content+s+content.com
==

View File

@ -2,7 +2,7 @@
:::: /hoon/action/publish/mar
::
/- *publish
=, format
/+ *publish
::
|_ del=primary-delta
::
@ -13,58 +13,64 @@
++ grow
|%
++ json
=, enjs:format
%+ frond -.del
%+ frond:enjs:format -.del
?- -.del
%add-book
(notebook-short-json host.del book.del data.del)
%+ frond:enjs:format (scot %p host.del)
%+ frond:enjs:format book.del
(notebook-short-json data.del)
::
%add-note
(note-short-json host.del book.del note.del data.del)
%+ frond:enjs:format (scot %p host.del)
%+ frond:enjs:format book.del
(note-full-json note.del data.del)
::
%add-comment
%- pairs:enjs:format
:~ host+(ship host.del)
:~ host+s+(scot %p host.del)
book+s+book.del
note+s+note.del
comment+s+(scot %da comment-date.del)
data+(comment-json data.del)
comment+(comment-json comment-date.del data.del)
==
::
%edit-book
(notebook-short-json host.del book.del data.del)
%+ frond:enjs:format (scot %p host.del)
%+ frond:enjs:format book.del
(notebook-short-json data.del)
::
%edit-note
(note-short-json host.del book.del note.del data.del)
%+ frond:enjs:format (scot %p host.del)
%+ frond:enjs:format book.del
(note-full-json note.del data.del)
::
%edit-comment
%- pairs:enjs:format
:~ host+(ship host.del)
:~ host+s+(scot %p host.del)
book+s+book.del
note+s+note.del
comment+s+(scot %da comment-date.del)
comment+(comment-json data.del)
comment+(comment-json comment-date.del data.del)
==
::
%del-book
%- pairs:enjs:format
:~ host+(ship host.del)
:~ host+s+(scot %p host.del)
book+s+book.del
==
::
%del-note
%- pairs:enjs:format
:~ host+(ship host.del)
:~ host+s+(scot %p host.del)
book+s+book.del
note+s+note.del
==
::
%del-comment
%- pairs:enjs:format
:~ host+(ship host.del)
:~ host+s+(scot %p host.del)
book+s+book.del
note+s+note.del
comment+s+(scot %da date-created.del)
comment+s+(scot %da comment.del)
==
--
==
--
--

View File

@ -35,6 +35,7 @@
filename=@tas
date-created=@da
last-edit=@da
read=?
file=@t
build=(each manx tang)
comments=(map @da comment)
@ -49,7 +50,7 @@
date-created=@da
notes=(map @tas note)
order=(list @tas)
pinned=(set @tas)
unread=(set @tas)
==
::
+$ notebook-info

View File

@ -42,6 +42,83 @@ class UrbitApi {
});
});
}
// TODO add error handling
handleErrors(response) {
if (!response.ok) throw Error(response.status);
return response;
}
fetchNotebooks() {
fetch('/~publish/notebooks.json')
.then((response) => response.json())
.then((json) => {
store.handleEvent({
type: 'notebooks',
data: json,
});
});
}
fetchNotebook(host, book) {
fetch(`/~publish/${host}/${book}.json`)
.then((response) => response.json())
.then((json) => {
store.handleEvent({
type: 'notebook',
data: json,
host: host,
notebook: book,
});
});
}
fetchNote(host, book, note) {
fetch(`/~publish/${host}/${book}/${note}.json`)
.then((response) => response.json())
.then((json) => {
store.handleEvent({
type: 'note',
data: json,
host: host,
notebook: book,
note: note,
});
});
}
fetchNotesPage(host, book, start, length) {
fetch(`/~publish/notes/${host}/${book}/${start}/${length}.json`)
.then((response) => response.json())
.then((json) => {
store.handleEvent({
type: 'notes-page',
data: json,
host: host,
notebook: book,
startIndex: start,
length: length,
});
});
}
fetchCommentsPage(host, book, note, start, length) {
fetch(`/~publish/comments/${host}/${book}/${note}/${start}/${length}.json`)
.then((response) => response.json())
.then((json) => {
store.handleEvent({
type: 'comments-page',
data: json,
host: host,
notebook: book,
note: note,
startIndex: start,
length: length,
});
});
}
}
export let api = new UrbitApi();

View File

@ -0,0 +1,7 @@
import _ from 'lodash';
export class InitialReducer {
reduce(json, state) {
state.notebooks = json.notebooks || null;
}
}

View File

@ -0,0 +1,213 @@
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);
break;
case "add-note":
this.addNote(json["add-note"], state);
break;
case "add-comment":
this.addComment(json["add-comment"], state);
break;
case "edit-book":
this.editBook(json["edit-book"], state);
break;
case "edit-note":
this.editNote(json["edit-note"], state);
break;
case "edit-comment":
this.editComment(json["edit-comment"], state);
break;
case "del-book":
this.delBook(json["del-book"], state);
break;
case "del-note":
this.delNote(json["del-note"], state);
break;
case "del-comment":
this.delComment(json["del-comment"], state);
break;
default:
break;
}
}
addBook(json, state) {
let host = Object.keys(json)[0];
let book = Object.keys(json[host])[0];
if (state.notebooks[host]) {
state.notebooks[host][book] = json[host][book];
} else {
state.notebooks[host] = json[host];
}
}
addNote(json, state) {
let host = Object.keys(json)[0];
let book = Object.keys(json[host])[0];
let noteId = json[host][book]["note-id"];
if (state.notebooks[host] && state.notebooks[host][book]) {
if (state.notebooks[host][book]["notes-by-date"]) {
state.notebooks[host][book]["notes-by-date"].unshift(noteId);
} else {
state.notebooks[host][book]["notes-by-date"] = [noteId];
}
if (state.notebooks[host][book].notes) {
state.notebooks[host][book].notes[noteId] = json[host][book];
} else {
state.notebooks[host][book].notes = {[noteId]: json[host][book]};
}
state.notebooks[host][book]["num-notes"] += 1;
if (!json[host][book].read) {
state.notebooks[host][book]["num-unread"] += 1;
}
let prevNoteId = state.notebooks[host][book]["notes-by-date"][1] || null;
state.notebooks[host][book].notes[noteId]["prev-note"] = prevNoteId
state.notebooks[host][book].notes[noteId]["next-note"] = null;
if (state.notebooks[host][book].notes[prevNoteId]) {
state.notebooks[host][book].notes[prevNoteId]["next-note"] = noteId;
}
}
}
addComment(json, state) {
let host = json.host
let book = json.book
let note = json.note
let comment = json.comment;
if (state.notebooks[host] &&
state.notebooks[host][book] &&
state.notebooks[host][book].notes &&
state.notebooks[host][book].notes[note])
{
state.notebooks[host][book].notes[note]["num-comments"] += 1;
if (state.notebooks[host][book].notes[note].comments) {
state.notebooks[host][book].notes[note].comments.unshift(comment);
} else if (state.notebooks[host][book].notes[note]["num-comments"] === 1) {
state.notebooks[host][book].notes[note].comments = [comment];
}
}
}
editBook(json, state) {
let host = Object.keys(json)[0];
let book = Object.keys(json[host])[0];
if (state.notebooks[host] && state.notebooks[host][book]) {
state.notebooks[host][book]["date-created"] = json[host][book]["date-created"];
state.notebooks[host][book]["num-notes"] = json[host][book]["num-notes"];
state.notebooks[host][book]["num-unread"] = json[host][book]["num-unread"];
state.notebooks[host][book]["title"] = json[host][book]["title"];
}
}
editNote(json, state) {
let host = Object.keys(json)[0];
let book = Object.keys(json[host])[0];
let noteId = json[host][book]["note-id"];
let note = json[host][book];
if (state.notebooks[host] &&
state.notebooks[host][book] &&
state.notebooks[host][book].notes &&
state.notebooks[host][book].notes[noteId])
{
state.notebooks[host][book].notes[noteId]["author"] = note["author"];
state.notebooks[host][book].notes[noteId]["build"] = note["build"];
state.notebooks[host][book].notes[noteId]["file"] = note["file"];
state.notebooks[host][book].notes[noteId]["title"] = note["title"];
}
}
editComment(json, state) {
let host = json.host
let book = json.book
let note = json.note
let comment = json.comment;
let commentId = Object.keys(comment)[0]
if (state.notebooks[host] &&
state.notebooks[host][book] &&
state.notebooks[host][book].notes &&
state.notebooks[host][book].notes[note] &&
state.notebooks[host][book].notes[note].comments)
{
let keys = state.notebooks[host][book].notes[note].comments.map((com) => {
return Object.keys(com)[0];
});
let index = keys.indexOf(commentId);
if (index > -1) {
state.notebooks[host][book].notes[note].comments[index] = comment;
}
}
}
delBook(json, state) {
let host = json.host;
let book = json.book;
if (state.notebooks[host]) {
if (state.notebooks[host][book]) {
delete state.notebooks[host][book];
}
if (Object.keys(state.notebooks[host]).length === 0) {
delete state.notebooks[host];
}
}
}
delNote(json, state) {
let host = json.host;
let book = json.book;
let note = json.note;
if (state.notebooks[host] &&
state.notebooks[host][book] &&
state.notebooks[host][book].notes)
{
if (state.notebooks[host][book].notes[note]) {
state.notebooks[host][book]["num-notes"] -= 1;
if (!state.notebooks[host][book].notes[note].read) {
state.notebooks[host][book]["num-unread"] -= 1;
}
delete state.notebooks[host][book].notes[note];
let index = state.notebooks[host][book]["notes-by-date"].indexOf(note);
if (index > -1) {
state.notebooks[host][book]["notes-by-date"].splice(index, 1);
}
}
if (Object.keys(state.notebooks[host][book].notes).length === 0) {
delete state.notebooks[host][book].notes;
delete state.notebooks[host][book]["notes-by-date"];
}
}
}
delComment(json, state) {
let host = json.host
let book = json.book
let note = json.note
let comment = json.comment;
if (state.notebooks[host] &&
state.notebooks[host][book] &&
state.notebooks[host][book].notes &&
state.notebooks[host][book].notes[note])
{
state.notebooks[host][book].notes[note]["num-comments"] -= 1;
if (state.notebooks[host][book].notes[note].comments) {
let keys = state.notebooks[host][book].notes[note].comments.map((com) => {
return Object.keys(com)[0];
});
let index = keys.indexOf(comment);
if (index > -1) {
state.notebooks[host][book].notes[note].comments.splice(index, 1);
}
}
}
}
}

View File

@ -0,0 +1,167 @@
import _ from 'lodash';
export class ResponseReducer {
reduce(json, state) {
console.log("responseReducer", json);
switch(json.type) {
case "notebooks":
this.handleNotebooks(json, state);
break;
case "notebook":
this.handleNotebook(json, state);
break;
case "note":
this.handleNote(json, state);
break;
case "notes-page":
this.handleNotesPage(json, state);
break;
case "comments-page":
this.handleCommentsPage(json, state);
break;
default:
break;
}
}
handleNotebooks(json, state) {
for (var host in state.notebooks) {
if (json.data[host]) {
for (var book in state.notebooks[host]) {
if (!json.data[host][book]) {
delete state.notebooks[host][book];
}
}
} else {
delete state.notebooks[host];
}
}
for (var host in json.data) {
if (state.notebooks[host]) {
for (var book in json.data[host]) {
if (state.notebooks[host][book]) {
state.notebooks[host][book]["title"] = json.data[host][book]["title"];
state.notebooks[host][book]["date-created"] =
json.data[host][book]["date-created"];
state.notebooks[host][book]["num-notes"] =
json.data[host][book]["num-notes"];
state.notebooks[host][book]["num-unread"] =
json.data[host][book]["num-unread"];
} else {
state.notebooks[host][book] = json.data[host][book];
}
}
} else {
state.notebooks[host] = json.data[host];
}
}
}
handleNotebook(json, state) {
if (state.notebooks[json.host]) {
if (state.notebooks[json.host][json.notebook]) {
state.notebooks[json.host][json.notebook]["notes-by-date"] =
json.data.notebook["notes-by-date"];
if (state.notebooks[json.host][json.notebook].notes) {
for (var key in json.data.notebook.notes) {
let oldNote = state.notebooks[json.host][json.notebook].notes[key];
if (!(oldNote)) {
state.notebooks[json.host][json.notebook].notes[key] =
json.data.notebook.notes[key];
} else if (!(oldNote.build)) {
state.notebooks[json.host][json.notebook].notes[key]["author"] =
json.data.notebook.notes[key]["author"];
state.notebooks[json.host][json.notebook].notes[key]["date-created"] =
json.data.notebook.notes[key]["date-created"];
state.notebooks[json.host][json.notebook].notes[key]["note-id"] =
json.data.notebook.notes[key]["note-id"];
state.notebooks[json.host][json.notebook].notes[key]["num-comments"] =
json.data.notebook.notes[key]["num-comments"];
state.notebooks[json.host][json.notebook].notes[key]["title"] =
json.data.notebook.notes[key]["title"];
}
}
} else {
state.notebooks[json.host][json.notebook].notes =
json.data.notebook.notes;
}
} else {
state.notebooks[json.host][json.notebook] = json.data.notebook;
}
} else {
state.notebooks[json.host] = {[json.notebook]: json.data.notebook};
}
}
handleNote(json, state) {
if (state.notebooks[json.host] &&
state.notebooks[json.host][json.notebook]) {
state.notebooks[json.host][json.notebook]["notes-by-date"] =
json.data["notes-by-date"];
if (state.notebooks[json.host][json.notebook].notes) {
for (var key in json.data.notes) {
let oldNote = state.notebooks[json.host][json.notebook].notes[key];
if (!(oldNote && oldNote.build && key !== json.note)) {
state.notebooks[json.host][json.notebook].notes[key] =
json.data.notes[key];
}
}
} else {
state.notebooks[json.host][json.notebook].notes = json.data.notes;
}
} else {
throw Error("tried to fetch note, but we don't have the notebook");
}
}
handleNotesPage(json, state) {
if (state.notebooks[json.host] && state.notebooks[json.host][json.notebook]) {
state.notebooks[json.host][json.notebook]["notes-by-date"] =
json.data["notes-by-date"];
if (state.notebooks[json.host][json.notebook].notes) {
for (var key in json.data.notes) {
let oldNote = state.notebooks[json.host][json.notebook].notes[key];
if (!(oldNote)) {
state.notebooks[json.host][json.notebook].notes[key] =
json.data.notes[key];
} else if (!(oldNote.build)) {
state.notebooks[json.host][json.notebook].notes[key]["author"] =
json.data.notes[key]["author"];
state.notebooks[json.host][json.notebook].notes[key]["date-created"] =
json.data.notes[key]["date-created"];
state.notebooks[json.host][json.notebook].notes[key]["note-id"] =
json.data.notes[key]["note-id"];
state.notebooks[json.host][json.notebook].notes[key]["num-comments"] =
json.data.notes[key]["num-comments"];
state.notebooks[json.host][json.notebook].notes[key]["title"] =
json.data.notes[key]["title"];
}
}
} else {
state.notebooks[json.host][json.notebook].notes =
json.data.notes;
}
} else {
throw Error("tried to fetch paginated notes, but we don't have the notebook");
}
}
handleCommentsPage(json, state) {
if (state.notebooks[json.host] &&
state.notebooks[json.host][json.notebook] &&
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);
} else {
state.notebooks[json.host][json.notebook].notes[json.note].comments =
json.data;
}
} else {
throw Error("tried to fetch paginated comments, but we don't have the note");
}
}
}

View File

@ -1,336 +0,0 @@
export class RumorReducer {
reduce(json, state){
if (json.collection) {
this.reduceCollection(json.collection, state);
}
if (json.post) {
this.reducePost(json, state);
}
if (json.comments) {
this.reduceComments(json, state);
}
if (json.total) {
this.reduceTotal(json, state);
}
if (json.remove) {
this.reduceRemove(json.remove, state);
}
}
reduceRemove(json, state) {
if (json.who === window.ship) {
if (json.post) {
this.removePost(json, state);
delete state.pubs[json.coll].posts[json.post];
} else {
let postIds = Object.keys(state.pubs[json.coll].posts);
postIds.forEach((postId) => {
this.removePost({
who: json.who,
coll: json.coll,
post: postId,
}, state);
});
delete state.pubs[json.coll];
}
} else {
if (json.post) {
this.removePost(json, state);
delete state.subs[json.who][json.coll].posts[json.post];
} else {
let postIds = Object.keys(state.subs[json.who][json.coll].posts);
postIds.forEach((postId) => {
this.removePost({
who: json.who,
coll: json.coll,
post: postId,
}, state);
});
delete state.subs[json.who][json.coll];
}
}
}
removePost(json, state) {
this.removeLatest(json, state);
this.removeOrder(json, state);
this.removeUnread(json, state);
}
removeLatest(json, state) {
let idx = _.findIndex(state.latest, json);
_.pullAt(state.latest, [idx]);
}
removeUnread(json, state) {
let idx = _.findIndex(state.latest, json);
_.pullAt(state.latest, [idx]);
}
removeOrder(json, state) {
if (json.who === window.ship) {
if (state.pubs[json.coll]) {
let pinIdx = state.pubs[json.coll].order.pin.indexOf(json.post);
let unpinIdx = state.pubs[json.coll].order.unpin.indexOf(json.post);
if (pinIdx != -1) {
_.pullAt(state.pubs[json.coll].order.pin, [pinIdx]);
}
if (unpinIdx != -1) {
_.pullAt(state.pubs[json.coll].order.unpin, [unpinIdx]);
}
}
} else {
if (state.subs[json.who][json.coll]) {
let pinIdx =
state.subs[json.who][json.coll].order.pin.indexOf(json.post);
let unpinIdx =
state.subs[json.who][json.coll].order.unpin.indexOf(json.post);
if (pinIdx != -1) {
_.pullAt(state.subs[json.who][json.coll].order.pin, [pinIdx]);
}
if (unpinIdx != -1) {
_.pullAt(state.subs[json.who][json.coll].order.unpin, [unpinIdx]);
}
}
}
}
reduceCollection(json, state) {
if (json.who === window.ship) {
if (state.pubs[json.coll]) {
state.pubs[json.coll].info = json.data;
} else {
state.pubs[json.coll] = {
info: json.data,
order: { pin: [], unpin: [] },
posts: {},
}
}
} else {
if (state.subs[json.who]) {
if (state.subs[json.who][json.coll]) {
state.subs[json.who][json.coll].info = json.data;
} else {
state.subs[json.who][json.coll] = {
info: json.data,
order: { pin: [], unpin: [] },
posts: {},
}
}
} else {
state.subs[json.who] = {
[json.coll]: {
info: json.data,
order: { pin: [], unpin: [] },
posts: {},
}
}
}
}
}
reducePost(json, state) {
let who = json.post.who;
let coll = json.post.coll;
let post = json.post.post;
let data = json.post.data;
if (who === window.ship) {
if (state.pubs[coll].posts[post]) {
state.pubs[coll].posts[post].post = data;
} else {
state.pubs[coll].posts[post] = {
post: data,
comments: [],
};
}
} else {
if (state.subs[who][coll].posts[post]) {
state.subs[who][coll].posts[post].post = data;
} else {
state.subs[who][coll].posts[post] = {
post: data,
comments: [],
};
}
}
this.insertPost(json, state);
}
insertPost(json, state) {
if (typeof(json.post.data) === 'string') {
return;
}
this.insertLatest(json, state);
this.insertUnread(json, state);
this.insertOrder(json, state);
}
insertLatest(json, state) {
let newIndex = {
post: json.post.post,
coll: json.post.coll,
who: json.post.who,
}
let newDate = json.post.data.info["date-created"];
if (state.latest.length == 0) {
state.latest.push(newIndex);
return;
}
if (state.latest.indexOf(newIndex) != -1) {
return;
}
for (var i=0; i<state.latest.length; i++) {
let postId = state.latest[i].post;
let blogId = state.latest[i].coll;
let ship = state.latest[i].who;
if (newIndex.post == postId && newIndex.coll == blogId && newIndex.who == ship) {
break;
}
let idate = this.retrievePost(state, blogId, postId, ship).info["date-created"];
if (newDate >= idate) {
state.latest.splice(i, 0, newIndex);
break;
} else if (i == (state.latest.length - 1)) {
state.latest.push(newIndex);
break;
}
}
}
insertUnread(json, state) {
if (json.post.who != window.ship) {
state.unread.push({
post: json.post.post,
coll: json.post.coll,
who: json.post.who,
});
}
}
insertOrder(json, state) {
let blogId = json.post.coll;
let ship = json.post.who;
let blog = this.retrieveColl(state, blogId, ship);
let list = json.post.data.info.pinned
? blog.order.pin
: blog.order.unpin;
let newDate = json.post.data.info["date-created"];
if (list.length == 0) {
list.push(json.post.post);
}
if (list.indexOf(json.post.post) != -1) {
return;
}
for (var i=0; i<list.length; i++) {
let postId = list[i];
if (json.post.post === postId) {
break;
}
let idate = this.retrievePost(state, blogId, postId, ship).info["date-created"];
if (newDate >= idate) {
list.splice(i, 0, json.post.post);
break;
} else if (i == (state.latest.length - 1)) {
list.push(json.post.post);
break;
}
}
if (window.ship == ship) {
state.pubs[blogId].order = json.post.data.info.pinned
? {pin: list, unpin: blog.order.unpin}
: {pin: blog.order.pin, unpin: list};
} else {
state.subs[ship][blogId].order = json.post.data.info.pinned
? {pin: list, unpin: blog.order.unpin}
: {pin: blog.order.pin, unpin: list};
}
}
retrieveColl(state, coll, who) {
if (who === window.ship) {
return state.pubs[coll];
} else {
return state.subs[who][coll];
}
}
retrievePost(state, coll, post, who) {
if (who === window.ship) {
return state.pubs[coll].posts[post].post;
} else {
return state.subs[who][coll].posts[post].post;
}
}
reduceComments(json, state) {
let who = json.comments.who;
let coll = json.comments.coll;
let post = json.comments.post;
let data = json.comments.data;
if (who === window.ship) {
if (state.pubs[coll].posts[post]) {
state.pubs[coll].posts[post].comments = data;
} else {
state.pubs[coll].posts[post] = {
post: null,
comments: data,
};
}
} else {
if (state.subs[who][coll].posts[post]) {
state.subs[who][coll].posts[post].comments = data;
} else {
state.subs[who][coll].posts[post] = {
post: null,
comments: data,
};
}
}
}
reduceTotal(json, state) {
if (json.total.who == window.ship) {
state.pubs[json.total.coll] = json.total.data
} else {
if (state.subs[json.total.who]) {
state.subs[json.total.who][json.total.coll] = json.total.data;
} else {
state.subs[json.total.who] = {
[json.total.coll] : json.total.data
}
}
}
let posts = Object.keys(json.total.data.posts);
for (var i=0; i<posts.length; i++) {
let post = {
post: {
coll: json.total.coll,
post: posts[i],
who: json.total.who,
data: json.total.data.posts[posts[i]].post,
}
};
this.insertPost(post, state);
}
}
}

View File

@ -1,14 +0,0 @@
import _ from 'lodash';
export class SpinnerReducer {
reduce(json, state){
if (json.spinner == undefined) {
return;
} else if (json.spinner == true) {
state.spinner = true;
} else if (json.spinner == false) {
state.spinner = false;
}
return;
}
}

View File

@ -1,36 +0,0 @@
import _ from 'lodash';
export class UpdateReducer {
reduce(json, state){
if (json.invite) {
this.reduceInvite(json.invite, state);
} else if (json.unread) {
this.reduceUnread(json.unread, state);
}
}
reduceInvite(json, state) {
let val = {
title: json.title,
coll: json.coll,
who: json.who,
};
if (json.add) {
state.invites.push(val);
} else {
let idx = _.findIndex(state.invites, val)
_.pullAt(state.invites, [idx]);
}
}
reduceUnread(json, state) {
if (json.add) {
state.unread = _.uniq(state.unread.concat(json.posts));
} else {
let idx = json.posts.map((val) => {
return _.findIndex(state.unread, val);
});
_.pullAt(state.unread, idx);
}
}
}

View File

@ -1,31 +1,33 @@
import { UpdateReducer } from '/reducers/update';
import { RumorReducer } from '/reducers/rumor';
import { SpinnerReducer } from '/reducers/spinner';
import { InitialReducer } from '/reducers/initial';
import { PrimaryReducer } from '/reducers/primary';
import { ResponseReducer } from '/reducers/response';
class Store {
constructor() {
this.state = {
spinner: false,
...window.injectedState,
notebooks: {},
}
this.updateReducer = new UpdateReducer();
this.rumorReducer = new RumorReducer();
this.spinnerReducer = new SpinnerReducer();
this.initialReducer = new InitialReducer();
this.primaryReducer = new PrimaryReducer();
this.responseReducer = new ResponseReducer();
this.setState = () => {};
this.initialReducer.reduce(window.injectedState, this.state);
}
setStateHandler(setState) {
this.setState = setState;
}
handleEvent(data) {
this.updateReducer.reduce(data.data, this.state);
this.rumorReducer.reduce(data.data, this.state);
this.spinnerReducer.reduce(data.data, this.state);
handleEvent(evt) {
if (evt.from && evt.from.path === '/primary'){
this.primaryReducer.reduce(evt.data, this.state);
} else if (evt.type) {
this.responseReducer.reduce(evt, this.state);
}
this.setState(this.state);
}
}
export let store = new Store();