[open-ils-commits] r16230 - in trunk/Open-ILS/web: css/skin/default js/dojo/openils/widget js/dojo/openils/widget/nls js/ui/default/acq/search templates/default/acq/search (senator)

svn at svn.open-ils.org svn at svn.open-ils.org
Tue Apr 13 16:18:01 EDT 2010


Author: senator
Date: 2010-04-13 16:17:55 -0400 (Tue, 13 Apr 2010)
New Revision: 16230

Added:
   trunk/Open-ILS/web/js/dojo/openils/widget/XULTermLoader.js
   trunk/Open-ILS/web/js/dojo/openils/widget/nls/XULTermLoader.js
Modified:
   trunk/Open-ILS/web/css/skin/default/acq.css
   trunk/Open-ILS/web/js/ui/default/acq/search/unified.js
   trunk/Open-ILS/web/templates/default/acq/search/unified.tt2
Log:
Acq: add search-by-file-of-terms to unified search

This feature was present in the now deprecated lineitem search interface.
It works, but it is severely limited at the moment in the number of search
terms you can use, because search queries are made into URIs before the
search actually happens (in order to make backing up to old search results
possible), and at a certain point, very large URIs become infeasible.

Some adjustments to how search history is made naviagable may be in order.


Modified: trunk/Open-ILS/web/css/skin/default/acq.css
===================================================================
--- trunk/Open-ILS/web/css/skin/default/acq.css	2010-04-13 18:02:25 UTC (rev 16229)
+++ trunk/Open-ILS/web/css/skin/default/acq.css	2010-04-13 20:17:55 UTC (rev 16230)
@@ -202,6 +202,12 @@
 #acq-invoice-new-msg { font-weight: bold; margin: 10px;}
 #acq-invoice-li-details { padding: 10px; font-weight: bold; border: 1px solid #888; margin: 10px; }
 #acq-invoice-create { margin: 10px; }
