1 /**
  2  * @fileOverview
  3  * @author <a href="https://www.labkey.org">LabKey</a> (<a href="mailto:info@labkey.com">info@labkey.com</a>)
  4  * @license Copyright (c) 2014-2016 LabKey Corporation
  5  * <p/>
  6  * Licensed under the Apache License, Version 2.0 (the "License");
  7  * you may not use this file except in compliance with the License.
  8  * You may obtain a copy of the License at
  9  * <p/>
 10  * http://www.apache.org/licenses/LICENSE-2.0
 11  * <p/>
 12  * Unless required by applicable law or agreed to in writing, software
 13  * distributed under the License is distributed on an "AS IS" BASIS,
 14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 15  * See the License for the specific language governing permissions and
 16  * limitations under the License.
 17  * <p/>
 18  */
 19 LABKEY.Query = new function(impl, $) {
 20 
 21     // Insert a hidden <form> into to page, put the JSON into it, and submit it - the server's response
 22     // will make the browser pop up a dialog
 23     function submitForm(url, formData) {
 24         if (!formData['X-LABKEY-CSRF'])
 25             formData['X-LABKEY-CSRF'] = LABKEY.CSRF;
 26 
 27         var formId = LABKEY.Utils.generateUUID();
 28 
 29         var html = '<form method="POST" id="' + formId + '"action="' + url + '">';
 30         for (var name in formData)
 31         {
 32             if (!formData.hasOwnProperty(name))
 33                 continue;
 34 
 35             var value = formData[name];
 36             if (value == undefined)
 37                 continue;
 38 
 39             html += '<input type="hidden"' +
 40                     ' name="' + LABKEY.Utils.encodeHtml(name) + '"' +
 41                     ' value="' + LABKEY.Utils.encodeHtml(value) + '" />';
 42         }
 43         html += "</form>";
 44 
 45         $('body').append(html);
 46         $('form#' + formId).submit();
 47     }
 48 
 49     /**
 50      * Execute arbitrary LabKey SQL and export the results to Excel or TSV. After this method is
 51      * called, the user will be prompted to accept a file from the server, and most browsers will allow
 52      * the user to either save it or open it in an appropriate application.
 53      * For more information, see the
 54      * <a href="https://www.labkey.org/wiki/home/Documentation/page.view?name=labkeySql">
 55      * LabKey SQL Reference</a>.
 56      * @param config An object which contains the following configuration properties.
 57      * @param {String} config.schemaName name of the schema to query.
 58      * @param {String} config.sql The LabKey SQL to execute.
 59      * @param {String} [config.format] The desired export format. May be either 'excel' or 'tsv'. Defaults to 'excel'.
 60      * @param {String} [config.containerPath] The path to the container in which the schema and query are defined,
 61      *       if different than the current container. If not supplied, the current container's path will be used.
 62      * @param {String} [config.containerFilter] One of the values of {@link LABKEY.Query.containerFilter} that sets
 63      *       the scope of this query. Defaults to containerFilter.current, and is interpreted relative to
 64      *       config.containerPath.
 65      */
 66     impl.exportSql = function(config) {
 67 
 68         var url = LABKEY.ActionURL.buildURL("query", "exportSql", config.containerPath);
 69         var formData = {
 70             sql: config.sql,
 71             schemaName: config.schemaName,
 72             format: config.format,
 73             containerFilter: config.containerFilter
 74         };
 75 
 76         submitForm(url, formData);
 77     };
 78 
 79     /**
 80      * @private Not yet official API
 81      * Export a set of tables
 82      * @param config An object which contains the following:
 83      * @param {String} config.schemas An object with the following structure:
 84      * <pre>
 85      * {
 86      *    schemas: {
 87      *
 88      *      // export the named queries from schema "A" using the default view or the named view
 89      *      "A": [{
 90      *          queryName: "a"
 91      *          filters: [ LABKEY.Filters.create("Name", "bob", LABKEY.Filter.Types.NEQ) ],
 92      *          sort: "Name"
 93      *      },{
 94      *          queryName: "b",
 95      *          viewName: "b-view"
 96      *      }]
 97      *
 98      *    }
 99      * }
100      * </pre>
101      * @param {String} [config.headerType] Column header type
102      *
103      */
104     impl.exportTables = function (config) {
105 
106         var formData = {};
107 
108         if (config.headerType)
109             formData.headerType = config.headerType;
110 
111         // Create a copy of the schema config that we can mutate
112         var schemas = LABKEY.Utils.merge({}, config.schemas);
113         for (var schemaName in schemas)
114         {
115             if (!schemas.hasOwnProperty(schemaName))
116                 continue;
117 
118             var queryList = schemas[schemaName];
119             for (var i = 0; i < queryList.length; i++)
120             {
121                 var querySettings = queryList[i];
122                 var o = LABKEY.Utils.merge({}, querySettings);
123 
124                 delete o.filter;
125                 delete o.filterArray;
126                 delete o.sort;
127 
128                 // Turn the filters array into a filters map similar to QueryWebPart.js
129                 o.filters = LABKEY.Filter.appendFilterParams(null, querySettings.filters || querySettings.filterArray);
130 
131                 if (querySettings.sort)
132                     o.filters["query.sort"] = querySettings.sort;
133 
134                 queryList[i] = o;
135             }
136         }
137 
138         formData.schemas = JSON.stringify(schemas);
139 
140         var url = LABKEY.ActionURL.buildURL("query", "exportTables.view");
141         submitForm(url, formData);
142     };
143 
144     return impl;
145 
146 }(LABKEY.Query, jQuery);
147