[open-ils-commits] [GIT] Evergreen ILS branch master updated. 71871c25088e592848b90b8deba70bc6d7347d30

Evergreen Git git at git.evergreen-ils.org
Wed Aug 23 12:23:13 EDT 2017


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Evergreen ILS".

The branch, master has been updated
       via  71871c25088e592848b90b8deba70bc6d7347d30 (commit)
       via  3fa270582a1d6a11604092da8fcb3883a756d829 (commit)
       via  40f80bda176375653a8835dbad0a6311e02e66f2 (commit)
       via  3380dacfcd88ea8168e84caccf0c4e41ccd8df33 (commit)
       via  675fd78e952c3b339a9e4ea42d40e19176476d67 (commit)
      from  6830b4e30ce7f2dd5275928d47f9398461b47f4a (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 71871c25088e592848b90b8deba70bc6d7347d30
Author: Galen Charlton <gmc at equinoxinitiative.org>
Date:   Wed Aug 23 12:08:12 2017 -0400

    LP#1694577: exclude empheral search results folder from selector
    
    Otherwise, the folder selector for the move or clone template
    actions includes a blank entry.
    
    Signed-off-by: Galen Charlton <gmc at equinoxinitiative.org>
    Signed-off-by: Jason Etheridge <jason at EquinoxInitiative.org>

diff --git a/Open-ILS/web/reports/oils_rpt_folders.js b/Open-ILS/web/reports/oils_rpt_folders.js
index 71c656d..03c961d 100644
--- a/Open-ILS/web/reports/oils_rpt_folders.js
+++ b/Open-ILS/web/reports/oils_rpt_folders.js
@@ -396,6 +396,7 @@ function oilsRptBuildFolder(type, node, treeVar, rootName, action, shared, eachF
 		var f = cache[c].folder;
 
 		if( !shared && (f.owner().id() != USER.id()) ) continue;
+		if( f.id() == oilsRptSearchResultFolderId ) continue;
 
 		if(f.parent()) {
 			/* find the parent's tree id so we can latch on to it */

commit 3fa270582a1d6a11604092da8fcb3883a756d829
Author: Galen Charlton <gmc at equinoxinitiative.org>
Date:   Wed Aug 23 11:54:32 2017 -0400

    LP#1694577: tweak searching for words in report templates
    
    Use \m to recognize beginning-of-word boundaries; this fixes
    an issue where you couldn't use "clone" to retrieve templates
    whose name was of the form "foo (clone)".
    
    Signed-off-by: Galen Charlton <gmc at equinoxinitiative.org>
    Signed-off-by: Jason Etheridge <jason at EquinoxInitiative.org>

diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Reporter.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Reporter.pm
index 6d55157..81964ab 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Reporter.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Reporter.pm
@@ -759,10 +759,10 @@ sub search_templates {
         if (@$fields > 1) {
             $subq = {'-or' => []};
             for my $field (@$fields) {
-                push(@{$subq->{'-or'}}, {$field => {'~*' => "(^| )$part"}});
+                push(@{$subq->{'-or'}}, {$field => {'~*' => "(^|\\m)$part"}});
             }
         } else {
-            $subq = {$fields->[0] => {'~*' => "(^| )$part"}};
+            $subq = {$fields->[0] => {'~*' => "(^|\\m)$part"}};
         }
 
         push(@{$query->{where}->{'-and'}}, $subq);
diff --git a/docs/RELEASE_NOTES_NEXT/Reports/template-search.adoc b/docs/RELEASE_NOTES_NEXT/Reports/template-search.adoc
index 2929a79..09ec8a1 100644
--- a/docs/RELEASE_NOTES_NEXT/Reports/template-search.adoc
+++ b/docs/RELEASE_NOTES_NEXT/Reports/template-search.adoc
@@ -17,6 +17,7 @@ Examples
   ** stat cat
   ** statistical category
   ** categories, statistical
+  ** patrons (stat cat)
  * Searching for 'stat cat' does not match:
   ** stat 
    *** both words must be present in the searched field(s)

commit 40f80bda176375653a8835dbad0a6311e02e66f2
Author: Bill Erickson <berickxx at gmail.com>
Date:   Sat Aug 12 11:25:16 2017 -0400

    LP#1694577 Release notes for report template search
    
    Signed-off-by: Bill Erickson <berickxx at gmail.com>
    Signed-off-by: Galen Charlton <gmc at equinoxinitiative.org>
    Signed-off-by: Jason Etheridge <jason at EquinoxInitiative.org>

diff --git a/docs/RELEASE_NOTES_NEXT/Reports/template-search.adoc b/docs/RELEASE_NOTES_NEXT/Reports/template-search.adoc
new file mode 100644
index 0000000..2929a79
--- /dev/null
+++ b/docs/RELEASE_NOTES_NEXT/Reports/template-search.adoc
@@ -0,0 +1,32 @@
+Reports Template Searching
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+A new form appears along the top of the reports interface for searching
+report templates.  Once found, typical template actions (e.g. create new
+report) are available from within the results interface.
+
+Searches may be performed across selected (visible) folders or all 
+folders visible to the logged in user.
+
+Searches are case-insensitive, any word order, with left-anchored words.  
+All searched words must appear in at least one of the searched fields.
+
+Examples
+++++++++
+
+ * Searching for 'stat cat' matches:
+  ** stat cat
+  ** statistical category
+  ** categories, statistical
+ * Searching for 'stat cat' does not match:
+  ** stat 
+   *** both words must be present in the searched field(s)
+  ** stat location
+    *** location contains 'cat' but it's not left-anchored.
+
+Reporter Paging
++++++++++++++++
+
+The templates, reports, and output interfaces now support paging via 
+new 'Next', 'Prev', and 'Start' links next to the output limit selector.
+
+

commit 3380dacfcd88ea8168e84caccf0c4e41ccd8df33
Author: Bill Erickson <berickxx at gmail.com>
Date:   Sat Aug 12 11:12:17 2017 -0400

    LP#1694577 Reports template searching and paging
    
    Adds a new template search from along the top of the reports interface.
    Templates may be searched name and/or description.
    
    Adds paging support to the template, reports, and output interfaces.
    
    Signed-off-by: Bill Erickson <berickxx at gmail.com>
    Signed-off-by: Galen Charlton <gmc at equinoxinitiative.org>
    Signed-off-by: Jason Etheridge <jason at EquinoxInitiative.org>

diff --git a/Open-ILS/web/opac/locale/en-US/reports.dtd b/Open-ILS/web/opac/locale/en-US/reports.dtd
index 85fc17d..4654292 100644
--- a/Open-ILS/web/opac/locale/en-US/reports.dtd
+++ b/Open-ILS/web/opac/locale/en-US/reports.dtd
@@ -188,6 +188,16 @@
 <!ENTITY reports.oils_rpt_param_editor.months "Months(s)">
 <!ENTITY reports.oils_rpt_param_editor.ago " ago">
 
+<!ENTITY reports.oils_rpt_template_search_results "Template Search Results">
+<!ENTITY reports.oils_rpt_template_search_query "Template query...">
+<!ENTITY reports.oils_rpt_template_search_label "Search Templates">
+<!ENTITY reports.oils_rpt_template_search_all_fields "All Fields">
+<!ENTITY reports.oils_rpt_template_search_name "Name">
+<!ENTITY reports.oils_rpt_template_search_desc "Description">
+<!ENTITY reports.oils_rpt_template_search_all_folders "All Folders">
+<!ENTITY reports.oils_rpt_paging_start "Start">
+<!ENTITY reports.oils_rpt_paging_prev "Prev">
+<!ENTITY reports.oils_rpt_paging_next "Next">
 
 <!ENTITY reports.xul.template_builder.db_source_browser.label "Database Source Browser">
 <!ENTITY reports.xul.template_builder.sources_menulist.label "Sources">
diff --git a/Open-ILS/web/reports/oils_rpt.css b/Open-ILS/web/reports/oils_rpt.css
index 17a71ed..da744b2 100644
--- a/Open-ILS/web/reports/oils_rpt.css
+++ b/Open-ILS/web/reports/oils_rpt.css
@@ -303,6 +303,10 @@ button:disabled {
 .oils_rpt_generic_table { width: 100%; }
 .oils_rpt_generic_table td { border: 1px solid #808080; padding: 5px; }
 
+#oils_rpt_content_count_row a {
+    padding-left: 5px;
+}
+
 #oils_rpt_content_count_row_2 {
 	border-top: 2px solid #808080;
 	border-bottom: 1px solid #808080;
@@ -334,3 +338,11 @@ button:disabled {
 #oils_rpt_editor_sched_confirm:first-child {
     font-size: 110%;
 }
+
+#template_search_form_wrapper label {
+    font-weight: bold;
+}
+
+#template_search_form_wrapper span {
+    padding-right: 10px;
+}
diff --git a/Open-ILS/web/reports/oils_rpt.js b/Open-ILS/web/reports/oils_rpt.js
index 3d212de..3a75552 100644
--- a/Open-ILS/web/reports/oils_rpt.js
+++ b/Open-ILS/web/reports/oils_rpt.js
@@ -28,12 +28,21 @@ function oilsInitReports() {
 	dojo.cookie(COOKIE_SES, SESSION, { 'path' : '/', 'secure' : true});
 	dojo.cookie('ws_ou', USER.ws_ou(), { 'path' : '/', 'secure' : true});
 
+    // set the search form to submit-on-enter
+    DOM.template_search_query.onkeyup = function(evt) {
+        if (evt.keyCode == 13 && 
+            DOM.template_search_query.value) {
+            DOM.template_search_submit_button.onclick();
+        }
+    }
+
 	oilsRptFetchOrgTree(
 		function() {
 			oilsLoadRptTree(
 				function() {
 					hideMe(DOM.oils_rpt_tree_loading); 
 					unHideMe(DOM.oils_rpt_folder_table);
+					unHideMe(DOM.template_search_form_wrapper);
 				}
 			)
 		}
diff --git a/Open-ILS/web/reports/oils_rpt.xhtml b/Open-ILS/web/reports/oils_rpt.xhtml
index f3ceac5..c5bcd28 100644
--- a/Open-ILS/web/reports/oils_rpt.xhtml
+++ b/Open-ILS/web/reports/oils_rpt.xhtml
@@ -45,6 +45,29 @@
 			&reports.common.loading;
 		</div>
 
+        <div id='template_search_form_wrapper' class='hide_me'>
+            <span><label>&reports.oils_rpt_template_search_label;</label></span>
+            <span><input type='text' id='template_search_query' 
+                placeholder="&reports.oils_rpt_template_search_query;"/></span>
+            <span>
+                <select id='template_search_fields_selector'>
+                    <option value='' selected='selected'>&reports.oils_rpt_template_search_all_fields;</option>
+                    <option value='name'>&reports.oils_rpt_template_search_name;</option>
+                    <option value='description'>&reports.oils_rpt_template_search_desc;</option>
+                </select>
+            </span>
+            <span>
+                <select id='template_search_folder_selector'>
+                    <option value=''>&reports.oils_rpt_template_search_all_folders;</option>
+                </select>
+            </span>
+            <span>
+                <button id='template_search_submit_button'>
+                    &reports.oils_rpt_folder_manager.fldr_mngr_actions_submit;
+                </button>
+            </span>
+        </div>
+
 		<table id='oils_rpt_folder_table' class='hide_me'>
 			<tbody>
 				<tr>
@@ -66,7 +89,8 @@
 					<td id='oils_rpt_folder_table_right_td' class='hide_me'>
 						<div class='oils_rpt_folder_window'>
 
-							<table class='oils_rpt_tab_table' id='oils_rpt_folder_manager_tab_table'><tbody>
+							<table class='oils_rpt_tab_table hidden-for-search-results' 
+                                    id='oils_rpt_folder_manager_tab_table'><tbody>
 								<tr>
 									<td width='50%'>
 										<a id='oils_rpt_folder_window_manage_tab' href='javascript:void(0);'>&reports.oils_rpt.manage_folder_contents;</a></td>
@@ -76,14 +100,15 @@
 							</tbody></table>
 
 							<table id='oils_rpt_folder_details_table'>
-								<tbody>
-									<tr>
-										<td>
-											<span><b id='oils_rpt_folder_name_label'/>: 
-											&reports.oils_rpt.created_by;</span> <b id='oils_rpt_folder_creator_label'/>
-										</td>
-									</tr>
-								</tbody>
+								<tbody><tr><td>
+                                    <div id='real_folder_name'>
+    									<span><b id='oils_rpt_folder_name_label'/>: 
+										&reports.oils_rpt.created_by;</span> <b id='oils_rpt_folder_creator_label'/>
+                                    </div>
+                                    <div id='search_results_folder_name'>
+                                        <b>&reports.oils_rpt_template_search_results;</b>
+                                    </div>
+    							</td></tr></tbody>
 							</table>
 
 							<div>
diff --git a/Open-ILS/web/reports/oils_rpt_folder_window.js b/Open-ILS/web/reports/oils_rpt_folder_window.js
index f5e0cf8..d1ba641 100644
--- a/Open-ILS/web/reports/oils_rpt_folder_window.js
+++ b/Open-ILS/web/reports/oils_rpt_folder_window.js
@@ -23,24 +23,57 @@ function oilsRptFolderWindow(type, folderId) {
 // maps folder IDs to their containing oilsRptFolderWindow objects
 oilsRptFolderWindow.folderIdMap = {};
 
-oilsRptFolderWindow.prototype.draw = function() {
+// Here lie the contents of a specific folder
+oilsRptFolderWindow.prototype.draw = function(viaPaging) {
 
 	_debug('drawing folder window for ' + this.folderNode.folder.name() );
 
+    // always start a new folder at the first page of results
+    if (!viaPaging) oilsRptOutputOffset = 0;
+
+    console.log('drawing folder ' + this.folderNode.folder.name() + 
+        ' ; offset=' + oilsRptOutputOffset + ' ; limit=' + oilsRptOutputLimit);
+
 	var obj = this;
 	setSelector(DOM.oils_rpt_output_limit_selector, oilsRptOutputLimit);
 	setSelector(DOM.oils_rpt_output_limit_selector_2, oilsRptOutputLimit2);
 
 	DOM.oils_rpt_output_limit_selector.onchange = function() {
 		oilsRptOutputLimit = getSelectorVal(DOM.oils_rpt_output_limit_selector);
-		obj.draw();
+		obj.draw(); // resets offset
 	}
 
 	DOM.oils_rpt_output_limit_selector_2.onchange = function() {
 		oilsRptOutputLimit2 = getSelectorVal(DOM.oils_rpt_output_limit_selector_2);
-		obj.draw();
+		obj.draw(); // resets offset
 	}
 
+    DOM.oils_rpt_output_next_selector.onclick = function() {
+        oilsRptOutputOffset += Number(oilsRptOutputLimit);
+        obj.draw(true);
+    }
+
+    // Enable / disable the Previous and Start links depending on
+    // current page.
+    if (oilsRptOutputOffset <= 0) {
+        DOM.oils_rpt_output_prev_selector.onclick = function(){};
+        DOM.oils_rpt_output_first_selector.onclick = function(){};
+        DOM.oils_rpt_output_prev_selector.removeAttribute('href');
+        DOM.oils_rpt_output_first_selector.removeAttribute('href');
+    } else {
+        DOM.oils_rpt_output_prev_selector.setAttribute('href', 'javascript:');
+        DOM.oils_rpt_output_first_selector.setAttribute('href', 'javascript:');
+
+        DOM.oils_rpt_output_prev_selector.onclick = function() {
+            oilsRptOutputOffset -= Number(oilsRptOutputLimit);
+            obj.draw(true);
+        }
+
+        DOM.oils_rpt_output_first_selector.onclick = function() {
+            obj.draw(); // resets offset
+        }
+    }
+
 	var mine = ( this.folderNode.folder.owner().id() == USER.id() );
 
 	_debug('drawing folder window with type '+this.type);
@@ -486,6 +519,22 @@ oilsRptFolderWindow.prototype.drawFolderDetails = function() {
 }
 
 
+oilsRptFolderWindow.prototype.createSearchRequest = function() {
+    var field = getSelectorVal(DOM.template_search_fields_selector);
+    var fields = field ? [field] : ['name', 'description'];
+
+    return new Request(
+        'open-ils.reporter:open-ils.reporter.search.templates.atomic', 
+        SESSION, {
+            limit  : oilsRptOutputLimit,
+            offset : oilsRptOutputOffset,
+            query  : DOM.template_search_query.value,
+            folder : getSelectorVal(DOM.template_search_folder_selector),
+            fields : fields,
+        }
+    );
+}
+
 oilsRptFolderWindow.prototype.fetchFolderData = function(callback) {
 
 	hideMe(DOM.oils_rpt_content_count_row_2);
@@ -493,7 +542,8 @@ oilsRptFolderWindow.prototype.fetchFolderData = function(callback) {
 
 	removeChildren(this.selector);
 	var req = new Request(OILS_RPT_FETCH_FOLDER_DATA, 
-		SESSION, this.type, this.folderNode.folder.id(), oilsRptOutputLimit);
+		SESSION, this.type, this.folderNode.folder.id(), 
+        oilsRptOutputLimit, oilsRptOutputOffset);
 
 	hideMe(DOM.oils_rpt_pending_output);
 
@@ -504,6 +554,26 @@ oilsRptFolderWindow.prototype.fetchFolderData = function(callback) {
 			SESSION, this.folderNode.folder.id(), oilsRptOutputLimit, 0);
 	}
 
+    // Displaying the special template "Search Results" folder means 
+    // starting a new search.
+    var hidableNodes = document.getElementsByClassName('hidden-for-search-results');
+    var showableNodes = document.getElementsByClassName('show-for-search-results');
+    if (this.type == 'template' && 
+        this.folderNode.folder.id() == oilsRptSearchResultFolderId) {
+        req = this.createSearchRequest();
+
+        // when displaying search results, hide anything that should be hidden
+        dojo.forEach(hidableNodes, function(n) { n.style.visibility = 'hidden' });
+        dojo.forEach(showableNodes, function(n) { n.style.visibility = 'visible' });
+        hideMe(DOM.real_folder_name);
+        unHideMe(DOM.search_results_folder_name);
+    } else {
+        dojo.forEach(hidableNodes, function(n) { n.style.visibility = 'visible' });
+        dojo.forEach(showableNodes, function(n) { n.style.visibility = 'hidden' });
+        unHideMe(DOM.real_folder_name);
+        hideMe(DOM.search_results_folder_name);
+    }
+
 	var obj = this;
 	removeChildren(obj.selector);
 	req.callback(
diff --git a/Open-ILS/web/reports/oils_rpt_folder_window.xhtml b/Open-ILS/web/reports/oils_rpt_folder_window.xhtml
index 34090bc..1003cc3 100644
--- a/Open-ILS/web/reports/oils_rpt_folder_window.xhtml
+++ b/Open-ILS/web/reports/oils_rpt_folder_window.xhtml
@@ -9,7 +9,7 @@
 	<table id='oils_rpt_folder_window_contents_table'>
 		<tbody>
 			<tr>
-				<td colspan='2'> 
+				<td colspan='2' _class='hidden-for-search-results'> 
 					<span>
 						<select id='oils_rpt_folder_contents_action_selector' style='width: auto;'>
 							<option type='template' value='create_report'>&reports.oils_rpt_folder_window.new_report_from_template;</option>
@@ -41,10 +41,13 @@
 							<option value='50'>50</option>
 							<option value=''>&reports.oils_rpt_folder_window.all;</option>
 						</select>
+                        <a id='oils_rpt_output_first_selector' href='javascript:void(0);'>&reports.oils_rpt_paging_start;</a>
+                        <a id='oils_rpt_output_prev_selector' href='javascript:void(0);'>&reports.oils_rpt_paging_prev;</a>
+                        <a id='oils_rpt_output_next_selector' href='javascript:void(0);'>&reports.oils_rpt_paging_next;</a>
 						<span><b id='oils_rpt_pending_output' class='hide_me'>&reports.oils_rpt_folder_window.pending_items;</b></span>
 					</div>
 				</td>
-				<td style='text-align:right;'>
+				<td style='text-align:right;' class='hidden-for-search-results'>
 					<a id='oils_rpt_folder_window_contents_new_template' 
 						href='javascript:void(0);'><b>&reports.oils_rpt_folder_window.new_template;</b></a>
 				</td>
diff --git a/Open-ILS/web/reports/oils_rpt_folders.js b/Open-ILS/web/reports/oils_rpt_folders.js
index 2c2b3ff..71c656d 100644
--- a/Open-ILS/web/reports/oils_rpt_folders.js
+++ b/Open-ILS/web/reports/oils_rpt_folders.js
@@ -6,6 +6,9 @@ var oilsRptFolderNodeCache = {};
 oilsRptFolderNodeCache.template = {};
 oilsRptFolderNodeCache.report  = {};
 oilsRptFolderNodeCache.output  = {};
+// ephemeral template search results folder needs an ID.
+var oilsRptSearchResultFolderId = -1000; 
+var oilsRptSearchResultFolderWindowId = null;
 
 oilsRptSetSubClass('oilsRptFolderManager','oilsRptObject');
 
@@ -130,6 +133,10 @@ oilsRptFolderManager.prototype.draw = function(auth) {
 
 	oilsRptSharedOutputFolderTree.addNode(this.soId, -1, rpt_strings.FOLDERS_OUTPUT)
 
+    DOM.template_search_submit_button.onclick = function() {
+        oilsRptObject.find(oilsRptSearchResultFolderWindowId).draw();
+    }
+
 	this.fetchFolders(auth);
 }
 
@@ -190,6 +197,15 @@ oilsRptFolderManager.prototype.drawFolders = function(type, folders) {
 	var tree;
 	var owners = {};
 
+    // Special search results folders ; not added to folder tree.
+    if (type == 'template') {
+        var resFolder = new rtf();
+        resFolder.id(oilsRptSearchResultFolderId);
+        resFolder.name(''); // not shown
+        resFolder.owner(USER);
+        folders.unshift(resFolder);
+    }
+
 	for( var i = 0; i < folders.length; i++ ) {
 
 		var folder = folders[i];
@@ -199,6 +215,9 @@ oilsRptFolderManager.prototype.drawFolders = function(type, folders) {
 		oilsRptFolderNodeCache[type][folder.id()] = node;
 		node.folderWindow = new oilsRptFolderWindow(type, folder.id())
 
+        if (folder.id() == oilsRptSearchResultFolderId) 
+            oilsRptSearchResultFolderWindowId = node.folderWindow.id;
+
 		/*
 		_debug("creating folder node for "+folder.name()+" : id = "+
 			folder.id()+' treeId = '+id + ' window id = ' + node.folderWindow.id);
@@ -238,9 +257,9 @@ oilsRptFolderManager.prototype.drawFolders = function(type, folders) {
 		}
 	}
 
+    var search_folders = [];
 	for( var i = 0; i < folders.length; i++ ) {
 
-
 		var folder = folders[i];
 		var mine = (folder.owner().id() == USER.id());
 		var pid;
@@ -283,8 +302,13 @@ oilsRptFolderManager.prototype.drawFolders = function(type, folders) {
 
 		node = this.findNode(type, folder.id());
 		id = node.treeId;
-		if( folder.parent() ) 
-			pid = this.findNode(type, folder.parent()).treeId;
+		if( folder.parent() ) {
+            var pnode = this.findNode(type, folder.parent());
+			pid = pnode.treeId;
+            node.depth = pnode.depth + 1;
+        } else {
+            node.depth = 0;
+        }
 
 		var fname = folder.name();
 
@@ -304,9 +328,38 @@ oilsRptFolderManager.prototype.drawFolders = function(type, folders) {
 			+pid + ' parent = ' + folder.parent() + ' folder-window = ' + node.folderWindow.id );
 			*/
 
-		tree.addNode(id, pid, fname, action);
-		tree.close(pid);
+        if (folder.id() != oilsRptSearchResultFolderId) {
+            search_folders.push({id : folder.id(), pid: folder.parent(), fname : fname, depth : node.depth});
+		    tree.addNode(id, pid, fname, action);
+		    tree.close(pid);
+        }
 	}
+
+    // search only applies to templates
+    if (type != 'template') return;
+
+    // Sort the list of search folders from top to bottom of the folder tree.
+    var depth_cache = {};
+    function add_folder(node) {
+        if (!node) return;
+
+        var label = node.fname;
+        // Left-pad the selector options by depth with U+2003 'EM SPACE'
+        // characters so the browser won't collapse the space.
+        for (var i = 0; i < node.depth; i++) label = ' ' + label;
+
+        insertSelectorVal(
+            DOM.template_search_folder_selector, -1, label, node.id);
+
+        var children = search_folders.filter(
+            function(f) { return (f.pid == node.id) });
+        dojo.forEach(children, add_folder);
+    }
+
+    // start with the parent-less folders
+    dojo.forEach(
+        search_folders.filter(
+            function(f) {return f.pid == null}), add_folder);
 }
 
 
diff --git a/Open-ILS/web/reports/oils_rpt_vars.js b/Open-ILS/web/reports/oils_rpt_vars.js
index bf3594e..bd9a5e5 100644
--- a/Open-ILS/web/reports/oils_rpt_vars.js
+++ b/Open-ILS/web/reports/oils_rpt_vars.js
@@ -24,6 +24,7 @@ var oilsRptSharedOutputFolderTree;
 
 var oilsRptOutputLimit = 10;
 var oilsRptOutputLimit2 = 10;
+var oilsRptOutputOffset = 0;
 
 var OILS_RPT_INVALID_DATA = 'oils_rpt_invalid_input';
 

commit 675fd78e952c3b339a9e4ea42d40e19176476d67
Author: Bill Erickson <berickxx at gmail.com>
Date:   Sat Aug 12 11:08:30 2017 -0400

    LP#1694577 Report templates search API & paging
    
    Adds new API call open-ils.reporter.search.templates allowing search of
    reporter template names and/or descriptions.  Searching is
    case-insensitive, any order, with left-anchored words.  Searching can be
    for specific folders or all folders visible to the calling user.
    
    Adds paging support (limit / offset) for retriving templates, reports,
    and outputs.
    
    Signed-off-by: Bill Erickson <berickxx at gmail.com>
    Signed-off-by: Galen Charlton <gmc at equinoxinitiative.org>
    Signed-off-by: Jason Etheridge <jason at EquinoxInitiative.org>

diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Reporter.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Reporter.pm
index 897fb22..6d55157 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Reporter.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Reporter.pm
@@ -109,7 +109,7 @@ __PACKAGE__->register_method(
 );
 
 sub retrieve_folder_data {
-    my( $self, $conn, $auth, $type, $folderid, $limit ) = @_;
+    my( $self, $conn, $auth, $type, $folderid, $limit, $offset ) = @_;
     my $e = new_rstore_editor(authtoken=>$auth);
     return $e->event unless $e->checkauth;
     if($type eq 'output') {
@@ -126,6 +126,7 @@ sub retrieve_folder_data {
         order_by => { $class => 'create_time DESC'}
     };
     $flesh->{limit} = $limit if $limit;
+    $flesh->{offset} = $offset if $offset;
     return $e->$meth([{ folder => $folderid }, $flesh]);
 }
 
@@ -674,5 +675,110 @@ sub magic_fetch_all {
     return $e->$method($margs);
 }
 
+__PACKAGE__->register_method(
+    method => 'search_templates',
+    api_name => 'open-ils.reporter.search.templates',
+    stream => 1
+);
+
+sub search_templates {
+    my ($self, $client, $auth, $query_args) = @_;
+
+    my $limit  = $query_args->{limit} || 100;
+    my $offset = $query_args->{offset} || 0;
+    my $folder = $query_args->{folder};
+    my $fields = $query_args->{fields} || ['name','description'];
+    my $query_string  = $query_args->{query};
+
+    return undef unless $query_string;
+
+    my $e = new_rstore_editor(authtoken => $auth);
+    return $e->event unless $e->checkauth;
+
+    my ($visible_folders) = $self
+        ->method_lookup('open-ils.reporter.folder.visible.retrieve')
+        ->run($auth, 'template');
+
+    my @visible_folder_ids = map { $_->id } @$visible_folders; 
+
+    return undef unless @$visible_folders;
+
+    my $query = {
+        select => {rt => ['id']},
+        from => 'rt',
+        where => {
+            folder => \@visible_folder_ids,
+            '-and' => []
+        },
+        limit => $limit,
+        offset => $offset
+    };
+
+    if ($folder) { # search request for specific folder + sub-folders
+        my ($root_folder) = grep { $_->id == $folder} @$visible_folders;
+
+        return OpenILS::Event->new('BAD_PARAMS', 
+            desc => q/Cannot search requested folder/) unless $root_folder;
+
+        # find all folders that are descendants of the selected folder.
+        my @ffilter;
+        my $finder;
+        $finder = sub {
+            my $node = shift;
+            return unless $node;
+            push(@ffilter, $node->id);
+            my @children = grep { $_->parent == $node->id } @$visible_folders;
+            $finder->($_) for @children;
+        };
+
+        $finder->($root_folder);
+        $query->{where}->{folder} = \@ffilter;
+    }
+
+    $query_string =~ s/^\s+|\s+$//gm; # remove open/trailing spaces
+    my @query_parts = split(/ +/, $query_string);
+
+    # Compile the query parts and searched fields down to a JSON-query
+    # structure like this.  Note that single-field searches have no
+    # nested -or's.
+    # where => {
+    #   -and => [
+    #       {-or => [
+    #           {$field1 => {~* => $value1}},
+    #           {$field2 => {~* => $value1}}
+    #       },
+    #       {-or => [
+    #           {$field1 => {~* => $value2}},
+    #           {$field2 => {~* => $value2}}
+    #       }
+    #   ]
+    #}
+    for my $part (@query_parts) {
+        my $subq;
+
+        if (@$fields > 1) {
+            $subq = {'-or' => []};
+            for my $field (@$fields) {
+                push(@{$subq->{'-or'}}, {$field => {'~*' => "(^| )$part"}});
+            }
+        } else {
+            $subq = {$fields->[0] => {'~*' => "(^| )$part"}};
+        }
+
+        push(@{$query->{where}->{'-and'}}, $subq);
+    }
+
+    my $template_ids = $e->json_query($query);
+
+    # Flesh template owner for consistency with retrieve_folder_data
+    my $flesh = {flesh => 1, flesh_fields => {rt => ['owner']}};
+
+    $client->respond($e->retrieve_reporter_template([$_->{id}, $flesh])) 
+        for @$template_ids;
+
+    return;
+}
+
+
 
 1;

-----------------------------------------------------------------------

Summary of changes:
 .../perlmods/lib/OpenILS/Application/Reporter.pm   |  108 +++++++++++++++++++-
 Open-ILS/web/opac/locale/en-US/reports.dtd         |   10 ++
 Open-ILS/web/reports/oils_rpt.css                  |   12 ++
 Open-ILS/web/reports/oils_rpt.js                   |    9 ++
 Open-ILS/web/reports/oils_rpt.xhtml                |   43 ++++++--
 Open-ILS/web/reports/oils_rpt_folder_window.js     |   78 +++++++++++++-
 Open-ILS/web/reports/oils_rpt_folder_window.xhtml  |    7 +-
 Open-ILS/web/reports/oils_rpt_folders.js           |   64 +++++++++++-
 Open-ILS/web/reports/oils_rpt_vars.js              |    1 +
 .../Reports/template-search.adoc                   |   33 ++++++
 10 files changed, 344 insertions(+), 21 deletions(-)
 create mode 100644 docs/RELEASE_NOTES_NEXT/Reports/template-search.adoc


hooks/post-receive
-- 
Evergreen ILS


More information about the open-ils-commits mailing list