diff --git a/awx/ui_next/src/screens/Credential/CredentialDetail/CredentialDetail.jsx b/awx/ui_next/src/screens/Credential/CredentialDetail/CredentialDetail.jsx
index b297c679ef..f66389f3a1 100644
--- a/awx/ui_next/src/screens/Credential/CredentialDetail/CredentialDetail.jsx
+++ b/awx/ui_next/src/screens/Credential/CredentialDetail/CredentialDetail.jsx
@@ -1,9 +1,9 @@
-import React, { useState, useEffect, useCallback } from 'react';
+import React, { Fragment, useState, useEffect, useCallback } from 'react';
import { Link, useHistory } from 'react-router-dom';
import { withI18n } from '@lingui/react';
-import { t } from '@lingui/macro';
+import { t, Trans } from '@lingui/macro';
import { shape } from 'prop-types';
-
+import styled from 'styled-components';
import { Button, List, ListItem } from '@patternfly/react-core';
import AlertModal from '../../../components/AlertModal';
import { CardBody, CardActionsRow } from '../../../components/Card';
@@ -11,15 +11,26 @@ import ContentError from '../../../components/ContentError';
import ContentLoading from '../../../components/ContentLoading';
import DeleteButton from '../../../components/DeleteButton';
import {
- DetailList,
Detail,
+ DetailList,
UserDateDetail,
} from '../../../components/DetailList';
+import ChipGroup from '../../../components/ChipGroup';
+import CodeMirrorInput from '../../../components/CodeMirrorInput';
+import CredentialChip from '../../../components/CredentialChip';
import ErrorDetail from '../../../components/ErrorDetail';
import { CredentialsAPI, CredentialTypesAPI } from '../../../api';
import { Credential } from '../../../types';
import useRequest, { useDismissableError } from '../../../util/useRequest';
+const PluginInputMetadata = styled(CodeMirrorInput)`
+ grid-column: 1 / -1;
+`;
+
+const PluginFieldText = styled.p`
+ margin-top: 10px;
+`;
+
function CredentialDetail({ i18n, credential }) {
const {
id: credentialId,
@@ -38,6 +49,7 @@ function CredentialDetail({ i18n, credential }) {
} = credential;
const [fields, setFields] = useState([]);
+ const [inputSources, setInputSources] = useState({});
const [managedByTower, setManagedByTower] = useState([]);
const [contentError, setContentError] = useState(null);
const [hasContentLoading, setHasContentLoading] = useState(true);
@@ -48,19 +60,33 @@ function CredentialDetail({ i18n, credential }) {
setContentError(null);
setHasContentLoading(true);
try {
- const {
- data: { inputs: credentialTypeInputs, managed_by_tower },
- } = await CredentialTypesAPI.readDetail(credential_type.id);
+ const [
+ {
+ data: { inputs: credentialTypeInputs, managed_by_tower },
+ },
+ {
+ data: { results: loadedInputSources },
+ },
+ ] = await Promise.all([
+ CredentialTypesAPI.readDetail(credential_type.id),
+ CredentialsAPI.readInputSources(credentialId, { page_size: 200 }),
+ ]);
setFields(credentialTypeInputs.fields || []);
setManagedByTower(managed_by_tower);
+ setInputSources(
+ loadedInputSources.reduce((inputSourcesMap, inputSource) => {
+ inputSourcesMap[inputSource.input_field_name] = inputSource;
+ return inputSourcesMap;
+ }, {})
+ );
} catch (error) {
setContentError(error);
} finally {
setHasContentLoading(false);
}
})();
- }, [credential_type]);
+ }, [credential_type, credentialId]);
const {
request: deleteCredential,
@@ -76,35 +102,77 @@ function CredentialDetail({ i18n, credential }) {
const { error, dismissError } = useDismissableError(deleteError);
const renderDetail = ({ id, label, type, ask_at_runtime }) => {
- let detail;
+ if (inputSources[id]) {
+ return (
+
+ {label} *}
+ value={
+
+
+
+ }
+ />
+ {}}
+ rows={5}
+ hasErrors={false}
+ />
+
+ );
+ }
if (type === 'boolean') {
- detail = (
+ return (
{inputs[id] && {label}}}
/>
);
- } else if (inputs[id] === '$encrypted$') {
- const isEncrypted = true;
- detail = (
+ }
+
+ if (inputs[id] === '$encrypted$') {
+ return (
);
- } else if (ask_at_runtime && inputs[id] === 'ASK') {
- detail = (
-
- );
- } else {
- detail = ;
}
- return detail;
+ if (ask_at_runtime && inputs[id] === 'ASK') {
+ return (
+
+ );
+ }
+
+ return (
+
+ );
};
if (hasContentLoading) {
@@ -118,10 +186,19 @@ function CredentialDetail({ i18n, credential }) {
return (
-
-
+
+
{organization && (
@@ -131,6 +208,7 @@ function CredentialDetail({ i18n, credential }) {
/>
)}
renderDetail(field))}
+ {Object.keys(inputSources).length > 0 && (
+
+
+ * This field will be retrieved from an external secret management
+ system using the specified credential.
+
+
+ )}
{user_capabilities.edit && (