diff --git a/awx/ui/eslint.config.mjs b/awx/ui/eslint.config.mjs index 97d906b45..d1fc03f6c 100644 --- a/awx/ui/eslint.config.mjs +++ b/awx/ui/eslint.config.mjs @@ -214,6 +214,10 @@ export default defineConfig([ 'react/jsx-props-no-spreading': ['off'], 'react/prefer-stateless-function': 'off', 'react/prop-types': 'off', + // default values are expressed via ES default parameters (the React + // 18.3/19 migration away from the deprecated defaultProps), so accept a + // destructured default argument in place of a defaultProps entry + 'react/require-default-props': ['error', { functions: 'defaultArguments' }], 'react/sort-comp': ['error', {}], 'jsx-a11y/label-has-for': 'off', 'jsx-a11y/label-has-associated-control': 'off', diff --git a/awx/ui/src/components/About/About.js b/awx/ui/src/components/About/About.js index 6882dae74..714ef8af4 100644 --- a/awx/ui/src/components/About/About.js +++ b/awx/ui/src/components/About/About.js @@ -8,7 +8,7 @@ import { useLingui } from '@lingui/react/macro'; import { AboutModal } from '@patternfly/react-core'; import useBrandName from 'hooks/useBrandName'; -function About({ version, isOpen, onClose }) { +function About({ version = null, isOpen = false, onClose }) { const { t } = useLingui(); const brandName = useBrandName(); @@ -76,9 +76,4 @@ About.propTypes = { version: PropTypes.string, }; -About.defaultProps = { - isOpen: false, - version: null, -}; - export default About; diff --git a/awx/ui/src/components/AddRole/AddResourceRole.js b/awx/ui/src/components/AddRole/AddResourceRole.js index a909280eb..3a297efc2 100644 --- a/awx/ui/src/components/AddRole/AddResourceRole.js +++ b/awx/ui/src/components/AddRole/AddResourceRole.js @@ -18,7 +18,13 @@ const readTeams = async (queryParams) => TeamsAPI.read(queryParams); const readTeamsOptions = async () => TeamsAPI.readOptions(); -function AddResourceRole({ onSave, onClose, roles, resource, onError }) { +function AddResourceRole({ + onSave, + onClose, + roles = {}, + resource = {}, + onError, +}) { const { t } = useLingui(); const userSearchColumns = useMemo(() => [ @@ -285,10 +291,5 @@ AddResourceRole.propTypes = { resource: PropTypes.shape(), }; -AddResourceRole.defaultProps = { - roles: {}, - resource: {}, -}; - export { AddResourceRole as _AddResourceRole }; export default AddResourceRole; diff --git a/awx/ui/src/components/AddRole/CheckboxCard.js b/awx/ui/src/components/AddRole/CheckboxCard.js index b055ee930..b4fd17aae 100644 --- a/awx/ui/src/components/AddRole/CheckboxCard.js +++ b/awx/ui/src/components/AddRole/CheckboxCard.js @@ -17,8 +17,13 @@ const Checkbox = styled(PFCheckbox)` } `; -function CheckboxCard(props) { - const { name, description, isSelected, onSelect, itemId } = props; +function CheckboxCard({ + name, + description = '', + isSelected = false, + onSelect = null, + itemId, +}) { return ( }`, }); function SelectResourceStep({ - searchColumns, - sortColumns, - displayKey, - onRowClick, - selectedLabel, - selectedResourceRows, + searchColumns = null, + sortColumns = null, + displayKey = 'name', + onRowClick = () => {}, + selectedLabel = null, + selectedResourceRows = [], fetchItems, fetchOptions, }) { @@ -150,14 +150,5 @@ SelectResourceStep.propTypes = { selectedResourceRows: PropTypes.arrayOf(PropTypes.object), }; -SelectResourceStep.defaultProps = { - searchColumns: null, - sortColumns: null, - displayKey: 'name', - onRowClick: () => {}, - selectedLabel: null, - selectedResourceRows: [], -}; - export { SelectResourceStep as _SelectResourceStep }; export default SelectResourceStep; diff --git a/awx/ui/src/components/AddRole/SelectRoleStep.js b/awx/ui/src/components/AddRole/SelectRoleStep.js index 96c4f8b8e..81b83559d 100644 --- a/awx/ui/src/components/AddRole/SelectRoleStep.js +++ b/awx/ui/src/components/AddRole/SelectRoleStep.js @@ -7,12 +7,12 @@ import CheckboxCard from './CheckboxCard'; import { SelectedList } from '../SelectedList'; function RolesStep({ - onRolesClick, + onRolesClick = () => {}, roles, - selectedListKey, - selectedListLabel, - selectedResourceRows, - selectedRoleRows, + selectedListKey = 'name', + selectedListLabel = null, + selectedResourceRows = [], + selectedRoleRows = [], }) { const { t } = useLingui(); @@ -65,12 +65,4 @@ RolesStep.propTypes = { selectedRoleRows: PropTypes.arrayOf(PropTypes.object), }; -RolesStep.defaultProps = { - onRolesClick: () => {}, - selectedListKey: 'name', - selectedListLabel: null, - selectedResourceRows: [], - selectedRoleRows: [], -}; - export default RolesStep; diff --git a/awx/ui/src/components/AnsibleSelect/AnsibleSelect.js b/awx/ui/src/components/AnsibleSelect/AnsibleSelect.js index 96281d80d..47e58abfc 100644 --- a/awx/ui/src/components/AnsibleSelect/AnsibleSelect.js +++ b/awx/ui/src/components/AnsibleSelect/AnsibleSelect.js @@ -14,12 +14,12 @@ import { FormSelect, FormSelectOption } from '@patternfly/react-core'; function AnsibleSelect({ id, - data, - isValid, - onBlur, + data = [], + isValid = true, + onBlur = () => {}, value, - className, - isDisabled, + className = '', + isDisabled = false, onChange, name, }) { @@ -62,14 +62,6 @@ const Option = shape({ isDisabled: bool, }); -AnsibleSelect.defaultProps = { - data: [], - isValid: true, - onBlur: () => {}, - className: '', - isDisabled: false, -}; - AnsibleSelect.propTypes = { data: arrayOf(Option), id: string.isRequired, diff --git a/awx/ui/src/components/AppContainer/PageHeaderToolbar.js b/awx/ui/src/components/AppContainer/PageHeaderToolbar.js index 6941400a3..132860a35 100644 --- a/awx/ui/src/components/AppContainer/PageHeaderToolbar.js +++ b/awx/ui/src/components/AppContainer/PageHeaderToolbar.js @@ -39,7 +39,7 @@ const UserName = styled.span` `; function PageHeaderToolbar({ - isAboutDisabled, + isAboutDisabled = false, onAboutClick, onLogoutClick, loggedInUser, @@ -239,8 +239,4 @@ PageHeaderToolbar.propTypes = { onLogoutClick: PropTypes.func.isRequired, }; -PageHeaderToolbar.defaultProps = { - isAboutDisabled: false, -}; - export default PageHeaderToolbar; diff --git a/awx/ui/src/components/CheckboxListItem/CheckboxListItem.js b/awx/ui/src/components/CheckboxListItem/CheckboxListItem.js index f26a1945f..506dcc5b6 100644 --- a/awx/ui/src/components/CheckboxListItem/CheckboxListItem.js +++ b/awx/ui/src/components/CheckboxListItem/CheckboxListItem.js @@ -79,7 +79,7 @@ const CheckboxListItem = ({ }; CheckboxListItem.propTypes = { - isSelected: PropTypes.bool.isRequired, + isSelected: PropTypes.bool, itemId: PropTypes.number.isRequired, label: PropTypes.string.isRequired, name: PropTypes.string.isRequired, diff --git a/awx/ui/src/components/CodeEditor/CodeEditor.js b/awx/ui/src/components/CodeEditor/CodeEditor.js index e7feaa699..54658c799 100644 --- a/awx/ui/src/components/CodeEditor/CodeEditor.js +++ b/awx/ui/src/components/CodeEditor/CodeEditor.js @@ -86,15 +86,15 @@ AceEditor.displayName = 'AceEditor'; function CodeEditor({ id, value, - onChange, + onChange = () => {}, onFocus, onBlur, mode, - readOnly, - hasErrors, - rows, - fullHeight, - className, + readOnly = false, + hasErrors = false, + rows = 6, + fullHeight = false, + className = '', }) { const { t } = useLingui(); if (rows && typeof rows !== 'number' && rows !== 'auto') { @@ -213,13 +213,4 @@ CodeEditor.propTypes = { rows: oneOfType([number, string]), className: string, }; -CodeEditor.defaultProps = { - readOnly: false, - onChange: () => {}, - rows: 6, - fullHeight: false, - hasErrors: false, - className: '', -}; - export default CodeEditor; diff --git a/awx/ui/src/components/CodeEditor/CodeEditorField.js b/awx/ui/src/components/CodeEditor/CodeEditorField.js index ee7f4d9cd..f2fec4404 100644 --- a/awx/ui/src/components/CodeEditor/CodeEditorField.js +++ b/awx/ui/src/components/CodeEditor/CodeEditorField.js @@ -18,11 +18,12 @@ function CodeEditorField({ id, name, label, - tooltip, - helperText, - validate, - isRequired, + tooltip = null, + helperText = '', + validate = () => {}, + isRequired = false, mode, + rows = 5, ...rest }) { const [field, meta, helpers] = useField({ name, validate }); @@ -47,6 +48,7 @@ function CodeEditorField({ helpers.setValue(value); }} mode={mode} + rows={rows} /> ); @@ -63,12 +65,4 @@ CodeEditorField.propTypes = { rows: number, }; -CodeEditorField.defaultProps = { - helperText: '', - validate: () => {}, - isRequired: false, - tooltip: null, - rows: 5, -}; - export default CodeEditorField; diff --git a/awx/ui/src/components/CodeEditor/VariablesDetail.js b/awx/ui/src/components/CodeEditor/VariablesDetail.js index 6d1df2748..7a2c82384 100644 --- a/awx/ui/src/components/CodeEditor/VariablesDetail.js +++ b/awx/ui/src/components/CodeEditor/VariablesDetail.js @@ -18,11 +18,11 @@ import CodeEditor from './CodeEditor'; import { JSON_MODE, YAML_MODE } from './constants'; function VariablesDetail({ - dataCy, - helpText, + dataCy = '', + helpText = '', value, label, - rows, + rows = null, fullHeight, name, }) { @@ -158,12 +158,6 @@ VariablesDetail.propTypes = { helpText: oneOfType([node, string]), name: string.isRequired, }; -VariablesDetail.defaultProps = { - rows: null, - dataCy: '', - helpText: '', -}; - function ModeToggle({ id, label, diff --git a/awx/ui/src/components/CodeEditor/VariablesField.js b/awx/ui/src/components/CodeEditor/VariablesField.js index b9889c8e5..21f5f2da8 100644 --- a/awx/ui/src/components/CodeEditor/VariablesField.js +++ b/awx/ui/src/components/CodeEditor/VariablesField.js @@ -29,17 +29,19 @@ const StyledCheckboxField = styled(CheckboxField)` margin-left: auto; `; +const defaultValidators = {}; + function VariablesField({ id, name, label, - readOnly, - promptId, + readOnly = false, + promptId = null, tooltip, - initialMode, - onModeChange, - isRequired, - validators, + initialMode = YAML_MODE, + onModeChange = () => {}, + isRequired = false, + validators = defaultValidators, }) { const { t } = useLingui(); // track focus manually, because the Code Editor library doesn't wire @@ -192,15 +194,6 @@ VariablesField.propTypes = { isRequired: bool, validators: shape({}), }; -VariablesField.defaultProps = { - readOnly: false, - promptId: null, - initialMode: YAML_MODE, - onModeChange: () => {}, - isRequired: false, - validators: {}, -}; - function VariablesFieldInternals({ id, name, diff --git a/awx/ui/src/components/ContentError/ContentError.js b/awx/ui/src/components/ContentError/ContentError.js index 5ebf0c938..6f19d2ccc 100644 --- a/awx/ui/src/components/ContentError/ContentError.js +++ b/awx/ui/src/components/ContentError/ContentError.js @@ -15,7 +15,7 @@ import { ExclamationTriangleIcon } from '@patternfly/react-icons'; import { useSession } from 'contexts/Session'; import ErrorDetail from '../ErrorDetail'; -function ContentError({ error, children, isNotFound }) { +function ContentError({ error = null, children, isNotFound = false }) { const { t } = useLingui(); const { logout } = useSession(); @@ -58,10 +58,5 @@ ContentError.propTypes = { error: instanceOf(Error), isNotFound: bool, }; -ContentError.defaultProps = { - error: null, - isNotFound: false, -}; - export { ContentError as _ContentError }; export default ContentError; diff --git a/awx/ui/src/components/CopyButton/CopyButton.js b/awx/ui/src/components/CopyButton/CopyButton.js index 599aec5bb..a5d2a03b5 100644 --- a/awx/ui/src/components/CopyButton/CopyButton.js +++ b/awx/ui/src/components/CopyButton/CopyButton.js @@ -10,11 +10,11 @@ import ErrorDetail from '../ErrorDetail'; function CopyButton({ id, copyItem, - isDisabled, + isDisabled = false, onCopyStart, onCopyFinish, errorMessage, - ouiaId, + ouiaId = null, }) { const { t } = useLingui(); const { @@ -69,9 +69,4 @@ CopyButton.propTypes = { ouiaId: PropTypes.string, }; -CopyButton.defaultProps = { - isDisabled: false, - ouiaId: null, -}; - export default CopyButton; diff --git a/awx/ui/src/components/DataListToolbar/DataListToolbar.js b/awx/ui/src/components/DataListToolbar/DataListToolbar.js index 0055b92c4..ffc1af1a8 100644 --- a/awx/ui/src/components/DataListToolbar/DataListToolbar.js +++ b/awx/ui/src/components/DataListToolbar/DataListToolbar.js @@ -35,29 +35,29 @@ const ToolbarContent = styled(PFToolbarContent)` function DataListToolbar({ isAllExpanded, onExpandAll, - itemCount, - clearAllFilters, + itemCount = 0, + clearAllFilters = null, searchColumns, - searchableKeys, - relatedSearchableKeys, - sortColumns, - isAllSelected, - onSelectAll, - isCompact, - onSort, - onSearch, - onReplaceSearch, + searchableKeys = [], + relatedSearchableKeys = [], + sortColumns = null, + isAllSelected = false, + onSelectAll = null, + isCompact = false, + onSort = null, + onSearch = null, + onReplaceSearch = null, onRemove, - onCompact, - onExpand, - additionalControls, + onCompact = null, + onExpand = null, + additionalControls = [], qsConfig, pagination, - enableNegativeFiltering, - enableRelatedFuzzyFiltering, + enableNegativeFiltering = true, + enableRelatedFuzzyFiltering = true, handleIsAnsibleFactsSelected, isFilterCleared, - advancedSearchDisabled, + advancedSearchDisabled = false, }) { const { t } = useLingui(); const showExpandCollapse = onCompact && onExpand; @@ -230,24 +230,4 @@ DataListToolbar.propTypes = { advancedSearchDisabled: PropTypes.bool, }; -DataListToolbar.defaultProps = { - itemCount: 0, - searchableKeys: [], - relatedSearchableKeys: [], - sortColumns: null, - clearAllFilters: null, - isAllSelected: false, - isCompact: false, - onCompact: null, - onExpand: null, - onSearch: null, - onReplaceSearch: null, - onSelectAll: null, - onSort: null, - additionalControls: [], - enableNegativeFiltering: true, - enableRelatedFuzzyFiltering: true, - advancedSearchDisabled: false, -}; - export default DataListToolbar; diff --git a/awx/ui/src/components/DeleteButton/DeleteButton.js b/awx/ui/src/components/DeleteButton/DeleteButton.js index c1bf06069..0b3610a51 100644 --- a/awx/ui/src/components/DeleteButton/DeleteButton.js +++ b/awx/ui/src/components/DeleteButton/DeleteButton.js @@ -24,7 +24,7 @@ function DeleteButton({ variant, children, isDisabled, - ouiaId, + ouiaId = null, deleteMessage, deleteDetailsRequests, disabledTooltip, @@ -155,8 +155,4 @@ DeleteButton.propTypes = { ouiaId: PropTypes.string, }; -DeleteButton.defaultProps = { - ouiaId: null, -}; - export default DeleteButton; diff --git a/awx/ui/src/components/DetailList/CodeDetail.js b/awx/ui/src/components/DetailList/CodeDetail.js index 9a6a27f3f..d1f66d369 100644 --- a/awx/ui/src/components/DetailList/CodeDetail.js +++ b/awx/ui/src/components/DetailList/CodeDetail.js @@ -13,7 +13,14 @@ import { DetailName, DetailValue } from './Detail'; import CodeEditor from '../CodeEditor'; import Popover from '../Popover'; -function CodeDetail({ value, label, mode, rows, helpText, dataCy }) { +function CodeDetail({ + value, + label, + mode, + rows = null, + helpText = '', + dataCy = '', +}) { const labelCy = dataCy ? `${dataCy}-label` : null; const valueCy = dataCy ? `${dataCy}-value` : null; const editorId = dataCy ? `${dataCy}-editor` : 'code-editor'; @@ -65,10 +72,4 @@ CodeDetail.propTypes = { rows: oneOfType([number, string]), mode: oneOf(['json', 'javascript', 'yaml', 'jinja2']).isRequired, }; -CodeDetail.defaultProps = { - rows: null, - helpText: '', - dataCy: '', -}; - export default CodeDetail; diff --git a/awx/ui/src/components/DetailList/Detail.js b/awx/ui/src/components/DetailList/Detail.js index bd89cfdd2..b7beeac7b 100644 --- a/awx/ui/src/components/DetailList/Detail.js +++ b/awx/ui/src/components/DetailList/Detail.js @@ -36,13 +36,13 @@ const DetailValue = styled( const Detail = ({ label, - value, - fullWidth, + value = null, + fullWidth = false, className, dataCy, - alwaysVisible, + alwaysVisible = false, isEmpty, - helpText, + helpText = null, isEncrypted, isNotConfigured, }) => { @@ -89,13 +89,6 @@ Detail.propTypes = { alwaysVisible: bool, helpText: oneOfType([string, node]), }; -Detail.defaultProps = { - value: null, - fullWidth: false, - alwaysVisible: false, - helpText: null, -}; - export default Detail; export { DetailName }; export { DetailValue }; diff --git a/awx/ui/src/components/DetailList/UserDateDetail.js b/awx/ui/src/components/DetailList/UserDateDetail.js index 2803983da..b0e54eee3 100644 --- a/awx/ui/src/components/DetailList/UserDateDetail.js +++ b/awx/ui/src/components/DetailList/UserDateDetail.js @@ -11,7 +11,7 @@ const Detail = styled(_Detail)` word-break: break-word; `; -function UserDateDetail({ label, date, user }) { +function UserDateDetail({ label, date, user = null }) { const dateStr = formatDateString(date); const username = user ? user.username : ''; return ( @@ -35,8 +35,4 @@ UserDateDetail.propTypes = { date: string.isRequired, user: SummaryFieldUser, }; -UserDateDetail.defaultProps = { - user: null, -}; - export default UserDateDetail; diff --git a/awx/ui/src/components/DisassociateButton/DisassociateButton.js b/awx/ui/src/components/DisassociateButton/DisassociateButton.js index f18fbe8c6..df4a2e85d 100644 --- a/awx/ui/src/components/DisassociateButton/DisassociateButton.js +++ b/awx/ui/src/components/DisassociateButton/DisassociateButton.js @@ -167,12 +167,6 @@ function DisassociateButton({ ); } -DisassociateButton.defaultProps = { - itemsToDisassociate: [], - modalNote: '', - modalTitle: '', -}; - DisassociateButton.propTypes = { itemsToDisassociate: oneOfType([ arrayOf( diff --git a/awx/ui/src/components/ErrorDetail/ErrorDetail.js b/awx/ui/src/components/ErrorDetail/ErrorDetail.js index ea4b689f8..3dae8b2bf 100644 --- a/awx/ui/src/components/ErrorDetail/ErrorDetail.js +++ b/awx/ui/src/components/ErrorDetail/ErrorDetail.js @@ -33,7 +33,7 @@ const Expandable = styled(PFExpandable)` } `; -function ErrorDetail({ error }) { +function ErrorDetail({ error = null }) { const { t } = useLingui(); const { response } = error; const [isExpanded, setIsExpanded] = useState(false); @@ -101,8 +101,4 @@ function ErrorDetail({ error }) { ErrorDetail.propTypes = { error: PropTypes.instanceOf(Error), }; -ErrorDetail.defaultProps = { - error: null, -}; - export default ErrorDetail; diff --git a/awx/ui/src/components/ExecutionEnvironmentDetail/ExecutionEnvironmentDetail.js b/awx/ui/src/components/ExecutionEnvironmentDetail/ExecutionEnvironmentDetail.js index e13a3572d..5af2c8f4d 100644 --- a/awx/ui/src/components/ExecutionEnvironmentDetail/ExecutionEnvironmentDetail.js +++ b/awx/ui/src/components/ExecutionEnvironmentDetail/ExecutionEnvironmentDetail.js @@ -26,12 +26,12 @@ const ExclamationTrianglePopover = styled(PFExclamationTriangleIcon)` ExclamationTrianglePopover.displayName = 'ExclamationTrianglePopover'; function ExecutionEnvironmentDetail({ - executionEnvironment, - isDefaultEnvironment, - virtualEnvironment, - verifyMissingVirtualEnv, - helpText, - dataCy, + executionEnvironment = null, + isDefaultEnvironment = false, + virtualEnvironment = '', + verifyMissingVirtualEnv = true, + helpText = '', + dataCy = 'execution-environment-detail', }) { const { t } = useLingui(); const config = useConfig(); @@ -137,13 +137,4 @@ ExecutionEnvironmentDetail.propTypes = { dataCy: string, }; -ExecutionEnvironmentDetail.defaultProps = { - isDefaultEnvironment: false, - executionEnvironment: null, - virtualEnvironment: '', - verifyMissingVirtualEnv: true, - helpText: '', - dataCy: 'execution-environment-detail', -}; - export default ExecutionEnvironmentDetail; diff --git a/awx/ui/src/components/ExpandCollapse/ExpandCollapse.js b/awx/ui/src/components/ExpandCollapse/ExpandCollapse.js index 6d0679b2b..fdf78c3e5 100644 --- a/awx/ui/src/components/ExpandCollapse/ExpandCollapse.js +++ b/awx/ui/src/components/ExpandCollapse/ExpandCollapse.js @@ -31,7 +31,7 @@ const ToolbarItem = styled(PFToolbarItem)` // TODO: Recommend renaming this component to avoid confusion // with ExpandingContainer -function ExpandCollapse({ isCompact, onCompact, onExpand }) { +function ExpandCollapse({ isCompact = true, onCompact, onExpand }) { const { t } = useLingui(); return ( <> @@ -67,8 +67,4 @@ ExpandCollapse.propTypes = { isCompact: PropTypes.bool, }; -ExpandCollapse.defaultProps = { - isCompact: true, -}; - export default ExpandCollapse; diff --git a/awx/ui/src/components/FieldWithPrompt/FieldWithPrompt.js b/awx/ui/src/components/FieldWithPrompt/FieldWithPrompt.js index 3c8c5c1f8..baffc6913 100644 --- a/awx/ui/src/components/FieldWithPrompt/FieldWithPrompt.js +++ b/awx/ui/src/components/FieldWithPrompt/FieldWithPrompt.js @@ -19,11 +19,11 @@ const StyledCheckboxField = styled(CheckboxField)` function FieldWithPrompt({ children, fieldId, - isRequired, + isRequired = false, label, promptId, promptName, - tooltip, + tooltip = null, isDisabled, }) { const { t } = useLingui(); @@ -63,9 +63,4 @@ FieldWithPrompt.propTypes = { tooltip: node, }; -FieldWithPrompt.defaultProps = { - isRequired: false, - tooltip: null, -}; - export default FieldWithPrompt; diff --git a/awx/ui/src/components/FormActionGroup/FormActionGroup.js b/awx/ui/src/components/FormActionGroup/FormActionGroup.js index 3b1d247d4..4cfd0e8d6 100644 --- a/awx/ui/src/components/FormActionGroup/FormActionGroup.js +++ b/awx/ui/src/components/FormActionGroup/FormActionGroup.js @@ -5,7 +5,7 @@ import { useLingui } from '@lingui/react/macro'; import { ActionGroup, Button } from '@patternfly/react-core'; import { FormFullWidthLayout } from '../FormLayout'; -const FormActionGroup = ({ onCancel, onSubmit, submitDisabled }) => { +const FormActionGroup = ({ onCancel, onSubmit, submitDisabled = false }) => { const { t } = useLingui(); return ( @@ -41,8 +41,4 @@ FormActionGroup.propTypes = { submitDisabled: PropTypes.bool, }; -FormActionGroup.defaultProps = { - submitDisabled: false, -}; - export default FormActionGroup; diff --git a/awx/ui/src/components/FormField/ArrayTextField.js b/awx/ui/src/components/FormField/ArrayTextField.js index f96505682..00ad86ca6 100644 --- a/awx/ui/src/components/FormField/ArrayTextField.js +++ b/awx/ui/src/components/FormField/ArrayTextField.js @@ -4,20 +4,18 @@ import { useField } from 'formik'; import { FormGroup, TextArea } from '@patternfly/react-core'; import Popover from '../Popover'; -function ArrayTextField(props) { - const { - id, - helperText, - name, - label, - tooltip, - tooltipMaxWidth, - validate, - isRequired, - type, - ...rest - } = props; - +function ArrayTextField({ + id, + helperText = '', + name, + label, + tooltip = null, + tooltipMaxWidth = '', + validate = () => {}, + isRequired = false, + type, + ...rest +}) { const [field, meta, helpers] = useField({ name, validate }); const isValid = !(meta.touched && meta.error); const value = field.value || []; @@ -63,12 +61,4 @@ ArrayTextField.propTypes = { tooltipMaxWidth: PropTypes.string, }; -ArrayTextField.defaultProps = { - helperText: '', - validate: () => {}, - isRequired: false, - tooltip: null, - tooltipMaxWidth: '', -}; - export default ArrayTextField; diff --git a/awx/ui/src/components/FormField/CheckboxField.js b/awx/ui/src/components/FormField/CheckboxField.js index daa8677ca..abe2f5333 100644 --- a/awx/ui/src/components/FormField/CheckboxField.js +++ b/awx/ui/src/components/FormField/CheckboxField.js @@ -8,8 +8,8 @@ function CheckboxField({ id, name, label, - tooltip, - validate, + tooltip = '', + validate = () => {}, isDisabled, ...rest }) { @@ -43,9 +43,4 @@ CheckboxField.propTypes = { validate: func, tooltip: node, }; -CheckboxField.defaultProps = { - validate: () => {}, - tooltip: '', -}; - export default CheckboxField; diff --git a/awx/ui/src/components/FormField/FormField.js b/awx/ui/src/components/FormField/FormField.js index 20a3dfec1..af0468f62 100644 --- a/awx/ui/src/components/FormField/FormField.js +++ b/awx/ui/src/components/FormField/FormField.js @@ -5,20 +5,18 @@ import { useField } from 'formik'; import { FormGroup, TextInput, TextArea } from '@patternfly/react-core'; import Popover from '../Popover'; -function FormField(props) { - const { - id, - helperText, - name, - label, - tooltip, - tooltipMaxWidth, - validate, - isRequired, - type, - ...rest - } = props; - +function FormField({ + id, + helperText = '', + name, + label, + tooltip = null, + tooltipMaxWidth = '', + validate = () => {}, + isRequired = false, + type = 'text', + ...rest +}) { const [field, meta] = useField({ name, validate }); const isValid = !(meta.touched && meta.error); @@ -87,13 +85,4 @@ FormField.propTypes = { tooltipMaxWidth: PropTypes.string, }; -FormField.defaultProps = { - helperText: '', - type: 'text', - validate: () => {}, - isRequired: false, - tooltip: null, - tooltipMaxWidth: '', -}; - export default FormField; diff --git a/awx/ui/src/components/FormField/PasswordField.js b/awx/ui/src/components/FormField/PasswordField.js index 44ebe5f88..2133e8ab9 100644 --- a/awx/ui/src/components/FormField/PasswordField.js +++ b/awx/ui/src/components/FormField/PasswordField.js @@ -5,8 +5,15 @@ import { FormGroup, InputGroup } from '@patternfly/react-core'; import Popover from '../Popover'; import PasswordInput from './PasswordInput'; -function PasswordField(props) { - const { id, name, label, validate, isRequired, helperText } = props; +function PasswordField({ + id, + name, + label, + validate = () => {}, + isRequired = false, + helperText, + ...rest +}) { const [, meta] = useField({ name, validate }); const isValid = !(meta.touched && meta.error); @@ -20,7 +27,15 @@ function PasswordField(props) { labelIcon={helperText && } > - + ); @@ -35,10 +50,4 @@ PasswordField.propTypes = { isDisabled: PropTypes.bool, }; -PasswordField.defaultProps = { - validate: () => {}, - isRequired: false, - isDisabled: false, -}; - export default PasswordField; diff --git a/awx/ui/src/components/FormField/PasswordInput.js b/awx/ui/src/components/FormField/PasswordInput.js index 9ed652983..dd7bcb92e 100644 --- a/awx/ui/src/components/FormField/PasswordInput.js +++ b/awx/ui/src/components/FormField/PasswordInput.js @@ -11,17 +11,16 @@ import { } from '@patternfly/react-core'; import { EyeIcon, EyeSlashIcon } from '@patternfly/react-icons'; -function PasswordInput(props) { +function PasswordInput({ + autocomplete = 'new-password', + id, + name, + validate = () => {}, + isFieldGroupValid, + isRequired = false, + isDisabled = false, +}) { const { t } = useLingui(); - const { - autocomplete, - id, - name, - validate, - isFieldGroupValid, - isRequired, - isDisabled, - } = props; const [inputType, setInputType] = useState('password'); const [field, meta] = useField({ name, validate }); @@ -76,11 +75,4 @@ PasswordInput.propTypes = { isDisabled: PropTypes.bool, }; -PasswordInput.defaultProps = { - autocomplete: 'new-password', - validate: () => {}, - isRequired: false, - isDisabled: false, -}; - export default PasswordInput; diff --git a/awx/ui/src/components/HostForm/HostForm.js b/awx/ui/src/components/HostForm/HostForm.js index a8d1d6b5c..b2f5e19e2 100644 --- a/awx/ui/src/components/HostForm/HostForm.js +++ b/awx/ui/src/components/HostForm/HostForm.js @@ -73,10 +73,18 @@ const InventoryLookupField = ({ isDisabled }) => { const HostForm = ({ handleCancel, handleSubmit, - host, - isInventoryVisible, - submitError, - disableInventoryLookup, + host = { + name: '', + description: '', + inventory: undefined, + variables: '---\n', + summary_fields: { + inventory: null, + }, + }, + isInventoryVisible = true, + submitError = null, + disableInventoryLookup = false, }) => { const { t } = useLingui(); return ( @@ -137,20 +145,5 @@ HostForm.propTypes = { disableInventoryLookup: bool, }; -HostForm.defaultProps = { - host: { - name: '', - description: '', - inventory: undefined, - variables: '---\n', - summary_fields: { - inventory: null, - }, - }, - isInventoryVisible: true, - submitError: null, - disableInventoryLookup: false, -}; - export { HostForm as _HostForm }; export default HostForm; diff --git a/awx/ui/src/components/InstanceGroupLabels/InstanceGroupLabels.js b/awx/ui/src/components/InstanceGroupLabels/InstanceGroupLabels.js index e3d89f928..f6fe77fda 100644 --- a/awx/ui/src/components/InstanceGroupLabels/InstanceGroupLabels.js +++ b/awx/ui/src/components/InstanceGroupLabels/InstanceGroupLabels.js @@ -4,7 +4,7 @@ import { arrayOf, bool, number, shape, string } from 'prop-types'; import { Label, LabelGroup } from '@patternfly/react-core'; import { Link } from 'react-router-dom'; -function InstanceGroupLabels({ labels, isLinkable }) { +function InstanceGroupLabels({ labels, isLinkable = false }) { const buildLinkURL = (isContainerGroup) => isContainerGroup ? '/instance_groups/container_group/' @@ -44,6 +44,4 @@ InstanceGroupLabels.propTypes = { isLinkable: bool, }; -InstanceGroupLabels.defaultProps = { isLinkable: false }; - export default InstanceGroupLabels; diff --git a/awx/ui/src/components/JobList/JobListCancelButton.js b/awx/ui/src/components/JobList/JobListCancelButton.js index 646bcd330..75df44113 100644 --- a/awx/ui/src/components/JobList/JobListCancelButton.js +++ b/awx/ui/src/components/JobList/JobListCancelButton.js @@ -17,7 +17,7 @@ function cannotCancelBecauseNotRunning(job) { return !isJobRunning(job.status); } -function JobListCancelButton({ jobsToCancel, onCancel }) { +function JobListCancelButton({ jobsToCancel = [], onCancel = () => {} }) { const { t } = useLingui(); const { isKebabified, onKebabModalChange } = useContext(KebabifiedContext); const [isModalOpen, setIsModalOpen] = useState(false); @@ -188,9 +188,4 @@ JobListCancelButton.propTypes = { onCancel: func, }; -JobListCancelButton.defaultProps = { - jobsToCancel: [], - onCancel: () => {}, -}; - export default JobListCancelButton; diff --git a/awx/ui/src/components/LabelSelect/LabelSelect.js b/awx/ui/src/components/LabelSelect/LabelSelect.js index 3d1cb8a75..016e56126 100644 --- a/awx/ui/src/components/LabelSelect/LabelSelect.js +++ b/awx/ui/src/components/LabelSelect/LabelSelect.js @@ -40,7 +40,13 @@ async function loadLabelOptions(setLabels, onError, isMounted) { } } -function LabelSelect({ value, placeholder, onChange, onError, createText }) { +function LabelSelect({ + value, + placeholder = '', + onChange, + onError, + createText, +}) { const [isLoading, setIsLoading] = useState(true); const [isExpanded, setIsExpanded] = useState(false); const isMounted = useIsMounted(); @@ -147,8 +153,4 @@ LabelSelect.propTypes = { onChange: func.isRequired, onError: func.isRequired, }; -LabelSelect.defaultProps = { - placeholder: '', -}; - export default LabelSelect; diff --git a/awx/ui/src/components/ListHeader/ListHeader.js b/awx/ui/src/components/ListHeader/ListHeader.js index e9aff4f03..9ae5a2fd1 100644 --- a/awx/ui/src/components/ListHeader/ListHeader.js +++ b/awx/ui/src/components/ListHeader/ListHeader.js @@ -26,21 +26,20 @@ const EmptyStateControlsWrapper = styled.div` margin-left: 20px; } `; -function ListHeader(props) { +function ListHeader({ + emptyStateControls, + itemCount, + pagination, + qsConfig, + relatedSearchableKeys = [], + renderToolbar = (toolbarProps) => , + searchColumns, + searchableKeys = [], + sortColumns = null, +}) { const { search, pathname } = useLocation(); const [isFilterCleared, setIsFilterCleared] = useState(false); const navigate = useNavigate(); - const { - emptyStateControls, - itemCount, - pagination, - qsConfig, - relatedSearchableKeys, - renderToolbar, - searchColumns, - searchableKeys, - sortColumns, - } = props; const handleSearch = (key, value) => { const params = parseQueryString(qsConfig, search); @@ -141,11 +140,4 @@ ListHeader.propTypes = { renderToolbar: PropTypes.func, }; -ListHeader.defaultProps = { - renderToolbar: (props) => , - searchableKeys: [], - sortColumns: null, - relatedSearchableKeys: [], -}; - export default ListHeader; diff --git a/awx/ui/src/components/Lookup/ApplicationLookup.js b/awx/ui/src/components/Lookup/ApplicationLookup.js index 4309c59bf..3a14fde85 100644 --- a/awx/ui/src/components/Lookup/ApplicationLookup.js +++ b/awx/ui/src/components/Lookup/ApplicationLookup.js @@ -18,7 +18,13 @@ const QS_CONFIG = getQSConfig('applications', { order_by: 'name', }); -function ApplicationLookup({ onChange, value, label, fieldName, validate }) { +function ApplicationLookup({ + onChange, + value = null, + label, + fieldName = 'application', + validate = () => undefined, +}) { const { t } = useLingui(); const location = useLocation(); const { @@ -146,10 +152,4 @@ ApplicationLookup.propTypes = { fieldName: string, }; -ApplicationLookup.defaultProps = { - value: null, - validate: () => undefined, - fieldName: 'application', -}; - export default ApplicationLookup; diff --git a/awx/ui/src/components/Lookup/CredentialLookup.js b/awx/ui/src/components/Lookup/CredentialLookup.js index cf2b3b68c..8b6960cfa 100644 --- a/awx/ui/src/components/Lookup/CredentialLookup.js +++ b/awx/ui/src/components/Lookup/CredentialLookup.js @@ -30,24 +30,24 @@ const QS_CONFIG = getQSConfig('credentials', { }); function CredentialLookup({ - autoPopulate, - credentialTypeId, - credentialTypeKind, + autoPopulate = false, + credentialTypeId = '', + credentialTypeKind = '', credentialTypeNamespace, - fieldName, - helperTextInvalid, - isDisabled, + fieldName = 'credential', + helperTextInvalid = '', + isDisabled = false, isSelectedDraggable, - isValid, + isValid = true, label, modalDescription, - multiple, - onBlur, + multiple = false, + onBlur = () => {}, onChange, - required, + required = false, tooltip, - validate, - value, + validate = () => undefined, + value = null, }) { const { t } = useLingui(); const location = useLocation(); @@ -233,16 +233,17 @@ function CredentialLookup({ function idOrKind(props, propName, componentName) { let error; + // credentialTypeKind formerly defaulted to '' via defaultProps, which React + // applied to the element's props BEFORE running PropTypes — so this validator + // always saw a present empty string and never fired (callers may pass + // credentialTypeNamespace instead of id/kind). Default params don't reach + // PropTypes, so treat an omitted/undefined value as that former '' default to + // preserve behavior. + const kindValue = + props.credentialTypeKind === undefined ? '' : props.credentialTypeKind; if ( !Object.prototype.hasOwnProperty.call(props, 'credentialTypeId') && - !Object.prototype.hasOwnProperty.call(props, 'credentialTypeKind') - ) - error = new Error( - `Either "credentialTypeId" or "credentialTypeKind" is required` - ); - if ( - !Object.prototype.hasOwnProperty.call(props, 'credentialTypeId') && - typeof props[propName] !== 'string' + typeof kindValue !== 'string' ) { error = new Error( `Invalid prop '${propName}' '${props[propName]}' supplied to '${componentName}'.` @@ -268,20 +269,5 @@ CredentialLookup.propTypes = { fieldName: string, }; -CredentialLookup.defaultProps = { - credentialTypeId: '', - credentialTypeKind: '', - helperTextInvalid: '', - isValid: true, - multiple: false, - onBlur: () => {}, - required: false, - value: null, - isDisabled: false, - autoPopulate: false, - validate: () => undefined, - fieldName: 'credential', -}; - export { CredentialLookup as _CredentialLookup }; export default CredentialLookup; diff --git a/awx/ui/src/components/Lookup/CredentialLookup.test.js b/awx/ui/src/components/Lookup/CredentialLookup.test.js index d3a59bcc0..20d4c7a3a 100644 --- a/awx/ui/src/components/Lookup/CredentialLookup.test.js +++ b/awx/ui/src/components/Lookup/CredentialLookup.test.js @@ -74,11 +74,6 @@ describe('CredentialLookup', () => { expect(await screen.findByText('Foo')).toBeInTheDocument(); }); - test('should define default value for function props', () => { - expect(_CredentialLookup.defaultProps.onBlur).toBeInstanceOf(Function); - expect(_CredentialLookup.defaultProps.onBlur).not.toThrow(); - }); - test('should not auto-select credential when autoPopulate prop is false', async () => { CredentialsAPI.read.mockResolvedValue({ data: { diff --git a/awx/ui/src/components/Lookup/ExecutionEnvironmentLookup.js b/awx/ui/src/components/Lookup/ExecutionEnvironmentLookup.js index ec84d19be..5bdf399ab 100644 --- a/awx/ui/src/components/Lookup/ExecutionEnvironmentLookup.js +++ b/awx/ui/src/components/Lookup/ExecutionEnvironmentLookup.js @@ -21,21 +21,21 @@ const QS_CONFIG = getQSConfig('execution_environments', { }); function ExecutionEnvironmentLookup({ - id, + id = 'execution-environments', globallyAvailable, helperTextInvalid, isDisabled, isValid, onBlur, onChange, - organizationId, - popoverContent, - projectId, + organizationId = null, + popoverContent = '', + projectId = null, tooltip, - validate, - value, - fieldName, - overrideLabel, + validate = () => undefined, + value = null, + fieldName = 'execution_environment', + overrideLabel = false, isPromptableField, promptId, promptName, @@ -254,15 +254,4 @@ ExecutionEnvironmentLookup.propTypes = { overrideLabel: bool, }; -ExecutionEnvironmentLookup.defaultProps = { - id: 'execution-environments', - popoverContent: '', - value: null, - projectId: null, - organizationId: null, - validate: () => undefined, - fieldName: 'execution_environment', - overrideLabel: false, -}; - export default ExecutionEnvironmentLookup; diff --git a/awx/ui/src/components/Lookup/HostFilterLookup.js b/awx/ui/src/components/Lookup/HostFilterLookup.js index 56fc66f27..72a2bf5c8 100644 --- a/awx/ui/src/components/Lookup/HostFilterLookup.js +++ b/awx/ui/src/components/Lookup/HostFilterLookup.js @@ -92,14 +92,14 @@ const QS_CONFIG = getQSConfig( function HostFilterLookup({ helperTextInvalid, - isValid, + isValid = true, isDisabled, - onBlur, - onChange, - organizationId, - value, - enableNegativeFiltering, - enableRelatedFuzzyFiltering, + onBlur = () => {}, + onChange = () => {}, + organizationId = null, + value = '', + enableNegativeFiltering = true, + enableRelatedFuzzyFiltering = true, }) { const { t } = useLingui(); const navigate = useNavigate(); @@ -465,14 +465,4 @@ HostFilterLookup.propTypes = { enableNegativeFiltering: bool, enableRelatedFuzzyFiltering: bool, }; -HostFilterLookup.defaultProps = { - isValid: true, - onBlur: () => {}, - onChange: () => {}, - organizationId: null, - value: '', - enableNegativeFiltering: true, - enableRelatedFuzzyFiltering: true, -}; - export default HostFilterLookup; diff --git a/awx/ui/src/components/Lookup/InstanceGroupsLookup.js b/awx/ui/src/components/Lookup/InstanceGroupsLookup.js index c5e63fe8d..3bacb1303 100644 --- a/awx/ui/src/components/Lookup/InstanceGroupsLookup.js +++ b/awx/ui/src/components/Lookup/InstanceGroupsLookup.js @@ -21,14 +21,14 @@ const QS_CONFIG = getQSConfig('instance-groups', { }); function InstanceGroupsLookup({ - id, + id = 'org-instance-groups', value, onChange, - tooltip, - className, - required, - fieldName, - validate, + tooltip = '', + className = '', + required = false, + fieldName = 'instance_groups', + validate = () => undefined, isPromptableField, promptId, promptName, @@ -169,13 +169,4 @@ InstanceGroupsLookup.propTypes = { fieldName: string, }; -InstanceGroupsLookup.defaultProps = { - id: 'org-instance-groups', - tooltip: '', - className: '', - required: false, - validate: () => undefined, - fieldName: 'instance_groups', -}; - export default InstanceGroupsLookup; diff --git a/awx/ui/src/components/Lookup/InventoryLookup.js b/awx/ui/src/components/Lookup/InventoryLookup.js index 395727f9a..b68f468ee 100644 --- a/awx/ui/src/components/Lookup/InventoryLookup.js +++ b/awx/ui/src/components/Lookup/InventoryLookup.js @@ -20,20 +20,20 @@ const QS_CONFIG = getQSConfig('inventory', { }); function InventoryLookup({ - autoPopulate, - excludeIds, - fieldId, - fieldName, - hideAdvancedInventories, - isDisabled, + autoPopulate = false, + excludeIds = [], + fieldId = 'inventory', + fieldName = 'inventory', + hideAdvancedInventories = false, + isDisabled = false, isPromptableField, onBlur, onChange, promptId, promptName, - required, - validate, - value, + required = false, + validate = () => {}, + value = null, multiple, }) { const location = useLocation(); @@ -265,16 +265,4 @@ InventoryLookup.propTypes = { value: oneOfType([Inventory, arrayOf(Inventory)]), }; -InventoryLookup.defaultProps = { - autoPopulate: false, - excludeIds: [], - fieldId: 'inventory', - fieldName: 'inventory', - hideAdvancedInventories: false, - isDisabled: false, - required: false, - validate: () => {}, - value: null, -}; - export default InventoryLookup; diff --git a/awx/ui/src/components/Lookup/Lookup.js b/awx/ui/src/components/Lookup/Lookup.js index beb47cdb1..bf64007e9 100644 --- a/awx/ui/src/components/Lookup/Lookup.js +++ b/awx/ui/src/components/Lookup/Lookup.js @@ -33,26 +33,29 @@ const ChipHolder = styled.div` background-color: ${(props) => props.$isDisabled ? 'var(--pf-global--disabled-color--300)' : null}; `; -function Lookup(props) { - const { - id, - header, - onChange, - onBlur, - isLoading, - value, - multiple, - required, - qsConfig, - renderItemChip, - renderOptionsList, - isDisabled, - onDebounce, - fieldName, - validate, - modalDescription, - onUpdate, - } = props; +function Lookup({ + id = 'lookup-search', + header = null, + onChange, + onBlur = () => {}, + isLoading, + value = null, + multiple = false, + required = false, + qsConfig, + renderItemChip = ({ item, removeItem, canDelete }) => ( + removeItem(item)} isReadOnly={!canDelete}> + {item.name} + + ), + renderOptionsList, + isDisabled = false, + onDebounce = () => undefined, + fieldName, + validate = () => undefined, + modalDescription = '', + onUpdate = () => {}, +}) { const { t } = useLingui(); const location = useLocation(); const navigate = useNavigate(); @@ -255,28 +258,5 @@ Lookup.propTypes = { isDisabled: bool, }; -Lookup.defaultProps = { - id: 'lookup-search', - header: null, - value: null, - multiple: false, - required: false, - modalDescription: '', - onBlur: () => {}, - renderItemChip: ({ item, removeItem, canDelete }) => ( - removeItem(item)} - isReadOnly={!canDelete} - > - {item.name} - - ), - validate: () => undefined, - onDebounce: () => undefined, - onUpdate: () => {}, - isDisabled: false, -}; - export { Lookup as _Lookup }; export default Lookup; diff --git a/awx/ui/src/components/Lookup/MultiCredentialsLookup.js b/awx/ui/src/components/Lookup/MultiCredentialsLookup.js index 3253800d7..614ea2679 100644 --- a/awx/ui/src/components/Lookup/MultiCredentialsLookup.js +++ b/awx/ui/src/components/Lookup/MultiCredentialsLookup.js @@ -26,11 +26,11 @@ async function loadCredentials(params, selectedCredentialTypeId) { } function MultiCredentialsLookup({ - value, + value = [], onChange, onError, - fieldName, - validate, + fieldName = 'credentials', + validate = () => undefined, }) { const location = useLocation(); const navigate = useNavigate(); @@ -260,11 +260,5 @@ MultiCredentialsLookup.propTypes = { fieldName: PropTypes.string, }; -MultiCredentialsLookup.defaultProps = { - value: [], - validate: () => undefined, - fieldName: 'credentials', -}; - export { MultiCredentialsLookup as _MultiCredentialsLookup }; export default MultiCredentialsLookup; diff --git a/awx/ui/src/components/Lookup/OrganizationLookup.js b/awx/ui/src/components/Lookup/OrganizationLookup.js index af8ff8c25..40b5ff660 100644 --- a/awx/ui/src/components/Lookup/OrganizationLookup.js +++ b/awx/ui/src/components/Lookup/OrganizationLookup.js @@ -20,18 +20,18 @@ const QS_CONFIG = getQSConfig('organizations', { }); function OrganizationLookup({ - id, - helperTextInvalid, - isValid, - onBlur, + id = 'organization', + helperTextInvalid = '', + isValid = true, + onBlur = () => {}, onChange, - required, - value, - autoPopulate, - isDisabled, + required = false, + value = null, + autoPopulate = false, + isDisabled = false, helperText, - validate, - fieldName, + validate = () => undefined, + fieldName = 'organization', }) { const location = useLocation(); const { t } = useLingui(); @@ -173,18 +173,5 @@ OrganizationLookup.propTypes = { fieldName: string, }; -OrganizationLookup.defaultProps = { - id: 'organization', - helperTextInvalid: '', - isValid: true, - onBlur: () => {}, - required: false, - value: null, - autoPopulate: false, - isDisabled: false, - validate: () => undefined, - fieldName: 'organization', -}; - export { OrganizationLookup as _OrganizationLookup }; export default OrganizationLookup; diff --git a/awx/ui/src/components/Lookup/OrganizationLookup.test.js b/awx/ui/src/components/Lookup/OrganizationLookup.test.js index 633ffeb94..757d48141 100644 --- a/awx/ui/src/components/Lookup/OrganizationLookup.test.js +++ b/awx/ui/src/components/Lookup/OrganizationLookup.test.js @@ -58,11 +58,6 @@ describe('OrganizationLookup', () => { expect(await screen.findByText('Organization')).toBeInTheDocument(); }); - test('should define default value for function props', () => { - expect(_OrganizationLookup.defaultProps.onBlur).toBeInstanceOf(Function); - expect(_OrganizationLookup.defaultProps.onBlur).not.toThrow(); - }); - test('should auto-select organization when only one available and autoPopulate prop is true', async () => { const org = { id: 1, name: 'org', url: '/api/v2/organizations/1/' }; OrganizationsAPI.read.mockResolvedValue({ diff --git a/awx/ui/src/components/Lookup/PeersLookup.js b/awx/ui/src/components/Lookup/PeersLookup.js index 0bf46a8e5..481283509 100755 --- a/awx/ui/src/components/Lookup/PeersLookup.js +++ b/awx/ui/src/components/Lookup/PeersLookup.js @@ -20,23 +20,25 @@ const QS_CONFIG = getQSConfig('instances', { order_by: 'hostname', }); +const defaultInstanceDetails = {}; + function PeersLookup({ - id, + id = 'instances', value, onChange, - tooltip, - className, - required, - fieldName, - multiple, - validate, - columns, + tooltip = '', + className = '', + required = false, + fieldName = 'instances', + multiple = true, + validate = () => undefined, + columns = undefined, isPromptableField, promptId, promptName, - formLabel, - typePeers, - instance_details, + formLabel = undefined, + typePeers = false, + instance_details = defaultInstanceDetails, }) { const location = useLocation(); const { t } = useLingui(); @@ -187,18 +189,4 @@ PeersLookup.propTypes = { typePeers: bool, }; -PeersLookup.defaultProps = { - id: 'instances', - tooltip: '', - className: '', - required: false, - validate: () => undefined, - fieldName: 'instances', - columns: undefined, - formLabel: undefined, - instance_details: {}, - multiple: true, - typePeers: false, -}; - export default PeersLookup; diff --git a/awx/ui/src/components/Lookup/ProjectLookup.js b/awx/ui/src/components/Lookup/ProjectLookup.js index 26492e282..0decf071e 100644 --- a/awx/ui/src/components/Lookup/ProjectLookup.js +++ b/awx/ui/src/components/Lookup/ProjectLookup.js @@ -22,17 +22,17 @@ const QS_CONFIG = getQSConfig('project', { }); function ProjectLookup({ - helperTextInvalid, - autoPopulate, - isValid, + helperTextInvalid = '', + autoPopulate = false, + isValid = true, onChange, - required, - tooltip, - value, - onBlur, - isOverrideDisabled, - validate, - fieldName, + required = false, + tooltip = '', + value = null, + onBlur = () => {}, + isOverrideDisabled = false, + validate = () => undefined, + fieldName = 'project', }) { const location = useLocation(); const { t } = useLingui(); @@ -192,18 +192,5 @@ ProjectLookup.propTypes = { fieldName: string, }; -ProjectLookup.defaultProps = { - autoPopulate: false, - helperTextInvalid: '', - isValid: true, - onBlur: () => {}, - required: false, - tooltip: '', - value: null, - isOverrideDisabled: false, - validate: () => undefined, - fieldName: 'project', -}; - export { ProjectLookup as _ProjectLookup }; export default ProjectLookup; diff --git a/awx/ui/src/components/NotificationList/NotificationList.js b/awx/ui/src/components/NotificationList/NotificationList.js index e0617c877..9996e2a73 100644 --- a/awx/ui/src/components/NotificationList/NotificationList.js +++ b/awx/ui/src/components/NotificationList/NotificationList.js @@ -26,7 +26,7 @@ function NotificationList({ canToggleNotifications, id, - showApprovalsToggle, + showApprovalsToggle = false, }) { const { t } = useLingui(); const location = useLocation(); @@ -265,8 +265,4 @@ NotificationList.propTypes = { showApprovalsToggle: bool, }; -NotificationList.defaultProps = { - showApprovalsToggle: false, -}; - export default NotificationList; diff --git a/awx/ui/src/components/NotificationList/NotificationListItem.js b/awx/ui/src/components/NotificationList/NotificationListItem.js index 37c04e9ef..7a9d53bb0 100644 --- a/awx/ui/src/components/NotificationList/NotificationListItem.js +++ b/awx/ui/src/components/NotificationList/NotificationListItem.js @@ -12,14 +12,14 @@ function NotificationListItem({ canToggleNotifications, notification, detailUrl, - approvalsTurnedOn, - startedTurnedOn, - successTurnedOn, - errorTurnedOn, + approvalsTurnedOn = false, + startedTurnedOn = false, + successTurnedOn = false, + errorTurnedOn = false, toggleNotification, typeLabels, - showApprovalsToggle, + showApprovalsToggle = false, }) { const { t } = useLingui(); return ( @@ -121,12 +121,4 @@ NotificationListItem.propTypes = { showApprovalsToggle: bool, }; -NotificationListItem.defaultProps = { - approvalsTurnedOn: false, - errorTurnedOn: false, - startedTurnedOn: false, - successTurnedOn: false, - showApprovalsToggle: false, -}; - export default NotificationListItem; diff --git a/awx/ui/src/components/OptionsList/OptionsList.js b/awx/ui/src/components/OptionsList/OptionsList.js index c69b0a527..223496c80 100644 --- a/awx/ui/src/components/OptionsList/OptionsList.js +++ b/awx/ui/src/components/OptionsList/OptionsList.js @@ -26,22 +26,22 @@ function OptionsList({ columns, contentError, deselectItem, - displayKey, + displayKey = 'name', header, isLoading, - isSelectedDraggable, - multiple, + isSelectedDraggable = false, + multiple = false, name, optionCount, options, qsConfig, readOnly, relatedSearchableKeys, - renderItemChip, - searchColumns, + renderItemChip = null, + searchColumns = [], searchableKeys, selectItem, - sortColumns, + sortColumns = [], sortSelectedItems, value, }) { @@ -145,13 +145,5 @@ OptionsList.propTypes = { sortColumns: SortColumns, value: oneOfType([arrayOf(Item), arrayOf(InstanceItem)]).isRequired, }; -OptionsList.defaultProps = { - isSelectedDraggable: false, - multiple: false, - renderItemChip: null, - searchColumns: [], - sortColumns: [], - displayKey: 'name', -}; export default OptionsList; diff --git a/awx/ui/src/components/PaginatedTable/HeaderRow.js b/awx/ui/src/components/PaginatedTable/HeaderRow.js index 13269593f..38a95c19b 100644 --- a/awx/ui/src/components/PaginatedTable/HeaderRow.js +++ b/awx/ui/src/components/PaginatedTable/HeaderRow.js @@ -14,7 +14,7 @@ const Th = styled(PFTh)` export default function HeaderRow({ qsConfig, isExpandable, - isSelectable, + isSelectable = true, children, }) { const location = useLocation(); @@ -59,10 +59,6 @@ export default function HeaderRow({ ); } -HeaderRow.defaultProps = { - isSelectable: true, -}; - export function HeaderCell({ sortKey, onSort, diff --git a/awx/ui/src/components/PaginatedTable/PaginatedTable.js b/awx/ui/src/components/PaginatedTable/PaginatedTable.js index 75c97dc62..d6758f6c2 100644 --- a/awx/ui/src/components/PaginatedTable/PaginatedTable.js +++ b/awx/ui/src/components/PaginatedTable/PaginatedTable.js @@ -19,24 +19,27 @@ import Pagination from '../Pagination'; import DataListToolbar from '../DataListToolbar'; import LoadingSpinner from '../LoadingSpinner'; +// Stable default so the clearSelected effect dep does not change every render. +const noop = () => {}; + function PaginatedTable({ - contentError, - hasContentLoading, + contentError = null, + hasContentLoading = false, emptyStateControls, items, itemCount, qsConfig, headerRow, renderRow, - toolbarSearchColumns, - toolbarSearchableKeys, - toolbarRelatedSearchableKeys, - pluralizedItemName, - showPageSizeOptions, - renderToolbar, + toolbarSearchColumns = [], + toolbarSearchableKeys = [], + toolbarRelatedSearchableKeys = [], + pluralizedItemName = null, + showPageSizeOptions = true, + renderToolbar = (props) => , emptyContentMessage, - clearSelected, - ouiaId, + clearSelected = noop, + ouiaId = null, }) { const { t } = useLingui(); const location = useLocation(); @@ -207,18 +210,5 @@ PaginatedTable.propTypes = { ouiaId: PropTypes.string, }; -PaginatedTable.defaultProps = { - hasContentLoading: false, - contentError: null, - toolbarSearchColumns: [], - toolbarSearchableKeys: [], - toolbarRelatedSearchableKeys: [], - pluralizedItemName: null, - showPageSizeOptions: true, - renderToolbar: (props) => , - ouiaId: null, - clearSelected: () => {}, -}; - export { PaginatedTable as _PaginatedTable }; export default PaginatedTable; diff --git a/awx/ui/src/components/PaginatedTable/ToolbarAddButton.js b/awx/ui/src/components/PaginatedTable/ToolbarAddButton.js index 7de33f03d..4a0e9fa3d 100644 --- a/awx/ui/src/components/PaginatedTable/ToolbarAddButton.js +++ b/awx/ui/src/components/PaginatedTable/ToolbarAddButton.js @@ -7,8 +7,8 @@ import { useLingui } from '@lingui/react/macro'; import { useKebabifiedMenu } from 'contexts/Kebabified'; function ToolbarAddButton({ - linkTo, - onClick, + linkTo = null, + onClick = null, isDisabled, defaultLabel, showToggleIndicator, @@ -64,9 +64,5 @@ ToolbarAddButton.propTypes = { linkTo: string, onClick: func, }; -ToolbarAddButton.defaultProps = { - linkTo: null, - onClick: null, -}; export default ToolbarAddButton; diff --git a/awx/ui/src/components/PaginatedTable/ToolbarDeleteButton.js b/awx/ui/src/components/PaginatedTable/ToolbarDeleteButton.js index f25737e16..11ab33ff7 100644 --- a/awx/ui/src/components/PaginatedTable/ToolbarDeleteButton.js +++ b/awx/ui/src/components/PaginatedTable/ToolbarDeleteButton.js @@ -88,13 +88,13 @@ const ItemToDelete = shape({ function ToolbarDeleteButton({ itemsToDelete, - pluralizedItemName, + pluralizedItemName = 'Items', errorMessage, onDelete, deleteDetailsRequests, - warningMessage, + warningMessage = null, deleteMessage, - cannotDelete, + cannotDelete = (item) => !item.summary_fields.user_capabilities.delete, }) { const { t } = useLingui(); const { isKebabified, onKebabModalChange } = useContext(KebabifiedContext); @@ -312,10 +312,4 @@ ToolbarDeleteButton.propTypes = { cannotDelete: func, }; -ToolbarDeleteButton.defaultProps = { - pluralizedItemName: 'Items', - warningMessage: null, - cannotDelete: (item) => !item.summary_fields.user_capabilities.delete, -}; - export default ToolbarDeleteButton; diff --git a/awx/ui/src/components/PaginatedTable/ToolbarSyncSourceButton.js b/awx/ui/src/components/PaginatedTable/ToolbarSyncSourceButton.js index e148182bc..16c81be59 100644 --- a/awx/ui/src/components/PaginatedTable/ToolbarSyncSourceButton.js +++ b/awx/ui/src/components/PaginatedTable/ToolbarSyncSourceButton.js @@ -5,7 +5,7 @@ import { useLingui } from '@lingui/react/macro'; import { useKebabifiedMenu } from 'contexts/Kebabified'; -function ToolbarSyncSourceButton({ onClick }) { +function ToolbarSyncSourceButton({ onClick = null }) { const { t } = useLingui(); const { isKebabified } = useKebabifiedMenu(); @@ -43,8 +43,5 @@ function ToolbarSyncSourceButton({ onClick }) { ToolbarSyncSourceButton.propTypes = { onClick: func, }; -ToolbarSyncSourceButton.defaultProps = { - onClick: null, -}; export default ToolbarSyncSourceButton; diff --git a/awx/ui/src/components/Popover/Popover.js b/awx/ui/src/components/Popover/Popover.js index 4ed98142b..3dceadd1d 100644 --- a/awx/ui/src/components/Popover/Popover.js +++ b/awx/ui/src/components/Popover/Popover.js @@ -13,7 +13,14 @@ const PopoverButton = styled.button` --pf-c-form__group-label-help--hover--Color: var(--pf-global--Color--100); `; -function Popover({ ariaLabel, content, header, id, maxWidth, ...rest }) { +function Popover({ + ariaLabel = null, + content = null, + header = null, + id = '', + maxWidth = '', + ...rest +}) { const { t } = useLingui(); if (!content) { return null; @@ -48,12 +55,5 @@ Popover.propTypes = { id: string, maxWidth: string, }; -Popover.defaultProps = { - ariaLabel: null, - content: null, - header: null, - id: '', - maxWidth: '', -}; export default Popover; diff --git a/awx/ui/src/components/PromptDetail/PromptDetail.js b/awx/ui/src/components/PromptDetail/PromptDetail.js index 8002e91d9..1039cc785 100644 --- a/awx/ui/src/components/PromptDetail/PromptDetail.js +++ b/awx/ui/src/components/PromptDetail/PromptDetail.js @@ -99,7 +99,7 @@ function omitOverrides(resource, overrides, defaultConfig) { function PromptDetail({ resource, - launchConfig = {}, + launchConfig = { defaults: {} }, overrides = {}, workflowNode = false, }) { @@ -386,10 +386,6 @@ function PromptDetail({ ); } -PromptDetail.defaultProps = { - launchConfig: { defaults: {} }, -}; - PromptDetail.propTypes = { resource: shape({}).isRequired, launchConfig: shape({}), diff --git a/awx/ui/src/components/ResourceAccessList/DeleteRoleConfirmationModal.js b/awx/ui/src/components/ResourceAccessList/DeleteRoleConfirmationModal.js index 8810acd83..badc02286 100644 --- a/awx/ui/src/components/ResourceAccessList/DeleteRoleConfirmationModal.js +++ b/awx/ui/src/components/ResourceAccessList/DeleteRoleConfirmationModal.js @@ -7,7 +7,12 @@ import { useLingui } from '@lingui/react/macro'; import { Role } from 'types'; import AlertModal from '../AlertModal'; -function DeleteRoleConfirmationModal({ role, username, onCancel, onConfirm }) { +function DeleteRoleConfirmationModal({ + role, + username = '', + onCancel, + onConfirm, +}) { const { t } = useLingui(); const sourceOfRole = () => typeof role.team_id !== 'undefined' ? t`Team` : t`User`; @@ -61,8 +66,4 @@ DeleteRoleConfirmationModal.propTypes = { onConfirm: func.isRequired, }; -DeleteRoleConfirmationModal.defaultProps = { - username: '', -}; - export default DeleteRoleConfirmationModal; diff --git a/awx/ui/src/components/Schedule/ScheduleAdd/ScheduleAdd.js b/awx/ui/src/components/Schedule/ScheduleAdd/ScheduleAdd.js index b9cfa1f4f..c8d661c64 100644 --- a/awx/ui/src/components/Schedule/ScheduleAdd/ScheduleAdd.js +++ b/awx/ui/src/components/Schedule/ScheduleAdd/ScheduleAdd.js @@ -168,6 +168,4 @@ ScheduleAdd.propTypes = { apiModel: shape({ createSchedule: func.isRequired }).isRequired, }; -ScheduleAdd.defaultProps = {}; - export default ScheduleAdd; diff --git a/awx/ui/src/components/Schedule/ScheduleEdit/ScheduleEdit.js b/awx/ui/src/components/Schedule/ScheduleEdit/ScheduleEdit.js index 2814ceb12..ac352cfd0 100644 --- a/awx/ui/src/components/Schedule/ScheduleEdit/ScheduleEdit.js +++ b/awx/ui/src/components/Schedule/ScheduleEdit/ScheduleEdit.js @@ -201,6 +201,4 @@ ScheduleEdit.propTypes = { schedule: shape({}).isRequired, }; -ScheduleEdit.defaultProps = {}; - export default ScheduleEdit; diff --git a/awx/ui/src/components/Schedule/ScheduleList/ScheduleList.js b/awx/ui/src/components/Schedule/ScheduleList/ScheduleList.js index dedb81d16..aa1cbc8ae 100644 --- a/awx/ui/src/components/Schedule/ScheduleList/ScheduleList.js +++ b/awx/ui/src/components/Schedule/ScheduleList/ScheduleList.js @@ -27,7 +27,7 @@ const QS_CONFIG = getQSConfig('schedule', { function ScheduleList({ loadSchedules, loadScheduleOptions, - hideAddButton, + hideAddButton = false, resource, launchConfig, surveyConfig, @@ -259,8 +259,5 @@ ScheduleList.propTypes = { loadSchedules: func.isRequired, loadScheduleOptions: func.isRequired, }; -ScheduleList.defaultProps = { - hideAddButton: false, -}; export default ScheduleList; diff --git a/awx/ui/src/components/Schedule/ScheduleOccurrences/ScheduleOccurrences.js b/awx/ui/src/components/Schedule/ScheduleOccurrences/ScheduleOccurrences.js index 41fa5b725..7a6fa9001 100644 --- a/awx/ui/src/components/Schedule/ScheduleOccurrences/ScheduleOccurrences.js +++ b/awx/ui/src/components/Schedule/ScheduleOccurrences/ScheduleOccurrences.js @@ -22,7 +22,10 @@ const OccurrencesLabel = styled.div` } `; -function ScheduleOccurrences({ preview = { local: [], utc: [] }, tz }) { +function ScheduleOccurrences({ + preview = { local: [], utc: [] }, + tz = Intl.DateTimeFormat().resolvedOptions().timeZone, +}) { const { t } = useLingui(); const [mode, setMode] = useState('local'); @@ -79,9 +82,4 @@ ScheduleOccurrences.propTypes = { tz: string, }; -ScheduleOccurrences.defaultProps = { - preview: { local: [], utc: [] }, - tz: Intl.DateTimeFormat().resolvedOptions().timeZone, -}; - export default ScheduleOccurrences; diff --git a/awx/ui/src/components/Schedule/shared/ScheduleForm.js b/awx/ui/src/components/Schedule/shared/ScheduleForm.js index a3e52f217..78ad95791 100644 --- a/awx/ui/src/components/Schedule/shared/ScheduleForm.js +++ b/awx/ui/src/components/Schedule/shared/ScheduleForm.js @@ -28,12 +28,14 @@ const NUM_DAYS_PER_FREQUENCY = { year: 365, }; +const defaultSchedule = {}; + function ScheduleForm({ hasDaysToKeepField, handleCancel, handleSubmit: submitSchedule, - schedule, - submitError, + schedule = defaultSchedule, + submitError = null, resource, launchConfig, surveyConfig, @@ -577,11 +579,6 @@ ScheduleForm.propTypes = { submitError: shape(), }; -ScheduleForm.defaultProps = { - schedule: {}, - submitError: null, -}; - export default ScheduleForm; function scheduleHasInstances(values) { diff --git a/awx/ui/src/components/Search/AdvancedSearch.js b/awx/ui/src/components/Search/AdvancedSearch.js index ff0c85cef..135ad2427 100644 --- a/awx/ui/src/components/Search/AdvancedSearch.js +++ b/awx/ui/src/components/Search/AdvancedSearch.js @@ -42,12 +42,12 @@ const AdvancedGroup = styled.div` function AdvancedSearch({ onSearch, - searchableKeys, - relatedSearchableKeys, - maxSelectHeight, - enableNegativeFiltering, - enableRelatedFuzzyFiltering, - handleIsAnsibleFactsSelected, + searchableKeys = [], + relatedSearchableKeys = [], + maxSelectHeight = '300px', + enableNegativeFiltering = true, + enableRelatedFuzzyFiltering = true, + handleIsAnsibleFactsSelected = () => {}, isFilterCleared, }) { const { t } = useLingui(); @@ -356,13 +356,4 @@ AdvancedSearch.propTypes = { handleIsAnsibleFactsSelected: func, }; -AdvancedSearch.defaultProps = { - searchableKeys: [], - relatedSearchableKeys: [], - maxSelectHeight: '300px', - enableNegativeFiltering: true, - enableRelatedFuzzyFiltering: true, - handleIsAnsibleFactsSelected: () => {}, -}; - export default AdvancedSearch; diff --git a/awx/ui/src/components/Search/LookupTypeInput.js b/awx/ui/src/components/Search/LookupTypeInput.js index 42a316342..b5eb60c18 100644 --- a/awx/ui/src/components/Search/LookupTypeInput.js +++ b/awx/ui/src/components/Search/LookupTypeInput.js @@ -3,17 +3,19 @@ import { string, oneOfType, arrayOf, func } from 'prop-types'; import { useLingui } from '@lingui/react/macro'; import { Select, SelectOption, SelectVariant } from '@patternfly/react-core'; -function Option({ show, ...props }) { +function Option({ show = true, ...props }) { if (!show) { return null; } return ; } -Option.defaultProps = { - show: true, -}; -function LookupTypeInput({ value, type, setValue, maxSelectHeight }) { +function LookupTypeInput({ + value = '', + type = 'string', + setValue, + maxSelectHeight = '300px', +}) { const [isOpen, setIsOpen] = useState(false); const { t } = useLingui(); return ( @@ -148,10 +150,5 @@ LookupTypeInput.propTypes = { setValue: func.isRequired, maxSelectHeight: string, }; -LookupTypeInput.defaultProps = { - type: 'string', - value: '', - maxSelectHeight: '300px', -}; export default LookupTypeInput; diff --git a/awx/ui/src/components/Search/Search.js b/awx/ui/src/components/Search/Search.js index 0269ff925..047cf46df 100644 --- a/awx/ui/src/components/Search/Search.js +++ b/awx/ui/src/components/Search/Search.js @@ -49,17 +49,17 @@ const NoOptionDropdown = styled.div` function Search({ columns, - onSearch, + onSearch = null, onReplaceSearch, - onRemove, + onRemove = null, qsConfig, - searchableKeys, + searchableKeys = [], relatedSearchableKeys, onShowAdvancedSearch, - isDisabled, - maxSelectHeight, - enableNegativeFiltering, - enableRelatedFuzzyFiltering, + isDisabled = false, + maxSelectHeight = '300px', + enableNegativeFiltering = true, + enableRelatedFuzzyFiltering = true, handleIsAnsibleFactsSelected, isFilterCleared, }) { @@ -400,14 +400,4 @@ Search.propTypes = { searchableKeys: SearchableKeys, }; -Search.defaultProps = { - onSearch: null, - onRemove: null, - isDisabled: false, - maxSelectHeight: '300px', - enableNegativeFiltering: true, - enableRelatedFuzzyFiltering: true, - searchableKeys: [], -}; - export default Search; diff --git a/awx/ui/src/components/SelectableCard/SelectableCard.js b/awx/ui/src/components/SelectableCard/SelectableCard.js index d383c59d1..0c35a6046 100644 --- a/awx/ui/src/components/SelectableCard/SelectableCard.js +++ b/awx/ui/src/components/SelectableCard/SelectableCard.js @@ -32,12 +32,12 @@ const Description = styled.p` `; function SelectableCard({ - label, - description, + label = '', + description = '', onClick, - isSelected, + isSelected = false, dataCy, - ariaLabel, + ariaLabel = '', }) { return ( null, + onRowDrag = () => null, +}) { const { t } = useLingui(); const [liveText, setLiveText] = useState(''); const [id, setId] = useState(''); @@ -134,10 +138,5 @@ DraggableSelectedList.propTypes = { onRowDrag: PropTypes.func, selected: PropTypes.arrayOf(ListItem), }; -DraggableSelectedList.defaultProps = { - onRemove: () => null, - onRowDrag: () => null, - selected: [], -}; export default DraggableSelectedList; diff --git a/awx/ui/src/components/SelectedList/SelectedList.js b/awx/ui/src/components/SelectedList/SelectedList.js index aaf7dca48..bd6287cb1 100644 --- a/awx/ui/src/components/SelectedList/SelectedList.js +++ b/awx/ui/src/components/SelectedList/SelectedList.js @@ -16,10 +16,14 @@ const SplitLabelItem = styled(SplitItem)` word-break: initial; `; -function SelectedList(props) { - const { label, selected, onRemove, displayKey, isReadOnly, renderItemChip } = - props; - +function SelectedList({ + label = 'Selected', + selected, + onRemove = () => null, + displayKey = 'name', + isReadOnly = false, + renderItemChip = null, +}) { const renderChip = renderItemChip || (({ item, removeItem }) => ( @@ -59,12 +63,4 @@ SelectedList.propTypes = { renderItemChip: PropTypes.func, }; -SelectedList.defaultProps = { - displayKey: 'name', - label: 'Selected', - onRemove: () => null, - isReadOnly: false, - renderItemChip: null, -}; - export default SelectedList; diff --git a/awx/ui/src/components/Sort/Sort.js b/awx/ui/src/components/Sort/Sort.js index 4d01ca056..0a16567f2 100644 --- a/awx/ui/src/components/Sort/Sort.js +++ b/awx/ui/src/components/Sort/Sort.js @@ -32,7 +32,7 @@ const NoOptionDropdown = styled.div` border-bottom-color: var(--pf-global--BorderColor--200); `; -function Sort({ columns, qsConfig, onSort }) { +function Sort({ columns, qsConfig, onSort = null }) { const { t } = useLingui(); const location = useLocation(); const [isSortDropdownOpen, setIsSortDropdownOpen] = useState(false); @@ -155,8 +155,4 @@ Sort.propTypes = { onSort: PropTypes.func, }; -Sort.defaultProps = { - onSort: null, -}; - export default Sort; diff --git a/awx/ui/src/components/Sparkline/Sparkline.js b/awx/ui/src/components/Sparkline/Sparkline.js index 64eba5ec2..1980f6209 100644 --- a/awx/ui/src/components/Sparkline/Sparkline.js +++ b/awx/ui/src/components/Sparkline/Sparkline.js @@ -21,7 +21,7 @@ const Wrapper = styled.div` `; /* eslint-enable react/jsx-pascal-case */ -const Sparkline = ({ jobs }) => { +const Sparkline = ({ jobs = [] }) => { const { t } = useLingui(); const generateTooltip = (job) => ( <> @@ -56,8 +56,5 @@ const Sparkline = ({ jobs }) => { Sparkline.propTypes = { jobs: arrayOf(Job), }; -Sparkline.defaultProps = { - jobs: [], -}; export default Sparkline; diff --git a/awx/ui/src/components/Workflow/WorkflowActionTooltipItem.js b/awx/ui/src/components/Workflow/WorkflowActionTooltipItem.js index 419a4465f..3dd647857 100644 --- a/awx/ui/src/components/Workflow/WorkflowActionTooltipItem.js +++ b/awx/ui/src/components/Workflow/WorkflowActionTooltipItem.js @@ -25,9 +25,9 @@ const TooltipItem = styled.div` function WorkflowActionTooltipItem({ children, id, - onClick, - onMouseEnter, - onMouseLeave, + onClick = () => {}, + onMouseEnter = () => {}, + onMouseLeave = () => {}, }) { return ( {}, - onMouseEnter: () => {}, - onMouseLeave: () => {}, -}; - export default WorkflowActionTooltipItem; diff --git a/awx/ui/src/components/Workflow/WorkflowStartNode.js b/awx/ui/src/components/Workflow/WorkflowStartNode.js index 245c1b688..f48f9a598 100644 --- a/awx/ui/src/components/Workflow/WorkflowStartNode.js +++ b/awx/ui/src/components/Workflow/WorkflowStartNode.js @@ -30,7 +30,7 @@ const StartDiv = styled.div` padding: 0px 10px; `; -function WorkflowStartNode({ onUpdateHelpText, showActionTooltip }) { +function WorkflowStartNode({ onUpdateHelpText = () => {}, showActionTooltip }) { const { t } = useLingui(); const ref = useRef(null); const startNodeRef = useRef(null); @@ -90,8 +90,4 @@ WorkflowStartNode.propTypes = { onUpdateHelpText: func, }; -WorkflowStartNode.defaultProps = { - onUpdateHelpText: () => {}, -}; - export default WorkflowStartNode; diff --git a/awx/ui/src/screens/Credential/shared/CredentialForm.js b/awx/ui/src/screens/Credential/shared/CredentialForm.js index 5497b3ab0..952f1b351 100644 --- a/awx/ui/src/screens/Credential/shared/CredentialForm.js +++ b/awx/ui/src/screens/Credential/shared/CredentialForm.js @@ -211,10 +211,10 @@ function CredentialFormFields({ initialTypeId, credentialTypes }) { function CredentialForm({ credential = {}, credentialTypes, - inputSources, + inputSources = {}, onSubmit, onCancel, - submitError, + submitError = null, isOrgLookupDisabled, ...rest }) { @@ -364,10 +364,4 @@ CredentialForm.propTypes = { submitError: shape({}), }; -CredentialForm.defaultProps = { - credential: {}, - inputSources: {}, - submitError: null, -}; - export default CredentialForm; diff --git a/awx/ui/src/screens/Credential/shared/CredentialFormFields/BecomeMethodField.js b/awx/ui/src/screens/Credential/shared/CredentialFormFields/BecomeMethodField.js index eab798e92..d66a53abe 100644 --- a/awx/ui/src/screens/Credential/shared/CredentialFormFields/BecomeMethodField.js +++ b/awx/ui/src/screens/Credential/shared/CredentialFormFields/BecomeMethodField.js @@ -10,7 +10,7 @@ import { } from '@patternfly/react-core'; import Popover from 'components/Popover'; -function BecomeMethodField({ fieldOptions, isRequired }) { +function BecomeMethodField({ fieldOptions, isRequired = false }) { const { t } = useLingui(); const [isOpen, setIsOpen] = useState(false); const [options, setOptions] = useState( @@ -80,8 +80,5 @@ BecomeMethodField.propTypes = { }).isRequired, isRequired: bool, }; -BecomeMethodField.defaultProps = { - isRequired: false, -}; export default BecomeMethodField; diff --git a/awx/ui/src/screens/Credential/shared/CredentialFormFields/CredentialField.js b/awx/ui/src/screens/Credential/shared/CredentialFormFields/CredentialField.js index 9ffeae675..a3e2cef3d 100644 --- a/awx/ui/src/screens/Credential/shared/CredentialFormFields/CredentialField.js +++ b/awx/ui/src/screens/Credential/shared/CredentialFormFields/CredentialField.js @@ -29,7 +29,7 @@ const FileUpload = styled(PFFileUpload)` function CredentialInput({ fieldOptions, isFieldGroupValid, - credentialKind, + credentialKind = '', isVaultIdDisabled, ...rest }) { @@ -167,10 +167,6 @@ CredentialInput.propTypes = { credentialKind: string, }; -CredentialInput.defaultProps = { - credentialKind: '', -}; - function CredentialField({ credentialType, fieldOptions }) { const { values: formikValues } = useFormikContext(); const location = useLocation(); @@ -256,6 +252,4 @@ CredentialField.propTypes = { }).isRequired, }; -CredentialField.defaultProps = {}; - export default CredentialField; diff --git a/awx/ui/src/screens/Credential/shared/CredentialPlugins/CredentialPluginField.js b/awx/ui/src/screens/Credential/shared/CredentialPlugins/CredentialPluginField.js index 5649c890b..c5643d141 100644 --- a/awx/ui/src/screens/Credential/shared/CredentialPlugins/CredentialPluginField.js +++ b/awx/ui/src/screens/Credential/shared/CredentialPlugins/CredentialPluginField.js @@ -95,8 +95,13 @@ function CredentialPluginInput(props) { ); } -function CredentialPluginField(props) { - const { fieldOptions, isRequired, validated } = props; +function CredentialPluginField({ + isDisabled = false, + isRequired = false, + ...restProps +}) { + const props = { isDisabled, isRequired, ...restProps }; + const { fieldOptions, validated } = props; const [, meta, helpers] = useField(`inputs.${fieldOptions.id}`); const [passwordPromptField] = useField(`passwordPrompts.${fieldOptions.id}`); @@ -170,9 +175,4 @@ CredentialPluginField.propTypes = { isRequired: PropTypes.bool, }; -CredentialPluginField.defaultProps = { - isDisabled: false, - isRequired: false, -}; - export default CredentialPluginField; diff --git a/awx/ui/src/screens/Credential/shared/CredentialPlugins/CredentialPluginPrompt/CredentialPluginPrompt.js b/awx/ui/src/screens/Credential/shared/CredentialPlugins/CredentialPluginPrompt/CredentialPluginPrompt.js index c2e9db0bf..cc44f5536 100644 --- a/awx/ui/src/screens/Credential/shared/CredentialPlugins/CredentialPluginPrompt/CredentialPluginPrompt.js +++ b/awx/ui/src/screens/Credential/shared/CredentialPlugins/CredentialPluginPrompt/CredentialPluginPrompt.js @@ -129,7 +129,7 @@ function CredentialPluginWizard({ handleSubmit, onClose }) { ); } -function CredentialPluginPrompt({ onClose, onSubmit, initialValues }) { +function CredentialPluginPrompt({ onClose, onSubmit, initialValues = {} }) { return ( {}, + onClearPlugin = () => {}, fieldId, }) { const { t } = useLingui(); @@ -63,9 +63,4 @@ CredentialPluginSelected.propTypes = { onClearPlugin: func, }; -CredentialPluginSelected.defaultProps = { - onEditPlugin: () => {}, - onClearPlugin: () => {}, -}; - export default CredentialPluginSelected; diff --git a/awx/ui/src/screens/Credential/shared/CredentialPlugins/CredentialPluginTestAlert.js b/awx/ui/src/screens/Credential/shared/CredentialPlugins/CredentialPluginTestAlert.js index 8a5699d3f..2979c7b02 100644 --- a/awx/ui/src/screens/Credential/shared/CredentialPlugins/CredentialPluginTestAlert.js +++ b/awx/ui/src/screens/Credential/shared/CredentialPlugins/CredentialPluginTestAlert.js @@ -10,8 +10,8 @@ import { function CredentialPluginTestAlert({ credentialName, - successResponse, - errorResponse, + successResponse = null, + errorResponse = null, }) { const { t } = useLingui(); const [testMessage, setTestMessage] = useState(''); @@ -79,9 +79,4 @@ CredentialPluginTestAlert.propTypes = { errorResponse: shape({}), }; -CredentialPluginTestAlert.defaultProps = { - successResponse: null, - errorResponse: null, -}; - export default CredentialPluginTestAlert; diff --git a/awx/ui/src/screens/Credential/shared/ExternalTestModal.js b/awx/ui/src/screens/Credential/shared/ExternalTestModal.js index 6578cf7f5..43ad6b1b2 100644 --- a/awx/ui/src/screens/Credential/shared/ExternalTestModal.js +++ b/awx/ui/src/screens/Credential/shared/ExternalTestModal.js @@ -14,7 +14,7 @@ import useRequest from 'hooks/useRequest'; import { CredentialPluginTestAlert } from './CredentialPlugins'; function ExternalTestModal({ - credential, + credential = null, credentialType, credentialFormValues, onClose, @@ -175,8 +175,4 @@ ExternalTestModal.propType = { onClose: func.isRequired, }; -ExternalTestModal.defaultProps = { - credential: null, -}; - export default ExternalTestModal; diff --git a/awx/ui/src/screens/Credential/shared/TypeInputsSubForm.js b/awx/ui/src/screens/Credential/shared/TypeInputsSubForm.js index 95b5bfb84..b295b21a6 100644 --- a/awx/ui/src/screens/Credential/shared/TypeInputsSubForm.js +++ b/awx/ui/src/screens/Credential/shared/TypeInputsSubForm.js @@ -71,6 +71,4 @@ TypeInputsSubForm.propTypes = { credentialType: CredentialType.isRequired, }; -TypeInputsSubForm.defaultProps = {}; - export default TypeInputsSubForm; diff --git a/awx/ui/src/screens/CredentialType/shared/CredentialTypeForm.js b/awx/ui/src/screens/CredentialType/shared/CredentialTypeForm.js index b73f97f36..cb1c11beb 100644 --- a/awx/ui/src/screens/CredentialType/shared/CredentialTypeForm.js +++ b/awx/ui/src/screens/CredentialType/shared/CredentialTypeForm.js @@ -55,7 +55,7 @@ function CredentialTypeForm({ credentialType = {}, onSubmit, onCancel, - submitError, + submitError = null, ...rest }) { const initialValues = { @@ -96,9 +96,4 @@ CredentialTypeForm.propTypes = { submitError: shape({}), }; -CredentialTypeForm.defaultProps = { - credentialType: {}, - submitError: null, -}; - export default CredentialTypeForm; diff --git a/awx/ui/src/screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js b/awx/ui/src/screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js index eb526b03a..499d70fa6 100644 --- a/awx/ui/src/screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js +++ b/awx/ui/src/screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js @@ -159,9 +159,9 @@ function ExecutionEnvironmentForm({ executionEnvironment = {}, onSubmit, onCancel, - submitError, + submitError = null, me, - isOrgLookupDisabled, + isOrgLookupDisabled = false, ...rest }) { const { @@ -234,10 +234,4 @@ ExecutionEnvironmentForm.propTypes = { isOrgLookupDisabled: bool, }; -ExecutionEnvironmentForm.defaultProps = { - executionEnvironment: {}, - submitError: null, - isOrgLookupDisabled: false, -}; - export default ExecutionEnvironmentForm; diff --git a/awx/ui/src/screens/Host/HostList/SmartInventoryButton.js b/awx/ui/src/screens/Host/HostList/SmartInventoryButton.js index 8ab1bdf86..3d320954f 100644 --- a/awx/ui/src/screens/Host/HostList/SmartInventoryButton.js +++ b/awx/ui/src/screens/Host/HostList/SmartInventoryButton.js @@ -8,9 +8,9 @@ import { useKebabifiedMenu } from 'contexts/Kebabified'; function SmartInventoryButton({ onClick, - isDisabled, - hasInvalidKeys, - hasAnsibleFactsKeys, + isDisabled = false, + hasInvalidKeys = false, + hasAnsibleFactsKeys = false, }) { const { t } = useLingui(); const { isKebabified } = useKebabifiedMenu(); @@ -74,10 +74,4 @@ SmartInventoryButton.propTypes = { hasAnsibleFactsKeys: bool, }; -SmartInventoryButton.defaultProps = { - hasInvalidKeys: false, - isDisabled: false, - hasAnsibleFactsKeys: false, -}; - export default SmartInventoryButton; diff --git a/awx/ui/src/screens/HostMetrics/HostMetricsDeleteButton.js b/awx/ui/src/screens/HostMetrics/HostMetricsDeleteButton.js index 6fd7787cd..89e84bdd3 100644 --- a/awx/ui/src/screens/HostMetrics/HostMetricsDeleteButton.js +++ b/awx/ui/src/screens/HostMetrics/HostMetricsDeleteButton.js @@ -24,10 +24,10 @@ const ItemToDelete = shape({ function HostMetricsDeleteButton({ itemsToDelete, - pluralizedItemName, + pluralizedItemName = 'Items', onDelete, deleteDetailsRequests, - warningMessage, + warningMessage = null, deleteMessage, }) { const { t } = useLingui(); @@ -198,9 +198,4 @@ HostMetricsDeleteButton.propTypes = { warningMessage: node, }; -HostMetricsDeleteButton.defaultProps = { - pluralizedItemName: 'Items', - warningMessage: null, -}; - export default HostMetricsDeleteButton; diff --git a/awx/ui/src/screens/InstanceGroup/shared/ContainerGroupForm.js b/awx/ui/src/screens/InstanceGroup/shared/ContainerGroupForm.js index b49177690..49d91f58b 100644 --- a/awx/ui/src/screens/InstanceGroup/shared/ContainerGroupForm.js +++ b/awx/ui/src/screens/InstanceGroup/shared/ContainerGroupForm.js @@ -108,11 +108,11 @@ function ContainerGroupFormFields({ instanceGroup }) { } function ContainerGroupForm({ - initialPodSpec, - instanceGroup, + initialPodSpec = {}, + instanceGroup = {}, onSubmit, onCancel, - submitError, + submitError = null, ...rest }) { const isCheckboxChecked = Boolean(instanceGroup?.pod_spec_override) || false; @@ -159,10 +159,4 @@ ContainerGroupForm.propTypes = { initialPodSpec: shape({}), }; -ContainerGroupForm.defaultProps = { - instanceGroup: {}, - submitError: null, - initialPodSpec: {}, -}; - export default ContainerGroupForm; diff --git a/awx/ui/src/screens/InstanceGroup/shared/InstanceGroupForm.js b/awx/ui/src/screens/InstanceGroup/shared/InstanceGroupForm.js index 0622ac825..7efab01e9 100644 --- a/awx/ui/src/screens/InstanceGroup/shared/InstanceGroupForm.js +++ b/awx/ui/src/screens/InstanceGroup/shared/InstanceGroupForm.js @@ -66,7 +66,7 @@ function InstanceGroupForm({ instanceGroup = {}, onSubmit, onCancel, - submitError, + submitError = null, ...rest }) { const initialValues = { @@ -104,9 +104,4 @@ InstanceGroupForm.propTypes = { submitError: shape({}), }; -InstanceGroupForm.defaultProps = { - instanceGroup: {}, - submitError: null, -}; - export default InstanceGroupForm; diff --git a/awx/ui/src/screens/Inventory/shared/ConstructedInventoryForm.js b/awx/ui/src/screens/Inventory/shared/ConstructedInventoryForm.js index b30f89f25..2f58e3de4 100644 --- a/awx/ui/src/screens/Inventory/shared/ConstructedInventoryForm.js +++ b/awx/ui/src/screens/Inventory/shared/ConstructedInventoryForm.js @@ -160,7 +160,7 @@ function ConstructedInventoryForm({ inputInventories, onCancel, onSubmit, - submitError, + submitError = null, options, }) { const initialValues = { @@ -200,8 +200,4 @@ ConstructedInventoryForm.propTypes = { submitError: shape({}), }; -ConstructedInventoryForm.defaultProps = { - submitError: null, -}; - export default ConstructedInventoryForm; diff --git a/awx/ui/src/screens/Inventory/shared/FederatedInventoryForm.js b/awx/ui/src/screens/Inventory/shared/FederatedInventoryForm.js index f875371a5..5ded87ec4 100644 --- a/awx/ui/src/screens/Inventory/shared/FederatedInventoryForm.js +++ b/awx/ui/src/screens/Inventory/shared/FederatedInventoryForm.js @@ -109,7 +109,7 @@ function FederatedInventoryForm({ inputInventories, onCancel, onSubmit, - submitError, + submitError = null, }) { const initialValues = { kind: 'federated', @@ -143,8 +143,4 @@ FederatedInventoryForm.propTypes = { submitError: shape({}), }; -FederatedInventoryForm.defaultProps = { - submitError: null, -}; - export default FederatedInventoryForm; diff --git a/awx/ui/src/screens/Inventory/shared/InventoryForm.js b/awx/ui/src/screens/Inventory/shared/InventoryForm.js index 29e7aaab0..b91fcc9c8 100644 --- a/awx/ui/src/screens/Inventory/shared/InventoryForm.js +++ b/awx/ui/src/screens/Inventory/shared/InventoryForm.js @@ -120,8 +120,8 @@ function InventoryForm({ inventory = {}, onSubmit, onCancel, - submitError, - instanceGroups, + submitError = null, + instanceGroups = [], ...rest }) { const initialValues = { @@ -167,10 +167,4 @@ InventoryForm.propType = { submitError: shape(), }; -InventoryForm.defaultProps = { - inventory: {}, - instanceGroups: [], - submitError: null, -}; - export default InventoryForm; diff --git a/awx/ui/src/screens/Inventory/shared/InventoryGroupsDeleteModal.js b/awx/ui/src/screens/Inventory/shared/InventoryGroupsDeleteModal.js index 95a62baf1..14c73c0f5 100644 --- a/awx/ui/src/screens/Inventory/shared/InventoryGroupsDeleteModal.js +++ b/awx/ui/src/screens/Inventory/shared/InventoryGroupsDeleteModal.js @@ -16,7 +16,11 @@ const ListItem = styled.li` color: var(--pf-global--danger-color--100); `; -const InventoryGroupsDeleteModal = ({ onAfterDelete, isDisabled, groups }) => { +const InventoryGroupsDeleteModal = ({ + onAfterDelete, + isDisabled, + groups = [], +}) => { const { t } = useLingui(); const [radioOption, setRadioOption] = useState(null); const [isModalOpen, setIsModalOpen] = useState(false); @@ -166,8 +170,4 @@ InventoryGroupsDeleteModal.propTypes = { isDisabled: bool.isRequired, }; -InventoryGroupsDeleteModal.defaultProps = { - groups: [], -}; - export default InventoryGroupsDeleteModal; diff --git a/awx/ui/src/screens/Inventory/shared/InventorySourceForm.js b/awx/ui/src/screens/Inventory/shared/InventorySourceForm.js index 1a3564609..74e6b55e4 100644 --- a/awx/ui/src/screens/Inventory/shared/InventorySourceForm.js +++ b/awx/ui/src/screens/Inventory/shared/InventorySourceForm.js @@ -348,8 +348,4 @@ InventorySourceForm.propTypes = { submitError: shape({}), }; -InventorySourceForm.defaultProps = { - submitError: null, -}; - export default InventorySourceForm; diff --git a/awx/ui/src/screens/Inventory/shared/InventorySourceSyncButton.js b/awx/ui/src/screens/Inventory/shared/InventorySourceSyncButton.js index af089e1e2..0f6d9daf4 100644 --- a/awx/ui/src/screens/Inventory/shared/InventorySourceSyncButton.js +++ b/awx/ui/src/screens/Inventory/shared/InventorySourceSyncButton.js @@ -9,7 +9,7 @@ import AlertModal from 'components/AlertModal/AlertModal'; import ErrorDetail from 'components/ErrorDetail/ErrorDetail'; import { InventorySourcesAPI } from 'api'; -function InventorySourceSyncButton({ source, icon }) { +function InventorySourceSyncButton({ source = {}, icon = true }) { const { t } = useLingui(); const { isLoading: startSyncLoading, @@ -58,11 +58,6 @@ function InventorySourceSyncButton({ source, icon }) { ); } -InventorySourceSyncButton.defaultProps = { - source: {}, - icon: true, -}; - InventorySourceSyncButton.propTypes = { source: PropTypes.shape({}), icon: PropTypes.bool, diff --git a/awx/ui/src/screens/Inventory/shared/SmartInventoryForm.js b/awx/ui/src/screens/Inventory/shared/SmartInventoryForm.js index 794aed440..c30fc4b33 100644 --- a/awx/ui/src/screens/Inventory/shared/SmartInventoryForm.js +++ b/awx/ui/src/screens/Inventory/shared/SmartInventoryForm.js @@ -100,11 +100,11 @@ const SmartInventoryFormFields = ({ inventory }) => { }; function SmartInventoryForm({ - inventory, - instanceGroups, + inventory = {}, + instanceGroups = [], onSubmit, onCancel, - submitError, + submitError = null, }) { const { search } = useLocation(); const queryParams = new URLSearchParams(search); @@ -189,10 +189,4 @@ SmartInventoryForm.propTypes = { submitError: shape({}), }; -SmartInventoryForm.defaultProps = { - instanceGroups: [], - inventory: {}, - submitError: null, -}; - export default SmartInventoryForm; diff --git a/awx/ui/src/screens/Job/JobOutput/HostEventModal.js b/awx/ui/src/screens/Job/JobOutput/HostEventModal.js index eb61a7c28..dc92b3fea 100644 --- a/awx/ui/src/screens/Job/JobOutput/HostEventModal.js +++ b/awx/ui/src/screens/Job/JobOutput/HostEventModal.js @@ -65,7 +65,9 @@ const getStdOutValue = (hostEvent) => { return stdOut; }; -function HostEventModal({ onClose, hostEvent = {}, isOpen = false }) { +const defaultHostEvent = {}; + +function HostEventModal({ onClose, hostEvent = defaultHostEvent, isOpen = false }) { const { t } = useLingui(); const [hostStatus, setHostStatus] = useState(null); const [activeTabKey, setActiveTabKey] = useState(0); @@ -221,8 +223,3 @@ HostEventModal.propTypes = { hostEvent: PropTypes.shape({}), isOpen: PropTypes.bool, }; - -HostEventModal.defaultProps = { - hostEvent: null, - isOpen: false, -}; diff --git a/awx/ui/src/screens/Job/JobOutput/shared/OutputToolbar.js b/awx/ui/src/screens/Job/JobOutput/shared/OutputToolbar.js index 5feb6138c..684eafcdb 100644 --- a/awx/ui/src/screens/Job/JobOutput/shared/OutputToolbar.js +++ b/awx/ui/src/screens/Job/JobOutput/shared/OutputToolbar.js @@ -70,7 +70,12 @@ const OUTPUT_NO_COUNT_JOB_TYPES = [ 'inventory_update', ]; -const OutputToolbar = ({ job, onDelete, isDeleteDisabled, jobStatus }) => { +const OutputToolbar = ({ + job, + onDelete, + isDeleteDisabled = false, + jobStatus, +}) => { const { t } = useLingui(); const [activeJobElapsedTime, setActiveJobElapsedTime] = useState('00:00:00'); const hideCounts = OUTPUT_NO_COUNT_JOB_TYPES.includes(job.type); @@ -254,8 +259,4 @@ OutputToolbar.propTypes = { onDelete: func.isRequired, }; -OutputToolbar.defaultProps = { - isDeleteDisabled: false, -}; - export default OutputToolbar; diff --git a/awx/ui/src/screens/Job/JobTypeRedirect.js b/awx/ui/src/screens/Job/JobTypeRedirect.js index 84dbe02a0..7ee910de3 100644 --- a/awx/ui/src/screens/Job/JobTypeRedirect.js +++ b/awx/ui/src/screens/Job/JobTypeRedirect.js @@ -13,7 +13,7 @@ import { JOB_TYPE_URL_SEGMENTS } from '../../constants'; const NOT_FOUND = 'not found'; -function JobTypeRedirect({ id, view }) { +function JobTypeRedirect({ id, view = 'output' }) { const { t } = useLingui(); const { isLoading, @@ -64,7 +64,4 @@ function JobTypeRedirect({ id, view }) { ); } -JobTypeRedirect.defaultProps = { - view: 'output', -}; export default JobTypeRedirect; diff --git a/awx/ui/src/screens/Job/WorkflowOutput/WorkflowOutputToolbar.js b/awx/ui/src/screens/Job/WorkflowOutput/WorkflowOutputToolbar.js index e12d856cf..62f941e6c 100644 --- a/awx/ui/src/screens/Job/WorkflowOutput/WorkflowOutputToolbar.js +++ b/awx/ui/src/screens/Job/WorkflowOutput/WorkflowOutputToolbar.js @@ -93,7 +93,11 @@ const ActionButton = styled(Button)` color: #fff; } `; -function WorkflowOutputToolbar({ job, onDelete, isDeleteDisabled }) { +function WorkflowOutputToolbar({ + job, + onDelete = () => {}, + isDeleteDisabled = false, +}) { const { t } = useLingui(); const dispatch = useContext(WorkflowDispatchContext); const navigate = useNavigate(); @@ -265,9 +269,4 @@ WorkflowOutputToolbar.propTypes = { isDeleteDisabled: bool, }; -WorkflowOutputToolbar.defaultProps = { - onDelete: () => {}, - isDeleteDisabled: false, -}; - export default WorkflowOutputToolbar; diff --git a/awx/ui/src/screens/NotificationTemplate/shared/NotificationTemplateForm.js b/awx/ui/src/screens/NotificationTemplate/shared/NotificationTemplateForm.js index 39e3f108e..c2541ce16 100644 --- a/awx/ui/src/screens/NotificationTemplate/shared/NotificationTemplateForm.js +++ b/awx/ui/src/screens/NotificationTemplate/shared/NotificationTemplateForm.js @@ -102,11 +102,15 @@ function NotificationTemplateFormFields({ defaultMessages, template }) { } function NotificationTemplateForm({ - template, + template = { + name: '', + description: '', + notification_type: '', + }, defaultMessages, onSubmit, onCancel, - submitError, + submitError = null, }) { const handleSubmit = (values) => { onSubmit( @@ -203,15 +207,6 @@ NotificationTemplateForm.propTypes = { submitError: shape(), }; -NotificationTemplateForm.defaultProps = { - template: { - name: '', - description: '', - notification_type: '', - }, - submitError: null, -}; - export default NotificationTemplateForm; function normalizeFields(values, defaultMessages) { diff --git a/awx/ui/src/screens/NotificationTemplate/shared/TypeInputsSubForm.js b/awx/ui/src/screens/NotificationTemplate/shared/TypeInputsSubForm.js index 92bf0c174..0c7e618f2 100644 --- a/awx/ui/src/screens/NotificationTemplate/shared/TypeInputsSubForm.js +++ b/awx/ui/src/screens/NotificationTemplate/shared/TypeInputsSubForm.js @@ -41,10 +41,6 @@ const editFieldPropTypes = { isEdit: PropTypes.bool, }; -const editFieldDefaultProps = { - isEdit: false, -}; - const TypeFields = { email: EmailFields, grafana: GrafanaFields, @@ -56,7 +52,7 @@ const TypeFields = { twilio: TwilioFields, webhook: WebhookFields, }; -function TypeInputsSubForm({ type, isEdit }) { +function TypeInputsSubForm({ type, isEdit = false }) { const { t } = useLingui(); const Fields = TypeFields[type]; return ( @@ -75,17 +71,13 @@ TypeInputsSubForm.propTypes = { isEdit: PropTypes.bool, }; -TypeInputsSubForm.defaultProps = { - isEdit: false, -}; - export default TypeInputsSubForm; function SecretPasswordField({ id, label, name, - isEdit, + isEdit = false, isRequiredOnCreate = false, }) { const validate = isRequiredOnCreate && !isEdit ? required(null) : undefined; @@ -126,12 +118,7 @@ SecretPasswordField.propTypes = { isRequiredOnCreate: PropTypes.bool, }; -SecretPasswordField.defaultProps = { - isEdit: false, - isRequiredOnCreate: false, -}; - -function EmailFields({ isEdit }) { +function EmailFields({ isEdit = false }) { const { t } = useLingui(); const helpText = useMemo(() => ({ emailRecipients: t`Use one email address per line to create a recipient list for this type of notification.`, @@ -235,7 +222,7 @@ function EmailFields({ isEdit }) { ); } -function GrafanaFields({ isEdit }) { +function GrafanaFields({ isEdit = false }) { const { t } = useLingui(); const helpText = { grafanaUrl: t`The base URL of the Grafana server - the @@ -292,12 +279,8 @@ function GrafanaFields({ isEdit }) { EmailFields.propTypes = editFieldPropTypes; -EmailFields.defaultProps = editFieldDefaultProps; - GrafanaFields.propTypes = editFieldPropTypes; - -GrafanaFields.defaultProps = editFieldDefaultProps; -function IRCFields({ isEdit }) { +function IRCFields({ isEdit = false }) { const { t } = useLingui(); const helpText = { ircTargets: t`Use one IRC channel or username per line. The pound @@ -357,8 +340,6 @@ function IRCFields({ isEdit }) { IRCFields.propTypes = editFieldPropTypes; -IRCFields.defaultProps = editFieldDefaultProps; - function MattermostFields() { const { t } = useLingui(); return ( @@ -399,7 +380,7 @@ function MattermostFields() { ); } -function PagerdutyFields({ isEdit }) { +function PagerdutyFields({ isEdit = false }) { const { t } = useLingui(); return ( <> @@ -440,8 +421,6 @@ function PagerdutyFields({ isEdit }) { PagerdutyFields.propTypes = editFieldPropTypes; -PagerdutyFields.defaultProps = editFieldDefaultProps; - function RocketChatFields() { const { t } = useLingui(); return ( @@ -476,7 +455,7 @@ function RocketChatFields() { ); } -function SlackFields({ isEdit }) { +function SlackFields({ isEdit = false }) { const { t } = useLingui(); const helpText = useMemo(() => ({ slackChannels: ( @@ -523,9 +502,7 @@ function SlackFields({ isEdit }) { SlackFields.propTypes = editFieldPropTypes; -SlackFields.defaultProps = editFieldDefaultProps; - -function TwilioFields({ isEdit }) { +function TwilioFields({ isEdit = false }) { const { t } = useLingui(); const helpText = { twilioSourcePhoneNumber: t`The number associated with the "Messaging @@ -574,9 +551,7 @@ function TwilioFields({ isEdit }) { TwilioFields.propTypes = editFieldPropTypes; -TwilioFields.defaultProps = editFieldDefaultProps; - -function WebhookFields({ isEdit }) { +function WebhookFields({ isEdit = false }) { const { t } = useLingui(); const helpText = { webhookHeaders: t`Specify HTTP Headers in JSON format. Refer to @@ -652,5 +627,3 @@ function WebhookFields({ isEdit }) { } WebhookFields.propTypes = editFieldPropTypes; - -WebhookFields.defaultProps = editFieldDefaultProps; diff --git a/awx/ui/src/screens/Organization/shared/OrganizationForm.js b/awx/ui/src/screens/Organization/shared/OrganizationForm.js index 541b425af..c7fb5cde4 100644 --- a/awx/ui/src/screens/Organization/shared/OrganizationForm.js +++ b/awx/ui/src/screens/Organization/shared/OrganizationForm.js @@ -125,11 +125,17 @@ function OrganizationFormFields({ } function OrganizationForm({ - organization, + organization = { + id: '', + name: '', + description: '', + max_hosts: '0', + default_environment: '', + }, onCancel, onSubmit, - submitError, - defaultGalaxyCredential, + submitError = null, + defaultGalaxyCredential = null, ...rest }) { const [contentError, setContentError] = useState(null); @@ -225,17 +231,5 @@ OrganizationForm.propTypes = { submitError: PropTypes.shape(), }; -OrganizationForm.defaultProps = { - defaultGalaxyCredential: null, - organization: { - id: '', - name: '', - description: '', - max_hosts: '0', - default_environment: '', - }, - submitError: null, -}; - export { OrganizationForm as _OrganizationForm }; export default OrganizationForm; diff --git a/awx/ui/src/screens/Project/shared/ProjectForm.js b/awx/ui/src/screens/Project/shared/ProjectForm.js index 862c77c47..a748301ba 100644 --- a/awx/ui/src/screens/Project/shared/ProjectForm.js +++ b/awx/ui/src/screens/Project/shared/ProjectForm.js @@ -340,7 +340,7 @@ function ProjectFormFields({ ); } -function ProjectForm({ project, submitError, ...props }) { +function ProjectForm({ project = {}, submitError = null, ...props }) { const { handleCancel, handleSubmit } = props; const { summary_fields = {} } = project; const { project_base_dir, project_local_paths } = useConfig(); @@ -483,9 +483,4 @@ ProjectForm.propTypes = { submitError: PropTypes.shape({}), }; -ProjectForm.defaultProps = { - project: {}, - submitError: null, -}; - export default ProjectForm; diff --git a/awx/ui/src/screens/Setting/shared/SharedFields.js b/awx/ui/src/screens/Setting/shared/SharedFields.js index e8edfb077..7399d769c 100644 --- a/awx/ui/src/screens/Setting/shared/SharedFields.js +++ b/awx/ui/src/screens/Setting/shared/SharedFields.js @@ -372,7 +372,12 @@ InputAlertField.propTypes = { config: shape({}).isRequired, }; -const InputField = ({ name, config, type = 'text', isRequired = false }) => { +const InputField = ({ + name, + config = null, + type = 'text', + isRequired = false, +}) => { const { t } = useLingui(); const min_value = config?.min_value ?? Number.MIN_SAFE_INTEGER; const max_value = config?.max_value ?? Number.MAX_SAFE_INTEGER; @@ -414,9 +419,6 @@ InputField.propTypes = { name: string.isRequired, config: shape({}), }; -InputField.defaultProps = { - config: null, -}; const TextAreaField = ({ name, config, isRequired = false }) => { const { t } = useLingui(); diff --git a/awx/ui/src/screens/Team/shared/TeamForm.js b/awx/ui/src/screens/Team/shared/TeamForm.js index 30b81c71f..16111ff7e 100644 --- a/awx/ui/src/screens/Team/shared/TeamForm.js +++ b/awx/ui/src/screens/Team/shared/TeamForm.js @@ -53,9 +53,13 @@ function TeamFormFields({ team }) { ); } -function TeamForm(props) { - const { team, handleCancel, handleSubmit, submitError, ...rest } = props; - +function TeamForm({ + team = {}, + handleCancel, + handleSubmit, + submitError = null, + ...rest +}) { return ( {}, readOnly, updateHelpText, updateNodeHelp, @@ -395,8 +395,4 @@ VisualizerNode.propTypes = { updateNodeHelp: func.isRequired, }; -VisualizerNode.defaultProps = { - onMouseOver: () => {}, -}; - export default VisualizerNode; diff --git a/awx/ui/src/screens/Template/shared/JobTemplateForm.js b/awx/ui/src/screens/Template/shared/JobTemplateForm.js index 51f9a4e58..384d8b49b 100644 --- a/awx/ui/src/screens/Template/shared/JobTemplateForm.js +++ b/awx/ui/src/screens/Template/shared/JobTemplateForm.js @@ -50,15 +50,34 @@ import getHelpText from './JobTemplate.helptext'; const { origin } = document.location; +// Stable default so it doesn't change identity each render (it feeds a +// useCallback dependency below); previously this lived in defaultProps. +const defaultTemplate = { + name: '', + description: '', + job_type: 'run', + inventory: undefined, + project: undefined, + playbook: '', + scm_branch: '', + summary_fields: { + inventory: null, + labels: { results: [] }, + project: null, + credentials: [], + }, + isNew: true, +}; + function JobTemplateForm({ - template, + template = defaultTemplate, handleCancel, handleSubmit, setFieldValue, setFieldTouched, - submitError, + submitError = null, validateField, - isOverrideDisabledLookup, // TODO: this is a confusing variable name + isOverrideDisabledLookup = false, // TODO: this is a confusing variable name }) { const { t } = useLingui(); const helpText = getHelpText(t); @@ -670,27 +689,6 @@ JobTemplateForm.propTypes = { isOverrideDisabledLookup: PropTypes.bool, }; -JobTemplateForm.defaultProps = { - template: { - name: '', - description: '', - job_type: 'run', - inventory: undefined, - project: undefined, - playbook: '', - scm_branch: '', - summary_fields: { - inventory: null, - labels: { results: [] }, - project: null, - credentials: [], - }, - isNew: true, - }, - submitError: null, - isOverrideDisabledLookup: false, -}; - const FormikApp = withFormik({ mapPropsToValues({ resourceValues = null, template = {} }) { const { diff --git a/awx/ui/src/screens/Template/shared/PlaybookSelect.js b/awx/ui/src/screens/Template/shared/PlaybookSelect.js index 2aa087619..2bb55794d 100644 --- a/awx/ui/src/screens/Template/shared/PlaybookSelect.js +++ b/awx/ui/src/screens/Template/shared/PlaybookSelect.js @@ -6,13 +6,15 @@ import { SelectVariant, Select, SelectOption } from '@patternfly/react-core'; import { ProjectsAPI } from 'api'; import useRequest from 'hooks/useRequest'; +const noop = () => {}; + function PlaybookSelect({ - projectId, + projectId = null, isValid, selected, onBlur, onError, - onChange, + onChange = noop, }) { const { t } = useLingui(); const [isDisabled, setIsDisabled] = useState(false); @@ -83,10 +85,5 @@ PlaybookSelect.propTypes = { projectId: oneOfType([number, string]), onChange: func, }; -PlaybookSelect.defaultProps = { - projectId: null, - onChange: () => {}, -}; - export { PlaybookSelect as _PlaybookSelect }; export default PlaybookSelect; diff --git a/awx/ui/src/screens/Template/shared/WorkflowJobTemplateForm.js b/awx/ui/src/screens/Template/shared/WorkflowJobTemplateForm.js index de956e43f..4f7221101 100644 --- a/awx/ui/src/screens/Template/shared/WorkflowJobTemplateForm.js +++ b/awx/ui/src/screens/Template/shared/WorkflowJobTemplateForm.js @@ -34,12 +34,17 @@ import getHelpText from './WorkflowJobTemplate.helptext'; const urlOrigin = window.location.origin; function WorkflowJobTemplateForm({ - template, + template = { + name: '', + description: '', + inventory: undefined, + project: undefined, + }, handleSubmit, handleCancel, - submitError, - isOrgAdmin, - isInventoryDisabled, + submitError = null, + isOrgAdmin = false, + isInventoryDisabled = false, }) { const { t } = useLingui(); const helpText = getHelpText(t); @@ -292,18 +297,6 @@ WorkflowJobTemplateForm.propTypes = { isInventoryDisabled: PropTypes.bool, }; -WorkflowJobTemplateForm.defaultProps = { - submitError: null, - template: { - name: '', - description: '', - inventory: undefined, - project: undefined, - }, - isOrgAdmin: false, - isInventoryDisabled: false, -}; - const FormikApp = withFormik({ mapPropsToValues({ template = {} }) { return { diff --git a/awx/ui/src/screens/User/shared/UserForm.js b/awx/ui/src/screens/User/shared/UserForm.js index 964c4e293..7b8462977 100644 --- a/awx/ui/src/screens/User/shared/UserForm.js +++ b/awx/ui/src/screens/User/shared/UserForm.js @@ -167,7 +167,7 @@ function UserFormFields({ user }) { ); } -function UserForm({ user, handleCancel, handleSubmit, submitError }) { +function UserForm({ user = {}, handleCancel, handleSubmit, submitError }) { const { t } = useLingui(); const handleValidateAndSubmit = (values, { setErrors }) => { if (values.password !== values.confirm_password) { @@ -234,8 +234,4 @@ UserForm.propTypes = { user: PropTypes.shape({}), }; -UserForm.defaultProps = { - user: {}, -}; - export default UserForm; diff --git a/awx/ui/src/screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js b/awx/ui/src/screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js index 1eb6fd41d..8cbd82964 100644 --- a/awx/ui/src/screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js +++ b/awx/ui/src/screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js @@ -20,7 +20,6 @@ import { VariablesDetail } from 'components/CodeEditor'; import { formatDateString, secondsToHHMMSS } from 'util/dates'; import { WorkflowApprovalsAPI, WorkflowJobsAPI } from 'api'; import useRequest, { useDismissableError } from 'hooks/useRequest'; -import { WorkflowApproval } from 'types'; import StatusLabel from 'components/StatusLabel'; import JobCancelButton from 'components/JobCancelButton'; import useToast, { AlertVariant } from 'hooks/useToast'; @@ -338,8 +337,4 @@ function WorkflowApprovalDetail({ workflowApproval, fetchWorkflowApproval }) { ); } -WorkflowApprovalDetail.defaultProps = { - workflowApproval: WorkflowApproval.isRequired, -}; - export default WorkflowApprovalDetail; diff --git a/awx/ui/src/screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js b/awx/ui/src/screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js index fb638f6c7..d0daad94c 100644 --- a/awx/ui/src/screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js +++ b/awx/ui/src/screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js @@ -10,7 +10,7 @@ function cannotApprove(item) { return !item.can_approve_or_deny; } -function WorkflowApprovalListApproveButton({ onApprove, selectedItems }) { +function WorkflowApprovalListApproveButton({ onApprove, selectedItems = [] }) { const { t } = useLingui(); const { isKebabified } = useContext(KebabifiedContext); @@ -70,8 +70,4 @@ WorkflowApprovalListApproveButton.propTypes = { selectedItems: PropTypes.arrayOf(WorkflowApproval), }; -WorkflowApprovalListApproveButton.defaultProps = { - selectedItems: [], -}; - export default WorkflowApprovalListApproveButton; diff --git a/awx/ui/src/screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js b/awx/ui/src/screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js index 00cef2cfa..5f7684a3d 100644 --- a/awx/ui/src/screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js +++ b/awx/ui/src/screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js @@ -9,7 +9,7 @@ function cannotDeny(item) { return !item.can_approve_or_deny; } -function WorkflowApprovalListDenyButton({ onDeny, selectedItems }) { +function WorkflowApprovalListDenyButton({ onDeny, selectedItems = [] }) { const { t } = useLingui(); const { isKebabified } = useContext(KebabifiedContext); @@ -69,8 +69,4 @@ WorkflowApprovalListDenyButton.propTypes = { selectedItems: PropTypes.arrayOf(WorkflowApproval), }; -WorkflowApprovalListDenyButton.defaultProps = { - selectedItems: [], -}; - export default WorkflowApprovalListDenyButton;