UNPKG

ucsc-xena-client

Version:

UCSC Xena Client. Functional genomics visualizations.

1,187 lines (1,002 loc) 36.7 kB
'use strict'; var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _link = require('react-toolbox/lib/link'); var _link2 = _interopRequireDefault(_link); var _checkbox = require('react-toolbox/lib/checkbox'); var _button = require('react-toolbox/lib/button'); var _dialog = require('react-toolbox/lib/dialog'); var _dialog2 = _interopRequireDefault(_dialog); var _reactCssThemr = require('react-css-themr'); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } require('./base'); var React = require('react'); var _require = require('./underscore_ext'), uniq = _require.uniq, flatten = _require.flatten, sortBy = _require.sortBy, groupBy = _require.groupBy, map = _require.map, flatmap = _require.flatmap, partitionN = _require.partitionN, mapObject = _require.mapObject, pluck = _require.pluck, concat = _require.concat, where = _require.where, contains = _require.contains, get = _require.get, updateIn = _require.updateIn, range = _require.range, Let = _require.Let, zip = _require.zip, identity = _require.identity, getIn = _require.getIn, sum = _require.sum, keys = _require.keys, values = _require.values, mmap = _require.mmap; var _require2 = require('./rx'), from = _require2.Observable.from, animationFrame = _require2.Scheduler.animationFrame; var _require3 = require('./xenaQuery'), parseDsID = _require3.parseDsID; var styles = require('./Datapages.module.css'); var nav = require('./nav'); var showdown = require('showdown'); var _require4 = require('./dom_helper'), stripHTML = _require4.stripHTML; var treehouseImg = require('../images/Treehouse.jpg'); var _require5 = require('./react-utils'), rxEvents = _require5.rxEvents; var _require6 = require('./defaultServers'), localHub = _require6.servers.localHub, serverNames = _require6.serverNames; var _require7 = require('./util'), encodeObject = _require7.encodeObject, urlParams = _require7.urlParams; var appTheme = require('./appTheme'); var _require8 = require('./hubParams'), getHubParams = _require8.getHubParams; var getHubName = function getHubName(host) { return get(serverNames, host, host); }; var pluralize = function pluralize(str, count) { return count === 1 ? '1 ' + str : count + ' ' + str + 's'; }; // Get params from the anchor href. With RT Link, the anchor is parentElement. var paramFromHref = function paramFromHref(ev) { return mapObject(urlParams(ev.target.parentElement.href), function (a) { return a[0]; }); }; // // event handler for navigating within datapages. Prevents page load, and // sets url params. // function navHandler(ev) { ev.preventDefault(); this.props.callback(['navigate', 'datapages', paramFromHref(ev, this.props.state)]); } var getUserServers = function getUserServers(servers) { return keys(servers).filter(function (k) { return servers[k].user; }); }; // // Data hubs sidebar // var hubLink = function hubLink(host, onClick, hubParams) { return React.createElement(_link2.default, { className: styles.link, href: '?' + encodeObject(_extends({ host: host }, hubParams)), label: getHubName(host), onClick: onClick }); }; var DataHubs = function (_React$Component) { _inherits(DataHubs, _React$Component); function DataHubs() { var _ref; var _temp, _this, _ret; _classCallCheck(this, DataHubs); for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = DataHubs.__proto__ || Object.getPrototypeOf(DataHubs)).call.apply(_ref, [this].concat(args))), _this), _this.onHub = function (ev) { navHandler.call(_this, ev); }, _this.onSelect = function (isOn, ev) { var checked = ev.target.checked, host = ev.target.getAttribute('data-host'); _this.props.callback([checked ? 'enable-host' : 'disable-host', host, 'user']); }, _temp), _possibleConstructorReturn(_this, _ret); } _createClass(DataHubs, [{ key: 'render', value: function render() { var _this2 = this; var _props = this.props, hubParams = _props.hubParams, servers = _props.state.spreadsheet.servers; return React.createElement( 'div', { className: styles.dataHubs }, React.createElement( 'h2', null, 'Active Data Hubs' ), React.createElement( 'ul', null, map(servers, function (_ref2, host) { var user = _ref2.user; return React.createElement( 'li', { key: host }, React.createElement(_checkbox.Checkbox, { label: hubLink(host, _this2.onHub, hubParams), onChange: _this2.onSelect, checked: user, 'data-host': host }) ); }) ) ); } }]); return DataHubs; }(React.Component); // // Cohort Summary Page // var treehouse = function treehouse(cohort) { return cohort.search(/^Treehouse/gi) === -1 ? null : React.createElement('img', { src: treehouseImg, height: '40px' }); }; var cohortLink = function cohortLink(cohort, onClick, hubParams) { return React.createElement(_link2.default, { className: styles.link, href: '?' + encodeObject(_extends({ cohort: cohort }, hubParams)), label: cohort, onClick: onClick }); }; var collateCohorts = function collateCohorts(hubCohorts) { return concat.apply(undefined, _toConsumableArray(pluck(hubCohorts, 'cohorts'))).reduce(function (acc, cohort) { return updateIn(acc, [cohort.cohort], function () { var v = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; return cohort.count + v; }); }, {}); }; var CohortSummary = function CohortSummary(_ref3) { var cohorts = _ref3.cohorts, onCohort = _ref3.onCohort, hubParams = _ref3.hubParams; var names = sortBy(keys(cohorts), function (c) { return c.toLowerCase(); }), nCohorts = names.length, nDatasets = sum(values(cohorts)); return React.createElement( 'div', null, React.createElement( 'h2', null, pluralize('Cohort', nCohorts), ', ', pluralize('Dataset', nDatasets) ), React.createElement( 'ul', { className: styles.list }, map(names, function (name) { return React.createElement( 'li', { key: name }, treehouse(name), cohortLink(name, onCohort, hubParams), ' (' + pluralize('dataset', cohorts[name]) + ')' ); }) ) ); }; var CohortSummaryPage = function (_React$Component2) { _inherits(CohortSummaryPage, _React$Component2); function CohortSummaryPage() { var _ref4; var _temp2, _this3, _ret2; _classCallCheck(this, CohortSummaryPage); for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { args[_key2] = arguments[_key2]; } return _ret2 = (_temp2 = (_this3 = _possibleConstructorReturn(this, (_ref4 = CohortSummaryPage.__proto__ || Object.getPrototypeOf(CohortSummaryPage)).call.apply(_ref4, [this].concat(args))), _this3), _this3.onCohort = function (ev) { navHandler.call(_this3, ev); }, _temp2), _possibleConstructorReturn(_this3, _ret2); } _createClass(CohortSummaryPage, [{ key: 'render', value: function render() { var _props2 = this.props, hubParams = _props2.hubParams, state = _props2.state, servers = state.spreadsheet.servers, userServers = getUserServers(servers), cohorts = getIn(this.props.state, ['datapages', 'cohorts'], []), activeCohorts = cohorts.filter(function (c) { return contains(userServers, c.server); }), combined = collateCohorts(activeCohorts); return React.createElement( 'div', { className: styles.datapages }, React.createElement(DataHubs, this.props), React.createElement(CohortSummary, { hubParams: hubParams, cohorts: combined, onCohort: this.onCohort }) ); } }]); return CohortSummaryPage; }(React.Component); // // Dataset delete button // var DeleteButton = function (_React$Component3) { _inherits(DeleteButton, _React$Component3); function DeleteButton() { var _ref5; var _temp3, _this4, _ret3; _classCallCheck(this, DeleteButton); for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { args[_key3] = arguments[_key3]; } return _ret3 = (_temp3 = (_this4 = _possibleConstructorReturn(this, (_ref5 = DeleteButton.__proto__ || Object.getPrototypeOf(DeleteButton)).call.apply(_ref5, [this].concat(args))), _this4), _this4.state = { active: false }, _this4.onDelete = function () { _this4.setState({ active: !_this4.state.active }); }, _this4.onReally = function () { var name = _this4.props.name; _this4.props.callback(['navigate', 'datapages', { host: localHub }]); _this4.props.callback(['delete-dataset', localHub, name]); }, _this4.actions = function () { return [{ label: 'Cancel', onClick: _this4.onDelete }, { label: 'Really Delete', onClick: _this4.onReally }]; }, _temp3), _possibleConstructorReturn(_this4, _ret3); } _createClass(DeleteButton, [{ key: 'render', value: function render() { var active = this.state.active, label = this.props.label; return React.createElement( 'div', { className: styles.deleteButton }, React.createElement( _dialog2.default, { actions: this.actions(), active: active, onEscKeyDown: this.onDelete, onOverlayClick: this.onDelete, title: 'Delete dataset' }, label ), React.createElement( _button.Button, { onClick: this.onDelete, accent: true }, 'Delete' ) ); } }]); return DeleteButton; }(React.Component); var canDelete = function canDelete(_ref6, host) { var status = _ref6.status; return host === localHub && contains(['loaded', 'error'], status); }; var markdownValue = function markdownValue(value) { if (value) { var converter = new showdown.Converter(); return React.createElement('div', { className: styles.header, dangerouslySetInnerHTML: { __html: converter.makeHtml(value) } }); } }; // // Cohort Datasets Page // var datasetLink = function datasetLink(callback, preferred, onClick, hubParams) { return function (ds) { var _parseDsID = parseDsID(ds.dsID), _parseDsID2 = _slicedToArray(_parseDsID, 1), host = _parseDsID2[0]; return React.createElement( 'li', { key: ds.name }, React.createElement(_link2.default, { className: styles.link, href: '?' + encodeObject(_extends({ dataset: ds.name, host: host }, hubParams)), label: ds.label, onClick: onClick }), preferred.has(ds.dsID) ? React.createElement( 'span', { className: styles.star }, '*' ) : null, ds.status !== 'loaded' ? React.createElement( 'span', { className: styles.count }, ' [', ds.status, ']' ) : null, ds.status === 'loaded' ? React.createElement( 'span', { className: styles.count }, ' (n=', (ds.count || 0).toLocaleString(), ')' ) : null, React.createElement( 'span', null, ' ', getHubName(host) ), canDelete(ds, host) ? React.createElement(DeleteButton, { callback: callback, name: ds.name, label: ds.label || ds.name }) : null, React.createElement( 'div', { className: styles.lineClamp }, React.createElement( 'span', { className: styles.description }, stripHTML(ds.description) ) ) ); }; }; var drawGroup = function drawGroup(callback, groups, preferred, onClick, hubParams) { return function (dataSubType) { var list = sortBy(groups[dataSubType], function (g) { return g.label.toLowerCase(); }); return React.createElement( 'div', { key: dataSubType }, React.createElement( 'h3', null, dataSubType ), React.createElement( 'ul', { className: styles.groupList }, map(list, datasetLink(callback, preferred, onClick, hubParams)) ) ); }; }; var COHORT_NULL = '(unassigned)'; var getPreferred = function getPreferred(wizard, cohort) { return new Set(values(getIn(wizard, ['cohortPreferred', cohort], {}))); }; var CohortPage = function (_React$Component4) { _inherits(CohortPage, _React$Component4); function CohortPage() { var _ref7; var _temp4, _this5, _ret4; _classCallCheck(this, CohortPage); for (var _len4 = arguments.length, args = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) { args[_key4] = arguments[_key4]; } return _ret4 = (_temp4 = (_this5 = _possibleConstructorReturn(this, (_ref7 = CohortPage.__proto__ || Object.getPrototypeOf(CohortPage)).call.apply(_ref7, [this].concat(args))), _this5), _this5.onViz = function () { var _this5$props$state = _this5.props.state, datapages = _this5$props$state.datapages, currentCohort = _this5$props$state.spreadsheet.cohort, cohort = getIn(datapages, ['cohort', 'cohort'], COHORT_NULL); if (cohort !== get(currentCohort, 'name')) { _this5.props.callback(['cohort', cohort]); } _this5.props.callback(['navigate', 'heatmap']); }, _this5.onDataset = function (ev) { navHandler.call(_this5, ev); }, _temp4), _possibleConstructorReturn(_this5, _ret4); } _createClass(CohortPage, [{ key: 'render', value: function render() { var _props3 = this.props, hubParams = _props3.hubParams, _props3$state = _props3.state, datapages = _props3$state.datapages, params = _props3$state.params, wizard = _props3$state.wizard, cohort = getIn(datapages, ['cohort', 'cohort']) === params.cohort ? datapages.cohort : { cohort: '...', datasets: [] }, callback = this.props.callback, dsGroups = groupBy(values(cohort.datasets), 'dataSubType'), dataSubTypes = sortBy(keys(dsGroups), function (g) { return g.toLowerCase(); }), preferred = getPreferred(wizard, params.cohort); return React.createElement( 'div', { className: styles.datapages }, markdownValue(cohort.meta), React.createElement( 'div', { className: styles.sidebar }, React.createElement( _button.Button, { onClick: this.onViz, accent: true }, 'Visualize' ) ), React.createElement( 'h2', null, 'cohort: ', treehouse(cohort.cohort), cohort.cohort ), dataSubTypes.map(drawGroup(callback, dsGroups, preferred, this.onDataset, hubParams)), preferred.size === 0 ? null : React.createElement( 'span', null, React.createElement( 'span', { className: styles.star }, '*' ), React.createElement( 'span', null, 'default dataset in visualization' ) ) ); } }]); return CohortPage; }(React.Component); // // Dataset Page // var TYPE_NULL = 'genomicMatrix', FORMAT_MAPPING = { 'clinicalMatrix': "ROWs (samples) x COLUMNs (identifiers) (i.e. clinicalMatrix)", 'genomicMatrix': "ROWs (identifiers) x COLUMNs (samples) (i.e. genomicMatrix)", 'mutationVector': "Variant by Position (i.e. mutationVector)", 'genomicSegment': 'Genomic Segment (i.e. genomicSegment)', 'unknown': "unknown" }; var dataPair = function dataPair(key, value) { var method = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : identity; return value == null ? [] : [React.createElement( 'span', { className: styles.key }, key ), React.createElement( 'span', { className: styles.value }, method(value) ), React.createElement('br', null)]; }; var toLink = function toLink(value) { return React.createElement( 'a', { href: value }, value ); }; var toCohortLink = function toCohortLink(onClick, hubParams) { return function (cohort) { return React.createElement(_link2.default, { href: '?' + encodeObject(_extends({ cohort: cohort }, hubParams)), onClick: onClick, label: cohort }); }; }; var toPMIDLink = function toPMIDLink(value) { return React.createElement( 'a', { href: 'http://www.ncbi.nlm.nih.gov/pubmed/?term=' + value.toString() }, value ); }; var jsonLink = function jsonLink(link) { return link.replace(/(.gz)?$/, '.json'); }; var toDownloadLink = function toDownloadLink(value) { return React.createElement( 'span', null, React.createElement( 'a', { href: value }, value ), '; ', React.createElement( 'a', { href: jsonLink(value) }, 'Full metadata' ) ); }; var toHTML = function toHTML(value) { return React.createElement('span', { dangerouslySetInnerHTML: { __html: value } }); }; var headerValue = function headerValue(value) { return value && React.createElement( 'p', { className: styles.header }, value ); }; var htmlValue = function htmlValue(value) { return value && React.createElement('p', { className: styles.header, dangerouslySetInnerHTML: { __html: value } }); }; // XXX Does not display load warning in pop-up // XXX Does not use red/blue coloring for error vs. other load status (e.g. 'loading') var getStatus = function getStatus(status, loaderWarning) { return status === 'loaded' && !loaderWarning ? [] : status === 'loaded' ? dataPair('status', 'loaded with warning') : dataPair('status', status); }; // split, handling falsey values var split = function split(str, pat) { return str ? str.split(pat) : []; }; var resolveCodes = function resolveCodes(probes, codes, data) { return mmap(probes, data, function (probe, row) { return codes[probe] ? map(row, function (v) { return isNaN(v) ? v : codes[probe][v]; }) : row; }); }; // not the most efficient algorithm :-/ var addHeaders = function addHeaders(fields, samples, data) { return mmap([''].concat(_toConsumableArray(fields)), [samples].concat(_toConsumableArray(data)), function (header, row) { return [header].concat(_toConsumableArray(row)); }); }; var transpose = function transpose(data) { return zip.apply(null, data); }; // Transpose matrix if it's clinical var transposeClinical = function transposeClinical(meta, data) { return get(meta, 'type') === 'clinicalMatrix' ? transpose(data) : data; }; var table = function table(data) { return React.createElement( 'table', { className: styles.dataSnippetTable }, React.createElement( 'tbody', null, map(data, function (row, i) { return React.createElement( 'tr', { key: i }, map(row, function (c, j) { return React.createElement( 'td', { key: j }, c ); }) ); }) ) ); }; var matrixTable = function matrixTable(meta, _ref8) { var fields = _ref8.fields, samples = _ref8.samples, codes = _ref8.codes, data = _ref8.data; return table(transposeClinical(meta, addHeaders(fields, samples, resolveCodes(fields, codes, data)))); }; // swap chromend & chromstart when sorting fields var cmpSparseFields = function cmpSparseFields(a, b) { return a === 'chromend' && b === 'chromstart' ? 1 : a === 'chromstart' && b === 'chromend' ? -1 : a.localeCompare(b); }; var sparseTable = function sparseTable(meta, data) { var fields = keys(data).sort(cmpSparseFields), rows = fields.map(function (field) { return data[field]; }), samples = data.sampleID; return table(transpose(addHeaders(fields, samples, rows))); }; var noTable = function noTable() { return null; }; var dataMethod = function dataMethod() { var _ref9 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, _ref9$type = _ref9.type, type = _ref9$type === undefined ? 'genomicMatrix' : _ref9$type, status = _ref9.status; return status !== 'loaded' ? noTable : type === 'genomicMatrix' ? matrixTable : type === 'clinicalMatrix' ? matrixTable : type === 'mutationVector' ? sparseTable : type === 'genomicSegment' ? sparseTable : noTable; }; var setKey = function setKey(arr) { return arr.map(function (el, i) { return React.cloneElement(el, { key: i }); }); }; var DatasetPage = function (_React$Component5) { _inherits(DatasetPage, _React$Component5); function DatasetPage() { var _ref10; var _temp5, _this6, _ret5; _classCallCheck(this, DatasetPage); for (var _len5 = arguments.length, args = Array(_len5), _key5 = 0; _key5 < _len5; _key5++) { args[_key5] = arguments[_key5]; } return _ret5 = (_temp5 = (_this6 = _possibleConstructorReturn(this, (_ref10 = DatasetPage.__proto__ || Object.getPrototypeOf(DatasetPage)).call.apply(_ref10, [this].concat(args))), _this6), _this6.onCohort = function (ev) { navHandler.call(_this6, ev); }, _this6.onViz = function () { var _this6$props$state = _this6.props.state, datapages = _this6$props$state.datapages, currentCohort = _this6$props$state.spreadsheet.cohort, cohort = getIn(datapages, ['dataset', 'meta', 'cohort'], COHORT_NULL); if (cohort !== get(currentCohort, 'name')) { _this6.props.callback(['cohort', cohort]); } _this6.props.callback(['navigate', 'heatmap']); }, _this6.onIdentifiers = function (ev) { navHandler.call(_this6, ev); }, _this6.onSamples = function (ev) { navHandler.call(_this6, ev); }, _temp5), _possibleConstructorReturn(_this6, _ret5); } _createClass(DatasetPage, [{ key: 'render', value: function render() { var _props4 = this.props, callback = _props4.callback, state = _props4.state, hubParams = _props4.hubParams, _state$params = state.params, host = _state$params.host, dataset = _state$params.dataset, datapages = state.datapages, _get = get(datapages, 'dataset', {}), meta = _get.meta, _get$probeCount = _get.probeCount, probeCount = _get$probeCount === undefined ? 0 : _get$probeCount, data = _get.data, downloadLink = _get.downloadLink, probemapLink = _get.probemapLink, currentDataset = _get.dataset, currentHost = _get.host; if (!meta || currentHost !== host || currentDataset !== dataset) { return React.createElement( 'div', { className: styles.datapages }, React.createElement( 'h2', null, 'dataset: ...' ) ); } var name = meta.name, _meta$label = meta.label, label = _meta$label === undefined ? name : _meta$label, description = meta.description, longTitle = meta.longTitle, _meta$cohort = meta.cohort, cohort = _meta$cohort === undefined ? COHORT_NULL : _meta$cohort, dataSubType = meta.dataSubType, platform = meta.platform, unit = meta.unit, assembly = meta.assembly, version = meta.version, url = meta.url, articletitle = meta.articletitle, citation = meta.citation, pmid = meta.pmid, dataproducer = meta.dataproducer, _meta$author = meta.author, author = _meta$author === undefined ? dataproducer : _meta$author, wranglingProcedure = meta['wrangling_procedure'], _meta$type = meta.type, type = _meta$type === undefined ? TYPE_NULL : _meta$type, status = meta.status, loader = meta.loader, count = meta.count; return React.createElement( 'div', { className: styles.datapages }, React.createElement( 'div', { className: styles.sidebar }, React.createElement( _button.Button, { onClick: this.onViz, accent: true }, 'Visualize' ), canDelete(meta, host) ? React.createElement(DeleteButton, { callback: callback, name: name, label: label }) : null ), React.createElement( 'h2', null, 'dataset: ', (dataSubType ? dataSubType + ' - ' : '') + label ), headerValue(longTitle), htmlValue(description), setKey(flatten([dataPair('cohort', cohort, toCohortLink(this.onCohort, hubParams)), dataPair('dataset ID', name), getStatus(status, loader), dataPair('download', downloadLink, toDownloadLink), dataPair('samples', count), dataPair('version', version), dataPair('hub', host), dataPair('type of data', dataSubType), dataPair('assembly', assembly), dataPair('unit', unit), dataPair('platform', platform), dataPair('ID/Gene Mapping', probemapLink, toDownloadLink), dataPair('publication', articletitle), dataPair('citation', citation), dataPair('author', author), dataPair('PMID', pmid, toPMIDLink), flatmap(uniq(split(url, /,/)), function (url) { return dataPair('raw data', url, toLink); }), dataPair('wrangling', wranglingProcedure, toHTML), dataPair('input data format', FORMAT_MAPPING[type])])), status === 'loaded' ? React.createElement( 'span', { className: styles.tableControls }, type === 'genomicMatrix' ? probeCount.toLocaleString() + ' identifiers X ' + count + ' samples' : null, type === 'clinicalMatrix' ? count + ' samples X ' + probeCount.toLocaleString() + ' identifiers' : null, React.createElement(_link2.default, { href: '?' + encodeObject(_extends({ host: host, dataset: dataset, allIdentifiers: true }, hubParams)), onClick: this.onIdentifiers, label: 'All Identifiers' }), React.createElement(_link2.default, { href: '?' + encodeObject(_extends({ host: host, dataset: dataset, allSamples: true }, hubParams)), onClick: this.onSamples, label: 'All Samples' }) ) : null, dataMethod(meta)(meta, data) ); } }]); return DatasetPage; }(React.Component); // Our handling of parameters 'hub' and 'host', is somewhat confusing. 'host' // means "show the hub page for this url". 'hub' means "add this url to the // active hub list, and, if in /datapages/ show the hub page for this url". // The 'hub' parameter can be repeated, which adds each hub to the active hub // list. Only the first one will be displayed when linking to /datapages/. // Needs refactor. var defaultHost = function defaultHost(params) { return Let(function () { var _ref11 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : params, host = _ref11.host, hubs = _ref11.hubs; return !host && hubs ? _extends({}, params, { host: hubs[0] }) : params; }); }; // // Hub page // var HubPage = function (_React$Component6) { _inherits(HubPage, _React$Component6); function HubPage() { var _ref12; var _temp6, _this7, _ret6; _classCallCheck(this, HubPage); for (var _len6 = arguments.length, args = Array(_len6), _key6 = 0; _key6 < _len6; _key6++) { args[_key6] = arguments[_key6]; } return _ret6 = (_temp6 = (_this7 = _possibleConstructorReturn(this, (_ref12 = HubPage.__proto__ || Object.getPrototypeOf(HubPage)).call.apply(_ref12, [this].concat(args))), _this7), _this7.onCohort = function (ev) { navHandler.call(_this7, ev); }, _temp6), _possibleConstructorReturn(_this7, _ret6); } _createClass(HubPage, [{ key: 'render', value: function render() { var _props5 = this.props, state = _props5.state, hubParams = _props5.hubParams, servers = state.spreadsheet.servers, userServers = getUserServers(servers), _defaultHost = defaultHost(state.params), host = _defaultHost.host, cohorts = getIn(state, ['datapages', 'cohorts'], []), hubCohorts = where(cohorts, { server: host }), coll = collateCohorts(hubCohorts), inHubs = contains(userServers, host) ? '' : ' (not in my data hubs)'; return React.createElement( 'div', { className: styles.datapages }, markdownValue(getIn(hubCohorts, [0, 'meta'])), React.createElement( 'h2', null, getHubName(host), inHubs ), React.createElement( 'p', null, 'Hub address: ', host ), React.createElement(CohortSummary, { hubParams: hubParams, cohorts: coll, onCohort: this.onCohort }) ); } }]); return HubPage; }(React.Component); // // Samples / Identifiers page // var binSize = 1000; // The point of ListPage is to render a potentially very long list // incrementally, so we get a fast first render, and don't lock up the UI. // We do that by rendering binSize rows at a time, on a requestAnimationFrame // timeout. var ListPage = function (_React$Component7) { _inherits(ListPage, _React$Component7); function ListPage() { var _ref13; var _temp7, _this8, _ret7; _classCallCheck(this, ListPage); for (var _len7 = arguments.length, args = Array(_len7), _key7 = 0; _key7 < _len7; _key7++) { args[_key7] = arguments[_key7]; } return _ret7 = (_temp7 = (_this8 = _possibleConstructorReturn(this, (_ref13 = ListPage.__proto__ || Object.getPrototypeOf(ListPage)).call.apply(_ref13, [this].concat(args))), _this8), _this8.state = {}, _temp7), _possibleConstructorReturn(_this8, _ret7); } _createClass(ListPage, [{ key: 'componentWillMount', value: function componentWillMount() { var _this9 = this; var _props6 = this.props, state = _props6.state, path = _props6.path, list = getIn(state, ['datapages', path, 'list']); var events = rxEvents(this, 'list'); var chunks = events.list.startWith(list).distinctUntilChanged().filter(identity).switchMap(function (ids) { var chunks = partitionN(ids, binSize).map(function (a) { return a.join('\n'); }); return from(range(chunks.length), animationFrame).map(function (i) { return { chunks: chunks.slice(0, i + 1), total: chunks.length }; }); }); this.sub = chunks.subscribe(function (chunks) { _this9.setState(chunks); }); } }, { key: 'componentWillUnmount', value: function componentWillUnmount() { this.sub.unsubscribe(); } }, { key: 'componentWillReceiveProps', value: function componentWillReceiveProps(props) { var state = props.state, path = props.path, list = getIn(state, ['datapages', path, 'list']); this.on.list(list); } }, { key: 'render', value: function render() { var _props7 = this.props, state = _props7.state, path = _props7.path, title = _props7.title, _state$params2 = state.params, host = _state$params2.host, dataset = _state$params2.dataset, datapages = state.datapages, _getIn = getIn(datapages, [path], {}), currentDataset = _getIn.dataset, currentHost = _getIn.host, _ref14 = currentHost !== host || currentDataset !== dataset ? {} : this.state, chunks = _ref14.chunks, total = _ref14.total, percent = !chunks ? ' 0%' : chunks.length === total ? '' : ' ' + Math.floor(chunks.length / total * 100) + '%'; return React.createElement( 'div', { className: styles.datapages }, React.createElement( 'h3', null, 'dataset: ', dataset ), React.createElement( 'h4', null, title, percent ), chunks ? chunks.map(function (c, i) { return React.createElement( 'pre', { key: i, className: styles.list }, c ); }) : 'Loading...' ); } }]); return ListPage; }(React.Component); var markdownPage = function (_React$Component8) { _inherits(markdownPage, _React$Component8); function markdownPage() { _classCallCheck(this, markdownPage); return _possibleConstructorReturn(this, (markdownPage.__proto__ || Object.getPrototypeOf(markdownPage)).apply(this, arguments)); } _createClass(markdownPage, [{ key: 'render', value: function render() { var state = this.props.state, content = getIn(state, ['datapages', 'markdownContent']); return React.createElement( 'div', { className: styles.datapages }, markdownValue(content) ); } }]); return markdownPage; }(React.Component); var IdentifiersPage = function IdentifiersPage(props) { return React.createElement(ListPage, _extends({ title: 'Identifiers', path: 'identifiers' }, props)); }; var SamplesPage = function SamplesPage(props) { return React.createElement(ListPage, _extends({ title: 'Samples', path: 'samples' }, props)); }; // // Top-level dispatch to sub-pages // var getPage = function getPage(_ref15) { var dataset = _ref15.dataset, host = _ref15.host, cohort = _ref15.cohort, allIdentifiers = _ref15.allIdentifiers, allSamples = _ref15.allSamples, markdown = _ref15.markdown; return markdown ? markdownPage : allSamples ? SamplesPage : allIdentifiers ? IdentifiersPage : dataset && host ? DatasetPage : host ? HubPage : cohort ? CohortPage : CohortSummaryPage; }; var Datapages = function (_React$Component9) { _inherits(Datapages, _React$Component9); function Datapages() { var _ref16; var _temp8, _this11, _ret8; _classCallCheck(this, Datapages); for (var _len8 = arguments.length, args = Array(_len8), _key8 = 0; _key8 < _len8; _key8++) { args[_key8] = arguments[_key8]; } return _ret8 = (_temp8 = (_this11 = _possibleConstructorReturn(this, (_ref16 = Datapages.__proto__ || Object.getPrototypeOf(Datapages)).call.apply(_ref16, [this].concat(args))), _this11), _this11.onNavigate = function (page) { _this11.props.callback(['navigate', page]); }, _temp8), _possibleConstructorReturn(_this11, _ret8); } _createClass(Datapages, [{ key: 'componentDidMount', value: function componentDidMount() { nav({ activeLink: 'datapages', onNavigate: this.onNavigate }); } }, { key: 'render', value: function render() { var state = this.props.state, params = state.params, hubParams = getHubParams(state), Page = getPage(defaultHost(params)); return React.createElement(Page, _extends({}, this.props, { hubParams: hubParams })); } }]); return Datapages; }(React.Component); var ThemedDatapages = function (_React$Component10) { _inherits(ThemedDatapages, _React$Component10); function ThemedDatapages() { _classCallCheck(this, ThemedDatapages); return _possibleConstructorReturn(this, (ThemedDatapages.__proto__ || Object.getPrototypeOf(ThemedDatapages)).apply(this, arguments)); } _createClass(ThemedDatapages, [{ key: 'render', value: function render() { return React.createElement( _reactCssThemr.ThemeProvider, { theme: appTheme }, React.createElement(Datapages, this.props) ); } }]); return ThemedDatapages; }(React.Component); var selector = function selector(state) { return state; }; module.exports = function (props) { return React.createElement(ThemedDatapages, _extends({}, props, { selector: selector })); };