From e402b168328db4b8ba94e38893789081e8d6f488 Mon Sep 17 00:00:00 2001 From: Christine Yu Date: Wed, 13 Apr 2016 14:41:38 -0400 Subject: [PATCH 01/80] fix(header): use flexbox for gdc-apps-menu Closes #1933 --- .../components/header/templates/header.html | 88 +++++++------------ app/styles/home.less | 14 ++- 2 files changed, 46 insertions(+), 56 deletions(-) diff --git a/app/scripts/components/header/templates/header.html b/app/scripts/components/header/templates/header.html index 028dc473b..fc812afc5 100755 --- a/app/scripts/components/header/templates/header.html +++ b/app/scripts/components/header/templates/header.html @@ -114,77 +114,57 @@ + + - diff --git a/app/styles/home.less b/app/styles/home.less index e661d2822..3a7d8171d 100644 --- a/app/styles/home.less +++ b/app/styles/home.less @@ -29,7 +29,14 @@ text-align: center; font-size: 1.2rem; + display: flex; + justify-content: space-between; + .menu-column { + display: flex; + flex-wrap: wrap; + flex-direction: column; + } &:before { width: 0; @@ -51,8 +58,11 @@ background-color: #ccc; } - td { - padding: 0.25rem; + .menu-item { + padding: 0.5rem; + white-space: nowrap; + margin: 0.25rem; + flex: 1; } a { From e12dd5293900db19a2e03ff55bc5817f81ca1e6c Mon Sep 17 00:00:00 2001 From: Alex Wilmer Date: Fri, 15 Apr 2016 11:06:24 -0400 Subject: [PATCH 02/80] fix(tables): disable export > 2000 rows, exts - only allow JSON export and only when < 2000 rows Closes #2071 --- .../tables/templates/export-table.html | 4 +++- .../components/tables/templates/gdc-table.html | 16 +++++++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/app/scripts/components/tables/templates/export-table.html b/app/scripts/components/tables/templates/export-table.html index ee3634f1e..129c50d92 100644 --- a/app/scripts/components/tables/templates/export-table.html +++ b/app/scripts/components/tables/templates/export-table.html @@ -34,7 +34,9 @@ From b031a942b297f3229e216822865400cde83805aa Mon Sep 17 00:00:00 2001 From: Terry Lin Date: Tue, 19 Apr 2016 14:42:15 -0400 Subject: [PATCH 15/80] fix(download): 2056 displays progress in button Closes #2056 --- app/scripts/cart/cart.directives.ts | 18 ++++++++ app/scripts/cases/cases.directives.ts | 6 +++ .../ui/controls/controls.directives.ts | 45 ++++++++++++------- .../templates/split-control-option.html | 2 +- app/scripts/files/files.directives.ts | 6 +++ 5 files changed, 61 insertions(+), 16 deletions(-) diff --git a/app/scripts/cart/cart.directives.ts b/app/scripts/cart/cart.directives.ts index d421227e8..b813ca5d7 100644 --- a/app/scripts/cart/cart.directives.ts +++ b/app/scripts/cart/cart.directives.ts @@ -262,12 +262,18 @@ module ngApp.cart.directives { const scope = $scope; scope.active = false; + const reportStatus = _.isFunction(scope.$parent.reportStatus) ? + _.partial(scope.$parent.reportStatus, scope.$id) : + () => {}; + const inProgress = () => { scope.active = true; + reportStatus(scope.active); $attrs.$set('disabled', 'disabled'); }; const done = () => { scope.active = false; + reportStatus(scope.active); $element.removeAttr('disabled'); }; const files = [].concat(CartService.getFiles()); @@ -290,12 +296,18 @@ module ngApp.cart.directives { link: (scope, $element, $attrs) => { scope.active = false; + const reportStatus = _.isFunction(scope.$parent.reportStatus) ? + _.partial(scope.$parent.reportStatus, scope.$id) : + () => {}; + const inProgress = () => { scope.active = true; + reportStatus(scope.active); $attrs.$set('disabled', 'disabled'); }; const done = () => { scope.active = false; + reportStatus(scope.active); $element.removeAttr('disabled'); }; const files = [].concat(CartService.getFiles()); @@ -327,12 +339,18 @@ module ngApp.cart.directives { authorized: authorizedInCart }; + const reportStatus = _.isFunction(scope.$parent.reportStatus) ? + _.partial(scope.$parent.reportStatus, scope.$id) : + () => {}; + const inProgress = () => { scope.active = true; + reportStatus(scope.active); $attrs.$set('disabled', 'disabled'); }; const done = () => { scope.active = false; + reportStatus(scope.active); $element.removeAttr('disabled'); }; const files = [].concat(authorizedInCart); diff --git a/app/scripts/cases/cases.directives.ts b/app/scripts/cases/cases.directives.ts index 90bbab617..296945a8c 100644 --- a/app/scripts/cases/cases.directives.ts +++ b/app/scripts/cases/cases.directives.ts @@ -20,12 +20,18 @@ module ngApp.cases.directives {  {{ ::textNormal }} \  {{ ::textInProgress }}', link: (scope, $element, $attrs) => { + const reportStatus = _.isFunction(scope.$parent.reportStatus) ? + _.partial(scope.$parent.reportStatus, scope.$id) : + () => {}; + const inProgress = () => { scope.active = true; + reportStatus(scope.active); $attrs.$set('disabled', 'disabled'); }; const done = () => { scope.active = false; + reportStatus(scope.active); $element.removeAttr('disabled'); }; const url = config.api + '/cases'; diff --git a/app/scripts/components/ui/controls/controls.directives.ts b/app/scripts/components/ui/controls/controls.directives.ts index f425d1617..a003a4dc5 100644 --- a/app/scripts/components/ui/controls/controls.directives.ts +++ b/app/scripts/components/ui/controls/controls.directives.ts @@ -25,25 +25,23 @@ module ngApp.components.ui.control.directives { // Included for extensibility }, link: ($scope: ISplitControlScope, $element: ng.IAugmentedJQuery, $attrs: ng.IAttributes) => { - - const scope = $scope; + var loadingState = false; + var childStates = {}; function _initListeners() { - $element.keydown(function(e){ - if(e.which == 13){ // enter key - $element.find('#' + $scope.uiControl.id).click(); - } + $element.keydown(function(e) { + if(e.which == 13) { // enter key + $element.find('#' + $scope.uiControl.id).click(); + } }); - scope.$watch(() => { - return scope[$attrs.isLoadingIndicatorFlag]; - }, (isLoading) => { - scope.uiControl.isLoading = isLoading; + $scope.$watch(() => loadingState, (isLoading) => { + $scope.uiControl.isLoading = isLoading; }); } function _init() { - scope.uiControl = { + $scope.uiControl = { id: 'split-control-' + (new Date().getTime()), isLoading: false, controlLabelText: $attrs.controlLabelText || 'Action Label', @@ -52,13 +50,15 @@ module ngApp.components.ui.control.directives { iconClasses: $attrs.iconClasses || false, btnType: $attrs.btnType || 'primary' }; + $scope.reportStatus = (id, status) => { + _.set(childStates, [id], status); + loadingState = _.some(_.values(childStates), (s) => s); + }; _initListeners(); } _init(); - - } }; } @@ -71,12 +71,27 @@ module ngApp.components.ui.control.directives { transclude: true, require: "^splitControl", templateUrl: "components/ui/controls/templates/split-control-option.html", - link: () => { + link: (scope, element, attributes, controller, transclude) => { + const myId = scope.id; + var loadingState = false; + var childStates = {}; + + scope.reportStatus = (id, status) => { + _.set(childStates, [id], status); + loadingState = _.some(_.values(childStates), (s) => s); + }; + + scope.$watch(() => loadingState, (isLoading) => { + scope.$parent.$parent.reportStatus(myId, isLoading); + }); + + transclude(scope.$new(), (clone) => { + element.append(clone); + }); } }; } - angular.module("ui.control.directives", []) .directive("splitControl", SplitControl) .directive("splitControlOption", SplitControlOption); diff --git a/app/scripts/components/ui/controls/templates/split-control-option.html b/app/scripts/components/ui/controls/templates/split-control-option.html index ae2c57465..a6ab67787 100644 --- a/app/scripts/components/ui/controls/templates/split-control-option.html +++ b/app/scripts/components/ui/controls/templates/split-control-option.html @@ -1 +1 @@ - + diff --git a/app/scripts/files/files.directives.ts b/app/scripts/files/files.directives.ts index c41193a73..0fd783265 100644 --- a/app/scripts/files/files.directives.ts +++ b/app/scripts/files/files.directives.ts @@ -21,13 +21,19 @@ module ngApp.files.directives { controller: function($scope: ng.IScope, $attrs, $element, $uibModal, CartService: ICartService, UserService: IUserService, config: IGDCConfig) { const url = config.api + '/files'; + const reportStatus = _.isFunction($scope.$parent.reportStatus) ? + _.partial($scope.$parent.reportStatus, $scope.$id) : + () => {}; + const inProgress = () => { $scope.active = true; + reportStatus($scope.active); $attrs.$set('disabled', 'disabled'); }; const done = () => { $scope.active = false; + reportStatus($scope.active); $element.removeAttr('disabled'); }; From ad2d4d2c6fe1e392608b72850a0fb8840b23ac11 Mon Sep 17 00:00:00 2001 From: Alex Wilmer Date: Wed, 20 Apr 2016 15:11:12 -0400 Subject: [PATCH 16/80] fix(reports): 2137 handle no reports - do not load graph - show message Closes #2137 --- app/scripts/reports/reports.controllers.ts | 33 +++++++++++----------- app/scripts/reports/templates/reports.html | 6 +++- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/app/scripts/reports/reports.controllers.ts b/app/scripts/reports/reports.controllers.ts index 9baf5bc57..3f24776e4 100755 --- a/app/scripts/reports/reports.controllers.ts +++ b/app/scripts/reports/reports.controllers.ts @@ -37,22 +37,24 @@ module ngApp.reports.controllers { CoreService.setPageTitle("Reports"); - var dataNoZeros = _.reject(reports.hits, (hit) => { return hit.count === 0 && hit.size ===0; }); - this.byProject = this.dataNest("project_id").entries(dataNoZeros); - this.byDisease = this.dataNest("disease_type").entries(dataNoZeros); - this.byProgram = this.dataNest("program").entries(dataNoZeros); - this.byDataType = this.dataNest("data_categories").entries(this.reduceBy(dataNoZeros, "data_categories")); - this.bySubtype = this.dataNest("data_type").entries(this.reduceBy(dataNoZeros, "data_types")); - this.byStrat = this.dataNest("experimental_strategy").entries(this.reduceBy(dataNoZeros, "experimental_strategies")); - this.byDataAccess = this.dataNest("access").entries(this.reduceBy(dataNoZeros, "data_access")); - this.byUserType = this.dataNest("user_access_type").entries(this.reduceBy(dataNoZeros, "user_access_types")); - this.byLocation = this.dataNest("country").entries(this.reduceBy(dataNoZeros, "countries")); + if (reports.hits.length) { + var dataNoZeros = _.reject(reports.hits, (hit) => { return hit.count === 0 && hit.size ===0; }); + this.byProject = this.dataNest("project_id").entries(dataNoZeros); + this.byDisease = this.dataNest("disease_type").entries(dataNoZeros); + this.byProgram = this.dataNest("program").entries(dataNoZeros); + this.byDataType = this.dataNest("data_categories").entries(this.reduceBy(dataNoZeros, "data_categories")); + this.bySubtype = this.dataNest("data_type").entries(this.reduceBy(dataNoZeros, "data_types")); + this.byStrat = this.dataNest("experimental_strategy").entries(this.reduceBy(dataNoZeros, "experimental_strategies")); + this.byDataAccess = this.dataNest("access").entries(this.reduceBy(dataNoZeros, "data_access")); + this.byUserType = this.dataNest("user_access_type").entries(this.reduceBy(dataNoZeros, "user_access_types")); + this.byLocation = this.dataNest("country").entries(this.reduceBy(dataNoZeros, "countries")); - $timeout(() => { - var githut = ReportsGithut(dataNoZeros); - $scope.githutData = githut.data; - $scope.githutConfig = githut.config; - }, 500); + $timeout(() => { + var githut = ReportsGithut(dataNoZeros); + $scope.githutData = githut.data; + $scope.githutConfig = githut.config; + }, 500); + } } dataNest(key: string): any { @@ -87,4 +89,3 @@ module ngApp.reports.controllers { ]) .controller("ReportsController", ReportsController); } - diff --git a/app/scripts/reports/templates/reports.html b/app/scripts/reports/templates/reports.html index 8c50811bb..a5a20675c 100755 --- a/app/scripts/reports/templates/reports.html +++ b/app/scripts/reports/templates/reports.html @@ -4,7 +4,11 @@

Data Download Statistics

-
+
+ No downloads to date. +
+ +

This report depicts statistics describing data download since the GDC Data Portal launch. Represented GDC data From ca3bb8a869c034ce8e3ebef5b7d981c7d43c5fe7 Mon Sep 17 00:00:00 2001 From: Alex Wilmer Date: Wed, 20 Apr 2016 11:45:40 -0400 Subject: [PATCH 17/80] fix(cart): 1952 update cart limit warning Closes #1952 --- app/scripts/cart/cart.services.ts | 33 +++++++++++++------------------ 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/app/scripts/cart/cart.services.ts b/app/scripts/cart/cart.services.ts index cc907d163..736e2a1eb 100644 --- a/app/scripts/cart/cart.services.ts +++ b/app/scripts/cart/cart.services.ts @@ -241,32 +241,27 @@ module ngApp.cart.services { } sizeWarning() { - var cartAvailable = this.getCartVacancySize(), - template = ["Only", this.$filter("number")(cartAvailable)]; - - if (cartAvailable !== this.getMaxSize()) { - if (cartAvailable > 1) { - template.push("more"); - template.push("files"); - } else if (cartAvailable === 1) { - template.push("more"); - template.push("file"); - } else { - template = ["No more files"]; - } - } else { - template.push("files"); + var cartAvailable = this.getCartVacancySize() + var template = [ + "The cart is limited to " + this.$filter("number")(this.getMaxSize()) + " files.", + !this.files.length + ? "Please narrow down your search criteria to be able to add files to your cart." + : this.files.length < this.getMaxSize() + ? this.$filter("number")(cartAvailable) + getRemaining() + "can be added to the cart." + : "You cannot add anymore files to the cart." + ]; + + function getRemaining() { + return cartAvailable > 1 ? " more files " : " more file "; } - template.push("can be added to the cart."); - - template = "" + this.gettextCatalog.getString(template.join(" ")) + ""; + var messageTemplate = "" + this.gettextCatalog.getString(template.join(" ")) + ""; this.notify.config({ duration: 5000 }); this.notify.closeAll(); this.notify({ message: "", - messageTemplate: template, + messageTemplate: messageTemplate, container: "#notification", classes: "alert-warning" }); From bdb0f45592ab7c1854e746941afd275284fb7273 Mon Sep 17 00:00:00 2001 From: Christine Yu Date: Wed, 20 Apr 2016 14:41:29 -0400 Subject: [PATCH 18/80] fix(cart): 2063 add all files off by one bug Closes #2063 --- app/scripts/cart/cart.controllers.ts | 2 +- app/scripts/cart/tests/cart.tests.js | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/app/scripts/cart/cart.controllers.ts b/app/scripts/cart/cart.controllers.ts index c0ec8a5ec..534aa0360 100644 --- a/app/scripts/cart/cart.controllers.ts +++ b/app/scripts/cart/cart.controllers.ts @@ -312,7 +312,7 @@ module ngApp.cart.controllers { var filters = (this.filter ? JSON.parse(this.filter) : undefined) || this.LocationService.filters(); filters = this.UserService.addMyProjectsFilter(filters, "cases.project.project_id"); - if (this.size >= this.CartService.getCartVacancySize()) { + if (this.size > this.CartService.getCartVacancySize()) { this.CartService.sizeWarning(); return; } diff --git a/app/scripts/cart/tests/cart.tests.js b/app/scripts/cart/tests/cart.tests.js index 787d61412..6bf471bfd 100755 --- a/app/scripts/cart/tests/cart.tests.js +++ b/app/scripts/cart/tests/cart.tests.js @@ -149,5 +149,28 @@ describe('Cart:', function () { expect(returnValue).to.contain(fileB.file_id); })); + it('should correctly report space left in cart', inject(function (CartService) { + expect(CartService.getCartVacancySize()).to.eq(CartService.getMaxSize()); + CartService.addFiles([fileA, fileB]); + expect(CartService.getCartVacancySize()).to.eq(CartService.getMaxSize() - 2); + var files = []; + for (var i = 0; i < CartService.getCartVacancySize(); i++) { + files.push({file_id : Math.random()}); + } + CartService.addFiles(files); + expect(CartService.getCartVacancySize()).to.eq(0); + + })); + + it('should correctly determine fullness', inject(function (CartService) { + expect(CartService.isFull()).to.eq(false); + var files = []; + for (var i = 0; i < CartService.getMaxSize(); i++) { + files.push({file_id : Math.random()}); + } + CartService.addFiles(files); + expect(CartService.isFull()).to.eq(true); + })); + }); }); From 539b686d17e96f4164eaafb06289888dce1816e5 Mon Sep 17 00:00:00 2001 From: Alex Wilmer Date: Wed, 20 Apr 2016 12:08:08 -0400 Subject: [PATCH 19/80] fix(app): 2095 round mb to 2 decimal places Closes #2095 --- app/scripts/components/ui/file/file.filters.ts | 4 ++-- app/scripts/components/ui/file/tests/sizefilter.tests.js | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/scripts/components/ui/file/file.filters.ts b/app/scripts/components/ui/file/file.filters.ts index 4084531cf..5f3ee8935 100644 --- a/app/scripts/components/ui/file/file.filters.ts +++ b/app/scripts/components/ui/file/file.filters.ts @@ -22,7 +22,7 @@ module ngApp.components.ui.file { } else if (val >= FileSize.BYTES_MB_LIMIT) { formattedVal = (val / FileSize.BYTES_GB).toFixed(2) + " GB"; } else if (val >= FileSize.BYTES_KB_LIMIT) { - formattedVal = (val / FileSize.BYTES_MB).toFixed(0) + " MB"; + formattedVal = (val / FileSize.BYTES_MB).toFixed(2) + " MB"; } else if (val >= FileSize.BYTES_KB) { formattedVal = (val / FileSize.BYTES_KB).toFixed(0) + " KB"; } else if (val) { @@ -36,4 +36,4 @@ module ngApp.components.ui.file { angular.module("file.filters", []) .filter("size", FileSize); -} \ No newline at end of file +} diff --git a/app/scripts/components/ui/file/tests/sizefilter.tests.js b/app/scripts/components/ui/file/tests/sizefilter.tests.js index 77368ee3d..f63e46de5 100644 --- a/app/scripts/components/ui/file/tests/sizefilter.tests.js +++ b/app/scripts/components/ui/file/tests/sizefilter.tests.js @@ -40,11 +40,11 @@ describe("File Size Filter:", function () { it("should filter MB when 999500000 > size >= 999500 bytes ", inject(function ($filter) { var formattedSize; formattedSize = $filter("size")(999500); - expect(formattedSize).to.equal("1 MB"); + expect(formattedSize).to.equal("1.00 MB"); formattedSize = $filter("size")(1000000); - expect(formattedSize).to.equal("1 MB"); + expect(formattedSize).to.equal("1.00 MB"); formattedSize = $filter("size")(999499999); - expect(formattedSize).to.equal("999 MB"); + expect(formattedSize).to.equal("999.50 MB"); })); it("should filter KB when 999499 > size >= 1000 bytes ", inject(function ($filter) { @@ -69,4 +69,4 @@ describe("File Size Filter:", function () { expect(formattedSize).to.equal("0 B"); })); -}); \ No newline at end of file +}); From 1ade49c001eec5869d6d13a0bc9eb3ac97e36b16 Mon Sep 17 00:00:00 2001 From: Alex Wilmer Date: Wed, 20 Apr 2016 15:28:59 -0400 Subject: [PATCH 20/80] feat(app): 2067 update id search facet text Closes #2067 --- app/scripts/components/facets/templates/facets-section.html | 2 +- app/scripts/search/search.participants.table.model.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/scripts/components/facets/templates/facets-section.html b/app/scripts/components/facets/templates/facets-section.html index fdb31544d..6d38dd1d4 100644 --- a/app/scripts/components/facets/templates/facets-section.html +++ b/app/scripts/components/facets/templates/facets-section.html @@ -6,7 +6,7 @@ data-template="components/facets/templates/typeahead-{{doctype}}.html"> diff --git a/app/scripts/search/search.participants.table.model.ts b/app/scripts/search/search.participants.table.model.ts index fd84e4dfb..c0b1cf9b0 100644 --- a/app/scripts/search/search.participants.table.model.ts +++ b/app/scripts/search/search.participants.table.model.ts @@ -257,7 +257,7 @@ module ngApp.search.models { "summary.data_categories", ], facets: [ - {name: "case_id", title: "Case", collapsed: false, facetType: "free-text", placeholder: "Case UUID"}, + {name: "case_id", title: "Case", collapsed: false, facetType: "free-text", placeholder: "UUID, Submitter ID"}, {name: "project.primary_site", title: "Primary Site", collapsed: false, facetType: "terms"}, {name: "project.program.name", title: "Cancer Program", collapsed: false, facetType: "terms"}, {name: "project.project_id", title: "Project", collapsed: false, facetType: "terms"}, From 8e069e65853ccade6e81d7c0a2b426fb1df6ce82 Mon Sep 17 00:00:00 2001 From: Shane Wilson Date: Thu, 14 Apr 2016 10:56:04 -0400 Subject: [PATCH 21/80] feat(app): add no js text --- app/index.html | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/app/index.html b/app/index.html index 6913590f6..920977baa 100755 --- a/app/index.html +++ b/app/index.html @@ -65,9 +65,22 @@ #loadingScreen { display: none; }

-

- Javascript is required to use the features of this website. -

