Merge branch 'main' into fix/minor-bugs

This commit is contained in:
Siddhant Rai
2025-02-19 14:16:56 +05:30
committed by GitHub
21 changed files with 427 additions and 333 deletions

View File

@@ -1,7 +1,7 @@
import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
import Exit from '../assets/exit.svg';
import WrapperModal from './WrapperModal';
import Input from '../components/Input';
import { ActiveState } from '../models/misc';
@@ -35,23 +35,53 @@ export default function AddActionModal({
setActionName('');
setModalState('INACTIVE');
};
if (modalState !== 'ACTIVE') return null;
return (
<div
className={`${
modalState === 'ACTIVE' ? 'visible' : 'hidden'
} fixed top-0 left-0 z-30 h-screen w-screen bg-gray-alpha flex items-center justify-center`}
<WrapperModal
close={() => setModalState('INACTIVE')}
className="sm:w-[512px]"
>
<article className="flex w-11/12 sm:w-[512px] flex-col gap-4 rounded-2xl bg-white shadow-lg dark:bg-[#26272E]">
<div className="relative">
<div>
<h2 className="font-semibold text-xl text-jet dark:text-bright-gray px-3">
New Action
</h2>
<div className="mt-6 px-3">
<Input
type="text"
value={actionName}
onChange={(e) => setActionName(e.target.value)}
borderVariant="thin"
placeholder="Enter name"
label="Action Name"
/>
<p className="mt-1 text-gray-500 text-xs">
Use only letters, numbers, underscores, and hyphens (e.g.,
`get_user_data`, `send-report`).
</p>
{functionNameError && (
<p className="mt-1 text-red-500 text-xs">
Invalid function name format. Use only letters, numbers,
underscores, and hyphens.
</p>
)}
</div>
<div className="mt-8 flex flex-row-reverse gap-1 px-3">
<button
onClick={handleAddAction}
className="rounded-3xl bg-purple-30 px-5 py-2 text-sm text-white transition-all hover:bg-[#6F3FD1]"
>
Add
</button>
<button
className="absolute top-3 right-4 m-2 w-3"
onClick={() => {
setFunctionNameError(false);
setModalState('INACTIVE');
setActionName('');
}}
className="cursor-pointer rounded-3xl px-5 py-2 text-sm font-medium hover:bg-gray-100 dark:bg-transparent dark:text-light-gray dark:hover:bg-[#767183]/50"
>
<img className="filter dark:invert" src={Exit} />
{t('modals.configTool.closeButton')}
</button>
<div className="p-6">
<h2 className="font-semibold text-xl text-jet dark:text-bright-gray px-3">
@@ -102,7 +132,7 @@ export default function AddActionModal({
</div>
</div>
</div>
</article>
</div>
</div>
</WrapperModal>
);
}

View File

@@ -2,12 +2,12 @@ import React, { useRef } from 'react';
import { useTranslation } from 'react-i18next';
import userService from '../api/services/userService';
import Exit from '../assets/exit.svg';
import { useOutsideAlerter } from '../hooks';
import { ActiveState } from '../models/misc';
import ConfigToolModal from './ConfigToolModal';
import { AvailableToolType } from './types';
import Spinner from '../components/Spinner';
import WrapperComponent from './WrapperModal';
export default function AddToolModal({
message,
@@ -91,28 +91,12 @@ export default function AddToolModal({
}, [modalState]);
return (
<>
<div
className={`${
modalState === 'ACTIVE' ? 'visible' : 'hidden'
} fixed top-0 left-0 z-30 h-screen w-screen bg-gray-alpha flex items-center justify-center`}
>
<article
ref={modalRef}
className="flex h-[85vh] w-[90vw] md:w-[75vw] flex-col gap-4 rounded-2xl bg-[#FBFBFB] shadow-lg dark:bg-[#26272E]"
{modalState === 'ACTIVE' && (
<WrapperComponent
close={() => setModalState('INACTIVE')}
className="h-[85vh] w-[90vw] md:w-[75vw]"
>
<div className="relative">
<button
className="absolute top-3 right-4 m-2 w-3"
onClick={() => {
setModalState('INACTIVE');
}}
>
<img
className="filter dark:invert"
src={Exit}
alt={t('cancel')}
/>
</button>
<div className="flex flex-col gap-4 h-full">
<div className="p-6">
<h2 className="font-semibold text-xl text-jet dark:text-bright-gray px-3">
{t('settings.tools.selectToolSetup')}
@@ -165,8 +149,8 @@ export default function AddToolModal({
</div>
</div>
</div>
</article>
</div>
</WrapperComponent>
)}
<ConfigToolModal
modalState={configModalState}
setModalState={setConfigModalState}

View File

@@ -1,23 +1,25 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import Exit from '../assets/exit.svg';
import WrapperModal from './WrapperModal';
import Input from '../components/Input';
import { ActiveState } from '../models/misc';
import { AvailableToolType } from './types';
import userService from '../api/services/userService';
interface ConfigToolModalProps {
modalState: ActiveState;
setModalState: (state: ActiveState) => void;
tool: AvailableToolType | null;
getUserTools: () => void;
}
export default function ConfigToolModal({
modalState,
setModalState,
tool,
getUserTools,
}: {
modalState: ActiveState;
setModalState: (state: ActiveState) => void;
tool: AvailableToolType | null;
getUserTools: () => void;
}) {
}: ConfigToolModalProps) {
const { t } = useTranslation();
const [authKey, setAuthKey] = React.useState<string>('');
@@ -36,21 +38,44 @@ export default function ConfigToolModal({
getUserTools();
});
};
// Only render when modal is active
if (modalState !== 'ACTIVE') return null;
return (
<div
className={`${
modalState === 'ACTIVE' ? 'visible' : 'hidden'
} fixed top-0 left-0 z-30 h-screen w-screen bg-gray-alpha flex items-center justify-center`}
>
<article className="flex w-11/12 sm:w-[512px] flex-col gap-4 rounded-2xl bg-white shadow-lg dark:bg-[#26272E]">
<div className="relative">
<WrapperModal close={() => setModalState('INACTIVE')}>
<div>
<h2 className="font-semibold text-xl text-jet dark:text-bright-gray px-3">
{t('modals.configTool.title')}
</h2>
<p className="mt-5 text-sm text-gray-600 dark:text-gray-400 px-3">
{t('modals.configTool.type')}:{' '}
<span className="font-semibold">{tool?.name}</span>
</p>
<div className="mt-6 px-3">
<Input
type="text"
value={authKey}
onChange={(e) => setAuthKey(e.target.value)}
borderVariant="thin"
placeholder={t('modals.configTool.apiKeyPlaceholder')}
label={t('modals.configTool.apiKeyLabel')}
/>
</div>
<div className="mt-8 flex flex-row-reverse gap-1 px-3">
<button
className="absolute top-3 right-4 m-2 w-3"
onClick={() => {
setModalState('INACTIVE');
tool && handleAddTool(tool);
}}
className="rounded-3xl bg-purple-30 px-5 py-2 text-sm text-white transition-all hover:bg-[#6F3FD1]"
>
<img className="filter dark:invert" src={Exit} />
{t('modals.configTool.addButton')}
</button>
<button
onClick={() => setModalState('INACTIVE')}
className="cursor-pointer rounded-3xl px-5 py-2 text-sm font-medium hover:bg-gray-100 dark:bg-transparent dark:text-light-gray dark:hover:bg-[#767183]/50"
>
{t('modals.configTool.closeButton')}
</button>
<div className="p-6">
<h2 className="font-semibold text-xl text-jet dark:text-bright-gray px-3">
@@ -92,7 +117,7 @@ export default function ConfigToolModal({
</div>
</div>
</div>
</article>
</div>
</div>
</WrapperModal>
);
}

View File

@@ -73,21 +73,20 @@ export default function CreateAPIKeyModal({
handleFetchPrompts();
}, []);
return (
<WrapperModal close={close}>
<WrapperModal close={close} className="p-4">
<div className="mb-6">
<span className="text-xl text-jet dark:text-bright-gray">
{t('modals.createAPIKey.label')}
</span>
</div>
<div className="relative mt-5 mb-4">
<span className="absolute left-2 -top-2 bg-white px-2 text-xs text-gray-4000 dark:bg-outer-space dark:text-silver">
{t('modals.createAPIKey.apiKeyName')}
</span>
<Input
type="text"
className="rounded-md"
value={APIKeyName}
label={t('modals.createAPIKey.apiKeyName')}
onChange={(e) => setAPIKeyName(e.target.value)}
borderVariant="thin"
></Input>
</div>
<div className="my-4">

View File

@@ -1,8 +1,8 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import Exit from '../assets/exit.svg';
import { SaveAPIKeyModalProps } from '../models/misc';
import WrapperModal from './WrapperModal';
export default function SaveAPIKeyModal({
apiKey,
@@ -15,38 +15,37 @@ export default function SaveAPIKeyModal({
navigator.clipboard.writeText(apiKey);
setIsCopied(true);
};
return (
<div className="fixed top-0 left-0 z-30 flex h-screen w-screen items-center justify-center bg-gray-alpha bg-opacity-50">
<div className="relative w-11/12 rounded-3xl bg-white px-6 py-8 dark:bg-outer-space dark:text-bright-gray sm:w-[512px]">
<button className="absolute top-3 right-4 m-2 w-3" onClick={close}>
<img className="filter dark:invert" src={Exit} />
</button>
<h1 className="my-0 text-xl font-medium">
{' '}
{t('modals.saveKey.note')}
</h1>
<h3 className="text-sm font-normal text-outer-space">
{t('modals.saveKey.disclaimer')}
</h3>
<div className="flex justify-between py-2">
<div>
<h2 className="text-base font-semibold">API Key</h2>
<span className="text-sm font-normal leading-7 ">{apiKey}</span>
</div>
<button
className="my-1 h-10 w-20 rounded-full border border-solid border-purple-30 p-2 text-sm text-purple-30 hover:bg-purple-30 hover:text-white"
onClick={handleCopyKey}
>
{isCopied ? t('modals.saveKey.copied') : t('modals.saveKey.copy')}
</button>
<WrapperModal close={close}>
<h1 className="my-0 text-xl font-medium text-jet dark:text-bright-gray">
{t('modals.saveKey.note')}
</h1>
<h3 className="text-sm font-normal text-outer-space dark:text-silver">
{t('modals.saveKey.disclaimer')}
</h3>
<div className="flex justify-between py-2">
<div>
<h2 className="text-base font-semibold text-jet dark:text-bright-gray">
API Key
</h2>
<span className="text-sm font-normal leading-7 text-jet dark:text-bright-gray">
{apiKey}
</span>
</div>
<button
onClick={close}
className="rounded-full bg-philippine-yellow px-4 py-3 font-medium text-black hover:bg-[#E6B91A]"
className="my-1 h-10 w-20 rounded-full border border-solid border-purple-30 p-2 text-sm text-purple-30 hover:bg-purple-30 hover:text-white"
onClick={handleCopyKey}
>
{t('modals.saveKey.confirm')}
{isCopied ? t('modals.saveKey.copied') : t('modals.saveKey.copy')}
</button>
</div>
</div>
<button
onClick={close}
className="rounded-full bg-philippine-yellow px-4 py-3 font-medium text-black hover:bg-[#E6B91A]"
>
{t('modals.saveKey.confirm')}
</button>
</WrapperModal>
);
}

View File

@@ -1,12 +1,21 @@
import React, { useEffect, useRef } from 'react';
import Exit from '../assets/exit.svg';
import { WrapperModalPropsType } from './types';
interface WrapperModalPropsType {
children: React.ReactNode;
close: () => void;
isPerformingTask?: boolean;
className?: string;
contentClassName?: string;
}
export default function WrapperModal({
children,
close,
isPerformingTask,
isPerformingTask = false,
className = '', // Default width, but can be overridden
contentClassName = '', // Default padding, but can be overridden
}: WrapperModalPropsType) {
const modalRef = useRef<HTMLDivElement>(null);
@@ -40,17 +49,17 @@ export default function WrapperModal({
<div className="fixed top-0 left-0 z-30 flex h-screen w-screen items-center justify-center bg-gray-alpha bg-opacity-50">
<div
ref={modalRef}
className="relative w-11/12 rounded-2xl bg-white dark:bg-outer-space sm:w-[512px] p-8"
className={`relative w-11/12 sm:w-[512px] p-8 rounded-2xl bg-white dark:bg-[#26272E] ${className}`}
>
{!isPerformingTask && (
<button
className="absolute top-3 right-4 m-2 w-3 z-50"
onClick={close}
>
<img className="filter dark:invert" src={Exit} />
<img className="filter dark:invert" src={Exit} alt="Close" />
</button>
)}
{children}
<div className={`${contentClassName}`}>{children}</div>
</div>
</div>
);

View File

@@ -1,50 +0,0 @@
import * as React from 'react';
import { useTranslation } from 'react-i18next';
interface ModalProps {
handleSubmit: () => void;
isCancellable: boolean;
handleCancel?: () => void;
render: () => JSX.Element;
modalState: string;
isError: boolean;
errorMessage?: string;
textDelete?: boolean;
}
const Modal = (props: ModalProps) => {
const { t } = useTranslation();
return (
<div
className={`${
props.modalState === 'ACTIVE' ? 'visible' : 'hidden'
} absolute z-30 h-screen w-screen bg-gray-alpha`}
>
{props.render()}
<div className=" mx-auto flex w-[90vw] max-w-lg flex-row-reverse rounded-b-lg bg-white pb-5 pr-5 shadow-lg dark:bg-outer-space">
<div>
<button
onClick={() => props.handleSubmit()}
className="ml-auto h-10 w-20 rounded-3xl bg-violet-800 text-white transition-all hover:bg-violet-700 dark:text-silver"
>
{props.textDelete ? 'Delete' : 'Save'}
</button>
{props.isCancellable && (
<button
onClick={() => props.handleCancel && props.handleCancel()}
className="cursor-pointer rounded-3xl px-5 py-2 text-sm font-medium hover:bg-gray-100 dark:bg-transparent dark:text-light-gray dark:hover:bg-[#767183]/50"
>
{t('cancel')}
</button>
)}
</div>
{props.isError && (
<p className="mx-auto mt-2 mr-auto text-sm text-red-500">
{props.errorMessage}
</p>
)}
</div>
</div>
);
};
export default Modal;