mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
1) Improved autocomplete loading indicator.
2) Avoid too many ajax requests per key press. refs #4488
This commit is contained in:
@@ -29,12 +29,13 @@ const useStyles = makeStyles(()=>({
|
|||||||
|
|
||||||
function registerAutocomplete(api, transId, onFailure) {
|
function registerAutocomplete(api, transId, onFailure) {
|
||||||
let timeoutId;
|
let timeoutId;
|
||||||
|
let loadingEle;
|
||||||
|
let autoCompleteList = [];
|
||||||
|
let prevSearch = null;
|
||||||
OrigCodeMirror.registerHelper('hint', 'sql', function (editor) {
|
OrigCodeMirror.registerHelper('hint', 'sql', function (editor) {
|
||||||
var data = [],
|
var data = [],
|
||||||
doc = editor.getDoc(),
|
doc = editor.getDoc(),
|
||||||
cur = doc.getCursor(),
|
cur = doc.getCursor(),
|
||||||
// Get the current cursor position
|
|
||||||
current_cur = cur.ch,
|
|
||||||
// function context
|
// function context
|
||||||
ctx = {
|
ctx = {
|
||||||
editor: editor,
|
editor: editor,
|
||||||
@@ -78,21 +79,67 @@ function registerAutocomplete(api, transId, onFailure) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
data.push(doc.getValue());
|
data.push(doc.getValue());
|
||||||
// Get the text from start to the current cursor position.
|
|
||||||
data.push(
|
// This function is used to show the loading element until response comes.
|
||||||
doc.getRange({
|
const showLoading = (editor)=>{
|
||||||
line: 0,
|
if (editor.getInputField().getAttribute('aria-activedescendant') != null) {
|
||||||
ch: 0,
|
hideLoading();
|
||||||
}, {
|
return;
|
||||||
line: ctx.current_line,
|
}
|
||||||
ch: current_cur,
|
|
||||||
})
|
if(!loadingEle) {
|
||||||
);
|
var ownerDocument = editor.getInputField().ownerDocument;
|
||||||
|
loadingEle = ownerDocument.createElement('div');
|
||||||
|
loadingEle.className = 'CodeMirror-hints';
|
||||||
|
var iconEle = ownerDocument.createElement('div');
|
||||||
|
iconEle.className = 'icon-spinner';
|
||||||
|
iconEle.style.marginTop = '4px';
|
||||||
|
iconEle.style.marginLeft = '2px';
|
||||||
|
|
||||||
|
var spanEle = ownerDocument.createElement('span');
|
||||||
|
spanEle.innerText = gettext('Loading...');
|
||||||
|
spanEle.style.marginLeft = '17px';
|
||||||
|
|
||||||
|
iconEle.appendChild(spanEle);
|
||||||
|
loadingEle.appendChild(iconEle);
|
||||||
|
ownerDocument.body.appendChild(loadingEle);
|
||||||
|
}
|
||||||
|
var pos = editor.cursorCoords(true);
|
||||||
|
loadingEle.style.left = pos.left + 'px';
|
||||||
|
loadingEle.style.top = pos.bottom + 'px';
|
||||||
|
loadingEle.style.height = '25px';
|
||||||
|
};
|
||||||
|
|
||||||
|
// This function is used to hide the loading element.
|
||||||
|
const hideLoading = ()=>{
|
||||||
|
loadingEle?.parentNode?.removeChild(loadingEle);
|
||||||
|
loadingEle = null;
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
then: function (cb) {
|
then: function (cb) {
|
||||||
var self_local = this;
|
var self_local = this;
|
||||||
|
|
||||||
|
// This function is used to filter the data and call the callback
|
||||||
|
// function with that filtered data.
|
||||||
|
function setAutoCompleteData() {
|
||||||
|
let filterData = autoCompleteList.filter((item)=>{
|
||||||
|
return item.text.toLowerCase().startsWith(search.toLowerCase());
|
||||||
|
});
|
||||||
|
|
||||||
|
cb({
|
||||||
|
list: filterData,
|
||||||
|
from: {
|
||||||
|
line: self_local.current_line,
|
||||||
|
ch: start,
|
||||||
|
},
|
||||||
|
to: {
|
||||||
|
line: self_local.current_line,
|
||||||
|
ch: end,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Below logic find the start and end point
|
* Below logic find the start and end point
|
||||||
* to replace the selected auto complete suggestion.
|
* to replace the selected auto complete suggestion.
|
||||||
@@ -118,28 +165,37 @@ function registerAutocomplete(api, transId, onFailure) {
|
|||||||
* started with "." or "`" else auto complete of code mirror
|
* started with "." or "`" else auto complete of code mirror
|
||||||
* will remove the "." when user select any suggestion.
|
* will remove the "." when user select any suggestion.
|
||||||
*/
|
*/
|
||||||
if (search.charAt(0) == '.' || search.charAt(0) == '``')
|
if (search.charAt(0) == '.' || search.charAt(0) == '``') {
|
||||||
start += 1;
|
start += 1;
|
||||||
|
search = search.slice(1);
|
||||||
|
}
|
||||||
|
|
||||||
cb({
|
// Clear the auto complete list if previous token/search is blank or dot.
|
||||||
list: [{
|
prevSearch = search;
|
||||||
text: '',
|
if (prevSearch == '' || prevSearch == '.')
|
||||||
render: (elt)=>{
|
autoCompleteList = [];
|
||||||
var el = document.createElement('span');
|
|
||||||
el.className = 'sqleditor-hint icon-spinner';
|
// Get the text from start to the current cursor position.
|
||||||
el.appendChild(document.createTextNode(gettext('Loading...')));
|
self_local.data.push(
|
||||||
elt.appendChild(el);
|
doc.getRange({
|
||||||
},
|
line: 0,
|
||||||
}, {text: ''}],
|
ch: 0,
|
||||||
from: {
|
}, {
|
||||||
line: self_local.current_line,
|
line: self_local.current_line,
|
||||||
ch: start,
|
ch: token.start + 1,
|
||||||
},
|
})
|
||||||
to: {
|
);
|
||||||
line: self_local.current_line,
|
|
||||||
ch: end,
|
// If search token is not empty and auto complete list have some data
|
||||||
},
|
// then no need to send the request to the backend to fetch the data.
|
||||||
});
|
// auto complete the data using already fetched list.
|
||||||
|
if (search != '' && autoCompleteList.length != 0) {
|
||||||
|
setAutoCompleteData();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Show loading indicator
|
||||||
|
showLoading(self_local.editor);
|
||||||
|
|
||||||
timeoutId && clearTimeout(timeoutId);
|
timeoutId && clearTimeout(timeoutId);
|
||||||
timeoutId = setTimeout(()=> {
|
timeoutId = setTimeout(()=> {
|
||||||
@@ -147,6 +203,7 @@ function registerAutocomplete(api, transId, onFailure) {
|
|||||||
// Make ajax call to find the autocomplete data
|
// Make ajax call to find the autocomplete data
|
||||||
api.post(self_local.url, JSON.stringify(self_local.data))
|
api.post(self_local.url, JSON.stringify(self_local.data))
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
|
hideLoading();
|
||||||
var result = [];
|
var result = [];
|
||||||
|
|
||||||
_.each(res.data.data.result, function (obj, key) {
|
_.each(res.data.data.result, function (obj, key) {
|
||||||
@@ -157,19 +214,11 @@ function registerAutocomplete(api, transId, onFailure) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
cb({
|
autoCompleteList = result;
|
||||||
list: result,
|
setAutoCompleteData();
|
||||||
from: {
|
|
||||||
line: self_local.current_line,
|
|
||||||
ch: start,
|
|
||||||
},
|
|
||||||
to: {
|
|
||||||
line: self_local.current_line,
|
|
||||||
ch: end,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
|
hideLoading();
|
||||||
onFailure?.(err);
|
onFailure?.(err);
|
||||||
});
|
});
|
||||||
}, 300);
|
}, 300);
|
||||||
|
|||||||
Reference in New Issue
Block a user