diff --git a/pom.xml b/pom.xml index 18b9c6c1328..1820fc888d2 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.wso2.carbon.apimgt.ui apim.ui.apps pom - 9.1.13-SNAPSHOT + 9.1.22-SNAPSHOT WSO2 API Manager UI - Parent https://wso2.org diff --git a/portals/admin/pom.xml b/portals/admin/pom.xml index b4781207b69..3aad3612f68 100644 --- a/portals/admin/pom.xml +++ b/portals/admin/pom.xml @@ -20,7 +20,7 @@ org.wso2.carbon.apimgt.ui apim.ui.apps - 9.1.13-SNAPSHOT + 9.1.22-SNAPSHOT ../../pom.xml diff --git a/portals/devportal/pom.xml b/portals/devportal/pom.xml index 4de898d3490..99dc41f3db8 100644 --- a/portals/devportal/pom.xml +++ b/portals/devportal/pom.xml @@ -20,7 +20,7 @@ org.wso2.carbon.apimgt.ui apim.ui.apps - 9.1.13-SNAPSHOT + 9.1.22-SNAPSHOT ../../pom.xml diff --git a/portals/devportal/src/main/webapp/source/src/app/components/Apis/Details/Credentials/Credentials.jsx b/portals/devportal/src/main/webapp/source/src/app/components/Apis/Details/Credentials/Credentials.jsx index 18876896991..281aa2f579f 100755 --- a/portals/devportal/src/main/webapp/source/src/app/components/Apis/Details/Credentials/Credentials.jsx +++ b/portals/devportal/src/main/webapp/source/src/app/components/Apis/Details/Credentials/Credentials.jsx @@ -257,7 +257,16 @@ class Credentials extends React.Component { const { api, applicationsAvailable } = this.context; const { subscriptionRequest } = this.state; const newSubscriptionRequest = { ...subscriptionRequest, apiId: api.id }; - const throttlingPolicyList = api.tiers; + const throttlingPolicyList = api.tiers.sort((a, b) => { + // Sort by 'COMMERCIAL' tier plan first + if (a.tierPlan === 'COMMERCIAL' && b.tierPlan !== 'COMMERCIAL') { + return -1; + } else if (a.tierPlan !== 'COMMERCIAL' && b.tierPlan === 'COMMERCIAL') { + return 1; + } + // For options within the same tier plan, sort alphabetically + return a.tierName.localeCompare(b.tierName); + }); if (throttlingPolicyList && throttlingPolicyList[0]) { newSubscriptionRequest.throttlingPolicy = throttlingPolicyList[0].tierName; } @@ -512,9 +521,7 @@ class Credentials extends React.Component { applicationsAvailable={applicationsAvailable} subscriptionRequest={subscriptionRequest} throttlingPolicyList={throttlingPolicyList} - updateSubscriptionRequest={ - this.updateSubscriptionRequest - } + updateSubscriptionRequest={this.updateSubscriptionRequest} renderSmall /> - +
- + { descriptionType === CONSTS.DESCRIPTION_TYPES.DESCRIPTION ? ( @@ -347,8 +347,8 @@ export default function DescriptionEditor(props) { )}
-
- + + ); } diff --git a/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Configuration/components/Tags.jsx b/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Configuration/components/Tags.jsx index a95d43bf470..3435e19ed4e 100644 --- a/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Configuration/components/Tags.jsx +++ b/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Configuration/components/Tags.jsx @@ -116,8 +116,8 @@ export default function Tags(props) { }} style={{ backgroundColor: (regexPattern.test(value) || value.length > 30) ? red[300] : null, - margin: '0 8px 12px 0', float: 'left', + marginRight: '8px', }} /> )} diff --git a/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Documents/CreateEditForm.jsx b/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Documents/CreateEditForm.jsx index 80db7ea0c54..a6de815e115 100644 --- a/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Documents/CreateEditForm.jsx +++ b/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Documents/CreateEditForm.jsx @@ -166,12 +166,13 @@ class CreateEditForm extends React.Component { sourceUrl: '', file: null, disableName: false, - otherTypeName: null, + otherTypeName: '', nameNotDuplicate: true, nameMaxLengthExceeds: false, invalidUrl: false, nameEmpty: false, summeryEmpty: false, + otherTypeEmpty: false, urlEmpty: false, invalidDocName: false, visibility: 'API_LEVEL' @@ -198,6 +199,7 @@ class CreateEditForm extends React.Component { } } }; + handleChange = name => (e) => { const { value } = e.target; if (name === 'name') { @@ -208,7 +210,7 @@ class CreateEditForm extends React.Component { this.setState({ sourceUrl: value }); } else if (name === 'otherTypeName') { this.setState({ otherTypeName: value }); - }else if (name === 'visibility') { + } else if (name === 'visibility') { this.setState({ visibility: value }); } }; @@ -245,6 +247,7 @@ class CreateEditForm extends React.Component { }); return { docPromise, file }; }; + updateDocument = (apiId) => { const { apiType } = this.props; const restAPI = apiType === Api.CONSTS.APIProduct ? new APIProduct() : new Api(); @@ -264,6 +267,7 @@ class CreateEditForm extends React.Component { }); return { docPromise, file }; }; + getDocument() { const { apiId, docId, apiType } = this.props; const restAPI = apiType === Api.CONSTS.APIProduct ? new APIProduct() : new Api(); @@ -295,6 +299,7 @@ class CreateEditForm extends React.Component { }); } } + validate(field=null, value=null) { let invalidUrl = false; if (field === 'url') { @@ -311,17 +316,17 @@ class CreateEditForm extends React.Component { if (nameValidity === null) { this.setState({ invalidDocName: false }); const promise = APIValidation.apiDocument.validate({ id: this.props.apiId, name: value }); - promise - .then((isDocumentPresent) => { - this.setState({ nameNotDuplicate: !isDocumentPresent }); - }) - .catch((error) => { - if (error.status === 404) { - this.setState({ nameNotDuplicate: true }); - } else { - Alert.error('Error when validating document name'); - } - }); + promise + .then((isDocumentPresent) => { + this.setState({ nameNotDuplicate: !isDocumentPresent }); + }) + .catch((error) => { + if (error.status === 404) { + this.setState({ nameNotDuplicate: true }); + } else { + Alert.error('Error when validating document name'); + } + }); } else { this.setState({ invalidDocName: true }); } @@ -342,8 +347,15 @@ class CreateEditForm extends React.Component { } else { this.setState({ summeryEmpty: false }); } + } else if (field === 'otherTypeName') { + if (value === '') { + this.setState({ otherTypeEmpty: true }); + } else { + this.setState({ otherTypeEmpty: false }); + } } } + componentDidMount() { this.getDocument(); const { apiId, docId } = this.props; @@ -351,6 +363,7 @@ class CreateEditForm extends React.Component { this.setState({ disableName: true }); } } + showNameHelper() { const { nameEmpty, nameNotDuplicate, nameMaxLengthExceeds, invalidDocName } = this.state; if (nameMaxLengthExceeds) { @@ -390,6 +403,7 @@ class CreateEditForm extends React.Component { ); } } + getUrlHelperText() { const { invalidUrl, urlEmpty} = this.state; @@ -416,6 +430,7 @@ class CreateEditForm extends React.Component { ); } } + render() { const { name, @@ -432,6 +447,7 @@ class CreateEditForm extends React.Component { nameEmpty, invalidDocName, summeryEmpty, + otherTypeEmpty, urlEmpty, visibility } = this.state; @@ -440,6 +456,7 @@ class CreateEditForm extends React.Component { if ( name !== '' && summary !== '' && + (otherTypeName !== '' && type === 'OTHER') && nameNotDuplicate && !nameMaxLengthExceeds && !invalidDocName && @@ -527,18 +544,18 @@ class CreateEditForm extends React.Component { {settingsContext.docVisibilityEnabled && - } - helperText={ + helperText={ summeryEmpty ? ( ) } - type='text' - name='visibility' - margin='normal' - value={visibility} - onChange={this.handleChange('visibility')} - error={summeryEmpty} + type='text' + name='visibility' + margin='normal' + value={visibility} + onChange={this.handleChange('visibility')} + error={summeryEmpty} > - - + - - - + + - - - + + - - - } + + + } { + this.validate('otherTypeName', value); + }, + onKeyUp: ({ target: { value } }) => { + this.validate('otherTypeName', value); + }, + }} label={ } helperText={ - + otherTypeEmpty ? ( + + ) : ( + + ) } type='text' id='other-doc-type' name='otherTypeName' margin='normal' value={otherTypeName} + error={otherTypeEmpty} variant='outlined' onChange={this.handleChange('otherTypeName')} InputLabelProps={{ diff --git a/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Documents/Edit.jsx b/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Documents/Edit.jsx index 665d37ee7cb..e3f76ef509c 100644 --- a/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Documents/Edit.jsx +++ b/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Documents/Edit.jsx @@ -45,7 +45,7 @@ const classes = { editMetaButton: `${PREFIX}-editMetaButton` }; -const Root = styled('div')({ +const StyledDialog = styled(Dialog)({ [`& .${classes.appBar}`]: { position: 'relative', }, @@ -68,9 +68,6 @@ const Root = styled('div')({ height: 30, marginLeft: 30, }, - [`& .${classes.editMetaButton}`]: { - whiteSpace: 'nowrap', - }, }); function Transition(props) { @@ -138,11 +135,11 @@ function Edit(props) { const { docId, apiId, docName } = props; return ( - +
- + close @@ -188,8 +185,8 @@ function Edit(props) { setSaveDisabled={setSaveDisabled} />
- -
+ + ); } Edit.propTypes = { diff --git a/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Documents/MarkdownEditor.jsx b/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Documents/MarkdownEditor.jsx index f66e51da3e1..fe4bad2741f 100644 --- a/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Documents/MarkdownEditor.jsx +++ b/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Documents/MarkdownEditor.jsx @@ -50,7 +50,7 @@ const classes = { button: `${PREFIX}-button` }; -const Root = styled('div')({ +const StyledDialog = styled(Dialog)({ [`& .${classes.appBar}`]: { position: 'relative', }, @@ -175,7 +175,7 @@ function MarkdownEditor(props) { const { docName } = props; return ( - +
- + close @@ -257,8 +257,8 @@ function MarkdownEditor(props) {
- -
+ + ); } diff --git a/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Documents/TextEditor.jsx b/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Documents/TextEditor.jsx index 8e230b6381a..740a4377a26 100644 --- a/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Documents/TextEditor.jsx +++ b/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Documents/TextEditor.jsx @@ -50,7 +50,7 @@ const classes = { button: `${PREFIX}-button` }; -const Root = styled('div')({ +const StyledDialog = styled(Dialog)({ [`& .${classes.appBar}`]: { position: 'relative', }, @@ -154,7 +154,7 @@ function TextEditor(props) { const { docName } = props; return ( - +
- + close @@ -196,8 +196,8 @@ function TextEditor(props) { onEditorStateChange={onEditorStateChange} />
- -
+ + ); } diff --git a/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Environments/Environments.jsx b/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Environments/Environments.jsx index e7b54c1cf73..e158e1ca715 100644 --- a/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Environments/Environments.jsx +++ b/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Environments/Environments.jsx @@ -132,11 +132,7 @@ const classes = { }; -const Root = styled('div')(( - { - theme - } -) => ({ +const Root = styled('div')(({ theme }) => ({ [`& .${classes.root}`]: { display: 'flex', flexWrap: 'wrap', @@ -1223,36 +1219,30 @@ export default function Environments() { /> -
- +
+ {revName} - + {revDescription} -
- - {moment(revCreatedTime).fromNow()} - -
+ + {moment(revCreatedTime).fromNow()} +
@@ -1365,15 +1355,12 @@ export default function Environments() { /> -
- +
+ {revName} - + {revDescription} -
- - {moment(revCreatedTime).fromNow()} - -
+ + {moment(revCreatedTime).fromNow()} +
@@ -1428,29 +1413,21 @@ export default function Environments() { /> -
- - {revDescription} - -
+ {revDescription}
@@ -1477,15 +1454,14 @@ export default function Environments() { {item1} {allRevisions[revision].displayName} - {allRevisions[revision].description && <> - - {infoIconItem} - - } + {allRevisions[revision].description && ( + <> + + {infoIconItem} + + )} - + - - :null} - - - - -
+ } + placement='bottom-start' + > + + + + + {!isRestricted(['apim:gateway_policy_manage']) + ? + + + :null} + + + + +
+ ); }; diff --git a/portals/publisher/src/main/webapp/source/src/app/components/GlobalPolicies/Policies/GlobalSpecificComponents/PolicyConfigurationEditDrawer.tsx b/portals/publisher/src/main/webapp/source/src/app/components/GlobalPolicies/Policies/GlobalSpecificComponents/PolicyConfigurationEditDrawer.tsx index bb401daaa80..1c2e26df844 100644 --- a/portals/publisher/src/main/webapp/source/src/app/components/GlobalPolicies/Policies/GlobalSpecificComponents/PolicyConfigurationEditDrawer.tsx +++ b/portals/publisher/src/main/webapp/source/src/app/components/GlobalPolicies/Policies/GlobalSpecificComponents/PolicyConfigurationEditDrawer.tsx @@ -124,6 +124,7 @@ const PolicyConfigurationEditDrawer: FC = ({ open={drawerOpen} onClose={handleDrawerClose} classes={{ paper: classes.drawerPaper }} + sx={{ zIndex: 1300}} > diff --git a/portals/publisher/src/main/webapp/source/src/app/components/GlobalPolicies/Policies/GlobalSpecificComponents/PolicyConfiguringDrawer.tsx b/portals/publisher/src/main/webapp/source/src/app/components/GlobalPolicies/Policies/GlobalSpecificComponents/PolicyConfiguringDrawer.tsx index 7afee05edee..5a07a8d17f2 100644 --- a/portals/publisher/src/main/webapp/source/src/app/components/GlobalPolicies/Policies/GlobalSpecificComponents/PolicyConfiguringDrawer.tsx +++ b/portals/publisher/src/main/webapp/source/src/app/components/GlobalPolicies/Policies/GlobalSpecificComponents/PolicyConfiguringDrawer.tsx @@ -138,6 +138,7 @@ const PolicyConfiguringDrawer: FC = ({ open={drawerOpen} onClose={handleDrawerClose} classes={{ paper: classes.drawerPaper }} + sx={{ zIndex: 1300}} > diff --git a/portals/publisher/src/main/webapp/source/src/app/components/Scopes/EditScope.jsx b/portals/publisher/src/main/webapp/source/src/app/components/Scopes/EditScope.jsx index d9d18538c5e..d2b0eac3b65 100644 --- a/portals/publisher/src/main/webapp/source/src/app/components/Scopes/EditScope.jsx +++ b/portals/publisher/src/main/webapp/source/src/app/components/Scopes/EditScope.jsx @@ -389,15 +389,14 @@ class EditScope extends React.Component { return ; } return ( - - + {/* Following two grids control the placement of whole create page For centering the content better use `container` props, but instead used an empty grid item for flexibility */} - +
diff --git a/portals/publisher/src/main/webapp/source/src/app/components/Scopes/Listing/Listing.jsx b/portals/publisher/src/main/webapp/source/src/app/components/Scopes/Listing/Listing.jsx index f2027ecc38c..2ee3ddd0b36 100644 --- a/portals/publisher/src/main/webapp/source/src/app/components/Scopes/Listing/Listing.jsx +++ b/portals/publisher/src/main/webapp/source/src/app/components/Scopes/Listing/Listing.jsx @@ -62,11 +62,10 @@ const classes = { buttonLeft: `${PREFIX}-buttonLeft` }; -const Root = styled('div')(( - { - theme - } -) => ({ +const Root = styled('div')(({ theme }) => ({ + '&': { + padding: `${theme.spacing(1)} ${theme.spacing(3)}`, + }, [`& .${classes.contentInside}`]: { padding: theme.spacing(3), paddingTop: theme.spacing(2), @@ -196,9 +195,7 @@ function ScopeTablePagination(props) { } return ( - +
@@ -217,7 +214,7 @@ function ScopeTablePagination(props) { size='large'> - +
); } @@ -445,55 +442,57 @@ class Listing extends React.Component { } return ( -
- - - - - - - - {isRestricted(['apim:shared_scope_manage']) && ( - - + + +
+ + + {isRestricted(['apim:shared_scope_manage']) && ( + + + + + + )} + + + + +
+ ); } } diff --git a/portals/publisher/src/main/webapp/source/src/app/components/ServiceCatalog/Listing/Overview.jsx b/portals/publisher/src/main/webapp/source/src/app/components/ServiceCatalog/Listing/Overview.jsx index 1c5c1054f9e..318e9ab68a0 100644 --- a/portals/publisher/src/main/webapp/source/src/app/components/ServiceCatalog/Listing/Overview.jsx +++ b/portals/publisher/src/main/webapp/source/src/app/components/ServiceCatalog/Listing/Overview.jsx @@ -88,12 +88,7 @@ const classes = { editorRoot: `${PREFIX}-editorRoot` }; - -const Root = styled('div')(( - { - theme - } -) => ({ +const Root = styled('div')(({ theme }) => ({ [`& .${classes.preview}`]: { height: theme.spacing(16), marginBottom: theme.spacing(3), @@ -184,10 +179,6 @@ const Root = styled('div')(( marginRight: theme.spacing(1), }, - [`& .${classes.button}`]: { - marginLeft: theme.spacing(2), - }, - [`& .${classes.buttonIcon}`]: { marginRight: theme.spacing(1), }, @@ -195,6 +186,12 @@ const Root = styled('div')(( [`& .${classes.downloadButtonSpacing}`]: { marginLeft: theme.spacing(1), }, +})); + +const StyledDialog = styled(Dialog)(({ theme }) => ({ + [`& .${classes.button}`]: { + marginLeft: theme.spacing(2), + }, [`& .${classes.editorPane}`]: { width: '50%', @@ -624,12 +621,12 @@ function Overview(props) { - - + )} - + diff --git a/portals/publisher/src/main/webapp/source/src/app/components/Shared/ChipInput.js b/portals/publisher/src/main/webapp/source/src/app/components/Shared/ChipInput.js index c77c41e854f..371f0272d3a 100644 --- a/portals/publisher/src/main/webapp/source/src/app/components/Shared/ChipInput.js +++ b/portals/publisher/src/main/webapp/source/src/app/components/Shared/ChipInput.js @@ -81,9 +81,6 @@ const StyledFormControl = styled(FormControl)(({ theme }) => { } }, [`& .${classes.outlined}`]: { - '& input': { - padding: theme.spacing(2), - } }, [`& .${classes.standard}`]: {}, [`& .${classes.filled}`]: { @@ -181,9 +178,6 @@ const StyledFormControl = styled(FormControl)(({ theme }) => { float: 'left' }, [`& .${classes.marginDense}`]: {}, - [`& .MuiChip-root`]: { - margin: '0 !important', - }, }; }); @@ -763,7 +757,7 @@ export const defaultChipRenderer = ({ value, text, isFocused, isDisabled, isRead className={className} style={{ pointerEvents: isDisabled || isReadOnly ? 'none' : undefined, - backgroundColor: isFocused ? blue[300] : undefined + backgroundColor: isFocused ? blue[300] : undefined, }} onClick={handleClick} onDelete={handleDelete} diff --git a/portals/publisher/src/main/webapp/source/src/app/data/APIValidation.js b/portals/publisher/src/main/webapp/source/src/app/data/APIValidation.js index 964d4242914..50d16a0492a 100644 --- a/portals/publisher/src/main/webapp/source/src/app/data/APIValidation.js +++ b/portals/publisher/src/main/webapp/source/src/app/data/APIValidation.js @@ -138,7 +138,11 @@ const definition = { }); return tmpErrors; }), - apiContext: Joi.string().max(200).regex(/(?!.*\/t\/.*|.*\/t$)^[^~!@#:%^&*+=|\\<>"',&\s[\]]*$/).required() + apiContext: Joi.string().max(200).regex(/(?!.*\/t\/.*|.*\/t$)^[^`~!@#?:%^&*+=|\\<>"',&\s[\]]*$/).required() + .error((errors) => { + return errors.map((error) => ({ ...error, message: 'Context ' + getMessage(error.type, 200) })); + }), + apiContextWithoutKeyWords: Joi.string().max(200).regex(/^[^{}]*$/).required() .error((errors) => { return errors.map((error) => ({ ...error, message: 'Context ' + getMessage(error.type, false, 200) })); }), diff --git a/portals/publisher/src/main/webapp/source/src/app/data/api.js b/portals/publisher/src/main/webapp/source/src/app/data/api.js index 4f492e031a8..b5c123e1059 100644 --- a/portals/publisher/src/main/webapp/source/src/app/data/api.js +++ b/portals/publisher/src/main/webapp/source/src/app/data/api.js @@ -167,6 +167,26 @@ class API extends Resource { return promisedValidate; } + static validateOpenAPIByInlineDefinition(openAPIData) { + const apiClient = new APIClientFactory().getAPIClient(Utils.getCurrentEnvironment(), Utils.CONST.API_CLIENT).client; + let payload, promisedValidate; + payload = { + inlineAPIDefinition: openAPIData, + }; + const requestBody = { + requestBody: { + inlineAPIDefinition: openAPIData, + }, + }; + promisedValidate = apiClient.then(client => { + return client.apis.Validation.validateOpenAPIDefinition( + payload, + requestBody + ); + }); + return promisedValidate; + } + static validateOpenAPIByUrl(url, params = { returnContent: false }) { const apiClient = new APIClientFactory().getAPIClient(Utils.getCurrentEnvironment(), Utils.CONST.API_CLIENT).client; const payload = {