changeset 32:acc60a20582c

Temporary Changes for querybuilder. Selecting attribute and having results list filter not fully working yet. Need 'ALL' option in attributes.
author arussell
date Sat, 19 Dec 2015 09:15:43 -0500
parents 5384b71df52a
children 758a5313baf4
files query_builder/querybuild.html
diffstat 1 files changed, 162 insertions(+), 61 deletions(-) [+]
line wrap: on
line diff
--- a/query_builder/querybuild.html	Thu Dec 10 07:26:40 2015 -0500
+++ b/query_builder/querybuild.html	Sat Dec 19 09:15:43 2015 -0500
@@ -7,10 +7,12 @@
     <link rel="stylesheet" href="select2-4.0.1/dist/css/select2.min.css">
 
     <script type="text/javascript" src="js/d3.min.js"></script>
+    <script type="text/javascript" src="js/underscore-min.js"></script>
     <script type="text/javascript" src="select2-4.0.1/vendor/jquery-2.1.0.js"></script>
     <script type="text/javascript" src="select2-4.0.1/dist/js/select2.full.min.js"></script>
 
 
+
 </head>
 <body style="background:none;">
 <div role="navigation" class="navbar navbar-default navbar-static-top">
@@ -49,7 +51,7 @@
                             <div class="row" id="startrow" style="margin-top: 15px">
                                 <div class="col-sm-4 col-md-4" id="select-col1">
                                     <select class="selected-object form-control">
-                                        <option selected>Selected object is: </option>
+                                        <option selected>Object type :  </option>
                                     </select>
                                 </div>
                                 <div class="col-sm-4 col-md-4" id="select-col2">
@@ -57,6 +59,10 @@
                                         <option selected>TEXT</option>
                                         <option>WITNESS</option>
                                         <option>PERSON</option>
+                                        <option>CODEX</option>
+                                        <option>PLACE</option>
+                                        <option>REPOSITORY</option>
+                                        <option>COLLECTION</option>
                                     </select>
                                 </div>
                             </div>
@@ -105,17 +111,20 @@
     var sourceType = "TEXT";
     var targets = [];
     var targetTypes = [];
-    var listTolerance = 100;
+    var targetObj = []; // The current objects on the display box
     var numFilters = 1;
     var filters = [
         { id: 0, text: 'has relation' },
-        { id: 1, text: 'attribute contains' }
+        { id: 1, text: 'attribute' }
     ];
     $(".filter-box"+numFilters).select2({
         // Initialize first filter box
         data: filters,
         minimumResultsForSearch: Infinity
     });
+    var listTolerance = 100;
+    //$("")
+
     function filter_html(n) {
         return '<div class="row" id="row'+n+'" style="margin-top: 15px">' +
                 '<div class="col-sm-4 col-md-4" id="'+n+'filter-col1">' +
@@ -127,31 +136,36 @@
     }
     function constraint_html(classn) {
         return '<div class="col-sm-4 col-md-4" id="'+classn+'filter-col2">' +
-                '<select class="constraint-box'+classn+' form-control" >' +
+                '<select class="rel-constraint-box'+classn+' form-control" >' +
+                '</select>' +
+                '</div>';
+    }
+    function attr_constraint_html(classn) {
+        return '<div class="col-sm-4 col-md-4" id="'+classn+'filter-col2">' +
+                '<select class="attr-constraint-box'+classn+' form-control" >' +
                 '</select>' +
                 '</div>';
     }
     function submit_html(classn) {
-        return '<div class="col-sm-4 col-md-4" id="'+classn+'filter-col2">' +
+        return '<div class="col-sm-4 col-md-4" id="'+classn+'filter-col3">' +
                 '<div class="form-group'+classn+'">' +
-                '<textarea class="form-control" rows="1" id="attribute-text-search'+classn+'">' +
-                '</textarea>' +
+                '<form onsubmit="return false;"> ' +
+                '<input type="text" name="attr-field" class="form-control" id="attr-input'+classn+'">' +
+                '</input>' +
+                '</form>' +
                 '</div>' +
                 '</div>';
     }
-    function select_html(selection) {
-        return '<div class="row" id="startrow" style="margin-top: 15px">' +
+    function select_html(selection, n) {
+        return '<div class="row" id="row'+n+'" style="margin-top: 15px">' +
                 '<div class="col-sm-4 col-md-4" id="select-col1"> ' +
                 '<select class="selected-object form-control"> ' +
                 '<option selected>Selected object is: </option> ' +
                 '</select> ' +
                 '</div> ' +
                 '<div class="col-sm-4 col-md-4" id="select-col2"> ' +
-                '<select class="select-object1 form-control"> ' +
-                '<option selected>TEXT</option> ' +
-                '<option>WITNESS</option> ' +
-                '<option>PERSON</option> ' +
-                '</select> ' +
+                '<h4>' + selection +
+                '</h4>' +
                 '</div> ' +
                 '</div>';
     }
@@ -175,43 +189,44 @@
         numFilters--;
     });
     $("#results-container").dblclick(function() {
-        if ($("#results-container option:selected").length == 1) {
-            var selection = $(this).text();
-            console.log("add filter");
-            numFilters++;
-            $("#filters").append(select_html(selection, numFilters));
-            // Generate inner relation list
-            genRelations(sourceType, ".constraint-box"+classnum);
+        var displayChoice = $("#results-container").find("option:selected").text();
+        console.log(displayChoice + ".........");
+        var selection;
+
+        _.map(targetObj, function(obj){
 
-        }
+            if (_.values(_.values(targetObj))[1] === displayChoice) {
+                selection = (_.values(_.values(obj))[0])[1];
+            }
+            else {
+                selection = (_.values(_.values(obj))[0])[0];
+            }
+        });
+        numFilters++;
+        $("#filters").append(select_html(selection, numFilters));
+        // Generate inner relation list
+        //genRelations(sourceType, ".constraint-box"+numFilters);
+        sourceType = selection;
         console.log("add filter");
     });
