diff --git a/CHANGELOG.unreleased.md b/CHANGELOG.unreleased.md index 851daa9680f..0dfeedfed29 100644 --- a/CHANGELOG.unreleased.md +++ b/CHANGELOG.unreleased.md @@ -18,6 +18,7 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.released ### Fixed - Searching the segments in the sidebar will highlight newly focused segments properly now. [#7406](https://github.com/scalableminds/webknossos/pull/7406) - Fixed a bug when opening a task for which a mag restriction exists. The bug only occurred when the referenced mag didn't exist in the dataset. [#7403](https://github.com/scalableminds/webknossos/pull/7403) +- Fixed styling issues with the maintenance banner so that it no longer overlaps other menus, tabs, and buttons. [#7421](https://github.com/scalableminds/webknossos/pull/7421) ### Removed diff --git a/frontend/javascripts/maintenance_banner.tsx b/frontend/javascripts/maintenance_banner.tsx index 537c891f8ce..ed709633d0c 100644 --- a/frontend/javascripts/maintenance_banner.tsx +++ b/frontend/javascripts/maintenance_banner.tsx @@ -4,123 +4,143 @@ import { } from "admin/admin_rest_api"; import { Alert } from "antd"; import FormattedDate from "components/formatted_date"; -import { useFetch, useInterval } from "libs/react_helpers"; -import { sleep } from "libs/utils"; +import { useInterval } from "libs/react_helpers"; +import _ from "lodash"; import constants from "oxalis/constants"; +import { setNavbarHeightAction } from "oxalis/model/actions/ui_actions"; import { setActiveUserAction } from "oxalis/model/actions/user_actions"; import { Store } from "oxalis/singletons"; import { OxalisState } from "oxalis/store"; -import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; import { useSelector } from "react-redux"; import { MaintenanceInfo } from "types/api_flow_types"; const INITIAL_DELAY = 5000; -const INTERVAL_TO_FETCH_MAINTENANCES_MS = 60000; +const INTERVAL_TO_FETCH_MAINTENANCES_MS = 60000; // 1min -export function MaintenanceBanner() { +const BANNER_STYLE: React.CSSProperties = { + position: "absolute", + top: 0, + left: 0, + height: constants.MAINTENANCE_BANNER_HEIGHT, +}; + +function setNavbarHeight(newNavbarHeight: number) { + Store.dispatch(setNavbarHeightAction(newNavbarHeight)); + document.documentElement.style.setProperty("--navbar-height", `${newNavbarHeight}px`); +} + +function UpcomingMaintenanceBanner({ maintenanceInfo }: { maintenanceInfo: MaintenanceInfo }) { const activeUser = useSelector((state: OxalisState) => state.activeUser); - const { isInAnnotationView } = useSelector((state: OxalisState) => state.uiInformation); - const topPaddingForNavbar = constants.NAVBAR_HEIGHT; - const statusBarHeight = 20; - const [currentAndUpcomingMaintenances, setCurrentAndUpcomingMaintenances] = useState< - Array - >([]); - const [position, setPosition] = useState({ top: topPaddingForNavbar }); - const [isTop, setIsTop] = useState(true); - - // Do an initial fetch of the maintenance status so that users are notified - // quickly in case of ongoing maintenances. - useFetch( - async () => { - await sleep(INITIAL_DELAY); - setCurrentAndUpcomingMaintenances(await listCurrentAndUpcomingMaintenances()); - }, - null, - [], - ); - // Also poll regularly. - useInterval(async () => { - setCurrentAndUpcomingMaintenances(await listCurrentAndUpcomingMaintenances()); - }, INTERVAL_TO_FETCH_MAINTENANCES_MS); - const activeUsersLatestAcknowledgedMaintenance = - activeUser?.novelUserExperienceInfos.latestAcknowledgedMaintenanceInfo; + const { startTime, endTime, message } = maintenanceInfo; + + const startDate = new Date(startTime); + const endDate = new Date(endTime); + const endDateFormat = startDate.getDate() === endDate.getDate() ? "HH:mm" : "YYYY-MM-DD HH:mm"; const saveUserClosedMaintenanceInfo = (closestUpcomingMaintenance: MaintenanceInfo) => { if (activeUser == null) return; + const [nextMaintenanceAcknowledged] = updateNovelUserExperienceInfos(activeUser, { latestAcknowledgedMaintenanceInfo: closestUpcomingMaintenance.id, }); Store.dispatch(setActiveUserAction(nextMaintenanceAcknowledged)); }; - const toggleTopOrBottomPosition = () => { - setPosition(isTop ? { top: topPaddingForNavbar } : { bottom: statusBarHeight }); - setIsTop(!isTop); - }; + return ( + + Upcoming maintenance: until{" "} + . {message} + + } + type="info" + banner + style={BANNER_STYLE} + closable + onClose={() => { + saveUserClosedMaintenanceInfo(maintenanceInfo); + setNavbarHeight(constants.DEFAULT_NAVBAR_HEIGHT); + }} + /> + ); +} - const getClosestUpcomingMaintenanceBanner = () => { - if (activeUser == null) return null; // upcoming maintenances are only shown after login - const currentTime = Date.now(); - const closestUpcomingMaintenance = currentAndUpcomingMaintenances - ?.filter((maintenance) => maintenance.startTime > currentTime) - .sort((a, b) => a.startTime - b.startTime)[0]; - if ( - closestUpcomingMaintenance == null || - activeUsersLatestAcknowledgedMaintenance === closestUpcomingMaintenance.id - ) - return null; - const startDate = new Date(closestUpcomingMaintenance.startTime); - const endDate = new Date(closestUpcomingMaintenance.endTime); - const endDateFormat = startDate.getDate() === endDate.getDate() ? "HH:mm" : "YYYY-MM-DD HH:mm"; - return ( - - Upcoming maintenance: {" "} - until{" "} - .{" "} - {closestUpcomingMaintenance.message} - - } - type="info" - closable - banner - onClose={() => saveUserClosedMaintenanceInfo(closestUpcomingMaintenance)} - /> - ); - }; +function CurrentMaintenanceBanner({ maintenanceInfo }: { maintenanceInfo: MaintenanceInfo }) { + const { endTime, message } = maintenanceInfo; - const getCurrentMaintenanceBanner = () => { - const currentTime = Date.now(); - const currentMaintenance = currentAndUpcomingMaintenances.find( - (maintenance) => maintenance.startTime < currentTime, - ); - if (currentMaintenance == null) return; - return ( - - Currently under maintenance, scheduled until{" "} - . {currentMaintenance.message} - - } - type="warning" - banner - onMouseEnter={() => { - if (isInAnnotationView) { - toggleTopOrBottomPosition(); - } - }} - style={{ ...position, position: isInAnnotationView ? "absolute" : "sticky" }} - /> + return ( + + Currently under maintenance, scheduled until .{" "} + {message} + + } + type="warning" + banner + style={BANNER_STYLE} + /> + ); +} + +export function MaintenanceBanner() { + const activeUser = useSelector((state: OxalisState) => state.activeUser); + + const [closestUpcomingMaintenance, setClosestUpcomingMaintenance] = useState< + MaintenanceInfo | undefined + >(undefined); + const [currentMaintenance, setCurrentMaintenance] = useState( + undefined, + ); + + async function pollMaintenances() { + const newScheduledMaintenances = await listCurrentAndUpcomingMaintenances(); + + const closestUpcomingMaintenance = newScheduledMaintenances + .filter((maintenance) => maintenance.startTime > Date.now()) + .filter( + (maintenance) => + maintenance.id !== activeUser?.novelUserExperienceInfos.latestAcknowledgedMaintenanceInfo, + ) + .sort((a, b) => a.startTime - b.startTime); + + const currentMaintenance = newScheduledMaintenances.find( + (maintenance) => maintenance.startTime < Date.now(), ); - }; - if (currentAndUpcomingMaintenances.length === 0) return null; - const currentlyUnderMaintenanceBanner = getCurrentMaintenanceBanner(); - if (currentlyUnderMaintenanceBanner != null) { - return currentlyUnderMaintenanceBanner; + setCurrentMaintenance(currentMaintenance); + setClosestUpcomingMaintenance(_.first(closestUpcomingMaintenance)); } - const upcomingMaintenanceBanners = getClosestUpcomingMaintenanceBanner(); - return upcomingMaintenanceBanners == null ? null : upcomingMaintenanceBanners; + + useEffect(() => { + if (currentMaintenance || closestUpcomingMaintenance) { + setNavbarHeight(constants.DEFAULT_NAVBAR_HEIGHT + constants.MAINTENANCE_BANNER_HEIGHT); + } + + if (currentMaintenance == null && closestUpcomingMaintenance == null) { + // Reset Navbar height if maintenance is over + setNavbarHeight(constants.DEFAULT_NAVBAR_HEIGHT); + } + }, [currentMaintenance, closestUpcomingMaintenance]); + + useEffect(() => { + // Do an initial fetch of the maintenance status so that users are notified + // quickly in case of ongoing maintenances. + setTimeout(pollMaintenances, INITIAL_DELAY); + }, []); + + // Also poll regularly. + useInterval(pollMaintenances, INTERVAL_TO_FETCH_MAINTENANCES_MS); + + if (currentMaintenance) { + return ; + } + + if (closestUpcomingMaintenance && activeUser !== null) { + return ; + } + + return null; } diff --git a/frontend/javascripts/navbar.tsx b/frontend/javascripts/navbar.tsx index 0395917a283..92bc0060d73 100644 --- a/frontend/javascripts/navbar.tsx +++ b/frontend/javascripts/navbar.tsx @@ -52,6 +52,8 @@ import messages from "messages"; import { PricingEnforcedSpan } from "components/pricing_enforcers"; import { ItemType, MenuItemType, SubMenuType } from "antd/lib/menu/hooks/useItems"; import { MenuClickEventHandler } from "rc-menu/lib/interface"; +import constants from "oxalis/constants"; +import { MaintenanceBanner } from "maintenance_banner"; const { Header } = Layout; @@ -67,6 +69,7 @@ type StateProps = { othersMayEdit: boolean; allowUpdate: boolean; blockedByUser: APIUserCompact | null | undefined; + navbarHeight: number; }; type Props = OwnProps & StateProps; // The user should click somewhere else to close that menu like it's done in most OS menus, anyway. 10 seconds. @@ -423,7 +426,13 @@ function getDashboardSubMenu(collapse: boolean): SubMenuType { }; } -function NotificationIcon({ activeUser }: { activeUser: APIUser }) { +function NotificationIcon({ + activeUser, + navbarHeight, +}: { + activeUser: APIUser; + navbarHeight: number; +}) { const maybeUnreadReleaseCount = useOlvyUnreadReleasesCount(activeUser); const handleShowWhatsNewView = () => { @@ -444,6 +453,8 @@ function NotificationIcon({ activeUser }: { activeUser: APIUser }) { position: "relative", display: "flex", marginRight: 12, + paddingTop: + navbarHeight > constants.DEFAULT_NAVBAR_HEIGHT ? constants.MAINTENANCE_BANNER_HEIGHT : 0, }} > @@ -477,7 +488,12 @@ export const switchTo = async (org: APIOrganization) => { function LoggedInAvatar({ activeUser, handleLogout, -}: { activeUser: APIUser; handleLogout: (event: React.SyntheticEvent) => void } & SubMenuProps) { + navbarHeight, +}: { + activeUser: APIUser; + handleLogout: (event: React.SyntheticEvent) => void; + navbarHeight: number; +} & SubMenuProps) { const { firstName, lastName, organization: organizationName, selectedTheme } = activeUser; const usersOrganizations = useFetch(getUsersOrganizations, [], []); const activeOrganization = usersOrganizations.find((org) => org.name === organizationName); @@ -536,7 +552,9 @@ function LoggedInAvatar({ constants.DEFAULT_NAVBAR_HEIGHT ? constants.MAINTENANCE_BANNER_HEIGHT : 0, + lineHeight: `${constants.DEFAULT_NAVBAR_HEIGHT}px`, }} theme="dark" subMenuCloseDelay={subMenuCloseDelay} @@ -702,6 +720,7 @@ function Navbar({ othersMayEdit, blockedByUser, allowUpdate, + navbarHeight, }: Props) { const history = useHistory(); @@ -773,12 +792,19 @@ function Navbar({ />, ); } - trailingNavItems.push(); + trailingNavItems.push( + , + ); trailingNavItems.push( , ); } @@ -808,12 +834,17 @@ function Navbar({ "collapsed-nav-header": collapseAllNavItems, })} > + setIsHelpMenuOpen(openKeys.includes(HELP_MENU_KEY))} style={{ - lineHeight: "48px", + paddingTop: + navbarHeight > constants.DEFAULT_NAVBAR_HEIGHT + ? constants.MAINTENANCE_BANNER_HEIGHT + : 0, + lineHeight: `${constants.DEFAULT_NAVBAR_HEIGHT}px`, }} theme="dark" subMenuCloseDelay={subMenuCloseDelay} @@ -835,6 +866,10 @@ function Navbar({ style={{ flex: 1, display: "flex", + paddingTop: + navbarHeight > constants.DEFAULT_NAVBAR_HEIGHT + ? constants.MAINTENANCE_BANNER_HEIGHT + : 0, }} /> @@ -858,6 +893,7 @@ const mapStateToProps = (state: OxalisState): StateProps => ({ othersMayEdit: state.tracing.othersMayEdit, blockedByUser: state.tracing.blockedByUser, allowUpdate: state.tracing.restrictions.allowUpdate, + navbarHeight: state.uiInformation.navbarHeight, }); const connector = connect(mapStateToProps); diff --git a/frontend/javascripts/oxalis/constants.ts b/frontend/javascripts/oxalis/constants.ts index 360fa548296..ee602fed5de 100644 --- a/frontend/javascripts/oxalis/constants.ts +++ b/frontend/javascripts/oxalis/constants.ts @@ -310,7 +310,8 @@ const Constants = { BUCKET_WIDTH: 32, BUCKET_SIZE: 32 ** 3, VIEWPORT_WIDTH, - NAVBAR_HEIGHT: 48, + DEFAULT_NAVBAR_HEIGHT: 48, + MAINTENANCE_BANNER_HEIGHT: 38, // For reference, the area of a large brush size (let's say, 300px) corresponds to // pi * 300 ^ 2 == 282690. // We multiply this with 5, since the labeling is not done diff --git a/frontend/javascripts/oxalis/default_state.ts b/frontend/javascripts/oxalis/default_state.ts index 3b4130b4c16..56b8b8b7289 100644 --- a/frontend/javascripts/oxalis/default_state.ts +++ b/frontend/javascripts/oxalis/default_state.ts @@ -10,6 +10,7 @@ import Constants, { InterpolationModeEnum, } from "oxalis/constants"; import { APIAllowedMode, APIAnnotationType, APIAnnotationVisibility } from "types/api_flow_types"; +import constants from "oxalis/constants"; const defaultViewportRect = { top: 0, left: 0, @@ -250,6 +251,7 @@ const defaultState: OxalisState = { lastMeasuredPosition: null, isMeasuring: false, }, + navbarHeight: constants.DEFAULT_NAVBAR_HEIGHT, }, localSegmentationData: {}, }; diff --git a/frontend/javascripts/oxalis/model/accessors/view_mode_accessor.ts b/frontend/javascripts/oxalis/model/accessors/view_mode_accessor.ts index dae3d2deb56..f40d480ca66 100644 --- a/frontend/javascripts/oxalis/model/accessors/view_mode_accessor.ts +++ b/frontend/javascripts/oxalis/model/accessors/view_mode_accessor.ts @@ -154,6 +154,7 @@ function _calculateMaybePlaneScreenPos( // This is achieved by reversing the calculations in _calculateMaybeGlobalPos. let point: Point2; planeId = planeId || state.viewModeData.plane.activeViewport; + const navbarHeight = state.uiInformation.navbarHeight; const curGlobalPos = getPosition(state.flycam); const planeRatio = getBaseVoxelFactors(state.dataset.dataSource.scale); const { width, height, top, left } = getInputCatcherRect(state, planeId); @@ -187,7 +188,7 @@ function _calculateMaybePlaneScreenPos( return null; } point.x += width / 2 + left; - point.y += height / 2 + top + constants.NAVBAR_HEIGHT; + point.y += height / 2 + top + navbarHeight; point.x = Math.round(point.x); point.y = Math.round(point.y); diff --git a/frontend/javascripts/oxalis/model/actions/ui_actions.ts b/frontend/javascripts/oxalis/model/actions/ui_actions.ts index 5f2c07e4e8e..c7ea1777641 100644 --- a/frontend/javascripts/oxalis/model/actions/ui_actions.ts +++ b/frontend/javascripts/oxalis/model/actions/ui_actions.ts @@ -24,6 +24,7 @@ type ShowQuickSelectSettingsAction = ReturnType; type SetLastMeasuredPositionAction = ReturnType; type SetIsMeasuringAction = ReturnType; +type SetNavbarHeightAction = ReturnType; type SetRenderAnimationModalVisibilityAction = ReturnType< typeof setRenderAnimationModalVisibilityAction @@ -52,7 +53,8 @@ export type UiAction = | ShowQuickSelectSettingsAction | HideMeasurementTooltipAction | SetLastMeasuredPositionAction - | SetIsMeasuringAction; + | SetIsMeasuringAction + | SetNavbarHeightAction; export const setDropzoneModalVisibilityAction = (visible: boolean) => ({ @@ -171,3 +173,8 @@ export const setIsMeasuringAction = (isMeasuring: boolean) => type: "SET_IS_MEASURING", isMeasuring, } as const); +export const setNavbarHeightAction = (navbarHeight: number) => + ({ + type: "SET_NAVBAR_HEIGHT", + navbarHeight, + } as const); diff --git a/frontend/javascripts/oxalis/model/reducers/ui_reducer.ts b/frontend/javascripts/oxalis/model/reducers/ui_reducer.ts index a8a79a67c90..115b806c318 100644 --- a/frontend/javascripts/oxalis/model/reducers/ui_reducer.ts +++ b/frontend/javascripts/oxalis/model/reducers/ui_reducer.ts @@ -148,6 +148,11 @@ function UiReducer(state: OxalisState, action: Action): OxalisState { isMeasuring: action.isMeasuring, }); } + case "SET_NAVBAR_HEIGHT": { + return updateKey(state, "uiInformation", { + navbarHeight: action.navbarHeight, + }); + } default: return state; diff --git a/frontend/javascripts/oxalis/store.ts b/frontend/javascripts/oxalis/store.ts index 8507974f6cf..a40f7b68792 100644 --- a/frontend/javascripts/oxalis/store.ts +++ b/frontend/javascripts/oxalis/store.ts @@ -528,6 +528,7 @@ type UiInformation = { | "active"; // the quick select saga is currently running (calculating as well as preview mode) readonly areQuickSelectSettingsOpen: boolean; readonly measurementToolInfo: { lastMeasuredPosition: Vector3 | null; isMeasuring: boolean }; + readonly navbarHeight: number; }; type BaseMeshInformation = { readonly segmentId: number; diff --git a/frontend/javascripts/oxalis/view/arbitrary_view.ts b/frontend/javascripts/oxalis/view/arbitrary_view.ts index ee51db810fb..9598861b900 100644 --- a/frontend/javascripts/oxalis/view/arbitrary_view.ts +++ b/frontend/javascripts/oxalis/view/arbitrary_view.ts @@ -16,6 +16,7 @@ import app from "app"; import getSceneController from "oxalis/controller/scene_controller_provider"; import window from "libs/window"; import { clearCanvas, setupRenderArea, renderToTexture } from "oxalis/view/rendering_utils"; +import { listenToStoreProperty } from "oxalis/model/helpers/listener_helpers"; type GeometryLike = { addToScene: (obj: THREE.Object3D) => void; @@ -106,6 +107,13 @@ class ArbitraryView { this.animationRequestId = window.requestAnimationFrame(this.animate); // Dont forget to handle window resizing! window.addEventListener("resize", this.resizeThrottled); + this.unsubscribeFunctions.push( + listenToStoreProperty( + (storeState) => storeState.uiInformation.navbarHeight, + () => this.resizeThrottled(), + true, + ), + ); } } diff --git a/frontend/javascripts/oxalis/view/layouting/default_layout_configs.ts b/frontend/javascripts/oxalis/view/layouting/default_layout_configs.ts index 65064d089f7..fdb79b7cc92 100644 --- a/frontend/javascripts/oxalis/view/layouting/default_layout_configs.ts +++ b/frontend/javascripts/oxalis/view/layouting/default_layout_configs.ts @@ -6,7 +6,6 @@ */ import _ from "lodash"; import { getIsInIframe } from "libs/utils"; -import constants from "oxalis/constants"; import type { BorderTabType, ControlMode, ViewMode } from "oxalis/constants"; import Constants, { ArbitraryViews, @@ -26,6 +25,7 @@ import type { Border, ModelConfig, } from "./flex_layout_types"; +import { Store } from "oxalis/singletons"; // Increment this number to invalidate old layoutConfigs in localStorage export const currentLayoutVersion = 15; const layoutHeaderHeight = 20; @@ -40,6 +40,7 @@ export const DEFAULT_LAYOUT_NAME = "Custom Layout"; // when it is set to 0, we use a value near value to make it almost not visible. const borderBarSize = 1; export const getGroundTruthLayoutRect = () => { + const storeState = Store.getState(); const mainContainer = document.querySelector(".ant-layout .ant-layout-has-sider"); let width; let height; @@ -48,7 +49,7 @@ export const getGroundTruthLayoutRect = () => { if (window.innerWidth) { width = window.innerWidth; height = window.innerHeight; - height -= constants.NAVBAR_HEIGHT; + height -= storeState.uiInformation.navbarHeight; } else { // use fallback values height = dummyExtent; diff --git a/frontend/javascripts/oxalis/view/nml_upload_zone_container.tsx b/frontend/javascripts/oxalis/view/nml_upload_zone_container.tsx index 52368dd9125..5ffc09bd841 100644 --- a/frontend/javascripts/oxalis/view/nml_upload_zone_container.tsx +++ b/frontend/javascripts/oxalis/view/nml_upload_zone_container.tsx @@ -9,7 +9,7 @@ import type { OxalisState } from "oxalis/store"; import { setDropzoneModalVisibilityAction } from "oxalis/model/actions/ui_actions"; import FormattedDate from "components/formatted_date"; import { trackAction } from "oxalis/model/helpers/analytics"; -import constants from "oxalis/constants"; + type State = { files: Array; dropzoneActive: boolean; @@ -25,6 +25,7 @@ type OwnProps = { type StateProps = { showDropzoneModal: boolean; hideDropzoneModal: () => void; + navbarHeight: number; }; type Props = StateProps & OwnProps; @@ -271,7 +272,7 @@ class NmlUploadZoneContainer extends React.PureComponent { {...getRootProps()} style={{ position: "relative", - height: `calc(100vh - ${constants.NAVBAR_HEIGHT}px)`, + height: `calc(100vh - ${this.props.navbarHeight}px)`, }} className="flex-column" > @@ -309,6 +310,7 @@ class NmlUploadZoneContainer extends React.PureComponent { const mapStateToProps = (state: OxalisState) => ({ showDropzoneModal: state.uiInformation.showDropzoneModal, + navbarHeight: state.uiInformation.navbarHeight, }); const mapDispatchToProps = (dispatch: Dispatch) => ({ diff --git a/frontend/javascripts/oxalis/view/plane_view.ts b/frontend/javascripts/oxalis/view/plane_view.ts index 409ab09491c..44a31f2c6c7 100644 --- a/frontend/javascripts/oxalis/view/plane_view.ts +++ b/frontend/javascripts/oxalis/view/plane_view.ts @@ -15,6 +15,7 @@ import { clearCanvas, setupRenderArea } from "oxalis/view/rendering_utils"; import VisibilityAwareRaycaster, { type RaycastIntersection, } from "libs/visibility_aware_raycaster"; +import { listenToStoreProperty } from "oxalis/model/helpers/listener_helpers"; const createDirLight = ( position: Vector3, @@ -248,6 +249,13 @@ class PlaneView { this.resize(); this.animate(); window.addEventListener("resize", this.resizeThrottled); + this.unsubscribeFunctions.push( + listenToStoreProperty( + (storeState) => storeState.uiInformation.navbarHeight, + () => this.resizeThrottled(), + true, + ), + ); } } diff --git a/frontend/javascripts/router.tsx b/frontend/javascripts/router.tsx index 68bb067132a..983ac54aea4 100644 --- a/frontend/javascripts/router.tsx +++ b/frontend/javascripts/router.tsx @@ -67,7 +67,6 @@ import { import ErrorBoundary from "components/error_boundary"; import { Store } from "oxalis/singletons"; import VerifyEmailView from "admin/auth/verify_email_view"; -import { MaintenanceBanner } from "maintenance_banner"; const { Content } = Layout; @@ -223,7 +222,6 @@ class ReactRouter extends React.Component { - section > .ant-layout-header { @@ -139,7 +139,7 @@ body { } .onboarding { - min-height: calc(100vh - @navbar-height); + min-height: calc(100vh - var(--navbar-height)); display: flex; flex-direction: column; padding-bottom: 50px; @@ -626,7 +626,7 @@ i.without-icon-margin, .login-view { & { height: 100%; - min-height: calc(100vh - @navbar-height); + min-height: calc(100vh - var(--navbar-height)); background: @background-blue-neurons; } diff --git a/frontend/stylesheets/trace_view/_tracing_view.less b/frontend/stylesheets/trace_view/_tracing_view.less index d7a32e389a3..5584f5bbab8 100644 --- a/frontend/stylesheets/trace_view/_tracing_view.less +++ b/frontend/stylesheets/trace_view/_tracing_view.less @@ -92,7 +92,7 @@ } .tracing-layout { - height: calc(100vh - @navbar-height); + height: calc(100vh - var(--navbar-height)); display: flex; &.ant-layout, @@ -205,7 +205,7 @@ position: fixed; right: 0; z-index: 1000; - top: @navbar-height; + top: var(--navbar-height); bottom: 0; .version-section { @@ -319,7 +319,7 @@ img.keyboard-mouse-icon:first-child { overflow-x: auto; overflow-y: hidden; position: fixed; - height: @navbar-height; + height: var(--navbar-height); display: flex; align-items: center; white-space: nowrap; @@ -599,7 +599,7 @@ img.keyboard-mouse-icon:first-child { /* The navbar and footer have a higher z-value than the context menu and should not be covered by the context menu overlay. At the same time the overlay serves as the container for the css-sticky context menu. */ - height: calc(100% - @navbar-height - @footer-height); + height: calc(100% - var(--navbar-height) - @footer-height); position: absolute; /* The context menu needs a higher z-value than flexlayout__tab_button_content. Otherwise the tab title covers the context menu. */