Merge pull request #4924 from epixa/4684-unknown-settings

Allow modifying unknown/custom advanced settings
This commit is contained in:
Joe Fleming 2015-09-14 08:54:06 -07:00
commit 89d0b168ca
9 changed files with 200 additions and 34 deletions

View file

@ -1,9 +1,12 @@
<tr ng-class="conf.value === undefined ? 'default' : 'custom'">
<td class="name">
<b>{{conf.name}}</b>
<span class="smaller" ng-show="conf.value !== undefined">
<span class="smaller" ng-show="!conf.isCustom && conf.value !== undefined">
(Default: <i>{{conf.defVal == undefined ? 'null' : conf.defVal}}</i>)
</span>
<span class="smaller" ng-show="conf.isCustom">
(Custom setting)
</span>
<br>
<span class="smaller" ng-bind-html="conf.description | trustAsHtml"></span>
</td>

View file

@ -2,9 +2,12 @@
<kbn-settings-advanced class="container">
<div class="bs-callout bs-callout-warning">
<h4>Caution: You can break stuff here</h4>
Be careful in here, these settings are for very advanced users only. Tweaks you make here can break large portions of Kibana.
Some of these settings may be undocumented, unsupported or experimental. Blanking a field will cause Kibana to use its internal
defaults which may be unacceptable given other configuration directives.
Be careful in here, these settings are for very advanced users only.
Tweaks you make here can break large portionsof Kibana. Some of these
settings may be undocumented, unsupported or experimental. If a field has
a default value, blanking the field will reset it to its default which
may be unacceptable given other configuration directives. Deleting a
custom setting will permanently remove it from Kibana's config.
</div>
<form role="form">
<input aria-label="Filter" ng-model="advancedFilter" class="form-control span12" type="text" placeholder="Filter"/>

View file

@ -1,6 +1,6 @@
define(function (require) {
var _ = require('lodash');
var getValType = require('plugins/kibana/settings/sections/advanced/lib/get_val_type');
var toEditableConfig = require('plugins/kibana/settings/sections/advanced/lib/to_editable_config');
require('plugins/kibana/settings/sections/advanced/advanced_row');
@ -20,46 +20,34 @@ define(function (require) {
ESC: 27
};
var NAMED_EDITORS = ['json', 'array', 'boolean', 'select'];
var NORMAL_EDITOR = ['number', 'string', 'null', 'undefined'];
function getEditorType(conf) {
if (_.contains(NAMED_EDITORS, conf.type)) return conf.type;
if (_.contains(NORMAL_EDITOR, conf.type)) return 'normal';
}
function isTypeComplex(conf) {
return !(conf.json || conf.array || conf.bool || conf.normal);
}
function notDefaultConfig(configName) {
return !(configName in configDefaults);
}
function readConfigVals() {
var configVals = config._vals();
$scope.configs = _.map(configDefaults, function (def, name) {
var val = configVals[name];
var conf = {
name: name,
defVal: def.value,
type: getValType(def, val),
description: def.description,
options: def.options,
value: val,
};
var customConfig = Object.keys(configVals)
.filter(notDefaultConfig)
.map(name => toEditableConfig(false, name, configVals[name]));
var editor = getEditorType(conf);
conf.json = editor === 'json';
conf.select = editor === 'select';
conf.bool = editor === 'boolean';
conf.array = editor === 'array';
conf.normal = editor === 'normal';
conf.tooComplex = !editor;
return conf;
});
$scope.configs = _(configDefaults)
.map((def, name) => toEditableConfig(def, name, configVals[name]))
.reject('readonly')
.concat(customConfig)
.value();
}
// react to changes of the config values
var unhook = $rootScope.$on('change:config', readConfigVals);
$scope.$on('$destroy', unhook);
// initial config setup
readConfigVals();
$rootScope.$on('change:config', readConfigVals);
}
};
});

View file

