From 3000814e480c814b0f25c17d14d91baaceb16904 Mon Sep 17 00:00:00 2001 From: Savindu Dimal Date: Mon, 9 Sep 2024 22:12:11 +0530 Subject: [PATCH 1/2] Add changes to support AI API subscription policies Update subscription policies listing page Add new page to add/edit AI API subscription policies --- .../main/webapp/site/public/locales/en.json | 14 +- .../main/webapp/site/public/locales/fr.json | 286 ++++++- .../components/AdminPages/Addons/ListBase.jsx | 87 +- .../Throttling/Subscription/AddEdit.jsx | 767 ++++++++++++------ .../Throttling/Subscription/List.jsx | 125 ++- 5 files changed, 1014 insertions(+), 265 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 da5c4854698..bf83408fac6 100644 --- a/portals/admin/src/main/webapp/site/public/locales/en.json +++ b/portals/admin/src/main/webapp/site/public/locales/en.json @@ -73,17 +73,23 @@ "Admin.Throttling.Custom.policy.add.siddhi.query": "Siddhi Query:", "Admin.Throttling.Custom.policy.add.siddhi.query.description": "The following sample query will allow 5 requests per minute for an Admin user.", "Admin.Throttling.Custom.policy.add.siddhi.query.key.template": "Key Template : $userId", + "Admin.Throttling.Subscription.Throttling.Policy.add.completion.token.count.helper.text": "Number of completion tokens allowed", + "Admin.Throttling.Subscription.Throttling.Policy.add.prompt.token.count.helper.text": "Number of prompt tokens allowed", "Admin.Throttling.Subscription.Throttling.Policy.add.request.count.helper.text": "Number of requests allowed", "Admin.Throttling.Subscription.Throttling.Policy.add.time.days": "Day(s)", "Admin.Throttling.Subscription.Throttling.Policy.add.time.hours": "Hour(s)", "Admin.Throttling.Subscription.Throttling.Policy.add.time.minutes": "Minute(s)", "Admin.Throttling.Subscription.Throttling.Policy.add.time.months": "Month(s)", "Admin.Throttling.Subscription.Throttling.Policy.add.time.years": "Year(s)", + "Admin.Throttling.Subscription.Throttling.Policy.add.total.token.count.helper.text": "Number of total tokens allowed", + "Admin.Throttling.Subscription.Throttling.policy.table.header.completion.token.count": "Completion Token Count", "Admin.Throttling.Subscription.Throttling.policy.table.header.name": "Name", + "Admin.Throttling.Subscription.Throttling.policy.table.header.prompt.token.count": "Prompt Token Count", "Admin.Throttling.Subscription.Throttling.policy.table.header.quota": "Quota", "Admin.Throttling.Subscription.Throttling.policy.table.header.quota.policy": "Quota Policy", "Admin.Throttling.Subscription.Throttling.policy.table.header.rate.limit": "Rate Limit", "Admin.Throttling.Subscription.Throttling.policy.table.header.time.unit": "Time Unit", + "Admin.Throttling.Subscription.Throttling.policy.table.header.total.token.count": "Total Token Count", "Admin.Throttling.Subscription.Throttling.policy.table.header.unit.time": "Unit Time", "Admin.components.form.delete.btn": "Delete", "AdminPages.Addons.InlineProgress.message": "Loading...", @@ -780,6 +786,7 @@ "Throttling.Subscription.AddEdit.form.add": "Save", "Throttling.Subscription.AddEdit.form.add.data.amount.helper.text": "Bandwidth allowed", "Throttling.Subscription.AddEdit.form.cancel": "Cancel", + "Throttling.Subscription.AddEdit.form.completionTokenCount.count": "Completion Token Count", "Throttling.Subscription.AddEdit.form.dataAmount.name": "Data Bandwidth", "Throttling.Subscription.AddEdit.form.description": "Description", "Throttling.Subscription.AddEdit.form.description.help": "Description of the rate limiting policy", @@ -790,8 +797,10 @@ "Throttling.Subscription.AddEdit.form.max.webhooks.connections": "Max Subscriptions", "Throttling.Subscription.AddEdit.form.name.help": "Name of the rate limiting policy", "Throttling.Subscription.AddEdit.form.policyName": "Name", + "Throttling.Subscription.AddEdit.form.promptTokenCount.count": "Prompt Token Count", "Throttling.Subscription.AddEdit.form.request.rate": "Request Rate", "Throttling.Subscription.AddEdit.form.requestCount.count": "Request Count", + "Throttling.Subscription.AddEdit.form.totalTokenCount.count": "Total Token Count", "Throttling.Subscription.AddEdit.form.unit.time.label": "Unit Time", "Throttling.Subscription.AddEdit.general.details": "General Details", "Throttling.Subscription.AddEdit.general.details.description": "Provide the name and description of the subscription policy.", @@ -801,11 +810,14 @@ "Throttling.Subscription.AddEdit.permissions.add.role.placeholder": "Type roles and press Enter", "Throttling.Subscription.AddEdit.policy.flags.add.description": "Define the billing plan for the subscription policy. Enable stop on quota reach to block invoking an API when the defined quota is reached.", "Throttling.Subscription.AddEdit.quota.limits": "Quota Limits", + "Throttling.Subscription.AddEdit.quota.limits.ai.description": "Specify the quota limits for AI API Subscription policy.", "Throttling.Subscription.AddEdit.quota.policies.add.description": "Request Count and Request Bandwidth are the two options for Quota Limit. You can use the option according to your requirement.", "Throttling.Subscription.AddEdit.quota.policies.add.limits.event.count": "Event Based (Async API)", "Throttling.Subscription.AddEdit.quota.policies.add.limits.request.bandwidth": "Request Bandwidth", "Throttling.Subscription.AddEdit.quota.policies.add.limits.request.count": "Request Count", "Throttling.Subscription.AddEdit.subscription.count.add.description": "Maximum number of webhooks allowed for a Webhooks API using this policy.", + "Throttling.Subscription.AddEdit.title.AIPolicy.add": "AI API Subscription Rate Limiting Policy - Create new", + "Throttling.Subscription.AddEdit.title.AIPolicy.edit": "AI API Subscription Rate Limiting Policy - Edit", "Throttling.Subscription.AddEdit.title.add": "Subscription Rate Limiting Policy - Create new", "Throttling.Subscription.AddEdit.title.edit": "Subscription Rate Limiting Policy - Edit", "Throttling.Subscription.AddEdit.unitTime": "Unit Time", @@ -1038,4 +1050,4 @@ "error.list.404.description": "The page you are looking for might have been removed, had its name changed or is temporarily unavailable.", "error.list.500": "500 : The page cannot be displayed.", "error.list.500.description": "The server encountered an internal error or misconfiguration and was unable to complete your request." -} \ No newline at end of file +} 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 9b13680f20f..bf83408fac6 100644 --- a/portals/admin/src/main/webapp/site/public/locales/fr.json +++ b/portals/admin/src/main/webapp/site/public/locales/fr.json @@ -1,4 +1,5 @@ { + "Admin.Addons.Help.Base.title": "Help", "Admin.KeyManager.form.type": "Key Manager Type", "Admin.KeyManager.label.ConsumerKey.Claim": "Consumer Key Claim URI", "Admin.KeyManager.label.DisplayName": "Display Name", @@ -22,38 +23,95 @@ "Admin.Throttling.Application.Throttling.Policy.add.name.helper.text": "Name of the throttle policy", "Admin.Throttling.Application.Throttling.Policy.add.quota.limits.details": "Quota Limits", "Admin.Throttling.Application.Throttling.Policy.add.request.count.helper.text": "Number of requests allowed", + "Admin.Throttling.Application.Throttling.Policy.add.save.btn": "Save", + "Admin.Throttling.Application.Throttling.Policy.add.time.days": "Day(s)", "Admin.Throttling.Application.Throttling.Policy.add.time.helper.text": "Time configuration", + "Admin.Throttling.Application.Throttling.Policy.add.time.hours": "Hour(s)", + "Admin.Throttling.Application.Throttling.Policy.add.time.minutes": "Minute(s)", + "Admin.Throttling.Application.Throttling.Policy.add.time.months": "Month(s)", + "Admin.Throttling.Application.Throttling.Policy.add.time.weeks": "Week(s)", + "Admin.Throttling.Application.Throttling.Policy.add.time.years": "Year(s)", + "Admin.Throttling.Application.Throttling.Policy.form.description": "Description", + "Admin.Throttling.Application.Throttling.Policy.form.policyName": "Name", + "Admin.Throttling.Application.Throttling.Policy.option.data.bandwidth.label": "Data Bandwith", + "Admin.Throttling.Application.Throttling.Policy.option.request.bandwidth.label": "Request Bandwidth", + "Admin.Throttling.Application.Throttling.Policy.option.request.count.label": "Request Count", + "Admin.Throttling.Application.Throttling.Policy.option.request.unit.time.label": "Unit Time", "Admin.Throttling.Application.Throttling.policy.table.header.name": "Name", "Admin.Throttling.Application.Throttling.policy.table.header.quota": "Quota", "Admin.Throttling.Application.Throttling.policy.table.header.unit.time": "Unit Time", "Admin.Throttling.Blacklist.Throttling.Policy.add.condition.type": "Condition Type", + "Admin.Throttling.Blacklist.Throttling.Policy.add.condition.type.User": "User", + "Admin.Throttling.Blacklist.Throttling.Policy.add.condition.type.api.context": "API Context", + "Admin.Throttling.Blacklist.Throttling.Policy.add.condition.type.api.context.format": "Format : ${context}", + "Admin.Throttling.Blacklist.Throttling.Policy.add.condition.type.application": "Application", + "Admin.Throttling.Blacklist.Throttling.Policy.add.condition.type.application.format": "Format : ${userName}:${applicationName}", + "Admin.Throttling.Blacklist.Throttling.Policy.add.condition.type.enable.condition": "Enable Condition", + "Admin.Throttling.Blacklist.Throttling.Policy.add.condition.type.ip.address": "IP Address", + "Admin.Throttling.Blacklist.Throttling.Policy.add.condition.type.ip.format": "Format : ${ip}", + "Admin.Throttling.Blacklist.Throttling.Policy.add.condition.type.ip.range": "IP Range", + "Admin.Throttling.Blacklist.Throttling.Policy.add.condition.type.user.format": "Format : ${userName}", + "Admin.Throttling.Blacklist.Throttling.Policy.add.condition.type.value.ip.end.address": "End IP Address", + "Admin.Throttling.Blacklist.Throttling.Policy.add.condition.type.value.ip.start.address": "Start IP Address", + "Admin.Throttling.Blacklist.Throttling.Policy.add.condition.type.value.label": "Value", + "Admin.Throttling.Blacklist.Throttling.Policy.add.dialog.btn.deny": "Deny", + "Admin.Throttling.Blacklist.Throttling.Policy.example.abbr": "Eg", "Admin.Throttling.Blacklist.Throttling.policy.table.header.condition.status": "Condition Status", "Admin.Throttling.Blacklist.Throttling.policy.table.header.condition.type": "Condition Type", "Admin.Throttling.Blacklist.Throttling.policy.table.header.conditional.value": "Conditional Value", "Admin.Throttling.Blacklist.policy.add.invert.condition": "Invert Condition:", "Admin.Throttling.Blacklist.policy.enable.condition": "Enable Condition", + "Admin.Throttling.Custom.Throttling.policy.add.field.description": "Description", + "Admin.Throttling.Custom.Throttling.policy.add.field.key.template": "Key Template", + "Admin.Throttling.Custom.Throttling.policy.add.field.name": "Name", "Admin.Throttling.Custom.Throttling.policy.table.header.description": "Description", "Admin.Throttling.Custom.Throttling.policy.table.header.key.template": "Key Template", "Admin.Throttling.Custom.Throttling.policy.table.header.name": "Name", + "Admin.Throttling.Custom.policy.add.key.template.helper.text": "Eg: $userId:$apiContext:$apiVersion", "Admin.Throttling.Custom.policy.add.policy.description": "Description of the throttle policy", "Admin.Throttling.Custom.policy.add.policy.name": "Name of the throttle policy", "Admin.Throttling.Custom.policy.add.siddhi.query": "Siddhi Query:", "Admin.Throttling.Custom.policy.add.siddhi.query.description": "The following sample query will allow 5 requests per minute for an Admin user.", "Admin.Throttling.Custom.policy.add.siddhi.query.key.template": "Key Template : $userId", + "Admin.Throttling.Subscription.Throttling.Policy.add.completion.token.count.helper.text": "Number of completion tokens allowed", + "Admin.Throttling.Subscription.Throttling.Policy.add.prompt.token.count.helper.text": "Number of prompt tokens allowed", + "Admin.Throttling.Subscription.Throttling.Policy.add.request.count.helper.text": "Number of requests allowed", + "Admin.Throttling.Subscription.Throttling.Policy.add.time.days": "Day(s)", + "Admin.Throttling.Subscription.Throttling.Policy.add.time.hours": "Hour(s)", + "Admin.Throttling.Subscription.Throttling.Policy.add.time.minutes": "Minute(s)", + "Admin.Throttling.Subscription.Throttling.Policy.add.time.months": "Month(s)", + "Admin.Throttling.Subscription.Throttling.Policy.add.time.years": "Year(s)", + "Admin.Throttling.Subscription.Throttling.Policy.add.total.token.count.helper.text": "Number of total tokens allowed", + "Admin.Throttling.Subscription.Throttling.policy.table.header.completion.token.count": "Completion Token Count", "Admin.Throttling.Subscription.Throttling.policy.table.header.name": "Name", + "Admin.Throttling.Subscription.Throttling.policy.table.header.prompt.token.count": "Prompt Token Count", "Admin.Throttling.Subscription.Throttling.policy.table.header.quota": "Quota", "Admin.Throttling.Subscription.Throttling.policy.table.header.quota.policy": "Quota Policy", "Admin.Throttling.Subscription.Throttling.policy.table.header.rate.limit": "Rate Limit", "Admin.Throttling.Subscription.Throttling.policy.table.header.time.unit": "Time Unit", + "Admin.Throttling.Subscription.Throttling.policy.table.header.total.token.count": "Total Token Count", "Admin.Throttling.Subscription.Throttling.policy.table.header.unit.time": "Unit Time", + "Admin.components.form.delete.btn": "Delete", "AdminPages.Addons.InlineProgress.message": "Loading...", "AdminPages.Addons.ListBase.noDataError": "Error while retrieving data.", "AdminPages.Addons.ListBase.nodata.message": "No items yet", "AdminPages.Addons.ListBase.reload": "Reload", "AdminPages.ApiCategories.AddEdit.form.add.successful": "API Category added successfully", + "AdminPages.ApiCategories.AddEdit.form.description": "Description", + "AdminPages.ApiCategories.AddEdit.form.description.helper.text": "Description of the API category", "AdminPages.ApiCategories.AddEdit.form.edit.successful": "API Category edited successfully", + "AdminPages.ApiCategories.AddEdit.form.error.description.too.long": "API Category description is too long", + "AdminPages.ApiCategories.AddEdit.form.error.name.empty": "Name is Empty", + "AdminPages.ApiCategories.AddEdit.form.error.name.has.spaces": "Name contains spaces", + "AdminPages.ApiCategories.AddEdit.form.error.name.has.special.chars": "Name field contains special characters", + "AdminPages.ApiCategories.AddEdit.form.error.name.too.long": "API Category name is too long", "AdminPages.ApiCategories.AddEdit.form.name": "Name", + "AdminPages.ApiCategories.AddEdit.form.name.helper.text": "Name of the API category", + "AdminPages.ApiCategories.AddEdit.form.save.btn": "Save", + "AdminPages.ApiCategories.Delete.form.delete.btn": "Delete", + "AdminPages.ApiCategories.Delete.form.delete.content": "Are you sure you want to delete this API Category?", "AdminPages.ApiCategories.Delete.form.delete.successful": "API Category deleted successfully", + "AdminPages.ApiCategories.Delete.form.delete.title": "Delete API category?", "AdminPages.ApiCategories.List.addButtonProps.title": "Add API Category", "AdminPages.ApiCategories.List.addButtonProps.triggerButtonText": "Add API Category", "AdminPages.ApiCategories.List.empty.content.apicategories": "You can use API categories to group APIs. In previous versions of WSO2 API Manager, the process of grouping APIs was carried out by using tag-wise groups. Unlike tag-wise grouping, API categories do not use a naming convention. Therefore, the admin does not need to take into consideration any naming conventions when using API category-based grouping.", @@ -66,12 +124,15 @@ "AdminPages.ApiCategories.table.header.category.number.of.apis": "Number of APIs", "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.provider.label": "Provider Name", "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", + "AdminPages.Gateways.Delete.form.delete.confirmation.delete.btn": "Delete", "AdminPages.Gateways.Delete.form.delete.confirmation.message": "Are you sure you want to delete this Gateway Environment?", + "AdminPages.Gateways.Delete.form.delete.confirmation.message.title": "Delete Gateway Environment?", "AdminPages.Gateways.Delete.form.delete.successful": "Gateway Environment deleted successfully", "AdminPages.Gateways.List.addButtonProps.title": "Add Gateway Environment", "AdminPages.Gateways.List.addButtonProps.triggerButtonText": "Add Gateway Environment", @@ -85,8 +146,12 @@ "AdminPages.Gateways.table.header.type": "Type", "AdminPages.Gateways.table.header.vhosts": "Virtual Host(s)", "AdminPages.KeyManager.Delete.form.delete.confirmation.message": "Are you sure you want to delete this KeyManager ?", + "AdminPages.KeyManagers.Delete.form.delete.dialog.btn": "Delete", + "AdminPages.KeyManagers.Delete.form.delete.dialog.title": "Delete KeyManager ?", "AdminPages.KeyManagers.Delete.form.delete.successful": "KeyManager deleted successfully", "AdminPages.KeyManagers.List.empty.content.keymanagers": "It is possible to register an OAuth Provider.", + "AdminPages.KeyManagers.Usages.dialog.close.btn": "Close", + "AdminPages.KeyManagers.Usages.dialog.title": "Key Manager Usages -", "AdminPagesGatewayEnvironments.AddEditGWEnvironment.form.environment.displayName.empty": "Display Name is Empty", "AdminPagesGatewayEnvironments.AddEditGWEnvironment.form.environment.vhost.duplicate": "VHosts are duplicated", "AdminPagesGatewayEnvironments.AddEditGWEnvironment.form.environment.vhost.empty": "VHost is empty", @@ -94,6 +159,9 @@ "Api.Provider": "Provider", "Api.Version": "Version", "Apis.Details.Scopes.CreateScope.roles.help": "Enter a valid role and press `Enter`.", + "Apis.Details.Scopes.permission.status.allow": "Allow", + "Apis.Details.Scopes.permission.status.deny": "Deny", + "Apis.Details.Scopes.permission.status.none": "None", "Apis.Listing.Listing.apis.search": "Search", "Apis.Listing.Listing.apis.search.label": "Search by API", "Apis.Listing.Listing.apis.searching": "Searching", @@ -119,12 +187,26 @@ "Applications.Listing.ApplicationTableHead.actions": "Actions", "Applications.Listing.ApplicationTableHead.name": "Name", "Applications.Listing.ApplicationTableHead.owner": "Owner", + "Applications.Listing.Listing.applications.edit.error.already.exist": "{owner} already has an application with name: {name}", + "Applications.Listing.Listing.applications.edit.error.default": "Something went wrong when validating user", + "Applications.Listing.Listing.applications.edit.error.owner.invalid": "{owner} is not a valid Subscriber", + "Applications.Listing.Listing.applications.edit.error.subscriber.invalid": "Error while updating ownership to {owner}", + "Applications.Listing.Listing.applications.edit.error.unknown": "Something went wrong when updating owner", + "Applications.Listing.Listing.applications.edit.owner.label": "Owner", + "Applications.Listing.Listing.applications.edit.save.btn": "Save", + "Applications.Listing.Listing.applications.list.rows.more.than.label": "more than {to}", + "Applications.Listing.Listing.applications.list.rows.range.label": "{from}-{to} of {count}", + "Applications.Listing.Listing.applications.list.rows.show.label": "Show", + "Applications.Listing.Listing.applications.list.title": "Change Application Owner", "Applications.Listing.Listing.applications.search": "Search", "Applications.Listing.Listing.applications.search.label": "Search Application by Application Owner", "Applications.Listing.Listing.applications.searching": "Searching", "Applications.Listing.Listing.clear.search": "Clear Search", "Applications.Listing.Listing.empty.message": "No Data to Display", "Applications.Listing.Listing.search.placeholder": "Application Owner", + "Applications.Listing.apis.list.rows.more.than.label": "more than {to}", + "Applications.Listing.apis.list.rows.range.label": "{from}-{to} of {count}", + "Applications.Listing.apis.list.rows.show.label": "Show", "Base.Errors.ResourceNotFound.api.list": "API List", "Base.Errors.ResourceNotFound.api.product.list": "API Product List", "Base.Errors.ResourceNotFound.more.links": "You may check the links below", @@ -137,9 +219,13 @@ "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.api.product.state.change": "API Product State Change", + "Base.RouteMenuMapping.api.revision.deployment": "API Revision Deployment", + "Base.RouteMenuMapping.api.state.change": "API State Change", "Base.RouteMenuMapping.apis": "Change API Provider", "Base.RouteMenuMapping.application.creation": "Application Creation", "Base.RouteMenuMapping.application.deletion": "Application Deletion", + "Base.RouteMenuMapping.application.reg": "Application Registration", "Base.RouteMenuMapping.application.throttling.policies": "Application Policies", "Base.RouteMenuMapping.applications": "Change Application Owner", "Base.RouteMenuMapping.blacklisted.items": "Deny Policies", @@ -169,7 +255,9 @@ "Dashboard.apiCategories.apiCategoriesListing.no.description": "No description available", "Dashboard.apiCategories.noApiCategories.card.add.new.link.text": "Add new Category", "Dashboard.apiCategories.noApiCategories.card.description": "API categories allow API providers to categorize APIs that have similar attributes. When a categorized API gets published to the Developer Portal, its categories appear as clickable links to the API consumers. The API consumers can use the available API categories to quickly jump to a category of interest. {learnMoreLink}", + "Dashboard.apiCategories.noApiCategories.card.document.link.text": "Go to Category Documentation", "Dashboard.apiCategories.noApiCategories.card.title": "API Category based grouping", + "Dashboard.header.title": "Dashboard", "Dashboard.rateLimiting.card.advancedPolicies.description": "Control access per API or API resource using advanced rules", "Dashboard.rateLimiting.card.advancedPolicies.name": "Advanced Policies", "Dashboard.rateLimiting.card.applicationPolicies.description": "Applicable per access token generated for an application", @@ -194,19 +282,43 @@ "Dashboard.tasksWorkflow.compactTasks.userCreation.name": "User Creation", "Dashboard.tasksWorkflow.noTasks.card.description": "Manage workflow tasks, increase productivity and enhance competitiveness by enabling developers to easily deploy business processes and models.", "Dashboard.tasksWorkflow.noTasks.card.title": "All the pending tasks completed", + "Form.Dialog.Base.cancel.btn": "Cancel", "GatewayEnvironments.AddEditGWEnvironment.form.description.help": "Description of the Gateway Environment", + "GatewayEnvironments.AddEditGWEnvironment.form.description.label": "Description", "GatewayEnvironments.AddEditGWEnvironment.form.displayName": "Display Name", "GatewayEnvironments.AddEditGWEnvironment.form.displayName.help": "Display name of the Gateway Environment", "GatewayEnvironments.AddEditGWEnvironment.form.environment.name.empty": "Name is Empty", "GatewayEnvironments.AddEditGWEnvironment.form.environment.name.invalid": "Name must not contain special characters or spaces", + "GatewayEnvironments.AddEditGWEnvironment.form.gateway.type.apk": "APK Gateway", + "GatewayEnvironments.AddEditGWEnvironment.form.gateway.type.apk.description": "Fast API gateway running on kubernetes designed to manage and secure APIs.", + "GatewayEnvironments.AddEditGWEnvironment.form.gateway.type.apk.new.label": "New", + "GatewayEnvironments.AddEditGWEnvironment.form.gateway.type.label": "Select Gateway type", + "GatewayEnvironments.AddEditGWEnvironment.form.gateway.type.regular": "Regular Gateway", + "GatewayEnvironments.AddEditGWEnvironment.form.gateway.type.regular.description": "API gateway embedded in APIM runtime. Connect directly to an existing APIManager.", "GatewayEnvironments.AddEditGWEnvironment.form.info.add.successful": "Gateway Environment added successfully", "GatewayEnvironments.AddEditGWEnvironment.form.info.edit.successful": "Gateway Environment edited successfully", "GatewayEnvironments.AddEditGWEnvironment.form.name": "Name", + "GatewayEnvironments.AddEditGWEnvironment.form.name.help": "Name of the Gateway Environment", "GatewayEnvironments.AddEditGWEnvironment.form.save.button.label": "Save", + "GatewayEnvironments.AddEditGWEnvironment.form.type.helper.text": "Supported Key Type of the Gateway Environment", + "GatewayEnvironments.AddEditGWEnvironment.form.type.hybrid.option": "Hybrid", + "GatewayEnvironments.AddEditGWEnvironment.form.type.label": "Type", + "GatewayEnvironments.AddEditGWEnvironment.form.type.prod.option": "Production", + "GatewayEnvironments.AddEditGWEnvironment.form.type.sandbox.option": "Sandbox", "GatewayEnvironments.AddEditGWEnvironment.form.vhost.context.invalid": "Invalid Http context", "GatewayEnvironments.AddEditGWEnvironment.form.vhost.host.empty": "Host of Vhost is empty", "GatewayEnvironments.AddEditGWEnvironment.form.vhost.host.invalid": "Invalid Host", + "GatewayEnvironments.AddEditVhost.add.vhost.btn": "New VHost", "GatewayEnvironments.AddEditVhost.host": "Host", + "GatewayEnvironments.AddEditVhost.host.gateway.access.url": "Gateway Access URLs", + "GatewayEnvironments.AddEditVhost.host.gateway.advanced.settings": "Advanced Settings", + "GatewayEnvironments.AddEditVhost.host.gateway.http.context": "HTTP(s) context", + "GatewayEnvironments.AddEditVhost.host.helper.text": "ex: mg.wso2.com", + "GatewayEnvironments.AddEditVhost.host.remove.btn": "Remove", + "GatewayEnvironments.AddEditVhost.host.remove.dialog.content": "Removing an existing VHost may result in inconsistent state if APIs are deployed with this VHost. Please make sure there are no APIs deployed with this VHost or redeploy those APIs.", + "GatewayEnvironments.AddEditVhost.host.remove.dialog.no.btn": "No, Don't Remove", + "GatewayEnvironments.AddEditVhost.host.remove.dialog.title": "Remove Existing Vhost?", + "GatewayEnvironments.AddEditVhost.host.remove.dialog.yes.btn": "Yes", "GatewayEnvironments.AddEditVhost.httpPort": "HTTP Port", "GatewayEnvironments.AddEditVhost.httpsPort": "HTTPS Port", "GatewayEnvironments.AddEditVhost.wsPort": "WS Port", @@ -226,9 +338,7 @@ "KeyManager.enter.permission.allowed": "Use of this Key-Manager is \"Allowed\" for above roles.", "KeyManager.enter.permission.denied": "Use of this Key-Manager is \"Denied\" for above roles.", "KeyManager.permissions": "Permissions", - "KeyManagers.AddEditKeyManager.\n form.scopeManagementEndpoint": "Scope Management Endpoint", - "KeyManagers.AddEditKeyManager.\n form.displayRevokeEndpoint": "Display Revoke Endpoint", - "KeyManagers.AddEditKeyManager.External.KeyManager\n .general.details.description": "Identity Provider vendor and the token usage mode", + "KeyManagers.AddEditKeyManager.External.KeyManager.general.details.description": "Identity Provider vendor and the token usage mode", "KeyManagers.AddEditKeyManager.KeyManager.type": "Key Manager Type", "KeyManagers.AddEditKeyManager.advanced": "Advanced Configurations", "KeyManagers.AddEditKeyManager.advanced.description": "Advanced options for the Key Manager", @@ -245,15 +355,15 @@ "KeyManagers.AddEditKeyManager.connector.configurations.description": "Provide connection params for the selected Key Manager.", "KeyManagers.AddEditKeyManager.endpoints": "Key Manager Endpoints", "KeyManagers.AddEditKeyManager.endpoints.description": "Configure endpoints such as client registration endpoint, the token endpoint for this Key Manager.", - "KeyManagers.AddEditKeyManager.exchange.token.form.\n token.audience.help": "The Audience of the authorization server which the access token is intended for.", - "KeyManagers.AddEditKeyManager.form.\n clientRegistrationEndpoint": "Client Registration Endpoint", - "KeyManagers.AddEditKeyManager.form.\n introspectionEndpoint": "Introspection Endpoint", + "KeyManagers.AddEditKeyManager.exchange.token.form.token.audience.help": "The Audience of the authorization server which the access token is intended for.", "KeyManagers.AddEditKeyManager.form.Issuer": "Issuer", "KeyManagers.AddEditKeyManager.form.add": "Add", "KeyManagers.AddEditKeyManager.form.authorizeEndpoint": "Authorize Endpoint", "KeyManagers.AddEditKeyManager.form.authorizeEndpoint.help": "E.g., https://localhost:9443/oauth2/userinfo", "KeyManagers.AddEditKeyManager.form.cancel": "Cancel", "KeyManagers.AddEditKeyManager.form.claim.help": "Type Available Grant Types and press Enter/Return to add them.", + "KeyManagers.AddEditKeyManager.form.claim.placeholder": "Type Grant Types and press Enter", + "KeyManagers.AddEditKeyManager.form.clientRegistrationEndpoint": "Client Registration Endpoint", "KeyManagers.AddEditKeyManager.form.clientRegistrationEndpoint.help": "E.g., https://localhost:9444/client-registration/v0.17/register", "KeyManagers.AddEditKeyManager.form.consumerKeyClaim.help": "Provide consumer key claim URIs.", "KeyManagers.AddEditKeyManager.form.description": "Description", @@ -262,12 +372,14 @@ "KeyManagers.AddEditKeyManager.form.displayRevokeEndpoint": "Display Revoke Endpoint", "KeyManagers.AddEditKeyManager.form.displayTokenEndpoint": "Display Token Endpoint", "KeyManagers.AddEditKeyManager.form.has.errors": "One or more fields contain errors.", + "KeyManagers.AddEditKeyManager.form.introspectionEndpoint": "Introspection Endpoint", "KeyManagers.AddEditKeyManager.form.introspectionEndpoint.help": "E.g., https://localhost:9443/oauth2/introspect", "KeyManagers.AddEditKeyManager.form.issuer.help": "E.g.,: https://localhost:9443/oauth2/token", "KeyManagers.AddEditKeyManager.form.name": "Name", "KeyManagers.AddEditKeyManager.form.name.help": "Name of the Key Manager.", "KeyManagers.AddEditKeyManager.form.revokeEndpoint": "Revoke Endpoint", "KeyManagers.AddEditKeyManager.form.revokeEndpoint.help": "E.g., https://localhost:9443/oauth2/revoke", + "KeyManagers.AddEditKeyManager.form.scopeManagementEndpoint": "Scope Management Endpoint", "KeyManagers.AddEditKeyManager.form.scopeManagementEndpoint.help": "E.g, https://localhost:9443/oauth2/scope", "KeyManagers.AddEditKeyManager.form.scopesClaim.help": "Provide scope claim URI.", "KeyManagers.AddEditKeyManager.form.token.audience.help": "The Audience of the authorization server which the access token is intended for.", @@ -313,20 +425,28 @@ "KeyManagers.Certificates.paste.label": "Paste the content of the PEM file", "KeyManagers.ListKeyManagerAPIUsages.error": "Unable to get Key Manager API usage details", "KeyManagers.ListKeyManagerApplicationUsages.error": "Unable to get Key Manager application usage details", + "KeyManagers.ListKeyManagerUsages.API.usages.count.multiple": "{count} APIs are using this key manager specifically", + "KeyManagers.ListKeyManagerUsages.API.usages.count.one": "1 API is using this key manager specifically.", + "KeyManagers.ListKeyManagerUsages.Application.usages.count.multiple": "{count} Applications are using this key manager specifically", + "KeyManagers.ListKeyManagerUsages.Application.usages.count.one": "1 Application is using this key manager specifically.", "KeyManagers.ListKeyManagerUsages.empty.content": "There are no Key Manger usages.", "KeyManagers.ListKeyManagerUsages.empty.title": "Key Manager Usages", "KeyManagers.ListKeyManagerUsages.permission.denied.content": "You dont have enough permission to view Key Manager Usages. Please contact the site administrator.", "KeyManagers.ListKeyManagerUsages.permission.denied.title": "Permission Denied", + "KeyManagers.ListKeyManagerUsages.tab.API.usages": "API Usages", + "KeyManagers.ListKeyManagerUsages.tab.Application.usages": "Application Usages", "KeyManagers.ListKeyManagers.List.title": "Key Managers", "KeyManagers.ListKeyManagers.addButtonProps.triggerButtonText": "Add Key Manager", "KeyManagers.ListKeyManagers.addGlobalKeyManager": "Add Global Key Manager", "KeyManagers.ListKeyManagers.edit.success": "Key Manager updated successfully.", "KeyManagers.ListKeyManagers.empty.title": "Key Managers", + "KeyManagers.ListKeyManagers.table.global.delete.tooltip": "Global Key Manager only can be deleted by the super admin user", "KeyManagers.ListKeyManagers.table.header.label.description": "Description", "KeyManagers.ListKeyManagers.table.header.label.name": "Name", "KeyManagers.ListKeyManagers.table.header.label.provider": "Provider", "KeyManagers.ListKeyManagers.table.header.label.tokenType": "Type", "KeyManagers.ListKeyManagers.table.header.label.usage": "Usage", + "KeyManagers.ListKeyManagers.table.is.used.delete.tooltip": "Key manager is used by an API or an Application", "Keymanager.Claim.Action": "Action", "Keymanager.KeyValidation.Action": "Action", "Keymanager.KeyValidation.ClaimKey": "Claim Key", @@ -338,20 +458,131 @@ "LoginDenied.message": "The server could not verify that you are authorized to access the requested resource.", "LoginDenied.retry": "Retry", "LoginDenied.title": "Error 403 : Forbidden", + "Mui.data.table.filter.icon.label": "Filter Table", + "Mui.data.table.pagination.display.rows": "of", + "Mui.data.table.pagination.rows.per.page": "Rows per page:", + "Mui.data.table.search.icon.label": "Search", + "Mui.data.table.search.no.records.found": "Sorry, no matching records found", + "PERMISSION_TREE.apim.admin": "Manage all admin operations", + "PERMISSION_TREE.apim.admin_alert_manage": "Manage admin alerts", + "PERMISSION_TREE.apim.admin_application_view": "View Applications", + "PERMISSION_TREE.apim.admin_operations": "Manage API categories and Key Managers related operations", + "PERMISSION_TREE.apim.admin_settings": "Retrieve admin settings", + "PERMISSION_TREE.apim.admin_tier_manage": "Update and delete throttling policies", + "PERMISSION_TREE.apim.admin_tier_view": "View throttling policies", + "PERMISSION_TREE.apim.api_category": "Manage API categories", + "PERMISSION_TREE.apim.api_create": "Create API", + "PERMISSION_TREE.apim.api_definition_view": "View, Retrieve API definition", + "PERMISSION_TREE.apim.api_delete": "Delete API", + "PERMISSION_TREE.apim.api_generate_key": "Generate Internal Key", + "PERMISSION_TREE.apim.api_import_export": "Import and export APIs related operations", + "PERMISSION_TREE.apim.api_key": "Generate API Keys", + "PERMISSION_TREE.apim.api_list_view": "View, Retrieve API list", + "PERMISSION_TREE.apim.api_manage": "Manage all API related operations", + "PERMISSION_TREE.apim.api_mediation_policy_manage": "View, create, update and remove API specific mediation policies", + "PERMISSION_TREE.apim.api_product_import_export": "Import and export API Products related operations", + "PERMISSION_TREE.apim.api_provider_change": "Retrieve and manage applications", + "PERMISSION_TREE.apim.api_publish": "Publish API", + "PERMISSION_TREE.apim.api_view": "View API", + "PERMISSION_TREE.apim.api_workflow_approve": "Manage workflows", + "PERMISSION_TREE.apim.api_workflow_view": "Retrive workflow requests", + "PERMISSION_TREE.apim.app_import_export": "Import and export applications related operations", + "PERMISSION_TREE.apim.app_manage": "Retrieve, Manage and Import, Export applications", + "PERMISSION_TREE.apim.app_owner_change": "Retrieve and manage applications", + "PERMISSION_TREE.apim.bl_manage": "Update and delete deny policies", + "PERMISSION_TREE.apim.bl_view": "View deny policies", + "PERMISSION_TREE.apim.bot_data": "Retrieve bot detection data", + "PERMISSION_TREE.apim.client_certificates_add": "Add client certificates", + "PERMISSION_TREE.apim.client_certificates_manage": "View, create, update and remove client certificates", + "PERMISSION_TREE.apim.client_certificates_update": "Update and delete client certificates", + "PERMISSION_TREE.apim.client_certificates_view": "View client certificates", + "PERMISSION_TREE.apim.comment_manage": "Read and Write comments", + "PERMISSION_TREE.apim.comment_view": "Read permission to comments", + "PERMISSION_TREE.apim.comment_write": "Write permission to comments", + "PERMISSION_TREE.apim.common_operation_policy_manage": "Add, Update and Delete common operation policies", + "PERMISSION_TREE.apim.common_operation_policy_view": "View common operation policies", + "PERMISSION_TREE.apim.document_create": "Create API documents", + "PERMISSION_TREE.apim.document_manage": "Create, update and delete API documents", + "PERMISSION_TREE.apim.environment_manage": "Manage gateway environments", + "PERMISSION_TREE.apim.environment_read": "Retrieve gateway environments", + "PERMISSION_TREE.apim.ep_certificates_add": "Add backend endpoint certificates", + "PERMISSION_TREE.apim.ep_certificates_manage": "View, create, update and remove endpoint certificates", + "PERMISSION_TREE.apim.ep_certificates_update": "Update and delete backend endpoint certificates", + "PERMISSION_TREE.apim.ep_certificates_view": "View backend endpoint certificates", + "PERMISSION_TREE.apim.gateway_policy_manage": "Add, Update and Delete gateway policies", + "PERMISSION_TREE.apim.gateway_policy_view": "View gateway policies", + "PERMISSION_TREE.apim.keymanagers_manage": "Manage Key Managers", + "PERMISSION_TREE.apim.mediation_policy_create": "Create mediation policies", + "PERMISSION_TREE.apim.mediation_policy_manage": "Update and delete mediation policies", + "PERMISSION_TREE.apim.mediation_policy_view": "View mediation policies", + "PERMISSION_TREE.apim.monetization_usage_publish": "Retrieve and publish Monetization related usage records", + "PERMISSION_TREE.apim.policies_import_export": "Export and import policies related operations", + "PERMISSION_TREE.apim.pub_alert_manage": "Get/ subscribe/ configure publisher alerts", + "PERMISSION_TREE.apim.publisher_settings": "Retrieve store settings", + "PERMISSION_TREE.apim.role_manage": "Manage system roles", + "PERMISSION_TREE.apim.scope_manage": "Manage system scopes", + "PERMISSION_TREE.apim.shared_scope_manage": "Manage shared scopes", + "PERMISSION_TREE.apim.store_settings": "Retrieve Developer Portal settings", + "PERMISSION_TREE.apim.sub_alert_manage": "Retrieve, subscribe and configure Developer Portal alert types", + "PERMISSION_TREE.apim.sub_manage": "Retrieve, Manage subscriptions", + "PERMISSION_TREE.apim.subscribe": "Subscribe API", + "PERMISSION_TREE.apim.subscription_block": "Block Subscription", + "PERMISSION_TREE.apim.subscription_manage": "Manage all Subscription related operations", + "PERMISSION_TREE.apim.subscription_view": "View Subscription", + "PERMISSION_TREE.apim.tenantInfo": "Retrieve tenant related information", + "PERMISSION_TREE.apim.tenant_theme_manage": "Manage tenant themes", + "PERMISSION_TREE.apim.threat_protection_policy_create": "Create threat protection policies", + "PERMISSION_TREE.apim.threat_protection_policy_manage": "Update and delete threat protection policies", + "PERMISSION_TREE.apim.tier_manage": "View, update and delete throttling policies", + "PERMISSION_TREE.apim.tier_view": "View throttling policies", + "PERMISSION_TREE.service_catalog.service_view": "view access to services in service catalog", + "PERMISSION_TREE.service_catalog.service_write": "write access to services in service catalog", + "Permissions.tree.scope.assignments.title": "Scope Assignments ({totalPermissions})", + "Role.permissions.Role.Permissions.Admin.Table.displayed.rows.more.than.label": "more than {to}", + "Role.permissions.Role.Permissions.Admin.Table.displayed.rows.range.label": "{from}-{to} of {count}", + "Role.permissions.Role.Permissions.Admin.Table.row.per.page.label": "Rows per page:", + "RolePermissions.Common.AddRoleWizard.add.dialog.back": "Back", + "RolePermissions.Common.AddRoleWizard.add.dialog.cancel": "Cancel", "RolePermissions.Common.AddRoleWizard.add.mapping.button": "Add scope mapping", "RolePermissions.Common.AddRoleWizard.add.mapping.title": "Add new scope mapping", + "RolePermissions.Common.AddRoleWizard.add.provide.role.next.btn": "Next", + "RolePermissions.Common.AddRoleWizard.add.provide.role.save.btn": "Save", + "RolePermissions.Common.AddRoleWizard.add.provide.role.text": "Provide role name", + "RolePermissions.Common.AddRoleWizard.add.provide.select.permissions": "Select permissions", + "RolePermissions.Common.AddRoleWizard.add.role.alias.label": "Role alias", + "RolePermissions.Common.AddRoleWizard.add.role.custom.scope.assignments": "Custom scope assignments", + "RolePermissions.Common.AddRoleWizard.add.role.mapping.label": "Mapping role", "RolePermissions.Common.AddRoleWizard.add.role.warn.empty": "Role name can not be empty!", "RolePermissions.Common.AddRoleWizard.add.scope.error": "Something went wrong while adding new scope mapping", + "RolePermissions.Common.AddRoleWizard.add.scope.error.add.role.alias": "Something went wrong while adding new role alias", + "RolePermissions.Common.AddRoleWizard.add.scope.error.add.role.alias.success": "Add new alias for {newRole} successfully", + "RolePermissions.Common.AddRoleWizard.add.scope.error.empty.permission": "You need to select at least one permission!", + "RolePermissions.Common.AddRoleWizard.add.scope.error.role.empty": "Mapped role selection can't be empty!", + "RolePermissions.Common.AddRoleWizard.add.scope.success": "Added scope mapping for {newRole} successfully", + "RolePermissions.Common.AddRoleWizard.add.type.role": "Type existing user role, If not create a new role from carbon console first", + "RolePermissions.Common.AddRoleWizard.add.type.role.label": "Role Name", + "RolePermissions.Common.AddRoleWizard.selected.role": "Role {role_value} will be mapped to the selected role", "RolePermissions.Common.DeletePermission.delete.scope.error": "Something went wrong while deleting the scope assignments", "RolePermissions.ListRoles.error.retrieving.perm": "Error while retrieving permission info", "RolePermissions.ListRoles.page.description": "Scope assignments are only related to internal, APIM-specific scope assignments. They are not related to role permission assignments in the Management Console.", + "RolePermissions.ListRoles.permission.delete.button": "Delete", "RolePermissions.ListRoles.permission.denied.content": "You do not have enough permission to view Scope Assignments. Please contact the site administrator.", "RolePermissions.ListRoles.permission.denied.title": "Permission Denied", "RolePermissions.ListRoles.scope.assignment.button": "Add scope mappings", + "RolePermissions.ListRoles.scope.assignment.cancel.button": "Cancel", + "RolePermissions.ListRoles.scope.assignment.delete.button": "Delete", + "RolePermissions.ListRoles.scope.assignment.delete.dialog.content": "Are you sure you want to delete scope assignments for {role} ?", + "RolePermissions.ListRoles.scope.assignment.delete.dialog.title": "Delete scope assignments of {role} ?", + "RolePermissions.ListRoles.scope.assignment.delete.scope.success": "Scope Assignments {role} deleted successfully", + "RolePermissions.ListRoles.table.column.role": "Roles", + "RolePermissions.ListRoles.table.column.scope.assignments": "Scope Assignments", "RolePermissions.ListRoles.title.role.permissions": "Scope Assignments", "RolePermissions.TreeView.PermissionsSelector.scope.assignment.button": "Scope Assignments", + "RolePermissions.TreeView.PermissionsSelector.scope.assignment.cancel.btn": "Cancel", + "RolePermissions.TreeView.PermissionsSelector.scope.assignment.save.btn": "Save", "RolePermissions.TreeView.PermissionsSelector.scope.assignment.title": "Select Scope Assignments", "RolePermissions.TreeView.PermissionsSelector.update.scope.error": "Something went wrong while updating the permission", + "RolePermissions.TreeView.PermissionsSelector.update.scope.success": "Update permissions for {role} successfully", "ScopeAssignments.List.search.default": "Search by Role Name", "Settings.Advanced.TenantConf.edit.success": "Advanced Configuration saved successfully", "Settings.Advanced.TenantConfSave.form.cancel": "Cancel", @@ -363,6 +594,7 @@ "TenantTheme.Upload.Theme.drag.and.drop.message": "Drag & Drop files here {break} or {break}", "TenantTheme.Upload.Theme.help.link.one": "Tenant theming", "TenantTheme.Upload.Theme.info.message": "The theme should be a zip file containing CSS and images compliant with the", + "TenantTheme.Upload.Theme.info.message.link": "API Manager theme format", "TenantTheme.Upload.Theme.page.heading": "Manage Tenant Theme", "TenantTheme.Upload.Theme.upload.files": "Upload/Download Theme", "TenantTheme.Upload.Theme.upload.successful": "Theme uploaded successfully", @@ -376,6 +608,7 @@ "Throttling.Advanced.AddEdit.default.limits.description": "Request Count and Request Bandwidth are the two options for default limit. You can use the option according to your requirement.", "Throttling.Advanced.AddEdit.edit.success": "Policy Updated Successfully", "Throttling.Advanced.AddEdit.empty.error": "contains white spaces.", + "Throttling.Advanced.AddEdit.form.actions.label": "Actions", "Throttling.Advanced.AddEdit.form.add.btn": "Add", "Throttling.Advanced.AddEdit.form.bandwidth.allowed.help": "Bandwidth allowed", "Throttling.Advanced.AddEdit.form.cancel": "Cancel", @@ -385,6 +618,7 @@ "Throttling.Advanced.AddEdit.form.has.errors": "One or more fields contain errors.", "Throttling.Advanced.AddEdit.form.name.help": "Name of the throttle policy.", "Throttling.Advanced.AddEdit.form.policyName": "Name", + "Throttling.Advanced.AddEdit.form.request.count.allowed.help": "Number of requests allowed", "Throttling.Advanced.AddEdit.form.requestCount.label": "Request Count", "Throttling.Advanced.AddEdit.form.timeUnit.day": "Day(s)", "Throttling.Advanced.AddEdit.form.timeUnit.hour": "Hour(s)", @@ -425,14 +659,19 @@ "Throttling.Advanced.AddEditConditionPolicyIP.valid.ip.address.error": "Invalid IP Addresss", "Throttling.Advanced.AddEditConditionPolicyIP.valid.ip.range.error": "Invalid IP Range", "Throttling.Advanced.AddEditExecution.default.limit.option": "Default Limit Option", + "Throttling.Advanced.AddEditExecution.default.limit.option.request.bandwith.label": "Request Bandwidth", + "Throttling.Advanced.AddEditExecution.default.limit.option.request.count.label": "Request Count", "Throttling.Advanced.ConditionalGroup.alert": "To add rate limiting with different parameters for Query Params, Header Data and JWT token claim, you must enable them in the deployment.toml file.", + "Throttling.Advanced.ConditionalGroup.alert.title": "Warning", "Throttling.Advanced.ConditionalGroup.condition.policies": "Condition Policies", "Throttling.Advanced.ConditionalGroup.execution.policy": "Execution Policy", + "Throttling.Advanced.ConditionalGroup.expand.label": "Expand to edit", "Throttling.Advanced.ConditionalGroup.from": "From:", "Throttling.Advanced.ConditionalGroup.header": "Header Condition Policy", "Throttling.Advanced.ConditionalGroup.header.help": "This configuration is used to throttle based on Headers.", "Throttling.Advanced.ConditionalGroup.header.name": "Name", "Throttling.Advanced.ConditionalGroup.header.value": "Value", + "Throttling.Advanced.ConditionalGroup.hide.label": "Hide group", "Throttling.Advanced.ConditionalGroup.invert.condition": "Invert Condition", "Throttling.Advanced.ConditionalGroup.ip": "IP Condition Policy", "Throttling.Advanced.ConditionalGroup.ip.header.name": "IP Condition Type", @@ -465,6 +704,8 @@ "Throttling.Advanced.List.search.default": "Search by Advanced Policy name", "Throttling.Advanced.List.title.main": "Advanced Rate Limiting Policies", "Throttling.Application.AddEdit.burst.control.limit": "Number of requests for burst control", + "Throttling.Application.AddEdit.burst.rate.limit.min": "Requests/min", + "Throttling.Application.AddEdit.burst.rate.limit.seconds": "Requests/sec", "Throttling.Application.AddEdit.form.request.rate": "Request Rate", "Throttling.Application.Policy..List.search.default": "Search by Application Policy name", "Throttling.Application.Policy.List.addButtonProps.title": "Add Policy", @@ -477,7 +718,9 @@ "Throttling.Application.Policy.policy.data.amount.empty": "Data Amount is Empty", "Throttling.Application.Policy.policy.delete.error": "Application Rate Limiting Policy could not be deleted.", "Throttling.Application.Policy.policy.delete.success": "Application Rate Limiting Policy successfully deleted.", + "Throttling.Application.Policy.policy.dialog.delete.btn": "Delete", "Throttling.Application.Policy.policy.dialog.delete.error": "Application Rate Limiting Policy will be deleted.", + "Throttling.Application.Policy.policy.dialog.delete.title": "Delete Application Policy?", "Throttling.Application.Policy.policy.edit.success": "Application Rate Limiting Policy edited successfully.", "Throttling.Application.Policy.policy.name.empty": "Name is Empty", "Throttling.Application.Policy.policy.name.invalid.character": "Name contains one or more illegal characters", @@ -494,6 +737,7 @@ "Throttling.Blacklist.Policy.List.help.link.one": "Denying requests", "Throttling.Blacklist.Policy.List.search.default": "Search by Deny Policy name", "Throttling.Blacklist.Policy.policy.add.success": "Deny Policy added successfully.", + "Throttling.Blacklist.Policy.policy.delete.dialog.title": "Delete Deny Policy?", "Throttling.Blacklist.Policy.policy.delete.error": "Deny Policy could not be deleted.", "Throttling.Blacklist.Policy.policy.delete.success": "Deny Policy successfully deleted.", "Throttling.Blacklist.Policy.policy.dialog.delete.error": "Deny Policy will be deleted.", @@ -521,8 +765,10 @@ "Throttling.Custom.Policy.List.help.link.one": "Custom Throttling Policy", "Throttling.Custom.Policy.List.search.default": "Search by Custom Policy name", "Throttling.Custom.Policy.policy.add.success": "Custom Policy added successfully.", + "Throttling.Custom.Policy.policy.delete.btn": "Delete", "Throttling.Custom.Policy.policy.delete.error": "Custom Policy could not be deleted.", "Throttling.Custom.Policy.policy.delete.success": "Custom Policy successfully deleted.", + "Throttling.Custom.Policy.policy.delete.title": "Delete Custom Policy?", "Throttling.Custom.Policy.policy.dialog.delete.error": "Custom Policy will be deleted.", "Throttling.Custom.Policy.policy.edit.success": "Custom Policy edited successfully", "Throttling.Custom.Policy.policy.invalid.key.template": "Invalid Key Template", @@ -533,33 +779,51 @@ "Throttling.Custom.Policy.search.default": "Custom Rate Limiting Policies", "Throttling.Subscription.AddEdit.burst.control.add.description": "Define Burst Control Limits for the subscription policy. This is optional.", "Throttling.Subscription.AddEdit.burst.control.limit": "Number of requests for burst control", + "Throttling.Subscription.AddEdit.burst.control.limit.time.unit.minute": "Requests/min", + "Throttling.Subscription.AddEdit.burst.control.limit.time.unit.second": "Requests/s", "Throttling.Subscription.AddEdit.burst.control.limits": "Burst Control (Rate Limiting)", "Throttling.Subscription.AddEdit.custom.attributes.add.description": "Define custom attributes for the subscription policy.", "Throttling.Subscription.AddEdit.form.add": "Save", + "Throttling.Subscription.AddEdit.form.add.data.amount.helper.text": "Bandwidth allowed", "Throttling.Subscription.AddEdit.form.cancel": "Cancel", + "Throttling.Subscription.AddEdit.form.completionTokenCount.count": "Completion Token Count", "Throttling.Subscription.AddEdit.form.dataAmount.name": "Data Bandwidth", "Throttling.Subscription.AddEdit.form.description": "Description", "Throttling.Subscription.AddEdit.form.description.help": "Description of the rate limiting policy", "Throttling.Subscription.AddEdit.form.eventCount.count": "Event Count", + "Throttling.Subscription.AddEdit.form.eventCount.count.helper.text": "Number of events allowed", "Throttling.Subscription.AddEdit.form.max.complexity": "Max Complexity", "Throttling.Subscription.AddEdit.form.max.depth": "Max Depth", "Throttling.Subscription.AddEdit.form.max.webhooks.connections": "Max Subscriptions", "Throttling.Subscription.AddEdit.form.name.help": "Name of the rate limiting policy", "Throttling.Subscription.AddEdit.form.policyName": "Name", + "Throttling.Subscription.AddEdit.form.promptTokenCount.count": "Prompt Token Count", "Throttling.Subscription.AddEdit.form.request.rate": "Request Rate", "Throttling.Subscription.AddEdit.form.requestCount.count": "Request Count", + "Throttling.Subscription.AddEdit.form.totalTokenCount.count": "Total Token Count", + "Throttling.Subscription.AddEdit.form.unit.time.label": "Unit Time", "Throttling.Subscription.AddEdit.general.details": "General Details", "Throttling.Subscription.AddEdit.general.details.description": "Provide the name and description of the subscription policy.", "Throttling.Subscription.AddEdit.graphql.add.description": "Provide the Maximum Complexity and Maximum depth values for GraphQL APIs using this policy.", "Throttling.Subscription.AddEdit.permissions.add.description": "Define the permissions for the subscription policy.", + "Throttling.Subscription.AddEdit.permissions.add.role.label": "Roles", + "Throttling.Subscription.AddEdit.permissions.add.role.placeholder": "Type roles and press Enter", "Throttling.Subscription.AddEdit.policy.flags.add.description": "Define the billing plan for the subscription policy. Enable stop on quota reach to block invoking an API when the defined quota is reached.", "Throttling.Subscription.AddEdit.quota.limits": "Quota Limits", + "Throttling.Subscription.AddEdit.quota.limits.ai.description": "Specify the quota limits for AI API Subscription policy.", "Throttling.Subscription.AddEdit.quota.policies.add.description": "Request Count and Request Bandwidth are the two options for Quota Limit. You can use the option according to your requirement.", + "Throttling.Subscription.AddEdit.quota.policies.add.limits.event.count": "Event Based (Async API)", + "Throttling.Subscription.AddEdit.quota.policies.add.limits.request.bandwidth": "Request Bandwidth", + "Throttling.Subscription.AddEdit.quota.policies.add.limits.request.count": "Request Count", "Throttling.Subscription.AddEdit.subscription.count.add.description": "Maximum number of webhooks allowed for a Webhooks API using this policy.", + "Throttling.Subscription.AddEdit.title.AIPolicy.add": "AI API Subscription Rate Limiting Policy - Create new", + "Throttling.Subscription.AddEdit.title.AIPolicy.edit": "AI API Subscription Rate Limiting Policy - Edit", "Throttling.Subscription.AddEdit.title.add": "Subscription Rate Limiting Policy - Create new", "Throttling.Subscription.AddEdit.title.edit": "Subscription Rate Limiting Policy - Edit", "Throttling.Subscription.AddEdit.unitTime": "Unit Time", "Throttling.Subscription.Billing.Plan": "Billing Plan", + "Throttling.Subscription.Billing.Plan.type.commercial": "Commercial", + "Throttling.Subscription.Billing.Plan.type.free": "Free", "Throttling.Subscription.Fixed.Rate": "Fixed Rate", "Throttling.Subscription.GraphQL": "GraphQL", "Throttling.Subscription.Policy..List.search.default": "Search by Subscription Policy name", @@ -571,8 +835,10 @@ "Throttling.Subscription.Policy.List.help.link.two": "Setting a Subscription Rate Limiting Policy as an API Publisher", "Throttling.Subscription.Policy.policy.add.success": "Subscription Rate Limiting Policy added successfully.", "Throttling.Subscription.Policy.policy.data.amount.empty.error.msg": "Data Bandwidth amount is Empty", + "Throttling.Subscription.Policy.policy.delete.btn": "Delete", "Throttling.Subscription.Policy.policy.delete.error": "Subscription Rate Limiting Policy could not be deleted.", "Throttling.Subscription.Policy.policy.delete.success": "Subscription Rate Limiting Policy successfully deleted.", + "Throttling.Subscription.Policy.policy.delete.title": "Delete Subscription Policy?", "Throttling.Subscription.Policy.policy.dialog.delete.error": "Subscription Rate Limiting Policy will be deleted.", "Throttling.Subscription.Policy.policy.edit.success": "Subscription Rate Limiting Policy updated successfully.", "Throttling.Subscription.Policy.policy.event.count.empty.error.msg": "Event Count is Empty", @@ -590,6 +856,9 @@ "Throttling.Subscription.Subscriber.Count": "Webhooks", "Throttling.Subscription.attribute.delete.tooltip": "Delete", "Throttling.Subscription.billing.cycle": "Billing Cycle", + "Throttling.Subscription.billing.cycle.menu.month": "Month", + "Throttling.Subscription.billing.cycle.menu.week": "Week", + "Throttling.Subscription.billing.cycle.menu.year": "Year", "Throttling.Subscription.currency": "Currency", "Throttling.Subscription.custom.attributes": "Custom Attributes", "Throttling.Subscription.custom.attributes.add": "Add Custom Attribute", @@ -599,8 +868,11 @@ "Throttling.Subscription.enter.permission.denied": "This policy is \"Denied\" for above roles.", "Throttling.Subscription.fixed.rate.tooltip": "Fixed rate for the given billing cycle", "Throttling.Subscription.monetization.plan": "Monetization Plan", + "Throttling.Subscription.monetization.plan.dynamic.usage": "Dynamic Usage", + "Throttling.Subscription.monetization.plan.fixed.rate": "Fixed Rate", "Throttling.Subscription.monetization.plan.tooltip": "Monetization category type", "Throttling.Subscription.permissions": "Permissions", + "Throttling.Subscription.price.per.request": "Price Per Request", "Throttling.Subscription.stop.quota.reach": "Stop On Quota Reach", "Throttling.Subsription.Policy.List.empty.content.subscription.policies": "Subscription-level throttling policies are applicable per access token generated for an application.", "UnexpectedError.logout": "Logout", @@ -609,6 +881,7 @@ "Workflow.APIProductStateChange.List.empty.content.apiProduct.statechange": "There are no pending workflow requests for API Product state change", "Workflow.APIProductStateChange.List.empty.title.apistatechange": "API Product State Change", "Workflow.APIProductStateChange.apicall.has.errors": "Unable to get workflow pending requests for API Product State Change", + "Workflow.APIProductStateChange.title.apistatechange": "API Product State Change - Approval Tasks", "Workflow.APIProductStateChange.updateStatus.has.errors": "Unable to complete API Product state change approve/reject process.", "Workflow.APIRevisionDeployment.List.empty.content.revisiondeployments": "There are no pending workflow requests for revision deployment.", "Workflow.APIRevisionDeployment.List.empty.title.revisiondeployments": "Revision Deployment", @@ -639,6 +912,7 @@ "Workflow.APIStateChange.table.header.CurrentState": "Current State", "Workflow.APIStateChange.table.header.Description": "Description", "Workflow.APIStateChange.table.header.RequestState": "Request State", + "Workflow.APIStateChange.title.apistatechange": "API State Change - Approval Tasks", "Workflow.APIStateChange.update.success": "Workflow status is updated successfully.", "Workflow.APIStateChange.updateStatus.has.errors": "Unable to complete API state change approve/reject process.", "Workflow.APIStatechange.help.link.one": "Create a API State change approval workflow request", diff --git a/portals/admin/src/main/webapp/source/src/app/components/AdminPages/Addons/ListBase.jsx b/portals/admin/src/main/webapp/source/src/app/components/AdminPages/Addons/ListBase.jsx index fc4369b8e27..a0ae50933b9 100644 --- a/portals/admin/src/main/webapp/source/src/app/components/AdminPages/Addons/ListBase.jsx +++ b/portals/admin/src/main/webapp/source/src/app/components/AdminPages/Addons/ListBase.jsx @@ -38,6 +38,9 @@ import InlineProgress from 'AppComponents/AdminPages/Addons/InlineProgress'; import { Link as RouterLink } from 'react-router-dom'; import EditIcon from '@mui/icons-material/Edit'; import Alert from '@mui/material/Alert'; +import { + Table, TableHead, TableBody, TableRow, TableCell, +} from '@mui/material'; /** * Render a list @@ -54,6 +57,7 @@ function ListBase(props) { }, noDataMessage, addedActions, + enableCollapsable, } = props; const [searchText, setSearchText] = useState(''); @@ -150,9 +154,15 @@ function ListBase(props) { if (editComponentProps && editComponentProps.routeTo) { if (typeof tableMeta.rowData === 'object') { const artifactId = tableMeta.rowData[tableMeta.rowData.length - 2]; + const isAI = tableMeta.rowData[1] === 'AI API Quota'; return (
- + @@ -234,6 +244,79 @@ function ListBase(props) { }), }, }, + expandableRows: enableCollapsable, + renderExpandableRow: (rowData) => { + if (!enableCollapsable) return null; + + const isAIQuota = rowData[1] === 'AI API Quota'; + return ( + + + + + + + {isAIQuota ? ( + <> + + Request Count + + + Total Token Count + + + Prompt Token Count + + + Completion Token Count + + + Unit Time + + + ) : ( + <> + + Quota + + + Unit Time + + + Rate Limit + + + Time Unit + + + )} + + + + + {isAIQuota ? ( + <> + {rowData[2]} + {rowData[6]} + {rowData[7]} + {rowData[8]} + {rowData[3]} + + ) : ( + <> + {rowData[2]} + {rowData[3]} + {rowData[4]} + {rowData[5]} + + )} + + +
+
+
+ ); + }, }; // If no apiCall is provided OR, @@ -392,6 +475,7 @@ ListBase.defaultProps = { DeleteComponent: null, editComponentProps: {}, columProps: null, + enableCollapsable: false, }; ListBase.propTypes = { EditComponent: PropTypes.element, @@ -418,5 +502,6 @@ ListBase.propTypes = { noDataMessage: PropTypes.element, addButtonOverride: PropTypes.element, addedActions: PropTypes.shape([]), + enableCollapsable: PropTypes.bool, }; export default ListBase; diff --git a/portals/admin/src/main/webapp/source/src/app/components/Throttling/Subscription/AddEdit.jsx b/portals/admin/src/main/webapp/source/src/app/components/Throttling/Subscription/AddEdit.jsx index b956c5f1343..971d4e4406d 100644 --- a/portals/admin/src/main/webapp/source/src/app/components/Throttling/Subscription/AddEdit.jsx +++ b/portals/admin/src/main/webapp/source/src/app/components/Throttling/Subscription/AddEdit.jsx @@ -26,7 +26,7 @@ import Alert from 'AppComponents/Shared/Alert'; import ContentBase from 'AppComponents/AdminPages/Addons/ContentBase'; import Box from '@mui/material/Box'; import Typography from '@mui/material/Typography'; -import { Link as RouterLink } from 'react-router-dom'; +import { Link as RouterLink, useLocation } from 'react-router-dom'; import Grid from '@mui/material/Grid'; import Radio from '@mui/material/Radio'; import RadioGroup from '@mui/material/RadioGroup'; @@ -80,6 +80,9 @@ function reducer(state, newValue) { case 'dataAmount': case 'unitTime': case 'eventCount': + case 'totalTokenCount': + case 'promptTokenCount': + case 'completionTokenCount': return { ...state, defaultLimit: { ...state.defaultLimit, [field]: value }, @@ -125,11 +128,20 @@ function AddEdit(props) { const [validRoles, setValidRoles] = useState([]); const [invalidRoles, setInvalidRoles] = useState([]); const [roleValidity, setRoleValidity] = useState(true); - + const location = useLocation(); + const isAI = location.state?.isAI || false; const [initialState, setInitialState] = useState({ policyName: '', description: '', - defaultLimit: { + defaultLimit: isAI ? { + requestCount: '', + timeUnit: 'min', + unitTime: '', + type: 'AIAPIQUOTALIMIT', + totalTokenCount: '', + promptTokenCount: '', + completionTokenCount: '', + } : { requestCount: '', timeUnit: 'min', unitTime: '', @@ -168,6 +180,9 @@ function AddEdit(props) { if (isEdit) { restApi.subscriptionThrottlingPolicyGet(params.id).then((result) => { let requestCountEdit = ''; + let totalTokenCountEdit = ''; + let promptTokenCountEdit = ''; + let completionTokenCountEdit = ''; let dataAmountEdit = ''; let timeUnitEdit = 'min'; let unitTimeEdit = ''; @@ -179,6 +194,14 @@ function AddEdit(props) { timeUnitEdit = result.body.defaultLimit.requestCount.timeUnit; unitTimeEdit = result.body.defaultLimit.requestCount.unitTime; typeEdit = result.body.defaultLimit.type; + } else if (result.body.defaultLimit.aiApiQuota !== null) { + requestCountEdit = result.body.defaultLimit.aiApiQuota.requestCount; + totalTokenCountEdit = result.body.defaultLimit.aiApiQuota.totalTokenCount; + promptTokenCountEdit = result.body.defaultLimit.aiApiQuota.promptTokenCount; + completionTokenCountEdit = result.body.defaultLimit.aiApiQuota.completionTokenCount; + timeUnitEdit = result.body.defaultLimit.aiApiQuota.timeUnit; + unitTimeEdit = result.body.defaultLimit.aiApiQuota.unitTime; + typeEdit = result.body.defaultLimit.type; } else if (result.body.defaultLimit.bandwidth != null) { dataAmountEdit = result.body.defaultLimit.bandwidth.dataAmount; dataUnitEdit = result.body.defaultLimit.bandwidth.dataUnit; @@ -198,7 +221,15 @@ function AddEdit(props) { const editState = { policyName: result.body.policyName, description: result.body.description, - defaultLimit: { + defaultLimit: isAI ? { + requestCount: requestCountEdit, + timeUnit: timeUnitEdit, + unitTime: unitTimeEdit, + type: typeEdit, + totalTokenCount: totalTokenCountEdit, + promptTokenCount: promptTokenCountEdit, + completionTokenCount: completionTokenCountEdit, + } : { requestCount: requestCountEdit, timeUnit: timeUnitEdit, unitTime: unitTimeEdit, @@ -243,7 +274,15 @@ function AddEdit(props) { setInitialState({ policyName: '', description: '', - defaultLimit: { + defaultLimit: isAI ? { + requestCount: '', + timeUnit: 'min', + unitTime: '', + type: 'AIAPIQUOTALIMIT', + totalTokenCount: '', + promptTokenCount: '', + completionTokenCount: '', + } : { requestCount: '', timeUnit: 'min', unitTime: '', @@ -312,6 +351,27 @@ function AddEdit(props) { }) : ''; setValidationError({ requestCount: error }); break; + // case 'totalTokenCount': + // error = value === '' ? intl.formatMessage({ + // id: 'Throttling.Subscription.Policy.policy.total.token.count.empty.error.msg', + // defaultMessage: 'Total Token Count is Empty', + // }) : ''; + // setValidationError({ totalTokenCount: error }); + // break; + // case 'promoptTokenCount': + // error = value === '' ? intl.formatMessage({ + // id: 'Throttling.Subscription.Policy.policy.prompt.token.count.empty.error.msg', + // defaultMessage: 'Prompt Token Count is Empty', + // }) : ''; + // setValidationError({ promptTokenCount: error }); + // break; + // case 'completionTokenCount': + // error = value === '' ? intl.formatMessage({ + // id: 'Throttling.Subscription.Policy.policy.completion.token.count.empty.error.msg', + // defaultMessage: 'Completion Token Count is Empty', + // }) : ''; + // setValidationError({ completionTokenCount: error }); + // break; case 'eventCount': error = value === '' ? intl.formatMessage({ id: 'Throttling.Subscription.Policy.policy.event.count.empty.error.msg', @@ -359,6 +419,9 @@ function AddEdit(props) { dataAmount, dataUnit, eventCount, + totalTokenCount, + promptTokenCount, + completionTokenCount, }, rateLimitCount, rateLimitTimeUnit, @@ -486,6 +549,44 @@ function AddEdit(props) { roles: validRoles, }, }; + } else if (type === 'AIAPIQUOTALIMIT') { + subscriptionThrottlingPolicy = { + policyName: state.policyName, + description: state.description, + defaultLimit: { + type: state.defaultLimit.type, + aiApiQuota: { + requestCount: state.defaultLimit.requestCount, + totalTokenCount: state.defaultLimit.totalTokenCount, + promptTokenCount: state.defaultLimit.promptTokenCount, + completionTokenCount: state.defaultLimit.completionTokenCount, + timeUnit: state.defaultLimit.timeUnit, + unitTime: state.defaultLimit.unitTime, + }, + }, + subscriberCount: 0, + rateLimitCount: 0, + rateLimitTimeUnit: state.rateLimitTimeUnit, + billingPlan: state.billingPlan, + stopOnQuotaReach: state.stopOnQuotaReach, + customAttributes, + graphQLMaxComplexity: 0, + graphQLMaxDepth: 0, + monetization: { + monetizationPlan: state.monetization.monetizationPlan, + properties: { + fixedPrice: state.monetization.fixedPrice, + pricePerRequest: state.monetization.pricePerRequest, + currencyType: state.monetization.currencyType, + billingCycle: state.monetization.billingCycle, + }, + }, + permissions: (state.permissions === null || state.permissions.permissionStatus === null + || state.permissions.permissionStatus === 'NONE') ? null : { + permissionType: state.permissions.permissionStatus, + roles: validRoles, + }, + }; } else if (type === 'BANDWIDTHLIMIT') { subscriptionThrottlingPolicy = { policyName: state.policyName, @@ -630,18 +731,33 @@ function AddEdit(props) { setCustomAttributes(tmpCustomAttributes); }; + let pageTitle; + if (isAI) { + pageTitle = isEdit + ? intl.formatMessage({ + id: 'Throttling.Subscription.AddEdit.title.AIPolicy.edit', + defaultMessage: 'AI API Subscription Rate Limiting Policy - Edit', + }) + : intl.formatMessage({ + id: 'Throttling.Subscription.AddEdit.title.AIPolicy.add', + defaultMessage: 'AI API Subscription Rate Limiting Policy - Create new', + }); + } else { + pageTitle = isEdit + ? intl.formatMessage({ + id: 'Throttling.Subscription.AddEdit.title.edit', + defaultMessage: 'Subscription Rate Limiting Policy - Edit', + }) + : intl.formatMessage({ + id: 'Throttling.Subscription.AddEdit.title.add', + defaultMessage: 'Subscription Rate Limiting Policy - Create new', + }); + } + return ( @@ -731,57 +847,68 @@ function AddEdit(props) { /> - + {isAI ? ( + + ) : ( + + )} - - } - label={( - - )} - /> - } - label={( - - )} - /> - } - label={( - - )} - /> - + {isAI ? null : ( + + } + label={( + + )} + /> + } + label={( + + )} + /> + } + label={( + + )} + /> + + )} {type === 'REQUESTCOUNTLIMIT' && ( @@ -819,6 +946,142 @@ function AddEdit(props) { /> )} + {type === 'AIAPIQUOTALIMIT' && ( + <> + + { + validate('requestCount', value); + }, + }} + label={( + + )} + fullWidth + error={validationError.requestCount} + helperText={validationError.requestCount + || ( + + )} + variant='outlined' + /> + + + { + validate('totalTokenCount', value); + }, + }} + label={( + + )} + fullWidth + error={validationError.totalTokenCount} + helperText={validationError.totalTokenCount + || ( + + )} + variant='outlined' + /> + + + { + validate('promptTokenCount', value); + }, + }} + label={( + + )} + fullWidth + error={validationError.promptTokenCount} + helperText={validationError.promptTokenCount + || ( + + )} + variant='outlined' + /> + + + { + validate('completionTokenCount', value); + }, + }} + label={( + + )} + fullWidth + error={validationError.completionTokenCount} + helperText={validationError.completionTokenCount + || ( + + )} + variant='outlined' + /> + + + )} {type === 'BANDWIDTHLIMIT' && ( - {/* Burst Control (Rate Limiting) */} - - - - - - - - - - - - - - - - - + {/* Burst Control (Rate Limiting) */} + + + + - )} - sx={{ width: 380 }} - helperText={intl.formatMessage({ - id: 'Throttling.Subscription.AddEdit.burst.control.limit', - defaultMessage: 'Number of requests for burst control', - })} - variant='outlined' - /> - - - - - - - - - - - - + + + + + + + + + + + + - {/* GraphQL */} - - - - - - - - - - - - - - - - - - - - )} - fullWidth - variant='outlined' - /> + {/* GraphQL */} + + + + + + + + + + - - - - - - - )} - fullWidth - variant='outlined' - /> + + + + + + + + + )} + fullWidth + variant='outlined' + /> + + + + + + + + )} + fullWidth + variant='outlined' + /> + + - - - - - - - - - {/* Web Hooks */} - - - - - - - - - - - - - - - - - - - - )} - fullWidth - variant='outlined' - /> + + + + - - - - - - - - + + {/* Web Hooks */} + + + + + + + + + + + + + + + + + + + + )} + fullWidth + variant='outlined' + /> + + + + + + + + + + + )} {/* Policy flags */} diff --git a/portals/admin/src/main/webapp/source/src/app/components/Throttling/Subscription/List.jsx b/portals/admin/src/main/webapp/source/src/app/components/Throttling/Subscription/List.jsx index a73fab70789..dda667d5823 100644 --- a/portals/admin/src/main/webapp/source/src/app/components/Throttling/Subscription/List.jsx +++ b/portals/admin/src/main/webapp/source/src/app/components/Throttling/Subscription/List.jsx @@ -16,7 +16,7 @@ * under the License. */ -import React from 'react'; +import React, { useState } from 'react'; import { useIntl, FormattedMessage } from 'react-intl'; import List from '@mui/material/List'; import ListItem from '@mui/material/ListItem'; @@ -32,7 +32,10 @@ import Delete from 'AppComponents/Throttling/Subscription/Delete'; import API from 'AppData/api'; import EditIcon from '@mui/icons-material/Edit'; import { Link as RouterLink } from 'react-router-dom'; -import Button from '@mui/material/Button'; +import { + Button, Menu, MenuItem, +} from '@mui/material'; +import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown'; /** * Render a list @@ -41,6 +44,20 @@ import Button from '@mui/material/Button'; export default function ListSubscriptionThrottlingPolicies() { const intl = useIntl(); const restApi = new API(); + const enableCollapsable = true; + const [anchorEl, setAnchorEl] = useState(null); + + const handleClick = (event) => { + setAnchorEl(event.currentTarget); + }; + + const handleClose = () => { + setAnchorEl(null); + }; + + const handleMenuItemClick = () => { + setAnchorEl(null); + }; const searchProps = { searchPlaceholder: intl.formatMessage({ @@ -137,7 +154,17 @@ export default function ListSubscriptionThrottlingPolicies() { customBodyRender: (value, tableMeta) => { if (typeof tableMeta.rowData === 'object') { const artifactId = tableMeta.rowData[tableMeta.rowData.length - 2]; - return {value}; + const isAI = tableMeta.rowData[1] === 'AI API Quota'; + return ( + + {value} + + ); } else { return
; } @@ -154,7 +181,7 @@ export default function ListSubscriptionThrottlingPolicies() { }), options: { filter: true, - sort: false, + sort: true, }, }, { @@ -166,6 +193,7 @@ export default function ListSubscriptionThrottlingPolicies() { options: { filter: true, sort: false, + display: false, }, }, { @@ -177,6 +205,7 @@ export default function ListSubscriptionThrottlingPolicies() { options: { filter: true, sort: false, + display: false, }, }, { @@ -188,6 +217,7 @@ export default function ListSubscriptionThrottlingPolicies() { options: { filter: true, sort: false, + display: false, }, }, { @@ -199,6 +229,37 @@ export default function ListSubscriptionThrottlingPolicies() { options: { filter: true, sort: false, + display: false, + }, + }, + { + name: 'totalTokenCount', + label: intl.formatMessage({ + id: 'Admin.Throttling.Subscription.Throttling.policy.table.header.total.token.count', + defaultMessage: 'Total Token Count', + }), + options: { + display: false, + }, + }, + { + name: 'promptTokenCount', + label: intl.formatMessage({ + id: 'Admin.Throttling.Subscription.Throttling.policy.table.header.prompt.token.count', + defaultMessage: 'Prompt Token Count', + }), + options: { + display: false, + }, + }, + { + name: 'completionTokenCount', + label: intl.formatMessage({ + id: 'Admin.Throttling.Subscription.Throttling.policy.table.header.completion.token.count', + defaultMessage: 'Completion Token Count', + }), + options: { + display: false, }, }, { // Id column has to be always the last. @@ -229,19 +290,40 @@ export default function ListSubscriptionThrottlingPolicies() { }; const addButtonOverride = ( - + <> - + + handleMenuItemClick(false)} + component={RouterLink} + to={{ pathname: '/throttling/subscription/add', state: { isAI: false } }} + > + Add Policy + + handleMenuItemClick(true)} + component={RouterLink} + to={{ pathname: '/throttling/subscription/add', state: { isAI: true } }} + > + Add AI Policy + + + ); /** @@ -261,6 +343,9 @@ export default function ListSubscriptionThrottlingPolicies() { + obj.defaultLimit.requestCount.timeUnit, rateLimit: (obj.rateLimitCount === 0) ? 'NA' : obj.rateLimitCount, timeUnit: (obj.rateLimitCount === 0) ? 'NA' : obj.rateLimitTimeUnit, + totalTokenCount: 'NA', + promptTokenCount: 'NA', + completionTokenCount: 'NA', policyId: obj.policyId, }; } else if (obj.defaultLimit.bandwidth !== null) { @@ -273,6 +358,26 @@ export default function ListSubscriptionThrottlingPolicies() { + obj.defaultLimit.bandwidth.timeUnit, rateLimit: (obj.rateLimitCount === 0) ? 'NA' : obj.rateLimitCount, timeUnit: (obj.rateLimitCount === 0) ? 'NA' : obj.rateLimitTimeUnit, + totalTokenCount: 'NA', + promptTokenCount: 'NA', + completionTokenCount: 'NA', + policyId: obj.policyId, + }; + } else if (obj.defaultLimit.aiApiQuota !== null) { + return { + policyName: obj.policyName, + quotaPolicy: 'AI API Quota', + quota: obj.defaultLimit.aiApiQuota.requestCount, + unitTime: obj.defaultLimit.aiApiQuota.unitTime + ' ' + + obj.defaultLimit.aiApiQuota.timeUnit, + rateLimit: (obj.rateLimitCount === 0) ? 'NA' : obj.rateLimitCount, + timeUnit: (obj.rateLimitCount === 0) ? 'NA' : obj.rateLimitTimeUnit, + totalTokenCount: (obj.defaultLimit.aiApiQuota.totalTokenCount === 0) ? 'NA' + : obj.defaultLimit.aiApiQuota.totalTokenCount, + promptTokenCount: (obj.defaultLimit.aiApiQuota.promptTokenCount === 0) ? 'NA' + : obj.defaultLimit.aiApiQuota.promptTokenCount, + completionTokenCount: (obj.defaultLimit.aiApiQuota.completionTokenCount === 0) ? 'NA' + : obj.defaultLimit.aiApiQuota.completionTokenCount, policyId: obj.policyId, }; } else { @@ -284,6 +389,9 @@ export default function ListSubscriptionThrottlingPolicies() { + obj.defaultLimit.eventCount.timeUnit, rateLimit: (obj.rateLimitCount === 0) ? 'NA' : obj.rateLimitCount, timeUnit: (obj.rateLimitCount === 0) ? 'NA' : obj.rateLimitTimeUnit, + totalTokenCount: 'NA', + promptTokenCount: 'NA', + completionTokenCount: 'NA', policyId: obj.policyId, }; } @@ -315,6 +423,7 @@ export default function ListSubscriptionThrottlingPolicies() { routeTo: '/throttling/subscription/', }} DeleteComponent={Delete} + enableCollapsable={enableCollapsable} /> ); } From f27676ec83def2939b1fe64f75aa185d5e2d7139 Mon Sep 17 00:00:00 2001 From: Savindu Dimal Date: Tue, 10 Sep 2024 23:06:13 +0530 Subject: [PATCH 2/2] Refactor code Add renderExpandableRow prop to ListBase component --- .../components/AdminPages/Addons/ListBase.jsx | 79 +------------------ .../Throttling/Subscription/AddEdit.jsx | 21 ----- .../Throttling/Subscription/List.jsx | 74 ++++++++++++++++- 3 files changed, 77 insertions(+), 97 deletions(-) diff --git a/portals/admin/src/main/webapp/source/src/app/components/AdminPages/Addons/ListBase.jsx b/portals/admin/src/main/webapp/source/src/app/components/AdminPages/Addons/ListBase.jsx index a0ae50933b9..38ce3db667b 100644 --- a/portals/admin/src/main/webapp/source/src/app/components/AdminPages/Addons/ListBase.jsx +++ b/portals/admin/src/main/webapp/source/src/app/components/AdminPages/Addons/ListBase.jsx @@ -38,9 +38,6 @@ import InlineProgress from 'AppComponents/AdminPages/Addons/InlineProgress'; import { Link as RouterLink } from 'react-router-dom'; import EditIcon from '@mui/icons-material/Edit'; import Alert from '@mui/material/Alert'; -import { - Table, TableHead, TableBody, TableRow, TableCell, -} from '@mui/material'; /** * Render a list @@ -58,6 +55,7 @@ function ListBase(props) { noDataMessage, addedActions, enableCollapsable, + renderExpandableRow, } = props; const [searchText, setSearchText] = useState(''); @@ -245,78 +243,7 @@ function ListBase(props) { }, }, expandableRows: enableCollapsable, - renderExpandableRow: (rowData) => { - if (!enableCollapsable) return null; - - const isAIQuota = rowData[1] === 'AI API Quota'; - return ( - - - - - - - {isAIQuota ? ( - <> - - Request Count - - - Total Token Count - - - Prompt Token Count - - - Completion Token Count - - - Unit Time - - - ) : ( - <> - - Quota - - - Unit Time - - - Rate Limit - - - Time Unit - - - )} - - - - - {isAIQuota ? ( - <> - {rowData[2]} - {rowData[6]} - {rowData[7]} - {rowData[8]} - {rowData[3]} - - ) : ( - <> - {rowData[2]} - {rowData[3]} - {rowData[4]} - {rowData[5]} - - )} - - -
-
-
- ); - }, + renderExpandableRow, }; // If no apiCall is provided OR, @@ -476,6 +403,7 @@ ListBase.defaultProps = { editComponentProps: {}, columProps: null, enableCollapsable: false, + renderExpandableRow: null, }; ListBase.propTypes = { EditComponent: PropTypes.element, @@ -503,5 +431,6 @@ ListBase.propTypes = { addButtonOverride: PropTypes.element, addedActions: PropTypes.shape([]), enableCollapsable: PropTypes.bool, + renderExpandableRow: PropTypes.func, }; export default ListBase; diff --git a/portals/admin/src/main/webapp/source/src/app/components/Throttling/Subscription/AddEdit.jsx b/portals/admin/src/main/webapp/source/src/app/components/Throttling/Subscription/AddEdit.jsx index 971d4e4406d..b79e3a153e4 100644 --- a/portals/admin/src/main/webapp/source/src/app/components/Throttling/Subscription/AddEdit.jsx +++ b/portals/admin/src/main/webapp/source/src/app/components/Throttling/Subscription/AddEdit.jsx @@ -351,27 +351,6 @@ function AddEdit(props) { }) : ''; setValidationError({ requestCount: error }); break; - // case 'totalTokenCount': - // error = value === '' ? intl.formatMessage({ - // id: 'Throttling.Subscription.Policy.policy.total.token.count.empty.error.msg', - // defaultMessage: 'Total Token Count is Empty', - // }) : ''; - // setValidationError({ totalTokenCount: error }); - // break; - // case 'promoptTokenCount': - // error = value === '' ? intl.formatMessage({ - // id: 'Throttling.Subscription.Policy.policy.prompt.token.count.empty.error.msg', - // defaultMessage: 'Prompt Token Count is Empty', - // }) : ''; - // setValidationError({ promptTokenCount: error }); - // break; - // case 'completionTokenCount': - // error = value === '' ? intl.formatMessage({ - // id: 'Throttling.Subscription.Policy.policy.completion.token.count.empty.error.msg', - // defaultMessage: 'Completion Token Count is Empty', - // }) : ''; - // setValidationError({ completionTokenCount: error }); - // break; case 'eventCount': error = value === '' ? intl.formatMessage({ id: 'Throttling.Subscription.Policy.policy.event.count.empty.error.msg', diff --git a/portals/admin/src/main/webapp/source/src/app/components/Throttling/Subscription/List.jsx b/portals/admin/src/main/webapp/source/src/app/components/Throttling/Subscription/List.jsx index dda667d5823..a6d7f979352 100644 --- a/portals/admin/src/main/webapp/source/src/app/components/Throttling/Subscription/List.jsx +++ b/portals/admin/src/main/webapp/source/src/app/components/Throttling/Subscription/List.jsx @@ -33,7 +33,7 @@ import API from 'AppData/api'; import EditIcon from '@mui/icons-material/Edit'; import { Link as RouterLink } from 'react-router-dom'; import { - Button, Menu, MenuItem, + Button, Menu, MenuItem, Table, TableHead, TableBody, TableRow, TableCell, } from '@mui/material'; import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown'; @@ -409,6 +409,77 @@ export default function ListSubscriptionThrottlingPolicies() { }); } + const renderExpandableRow = (rowData) => { + const isAIQuota = rowData[1] === 'AI API Quota'; + return ( + + + + + + + {isAIQuota ? ( + <> + + Request Count + + + Total Token Count + + + Prompt Token Count + + + Completion Token Count + + + Unit Time + + + ) : ( + <> + + Quota + + + Unit Time + + + Rate Limit + + + Time Unit + + + )} + + + + + {isAIQuota ? ( + <> + {rowData[2]} + {rowData[6]} + {rowData[7]} + {rowData[8]} + {rowData[3]} + + ) : ( + <> + {rowData[2]} + {rowData[3]} + {rowData[4]} + {rowData[5]} + + )} + + +
+
+
+ ); + }; + return ( ); }