Add Preview, more and Show less for translation

Also, create a new custom component called `ChipGroup` to avoid repeat
code related to the total of chips to be translated.

See: https://www.patternfly.org/v4/documentation/react/components/chipgroup

closes:https://github.com/ansible/awx/issues/6861
This commit is contained in:
nixocio
2020-05-05 14:02:12 -04:00
parent bb0abf37e0
commit 8f6b654696
20 changed files with 319 additions and 229 deletions

View File

@@ -0,0 +1,24 @@
import React from 'react';
import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
import { ChipGroup as PFChipGroup } from '@patternfly/react-core';
import { number, shape } from 'prop-types';
function ChipGroup({ i18n, numChips, totalChips, ...props }) {
return (
<PFChipGroup
{...props}
numChips={numChips}
expandedText={i18n._(t`Show less`)}
collapsedText={i18n._(t`${totalChips - numChips} more`)}
/>
);
}
ChipGroup.propTypes = {
numChips: number.isRequired,
totalChips: number.isRequired,
i18n: shape({}).isRequired,
};
export default withI18n()(ChipGroup);

View File

@@ -0,0 +1,17 @@
import React from 'react';
import { mountWithContexts } from '@testUtils/enzymeHelpers';
import ChipGroup from './ChipGroup';
describe('ChipGroup', () => {
test('should mount properly', () => {
const wrapper = mountWithContexts(
<ChipGroup numChips={5} totalChips={10} />
);
expect(
wrapper
.find('ChipGroup')
.at(1)
.props().collapsedText
).toEqual('5 more');
});
});

View File

@@ -0,0 +1 @@
export { default } from './ChipGroup';

View File

