From 759ee93a72c9a32f447e6e56d13351524152b811 Mon Sep 17 00:00:00 2001 From: Athul Date: Mon, 26 Feb 2024 22:02:34 +0530 Subject: [PATCH 1/8] Basic workflow and adapter exception messages --- .../adapter_processor/adapter_processor.py | 6 +++-- backend/adapter_processor/views.py | 26 +++++++++++++------ backend/platform_settings/exceptions.py | 4 +++ .../workflow_manager/workflow/exceptions.py | 4 +++ backend/workflow_manager/workflow/views.py | 11 ++++++++ 5 files changed, 41 insertions(+), 10 deletions(-) diff --git a/backend/adapter_processor/adapter_processor.py b/backend/adapter_processor/adapter_processor.py index b44088a64a..07650e2519 100644 --- a/backend/adapter_processor/adapter_processor.py +++ b/backend/adapter_processor/adapter_processor.py @@ -13,7 +13,7 @@ ) from django.conf import settings from django.core.exceptions import ObjectDoesNotExist -from platform_settings.exceptions import ActiveKeyNotFound +from platform_settings.exceptions import ActiveKeyNotFound, InvalidRequest from platform_settings.platform_auth_service import ( PlatformAuthenticationService, ) @@ -120,7 +120,9 @@ def test_adapter(adapter_id: str, adapter_metadata: dict[str, Any]) -> bool: logger.info(f"{adapter_id} test result: {test_result}") return test_result except ActiveKeyNotFound: - raise + raise ActiveKeyNotFound() + except InvalidRequest as e: + raise InvalidRequest(str(e.detail)) except Exception as e: logger.error(f"Error while testing {adapter_id}: {e}") if isinstance(e, AdapterError): diff --git a/backend/adapter_processor/views.py b/backend/adapter_processor/views.py index 2009527afa..670b5d5611 100644 --- a/backend/adapter_processor/views.py +++ b/backend/adapter_processor/views.py @@ -96,14 +96,24 @@ def test(self, request: Request) -> Response: adapter_metadata[ AdapterKeys.ADAPTER_TYPE ] = serializer.validated_data.get(AdapterKeys.ADAPTER_TYPE) - test_result = AdapterProcessor.test_adapter( - adapter_id=adapter_id, adapter_metadata=adapter_metadata - ) - return Response( - {AdapterKeys.IS_VALID: test_result}, - status=status.HTTP_200_OK, - ) - + try: + test_result = AdapterProcessor.test_adapter( + adapter_id=adapter_id, adapter_metadata=adapter_metadata + ) + return Response( + {AdapterKeys.IS_VALID: test_result}, + status=status.HTTP_200_OK, + ) + except Exception as e: + if str(e).find("invalid_api_key") != -1: + return Response( + {"message": "Incorrect API key provided."}, + status=status.HTTP_401_UNAUTHORIZED, + ) + return Response( + {AdapterKeys.IS_VALID: False}, + status=status.HTTP_500_INTERNAL_SERVER_ERROR, + ) class AdapterInstanceViewSet(ModelViewSet): queryset = AdapterInstance.objects.all() diff --git a/backend/platform_settings/exceptions.py b/backend/platform_settings/exceptions.py index e591ae5ca9..009dbf6614 100644 --- a/backend/platform_settings/exceptions.py +++ b/backend/platform_settings/exceptions.py @@ -32,6 +32,10 @@ class ActiveKeyNotFound(APIException): default_detail = "At least one active platform key should be available" +class InvalidRequest(APIException): + status_code = 401 + default_detail = "Invalid Request" + class DuplicateData(APIException): status_code = 400 default_detail = "Duplicate Data" diff --git a/backend/workflow_manager/workflow/exceptions.py b/backend/workflow_manager/workflow/exceptions.py index 82a9b35383..0e267f69b6 100644 --- a/backend/workflow_manager/workflow/exceptions.py +++ b/backend/workflow_manager/workflow/exceptions.py @@ -37,6 +37,10 @@ class InvalidRequest(APIException): status_code = 400 default_detail = "Invalid Request" +class MissingEnvException(APIException): + status_code = 500 + default_detail = "At least one active platform key should be available." + class InternalException(APIException): """Internal Error. diff --git a/backend/workflow_manager/workflow/views.py b/backend/workflow_manager/workflow/views.py index 496c972125..079e271413 100644 --- a/backend/workflow_manager/workflow/views.py +++ b/backend/workflow_manager/workflow/views.py @@ -31,6 +31,7 @@ WorkflowExecutionError, WorkflowGenerationError, WorkflowRegenerationError, + MissingEnvException, ) from workflow_manager.workflow.generator import WorkflowGenerator from workflow_manager.workflow.models.workflow import Workflow @@ -241,8 +242,18 @@ def execute( status=status.HTTP_200_OK, ) except (InvalidRequest, WorkflowExecutionError) as exception: + logger.error(f"Error while executing workflow: {exception}") update_pipeline(pipeline_guid, Pipeline.PipelineStatus.FAILURE) raise exception + except MissingEnvException as exception: + update_pipeline(pipeline_guid, Pipeline.PipelineStatus.FAILURE) + logger.error(f"Error while executing workflow: {exception}") + return Response( + { + "error": "Please check the logs for more details: " + str(exception) + }, + status=status.HTTP_400_BAD_REQUEST + ) except Exception as exception: logger.error(f"Error while executing workflow: {exception}") update_pipeline(pipeline_guid, Pipeline.PipelineStatus.FAILURE) From badf00d6841d684c4b04789a8ff182ebd7f5d094 Mon Sep 17 00:00:00 2001 From: siddhiq Date: Tue, 27 Feb 2024 12:16:32 +0530 Subject: [PATCH 2/8] Corrected alignment of the OnBoard page to accommodate various screen sizes --- .../components/helpers/auth/RequireAuth.js | 13 +++- .../components/helpers/auth/RequireGuest.js | 9 ++- .../navigations/top-nav-bar/TopNavBar.css | 13 ++++ .../navigations/top-nav-bar/TopNavBar.jsx | 71 ++++++++++++++----- frontend/src/components/onboard/OnBoard.jsx | 14 ++-- frontend/src/components/onboard/onBoard.css | 64 +++++++++++++++++ frontend/src/helpers/GetStaticData.js | 13 ++++ 7 files changed, 169 insertions(+), 28 deletions(-) diff --git a/frontend/src/components/helpers/auth/RequireAuth.js b/frontend/src/components/helpers/auth/RequireAuth.js index 584884cf86..01e222d96e 100644 --- a/frontend/src/components/helpers/auth/RequireAuth.js +++ b/frontend/src/components/helpers/auth/RequireAuth.js @@ -1,6 +1,9 @@ import { Navigate, Outlet, useLocation } from "react-router-dom"; -import { getOrgNameFromPathname } from "../../../helpers/GetStaticData"; +import { + getOrgNameFromPathname, + onboardCompleted, +} from "../../../helpers/GetStaticData"; import { useSessionStore } from "../../../store/session-store"; const RequireAuth = () => { @@ -9,14 +12,20 @@ const RequireAuth = () => { const isLoggedIn = sessionDetails?.isLoggedIn; const orgName = sessionDetails?.orgName; const pathname = location?.pathname; + const adapters = sessionDetails?.adapters; const currOrgName = getOrgNameFromPathname(pathname); + let navigateTo = `/${orgName}/onboard`; + if (onboardCompleted(adapters)) { + navigateTo = `/${orgName}/etl`; + } + if (!isLoggedIn) { return ; } if (currOrgName !== orgName) { - return ; + return ; } return ; diff --git a/frontend/src/components/helpers/auth/RequireGuest.js b/frontend/src/components/helpers/auth/RequireGuest.js index 71bc242d93..2c5bf77e3e 100644 --- a/frontend/src/components/helpers/auth/RequireGuest.js +++ b/frontend/src/components/helpers/auth/RequireGuest.js @@ -1,17 +1,22 @@ import { Navigate, Outlet, useLocation } from "react-router-dom"; -import { publicRoutes } from "../../../helpers/GetStaticData"; +import { publicRoutes, onboardCompleted } from "../../../helpers/GetStaticData"; import { useSessionStore } from "../../../store/session-store"; const RequireGuest = () => { const { sessionDetails } = useSessionStore(); + const { orgName, adapters } = sessionDetails; const location = useLocation(); const pathname = location.pathname; + let navigateTo = `/${orgName}/onboard`; + if (onboardCompleted(adapters)) { + navigateTo = `/${orgName}/etl`; + } return !sessionDetails?.isLoggedIn && publicRoutes.includes(pathname) ? ( ) : ( - + ); }; diff --git a/frontend/src/components/navigations/top-nav-bar/TopNavBar.css b/frontend/src/components/navigations/top-nav-bar/TopNavBar.css index 6a09d4035a..9506f67a90 100644 --- a/frontend/src/components/navigations/top-nav-bar/TopNavBar.css +++ b/frontend/src/components/navigations/top-nav-bar/TopNavBar.css @@ -40,4 +40,17 @@ .logout-button:active{ color: inherit !important; border-color: transparent !important; +} + +.top-nav-alert-col { + display: flex; + justify-content: center; +} + +.top-nav-alert-col .top-nav-alert-msg { + margin-right: 6px; +} + +.top-nav-alert-col .top-nav-alert-link { + text-decoration: underline; } \ No newline at end of file diff --git a/frontend/src/components/navigations/top-nav-bar/TopNavBar.jsx b/frontend/src/components/navigations/top-nav-bar/TopNavBar.jsx index 9bfec966a5..b647072e4b 100644 --- a/frontend/src/components/navigations/top-nav-bar/TopNavBar.jsx +++ b/frontend/src/components/navigations/top-nav-bar/TopNavBar.jsx @@ -8,11 +8,16 @@ import { Switch, Typography, } from "antd"; -import { useEffect } from "react"; +import { useEffect, useState } from "react"; import { useNavigate } from "react-router-dom"; import { MoonIcon, SunIcon, UnstractLogo } from "../../../assets/index.js"; -import { THEME, getBaseUrl } from "../../../helpers/GetStaticData.js"; +import { + THEME, + getBaseUrl, + onboardCompleted, +} from "../../../helpers/GetStaticData.js"; +import { useAxiosPrivate } from "../../../hooks/useAxiosPrivate.js"; import useLogout from "../../../hooks/useLogout.js"; import "../../../layouts/page-layout/PageLayout.css"; import { useSessionStore } from "../../../store/session-store.js"; @@ -23,13 +28,39 @@ import "./TopNavBar.css"; function TopNavBar() { const navigate = useNavigate(); const { sessionDetails } = useSessionStore(); - const { orgName, adapters } = sessionDetails; + const { orgName } = sessionDetails; const updateSessionDetails = useSessionStore( (state) => state.updateSessionDetails ); const baseUrl = getBaseUrl(); const onBoardUrl = baseUrl + `/${orgName}/onboard`; const logout = useLogout(); + const axiosPrivate = useAxiosPrivate(); + const [showOnboardBanner, setShowOnboardBanner] = useState(false); + + useEffect(() => { + getAdapters(); + }, []); + + const getAdapters = () => { + const requestOptions = { + method: "GET", + url: `/api/v1/unstract/${sessionDetails?.orgId}/adapter/`, + }; + + axiosPrivate(requestOptions) + .then((res) => { + const data = res?.data; + const adapterTypes = [ + ...new Set(data?.map((obj) => obj.adapter_type.toLowerCase())), + ]; + if (!onboardCompleted(adapterTypes)) { + setShowOnboardBanner(true); + } + }) + .catch((err) => {}) + .finally(() => {}); + }; // Dropdown items const items = [ @@ -86,29 +117,33 @@ function TopNavBar() { return ( - + - - {adapters.length < 3 && ( + + {showOnboardBanner && ( - Complete it to start using Unstract. - + message={ + <> + + Your setup process is incomplete. Now, that's a bummer! + + + Complete it to start using Unstract + + } + showIcon /> )} - + { - if (adapters?.length >= 3) { + if (onboardCompleted(adaptersList)) { navigate(homePageUrl); } - }, []); + }, [adaptersList]); const steps = [ { @@ -62,7 +63,8 @@ function OnBoard() { }; const addNewItem = (row, isEdit) => { - navigate(0); + const newAdapter = row?.adapter_type.toLowerCase(); + setAdaptersList([...adaptersList, newAdapter]); }; return ( @@ -101,7 +103,7 @@ function OnBoard() { - {adapters?.includes(step.type) ? ( + {adaptersList?.includes(step.type) ? (
Configured diff --git a/frontend/src/components/onboard/onBoard.css b/frontend/src/components/onboard/onBoard.css index 1d96ca99f6..2944ac3d8b 100644 --- a/frontend/src/components/onboard/onBoard.css +++ b/frontend/src/components/onboard/onBoard.css @@ -4,6 +4,12 @@ margin-top: 50px; } +@media screen and (max-height: 900px) { + .onboard-content { + margin-top: 30px; + } +} + .uppercase-text { text-transform: uppercase; color: #0C355A; @@ -11,6 +17,18 @@ margin-bottom: 50px; } +@media screen and (max-height: 900px) { + .uppercase-text { + margin-bottom: 10px; + } +} + +@media screen and (max-height: 900px) { + h1 { + font-size: 1.2rem; + } +} + .text-title-style { color: #0C355A; font-family: 'SF Pro Text', sans-serif; @@ -44,6 +62,13 @@ margin-bottom: 50px; } +@media screen and (max-height: 900px) { + .landing-logo { + height: 30px; + margin-bottom: 10px; + } +} + .circle { position: absolute; left: 0%; @@ -70,6 +95,12 @@ margin-top: 25px; } +@media screen and (max-height: 900px) { + .later-div-style { + margin-top: 10px; + } +} + .svg-container { position: relative; width: 100px; @@ -99,4 +130,37 @@ .configured-text { margin-left: 8px; vertical-align: middle; +} + +@media screen and (max-height: 900px) { + .ant-space .ant-space-item .ant-card { + padding: 6px; + } +} + +@media screen and (max-height: 900px) { + .card-style { + width: 940px; + margin-bottom: 5px; + } +} + +@media screen and (max-height: 720px) and (max-width: 1280px){ + .card-style { + width: 1200px; + margin-bottom: 5px; + } +} + +@media screen and (max-height: 780px) and (max-width: 1024px){ + .card-style { + width: 940px; + margin-bottom: 5px; + } +} + +@media screen and (max-height: 800px) { + .ant-space .ant-space-item .ant-card .ant-card-body { + padding: 10px; + } } \ No newline at end of file diff --git a/frontend/src/helpers/GetStaticData.js b/frontend/src/helpers/GetStaticData.js index 996ed44bc7..d0b5e6b4b7 100644 --- a/frontend/src/helpers/GetStaticData.js +++ b/frontend/src/helpers/GetStaticData.js @@ -263,6 +263,18 @@ const handleException = (err, errMessage) => { } }; +const onboardCompleted = (adaptersList) => { + if (!Array.isArray(adaptersList)) { + return false; + } + const MANDATORY_ADAPTERS = ["llm", "vector_db", "embedding"]; + if (MANDATORY_ADAPTERS.length !== adaptersList.length) { + return false; + } + adaptersList = adaptersList.map((element) => element.toLowerCase()); + return MANDATORY_ADAPTERS.every((value) => adaptersList.includes(value)); +}; + export { CONNECTOR_TYPE_MAP, O_AUTH_PROVIDERS, @@ -278,6 +290,7 @@ export { getTimeForLogs, handleException, listOfAppDeployments, + onboardCompleted, promptStudioUpdateStatus, promptType, publicRoutes, From 2064d49fb53909dea9b375dadc159dad2fe5b981 Mon Sep 17 00:00:00 2001 From: Athul Date: Wed, 28 Feb 2024 14:22:17 +0530 Subject: [PATCH 3/8] Adapter error messages updated --- backend/adapter_processor/adapter_processor.py | 4 ++-- backend/adapter_processor/exceptions.py | 5 +++-- backend/adapter_processor/views.py | 11 ++++------- backend/backend/exceptions.py | 12 +++++++++++- .../input-output/configure-ds/ConfigureDs.jsx | 4 +++- frontend/src/helpers/GetStaticData.js | 2 +- tools/translate/src/main.py | 2 +- .../src/unstract/connectors/connectorkit.py | 2 +- .../src/unstract/connectors/databases/__init__.py | 2 +- .../src/unstract/connectors/filesystems/__init__.py | 2 +- 10 files changed, 28 insertions(+), 18 deletions(-) diff --git a/backend/adapter_processor/adapter_processor.py b/backend/adapter_processor/adapter_processor.py index 07650e2519..95478cf5c4 100644 --- a/backend/adapter_processor/adapter_processor.py +++ b/backend/adapter_processor/adapter_processor.py @@ -126,11 +126,11 @@ def test_adapter(adapter_id: str, adapter_metadata: dict[str, Any]) -> bool: except Exception as e: logger.error(f"Error while testing {adapter_id}: {e}") if isinstance(e, AdapterError): - raise TestAdapterInputException(str(e.message)) + raise TestAdapterInputException(e) elif isinstance(e, ActiveKeyNotFound): raise e else: - raise TestAdapterException() + raise TestAdapterException(str(e)) @staticmethod def __fetch_adapters_by_key_value(key: str, value: Any) -> Adapter: diff --git a/backend/adapter_processor/exceptions.py b/backend/adapter_processor/exceptions.py index 2feb8a2988..5634a90172 100644 --- a/backend/adapter_processor/exceptions.py +++ b/backend/adapter_processor/exceptions.py @@ -1,6 +1,7 @@ -from backend.exceptions import UnstractBaseException from rest_framework.exceptions import APIException +from backend.exceptions import UnstractBaseException + class IdIsMandatory(APIException): status_code = 400 @@ -41,7 +42,7 @@ class UniqueConstraintViolation(APIException): class TestAdapterException(APIException): - status_code = 500 + status_code = 401 default_detail = "Error while testing adapter." diff --git a/backend/adapter_processor/views.py b/backend/adapter_processor/views.py index 670b5d5611..ab2e354505 100644 --- a/backend/adapter_processor/views.py +++ b/backend/adapter_processor/views.py @@ -105,16 +105,13 @@ def test(self, request: Request) -> Response: status=status.HTTP_200_OK, ) except Exception as e: - if str(e).find("invalid_api_key") != -1: - return Response( - {"message": "Incorrect API key provided."}, - status=status.HTTP_401_UNAUTHORIZED, - ) + logger.error(f"Error testing adapter: {str(e)}") return Response( - {AdapterKeys.IS_VALID: False}, - status=status.HTTP_500_INTERNAL_SERVER_ERROR, + {"message": str(e)}, + status=status.HTTP_401_UNAUTHORIZED, ) + class AdapterInstanceViewSet(ModelViewSet): queryset = AdapterInstance.objects.all() diff --git a/backend/backend/exceptions.py b/backend/backend/exceptions.py index f955976702..cf770a4772 100644 --- a/backend/backend/exceptions.py +++ b/backend/backend/exceptions.py @@ -1,8 +1,11 @@ +import ast from typing import Any, Optional from rest_framework.exceptions import APIException from rest_framework.response import Response from rest_framework.views import exception_handler +from unstract.adapters.exceptions import AdapterError + from unstract.connectors.exceptions import ConnectorBaseException @@ -11,7 +14,7 @@ class UnstractBaseException(APIException): def __init__( self, - detail: Optional[str] = None, + detail: Optional[AdapterError] = None, core_err: Optional[ConnectorBaseException] = None, **kwargs: Any, ) -> None: @@ -19,6 +22,13 @@ def __init__( detail = self.default_detail if core_err and core_err.user_message: detail = core_err.user_message + if detail and detail.message: + message = detail.message + start = message.find("{") + dict_str = message[start:] + error_object = ast.literal_eval(dict_str) + err_message = error_object["error"]["message"] + detail = err_message super().__init__(detail=detail, **kwargs) self._core_err = core_err diff --git a/frontend/src/components/input-output/configure-ds/ConfigureDs.jsx b/frontend/src/components/input-output/configure-ds/ConfigureDs.jsx index 60c2f8cd6d..2552295137 100644 --- a/frontend/src/components/input-output/configure-ds/ConfigureDs.jsx +++ b/frontend/src/components/input-output/configure-ds/ConfigureDs.jsx @@ -128,7 +128,9 @@ function ConfigureDs({ } }) .catch((err) => { - setAlertDetails(handleException(err, "Test connection failed")); + const TestErrorMessage = + err?.response?.data?.message || "Test connection failed"; + setAlertDetails(handleException(err, TestErrorMessage)); }) .finally(() => { setIsTcLoading(false); diff --git a/frontend/src/helpers/GetStaticData.js b/frontend/src/helpers/GetStaticData.js index 996ed44bc7..fb72d9fce0 100644 --- a/frontend/src/helpers/GetStaticData.js +++ b/frontend/src/helpers/GetStaticData.js @@ -258,7 +258,7 @@ const handleException = (err, errMessage) => { } else { return { type: "error", - content: err?.message, + content: errMessage || err?.message, }; } }; diff --git a/tools/translate/src/main.py b/tools/translate/src/main.py index 3e18285b4a..a415d2a83a 100644 --- a/tools/translate/src/main.py +++ b/tools/translate/src/main.py @@ -6,7 +6,7 @@ from constants import EnvKey, GoogleTranslateKey, StaticData from google.auth.transport import requests as google_requests -from google.cloud import translate_v2 as translate # type: ignore +from google.cloud import translate_v2 as translate from google.oauth2.service_account import Credentials from unstract.sdk.cache import ToolCache from unstract.sdk.constants import LogState, MetadataKey, ToolEnv diff --git a/unstract/connectors/src/unstract/connectors/connectorkit.py b/unstract/connectors/src/unstract/connectors/connectorkit.py index aba55e9a2e..e53ad43e86 100644 --- a/unstract/connectors/src/unstract/connectors/connectorkit.py +++ b/unstract/connectors/src/unstract/connectors/connectorkit.py @@ -1,7 +1,7 @@ import logging from typing import Any, Optional -from unstract.connectors import ConnectorDict +from unstract.connectors import ConnectorDict # type: ignore from unstract.connectors.base import UnstractConnector from unstract.connectors.constants import Common from unstract.connectors.databases import connectors as db_connectors diff --git a/unstract/connectors/src/unstract/connectors/databases/__init__.py b/unstract/connectors/src/unstract/connectors/databases/__init__.py index 402e69e66d..fbdc6050e3 100644 --- a/unstract/connectors/src/unstract/connectors/databases/__init__.py +++ b/unstract/connectors/src/unstract/connectors/databases/__init__.py @@ -1,4 +1,4 @@ -from unstract.connectors import ConnectorDict +from unstract.connectors import ConnectorDict # type: ignore from unstract.connectors.databases.register import register_connectors connectors: ConnectorDict = {} diff --git a/unstract/connectors/src/unstract/connectors/filesystems/__init__.py b/unstract/connectors/src/unstract/connectors/filesystems/__init__.py index 9cdfe10835..4826bdb25f 100644 --- a/unstract/connectors/src/unstract/connectors/filesystems/__init__.py +++ b/unstract/connectors/src/unstract/connectors/filesystems/__init__.py @@ -1,4 +1,4 @@ -from unstract.connectors import ConnectorDict +from unstract.connectors import ConnectorDict # type: ignore from unstract.connectors.filesystems.register import register_connectors connectors: ConnectorDict = {} From 60f062b8ed36674e0feaf4cda9c91fdeb9c40f66 Mon Sep 17 00:00:00 2001 From: ali-zipstack Date: Wed, 28 Feb 2024 17:18:49 +0530 Subject: [PATCH 4/8] removed translator, PII redactor and workflow settings --- ...0005_alter_adapterinstance_adapter_type.py | 27 ++ .../workflow_manager/workflow/execution.py | 5 +- .../0002_remove_workflow_settings.py | 16 + .../workflow/models/workflow.py | 1 - backend/workflow_manager/workflow/urls.py | 15 - backend/workflow_manager/workflow/views.py | 36 +- .../ConfigurationModal.css | 0 .../ConfigurationModal.jsx | 25 -- .../agency/configuration/Configuration.css | 10 - .../agency/configuration/Configuration.jsx | 135 -------- .../src/layouts/menu-layout/MenuLayout.jsx | 20 +- .../unstract/tool_registry/public_tools.json | 311 +----------------- .../unstract/tool_registry/tool_registry.py | 9 - .../src/unstract/tool_registry/tool_utils.py | 44 +-- .../src/unstract/workflow_execution/dto.py | 1 - .../workflow_execution/tools_utils.py | 7 +- 16 files changed, 51 insertions(+), 611 deletions(-) create mode 100644 backend/adapter_processor/migrations/0005_alter_adapterinstance_adapter_type.py create mode 100644 backend/workflow_manager/workflow/migrations/0002_remove_workflow_settings.py delete mode 100644 frontend/src/components/agency/configuration-modal/ConfigurationModal.css delete mode 100644 frontend/src/components/agency/configuration-modal/ConfigurationModal.jsx delete mode 100644 frontend/src/components/agency/configuration/Configuration.css delete mode 100644 frontend/src/components/agency/configuration/Configuration.jsx diff --git a/backend/adapter_processor/migrations/0005_alter_adapterinstance_adapter_type.py b/backend/adapter_processor/migrations/0005_alter_adapterinstance_adapter_type.py new file mode 100644 index 0000000000..9d622b190b --- /dev/null +++ b/backend/adapter_processor/migrations/0005_alter_adapterinstance_adapter_type.py @@ -0,0 +1,27 @@ +# Generated by Django 4.2.1 on 2024-02-28 11:25 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("adapter_processor", "0004_alter_adapterinstance_adapter_type"), + ] + + operations = [ + migrations.AlterField( + model_name="adapterinstance", + name="adapter_type", + field=models.CharField( + choices=[ + ("UNKNOWN", "UNKNOWN"), + ("LLM", "LLM"), + ("EMBEDDING", "EMBEDDING"), + ("VECTOR_DB", "VECTOR_DB"), + ("OCR", "OCR"), + ("X2TEXT", "X2TEXT"), + ], + db_comment="Type of adapter LLM/EMBEDDING/VECTOR_DB", + ), + ), + ] diff --git a/backend/workflow_manager/workflow/execution.py b/backend/workflow_manager/workflow/execution.py index 59388d8608..5f2074e9ed 100644 --- a/backend/workflow_manager/workflow/execution.py +++ b/backend/workflow_manager/workflow/execution.py @@ -449,7 +449,4 @@ def convert_tool_instance_model_to_data_class( def convert_workflow_model_to_data_class( workflow: Workflow, ) -> WorkflowDto: - return WorkflowDto( - id=workflow.id, - settings=workflow.settings, - ) + return WorkflowDto(id=workflow.id) diff --git a/backend/workflow_manager/workflow/migrations/0002_remove_workflow_settings.py b/backend/workflow_manager/workflow/migrations/0002_remove_workflow_settings.py new file mode 100644 index 0000000000..b42e3efa1d --- /dev/null +++ b/backend/workflow_manager/workflow/migrations/0002_remove_workflow_settings.py @@ -0,0 +1,16 @@ +# Generated by Django 4.2.1 on 2024-02-28 11:29 + +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ("workflow", "0001_initial"), + ] + + operations = [ + migrations.RemoveField( + model_name="workflow", + name="settings", + ), + ] diff --git a/backend/workflow_manager/workflow/models/workflow.py b/backend/workflow_manager/workflow/models/workflow.py index 5fdfac6780..3da08344b4 100644 --- a/backend/workflow_manager/workflow/models/workflow.py +++ b/backend/workflow_manager/workflow/models/workflow.py @@ -41,7 +41,6 @@ class ExecutionAction(models.TextChoices): max_length=DESCRIPTION_FIELD_LENGTH, default="" ) workflow_name = models.CharField(max_length=WORKFLOW_NAME_SIZE, unique=True) - settings = models.JSONField(null=True, db_comment="Workflow settings") prompt_text = models.TextField(default="") is_active = models.BooleanField(default=False) status = models.CharField(max_length=WORKFLOW_STATUS_LENGTH, default="") diff --git a/backend/workflow_manager/workflow/urls.py b/backend/workflow_manager/workflow/urls.py index 4bcc4b69cb..7aa4c9925f 100644 --- a/backend/workflow_manager/workflow/urls.py +++ b/backend/workflow_manager/workflow/urls.py @@ -27,13 +27,6 @@ {"get": "clear_file_marker"} ) workflow_schema = WorkflowViewSet.as_view({"get": "get_schema"}) -workflow_settings = WorkflowViewSet.as_view( - {"get": "workflow_settings", "put": "workflow_settings"} -) -workflow_settings_schema = WorkflowViewSet.as_view( - {"get": "workflow_settings_schema"} -) - urlpatterns = format_suffix_patterns( [ path("", workflow_list, name="workflow-list"), @@ -64,13 +57,5 @@ workflow_schema, name="workflow-schema", ), - path( - "/settings/", workflow_settings, name="workflow-settings" - ), - path( - "settings/", - workflow_settings_schema, - name="workflow-settings-schema", - ), ] ) diff --git a/backend/workflow_manager/workflow/views.py b/backend/workflow_manager/workflow/views.py index 496c972125..5a1fb8127a 100644 --- a/backend/workflow_manager/workflow/views.py +++ b/backend/workflow_manager/workflow/views.py @@ -1,11 +1,9 @@ import logging from typing import Any, Optional -from backend.constants import RequestKey from connector.connector_instance_helper import ConnectorInstanceHelper from django.conf import settings from django.db.models.query import QuerySet -from django.http import HttpRequest from permissions.permission import IsOwner from pipeline.models import Pipeline from pipeline.pipeline_processor import PipelineProcessor @@ -16,7 +14,6 @@ from rest_framework.versioning import URLPathVersioning from tool_instance.tool_processor import ToolProcessor from unstract.tool_registry.dto import Tool -from unstract.tool_registry.tool_registry import ToolRegistry from utils.filtering import FilterHelper from workflow_manager.endpoint.destination import DestinationConnector from workflow_manager.endpoint.endpoint_utils import WorkflowEndpointUtils @@ -27,7 +24,6 @@ from workflow_manager.workflow.exceptions import ( InvalidRequest, WorkflowDoesNotExistError, - WorkflowExecutionBadRequestException, WorkflowExecutionError, WorkflowGenerationError, WorkflowRegenerationError, @@ -44,6 +40,8 @@ WorkflowSchemaHelper, ) +from backend.constants import RequestKey + logger = logging.getLogger(__name__) @@ -340,33 +338,3 @@ def get_schema( schema_type=schema_type, schema_entity=schema_entity ) return Response(data=json_schema, status=status.HTTP_200_OK) - - @action(detail=True, methods=["GET"]) - def workflow_settings_schema(self, request: HttpRequest) -> Response: - tool_registry = ToolRegistry() - schema = tool_registry.get_project_settings_schema() - return Response(schema) - - @action(detail=True, methods=["GET", "PUT"]) - def workflow_settings(self, request: HttpRequest, pk: str) -> Response: - workflow = self.get_object() - tool_registry = ToolRegistry() - if request.method == "GET": - schema = tool_registry.get_project_settings_schema() - return Response({"schema": schema, "settings": workflow.settings}) - - elif request.method == "PUT": - schema = tool_registry.get_project_settings_schema() - - try: - tool_registry.validate_schema_with_data(request.data, schema) - except Exception as e: - logger.error(f"Invalid input data {str(e)}") - raise WorkflowExecutionBadRequestException("Invalid input") - - workflow.settings = request.data - workflow.save() - return Response( - {"message": "Settings updated successfully"}, - status=status.HTTP_200_OK, - ) diff --git a/frontend/src/components/agency/configuration-modal/ConfigurationModal.css b/frontend/src/components/agency/configuration-modal/ConfigurationModal.css deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/frontend/src/components/agency/configuration-modal/ConfigurationModal.jsx b/frontend/src/components/agency/configuration-modal/ConfigurationModal.jsx deleted file mode 100644 index 3e5597f762..0000000000 --- a/frontend/src/components/agency/configuration-modal/ConfigurationModal.jsx +++ /dev/null @@ -1,25 +0,0 @@ -import { Modal } from "antd"; -import PropTypes from "prop-types"; - -import { Configuration } from "../configuration/Configuration"; - -function ConfigurationModal({ isOpen, setOpen }) { - return ( - setOpen(false)} - footer={false} - closable={true} - maskClosable={false} - > - - - ); -} - -ConfigurationModal.propTypes = { - isOpen: PropTypes.bool.isRequired, - setOpen: PropTypes.func.isRequired, -}; - -export { ConfigurationModal }; diff --git a/frontend/src/components/agency/configuration/Configuration.css b/frontend/src/components/agency/configuration/Configuration.css deleted file mode 100644 index 534b54fb25..0000000000 --- a/frontend/src/components/agency/configuration/Configuration.css +++ /dev/null @@ -1,10 +0,0 @@ -/* Styles for Configuration */ - -.config-head { - padding-bottom: 10px; -} - -.config-head-typo { - font-size: 18px; - font-weight: 600; -} \ No newline at end of file diff --git a/frontend/src/components/agency/configuration/Configuration.jsx b/frontend/src/components/agency/configuration/Configuration.jsx deleted file mode 100644 index e834e46258..0000000000 --- a/frontend/src/components/agency/configuration/Configuration.jsx +++ /dev/null @@ -1,135 +0,0 @@ -import { Button, Space, Typography } from "antd"; -import PropTypes from "prop-types"; -import { createRef, useEffect, useState } from "react"; -import { useParams } from "react-router-dom"; - -import { handleException } from "../../../helpers/GetStaticData"; -import { useAxiosPrivate } from "../../../hooks/useAxiosPrivate"; -import { RjsfFormLayout } from "../../../layouts/rjsf-form-layout/RjsfFormLayout"; -import { useAlertStore } from "../../../store/alert-store"; -import { useSessionStore } from "../../../store/session-store"; -import { useWorkflowStore } from "../../../store/workflow-store"; -import { CustomButton } from "../../widgets/custom-button/CustomButton"; -import "./Configuration.css"; - -function Configuration({ setOpen }) { - const formRef = createRef(null); - const [schema, setSchema] = useState({}); - const [formData, setFormData] = useState({}); - const [isSchemaLoading, setSchemaLoading] = useState(false); - const [isUpdateApiLoading, setUpdateApiLoading] = useState(false); - const { id } = useParams(); - const axiosPrivate = useAxiosPrivate(); - const { sessionDetails } = useSessionStore(); - const { projectName } = useWorkflowStore(); - const { setAlertDetails } = useAlertStore(); - - useEffect(() => { - const requestOptions = { - method: "GET", - url: `/api/v1/unstract/${sessionDetails?.orgId}/workflow/${id}/settings/`, - }; - - setSchemaLoading(true); - axiosPrivate(requestOptions) - .then((res) => { - const data = res?.data; - setSchema(data?.schema || {}); - setFormData(data?.settings || {}); - }) - .catch((err) => { - setAlertDetails(handleException(err, "Failed to load the form")); - }) - .finally(() => { - setSchemaLoading(false); - }); - }, []); - - const isFormValid = () => { - if (formRef) { - formRef?.current?.validateFields((errors, values) => { - if (errors) { - return false; - } - }); - } - return true; - }; - - const validateAndSubmit = (updatedFormData) => { - if (!isFormValid()) { - return; - } - handleSubmit(updatedFormData); - }; - - const handleSubmit = (updatedFormData) => { - setFormData(updatedFormData); - const body = { - workflow_name: projectName, - settings: updatedFormData, - }; - - const requestOptions = { - method: "PUT", - url: `/api/v1/unstract/${sessionDetails?.orgId}/workflow/${id}/`, - headers: { - "X-CSRFToken": sessionDetails?.csrfToken, - "Content-Type": "application/json", - }, - data: body, - }; - - setUpdateApiLoading(true); - axiosPrivate(requestOptions) - .then(() => { - setAlertDetails({ - type: "success", - content: "Saved successfully", - }); - setOpen(false); - }) - .catch((err) => { - setAlertDetails(handleException(err, "Failed to save")); - }) - .finally(() => { - setUpdateApiLoading(false); - }); - }; - - return ( -
-
- - Configuration - -
- -
- - - - Save - - -
-
-
- ); -} - -Configuration.propTypes = { - setOpen: PropTypes.func.isRequired, -}; - -export { Configuration }; diff --git a/frontend/src/layouts/menu-layout/MenuLayout.jsx b/frontend/src/layouts/menu-layout/MenuLayout.jsx index e2f18f45a6..893130fdea 100644 --- a/frontend/src/layouts/menu-layout/MenuLayout.jsx +++ b/frontend/src/layouts/menu-layout/MenuLayout.jsx @@ -2,23 +2,17 @@ import { useEffect, useState, useRef } from "react"; import { useLocation, useNavigate } from "react-router-dom"; import PropTypes from "prop-types"; import { Button, Space, Typography } from "antd"; -import { - ArrowLeftOutlined, - ToolOutlined, - QuestionCircleOutlined, -} from "@ant-design/icons"; +import { ArrowLeftOutlined, QuestionCircleOutlined } from "@ant-design/icons"; import "./MenuLayout.css"; import { useSessionStore } from "../../store/session-store"; import { useWorkflowStore } from "../../store/workflow-store"; -import { ConfigurationModal } from "../../components/agency/configuration-modal/ConfigurationModal"; function MenuLayout({ children }) { const navigate = useNavigate(); const location = useLocation(); const currentMenu = useRef(); const [activeTab, setActiveTab] = useState(""); - const [openConfigModal, setOpenConfigModal] = useState(false); const { sessionDetails } = useSessionStore(); const { projectName } = useWorkflowStore(); @@ -51,14 +45,6 @@ function MenuLayout({ children }) {
-