Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug 1910409: Add externalized strings for i18n for notification drawer #7649

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,34 +1,42 @@
import * as React from 'react';
import { useTranslation } from 'react-i18next';

const NotificationDrawerHeading: React.FC<NotificationDrawerHeadingProps> = ({
count,
children,
onClose,
}) => (
<div className="pf-c-notification-drawer">
<div className="pf-c-notification-drawer__header">
<h1 className="pf-c-notification-drawer__header-title">Notifications</h1>
{count && (
<span className="pf-c-notification-drawer__header-status">{`${count} unread`}</span>
)}
<div className="pf-c-notification-drawer__header-action">
<div className="pf-c-notification-drawer__header-action-close">
<button
className="pf-c-button pf-m-plain"
type="button"
aria-label="Close"
onClick={onClose}
>
<i className="fas fa-times" aria-hidden="true"></i>
</button>
}) => {
const { t } = useTranslation();
return (
<div className="pf-c-notification-drawer">
<div className="pf-c-notification-drawer__header">
<h1 className="pf-c-notification-drawer__header-title">
{t('notification-drawer~Notifications')}
</h1>
{count && (
<span className="pf-c-notification-drawer__header-status">
{t('notification-drawer~{{count}} unread', { count })}
</span>
)}
<div className="pf-c-notification-drawer__header-action">
<div className="pf-c-notification-drawer__header-action-close">
<button
className="pf-c-button pf-m-plain"
type="button"
aria-label={t('notification-drawer~Close')}
onClick={onClose}
>
<i className="fas fa-times" aria-hidden="true"></i>
</button>
</div>
</div>
</div>
<div className="pf-c-notification-drawer__body">
<div className="pf-c-notification-drawer__group-list">{children}</div>
</div>
</div>
<div className="pf-c-notification-drawer__body">
<div className="pf-c-notification-drawer__group-list">{children}</div>
</div>
</div>
);
);
};

