Skip to content

Commit

Permalink
i18n ocs dashboards
Browse files Browse the repository at this point in the history
 - independent mode dashboard
 - internal mode dashboard
 - object service dashboard

Additional modifications:
- dropdown options format to be {name: /*the string to be displayed and used for i18n*/,id: /*a unique name of the option-key*/} on all ocs dashboards
- unit test adjustments
- i18n of empty states in core components of details-card,inventory-card,graph-empty

Namespaces added: ceph-storage-plugin, noobaa-storage-pugin

Signed-off-by: Afreen Rahman <afrahman@redhat.com>
  • Loading branch information
Afreen Rahman committed Dec 1, 2020
1 parent b94adb6 commit 387cea6
Show file tree
Hide file tree
Showing 59 changed files with 816 additions and 443 deletions.
8 changes: 8 additions & 0 deletions frontend/__tests__/components/graphs/area.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ import {

const MOCK_DATA = [[{ x: 1, y: 100 }]];

jest.mock('react-i18next', () => {
const reactI18next = require.requireActual('react-i18next');
return {
...reactI18next,
useTranslation: () => ({ t: (key) => key }),
};
});

describe('<AreaChart />', () => {
it('should render an area chart', () => {
const wrapper = shallow(<AreaChart title="Test Area" data={MOCK_DATA} />);
Expand Down
8 changes: 8 additions & 0 deletions frontend/__tests__/components/graphs/bar.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ import {

const MOCK_DATA = [{ x: 1, y: 100 }];

jest.mock('react-i18next', () => {
const reactI18next = require.requireActual('react-i18next');
return {
...reactI18next,
useTranslation: () => ({ t: (key) => key }),
};
});

describe('<BarChart />', () => {
it('should render a bar chart', () => {
const wrapper = shallow(<BarChart title="Test Bar" data={MOCK_DATA} />);
Expand Down
12 changes: 11 additions & 1 deletion frontend/__tests__/components/graphs/graph-empty.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@ import { shallow } from 'enzyme';

import { GraphEmpty } from '@console/internal/components/graphs/graph-empty';

jest.mock('react-i18next', () => {
const reactI18next = require.requireActual('react-i18next');
return {
...reactI18next,
useTranslation: () => ({ t: (key) => key }),
};
});

const i18ns = 'monitoring';

describe('<GraphEmpty />', () => {
it('should render a loading state', () => {
const wrapper = shallow(<GraphEmpty loading />);
Expand All @@ -12,6 +22,6 @@ describe('<GraphEmpty />', () => {
it('should render an empty state', () => {
const wrapper = shallow(<GraphEmpty />);
expect(wrapper.find('.text-secondary').exists()).toBe(true);
expect(wrapper.text()).toEqual('No datapoints found.');
expect(wrapper.text()).toEqual(`${i18ns}~No datapoints found.`);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"Activity": "Activity",
"Expanding OCS Cluster": "Expanding OCS Cluster",
"Rebuilding data resiliency": "Rebuilding data resiliency",
"{{formattedProgress, number}}%": "{{formattedProgress, number}}%",
"Upgrading OCS Operator": "Upgrading OCS Operator",
"Not enough usage data": "Not enough usage data",
"used": "used",
"available": "available",
"Other": "Other",
"All other capacity usage that are not a part of the top 5 consumers.": "All other capacity usage that are not a part of the top 5 consumers.",
"Available": "Available",
"Projects": "Projects",
"Storage Classes": "Storage Classes",
"Pods": "Pods",
"Capacity breakdown": "Capacity breakdown",
"{{metricType}}": "{{metricType}}",
"Break By Dropdown": "Break By Dropdown",
"Details": "Details",
"Service Name": "Service Name",
"Cluster Name": "Cluster Name",
"Provider": "Provider",
"Mode": "Mode",
"Version": "Version",
"Inventory": "Inventory",
"Status": "Status",
"OCS Cluster": "OCS Cluster",
"Data Resiliency": "Data Resiliency",
"Warning": "Warning",
"Error": "Error",
"Progressing": "Progressing",
"{{capacityRatio, number}}:1": "{{capacityRatio, number}}:1",
"Compression ratio": "Compression ratio",
" The ratio of the data physical stored (after compression) compared to the size of the data received from the client.": " The ratio of the data physical stored (after compression) compared to the size of the data received from the client.",
"Savings": "Savings",
"The amount of physical storage saved after applying compression.": "The amount of physical storage saved after applying compression.",
"Storage Efficiency": "Storage Efficiency",
"Used Capacity": "Used Capacity",
"Utilization": "Utilization",
"IOPS": "IOPS",
"Latency": "Latency",
"Throughput": "Throughput",
"Recovery": "Recovery",
"Requested capacity": "Requested capacity",
"Persistent Storage": "Persistent Storage",
"Storage": "Storage",
"Troubleshoot": "Troubleshoot"
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@ import { BreakdownChartLoading } from '../components/dashboard-page/storage-dash

const top5MetricsStats = getStackChartStats(breakdownData.top5, breakdownData.humanize);

jest.mock('react-i18next', () => {
const reactI18next = require.requireActual('react-i18next');
return {
...reactI18next,
useTranslation: () => ({ t: (key) => key }),
};
});

const i18ns = 'ceph-storage-plugin';

describe('<BreakdownCardBody>', () => {
let wrapper: ShallowWrapper<BreakdownBodyProps>;
beforeEach(() => {
Expand Down Expand Up @@ -68,7 +78,7 @@ describe('<BreakdownCardBody>', () => {

it('Shows usage data warning', () => {
wrapper.setProps({ capacityUsed: '0' });
expect(wrapper.text()).toBe('Not enough usage data');
expect(wrapper.text()).toBe(`${i18ns}~Not enough usage data`);
});

it('Shows loading state', () => {
Expand All @@ -78,6 +88,6 @@ describe('<BreakdownCardBody>', () => {

it('Shows not available', () => {
wrapper.setProps({ capacityUsed: null, top5MetricsStats: [], hasLoadError: true });
expect(wrapper.text()).toBe('Not available');
expect(wrapper.text()).toBe(`dashboard~Not available`);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,22 @@ import { Link } from 'react-router-dom';
import { Chart, ChartBar } from '@patternfly/react-charts';
import { Tooltip } from '@patternfly/react-core';

jest.mock('react-i18next', () => {
const reactI18next = require.requireActual('react-i18next');
return {
...reactI18next,
useTranslation: () => ({ t: (key) => key }),
};
});

const stackData = getStackChartStats(breakdownData.top5, breakdownData.humanize);

const chartData = addAvailable(
stackData,
breakdownData.capacityAvailable,
breakdownData.metricTotal,
breakdownData.humanize,
(key) => key,
);

const legends = getLegends(chartData);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,44 @@
import * as React from 'react';
import { ShallowWrapper, shallow } from 'enzyme';

import { Select } from '@patternfly/react-core';
import { DashboardItemProps } from '@console/internal/components/dashboard/with-dashboard-resources';
import DashboardCardHeader from '@console/shared/src/components/dashboard/dashboard-card/DashboardCardHeader';
import DashboardCardBody from '@console/shared/src/components/dashboard/dashboard-card/DashboardCardBody';
import DashboardCardTitle from '@console/shared/src/components/dashboard/dashboard-card/DashboardCardTitle';
import { Select } from '@patternfly/react-core';
import { PROJECTS, STORAGE_CLASSES, PODS } from '../constants';
import { BreakdownCard } from '../components/independent-dashboard-page/breakdown-card';
import { dashboardData } from '../__mocks__/independent-mode-dashboard-data';
import { BreakdownCardBody } from '../components/dashboard-page/storage-dashboard/breakdown-card/breakdown-body';
import { getSelectOptions } from '../components/dashboard-page/storage-dashboard/breakdown-card/breakdown-dropdown';
import { breakdownIndependentQueryMap } from '../constants/queries';

jest.mock('react-i18next', () => {
const reactI18next = require.requireActual('react-i18next');
return {
...reactI18next,
useTranslation: () => ({ t: (key) => key }),
};
});

const i18ns = 'ceph-storage-plugin';

describe('BreakdownCard', () => {
let wrapper: ShallowWrapper<DashboardItemProps>;
const keys = Object.keys(breakdownIndependentQueryMap);
const breakdownSelectItems = getSelectOptions(keys);
const dropdownOptions = [
{
name: `${i18ns}~${PROJECTS}`,
id: PROJECTS,
},
{
name: `${i18ns}~${STORAGE_CLASSES}`,
id: STORAGE_CLASSES,
},
{
name: `${i18ns}~${PODS}`,
id: PODS,
},
];

const breakdownSelectItems = getSelectOptions(dropdownOptions);
beforeEach(() => {
wrapper = shallow(
<BreakdownCard
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ import DashboardCardTitle from '@console/shared/src/components/dashboard/dashboa
import { DetailsCard } from '../components/independent-dashboard-page/details-card';
import { dashboardData } from '../__mocks__/independent-mode-dashboard-data';

jest.mock('react-i18next', () => {
const reactI18next = require.requireActual('react-i18next');
return {
...reactI18next,
useTranslation: () => ({ t: (key) => key }),
};
});

describe('DetailsCard', () => {
let wrapper: ShallowWrapper<DashboardItemProps>;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as React from 'react';
import { useTranslation } from 'react-i18next';
import * as _ from 'lodash';
import DashboardCard from '@console/shared/src/components/dashboard/dashboard-card/DashboardCard';
import DashboardCardBody from '@console/shared/src/components/dashboard/dashboard-card/DashboardCardBody';
Expand Down Expand Up @@ -143,16 +144,20 @@ const OngoingActivity = withDashboardResources(
},
);

export const ActivityCard: React.FC = React.memo(() => (
<DashboardCard gradient>
<DashboardCardHeader>
<DashboardCardTitle>Activity</DashboardCardTitle>
</DashboardCardHeader>
<DashboardCardBody>
<ActivityBody className="ceph-activity-card__body">
<OngoingActivity />
<RecentEvent />
</ActivityBody>
</DashboardCardBody>
</DashboardCard>
));
export const ActivityCard: React.FC = React.memo(() => {
const { t } = useTranslation();

return (
<DashboardCard gradient>
<DashboardCardHeader>
<DashboardCardTitle>{t('ceph-storage-plugin~Activity')}</DashboardCardTitle>
</DashboardCardHeader>
<DashboardCardBody>
<ActivityBody className="ceph-activity-card__body">
<OngoingActivity />
<RecentEvent />
</ActivityBody>
</DashboardCardBody>
</DashboardCard>
);
});
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import * as React from 'react';
import { useTranslation } from 'react-i18next';
import ActivityItem from '@console/shared/src/components/dashboard/activity-card/ActivityItem';
import { K8sResourceKind } from '@console/internal/module/k8s';

export const ClusterExpandActivity: React.FC = () => (
<ActivityItem>Expanding OCS Cluster</ActivityItem>
);
export const ClusterExpandActivity: React.FC = () => {
const { t } = useTranslation();

return <ActivityItem>{t('ceph-storage-plugin~Expanding OCS Cluster')}</ActivityItem>;
};

export const isClusterExpandActivity = (storageCluster: K8sResourceKind): boolean =>
storageCluster?.status?.phase === 'Expanding';
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import * as React from 'react';
import { useTranslation } from 'react-i18next';
import { Progress, ProgressSize } from '@patternfly/react-core';
import { PrometheusResponse } from '@console/internal/components/graphs';
import { getResiliencyProgress } from '../../../../utils';

export const DataResiliency: React.FC<DataResiliencyProps> = ({ results }) => {
const { t } = useTranslation();

const progress: number = getResiliencyProgress(results);
const formattedProgress = Math.round(progress * 100);
return (
Expand All @@ -12,8 +15,8 @@ export const DataResiliency: React.FC<DataResiliencyProps> = ({ results }) => {
className="co-activity-item__progress"
value={formattedProgress}
size={ProgressSize.sm}
title="Rebuilding data resiliency"
label={`${formattedProgress}%`}
title={t('ceph-storage-plugin~Rebuilding data resiliency')}
label={t('ceph-storage-plugin~{{formattedProgress, number}}%', { formattedProgress })}
/>
</>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import * as React from 'react';
import { useTranslation } from 'react-i18next';
import ActivityItem from '@console/shared/src/components/dashboard/activity-card/ActivityItem';
import { SubscriptionState, SubscriptionKind } from '@console/operator-lifecycle-manager';
import { getSubscriptionStatus } from '@console/operator-lifecycle-manager/src/status/csv-status';

export const isOCSUpgradeActivity = (subscription: SubscriptionKind): boolean =>
getSubscriptionStatus(subscription).status === SubscriptionState.SubscriptionStateUpgradePending;

export const OCSUpgradeActivity: React.FC = () => (
<ActivityItem>Upgrading OCS Operator</ActivityItem>
);
export const OCSUpgradeActivity: React.FC = () => {
const { t } = useTranslation();

return <ActivityItem>{t('ceph-storage-plugin~Upgrading OCS Operator')}</ActivityItem>;
};
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as React from 'react';
import { useTranslation } from 'react-i18next';
import { Grid, GridItem } from '@patternfly/react-core';
import { Humanize } from '@console/internal/components/utils';
import { K8sKind } from '@console/internal/module/k8s';
Expand All @@ -19,20 +20,19 @@ export const BreakdownCardBody: React.FC<BreakdownBodyProps> = ({
ocsVersion = '',
labelPadding,
}) => {
const { t } = useTranslation();

if (isLoading && !hasLoadError) {
return <BreakdownChartLoading />;
}
if (!capacityUsed || !top5MetricsStats.length || hasLoadError) {
return <div className="text-secondary">Not available</div>;
return <div className="text-secondary">{t('dashboard~Not available')}</div>;
}
if (capacityUsed === '0') {
return <div className="text-secondary">Not enough usage data</div>;
return <div className="text-secondary">{t('ceph-storage-plugin~Not enough usage data')}</div>;
}

const usedCapacity = `${humanize(capacityUsed).string} used`;
const availableCapacity = `${humanize(capacityAvailable).string} available`;

const chartData = addAvailable(top5MetricsStats, capacityAvailable, metricTotal, humanize);
const chartData = addAvailable(top5MetricsStats, capacityAvailable, metricTotal, humanize, t);

const legends = getLegends(chartData);

Expand All @@ -44,13 +44,17 @@ export const BreakdownCardBody: React.FC<BreakdownBodyProps> = ({
return (
<Grid>
<GridItem span={4}>
<TotalCapacityBody value={usedCapacity} />
<TotalCapacityBody
capacity={humanize(capacityUsed).string}
suffix={t('ceph-storage-plugin~used')}
/>
</GridItem>
<GridItem span={4} />
<GridItem span={4}>
{capacityAvailable && (
<TotalCapacityBody
value={availableCapacity}
capacity={humanize(capacityAvailable).string}
suffix={t('ceph-storage-plugin~available')}
className="capacity-breakdown-card__available-body text-secondary"
/>
)}
Expand Down

0 comments on commit 387cea6

Please sign in to comment.