bin URL navigation

readme
brian 4 years ago
parent ce0383d31f
commit 10071edfa0

@ -24,8 +24,14 @@ endpoints.post['/load-notes'] = function(resolve, reject, body){
let i = 0; let i = 0;
if(body.bin_id){ if(body.bin_id){
i = state.bins.findIndex(b=>b.id===body.bin_id); i = state.bins.findIndex(b=>b.id===body.bin_id);
// if there is no such bin, just return a well-formed response, but don't create such a bin server-side yet, until a save
if(i === -1){
resolve( {status: 'ok', bin:{id:body.bin_id}, notes:[]} );
return;
} }
resolve( {status: 'ok', notes: state.bins[i].notes} ); }
const bin = state.bins[i];
resolve( {status: 'ok', bin:{id:bin.id}, notes: bin.notes} );
}; };
endpoints.post['/search'] = function(resolve, reject, body){ endpoints.post['/search'] = function(resolve, reject, body){

@ -31,9 +31,9 @@ const sorting_change_handler = function(state, dispatch, e){
}; };
const new_bin_handler = function(state, dispatch){ const new_bin_handler = function(state, dispatch){
const id = nanoid(); const id = nanoid();
// TODO: consolidate: this will cause two redraws: // change browser location in address bar:
window.history.pushState(null,'','#'+id);
dispatch('new-bin', {id}); dispatch('new-bin', {id});
dispatch('notes-loaded', []);
}; };
export {new_note_handler, search_term_change_handler, sorting_change_handler, load_notes, new_bin_handler}; export {new_note_handler, search_term_change_handler, sorting_change_handler, load_notes, new_bin_handler};

@ -0,0 +1,32 @@
import api from '../api-stub.js';
const load_bin_handler = function(state, dispatch, bin_id){
/*
api.post('/load-bin', {id: bin_id})
.then(res => {
dispatch('bin-loaded', {bin:res.bin, _notes:res.notes});
});
*/
api.post('/load-notes', {bin_id})
.then(res => {
dispatch('notes-loaded', res.notes);
});
};
const hash_change_handler = function(state, dispatch, e){
// get bin id from URL
let bin_id = window.location.hash.substring(1); // extract the leading '#'
if(bin_id === ''){
const old_bin_id = state.bin.id;
window.history.replaceState(null,'', '#'+old_bin_id);
}
else{
dispatch('bin-requested', bin_id);
api.post('/load-notes', {bin_id})
.then(res => {
dispatch('notes-loaded', res.notes);
});
}
};
export {load_bin_handler, hash_change_handler};

@ -1,5 +1,6 @@
import App from './App.js'; import App from './App.js';
import nanoid from './nanoid.min.js'; import nanoid from './nanoid.min.js';
import {load_bin_handler, hash_change_handler} from './handlers/index.js';
const produce = immer.produce; const produce = immer.produce;
immer.setAutoFreeze(false); // needed for high-frequency updated values, like onkeyup->note.temp_text; only once 'save' is called will it produce a new immutable state tree immer.setAutoFreeze(false); // needed for high-frequency updated values, like onkeyup->note.temp_text; only once 'save' is called will it produce a new immutable state tree
@ -13,8 +14,18 @@ const handleActions = (actionsMap, defaultState) =>
action && action(draft, payload); action && action(draft, payload);
}); });
// get bin id from URL, and load notes from that bin; if a bin id isn't specified in the URL, create a new one and update the URL
let bin_id = window.location.hash.substring(1); // extract the leading '#'
if(bin_id === ''){
bin_id = nanoid();
window.history.replaceState(null,'', '#'+bin_id);
}
// the actual loading from server is done later, after store and dispatch are defined
const reducer = handleActions({ const reducer = handleActions({
'new-bin': (s, bin) => { s.bin=bin; }, 'new-bin': (s, bin) => { s.bin=bin; s.notes=[]; },
'bin-requested': (s, bin_id) => { s.bin={id:bin_id}; s.notes = []; },
'bin-loaded': (s, {bin, _notes}) => { s.bin=bin; s.notes=_notes.map(n=>({is_editing: false, temp_text: n.text, bin_id: bin.id, note:n})); },
'update-search-term': (s, search_term) => { s.search_term=search_term; }, 'update-search-term': (s, search_term) => { s.search_term=search_term; },
'update-search-results': (s, _notes) => { s.notes =_notes.map(n=>({is_editing: false, temp_text: '', bin_id: s.bin.id, note:n})); }, 'update-search-results': (s, _notes) => { s.notes =_notes.map(n=>({is_editing: false, temp_text: '', bin_id: s.bin.id, note:n})); },
'add-note': (s, {id, date}) => { s.notes.unshift({is_editing: true, temp_text: '', bin_id: s.bin.id, is_focused:true, note: {id: id, text: '', modified: date}}); }, 'add-note': (s, {id, date}) => { s.notes.unshift({is_editing: true, temp_text: '', bin_id: s.bin.id, is_focused:true, note: {id: id, text: '', modified: date}}); },
@ -24,7 +35,7 @@ const reducer = handleActions({
'save-note-edit': (s, {id, text}) => { const note_s=s.notes.find(n=>n.note.id===id); note_s.note.text=text; note_s.temp_text=text; note_s.is_editing=false; }, 'save-note-edit': (s, {id, text}) => { const note_s=s.notes.find(n=>n.note.id===id); note_s.note.text=text; note_s.temp_text=text; note_s.is_editing=false; },
'update-sorting': (s, sorting) => { s.sorting=sorting; } 'update-sorting': (s, sorting) => { s.sorting=sorting; }
}, { }, {
bin: {id: nanoid()}, bin: {id: bin_id},
notes: [ notes: [
//{is_editing: false, temp_text: '', bin_id: '', note: {id: nanoid(), text: 'Note one', modified: 1}}, //{is_editing: false, temp_text: '', bin_id: '', note: {id: nanoid(), text: 'Note one', modified: 1}},
], ],
@ -42,7 +53,11 @@ store.subscribe(()=>{
m.render(root, m(App, {state: store.getState(), dispatch})); m.render(root, m(App, {state: store.getState(), dispatch}));
}); });
window.addEventListener("hashchange", (e)=>hash_change_handler(store.getState(), dispatch, e), false);
let state = store.getState();
load_bin_handler(state, dispatch, bin_id);
// we don't want Mithril auto-redraw system in place, since Redux will manually re-render when necessary with store.subscribe(): // we don't want Mithril auto-redraw system in place, since Redux will manually re-render when necessary with store.subscribe():
// m.mount(root, App); // m.mount(root, App);
m.render(root, m(App, {state: store.getState(), dispatch})) m.render(root, m(App, {state, dispatch}))
Loading…
Cancel
Save