Skip to content

Commit

Permalink
Merge branch 'master' into study-plots-tab
Browse files Browse the repository at this point in the history
  • Loading branch information
alisman authored Mar 21, 2024
2 parents 514c3d6 + db8d21a commit ed8ef6f
Show file tree
Hide file tree
Showing 12 changed files with 131 additions and 36 deletions.
4 changes: 0 additions & 4 deletions end-to-end-test/local/runtime-config/portal.properties
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@ spring.datasource.username=cbio_user
spring.datasource.password=somepassword
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
db.user=cbio_user
db.password=somepassword
db.driver=com.mysql.jdbc.Driver
db.connection_string=jdbc:mysql://cbioportal-database:3306/cbioportal?useSSL=false&allowPublicKeyRetrieval=true
# set tomcat_resource_name when using dbconnector=jndi instead of the default
# dbconnector=dbcp. Note that dbconnector needs to be set in CATLINA_OPTS when
# using Tomcat (CATALINA_OPTS="-Ddbconnector=jndi"). It does not get picked up
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,6 @@ describe('oncoprint', function() {
const urlWithUserConfig = createUrlWithSettingsQueryParam(
MANUAL_TRACK_CONFIG
);
// go to home page first because navigating to same page with hash params doesn't cause change
goToUrlAndSetLocalStorage(CBIOPORTAL_URL, false);
goToUrlAndSetLocalStorage(urlWithUserConfig, false);
waitForOncoprint(ONCOPRINT_TIMEOUT);

Expand Down Expand Up @@ -172,9 +170,7 @@ describe('oncoprint', function() {
const urlWithUserConfig = createUrlWithSettingsQueryParam(
customConfig
);
// go to home page first because navigating to same page with hash params doesn't cause change
goToUrlAndSetLocalStorage(CBIOPORTAL_URL, false);
browser.url(urlWithUserConfig);
goToUrlAndSetLocalStorage(urlWithUserConfig, false);

waitForOncoprint(ONCOPRINT_TIMEOUT);

Expand Down
2 changes: 2 additions & 0 deletions end-to-end-test/shared/specUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ function goToUrlAndSetLocalStorage(url, authenticated = false) {
const currentUrl = browser.getUrl();
const needToLogin =
authenticated && (!currentUrl || !currentUrl.includes('http'));
// navigate to blank page first to prevent issues with url hash params
browser.url('about:blank');
if (!useExternalFrontend) {
browser.url(url);
console.log('Connecting to: ' + url);
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "cbioportal-frontend",
"private": true,
"version": "3.3.273",
"version": "3.3.274",
"workspaces": {
"packages": [
".",
Expand Down Expand Up @@ -160,7 +160,7 @@
"bundle-loader": "^0.5.4",
"cbioportal-clinical-timeline": "^0.3.79",
"cbioportal-frontend-commons": "^0.5.63",
"cbioportal-ts-api-client": "^0.9.67",
"cbioportal-ts-api-client": "^0.9.68",
"cbioportal-utils": "^0.3.39",
"chart.js": "^2.6.0",
"classnames": "^2.2.5",
Expand Down
2 changes: 1 addition & 1 deletion packages/cbioportal-ts-api-client/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "cbioportal-ts-api-client",
"description": "cBioPortal API Client for TypeScript",
"version": "0.9.67",
"version": "0.9.68",
"main": "dist/index.js",
"module": "dist/index.es.js",
"jsnext:main": "dist/index.es.js",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5423,7 +5423,7 @@
"categorization": {
"enum": [
"MUTATED",
"EVENT"
"MUTATION_TYPE"
],
"type": "string"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,7 @@ export type Mutation = {

};
export type MutationDataFilter = {
'categorization': "MUTATED" | "EVENT"
'categorization': "MUTATED" | "MUTATION_TYPE"

'hugoGeneSymbol': string

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5233,7 +5233,7 @@
"categorization": {
"enum": [
"MUTATED",
"EVENT"
"MUTATION_TYPE"
],
"type": "string"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -901,7 +901,7 @@ export type MutationCountByPosition = {

};
export type MutationDataFilter = {
'categorization': "MUTATED" | "EVENT"
'categorization': "MUTATED" | "MUTATION_TYPE"

'hugoGeneSymbol': string

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import _ from 'lodash';
import _, { uniq } from 'lodash';
import { Sample } from 'cbioportal-ts-api-client';
import { ClinicalDataType, ClinicalDataTypeEnum } from '../../StudyViewUtils';
import Pluralize from 'pluralize';
Expand Down Expand Up @@ -132,6 +132,7 @@ export function validateLines(

let occurrence: { [key: string]: number } = {};
let validLines: { [key: string]: InputLine } = {};
let multiStudyCases: string[] = [];

// Remove all dups, not necessary to mention in the message
_.reduce(
Expand All @@ -140,27 +141,34 @@ export function validateLines(
}),
(acc, line) => {
let _case = '';
let validLine = true;
let validLine = false;
let newLines: InputLine[] = [];
if (line.studyId === undefined || line.studyId === '') {
if (!isSingleStudy) {
warningMessages.push({
code: CodeEnum.INVALID_CASE_ID,
message: new Error(
`No study specified for ${caseType} id: ${line.caseId}, and more than one study selected for query. The case will be ignored.`
),
});
validLine = false;
} else {
_case = getUniqueCaseId(selectedStudies[0], line.caseId);
if (!validPair[_case]) {
invalidCases.push(line.caseId);
validLine = false;
} else {
let validCaseCount = 0;
selectedStudies.map(studyId => {
_case = getUniqueCaseId(studyId, line.caseId);
if (validPair[_case]) {
if (occurrence[_case] === undefined) {
occurrence[_case] = 0;
}
occurrence[_case]++;

let newLine = _.cloneDeep(line);
newLine.studyId = studyId;
newLines.push(newLine);

validCaseCount += 1;
validLine = true;
}
});

if (validCaseCount === 0) {
invalidCases.push(line.caseId);
}

// case where it belongs to multiple studies
if (validCaseCount > 1) {
multiStudyCases.push(line.caseId);
}
} else {
if (!_.includes(selectedStudies, line.studyId)) {
Expand All @@ -170,28 +178,42 @@ export function validateLines(
`Incorrect study id: ${line.studyId}`
),
});
validLine = false;
} else {
_case = getUniqueCaseId(line.studyId, line.caseId);
if (validPair[_case] !== undefined) {
if (occurrence[_case] === undefined) {
occurrence[_case] = 0;
}
occurrence[_case]++;
validLine = true;
} else {
invalidCases.push(line.caseId);
validLine = false;
}
newLines.push(_.cloneDeep(line));
}
}

if (validLine) {
acc[getInputLineKey(line)] = line;
_.forEach(newLines, newLine => {
acc[getInputLineKey(newLine)] = newLine;
});
}
return acc;
},
validLines
);

if (!isSingleStudy && !_.isEmpty(multiStudyCases)) {
warningMessages.push({
code: CodeEnum.INVALID_CASE_ID,
message: new Error(
`The ${caseType} ID's below belong to multiple studies. All of them in the different studies will be selected.
To select specific ${caseType}, pelase specify study_id, Example: study_id:sample_id.
${caseType} ID's: ${multiStudyCases.join(', ')}`
),
});
}

// Find duplication cases
const dups = _.reduce(
occurrence,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import _ from 'lodash';
import { Dropdown, Checkbox } from 'react-bootstrap';
import { DropdownToggleProps } from 'react-bootstrap/lib/DropdownToggle';
import { DropdownMenuProps } from 'react-bootstrap/lib/DropdownMenu';
import { action, computed } from 'mobx';

export interface IColumnVisibilityDef {
id: string;
Expand Down Expand Up @@ -40,6 +41,8 @@ export class ColumnVisibilityControls extends React.Component<
constructor(props: IColumnVisibilityControlsProps) {
super(props);
this.handleSelect = this.handleSelect.bind(this);
this.selectAll = this.selectAll.bind(this);
this.deselectAll = this.deselectAll.bind(this);
}

public render() {
Expand All @@ -52,6 +55,59 @@ export class ColumnVisibilityControls extends React.Component<
);
}

private toggleAllColumns(select: boolean) {
if (!this.props.columnVisibility) return;

const toggledColumns = new Set<string>();
this.props.columnVisibility.forEach(column => {
if (column.visible !== select) {
toggledColumns.add(column.id);
}
});

toggledColumns.forEach(columnId => {
if (this.props.onColumnToggled && columnId) {
this.props.onColumnToggled(
columnId,
this.props.columnVisibility
);
}
});
}

private selectAll() {
this.toggleAllColumns(true);
}

private deselectAll() {
this.toggleAllColumns(false);
}

get selectDeselectAllButtons() {
return (
<div
style={{
display: 'flex',
alignItems: 'baseline',
gap: '3px',
}}
>
<button
className="btn btn-default btn-xs"
onClick={this.selectAll}
>
{`Select all`}
</button>
<button
className="btn btn-default btn-xs"
onClick={this.deselectAll}
>
{'Deselect all'}
</button>
</div>
);
}

private get defaultDropdown() {
return (
<Dropdown className={this.props.className} id="dropdown-custom-1">
Expand All @@ -70,6 +126,9 @@ export class ColumnVisibilityControls extends React.Component<
whiteSpace: 'nowrap',
}}
>
<div style={{ marginTop: 10, marginBottom: 10 }}>
{this.selectDeselectAllButtons}
</div>
<ul className="list-unstyled">
{this.props.columnVisibility &&
_.map(
Expand Down
22 changes: 21 additions & 1 deletion src/shared/components/iframeLoader/IFrameLoader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import LoadingIndicator from '../loadingIndicator/LoadingIndicator';
import { observer } from 'mobx-react';
import { makeObservable, observable } from 'mobx';
import autobind from 'autobind-decorator';
import FontAwesome from 'react-fontawesome';
interface FrameLoaderProps {
url: string;
className?: string;
Expand Down Expand Up @@ -35,12 +36,30 @@ export default class IFrameLoader extends React.Component<
//NOTE: we need zindex to be higher than that of global loader
render() {
return (
<div style={{ position: 'relative', width: this.props.width }}>
<div
style={{
position: 'relative',
width: this.props.width,
marginTop: 5,
}}
>
<LoadingIndicator
center={true}
size={'big'}
isLoading={!this.iframeLoaded}
/>
<a
href={this.props.url}
target="_blank"
style={{
position: 'absolute',
fontSize: 12,
right: 0,
top: -18,
}}
>
Open in new window <FontAwesome name="external-link" />
</a>
<iframe
id={this.props.iframeId || ''}
className={this.props.className || ''}
Expand All @@ -50,6 +69,7 @@ export default class IFrameLoader extends React.Component<
zIndex: 100,
height: this.props.height,
border: 'none',
marginTop: 5,
}}
src={this.props.url}
onLoad={this.onLoad}
Expand Down

0 comments on commit ed8ef6f

Please sign in to comment.