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

[Vis: Default editor] EUIficate agg-select #31892

Merged
merged 59 commits into from
Mar 28, 2019
Merged
Show file tree
Hide file tree
Changes from 46 commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
2d59c0d
EUIficate agg-select
maryia-lapata Feb 25, 2019
83d6188
Improve validation; update TS
maryia-lapata Feb 25, 2019
0e14bd9
Move aggHelpLink to agg-params
maryia-lapata Feb 26, 2019
2488f60
Apply styles for helpLink
maryia-lapata Feb 26, 2019
b4286ac
Look form controller upper
maryia-lapata Feb 26, 2019
bd25bce
Fix unit test
maryia-lapata Feb 27, 2019
ea82d07
Update functional tests
maryia-lapata Feb 27, 2019
8532799
Rename component
maryia-lapata Feb 27, 2019
cd7cc7f
Adjust comboBox service to chose the item where the text mates exactly
maryia-lapata Feb 27, 2019
0b8d3f5
Update vis page object
maryia-lapata Feb 27, 2019
60a9060
Add default value for agg
maryia-lapata Feb 27, 2019
e5f7e6a
Merge branch 'master' into vis-editor-agg-select
maryia-lapata Feb 28, 2019
a2b9558
Refactoring
maryia-lapata Feb 28, 2019
3303d25
Fix tests
maryia-lapata Feb 28, 2019
b104972
Move aggs grouping function to a separate file
maryia-lapata Feb 28, 2019
b2ee217
Merge branch 'master' into vis-editor-agg-select
maryia-lapata Mar 1, 2019
2734ddb
Merge branch 'master' into vis-editor-agg-select
maryia-lapata Mar 7, 2019
e76df1f
Use labelAppend prop for help link node
maryia-lapata Mar 7, 2019
454c5d9
Fix throwing an error by clicking Enter because object from selectedO…
maryia-lapata Mar 7, 2019
36ea5f5
Merge branch 'master' into vis-editor-agg-select
maryia-lapata Mar 11, 2019
1eeec65
Merge branch 'master' into vis-editor-agg-select
maryia-lapata Mar 12, 2019
c0db133
Add watcher for aggType to manage to discard changes
maryia-lapata Mar 12, 2019
9dea5e6
Remove unused useState
maryia-lapata Mar 12, 2019
1eb50b1
Add default value for agg type title
maryia-lapata Mar 12, 2019
ce67b68
Merge branch 'master' into vis-editor-agg-select
maryia-lapata Mar 13, 2019
6f0908c
Fix defining selected option when aggType is defined
maryia-lapata Mar 13, 2019
18ae7c0
Merge branch 'master' into vis-editor-agg-select
maryia-lapata Mar 14, 2019
37bd492
Refactoring
maryia-lapata Mar 14, 2019
8aeeac6
Merge branch 'master' into vis-editor-agg-select
maryia-lapata Mar 15, 2019
d337648
Refactoring
maryia-lapata Mar 16, 2019
44aab2b
Merge branch 'master' into vis-editor-agg-select
maryia-lapata Mar 18, 2019
d53de37
Fix tests
maryia-lapata Mar 18, 2019
1bdbd81
Merge branch 'master' into vis-editor-agg-select
maryia-lapata Mar 18, 2019
52dfda8
Merge branch 'master' into vis-editor-agg-select
maryia-lapata Mar 18, 2019
b0c8f53
Update test comment
maryia-lapata Mar 18, 2019
5bfe018
Update test
maryia-lapata Mar 18, 2019
45062aa
Fix validation issues
maryia-lapata Mar 18, 2019
c742460
Merge branch 'master' into vis-editor-agg-select
maryia-lapata Mar 20, 2019
62e09a7
Remove a bootstrap specific class
maryia-lapata Mar 20, 2019
9105111
Update comments
maryia-lapata Mar 20, 2019
39d638d
Refactor validation
maryia-lapata Mar 20, 2019
1e0c535
Change css selector in test
maryia-lapata Mar 20, 2019
2328927
Merge branch 'master' into vis-editor-agg-select
maryia-lapata Mar 21, 2019
76d8364
Update according to SASS guidelines
maryia-lapata Mar 21, 2019
8705d0b
Merge branch 'master' into vis-editor-agg-select
maryia-lapata Mar 22, 2019
63079c7
Refactoring for form validation
maryia-lapata Mar 22, 2019
35a1f4d
Update functinal comboBox service
maryia-lapata Mar 25, 2019
ae01d9f
Merge branch 'master' into vis-editor-agg-select
maryia-lapata Mar 25, 2019
5a8ef6a
Added check for undefined
maryia-lapata Mar 25, 2019
a1f7863
Add jsdoc for groupAggregationsBy function
maryia-lapata Mar 25, 2019
5f7b8f9
Fix types
maryia-lapata Mar 25, 2019
0f68ca6
Add unit tests for groupAggregationsBy
maryia-lapata Mar 25, 2019
b112a83
Merge branch 'master' into vis-editor-agg-select
maryia-lapata Mar 26, 2019
3bf17e6
Move setValidity invocation to DefaultEditorAggSelect component
maryia-lapata Mar 26, 2019
4fc0c21
Merge branch 'master' into vis-editor-agg-select
maryia-lapata Mar 27, 2019
0493053
Fix merge conflict
maryia-lapata Mar 27, 2019
9ac2062
Wrap setValidity into useEffect due to react warning when select is c…
maryia-lapata Mar 27, 2019
dd4c8b8
Merge branch 'master' into vis-editor-agg-select
maryia-lapata Mar 28, 2019
f3d5936
Move help link definition to select component
maryia-lapata Mar 28, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/legacy/ui/public/agg_types/controls/string.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ function StringParamEditor({ agg, aggParam, value, setValue }: AggParamEditorPro
return (
<EuiFormRow
label={aggParam.displayName || aggParam.name}
className="form-group"
fullWidth={true}
className="visEditorSidebar__aggParamFormRow"
>
<EuiFieldText
value={value || ''}
Expand Down
4 changes: 4 additions & 0 deletions src/legacy/ui/public/vis/editors/default/_agg_select.scss
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,7 @@
.visEditorAggSelect__helpLink {
@include euiFontSizeXS;
}

.visEditorAggSelect__formRow {
margin-bottom: $euiSizeS;
}
4 changes: 4 additions & 0 deletions src/legacy/ui/public/vis/editors/default/_sidebar.scss
Original file line number Diff line number Diff line change
Expand Up @@ -221,3 +221,7 @@
}
}

