diff --git a/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Endpoints/EndpointOverview.jsx b/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Endpoints/EndpointOverview.jsx index c195f8be2df..ab740432867 100644 --- a/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Endpoints/EndpointOverview.jsx +++ b/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Endpoints/EndpointOverview.jsx @@ -54,6 +54,12 @@ import EndpointSecurity from './GeneralConfiguration/EndpointSecurity'; import Credentials from './AWSLambda/Credentials.jsx'; import ServiceEndpoint from './ServiceEndpoint'; import CustomBackend from './CustomBackend'; +import { + ENDPOINT_TYPE_PROTOTYPED, + ENDPOINT_IMPLEMENTATION_TYPE_INLINE, + ENDPOINT_IMPLEMENTATION_TYPE_ENDPOINT, + ENDPOINT_IMPLEMENTATION_TYPE_MOCKED_OAS, +} from './endpointConstants'; const PREFIX = 'EndpointOverview'; @@ -162,11 +168,11 @@ const endpointTypes = [ { key: 'http', value: 'HTTP/REST Endpoint' }, { key: 'default', value: 'Dynamic Endpoints' }, { key: 'address', value: 'HTTP/SOAP Endpoint' }, - { key: 'prototyped', value: 'Prototype Endpoint' }, - { key: 'INLINE', value: 'Mock Implementation' }, + { key: ENDPOINT_TYPE_PROTOTYPED, value: 'Prototype Endpoint' }, + { key: ENDPOINT_IMPLEMENTATION_TYPE_INLINE, value: 'Mock Implementation' }, { key: 'awslambda', value: 'AWS Lambda' }, { key: 'service', value: 'Service Endpoint' }, - { key: 'MOCKED_OAS', value: 'Mock Implementation' }, + { key: ENDPOINT_IMPLEMENTATION_TYPE_MOCKED_OAS, value: 'Mock Implementation' }, { key: 'sequence_backend', value: 'Sequence Backend' }, { key: 'ws', value: 'Websocket Endpoint' }, ]; @@ -237,12 +243,12 @@ function EndpointOverview(props) { * */ const getEndpointType = (apiObject) => { const type = apiObject.endpointConfig && apiObject.endpointConfig.endpoint_type; - if (apiObject.endpointImplementationType === 'INLINE') { + if (apiObject.endpointImplementationType === ENDPOINT_IMPLEMENTATION_TYPE_INLINE) { return endpointTypes[4]; - } else if (apiObject.endpointImplementationType === 'MOCKED_OAS') { + } else if (apiObject.endpointImplementationType === ENDPOINT_IMPLEMENTATION_TYPE_MOCKED_OAS) { return endpointTypes[7]; - } else if (apiObject.endpointImplementationType === 'ENDPOINT' - && apiObject.endpointConfig.implementation_status === 'prototyped' + } else if (apiObject.endpointImplementationType === ENDPOINT_IMPLEMENTATION_TYPE_ENDPOINT + && apiObject.endpointConfig.implementation_status === ENDPOINT_TYPE_PROTOTYPED && api.lifeCycleStatus === 'PROTOTYPED') { return endpointTypes[3]; } else if (type === 'http') { @@ -322,7 +328,7 @@ function EndpointOverview(props) { { key: 'service', value: 'Service Endpoint' }, { key: 'address', value: 'HTTP/SOAP Endpoint' }, { key: 'default', value: 'Dynamic Endpoints' }, - { key: 'INLINE', value: 'Mock Implementation' }, + { key: ENDPOINT_IMPLEMENTATION_TYPE_INLINE, value: 'Mock Implementation' }, { key: 'awslambda', value: 'AWS Lambda' }, ]; } @@ -361,7 +367,7 @@ function EndpointOverview(props) { if (epType.key === 'service') { getServices(); } - if (epType.key !== 'INLINE' || epType.key !== 'MOCKED_OAS') { + if (epType.key !== ENDPOINT_IMPLEMENTATION_TYPE_INLINE && epType.key !== ENDPOINT_IMPLEMENTATION_TYPE_MOCKED_OAS) { setEndpointCategory({ prod: !!endpointConfig.production_endpoints, sandbox: !!endpointConfig.sandbox_endpoints, @@ -563,8 +569,8 @@ function EndpointOverview(props) { setTypeChangeConfirmation({ openDialog: false, serviceInfo: false }); setIsCustomBackendSelected(false); const selectedKey = typeChangeConfirmation.type || value; - if (selectedKey === 'INLINE' || selectedKey === 'MOCKED_OAS') { - const tmpConfig = createEndpointConfig('prototyped'); + if (selectedKey === ENDPOINT_IMPLEMENTATION_TYPE_INLINE || selectedKey === ENDPOINT_IMPLEMENTATION_TYPE_MOCKED_OAS) { + const tmpConfig = createEndpointConfig(ENDPOINT_TYPE_PROTOTYPED); endpointsDispatcher({ action: 'set_inline_or_mocked_oas', value: { @@ -572,12 +578,12 @@ function EndpointOverview(props) { endpointImplementationType: selectedKey, }, }); - } else if (selectedKey === 'prototyped') { + } else if (selectedKey === ENDPOINT_TYPE_PROTOTYPED) { const tmpConfig = createEndpointConfig(selectedKey); endpointsDispatcher({ action: 'set_prototyped', value: { - endpointImplementationType: 'ENDPOINT', + endpointImplementationType: ENDPOINT_IMPLEMENTATION_TYPE_ENDPOINT, endpointConfig: tmpConfig, }, }); @@ -586,7 +592,7 @@ function EndpointOverview(props) { endpointsDispatcher({ action: 'select_endpoint_type', value: { - endpointImplementationType: 'ENDPOINT', + endpointImplementationType: ENDPOINT_IMPLEMENTATION_TYPE_ENDPOINT, endpointConfig: { ...generatedEndpointConfig }, }, }); @@ -596,7 +602,7 @@ function EndpointOverview(props) { endpointsDispatcher({ action: 'select_endpoint_type', value: { - endpointImplementationType: 'ENDPOINT', + endpointImplementationType: ENDPOINT_IMPLEMENTATION_TYPE_ENDPOINT, endpointConfig: { ...generatedEndpointConfig }, }, }); @@ -605,7 +611,7 @@ function EndpointOverview(props) { endpointsDispatcher({ action: 'select_endpoint_type', value: { - endpointImplementationType: 'ENDPOINT', + endpointImplementationType: ENDPOINT_IMPLEMENTATION_TYPE_ENDPOINT, endpointConfig: { ...generatedEndpointConfig }, }, }); @@ -782,7 +788,8 @@ function EndpointOverview(props) { aria-label='EndpointType' name='endpointType' className={classes.radioGroup} - value={endpointType.key === 'MOCKED_OAS' ? 'INLINE' : endpointType.key} + value={endpointType.key === ENDPOINT_IMPLEMENTATION_TYPE_MOCKED_OAS + ? ENDPOINT_IMPLEMENTATION_TYPE_INLINE : endpointType.key} onChange={handleEndpointTypeSelect} > {supportedEnpointTypes.map((endpoint) => { @@ -804,7 +811,8 @@ function EndpointOverview(props) { - {(endpointType.key === 'INLINE' || endpointType.key === 'MOCKED_OAS') ? + {(endpointType.key === ENDPOINT_IMPLEMENTATION_TYPE_INLINE + || endpointType.key === ENDPOINT_IMPLEMENTATION_TYPE_MOCKED_OAS) ? iff(Object.keys(swaggerDef.paths).length !== 0, - {endpointType.key === 'prototyped' + {endpointType.key === ENDPOINT_TYPE_PROTOTYPED ? ( )} - {endpointType.key === 'prototyped' ?
+ {endpointType.key === ENDPOINT_TYPE_PROTOTYPED ?
: (
{componentValidator.includes("typeSANDBOX") && @@ -1296,8 +1305,10 @@ function EndpointOverview(props) { )} - {endpointType.key === 'INLINE' || endpointType.key === 'MOCKED_OAS' || - endpointType.key === 'prototyped' || endpointType.key === 'awslambda' || api.type === 'WS' || endpointType.key === 'sequence_backend' + {endpointType.key === ENDPOINT_IMPLEMENTATION_TYPE_INLINE + || endpointType.key === ENDPOINT_IMPLEMENTATION_TYPE_MOCKED_OAS + || endpointType.key === ENDPOINT_TYPE_PROTOTYPED || endpointType.key === 'awslambda' + || api.type === 'WS' || endpointType.key === 'sequence_backend' ?
: ( @@ -1315,10 +1326,10 @@ function EndpointOverview(props) { )} { - endpointType.key === 'INLINE' - || endpointType.key === 'MOCKED_OAS' + endpointType.key === ENDPOINT_IMPLEMENTATION_TYPE_INLINE + || endpointType.key === ENDPOINT_IMPLEMENTATION_TYPE_MOCKED_OAS || endpointType.key === 'default' - || endpointType.key === 'prototyped' + || endpointType.key === ENDPOINT_TYPE_PROTOTYPED || endpointType.key === 'sequence_backend' || api.type === 'WS' || endpointType.key === 'awslambda' diff --git a/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Endpoints/Endpoints.jsx b/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Endpoints/Endpoints.jsx index 73593382450..bc96f1259a2 100644 --- a/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Endpoints/Endpoints.jsx +++ b/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Endpoints/Endpoints.jsx @@ -37,8 +37,15 @@ import MCPServerEndpoints from 'AppComponents/MCPServers/Details/Endpoints/Endpo import EndpointOverview from './EndpointOverview'; import AIEndpoints from './AIEndpoints/AIEndpoints'; import { createEndpointConfig, getEndpointTemplateByType } from './endpointUtils'; -import { API_SECURITY_KEY_TYPE_PRODUCTION, +import { API_SECURITY_KEY_TYPE_PRODUCTION, API_SECURITY_KEY_TYPE_SANDBOX } from '../Configuration/components/APISecurity/components/apiSecurityConstants'; +import { + ENDPOINT_TYPE_PROTOTYPED, + ENDPOINT_IMPLEMENTATION_TYPE_INLINE, + ENDPOINT_IMPLEMENTATION_TYPE_ENDPOINT, + ENDPOINT_IMPLEMENTATION_TYPE_MOCKED_OAS, + ENDPOINT_IMPLEMENTATION_METHOD_MOCK, +} from './endpointConstants'; const PREFIX = 'Endpoints'; @@ -172,16 +179,25 @@ function Endpoints(props) { } case 'endpointImplementationType': { // set implementation status const { endpointType, implementationType } = value; - const config = createEndpointConfig(endpointType); - if (endpointType === 'prototyped') { - if (implementationType === 'mock') { + if (endpointType === ENDPOINT_TYPE_PROTOTYPED || endpointType === ENDPOINT_IMPLEMENTATION_TYPE_INLINE) { + const config = createEndpointConfig(ENDPOINT_TYPE_PROTOTYPED); + if (implementationType === ENDPOINT_IMPLEMENTATION_METHOD_MOCK) { api.generateMockScripts(api.id).then((res) => { // generates mock/sample payloads setSwagger(res.obj); }); - return { ...initState, endpointConfig: config, endpointImplementationType: 'INLINE' }; + return { + ...initState, + endpointConfig: config, + endpointImplementationType: ENDPOINT_IMPLEMENTATION_TYPE_INLINE, + }; } - return { ...initState, endpointConfig: config, endpointImplementationType: 'ENDPOINT' }; + return { + ...initState, + endpointConfig: config, + endpointImplementationType: ENDPOINT_IMPLEMENTATION_TYPE_ENDPOINT, + }; } + const config = createEndpointConfig(endpointType); return { ...initState, endpointConfig: config }; } case 'endpointSecurity': { // set endpoint security @@ -201,7 +217,7 @@ function Endpoints(props) { } case 'set_inline_or_mocked_oas': { const { endpointImplementationType, endpointConfig } = value; - if (endpointImplementationType === 'INLINE') { + if (endpointImplementationType === ENDPOINT_IMPLEMENTATION_TYPE_INLINE) { api.generateMockScripts(api.id).then((res) => { // generates mock/sample payloads setSwagger(res.obj); }); @@ -263,89 +279,105 @@ function Endpoints(props) { * * @param {boolean} isRedirect Used for dynamic endpoints to redirect to the runtime config page. */ - const handleSave = (isRedirect) => { + /** + * Delete/ upload the production and sandbox sequence backends based on the current backend lists. + */ + const deleteSequenceBackendOf = (keyType, deleteErrorMessage) => api + .deleteSequenceBackend(keyType, api.id) + .then(() => { + Alert.success(keyType === API_SECURITY_KEY_TYPE_PRODUCTION + ? 'Production Sequence backend deleted successfully' + : 'Sandbox Sequence backend deleted successfully'); + }) + .catch(() => { + Alert.error(deleteErrorMessage); + }); + + const uploadSequenceBackendOf = (keyType, content, uploadErrorMessage) => api + .uploadCustomBackend(content, keyType, api.id) + .then(() => { + Alert.success('Custom backend uploaded successfully'); + }) + .catch((error) => { + const backendMessage = error?.response?.body?.description; + Alert.error(backendMessage || uploadErrorMessage); + }); - const { endpointConfig, endpointImplementationType, serviceInfo } = apiObject; - if (endpointConfig.endpoint_type === 'service') { - endpointConfig.endpoint_type = 'http'; - } - setUpdating(true); - if (endpointConfig.endpoint_type === 'sequence_backend') { - if (productionBackendList?.length === 0 || (productionBackendList?.length > 0 - && productionBackendList[0].content)) { - api.deleteSequenceBackend(API_SECURITY_KEY_TYPE_PRODUCTION, api.id).then(() => { - Alert.success('Production Sequence backend deleted successfully'); - }) - .catch(() => { - Alert.error(intl.formatMessage({ - id: 'Apis.Details.Endpoints.Endpoints.delete.sequence.backend.error', - defaultMessage: 'Error Deleting Production Sequence Backend', - })); - }); - } + /** + * Delete a sequence backend of the given type, then, only once that delete has settled, upload its + * replacement content if any was provided. Chaining the upload off the delete's promise (rather than + * firing both at once) keeps the two requests deterministic instead of racing against each other. + */ + const updateSequenceBackendOf = async (keyType, backendList, deleteErrorMessage, uploadErrorMessage) => { + const shouldDelete = backendList?.length === 0 + || (backendList?.length > 0 && backendList[0].content); + const shouldUpload = backendList?.length > 0 && backendList[0].content; - if (sandBoxBackendList?.length === 0 || (sandBoxBackendList?.length > 0 && sandBoxBackendList[0].content)) { - api.deleteSequenceBackend(API_SECURITY_KEY_TYPE_SANDBOX, api.id).then(() => { - Alert.success('Sandbox Sequence backend deleted successfully'); - }) - .catch(() => { - Alert.error(intl.formatMessage({ - id: 'Apis.Details.Endpoints.Endpoints.delete.sequence.backend.error', - defaultMessage: 'Error Deleting Sandbox Sequence Backend', - })); - }); - } - if (productionBackendList?.length > 0 && productionBackendList[0].content) { - const productionBackend = productionBackendList[0]; - api.uploadCustomBackend(productionBackend.content, API_SECURITY_KEY_TYPE_PRODUCTION, api.id) - .then(() => { - Alert.success('Custom backend uploaded successfully'); - }) - .catch((error) => { - const backendMessage = error?.response?.body?.description; - Alert.error( - backendMessage || intl.formatMessage({ - id: 'Apis.Details.Endpoints.Endpoints.upload.sequence.backend.error', - defaultMessage: 'Error Uploading Production Sequence Backend', - }), - ); - }); - } - if (sandBoxBackendList?.length > 0 && sandBoxBackendList[0].content) { - const sandBackend = sandBoxBackendList[0]; - api.uploadCustomBackend(sandBackend.content, API_SECURITY_KEY_TYPE_SANDBOX, api.id) - .then(() => { - Alert.success('Custom backend uploaded successfully'); - }) - .catch((error) => { - const backendMessage = error?.response?.body?.description; - Alert.error( - backendMessage || intl.formatMessage({ - id: 'Apis.Details.Endpoints.Endpoints.upload.sequence.backend.error', - defaultMessage: 'Error Uploading Sandbox Sequence Backend', - }), - ); - }); - } + if (shouldDelete) { + await deleteSequenceBackendOf(keyType, deleteErrorMessage); } - if (endpointImplementationType === 'INLINE' || endpointImplementationType === 'MOCKED_OAS') { + if (shouldUpload) { + await uploadSequenceBackendOf(keyType, backendList[0].content, uploadErrorMessage); + } + }; + + const updateSequenceBackends = () => Promise.all([ + updateSequenceBackendOf( + API_SECURITY_KEY_TYPE_PRODUCTION, + productionBackendList, + intl.formatMessage({ + id: 'Apis.Details.Endpoints.Endpoints.delete.sequence.backend.error', + defaultMessage: 'Error Deleting Production Sequence Backend', + }), + intl.formatMessage({ + id: 'Apis.Details.Endpoints.Endpoints.upload.sequence.backend.error', + defaultMessage: 'Error Uploading Production Sequence Backend', + }), + ), + updateSequenceBackendOf( + API_SECURITY_KEY_TYPE_SANDBOX, + sandBoxBackendList, + intl.formatMessage({ + id: 'Apis.Details.Endpoints.Endpoints.delete.sequence.backend.error', + defaultMessage: 'Error Deleting Sandbox Sequence Backend', + }), + intl.formatMessage({ + id: 'Apis.Details.Endpoints.Endpoints.upload.sequence.backend.error', + defaultMessage: 'Error Uploading Sandbox Sequence Backend', + }), + ), + ]); + + /** + * Update the swagger (for INLINE/ MOCKED_OAS implementations) or the API object, then invoke the completion + * callback. Shared by handleSave and handleSaveAndDeploy, which only differ in the update payload and what + * happens once the update settles. + * + * @param {string} endpointImplementationType The api implementation type (INLINE/ ENDPOINT/ MOCKED_OAS). + * @param {object} updatePayload The payload to send via updateAPI for INLINE/ MOCKED_OAS implementations. + * @param {Function} onComplete Callback invoked once the update settles. + */ + const persistEndpointConfig = (endpointImplementationType, updatePayload, onComplete) => { + if (endpointImplementationType === ENDPOINT_IMPLEMENTATION_TYPE_INLINE + || endpointImplementationType === ENDPOINT_IMPLEMENTATION_TYPE_MOCKED_OAS) { api.updateSwagger(swagger).then((resp) => { setSwagger(resp.obj); - }).then(() => { - updateAPI({ endpointConfig, endpointImplementationType, serviceInfo }) - .catch((error) => { - if (error.response) { - Alert.error(error.response.body.description); - } else { - Alert.error('Error occurred while updating endpoint configurations'); - } - }); - }).finally(() => { - setUpdating(false); - if (isRedirect) { - history.push('/apis/' + api.id + '/policies'); - } - }); + }).then(() => updateAPI(updatePayload) + .catch((error) => { + if (error.response) { + Alert.error(error.response.body.description); + } else { + Alert.error('Error occurred while updating endpoint configurations'); + } + })) + .catch((error) => { + if (error.response) { + Alert.error(error.response.body.description); + } else { + Alert.error('Error occurred while updating endpoint configurations'); + } + }) + .finally(onComplete); } else { const apiObjectCopy = cloneDeep(apiObject); if (apiObjectCopy.endpointConfig.endpoint_type === 'service') { @@ -359,13 +391,36 @@ function Endpoints(props) { Alert.error('Error occurred while updating endpoint configurations'); } }) - .finally(() => { + .finally(onComplete); + } + }; + + /** + * Method to update the api. + * + * @param {boolean} isRedirect Used for dynamic endpoints to redirect to the runtime config page. + */ + const handleSave = (isRedirect) => { + const { endpointConfig, endpointImplementationType, serviceInfo } = apiObject; + if (endpointConfig.endpoint_type === 'service') { + endpointConfig.endpoint_type = 'http'; + } + setUpdating(true); + const sequenceBackendsUpdated = endpointConfig.endpoint_type === 'sequence_backend' + ? updateSequenceBackends() + : Promise.resolve(); + sequenceBackendsUpdated.then(() => { + persistEndpointConfig( + endpointImplementationType, + { endpointConfig, endpointImplementationType, serviceInfo }, + () => { setUpdating(false); if (isRedirect) { history.push('/apis/' + api.id + '/policies'); } - }); - } + }, + ); + }); }; const handleSaveAndDeploy = () => { @@ -374,103 +429,20 @@ function Endpoints(props) { endpointConfig.endpoint_type = 'http'; } setUpdating(true); - if (endpointConfig.endpoint_type === 'sequence_backend') { - if (productionBackendList?.length === 0 - || (productionBackendList?.length > 0 && productionBackendList[0].content)) { - api.deleteSequenceBackend(API_SECURITY_KEY_TYPE_PRODUCTION, api.id) - .then(() => { - Alert.success('Production Sequence backend deleted successfully'); - }) - .catch(() => { - Alert.error(intl.formatMessage({ - id: 'Apis.Details.Endpoints.Endpoints.delete.sequence.backend.error', - defaultMessage: 'Error Deleting Production Sequence Backend', - })); - }); - } - - if (sandBoxBackendList?.length === 0 - || (sandBoxBackendList?.length > 0 && sandBoxBackendList[0].content)) { - api.deleteSequenceBackend(API_SECURITY_KEY_TYPE_SANDBOX, api.id) - .then(() => { - Alert.success('Sandbox Sequence backend deleted successfully'); - }) - .catch(() => { - Alert.error(intl.formatMessage({ - id: 'Apis.Details.Endpoints.Endpoints.delete.sequence.backend.error', - defaultMessage: 'Error Deleting Sandbox Sequence Backend', - })); - }); - } - if (productionBackendList?.length > 0 && productionBackendList[0].content) { - const productionBackend = productionBackendList[0]; - api.uploadCustomBackend(productionBackend.content, API_SECURITY_KEY_TYPE_PRODUCTION, api.id) - .then(() => { - Alert.success('Custom backend uploaded successfully'); - }) - .catch((error) => { - const backendMessage = error?.response?.body?.description; - Alert.error( - backendMessage || intl.formatMessage({ - id: 'Apis.Details.Endpoints.Endpoints.upload.sequence.backend.error', - defaultMessage: 'Error Uploading Production Sequence Backend', - }), - ); - }); - } - if (sandBoxBackendList?.length > 0 && sandBoxBackendList[0].content) { - const sandBackend = sandBoxBackendList[0]; - api.uploadCustomBackend(sandBackend.content, API_SECURITY_KEY_TYPE_SANDBOX, api.id) - .then(() => { - Alert.success('Custom backend uploaded successfully'); - }) - .catch((error) => { - const backendMessage = error?.response?.body?.description; - Alert.error( - backendMessage || intl.formatMessage({ - id: 'Apis.Details.Endpoints.Endpoints.upload.sequence.backend.error', - defaultMessage: 'Error Uploading Sandbox Sequence Backend', - }), - ); - }); - } - } - if (endpointImplementationType === 'INLINE' || endpointImplementationType === 'MOCKED_OAS') { - api.updateSwagger(swagger).then((resp) => { - setSwagger(resp.obj); - }).then(() => { - updateAPI({ endpointConfig, endpointImplementationType, endpointSecurity, serviceInfo }) - .catch((error) => { - if (error.response) { - Alert.error(error.response.body.description); - } else { - Alert.error('Error occurred while updating endpoint configurations'); - } - }); - }).finally(() => history.push({ - pathname: api.isAPIProduct() ? `/api-products/${api.id}/deployments` - : `/apis/${api.id}/deployments`, - state: 'deploy', - })); - } else { - const apiObjectCopy = cloneDeep(apiObject); - if (apiObjectCopy.endpointConfig.endpoint_type === 'service') { - apiObjectCopy.endpointConfig.endpoint_type = 'http'; - } - updateAPI(apiObjectCopy) - .catch((error) => { - if (error.response) { - Alert.error(error.response.body.description); - } else { - Alert.error('Error occurred while updating endpoint configurations'); - } - }) - .finally(() => history.push({ + const sequenceBackendsUpdated = endpointConfig.endpoint_type === 'sequence_backend' + ? updateSequenceBackends() + : Promise.resolve(); + sequenceBackendsUpdated.then(() => { + persistEndpointConfig( + endpointImplementationType, + { endpointConfig, endpointImplementationType, endpointSecurity, serviceInfo }, + () => history.push({ pathname: api.isAPIProduct() ? `/api-products/${api.id}/deployments` : `/apis/${api.id}/deployments`, state: 'deploy', - })); - } + }), + ); + }); }; /** @@ -677,8 +649,9 @@ function Endpoints(props) { } } else { let isValidEndpoint = false; - if (endpointConfig.implementation_status === 'prototyped' && api.lifeCycleStatus === 'PROTOTYPED') { - if (implementationType === 'ENDPOINT') { + if (endpointConfig.implementation_status === ENDPOINT_TYPE_PROTOTYPED + && api.lifeCycleStatus === 'PROTOTYPED') { + if (implementationType === ENDPOINT_IMPLEMENTATION_TYPE_ENDPOINT) { if (endpointConfig.production_endpoints && endpointConfig.production_endpoints.url === '') { return { isValid: false, diff --git a/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Endpoints/GenericEndpoint.jsx b/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Endpoints/GenericEndpoint.jsx index 367620acf54..155058728e9 100644 --- a/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Endpoints/GenericEndpoint.jsx +++ b/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Endpoints/GenericEndpoint.jsx @@ -32,6 +32,7 @@ import { isRestricted } from 'AppData/AuthManager'; import APIContext from 'AppComponents/Apis/Details/components/ApiContext'; import API from 'AppData/api'; import { green } from '@mui/material/colors'; +import { ENDPOINT_TYPE_PROTOTYPED } from './endpointConstants'; const PREFIX = 'GenericEndpoint'; @@ -224,7 +225,7 @@ function GenericEndpoint(props) { )} )} - {type === 'prototyped' + {type === ENDPOINT_TYPE_PROTOTYPED ?
: ( <> diff --git a/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Endpoints/NewEndpointCreate.jsx b/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Endpoints/NewEndpointCreate.jsx index 602bfe43eb9..894bb9f6142 100644 --- a/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Endpoints/NewEndpointCreate.jsx +++ b/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Endpoints/NewEndpointCreate.jsx @@ -33,6 +33,10 @@ import { CardActions, } from '@mui/material'; import PropTypes from 'prop-types'; +import { + ENDPOINT_IMPLEMENTATION_TYPE_INLINE, + ENDPOINT_IMPLEMENTATION_METHOD_MOCK, +} from './endpointConstants'; const PREFIX = 'NewEndpointCreate'; @@ -97,7 +101,7 @@ function NewEndpointCreate(props) { componentValidator, } = props; const intl = useIntl(); - const [endpointImplType, setImplType] = useState('mock'); + const [endpointImplType, setEndpointImplType] = useState(ENDPOINT_IMPLEMENTATION_METHOD_MOCK); const endpointTypes = [ { type: 'http', @@ -152,7 +156,7 @@ function NewEndpointCreate(props) { disabled: ['SOAPTOREST', 'GRAPHQL', 'SSE', 'SOAP', 'HTTP'], }, { - type: 'INLINE', + type: ENDPOINT_IMPLEMENTATION_TYPE_INLINE, name: intl.formatMessage({ id: 'Apis.Details.Endpoints.NewEndpointCreate.create.prototype.endpoint', defaultMessage: 'Mock Implementation', @@ -240,7 +244,9 @@ function NewEndpointCreate(props) { name='endpointType' className={classes.radioGroup} value={endpointImplType} - onChange={(event) => { setImplType(event.target.value); }} + onChange={(event) => { + setEndpointImplType(event.target.value); + }} > {type.options.filter((types) => !types.disabled .includes(apiType)).map(((option) => { diff --git a/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Endpoints/endpointConstants.js b/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Endpoints/endpointConstants.js new file mode 100644 index 00000000000..a176f0bd129 --- /dev/null +++ b/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Endpoints/endpointConstants.js @@ -0,0 +1,29 @@ +/** + * Copyright (c) WSO2 Inc. (http://wso2.com) All Rights Reserved. + * + * Licensed 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 CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const ENDPOINT_TYPE_PROTOTYPED = 'prototyped'; +const ENDPOINT_IMPLEMENTATION_TYPE_INLINE = 'INLINE'; +const ENDPOINT_IMPLEMENTATION_TYPE_ENDPOINT = 'ENDPOINT'; +const ENDPOINT_IMPLEMENTATION_TYPE_MOCKED_OAS = 'MOCKED_OAS'; +const ENDPOINT_IMPLEMENTATION_METHOD_MOCK = 'mock'; + +export { + ENDPOINT_TYPE_PROTOTYPED, + ENDPOINT_IMPLEMENTATION_TYPE_INLINE, + ENDPOINT_IMPLEMENTATION_TYPE_ENDPOINT, + ENDPOINT_IMPLEMENTATION_TYPE_MOCKED_OAS, + ENDPOINT_IMPLEMENTATION_METHOD_MOCK, +}; \ No newline at end of file diff --git a/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Endpoints/endpointUtils.js b/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Endpoints/endpointUtils.js index 34c86b7b001..456b6c7bd16 100644 --- a/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Endpoints/endpointUtils.js +++ b/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Endpoints/endpointUtils.js @@ -15,6 +15,7 @@ */ import cloneDeep from 'lodash.clonedeep'; +import { ENDPOINT_TYPE_PROTOTYPED } from './endpointConstants'; /** * Utility method to get the endpoint property name based on the given endpoint type and category. @@ -140,7 +141,7 @@ function getEndpointConfigByImpl(implementationType) { const tmpEndpointConfig = {}; if (implementationType === 'PROTOTYPED') { tmpEndpointConfig.endpoint_type = 'http'; - tmpEndpointConfig.implementation_status = 'prototyped'; + tmpEndpointConfig.implementation_status = ENDPOINT_TYPE_PROTOTYPED; tmpEndpointConfig.production_endpoints = { config: null, url: 'http://localhost' }; tmpEndpointConfig.sandbox_endpoints = { config: null, url: 'http://localhost' }; } else { @@ -184,8 +185,8 @@ function createEndpointConfig(endpointType) { tmpEndpointConfig.endpoint_type = 'ws'; tmpEndpointConfig.failOver = false; break; - case 'prototyped': - tmpEndpointConfig.implementation_status = 'prototyped'; + case ENDPOINT_TYPE_PROTOTYPED: + tmpEndpointConfig.implementation_status = ENDPOINT_TYPE_PROTOTYPED; tmpEndpointConfig.endpoint_type = 'http'; tmpEndpointConfig.production_endpoints = { config: null, url: 'http://localhost' }; tmpEndpointConfig.sandbox_endpoints = { config: null, url: 'http://localhost' };