mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Navigation: Remove bodyScrolling
toggle and make it default (#93652)
* remove bodyScrolling toggle and make it default * fix e2e tests
This commit is contained in:
parent
7f7fed8c3c
commit
a54308138f
@ -12,7 +12,7 @@ describe('Dashboards', () => {
|
|||||||
e2e.components.Panels.Panel.title('Panel #1').should('be.visible');
|
e2e.components.Panels.Panel.title('Panel #1').should('be.visible');
|
||||||
|
|
||||||
// scroll to the bottom
|
// scroll to the bottom
|
||||||
cy.get('#page-scrollbar').scrollTo('bottom', {
|
cy.scrollTo('bottom', {
|
||||||
timeout: 5 * 1000,
|
timeout: 5 * 1000,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ describe('Dashboards', () => {
|
|||||||
e2e.components.Panels.Panel.title('Panel #1').should('be.visible');
|
e2e.components.Panels.Panel.title('Panel #1').should('be.visible');
|
||||||
|
|
||||||
// scroll to the bottom
|
// scroll to the bottom
|
||||||
cy.get('#page-scrollbar').scrollTo('bottom', {
|
cy.scrollTo('bottom', {
|
||||||
timeout: 5 * 1000,
|
timeout: 5 * 1000,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ describe('Auto-migrate graph panel', () => {
|
|||||||
e2e.pages.Dashboard.Annotations.marker().should('exist');
|
e2e.pages.Dashboard.Annotations.marker().should('exist');
|
||||||
});
|
});
|
||||||
|
|
||||||
cy.get('#pageContent .scrollbar-view').first().scrollTo('bottom');
|
cy.scrollTo('bottom');
|
||||||
|
|
||||||
e2e.components.Panels.Panel.title('05:00')
|
e2e.components.Panels.Panel.title('05:00')
|
||||||
.should('exist')
|
.should('exist')
|
||||||
|
@ -64,7 +64,7 @@ describe('Auto-migrate graph panel', () => {
|
|||||||
e2e.pages.Dashboard.Annotations.marker().should('exist');
|
e2e.pages.Dashboard.Annotations.marker().should('exist');
|
||||||
});
|
});
|
||||||
|
|
||||||
cy.get('#pageContent .scrollbar-view').first().scrollTo('bottom');
|
cy.scrollTo('bottom');
|
||||||
|
|
||||||
e2e.components.Panels.Panel.title('05:00')
|
e2e.components.Panels.Panel.title('05:00')
|
||||||
.should('exist')
|
.should('exist')
|
||||||
|
@ -199,7 +199,6 @@ export interface FeatureToggles {
|
|||||||
alertingApiServer?: boolean;
|
alertingApiServer?: boolean;
|
||||||
dashboardRestoreUI?: boolean;
|
dashboardRestoreUI?: boolean;
|
||||||
cloudWatchRoundUpEndTime?: boolean;
|
cloudWatchRoundUpEndTime?: boolean;
|
||||||
bodyScrolling?: boolean;
|
|
||||||
cloudwatchMetricInsightsCrossAccount?: boolean;
|
cloudwatchMetricInsightsCrossAccount?: boolean;
|
||||||
prometheusAzureOverrideAudience?: boolean;
|
prometheusAzureOverrideAudience?: boolean;
|
||||||
alertingFilterV2?: boolean;
|
alertingFilterV2?: boolean;
|
||||||
|
@ -15,7 +15,6 @@ export interface WithContextMenuProps {
|
|||||||
export const WithContextMenu = ({ children, renderMenuItems, focusOnOpen = true }: WithContextMenuProps) => {
|
export const WithContextMenu = ({ children, renderMenuItems, focusOnOpen = true }: WithContextMenuProps) => {
|
||||||
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
||||||
const [menuPosition, setMenuPosition] = useState({ x: 0, y: 0 });
|
const [menuPosition, setMenuPosition] = useState({ x: 0, y: 0 });
|
||||||
const isBodyScrolling = window.grafanaBootData?.settings.featureToggles.bodyScrolling;
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{children({
|
{children({
|
||||||
@ -23,7 +22,7 @@ export const WithContextMenu = ({ children, renderMenuItems, focusOnOpen = true
|
|||||||
setIsMenuOpen(true);
|
setIsMenuOpen(true);
|
||||||
setMenuPosition({
|
setMenuPosition({
|
||||||
x: e.pageX,
|
x: e.pageX,
|
||||||
y: isBodyScrolling ? e.pageY - window.scrollY : e.pageY,
|
y: e.pageY - window.scrollY,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
})}
|
})}
|
||||||
|
@ -55,21 +55,13 @@ export function PortalContainer() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const getStyles = (theme: GrafanaTheme2) => {
|
const getStyles = (theme: GrafanaTheme2) => {
|
||||||
const isBodyScrolling = window.grafanaBootData?.settings.featureToggles.bodyScrolling;
|
|
||||||
return {
|
return {
|
||||||
grafanaPortalContainer: css(
|
grafanaPortalContainer: css({
|
||||||
isBodyScrolling
|
position: 'fixed',
|
||||||
? {
|
top: 0,
|
||||||
position: 'fixed',
|
width: '100%',
|
||||||
top: 0,
|
zIndex: theme.zIndex.portal,
|
||||||
width: '100%',
|
}),
|
||||||
zIndex: theme.zIndex.portal,
|
|
||||||
}
|
|
||||||
: {
|
|
||||||
position: 'absolute',
|
|
||||||
width: '100%',
|
|
||||||
}
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -5,9 +5,6 @@ import { GrafanaTheme2, ThemeTypographyVariant } from '@grafana/data';
|
|||||||
import { getFocusStyles } from '../mixins';
|
import { getFocusStyles } from '../mixins';
|
||||||
|
|
||||||
export function getElementStyles(theme: GrafanaTheme2) {
|
export function getElementStyles(theme: GrafanaTheme2) {
|
||||||
// TODO can we get the feature toggle in a better way?
|
|
||||||
const isBodyScrolling = window.grafanaBootData?.settings.featureToggles.bodyScrolling;
|
|
||||||
|
|
||||||
return css({
|
return css({
|
||||||
'*, *::before, *::after': {
|
'*, *::before, *::after': {
|
||||||
boxSizing: 'inherit',
|
boxSizing: 'inherit',
|
||||||
@ -40,26 +37,24 @@ export function getElementStyles(theme: GrafanaTheme2) {
|
|||||||
body: {
|
body: {
|
||||||
height: '100%',
|
height: '100%',
|
||||||
width: '100%',
|
width: '100%',
|
||||||
position: isBodyScrolling ? 'unset' : 'absolute',
|
position: 'unset',
|
||||||
color: theme.colors.text.primary,
|
color: theme.colors.text.primary,
|
||||||
backgroundColor: theme.colors.background.canvas,
|
backgroundColor: theme.colors.background.canvas,
|
||||||
|
// react select tries prevent scrolling by setting overflow/padding-right on the body
|
||||||
|
// Need type assertion here due to the use of !important
|
||||||
|
// see https://github.com/frenic/csstype/issues/114#issuecomment-697201978
|
||||||
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
||||||
|
overflowY: 'auto !important' as 'auto',
|
||||||
|
paddingRight: '0 !important',
|
||||||
|
'@media print': {
|
||||||
|
overflow: 'visible',
|
||||||
|
},
|
||||||
|
'@page': {
|
||||||
|
margin: 0,
|
||||||
|
size: 'auto',
|
||||||
|
padding: 0,
|
||||||
|
},
|
||||||
...theme.typography.body,
|
...theme.typography.body,
|
||||||
...(isBodyScrolling && {
|
|
||||||
// react select tries prevent scrolling by setting overflow/padding-right on the body
|
|
||||||
// Need type assertion here due to the use of !important
|
|
||||||
// see https://github.com/frenic/csstype/issues/114#issuecomment-697201978
|
|
||||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
||||||
overflowY: 'auto !important' as 'auto',
|
|
||||||
paddingRight: '0 !important',
|
|
||||||
'@media print': {
|
|
||||||
overflow: 'visible',
|
|
||||||
},
|
|
||||||
'@page': {
|
|
||||||
margin: 0,
|
|
||||||
size: 'auto',
|
|
||||||
padding: 0,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
|
|
||||||
'h1, .h1': getVariantStyles(theme.typography.h1),
|
'h1, .h1': getVariantStyles(theme.typography.h1),
|
||||||
|
@ -5,42 +5,21 @@ import { GrafanaTheme2 } from '@grafana/data';
|
|||||||
export function getPageStyles(theme: GrafanaTheme2) {
|
export function getPageStyles(theme: GrafanaTheme2) {
|
||||||
const maxWidthBreakpoint =
|
const maxWidthBreakpoint =
|
||||||
theme.breakpoints.values.xxl + theme.spacing.gridSize * 2 + theme.components.sidemenu.width;
|
theme.breakpoints.values.xxl + theme.spacing.gridSize * 2 + theme.components.sidemenu.width;
|
||||||
const isBodyScrolling = window.grafanaBootData?.settings.featureToggles.bodyScrolling;
|
|
||||||
|
|
||||||
return css({
|
return css({
|
||||||
'.grafana-app': isBodyScrolling
|
'.grafana-app': {
|
||||||
? {
|
display: 'flex',
|
||||||
display: 'flex',
|
flexDirection: 'column',
|
||||||
flexDirection: 'column',
|
height: '100vh',
|
||||||
height: '100vh',
|
},
|
||||||
}
|
|
||||||
: {
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'stretch',
|
|
||||||
position: 'absolute',
|
|
||||||
width: '100%',
|
|
||||||
height: '100%',
|
|
||||||
top: 0,
|
|
||||||
left: 0,
|
|
||||||
},
|
|
||||||
|
|
||||||
'.main-view': isBodyScrolling
|
'.main-view': {
|
||||||
? {
|
display: 'flex',
|
||||||
display: 'flex',
|
flexDirection: 'column',
|
||||||
flexDirection: 'column',
|
flexGrow: 1,
|
||||||
flexGrow: 1,
|
position: 'relative',
|
||||||
position: 'relative',
|
minWidth: 0,
|
||||||
minWidth: 0,
|
},
|
||||||
}
|
|
||||||
: {
|
|
||||||
position: 'relative',
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
flexGrow: 1,
|
|
||||||
height: '100%',
|
|
||||||
flex: '1 1 0',
|
|
||||||
minWidth: 0,
|
|
||||||
},
|
|
||||||
|
|
||||||
'.page-scrollbar-content': {
|
'.page-scrollbar-content': {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
|
@ -1371,17 +1371,6 @@ var (
|
|||||||
Owner: awsDatasourcesSquad,
|
Owner: awsDatasourcesSquad,
|
||||||
Expression: "true",
|
Expression: "true",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
Name: "bodyScrolling",
|
|
||||||
Description: "Adjusts Page to make body the scrollable element",
|
|
||||||
Stage: FeatureStagePublicPreview,
|
|
||||||
Owner: grafanaFrontendPlatformSquad,
|
|
||||||
Expression: "false", // enabled by default
|
|
||||||
FrontendOnly: true,
|
|
||||||
AllowSelfServe: true,
|
|
||||||
HideFromDocs: true,
|
|
||||||
HideFromAdminPage: false,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
Name: "cloudwatchMetricInsightsCrossAccount",
|
Name: "cloudwatchMetricInsightsCrossAccount",
|
||||||
Description: "Enables cross account observability for Cloudwatch Metric Insights query builder",
|
Description: "Enables cross account observability for Cloudwatch Metric Insights query builder",
|
||||||
|
@ -180,7 +180,6 @@ passScopeToDashboardApi,experimental,@grafana/dashboards-squad,false,false,false
|
|||||||
alertingApiServer,experimental,@grafana/alerting-squad,false,true,false
|
alertingApiServer,experimental,@grafana/alerting-squad,false,true,false
|
||||||
dashboardRestoreUI,experimental,@grafana/grafana-frontend-platform,false,false,false
|
dashboardRestoreUI,experimental,@grafana/grafana-frontend-platform,false,false,false
|
||||||
cloudWatchRoundUpEndTime,GA,@grafana/aws-datasources,false,false,false
|
cloudWatchRoundUpEndTime,GA,@grafana/aws-datasources,false,false,false
|
||||||
bodyScrolling,preview,@grafana/grafana-frontend-platform,false,false,true
|
|
||||||
cloudwatchMetricInsightsCrossAccount,preview,@grafana/aws-datasources,false,false,true
|
cloudwatchMetricInsightsCrossAccount,preview,@grafana/aws-datasources,false,false,true
|
||||||
prometheusAzureOverrideAudience,deprecated,@grafana/partner-datasources,false,false,false
|
prometheusAzureOverrideAudience,deprecated,@grafana/partner-datasources,false,false,false
|
||||||
alertingFilterV2,experimental,@grafana/alerting-squad,false,false,false
|
alertingFilterV2,experimental,@grafana/alerting-squad,false,false,false
|
||||||
|
|
@ -731,10 +731,6 @@ const (
|
|||||||
// Round up end time for metric queries to the next minute to avoid missing data
|
// Round up end time for metric queries to the next minute to avoid missing data
|
||||||
FlagCloudWatchRoundUpEndTime = "cloudWatchRoundUpEndTime"
|
FlagCloudWatchRoundUpEndTime = "cloudWatchRoundUpEndTime"
|
||||||
|
|
||||||
// FlagBodyScrolling
|
|
||||||
// Adjusts Page to make body the scrollable element
|
|
||||||
FlagBodyScrolling = "bodyScrolling"
|
|
||||||
|
|
||||||
// FlagCloudwatchMetricInsightsCrossAccount
|
// FlagCloudwatchMetricInsightsCrossAccount
|
||||||
// Enables cross account observability for Cloudwatch Metric Insights query builder
|
// Enables cross account observability for Cloudwatch Metric Insights query builder
|
||||||
FlagCloudwatchMetricInsightsCrossAccount = "cloudwatchMetricInsightsCrossAccount"
|
FlagCloudwatchMetricInsightsCrossAccount = "cloudwatchMetricInsightsCrossAccount"
|
||||||
|
@ -595,6 +595,7 @@
|
|||||||
"name": "bodyScrolling",
|
"name": "bodyScrolling",
|
||||||
"resourceVersion": "1721723807004",
|
"resourceVersion": "1721723807004",
|
||||||
"creationTimestamp": "2024-07-01T10:28:39Z",
|
"creationTimestamp": "2024-07-01T10:28:39Z",
|
||||||
|
"deletionTimestamp": "2024-09-24T09:17:00Z",
|
||||||
"annotations": {
|
"annotations": {
|
||||||
"grafana.app/updatedTimestamp": "2024-07-23 08:36:47.004393 +0000 UTC"
|
"grafana.app/updatedTimestamp": "2024-07-23 08:36:47.004393 +0000 UTC"
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ import classNames from 'classnames';
|
|||||||
import { PropsWithChildren, useEffect } from 'react';
|
import { PropsWithChildren, useEffect } from 'react';
|
||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
import { config, locationSearchToObject, locationService } from '@grafana/runtime';
|
import { locationSearchToObject, locationService } from '@grafana/runtime';
|
||||||
import { useStyles2, LinkButton, useTheme2 } from '@grafana/ui';
|
import { useStyles2, LinkButton, useTheme2 } from '@grafana/ui';
|
||||||
import { useGrafana } from 'app/core/context/GrafanaContext';
|
import { useGrafana } from 'app/core/context/GrafanaContext';
|
||||||
import { useMediaQueryChange } from 'app/core/hooks/useMediaQueryChange';
|
import { useMediaQueryChange } from 'app/core/hooks/useMediaQueryChange';
|
||||||
@ -121,10 +121,8 @@ export function AppChrome({ children }: Props) {
|
|||||||
)}
|
)}
|
||||||
<main
|
<main
|
||||||
className={cx(styles.pageContainer, {
|
className={cx(styles.pageContainer, {
|
||||||
[styles.pageContainerMenuDocked]:
|
[styles.pageContainerMenuDocked]: menuDockedAndOpen || isScopesDashboardsOpen,
|
||||||
config.featureToggles.bodyScrolling && (menuDockedAndOpen || isScopesDashboardsOpen),
|
[styles.pageContainerMenuDockedScopes]: menuDockedAndOpen && isScopesDashboardsOpen,
|
||||||
[styles.pageContainerMenuDockedScopes]:
|
|
||||||
config.featureToggles.bodyScrolling && menuDockedAndOpen && isScopesDashboardsOpen,
|
|
||||||
})}
|
})}
|
||||||
id="pageContent"
|
id="pageContent"
|
||||||
>
|
>
|
||||||
@ -148,7 +146,7 @@ const getStyles = (theme: GrafanaTheme2, searchBarHidden: boolean) => {
|
|||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
paddingTop: TOP_BAR_LEVEL_HEIGHT * 2,
|
paddingTop: TOP_BAR_LEVEL_HEIGHT * 2,
|
||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
height: config.featureToggles.bodyScrolling ? 'auto' : '100%',
|
height: 'auto',
|
||||||
}),
|
}),
|
||||||
contentNoSearchBar: css({
|
contentNoSearchBar: css({
|
||||||
paddingTop: TOP_BAR_LEVEL_HEIGHT,
|
paddingTop: TOP_BAR_LEVEL_HEIGHT,
|
||||||
@ -167,27 +165,17 @@ const getStyles = (theme: GrafanaTheme2, searchBarHidden: boolean) => {
|
|||||||
display: 'block',
|
display: 'block',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
config.featureToggles.bodyScrolling
|
{
|
||||||
? {
|
position: 'fixed',
|
||||||
position: 'fixed',
|
height: `calc(100% - ${searchBarHidden ? TOP_BAR_LEVEL_HEIGHT : TOP_BAR_LEVEL_HEIGHT * 2}px)`,
|
||||||
height: `calc(100% - ${searchBarHidden ? TOP_BAR_LEVEL_HEIGHT : TOP_BAR_LEVEL_HEIGHT * 2}px)`,
|
zIndex: 2,
|
||||||
zIndex: 2,
|
}
|
||||||
}
|
|
||||||
: {
|
|
||||||
zIndex: theme.zIndex.navbarFixed,
|
|
||||||
}
|
|
||||||
),
|
|
||||||
scopesDashboardsContainer: css(
|
|
||||||
config.featureToggles.bodyScrolling
|
|
||||||
? {
|
|
||||||
position: 'fixed',
|
|
||||||
height: `calc(100% - ${searchBarHidden ? TOP_BAR_LEVEL_HEIGHT : TOP_BAR_LEVEL_HEIGHT * 2}px)`,
|
|
||||||
zIndex: 1,
|
|
||||||
}
|
|
||||||
: {
|
|
||||||
zIndex: theme.zIndex.navbarFixed,
|
|
||||||
}
|
|
||||||
),
|
),
|
||||||
|
scopesDashboardsContainer: css({
|
||||||
|
position: 'fixed',
|
||||||
|
height: `calc(100% - ${searchBarHidden ? TOP_BAR_LEVEL_HEIGHT : TOP_BAR_LEVEL_HEIGHT * 2}px)`,
|
||||||
|
zIndex: 1,
|
||||||
|
}),
|
||||||
scopesDashboardsContainerDocked: css({
|
scopesDashboardsContainerDocked: css({
|
||||||
left: MENU_WIDTH,
|
left: MENU_WIDTH,
|
||||||
}),
|
}),
|
||||||
@ -200,49 +188,24 @@ const getStyles = (theme: GrafanaTheme2, searchBarHidden: boolean) => {
|
|||||||
background: theme.colors.background.primary,
|
background: theme.colors.background.primary,
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
}),
|
}),
|
||||||
panes: css(
|
panes: css({
|
||||||
{
|
display: 'flex',
|
||||||
display: 'flex',
|
flexDirection: 'column',
|
||||||
flexDirection: 'column',
|
flexGrow: 1,
|
||||||
flexGrow: 1,
|
label: 'page-panes',
|
||||||
label: 'page-panes',
|
}),
|
||||||
},
|
|
||||||
!config.featureToggles.bodyScrolling && {
|
|
||||||
height: '100%',
|
|
||||||
minHeight: 0,
|
|
||||||
width: '100%',
|
|
||||||
[theme.breakpoints.up('md')]: {
|
|
||||||
flexDirection: 'row',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
),
|
|
||||||
pageContainerMenuDocked: css({
|
pageContainerMenuDocked: css({
|
||||||
paddingLeft: MENU_WIDTH,
|
paddingLeft: MENU_WIDTH,
|
||||||
}),
|
}),
|
||||||
pageContainerMenuDockedScopes: css({
|
pageContainerMenuDockedScopes: css({
|
||||||
paddingLeft: `calc(${MENU_WIDTH} * 2)`,
|
paddingLeft: `calc(${MENU_WIDTH} * 2)`,
|
||||||
}),
|
}),
|
||||||
pageContainer: css(
|
pageContainer: css({
|
||||||
{
|
label: 'page-container',
|
||||||
label: 'page-container',
|
display: 'flex',
|
||||||
display: 'flex',
|
flexDirection: 'column',
|
||||||
flexDirection: 'column',
|
flexGrow: 1,
|
||||||
flexGrow: 1,
|
}),
|
||||||
},
|
|
||||||
!config.featureToggles.bodyScrolling && {
|
|
||||||
minHeight: 0,
|
|
||||||
minWidth: 0,
|
|
||||||
overflow: 'auto',
|
|
||||||
'@media print': {
|
|
||||||
overflow: 'visible',
|
|
||||||
},
|
|
||||||
'@page': {
|
|
||||||
margin: 0,
|
|
||||||
size: 'auto',
|
|
||||||
padding: 0,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
),
|
|
||||||
skipLink: css({
|
skipLink: css({
|
||||||
position: 'fixed',
|
position: 'fixed',
|
||||||
top: -1000,
|
top: -1000,
|
||||||
|
@ -3,7 +3,6 @@ import { useEffect, useState } from 'react';
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
import { config } from '@grafana/runtime';
|
|
||||||
import { useStyles2 } from '@grafana/ui';
|
import { useStyles2 } from '@grafana/ui';
|
||||||
|
|
||||||
import { Branding } from '../Branding/Branding';
|
import { Branding } from '../Branding/Branding';
|
||||||
@ -37,9 +36,7 @@ export const LoginLayout = ({ children, branding, isChangingPassword }: React.Pr
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Branding.LoginBackground
|
<Branding.LoginBackground
|
||||||
className={cx(loginStyles.container, startAnim && loginStyles.loginAnim, branding?.loginBackground, {
|
className={cx(loginStyles.container, startAnim && loginStyles.loginAnim, branding?.loginBackground)}
|
||||||
[loginStyles.containerBodyScrolling]: config.featureToggles.bodyScrolling,
|
|
||||||
})}
|
|
||||||
>
|
>
|
||||||
<div className={loginStyles.loginMain}>
|
<div className={loginStyles.loginMain}>
|
||||||
<div className={cx(loginStyles.loginContent, loginBoxBackground, 'login-content-box')}>
|
<div className={cx(loginStyles.loginContent, loginBoxBackground, 'login-content-box')}>
|
||||||
@ -89,6 +86,7 @@ export const getLoginStyles = (theme: GrafanaTheme2) => {
|
|||||||
minHeight: '100%',
|
minHeight: '100%',
|
||||||
backgroundPosition: 'center',
|
backgroundPosition: 'center',
|
||||||
backgroundRepeat: 'no-repeat',
|
backgroundRepeat: 'no-repeat',
|
||||||
|
flex: 1,
|
||||||
minWidth: '100%',
|
minWidth: '100%',
|
||||||
marginLeft: 0,
|
marginLeft: 0,
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
@ -96,9 +94,6 @@ export const getLoginStyles = (theme: GrafanaTheme2) => {
|
|||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
}),
|
}),
|
||||||
containerBodyScrolling: css({
|
|
||||||
flex: 1,
|
|
||||||
}),
|
|
||||||
loginAnim: css({
|
loginAnim: css({
|
||||||
['&:before']: {
|
['&:before']: {
|
||||||
opacity: 1,
|
opacity: 1,
|
||||||
|
@ -1,9 +1,4 @@
|
|||||||
import { css, cx } from '@emotion/css';
|
|
||||||
import { useEffect, useRef } from 'react';
|
import { useEffect, useRef } from 'react';
|
||||||
|
|
||||||
import { config } from '@grafana/runtime';
|
|
||||||
import { useStyles2 } from '@grafana/ui';
|
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
onSetScrollRef?: (ref: ScrollRefElement) => void;
|
onSetScrollRef?: (ref: ScrollRefElement) => void;
|
||||||
@ -16,30 +11,16 @@ export interface ScrollRefElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Shim to provide API-compatibility for Page's scroll-related props
|
// Shim to provide API-compatibility for Page's scroll-related props
|
||||||
// when bodyScrolling is enabled, this is a no-op
|
|
||||||
// TODO remove this shim completely when bodyScrolling is enabled
|
|
||||||
export default function NativeScrollbar({ children, onSetScrollRef, divId }: Props) {
|
export default function NativeScrollbar({ children, onSetScrollRef, divId }: Props) {
|
||||||
const styles = useStyles2(getStyles);
|
|
||||||
const ref = useRef<HTMLDivElement>(null);
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (config.featureToggles.bodyScrolling && onSetScrollRef) {
|
if (onSetScrollRef) {
|
||||||
onSetScrollRef(new DivScrollElement(document.documentElement));
|
onSetScrollRef(new DivScrollElement(document.documentElement));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!config.featureToggles.bodyScrolling && ref.current && onSetScrollRef) {
|
|
||||||
onSetScrollRef(new DivScrollElement(ref.current));
|
|
||||||
}
|
|
||||||
}, [ref, onSetScrollRef]);
|
}, [ref, onSetScrollRef]);
|
||||||
|
|
||||||
return config.featureToggles.bodyScrolling ? (
|
return children;
|
||||||
children
|
|
||||||
) : (
|
|
||||||
// Set the .scrollbar-view class to help e2e tests find this, like in CustomScrollbar
|
|
||||||
<div ref={ref} className={cx(styles.nativeScrollbars, 'scrollbar-view')} id={divId}>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class DivScrollElement {
|
class DivScrollElement {
|
||||||
@ -61,17 +42,3 @@ class DivScrollElement {
|
|||||||
this.element.scrollTo(x, y);
|
this.element.scrollTo(x, y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getStyles() {
|
|
||||||
return {
|
|
||||||
nativeScrollbars: css({
|
|
||||||
label: 'native-scroll-container',
|
|
||||||
minHeight: `calc(100% + 0px)`, // I don't know, just copied from custom scrollbars
|
|
||||||
maxHeight: `calc(100% + 0px)`, // I don't know, just copied from custom scrollbars
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
flexGrow: 1,
|
|
||||||
overflow: 'auto',
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
@ -2,7 +2,6 @@ import { css, cx } from '@emotion/css';
|
|||||||
import { useLayoutEffect } from 'react';
|
import { useLayoutEffect } from 'react';
|
||||||
|
|
||||||
import { GrafanaTheme2, PageLayoutType } from '@grafana/data';
|
import { GrafanaTheme2, PageLayoutType } from '@grafana/data';
|
||||||
import { config } from '@grafana/runtime';
|
|
||||||
import { useStyles2 } from '@grafana/ui';
|
import { useStyles2 } from '@grafana/ui';
|
||||||
import { useGrafana } from 'app/core/context/GrafanaContext';
|
import { useGrafana } from 'app/core/context/GrafanaContext';
|
||||||
|
|
||||||
@ -94,24 +93,13 @@ Page.Contents = PageContents;
|
|||||||
|
|
||||||
const getStyles = (theme: GrafanaTheme2) => {
|
const getStyles = (theme: GrafanaTheme2) => {
|
||||||
return {
|
return {
|
||||||
wrapper: css(
|
wrapper: css({
|
||||||
config.featureToggles.bodyScrolling
|
label: 'page-wrapper',
|
||||||
? {
|
display: 'flex',
|
||||||
label: 'page-wrapper',
|
flex: '1 1 0',
|
||||||
display: 'flex',
|
flexDirection: 'column',
|
||||||
flex: '1 1 0',
|
position: 'relative',
|
||||||
flexDirection: 'column',
|
}),
|
||||||
position: 'relative',
|
|
||||||
}
|
|
||||||
: {
|
|
||||||
label: 'page-wrapper',
|
|
||||||
height: '100%',
|
|
||||||
display: 'flex',
|
|
||||||
flex: '1 1 0',
|
|
||||||
flexDirection: 'column',
|
|
||||||
minHeight: 0,
|
|
||||||
}
|
|
||||||
),
|
|
||||||
pageContent: css({
|
pageContent: css({
|
||||||
label: 'page-content',
|
label: 'page-content',
|
||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
|
@ -23,11 +23,7 @@ export interface PageProps extends HTMLAttributes<HTMLDivElement> {
|
|||||||
subTitle?: React.ReactNode;
|
subTitle?: React.ReactNode;
|
||||||
/** Control the page layout. */
|
/** Control the page layout. */
|
||||||
layout?: PageLayoutType;
|
layout?: PageLayoutType;
|
||||||
/**
|
/** Can be used to get the scroll container element to access scroll position */
|
||||||
* TODO: Not sure we should deprecated it given the sidecar project?
|
|
||||||
* @deprecated this will be removed when bodyScrolling is enabled by default
|
|
||||||
* Can be used to get the scroll container element to access scroll position
|
|
||||||
* */
|
|
||||||
onSetScrollRef?: (ref: ScrollRefElement) => void;
|
onSetScrollRef?: (ref: ScrollRefElement) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { createContext, useCallback, useContext } from 'react';
|
import { createContext, useCallback, useContext } from 'react';
|
||||||
|
|
||||||
import { GrafanaConfig } from '@grafana/data';
|
import { GrafanaConfig } from '@grafana/data';
|
||||||
import { LocationService, locationService, BackendSrv, config } from '@grafana/runtime';
|
import { LocationService, locationService, BackendSrv } from '@grafana/runtime';
|
||||||
|
|
||||||
import { AppChromeService } from '../components/AppChrome/AppChromeService';
|
import { AppChromeService } from '../components/AppChrome/AppChromeService';
|
||||||
import { NewFrontendAssetsChecker } from '../services/NewFrontendAssetsChecker';
|
import { NewFrontendAssetsChecker } from '../services/NewFrontendAssetsChecker';
|
||||||
@ -48,7 +48,7 @@ export function useChromeHeaderHeight() {
|
|||||||
const { chrome } = useGrafana();
|
const { chrome } = useGrafana();
|
||||||
const { kioskMode, searchBarHidden, chromeless } = chrome.useState();
|
const { kioskMode, searchBarHidden, chromeless } = chrome.useState();
|
||||||
|
|
||||||
if (kioskMode || chromeless || !config.featureToggles.bodyScrolling) {
|
if (kioskMode || chromeless) {
|
||||||
return 0;
|
return 0;
|
||||||
} else if (searchBarHidden) {
|
} else if (searchBarHidden) {
|
||||||
return SINGLE_HEADER_BAR_HEIGHT;
|
return SINGLE_HEADER_BAR_HEIGHT;
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { css, cx } from '@emotion/css';
|
import { css } from '@emotion/css';
|
||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
import { config } from '@grafana/runtime';
|
|
||||||
import { useStyles2 } from '@grafana/ui';
|
import { useStyles2 } from '@grafana/ui';
|
||||||
|
|
||||||
import { BouncingLoader } from '../components/BouncingLoader/BouncingLoader';
|
import { BouncingLoader } from '../components/BouncingLoader/BouncingLoader';
|
||||||
@ -10,12 +9,7 @@ export function GrafanaRouteLoading() {
|
|||||||
const styles = useStyles2(getStyles);
|
const styles = useStyles2(getStyles);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div className={styles.loadingPage}>
|
||||||
className={cx({
|
|
||||||
[styles.loadingPage]: !config.featureToggles.bodyScrolling,
|
|
||||||
[styles.loadingPageBodyScrolling]: config.featureToggles.bodyScrolling,
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<BouncingLoader />
|
<BouncingLoader />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -23,14 +17,6 @@ export function GrafanaRouteLoading() {
|
|||||||
|
|
||||||
const getStyles = (theme: GrafanaTheme2) => ({
|
const getStyles = (theme: GrafanaTheme2) => ({
|
||||||
loadingPage: css({
|
loadingPage: css({
|
||||||
backgroundColor: theme.colors.background.primary,
|
|
||||||
height: '100%',
|
|
||||||
flexDrection: 'column',
|
|
||||||
display: 'flex',
|
|
||||||
justifyContent: 'center',
|
|
||||||
alignItems: 'center',
|
|
||||||
}),
|
|
||||||
loadingPageBodyScrolling: css({
|
|
||||||
backgroundColor: theme.colors.background.primary,
|
backgroundColor: theme.colors.background.primary,
|
||||||
flex: 1,
|
flex: 1,
|
||||||
flexDrection: 'column',
|
flexDrection: 'column',
|
||||||
|
@ -2,7 +2,7 @@ import { css } from '@emotion/css';
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
import { config, useChromeHeaderHeight } from '@grafana/runtime';
|
import { useChromeHeaderHeight } from '@grafana/runtime';
|
||||||
import { Icon, Input, useStyles2 } from '@grafana/ui';
|
import { Icon, Input, useStyles2 } from '@grafana/ui';
|
||||||
import { t } from 'app/core/internationalization';
|
import { t } from 'app/core/internationalization';
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ export interface Props {
|
|||||||
|
|
||||||
export const Search = ({ onChange, value }: Props) => {
|
export const Search = ({ onChange, value }: Props) => {
|
||||||
const chromeHeaderHeight = useChromeHeaderHeight();
|
const chromeHeaderHeight = useChromeHeaderHeight();
|
||||||
const styles = useStyles2(getStyles, config.featureToggles.bodyScrolling ? (chromeHeaderHeight ?? 0) : 0);
|
const styles = useStyles2(getStyles, chromeHeaderHeight ?? 0);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.searchContainer}>
|
<div className={styles.searchContainer}>
|
||||||
|
@ -2,7 +2,6 @@ import { css, cx } from '@emotion/css';
|
|||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
import { selectors } from '@grafana/e2e-selectors';
|
import { selectors } from '@grafana/e2e-selectors';
|
||||||
import { config } from '@grafana/runtime';
|
|
||||||
import { SceneComponentProps } from '@grafana/scenes';
|
import { SceneComponentProps } from '@grafana/scenes';
|
||||||
import { Button, ToolbarButton, useStyles2 } from '@grafana/ui';
|
import { Button, ToolbarButton, useStyles2 } from '@grafana/ui';
|
||||||
|
|
||||||
@ -35,9 +34,7 @@ export function PanelEditorRenderer({ model }: SceneComponentProps<PanelEditor>)
|
|||||||
<NavToolbarActions dashboard={dashboard} />
|
<NavToolbarActions dashboard={dashboard} />
|
||||||
<div
|
<div
|
||||||
{...containerProps}
|
{...containerProps}
|
||||||
className={cx(containerProps.className, {
|
className={cx(containerProps.className, styles.content)}
|
||||||
[styles.content]: config.featureToggles.bodyScrolling,
|
|
||||||
})}
|
|
||||||
data-testid={selectors.components.PanelEditor.General.content}
|
data-testid={selectors.components.PanelEditor.General.content}
|
||||||
>
|
>
|
||||||
<div {...primaryProps} className={cx(primaryProps.className, styles.body)}>
|
<div {...primaryProps} className={cx(primaryProps.className, styles.body)}>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { css, cx } from '@emotion/css';
|
import { css } from '@emotion/css';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
import { AppPlugin, GrafanaTheme2, PluginContextProvider, UrlQueryMap } from '@grafana/data';
|
import { AppPlugin, GrafanaTheme2, PluginContextProvider, UrlQueryMap } from '@grafana/data';
|
||||||
@ -45,7 +45,7 @@ export function PluginDetailsBody({ plugin, queryParams, pageId }: Props): JSX.E
|
|||||||
if (pageId === PluginTabIds.OVERVIEW) {
|
if (pageId === PluginTabIds.OVERVIEW) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cx(styles.readme, styles.container)}
|
className={styles.readme}
|
||||||
dangerouslySetInnerHTML={{
|
dangerouslySetInnerHTML={{
|
||||||
__html: plugin.details?.readme ?? 'No plugin help or readme markdown file was found',
|
__html: plugin.details?.readme ?? 'No plugin help or readme markdown file was found',
|
||||||
}}
|
}}
|
||||||
@ -55,7 +55,7 @@ export function PluginDetailsBody({ plugin, queryParams, pageId }: Props): JSX.E
|
|||||||
|
|
||||||
if (pageId === PluginTabIds.VERSIONS) {
|
if (pageId === PluginTabIds.VERSIONS) {
|
||||||
return (
|
return (
|
||||||
<div className={styles.container}>
|
<div>
|
||||||
<VersionList versions={plugin.details?.versions} installedVersion={plugin.installedVersion} />
|
<VersionList versions={plugin.details?.versions} installedVersion={plugin.installedVersion} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -67,7 +67,7 @@ export function PluginDetailsBody({ plugin, queryParams, pageId }: Props): JSX.E
|
|||||||
|
|
||||||
if (pageId === PluginTabIds.CONFIG && pluginConfig?.angularConfigCtrl) {
|
if (pageId === PluginTabIds.CONFIG && pluginConfig?.angularConfigCtrl) {
|
||||||
return (
|
return (
|
||||||
<div className={styles.container}>
|
<div>
|
||||||
<AppConfigCtrlWrapper app={pluginConfig as AppPlugin} />
|
<AppConfigCtrlWrapper app={pluginConfig as AppPlugin} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -102,7 +102,7 @@ export function PluginDetailsBody({ plugin, queryParams, pageId }: Props): JSX.E
|
|||||||
for (const configPage of pluginConfig.configPages) {
|
for (const configPage of pluginConfig.configPages) {
|
||||||
if (pageId === configPage.id) {
|
if (pageId === configPage.id) {
|
||||||
return (
|
return (
|
||||||
<div className={styles.container}>
|
<div>
|
||||||
<PluginContextProvider meta={pluginConfig.meta}>
|
<PluginContextProvider meta={pluginConfig.meta}>
|
||||||
<configPage.body plugin={pluginConfig} query={queryParams} />
|
<configPage.body plugin={pluginConfig} query={queryParams} />
|
||||||
</PluginContextProvider>
|
</PluginContextProvider>
|
||||||
@ -114,7 +114,7 @@ export function PluginDetailsBody({ plugin, queryParams, pageId }: Props): JSX.E
|
|||||||
|
|
||||||
if (pageId === PluginTabIds.USAGE && pluginConfig) {
|
if (pageId === PluginTabIds.USAGE && pluginConfig) {
|
||||||
return (
|
return (
|
||||||
<div className={styles.container}>
|
<div>
|
||||||
<PluginUsage plugin={pluginConfig?.meta} />
|
<PluginUsage plugin={pluginConfig?.meta} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -122,25 +122,20 @@ export function PluginDetailsBody({ plugin, queryParams, pageId }: Props): JSX.E
|
|||||||
|
|
||||||
if (pageId === PluginTabIds.DASHBOARDS && pluginConfig) {
|
if (pageId === PluginTabIds.DASHBOARDS && pluginConfig) {
|
||||||
return (
|
return (
|
||||||
<div className={styles.container}>
|
<div>
|
||||||
<PluginDashboards plugin={pluginConfig?.meta} />
|
<PluginDashboards plugin={pluginConfig?.meta} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.container}>
|
<div>
|
||||||
<p>Page not found.</p>
|
<p>Page not found.</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getStyles = (theme: GrafanaTheme2) => ({
|
export const getStyles = (theme: GrafanaTheme2) => ({
|
||||||
container: config.featureToggles.bodyScrolling
|
|
||||||
? css({})
|
|
||||||
: css({
|
|
||||||
height: '100%',
|
|
||||||
}),
|
|
||||||
readme: css({
|
readme: css({
|
||||||
'& img': {
|
'& img': {
|
||||||
maxWidth: '100%',
|
maxWidth: '100%',
|
||||||
|
@ -113,15 +113,9 @@ export const getStyles = (theme: GrafanaTheme2) => {
|
|||||||
gap: theme.spacing(1),
|
gap: theme.spacing(1),
|
||||||
}),
|
}),
|
||||||
// Needed due to block formatting context
|
// Needed due to block formatting context
|
||||||
tabContent: config.featureToggles.bodyScrolling
|
tabContent: css({
|
||||||
? css({
|
paddingLeft: '5px',
|
||||||
paddingLeft: '5px',
|
}),
|
||||||
})
|
|
||||||
: css({
|
|
||||||
overflow: 'auto',
|
|
||||||
height: '100%',
|
|
||||||
paddingLeft: '5px',
|
|
||||||
}),
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user