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

[uiSettings] support defining settings with uiExports #12250

Merged
merged 10 commits into from
Jun 13, 2017

Conversation

spalger
Copy link
Contributor

@spalger spalger commented Jun 9, 2017

Fixes #10863

This PR introduces a new uiExports type, uiSettingDefaults. The specification for these uiExports follow the same pattern as the defaults did before this change, the only difference is that they can be defined in a plugin's definition file and will be merged with the uiSettingDefaults from all other plugins.

Summary:

  • define a uiExports.uiSettingDefaults key your plugin definition to add uiSettingDefaults
  • uiSettingDefaults must be unique. If a key is already defined elsewhere then the server will not start.
  • defined settings will display in the advanced settings editor, along with the intended default value and description
  • the REST API is identical to before
  • the browser API is identical to before
  • defaults for timelion have been extracted to the timelion plugin definition and the existing defaults are defined in the kibana plugin definition

PS: I'd like to split the defaults in the kibana plugin from the "core" defaults and define those in ui/ui_settings, but didn't want to make too many changes to the defaults list in this PR. If you're up for the change now let me know, or I will send another PR once this one is merged.

PS: I'd like to split the defaults in the kibana plugin from the "core" defaults and define those in ui/ui_settings, but didn't want to make too many changes to the defaults list in this PR. If you're up for the change now let me know, or I will send another PR once this one is merged.

Release Note: We introduced a new uiExports type, uiSettingDefaults. The specification for these uiExports follow the same pattern as the defaults did before this change, the only difference is that they can be defined in a plugin's definition file and will be merged with the uiSettingDefaults from all other plugins.

@spalger spalger added v6.0.0 WIP Work in progress labels Jun 9, 2017
@spalger spalger force-pushed the ui-settings/ui-exports branch 2 times, most recently from f5970ce to 3eadde0 Compare June 12, 2017 21:22
@spalger spalger force-pushed the ui-settings/ui-exports branch from 3eadde0 to eec0833 Compare June 12, 2017 21:27
@spalger spalger added Team:Core Core services & architecture: plugins, logging, config, saved objects, http, ES client, i18n, etc review and removed WIP Work in progress labels Jun 12, 2017
@spalger spalger requested review from azasypkin and kimjoar June 12, 2017 23:12
@spalger
Copy link
Contributor Author

spalger commented Jun 13, 2017

cc @tsullivan

Copy link
Member

@azasypkin azasypkin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, just few tiny nits.

foo: 'bar'
});
sinon.assert.calledOnce(uiSettingsServiceFactory);
const { args } = uiSettingsServiceFactory.firstCall;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: how about this instead?

sinon.assert.calledWithExactly(uiSettingsServiceFactory, server, {
	foo: 'bar',
	getDefaults: sinon.match.func
});

@@ -0,0 +1,24 @@
export class UiExportsConsumer {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: Would you mind adding a brief comment for this class (what this is supposed to do and what are these consumers)? Honestly, I'm having a hard time trying to understand what this thing does :/

@@ -1,8 +1,6 @@
import { defaultsDeep, noop } from 'lodash';
import { errors as esErrors } from 'elasticsearch';

import { getDefaultSettings } from './defaults';

function hydrateUserSettings(userSettings) {
return Object.keys(userSettings)
.map(key => ({ key, userValue: userSettings[key] }))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not related to this PR, but looks funny that we map before filter that theoretically results in allocation of unnecessary objects, wondering if there is any hidden rationale here :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC I was coming down from an rx/observable high and didn't like that this method was previously implemented as a reduce that just assigned to a value and returned it (so that it could filter that value)... Then I remember wanting to implement it without the if()... Yeah, not a huge fan of how it turned out. If you want to take a stab at it in another pr I'd love to see your prefered alternative

* @property {AsyncFunction} [options.getDefaults] async function that returns defaults/details about
* the uiSettings.
* @property {AsyncFunction} [options.readInterceptor] async function that is called when the
* UiSettingsService does a read() an has an oportunity to intercept the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: read() an has -----> read() and has?

Copy link
Contributor

@kimjoar kimjoar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm struggling with following the flow here, but it feels like it's unavoidable without larger changes.

LGTM, just had a couple questions/nits.

@@ -57,7 +56,9 @@ export default (kibana) => {
});
}

