Make the Query Tool history persistent across sessions. Fixes #4017

This commit is contained in:
Dave Page
2019-03-13 13:37:34 +00:00
parent a502019e20
commit ab9a3a57ad
16 changed files with 581 additions and 66 deletions

View File

@@ -10,6 +10,7 @@ export default class QueryHistory {
this.histCollection = histModel;
this.editorPref = {};
this.onCopyToEditorHandler = ()=>{};
this.histCollection.onAdd(this.onAddEntry.bind(this));
this.histCollection.onReset(this.onResetEntries.bind(this));
}
@@ -35,8 +36,19 @@ export default class QueryHistory {
this.render();
}
onCopyToEditorClick(onCopyToEditorHandler) {
this.onCopyToEditorHandler = onCopyToEditorHandler;
if(this.queryHistDetails) {
this.queryHistDetails.onCopyToEditorClick(this.onCopyToEditorHandler);
}
}
setEditorPref(editorPref) {
this.editorPref = editorPref;
this.editorPref = {
...this.editorPref,
...editorPref,
};
if(this.queryHistDetails) {
this.queryHistDetails.setEditorPref(this.editorPref);
}
@@ -63,6 +75,7 @@ export default class QueryHistory {
this.queryHistDetails = new QueryHistoryDetails($histDetails);
this.queryHistDetails.setEditorPref(this.editorPref);
this.queryHistDetails.onCopyToEditorClick(this.onCopyToEditorHandler);
this.queryHistDetails.render();
this.queryHistEntries = new QueryHistoryEntries($histEntries);

View File

@@ -1,7 +1,8 @@
import CodeMirror from 'bundled_codemirror';
import clipboard from 'sources/selection/clipboard';
import moment from 'moment';
import gettext from 'sources/gettext';
import $ from 'jquery';
import _ from 'underscore';
export default class QueryHistoryDetails {
constructor(parentNode) {
@@ -10,9 +11,11 @@ export default class QueryHistoryDetails {
this.timeout = null;
this.isRendered = false;
this.sqlFontSize = null;
this.onCopyToEditorHandler = ()=>{};
this.editorPref = {
'sql_font_size': '1em',
'copy_to_editor': true,
};
}
@@ -31,13 +34,21 @@ export default class QueryHistoryDetails {
...editorPref,
};
if(this.query_codemirror) {
if(this.query_codemirror && !_.isUndefined(editorPref.sql_font_size)) {
$(this.query_codemirror.getWrapperElement()).css(
'font-size',this.editorPref.sql_font_size
);
this.query_codemirror.refresh();
}
if(this.$copyToEditor && !_.isUndefined(editorPref.copy_to_editor)) {
if(editorPref.copy_to_editor) {
this.$copyToEditor.removeClass('d-none');
} else {
this.$copyToEditor.addClass('d-none');
}
}
}
parseErrorMessage(message) {
@@ -47,7 +58,7 @@ export default class QueryHistoryDetails {
}
formatDate(date) {
return moment(date).format('M-D-YY HH:mm:ss');
return date.toLocaleDateString() + ' ' + date.toLocaleTimeString();
}
copyAllHandler() {
@@ -62,6 +73,10 @@ export default class QueryHistoryDetails {
}, 1500);
}
onCopyToEditorClick(onCopyToEditorHandler) {
this.onCopyToEditorHandler = onCopyToEditorHandler;
}
clearPreviousTimeout() {
if (this.timeout) {
clearTimeout(this.timeout);
@@ -71,11 +86,11 @@ export default class QueryHistoryDetails {
updateCopyButton(copied) {
if (copied) {
this.$copyBtn.attr('class', 'was-copied');
this.$copyBtn.addClass('was-copied').removeClass('copy-all');
this.$copyBtn.text('Copied!');
} else {
this.$copyBtn.attr('class', 'copy-all');
this.$copyBtn.text('Copy All');
this.$copyBtn.addClass('copy-all').removeClass('was-copied');
this.$copyBtn.text('Copy');
}
}
@@ -137,7 +152,8 @@ export default class QueryHistoryDetails {
<div class='metadata-block'></div>
<div class='query-statement-block'>
<div id='history-detail-query'>
<button class='' tabindex=0 accesskey='y'></button>
<button class='btn-copy' tabindex=0 accesskey='y'></button>
<button class='btn-copy-editor copy-to-editor' tabindex=0 accesskey='y'>` + gettext('Copy to Query Editor') + `</button>
<div></div>
</div>
</div>
@@ -154,8 +170,13 @@ export default class QueryHistoryDetails {
);
this.$errMsgBlock = this.parentNode.find('.error-message-block');
this.$copyBtn = this.parentNode.find('#history-detail-query button');
this.$copyBtn = this.parentNode.find('#history-detail-query .btn-copy');
this.$copyBtn.off('click').on('click', this.copyAllHandler.bind(this));
this.$copyToEditor = this.parentNode.find('#history-detail-query .btn-copy-editor');
this.$copyToEditor.off('click').on('click', () => {
this.onCopyToEditorHandler(this.entry.query);
});
this.$copyToEditor.addClass(this.editorPref.copy_to_editor?'':'d-none');
this.$metaData = this.parentNode.find('.metadata-block');
this.query_codemirror = CodeMirror(
this.parentNode.find('#history-detail-query div')[0],

View File

@@ -21,26 +21,20 @@ export class QueryHistoryEntryDateGroup {
return prefix;
}
getDateFormatted(momentToFormat) {
return momentToFormat.format(this.formatString);
}
getDateMoment() {
return moment(this.date);
getDateFormatted(date) {
return date.toLocaleDateString();
}
isDaysBefore(before) {
return (
this.getDateFormatted(this.getDateMoment()) ===
this.getDateFormatted(moment().subtract(before, 'days'))
this.getDateFormatted(this.date) ===
this.getDateFormatted(moment().subtract(before, 'days').toDate())
);
}
render() {
return $(`<div class='query-group' data-key='${this.groupKey}'>
<div class='date-label'>${this.getDatePrefix()}${this.getDateFormatted(
this.getDateMoment()
)}</div>
<div class='date-label'>${this.getDatePrefix()}${this.getDateFormatted(this.date)}</div>
<ul class='query-entries'></ul>
</div>`);
}
@@ -66,9 +60,13 @@ export class QueryHistoryItem {
return moment(date).format('HH:mm:ss');
}
dataKey() {
return this.formatDate(this.entry.start_time);
}
render() {
this.$el = $(
`<li class='list-item' tabindex='0' data-key='${this.formatDate(this.entry.start_time)}'>
`<li class='list-item' tabindex='0' data-key='${this.dataKey()}'>
<div class='entry ${this.entry.status ? '' : 'error'}'>
<div class='query'>${this.entry.query}</div>
<div class='other-info'>
@@ -98,15 +96,11 @@ export class QueryHistoryEntries {
}
focus() {
let self = this;
if (!this.$selectedItem) {
this.setSelectedListItem(this.$el.find('.list-item').first());
}
setTimeout(() => {
self.$selectedItem.trigger('click');
}, 500);
this.$selectedItem.trigger('click');
this.$el[0].focus();
}
isArrowDown(event) {
@@ -170,7 +164,8 @@ export class QueryHistoryEntries {
}
$listItem.addClass('selected');
this.$selectedItem = $listItem;
this.$selectedItem[0].scrollIntoView(false);
this.$selectedItem[0].scrollIntoView({block: 'center'});
if (this.onSelectedChangeHandler) {
this.onSelectedChangeHandler(this.$selectedItem.data('entrydata'));
@@ -200,13 +195,20 @@ export class QueryHistoryEntries {
entry.start_time,
entryGroupKey
).render();
if (groups[groupIdx]) {
$groupEl.insertBefore(groups[groupIdx]);
} else {
this.$el.prepend($groupEl);
let i=0;
while(i<groupsKeys.length){
if(entryGroupKey > groupsKeys[i]) {
$groupEl.insertBefore(groups[i]);
break;
}
i++;
}
if(i == groupsKeys.length) {
this.$el.append($groupEl);
}
} else if (groupIdx >= 0) {
/* if groups present, but this is a new one */
/* if the group is present */
$groupEl = $(groups[groupIdx]);
}