synapse-react-client
Version:
[](https://travis-ci.com/Sage-Bionetworks/Synapse-React-Client) [](https://badge.fury.io/js/synaps
283 lines • 13.9 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.QUERY_FILTERS_COLLAPSED_CSS = exports.QUERY_FILTERS_EXPANDED_CSS = void 0;
var tslib_1 = require("tslib");
var React = (0, tslib_1.__importStar)(require("react"));
var utils_1 = require("../utils/");
var queryUtils_1 = require("../utils/functions/queryUtils");
var DeepLinkingUtils = (0, tslib_1.__importStar)(require("../utils/functions/deepLinkingUtils"));
var lodash_es_1 = require("lodash-es");
var SynapseConstants_1 = require("../utils/SynapseConstants");
exports.QUERY_FILTERS_EXPANDED_CSS = 'isShowingFacetFilters';
exports.QUERY_FILTERS_COLLAPSED_CSS = 'isHidingFacetFilters';
/**
* Class wraps around any Synapse views that are dependent on a query bundle
* Those classes then take in as props:
*
* @class QueryWrapper
* @extends {React.Component}
*/
var QueryWrapper = /** @class */ (function (_super) {
(0, tslib_1.__extends)(QueryWrapper, _super);
function QueryWrapper(props) {
var _a;
var _this = _super.call(this, props) || this;
_this.executeInitialQueryRequest = _this.executeInitialQueryRequest.bind(_this);
_this.executeQueryRequest = _this.executeQueryRequest.bind(_this);
_this.getLastQueryRequest = _this.getLastQueryRequest.bind(_this);
_this.getNextPageOfData = _this.getNextPageOfData.bind(_this);
_this.updateParentState = _this.updateParentState.bind(_this);
_this.getInitQueryRequest = _this.getInitQueryRequest.bind(_this);
var showFacetVisualization = (_a = props.defaultShowFacetVisualization) !== null && _a !== void 0 ? _a : true;
_this.state = {
data: undefined,
isLoading: true,
isLoadingNewData: true,
hasMoreData: true,
lastFacetSelection: {
columnName: '',
facetValue: '',
selector: '',
},
chartSelectionIndex: 0,
isAllFilterSelectedForFacet: {},
loadNowStarted: false,
lastQueryRequest: (0, lodash_es_1.cloneDeep)(_this.props.initQueryRequest),
topLevelControlsState: {
showColumnFilter: true,
showFacetFilter: true,
showFacetVisualization: showFacetVisualization,
showSearchBar: false,
showDownloadConfirmation: false,
showColumnSelectDropdown: false,
},
isColumnSelected: [],
selectedRowIndices: [],
error: undefined,
};
_this.componentIndex = props.componentIndex || 0;
return _this;
}
/**
* Compute default query request
*
* @memberof QueryWrapper
*/
QueryWrapper.prototype.componentDidMount = function () {
var _a = this.props.loadNow, loadNow = _a === void 0 ? true : _a;
var query = DeepLinkingUtils.getQueryRequestFromLink('QueryWrapper', this.componentIndex);
if (loadNow) {
this.executeInitialQueryRequest(query);
}
};
/**
* @memberof QueryWrapper
*/
QueryWrapper.prototype.componentDidUpdate = function (prevProps) {
/**
* If component updates and the token has changed (they signed in) then the data should be pulled in. Or if the
* sql query has changed of the component then perform an update.
*/
var _a = this.props.loadNow, loadNow = _a === void 0 ? true : _a;
if (loadNow && !this.state.loadNowStarted) {
this.executeInitialQueryRequest();
}
else if (loadNow && this.props.token !== prevProps.token) {
// if loadNow is true and they've logged in with a token that is not undefined, null, or an empty string when it was before
this.executeQueryRequest(this.getLastQueryRequest());
}
else if (prevProps.initQueryRequest.query.sql !==
this.props.initQueryRequest.query.sql) {
this.executeInitialQueryRequest();
}
};
/**
* Pass down a deep clone (so no side affects on the child's part) of the
* last query request made
*
* @returns
* @memberof QueryWrapper
*/
QueryWrapper.prototype.getLastQueryRequest = function () {
return (0, lodash_es_1.cloneDeep)(this.state.lastQueryRequest);
};
/**
* Pass down a deep clone (so no side affects on the child's part) of the
* first query request made
*
* @returns
* @memberof QueryWrapper
*/
QueryWrapper.prototype.getInitQueryRequest = function () {
return (0, lodash_es_1.cloneDeep)(this.props.initQueryRequest);
};
/**
* Execute the given query
*
* @param {*} queryRequest Query request as specified by
* https://rest-docs.synapse.org/rest/org/sagebionetworks/repo/model/table/Query.html
* @memberof QueryWrapper
*/
QueryWrapper.prototype.executeQueryRequest = function (queryRequest) {
var _this = this;
var clonedQueryRequest = (0, lodash_es_1.cloneDeep)(queryRequest);
this.setState({
isLoading: true,
lastQueryRequest: clonedQueryRequest,
selectedRowIndices: [], // reset selected row indices any time the query is re-run
});
if (clonedQueryRequest.query) {
var stringifiedQuery = encodeURIComponent(JSON.stringify(clonedQueryRequest.query));
if (this.props.shouldDeepLink) {
DeepLinkingUtils.updateUrlWithNewSearchParam('QueryWrapper', this.componentIndex, stringifiedQuery);
}
}
return utils_1.SynapseClient.getQueryTableResults(clonedQueryRequest, this.props.token, this.updateParentState)
.then(function (data) {
var hasMoreData = data.queryResult.queryResults.rows.length ===
clonedQueryRequest.query.limit;
var newState = {
hasMoreData: hasMoreData,
data: data,
asyncJobStatus: undefined,
};
_this.setState(newState);
})
.catch(function (error) {
console.error('Failed to get data ', error);
_this.setState(error);
})
.finally(function () {
_this.setState({ isLoading: false, isLoadingNewData: false });
});
};
/**
* Grab the next page of data, pulling in 25 more rows.
*
* @param {*} queryRequest Query request as specified by
* https://rest-docs.synapse.org/rest/org/sagebionetworks/repo/model/table/Query.html
* @memberof QueryWrapper
*/
QueryWrapper.prototype.getNextPageOfData = function (queryRequest) {
return (0, tslib_1.__awaiter)(this, void 0, void 0, function () {
var _this = this;
return (0, tslib_1.__generator)(this, function (_a) {
switch (_a.label) {
case 0:
this.setState({
isLoading: true,
});
return [4 /*yield*/, (0, queryUtils_1.getNextPageOfData)(queryRequest, this.state.data, this.props.token).then(function (newState) {
_this.setState((0, tslib_1.__assign)((0, tslib_1.__assign)({}, newState), { isLoading: false, lastQueryRequest: (0, lodash_es_1.cloneDeep)(queryRequest) }));
})];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
/**
* Execute the initial query passed into the component
*
* @param {*} queryRequest Query request as specified by
* https://rest-docs.synapse.org/rest/org/sagebionetworks/repo/model/table/Query.html
* @memberof QueryWrapper
*/
QueryWrapper.prototype.executeInitialQueryRequest = function (initQueryRequest) {
var _this = this;
if (initQueryRequest === void 0) { initQueryRequest = this.props.initQueryRequest; }
var lastQueryRequest = (0, lodash_es_1.cloneDeep)(initQueryRequest);
this.setState({
isLoading: true,
chartSelectionIndex: 0,
loadNowStarted: true,
lastQueryRequest: lastQueryRequest,
});
utils_1.SynapseClient.getQueryTableResults(initQueryRequest, this.props.token, this.updateParentState)
.then(function (data) {
var _a, _b, _c, _d;
var hasMoreData = (_a = data.queryResult.queryResults.rows.length ===
initQueryRequest.query.limit) !== null && _a !== void 0 ? _a : SynapseConstants_1.DEFAULT_PAGE_SIZE;
var isAllFilterSelectedForFacet = (0, lodash_es_1.cloneDeep)(_this.state.isAllFilterSelectedForFacet);
var chartSelectionIndex = _this.state.chartSelectionIndex;
if (_this.props.facet) {
if (!data.facets) {
throw Error('Error on query request, must include facets in partmask to show facets');
}
var enumFacets = data.facets.filter(function (el) { return el.facetType === 'enumeration'; });
enumFacets.forEach(function (el) {
// isAll is only true iff there are no facets selected or all elements are selected
var facetValues = el.facetValues;
var isAllFalse = facetValues.every(function (facet) { return !facet.isSelected; });
var isAllTrue = facetValues.every(function (facet) { return facet.isSelected; });
var isByDefaultSelected = isAllFalse || isAllTrue;
isAllFilterSelectedForFacet[el.columnName] = isByDefaultSelected;
if (el.columnName === _this.props.facet && !isAllFalse) {
// Note - this picks the first selected facet
chartSelectionIndex = facetValues
.sort(function (a, b) { return b.count - a.count; })
.findIndex(function (facet) { return facet.isSelected; });
}
});
}
var newState = {
isAllFilterSelectedForFacet: isAllFilterSelectedForFacet,
hasMoreData: hasMoreData,
data: data,
chartSelectionIndex: chartSelectionIndex,
asyncJobStatus: undefined,
isColumnSelected: (_d = (_b = data === null || data === void 0 ? void 0 : data.selectColumns) === null || _b === void 0 ? void 0 : _b.slice(0, (_c = _this.props.visibleColumnCount) !== null && _c !== void 0 ? _c : Infinity).map(function (el) { return el.name; })) !== null && _d !== void 0 ? _d : [],
};
_this.setState(newState);
})
.catch(function (error) {
console.error('Failed to get data ', error);
_this.setState({
error: error,
});
})
.finally(function () {
_this.setState({
isLoading: false,
isLoadingNewData: false,
});
});
};
QueryWrapper.prototype.updateParentState = function (update) {
this.setState(update);
};
/**
* remove a particular facet name (e.g. study) and its all possible values based on the parameter specified in the url
* this is to remove the facet from the charts, search and filter.
* @return data: QueryResultBundle
*/
QueryWrapper.prototype.removeLockedFacetData = function () {
var _a, _b;
var lockedFacet = (_a = this.props.lockedFacet) === null || _a === void 0 ? void 0 : _a.facet;
if (lockedFacet && this.state.data) {
// for details page, return data without the "locked" facet
var data = (0, lodash_es_1.cloneDeep)(this.state.data);
var facets = (_b = data.facets) === null || _b === void 0 ? void 0 : _b.filter(function (item) { return item.columnName.toLowerCase() !== lockedFacet.toLowerCase(); });
data.facets = facets;
return data;
}
else {
// for other pages, just return the data
return this.state.data;
}
};
/**
* Render the children without any formatting
*/
QueryWrapper.prototype.render = function () {
var isLoading = this.state.isLoading;
var _a = this.props, children = _a.children, rest = (0, tslib_1.__rest)(_a, ["children"]);
var queryWrapperChildProps = (0, tslib_1.__assign)({ isAllFilterSelectedForFacet: this.state.isAllFilterSelectedForFacet, data: this.removeLockedFacetData(), hasMoreData: this.state.hasMoreData, lastFacetSelection: this.state.lastFacetSelection, chartSelectionIndex: this.state.chartSelectionIndex, isLoading: this.state.isLoading, isLoadingNewData: this.state.isLoadingNewData, asyncJobStatus: this.state.asyncJobStatus, topLevelControlsState: this.state.topLevelControlsState, isColumnSelected: this.state.isColumnSelected, selectedRowIndices: this.state.selectedRowIndices, error: this.state.error, executeInitialQueryRequest: this.executeInitialQueryRequest, executeQueryRequest: this.executeQueryRequest, getLastQueryRequest: this.getLastQueryRequest, getNextPageOfData: this.getNextPageOfData, updateParentState: this.updateParentState, getInitQueryRequest: this.getInitQueryRequest }, rest);
var loadingCusrorClass = isLoading ? 'SRC-logo-cursor' : '';
return (React.createElement("div", { className: "SRC-wrapper " + loadingCusrorClass }, children && children(queryWrapperChildProps)));
};
return QueryWrapper;
}(React.Component));
exports.default = QueryWrapper;
//# sourceMappingURL=QueryWrapper.js.map