diff --git a/GUI/src/components/ServiceConfigurationForm/index.tsx b/GUI/src/components/ServiceConfigurationForm/index.tsx
new file mode 100644
index 000000000..11353b0ba
--- /dev/null
+++ b/GUI/src/components/ServiceConfigurationForm/index.tsx
@@ -0,0 +1,112 @@
+import { Card, FormInput, Switch, Track } from 'components';
+import { FC, useRef } from 'react';
+import { useTranslation } from 'react-i18next';
+
+import useServiceStore from '../../store/new-services.store';
+import DynamicList from '../DynamicList';
+import { InfoTooltip } from '../InfoTooltip';
+
+type SettingsModalProps = {
+ id?: string;
+};
+
+const SettingsModal: FC
= () => {
+ const { t } = useTranslation();
+
+ const name = useServiceStore((state) => state.serviceNameDashed());
+ const description = useServiceStore((state) => state.description);
+ const isCommon = useServiceStore((state) => state.isCommon);
+ const examples = useServiceStore((state) => state.examples);
+ const entities = useServiceStore((state) => state.entities);
+
+ const { setHasUnsavedChanges } = useServiceStore();
+ const titleRef = useRef(null);
+ const descriptionRef = useRef(null);
+
+ return (
+ <>
+
+
+
+
+
+
+
+ {
+ setHasUnsavedChanges(true);
+ useServiceStore.getState().setIsCommon(e);
+ }}
+ />
+
+
+ >
+ );
+};
+
+export default SettingsModal;
diff --git a/GUI/src/components/ServicesTable/columns.tsx b/GUI/src/components/ServicesTable/columns.tsx
index e73ae0030..b2e7abdd1 100644
--- a/GUI/src/components/ServicesTable/columns.tsx
+++ b/GUI/src/components/ServicesTable/columns.tsx
@@ -3,32 +3,26 @@ import { createColumnHelper } from '@tanstack/react-table';
import Label from 'components/Label';
import Tooltip from 'components/Tooltip';
import i18n from 'i18n';
+import { AiOutlineExport } from 'react-icons/ai';
+import { AiOutlineInfoCircle } from 'react-icons/ai';
import { IoCopyOutline } from 'react-icons/io5';
-import { MdDeleteOutline, MdOutlineArrowForward, MdOutlineDescription, MdOutlineEdit } from 'react-icons/md';
+import { MdDeleteOutline, MdOutlineDescription, MdOutlineEdit } from 'react-icons/md';
import { NavigateFunction } from 'react-router-dom';
import { ROUTES } from 'resources/routes-constants';
import useServiceListStore from 'store/services.store';
import useStore from 'store/store';
import useToastStore from 'store/toasts.store';
import { Service, ServiceState } from 'types';
+import { exportServices } from 'utils/service-export';
interface GetColumnsConfig {
isCommon: boolean;
navigate: NavigateFunction;
- checkIntentConnection: () => void;
hideDeletePopup: () => void;
showReadyPopup: () => void;
- showIntentConnectionModal: () => void;
}
-export const getColumns = ({
- isCommon,
- navigate,
- checkIntentConnection,
- hideDeletePopup,
- showReadyPopup,
- showIntentConnectionModal,
-}: GetColumnsConfig) => {
+export const getColumns = ({ isCommon, navigate, hideDeletePopup, showReadyPopup }: GetColumnsConfig) => {
const columnHelper = createColumnHelper();
const userInfo = useStore.getState().userInfo;
@@ -79,44 +73,63 @@ export const getColumns = ({
),
}),
- columnHelper.accessor('linkedIntent', {
- header: i18n.t('overview.service.linkedIntent') ?? '',
+ columnHelper.accessor('description', {
+ header: i18n.t('overview.service.description') ?? '',
meta: {
size: 200,
},
- cell: (props) => (
-
- {props.cell.getValue() ? (
-
- ) : (
-
- )}
-
- ),
+
+ {isLong && (
+ }
+ size="medium"
+ />
+ )}
+
+
+
+ );
+ },
}),
columnHelper.accessor('state', {
header: i18n.t('overview.service.state') ?? '',
@@ -129,8 +142,7 @@ export const getColumns = ({
onClick={() => {
useServiceListStore.getState().setSelectedService(props.row.original);
const state = props.row.original.state;
- if (state === ServiceState.Ready && props.row.original.linkedIntent != '') {
- checkIntentConnection();
+ if (state === ServiceState.Ready) {
showReadyPopup();
}
}}
@@ -161,6 +173,25 @@ export const getColumns = ({
),
}),
+ columnHelper.display({
+ id: 'export',
+ meta: {
+ size: 90,
+ },
+ cell: (props) => (
+
+ {
+ await exportServices([props.row.original]);
+ }}
+ >
+ } size="medium" />
+ {i18n.t('overview.export')}
+
+
+ ),
+ }),
columnHelper.display({
id: 'delete',
meta: {
diff --git a/GUI/src/components/ServicesTable/index.tsx b/GUI/src/components/ServicesTable/index.tsx
index 012707cd8..2daff8cf4 100644
--- a/GUI/src/components/ServicesTable/index.tsx
+++ b/GUI/src/components/ServicesTable/index.tsx
@@ -1,10 +1,8 @@
import { PaginationState, SortingState } from '@tanstack/react-table';
-import ConnectServiceToIntentModel from 'pages/Integration/ConnectServiceToIntentModel';
import { FC, useCallback, useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
import useServiceListStore from 'store/services.store';
-import { Trigger } from 'types/Trigger';
import { Button, Card, Modal, Track } from '..';
import DataTable from '../DataTable';
@@ -20,19 +18,13 @@ type ServicesTableProps = {
const ServicesTable: FC = ({ isCommon = false }) => {
const { t } = useTranslation();
const [isDeletePopupVisible, setIsDeletePopupVisible] = useState(false);
- const [isReadyPopupVisible, setIsReadyPopupVisible] = useState(false);
- const [isIntentConnectionPopupVisible, setIsIntentConnectionPopupVisible] = useState(false);
- const [readyPopupText, setReadyPopupText] = useState('');
- const [isReadyStatusChecking, setIsReadyStatusChecking] = useState(false);
const services = useServiceListStore((state) => (isCommon ? state.commonServices : state.notCommonServices));
const navigate = useNavigate();
- const [selectedConnectionTrigger, setSelectedConnectionTrigger] = useState();
const [pagination, setPagination] = useState({
pageIndex: 0,
pageSize: 10,
});
const [sorting, setSorting] = useState([{ id: 'name', desc: false }]);
- const [isActivating, setIsActivating] = useState(false);
const loadServices = (paginationState: PaginationState, sortingState: SortingState) => {
void useServiceListStore.getState().loadServicesList(paginationState, sortingState);
@@ -57,9 +49,7 @@ const ServicesTable: FC = ({ isCommon = false }) => {
useServiceListStore
.getState()
.changeServiceState(
- () => {
- setIsReadyPopupVisible(false);
- },
+ () => {},
t('overview.service.toast.updated'),
t('overview.service.toast.failed.state'),
activate,
@@ -67,49 +57,24 @@ const ServicesTable: FC = ({ isCommon = false }) => {
pagination,
sorting,
)
- .then(() => {
- setIsActivating(false);
- })
- .catch(() => {
- setIsActivating(false);
+ .then(() => {})
+ .catch((e) => {
+ console.error(e);
});
},
[t, pagination, sorting],
);
const columns = useMemo(() => {
- const checkIntentConnection = () => {
- void useServiceListStore.getState().checkServiceIntentConnection(
- (response) => {
- setSelectedConnectionTrigger(response);
- setIsReadyStatusChecking(false);
- if (response.status === 'pending') {
- setReadyPopupText(t('overview.popup.connectionPending').toString());
- } else {
- setReadyPopupText(t('overview.popup.setActive').toString());
- }
- },
- () => {
- setIsReadyStatusChecking(false);
- setReadyPopupText(t('overview.popup.intentNotConnected').toString());
- },
- );
- };
-
return getColumns({
isCommon,
navigate,
- checkIntentConnection,
hideDeletePopup: () => setIsDeletePopupVisible(true),
showReadyPopup: () => {
- setIsReadyStatusChecking(true);
- setIsReadyPopupVisible(true);
- },
- showIntentConnectionModal: () => {
- setIsIntentConnectionPopupVisible(true);
+ changeServiceState(true);
},
});
- }, [isCommon, navigate, t]);
+ }, [isCommon, changeServiceState, navigate]);
const deleteSelectedService = () => {
setIsDeletingService(true);
@@ -134,48 +99,6 @@ const ServicesTable: FC = ({ isCommon = false }) => {
});
};
- const cancelConnectionRequest = () => {
- if (selectedConnectionTrigger) {
- void useServiceListStore
- .getState()
- .cancelConnectionRequest(
- () => setIsReadyPopupVisible(false),
- t('overview.service.toast.cancelledConnection'),
- t('overview.service.toast.failed.cancelledConnection'),
- selectedConnectionTrigger,
- );
- }
- };
-
- const getActiveAndConnectionButton = () => {
- if (readyPopupText === t('overview.popup.setActive')) {
- return (
- {
- setIsActivating(true);
- changeServiceState(true);
- }}
- >
- {t('overview.popup.activateService')}
-
- );
- }
- if (readyPopupText === t('overview.popup.connectionPending')) {
- return {t('overview.popup.cancelRequest')};
- }
- return (
- {
- setIsReadyPopupVisible(false);
- setIsIntentConnectionPopupVisible(true);
- }}
- >
- {t('overview.popup.connectToIntent')}
-
- );
- };
-
return (
{isDeletePopupVisible && (
@@ -190,34 +113,6 @@ const ServicesTable: FC = ({ isCommon = false }) => {
)}
- {isReadyPopupVisible && (
- setIsReadyPopupVisible(false)}>
- {isReadyStatusChecking ? (
-
-
-
-
- ) : (
-
- setIsReadyPopupVisible(false)}>
- {t('overview.cancel')}
-
- {readyPopupText != t('overview.popup.connectionPending').toString() &&
- readyPopupText != t('overview.popup.setActive').toString() &&
- readyPopupText != t('overview.popup.intentNotConnected').toString() && (
- changeServiceState()}>{t('overview.popup.setToDraft')}
- )}
- {getActiveAndConnectionButton()}
-
- )}
-
- )}
- {isIntentConnectionPopupVisible && (
- setIsIntentConnectionPopupVisible(false)}
- onConnect={() => setIsIntentConnectionPopupVisible(false)}
- />
- )}
{
- const { t } = useTranslation();
-
- const renderConent = useCallback(() => {
+ const renderContent = useCallback(() => {
if (message.message.startsWith('')) return message.message.replace('
', '').replace('
', '');
- return t(message.message);
- }, [message.message, t]);
+ return ;
+ }, [message.message]);
+
+ const hasButtons = useMemo(() => {
+ return parseButtons(message).length > 0;
+ }, [message]);
return (
@@ -32,7 +37,10 @@ const BotMessage = ({ message }: ChatMessageProps) => {
- {renderConent()}
+
+ {message.message && {renderContent()}
}
+ {hasButtons && }
+
diff --git a/GUI/src/components/chat/chat-button-group.tsx b/GUI/src/components/chat/chat-button-group.tsx
new file mode 100644
index 000000000..b1e94acf8
--- /dev/null
+++ b/GUI/src/components/chat/chat-button-group.tsx
@@ -0,0 +1,35 @@
+import React, { useMemo } from 'react';
+import useTestServiceStore, { TestingMessage } from 'store/test-services.store';
+import { parseButtons, parseServiceString } from 'utils/chat-utils';
+import { generateUniqueId } from 'utils/flow-utils';
+
+import styles from './chat.module.scss';
+
+const ChatButtonGroup = ({ message }: { message: TestingMessage }): React.JSX.Element => {
+ const parsedButtons = useMemo(() => {
+ return parseButtons(message);
+ }, [message]);
+
+ return (
+
+ {parsedButtons?.map(({ title, payload }) => {
+ const { serviceName, serviceInputs } = parseServiceString(payload);
+
+ return (
+ {
+ useTestServiceStore.getState().sendUserInput(serviceInputs, serviceName);
+ }}
+ >
+ {title}
+
+ );
+ })}
+
+ );
+};
+
+export default ChatButtonGroup;
diff --git a/GUI/src/components/chat/chat.module.scss b/GUI/src/components/chat/chat.module.scss
index e83d49031..6de0ece85 100644
--- a/GUI/src/components/chat/chat.module.scss
+++ b/GUI/src/components/chat/chat.module.scss
@@ -5,8 +5,8 @@
z-index: 99;
position: fixed;
margin: 1em;
- right: 250px;
- bottom: 30px;
+ right: 0;
+ bottom: 95px;
width: 650px;
height: 500px;
}
@@ -150,6 +150,33 @@
}
}
+.actionButton {
+ cursor: pointer;
+ font-size: 1em;
+ margin: 0.7rem 0.3rem 0.3rem 0.3rem;
+ padding: 0.3rem 1.5rem;
+ background-color: get-color(sapphire-blue-10);
+ color: white;
+ border: none;
+ border-radius: 4px;
+ box-shadow: 2px 1px 4px grey;
+
+ &:hover {
+ filter: brightness(0.95);
+ }
+
+ &:active:not(:disabled) {
+ filter: brightness(0.75);
+ box-shadow: none;
+ }
+
+ &:disabled {
+ opacity: 0.5;
+ box-shadow: none;
+ cursor: default;
+ }
+}
+
.keypadContainer {
margin: 1em;
}
@@ -284,8 +311,8 @@
.profile {
position: fixed;
- bottom: 0px;
- right: 250px;
+ bottom: 95px;
+ right: 0;
display: flex;
align-items: center;
diff --git a/GUI/src/components/chat/user-message.tsx b/GUI/src/components/chat/user-message.tsx
index 0ac17197c..81bdfa339 100644
--- a/GUI/src/components/chat/user-message.tsx
+++ b/GUI/src/components/chat/user-message.tsx
@@ -1,4 +1,5 @@
import classNames from 'classnames';
+import Markdownify from 'components/Markdowify';
import { motion } from 'framer-motion';
import { TestingMessage } from 'store/test-services.store';
@@ -27,7 +28,7 @@ const UserMessage = ({ message }: ChatMessageProps) =>