-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
Introduce EditorConfigProvider to customize vis editor #20519
Conversation
💚 Build Succeeded |
💔 Build Failed |
💔 Build Failed |
💚 Build Succeeded |
💚 Build Succeeded |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great @timroes! Thanks for all of the comments and clear tests. I had some suggestions but nothing major.
expect(config.base).toBe(40); | ||
}); | ||
|
||
it('should throw on combinding fixedValue with base', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo: "combinding" -> "combining"
// If not we'll throw an error. | ||
throw new Error(`Two EditorConfigProviders provided different fixed values for field ${paramName}: | ||
${merged.fixedValue} !== ${current.fixedValue}`); | ||
} else if ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this can be just a regular if
instead of else if
, since the first condition is an early exit. This will make the code a bit easier to scan.
// that are the multiple of the specific base value, but since there is no use-case for that | ||
// right now, this isn't implemented. | ||
throw new Error(`Tried to provide a fixedValue and a base for param ${paramName}.`); | ||
} else if (this.isBaseParam(current) && this.isBaseParam(merged)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here.
return { | ||
base: leastCommonMultiple(current.base, merged.base), | ||
}; | ||
} else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't need to be inside a condition at all, since the previous conditions all throw or return.
return { | ||
fixedValue: current.fixedValue, | ||
}; | ||
} else if (this.isBaseParam(current)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can just be an if
.
@@ -28,6 +28,29 @@ import { uiModules } from '../../../modules'; | |||
import { documentationLinks } from '../../../documentation_links/documentation_links'; | |||
import aggParamsTemplate from './agg_params.html'; | |||
import { aggTypeFilters } from '../../../agg_types/filter'; | |||
import { editorConfigProviders } from '../config/editor_config_providers'; | |||
|
|||
// TODO: This is just an example how to use this, and will be removed later. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this still need to be here? It does seem useful, so maybe we should remove the TODO
annotation and just change this comment to be This is an example of how to use this.
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wait why is this still there? Oh yeah I forgot to push my last commit from yesterday :D
if (config.hasOwnProperty('fixedValue')) { | ||
$scope.agg.params[param] = config.fixedValue; | ||
} | ||
// TODO: process more editor config? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you mean by this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That should have been removed
const isExtraParam = i > 0; | ||
if (!hasIndexedFields && isExtraParam) { // don't draw the rest of the options if there are no indexed fields. | ||
$scope.agg.type.params | ||
.filter(param => !get($scope, ['editorConfig', param.name, 'hidden'], false)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To make this easier to scan, can we assign this to a new variable or add a comment explaining what the intention is?
const visibleParams =
$scope.agg.type.params.filter(param => !get($scope, ['editorConfig', param.name, 'hidden'], false));
aggConfig: AggConfig | ||
) => EditorConfig; | ||
|
||
function greatestCommonDivisor(a: number, b: number): number { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jen-huang Weren't you looking for utilities like this?
These seem general enough to belong in their own math
module in ui/public
, with a couple unit tests. What do you think @timroes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeap, I will move them
return configs.reduce((output, conf) => { | ||
Object.entries(conf).forEach(([paramName, paramConfig]) => { | ||
if (!output[paramName]) { | ||
output[paramName] = paramConfig; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know we're not mutating paramConfig
anywhere in this code but is it possible someone might add code that adds properties to it in the future (outside of this module)? If so, is it worth being defensive and just creating a shallow copy here? After all, we do that on line 122 so we may as well retain parity.
output[paramName] = { ... paramConfig };
💚 Build Succeeded |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work! I pulled this down and tested by creating a configuration that hides otherBucket
and multipleBucket
params, as well as configuring interval for histograms and timezone for date histogram based on rollup capabilities.
Just have a small question and suggestion regarding intervals.
return {
'intervalBase': {
fixedValue: 50
},
'interval': {
base: 50
}
};
Why do we need both intervalBase
and interval
? Would there be a case where intervalBase.fixedValue
and interval.base
are different?
@@ -14,7 +14,8 @@ | |||
type="number" | |||
class="form-control" | |||
name="interval" | |||
min="0" | |||
min="{{editorConfig.interval.base || 0}}" | |||
step="{{editorConfig.interval.base}}" |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I have editor hints still on the list, but wanted to pull it into a separate PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually still added it to this PR.
@jen-huang The reason why there are two different parameters is in the way aggregations in visualizations work. Basically everything needed to calculate the DSL must be an argument to the aggregation configuration, like The other part of that question is: why do you need to write it out separately in the editor config? We could indeed say, whenever we hit a We already have a lot of implicit behavior in there, and that way we would need to add another one which potentially is also error prone, like how is the parameter to the aggConfig called, that needs that base value? We always assume For that reason I rather tend not to do stuff implicitly anymore, but rather make them explicit. You want to set a value for the base that the aggregation uses to calculate - set it explicitly. You want the editor to only allow to configure a specific parameter to a specific base - set it explicitly. Technically setting those separate would work technically: you could "step" the UI without forcing the scaling to come up with a multiple of that. Or always force the interval it ends up with being a specific multiple, and still let the user configure whatever they want in the UI. Is there a real use-case for that? I don't think so. |
💚 Build Succeeded |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for that explanation and adding the warning. LGTM!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
left some small comments i hope can still get it, apart from that LGTM, gave just a quick look to the code.
self.aggType = aggTypes.byName[self.aggType]; | ||
} | ||
constructor(opts) { | ||
const self = this; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
get rid of self
const self = this; | ||
paramValues = _.clone(paramValues); | ||
write(paramValues, modifyAggConfig = null) { | ||
const self = this; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as above
import { leastCommonMultiple } from '../../../utils/math'; | ||
import { EditorConfig, EditorParamConfig, FixedParam, NumericIntervalParam } from './types'; | ||
|
||
type EditorConfigProvider = ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could we use a different name for this ... Provider is currently used to indicate you will need to call it with Private to get the actual thing out of it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I struggled with that too. The problem is I couldn't come up with a better name (Service
would sound more like the central class, and couldn't find much better names). We also just had a discussion with CJ and Jen, and couldn't find any better name. So I'll use CJ's argument here, that we are trying to remove Private
in the long run and it shouldn't keep the monopoly on that word, since it makes sense in other places too where it's more conventional.
💚 Build Succeeded |
* Add possibility to specify base for histogram interval * Move AggParamsWriter to ES6 * Add param for time_zone in date_histogram * Prevent writing intervalBase to DSL * Add basic EditorConfig providers * Merge multiple configs together * Allow hiding parameters * Improve config merging and add tests * Remove TODO * Implement review feedback * Add warning to parameter * Remove unneeded self
* Add possibility to specify base for histogram interval * Move AggParamsWriter to ES6 * Add param for time_zone in date_histogram * Prevent writing intervalBase to DSL * Add basic EditorConfig providers * Merge multiple configs together * Allow hiding parameters * Improve config merging and add tests * Remove TODO * Implement review feedback * Add warning to parameter * Remove unneeded self
This PR introduces the basic
EditorConfigProvider
which will be needed for roll-up support to limit down parameters to specific values. It introduces thebase
,fixedValue
andhidden
configurations.It does not yet implement anything around date histograms and date interval multiples. Those will be in a separate PR to keep the size of the PRs reviewable.
Sample code on how to use this:
@jen-huang Could you please check again if this PR satisfies the need around base, fixed values and hiding. Also since we don't leverage any of those yet in the UI, we cannot provide functional tests with those. Please make sure that roll-up feature has a high coverage on functional tests, that the vis editor really behaves properly (hides, only allow multiples, etc.) according to the configuration.