1 /*
  2  * Copyright (c) 2012-2018 LabKey Corporation
  3  *
  4  * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0
  5  */
  6 Ext.namespace('LABKEY.ext');
  7 
  8 // TODO: Get these off the global 'Date' object
  9 Ext.ns("Date.patterns");
 10 Ext.applyIf(Date.patterns,{
 11     ISO8601Long:"Y-m-d H:i:s",
 12     ISO8601Short:"Y-m-d"
 13 });
 14 
 15 LABKEY.ext.Utils = new function() {
 16     var createHttpProxyImpl = function(containerPath, errorListener) {
 17         var proxy = new Ext.data.HttpProxy(new Ext.data.Connection({
 18             //where to retrieve data
 19             url: LABKEY.ActionURL.buildURL("query", "selectRows", containerPath), //url to data object (server side script)
 20             method: 'GET'
 21         }));
 22 
 23         if (errorListener)
 24             proxy.on("loadexception", errorListener);
 25 
 26         proxy.on("beforeload", mapQueryParameters);
 27 
 28         return proxy;
 29     };
 30 
 31     var mapQueryParameters = function(store, options) {
 32         // map all parameters from ext names to labkey names:
 33         for (var p in options)
 34         {
 35             if (options.hasOwnProperty(p)) {
 36                 if (_extParamMapping[p])
 37                     options[_extParamMapping[p]] = options[p];
 38             }
 39         }
 40 
 41         // fix up any necessary parameter values:
 42         if ("DESC" == options['query.sortdir'])
 43         {
 44             var sortCol = options['query.sort'];
 45             options['query.sort'] = "-" + sortCol;
 46         }
 47     };
 48 
 49     /**
 50      * This method takes an object that is/extends an Ext3.Container (e.g. Panels, Toolbars, Viewports, Menus) and
 51      * resizes it so the Container fits inside the its parent container.
 52      * @param extContainer - (Required) outer container which is the target to be resized
 53      * @param options - The set of options
 54      * @param options.skipWidth - true to skip updating width, default false
 55      * @param options.skipHeight - true to skip updating height, default false
 56      * @param options.paddingWidth - total width padding
 57      * @param options.paddingHeight - total height padding
 58      * @param options.offsetY - distance between bottom of page to bottom of component
 59      */
 60     var resizeToContainer = function(extContainer, options) {
 61         var config = {
 62             offsetY: 35,
 63             paddingHeight: 0,
 64             paddingWidth: 0,
 65             skipHeight: false,
 66             skipWidth: false
 67         };
 68 
 69         if (Ext.isObject(options)) {
 70             config = Ext.apply(config, options);
 71         }
 72         // else ignore the parameters
 73 
 74         if (!extContainer || !extContainer.rendered || (config.skipWidth && config.skipHeight)) {
 75             return;
 76         }
 77 
 78         var height = 0;
 79         var width = 0;
 80 
 81         if (!config.skipWidth) {
 82             width = extContainer.el.parent().getBox().width;
 83         }
 84 
 85 
 86         if (!config.skipHeight) {
 87             height = window.innerHeight - extContainer.el.getXY()[1];
 88         }
 89 
 90         var padding = [
 91             config.paddingWidth,
 92             config.paddingHeight
 93         ];
 94 
 95         var size = {
 96             width: Math.max(100, width - padding[0]),
 97             height: Math.max(100, height - padding[1] - config.offsetY)
 98         };
 99 
100         if (config.skipWidth) {
101             extContainer.setHeight(size.height);
102         }
103         else if (config.skipHeight) {
104             extContainer.setWidth(size.width);
105         }
106         else {
107             extContainer.setSize(size);
108         }
109 
110         extContainer.doLayout();
111     };
112 
113     return {
114         /**
115          * Creates an Ext.data.Store that queries the LabKey Server database and can be used as the data source
116          * for various components, including GridViews, ComboBoxes, and so forth.
117          * @deprecated
118          * @param {Object} config Describes the GridView's properties.
119          * @param {String} config.schemaName Name of a schema defined within the current
120          *                 container.  Example: 'study'.  See also: <a class="link"
121          href="https://www.labkey.org/Documentation/wiki-page.view?name=findNames">
122          How To Find schemaName, queryName & viewName</a>.
123          * @param {String} config.queryName Name of a query defined within the specified schema
124          *                 in the current container.  Example: 'SpecimenDetail'. See also: <a class="link"
125          href="https://www.labkey.org/Documentation/wiki-page.view?name=findNames">
126          How To Find schemaName, queryName & viewName</a>.
127          * @param {String} [config.containerPath] The container path in which the schemaName and queryName are defined.
128          * @param {String} [config.viewName] Name of a custom view defined over the specified query.
129          *                 in the current container. Example: 'SpecimenDetail'.  See also: <a class="link"
130          href="https://www.labkey.org/Documentation/wiki-page.view?name=findNames">
131          How To Find schemaName, queryName & viewName</a>.
132          * @param {Object} [config.allowNull] If specified, this configuration will be used to insert a blank
133          *                 entry as the first entry in the store.
134          * @param {String} [config.allowNull.keyColumn] If specified, the name of the column in the underlying database
135          *                 that holds the key.
136          * @param {String} [config.allowNull.displayColumn] If specified, the name of the column in the underlying database
137          *                 that holds the value to be shown by default in the display component.
138          * @param {String} [config.allowNull.emptyName] If specified, what to show in the list for the blank entry.
139          *                 Defaults to '[None]'.
140          * @param {String} [config.allowNull.emptyValue] If specified, the value to be used for the blank entry.
141          *                 Defaults to the empty string.
142          *
143          * @return {Ext.data.Store} The initialized Store object
144          */
145         createExtStore: function(storeConfig) {
146             if (!storeConfig)
147                 storeConfig = {};
148             if (!storeConfig.baseParams)
149                 storeConfig.baseParams = {};
150             storeConfig.baseParams['query.queryName'] = storeConfig.queryName;
151             storeConfig.baseParams['schemaName'] = storeConfig.schemaName;
152             if (storeConfig.viewName)
153                 storeConfig.baseParams['query.viewName'] = storeConfig.viewName;
154 
155             if (!storeConfig.proxy)
156                 storeConfig.proxy = createHttpProxyImpl(storeConfig.containerPath);
157 
158             if (!storeConfig.remoteSort)
159                 storeConfig.remoteSort = true;
160 
161             if (!storeConfig.listeners || !storeConfig.listeners.loadexception)
162                 storeConfig.listeners = { loadexception : { fn : handleLoadError } };
163 
164             storeConfig.reader = new Ext.data.JsonReader();
165 
166             var result = new Ext.data.Store(storeConfig);
167 
168             if (storeConfig.allowNull)
169             {
170                 var emptyValue = storeConfig.allowNull.emptyValue;
171                 if (!emptyValue)
172                 {
173                     emptyValue = "";
174                 }
175                 var emptyName = storeConfig.allowNull.emptyName;
176                 if (!emptyName)
177                 {
178                     emptyName = "[None]";
179                 }
180                 result.on("load", function(store)
181                 {
182                     var emptyRecordConstructor = Ext.data.Record.create([storeConfig.allowNull.keyColumn, storeConfig.allowNull.displayColumn]);
183                     var recordData = {};
184                     recordData[storeConfig.allowNull.keyColumn] = emptyValue;
185                     recordData[storeConfig.allowNull.displayColumn] = emptyName;
186                     var emptyRecord = new emptyRecordConstructor(recordData);
187                     store.insert(0, emptyRecord);
188                 });
189             }
190 
191             return result;
192         },
193 
194         /**
195          * Ensure BoxComponent is visible on the page.
196          * @param boxComponent
197          * @deprecated
198          */
199         ensureBoxVisible: function(boxComponent) {
200             var box = boxComponent.getBox(true);
201             var viewportWidth = Ext.lib.Dom.getViewWidth();
202             var scrollLeft = Ext.dd.DragDropMgr.getScrollLeft();
203 
204             var scrollBarWidth = 20;
205             if (viewportWidth - scrollBarWidth + scrollLeft < box.width + box.x) {
206                 boxComponent.setPosition(viewportWidth + scrollLeft - box.width - scrollBarWidth);
207             }
208         },
209 
210         /**
211          * Use LABKEY.Utils.handleTabsInTextArea instead
212          * @deprecated
213          */
214         handleTabsInTextArea: function(event){
215             LABKEY.Utils.handleTabsInTextArea(event);
216         },
217 
218         /**
219          * This method takes an object that is/extends an Ext.Container (e.g. Panels, Toolbars, Viewports, Menus) and
220          * resizes it so the Container fits inside the viewable region of the window. This is generally used in the case
221          * where the Container is not rendered to a webpart but rather displayed on the page itself (e.g. SchemaBrowser,
222          * manageFolders, etc).
223          * @param extContainer - (Required) outer container which is the target to be resized
224          * @param width - (Required) width of the viewport. In many cases, the window width. If a negative width is passed than
225          *                           the width will not be set.
226          * @param height - (Required) height of the viewport. In many cases, the window height. If a negative height is passed than
227          *                           the height will not be set.
228          * @param paddingX - distance from the right edge of the viewport. Defaults to 35.
229          * @param paddingY - distance from the bottom edge of the viewport. Defaults to 35.
230          */
231         resizeToViewport: function(extContainer, width, height, paddingX, paddingY, offsetX, offsetY)
232         {
233             resizeToContainer.apply(this, arguments);
234         }
235     };
236 };