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:
softwarefactory-project-zuul[bot] 2021-05-06 21:49:55 +00:00 committed by GitHub
commit ddb1d12a79
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 80 additions and 63 deletions

View File

@ -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>
);

View File

@ -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>
);
}