/* * License information at https://github.com/Caltech-IPAC/firefly/blob/master/License.txt */ /** * @author Trey Roby * Date: 3/5/12 */ import {get, set, pickBy, cloneDeep, has, isUndefined} from 'lodash'; import {ServerParams} from '../data/ServerParams.js'; import {doJsonRequest, DEF_BASE_URL} from '../core/JsonUtils.js'; import {getBgEmail} from '../core/background/BackgroundUtil.js'; import {encodeUrl, download, getModuleName} from '../util/WebUtil.js'; import Enum from 'enum'; import {getTblById, getResultSetID, getResultSetRequest} from '../tables/TableUtil.js'; import {MAX_ROW, DataTagMeta, getTblId, setResultSetID, setResultSetRequest, setSelectInfo} from '../tables/TableRequestUtil.js'; import {SelectInfo} from '../tables/SelectInfo.js'; import {getBackgroundJobs} from '../core/background/BackgroundUtil.js'; export const DownloadProgress= new Enum(['STARTING', 'WORKING', 'DONE', 'UNKNOWN', 'FAIL']); export const ScriptAttributes= new Enum(['URLsOnly', 'Unzip', 'Ditto', 'Curl', 'Wget', 'RemoveZip']); const DOWNLOAD_REQUEST = 'downloadRequest'; const SELECTION_INFO = 'selectionInfo'; //TODO: convert FileStatus /** * tableRequest will be sent to the server as a json string. * @param {TableRequest} tableRequest is a table request params object * @param {number} [hlRowIdx] set the highlightedRow. default to startIdx. * @returns {Promise.<TableModel>} * @public * @func doFetchTable * @memberof firefly.util.table */ export function fetchTable(tableRequest, hlRowIdx) { const def = { startIdx: 0, pageSize : MAX_ROW }; tableRequest = setupNewRequest(tableRequest, def); const params = { [ServerParams.REQUEST]: JSON.stringify(tableRequest), }; return doJsonRequest(ServerParams.TABLE_SEARCH, params) .then( (tableModel) => { const startIdx = get(tableModel, 'request.startIdx', 0); if (startIdx > 0) { // shift data arrays indices to match partial fetch tableModel.tableData.data = tableModel.tableData.data.reduce( (nAry, v, idx) => { nAry[idx+startIdx] = v; return nAry; }, []); } if (tableModel.selectInfo) { // convert selectInfo to JS object const selectInfo = SelectInfo.parse(tableModel.selectInfo); tableModel.selectInfo = selectInfo.data; } if (!isUndefined(hlRowIdx)) { tableModel.highlightedRow = hlRowIdx; } else if (!has(tableModel, 'highlightedRow')) { tableModel.highlightedRow = startIdx; } return tableModel; }); } /** * a utility function used to query data from the given tableRequest without altering the table. * @param {TableRequest} tableRequest is a table request params object * @param {TableRequest} queryRequest filters, sortInfo, and inclCols are used on the tableRequest to return the results * @returns {Promise.<number>} */ export function queryTable(tableRequest, {filters, sortInfo, inclCols}) { const params = Object.assign(pickBy({filters, sortInfo, inclCols}), {[ServerParams.REQUEST]: JSON.stringify(tableRequest)}); return doJsonRequest(ServerParams.QUERY_TABLE, params) .then( (index) => { return index; }); } /** * returns the table data for the given parameters * @param {Object} p parameters object * @param {string[]} p.columnNames an array of column names * @param {TableRequest} p.request location of the file on the server * @param {string} p.selectedRows a comma-separated string of indices of the rows to get the data from * @return {Promise<TableModel>} */ export function selectedValues({columnNames, request, selectedRows}) { columnNames = Array.isArray(columnNames) ? columnNames.join() : String(columnNames); selectedRows = Array.isArray(selectedRows) ? selectedRows.join() : String(selectedRows); return doJsonRequest(ServerParams.SELECTED_VALUES, {columnNames, request: JSON.stringify(request), selectedRows}) .then((tableModel) => { return tableModel; }); } /** * * @param {DownloadRequest} dlRequest * @param {Object} searchRequest * @param {string} selectionInfo */ export function packageRequest(dlRequest, searchRequest, selectionInfo) { if (!selectionInfo) { const {totalRow} = getTblById(searchRequest.tbl_id) || {}; if (totalRow) { selectionInfo = SelectInfo.newInstance({selectAll: true, rowCount: totalRow}).toString(); } } if (!dlRequest.Email && getBgEmail()) { dlRequest.Email = getBgEmail(); } // insert DataTag if not present if (!get(searchRequest, DataTagMeta)) { set(searchRequest, DataTagMeta, `${getModuleName()}-${ServerParams.PACKAGE_REQUEST}`); } const params = { [DOWNLOAD_REQUEST]: JSON.stringify(dlRequest), [ServerParams.REQUEST]: JSON.stringify(searchRequest), [SELECTION_INFO]: selectionInfo }; return doJsonRequest(ServerParams.PACKAGE_REQUEST, params); } /** * * @param {ServerRequest} request * @return {Promise} */ export function getJsonData(request) { const paramList = []; paramList.push({name:ServerParams.REQUEST, value: request.toString()}); return doJsonRequest(ServerParams.JSON_DATA, paramList ).then((data) => {return data; }); } /** * * @param {ServerRequest} request * @param {ServerRequest} clientRequest * @param {number} waitMillis * @return {Promise} */ export function submitBackgroundSearch(request, clientRequest, waitMillis) { if (getBgEmail()) { request = set(request, ['META_INFO', ServerParams.EMAIL], getBgEmail()); } // insert DataTag if not present if (!get(request, DataTagMeta)) { set(request, DataTagMeta, `${getModuleName()}-${request.id}`); } const params = { [ServerParams.REQUEST]: JSON.stringify(request), [ServerParams.WAIT_MILS]: String(waitMillis) }; clientRequest && (params[ServerParams.CLIENT_REQUEST] = JSON.stringify(clientRequest)); return doJsonRequest(ServerParams.SUB_BACKGROUND_SEARCH, params); } /** * add this job to the background * @param {string} bgStatus background id * @return {Promise} */ export function addBgJob(bgStatus) { const params = {bgStatus: JSON.stringify(bgStatus)}; return doJsonRequest(ServerParams.ADD_JOB, params).then( () => true); } /** * * @param {string} id background id * @return {Promise} */ export function removeBgJob(id) { const params = {[ServerParams.ID]: id}; return doJsonRequest(ServerParams.REMOVE_JOB, params).then( () => true); } /** * * @param {string} id background id * @return {Promise} */ export function cancel(id) { const paramList = []; paramList.push({name: ServerParams.ID, value: id}); return doJsonRequest(ServerParams.CANCEL, paramList ).then( () => true); } /** * * @param {string} fileKey * @return {Promise} */ export function getDownloadProgress(fileKey) { const paramList = []; paramList.push({name: ServerParams.FILE, value: fileKey}); return doJsonRequest(ServerParams.DOWNLOAD_PROGRESS, paramList ).then((data) => {return DownloadProgress.get(data); }); } /** * @param {string} email * @return {Promise} */ export function setEmail(email) { const idList= Object.keys(getBackgroundJobs() || {}); const paramList= idList.map( (id) => { return {name:ServerParams.ID, value: id}; } ); if(paramList.length > 0) { paramList.push({name:ServerParams.EMAIL, value:email}); return doJsonRequest(ServerParams.SET_EMAIL, paramList ).then( () => true); } } /** * * @param {array|string} ids one id or an array of ids * @param {JobAttributes} attribute job attribute * @return {Promise} */ export function setAttribute(ids, attribute) { const idList= Array.isArray(ids) ? ids : [ids]; const paramList= idList.map( (id) => { return {name:ServerParams.ID, value: id}; } ); paramList.push({name:ServerParams.ATTRIBUTE, value:attribute.toString()}); return doJsonRequest(ServerParams.SET_ATTR, paramList ).then( () => true); } /** * resend email notification to all successfully completed background jobs. * @param {string} email * @return {Promise} */ export function resendEmail(email) { return doJsonRequest(ServerParams.RESEND_EMAIL, {[ServerParams.EMAIL]: email} ).then( () => true); } /** * * @param {string} id * @param {number} idx * @return {Promise} */ export function clearPushEntry(id, idx ) { const paramList = []; paramList.push({name: ServerParams.ID, value: id}); paramList.push({name: ServerParams.IDX, value: `${idx}`}); return doJsonRequest(ServerParams.CLEAR_PUSH_ENTRY, paramList ).then( () => true); } /** * * @param {string} channel * @param {string} desc * @param {string} data * @return {Promise} */ export function reportUserAction(channel, desc, data) { const paramList = []; paramList.push({name: ServerParams.CHANNEL_ID, value: channel}); paramList.push({name: ServerParams.DATA, value: data}); paramList.push({name: ServerParams.DESC, value: desc}); return doJsonRequest(ServerParams.REPORT_USER_ACTION, paramList ).then( () => true); } /** * * @param id * @param fname * @param dataSource * @param {array} attributes and array of ScriptAttributes * @return {Promise} */ export function createDownloadScript(id, fname, dataSource, attributes) { const attrAry= Array.isArray(attributes) ? attributes : [attributes]; const paramList= attrAry.map( (v='') => ({name:ServerParams.ATTRIBUTE, value: v.toString()}) ); paramList.push({name: ServerParams.ID, value: id}); paramList.push({name: ServerParams.FILE, value: fname}); paramList.push({name: ServerParams.SOURCE, value: dataSource}); return doJsonRequest(ServerParams.CREATE_DOWNLOAD_SCRIPT, paramList); } /** * Download the download script to the user's computer. * @param {Object} p * @param {string} p.packageID * @param {string} p.type * @param {string} p.fname * @param {string} p.dataSource */ export function getDownloadScript({packageID, type, fname, dataSource}) { const url = encodeUrl(DEF_BASE_URL, {packageID, type, fname, dataSource}); if (url) download(url); } /** * This function add some important meta info needed by the server to process this request. * These meta are system-only info and should not need to be known outside of this app. * @param {TableRequest} tableRequest * @param {object} defaults */ function setupNewRequest(tableRequest, defaults) { const newRequest = Object.assign(defaults, cloneDeep(tableRequest)); const tableModel = getTblById(getTblId(newRequest)); if (tableModel) { // pass along its resultSetID const resultSetID = getResultSetID(tableModel.tbl_id); resultSetID && setResultSetID(newRequest, resultSetID); // pass along its resultSetRequest const resultSetRequest = getResultSetRequest(tableModel.tbl_id); resultSetRequest && setResultSetRequest(newRequest, resultSetRequest); // pass along selectInfo tableModel.selectInfo && setSelectInfo(newRequest, tableModel.selectInfo); } return newRequest; }