188 lines
4.6 KiB
JavaScript
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;
|
||
|
|
}
|
||
|
|
}
|