From 7aa2c32e729280685d12332a67e0ec6251a74ba1 Mon Sep 17 00:00:00 2001 From: shnrndk Date: Mon, 27 Nov 2023 17:05:13 +0530 Subject: [PATCH 01/19] Change Api Provider Screen Added (cherry picked from commit ff9008a18c7054368ead9682d66d145c50809eae) --- .../main/webapp/site/public/locales/en.json | 13 + .../main/webapp/site/public/locales/fr.json | 14 + .../APISettings/ApisTableContent.jsx | 163 ++++++++++ .../components/APISettings/ApisTableHead.jsx | 102 +++++++ .../app/components/APISettings/EditApi.jsx | 208 +++++++++++++ .../app/components/APISettings/ListApis.jsx | 281 ++++++++++++++++++ .../app/components/Base/RouteMenuMapping.jsx | 10 + 7 files changed, 791 insertions(+) create mode 100644 portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx create mode 100644 portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableHead.jsx create mode 100644 portals/admin/src/main/webapp/source/src/app/components/APISettings/EditApi.jsx create mode 100644 portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx diff --git a/portals/admin/src/main/webapp/site/public/locales/en.json b/portals/admin/src/main/webapp/site/public/locales/en.json index 8fbe43ca97f..52ae05f5dc5 100644 --- a/portals/admin/src/main/webapp/site/public/locales/en.json +++ b/portals/admin/src/main/webapp/site/public/locales/en.json @@ -62,6 +62,9 @@ "AdminPages.ApiCategories.table.header.category.description": "Description", "AdminPages.ApiCategories.table.header.category.name": "Category Name", "AdminPages.ApiCategories.table.header.category.number.of.apis": "Number of APIs", + "AdminPages.ApiSettings.EditApi.form.edit.successful": "Api owner changed successfully", + "AdminPages.ApiSettings.EditApi.form.helperText": "Enter a new Owner. Make sure the new owner has logged into the Developer Portal at least once", + "AdminPages.ApiSettings.EditApi.form.name": "Api Name", "AdminPages.ApplicationSettings.Edit.form.edit.successful": "Application owner changed successfully", "AdminPages.ApplicationSettings.Edit.form.helperText": "Enter a new Owner. Make sure the new owner has logged into the Developer Portal at least once", "AdminPages.ApplicationSettings.Edit.form.name": "Application Name", @@ -84,6 +87,15 @@ "AdminPagesGatewayEnvironments.AddEditGWEnvironment.form.environment.vhost.empty": "VHost is empty", "Apis.Details.Scopes.CreateScope.roles.help": "Enter a valid role and press `Enter`.", "Apis.Details.Scopes.Roles.Invalid": "A Role is invalid", + "Apis.Listing.Listing.apis.search": "Search", + "Apis.Listing.Listing.apis.search.label": "Search Api by Api Owner", + "Apis.Listing.Listing.apis.searching": "Searching", + "Apis.Listing.Listing.clear.search": "Clear Search", + "Apis.Listing.Listing.empty.message": "No Data to Display", + "Apis.Listing.Listing.search.placeholder": "Api Owner", + "Apis.Listing.apiTableHead.actions": "Actions", + "Apis.Listing.apiTableHead.name": "Name", + "Apis.Listing.apiTableHead.owner": "Owner", "Apis.Shared.AdminRootErrorBoundary.refresh": "Refresh", "Apis.Shared.AdminRootErrorBoundary.refresh.or.try.again.message": "You may refresh the page now or try again later", "Apis.Shared.AdminRootErrorBoundary.something.went.wrong.while.rendering.button": "Something went wrong while rendering the", @@ -119,6 +131,7 @@ "Base.RouteMenuMapping.application.deletion": "Application Deletion", "Base.RouteMenuMapping.application.throttling.policies": "Application Policies", "Base.RouteMenuMapping.applications": "Applications", + "Base.RouteMenuMapping.apps": "Apps", "Base.RouteMenuMapping.blacklisted.items": "Deny Policies", "Base.RouteMenuMapping.custom.throttling.policies": "Custom Policies", "Base.RouteMenuMapping.custom.throttling.policies.items.Adding": "Add Custom Policy", diff --git a/portals/admin/src/main/webapp/site/public/locales/fr.json b/portals/admin/src/main/webapp/site/public/locales/fr.json index dbb9e9608d3..b0911044fb5 100644 --- a/portals/admin/src/main/webapp/site/public/locales/fr.json +++ b/portals/admin/src/main/webapp/site/public/locales/fr.json @@ -62,6 +62,9 @@ "AdminPages.ApiCategories.table.header.category.description": "", "AdminPages.ApiCategories.table.header.category.name": "", "AdminPages.ApiCategories.table.header.category.number.of.apis": "", + "AdminPages.ApiSettings.EditApi.form.edit.successful": "", + "AdminPages.ApiSettings.EditApi.form.helperText": "", + "AdminPages.ApiSettings.EditApi.form.name": "", "AdminPages.ApplicationSettings.Edit.form.edit.successful": "", "AdminPages.ApplicationSettings.Edit.form.helperText": "", "AdminPages.ApplicationSettings.Edit.form.name": "", @@ -84,6 +87,15 @@ "AdminPagesGatewayEnvironments.AddEditGWEnvironment.form.environment.vhost.empty": "", "Apis.Details.Scopes.CreateScope.roles.help": "", "Apis.Details.Scopes.Roles.Invalid": "", + "Apis.Listing.Listing.apis.search": "", + "Apis.Listing.Listing.apis.search.label": "", + "Apis.Listing.Listing.apis.searching": "", + "Apis.Listing.Listing.clear.search": "", + "Apis.Listing.Listing.empty.message": "", + "Apis.Listing.Listing.search.placeholder": "", + "Apis.Listing.apiTableHead.actions": "", + "Apis.Listing.apiTableHead.name": "", + "Apis.Listing.apiTableHead.owner": "", "Apis.Shared.AdminRootErrorBoundary.refresh": "", "Apis.Shared.AdminRootErrorBoundary.refresh.or.try.again.message": "", "Apis.Shared.AdminRootErrorBoundary.something.went.wrong.while.rendering.button": "", @@ -119,6 +131,7 @@ "Base.RouteMenuMapping.application.deletion": "", "Base.RouteMenuMapping.application.throttling.policies": "", "Base.RouteMenuMapping.applications": "", + "Base.RouteMenuMapping.apps": "", "Base.RouteMenuMapping.blacklisted.items": "", "Base.RouteMenuMapping.custom.throttling.policies": "", "Base.RouteMenuMapping.custom.throttling.policies.items.Adding": "", @@ -347,6 +360,7 @@ "Manage.Alerts.unsubscribe.success.msg": "", "RolePermissions.Common.AddRoleWizard.add.mapping.button": "", "RolePermissions.Common.AddRoleWizard.add.mapping.title": "", + "RolePermissions.Common.AddRoleWizard.add.role.warn.empty": "", "RolePermissions.Common.AddRoleWizard.add.scope.error": "", "RolePermissions.Common.DeletePermission.delete.scope.error": "", "RolePermissions.ListRoles.error.retrieving.perm": "", diff --git a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx new file mode 100644 index 00000000000..19f783a5d7b --- /dev/null +++ b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file 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 CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { Component } from 'react'; +import TableBody from '@material-ui/core/TableBody'; +import TableCell from '@material-ui/core/TableCell'; +import TableRow from '@material-ui/core/TableRow'; +import ResourceNotFound from 'AppComponents/Base/Errors/ResourceNotFound'; +import PropTypes from 'prop-types'; +import { withStyles } from '@material-ui/core/styles'; +import EditApi from 'AppComponents/APISettings/EditApi'; +/** + * @inheritdoc + * @param {*} theme theme object + */ +const styles = (theme) => ({ + fullHeight: { + height: '100%', + }, + tableRow: { + height: theme.spacing(5), + '& td': { + padding: theme.spacing(0.5), + }, + }, + appOwner: { + pointerEvents: 'none', + }, + appName: { + '& a': { + color: '#1b9ec7 !important', + }, + }, + appTablePaper: { + '& table tr td': { + paddingLeft: theme.spacing(1), + }, + '& table tr td:first-child, & table tr th:first-child': { + paddingLeft: theme.spacing(2), + }, + '& table tr td button.Mui-disabled span.material-icons': { + color: theme.palette.action.disabled, + }, + }, + tableCellWrapper: { + '& td': { + 'word-break': 'break-all', + 'white-space': 'normal', + }, + }, +}); +const StyledTableCell = withStyles((theme) => ({ + head: { + backgroundColor: theme.palette.common.black, + color: theme.palette.common.white, + }, + body: { + fontSize: 14, + }, + root: { + '&:first-child': { + paddingLeft: theme.spacing(2), + }, + }, +}))(TableCell); + +const StyledTableRow = withStyles((theme) => ({ + root: { + '&:nth-of-type(odd)': { + backgroundColor: theme.palette.background.default, + }, + }, +}))(TableRow); + +/** + * + * + * @class ApisTableContent + * @extends {Component} + */ +class ApisTableContent extends Component { + /** + * @inheritdoc + */ + constructor(props) { + super(props); + this.state = { + notFound: false, + }; + this.handleAppEdit = this.handleAppEdit.bind(this); + } + + handleAppEdit = (app) => { + const { EditComponent, editComponentProps, apiCall } = this.props; + return ( + <> + {EditComponent && ( + + )} + + ); + }; + + /** + * @inheritdoc + * @memberof ApisTableContent + */ + render() { + const { + apps, classes, editComponentProps, apiCall, + } = this.props; + const { notFound } = this.state; + + if (notFound) { + return ; + } + return ( + + {apps && apps.map((app) => { + return ( + + + {app.name} + + {app.owner} + + + + + ); + })} + + ); + } +} +ApisTableContent.propTypes = { + toggleDeleteConfirmation: PropTypes.func.isRequired, + apps: PropTypes.instanceOf(Map).isRequired, +}; +export default withStyles(styles)(ApisTableContent); diff --git a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableHead.jsx b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableHead.jsx new file mode 100644 index 00000000000..53e00fb6664 --- /dev/null +++ b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableHead.jsx @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file 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 CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import PropTypes from 'prop-types'; +import TableCell from '@material-ui/core/TableCell'; +import TableHead from '@material-ui/core/TableHead'; +import TableRow from '@material-ui/core/TableRow'; +import TableSortLabel from '@material-ui/core/TableSortLabel'; +import { FormattedMessage } from 'react-intl'; + +/** + * @inheritdoc + * @class apiTableHead + * @extends {Component} + */ +const apisTableHead = (props) => { + const createSortHandler = (property) => (event) => { + props.onRequestSort(event, property); + }; + const columnData = [ + { + id: 'name', + numeric: false, + disablePadding: true, + label: (), + sorting: true, + }, + { + id: 'owner', + numeric: false, + disablePadding: false, + label: (), + sorting: true, + }, + { + id: 'actions', + numeric: false, + disablePadding: false, + label: (), + sorting: false, + }, + ]; + const { order, orderBy } = props; + return ( + + + {columnData.map((column) => { + return ( + + {column.sorting ? ( + + {column.label} + + ) : ( + column.label + )} + + ); + })} + + + ); +}; +apisTableHead.propTypes = { + onRequestSort: PropTypes.func.isRequired, + order: PropTypes.string.isRequired, + orderBy: PropTypes.string.isRequired, +}; +export default apisTableHead; diff --git a/portals/admin/src/main/webapp/source/src/app/components/APISettings/EditApi.jsx b/portals/admin/src/main/webapp/source/src/app/components/APISettings/EditApi.jsx new file mode 100644 index 00000000000..cfd38b04db2 --- /dev/null +++ b/portals/admin/src/main/webapp/source/src/app/components/APISettings/EditApi.jsx @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file 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 CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { useReducer, useEffect, useState } from 'react'; +import API from 'AppData/api'; +import PropTypes from 'prop-types'; +import TextField from '@material-ui/core/TextField'; +import { FormattedMessage } from 'react-intl'; +import { makeStyles } from '@material-ui/core/styles'; +import FormDialogBase from 'AppComponents/AdminPages/Addons/FormDialogBase'; + +const useStyles = makeStyles((theme) => ({ + error: { + color: theme.palette.error.dark, + }, +})); + +/** + * Reducer + * @param {JSON} state State + * @returns {Promise}. + */ +function reducer(state, { field, value }) { + switch (field) { + case 'name': + case 'owner': + return { ...state, [field]: value }; + case 'editDetails': + return value; + default: + return state; + } +} +/** + * Render a pop-up dialog to change ownership of an Api + * @param {JSON} props props passed from parent + * @returns {JSX}. + */ +function EditApi(props) { + const classes = useStyles(); + const restApi = new API(); + const { + updateList, dataRow, icon, triggerButtonText, title, apiList, + } = props; + const [initialState, setInitialState] = useState({ + name: '', + owner: '', + }); + + const [state, dispatch] = useReducer(reducer, initialState); + const { name, owner } = state; + + useEffect(() => { + setInitialState({ + name: '', + owner: '', + }); + }, []); + const onChange = (e) => { + dispatch({ field: e.target.name, value: e.target.value }); + }; + + const validateOwner = () => { + let validationError = 'Something went wrong when validating user'; + + const apisWithSameName = apiList.filter( + (app) => app.name === name && app.owner === owner, + ); + + const promiseValidation = new Promise((resolve, reject) => { + if (apisWithSameName.length > 0) { + validationError = `${owner} already has an api with name: ${name}`; + reject(validationError); + } + const basicScope = 'apim:subscribe'; + restApi.getUserScope(owner, basicScope) + .then(() => { + // This api returns 200 when only the $owner has the $basicScope. + resolve(); + }).catch((error) => { + const { response } = error; + // This api returns 404 when the $owner is not found. + // error codes: 901502, 901500 for user not found and scope not found + if (response?.body?.code === 901502 || response?.body?.code === 901500) { + validationError = `${owner} is not a valid Subscriber`; + } + }).finally(() => { + if (validationError) { + reject(validationError); + } + }); + }); + + return promiseValidation; + }; + + const formSaveCallback = () => { + return validateOwner().then(() => { + return restApi.updateApiOwner(dataRow.apiId, owner) + .then(() => { + return ( + + ); + }) + .catch((error) => { + const { response } = error; + if (response?.body?.code === 500) { + const notValidSubscriber = 'Error while updating ownership to ' + owner; + throw notValidSubscriber; + } else { + const updateError = 'Something went wrong when updating owner'; + throw updateError; + } + }) + .finally(() => { + updateList(); + }); + }); + }; + const dialogOpenCallback = () => { + if (dataRow) { + const { name: originalName, owner: originalOwner } = dataRow; + dispatch({ field: 'editDetails', value: { name: originalName, owner: originalOwner } }); + } + }; + return ( + + + + * + + )} + fullWidth + variant='outlined' + disabled + /> + + )} + variant='outlined' + /> + + ); +} + +EditApi.defaultProps = { + icon: null, +}; + +EditApi.propTypes = { + updateList: PropTypes.func.isRequired, + dataRow: PropTypes.shape({ + apiId: PropTypes.string.isRequired, + owner: PropTypes.string.isRequired, + name: PropTypes.string.isRequired, + }).isRequired, + icon: PropTypes.element, + triggerButtonText: PropTypes.shape({}).isRequired, + title: PropTypes.shape({}).isRequired, + apiList: PropTypes.shape([]).isRequired, +}; + +export default EditApi; diff --git a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx new file mode 100644 index 00000000000..a4b9356ecbc --- /dev/null +++ b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx @@ -0,0 +1,281 @@ +/* + * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file 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 CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { useEffect, useState } from 'react'; +import { makeStyles } from '@material-ui/core/styles'; +import API from 'AppData/api'; +import { useIntl, FormattedMessage } from 'react-intl'; +import EditApi from 'AppComponents/APISettings/EditApi'; +import ApisTableContent from 'AppComponents/APISettings/ApisTableContent'; +import ApisTableHead from 'AppComponents/APISettings/ApisTableHead'; +import EditIcon from '@material-ui/icons/Edit'; +import Table from '@material-ui/core/Table'; +import ContentBase from 'AppComponents/AdminPages/Addons/ContentBase'; +import TableFooter from '@material-ui/core/TableFooter'; +import TablePagination from '@material-ui/core/TablePagination'; +import TableRow from '@material-ui/core/TableRow'; +import AppBar from '@material-ui/core/AppBar'; +import Toolbar from '@material-ui/core/Toolbar'; +import Box from '@material-ui/core/Box'; +import Grid from '@material-ui/core/Grid'; +import Button from '@material-ui/core/Button'; +import IconButton from '@material-ui/core/IconButton'; +import HighlightOffRoundedIcon from '@material-ui/icons/HighlightOffRounded'; +import Tooltip from '@material-ui/core/Tooltip'; +import TextField from '@material-ui/core/TextField'; +import SearchIcon from '@material-ui/icons/Search'; +import Alert from '@material-ui/lab/Alert'; +import Typography from '@material-ui/core/Typography'; + +/** + * Render a list + * @returns {JSX} Header AppBar components. + */ + +const useStyles = makeStyles((theme) => ({ + searchBar: { + borderBottom: '1px solid rgba(0, 0, 0, 0.12)', + }, + block: { + display: 'block', + }, + clearSearch: { + position: 'absolute', + right: 111, + top: 13, + }, + addUser: { + marginRight: theme.spacing(1), + }, +})); + +export default function ListApis() { + const intl = useIntl(); + const classes = useStyles(); + const [loading, setLoading] = useState(false); + const [apiList, setApiList] = useState(null); + const [totalApps, setTotalApps] = useState(0); + const [rowsPerPage, setRowsPerPage] = useState(10); + const [page, setPage] = useState(0); + const [owner, setOwner] = useState(''); + + /** + * API call to get api list + * @returns {Promise}. + */ + function apiCall(pageNo, user = owner) { + setLoading(true); + const restApi = new API(); + return restApi + .getApplicationList({ limit: rowsPerPage, offset: pageNo * rowsPerPage, user }) + .then((result) => { + setApiList(result.body.list); + const { pagination: { total } } = result.body; + setTotalApps(total); + return result.body.list; + }) + .catch((error) => { + throw error; + }) + .finally(() => { + setLoading(false); + }); + } + + useEffect(() => { + apiCall(page).then((result) => { + setApiList(result); + }); + }, [page]); + + useEffect(() => { + apiCall(page).then((result) => { + setApiList(result); + }); + }, [rowsPerPage]); + + function handleChangePage(event, pageNo) { + setPage(pageNo); + apiCall(pageNo).then((result) => { + setApiList(result); + }); + } + + function handleChangeRowsPerPage(event) { + const nextRowsPerPage = event.target.value; + const rowsPerPageRatio = rowsPerPage / nextRowsPerPage; + const nextPage = Math.floor(page * rowsPerPageRatio); + setPage(nextPage); + setRowsPerPage(nextRowsPerPage); + apiCall(page).then((result) => { + setApiList(result); + }); + } + + function clearSearch() { + setPage(0); + setOwner(''); + apiCall(page, '').then((result) => { + setApiList(result); + }); + } + + function setQuery(event) { + const newQuery = event.target.value; + if (newQuery === '') { + clearSearch(); + } else { + setOwner(newQuery); + } + } + + function filterApps(e) { + e.preventDefault(); + setPage(0); + apiCall(page).then((result) => { + setApiList(result); + }); + } + + return ( + + + +
+ + + + + + + { owner.length > 0 + && ( + + + + + + )} + + + + + +
+
+
+ {apiList && apiList.length > 0 + && ( + + + , + title: 'Change Api Owner', + apiList, + }} + EditComponent={EditApi} + apiCall={apiCall} + /> + + + + + +
+ )} + {apiList && apiList.length === 0 && !loading && ( + + + + + + + + )} +
+ ); +} diff --git a/portals/admin/src/main/webapp/source/src/app/components/Base/RouteMenuMapping.jsx b/portals/admin/src/main/webapp/source/src/app/components/Base/RouteMenuMapping.jsx index 5d4d00fceea..6a2706918a6 100644 --- a/portals/admin/src/main/webapp/source/src/app/components/Base/RouteMenuMapping.jsx +++ b/portals/admin/src/main/webapp/source/src/app/components/Base/RouteMenuMapping.jsx @@ -56,6 +56,7 @@ import SecurityIcon from '@material-ui/icons/Security'; import TouchAppIcon from '@material-ui/icons/TouchApp'; import VpnKeyIcon from '@material-ui/icons/VpnKey'; import AccountTreeIcon from '@material-ui/icons/AccountTree'; +import ListApis from '../APISettings/ListApis'; const RouteMenuMapping = (intl) => [ { @@ -307,6 +308,15 @@ const RouteMenuMapping = (intl) => [ component: ListApplications, icon: , }, + { + id: intl.formatMessage({ + id: 'Base.RouteMenuMapping.apis', + defaultMessage: 'Apis', + }), + path: '/settings/apis', + component: ListApis, + icon: , + }, { id: intl.formatMessage({ id: 'Base.RouteMenuMapping.role.permissions', From e3cb8aa34ab349924a2f586c69bd31c9a10636aa Mon Sep 17 00:00:00 2001 From: shnrndk Date: Tue, 28 Nov 2023 10:02:46 +0530 Subject: [PATCH 02/19] Add change api provider and get all apis rest api. --- .../main/webapp/site/public/locales/en.json | 9 +- .../APISettings/ApisTableContent.jsx | 2 +- .../components/APISettings/ApisTableHead.jsx | 6 +- .../app/components/APISettings/EditApi.jsx | 88 +++++++++---------- .../app/components/APISettings/ListApis.jsx | 20 ++--- .../main/webapp/source/src/app/data/api.js | 23 +++++ 6 files changed, 85 insertions(+), 63 deletions(-) diff --git a/portals/admin/src/main/webapp/site/public/locales/en.json b/portals/admin/src/main/webapp/site/public/locales/en.json index 52ae05f5dc5..c0d04c740cf 100644 --- a/portals/admin/src/main/webapp/site/public/locales/en.json +++ b/portals/admin/src/main/webapp/site/public/locales/en.json @@ -88,14 +88,14 @@ "Apis.Details.Scopes.CreateScope.roles.help": "Enter a valid role and press `Enter`.", "Apis.Details.Scopes.Roles.Invalid": "A Role is invalid", "Apis.Listing.Listing.apis.search": "Search", - "Apis.Listing.Listing.apis.search.label": "Search Api by Api Owner", + "Apis.Listing.Listing.apis.search.label": "Search Api by Api Provider", "Apis.Listing.Listing.apis.searching": "Searching", "Apis.Listing.Listing.clear.search": "Clear Search", "Apis.Listing.Listing.empty.message": "No Data to Display", - "Apis.Listing.Listing.search.placeholder": "Api Owner", + "Apis.Listing.Listing.search.placeholder": "Api Provider", "Apis.Listing.apiTableHead.actions": "Actions", "Apis.Listing.apiTableHead.name": "Name", - "Apis.Listing.apiTableHead.owner": "Owner", + "Apis.Listing.apiTableHead.provider": "Provider", "Apis.Shared.AdminRootErrorBoundary.refresh": "Refresh", "Apis.Shared.AdminRootErrorBoundary.refresh.or.try.again.message": "You may refresh the page now or try again later", "Apis.Shared.AdminRootErrorBoundary.something.went.wrong.while.rendering.button": "Something went wrong while rendering the", @@ -130,7 +130,8 @@ "Base.RouteMenuMapping.application.creation": "Application Creation", "Base.RouteMenuMapping.application.deletion": "Application Deletion", "Base.RouteMenuMapping.application.throttling.policies": "Application Policies", - "Base.RouteMenuMapping.applications": "Applications", + "Base.RouteMenuMapping.applications": "Change Application Owner", + "Base.RouteMenuMapping.apis": "Change Api Provder", "Base.RouteMenuMapping.apps": "Apps", "Base.RouteMenuMapping.blacklisted.items": "Deny Policies", "Base.RouteMenuMapping.custom.throttling.policies": "Custom Policies", diff --git a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx index 19f783a5d7b..5ef97e46308 100644 --- a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx +++ b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx @@ -141,7 +141,7 @@ class ApisTableContent extends Component { {app.name} - {app.owner} + {app.provider} { sorting: true, }, { - id: 'owner', + id: 'provider', numeric: false, disablePadding: false, label: (), sorting: true, }, diff --git a/portals/admin/src/main/webapp/source/src/app/components/APISettings/EditApi.jsx b/portals/admin/src/main/webapp/source/src/app/components/APISettings/EditApi.jsx index cfd38b04db2..183b96427c8 100644 --- a/portals/admin/src/main/webapp/source/src/app/components/APISettings/EditApi.jsx +++ b/portals/admin/src/main/webapp/source/src/app/components/APISettings/EditApi.jsx @@ -38,7 +38,7 @@ const useStyles = makeStyles((theme) => ({ function reducer(state, { field, value }) { switch (field) { case 'name': - case 'owner': + case 'provider': return { ...state, [field]: value }; case 'editDetails': return value; @@ -47,7 +47,7 @@ function reducer(state, { field, value }) { } } /** - * Render a pop-up dialog to change ownership of an Api + * Render a pop-up dialog to change providership of an Api * @param {JSON} props props passed from parent * @returns {JSX}. */ @@ -59,45 +59,45 @@ function EditApi(props) { } = props; const [initialState, setInitialState] = useState({ name: '', - owner: '', + provider: '', }); const [state, dispatch] = useReducer(reducer, initialState); - const { name, owner } = state; + const { name, provider } = state; useEffect(() => { setInitialState({ name: '', - owner: '', + provider: '', }); }, []); const onChange = (e) => { dispatch({ field: e.target.name, value: e.target.value }); }; - const validateOwner = () => { + const validateProvider = () => { let validationError = 'Something went wrong when validating user'; const apisWithSameName = apiList.filter( - (app) => app.name === name && app.owner === owner, + (app) => app.name === name && app.provider === provider, ); const promiseValidation = new Promise((resolve, reject) => { if (apisWithSameName.length > 0) { - validationError = `${owner} already has an api with name: ${name}`; + validationError = `${provider} already has an api with name: ${name}`; reject(validationError); } const basicScope = 'apim:subscribe'; - restApi.getUserScope(owner, basicScope) + restApi.getUserScope(provider, basicScope) .then(() => { - // This api returns 200 when only the $owner has the $basicScope. + // This api returns 200 when only the $provider has the $basicScope. resolve(); }).catch((error) => { const { response } = error; - // This api returns 404 when the $owner is not found. + // This api returns 404 when the $provider is not found. // error codes: 901502, 901500 for user not found and scope not found if (response?.body?.code === 901502 || response?.body?.code === 901500) { - validationError = `${owner} is not a valid Subscriber`; + validationError = `${provider} is not a valid Subscriber`; } }).finally(() => { if (validationError) { @@ -110,35 +110,33 @@ function EditApi(props) { }; const formSaveCallback = () => { - return validateOwner().then(() => { - return restApi.updateApiOwner(dataRow.apiId, owner) - .then(() => { - return ( - - ); - }) - .catch((error) => { - const { response } = error; - if (response?.body?.code === 500) { - const notValidSubscriber = 'Error while updating ownership to ' + owner; - throw notValidSubscriber; - } else { - const updateError = 'Something went wrong when updating owner'; - throw updateError; - } - }) - .finally(() => { - updateList(); - }); - }); + return restApi.updateApiProvider(dataRow.id, provider) + .then(() => { + return ( + + ); + }) + .catch((error) => { + const { response } = error; + if (response?.body?.code === 500) { + const notValidSubscriber = 'Error while updating providership to ' + provider; + throw notValidSubscriber; + } else { + const updateError = 'Something went wrong when updating provider'; + throw updateError; + } + }) + .finally(() => { + updateList(); + }); }; const dialogOpenCallback = () => { if (dataRow) { - const { name: originalName, owner: originalOwner } = dataRow; - dispatch({ field: 'editDetails', value: { name: originalName, owner: originalOwner } }); + const { name: originalName, provider: originalProvider } = dataRow; + dispatch({ field: 'editDetails', value: { name: originalName, provider: originalProvider } }); } }; return ( @@ -170,16 +168,16 @@ function EditApi(props) { )} variant='outlined' @@ -195,8 +193,8 @@ EditApi.defaultProps = { EditApi.propTypes = { updateList: PropTypes.func.isRequired, dataRow: PropTypes.shape({ - apiId: PropTypes.string.isRequired, - owner: PropTypes.string.isRequired, + id: PropTypes.string.isRequired, + provider: PropTypes.string.isRequired, name: PropTypes.string.isRequired, }).isRequired, icon: PropTypes.element, diff --git a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx index a4b9356ecbc..4ee40589b24 100644 --- a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx +++ b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx @@ -72,17 +72,17 @@ export default function ListApis() { const [totalApps, setTotalApps] = useState(0); const [rowsPerPage, setRowsPerPage] = useState(10); const [page, setPage] = useState(0); - const [owner, setOwner] = useState(''); + const [provider, setProvider] = useState(''); /** * API call to get api list * @returns {Promise}. */ - function apiCall(pageNo, user = owner) { + function apiCall(pageNo, user = provider) { setLoading(true); const restApi = new API(); return restApi - .getApplicationList({ limit: rowsPerPage, offset: pageNo * rowsPerPage, user }) + .getApiList({ limit: rowsPerPage, offset: pageNo * rowsPerPage, user }) .then((result) => { setApiList(result.body.list); const { pagination: { total } } = result.body; @@ -129,7 +129,7 @@ export default function ListApis() { function clearSearch() { setPage(0); - setOwner(''); + setProvider(''); apiCall(page, '').then((result) => { setApiList(result); }); @@ -140,7 +140,7 @@ export default function ListApis() { if (newQuery === '') { clearSearch(); } else { - setOwner(newQuery); + setProvider(newQuery); } } @@ -166,22 +166,22 @@ export default function ListApis() { fullWidth id='search-label' label={intl.formatMessage({ - defaultMessage: 'Search Api by Api Owner', + defaultMessage: 'Search Api by Api Provider', id: 'Apis.Listing.Listing.apis.search.label', })} placeholder={intl.formatMessage({ - defaultMessage: 'Api Owner', + defaultMessage: 'Api Provider', id: 'Apis.Listing.Listing.search.placeholder', })} InputProps={{ disableUnderline: true, className: classes.searchInput, }} - value={owner} + value={provider} onChange={setQuery} // onKeyPress={this.handleSearchKeyPress} /> - { owner.length > 0 + { provider.length > 0 && ( , - title: 'Change Api Owner', + title: 'Change Api Provider', apiList, }} EditComponent={EditApi} diff --git a/portals/admin/src/main/webapp/source/src/app/data/api.js b/portals/admin/src/main/webapp/source/src/app/data/api.js index 305510cbe41..ae41917de76 100644 --- a/portals/admin/src/main/webapp/source/src/app/data/api.js +++ b/portals/admin/src/main/webapp/source/src/app/data/api.js @@ -420,6 +420,17 @@ class API extends Resource { }); } + /** + * Get a list of apis from all users + */ + getApiList(params) { + return this.client.then((client) => { + return client.apis['APIs'].getAllAPIs( + params, this._requestMetaData(), + ); + }); + } + /** * Get Subscription Throttling Policies */ @@ -445,6 +456,18 @@ class API extends Resource { }); } + /** + * Update an api's owner + */ + updateApiProvider(apiId, provider) { + return this.client.then((client) => { + return client.apis["Api Provider Change"].providerProviderNameApisApiIdPut( + { providerName: provider, apiId: apiId }, + this._requestMetaData(), + ); + }); + } + /** * Get a list of available Gateway Environments */ From d57e2af403f1f90d44c7ec965ef75f6a20ded518 Mon Sep 17 00:00:00 2001 From: shnrndk Date: Tue, 28 Nov 2023 11:25:07 +0530 Subject: [PATCH 03/19] User validation and Api Version Column added --- .../APISettings/ApisTableContent.jsx | 1 + .../components/APISettings/ApisTableHead.jsx | 10 ++++ .../app/components/APISettings/EditApi.jsx | 46 ++++--------------- 3 files changed, 20 insertions(+), 37 deletions(-) diff --git a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx index 5ef97e46308..909aff1bfbd 100644 --- a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx +++ b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx @@ -141,6 +141,7 @@ class ApisTableContent extends Component { {app.name} + {app.version} {app.provider} { />), sorting: true, }, + { + id: 'version', + numeric: false, + disablePadding: true, + label: (), + sorting: true, + }, { id: 'provider', numeric: false, diff --git a/portals/admin/src/main/webapp/source/src/app/components/APISettings/EditApi.jsx b/portals/admin/src/main/webapp/source/src/app/components/APISettings/EditApi.jsx index 183b96427c8..05edb617c7a 100644 --- a/portals/admin/src/main/webapp/source/src/app/components/APISettings/EditApi.jsx +++ b/portals/admin/src/main/webapp/source/src/app/components/APISettings/EditApi.jsx @@ -75,40 +75,6 @@ function EditApi(props) { dispatch({ field: e.target.name, value: e.target.value }); }; - const validateProvider = () => { - let validationError = 'Something went wrong when validating user'; - - const apisWithSameName = apiList.filter( - (app) => app.name === name && app.provider === provider, - ); - - const promiseValidation = new Promise((resolve, reject) => { - if (apisWithSameName.length > 0) { - validationError = `${provider} already has an api with name: ${name}`; - reject(validationError); - } - const basicScope = 'apim:subscribe'; - restApi.getUserScope(provider, basicScope) - .then(() => { - // This api returns 200 when only the $provider has the $basicScope. - resolve(); - }).catch((error) => { - const { response } = error; - // This api returns 404 when the $provider is not found. - // error codes: 901502, 901500 for user not found and scope not found - if (response?.body?.code === 901502 || response?.body?.code === 901500) { - validationError = `${provider} is not a valid Subscriber`; - } - }).finally(() => { - if (validationError) { - reject(validationError); - } - }); - }); - - return promiseValidation; - }; - const formSaveCallback = () => { return restApi.updateApiProvider(dataRow.id, provider) .then(() => { @@ -120,12 +86,18 @@ function EditApi(props) { ); }) .catch((error) => { + let validationError = 'Something went wrong when validating the user'; const { response } = error; + // This api returns 404 when the $provider is not found. + // error codes: 901502, 901500 for user not found and scope not found + if (response?.body?.code === 901502 || response?.body?.code === 901500) { + validationError = `${provider} is not a valid User`; + } if (response?.body?.code === 500) { - const notValidSubscriber = 'Error while updating providership to ' + provider; - throw notValidSubscriber; + const notValidUser = 'Error while updating the provider name to ' + provider; + throw notValidUser; } else { - const updateError = 'Something went wrong when updating provider'; + const updateError = validationError; throw updateError; } }) From 92322729f004ec45594e995e38fd34f253fccdd3 Mon Sep 17 00:00:00 2001 From: shnrndk Date: Tue, 28 Nov 2023 11:51:27 +0530 Subject: [PATCH 04/19] Fixed api search issue --- portals/admin/src/main/webapp/site/public/locales/en.json | 6 +++--- .../source/src/app/components/APISettings/ListApis.jsx | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/portals/admin/src/main/webapp/site/public/locales/en.json b/portals/admin/src/main/webapp/site/public/locales/en.json index c0d04c740cf..a3f221fb221 100644 --- a/portals/admin/src/main/webapp/site/public/locales/en.json +++ b/portals/admin/src/main/webapp/site/public/locales/en.json @@ -88,11 +88,11 @@ "Apis.Details.Scopes.CreateScope.roles.help": "Enter a valid role and press `Enter`.", "Apis.Details.Scopes.Roles.Invalid": "A Role is invalid", "Apis.Listing.Listing.apis.search": "Search", - "Apis.Listing.Listing.apis.search.label": "Search Api by Api Provider", + "Apis.Listing.Listing.apis.search.label": "Search by Api", "Apis.Listing.Listing.apis.searching": "Searching", "Apis.Listing.Listing.clear.search": "Clear Search", "Apis.Listing.Listing.empty.message": "No Data to Display", - "Apis.Listing.Listing.search.placeholder": "Api Provider", + "Apis.Listing.Listing.search.placeholder": "Api Name", "Apis.Listing.apiTableHead.actions": "Actions", "Apis.Listing.apiTableHead.name": "Name", "Apis.Listing.apiTableHead.provider": "Provider", @@ -131,7 +131,7 @@ "Base.RouteMenuMapping.application.deletion": "Application Deletion", "Base.RouteMenuMapping.application.throttling.policies": "Application Policies", "Base.RouteMenuMapping.applications": "Change Application Owner", - "Base.RouteMenuMapping.apis": "Change Api Provder", + "Base.RouteMenuMapping.apis": "Change Api Provider", "Base.RouteMenuMapping.apps": "Apps", "Base.RouteMenuMapping.blacklisted.items": "Deny Policies", "Base.RouteMenuMapping.custom.throttling.policies": "Custom Policies", diff --git a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx index 4ee40589b24..1923500c85e 100644 --- a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx +++ b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx @@ -78,11 +78,11 @@ export default function ListApis() { * API call to get api list * @returns {Promise}. */ - function apiCall(pageNo, user = provider) { + function apiCall(pageNo, query = provider) { setLoading(true); const restApi = new API(); return restApi - .getApiList({ limit: rowsPerPage, offset: pageNo * rowsPerPage, user }) + .getApiList({ limit: rowsPerPage, offset: pageNo * rowsPerPage, query }) .then((result) => { setApiList(result.body.list); const { pagination: { total } } = result.body; From 000cfdb28343dc52a5348b2e2b68cafe6efe922e Mon Sep 17 00:00:00 2001 From: shnrndk Date: Thu, 30 Nov 2023 10:24:43 +0530 Subject: [PATCH 05/19] Action column removed --- .../app/components/APISettings/ApisTableContent.jsx | 2 +- .../app/components/APISettings/ApisTableHead.jsx | 10 ---------- .../src/app/components/APISettings/EditApi.jsx | 13 ++++++------- .../src/app/components/APISettings/ListApis.jsx | 4 ++-- .../src/app/components/Base/RouteMenuMapping.jsx | 4 ++-- 5 files changed, 11 insertions(+), 22 deletions(-) diff --git a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx index 909aff1bfbd..a6960fea018 100644 --- a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx +++ b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx @@ -142,8 +142,8 @@ class ApisTableContent extends Component { {app.name} {app.version} - {app.provider} + {app.provider} { />), sorting: true, }, - { - id: 'actions', - numeric: false, - disablePadding: false, - label: (), - sorting: false, - }, ]; const { order, orderBy } = props; return ( diff --git a/portals/admin/src/main/webapp/source/src/app/components/APISettings/EditApi.jsx b/portals/admin/src/main/webapp/source/src/app/components/APISettings/EditApi.jsx index 05edb617c7a..8b156721461 100644 --- a/portals/admin/src/main/webapp/source/src/app/components/APISettings/EditApi.jsx +++ b/portals/admin/src/main/webapp/source/src/app/components/APISettings/EditApi.jsx @@ -55,7 +55,7 @@ function EditApi(props) { const classes = useStyles(); const restApi = new API(); const { - updateList, dataRow, icon, triggerButtonText, title, apiList, + updateList, dataRow, icon, triggerButtonText, title, } = props; const [initialState, setInitialState] = useState({ name: '', @@ -88,11 +88,11 @@ function EditApi(props) { .catch((error) => { let validationError = 'Something went wrong when validating the user'; const { response } = error; - // This api returns 404 when the $provider is not found. - // error codes: 901502, 901500 for user not found and scope not found - if (response?.body?.code === 901502 || response?.body?.code === 901500) { - validationError = `${provider} is not a valid User`; - } + // This api returns 404 when the $provider is not found. + // error codes: 901502, 901500 for user not found and scope not found + if (response?.body?.code === 901502 || response?.body?.code === 901500) { + validationError = `${provider} is not a valid User`; + } if (response?.body?.code === 500) { const notValidUser = 'Error while updating the provider name to ' + provider; throw notValidUser; @@ -172,7 +172,6 @@ EditApi.propTypes = { icon: PropTypes.element, triggerButtonText: PropTypes.shape({}).isRequired, title: PropTypes.shape({}).isRequired, - apiList: PropTypes.shape([]).isRequired, }; export default EditApi; diff --git a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx index 1923500c85e..871b75dc44e 100644 --- a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx +++ b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx @@ -166,11 +166,11 @@ export default function ListApis() { fullWidth id='search-label' label={intl.formatMessage({ - defaultMessage: 'Search Api by Api Provider', + defaultMessage: 'Search by Api', id: 'Apis.Listing.Listing.apis.search.label', })} placeholder={intl.formatMessage({ - defaultMessage: 'Api Provider', + defaultMessage: 'Api Name', id: 'Apis.Listing.Listing.search.placeholder', })} InputProps={{ diff --git a/portals/admin/src/main/webapp/source/src/app/components/Base/RouteMenuMapping.jsx b/portals/admin/src/main/webapp/source/src/app/components/Base/RouteMenuMapping.jsx index 6a2706918a6..7e822afb75f 100644 --- a/portals/admin/src/main/webapp/source/src/app/components/Base/RouteMenuMapping.jsx +++ b/portals/admin/src/main/webapp/source/src/app/components/Base/RouteMenuMapping.jsx @@ -302,7 +302,7 @@ const RouteMenuMapping = (intl) => [ { id: intl.formatMessage({ id: 'Base.RouteMenuMapping.applications', - defaultMessage: 'Applications', + defaultMessage: 'Change Application Owner', }), path: '/settings/applications', component: ListApplications, @@ -311,7 +311,7 @@ const RouteMenuMapping = (intl) => [ { id: intl.formatMessage({ id: 'Base.RouteMenuMapping.apis', - defaultMessage: 'Apis', + defaultMessage: 'Change Api Provider', }), path: '/settings/apis', component: ListApis, From d6e526214dda44d59d7947b3a095f1d6282817fe Mon Sep 17 00:00:00 2001 From: shnrndk Date: Tue, 5 Dec 2023 09:48:20 +0530 Subject: [PATCH 06/19] Removed Api Name Space validation --- .../APISettings/ApisTableContent.jsx | 32 ++++++++-------- .../components/APISettings/ApisTableHead.jsx | 32 ++++++++-------- .../app/components/APISettings/EditApi.jsx | 35 +++++++++-------- .../app/components/APISettings/ListApis.jsx | 38 ++++++++++--------- .../source/src/app/data/APIValidation.js | 2 +- 5 files changed, 71 insertions(+), 68 deletions(-) diff --git a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx index a6960fea018..d3cca7638d1 100644 --- a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx +++ b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx @@ -1,20 +1,20 @@ /* - * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file 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 CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ +* Copyright (c) 2023, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. +* +* WSO2 LLC. licenses this file 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 CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ import React, { Component } from 'react'; import TableBody from '@material-ui/core/TableBody'; diff --git a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableHead.jsx b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableHead.jsx index 9df135d55ae..7874c7ff1d8 100644 --- a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableHead.jsx +++ b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableHead.jsx @@ -1,20 +1,20 @@ /* - * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file 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 CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ +* Copyright (c) 2023, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. +* +* WSO2 LLC. licenses this file 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 CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ import React from 'react'; import PropTypes from 'prop-types'; diff --git a/portals/admin/src/main/webapp/source/src/app/components/APISettings/EditApi.jsx b/portals/admin/src/main/webapp/source/src/app/components/APISettings/EditApi.jsx index 8b156721461..16bcbe16f25 100644 --- a/portals/admin/src/main/webapp/source/src/app/components/APISettings/EditApi.jsx +++ b/portals/admin/src/main/webapp/source/src/app/components/APISettings/EditApi.jsx @@ -1,20 +1,20 @@ /* - * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file 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 CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ +* Copyright (c) 2023, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. +* +* WSO2 LLC. licenses this file 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 CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ import React, { useReducer, useEffect, useState } from 'react'; import API from 'AppData/api'; @@ -148,8 +148,7 @@ function EditApi(props) { helperText={( )} variant='outlined' diff --git a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx index 871b75dc44e..6a397da6a2d 100644 --- a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx +++ b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx @@ -1,20 +1,20 @@ /* - * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file 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 CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ +* Copyright (c) 2023, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. +* +* WSO2 LLC. licenses this file 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 CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ import React, { useEffect, useState } from 'react'; import { makeStyles } from '@material-ui/core/styles'; @@ -235,7 +235,11 @@ export default function ListApis() { page={page} rowsPerPage={rowsPerPage} editComponentProps={{ - icon: , + icon: ( + + + + ), title: 'Change Api Provider', apiList, }} 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 7bef690a934..052e58b07d0 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 @@ -121,7 +121,7 @@ const documentSchema = Joi.extend((joi) => ({ })); const definition = { - apiName: Joi.string().max(50).regex(/^[^~!@#;:%^*()+={}|\\<>"',&$\s+[\]/]*$/).required() + apiName: Joi.string().max(50).regex(/^[^~!@#;:%^*()+={}|\\<>"',&$[\]/]*$/).required() .error((errors) => { return errors.map((error) => ({ ...error, message: 'Name ' + getMessage(error.type, 50) })); }), From df4f773eabf7cc47bfec08272410f031b96bcfbc Mon Sep 17 00:00:00 2001 From: shnrndk Date: Tue, 5 Dec 2023 20:21:31 +0530 Subject: [PATCH 07/19] Removed Edit Api Component --- .../APISettings/ApisTableContent.jsx | 21 +++++++++++-------- .../app/components/APISettings/ListApis.jsx | 9 +------- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx index d3cca7638d1..3f76bcd4d44 100644 --- a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx +++ b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx @@ -23,7 +23,10 @@ import TableRow from '@material-ui/core/TableRow'; import ResourceNotFound from 'AppComponents/Base/Errors/ResourceNotFound'; import PropTypes from 'prop-types'; import { withStyles } from '@material-ui/core/styles'; -import EditApi from 'AppComponents/APISettings/EditApi'; +import Tooltip from '@material-ui/core/Tooltip'; +import EditIcon from '@material-ui/icons/Edit'; +import { IconButton } from '@material-ui/core'; + /** * @inheritdoc * @param {*} theme theme object @@ -126,7 +129,7 @@ class ApisTableContent extends Component { */ render() { const { - apps, classes, editComponentProps, apiCall, + apis, classes, editComponentProps, apiCall, } = this.props; const { notFound } = this.state; @@ -135,7 +138,7 @@ class ApisTableContent extends Component { } return ( - {apps && apps.map((app) => { + {apis && apis.map((app) => { return ( @@ -144,11 +147,11 @@ class ApisTableContent extends Component { {app.version} {app.provider} - + {/* */} + console.log("123")}> + + + {/* */} ); @@ -159,6 +162,6 @@ class ApisTableContent extends Component { } ApisTableContent.propTypes = { toggleDeleteConfirmation: PropTypes.func.isRequired, - apps: PropTypes.instanceOf(Map).isRequired, + apis: PropTypes.instanceOf(Map).isRequired, }; export default withStyles(styles)(ApisTableContent); diff --git a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx index 6a397da6a2d..1a744789c0d 100644 --- a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx +++ b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx @@ -23,7 +23,6 @@ import { useIntl, FormattedMessage } from 'react-intl'; import EditApi from 'AppComponents/APISettings/EditApi'; import ApisTableContent from 'AppComponents/APISettings/ApisTableContent'; import ApisTableHead from 'AppComponents/APISettings/ApisTableHead'; -import EditIcon from '@material-ui/icons/Edit'; import Table from '@material-ui/core/Table'; import ContentBase from 'AppComponents/AdminPages/Addons/ContentBase'; import TableFooter from '@material-ui/core/TableFooter'; @@ -231,16 +230,10 @@ export default function ListApis() { - - - ), - title: 'Change Api Provider', apiList, }} EditComponent={EditApi} From f6415bad4aa1371d6f21121832565eec76c8dce9 Mon Sep 17 00:00:00 2001 From: shnrndk Date: Tue, 5 Dec 2023 20:34:24 +0530 Subject: [PATCH 08/19] ApisTableContent changed to functional component --- .../APISettings/ApisTableContent.jsx | 128 +++++------------- .../app/components/APISettings/ListApis.jsx | 1 - 2 files changed, 33 insertions(+), 96 deletions(-) diff --git a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx index 3f76bcd4d44..73eba8d9653 100644 --- a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx +++ b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx @@ -1,37 +1,15 @@ -/* -* Copyright (c) 2023, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. -* -* WSO2 LLC. licenses this file 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 CONDITIONS OF ANY -* KIND, either express or implied. See the License for the -* specific language governing permissions and limitations -* under the License. -*/ - -import React, { Component } from 'react'; +import React, { useState } from 'react'; import TableBody from '@material-ui/core/TableBody'; import TableCell from '@material-ui/core/TableCell'; import TableRow from '@material-ui/core/TableRow'; import ResourceNotFound from 'AppComponents/Base/Errors/ResourceNotFound'; import PropTypes from 'prop-types'; -import { withStyles } from '@material-ui/core/styles'; +import { makeStyles, withStyles } from '@material-ui/core/styles'; import Tooltip from '@material-ui/core/Tooltip'; import EditIcon from '@material-ui/icons/Edit'; import { IconButton } from '@material-ui/core'; -/** - * @inheritdoc - * @param {*} theme theme object - */ -const styles = (theme) => ({ +const useStyles = makeStyles((theme) => ({ fullHeight: { height: '100%', }, @@ -66,7 +44,8 @@ const styles = (theme) => ({ 'white-space': 'normal', }, }, -}); +})); + const StyledTableCell = withStyles((theme) => ({ head: { backgroundColor: theme.palette.common.black, @@ -90,78 +69,37 @@ const StyledTableRow = withStyles((theme) => ({ }, }))(TableRow); -/** - * - * - * @class ApisTableContent - * @extends {Component} - */ -class ApisTableContent extends Component { - /** - * @inheritdoc - */ - constructor(props) { - super(props); - this.state = { - notFound: false, - }; - this.handleAppEdit = this.handleAppEdit.bind(this); - } +const ApisTableContent = ({ apis }) => { + const [notFound, setNotFound] = useState(false); + const classes = useStyles(); - handleAppEdit = (app) => { - const { EditComponent, editComponentProps, apiCall } = this.props; - return ( - <> - {EditComponent && ( - - )} - - ); - }; + if (notFound) { + return ; + } - /** - * @inheritdoc - * @memberof ApisTableContent - */ - render() { - const { - apis, classes, editComponentProps, apiCall, - } = this.props; - const { notFound } = this.state; + return ( + + {apis && apis.map((api) => ( + + + {api.name} + + {api.version} + + {api.provider} + console.log("123")}> + + + + + ))} + + ); +}; - if (notFound) { - return ; - } - return ( - - {apis && apis.map((app) => { - return ( - - - {app.name} - - {app.version} - - {app.provider} - {/* */} - console.log("123")}> - - - {/* */} - - - ); - })} - - ); - } -} ApisTableContent.propTypes = { - toggleDeleteConfirmation: PropTypes.func.isRequired, apis: PropTypes.instanceOf(Map).isRequired, + classes: PropTypes.object.isRequired, }; -export default withStyles(styles)(ApisTableContent); + +export default ApisTableContent; diff --git a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx index 1a744789c0d..9e65862e0df 100644 --- a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx +++ b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx @@ -236,7 +236,6 @@ export default function ListApis() { editComponentProps={{ apiList, }} - EditComponent={EditApi} apiCall={apiCall} /> From 7a95e99ba9ca89bc4aa2198189932b5fe8be7328 Mon Sep 17 00:00:00 2001 From: shnrndk Date: Wed, 6 Dec 2023 05:27:15 +0530 Subject: [PATCH 09/19] Add the user inputs inside the ApisTableContent. --- .../APISettings/ApisTableContent.jsx | 114 ++++++++++++++++-- .../app/components/APISettings/ListApis.jsx | 3 +- 2 files changed, 106 insertions(+), 11 deletions(-) diff --git a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx index 73eba8d9653..999aacaa572 100644 --- a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx +++ b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx @@ -4,9 +4,13 @@ import TableCell from '@material-ui/core/TableCell'; import TableRow from '@material-ui/core/TableRow'; import ResourceNotFound from 'AppComponents/Base/Errors/ResourceNotFound'; import PropTypes from 'prop-types'; +import API from 'AppData/api'; import { makeStyles, withStyles } from '@material-ui/core/styles'; -import Tooltip from '@material-ui/core/Tooltip'; +import Alert from 'AppComponents/Shared/Alert'; +import Button from '@material-ui/core/Button'; +import TextField from '@material-ui/core/TextField'; import EditIcon from '@material-ui/icons/Edit'; +import { FormattedMessage } from 'react-intl'; import { IconButton } from '@material-ui/core'; const useStyles = makeStyles((theme) => ({ @@ -27,6 +31,11 @@ const useStyles = makeStyles((theme) => ({ color: '#1b9ec7 !important', }, }, + button: { + marginLeft: theme.spacing(0.5), + marginRight: theme.spacing(0.5), + marginTop: theme.spacing(1), + }, appTablePaper: { '& table tr td': { paddingLeft: theme.spacing(1), @@ -69,27 +78,115 @@ const StyledTableRow = withStyles((theme) => ({ }, }))(TableRow); -const ApisTableContent = ({ apis }) => { - const [notFound, setNotFound] = useState(false); +const ApisTableContent = ({ apis, updateApiList }) => { + const [notFound] = useState(false); + const restApi = new API(); + const [provider, setProvider] = useState(''); + const [editableRows, setEditableRows] = useState(new Set()); + const classes = useStyles(); if (notFound) { return ; } + const handleEditClick = (apiId) => { + setEditableRows((prevRows) => { + const newRows = new Set(prevRows); + newRows.add(apiId); + return newRows; + }); + }; + + const handleCancelClick = (apiId) => { + setEditableRows((prevRows) => { + const newRows = new Set(prevRows); + newRows.delete(apiId); + return newRows; + }); + }; + + const handleSubmitClick = (apiId, apiProvider) => { + return restApi.updateApiProvider(apiId, apiProvider) + .then(() => { + return ( + Alert.success( + , + ) + ); + }) + .catch((error) => { + let validationError = 'Something went wrong when validating the user'; + const { response } = error; + // This api returns 404 when the $provider is not found. + // error codes: 901502, 901500 for user not found and scope not found + if (response?.body?.code === 901502 || response?.body?.code === 901500) { + validationError = `${provider} is not a valid User`; + } + if (response?.body?.code === 500) { + const notValidUser = 'Error while updating the provider name to ' + provider; + throw notValidUser; + } else { + const updateError = validationError; + throw updateError; + } + }) + .finally(() => { + updateApiList(); + handleCancelClick(apiId); + }); + }; + return ( {apis && apis.map((api) => ( - + {api.name} {api.version} - {api.provider} - console.log("123")}> - - + {!editableRows.has(api.id) && ( + <> + {api.provider} + handleEditClick(api.id)}> + + + + )} + {editableRows.has(api.id) && ( + <> + { setProvider(e.target.value); }} + /> + + + + )} ))} @@ -99,7 +196,6 @@ const ApisTableContent = ({ apis }) => { ApisTableContent.propTypes = { apis: PropTypes.instanceOf(Map).isRequired, - classes: PropTypes.object.isRequired, }; export default ApisTableContent; diff --git a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx index 9e65862e0df..c193f640f18 100644 --- a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx +++ b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx @@ -20,7 +20,6 @@ import React, { useEffect, useState } from 'react'; import { makeStyles } from '@material-ui/core/styles'; import API from 'AppData/api'; import { useIntl, FormattedMessage } from 'react-intl'; -import EditApi from 'AppComponents/APISettings/EditApi'; import ApisTableContent from 'AppComponents/APISettings/ApisTableContent'; import ApisTableHead from 'AppComponents/APISettings/ApisTableHead'; import Table from '@material-ui/core/Table'; @@ -236,7 +235,7 @@ export default function ListApis() { editComponentProps={{ apiList, }} - apiCall={apiCall} + updateApiList={apiCall} /> From 7043cab7a126f736cb156d8e09fb7ccbf8e59803 Mon Sep 17 00:00:00 2001 From: shnrndk Date: Sat, 9 Dec 2023 20:08:16 +0530 Subject: [PATCH 10/19] update api provider bugs fix and alignments fix --- .../APISettings/ApisTableContent.jsx | 125 ++++++++++-------- .../components/APISettings/ApisTableHead.jsx | 5 + .../app/components/APISettings/ListApis.jsx | 4 +- .../main/webapp/source/src/app/data/api.js | 4 +- 4 files changed, 79 insertions(+), 59 deletions(-) diff --git a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx index 999aacaa572..733f13acad8 100644 --- a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx +++ b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx @@ -12,6 +12,8 @@ import TextField from '@material-ui/core/TextField'; import EditIcon from '@material-ui/icons/Edit'; import { FormattedMessage } from 'react-intl'; import { IconButton } from '@material-ui/core'; +import SaveIcon from '@material-ui/icons/Save'; +import CancelIcon from '@material-ui/icons/Cancel'; const useStyles = makeStyles((theme) => ({ fullHeight: { @@ -104,40 +106,60 @@ const ApisTableContent = ({ apis, updateApiList }) => { newRows.delete(apiId); return newRows; }); + setProvider(''); }; const handleSubmitClick = (apiId, apiProvider) => { - return restApi.updateApiProvider(apiId, apiProvider) - .then(() => { - return ( - Alert.success( - , - ) - ); - }) - .catch((error) => { - let validationError = 'Something went wrong when validating the user'; - const { response } = error; - // This api returns 404 when the $provider is not found. - // error codes: 901502, 901500 for user not found and scope not found - if (response?.body?.code === 901502 || response?.body?.code === 901500) { - validationError = `${provider} is not a valid User`; - } - if (response?.body?.code === 500) { - const notValidUser = 'Error while updating the provider name to ' + provider; - throw notValidUser; - } else { - const updateError = validationError; - throw updateError; - } - }) - .finally(() => { - updateApiList(); - handleCancelClick(apiId); - }); + if (apiProvider == '') { + Alert.error( + , + ) + } else { + return restApi.updateApiProvider(apiId, apiProvider) + .then(() => { + return ( + Alert.success( + , + ) + ); + }) + .catch((error) => { + let validationError = 'Something went wrong when validating the user'; + const { response } = error; + // This api returns 404 when the $provider is not found. + // error codes: 901502, 901500 for user not found and scope not found + if (response?.body?.code === 901502 || response?.body?.code === 901500) { + validationError = `${provider} is not a valid User`; + } + if (response?.body?.code === 500) { + const notValidUser = 'Error while updating the provider name to ' + provider; + Alert.error( + , + ) + } else { + const updateError = validationError; + Alert.error( + , + ) + } + }) + .finally(() => { + updateApiList(); + handleCancelClick(apiId); + }); + } }; return ( @@ -147,45 +169,38 @@ const ApisTableContent = ({ apis, updateApiList }) => { {api.name} - {api.version} + +
+ {api.version} +
+
{!editableRows.has(api.id) && ( - <> +
{api.provider} handleEditClick(api.id)}> - +
)} {editableRows.has(api.id) && ( - <> +
{ setProvider(e.target.value); }} /> - - - + handleSubmitClick(api.id, provider)}> + + + handleCancelClick(api.id)}> + + +
)}
diff --git a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableHead.jsx b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableHead.jsx index 7874c7ff1d8..a8e912a19b8 100644 --- a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableHead.jsx +++ b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableHead.jsx @@ -43,6 +43,7 @@ const apisTableHead = (props) => { defaultMessage='Name' />), sorting: true, + width: 200, }, { id: 'version', @@ -53,6 +54,7 @@ const apisTableHead = (props) => { defaultMessage='Version' />), sorting: true, + width: 100, }, { id: 'provider', @@ -63,6 +65,7 @@ const apisTableHead = (props) => { defaultMessage='Provider' />), sorting: true, + width: 130 }, ]; const { order, orderBy } = props; @@ -75,6 +78,8 @@ const apisTableHead = (props) => { key={column.id} align='left' sortDirection={orderBy === column.id ? order : false} + width={column.width} + style={{marginLeft:50}} > {column.sorting ? ( { - setApiList(result.body.list); + setApiList(result.body.apis); const { pagination: { total } } = result.body; setTotalApps(total); - return result.body.list; + return result.body.apis; }) .catch((error) => { throw error; diff --git a/portals/admin/src/main/webapp/source/src/app/data/api.js b/portals/admin/src/main/webapp/source/src/app/data/api.js index ae41917de76..cec3d114bea 100644 --- a/portals/admin/src/main/webapp/source/src/app/data/api.js +++ b/portals/admin/src/main/webapp/source/src/app/data/api.js @@ -461,8 +461,8 @@ class API extends Resource { */ updateApiProvider(apiId, provider) { return this.client.then((client) => { - return client.apis["Api Provider Change"].providerProviderNameApisApiIdPut( - { providerName: provider, apiId: apiId }, + return client.apis["Api Provider Change"].providerNamePost( + { provider: provider, apiId: apiId }, this._requestMetaData(), ); }); From 70664e2923ecd8d2e647ef7309b1014b84cbb916 Mon Sep 17 00:00:00 2001 From: shnrndk Date: Mon, 11 Dec 2023 10:56:38 +0530 Subject: [PATCH 11/19] Formatting issues fix --- .../APISettings/ApisTableContent.jsx | 72 +++---- .../components/APISettings/ApisTableHead.jsx | 4 +- .../app/components/APISettings/EditApi.jsx | 176 ------------------ .../app/components/APISettings/ListApis.jsx | 2 +- .../app/components/Base/RouteMenuMapping.jsx | 2 +- 5 files changed, 43 insertions(+), 213 deletions(-) delete mode 100644 portals/admin/src/main/webapp/source/src/app/components/APISettings/EditApi.jsx diff --git a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx index 733f13acad8..4ddb504cd02 100644 --- a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx +++ b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx @@ -7,7 +7,6 @@ import PropTypes from 'prop-types'; import API from 'AppData/api'; import { makeStyles, withStyles } from '@material-ui/core/styles'; import Alert from 'AppComponents/Shared/Alert'; -import Button from '@material-ui/core/Button'; import TextField from '@material-ui/core/TextField'; import EditIcon from '@material-ui/icons/Edit'; import { FormattedMessage } from 'react-intl'; @@ -110,13 +109,15 @@ const ApisTableContent = ({ apis, updateApiList }) => { }; const handleSubmitClick = (apiId, apiProvider) => { - if (apiProvider == '') { - Alert.error( - , - ) + if (apiProvider === '') { + return ( + Alert.error( + , + ) + ); } else { return restApi.updateApiProvider(apiId, apiProvider) .then(() => { @@ -124,35 +125,33 @@ const ApisTableContent = ({ apis, updateApiList }) => { Alert.success( , ) ); }) .catch((error) => { - let validationError = 'Something went wrong when validating the user'; const { response } = error; // This api returns 404 when the $provider is not found. // error codes: 901502, 901500 for user not found and scope not found if (response?.body?.code === 901502 || response?.body?.code === 901500) { - validationError = `${provider} is not a valid User`; - } - if (response?.body?.code === 500) { - const notValidUser = 'Error while updating the provider name to ' + provider; - Alert.error( - , - ) + return ( + Alert.error( + , + ) + ); } else { - const updateError = validationError; - Alert.error( - , - ) + return ( + Alert.error( + , + ) + ); } }) .finally(() => { @@ -170,28 +169,35 @@ const ApisTableContent = ({ apis, updateApiList }) => { {api.name} -
+
{api.version}
{!editableRows.has(api.id) && ( -
- {api.provider} +
+ { api.provider } handleEditClick(api.id)}>
)} - {editableRows.has(api.id) && ( -
+ { editableRows.has(api.id) && ( +
{ setProvider(e.target.value); }} /> handleSubmitClick(api.id, provider)}> diff --git a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableHead.jsx b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableHead.jsx index a8e912a19b8..7521fd994d7 100644 --- a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableHead.jsx +++ b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableHead.jsx @@ -65,7 +65,7 @@ const apisTableHead = (props) => { defaultMessage='Provider' />), sorting: true, - width: 130 + width: 130, }, ]; const { order, orderBy } = props; @@ -79,7 +79,7 @@ const apisTableHead = (props) => { align='left' sortDirection={orderBy === column.id ? order : false} width={column.width} - style={{marginLeft:50}} + style={{ marginLeft: 50 }} > {column.sorting ? ( ({ - error: { - color: theme.palette.error.dark, - }, -})); - -/** - * Reducer - * @param {JSON} state State - * @returns {Promise}. - */ -function reducer(state, { field, value }) { - switch (field) { - case 'name': - case 'provider': - return { ...state, [field]: value }; - case 'editDetails': - return value; - default: - return state; - } -} -/** - * Render a pop-up dialog to change providership of an Api - * @param {JSON} props props passed from parent - * @returns {JSX}. - */ -function EditApi(props) { - const classes = useStyles(); - const restApi = new API(); - const { - updateList, dataRow, icon, triggerButtonText, title, - } = props; - const [initialState, setInitialState] = useState({ - name: '', - provider: '', - }); - - const [state, dispatch] = useReducer(reducer, initialState); - const { name, provider } = state; - - useEffect(() => { - setInitialState({ - name: '', - provider: '', - }); - }, []); - const onChange = (e) => { - dispatch({ field: e.target.name, value: e.target.value }); - }; - - const formSaveCallback = () => { - return restApi.updateApiProvider(dataRow.id, provider) - .then(() => { - return ( - - ); - }) - .catch((error) => { - let validationError = 'Something went wrong when validating the user'; - const { response } = error; - // This api returns 404 when the $provider is not found. - // error codes: 901502, 901500 for user not found and scope not found - if (response?.body?.code === 901502 || response?.body?.code === 901500) { - validationError = `${provider} is not a valid User`; - } - if (response?.body?.code === 500) { - const notValidUser = 'Error while updating the provider name to ' + provider; - throw notValidUser; - } else { - const updateError = validationError; - throw updateError; - } - }) - .finally(() => { - updateList(); - }); - }; - const dialogOpenCallback = () => { - if (dataRow) { - const { name: originalName, provider: originalProvider } = dataRow; - dispatch({ field: 'editDetails', value: { name: originalName, provider: originalProvider } }); - } - }; - return ( - - - - * - - )} - fullWidth - variant='outlined' - disabled - /> - - )} - variant='outlined' - /> - - ); -} - -EditApi.defaultProps = { - icon: null, -}; - -EditApi.propTypes = { - updateList: PropTypes.func.isRequired, - dataRow: PropTypes.shape({ - id: PropTypes.string.isRequired, - provider: PropTypes.string.isRequired, - name: PropTypes.string.isRequired, - }).isRequired, - icon: PropTypes.element, - triggerButtonText: PropTypes.shape({}).isRequired, - title: PropTypes.shape({}).isRequired, -}; - -export default EditApi; diff --git a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx index 906f0c5e812..fc8b6be7b3c 100644 --- a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx +++ b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx @@ -164,7 +164,7 @@ export default function ListApis() { fullWidth id='search-label' label={intl.formatMessage({ - defaultMessage: 'Search by Api', + defaultMessage: 'Search by API', id: 'Apis.Listing.Listing.apis.search.label', })} placeholder={intl.formatMessage({ diff --git a/portals/admin/src/main/webapp/source/src/app/components/Base/RouteMenuMapping.jsx b/portals/admin/src/main/webapp/source/src/app/components/Base/RouteMenuMapping.jsx index 7e822afb75f..e83a5224260 100644 --- a/portals/admin/src/main/webapp/source/src/app/components/Base/RouteMenuMapping.jsx +++ b/portals/admin/src/main/webapp/source/src/app/components/Base/RouteMenuMapping.jsx @@ -311,7 +311,7 @@ const RouteMenuMapping = (intl) => [ { id: intl.formatMessage({ id: 'Base.RouteMenuMapping.apis', - defaultMessage: 'Change Api Provider', + defaultMessage: 'Change API Provider', }), path: '/settings/apis', component: ListApis, From e0bc9e7899f185daf5e1f31a4a452ec0ee076128 Mon Sep 17 00:00:00 2001 From: shnrndk Date: Mon, 11 Dec 2023 14:18:41 +0530 Subject: [PATCH 12/19] apim:api_provider_change scope added. --- portals/admin/src/main/webapp/source/src/app/data/Constants.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/portals/admin/src/main/webapp/source/src/app/data/Constants.js b/portals/admin/src/main/webapp/source/src/app/data/Constants.js index 79df9500e8e..34c53cd1659 100644 --- a/portals/admin/src/main/webapp/source/src/app/data/Constants.js +++ b/portals/admin/src/main/webapp/source/src/app/data/Constants.js @@ -39,7 +39,7 @@ const CONSTS = { KEY_MANAGER: ['apim:keymanagers_manage', 'openid', 'apim:tenantInfo', 'apim:admin_settings'], GATEWAY_MANAGER: ['apim:environment_manage', 'openid', 'apim:admin_settings', 'apim:environment_read'], SETTINGS_MANAGER: ['apim:app_owner_change', 'apim:admin_application_view', - 'apim:scope_manage', 'openid', 'apim:admin_settings', 'apim:tenantInfo', + 'apim:scope_manage', 'openid', 'apim:admin_settings', 'apim:tenantInfo', 'apim:api_provider_change', ], }, }; From a213e579aab06218d2496fa1145a80345b2f452f Mon Sep 17 00:00:00 2001 From: shnrndk Date: Mon, 11 Dec 2023 20:47:05 +0530 Subject: [PATCH 13/19] api name regex validation updated --- .../Apis/Create/Default/APICreateDefault.test.tsx | 2 +- .../src/main/webapp/source/src/app/data/APIValidation.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/portals/publisher/src/main/webapp/source/src/app/components/Apis/Create/Default/APICreateDefault.test.tsx b/portals/publisher/src/main/webapp/source/src/app/components/Apis/Create/Default/APICreateDefault.test.tsx index fce436be9bd..b8d5a49ba8a 100644 --- a/portals/publisher/src/main/webapp/source/src/app/components/Apis/Create/Default/APICreateDefault.test.tsx +++ b/portals/publisher/src/main/webapp/source/src/app/components/Apis/Create/Default/APICreateDefault.test.tsx @@ -64,7 +64,7 @@ describe('Create REST API From scratch', () => { userEvent.clear(NAME_INPUT); // Test for special characters - const NO_SPACE_ERROR = /name should not contain spaces or special characters/i; + const NO_SPACE_ERROR = /Api name should not contain trailing or leading spaces, special characters, and consecutive spaces/i; userEvent.type(NAME_INPUT, 'invalid@name'); NAME_INPUT.blur(); expect(screen.getByText(NO_SPACE_ERROR)).toBeInTheDocument(); 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 052e58b07d0..e6c05eb26b6 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 @@ -32,7 +32,7 @@ function getMessage(errorType, maxLength) { case 'any.empty': return 'should not be empty'; case 'string.regex.base': - return 'should not contain spaces or special characters'; + return 'Api name should not contain trailing or leading spaces, special characters, and consecutive spaces'; case 'string.max': return 'has exceeded the maximum number of ' + maxLength + ' characters'; default: @@ -121,9 +121,9 @@ const documentSchema = Joi.extend((joi) => ({ })); const definition = { - apiName: Joi.string().max(50).regex(/^[^~!@#;:%^*()+={}|\\<>"',&$[\]/]*$/).required() + apiName: Joi.string().max(50).regex(/^(?!.*\s{2})(?!.*[~!@#;:%^*()+={}|\\<>"',&$[\]/]).*$/).required() .error((errors) => { - return errors.map((error) => ({ ...error, message: 'Name ' + getMessage(error.type, 50) })); + return errors.map((error) => ({ ...error, message: getMessage(error.type, 50) })); }), apiVersion: Joi.string().regex(/^[^~!@#;:%^*()+={}|\\<>"',&/$[\]\s]+$/).required().error((errors) => { const tmpErrors = [...errors]; From 2f6e6bc84389705d885057dd0b1e0f59819accd4 Mon Sep 17 00:00:00 2001 From: shnrndk Date: Tue, 12 Dec 2023 09:07:10 +0530 Subject: [PATCH 14/19] inline styles removed --- .../APISettings/ApisTableContent.jsx | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx index 4ddb504cd02..949146c96e5 100644 --- a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx +++ b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx @@ -54,6 +54,21 @@ const useStyles = makeStyles((theme) => ({ 'white-space': 'normal', }, }, + tableActionBtnContainer: { + display: 'flex', + flexDirection: 'row', + alignItems: 'left', + justifyContent: 'left', + marginLeft: 10, + }, + textfield: { + maxHeight: '10px', + marginTop: '-5px', + maxWidth: '120px', + }, + tableCell: { + marginLeft: 10, + }, })); const StyledTableCell = withStyles((theme) => ({ @@ -169,13 +184,13 @@ const ApisTableContent = ({ apis, updateApiList }) => { {api.name} -
+
{api.version}
{!editableRows.has(api.id) && ( -
+
{ api.provider } handleEditClick(api.id)}> @@ -183,21 +198,14 @@ const ApisTableContent = ({ apis, updateApiList }) => {
)} { editableRows.has(api.id) && ( -
+
{ setProvider(e.target.value); }} /> handleSubmitClick(api.id, provider)}> From c7484df7be3a817e7667de01ec09bf5c63675806 Mon Sep 17 00:00:00 2001 From: Sahan Randika Date: Wed, 10 Jan 2024 10:28:51 +0530 Subject: [PATCH 15/19] add license header --- .../APISettings/ApisTableContent.jsx | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx index 949146c96e5..026f2be5f99 100644 --- a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx +++ b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx @@ -1,3 +1,21 @@ +/* +* Copyright (c) 2023, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. +* +* WSO2 LLC. licenses this file 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 CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + import React, { useState } from 'react'; import TableBody from '@material-ui/core/TableBody'; import TableCell from '@material-ui/core/TableCell'; From da90977b93c1162dc10665f175d712901beb8ff5 Mon Sep 17 00:00:00 2001 From: Sahan Randika Date: Wed, 10 Jan 2024 14:52:16 +0530 Subject: [PATCH 16/19] fix unit test failure --- .../Create/Default/APICreateDefault.test.tsx | 2 +- .../source/src/app/data/APIValidation.js | 29 +++++++++++-------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/portals/publisher/src/main/webapp/source/src/app/components/Apis/Create/Default/APICreateDefault.test.tsx b/portals/publisher/src/main/webapp/source/src/app/components/Apis/Create/Default/APICreateDefault.test.tsx index b8d5a49ba8a..b1ed04fcfeb 100644 --- a/portals/publisher/src/main/webapp/source/src/app/components/Apis/Create/Default/APICreateDefault.test.tsx +++ b/portals/publisher/src/main/webapp/source/src/app/components/Apis/Create/Default/APICreateDefault.test.tsx @@ -64,7 +64,7 @@ describe('Create REST API From scratch', () => { userEvent.clear(NAME_INPUT); // Test for special characters - const NO_SPACE_ERROR = /Api name should not contain trailing or leading spaces, special characters, and consecutive spaces/i; + const NO_SPACE_ERROR = /name should not contain trailing or leading spaces, special characters, and consecutive spaces/i; userEvent.type(NAME_INPUT, 'invalid@name'); NAME_INPUT.blur(); expect(screen.getByText(NO_SPACE_ERROR)).toBeInTheDocument(); 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 e6c05eb26b6..360ce277755 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 @@ -27,12 +27,16 @@ import queryString from 'query-string'; * @param {string} errorType The joi error type * @return {string} simplified error message. * */ -function getMessage(errorType, maxLength) { +function getMessage(errorType, isApiName, maxLength) { switch (errorType) { case 'any.empty': return 'should not be empty'; case 'string.regex.base': - return 'Api name should not contain trailing or leading spaces, special characters, and consecutive spaces'; + if(isApiName){ + return 'should not contain trailing or leading spaces, special characters, and consecutive spaces'; + }else{ + return 'should not contain spaces or special characters'; + } case 'string.max': return 'has exceeded the maximum number of ' + maxLength + ' characters'; default: @@ -123,36 +127,37 @@ const documentSchema = Joi.extend((joi) => ({ const definition = { apiName: Joi.string().max(50).regex(/^(?!.*\s{2})(?!.*[~!@#;:%^*()+={}|\\<>"',&$[\]/]).*$/).required() .error((errors) => { - return errors.map((error) => ({ ...error, message: getMessage(error.type, 50) })); + return errors.map((error) => ({ ...error, message: 'Name ' + getMessage(error.type, true, 50) })); }), apiVersion: Joi.string().regex(/^[^~!@#;:%^*()+={}|\\<>"',&/$[\]\s]+$/).required().error((errors) => { const tmpErrors = [...errors]; errors.forEach((err, index) => { const tmpError = { ...err }; - tmpError.message = 'API Version ' + getMessage(err.type); + tmpError.message = 'API Version ' + getMessage(err.type, false); tmpErrors[index] = tmpError; }); return tmpErrors; }), apiContext: Joi.string().max(200).regex(/(?!.*\/t\/.*|.*\/t$)^[^~!@#:%^&*+=|\\<>"',&\s[\]]*$/).required() .error((errors) => { - return errors.map((error) => ({ ...error, message: 'Context ' + getMessage(error.type, 200) })); + return errors.map((error) => ({ ...error, message: 'Context ' + getMessage(error.type, false, 200) })); }), gatewayVendor: Joi.string().max(50).regex(/^[^~!@#;:%^*()+={}|\\<>"',&$\s+[\]/]*$/).required() .error((errors) => { - return errors.map((error) => ({ ...error, message: 'Name ' + getMessage(error.type, 50) })); + return errors.map((error) => ({ ...error, message: 'Name ' + getMessage(error.type, false, 50) })); }), documentName: Joi.string().max(50).regex(/^[^~!@#;:%^*()+={}|\\<>"',&$+[\]/]*$/).required() .error((errors) => { - return errors.map((error) => ({ ...error, message: 'Document name ' + getMessage(error.type, 50) })); + return errors.map((error) => ({ ...error, message: 'Document name ' + getMessage(error.type, false, 50) })); }), authorizationHeader: Joi.string().regex(/^[^~!@#;:%^*()+={}|\\<>"',&$\s+]*$/).required() .error((errors) => { - return errors.map((error) => ({ ...error, message: 'Authorization Header ' + getMessage(error.type) })); + return errors.map((error) => ({ ...error, message: 'Authorization Header ' + + getMessage(error.type, false) })); }), apiKeyHeader: Joi.string().regex(/^[^~!@#;:%^*()+={}|\\<>"',&$\s+]*$/).required() .error((errors) => { - return errors.map((error) => ({ ...error, message: 'Api Key Header ' + getMessage(error.type) })); + return errors.map((error) => ({ ...error, message: 'Api Key Header ' + getMessage(error.type, false) })); }), role: roleSchema.systemRole().role(), scope: scopeSchema.scopes().scope(), @@ -160,7 +165,7 @@ const definition = { const tmpErrors = [...errors]; errors.forEach((err, index) => { const tmpError = { ...err }; - tmpError.message = 'URL ' + getMessage(err.type); + tmpError.message = 'URL ' + getMessage(err.type, false); tmpErrors[index] = tmpError; }); return tmpErrors; @@ -171,14 +176,14 @@ const definition = { const tmpError = { ...err }; const errType = err.type; tmpError.message = errType === 'string.uriCustomScheme' ? 'Invalid WebSocket URL' - : 'WebSocket URL ' + getMessage(errType); + : 'WebSocket URL ' + getMessage(errType, false); tmpErrors[index] = tmpError; }); return tmpErrors; }), alias: Joi.string().max(30).regex(/^[^~!@#;:%^*()+={}|\\<>"',&$\s+[\]/]*$/).required() .error((errors) => { - return errors.map((error) => ({ ...error, message: 'Alias ' + getMessage(error.type, 30) })); + return errors.map((error) => ({ ...error, message: 'Alias ' + getMessage(error.type, false, 30) })); }), userRole: userRoleSchema.userRole().role(), apiParameter: apiSchema.api().isAPIParameterExist(), From 29607f7f40ef583590bb286f3e1ea8d36af5091c Mon Sep 17 00:00:00 2001 From: Sahan Randika Date: Wed, 10 Jan 2024 15:06:06 +0530 Subject: [PATCH 17/19] fix case issues --- .../src/main/webapp/site/public/locales/en.json | 16 ++++++++-------- .../src/app/components/APISettings/ListApis.jsx | 1 - .../src/main/webapp/source/src/app/data/api.js | 2 +- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/portals/admin/src/main/webapp/site/public/locales/en.json b/portals/admin/src/main/webapp/site/public/locales/en.json index a3f221fb221..aa912039493 100644 --- a/portals/admin/src/main/webapp/site/public/locales/en.json +++ b/portals/admin/src/main/webapp/site/public/locales/en.json @@ -62,9 +62,10 @@ "AdminPages.ApiCategories.table.header.category.description": "Description", "AdminPages.ApiCategories.table.header.category.name": "Category Name", "AdminPages.ApiCategories.table.header.category.number.of.apis": "Number of APIs", - "AdminPages.ApiSettings.EditApi.form.edit.successful": "Api owner changed successfully", - "AdminPages.ApiSettings.EditApi.form.helperText": "Enter a new Owner. Make sure the new owner has logged into the Developer Portal at least once", - "AdminPages.ApiSettings.EditApi.form.name": "Api Name", + "AdminPages.ApiSettings.EditApi.form.edit.error": "API provider should not be empty.", + "AdminPages.ApiSettings.EditApi.form.edit.other.error": "Given Username is not valid.", + "AdminPages.ApiSettings.EditApi.form.edit.successful": "API provider changed successfully", + "AdminPages.ApiSettings.EditApi.form.edit.user.notvalid": "Error while updating the provider name.", "AdminPages.ApplicationSettings.Edit.form.edit.successful": "Application owner changed successfully", "AdminPages.ApplicationSettings.Edit.form.helperText": "Enter a new Owner. Make sure the new owner has logged into the Developer Portal at least once", "AdminPages.ApplicationSettings.Edit.form.name": "Application Name", @@ -88,14 +89,14 @@ "Apis.Details.Scopes.CreateScope.roles.help": "Enter a valid role and press `Enter`.", "Apis.Details.Scopes.Roles.Invalid": "A Role is invalid", "Apis.Listing.Listing.apis.search": "Search", - "Apis.Listing.Listing.apis.search.label": "Search by Api", + "Apis.Listing.Listing.apis.search.label": "Search by API", "Apis.Listing.Listing.apis.searching": "Searching", "Apis.Listing.Listing.clear.search": "Clear Search", "Apis.Listing.Listing.empty.message": "No Data to Display", - "Apis.Listing.Listing.search.placeholder": "Api Name", - "Apis.Listing.apiTableHead.actions": "Actions", + "Apis.Listing.Listing.search.placeholder": "API Name", "Apis.Listing.apiTableHead.name": "Name", "Apis.Listing.apiTableHead.provider": "Provider", + "Apis.Listing.apiTableHead.version": "Version", "Apis.Shared.AdminRootErrorBoundary.refresh": "Refresh", "Apis.Shared.AdminRootErrorBoundary.refresh.or.try.again.message": "You may refresh the page now or try again later", "Apis.Shared.AdminRootErrorBoundary.something.went.wrong.while.rendering.button": "Something went wrong while rendering the", @@ -127,12 +128,11 @@ "Base.RouteMenuMapping.advanced.throttling.policies.Adding": "Add Advanced Policy", "Base.RouteMenuMapping.advanced.throttling.policies.Editing": "Edit Advanced Policy", "Base.RouteMenuMapping.api.categories": "API Categories", + "Base.RouteMenuMapping.apis": "Change API Provider", "Base.RouteMenuMapping.application.creation": "Application Creation", "Base.RouteMenuMapping.application.deletion": "Application Deletion", "Base.RouteMenuMapping.application.throttling.policies": "Application Policies", "Base.RouteMenuMapping.applications": "Change Application Owner", - "Base.RouteMenuMapping.apis": "Change Api Provider", - "Base.RouteMenuMapping.apps": "Apps", "Base.RouteMenuMapping.blacklisted.items": "Deny Policies", "Base.RouteMenuMapping.custom.throttling.policies": "Custom Policies", "Base.RouteMenuMapping.custom.throttling.policies.items.Adding": "Add Custom Policy", diff --git a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx index fc8b6be7b3c..7e6d0583526 100644 --- a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx +++ b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx @@ -177,7 +177,6 @@ export default function ListApis() { }} value={provider} onChange={setQuery} - // onKeyPress={this.handleSearchKeyPress} /> { provider.length > 0 && ( diff --git a/portals/admin/src/main/webapp/source/src/app/data/api.js b/portals/admin/src/main/webapp/source/src/app/data/api.js index cec3d114bea..aa552e7c900 100644 --- a/portals/admin/src/main/webapp/source/src/app/data/api.js +++ b/portals/admin/src/main/webapp/source/src/app/data/api.js @@ -461,7 +461,7 @@ class API extends Resource { */ updateApiProvider(apiId, provider) { return this.client.then((client) => { - return client.apis["Api Provider Change"].providerNamePost( + return client.apis['Api Provider Change'].providerNamePost( { provider: provider, apiId: apiId }, this._requestMetaData(), ); From 426260ecaebe104033a2bdebe2ec8a03eef3d248 Mon Sep 17 00:00:00 2001 From: Sahan Randika Date: Fri, 19 Jan 2024 14:49:23 +0530 Subject: [PATCH 18/19] fix formatting issues --- .../src/app/components/APISettings/ApisTableContent.jsx | 8 +------- .../src/app/components/APISettings/ApisTableHead.jsx | 2 +- .../source/src/app/components/APISettings/ListApis.jsx | 2 +- .../src/main/webapp/source/src/app/data/APIValidation.js | 4 ++-- 4 files changed, 5 insertions(+), 11 deletions(-) diff --git a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx index 026f2be5f99..9297233a146 100644 --- a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx +++ b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableContent.jsx @@ -1,5 +1,5 @@ /* -* Copyright (c) 2023, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. +* Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. * * WSO2 LLC. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except @@ -20,7 +20,6 @@ import React, { useState } from 'react'; import TableBody from '@material-ui/core/TableBody'; import TableCell from '@material-ui/core/TableCell'; import TableRow from '@material-ui/core/TableRow'; -import ResourceNotFound from 'AppComponents/Base/Errors/ResourceNotFound'; import PropTypes from 'prop-types'; import API from 'AppData/api'; import { makeStyles, withStyles } from '@material-ui/core/styles'; @@ -113,17 +112,12 @@ const StyledTableRow = withStyles((theme) => ({ }))(TableRow); const ApisTableContent = ({ apis, updateApiList }) => { - const [notFound] = useState(false); const restApi = new API(); const [provider, setProvider] = useState(''); const [editableRows, setEditableRows] = useState(new Set()); const classes = useStyles(); - if (notFound) { - return ; - } - const handleEditClick = (apiId) => { setEditableRows((prevRows) => { const newRows = new Set(prevRows); diff --git a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableHead.jsx b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableHead.jsx index 7521fd994d7..b7222e1b3b1 100644 --- a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableHead.jsx +++ b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ApisTableHead.jsx @@ -1,5 +1,5 @@ /* -* Copyright (c) 2023, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. +* Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. * * WSO2 LLC. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except diff --git a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx index 7e6d0583526..517434daf9d 100644 --- a/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx +++ b/portals/admin/src/main/webapp/source/src/app/components/APISettings/ListApis.jsx @@ -1,5 +1,5 @@ /* -* Copyright (c) 2023, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. +* Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. * * WSO2 LLC. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except 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 360ce277755..964d4242914 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 @@ -32,9 +32,9 @@ function getMessage(errorType, isApiName, maxLength) { case 'any.empty': return 'should not be empty'; case 'string.regex.base': - if(isApiName){ + if (isApiName) { return 'should not contain trailing or leading spaces, special characters, and consecutive spaces'; - }else{ + } else { return 'should not contain spaces or special characters'; } case 'string.max': From e015d0b335a22390e47b316d4cd2bfcd57e0ddaa Mon Sep 17 00:00:00 2001 From: Sahan Randika Date: Wed, 7 Feb 2024 09:46:11 +0530 Subject: [PATCH 19/19] fix change the owner of application test failure --- .../admin/11-change-the-owner-of-application.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cypress/integration/admin/11-change-the-owner-of-application.spec.js b/tests/cypress/integration/admin/11-change-the-owner-of-application.spec.js index a6bbb81ba17..e2ff199313f 100644 --- a/tests/cypress/integration/admin/11-change-the-owner-of-application.spec.js +++ b/tests/cypress/integration/admin/11-change-the-owner-of-application.spec.js @@ -36,7 +36,7 @@ describe("Change the owner of application", () => { //login to admin portal cy.loginToAdmin(carbonUsername, carbonPassword); - cy.get('[data-testid="Applications-child-link"]').click({ force: true }); + cy.get('[data-testid="Change Application Owner-child-link"]').click({ force: true }); cy.get("#itest-application-list-table").within(() => { cy.contains("tr", appName).within(() => { cy.get("td > span").click({ force: true });