@ -24,45 +24,100 @@ if(bin_id === ''){
}
// the actual loading from server is done later, after store and dispatch are defined
/* Integrates a database row from the server into the local store: */
const integrate = function ( s , model _object ) {
const id = model _object . id ;
s . db [ id ] = s . db [ id ] || { ref _count : 0 , model : null } ;
s . db [ id ] . model = model _object ;
} ;
const i = integrate ;
/* integrates a list of model objects, as if 'integrate' were called on each element. */
const integrateAll = function ( s , model _objects ) {
model _objects . forEach ( mo => {
integrate ( s , mo ) ;
} ) ;
} ;
/* Register a reference-by-id: */
const ref = function ( s , o , key , new _model _id ) {
const old _model _id = o [ key ] ;
s . db [ new _model _id ] . ref _count ++ ;
if ( old _model _id && s . db [ old _model _id ] ) {
s . db [ old _model _id ] . ref _count -- ;
if ( s . db [ old _model _id ] . ref _count === 0 ) {
delete s . db [ old _model _id ] ;
}
}
// this needs to come after the above 'if' statement:
o [ key ] = new _model _id ;
} ;
/* Register references in-bulk: */
/* o[key] refers to an array-of-ids */
const refAll = function ( s , o , key , new _model _ids ) {
const old _model _ids = o [ key ] ;
// ref the new refs:
o [ key ] = new _model _ids ;
new _model _ids . forEach ( new _model _id => {
s . db [ new _model _id ] . ref _count ++ ;
} ) ;
// de-ref the existing refs, deleting no-longer-referred-to models:
old _model _ids . forEach ( old _model _id => {
s . db [ old _model _id ] . ref _count -- ;
// if this is the last reference, delete it from the store:
if ( s . db [ old _model _id ] . ref _count === 0 ) {
delete s . db [ old _model _id ] ;
}
} ) ;
} ;
/ * T O D O : r o u t i n e t o d e - r e f a n d r e f i n b u l k w h e n t h e i d i s i n a n o b j e c t w h i c h i s i n a n a r r a y ( a s o p p o s e d t o r e f A l l , w h e r e t h e i d i t s e l f i s i n t h e a r r a y )
This routine would need to be called for state . notes , which contains refs of the form : ` state.notes[n].note_id `
* /
function addToBinListIfLoggedIn ( state ) {
const s = state ;
// if user is logged in:
if ( s . login . is _logged _in ) {
// if bin is not already in the list:
if ( s . login . bins . filter ( b => b . id === s . bin . id ) . length === 0 ) {
s . login . bins . push ( { id : s . bin . id , name : s . bin . name } ) ;
if ( s . login . bin _ids . filter ( bin _id => bin _id === s . bin _id ) . length === 0 ) {
i ( s , { id : s . bin _id , name : s . db [ s . bin _id ] . model . name } ) ;
s . login . bin _ids . push ( s . bin _id ) ;
}
}
}
const reducer = handleActions ( {
'new-bin' : ( s , bin ) => { s . bin = bin ; s . notes = [ ] ; s . temp _bin _name = bin . id ; } ,
'bin-requested' : ( s , bin _id ) => { s . bin = { id : bin _id } ; s . notes = [ ] ; } ,
'bin-loaded' : ( s , bin ) => { s . bin = bin ; s . temp _bin _name = bin . name ; } ,
'new-bin' : ( s , bin ) => { i( s , bin ) ; ref ( s , s , 'bin_id' , bin . id ) ; s . notes = [ ] ; s . temp _bin _name = bin . id ; } ,
'bin-requested' : ( s , bin _id ) => { i( s , { id : bin _id } ) ; ref ( s , s , 'bin_id' , bin _id ) ; s . notes = [ ] ; } ,
'bin-loaded' : ( s , bin ) => { i( s , bin ) ; ref ( s , s , 'bin_id' , bin . id ) ; s . temp _bin _name = bin . name ; } ,
'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 } ) ) ; } ,
'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 } } ) ; } ,
'notes-loaded' : ( s , _notes ) => { s . notes = _notes . map ( n => ( { is _editing : false , temp _text : n . text , bin _id : s . bin . id , note : n } ) ) ; } ,
'update-note-text' : ( s , { id , text } ) => { const note _s = s . notes . find ( n => n . note . id === id ) ; note _s . note . text = text ; } , // updates underlying note text (i.e. the "model", not the app note_state) "in the background" (e.g. from a server-pushed update), regardless of whether it's being edited; "save" is a separate action, below
'update-note-editing' : ( s , { id , is _editing } ) => { const note _s = s . notes . find ( n => n . note . id === id ) ; note _s . is _editing = is _editing ; note _s . temp _text = note _s . note . text ; } ,
'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-search-results' : ( s , _notes ) => { integrateAll( s , s . notes , 'note_id' , _notes ) ; s. notes = _notes . map ( n => ( { is _editing : false , temp _text : '' , bin _id : s . bin _ id, note _id : n . id } ) ) ; } ,
'add-note' : ( s , { id , date } ) => { i( s , { id : id , text : '' , modified : date } ) ; s. notes . unshift ( { is _editing : true , temp _text : '' , bin _id : s . bin _ id, is _focused : true , note _ id: id } ) ; } ,
'notes-loaded' : ( s , _notes ) => { integrateAll( s , _notes ) ; s. notes = _notes . map ( n => ( { is _editing : false , temp _text : n . text , bin _id : s . bin _ id, note _id : n . id } ) ) ; } ,
'update-note-text' : ( s , { id , text } ) => { const note _s = s . notes . find ( n => n . note _ id=== id ) ; s. db [ note_s . note _id ] . model . text = text ; } , // updates underlying note text (i.e. the "model", not the app note_state) "in the background" (e.g. from a server-pushed update), regardless of whether it's being edited; "save" is a separate action, below
'update-note-editing' : ( s , { id , is _editing } ) => { const note _s = s . notes . find ( n => n . note _ id=== id ) ; note _s . is _editing = is _editing ; note _s . temp _text = s. db [ note_s . note _id ] . model . text ; } ,
'save-note-edit' : ( s , { id , text } ) => { const note _s = s . notes . find ( n => n . note _ id=== id ) ; s. db [ note_s . note _id ] . model . text = text ; note _s . temp _text = text ; note _s . is _editing = false ; } ,
'update-sorting' : ( s , sorting ) => { s . sorting = sorting ; } ,
'update-username' : ( s , username ) => { s . login . username = username ; } ,
'update-password' : ( s , password ) => { s . login . password = password ; } ,
'login-requested' : ( s ) => { s . login . showing = false ; } ,
'login-succeeded' : ( s , { user , session _id } ) => { s . login . is _logged _in = true ; s . login . showing = true ; s . login . password = '' ; s . login . user = user ; s . login . session _id = session _id ; } ,
'login-succeeded' : ( s , { user , session _id } ) => { i( s , user ) ; s. login . is _logged _in = true ; s . login . showing = true ; s . login . password = '' ; ref( s , s . login , 'user_id' , user . id ) ; s . login . session _id = session _id ; } ,
'login-failed' : ( s ) => { s . login . showing = true ; s . login . password = '' ; } ,
'logout-requested' : ( s ) => { s . login . is _logged _in = false ; s . login . showing = true ; s . login . username = '' ; s . login . password = '' ; s . login . session _id = '' ; s . login . bins = [ ] ; } ,
'user-bin-list-loaded' : ( s , bins ) => { s . login . bins = bins ; } ,
'logout-requested' : ( s ) => { s . login . is _logged _in = false ; s . login . showing = true ; s . login . username = '' ; s . login . password = '' ; s . login . session _id = '' ; refAll( s , s . login , 'bin_ids' , [ ] ) ; } ,
'user-bin-list-loaded' : ( s , bins ) => { s . login . bins = bins ; integrateAll ( s , bins ) ; refAll ( s , s . login , 'bin_ids' , bins . map ( b => b . id ) ) ; } ,
'update-bin-name-editing' : ( s , is _editing ) => { s . is _editing _bin _name = is _editing ; } ,
'update-bin-name' : ( s , name ) => { s . temp _bin _name = name ; } ,
'commit-bin-name' : ( s ) => { s . bin . name = s . temp _bin _name ; s . is _editing _bin _name = false ; addToBinListIfLoggedIn ( s ) ; }
'commit-bin-name' : ( s ) => { s . db[ s . bin_id ] . model . name = s . temp _bin _name ; s . is _editing _bin _name = false ; addToBinListIfLoggedIn ( s ) ; }
} , {
bin : { id : bin _id , name : bin _id , user _id : '' } ,
bin _id : bin _id ,
is _editing _bin _name : false ,
temp _bin _name : bin _id ,
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: '' },
] ,
search _term : '' ,
sorting : 'new->old' ,
@ -71,12 +126,18 @@ const reducer = handleActions({
username : '' , // value of textbox
password : '' , // value of textbox
is _logged _in : false ,
user : null / * {
user _id : '' / * {
id : '' ,
username : ''
} * / ,
session _id : '' ,
bins : [ ]
bin _ids : [ ]
} ,
db : {
[ bin _id ] : {
ref _count : 1 ,
model : { id : bin _id , name : bin _id , user _id : '' }
}
}
//search_result_notes: []
} ) ;