From dc205ba6ab2351550730b4b381ca25969de99d14 Mon Sep 17 00:00:00 2001 From: Chenxin Wang Date: Wed, 23 Oct 2024 15:02:04 -0500 Subject: [PATCH 1/3] fix design audit --- .../cluster-scatterplot.component.html | 8 +++--- .../cluster-scatterplot.component.scss | 6 ++--- .../cluster-scatterplot.component.ts | 18 ++++++++++++- .../molecule2d/molecule2d.component.scss | 6 ----- .../molli/molecule2d/molecule2d.component.ts | 9 ++++--- .../molli/results/results.component.html | 10 ++++---- .../molli/results/results.component.scss | 7 +++--- .../molli/results/results.component.ts | 25 ++++++++++++++++--- 8 files changed, 60 insertions(+), 29 deletions(-) diff --git a/src/app/components/molli/cluster-scatterplot/cluster-scatterplot.component.html b/src/app/components/molli/cluster-scatterplot/cluster-scatterplot.component.html index 68b66cd..345d480 100644 --- a/src/app/components/molli/cluster-scatterplot/cluster-scatterplot.component.html +++ b/src/app/components/molli/cluster-scatterplot/cluster-scatterplot.component.html @@ -2,14 +2,16 @@
- + + View All
- + +
{{ cluster.index }}
@@ -56,7 +58,7 @@
- +
diff --git a/src/app/components/molli/cluster-scatterplot/cluster-scatterplot.component.scss b/src/app/components/molli/cluster-scatterplot/cluster-scatterplot.component.scss index 34e0213..b8b5d11 100644 --- a/src/app/components/molli/cluster-scatterplot/cluster-scatterplot.component.scss +++ b/src/app/components/molli/cluster-scatterplot/cluster-scatterplot.component.scss @@ -86,7 +86,7 @@ svg { .filler { background-color: #f7f8f9; - height: 130px; + height: 120px; .focus_restricted { height: 20px; @@ -102,19 +102,17 @@ svg { .focus_item { width: 408px; - height: 130px; background-color: #ffffff; border: 1px solid #dee2e6; border-radius: 6px; .focus_content { - padding: 6px 12px 0 12px; + padding: 12px; } .focus_point_container { width: 247px; - height: 79px; } .foucs_info_item { diff --git a/src/app/components/molli/cluster-scatterplot/cluster-scatterplot.component.ts b/src/app/components/molli/cluster-scatterplot/cluster-scatterplot.component.ts index 8e2b093..35d7e66 100644 --- a/src/app/components/molli/cluster-scatterplot/cluster-scatterplot.component.ts +++ b/src/app/components/molli/cluster-scatterplot/cluster-scatterplot.component.ts @@ -30,16 +30,21 @@ export class ClusterScatterplotComponent implements OnChanges { mode: 'tsne'|'pca'; highlightedClusterIndex: number|null = null; + @Input() highlightedPointName: string|null = null; @Output() highlightedPointNameChange = new EventEmitter(); + // check if the point/examplar is restricted to select/unselect by additional filters @Input() checkRestrict: (name: string) => Boolean; + @Input() handleScroll: (name: string, navigate?: boolean) => void; + lastClickedPointName: string|null = null; + viewBox = { height: 400, width: 400 @@ -187,7 +192,7 @@ export class ClusterScatterplotComponent implements OnChanges { toggleAllCluster() { this.allClusterSelected = this.allClusterSelected == 1 ? 0 : 1; this.clusters.forEach(cluster => cluster.isSelected = this.allClusterSelected); - this.points.forEach(point => point.isSelected = !!this.allClusterSelected); + this.points.forEach(point => point.isSelected = !!this.allClusterSelected); this.onPointsChange(); } @@ -210,6 +215,17 @@ export class ClusterScatterplotComponent implements OnChanges { if (this.checkRestrict(point.name)) { return; } + + // if it's the first time the point is clicked, just scoll to it + if (point.isSelected && this.lastClickedPointName != point.name) { + this.lastClickedPointName = point.name; + setTimeout(() => { + this.handleScroll(point.name, true); + }); + return + } + + // not the first time, toggle point point.isSelected = !point.isSelected; if (point.cluster.isSelected == 2) { const selectedPointsCntInCluster = this.getSelectedPointsCntInCluster(point.cluster); diff --git a/src/app/components/molli/molecule2d/molecule2d.component.scss b/src/app/components/molli/molecule2d/molecule2d.component.scss index 9d18b4e..e69de29 100644 --- a/src/app/components/molli/molecule2d/molecule2d.component.scss +++ b/src/app/components/molli/molecule2d/molecule2d.component.scss @@ -1,6 +0,0 @@ -.svg_container { - ::ng-deep svg { - display: block; - margin: auto; - } -} diff --git a/src/app/components/molli/molecule2d/molecule2d.component.ts b/src/app/components/molli/molecule2d/molecule2d.component.ts index 6813b45..a1961a1 100644 --- a/src/app/components/molli/molecule2d/molecule2d.component.ts +++ b/src/app/components/molli/molecule2d/molecule2d.component.ts @@ -23,15 +23,18 @@ export class Molecule2dComponent implements OnChanges { ngOnChanges(changes: SimpleChanges) { let workingSvg = this.svg; - if (this.height !== null) { + if (this.height != null) { // replacing just the first instance of height, and for now we assume all heights are originally 200px // TODO improve this logic workingSvg = workingSvg.replace('height="200px"', 'height="' + this.height + 'px"'); + if (this.height < 200) { + workingSvg = workingSvg.replace('viewBox="0 0 100 100"', 'viewBox="0 25 100 50"') + } } - if (this.width !== null) { + if (this.width != null) { // replacing just the first instance of width, and for now we assume all widths are originally 200px // TODO improve this logic - workingSvg = workingSvg.replace('width="200px"', 'width="' + this.height + 'px"'); + workingSvg = workingSvg.replace('width="200px"', 'width="' + this.width + 'px"'); } this.scaledSvg = this.sanitizer.bypassSecurityTrustHtml(workingSvg); } diff --git a/src/app/components/molli/results/results.component.html b/src/app/components/molli/results/results.component.html index fb8bb52..89035c1 100644 --- a/src/app/components/molli/results/results.component.html +++ b/src/app/components/molli/results/results.component.html @@ -56,16 +56,16 @@

Data clustering

Molecules

Cores:

-

Substituents:

-

Other filters:

- +
@@ -76,7 +76,7 @@

Other filters:

@@ -131,7 +131,7 @@

Other filters:

{{row.cluster}} {{row.name}} -
+
{{row.core}}
{{subst.label}} ({{subst.count}})
diff --git a/src/app/components/molli/results/results.component.scss b/src/app/components/molli/results/results.component.scss index e88bb9a..82f0f81 100644 --- a/src/app/components/molli/results/results.component.scss +++ b/src/app/components/molli/results/results.component.scss @@ -261,10 +261,11 @@ tr.highlighted { } td { - vertical-align: middle; - padding: 7px 16px !important; + vertical-align: top; + padding: 5px !important; - &.structure_2d { + .structure_2d { + margin-top: 6px; &:hover { cursor: pointer; diff --git a/src/app/components/molli/results/results.component.ts b/src/app/components/molli/results/results.component.ts index 0854722..6e2f500 100644 --- a/src/app/components/molli/results/results.component.ts +++ b/src/app/components/molli/results/results.component.ts @@ -33,6 +33,8 @@ export class ResultsComponent { allRows: GeneratedStructureViewModel[] = []; filteredRows: GeneratedStructureViewModel[] = []; + // number showed on filter button + filterLenth: number = 0; clusteringMethodOptions = [ { name: 't-SNE(Default)', key: 'tsne' }, @@ -229,7 +231,7 @@ export class ResultsComponent { this.selectedCores = []; this.selectedSubstituents = []; this.isShowSavedMoleculesOnly = false; - this.filterTable(); + this.filterTable(true); } resetTable() { @@ -237,7 +239,7 @@ export class ResultsComponent { this.selectedSubstituents = []; this.isShowSavedMoleculesOnly = false; this.selectedPoints = this.allRows.map(row => row.name); - this.filterTable(); + this.filterTable(true); } applyAdditionalFilters(row: GeneratedStructureViewModel) { @@ -253,8 +255,23 @@ export class ResultsComponent { return coreLookup.has(row.core) && row.substituents.some(subst => substituentLookup.has(subst.label)) && saveMoleculesLookup(row); } - filterTable() { - this.filteredRows = this.allRows.filter(row => this.selectedPoints.includes(row.name) && this.applyAdditionalFilters(row)); + filterTable(isApplyAdditionalFilters = false) { + let additionalFilterResultLen = 0; + this.filteredRows = this.allRows.filter(row => { + if (this.applyAdditionalFilters(row)) { + if (this.selectedCores.length || this.selectedSubstituents.length) { + additionalFilterResultLen++; + } + if (this.selectedPoints.includes(row.name)) { + return true; + } + } + return false; + }) + this.filterLenth = Math.min(additionalFilterResultLen, this.filteredRows.length); + if (isApplyAdditionalFilters) { + this.table.first = 0; + } } isPointRestrictedByFilters(pointName: string) { From 1ce1a868c08ac404ae2288dd2b696616fb310a35 Mon Sep 17 00:00:00 2001 From: Chenxin Wang Date: Wed, 30 Oct 2024 15:18:03 -0500 Subject: [PATCH 2/3] fix typo --- .../cluster-scatterplot/cluster-scatterplot.component.ts | 8 ++------ src/app/components/molli/results/results.component.html | 2 +- src/app/components/molli/results/results.component.ts | 4 ++-- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/app/components/molli/cluster-scatterplot/cluster-scatterplot.component.ts b/src/app/components/molli/cluster-scatterplot/cluster-scatterplot.component.ts index 35d7e66..4b33b45 100644 --- a/src/app/components/molli/cluster-scatterplot/cluster-scatterplot.component.ts +++ b/src/app/components/molli/cluster-scatterplot/cluster-scatterplot.component.ts @@ -219,9 +219,7 @@ export class ClusterScatterplotComponent implements OnChanges { // if it's the first time the point is clicked, just scoll to it if (point.isSelected && this.lastClickedPointName != point.name) { this.lastClickedPointName = point.name; - setTimeout(() => { - this.handleScroll(point.name, true); - }); + this.handleScroll(point.name, true); return } @@ -243,9 +241,7 @@ export class ClusterScatterplotComponent implements OnChanges { } this.onPointsChange(); if (point.isSelected) { - setTimeout(() => { - this.handleScroll(point.name, true); - }); + this.handleScroll(point.name, true); } } diff --git a/src/app/components/molli/results/results.component.html b/src/app/components/molli/results/results.component.html index 89035c1..3425d32 100644 --- a/src/app/components/molli/results/results.component.html +++ b/src/app/components/molli/results/results.component.html @@ -76,7 +76,7 @@

Other filters:

diff --git a/src/app/components/molli/results/results.component.ts b/src/app/components/molli/results/results.component.ts index 6e2f500..65756b4 100644 --- a/src/app/components/molli/results/results.component.ts +++ b/src/app/components/molli/results/results.component.ts @@ -34,7 +34,7 @@ export class ResultsComponent { allRows: GeneratedStructureViewModel[] = []; filteredRows: GeneratedStructureViewModel[] = []; // number showed on filter button - filterLenth: number = 0; + filterLength: number = 0; clusteringMethodOptions = [ { name: 't-SNE(Default)', key: 'tsne' }, @@ -268,7 +268,7 @@ export class ResultsComponent { } return false; }) - this.filterLenth = Math.min(additionalFilterResultLen, this.filteredRows.length); + this.filterLength = Math.min(additionalFilterResultLen, this.filteredRows.length); if (isApplyAdditionalFilters) { this.table.first = 0; } From 7a8d0447c63f67ef02f27e6b8665282434892d6e Mon Sep 17 00:00:00 2001 From: Chenxin Wang Date: Wed, 6 Nov 2024 16:58:08 -0600 Subject: [PATCH 3/3] fix interaction between additional filter and cluster legend --- .../cluster-scatterplot.component.html | 15 ++++-- .../cluster-scatterplot.component.scss | 2 +- .../cluster-scatterplot.component.ts | 49 +++++++------------ .../molli/results/results.component.scss | 8 ++- 4 files changed, 35 insertions(+), 39 deletions(-) diff --git a/src/app/components/molli/cluster-scatterplot/cluster-scatterplot.component.html b/src/app/components/molli/cluster-scatterplot/cluster-scatterplot.component.html index 345d480..73cacb5 100644 --- a/src/app/components/molli/cluster-scatterplot/cluster-scatterplot.component.html +++ b/src/app/components/molli/cluster-scatterplot/cluster-scatterplot.component.html @@ -2,17 +2,22 @@
- - + View All
- - - + + + + + + + + +
{{ cluster.index }}
diff --git a/src/app/components/molli/cluster-scatterplot/cluster-scatterplot.component.scss b/src/app/components/molli/cluster-scatterplot/cluster-scatterplot.component.scss index b8b5d11..26a1e95 100644 --- a/src/app/components/molli/cluster-scatterplot/cluster-scatterplot.component.scss +++ b/src/app/components/molli/cluster-scatterplot/cluster-scatterplot.component.scss @@ -132,7 +132,7 @@ svg { } .cluster_desc { - margin-left: 5px; + margin-left: 2px; font-family: Inter; font-size: 11px; font-style: italic; diff --git a/src/app/components/molli/cluster-scatterplot/cluster-scatterplot.component.ts b/src/app/components/molli/cluster-scatterplot/cluster-scatterplot.component.ts index 4b33b45..2e3cad8 100644 --- a/src/app/components/molli/cluster-scatterplot/cluster-scatterplot.component.ts +++ b/src/app/components/molli/cluster-scatterplot/cluster-scatterplot.component.ts @@ -70,8 +70,12 @@ export class ClusterScatterplotComponent implements OnChanges { "#BB772B", "#AD2828", "#136C34", "#268FB0", "#5C2F88" ]; + get allClusterSelected() { + const filtered = this.points.filter(point => point.isSelected && !this.checkRestrict(point.name)); + return filtered.length == this.points.length; + }; + // 0: unselected, 1: selected, 2: partially selected - allClusterSelected = 1; selectedClusterPath = [ { path: "M10.6667 1.33333V10.6667H1.33333V1.33333H10.6667ZM10.6667 0H1.33333C0.6 0 0 0.6 0 1.33333V10.6667C0 11.4 0.6 12 1.33333 12H10.6667C11.4 12 12 11.4 12 10.6667V1.33333C12 0.6 11.4 0 10.6667 0", @@ -104,7 +108,6 @@ export class ClusterScatterplotComponent implements OnChanges { // Reset-all this.points.forEach(point => point.isSelected = true); this.clusters.forEach(cluster => cluster.isSelected = 1); - this.allClusterSelected = 1; } else { // hide in the table this.points.forEach(point => point.isSelected = this.selectedPoints.includes(point.name)); @@ -118,7 +121,6 @@ export class ClusterScatterplotComponent implements OnChanges { cluster.isSelected = 2; } }) - this.onClusterChange(); } } } @@ -169,8 +171,6 @@ export class ClusterScatterplotComponent implements OnChanges { const cluster = this.clusters[exemplarNameToClusterIndex.get(exemplar.name)!]; cluster.exemplar = exemplar; }); - - this.allClusterSelected = 1; } } @@ -179,34 +179,24 @@ export class ClusterScatterplotComponent implements OnChanges { this.selectedPointsChange.emit(this.selectedPoints); } - onClusterChange() { - const seletedClusterNum = this.clusters.filter(cluster => cluster.isSelected === 1).length; - if (seletedClusterNum === 0) { - this.allClusterSelected = 0; - } - if (seletedClusterNum === this.numberOfClusters) { - this.allClusterSelected = 1; - } - } - toggleAllCluster() { - this.allClusterSelected = this.allClusterSelected == 1 ? 0 : 1; - this.clusters.forEach(cluster => cluster.isSelected = this.allClusterSelected); - this.points.forEach(point => point.isSelected = !!this.allClusterSelected); + let selected = this.allClusterSelected; + this.clusters.forEach(cluster => cluster.isSelected = selected ? 0 : 1); + this.points.forEach(point => point.isSelected = !selected); this.onPointsChange(); } toggleCluster(cluster: Cluster): void { - cluster.isSelected = cluster.isSelected == 1 ? 0 : 1; - this.points.forEach(point => { - if (point.cluster.index === cluster.index) { - point.isSelected = !!cluster.isSelected; - } - }) - if (this.allClusterSelected == 2) { - this.onClusterChange(); + if (this.allClusterSelected) { + // when under view all, only current cluster is toggled on + this.points.forEach(point => point.isSelected = point.cluster.index === cluster.index) } else { - this.allClusterSelected = 2; + cluster.isSelected = cluster.isSelected == 1 ? 0 : 1; + this.points.forEach(point => { + if (point.cluster.index === cluster.index) { + point.isSelected = !!cluster.isSelected; + } + }) } this.onPointsChange(); } @@ -229,15 +219,12 @@ export class ClusterScatterplotComponent implements OnChanges { const selectedPointsCntInCluster = this.getSelectedPointsCntInCluster(point.cluster); if (selectedPointsCntInCluster == 0) { point.cluster.isSelected = 0; - this.onClusterChange(); } if (selectedPointsCntInCluster == point.cluster.pointCount) { point.cluster.isSelected = 1; - this.onClusterChange(); } } else { point.cluster.isSelected = 2; - this.allClusterSelected = 2; } this.onPointsChange(); if (point.isSelected) { @@ -246,7 +233,7 @@ export class ClusterScatterplotComponent implements OnChanges { } getSelectedPointsCntInCluster(cluster: Cluster) { - return this.points.filter(point => point.cluster.index === cluster.index && point.isSelected).length; + return this.points.filter(point => point.cluster.index === cluster.index && point.isSelected && !this.checkRestrict(point.name)).length; } highlightCluster(cluster: Cluster): void { diff --git a/src/app/components/molli/results/results.component.scss b/src/app/components/molli/results/results.component.scss index 82f0f81..a389edf 100644 --- a/src/app/components/molli/results/results.component.scss +++ b/src/app/components/molli/results/results.component.scss @@ -260,10 +260,14 @@ tr.highlighted { background-color: #F5F9FF; } +th { + padding: 0.8rem !important; +} + td { vertical-align: top; - padding: 5px !important; - + padding: 0.8rem !important; + .structure_2d { margin-top: 6px; &:hover {