env.defaultUiSettings = getDefaultSettings();
env.defaultUiSettings = plugins.kbnServer.uiExports.consumers
.find(consumer => consumer.getUiSettingDefaults)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit slow today, and I just couldn't understand this at first. I was just thinking "waaait, so getUiSettingDefaults is not a function"? But yeah, I understand it now. I'd love a comment on why it's only doing this on the first consumer it finds that has this function.

I also think this should change to something like:

.find(consumer => consumer.getUiSettingDefaults !== undefined)

or

.find(consumer => isFunction(consumer.getUiSettingDefaults))


export default async (kbnServer, server, config) => {
const uiExports = kbnServer.uiExports = new UiExports({
urlBasePath: config.get('server.basePath')
});

await kbnServer.mixin(uiSettingsMixin);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm soooo looking forward to 🔥 these mixins.

Why is this moved here, btw?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved here so that the uiExport consumer is registered before we try to consume all of the exports. This bit of pluggability isn't quite as pluggable as originally thought, uiExportConsumers need to be registered between the time that kbnServer.uiExports is created and when kbnServer.uiExports.consumePlugin() is called for the first time, which doesn't provide any time in this case...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

return uiSettingsServiceFactory(server, options);
server.decorate('server', 'uiSettingsServiceFactory', (options = {}) => {
return uiSettingsServiceFactory(server, {
getDefaults,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why pass around the function instead of just the defaults themselves?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the defaults can change without needing to tell the uiSettingsService, but if you're really against it I can change that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah 👍 Let's keep it (maybe add a comment above it, so it's easier to understand when looking at it later and thinking the same thought I had?)

@spalger spalger merged commit 7bec60c into elastic:master Jun 13, 2017
spalger added a commit to spalger/kibana that referenced this pull request Jun 28, 2017
* [uiSettings] add `uiSettingDefaults` export type

* [uiSettings/uiExportsConsumer] ensure that there are not conflicts

* use `sinon.assert.calledWithExactly()`

* describe the UiExportsConsumer class

* make uiExport consumers filtering intention more clear

* fix typo

* fix typos

* add note about why getDefaults() is a function

(cherry picked from commit 7bec60c)
spalger added a commit that referenced this pull request Jun 28, 2017
* [uiSettings] make service request based (#12243)

* [server/uiSettings] make uiSettings service request based

* [server/uiSettings] disambiguate UiSettings/Service

* [server/uiSettings] link to PR in removal error

* [server/uiSettings] await _read before hydrating

* [server/uiSettings] focus tests, remove server integration

* [server/uiSettings] add tests for readInterceptor() arg

* [server/uiSettings] add server integration tests

* [server/uiExports] fix replaceInjectedVars tests

* [server/uiSettings] convert all methods to use async/await

* [uiSettings/serviceFactory] fix doc block

* [uiSettings/service] fix doc block

* [uiSettings/tests/callClusterStub] stop tracking state needlessly

* [uiSettings/tests] remove invalid tests and pointless promise helpers

* [uiSettings/forRequest] fix typo

* [uiSettings/tests] remove mixture of arrow and function expressions

* [uiSettings/tests/callClusterStub] leverage sinon.calledWithExactly

* [uiSettings/mixin/tests] add exception for eslint import/no-duplicates

* [uiSettings/mixin/tests] wrap single args in parens

(cherry picked from commit 65d6b5d)

* [uiSettings] support defining settings with uiExports (#12250)

* [uiSettings] add `uiSettingDefaults` export type

* [uiSettings/uiExportsConsumer] ensure that there are not conflicts

* use `sinon.assert.calledWithExactly()`

* describe the UiExportsConsumer class

* make uiExport consumers filtering intention more clear

* fix typo

* fix typos

* add note about why getDefaults() is a function

(cherry picked from commit 7bec60c)
@spalger spalger deleted the ui-settings/ui-exports branch October 18, 2019 17:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
release_note:enhancement review Team:Core Core services & architecture: plugins, logging, config, saved objects, http, ES client, i18n, etc v6.0.0-rc1 v6.0.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants