Search Templates: Allows staff to create and save default searches user/catalystit/search_templates
authorJustin Douma <jdouma@catalystitservices.com>
Thu, 17 Jan 2013 00:16:58 +0000 (16:16 -0800)
committerJustin Douma <jdouma@catalystitservices.com>
Fri, 25 Jan 2013 02:02:25 +0000 (18:02 -0800)
Allows staff to create templates for advanced search page. Templates can
save any option available on the Advanced Search page but will not save
text inputs. Templates are saved to the users workstation. Templates can be
created and saved, or deleted, at Admin->Workstation Administration->
Search Templates.

Signed-off-by: Justin Douma <jdouma@catalystitservices.com>
Open-ILS/src/templates/conify/global/config/search_templates.tt2 [new file with mode: 0644]
Open-ILS/src/templates/opac/parts/advanced/search.tt2
Open-ILS/src/templates/opac/parts/config.tt2
Open-ILS/web/js/ui/default/conify/global/config/search_templates.js [new file with mode: 0644]
Open-ILS/web/opac/locale/en-US/lang.dtd
Open-ILS/xul/staff_client/chrome/content/OpenILS/data.js
Open-ILS/xul/staff_client/chrome/content/main/menu.js
Open-ILS/xul/staff_client/chrome/content/main/menu_frame_menus.xul
Open-ILS/xul/staff_client/chrome/locale/en-US/offline.properties
docs/RELEASE_NOTES_NEXT/search_templates.txt [new file with mode: 0644]

diff --git a/Open-ILS/src/templates/conify/global/config/search_templates.tt2 b/Open-ILS/src/templates/conify/global/config/search_templates.tt2
new file mode 100644 (file)
index 0000000..017fe6a
--- /dev/null
@@ -0,0 +1,286 @@
+[% WRAPPER base.tt2 %]
+[% INCLUDE 'opac/parts/js.tt2' %]
+[%
+    PROCESS "opac/parts/config.tt2";
+%]
+<script type="text/javascript" src="/xul/server/OpenILS/global_util.js"></script>
+<script type="text/javascript" src="/xul/server/main/constants.js"></script>
+<script type="text/javascript" src="/xul/server/main/JSAN.js"></script>
+<script type="text/javascript" src="/xul/server/util/file.js"></script>
+<script type="text/javascript" src="/xul/server/util/error.js"></script>
+<script type="text/javascript" src="/js/ui/default/conify/global/config/search_templates.js"></script>
+
+<style>
+    #adv_global_tbody input, #adv_global_tbody a {display:none;}
+    .ccvmSelect {width:200px;}
+    #currentSettings {float:right;  width:300px; height:200px;}
+    #options {float:left;}
+    #searchFilters td {padding:.5em;}
+    #currentSettings td {padding:.3em;}
+    #adv_global_tbody select {max-width:115px;}
+    #ssContainer {width:1200px;}
+</style>
+<div id="ssContainer">
+    <h1>[% l('Search Settings') %]</h1>
+    <br/>
+
+    <div id="currentSettings">
+        <h2>[% l('Current Template') %]</h2>
+        <select id="templateListSel" onChange="selectSearchTemplateOrClear(this.value), textIn.value = this.value" style="min-width:150px;">
+            <option value="">--Default--</option>
+        </select>
+        <br/>
+        <br/>
+        <br/>
+        <br/>
+
+        <strong>[% l('Template Name') %]</strong>
+        <br/>
+        <table>
+            <tr>
+                <td>
+                    <input type="text" id="nameInput" name="nameInput"/>
+                </td>
+                <td>
+                    <button id="save" onclick="create_template(textIn.value)">Save Template To Disk</button>
+                </td>
+            </tr>
+            <tr>
+                <td>
+                    <button id="delete" onclick="removeTemplate(templateList,template)">[% l('Delete Template') %]</button>
+                </td>
+            </tr>
+        </table>
+    </div>
+    <div id="options">
+        <table width='100%' id='adv_global_input_table'>
+
+            <tbody id='adv_global_tbody' >
+               [% INCLUDE "opac/parts/advanced/global_row.tt2" %]
+
+            </tbody>
+        </table>
+
+        <br/>
+
+        <table id="searchFilters">
+[%
+    in_row = 0;
+    FOR adv_chunk IN search.adv_config;
+        NEXT IF adv_chunk.adv_hide;
+        IF in_row == 0;
+            in_row = 1; %]
+            <tr>
+[%
+        END; %]
+        [% IF adv_chunk.adv_attr.size || adv_chunk.adv_filter.size; %]
+                <td>
+                    <strong>[% adv_chunk.adv_label %]</strong>
+                    <br />
+                    <select name="type" multiple="multiple" size="7" class="ccvmSelect">
+                    </select>
+                </td>
+        [% END; %]
+      [%  IF adv_chunk.adv_break;
+            in_row = 0; %]
+            </tr>
+        [% END; %]
+ [%   END; %]
+            <tr>
+                <td>
+                    <strong>[% l('Search Library') %]</strong>
+                    <br />
+                    <select id="orgSel" name="orgSel"></select>
+                </td>
+                <td>
+                    <strong>[% l('Publication Date') %]</strong>
+                    <br/>
+                    <select id="pubdateSel" name="pubdateSel">
+                        <option value="is">[% l('Is') %]</option>
+                        <option value="before">[% l('Before') %]</option>
+                        <option value="after">[% l('After') %]</option>
+                        <option value="between">[% l('Between') %]</option>
+                    </select>
+                </td>
+            </tr>
+
+            <tr>
+                <td>
+                    <strong>[% l('Search Results') %]</strong>
+                    <br/>
+                    <select id="sortBySel" name="sortBySel">
+                        <option value="">[% l('Sort by Relevance') %]</option>
+                        <optgroup label="[% l('Sort by Title') %]">
+                            <option value="titlesort">[% l('Title: A to Z') %]</option>
+                            <option value="titlesort.descending">[% l('Title: Z to A') %]</option>
+                        </optgroup>
+                        <optgroup label="[% l('Sort by Author') %]">
+                            <option value="authorsort">[% l('Author: A to Z') %]</option>
+                            <option value="authorsort.descending">[% l('Author: Z to A') %]</option>
+                        </optgroup>
+                        <optgroup label="[% l('Sort by Publication Date') %]">
+                            <option value="pubdate.descending">[% l('Date: Newest to Oldest') %]</option>
+                            <option value="pubdate">[% l('Date: Oldest to Newest') %]</option>
+                        </optgroup>
+                    </select>
+                </td>
+                <td>
+                    <strong>[% l('Result View') %]</strong>
+                    <br/>
+                    <select id="resultViewSel">
+                        <option value="0">[% l('Simple View') %]</option>
+                        <option value="1">[% l('Detail View') %]</option>
+                    </select>
+                </td>
+                <td>
+                    <input type="checkbox" name="modifier" id="modifier" value="available" />
+                    <span>[% l('Limit to Available') %]</span>
+                </td>
+            </tr>
+            <tr>
+                <td>
+                <button id="clear" onclick="clearOptions()">[% l('Clear Options') %]</button>
+                </td>
+            </tr>
+        </table>
+
+    </div>
+
+</div>
+
+<!-- /////////////////  -- JAVASCRIPT -- /////////////////////// -->
+
+<script type="text/javascript">
+    dojo.require('openils.PermaCrud');
+    var pcrud;
+    pcrud = new openils.PermaCrud();
+    //HTML element handles
+    var templateSel = document.getElementById("templateListSel");
+    var pubdateSel = document.getElementById("pubdateSel");
+    var orgSel = document.getElementById("orgSel");
+    var sortBySel = document.getElementById("sortBySel");
+    var resultViewSel = document.getElementById("resultViewSel");
+    var modCheck = document.getElementById("modifier");
+    var textIn = document.getElementById("nameInput");
+    var ccvmTable = document.getElementById("searchFilters");
+    var searchFilters = ccvmTable.getElementsByTagName("select");
+
+
+    var ccvmList = pcrud.retrieveAll("ccvm", {"order_by" : {"ccvm" : 'value'}});
+    var searchfilterList = pcrud.retrieveAll("asfg",{ "flesh":2, "flesh_fields":{"asfg":["entries"],"asfge":["query"]},"order_by" : {"asfg" : 'code'}});
+    var ccvmLength = ccvmList.length;
+    var filterList = new Array();
+    var foundValue = 0;
+    var n = 0; //tracks filterList
+    var s = 0; // tracks adv_config
+    [%  FOR adv_chunk IN search.adv_config;
+        NEXT IF adv_chunk.adv_hide;
+        IF adv_chunk.adv_special; %]
+        s++;
+        [% NEXT; END; %]
+        foundValue = 0;
+        filterList[n] = {};
+        filterList[n].label = "[% adv_chunk.adv_label %]";
+        filterList[n].last_in_row = "[% adv_chunk.adv_break %]";
+        filterList[n].codeList = [];
+        filterList[n].groupList = [];
+        [% IF adv_chunk.adv_attr.defined; %]
+            [% FOR attr IN adv_chunk.adv_attr; %]
+            if(!foundValue)
+            {
+                filterList[n].ctype = "[% attr %]";
+                for ( i= 0; i < ccvmLength; i++)
+                {
+                    if (ccvmList[i].ctype() == "[% attr %]")
+                    {
+                        filterList[n].codeList.push(ccvmList[i]);
+                    }
+                }
+                if (filterList[n].codeList.length )
+                {
+                    foundValue = 1;
+                }
+            }
+            searchFilters[s].setAttribute("id", "[% attr %]" + "_selector");
+            filterList[n].id = "[% attr %]" + "_selector";
+           [% END;
+        ELSIF adv_chunk.adv_filter.defined; %]
+            [% FOR filter IN adv_chunk.adv_filter; %]
+            if(!foundValue)
+            {
+                filterList[n].ctype = "[% filter %]";
+                for ( i= 0; i < searchfilterList.length; i++)
+                {
+                    if (searchfilterList[i].code() == "[% filter %]")
+                    {
+                         var len = searchfilterList[i].entries().length;
+                        for (var k = 0; k < len; k++)
+                        {
+                           filterList[n].groupList.push(searchfilterList[i].entries()[k]);
+                        }
+                    }
+                }
+                if (filterList[n].groupList.length )
+                {
+                    foundValue = 1;
+                }
+            }
+            searchFilters[s].setAttribute("id", "[% filter %]" + "_selector");
+            filterList[n].id = "[% filter %]" + "_selector";
+            [% END; %]
+        [% END; %]
+        n++;
+
+[% END; %]
+
+    //Add option tags to searchFilters
+    for (var f = 0; f < searchFilters.length; f++)
+    {
+        if (searchFilters[f].multiple)
+        {
+            if (filterList[f] && filterList[f].id)
+            {
+                if (filterList[f].codeList.length)
+                {
+                    if (filterList[f].codeList.length)
+                    for(var i=0; i<filterList[f].codeList.length; i++)
+                    {
+                        searchFilters[f].options[i]= new Option(filterList[f].codeList[i].value(), filterList[f].codeList[i].code());
+                    }
+                }
+                else if (filterList[f].groupList.length)
+                {
+                    if (filterList[f].groupList.length)
+                    for(var i=0; i<filterList[f].groupList.length; i++)
+                    {
+                        searchFilters[f].options[i]= new Option(filterList[f].groupList[i].query().label(), filterList[f].groupList[i].id());
+                    }
+                }
+            }
+        }
+    }
+
+    //create org unit dropdown
+    var orgList;
+    orgList = pcrud.retrieveAll("aou",{"order_by" : [{'class' : "aou", 'field' : 'ou_type'}, {'class' : "aou", 'field' : "name" }]});
+    for(var i=0; i< orgList.length; i++){
+        document.getElementById("orgSel").options[i]= new Option(orgList[i].name(), orgList[i].id());
+    }
+
+    //get g.data cache
+    getSearchStash();
+    populateTemplateOptions(templateList);
+
+    if (template)
+    {
+        selectOptionValue(templateSel, template.name);
+        textIn.value = template.name;
+        if(template.name != "Default")
+        {
+            populateSearchOptions(template);
+        }
+    }
+
+</script>
+
+[% END %]
index e90b6d3..aaec5d3 100644 (file)
@@ -32,7 +32,7 @@
     <tr>
         <td align='top'>
           <div style="width:100%;" class="header_middle">[% l('Search Filters') %]</div>
-          <table cellpadding='10' cellspacing='0' border='0'>
+          <table cellpadding='10' cellspacing='0' border='0' id='filterTable'>
 [%
     in_row = 0;
     FOR adv_chunk IN search.adv_config;
@@ -49,7 +49,7 @@
             SWITCH adv_chunk.adv_special;
                 CASE "lib_selector";
                     PROCESS "opac/parts/org_selector.tt2";
-                        INCLUDE build_org_selector show_loc_groups=1; %]
+                        INCLUDE build_org_selector show_loc_groups=1 id='org_selector'; %]
                             <div style="position:relative;top:7px;">
                                 <input type='checkbox' name="modifier"
                                     value="available"[% CGI.param('modifier').grep('available').size ? ' checked="checked"' : '' %]
@@ -60,7 +60,7 @@
                             </div>
 [%
                 CASE "pub_year"; %]
-                            <select name='pubdate' onchange='
+                            <select id='adv_global_pub_date_type' name='pubdate' onchange='
                                 if(this.selectedIndex == 3)
                                     unHideMe($("adv_global_pub_date_2_span"));
                                 else
                                     [%  END %]
                             </select>    
                             <div style='margin-top:5px;'>
-                                <input name='date1' type='text' size='4' maxlength='4' value="[% CGI.param('date1') | html %]" />
+                                <input name='date1' id='adv_global_pub_date_1_input' type='text' size='4' maxlength='4' value="[% CGI.param('date1') | html %]" />
                                 <span id='adv_global_pub_date_2_span' class='[% CGI.param("pubdate") == "between" ? "" : "hide_me" %]'>