+    $(function() {
+        $("input").submit(function(event, data) {
+            console.log($('.form-control').find("option:selected").text());
+            console.log(event);
+            console.log(data);
+            event.preventDefault();
+
+        });
+    });
 
 
-
-
-    // For use in the onchange events below
-    function genRelations(sourceNodeType, constraintBox) {
-        var query = "match (source:"+sourceNodeType+")-[rel]-target return distinct rel.type";
-        ajax1(query, constraintBox);
-    }
-    function genResults(sourceNodeType, selected, constraintBox) {
-        var query = "match (source:"+sourceNodeType+")-["+selected+"]-(target) return target.label, target.type";
-        ajax1(query, constraintBox);
-    }
-    // Can be used to return a list of all available attributes
-    // TODO: Not implemented
-    function genAttributes(sourceNodeType, constraintBox) {
-        var query = "match (n:"+sourceNodeType+") with keys(n) as collection unwind collection as attributes return distinct attributes";
-        ajax1(query, constraintBox);
-    }
-
     // Change Events
     $('body').on('change', function(event){
         var classname = (event.target.className).substr(0, (event.target.className).indexOf(" "));
-        var classnum = (event.target.className.match(/\d+\.\d+|\d+\b|\d+(?=\w)/g) || [] )
-                .map(function (v) {return +v;}).shift();
-        var selectedOption = $('.'+classname+' option:selected').text();
+        var classnum = (event.target.className.match(/\d+\.\d+|\d+\b|\d+(?=\w)/g) || [] ).map(function (v) {return +v;}).shift();
+        var allclass = '.'+classname;
+        var selectedOption = $(allclass).find('option:selected').text();
+        console.log("SEL "+ selectedOption);
 
         // Change is on the filter box
         if (classname.indexOf("filter-box") > -1) {
@@ -220,40 +235,121 @@
                 $("#"+classnum+"filter-col2").remove();
                 $("#row"+classnum).append(constraint_html(classnum));
                 // Generate inner relation list
-                genRelations(sourceType, ".constraint-box"+classnum);
+                genRelations(sourceType, ".rel-constraint-box"+classnum);
             }
-            if (selectedOption === "attribute contains") {
+            if (selectedOption === "attribute") {
                 $("#"+classnum+"filter-col2").remove();
+                $("#row"+classnum).append(attr_constraint_html(classnum));
+                genAttributes(sourceType, ".attr-constraint-box"+classnum);
+                //$("#row"+classnum).append(submit_html(classnum));
                 $("#row"+classnum).append(submit_html(classnum));
-                //genAttributes(sourceType, ".constraint-box"+classnum);
+
             }
+
+            // NOT IMPLEMENTED
+            /*
             if (selectedOption === "return") {
                 $("#"+classnum+"filter-col2").remove();
                 $("#row"+classnum).append(constraint_html(classnum));
                 genAttributes(targetTypes, ".constraint-box"+classnum);
             }
+            */
         }
 
         // Change is on the relationship constraint box
-        if (classname.indexOf("constraint-box") > -1) {
+        if (classname.indexOf("rel-constraint-box") > -1) {
             //$().remove();
             genResults(sourceType, selectedOption, "results-container");
         }
 
-        // TODO: if the select object is changed update the sourceType var that we are looking at
+        // Change is on the attr constraint box
+        if (classname.indexOf("attr-constraint-box") > -1) {
+            //$().remove();
+            console.log("CHANGE ON ATTR");
+            console.log("changing currentqueryattr to" + selectedOption);
+            currentQueryAttr = selectedOption;
+            console.log("currentQueryAttr is" + currentQueryAttr);
+            //genResults(sourceType, selectedOption, "results-container");
+        }
+
         // Change is on subject scope
         if (classname.indexOf("select-object") > -1) {
+            sourceType = selectedOption;
+            console.log("CHANGE ON SCOPE");
+            genResults(sourceType, "New Source", "results-container");
 
             //ajax1(query, "results-container")
         }
     });
+    $("#filters").submit(function (event) {
+        var inputId = $("input:text[name=attr-field]")[0].id;
+        var inputValue = $("input:text[name=attr-field]").val();
+        // Alter results list
+        console.log("QUERY TYPE IS ATTRIBUTE NOW");
+        currentQueryType = "attribute";
+        console.log("SUBMITTED");
+        genResults(sourceType, inputValue, "results-container")
 
 
+    });
+    // For use in the onchange events above
+    function genRelations(sourceNodeType, constraintBox) {
+        console.log("GENERATE ALL RELATIONS");
+        var query = "match (source:"+sourceNodeType+")-[rel]-target return distinct rel.type";
+        console.log("QUERY TYPE IS RELATION NOW");
+        currentQueryType = "relation";
+        ajax1(query, constraintBox);
+    }
+    function genAttributes(sourceNodeType, constraintBox) {
+        console.log("GENERATE ALL ATTRIBUTES");
+        var query = "match (n:"+sourceNodeType+") with keys(n) as collection unwind collection as attributes return distinct attributes";
+        ajax1(query, constraintBox);
+    }
+    function genResults(sourceNodeType, selected, constraintBox) {
+        // TODO: Return first the list of current values of the display box
+
+        if (selected === "New Source") {
+            console.log("NEW SOURCE - UPDATE RESULTS");
+            var query = "match (source:"+sourceNodeType+") return source._n_label, source.type";
+        }
+        else if (currentQueryType === "attribute") {
+            console.log("ATTR CHANGE - UPDATE RESULTS");
+            console.log("before update currentQueryAttr is " + currentQueryAttr);
+            var qAttr = currentQueryAttr;
+            var query = "match (source:"+sourceNodeType+") where "+get_result_labels()+" AND source."+qAttr+"=~\"(?i).*"+selected+".*\" return distinct source._n_label, source.type limit 5";
+            console.log(query);
+        }
+        else if (currentQueryType === "relation") {
+            var query = "match (source:" + sourceNodeType + ")-[rel:" + selected + "]->(target) return distinct target._n_label, target.type";
+            console.log("REL CHANGE - UPDATE RESULTS");
+        }
+        else {
+            console.log("GENRESULTS IMPROPERLY CALLED");
+            return;
+        }
+        ajax1(query, constraintBox);
+    }
+    var currentQueryType;
+    var currentQueryAttr;
+    var resultLabelString = "";
+    function get_result_labels() {
+        return resultLabelString;
+    }
+    function set_result_labels(currentResults) {
+        resultLabelString = "(";
+        for (var i = 0; i < currentResults.length; i++) {
+            if (i > 0) resultLabelString += " OR ";
+            resultLabelString += 'source._n_label=\"'+currentResults[i].text.substr(1)+'\"';
+        }
+        resultLabelString += ")"
+    }
+    // to use contains
+    // TODO: start n = node(*) where n.Name =~ '.*SUBSTRING.*' return n.Name, n;
+
 
 
     // Ajax request function
     function ajax1(q, resBox) {
-        console.log(q);
         $.ajaxSetup({
             headers: {
                 "Authorization": 'Basic ' + window.btoa("neo4j"+":"+"neo5j")
@@ -301,7 +397,6 @@
     // On success, generate new data
     // TODO: might want to just always return nodes and then deal with the queryData different for each type of return
     function dataGen(dataArr, resBox) {
-        console.log(dataArr);
         var d = dataArr;
         targets = [];
 
@@ -318,12 +413,12 @@
             var d = b.text.replace(/<|>/g, '');
             return c.localeCompare(d);
         });
-        console.log(queryData[0].text);
 
         // Change the displayed results
         if (resBox === "results-container") {
             process_display_results(queryData);
         }
+        // Or fill any select boxes
         else {
             $(resBox).select2({
                 data: queryData
@@ -334,16 +429,31 @@
         var weights = [];
         var resultLength = queryData.length;
         targetTypes = [];
-
+        targetObj = queryData;
+        set_result_labels(queryData);
         $('#results-container')
                 .find('option')
                 .remove()
                 .end()
         ;
+        for (var i = 0; i < targets.length; i++) {
+            if (targetTypes.indexOf(targets[i]) == -1) {
+                targetTypes.push(targets[i]);
+                weights.push(1);
+            }
+            else {
+                weights[targetTypes.indexOf(targets[i])] += 1;
+            }
+        }
         if (resultLength < listTolerance) {
             for (var i = 0; i < resultLength; i++) {
                 // TODO: put this jQuery call into its own function to be called if the else statement occurs
                 // TODO: but the user actually does want to see the entire huge list.
+                // This next bit removes duplicate labels if we want to use that for things like cities
+                // would this throw issues with other things??
+                //$('#results-container option:contains('+queryData[i].text+')').each(function(){
+                //    $(this).remove();
+                //});
                 $('#results-container')
                         .append($("<option></option>")
                                 .attr("value", i)
@@ -351,15 +461,6 @@
             }
         }
         else {
-            for (var i = 0; i < targets.length; i++) {
-                if (targetTypes.indexOf(targets[i]) == -1) {
-                    targetTypes.push(targets[i]);
-                    weights.push(1);
-                }
-                else {
-                    weights[targetTypes.indexOf(targets[i])] += 1;
-                }
-            }
             for (var i = 0; i < targetTypes.length; i++) {
                 $('#results-container')
                         .append($("<option></option>")