Skip to content

Commit a8b03cc

Browse files
Attach notification bar to top (opensearch-project#3336)
Co-authored-by: Andrey Myssak <andreymyssak@gmail.com> Signed-off-by: Sergey Myssak <sergey.myssak@gmail.com>
1 parent 755f16b commit a8b03cc

File tree

4 files changed

+96
-65
lines changed

4 files changed

+96
-65
lines changed

src/core/public/rendering/_base.scss

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
*/
66
// SASSTODO: Naming here is too embedded and high up that changing them could cause major breaks
77
#opensearch-dashboards-body {
8-
overflow-x: hidden;
98
min-height: 100%;
109
}
1110

@@ -25,6 +24,7 @@
2524
}
2625

2726
.app-wrapper-panel {
27+
position: relative;
2828
display: flex;
2929
flex: 1 0 auto;
3030
flex-direction: column;

src/plugins/advanced_settings/public/management_app/_advanced_settings.scss

+17-2
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,21 @@
7777
width: 100%;
7878
}
7979

80-
.osdBody--mgtAdvancedSettingsHasBottomBar .mgtPage__body {
81-
padding-bottom: $euiSizeXL * 2;
80+
.mgtAdvancedSettingsForm {
81+
&__notificationBarMask {
82+
height: 64px;
83+
width: 100%;
84+
}
85+
86+
&__notificationBarArea {
87+
position: absolute;
88+
top: 0;
89+
left: 0;
90+
right: 0;
91+
height: 100%;
92+
}
93+
94+
&__notificationBar {
95+
top: 99px !important;
96+
}
8297
}

src/plugins/advanced_settings/public/management_app/components/form/form.test.tsx

+10-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030

3131
import React from 'react';
3232
import { shallowWithI18nProvider, mountWithI18nProvider } from 'test_utils/enzyme_helpers';
33-
import { UiSettingsType } from '../../../../../../core/public';
33+
import { UiSettingsType } from '../../../../../../core/types';
3434

3535
import { findTestSubject } from '@elastic/eui/lib/test';
3636

@@ -44,6 +44,15 @@ jest.mock('../field', () => ({
4444
},
4545
}));
4646