-                                   [% l("and") %] <input name='date2' type='text' size='4' maxlength='4' value="[% CGI.param('date2') | html %]" />
+                                   [% l("and") %] <input name='date2' id='adv_global_pub_date_2_input' type='text' size='4' maxlength='4' value="[% CGI.param('date2') | html %]" />
                                 </span>
                             </div>
 [%
                 CASE "sort_selector";
                     INCLUDE "opac/parts/filtersort.tt2"
-                        value=CGI.param('sort') class='results_header_sel';
+                        value=CGI.param('sort') class='results_header_sel' id='opac.result.sort';
             END;
         ELSIF adv_chunk.adv_attr;
             INCLUDE "opac/parts/coded_value_selector.tt2"
     END; %]
             </table>
         </td>
+        [% IF ctx.is_staff && search.allow_templates == 'true' %]
+            <td valign='top' style="padding-left:50px;">
+                <div style="width:100%;" class="header_middle">[% l('Search Templates') %]</div>
+                <br/>
+                <strong>[% l('Select Template') %]</strong>
+                <br/>
+                <select id="templateList" onChange="selectSearchTemplateOrClearAll(this.value);">
+                </select>
+            </td>
+                <td valign="top" class="hide_me">
+               <select id="resultViewSel" name="detail_record_view" >
+                <option value="0" selected="selected">Simple View</option>
+                <option value="1">Detail View</option>
+               </select>
+            </td>
+        [% END %]
     </tr>
 </table>
 <input type="hidden" name="_adv" value="1" />
             <img id='search-submit-spinner' src='/opac/images/progressbar_green.gif' style='height:16px;width:16px;' class='hidden' alt=''/>
           </span>
 
+[% IF ctx.is_staff && search.allow_templates == 'true' %]
+<a onclick="clearAll()"
+[% ELSE %]
 <a href="[% mkurl(ctx.opac_root _ '/advanced', {$loc_name => loc_value}, 1) %]"
+[% END %]
     class="pointer opac-button">[% l('Clear Form') %]</a>
 </form>
+
+[% IF ctx.is_staff && search.allow_templates == 'true' %]
+<script type="text/javascript" src="[% ctx.media_prefix %]/js/ui/default/opac/staff.js"></script>
+<script type="text/javascript" src="/xul/server/OpenILS/global_util.js"></script>
+<script type="text/javascript" src="/js/ui/default/opac/simple.js"></script>
+<script type="text/javascript" src="/xul/server/main/constants.js"></script>
+<script type="text/javascript" src="/xul/server/main/JSAN.js"></script>
+<script type="text/javascript" src="/js/ui/default/conify/global/config/search_templates.js"></script>
+<script type="text/javascript">
+
+    var pubdateSel = $("adv_global_pub_date_type");
+    var orgSel = document.getElementById("org_selector");
+    var sortBySel = document.getElementById("opac.result.sort");
+    var resultViewSel = document.getElementById("resultViewSel");
+    var modCheck = document.getElementById("opac.result.limit2avail");
+    var templateSel = document.getElementById("templateList");
+    var filterTable = document.getElementById("filterTable");
+    var searchFilters = filterTable.getElementsByTagName("select");
+    getSearchStash();
+
+    populateTemplateOptions(templateList);
+    if (template)
+    {
+        selectOptionValue(templateSel, template.name);
+        populateSearchOptions(template);
+    }
+</script>
+[% END %]
index b0fee8f..78d73cf 100644 (file)
@@ -127,5 +127,13 @@ search.basic_config = {
     group => ['mattype','item_type'],
     none_label => l("All Formats"),
 };
+##############################################################################
+# This will allow the display and use of a Search Template dropdown that
+# staff may use to select often used searches. Upon selection of a Template, the
+# Advanced Search page's Global Rows and Search Filters will populate according
+# to the Template. Templates are configurable at
+# Admin->WorkStation Administraion->Search Templates
+
+search.allow_templates = 'true';
 
 %]