@@ -14,10 +14,10 @@ import {
Button, Button,
ButtonVariant, ButtonVariant,
Chip, Chip,
ChipGroup,
InputGroup as PFInputGroup, InputGroup as PFInputGroup,
Modal, Modal,
} from '@patternfly/react-core'; } from '@patternfly/react-core';
import ChipGroup from '@components/ChipGroup';
import { withI18n } from '@lingui/react'; import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro'; import { t } from '@lingui/macro';
import styled from 'styled-components'; import styled from 'styled-components';
@@ -128,7 +128,7 @@ function Lookup(props) {
<SearchIcon /> <SearchIcon />
</SearchButton> </SearchButton>
<ChipHolder className="pf-c-form-control"> <ChipHolder className="pf-c-form-control">
<ChipGroup numChips={5}> <ChipGroup numChips={5} totalChips={items.length}>
{items.map(item => {items.map(item =>
renderItemChip({ renderItemChip({
item, item,

View File

@@ -6,10 +6,11 @@ import { Link } from 'react-router-dom';
import styled from 'styled-components'; import styled from 'styled-components';
import { toTitleCase } from '@util/strings'; import { toTitleCase } from '@util/strings';
import { Chip, ChipGroup, Divider } from '@patternfly/react-core'; import { Chip, Divider } from '@patternfly/react-core';
import { VariablesDetail } from '@components/CodeMirrorInput';
import CredentialChip from '@components/CredentialChip'; import CredentialChip from '@components/CredentialChip';
import ChipGroup from '@components/ChipGroup';
import { DetailList, Detail, UserDateDetail } from '@components/DetailList'; import { DetailList, Detail, UserDateDetail } from '@components/DetailList';
import { VariablesDetail } from '@components/CodeMirrorInput';
import PromptProjectDetail from './PromptProjectDetail'; import PromptProjectDetail from './PromptProjectDetail';
import PromptInventorySourceDetail from './PromptInventorySourceDetail'; import PromptInventorySourceDetail from './PromptInventorySourceDetail';
@@ -220,7 +221,10 @@ function PromptDetail({ i18n, resource, launchConfig = {} }) {
label={i18n._(t`Credentials`)} label={i18n._(t`Credentials`)}
rows={4} rows={4}
value={ value={
<ChipGroup numChips={5}> <ChipGroup
numChips={5}
totalChips={overrides.credentials.length}
>
{overrides.credentials.map(cred => ( {overrides.credentials.map(cred => (
<CredentialChip <CredentialChip
key={cred.id} key={cred.id}
@@ -258,7 +262,10 @@ function PromptDetail({ i18n, resource, launchConfig = {} }) {
fullWidth fullWidth
label={i18n._(t`Job Tags`)} label={i18n._(t`Job Tags`)}
value={ value={
<ChipGroup numChips={5}> <ChipGroup
numChips={5}
totalChips={overrides.job_tags.split(',').length}
>
{overrides.job_tags.split(',').map(jobTag => ( {overrides.job_tags.split(',').map(jobTag => (
<Chip key={jobTag} isReadOnly> <Chip key={jobTag} isReadOnly>
{jobTag} {jobTag}
@@ -273,7 +280,10 @@ function PromptDetail({ i18n, resource, launchConfig = {} }) {
fullWidth fullWidth
label={i18n._(t`Skip Tags`)} label={i18n._(t`Skip Tags`)}
value={ value={
<ChipGroup numChips={5}> <ChipGroup
numChips={5}
totalChips={overrides.skip_tags.split(',').length}
>
{overrides.skip_tags.split(',').map(skipTag => ( {overrides.skip_tags.split(',').map(skipTag => (
<Chip key={skipTag} isReadOnly> <Chip key={skipTag} isReadOnly>
{skipTag} {skipTag}

View File

@@ -3,10 +3,11 @@ import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro'; import { t } from '@lingui/macro';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { Chip, ChipGroup, List, ListItem } from '@patternfly/react-core'; import { Chip, List, ListItem } from '@patternfly/react-core';
import { Detail, DeletedDetail } from '@components/DetailList'; import { Detail, DeletedDetail } from '@components/DetailList';
import { VariablesDetail } from '@components/CodeMirrorInput'; import { VariablesDetail } from '@components/CodeMirrorInput';
import CredentialChip from '@components/CredentialChip'; import CredentialChip from '@components/CredentialChip';
import ChipGroup from '@components/ChipGroup';
function PromptInventorySourceDetail({ i18n, resource }) { function PromptInventorySourceDetail({ i18n, resource }) {
const { const {
@@ -120,7 +121,10 @@ function PromptInventorySourceDetail({ i18n, resource }) {
fullWidth fullWidth
label={i18n._(t`Regions`)} label={i18n._(t`Regions`)}
value={ value={
<ChipGroup numChips={5}> <ChipGroup
numChips={5}
totalChips={source_regions.split(',').length}
>
{source_regions.split(',').map(region => ( {source_regions.split(',').map(region => (
<Chip key={region} isReadOnly> <Chip key={region} isReadOnly>
{region} {region}
@@ -135,7 +139,10 @@ function PromptInventorySourceDetail({ i18n, resource }) {
fullWidth fullWidth
label={i18n._(t`Instance Filters`)} label={i18n._(t`Instance Filters`)}
value={ value={
<ChipGroup numChips={5}> <ChipGroup
numChips={5}
totalChips={instance_filters.split(',').length}
>
{instance_filters.split(',').map(filter => ( {instance_filters.split(',').map(filter => (
<Chip key={filter} isReadOnly> <Chip key={filter} isReadOnly>
{filter} {filter}
@@ -150,7 +157,7 @@ function PromptInventorySourceDetail({ i18n, resource }) {
fullWidth fullWidth
label={i18n._(t`Only Group By`)} label={i18n._(t`Only Group By`)}
value={ value={
<ChipGroup numChips={5}> <ChipGroup numChips={5} totalChips={group_by.split(',').length}>
{group_by.split(',').map(group => ( {group_by.split(',').map(group => (
<Chip key={group} isReadOnly> <Chip key={group} isReadOnly>
{group} {group}

View File

@@ -3,11 +3,12 @@ import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro'; import { t } from '@lingui/macro';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { Chip, ChipGroup, List, ListItem } from '@patternfly/react-core'; import { Chip, List, ListItem } from '@patternfly/react-core';
import CredentialChip from '@components/CredentialChip';
import ChipGroup from '@components/ChipGroup';
import Sparkline from '@components/Sparkline';
import { Detail, DeletedDetail } from '@components/DetailList'; import { Detail, DeletedDetail } from '@components/DetailList';
import { VariablesDetail } from '@components/CodeMirrorInput'; import { VariablesDetail } from '@components/CodeMirrorInput';
import CredentialChip from '@components/CredentialChip';
import Sparkline from '@components/Sparkline';
import { toTitleCase } from '@util/strings'; import { toTitleCase } from '@util/strings';
function PromptJobTemplateDetail({ i18n, resource }) { function PromptJobTemplateDetail({ i18n, resource }) {
@@ -174,7 +175,10 @@ function PromptJobTemplateDetail({ i18n, resource }) {
fullWidth fullWidth
label={i18n._(t`Credentials`)} label={i18n._(t`Credentials`)}
value={ value={
<ChipGroup numChips={5}> <ChipGroup
numChips={5}
totalChips={summary_fields.credentials.length}
>
{summary_fields.credentials.map(cred => ( {summary_fields.credentials.map(cred => (
<CredentialChip key={cred.id} credential={cred} isReadOnly /> <CredentialChip key={cred.id} credential={cred} isReadOnly />
))} ))}
@@ -187,7 +191,10 @@ function PromptJobTemplateDetail({ i18n, resource }) {
fullWidth fullWidth
label={i18n._(t`Labels`)} label={i18n._(t`Labels`)}
value={ value={
<ChipGroup numChips={5}> <ChipGroup
numChips={5}
totalChips={summary_fields.labels.results.length}
>
{summary_fields.labels.results.map(label => ( {summary_fields.labels.results.map(label => (
<Chip key={label.id} isReadOnly> <Chip key={label.id} isReadOnly>
{label.name} {label.name}
@@ -202,7 +209,7 @@ function PromptJobTemplateDetail({ i18n, resource }) {
fullWidth fullWidth
label={i18n._(t`Instance Groups`)} label={i18n._(t`Instance Groups`)}
value={ value={
<ChipGroup numChips={5}> <ChipGroup numChips={5} totalChips={instance_groups.length}>
{instance_groups.map(ig => ( {instance_groups.map(ig => (
<Chip key={ig.id} isReadOnly> <Chip key={ig.id} isReadOnly>
{ig.name} {ig.name}
@@ -217,7 +224,7 @@ function PromptJobTemplateDetail({ i18n, resource }) {
fullWidth fullWidth
label={i18n._(t`Job Tags`)} label={i18n._(t`Job Tags`)}
value={ value={
<ChipGroup numChips={5}> <ChipGroup numChips={5} totalChips={job_tags.split(',').length}>
{job_tags.split(',').map(jobTag => ( {job_tags.split(',').map(jobTag => (
<Chip key={jobTag} isReadOnly> <Chip key={jobTag} isReadOnly>
{jobTag} {jobTag}
@@ -232,7 +239,7 @@ function PromptJobTemplateDetail({ i18n, resource }) {
fullWidth fullWidth
label={i18n._(t`Skip Tags`)} label={i18n._(t`Skip Tags`)}
value={ value={
<ChipGroup numChips={5}> <ChipGroup numChips={5} totalChips={skip_tags.split(',').length}>
{skip_tags.split(',').map(skipTag => ( {skip_tags.split(',').map(skipTag => (
<Chip key={skipTag} isReadOnly> <Chip key={skipTag} isReadOnly>
{skipTag} {skipTag}

View File

@@ -3,8 +3,9 @@ import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro'; import { t } from '@lingui/macro';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { Chip, ChipGroup, List, ListItem } from '@patternfly/react-core'; import { Chip, List, ListItem } from '@patternfly/react-core';
import CredentialChip from '@components/CredentialChip'; import CredentialChip from '@components/CredentialChip';
import ChipGroup from '@components/ChipGroup';
import { Detail } from '@components/DetailList'; import { Detail } from '@components/DetailList';
import { VariablesDetail } from '@components/CodeMirrorInput'; import { VariablesDetail } from '@components/CodeMirrorInput';
import Sparkline from '@components/Sparkline'; import Sparkline from '@components/Sparkline';
@@ -108,7 +109,10 @@ function PromptWFJobTemplateDetail({ i18n, resource }) {
fullWidth fullWidth
label={i18n._(t`Labels`)} label={i18n._(t`Labels`)}
value={ value={
<ChipGroup numChips={5}> <ChipGroup
numChips={5}
totalChips={summary_fields.labels.results.length}
>
{summary_fields.labels.results.map(label => ( {summary_fields.labels.results.map(label => (
<Chip key={label.id} isReadOnly> <Chip key={label.id} isReadOnly>
{label.name} {label.name}

View File

@@ -4,7 +4,6 @@ import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro'; import { t } from '@lingui/macro';
import { import {
Chip, Chip,
ChipGroup,
DataListItem, DataListItem,
DataListItemRow, DataListItemRow,
DataListItemCells as PFDataListItemCells, DataListItemCells as PFDataListItemCells,
@@ -16,6 +15,7 @@ import DataListCell from '@components/DataListCell';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import styled from 'styled-components'; import styled from 'styled-components';
import ChipGroup from '@components/ChipGroup';
import { DetailList, Detail } from '@components/DetailList'; import { DetailList, Detail } from '@components/DetailList';
import { AccessRecord } from '@types'; import { AccessRecord } from '@types';
@@ -115,7 +115,7 @@ class ResourceAccessListItem extends React.Component {
<Detail <Detail
label={i18n._(t`User Roles`)} label={i18n._(t`User Roles`)}
value={ value={
<ChipGroup numChips={5}> <ChipGroup numChips={5} totalChips={userRoles.length}>
{userRoles.map(this.renderChip)} {userRoles.map(this.renderChip)}
</ChipGroup> </ChipGroup>
} }
@@ -125,7 +125,7 @@ class ResourceAccessListItem extends React.Component {
<Detail <Detail
label={i18n._(t`Team Roles`)} label={i18n._(t`Team Roles`)}
value={ value={
<ChipGroup numChips={5}> <ChipGroup numChips={5} totalChips={teamRoles.length}>
{teamRoles.map(this.renderChip)} {teamRoles.map(this.renderChip)}
</ChipGroup> </ChipGroup>
} }

View File

@@ -88,13 +88,9 @@ exports[`<ResourceAccessListItem /> initially renders succesfully 1`] = `
fullWidth={false} fullWidth={false}
label="Team Roles" label="Team Roles"
value={ value={
<ChipGroup <WithI18n
className=""
collapsedText="\${remaining} more"
defaultIsOpen={false}
expandedText="Show Less"
numChips={5} numChips={5}
withToolbar={false} totalChips={1}
> >
<Unknown <Unknown
isReadOnly={false} isReadOnly={false}
@@ -102,7 +98,7 @@ exports[`<ResourceAccessListItem /> initially renders succesfully 1`] = `
> >
Member Member
</Unknown> </Unknown>
</ChipGroup> </WithI18n>
} }
/> />
</DetailList> </DetailList>
@@ -151,13 +147,9 @@ exports[`<ResourceAccessListItem /> initially renders succesfully 1`] = `
fullWidth={false} fullWidth={false}
label="Team Roles" label="Team Roles"
value={ value={
<ChipGroup <WithI18n
className=""
collapsedText="\${remaining} more"
defaultIsOpen={false}
expandedText="Show Less"
numChips={5} numChips={5}
withToolbar={false} totalChips={1}
> >
<Unknown <Unknown
isReadOnly={false} isReadOnly={false}
@@ -165,7 +157,7 @@ exports[`<ResourceAccessListItem /> initially renders succesfully 1`] = `
> >
Member Member
</Unknown> </Unknown>
</ChipGroup> </WithI18n>
} }
/> />
</DetailList> </DetailList>
@@ -237,13 +229,9 @@ exports[`<ResourceAccessListItem /> initially renders succesfully 1`] = `
fullWidth={false} fullWidth={false}
label="Team Roles" label="Team Roles"
value={ value={
<ChipGroup <WithI18n
className=""
collapsedText="\${remaining} more"
defaultIsOpen={false}
expandedText="Show Less"
numChips={5} numChips={5}
withToolbar={false} totalChips={1}
> >
<Unknown <Unknown
isReadOnly={false} isReadOnly={false}
@@ -251,7 +239,7 @@ exports[`<ResourceAccessListItem /> initially renders succesfully 1`] = `
> >
Member Member
</Unknown> </Unknown>
</ChipGroup> </WithI18n>
} }
/> />
</DetailList> </DetailList>
@@ -644,13 +632,9 @@ exports[`<ResourceAccessListItem /> initially renders succesfully 1`] = `
fullWidth={false} fullWidth={false}
label="Team Roles" label="Team Roles"
value={ value={
<ChipGroup <WithI18n
className=""
collapsedText="\${remaining} more"
defaultIsOpen={false}
expandedText="Show Less"
numChips={5} numChips={5}
withToolbar={false} totalChips={1}
> >
<Unknown <Unknown
isReadOnly={false} isReadOnly={false}
@@ -658,7 +642,7 @@ exports[`<ResourceAccessListItem /> initially renders succesfully 1`] = `
> >
Member Member
</Unknown> </Unknown>
</ChipGroup> </WithI18n>
} }
> >
<Detail__DetailName <Detail__DetailName
@@ -769,177 +753,193 @@ exports[`<ResourceAccessListItem /> initially renders succesfully 1`] = `
data-cy={null} data-cy={null}
data-pf-content={true} data-pf-content={true}
> >
<ChipGroup <WithI18n
className=""
collapsedText="\${remaining} more"
defaultIsOpen={false}
expandedText="Show Less"
numChips={5} numChips={5}
withToolbar={false} totalChips={1}
> >
<ul <I18n
className="pf-c-chip-group" update={true}
withHash={true}
> >
<InnerChipGroup <ChipGroup
className="" i18n={"/i18n/"}
collapsedText="\${remaining} more"
defaultIsOpen={false}
expandedText="Show Less"
isOpen={false}
numChips={5} numChips={5}
onToggleCollapse={[Function]} totalChips={1}
withToolbar={false}
> >
<Component <ChipGroup
component="li" className=""
isReadOnly={false} collapsedText="-4 more"
key=".$3" defaultIsOpen={false}
onClick={[Function]} expandedText="Show less"
numChips={5}
withToolbar={false}
> >
<ComponentWithOuia <ul
component={[Function]} className="pf-c-chip-group"
componentProps={
Object {
"children": "Member",
"component": "li",
"isReadOnly": false,
"onClick": [Function],
}
}
consumerContext={null}
> >
<Chip <InnerChipGroup
className="" className=""
closeBtnAriaLabel="close" collapsedText="-4 more"
component="li" defaultIsOpen={false}
isOverflowChip={false} expandedText="Show less"
isReadOnly={false} isOpen={false}
onClick={[Function]} numChips={5}
ouiaContext={ onToggleCollapse={[Function]}
Object { withToolbar={false}
"isOuia": false,
"ouiaId": null,
}
}
tooltipPosition="top"
> >
<GenerateId <Component
prefix="pf-random-id-" component="li"
isReadOnly={false}
key=".$3"
onClick={[Function]}
> >
<li <ComponentWithOuia
className="pf-c-chip" component={[Function]}
componentProps={
Object {
"children": "Member",
"component": "li",
"isReadOnly": false,
"onClick": [Function],
}
}
consumerContext={null}
> >
<span <Chip
className="pf-c-chip__text" className=""
id="pf-random-id-0" closeBtnAriaLabel="close"
> component="li"
Member isOverflowChip={false}
</span> isReadOnly={false}
<ChipButton
aria-labelledby="remove_pf-random-id-0 pf-random-id-0"
ariaLabel="close"
id="remove_pf-random-id-0"
onClick={[Function]} onClick={[Function]}
ouiaContext={
Object {
"isOuia": false,
"ouiaId": null,
}
}
tooltipPosition="top"
> >
<Component <GenerateId
aria-label="close" prefix="pf-random-id-"
aria-labelledby="remove_pf-random-id-0 pf-random-id-0"
className=""
id="remove_pf-random-id-0"
onClick={[Function]}
variant="plain"
> >
<ComponentWithOuia <li
component={[Function]} className="pf-c-chip"
componentProps={
Object {
"aria-label": "close",
"aria-labelledby": "remove_pf-random-id-0 pf-random-id-0",
"children": <TimesCircleIcon
aria-hidden="true"
color="currentColor"
noVerticalAlign={false}
size="sm"
title={null}
/>,
"className": "",
"id": "remove_pf-random-id-0",
"onClick": [Function],
"variant": "plain",
}
}
consumerContext={
Object {
"isOuia": false,
"ouiaId": null,
}
}
> >
<Button <span
aria-label="close" className="pf-c-chip__text"
id="pf-random-id-0"
>
Member
</span>
<ChipButton
aria-labelledby="remove_pf-random-id-0 pf-random-id-0" aria-labelledby="remove_pf-random-id-0 pf-random-id-0"
className="" ariaLabel="close"
id="remove_pf-random-id-0" id="remove_pf-random-id-0"
onClick={[Function]} onClick={[Function]}
ouiaContext={
Object {
"isOuia": false,
"ouiaId": null,
}
}
variant="plain"
> >
<button <Component
aria-disabled={null}
aria-label="close" aria-label="close"
aria-labelledby="remove_pf-random-id-0 pf-random-id-0" aria-labelledby="remove_pf-random-id-0 pf-random-id-0"
className="pf-c-button pf-m-plain" className=""
disabled={false}
id="remove_pf-random-id-0" id="remove_pf-random-id-0"
onClick={[Function]} onClick={[Function]}
tabIndex={null} variant="plain"
type="button"
> >
<TimesCircleIcon <ComponentWithOuia
aria-hidden="true" component={[Function]}
color="currentColor" componentProps={
noVerticalAlign={false} Object {
size="sm" "aria-label": "close",
title={null} "aria-labelledby": "remove_pf-random-id-0 pf-random-id-0",
"children": <TimesCircleIcon
aria-hidden="true"
color="currentColor"
noVerticalAlign={false}
size="sm"
title={null}
/>,
"className": "",
"id": "remove_pf-random-id-0",
"onClick": [Function],
"variant": "plain",
}
}
consumerContext={
Object {
"isOuia": false,
"ouiaId": null,
}
}
> >
<svg <Button
aria-hidden="true" aria-label="close"
aria-labelledby={null} aria-labelledby="remove_pf-random-id-0 pf-random-id-0"
fill="currentColor" className=""
height="1em" id="remove_pf-random-id-0"
role="img" onClick={[Function]}
style={ ouiaContext={
Object { Object {
"verticalAlign": "-0.125em", "isOuia": false,
"ouiaId": null,
} }
} }
viewBox="0 0 512 512" variant="plain"
width="1em"
> >
<path <button
d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm121.6 313.1c4.7 4.7 4.7 12.3 0 17L338 377.6c-4.7 4.7-12.3 4.7-17 0L256 312l-65.1 65.6c-4.7 4.7-12.3 4.7-17 0L134.4 338c-4.7-4.7-4.7-12.3 0-17l65.6-65-65.6-65.1c-4.7-4.7-4.7-12.3 0-17l39.6-39.6c4.7-4.7 12.3-4.7 17 0l65 65.7 65.1-65.6c4.7-4.7 12.3-4.7 17 0l39.6 39.6c4.7 4.7 4.7 12.3 0 17L312 256l65.6 65.1z" aria-disabled={null}
transform="" aria-label="close"
/> aria-labelledby="remove_pf-random-id-0 pf-random-id-0"
</svg> className="pf-c-button pf-m-plain"
</TimesCircleIcon> disabled={false}
</button> id="remove_pf-random-id-0"
</Button> onClick={[Function]}
</ComponentWithOuia> tabIndex={null}
</Component> type="button"
</ChipButton> >
</li> <TimesCircleIcon
</GenerateId> aria-hidden="true"
</Chip> color="currentColor"
</ComponentWithOuia> noVerticalAlign={false}
</Component> size="sm"
</InnerChipGroup> title={null}
</ul> >
</ChipGroup> <svg
aria-hidden="true"
aria-labelledby={null}
fill="currentColor"
height="1em"
role="img"
style={
Object {
"verticalAlign": "-0.125em",
}
}
viewBox="0 0 512 512"
width="1em"
>
<path
d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm121.6 313.1c4.7 4.7 4.7 12.3 0 17L338 377.6c-4.7 4.7-12.3 4.7-17 0L256 312l-65.1 65.6c-4.7 4.7-12.3 4.7-17 0L134.4 338c-4.7-4.7-4.7-12.3 0-17l65.6-65-65.6-65.1c-4.7-4.7-4.7-12.3 0-17l39.6-39.6c4.7-4.7 12.3-4.7 17 0l65 65.7 65.1-65.6c4.7-4.7 12.3-4.7 17 0l39.6 39.6c4.7 4.7 4.7 12.3 0 17L312 256l65.6 65.1z"
transform=""
/>
</svg>
</TimesCircleIcon>
</button>
</Button>
</ComponentWithOuia>
</Component>
</ChipButton>
</li>
</GenerateId>
</Chip>
</ComponentWithOuia>
</Component>
</InnerChipGroup>
</ul>
</ChipGroup>
</ChipGroup>
</I18n>
</WithI18n>
</dd> </dd>
</TextListItem> </TextListItem>
</Component> </Component>

View File

@@ -5,7 +5,7 @@ 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 { Schedule } from '@types'; import { Schedule } from '@types';
import { Chip, ChipGroup, Title, Button } from '@patternfly/react-core'; import { Chip, Title, Button } from '@patternfly/react-core';
import AlertModal from '@components/AlertModal'; import AlertModal from '@components/AlertModal';
import { CardBody, CardActionsRow } from '@components/Card'; import { CardBody, CardActionsRow } from '@components/Card';
import ContentError from '@components/ContentError'; import ContentError from '@components/ContentError';
@@ -18,6 +18,7 @@ import useRequest from '@util/useRequest';
import { SchedulesAPI } from '@api'; import { SchedulesAPI } from '@api';
import DeleteButton from '@components/DeleteButton'; import DeleteButton from '@components/DeleteButton';
import ErrorDetail from '@components/ErrorDetail'; import ErrorDetail from '@components/ErrorDetail';
import ChipGroup from '@components/ChipGroup';
const PromptTitle = styled(Title)` const PromptTitle = styled(Title)`
--pf-c-title--m-md--FontWeight: 700; --pf-c-title--m-md--FontWeight: 700;
@@ -173,7 +174,7 @@ function ScheduleDetail({ schedule, i18n }) {
fullWidth fullWidth
label={i18n._(t`Credentials`)} label={i18n._(t`Credentials`)}
value={ value={
<ChipGroup numChips={5}> <ChipGroup numChips={5} totalChips={credentials.length}>
{credentials.map(c => ( {credentials.map(c => (
<CredentialChip key={c.id} credential={c} isReadOnly /> <CredentialChip key={c.id} credential={c} isReadOnly />
))} ))}
@@ -186,7 +187,10 @@ function ScheduleDetail({ schedule, i18n }) {
fullWidth fullWidth
label={i18n._(t`Job Tags`)} label={i18n._(t`Job Tags`)}
value={ value={
<ChipGroup numChips={5}> <ChipGroup
numChips={5}
totalChips={job_tags.split(',').length}
>
{job_tags.split(',').map(jobTag => ( {job_tags.split(',').map(jobTag => (
<Chip key={jobTag} isReadOnly> <Chip key={jobTag} isReadOnly>
{jobTag} {jobTag}
@@ -201,7 +205,10 @@ function ScheduleDetail({ schedule, i18n }) {
fullWidth fullWidth
label={i18n._(t`Skip Tags`)} label={i18n._(t`Skip Tags`)}
value={ value={
<ChipGroup numChips={5}> <ChipGroup
numChips={5}
totalChips={skip_tags.split(',').length}
>
{skip_tags.split(',').map(skipTag => ( {skip_tags.split(',').map(skipTag => (
<Chip key={skipTag} isReadOnly> <Chip key={skipTag} isReadOnly>
{skipTag} {skipTag}

View File

@@ -1,11 +1,8 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { import { Chip, Split as PFSplit, SplitItem } from '@patternfly/react-core';
Chip,
ChipGroup, import ChipGroup from '@components/ChipGroup';
Split as PFSplit,
SplitItem,
} from '@patternfly/react-core';
import styled from 'styled-components'; import styled from 'styled-components';
const Split = styled(PFSplit)` const Split = styled(PFSplit)`
@@ -42,7 +39,7 @@ class SelectedList extends Component {
<Split> <Split>
<SplitLabelItem>{label}</SplitLabelItem> <SplitLabelItem>{label}</SplitLabelItem>
<SplitItem> <SplitItem>
<ChipGroup numChips={5}> <ChipGroup numChips={5} totalChips={selected.length}>
{selected.map(item => {selected.map(item =>
renderChip({ renderChip({
item, item,

View File

@@ -1,11 +1,11 @@
import React from 'react'; import React from 'react';
import { mount } from 'enzyme'; import { mountWithContexts } from '@testUtils/enzymeHelpers';
import { ChipGroup } from '@patternfly/react-core'; import ChipGroup from '@components/ChipGroup';
import SelectedList from './SelectedList'; import SelectedList from './SelectedList';
describe('<SelectedList />', () => { describe('<SelectedList />', () => {
test('initially renders succesfully', () => { test('initially renders successfully', () => {
const mockSelected = [ const mockSelected = [
{ {
id: 1, id: 1,
@@ -16,17 +16,18 @@ describe('<SelectedList />', () => {
name: 'bar', name: 'bar',
}, },
]; ];
mount( const wrapper = mountWithContexts(
<SelectedList <SelectedList
label="Selectedeeee" label="Selectedeeee"
selected={mockSelected} selected={mockSelected}
onRemove={() => {}} onRemove={() => {}}
/> />
); );
expect(wrapper.length).toBe(1);
}); });
test('showOverflow should set showOverflow on ChipGroup', () => { test('showOverflow should set showOverflow on ChipGroup', () => {
const wrapper = mount( const wrapper = mountWithContexts(
<SelectedList label="Selected" selected={[]} onRemove={() => {}} /> <SelectedList label="Selected" selected={[]} onRemove={() => {}} />
); );
const chipGroup = wrapper.find(ChipGroup); const chipGroup = wrapper.find(ChipGroup);
@@ -42,7 +43,7 @@ describe('<SelectedList />', () => {
name: 'foo', name: 'foo',
}, },
]; ];
const wrapper = mount( const wrapper = mountWithContexts(
<SelectedList <SelectedList
label="Selected" label="Selected"
selected={mockSelected} selected={mockSelected}

View File

@@ -2,13 +2,14 @@ import React, { useCallback, useEffect } from 'react';
import { Link, useHistory } from 'react-router-dom'; import { Link, useHistory } from 'react-router-dom';
import { withI18n } from '@lingui/react'; import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro'; import { t } from '@lingui/macro';
import { Button, Chip, ChipGroup } from '@patternfly/react-core'; import { Button, Chip } from '@patternfly/react-core';
import { CardBody, CardActionsRow } from '@components/Card'; import { CardBody, CardActionsRow } from '@components/Card';
import { DetailList, Detail, UserDateDetail } from '@components/DetailList'; import { DetailList, Detail, UserDateDetail } from '@components/DetailList';
import { VariablesDetail } from '@components/CodeMirrorInput'; import { VariablesDetail } from '@components/CodeMirrorInput';
import DeleteButton from '@components/DeleteButton'; import DeleteButton from '@components/DeleteButton';
import ContentError from '@components/ContentError'; import ContentError from '@components/ContentError';
import ContentLoading from '@components/ContentLoading'; import ContentLoading from '@components/ContentLoading';
import ChipGroup from '@components/ChipGroup';
import { InventoriesAPI } from '@api'; import { InventoriesAPI } from '@api';
import useRequest from '@util/useRequest'; import useRequest from '@util/useRequest';
import { Inventory } from '../../../types'; import { Inventory } from '../../../types';
@@ -74,7 +75,7 @@ function InventoryDetail({ inventory, i18n }) {
fullWidth fullWidth
label={i18n._(t`Instance Groups`)} label={i18n._(t`Instance Groups`)}
value={ value={
<ChipGroup numChips={5}> <ChipGroup numChips={5} totalChips={instanceGroups.length}>
{instanceGroups.map(ig => ( {instanceGroups.map(ig => (
<Chip key={ig.id} isReadOnly> <Chip key={ig.id} isReadOnly>
{ig.name} {ig.name}

View File

@@ -2,12 +2,13 @@ import React, { useState } from 'react';
import { Link, useHistory } from 'react-router-dom'; import { Link, useHistory } from 'react-router-dom';
import { withI18n } from '@lingui/react'; import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro'; import { t } from '@lingui/macro';
import { Button, Chip, ChipGroup } from '@patternfly/react-core'; import { Button, Chip } from '@patternfly/react-core';
import styled from 'styled-components'; import styled from 'styled-components';
import AlertModal from '@components/AlertModal'; import AlertModal from '@components/AlertModal';
import { DetailList, Detail } from '@components/DetailList'; import { DetailList, Detail } from '@components/DetailList';
import { CardBody, CardActionsRow } from '@components/Card'; import { CardBody, CardActionsRow } from '@components/Card';
import ChipGroup from '@components/ChipGroup';
import CredentialChip from '@components/CredentialChip'; import CredentialChip from '@components/CredentialChip';
import { VariablesInput as _VariablesInput } from '@components/CodeMirrorInput'; import { VariablesInput as _VariablesInput } from '@components/CodeMirrorInput';
import DeleteButton from '@components/DeleteButton'; import DeleteButton from '@components/DeleteButton';
@@ -215,7 +216,7 @@ function JobDetail({ job, i18n }) {
fullWidth fullWidth
label={i18n._(t`Credentials`)} label={i18n._(t`Credentials`)}
value={ value={
<ChipGroup numChips={5}> <ChipGroup numChips={5} totalChips={credentials.length}>
{credentials.map(c => ( {credentials.map(c => (
<CredentialChip key={c.id} credential={c} isReadOnly /> <CredentialChip key={c.id} credential={c} isReadOnly />
))} ))}
@@ -228,7 +229,7 @@ function JobDetail({ job, i18n }) {
fullWidth fullWidth
label={i18n._(t`Labels`)} label={i18n._(t`Labels`)}
value={ value={
<ChipGroup numChips={5}> <ChipGroup numChips={5} totalChips={labels.results.length}>
{labels.results.map(l => ( {labels.results.map(l => (
<Chip key={l.id} isReadOnly> <Chip key={l.id} isReadOnly>
{l.name} {l.name}

View File

@@ -2,11 +2,12 @@ import React, { useEffect, useState } from 'react';
import { Link, useHistory, useRouteMatch } from 'react-router-dom'; import { Link, useHistory, useRouteMatch } from 'react-router-dom';
import { withI18n } from '@lingui/react'; import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro'; import { t } from '@lingui/macro';
import { Button, Chip, ChipGroup } from '@patternfly/react-core'; import { Button, Chip } from '@patternfly/react-core';
import { OrganizationsAPI } from '@api'; import { OrganizationsAPI } from '@api';
import { DetailList, Detail, UserDateDetail } from '@components/DetailList'; import { DetailList, Detail, UserDateDetail } from '@components/DetailList';
import { CardBody, CardActionsRow } from '@components/Card'; import { CardBody, CardActionsRow } from '@components/Card';
import AlertModal from '@components/AlertModal'; import AlertModal from '@components/AlertModal';
import ChipGroup from '@components/ChipGroup';
import ContentError from '@components/ContentError'; import ContentError from '@components/ContentError';
import ContentLoading from '@components/ContentLoading'; import ContentLoading from '@components/ContentLoading';
import DeleteButton from '@components/DeleteButton'; import DeleteButton from '@components/DeleteButton';
@@ -96,7 +97,7 @@ function OrganizationDetail({ i18n, organization }) {
fullWidth fullWidth
label={i18n._(t`Instance Groups`)} label={i18n._(t`Instance Groups`)}
value={ value={
<ChipGroup numChips={5}> <ChipGroup numChips={5} totalChips={instanceGroups.length}>
{instanceGroups.map(ig => ( {instanceGroups.map(ig => (
<Chip key={ig.id} isReadOnly> <Chip key={ig.id} isReadOnly>
{ig.name} {ig.name}

View File

@@ -4,7 +4,6 @@ import { withI18n } from '@lingui/react';
import { import {
Button, Button,
Chip, Chip,
ChipGroup,
TextList, TextList,
TextListItem, TextListItem,
TextListItemVariants, TextListItemVariants,
@@ -15,6 +14,7 @@ import { t } from '@lingui/macro';
import AlertModal from '@components/AlertModal'; import AlertModal from '@components/AlertModal';
import { CardBody, CardActionsRow } from '@components/Card'; import { CardBody, CardActionsRow } from '@components/Card';
import ChipGroup from '@components/ChipGroup';
import ContentError from '@components/ContentError'; import ContentError from '@components/ContentError';
import ContentLoading from '@components/ContentLoading'; import ContentLoading from '@components/ContentLoading';
import CredentialChip from '@components/CredentialChip'; import CredentialChip from '@components/CredentialChip';
@@ -281,7 +281,10 @@ function JobTemplateDetail({ i18n, template }) {
fullWidth fullWidth
label={i18n._(t`Credentials`)} label={i18n._(t`Credentials`)}
value={ value={
<ChipGroup numChips={5}> <ChipGroup
numChips={5}
totalChips={summary_fields.credentials.length}
>
{summary_fields.credentials.map(c => ( {summary_fields.credentials.map(c => (
<CredentialChip key={c.id} credential={c} isReadOnly /> <CredentialChip key={c.id} credential={c} isReadOnly />
))} ))}
@@ -294,7 +297,10 @@ function JobTemplateDetail({ i18n, template }) {
fullWidth fullWidth
label={i18n._(t`Labels`)} label={i18n._(t`Labels`)}
value={ value={
<ChipGroup numChips={5}> <ChipGroup
numChips={5}
totalChips={summary_fields.labels.results.length}
>
{summary_fields.labels.results.map(l => ( {summary_fields.labels.results.map(l => (
<Chip key={l.id} isReadOnly> <Chip key={l.id} isReadOnly>
{l.name} {l.name}
@@ -309,7 +315,7 @@ function JobTemplateDetail({ i18n, template }) {
fullWidth fullWidth
label={i18n._(t`Instance Groups`)} label={i18n._(t`Instance Groups`)}
value={ value={
<ChipGroup numChips={5}> <ChipGroup numChips={5} totalChips={instanceGroups.length}>
{instanceGroups.map(ig => ( {instanceGroups.map(ig => (
<Chip key={ig.id} isReadOnly> <Chip key={ig.id} isReadOnly>
{ig.name} {ig.name}
@@ -324,7 +330,7 @@ function JobTemplateDetail({ i18n, template }) {
fullWidth fullWidth
label={i18n._(t`Job Tags`)} label={i18n._(t`Job Tags`)}
value={ value={
<ChipGroup numChips={5}> <ChipGroup numChips={5} totalChips={job_tags.split(',').length}>
{job_tags.split(',').map(jobTag => ( {job_tags.split(',').map(jobTag => (
<Chip key={jobTag} isReadOnly> <Chip key={jobTag} isReadOnly>
{jobTag} {jobTag}
@@ -339,7 +345,7 @@ function JobTemplateDetail({ i18n, template }) {
fullWidth fullWidth
label={i18n._(t`Skip Tags`)} label={i18n._(t`Skip Tags`)}
value={ value={
<ChipGroup numChips={5}> <ChipGroup numChips={5} totalChips={skip_tags.split(',').length}>
{skip_tags.split(',').map(skipTag => ( {skip_tags.split(',').map(skipTag => (
<Chip key={skipTag} isReadOnly> <Chip key={skipTag} isReadOnly>
{skipTag} {skipTag}

View File

@@ -114,7 +114,7 @@ function SurveyList({
variant="primary" variant="primary"
aria-label={i18n._(t`Preview`)} aria-label={i18n._(t`Preview`)}
> >
Preview {i18n._(t`Preview`)}
</Button> </Button>
</DataList> </DataList>
); );

View File

@@ -5,7 +5,6 @@ import { Link } from 'react-router-dom';
import { import {
Button as _Button, Button as _Button,
Chip, Chip,
ChipGroup,
DataListAction as _DataListAction, DataListAction as _DataListAction,
DataListCheck, DataListCheck,
DataListItemCells, DataListItemCells,
@@ -15,6 +14,7 @@ import {
StackItem, StackItem,
} from '@patternfly/react-core'; } from '@patternfly/react-core';
import DataListCell from '@components/DataListCell'; import DataListCell from '@components/DataListCell';
import ChipGroup from '@components/ChipGroup';
import { CaretDownIcon, CaretUpIcon } from '@patternfly/react-icons'; import { CaretDownIcon, CaretUpIcon } from '@patternfly/react-icons';
import styled from 'styled-components'; import styled from 'styled-components';
@@ -119,7 +119,10 @@ function SurveyListItem({
)} )}
{[question.type].includes('multiselect') && {[question.type].includes('multiselect') &&
question.default.length > 0 && ( question.default.length > 0 && (
<ChipGroup numChips={5}> <ChipGroup
numChips={5}
totalChips={question.default.split('\n').length}
>
{question.default.split('\n').map(chip => ( {question.default.split('\n').map(chip => (
<Chip key={chip} isReadOnly> <Chip key={chip} isReadOnly>
{chip} {chip}

View File

@@ -5,7 +5,6 @@ import { t } from '@lingui/macro';
import { WorkflowJobTemplatesAPI } from '@api'; import { WorkflowJobTemplatesAPI } from '@api';
import { import {
Chip, Chip,
ChipGroup,
Button, Button,
TextList, TextList,
TextListItem, TextListItem,
@@ -16,6 +15,7 @@ import {
import AlertModal from '@components/AlertModal'; import AlertModal from '@components/AlertModal';
import { CardBody, CardActionsRow } from '@components/Card'; import { CardBody, CardActionsRow } from '@components/Card';
import ChipGroup from '@components/ChipGroup';
import { VariablesDetail } from '@components/CodeMirrorInput'; import { VariablesDetail } from '@components/CodeMirrorInput';
import ContentLoading from '@components/ContentLoading'; import ContentLoading from '@components/ContentLoading';
import DeleteButton from '@components/DeleteButton'; import DeleteButton from '@components/DeleteButton';
@@ -168,7 +168,10 @@ function WorkflowJobTemplateDetail({ template, i18n }) {
fullWidth fullWidth
label={i18n._(t`Labels`)} label={i18n._(t`Labels`)}
value={ value={
<ChipGroup> <ChipGroup
numChips={3}
totalChips={summary_fields.labels.results.length}
>
{summary_fields.labels.results.map(l => ( {summary_fields.labels.results.map(l => (
<Chip key={l.id} isReadOnly> <Chip key={l.id} isReadOnly>
{l.name} {l.name}