.visEditorSidebar__aggParamFormRow {
margin-top: $euiSizeS;
margin-bottom: $euiSizeS;
}
2 changes: 1 addition & 1 deletion src/legacy/ui/public/vis/editors/default/agg.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ uiModules
* @return {[type]} [description]
*/
$scope.describe = function () {
if (!$scope.agg.type.makeLabel) return '';
if (!$scope.agg.type || !$scope.agg.type.makeLabel) return '';
const label = $scope.agg.type.makeLabel($scope.agg);
return label ? label : '';
};
Expand Down
7 changes: 7 additions & 0 deletions src/legacy/ui/public/vis/editors/default/agg_params.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,11 @@
</p>
</div>

<vis-agg-select
agg="agg"
is-sub-aggregation="isSubAggregation"
agg-type-options="groupedAggTypeOptions"
ng-model="_internalNgModelStateAggType"
/>

<!-- schema editors get added down here: aggSelect.html, agg_types/controls/*.html -->
27 changes: 12 additions & 15 deletions src/legacy/ui/public/vis/editors/default/agg_params.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,18 @@
*/

import $ from 'jquery';
import { get, has } from 'lodash';
import { get } from 'lodash';
import { aggTypes } from '../../../agg_types';
import { aggTypeFilters } from '../../../agg_types/filter';
import { aggTypeFieldFilters } from '../../../agg_types/param_types/filter';
import { documentationLinks } from '../../../documentation_links/documentation_links';
import '../../../filters/match_any';
import { uiModules } from '../../../modules';
import { editorConfigProviders } from '../config/editor_config_providers';
import advancedToggleHtml from './advanced_toggle.html';
import './agg_param';
import './agg_select';
import aggParamsTemplate from './agg_params.html';
import aggSelectHtml from './agg_select.html';
import { groupAggregationsBy } from './default_editor_utils';