diff --git a/Open-ILS/web/js/ui/default/conify/global/config/search_templates.js b/Open-ILS/web/js/ui/default/conify/global/config/search_templates.js
new file mode 100644 (file)
index 0000000..fee3a64
--- /dev/null
@@ -0,0 +1,426 @@
+
+
+    var g = {};
+    var templateList;
+    var template;
+    var DEFAULT = "--Default--"
+
+function getSearchStash() {
+    try
+    {
+        if (typeof JSAN == 'undefined')
+        {
+            throw( document.getElementById("commonStrings").getString('common.jsan.missing') );
+        }
+        JSAN.errorLevel = "die"; // none, warn, or die
+        JSAN.addRepository('/xul/server/');
+        JSAN.use('util.error');
+        g.error = new util.error();
+        g.error.sdump('D_TRACE','getSearchStash() from search_settings.tt2 or search.tt2');
+
+        JSAN.use('OpenILS.data');
+        g.data = new OpenILS.data();
+        g.data.stash_retrieve();
+
+        //populate templateList, or not.
+        if (g.data.search_templates)
+        {
+            templateList = g.data.search_templates;
+
+            //check for current template
+            if (g.data.current_search_template)
+            {
+                template = g.data.current_search_template;
+            }
+        }
+        else
+        {
+            templateList = new Array();
+        }
+    } catch(E) {
+        try { g.error.standard_unexpected_error_alert('search_settings.tt2',E); } catch(F) { alert(E); }
+        return 0;
+    }
+}
+
+//Creates, or edits, a search template based off the currently selected values
+function create_template(tName) {
+    var template;
+    if (!tName || tName == DEFAULT)
+    {
+        alert("That is not a valid name.");
+        return;
+    }
+    template = getTemplateByName(tName, templateList);
+
+    if (template == null)
+    {
+        var isNew = 1;
+        template = new Object();
+        populateTemplate(template);
+        this.template = template;
+        templateList.push(template);
+        templateList.sort(compareTemplateNames)
+    }
+    else
+    {
+        if (confirm("Do you want to overwrite " + template.name + " template?"))
+        {
+            populateTemplate(template);
+            this.template = template;
+        }
+        else
+        { return;}
+    }
+    saveCurrentTemplate( template );
+    saveTemplateList(templateList);
+
+    //Add to templateSel and select if new template
+    if(isNew)
+    {
+        populateTemplateOptions(templateList);
+        selectOptionValue(templateSel, template.name);
+    }
+}
+
+//Returns the selected values of of a given element
+function getSelectedValues(elmnt)   {
+elmntVals = [];
+    var x = 0;
+    for (x=0;x<elmnt.length;x++)
+    {
+        if (elmnt[x].selected)
+        {
+            elmntVals.push(elmnt[x].value);
+        }
+    }
+return elmntVals;
+}
+
+//Select options in element whose values are equal to the values submitted
+function selectOptionValues(elmnt, values){
+    elmnt.selectedIndex = -1;
+    for(var i=0; i < elmnt.options.length; i++)
+    {
+        for (v in values)
+        {
+            if(elmnt.options[i].value == values[v])
+            {
+            elmnt.options[i].selected = true;
+            break;
+            }
+        }
+    }
+}
+
+//Saves templateList to File in JSON format.
+function saveTemplateListToFile( templateList ) {
+    try {
+        JSAN.use('util.file');
+        var file = new util.file('search_templates');
+        file.write_content( 'truncate', String( JSON.stringify(templateList) ) );
+        file.close();
+        alert("Template List has been updated.");
+        } catch(E) {
+            try { g.error.standard_unexpected_error_alert('saving in search_settings.tt2',E); } catch(F) { alert(E); }
+        }
+}
+
+//Saves current template name to file
+function saveCurrentTemplateToFile( template ) {
+    try {
+        JSAN.use('util.file');
+        var file = new util.file('yesterdays_search_template');
+        file.write_content( 'truncate', String( JSON.stringify(template) ) );
+        file.close();
+    } catch(E) {
+        try { g.error.standard_unexpected_error_alert('saving in search_settings.tt2',E); } catch(F) { alert(E); }
+    }
+}
+
+//Populates template dropdown from given template list
+function populateTemplateOptions(templateList)  {
+    templateSel.options.length = 0;
+    templateSel.options[0]= new Option(DEFAULT, "");
+    var len = templateList.length;
+
+    for(var i=1; i<=len; i++)
+    {
+        templateSel.options[i]= new Option(templateList[i-1].name, templateList[i-1].name);
+        if (template && template.name == templateList[i-1].name)
+        {
+            templateSel.options[i].selected= true;
+        }
+    }
+
+}
+//returns template with a given name from templatelist
+function getTemplateByName(templateName, templateList)  {
+    var len = templateList.length;
+
+    for(var i=0; i<len; i++)
+    {
+        if (templateList[i].name == templateName)
+        {
+            return templateList[i];
+        }
+    }
+    return null;
+}
+
+//returns template's index value in templateList with a given name from templatelist
+function getTemplateIndex(templateName, templateList)   {
+    var len = templateList.length;
+
+    for(var i=0; i<len; i++)
+    {
+        if (templateList[i].name == templateName)
+        {
+            return i;
+        }
+    }
+    return null;
+}
+
+//Saves selected values to a search template
+function populateTemplate(template) {
+    template.name = document.getElementById("nameInput").value;
+    template.gRows = getGlobalRowValues();
+    template.advFilters = getFilterValues();
+    template.pubdate = pubdateSel.value;
+    template.org = orgSel.value;
+    template.sort = sortBySel.value;
+    template.view = resultViewSel.value;
+    template.modifier = document.getElementById("modifier").checked;
+}
+
+//returns array containing the selected values of the global rows
+function getGlobalRowValues(){
+    var tBody = document.getElementById("adv_global_tbody");
+    var rows = tBody.getElementsByTagName("tr");
+    var gRows = [];
+    for (var i=0; i<rows.length; i++)
+    {
+        gRows[i] = {};
+        var gSels = rows[i].getElementsByTagName("select");
+        for (var s = 0; s<gSels.length; s++)
+        {
+            gRows[i][gSels[s].name] = gSels[s].value;
+        }
+    }
+    return gRows;
+}
+
+//returns array containing the selected values of the search filters
+function getFilterValues()   {
+    var filters = [];
+    for (var s = 0; s < searchFilters.length; s++)
+    {
+        filters[s] = getSelectedValues(searchFilters[s]);
+    }
+    return filters;
+}
+
+//Select the apropriate search options given a search template
+function populateSearchOptions(template) {
+    setFilterValues(template);
+    selectOptionValue(pubdateSel, template.pubdate);
+    if (template.pubdate == "between")
+        { unHideMe(document.getElementById("adv_global_pub_date_2_span")); }
+    else
+        { hideMe(document.getElementById("adv_global_pub_date_2_span")); }
+
+    selectOptionValue(orgSel, template.org);
+    selectOptionValue(sortBySel, template.sort);
+
+    selectOptionValue(resultViewSel, template.view);
+    modCheck.checked = template.modifier;
+    setGlobalRowValues(template);
+}
+//clears all selects and inputs, except the templateList select
+function clearOptions() {
+    resultViewSel.selectedIndex = 0;
+    modCheck.checked = false;
+    clearGlobalRowValues();
+    clearSearchFilters();
+    hideMe(document.getElementById("adv_global_pub_date_2_span"));
+}
+//removes any selections in the searchFilter table
+function clearSearchFilters() {
+    for (var s = 0; s < searchFilters.length; s++)
+    {
+        if (searchFilters[s].multiple)
+        { searchFilters[s].selectedIndex = -1; }
+        else
+        { searchFilters[s].selectedIndex = 0; }
+    }
+}
+
+//Given a template name, saves template as the current search template if name found in TemplateList
+//Populates options, or not, accordingly
+function selectSearchTemplateOrClear(tName) {
+    template = getTemplateByName(tName, templateList);
+    saveCurrentTemplate( template )
+
+    if (template)
+    {
+        populateSearchOptions(template);
+    } else {
+        clearOptions();
+    }
+}
+//Given a template name, saves template as the current search template if name found in TemplateList
+//Populates options, or not, accordingly. Then clears search text fields
+function selectSearchTemplateOrClearAll(tName)  {
+    selectSearchTemplateOrClear(tName);
+    clearGlobalRowInputs();
+    clearPubDateInputs();
+}
+
+ //Unselects all search options, clears text inputs
+function clearAll()     {
+    clearOptions();
+    clearGlobalRowInputs();
+    clearPubDateInputs();
+}
+
+//Make selections in the "global_row.tt2" according to the given search template
+function setGlobalRowValues(template){
+    var tBody = document.getElementById("adv_global_tbody");
+    var rows = tBody.getElementsByTagName("tr");
+    var gRows = [];
+    for (var i=0; i<rows.length; i++)
+    {
+        var gRowSels = rows[i].getElementsByTagName("select");
+        gRow = template.gRows[i];
+        var qtypeSel;
+        var containsSel;
+        for (var s = 0; s<gRowSels.length; s++)
+        {
+            selectOptionValue(gRowSels[s], gRow[gRowSels[s].name]);
+        }
+    }
+}
+//Sets the values of the adv_attr and adv_filter filters from a template
+function setFilterValues(template) {
+    var t = 0;
+    for (var s = 0; s < searchFilters.length; s++)
+    {
+        //determining adv_attr or adv_filter by checking if select is multiple, there may be a better way...
+        if(searchFilters[s].multiple)
+        {
+            selectOptionValues(searchFilters[s], template.advFilters[t]);
+            t++;
+        }
+    }
+}
+//select the first option in each Select in the "global_row.tt2)
+function clearGlobalRowValues() {
+    var tBody = document.getElementById("adv_global_tbody");
+    var rows = tBody.getElementsByTagName("tr");
+    for (var i=0; i<rows.length; i++)
+    {
+        var gRowSels = rows[i].getElementsByTagName("select");
+        for (var s = 0; s<gRowSels.length; s++)
+        {
+            gRowSels[s].selectedIndex = 0;
+        }
+    }
+}
+
+//Select a single value in an element
+function selectOptionValue(elmnt, value) {
+    for(var i=0; i < elmnt.options.length; i++)
+    {
+        if(elmnt.options[i].value == value)
+        {
+            elmnt.options[i].selected = true;
+            break;
+        }
+    }
+}
+//sort comparator for template names
+function compareTemplateNames(templateA,templateB) {
+    if (templateA.name < templateB.name)
+        { return -1; }
+    if (templateA.name > templateB.name)
+        { return 1; }
+    else
+        { return 0; }
+}
+
+//removes a template from the templateList object
+function deleteTemplatefromTemplateList(tName, templateList) {
+    var index = getTemplateIndex(tName, templateList);
+    templateList.splice(index,1);
+    saveTemplateList(templateList);
+    return templateList;
+}
+
+//Removes template from templateList and saved file if it exists and user wants it deleted
+function removeTemplate(templateList, currentTemplate)  {
+    var tempTemplate = getTemplateByName(textIn.value, templateList);
+    if (tempTemplate)
+    {
+        if(confirm("Are you sure you want to delete Template '" + tempTemplate.name + "'?"))
+        {
+            deleteTemplatefromTemplateList(tempTemplate.name, templateList);
+            populateTemplateOptions(templateList);
+
+            //deleted template is the current template in use
+            if (currentTemplate.name == tempTemplate.name)
+            {
+                saveCurrentTemplate(null);
+                clearOptions();
+                templateSel.selectedIndex = 0;
+            }
+            else
+            {
+                selectOptionValue(templateSel, currentTemplate.name);
+            }
+            textIn.value = "";
+        }
+        else {
+            return;
+        }
+    }
+    else {
+        alert("Template '" + textIn.value + "' does not exist.");
+    }
+}
+//caches templateList and saves to file for posterity
+function saveTemplateList(templateList) {
+    g.data.search_templates = templateList;
+    g.data.stash('search_templates');
+    saveTemplateListToFile(templateList);
+}
+
+//caches template currently in use and saves it to file
+function saveCurrentTemplate(template)  {
+    g.data.current_search_template = template;
+    g.data.stash('current_search_template');
+    saveCurrentTemplateToFile(template)
+}
+
+//clears all global row input fields
+function clearGlobalRowInputs() {
+    var tBody = document.getElementById("adv_global_tbody");
+    if(tBody)
+    {
+        var rows = tBody.getElementsByTagName("tr");
+        if(rows.length > 0)
+        for (var i=0; i<rows.length; i++)
+        {
+            var inputs = rows[i].getElementsByTagName("input");
+            if (inputs.length > 0) {
+                inputs[0].value = '';
+            }
+        }
+    }
+}
+//clears input fields associated with the pubdate
+function clearPubDateInputs()
+    {
+        document.getElementById("adv_global_pub_date_1_input").value = '';
+        document.getElementById("adv_global_pub_date_2_input").value = '';
+    }
index 70063d8..7899068 100644 (file)
 <!ENTITY staff.server.admin.index.library_configuration "Library Configuration">
 <!ENTITY staff.server.admin.index.maintenance_reports "Maintenance Reports">
 <!ENTITY staff.server.admin.index.fonts_and_sounds "Global Font and Sound Settings">
