discourse-data-explorer/assets/javascripts/discourse/components/query-result.js.es6

204 lines
5.9 KiB
JavaScript

import { ajax } from "discourse/lib/ajax";
import Badge from "discourse/models/badge";
import { getOwner } from "discourse-common/lib/get-owner";
import { default as computed } from "ember-addons/ember-computed-decorators";
function randomIdShort() {
return "xxxxxxxx".replace(/[xy]/g, function() {
/*eslint-disable*/
return ((Math.random() * 16) | 0).toString(16);
/*eslint-enable*/
});
}
function transformedRelTable(table, modelClass) {
const result = {};
table.forEach(function(item) {
if (modelClass) {
result[item.id] = modelClass.create(item);
} else {
result[item.id] = item;
}
});
return result;
}
const QueryResultComponent = Ember.Component.extend({
layoutName: "explorer-query-result",
rows: Ember.computed.alias("content.rows"),
columns: Ember.computed.alias("content.columns"),
params: Ember.computed.alias("content.params"),
explainText: Ember.computed.alias("content.explain"),
hasExplain: Ember.computed.notEmpty("content.explain"),
@computed("content.result_count")
resultCount: function(count) {
if (count === this.get("content.default_limit")) {
return I18n.t("explorer.max_result_count", { count });
} else {
return I18n.t("explorer.result_count", { count });
}
},
colCount: function() {
return this.get("content.columns").length;
}.property("content.columns.length"),
duration: function() {
return I18n.t("explorer.run_time", {
value: I18n.toNumber(this.get("content.duration"), { precision: 1 })
});
}.property("content.duration"),
parameterAry: function() {
let arr = [];
const params = this.get("params");
for (var key in params) {
if (params.hasOwnProperty(key)) {
arr.push({ key: key, value: params[key] });
}
}
return arr;
}.property("params.[]"),
columnDispNames: function() {
if (!this.get("columns")) {
return [];
}
return this.get("columns").map(function(colName) {
if (colName.endsWith("_id")) {
return colName.slice(0, -3);
}
const dIdx = colName.indexOf("$");
if (dIdx >= 0) {
return colName.substring(dIdx + 1);
}
return colName;
});
}.property("content", "columns.[]"),
fallbackTemplate: function() {
return getOwner(this).lookup("template:explorer/text.raw");
}.property(),
columnTemplates: function() {
const self = this;
if (!this.get("columns")) {
return [];
}
return this.get("columns").map(function(colName, idx) {
let viewName = "text";
if (self.get("content.colrender")[idx]) {
viewName = self.get("content.colrender")[idx];
}
// After `findRawTemplates` is in stable this should be updated to use that
let template = getOwner(self).lookup(
"template:explorer/" + viewName + ".raw"
);
if (!template) {
template = Discourse.RAW_TEMPLATES[`javascripts/explorer/${viewName}`];
}
return { name: viewName, template };
});
}.property("content", "columns.[]"),
transformedUserTable: function() {
return transformedRelTable(this.get("content.relations.user"));
}.property("content.relations.user"),
transformedBadgeTable: function() {
return transformedRelTable(this.get("content.relations.badge"), Badge);
}.property("content.relations.badge"),
transformedPostTable: function() {
return transformedRelTable(this.get("content.relations.post"));
}.property("content.relations.post"),
transformedTopicTable: function() {
return transformedRelTable(this.get("content.relations.topic"));
}.property("content.relations.topic"),
transformedGroupTable: function() {
return transformedRelTable(this.get("site.groups"));
}.property("site.groups"),
lookupUser(id) {
return this.get("transformedUserTable")[id];
},
lookupBadge(id) {
return this.get("transformedBadgeTable")[id];
},
lookupPost(id) {
return this.get("transformedPostTable")[id];
},
lookupTopic(id) {
return this.get("transformedTopicTable")[id];
},
lookupGroup(id) {
return this.get("transformedGroupTable")[id];
},
lookupCategory(id) {
return this.site.get("categoriesById")[id];
},
downloadResult(format) {
// Create a frame to submit the form in (?)
// to avoid leaving an about:blank behind
let windowName = randomIdShort();
const newWindowContents =
"<style>body{font-size:36px;display:flex;justify-content:center;align-items:center;}</style><body>Click anywhere to close this window once the download finishes.<script>window.onclick=function(){window.close()};</script>";
window.open("data:text/html;base64," + btoa(newWindowContents), windowName);
let form = document.createElement("form");
form.setAttribute("id", "query-download-result");
form.setAttribute("method", "post");
form.setAttribute(
"action",
Discourse.getURL(
"/admin/plugins/explorer/queries/" +
this.get("query.id") +
"/run." +
format +
"?download=1"
)
);
form.setAttribute("target", windowName);
form.setAttribute("style", "display:none;");
function addInput(name, value) {
let field;
field = document.createElement("input");
field.setAttribute("name", name);
field.setAttribute("value", value);
form.appendChild(field);
}
addInput("params", JSON.stringify(this.get("params")));
addInput("explain", this.get("hasExplain"));
addInput("limit", "1000000");
ajax("/session/csrf.json").then(function(csrf) {
addInput("authenticity_token", csrf.csrf);
document.body.appendChild(form);
form.submit();
Ember.run.next("afterRender", function() {
document.body.removeChild(form);
});
});
},
actions: {
downloadResultJson() {
this.downloadResult("json");
},
downloadResultCsv() {
this.downloadResult("csv");
}
}
});
export default QueryResultComponent;