[Controls] Conditionally hide settings that only make sense when at least one control (#127932) (#128097)

* Make some settings conditional on control count

* Add functional tests for control group settings

* Remove unnecessary string

(cherry picked from commit fe34af7bc0)

Co-authored-by: Hannah Mudge <Heenawter@users.noreply.github.com>
This commit is contained in:
Kibana Machine 2022-03-18 17:39:50 -04:00 committed by GitHub
parent 14cc6af66a
commit 8e0253b259
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 181 additions and 29 deletions

View file

@ -102,6 +102,7 @@ export const ControlGroup = () => {
borderRadius="m"
color={panelBg}
paddingSize={emptyState ? 's' : 'none'}
data-test-subj="controls-group-wrapper"
className={classNames('controlsWrapper', {
'controlsWrapper--empty': emptyState,
'controlsWrapper--twoLine': controlStyle === 'twoLine',

View file

@ -38,6 +38,7 @@ interface EditControlGroupProps {
width: ControlWidth;
controlStyle: ControlStyle;
setAllWidths: boolean;
controlCount: number;
updateControlStyle: (controlStyle: ControlStyle) => void;
updateWidth: (newWidth: ControlWidth) => void;
updateAllControlWidths: (newWidth: ControlWidth) => void;
@ -49,6 +50,7 @@ export const ControlGroupEditor = ({
width,
controlStyle,
setAllWidths,
controlCount,
updateControlStyle,
updateWidth,
updateAllControlWidths,
@ -66,12 +68,13 @@ export const ControlGroupEditor = ({
<h2>{ControlGroupStrings.management.getFlyoutTitle()}</h2>
</EuiTitle>
</EuiFlyoutHeader>
<EuiFlyoutBody>
<EuiFlyoutBody data-test-subj="control-group-settings-flyout">
<EuiFormRow label={ControlGroupStrings.management.getLayoutTitle()}>
<EuiButtonGroup
color="primary"
idSelected={currentControlStyle}
legend={ControlGroupStrings.management.controlStyle.getDesignSwitchLegend()}
data-test-subj="control-group-layout-options"
options={CONTROL_LAYOUT_OPTIONS}
onChange={(newControlStyle: string) => {
setCurrentControlStyle(newControlStyle as ControlStyle);
@ -84,33 +87,39 @@ export const ControlGroupEditor = ({
color="primary"
idSelected={currentWidth}
legend={ControlGroupStrings.management.controlWidth.getWidthSwitchLegend()}
data-test-subj="control-group-default-size-options"
options={CONTROL_WIDTH_OPTIONS}
onChange={(newWidth: string) => {
setCurrentWidth(newWidth as ControlWidth);
}}
/>
</EuiFormRow>
<EuiSpacer size="s" />
<EuiCheckbox
id="editControls_setAllSizesCheckbox"
label={ControlGroupStrings.management.getSetAllWidthsToDefaultTitle()}
checked={applyToAll}
onChange={(e) => {
setApplyToAll(e.target.checked);
}}
/>
<EuiSpacer size="l" />
<EuiButtonEmpty
onClick={onCancel}
aria-label={'delete-all'}
iconType="trash"
color="danger"
flush="left"
size="s"
>
{ControlGroupStrings.management.getDeleteAllButtonTitle()}
</EuiButtonEmpty>
{controlCount > 0 ? (
<>
<EuiSpacer size="s" />
<EuiCheckbox
id="editControls_setAllSizesCheckbox"
data-test-subj="set-all-control-sizes-checkbox"
label={ControlGroupStrings.management.getSetAllWidthsToDefaultTitle()}
checked={applyToAll}
onChange={(e) => {
setApplyToAll(e.target.checked);
}}
/>
<EuiSpacer size="l" />
<EuiButtonEmpty
onClick={onCancel}
aria-label={'delete-all'}
data-test-subj="delete-all-controls-button"
iconType="trash"
color="danger"
flush="left"
size="s"
>
{ControlGroupStrings.management.getDeleteAllButtonTitle()}
</EuiButtonEmpty>
</>
) : null}
</EuiFlyoutBody>
<EuiFlyoutFooter>
<EuiFlexGroup responsive={false} justifyContent="spaceBetween">
@ -130,6 +139,7 @@ export const ControlGroupEditor = ({
aria-label={`save-group`}
iconType="check"
color="primary"
data-test-subj="control-group-editor-save"
onClick={() => {
if (currentControlStyle && currentControlStyle !== controlStyle) {
updateControlStyle(currentControlStyle);

View file

@ -65,6 +65,7 @@ export const EditControlGroup = ({
width={defaultControlWidth ?? DEFAULT_CONTROL_WIDTH}
controlStyle={controlStyle ?? DEFAULT_CONTROL_STYLE}
setAllWidths={false}
controlCount={Object.keys(panels ?? {}).length}
updateControlStyle={setControlStyle}
updateWidth={setDefaultControlWidth}
updateAllControlWidths={setAllControlWidths}
@ -86,7 +87,7 @@ export const EditControlGroup = ({
closePopover();
},
icon: 'gear',
'data-test-subj': 'controls-sorting-button',
'data-test-subj': 'controls-settings-button',
'aria-label': ControlGroupStrings.management.getManageButtonTitle(),
};

View file

@ -38,10 +38,12 @@ export const CONTROL_WIDTH_OPTIONS = [
export const CONTROL_LAYOUT_OPTIONS = [
{
id: `oneLine`,
'data-test-subj': 'control-editor-layout-oneLine',
label: ControlGroupStrings.management.controlStyle.getSingleLineTitle(),
},
{
id: `twoLine`,
'data-test-subj': 'control-editor-layout-twoLine',
label: ControlGroupStrings.management.controlStyle.getTwoLineTitle(),
},
];

View file

@ -128,7 +128,7 @@ export class ControlGroupContainer extends Container<
iconType="arrowDown"
iconSide="right"
panelPaddingSize="none"
data-test-subj="dashboardControlsMenuButton"
data-test-subj="dashboard-controls-menu-button"
>
{({ closePopover }: { closePopover: () => void }) => (
<EuiContextMenuPanel

View file

@ -19,6 +19,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
const testSubjects = getService('testSubjects');
const kibanaServer = getService('kibanaServer');
const dashboardAddPanel = getService('dashboardAddPanel');
const find = getService('find');
const { dashboardControls, timePicker, common, dashboard, header } = getPageObjects([
'dashboardControls',
'timePicker',
@ -41,9 +42,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
await dashboardControls.enableControlsLab();
await common.navigateToApp('dashboard');
await dashboard.preserveCrossAppState();
await dashboard.gotoDashboardLandingPage();
await dashboard.clickNewDashboard();
await timePicker.setDefaultDataRange();
});
after(async () => {
@ -52,9 +50,15 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
});
describe('Controls callout visibility', async () => {
before(async () => {
await dashboard.gotoDashboardLandingPage();
await dashboard.clickNewDashboard();
await timePicker.setDefaultDataRange();
await dashboard.saveDashboard('Test Controls Callout');
});
describe('does not show the empty control callout on an empty dashboard', async () => {
it('in view mode', async () => {
await dashboard.saveDashboard('Test Controls Callout');
await dashboard.clickCancelOutOfEditMode();
await testSubjects.missingOrFail('controls-empty');
});
@ -66,6 +70,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
});
it('show the empty control callout on a dashboard with panels', async () => {
await dashboard.switchToEditMode();
await dashboardAddPanel.addVisualization('Rendering-Test:-animal-sounds-pie');
await testSubjects.existOrFail('controls-empty');
});
@ -84,6 +89,92 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
});
});
describe('Control group settings', async () => {
before(async () => {
await dashboard.gotoDashboardLandingPage();
await dashboard.clickNewDashboard();
await dashboard.saveDashboard('Test Control Group Settings');
});
it('adjust layout of controls', async () => {
await dashboard.switchToEditMode();
await dashboardControls.createOptionsListControl({
dataViewTitle: 'animals-*',
fieldName: 'sound.keyword',
});
await dashboardControls.adjustControlsLayout('twoLine');
const controlGroupWrapper = await testSubjects.find('controls-group-wrapper');
expect(await controlGroupWrapper.elementHasClass('controlsWrapper--twoLine')).to.be(true);
});
describe('apply new default size', async () => {
it('to new controls only', async () => {
await dashboardControls.updateControlsSize('medium');
await dashboardControls.createOptionsListControl({
dataViewTitle: 'animals-*',
fieldName: 'name.keyword',
});
const controlIds = await dashboardControls.getAllControlIds();
const firstControl = await find.byXPath(`//div[@data-control-id="${controlIds[0]}"]`);
expect(await firstControl.elementHasClass('controlFrameWrapper--medium')).to.be(false);
const secondControl = await find.byXPath(`//div[@data-control-id="${controlIds[1]}"]`);
expect(await secondControl.elementHasClass('controlFrameWrapper--medium')).to.be(true);
});
it('to all existing controls', async () => {
await dashboardControls.createOptionsListControl({
dataViewTitle: 'animals-*',
fieldName: 'animal.keyword',
width: 'large',
});
await dashboardControls.updateControlsSize('small', true);
const controlIds = await dashboardControls.getAllControlIds();
for (const id of controlIds) {
const control = await find.byXPath(`//div[@data-control-id="${id}"]`);
expect(await control.elementHasClass('controlFrameWrapper--small')).to.be(true);
}
});
});
describe('flyout only show settings that are relevant', async () => {
before(async () => {
await dashboard.switchToEditMode();
});
it('when no controls', async () => {
await dashboardControls.deleteAllControls();
await dashboardControls.openControlGroupSettingsFlyout();
await testSubjects.missingOrFail('delete-all-controls-button');
await testSubjects.missingOrFail('set-all-control-sizes-checkbox');
});
it('when at least one control', async () => {
await dashboardControls.createOptionsListControl({
dataViewTitle: 'animals-*',
fieldName: 'sound.keyword',
});
await dashboardControls.openControlGroupSettingsFlyout();
await testSubjects.existOrFail('delete-all-controls-button');
await testSubjects.existOrFail('set-all-control-sizes-checkbox', { allowHidden: true });
});
afterEach(async () => {
await testSubjects.click('euiFlyoutCloseButton');
});
after(async () => {
await dashboardControls.deleteAllControls();
});
});
after(async () => {
await dashboard.clickCancelOutOfEditMode();
await dashboard.gotoDashboardLandingPage();
});
});
describe('Options List Control creation and editing experience', async () => {
it('can add a new options list control from a blank state', async () => {
await dashboard.clickNewDashboard();

View file

@ -6,6 +6,7 @@
* Side Public License, v 1.
*/
import expect from '@kbn/expect';
import { WebElementWrapper } from 'test/functional/services/lib/web_element_wrapper';
import { OPTIONS_LIST_CONTROL, ControlWidth } from '../../../src/plugins/controls/common';
@ -64,13 +65,59 @@ export class DashboardPageControls extends FtrService {
public async openCreateControlFlyout(type: string) {
this.log.debug(`Opening flyout for ${type} control`);
await this.testSubjects.click('dashboardControlsMenuButton');
await this.testSubjects.click('dashboard-controls-menu-button');
await this.testSubjects.click(`create-${type}-control`);
await this.retry.try(async () => {
await this.testSubjects.existOrFail('control-editor-flyout');
});
}
/* -----------------------------------------------------------
Control group editor flyout
----------------------------------------------------------- */
public async openControlGroupSettingsFlyout() {
this.log.debug('Open controls group settings flyout');
await this.testSubjects.click('dashboard-controls-menu-button');
await this.testSubjects.click('controls-settings-button');
await this.retry.try(async () => {
await this.testSubjects.existOrFail('control-group-settings-flyout');
});
}
public async deleteAllControls() {
this.log.debug('Delete all controls');
if ((await this.getControlsCount()) === 0) return;
await this.openControlGroupSettingsFlyout();
await this.testSubjects.click('delete-all-controls-button');
await this.testSubjects.click('confirmModalConfirmButton');
expect(await this.getControlsCount()).to.be(0);
}
public async adjustControlsLayout(layout: 'oneLine' | 'twoLine') {
this.log.debug(`Adjust controls layout to "${layout}"`);
await this.openControlGroupSettingsFlyout();
await this.testSubjects.existOrFail('control-group-layout-options');
await this.testSubjects.click(`control-editor-layout-${layout}`);
await this.testSubjects.click('control-group-editor-save');
}
public async updateControlsSize(width: ControlWidth, applyToAll: boolean = false) {
this.log.debug(
`Update default control size to ${width}`,
applyToAll ? ' for all controls' : ''
);
await this.openControlGroupSettingsFlyout();
await this.testSubjects.existOrFail('control-group-default-size-options');
await this.testSubjects.click(`control-editor-width-${width}`);
if (applyToAll) {
const checkbox = await this.find.byXPath('//label[@for="editControls_setAllSizesCheckbox"]');
await checkbox.click();
}
await this.testSubjects.click('control-group-editor-save');
}
/* -----------------------------------------------------------
Individual controls functions
----------------------------------------------------------- */