+<!ENTITY staff.server.admin.index.search_templates "Search Templates">
 <!ENTITY staff.server.admin.index.printer "Printer Settings Editor">
 <!ENTITY staff.server.admin.index.do_not_auto_attempt_print_setting.label "'Do Not Attempt Auto-Print' Setting">
 <!ENTITY staff.server.admin.index.do_not_auto_attempt_print_setting.accesskey "">
index fc17229..b7fe0b4 100644 (file)
@@ -515,6 +515,35 @@ OpenILS.data.prototype = {
         }
         file.close();
 
+        JSAN.use('util.file'); var file = new util.file('yesterdays_search_template');
+        if (file._file.exists()) {
+            try {
+                var x = file.get_content();
+                if (x && x != "null") {
+                    obj.current_search_template = JSON.parse(x);
+                    obj.stash('current_search_template');
+                    obj.data_progress('Saved current search template retrieved from file. ');
+                }
+            } catch(E) {
+                alert(E);
+            }
+        }
+        file.close();
+
+        JSAN.use('util.file'); var file = new util.file('search_templates');
+        if (file._file.exists()) {
+            try {
+                var x = file.get_content();
+                if (x) {
+                    obj.search_templates = JSON.parse(x);
+                    obj.stash('search_templates');
+                    obj.data_progress('Saved search templates retrieved from file. ');
+                }
+            } catch(E) {
+                alert(E);
+            }
+        }
+        file.close();
         obj.print_list_defaults();
         obj.data_progress('Default print templates set. ');
         obj.load_saved_print_templates();
