diff --git a/awx/ui_next/src/screens/Template/JobTemplateDetail/JobTemplateDetail.jsx b/awx/ui_next/src/screens/Template/JobTemplateDetail/JobTemplateDetail.jsx index 94955e78f5..ef5f8e32f8 100644 --- a/awx/ui_next/src/screens/Template/JobTemplateDetail/JobTemplateDetail.jsx +++ b/awx/ui_next/src/screens/Template/JobTemplateDetail/JobTemplateDetail.jsx @@ -1,5 +1,5 @@ -import React, { Component, Fragment } from 'react'; -import { Link, withRouter } from 'react-router-dom'; +import React, { Fragment, useState, useEffect } from 'react'; +import { Link, useParams } from 'react-router-dom'; import { withI18n } from '@lingui/react'; import { Button, @@ -13,10 +13,10 @@ import { t } from '@lingui/macro'; import { CardBody, CardActionsRow } from '@components/Card'; import ContentError from '@components/ContentError'; -import LaunchButton from '@components/LaunchButton'; import ContentLoading from '@components/ContentLoading'; import { ChipGroup, Chip, CredentialChip } from '@components/Chip'; import { DetailList, Detail, UserDateDetail } from '@components/DetailList'; +import LaunchButton from '@components/LaunchButton'; import { JobTemplatesAPI } from '@api'; const MissingDetail = styled(Detail)` @@ -25,319 +25,290 @@ const MissingDetail = styled(Detail)` } `; -class JobTemplateDetail extends Component { - constructor(props) { - super(props); - this.state = { - contentError: null, - hasContentLoading: true, - instanceGroups: [], - }; - this.readInstanceGroups = this.readInstanceGroups.bind(this); - } +function JobTemplateDetail({ i18n, template }) { + const { + ask_inventory_on_launch, + allow_simultaneous, + become_enabled, + created, + description, + diff_mode, + forks, + host_config_key, + job_slice_count, + job_tags, + job_type, + name, + limit, + modified, + playbook, + skip_tags, + timeout, + summary_fields, + use_fact_cache, + url, + verbosity, + } = template; + const [contentError, setContentError] = useState(null); + const [hasContentLoading, setHasContentLoading] = useState(false); + const [instanceGroups, setInstanceGroups] = useState([]); + const { id: templateId } = useParams(); - componentDidMount() { - this.readInstanceGroups(); - } + useEffect(() => { + (async () => { + setContentError(null); + setHasContentLoading(true); + try { + const { + data: { results = [] }, + } = await JobTemplatesAPI.readInstanceGroups(templateId); + setInstanceGroups(results); + } catch (error) { + setContentError(error); + } finally { + setHasContentLoading(false); + } + })(); + }, [templateId]); - async readInstanceGroups() { - const { match } = this.props; - try { - const { data } = await JobTemplatesAPI.readInstanceGroups( - match.params.id - ); - this.setState({ instanceGroups: [...data.results] }); - } catch (err) { - this.setState({ contentError: err }); - } finally { - this.setState({ hasContentLoading: false }); - } - } + const canLaunch = + summary_fields.user_capabilities && summary_fields.user_capabilities.start; + const verbosityOptions = [ + { verbosity: 0, details: i18n._(t`0 (Normal)`) }, + { verbosity: 1, details: i18n._(t`1 (Verbose)`) }, + { verbosity: 2, details: i18n._(t`2 (More Verbose)`) }, + { verbosity: 3, details: i18n._(t`3 (Debug)`) }, + { verbosity: 4, details: i18n._(t`4 (Connection Debug)`) }, + { verbosity: 5, details: i18n._(t`5 (WinRM Debug)`) }, + ]; + const verbosityDetails = verbosityOptions.filter( + option => option.verbosity === verbosity + ); + const generateCallBackUrl = `${window.location.origin + url}callback/`; + const renderOptionsField = + become_enabled || host_config_key || allow_simultaneous || use_fact_cache; - render() { - const { - template: { - ask_inventory_on_launch, - allow_simultaneous, - become_enabled, - created, - description, - diff_mode, - forks, - host_config_key, - job_slice_count, - job_tags, - job_type, - name, - limit, - modified, - playbook, - skip_tags, - timeout, - summary_fields, - use_fact_cache, - url, - verbosity, - }, - hasTemplateLoading, - template, - i18n, - match, - } = this.props; - const canLaunch = summary_fields.user_capabilities.start; - const { instanceGroups, hasContentLoading, contentError } = this.state; - const verbosityOptions = [ - { verbosity: 0, details: i18n._(t`0 (Normal)`) }, - { verbosity: 1, details: i18n._(t`1 (Verbose)`) }, - { verbosity: 2, details: i18n._(t`2 (More Verbose)`) }, - { verbosity: 3, details: i18n._(t`3 (Debug)`) }, - { verbosity: 4, details: i18n._(t`4 (Connection Debug)`) }, - { verbosity: 5, details: i18n._(t`5 (WinRM Debug)`) }, - ]; - const verbosityDetails = verbosityOptions.filter( - option => option.verbosity === verbosity - ); - const generateCallBackUrl = `${window.location.origin + url}callback/`; - const isInitialized = !hasTemplateLoading && !hasContentLoading; + const renderOptions = ( + + {become_enabled && ( + + {i18n._(t`Enable Privilege Escalation`)} + + )} + {host_config_key && ( + + {i18n._(t`Allow Provisioning Callbacks`)} + + )} + {allow_simultaneous && ( + + {i18n._(t`Enable Concurrent Jobs`)} + + )} + {use_fact_cache && ( + + {i18n._(t`Use Fact Cache`)} + + )} + + ); - const renderOptionsField = - become_enabled || host_config_key || allow_simultaneous || use_fact_cache; + const renderMissingDataDetail = value => ( + + ); - const renderOptions = ( - - {become_enabled && ( - - {i18n._(t`Enable Privilege Escalation`)} - - )} - {host_config_key && ( - - {i18n._(t`Allow Provisioning Callbacks`)} - - )} - {allow_simultaneous && ( - - {i18n._(t`Enable Concurrent Jobs`)} - - )} - {use_fact_cache && ( - - {i18n._(t`Use Fact Cache`)} - - )} - - ); + const inventoryValue = (kind, id) => { + const inventorykind = kind === 'smart' ? 'smart_inventory' : 'inventory'; - const renderMissingDataDetail = value => ( - - ); - - const inventoryValue = (kind, id) => { - const inventorykind = - kind === 'smart' ? (kind = 'smart_inventory') : (kind = 'inventory'); - - return ask_inventory_on_launch ? ( - - - {summary_fields.inventory.name} - - {i18n._(t`(Prompt on Launch)`)} - - ) : ( + return ask_inventory_on_launch ? ( + {summary_fields.inventory.name} - ); - }; + {i18n._(t`(Prompt on Launch)`)} + + ) : ( + + {summary_fields.inventory.name} + + ); + }; - if (contentError) { - return ; - } + if (contentError) { + return ; + } - if (hasContentLoading) { - return ; - } + if (hasContentLoading) { + return ; + } - return ( - isInitialized && ( - - - - - - - {summary_fields.inventory ? ( - - ) : ( - !ask_inventory_on_launch && - renderMissingDataDetail(i18n._(t`Inventory`)) + return ( + + + + + + {summary_fields.inventory ? ( + - {summary_fields.project - ? summary_fields.project.name - : i18n._(t`Deleted`)} - - } - /> - ) : ( - renderMissingDataDetail(i18n._(t`Project`)) - )} - - - - + /> + ) : ( + !ask_inventory_on_launch && + renderMissingDataDetail(i18n._(t`Inventory`)) + )} + {summary_fields.project ? ( + + {summary_fields.project.name} + + } + /> + ) : ( + renderMissingDataDetail(i18n._(t`Project`)) + )} + + + + + + + + + + + {host_config_key && ( + - - - - - {host_config_key && ( - - - - - )} - {renderOptionsField && ( - - )} - {summary_fields.credentials && - summary_fields.credentials.length > 0 && ( - - {summary_fields.credentials.map(c => ( - - ))} - - } - /> - )} - {summary_fields.labels && summary_fields.labels.results.length > 0 && ( - - {summary_fields.labels.results.map(l => ( - - {l.name} - - ))} - - } - /> - )} - {instanceGroups.length > 0 && ( - - {instanceGroups.map(ig => ( - - {ig.name} - - ))} - - } - /> - )} - {job_tags && job_tags.length > 0 && ( - - {job_tags.split(',').map(jobTag => ( - - {jobTag} - - ))} - - } - /> - )} - {skip_tags && skip_tags.length > 0 && ( - - {skip_tags.split(',').map(skipTag => ( - - {skipTag} - - ))} - - } - /> - )} - - - {summary_fields.user_capabilities.edit && ( - + )} + {canLaunch && ( + + {({ handleLaunch }) => ( + )} - {canLaunch && ( - - {({ handleLaunch }) => ( - - )} - - )} - - - ) - ); - } + + )} + + + ); } + export { JobTemplateDetail as _JobTemplateDetail }; -export default withI18n()(withRouter(JobTemplateDetail)); +export default withI18n()(JobTemplateDetail);