Add 'download results as CSV'

This commit is contained in:
Kane York 2015-08-03 15:07:29 -07:00
parent d1a58e83a2
commit 1601f4f269
4 changed files with 87 additions and 56 deletions

View File

@ -100,43 +100,50 @@ const QueryResultComponent = Ember.Component.extend({
}); });
}.property('content', 'columns.@each'), }.property('content', 'columns.@each'),
downloadResult(format) {
// Create a frame to submit the form in (?)
// to avoid leaving an about:blank behind
let windowName = randomIdShort();
const newWindowContents = "<body>Click anywhere to close this window once the download finishes.<script>window.onclick=function(){window.close()};</script>";
let newWindow = 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(form, name, value) {
let field;
field = document.createElement('input');
field.setAttribute('name', name);
field.setAttribute('value', value);
form.appendChild(field);
}
addInput(form, 'params', JSON.stringify(this.get('params')));
addInput(form, 'explain', this.get('hasExplain'));
addInput(form, 'limit', '1000000');
Discourse.ajax('/session/csrf.json').then(function(csrf) {
addInput(form, 'authenticity_token', csrf.csrf);
document.body.appendChild(form);
form.submit();
Em.run.next('afterRender', function() {
document.body.removeChild(form);
})
});
},
actions: { actions: {
downloadResult() { downloadResultJson() {
// Create a frame to submit the form in (?) this.downloadResult('json');
// to avoid leaving an about:blank behind },
let windowName = randomIdShort(); downloadResultCsv() {
const newWindowContents = "<body>Click anywhere to close this window once the download finishes.<script>window.onclick=function(){window.close()};</script>"; this.downloadResult('csv');
let newWindow = 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.json?download=1'));
form.setAttribute('target', windowName);
form.setAttribute('style', 'display:none;');
function addInput(form, name, value) {
let field;
field = document.createElement('input');
field.setAttribute('name', name);
field.setAttribute('value', value);
form.appendChild(field);
}
addInput(form, 'params', JSON.stringify(this.get('params')));
addInput(form, 'explain', this.get('hasExplain'));
addInput(form, 'limit', '1000000');
Discourse.ajax('/session/csrf.json').then(function(csrf) {
addInput(form, 'authenticity_token', csrf.csrf);
document.body.appendChild(form);
form.submit();
Em.run.next('afterRender', function() {
document.body.removeChild(form);
})
});
} }
}, },

View File

@ -1,5 +1,7 @@
<div class="result-info"> <div class="result-info">
{{d-button action="downloadResult" icon="download" label="explorer.download_json"}} {{i18n "explorer.download"}}
{{d-button action="downloadResultJson" icon="download" label="explorer.download_json"}}
{{d-button action="downloadResultCsv" icon="download" label="explorer.download_csv"}}
<div class="result-about"> <div class="result-about">
{{duration}} {{duration}}
</div> </div>

View File

@ -46,13 +46,15 @@ en:
edit: "Edit" edit: "Edit"
delete: "Delete" delete: "Delete"
recover: "Undelete Query" recover: "Undelete Query"
download_json: "Download Results" download: "Download Results"
download_json: "JSON"
download_csv: "CSV"
others_dirty: "A query has unsaved changes that will be lost if you navigate away." others_dirty: "A query has unsaved changes that will be lost if you navigate away."
run_time: "Query completed in {{value}} ms." run_time: "Query completed in {{value}} ms."
column: "Column {{number}}" column: "Column {{number}}"
explain_label: "Include query plan?" explain_label: "Include query plan?"
save_params: "Set Defaults" save_params: "Set Defaults"
reset_params: "Reset" reset_params: "Reset"
https_warning: "Use of the Data Explorer on sites not protected by HTTPS is discouraged. Please be careful to not retrieve sensitive information over insecure links." https_warning: "This site is not protected by HTTPS. Please be careful to not retrieve sensitive information over insecure links."
no_queries: "There are no queries. Why not " no_queries: "There are no queries. Why not "
no_queries_hook: "create one?" no_queries_hook: "create one?"

View File

@ -917,8 +917,6 @@ SQL
check_xhr unless params[:download] check_xhr unless params[:download]
query = DataExplorer::Query.find(params[:id].to_i) query = DataExplorer::Query.find(params[:id].to_i)
if params[:download] if params[:download]
response.headers['Content-Disposition'] =
"attachment; filename=#{query.slug}@#{Slug.for(Discourse.current_hostname, 'discourse')}-#{Date.today}.dcqresult.json"
response.sending_file = true response.sending_file = true
end end
@ -952,23 +950,45 @@ SQL
else else
pg_result = result[:pg_result] pg_result = result[:pg_result]
cols = pg_result.fields cols = pg_result.fields
json = { respond_to do |format|
success: true, format.json do
errors: [], if params[:download]
duration: (result[:duration_secs].to_f * 1000).round(1), response.headers['Content-Disposition'] =
params: query_params, "attachment; filename=#{query.slug}@#{Slug.for(Discourse.current_hostname, 'discourse')}-#{Date.today}.dcqresult.json"
columns: cols, end
} json = {
json[:explain] = result[:explain] if opts[:explain] success: true,
# TODO - special serialization errors: [],
# This is dead code in the client right now duration: (result[:duration_secs].to_f * 1000).round(1),
# if cols.any? { |col_name| special_serialization? col_name } params: query_params,
# json[:relations] = DataExplorer.add_extra_data(pg_result) columns: cols,
# end }
json[:explain] = result[:explain] if opts[:explain]
# TODO - special serialization
# This is dead code in the client right now
# if cols.any? { |col_name| special_serialization? col_name }
# json[:relations] = DataExplorer.add_extra_data(pg_result)
# end
json[:rows] = pg_result.values json[:rows] = pg_result.values
render json: json render json: json
end
format.csv do
response.headers['Content-Disposition'] =
"attachment; filename=#{query.slug}@#{Slug.for(Discourse.current_hostname, 'discourse')}-#{Date.today}.dcqresult.csv"
require 'csv'
text = CSV.generate do |csv|
csv << cols
pg_result.values.each do |row|
csv << row
end
end
render text: text
end
end
end end
end end
end end