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-24 11:21:54 -04:00
parent 8dd4379bf2
commit b3b53a8ce4
16 changed files with 33 additions and 52 deletions
@@ -212,7 +212,6 @@ class AddResourceRole extends React.Component {
selectedLabel={i18n._(t`Selected`)} selectedLabel={i18n._(t`Selected`)}
selectedResourceRows={selectedResourceRows} selectedResourceRows={selectedResourceRows}
sortedColumnKey="username" sortedColumnKey="username"
itemName="user"
/> />
)} )}
{selectedResource === 'teams' && ( {selectedResource === 'teams' && (
@@ -222,7 +221,6 @@ class AddResourceRole extends React.Component {
onSearch={readTeams} onSearch={readTeams}
selectedLabel={i18n._(t`Selected`)} selectedLabel={i18n._(t`Selected`)}
selectedResourceRows={selectedResourceRows} selectedResourceRows={selectedResourceRows}
itemName="team"
/> />
)} )}
</Fragment> </Fragment>
@@ -74,7 +74,6 @@ class SelectResourceStep extends React.Component {
onRowClick, onRowClick,
selectedLabel, selectedLabel,
selectedResourceRows, selectedResourceRows,
itemName,
i18n, i18n,
} = this.props; } = this.props;
@@ -100,7 +99,6 @@ class SelectResourceStep extends React.Component {
<PaginatedDataList <PaginatedDataList
items={resources} items={resources}
itemCount={count} itemCount={count}
itemName={itemName}
qsConfig={this.qsConfig} qsConfig={this.qsConfig}
toolbarColumns={columns} toolbarColumns={columns}
renderItem={item => ( renderItem={item => (
@@ -132,7 +130,6 @@ SelectResourceStep.propTypes = {
selectedLabel: PropTypes.string, selectedLabel: PropTypes.string,
selectedResourceRows: PropTypes.arrayOf(PropTypes.object), selectedResourceRows: PropTypes.arrayOf(PropTypes.object),
sortedColumnKey: PropTypes.string, sortedColumnKey: PropTypes.string,
itemName: PropTypes.string,
}; };
SelectResourceStep.defaultProps = { SelectResourceStep.defaultProps = {
@@ -141,7 +138,6 @@ SelectResourceStep.defaultProps = {
selectedLabel: null, selectedLabel: null,
selectedResourceRows: [], selectedResourceRows: [],
sortedColumnKey: 'name', sortedColumnKey: 'name',
itemName: 'item',
}; };
export { SelectResourceStep as _SelectResourceStep }; export { SelectResourceStep as _SelectResourceStep };
+2 -2
View File
@@ -212,7 +212,7 @@ class Lookup extends React.Component {
i18n, i18n,
} = this.props; } = this.props;
const header = lookupHeader || i18n._(t`items`); const header = lookupHeader || i18n._(t`Items`);
const canDelete = !required || (multiple && value.length > 1); const canDelete = !required || (multiple && value.length > 1);
const chips = value ? ( const chips = value ? (
@@ -268,7 +268,7 @@ class Lookup extends React.Component {
<PaginatedDataList <PaginatedDataList
items={results} items={results}
itemCount={count} itemCount={count}
itemName={lookupHeader} pluralizedItemName={lookupHeader}
qsConfig={this.qsConfig} qsConfig={this.qsConfig}
toolbarColumns={columns} toolbarColumns={columns}
renderItem={item => ( renderItem={item => (
@@ -17,7 +17,6 @@ import {
parseQueryString, parseQueryString,
addParams, addParams,
} from '@util/qs'; } from '@util/qs';
import { ucFirst } from '@util/strings';
import { QSConfig } from '@types'; import { QSConfig } from '@types';
@@ -63,7 +62,7 @@ class PaginatedDataList extends React.Component {
qsConfig, qsConfig,
renderItem, renderItem,
toolbarColumns, toolbarColumns,
itemName, pluralizedItemName,
showPageSizeOptions, showPageSizeOptions,
location, location,
i18n, i18n,
@@ -81,11 +80,11 @@ class PaginatedDataList extends React.Component {
]; ];
const queryParams = parseQueryString(qsConfig, location.search); const queryParams = parseQueryString(qsConfig, location.search);
const dataListLabel = i18n._(t`${itemName} List`); const dataListLabel = i18n._(t`${pluralizedItemName} List`);
const emptyContentMessage = i18n._( 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; let Content;
if (hasContentLoading && items.length <= 0) { if (hasContentLoading && items.length <= 0) {
@@ -157,7 +156,7 @@ const Item = PropTypes.shape({
PaginatedDataList.propTypes = { PaginatedDataList.propTypes = {
items: PropTypes.arrayOf(Item).isRequired, items: PropTypes.arrayOf(Item).isRequired,
itemCount: PropTypes.number.isRequired, itemCount: PropTypes.number.isRequired,
itemName: PropTypes.string, pluralizedItemName: PropTypes.string,
qsConfig: QSConfig.isRequired, qsConfig: QSConfig.isRequired,
renderItem: PropTypes.func, renderItem: PropTypes.func,
toolbarColumns: arrayOf( toolbarColumns: arrayOf(
@@ -177,7 +176,7 @@ PaginatedDataList.defaultProps = {
hasContentLoading: false, hasContentLoading: false,
contentError: null, contentError: null,
toolbarColumns: [], toolbarColumns: [],
itemName: 'item', pluralizedItemName: 'Items',
showPageSizeOptions: true, showPageSizeOptions: true,
renderItem: item => <PaginatedDataListItem key={item.id} item={item} />, renderItem: item => <PaginatedDataListItem key={item.id} item={item} />,
renderToolbar: props => <DataListToolbar {...props} />, renderToolbar: props => <DataListToolbar {...props} />,
@@ -6,7 +6,6 @@ import styled from 'styled-components';
import { withI18n } from '@lingui/react'; import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro'; import { t } from '@lingui/macro';
import AlertModal from '../AlertModal'; import AlertModal from '../AlertModal';
import { pluralize } from '../../util/strings';
const DeleteButton = styled(Button)` const DeleteButton = styled(Button)`
padding: 5px 8px; padding: 5px 8px;
@@ -41,11 +40,11 @@ class ToolbarDeleteButton extends React.Component {
static propTypes = { static propTypes = {
onDelete: func.isRequired, onDelete: func.isRequired,
itemsToDelete: arrayOf(ItemToDelete).isRequired, itemsToDelete: arrayOf(ItemToDelete).isRequired,
itemName: string, pluralizedItemName: string,
}; };
static defaultProps = { static defaultProps = {
itemName: 'item', pluralizedItemName: 'Items',
}; };
constructor(props) { constructor(props) {
@@ -75,7 +74,7 @@ class ToolbarDeleteButton extends React.Component {
} }
renderTooltip() { renderTooltip() {
const { itemsToDelete, itemName, i18n } = this.props; const { itemsToDelete, pluralizedItemName, i18n } = this.props;
const itemsUnableToDelete = itemsToDelete const itemsUnableToDelete = itemsToDelete
.filter(cannotDelete) .filter(cannotDelete)
@@ -85,7 +84,7 @@ class ToolbarDeleteButton extends React.Component {
return ( return (
<div> <div>
{i18n._( {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> </div>
); );
@@ -97,7 +96,7 @@ class ToolbarDeleteButton extends React.Component {
} }
render() { render() {
const { itemsToDelete, itemName, i18n } = this.props; const { itemsToDelete, pluralizedItemName, i18n } = this.props;
const { isModalOpen } = this.state; const { isModalOpen } = this.state;
const isDisabled = const isDisabled =
@@ -123,7 +122,7 @@ class ToolbarDeleteButton extends React.Component {
{isModalOpen && ( {isModalOpen && (
<AlertModal <AlertModal
variant="danger" variant="danger"
title={itemName} title={pluralizedItemName}
isOpen={isModalOpen} isOpen={isModalOpen}
onClose={this.handleCancelDelete} onClose={this.handleCancelDelete}
actions={[ actions={[
@@ -3,9 +3,9 @@
exports[`<ToolbarDeleteButton /> should render button 1`] = ` exports[`<ToolbarDeleteButton /> should render button 1`] = `
<ToolbarDeleteButton <ToolbarDeleteButton
i18n={"/i18n/"} i18n={"/i18n/"}
itemName="item"
itemsToDelete={Array []} itemsToDelete={Array []}
onDelete={[Function]} onDelete={[Function]}
pluralizedItemName="Items"
> >
<Tooltip <Tooltip
appendTo={[Function]} appendTo={[Function]}
@@ -159,7 +159,7 @@ class JobList extends Component {
hasContentLoading={hasContentLoading} hasContentLoading={hasContentLoading}
items={jobs} items={jobs}
itemCount={itemCount} itemCount={itemCount}
itemName={itemCount === 1 ? 'Job' : 'Jobs'} pluralizedItemName="Jobs"
qsConfig={QS_CONFIG} qsConfig={QS_CONFIG}
toolbarColumns={[ toolbarColumns={[
{ {
@@ -188,7 +188,7 @@ class JobList extends Component {
key="delete" key="delete"
onDelete={this.handleJobDelete} onDelete={this.handleJobDelete}
itemsToDelete={selected} itemsToDelete={selected}
itemName={selected.length === 1 ? 'Job' : 'Jobs' } pluralizedItemName="Jobs"
/>, />,
]} ]}
/> />
@@ -165,7 +165,7 @@ class OrganizationAccess extends React.Component {
hasContentLoading={hasContentLoading} hasContentLoading={hasContentLoading}
items={accessRecords} items={accessRecords}
itemCount={itemCount} itemCount={itemCount}
itemName={itemCount.length === 1 ? 'Role' : 'Roles'} pluralizedItemName="Roles"
qsConfig={QS_CONFIG} qsConfig={QS_CONFIG}
toolbarColumns={[ toolbarColumns={[
{ {
@@ -37,8 +37,8 @@ exports[`<OrganizationAccess /> initially renders succesfully 1`] = `
error={null} error={null}
hasContentLoading={true} hasContentLoading={true}
itemCount={0} itemCount={0}
itemName="Roles"
items={Array []} items={Array []}
pluralizedItemName="Roles"
qsConfig={ qsConfig={
Object { Object {
"dateFields": Array [ "dateFields": Array [
@@ -91,8 +91,8 @@ exports[`<OrganizationAccess /> initially renders succesfully 1`] = `
hasContentLoading={true} hasContentLoading={true}
i18n={"/i18n/"} i18n={"/i18n/"}
itemCount={0} itemCount={0}
itemName="Roles"
items={Array []} items={Array []}
pluralizedItemName="Roles"
qsConfig={ qsConfig={
Object { Object {
"dateFields": Array [ "dateFields": Array [
@@ -144,7 +144,6 @@ exports[`<OrganizationAccess /> initially renders succesfully 1`] = `
history={"/history/"} history={"/history/"}
i18n={"/i18n/"} i18n={"/i18n/"}
itemCount={0} itemCount={0}
itemName="Roles"
items={Array []} items={Array []}
location={ location={
Object { Object {
@@ -162,6 +161,7 @@ exports[`<OrganizationAccess /> initially renders succesfully 1`] = `
"url": "", "url": "",
} }
} }
pluralizedItemName="Roles"
qsConfig={ qsConfig={
Object { Object {
"dateFields": Array [ "dateFields": Array [
@@ -153,7 +153,7 @@ class OrganizationsList extends Component {
hasContentLoading={hasContentLoading} hasContentLoading={hasContentLoading}
items={organizations} items={organizations}
itemCount={itemCount} itemCount={itemCount}
itemName={itemCount === 1 ? 'Organization' : 'Organizations'} pluralizedItemName="Organizations"
qsConfig={QS_CONFIG} qsConfig={QS_CONFIG}
toolbarColumns={[ toolbarColumns={[
{ {
@@ -187,7 +187,7 @@ class OrganizationsList extends Component {
key="delete" key="delete"
onDelete={this.handleOrgDelete} onDelete={this.handleOrgDelete}
itemsToDelete={selected} itemsToDelete={selected}
itemName="Organization" pluralizedItemName="Organizations"
/>, />,
canAdd ? ( canAdd ? (
<ToolbarAddButton key="add" linkTo={`${match.url}/add`} /> <ToolbarAddButton key="add" linkTo={`${match.url}/add`} />
@@ -204,7 +204,7 @@ class OrganizationNotifications extends Component {
hasContentLoading={hasContentLoading} hasContentLoading={hasContentLoading}
items={notifications} items={notifications}
itemCount={itemCount} itemCount={itemCount}
itemName={itemCount.length === 1 ? 'Notification' : 'Notifications'} pluralizedItemName="Notifications"
qsConfig={QS_CONFIG} qsConfig={QS_CONFIG}
toolbarColumns={COLUMNS} toolbarColumns={COLUMNS}
renderItem={notification => ( renderItem={notification => (
@@ -42,7 +42,6 @@ exports[`<OrganizationNotifications /> initially renders succesfully 1`] = `
contentError={null} contentError={null}
hasContentLoading={false} hasContentLoading={false}
itemCount={2} itemCount={2}
itemName="Notifications"
items={ items={
Array [ Array [
Object { Object {
@@ -65,6 +64,7 @@ exports[`<OrganizationNotifications /> initially renders succesfully 1`] = `
}, },
] ]
} }
pluralizedItemName="Notifications"
qsConfig={ qsConfig={
Object { Object {
"dateFields": Array [ "dateFields": Array [
@@ -116,7 +116,6 @@ exports[`<OrganizationNotifications /> initially renders succesfully 1`] = `
hasContentLoading={false} hasContentLoading={false}
i18n={"/i18n/"} i18n={"/i18n/"}
itemCount={2} itemCount={2}
itemName="Notifications"
items={ items={
Array [ Array [
Object { Object {
@@ -139,6 +138,7 @@ exports[`<OrganizationNotifications /> initially renders succesfully 1`] = `
}, },
] ]
} }
pluralizedItemName="Notifications"
qsConfig={ qsConfig={
Object { Object {
"dateFields": Array [ "dateFields": Array [
@@ -188,7 +188,6 @@ exports[`<OrganizationNotifications /> initially renders succesfully 1`] = `
history={"/history/"} history={"/history/"}
i18n={"/i18n/"} i18n={"/i18n/"}
itemCount={2} itemCount={2}
itemName="Notifications"
items={ items={
Array [ Array [
Object { Object {
@@ -227,6 +226,7 @@ exports[`<OrganizationNotifications /> initially renders succesfully 1`] = `
"url": "", "url": "",
} }
} }
pluralizedItemName="Notifications"
qsConfig={ qsConfig={
Object { Object {
"dateFields": Array [ "dateFields": Array [
@@ -1827,10 +1827,10 @@ exports[`<OrganizationNotifications /> initially renders succesfully 1`] = `
</Route> </Route>
</withRouter(ListHeader)> </withRouter(ListHeader)>
<DataList <DataList
aria-label="{itemDisplayName} List" aria-label="{pluralizedItemName} List"
> >
<ul <ul
aria-label="{itemDisplayName} List" aria-label="{pluralizedItemName} List"
className="pf-c-data-list" className="pf-c-data-list"
> >
<WithI18n <WithI18n
@@ -65,7 +65,7 @@ class OrganizationTeams extends React.Component {
hasContentLoading={hasContentLoading} hasContentLoading={hasContentLoading}
items={teams} items={teams}
itemCount={itemCount} itemCount={itemCount}
itemName={itemCount.length === 1 ? 'Notification' : 'Notifications'} pluralizedItemName="Notifications"
qsConfig={QS_CONFIG} qsConfig={QS_CONFIG}
/> />
); );
@@ -178,7 +178,7 @@ class TemplatesList extends Component {
hasContentLoading={hasContentLoading} hasContentLoading={hasContentLoading}
items={templates} items={templates}
itemCount={itemCount} itemCount={itemCount}
itemName={itemCount === 1 ? 'Template' : 'Templates'} pluralizedItemName="Templates"
qsConfig={QS_CONFIG} qsConfig={QS_CONFIG}
toolbarColumns={[ toolbarColumns={[
{ {
@@ -213,7 +213,7 @@ class TemplatesList extends Component {
key="delete" key="delete"
onDelete={this.handleTemplateDelete} onDelete={this.handleTemplateDelete}
itemsToDelete={selected} itemsToDelete={selected}
itemName={selected.length === 1 ? 'Template' : 'Templates'} pluralizedItemName="Templates"
/>, />,
canAdd && ( canAdd && (
<Dropdown <Dropdown
-5
View File
@@ -1,4 +1,3 @@
// TODO: switch to using Lingui i18n for articles // TODO: switch to using Lingui i18n for articles
export function getArticle(str) { export function getArticle(str) {
const first = str[0]; const first = str[0];
@@ -8,10 +7,6 @@ export function getArticle(str) {
return 'a'; return 'a';
} }
export function ucFirst(str) {
return `${str[0].toUpperCase()}${str.substr(1)}`;
}
export const toTitleCase = string => { export const toTitleCase = string => {
if (!string) { if (!string) {
return ''; return '';
+1 -7
View File
@@ -1,4 +1,4 @@
import { getArticle, ucFirst, toTitleCase } from './strings'; import { getArticle, toTitleCase } from './strings';
describe('string utils', () => { describe('string utils', () => {
describe('getArticle', () => { describe('getArticle', () => {
@@ -16,12 +16,6 @@ describe('string utils', () => {
}); });
}); });
describe('ucFirst', () => {
test('should capitalize first character', () => {
expect(ucFirst('team')).toEqual('Team');
});
});
describe('toTitleCase', () => { describe('toTitleCase', () => {
test('should upper case each word', () => { test('should upper case each word', () => {
expect(toTitleCase('a_string_of_words')).toEqual('A String Of Words'); expect(toTitleCase('a_string_of_words')).toEqual('A String Of Words');