diff --git a/gatsby-config.js b/gatsby-config.js
index 99d6a679..db9fb143 100644
--- a/gatsby-config.js
+++ b/gatsby-config.js
@@ -10,6 +10,8 @@
* governing permissions and limitations under the License.
*/
+
+
module.exports = {
siteMetadata: {
pages: [
@@ -224,5 +226,6 @@ module.exports = {
]
},
plugins: [`@adobe/gatsby-theme-aio`],
- pathPrefix: process.env.PATH_PREFIX || "/developer-console/docs/"
+ pathPrefix: process.env.PATH_PREFIX || "/developer-console/docs/",
+
};
diff --git a/package.json b/package.json
index 091d68e8..11587873 100644
--- a/package.json
+++ b/package.json
@@ -12,8 +12,9 @@
"url": "https://github.com/icaraps"
},
"dependencies": {
- "@adobe/gatsby-theme-aio": "^4.14.4",
+ "@adobe/gatsby-theme-aio": "^4.14.12",
"gatsby": "4.22.0",
+ "http-proxy-middleware": "^3.0.3",
"react": "^17.0.2",
"react-dom": "^17.0.2"
},
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/Card/AccessToken.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/Card/AccessToken.js
new file mode 100644
index 00000000..65579d78
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/Card/AccessToken.js
@@ -0,0 +1,142 @@
+import React, { useContext, useEffect, useState } from 'react';
+import { css } from '@emotion/react';
+import { ProgressCircle } from "@adobe/gatsby-theme-aio/src/components/ProgressCircle";
+import { Button } from "@adobe/gatsby-theme-aio/src/components/Button";
+import { CopyIcon } from '../Icons';
+import { Toast } from '@adobe/gatsby-theme-aio/src/components/Toast';
+import GetCredentialContext from '../GetCredentialContext';
+import { generateToken, getCredentialSecrets } from '../Service';
+import { ActionButton } from '@adobe/gatsby-theme-aio/src/components/ActionButton';
+
+const AccessToken = ({ accessToken, response, scopesDetails }) => {
+ const [credentialToken, setCredentialToken] = useState(null);
+ const { selectedOrganization } = useContext(GetCredentialContext);
+ const [isCopiedTooltip, setIsCopiedTooltip] = useState(false);
+ const [isHoveringCopyButton, setIsHoveringCopyButton] = useState(false);
+
+ const handleGenerateToken = async () => {
+ setCredentialToken('loading');
+ const secrets = await getCredentialSecrets(response, selectedOrganization);
+ if (secrets) {
+ let clientId = response?.workspaces ? response?.workspaces[0]?.credentials[0]?.clientId : response?.apiKey;
+ const tokenVal = await generateToken(clientId, secrets?.clientSecret, scopesDetails);
+ navigator.clipboard.writeText(tokenVal);
+ setCredentialToken(tokenVal);
+ }
+ };
+
+ const handleSecretCopyCode = (copiedVal) => {
+ setIsCopiedTooltip(true);
+ navigator.clipboard.writeText(copiedVal);
+ setTimeout(() => setIsCopiedTooltip(false), 1000); // Hide tooltip after 1 second
+ };
+
+ useEffect(() => {
+ setCredentialToken(null);
+ }, [response]);
+
+ return (
+ <>
+ {accessToken && (
+
+ {accessToken?.heading && (
+
{accessToken?.heading}
+ )}
+ {credentialToken === null ? (
+ accessToken?.buttonLabel && (
+
handleGenerateToken()}
+ css={css`
+ width: fit-content;
+ & > button {
+ background-color : #0265dc !important;
+ }
+ `}>
+
+ {accessToken?.buttonLabel}
+
+
+ )
+ ) : (
+ credentialToken === 'loading' ? (
+
+ ) : (
+
+
+ {credentialToken}
+
+
handleSecretCopyCode(credentialToken)}
+ css={css`
+ position: relative;
+ & > button {
+ border: 1px solid rgba(177, 177, 177) !important;
+ padding: 4px !important;
+ border-radius: 2px !important;
+ }
+ `}>
+
setIsHoveringCopyButton(true)}
+ onMouseLeave={() => setIsHoveringCopyButton(false)}
+ >
+
+
+ {isHoveringCopyButton && (
+
+ )}
+
+
+ )
+ )}
+
+ )}
+ {
+ isCopiedTooltip && (
+
+ )
+ }
+ >
+ );
+};
+
+export { AccessToken };
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/Card/CardAPIKey.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/Card/CardAPIKey.js
new file mode 100644
index 00000000..88e09d4a
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/Card/CardAPIKey.js
@@ -0,0 +1,10 @@
+import React from 'react'
+import ShowCard from './ShowCard';
+
+const CardAPIKey = ({ cardAPIKey, apiKey }) => {
+ return (
+
+ )
+}
+
+export { CardAPIKey };
\ No newline at end of file
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/Card/CardAllowedOrigins.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/Card/CardAllowedOrigins.js
new file mode 100644
index 00000000..0ba25ac2
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/Card/CardAllowedOrigins.js
@@ -0,0 +1,10 @@
+import React from 'react'
+import ShowCard from './ShowCard';
+
+const CardAllowedOrigins = ({ cardAllowedOrigins, allowedOrigins }) => {
+ return (
+
+ )
+}
+
+export { CardAllowedOrigins };
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/Card/CardClientDetails.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/Card/CardClientDetails.js
new file mode 100644
index 00000000..0eae54b4
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/Card/CardClientDetails.js
@@ -0,0 +1,82 @@
+import React, { useContext } from 'react';
+import { css } from "@emotion/react";
+import { CardAPIKey } from './CardAPIKey';
+import { CardClientId } from './CardClientId';
+import { CardAllowedOrigins } from './CardAllowedOrigins';
+import { CardClientSecret } from './CardClientSecret';
+import { CardOrganizationName } from './CardOrganizationName';
+import { CardScopes } from './CardScopes';
+import { CardImsOrgID } from './CardImsOrgID';
+import GetCredentialContext from '../GetCredentialContext';
+
+const CardClientDetails = ({
+ clientDetails,
+ clientIdDetails,
+ clientSecretDetails,
+ organizationDetails,
+ scopesDetails,
+ apiKeyDetails,
+ allowedOriginsDetails,
+ organizationName,
+ allowedOrigins,
+ response,
+ imsOrgID
+}) => {
+
+ const { selectedOrganization } = useContext(GetCredentialContext);
+
+ const splitedOrderBy = clientDetails?.orderBy ? clientDetails?.orderBy?.split(',') : [];
+
+ return (
+
+
{clientDetails?.heading}
+
+ {
+ splitedOrderBy?.length > 0 ?
+ <>
+ {splitedOrderBy?.map((list) => {
+ if (list === "APIKey") {
+ return apiKeyDetails &&
+ }
+ if (list === "AllowedOrigins") {
+ return allowedOrigins &&
+ }
+ if (list === "ImsOrgID") {
+ return imsOrgID &&
+ }
+ if (list === "OrganizationName") {
+ return organizationDetails &&
+ }
+ if (list === "ClientId") {
+ return clientIdDetails &&
+ }
+ if (list === "ClientSecret") {
+ return clientSecretDetails &&
+ }
+ if (list === "Scopes") {
+ return scopesDetails &&
+ }
+ })}
+ >
+ :
+ <>
+ {apiKeyDetails && ( )}
+ {clientIdDetails && ( )}
+ {allowedOrigins && ( )}
+ {clientSecretDetails && ( )}
+ {organizationDetails && ( )}
+ {scopesDetails && }
+ {imsOrgID && ( )}
+ >
+ }
+
+
+ );
+};
+
+export { CardClientDetails };
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/Card/CardClientId.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/Card/CardClientId.js
new file mode 100644
index 00000000..4c9ca2ba
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/Card/CardClientId.js
@@ -0,0 +1,10 @@
+ import React from 'react'
+ import ShowCard from './ShowCard'
+
+ const CardClientId = ({ cardClientId, clientId }) => {
+ return (
+
+ )
+ }
+
+ export { CardClientId }
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/Card/CardClientSecret.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/Card/CardClientSecret.js
new file mode 100644
index 00000000..b9a93a94
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/Card/CardClientSecret.js
@@ -0,0 +1,10 @@
+import React from 'react'
+import ShowCard from './ShowCard';
+
+const CardClientSecret = ({ cardClientSecret, response }) => {
+ return (
+
+ )
+}
+
+export { CardClientSecret };
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/Card/CardImsOrgID.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/Card/CardImsOrgID.js
new file mode 100644
index 00000000..7b42d884
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/Card/CardImsOrgID.js
@@ -0,0 +1,8 @@
+import React from 'react';
+import ShowCard from './ShowCard';
+
+const CardImsOrgID = ({ cardImsOrgID, imsOrgId }) => {
+ return ;
+};
+
+export { CardImsOrgID };
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/Card/CardOrganizationName.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/Card/CardOrganizationName.js
new file mode 100644
index 00000000..7ed147c6
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/Card/CardOrganizationName.js
@@ -0,0 +1,10 @@
+import React from 'react'
+import ShowCard from './ShowCard';
+
+const CardOrganizationName = ({ cardOrganizationName, organization }) => {
+ return (
+
+ )
+}
+
+export { CardOrganizationName };
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/Card/CardScopes.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/Card/CardScopes.js
new file mode 100644
index 00000000..9c370c71
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/Card/CardScopes.js
@@ -0,0 +1,9 @@
+import React from 'react'
+import ShowCard from './ShowCard';
+
+const CardScopes = ({ cardScopes }) => {
+ return (
+
+ )
+}
+export { CardScopes };
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/Card/DevConsoleLink.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/Card/DevConsoleLink.js
new file mode 100644
index 00000000..11b62cc8
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/Card/DevConsoleLink.js
@@ -0,0 +1,60 @@
+import React, { useContext } from 'react';
+import { css } from '@emotion/react';
+import { MAX_TABLET_SCREEN_WIDTH, MIN_MOBILE_WIDTH } from '../FormFields';
+import GetCredentialContext from '../GetCredentialContext';
+import { LinkOut } from '../Icons';
+
+const DevConsoleLink = ({ devConsoleLinkHeading, credentialName, projectId }) => {
+
+ const { selectedOrganization } = useContext(GetCredentialContext);
+
+ return (
+ <>
+
+ {devConsoleLinkHeading && (
+
+ {devConsoleLinkHeading}
+
+ )}
+
+
+
+
+
+
+
+
+ >
+ );
+};
+
+export { DevConsoleLink };
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/Card/ShowCard.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/Card/ShowCard.js
new file mode 100644
index 00000000..ba627978
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/Card/ShowCard.js
@@ -0,0 +1,188 @@
+import React, { useContext, useEffect, useState } from 'react';
+import { css } from '@emotion/react';
+import { CopyIcon } from '../Icons';
+import { ActionButton } from "@adobe/gatsby-theme-aio/src/components/ActionButton";
+import { ProgressCircle } from "@adobe/gatsby-theme-aio/src/components/ProgressCircle";
+import { Toast } from '@adobe/gatsby-theme-aio/src/components/Toast';
+import GetCredentialContext from '../GetCredentialContext';
+import { getCredentialSecrets } from '../Service';
+
+const ShowCard = ({
+ heading,
+ value,
+ isClientSecret,
+ buttonLabel,
+ isOraganization,
+ response
+}) => {
+
+ const [showClientSecret, setShowClientSecret] = useState(null);
+ const [isCopiedTooltip, setIsCopiedTooltip] = useState(false);
+ const [isHoveringCopyButton, setIsHoveringCopyButton] = useState(false);
+ const { selectedOrganization } = useContext(GetCredentialContext);
+
+ const handleCreateClientSecret = async () => {
+ setShowClientSecret('loading');
+ const secrets = await getCredentialSecrets(response, selectedOrganization);
+ navigator.clipboard.writeText(secrets?.clientSecret);
+ setShowClientSecret(secrets);
+ };
+
+ const handleSecretCopyCode = (copiedVal) => {
+ setIsCopiedTooltip(true);
+ navigator.clipboard.writeText(copiedVal);
+ setTimeout(() => setIsCopiedTooltip(false), 1000); // Hide tooltip after 1 second
+ }
+
+ useEffect(() => {
+ setShowClientSecret(null);
+ }, [response]);
+
+ return (
+
+
{heading}
+
+ {isClientSecret && (
+ showClientSecret === null ? (
+
{ handleCreateClientSecret() }} data-cy="retrieve-client-secret"
+ css={css`
+ & > button {
+ border: 1px solid rgba(177, 177, 177) !important;
+ padding: 4px !important;
+ border-radius: 2px !important;
+ }
+ `}>
+
{buttonLabel}
+
+ ) : showClientSecret === 'loading' ? (
+
+ ) : (
+
+
+ {showClientSecret?.clientSecret}
+
+
+
setIsHoveringCopyButton(true)}
+ css={css`
+ & > button {
+ border: 1px solid rgba(177, 177, 177) !important;
+ padding: 4px !important;
+ border-radius: 2px !important;
+ }
+ `}
+ onMouseLeave={() => setIsHoveringCopyButton(false)} data-cy="copy-client-secret" onClick={() => { handleSecretCopyCode(showClientSecret?.clientSecret) }}>
+
+
+ {isHoveringCopyButton && (
+
+ )}
+
+
+ )
+ )}
+
+ {value && (
+
+ {value}
+
+ )}
+
+ {!isClientSecret && (
+
setIsHoveringCopyButton(true)}
+ onMouseLeave={() => setIsHoveringCopyButton(false)}
+ css={css`
+ position: relative;
+ display: ${isOraganization ? 'none' : 'block'};
+ `}>
+
{ handleSecretCopyCode(value) }}
+ css={css`
+ & > button {
+ border: 1px solid rgba(177, 177, 177) !important;
+ padding: 4px !important;
+ border-radius: 2px !important;
+ }
+ `}
+ >
+
+
+ {isHoveringCopyButton && (
+
+ )}
+
+ )}
+
+ {
+ isCopiedTooltip && (
+
+ )
+ }
+
+ );
+};
+
+export default ShowCard;
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/ContextHelp.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/ContextHelp.js
new file mode 100644
index 00000000..dedeb550
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/ContextHelp.js
@@ -0,0 +1,64 @@
+import React, { useEffect, useState, useRef } from 'react';
+import { css } from "@emotion/react";
+import classNames from 'classnames';
+import { MAX_TABLET_SCREEN_WIDTH, MIN_MOBILE_WIDTH } from './FormFields';
+
+export const ContextHelp = ({ heading, text, link, label }) => {
+
+ const [isVisible, setisVisible] = useState(false);
+ const buttonRef = useRef();
+
+ const handleClickOutside = e => {
+ if (buttonRef.current.contains(e.target)) setisVisible(!isVisible);
+ else setisVisible(false);
+ };
+
+ useEffect(() => {
+ document.addEventListener('click', handleClickOutside);
+ return () => document.removeEventListener('click', handleClickOutside);
+ });
+
+ return (
+
+
+
+
+
+
+
+
+
+ {heading &&
{heading} }
+ {text &&
{text}
}
+ {link &&
{label} }
+
+
+
+
+ )
+}
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/CredentialDetailsCard.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/CredentialDetailsCard.js
new file mode 100644
index 00000000..127a9e92
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/CredentialDetailsCard.js
@@ -0,0 +1,250 @@
+import React, { useEffect, useState } from 'react';
+import { MAX_TABLET_SCREEN_WIDTH, MIN_MOBILE_WIDTH } from './FormFields';
+import { css } from '@emotion/react';
+import { AccessToken } from './Card/AccessToken';
+import { DevConsoleLink } from './Card/DevConsoleLink';
+import { CardClientDetails } from './Card/CardClientDetails';
+import { CardClientId } from './Card/CardClientId';
+import { CardClientSecret } from './Card/CardClientSecret';
+import { CardOrganizationName } from './Card/CardOrganizationName';
+import { CardScopes } from './Card/CardScopes';
+import { CardAPIKey } from './Card/CardAPIKey';
+import { CardAllowedOrigins } from './Card/CardAllowedOrigins';
+import { ReturnAccessToken } from './Return/ReturnAccessToken';
+import { ReturnDevConsoleLink } from './Return/ReturnDevConsoleLink';
+import { ReturnCredentialDetails } from './Return/ReturnCredentialDetails';
+import { ReturnClientId } from './Return/ReturnClientId';
+import { ReturnClientSecret } from './Return/ReturnClientSecret';
+import { ReturnScopes } from './Return/ReturnScopes';
+import { ReturnAPIKey } from './Return/ReturnAPIKey';
+import { ReturnAllowedOrigins } from './Return/ReturnAllowedOrigins';
+import { ReturnOrganizationName } from './Return/ReturnOrganizationName';
+import { ArrowDown, ArrowRight, KeyIcon, LinkOut } from './Icons';
+import { CardImsOrgID } from './Card/CardImsOrgID';
+
+export const CredentialDetailsCard = ({
+ credentialName,
+ productList,
+ ProductComponent,
+ AccessTokenComponent,
+ DevConsoleLinkComponent,
+ ClientDetailsComponent,
+ allowedOriginsDetails,
+ organizationName,
+ nextButtonLink,
+ nextButtonLabel,
+ devConsoleLink,
+ developerConsoleManage,
+ response,
+ myCredentialFields,
+ returnFields,
+ collapse
+}) => {
+
+ let accessToken, devConsoleLinkHeading, clientDetails, clientIdDetails, clientSecretDetails, organizationDetails, scopesDetails, apiKeyDetails, allowedOrigins, imsOrgID;
+ if (myCredentialFields) {
+ accessToken = myCredentialFields[AccessToken];
+ devConsoleLinkHeading = myCredentialFields[DevConsoleLink]?.heading;
+ clientDetails = myCredentialFields[CardClientDetails];
+ clientIdDetails = myCredentialFields[CardClientId];
+ clientSecretDetails = myCredentialFields[CardClientSecret];
+ organizationDetails = myCredentialFields[CardOrganizationName];
+ scopesDetails = myCredentialFields[CardScopes];
+ apiKeyDetails = myCredentialFields[CardAPIKey];
+ allowedOrigins = myCredentialFields[CardAllowedOrigins];
+ imsOrgID = myCredentialFields?.[CardImsOrgID];
+ }
+ else if (returnFields) {
+ accessToken = returnFields?.[ReturnAccessToken];
+ devConsoleLinkHeading = returnFields?.[ReturnDevConsoleLink]?.heading;
+ clientDetails = returnFields?.[ReturnCredentialDetails];
+ clientIdDetails = returnFields?.[ReturnClientId];
+ clientSecretDetails = returnFields?.[ReturnClientSecret];
+ scopesDetails = returnFields?.[ReturnScopes];
+ apiKeyDetails = returnFields?.[ReturnAPIKey];
+ organizationDetails = returnFields?.[ReturnOrganizationName];
+ allowedOrigins = returnFields?.[ReturnAllowedOrigins];
+ imsOrgID = returnFields?.[CardImsOrgID];
+ }
+
+ const bool = collapse === "true" ? true : false;
+ const [isCollapse, setIsCollapse] = useState(false);
+
+ const handleCollapse = () => {
+ setIsCollapse(!isCollapse);
+ }
+
+ useEffect(() => {
+ if (!bool) {
+ setIsCollapse(true);
+ }
+ }, [bool])
+
+ console.log('clientDetails', clientDetails)
+ console.log('isCollapse', isCollapse)
+
+ return (
+ <>
+
+
+
+
+ {isCollapse &&
+ <>
+
+
+ {accessToken &&
}
+
+ {devConsoleLinkHeading && (
+
+ )}
+
+ {clientDetails && (
+
+ )}
+
+
+
+ >
+ }
+
+
+ >
+ );
+};
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/CredentialForm.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/CredentialForm.js
new file mode 100644
index 00000000..c2f2d51a
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/CredentialForm.js
@@ -0,0 +1,436 @@
+import React, { useContext, useEffect, useState } from 'react';
+import { css } from '@emotion/react';
+import classNames from 'classnames';
+import '@spectrum-css/contextualhelp/dist/index-vars.css';
+import { Toast } from '@adobe/gatsby-theme-aio/src/components/Toast';
+import { handleAllowedDomainsValidation, MAX_TABLET_SCREEN_WIDTH, MIN_MOBILE_WIDTH } from './FormFields';
+import { SideComponent } from './SideComponent';
+import { CredentialName } from './Form/CredentialName';
+import { AllowedOrigins } from './Form/AllowedOrigins';
+import { Downloads } from './Form/Downloads';
+import { Download } from './Form/Download';
+import { SideContent } from './Form/SideContent';
+import { AdobeDeveloperConsole } from './Form/AdobeDeveloperConsole';
+import { CreateCredential } from './Form/CreateCredential';
+import { MyCredential } from './MyCredential';
+import { Loading } from './Loading';
+import { IllustratedMessage } from './IllustratedMessage';
+import { Product, Products } from './Products';
+import { Organization } from './Organization';
+import GetCredentialContext from './GetCredentialContext';
+
+const credentialNameRegex = /^(?=[A-Za-z0-9\s]{6,}$)[A-Za-z0-9\s]*$/;
+
+const CredentialForm = ({
+ showCreateForm,
+ setShowCreateForm,
+ isCreateNewCredential,
+ setIsCreateNewCredential,
+ setIsPrevious,
+ formData,
+ setFormData
+}) => {
+ const { getCredentialData } = useContext(GetCredentialContext);
+ const formProps = getCredentialData;
+
+ const [loading, setLoading] = useState(false);
+ const [isError, setIsError] = useState(false);
+ const [response, setResponse] = useState({});
+ const [errResp, setErrorResp] = useState('');
+ const [showCredential, setShowCredential] = useState(false);
+ const [formField, setFormField] = useState([]);
+ const [isValid, setIsValid] = useState(false);
+ const [isMyCredential, setIsMyCredential] = useState(false);
+ const [isShow, setIsShow] = useState(false);
+ const [alertShow, setAlertShow] = useState(false);
+
+ const [isAllowedOriginsValid, setIsAllowedOriginsValid] = useState();
+
+ const { selectedOrganization, template, previousProjectDetail } = useContext(GetCredentialContext);
+
+ const credentialForm = formProps?.[CredentialForm];
+ const isFormValue = credentialForm?.children?.filter(data =>
+ Object.keys(data.props).some(key => key.startsWith('contextHelp'))
+ );
+
+ const initialLoad = () => {
+ const fields = {};
+ const downloadObj = { label: 'Language', selectOptions: [] };
+ const productsObj = { label: 'products', productList: [] };
+
+ credentialForm?.children.forEach(({ type, props }) => {
+ if (type === Downloads && props?.children) {
+ downloadObj.required = props.required || false;
+ downloadObj.selectOptions.push(
+ ...[].concat(props.children).map(({ props: { title, href } }) => ({ title, href }))
+ );
+ setFormData(prevData => ({
+ ...prevData,
+ ...(Array.isArray(props.children) ? null : { Download: props.children?.props?.title }),
+ }));
+ }
+ if (type === Products && props?.children) {
+ productsObj.productList.push(
+ ...[].concat(props.children).map(({ props: { label, icon } }) => ({ label, icon }))
+ );
+ }
+ fields[type] = { ...props, required: type === CredentialName || props?.required };
+ });
+
+ if (downloadObj.selectOptions.length) {
+ fields[Download] = downloadObj;
+ if (downloadObj.selectOptions.length === 1) {
+ setFormData(prevData => ({
+ ...prevData,
+ Download: downloadObj.selectOptions[0]?.title,
+ zipUrl: downloadObj.selectOptions[0]?.href,
+ }));
+ }
+ }
+ if (productsObj?.productList.length) {
+ fields[Product] = productsObj;
+ }
+
+ const isCredential = previousProjectDetail?.count ? true : false;
+ if (isCredential) {
+ setIsMyCredential(true);
+ } else {
+ setIsMyCredential(false);
+ }
+
+ setFormField(fields);
+ };
+
+ useEffect(() => {
+ if (window.adobeIMS?.isSignedInUser()) {
+ setTimeout(() => {
+ setLoading(false);
+ }, 1000);
+ } else {
+ setLoading(true);
+ }
+ }, [window.adobeIMS?.isSignedInUser()]);
+
+ useEffect(() => {
+ if (showCreateForm) setIsError(false);
+ }, [showCreateForm]);
+
+
+ useEffect(() => {
+ initialLoad();
+ }, []);
+
+ useEffect(() => {
+ const isValidCredentialName = credentialNameRegex.test(formData.CredentialName);
+
+ const isCheckAllowedOrgins = credentialForm.children.some((child) => {
+ return child.type === AllowedOrigins;
+ })
+ let isAllowedOriginsValid;
+ if (isCheckAllowedOrgins) {
+ if (formData['AllowedOrigins']) {
+ isAllowedOriginsValid = handleAllowedDomainsValidation(formData['AllowedOrigins'])
+ }
+ }
+ else {
+ isAllowedOriginsValid = true;
+ }
+ setIsAllowedOriginsValid(isAllowedOriginsValid)
+
+ const isValid = isValidCredentialName && (!isCheckAllowedOrgins || isAllowedOriginsValid) && formData.Agree === true;
+ setIsValid(isValid);
+ }, [formData]);
+
+ const handleChange = (e, type) => {
+ let value;
+ if (type === 'Download') {
+ value = e.title;
+ }
+ else {
+ value = type === 'Downloads' || type === 'Agree' ? e.target.checked : e.target.value;
+ }
+
+ setFormData(prevData => ({ ...prevData, [type]: value }));
+ if (type === 'Downloads') {
+ handleChange(download?.selectOptions[0], 'Download')
+ }
+
+ if (type === 'Download') {
+ const selectedData = formField?.[Download]?.selectOptions.find(
+ data => data.title === value
+ );
+ selectedData && setFormData(prevData => ({ ...prevData, zipUrl: selectedData.href }));
+ }
+ };
+
+ const handleErrors = (detailedMessage) => {
+ setLoading(false);
+ setAlertShow(true);
+ setIsValid(false);
+ setErrorResp(detailedMessage);
+ setShowCreateForm(true);
+ setIsError(true);
+ }
+
+ const createCredential = async () => {
+ const token = window.adobeIMS?.getTokenFromStorage()?.token;
+
+ if (!token) {
+ console.log('User not logged in');
+ }
+
+ setLoading(true);
+ setShowCreateForm(false);
+
+ const apis = template.apis.map(api => ({
+ code: api.code,
+ credentialType: api.credentialType,
+ flowType: api.flowType,
+ licenseConfigs:
+ Array.isArray(api.licenseConfigs) && api.licenseConfigs.length > 0
+ ? [{ ...api.licenseConfigs[0], op: 'add' }]
+ : [],
+ }));
+
+ const data = {
+ projectName: formData['CredentialName'],
+ description: 'created for get credential',
+ metadata: {
+ domain: formData['AllowedOrigins'],
+ },
+ orgId: selectedOrganization.code,
+ apis,
+ };
+
+ try {
+ const url = `/templates/install/${template.id}`;
+ const response = await fetch(url, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${token}`,
+ 'x-api-key': window?.adobeIMS?.adobeIdData?.client_id,
+ Accept: 'application/json',
+ },
+ body: JSON.stringify(data),
+ });
+
+ const resResp = await response?.json();
+
+ if (response.ok) {
+ setResponse(resResp);
+ setShowCredential(true);
+ setAlertShow(true);
+ setLoading(false);
+ } else {
+ const jsonString = resResp.errors[0].message.match(/\((\{.*\})\)/)[1];
+ const errorDetails = JSON.parse(jsonString);
+ handleErrors(errorDetails.messages[0].message)
+ }
+ } catch (error) {
+ setShowCreateForm(true);
+ setLoading(false);
+ setAlertShow(true);
+ setErrorResp(error.message);
+ setIsError(true);
+ }
+ };
+
+ useEffect(() => {
+ if (isMyCredential) {
+ setIsPrevious(true);
+ setShowCreateForm(true);
+ }
+ }, [isMyCredential]);
+
+ const sideObject = formField?.[SideComponent];
+ const credentialName = formField?.[CredentialName];
+ const allowedOrigins = formField?.[AllowedOrigins];
+ const downloads = formField?.[Downloads];
+ const download = formField?.[Download];
+ const products = formField?.[Products];
+ const product = formField?.[Product];
+ const adobeDeveloperConsole = formField?.[AdobeDeveloperConsole];
+
+ const handleRestart = () => {
+ setShowCreateForm(true);
+ setShowCredential(false);
+ setIsCreateNewCredential(true);
+ setIsMyCredential(true);
+ setFormData({});
+ };
+
+ return (
+ <>
+ {showCreateForm && !loading && (
+
+
+
+ {credentialForm?.title && (
+
+ {credentialForm?.title}
+
+ )}
+ {credentialForm?.paragraph && (
+
{credentialForm?.paragraph}
+ )}
+
setIsShow(true)}>
+ {selectedOrganization.type === "developer" ?
+ "You're creating this credential in your personal developer organization" :
+ <>You're creating this credential in [{selectedOrganization?.name} ].>}
+
+
+
+
+
+
+
+ {credentialName && (
+
+ )}
+ {allowedOrigins && (
+
+ )}
+ {downloads && download && (
+
+ )}
+ {formData['Downloads'] && download && (
+
+ )}
+
+ {adobeDeveloperConsole && (
+
+ )}
+
+
+
+ {sideObject ? (
+
+ ) : null}
+
+
+ )}
+ {alertShow && (
+ <>
+ {
+
+ }
+ >
+ )}
+ {loading && !showCredential && !isError && !showCreateForm && (
+
+ )}
+ {isError && !showCreateForm && !showCredential && (
+
+ )}
+ {showCredential && !showCreateForm && (
+
+ )}
+ >
+ );
+};
+
+export { CredentialForm };
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/ErrorBoundary.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/ErrorBoundary.js
new file mode 100644
index 00000000..b66f2abd
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/ErrorBoundary.js
@@ -0,0 +1,33 @@
+import React, { Component } from 'react';
+import { IllustratedMessage } from './IllustratedMessage';
+
+class ErrorBoundary extends Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ hasError: false,
+ error: null,
+ errorInfo: null,
+ errorMsg: this.props.errorMessage
+ };
+ }
+
+ componentDidCatch(error, errorInfo) {
+ this.setState({
+ hasError: true,
+ error: error,
+ errorInfo: errorInfo,
+ });
+ }
+
+ render() {
+ if (this.state.hasError) {
+ return ;
+ }
+
+ return this.props.children;
+ }
+}
+
+export default ErrorBoundary;
+
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/Form/AdobeDeveloperConsole.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/Form/AdobeDeveloperConsole.js
new file mode 100644
index 00000000..b4005617
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/Form/AdobeDeveloperConsole.js
@@ -0,0 +1,23 @@
+import React from 'react';
+import { css } from "@emotion/react";
+
+const AdobeDeveloperConsole = ({ formData, handleChange, adobeDeveloperConsole }) => {
+ return (
+
+ )
+}
+
+export { AdobeDeveloperConsole };
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/Form/AllowedOrigins.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/Form/AllowedOrigins.js
new file mode 100644
index 00000000..60aa8251
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/Form/AllowedOrigins.js
@@ -0,0 +1,45 @@
+import React from 'react';
+import { css } from "@emotion/react";
+import { FormFields } from '../FormFields';
+
+const AllowedOrigins = ({ originsProps, isFormValue, type, formData, handleChange, isAllowedOriginsValid }) => {
+
+ const isRed = isAllowedOriginsValid!==undefined ? !isAllowedOriginsValid : false;
+
+ return (
+
+
+
+ )
+}
+
+export { AllowedOrigins };
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/Form/CreateCredential.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/Form/CreateCredential.js
new file mode 100644
index 00000000..3b38120a
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/Form/CreateCredential.js
@@ -0,0 +1,24 @@
+import React from 'react';
+import { css } from "@emotion/react";
+
+const CreateCredential = ({ createCredential, isValid, setIsCreateNewCredential, isCreateNewCredential }) => {
+ return (
+
+
+ Create credential
+
+ {isCreateNewCredential &&
setIsCreateNewCredential(false)} data-cy="cancel-new-credential">Cancel
}
+
+ )
+}
+
+export { CreateCredential };
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/Form/CredentialName.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/Form/CredentialName.js
new file mode 100644
index 00000000..eafbb7a2
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/Form/CredentialName.js
@@ -0,0 +1,42 @@
+import React from 'react';
+import { css } from "@emotion/react";
+import { FormFields } from "../FormFields";
+import { AlertIcon } from '../Icons';
+
+const CredentialName = ({ nameProps, isFormValue, formData, handleChange }) => {
+
+ const credentialNameRegex = /^(?=[A-Za-z0-9\s]{6,}$)[A-Za-z0-9\s]*$/;
+ const inValidName = !credentialNameRegex.test(formData['CredentialName'])
+ const isRed = formData["CredentialName"]?.length !== 0 && inValidName;
+ return (
+
+
+
handleChange(e, "CredentialName")}
+ placeholder={nameProps?.placeholder}
+ maxLength={nameProps?.range}
+ data-cy="add-credential-name"
+ />
+
+
+
+ )
+}
+
+export { CredentialName }
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/Form/Download.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/Form/Download.js
new file mode 100644
index 00000000..c36d5259
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/Form/Download.js
@@ -0,0 +1,52 @@
+import React, { useState } from 'react';
+import { css } from "@emotion/react";
+import { FormFields } from "../FormFields";
+import { Picker } from '@adobe/gatsby-theme-aio/src/components/Picker';
+
+const Download = ({ downloadProp, isFormValue, handleChange }) => {
+ const [selectedIndex, setSelectedIndex] = useState(0);
+
+ return (
+ <>
+ {
+ downloadProp?.selectOptions?.length > 1 &&
+
+ div{
+ position: relative;
+ }
+
+ & >div> button{
+ width: 100%;
+ }
+
+ & >div> div{
+ width: 100%;
+ }
+ `}>
+
{
+ return {
+ title: option?.title,
+ selected: index === selectedIndex,
+ };
+ })}
+ onChange={index => {
+ setSelectedIndex(index);
+ handleChange(downloadProp?.selectOptions[index], "Download");
+ }}
+ data-cy="select-download-language"
+ id="selectBox"
+ />
+
+
+ }
+ >
+
+ )
+}
+
+export { Download };
\ No newline at end of file
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/Form/Downloads.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/Form/Downloads.js
new file mode 100644
index 00000000..13b511de
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/Form/Downloads.js
@@ -0,0 +1,20 @@
+import React from 'react';
+import { css } from "@emotion/react";
+import { ContextHelp } from "../ContextHelp";
+
+const Downloads = ({ downloadsProp, handleChange, formData }) => {
+
+ const { label, contextHelpLabelForLink, contextHelpLink, contextHelpText, contextHelp, contextHelpHeading } = downloadsProp;
+
+ return (
+
+
handleChange(e, "Downloads")} checked={formData['Downloads']} data-cy="download-checkBox" />
+
{label}
+
+ {contextHelp && }
+
+
+ )
+}
+
+export { Downloads };
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/Form/SideContent.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/Form/SideContent.js
new file mode 100644
index 00000000..6b5f102e
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/Form/SideContent.js
@@ -0,0 +1,34 @@
+import React from 'react';
+import { css } from "@emotion/react";
+import { MAX_TABLET_SCREEN_WIDTH, MIN_MOBILE_WIDTH } from '../FormFields';
+
+const SideContent = ({ sideContent, SideComp }) => {
+ return (
+ <>
+
+
+
+
+ >
+ )
+}
+
+export { SideContent };
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/FormFields.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/FormFields.js
new file mode 100644
index 00000000..8ee08077
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/FormFields.js
@@ -0,0 +1,128 @@
+import React from 'react';
+import { ContextHelp } from './ContextHelp';
+import { css } from "@emotion/react";
+import classNames from "classnames";
+
+export const FormFields = ({ isFormValue, fields, children, formData, isRed }) => {
+
+ const { label, range, contextHelpLabelForLink, contextHelpLink, contextHelpText, contextHelp, contextHelpHeading, description, className, required } = fields;
+
+ return (
+
+
+
+ {label &&
+ {label}
+ }
+ {required &&
* }
+ {isFormValue?.length ?
+
div > div > div > button {
+ border: none;
+ margin-left: 4px;
+ }
+ `} >
+ {contextHelp && }
+
: null
+ }
+
+ {range &&
+ {formData['CredentialName'] ? range - formData['CredentialName']?.length : range}
+ }
+
+
+ {children}
+
+ {description &&
+ }
+
+ )
+}
+
+export const MIN_MOBILE_WIDTH = "320px";
+export const MAX_MOBILE_WIDTH = "767px";
+export const MAX_TABLET_SCREEN_WIDTH = "1024px";
+export const MIN_TABLET_SCREEB_WIDTH = "768px";
+
+const domainPattern = /^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]$|localhost$/;
+
+export const handleAllowedDomainsValidation = (value) => {
+ const domains = value && value.split(',');
+ let errors = [];
+ if (value && value !== '') {
+ if (domains.length > 5) {
+ errors.push('A maximum of 5 domains are allowed');
+ }
+ domains.forEach((domain) => {
+ let domainToCheck = domain.trim();
+ if (domainToCheck.startsWith('*.')) {
+ domainToCheck = domainToCheck.substring(2);
+ }
+ if (!validateDomain(domainToCheck)) {
+ errors.push(`Domain ${domain} is invalid`);
+ }
+ });
+
+ if (errors.length) {
+ return false
+ }
+ else {
+ return true
+ }
+ }
+}
+
+const validateDomain = (domainToCheck) => {
+ if (domainToCheck.includes(':')) {
+ const domainsSplit = domainToCheck.split(':');
+ if (domainsSplit.length !== 2) {
+ return false;
+ }
+
+ // port is only allowed for localhost
+ if (domainsSplit[0] !== 'localhost') {
+ return false;
+ }
+
+ try {
+ const port = parseInt(domainsSplit[1]);
+ if (!port || port < 1024 || port > 65535) {
+ return false;
+ }
+ } catch (e) {
+ return false;
+ }
+
+ domainToCheck = domainsSplit[0];
+ }
+ return domainPattern.test(domainToCheck);
+}
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/GetCredentialContext.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/GetCredentialContext.js
new file mode 100644
index 00000000..a8aad72a
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/GetCredentialContext.js
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2020 Adobe. All rights reserved.
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License. You may obtain a copy
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
+ * OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ */
+
+import { createContext } from 'react';
+
+const GetCredentialContext = createContext({});
+
+export {GetCredentialContext as default};
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/Icons.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/Icons.js
new file mode 100644
index 00000000..c5a846d6
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/Icons.js
@@ -0,0 +1,83 @@
+import React from "react";
+
+export const CopyIcon = () => {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+};
+
+export const LinkOut = () => {
+ return (
+
+
+
+
+ )
+};
+
+export const KeyIcon = () => {
+ return (
+
+
+
+ )
+}
+
+
+export const AlertIcon = () => {
+ return (
+
+
+
+
+ )
+}
+
+export const ArrowDown = () => {
+ return (
+
+
+
+ )
+}
+
+export const ArrowRight = () => {
+ return (
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/IllustratedMessage.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/IllustratedMessage.js
new file mode 100644
index 00000000..4437c55d
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/IllustratedMessage.js
@@ -0,0 +1,49 @@
+import React from 'react';
+import { css } from "@emotion/react";
+import classNames from "classnames";
+
+const UnKnownErrorImage = () => {
+ return (
+
+
+
+ )
+}
+
+const IllustratedMessage = ({ errorMessage }) => {
+
+ return (
+
+
+
UnKnown Error
+ {
+ <>
+
An error has occured when you tried to create a new credential.
+
Please try to submit the form again.
+
window.location.reload()}>
+ Try Again
+
+
{errorMessage?.helpLinkText}
+ >
+ }
+
+ )
+}
+
+export { IllustratedMessage , UnKnownErrorImage }
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/JoinBetaProgram.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/JoinBetaProgram.js
new file mode 100644
index 00000000..f60d463e
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/JoinBetaProgram.js
@@ -0,0 +1,43 @@
+import React from 'react';
+import { css } from "@emotion/react";
+import classNames from "classnames";
+import { MAX_TABLET_SCREEN_WIDTH, MIN_MOBILE_WIDTH } from './FormFields';
+
+const JoinBetaProgram = ({ joinBeta }) => {
+
+ return (
+
+ )
+}
+
+export { JoinBetaProgram };
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/Loading.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/Loading.js
new file mode 100644
index 00000000..5871e3f2
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/Loading.js
@@ -0,0 +1,65 @@
+import React, { useEffect, useRef } from 'react';
+import { css } from "@emotion/react";
+import { ProgressCircle } from '@adobe/gatsby-theme-aio/src/components/ProgressCircle';
+
+const Loading = ({
+ credentials,
+ downloadStatus,
+ isCreateCredential,
+ initialLoading
+}) => {
+ const divRef = useRef(null);
+ useEffect(() => {
+ if (divRef.current) {
+ divRef.current.scrollIntoView({
+ behavior: 'smooth',
+ block: 'center',
+ inline: 'center',
+ });
+ }
+ }, [])
+
+ return (
+ <>
+ {credentials?.title && {credentials?.title} }
+
+
+ {initialLoading &&
+
+ {"Loading..."}
+
}
+
+ {isCreateCredential && "Creating credentials..."}
+
+ {downloadStatus &&
+
This process may take a few moments. Once complete, your download will start.
+ }
+
+ >
+ )
+}
+
+export { Loading };
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/MyCredential.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/MyCredential.js
new file mode 100644
index 00000000..7d550dce
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/MyCredential.js
@@ -0,0 +1,304 @@
+import React, { useContext, useEffect, useState } from 'react';
+import { css } from '@emotion/react';
+import classNames from 'classnames';
+import JSZip from 'jszip';
+import JSZipUtils from 'jszip-utils';
+import { saveAs } from 'file-saver';
+import { MAX_TABLET_SCREEN_WIDTH, MIN_MOBILE_WIDTH } from './FormFields';
+import { Toast } from '@adobe/gatsby-theme-aio/src/components/Toast';
+import { CardProducts } from './Products';
+import { SideComponent } from './SideComponent';
+import { AccessToken } from './Card/AccessToken';
+import { DevConsoleLink } from './Card/DevConsoleLink';
+import { CardClientDetails } from './Card/CardClientDetails';
+import { SideContent } from './Form/SideContent';
+import GetCredentialContext from './GetCredentialContext';
+import { CredentialDetailsCard } from './CredentialDetailsCard';
+
+const MyCredential = ({
+ formData,
+ response,
+ handleRestart
+}) => {
+ const { getCredentialData, selectedOrganization: organizationName } = useContext(GetCredentialContext);
+ const credentialProps = getCredentialData;
+
+ const [isDownloadStart, setIsDownloadStart] = useState();
+ const [isCopiedTooltip, setCopiedTooltip] = useState('');
+
+ const myCredentialFields = {};
+ const productsObj = { label: 'products', productList: [] };
+
+ credentialProps?.[MyCredential]?.children.forEach(({ type, props }) => {
+ myCredentialFields[type] = props;
+ if (props.children && type === CardClientDetails) {
+ myCredentialFields[type] = props;
+ props?.children?.forEach(({ type, props }) => {
+ myCredentialFields[type] = props;
+ });
+ }
+ if (type === CardProducts && props?.children) {
+ productsObj.productList.push(
+ ...[].concat(props.children).map(({ props: { label, icon } }) => ({ label, icon }))
+ );
+ }
+ });
+ const product = productsObj?.productList;
+
+ useEffect(() => {
+ if (formData['Downloads']) {
+ downloadZIP(
+ `/console/api/organizations/${organizationName?.id}/projects/${response.projectId}/workspaces/${response.workspaceId}/download`,
+ formData['Download'],
+ formData['zipUrl']
+ );
+ }
+ }, []);
+
+ const card = credentialProps?.[MyCredential];
+
+ const downloadZIP = async (downloadAPI, fileName = 'download', zipFileURL) => {
+ setIsDownloadStart(true);
+ try {
+ const zipData = await JSZipUtils.getBinaryContent(zipFileURL);
+ const zipArrayBuffer = new Uint8Array(zipData).buffer;
+ const zip = new JSZip();
+
+ await zip.loadAsync(zipArrayBuffer);
+
+ const token = window.adobeIMS?.getTokenFromStorage()?.token;
+ const options = {
+ method: 'GET',
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: 'Bearer ' + token,
+ 'x-api-key': window?.adobeIMS?.adobeIdData?.client_id,
+ },
+ };
+
+ const response = await fetch(downloadAPI, options);
+
+ if (response.status === 200) {
+ const credential = await response.json();
+
+ zip.file('credential.json', JSON.stringify(credential));
+
+ const modifiedZipBlob = await zip.generateAsync({ type: 'blob' });
+ saveAs(modifiedZipBlob, `${fileName}.zip`);
+ } else {
+ console.error('Failed to fetch additional data. Response status:', response.status);
+ }
+ } catch (error) {
+ console.error('An error occurred:', error);
+ } finally {
+ setIsDownloadStart(false);
+ }
+ };
+
+ return (
+
+
+
+ {card?.title && (
+
+ {card?.title}
+
+ )}
+ {isDownloadStart && (
+
+ )}
+
+ {formData['Downloads'] && card?.paragraph && (
+
+ {card?.paragraph}
+
+ )}
+ {formData['Downloads'] && (
+
+ Download not working?
+
+ downloadZIP(
+ `/console/api/organizations/${organizationName?.id}/projects/${response.projectId}/workspaces/${response.workspaceId}/download`,
+ formData['Download'],
+ formData['zipUrl']
+ )
+ }
+ data-cy="restart-download">
+ Restart download
+
+
+ )}
+
+
+
+
+
+
+ Need another credential
+
+
+
+ Restart and create a new credential
+
+
+
+
+ {card?.children ? (
+
+ ) : null}
+
+ {isCopiedTooltip && (
+
+ )}
+
+ );
+};
+
+export { MyCredential };
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/Organization.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/Organization.js
new file mode 100644
index 00000000..1d82d63c
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/Organization.js
@@ -0,0 +1,221 @@
+import React, { useContext, useEffect, useState } from 'react';
+import { css } from '@emotion/react';
+import '@spectrum-css/contextualhelp/dist/index-vars.css';
+import { Picker } from '@adobe/gatsby-theme-aio/src/components/Picker';
+import GetCredentialContext from './GetCredentialContext';
+
+const Organization = () => {
+
+ const { allOrganizations, switchOrganization, selectedOrganization } = useContext(GetCredentialContext);
+
+ const [selectedIndex, setSelectedIndex] = useState(allOrganizations.findIndex(org => org.id === selectedOrganization.id));
+ const [isOpenDialog, setIsOpenDialog] = useState(false);
+
+ useEffect(() => {
+ const underlay = document.querySelector('[data-testid="underlay"]');
+ if (underlay) {
+ document.body.style.overflow = 'hidden';
+ }
+ return () => {
+ document.body.style.overflow = '';
+ };
+ }, [isOpenDialog]);
+
+ const close = () => {
+ setIsOpenDialog(false)
+ }
+
+ return (
+ <>
+ setIsOpenDialog(true)}>Change organization
+ {isOpenDialog &&
+
+
+
+
+
+
+
Change organization
+
+
+
+
+
+ You are currently in [
+
+ {allOrganizations[selectedIndex].name}
+
+ ].
+
+
+
+
+ Choose organization
+
+
+ *
+
+
+
div > button {
+ width: 100%;
+ border-radius: 4px;
+ }
+
+ & > div > button > svg {
+ width: 10px;
+ height: 10px;
+ }
+
+ & > div > button {
+ path:nth-child(1) {
+ display: none;
+ }
+ }
+
+ & > div > div {
+ width: 246px;
+ max-height: 98px;
+
+ ul:nth-child(1) {
+ svg:nth-child(1) {
+ width: 10px;
+ height: 10px;
+ margin-top: 7px;
+
+ path:nth-child(1) {
+ display: none;
+ }
+ }
+ }
+ }
+
+ & > div > div > ul {
+ overflow-x: hidden !important;
+ overflow-y: scroll !important;
+ }
+
+ & > div > div > ul > li {
+ padding : 0 !important;
+ }
+
+ & > div > div > ul > li > div > div {
+ height: 20px !important;
+ }
+
+ & > div > div > ul > li > span > div > p {
+ white-space: normal;
+ overflow: visible;
+ word-wrap: break-word;
+ width: 185px;
+ }
+ `}>
+
{
+ return {
+ title: organization?.name,
+ selected: k === selectedIndex,
+ type: organization?.role === "DEVELOPER" ? 'Developer' : organization?.role === "ADMIN" ? 'System Administrator' : ""
+ };
+ })}
+ onChange={index => {
+ setSelectedIndex(index);
+ }}
+ data-cy="organization-picker"
+ />
+
+
+
+
div {
+ display: flex;
+ justify-content: right;
+ gap: 12px;
+ button {
+ cursor: pointer;
+ margin: 0px !important;
+ }
+ }
+ `}>
+
+
+
+
+ Cancel
+
+
+ {
+ close();
+ switchOrganization(allOrganizations[selectedIndex]);
+ }}>
+ Change organization
+
+
+
+
+
+
+
+
+
+
+
+
+ }
+ >
+ );
+};
+
+export { Organization };
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/PreviousCredential.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/PreviousCredential.js
new file mode 100644
index 00000000..48ff3e7d
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/PreviousCredential.js
@@ -0,0 +1,156 @@
+import React, { useContext, useState } from 'react';
+import { css } from '@emotion/react';
+import '@spectrum-css/contextualhelp/dist/index-vars.css';
+import classNames from 'classnames';
+import { MAX_TABLET_SCREEN_WIDTH, MIN_MOBILE_WIDTH } from './FormFields';
+import { PreviousProject } from './PreviousProject';
+import { Organization } from './Organization';
+import { CredentialForm } from './CredentialForm';
+import { ReturnSideComp } from './Return/ReturnSideComp';
+import { CardProducts } from './Products';
+import { ReturnCustomComp } from './Return/ReturnCustomComp';
+import { ReturnNewCredential } from './Return/ReturnNewCredential';
+import GetCredentialContext from './GetCredentialContext';
+import { ReturnCredentialDetails } from './Return/ReturnCredentialDetails';
+
+const PreviousCredential = ({ setIsCreateNewCredential }) => {
+ const { getCredentialData } = useContext(GetCredentialContext);
+ const returnProps = getCredentialData;
+
+ const [isShow, setIsShow] = useState(false);
+ const credentialHeader = returnProps[CredentialForm];
+ const { selectedOrganization } = useContext(GetCredentialContext);
+
+ const returnFields = {};
+ const productList = [];
+
+ returnProps?.[PreviousProject]?.children.forEach(({ type, props }) => {
+ returnFields[type] = props;
+
+ if (props?.children) {
+
+ const children = Array.isArray(props.children) ? props.children : [props.children];
+
+ children.forEach(({ props: childProps, type: childType }) => {
+ if (type === ReturnSideComp || type === ReturnCredentialDetails) {
+ returnFields[childType] = childProps;
+ } else if (type === CardProducts) {
+ const { label, icon } = childProps;
+ productList.push({ label, icon });
+ }
+
+ });
+ }
+
+ });
+
+ const returnSideComp = returnFields?.[ReturnSideComp];
+ const returnCustomComp = returnFields?.[ReturnCustomComp];
+ const returnNewCredential = returnFields?.[ReturnNewCredential];
+
+ return (
+ <>
+
+
+
+ {credentialHeader?.title && (
+
+ {credentialHeader?.title}
+
+ )}
+ {credentialHeader?.paragraph && (
+
{credentialHeader?.paragraph}
+ )}
+
setIsShow(true)}
+ css={css`
+ color: var(--spectrum-global-color-gray-800);
+ display: inline-flex;
+ `}>
+ {selectedOrganization.type === "developer" ?
+ "You’re viewing in your personal developer organization" :
+ <>You’re viewing in [ {selectedOrganization?.name} ] .>}
+
+
+
+
+
+
+ {returnSideComp && (
+
+ )}
+
+
+
+
+
+
+ >
+ );
+};
+
+export { PreviousCredential };
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/PreviousProject.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/PreviousProject.js
new file mode 100644
index 00000000..291fe73c
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/PreviousProject.js
@@ -0,0 +1,76 @@
+import React, { useContext, useState } from 'react';
+import { css } from '@emotion/react';
+import '@spectrum-css/contextualhelp/dist/index-vars.css';
+import { Toast } from '@adobe/gatsby-theme-aio/src/components/Toast';
+import classNames from 'classnames';
+import { ReturnAccessToken } from './Return/ReturnAccessToken';
+import { ProjectsDropdown } from './Return/ProjectsDropdown';
+import { ReturnDevConsoleLink } from './Return/ReturnDevConsoleLink';
+import { ReturnManageDeveloperConsole } from './Return/ReturnManageDeveloperConsole';
+import { ReturnCredentialDetails } from './Return/ReturnCredentialDetails';
+import { CardProducts } from './Products';
+import GetCredentialContext from './GetCredentialContext';
+import { CredentialDetailsCard } from './CredentialDetailsCard';
+
+const PreviousProject = ({ returnFields, productList, collapse }) => {
+
+ const { getCredentialData: returnProps, selectedOrganization, previousProjectDetail } = useContext(GetCredentialContext);
+
+ const [selectedIndex, setSelectedIndex] = useState(0);
+ const [isCopiedTooltip, setCopiedTooltip] = useState('');
+
+ const previousProjectsDetails = previousProjectDetail?.projects
+ const previousProject = returnProps?.[PreviousProject];
+ const projectsDropdown = returnFields?.[ProjectsDropdown];
+ const returnManageDeveloperConsole = returnFields?.[ReturnManageDeveloperConsole];
+ const response = previousProjectsDetails?.[selectedIndex];
+ const projectDetails = previousProjectsDetails?.[selectedIndex];
+ const manageProps = returnProps[PreviousProject];
+
+ const allowedDomains = projectDetails?.workspaces[0]?.credentials[0]?.metadata?.["adobeid.domain"];
+
+ return (
+ <>
+
+ {previousProject?.title &&
{previousProject?.title} }
+
+ {previousProject?.paragraph &&
{previousProject?.paragraph}
}
+
+ {returnManageDeveloperConsole &&
}
+
+ {projectsDropdown &&
}
+
+ {/* ----------- credential form ------------ */}
+
+
+
+
+ {isCopiedTooltip && }
+ >
+
+ )
+};
+
+export { PreviousProject };
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/Products.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/Products.js
new file mode 100644
index 00000000..6b2af567
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/Products.js
@@ -0,0 +1,241 @@
+import React, { useRef, useState, useEffect } from 'react';
+import { css } from '@emotion/react';
+import { ActionButton } from "@adobe/gatsby-theme-aio/src/components/ActionButton"
+
+const Products = ({ products, product }) => {
+ return (
+
+
+ {products?.label && (
+
+ {products?.label}{' '}
+
+ )}
+
+
+
+ );
+};
+
+const Product = ({ productList }) => {
+ return ;
+};
+
+const CardProduct = ({ productList }) => {
+ return (
+ <>
+ {productList?.map((product, index) => {
+ if (index < 2)
+ return (
+
+ {product?.icon ? (
+
+
+
+
+
{product?.label}
+
+ ) : (
+
{product?.label}
+ )}
+
+ );
+ })}
+ >
+ );
+};
+
+const CardProducts = ({ productList }) => {
+
+ return (
+
+
+
+
+ );
+};
+
+const CommonProduct = ({ productList }) => {
+
+ return (
+ <>
+ {productList &&
+ productList?.map((data, index) => {
+ if (index < 2)
+ return (
+
+
+
+ {data?.label}
+
+
+ );
+ })}
+
+ {productList?.length > 2 && (
+
+ )}
+ >
+ );
+};
+
+const ModelTrigger = ({ productList }) => {
+
+ const [isVisible, setisVisible] = useState(false);
+ const buttonRef = useRef();
+
+ const handleClickOutside = e => {
+ if (buttonRef?.current?.contains(e.target)) setisVisible(!isVisible);
+ else setisVisible(false);
+ };
+
+ useEffect(() => {
+ document.addEventListener('click', handleClickOutside);
+ return () => document.removeEventListener('click', handleClickOutside);
+ });
+
+ return (
+ <>
+ button, & > button : active {
+ border: none;
+ background: transparent !important;
+ }
+ `}>
+
+ {productList.length - 2 > 0 && (
+
+ +{productList.length - 2} more
+
+ )}
+
+ {isVisible &&
}
+
+ >
+ )
+}
+
+export { Product, Products, CardProducts, CardProduct };
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/RequestAccess/OrganizationAccessDetails.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/RequestAccess/OrganizationAccessDetails.js
new file mode 100644
index 00000000..ebed8a69
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/RequestAccess/OrganizationAccessDetails.js
@@ -0,0 +1,165 @@
+import React, { useContext, useEffect, useRef, useState } from 'react';
+import '@spectrum-css/contextualhelp/dist/index-vars.css';
+import { css } from '@emotion/react';
+import { Button } from "@adobe/gatsby-theme-aio/src/components/Button";
+import { RequestAccessModal } from './RequestAccessModal';
+import GetCredentialContext from '../GetCredentialContext';
+import { Organization } from '../Organization';
+import { Products } from '../Products';
+
+const OrganizationAccessDetails = ({ restrictedAccess, products }) => {
+
+ const { template, selectedOrganization } = useContext(GetCredentialContext);
+ const [isOpen, setIsOpen] = useState(false);
+
+ let productList = [];
+
+ if (Array.isArray(products?.children)) {
+ productList = products?.children.map((child) => (child?.props))
+ } else {
+ productList.push(products?.children?.props);
+ }
+
+ let product = { productList };
+
+ const handleClose = () => {
+ setIsOpen(!isOpen)
+ }
+
+ const [isVisible, setisVisible] = useState(false);
+ const buttonRef = useRef();
+
+ const handleClickOutside = e => {
+ if (buttonRef?.current?.contains(e.target)) setisVisible(!isVisible);
+ else setisVisible(false);
+ };
+
+ useEffect(() => {
+ document.addEventListener('click', handleClickOutside);
+ return () => document.removeEventListener('click', handleClickOutside);
+ });
+
+ return (
+ <>
+
+ {restrictedAccess?.title && (
+
{restrictedAccess?.title}
+ )}
+
+ You’re creating this credential in {' '}
+ {selectedOrganization.type === "developer" ?
+ "your personal developer organization" :
+ <>
+ [
+
+ {selectedOrganization.name}
+
+ ]
+ >} but you do not have a developer access in this organization and need admin approval to
+ use this API.
+ span {
+ color: #000000;
+ }
+
+ &>span: hover {
+ color: #000000;
+ }
+
+ & > div {
+ display: inline;
+ }
+
+ span {
+ padding: 0px 0px 0px 3px !important;
+ }
+ `}>
+
+
+
+ {products &&
}
+ {restrictedAccess?.buttonLabel && (
+ template.requestAccessAppId &&
+
+
+ {!template.isRequestPending ?
{restrictedAccess?.buttonLabel}
:
+
+
Request Pending
+
button {
+ border: none;
+ padding: 4px !important;
+ border-radius: 2px !important;
+ }
+ `}
+ >
+
+
+
+
+
+
+
+
Your request is pending approval
+
You'll hear back from your admin soon. If your request is approved, you'll get an email with instructions on how to start using your apps and service
+ Learn more about requesting Adobe apps.
+
+
+
+
+ }
+
+ {isOpen &&
}
+
+
+ )}
+
+ >
+ );
+};
+
+export { OrganizationAccessDetails };
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/RequestAccess/OrganizationAccessDetailsEdgeCase.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/RequestAccess/OrganizationAccessDetailsEdgeCase.js
new file mode 100644
index 00000000..275c2093
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/RequestAccess/OrganizationAccessDetailsEdgeCase.js
@@ -0,0 +1,131 @@
+import React, { useContext, useEffect, useState } from 'react';
+import { css } from '@emotion/react';
+import { Button } from "@adobe/gatsby-theme-aio/src/components/Button";
+import { Organization } from '../Organization';
+
+import GetCredentialContext from '../GetCredentialContext';
+import Context from '@adobe/gatsby-theme-aio/src/components/Context';
+
+const OrganizationAccessDetailsEdgeCase = ({ content, isNoProduct, productName }) => {
+ const { selectedOrganization } = useContext(GetCredentialContext);
+ const { ims } = useContext(Context);
+
+ const [emailID, setEmailID] = useState('');
+ useEffect(() => {
+ (async () => {
+ if (ims && ims.isSignedInUser()) {
+ const profile = await ims.getProfile();
+ setEmailID(profile?.email);
+ }
+ })();
+ }, [ims]);
+
+ return (
+ <>
+
+ {content?.title &&
+
+ {content?.title}
+ }
+ {isNoProduct ?
+
+ You are currently signed in with [
+ {emailID} ]
+ in {" "}
+ {selectedOrganization.type === "developer" ?
+ "your personal developer organization" :
+ <>organization [
+
+ {selectedOrganization.name}
+
+ ]
+ >}
+ currently does not have access to these APIs Contact us to learn more about {productName} APIs and how to get a free trial.
+ span, &>span: hover {
+ color: #000000;
+ }
+
+ & > div {
+ display: inline;
+ }
+
+ span {
+ padding: 0px 0px 0px 3px !important;
+ }
+ `}>
+
+
+
+ :
+
+ You are currently signed in with [
+ {emailID} ]
+ in {" "}
+ {selectedOrganization.type === "developer" ?
+ "your personal developer organization" :
+ <> organization [
+ {selectedOrganization.name} ]
+ >}
+ and can not access {productName} APIs.
+ span, &>span: hover {
+ color: #000000;
+ }
+
+ & > div {
+ display: inline;
+ }
+
+ span {
+ padding: 0px 0px 0px 3px !important;
+ }
+ `}>
+
+
+
+ }
+
+
+ >
+ );
+};
+
+export { OrganizationAccessDetailsEdgeCase };
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/RequestAccess/OrganizationAccessDetailsNoProduct.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/RequestAccess/OrganizationAccessDetailsNoProduct.js
new file mode 100644
index 00000000..ff032935
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/RequestAccess/OrganizationAccessDetailsNoProduct.js
@@ -0,0 +1,13 @@
+import React from "react";
+import { OrganizationAccessDetailsEdgeCase } from "./OrganizationAccessDetailsEdgeCase";
+
+const OrganizationAccessDetailsNoProduct = ({ content, productName }) => {
+
+ return (
+ <>
+
+ >
+ );
+};
+
+export { OrganizationAccessDetailsNoProduct };
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/RequestAccess/OrganizationAccessDetailsNotMember.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/RequestAccess/OrganizationAccessDetailsNotMember.js
new file mode 100644
index 00000000..46831b8d
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/RequestAccess/OrganizationAccessDetailsNotMember.js
@@ -0,0 +1,13 @@
+import React from 'react';
+import { OrganizationAccessDetailsEdgeCase } from './OrganizationAccessDetailsEdgeCase';
+
+const OrganizationAccessDetailsNotMember = ({content , productName}) => {
+
+ return (
+ <>
+
+ >
+ );
+};
+
+export { OrganizationAccessDetailsNotMember };
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/RequestAccess/OrganizationAccessDetailsNotSignUp.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/RequestAccess/OrganizationAccessDetailsNotSignUp.js
new file mode 100644
index 00000000..9d0df0cd
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/RequestAccess/OrganizationAccessDetailsNotSignUp.js
@@ -0,0 +1,12 @@
+import React from 'react';
+import { OrganizationAccessDetailsEdgeCase } from './OrganizationAccessDetailsEdgeCase';
+
+const OrganizationAccessDetailsNotSignUp = ({ content, productName }) => {
+ return (
+ <>
+
+ >
+ );
+};
+
+export { OrganizationAccessDetailsNotSignUp };
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/RequestAccess/OrganizationAccessDetailsType1User.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/RequestAccess/OrganizationAccessDetailsType1User.js
new file mode 100644
index 00000000..b614a83a
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/RequestAccess/OrganizationAccessDetailsType1User.js
@@ -0,0 +1,12 @@
+import React from 'react';
+import { OrganizationAccessDetailsEdgeCase } from './OrganizationAccessDetailsEdgeCase';
+
+const OrganizationAccessDetailsType1User = ({content,productName}) => {
+ return (
+ <>
+
+ >
+ );
+};
+
+export { OrganizationAccessDetailsType1User };
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/RequestAccess/RequestAccess.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/RequestAccess/RequestAccess.js
new file mode 100644
index 00000000..6c316bc3
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/RequestAccess/RequestAccess.js
@@ -0,0 +1,77 @@
+import React, { useContext } from 'react';
+import { RestrictedAccess } from './RestrictedAccessFields';
+import { css } from '@emotion/react';
+import { MAX_MOBILE_WIDTH } from '../FormFields';
+import '@spectrum-css/contextualhelp/dist/index-vars.css';
+import { RequestAccessSide } from './RequestAccessSide';
+import GetCredentialContext from '../GetCredentialContext';
+import { OrganizationAccessDetailsEdgeCase } from './OrganizationAccessDetailsEdgeCase';
+
+const RequestAccess = ({ productName }) => {
+ const { getCredentialData } = useContext(GetCredentialContext);
+
+ const requestAccess = getCredentialData?.[RequestAccess];
+ let side, restrictedAccess, organizationAccessDetailsEdgeCase;
+
+ if (Array.isArray(requestAccess?.children)) {
+ requestAccess?.children?.forEach(({ type, props }) => {
+ if (type === RequestAccessSide) {
+ side = props?.children;
+ }
+ if (type === RestrictedAccess) {
+ restrictedAccess = props;
+ }
+ if (type === OrganizationAccessDetailsEdgeCase) {
+ organizationAccessDetailsEdgeCase = props;
+ }
+ });
+ } else {
+ restrictedAccess = requestAccess?.children?.props;
+ }
+
+ return (
+ <>
+
+
+ {requestAccess?.title && (
+
{requestAccess?.title}
+ )}
+ {requestAccess?.paragraph && (
+
+ {requestAccess?.paragraph}
+
+ )}
+
+
+ {restrictedAccess && }
+ {side && }
+
+
+ >
+ );
+};
+
+export { RequestAccess };
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/RequestAccess/RequestAccessModal.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/RequestAccess/RequestAccessModal.js
new file mode 100644
index 00000000..bb394ef3
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/RequestAccess/RequestAccessModal.js
@@ -0,0 +1,139 @@
+import React, { useCallback, useContext, useEffect, useState } from "react";
+import "@spectrum-css/contextualhelp/dist/index-vars.css";
+import { ProgressCircle } from "@adobe/gatsby-theme-aio/src/components/ProgressCircle";
+import GetCredentialContext from "../GetCredentialContext";
+import { css } from '@emotion/react';
+
+const INITIAL_IFRAME_HEIGHT = 420;
+
+const RequestAccessModal = ({ accessPlatformAppId, close }) => {
+ const [targetUrl, setTargetUrl] = useState('');
+ const [loading, setLoading] = useState(true);
+ const [iframeHeight, setIframeHeight] = useState(INITIAL_IFRAME_HEIGHT);
+ const { setTemplate, template, selectedOrganization } = useContext(GetCredentialContext);
+
+ useEffect(() => {
+ const setTargetUrlHelper = async () => {
+ const { userId } = await window.adobeIMS.getProfile();
+ const acrsHostPrefix = window.adobeIMS.adobeIdData.environment === 'prod' ? '' : 'stage.';
+ setTargetUrl(`https://${acrsHostPrefix}acrs.adobe.com/requestAccess?flow=frame&colorScheme=light&applicationId=UDPWeb1&appId=${accessPlatformAppId}&userId=${userId}&accessRequestType=apiAccess`);
+ };
+ setTargetUrlHelper();
+ }, [setTargetUrl, accessPlatformAppId]);
+
+ const handleIframeMessage = useCallback(
+ (event) => {
+ if (!event.isTrusted || (typeof event.data !== 'string' && !(event.data instanceof String))) {
+ return;
+ }
+ const eventData = JSON.parse(event.data);
+
+ if (!eventData || eventData.app !== 'acrs-request-access' || eventData.type !== 'System') {
+ return;
+ }
+
+ switch (eventData.subType) {
+ case 'AppLoaded':
+ setLoading(false);
+ break;
+ case 'Resize':
+ setIframeHeight(eventData.data.height);
+ break;
+ case 'Close':
+ close(false);
+ fetchTemplate();
+ break;
+ }
+ },
+ [close, setLoading, setIframeHeight],
+ );
+
+ const fetchTemplate = async () => {
+ try {
+ const url = `/templates/${template.id}`
+ const response = await fetch(url, {
+ headers: {
+ "Content-Type": "application/json",
+ "Authorization": `Bearer ${window.adobeIMS.getTokenFromStorage().token}`,
+ "x-api-key": window.adobeIMS.adobeIdData.client_id,
+ "x-org-id": selectedOrganization.code
+ }
+ });
+
+ if (!response.ok) {
+ console.error('Template not found. Please check template id');
+ return;
+ }
+ setTemplate(await response.json());
+ }
+ catch (error) {
+ console.error('Error fetching template:', error);
+ }
+ }
+
+ useEffect(() => {
+ window.addEventListener('message', handleIframeMessage);
+ return () => window.removeEventListener('message', handleIframeMessage);
+ }, [handleIframeMessage]);
+
+ return (
+ .changeOrg {
+ border: none;
+ background: white;
+ padding: 0;
+ height: fit-content;
+ text-decoration: underline;
+ cursor: pointer;
+ }
+ `}>
+
+
+
+
+
+ {targetUrl ? (
+ <>
+
+ {loading && }
+ >
+ ) : (
+ 'Loading...'
+ )}
+
+
+
+
+
+ );
+};
+
+export { RequestAccessModal };
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/RequestAccess/RequestAccessSide.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/RequestAccess/RequestAccessSide.js
new file mode 100644
index 00000000..96fe675c
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/RequestAccess/RequestAccessSide.js
@@ -0,0 +1,19 @@
+import React from "react";
+import { css } from "@emotion/react";
+import "@spectrum-css/contextualhelp/dist/index-vars.css";
+
+const RequestAccessSide = ({ side }) => {
+ return (
+ <>
+
+ {side}
+ >
+ );
+};
+
+export { RequestAccessSide };
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/RequestAccess/RestrictedAccessFields.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/RequestAccess/RestrictedAccessFields.js
new file mode 100644
index 00000000..a1baadef
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/RequestAccess/RestrictedAccessFields.js
@@ -0,0 +1,67 @@
+import React, { useContext } from "react";
+import "@spectrum-css/contextualhelp/dist/index-vars.css";
+import { css } from "@emotion/react";
+import { InlineNestedAlert } from "@adobe/gatsby-theme-aio/src/components/InlineNestedAlert";
+import { OrganizationAccessDetails } from "./OrganizationAccessDetails";
+import { OrganizationAccessDetailsNoProduct } from "./OrganizationAccessDetailsNoProduct";
+import { OrganizationAccessDetailsType1User } from "./OrganizationAccessDetailsType1User";
+import { OrganizationAccessDetailsNotMember } from "./OrganizationAccessDetailsNotMember";
+import { OrganizationAccessDetailsNotSignUp } from "./OrganizationAccessDetailsNotSignUp";
+import GetCredentialContext from "../GetCredentialContext";
+
+const RestrictedAccess = ({ restrictedAccess, organizationAccessDetailsEdgeCase , productName}) => {
+ let products = restrictedAccess?.children?.props;
+ let childProps = {};
+ const { selectedOrganization, template } = useContext(GetCredentialContext);
+ let disEntitledReason = template?.disEntitledReasons[0];
+
+ if (Array.isArray(organizationAccessDetailsEdgeCase?.children)) {
+ organizationAccessDetailsEdgeCase?.children?.forEach(({ type, props }) => {
+ childProps[type] = props;
+ });
+ }
+
+ const render = () => {
+ if (selectedOrganization?.type === "developer" && childProps[OrganizationAccessDetailsType1User]) {
+ return
+ }
+ else if (disEntitledReason === "USER_MISSING_PUBLIC_BETA") {
+ return
+ }
+ else if (disEntitledReason === "ORG_MISSING_FIS") {
+ return
+ }
+ else if (template?.canRequestAccess) {
+ return
+ }
+ else {
+ return
+ }
+ };
+
+ return (
+ <>
+ div {
+ margin: 0px;
+ padding: 24px;
+ background: transparent;
+ }
+
+ & > div>svg {
+ margin-top: 5px;
+ }
+ `}
+ >
+
+ {render()}
+
+
+ >
+ );
+};
+
+export { RestrictedAccess };
\ No newline at end of file
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ProjectsDropdown.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ProjectsDropdown.js
new file mode 100644
index 00000000..9ab9a999
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ProjectsDropdown.js
@@ -0,0 +1,56 @@
+import React from 'react';
+import { css } from "@emotion/react";
+import { Picker } from "@adobe/gatsby-theme-aio/src/components/Picker";
+
+const ProjectsDropdown = ({ projectsDropdown, previousProjectsDetails, selectedIndex, setSelectedIndex }) => {
+
+ return (
+
+
+
{projectsDropdown?.label}
+
div{
+ position: relative;
+ }
+
+ & >div> button{
+ width: 100%;
+ }
+
+ & >div> div{
+ width: 100%;
+ }
+
+ & >div> div p{
+ margin-top: 2px;
+ }
+ ` }
+ >
+
{
+ return {
+ title: project.title,
+ selected: k === selectedIndex
+ }
+ })}
+ onChange={(index) => {
+ setSelectedIndex(index);
+ }}
+ data-cy="projects-picker"
+ />
+
+
{projectsDropdown?.subHeading}
+
+ )
+}
+
+export { ProjectsDropdown }
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnAPIKey.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnAPIKey.js
new file mode 100644
index 00000000..f1829243
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnAPIKey.js
@@ -0,0 +1,10 @@
+import React from 'react';
+import ShowCard from '../Card/ShowCard';
+
+const ReturnAPIKey = ({ returnCredentialDetails , returnAPIKey, apiKey }) => {
+ return (
+
+ )
+}
+
+export { ReturnAPIKey };
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnAccessToken.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnAccessToken.js
new file mode 100644
index 00000000..572c22c2
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnAccessToken.js
@@ -0,0 +1,8 @@
+import React from 'react';
+import { AccessToken } from '../Card/AccessToken';
+
+const ReturnAccessToken = ({ accessToken,response, scopesDetails }) => {
+ return
+}
+
+export { ReturnAccessToken }
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnAllowedOrigins.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnAllowedOrigins.js
new file mode 100644
index 00000000..dc53b5a4
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnAllowedOrigins.js
@@ -0,0 +1,10 @@
+import React from 'react';
+import ShowCard from '../Card/ShowCard';
+
+const ReturnAllowedOrigins = ({ returnAllowedOrigins, allowedOrigins }) => {
+ return (
+
+ )
+}
+
+export { ReturnAllowedOrigins };
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnClientId.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnClientId.js
new file mode 100644
index 00000000..edfd4c43
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnClientId.js
@@ -0,0 +1,9 @@
+import React from 'react'
+import ShowCard from '../Card/ShowCard';
+
+const ReturnClientId = ({ returnClientId, clientId }) => {
+ return (
+
+ )
+}
+export { ReturnClientId };
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnClientSecret.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnClientSecret.js
new file mode 100644
index 00000000..02b32bbe
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnClientSecret.js
@@ -0,0 +1,10 @@
+import React from 'react';
+import ShowCard from '../Card/ShowCard';
+
+const ReturnClientSecret = ({ returnClientSecret, response }) => {
+ return (
+
+ )
+}
+
+export { ReturnClientSecret };
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnCredentialDetails.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnCredentialDetails.js
new file mode 100644
index 00000000..5e9aa36f
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnCredentialDetails.js
@@ -0,0 +1,73 @@
+import React, { useContext } from 'react';
+import { css } from '@emotion/react';
+import { ReturnAPIKey } from './ReturnAPIKey';
+import { ReturnAllowedOrigins } from './ReturnAllowedOrigins';
+import { ReturnClientId } from './ReturnClientId';
+import { ReturnClientSecret } from './ReturnClientSecret';
+import { ReturnOrganizationName } from './ReturnOrganizationName';
+import { ReturnScopes } from './ReturnScopes';
+import GetCredentialContext from '../GetCredentialContext';
+import { CardImsOrgID } from '../Card/CardImsOrgID';
+
+const ReturnCredentialDetails = ({ clientDetails, clientIdDetails, clientSecretDetails, organizationDetails, scopesDetails, apiKeyDetails, allowedOriginsDetails, organizationName, allowedOrigins, response, imsOrgID }) => {
+
+ const { selectedOrganization } = useContext(GetCredentialContext);
+ console.log('clientDetails', clientDetails?.orderBy)
+
+ const splitedOrderBy = clientDetails?.orderBy ? clientDetails?.orderBy?.split(',') : [];
+ console.log('splitedOrderBy', splitedOrderBy)
+
+ console.log('splitedOrderBy?.length', splitedOrderBy?.length)
+
+return (
+
+
+
{clientDetails?.heading}
+ {
+ splitedOrderBy?.length > 0 ?
+ <>
+ {splitedOrderBy?.map((list) => {
+ if (list === "APIKey") {
+ return apiKeyDetails &&
+ }
+ if (list === "AllowedOrigins") {
+ return allowedOrigins &&
+ }
+ if (list === "ImsOrgID") {
+ return imsOrgID &&
+ }
+ if (list === "OrganizationName") {
+ return organizationDetails &&
+ }
+ if (list === "ClientId") {
+ return clientIdDetails &&
+ }
+ if (list === "ClientSecret") {
+ return clientSecretDetails &&
+ }
+ if (list === "Scopes") {
+ return scopesDetails &&
+ }
+ })}
+ > :
+ <>
+ {apiKeyDetails && }
+ {allowedOrigins && }
+ {clientIdDetails && }
+ {clientSecretDetails && }
+ {organizationDetails && }
+ {scopesDetails && }
+ {imsOrgID && }
+
+ >
+ }
+
+
+)
+}
+
+export { ReturnCredentialDetails };
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnCustomComp.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnCustomComp.js
new file mode 100644
index 00000000..ac95a829
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnCustomComp.js
@@ -0,0 +1,5 @@
+import React from 'react'
+
+const ReturnCustomComp = ({ returnCustomComp }) => <>{returnCustomComp?.children}>;
+
+export { ReturnCustomComp };
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnDevConsoleLink.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnDevConsoleLink.js
new file mode 100644
index 00000000..d1fca1b3
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnDevConsoleLink.js
@@ -0,0 +1,55 @@
+import React, { useContext } from 'react';
+import { css } from "@emotion/react";
+import { MIN_MOBILE_WIDTH, MAX_TABLET_SCREEN_WIDTH } from '../FormFields';
+import GetCredentialContext from '../GetCredentialContext';
+import { LinkOut } from '../Icons';
+
+const ReturnDevConsoleLink = ({ devConsoleLinkHeading, credentialName, projectId }) => {
+
+ const { selectedOrganization } = useContext(GetCredentialContext);
+
+ return (
+
+ )
+}
+
+export { ReturnDevConsoleLink };
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnManageDeveloperConsole.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnManageDeveloperConsole.js
new file mode 100644
index 00000000..ca7d8fdb
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnManageDeveloperConsole.js
@@ -0,0 +1,37 @@
+import React from 'react';
+import { css } from "@emotion/react";
+import { MIN_MOBILE_WIDTH, MAX_TABLET_SCREEN_WIDTH } from '../FormFields';
+import { LinkOut } from '../Icons';
+
+const ReturnManageDeveloperConsole = ({ returnManageDeveloperConsole }) => {
+ return (
+
+ )
+}
+
+export { ReturnManageDeveloperConsole }
\ No newline at end of file
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnNewCredential.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnNewCredential.js
new file mode 100644
index 00000000..b134d97d
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnNewCredential.js
@@ -0,0 +1,31 @@
+import React from 'react';
+import { css } from "@emotion/react";
+
+const ReturnNewCredential = ({ returnNewCredential, setIsCreateNewCredential, returnSideComp }) => {
+
+ return (
+
+
{returnNewCredential?.heading}
+ setIsCreateNewCredential(true)}
+ css={css`
+ width : 180px;
+ height : 32px;
+ `}
+ data-cy="create-new-credential"
+ >
+ {returnNewCredential?.buttonLabel}
+
+
+
+ )
+}
+
+export { ReturnNewCredential };
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnOrganizationName.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnOrganizationName.js
new file mode 100644
index 00000000..10264695
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnOrganizationName.js
@@ -0,0 +1,10 @@
+import React from 'react';
+import ShowCard from '../Card/ShowCard';
+
+const ReturnOrganizationName = ({ returnOrganizationName, organization }) => {
+ return (
+
+ )
+}
+
+export { ReturnOrganizationName };
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnProduct.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnProduct.js
new file mode 100644
index 00000000..75d94ab1
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnProduct.js
@@ -0,0 +1,41 @@
+import React from 'react';
+import { css } from "@emotion/react";
+import { ActionButton, Tooltip, TooltipTrigger } from '@adobe/react-spectrum';
+
+const ReturnProduct = ({ productList }) => {
+ return (
+ <>
+ {productList.map((product, index) => {
+ if (index < 2)
+ return (
+ button {
+ border : none !important;
+ }
+ `}
+ >
+ {product?.icon ? (
+
+
+
+
+ {product?.label}
+
+ ) : (
+
{product?.label}
+ )}
+
+ )
+ })}
+ >
+ )
+}
+
+export { ReturnProduct }
\ No newline at end of file
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnProducts.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnProducts.js
new file mode 100644
index 00000000..3eaad553
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnProducts.js
@@ -0,0 +1,46 @@
+import React from 'react';
+import { css } from "@emotion/react";
+import { ReturnProduct } from "./ReturnProduct";
+import { ActionButton, Item, Menu, MenuTrigger } from '@adobe/react-spectrum';
+
+const ReturnProducts = ({ productList }) => {
+ return (
+
+
+ {productList.length > 2 &&
+
button , & > button : active {
+ border:none;
+ background:transparent !important;
+ }`}
+ >
+
+
+ +{productList.length - 2} more
+
+
+ {item => - {item.label}
}
+
+
+
}
+
+ )
+}
+
+export { ReturnProducts };
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnScopes.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnScopes.js
new file mode 100644
index 00000000..f0a6ea63
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnScopes.js
@@ -0,0 +1,10 @@
+import React from 'react';
+import ShowCard from '../Card/ShowCard';
+
+const ReturnScopes = ({ returnScopes }) => {
+ return (
+
+ )
+}
+
+export { ReturnScopes };
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnSideComp.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnSideComp.js
new file mode 100644
index 00000000..a5d29de3
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/Return/ReturnSideComp.js
@@ -0,0 +1,24 @@
+import React from 'react';
+import { css } from "@emotion/react";
+import { ReturnCustomComp } from './ReturnCustomComp'
+import { ReturnNewCredential } from './ReturnNewCredential'
+
+const ReturnSideComp = ({ returnSideComp, setIsCreateNewCredential, returnNewCredential, returnCustomComp }) => {
+ return (
+ <>
+
+
+
+
+ >
+ )
+}
+
+export { ReturnSideComp }
\ No newline at end of file
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/Service.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/Service.js
new file mode 100644
index 00000000..5e7805f3
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/Service.js
@@ -0,0 +1,88 @@
+export const getOrganizations = async () => {
+ try {
+
+ const token = window.adobeIMS?.getTokenFromStorage()?.token;
+
+ if (token) {
+ const response = await fetch("/console/api/accounts?includeOrganizations=true", {
+ method: "GET",
+ headers: {
+ "Content-Type": "application/json",
+ "Authorization": "Bearer " + token,
+ "x-api-key": window?.adobeIMS?.adobeIdData?.client_id
+ }
+ });
+
+ if (!response.ok) {
+ if (response.status === 401) {
+ window.adobeIMS?.signIn();
+ }
+ throw new Error('Could not fetch accounts');
+ }
+
+ const accountsResult = await response.json();
+
+ const organizations = []
+ accountsResult.accounts.forEach(account => {
+ if (account.organizations?.length > 0) {
+ account.organizations.forEach(org => {
+ organizations.push({
+ ...org,
+ accountId: account.id,
+ accountType: account.type
+ })
+ });
+ }
+ });
+
+ organizations.sort((a, b) => a.name.localeCompare(b.name));
+
+ return organizations;
+ }
+
+ } catch (error) {
+ console.error('Error:', error);
+ }
+}
+
+export const getCredentialSecrets = async (response, selectedOrganization) => {
+
+ let projectId = response?.workspaces ? response?.workspaces[0]?.credentials[0]?.id : response?.id
+ const secretsUrl = `/console/api/organizations/${selectedOrganization.code}/integrations/${projectId}/secrets`;
+ const token = window.adobeIMS?.getTokenFromStorage()?.token;
+ const secretsResponse = await fetch(secretsUrl, {
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${token}`,
+ 'x-api-key': window.adobeIMS?.adobeIdData?.client_id,
+ },
+ });
+
+ const secrets = await secretsResponse.json();
+
+ const secret = secrets.client_secrets[0]?.client_secret;
+
+ return { clientId: secrets?.client_id, clientSecret: secret }
+
+};
+
+export const generateToken = async (apikey, secret, scopesDetails) => {
+ const options = {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ },
+ body: new URLSearchParams({
+ client_id: apikey,
+ client_secret: secret,
+ grant_type: 'client_credentials',
+ scope: scopesDetails?.scope,
+ }),
+ };
+
+ const tokenResponse = await fetch('/ims/token/v3', options);
+ const tokenJson = await tokenResponse.json();
+
+ return (tokenJson.access_token)
+
+}
\ No newline at end of file
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/SideComponent.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/SideComponent.js
new file mode 100644
index 00000000..5a9cdfb4
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/SideComponent.js
@@ -0,0 +1,3 @@
+const SideComponent = ({ side }) => (side);
+
+export { SideComponent };
\ No newline at end of file
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/SignIn.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/SignIn.js
new file mode 100644
index 00000000..0c0a9859
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/SignIn.js
@@ -0,0 +1,65 @@
+import React, { useContext } from 'react';
+import { css } from '@emotion/react';
+import classNames from 'classnames';
+import { MAX_TABLET_SCREEN_WIDTH, MIN_MOBILE_WIDTH } from './FormFields';
+import GetCredentialContext from './GetCredentialContext';
+
+const SignIn = ({}) => {
+ const { getCredentialData } = useContext(GetCredentialContext);
+ const signInProps = getCredentialData?.[SignIn];
+
+ return (
+ <>
+
+ {signInProps?.title && (
+
+ {signInProps?.title}
+
+ )}
+ {signInProps?.paragraph && (
+
+ {signInProps?.paragraph}
+
+ )}
+ {signInProps?.buttonText && (
+
window.adobeIMS.signIn()}
+ data-cy="sign-in-btn">
+ {signInProps?.buttonText}
+
+ )}
+
+ >
+ );
+};
+
+export { SignIn };
diff --git a/src/@adobe/gatsby-aio-theme/components/GetCredential/index.js b/src/@adobe/gatsby-aio-theme/components/GetCredential/index.js
new file mode 100644
index 00000000..f78beebb
--- /dev/null
+++ b/src/@adobe/gatsby-aio-theme/components/GetCredential/index.js
@@ -0,0 +1,408 @@
+import React, { useContext, useEffect, useState } from 'react';
+import { SignIn } from "./SignIn"
+import { css } from "@emotion/react";
+import PropTypes from 'prop-types';
+import classNames from "classnames";
+import { MAX_MOBILE_WIDTH, MAX_TABLET_SCREEN_WIDTH, MIN_MOBILE_WIDTH } from './FormFields';
+import { IllustratedMessage } from './IllustratedMessage';
+import { JoinBetaProgram } from './JoinBetaProgram';
+import ErrorBoundary from './ErrorBoundary';
+import { Product, Products, CardProduct, CardProducts } from './Products';
+import { Loading } from './Loading';
+import { CredentialForm } from './CredentialForm';
+import { CredentialName } from './Form/CredentialName';
+import { AllowedOrigins } from './Form/AllowedOrigins';
+import { SideComponent } from './SideComponent';
+import { Downloads } from './Form/Downloads';
+import { Download } from './Form/Download';
+import { AdobeDeveloperConsole } from './Form/AdobeDeveloperConsole';
+import { CardClientDetails } from './Card/CardClientDetails';
+import { CardClientId } from './Card/CardClientId';
+import { CardClientSecret } from './Card/CardClientSecret';
+import { CardOrganizationName } from './Card/CardOrganizationName';
+import { CardScopes } from './Card/CardScopes';
+import { CardAllowedOrigins } from './Card/CardAllowedOrigins';
+import { CardAPIKey } from './Card/CardAPIKey';
+import { PreviousProject } from './PreviousProject';
+import { PreviousCredential } from "./PreviousCredential";
+import { ReturnAccessToken } from './Return/ReturnAccessToken';
+import { ProjectsDropdown } from './Return/ProjectsDropdown';
+import { ReturnManageDeveloperConsole } from './Return/ReturnManageDeveloperConsole';
+import { ReturnDevConsoleLink } from './Return/ReturnDevConsoleLink';
+import { ReturnSideComp } from './Return/ReturnSideComp';
+import { ReturnCustomComp } from './Return/ReturnCustomComp';
+import { ReturnNewCredential } from './Return/ReturnNewCredential';
+import { ReturnClientId } from './Return/ReturnClientId';
+import { ReturnClientSecret } from './Return/ReturnClientSecret';
+import { ReturnOrganizationName } from './Return/ReturnOrganizationName';
+import { ReturnScopes } from './Return/ReturnScopes';
+import { ReturnAllowedOrigins } from './Return/ReturnAllowedOrigins';
+import { ReturnAPIKey } from './Return/ReturnAPIKey';
+import { MyCredential } from './MyCredential';
+import { AccessToken } from './Card/AccessToken';
+import { DevConsoleLink } from './Card/DevConsoleLink';
+import { RequestAccess } from "./RequestAccess/RequestAccess"
+import { RestrictedAccess } from './RequestAccess/RestrictedAccessFields';
+import { RequestAccessSide } from "./RequestAccess/RequestAccessSide";
+import Context from '@adobe/gatsby-theme-aio/src/components/Context';
+import GetCredentialContext from './GetCredentialContext';
+import { ReturnCredentialDetails } from './Return/ReturnCredentialDetails';
+import { OrganizationAccessDetailsEdgeCase } from './RequestAccess/OrganizationAccessDetailsEdgeCase';
+import { OrganizationAccessDetailsNoProduct } from './RequestAccess/OrganizationAccessDetailsNoProduct';
+import { OrganizationAccessDetailsType1User } from './RequestAccess/OrganizationAccessDetailsType1User';
+import { OrganizationAccessDetailsNotMember } from './RequestAccess/OrganizationAccessDetailsNotMember';
+import { OrganizationAccessDetailsNotSignUp } from './RequestAccess/OrganizationAccessDetailsNotSignUp';
+import { getOrganizations } from './Service';
+import { CardImsOrgID } from './Card/CardImsOrgID';
+
+const LocalStorageKey = 'OrgInfo';
+
+const GetCredential = ({ templateId, productName = "Firefly Service", children, className }) => {
+ const isBrowser = typeof window !== "undefined";
+ const [isPrevious, setIsPrevious] = useState(false);
+ const [selectedOrganization, setOrganization] = useState(undefined);
+ const [orgsLoading, setOrgsLoading] = useState(true);
+ const [templateLoading, setTemplateLoading] = useState(true);
+ const [previousProjectsLoading, setPreviousProjectsLoading] = useState(false);
+ const [allOrganizations, setAllOrganizations] = useState([]);
+ const [showCreateForm, setShowCreateForm] = useState(true);
+ const [isCreateNewCredential, setIsCreateNewCredential] = useState(false);
+ const [template, setTemplate] = useState(null);
+ const [isError, setIsError] = useState(false);
+ const [previousProjectDetail, setPreviousProjectDetail] = useState();
+
+ const [formData, setFormData] = useState({});
+
+ if (!templateId) {
+ console.error('No template id provided. Cannot continue. Will fail.');
+ }
+
+ const { isLoadingIms } = useContext(Context);
+
+ let getCredentialData = {};
+ React.Children.forEach(children, (child) => {
+ if (!React.isValidElement(child)) return;
+ if (child.props) {
+ getCredentialData[child.type] = child.props;
+ }
+ });
+
+ useEffect(() => {
+ const fetchTemplate = async () => {
+ try {
+ setIsError(false);
+ setTemplateLoading(true);
+ setTemplate(null);
+ const url = `/templates/${templateId}`
+ const response = await fetch(url, {
+ headers: {
+ "Content-Type": "application/json",
+ "Authorization": `Bearer ${window.adobeIMS.getTokenFromStorage().token}`,
+ "x-api-key": window.adobeIMS.adobeIdData.client_id,
+ "x-org-id": selectedOrganization.code
+ }
+ });
+
+ if (!response.ok) {
+ console.error('Template not found. Please check template id');
+ setIsError(true);
+ return;
+ }
+ setTemplate(await response.json());
+ setTemplateLoading(false);
+ }
+ catch (error) {
+ console.error('Error fetching template:', error);
+ setIsError(true);
+ setTemplateLoading(false);
+ }
+ }
+
+ if (templateId && selectedOrganization?.code) {
+ fetchTemplate();
+ }
+ }, [selectedOrganization]);
+
+ const switchOrganization = async (org) => {
+ const { userId: accountId } = (await window.adobeIMS.getProfile());
+
+ if (!org) {
+ // this means it's initial load. Try reading from local storage
+ const orgInLocalStorage = JSON.parse(localStorage.getItem(LocalStorageKey));
+ console.log('Found', orgInLocalStorage?.name, 'in local storage');
+
+ // check if the user has access to the org
+ if (orgInLocalStorage) {
+ org = allOrganizations.filter(o => o.code === orgInLocalStorage.code && accountId === orgInLocalStorage.accountId)[0];
+ console.log(`Org in local storage ${org ? '' : 'not '}accessible`);
+ }
+
+ // if no accessible org found in local storage, we pick the default org
+ if (!org) {
+ console.log('No accessible org found in local storage. Removing entry in local storage, if exists and picking default org');
+ localStorage.removeItem(LocalStorageKey);
+ const currentAccountOrgs = allOrganizations.filter(o => o.accountId === accountId);
+ org = currentAccountOrgs.filter(o => o.default)[0] ?? currentAccountOrgs[0];
+ }
+ }
+
+ console.log('Switching to org:', org?.name);
+ if (!org) {
+ throw new Error('No org found to switch to');
+ }
+
+ // switch accounts if org requires account switch
+ if (accountId !== org.accountId) {
+ await window.adobeIMS.switchProfile(org.accountId);
+ }
+
+ // set the org in local storage
+ localStorage.setItem(LocalStorageKey, JSON.stringify(org));
+ setOrganization(org);
+ setFormData(pre => {
+ return { ...pre, Agree: false }
+ })
+ }
+
+ useEffect(() => {
+ if (!selectedOrganization && !isLoadingIms && allOrganizations?.length > 0) {
+ // switch to default or last used org if no org already selected
+ switchOrganization();
+ }
+ }, [allOrganizations, selectedOrganization, isLoadingIms]);
+
+ useEffect(() => {
+ const getPreviousProjects = async () => {
+ setPreviousProjectsLoading(true);
+ const { userId } = await window.adobeIMS.getProfile();
+ const previousProjectDetailsUrl = `/console/api/organizations/${selectedOrganization?.id}/search/projects?templateId=${templateId}&createdBy=${userId}&excludeUserProfiles=true&skipReadOnlyCheck=true`;
+ const token = window.adobeIMS?.getTokenFromStorage()?.token;
+ const previousProjectDetailsResponse = await fetch(previousProjectDetailsUrl, {
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${token}`,
+ 'x-api-key': window.adobeIMS?.adobeIdData?.client_id,
+ },
+ });
+
+ const previousProjectDetails = await previousProjectDetailsResponse.json();
+ setPreviousProjectDetail(previousProjectDetails);
+
+ if (previousProjectDetails.count) {
+ setIsPrevious(true);
+ setPreviousProjectsLoading(false);
+ } else {
+ setIsPrevious(false);
+ setPreviousProjectsLoading(false);
+ }
+ }
+
+ if (selectedOrganization?.id && templateId && template?.userEntitled && !isCreateNewCredential) {
+ getPreviousProjects();
+ }
+
+ }, [template, isCreateNewCredential]);
+
+ useEffect(async () => {
+ // if IMS is still loading, do nothing
+ if (isLoadingIms) {
+ return;
+ }
+
+ // if user not signed in, set loading to false so that the sign in screen renders
+ if (!window.adobeIMS.isSignedInUser()) {
+ setTemplateLoading(false);
+ setPreviousProjectsLoading(false);
+ setOrgsLoading(false);
+ return;
+ }
+
+ setOrgsLoading(true);
+ const organizations = await getOrganizations();
+
+ if (!organizations || organizations.length < 1) {
+ console.error('No organizations found for the user. Cannot continue.');
+ setIsError(true);
+ setOrgsLoading(false);
+ return;
+ }
+
+ setAllOrganizations(organizations);
+ setOrgsLoading(false);
+
+ }, [isLoadingIms]);
+
+ useEffect(() => {
+
+ if (!isPrevious) {
+ setShowCreateForm(true)
+ }
+ else {
+ if (isPrevious && isCreateNewCredential) {
+ setShowCreateForm(true)
+ }
+ else {
+ setShowCreateForm(false)
+ }
+ }
+
+ }, [isPrevious, isCreateNewCredential])
+
+ const render = () => {
+ if (!templateId || isError) {
+ return
+ }
+
+ if (isLoadingIms || orgsLoading || templateLoading || previousProjectsLoading) {
+ return
+ }
+
+ if (!window.adobeIMS.isSignedInUser()) {
+ return
+ }
+
+ // template should never be null or undefined here
+ if (!template.userEntitled || !template.orgEntitled) {
+ return
+ }
+
+ if (isPrevious && !showCreateForm && !isCreateNewCredential) {
+ return
+ }
+
+ return
+
+ }
+
+ return (
+ <>
+ {
+ isBrowser &&
+
+
+
+ Get Credentials
+
+ {render()}
+
+
+
+
+
+ }
+ >
+ )
+
+};
+
+GetCredential.propTypes = {
+ templateId: PropTypes.string,
+ className: PropTypes.string,
+}
+
+GetCredential.SignIn = SignIn;
+GetCredential.Form = CredentialForm;
+GetCredential.Form.CredentialName = CredentialName;
+GetCredential.Form.AllowedOrigins = AllowedOrigins;
+GetCredential.Form.Products = Products;
+GetCredential.Form.Product = Product;
+GetCredential.Form.Side = SideComponent;
+GetCredential.Form.Downloads = Downloads;
+GetCredential.Form.Download = Download;
+GetCredential.Form.AdobeDeveloperConsole = AdobeDeveloperConsole;
+GetCredential.UnknownError = IllustratedMessage;
+GetCredential.Card = MyCredential;
+GetCredential.Card.AccessToken = AccessToken;
+GetCredential.Card.DevConsoleLink = DevConsoleLink;
+GetCredential.Card.Side = SideComponent;
+GetCredential.Card.Product = CardProduct;
+GetCredential.Card.Products = CardProducts;
+GetCredential.Card.CredentialDetails = CardClientDetails;
+GetCredential.Card.CredentialDetails.ClientId = CardClientId;
+GetCredential.Card.CredentialDetails.ClientSecret = CardClientSecret;
+GetCredential.Card.CredentialDetails.OrganizationName = CardOrganizationName;
+GetCredential.Card.CredentialDetails.Scopes = CardScopes;
+GetCredential.Card.CredentialDetails.AllowedOrigins = CardAllowedOrigins;
+GetCredential.Card.CredentialDetails.APIKey = CardAPIKey;
+GetCredential.Card.CredentialDetails.ImsOrgID = CardImsOrgID;
+GetCredential.NoBetaAccessError = JoinBetaProgram;
+GetCredential.Return = PreviousProject;
+GetCredential.Return.AccessToken = ReturnAccessToken;
+GetCredential.Return.ProjectsDropdown = ProjectsDropdown;
+GetCredential.Return.ManageDeveloperConsole = ReturnManageDeveloperConsole;
+GetCredential.Return.DevConsoleLink = ReturnDevConsoleLink;
+GetCredential.Return.Side = ReturnSideComp;
+GetCredential.Return.Side.Custom = ReturnCustomComp;
+GetCredential.Return.Side.NewCredential = ReturnNewCredential;
+GetCredential.Return.Product = CardProduct;
+GetCredential.Return.Products = CardProducts;
+GetCredential.Return.CredentialDetails = ReturnCredentialDetails;
+GetCredential.Return.CredentialDetails.ClientId = ReturnClientId;
+GetCredential.Return.CredentialDetails.ClientSecret = ReturnClientSecret;
+GetCredential.Return.CredentialDetails.OrganizationName = ReturnOrganizationName;
+GetCredential.Return.CredentialDetails.Scopes = ReturnScopes;
+GetCredential.Return.CredentialDetails.AllowedOrigins = ReturnAllowedOrigins;
+GetCredential.Return.CredentialDetails.APIKey = ReturnAPIKey;
+GetCredential.Return.CredentialDetails.ImsOrgID = CardImsOrgID;
+GetCredential.RequestAccess = RequestAccess;
+GetCredential.RequestAccess.RestrictedAccess = RestrictedAccess;
+GetCredential.RequestAccess.EdgeCase = OrganizationAccessDetailsEdgeCase;
+GetCredential.RequestAccess.EdgeCase.NoProduct = OrganizationAccessDetailsNoProduct;
+GetCredential.RequestAccess.EdgeCase.Type1User = OrganizationAccessDetailsType1User;
+GetCredential.RequestAccess.EdgeCase.NotMember = OrganizationAccessDetailsNotMember;
+GetCredential.RequestAccess.EdgeCase.NotSignUp = OrganizationAccessDetailsNotSignUp;
+GetCredential.RequestAccess.RestrictedAccess.Products = Products;
+GetCredential.RequestAccess.RestrictedAccess.Products.Product = Product;
+GetCredential.RequestAccess.RequestAccessSide = RequestAccessSide;
+
+export { GetCredential };
diff --git a/src/pages/credential/Credential.css b/src/pages/credential/Credential.css
new file mode 100644
index 00000000..c905c7d4
--- /dev/null
+++ b/src/pages/credential/Credential.css
@@ -0,0 +1,17 @@
+.side-container {
+ display: flex;
+ gap: 16px;
+ flex-direction: column;
+}
+
+.side-header {
+ color: var(--spectrum-global-color-gray-900);
+}
+
+.side-documentation {
+ color: rgb(2, 101, 220);
+}
+
+.side-documentation:hover {
+ color: rgb(0, 84, 182);
+}
\ No newline at end of file
diff --git a/src/pages/credential/GetCredentialApiKey.js b/src/pages/credential/GetCredentialApiKey.js
new file mode 100644
index 00000000..48c578a6
--- /dev/null
+++ b/src/pages/credential/GetCredentialApiKey.js
@@ -0,0 +1,136 @@
+import React from 'react'
+import { GetCredential } from '../../@adobe/gatsby-aio-theme/components/GetCredential';
+import creativeCloud from "./images/cc-icon.png";
+
+const GetCredentialApiKey = () => {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
API key credential
+
Submitting this form creates an API Key credential. The API key credential identifies your application to Adobe servers and can help accept or reject requests originating from certain domains.
+
Learn more
+
Authentication documentation
+
Express Embed SDK documentation
+
+
+
+
+
+
+
+
+
+
+
+
API key credential
+
Submitting this form creates an API Key credential. The API key credential identifies your application to Adobe servers and can help accept or reject requests originating from certain domains.
+
Learn more
+
Authentication documentation
+
Express Embed SDK documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Welcome back
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
API key credential
+
Submitting this form creates an API Key credential. The API key credential identifies your application to Adobe servers and can help accept or reject requests originating from certain domains.
+
Learn more
+
Authentication documentation
+
Express Embed SDK documentation
+
+
+
+
+
+
+ )
+}
+
+export default GetCredentialApiKey;
diff --git a/src/pages/credential/GetCredentialOAuthS2s.js b/src/pages/credential/GetCredentialOAuthS2s.js
new file mode 100644
index 00000000..5a706bc5
--- /dev/null
+++ b/src/pages/credential/GetCredentialOAuthS2s.js
@@ -0,0 +1,216 @@
+import React from 'react'
+import { GetCredential } from '../../@adobe/gatsby-aio-theme/components/GetCredential';
+import firefly from "./images/firefly.png";
+import ps from "./images/ps.png";
+
+const GetCredentialOAuthS2s = () => {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ OAuth server-to-server credential
+
+
+ This credential allows you to use industry standard OAuth2.0
+ libraries to generate access tokens using the OAuth 2.0 client
+ credentials grant type.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ OAuth server-to-server credential
+
+
+ This credential allows you to use industry standard OAuth2.0
+ libraries to generate access tokens using the OAuth 2.0 client
+ credentials grant type.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Welcome back
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ OAuth server-to-server credential
+
+
+ This credential allows you to use industry standard OAuth2.0
+ libraries to generate access tokens using the OAuth 2.0 client
+ credentials grant type.
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export default GetCredentialOAuthS2s;
diff --git a/src/pages/credential/images/cc-icon.png b/src/pages/credential/images/cc-icon.png
new file mode 100644
index 00000000..ecd8da46
Binary files /dev/null and b/src/pages/credential/images/cc-icon.png differ
diff --git a/src/pages/credential/images/firefly.png b/src/pages/credential/images/firefly.png
new file mode 100644
index 00000000..7122679f
Binary files /dev/null and b/src/pages/credential/images/firefly.png differ
diff --git a/src/pages/credential/images/ps.png b/src/pages/credential/images/ps.png
new file mode 100644
index 00000000..e10fbac6
Binary files /dev/null and b/src/pages/credential/images/ps.png differ
diff --git a/src/pages/get-credential-apikey/index.md b/src/pages/get-credential-apikey/index.md
new file mode 100644
index 00000000..f3523d3a
--- /dev/null
+++ b/src/pages/get-credential-apikey/index.md
@@ -0,0 +1,5 @@
+# Get API Key Credential
+
+import GetCredentialApiKey from "../credential/GetCredentialApiKey.js";
+
+
\ No newline at end of file
diff --git a/src/pages/get-credential-oauth/index.md b/src/pages/get-credential-oauth/index.md
new file mode 100644
index 00000000..caeb23be
--- /dev/null
+++ b/src/pages/get-credential-oauth/index.md
@@ -0,0 +1,5 @@
+# Get OAuth S2S Credential
+
+import GetCredentialOAuthS2s from "../credential/GetCredentialOAuthS2s.js"
+
+
\ No newline at end of file