Skip to content

Commit

Permalink
feat(chat): implement unique entitiy names validation (Issue #633) (#694
Browse files Browse the repository at this point in the history
)
  • Loading branch information
Alexander-Kezik authored Feb 13, 2024
1 parent bf65315 commit 39a226c
Show file tree
Hide file tree
Showing 8 changed files with 253 additions and 64 deletions.
7 changes: 6 additions & 1 deletion apps/chat/src/components/Chatbar/ChatFolders.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ const ChatFolderTemplate = ({
searchTerm,
),
);
const allConversations = useAppSelector(
ConversationsSelectors.selectConversations,
);
const allFolders = useAppSelector(ConversationsSelectors.selectFolders);
const conversationFolders = useAppSelector((state) =>
ConversationsSelectors.selectFilteredFolders(
state,
Expand Down Expand Up @@ -116,7 +120,6 @@ const ChatFolderTemplate = ({
},
[dispatch],
);

const onDropBetweenFolders = useCallback(
(folder: FolderInterface, parentFolderId: string | undefined) => {
dispatch(
Expand Down Expand Up @@ -152,7 +155,9 @@ const ChatFolderTemplate = ({
currentFolder={folder}
itemComponent={ConversationComponent}
allItems={conversations}
allItemsWithoutFilters={allConversations}
allFolders={conversationFolders}
allFoldersWithoutFilters={allFolders}
highlightedFolders={highlightedFolders}
openedFoldersIds={openedFoldersIds}
handleDrop={handleDrop}
Expand Down
47 changes: 41 additions & 6 deletions apps/chat/src/components/Chatbar/Conversation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,14 @@ import {
useState,
} from 'react';

import { useTranslation } from 'next-i18next';

import classNames from 'classnames';

import {
isEntityNameOnSameLevelUnique,
prepareEntityName,
} from '@/src/utils/app/common';
import { notAllowedSymbolsRegex } from '@/src/utils/app/file';
import { hasParentWithFloatingOverlay } from '@/src/utils/app/modals';
import { MoveType, getDragImage } from '@/src/utils/app/move';
Expand All @@ -22,6 +28,7 @@ import { isEntityOrParentsExternal } from '@/src/utils/app/share';
import { Conversation, ConversationInfo } from '@/src/types/chat';
import { FeatureType, isNotLoaded } from '@/src/types/common';
import { SharingType } from '@/src/types/share';
import { Translation } from '@/src/types/translation';

import {
ConversationsActions,
Expand Down Expand Up @@ -96,6 +103,8 @@ interface Props {
}

export const ConversationComponent = ({ item: conversation, level }: Props) => {
const { t } = useTranslation(Translation.Chat);

const dispatch = useAppDispatch();

const modelsMap = useAppSelector(ModelsSelectors.selectModelsMap);
Expand Down Expand Up @@ -141,6 +150,9 @@ export const ConversationComponent = ({ item: conversation, level }: Props) => {
const newFolderName = useAppSelector((state) =>
ConversationsSelectors.selectNewFolderName(state, conversation.folderId),
);
const allConversations = useAppSelector(
ConversationsSelectors.selectConversations,
);

const { refs, context } = useFloating({
open: isContextMenu,
Expand All @@ -166,22 +178,46 @@ export const ConversationComponent = ({ item: conversation, level }: Props) => {

const handleRename = useCallback(
(conversation: ConversationInfo) => {
if (renameValue.trim().length > 0) {
const newName = prepareEntityName(renameValue);
setRenameValue(newName);

if (
!isEntityNameOnSameLevelUnique(newName, conversation, allConversations)
) {
dispatch(
UIActions.showToast({
message: t(
'Conversation with name "{{newName}}" already exists in this folder.',
{
ns: 'chat',
newName,
},
),
type: 'error',
}),
);

return;
}

if (newName.length > 0) {
dispatch(
ConversationsActions.updateConversation({
id: conversation.id,
values: {
name: renameValue.trim(),
name: newName,
isNameChanged: true,
},
}),
);

setRenameValue('');
setIsRenaming(false);
setIsContextMenu(false);
}

setIsRenaming(false);
},
[dispatch, renameValue],
[allConversations, dispatch, renameValue, t],
);

const handleEnterDown = useCallback(
Expand Down Expand Up @@ -217,11 +253,10 @@ export const ConversationComponent = ({ item: conversation, level }: Props) => {
conversationIds: [conversation.id],
}),
);
setIsDeleting(false);
} else if (isRenaming) {
handleRename(conversation);
}
setIsDeleting(false);
setIsRenaming(false);
},
[conversation, dispatch, handleRename, isDeleting, isRenaming],
);
Expand Down
119 changes: 112 additions & 7 deletions apps/chat/src/components/Folder/Folder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ import { useTranslation } from 'next-i18next';

import classNames from 'classnames';

import {
isEntityNameOnSameLevelUnique,
prepareEntityName,
} from '@/src/utils/app/common';
import { notAllowedSymbolsRegex } from '@/src/utils/app/file';
import {
compareEntitiesByName,
Expand All @@ -28,6 +32,7 @@ import {
import { hasParentWithFloatingOverlay } from '@/src/utils/app/modals';
import {
getDragImage,
getEntityMoveType,
getFolderMoveType,
hasDragEventAnyData,
} from '@/src/utils/app/move';
Expand Down Expand Up @@ -90,14 +95,18 @@ export interface FolderProps<T, P = unknown> {
maxDepth?: number;
highlightTemporaryFolders?: boolean;
withBorderHighlight?: boolean;
allFoldersWithoutFilters?: FolderInterface[];
allItemsWithoutFilters?: T[];
}

const Folder = <T extends ConversationInfo | PromptInfo | DialFile>({
currentFolder,
searchTerm,
itemComponent,
allItems,
allItemsWithoutFilters = [],
allFolders,
allFoldersWithoutFilters = [],
highlightedFolders,
openedFoldersIds,
level = 0,
Expand Down Expand Up @@ -229,11 +238,45 @@ const Folder = <T extends ConversationInfo | PromptInfo | DialFile>({
if (!onRenameFolder) {
return;
}
renameValue.trim() && onRenameFolder(renameValue, currentFolder.id);

const newName = prepareEntityName(renameValue);
setRenameValue(newName);

if (
!isEntityNameOnSameLevelUnique(
newName,
currentFolder,
allFoldersWithoutFilters,
)
) {
dispatch(
UIActions.showToast({
message: t(
'Folder with name "{{folderName}}" already exists in this folder.',
{
ns: 'folder',
folderName: newName,
},
),
type: 'error',
}),
);

return;
}

newName && onRenameFolder(newName, currentFolder.id);
setRenameValue('');
setIsRenaming(false);
setIsContextMenu(false);
}, [onRenameFolder, renameValue, currentFolder]);
}, [
onRenameFolder,
renameValue,
currentFolder,
allFoldersWithoutFilters,
dispatch,
t,
]);

const handleEnterDown = useCallback(
(e: KeyboardEvent<HTMLDivElement>) => {
Expand Down Expand Up @@ -297,19 +340,79 @@ const Folder = <T extends ConversationInfo | PromptInfo | DialFile>({
);
return;
}

if (
!isEntityNameOnSameLevelUnique(
draggedFolder.name,
{ ...draggedFolder, folderId: currentFolder.id },
allFoldersWithoutFilters,
)
) {
dispatch(
UIActions.showToast({
message: t(
'Folder with name "{{folderName}}" already exists in this folder.',
{
ns: 'folder',
folderName: draggedFolder.name,
},
),
type: 'error',
}),
);

return;
}
}

const entityData = e.dataTransfer.getData(
getEntityMoveType(featureType),
);
if (entityData) {
const draggedEntity = JSON.parse(entityData);

if (
!isEntityNameOnSameLevelUnique(
draggedEntity.name,
{ ...draggedEntity, folderId: currentFolder.id },
allItemsWithoutFilters,
)
) {
dispatch(
UIActions.showToast({
message: t(
'{{entityType}} with name "{{entityName}}" already exists in this folder.',
{
ns: 'common',
entityType:
featureType === FeatureType.Chat
? 'Conversation'
: 'Prompt',
entityName: draggedEntity.name,
},
),
type: 'error',
}),
);

return;
}
}

handleDrop(e, currentFolder);
}
},
[
handleDrop,
isExternal,
dispatch,
allFolders,
allFoldersWithoutFilters,
allItemsWithoutFilters,
currentFolder,
dispatch,
featureType,
allFolders,
maxDepth,
handleDrop,
isExternal,
level,
maxDepth,
t,
],
);
Expand Down Expand Up @@ -680,7 +783,9 @@ const Folder = <T extends ConversationInfo | PromptInfo | DialFile>({
currentFolder={item}
itemComponent={itemComponent}
allItems={allItems}
allItemsWithoutFilters={allItemsWithoutFilters}
allFolders={allFolders}
allFoldersWithoutFilters={allFoldersWithoutFilters}
highlightedFolders={highlightedFolders}
openedFoldersIds={openedFoldersIds}
loadingFolderIds={loadingFolderIds}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,11 @@ const PromptFolderTemplate = ({
const highlightedFolders = useAppSelector(
PromptsSelectors.selectSelectedPromptFoldersIds,
);
const allPrompts = useAppSelector(PromptsSelectors.selectPrompts);
const prompts = useAppSelector((state) =>
PromptsSelectors.selectFilteredPrompts(state, filters, searchTerm),
);
const allFolders = useAppSelector(PromptsSelectors.selectFolders);
const promptFolders = useAppSelector((state) =>
PromptsSelectors.selectFilteredFolders(
state,
Expand Down Expand Up @@ -147,7 +149,9 @@ const PromptFolderTemplate = ({
currentFolder={folder}
itemComponent={PromptComponent}
allItems={prompts}
allItemsWithoutFilters={allPrompts}
allFolders={promptFolders}
allFoldersWithoutFilters={allFolders}
highlightedFolders={highlightedFolders}
openedFoldersIds={openedFoldersIds}
handleDrop={handleDrop}
Expand Down
Loading

0 comments on commit 39a226c

Please sign in to comment.