@ -0,0 +1,27 @@
var getEditorType = require('plugins/kibana/settings/sections/advanced/lib/get_editor_type');
var expect = require('expect.js');
describe('Settings', function () {
describe('Advanced', function () {
describe('getEditorType(conf)', function () {
context('when given type has a named editor', function () {
it('returns that named editor', function () {
expect(getEditorType({ type: 'json' })).to.equal('json');
expect(getEditorType({ type: 'array' })).to.equal('array');
expect(getEditorType({ type: 'boolean' })).to.equal('boolean');
expect(getEditorType({ type: 'select' })).to.equal('select');
});
});
context('when given a type of number, string, null, or undefined', function () {
it('returns "normal"', function () {
expect(getEditorType({ type: 'number' })).to.equal('normal');
expect(getEditorType({ type: 'string' })).to.equal('normal');
expect(getEditorType({ type: 'null' })).to.equal('normal');
expect(getEditorType({ type: 'undefined' })).to.equal('normal');
});
});
});
});
});

View file

@ -0,0 +1,86 @@
var toEditableConfig = require('plugins/kibana/settings/sections/advanced/lib/to_editable_config');
var expect = require('expect.js');
describe('Settings', function () {
describe('Advanced', function () {
describe('toEditableConfig(def, name, value)', function () {
it('sets name', function () {
expect(invoke({ name: 'who' }).name).to.equal('who');
});
it('sets value', function () {
expect(invoke({ value: 'what' }).value).to.equal('what');
});
it('sets type', function () {
expect(invoke({ value: 'what' }).type).to.be('string');
expect(invoke({ value: 0 }).type).to.be('number');
expect(invoke({ value: [] }).type).to.be('array');
});
context('when given a setting definition object', function () {
var def;
beforeEach(function () {
def = {
value: 'the original',
description: 'the one and only',
options: 'all the options'
};
});
it('is not marked as custom', function () {
expect(invoke({ def }).isCustom).to.be.false;
});
it('sets a default value', function () {
expect(invoke({ def }).defVal).to.equal(def.value);
});
it('sets a description', function () {
expect(invoke({ def }).description).to.equal(def.description);
});
it('sets options', function () {
expect(invoke({ def }).options).to.equal(def.options);
});
context('that contains a type', function () {
it('sets that type', function () {
def.type = 'something';
expect(invoke({ def }).type).to.equal(def.type);
});
});
context('that contains a value of type array', function () {
it('sets type to array', function () {
def.value = [];
expect(invoke({ def }).type).to.equal('array');
});
});
});
context('when not given a setting definition object', function () {
it('is marked as custom', function () {
expect(invoke().isCustom).to.be.true;
});
it('sets defVal to undefined', function () {
expect(invoke().defVal).to.be.undefined;
});
it('sets description to undefined', function () {
expect(invoke().description).to.be.undefined;
});
it('sets options to undefined', function () {
expect(invoke().options).to.be.undefined;
});
});
});
});
});
function invoke({ def = false, name = 'woah', value = 'forreal' } = {}) {
return toEditableConfig(def, name, value);
}

View file

@ -0,0 +1,17 @@
define(function (require) {
var _ = require('lodash');
var NAMED_EDITORS = ['json', 'array', 'boolean', 'select'];
var NORMAL_EDITOR = ['number', 'string', 'null', 'undefined'];
/**
* @param {object} advanced setting configuration object
* @returns {string} the editor type to use when editing value
*/
function getEditorType(conf) {
if (_.contains(NAMED_EDITORS, conf.type)) return conf.type;
if (_.contains(NORMAL_EDITOR, conf.type)) return 'normal';
}
return getEditorType;
});

View file

@ -0,0 +1,39 @@
define(function (require) {
var _ = require('lodash');
var getValType = require('./get_val_type');
var getEditorType = require('./get_editor_type');
/**
* @param {object} advanced setting definition object
* @param {object} name of setting
* @param {object} current value of setting
* @returns {object} the editable config object
*/
function toEditableConfig(def, name, value) {
var isCustom = !def;
if (isCustom) def = {};
var conf = {
name,
value,
isCustom,
readonly: !!def.readonly,
defVal: def.value,
type: getValType(def, value),
description: def.description,
options: def.options
};
var editor = getEditorType(conf);
conf.json = editor === 'json';
conf.select = editor === 'select';
conf.bool = editor === 'boolean';
conf.array = editor === 'array';
conf.normal = editor === 'normal';
conf.tooComplex = !editor;
return conf;
}
return toEditableConfig;
});

View file

@ -3,6 +3,9 @@ define(function () {
// wraped in provider so that a new instance is given to each app/test
return {
'buildNum': {
readonly: true
},
'query:queryString:options': {
value: '{ "analyze_wildcard": true }',
description: 'Options for the lucene query string parser',