Search code examples
javascriptodata

How to reflect URL back to query builder


I am using OData query builder js library to generate adhoc reports and save them to database using OData generated URL for the report along with it's title.

Above works perfectly - clients can select there tables, conditions and filters to create adhoc reports and save them to database.

Problem

When my client come back to view reports they created, I can query JSON data using report's URL, but I am not sure how to select or add tables, conditions and filters they selected for that particular report.

E.g. a report url can be as simple as this,

1 -  www.example.com/Table1&$format=json  // this will return a simple table

For above example I can using JS get the first table name "Table1" in this scenario and select it in the query builder.

But for complicated urls... like this,

http://services.odata.org/Northwind/Northwind.svc/Customers?$filter=replace(CompanyName, ' ', '') eq 'AlfredsFutterkiste'

Its extremely difficult to parse it back to HTML.

Question Time

How can I translate URLs back to HTML to select table user selected, conditions & filters they added etc.. (preferably using JS library I mentioned in start)

One dirty work around is to save HTML along with URL and then display it back when user wants to edit a custom report, but it sounds too dirty way.

This is what I am trying to generate, FIRST PART Above URL

enter image description here


Solution

  • As I said, I don't know your library.

    But here's what I understand:

    A user enters several options into your pages GUI, and you use the library to generate a report. The library returns the url for that report. If the user returns to the page, you want them to be-able to plugin the URL and the GUI will return to the state it was in when the report was generated (all the selected items and stuff are as they were).

    Best solution, if possible

    If somehow the URL or something has data you can parse those fields form that's probably best.

    Another solution if you have a backend

    You could store in a database a table with "url", and a column for each of the fields. When they generate a report it makes a request to the backend which then inserts into the table a row with the URL generated and the values they entered.

    When they return to the page and enter a URL just make a request to the backend that returns the row that matches the url. (eg. select * from generated_reports where url='queryUrl')

    If your app is frontend app only (no backend)

    You could store it in browser localstorage:

    Example:

    var assigned_fields = {
        tables_selected: ["user", "cats", "dogs"]
    }
    var report_url = "http://not-really.com"
    window.localStorage.setItem("report_"+report_url, JSON.stringify(assigned_fields))
    
    function getAssignedFieldsFromURL(url) {
        return JSON.parse(window.localStorage.getItem("report_"+url))
    }
    

    Notice that if you run this javascript in the console you can use:

    getAssignedFieldsFromURL("http://not-really.com")
    

    This will return the object even after a page refresh.

    This solution will not work if they use a different browser or a different computer.

    You can use the library of your choice or native javascript to populate the assigned fields object, and to populate the GUI from the object. If you want more information on that step, comment and I'll add it.

    Parsing the URL

    I got this from: How do I parse a URL query parameters, in Javascript?

    I changed it to take a url as a param

    function getJsonFromUrl(str) {
        var query
    
        var pos = str.indexOf("?")
    
        if (pos !== -1)
            query = str.substr(pos+1)
    
        else
            query = str
    
        var result = {}
        query.split("&").forEach(function(part) {
    
            if (!part)
                return
            part = part.split("+").join(" ") // replace every + with space, regexp-free version
    
            var eq = part.indexOf("=")
            var key = eq>-1 ? part.substr(0,eq) : part
            var val = eq>-1 ? decodeURIComponent(part.substr(eq+1)) : ""
    
            var from = key.indexOf("[")
    
            if (from == -1)
                result[decodeURIComponent(key)] = val
            else {
                var to = key.indexOf("]")
                var index = decodeURIComponent(key.substring(from+1,to))
                key = decodeURIComponent(key.substring(0,from))
                if(!result[key]) result[key] = []
                if(!index) result[key].push(val)
                else result[key][index] = val
            }
        })
        return result
    }
    

    Example Usage:

    getJsonFromUrl("http://google.com?test=5&cat=3")
    

    Returns: Object {test: "5", cat: "3"}

    With that you can hopefully get the information you want form the query params

    Note: You may want to ensure this is parsing correctly. I noticed it transforms all "+" to " " and some other things.