Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TASK-6385 - Issues with the Study Filter dropdown of Variant Browser #936

Merged
merged 8 commits into from
Jul 5, 2024
145 changes: 88 additions & 57 deletions src/webcomponents/commons/filters/study-filter.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ import UtilsNew from "../../../core/utils-new.js";
import LitUtils from "../utils/lit-utils.js";
import "../forms/select-field-filter.js";

import {guardPage} from "../html-utils.js";

export default class StudyFilter extends LitElement {

constructor() {
Expand All @@ -44,90 +42,116 @@ export default class StudyFilter extends LitElement {
}

#init() {
$.fn.selectpicker.Constructor.BootstrapVersion = "5";
this._prefix = UtilsNew.randomString(8);
this.operator = ",";
this.selectedStudies = [];
this.differentStudies = [];
this._studies = [];
this._operator = ",";
this._selection = [];
this._config = this.getDefaultConfig();
}

update(changedProperties) {
if (changedProperties.has("opencgaSession")) {
if (this.opencgaSession?.project?.studies?.length) {
this.differentStudies = this.opencgaSession.project.studies
.filter(study => this.opencgaSession.study.id !== study.id);
}
this.opencgaSessionObserver();
}

if (changedProperties.has("opencgaSession") || changedProperties.has("value")) {
this.selectedStudies = Array.from(new Set([
this.opencgaSession.study.fqn,
...(this.value || "").split(this.operator).filter(v => !!v),
]));
this.valueObserver();
}
if (changedProperties.has("config")) {
this._config = {
...this.getDefaultConfig(),
...this.config,
};
}

super.update(changedProperties);
}

updated(changedProperties) {
if (changedProperties.has("opencgaSession")) {
$(".selectpicker", this).selectpicker("refresh");
opencgaSessionObserver() {
this._studies = [];
if (this.opencgaSession?.project?.studies?.length) {
// 1. Add current study as the first element and mark it as disabled
this._studies.push({
name: this.opencgaSession.study.name,
id: this.opencgaSession.study.fqn,
selected: true,
disabled: true,
});
// 2. Add other studies to the studies dropdown
this.opencgaSession.project.studies.forEach(study => {
if (study.fqn !== this.opencgaSession.study.fqn) {
this._studies.push({
name: study.name,
id: study.fqn,
});
}
});
}
$(".selectpicker", this).selectpicker("val", this.selectedStudies);
}

filterChange() {
let querystring;
// AND or OR operators
if (this.operator !== "!") {
querystring = [...this.selectedStudies.map(study => `${study}`)].join(this.operator);
} else {
// NOT operator (not visible/not implemented)
querystring = [...this.selectedStudies.map(study => `${this.operator}${study}`)].join(";");
}
LitUtils.dispatchCustomEvent(this, "filterChange", querystring);
valueObserver() {
// 1. Reset the operator value. If the current value does not contain ';', maintain the current selected operator
this._operator = (this.value || "").indexOf(";") > -1 ? ";" : this._operator;
// 2. Reset the selection
this._selection = Array.from(new Set([
this.opencgaSession.study.fqn,
...(this.value || "").split(this._operator).filter(v => !!v),
]));
}

onChangeOperator(e) {
this.operator = e.target.value;
this.filterChange();
onStudyChange(event) {
// 1. Split values returned from select-field-filter and remove empty items
// Note: select-field-filter returns values joined with a comma character
const values = (event.detail.value || "")
.split(",")
.filter(value => !!value);
// 2. Trigger 'filterChange' event with the values joined with the current operator
LitUtils.dispatchCustomEvent(this, "filterChange", values.join(this._operator));
}

onChangeSelectedStudy() {
const selected = $(".selectpicker", this).selectpicker("val");
// Active study is always the first element
this.selectedStudies = [this.opencgaSession.study.fqn, ...selected];
this.requestUpdate();
this.filterChange();
onOperatorChange(event) {
// 1. Save the new operator value
this._operator = event.target.value || ",";
// 2. Trigger the 'filterChange' event
LitUtils.dispatchCustomEvent(this, "filterChange", this._selection.join(this._operator));
}

render() {
// Check Project exists
if (!this.opencgaSession && !this.opencgaSession.project) {
return guardPage();
return nothing;
}

return html`
<div class="mb-3" id="${this._prefix}DifferentStudies">
<select multiple class="form-control selectpicker" @change="${this.onChangeSelectedStudy}">
<option value="${this.opencgaSession.study.fqn}" selected="selected" disabled>
${this.opencgaSession.study.name}
</option>
${(this.differentStudies || []).map(study => html`
<option value="${study.fqn}">${study.name}</option>
`)}
</select>
<fieldset class="d-grid my-1 mx-0" ?disabled="${this.selectedStudies.length < 2}">
<div class="mb-3">
<select-field-filter
.data="${this._studies}"
.value="${this._selection}"
.config="${this._config}"
@filterChange="${event => this.onStudyChange(event)}">
</select-field-filter>
<fieldset class="d-grid my-1 mx-0" ?disabled="${this._selection.length < 2}">
<div class="btn-group" role="group">
<input class="btn-check" id="${this._prefix}orInput" name="pss"
type="radio" value="," @change="${this.onChangeOperator}"
autocomplete="off" checked>
<input
id="${this._prefix}orInput"
name="studyFilterOperator"
type="radio"
class="btn-check"
value=","
?checked="${this._operator === ","}"
?disabled="${this._selection.length < 2}"
@change="${event => this.onOperatorChange(event)}"
/>
<label class="btn btn-outline-primary" for="${this._prefix}orInput">
In any of (OR)
</label>
<input class="btn-check" id="${this._prefix}andInput" name="pss"
type="radio" value=";" @change="${this.onChangeOperator}"
autocomplete="off">
<input
id="${this._prefix}andInput"
name="studyFilterOperator"
type="radio"
class="btn-check"
value=";"
?checked="${this._operator === ";"}"
?disabled="${this._selection.length < 2}"
@change="${event => this.onOperatorChange(event)}"
/>
<label class="btn btn-outline-primary" for="${this._prefix}andInput">
In all (AND)
</label>
Expand All @@ -137,6 +161,13 @@ export default class StudyFilter extends LitElement {
`;
}

getDefaultConfig() {
return {
multiple: true,
disabled: false,
};
}

}

customElements.define("study-filter", StudyFilter);
2 changes: 1 addition & 1 deletion src/webcomponents/variant/variant-browser-filter.js
Original file line number Diff line number Diff line change
Expand Up @@ -656,7 +656,7 @@ export default class VariantBrowserFilter extends LitElement {

render() {
return html`
<div class="d-grid gap-1 mb-3" id="${this._prefix}Accordion" role="tablist" aria-multiselectable="true">
<div class="d-flex flex-column gap-3" id="${this._prefix}Accordion" role="tablist" aria-multiselectable="true">
${this.renderFilterMenu()}
</div>
`;
Expand Down
Loading