Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow modifying unknown/custom advanced settings #4924

Merged
merged 9 commits into from
Sep 14, 2015
Original file line number Diff line number Diff line change
@@ -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>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"/>
Expand Down
48 changes: 18 additions & 30 deletions src/plugins/kibana/public/settings/sections/advanced/index.js
Original file line number Diff line number Diff line change
@@ -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');
Expand All @@ -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 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;
var customConfig = Object.keys(configVals)
.filter(notDefaultConfig)
.map(name => toEditableConfig(false, name, configVals[name]));

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);
}
};
});
Expand Down
Original file line number Diff line number Diff line change
@@ -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');
});
});
});
});
});
Original file line number Diff line number Diff line change
@@ -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);
}
Original file line number Diff line number Diff line change
@@ -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;
});
Original file line number Diff line number Diff line change
@@ -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;
});
3 changes: 3 additions & 0 deletions src/ui/public/config/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down