Skip to content

Commit

Permalink
UI fixes for versioning support of API Products
Browse files Browse the repository at this point in the history
  • Loading branch information
HiranyaKavishani committed Dec 19, 2023
1 parent 099dd40 commit 76667f9
Show file tree
Hide file tree
Showing 14 changed files with 205 additions and 89 deletions.
20 changes: 19 additions & 1 deletion portals/publisher/src/main/webapp/site/public/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@
"Apis.Create.APIProduct.APIProductCreateWrapper.sub.heading": [
{
"type": 0,
"value": "Create an API Product by providing a Name, a Context, Resources, and Business Plans (optional)."
"value": "Create an API Product by providing a Name, a Context, a Version, Resources, and Business Plans (optional)."
}
],
"Apis.Create.AsyncAPI.ApiCreateAsyncAPI.advertiseOnly.warning": [
Expand Down Expand Up @@ -225,6 +225,12 @@
"value": "Version"
}
],
"Apis.Create.Components.DefaultAPIForm.api.product.version": [
{
"type": 0,
"value": "Version"
}
],
"Apis.Create.Components.NewTopic.topic.name": [
{
"type": 0,
Expand Down Expand Up @@ -1359,6 +1365,18 @@
"value": "Selected Rate Limiting Policy will be applied to all the requests of this API."
}
],
"Apis.Details.APIProduct.NewVersion.NewVersion.error": [
{
"type": 0,
"value": "Something went wrong while creating a new version!. Error:"
}
],
"Apis.Details.APIProduct.NewVersion.NewVersion.success": [
{
"type": 0,
"value": "Successfully created new version"
}
],
"Apis.Details.AccessControl.roles.help": [
{
"type": 0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
"defaultMessage": "Add Resources"
},
"Apis.Create.APIProduct.APIProductCreateWrapper.sub.heading": {
"defaultMessage": "Create an API Product by providing a Name, a Context, Resources, and Business Plans (optional)."
"defaultMessage": "Create an API Product by providing a Name, a Context, a Version, Resources, and Business Plans (optional)."
},
"Apis.Create.AsyncAPI.ApiCreateAsyncAPI.advertiseOnly.warning": {
"defaultMessage": "API Manager only supports the streaming APIs of types WebSocket, SSE and WebSub. Please create one of the supported types if you want to deploy it in the gateway."
Expand Down Expand Up @@ -98,6 +98,9 @@
"Apis.Create.Components.DefaultAPIForm.api.product.context": {
"defaultMessage": "Context"
},
"Apis.Create.Components.DefaultAPIForm.api.product.version": {
"defaultMessage": "Version"
},
"Apis.Create.Components.DefaultAPIForm.name": {
"defaultMessage": "Name"
},
Expand Down Expand Up @@ -582,6 +585,12 @@
"Apis.Details.APILevelRateLimitingPolicies.components.Configuration.tooltip": {
"defaultMessage": "Selected Rate Limiting Policy will be applied to all the requests of this API."
},
"Apis.Details.APIProduct.NewVersion.NewVersion.error": {
"defaultMessage": "Something went wrong while creating a new version!. Error:"
},
"Apis.Details.APIProduct.NewVersion.NewVersion.success": {
"defaultMessage": "Successfully created new version"
},
"Apis.Details.AccessControl.roles.help": {
"defaultMessage": "Enter valid role and press enter"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ export default function ApiProductCreateWrapper(props) {
<FormattedMessage
id='Apis.Create.APIProduct.APIProductCreateWrapper.sub.heading'
defaultMessage={
'Create an API Product by providing a Name, a Context, Resources, '
'Create an API Product by providing a Name, a Context, a Version, Resources, '
+ 'and Business Plans (optional).'
}
/>
Expand Down Expand Up @@ -190,11 +190,12 @@ export default function ApiProductCreateWrapper(props) {
const createAPIProduct = () => {
setCreating(true);
const {
name, context,
name, context, version,
} = apiInputs;
const apiData = {
name,
context,
version,
policies,
apis: apiResources,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ export default function DefaultAPIForm(props) {
// Check the provided API validity on mount, TODO: Better to use Joi schema here ~tmkb
useEffect(() => {
onValidate(Boolean(api.name)
&& (isAPIProduct || Boolean(api.version))
&& (Boolean(api.version))
&& Boolean(api.context));
}, []);

Expand All @@ -154,10 +154,9 @@ export default function DefaultAPIForm(props) {
.reduce((acc, cVal) => acc && cVal); // Aggregate the individual validation states
// TODO: refactor following redundant validation.
// The valid state should available in the above reduced state ~tmkb
// if isAPIProduct gets true version validation has been skipped
isFormValid = isFormValid
&& Boolean(api.name)
&& (isAPIProduct || Boolean(api.version))
&& Boolean(api.version)
&& Boolean(api.context);
onValidate(isFormValid, validity);
setValidity(newState);
Expand Down Expand Up @@ -430,7 +429,7 @@ export default function DefaultAPIForm(props) {
</>
) : (
<>
<Grid item md={12}>
<Grid item md={8} xs={6}>
<TextField
fullWidth
id='context'
Expand Down Expand Up @@ -470,6 +469,37 @@ export default function DefaultAPIForm(props) {
variant='outlined'
/>
</Grid>
<Grid item md={4} xs={6}>
<TextField
fullWidth
id='version'
error={Boolean(validity.version)}
label={(
<>
<FormattedMessage
id='Apis.Create.Components.DefaultAPIForm.api.product.version'
defaultMessage='Version'
/>
<sup className={classes.mandatoryStar}>*</sup>
</>
)}
name='version'
value={api.version}
onChange={onChange}
InputProps={{
id: 'itest-id-apiversion-input',
onBlur: ({ target: { value } }) => {
validate('version', value);
},
}}
InputLabelProps={{
for: 'itest-id-apiversion-input',
}}
helperText={validity.version && validity.version.message}
margin='normal'
variant='outlined'
/>
</Grid>
</>
)}
</Grid>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,11 @@ const useStyles = makeStyles((theme) => ({
* @returns {Object} Deep copy of an object
*/
function copyAPIConfig(api) {
let isDefaultVersion = false;
// to set isDefaultVersion of migrated APIProducts as true
if (api.apiType === API.CONSTS.APIProduct && api.isDefaultVersion == null) {
isDefaultVersion = true;
}
const copiedConfig = {
id: api.id,
name: api.name,
Expand All @@ -146,7 +151,7 @@ function copyAPIConfig(api) {
responseCachingEnabled: api.responseCachingEnabled,
cacheTimeout: api.cacheTimeout,
visibility: api.visibility,
isDefaultVersion: api.isDefaultVersion,
isDefaultVersion: api.isDefaultVersion || isDefaultVersion,
enableSchemaValidation: api.enableSchemaValidation,
accessControlRoles: [...api.accessControlRoles],
visibleRoles: [...api.visibleRoles],
Expand Down Expand Up @@ -562,9 +567,7 @@ export default function DesignConfigurations() {
)}
</Box>
<Box py={1}>
{api.apiType !== API.CONSTS.APIProduct && (
<DefaultVersion api={apiConfig} configDispatcher={configDispatcher} />
)}
<DefaultVersion api={apiConfig} configDispatcher={configDispatcher} />
</Box>
<Box pt={2}>
<Button
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,11 +171,12 @@ class LifeCycleUpdate extends Component {
const lifecycleChecklist = this.props.checkList.map((item) => item.value + ':' + item.checked);
const { isAPIProduct } = this.props;
if (isAPIProduct) {
promisedUpdate = this.apiProduct.updateLcState(apiUUID, action, lifecycleChecklist);
} else if (lifecycleChecklist.length > 0) {
promisedUpdate = this.api.updateLcState(apiUUID, action, lifecycleChecklist.toString());
promisedUpdate = this.apiProduct.updateLcState(apiUUID, action, lifecycleChecklist.length > 0
? lifecycleChecklist.toString() : lifecycleChecklist );
} else {
promisedUpdate = this.api.updateLcState(apiUUID, action);
promisedUpdate = (lifecycleChecklist.length > 0)
? this.api.updateLcState(apiUUID, action, lifecycleChecklist.toString())
: this.api.updateLcState(apiUUID, action);
}
promisedUpdate
.then((response) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import FormControlLabel from '@material-ui/core/FormControlLabel';
import Radio from '@material-ui/core/Radio';
import FormLabel from '@material-ui/core/FormLabel';
import Alert from 'AppComponents/Shared/Alert';
import API from 'AppData/api';
import { withAPI } from 'AppComponents/Apis/Details/components/ApiContext';

const styles = (theme) => ({
Expand Down Expand Up @@ -114,15 +115,17 @@ class CreateNewVersion extends React.Component {

componentDidMount() {
const { api } = this.props;
if (api.serviceInfo !== null) {
const promisedServices = ServiceCatalog.getServiceByName(api.serviceInfo);
promisedServices.then((data) => {
const array = data.list.map((item) => item.version);
this.setState({ versionList: array });
}).catch((error) => {
console.error(error);
Alert.error('Error while loading services version');
});
if (api.serviceInfo !== undefined) {
if (api.serviceInfo !== null) {
const promisedServices = ServiceCatalog.getServiceByName(api.serviceInfo);
promisedServices.then((data) => {
const array = data.list.map((item) => item.version);
this.setState({ versionList: array });
}).catch((error) => {
console.error(error);
Alert.error('Error while loading services version');
});
}
}
}

Expand Down Expand Up @@ -168,28 +171,53 @@ class CreateNewVersion extends React.Component {
return;
}
const isDefaultVersionBool = isDefaultVersion === 'yes';
const apiClient = new API();
const { intl } = this.props;
api.createNewAPIVersion(newVersion, isDefaultVersionBool, serviceVersion)
.then((response) => {
this.setState({
redirectToReferrer: true,
apiId: response.obj.id,
if (api.apiType === 'APIPRODUCT') {
apiClient.createNewAPIProductVersion(api.id ,newVersion, isDefaultVersionBool)
.then((response) => {
this.setState({
redirectToReferrer: true,
apiId: response.obj.id,
});
Alert.info(intl.formatMessage({
id: 'Apis.Details.APIProduct.NewVersion.NewVersion.success',
defaultMessage: 'Successfully created new version ',
}) + newVersion);
})
.catch((error) => {
if (error.status === 409) {
this.setState({ valid: { version: { alreadyExists: true } } });
} else {
Alert.error(intl.formatMessage({
id: 'Apis.Details.APIProduct.NewVersion.NewVersion.error',
defaultMessage: 'Something went wrong while creating a new version!. Error: ',
}) + error.status);
}
});
} else {
apiClient.createNewAPIVersion(api.id, newVersion, isDefaultVersionBool, serviceVersion)
.then((response) => {
this.setState({
redirectToReferrer: true,
apiId: response.obj.id,
});
Alert.info(intl.formatMessage({
id: 'Apis.Details.NewVersion.NewVersion.success',
defaultMessage: 'Successfully created new version ',
}) + newVersion);
})
.catch((error) => {
if (error.status === 409) {
this.setState({ valid: { version: { alreadyExists: true } } });
} else {
Alert.error(intl.formatMessage({
id: 'Apis.Details.NewVersion.NewVersion.error',
defaultMessage: 'Something went wrong while creating a new version!. Error: ',
}) + error.status);
}
});
Alert.info(intl.formatMessage({
id: 'Apis.Details.NewVersion.NewVersion.success',
defaultMessage: 'Successfully created new version ',
}) + newVersion);
})
.catch((error) => {
if (error.status === 409) {
this.setState({ valid: { version: { alreadyExists: true } } });
} else {
Alert.error(intl.formatMessage({
id: 'Apis.Details.NewVersion.NewVersion.error',
defaultMessage: 'Something went wrong while creating a new version!. Error: ',
}) + error.status);
}
});
}
}

/**
Expand Down Expand Up @@ -224,7 +252,7 @@ class CreateNewVersion extends React.Component {
isDefaultVersion, newVersion, redirectToReferrer, apiId, valid, serviceVersion, versionList,
} = this.state;
if (redirectToReferrer) {
return <Redirect to={'/apis/' + apiId + '/overview'} />;
return <Redirect to={(api.apiType === 'APIPRODUCT' ? '/api-products/' : '/apis/') + apiId + '/overview'} />;
}

let helperText = '';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,6 @@ const TryOutConsole = () => {
}
}, [publisherSettings]);

const isAPIProduct = api.apiType === 'APIPRODUCT';
const isAdvertised = api.advertiseInfo && api.advertiseInfo.advertised;
const setServersSpec = (spec, serverUrl) => {
let schemes;
Expand Down Expand Up @@ -186,18 +185,12 @@ const TryOutConsole = () => {
}
if (transportPort !== -1) {
const baseURL = `${transport}://${selectedDeployment.vhost}:${transportPort}`;
let url;
if (isAPIProduct) {
url = `${baseURL}${pathSeparator}`
+ `${selectedDeploymentVhost.httpContext}${api.context}`;
} else {
url = `${baseURL}${pathSeparator}`
let url = `${baseURL}${pathSeparator}`
+ `${selectedDeploymentVhost.httpContext}${api.context}/${api.version}`;
if (`${api.context}`.includes('{version}')) {
url = `${baseURL}${pathSeparator}`
if (`${api.context}`.includes('{version}')) {
url = `${baseURL}${pathSeparator}`
+ `${selectedDeploymentVhost.httpContext}${api.context}`
.replaceAll('{version}', `${api.version}`);
}
}
return {url};
}
Expand All @@ -216,16 +209,15 @@ const TryOutConsole = () => {
}
const host = `${selectedDeploymentVhost.host}:${transportPort}`;
let basePath;
if (isAPIProduct) {
basePath = `${pathSeparator}${selectedDeploymentVhost.httpContext}${api.context}`;
} else {
basePath = `${pathSeparator}${selectedDeploymentVhost.
httpContext}${api.context}/${api.version}`;
if (`${api.context}`.includes('{version}')) {
basePath = `${pathSeparator}${selectedDeploymentVhost.httpContext}${api.context}`
.replaceAll('{version}', `${api.version}`);
}

basePath = `${pathSeparator}${selectedDeploymentVhost.
httpContext}${api.context}/${api.version}`;

if (`${api.context}`.includes('{version}')) {
basePath = `${pathSeparator}${selectedDeploymentVhost
.httpContext}${api.context}`.replaceAll('{version}', `${api.version}`);
}

let schemes = api.transport.slice().sort((a, b) => ((a > b) ? -1 : 1));
if (selectedDeploymentVhost.httpPort === -1){
schemes = schemes.filter(item => item !== 'http');
Expand Down
Loading

0 comments on commit 76667f9

Please sign in to comment.