Files
discourse-data-explorer/assets/javascripts/discourse/controllers/admin-plugins-explorer-index.js
T
Gary Pendergast c13e79d21b FIX: Query downloads were being passed an incorrect query object. (#359)
This is a follow-up to d726c4889e.

The previous change missed changing the name of the query object when passing it to QueryResultsWrapper, which resulted in the download links not working properly after a query was run.

This change fixes that bug, and includes an acceptance test to ensure it stays fixed during future work on this plugin.
2025-02-14 10:11:32 +11:00

188 lines
4.6 KiB
JavaScript

import { tracked } from "@glimmer/tracking";
import Controller from "@ember/controller";
import { action } from "@ember/object";
import { service } from "@ember/service";
import { Promise } from "rsvp";
import { popupAjaxError } from "discourse/lib/ajax-error";
import { bind } from "discourse/lib/decorators";
import { i18n } from "discourse-i18n";
export default class PluginsExplorerController extends Controller {
@service dialog;
@service appEvents;
@service router;
@tracked sortByProperty = "last_run_at";
@tracked sortDescending = true;
@tracked params;
@tracked search;
@tracked newQueryName;
@tracked showCreate;
@tracked loading = false;
queryParams = ["id"];
explain = false;
acceptedImportFileTypes = ["application/json"];
order = null;
form = null;
get sortedQueries() {
const sortedQueries = this.model.sortBy(this.sortByProperty);
return this.sortDescending ? sortedQueries.reverse() : sortedQueries;
}
get parsedParams() {
return this.params ? JSON.parse(this.params) : null;
}
get filteredContent() {
const regexp = new RegExp(this.search, "i");
return this.sortedQueries.filter(
(result) => regexp.test(result.name) || regexp.test(result.description)
);
}
get createDisabled() {
return (this.newQueryName || "").trim().length === 0;
}
addCreatedRecord(record) {
this.model.pushObject(record);
this.router.transitionTo(
"adminPlugins.explorer.queries.details",
record.id
);
}
async _importQuery(file) {
const json = await this._readFileAsTextAsync(file);
const query = this._parseQuery(json);
const record = this.store.createRecord("query", query);
const response = await record.save();
return response.target;
}
_parseQuery(json) {
const parsed = JSON.parse(json);
const query = parsed.query;
if (!query || !query.sql) {
throw new TypeError();
}
query.id = 0; // 0 means no Id yet
return query;
}
_readFileAsTextAsync(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => {
resolve(reader.result);
};
reader.onerror = reject;
reader.readAsText(file);
});
}
@bind
dragMove(e) {
if (!e.movementY && !e.movementX) {
return;
}
const editPane = document.querySelector(".query-editor");
const target = editPane.querySelector(".panels-flex");
const grippie = editPane.querySelector(".grippie");
// we need to get the initial height / width of edit pane
// before we manipulate the size
if (!this.initialPaneWidth && !this.originalPaneHeight) {
this.originalPaneWidth = target.clientWidth;
this.originalPaneHeight = target.clientHeight;
}
const newHeight = Math.max(
this.originalPaneHeight,
target.clientHeight + e.movementY
);
const newWidth = Math.max(
this.originalPaneWidth,
target.clientWidth + e.movementX
);
target.style.height = newHeight + "px";
target.style.width = newWidth + "px";
grippie.style.width = newWidth + "px";
this.appEvents.trigger("ace:resize");
}
@bind
scrollTop() {
window.scrollTo(0, 0);
}
@action
async import(files) {
try {
this.loading = true;
const file = files[0];
const record = await this._importQuery(file);
this.addCreatedRecord(record);
} catch (e) {
if (e.jqXHR) {
popupAjaxError(e);
} else if (e instanceof SyntaxError) {
this.dialog.alert(i18n("explorer.import.unparseable_json"));
} else if (e instanceof TypeError) {
this.dialog.alert(i18n("explorer.import.wrong_json"));
} else {
this.dialog.alert(i18n("errors.desc.unknown"));
// eslint-disable-next-line no-console
console.error(e);
}
} finally {
this.loading = false;
}
}
@action
displayCreate() {
this.showCreate = true;
}
@action
updateSortProperty(property) {
if (this.sortByProperty === property) {
this.sortDescending = !this.sortDescending;
} else {
this.sortByProperty = property;
this.sortDescending = true;
}
}
@action
async create() {
try {
const name = this.newQueryName.trim();
this.loading = true;
this.showCreate = false;
const result = await this.store.createRecord("query", { name }).save();
this.addCreatedRecord(result.target);
} catch (error) {
popupAjaxError(error);
} finally {
this.loading = false;
}
}
@action
updateSearch(value) {
this.search = value;
}
@action
updateNewQueryName(value) {
this.newQueryName = value;
}
}