Skip to content

Commit 2db9eec

Browse files
authored
feat(model-ad): add ability to download all pinned data from a CT table (MG-451) (Sage-Bionetworks#3660)
1 parent 5d7f3f5 commit 2db9eec

26 files changed

+535
-75
lines changed

apps/model-ad/api/src/models/disease-correlation-comparison-tool.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { Schema, model } from 'mongoose';
33

44
const CorrelationResultSchema = new Schema<CorrelationResult>({
55
correlation: { type: Number, required: true },
6-
adj_p_value: { type: Number, required: true },
6+
adj_p_val: { type: Number, required: true },
77
});
88

99
const DiseaseCorrelationSchema = new Schema<DiseaseCorrelation>(

libs/explorers/comparison-tool/src/lib/comparison-tool-controls/comparison-tool-column-selector/comparison-tool-column-selector.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
tooltipPosition="top"
2626
tooltipStyleClass="tooltip-xs"
2727
>
28-
<p-overlaybadge severity="warn" [badgeDisabled]="!hasHiddenColumns()">
28+
<p-overlaybadge severity="warn" [badgeDisabled]="!hasUnselectedColumns()">
2929
<explorers-svg-icon
3030
imagePath="/explorers-assets/icons/column.svg"
3131
[width]="20"

libs/explorers/comparison-tool/src/lib/comparison-tool-controls/comparison-tool-column-selector/comparison-tool-column-selector.component.spec.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,10 @@ describe('ComparisonToolColumnSelectorComponent', () => {
5858
expect(icon).toBeInTheDocument();
5959
});
6060

61-
it('should show overlay badge when there are hidden columns', async () => {
61+
it('should show overlay badge when there are unselected columns', async () => {
6262
const { service } = await setup();
6363

64-
// Toggle a column to hide it
64+
// Toggle a column to unselect it
6565
const columns = service.columns();
6666
if (columns.length > 0) {
6767
service.toggleColumn(columns[0]);
@@ -70,20 +70,20 @@ describe('ComparisonToolColumnSelectorComponent', () => {
7070
// Wait for re-render
7171
await screen.findByRole('button');
7272

73-
expect(service.hasHiddenColumns()).toBe(true);
73+
expect(service.hasUnselectedColumns()).toBe(true);
7474
});
75-
it('should not show overlay badge when all columns are visible', async () => {
75+
it('should not show overlay badge when all columns are selected', async () => {
7676
const { service } = await setup();
7777

78-
// Ensure all columns are visible
78+
// Ensure all columns are selected
7979
const columns = service.columns();
8080
columns.forEach((col) => {
8181
if (!col.selected) {
8282
service.toggleColumn(col);
8383
}
8484
});
8585

86-
expect(service.hasHiddenColumns()).toBe(false);
86+
expect(service.hasUnselectedColumns()).toBe(false);
8787
});
8888

8989
it('should open popover when button is clicked', async () => {
@@ -331,8 +331,8 @@ describe('ComparisonToolColumnSelectorComponent', () => {
331331
// Test that getter returns service columns
332332
expect(instance.columns).toBe(service.columns());
333333

334-
// Test that hasHiddenColumns returns correct value
335-
expect(instance.hasHiddenColumns()).toBe(service.hasHiddenColumns());
334+
// Test that hasUnselectedColumns returns correct value
335+
expect(instance.hasUnselectedColumns()).toBe(service.hasUnselectedColumns());
336336
});
337337

338338
it('should update UI when columns change in service', async () => {

libs/explorers/comparison-tool/src/lib/comparison-tool-controls/comparison-tool-column-selector/comparison-tool-column-selector.component.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export class ComparisonToolColumnSelectorComponent {
2424
this.comparisonToolService.toggleColumn(column);
2525
}
2626

27-
hasHiddenColumns() {
28-
return this.comparisonToolService.hasHiddenColumns();
27+
hasUnselectedColumns() {
28+
return this.comparisonToolService.hasUnselectedColumns();
2929
}
3030
}

libs/explorers/comparison-tool/src/lib/comparison-tool-table/base-table/base-table.component.spec.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,6 @@ describe('BaseTableComponent', () => {
4444
it('should render table rows with text content', async () => {
4545
await setup();
4646

47-
const modelTypes = screen.getAllByText('Familial AD');
48-
expect(modelTypes.length).toBeGreaterThan(0);
49-
5047
const ageCells = screen.getAllByText('12 months');
5148
expect(ageCells.length).toBeGreaterThan(0);
5249

libs/explorers/comparison-tool/src/lib/comparison-tool-table/comparison-tool-table.component.html

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,34 @@
11
<div class="comparison-tool-table" #table>
2-
<explorers-comparison-tool-columns [columnWidth]="columnWidth" />
2+
<div class="table-header-and-pinned" #tableHeaderAndPinned>
3+
<explorers-comparison-tool-columns [columnWidth]="columnWidth" />
34

4-
@if (pinnedResultsCount() > 0) {
5-
<div class="table-divider table-divider-1">
6-
<div class="table-divider-inner">
7-
<div id="pinned-genes-header">
8-
<span> Pinned Items ({{ pinnedResultsCount() }}/{{ maxPinnedItems() }}) </span>
9-
</div>
10-
<div class="pinned-items-controls">
11-
<button (click)="downloadPinned()" class="csv-download-button">
12-
<explorers-svg-icon
13-
imagePath="/explorers-assets/icons/download.svg"
14-
altText="download"
15-
[enableHoverEffects]="true"
5+
@if (pinnedResultsCount() > 0) {
6+
<div class="table-divider table-divider-1">
7+
<div class="table-divider-inner">
8+
<div id="pinned-genes-header">
9+
<span> Pinned Items ({{ pinnedResultsCount() }}/{{ maxPinnedItems() }}) </span>
10+
</div>
11+
<div class="pinned-items-controls">
12+
<explorers-download-dom-image
13+
[target]="tableHeaderAndPinned"
14+
[filename]="getPinnedDataFilename()"
15+
[hasCsvDownload]="true"
16+
[data]="getPinnedDataForCsv()"
17+
[buttonLabel]="'Download'"
18+
[heading]="'Download all results as:'"
1619
/>
17-
Download
18-
</button>
19-
<button (click)="clearAllPinned()" class="clear-all-button">Clear All</button>
20+
<button (click)="clearAllPinned()" class="clear-all-button">Clear All</button>
21+
</div>
2022
</div>
2123
</div>
22-
</div>
23-
}
24-
<explorers-base-table
25-
[data]="pinnedData()"
26-
[shouldPaginate]="false"
27-
[shouldShowNoDataMessage]="false"
28-
[columnWidth]="columnWidth"
29-
/>
24+
}
25+
<explorers-base-table
26+
[data]="pinnedData()"
27+
[shouldPaginate]="false"
28+
[shouldShowNoDataMessage]="false"
29+
[columnWidth]="columnWidth"
30+
/>
31+
</div>
3032

3133
@if (searchTerm() || hasSelectedFilters()) {
3234
<div class="table-divider">

libs/explorers/comparison-tool/src/lib/comparison-tool-table/comparison-tool-table.component.scss

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,6 @@
22
@use 'explorers/styles/src/lib/mixins';
33

44
.comparison-tool-table {
5-
button {
6-
@include mixins.reset-button;
7-
}
8-
95
.table-divider {
106
background-color: var(--color-gray-300);
117
margin-left: -44px;
@@ -46,6 +42,19 @@
4642
}
4743
}
4844

45+
.pin-all-button,
46+
.clear-all-button {
47+
@include mixins.reset-button;
48+
}
49+
50+
.base-download-dom-image-action-button {
51+
button:hover {
52+
@include mixins.link-hover;
53+
54+
background: none;
55+
}
56+
}
57+
4958
.pin-all-button,
5059
.csv-download-button {
5160
display: flex;

libs/explorers/comparison-tool/src/lib/comparison-tool-table/comparison-tool-table.component.ts

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,34 @@ import {
1010
} from '@angular/core';
1111
import {
1212
ComparisonToolFilterService,
13+
ComparisonToolHelperService,
1314
ComparisonToolService,
1415
HelperService,
1516
PlatformService,
1617
} from '@sagebionetworks/explorers/services';
18+
import { DownloadDomImageComponent } from '@sagebionetworks/explorers/ui';
1719
import { SvgIconComponent } from '@sagebionetworks/explorers/util';
1820
import { TooltipModule } from 'primeng/tooltip';
1921
import { BaseTableComponent } from './base-table/base-table.component';
2022
import { ComparisonToolColumnsComponent } from './comparison-tool-columns/comparison-tool-columns.component';
2123

2224
@Component({
2325
selector: 'explorers-comparison-tool-table',
24-
imports: [TooltipModule, ComparisonToolColumnsComponent, SvgIconComponent, BaseTableComponent],
26+
imports: [
27+
TooltipModule,
28+
ComparisonToolColumnsComponent,
29+
SvgIconComponent,
30+
BaseTableComponent,
31+
DownloadDomImageComponent,
32+
],
2533
templateUrl: './comparison-tool-table.component.html',
2634
styleUrls: ['./comparison-tool-table.component.scss'],
2735
encapsulation: ViewEncapsulation.None,
2836
})
2937
export class ComparisonToolTableComponent implements AfterViewInit {
3038
comparisonToolService = inject(ComparisonToolService);
3139
comparisonToolFilterService = inject(ComparisonToolFilterService);
40+
comparisonToolHelperService = inject(ComparisonToolHelperService);
3241
helperService = inject(HelperService);
3342
platformService = inject(PlatformService);
3443

@@ -74,7 +83,7 @@ export class ComparisonToolTableComponent implements AfterViewInit {
7483
}, 100);
7584
}
7685

77-
@HostListener('window:resize', ['$event'])
86+
@HostListener('window:resize')
7887
onWindowResize() {
7988
if (this.platformService.isBrowser) {
8089
const tableElementWidth = this.tableElement()?.nativeElement?.offsetWidth || 0;
@@ -85,8 +94,19 @@ export class ComparisonToolTableComponent implements AfterViewInit {
8594
}
8695
}
8796

88-
downloadPinned() {
89-
// TODO: MG-451
97+
getPinnedDataFilename(): string {
98+
const config = this.comparisonToolService.currentConfig();
99+
if (!config) return '';
100+
return this.comparisonToolHelperService.getComparisonToolDataFilename(config);
101+
}
102+
103+
getPinnedDataForCsv(): string[][] {
104+
const config = this.comparisonToolService.currentConfig();
105+
if (!config) return [];
106+
107+
const data = this.pinnedData();
108+
const siteUrl = window.location.origin;
109+
return this.comparisonToolHelperService.buildComparisonToolCsvRows(data, config, siteUrl);
90110
}
91111

92112
pinAll() {

libs/explorers/models/src/lib/comparison-tool.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,3 +87,8 @@ export type HeatmapCircleColorKey<T extends HeatmapCircleData> = Extract<
8787
Exclude<keyof T, 'adj_p_val'>,
8888
string
8989
>;
90+
91+
export type ComparisonToolLink = {
92+
link_text?: string;
93+
link_url?: string;
94+
};

libs/explorers/services/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
export * from './lib/breakpoint-config.service';
22
export * from './lib/comparison-tool-filter.service';
33
export * from './lib/comparison-tool-filter.service.providers';
4+
export * from './lib/comparison-tool-helper.service';
45
export * from './lib/comparison-tool.service';
56
export * from './lib/comparison-tool.service.providers';
67
export * from './lib/github.service';

0 commit comments

Comments
 (0)