aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main/js/app
diff options
context:
space:
mode:
authorMathieu Suen <mathieu.suen@sonarsource.com>2023-06-07 10:47:43 +0200
committersonartech <sonartech@sonarsource.com>2023-06-08 20:03:08 +0000
commit6f888d63127e272d76683f05af7949222c424f9e (patch)
tree5c0a789195396c29bdf85e847bf31040800878fc /server/sonar-web/src/main/js/app
parent514e75c10add5b1bbe95387dd6b03db5f6a8aa93 (diff)
downloadsonarqube-6f888d63127e272d76683f05af7949222c424f9e.tar.gz
sonarqube-6f888d63127e272d76683f05af7949222c424f9e.zip
SONAR-19380 Make alert component less noisy for screen reader
Diffstat (limited to 'server/sonar-web/src/main/js/app')
-rw-r--r--server/sonar-web/src/main/js/app/components/GitHubSynchronisationWarning.tsx84
-rw-r--r--server/sonar-web/src/main/js/app/components/SystemAnnouncement.tsx14
-rw-r--r--server/sonar-web/src/main/js/app/components/__tests__/SystemAnnouncement-test.tsx2
-rw-r--r--server/sonar-web/src/main/js/app/components/indexation/IndexationNotification.tsx4
-rw-r--r--server/sonar-web/src/main/js/app/components/indexation/IndexationNotificationRenderer.tsx26
-rw-r--r--server/sonar-web/src/main/js/app/components/indexation/__tests__/__snapshots__/IndexationNotificationRenderer-test.tsx.snap8
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/projectInformation/notifications/ProjectNotifications.tsx2
7 files changed, 84 insertions, 56 deletions
diff --git a/server/sonar-web/src/main/js/app/components/GitHubSynchronisationWarning.tsx b/server/sonar-web/src/main/js/app/components/GitHubSynchronisationWarning.tsx
index 5d7cb2544c7..b9ee787e9ba 100644
--- a/server/sonar-web/src/main/js/app/components/GitHubSynchronisationWarning.tsx
+++ b/server/sonar-web/src/main/js/app/components/GitHubSynchronisationWarning.tsx
@@ -31,7 +31,7 @@ import './SystemAnnouncement.css';
interface LastSyncProps {
short?: boolean;
- info: Required<GithubStatusEnabled>['lastSync'];
+ info: GithubStatusEnabled['lastSync'];
}
interface GitHubSynchronisationWarningProps {
@@ -39,6 +39,9 @@ interface GitHubSynchronisationWarningProps {
}
function LastSyncAlert({ info, short }: LastSyncProps) {
+ if (info === undefined) {
+ return null;
+ }
const { finishedAt, errorMessage, status, summary } = info;
const formattedDate = finishedAt ? formatDistance(new Date(finishedAt), new Date()) : '';
@@ -73,25 +76,33 @@ function LastSyncAlert({ info, short }: LastSyncProps) {
);
}
- return status === TaskStatuses.Success ? (
- <Alert variant="success">
- {translateWithParameters(
- 'settings.authentication.github.synchronization_successful',
- formattedDate
+ return (
+ <Alert
+ variant={status === TaskStatuses.Success ? 'success' : 'error'}
+ role="alert"
+ aria-live="assertive"
+ >
+ {status === TaskStatuses.Success ? (
+ <>
+ {translateWithParameters(
+ 'settings.authentication.github.synchronization_successful',
+ formattedDate
+ )}
+ <br />
+ {summary ?? ''}
+ </>
+ ) : (
+ <React.Fragment key={`synch-alert-${finishedAt}`}>
+ <div>
+ {translateWithParameters(
+ 'settings.authentication.github.synchronization_failed',
+ formattedDate
+ )}
+ </div>
+ <br />
+ {errorMessage ?? ''}
+ </React.Fragment>
)}
- <br />
- {summary ?? ''}
- </Alert>
- ) : (
- <Alert variant="error">
- <div>
- {translateWithParameters(
- 'settings.authentication.github.synchronization_failed',
- formattedDate
- )}
- </div>
- <br />
- {errorMessage ?? ''}
</Alert>
);
}
@@ -105,19 +116,28 @@ function GitHubSynchronisationWarning({ short }: GitHubSynchronisationWarningPro
return (
<>
- {!short && data?.nextSync && (
- <>
- <Alert variant="loading" className="spacer-bottom">
- {translate(
- data.nextSync.status === TaskStatuses.Pending
- ? 'settings.authentication.github.synchronization_pending'
- : 'settings.authentication.github.synchronization_in_progress'
- )}
- </Alert>
- <br />
- </>
- )}
- {data?.lastSync && <LastSyncAlert short={short} info={data.lastSync} />}
+ <Alert
+ variant="loading"
+ className="spacer-bottom"
+ aria-atomic={true}
+ role="alert"
+ aria-live="assertive"
+ aria-label={
+ data.nextSync === undefined
+ ? translate('settings.authentication.github.synchronization_finish')
+ : ''
+ }
+ >
+ {!short &&
+ data?.nextSync &&
+ translate(
+ data.nextSync.status === TaskStatuses.Pending
+ ? 'settings.authentication.github.synchronization_pending'
+ : 'settings.authentication.github.synchronization_in_progress'
+ )}
+ </Alert>
+
+ <LastSyncAlert short={short} info={data.lastSync} />
</>
);
}
diff --git a/server/sonar-web/src/main/js/app/components/SystemAnnouncement.tsx b/server/sonar-web/src/main/js/app/components/SystemAnnouncement.tsx
index a35020a1aaf..e954c7769c6 100644
--- a/server/sonar-web/src/main/js/app/components/SystemAnnouncement.tsx
+++ b/server/sonar-web/src/main/js/app/components/SystemAnnouncement.tsx
@@ -17,16 +17,17 @@
* 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, throttle } from 'lodash';
+import classNames from 'classnames';
+import { keyBy, throttle } from 'lodash';
import * as React from 'react';
import { getValues } from '../../api/settings';
import { Alert } from '../../components/ui/Alert';
import { Feature } from '../../types/features';
import { GlobalSettingKeys, SettingValue } from '../../types/settings';
+import './SystemAnnouncement.css';
import withAvailableFeatures, {
WithAvailableFeaturesProps,
} from './available-features/withAvailableFeatures';
-import './SystemAnnouncement.css';
const THROTTLE_TIME_MS = 10000;
@@ -75,19 +76,18 @@ export class SystemAnnouncement extends React.PureComponent<WithAvailableFeature
render() {
const { displayMessage, message } = this.state;
- if (!displayMessage || isEmpty(message)) {
- return null;
- }
return (
- <div className="system-announcement-wrapper">
+ <div className={classNames({ 'system-announcement-wrapper': displayMessage && message })}>
<Alert
className="system-announcement-banner"
title={message}
display="banner"
variant="warning"
+ aria-live="assertive"
+ role="alert"
>
- {message}
+ {displayMessage && message}
</Alert>
</div>
);
diff --git a/server/sonar-web/src/main/js/app/components/__tests__/SystemAnnouncement-test.tsx b/server/sonar-web/src/main/js/app/components/__tests__/SystemAnnouncement-test.tsx
index 7bf9b99a359..686e7c50a7c 100644
--- a/server/sonar-web/src/main/js/app/components/__tests__/SystemAnnouncement-test.tsx
+++ b/server/sonar-web/src/main/js/app/components/__tests__/SystemAnnouncement-test.tsx
@@ -22,8 +22,8 @@ import * as React from 'react';
import { getValues } from '../../../api/settings';
import { renderComponent } from '../../../helpers/testReactTestingUtils';
import { Feature } from '../../../types/features';
-import { AvailableFeaturesContext } from '../available-features/AvailableFeaturesContext';
import SystemAnnouncement from '../SystemAnnouncement';
+import { AvailableFeaturesContext } from '../available-features/AvailableFeaturesContext';
jest.mock('../../../api/settings', () => ({
getValues: jest.fn(),
diff --git a/server/sonar-web/src/main/js/app/components/indexation/IndexationNotification.tsx b/server/sonar-web/src/main/js/app/components/indexation/IndexationNotification.tsx
index 4a41b5d0e0a..d1d96f6f081 100644
--- a/server/sonar-web/src/main/js/app/components/indexation/IndexationNotification.tsx
+++ b/server/sonar-web/src/main/js/app/components/indexation/IndexationNotification.tsx
@@ -97,10 +97,6 @@ export class IndexationNotification extends React.PureComponent<Props, State> {
},
} = this.props;
- if (notificationType === undefined) {
- return null;
- }
-
return (
<IndexationNotificationRenderer
type={notificationType}
diff --git a/server/sonar-web/src/main/js/app/components/indexation/IndexationNotificationRenderer.tsx b/server/sonar-web/src/main/js/app/components/indexation/IndexationNotificationRenderer.tsx
index 07d5839c7f5..defc97b7527 100644
--- a/server/sonar-web/src/main/js/app/components/indexation/IndexationNotificationRenderer.tsx
+++ b/server/sonar-web/src/main/js/app/components/indexation/IndexationNotificationRenderer.tsx
@@ -19,6 +19,7 @@
*/
/* eslint-disable react/no-unused-prop-types */
+import classNames from 'classnames';
import * as React from 'react';
import { FormattedMessage } from 'react-intl';
import Link from '../../../components/common/Link';
@@ -29,7 +30,7 @@ import { IndexationNotificationType } from '../../../types/indexation';
import { TaskStatuses, TaskTypes } from '../../../types/tasks';
export interface IndexationNotificationRendererProps {
- type: IndexationNotificationType;
+ type?: IndexationNotificationType;
percentCompleted: number;
isSystemAdmin: boolean;
}
@@ -45,20 +46,23 @@ export default function IndexationNotificationRenderer(props: IndexationNotifica
const { type } = props;
return (
- <div className="indexation-notification-wrapper">
+ <div className={classNames({ 'indexation-notification-wrapper': type })}>
<Alert
className="indexation-notification-banner"
display="banner"
- variant={NOTIFICATION_VARIANTS[type]}
+ variant={type ? NOTIFICATION_VARIANTS[type] : 'success'}
+ aria-live="assertive"
>
- <div className="display-flex-center">
- {type === IndexationNotificationType.Completed && renderCompletedBanner(props)}
- {type === IndexationNotificationType.CompletedWithFailure &&
- renderCompletedWithFailureBanner(props)}
- {type === IndexationNotificationType.InProgress && renderInProgressBanner(props)}
- {type === IndexationNotificationType.InProgressWithFailure &&
- renderInProgressWithFailureBanner(props)}
- </div>
+ {type !== undefined && (
+ <div className="display-flex-center">
+ {type === IndexationNotificationType.Completed && renderCompletedBanner(props)}
+ {type === IndexationNotificationType.CompletedWithFailure &&
+ renderCompletedWithFailureBanner(props)}
+ {type === IndexationNotificationType.InProgress && renderInProgressBanner(props)}
+ {type === IndexationNotificationType.InProgressWithFailure &&
+ renderInProgressWithFailureBanner(props)}
+ </div>
+ )}
</Alert>
</div>
);
diff --git a/server/sonar-web/src/main/js/app/components/indexation/__tests__/__snapshots__/IndexationNotificationRenderer-test.tsx.snap b/server/sonar-web/src/main/js/app/components/indexation/__tests__/__snapshots__/IndexationNotificationRenderer-test.tsx.snap
index ffa9743fd65..edcf985e28b 100644
--- a/server/sonar-web/src/main/js/app/components/indexation/__tests__/__snapshots__/IndexationNotificationRenderer-test.tsx.snap
+++ b/server/sonar-web/src/main/js/app/components/indexation/__tests__/__snapshots__/IndexationNotificationRenderer-test.tsx.snap
@@ -5,6 +5,7 @@ exports[`should render correctly for type="Completed" & isSystemAdmin=false 1`]
className="indexation-notification-wrapper"
>
<Alert
+ aria-live="assertive"
className="indexation-notification-banner"
display="banner"
variant="success"
@@ -27,6 +28,7 @@ exports[`should render correctly for type="Completed" & isSystemAdmin=true 1`] =
className="indexation-notification-wrapper"
>
<Alert
+ aria-live="assertive"
className="indexation-notification-banner"
display="banner"
variant="success"
@@ -49,6 +51,7 @@ exports[`should render correctly for type="CompletedWithFailure" & isSystemAdmin
className="indexation-notification-wrapper"
>
<Alert
+ aria-live="assertive"
className="indexation-notification-banner"
display="banner"
variant="error"
@@ -79,6 +82,7 @@ exports[`should render correctly for type="CompletedWithFailure" & isSystemAdmin
className="indexation-notification-wrapper"
>
<Alert
+ aria-live="assertive"
className="indexation-notification-banner"
display="banner"
variant="error"
@@ -118,6 +122,7 @@ exports[`should render correctly for type="InProgress" & isSystemAdmin=false 1`]
className="indexation-notification-wrapper"
>
<Alert
+ aria-live="assertive"
className="indexation-notification-banner"
display="banner"
variant="warning"
@@ -148,6 +153,7 @@ exports[`should render correctly for type="InProgress" & isSystemAdmin=true 1`]
className="indexation-notification-wrapper"
>
<Alert
+ aria-live="assertive"
className="indexation-notification-banner"
display="banner"
variant="warning"
@@ -200,6 +206,7 @@ exports[`should render correctly for type="InProgressWithFailure" & isSystemAdmi
className="indexation-notification-wrapper"
>
<Alert
+ aria-live="assertive"
className="indexation-notification-banner"
display="banner"
variant="error"
@@ -238,6 +245,7 @@ exports[`should render correctly for type="InProgressWithFailure" & isSystemAdmi
className="indexation-notification-wrapper"
>
<Alert
+ aria-live="assertive"
className="indexation-notification-banner"
display="banner"
variant="error"
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/notifications/ProjectNotifications.tsx b/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/notifications/ProjectNotifications.tsx
index 8e666804de8..b8d254a6dbc 100644
--- a/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/notifications/ProjectNotifications.tsx
+++ b/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/notifications/ProjectNotifications.tsx
@@ -69,7 +69,7 @@ export function ProjectNotifications(props: WithNotificationsProps & Props) {
{translate('project.info.notifications')}
</h3>
- <Alert className="spacer-top" variant="info" aria-live="off">
+ <Alert className="spacer-top" variant="info">
{translate('notification.dispatcher.information')}
</Alert>