Merge pull request #9897 from AlexSCorey/9891-Plural

Properly tags Plural-able strings for translation, and removes unnecessary i18n

SUMMARY
This resolves #9891.
It also begings the process of remove i18n._(t string) in places in favor of this syntax
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

UI

AWX VERSION



ADDITIONAL INFORMATION

Reviewed-by: Keith Grant <keithjgrant@gmail.com>
Reviewed-by: Kersom <None>
Reviewed-by: Alex Corey <Alex.swansboro@gmail.com>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
This commit is contained in:
softwarefactory-project-zuul[bot] 2021-04-23 17:12:04 +00:00 committed by GitHub
commit a744f0d30f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 5367 additions and 3847 deletions

View File

@ -1,7 +1,6 @@
import React, { useState, useEffect, useCallback } from 'react';
import { useLocation } from 'react-router-dom';
import { withI18n } from '@lingui/react';
import { t, plural } from '@lingui/macro';
import { t, Plural } from '@lingui/macro';
import { Card } from '@patternfly/react-core';
import AlertModal from '../AlertModal';
@ -20,7 +19,7 @@ import JobListCancelButton from './JobListCancelButton';
import useWsJobs from './useWsJobs';
import { UnifiedJobsAPI } from '../../api';
function JobList({ i18n, defaultParams, showTypeColumn = false }) {
function JobList({ defaultParams, showTypeColumn = false }) {
const qsConfig = getQSConfig(
'job',
{
@ -162,67 +161,65 @@ function JobList({ i18n, defaultParams, showTypeColumn = false }) {
hasContentLoading={isLoading || isDeleteLoading || isCancelLoading}
items={jobs}
itemCount={count}
pluralizedItemName={i18n._(t`Jobs`)}
pluralizedItemName={t`Jobs`}
qsConfig={qsConfig}
toolbarSearchColumns={[
{
name: i18n._(t`Name`),
name: t`Name`,
key: 'name__icontains',
isDefault: true,
},
{
name: i18n._(t`ID`),
name: t`ID`,
key: 'id',
},
{
name: i18n._(t`Label Name`),
name: t`Label Name`,
key: 'labels__name__icontains',
},
{
name: i18n._(t`Job Type`),
name: t`Job Type`,
key: `or__type`,
options: [
[`project_update`, i18n._(t`Source Control Update`)],
[`inventory_update`, i18n._(t`Inventory Sync`)],
[`job`, i18n._(t`Playbook Run`)],
[`ad_hoc_command`, i18n._(t`Command`)],
[`system_job`, i18n._(t`Management Job`)],
[`workflow_job`, i18n._(t`Workflow Job`)],
[`project_update`, t`Source Control Update`],
[`inventory_update`, t`Inventory Sync`],
[`job`, t`Playbook Run`],
[`ad_hoc_command`, t`Command`],
[`system_job`, t`Management Job`],
[`workflow_job`, t`Workflow Job`],
],
},
{
name: i18n._(t`Launched By (Username)`),
name: t`Launched By (Username)`,
key: 'created_by__username__icontains',
},
{
name: i18n._(t`Status`),
name: t`Status`,
key: 'status',
options: [
[`new`, i18n._(t`New`)],
[`pending`, i18n._(t`Pending`)],
[`waiting`, i18n._(t`Waiting`)],
[`running`, i18n._(t`Running`)],
[`successful`, i18n._(t`Successful`)],
[`failed`, i18n._(t`Failed`)],
[`error`, i18n._(t`Error`)],
[`canceled`, i18n._(t`Canceled`)],
[`new`, t`New`],
[`pending`, t`Pending`],
[`waiting`, t`Waiting`],
[`running`, t`Running`],
[`successful`, t`Successful`],
[`failed`, t`Failed`],
[`error`, t`Error`],
[`canceled`, t`Canceled`],
],
},
{
name: i18n._(t`Limit`),
name: t`Limit`,
key: 'job__limit',
},
]}
headerRow={
<HeaderRow qsConfig={qsConfig} isExpandable>
<HeaderCell sortKey="name">{i18n._(t`Name`)}</HeaderCell>
<HeaderCell sortKey="status">{i18n._(t`Status`)}</HeaderCell>
{showTypeColumn && <HeaderCell>{i18n._(t`Type`)}</HeaderCell>}
<HeaderCell sortKey="started">{i18n._(t`Start Time`)}</HeaderCell>
<HeaderCell sortKey="finished">
{i18n._(t`Finish Time`)}
</HeaderCell>
<HeaderCell>{i18n._(t`Actions`)}</HeaderCell>
<HeaderCell sortKey="name">{t`Name`}</HeaderCell>
<HeaderCell sortKey="status">{t`Status`}</HeaderCell>
{showTypeColumn && <HeaderCell>{t`Type`}</HeaderCell>}
<HeaderCell sortKey="started">{t`Start Time`}</HeaderCell>
<HeaderCell sortKey="finished">{t`Finish Time`}</HeaderCell>
<HeaderCell>{t`Actions`}</HeaderCell>
</HeaderRow>
}
toolbarSearchableKeys={searchableKeys}
@ -239,17 +236,18 @@ function JobList({ i18n, defaultParams, showTypeColumn = false }) {
key="delete"
onDelete={handleJobDelete}
itemsToDelete={selected}
pluralizedItemName={i18n._(t`Jobs`)}
pluralizedItemName={t`Jobs`}
cannotDelete={item =>
isJobRunning(item.status) ||
!item.summary_fields.user_capabilities.delete
}
errorMessage={plural(cannotDeleteItems.length, {
one:
'The selected job cannot be deleted due to insufficient permission or a running job status',
other:
'The selected jobs cannot be deleted due to insufficient permissions or a running job status',
})}
errorMessage={
<Plural
value={cannotDeleteItems.length}
one="The selected job cannot be deleted due to insufficient permission or a running job status"
other="The selected jobs cannot be deleted due to insufficient permissions or a running job status"
/>
}
/>,
<JobListCancelButton
key="cancel"
@ -275,10 +273,10 @@ function JobList({ i18n, defaultParams, showTypeColumn = false }) {
<AlertModal
isOpen
variant="error"
title={i18n._(t`Error!`)}
title={t`Error!`}
onClose={clearDeletionError}
>
{i18n._(t`Failed to delete one or more jobs.`)}
{t`Failed to delete one or more jobs.`}
<ErrorDetail error={deletionError} />
</AlertModal>
)}
@ -286,10 +284,10 @@ function JobList({ i18n, defaultParams, showTypeColumn = false }) {
<AlertModal
isOpen
variant="error"
title={i18n._(t`Error!`)}
title={t`Error!`}
onClose={dismissCancelError}
>
{i18n._(t`Failed to cancel one or more jobs.`)}
{t`Failed to cancel one or more jobs.`}
<ErrorDetail error={cancelError} />
</AlertModal>
)}
@ -297,4 +295,4 @@ function JobList({ i18n, defaultParams, showTypeColumn = false }) {
);
}
export default withI18n()(JobList);
export default JobList;

View File

@ -320,10 +320,8 @@ describe('<JobList />', () => {
wrapper.update();
const deleteButton = wrapper.find('ToolbarDeleteButton');
expect(deleteButton.find('Tooltip').prop('content').props.children).toEqual(
'The selected jobs cannot be deleted due to insufficient permissions or a running job status: job 1, job 2'
);
const deleteButton = wrapper.find('ToolbarDeleteButton').find('Button');
expect(deleteButton.prop('isDisabled')).toBe(true);
jest.restoreAllMocks();
});

View File

@ -17,7 +17,6 @@ import {
DropdownItem,
Tooltip,
} from '@patternfly/react-core';
import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
import AlertModal from '../AlertModal';
import { KebabifiedContext } from '../../contexts/Kebabified';
@ -95,7 +94,6 @@ function ToolbarDeleteButton({
deleteDetailsRequests,
warningMessage,
deleteMessage,
i18n,
cannotDelete,
}) {
const { isKebabified, onKebabModalChange } = useContext(KebabifiedContext);
@ -145,21 +143,24 @@ function ToolbarDeleteButton({
if (itemsToDelete.some(cannotDelete)) {
return (
<div>
{errorMessage
? `${errorMessage}: ${itemsUnableToDelete}`
: i18n._(
t`You do not have permission to delete ${pluralizedItemName}: ${itemsUnableToDelete}`
)}
{errorMessage ? (
<>
<span>{errorMessage}</span>
<span>{`: ${itemsUnableToDelete}`}</span>
</>
) : (
t`You do not have permission to delete ${pluralizedItemName}: ${itemsUnableToDelete}`
)}
</div>
);
}
if (itemsToDelete.length) {
return i18n._(t`Delete`);
return t`Delete`;
}
return i18n._(t`Select a row to delete`);
return t`Select a row to delete`;
};
const modalTitle = i18n._(t`Delete ${pluralizedItemName}?`);
const modalTitle = t`Delete ${pluralizedItemName}?`;
const isDisabled =
itemsToDelete.length === 0 || itemsToDelete.some(cannotDelete);
@ -201,7 +202,7 @@ function ToolbarDeleteButton({
return (
<AlertModal
isOpen={deleteMessageError}
title={i18n._(t`Error!`)}
title={t`Error!`}
onClose={() => {
toggleModal(false);
setDeleteMessageError();
@ -230,7 +231,7 @@ function ToolbarDeleteButton({
toggleModal(true);
}}
>
{i18n._(t`Delete`)}
{t`Delete`}
</DropdownItem>
</Tooltip>
) : (
@ -240,11 +241,11 @@ function ToolbarDeleteButton({
variant="secondary"
isLoading={isLoading}
spinnerAriaValueText={isLoading ? 'Loading' : undefined}
aria-label={i18n._(t`Delete`)}
aria-label={t`Delete`}
onClick={() => toggleModal(true)}
isDisabled={isDisabled}
>
{i18n._(t`Delete`)}
{t`Delete`}
</Button>
</div>
</Tooltip>
@ -261,25 +262,25 @@ function ToolbarDeleteButton({
ouiaId="delete-modal-confirm"
key="delete"
variant="danger"
aria-label={i18n._(t`confirm delete`)}
aria-label={t`confirm delete`}
isDisabled={Boolean(
deleteDetails && itemsToDelete[0]?.type === 'credential_type'
)}
onClick={handleDelete}
>
{i18n._(t`Delete`)}
{t`Delete`}
</Button>,
<Button
key="cancel"
variant="link"
aria-label={i18n._(t`cancel delete`)}
aria-label={t`cancel delete`}
onClick={() => toggleModal(false)}
>
{i18n._(t`Cancel`)}
{t`Cancel`}
</Button>,
]}
>
<div>{i18n._(t`This action will delete the following:`)}</div>
<div>{t`This action will delete the following:`}</div>
{itemsToDelete.map(item => (
<span key={item.id}>
<strong>{item.name || item.username || item.image}</strong>
@ -303,16 +304,14 @@ ToolbarDeleteButton.propTypes = {
onDelete: func.isRequired,
itemsToDelete: arrayOf(ItemToDelete).isRequired,
pluralizedItemName: string,
errorMessage: string,
warningMessage: node,
cannotDelete: func,
};
ToolbarDeleteButton.defaultProps = {
pluralizedItemName: 'Items',
errorMessage: '',
warningMessage: null,
cannotDelete: item => !item.summary_fields.user_capabilities.delete,
};
export default withI18n()(ToolbarDeleteButton);
export default ToolbarDeleteButton;

View File

@ -1,5 +1,6 @@
import React from 'react';
import { act } from 'react-dom/test-utils';
import {
mountWithContexts,
waitForElement,

View File

@ -1,7 +1,6 @@
import React, { Fragment, useEffect, useState, useCallback } from 'react';
import { useLocation, Link } from 'react-router-dom';
import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
import { t, Plural } from '@lingui/macro';
import { Card, DropdownItem } from '@patternfly/react-core';
import {
JobTemplatesAPI,
@ -20,7 +19,7 @@ import AddDropDownButton from '../AddDropDownButton';
import TemplateListItem from './TemplateListItem';
import { relatedResourceDeleteRequests } from '../../util/getRelatedResourceDeleteDetails';
function TemplateList({ defaultParams, i18n }) {
function TemplateList({ defaultParams }) {
// The type value in const qsConfig below does not have a space between job_template and
// workflow_job_template so the params sent to the API match what the api expects.
const qsConfig = getQSConfig(
@ -138,8 +137,8 @@ function TemplateList({ defaultParams, i18n }) {
const canAddWFJT =
wfjtActions && Object.prototype.hasOwnProperty.call(wfjtActions, 'POST');
const addTemplate = i18n._(t`Add job template`);
const addWFTemplate = i18n._(t`Add workflow template`);
const addTemplate = t`Add job template`;
const addWFTemplate = t`Add workflow template`;
const addDropDownButton = [];
if (canAddJT) {
addDropDownButton.push(
@ -181,37 +180,37 @@ function TemplateList({ defaultParams, i18n }) {
hasContentLoading={isLoading || isDeleteLoading}
items={templates}
itemCount={count}
pluralizedItemName={i18n._(t`Templates`)}
pluralizedItemName={t`Templates`}
qsConfig={qsConfig}
onRowClick={handleSelect}
toolbarSearchColumns={[
{
name: i18n._(t`Name`),
name: t`Name`,
key: 'name__icontains',
isDefault: true,
},
{
name: i18n._(t`Description`),
name: t`Description`,
key: 'description__icontains',
},
{
name: i18n._(t`Type`),
name: t`Type`,
key: 'or__type',
options: [
[`job_template`, i18n._(t`Job Template`)],
[`workflow_job_template`, i18n._(t`Workflow Template`)],
[`job_template`, t`Job Template`],
[`workflow_job_template`, t`Workflow Template`],
],
},
{
name: i18n._(t`Playbook name`),
name: t`Playbook name`,
key: 'job_template__playbook__icontains',
},
{
name: i18n._(t`Created By (Username)`),
name: t`Created By (Username)`,
key: 'created_by__username__icontains',
},
{
name: i18n._(t`Modified By (Username)`),
name: t`Modified By (Username)`,
key: 'modified_by__username__icontains',
},
]}
@ -219,12 +218,10 @@ function TemplateList({ defaultParams, i18n }) {
toolbarRelatedSearchableKeys={relatedSearchableKeys}
headerRow={
<HeaderRow qsConfig={qsConfig} isExpandable>
<HeaderCell sortKey="name">{i18n._(t`Name`)}</HeaderCell>
<HeaderCell sortKey="type">{i18n._(t`Type`)}</HeaderCell>
<HeaderCell sortKey="last_job_run">
{i18n._(t`Last Ran`)}
</HeaderCell>
<HeaderCell>{i18n._(t`Actions`)}</HeaderCell>
<HeaderCell sortKey="name">{t`Name`}</HeaderCell>
<HeaderCell sortKey="type">{t`Type`}</HeaderCell>
<HeaderCell sortKey="last_job_run">{t`Last Ran`}</HeaderCell>
<HeaderCell>{t`Actions`}</HeaderCell>
</HeaderRow>
}
renderToolbar={props => (
@ -240,12 +237,15 @@ function TemplateList({ defaultParams, i18n }) {
key="delete"
onDelete={handleTemplateDelete}
itemsToDelete={selected}
pluralizedItemName={i18n._(t`Templates`)}
pluralizedItemName={t`Templates`}
deleteDetailsRequests={deleteDetailsRequests}
deleteMessage={i18n._(
'{numItemsToDelete, plural, one {This template is currently being used by some workflow nodes. Are you sure you want to delete it?} other {Deleting these templates could impact some workflow nodes that rely on them. Are you sure you want to delete anyway?}}',
{ numItemsToDelete: selected.length }
)}
deleteMessage={
<Plural
value={selected.length}
one="This template is currently being used by some workflow nodes. Are you sure you want to delete it?"
other="Deleting these templates could impact some workflow nodes that rely on them. Are you sure you want to delete anyway?"
/>
}
/>,
]}
/>
@ -266,17 +266,17 @@ function TemplateList({ defaultParams, i18n }) {
/>
</Card>
<AlertModal
aria-label={i18n._(t`Deletion Error`)}
aria-label={t`Deletion Error`}
isOpen={deletionError}
variant="error"
title={i18n._(t`Error!`)}
title={t`Error!`}
onClose={clearDeletionError}
>
{i18n._(t`Failed to delete one or more templates.`)}
{t`Failed to delete one or more templates.`}
<ErrorDetail error={deletionError} />
</AlertModal>
</Fragment>
);
}
export default withI18n()(TemplateList);
export default TemplateList;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,6 @@
import React, { useEffect, useCallback } from 'react';
import { useLocation } from 'react-router-dom';
import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
import { t, Plural } from '@lingui/macro';
import { Card, PageSection } from '@patternfly/react-core';
import { CredentialsAPI } from '../../../api';
import useSelected from '../../../util/useSelected';
@ -27,7 +26,7 @@ const QS_CONFIG = getQSConfig('credential', {
order_by: 'name',
});
function CredentialList({ i18n }) {
function CredentialList() {
const location = useLocation();
const {
result: {
@ -121,28 +120,28 @@ function CredentialList({ i18n }) {
toolbarRelatedSearchableKeys={relatedSearchableKeys}
toolbarSearchColumns={[
{
name: i18n._(t`Name`),
name: t`Name`,
key: 'name__icontains',
isDefault: true,
},
{
name: i18n._(t`Description`),
name: t`Description`,
key: 'description__icontains',
},
{
name: i18n._(t`Created By (Username)`),
name: t`Created By (Username)`,
key: 'created_by__username__icontains',
},
{
name: i18n._(t`Modified By (Username)`),
name: t`Modified By (Username)`,
key: 'modified_by__username__icontains',
},
]}
headerRow={
<HeaderRow qsConfig={QS_CONFIG}>
<HeaderCell sortKey="name">{i18n._(t`Name`)}</HeaderCell>
<HeaderCell>{i18n._(t`Type`)}</HeaderCell>
<HeaderCell alignRight>{i18n._(t`Actions`)}</HeaderCell>
<HeaderCell sortKey="name">{t`Name`}</HeaderCell>
<HeaderCell>{t`Type`}</HeaderCell>
<HeaderCell alignRight>{t`Actions`}</HeaderCell>
</HeaderRow>
}
renderRow={(item, index) => (
@ -173,12 +172,15 @@ function CredentialList({ i18n }) {
key="delete"
onDelete={handleDelete}
itemsToDelete={selected}
pluralizedItemName={i18n._(t`Credentials`)}
pluralizedItemName={t`Credentials`}
deleteDetailsRequests={deleteDetailsRequests}
deleteMessage={i18n._(
'{numItemsToDelete, plural, one {This credential is currently being used by other resources. Are you sure you want to delete it?} other {Deleting these credentials could impact other resources that rely on them. Are you sure you want to delete anyway?}}',
{ numItemsToDelete: selected.length }
)}
deleteMessage={
<Plural
value={selected.length}
one="This credential is currently being used by other resources. Are you sure you want to delete it?"
other="Deleting these credentials could impact other resources that rely on them. Are you sure you want to delete anyway?"
/>
}
/>,
]}
/>
@ -186,17 +188,17 @@ function CredentialList({ i18n }) {
/>
</Card>
<AlertModal
aria-label={i18n._(t`Deletion Error`)}
aria-label={t`Deletion Error`}
isOpen={deletionError}
variant="error"
title={i18n._(t`Error!`)}
title={t`Error!`}
onClose={clearDeletionError}
>
{i18n._(t`Failed to delete one or more credentials.`)}
{t`Failed to delete one or more credentials.`}
<ErrorDetail error={deletionError} />
</AlertModal>
</PageSection>
);
}
export default withI18n()(CredentialList);
export default CredentialList;

View File

@ -1,7 +1,7 @@
import React, { useEffect, useCallback } from 'react';
import { useLocation, useRouteMatch } from 'react-router-dom';
import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
import { t, Plural } from '@lingui/macro';
import { Card, PageSection } from '@patternfly/react-core';
import { CredentialTypesAPI } from '../../../api';
@ -28,7 +28,7 @@ const QS_CONFIG = getQSConfig('credential-type', {
managed_by_tower: false,
});
function CredentialTypeList({ i18n }) {
function CredentialTypeList() {
const location = useLocation();
const match = useRouteMatch();
@ -119,25 +119,25 @@ function CredentialTypeList({ i18n }) {
hasContentLoading={isLoading || deleteLoading}
items={credentialTypes}
itemCount={credentialTypesCount}
pluralizedItemName={i18n._(t`Credential Types`)}
pluralizedItemName={t`Credential Types`}
qsConfig={QS_CONFIG}
onRowClick={handleSelect}
toolbarSearchColumns={[
{
name: i18n._(t`Name`),
name: t`Name`,
key: 'name__icontains',
isDefault: true,
},
{
name: i18n._(t`Description`),
name: t`Description`,
key: 'description__icontains',
},
{
name: i18n._(t`Created By (Username)`),
name: t`Created By (Username)`,
key: 'created_by__username__icontains',
},
{
name: i18n._(t`Modified By (Username)`),
name: t`Modified By (Username)`,
key: 'modified_by__username__icontains',
},
]}
@ -165,20 +165,23 @@ function CredentialTypeList({ i18n }) {
key="delete"
onDelete={handleDelete}
itemsToDelete={selected}
pluralizedItemName={i18n._(t`Credential Types`)}
pluralizedItemName={t`Credential Types`}
deleteDetailsRequests={deleteDetailsRequests}
deleteMessage={i18n._(
'{numItemsToDelete, plural, one {This credential type is currently being used by some credentials and cannot be deleted.} other {Credential types that are being used by credentials cannot be deleted. Are you sure you want to delete anyway?}}',
{ numItemsToDelete: selected.length }
)}
deleteMessage={
<Plural
value={selected.length}
one="This credential type is currently being used by some credentials and cannot be deleted."
other="Credential types that are being used by credentials cannot be deleted. Are you sure you want to delete anyway?"
/>
}
/>,
]}
/>
)}
headerRow={
<HeaderRow qsConfig={QS_CONFIG}>
<HeaderCell sortKey="name">{i18n._(t`Name`)}</HeaderCell>
<HeaderCell>{i18n._(t`Actions`)}</HeaderCell>
<HeaderCell sortKey="name">{t`Name`}</HeaderCell>
<HeaderCell>{t`Actions`}</HeaderCell>
</HeaderRow>
}
renderRow={(credentialType, index) => (
@ -201,17 +204,17 @@ function CredentialTypeList({ i18n }) {
</Card>
</PageSection>
<AlertModal
aria-label={i18n._(t`Deletion error`)}
aria-label={t`Deletion error`}
isOpen={deletionError}
onClose={clearDeletionError}
title={i18n._(t`Error`)}
title={t`Error`}
variant="error"
>
{i18n._(t`Failed to delete one or more credential types.`)}
{t`Failed to delete one or more credential types.`}
<ErrorDetail error={deletionError} />
</AlertModal>
</>
);
}
export default withI18n()(CredentialTypeList);
export default CredentialTypeList;

View File

@ -1,7 +1,6 @@
import React, { useEffect, useCallback } from 'react';
import { useLocation, useRouteMatch } from 'react-router-dom';
import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
import { t, Plural } from '@lingui/macro';
import { Card, PageSection } from '@patternfly/react-core';
import { ExecutionEnvironmentsAPI } from '../../../api';
@ -28,7 +27,7 @@ const QS_CONFIG = getQSConfig('execution_environments', {
order_by: 'name',
});
function ExecutionEnvironmentList({ i18n }) {
function ExecutionEnvironmentList() {
const location = useLocation();
const match = useRouteMatch();
@ -118,46 +117,46 @@ function ExecutionEnvironmentList({ i18n }) {
hasContentLoading={isLoading || deleteLoading}
items={executionEnvironments}
itemCount={executionEnvironmentsCount}
pluralizedItemName={i18n._(t`Execution Environments`)}
pluralizedItemName={t`Execution Environments`}
qsConfig={QS_CONFIG}
onRowClick={handleSelect}
toolbarSearchableKeys={searchableKeys}
toolbarRelatedSearchableKeys={relatedSearchableKeys}
toolbarSearchColumns={[
{
name: i18n._(t`Name`),
name: t`Name`,
key: 'name__icontains',
isDefault: true,
},
{
name: i18n._(t`Image`),
name: t`Image`,
key: 'image__icontains',
},
]}
toolbarSortColumns={[
{
name: i18n._(t`Image`),
name: t`Image`,
key: 'image',
},
{
name: i18n._(t`Created`),
name: t`Created`,
key: 'created',
},
{
name: i18n._(t`Organization`),
name: t`Organization`,
key: 'organization',
},
{
name: i18n._(t`Description`),
name: t`Description`,
key: 'description',
},
]}
headerRow={
<HeaderRow qsConfig={QS_CONFIG}>
<HeaderCell sortKey="name">{i18n._(t`Name`)}</HeaderCell>
<HeaderCell>{i18n._(t`Image`)}</HeaderCell>
<HeaderCell>{i18n._(t`Organization`)}</HeaderCell>
<HeaderCell>{i18n._(t`Actions`)}</HeaderCell>
<HeaderCell sortKey="name">{t`Name`}</HeaderCell>
<HeaderCell>{t`Image`}</HeaderCell>
<HeaderCell>{t`Organization`}</HeaderCell>
<HeaderCell>{t`Actions`}</HeaderCell>
</HeaderRow>
}
renderToolbar={props => (
@ -182,12 +181,15 @@ function ExecutionEnvironmentList({ i18n }) {
key="delete"
onDelete={handleDelete}
itemsToDelete={selected}
pluralizedItemName={i18n._(t`Execution Environments`)}
pluralizedItemName={t`Execution Environments`}
deleteDetailsRequests={deleteDetailsRequests}
deleteMessage={i18n._(
'{numItemsToDelete, plural, one {This execution environment is currently being used by other resources. Are you sure you want to delete it?} other {Deleting these execution environemnts could impact other resources that rely on them. Are you sure you want to delete anyway?}}',
{ numItemsToDelete: selected.length }
)}
deleteMessage={
<Plural
value={selected.length}
one="This execution environment is currently being used by other resources. Are you sure you want to delete it?"
other="These execution environments could be in use by other resources that rely on them. Are you sure you want to delete them anyway?"
/>
}
/>,
]}
/>
@ -214,17 +216,17 @@ function ExecutionEnvironmentList({ i18n }) {
</Card>
</PageSection>
<AlertModal
aria-label={i18n._(t`Deletion error`)}
aria-label={t`Deletion error`}
isOpen={deletionError}
onClose={clearDeletionError}
title={i18n._(t`Error`)}
title={t`Error`}
variant="error"
>
{i18n._(t`Failed to delete one or more execution environments`)}
{t`Failed to delete one or more execution environments`}
<ErrorDetail error={deletionError} />
</AlertModal>
</>
);
}
export default withI18n()(ExecutionEnvironmentList);
export default ExecutionEnvironmentList;

View File

@ -1,7 +1,7 @@
import React, { useEffect, useCallback } from 'react';
import { useLocation, useRouteMatch, Link } from 'react-router-dom';
import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
import { t, Plural } from '@lingui/macro';
import { Card, PageSection, DropdownItem } from '@patternfly/react-core';
import { InstanceGroupsAPI } from '../../../api';
@ -43,7 +43,7 @@ function modifyInstanceGroups(items = []) {
});
}
function InstanceGroupList({ i18n }) {
function InstanceGroupList() {
const location = useLocation();
const match = useRouteMatch();
@ -127,7 +127,7 @@ function InstanceGroupList({ i18n }) {
return !item.summary_fields.user_capabilities.delete;
}
const pluralizedItemName = i18n._(t`Instance Groups`);
const pluralizedItemName = t`Instance Groups`;
let errorMessageDelete = '';
@ -140,9 +140,7 @@ function InstanceGroupList({ i18n }) {
if (itemsUnableToDelete) {
if (modifiedSelected.some(cannotDelete)) {
errorMessageDelete = i18n._(
t`You do not have permission to delete ${pluralizedItemName}: ${itemsUnableToDelete}. `
);
errorMessageDelete = t`You do not have permission to delete ${pluralizedItemName}: ${itemsUnableToDelete}. `;
}
}
@ -150,12 +148,12 @@ function InstanceGroupList({ i18n }) {
errorMessageDelete = errorMessageDelete.concat('\n');
}
errorMessageDelete = errorMessageDelete.concat(
i18n._(t`The tower instance group cannot be deleted.`)
t`The tower instance group cannot be deleted.`
);
}
const addContainerGroup = i18n._(t`Add container group`);
const addInstanceGroup = i18n._(t`Add instance group`);
const addContainerGroup = t`Add container group`;
const addInstanceGroup = t`Add instance group`;
const addButton = (
<AddDropDownButton
@ -218,26 +216,29 @@ function InstanceGroupList({ i18n }) {
key="delete"
onDelete={handleDelete}
itemsToDelete={modifiedSelected}
pluralizedItemName={i18n._(t`Instance Groups`)}
pluralizedItemName={t`Instance Groups`}
errorMessage={errorMessageDelete}
deleteDetailsRequests={deleteDetailsRequests}
deleteMessage={i18n._(
'{numItemsToDelete, plural, one {This instance group is currently being by other resources. Are you sure you want to delete it?} other {Deleting these instance groups could impact other resources that rely on them. Are you sure you want to delete anyway?}}',
{ numItemsToDelete: selected.length }
)}
deleteMessage={
<Plural
value={selected.length}
one="This instance group is currently being by other resources. Are you sure you want to delete it?"
other="Deleting these instance groups could impact other resources that rely on them. Are you sure you want to delete anyway?"
/>
}
/>,
]}
/>
)}
headerRow={
<HeaderRow qsConfig={QS_CONFIG}>
<HeaderCell sortKey="name">{i18n._(t`Name`)}</HeaderCell>
<HeaderCell>{i18n._(t`Type`)}</HeaderCell>
<HeaderCell>{i18n._(t`Running Jobs`)}</HeaderCell>
<HeaderCell>{i18n._(t`Total Jobs`)}</HeaderCell>
<HeaderCell>{i18n._(t`Instances`)}</HeaderCell>
<HeaderCell>{i18n._(t`Capacity`)}</HeaderCell>
<HeaderCell>{i18n._(t`Actions`)}</HeaderCell>
<HeaderCell sortKey="name">{t`Name`}</HeaderCell>
<HeaderCell>{t`Type`}</HeaderCell>
<HeaderCell>{t`Running Jobs`}</HeaderCell>
<HeaderCell>{t`Total Jobs`}</HeaderCell>
<HeaderCell>{t`Instances`}</HeaderCell>
<HeaderCell>{t`Capacity`}</HeaderCell>
<HeaderCell>{t`Actions`}</HeaderCell>
</HeaderRow>
}
renderRow={(instanceGroup, index) => (
@ -256,17 +257,17 @@ function InstanceGroupList({ i18n }) {
</Card>
</PageSection>
<AlertModal
aria-label={i18n._(t`Deletion error`)}
aria-label={t`Deletion error`}
isOpen={deletionError}
onClose={clearDeletionError}
title={i18n._(t`Error`)}
title={t`Error`}
variant="error"
>
{i18n._(t`Failed to delete one or more instance groups.`)}
{t`Failed to delete one or more instance groups.`}
<ErrorDetail error={deletionError} />
</AlertModal>
</>
);
}
export default withI18n()(InstanceGroupList);
export default InstanceGroupList;

View File

@ -1,7 +1,6 @@
import React, { useState, useCallback, useEffect } from 'react';
import { useLocation, useRouteMatch, Link } from 'react-router-dom';
import { withI18n } from '@lingui/react';
import { t, plural } from '@lingui/macro';
import { t, Plural } from '@lingui/macro';
import { Card, PageSection, DropdownItem } from '@patternfly/react-core';
import { InventoriesAPI } from '../../../api';
import useRequest, { useDeleteItems } from '../../../util/useRequest';
@ -25,7 +24,7 @@ const QS_CONFIG = getQSConfig('inventory', {
order_by: 'name',
});
function InventoryList({ i18n }) {
function InventoryList() {
const location = useLocation();
const match = useRouteMatch();
const [selected, setSelected] = useState([]);
@ -132,8 +131,8 @@ function InventoryList({ i18n }) {
selected[0]
);
const addInventory = i18n._(t`Add inventory`);
const addSmartInventory = i18n._(t`Add smart inventory`);
const addInventory = t`Add inventory`;
const addSmartInventory = t`Add smart inventory`;
const addButton = (
<AddDropDownButton
key="add"
@ -166,30 +165,30 @@ function InventoryList({ i18n }) {
hasContentLoading={hasContentLoading}
items={inventories}
itemCount={itemCount}
pluralizedItemName={i18n._(t`Inventories`)}
pluralizedItemName={t`Inventories`}
qsConfig={QS_CONFIG}
toolbarSearchColumns={[
{
name: i18n._(t`Name`),
name: t`Name`,
key: 'name__icontains',
isDefault: true,
},
{
name: i18n._(t`Description`),
name: t`Description`,
key: 'description__icontains',
},
{
name: i18n._(t`Created By (Username)`),
name: t`Created By (Username)`,
key: 'created_by__username__icontains',
},
{
name: i18n._(t`Modified By (Username)`),
name: t`Modified By (Username)`,
key: 'modified_by__username__icontains',
},
]}
toolbarSortColumns={[
{
name: i18n._(t`Name`),
name: t`Name`,
key: 'name',
},
]}
@ -197,11 +196,11 @@ function InventoryList({ i18n }) {
toolbarRelatedSearchableKeys={relatedSearchableKeys}
headerRow={
<HeaderRow qsConfig={QS_CONFIG}>
<HeaderCell sortKey="name">{i18n._(t`Name`)}</HeaderCell>
<HeaderCell>{i18n._(t`Status`)}</HeaderCell>
<HeaderCell>{i18n._(t`Type`)}</HeaderCell>
<HeaderCell>{i18n._(t`Organization`)}</HeaderCell>
<HeaderCell>{i18n._(t`Actions`)}</HeaderCell>
<HeaderCell sortKey="name">{t`Name`}</HeaderCell>
<HeaderCell>{t`Status`}</HeaderCell>
<HeaderCell>{t`Type`}</HeaderCell>
<HeaderCell>{t`Organization`}</HeaderCell>
<HeaderCell>{t`Actions`}</HeaderCell>
</HeaderRow>
}
renderToolbar={props => (
@ -217,14 +216,22 @@ function InventoryList({ i18n }) {
key="delete"
onDelete={handleInventoryDelete}
itemsToDelete={selected}
pluralizedItemName={i18n._(t`Inventories`)}
pluralizedItemName={t`Inventories`}
deleteDetailsRequests={deleteDetailsRequests}
warningMessage={plural(selected.length, {
one:
'The inventory will be in a pending status until the final delete is processed.',
other:
'The inventories will be in a pending status until the final delete is processed.',
})}
deleteMessage={
<Plural
value={selected.length}
one="This invetory is currently being used by some temeplates. Are you sure you want to delete it?"
other="Deleting these inventories could impact some templates that rely on them. Are you sure you want to delete anyway?"
/>
}
warningMessage={
<Plural
value={selected.length}
one="The inventory will be in a pending status until the final delete is processed."
other="The inventories will be in a pending status until the final delete is processed."
/>
}
/>,
]}
/>
@ -251,15 +258,15 @@ function InventoryList({ i18n }) {
<AlertModal
isOpen={deletionError}
variant="error"
aria-label={i18n._(t`Deletion Error`)}
title={i18n._(t`Error!`)}
aria-label={t`Deletion Error`}
title={t`Error!`}
onClose={clearDeletionError}
>
{i18n._(t`Failed to delete one or more inventories.`)}
{t`Failed to delete one or more inventories.`}
<ErrorDetail error={deletionError} />
</AlertModal>
</PageSection>
);
}
export default withI18n()(InventoryList);
export default InventoryList;

View File

@ -1,7 +1,6 @@
import React, { useCallback, useEffect } from 'react';
import { useParams, useLocation } from 'react-router-dom';
import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
import { t, Plural } from '@lingui/macro';
import { Button, Tooltip } from '@patternfly/react-core';
import useRequest, {
@ -29,7 +28,7 @@ const QS_CONFIG = getQSConfig('inventory', {
order_by: 'name',
});
function InventorySourceList({ i18n }) {
function InventorySourceList() {
const { inventoryType, id } = useParams();
const { search } = useLocation();
@ -159,7 +158,7 @@ function InventorySourceList({ i18n }) {
}
items={sources}
itemCount={sourceCount}
pluralizedItemName={i18n._(t`Inventory Sources`)}
pluralizedItemName={t`Inventory Sources`}
qsConfig={QS_CONFIG}
renderToolbar={props => (
<DatalistToolbar
@ -178,27 +177,30 @@ function InventorySourceList({ i18n }) {
key="delete"
onDelete={handleDelete}
itemsToDelete={selected}
pluralizedItemName={i18n._(t`Inventory Sources`)}
pluralizedItemName={t`Inventory Sources`}
deleteDetailsRequests={deleteDetailsRequests}
deleteMessage={i18n._(
'{numItemsToDelete, plural, one {This inventory source is currently being used by other resources that rely on it. Are you sure you want to delete it?} other {Deleting these inventory sources could impact other resources that rely on them. Are you sure you want to delete anyway?}}',
{ numItemsToDelete: selected.length }
)}
deleteMessage={
<Plural
value={selected.length}
one="This inventory source is currently being used by other resources that rely on it. Are you sure you want to delete it?"
other="Deleting these inventory sources could impact other resources that rely on them. Are you sure you want to delete anyway"
/>
}
/>,
...(canSyncSources
? [
<Tooltip
key="update"
content={i18n._(t`Sync all sources`)}
content={t`Sync all sources`}
position="top"
>
<Button
ouiaId="sync-all-button"
onClick={syncAll}
aria-label={i18n._(t`Sync all`)}
aria-label={t`Sync all`}
variant="secondary"
>
{i18n._(t`Sync all`)}
{t`Sync all`}
</Button>
</Tooltip>,
]
@ -227,30 +229,30 @@ function InventorySourceList({ i18n }) {
/>
{syncError && (
<AlertModal
aria-label={i18n._(t`Sync error`)}
aria-label={t`Sync error`}
isOpen={syncError}
variant="error"
title={i18n._(t`Error!`)}
title={t`Error!`}
onClose={dismissError}
>
{i18n._(t`Failed to sync some or all inventory sources.`)}
{t`Failed to sync some or all inventory sources.`}
<ErrorDetail error={syncError} />
</AlertModal>
)}
{(deletionError || deleteRelatedResourcesError) && (
<AlertModal
aria-label={i18n._(t`Delete error`)}
aria-label={t`Delete error`}
isOpen={deletionError || deleteRelatedResourcesError}
variant="error"
title={i18n._(t`Error!`)}
title={t`Error!`}
onClose={clearDeletionError}
>
{i18n._(t`Failed to delete one or more inventory sources.`)}
{t`Failed to delete one or more inventory sources.`}
<ErrorDetail error={deletionError || deleteRelatedResourcesError} />
</AlertModal>
)}
</>
);
}
export default withI18n()(InventorySourceList);
export default InventorySourceList;

View File

@ -1,7 +1,6 @@
import React, { useState, useEffect, useCallback } from 'react';
import { useLocation, useRouteMatch } from 'react-router-dom';
import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
import { t, Plural } from '@lingui/macro';
import { Card, PageSection } from '@patternfly/react-core';
import { OrganizationsAPI } from '../../../api';
@ -27,7 +26,7 @@ const QS_CONFIG = getQSConfig('organization', {
order_by: 'name',
});
function OrganizationsList({ i18n }) {
function OrganizationsList() {
const location = useLocation();
const match = useRouteMatch();
@ -130,24 +129,24 @@ function OrganizationsList({ i18n }) {
hasContentLoading={hasContentLoading}
items={organizations}
itemCount={organizationCount}
pluralizedItemName={i18n._(t`Organizations`)}
pluralizedItemName={t`Organizations`}
qsConfig={QS_CONFIG}
toolbarSearchColumns={[
{
name: i18n._(t`Name`),
name: t`Name`,
key: 'name__icontains',
isDefault: true,
},
{
name: i18n._(t`Description`),
name: t`Description`,
key: 'description__icontains',
},
{
name: i18n._(t`Created By (Username)`),
name: t`Created By (Username)`,
key: 'created_by__username__icontains',
},
{
name: i18n._(t`Modified By (Username)`),
name: t`Modified By (Username)`,
key: 'modified_by__username__icontains',
},
]}
@ -155,10 +154,10 @@ function OrganizationsList({ i18n }) {
toolbarRelatedSearchableKeys={relatedSearchableKeys}
headerRow={
<HeaderRow qsConfig={QS_CONFIG}>
<HeaderCell sortKey="name">{i18n._(t`Name`)}</HeaderCell>
<HeaderCell>{i18n._(t`Members`)}</HeaderCell>
<HeaderCell>{i18n._(t`Teams`)}</HeaderCell>
<HeaderCell>{i18n._(t`Actions`)}</HeaderCell>
<HeaderCell sortKey="name">{t`Name`}</HeaderCell>
<HeaderCell>{t`Members`}</HeaderCell>
<HeaderCell>{t`Teams`}</HeaderCell>
<HeaderCell>{t`Actions`}</HeaderCell>
</HeaderRow>
}
renderToolbar={props => (
@ -176,12 +175,15 @@ function OrganizationsList({ i18n }) {
key="delete"
onDelete={handleOrgDelete}
itemsToDelete={selected}
pluralizedItemName={i18n._(t`Organizations`)}
pluralizedItemName={t`Organizations`}
deleteDetailsRequests={deleteDetailsRequests}
deleteMessage={i18n._(
'{numItemsToDelete, plural, one {This organization is currently being by other resources. Are you sure you want to delete it?} other {Deleting these organizations could impact other resources that rely on them. Are you sure you want to delete anyway?}}',
{ numItemsToDelete: selected.length }
)}
deleteMessage={
<Plural
value={selected.length}
one="This organization is currently being by other resources. Are you sure you want to delete it?"
other="Deleting these organizations could impact other resources that rely on them. Are you sure you want to delete anyway?"
/>
}
/>,
]}
/>
@ -205,10 +207,10 @@ function OrganizationsList({ i18n }) {
<AlertModal
isOpen={deletionError}
variant="error"
title={i18n._(t`Error!`)}
title={t`Error!`}
onClose={clearDeletionError}
>
{i18n._(t`Failed to delete one or more organizations.`)}
{t`Failed to delete one or more organizations.`}
<ErrorDetail error={deletionError} />
</AlertModal>
</>
@ -216,4 +218,4 @@ function OrganizationsList({ i18n }) {
}
export { OrganizationsList as _OrganizationsList };
export default withI18n()(OrganizationsList);
export default OrganizationsList;

View File

@ -1,7 +1,6 @@
import React, { Fragment, useState, useEffect, useCallback } from 'react';
import { useLocation, useRouteMatch } from 'react-router-dom';
import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
import { t, Plural } from '@lingui/macro';
import { Card, PageSection } from '@patternfly/react-core';
import { ProjectsAPI } from '../../../api';
@ -29,7 +28,7 @@ const QS_CONFIG = getQSConfig('project', {
order_by: 'name',
});
function ProjectList({ i18n }) {
function ProjectList() {
const location = useLocation();
const match = useRouteMatch();
const [selected, setSelected] = useState([]);
@ -130,52 +129,52 @@ function ProjectList({ i18n }) {
hasContentLoading={hasContentLoading}
items={projects}
itemCount={itemCount}
pluralizedItemName={i18n._(t`Projects`)}
pluralizedItemName={t`Projects`}
qsConfig={QS_CONFIG}
onRowClick={handleSelect}
toolbarSearchColumns={[
{
name: i18n._(t`Name`),
name: t`Name`,
key: 'name__icontains',
isDefault: true,
},
{
name: i18n._(t`Description`),
name: t`Description`,
key: 'description__icontains',
},
{
name: i18n._(t`Type`),
name: t`Type`,
key: 'or__scm_type',
options: [
[``, i18n._(t`Manual`)],
[`git`, i18n._(t`Git`)],
[`svn`, i18n._(t`Subversion`)],
[`archive`, i18n._(t`Remote Archive`)],
[`insights`, i18n._(t`Red Hat Insights`)],
[``, t`Manual`],
[`git`, t`Git`],
[`svn`, t`Subversion`],
[`archive`, t`Remote Archive`],
[`insights`, t`Red Hat Insights`],
],
},
{
name: i18n._(t`Source Control URL`),
name: t`Source Control URL`,
key: 'scm_url__icontains',
},
{
name: i18n._(t`Modified By (Username)`),
name: t`Modified By (Username)`,
key: 'modified_by__username__icontains',
},
{
name: i18n._(t`Created By (Username)`),
name: t`Created By (Username)`,
key: 'created_by__username__icontains',
},
]}
toolbarSearchableKeys={searchableKeys}
toolbarRelatedSearchableKeys={relatedSearchableKeys}
headerRow={
<HeaderRow qsConfig={QS_CONFIG} isExpandable>
<HeaderCell sortKey="name">{i18n._(t`Name`)}</HeaderCell>
<HeaderCell>{i18n._(t`Status`)}</HeaderCell>
<HeaderCell>{i18n._(t`Type`)}</HeaderCell>
<HeaderCell>{i18n._(t`Revision`)}</HeaderCell>
<HeaderCell>{i18n._(t`Actions`)}</HeaderCell>
<HeaderRow qsConfig={QS_CONFIG}>
<HeaderCell sortKey="name">{t`Name`}</HeaderCell>
<HeaderCell>{t`Status`}</HeaderCell>
<HeaderCell>{t`Type`}</HeaderCell>
<HeaderCell>{t`Revision`}</HeaderCell>
<HeaderCell>{t`Actions`}</HeaderCell>
</HeaderRow>
}
renderToolbar={props => (
@ -198,12 +197,15 @@ function ProjectList({ i18n }) {
key="delete"
onDelete={handleProjectDelete}
itemsToDelete={selected}
pluralizedItemName={i18n._(t`Projects`)}
pluralizedItemName={t`Projects`}
deleteDetailsRequests={deleteDetailsRequests}
deleteMessage={i18n._(
'{numItemsToDelete, plural, one {This project is currently being used by other resources. Are you sure you want to delete it?} other {Deleting these projects could impact other resources that rely on them. Are you sure you want to delete anyway?}}',
{ numItemsToDelete: selected.length }
)}
deleteMessage={
<Plural
value={selected.length}
one="This project is currently being used by other resources. Are you sure you want to delete it?"
other="Deleting these projects could impact other resources that rely on them. Are you sure you want to delete anyway?"
/>
}
/>,
]}
/>
@ -230,15 +232,15 @@ function ProjectList({ i18n }) {
<AlertModal
isOpen={deletionError}
variant="error"
aria-label={i18n._(t`Deletion Error`)}
title={i18n._(t`Error!`)}
aria-label={t`Deletion Error`}
title={t`Error!`}
onClose={clearDeletionError}
>
{i18n._(t`Failed to delete one or more projects.`)}
{t`Failed to delete one or more projects.`}
<ErrorDetail error={deletionError} />
</AlertModal>
</Fragment>
);
}
export default withI18n()(ProjectList);
export default ProjectList;

View File

@ -1,7 +1,6 @@
import React, { useCallback, useEffect } from 'react';
import { useLocation, useRouteMatch } from 'react-router-dom';
import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
import { t, Plural } from '@lingui/macro';
import { Card, PageSection } from '@patternfly/react-core';
import { WorkflowApprovalsAPI } from '../../../api';
import PaginatedTable, {
@ -29,7 +28,7 @@ const QS_CONFIG = getQSConfig('workflow_approvals', {
order_by: '-started',
});
function WorkflowApprovalsList({ i18n }) {
function WorkflowApprovalsList() {
const location = useLocation();
const match = useRouteMatch();
@ -167,17 +166,17 @@ function WorkflowApprovalsList({ i18n }) {
}
items={workflowApprovals}
itemCount={count}
pluralizedItemName={i18n._(t`Workflow Approvals`)}
pluralizedItemName={t`Workflow Approvals`}
qsConfig={QS_CONFIG}
onRowClick={handleSelect}
toolbarSearchColumns={[
{
name: i18n._(t`Name`),
name: t`Name`,
key: 'name__icontains',
isDefault: true,
},
{
name: i18n._(t`Description`),
name: t`Description`,
key: 'description__icontains',
},
]}
@ -207,24 +206,28 @@ function WorkflowApprovalsList({ i18n }) {
key="delete"
onDelete={handleDelete}
itemsToDelete={selected}
pluralizedItemName={i18n._(t`Workflow Approvals`)}
pluralizedItemName={t`Workflow Approvals`}
cannotDelete={item =>
item.status === 'pending' ||
!item.summary_fields.user_capabilities.delete
}
errorMessage={i18n._(
t`These approvals cannot be deleted due to insufficient permissions or a pending job status`
)}
errorMessage={
<Plural
value={selected.length}
one="This approval cannot be deleted due to insufficient permissions or a pending job status"
other="These approvals cannot be deleted due to insufficient permissions or a pending job status"
/>
}
/>,
]}
/>
)}
headerRow={
<HeaderRow qsConfig={QS_CONFIG}>
<HeaderCell sortKey="name">{i18n._(t`Name`)}</HeaderCell>
<HeaderCell>{i18n._(t`Job`)}</HeaderCell>
<HeaderCell sortKey="started">{i18n._(t`Started`)}</HeaderCell>
<HeaderCell>{i18n._(t`Status`)}</HeaderCell>
<HeaderCell sortKey="name">{t`Name`}</HeaderCell>
<HeaderCell>{t`Job`}</HeaderCell>
<HeaderCell sortKey="started">{t`Started`}</HeaderCell>
<HeaderCell>{t`Status`}</HeaderCell>
</HeaderRow>
}
renderRow={(workflowApproval, index) => (
@ -247,10 +250,10 @@ function WorkflowApprovalsList({ i18n }) {
<AlertModal
isOpen={deletionError}
variant="error"
title={i18n._(t`Error!`)}
title={t`Error!`}
onClose={clearDeletionError}
>
{i18n._(t`Failed to delete one or more workflow approval.`)}
{t`Failed to delete one or more workflow approval.`}
<ErrorDetail error={deletionError} />
</AlertModal>
)}
@ -258,12 +261,12 @@ function WorkflowApprovalsList({ i18n }) {
<AlertModal
isOpen={actionError}
variant="error"
title={i18n._(t`Error!`)}
title={t`Error!`}
onClose={dismissActionError}
>
{approveApprovalError
? i18n._(t`Failed to approve one or more workflow approval.`)
: i18n._(t`Failed to deny one or more workflow approval.`)}
? t`Failed to approve one or more workflow approval.`
: t`Failed to deny one or more workflow approval.`}
<ErrorDetail error={actionError} />
</AlertModal>
)}
@ -271,4 +274,4 @@ function WorkflowApprovalsList({ i18n }) {
);
}
export default withI18n()(WorkflowApprovalsList);
export default WorkflowApprovalsList;