Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
186 changes: 186 additions & 0 deletions portals/admin/src/main/webapp/site/public/locales/en.json

Large diffs are not rendered by default.

186 changes: 186 additions & 0 deletions portals/admin/src/main/webapp/site/public/locales/fr.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import ListRoles from 'AppComponents//RolePermissions/ListRoles.jsx';
import TenantConfSave from 'AppComponents/AdvancedSettings/TenantConfSave';
import Policies from 'AppComponents/Governance/Policies';
import RulesetCatalog from 'AppComponents/Governance/RulesetCatalog';
import ListTemplates from 'AppComponents/Governance/Templates';
import BusinessIcon from '@mui/icons-material/Business';
import Organizations from 'AppComponents/Organizations/ListOrganizations';

Expand All @@ -50,6 +51,7 @@ import CategoryIcon from '@mui/icons-material/Category';
import BookmarksIcon from '@mui/icons-material/Bookmarks';
import PolicyIcon from '@mui/icons-material/Policy';
import RuleIcon from '@mui/icons-material/Rule';
import LayersIcon from '@mui/icons-material/Layers';
import BlockIcon from '@mui/icons-material/Block';
import CheckCircleIcon from '@mui/icons-material/CheckCircle';
import AssignmentIcon from '@mui/icons-material/Assignment';
Expand Down Expand Up @@ -370,6 +372,34 @@ const RouteMenuMapping = (intl) => [
component: RulesetCatalog,
icon: <RuleIcon />,
},
{
id: 'Templates',
displayText: intl.formatMessage({
id: 'Base.RouteMenuMapping.governance.templates',
defaultMessage: 'Templates',
}),
path: '/governance/templates',
component: ListTemplates,
icon: <LayersIcon />,
addEditPageDetails: [
{
id: 'Create Template',
displayText: intl.formatMessage({
id: 'Base.RouteMenuMapping.governance.templates.create',
defaultMessage: 'Create Template',
}),
path: '/governance/templates/create',
},
{
id: 'Edit Template',
displayText: intl.formatMessage({
id: 'Base.RouteMenuMapping.governance.templates.edit',
defaultMessage: 'Edit Template',
}),
path: '/governance/templates/(.*?)$',
},
],
},
],
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,19 @@
rulesetContent,
documentationLink,
} = state;
const rulesetTypeOptions = artifactType === 'MCP'
? CONSTS.RULESET_TYPES.filter((option) => option.value !== 'API_DEFINITION')
: CONSTS.RULESET_TYPES;
const CONSUMER_ARTIFACT_TYPES = ['APPLICATION'];
const CONSUMER_RULE_TYPES = ['APP_INFO', 'APP_OAUTH'];

Check warning on line 134 in portals/admin/src/main/webapp/source/src/app/components/Governance/RulesetCatalog/AddEditRuleset.jsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

`CONSUMER_RULE_TYPES` should be a `Set`, and use `CONSUMER_RULE_TYPES.has()` to check existence or non-existence.

See more on https://sonarcloud.io/project/issues?id=wso2_apim-apps&issues=AZ4TutcnwyfbI-4OJMYb&open=AZ4TutcnwyfbI-4OJMYb&pullRequest=1346
const rulesetTypeOptions = (() => {
if (CONSUMER_ARTIFACT_TYPES.includes(artifactType)) {
return CONSTS.RULESET_TYPES.filter((o) => CONSUMER_RULE_TYPES.includes(o.value));
}
if (artifactType === 'MCP') {
return CONSTS.RULESET_TYPES.filter(
(o) => !CONSUMER_RULE_TYPES.includes(o.value) && o.value !== 'API_DEFINITION',
);
}
return CONSTS.RULESET_TYPES.filter((o) => !CONSUMER_RULE_TYPES.includes(o.value));
})();

useEffect(() => {
const restApi = new GovernanceAPI();
Expand Down Expand Up @@ -168,9 +178,15 @@
}, [id]);

useEffect(() => {
if (artifactType === 'MCP' && ruleType === 'API_DEFINITION') {
const isConsumerArtifact = CONSUMER_ARTIFACT_TYPES.includes(artifactType);
const isConsumerRuleType = CONSUMER_RULE_TYPES.includes(ruleType);
if (isConsumerArtifact && !isConsumerRuleType && ruleType !== '') {
dispatch({ field: 'ruleType', value: '' });
} else if (!isConsumerArtifact && isConsumerRuleType) {
dispatch({ field: 'ruleType', value: '' });
} else if (artifactType === 'MCP' && ruleType === 'API_DEFINITION') {
dispatch({ field: 'ruleType', value: '' });
}

Check warning on line 189 in portals/admin/src/main/webapp/source/src/app/components/Governance/RulesetCatalog/AddEditRuleset.jsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

This branch's code block is the same as the block for the branch on line 185.

See more on https://sonarcloud.io/project/issues?id=wso2_apim-apps&issues=AZ4TutcnwyfbI-4OJMYd&open=AZ4TutcnwyfbI-4OJMYd&pullRequest=1346
}, [artifactType, ruleType]);

const onChange = (e) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*
* Copyright (c) 2025, 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 GovernanceAPI from 'AppData/GovernanceAPI';
import PropTypes from 'prop-types';
import { FormattedMessage, useIntl } from 'react-intl';
import DialogContentText from '@mui/material/DialogContentText';
import DeleteForeverIcon from '@mui/icons-material/DeleteForever';
import IconButton from '@mui/material/IconButton';
import Tooltip from '@mui/material/Tooltip';
import FormDialogBase from 'AppComponents/AdminPages/Addons/FormDialogBase';
import Alert from 'AppComponents/Shared/Alert';

/**
* Renders delete dialog or a disabled icon for read-only (global) templates.
* @param {Object} props component properties
* @returns {JSX} Delete control
*/
function DeleteTemplate({ updateList, dataRow }) {
const { id, isReadOnly } = dataRow;
const intl = useIntl();

if (isReadOnly) {
return (
<Tooltip
title={intl.formatMessage({
id: 'Governance.Templates.Delete.readOnly.tooltip',
defaultMessage: 'Global templates can only be deleted by Super Tenant admins',
})}
>
<span>
<IconButton size='large' disabled>
<DeleteForeverIcon />
</IconButton>
</span>
</Tooltip>
);
}

const formSaveCallback = () => {
return new GovernanceAPI()
.deleteDevportalGovernanceTemplate(id)
.then(() => (
<FormattedMessage
id='Governance.Templates.Delete.success'
defaultMessage='Template deleted successfully'
/>
))
.catch((error) => {
const { response, message } = error;
if (response && response.body) {

Check warning on line 67 in portals/admin/src/main/webapp/source/src/app/components/Governance/Templates/DeleteTemplate.jsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Prefer using an optional chain expression instead, as it's more concise and easier to read.

See more on https://sonarcloud.io/project/issues?id=wso2_apim-apps&issues=AZ4TutcEwyfbI-4OJMYX&open=AZ4TutcEwyfbI-4OJMYX&pullRequest=1346
Alert.error(response.body.message);
} else if (message) {
Alert.error(message);
} else {
Alert.error(intl.formatMessage({
id: 'Governance.Templates.Delete.error',
defaultMessage: 'Something went wrong while deleting the Template',
}));
}
})
.finally(() => {
updateList();
});
};

return (
<FormDialogBase
title={intl.formatMessage({
id: 'Governance.Templates.Delete.dialog.title',
defaultMessage: 'Delete Template?',
})}
saveButtonText={intl.formatMessage({
id: 'Governance.Templates.Delete.dialog.btn',
defaultMessage: 'Delete',
})}
icon={<DeleteForeverIcon />}
formSaveCallback={formSaveCallback}
>
<DialogContentText>
<FormattedMessage
id='Governance.Templates.Delete.confirmation'
defaultMessage='Are you sure you want to delete this Template? This action cannot be undone.'
/>
</DialogContentText>
</FormDialogBase>
);
}

DeleteTemplate.propTypes = {
updateList: PropTypes.func.isRequired,
dataRow: PropTypes.shape({
id: PropTypes.string.isRequired,
isReadOnly: PropTypes.bool,
}).isRequired,
};

export default DeleteTemplate;
Loading
Loading