type NotificationDrawerHeadingProps = {
children: React.ReactNode;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as classNames from 'classnames';
import * as _ from 'lodash';
import * as React from 'react';
import { useTranslation } from 'react-i18next';
import { Link } from 'react-router-dom';
import {
BlueArrowCircleUpIcon,
Expand Down Expand Up @@ -59,43 +59,61 @@ const NotificationEntry: React.FC<NotificationEntryProps> = ({
targetPath,
toggleNotificationDrawer,
type,
}) => (
<li
className={classNames(`pf-c-notification-drawer__list-item pf-m-hoverable pf-m-${type}`, {
'pf-m-read': isRead,
})}
tabIndex={0}
onClick={
targetPath
? () => {
history.push(targetPath);
toggleNotificationDrawer();
}
: null
}) => {
const { t } = useTranslation();
const notificationTypeString = (notificationType: NotificationTypes): string => {
switch (notificationType) {
case NotificationTypes.warning:
return t('notification-drawer~Warning notification:');
case NotificationTypes.critical:
return t('notification-drawer~Critical notification:');
case NotificationTypes.success:
return t('notification-drawer~Success notification:');
case NotificationTypes.update:
return t('notification-drawer~Update notification:');
default:
return t('notification-drawer~Info notification:');
}
>
<div className="pf-c-notification-drawer__list-item-header">
<span className="pf-c-notification-drawer__list-item-header-icon">
<NotificationIcon type={type} />
</span>
<h4 className="pf-c-notification-drawer__list-item-header-title">
<span className="pf-screen-reader">{`${_.capitalize(type)} notification:`}</span>
{title}
</h4>
{actionText && actionPath && (
<NotificationAction
text={actionText}
path={actionPath}
onClick={toggleNotificationDrawer}
/>
)}
</div>
<div className="pf-c-notification-drawer__list-item-description">{description}</div>
<div className="pf-c-notification-drawer__list-item-timestamp">
{timestamp && <Timestamp simple timestamp={timestamp} />}
</div>
</li>
);
};

return (
<li
className={classNames(`pf-c-notification-drawer__list-item pf-m-hoverable pf-m-${type}`, {
'pf-m-read': isRead,
})}
tabIndex={0}
onClick={
targetPath
? () => {
history.push(targetPath);
toggleNotificationDrawer();
}
: null
}
>
<div className="pf-c-notification-drawer__list-item-header">
<span className="pf-c-notification-drawer__list-item-header-icon">
<NotificationIcon type={type} />
</span>
<h4 className="pf-c-notification-drawer__list-item-header-title">
<span className="pf-screen-reader">{notificationTypeString(type)}</span>
{title}
</h4>
{actionText && actionPath && (
<NotificationAction
text={actionText}
path={actionPath}
onClick={toggleNotificationDrawer}
/>
)}
</div>
<div className="pf-c-notification-drawer__list-item-description">{description}</div>
<div className="pf-c-notification-drawer__list-item-timestamp">
{timestamp && <Timestamp simple timestamp={timestamp} />}
</div>
</li>
);
};

export type NotificationEntryProps = {
actionText?: string;
Expand Down
100 changes: 59 additions & 41 deletions frontend/public/components/notification-drawer.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import * as _ from 'lodash';
import * as React from 'react';
import { useTranslation } from 'react-i18next';
import i18next from 'i18next';
import { connect } from 'react-redux';
import { Link } from 'react-router-dom';
import {
Expand Down Expand Up @@ -51,36 +53,43 @@ import { PrometheusEndpoint } from './graphs/helpers';
const criticalCompare = (a: Alert): boolean => getAlertSeverity(a) === 'critical';
const otherAlertCompare = (a: Alert): boolean => getAlertSeverity(a) !== 'critical';

const AlertErrorState: React.FC<AlertErrorProps> = ({ errorText }) => (
<EmptyState variant={EmptyStateVariant.full}>
<EmptyStateIcon className="co-status-card__alerts-icon" icon={RedExclamationCircleIcon} />
<Title headingLevel="h5" size="lg">
Alerts could not be loaded
</Title>
{errorText && <EmptyStateBody>{errorText}</EmptyStateBody>}
</EmptyState>
);
const AlertErrorState: React.FC<AlertErrorProps> = ({ errorText }) => {
const { t } = useTranslation();
return (
<EmptyState variant={EmptyStateVariant.full}>
<EmptyStateIcon className="co-status-card__alerts-icon" icon={RedExclamationCircleIcon} />
<Title headingLevel="h5" size="lg">
{t('notification-drawer~Alerts could not be loaded')}
</Title>
{errorText && <EmptyStateBody>{errorText}</EmptyStateBody>}
</EmptyState>
);
};

const AlertEmptyState: React.FC<AlertEmptyProps> = ({ drawerToggle }) => (
<EmptyState variant={EmptyStateVariant.full} className="co-status-card__alerts-msg">
<Title headingLevel="h5" size="lg">
No critical alerts
</Title>
<EmptyStateBody>
There are currently no critical alerts firing. There may be firing alerts of other severities
or silenced critical alerts however.
</EmptyStateBody>
<EmptyStateSecondaryActions>
<Link to="/monitoring/alerts" onClick={drawerToggle}>
View all alerts
</Link>
</EmptyStateSecondaryActions>
</EmptyState>
);
const AlertEmptyState: React.FC<AlertEmptyProps> = ({ drawerToggle }) => {
const { t } = useTranslation();
return (
<EmptyState variant={EmptyStateVariant.full} className="co-status-card__alerts-msg">
<Title headingLevel="h5" size="lg">
{t('notification-drawer~No critical alerts')}
</Title>
<EmptyStateBody>
{t(
'notification-drawer~There are currently no critical alerts firing. There may be firing alerts of other severities or silenced critical alerts however.',
)}
</EmptyStateBody>
<EmptyStateSecondaryActions>
<Link to="/monitoring/alerts" onClick={drawerToggle}>
{t('notification-drawer~View all alerts')}
</Link>
</EmptyStateSecondaryActions>
</EmptyState>
);
};

export const getAlertActions = (actionsExtensions: AlertAction[]) => {
const alertActions = new Map().set('AlertmanagerReceiversNotConfigured', {
text: 'Configure',
text: i18next.t('notification-drawer~Configure'),
path: '/monitoring/alertmanagerconfig',
});
actionsExtensions.forEach(({ properties }) =>
Expand Down Expand Up @@ -144,11 +153,11 @@ const getUpdateNotificationEntries = (
entries.push(
<NotificationEntry
actionPath="/settings/cluster?showVersions"
actionText="Update cluster"
actionText={i18next.t('notification-drawer~Update cluster')}
key="cluster-update"
description={updateData[0].version || 'Unknown'}
description={updateData[0].version || i18next.t('notification-drawer~Unknown')}
type={NotificationTypes.update}
title="Cluster update available"
title={i18next.t('notification-drawer~Cluster update available')}
toggleNotificationDrawer={toggleNotificationDrawer}
targetPath="/settings/cluster?showVersions"
/>,
Expand All @@ -158,14 +167,16 @@ const getUpdateNotificationEntries = (
entries.push(
<NotificationEntry
actionPath="/settings/cluster?showChannels"
actionText="Update channel"
actionText={i18next.t('notification-drawer~Update channel')}
key="channel-update"
description={`The ${newerChannel} channel is available. If you are
interested in updating this cluster to ${newerChannelVersion} in the
future, change the update channel to ${newerChannel} to receive recommended
updates.`}
description={i18next.t(
'notification-drawer~The {{newerChannel}} channel is available. If you are interested in updating this cluster to {{newerChannelVersion}} in the future, change the update channel to {{newerChannel}} to receive recommended updates.',
{ newerChannel, newerChannelVersion },
)}
type={NotificationTypes.update}
title={`${newerChannel} channel available`}
title={i18next.t('notification-drawer~{{newerChannel}} channel available', {
newerChannel,
})}
toggleNotificationDrawer={toggleNotificationDrawer}
targetPath="/settings/cluster?showChannels"
/>,
Expand Down Expand Up @@ -210,6 +221,7 @@ export const ConnectedNotificationDrawer_: React.FC<ConnectedNotificationDrawerP
alerts,
children,
}) => {
const { t } = useTranslation();
React.useEffect(() => {
const poll: NotificationPoll = (url, key: 'notificationAlerts' | 'silences', dataHandler) => {
store.dispatch(UIActions.monitoringLoading(key));
Expand All @@ -229,7 +241,10 @@ export const ConnectedNotificationDrawer_: React.FC<ConnectedNotificationDrawerP
poll(`${prometheusBaseURL}/${PrometheusEndpoint.RULES}`, 'notificationAlerts', getAlerts);
} else {
store.dispatch(
UIActions.monitoringErrored('notificationAlerts', new Error('prometheusBaseURL not set')),
UIActions.monitoringErrored(
'notificationAlerts',
new Error(t('notification-drawer~prometheusBaseURL not set')),
jcaianirh marked this conversation as resolved.
Show resolved Hide resolved
),
);
}

Expand All @@ -249,12 +264,15 @@ export const ConnectedNotificationDrawer_: React.FC<ConnectedNotificationDrawerP
});
} else {
store.dispatch(
UIActions.monitoringErrored('silences', new Error('alertManagerBaseURL not set')),
UIActions.monitoringErrored(
'silences',
new Error(t('notification-drawer~alertManagerBaseURL not set')),
),
);
}

return () => _.each(pollerTimeouts, clearTimeout);
}, []);
}, [t]);
const [clusterVersionData] = useK8sWatchResource<ClusterVersionKind>(cvResource);
const alertActionExtensions = useExtensions<AlertAction>(isAlertAction);

Expand Down Expand Up @@ -327,7 +345,7 @@ export const ConnectedNotificationDrawer_: React.FC<ConnectedNotificationDrawerP
<NotificationCategory
key="critical-alerts"
isExpanded={isAlertExpanded}
label="Critical Alerts"
label={t('notification-drawer~Critical Alerts')}
count={criticalAlertList.length}
onExpandContents={toggleAlertExpanded}
>
Expand All @@ -338,7 +356,7 @@ export const ConnectedNotificationDrawer_: React.FC<ConnectedNotificationDrawerP
<NotificationCategory
key="other-alerts"
isExpanded={isNonCriticalAlertExpanded}
label="Other Alerts"
label={t('notification-drawer~Other Alerts')}
count={otherAlertList.length}
onExpandContents={toggleNonCriticalAlertExpanded}
>
Expand All @@ -350,7 +368,7 @@ export const ConnectedNotificationDrawer_: React.FC<ConnectedNotificationDrawerP
<NotificationCategory
key="recommendations"
isExpanded={isClusterUpdateExpanded}
label="Recommendations"
label={t('notification-drawer~Recommendations')}
count={updateList.length}
onExpandContents={toggleClusterUpdateExpanded}
>
Expand Down
2 changes: 2 additions & 0 deletions frontend/public/i18n.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ i18n
'network-service',
'nodes',
'noobaa-storage-plugin',
'notification-drawer',
'oauth',
'olm',
'openid-idp-form',
'operator-hub-subscribe',
Expand Down
27 changes: 27 additions & 0 deletions frontend/public/locales/en/notification-drawer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"Alerts could not be loaded": "Alerts could not be loaded",
"No critical alerts": "No critical alerts",
"There are currently no critical alerts firing. There may be firing alerts of other severities or silenced critical alerts however.": "There are currently no critical alerts firing. There may be firing alerts of other severities or silenced critical alerts however.",
"View all alerts": "View all alerts",
"Configure": "Configure",
"Update cluster": "Update cluster",
"Unknown": "Unknown",
"Cluster update available": "Cluster update available",
"Update channel": "Update channel",
"The {{newerChannel}} channel is available. If you are interested in updating this cluster to {{newerChannelVersion}} in the future, change the update channel to {{newerChannel}} to receive recommended updates.": "The {{newerChannel}} channel is available. If you are interested in updating this cluster to {{newerChannelVersion}} in the future, change the update channel to {{newerChannel}} to receive recommended updates.",
"{{newerChannel}} channel available": "{{newerChannel}} channel available",
"prometheusBaseURL not set": "prometheusBaseURL not set",
"alertManagerBaseURL not set": "alertManagerBaseURL not set",
"Critical Alerts": "Critical Alerts",
"Other Alerts": "Other Alerts",
"Recommendations": "Recommendations",
"Notifications": "Notifications",
"{{count}} unread": "{{count}} unread",
"{{count}} unread_plural": "{{count}} unreads",
"Close": "Close",
"Warning notification:": "Warning notification:",
"Critical notification:": "Critical notification:",
"Success notification:": "Success notification:",
"Update notification:": "Update notification:",
"Info notification:": "Info notification:"
}