+ +
+
+
+ Javascript is required to use the features of this website. Please enable Javascript and reload the page. +
+
+
@@ -78,7 +91,7 @@
diff --git a/app/scripts/app.ts b/app/scripts/app.ts index 5313028c0..af421b878 100755 --- a/app/scripts/app.ts +++ b/app/scripts/app.ts @@ -34,6 +34,40 @@ import IUserService = ngApp.components.user.services.IUserService; import IProjectsService = ngApp.projects.services.IProjectsService; import ILocalStorageService = ngApp.core.services.ILocalStorageService; +function logVersionInfo (config) { + console.groupCollapsed( + "%c★ UI Git Info\n" + + "=============", + "color: rgb(173, 30, 30); font-weight: bold;" + ) + + console.info("%cTag: %c" + config.tag, + "font-weight: bold;", "color: rgb(89, 139, 214);" + ) + + console.info("%cCommit Link: %c" + config.commitLink, + "font-weight: bold;", "color: rgb(89, 139, 214);" + ) + + console.groupEnd() + + console.groupCollapsed( + "%c★ API Git Info\n" + + "==============", + "color: rgb(173, 30, 30); font-weight: bold;" + ) + + console.info("%cTag: %c" + config.apiTag, + "font-weight: bold;", "color: rgb(89, 139, 214);" + ) + + console.info("%cCommit Link: %c" + config.apiCommitLink, + "font-weight: bold;", "color: rgb(89, 139, 214);" + ) + + console.groupEnd() +} + // Cross-Site Request Forgery (CSRF) Prevention // https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet#General_Recommendation:_Synchronizer_Token_Pattern function addTokenToRequest (element, operation, route, url, headers, params, httpConfig) { @@ -137,6 +171,8 @@ function appRun(gettextCatalog: any, config.apiTag = "https://github.com/NCI-GDC/gdcapi/releases/tag/" + config.apiVersion; config.apiCommitLink ="https://github.com/NCI-GDC/gdcapi/commit/" + config.apiCommitHash; + logVersionInfo(config) + if (+data.version !== +config.supportedAPI) { config.apiIsMismatched = true; } @@ -177,7 +213,6 @@ function appRun(gettextCatalog: any, // Page change CoreService.setLoadedState(true); }); - } angular From 6aa13b340b2008542b49d574cf3f2059ecf5578b Mon Sep 17 00:00:00 2001 From: Alex Wilmer Date: Mon, 18 Apr 2016 13:09:51 -0400 Subject: [PATCH 34/80] feat(components): file.submitter_id > quicksearch - only return one item max in highlight filter Closes #1792 --- .../quick-search/highlight.filter.ts | 41 ++++++++++++++++ app/scripts/components/quick-search/module.ts | 3 +- .../quick-search/quick-search.directives.ts | 47 ------------------- .../quick-search/templates/file.html | 4 ++ .../templates/quick-search-input-home.html | 44 ++++++++++------- .../tests/highlight.filter.tests.js | 15 ++++++ 6 files changed, 88 insertions(+), 66 deletions(-) create mode 100644 app/scripts/components/quick-search/highlight.filter.ts create mode 100644 app/scripts/components/quick-search/tests/highlight.filter.tests.js diff --git a/app/scripts/components/quick-search/highlight.filter.ts b/app/scripts/components/quick-search/highlight.filter.ts new file mode 100644 index 000000000..36378bee4 --- /dev/null +++ b/app/scripts/components/quick-search/highlight.filter.ts @@ -0,0 +1,41 @@ +module ngApp.components.ui.string { + + class Highlight { + constructor($rootScope: ng.IScope) { + return function (value: any, query: string = "") { + if (!value) { + return ""; + } + + var regex = new RegExp("[" + query.replace(/\-/g, "\\-") + "]{" + query.length + "}", "i"); + + if (!_.isArray(value)) { + value = [value]; + } + + var html = ""; + // Only ever show the top matched term in the arrays returned. + var term = value.filter(item => { + var matchedText = item.match(regex); + return matchedText && matchedText[0] && + matchedText[0].toLowerCase() === query.toLowerCase(); + }).sort((a, b) => a.match(regex).length - b.match(regex).length)[0]; + + if (term) { + var matchedText = term.match(regex); + matchedText = matchedText[0]; + var boldedQuery = "" + matchedText + ""; + html = term.replace(regex, boldedQuery); + } else { + html = value[0]; // if nothing matches, take first value + } + + return html; + }; + } + } + + angular + .module("quickSearch.filters", []) + .filter("highlight", Highlight) +} diff --git a/app/scripts/components/quick-search/module.ts b/app/scripts/components/quick-search/module.ts index 25b1fe2e5..d87745d90 100644 --- a/app/scripts/components/quick-search/module.ts +++ b/app/scripts/components/quick-search/module.ts @@ -1,5 +1,6 @@ module ngApp.components.quickSearch { angular.module("components.quickSearch", [ - "quickSearch.directives" + "quickSearch.directives", + "quickSearch.filters", ]); } diff --git a/app/scripts/components/quick-search/quick-search.directives.ts b/app/scripts/components/quick-search/quick-search.directives.ts index a28a92d41..368f6dd1f 100644 --- a/app/scripts/components/quick-search/quick-search.directives.ts +++ b/app/scripts/components/quick-search/quick-search.directives.ts @@ -272,59 +272,12 @@ module ngApp.components.quickSearch.directives { }; } - - - class Highlight { - constructor($rootScope: ng.IScope) { - return function (value: any, query: string = "") { - if (!value) { - return ""; - } - - var regex = new RegExp("[" + query.replace(/\-/g, "\\-") + "]{" + query.length + "}", "i"); - - if (!_.isArray(value)) { - value = [value]; - } - - var html = ""; - // Only ever show the top matched term in the arrays returned. - var term = _.filter(value, (item) => { - var matchedText = item.match(regex); - - if (matchedText) { - matchedText = matchedText[0]; - - return matchedText.toLowerCase() === query.toLowerCase(); - } - - return false; - }).sort((a, b) => { - return a.match(regex).length - b.match(regex).length; - })[0]; - - if (term) { - var matchedText = term.match(regex); - matchedText = matchedText[0]; - var boldedQuery = "" + matchedText + ""; - html = term.replace(regex, boldedQuery); - } else { - html = value; - } - - return html; - }; - } - } - - angular .module("quickSearch.directives", [ "ui.bootstrap.modal", "facets.services", "quickSearch.services" ]) - .filter("highlight", Highlight) .directive("quickSearchDropdown", QuickSearchDropdown) .directive("quickSearchInput", QuickSearchInput) .directive("quickSearchInputHome", QuickSearchInputHome) diff --git a/app/scripts/components/quick-search/templates/file.html b/app/scripts/components/quick-search/templates/file.html index aab695518..fca4c2749 100644 --- a/app/scripts/components/quick-search/templates/file.html +++ b/app/scripts/components/quick-search/templates/file.html @@ -13,6 +13,10 @@ File Name {{ selectedItem.file_name }} + + File Submitter ID + {{ selectedItem.submitter_id }} + Data Type {{ selectedItem.data_type }} diff --git a/app/scripts/components/quick-search/templates/quick-search-input-home.html b/app/scripts/components/quick-search/templates/quick-search-input-home.html index 3ef9e532a..35d715e6c 100644 --- a/app/scripts/components/quick-search/templates/quick-search-input-home.html +++ b/app/scripts/components/quick-search/templates/quick-search-input-home.html @@ -32,29 +32,37 @@
- +
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
@@ -62,4 +70,4 @@ - \ No newline at end of file + diff --git a/app/scripts/components/quick-search/tests/highlight.filter.tests.js b/app/scripts/components/quick-search/tests/highlight.filter.tests.js new file mode 100644 index 000000000..053391519 --- /dev/null +++ b/app/scripts/components/quick-search/tests/highlight.filter.tests.js @@ -0,0 +1,15 @@ +describe("Highlight Filter:", function() { + beforeEach(module("ngApp.components")); + + it ("it should wrap bolded span if the query matches an item in the array", + inject(function ($filter) { + expect($filter("highlight")(["foo"], "foo")).to.equal( + "foo" + ); + }) + ); + + it ("it should never return an array", inject(function ($filter) { + expect($filter("highlight")(["foo"])).to.equal("foo"); + })); +}); From fc69f8381d8cb31c6b15289b527cca63712397a2 Mon Sep 17 00:00:00 2001 From: Alex Wilmer Date: Thu, 21 Apr 2016 17:37:26 -0400 Subject: [PATCH 35/80] fix(file): 2140 remove date fields from table Closes #2140 --- app/scripts/files/module.ts | 2 -- app/scripts/files/templates/file.html | 8 -------- 2 files changed, 10 deletions(-) diff --git a/app/scripts/files/module.ts b/app/scripts/files/module.ts index 85c3de44b..0b970d932 100755 --- a/app/scripts/files/module.ts +++ b/app/scripts/files/module.ts @@ -28,8 +28,6 @@ module ngApp.files { "platform", "experimental_strategy", "center.short_name", - "created_datetime", - "uploaded_datetime", "cases.case_id", "cases.project.project_id", "annotations.annotation_id", diff --git a/app/scripts/files/templates/file.html b/app/scripts/files/templates/file.html index 29052c553..b55c5fe90 100755 --- a/app/scripts/files/templates/file.html +++ b/app/scripts/files/templates/file.html @@ -55,14 +55,6 @@

File Properties