index f94e9ed..68ad136 100644 (file)
@@ -703,6 +703,12 @@ main.menu.prototype = {
                 ['oncommand'],
                 function(event) { open_admin_page('font_settings.xul', 'menu.cmd_local_admin_fonts_and_sounds.tab', false, event); }
             ],
+            'cmd_local_admin_search_templates' : [
+                ['oncommand'],
+                function(event) {
+                    open_eg_web_page('conify/global/config/search_templates', 'menu.cmd_local_admin_search_templates.tab', event);
+                }
+            ],
             'cmd_local_admin_printer' : [
                 ['oncommand'],
                 function(event) { open_admin_page('printer_settings.xul', 'menu.cmd_local_admin_printer.tab', false, event); }
index 2e984d7..c31a230 100644 (file)
 
     <!-- local admin menu commands -->
     <command id="cmd_local_admin_fonts_and_sounds" />
+    <command id="cmd_local_admin_search_templates" />
     <command id="cmd_local_admin_printer" />
     <command id="cmd_local_admin_do_not_auto_attempt_print_setting" />
     <command id="cmd_local_admin_closed_dates"
                 <menuitem label="&staff.server.admin.index.printer;" command="cmd_local_admin_printer"/>
                 <menuitem label="&staff.main.menu.admin.template_edit.label;" accesskey="&staff.main.menu.admin.template_edit.accesskey;" command="cmd_print_list_template_edit"/>
                 <menuitem label="&staff.server.admin.index.fonts_and_sounds;" command="cmd_local_admin_fonts_and_sounds"/>
+                <menuitem label="&staff.server.admin.index.search_templates;" command="cmd_local_admin_search_templates"/>
                 <menuitem label="&staff.main.menu.admin.client.search_prefs.label;" command="cmd_search_prefs"/>
                 <menuitem type="checkbox" label="&staff.main.menu.admin.client.copy_editor.copy_location.label;" command="cmd_copy_editor_copy_location_first_toggle"/>
                 <menu id="main.menu.admin.client.hotkeys" label="&staff.main.menu.admin.client.hotkeys;">
index 2405b95..7ed5be7 100644 (file)
@@ -229,6 +229,7 @@ list.dump_extended_format.record_separator==-=-=
 list.line_number=#
 menu.cmd_survey_wizard.inadequate_perm=You are lacking the CREATE_SURVEY permission and/or working locations.
 menu.cmd_local_admin_fonts_and_sounds.tab=Global Font and Sound Settings
+menu.cmd_local_admin_search_templates.tab=Search Templates
 menu.cmd_local_admin_printer.tab=Printer Settings Editor
 menu.cmd_local_admin_do_not_auto_attempt_print_setting.tab='Do Not Attempt Auto-Print' Setting
 menu.cmd_local_admin_closed_dates.tab=Closed Dates Editor
diff --git a/docs/RELEASE_NOTES_NEXT/search_templates.txt b/docs/RELEASE_NOTES_NEXT/search_templates.txt
new file mode 100644 (file)
index 0000000..f762db5
--- /dev/null
@@ -0,0 +1,33 @@
+New Feature: Search Templates
+===============================
+
+Allows staff to create 'Search Templates' which will save commonly used
+search combinations for tpac Advanced Search page. All selectable
+options available on the Advanced Search page, as well as whether
+results display in 'Detail View', can be saved. Search terms will not
+be savable.
+
+Search Templates Creation page
+
+A Search Templates Creation page will be created that mocks the
+Advanced Search page in the opac/tpac. Also available on this page would
+be a dropdown list of saved Search Templates, a textbox for entering
+template names, a 'Save Template' button, and a 'Delete Template'
+button. Staff will be able to select commonly used search option
+pairings and save them to a template on their workstation. Search
+Templates would be saved to file as a JSON object. Staff would be able
+to delete unused templates. A new menu option would be created in Admin
+-> WorkStation Administration called 'Search Templates'. This will take
+you to the Search Templates creation page. TPAC Advanced Search page.
+
+A Search Templates dropdown will be available to staff, but not patrons,
+from which they can select from their saved Search Templates.
+
+When selected, a Search Template will populate the search options
+according to the options saved to that template.
+
+The selected template will be remembered and will populate the search
+options upon returning to the Advanced Search page.
+
+A 'Default' template will also be available that 'turns off' Search
+Templates and reverts to Default Evergreen functionality.