47+
jest.mock('@elastic/eui', () => {
48+
const lib = jest.requireActual('@elastic/eui');
49+
50+
return {
51+
...lib,
52+
EuiPortal: ({ children }: any) => <>{children}</>,
53+
};
54+
});
55+
4756
beforeAll(() => {
4857
const localStorage: Record<string, any> = {
4958
'core.chrome.isLocked': true,

src/plugins/advanced_settings/public/management_app/components/form/form.tsx

+68-61
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,13 @@ import {
4343
EuiButton,
4444
EuiToolTip,
4545
EuiButtonEmpty,
46+
EuiPortal,
4647
} from '@elastic/eui';
4748
import { FormattedMessage } from '@osd/i18n/react';
4849
import { isEmpty } from 'lodash';
4950
import { i18n } from '@osd/i18n';
51+
import { DocLinksStart, ToastsStart } from 'opensearch-dashboards/public';
5052
import { toMountPoint } from '../../../../../opensearch_dashboards_react/public';
51-
import { DocLinksStart, ToastsStart } from '../../../../../../core/public';
5253

5354
import { getCategoryName } from '../../lib';
5455
import { Field, getEditableValue } from '../field';
@@ -335,63 +336,75 @@ export class Form extends PureComponent<FormProps> {
335336
);
336337
};
337338

338-
renderBottomBar = () => {
339+
renderNotificationBar = () => {
340+
const sibling = document.getElementById('globalBannerList')!;
339341
const areChangesInvalid = this.areChangesInvalid();
342+
340343
return (
341-
<EuiBottomBar data-test-subj="advancedSetting-bottomBar">
342-
<EuiFlexGroup
343-
justifyContent="spaceBetween"
344-
alignItems="center"
345-
responsive={false}
346-
gutterSize="s"
347-
>
348-
<EuiFlexItem grow={false} className="mgtAdvancedSettingsForm__unsavedCount">
349-
<p id="aria-describedby.countOfUnsavedSettings">{this.renderCountOfUnsaved()}</p>
350-
</EuiFlexItem>
351-
<EuiFlexItem />
352-
<EuiFlexItem grow={false}>
353-
<EuiButtonEmpty
354-
color="ghost"
355-
size="s"
356-
iconType="cross"
357-
onClick={this.clearAllUnsaved}
358-
aria-describedby="aria-describedby.countOfUnsavedSettings"
359-
data-test-subj="advancedSetting-cancelButton"
360-
>
361-
{i18n.translate('advancedSettings.form.cancelButtonLabel', {
362-
defaultMessage: 'Cancel changes',
363-
})}
364-
</EuiButtonEmpty>
365-
</EuiFlexItem>
366-
<EuiFlexItem grow={false}>
367-
<EuiToolTip
368-
content={
369-
areChangesInvalid &&
370-
i18n.translate('advancedSettings.form.saveButtonTooltipWithInvalidChanges', {
371-
defaultMessage: 'Fix invalid settings before saving.',
372-
})
373-
}
344+
<EuiPortal insert={{ sibling, position: 'after' }}>
345+
<div className="mgtAdvancedSettingsForm__notificationBarMask">
346+
<div className="mgtAdvancedSettingsForm__notificationBarArea">
347+
<EuiBottomBar
348+
data-test-subj="advancedSetting-bottomBar"
349+
position="sticky"
350+
className="mgtAdvancedSettingsForm__notificationBar"
374351
>
375-
<EuiButton
376-
className="mgtAdvancedSettingsForm__button"
377-
disabled={areChangesInvalid}
378-
color="secondary"
379-
fill
380-
size="s"
381-
iconType="check"
382-
onClick={this.saveAll}
383-
aria-describedby="aria-describedby.countOfUnsavedSettings"
384-
isLoading={this.state.loading}
385-
data-test-subj="advancedSetting-saveButton"
352+
<EuiFlexGroup
353+
justifyContent="spaceBetween"
354+
alignItems="center"
355+
responsive={false}
356+
gutterSize="s"
386357
>
387-
{i18n.translate('advancedSettings.form.saveButtonLabel', {
388-
defaultMessage: 'Save changes',
389-
})}
390-
</EuiButton>
391-
</EuiToolTip>
392-
</EuiFlexItem>
393-
</EuiFlexGroup>
394-
</EuiBottomBar>
358+
<EuiFlexItem grow={false} className="mgtAdvancedSettingsForm__unsavedCount">
359+
<p id="aria-describedby.countOfUnsavedSettings">{this.renderCountOfUnsaved()}</p>
360+
</EuiFlexItem>
361+
<EuiFlexItem />
362+
<EuiFlexItem grow={false}>
363+
<EuiButtonEmpty
364+
color="ghost"
365+
size="s"
366+
iconType="cross"
367+
onClick={this.clearAllUnsaved}
368+
aria-describedby="aria-describedby.countOfUnsavedSettings"
369+
data-test-subj="advancedSetting-cancelButton"
370+
>
371+
{i18n.translate('advancedSettings.form.cancelButtonLabel', {
372+
defaultMessage: 'Cancel changes',
373+
})}
374+
</EuiButtonEmpty>
375+
</EuiFlexItem>
376+
<EuiFlexItem grow={false}>
377+
<EuiToolTip
378+
content={
379+
areChangesInvalid &&
380+
i18n.translate('advancedSettings.form.saveButtonTooltipWithInvalidChanges', {
381+
defaultMessage: 'Fix invalid settings before saving.',
382+
})
383+
}
384+
>
385+
<EuiButton
386+
className="mgtAdvancedSettingsForm__button"
387+
disabled={areChangesInvalid}
388+
color="secondary"
389+
fill
390+
size="s"
391+
iconType="check"
392+
onClick={this.saveAll}
393+
aria-describedby="aria-describedby.countOfUnsavedSettings"
394+
isLoading={this.state.loading}
395+
data-test-subj="advancedSetting-saveButton"
396+
>
397+
{i18n.translate('advancedSettings.form.saveButtonLabel', {
398+
defaultMessage: 'Save changes',
399+
})}
400+
</EuiButton>
401+
</EuiToolTip>
402+
</EuiFlexItem>
403+
</EuiFlexGroup>
404+
</EuiBottomBar>
405+
</div>
406+
</div>
407+
</EuiPortal>
395408
);
396409
};
397410

@@ -401,12 +414,6 @@ export class Form extends PureComponent<FormProps> {
401414
const currentCategories: Category[] = [];
402415
const hasUnsavedChanges = !isEmpty(unsavedChanges);
403416

404-
if (hasUnsavedChanges) {
405-
document.body.classList.add('osdBody--mgtAdvancedSettingsHasBottomBar');
406-
} else {
407-
document.body.classList.remove('osdBody--mgtAdvancedSettingsHasBottomBar');
408-
}
409-
410417
categories.forEach((category) => {
411418
if (visibleSettings[category] && visibleSettings[category].length) {
412419
currentCategories.push(category);
@@ -426,7 +433,7 @@ export class Form extends PureComponent<FormProps> {
426433
})
427434
: this.maybeRenderNoSettings(clearQuery)}
428435
</div>
429-
{hasUnsavedChanges && this.renderBottomBar()}
436+
{hasUnsavedChanges && this.renderNotificationBar()}
430437
</Fragment>
431438
);
432439
}

0 commit comments

Comments
 (0)