uiModules
.get('app/visualize')
Expand All @@ -56,6 +56,15 @@ uiModules
updateEditorConfig('default');
});

$scope.groupedAggTypeOptions = groupAggregationsBy($scope.aggTypeOptions, 'subtype');
$scope.isSubAggregation = $scope.$index >= 1 && $scope.groupName === 'buckets';

$scope.onAggTypeChange = (agg, value) => {
if (agg.type !== value) {
agg.type = value;
}
};

$scope.onParamChange = (agg, paramName, value) => {
if(agg.params[paramName] !== value) {
agg.params[paramName] = value;
Expand Down Expand Up @@ -91,9 +100,6 @@ uiModules
// controls for the agg, which is why they are first
addSchemaEditor();

// allow selection of an aggregation
addAggSelector();

function addSchemaEditor() {
const $schemaEditor = $('<div>').addClass('schemaEditors form-group').appendTo($el);

Expand All @@ -103,21 +109,12 @@ uiModules
}
}

function addAggSelector() {
const $aggSelect = $(aggSelectHtml).appendTo($el);
$compile($aggSelect)($scope);
}

// params for the selected agg, these are rebuilt every time the agg in $aggSelect changes
let $aggParamEditors; // container for agg type param editors
let $aggParamEditorsScope;

function updateAggParamEditor() {
updateEditorConfig();
$scope.aggHelpLink = null;
if (has($scope, 'agg.type.name')) {
$scope.aggHelpLink = get(documentationLinks, ['aggs', $scope.agg.type.name]);
}

if ($aggParamEditors) {
$aggParamEditors.remove();
Expand Down
50 changes: 0 additions & 50 deletions src/legacy/ui/public/vis/editors/default/agg_select.html

This file was deleted.

106 changes: 106 additions & 0 deletions src/legacy/ui/public/vis/editors/default/agg_select.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import 'ngreact';
import { has, get } from 'lodash';
import { uiModules } from '../../../modules';
import { DefaultEditorAggSelect } from './components/default_editor_agg_select';
import { wrapInI18nContext } from 'ui/i18n';
import { documentationLinks } from '../../../documentation_links/documentation_links';

uiModules
.get('app/visualize', ['react'])
.directive('visAggSelectReactWrapper', reactDirective => reactDirective(wrapInI18nContext(DefaultEditorAggSelect), [
['agg', { watchDepth: 'collection' }],
['aggTypeOptions', { watchDepth: 'collection' }],
['setValue', { watchDepth: 'reference' }],
['setTouched', { watchDepth: 'reference' }],
'value',
'isSubAggregation',
'aggHelpLink',
'isSelectInvalid'
]))
.directive('visAggSelect', function () {
return {
restrict: 'E',
scope: true,
require: '^ngModel',
template: function () {
return `<vis-agg-select-react-wrapper
agg="agg"
value="paramValue"
set-value="onChange"
is-sub-aggregation="isSubAggregation"
agg-help-link="aggHelpLink"
agg-type-options="aggTypeOptions"
is-select-invalid="isSelectInvalid"
set-touched="setTouched"
></vis-agg-select-react-wrapper>`;
},
link: {
pre: function ($scope, $el, attr) {
$scope.$bind('agg', attr.agg);
$scope.$bind('isSubAggregation', attr.isSubAggregation);
$scope.$bind('aggTypeOptions', attr.aggTypeOptions);
},
post: function ($scope, $el, attr, ngModelCtrl) {
$scope.$watch('agg.type', (value, oldValue) => {
// Whenever the value of the parameter changed (e.g. by a reset or actually by calling)
// we store the new value in $scope.paramValue, which will be passed as a new value to the react component.
$scope.paramValue = value;

// Set value to trigger $validators calling
ngModelCtrl.$setViewValue(value);

// We skip the first time the listener is called
if (value !== oldValue) {
// We should set isSelectInvalid here in case the form is reseted
$scope.isSelectInvalid = !value;
}

$scope.aggHelpLink = null;
if (has($scope, 'agg.type.name')) {
$scope.aggHelpLink = get(documentationLinks, ['aggs', $scope.agg.type.name]);
maryia-lapata marked this conversation as resolved.
Show resolved Hide resolved
}
});

$scope.onChange = (value) => {
// This is obviously not a good code quality, but without using scope binding (which we can't see above)
// to bind function values, this is right now the best temporary fix, until all of this will be gone.
$scope.$parent.onAggTypeChange($scope.agg, value);

ngModelCtrl.$setDirty();
};

$scope.setTouched = () => {
ngModelCtrl.$setTouched();
$scope.isSelectInvalid = !$scope.paramValue;
};

ngModelCtrl.$validators.required = (modelValue) => {
// The field will be marked as invalid when the value is empty and the field is untouched.
$scope.isSelectInvalid = ngModelCtrl.$touched && !modelValue;

// Since aggType is required field, the model and the form should become invalid when the aggregation field is set to empty.
return !!modelValue;
};
}
}
};
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { get } from 'lodash';
import React from 'react';

import { EuiComboBox, EuiFormRow, EuiLink } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import { AggType } from 'ui/agg_types';
import { AggConfig } from 'ui/vis/agg_config';
import { ComboBoxGroupedOption } from '../default_editor_utils';

interface DefaultEditorAggSelectProps {
agg: AggConfig;
value: AggType;
setValue: (aggType: AggType) => void;
aggHelpLink: string;
aggTypeOptions: AggType[];
isSubAggregation: boolean;
isSelectInvalid: boolean;
setTouched: () => void;
}

function DefaultEditorAggSelect({
agg = {},
value = { title: '' },
setValue,
aggTypeOptions = [],
aggHelpLink,
isSelectInvalid,
isSubAggregation,
setTouched,
}: DefaultEditorAggSelectProps) {
const isAggTypeDefined = value && Boolean(value.title);
const selectedOptions: ComboBoxGroupedOption[] = isAggTypeDefined
? [{ label: value.title, value }]
: [];

const label = isSubAggregation ? (
<FormattedMessage
id="common.ui.vis.defaultEditor.aggSelect.subAggregationLabel"
defaultMessage="Sub aggregation"
/>
) : (
<FormattedMessage
id="common.ui.vis.defaultEditor.aggSelect.aggregationLabel"
defaultMessage="Aggregation"
/>
);
const helpLink = isAggTypeDefined && aggHelpLink && (
<EuiLink
href={aggHelpLink}
target="_blank"
rel="noopener"
className="visEditorAggSelect__helpLink"
>
<FormattedMessage
id="common.ui.vis.defaultEditor.aggSelect.helpLinkLabel"
defaultMessage="{aggTitle} help"
values={{ aggTitle: isAggTypeDefined ? value.title : '' }}
/>
</EuiLink>
);

return (
<EuiFormRow
label={label}
labelAppend={helpLink}
isInvalid={isSelectInvalid}
fullWidth={true}
className="visEditorAggSelect__formRow"
>
<EuiComboBox
placeholder={i18n.translate('common.ui.vis.defaultEditor.aggSelect.selectAggPlaceholder', {
defaultMessage: 'Select an aggregation…',
})}
id={`visDefaultEditorAggSelect${agg.id}`}
options={aggTypeOptions}
selectedOptions={selectedOptions}
singleSelection={{ asPlainText: true }}
onChange={options => setValue(get(options, '0.value'))}
data-test-subj="defaultEditorAggSelect"
isClearable={false}
isInvalid={isSelectInvalid}
fullWidth={true}
onBlur={() => setTouched()}
/>
</EuiFormRow>
);
}

export { DefaultEditorAggSelect };
Loading