More work on interface, fixes for backend
This commit is contained in:
parent
01b38207d9
commit
2c71bc11aa
|
@ -1,3 +1,11 @@
|
|||
import buildPluginAdapter from 'discourse/adapters/build-plugin';
|
||||
|
||||
export default buildPluginAdapter('explorer');
|
||||
export default buildPluginAdapter('explorer').extend({
|
||||
|
||||
createRecord(store, type, args) {
|
||||
const typeField = Ember.String.underscore(type);
|
||||
return Discourse.ajax(this.pathFor(store, type), {method: 'POST', data: args}).then(function (json) {
|
||||
return new Result(json[typeField], json);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
import showModal from 'discourse/lib/show-modal';
|
||||
|
||||
export default Ember.Controller.extend({
|
||||
selectedItem: null,
|
||||
|
||||
actions: {
|
||||
selectItem(item) {
|
||||
this.set('selectedItem', item);
|
||||
},
|
||||
|
||||
dummy() {},
|
||||
|
||||
create() {
|
||||
var newQuery = this.store.createRecord('query', {name: this.get('newQueryName')});
|
||||
newQuery.save();
|
||||
},
|
||||
|
||||
importQuery() {
|
||||
showModal('import-query');
|
||||
},
|
||||
|
||||
run() {
|
||||
const self = this;
|
||||
this.set('loading', true);
|
||||
Discourse.ajax("/admin/plugins/explorer/query/" + this.get('selectedItem.id') + "/run", {
|
||||
type: "POST",
|
||||
data: {
|
||||
params: JSON.stringify({foo: 34}),
|
||||
explain: true
|
||||
}
|
||||
}).then(function(result) {
|
||||
console.log(result);
|
||||
self.set('results', result);
|
||||
}).finally(function() {
|
||||
self.set('loading', false);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
|
@ -1,5 +0,0 @@
|
|||
|
||||
|
||||
export default Ember.ArrayController.extend({
|
||||
|
||||
});
|
|
@ -22,7 +22,7 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
|||
const object = JSON.parse(this.get('queryFile')).query;
|
||||
|
||||
// Slight fixup before creating object
|
||||
delete object.id;
|
||||
object.id = 0; // 0 means no Id yet
|
||||
|
||||
this.set('loading', true);
|
||||
this.store.createRecord('query', object).save().then(function(query) {
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
import RestModel from 'discourse/models/rest';
|
||||
|
||||
const Query = RestModel.extend({
|
||||
createProperties() {
|
||||
return this.getProperties("name", "description");
|
||||
},
|
||||
|
||||
run() {
|
||||
console.log("Called query#run");
|
||||
}
|
||||
});
|
||||
|
||||
console.log('query model loaded');
|
||||
|
||||
export default Query;
|
|
@ -1,22 +1,9 @@
|
|||
import showModal from 'discourse/lib/show-modal';
|
||||
|
||||
|
||||
export default Discourse.Route.extend({
|
||||
controllerName: 'admin-plugins-explorer',
|
||||
|
||||
model() {
|
||||
return this.store.findAll('query');
|
||||
},
|
||||
|
||||
setupController(controller, model) {
|
||||
|
||||
},
|
||||
|
||||
actions: {
|
||||
create() {
|
||||
|
||||
},
|
||||
importQuery() {
|
||||
showModal('import-query');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
{{#if model}}
|
||||
<h2>{{model.name}}</h2>
|
||||
<div>{{model.description}}</div>
|
||||
{{textarea value=model.sql}}
|
||||
{{d-button action="run" label="explorer.run"}}
|
||||
{{/if}}
|
|
@ -1,8 +1,23 @@
|
|||
{{text-field value=newQueryName placeholderKey="explorer.create_placeholder"}}
|
||||
{{d-button action="create" label="explorer.create" icon="plus"}}
|
||||
{{d-button action="importQuery" label="explorer.import.label" icon="upload"}}
|
||||
{{d-button action="importQuery" label="explorer.import.label" icon="upload" class="import-button"}}
|
||||
|
||||
{{#each query in model}}
|
||||
<div class="row">
|
||||
{{query.name}}
|
||||
</div>
|
||||
{{/each}}
|
||||
<h3>Queries</h3>
|
||||
<table class="query-list">
|
||||
<thead>
|
||||
<th class="q-name">Name</th>
|
||||
<th class="q-desc">Description</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#each query in content}}
|
||||
<tr {{action "selectItem" query}}>
|
||||
<td class="q-name">{{query.name}}</td>
|
||||
<td class="q-desc">{{query.description}}</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{{render "admin/plugins-explorer-show" selectedItem}}
|
||||
|
||||
{{! results }}
|
||||
|
|
|
@ -23,8 +23,9 @@ en:
|
|||
explorer:
|
||||
title: "Data Explorer"
|
||||
create: "Create New"
|
||||
create_placeholder: "Query name..."
|
||||
import:
|
||||
label: "Import"
|
||||
modal: "Import A Query"
|
||||
export: "Export"
|
||||
|
||||
run: "Run Query"
|
||||
|
|
24
plugin.rb
24
plugin.rb
|
@ -75,9 +75,7 @@ after_initialize do
|
|||
|
||||
query_args = query.defaults.merge(params)
|
||||
|
||||
time_start, time_end = nil
|
||||
explain = nil
|
||||
err = nil
|
||||
time_start, time_end, explain, err, result = nil
|
||||
begin
|
||||
ActiveRecord::Base.connection.transaction do
|
||||
# Setting transaction to read only prevents shoot-in-foot actions like SELECT FOR UPDATE
|
||||
|
@ -87,7 +85,7 @@ after_initialize do
|
|||
/*
|
||||
DataExplorer Query
|
||||
Query: /admin/plugins/explorer/#{query.id}
|
||||
Started by: #{current_user}
|
||||
Started by: #{opts[:current_user]}
|
||||
*/
|
||||
WITH query AS (
|
||||
|
||||
|
@ -143,7 +141,7 @@ SQL
|
|||
def self.alloc_id
|
||||
DistributedMutex.synchronize('data-explorer_query-id') do
|
||||
max_id = DataExplorer.pstore_get("q:_id")
|
||||
max_id = 0 unless max_id
|
||||
max_id = 1 unless max_id
|
||||
DataExplorer.pstore_set("q:_id", max_id + 1)
|
||||
max_id
|
||||
end
|
||||
|
@ -185,7 +183,7 @@ SQL
|
|||
end
|
||||
|
||||
def save
|
||||
unless @id
|
||||
unless @id && @id > 0
|
||||
@id = self.class.alloc_id
|
||||
end
|
||||
DataExplorer.pstore_set "q:#{id}", to_hash
|
||||
|
@ -195,9 +193,15 @@ SQL
|
|||
DataExplorer.pstore_delete "q:#{id}"
|
||||
end
|
||||
|
||||
def read_attribute_for_serialization(attr)
|
||||
self.send(attr)
|
||||
end
|
||||
|
||||
def self.all
|
||||
PluginStoreRow.where(plugin_name: DataExplorer.plugin_name).where("key LIKE 'q:%'").map do |psr|
|
||||
next if psr.key == "q:_id"
|
||||
PluginStoreRow.where(plugin_name: DataExplorer.plugin_name)
|
||||
.where("key LIKE 'q:%'")
|
||||
.where("key != 'q:_id'")
|
||||
.map do |psr|
|
||||
DataExplorer::Query.from_hash PluginStore.cast_value(psr.type_name, psr.value)
|
||||
end
|
||||
end
|
||||
|
@ -265,7 +269,7 @@ SQL
|
|||
def run
|
||||
query = DataExplorer::Query.find(params[:id].to_i)
|
||||
query_params = MultiJson.load(params[:params])
|
||||
opts = {}
|
||||
opts = {current_user: current_user.username}
|
||||
opts[:explain] = true if params[:explain]
|
||||
result = DataExplorer.run_query(query, query_params, opts)
|
||||
|
||||
|
@ -293,7 +297,7 @@ SQL
|
|||
success: true,
|
||||
errors: [],
|
||||
params: query_params,
|
||||
duration: result[:duration_nanos].to_f * 1_000_000,
|
||||
duration: (result[:duration_nanos].to_f / 1_000_000).round(1),
|
||||
columns: cols,
|
||||
}
|
||||
json[:explain] = result[:explain] if opts[:explain]
|
||||
|
|
Loading…
Reference in New Issue