Work on new parameter model
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
const layoutMap = {
|
||||
int: 'int',
|
||||
bigint: 'int',
|
||||
boolean: 'boolean',
|
||||
string: 'generic',
|
||||
time: 'generic',
|
||||
date: 'generic',
|
||||
datetime: 'generic',
|
||||
double: 'string',
|
||||
inet: 'generic',
|
||||
user_id: 'user_id',
|
||||
post_id: 'string',
|
||||
topic_id: 'int',
|
||||
category_id: 'int',
|
||||
group_id: 'int',
|
||||
badge_id: 'int',
|
||||
int_list: 'generic',
|
||||
string_list: 'generic'
|
||||
};
|
||||
|
||||
function allowsInputTypeTime() {
|
||||
try {
|
||||
const inp = document.createElement('input');
|
||||
inp.attributes.type = 'time';
|
||||
inp.attributes.type = 'date';
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export default Ember.Component.extend({
|
||||
|
||||
classNameBindings: ['valid:valid:invalid', ':param'],
|
||||
|
||||
boolTypes: [ {name: I18n.t('explorer.types.bool.true'), id: 'Y'}, {name: I18n.t('explorer.types.bool.false'), id: 'N'}, {name: I18n.t('explorer.types.bool.null_'), id: '#null'} ],
|
||||
|
||||
value: function(key, value, previousValue) {
|
||||
if (arguments.length > 1) {
|
||||
this.get('params')[this.get('info.identifier')] = value.toString();
|
||||
}
|
||||
return this.get('params')[this.get('info.identifier')];
|
||||
}.property('params', 'pname'),
|
||||
|
||||
valid: function() {
|
||||
const type = this.get('info.type'),
|
||||
value = this.get('value');
|
||||
|
||||
if (Em.isEmpty(this.get('value'))) {
|
||||
return this.get('info.nullable');
|
||||
}
|
||||
|
||||
function matches(regex) {
|
||||
return regex.test(value);
|
||||
}
|
||||
|
||||
const intVal = parseInt(value, 10);
|
||||
const intValid = !isNaN(intVal) && intVal < 2147483648 && intVal > -2147483649;
|
||||
switch (type) {
|
||||
case 'int':
|
||||
return /^-?\d+$/.test(value) && intValid;
|
||||
case 'bigint':
|
||||
return /^-?\d+$/.test(value) && !isNaN(intVal);
|
||||
case 'boolean':
|
||||
return /^Y|N|#null|true|false/.test(value);
|
||||
case 'double':
|
||||
return !isNaN(parseFloat(value));
|
||||
case 'int_list':
|
||||
return value.split(',').every(function(i) {
|
||||
return /^(-?\d+|null)$/.test(i.trim());
|
||||
});
|
||||
case 'post_id':
|
||||
return /^\d+$/.test(value) || /\d+\/\d+(\?u=.*)?$/.test(value);
|
||||
}
|
||||
return true;
|
||||
}.property('value', 'info.type', 'info.nullable'),
|
||||
|
||||
layoutType: function() {
|
||||
const type = this.get('info.type');
|
||||
if ((type === "time" || type === "date") && !allowsInputTypeTime()) {
|
||||
return "string";
|
||||
}
|
||||
if (layoutMap[type]) {
|
||||
return layoutMap[type];
|
||||
}
|
||||
return type;
|
||||
}.property('info.type'),
|
||||
|
||||
layoutName: function() {
|
||||
return "admin/components/q-params/" + this.get('layoutType');
|
||||
}.property('layoutType')
|
||||
});
|
||||
@@ -7,37 +7,35 @@ const Query = RestModel.extend({
|
||||
|
||||
_init: function() {
|
||||
this._super();
|
||||
if (!this.get('options')) {
|
||||
this.set('options', {defaults:{}});
|
||||
}
|
||||
this.set('dirty', false);
|
||||
}.on('init'),
|
||||
|
||||
_initParams: function() {
|
||||
this.resetParams();
|
||||
}.on('init').observes('param_names'),
|
||||
|
||||
// the server uses 'qopts' and the client uses 'options' due to ActiveRecord
|
||||
// freaking out if a serialized value is named 'options'
|
||||
options: Em.computed.alias('qopts'),
|
||||
}.on('init').observes('param_info'),
|
||||
|
||||
markDirty: function() {
|
||||
this.set('dirty', true);
|
||||
}.observes('name', 'description', 'sql', 'options', 'options.defaults'),
|
||||
}.observes('name', 'description', 'sql'),
|
||||
|
||||
markNotDirty() {
|
||||
this.set('dirty', false);
|
||||
},
|
||||
|
||||
hasParams: function() {
|
||||
return this.get('param_info.length') > 0;
|
||||
}.property('param_info'),
|
||||
|
||||
resetParams() {
|
||||
const newParams = {};
|
||||
const oldParams = this.get('params');
|
||||
const defaults = this.get('options.defaults') || {};
|
||||
(this.get('param_names') || []).forEach(function(name) {
|
||||
if (defaults[name]) {
|
||||
newParams[name] = defaults[name];
|
||||
} else if (oldParams[name]) {
|
||||
const paramInfo = this.get('param_info') || [];
|
||||
paramInfo.forEach(function(pinfo) {
|
||||
const name = pinfo.identifier;
|
||||
if (oldParams[pinfo.identifier]) {
|
||||
newParams[name] = oldParams[name];
|
||||
} else if (pinfo['default'] !== null) {
|
||||
newParams[name] = pinfo['default'];
|
||||
} else {
|
||||
newParams[name] = '';
|
||||
}
|
||||
@@ -45,19 +43,6 @@ const Query = RestModel.extend({
|
||||
this.set('params', newParams);
|
||||
},
|
||||
|
||||
saveDefaults() {
|
||||
const currentParams = this.get('params');
|
||||
let defaults = {};
|
||||
(this.get('param_names') || []).forEach(function(name) {
|
||||
if (currentParams[name]) {
|
||||
defaults[name] = currentParams[name];
|
||||
} else {
|
||||
delete defaults[name];
|
||||
}
|
||||
});
|
||||
this.set('options.defaults', defaults);
|
||||
},
|
||||
|
||||
downloadUrl: function() {
|
||||
// TODO - can we change this to use the store/adapter?
|
||||
return Discourse.getURL("/admin/plugins/explorer/queries/" + this.get('id') + ".json?export=1");
|
||||
@@ -88,15 +73,11 @@ const Query = RestModel.extend({
|
||||
props.id = this.get('id');
|
||||
}
|
||||
return props;
|
||||
},
|
||||
|
||||
run() {
|
||||
console.log("Called query#run");
|
||||
}
|
||||
});
|
||||
|
||||
Query.reopenClass({
|
||||
updatePropertyNames: ["name", "description", "sql", "qopts"]
|
||||
updatePropertyNames: ["name", "description", "sql"]
|
||||
});
|
||||
|
||||
export default Query;
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
{{#if info.nullable}}
|
||||
{{combo-box valueAttribute="id" value=value nameProperty="name" content=boolTypes}}
|
||||
{{else}}
|
||||
{{input type="checkbox" checked=value}}
|
||||
{{/if}}
|
||||
<span class="param-name">{{info.identifier}}</span>
|
||||
@@ -0,0 +1,2 @@
|
||||
{{text-field value=value}}
|
||||
<span class="param-name">{{info.identifier}}</span>
|
||||
@@ -0,0 +1,2 @@
|
||||
{{input type="number" value=value}}
|
||||
<span class="param-name">{{info.identifier}}</span>
|
||||
@@ -0,0 +1,2 @@
|
||||
{{text-field value=value}}
|
||||
<span class="param-name">{{info.identifier}}</span>
|
||||
@@ -0,0 +1,2 @@
|
||||
{{user-selector usernames=value single="true"}}
|
||||
<span class="param-name">{{info.identifier}}</span>
|
||||
@@ -75,14 +75,20 @@
|
||||
|
||||
<div class="clear"></div>
|
||||
<div class="pull-left">
|
||||
{{d-button action="save" label="explorer.save" disabled=saveDisabled class="btn-primary"}}
|
||||
{{#if everEditing}}
|
||||
{{d-button action="save" label="explorer.save" disabled=saveDisabled class="btn-primary"}}
|
||||
{{else}}
|
||||
{{d-button action="editName" label="explorer.edit" icon="pencil" class="btn-primary"}}
|
||||
{{/if}}
|
||||
{{d-button action="download" label="explorer.export" disabled=runDisabled icon="download"}}
|
||||
</div>
|
||||
<div class="pull-right">
|
||||
{{#if selectedItem.destroyed}}
|
||||
{{d-button action="recover" class="" icon="undo" label="explorer.recover"}}
|
||||
{{else}}
|
||||
{{d-button action="discard" class="btn-danger" icon="undo" label="explorer.undo" disabled=saveDisabled}}
|
||||
{{#if everEditing}}
|
||||
{{d-button action="discard" class="btn-danger" icon="undo" label="explorer.undo" disabled=saveDisabled}}
|
||||
{{/if}}
|
||||
{{d-button action="destroy" class="btn-danger" icon="trash" label="explorer.delete"}}
|
||||
{{/if}}
|
||||
</div>
|
||||
@@ -91,17 +97,14 @@
|
||||
</div>
|
||||
|
||||
<form class="query-run" {{action "run" on="submit"}}>
|
||||
{{#if selectedItem.param_names}}
|
||||
{{#if selectedItem.hasParams}}
|
||||
<div class="query-params">
|
||||
<div class="param-save">
|
||||
{{d-button action="saveDefaults" label="explorer.save_params" type="button"}}
|
||||
{{d-button action="resetParams" label="explorer.reset_params" type="button"}}
|
||||
</div>
|
||||
{{#each selectedItem.param_names as |pname|}}
|
||||
<div class="param">
|
||||
{{param-field params=selectedItem.params pname=pname}}
|
||||
<span class="param-name">{{pname}}</span>
|
||||
</div>
|
||||
{{#each selectedItem.param_info as |pinfo|}}
|
||||
{{param-input params=selectedItem.params info=pinfo}}
|
||||
{{! <div class="param">
|
||||
{{param-field params=selectedItem.params pname=pinfo.identifier type=pinfo.type}
|
||||
<span class="param-name">{{pinfo.identifier}</span>
|
||||
</div> }}
|
||||
{{/each}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
Reference in New Issue
Block a user