Skip to content

Commit

Permalink
Merge branch 'development' of github.com:epam/ai-dial-chat into feat/…
Browse files Browse the repository at this point in the history
…chat-monorepo
  • Loading branch information
mikitabut committed Jan 26, 2024
2 parents 1c29066 + 6f5aadd commit dcb0f1a
Show file tree
Hide file tree
Showing 72 changed files with 2,839 additions and 1,013 deletions.
2 changes: 1 addition & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ dist

.github
helm
__tests__
__tests__
65 changes: 33 additions & 32 deletions README.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions apps/ai-dial-chat-e2e/src/tests/entityIcon.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ test(
apiHelper,
setTestIds,
}) => {
test.slow();
setTestIds('EPMRTC-1036', 'EPMRTC-1038', 'EPMRTC-378');
await test.step('Open initial screen and click "See full list" to view all available entities', async () => {
await dialHomePage.openHomePage();
Expand Down
4 changes: 3 additions & 1 deletion apps/ai-dial-chat-e2e/src/ui/webElements/baseElement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,9 @@ export class BaseElement {
.replaceAll(/><\/path>/g, Tags.closingTag)
.replaceAll(/><\/rect>/g, Tags.closingTag)
.replaceAll(/><\/polygon>/g, Tags.closingTag)
.replaceAll(/><\/circle>/g, Tags.closingTag),
.replaceAll(/><\/circle>/g, Tags.closingTag)
.replaceAll(/><\/use>/g, Tags.closingTag)
.replaceAll(/><\/image>/g, Tags.closingTag),
);
}
}
3 changes: 2 additions & 1 deletion apps/ai-dial-chat/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ COPY --from=build /app/public ./public
COPY --from=build /app/package*.json ./
COPY --from=build /app/next.config.js ./next.config.js
COPY --from=build /app/next-i18next.config.js ./next-i18next.config.js
COPY --from=build /app/startup.sh ./startup.sh

ENV NODE_ENV production
ENV NEXT_TELEMETRY_DISABLED 1
Expand All @@ -37,4 +38,4 @@ USER nextjs
EXPOSE 3000 9464

# Start the application
CMD ["npm", "start"]
CMD ["/app/startup.sh"]
2 changes: 1 addition & 1 deletion apps/ai-dial-chat/src/components/Chat/Addons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const Addon = ({
<ModelIcon entity={addonsMap[addonId]} entityId={addonId} size={15} />
<span>{addonsMap[addonId]?.name || addonId}</span>
{isSelected && !preselectedAddonsIds.includes(addonId) && (
<IconX height={12} width={12} className="text-secondary" />
<IconX size={14} className="text-secondary" />
)}
</button>
);
Expand Down
188 changes: 91 additions & 97 deletions apps/ai-dial-chat/src/components/Chat/AddonsDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,7 @@ const SelectedAddon = ({
<ModelIcon entity={addon} entityId={addon.id} size={15} />
<span>{addon.name}</span>
{!isPreselected && (
<IconX
height={12}
width={12}
className="text-secondary hover:text-accent-primary"
/>
<IconX size={14} className="text-secondary hover:text-accent-primary" />
)}
</button>
);
Expand Down Expand Up @@ -195,118 +191,116 @@ export const AddonsDialog: FC<Props> = ({
<FloatingPortal id="chat">
<div className="fixed inset-0 top-[48px] z-30 flex items-center justify-center bg-blackout p-3 md:p-5">
<div
className="m-auto flex size-full grow flex-col gap-4 overflow-y-auto rounded bg-layer-3 py-4 text-left md:grow-0 xl:max-w-[720px] 2xl:max-w-[780px]"
className="m-auto flex size-full grow flex-col gap-4 divide-tertiary overflow-y-auto rounded bg-layer-3 py-4 text-left md:grow-0 xl:max-w-[720px] 2xl:max-w-[780px]"
role="dialog"
ref={refs.setFloating}
{...getFloatingProps()}
data-qa="addons-dialog"
>
<div className="flex justify-between px-3 md:px-5">
{t('Addons (max 10)')}
<button
onClick={() => {
onClose();
}}
className="text-secondary hover:text-accent-primary"
data-qa="close-addons-dialog"
>
<IconX height={24} width={24} />
</button>
</div>
<div className="flex grow flex-col justify-between gap-4">
<div className="flex justify-between px-3 md:px-5">
{t('Addons (max 10)')}
<button
onClick={onClose}
className="text-secondary hover:text-accent-primary"
data-qa="close-addons-dialog"
>
<IconX height={24} width={24} />
</button>
</div>

<div className="px-3 md:px-5">
<input
name="titleInput"
placeholder={t('Search for addons') || ''}
type="text"
onChange={(e) => {
handleSearch(e.target.value);
}}
className="m-0 w-full rounded border border-primary bg-transparent px-3 py-2 outline-none placeholder:text-secondary focus-visible:border-accent-primary"
></input>
</div>
<div
className="flex flex-col gap-4 px-3 text-xs md:px-5"
data-qa="addon-search-results"
>
{(selectedAddons?.filter((addon) => addonsMap[addon.id]).length >
0 ||
preselectedAddonsIds?.length > 0) && (
<div className="flex flex-col gap-3">
<span className="text-secondary">{t('Selected')}</span>
<div className="px-3 md:px-5">
<input
name="titleInput"
placeholder={t('Search for addons') || ''}
type="text"
onChange={(e) => {
handleSearch(e.target.value);
}}
className="m-0 w-full rounded border border-primary bg-transparent px-3 py-2 outline-none placeholder:text-secondary focus-visible:border-accent-primary"
></input>
</div>
<div
className="flex grow flex-col gap-4 px-3 text-xs md:px-5"
data-qa="addon-search-results"
>
{(selectedAddons?.filter((addon) => addonsMap[addon.id]).length >
0 ||
preselectedAddonsIds?.length > 0) && (
<div className="flex flex-col gap-3">
<span className="text-secondary">{t('Selected')}</span>

<div className="flex flex-wrap gap-1">
{preselectedAddonsIds.map((addonID) => {
const addon = addonsMap[addonID];
if (
!addon ||
selectedAddons.map((addon) => addon.id).includes(addonID)
) {
return null;
}
<div className="flex flex-wrap gap-1">
{preselectedAddonsIds.map((addonID) => {
const addon = addonsMap[addonID];
if (
!addon ||
selectedAddons
.map((addon) => addon.id)
.includes(addonID)
) {
return null;
}

return (
return (
<SelectedAddon
key={addon.id}
addon={addon}
preselectedAddonsIds={preselectedAddonsIds}
selectedAddons={selectedAddons}
onSelectAddons={handleSelectAddon}
/>
);
})}
{selectedAddons.map((addon) => (
<SelectedAddon
key={addon.id}
addon={addon}
preselectedAddonsIds={preselectedAddonsIds}
selectedAddons={selectedAddons}
onSelectAddons={handleSelectAddon}
/>
);
})}
{selectedAddons.map((addon) => (
<SelectedAddon
key={addon.id}
addon={addon}
preselectedAddonsIds={preselectedAddonsIds}
selectedAddons={selectedAddons}
onSelectAddons={handleSelectAddon}
/>
))}
))}
</div>
</div>
</div>
)}
{displayedAddons?.length > 0 ? (
<div className="flex shrink grow flex-col gap-3 overflow-auto">
<span className="text-secondary">{t('Search results')}</span>
)}
{displayedAddons?.length > 0 ? (
<div className="flex shrink grow flex-col gap-3 overflow-auto">
<span className="text-secondary">{t('Search results')}</span>

<div className="grid grid-cols-2 flex-wrap gap-3 md:grid-cols-3">
{displayedAddons.map((addon) => (
<Addon
key={addon.id}
addon={addon}
preselectedAddonsIds={preselectedAddonsIds}
selectedAddons={selectedAddons}
onSelectAddons={handleSelectAddon}
/>
))}
<div className="grid grid-cols-2 flex-wrap gap-3 md:grid-cols-3">
{displayedAddons.map((addon) => (
<Addon
key={addon.id}
addon={addon}
preselectedAddonsIds={preselectedAddonsIds}
selectedAddons={selectedAddons}
onSelectAddons={handleSelectAddon}
/>
))}
</div>
</div>
</div>
) : (
<div className="flex min-h-[200px] grow items-center justify-center">
<NoResultsFound />
</div>
)}

<div className="h-[40px] shrink-0"></div>
</div>
<div className="relative h-0 grow">
<div className="absolute bottom-0 flex h-[80px] w-full items-end justify-center bg-gradient-to-b from-transparent via-layer-3 to-layer-3 px-3 md:px-5">
<button
className="button button-primary"
onClick={() => {
onClose();
onAddonsSelected(selectedAddons.map(({ id }) => id));
}}
disabled={
selectedAddons.length + preselectedAddonsIds.length > 10
}
>
{t('Apply addons')}
</button>
) : (
<div className="flex min-h-[200px] grow items-center justify-center">
<NoResultsFound />
</div>
)}
</div>
</div>
<div className="flex items-center justify-end border-t-[1px] px-3 pt-4 md:px-5">
<button
className="button button-primary"
onClick={() => {
onClose();
onAddonsSelected(selectedAddons.map(({ id }) => id));
}}
disabled={
selectedAddons.length + preselectedAddonsIds.length > 10
}
>
{t('Apply addons')}
</button>
</div>
</div>
</div>
</FloatingPortal>
Expand Down
60 changes: 35 additions & 25 deletions apps/ai-dial-chat/src/components/Chat/Chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ export const Chat = memo(() => {
const nextMessageBoxRef = useRef<HTMLDivElement | null>(null);
const [inputHeight, setInputHeight] = useState<number>(142);
const [notAllowedType, setNotAllowedType] = useState<EntityType | null>(null);
const isSentRef = useRef(false);
const disableAutoScrollTimeoutRef = useRef<ReturnType<typeof setTimeout>>();

const showReplayControls = useMemo(() => {
Expand All @@ -117,30 +118,6 @@ export const Chat = memo(() => {
(conv) => conv.messages.length > 0,
);

useEffect(() => {
setIsShowChatSettings(false);

if (selectedConversations.length > 0) {
const mergedMessages: MergedMessages[] = [];
for (let i = 0; i < selectedConversations[0].messages.length; i++) {
if (selectedConversations[0].messages[i].role === Role.System) continue;

mergedMessages.push(
selectedConversations.map((conv) => [
conv,
conv.messages[i] || { role: Role.Assistant, content: '' },
i,
]),
);
}
setMergedMessages([...mergedMessages]);
}

if (selectedConversations.some((conv) => conv.messages.length === 0)) {
setShowScrollDownButton(false);
}
}, [selectedConversations]);

useEffect(() => {
const modelIds = models.map((model) => model.id);
const isNotAllowedModel =
Expand Down Expand Up @@ -254,6 +231,7 @@ export const Chat = memo(() => {
threshold: 0.1,
},
);

const messagesEndElement = messagesEndRef.current;
if (messagesEndElement) {
observer.observe(messagesEndElement);
Expand All @@ -265,6 +243,35 @@ export const Chat = memo(() => {
};
}, [messagesEndRef]);

useEffect(() => {
setIsShowChatSettings(false);

if (selectedConversations.length > 0) {
if (isSentRef.current) {
handleScroll();
isSentRef.current = false;
}

const mergedMessages: MergedMessages[] = [];
for (let i = 0; i < selectedConversations[0].messages.length; i++) {
if (selectedConversations[0].messages[i].role === Role.System) continue;

mergedMessages.push(
selectedConversations.map((conv) => [
conv,
conv.messages[i] || { role: Role.Assistant, content: '' },
i,
]),
);
}
setMergedMessages([...mergedMessages]);
}

if (selectedConversations.some((conv) => conv.messages.length === 0)) {
setShowScrollDownButton(false);
}
}, [handleScroll, selectedConversations]);

const handleClearConversation = useCallback(
(conversation: Conversation) => {
if (conversation) {
Expand Down Expand Up @@ -436,6 +443,7 @@ export const Chat = memo(() => {
activeReplayIndex: 0,
}),
);
isSentRef.current = true;
},
[dispatch, selectedConversations],
);
Expand All @@ -453,6 +461,7 @@ export const Chat = memo(() => {
activeReplayIndex: 0,
}),
);
isSentRef.current = true;
}, [dispatch, selectedConversations]);

const onEditMessage = useCallback(
Expand All @@ -466,6 +475,7 @@ export const Chat = memo(() => {
activeReplayIndex: 0,
}),
);
isSentRef.current = true;
},
[dispatch, selectedConversations],
);
Expand Down Expand Up @@ -649,7 +659,7 @@ export const Chat = memo(() => {
>
{conv.messages.length !== 0 &&
enabledFeatures.has(Feature.TopSettings) && (
<div className={`z-10 flex flex-col `}>
<div className="z-10 flex flex-col">
<ChatHeader
conversation={conv}
isCompareMode={isCompareMode}
Expand Down
Loading

0 comments on commit dcb0f1a

Please sign in to comment.