MD5 Checksum {{ ::fc.file.md5sum }} - - Published - {{ ::fc.file.created_datetime || '--' | date:'yyyy-MM-dd' }} - - - Uploaded - {{ ::fc.file.uploaded_datetime || '--' | date:'yyyy-MM-dd' }} - State {{ ::fc.file.state | humanify }} From 8bc8196484a3253bfc59d87f2230a511396cfbfb Mon Sep 17 00:00:00 2001 From: Terry Lin Date: Thu, 21 Apr 2016 17:48:37 -0400 Subject: [PATCH 36/80] fix(entity): 2136 displays treatments Closes #2136 --- app/scripts/participant/module.ts | 1 + app/scripts/participant/participants.controllers.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/scripts/participant/module.ts b/app/scripts/participant/module.ts index 2260ff043..4272ee715 100755 --- a/app/scripts/participant/module.ts +++ b/app/scripts/participant/module.ts @@ -21,6 +21,7 @@ module ngApp.participants { expand: [ "demographic", "diagnoses", + "diagnoses.treatments", "exposures", "family_histories", "files", diff --git a/app/scripts/participant/participants.controllers.ts b/app/scripts/participant/participants.controllers.ts index 88ea29d9e..64f94c948 100755 --- a/app/scripts/participant/participants.controllers.ts +++ b/app/scripts/participant/participants.controllers.ts @@ -56,7 +56,7 @@ module ngApp.participants.controllers { this.clinicalDataExportFilters = { 'cases.case_id': participant.case_id }; - this.clinicalDataExportExpands = ['demographic', 'diagnoses', 'family_histories', 'exposures']; + this.clinicalDataExportExpands = ['demographic', 'diagnoses', 'diagnoses.treatments', 'family_histories', 'exposures']; this.hasNoClinical = _.all(this.clinicalDataExportExpands, (field) => ! _.has(participant, field)); this.clinicalDataExportFileName = 'clinical.case-' + participant.case_id; From b863ba49b8df1f1f41fd250db8c8d4f2efd8f653 Mon Sep 17 00:00:00 2001 From: Alex Wilmer Date: Fri, 22 Apr 2016 14:45:28 -0400 Subject: [PATCH 37/80] fix(components): if blacklist exists then filter - fix bug where experimental strategies was not displaying --- .../summary-card/summary-card.directives.ts | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/app/scripts/components/summary-card/summary-card.directives.ts b/app/scripts/components/summary-card/summary-card.directives.ts index 419b7cdd1..c4c7e51df 100644 --- a/app/scripts/components/summary-card/summary-card.directives.ts +++ b/app/scripts/components/summary-card/summary-card.directives.ts @@ -129,11 +129,13 @@ module ngApp.components.summaryCard.directives { item.color = color(index); }); - $scope.tableData = newVal.filter(x => - !config.blacklist.some(y => - y.toLowerCase() === x.data_category.toLowerCase() - ) - ); + $scope.tableData = config.blacklist + ? newVal.filter(x => + !config.blacklist.some(y => + y.toLowerCase() === x.data_category.toLowerCase() + ) + ) + : newVal; } }); } @@ -200,11 +202,13 @@ module ngApp.components.summaryCard.directives { item.color = color(index); }); - $scope.tableData = newVal.filter(x => - !config.blacklist.some(y => - y.toLowerCase() === x.data_category.toLowerCase() - ) - ); + $scope.tableData = config.blacklist + ? newVal.filter(x => + !config.blacklist.some(y => + y.toLowerCase() === x.data_category.toLowerCase() + ) + ) + : newVal; } }); } From 8baede1a5f3a0950afcd3587b5ffa3f22cc6109f Mon Sep 17 00:00:00 2001 From: Shane Wilson Date: Wed, 20 Apr 2016 15:40:03 -0400 Subject: [PATCH 38/80] feat(gql): 1045 support mapping description Closes #1045 --- app/scripts/components/facets/facets.services.ts | 2 +- app/scripts/components/gql/templates/gql_dropdown.html | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/scripts/components/facets/facets.services.ts b/app/scripts/components/facets/facets.services.ts index 35bf98d41..3a76c8bb8 100644 --- a/app/scripts/components/facets/facets.services.ts +++ b/app/scripts/components/facets/facets.services.ts @@ -235,7 +235,7 @@ module ngApp.components.facets.services { !_.includes(datum.field, "_id") && !_.includes(current, datum.field) && !_.includes(docType === 'files' ? _.pluck(this.SearchTableFilesModel.facets, "name") : _.pluck(this.SearchTableParticipantsModel.facets, "name"), datum.field); - }), f => _.merge(f, {'description': 'this is a description'})); + }), f => f); }); } diff --git a/app/scripts/components/gql/templates/gql_dropdown.html b/app/scripts/components/gql/templates/gql_dropdown.html index 6c19a4dd6..85c2e3362 100644 --- a/app/scripts/components/gql/templates/gql_dropdown.html +++ b/app/scripts/components/gql/templates/gql_dropdown.html @@ -17,7 +17,8 @@ style="margin-right: 10px;background: #5b5151;padding: 1rem;color: #fff;"> - + +
  • From bd564ac243564b2fe186c8acc4095b16442ceecc Mon Sep 17 00:00:00 2001 From: Shane Wilson Date: Wed, 20 Apr 2016 16:43:38 -0400 Subject: [PATCH 39/80] chore(app): feedback --- app/scripts/components/facets/templates/add-facets-modal.html | 2 +- app/scripts/components/gql/module.ts | 3 ++- app/scripts/components/gql/styles/styles.less | 2 +- app/scripts/components/gql/templates/gql_dropdown.html | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/app/scripts/components/facets/templates/add-facets-modal.html b/app/scripts/components/facets/templates/add-facets-modal.html index f0ba5e639..138a2c6ac 100644 --- a/app/scripts/components/facets/templates/add-facets-modal.html +++ b/app/scripts/components/facets/templates/add-facets-modal.html @@ -43,7 +43,7 @@

    {{ filteredFields.length }} {{ cufc.docType }} fields

    diff --git a/app/scripts/components/gql/module.ts b/app/scripts/components/gql/module.ts index 186c02d9a..001b8bf8a 100644 --- a/app/scripts/components/gql/module.ts +++ b/app/scripts/components/gql/module.ts @@ -404,7 +404,8 @@ module ngApp.components.gql { GqlService.clean(m.full.toString()) && ( GqlService.contains(m.full.toString(), $scope.parts.needle.replace(T.LPARENS, T.NOTHING)) || - GqlService.contains(m.type, $scope.parts.needle.replace(T.LPARENS, T.NOTHING)) + GqlService.contains(m.type, $scope.parts.needle.replace(T.LPARENS, T.NOTHING)) || + GqlService.contains(m.description, $scope.parts.needle.replace(T.LPARENS, T.NOTHING)) ) ); diff --git a/app/scripts/components/gql/styles/styles.less b/app/scripts/components/gql/styles/styles.less index a668f58f5..1f57ce827 100644 --- a/app/scripts/components/gql/styles/styles.less +++ b/app/scripts/components/gql/styles/styles.less @@ -25,7 +25,7 @@ .Gql_dropdown_item:hover, .Gql_dropdown_item-active { color: #fff; - background: navy; + background: #1f486c; } .Gql_dropdown_arrow { diff --git a/app/scripts/components/gql/templates/gql_dropdown.html b/app/scripts/components/gql/templates/gql_dropdown.html index 85c2e3362..dcb43b92d 100644 --- a/app/scripts/components/gql/templates/gql_dropdown.html +++ b/app/scripts/components/gql/templates/gql_dropdown.html @@ -18,7 +18,7 @@ -
    +
  • From 9596437df9a58ebf65dfd2fbc4a15c2119cb6eb7 Mon Sep 17 00:00:00 2001 From: Terry Lin Date: Mon, 25 Apr 2016 16:26:12 -0400 Subject: [PATCH 40/80] fix(facet): 2171 custom facet not added in IE Closes #2171 --- app/scripts/components/facets/facets.services.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/scripts/components/facets/facets.services.ts b/app/scripts/components/facets/facets.services.ts index 3a76c8bb8..031f17c1a 100644 --- a/app/scripts/components/facets/facets.services.ts +++ b/app/scripts/components/facets/facets.services.ts @@ -275,7 +275,7 @@ module ngApp.components.facets.services { name: fieldName, title: fieldName, collapsed: false, - facetType: fieldType === 'long' ? 'range' : fieldName.includes('datetime') ? 'datetime' : 'terms', + facetType: fieldType === 'long' ? 'range' : _.includes(fieldName, 'datetime') ? 'datetime' : 'terms', removable: true }); this.save(); From 75637e23a483aef7b22615be5bfbd540425fcbe0 Mon Sep 17 00:00:00 2001 From: Christine Yu Date: Mon, 18 Apr 2016 11:11:25 -0400 Subject: [PATCH 41/80] feat(file): 1470 entity pg updates - workflow, referenceGenome, readGroup, downstreamAnalysis tables w/ real fields - show different tables according to data_category Closes #1470 --- app/scripts/files/files.controllers.ts | 31 ++++++- app/scripts/files/module.ts | 19 ++++- app/scripts/files/templates/file.html | 85 ++++++++++--------- .../search/search.participants.table.model.ts | 1 + 4 files changed, 90 insertions(+), 46 deletions(-) diff --git a/app/scripts/files/files.controllers.ts b/app/scripts/files/files.controllers.ts index 5159d1a73..028ffdfcb 100755 --- a/app/scripts/files/files.controllers.ts +++ b/app/scripts/files/files.controllers.ts @@ -12,22 +12,41 @@ module ngApp.files.controllers { handleCartButton(): void; archiveCount: number; annotationIds: string[]; + tablesToDisplay: string[]; + makeSearchPageLink(files: IFile[]): string; } class FileController implements IFileController { archiveCount: number = 0; annotationIds: string[] = []; + tablesToDisplay: string[]; /* @ngInject */ constructor(public file: IFile, public $scope: ng.IScope, private CoreService: ICoreService, private CartService: ICartService, - private FilesService: IFilesService + private FilesService: IFilesService, + private $filter: ng.IFilterService ) { CoreService.setPageTitle("File", file.file_name); + var toDisplayLogic = { + 'Raw Sequencing Data': ['workflow', 'referenceGenome', 'readGroup', 'downstreamAnalysis'], + 'Transcriptome Profiling': ['workflow', 'referenceGenome', 'downstreamAnalysis'], + 'Simple Nucleotide Variation': ['workflow', 'referenceGenome', 'downstreamAnalysis'], + 'Copy Number Variation': ['workflow', 'referenceGenome', 'downstreamAnalysis'], + 'Structural Rearrangement': ['workflow', 'referenceGenome', 'downstreamAnalysis'], + 'DNA Methylation': ['workflow', 'referenceGenome', 'downstreamAnalysis'], + 'Clinical': [], + 'Biospecimen': [] + } + this.tablesToDisplay = (toDisplayLogic[file.data_category] || []).reduce((acc, t) => { + acc[t] = true; + return acc; + }, {}); + if (this.file.archive) { this.FilesService.getFiles({ fields: [ @@ -73,6 +92,15 @@ module ngApp.files.controllers { (this.file.data_format || '').toLowerCase() === 'bam'; } + makeSearchPageLink(files: IFile[] = []): string { + if (!files.length) { + return 0; + } + var filterString = this.$filter("makeFilter")([{field: 'file_id', value: files.map(f => f.file_id)}], true); + var href = 'search/f?filters=' + filterString; + return files.length ? "" + files.length + '' : '0'; + } + } class BAMSlicingController { @@ -126,7 +154,6 @@ module ngApp.files.controllers { private errorBlob: any) {} } - angular .module("files.controller", [ "files.services" diff --git a/app/scripts/files/module.ts b/app/scripts/files/module.ts index 0b970d932..7e011f640 100755 --- a/app/scripts/files/module.ts +++ b/app/scripts/files/module.ts @@ -19,8 +19,6 @@ module ngApp.files { "access", "data_format", "data_type", - "data_subtype", - "data_format", "data_category", "file_name", "file_size", @@ -42,6 +40,23 @@ module ngApp.files { "associated_entities.entity_id", "associated_entities.entity_type", "associated_entities.case_id", + "analysis.analysis_id", + "analysis.workflow_type", + "analysis.updated_datetime", + "analysis.input_files.file_id", + "analysis.metadata.read_groups.read_group_id", + "analysis.metadata.read_groups.is_paired_end", + "analysis.metadata.read_groups.read_length", + "analysis.metadata.read_groups.library_name", + "analysis.metadata.read_groups.sequencing_center", + "analysis.metadata.read_groups.sequencing_date", + "downstream_analysis.output_files.file_id", + "downstream_analysis.output_files.file_name", + "downstream_analysis.output_files.data_category", + "downstream_analysis.output_files.data_type", + "downstream_analysis.output_files.data_format", + "downstream_analysis.workflow_type", + "downstream_analysis.output_files.file_size", ] }); } diff --git a/app/scripts/files/templates/file.html b/app/scripts/files/templates/file.html index b55c5fe90..87446d979 100755 --- a/app/scripts/files/templates/file.html +++ b/app/scripts/files/templates/file.html @@ -169,39 +169,35 @@

    No Cases Found.

    -
    +

    Workflow

    -
    +

    No Workflow found.

    + data-ng-if="fc.file.analysis"> - - + + - - - - - - + + - + - +
    Workflow ID--Analysis ID{{fc.file.analysis.analysis_id || '--'}}
    Workflow--
    Workflow Version--Workflow Type{{fc.file.analysis.workflow_type | humanify}}
    Workflow Completion Date--{{fc.file.analysis.updated_datetime || '--' | date:'yyyy-MM-dd'}}
    Source Files--
    @@ -209,7 +205,7 @@

    No Workflow found.

    -
    +
    @@ -226,16 +222,12 @@

    No Reference Genome found.

    - Genome ID - -- - - - Genome Build - -- + Genome Build + GRCh38.p0 Genome Name - -- + GDC.hg38.v1 @@ -244,7 +236,7 @@

    No Reference Genome found.

    -
    +
    @@ -253,28 +245,30 @@

    No Reference Genome found.

    Read Groups

    -
    +

    No Read Groups found.

    + data-ng-if="fc.file.analysis.metadata.read_groups"> - + + - - - - - - + + + + + + +
    Read Group ID Is Paired End Read LengthBase Caller Name Library NameSequencing CenterSequencing Date
    ----------
    {{r.read_group_id || '--'}}{{r.is_paired_end | humanify}}{{r.read_length || '--'}}{{r.library_name || '--'}}{{r.sequencing_center | humanify}}{{r.sequencing_date || '--' | date:'yyyy-MM-dd'}}
    @@ -290,7 +284,7 @@

    Metadata Files

    -

    No metadata files found.

    +

    No Metadata Files Found.

    No metadata files found. -
    +
    @@ -340,30 +334,37 @@

    No metadata files found.

    Downstream Analysis Files

    -
    +

    No Downstream Analysis Files Found.

    + data-ng-if="fc.file.downstream_analysis.output_files"> + - - - - - - - + + + + + + + +
    File Name Data Category Data TypeData Format Analysis Workflow File Size Action
    ------------
    {{outf.file_name || '--'}}{{outf.data_category | humanify}}{{outf.data_type | humanify}}{{outf.data_format | humanify}}{{fc.file.downstream_analysis.workflow_type | humanify}}{{outf.file_size | size}} + + + + +
    diff --git a/app/scripts/search/search.participants.table.model.ts b/app/scripts/search/search.participants.table.model.ts index cf859c439..627ee4133 100644 --- a/app/scripts/search/search.participants.table.model.ts +++ b/app/scripts/search/search.participants.table.model.ts @@ -12,6 +12,7 @@ module ngApp.search.models { var val = '{{' + value + '|number:0}}'; return value ? "" + val + '' : '0'; } + function getDataCategory(dataCategories: Object[], dataCategory: string): number { var data = _.find(dataCategories, {data_category: dataCategory}); return data ? data.file_count : 0; From 4123d50aa5db1a2b39ead55bf5dba13deda49efd Mon Sep 17 00:00:00 2001 From: Alex Wilmer Date: Fri, 22 Apr 2016 16:46:05 -0400 Subject: [PATCH 42/80] feat(file): downstream_analyses --- .../templates/add-to-cart-button-single.html | 45 +++++++++++-------- app/scripts/files/files.controllers.ts | 10 ++++- app/scripts/files/module.ts | 14 +++--- app/scripts/files/templates/file.html | 20 ++++----- app/styles/tooltip.less | 4 ++ 5 files changed, 55 insertions(+), 38 deletions(-) diff --git a/app/scripts/cart/templates/add-to-cart-button-single.html b/app/scripts/cart/templates/add-to-cart-button-single.html index 84f4fd235..55a0d6081 100644 --- a/app/scripts/cart/templates/add-to-cart-button-single.html +++ b/app/scripts/cart/templates/add-to-cart-button-single.html @@ -1,19 +1,26 @@ - + + + + diff --git a/app/scripts/files/files.controllers.ts b/app/scripts/files/files.controllers.ts index 028ffdfcb..08b7c9a17 100755 --- a/app/scripts/files/files.controllers.ts +++ b/app/scripts/files/files.controllers.ts @@ -73,6 +73,15 @@ module ngApp.files.controllers { related_file['cases'] = file.cases; }); + if (file.downstream_analyses) { + file.downstream_analyses = file.downstream_analyses.reduce( + (prev, curr) => + prev.concat((curr.output_files || []).map(x => + _.extend({}, x, { workflow_type: curr.workflow_type })) + ), + [] + ); + } } isInCart(): boolean { @@ -162,4 +171,3 @@ module ngApp.files.controllers { .controller("BAMFailedModalController", BAMFailedModalController) .controller("FileController", FileController); } - diff --git a/app/scripts/files/module.ts b/app/scripts/files/module.ts index 7e011f640..835c26c94 100755 --- a/app/scripts/files/module.ts +++ b/app/scripts/files/module.ts @@ -50,13 +50,13 @@ module ngApp.files { "analysis.metadata.read_groups.library_name", "analysis.metadata.read_groups.sequencing_center", "analysis.metadata.read_groups.sequencing_date", - "downstream_analysis.output_files.file_id", - "downstream_analysis.output_files.file_name", - "downstream_analysis.output_files.data_category", - "downstream_analysis.output_files.data_type", - "downstream_analysis.output_files.data_format", - "downstream_analysis.workflow_type", - "downstream_analysis.output_files.file_size", + "downstream_analyses.output_files.file_id", + "downstream_analyses.output_files.file_name", + "downstream_analyses.output_files.data_category", + "downstream_analyses.output_files.data_type", + "downstream_analyses.output_files.data_format", + "downstream_analyses.workflow_type", + "downstream_analyses.output_files.file_size", ] }); } diff --git a/app/scripts/files/templates/file.html b/app/scripts/files/templates/file.html index 87446d979..40a892a44 100755 --- a/app/scripts/files/templates/file.html +++ b/app/scripts/files/templates/file.html @@ -315,7 +315,7 @@

    No Metadata Files Found.

    {{ ::f.data_format || '--' }} {{ ::f.file_size | size }} - + @@ -331,15 +331,15 @@

    No Metadata Files Found.

    -

    Downstream Analysis Files

    +

    Downstream Analyses Files

    -
    -

    No Downstream Analysis Files Found.

    +
    +

    No Downstream Analyses Files Found.

    + data-ng-if="fc.file.downstream_analyses.length"> @@ -352,18 +352,16 @@

    No Downstream Analysis Files Found.

    - + - + diff --git a/app/styles/tooltip.less b/app/styles/tooltip.less index 87e6570c3..244c48eba 100644 --- a/app/styles/tooltip.less +++ b/app/styles/tooltip.less @@ -1,3 +1,7 @@ +.raised-tooltip { + transform: translateY(-25px); +} + .tooltip { font-weight: 300; font-size: 1.3rem; From 15a7de4e5743193fbb81c0aba38be757d819698b Mon Sep 17 00:00:00 2001 From: Alex Wilmer Date: Mon, 25 Apr 2016 15:21:49 -0400 Subject: [PATCH 43/80] feat(file): update genome name to GRCh38.d1.vd1 --- app/scripts/files/templates/file.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/scripts/files/templates/file.html b/app/scripts/files/templates/file.html index 40a892a44..1192dbc52 100755 --- a/app/scripts/files/templates/file.html +++ b/app/scripts/files/templates/file.html @@ -227,7 +227,7 @@

    No Reference Genome found.

    - +
    File Name
    {{outf.file_name || '--'}} {{outf.data_category | humanify}} {{outf.data_type | humanify}} {{outf.data_format | humanify}}{{fc.file.downstream_analysis.workflow_type | humanify}}{{outf.workflow_type | humanify}} {{outf.file_size | size}} - - - - + +
    Genome NameGDC.hg38.v1GRCh38.d1.vd1
    From 05d4462e5b263e78f2828b215bb3b0359e5981be Mon Sep 17 00:00:00 2001 From: Terry Lin Date: Mon, 25 Apr 2016 14:03:17 -0400 Subject: [PATCH 44/80] fix(chore): 2163 null-safety when calling #some Closes #2163 --- app/scripts/components/summary-card/summary-card.controllers.ts | 2 +- app/scripts/components/ui/biospecimen/biospecimen.services.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/scripts/components/summary-card/summary-card.controllers.ts b/app/scripts/components/summary-card/summary-card.controllers.ts index 128f84d83..71b16294a 100644 --- a/app/scripts/components/summary-card/summary-card.controllers.ts +++ b/app/scripts/components/summary-card/summary-card.controllers.ts @@ -32,7 +32,7 @@ module ngApp.components.summaryCard.controllers { var newFilter = JSON.parse(params.filters).content[0]; // there is always just one - filters.content = filters.content.some(filter => _.isEqual(filter, newFilter)) + filters.content = (filters.content || []).some(filter => _.isEqual(filter, newFilter)) ? filters.content : filters.content.concat(newFilter); diff --git a/app/scripts/components/ui/biospecimen/biospecimen.services.ts b/app/scripts/components/ui/biospecimen/biospecimen.services.ts index abd3844b1..1197c430a 100644 --- a/app/scripts/components/ui/biospecimen/biospecimen.services.ts +++ b/app/scripts/components/ui/biospecimen/biospecimen.services.ts @@ -52,7 +52,7 @@ module ngApp.components.ui.biospecimen.services { function search (entity, type, parents, depth) { if (depth === self.hierarchy.length + 1) return; - if (fields.some(f => (entity[f] || '').toLowerCase().indexOf(loweredSearchTerm) > -1)) { + if ((fields || []).some(f => (entity[f] || '').toLowerCase().indexOf(loweredSearchTerm) > -1)) { parents.forEach(p => p.expanded = true); entity.expanded = true; found.push({ entity: entity, type: type }); From 475725b9e74d222a55e502a554a3e57d55e4f4ff Mon Sep 17 00:00:00 2001 From: Christine Yu Date: Wed, 20 Apr 2016 15:46:29 -0400 Subject: [PATCH 45/80] feat(app): 2066 tooltips Closes #2066 --- .../annotations/annotations.table.model.ts | 21 ++++++++++--------- app/scripts/app.ts | 2 +- .../components/facets/facets.directives.ts | 3 ++- .../components/facets/templates/facet.html | 13 +++++++++--- .../facets/templates/facets-section.html | 1 + .../summary-card/summary-card.directives.ts | 4 +++- .../summary-card/templates/summary-card.html | 5 ++++- .../projects/templates/projects.facets.html | 4 +++- .../search/search.participants.table.model.ts | 2 +- app/scripts/search/tests/search.tests.js | 1 + 10 files changed, 37 insertions(+), 19 deletions(-) diff --git a/app/scripts/annotations/annotations.table.model.ts b/app/scripts/annotations/annotations.table.model.ts index f2953c6a0..b290bad94 100644 --- a/app/scripts/annotations/annotations.table.model.ts +++ b/app/scripts/annotations/annotations.table.model.ts @@ -8,14 +8,16 @@ module ngApp.projects.models { id: "annotation_id", td: row => '' + row.annotation_id + '', sortable: true, - tdClassName: 'truncated-cell' + tdClassName: 'truncated-cell', + toolTipText: row => row.annotation_id }, { name: "Case UUID", id: "case_id", td: row => '' + row.case_id + '', sortable: true, - tdClassName: 'truncated-cell' + tdClassName: 'truncated-cell', + toolTipText: row => row.case_id }, { name: "Program", @@ -28,12 +30,9 @@ module ngApp.projects.models { name: "Project", id: "project.project_id", td: row => row.project && '' + - row.project.project_id + - '', - sortable: true + '">' + row.project.project_id + '', + sortable: true, + toolTipText: row => row.project.name }, { name: "Entity Type", @@ -46,7 +45,8 @@ module ngApp.projects.models { id: "entity_id", td: row => row.entity_id, sortable: true, - tdClassName: 'truncated-cell' + tdClassName: 'truncated-cell', + toolTipText: row => row.entity_id }, { name: "Entity Barcode", @@ -100,7 +100,8 @@ module ngApp.projects.models { "case_id", "notes", "project.program.name", - "project.project_id" + "project.project_id", + "project.name", ], facets: [ { diff --git a/app/scripts/app.ts b/app/scripts/app.ts index af421b878..b38182de2 100755 --- a/app/scripts/app.ts +++ b/app/scripts/app.ts @@ -125,7 +125,7 @@ function appRun(gettextCatalog: any, if (navigator.cookieEnabled && $cookies.get("GDC-Portal-Sha") !== config.commitHash) { $cookies.put("GDC-Portal-Sha", config.commitHash); [ "Projects-col", "Annotations-col", "Files-col", "Cases-col", - "Cart-col", "gdc-cart-items", "gdc-cart-updated" + "Cart-col", "gdc-cart-items", "gdc-cart-updated", "gdc-facet-config" ].forEach(item => LocalStorageService.removeItem(item)) } gettextCatalog.debug = true; diff --git a/app/scripts/components/facets/facets.directives.ts b/app/scripts/components/facets/facets.directives.ts index e71d32caa..04bf80aef 100644 --- a/app/scripts/components/facets/facets.directives.ts +++ b/app/scripts/components/facets/facets.directives.ts @@ -18,7 +18,8 @@ module ngApp.components.facets.directives { title: "@", name: "@", removeFunction: "&", - removable: "@" + removable: "@", + showTooltip: "@" }, replace: true, templateUrl: "components/facets/templates/facet.html", diff --git a/app/scripts/components/facets/templates/facet.html b/app/scripts/components/facets/templates/facet.html index afc7b272e..a580254fa 100644 --- a/app/scripts/components/facets/templates/facet.html +++ b/app/scripts/components/facets/templates/facet.html @@ -51,10 +51,17 @@ class="facet-term-label"> {{ ::term.key.toUpperCase() }} - + data-tooltip-placement="right"> + {{ ::term.key.toUpperCase() }} + + + {{ ::term.key | translate | humanify: true:true }} + + {{ ::term.key | translate | humanify: true:true }} diff --git a/app/scripts/components/facets/templates/facets-section.html b/app/scripts/components/facets/templates/facets-section.html index 6d38dd1d4..50caad203 100644 --- a/app/scripts/components/facets/templates/facets-section.html +++ b/app/scripts/components/facets/templates/facets-section.html @@ -17,6 +17,7 @@ data-facet="aggregations[f.name]" data-collapsed="{{ f.collapsed }}" data-removable="{{ f.removable }}" + data-show-tooltip="{{ f.showTooltip }}" data-remove-function="removeFacet(f.name)">
    - {{ item[config.displayKey] | humanify }} + + {{ item[config.displayKey] | humanify }} + diff --git a/app/scripts/projects/templates/projects.facets.html b/app/scripts/projects/templates/projects.facets.html index c3502b37b..74db0e8a5 100644 --- a/app/scripts/projects/templates/projects.facets.html +++ b/app/scripts/projects/templates/projects.facets.html @@ -5,7 +5,9 @@ data-facet="prsc.projects.aggregations.primary_site" data-title="Primary Site"> - diff --git a/app/scripts/search/search.participants.table.model.ts b/app/scripts/search/search.participants.table.model.ts index 627ee4133..e9e8260b3 100644 --- a/app/scripts/search/search.participants.table.model.ts +++ b/app/scripts/search/search.participants.table.model.ts @@ -248,7 +248,7 @@ module ngApp.search.models { {name: "project.primary_site", title: "Primary Site", collapsed: false, facetType: "terms"}, {name: "project.program.name", title: "Cancer Program", collapsed: false, facetType: "terms"}, {name: "project.project_id", title: "Project", collapsed: false, facetType: "terms"}, - {name: "project.disease_type", title: "Disease Type", collapsed: false, facetType: "terms"}, + {name: "project.disease_type", title: "Disease Type", collapsed: false, facetType: "terms", showTooltip: true}, {name: "demographic.gender", title: "Gender", collapsed: false, facetType: "terms"}, {name: "diagnoses.age_at_diagnosis", title: "Age at diagnosis", collapsed: false, facetType: "range", unitsMap: [ { diff --git a/app/scripts/search/tests/search.tests.js b/app/scripts/search/tests/search.tests.js index d07901d52..986f7322f 100755 --- a/app/scripts/search/tests/search.tests.js +++ b/app/scripts/search/tests/search.tests.js @@ -9,6 +9,7 @@ describe('Search:', function () { beforeEach(module(function ($provide) { $provide.value('AuthRestangular', {}); + $provide.value('ProjectsService', {}); $provide.value('config', {}); })); From 0d3a02051a85739a21007264ff959743a6901076 Mon Sep 17 00:00:00 2001 From: Alex Wilmer Date: Mon, 25 Apr 2016 16:29:25 -0400 Subject: [PATCH 46/80] fix(reports): 2173 remove export btn Closes #2173 --- app/scripts/reports/templates/reports.html | 8 -------- 1 file changed, 8 deletions(-) diff --git a/app/scripts/reports/templates/reports.html b/app/scripts/reports/templates/reports.html index d6520ff54..46928acdf 100755 --- a/app/scripts/reports/templates/reports.html +++ b/app/scripts/reports/templates/reports.html @@ -15,14 +15,6 @@

    includes information about the total number and size of downloaded files categorized at project, data and user access levels.

    - -

    - - -

    Project

    From 45ffbbfb8ceff816799cdc7f249565df14650764 Mon Sep 17 00:00:00 2001 From: Shane Wilson Date: Tue, 26 Apr 2016 10:15:40 -0400 Subject: [PATCH 47/80] fix(search): fix pagination not updating - We had an optimization that only updated the hits when they actually changed to reduce extra ajax request/processing but forgot exclude the pagination data. So anytime the first page of results didnt change the pagination data would update either. Closes #2185 --- app/scripts/query/query.controllers.ts | 8 +++++--- app/scripts/search/search.controllers.ts | 8 +++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/app/scripts/query/query.controllers.ts b/app/scripts/query/query.controllers.ts index 71bb0b6d6..6b4bca716 100755 --- a/app/scripts/query/query.controllers.ts +++ b/app/scripts/query/query.controllers.ts @@ -111,9 +111,10 @@ module ngApp.query.controllers { this.filesLoading = false; this.files = this.files || {}; this.files.aggregations = data.aggregations; + this.files.pagination = data.pagination; if (!_.isEqual(this.files.hits, data.hits)) { - this.files = data; + this.files.hits = data.hits; this.tabSwitch = false; if (this.QState.tabs.files.active) { this.QState.setActive("files", "hasLoadedOnce"); @@ -129,9 +130,10 @@ module ngApp.query.controllers { this.participantsLoading = false; this.participants = this.participants || {}; this.participants.aggregations = data.aggregations; - + this.participants.pagination = data.pagination + if (!_.isEqual(this.participants.hits, data.hits)) { - this.participants = data; + this.participants.hits = data.hits; this.tabSwitch = false; if (this.QState.tabs.participants.active) { this.QState.setActive("participants", "hasLoadedOnce"); diff --git a/app/scripts/search/search.controllers.ts b/app/scripts/search/search.controllers.ts index e5e16f619..bd1ee1f69 100755 --- a/app/scripts/search/search.controllers.ts +++ b/app/scripts/search/search.controllers.ts @@ -143,9 +143,10 @@ module ngApp.search.controllers { this.filesLoading = false; this.files = this.files || {}; this.files.aggregations = data.aggregations; + this.files.pagination = data.pagination; if (!_.isEqual(this.files.hits, data.hits)) { - this.files = data; + this.files.hits = data.hits; this.tabSwitch = false; if (this.SearchState.tabs.files.active) { this.SearchState.setActive("tabs", "files", "hasLoadedOnce"); @@ -161,9 +162,10 @@ module ngApp.search.controllers { this.participantsLoading = false; this.participants = this.participants || {}; this.participants.aggregations = data.aggregations; - + this.participants.pagination = data.pagination; + if (!_.isEqual(this.participants.hits, data.hits)) { - this.participants = data; + this.participants.hits = data.hits; this.tabSwitch = false; if (this.SearchState.tabs.participants.active) { this.SearchState.setActive("tabs", "participants", "hasLoadedOnce"); From 58ca6f7cf8d5c582e5a2041f8ff6db057666a500 Mon Sep 17 00:00:00 2001 From: Alex Wilmer Date: Fri, 22 Apr 2016 14:33:24 -0400 Subject: [PATCH 48/80] feat(app): 1755 title case for data category - add constant for data categories - turn table models into services Closes #1755 --- .../components/facets/facets.controllers.ts | 2 +- .../components/facets/facets.services.ts | 6 +- app/scripts/core/module.ts | 10 +- app/scripts/home/home.controllers.ts | 4 +- app/scripts/projects/projects.controller.ts | 11 +- app/scripts/projects/projects.table.model.ts | 276 ------------------ .../projects/projects.table.service.ts | 247 ++++++++++++++++ app/scripts/query/query.controllers.ts | 10 +- .../search/search.cases.table.service.ts | 247 ++++++++++++++++ app/scripts/search/search.controllers.ts | 14 +- .../search/search.participants.table.model.ts | 271 ----------------- app/scripts/search/templates/search.html | 2 +- 12 files changed, 531 insertions(+), 569 deletions(-) delete mode 100644 app/scripts/projects/projects.table.model.ts create mode 100644 app/scripts/projects/projects.table.service.ts create mode 100644 app/scripts/search/search.cases.table.service.ts delete mode 100644 app/scripts/search/search.participants.table.model.ts diff --git a/app/scripts/components/facets/facets.controllers.ts b/app/scripts/components/facets/facets.controllers.ts index 721b3468b..8df7965f1 100644 --- a/app/scripts/components/facets/facets.controllers.ts +++ b/app/scripts/components/facets/facets.controllers.ts @@ -495,7 +495,7 @@ module ngApp.components.facets.controllers { _this.setSelectedIndex(Cycle.Down); break; case KeyCode.Esc: - _this.$uibModalStack.dismissAll(); + if (_this.$uibModalStack) _this.$uibModalStack.dismissAll(); break; case KeyCode.Tab: e.preventDefault(); diff --git a/app/scripts/components/facets/facets.services.ts b/app/scripts/components/facets/facets.services.ts index 031f17c1a..6a1a5c74c 100644 --- a/app/scripts/components/facets/facets.services.ts +++ b/app/scripts/components/facets/facets.services.ts @@ -221,7 +221,7 @@ module ngApp.components.facets.services { /* @ngInject */ constructor(private Restangular: restangular.IService, private SearchTableFilesModel: TableiciousConfig, - private SearchTableParticipantsModel: TableiciousConfig, + private SearchCasesTableService: TableiciousConfig, private FacetsConfigService: IFacetsConfigService) { this.ds = Restangular.all("gql/_mapping"); } @@ -234,7 +234,9 @@ module ngApp.components.facets.services { datum.field !== 'archive.revision' && !_.includes(datum.field, "_id") && !_.includes(current, datum.field) && - !_.includes(docType === 'files' ? _.pluck(this.SearchTableFilesModel.facets, "name") : _.pluck(this.SearchTableParticipantsModel.facets, "name"), datum.field); + !_.includes(docType === 'files' + ? _.pluck(this.SearchTableFilesModel.facets, "name") + : _.pluck(this.SearchCasesTableService.model().facets, "name"), datum.field); }), f => f); }); } diff --git a/app/scripts/core/module.ts b/app/scripts/core/module.ts index 3cb633ffc..b08296a37 100644 --- a/app/scripts/core/module.ts +++ b/app/scripts/core/module.ts @@ -7,4 +7,12 @@ angular "core.directives", "core.services", "core.filters" - ]); + ]) + .constant('DATA_CATEGORIES', { + SEQ: { full: "Raw Sequencing Data", abbr: "Seq" }, + EXP: { full: "Gene Expression", abbr: "Exp" }, + SNV: { full: "Simple Nucleotide Variation", abbr: "SNV" }, + CNV: { full: "Copy Number Variation", abbr: "CNV" }, + CLINICAL: { full: "Clinical", abbr: "Clinical" }, + BIOSPECIMEN: { full: "Biospecimen", abbr: "Biospecimen" }, + }); diff --git a/app/scripts/home/home.controllers.ts b/app/scripts/home/home.controllers.ts index bf6472f11..9e587f2ae 100755 --- a/app/scripts/home/home.controllers.ts +++ b/app/scripts/home/home.controllers.ts @@ -27,7 +27,7 @@ module ngApp.home.controllers { defaultParams: any; /* @ngInject */ - constructor(private HomeService: IHomeService, private ProjectTableModel: TableiciousConfig, + constructor(private HomeService: IHomeService, private ProjectsTableService: TableiciousConfig, private CoreService: ICoreService, private $filter: ng.ui.IFilterService) { CoreService.setPageTitle("Welcome to The Genomics Data Commons Data Portal"); @@ -90,7 +90,7 @@ module ngApp.home.controllers { ]; this.defaultParams = { - fields: this.ProjectTableModel.fields, + fields: this.ProjectsTableService.model().fields, facets: [ "disease_type", "program.name", diff --git a/app/scripts/projects/projects.controller.ts b/app/scripts/projects/projects.controller.ts index 52f256d11..417480360 100644 --- a/app/scripts/projects/projects.controller.ts +++ b/app/scripts/projects/projects.controller.ts @@ -30,7 +30,7 @@ module ngApp.projects.controllers { /* @ngInject */ constructor(private $scope: IProjectScope, private ProjectsService: IProjectsService, - private CoreService: ICoreService, private ProjectTableModel: TableiciousConfig, + private CoreService: ICoreService, private ProjectsTableService: TableiciousConfig, private $state: ng.ui.IStateService, public ProjectsState: IProjectsState, private LocationService: ILocationService, private $filter, private ProjectsGithutConfig, private ProjectsGithutColumns, private ProjectsGithut, private FacetService: IFacetService @@ -52,17 +52,18 @@ module ngApp.projects.controllers { var data = $state.current.data || {}; this.ProjectsState.setActive("tabs", data.tab); - $scope.tableConfig = ProjectTableModel; + $scope.tableConfig = this.ProjectsTableService.model(); this.refresh(); } refresh() { this.loading = true; + var projectsTableModel = this.ProjectsTableService.model(); if (!this.tabSwitch) { this.ProjectsService.getProjects({ - fields: this.ProjectTableModel.fields, - facets: this.FacetService.filterFacets(this.ProjectTableModel.facets), + fields: projectsTableModel.fields, + facets: this.FacetService.filterFacets(projectsTableModel.facets), size: 100 }).then((data) => { this.loading = false; @@ -280,7 +281,7 @@ module ngApp.projects.controllers { .module("projects.controller", [ "projects.services", "core.services", - "projects.table.model", + "projects.table.service", "projects.githut.config", "annotations.services" ]) diff --git a/app/scripts/projects/projects.table.model.ts b/app/scripts/projects/projects.table.model.ts deleted file mode 100644 index 889e654c7..000000000 --- a/app/scripts/projects/projects.table.model.ts +++ /dev/null @@ -1,276 +0,0 @@ -module ngApp.projects.models { - import ILocationService = ngApp.components.location.ILocationService; - - type IWithFilterFn = (value: number, filters: Object[], $filter: ng.IFilterService) => string; - - type DataCategory = { - case_count: number - } - - type Summary = { - data_categories: DataCategory[] - } - - type Row = { - project_id: string; - summary: Summary; - } - - type Rows = Row[]; - - function filterFactory(url: string) : IWithFilterFn { - return function(value: number, filters: Object[], $filter: ng.IFilterService) { - var filterString = _.isObject(filters) ? $filter("makeFilter")(filters, true) : null; - var href = url + (filterString ? "?filters=" + filterString : ""); - var val = $filter("number")(value); - return value ? "" + val + '' : '0'; - }; - } - - var withFilterF : IWithFilterFn = filterFactory("search/f"), - withFilter : IWithFilterFn = filterFactory("search/c"); - - function getdataCategory(dataCategories: DataCategory[], dataCategory:string): number { - var data = _.find(dataCategories, {data_category: dataCategory}); - return data ? data.case_count : 0; - } - - function dataCategoryWithFilters(dataCategory: string, row: Row, $filter: ng.IFilterService): string { - var fs = [{field: 'cases.project.project_id', value: row.project_id}, - {field: 'files.data_category', value: dataCategory}]; - return withFilter(getdataCategory(row.summary.data_categories, dataCategory), fs, $filter); - } - - function dataCategoryTotalWithFilters(dataCategory: string, data: Rows, $filter: ng.IFilterService): string { - var fs = [{field: 'files.data_category', value: [dataCategory]}, - {field: 'cases.project.project_id', value: data.map(d => d.project_id)}]; - return withFilter(_.sum(_.map(data, row => getdataCategory(row.summary.data_categories, dataCategory))), fs, $filter); - } - - function withCurrentFilters(value: number, $filter: ng.IFilterService, LocationService: ILocationService) { - var fs = _.map(LocationService.filters().content, x => ({ - field: x.content.field.indexOf("summary") === 0 ? "files." + x.content.field.split(".")[2] : "cases.project." + x.content.field, - value: x.content.value - })); - return withFilter(value, fs, $filter); - } - - function hasFilters(LocationService: ILocationService) : boolean { - var filters = _.get(LocationService.filters(), 'content', null), - hasFiltersFlag = false; - - if (! filters) { - return hasFiltersFlag; - } - - for (var i = 0; i < filters.length; i++) { - var field = _.get(filters[i], 'content.field', false); - - if (! field) { - continue; - } - - hasFiltersFlag = true; - break; - } - - return hasFiltersFlag; - } - - function withProjectFilters(data: Object[], $filter: ng.IFilterService, LocationService: ILocationService, withFilterFn?: IWithFilterFn) : string { - - var projectIDs = [], - totalCount = 0, - wFilterFn : IWithFilterFn = withFilterFn || withFilter, - fs = []; - - _.map(data, function(d) { - - - if (! _.has(d, 'project_id')) { - return; - } - - projectIDs.push(d.project_id); - - var countKey = 'summary.case_count'; - - if ( withFilterFn !== withFilter ) { - countKey = 'summary.file_count'; - } - - totalCount += _.get(d, countKey, 0); - - }); - - if (hasFilters(LocationService) && projectIDs.length) { - fs.push({field: 'cases.project.project_id', value: projectIDs}); - } - - return wFilterFn(totalCount, fs, $filter); - } - - var projectTableModel = { - title: 'Projects', - rowId: 'project_id', - headings: [ - { - name: "ID", - id: "project_id", - td: row => '' + - row.project_id + - '', - sortable: true, - hidden: false, - draggable: true, - total: data => 'Total', - colSpan: 4 - }, { - name: "Disease Type", - id: "disease_type", - tdClassName: 'truncated-cell', - td: row => row.disease_type, - toolTipText: row => row.disease_type, - sortable: true, - hidden: false, - draggable: true - }, { - name: "Primary Site", - id: "primary_site", - tdClassName: 'truncated-cell', - td: row => row.primary_site, - sortable: true, - hidden: false, - canReorder: true, - enabled: true - }, { - name: "Program", - id: "program.name", - td: row => row.program && row.program.name, - sortable: true, - hidden: false - }, { - name: "Cases", - id: "summary.case_count", - td: (row, $scope) => { - var fs = [{field: 'cases.project.project_id', value: row.project_id}] - return withFilter(row.summary.case_count, fs, $scope.$filter); - }, - sortable: true, - hidden: false, - thClassName: 'text-right', - tdClassName: 'text-right', - total: (data, $scope) => withProjectFilters(data, $scope.$filter, $scope.LocationService, withFilter) - }, { - name: "Available Cases per Data Category", - id: "summary.data_categories", - thClassName: 'text-center', - hidden: false, - children: [ - { - name: 'Seq', - th: 'Seq', - id: 'Seq', - td: (row, $scope) => dataCategoryWithFilters("Raw sequencing data", row, $scope.$filter), - thClassName: 'text-right', - tdClassName: 'text-right', - total: (data, $scope) => dataCategoryTotalWithFilters("Raw sequencing data", data, $scope.$filter) - }, { - name: 'Exp', - th: 'Exp', - id: 'Exp', - td: (row, $scope) => dataCategoryWithFilters("Gene expression", row, $scope.$filter), - thClassName: 'text-right', - tdClassName: 'text-right', - total: (data, $scope) => dataCategoryTotalWithFilters("Gene expression", data, $scope.$filter) - }, { - name: 'SNV', - th: 'SNV', - id: 'SNV', - td: (row, $scope) => dataCategoryWithFilters("Simple nucleotide variation", row, $scope.$filter), - thClassName: 'text-right', - tdClassName: 'text-right', - total: (data, $scope) => dataCategoryTotalWithFilters("Simple nucleotide variation", data, $scope.$filter) - }, { - name: 'CNV', - th: 'CNV', - id: 'CNV', - td: (row, $scope) => dataCategoryWithFilters("Copy number variation", row, $scope.$filter), - thClassName: 'text-right', - tdClassName: 'text-right', - total: (data, $scope) => dataCategoryTotalWithFilters("Copy number variation", data, $scope.$filter) - },{ - name: 'Clinical', - id: 'clinical', - td: (row, $scope) => dataCategoryWithFilters("Clinical", row, $scope.$filter), - thClassName: 'text-right', - tdClassName: 'text-right', - total: (data, $scope) => dataCategoryTotalWithFilters('Clinical', data, $scope.$filter) - }, { - name: 'Biospecimen', - id: 'biospecimen', - td: (row, $scope) => dataCategoryWithFilters("Biospecimen", row, $scope.$filter), - thClassName: 'text-right', - tdClassName: 'text-right', - total: (data, $scope) => dataCategoryTotalWithFilters('Biospecimen', data, $scope.$filter) - } - ] - }, { - name: "Files", - id: "summary.file_count", - td: (row, $scope) => { - var fs = [{field: 'cases.project.project_id', value: row.project_id}] - return withFilterF(row.summary.file_count, fs, $scope.$filter); - }, - sortable: true, - thClassName: 'text-right', - tdClassName: 'text-right', - total: (data, $scope) => withProjectFilters(data, $scope.$filter, $scope.LocationService, withFilterF) - }, { - name: "File Size", - id: "file_size", - td: (row, $scope) => row.summary && $scope.$filter("size")(row.summary.file_size), - sortable: true, - thClassName: 'text-right', - tdClassName: 'text-right', - total: (data, $scope) => $scope.$filter("size")(_.sum(_.pluck(data, "summary.file_size"))) - } - ], - fields: [ - "disease_type", - "state", - "primary_site", - "project_id", - "name", - "program.name", - "summary.case_count", - "summary.file_count", - "summary.data_categories.data_category", - "summary.data_categories.case_count", - ], - facets: [ - { - name: 'project_id', - facetType: 'free-text' - }, { - name: 'disease_type', - facetType: 'terms' - }, { - name: 'program.name', - facetType: 'terms' - }, { - name: 'primary_site', - facetType: 'terms' - }, { - name: 'summary.experimental_strategies.experimental_strategy', - facetType: 'terms' - }, { - name: 'summary.data_categories.data_category', - facetType: 'terms' - }] - }; - angular.module("projects.table.model", []) - .value("ProjectTableModel", projectTableModel); -} diff --git a/app/scripts/projects/projects.table.service.ts b/app/scripts/projects/projects.table.service.ts new file mode 100644 index 000000000..dbcbe251e --- /dev/null +++ b/app/scripts/projects/projects.table.service.ts @@ -0,0 +1,247 @@ +module ngApp.projects.table.service { + import ILocationService = ngApp.components.location.ILocationService; + + type IWithFilterFn = (value: number, filters: Object[], $filter: ng.IFilterService) => string; + + type DataCategory = { + case_count: number + } + + type Summary = { + data_categories: DataCategory[] + } + + type Row = { + project_id: string; + summary: Summary; + } + + type Rows = Row[]; + + class ProjectsTableService { + + /* @ngInject */ + constructor(private DATA_CATEGORIES) {} + + filterFactory(url: string) : IWithFilterFn { + return function(value: number, filters: Object[], $filter: ng.IFilterService) { + var filterString = _.isObject(filters) ? $filter("makeFilter")(filters, true) : null; + var href = url + (filterString ? "?filters=" + filterString : ""); + var val = $filter("number")(value); + return value ? "" + val + '' : '0'; + }; + } + + withFilterF : IWithFilterFn = this.filterFactory("search/f"); + withFilter : IWithFilterFn = this.filterFactory("search/c"); + + getdataCategory(dataCategories: DataCategory[], dataCategory:string): number { + var data = _.find(dataCategories, {data_category: dataCategory}); + return data ? data.case_count : 0; + } + + dataCategoryWithFilters(dataCategory: string, row: Row, $filter: ng.IFilterService): string { + var fs = [{field: 'cases.project.project_id', value: row.project_id}, + {field: 'files.data_category', value: dataCategory}]; + return this.withFilter(this.getdataCategory(row.summary.data_categories, dataCategory), fs, $filter); + } + + dataCategoryTotalWithFilters(dataCategory: string, data: Rows, $filter: ng.IFilterService): string { + var fs = [{field: 'files.data_category', value: [dataCategory]}, + {field: 'cases.project.project_id', value: data.map(d => d.project_id)}]; + return this.withFilter(_.sum(_.map(data, row => this.getdataCategory(row.summary.data_categories, dataCategory))), fs, $filter); + } + + withCurrentFilters(value: number, $filter: ng.IFilterService, LocationService: ILocationService) { + var fs = _.map(LocationService.filters().content, x => ({ + field: x.content.field.indexOf("summary") === 0 ? "files." + x.content.field.split(".")[2] : "cases.project." + x.content.field, + value: x.content.value + })); + return this.withFilter(value, fs, $filter); + } + + hasFilters(LocationService: ILocationService) : boolean { + var filters = _.get(LocationService.filters(), 'content', null), + hasFiltersFlag = false; + + if (! filters) { + return hasFiltersFlag; + } + + for (var i = 0; i < filters.length; i++) { + var field = _.get(filters[i], 'content.field', false); + + if (! field) { + continue; + } + + hasFiltersFlag = true; + break; + } + + return hasFiltersFlag; + } + + withProjectFilters(data: Object[], $filter: ng.IFilterService, LocationService: ILocationService, withFilterFn?: IWithFilterFn) : string { + + var projectIDs = [], + totalCount = 0, + wFilterFn : IWithFilterFn = withFilterFn || this.withFilter, + fs = []; + + _.map(data, function(d) { + + + if (! _.has(d, 'project_id')) { + return; + } + + projectIDs.push(d.project_id); + + var countKey = 'summary.case_count'; + + if ( withFilterFn !== this.withFilter ) { + countKey = 'summary.file_count'; + } + + totalCount += _.get(d, countKey, 0); + + }); + + if (this.hasFilters(LocationService) && projectIDs.length) { + fs.push({field: 'cases.project.project_id', value: projectIDs}); + } + + return wFilterFn(totalCount, fs, $filter); + } + + model() { + return { + title: 'Projects', + rowId: 'project_id', + headings: [ + { + name: "ID", + id: "project_id", + td: row => '' + + row.project_id + + '', + sortable: true, + hidden: false, + draggable: true, + total: data => 'Total', + colSpan: 4 + }, { + name: "Disease Type", + id: "disease_type", + tdClassName: 'truncated-cell', + td: row => row.disease_type, + toolTipText: row => row.disease_type, + sortable: true, + hidden: false, + draggable: true + }, { + name: "Primary Site", + id: "primary_site", + tdClassName: 'truncated-cell', + td: row => row.primary_site, + sortable: true, + hidden: false, + canReorder: true, + enabled: true + }, { + name: "Program", + id: "program.name", + td: row => row.program && row.program.name, + sortable: true, + hidden: false + }, { + name: "Cases", + id: "summary.case_count", + td: (row, $scope) => { + var fs = [{field: 'cases.project.project_id', value: row.project_id}] + return this.withFilter(row.summary.case_count, fs, $scope.$filter); + }, + sortable: true, + hidden: false, + thClassName: 'text-right', + tdClassName: 'text-right', + total: (data, $scope) => this.withProjectFilters(data, $scope.$filter, $scope.LocationService, this.withFilter) + }, { + name: "Available Cases per Data Category", + id: "summary.data_categories", + thClassName: 'text-center', + hidden: false, + children: Object.keys(this.DATA_CATEGORIES).map(key => ({ + name: this.DATA_CATEGORIES[key].abbr, + th: + '' + + this.DATA_CATEGORIES[key].abbr + '', + id: this.DATA_CATEGORIES[key].abbr, + td: (row, $scope) => this.dataCategoryWithFilters(this.DATA_CATEGORIES[key].full, row, $scope.$filter), + thClassName: 'text-right', + tdClassName: 'text-right', + total: (data, $scope) => this.dataCategoryTotalWithFilters(this.DATA_CATEGORIES[key].full, data, $scope.$filter) + })) + }, { + name: "Files", + id: "summary.file_count", + td: (row, $scope) => { + var fs = [{field: 'cases.project.project_id', value: row.project_id}] + return this.withFilterF(row.summary.file_count, fs, $scope.$filter); + }, + sortable: true, + thClassName: 'text-right', + tdClassName: 'text-right', + total: (data, $scope) => this.withProjectFilters(data, $scope.$filter, $scope.LocationService, this.withFilterF) + }, { + name: "File Size", + id: "file_size", + td: (row, $scope) => row.summary && $scope.$filter("size")(row.summary.file_size), + sortable: true, + thClassName: 'text-right', + tdClassName: 'text-right', + total: (data, $scope) => $scope.$filter("size")(_.sum(_.pluck(data, "summary.file_size"))) + } + ], + fields: [ + "disease_type", + "state", + "primary_site", + "project_id", + "name", + "program.name", + "summary.case_count", + "summary.file_count", + "summary.data_categories.data_category", + "summary.data_categories.case_count", + ], + facets: [ + { + name: 'project_id', + facetType: 'free-text' + }, { + name: 'disease_type', + facetType: 'terms' + }, { + name: 'program.name', + facetType: 'terms' + }, { + name: 'primary_site', + facetType: 'terms' + }, { + name: 'summary.experimental_strategies.experimental_strategy', + facetType: 'terms' + }, { + name: 'summary.data_categories.data_category', + facetType: 'terms' + }] + }; + } + } + + angular.module("projects.table.service", []) + .service("ProjectsTableService", ProjectsTableService); +} diff --git a/app/scripts/query/query.controllers.ts b/app/scripts/query/query.controllers.ts index 6b4bca716..60d802534 100755 --- a/app/scripts/query/query.controllers.ts +++ b/app/scripts/query/query.controllers.ts @@ -57,7 +57,7 @@ module ngApp.query.controllers { private UserService: IUserService, private CoreService: ICoreService, private SearchTableFilesModel: TableiciousConfig, - private SearchTableParticipantsModel: TableiciousConfig, + private SearchCasesTableService: TableiciousConfig, SearchChartConfigs) { var data = $state.current.data || {}; this.QState.setActive(data.tab, "active"); @@ -73,7 +73,7 @@ module ngApp.query.controllers { }); $scope.fileTableConfig = this.SearchTableFilesModel; - $scope.participantTableConfig = this.SearchTableParticipantsModel; + $scope.participantTableConfig = this.SearchCasesTableService.model(); this.refresh(); this.chartConfigs = SearchChartConfigs; @@ -99,12 +99,14 @@ module ngApp.query.controllers { this.summary = data; }); + var casesTableModel = this.SearchCasesTableService.model(); + var fileOptions = { fields: this.SearchTableFilesModel.fields }; var participantOptions = { - fields: this.SearchTableParticipantsModel.fields, + fields: casesTableModel.fields, }; this.FilesService.getFiles(fileOptions).then((data: IFiles) => { @@ -190,7 +192,7 @@ module ngApp.query.controllers { "core.services", "participants.services", "search.table.files.model", - 'search.table.participants.model', + "search.cases.table.service", "files.services" ]) .controller("QueryController", QueryController); diff --git a/app/scripts/search/search.cases.table.service.ts b/app/scripts/search/search.cases.table.service.ts new file mode 100644 index 000000000..768267cc2 --- /dev/null +++ b/app/scripts/search/search.cases.table.service.ts @@ -0,0 +1,247 @@ +module ngApp.search.cases.table.service { + + class SearchCasesTableService { + + /* @ngInject */ + constructor(private DATA_CATEGORIES) {} + + withAnnotationFilter(value: number, filters: Object[], $filter: ng.IFilterService): string { + var filterString = $filter("makeFilter")(filters, true); + var href = 'annotations?filters=' + filterString; + var val = '{{' + value + '|number:0}}'; + return "" + val + ''; + } + + withFilter(value: number, filters: Object[], $filter: ng.IFilterService): string { + var filterString = $filter("makeFilter")(filters, true); + var href = 'search/f?filters=' + filterString; + var val = '{{' + value + '|number:0}}'; + return value ? "" + val + '' : '0'; + } + + getDataCategory(dataCategories: Object[], dataCategory: string): number { + var data = _.find(dataCategories, {data_category: dataCategory}); + return data ? data.file_count : 0; + } + + dataCategoryWithFilters(dataCategory: string, row: Object[], $filter: ng.IFilterService) { + var fs = [ + {field: 'cases.case_id', value: row.case_id}, + {field: 'files.data_category', value: dataCategory} + ]; + return this.withFilter(this.getDataCategory(row.summary ? row.summary.data_categories : [], dataCategory), fs, $filter); + } + + youngestDiagnosis(p: { age_at_diagnosis: number }, c: { age_at_diagnosis: number }): { age_at_diagnosis: number } { + return c.age_at_diagnosis < p.age_at_diagnosis ? c : p + } + + model() { + return { + title: 'Cases', + rowId: 'case_id', + headings: [{ + name: "Cart", + id: "add_to_cart_filtered", + td: row => '', + tdClassName: 'text-center' + }, { + name: "My Projects", + id: "my_projects", + td: (row, $scope) => { + var fakeFile = {cases: [{project: row.project}]}; + var isUserProject = $scope.UserService.isUserProject(fakeFile); + var icon = isUserProject ? 'check' : 'remove'; + return ''; + }, + inactive: $scope => !$scope.UserService.currentUser || $scope.UserService.currentUser.isFiltered, + hidden: false, + tdClassName: "text-center" + }, { + name: "Case UUID", + id: "case_id", + toolTipText: row => row.case_id, + td: row => '' + row.case_id + '', + tdClassName: 'truncated-cell' + }, { + name: "Project", + id: "project.project_id", + toolTipText: row => row.project.name, + td: row => '' + row.project.project_id + '', + sortable: true, + }, { + name: "Primary Site", + id: "project.primary_site", + td: row => row.project && row.project.primary_site, + sortable: true + }, { + name: "Gender", + id: "demographic.gender", + td: (row, $scope) => row.demographic && $scope.$filter("humanify")(row.demographic.gender) || '--', + sortable: true + }, { + name: "Files", + id: "files", + td: (row, $scope) => { + var fs = [{field: 'cases.case_id', value: row.case_id}] + var sum = _.sum(_.pluck(row.summary ? row.summary.data_categories : [], 'file_count')) + return this.withFilter(sum, fs, $scope.$filter); + }, + thClassName: 'text-right', + tdClassName: 'text-right' + }, { + name: "Available Files per Data Category", + id: "summary.data_categories", + thClassName:'text-center', + children: Object.keys(this.DATA_CATEGORIES).map(key => ({ + name: this.DATA_CATEGORIES[key].abbr, + th: '' + + this.DATA_CATEGORIES[key].abbr + '', + id: this.DATA_CATEGORIES[key].abbr, + td: (row, $scope) => this.dataCategoryWithFilters(this.DATA_CATEGORIES[key].full, row, $scope.$filter), + thClassName: 'text-right', + tdClassName: 'text-right' + })) + }, { + name: "Annotations", + id: "annotations.annotation_id", + td: (row, $scope) => { + function getAnnotations(row, $filter) { + return row.annotations.length == 1 ? + '' + 1 + '' : + this.withAnnotationFilter( + row.annotations.length, + [{field: "annotation_id", value: _.pluck(row.annotations, 'annotation_id')}], + $filter); + } + + return row.annotations && row.annotations.length ? getAnnotations(row, $scope.$filter) : 0; + }, + thClassName: 'text-right', + tdClassName: 'text-right' + }, { + name: 'Program', + id: 'project.program.name', + td: (row, $scope) => row.project && $scope.$filter("humanify")(row.project.program.name), + sortable: false, + hidden: true + }, { + name: 'Disease Type', + id: 'project.disease_type', + td: (row, $scope) => row.project && $scope.$filter("humanify")(row.project.disease_type), + sortable: false, + hidden: true + }, { + name: 'Age at diagnosis', + id: 'diagnoses.age_at_diagnosis', + td: (row, $scope) => { + // Use diagnosis with minimum age + const age = (row.diagnoses || []).reduce((p, c) => c.age_at_diagnosis < p ? c.age_at_diagnosis : p, Infinity); + return age !== Infinity && row.diagnoses ? $scope.$filter("ageDisplay")(age) : "--"; + }, + sortable: false, + hidden: true + }, { + name: 'Days to death', + id: 'diagnoses.days_to_death', + td: (row, $scope) => { + const primaryDiagnosis = (row.diagnoses || []) + .reduce(this.youngestDiagnosis, { age_at_diagnosis: Infinity }); + return (row.diagnoses && $scope.$filter("number")(primaryDiagnosis.days_to_death, 0)) || "--" + }, + sortable: false, + hidden: true + }, { + name: 'Vital Status', + id: 'diagnoses.vital_status', + td: (row, $scope) => { + const primaryDiagnosis = (row.diagnoses || []) + .reduce(this.youngestDiagnosis, { age_at_diagnosis: Infinity }); + return row.diagnoses && $scope.$filter("humanify")(primaryDiagnosis.vital_status) + }, + sortable: false, + hidden: true + }, { + name: 'Year of diagnosis', + id: 'diagnoses.year_of_diagnosis', + td: (row, $scope) => { + const primaryDiagnosis = (row.diagnoses || []) + .reduce(this.youngestDiagnosis, { age_at_diagnosis: Infinity }); + return (row.diagnoses && primaryDiagnosis.year_of_diagnosis) || "--" + }, + sortable: false, + hidden: true + }, { + name: 'ICD-10', + id: 'icd_10', + td: (row, $scope) => (row.clinical && row.clinical.icd_10) || "--", + sortable: false, + hidden: true + }, { + name: 'Ethnicity', + id: 'demographic.ethnicity', + td: (row, $scope) => row.demographic && $scope.$filter("humanify")(row.demographic.ethnicity), + sortable: false, + hidden: true + }, { + name: 'Race', + id: 'demographic.race', + td: (row, $scope) => row.demographic && $scope.$filter("humanify")(row.demographic.race), + sortable: false, + hidden: true + }, { + name: 'Submitter ID', + id: 'submitter_id', + td: (row, $scope) => row.submitter_id, + sortable: false, + hidden: true + }], + fields: [ + "case_id", + "annotations.annotation_id", + "project.project_id", + "project.name", + "project.primary_site", + "project.program.name", + "project.disease_type", + "submitter_id", + "clinical.icd_10", + "demographic.gender", + "demographic.race", + "demographic.ethnicity", + "diagnoses.year_of_diagnosis", + "diagnoses.vital_status", + "diagnoses.days_to_death", + "diagnoses.age_at_diagnosis" + ], + expand: [ + "summary.data_categories", + ], + facets: [ + {name: "case_id", title: "Case", collapsed: false, facetType: "free-text", placeholder: "UUID, Submitter ID"}, + {name: "project.primary_site", title: "Primary Site", collapsed: false, facetType: "terms"}, + {name: "project.program.name", title: "Cancer Program", collapsed: false, facetType: "terms"}, + {name: "project.project_id", title: "Project", collapsed: false, facetType: "terms"}, + {name: "project.disease_type", title: "Disease Type", collapsed: false, facetType: "terms"}, + {name: "demographic.gender", title: "Gender", collapsed: false, facetType: "terms"}, + {name: "diagnoses.age_at_diagnosis", title: "Age at diagnosis", collapsed: false, facetType: "range", unitsMap: [ + { + "label": "years", + "conversionDivisor": 365.25, + }, + { + "label": "days", + "conversionDivisor": 1, + } + ]}, + {name: "diagnoses.vital_status", title: "Vital Status", collapsed: false, facetType: "terms"}, + {name: "diagnoses.days_to_death", title: "Days to Death", collapsed: false, facetType: "range", hasGraph: true}, + {name: "demographic.race", title: "Race", collapsed: false, facetType: "terms"}, + {name: "demographic.ethnicity", title: "Ethnicity", collapsed: false, facetType: "terms"} + ] + }; + } + } + angular.module("search.cases.table.service", ["ngApp.core"]) + .service("SearchCasesTableService", SearchCasesTableService); +} diff --git a/app/scripts/search/search.controllers.ts b/app/scripts/search/search.controllers.ts index bd1ee1f69..84ff5aa58 100755 --- a/app/scripts/search/search.controllers.ts +++ b/app/scripts/search/search.controllers.ts @@ -58,7 +58,7 @@ module ngApp.search.controllers { private UserService: IUserService, public CoreService: ICoreService, public SearchTableFilesModel: TableiciousConfig, - public SearchTableParticipantsModel: TableiciousConfig, + public SearchCasesTableService: TableiciousConfig, private FacetsConfigService: IFacetsConfigService, public FacetService, SearchChartConfigs) { @@ -83,7 +83,7 @@ module ngApp.search.controllers { }); $scope.fileTableConfig = this.SearchTableFilesModel; - $scope.participantTableConfig = this.SearchTableParticipantsModel; + $scope.participantTableConfig = this.SearchCasesTableService.model(); this.refresh(); this.chartConfigs = SearchChartConfigs; @@ -118,6 +118,8 @@ module ngApp.search.controllers { return; } + const casesTableModel = this.SearchCasesTableService.model(); + this.filesLoading = true; this.participantsLoading = true; @@ -132,10 +134,10 @@ module ngApp.search.controllers { facets: this.FacetService.filterFacets(this.FacetsConfigService.fieldsMap['files']) }; - this.FacetsConfigService.setFields('cases', this.SearchTableParticipantsModel.facets); + this.FacetsConfigService.setFields('cases', casesTableModel.facets); var participantOptions = { - fields: this.SearchTableParticipantsModel.fields, - expand: this.SearchTableParticipantsModel.expand, + fields: casesTableModel.fields, + expand: casesTableModel.expand, facets: this.FacetService.filterFacets(this.FacetsConfigService.fieldsMap['cases']) }; @@ -233,7 +235,7 @@ module ngApp.search.controllers { "core.services", "participants.services", "search.table.files.model", - "search.table.participants.model", + "search.cases.table.service", "files.services", "facets.services" ]) diff --git a/app/scripts/search/search.participants.table.model.ts b/app/scripts/search/search.participants.table.model.ts deleted file mode 100644 index e9e8260b3..000000000 --- a/app/scripts/search/search.participants.table.model.ts +++ /dev/null @@ -1,271 +0,0 @@ -module ngApp.search.models { - function withAnnotationFilter(value: number, filters: Object[], $filter: ng.IFilterService): string { - var filterString = $filter("makeFilter")(filters, true); - var href = 'annotations?filters=' + filterString; - var val = '{{' + value + '|number:0}}'; - return "" + val + ''; - } - - function withFilter(value: number, filters: Object[], $filter: ng.IFilterService): string { - var filterString = $filter("makeFilter")(filters, true); - var href = 'search/f?filters=' + filterString; - var val = '{{' + value + '|number:0}}'; - return value ? "" + val + '' : '0'; - } - - function getDataCategory(dataCategories: Object[], dataCategory: string): number { - var data = _.find(dataCategories, {data_category: dataCategory}); - return data ? data.file_count : 0; - } - function dataCategoryWithFilters(dataCategory: string, row: Object[], $filter: ng.IFilterService) { - var fs = [ - {field: 'cases.case_id', value: row.case_id}, - {field: 'files.data_category', value: dataCategory} - ]; - return withFilter(getDataCategory(row.summary ? row.summary.data_categories : [], dataCategory), fs, $filter); - } - function youngestDiagnosis(p: { age_at_diagnosis: number }, c: { age_at_diagnosis: number }): { age_at_diagnosis: number } { - return c.age_at_diagnosis < p.age_at_diagnosis ? c : p - } - - var searchParticipantsModel = { - title: 'Cases', - rowId: 'case_id', - headings: [{ - name: "Cart", - id: "add_to_cart_filtered", - td: row => '', - tdClassName: 'text-center' - }, { - name: "My Projects", - id: "my_projects", - td: (row, $scope) => { - var fakeFile = {cases: [{project: row.project}]}; - var isUserProject = $scope.UserService.isUserProject(fakeFile); - var icon = isUserProject ? 'check' : 'remove'; - return ''; - }, - inactive: $scope => !$scope.UserService.currentUser || $scope.UserService.currentUser.isFiltered, - hidden: false, - tdClassName: "text-center" - }, { - name: "Case UUID", - id: "case_id", - toolTipText: row => row.case_id, - td: row => '' + row.case_id + '', - tdClassName: 'truncated-cell' - }, { - name: "Project", - id: "project.project_id", - toolTipText: row => row.project.name, - td: row => '' + row.project.project_id + '', - sortable: true, - }, { - name: "Primary Site", - id: "project.primary_site", - td: row => row.project && row.project.primary_site, - sortable: true - }, { - name: "Gender", - id: "demographic.gender", - td: (row, $scope) => row.demographic && $scope.$filter("humanify")(row.demographic.gender) || '--', - sortable: true - }, { - name: "Files", - id: "files", - td: (row, $scope) => { - var fs = [{field: 'cases.case_id', value: row.case_id}] - var sum = _.sum(_.pluck(row.summary ? row.summary.data_categories : [], 'file_count')) - return withFilter(sum, fs, $scope.$filter); - }, - thClassName: 'text-right', - tdClassName: 'text-right' - }, { - name: "Available Files per Data Category", - id: "summary.data_categories", - thClassName:'text-center', - children: [ - { - name: 'Seq', - th: 'Seq', - id: 'Seq', - td: (row, $scope) => dataCategoryWithFilters("Raw sequencing data", row, $scope.$filter), - thClassName: 'text-right', - tdClassName: 'text-right' - }, { - name: "Exp", - th: 'Exp', - id: "Exp", - td: (row, $scope) => dataCategoryWithFilters("Gene expression", row, $scope.$filter), - thClassName: 'text-right', - tdClassName: 'text-right' - }, { - name: 'SNV', - th: 'SNV', - id: 'SNV', - td: (row, $scope) => dataCategoryWithFilters("Simple nucleotide variation", row, $scope.$filter), - thClassName: 'text-right', - tdClassName: 'text-right' - }, { - name: 'CNV', - th: 'CNV', - id: 'cnv', - td: (row, $scope) => dataCategoryWithFilters("Copy number variation", row, $scope.$filter), - thClassName: 'text-right', - tdClassName: 'text-right' - }, { - name: 'Clinical', - th: 'Clinical', - id: 'clinical', - td: (row, $scope) => dataCategoryWithFilters("Clinical", row, $scope.$filter), - thClassName: 'text-right', - tdClassName: 'text-right' - }, { - name: 'Biospecimen', - id: 'biospecimen', - td: (row, $scope) => dataCategoryWithFilters("Biospecimen", row, $scope.$filter), - thClassName: 'text-right', - tdClassName: 'text-right' - } - ] - }, { - name: "Annotations", - id: "annotations.annotation_id", - td: (row, $scope) => { - function getAnnotations(row, $filter) { - return row.annotations.length == 1 ? - '' + 1 + '' : - withAnnotationFilter( - row.annotations.length, - [{field: "annotation_id", value: _.pluck(row.annotations, 'annotation_id')}], - $filter); - } - - return row.annotations && row.annotations.length ? getAnnotations(row, $scope.$filter) : 0; - }, - thClassName: 'text-right', - tdClassName: 'text-right' - }, { - name: 'Program', - id: 'project.program.name', - td: (row, $scope) => row.project && $scope.$filter("humanify")(row.project.program.name), - sortable: false, - hidden: true - }, { - name: 'Disease Type', - id: 'project.disease_type', - td: (row, $scope) => row.project && $scope.$filter("humanify")(row.project.disease_type), - sortable: false, - hidden: true - }, { - name: 'Age at diagnosis', - id: 'diagnoses.age_at_diagnosis', - td: (row, $scope) => { - // Use diagnosis with minimum age - const age = (row.diagnoses || []).reduce((p, c) => c.age_at_diagnosis < p ? c.age_at_diagnosis : p, Infinity); - return age !== Infinity && row.diagnoses ? $scope.$filter("ageDisplay")(age) : "--"; - }, - sortable: false, - hidden: true - }, { - name: 'Days to death', - id: 'diagnoses.days_to_death', - td: (row, $scope) => { - const primaryDiagnosis = (row.diagnoses || []) - .reduce(youngestDiagnosis, { age_at_diagnosis: Infinity }); - return (row.diagnoses && $scope.$filter("number")(primaryDiagnosis.days_to_death, 0)) || "--" - }, - sortable: false, - hidden: true - }, { - name: 'Vital Status', - id: 'diagnoses.vital_status', - td: (row, $scope) => { - const primaryDiagnosis = (row.diagnoses || []) - .reduce(youngestDiagnosis, { age_at_diagnosis: Infinity }); - return row.diagnoses && $scope.$filter("humanify")(primaryDiagnosis.vital_status) - }, - sortable: false, - hidden: true - }, { - name: 'Year of diagnosis', - id: 'diagnoses.year_of_diagnosis', - td: (row, $scope) => { - const primaryDiagnosis = (row.diagnoses || []) - .reduce(youngestDiagnosis, { age_at_diagnosis: Infinity }); - return (row.diagnoses && primaryDiagnosis.year_of_diagnosis) || "--" - }, - sortable: false, - hidden: true - }, { - name: 'ICD-10', - id: 'icd_10', - td: (row, $scope) => (row.clinical && row.clinical.icd_10) || "--", - sortable: false, - hidden: true - }, { - name: 'Ethnicity', - id: 'demographic.ethnicity', - td: (row, $scope) => row.demographic && $scope.$filter("humanify")(row.demographic.ethnicity), - sortable: false, - hidden: true - }, { - name: 'Race', - id: 'demographic.race', - td: (row, $scope) => row.demographic && $scope.$filter("humanify")(row.demographic.race), - sortable: false, - hidden: true - }, { - name: 'Submitter ID', - id: 'submitter_id', - td: (row, $scope) => row.submitter_id, - sortable: false, - hidden: true - }], - fields: [ - "case_id", - "annotations.annotation_id", - "project.project_id", - "project.name", - "project.primary_site", - "project.program.name", - "project.disease_type", - "submitter_id", - "clinical.icd_10", - "demographic.gender", - "demographic.race", - "demographic.ethnicity", - "diagnoses.year_of_diagnosis", - "diagnoses.vital_status", - "diagnoses.days_to_death", - "diagnoses.age_at_diagnosis" - ], - expand: [ - "summary.data_categories", - ], - facets: [ - {name: "case_id", title: "Case", collapsed: false, facetType: "free-text", placeholder: "UUID, Submitter ID"}, - {name: "project.primary_site", title: "Primary Site", collapsed: false, facetType: "terms"}, - {name: "project.program.name", title: "Cancer Program", collapsed: false, facetType: "terms"}, - {name: "project.project_id", title: "Project", collapsed: false, facetType: "terms"}, - {name: "project.disease_type", title: "Disease Type", collapsed: false, facetType: "terms", showTooltip: true}, - {name: "demographic.gender", title: "Gender", collapsed: false, facetType: "terms"}, - {name: "diagnoses.age_at_diagnosis", title: "Age at diagnosis", collapsed: false, facetType: "range", unitsMap: [ - { - "label": "years", - "conversionDivisor": 365.25, - }, - { - "label": "days", - "conversionDivisor": 1, - } - ]}, - {name: "diagnoses.vital_status", title: "Vital Status", collapsed: false, facetType: "terms"}, - {name: "diagnoses.days_to_death", title: "Days to Death", collapsed: false, facetType: "range", hasGraph: true}, - {name: "demographic.race", title: "Race", collapsed: false, facetType: "terms"}, - {name: "demographic.ethnicity", title: "Ethnicity", collapsed: false, facetType: "terms"} - ] - }; - angular.module("search.table.participants.model", []) - .value("SearchTableParticipantsModel", searchParticipantsModel); -} diff --git a/app/scripts/search/templates/search.html b/app/scripts/search/templates/search.html index cf0c0927f..59b855800 100755 --- a/app/scripts/search/templates/search.html +++ b/app/scripts/search/templates/search.html @@ -9,7 +9,7 @@ aggregations="sc.participants.aggregations" data-doc-type="cases"> - From 9a797c38347422d0f54a4023bd7473d2e8458bae Mon Sep 17 00:00:00 2001 From: Alex Wilmer Date: Mon, 25 Apr 2016 14:44:19 -0400 Subject: [PATCH 49/80] fix(githut): 2164 link add data_category filter - use DATA_CATEGORIES constant in githut Closes #2164 --- app/scripts/core/module.ts | 2 +- .../projects/projects.githut.config.ts | 80 +++++-------------- .../search/search.cases.table.service.ts | 17 ++-- 3 files changed, 30 insertions(+), 69 deletions(-) diff --git a/app/scripts/core/module.ts b/app/scripts/core/module.ts index b08296a37..ae407128f 100644 --- a/app/scripts/core/module.ts +++ b/app/scripts/core/module.ts @@ -10,7 +10,7 @@ angular ]) .constant('DATA_CATEGORIES', { SEQ: { full: "Raw Sequencing Data", abbr: "Seq" }, - EXP: { full: "Gene Expression", abbr: "Exp" }, + EXP: { full: "Transcriptome Profiling", abbr: "Exp" }, SNV: { full: "Simple Nucleotide Variation", abbr: "SNV" }, CNV: { full: "Copy Number Variation", abbr: "CNV" }, CLINICAL: { full: "Clinical", abbr: "Clinical" }, diff --git a/app/scripts/projects/projects.githut.config.ts b/app/scripts/projects/projects.githut.config.ts index be3270b64..9cf4e51af 100644 --- a/app/scripts/projects/projects.githut.config.ts +++ b/app/scripts/projects/projects.githut.config.ts @@ -1,4 +1,4 @@ -angular.module('projects.githut.config', []) +angular.module('projects.githut.config', ['ngApp.core']) .factory("ProjectsGithut", function(ProjectsGithutConfig, ProjectsGithutColumns) { return function(data) { var hits = filterData(data.hits); @@ -88,7 +88,7 @@ angular.module('projects.githut.config', []) } } }) -.service("ProjectsGithutColumns",function($state, $filter){ +.service("ProjectsGithutColumns", function($state, $filter, DATA_CATEGORIES){ function projectSref(d) { var filter = $filter("makeFilter")([{ field: 'cases.project.project_id', @@ -102,12 +102,12 @@ angular.module('projects.githut.config', []) var filter = $filter("makeFilter")([{ field: 'cases.project.project_id', value: d.lang - }, {field: 'files.data_type', value: d.column}]); + }, {field: 'files.data_category', value: d.column}]); $state.go("search.participants", { filters:JSON.parse(filter) }); } - return [ + var results = [ { id: 'project_id', display_name: ["Project","ID"], @@ -125,61 +125,19 @@ angular.module('projects.githut.config', []) colorgroup:'case_count', href: projectSref }, - { - id:'Raw Sequencing Data', - display_name:['Seq'], - scale:'ordinal', - is_subtype:true, - dimensional:true, - colorgroup:'case_count', - href: dataTypeSref - }, - { - id:'Protein Expression', - display_name:['Exp'], - scale:'ordinal', - is_subtype:true, - dimensional:true, - colorgroup:'case_count', - href: dataTypeSref - }, - { - id:'Simple Nucleotide Variation', - display_name:['SNV'], - scale:'ordinal', - is_subtype:true, - dimensional:true, - colorgroup:'case_count', - href: dataTypeSref - }, - { - id:'Copy Number Variation', - display_name:['CNV'], - scale:'ordinal', - is_subtype:true, - dimensional:true, - colorgroup:'case_count', - href: dataTypeSref - }, - { - id:'Clinical', - display_name:['Clinical'], - scale:'ordinal', - is_subtype:true, - dimensional:true, - colorgroup:'case_count', - href: dataTypeSref - }, - // Biospecimen - { - id:'Biospecimen', - display_name:['Biospecimen'], - scale:'ordinal', - is_subtype:true, - dimensional:true, - colorgroup:'case_count', - href: dataTypeSref - }, + ] + + results = results.concat(Object.keys(DATA_CATEGORIES).map(key => ({ + id: DATA_CATEGORIES[key].full, + display_name: [DATA_CATEGORIES[key].abbr], + scale:'ordinal', + is_subtype:true, + dimensional:true, + colorgroup:'case_count', + href: dataTypeSref + }))); + + results = results.concat([ { id:'file_count', display_name:["File","Count"], @@ -204,7 +162,9 @@ angular.module('projects.githut.config', []) scale:'linear', dimensional:true } - ] + ]); + + return results; }) .service("ProjectsGithutConfig",function(ProjectsService,ProjectsGithutColumns, $filter){ var color = d3.scale.category10(); diff --git a/app/scripts/search/search.cases.table.service.ts b/app/scripts/search/search.cases.table.service.ts index 768267cc2..e85174d38 100644 --- a/app/scripts/search/search.cases.table.service.ts +++ b/app/scripts/search/search.cases.table.service.ts @@ -106,16 +106,17 @@ module ngApp.search.cases.table.service { name: "Annotations", id: "annotations.annotation_id", td: (row, $scope) => { - function getAnnotations(row, $filter) { - return row.annotations.length == 1 ? - '' + 1 + '' : - this.withAnnotationFilter( - row.annotations.length, - [{field: "annotation_id", value: _.pluck(row.annotations, 'annotation_id')}], - $filter); + var getAnnotations = (row, $filter) => { + return row.annotations.length === 1 + ? '' + 1 + '' + : this.withAnnotationFilter( + row.annotations.length, + [{field: "annotation_id", value: _.pluck(row.annotations, 'annotation_id')}], + $filter + ); } - return row.annotations && row.annotations.length ? getAnnotations(row, $scope.$filter) : 0; + return (row.annotations || []).length && getAnnotations(row, $scope.$filter); }, thClassName: 'text-right', tdClassName: 'text-right' From 1dffaf61b7ad835d7d5ffdfe5df6aa26972a45dd Mon Sep 17 00:00:00 2001 From: Alex Wilmer Date: Mon, 25 Apr 2016 16:16:02 -0400 Subject: [PATCH 50/80] fix(home): 2178 adjust queries - fix issue where getting 0 where there should be results - minor refactoring Closes #2178 --- app/scripts/home/home.controllers.ts | 114 +++++++++++++++++-------- app/scripts/home/home.services.ts | 29 ++----- app/scripts/query/query.controllers.ts | 3 +- 3 files changed, 90 insertions(+), 56 deletions(-) diff --git a/app/scripts/home/home.controllers.ts b/app/scripts/home/home.controllers.ts index 9e587f2ae..afdb4202e 100755 --- a/app/scripts/home/home.controllers.ts +++ b/app/scripts/home/home.controllers.ts @@ -28,7 +28,8 @@ module ngApp.home.controllers { /* @ngInject */ constructor(private HomeService: IHomeService, private ProjectsTableService: TableiciousConfig, - private CoreService: ICoreService, private $filter: ng.ui.IFilterService) { + private CoreService: ICoreService, private $filter: ng.ui.IFilterService, + private DATA_CATEGORIES) { CoreService.setPageTitle("Welcome to The Genomics Data Commons Data Portal"); @@ -71,19 +72,80 @@ module ngApp.home.controllers { this.exampleSearchQueries = [ { description: "Cases of kidney cancer diagnosed at the age of 20 and below", - filters: {"op":"and","content":[{"op":"<=","content":{"field":"cases.clinical.age_at_diagnosis","value":[yearsToDays(20)]}},{"op":"in","content":{"field":"cases.project.primary_site","value":["Kidney"]}}]}, + filters: { + op: "and", + content: [ + { + op: "<=", + content: { + field: "cases.diagnoses.age_at_diagnosis", + value: [ yearsToDays(20) ] + } + }, + { + op: "in", + content: { + field: "cases.project.primary_site", + value: [ "Kidney" ] + } + } + ] + }, caseCount: null, fileCount: null }, { description: "CNV data of female brain cancer cases", - filters: {"op":"and","content":[{"op":"in","content":{"field":"files.data_category","value":["Copy number variation"]}},{"op":"in","content":{"field":"cases.project.primary_site","value":["Brain"]}},{"op":"in","content":{"field":"cases.demographic.gender","value":["female"]}}]}, + filters: { + op: "and", + content: [ + { + op: "in", + content: { + field: "files.data_category", + value: [ this.DATA_CATEGORIES.CNV.full ] + } + }, + { + op: "in", + content: { + field: "cases.project.primary_site", + value: [ "Brain" ] + } + }, + { + op: "in", + content: { + field: "cases.demographic.gender", + value: [ "female" ] + } + } + ] + }, caseCount: null, fileCount: null }, { description: "Germline mutation data in TCGA-OV project", - filters: {"op":"and","content":[{"op":"in","content":{"field":"files.data_type","value":["Simple nucleotide variation"]}},{"op":"in","content":{"field":"cases.project.project_id","value":["TCGA-OV"]}}]}, + filters: { + op: "and", + content: [ + { + op: "in", + content: { + field: "files.data_category", + value: [ this.DATA_CATEGORIES.SNV.full ] + } + }, + { + op: "in", + content: { + field: "cases.project.project_id", + value: [ "TCGA-OV" ] + } + } + ] + }, caseCount: null, fileCount: null }, @@ -107,39 +169,21 @@ module ngApp.home.controllers { } fetchExampleSearchQueryStats() { - var _controller = this, - exampleQueries = _controller.exampleSearchQueries, - defaultParams = _controller.defaultParams; - - for (var i = 0; i < exampleQueries.length; i++) { - var query = exampleQueries[i]; - - (function(q) { - - var params = _.cloneDeep(defaultParams); - params.filters = q.filters; - _controller.HomeService.getParticipants(params).then( - function (projectData) { - q.caseCount = _.get(projectData, 'pagination.total', 0); - }, - function () { - q.caseCount = '--'; - } - ); + var exampleQueries = this.exampleSearchQueries; + var defaultParams = this.defaultParams; - _controller.HomeService.getFiles(params).then( - function (projectData) { - q.fileCount = _.get(projectData, 'pagination.total', 0); - }, - function () { - q.fileCount = '--'; - } - ); + exampleQueries.forEach(query => { + var params = _.cloneDeep(defaultParams); + params.filters = query.filters; + this.HomeService.getParticipants(params).then( + projectData => query.caseCount = projectData.pagination.total + ).catch(() => query.fileCount = '--'); - })(query); - - } + this.HomeService.getFiles(params).then( + projectData => query.fileCount = projectData.pagination.total + ).catch(() => query.fileCount = '--'); + }); } getExampleSearchQueries() { @@ -337,6 +381,6 @@ module ngApp.home.controllers { } angular - .module("home.controller", []) + .module("home.controller", ["ngApp.core"]) .controller("HomeController", HomeController); } diff --git a/app/scripts/home/home.services.ts b/app/scripts/home/home.services.ts index 5ed661241..3359e2542 100644 --- a/app/scripts/home/home.services.ts +++ b/app/scripts/home/home.services.ts @@ -33,22 +33,11 @@ module ngApp.home.services { } prepParams(params:Object = {}) { - - var p = _.cloneDeep(params); - - if (_.has(p, "fields")) { - p["fields"] = p["fields"].join(); - } - - if (_.has(p, "expand")) { - p["expand"] = p["expand"].join(); - } - - if (_.has(params, "facets")) { - p["facets"] = p["facets"].join(); - } - - return p; + return _.extend({}, params, { + fields: params.fields && params.fields.join(), + expand: params.expand && params.expand.join(), + facets: params.facets && params.facets.join(), + }) } getProjects(params:Object = {}):ng.IPromise { @@ -57,9 +46,9 @@ module ngApp.home.services { // Testing is expecting these values in URL, so this is needed. var paging = params.paging || { - size: 20, - from: 1 - }; + size: 20, + from: 1 + }; var defaults = { size: params.size || paging.size, @@ -184,4 +173,4 @@ module ngApp.home.services { angular .module("home.services", ["reports.services"]) .service("HomeService", HomeService); -} \ No newline at end of file +} diff --git a/app/scripts/query/query.controllers.ts b/app/scripts/query/query.controllers.ts index 60d802534..72dfd246e 100755 --- a/app/scripts/query/query.controllers.ts +++ b/app/scripts/query/query.controllers.ts @@ -107,6 +107,7 @@ module ngApp.query.controllers { var participantOptions = { fields: casesTableModel.fields, + expand: casesTableModel.expand, }; this.FilesService.getFiles(fileOptions).then((data: IFiles) => { @@ -133,7 +134,7 @@ module ngApp.query.controllers { this.participants = this.participants || {}; this.participants.aggregations = data.aggregations; this.participants.pagination = data.pagination - + if (!_.isEqual(this.participants.hits, data.hits)) { this.participants.hits = data.hits; this.tabSwitch = false; From 3056b21239b6cd918518f84b2806f6ecc0432a38 Mon Sep 17 00:00:00 2001 From: Terry Lin Date: Mon, 25 Apr 2016 15:14:43 -0400 Subject: [PATCH 51/80] fix(css): 2150 gdc-app menu layout issue in IE Closes #2150 --- app/styles/home.less | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/app/styles/home.less b/app/styles/home.less index 412229862..2d22ff607 100644 --- a/app/styles/home.less +++ b/app/styles/home.less @@ -33,7 +33,6 @@ justify-content: space-between; .menu-column { - display: flex; flex-wrap: wrap; flex-direction: column; } @@ -384,7 +383,7 @@ display: inline-block; position: relative; color: #777; - + a { display: block; color: inherit; @@ -420,7 +419,7 @@ flex: 1; text-transform: uppercase; border-right: solid 2px #d3e5e7; - + .stats-block-body { font-size: 3.5rem; font-weight: 300; @@ -438,7 +437,7 @@ // Layout: Row 3 .table-row-container { - + .info-table { padding: 0 .25rem; a { @@ -458,7 +457,7 @@ min-height: 11.4rem; line-height: 2rem; } - + .gdc-apps { td { background-color: #fff; From 1078fae0d4f97de911ac89ef665a7c1cde12c946 Mon Sep 17 00:00:00 2001 From: Shane Wilson Date: Tue, 26 Apr 2016 15:32:42 -0400 Subject: [PATCH 52/80] fix(components): handle empty fields in gql/facets Closes #2126, #2124 --- app/scripts/components/facets/facets.controllers.ts | 1 + app/scripts/components/gql/gql.filters.ts | 2 +- app/scripts/components/gql/module.ts | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/scripts/components/facets/facets.controllers.ts b/app/scripts/components/facets/facets.controllers.ts index 8df7965f1..92a07f4dd 100644 --- a/app/scripts/components/facets/facets.controllers.ts +++ b/app/scripts/components/facets/facets.controllers.ts @@ -515,6 +515,7 @@ module ngApp.components.facets.controllers { addFacet() { var selectedField = this.$scope.filteredFields[this.selectedIndex]; + if (!selectedField) return; var fileOptions = { fields: [], expand: [], diff --git a/app/scripts/components/gql/gql.filters.ts b/app/scripts/components/gql/gql.filters.ts index d2052843d..1193aa867 100644 --- a/app/scripts/components/gql/gql.filters.ts +++ b/app/scripts/components/gql/gql.filters.ts @@ -3,7 +3,7 @@ module ngApp.components.gql.filters { class GqlHighlight { constructor() { return function (value: string, query: string): string { - return value.replace(query, '' + query + ''); + return (value || '').replace(query, '' + query + ''); }; } } diff --git a/app/scripts/components/gql/module.ts b/app/scripts/components/gql/module.ts index 001b8bf8a..658616229 100644 --- a/app/scripts/components/gql/module.ts +++ b/app/scripts/components/gql/module.ts @@ -151,7 +151,7 @@ module ngApp.components.gql { if (parts.docType === "files") { return this.FilesService.getFiles(params) .then((fs: IFiles): IDdItem[] => { - var f: IFacet = fs.aggregations[parts.facet]; + var f: IFacet = (fs.aggregations || {})[parts.facet] || []; return _.map(f.buckets, (b) => { return {field: b.key, full: b.key}; }); @@ -159,7 +159,7 @@ module ngApp.components.gql { } else { return this.ParticipantsService.getParticipants(params) .then((fs: IParticipants): IDdItem[] => { - var f: IFacet = fs.aggregations[parts.facet]; + var f: IFacet = (fs.aggregations || {})[parts.facet] || []; return _.map(f.buckets, (b) => { return {field: b.key, full: b.key}; }); From ac275683ff4c0dd75225a03946e5e0289ff53e7e Mon Sep 17 00:00:00 2001 From: Alex Wilmer Date: Tue, 26 Apr 2016 12:39:23 -0400 Subject: [PATCH 53/80] fix(components): add track by for facetConfig - fix bug where refreshing page after adding custom facet crashed --- app/scripts/components/facets/templates/facets-section.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/scripts/components/facets/templates/facets-section.html b/app/scripts/components/facets/templates/facets-section.html index 50caad203..d4b4c9e04 100644 --- a/app/scripts/components/facets/templates/facets-section.html +++ b/app/scripts/components/facets/templates/facets-section.html @@ -1,4 +1,4 @@ -
    +
    Date: Tue, 26 Apr 2016 12:44:12 -0400 Subject: [PATCH 54/80] fix(components): 2181 don't humanify fields Closes #2181 --- app/scripts/components/facets/templates/current.html | 2 +- app/scripts/components/facets/templates/facet.html | 6 +++--- app/scripts/components/facets/templates/facets-section.html | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/scripts/components/facets/templates/current.html b/app/scripts/components/facets/templates/current.html index ad6d6b189..f25cddc48 100644 --- a/app/scripts/components/facets/templates/current.html +++ b/app/scripts/components/facets/templates/current.html @@ -34,7 +34,7 @@ {{ v }} {{ v | translate | humanify }} + class="facet-block">{{ v | translate }} and in My Projects diff --git a/app/scripts/components/facets/templates/facet.html b/app/scripts/components/facets/templates/facet.html index a580254fa..c118b08cd 100644 --- a/app/scripts/components/facets/templates/facet.html +++ b/app/scripts/components/facets/templates/facet.html @@ -36,7 +36,7 @@ data-tooltip-append-to-body="true" data-tooltip-placement="right">{{ ::term.key.toUpperCase() }} - {{ ::term.key | translate | humanify:true:true }} + {{ ::term.key | translate }} {{ term.doc_count | number:0 }} @@ -59,10 +59,10 @@ - {{ ::term.key | translate | humanify: true:true }} + {{ ::term.key | translate }} - {{ ::term.key | translate | humanify: true:true }} + {{ ::term.key | translate }} {{ term.doc_count | number:0 }} diff --git a/app/scripts/components/facets/templates/facets-section.html b/app/scripts/components/facets/templates/facets-section.html index d4b4c9e04..2f0f004a6 100644 --- a/app/scripts/components/facets/templates/facets-section.html +++ b/app/scripts/components/facets/templates/facets-section.html @@ -1,4 +1,4 @@ -
    +
    Date: Tue, 26 Apr 2016 15:47:30 -0400 Subject: [PATCH 55/80] fix(search): 2177 ICD-10 to Primary Diagnoses Closes #2177 --- app/scripts/search/search.cases.table.service.ts | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/app/scripts/search/search.cases.table.service.ts b/app/scripts/search/search.cases.table.service.ts index e85174d38..98dd875ed 100644 --- a/app/scripts/search/search.cases.table.service.ts +++ b/app/scripts/search/search.cases.table.service.ts @@ -163,21 +163,16 @@ module ngApp.search.cases.table.service { sortable: false, hidden: true }, { - name: 'Year of diagnosis', - id: 'diagnoses.year_of_diagnosis', + name: 'Primary Diagnosis', + id: 'diagnoses.primary_diagnosis', td: (row, $scope) => { + console.log(this.DATA_CATEGORIES) const primaryDiagnosis = (row.diagnoses || []) .reduce(this.youngestDiagnosis, { age_at_diagnosis: Infinity }); - return (row.diagnoses && primaryDiagnosis.year_of_diagnosis) || "--" + return (row.diagnoses && primaryDiagnosis.primary_diagnosis) || "--" }, sortable: false, hidden: true - }, { - name: 'ICD-10', - id: 'icd_10', - td: (row, $scope) => (row.clinical && row.clinical.icd_10) || "--", - sortable: false, - hidden: true }, { name: 'Ethnicity', id: 'demographic.ethnicity', @@ -206,11 +201,10 @@ module ngApp.search.cases.table.service { "project.program.name", "project.disease_type", "submitter_id", - "clinical.icd_10", "demographic.gender", "demographic.race", "demographic.ethnicity", - "diagnoses.year_of_diagnosis", + "diagnoses.primary_diagnosis", "diagnoses.vital_status", "diagnoses.days_to_death", "diagnoses.age_at_diagnosis" From cf2c32a8936215ca36b2ba34f31fdd3dcff035d5 Mon Sep 17 00:00:00 2001 From: Christine Yu Date: Tue, 26 Apr 2016 15:55:13 -0400 Subject: [PATCH 56/80] fix(annotation): add tooltip to project_id Closes #2066 --- app/scripts/annotations/annotations.controllers.ts | 5 ++++- app/scripts/annotations/templates/annotation.html | 4 +++- app/scripts/annotations/tests/annotations.tests.js | 1 + 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/app/scripts/annotations/annotations.controllers.ts b/app/scripts/annotations/annotations.controllers.ts index 461fd961b..550740b16 100755 --- a/app/scripts/annotations/annotations.controllers.ts +++ b/app/scripts/annotations/annotations.controllers.ts @@ -5,6 +5,7 @@ module ngApp.annotations.controllers { import IAnnotationsService = ngApp.annotations.services.IAnnotationsService; import TableiciousConfig = ngApp.components.tables.directives.tableicious.TableiciousConfig; import IFacetService = ngApp.components.facets.services.IFacetService; + import IProjectsService = ngApp.projects.services.IProjectsService; export interface IAnnotationsController { @@ -58,7 +59,9 @@ module ngApp.annotations.controllers { class AnnotationController implements IAnnotationController { /* @ngInject */ - constructor(public annotation: IAnnotation, private CoreService: ICoreService) { + constructor(public annotation: IAnnotation, + public ProjectsService: IProjectsService, + private CoreService: ICoreService) { CoreService.setPageTitle("Annotation", annotation.annotation_id); } } diff --git a/app/scripts/annotations/templates/annotation.html b/app/scripts/annotations/templates/annotation.html index ad53d8fb6..8164957bf 100755 --- a/app/scripts/annotations/templates/annotation.html +++ b/app/scripts/annotations/templates/annotation.html @@ -38,7 +38,9 @@

    Summary

    Project ID - + {{ ::ac.annotation.project.project_id }} diff --git a/app/scripts/annotations/tests/annotations.tests.js b/app/scripts/annotations/tests/annotations.tests.js index 11cfc1720..a964ef768 100755 --- a/app/scripts/annotations/tests/annotations.tests.js +++ b/app/scripts/annotations/tests/annotations.tests.js @@ -8,6 +8,7 @@ describe('Annotations:', function () { $provide.value('AuthRestangular', {}); $provide.value('notify', {}); $provide.value('config', {}); + $provide.value('ProjectsService', {}); })); // Injection of dependencies, $http will be mocked with $httpBackend From a69d166639b0e25cb7ac4cb27a00f5a10d35b1ce Mon Sep 17 00:00:00 2001 From: Christine Yu Date: Wed, 27 Apr 2016 12:08:36 -0400 Subject: [PATCH 57/80] fix(projects): 2172 missing line in facet section Closes #2172 --- app/scripts/components/facets/styles/facets.less | 1 - 1 file changed, 1 deletion(-) diff --git a/app/scripts/components/facets/styles/facets.less b/app/scripts/components/facets/styles/facets.less index 88aca8a82..eb66a6d9e 100644 --- a/app/scripts/components/facets/styles/facets.less +++ b/app/scripts/components/facets/styles/facets.less @@ -8,7 +8,6 @@ > .list-group:last-child, .list-group-item:last-child { border-bottom-left-radius: 0; border-bottom-right-radius: 0; - border-top: none; } } From b04663c610f26f5b517f446aa202c5ffc9528fd7 Mon Sep 17 00:00:00 2001 From: Christine Yu Date: Wed, 27 Apr 2016 14:28:21 -0400 Subject: [PATCH 58/80] fix(header): 2224 remove reports link Closes #2224 --- app/scripts/components/header/templates/header.html | 5 ----- 1 file changed, 5 deletions(-) diff --git a/app/scripts/components/header/templates/header.html b/app/scripts/components/header/templates/header.html index fc812afc5..6c928f0bb 100755 --- a/app/scripts/components/header/templates/header.html +++ b/app/scripts/components/header/templates/header.html @@ -32,11 +32,6 @@
  • -
  • - - - -
  • - -
    - -
    + +
    + +
    -

    Workflow

    +

    Analysis

    -

    No Workflow found.

    +

    No Analyses found.

    - @@ -346,7 +346,7 @@

    No Downstream Analyses Files Found.

    - + diff --git a/app/scripts/search/search.files.table.model.ts b/app/scripts/search/search.files.table.model.ts index 03891a5cb..8950cd653 100644 --- a/app/scripts/search/search.files.table.model.ts +++ b/app/scripts/search/search.files.table.model.ts @@ -168,6 +168,7 @@ module ngApp.search.models { {name: "data_category", title: "Data Category", collapsed: false, facetType: "terms", removable: false }, {name: "data_type", title: "Data Type", collapsed: false, facetType: "terms", removable: false }, {name: "experimental_strategy", title: "Experimental Strategy", collapsed: false, facetType: "terms", removable: false }, + {name: "analysis.workflow_type", title: "Workflow Type", collapsed: false, facetType: "terms", removable: false }, {name: "data_format", title: "Data Format", collapsed: false, facetType: "terms", removable: false }, {name: "platform", title: "Platform", collapsed: false, facetType: "terms", removable: false }, {name: "access", title: "Access Level", collapsed: false, facetType: "terms", removable: false }, From b26021b608bf31a0126f58e1fd6dd1c8752f5f3e Mon Sep 17 00:00:00 2001 From: Christine Yu Date: Wed, 27 Apr 2016 14:22:53 -0400 Subject: [PATCH 60/80] fix(exportTable): 2220 include case_id Closes #2220 --- app/scripts/search/search.files.table.model.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/scripts/search/search.files.table.model.ts b/app/scripts/search/search.files.table.model.ts index 8950cd653..14c805f9b 100644 --- a/app/scripts/search/search.files.table.model.ts +++ b/app/scripts/search/search.files.table.model.ts @@ -67,7 +67,7 @@ module ngApp.search.models { tdClassName: 'truncated-cell' }, { name: "Cases", - id: "cases", + id: "cases.case_id", td: (row, $scope) => { function getParticipants(row, $filter) { return row.cases.length == 1 ? From ff5edebbc4e46d021ac37b2e764deaff084e7536 Mon Sep 17 00:00:00 2001 From: Terry Lin Date: Mon, 25 Apr 2016 11:13:37 -0400 Subject: [PATCH 61/80] fix(login): 2151 login not shown in IE Closes #2151 --- app/scripts/core/core.directives.ts | 40 +++++++++++++++++------------ 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/app/scripts/core/core.directives.ts b/app/scripts/core/core.directives.ts index 2c64e5e58..75a8c1c18 100644 --- a/app/scripts/core/core.directives.ts +++ b/app/scripts/core/core.directives.ts @@ -10,34 +10,40 @@ module ngApp.core.directives { }, controller: function($scope, $element, $window) { $element.on('click', function(){ - var redirect = config.auth; - var authQuery = ""; - - if ($scope.redirect) { - redirect += "/" + $scope.redirect; - } + const returningPath = $window.location.pathname + '?' + (+new Date); + const redirectUrl = config.auth + + (p => p ? ('/' + p) : '')($scope.redirect) + + '?next=' + + (p => p ? (':' + p) : '')($window.location.port) + + returningPath; - if ($window.location.port) { - authQuery = "?next=" + ":" + $window.location.port + $window.location.pathname; - } else { - authQuery = "?next=" + $window.location.pathname; + const closeLogin = (url) => { + if (url === redirectUrl) { + // Redirect hasn't happened yet so don't kill the login window. + return false; + } else { + return _.includes(url, returningPath); + } } - var win = open(redirect + authQuery, 'Auth', 'width=800, height=600'); - - var interval = setInterval(() => { + const win = open(redirectUrl, 'Auth', 'width=800, height=600'); + const interval = setInterval(() => { try { - if (win.document && win.document.URL.indexOf($window.location.pathname) > -1) { + // Because the login window redirects to a different domain, checking win.document in IE11 throws + // exceptions right away, which prevents #clearInterval from ever getting called in this block. + // Must check this block (if the login window has been closed) first! + if (win.closed) { + clearInterval(interval); + } + else if (closeLogin(_.get(win, 'document.URL', ''))) { win.close(); setTimeout(() => { clearInterval(interval); UserService.login(); }, 1000); - } else if (!win.document) { // window is closed - clearInterval(interval); } } catch (err) { - console.log(err); + console.log('Error while monitoring the Login window: ', err); } }, 500); }); From 31ed1ecbefb1be94b977ac96940319399e96da99 Mon Sep 17 00:00:00 2001 From: Terry Lin Date: Wed, 27 Apr 2016 13:52:57 -0400 Subject: [PATCH 62/80] fix(case): 2199 better display for clinical data Closes #2199 --- .../participant/participants.controllers.ts | 2 +- .../participant/templates/participant.html | 35 +++++++++++++++---- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/app/scripts/participant/participants.controllers.ts b/app/scripts/participant/participants.controllers.ts index 64f94c948..8fa591e4e 100755 --- a/app/scripts/participant/participants.controllers.ts +++ b/app/scripts/participant/participants.controllers.ts @@ -57,7 +57,7 @@ module ngApp.participants.controllers { 'cases.case_id': participant.case_id }; this.clinicalDataExportExpands = ['demographic', 'diagnoses', 'diagnoses.treatments', 'family_histories', 'exposures']; - this.hasNoClinical = _.all(this.clinicalDataExportExpands, (field) => ! _.has(participant, field)); + this.hasNoClinical = ! this.clinicalDataExportExpands.some((field) => (participant[field] || []).length > 0); this.clinicalDataExportFileName = 'clinical.case-' + participant.case_id; this.dataCategories = _.reduce(DataCategoryNames.slice(), function(result, name) { diff --git a/app/scripts/participant/templates/participant.html b/app/scripts/participant/templates/participant.html index 5ac8bf4b1..99fb8dc4a 100755 --- a/app/scripts/participant/templates/participant.html +++ b/app/scripts/participant/templates/participant.html @@ -113,7 +113,8 @@

    Summary

    -
    +

    @@ -150,7 +151,7 @@

    @@ -203,6 +204,12 @@

    Data Category Data Type Data FormatAnalysis WorkflowAnalysis workflow File Size Action
    +
    +

    No Demographic Data Found.

    +
    -

    No treatments found.

    +

    No Treatments Found.

    @@ -381,7 +388,7 @@

    No treatments found.

    ng-if="pc.activeClinicalTab === 'diagnoses' && ! pc.participant.diagnoses.length" class="table table-striped table-hover table-condensed table-bordered table-vertical" style="border-top: 0; padding-top: 0.2rem; padding-left: 2rem"> -

    No diagnoses found.

    +

    No Diagnoses Found.

    No diagnoses found. ng-if="pc.activeClinicalTab === 'family_histories' && ! pc.participant.family_histories.length" class="table table-striped table-hover table-condensed table-bordered table-vertical" style="border-top: 0; padding-top: 0.2rem; padding-left: 2rem"> -

    No family histories found.

    +

    No Family Histories Found.

    No family histories found. ng-if="pc.activeClinicalTab === 'exposures' && ! pc.participant.exposures.length" class="table table-striped table-hover table-condensed table-bordered table-vertical" style="border-top: 0; padding-top: 0.2rem; padding-left: 2rem"> -

    No exposures found.

    +

    No Exposures Found.

    + +
    +
    +
    +

    + Clinical +

    +
    +
    +
    +

    No Clinical Data Found.

    +
    +
    From 636716eb5379eb129f49926db6b256c9525b61f1 Mon Sep 17 00:00:00 2001 From: Terry Lin Date: Wed, 27 Apr 2016 16:22:08 -0400 Subject: [PATCH 63/80] fix(file): 2198 displays file data as is Closes #2198 --- app/scripts/files/templates/file.html | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/app/scripts/files/templates/file.html b/app/scripts/files/templates/file.html index 2aa8b4e53..ca2b29624 100755 --- a/app/scripts/files/templates/file.html +++ b/app/scripts/files/templates/file.html @@ -86,11 +86,11 @@

    Data Information

    Data Category - {{ ::fc.file.data_category || '--' | titlefy }} + {{ ::fc.file.data_category || '--' }} Data Type - {{ ::fc.file.data_type || '--' | titlefy }} + {{ ::fc.file.data_type || '--' }} Experimental Strategy @@ -353,12 +353,12 @@

    No Downstream Analyses Files Found.

    - {{outf.file_name || '--'}} - {{outf.data_category | humanify}} - {{outf.data_type | humanify}} - {{outf.data_format | humanify}} - {{outf.workflow_type | humanify}} - {{outf.file_size | size}} + {{ ::outf.file_name || '--' }} + {{ ::outf.data_category || '--' }} + {{ ::outf.data_type || '--' }} + {{ ::outf.data_format || '--' }} + {{ ::outf.workflow_type || '--' }} + {{ ::outf.file_size | size }} From b614f352859aae8421de02d2c5511eb63adfa909 Mon Sep 17 00:00:00 2001 From: Alex Wilmer Date: Wed, 27 Apr 2016 14:22:25 -0400 Subject: [PATCH 64/80] fix(cart): 2161 download metadata_files - check file state on click Closes #2161 --- app/scripts/cart/cart.directives.ts | 47 ++++++++++++++--------------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/app/scripts/cart/cart.directives.ts b/app/scripts/cart/cart.directives.ts index 9a2787b18..d0febc11f 100644 --- a/app/scripts/cart/cart.directives.ts +++ b/app/scripts/cart/cart.directives.ts @@ -293,32 +293,31 @@ module ngApp.cart.directives { return { restrict:"AE", scope: true, - link: (scope, $element, $attrs) => { - scope.active = false; - - const reportStatus = _.isFunction(scope.$parent.reportStatus) ? - _.partial(scope.$parent.reportStatus, scope.$id) : - () => {}; + link: ($scope, $element, $attrs) => { + $element.on('click', () => { - const inProgress = () => { - scope.active = true; - reportStatus(scope.active); - $attrs.$set('disabled', 'disabled'); - }; - const done = () => { - scope.active = false; - reportStatus(scope.active); - $element.removeAttr('disabled'); - }; - const files = [].concat(CartService.getFiles()); - const params = { ids: files.map(f => f.file_id) }; - const url = config.api + '/data/metadata_files'; - const clickHandler = () => { - const checkProgress = scope.download(params, url, () => $element, 'POST'); + $scope.active = false; + + const reportStatus = _.isFunction($scope.$parent.reportStatus) + ? _.partial($scope.$parent.reportStatus, $scope.$id) + : () => {}; + + const inProgress = () => { + $scope.active = true; + reportStatus($scope.active); + $attrs.$set('disabled', 'disabled'); + }; + const done = () => { + $scope.active = false; + reportStatus($scope.active); + $element.removeAttr('disabled'); + }; + const files = [].concat(CartService.getFiles()); + const params = { ids: files.map(f => f.file_id) }; + const url = config.api + '/data/metadata_files'; + const checkProgress = $scope.download(params, url, () => $element, 'POST'); checkProgress(inProgress, done); - }; - - $element.on('click', clickHandler); + }); } }; } From e59ffa2fcb48c1adc494a8804ca9fa9ac6298312 Mon Sep 17 00:00:00 2001 From: Alex Wilmer Date: Thu, 28 Apr 2016 10:30:51 -0400 Subject: [PATCH 65/80] fix(app): 2201 data_category > summary cards - use DATA_CATEGORY constants Closes #2201 --- .../participant/participants.controllers.ts | 24 +++++++------------ app/scripts/projects/projects.controller.ts | 19 ++++++--------- 2 files changed, 16 insertions(+), 27 deletions(-) diff --git a/app/scripts/participant/participants.controllers.ts b/app/scripts/participant/participants.controllers.ts index 8fa591e4e..2b24b0d92 100755 --- a/app/scripts/participant/participants.controllers.ts +++ b/app/scripts/participant/participants.controllers.ts @@ -21,7 +21,7 @@ module ngApp.participants.controllers { private LocationService: ILocationService, private $filter: ng.IFilterService, private ExperimentalStrategyNames: string[], - private DataCategoryNames: string[], + private DATA_CATEGORIES, private config: IGDCConfig) { CoreService.setPageTitle("Case", participant.case_id); @@ -60,21 +60,15 @@ module ngApp.participants.controllers { this.hasNoClinical = ! this.clinicalDataExportExpands.some((field) => (participant[field] || []).length > 0); this.clinicalDataExportFileName = 'clinical.case-' + participant.case_id; - this.dataCategories = _.reduce(DataCategoryNames.slice(), function(result, name) { - var type = _.find(participant.summary.data_categories, (item) => { - return item.data_category.toLowerCase() === name.toLowerCase(); - }); - - if (type) { - result.push(type); - } else { - result.push({ - data_category: name, - file_count: 0 - }); - } + this.dataCategories = Object.keys(this.DATA_CATEGORIES).reduce((acc, key) => { + var type = _.find(participant.summary.data_categories, (item) => + item.data_category === this.DATA_CATEGORIES[key].full + ); - return result; + return acc.concat(type || { + data_category: this.DATA_CATEGORIES[key].full, + file_count: 0 + }); }, []); this.expStratConfig = { diff --git a/app/scripts/projects/projects.controller.ts b/app/scripts/projects/projects.controller.ts index 417480360..3994041b0 100644 --- a/app/scripts/projects/projects.controller.ts +++ b/app/scripts/projects/projects.controller.ts @@ -137,7 +137,7 @@ module ngApp.projects.controllers { constructor(public project: IProject, private CoreService: ICoreService, private AnnotationsService: IAnnotationsService, private ExperimentalStrategyNames: string[], - private DataCategoryNames: string[], + private DATA_CATEGORIES, public $state: ng.ui.IStateService, private $filter: ng.ui.IFilterService) { CoreService.setPageTitle("Project", project.project_id); @@ -154,20 +154,15 @@ module ngApp.projects.controllers { return result; }, []); - this.dataCategories = _.reduce(DataCategoryNames.slice(), function(result, name) { + this.dataCategories = Object.keys(this.DATA_CATEGORIES).reduce((acc, key) => { var type = _.find(project.summary.data_categories, (item) => { - return item.data_category.toLowerCase() === name.toLowerCase(); + return item.data_category === this.DATA_CATEGORIES[key].full; }); - if (type) { - result.push(type); - } else { - result.push({ - data_category: name, - file_count: 0 - }); - } - return result; + return acc.concat(type || { + data_category: this.DATA_CATEGORIES[key].full, + file_count: 0 + }); }, []); this.expStratConfig = { From 416045b319116b36d0ebdfd7d6a9338034e44d9b Mon Sep 17 00:00:00 2001 From: Shane Wilson Date: Thu, 28 Apr 2016 11:00:31 -0400 Subject: [PATCH 66/80] fix(gql): autocomplete with all OP by default Closes #2195 --- app/scripts/components/gql/module.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/scripts/components/gql/module.ts b/app/scripts/components/gql/module.ts index 658616229..709561f9f 100644 --- a/app/scripts/components/gql/module.ts +++ b/app/scripts/components/gql/module.ts @@ -363,10 +363,8 @@ module ngApp.components.gql { return [T.EQ, T.NE, T.GT, T.GTE, T.LT, T.LTE, T.IS, T.NOT].indexOf(item.full.toString()) != -1 } else if ((op.full || '').toString().indexOf('datetime') != -1) { return [T.GT, T.GTE, T.LT, T.LTE, T.IS, T.NOT].indexOf(item.full.toString()) != -1 - } else if (op.type === 'string') { - return [T.EQ, T.NE, T.IN, T.EXCLUDE, T.IS, T.NOT].indexOf(item.full.toString()) != -1 } else { - return false; + return [T.EQ, T.NE, T.IN, T.EXCLUDE, T.IS, T.NOT].indexOf(item.full.toString()) != -1 } } ); From 2510e58c0918b181e18221d75f73bb8f3e3bd218 Mon Sep 17 00:00:00 2001 From: Shane Wilson Date: Thu, 28 Apr 2016 11:21:23 -0400 Subject: [PATCH 67/80] style(components): limit facet width to 375px Closes #2076 --- app/styles/app.less | 1 + 1 file changed, 1 insertion(+) diff --git a/app/styles/app.less b/app/styles/app.less index 35ecc0ad6..c0e8daa04 100755 --- a/app/styles/app.less +++ b/app/styles/app.less @@ -718,6 +718,7 @@ pre code { /* Left Panal sidebar */ .facets-sidebar { + max-width: 375px; width: 30%; float: left; padding: 0 15px; From 311e764be50c2f27b323ad3874bc163ce69c41bd Mon Sep 17 00:00:00 2001 From: Shane Wilson Date: Thu, 28 Apr 2016 11:24:18 -0400 Subject: [PATCH 68/80] fix(search): remove file state from default facets Closes #2208 --- app/scripts/search/search.files.table.model.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/app/scripts/search/search.files.table.model.ts b/app/scripts/search/search.files.table.model.ts index 14c805f9b..859619b1f 100644 --- a/app/scripts/search/search.files.table.model.ts +++ b/app/scripts/search/search.files.table.model.ts @@ -172,7 +172,6 @@ module ngApp.search.models { {name: "data_format", title: "Data Format", collapsed: false, facetType: "terms", removable: false }, {name: "platform", title: "Platform", collapsed: false, facetType: "terms", removable: false }, {name: "access", title: "Access Level", collapsed: false, facetType: "terms", removable: false }, - {name: "state", title: "File Status", collapsed: false, facetType: "terms", removable: false }, ] }; angular.module("search.table.files.model", []) From 5356b82e78ed782b1bc06b1f9a5387313fc5379f Mon Sep 17 00:00:00 2001 From: Shane Wilson Date: Thu, 28 Apr 2016 11:33:34 -0400 Subject: [PATCH 69/80] fix(charts): remove undefined fn call Closes #2197 --- app/scripts/components/charts/chart.directives.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/scripts/components/charts/chart.directives.ts b/app/scripts/components/charts/chart.directives.ts index 5006b0b26..742a1515f 100644 --- a/app/scripts/components/charts/chart.directives.ts +++ b/app/scripts/components/charts/chart.directives.ts @@ -691,6 +691,7 @@ module ngApp.components.charts { // }) .on("click", function () { var tick = d3.select(this); + console.log('here: ', tick); var filters = { "op":"and", "content":[ @@ -699,9 +700,6 @@ module ngApp.components.charts { } ]}; - - _axisTipFn.hide(); - $state.go("projects.table", { filters: JSON.stringify(filters) }, From 8445c8048d05b451e059e9afa6f74eb789ea41c0 Mon Sep 17 00:00:00 2001 From: Shane Wilson Date: Thu, 28 Apr 2016 12:11:22 -0400 Subject: [PATCH 70/80] fix(home): update infra numbers Closes #2234 --- app/scripts/home/templates/home.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/scripts/home/templates/home.html b/app/scripts/home/templates/home.html index fbc82d023..9b591612b 100755 --- a/app/scripts/home/templates/home.html +++ b/app/scripts/home/templates/home.html @@ -118,13 +118,13 @@

    Infrastructure

    Compute Infrastructure - 13,120 Cores - 81,920 GB RAM + 12,800 Cores + 87.96 GB RAM Internet Bandwidth - 1.2 Gbps in - 18.2 Mbps out + 60 Gbps Total + 21.65 Gbps Utilized Unique Visitors From b373a26ec9f07f95c1dce1b2ec3492bf312d8300 Mon Sep 17 00:00:00 2001 From: Terry Lin Date: Thu, 28 Apr 2016 14:35:10 -0400 Subject: [PATCH 71/80] fix(login): 2221 retain my-project toggle state Closes #2221 --- app/scripts/components/user/user.services.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/scripts/components/user/user.services.ts b/app/scripts/components/user/user.services.ts index 48abf43a2..0249d430c 100755 --- a/app/scripts/components/user/user.services.ts +++ b/app/scripts/components/user/user.services.ts @@ -57,7 +57,6 @@ module ngApp.components.user.services { }) .post({}, {}) .then((data) => { - data.isFiltered = true; this.setUser(data); }, (response) => { if(response.status === 401) { @@ -106,6 +105,7 @@ module ngApp.components.user.services { setUser(user: IUser): void { this.currentUser = { username: user.username, + isFiltered: _.get(this, 'currentUser.isFiltered', true), projects: { gdc_ids: _.reduce(user.projects.gdc_ids || {}, (acc, p, key) => { if (p.indexOf("_member_") !== -1) { From e7f2d13e1fa6ae1f353ac0384e45816729212ec4 Mon Sep 17 00:00:00 2001 From: Christine Yu Date: Mon, 4 Apr 2016 12:38:29 -0400 Subject: [PATCH 72/80] fix(bam): 1888 error handling tweaks - show 'invalid BED format' for 400s only - only show app wide error msg for 500s Closes #1888 --- app/scripts/files/files.controllers.ts | 15 ++++++++++++--- app/scripts/files/files.services.ts | 19 +++++++++++++------ app/scripts/files/module.ts | 1 + .../files/templates/bam-slicing-failed.html | 14 +++++++++++--- app/scripts/files/templates/file.html | 2 +- 5 files changed, 38 insertions(+), 13 deletions(-) diff --git a/app/scripts/files/files.controllers.ts b/app/scripts/files/files.controllers.ts index 2f2e86634..0c190115f 100755 --- a/app/scripts/files/files.controllers.ts +++ b/app/scripts/files/files.controllers.ts @@ -98,6 +98,7 @@ module ngApp.files.controllers { canBAMSlice(): boolean { return (this.file.data_type || '').toLowerCase() === 'aligned reads' && + (this.file.index_files || []).length != 0 && (this.file.data_format || '').toLowerCase() === 'bam'; } @@ -155,12 +156,20 @@ module ngApp.files.controllers { } class BAMFailedModalController { - msg: string = "Invalid BED Format. Please refer to the examples described in the BAM Slicing pop-up."; + errorBlobString: string; + msg400: string = "Invalid BED Format. Please refer to the examples described in the BAM Slicing pop-up."; /* @ngInject */ constructor(private $uibModalInstance, public errorStatus: string, - public errorMsg: string, - private errorBlob: any) {} + public errorStatusText: string, + private errorBlob: Blob) { + this.errorBlobString = ""; + var reader = new FileReader(); + reader.addEventListener("loadend", () => { + this.errorBlobString = _.get(JSON.parse(reader.result), "error", "Error slicing"); + }); + reader.readAsText(errorBlob); + } } angular diff --git a/app/scripts/files/files.services.ts b/app/scripts/files/files.services.ts index c4870326f..946a4b89d 100755 --- a/app/scripts/files/files.services.ts +++ b/app/scripts/files/files.services.ts @@ -95,7 +95,7 @@ module ngApp.files.services { return {}; } - sliceBAM(fileID: string, bedTSV: string, callback: any) { + sliceBAM(fileID: string, bedTSV: string, completeCallback: () => void) { var abort = this.$q.defer(); var params = this.processBED(bedTSV); this.RestFullResponse.all("/v0/slicing/view/" + fileID) @@ -107,9 +107,12 @@ module ngApp.files.services { .post(params, undefined, { 'Content-Type': 'application/json' }) .then((response) => { this.$window.saveAs(response, fileID + '-sliced.bam'); - if(callback) callback(true); - }, (response)=>{ + }, (response) => { //Slicing Failed + if (response.status === 500) { + // 500s show default app 500 error only + return; + } this.$uibModal.open({ templateUrl: 'files/templates/bam-slicing-failed.html', controller: "BAMFailedModalController", @@ -120,11 +123,15 @@ module ngApp.files.services { size: "lg", resolve: { errorStatus: () => { return response.status; }, - errorMsg: () => { return response.statusText; }, - errorBlob: () => { return response.data; } + errorStatusText: () => { return response.statusText || 'Error'; }, + errorBlob: () => { return response.data || new Blob([JSON.stringify({error: 'Unexpected Error'})]); } } }); - if(callback) callback(false); + }) + .finally(() => { + if (completeCallback) { + completeCallback(); + } }); } diff --git a/app/scripts/files/module.ts b/app/scripts/files/module.ts index 835c26c94..ffbf5dbb8 100755 --- a/app/scripts/files/module.ts +++ b/app/scripts/files/module.ts @@ -57,6 +57,7 @@ module ngApp.files { "downstream_analyses.output_files.data_format", "downstream_analyses.workflow_type", "downstream_analyses.output_files.file_size", + "index_files.file_id" ] }); } diff --git a/app/scripts/files/templates/bam-slicing-failed.html b/app/scripts/files/templates/bam-slicing-failed.html index 0d668014a..08c0272a4 100644 --- a/app/scripts/files/templates/bam-slicing-failed.html +++ b/app/scripts/files/templates/bam-slicing-failed.html @@ -2,9 +2,17 @@

    BAM Slicing Failed

    From 364d1a6014e8ad9b54ba0818ea0570bf0c5dc8d9 Mon Sep 17 00:00:00 2001 From: Christine Yu Date: Thu, 28 Apr 2016 16:11:58 -0400 Subject: [PATCH 73/80] fix(biospecimen): 2239 add title to search input Closes #2239 --- app/scripts/components/ui/biospecimen/templates/biospecimen.html | 1 + 1 file changed, 1 insertion(+) diff --git a/app/scripts/components/ui/biospecimen/templates/biospecimen.html b/app/scripts/components/ui/biospecimen/templates/biospecimen.html index 2d0b66504..1b5962e48 100644 --- a/app/scripts/components/ui/biospecimen/templates/biospecimen.html +++ b/app/scripts/components/ui/biospecimen/templates/biospecimen.html @@ -28,6 +28,7 @@

    No biospecimen found.

    Date: Thu, 28 Apr 2016 11:20:52 -0400 Subject: [PATCH 74/80] fix(cart): 2222 no undefined in notifications -Bug was 'Removed undefined' appearing instead of 'Removed [file_name]' when 1 unauthorized file removed. CartService doesn't have file_name stored, and can't think of a nice way to get the file name because CartController only has 1 page of names as well. So bandaid solution, show '1 file' instead of undefined. Closes #2222 --- app/scripts/cart/cart.services.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/scripts/cart/cart.services.ts b/app/scripts/cart/cart.services.ts index 736e2a1eb..9fc604266 100644 --- a/app/scripts/cart/cart.services.ts +++ b/app/scripts/cart/cart.services.ts @@ -182,7 +182,7 @@ module ngApp.cart.services { } getUnauthorizedFiles(): IFile[] { - return this.files.filter((file)=>{ + return this.files.filter( (file) => { return !this.UserService.userCanDownloadFile(file); }); } @@ -269,7 +269,7 @@ module ngApp.cart.services { buildAddedMsg(added: Array, alreadyIn: Array): string { var message = this.gettextCatalog.getPlural(added.length, - "Added " + _.get(_.first(added), "file_name") + " to the cart.", + "Added " + _.get(_.first(added), "file_name", "1 file") + " to the cart.", "Added " + added.length + " files to the cart."); if (alreadyIn.length) { @@ -286,7 +286,7 @@ module ngApp.cart.services { buildRemovedMsg(removedFiles: IFile[]): string { var message = this.gettextCatalog.getPlural(removedFiles.length, - "Removed " + _.get(_.first(removedFiles), "file_name") + " from the cart.", + "Removed " + _.get(_.first(removedFiles), "file_name", "1 file") + " from the cart.", "Removed " + removedFiles.length + " files from the cart."); if (removedFiles.length !== 0) { @@ -306,7 +306,7 @@ module ngApp.cart.services { return { remaining: acc.remaining, removed: acc.removed.concat(fileToRemove)}; } return { remaining: acc.remaining.concat(f), removed: acc.removed}; - } ,{ remaining: [], removed: [] }); + } , { remaining: [], removed: [] }); this.lastModifiedFiles = partitioned.removed; this.notify.closeAll(); this.notify({ From d9fd0af7629c26176ebb61cdc64abfbd87982d67 Mon Sep 17 00:00:00 2001 From: Shane Wilson Date: Wed, 27 Apr 2016 14:34:40 -0400 Subject: [PATCH 75/80] feat(app): remove direct download links for files - Make direct download links less obvious - people should be using the cart to download multiple items Closes #2162 --- app/scripts/cart/cart.table.model.ts | 3 +-- app/scripts/cart/templates/add-to-cart-all-dropdown.html | 2 +- app/scripts/cart/templates/add-to-cart-button-single.html | 8 +------- app/scripts/search/search.files.table.model.ts | 3 +-- 4 files changed, 4 insertions(+), 12 deletions(-) diff --git a/app/scripts/cart/cart.table.model.ts b/app/scripts/cart/cart.table.model.ts index 58b7a0d1a..4d6ab8c1d 100644 --- a/app/scripts/cart/cart.table.model.ts +++ b/app/scripts/cart/cart.table.model.ts @@ -20,8 +20,7 @@ module ngApp.cart.models { { name: "Action", id: "file_actions", - td: row => '' + - '', + td: row => '', tdClassName: "text-center" },{ name: "My Projects", diff --git a/app/scripts/cart/templates/add-to-cart-all-dropdown.html b/app/scripts/cart/templates/add-to-cart-all-dropdown.html index 5484da561..3f8bcc737 100644 --- a/app/scripts/cart/templates/add-to-cart-all-dropdown.html +++ b/app/scripts/cart/templates/add-to-cart-all-dropdown.html @@ -1,4 +1,4 @@ -
    +
    From f70b9485dbab8a6e9c84b07d33a38ef94221ef08 Mon Sep 17 00:00:00 2001 From: Terry Lin Date: Wed, 27 Apr 2016 18:09:32 -0400 Subject: [PATCH 78/80] fix(table): 2229 update table column layout Closes #2229 --- app/scripts/core/module.ts | 2 +- app/scripts/projects/projects.table.service.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/scripts/core/module.ts b/app/scripts/core/module.ts index ae407128f..280a513c5 100644 --- a/app/scripts/core/module.ts +++ b/app/scripts/core/module.ts @@ -14,5 +14,5 @@ angular SNV: { full: "Simple Nucleotide Variation", abbr: "SNV" }, CNV: { full: "Copy Number Variation", abbr: "CNV" }, CLINICAL: { full: "Clinical", abbr: "Clinical" }, - BIOSPECIMEN: { full: "Biospecimen", abbr: "Biospecimen" }, + BIOSPECIMEN: { full: "Biospecimen", abbr: "Bio" }, }); diff --git a/app/scripts/projects/projects.table.service.ts b/app/scripts/projects/projects.table.service.ts index dbcbe251e..40f0247b5 100644 --- a/app/scripts/projects/projects.table.service.ts +++ b/app/scripts/projects/projects.table.service.ts @@ -203,6 +203,7 @@ module ngApp.projects.table.service { sortable: true, thClassName: 'text-right', tdClassName: 'text-right', + hidden: true, total: (data, $scope) => $scope.$filter("size")(_.sum(_.pluck(data, "summary.file_size"))) } ], From 30b610a3c3cd716441388bf54959f4d30420603c Mon Sep 17 00:00:00 2001 From: Christine Yu Date: Fri, 29 Apr 2016 14:38:20 -0400 Subject: [PATCH 79/80] fix(cart): 2113 dont clobber project ids Closes #2113 --- app/scripts/cart/cart.services.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/scripts/cart/cart.services.ts b/app/scripts/cart/cart.services.ts index 9fc604266..b9f5c2726 100644 --- a/app/scripts/cart/cart.services.ts +++ b/app/scripts/cart/cart.services.ts @@ -340,7 +340,7 @@ module ngApp.cart.services { access: f.access, file_id: f.file_id, file_size: f.file_size, - projects: _.map(f.cases, c => c.project.project_id) + projects: f.projects || _.map(f.cases, c => c.project.project_id) } }); From b1d582ecea5ceac65e9e0a474d10f4f69e978de3 Mon Sep 17 00:00:00 2001 From: Shane Wilson Date: Fri, 29 Apr 2016 16:10:11 -0400 Subject: [PATCH 80/80] chore(release): Release 0.3.24.3 --- CHANGELOG.md | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++ package.json | 2 +- 2 files changed, 103 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4cb679bb1..05a9f695c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,105 @@ + +### 0.3.24.3 (2016-04-29) + + +#### Bug Fixes + +* **annotation:** + * add tooltip to project_id ([cf2c32a8](https://github.com/NCI-GDC/portal-ui/commit/cf2c32a8), closes [PGDC-2066](https://jira.opensciencedatacloud.org/browse/PGDC-2066)) + * remove annotator ([d07075d6](https://github.com/NCI-GDC/portal-ui/commit/d07075d6), closes [PGDC-2106](https://jira.opensciencedatacloud.org/browse/PGDC-2106)) +* **app:** + * 2201 data_category > summary cards ([e59ffa2f](https://github.com/NCI-GDC/portal-ui/commit/e59ffa2f), closes [PGDC-2201](https://jira.opensciencedatacloud.org/browse/PGDC-2201)) + * 2073 hide git links in footer ([cb15d763](https://github.com/NCI-GDC/portal-ui/commit/cb15d763), closes [PGDC-2073](https://jira.opensciencedatacloud.org/browse/PGDC-2073)) + * 2095 round mb to 2 decimal places ([539b686d](https://github.com/NCI-GDC/portal-ui/commit/539b686d), closes [PGDC-2095](https://jira.opensciencedatacloud.org/browse/PGDC-2095)) + * don't use expand whenever possible ([3afc1934](https://github.com/NCI-GDC/portal-ui/commit/3afc1934), closes [PGDC-2023](https://jira.opensciencedatacloud.org/browse/PGDC-2023)) +* **bam:** 1888 error handling tweaks ([e7f2d13e](https://github.com/NCI-GDC/portal-ui/commit/e7f2d13e), closes [PGDC-1888](https://jira.opensciencedatacloud.org/browse/PGDC-1888)) +* **biospecimen:** 2239 add title to search input ([364d1a60](https://github.com/NCI-GDC/portal-ui/commit/364d1a60), closes [PGDC-2239](https://jira.opensciencedatacloud.org/browse/PGDC-2239)) +* **cart:** + * 2113 dont clobber project ids ([30b610a3](https://github.com/NCI-GDC/portal-ui/commit/30b610a3), closes [PGDC-2113](https://jira.opensciencedatacloud.org/browse/PGDC-2113)) + * 2222 no undefined in notifications ([ca6efd95](https://github.com/NCI-GDC/portal-ui/commit/ca6efd95), closes [PGDC-2222](https://jira.opensciencedatacloud.org/browse/PGDC-2222)) + * 2161 download metadata_files ([b614f352](https://github.com/NCI-GDC/portal-ui/commit/b614f352), closes [PGDC-2161](https://jira.opensciencedatacloud.org/browse/PGDC-2161)) + * gather files in click handler ([4466c959](https://github.com/NCI-GDC/portal-ui/commit/4466c959)) + * 2063 add all files off by one bug ([bdb0f455](https://github.com/NCI-GDC/portal-ui/commit/bdb0f455), closes [PGDC-2063](https://jira.opensciencedatacloud.org/browse/PGDC-2063)) + * 1952 update cart limit warning ([ca3bb8a8](https://github.com/NCI-GDC/portal-ui/commit/ca3bb8a8), closes [PGDC-1952](https://jira.opensciencedatacloud.org/browse/PGDC-1952)) + * 'No Files' when no files ([4f6053de](https://github.com/NCI-GDC/portal-ui/commit/4f6053de), closes [PGDC-1981](https://jira.opensciencedatacloud.org/browse/PGDC-1981)) + * check for controlled files on click ([8de8c587](https://github.com/NCI-GDC/portal-ui/commit/8de8c587), closes [PGDC-2086](https://jira.opensciencedatacloud.org/browse/PGDC-2086)) +* **case:** + * 2199 better display for clinical data ([31ed1ecb](https://github.com/NCI-GDC/portal-ui/commit/31ed1ecb), closes [PGDC-2199](https://jira.opensciencedatacloud.org/browse/PGDC-2199)) + * 2134 minor issues in case entity ([1facc757](https://github.com/NCI-GDC/portal-ui/commit/1facc757), closes [PGDC-2134](https://jira.opensciencedatacloud.org/browse/PGDC-2134)) +* **chart:** make barchart labels more readable ([38543a39](https://github.com/NCI-GDC/portal-ui/commit/38543a39), closes [PGDC-2042](https://jira.opensciencedatacloud.org/browse/PGDC-2042)) +* **charts:** remove undefined fn call ([5356b82e](https://github.com/NCI-GDC/portal-ui/commit/5356b82e), closes [PGDC-2197](https://jira.opensciencedatacloud.org/browse/PGDC-2197)) +* **chore:** 2163 null-safety when calling #some ([05d4462e](https://github.com/NCI-GDC/portal-ui/commit/05d4462e), closes [PGDC-2163](https://jira.opensciencedatacloud.org/browse/PGDC-2163)) +* **components:** + * 2181 don't humanify fields ([48276153](https://github.com/NCI-GDC/portal-ui/commit/48276153), closes [PGDC-2181](https://jira.opensciencedatacloud.org/browse/PGDC-2181)) + * add track by for facetConfig ([ac275683](https://github.com/NCI-GDC/portal-ui/commit/ac275683)) + * handle empty fields in gql/facets ([1078fae0](https://github.com/NCI-GDC/portal-ui/commit/1078fae0), closes [PGDC-2126](https://jira.opensciencedatacloud.org/browse/PGDC-2126), [PGDC-2124](https://jira.opensciencedatacloud.org/browse/PGDC-2124)) + * if blacklist exists then filter ([b863ba49](https://github.com/NCI-GDC/portal-ui/commit/b863ba49)) + * 2067 remove GO btn from prefix ([32e75c52](https://github.com/NCI-GDC/portal-ui/commit/32e75c52), closes [PGDC-2067](https://jira.opensciencedatacloud.org/browse/PGDC-2067)) +* **css:** 2150 gdc-app menu layout issue in IE ([3056b212](https://github.com/NCI-GDC/portal-ui/commit/3056b212), closes [PGDC-2150](https://jira.opensciencedatacloud.org/browse/PGDC-2150)) +* **download:** 2056 displays progress in button ([b031a942](https://github.com/NCI-GDC/portal-ui/commit/b031a942), closes [PGDC-2056](https://jira.opensciencedatacloud.org/browse/PGDC-2056)) +* **entity:** + * 2136 displays treatments ([8bc81964](https://github.com/NCI-GDC/portal-ui/commit/8bc81964), closes [PGDC-2136](https://jira.opensciencedatacloud.org/browse/PGDC-2136)) + * 2039 double dash when id is null ([a4c62b39](https://github.com/NCI-GDC/portal-ui/commit/a4c62b39), closes [PGDC-2039](https://jira.opensciencedatacloud.org/browse/PGDC-2039)) +* **exportTable:** 2220 include case_id ([b26021b6](https://github.com/NCI-GDC/portal-ui/commit/b26021b6), closes [PGDC-2220](https://jira.opensciencedatacloud.org/browse/PGDC-2220)) +* **facet:** + * 2171 custom facet not added in IE ([9596437d](https://github.com/NCI-GDC/portal-ui/commit/9596437d), closes [PGDC-2171](https://jira.opensciencedatacloud.org/browse/PGDC-2171)) + * ignored missing in facets ([26920a00](https://github.com/NCI-GDC/portal-ui/commit/26920a00), closes [PGDC-2069](https://jira.opensciencedatacloud.org/browse/PGDC-2069)) +* **file:** + * 2198 displays file data as is ([636716eb](https://github.com/NCI-GDC/portal-ui/commit/636716eb), closes [PGDC-2198](https://jira.opensciencedatacloud.org/browse/PGDC-2198)) + * 2140 remove date fields from table ([fc69f838](https://github.com/NCI-GDC/portal-ui/commit/fc69f838), closes [PGDC-2140](https://jira.opensciencedatacloud.org/browse/PGDC-2140)) +* **gdctable:** never mutate config.headings ([fdb72e08](https://github.com/NCI-GDC/portal-ui/commit/fdb72e08), closes [PGDC-1769](https://jira.opensciencedatacloud.org/browse/PGDC-1769)) +* **git:** 2241 reinstated commit info ([a17f9707](https://github.com/NCI-GDC/portal-ui/commit/a17f9707), closes [PGDC-2241](https://jira.opensciencedatacloud.org/browse/PGDC-2241)) +* **githut:** + * 2164 link add data_category filter ([9a797c38](https://github.com/NCI-GDC/portal-ui/commit/9a797c38), closes [PGDC-2164](https://jira.opensciencedatacloud.org/browse/PGDC-2164)) + * handle NaN values ([75d5cdba](https://github.com/NCI-GDC/portal-ui/commit/75d5cdba)) +* **gql:** autocomplete with all OP by default ([416045b3](https://github.com/NCI-GDC/portal-ui/commit/416045b3), closes [PGDC-2195](https://jira.opensciencedatacloud.org/browse/PGDC-2195)) +* **header:** + * 2224 remove reports link ([b04663c6](https://github.com/NCI-GDC/portal-ui/commit/b04663c6), closes [PGDC-2224](https://jira.opensciencedatacloud.org/browse/PGDC-2224)) + * use flexbox for gdc-apps-menu ([e402b168](https://github.com/NCI-GDC/portal-ui/commit/e402b168), closes [PGDC-1933](https://jira.opensciencedatacloud.org/browse/PGDC-1933)) +* **home:** + * update infra numbers ([8445c804](https://github.com/NCI-GDC/portal-ui/commit/8445c804), closes [PGDC-2234](https://jira.opensciencedatacloud.org/browse/PGDC-2234)) + * 2178 adjust queries ([1dffaf61](https://github.com/NCI-GDC/portal-ui/commit/1dffaf61), closes [PGDC-2178](https://jira.opensciencedatacloud.org/browse/PGDC-2178)) +* **login:** + * 2221 retain my-project toggle state ([b373a26e](https://github.com/NCI-GDC/portal-ui/commit/b373a26e), closes [PGDC-2221](https://jira.opensciencedatacloud.org/browse/PGDC-2221)) + * 2151 login not shown in IE ([ff5edebb](https://github.com/NCI-GDC/portal-ui/commit/ff5edebb), closes [PGDC-2151](https://jira.opensciencedatacloud.org/browse/PGDC-2151)) +* **projects:** 2172 missing line in facet section ([a69d1666](https://github.com/NCI-GDC/portal-ui/commit/a69d1666), closes [PGDC-2172](https://jira.opensciencedatacloud.org/browse/PGDC-2172)) +* **reports:** + * 2098 hide data category ([fefb57d4](https://github.com/NCI-GDC/portal-ui/commit/fefb57d4), closes [PGDC-2098](https://jira.opensciencedatacloud.org/browse/PGDC-2098)) + * 2173 remove export btn ([0d3a0205](https://github.com/NCI-GDC/portal-ui/commit/0d3a0205), closes [PGDC-2173](https://jira.opensciencedatacloud.org/browse/PGDC-2173)) + * 2137 handle no reports ([ad2d4d2c](https://github.com/NCI-GDC/portal-ui/commit/ad2d4d2c), closes [PGDC-2137](https://jira.opensciencedatacloud.org/browse/PGDC-2137)) +* **search:** + * remove file state from default facets ([311e764b](https://github.com/NCI-GDC/portal-ui/commit/311e764b), closes [PGDC-2208](https://jira.opensciencedatacloud.org/browse/PGDC-2208)) + * 2177 ICD-10 to Primary Diagnoses ([8e0cfba8](https://github.com/NCI-GDC/portal-ui/commit/8e0cfba8), closes [PGDC-2177](https://jira.opensciencedatacloud.org/browse/PGDC-2177)) + * fix pagination not updating ([45ffbbfb](https://github.com/NCI-GDC/portal-ui/commit/45ffbbfb), closes [PGDC-2185](https://jira.opensciencedatacloud.org/browse/PGDC-2185)) + * pass expands fields to query ([1c4919c7](https://github.com/NCI-GDC/portal-ui/commit/1c4919c7)) + * all facets open by default ([d34f69f6](https://github.com/NCI-GDC/portal-ui/commit/d34f69f6), closes [PGDC-2061](https://jira.opensciencedatacloud.org/browse/PGDC-2061)) +* **table:** 2229 update table column layout ([f70b9485](https://github.com/NCI-GDC/portal-ui/commit/f70b9485), closes [PGDC-2229](https://jira.opensciencedatacloud.org/browse/PGDC-2229)) +* **tables:** disable export > 2000 rows, exts ([e12dd529](https://github.com/NCI-GDC/portal-ui/commit/e12dd529), closes [PGDC-2071](https://jira.opensciencedatacloud.org/browse/PGDC-2071)) + + +#### Features + +* **app:** + * remove direct download links for files ([d9fd0af7](https://github.com/NCI-GDC/portal-ui/commit/d9fd0af7), closes [PGDC-2162](https://jira.opensciencedatacloud.org/browse/PGDC-2162)) + * 1755 title case for data category ([58ca6f7c](https://github.com/NCI-GDC/portal-ui/commit/58ca6f7c), closes [PGDC-1755](https://jira.opensciencedatacloud.org/browse/PGDC-1755)) + * 2066 tooltips ([475725b9](https://github.com/NCI-GDC/portal-ui/commit/475725b9), closes [PGDC-2066](https://jira.opensciencedatacloud.org/browse/PGDC-2066)) + * blacklist data_categories in summary ([0a464140](https://github.com/NCI-GDC/portal-ui/commit/0a464140)) + * update data_category fields ([e3467b9c](https://github.com/NCI-GDC/portal-ui/commit/e3467b9c), closes [PGDC-1755](https://jira.opensciencedatacloud.org/browse/PGDC-1755)) + * add no js text ([8e069e65](https://github.com/NCI-GDC/portal-ui/commit/8e069e65)) + * 2067 update id search facet text ([1ade49c0](https://github.com/NCI-GDC/portal-ui/commit/1ade49c0), closes [PGDC-2067](https://jira.opensciencedatacloud.org/browse/PGDC-2067)) +* **components:** + * file.submitter_id > quicksearch ([6aa13b34](https://github.com/NCI-GDC/portal-ui/commit/6aa13b34), closes [PGDC-1792](https://jira.opensciencedatacloud.org/browse/PGDC-1792)) + * search bio id fields in tree ([3afd2127](https://github.com/NCI-GDC/portal-ui/commit/3afd2127)) +* **facets:** use max, min don't show bar graph ([6d0c2a55](https://github.com/NCI-GDC/portal-ui/commit/6d0c2a55), closes [PGDC-2097](https://jira.opensciencedatacloud.org/browse/PGDC-2097)) +* **file:** + * 2170 add workflow facet ([d3b3b956](https://github.com/NCI-GDC/portal-ui/commit/d3b3b956), closes [PGDC-2170](https://jira.opensciencedatacloud.org/browse/PGDC-2170)) + * update genome name to GRCh38.d1.vd1 ([15a7de4e](https://github.com/NCI-GDC/portal-ui/commit/15a7de4e)) + * downstream_analyses ([4123d50a](https://github.com/NCI-GDC/portal-ui/commit/4123d50a)) + * 1470 entity pg updates ([75637e23](https://github.com/NCI-GDC/portal-ui/commit/75637e23), closes [PGDC-1470](https://jira.opensciencedatacloud.org/browse/PGDC-1470)) +* **gql:** 1045 support mapping description ([8baede1a](https://github.com/NCI-GDC/portal-ui/commit/8baede1a), closes [PGDC-1045](https://jira.opensciencedatacloud.org/browse/PGDC-1045)) +* **reports:** update fields ([f444fe99](https://github.com/NCI-GDC/portal-ui/commit/f444fe99)) + + ### 0.3.24.2 (2016-04-04) diff --git a/package.json b/package.json index abf747059..c496c2ca6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "author": "OICR", "name": "gdc-portal-ui", - "version": "0.3.24-spr5", + "version": "0.3.24.3", "homepage": "", "description": "", "repository": "https://github.com/NCI-GDC/portal-ui",