diff --git a/apps/web/app/(webapp)/(components)/CodeEditor.tsx b/apps/web/app/(webapp)/(components)/CodeEditor.tsx
new file mode 100644
index 00000000..f6837247
--- /dev/null
+++ b/apps/web/app/(webapp)/(components)/CodeEditor.tsx
@@ -0,0 +1,56 @@
+'use client'
+
+import React from 'react';
+// import dynamic from 'next/dynamic';
+import MonacoEditor from 'react-monaco-editor';
+import { CodeEditorProps } from '@/types/webappTypes/componentsTypes';
+// const MonacoEditor = dynamic(import('react-monaco-editor'), { ssr: false });
+
+const CodeEditor = ({
+ code,
+ setCode
+}: CodeEditorProps) => {
+
+ const handleEditorChange = (newCode: string, event: any) => {
+ setCode(newCode);
+ };
+
+ const options = {
+ autoIndent: 'full',
+ contextmenu: true,
+ fontFamily: 'monospace',
+ fontSize: 13,
+ lineHeight: 24,
+ hideCursorInOverviewRuler: true,
+ matchBrackets: 'always',
+ minimap: {
+ enabled: true,
+ },
+ scrollbar: {
+ horizontalSliderSize: 4,
+ verticalSliderSize: 18,
+ },
+ selectOnLineNumbers: true,
+ roundedSelection: false,
+ readOnly: false,
+ cursorStyle: 'line',
+ automaticLayout: true,
+ };
+
+ return (
+
+
+
+ )
+}
+
+export default CodeEditor
\ No newline at end of file
diff --git a/apps/web/app/(webapp)/(components)/EmptyState.tsx b/apps/web/app/(webapp)/(components)/EmptyState.tsx
index 45fc61ca..e170d990 100644
--- a/apps/web/app/(webapp)/(components)/EmptyState.tsx
+++ b/apps/web/app/(webapp)/(components)/EmptyState.tsx
@@ -1,6 +1,6 @@
import { EmptyStateProps } from '@/types/webappTypes/componentsTypes';
import React from 'react';
-import { EmptyStateButton } from '.';
+import { AddPermissionButton } from '../app/api-management/consumers/(components)';
const EmptyState = ({
type,
@@ -8,6 +8,8 @@ const EmptyState = ({
body,
parentStyle,
titleStyle,
+ searchQuery,
+ altData,
bodyStyle,
iconStyle,
containerStyle,
@@ -77,8 +79,14 @@ const EmptyState = ({
{
- button &&
-
+ button && (
+ buttonType == 'ADD_PERMISSIONS' ?
+
+ : null
+ )
}
diff --git a/apps/web/app/(webapp)/(components)/EmptyStateButton.tsx b/apps/web/app/(webapp)/(components)/EmptyStateButton.tsx
deleted file mode 100644
index 7a66e4e3..00000000
--- a/apps/web/app/(webapp)/(components)/EmptyStateButton.tsx
+++ /dev/null
@@ -1,27 +0,0 @@
-'use client'
-
-import { Button } from '@/components/globalComponents'
-import React from 'react'
-
-const EmptyStateButton = ({ type }: { type?: string}) => {
-
- const handleAddPermission = () => null;
-
- return (
-
- {
- type == 'ADD_PERMISSIONS' ?
-
- :
- null
- }
-
- )
-}
-
-export default EmptyStateButton
\ No newline at end of file
diff --git a/apps/web/app/(webapp)/(components)/ListPanel.tsx b/apps/web/app/(webapp)/(components)/ListPanel.tsx
new file mode 100644
index 00000000..cfc853b8
--- /dev/null
+++ b/apps/web/app/(webapp)/(components)/ListPanel.tsx
@@ -0,0 +1,88 @@
+'use client'
+
+import { ListPanelContainerProps } from '@/types/webappTypes/componentsTypes'
+import React, { useEffect, useState } from 'react';
+import { motion } from 'framer-motion';
+import { getObjectsNotInArrayB } from '@/utils/getObjectNotInArray';
+
+const ListPanel = ({
+ panel,
+ currentValue,
+ setCurrentValue,
+ containerStyle
+}: ListPanelContainerProps) => {
+
+ const [panelOut, setPanelOut] = useState([]);
+ const panelRemaining = getObjectsNotInArrayB(panel, panelOut);
+
+ useEffect(() => {
+ setPanelOut([panel[0]]);
+ }, []);
+
+ const handlePanelList = (data: any) => {
+ if (panelOut?.find((item: any) => item?.id == data?.id)) {
+ const filteredItem = panelOut?.filter(item => item?.id != data?.id);
+ setPanelOut(filteredItem);
+ } else {
+ setPanelOut((prev: any) => [...prev, data]);
+ }
+ }
+
+ return (
+
+ {
+ panelOut?.map((data) => (
+
setCurrentValue(data?.value)}
+ >
+
+ {data?.label}
+
+
+ {
+ currentValue == data?.value &&
+
+ }
+
+ ))
+ }
+
+
+
+
+
+ {
+ panelRemaining?.map((data) => (
+
+ ))
+ }
+
+
+
+ )
+}
+
+export default ListPanel
\ No newline at end of file
diff --git a/apps/web/app/(webapp)/(components)/index.ts b/apps/web/app/(webapp)/(components)/index.ts
index 6c2843d4..c29b7342 100644
--- a/apps/web/app/(webapp)/(components)/index.ts
+++ b/apps/web/app/(webapp)/(components)/index.ts
@@ -27,7 +27,8 @@ import TierBox from "./TierBox";
import DownloadButton from "./DownloadButton";
import DragAndUploadFile from "./DragAndUploadFile";
import KybBanner from "./KybBanner";
-import EmptyStateButton from "./EmptyStateButton";
+import ListPanel from "./ListPanel";
+import CodeEditor from "./CodeEditor";
export {
DatePicker,
@@ -59,5 +60,6 @@ export {
TierBox,
DownloadButton,
DragAndUploadFile,
- EmptyStateButton
+ ListPanel,
+ CodeEditor
}
\ No newline at end of file
diff --git a/apps/web/app/(webapp)/app/api-management/collections/(components)/CollectionSection.tsx b/apps/web/app/(webapp)/app/api-management/collections/(components)/CollectionSection.tsx
index e9597f5f..a6ae24f9 100644
--- a/apps/web/app/(webapp)/app/api-management/collections/(components)/CollectionSection.tsx
+++ b/apps/web/app/(webapp)/app/api-management/collections/(components)/CollectionSection.tsx
@@ -1,14 +1,12 @@
'use client'
-import { AppCenterModal, AppRightModal, ConfigurationBox, EmptyState, TableElement, TwoFactorAuthModal } from '@/app/(webapp)/(components)'
+import { AppCenterModal, ConfigurationBox, EmptyState, TableElement, TwoFactorAuthModal } from '@/app/(webapp)/(components)'
import { SearchBar, SelectElement } from '@/components/forms'
import { COLLECTION_ACTIONS_DATA } from '@/data/collectionDatas'
import { HeadersProps, HostsProps, SectionsProps, SnisProps } from '@/types/webappTypes/appTypes'
import { createColumnHelper } from '@tanstack/react-table'
import { useRouter } from 'next/navigation'
import React, { FormEvent, useEffect, useState } from 'react'
-import ApiConfiguration from './ApiConfiguration'
-import ModifyApiConfiguration from './ModifyApiConfiguration'
import { updateSearchParams } from '@/utils/searchParams'
import clientAxiosRequest from '@/hooks/clientAxiosRequest'
import * as API from '@/config/endpoints';
@@ -40,50 +38,50 @@ const CollectionSection = ({
const [api, setApi] = useState(null);
const profile = altData;
const userType = profile?.user?.role?.parent?.slug;
- const [api_endpoint, setApiEndpoint] = useState(null);
+ // const [api_endpoint, setApiEndpoint] = useState(null);
const environment = 'development';
// console.log(rawData);
- const [endpoint_url, setEndpointUrl] = useState('');
- const [parameters, setParameters] = useState('');
- const [snis, setSnis] = useState([]);
- const [hosts, setHost] = useState([]);
- const [headers, setHeaders] = useState([]);
+ // const [endpoint_url, setEndpointUrl] = useState('');
+ // const [parameters, setParameters] = useState('');
+ // const [snis, setSnis] = useState([]);
+ // const [hosts, setHost] = useState([]);
+ // const [headers, setHeaders] = useState([]);
// const getUserProfile = getJsCookies('aperta-user-profile');
// const userProfile = getUserProfile ? JSON.parse(getUserProfile) : null;
// const userType = userProfile?.userType;
- const refreshData = () => {
- setEndpointUrl('');
- setParameters('');
- setSnis([]);
- setHost([]);
- setHeaders([]);
- }
-
- const updateFields = (value: any) => {
- setEndpointUrl(value?.endpoint_url);
- setParameters(value?.parameters);
- }
-
- async function FetchData() {
- const result = await clientAxiosRequest({
- headers: {},
- apiEndpoint: API.getAPI({
- environment,
- id: api?.id
- }),
- method: 'GET',
- data: null,
- noToast: true,
- });
- setApiEndpoint(result?.data);
- }
-
- useEffect(() => {
- api?.id && FetchData();
- }, [api?.id]);
+ // const refreshData = () => {
+ // setEndpointUrl('');
+ // setParameters('');
+ // setSnis([]);
+ // setHost([]);
+ // setHeaders([]);
+ // }
+
+ // const updateFields = (value: any) => {
+ // setEndpointUrl(value?.endpoint_url);
+ // setParameters(value?.parameters);
+ // }
+
+ // async function FetchData() {
+ // const result = await clientAxiosRequest({
+ // headers: {},
+ // apiEndpoint: API.getAPI({
+ // environment,
+ // id: api?.id
+ // }),
+ // method: 'GET',
+ // data: null,
+ // noToast: true,
+ // });
+ // setApiEndpoint(result?.data);
+ // }
+
+ // useEffect(() => {
+ // api?.id && FetchData();
+ // }, [api?.id]);
useEffect(() => {
const slug = updateSearchParams('slug', details?.name);
@@ -134,8 +132,8 @@ const CollectionSection = ({
data: {
"name": api?.name,
"enabled": Boolean(openModal == 'activate'),
- "url": api?.url,
- "route": api?.route
+ "upstream": api?.upstream,
+ "downstream": api?.downstream
}
});
@@ -147,59 +145,59 @@ const CollectionSection = ({
}
}
- const handleApiConfiguration = (code: string, e?: FormEvent) => {
- e && e.preventDefault();
-
- if (profile?.user?.twofaEnabled && !code) {
- setOpen2FA(true);
- } else {
- setLoading(true);
- // TODO: GET CONFIGURATION ENDPOINT
- }
- }
-
- const handleApiModification = async (code: string, e?: FormEvent) => {
- e && e.preventDefault();
-
- if (profile?.user?.twofaEnabled && !code) {
- setOpen2FA(true);
- } else {
- setLoading(true);
- const result: any = await clientAxiosRequest({
- headers: code ? { 'X-TwoFA-Code' : code, } : {},
- apiEndpoint: API.updateAPI({
- environment,
- id: api?.id
- }),
- method: 'PATCH',
- data: {
- "name": api?.name,
- "enabled": true,
- "url": endpoint_url,
- "route": {
- "paths": [
- parameters
- ],
- "methods": api?.route?.methods
- }
- }
- });
-
- setLoading(false);
- if (result?.status == 200) {
- close2FAModal();
- refreshData();
- router.refresh();
- }
- }
- }
+ // const handleApiConfiguration = (code: string, e?: FormEvent) => {
+ // e && e.preventDefault();
+
+ // if (profile?.user?.twofaEnabled && !code) {
+ // setOpen2FA(true);
+ // } else {
+ // setLoading(true);
+ // // TODO: GET CONFIGURATION ENDPOINT
+ // }
+ // }
+
+ // const handleApiModification = async (code: string, e?: FormEvent) => {
+ // e && e.preventDefault();
+
+ // if (profile?.user?.twofaEnabled && !code) {
+ // setOpen2FA(true);
+ // } else {
+ // setLoading(true);
+ // const result: any = await clientAxiosRequest({
+ // headers: code ? { 'X-TwoFA-Code' : code, } : {},
+ // apiEndpoint: API.updateAPI({
+ // environment,
+ // id: api?.id
+ // }),
+ // method: 'PATCH',
+ // data: {
+ // "name": api?.name,
+ // "enabled": true,
+ // "url": endpoint_url,
+ // "route": {
+ // "paths": [
+ // parameters
+ // ],
+ // "methods": api?.route?.methods
+ // }
+ // }
+ // });
+
+ // setLoading(false);
+ // if (result?.status == 200) {
+ // close2FAModal();
+ // refreshData();
+ // router.refresh();
+ // }
+ // }
+ // }
const handle2FA = (value: string) => {
- openModal == 'configure' ?
- handleApiConfiguration(value, undefined) :
- openModal == 'modify' ?
- handleApiModification(value, undefined) :
- handleActivateDeactivateDeleteApi(value);
+ // openModal == 'configure' ?
+ // handleApiConfiguration(value, undefined) :
+ // openModal == 'modify' ?
+ // handleApiModification(value, undefined) :
+ handleActivateDeactivateDeleteApi(value);
};
const actionColumn = columnHelper.accessor('actions', {
@@ -223,11 +221,13 @@ const CollectionSection = ({
onClick={() => {
const api = rawData?.find(data => data?.id == row.original.id);
setApi(api)
- updateFields({
- endpoint_url: api?.url,
- parameters: api?.route?.paths
- })
- setOpenModal(action.name);
+ // updateFields({
+ // endpoint_url: api?.url,
+ // parameters: api?.route?.paths
+ // })
+ action.name == 'configure' ?
+ router.push(`/app/api-management/collections/${details?.id}/api-configuration?api_id=${row.original.id}`) :
+ setOpenModal(action.name);
}}
>
{action.icon}
@@ -245,7 +245,7 @@ const CollectionSection = ({
return (
<>
- {
+ {/* {
(openModal == 'configure' || openModal == 'modify') &&
}
- }
+ } */}
{
(
diff --git a/apps/web/app/(webapp)/app/api-management/collections/(components)/DownStreamForm.tsx b/apps/web/app/(webapp)/app/api-management/collections/(components)/DownStreamForm.tsx
new file mode 100644
index 00000000..5ca4b39e
--- /dev/null
+++ b/apps/web/app/(webapp)/app/api-management/collections/(components)/DownStreamForm.tsx
@@ -0,0 +1,77 @@
+'use client'
+
+import { InputElement } from '@/components/forms'
+import { APIConfigurationProps } from '@/types/webappTypes/appTypes';
+import React, { ChangeEvent, useEffect, useState } from 'react'
+
+const DownStreamForm = ({
+ rawData
+}: APIConfigurationProps) => {
+
+ const [api_name, setApiName] = useState('');
+ const [request_method, setRequestMethod] = useState('');
+ const [tier, setTier] = useState('');
+ const [paths, setPaths] = useState('');
+
+ console.log(rawData);
+
+ useEffect(() => {
+ setApiName(rawData?.name || '');
+ setRequestMethod(rawData?.downstream?.methods?.toString());
+ setTier('');
+ setPaths(rawData?.downstream?.paths?.toString());
+ }, []);
+
+ return (
+
+
+
+ Downstream Service
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export default DownStreamForm
\ No newline at end of file
diff --git a/apps/web/app/(webapp)/app/api-management/collections/(components)/TransformationForm.tsx b/apps/web/app/(webapp)/app/api-management/collections/(components)/TransformationForm.tsx
new file mode 100644
index 00000000..1a63af58
--- /dev/null
+++ b/apps/web/app/(webapp)/app/api-management/collections/(components)/TransformationForm.tsx
@@ -0,0 +1,180 @@
+'use client'
+
+import { AppCenterModal, CodeEditor, ListPanel, TwoFactorAuthModal } from '@/app/(webapp)/(components)'
+import { Button } from '@/components/globalComponents';
+import { API_CONFIGURATION_PANEL } from '@/data/collectionDatas';
+import clientAxiosRequest from '@/hooks/clientAxiosRequest';
+import { APIConfigurationProps } from '@/types/webappTypes/appTypes';
+import React, { useEffect, useState } from 'react';
+import * as API from '@/config/endpoints';
+
+const TransformationForm = ({
+ rawData,
+ profileData
+}: APIConfigurationProps) => {
+ const paths = API_CONFIGURATION_PANEL;
+ const [request_body, setRequestBody] = useState('');
+ const [response_body, setResponseBody] = useState('');
+ const [request_header, setRequestHeader] = useState('');
+ const [response_header, setResponseHeader] = useState('');
+
+ const [open2FA, setOpen2FA] = useState(false);
+ const [loading, setLoading] = useState(false);
+ const environment = 'development';
+ const [path, setPath] = useState('request_body');
+
+ async function fetchAPITransformation() {
+ const result: any = await clientAxiosRequest({
+ headers: {},
+ apiEndpoint: API.getAPITransformation({
+ environment,
+ id: rawData?.id
+ }),
+ method: 'GET',
+ data: null,
+ noToast: true
+ });
+
+ setResponseBody(result?.data?.downstream);
+ setRequestBody(result?.data?.upstream)
+ }
+
+ useEffect(() => {
+ fetchAPITransformation();
+ }, []);
+
+ const incorrect = (
+ !request_body ||
+ !response_body
+ )
+
+ const close2FAModal = () => {
+ setOpen2FA(false);
+ }
+
+ const handleSubmit = async (e: any, code: string,) => {
+ e && e.preventDefault();
+ if (profileData?.user?.twofaEnabled && !code) {
+ setOpen2FA(true);
+ } else {
+ setLoading(true);
+ const result: any = await clientAxiosRequest({
+ headers: code ? { 'X-TwoFA-Code' : code, } : {},
+ apiEndpoint: API.updateAPITransformation({
+ environment,
+ id: rawData?.id
+ }),
+ method: 'PUT',
+ data: {
+ "downstream": response_body,
+ "upstream": request_body,
+ }
+ });
+
+ if (result?.message) {
+ close2FAModal();
+ setLoading(false);
+ // router.refresh();
+ }
+ }
+ }
+
+ // console.log(
+ // `request_body >>>> ${request_body}, `,
+ // `response_body >>>> ${response_body}, `,
+ // `request_header >>>> ${request_header}, `,
+ // `response_header >>>> ${response_header}, `,
+ // `path >>>> ${path}`)
+
+ const handle2FA = (value: string) => {
+ handleSubmit('', value);
+ };
+
+ return (
+ <>
+ {
+ open2FA &&
+
+ handle2FA(value)}
+ />
+
+ }
+
+
+ >
+ )
+}
+
+export default TransformationForm
\ No newline at end of file
diff --git a/apps/web/app/(webapp)/app/api-management/collections/(components)/UpstreamForm.tsx b/apps/web/app/(webapp)/app/api-management/collections/(components)/UpstreamForm.tsx
new file mode 100644
index 00000000..7925939d
--- /dev/null
+++ b/apps/web/app/(webapp)/app/api-management/collections/(components)/UpstreamForm.tsx
@@ -0,0 +1,168 @@
+'use client'
+
+import { InputElement, ToggleSwitch } from '@/components/forms'
+import { Button } from '@/components/globalComponents';
+import clientAxiosRequest from '@/hooks/clientAxiosRequest';
+import { APIConfigurationProps } from '@/types/webappTypes/appTypes';
+import React, { useState } from 'react'
+import * as API from '@/config/endpoints';
+import { useRouter } from 'next/navigation';
+import { AppCenterModal, TwoFactorAuthModal } from '@/app/(webapp)/(components)';
+
+const UpStreamForm = ({
+ rawData,
+ profileData
+}: APIConfigurationProps) => {
+ const [enable, setEnable] = useState(rawData?.enabled || false);
+ const [host, setHost] = useState(rawData?.upstream?.host || '');
+ const [headerValue, setHeaderValue] = useState('');
+ const [headerName, setHeaderName] = useState('');
+ const [endpointUrl, setEndpointUrl] = useState(rawData?.upstream?.url || '');
+
+ const [open2FA, setOpen2FA] = useState(false);
+ const [loading, setLoading] = useState(false);
+ const environment = 'development';
+ const router = useRouter();
+
+ const incorrect = (
+ !host ||
+ // !headerName ||
+ // !headerValue ||
+ !endpointUrl
+ );
+
+ const close2FAModal = () => {
+ setOpen2FA(false);
+ }
+
+ const handleSubmit = async (e: any, code: string,) => {
+ e && e.preventDefault();
+ if (profileData?.user?.twofaEnabled && !code) {
+ setOpen2FA(true);
+ } else {
+ setLoading(true);
+ const result: any = await clientAxiosRequest({
+ headers: code ? { 'X-TwoFA-Code' : code, } : {},
+ apiEndpoint: API.updateAPI({
+ environment,
+ id: rawData?.id
+ }),
+ method: 'PATCH',
+ data: {
+ "name": rawData?.name,
+ "enabled": enable,
+ "upstream": {
+ ...rawData?.upstream,
+ host,
+ url: endpointUrl
+ },
+ "downstream": rawData?.downstream
+ }
+ });
+
+ if (result?.message) {
+ close2FAModal();
+ setLoading(false);
+ // router.refresh();
+ }
+ }
+ }
+
+ const handle2FA = (value: string) => {
+ handleSubmit('', value);
+ };
+
+ return (
+ <>
+ {
+ open2FA &&
+
+ handle2FA(value)}
+ />
+
+ }
+
+
+ >
+ )
+}
+
+export default UpStreamForm
\ No newline at end of file
diff --git a/apps/web/app/(webapp)/app/api-management/collections/(components)/index.ts b/apps/web/app/(webapp)/app/api-management/collections/(components)/index.ts
index 3b394708..03840501 100644
--- a/apps/web/app/(webapp)/app/api-management/collections/(components)/index.ts
+++ b/apps/web/app/(webapp)/app/api-management/collections/(components)/index.ts
@@ -6,6 +6,9 @@ import HostsContainer from "./HostsContainer";
import SnisContainer from "./SnisContainer";
import HeadersContainer from "./HeadersContainer";
import ActivateDeactivateDeleteApi from "./ActivateDeactivateDeleteApi";
+import DownStreamForm from "./DownStreamForm";
+import TransformationForm from "./TransformationForm";
+import UpstreamForm from "./UpstreamForm";
export {
CollectionsTable,
@@ -15,5 +18,8 @@ export {
HostsContainer,
SnisContainer,
HeadersContainer,
- ActivateDeactivateDeleteApi
+ ActivateDeactivateDeleteApi,
+ DownStreamForm,
+ TransformationForm,
+ UpstreamForm
}
\ No newline at end of file
diff --git a/apps/web/app/(webapp)/app/api-management/collections/[id]/api-configuration/page.tsx b/apps/web/app/(webapp)/app/api-management/collections/[id]/api-configuration/page.tsx
new file mode 100644
index 00000000..616de3c5
--- /dev/null
+++ b/apps/web/app/(webapp)/app/api-management/collections/[id]/api-configuration/page.tsx
@@ -0,0 +1,56 @@
+import { UrlParamsProps } from '@/types/webappTypes/appTypes'
+import React from 'react'
+import { DownStreamForm, TransformationForm, UpstreamForm } from '../../(components)';
+import { applyAxiosRequest } from '@/hooks';
+import * as API from '@/config/endpoints';
+import Logout from '@/components/globalComponents/Logout';
+
+const APIConfigurationPage = async({ params, searchParams }: UrlParamsProps) => {
+ const api_id = searchParams?.api_id || '';
+ const environment = 'development';
+
+ const fetchedAPI: any = await applyAxiosRequest({
+ headers: {},
+ apiEndpoint: API.getAPI({
+ environment,
+ id: api_id
+ }),
+ method: 'GET',
+ data: null
+ })
+
+ const fetchedProfile: any = await applyAxiosRequest({
+ headers: {},
+ apiEndpoint: API.getProfile(),
+ method: 'GET',
+ data: null
+ });
+
+ if (fetchedAPI?.status == 401) {
+ return
+ }
+
+ let apiDetails = fetchedAPI?.data;
+ let profile = fetchedProfile?.data;
+
+ return (
+
+
+ API Configuration
+
+
+
+
+
+
+ )
+}
+
+export default APIConfigurationPage
\ No newline at end of file
diff --git a/apps/web/app/(webapp)/app/api-management/collections/[id]/page.tsx b/apps/web/app/(webapp)/app/api-management/collections/[id]/page.tsx
index 6aef3505..252ecbae 100644
--- a/apps/web/app/(webapp)/app/api-management/collections/[id]/page.tsx
+++ b/apps/web/app/(webapp)/app/api-management/collections/[id]/page.tsx
@@ -55,11 +55,11 @@ const CollectionPage = async ({ params, searchParams }: UrlParamsProps) => {
return({
...endpoint,
api_name: endpoint?.name,
- request_method: endpoint?.route?.methods?.toString(),
+ request_method: endpoint?.downstream?.methods?.toString(),
configured: endpoint?.enabled,
- endpoint_url: endpoint?.url,
+ endpoint_url: endpoint?.upstream?.url,
tier: '',
- parameters: endpoint?.route?.paths?.toString(),
+ parameters: endpoint?.downstream?.paths?.toString(),
});
})
diff --git a/apps/web/app/(webapp)/app/api-management/consumers/(components)/AddPermissionButton.tsx b/apps/web/app/(webapp)/app/api-management/consumers/(components)/AddPermissionButton.tsx
new file mode 100644
index 00000000..52812d4c
--- /dev/null
+++ b/apps/web/app/(webapp)/app/api-management/consumers/(components)/AddPermissionButton.tsx
@@ -0,0 +1,139 @@
+'use client'
+
+import { Button } from '@/components/globalComponents'
+import clientAxiosRequest from '@/hooks/clientAxiosRequest';
+import { useRouter } from 'next/navigation';
+import React, { FormEvent, useEffect, useState } from 'react';
+import * as API from '@/config/endpoints';
+import { AppCenterModal, AppRightModal, TwoFactorAuthModal } from '@/app/(webapp)/(components)';
+import { AddAPIPermissions } from '.';
+
+const AddPermissionButton = ({
+ searchQuery,
+ customerId
+}: {
+ searchQuery: string,
+ customerId: string
+}) => {
+ const [openModal, setOpenModal] = useState(false);
+ const [open2FA, setOpen2FA] = useState(false);
+ const [loading, setLoading] = useState(false);
+ const [profile, setProfile] = useState(null);
+ const router = useRouter();
+ const [collections, setCollections] = useState([]);
+ const [apiIds, setApiIds] = useState([]);
+ const environment = 'development';
+
+ const fetchAPICollections = async () => {
+ const result: any = await clientAxiosRequest({
+ headers: {},
+ apiEndpoint: API.getCollections(),
+ method: 'GET',
+ data: null,
+ noToast: true
+ });
+ setCollections(result?.data);
+ }
+
+ const fetchProfile = async () => {
+ const result: any = await clientAxiosRequest({
+ headers: {},
+ apiEndpoint: API.getProfile(),
+ method: 'GET',
+ data: null,
+ noToast: true
+ });
+ setProfile(result?.data);
+ }
+
+ useEffect(() => {
+ fetchProfile();
+ fetchAPICollections();
+ }, []);
+
+ const close2FAModal = () => {
+ setOpen2FA(false);
+ setOpenModal(false);
+ };
+
+ const refreshData = () => {
+ setApiIds([]);
+ }
+
+ const handleAddPermission = async (code: string, e?: FormEvent) => {
+ e && e.preventDefault();
+
+ if (profile?.user?.twofaEnabled && !code) {
+ setOpen2FA(true);
+ } else {
+ setLoading(true);
+
+ let sanitizedApiIds = apiIds?.map((item: any) => item.id);
+
+ const result: any = await clientAxiosRequest({
+ headers: code ? { 'X-TwoFA-Code' : code, } : {},
+ apiEndpoint: API.postAssignAPIs({
+ environment,
+ id: customerId
+ }),
+ method: 'POST',
+ data: { apiIds: sanitizedApiIds }
+ });
+
+ setLoading(false);
+ if (result?.status == 201) {
+ close2FAModal();
+ refreshData();
+ router.refresh();
+ }
+ }
+ }
+
+ return (
+ <>
+ {
+ openModal &&
+ setOpenModal(false)}
+ childrenStyle='!px-0 !py-0 !pt-[20px]'
+ >
+ setOpenModal(false)}
+ data={collections}
+ next={handleAddPermission}
+ searchQuery={searchQuery}
+ loading={loading}
+ api_ids={apiIds}
+ setApiIds={setApiIds}
+ />
+
+ }
+
+ {
+ open2FA &&
+
+ handleAddPermission(value, undefined)}
+ />
+
+ }
+
+
+
+ >
+ )
+}
+
+export default AddPermissionButton
\ No newline at end of file
diff --git a/apps/web/app/(webapp)/app/api-management/consumers/(components)/ConsumerSections.tsx b/apps/web/app/(webapp)/app/api-management/consumers/(components)/ConsumerSections.tsx
index c662c3ba..c1f3d9da 100644
--- a/apps/web/app/(webapp)/app/api-management/consumers/(components)/ConsumerSections.tsx
+++ b/apps/web/app/(webapp)/app/api-management/consumers/(components)/ConsumerSections.tsx
@@ -304,8 +304,10 @@ const ConsumerSections = ({
title='Nothing to show'
type='DEFAULT'
parentStyle='!h-[calc(100vh-600px)]'
+ altData={altData?.id}
body='There’s no information to show for this user yet.'
button={path == ''}
+ searchQuery={filters[0]}
buttonType='ADD_PERMISSIONS'
/>
}
diff --git a/apps/web/app/(webapp)/app/api-management/consumers/(components)/index.ts b/apps/web/app/(webapp)/app/api-management/consumers/(components)/index.ts
index 64df0f35..ffe78b29 100644
--- a/apps/web/app/(webapp)/app/api-management/consumers/(components)/index.ts
+++ b/apps/web/app/(webapp)/app/api-management/consumers/(components)/index.ts
@@ -11,6 +11,7 @@ import EditPermissionButton from "./EditPermissionButton";
import AddAPIPermissions from "./AddAPIPermissions";
import ApiPermissionCard from "./ApiPermissionCard";
import ApiPermissionSelector from "./ApiPermissionSelector";
+import AddPermissionButton from "./AddPermissionButton";
export {
ConsumersTable,
@@ -25,5 +26,6 @@ export {
EditPermissionButton,
AddAPIPermissions,
ApiPermissionCard,
- ApiPermissionSelector
+ ApiPermissionSelector,
+ AddPermissionButton
}
\ No newline at end of file
diff --git a/apps/web/app/(webapp)/app/api-management/consumers/[id]/page.tsx b/apps/web/app/(webapp)/app/api-management/consumers/[id]/page.tsx
index 8ff647df..f314d007 100644
--- a/apps/web/app/(webapp)/app/api-management/consumers/[id]/page.tsx
+++ b/apps/web/app/(webapp)/app/api-management/consumers/[id]/page.tsx
@@ -84,15 +84,15 @@ const ConsumerPage = async ({ params, searchParams }: UrlParamsProps) => {
});
const consents = CONSUMER_CONSENTS;
- const collections = CONSUMER_COLLECTIONS_FULLDATA;
- // const collections = fetchedCollection?.data?.map((collection: any) => {
- // return({
- // ...collection,
- // collection_name: collection?.name,
- // endpoints: collection?.endpoints,
- // categories: collection?.categories
- // })
- // });
+ // const collections = CONSUMER_COLLECTIONS_FULLDATA;
+ const collections = fetchedCollection?.data?.map((collection: any) => {
+ return({
+ ...collection,
+ collection_name: collection?.name,
+ endpoints: collection?.endpoints,
+ categories: collection?.categories
+ })
+ });
const filters = [search_query, status, date_sent]
diff --git a/apps/web/config/endpoints.ts b/apps/web/config/endpoints.ts
index b35bdf09..0c46435d 100644
--- a/apps/web/config/endpoints.ts
+++ b/apps/web/config/endpoints.ts
@@ -86,6 +86,10 @@ export const postUnassignAPIs = ({ environment, id }: GetSingleEnvironmentProps)
`${BASE_URL}/apis/${environment}/company/${id}/unassign`;
export const getCompanyAPIs = ({ page, limit, environment, companyId }: GetEnvironmentProps) =>
`${BASE_URL}/apis/${environment}/company/${companyId}?page=${page}${limit ? `&limit=${limit}`: ''}`;
+export const updateAPITransformation = ({ environment, id }: GetSingleEnvironmentProps) =>
+ `${BASE_URL}/apis/${environment}/${id}/transformation`;
+export const getAPITransformation = ({ environment, id }: GetSingleEnvironmentProps) =>
+ `${BASE_URL}/apis/${environment}/${id}/transformation`;
// COMPANY
export const getCompanies = ({ page, limit, name, createdAt_gt, createdAt_l, status }: GetListProps) =>
diff --git a/apps/web/data/collectionDatas.tsx b/apps/web/data/collectionDatas.tsx
index 7627dd79..5762424e 100644
--- a/apps/web/data/collectionDatas.tsx
+++ b/apps/web/data/collectionDatas.tsx
@@ -17,6 +17,29 @@ export const COLLECTIONS_TABLE_HEADERS = [
}
];
+export const API_CONFIGURATION_PANEL = [
+ {
+ id: 1,
+ label: 'Request Body',
+ value: 'request_body'
+ },
+ {
+ id: 2,
+ label: 'Response Body',
+ value: 'response_body'
+ },
+ {
+ id: 3,
+ label: 'Request Header',
+ value: 'request_header'
+ },
+ {
+ id: 4,
+ label: 'Response Header',
+ value: 'response_header'
+ }
+];
+
export const DASHBOARD_API_HEADERS = [
{
header: 'API Name',
@@ -74,31 +97,31 @@ export const COLLECTION_ACTIONS_DATA = [
},
- // {
- // id: 2,
- // label: 'Configure',
- // name: 'configure',
- // type: 'not_configured',
- // icon:
- // },
{
- id: 3,
- label: 'Modify',
- name: 'modify',
+ id: 2,
+ label: 'Configure',
+ name: 'configure',
type: 'all',
icon:
},
+ // {
+ // id: 3,
+ // label: 'Modify',
+ // name: 'modify',
+ // type: 'all',
+ // icon:
+ // },
{
id: 4,
label: 'Deactivate',
diff --git a/apps/web/package.json b/apps/web/package.json
index cd909233..eac8adf4 100644
--- a/apps/web/package.json
+++ b/apps/web/package.json
@@ -24,6 +24,7 @@
"react-chartjs-2": "^5.2.0",
"react-dom": "^18",
"react-icons": "^4.11.0",
+ "react-monaco-editor": "^0.55.0",
"react-tailwindcss-datepicker": "^1.6.6",
"react-toastify": "^9.1.3",
"xlsx": "^0.18.5",
diff --git a/apps/web/types/webappTypes/appTypes.ts b/apps/web/types/webappTypes/appTypes.ts
index e32d3c21..a1e64045 100644
--- a/apps/web/types/webappTypes/appTypes.ts
+++ b/apps/web/types/webappTypes/appTypes.ts
@@ -27,6 +27,7 @@ export interface searchParamsProps {
two_fa?: string;
token?: string;
alt_data?: any;
+ api_id?: string;
}
export interface ParamsProps {
@@ -262,6 +263,11 @@ export interface APIConfigurationContainerProps {
handleAdd: (type: string) => void;
}
+export interface APIConfigurationProps {
+ rawData: any;
+ profileData?: any;
+}
+
export interface CreateRoleButtonProps {
permissions_list: any;
}
diff --git a/apps/web/types/webappTypes/componentsTypes.ts b/apps/web/types/webappTypes/componentsTypes.ts
index 5674398e..9a893c41 100644
--- a/apps/web/types/webappTypes/componentsTypes.ts
+++ b/apps/web/types/webappTypes/componentsTypes.ts
@@ -53,8 +53,10 @@ export interface EmptyStateProps {
title: string;
body: string;
parentStyle?: string;
+ altData?: any;
titleStyle?: string;
bodyStyle?: string;
+ searchQuery?: string;
iconStyle?: string;
containerStyle?: string;
button?: boolean;
@@ -82,6 +84,10 @@ export interface PanelContainerProps {
status?: string;
}
+export interface ListPanelContainerProps extends PanelContainerProps{
+ setCurrentValue: Dispatch>;
+}
+
export interface TopPanelContainerProps extends PanelContainerProps{
name: string;
}
@@ -142,6 +148,11 @@ export interface CodeSnippetProps {
codeContainerStyle?: string;
}
+export interface CodeEditorProps {
+ code: any;
+ setCode: Dispatch>;
+}
+
export interface RequestMethodTextProps {
method: any;
styles?: any;
diff --git a/apps/web/utils/getObjectNotInArray.ts b/apps/web/utils/getObjectNotInArray.ts
new file mode 100644
index 00000000..e107fb90
--- /dev/null
+++ b/apps/web/utils/getObjectNotInArray.ts
@@ -0,0 +1,7 @@
+export const getObjectsNotInArrayB = (arrayA: any[], arrayB: any[]) => {
+ const result = arrayA.filter((objA) => {
+ return !arrayB.some((objB) => objB.id === objA.id);
+ });
+
+ return result;
+}
\ No newline at end of file
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 91d71e3b..96c45686 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -215,6 +215,9 @@ importers:
react-icons:
specifier: ^4.11.0
version: 4.11.0(react@18.2.0)
+ react-monaco-editor:
+ specifier: ^0.55.0
+ version: 0.55.0(@types/react@18.2.28)(monaco-editor@0.44.0)(react@18.2.0)
react-tailwindcss-datepicker:
specifier: ^1.6.6
version: 1.6.6(dayjs@1.11.10)(react@18.2.0)
@@ -1704,7 +1707,6 @@ packages:
/@types/prop-types@15.7.8:
resolution: {integrity: sha512-kMpQpfZKSCBqltAJwskgePRaYRFukDkm1oItcAbC3gNELR20XIBcN9VRgg4+m8DKsTfkWeA4m4Imp4DDuWy7FQ==}
- dev: true
/@types/qs@6.9.8:
resolution: {integrity: sha512-u95svzDlTysU5xecFNTgfFG5RUWu1A9P0VzgpcIiGZA9iraHOdSzcxMxQ55DyeRaGCSxQi7LxXDI4rzq/MYfdg==}
@@ -1726,11 +1728,9 @@ packages:
'@types/prop-types': 15.7.8
'@types/scheduler': 0.16.4
csstype: 3.1.2
- dev: true
/@types/scheduler@0.16.4:
resolution: {integrity: sha512-2L9ifAGl7wmXwP4v3pN4p2FLhD0O1qsJpvKmNin5VA8+UvNVb447UDaAEV6UdrkA+m/Xs58U1RFps44x6TFsVQ==}
- dev: true
/@types/semver@7.5.3:
resolution: {integrity: sha512-OxepLK9EuNEIPxWNME+C6WwbRAOOI2o2BaQEGzz5Lu2e4Z5eDnEo+/aVEDMIXywoJitJ7xWd641wrGLZdtwRyw==}
@@ -2957,7 +2957,6 @@ packages:
/csstype@3.1.2:
resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==}
- dev: true
/damerau-levenshtein@1.0.8:
resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==}
@@ -5600,6 +5599,10 @@ packages:
resolution: {integrity: sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==}
dev: false
+ /monaco-editor@0.44.0:
+ resolution: {integrity: sha512-5SmjNStN6bSuSE5WPT2ZV+iYn1/yI9sd4Igtk23ChvqB7kDk9lZbB9F5frsuvpB+2njdIeGGFf2G4gbE6rCC9Q==}
+ dev: false
+
/ms@2.0.0:
resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
@@ -6269,7 +6272,6 @@ packages:
loose-envify: 1.4.0
object-assign: 4.1.1
react-is: 16.13.1
- dev: true
/proxy-addr@2.0.7:
resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==}
@@ -6384,12 +6386,24 @@ packages:
/react-is@16.13.1:
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
- dev: true
/react-is@18.2.0:
resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==}
dev: true
+ /react-monaco-editor@0.55.0(@types/react@18.2.28)(monaco-editor@0.44.0)(react@18.2.0):
+ resolution: {integrity: sha512-GdEP0Q3Rn1dczfKEEyY08Nes5plWwIYU4sWRBQO0+jsQWQsKMHKCC6+hPRwR7G/4aA3V/iU9jSmWPzVJYMVFSQ==}
+ peerDependencies:
+ '@types/react': '>=16 <= 18'
+ monaco-editor: ^0.44.0
+ react: '>=16 <= 18'
+ dependencies:
+ '@types/react': 18.2.28
+ monaco-editor: 0.44.0
+ prop-types: 15.8.1
+ react: 18.2.0
+ dev: false
+
/react-tailwindcss-datepicker@1.6.6(dayjs@1.11.10)(react@18.2.0):
resolution: {integrity: sha512-kHSUonRO86PoYQQWPqpaSw2JeEn9OafdLsLBG85zO5Sfs23Ku8Ixt/YO+Is3TCBcFeOKnZgzhGLmP3NAXVlFkA==}
peerDependencies: