Pluralized modal titles and empty state strings

All itemNames used in empty state messages, and delete modal titles
need to be plural and capitalized.  Because of this change we no
longer need the ucFirst() in utils/strings.js.
This commit is contained in:
Alex Corey 2019-09-19 13:41:13 -04:00
parent 8dd4379bf2
commit b3b53a8ce4
16 changed files with 33 additions and 52 deletions

View File

@ -212,7 +212,6 @@ class AddResourceRole extends React.Component {
selectedLabel={i18n._(t`Selected`)}
selectedResourceRows={selectedResourceRows}
sortedColumnKey="username"
itemName="user"
/>
)}
{selectedResource === 'teams' && (
@ -222,7 +221,6 @@ class AddResourceRole extends React.Component {
onSearch={readTeams}
selectedLabel={i18n._(t`Selected`)}
selectedResourceRows={selectedResourceRows}
itemName="team"
/>
)}
</Fragment>

View File

@ -74,7 +74,6 @@ class SelectResourceStep extends React.Component {
onRowClick,
selectedLabel,
selectedResourceRows,
itemName,
i18n,
} = this.props;
@ -100,7 +99,6 @@ class SelectResourceStep extends React.Component {
<PaginatedDataList
items={resources}
itemCount={count}
itemName={itemName}
qsConfig={this.qsConfig}
toolbarColumns={columns}
renderItem={item => (
@ -132,7 +130,6 @@ SelectResourceStep.propTypes = {
selectedLabel: PropTypes.string,
selectedResourceRows: PropTypes.arrayOf(PropTypes.object),
sortedColumnKey: PropTypes.string,
itemName: PropTypes.string,
};
SelectResourceStep.defaultProps = {
@ -141,7 +138,6 @@ SelectResourceStep.defaultProps = {
selectedLabel: null,
selectedResourceRows: [],
sortedColumnKey: 'name',
itemName: 'item',
};
export { SelectResourceStep as _SelectResourceStep };

View File

@ -212,7 +212,7 @@ class Lookup extends React.Component {
i18n,
} = this.props;
const header = lookupHeader || i18n._(t`items`);
const header = lookupHeader || i18n._(t`Items`);
const canDelete = !required || (multiple && value.length > 1);
const chips = value ? (
@ -268,7 +268,7 @@ class Lookup extends React.Component {
<PaginatedDataList
items={results}
itemCount={count}
itemName={lookupHeader}
pluralizedItemName={lookupHeader}
qsConfig={this.qsConfig}
toolbarColumns={columns}
renderItem={item => (

View File

@ -17,7 +17,6 @@ import {
parseQueryString,
addParams,
} from '@util/qs';
import { ucFirst } from '@util/strings';
import { QSConfig } from '@types';
@ -63,7 +62,7 @@ class PaginatedDataList extends React.Component {
qsConfig,
renderItem,
toolbarColumns,
itemName,
pluralizedItemName,
showPageSizeOptions,
location,
i18n,
@ -81,11 +80,11 @@ class PaginatedDataList extends React.Component {
];
const queryParams = parseQueryString(qsConfig, location.search);
const dataListLabel = i18n._(t`${itemName} List`);
const dataListLabel = i18n._(t`${pluralizedItemName} List`);
const emptyContentMessage = i18n._(
t`Please add ${itemName} to populate this list `
t`Please add ${pluralizedItemName} to populate this list `
);
const emptyContentTitle = i18n._(t`No ${itemName} Found `);
const emptyContentTitle = i18n._(t`No ${pluralizedItemName} Found `);
let Content;
if (hasContentLoading && items.length <= 0) {
@ -157,7 +156,7 @@ const Item = PropTypes.shape({
PaginatedDataList.propTypes = {
items: PropTypes.arrayOf(Item).isRequired,
itemCount: PropTypes.number.isRequired,
itemName: PropTypes.string,
pluralizedItemName: PropTypes.string,
qsConfig: QSConfig.isRequired,
renderItem: PropTypes.func,
toolbarColumns: arrayOf(
@ -177,7 +176,7 @@ PaginatedDataList.defaultProps = {
hasContentLoading: false,
contentError: null,
toolbarColumns: [],
itemName: 'item',
pluralizedItemName: 'Items',
showPageSizeOptions: true,
renderItem: item => <PaginatedDataListItem key={item.id} item={item} />,
renderToolbar: props => <DataListToolbar {...props} />,

View File

@ -6,7 +6,6 @@ import styled from 'styled-components';
import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
import AlertModal from '../AlertModal';
import { pluralize } from '../../util/strings';
const DeleteButton = styled(Button)`
padding: 5px 8px;
@ -41,11 +40,11 @@ class ToolbarDeleteButton extends React.Component {
static propTypes = {
onDelete: func.isRequired,
itemsToDelete: arrayOf(ItemToDelete).isRequired,
itemName: string,
pluralizedItemName: string,
};
static defaultProps = {
itemName: 'item',
pluralizedItemName: 'Items',
};
constructor(props) {
@ -75,7 +74,7 @@ class ToolbarDeleteButton extends React.Component {
}
renderTooltip() {
const { itemsToDelete, itemName, i18n } = this.props;
const { itemsToDelete, pluralizedItemName, i18n } = this.props;
const itemsUnableToDelete = itemsToDelete
.filter(cannotDelete)
@ -85,7 +84,7 @@ class ToolbarDeleteButton extends React.Component {
return (
<div>
{i18n._(
t`You do not have permission to delete the following ${itemName}: ${itemsUnableToDelete}`
t`You do not have permission to delete the following ${pluralizedItemName}: ${itemsUnableToDelete}`
)}
</div>
);
@ -97,7 +96,7 @@ class ToolbarDeleteButton extends React.Component {
}
render() {
const { itemsToDelete, itemName, i18n } = this.props;
const { itemsToDelete, pluralizedItemName, i18n } = this.props;
const { isModalOpen } = this.state;
const isDisabled =
@ -123,7 +122,7 @@ class ToolbarDeleteButton extends React.Component {
{isModalOpen && (
<AlertModal
variant="danger"
title={itemName}
title={pluralizedItemName}
isOpen={isModalOpen}
onClose={this.handleCancelDelete}
actions={[

View File

@ -3,9 +3,9 @@
exports[`<ToolbarDeleteButton /> should render button 1`] = `
<ToolbarDeleteButton
i18n={"/i18n/"}
itemName="item"
itemsToDelete={Array []}
onDelete={[Function]}
pluralizedItemName="Items"
>
<Tooltip
appendTo={[Function]}

View File

@ -159,7 +159,7 @@ class JobList extends Component {
hasContentLoading={hasContentLoading}
items={jobs}
itemCount={itemCount}
itemName={itemCount === 1 ? 'Job' : 'Jobs'}
pluralizedItemName="Jobs"
qsConfig={QS_CONFIG}
toolbarColumns={[
{
@ -188,7 +188,7 @@ class JobList extends Component {
key="delete"
onDelete={this.handleJobDelete}
itemsToDelete={selected}
itemName={selected.length === 1 ? 'Job' : 'Jobs' }
pluralizedItemName="Jobs"
/>,
]}
/>

View File

@ -165,7 +165,7 @@ class OrganizationAccess extends React.Component {
hasContentLoading={hasContentLoading}
items={accessRecords}
itemCount={itemCount}
itemName={itemCount.length === 1 ? 'Role' : 'Roles'}
pluralizedItemName="Roles"
qsConfig={QS_CONFIG}
toolbarColumns={[
{

View File

@ -37,8 +37,8 @@ exports[`<OrganizationAccess /> initially renders succesfully 1`] = `
error={null}
hasContentLoading={true}
itemCount={0}
itemName="Roles"
items={Array []}
pluralizedItemName="Roles"
qsConfig={
Object {
"dateFields": Array [
@ -91,8 +91,8 @@ exports[`<OrganizationAccess /> initially renders succesfully 1`] = `
hasContentLoading={true}
i18n={"/i18n/"}
itemCount={0}
itemName="Roles"
items={Array []}
pluralizedItemName="Roles"
qsConfig={
Object {
"dateFields": Array [
@ -144,7 +144,6 @@ exports[`<OrganizationAccess /> initially renders succesfully 1`] = `
history={"/history/"}
i18n={"/i18n/"}
itemCount={0}
itemName="Roles"
items={Array []}
location={
Object {
@ -162,6 +161,7 @@ exports[`<OrganizationAccess /> initially renders succesfully 1`] = `
"url": "",
}
}
pluralizedItemName="Roles"
qsConfig={
Object {
"dateFields": Array [

View File

@ -153,7 +153,7 @@ class OrganizationsList extends Component {
hasContentLoading={hasContentLoading}
items={organizations}
itemCount={itemCount}
itemName={itemCount === 1 ? 'Organization' : 'Organizations'}
pluralizedItemName="Organizations"
qsConfig={QS_CONFIG}
toolbarColumns={[
{
@ -187,7 +187,7 @@ class OrganizationsList extends Component {
key="delete"
onDelete={this.handleOrgDelete}
itemsToDelete={selected}
itemName="Organization"
pluralizedItemName="Organizations"
/>,
canAdd ? (
<ToolbarAddButton key="add" linkTo={`${match.url}/add`} />

View File

@ -204,7 +204,7 @@ class OrganizationNotifications extends Component {
hasContentLoading={hasContentLoading}
items={notifications}
itemCount={itemCount}
itemName={itemCount.length === 1 ? 'Notification' : 'Notifications'}
pluralizedItemName="Notifications"
qsConfig={QS_CONFIG}
toolbarColumns={COLUMNS}
renderItem={notification => (

View File

@ -42,7 +42,6 @@ exports[`<OrganizationNotifications /> initially renders succesfully 1`] = `
contentError={null}
hasContentLoading={false}
itemCount={2}
itemName="Notifications"
items={
Array [
Object {
@ -65,6 +64,7 @@ exports[`<OrganizationNotifications /> initially renders succesfully 1`] = `
},
]
}
pluralizedItemName="Notifications"
qsConfig={
Object {
"dateFields": Array [
@ -116,7 +116,6 @@ exports[`<OrganizationNotifications /> initially renders succesfully 1`] = `
hasContentLoading={false}
i18n={"/i18n/"}
itemCount={2}
itemName="Notifications"
items={
Array [
Object {
@ -139,6 +138,7 @@ exports[`<OrganizationNotifications /> initially renders succesfully 1`] = `
},
]
}
pluralizedItemName="Notifications"
qsConfig={
Object {
"dateFields": Array [
@ -188,7 +188,6 @@ exports[`<OrganizationNotifications /> initially renders succesfully 1`] = `
history={"/history/"}
i18n={"/i18n/"}
itemCount={2}
itemName="Notifications"
items={
Array [
Object {
@ -227,6 +226,7 @@ exports[`<OrganizationNotifications /> initially renders succesfully 1`] = `
"url": "",
}
}
pluralizedItemName="Notifications"
qsConfig={
Object {
"dateFields": Array [
@ -1827,10 +1827,10 @@ exports[`<OrganizationNotifications /> initially renders succesfully 1`] = `
</Route>
</withRouter(ListHeader)>
<DataList
aria-label="{itemDisplayName} List"
aria-label="{pluralizedItemName} List"
>
<ul
aria-label="{itemDisplayName} List"
aria-label="{pluralizedItemName} List"
className="pf-c-data-list"
>
<WithI18n

View File

@ -65,7 +65,7 @@ class OrganizationTeams extends React.Component {
hasContentLoading={hasContentLoading}
items={teams}
itemCount={itemCount}
itemName={itemCount.length === 1 ? 'Notification' : 'Notifications'}
pluralizedItemName="Notifications"
qsConfig={QS_CONFIG}
/>
);

View File

@ -178,7 +178,7 @@ class TemplatesList extends Component {
hasContentLoading={hasContentLoading}
items={templates}
itemCount={itemCount}
itemName={itemCount === 1 ? 'Template' : 'Templates'}
pluralizedItemName="Templates"
qsConfig={QS_CONFIG}
toolbarColumns={[
{
@ -213,7 +213,7 @@ class TemplatesList extends Component {
key="delete"
onDelete={this.handleTemplateDelete}
itemsToDelete={selected}
itemName={selected.length === 1 ? 'Template' : 'Templates'}
pluralizedItemName="Templates"
/>,
canAdd && (
<Dropdown

View File

@ -1,4 +1,3 @@
// TODO: switch to using Lingui i18n for articles
export function getArticle(str) {
const first = str[0];
@ -8,10 +7,6 @@ export function getArticle(str) {
return 'a';
}
export function ucFirst(str) {
return `${str[0].toUpperCase()}${str.substr(1)}`;
}
export const toTitleCase = string => {
if (!string) {
return '';

View File

@ -1,4 +1,4 @@
import { getArticle, ucFirst, toTitleCase } from './strings';
import { getArticle, toTitleCase } from './strings';
describe('string utils', () => {
describe('getArticle', () => {
@ -16,12 +16,6 @@ describe('string utils', () => {
});
});
describe('ucFirst', () => {
test('should capitalize first character', () => {
expect(ucFirst('team')).toEqual('Team');
});
});
describe('toTitleCase', () => {
test('should upper case each word', () => {
expect(toTitleCase('a_string_of_words')).toEqual('A String Of Words');