mirror of
https://github.com/ansible/awx.git
synced 2026-01-11 10:00:01 -03:30
Merge pull request #10019 from mabashian/9635-cred-bugs
Fixes for a couple of credential form bugs SUMMARY link #9635 This addresses the first and second bullet points in the linked issue. The third is actually covered by a separate PR. The ace editor fix was to simply wrap it in a div and apply the previous styling to that div instead of the editor. The secret key/details page crashing was caused by a race condition when would redirect back to the details view after editing. The details view was rendering with some stale data and a key that was expected to be there was not. To fix this I wrapped the request to fetch the credential detail in a useRequest hook and show the loading spinner while this request is outstanding. Only after the request resolves do we try to render the details view so that it always has the up to date object. ISSUE TYPE Bugfix Pull Request COMPONENT NAME UI Reviewed-by: Kersom <None> Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
This commit is contained in:
commit
ddb1d12a79
@ -1,4 +1,4 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import React, { useCallback, useEffect } from 'react';
|
||||
import { t } from '@lingui/macro';
|
||||
|
||||
import { CaretLeftIcon } from '@patternfly/react-icons';
|
||||
@ -12,37 +12,49 @@ import {
|
||||
Redirect,
|
||||
Link,
|
||||
} from 'react-router-dom';
|
||||
import useRequest from '../../util/useRequest';
|
||||
import { ResourceAccessList } from '../../components/ResourceAccessList';
|
||||
import ContentError from '../../components/ContentError';
|
||||
import ContentLoading from '../../components/ContentLoading';
|
||||
import RoutedTabs from '../../components/RoutedTabs';
|
||||
import CredentialDetail from './CredentialDetail';
|
||||
import CredentialEdit from './CredentialEdit';
|
||||
import { CredentialsAPI } from '../../api';
|
||||
|
||||
function Credential({ setBreadcrumb }) {
|
||||
const [credential, setCredential] = useState(null);
|
||||
const [contentError, setContentError] = useState(null);
|
||||
const [hasContentLoading, setHasContentLoading] = useState(true);
|
||||
const { pathname } = useLocation();
|
||||
|
||||
const match = useRouteMatch({
|
||||
path: '/credentials/:id',
|
||||
});
|
||||
const { id } = useParams();
|
||||
|
||||
useEffect(() => {
|
||||
async function fetchData() {
|
||||
try {
|
||||
const { data } = await CredentialsAPI.readDetail(id);
|
||||
setBreadcrumb(data);
|
||||
setCredential(data);
|
||||
} catch (error) {
|
||||
setContentError(error);
|
||||
} finally {
|
||||
setHasContentLoading(false);
|
||||
}
|
||||
const {
|
||||
request: fetchCredential,
|
||||
result: { credential },
|
||||
isLoading: hasContentLoading,
|
||||
error: contentError,
|
||||
} = useRequest(
|
||||
useCallback(async () => {
|
||||
const { data } = await CredentialsAPI.readDetail(id);
|
||||
return {
|
||||
credential: data,
|
||||
};
|
||||
}, [id]),
|
||||
{
|
||||
credential: null,
|
||||
}
|
||||
fetchData();
|
||||
}, [id, pathname, setBreadcrumb]);
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
fetchCredential();
|
||||
}, [fetchCredential, pathname]);
|
||||
|
||||
useEffect(() => {
|
||||
if (credential) {
|
||||
setBreadcrumb(credential);
|
||||
}
|
||||
}, [credential, setBreadcrumb]);
|
||||
|
||||
const tabsArray = [
|
||||
{
|
||||
@ -90,49 +102,52 @@ function Credential({ setBreadcrumb }) {
|
||||
<PageSection>
|
||||
<Card>
|
||||
{showCardHeader && <RoutedTabs tabsArray={tabsArray} />}
|
||||
<Switch>
|
||||
<Redirect
|
||||
from="/credentials/:id"
|
||||
to="/credentials/:id/details"
|
||||
exact
|
||||
/>
|
||||
{credential && [
|
||||
<Route key="details" path="/credentials/:id/details">
|
||||
<CredentialDetail credential={credential} />
|
||||
</Route>,
|
||||
<Route key="edit" path="/credentials/:id/edit">
|
||||
<CredentialEdit credential={credential} />
|
||||
</Route>,
|
||||
<Route key="access" path="/credentials/:id/access">
|
||||
<ResourceAccessList
|
||||
resource={credential}
|
||||
apiModel={CredentialsAPI}
|
||||
/>
|
||||
</Route>,
|
||||
{hasContentLoading && <ContentLoading />}
|
||||
{!hasContentLoading && credential && (
|
||||
<Switch>
|
||||
<Redirect
|
||||
from="/credentials/:id"
|
||||
to="/credentials/:id/details"
|
||||
exact
|
||||
/>
|
||||
{credential && [
|
||||
<Route key="details" path="/credentials/:id/details">
|
||||
<CredentialDetail credential={credential} />
|
||||
</Route>,
|
||||
<Route key="edit" path="/credentials/:id/edit">
|
||||
<CredentialEdit credential={credential} />
|
||||
</Route>,
|
||||
<Route key="access" path="/credentials/:id/access">
|
||||
<ResourceAccessList
|
||||
resource={credential}
|
||||
apiModel={CredentialsAPI}
|
||||
/>
|
||||
</Route>,
|
||||
<Route key="not-found" path="*">
|
||||
{!hasContentLoading && (
|
||||
<ContentError isNotFound>
|
||||
{match.params.id && (
|
||||
<Link to={`/credentials/${match.params.id}/details`}>
|
||||
{t`View Credential Details`}
|
||||
</Link>
|
||||
)}
|
||||
</ContentError>
|
||||
)}
|
||||
</Route>,
|
||||
]}
|
||||
<Route key="not-found" path="*">
|
||||
{!hasContentLoading && (
|
||||
<ContentError isNotFound>
|
||||
{match.params.id && (
|
||||
<Link to={`/credentials/${match.params.id}/details`}>
|
||||
{id && (
|
||||
<Link to={`/credentials/${id}/details`}>
|
||||
{t`View Credential Details`}
|
||||
</Link>
|
||||
)}
|
||||
</ContentError>
|
||||
)}
|
||||
</Route>,
|
||||
]}
|
||||
<Route key="not-found" path="*">
|
||||
{!hasContentLoading && (
|
||||
<ContentError isNotFound>
|
||||
{id && (
|
||||
<Link to={`/credentials/${id}/details`}>
|
||||
{t`View Credential Details`}
|
||||
</Link>
|
||||
)}
|
||||
</ContentError>
|
||||
)}
|
||||
</Route>
|
||||
</Switch>
|
||||
</Route>
|
||||
</Switch>
|
||||
)}
|
||||
</Card>
|
||||
</PageSection>
|
||||
);
|
||||
|
||||
@ -23,7 +23,7 @@ import { Credential } from '../../../types';
|
||||
import useRequest, { useDismissableError } from '../../../util/useRequest';
|
||||
import { relatedResourceDeleteRequests } from '../../../util/getRelatedResourceDeleteDetails';
|
||||
|
||||
const PluginInputMetadata = styled(CodeEditor)`
|
||||
const PluginInputMetadata = styled.div`
|
||||
grid-column: 1 / -1;
|
||||
`;
|
||||
|
||||
@ -117,16 +117,18 @@ function CredentialDetail({ credential }) {
|
||||
</ChipGroup>
|
||||
}
|
||||
/>
|
||||
<PluginInputMetadata
|
||||
dataCy={`credential-${id}-detail`}
|
||||
id={`credential-${id}-metadata`}
|
||||
mode="javascript"
|
||||
readOnly
|
||||
value={JSON.stringify(inputSources[id].metadata, null, 2)}
|
||||
onChange={() => {}}
|
||||
rows={5}
|
||||
hasErrors={false}
|
||||
/>
|
||||
<PluginInputMetadata>
|
||||
<CodeEditor
|
||||
dataCy={`credential-${id}-detail`}
|
||||
id={`credential-${id}-metadata`}
|
||||
mode="javascript"
|
||||
readOnly
|
||||
value={JSON.stringify(inputSources[id].metadata, null, 2)}
|
||||
onChange={() => {}}
|
||||
rows={5}
|
||||
hasErrors={false}
|
||||
/>
|
||||
</PluginInputMetadata>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user