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

273 lines
7.3 KiB
JavaScript
Raw Normal View History

import { findRawTemplate } from "discourse-common/lib/raw-templates";
2020-09-04 13:23:11 +02:00
import I18n from "I18n";
2018-10-10 17:26:23 +05:30
import { ajax } from "discourse/lib/ajax";
2020-07-06 15:25:19 -04:00
import getURL from "discourse-common/lib/get-url";
2018-10-10 17:26:23 +05:30
import Badge from "discourse/models/badge";
2020-02-19 11:57:59 -05:00
import { default as computed } from "discourse-common/utils/decorators";
2015-06-30 15:12:12 -07:00
function randomIdShort() {
return "xxxxxxxx".replace(/[xy]/g, () => {
2015-09-14 15:34:57 -07:00
/*eslint-disable*/
2018-10-10 17:26:23 +05:30
return ((Math.random() * 16) | 0).toString(16);
2015-09-14 15:34:57 -07:00
/*eslint-enable*/
});
}
2015-06-30 15:12:12 -07:00
2015-08-25 21:36:39 -07:00
function transformedRelTable(table, modelClass) {
2015-08-25 20:48:19 -07:00
const result = {};
2020-09-04 13:23:11 +02:00
table.forEach((item) => {
2015-08-25 21:36:39 -07:00
if (modelClass) {
result[item.id] = modelClass.create(item);
} else {
result[item.id] = item;
}
2015-08-25 20:48:19 -07:00
});
return result;
}
2015-06-30 15:12:12 -07:00
const QueryResultComponent = Ember.Component.extend({
2018-10-10 17:26:23 +05:30
layoutName: "explorer-query-result",
2015-06-30 15:12:12 -07:00
2019-01-22 17:19:01 +05:30
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"),
chartDatasetName: Ember.computed.reads("columnDispNames.1"),
chartValues: Ember.computed.mapBy("content.rows", "1"),
showChart: false,
2018-10-10 17:26:23 +05:30
@computed("content.result_count")
resultCount(count) {
if (count === this.get("content.default_limit")) {
2018-10-10 17:26:23 +05:30
return I18n.t("explorer.max_result_count", { count });
} else {
2018-10-10 17:26:23 +05:30
return I18n.t("explorer.result_count", { count });
}
},
colCount: Ember.computed.reads("content.columns.length"),
2015-06-30 15:12:12 -07:00
@computed("content.duration")
duration(contentDuration) {
2018-10-10 17:26:23 +05:30
return I18n.t("explorer.run_time", {
2020-09-04 13:23:11 +02:00
value: I18n.toNumber(contentDuration, { precision: 1 }),
2018-10-10 17:26:23 +05:30
});
},
2015-06-30 15:12:12 -07:00
@computed("params.[]")
parameterAry(params) {
2015-06-30 15:12:12 -07:00
let arr = [];
2021-01-27 10:38:56 +01:00
for (let key in params) {
2015-06-30 15:12:12 -07:00
if (params.hasOwnProperty(key)) {
arr.push({ key, value: params[key] });
2015-06-30 15:12:12 -07:00
}
}
return arr;
},
2015-06-30 15:12:12 -07:00
@computed("content", "columns.[]")
columnDispNames(content, columns) {
if (!columns) {
2015-06-30 21:21:14 -07:00
return [];
2015-06-30 15:12:12 -07:00
}
2020-09-04 13:23:11 +02:00
return columns.map((colName) => {
2015-08-25 20:48:19 -07:00
if (colName.endsWith("_id")) {
return colName.slice(0, -3);
2015-06-30 15:12:12 -07:00
}
2018-10-10 17:26:23 +05:30
const dIdx = colName.indexOf("$");
2015-08-25 20:48:19 -07:00
if (dIdx >= 0) {
return colName.substring(dIdx + 1);
}
return colName;
2015-06-30 15:12:12 -07:00
});
},
2015-06-30 15:12:12 -07:00
@computed
fallbackTemplate() {
return findRawTemplate("javascripts/explorer/text");
},
2015-09-14 16:00:39 -07:00
@computed("content", "columns.[]")
columnTemplates(content, columns) {
if (!columns) {
2015-08-25 20:48:19 -07:00
return [];
}
return columns.map((colName, idx) => {
2015-08-25 20:48:19 -07:00
let viewName = "text";
if (this.get("content.colrender")[idx]) {
viewName = this.get("content.colrender")[idx];
2015-08-25 20:48:19 -07:00
}
const template = findRawTemplate(`javascripts/explorer/${viewName}`);
2018-10-10 17:26:23 +05:30
return { name: viewName, template };
2015-08-25 20:48:19 -07:00
});
},
2015-08-25 20:48:19 -07:00
@computed("content.relations.user")
transformedUserTable(contentRelationsUser) {
return transformedRelTable(contentRelationsUser);
},
@computed("content.relations.badge")
transformedBadgeTable(contentRelationsBadge) {
return transformedRelTable(contentRelationsBadge, Badge);
},
@computed("content.relations.post")
transformedPostTable(contentRelationsPost) {
return transformedRelTable(contentRelationsPost);
},
@computed("content.relations.topic")
transformedTopicTable(contentRelationsTopic) {
return transformedRelTable(contentRelationsTopic);
},
2015-08-25 20:48:19 -07:00
@computed("site.groups")
transformedGroupTable(groups) {
return transformedRelTable(groups);
},
2015-09-21 14:43:23 -07:00
@computed(
"rows.[]",
"content.colrender.[]",
"content.result_count",
"colCount"
)
canShowChart(rows, colRender, resultCount, colCount) {
const hasTwoColumns = colCount === 2;
const secondColumnContainsNumber =
resultCount > 0 && typeof rows[0][1] === "number";
const secondColumnContainsId = colRender[1];
return (
hasTwoColumns && secondColumnContainsNumber && !secondColumnContainsId
);
},
@computed("content.rows.[]", "content.colrender.[]")
chartLabels(rows, colRender) {
const labelSelectors = {
user: (user) => user.username,
badge: (badge) => badge.name,
topic: (topic) => topic.title,
group: (group) => group.name,
category: (category) => category.name,
};
const relationName = colRender[0];
if (relationName) {
const lookupFunc = this[`lookup${relationName.capitalize()}`];
const labelSelector = labelSelectors[relationName];
if (lookupFunc && labelSelector) {
return rows.map((r) => {
const relation = lookupFunc.call(this, r[0]);
const label = labelSelector(relation);
return this._cutChartLabel(label);
});
}
}
return rows.map((r) => this._cutChartLabel(r[0]));
},
2015-08-25 21:36:39 -07:00
lookupUser(id) {
return this.transformedUserTable[id];
2015-08-25 20:48:19 -07:00
},
2015-08-25 21:36:39 -07:00
lookupBadge(id) {
return this.transformedBadgeTable[id];
2015-08-25 21:36:39 -07:00
},
lookupPost(id) {
return this.transformedPostTable[id];
2015-08-25 21:36:39 -07:00
},
lookupTopic(id) {
return this.transformedTopicTable[id];
2015-08-25 21:36:39 -07:00
},
2015-09-21 14:43:23 -07:00
lookupGroup(id) {
return this.transformedGroupTable[id];
2015-09-21 14:43:23 -07:00
},
2015-08-25 21:36:39 -07:00
lookupCategory(id) {
2018-10-10 17:26:23 +05:30
return this.site.get("categoriesById")[id];
2015-08-25 21:36:39 -07:00
},
2015-08-25 20:48:19 -07:00
2019-09-11 09:09:41 -05:00
download_url() {
return this.group
? `/g/${this.group.name}/reports/`
: "/admin/plugins/explorer/queries/";
},
2015-08-03 15:07:29 -07:00
downloadResult(format) {
// Create a frame to submit the form in (?)
// to avoid leaving an about:blank behind
let windowName = randomIdShort();
2018-10-10 17:26:23 +05:30
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>";
2015-08-03 15:07:29 -07:00
2018-10-10 17:26:23 +05:30
window.open("data:text/html;base64," + btoa(newWindowContents), windowName);
2015-08-03 15:07:29 -07:00
let form = document.createElement("form");
2018-10-10 17:26:23 +05:30
form.setAttribute("id", "query-download-result");
form.setAttribute("method", "post");
form.setAttribute(
"action",
2020-07-06 15:25:19 -04:00
getURL(
2019-09-11 09:09:41 -05:00
this.download_url() +
2018-10-10 17:26:23 +05:30
this.get("query.id") +
"/run." +
format +
"?download=1"
)
);
form.setAttribute("target", windowName);
form.setAttribute("style", "display:none;");
2015-08-03 15:07:29 -07:00
2015-09-14 15:34:57 -07:00
function addInput(name, value) {
2015-08-03 15:07:29 -07:00
let field;
2018-10-10 17:26:23 +05:30
field = document.createElement("input");
field.setAttribute("name", name);
field.setAttribute("value", value);
2015-08-03 15:07:29 -07:00
form.appendChild(field);
}
addInput("params", JSON.stringify(this.params));
addInput("explain", this.hasExplain);
2018-10-10 17:26:23 +05:30
addInput("limit", "1000000");
2015-08-03 15:07:29 -07:00
2020-09-04 13:23:11 +02:00
ajax("/session/csrf.json").then((csrf) => {
2018-10-10 17:26:23 +05:30
addInput("authenticity_token", csrf.csrf);
2015-08-03 15:07:29 -07:00
document.body.appendChild(form);
form.submit();
Ember.run.schedule("afterRender", () => document.body.removeChild(form));
2015-08-03 15:07:29 -07:00
});
},
_cutChartLabel(label) {
const labelString = label.toString();
if (labelString.length > 25) {
return `${labelString.substring(0, 25)}...`;
} else {
return labelString;
}
},
actions: {
2015-08-03 15:07:29 -07:00
downloadResultJson() {
2018-10-10 17:26:23 +05:30
this.downloadResult("json");
2015-08-03 15:07:29 -07:00
},
downloadResultCsv() {
2018-10-10 17:26:23 +05:30
this.downloadResult("csv");
2020-09-04 13:23:11 +02:00
},
showChart() {
this.set("showChart", true);
},
showTable() {
this.set("showChart", false);
},
2020-09-04 13:23:11 +02:00
},
2015-06-30 15:12:12 -07:00
});
export default QueryResultComponent;