best hold sort order UI off to rockin' start custom-best-hold
authorLebbeous Fogle-Weekley <lebbeous@esilibrary.com>
Fri, 21 Dec 2012 04:27:30 +0000 (23:27 -0500)
committerLebbeous Fogle-Weekley <lebbeous@esilibrary.com>
Fri, 21 Dec 2012 04:27:30 +0000 (23:27 -0500)
Signed-off-by: Lebbeous Fogle-Weekley <lebbeous@esilibrary.com>
Open-ILS/src/templates/conify/global/config/best_hold_order.tt2 [new file with mode: 0644]
Open-ILS/web/js/dojo/openils/conify/BestHoldOrder.js [new file with mode: 0644]
Open-ILS/web/js/dojo/openils/conify/nls/conify.js

diff --git a/Open-ILS/src/templates/conify/global/config/best_hold_order.tt2 b/Open-ILS/src/templates/conify/global/config/best_hold_order.tt2
new file mode 100644 (file)
index 0000000..41a9b5d
--- /dev/null
@@ -0,0 +1,89 @@
+[% WRAPPER base.tt2 %]
+<style type="text/css">
+    h1 { margin-bottom: 0.5ex; }
+    .body-part { margin: 1ex 0; }
+    .clear-both { clear: both; }
+    #cbho-field-order-space > div { float: left; }
+    .show-access-key { font-weight: bold; border-bottom: 1px dashed black; }
+    #cbho-name { width: 30em; }
+    #cbho-loading { text-align: center; }
+    select { width: 30em; }
+    #cbho-field-order option.post-rtime { color: #ccc; }
+    .needs-saved { background-color: #f96; }
+</style>
+<h1>[% l('Best-Hold Selection Sort Order') %]</h1>
+
+<!-- Hidden after JS load. Prevents early clicks from breaking anything. -->
+<div id="cbho-loading">
+    <img src="[% ctx.media_prefix %]/opac/images/progressbar_green-old.gif"
+        alt="[% l('Interface loading') %]" />
+    <!-- <audio src="knight rider theme ;)" /> -->
+</div>
+
+<div id="cbho-main-body" class="hidden"><!-- main body -->
+    <div class="body-part">
+        <span dojoType="dijit.form.Button" onClick="module.new_cbho()">[% l('Create New') %]</span>
+        [% l('or') %]
+        <span dojoType="dijit.form.Button" onClick="module.edit_cbho()">[% l('Edit Existing') %]</span>
+    </div>
+
+    <div class="body-part hidden" id="cbho-edit-space"><!-- editing space -->
+        <p id="cbho-editing"></p>
+        <div id="cbho-name-edit-space">
+            [% l('Name:') %]
+            <input id="cbho-name" type="text" onchange="module.editor_changed(true);" />
+        </div>
+        <div id="cbho-field-order-space" class="body-part">
+            <div>
+                [% l('Order:') %]
+            </div>
+            <div>
+                <select id="cbho-field-order" size="10"> </select>
+            </div>
+            <div>
+                <button onclick="module.editor_move(-1); return false;"
+                    accesskey="[% l('k') %]">
+                    &uarr; [% l('Move Up') %]
+                </button>
+                <span class="show-access-key">[% l('k') %]</span>
+                <br />
+                <button onclick="module.editor_move(1); return false;"
+                    accesskey="[% l('j') %]">
+                    &darr; [% l('Move Down') %]
+                </button>
+                <span class="show-access-key">[% l('j') %]</span>
+            </div>
+        </div>
+
+        <div class="clear-both"></div>
+
+        <div class="body-part"><!-- save changes -->
+            <p><em>[% l('Because rtime, a high-precision timestamp, is ' _
+                'essentially unique among holds, ' _
+                'no fields arranged after rtime really have any effect in ' _
+                'determining best-hold selection.') %]</em></p>
+
+            <button id="cbho-save-changes"
+                onclick="module.editor_save(); return false" disabled="disabled">
+                [% l('Save Changes') %]
+            </button>
+        </div><!-- save changes -->
+    </div><!-- editing space -->
+
+</div><!-- main body -->
+
+<script type="text/javascript">
+    dojo.require("dijit.form.Button");
+    dojo.require("dijit.form.TextBox");
+    dojo.require("openils.conify.BestHoldOrder");
+
+    var module; /* single point of pollution of global namespace */
+
+    openils.Util.addOnLoad(
+        function() {
+            module = openils.conify.BestHoldOrder;
+            module.init();
+        }
+    );
+</script>
+[% END %]
diff --git a/Open-ILS/web/js/dojo/openils/conify/BestHoldOrder.js b/Open-ILS/web/js/dojo/openils/conify/BestHoldOrder.js
new file mode 100644 (file)
index 0000000..5538b80
--- /dev/null
@@ -0,0 +1,183 @@
+if (!dojo._hasResource["openils.conify.BestHoldOrder"]) {
+    dojo.requireLocalization("openils.conify", "conify");
+
+    dojo._hasResource["openils.conify.BestHoldOrder"] = true;
+    dojo.provide("openils.conify.BestHoldOrder");
+    dojo.provide("openils.conify.SetOrderer");
+
+    dojo.require("dojo.string");
+    dojo.require("openils.Util");
+
+(function() {
+    var localeStrings =
+        dojo.i18n.getLocalization("openils.conify", "conify");
+
+    /* This helper module is OO. */
+    dojo.declare(
+        "openils.conify.SetOrderer", null, {
+            "constructor": function(select, field_map, format_string) {
+                this.select = select;   /* HTML <select> node */
+                this.field_map = field_map; /* object of id:label pairs */
+                this.format_string = format_string || "[${0}] ${1}";
+            },
+
+            "clear": function() {
+                dojo.forEach(
+                    this.select.options,
+                    dojo.hitch(
+                        this, function(o) { this.select.options.remove(o); }
+                    )
+                );
+            },
+
+            /* This trusts that what you are passing is actually a set (no
+             * repeats). */
+            "set": function(
+                set, pos_callback /* called for each set member's <option>
+                                     node now and at any position change */
+            ) {
+                this.clear();
+                this.pos_callback = pos_callback;
+                dojo.forEach(
+                    set, dojo.hitch(this, function(o, p) { this.add(o, p); })
+                );
+            },
+
+            /* For now this trusts that your item is in the field_map */
+            "add": function(item, position) {
+                var option = dojo.create(
+                    "option", {
+                        "value": item,
+                        "innerHTML": dojo.string.substitute(
+                            this.format_string, [item, this.field_map[item]]
+                        )
+                    }
+                );
+
+                this.select.options.add(option);
+                if (this.pos_callback)
+                    this.pos_callback(option, position);
+            },
+
+            /* Returns option values in order, as a set, assuming you didn't
+             * add dupes. */
+            "get": function() {
+                /* XXX Could probably use dojo.forEach() here, but don't have
+                 * time to check whether it's sure to preserve order
+                 * with pseudo-arrays or NodeLists or whatever this is. */
+                var list = [];
+                for (var i = 0; i < this.select.options.length; i++)
+                    list.push(this.select.options[i].value);
+
+                return list;
+            },
+
+            "move_selected": function(offset) {
+                var si = this.select.selectedIndex;
+                var opt = this.select.options[si];
+                var len = this.select.options.length;
+                var newpos = si + offset;
+
+                if (newpos >= 0 && newpos < len) {
+                    this.select.options.remove(opt);
+                    this.select.options.add(opt, newpos);
+
+                    if (this.pos_callback)
+                        for (var i = 0; i < len; i++)
+                            this.pos_callback(this.select.options[i], i);
+
+                    return true;
+                } else {
+                    return false;
+                }
+            },
+        }
+    );
+
+    /* This module is *not* OO. */
+    dojo.declare("openils.conify.BestHoldOrder", null, {});
+
+    var module = openils.conify.BestHoldOrder;
+
+    /* We could get these from the IDL, but if we add more fields to that
+     * later, we have no particular mechanism for determining what is or
+     * isn't metadata. */
+    module.fields = ["pprox", "hprox", "aprox", "priority", "cut", "depth",
+        "htime", "rtime", "approx", "shtime"];
+
+    module.init = function() {
+        module.field_labels = {};
+        dojo.forEach(
+            module.fields, function(f) {
+                module.field_labels[f] = fieldmapper.IDL.fmclasses.cbho.
+                    field_map[f].label
+            }
+        );
+
+        module.set_orderer = new openils.conify.SetOrderer(
+            dojo.byId("cbho-field-order"),
+            module.field_labels,
+            localeStrings.CBHO_FIELD_DISPLAY
+        );
+
+        openils.Util.hide("cbho-loading");
+        openils.Util.show("cbho-main-body");
+    };
+
+    module.new_cbho = function() {
+        module.cbho = new fieldmapper.cbho();
+
+        module.editor_start();
+    };
+
+    module.edit_cbho = function() {
+    };
+
+    module.editor_start = function() {
+        /* XXX make following conditional on new vs edit */
+        dojo.byId("cbho-editing").innerHTML = localeStrings.CBHO_EDITING_NEW;
+
+        dojo.attr(dojo.byId("cbho-name"), "value", module.cbho.name() || "");
+        module.editor_reset_order();
+
+        openils.Util.show("cbho-edit-space");
+        module.editor_changed(false);
+    };
+
+    /* Used to set all <option> nodes in the set_orderer to appear disabled if
+     * they now come after rtime. */
+    module.set_pos_callback = function(opt_node, pos) {
+        var method = module.rtime_reached ? "addClass" : "removeClass";
+        dojo[method](opt_node, "post-rtime");
+
+        if (opt_node.value == "rtime")
+            module.rtime_reached = true;
+    };
+
+    module.editor_reset_order = function() {
+        module.rtime_reached = false;
+        module.set_orderer.set(module.fields, module.set_pos_callback);
+    };
+
+    module.editor_move = function(offset) {
+        module.rtime_reached = false;
+        if (module.set_orderer.move_selected(offset))
+            module.editor_changed(true);
+
+        /* Without this, focus is now on the up or down button, breaking
+         * the user's ability to select other rows with the arrow keys. */
+        dojo.byId("cbho-field-order").focus();
+    };
+
+    module.editor_changed = function(yes) {
+        dojo.attr("cbho-save-changes", "disabled", !yes);
+        dojo[yes ? "addClass" : "removeClass"]("cbho-edit-space","needs-saved");
+    };
+
+    module.editor_save = function() {
+        module.editor_changed(false);
+    };
+
+})();
+
+}
index c482bb6..a4627ee 100644 (file)
@@ -88,6 +88,8 @@
     "SURVEY_FOOT_LABEL": "Questions & Answers",
     "EVENT_DEF_LABEL" : "${0}: ${1}",
     "ACQ_DISTRIB_FORMULA_NAME_PROMPT" : "Enter new formula name",
-    "ACQ_DISTRIB_FORMULA_NAME_CLONE" : "${0} (Clone)"
+    "ACQ_DISTRIB_FORMULA_NAME_CLONE" : "${0} (Clone)",
+    "CBHO_EDITING_NEW": "You are editing a new best-hold order",
+    "CBHO_FIELD_DISPLAY": "[${0}] ${1}"
 }