Skip to content

Commit

Permalink
Merge branch 'TASK-7100' of github.com:opencb/jsorolla into TASK-7100
Browse files Browse the repository at this point in the history
imedina committed Jan 27, 2025
2 parents f2565f3 + 8e66a97 commit 2c092de
Showing 11 changed files with 352 additions and 472 deletions.
201 changes: 101 additions & 100 deletions src/webcomponents/commons/filters-toolbar.js
Original file line number Diff line number Diff line change
@@ -22,8 +22,11 @@ export default class FiltersToolbar extends LitElement {
opencgaSession: {
type: Object
},
query: {
type: Object
preparedQuery: {
type: Object,
},
executedQuery: {
type: Object,
},
resource: {
type: String,
@@ -53,12 +56,11 @@ export default class FiltersToolbar extends LitElement {
this._prefix = UtilsNew.randomString(8);
this._config = this.getDefaultConfig();

this.query = {};
this.searchActive = true;

this.queryList = [];
this.preparedQuery = {};
this.executedQuery = {};

this.queryList = [];
this.quickFilters = [];
this.applicationFilters = [];
this.userFilters = [];
@@ -75,10 +77,14 @@ export default class FiltersToolbar extends LitElement {
this.opencgaSessionObserver();
}

if (changedProperties.has("query")) {
if (changedProperties.has("preparedQuery") || changedProperties.has("executedQuery")) {
this.queryObserver();
}

if (changedProperties.has("executedQuery")) {
this.updateHistory();
}

super.update(changedProperties);
}

@@ -104,13 +110,67 @@ export default class FiltersToolbar extends LitElement {
}

queryObserver() {
this.preparedQuery = UtilsNew.objectClone(this.query);
this.updateQueryList();
this.queryList = [];

// update the history only if it is empty
if (this.historyFilters.length === 0) {
this.updateHistory();
}
Object.keys(this.preparedQuery).forEach(key => {
if (!!this.preparedQuery[key] && (!this._config.activeFilters.hiddenFields || !this._config.activeFilters.hiddenFields.includes(key))) {
// We use the alias to rename the key
let title = key;

if (this._config?.activeFilters?.alias && this._config.activeFilters.alias[key]) {
title = this._config.activeFilters.alias[key];
}

// We convert the Query entry object into an array of small objects (queryList)
let value = this.preparedQuery[key];
if (typeof value === "boolean") {
value = value.toString();
}

let filterFields = [];

// in case of annotation
if (key === "annotation") {
filterFields = value.split(";");
} else if (key === "study") {
// We fist have need to remove defaultStudy from 'filterFields' and 'value'
filterFields = value.split(/[,;]/).filter(fqn => fqn !== this.opencgaSession?.study?.fqn);
// defaultStudy was the only one present so no need to render anything
if (!filterFields.length) {
return;
}
value = filterFields.join(/[,;]/);
} else {
// Check if the field has been defined as complex
const complexField = (this._config?.activeFilters?.complexFields || [])
.find(item => item.id === key);

if (complexField) {
filterFields = complexField?.separator ? value.split(complexField.separator) : UtilsNew.splitByRegex(value, complexField.separatorRegex);
} else if (value.indexOf(";") !== -1 && value.indexOf(",") !== -1) {
// If we find a field with both ; and , we will separate by ;
filterFields = value.split(";");
} else {
filterFields = value.split(new RegExp("[,;]"));
}
}

// Check if the field is locked
const locked = !!this.lockedFieldsMap[key];
const lockedTooltip = locked ? this.lockedFieldsMap[key].message : "";

// separator used in the text in case that we only have one filter field
const separator = (value.indexOf(">") !== -1 || value.indexOf("<") !== -1 || value.indexOf("=") !== -1) ? ": " : " = ";

this.queryList.push({
name: key,
text: filterFields.length === 1 ? title + separator + value : title,
items: filterFields,
locked: locked,
message: lockedTooltip,
});
}
});
}

configObserver() {
@@ -161,7 +221,7 @@ export default class FiltersToolbar extends LitElement {
updateHistory() {
// 1. remove all identical filters
const history = this.historyFilters.filter(historyItem => {
return JSON.stringify(historyItem.query) !== JSON.stringify(this.preparedQuery);
return JSON.stringify(historyItem.query) !== JSON.stringify(this.executedQuery);
});

// 2. remove previous latest
@@ -173,7 +233,7 @@ export default class FiltersToolbar extends LitElement {
history.unshift({
id: UtilsNew.dateFormatter(UtilsNew.getDatetime(), "HH:mm:ss"),
// date: UtilsNew.getDatetime(),
query: UtilsNew.objectClone(this.preparedQuery),
query: UtilsNew.objectClone(this.executedQuery),
latest: true,
});

@@ -182,67 +242,7 @@ export default class FiltersToolbar extends LitElement {
}

updateQueryList() {
this.queryList = [];

Object.keys(this.preparedQuery).forEach(key => {
if (!!this.preparedQuery[key] && (!this._config.activeFilters.hiddenFields || !this._config.activeFilters.hiddenFields.includes(key))) {
// We use the alias to rename the key
let title = key;

if (this._config?.activeFilters?.alias && this._config.activeFilters.alias[key]) {
title = this._config.activeFilters.alias[key];
}

// We convert the Query entry object into an array of small objects (queryList)
let value = this.preparedQuery[key];
if (typeof value === "boolean") {
value = value.toString();
}

let filterFields = [];

// in case of annotation
if (key === "annotation") {
filterFields = value.split(";");
} else if (key === "study") {
// We fist have need to remove defaultStudy from 'filterFields' and 'value'
filterFields = value.split(/[,;]/).filter(fqn => fqn !== this.opencgaSession?.study?.fqn);
// defaultStudy was the only one present so no need to render anything
if (!filterFields.length) {
return;
}
value = filterFields.join(/[,;]/);
} else {
// Check if the field has been defined as complex
const complexField = (this._config?.activeFilters?.complexFields || [])
.find(item => item.id === key);

if (complexField) {
filterFields = complexField?.separator ? value.split(complexField.separator) : UtilsNew.splitByRegex(value, complexField.separatorRegex);
} else if (value.indexOf(";") !== -1 && value.indexOf(",") !== -1) {
// If we find a field with both ; and , we will separate by ;
filterFields = value.split(";");
} else {
filterFields = value.split(new RegExp("[,;]"));
}
}

// Check if the field is locked
const locked = !!this.lockedFieldsMap[key];
const lockedTooltip = locked ? this.lockedFieldsMap[key].message : "";

// separator used in the text in case that we only have one filter field
const separator = (value.indexOf(">") !== -1 || value.indexOf("<") !== -1 || value.indexOf("=") !== -1) ? ": " : " = ";

this.queryList.push({
name: key,
text: filterFields.length === 1 ? title + separator + value : title,
items: filterFields,
locked: locked,
message: lockedTooltip,
});
}
});
return null;
}

saveFilter() {
@@ -358,75 +358,73 @@ export default class FiltersToolbar extends LitElement {
// Example: REST accepts filter and qual while filter returns FILTER and QUALITY
// - key: {filter: "FILTER", qual: "QUALITY"}
// - value: {FILTER: "pass", QUALITY: "25"}
const query = UtilsNew.objectClone(this.preparedQuery);

if (typeof key === "object" && typeof value === "object") {
Object.values(key).forEach(k => {
if (value[k] && value[k] !== "") {
this.preparedQuery[k] = value[k];
query[k] = value[k];
} else {
delete this.preparedQuery[k];
delete query[k];
}
});
} else {
if (!!value) {
this.preparedQuery[key] = value;
query[key] = value;
} else {
delete this.preparedQuery[key];
delete query[key];
}
}

this.notifyQuery(this.preparedQuery);
this.notifyQuery(query);
}

onFilterDelete(key, value) {
const query = UtilsNew.objectClone(this.preparedQuery);

// in case that we want to remove the whole filter, or the filter has a single value
if (!value || this.preparedQuery[key] === value) {
delete this.preparedQuery[key];
if (!value || query[key] === value) {
delete query[key];
} else {
let filterFields = [];
const complexField = (this._config?.complexFields || []).find(item => item.id === key);

if (complexField) {
filterFields = complexField?.separator ? this.preparedQuery[key].split(complexField.separator) : UtilsNew.splitByRegex(this.preparedQuery[key], complexField.separatorRegex);
filterFields = complexField?.separator ? query[key].split(complexField.separator) : UtilsNew.splitByRegex(query[key], complexField.separatorRegex);
} else if (value.indexOf(";") !== -1 && value.indexOf(",") !== -1) {
filterFields = this.preparedQuery[key].split(";"); // If we find a field with both ; and , we will separate by ;
filterFields = query[key].split(";"); // If we find a field with both ; and , we will separate by ;
} else {
filterFields = this.preparedQuery[key].split(new RegExp("[,;]"));
filterFields = query[key].split(new RegExp("[,;]"));
}

// remove value from filterFields
filterFields = filterFields.filter(field => field !== value);

// restore the query field
if (complexField) {
this.preparedQuery[key] = complexField?.separator ? filterFields.join(complexField.separator) : filterFields.join(",");
query[key] = complexField?.separator ? filterFields.join(complexField.separator) : filterFields.join(",");
} else if (value.indexOf(";") !== -1 && value.indexOf(",") !== -1) {
this.preparedQuery[key] = filterFields.join(";");
} else if (this.preparedQuery[key].indexOf(",") !== -1) {
this.preparedQuery[key] = filterFields.join(",");
query[key] = filterFields.join(";");
} else if (query[key].indexOf(",") !== -1) {
query[key] = filterFields.join(",");
} else {
this.preparedQuery[key] = filterFields.join(";");
query[key] = filterFields.join(";");
}
}

this.notifySearch(this.preparedQuery);
this.updateHistory();
this.notifySearch(query);
}

onApplyQuery(query) {
this.preparedQuery = UtilsNew.objectClone(query || {});
this.notifySearch(this.preparedQuery);
this.updateHistory();
this.notifySearch(query);
}

onSearch() {
this.notifySearch(this.preparedQuery);
this.updateHistory();
}

onClear() {
this.preparedQuery = {};
this.notifySearch(this.preparedQuery);
this.updateHistory();
LitUtils.dispatchCustomEvent(this, "queryClear", null, {});
}

onSave() {
@@ -435,7 +433,7 @@ export default class FiltersToolbar extends LitElement {

onCopyLink() {
// 1. Generate the url to the tool with the current query
const link = WebUtils.getIVALink(this.opencgaSession, this.toolId, this.query);
const link = WebUtils.getIVALink(this.opencgaSession, this.toolId, this.preparedQuery);

// 2. Copy this link to the user clipboard
UtilsNew.copyToClipboard(link);
@@ -755,6 +753,9 @@ export default class FiltersToolbar extends LitElement {
hiddenFields: [],
lockedFields: [],
},
save: {
ignoreParams: [],
},
sections: [],
examples: [],
defaultFilter: {},
Loading

0 comments on commit 2c092de

Please sign in to comment.