From 51b548428944ae9a90e88200b578bfcc46aa2787 Mon Sep 17 00:00:00 2001 From: erickson Date: Fri, 21 Aug 2009 15:33:58 +0000 Subject: [PATCH] more work on pcrud filter dialog. added filter option to autogrid. repaired faulty linked object caching in autogrid. with caching repaired, made linked grid cell data fetching synchronous to prevent excessive network requests (1st instance of an object is cached) git-svn-id: svn://svn.open-ils.org/ILS/branches/rel_1_6@13914 dcc99617-32d9-48b4-a31d-7c20da2025e4 --- .../web/js/dojo/openils/widget/AutoFieldWidget.js | 37 +++--- Open-ILS/web/js/dojo/openils/widget/AutoGrid.js | 45 ++++++-- .../js/dojo/openils/widget/PCrudFilterDialog.js | 128 +++++++++++++++++++++ 3 files changed, 187 insertions(+), 23 deletions(-) create mode 100644 Open-ILS/web/js/dojo/openils/widget/PCrudFilterDialog.js diff --git a/Open-ILS/web/js/dojo/openils/widget/AutoFieldWidget.js b/Open-ILS/web/js/dojo/openils/widget/AutoFieldWidget.js index 0b4a24213e..23192cf4bc 100644 --- a/Open-ILS/web/js/dojo/openils/widget/AutoFieldWidget.js +++ b/Open-ILS/web/js/dojo/openils/widget/AutoFieldWidget.js @@ -9,8 +9,6 @@ if(!dojo._hasResource['openils.widget.AutoFieldWidget']) { dojo.declare('openils.widget.AutoFieldWidget', null, { async : false, - cache : {}, - cacheSingle : {}, /** * args: @@ -48,9 +46,10 @@ if(!dojo._hasResource['openils.widget.AutoFieldWidget']) { this.fmClass + ' fmField=' + this.fmField + ' fmObject=' + js2JSON(this.fmObject)); this.auth = openils.User.authtoken; - if(!this.cache[this.auth]) { - this.cache[this.auth] = {}; - } + this.cache = openils.widget.AutoFieldWidget.cache; + this.cache[this.auth] = this.cache[this.auth] || {}; + this.cache[this.auth].single = this.cache[this.auth].single || {}; + this.cache[this.auth].list = this.cache[this.auth].list || {}; }, /** @@ -217,8 +216,8 @@ if(!dojo._hasResource['openils.widget.AutoFieldWidget']) { // first try the store cache var self = this; - if(this.cache[this.auth][lclass]) { - var store = this.cache[this.auth][lclass]; + if(this.cache[this.auth].list[lclass]) { + var store = this.cache[this.auth].list[lclass]; var query = {}; query[linkInfo.vfield.name] = ''+this.widgetValue; store.fetch({query:query, onComplete: @@ -230,11 +229,13 @@ if(!dojo._hasResource['openils.widget.AutoFieldWidget']) { } // then try the single object cache - if(this.cacheSingle[lclass] && this.cacheSingle[lclass][this.widgetValue]) { - this.widgetValue = this.cacheSingle[lclass][this.widgetValue]; + if(this.cache[this.auth].single[lclass] && this.cache[this.auth].single[lclass][this.widgetValue]) { + this.widgetValue = this.cache[this.auth].single[lclass][this.widgetValue]; return; } + console.log("Fetching sync object " + lclass + " : " + this.widgetValue); + // if those fail, fetch the linked object this.async = true; var self = this; @@ -242,10 +243,13 @@ if(!dojo._hasResource['openils.widget.AutoFieldWidget']) { async : !this.forceSync, oncomplete : function(r) { var item = openils.Util.readResponse(r); - if(!self.cacheSingle[lclass]) - self.cacheSingle[lclass] = {}; - self.widgetValue = item[linkInfo.vfield.selector](); - self.cacheSingle[lclass][self.widgetValue] = item; + var newvalue = item[linkInfo.vfield.selector](); + + if(!self.cache[self.auth].single[lclass]) + self.cache[self.auth].single[lclass] = {}; + self.cache[self.auth].single[lclass][self.widgetValue] = newvalue; + + self.widgetValue = newvalue; self.widget.startup(); self._widgetLoaded(); } @@ -306,15 +310,15 @@ if(!dojo._hasResource['openils.widget.AutoFieldWidget']) { if(list) { self.widget.store = new dojo.data.ItemFileReadStore({data:fieldmapper[linkClass].toStoreData(list)}); - self.cache[self.auth][linkClass] = self.widget.store; + self.cache[self.auth].list[linkClass] = self.widget.store; } else { - self.widget.store = self.cache[self.auth][linkClass]; + self.widget.store = self.cache[self.auth].list[linkClass]; } self.widget.startup(); self._widgetLoaded(); }; - if(this.cache[self.auth][linkClass]) { + if(this.cache[self.auth].list[linkClass]) { oncomplete(); } else { @@ -452,5 +456,6 @@ if(!dojo._hasResource['openils.widget.AutoFieldWidget']) { }); openils.widget.AutoFieldWidget.localeStrings = dojo.i18n.getLocalization("openils.widget", "AutoFieldWidget"); + openils.widget.AutoFieldWidget.cache = {}; } diff --git a/Open-ILS/web/js/dojo/openils/widget/AutoGrid.js b/Open-ILS/web/js/dojo/openils/widget/AutoGrid.js index f57f36a42f..78628a12f4 100644 --- a/Open-ILS/web/js/dojo/openils/widget/AutoGrid.js +++ b/Open-ILS/web/js/dojo/openils/widget/AutoGrid.js @@ -26,6 +26,7 @@ if(!dojo._hasResource['openils.widget.AutoGrid']) { displayLimit : 15, displayOffset : 0, showPaginator : false, + showLoadFilter : false, suppressLinkedFields : null, // list of fields whose linked display data should not be fetched from the server /* by default, don't show auto-generated (sequence) fields */ @@ -78,7 +79,7 @@ if(!dojo._hasResource['openils.widget.AutoGrid']) { var back = dojo.create('a', { - innerHTML : 'Back', + innerHTML : 'Back', // TODO i18n style : 'padding-right:6px;', href : 'javascript:void(0);', onclick : function() { @@ -92,7 +93,7 @@ if(!dojo._hasResource['openils.widget.AutoGrid']) { }); var forw = dojo.create('a', { - innerHTML : 'Next', + innerHTML : 'Next', // TODO i18n style : 'padding-right:6px;', href : 'javascript:void(0);', onclick : function() { @@ -108,8 +109,31 @@ if(!dojo._hasResource['openils.widget.AutoGrid']) { dojo.place(this.paginator.domNode, this.domNode, 'before'); dojo.place(back, this.paginator.domNode); dojo.place(forw, this.paginator.domNode); + + if(this.showLoadFilter) { + dojo.require('openils.widget.PCrudFilterDialog'); + dojo.place( + dojo.create('a', { + innerHTML : 'Filter', // TODO i18n + style : 'padding-right:6px;', + href : 'javascript:void(0);', + onclick : function() { + var dialog = new openils.widget.PCrudFilterDialog({fmClass:self.fmClass}) + dialog.onApply = function(filter) { + self.resetStore(); + self.loadAll(self.cachedQueryOpts, filter); + }; + dialog.startup(); + dialog.show(); + } + }), + this.paginator.domNode + ); + } + + // progress image this.loadProgressIndicator = dojo.create('img', { - src:'/opac/images/progressbar_green.gif', + src:'/opac/images/progressbar_green.gif', // TODO configured path style:'height:16px;width:16px;' }); dojo.place(this.loadProgressIndicator, this.paginator.domNode); @@ -540,18 +564,25 @@ if(!dojo._hasResource['openils.widget.AutoGrid']) { fmField: this.field, widgetValue : val, readOnly : true, + forceSync : true, // prevents many simultaneous requests for the same data suppressLinkedFields : this.grid.suppressLinkedFields }); + autoWidget.build(); + + /* + // With proper caching, this should not be necessary to prevent grid render flickering var _this = this; autoWidget.build( function(w, ww) { - var node = _this.grid.getCell(_this.index).view.getCellNode(rowIndex, _this.index); - if(node) { - node.innerHTML = ww.getDisplayString(); - } + try { + var node = _this.grid.getCell(_this.index).view.getCellNode(rowIndex, _this.index); + if(node) + node.innerHTML = ww.getDisplayString(); + } catch(E) {} } ); + */ return autoWidget.getDisplayString(); } diff --git a/Open-ILS/web/js/dojo/openils/widget/PCrudFilterDialog.js b/Open-ILS/web/js/dojo/openils/widget/PCrudFilterDialog.js new file mode 100644 index 0000000000..a1cfe2b6a7 --- /dev/null +++ b/Open-ILS/web/js/dojo/openils/widget/PCrudFilterDialog.js @@ -0,0 +1,128 @@ + +if(!dojo._hasResource['openils.widget.PCrudFilterDialog']) { + dojo.provide('openils.widget.PCrudFilterDialog'); + dojo.require('openils.widget.AutoFieldWidget'); + dojo.require('dijit.form.FilteringSelect'); + dojo.require('dijit.form.Button'); + dojo.require('dojo.data.ItemFileReadStore'); + dojo.require('dijit.Dialog'); + dojo.require('openils.Util'); + + /** + * Given a fieldmapper object, this builds a pop-up dialog used for editing the object + */ + + dojo.declare( + 'openils.widget.PCrudFilterDialog', + [dijit.Dialog, openils.widget.AutoWidget], + { + + constructor : function(args) { + for(var k in args) + this[k] = args[k]; + this.widgetIndex = 0; + this.widgetCache = {}; + }, + + /** + * Builds a basic table of key / value pairs. Keys are IDL display labels. + * Values are dijit's, when values set + */ + startup : function() { + var self = this; + this.inherited(arguments); + this.initAutoEnv(); + var realFieldList = this.sortedFieldList.filter( + function(item) { return !item.virtual; }); + this.fieldStore = new dojo.data.ItemFileReadStore({ + data : { + identifier : 'name', + name : 'label', + items : realFieldList.map( + function(item) { + return {label:item.label, name:item.name}; + } + ) + } + }); + + // TODO i18n/CSS + dojo.place( + dojo.create( + 'div', + {innerHTML:'Filter Selector', style:'text-align:center;width:100%;padding:10px;'} + ), this.domNode); + + dojo.place( + new dijit.form.Button({ + label:"Apply", + onClick : function() { + if(self.onApply) + self.onApply(self.compileFilter()); + self.hide(); + } + }).domNode, this.domNode); + + dojo.place( + new dijit.form.Button({ + label:"Cancel", + onClick : function() { + if(self.onCancel) + self.onCancel(); + self.hide(); + } + }).domNode, this.domNode); + + this.table = dojo.place(dojo.create('table'), this.domNode); + openils.Util.addCSSClass(this.table, 'oils-fm-edit-dialog'); + this.insertFieldSelector(); + }, + + insertFieldSelector : function() { + var selector = new dijit.form.FilteringSelect({labelAttr:'label', store:this.fieldStore}); + var row = dojo.place(dojo.create('tr'), this.table); + var selectorTd = dojo.place(dojo.create('td'), row); + var valueTd = dojo.place(dojo.create('td'), row); + dojo.place(selector.domNode, selectorTd); + + // dummy text box + dojo.place(new dijit.form.TextBox().domNode, valueTd); + + // when a field is selected, update the value widget + var self = this; + dojo.connect(selector, 'onChange', + function(value) { + + if(valueTd.childNodes[0]) + valueTd.removeChild(valueTd.childNodes[0]); + + var widget = new openils.widget.AutoFieldWidget({ + fmClass : self.fmClass, + fmField : value, + parentNode : dojo.place(dojo.create('div'), valueTd) + }); + widget.build(); + + if(self.widgetCache[selector.widgetIndex]) { + self.widgetCache[selector.widgetIndex].widget.destroy(); + delete self.widgetCache[selector.widgetIndex]; + } + + selector.widgetIndex = this.widgetIndex; + self.widgetCache[self.widgetIndex++] = widget; + } + ); + }, + + compileFilter : function() { + var filter = {}; + for(var i in this.widgetCache) { + var widget = this.widgetCache[i]; + filter[widget.fmField] = widget.getFormattedValue(); + } + return filter; + } + } + ); +} + -- 2.11.0