+.acq-inoice-item-extra-info { padding-left: 10px; }
+.acq-inoice-item-info { font-weight: bold; }
+.acq-invoice-row td { border-bottom: 1px solid #e0e0e0; }
+.acq-invoice-invalid-amount input { color: red; font-weight: bold; }
+.acq-link-invoice-dialog td,.acq-link-invoice-dialog th {padding-top: 10px;}
+
 #acq-unified-heading { margin-bottom: 10px; }
 #acq-unified-heading-actual { float: left; width: 50%; font-size: 120%; font-weight: bold; }
 #acq-unified-heading-controls { float: right; width: 50%; text-align: right; }
@@ -218,8 +224,3 @@
 .acq-unified-terms-match { width: 15%; }
 .acq-unified-terms-remove { width: 5%; text-align: right; }
 .acq-unified-remover { color: #c00; }
-.acq-inoice-item-extra-info { padding-left: 10px; }
-.acq-inoice-item-info { font-weight: bold; }
-.acq-invoice-row td { border-bottom: 1px solid #e0e0e0; }
-.acq-invoice-invalid-amount input { color: red; font-weight: bold; }
-.acq-link-invoice-dialog td,.acq-link-invoice-dialog th {padding-top: 10px;}

Added: trunk/Open-ILS/web/js/dojo/openils/widget/XULTermLoader.js
===================================================================
--- trunk/Open-ILS/web/js/dojo/openils/widget/XULTermLoader.js	                        (rev 0)
+++ trunk/Open-ILS/web/js/dojo/openils/widget/XULTermLoader.js	2010-04-13 20:17:55 UTC (rev 16230)
@@ -0,0 +1,96 @@
+if (!dojo._hasResource["openils.widget.XULTermLoader"]) {
+    dojo._hasResource["openils.widget.XULTermLoader"] = true;
+
+    dojo.provide("openils.widget.XULTermLoader");
+    dojo.require("openils.XUL");
+    dojo.requireLocalization("openils.widget", "XULTermLoader");
+
+    dojo.declare(
+        "openils.widget.XULTermLoader", [dijit.layout.ContentPane], {
+            "constructor": function(args) {
+                this.args = args;
+                this.terms = [];
+                this._ = openils.widget.XULTermLoader.localeStrings;
+
+                /* XXX Totally arbitrary defaults. Keeping them low for now
+                 * since all search terms have to be turned into a URL.
+                 * There will need to be a better long term solution.
+                 */
+                if (!this.args.fileSizeLimit)
+                    this.args.fileSizeLimit = 2048;
+                if (!this.args.termLimit)
+                    this.args.termLimit = 100;
+            },
+            "build": function(callback) {
+                var self = this;
+
+                this.domNode = dojo.create("span");
+                this.labelNode = dojo.create(
+                    "span", {
+                        "innerHTML": this._.LABEL_TEXT,
+                        "style": "padding-right: 8px;"
+                    }, this.domNode, "last"
+                );
+                this.countNode = dojo.create(
+                    "span", {"innerHTML": this.terms.length},
+                    this.labelNode, "first"
+                );
+                this.buttonNode = dojo.create(
+                    "button", {
+                        "innerHTML": this._.BUTTON_TEXT,
+                        "onclick": function() { self.loadTerms(); }
+                    },
+                    this.domNode, "last"
+                );
+
+                if (this.args.parentNode)
+                    dojo.place(this.domNode, this.args.parentNode, "last");
+
+                callback(this);
+            },
+            "updateCount": function() {
+                var value = this.attr("value");
+                if (dojo.isArray(value))
+                    this.terms = this.attr("value");
+                this.countNode.innerHTML = this.terms.length;
+            },
+            "focus": function() {
+                this.buttonNode.focus();
+            },
+            "loadTerms": function() {
+                try {
+                    if (this.terms.length >= this.args.termLimit) {
+                        alert(this._.TERM_LIMIT);
+                        return;
+                    }
+                    var data = this.parseUnimaginatively(
+                        openils.XUL.contentFromFileOpenDialog(
+                            this._.CHOOSE_FILE, this.args.fileSizeLimit
+                        )
+                    );
+                    if (data.length + this.terms.length >=
+                        this.args.termLimit) {
+                        alert(this._.TERM_LIMIT_SOME);
+                        var can = this.args.termLimit - this.terms.length;
+                        if (can > 0)
+                            this.terms = this.terms.concat(data.slice(0, can));
+                    } else {
+                        this.terms = this.terms.concat(data);
+                    }
+                    this.attr("value", this.terms);
+                    this.updateCount();
+                } catch(E) {
+                    alert(E);
+                }
+            },
+            "parseUnimaginatively": function(data) {
+                return data.split(/[\n, ]/).filter(
+                    function(o) { return o.length > 0; }
+                );
+            }
+        }
+    );
+
+    openils.widget.XULTermLoader.localeStrings =
+        dojo.i18n.getLocalization("openils.widget", "XULTermLoader");
+}

Added: trunk/Open-ILS/web/js/dojo/openils/widget/nls/XULTermLoader.js
===================================================================
--- trunk/Open-ILS/web/js/dojo/openils/widget/nls/XULTermLoader.js	                        (rev 0)
+++ trunk/Open-ILS/web/js/dojo/openils/widget/nls/XULTermLoader.js	2010-04-13 20:17:55 UTC (rev 16230)
@@ -0,0 +1,7 @@
+{
+    'LABEL_TEXT': " term(s) loaded",
+    'BUTTON_TEXT': "Load more terms",
+    'TERM_LIMIT': "You have already loaded the maximum number of terms.",
+    'TERM_LIMIT_SOME': "Could not load all terms from the file without exceeding maximum number of terms. Some data not included.",
+    'CHOOSE_FILE': "Choose a file from which to read search terms."
+}

Modified: trunk/Open-ILS/web/js/ui/default/acq/search/unified.js
===================================================================
--- trunk/Open-ILS/web/js/ui/default/acq/search/unified.js	2010-04-13 18:02:25 UTC (rev 16229)
+++ trunk/Open-ILS/web/js/ui/default/acq/search/unified.js	2010-04-13 20:17:55 UTC (rev 16230)
@@ -2,6 +2,7 @@
 dojo.require("dojox.encoding.base64");
 dojo.require("openils.widget.AutoGrid");
 dojo.require("openils.widget.AutoWidget");
+dojo.require("openils.widget.XULTermLoader");
 dojo.require("openils.PermaCrud");
 
 var termSelectorFactory;
@@ -19,7 +20,7 @@
 /* only sets the selected value if such an option is actually available */
 HTMLSelectElement.prototype.setValue = function(s) {
     for (var i = 0; i < this.options.length; i++) {
-        if (s == this.options[i].value && !this.options[i].disabled) {
+        if (s == this.options[i].value) {
             this.selectedIndex = i;
             break;
         }
@@ -88,26 +89,47 @@
                 "datatype": self.terms[parts[0]][parts[1]].datatype
             };
         },
-        "makeWidget": function(parentNode, wStore, callback) {
+        "makeWidget": function(parentNode, wStore, matchHow, value, callback) {
             var term = this.getTerm();
             var widgetKey = this.uniq;
-            if (term.hint == "acqlia") {
+            if (matchHow.getValue() == "__in") {
+                new openils.widget.XULTermLoader({
+                    "parentNode": parentNode
+                }).build(
+                    function(w) {
+                        wStore[widgetKey] = w;
+                        if (typeof(callback) == "function")
+                            callback(term, widgetKey);
+                        if (typeof(value) != "undefined")
+                            w.attr("value", value);
+                        /* I would love for the following call not to be
+                         * necessary, so that updating the value of the dijit
+                         * would lead to this automatically, but I can't yet
+                         * figure out the correct way to do this in Dojo.
+                         */
+                        w.updateCount();
+                    }
+                );
+            } else if (term.hint == "acqlia") {
                 wStore[widgetKey] = dojo.create(
                     "input", {"type": "text"}, parentNode, "only"
                 );
+                if (typeof(value) != "undefined")
+                    wStore[widgetKey].attr("value", value);
                 wStore[widgetKey].focus();
                 if (typeof(callback) == "function")
                     callback(term, widgetKey);
             } else {
-                var widget = new openils.widget.AutoFieldWidget({
+                new openils.widget.AutoFieldWidget({
                     "fmClass": term.hint,
                     "fmField": term.field,
                     "noDisablePkey": true,
                     "parentNode": dojo.create("span", null, parentNode, "only")
-                });
-                widget.build(
+                }).build(
                     function(w) {
                         wStore[widgetKey] = w;
+                        if (typeof(value) != "undefined")
+                            w.attr("value", value);
                         w.focus();
                         if (typeof(callback) == "function")
                             callback(term, widgetKey);
@@ -199,6 +221,40 @@
     this._selector = function(id) { return dojo.byId("term-" + id); };
     this._match_how = function(id) { return dojo.byId("term-match-" + id); };
 
+    this._updateMatchHowForField = function(term, key) {
+        /* NOTE important to use self, not this, in this function.
+         *
+         * Based on the selected field (its datatype and the kind of widget
+         * that AutoFieldWidget provides for it) we update the possible
+         * choices in the mach_how selector.
+         */
+        var w = self.widgets[key];
+        var can_do_fuzzy, can_do_in;
+        if (term.datatype == "id") {
+            can_do_fuzzy = false;
+            can_do_in = true;
+        } else if (term.datatype == "link") {
+            can_do_fuzzy = (self.getLinkTarget(term) == "au");
+            can_do_in = false; /* XXX might revise later */
+        } else if (typeof(w.declaredClass) != "undefined") {
+            can_do_fuzzy = can_do_in =
+                Boolean(w.declaredClass.match(/form\.Text/));
+        } else {
+            var type = dojo.attr(w, "type");
+            if (type)
+                can_do_fuzzy = can_do_in = (type == "text");
+            else
+                can_do_fuzzy = can_do_in = false;
+        }
+
+        self.matchHowAllow(key, "__fuzzy", can_do_fuzzy);
+        self.matchHowAllow(key, "__in", can_do_in);
+
+        var inequalities = (term.datatype == "timestamp");
+        self.matchHowAllow(key, "__gte", inequalities);
+        self.matchHowAllow(key, "__lte", inequalities);
+    };
+
     this.removerButton = function(n) {
         return dojo.create("button", {
             "innerHTML": "X",
@@ -225,36 +281,8 @@
         dojo.empty(where);
 
         this._selector(id).makeWidget(
-            where, this.widgets,
-            function(term, key) {
-                var w = self.widgets[key];
-                var can_do_fuzzy;
-                if (term.datatype == "id") {
-                    can_do_fuzzy = false;
-                } else if (term.datatype == "link") {
-                    can_do_fuzzy = (self.getLinkTarget(term) == "au");
-                } else if (typeof(w.declaredClass) != "undefined") {
-                    can_do_fuzzy = Boolean(w.declaredClass.match(/form\.Text/));
-                } else {
-                    var type = dojo.attr(w, "type");
-                    if (type)
-                        can_do_fuzzy = (type == "text");
-                    else
-                        can_do_fuzzy = false;
-                }
-                self.matchHowAllow(id, "__fuzzy", can_do_fuzzy);
-
-                var inequalities = (term.datatype == "timestamp");
-                self.matchHowAllow(id, "__gte", inequalities);
-                self.matchHowAllow(id, "__lte", inequalities);
-
-                if (value) {
-                    if (typeof(w.attr) == "function")
-                        w.attr("value", value);
-                    else
-                        w.value = value;
-                }
-            }
+            where, this.widgets, this._match_how(id), value,
+            this._updateMatchHowForField
         );
     };
 
@@ -308,6 +336,13 @@
         dojo.attr(
             match_how, "onchange",
             function() {
+                if (this.getValue() == "__in") {
+                    self.updateRowWidget(uniq);
+                    this.was_in = true;
+                } else if (this.was_in) {
+                    self.updateRowWidget(uniq);
+                    this.was_in = false;
+                }
                 if (self.widgets[uniq]) self.widgets[uniq].focus();
             }
         );
@@ -320,11 +355,13 @@
         if (term && hint) {
             var field = hint + ":" + this._term_reverse_selector_field(term);
             selector.setValue(field);
-            this.updateRowWidget(uniq, this._term_reverse_selector_value(term));
 
             var match_how_value = this._term_reverse_match_how(term);
             if (match_how_value)
                 match_how.setValue(match_how_value);
+
+            this.updateRowWidget(uniq, this._term_reverse_selector_value(term));
+
         }
     }
 

Modified: trunk/Open-ILS/web/templates/default/acq/search/unified.tt2
===================================================================
--- trunk/Open-ILS/web/templates/default/acq/search/unified.tt2	2010-04-13 18:02:25 UTC (rev 16229)
+++ trunk/Open-ILS/web/templates/default/acq/search/unified.tt2	2010-04-13 20:17:55 UTC (rev 16230)
@@ -106,16 +106,22 @@
                             <select>
                                 <option value="">is</option>
                                 <option value="__not">is NOT</option>
-                                <option value="__fuzzy">contains</option>
-                                <option value="__not,__fuzzy">
+                                <option value="__fuzzy" disabled="disabled">
+                                    contains
+                                </option>
+                                <option value="__not,__fuzzy"
+                                    disabled="disabled">
                                     does NOT contain
                                 </option>
-                                <option value="__lte">
+                                <option value="__lte" disabled="disabled">
                                     is on or BEFORE
                                 </option>
-                                <option value="__gte">
+                                <option value="__gte" disabled="disabled">
                                     is on or AFTER
                                 </option>
+                                <option value="__in" disabled="disabled">
+                                    matches a term from a file
+                                </option>
                             </select>
                         </td>
                         <td name="widget"



More information about the open-ils-commits mailing list