From b79c686336a9a65a381af66c587eee5aaedb46af Mon Sep 17 00:00:00 2001 From: Alex Corey Date: Tue, 17 Sep 2019 14:27:07 -0400 Subject: [PATCH 1/3] requires individual components to pluralize --- awx/ui_next/src/components/Lookup/Lookup.jsx | 1 - .../PaginatedDataList/PaginatedDataList.jsx | 11 +++-------- .../PaginatedDataList/ToolbarDeleteButton.jsx | 10 ++-------- awx/ui_next/src/screens/Job/JobList/JobList.jsx | 6 +++--- .../OrganizationAccess/OrganizationAccess.jsx | 2 +- .../OrganizationAccess.test.jsx.snap | 7 +++---- .../OrganizationList/OrganizationList.jsx | 2 +- .../OrganizationNotifications.jsx | 2 +- .../OrganizationNotifications.test.jsx.snap | 7 +++---- .../OrganizationTeams/OrganizationTeams.jsx | 7 +++++-- .../Template/TemplateList/TemplateList.jsx | 4 ++-- awx/ui_next/src/util/strings.js | 11 ----------- awx/ui_next/src/util/strings.test.js | 16 +--------------- 13 files changed, 25 insertions(+), 61 deletions(-) diff --git a/awx/ui_next/src/components/Lookup/Lookup.jsx b/awx/ui_next/src/components/Lookup/Lookup.jsx index b398c007ce..a0ee8e649f 100644 --- a/awx/ui_next/src/components/Lookup/Lookup.jsx +++ b/awx/ui_next/src/components/Lookup/Lookup.jsx @@ -269,7 +269,6 @@ class Lookup extends React.Component { items={results} itemCount={count} itemName={lookupHeader} - itemNamePlural={lookupHeader} qsConfig={this.qsConfig} toolbarColumns={columns} renderItem={item => ( diff --git a/awx/ui_next/src/components/PaginatedDataList/PaginatedDataList.jsx b/awx/ui_next/src/components/PaginatedDataList/PaginatedDataList.jsx index d238595212..b8f882dea9 100644 --- a/awx/ui_next/src/components/PaginatedDataList/PaginatedDataList.jsx +++ b/awx/ui_next/src/components/PaginatedDataList/PaginatedDataList.jsx @@ -17,7 +17,7 @@ import { parseQueryString, addParams, } from '@util/qs'; -import { pluralize, ucFirst } from '@util/strings'; +import { ucFirst } from '@util/strings'; import { QSConfig } from '@types'; @@ -64,7 +64,6 @@ class PaginatedDataList extends React.Component { renderItem, toolbarColumns, itemName, - itemNamePlural, showPageSizeOptions, location, i18n, @@ -82,10 +81,8 @@ class PaginatedDataList extends React.Component { ]; const queryParams = parseQueryString(qsConfig, location.search); - const itemDisplayName = ucFirst(pluralize(itemName)); - const itemDisplayNamePlural = ucFirst( - itemNamePlural || pluralize(itemName) - ); + const itemDisplayName = ucFirst(itemName); + const itemDisplayNamePlural = ucFirst(itemName); const dataListLabel = i18n._(t`${itemDisplayName} List`); const emptyContentMessage = i18n._( @@ -164,7 +161,6 @@ PaginatedDataList.propTypes = { items: PropTypes.arrayOf(Item).isRequired, itemCount: PropTypes.number.isRequired, itemName: PropTypes.string, - itemNamePlural: PropTypes.string, qsConfig: QSConfig.isRequired, renderItem: PropTypes.func, toolbarColumns: arrayOf( @@ -185,7 +181,6 @@ PaginatedDataList.defaultProps = { contentError: null, toolbarColumns: [], itemName: 'item', - itemNamePlural: '', showPageSizeOptions: true, renderItem: item => , renderToolbar: props => , diff --git a/awx/ui_next/src/components/PaginatedDataList/ToolbarDeleteButton.jsx b/awx/ui_next/src/components/PaginatedDataList/ToolbarDeleteButton.jsx index c324faf016..22d0064847 100644 --- a/awx/ui_next/src/components/PaginatedDataList/ToolbarDeleteButton.jsx +++ b/awx/ui_next/src/components/PaginatedDataList/ToolbarDeleteButton.jsx @@ -85,9 +85,7 @@ class ToolbarDeleteButton extends React.Component { return (
{i18n._( - t`You do not have permission to delete the following ${pluralize( - itemName - )}: ${itemsUnableToDelete}` + t`You do not have permission to delete the following ${itemName}: ${itemsUnableToDelete}` )}
); @@ -125,11 +123,7 @@ class ToolbarDeleteButton extends React.Component { {isModalOpen && ( @@ -160,7 +160,7 @@ class JobList extends Component { hasContentLoading={hasContentLoading} items={jobs} itemCount={itemCount} - itemName={itemName} + itemName={itemCount === 1 ? i18n._(t`Job`): i18n._(t`Jobs`)} qsConfig={QS_CONFIG} toolbarColumns={[ { @@ -189,7 +189,7 @@ class JobList extends Component { key="delete" onDelete={this.handleJobDelete} itemsToDelete={selected} - itemName={itemName} + itemName={selected.length === 1 ? i18n._(t`Job`): i18n._(t`Jobs`)} />, ]} /> diff --git a/awx/ui_next/src/screens/Organization/OrganizationAccess/OrganizationAccess.jsx b/awx/ui_next/src/screens/Organization/OrganizationAccess/OrganizationAccess.jsx index 4c3c20d2ec..e5ec016a72 100644 --- a/awx/ui_next/src/screens/Organization/OrganizationAccess/OrganizationAccess.jsx +++ b/awx/ui_next/src/screens/Organization/OrganizationAccess/OrganizationAccess.jsx @@ -165,7 +165,7 @@ class OrganizationAccess extends React.Component { hasContentLoading={hasContentLoading} items={accessRecords} itemCount={itemCount} - itemName="role" + itemName={itemCount.length === 1 ? i18n._(t`Role`): i18n._(t`Roles`)} qsConfig={QS_CONFIG} toolbarColumns={[ { diff --git a/awx/ui_next/src/screens/Organization/OrganizationAccess/__snapshots__/OrganizationAccess.test.jsx.snap b/awx/ui_next/src/screens/Organization/OrganizationAccess/__snapshots__/OrganizationAccess.test.jsx.snap index 78cf3807ad..c5440db492 100644 --- a/awx/ui_next/src/screens/Organization/OrganizationAccess/__snapshots__/OrganizationAccess.test.jsx.snap +++ b/awx/ui_next/src/screens/Organization/OrganizationAccess/__snapshots__/OrganizationAccess.test.jsx.snap @@ -37,7 +37,7 @@ exports[` initially renders succesfully 1`] = ` error={null} hasContentLoading={true} itemCount={0} - itemName="role" + itemName="Roles" items={Array []} qsConfig={ Object { @@ -91,7 +91,7 @@ exports[` initially renders succesfully 1`] = ` hasContentLoading={true} i18n={"/i18n/"} itemCount={0} - itemName="role" + itemName="Roles" items={Array []} qsConfig={ Object { @@ -144,8 +144,7 @@ exports[` initially renders succesfully 1`] = ` history={"/history/"} i18n={"/i18n/"} itemCount={0} - itemName="role" - itemNamePlural="" + itemName="Roles" items={Array []} location={ Object { diff --git a/awx/ui_next/src/screens/Organization/OrganizationList/OrganizationList.jsx b/awx/ui_next/src/screens/Organization/OrganizationList/OrganizationList.jsx index 3bcd6ff9a5..51684e93e3 100644 --- a/awx/ui_next/src/screens/Organization/OrganizationList/OrganizationList.jsx +++ b/awx/ui_next/src/screens/Organization/OrganizationList/OrganizationList.jsx @@ -153,7 +153,7 @@ class OrganizationsList extends Component { hasContentLoading={hasContentLoading} items={organizations} itemCount={itemCount} - itemName="organization" + itemName={itemCount === 1 ? i18n._(t`Organization`): i18n._(t`Organizations`)} qsConfig={QS_CONFIG} toolbarColumns={[ { diff --git a/awx/ui_next/src/screens/Organization/OrganizationNotifications/OrganizationNotifications.jsx b/awx/ui_next/src/screens/Organization/OrganizationNotifications/OrganizationNotifications.jsx index 4699c43aa2..6c34267121 100644 --- a/awx/ui_next/src/screens/Organization/OrganizationNotifications/OrganizationNotifications.jsx +++ b/awx/ui_next/src/screens/Organization/OrganizationNotifications/OrganizationNotifications.jsx @@ -204,7 +204,7 @@ class OrganizationNotifications extends Component { hasContentLoading={hasContentLoading} items={notifications} itemCount={itemCount} - itemName="notification" + itemName={itemCount.length === 1 ? i18n._(t`Notification`): i18n._(t`Notifications`)} qsConfig={QS_CONFIG} toolbarColumns={COLUMNS} renderItem={notification => ( diff --git a/awx/ui_next/src/screens/Organization/OrganizationNotifications/__snapshots__/OrganizationNotifications.test.jsx.snap b/awx/ui_next/src/screens/Organization/OrganizationNotifications/__snapshots__/OrganizationNotifications.test.jsx.snap index 8116327545..ef7859326c 100644 --- a/awx/ui_next/src/screens/Organization/OrganizationNotifications/__snapshots__/OrganizationNotifications.test.jsx.snap +++ b/awx/ui_next/src/screens/Organization/OrganizationNotifications/__snapshots__/OrganizationNotifications.test.jsx.snap @@ -42,7 +42,7 @@ exports[` initially renders succesfully 1`] = ` contentError={null} hasContentLoading={false} itemCount={2} - itemName="notification" + itemName="Notifications" items={ Array [ Object { @@ -116,7 +116,7 @@ exports[` initially renders succesfully 1`] = ` hasContentLoading={false} i18n={"/i18n/"} itemCount={2} - itemName="notification" + itemName="Notifications" items={ Array [ Object { @@ -188,8 +188,7 @@ exports[` initially renders succesfully 1`] = ` history={"/history/"} i18n={"/i18n/"} itemCount={2} - itemName="notification" - itemNamePlural="" + itemName="Notifications" items={ Array [ Object { diff --git a/awx/ui_next/src/screens/Organization/OrganizationTeams/OrganizationTeams.jsx b/awx/ui_next/src/screens/Organization/OrganizationTeams/OrganizationTeams.jsx index faa9d4b359..636f826cc7 100644 --- a/awx/ui_next/src/screens/Organization/OrganizationTeams/OrganizationTeams.jsx +++ b/awx/ui_next/src/screens/Organization/OrganizationTeams/OrganizationTeams.jsx @@ -1,6 +1,8 @@ import React from 'react'; import PropTypes from 'prop-types'; import { withRouter } from 'react-router-dom'; +import { t } from '@lingui/macro'; +import { withI18n } from '@lingui/react'; import { OrganizationsAPI } from '@api'; import PaginatedDataList from '@components/PaginatedDataList'; @@ -59,13 +61,14 @@ class OrganizationTeams extends React.Component { render() { const { contentError, hasContentLoading, teams, itemCount } = this.state; + const { i18n } = this.props; return ( ); @@ -77,4 +80,4 @@ OrganizationTeams.propTypes = { }; export { OrganizationTeams as _OrganizationTeams }; -export default withRouter(OrganizationTeams); +export default withI18n()(withRouter(OrganizationTeams)); diff --git a/awx/ui_next/src/screens/Template/TemplateList/TemplateList.jsx b/awx/ui_next/src/screens/Template/TemplateList/TemplateList.jsx index 90c4482936..1c4542ffae 100644 --- a/awx/ui_next/src/screens/Template/TemplateList/TemplateList.jsx +++ b/awx/ui_next/src/screens/Template/TemplateList/TemplateList.jsx @@ -178,7 +178,7 @@ class TemplatesList extends Component { hasContentLoading={hasContentLoading} items={templates} itemCount={itemCount} - itemName={i18n._(t`Template`)} + itemName={itemCount === 1 ? i18n._(t`Template`): i18n._(t`Templates`)} qsConfig={QS_CONFIG} toolbarColumns={[ { @@ -213,7 +213,7 @@ class TemplatesList extends Component { key="delete" onDelete={this.handleTemplateDelete} itemsToDelete={selected} - itemName={i18n._(t`Template`)} + itemName={selected.length === 1 ? i18n._(t`Template`): i18n._(t`Templates`)} />, canAdd && ( { - describe('pluralize', () => { - test('should add an "s"', () => { - expect(pluralize('team')).toEqual('teams'); - }); - - test('should add an "es"', () => { - expect(pluralize('class')).toEqual('classes'); - }); - - test('should handle word ending in y', () => { - expect(pluralize('inventory')).toEqual('inventories'); - }); - }); - describe('getArticle', () => { test('should return "a"', () => { expect(getArticle('team')).toEqual('a'); From 8dd4379bf2b56596e9407ff7ff8b09505e587490 Mon Sep 17 00:00:00 2001 From: Alex Corey Date: Wed, 18 Sep 2019 09:23:09 -0400 Subject: [PATCH 2/3] Adds proper translation. removes ucFirst()> --- .../components/PaginatedDataList/PaginatedDataList.jsx | 9 +++------ awx/ui_next/src/screens/Job/JobList/JobList.jsx | 5 ++--- .../OrganizationAccess/OrganizationAccess.jsx | 2 +- .../Organization/OrganizationList/OrganizationList.jsx | 2 +- .../OrganizationNotifications.jsx | 2 +- .../Organization/OrganizationTeams/OrganizationTeams.jsx | 7 ++----- .../src/screens/Template/TemplateList/TemplateList.jsx | 4 ++-- 7 files changed, 12 insertions(+), 19 deletions(-) diff --git a/awx/ui_next/src/components/PaginatedDataList/PaginatedDataList.jsx b/awx/ui_next/src/components/PaginatedDataList/PaginatedDataList.jsx index b8f882dea9..1e26cf728c 100644 --- a/awx/ui_next/src/components/PaginatedDataList/PaginatedDataList.jsx +++ b/awx/ui_next/src/components/PaginatedDataList/PaginatedDataList.jsx @@ -81,14 +81,11 @@ class PaginatedDataList extends React.Component { ]; const queryParams = parseQueryString(qsConfig, location.search); - const itemDisplayName = ucFirst(itemName); - const itemDisplayNamePlural = ucFirst(itemName); - - const dataListLabel = i18n._(t`${itemDisplayName} List`); + const dataListLabel = i18n._(t`${itemName} List`); const emptyContentMessage = i18n._( - t`Please add ${itemDisplayNamePlural} to populate this list ` + t`Please add ${itemName} to populate this list ` ); - const emptyContentTitle = i18n._(t`No ${itemDisplayNamePlural} Found `); + const emptyContentTitle = i18n._(t`No ${itemName} Found `); let Content; if (hasContentLoading && items.length <= 0) { diff --git a/awx/ui_next/src/screens/Job/JobList/JobList.jsx b/awx/ui_next/src/screens/Job/JobList/JobList.jsx index 547d512137..5a90a3bc45 100644 --- a/awx/ui_next/src/screens/Job/JobList/JobList.jsx +++ b/awx/ui_next/src/screens/Job/JobList/JobList.jsx @@ -151,7 +151,6 @@ class JobList extends Component { } = this.state; const { match, i18n } = this.props; const isAllSelected = selected.length === jobs.length; - // const itemName = i18n._(t`Job`); return ( @@ -160,7 +159,7 @@ class JobList extends Component { hasContentLoading={hasContentLoading} items={jobs} itemCount={itemCount} - itemName={itemCount === 1 ? i18n._(t`Job`): i18n._(t`Jobs`)} + itemName={itemCount === 1 ? 'Job' : 'Jobs'} qsConfig={QS_CONFIG} toolbarColumns={[ { @@ -189,7 +188,7 @@ class JobList extends Component { key="delete" onDelete={this.handleJobDelete} itemsToDelete={selected} - itemName={selected.length === 1 ? i18n._(t`Job`): i18n._(t`Jobs`)} + itemName={selected.length === 1 ? 'Job' : 'Jobs' } />, ]} /> diff --git a/awx/ui_next/src/screens/Organization/OrganizationAccess/OrganizationAccess.jsx b/awx/ui_next/src/screens/Organization/OrganizationAccess/OrganizationAccess.jsx index e5ec016a72..265860a6d1 100644 --- a/awx/ui_next/src/screens/Organization/OrganizationAccess/OrganizationAccess.jsx +++ b/awx/ui_next/src/screens/Organization/OrganizationAccess/OrganizationAccess.jsx @@ -165,7 +165,7 @@ class OrganizationAccess extends React.Component { hasContentLoading={hasContentLoading} items={accessRecords} itemCount={itemCount} - itemName={itemCount.length === 1 ? i18n._(t`Role`): i18n._(t`Roles`)} + itemName={itemCount.length === 1 ? 'Role' : 'Roles'} qsConfig={QS_CONFIG} toolbarColumns={[ { diff --git a/awx/ui_next/src/screens/Organization/OrganizationList/OrganizationList.jsx b/awx/ui_next/src/screens/Organization/OrganizationList/OrganizationList.jsx index 51684e93e3..4ef3ef50d5 100644 --- a/awx/ui_next/src/screens/Organization/OrganizationList/OrganizationList.jsx +++ b/awx/ui_next/src/screens/Organization/OrganizationList/OrganizationList.jsx @@ -153,7 +153,7 @@ class OrganizationsList extends Component { hasContentLoading={hasContentLoading} items={organizations} itemCount={itemCount} - itemName={itemCount === 1 ? i18n._(t`Organization`): i18n._(t`Organizations`)} + itemName={itemCount === 1 ? 'Organization' : 'Organizations'} qsConfig={QS_CONFIG} toolbarColumns={[ { diff --git a/awx/ui_next/src/screens/Organization/OrganizationNotifications/OrganizationNotifications.jsx b/awx/ui_next/src/screens/Organization/OrganizationNotifications/OrganizationNotifications.jsx index 6c34267121..9c382643df 100644 --- a/awx/ui_next/src/screens/Organization/OrganizationNotifications/OrganizationNotifications.jsx +++ b/awx/ui_next/src/screens/Organization/OrganizationNotifications/OrganizationNotifications.jsx @@ -204,7 +204,7 @@ class OrganizationNotifications extends Component { hasContentLoading={hasContentLoading} items={notifications} itemCount={itemCount} - itemName={itemCount.length === 1 ? i18n._(t`Notification`): i18n._(t`Notifications`)} + itemName={itemCount.length === 1 ? 'Notification' : 'Notifications'} qsConfig={QS_CONFIG} toolbarColumns={COLUMNS} renderItem={notification => ( diff --git a/awx/ui_next/src/screens/Organization/OrganizationTeams/OrganizationTeams.jsx b/awx/ui_next/src/screens/Organization/OrganizationTeams/OrganizationTeams.jsx index 636f826cc7..c12af7ec3f 100644 --- a/awx/ui_next/src/screens/Organization/OrganizationTeams/OrganizationTeams.jsx +++ b/awx/ui_next/src/screens/Organization/OrganizationTeams/OrganizationTeams.jsx @@ -1,8 +1,6 @@ import React from 'react'; import PropTypes from 'prop-types'; import { withRouter } from 'react-router-dom'; -import { t } from '@lingui/macro'; -import { withI18n } from '@lingui/react'; import { OrganizationsAPI } from '@api'; import PaginatedDataList from '@components/PaginatedDataList'; @@ -61,14 +59,13 @@ class OrganizationTeams extends React.Component { render() { const { contentError, hasContentLoading, teams, itemCount } = this.state; - const { i18n } = this.props; return ( ); @@ -80,4 +77,4 @@ OrganizationTeams.propTypes = { }; export { OrganizationTeams as _OrganizationTeams }; -export default withI18n()(withRouter(OrganizationTeams)); +export default withRouter(OrganizationTeams); diff --git a/awx/ui_next/src/screens/Template/TemplateList/TemplateList.jsx b/awx/ui_next/src/screens/Template/TemplateList/TemplateList.jsx index 1c4542ffae..f3b5a190ce 100644 --- a/awx/ui_next/src/screens/Template/TemplateList/TemplateList.jsx +++ b/awx/ui_next/src/screens/Template/TemplateList/TemplateList.jsx @@ -178,7 +178,7 @@ class TemplatesList extends Component { hasContentLoading={hasContentLoading} items={templates} itemCount={itemCount} - itemName={itemCount === 1 ? i18n._(t`Template`): i18n._(t`Templates`)} + itemName={itemCount === 1 ? 'Template' : 'Templates'} qsConfig={QS_CONFIG} toolbarColumns={[ { @@ -213,7 +213,7 @@ class TemplatesList extends Component { key="delete" onDelete={this.handleTemplateDelete} itemsToDelete={selected} - itemName={selected.length === 1 ? i18n._(t`Template`): i18n._(t`Templates`)} + itemName={selected.length === 1 ? 'Template' : 'Templates'} />, canAdd && ( Date: Thu, 19 Sep 2019 13:41:13 -0400 Subject: [PATCH 3/3] 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. --- .../src/components/AddRole/AddResourceRole.jsx | 2 -- .../src/components/AddRole/SelectResourceStep.jsx | 4 ---- awx/ui_next/src/components/Lookup/Lookup.jsx | 4 ++-- .../PaginatedDataList/PaginatedDataList.jsx | 13 ++++++------- .../PaginatedDataList/ToolbarDeleteButton.jsx | 13 ++++++------- .../__snapshots__/ToolbarDeleteButton.test.jsx.snap | 2 +- awx/ui_next/src/screens/Job/JobList/JobList.jsx | 4 ++-- .../OrganizationAccess/OrganizationAccess.jsx | 2 +- .../__snapshots__/OrganizationAccess.test.jsx.snap | 6 +++--- .../OrganizationList/OrganizationList.jsx | 4 ++-- .../OrganizationNotifications.jsx | 2 +- .../OrganizationNotifications.test.jsx.snap | 10 +++++----- .../OrganizationTeams/OrganizationTeams.jsx | 2 +- .../screens/Template/TemplateList/TemplateList.jsx | 4 ++-- awx/ui_next/src/util/strings.js | 5 ----- awx/ui_next/src/util/strings.test.js | 8 +------- 16 files changed, 33 insertions(+), 52 deletions(-) diff --git a/awx/ui_next/src/components/AddRole/AddResourceRole.jsx b/awx/ui_next/src/components/AddRole/AddResourceRole.jsx index 3710af710e..3add8286c9 100644 --- a/awx/ui_next/src/components/AddRole/AddResourceRole.jsx +++ b/awx/ui_next/src/components/AddRole/AddResourceRole.jsx @@ -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" /> )} diff --git a/awx/ui_next/src/components/AddRole/SelectResourceStep.jsx b/awx/ui_next/src/components/AddRole/SelectResourceStep.jsx index f1b436f92c..1128015bdd 100644 --- a/awx/ui_next/src/components/AddRole/SelectResourceStep.jsx +++ b/awx/ui_next/src/components/AddRole/SelectResourceStep.jsx @@ -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 { ( @@ -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 }; diff --git a/awx/ui_next/src/components/Lookup/Lookup.jsx b/awx/ui_next/src/components/Lookup/Lookup.jsx index a0ee8e649f..874571fcb0 100644 --- a/awx/ui_next/src/components/Lookup/Lookup.jsx +++ b/awx/ui_next/src/components/Lookup/Lookup.jsx @@ -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 { ( diff --git a/awx/ui_next/src/components/PaginatedDataList/PaginatedDataList.jsx b/awx/ui_next/src/components/PaginatedDataList/PaginatedDataList.jsx index 1e26cf728c..d6af7eae3d 100644 --- a/awx/ui_next/src/components/PaginatedDataList/PaginatedDataList.jsx +++ b/awx/ui_next/src/components/PaginatedDataList/PaginatedDataList.jsx @@ -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 => , renderToolbar: props => , diff --git a/awx/ui_next/src/components/PaginatedDataList/ToolbarDeleteButton.jsx b/awx/ui_next/src/components/PaginatedDataList/ToolbarDeleteButton.jsx index 22d0064847..dd595013e1 100644 --- a/awx/ui_next/src/components/PaginatedDataList/ToolbarDeleteButton.jsx +++ b/awx/ui_next/src/components/PaginatedDataList/ToolbarDeleteButton.jsx @@ -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 (
{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}` )}
); @@ -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 && ( should render button 1`] = ` , ]} /> diff --git a/awx/ui_next/src/screens/Organization/OrganizationAccess/OrganizationAccess.jsx b/awx/ui_next/src/screens/Organization/OrganizationAccess/OrganizationAccess.jsx index 265860a6d1..534a278524 100644 --- a/awx/ui_next/src/screens/Organization/OrganizationAccess/OrganizationAccess.jsx +++ b/awx/ui_next/src/screens/Organization/OrganizationAccess/OrganizationAccess.jsx @@ -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={[ { diff --git a/awx/ui_next/src/screens/Organization/OrganizationAccess/__snapshots__/OrganizationAccess.test.jsx.snap b/awx/ui_next/src/screens/Organization/OrganizationAccess/__snapshots__/OrganizationAccess.test.jsx.snap index c5440db492..a26f750136 100644 --- a/awx/ui_next/src/screens/Organization/OrganizationAccess/__snapshots__/OrganizationAccess.test.jsx.snap +++ b/awx/ui_next/src/screens/Organization/OrganizationAccess/__snapshots__/OrganizationAccess.test.jsx.snap @@ -37,8 +37,8 @@ exports[` 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[` 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[` initially renders succesfully 1`] = ` history={"/history/"} i18n={"/i18n/"} itemCount={0} - itemName="Roles" items={Array []} location={ Object { @@ -162,6 +161,7 @@ exports[` initially renders succesfully 1`] = ` "url": "", } } + pluralizedItemName="Roles" qsConfig={ Object { "dateFields": Array [ diff --git a/awx/ui_next/src/screens/Organization/OrganizationList/OrganizationList.jsx b/awx/ui_next/src/screens/Organization/OrganizationList/OrganizationList.jsx index 4ef3ef50d5..06e83022b8 100644 --- a/awx/ui_next/src/screens/Organization/OrganizationList/OrganizationList.jsx +++ b/awx/ui_next/src/screens/Organization/OrganizationList/OrganizationList.jsx @@ -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 ? ( diff --git a/awx/ui_next/src/screens/Organization/OrganizationNotifications/OrganizationNotifications.jsx b/awx/ui_next/src/screens/Organization/OrganizationNotifications/OrganizationNotifications.jsx index 9c382643df..56bf6cd5e9 100644 --- a/awx/ui_next/src/screens/Organization/OrganizationNotifications/OrganizationNotifications.jsx +++ b/awx/ui_next/src/screens/Organization/OrganizationNotifications/OrganizationNotifications.jsx @@ -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 => ( diff --git a/awx/ui_next/src/screens/Organization/OrganizationNotifications/__snapshots__/OrganizationNotifications.test.jsx.snap b/awx/ui_next/src/screens/Organization/OrganizationNotifications/__snapshots__/OrganizationNotifications.test.jsx.snap index ef7859326c..ac85a02e36 100644 --- a/awx/ui_next/src/screens/Organization/OrganizationNotifications/__snapshots__/OrganizationNotifications.test.jsx.snap +++ b/awx/ui_next/src/screens/Organization/OrganizationNotifications/__snapshots__/OrganizationNotifications.test.jsx.snap @@ -42,7 +42,6 @@ exports[` initially renders succesfully 1`] = ` contentError={null} hasContentLoading={false} itemCount={2} - itemName="Notifications" items={ Array [ Object { @@ -65,6 +64,7 @@ exports[` initially renders succesfully 1`] = ` }, ] } + pluralizedItemName="Notifications" qsConfig={ Object { "dateFields": Array [ @@ -116,7 +116,6 @@ exports[` initially renders succesfully 1`] = ` hasContentLoading={false} i18n={"/i18n/"} itemCount={2} - itemName="Notifications" items={ Array [ Object { @@ -139,6 +138,7 @@ exports[` initially renders succesfully 1`] = ` }, ] } + pluralizedItemName="Notifications" qsConfig={ Object { "dateFields": Array [ @@ -188,7 +188,6 @@ exports[` initially renders succesfully 1`] = ` history={"/history/"} i18n={"/i18n/"} itemCount={2} - itemName="Notifications" items={ Array [ Object { @@ -227,6 +226,7 @@ exports[` initially renders succesfully 1`] = ` "url": "", } } + pluralizedItemName="Notifications" qsConfig={ Object { "dateFields": Array [ @@ -1827,10 +1827,10 @@ exports[` initially renders succesfully 1`] = `
    ); diff --git a/awx/ui_next/src/screens/Template/TemplateList/TemplateList.jsx b/awx/ui_next/src/screens/Template/TemplateList/TemplateList.jsx index f3b5a190ce..e0f12f8bcb 100644 --- a/awx/ui_next/src/screens/Template/TemplateList/TemplateList.jsx +++ b/awx/ui_next/src/screens/Template/TemplateList/TemplateList.jsx @@ -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 && ( { if (!string) { return ''; diff --git a/awx/ui_next/src/util/strings.test.js b/awx/ui_next/src/util/strings.test.js index 3f09f88bd0..f1498d1df7 100644 --- a/awx/ui_next/src/util/strings.test.js +++ b/awx/ui_next/src/util/strings.test.js @@ -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');