Skip to content

Commit

Permalink
Merge pull request #7266 from kyoto/query-browser-i18n
Browse files Browse the repository at this point in the history
CONSOLE-2391: Monitoring: Add i18n for Metrics and Dashboards pages
  • Loading branch information
openshift-merge-robot committed Dec 7, 2020
2 parents 02df32e + 24c2b0d commit 5718965
Show file tree
Hide file tree
Showing 4 changed files with 160 additions and 71 deletions.
71 changes: 44 additions & 27 deletions frontend/public/components/monitoring/dashboards/index.tsx
Expand Up @@ -2,6 +2,7 @@ import * as _ from 'lodash-es';
import { Dropdown, DropdownToggle, DropdownItem } from '@patternfly/react-core';
import * as React from 'react';
import { Helmet } from 'react-helmet';
import { useTranslation } from 'react-i18next';
import { connect } from 'react-redux';
import { Map as ImmutableMap } from 'immutable';

Expand Down Expand Up @@ -70,6 +71,8 @@ const VariableDropdown: React.FC<VariableDropdownProps> = ({
onChange,
selectedKey,
}) => {
const { t } = useTranslation();

const [isOpen, toggleIsOpen, , setClosed] = useBoolean(false);

return (
Expand All @@ -79,7 +82,7 @@ const VariableDropdown: React.FC<VariableDropdownProps> = ({
<Dropdown
toggle={
<DropdownToggle className="monitoring-dashboards__dropdown-button" isDisabled={true}>
<RedExclamationCircleIcon /> Error loading options
<RedExclamationCircleIcon /> {t('monitoring~Error loading options')}
</DropdownToggle>
}
/>
Expand Down Expand Up @@ -201,29 +204,31 @@ const AllVariableDropdowns = connect(({ UI }: RootState) => ({
variables: UI.getIn(['monitoringDashboards', 'variables']),
}))(AllVariableDropdowns_);

const timespanOptions = {
'5m': '5 minutes',
'15m': '15 minutes',
'30m': '30 minutes',
'1h': '1 hour',
'2h': '2 hours',
'6h': '6 hours',
'12h': '12 hours',
'1d': '1 day',
'2d': '2 days',
'1w': '1 week',
'2w': '2 weeks',
};

const TimespanDropdown_: React.FC<TimespanDropdownProps> = ({ timespan, setTimespan }) => {
const { t } = useTranslation();

const onChange = React.useCallback((v: string) => setTimespan(parsePrometheusDuration(v)), [
setTimespan,
]);

const timespanOptions = {
'5m': t('monitoring~{{count}} minute', { count: 5 }),
'15m': t('monitoring~{{count}} minute', { count: 15 }),
'30m': t('monitoring~{{count}} minute', { count: 30 }),
'1h': t('monitoring~{{count}} hour', { count: 1 }),
'2h': t('monitoring~{{count}} hour', { count: 2 }),
'6h': t('monitoring~{{count}} hour', { count: 6 }),
'12h': t('monitoring~{{count}} hour', { count: 12 }),
'1d': t('monitoring~{{count}} day', { count: 1 }),
'2d': t('monitoring~{{count}} day', { count: 2 }),
'1w': t('monitoring~{{count}} week', { count: 1 }),
'2w': t('monitoring~{{count}} week', { count: 2 }),
};

return (
<VariableDropdown
items={timespanOptions}
label="Time Range"
label={t('monitoring~Time range')}
onChange={onChange}
selectedKey={formatPrometheusDuration(timespan)}
/>
Expand All @@ -239,12 +244,18 @@ export const TimespanDropdown = connect(
},
)(TimespanDropdown_);

const PollIntervalDropdown_ = ({ interval, setInterval }) => (
<div className="form-group monitoring-dashboards__dropdown-wrap">
<label className="monitoring-dashboards__dropdown-title">Refresh Interval</label>
<IntervalDropdown interval={interval} setInterval={setInterval} />
</div>
);
const PollIntervalDropdown_ = ({ interval, setInterval }) => {
const { t } = useTranslation();

return (
<div className="form-group monitoring-dashboards__dropdown-wrap">
<label className="monitoring-dashboards__dropdown-title">
{t('monitoring~Refresh interval')}
</label>
<IntervalDropdown interval={interval} setInterval={setInterval} />
</div>
);
};

export const PollIntervalDropdown = connect(
({ UI }: RootState) => ({
Expand Down Expand Up @@ -405,6 +416,8 @@ const MonitoringDashboardsPage_: React.FC<MonitoringDashboardsPageProps> = ({
match,
patchAllVariables,
}) => {
const { t } = useTranslation();

const [board, setBoard] = React.useState<string>();
const [boards, setBoards] = React.useState<Board[]>([]);
const [error, setError] = React.useState<string>();
Expand All @@ -428,7 +441,11 @@ const MonitoringDashboardsPage_: React.FC<MonitoringDashboardsPageProps> = ({
name: item.metadata.name,
};
} catch (e) {
setError(`Could not parse JSON data for dashboard "${item.metadata.name}"`);
setError(
t('monitoring~Could not parse JSON data for dashboard "{{dashboard}}"', {
dashboard: item.metadata.name,
}),
);
}
};

Expand All @@ -443,7 +460,7 @@ const MonitoringDashboardsPage_: React.FC<MonitoringDashboardsPageProps> = ({
setError(_.get(err, 'json.error', err.message));
}
});
}, [safeFetch, setLoaded]);
}, [safeFetch, setLoaded, t]);

const boardItems = React.useMemo(() => _.mapValues(_.mapKeys(boards, 'name'), 'data.title'), [
boards,
Expand Down Expand Up @@ -492,13 +509,13 @@ const MonitoringDashboardsPage_: React.FC<MonitoringDashboardsPageProps> = ({
return (
<>
<Helmet>
<title>Metrics Dashboards</title>
<title>{t('monitoring~Metrics dashboards')}</title>
</Helmet>
<div className="co-m-nav-title co-m-nav-title--detail">
<div className="monitoring-dashboards__header">
<h1 className="co-m-pane__heading">
<span>
Dashboards <GrafanaLink />
{t('monitoring~Dashboards')} <GrafanaLink />
</span>
</h1>
<div className="monitoring-dashboards__options">
Expand All @@ -510,7 +527,7 @@ const MonitoringDashboardsPage_: React.FC<MonitoringDashboardsPageProps> = ({
{!_.isEmpty(boardItems) && (
<VariableDropdown
items={boardItems}
label="Dashboard"
label={t('monitoring~Dashboard')}
onChange={changeBoard}
selectedKey={board}
/>
Expand Down
97 changes: 65 additions & 32 deletions frontend/public/components/monitoring/metrics.tsx
Expand Up @@ -149,18 +149,22 @@ const MetricsActionsMenu_: React.FC<MetricsActionsMenuProps> = ({
isAllExpanded,
setAllExpanded,
}) => {
const { t } = useTranslation();

const doDelete = () => {
deleteAll();
focusedQuery = undefined;
};

const actionsMenuActions = [
{ label: 'Add query', callback: addQuery },
{ label: t('monitoring~Add query'), callback: addQuery },
{
label: `${isAllExpanded ? 'Collapse' : 'Expand'} all query tables`,
label: isAllExpanded
? t('monitoring~Collapse all query tables')
: t('monitoring~Expand all query tables'),
callback: () => setAllExpanded(!isAllExpanded),
},
{ label: 'Delete all queries', callback: doDelete },
{ label: t('monitoring~Delete all queries'), callback: doDelete },
];

return (
Expand Down Expand Up @@ -208,6 +212,7 @@ const graphStateToProps = ({ UI }: RootState) => ({

const ToggleGraph_ = ({ hideGraphs, toggle }) => {
const { t } = useTranslation();

const icon = hideGraphs ? <ChartLineIcon /> : <CompressIcon />;

return (
Expand All @@ -226,6 +231,8 @@ export const ToggleGraph = connect(graphStateToProps, { toggle: UIActions.monito
);

const MetricsDropdown_: React.FC<MetricsDropdownProps> = ({ insertText, setMetrics }) => {
const { t } = useTranslation();

const [items, setItems] = React.useState<MetricsDropdownItems>();
const [error, setError] = React.useState<PrometheusAPIError>();

Expand Down Expand Up @@ -258,7 +265,7 @@ const MetricsDropdown_: React.FC<MetricsDropdownProps> = ({ insertText, setMetri
}
};

let title: React.ReactNode = 'Insert Metric at Cursor';
let title: React.ReactNode = t('monitoring~Insert metric at cursor');
if (error !== undefined) {
const message =
error?.response?.status === 403 ? 'Access restricted.' : 'Failed to load metrics list.';
Expand Down Expand Up @@ -396,6 +403,8 @@ const QueryInput_: React.FC<QueryInputProps> = ({
runQueries,
text = '',
}) => {
const { t } = useTranslation();

const [token, setToken] = React.useState('');

const inputRef = React.useRef(null);
Expand Down Expand Up @@ -487,24 +496,26 @@ const QueryInput_: React.FC<QueryInputProps> = ({
// Set the default textarea height to the number of lines in the query text
const rows = _.clamp((text.match(/\n/g) || []).length + 1, 2, 10);

const placeholder = t('monitoring~Expression (press Shift+Enter for newlines)');

return (
<div className="query-browser__query pf-c-dropdown">
<textarea
aria-label="Expression (press Shift+Enter for newlines)"
aria-label={placeholder}
autoFocus
className="pf-c-form-control query-browser__query-input"
onBlur={onBlur}
onChange={onChange}
onKeyDown={onKeyDown}
placeholder="Expression (press Shift+Enter for newlines)"
placeholder={placeholder}
ref={inputRef}
rows={rows}
spellCheck={false}
value={text}
/>
<Button
className="query-browser__clear-icon"
aria-label="Clear Query"
aria-label={t('monitoring~Clear query')}
onClick={onClear}
type="button"
variant="plain"
Expand Down Expand Up @@ -552,6 +563,8 @@ const QueryKebab_: React.FC<QueryKebabProps> = ({
series,
toggleIsEnabled,
}) => {
const { t } = useTranslation();

const toggleAllSeries = () => patchQuery({ disabledSeries: isDisabledSeriesEmpty ? series : [] });

const doDelete = () => {
Expand All @@ -562,12 +575,17 @@ const QueryKebab_: React.FC<QueryKebabProps> = ({
return (
<Kebab
options={[
{ label: `${isEnabled ? 'Disable' : 'Enable'} query`, callback: toggleIsEnabled },
{
label: `${isDisabledSeriesEmpty ? 'Hide' : 'Show'} all series`,
label: isEnabled ? t('monitoring~Disable query') : t('monitoring~Enable query'),
callback: toggleIsEnabled,
},
{
label: isDisabledSeriesEmpty
? t('monitoring~Hide all series')
: t('monitoring~Show all series'),
callback: toggleAllSeries,
},
{ label: 'Delete query', callback: doDelete },
{ label: t('monitoring~Delete query'), callback: doDelete },
]}
/>
);
Expand Down Expand Up @@ -633,13 +651,14 @@ const QueryTable_: React.FC<QueryTableProps> = ({
query,
series,
}) => {
const { t } = useTranslation();

const [data, setData] = React.useState<PrometheusData>();
const [error, setError] = React.useState<PrometheusAPIError>();
const [page, setPage] = React.useState(1);
const [perPage, setPerPage] = React.useState(50);
const [sortBy, setSortBy] = React.useState<ISortBy>();

const { t } = useTranslation();
const safeFetch = React.useCallback(useSafeFetch(), []);

const tick = () => {
Expand Down Expand Up @@ -809,8 +828,10 @@ const Query_: React.FC<QueryProps> = ({
patchQuery,
toggleIsEnabled,
}) => {
const { t } = useTranslation();

const switchKey = `${id}-${isEnabled}`;
const switchLabel = `${isEnabled ? 'Disable' : 'Enable'} query`;
const switchLabel = isEnabled ? t('monitoring~Disable query') : t('monitoring~Enable query');

const toggleIsExpanded = () => patchQuery({ isExpanded: !isExpanded });

Expand Down Expand Up @@ -850,6 +871,8 @@ const Query = connect(
)(Query_);

const QueryBrowserWrapper_: React.FC<QueryBrowserWrapperProps> = ({ patchQuery, queriesList }) => {
const { t } = useTranslation();

const queries = queriesList.toJS();

// Initialize queries from URL parameters
Expand Down Expand Up @@ -893,13 +916,13 @@ const QueryBrowserWrapper_: React.FC<QueryBrowserWrapperProps> = ({ patchQuery,
<EmptyState variant={EmptyStateVariant.full}>
<EmptyStateIcon icon={ChartLineIcon} />
<Title headingLevel="h2" size="md">
No Query Entered
{t('monitoring~No query entered')}
</Title>
<EmptyStateBody>
Enter a query in the box below to explore metrics for this cluster.
{t('monitoring~Enter a query in the box below to explore metrics for this cluster.')}
</EmptyStateBody>
<Button onClick={insertExampleQuery} variant="primary">
Insert Example Query
{t('monitoring~Insert example query')}
</Button>
</EmptyState>
</div>
Expand All @@ -916,23 +939,31 @@ const QueryBrowserWrapper = connect(
{ patchQuery: UIActions.queryBrowserPatchQuery },
)(QueryBrowserWrapper_);

const AddQueryButton_ = ({ addQuery }) => (
<Button
className="query-browser__inline-control"
onClick={addQuery}
type="button"
variant="secondary"
>
Add Query
</Button>
);
const AddQueryButton_ = ({ addQuery }) => {
const { t } = useTranslation();

return (
<Button
className="query-browser__inline-control"
onClick={addQuery}
type="button"
variant="secondary"
>
{t('monitoring~Add query')}
</Button>
);
};
const AddQueryButton = connect(null, { addQuery: UIActions.queryBrowserAddQuery })(AddQueryButton_);

const RunQueriesButton_ = ({ runQueries }) => (
<Button onClick={runQueries} type="submit" variant="primary">
Run Queries
</Button>
);
const RunQueriesButton_ = ({ runQueries }) => {
const { t } = useTranslation();

return (
<Button onClick={runQueries} type="submit" variant="primary">
{t('monitoring~Run queries')}
</Button>
);
};
const RunQueriesButton = connect(null, { runQueries: UIActions.queryBrowserRunQueries })(
RunQueriesButton_,
);
Expand All @@ -958,18 +989,20 @@ const PollIntervalDropdown = connect(
)(IntervalDropdown);

const QueryBrowserPage_: React.FC<QueryBrowserPageProps> = ({ deleteAll }) => {
const { t } = useTranslation();

// Clear queries on unmount
React.useEffect(() => deleteAll, [deleteAll]);

return (
<>
<Helmet>
<title>Metrics</title>
<title>{t('monitoring~Metrics')}</title>
</Helmet>
<div className="co-m-nav-title">
<h1 className="co-m-pane__heading">
<span>
Metrics
{t('monitoring~Metrics')}
<HeaderPrometheusLink />
</span>
<div className="co-actions">
Expand Down

0 comments on commit 5718965

Please sign in to comment.