Skip to content
Snippets Groups Projects
Commit 259d7737 authored by florian's avatar florian
Browse files

FIX: Broken merge

parent b87dad13
No related branches found
No related tags found
2 merge requests!111Release 0.11.1,!110F fix merge
/**
* Extend the functionality of the pure html query panel.
*
* Deprecated. This is to be replaced by the query form of caosdb-webui-core-components.
*
* @deprecated
* @module queryForm
* @global
*/
var queryForm = (function () {
const init = function (form) {
queryForm.restoreLastQuery(form, () => window.sessionStorage.lastQuery);
queryForm.bindOnClick(form, (set) => {
window.sessionStorage.lastQuery = set;
});
const BUILD_FREE_SEARCH_ROLE_NAME_FACET_OPTIONS = "";
queryForm.initFreeSearch(
form,
`${BUILD_FREE_SEARCH_ROLE_NAME_FACET_OPTIONS}`
);
};
const logger = log.getLogger("queryForm");
var role_name_facet_select = undefined;
const _isCql = function (query) {
query = query.toUpperCase().trim();
return (
query.startsWith("FIND") ||
query.startsWith("COUNT") ||
query.startsWith("SELECT")
);
};
/**
* Initialize the free search to generate search queries which search only
* within one of several options of roles or entity names.
*
* E.g. when `options` is "Person, Experiment, Sample" the user can select
* one of these options before submitting the query. When the user types in
* something that doesn't looks like a CQL-query, a query is generated
* instead which goes like: FIND Persion WHICH HAS A PROPERTY LIKE
* "*something*".
*
* Note: This feature is disabled by default. Enable it by specifying the
* build variable BUILD_FREE_SEARCH_ROLE_NAME_FACET_OPTIONS as a
* comma-separated list of **properly quoted** expressions, e.g.
* "FILE 'numpy array', 'Plant Experiemnt', 'quotes_not_necessary'".
* Otherwise, the server will throw a syntax error.
*
* @function initFreeSearch
* @param {HTMLElement} form - the form which will be initialized for the
* free search.
* @param {string} options - comma-separated list of options.
* @return {boolean} - true if the initialization was successful, false
* otherwise.
*/
const initFreeSearch = function (form, options) {
const textArea = $(form).find(".caosdb-f-query-textarea");
logger.trace("initFreeSearch", form, textArea, options);
if (textArea.length > 0 && options && options != "") {
const lastQuery =
window.localStorage["freeTextQuery:" + textArea[0].value];
if (lastQuery) {
textArea[0].value = lastQuery;
}
const selected = window.localStorage["role_name_facet_option"];
const select = $(`<select class="btn btn-secondary"/>`);
for (let option of options.split(",")) {
select.append(
`<option ${
selected === option.trim() ? "selected" : ""
}>${option}</option>`
);
}
$(form).find(".input-group").prepend(select);
role_name_facet_select = select[0];
const switchFreeSearch = (text_area) => {
if (_isCql(text_area.value)) {
select.hide();
$(text_area).css({
"border-top-left-radius": "0.375rem",
"border-bottom-left-radius": "0.375rem",
});
} else {
select.show();
$(text_area).css({});
}
};
switchFreeSearch(textArea[0]);
textArea.on("keydown", (e) => {
switchFreeSearch(e.target);
});
return true;
}
role_name_facet_select = undefined;
return false;
};
/**
* @function restoreLastQuery
*/
const restoreLastQuery = function (form, getter) {
if (form == null) {
throw new Error("form was null");
}
if (getter()) {
form.query.value = getter();
}
};
/**
* @function redirect
* @param {string} query - the query string.
* @param {string} paging - the paging string, e.g. 0L10.
*/
const redirect = function (query, paging) {
var pagingparam = "";
if (paging && paging.length > 0) {
pagingparam = "P=" + paging + "&";
}
location.href =
connection.getBasePath() + "Entity/?" + pagingparam + "query=" + encodeURIComponent(query);
};
/**
* Read out the selector for the role/name facet of the query. Return
* "RECORD" if the selector is disabled.
* @function getRoleNameFacet
*/
const getRoleNameFacet = function () {
if (role_name_facet_select) {
const result = role_name_facet_select.value;
window.localStorage["role_name_facet_option"] = result;
return result;
}
return "RECORD";
};
const _splitSearchTermsPattern =
/"(?<dq>[^"]*)" |'(?<sq>[^']*)' |(?<nq>[^ ]+)/g;
/**
* Split a query string into single terms.
*
* Terms are separated by white spaces. Terms which contain white spaces
* which are to be preserved must be enclosed in " or ' quotes. The
* enclosing quotation marks are being stripped. Currently no support for
* escape sequences for quotation marks.
*
* @function splitSearchTerms
* @param {string} query - complete query string.
* @return {string[]} array of the search terms.
*/
const splitSearchTerms = function (query) {
// add empty space at the end, so every matching group ends with it -> easier regex. Also, undefined is filtered out
return Array.from(
(query + " ").matchAll(_splitSearchTermsPattern),
(m) => m[1] || m[2] || m[3]
).filter((word) => word);
};
/**
* Is the query a SELECT field,... FROM entity query?
*
* @function isSelectQuery
* @param {HTMLElement} query, the query to be tested.
* @return {Boolean}
*/
const isSelectQuery = function (query) {
return query.toUpperCase().startsWith("SELECT");
};
/**
* @function bindOnClick
*/
const bindOnClick = function (form, setter) {
if (setter == null || typeof setter !== "function" || setter.length !== 1) {
throw new Error("setter must be a function with one param");
}
/*
Here a submit handler is created that is attached to both the form submit handler
and the click handler of the button.
See https://developer.mozilla.org/en-US/docs/Web/Events/submit why this is necessary.
*/
var submithandler = function () {
// store current query
var queryField = form.query;
var value = queryField.value;
if (typeof value == "undefined" || value.length == 0) {
return;
}
if (!_isCql(value)) {
// split words in query field at space and create query fragments
var words = splitSearchTerms(queryField.value).map(
(word) => `A PROPERTY LIKE '*${word.replaceAll("'", `\\'`)}*'`
);
if (!words.length) {
return false;
}
const e = getRoleNameFacet();
const query_string = `FIND ${e} WHICH HAS ` + words.join(" AND ");
queryField.value = query_string;
// store original value of the text field
window.localStorage["freeTextQuery:" + query_string] = value;
}
setter(queryField.value);
var paging = "";
if (form.P && !isSelectQuery(queryField.value)) {
paging = form.P.value;
}
queryForm.redirect(queryField.value.trim(), paging);
var btn = $(form).find(".caosdb-search-btn");
btn.html(
`<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>`
);
btn.prop("disabled", true);
var textField = $(form).find(".caosdb-f-query-textarea");
textField.blur();
textField.prop("disabled", true);
};
// handler for the form
form.onsubmit = function (e) {
e.preventDefault();
submithandler();
return false;
};
// same handler for the button
form.getElementsByClassName("caosdb-search-btn")[0].onclick = function () {
submithandler();
};
};
/**
* @function getRoleNameFacetSelect
*/
return {
init: init,
initFreeSearch: initFreeSearch,
isSelectQuery: isSelectQuery,
restoreLastQuery: restoreLastQuery,
redirect: redirect,
bindOnClick: bindOnClick,
splitSearchTerms: splitSearchTerms,
getRoleNameFacet: getRoleNameFacet,
getRoleNameFacetSelect: () => role_name_facet_select,
};
})();
$(document).ready(function () {
if (`${BUILD_MODULE_LEGACY_QUERY_FORM}` == "ENABLED") {
var form = document.getElementById("caosdb-query-form");
if (form != null) {
queryForm.init(form);
}
}
});
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment