From 2352cbc5dd931440cee42bfb387d89eeeab75948 Mon Sep 17 00:00:00 2001 From: Revanshu Paliwal Date: Fri, 5 Jan 2024 10:01:02 +0100 Subject: [PATCH] SONAR-21401 Migrating admin sub header to adopt the new UI --- .../main/js/app/components/AdminContainer.tsx | 22 +- .../__tests__/AdminContainer-test.tsx | 1 + .../settings/PendingPluginsActionNotif.tsx | 17 +- .../components/nav/settings/SettingsNav.tsx | 252 ++++++++---------- .../nav/settings/SystemRestartNotif.tsx | 25 +- .../js/components/common/RestartButton.tsx | 15 +- .../main/js/components/ui/ContextNavBar.css | 99 ------- .../main/js/components/ui/ContextNavBar.tsx | 36 --- .../src/main/js/components/ui/NavBar.css | 51 ---- .../src/main/js/components/ui/NavBar.tsx | 78 ------ 10 files changed, 156 insertions(+), 440 deletions(-) delete mode 100644 server/sonar-web/src/main/js/components/ui/ContextNavBar.css delete mode 100644 server/sonar-web/src/main/js/components/ui/ContextNavBar.tsx delete mode 100644 server/sonar-web/src/main/js/components/ui/NavBar.css delete mode 100644 server/sonar-web/src/main/js/components/ui/NavBar.tsx diff --git a/server/sonar-web/src/main/js/app/components/AdminContainer.tsx b/server/sonar-web/src/main/js/app/components/AdminContainer.tsx index 57fe2bc1643..8d5741c7176 100644 --- a/server/sonar-web/src/main/js/app/components/AdminContainer.tsx +++ b/server/sonar-web/src/main/js/app/components/AdminContainer.tsx @@ -18,6 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; +import { createPortal } from 'react-dom'; import { Helmet } from 'react-helmet-async'; import { Outlet } from 'react-router-dom'; import { getSettingsNavigation } from '../../api/navigation'; @@ -45,6 +46,7 @@ interface State { export class AdminContainer extends React.PureComponent { mounted = false; + portalAnchor: Element | null = null; state: State = { pendingPlugins: defaultPendingPlugins, systemStatus: defaultSystemStatus, @@ -53,6 +55,7 @@ export class AdminContainer extends React.PureComponent - + {this.portalAnchor && + createPortal( + , + this.portalAnchor, + )} + +
    {adminPages.map((page) => (
  • {page.name}
  • diff --git a/server/sonar-web/src/main/js/app/components/nav/settings/PendingPluginsActionNotif.tsx b/server/sonar-web/src/main/js/app/components/nav/settings/PendingPluginsActionNotif.tsx index 20776092fa1..0aebad7f66c 100644 --- a/server/sonar-web/src/main/js/app/components/nav/settings/PendingPluginsActionNotif.tsx +++ b/server/sonar-web/src/main/js/app/components/nav/settings/PendingPluginsActionNotif.tsx @@ -17,13 +17,12 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { ButtonSecondary, FlagMessage } from 'design-system/lib'; import * as React from 'react'; import { FormattedMessage } from 'react-intl'; import { cancelPendingPlugins } from '../../../../api/plugins'; import InstanceMessage from '../../../../components/common/InstanceMessage'; import RestartButton from '../../../../components/common/RestartButton'; -import { Button } from '../../../../components/controls/buttons'; -import { Alert } from '../../../../components/ui/Alert'; import { translate } from '../../../../helpers/l10n'; import { PendingPluginResult } from '../../../../types/plugins'; import { SysStatus } from '../../../../types/types'; @@ -48,9 +47,9 @@ export default class PendingPluginsActionNotif extends React.PureComponent -
    - + +
    + {[ @@ -71,15 +70,15 @@ export default class PendingPluginsActionNotif extends React.PureComponent - +
    - +
    ); } } diff --git a/server/sonar-web/src/main/js/app/components/nav/settings/SettingsNav.tsx b/server/sonar-web/src/main/js/app/components/nav/settings/SettingsNav.tsx index c50272d1468..45ee8fd6b01 100644 --- a/server/sonar-web/src/main/js/app/components/nav/settings/SettingsNav.tsx +++ b/server/sonar-web/src/main/js/app/components/nav/settings/SettingsNav.tsx @@ -17,20 +17,23 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import classNames from 'classnames'; +import { + Dropdown, + ItemNavLink, + LightLabel, + NavBarTabLink, + NavBarTabs, + PopupZLevel, + TopBar, +} from 'design-system'; import * as React from 'react'; -import { Location, NavLink } from 'react-router-dom'; -import Dropdown from '../../../../components/controls/Dropdown'; +import { Location } from 'react-router-dom'; import withLocation from '../../../../components/hoc/withLocation'; -import DropdownIcon from '../../../../components/icons/DropdownIcon'; -import ContextNavBar from '../../../../components/ui/ContextNavBar'; -import NavBarTabs from '../../../../components/ui/NavBarTabs'; import { translate } from '../../../../helpers/l10n'; import { getBaseUrl } from '../../../../helpers/system'; import { AdminPageExtension } from '../../../../types/extension'; import { PendingPluginResult } from '../../../../types/plugins'; import { Extension, SysStatus } from '../../../../types/types'; -import { rawSizes } from '../../../theme'; import PendingPluginsActionNotif from './PendingPluginsActionNotif'; import SystemRestartNotif from './SystemRestartNotif'; @@ -43,8 +46,6 @@ interface Props { systemStatus: SysStatus; } -const ALERT_HEIGHT = 30; - export class SettingsNav extends React.PureComponent { static defaultProps = { extensions: [], @@ -87,9 +88,9 @@ export class SettingsNav extends React.PureComponent { renderExtension = ({ key, name }: Extension) => { return ( -
  • - {name} -
  • + + {name} + ); }; @@ -99,50 +100,46 @@ export class SettingsNav extends React.PureComponent { ); return ( -
  • - - {translate('settings.page')} - -
  • -
  • - - {translate('property.category.security.encryption')} - -
  • -
  • - - {translate('webhooks.page')} - -
  • + <> + + {translate('settings.page')} + + + + {translate('property.category.security.encryption')} + + + + {translate('webhooks.page')} + + {extensionsWithoutSupport.map(this.renderExtension)} -
+ } - tagName="li" + size="auto" + zLevel={PopupZLevel.Global} > {({ onToggleClick, open }) => ( - - {translate('sidebar.project_settings')} - - + text={translate('sidebar.project_settings')} + withChevron + /> )} ); @@ -151,34 +148,31 @@ export class SettingsNav extends React.PureComponent { renderProjectsTab() { return ( -
  • - - {translate('management')} - -
  • -
  • - - {translate('background_tasks.page')} - -
  • - + <> + + {translate('management')} + + + + {translate('background_tasks.page')} + + } - tagName="li" + size="auto" + zLevel={PopupZLevel.Global} > {({ onToggleClick, open }) => ( - - {translate('sidebar.projects')} - - + text={translate('sidebar.projects')} + withChevron + /> )}
    ); @@ -187,44 +181,35 @@ export class SettingsNav extends React.PureComponent { renderSecurityTab() { return ( -
  • - - {translate('users.page')} - -
  • -
  • - - {translate('user_groups.page')} - -
  • -
  • - - {translate('global_permissions.page')} - -
  • -
  • - - {translate('permission_templates')} - -
  • - + <> + {translate('users.page')} + + {translate('user_groups.page')} + + + {translate('global_permissions.page')} + + + + {translate('permission_templates')} + + } - tagName="li" + size="auto" + zLevel={PopupZLevel.Global} > {({ onToggleClick, open }) => ( - - {translate('sidebar.security')} - - + text={translate('sidebar.security')} + withChevron + /> )}
    ); @@ -240,7 +225,6 @@ export class SettingsNav extends React.PureComponent { pendingPlugins.installing.length + pendingPlugins.removing.length + pendingPlugins.updating.length; - const contextNavHeight = rawSizes.contextNavHeightRaw; let notifComponent; if (this.props.systemStatus === 'RESTARTING') { notifComponent = ; @@ -256,50 +240,40 @@ export class SettingsNav extends React.PureComponent { } return ( - -
    -

    {translate('layout.settings')}

    -
    + <> + + {translate('layout.settings')} - - {this.renderConfigurationTab()} - {this.renderSecurityTab()} - {this.renderProjectsTab()} + + {this.renderConfigurationTab()} + {this.renderSecurityTab()} + {this.renderProjectsTab()} -
  • - - {translate('sidebar.system')} - -
  • + -
  • - - {translate('marketplace.page')} - -
  • + - {hasGovernanceExtension && ( -
  • - - {translate('audit_logs.page')} - -
  • - )} + {hasGovernanceExtension && ( + + )} - {hasSupportExtension && ( -
  • - - {translate('support')} - -
  • - )} -
    -
    + {hasSupportExtension && ( + + )} + + + {notifComponent} + + ); } } diff --git a/server/sonar-web/src/main/js/app/components/nav/settings/SystemRestartNotif.tsx b/server/sonar-web/src/main/js/app/components/nav/settings/SystemRestartNotif.tsx index 21b29c8426d..566fe405590 100644 --- a/server/sonar-web/src/main/js/app/components/nav/settings/SystemRestartNotif.tsx +++ b/server/sonar-web/src/main/js/app/components/nav/settings/SystemRestartNotif.tsx @@ -17,24 +17,25 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { FlagMessage, Link } from 'design-system'; import * as React from 'react'; import { FormattedMessage } from 'react-intl'; -import Link from '../../../../components/common/Link'; -import { Alert } from '../../../../components/ui/Alert'; import { translate } from '../../../../helpers/l10n'; import { getInstance } from '../../../../helpers/system'; export default function SystemRestartNotif() { return ( - - {translate('background_tasks.page')}, - }} - /> - + + + {translate('background_tasks.page')}, + }} + /> + + ); } diff --git a/server/sonar-web/src/main/js/components/common/RestartButton.tsx b/server/sonar-web/src/main/js/components/common/RestartButton.tsx index 497aef229f4..2ce86b2db29 100644 --- a/server/sonar-web/src/main/js/components/common/RestartButton.tsx +++ b/server/sonar-web/src/main/js/components/common/RestartButton.tsx @@ -17,10 +17,9 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import classNames from 'classnames'; +import { DangerButtonSecondary } from 'design-system/lib'; import * as React from 'react'; import { restart } from '../../api/system'; -import { Button } from '../../components/controls/buttons'; import ConfirmButton from '../../components/controls/ConfirmButton'; import { translate } from '../../helpers/l10n'; import { SysStatus } from '../../types/types'; @@ -41,10 +40,8 @@ export default class RestartButton extends React.PureComponent { confirmButtonText={translate('restart')} modalBody={ <> -

    - {translate('system.are_you_sure_to_restart')} -

    -

    {translate('system.forcing_shutdown_not_recommended')}

    +

    {translate('system.are_you_sure_to_restart')}

    +

    {translate('system.forcing_shutdown_not_recommended')}

    {translate('system.restart_does_not_reload_sonar_properties')}

    } @@ -52,15 +49,15 @@ export default class RestartButton extends React.PureComponent { onConfirm={this.handleConfirm} > {({ onClick }) => ( - + )} ); diff --git a/server/sonar-web/src/main/js/components/ui/ContextNavBar.css b/server/sonar-web/src/main/js/components/ui/ContextNavBar.css deleted file mode 100644 index d19f82b1617..00000000000 --- a/server/sonar-web/src/main/js/components/ui/ContextNavBar.css +++ /dev/null @@ -1,99 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -.navbar-context, -.navbar-context .navbar-inner { - background-color: #fff; - z-index: var(--contextbarZIndex); -} - -.navbar-context .navbar-inner { - padding-top: var(--gridSize); - border-bottom: 1px solid var(--barBorderColor); -} - -.navbar-context .navbar-inner-with-notif { - border-bottom: none; -} - -.navbar-context-justified { - display: flex; - justify-content: space-between; -} - -/* use `min-width: 0` to cut breadcrumb links (to end with "...") */ -/* https://stackoverflow.com/questions/38223879/white-space-nowrap-breaks-flexbox-layout */ -.navbar-context-header { - display: flex; - align-items: center; - min-width: 0; - height: calc(4 * var(--gridSize)); - font-size: var(--bigFontSize); -} - -/* disallow icons and slash separators to shrink */ -.navbar-context-header > *:not(.navbar-context-header-breadcrumb-link) { - flex-shrink: 0; -} - -.navbar-context-header-breadcrumb-link { - min-width: 0; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.navbar-context-header .slash-separator { - margin-left: var(--gridSize); - margin-right: var(--gridSize); - font-size: 24px; -} - -.navbar-context-header .slash-separator::after { - color: rgba(68, 68, 68, 0.2); -} - -/* set `min-width: 0` to allow flexbox item to shrink */ -/* https://stackoverflow.com/questions/38223879/white-space-nowrap-breaks-flexbox-layout */ -.navbar-context-meta { - display: flex; - align-items: center; - height: calc(4 * var(--gridSize)); - padding-left: 20px; - color: var(--secondFontColor); - font-size: var(--smallFontSize); - text-align: right; -} - -.navbar-context-meta-secondary { - position: absolute; - top: 34px; - right: 0; - padding: 0 20px; - white-space: nowrap; -} - -.navbar-context-description { - display: inline-block; - line-height: var(--controlHeight); - margin-left: var(--gridSize); - padding-top: 4px; - color: var(--secondFontColor); - font-size: var(--smallFontSize); -} diff --git a/server/sonar-web/src/main/js/components/ui/ContextNavBar.tsx b/server/sonar-web/src/main/js/components/ui/ContextNavBar.tsx deleted file mode 100644 index 5adca6e9e9a..00000000000 --- a/server/sonar-web/src/main/js/components/ui/ContextNavBar.tsx +++ /dev/null @@ -1,36 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import classNames from 'classnames'; -import * as React from 'react'; -import './ContextNavBar.css'; -import NavBar, { NavBarProps } from './NavBar'; - -interface Props extends NavBarProps { - className?: string; - id?: string; - height: number; - label: string; -} - -export default function ContextNavBar({ className, label, ...other }: Props) { - return ( - - ); -} diff --git a/server/sonar-web/src/main/js/components/ui/NavBar.css b/server/sonar-web/src/main/js/components/ui/NavBar.css deleted file mode 100644 index e1ad79b646e..00000000000 --- a/server/sonar-web/src/main/js/components/ui/NavBar.css +++ /dev/null @@ -1,51 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -.navbar, -[class^='navbar-'], -[class*=' navbar-'] { - box-sizing: border-box; -} - -.navbar-inner { - position: fixed; - left: 0; - right: 0; -} - -.navbar-inner h1 { - line-height: inherit; -} - -.navbar-inner > div { - position: relative; - min-width: var(--minPageWidth); - padding-left: var(--pagePadding); - padding-right: var(--pagePadding); -} - -.navbar-limited { - max-width: var(--maxPageWidth); - margin-left: auto; - margin-right: auto; -} - -.ReactModal__Body--open .navbar-inner { - padding-right: var(--sbw); -} diff --git a/server/sonar-web/src/main/js/components/ui/NavBar.tsx b/server/sonar-web/src/main/js/components/ui/NavBar.tsx deleted file mode 100644 index 3ad215155de..00000000000 --- a/server/sonar-web/src/main/js/components/ui/NavBar.tsx +++ /dev/null @@ -1,78 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import classNames from 'classnames'; -import { throttle } from 'lodash'; -import * as React from 'react'; -import './NavBar.css'; - -export interface NavBarProps { - children?: React.ReactNode; - className?: string; - height: number; - limited?: boolean; - top?: number; - notif?: React.ReactNode; -} - -interface State { - left: number; -} - -export default class NavBar extends React.PureComponent< - NavBarProps & React.HTMLProps, - State -> { - throttledFollowHorizontalScroll: () => void; - - constructor(props: NavBarProps) { - super(props); - this.state = { left: 0 }; - this.throttledFollowHorizontalScroll = throttle(this.followHorizontalScroll, 10); - } - - componentDidMount() { - document.addEventListener('scroll', this.throttledFollowHorizontalScroll); - } - - componentWillUnmount() { - document.removeEventListener('scroll', this.throttledFollowHorizontalScroll); - } - - followHorizontalScroll = () => { - if (document.documentElement) { - this.setState({ left: -document.documentElement.scrollLeft }); - } - }; - - render() { - const { children, className, height, limited = true, top, notif, ...other } = this.props; - return ( - - ); - } -} -- 2.39.5