Integrate proptypes for our shared components.

- Fix unit tests.
- Fix linter errors.
This commit is contained in:
kialam
2019-02-15 15:08:52 -05:00
parent 91f87b6d81
commit b340d49cb7
26 changed files with 313 additions and 55 deletions

View File

@@ -1,4 +1,5 @@
import React from 'react';
import PropTypes from 'prop-types';
import { I18n } from '@lingui/react';
import { Trans, t } from '@lingui/macro';
import {
@@ -86,4 +87,17 @@ class About extends React.Component {
}
}
About.propTypes = {
ansible_version: PropTypes.string,
isOpen: PropTypes.bool,
onClose: PropTypes.func.isRequired,
version: PropTypes.string,
};
About.defaultProps = {
ansible_version: null,
isOpen: false,
version: null,
};
export default About;

View File

@@ -1,6 +1,8 @@
import React from 'react';
import PropTypes from 'prop-types';
import {
FormGroup,
Select,
SelectOption,
} from '@patternfly/react-core';
@@ -32,15 +34,17 @@ class AnsibleSelect extends React.Component {
render () {
const { count } = this.state;
const { label = '', value, data, defaultSelected } = this.props;
const { label = '', value, data, name, defaultSelected } = this.props;
let elem;
if (count > 1) {
elem = (
<Select value={value} onChange={this.onSelectChange} aria-label="Select Input">
{data.map((datum) => (datum === defaultSelected
? (<SelectOption key="" value="" label={`Use Default ${label}`} />) : (<SelectOption key={datum} value={datum} label={datum} />)))
}
</Select>
<FormGroup label={label} fieldId={`ansible-select-${name}`}>
<Select value={value} onChange={this.onSelectChange} aria-label="Select Input">
{data.map((datum) => (datum === defaultSelected
? (<SelectOption key="" value="" label={`Use Default ${label}`} />) : (<SelectOption key={datum} value={datum} label={datum} />)))
}
</Select>
</FormGroup>
);
} else {
elem = null;
@@ -48,4 +52,21 @@ class AnsibleSelect extends React.Component {
return elem;
}
}
AnsibleSelect.defaultProps = {
data: [],
label: 'Ansible Select',
defaultSelected: null,
name: null,
};
AnsibleSelect.propTypes = {
data: PropTypes.arrayOf(PropTypes.string),
defaultSelected: PropTypes.string,
label: PropTypes.string,
name: PropTypes.string,
onChange: PropTypes.func.isRequired,
value: PropTypes.string.isRequired,
};
export default AnsibleSelect;

View File

@@ -1,4 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Chip } from '@patternfly/react-core';
import './basicChip.scss';
@@ -10,4 +12,8 @@ const BasicChip = ({ text }) => (
</Chip>
);
BasicChip.propTypes = {
text: PropTypes.string.isRequired,
};
export default BasicChip;

View File

@@ -1,4 +1,5 @@
import React, { Fragment } from 'react';
import PropTypes from 'prop-types';
import {
PageSection,
PageSectionVariants,
@@ -68,4 +69,12 @@ const Crumb = ({ breadcrumbConfig, match }) => {
);
};
Breadcrumbs.propTypes = {
breadcrumbConfig: PropTypes.objectOf(PropTypes.string).isRequired,
};
Crumb.propTypes = {
breadcrumbConfig: PropTypes.objectOf(PropTypes.string).isRequired,
};
export default withRouter(Breadcrumbs);

View File

@@ -1,4 +1,5 @@
import React from 'react';
import PropTypes from 'prop-types';
import { I18n } from '@lingui/react';
import { t } from '@lingui/macro';
import {
@@ -36,7 +37,6 @@ class DataListToolbar extends React.Component {
super(props);
const { sortedColumnKey } = this.props;
this.state = {
isSearchDropdownOpen: false,
isSortDropdownOpen: false,
@@ -282,4 +282,29 @@ class DataListToolbar extends React.Component {
}
}
DataListToolbar.propTypes = {
addUrl: PropTypes.string,
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
isAllSelected: PropTypes.bool,
onSearch: PropTypes.func,
onSelectAll: PropTypes.func,
onSort: PropTypes.func,
showDelete: PropTypes.bool,
showSelectAll: PropTypes.bool,
sortOrder: PropTypes.string,
sortedColumnKey: PropTypes.string,
};
DataListToolbar.defaultProps = {
addUrl: null,
onSearch: null,
onSelectAll: null,
onSort: null,
showDelete: false,
showSelectAll: false,
sortOrder: 'ascending',
sortedColumnKey: 'name',
isAllSelected: false,
};
export default DataListToolbar;

View File

@@ -1,4 +1,5 @@
import React from 'react';
import PropTypes from 'prop-types';
import { I18n } from '@lingui/react';
import { t } from '@lingui/macro';
@@ -21,7 +22,7 @@ const buttonGroupStyle = {
marginRight: '20px'
};
export default ({ onSubmit, submitDisabled, onCancel }) => (
const FormActionGroup = ({ onSubmit, submitDisabled, onCancel }) => (
<I18n>
{({ i18n }) => (
<ActionGroup style={formActionGroupStyle}>
@@ -37,3 +38,15 @@ export default ({ onSubmit, submitDisabled, onCancel }) => (
)}
</I18n>
);
FormActionGroup.propTypes = {
onCancel: PropTypes.func.isRequired,
onSubmit: PropTypes.func.isRequired,
submitDisabled: PropTypes.bool,
};
FormActionGroup.defaultProps = {
submitDisabled: true,
};
export default FormActionGroup;

View File

@@ -1,11 +1,12 @@
import React from 'react';
import PropTypes from 'prop-types';
import { I18n } from '@lingui/react';
import { t } from '@lingui/macro';
import {
Checkbox,
} from '@patternfly/react-core';
export default ({
const CheckboxListItem = ({
itemId,
name,
isSelected,
@@ -32,3 +33,12 @@ export default ({
</div>
</li>
);
CheckboxListItem.propTypes = {
itemId: PropTypes.number.isRequired,
name: PropTypes.string.isRequired,
isSelected: PropTypes.bool.isRequired,
onSelect: PropTypes.func.isRequired,
};
export default CheckboxListItem;

View File

@@ -1,5 +1,5 @@
import React, { Fragment } from 'react';
import PropTypes from 'prop-types';
import { SearchIcon, CubesIcon } from '@patternfly/react-icons';
import {
Modal,
@@ -125,7 +125,7 @@ class Lookup extends React.Component {
render () {
const { isModalOpen, lookupSelectedItems, error, results, count, page, page_size } = this.state;
const { lookupHeader = 'items', value } = this.props;
const { lookupHeader, value } = this.props;
return (
<I18n>
@@ -174,6 +174,7 @@ class Lookup extends React.Component {
pageCount={Math.ceil(count / page_size)}
page_size={page_size}
onSetPage={this.onSetPage}
pageSizeOptions={null}
style={paginationStyling}
/>
</Fragment>
@@ -194,4 +195,18 @@ class Lookup extends React.Component {
);
}
}
Lookup.propTypes = {
getItems: PropTypes.func.isRequired,
lookupHeader: PropTypes.string,
name: PropTypes.string,
onLookupSave: PropTypes.func.isRequired,
value: PropTypes.arrayOf(PropTypes.object).isRequired,
};
Lookup.defaultProps = {
lookupHeader: 'items',
name: null,
};
export default Lookup;

View File

@@ -1,4 +1,5 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import {
withRouter
} from 'react-router-dom';
@@ -55,4 +56,10 @@ class NavExpandableGroup extends Component {
}
}
NavExpandableGroup.propTypes = {
groupId: PropTypes.string.isRequired,
groupTitle: PropTypes.string.isRequired,
routes: PropTypes.arrayOf(PropTypes.object).isRequired,
};
export default withRouter(NavExpandableGroup);

View File

@@ -1,4 +1,5 @@
import React from 'react';
import PropTypes from 'prop-types';
import { I18n } from '@lingui/react';
import { t } from '@lingui/macro';
import {
@@ -20,7 +21,6 @@ class NotificationListItem extends React.Component {
errorTurnedOn,
toggleNotification
} = this.props;
const capText = {
textTransform: 'capitalize'
};
@@ -69,5 +69,21 @@ class NotificationListItem extends React.Component {
}
}
NotificationListItem.propTypes = {
detailUrl: PropTypes.string.isRequired,
errorTurnedOn: PropTypes.bool,
itemId: PropTypes.number.isRequired,
name: PropTypes.string,
notificationType: PropTypes.string.isRequired,
successTurnedOn: PropTypes.bool,
toggleNotification: PropTypes.func.isRequired,
};
NotificationListItem.defaultProps = {
errorTurnedOn: false,
name: null,
successTurnedOn: false,
};
export default NotificationListItem;

View File

@@ -2,6 +2,7 @@ import React, {
Component,
Fragment
} from 'react';
import PropTypes from 'prop-types';
import { Title, EmptyState, EmptyStateIcon, EmptyStateBody } from '@patternfly/react-core';
import { CubesIcon } from '@patternfly/react-icons';
import { I18n, i18nMark } from '@lingui/react';
@@ -29,8 +30,6 @@ class Notifications extends Component {
order_by: 'name',
};
pageSizeOptions = [5, 10, 25, 50];
constructor (props) {
super(props);
@@ -286,7 +285,6 @@ class Notifications extends Component {
successTemplateIds,
errorTemplateIds
} = this.state;
return (
<Fragment>
{noInitialResults && (
@@ -326,8 +324,6 @@ class Notifications extends Component {
name={o.name}
notificationType={o.notification_type}
detailUrl={`/notifications/${o.id}`}
isSelected={selected.includes(o.id)}
onSelect={() => this.onSelect(o.id)}
toggleNotification={this.toggleNotification}
errorTurnedOn={errorTemplateIds.includes(o.id)}
successTurnedOn={successTemplateIds.includes(o.id)}
@@ -341,7 +337,6 @@ class Notifications extends Component {
page={page}
pageCount={pageCount}
page_size={page_size}
pageSizeOptions={this.pageSizeOptions}
onSetPage={this.onSetPage}
/>
</Fragment>
@@ -353,4 +348,12 @@ class Notifications extends Component {
}
}
Notifications.propType = {
getError: PropTypes.func.isRequired,
getNotifications: PropTypes.func.isRequired,
getSuccess: PropTypes.func.isRequired,
postError: PropTypes.func.isRequired,
postSuccess: PropTypes.func.isRequired,
};
export default Notifications;

View File

@@ -1,4 +1,5 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';
import { t } from '@lingui/macro';
@@ -126,4 +127,14 @@ class PageHeaderToolbar extends Component {
}
}
PageHeaderToolbar.propTypes = {
isAboutDisabled: PropTypes.bool,
onAboutClick: PropTypes.func.isRequired,
onLogoutClick: PropTypes.func.isRequired,
};
PageHeaderToolbar.defaultProps = {
isAboutDisabled: false,
};
export default PageHeaderToolbar;

View File

@@ -1,4 +1,5 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { I18n } from '@lingui/react';
import { Trans, t } from '@lingui/macro';
import {
@@ -224,4 +225,19 @@ class Pagination extends Component {
}
}
Pagination.propTypes = {
count: PropTypes.number,
onSetPage: PropTypes.func.isRequired,
page: PropTypes.number.isRequired,
pageCount: PropTypes.number,
pageSizeOptions: PropTypes.arrayOf(PropTypes.number),
page_size: PropTypes.number.isRequired,
};
Pagination.defaultProps = {
count: null,
pageCount: null,
pageSizeOptions: [5, 10, 25, 50],
};
export default Pagination;

View File

@@ -1,4 +1,5 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import {
Chip
} from '@patternfly/react-core';
@@ -70,4 +71,16 @@ class SelectedList extends Component {
}
}
SelectedList.propTypes = {
label: PropTypes.string,
onRemove: PropTypes.func.isRequired,
selected: PropTypes.arrayOf(PropTypes.object).isRequired,
showOverflowAfter: PropTypes.number,
};
SelectedList.defaultProps = {
label: 'Selected',
showOverflowAfter: 5,
};
export default SelectedList;

View File

@@ -1,4 +1,5 @@
import React from 'react';
import PropTypes from 'prop-types';
import { NavLink } from 'react-router-dom';
import './tabs.scss';
@@ -15,4 +16,18 @@ const Tab = ({ children, link, replace }) => (
</li>
);
Tab.propTypes = {
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node
]).isRequired,
link: PropTypes.string,
replace: PropTypes.bool,
};
Tab.defaultProps = {
link: null,
replace: false,
};
export default Tab;

View File

@@ -1,4 +1,5 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';
import { Button } from '@patternfly/react-core';
import { TimesIcon } from '@patternfly/react-icons';
@@ -35,4 +36,21 @@ const Tabs = ({ children, labelText, closeButton }) => (
</div>
);
Tabs.propTypes = {
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node
]).isRequired,
labelText: PropTypes.string,
closeButton: PropTypes.shape({
text: PropTypes.string,
link: PropTypes.string,
}),
};
Tabs.defaultProps = {
labelText: null,
closeButton: null,
};
export default Tabs;

View File

@@ -1,4 +1,5 @@
import React from 'react';
import PropTypes from 'prop-types';
class Tooltip extends React.Component {
transforms = {
@@ -74,4 +75,14 @@ class Tooltip extends React.Component {
}
}
Tooltip.propTypes = {
children: PropTypes.element.isRequired,
message: PropTypes.string.isRequired,
position: PropTypes.string,
};
Tooltip.defaultProps = {
position: 'top',
};
export default Tooltip;

View File

@@ -1,4 +1,5 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { withRouter } from 'react-router-dom';
import { I18n } from '@lingui/react';
import { t } from '@lingui/macro';
@@ -58,4 +59,12 @@ class TowerLogo extends Component {
}
}
TowerLogo.propTypes = {
linkTo: PropTypes.string,
};
TowerLogo.defaultProps = {
linkTo: null,
};
export default withRouter(TowerLogo);

View File

@@ -137,16 +137,14 @@ class OrganizationAdd extends React.Component {
</FormGroup>
<ConfigContext.Consumer>
{({ custom_virtualenvs }) => (
<FormGroup label="Ansible Environment" fieldId="add-org-form-custom-virtualenv">
<AnsibleSelect
label="Ansible Environment"
name="custom_virtualenv"
value={custom_virtualenv}
onChange={this.onFieldChange}
data={custom_virtualenvs}
defaultSelected={defaultEnv}
/>
</FormGroup>
<AnsibleSelect
label="Ansible Environment"
name="custom_virtualenv"
value={custom_virtualenv}
onChange={this.onFieldChange}
data={custom_virtualenvs}
defaultSelected={defaultEnv}
/>
)}
</ConfigContext.Consumer>
</Gallery>

View File

@@ -39,8 +39,6 @@ class OrganizationsList extends Component {
order_by: 'name',
};
pageSizeOptions = [5, 10, 25, 50];
constructor (props) {
super(props);
@@ -207,7 +205,6 @@ class OrganizationsList extends Component {
selected,
} = this.state;
const { match } = this.props;
return (
<PageSection variant={medium}>
<Card>
@@ -258,7 +255,6 @@ class OrganizationsList extends Component {
page={page}
pageCount={pageCount}
page_size={page_size}
pageSizeOptions={this.pageSizeOptions}
onSetPage={this.onSetPage}
/>
{ loading ? <div>loading...</div> : '' }