import GlobalNav from './nav/global/GlobalNav';
import PromotionNotification from './promotion-notification/PromotionNotification';
import StartupModal from './StartupModal';
+import SystemAnnouncement from './SystemAnnouncement';
import UpdateNotification from './update-notification/UpdateNotification';
export default function GlobalContainer() {
<IndexationContextProvider>
<LanguagesContextProvider>
<MetricsContextProvider>
- <GlobalNav location={location} />
+ <SystemAnnouncement />
<IndexationNotification />
<UpdateNotification dismissable={true} />
+ <GlobalNav location={location} />
<Outlet />
</MetricsContextProvider>
</LanguagesContextProvider>
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 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.
+ */
+
+.system-announcement-wrapper {
+ height: 34px;
+}
+
+.system-announcement-banner {
+ position: fixed;
+ width: 100%;
+ z-index: var(--globalBannerZIndex);
+}
+
+.system-announcement-banner .alert-content {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 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 { isEmpty, keyBy } from 'lodash';
+import * as React from 'react';
+import { getValues } from '../../api/settings';
+import { Alert } from '../../components/ui/Alert';
+import { GlobalSettingKeys, SettingValue } from '../../types/settings';
+import './SystemAnnouncement.css';
+
+interface State {
+ displayMessage: boolean;
+ message: string;
+}
+
+export default class SystemAnnouncement extends React.PureComponent<{}, State> {
+ state: State = { displayMessage: false, message: '' };
+
+ componentDidMount() {
+ this.getSettings();
+ document.addEventListener('visibilitychange', this.handleVisibilityChange);
+ }
+
+ componentWillUnmount() {
+ document.removeEventListener('visibilitychange', this.handleVisibilityChange);
+ }
+
+ getSettings = async () => {
+ const values: SettingValue[] = await getValues({
+ keys: [GlobalSettingKeys.DisplaySystemMessage, GlobalSettingKeys.SystemMessage].join(',')
+ });
+ const settings = keyBy(values, 'key');
+
+ this.setState({
+ displayMessage: settings[GlobalSettingKeys.DisplaySystemMessage].value === 'true',
+ message:
+ (settings[GlobalSettingKeys.SystemMessage] &&
+ settings[GlobalSettingKeys.SystemMessage].value) ||
+ ''
+ });
+ };
+
+ handleVisibilityChange = () => {
+ if (document.visibilityState === 'visible') {
+ this.getSettings();
+ }
+ };
+
+ render() {
+ const { displayMessage, message } = this.state;
+ if (!displayMessage || isEmpty(message)) {
+ return null;
+ }
+
+ return (
+ <div className="system-announcement-wrapper">
+ <Alert
+ className="system-announcement-banner"
+ title={message}
+ display="banner"
+ variant="warning">
+ {message}
+ </Alert>
+ </div>
+ );
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 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 { fireEvent, screen } from '@testing-library/dom';
+import * as React from 'react';
+import { getValues } from '../../../api/settings';
+import { renderComponent } from '../../../helpers/testReactTestingUtils';
+import SystemAnnouncement from '../SystemAnnouncement';
+
+jest.mock('../../../api/settings', () => ({
+ getValues: jest.fn()
+}));
+
+it('should display system announcement', async () => {
+ (getValues as jest.Mock)
+ .mockResolvedValueOnce([
+ {
+ key: 'sonar.systemAnnouncement.displayMessage',
+ value: 'false',
+ inherited: true
+ }
+ ])
+ .mockResolvedValueOnce([
+ {
+ key: 'sonar.systemAnnouncement.displayMessage',
+ value: 'false',
+ inherited: true
+ }
+ ])
+ .mockResolvedValueOnce([
+ {
+ key: 'sonar.systemAnnouncement.displayMessage',
+ value: 'true'
+ }
+ ])
+ .mockResolvedValueOnce([
+ {
+ key: 'sonar.systemAnnouncement.displayMessage',
+ value: 'true'
+ },
+ {
+ key: 'sonar.systemAnnouncement.message',
+ value: ''
+ }
+ ])
+ .mockResolvedValueOnce([
+ {
+ key: 'sonar.systemAnnouncement.displayMessage',
+ value: 'true'
+ },
+ {
+ key: 'sonar.systemAnnouncement.message',
+ value: 'Foo'
+ }
+ ]);
+
+ renderSystemAnnouncement();
+
+ expect(screen.queryByRole('alert')).not.toBeInTheDocument();
+ fireEvent(document, new Event('visibilitychange'));
+ expect(screen.queryByRole('alert')).not.toBeInTheDocument();
+ fireEvent(document, new Event('visibilitychange'));
+ expect(screen.queryByRole('alert')).not.toBeInTheDocument();
+ fireEvent(document, new Event('visibilitychange'));
+ expect(screen.queryByRole('alert')).not.toBeInTheDocument();
+ fireEvent(document, new Event('visibilitychange'));
+ expect(await screen.findByRole('alert')).toBeInTheDocument();
+ expect(screen.getByText('Foo')).toBeInTheDocument();
+});
+
+function renderSystemAnnouncement() {
+ return renderComponent(<SystemAnnouncement />);
+}
GravatarServerUrl = 'sonar.lf.gravatarServerUrl',
RatingGrid = 'sonar.technicalDebt.ratingGrid',
DeveloperAggregatedInfoDisabled = 'sonar.developerAggregatedInfo.disabled',
- UpdatecenterActivated = 'sonar.updatecenter.activate'
+ UpdatecenterActivated = 'sonar.updatecenter.activate',
+ DisplaySystemMessage = 'sonar.systemAnnouncement.displayMessage',
+ SystemMessage = 'sonar.systemAnnouncement.message'
}
export type SettingDefinitionAndValue = {
.build(),
PropertyDefinition.builder(SYSTEM_ANNOUNCEMENT_MESSAGE)
.name("System announcement message")
- .description("If \"Display system announcement message\" is set to True, this message will be displayed in a banner to all authenticate SonarQube users.")
+ .description("If \"Display system announcement message\" is set to True, this message will be displayed in a warning banner to all SonarQube users."
+ +" If this field is empty, no message will be displayed, even if \"Display system announcement message\" is set to True.")
.category(CoreProperties.CATEGORY_GENERAL)
.subCategory(SUB_SYSTEM_ANNOUNCEMENT)
.type(TEXT)
.build(),
PropertyDefinition.builder(SYSTEM_ANNOUNCEMENT_DISPLAY_MESSAGE)
.name("Display system announcement message")
- .description("If set to True, the \"System announcement message\" will be displayed in a banner to all authenticate SonarQube users.")
+ .description("If set to True, the \"System announcement message\" will be displayed in a warning banner to all SonarQube users.")
.defaultValue(Boolean.toString(false))
.subCategory(SUB_SYSTEM_ANNOUNCEMENT)
.category(CoreProperties.CATEGORY_GENERAL)