Kinto + Editor local first storage?

Kinto + Editor local first storage?

weedenbweedenb Posts: 25Questions: 6Answers: 0

Just starting to dive into browser local first storage with DT Editor and Kinto and was wondering if anyone has any experience here? I need to study the Kinto api quite a bit more but I'm hoping I can spin something off from either the Editor Ajax Override or REST examples. Local storage seems to be a pretty muddy field still but kinto looks very promising. Got the server and basic client demo's up and running okay, still need to sort out the JSON data structures and the CRUD equivalents to code on the DT side. I'm never too proud to use others work if anyone has gone down this path already?

This question has an accepted answers - jump to answer

Answers

  • weedenbweedenb Posts: 25Questions: 6Answers: 0

    Made a bit of progress in getting the data moving between the backend server, local Indexed DB and DataTables. Not sure the best approach for the editor CRUD stuff, I could leave both the Datatable and Editor out of the processing and handle externally with js and the kinto api or try to to use the kinto api inside Datatables? Kintojs is all promise based so its making my head hurt trying to visualize how to run a promise inside an asynchronous dt callback. Here is a bit of code I've got so far that works minimally (I can manually load the local data from Indexed Db into the table and editor works on the local dom just fine). Haven't worked out the editor back to Indexed Db yet.

    var editor; // use a global for the submit and return data rendering in the examples
    var table;
    
     
    $(document).ready(function() {
    
        const db = new Kinto();
        const kinto = db.collection("newtasks");
        var syncOptions = {
          remote: "http://192.168.1.15:8888/v1",
          headers: {Authorization: "Basic " + btoa("user:pass")}
        };
     
        // Set up the editor
        editor = new $.fn.dataTable.Editor( {
            table: "#example",
            idSrc: "id",
            fields: [
                {
                    label: "Title:",
                    name: "title"
                }, {
                    label: "Done:",
                    name: "done",
                    type: "radio",
                    def: false,
                    options: [ true, false ]
                }
            ],
        } );
     
        // Initialise the DataTable
        table = $('#example').DataTable( {
            dom: "Bfrtip",
            data: null,
            columns: [
                { data: "title" },
                { data: "done" }
            ],
            select: true,
            buttons: [
                { extend: "create", editor: editor },
                { extend: "edit",   editor: editor },
                { extend: "remove", editor: editor },
                { text: 'LoadLocal',
                    action: function (e, dt, node, config) {
                        kinto.list().then(function(value) {
                            // console.log(value);
                            table.rows.add(value.data).draw();
                        });
                    }
                },
                { text: 'SyncServer',
                    action: function (e, dt, node, config) {
                        kinto.sync(syncOptions).then(console.log.bind(console));
                        }
                }
            ]
        } );
    
        // This doesn't seem to fire on the first table init
        table.one( 'init', function ( e, settings, json ) {
            console.log("initial load");
            kinto.list().then(function(value) {
                table.rows.add(value.data).draw();
            });
        } );  
    
        
        
    } );
    
  • allanallan Posts: 63,498Questions: 1Answers: 10,471 Site admin
    Answer ✓

    The approach I'd take here is to override the ajax call with a custom function that will hit the Kinto API (not dissimilar from the localStorage example.

    how to run a promise inside an asynchronous dt callback

    The only place you should need to do this is in the ajax function, where you could perhaps so something like:

    ajax: function ( method, url, d, successCallback, errorCallback ) {
      if ( d.action === 'create' ) {
        kinto.insert( ... ).then( function () {
          successCallback( ... );
        }
      }
    }
    

    Its not quite as simple as that of course, but that's the basic structure I think. You'll need to accept data in the format Editor submits and return it in the success callback function in the format Editor expected.

    I'm afraid I'm not aware of anyone who has integrated Editor and Kinto before - in fact I think this is the first time I've come across Kinto - looks cool though!

    Allan

  • weedenbweedenb Posts: 25Questions: 6Answers: 0

    Thanks for the feedback Allan, that looks like a good direction to try. After looking for quite some time on a practical solution to local storage applications, Kinto seems to be the most promising to me. I looked at CouchDB quite a bit as it seems pretty good also but the rather unique NoSQL DB backend wasn't something I really wanted to jump into. Kinto out of the box uses my standard old Postgres which all my other apps rely on so easy there. Developed and supported direct from Mozilla is a very good thing (also used internally in Firefox). Overall their manifesto seems to fit my personality quite well ;) Tests all good so far on Firefox, Chrome, IOS Safari, and Android Chrome using IndexedDB. MS Explorer and Edge have some troubles as expected but I don't use them so haven't followed up on those.

    Why Kinto

  • weedenbweedenb Posts: 25Questions: 6Answers: 0

    Followup with some code. Your suggestions worked very well, put the promise in each custom ajax editor function. Got stuck a bit on just getting the initial table loaded but found a previous response of yours that indicated a row.add call was the way to go. Tied that to the table initComplete event callback and everything is good. I'm not much of a complex coder so I was very impressed with the simplicity to integrate these two together.

    Thanks Again!

    var editor; // use a global for the submit and return data rendering in the examples
    var table;
    
    
    $(document).ready(function() {
    
        const db = new Kinto();
        const kinto = db.collection("newtasks");
        var syncOptions = {
            remote: "http://192.168.1.43:8888/v1",
            headers: {Authorization: "Basic " + btoa("user:pass")}
        };
    
        // Set up the editor
        editor = new $.fn.dataTable.Editor( {
            table: "#example",
            idSrc: "id",
            ajax: function ( method, url, d, successCallback, errorCallback ) {
                var output = { data: [] };
    
                if ( d.action === "create" ) {
                    $.each( d.data, function (key, value) {
                        kinto.create(value).then(function(result) {
                            output.data.push(result.data);
                        }).then(function() {
                            successCallback( output );
                        });
                    });
                }
                else if ( d.action === "edit" ) {
                    // Update each edited item with the data submitted
                    $.each( d.data, function (id, value) {
                        value.id = id;
                        kinto.update(value).then(function(result) {
                            output.data.push( result.data );
                        }).then(function() {
                            successCallback( output );
                        });
                    } );
                }
                else if ( d.action === "remove" ) {
                    // Remove items from the object
                    $.each( d.data, function (id) {
                        kinto.delete(id).then(function(value) {
                            successCallback( output );
                        });
                    } );
                }
    
            },
            
            fields: [
                {
                    label: "Title:",
                    name: "title"
                }, {
                    label: "Done:",
                    name: "done",
                    type: "radio",
                    def: false,
                    options: [ true, false ]
                }
            ],
        } );
    
        // Initialise the DataTable
        table = $("#example").DataTable( {
            dom: "Bfrtip",
            data: null,
            columns: [
                { data: "title" },
                { data: "done" }
            ],
            select: true,
            "initComplete": function(settings, json) {
                kinto.list().then(function(value) {
                    table.rows.add(value.data).draw();
                });
            },
            buttons: [
                { extend: "create", editor: editor },
                { extend: "edit",   editor: editor },
                { extend: "remove", editor: editor },
                { text: "SyncServer",
                    action: function (e, dt, node, config) {
                        kinto.sync(syncOptions).then(console.log.bind(console));
                    }
                }
            ]
        } );
    
    } );
    
    
  • allanallan Posts: 63,498Questions: 1Answers: 10,471 Site admin

    That's outstanding - thanks for sharing your solution with us.

    Allan

This discussion has been closed.