diff --git a/awx/ui_next/src/screens/Project/Project.jsx b/awx/ui_next/src/screens/Project/Project.jsx index cb518b7bff..f87aee15dc 100644 --- a/awx/ui_next/src/screens/Project/Project.jsx +++ b/awx/ui_next/src/screens/Project/Project.jsx @@ -137,10 +137,10 @@ function Project({ i18n, setBreadcrumb }) { ); } - let showCardHeader = true; - if (['edit', 'schedules/'].some(name => location.pathname.includes(name))) { - showCardHeader = false; - } + const showCardHeader = !( + location.pathname.endsWith('edit') || + location.pathname.includes('schedules/') + ); return ( diff --git a/awx/ui_next/src/screens/Template/JobTemplateEdit/JobTemplateEdit.jsx b/awx/ui_next/src/screens/Template/JobTemplateEdit/JobTemplateEdit.jsx index 1e206e03f3..182c4918f1 100644 --- a/awx/ui_next/src/screens/Template/JobTemplateEdit/JobTemplateEdit.jsx +++ b/awx/ui_next/src/screens/Template/JobTemplateEdit/JobTemplateEdit.jsx @@ -1,19 +1,21 @@ /* eslint react/no-unused-state: 0 */ import React, { useState } from 'react'; import { withRouter, Redirect, useHistory } from 'react-router-dom'; - import { CardBody } from '../../../components/Card'; + import { JobTemplatesAPI } from '../../../api'; import { JobTemplate } from '../../../types'; import { getAddedAndRemoved } from '../../../util/lists'; import JobTemplateForm from '../shared/JobTemplateForm'; +import ContentLoading from '../../../components/ContentLoading'; + function JobTemplateEdit({ template }) { - const { id, type } = template; const history = useHistory(); const [formSubmitError, setFormSubmitError] = useState(null); + const [isLoading, setIsLoading] = useState(false); - const detailsUrl = `/templates/${type}/${id}/details`; + const detailsUrl = `/templates/${template.type}/${template.id}/details`; const handleSubmit = async values => { const { @@ -28,6 +30,7 @@ function JobTemplateEdit({ template }) { } = values; setFormSubmitError(null); + setIsLoading(true); remainingValues.project = values.project.id; remainingValues.webhook_credential = webhook_credential?.id || null; try { @@ -38,8 +41,10 @@ function JobTemplateEdit({ template }) { submitCredentials(credentials), ]); history.push(detailsUrl); - } catch (err) { - setFormSubmitError(err); + } catch (error) { + setFormSubmitError(error); + } finally { + setIsLoading(false); } }; @@ -94,12 +99,14 @@ function JobTemplateEdit({ template }) { history.push(detailsUrl); }; - const canEdit = template.summary_fields.user_capabilities.edit; + const canEdit = template?.summary_fields?.user_capabilities?.edit; if (!canEdit) { return ; } - + if (isLoading) { + return ; + } return ( { @@ -44,9 +46,8 @@ function Template({ i18n, me, setBreadcrumb }) { role_level: 'notification_admin_role', }), ]); - - if (actions.data.actions.PUT) { - if (data.webhook_service && data?.related?.webhook_key) { + if (actions?.data?.actions?.PUT) { + if (data?.webhook_service && data?.related?.webhook_key) { const { data: { webhook_key }, } = await JobTemplatesAPI.readWebhookKey(templateId); @@ -54,35 +55,40 @@ function Template({ i18n, me, setBreadcrumb }) { data.webhook_key = webhook_key; } } - setBreadcrumb(data); - return { template: data, isNotifAdmin: notifAdminRes.data.results.length > 0, }; - }, [setBreadcrumb, templateId]), + }, [templateId]), { isNotifAdmin: false, template: null } ); + useEffect(() => { loadTemplateAndRoles(); }, [loadTemplateAndRoles, location.pathname]); + useEffect(() => { + if (template) { + setBreadcrumb(template); + } + }, [template, setBreadcrumb]); + const createSchedule = data => { - return JobTemplatesAPI.createSchedule(templateId, data); + return JobTemplatesAPI.createSchedule(template.id, data); }; const loadScheduleOptions = useCallback(() => { - return JobTemplatesAPI.readScheduleOptions(templateId); - }, [templateId]); + return JobTemplatesAPI.readScheduleOptions(template.id); + }, [template]); const loadSchedules = useCallback( params => { - return JobTemplatesAPI.readSchedules(templateId, params); + return JobTemplatesAPI.readSchedules(template.id, params); }, - [templateId] + [template] ); - const canSeeNotificationsTab = me.is_system_auditor || isNotifAdmin; + const canSeeNotificationsTab = me?.is_system_auditor || isNotifAdmin; const canAddAndEditSurvey = template?.summary_fields?.user_capabilities.edit || template?.summary_fields?.user_capabilities.delete; @@ -131,17 +137,7 @@ function Template({ i18n, me, setBreadcrumb }) { tab.id = n; }); - let showCardHeader = true; - - if ( - location.pathname.endsWith('edit') || - location.pathname.includes('schedules/') - ) { - showCardHeader = false; - } - - const contentError = rolesAndTemplateError; - if (!hasRolesandTemplateLoading && contentError) { + if (contentError) { return ( @@ -158,38 +154,37 @@ function Template({ i18n, me, setBreadcrumb }) { ); } + const showCardHeader = !( + location.pathname.endsWith('edit') || + location.pathname.includes('schedules/') + ); + return ( {showCardHeader && } - - - {template && ( + {template && ( + + - )} - {template && ( - )} - {template && ( - )} - {template && ( - )} - {canSeeNotificationsTab && ( - - - - )} - {template?.id && ( + {canSeeNotificationsTab && ( + + + + )} - )} - {template && ( - )} - {!hasRolesandTemplateLoading && ( - - - {match.params.id && ( - - {i18n._(t`View Template Details`)} - - )} - - - )} - + {!isLoading && ( + + + {match.params.id && ( + + {i18n._(t`View Template Details`)} + + )} + + + )} + + )} ); diff --git a/awx/ui_next/src/screens/Template/Templates.jsx b/awx/ui_next/src/screens/Template/Templates.jsx index a9d5ecc726..fbc9e237af 100644 --- a/awx/ui_next/src/screens/Template/Templates.jsx +++ b/awx/ui_next/src/screens/Template/Templates.jsx @@ -1,10 +1,9 @@ -import React, { useState } from 'react'; +import React, { useState, useCallback, useRef } from 'react'; import { withI18n } from '@lingui/react'; import { t } from '@lingui/macro'; -import { Route, withRouter, Switch, useRouteMatch } from 'react-router-dom'; +import { Route, withRouter, Switch } from 'react-router-dom'; import { PageSection } from '@patternfly/react-core'; -import { Config } from '../../contexts/Config'; import Breadcrumbs from '../../components/Breadcrumbs/Breadcrumbs'; import { TemplateList } from './TemplateList'; import Template from './Template'; @@ -13,101 +12,58 @@ import JobTemplateAdd from './JobTemplateAdd'; import WorkflowJobTemplateAdd from './WorkflowJobTemplateAdd'; function Templates({ i18n }) { - const match = useRouteMatch(); - const [breadcrumbConfig, setBreadcrumbs] = useState({ + const initBreadcrumbs = useRef({ '/templates': i18n._(t`Templates`), '/templates/job_template/add': i18n._(t`Create New Job Template`), '/templates/workflow_job_template/add': i18n._( t`Create New Workflow Template` ), }); - - const setBreadCrumbConfig = (template, schedule) => { - if (!template) { - return; - } - const breadcrumb = { - '/templates': i18n._(t`Templates`), - '/templates/job_template/add': i18n._(t`Create New Job Template`), - '/templates/workflow_job_template/add': i18n._( - t`Create New Workflow Template` - ), - [`/templates/${template.type}/${template.id}`]: `${template.name}`, - [`/templates/${template.type}/${template.id}/details`]: i18n._( - t`Details` - ), - [`/templates/${template.type}/${template.id}/edit`]: i18n._( - t`Edit Details` - ), - [`/templates/${template.type}/${template.id}/access`]: i18n._(t`Access`), - [`/templates/${template.type}/${template.id}/notifications`]: i18n._( - t`Notifications` - ), - [`/templates/${template.type}/${template.id}/completed_jobs`]: i18n._( - t`Completed Jobs` - ), - [`/templates/${template.type}/${template.id}/survey`]: i18n._(t`Survey`), - [`/templates/${template.type}/${template.id}/survey/add`]: i18n._( - t`Add Question` - ), - [`/templates/${template.type}/${template.id}/survey/edit`]: i18n._( - t`Edit Question` - ), - [`/templates/${template.type}/${template.id}/schedules`]: i18n._( - t`Schedules` - ), - [`/templates/${template.type}/${template.id}/schedules/add`]: i18n._( - t`Create New Schedule` - ), - [`/templates/${template.type}/${template.id}/schedules/${schedule && - schedule.id}`]: `${schedule && schedule.name}`, - [`/templates/${template.type}/${template.id}/schedules/${schedule && - schedule.id}/details`]: i18n._(t`Schedule Details`), - [`/templates/${template.type}/${template.id}/schedules/${schedule && - schedule.id}/edit`]: i18n._(t`Edit Details`), - }; - setBreadcrumbs(breadcrumb); - }; + const [breadcrumbConfig, setBreadcrumbs] = useState(initBreadcrumbs.current); + const setBreadcrumbConfig = useCallback( + (template, schedule) => { + if (!template) return; + const templatePath = `/templates/${template.type}/${template.id}`; + const schedulesPath = `${templatePath}/schedules`; + const surveyPath = `${templatePath}/survey`; + setBreadcrumbs({ + ...initBreadcrumbs.current, + [templatePath]: `${template.name}`, + [`${templatePath}/details`]: i18n._(t`Details`), + [`${templatePath}/edit`]: i18n._(t`Edit Details`), + [`${templatePath}/access`]: i18n._(t`Access`), + [`${templatePath}/notifications`]: i18n._(t`Notifications`), + [`${templatePath}/completed_jobs`]: i18n._(t`Completed Jobs`), + [surveyPath]: i18n._(t`Survey`), + [`${surveyPath}add`]: i18n._(t`Add Question`), + [`${surveyPath}/edit`]: i18n._(t`Edit Question`), + [schedulesPath]: i18n._(t`Schedules`), + [`${schedulesPath}/add`]: i18n._(t`Create New Schedule`), + [`${schedulesPath}/${schedule?.id}`]: `${schedule?.name}`, + [`${schedulesPath}/details`]: i18n._(t`Schedule Details`), + [`${schedulesPath}/edit`]: i18n._(t`Edit Details`), + }); + }, + [i18n] + ); return ( <> - + - + - ( - - {({ me }) => ( -