Add a miniwizard for serials holding codes in the AutoGrid based interfaces,
authorsenator <senator@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Mon, 20 Sep 2010 07:29:58 +0000 (07:29 +0000)
committersenator <senator@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Mon, 20 Sep 2010 07:29:58 +0000 (07:29 +0000)
sparing the user from needed to input MARC breaker.

TODO:
    i18n
    Don't assume we always start with 4,1,8,1
    auto-populate chronlogy caption fields based on date (this should be easy)
    make it work in a tooltipdialog? (or don't, it seems frustrating)

git-svn-id: svn://svn.open-ils.org/ILS/trunk@17831 dcc99617-32d9-48b4-a31d-7c20da2025e4

Open-ILS/web/css/skin/default/serial.css
Open-ILS/web/js/dojo/openils/widget/HoldingCode.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/serial/subscription.js
Open-ILS/web/js/ui/default/serial/subscription/issuance.js

index 8322252..1889c8f 100644 (file)
@@ -21,3 +21,7 @@
     margin-right: 16px;
     padding: 8px 0;
 }
+.serial-holding-code { border: 0 !important; margin: 0;}
+.serial-holding-code tr { border: 0 !important; margin: 0 !important; }
+.serial-holding-code td { border: 0 !important; padding: 3px; margin: 0 !important; }
+.serial-holding-code td[colspan="2"] { text-align:center; }
diff --git a/Open-ILS/web/js/dojo/openils/widget/HoldingCode.js b/Open-ILS/web/js/dojo/openils/widget/HoldingCode.js
new file mode 100644 (file)
index 0000000..f786460
--- /dev/null
@@ -0,0 +1,167 @@
+if (!dojo._hasResource["openils.widget.HoldingCode"]) {
+    dojo.provide("openils.widget.HoldingCode");
+    dojo.require("dijit.layout.ContentPane");
+    dojo.require("dijit.form.DropDownButton");
+    dojo.require("dijit.form.TextBox");
+    dojo.require("dijit.form.NumberTextBox");
+
+    var _needed_fields = "abcdefghijklm";
+
+    function _prepare_ttip_dialog(div, wizard) {
+        dojo.empty(div);
+
+        var selector = wizard.args.scap_selector;
+        var caption_and_pattern = new scap().fromStoreItem(selector.item);
+
+        /* we're going to look for subfields a-h and i-m now. There may already
+         * be JS libs available to make this easier, but for now I'm doing this
+         * the fastest way I know. */
+
+        var pattern_code;
+        try {
+            pattern_code = JSON2js(caption_and_pattern.pattern_code());
+        } catch (E) {
+            /* no-op */;
+        }
+
+        if (!dojo.isArray(pattern_code)) {
+            div.innerHTML =
+                "Have you selected a valid caption and pattern?";/* XXX i18n */
+            return;
+        }
+
+        var fields = [];
+        for (var i = 0; i < pattern_code.length; i += 2) {
+            var subfield = pattern_code[i];
+            var value = pattern_code[i + 1];
+
+            if (_needed_fields.indexOf(subfield) != -1)
+                fields.push({"subfield": subfield, "caption": value});
+        }
+
+        if (!fields.length) {
+            div.innerHTML = /* XXX i18n (below) */
+                "No caption subfields in seleted caption and pattern";
+            return;
+        }
+
+        _prepare_ttip_dialog_fields(div, fields, wizard);
+    }
+
+    function _prepare_ttip_dialog_fields(div, fields, wizard) {
+        /* XXX TODO Don't assume these defaults for the indicators and $8, and
+         * provide reasonable control over them. */
+        var holding_code = ["4", "1", "8", "1"];
+        var inputs = [];
+
+        wizard.wizard_button.attr("disabled", true);
+        var table = dojo.create("table", {"className": "serial-holding-code"});
+        fields.forEach(
+            function(field) {
+                var tr = dojo.create("tr", null, table);
+
+                field.caption = field.caption.replace(/^\(?([^\)]+)\)?$/, "$1");
+                if (field.subfield > "h") {
+                    field.caption = field.caption.slice(0,1).toUpperCase() +
+                        field.caption.slice(1);
+                }
+
+                dojo.create("td", {"innerHTML": field.caption}, tr);
+                var dij = field.subfield > "h" ?
+                    dijit.form.NumberTextBox : dijit.form.TextBox;
+                var input = new dij(
+                    {
+                        "name": field.subfield,
+                        "constraints": {"pattern": "####"}
+                    },
+                    dojo.create("td", null, tr)
+                );
+                input.startup();
+                inputs.push({"subfield": field.subfield, "input": input});
+            }
+        );
+
+        new dijit.form.Button(
+            {
+                "label": "Compile",
+                "onClick": function() {
+                    inputs.forEach(
+                        function(input) {
+                            var value = input.input.attr("value");
+                            if (value === null || isNaN(value)) {
+                                /* XXX i18n */
+                                alert("A valid holding code cannot be " +
+                                    "produced with any blank fields.");
+                            }
+                            holding_code.push(input.subfield);
+                            holding_code.push(value);
+                        }
+                    );
+                    wizard.code_text_box.attr("value", js2JSON(holding_code));
+                    wizard.wizard_button.attr("disabled", false);
+                    dojo.empty(div);
+                }
+            }, dojo.create(
+                "span", null, dojo.create(
+                    "td", {"colspan": 2},
+                    dojo.create("tr", null, table)
+                )
+            )
+        );
+        dojo.place(table, div, "only");
+    }
+
+    dojo.declare(
+        "openils.widget.HoldingCode", dijit.layout.ContentPane, {
+            "constructor": function(args) {
+                this.args = args || {};
+            },
+
+            "startup": function() {
+                var self = this;
+                this.inherited(arguments);
+
+                var dialog_div = dojo.create(
+                    "div", {
+                        "style": "padding:1em;margin:0;text-align:center;"
+                    }, this.domNode
+                );
+                var target_div = dojo.create("div", null, this.domNode);
+                dojo.create("br", null, this.domNode);
+
+                this.wizard_button = new dijit.form.Button(
+                    {
+                        "label": "Wizard" /* XXX i18n */,
+                        "onClick": function() {
+                            _prepare_ttip_dialog(target_div, self);
+                        }
+                    },
+                    dojo.create("span", null, dialog_div)
+                );
+
+                this.code_text_box = new dijit.form.TextBox(
+                    {}, dojo.create("div", null, this.domNode)
+                );
+                this.code_text_box.startup();
+            },
+
+            "attr": function(name, value) {
+                if (name == "value") {
+                    /* XXX can this get called before any subdijits are
+                     * built (before startup() is run)? */
+                    if (value) {
+                        this.code_text_box.attr(name, value);
+                    }
+                    return this.code_text_box.attr(name);
+                } else {
+                    return this.inherited(arguments);
+                }
+            },
+
+            "update_scap_selector": function(selector) {
+                this.args.scap_selector = selector;
+                this.attr("value", "");
+            }
+        }
+    );
+}
index 3f17749..9c23942 100644 (file)
@@ -8,6 +8,7 @@ dojo.require("dijit.layout.ContentPane");
 dojo.require("dojox.grid.DataGrid");
 dojo.require("openils.widget.AutoGrid");
 dojo.require("openils.widget.ProgressDialog");
+dojo.require("openils.widget.HoldingCode");
 dojo.require("openils.PermaCrud");
 
 var pcrud;
index 55dba09..a0cc670 100644 (file)
@@ -1,6 +1,8 @@
 function fresh_scap_selector(grid) {
+    /* this really needs to be sync, not async */
     pcrud.search(
         "scap", {"subscription": sub_id, "active": "t"}, {
+            "timeout": 10,
             "oncomplete": function(r) {
                 var data = scap.toStoreData(openils.Util.readResponse(r));
                 var selector = new dijit.form.FilteringSelect(
@@ -25,6 +27,20 @@ function fresh_scap_selector(grid) {
                 );
 
                 grid.overrideEditWidgets.caption_and_pattern = selector;
+                if (grid.overrideEditWidgets.holding_code) {
+                    grid.overrideEditWidgets.holding_code.update_scap_selector(
+                        selector
+                    );
+                } else {
+                    grid.overrideEditWidgets.holding_code =
+                        new openils.widget.HoldingCode({
+                            "scap_selector": selector
+                        });
+                    grid.overrideEditWidgets.holding_code.shove = {
+                        "create": "[]"
+                    };
+                    grid.overrideEditWidgets.holding_code.startup();
+                }
             }
         }
     );