Skip to content

Commit

Permalink
add docs to studios
Browse files Browse the repository at this point in the history
  • Loading branch information
anastasiya1155 committed Jan 19, 2024
1 parent 3b89d77 commit bdd39b5
Show file tree
Hide file tree
Showing 36 changed files with 1,201 additions and 180 deletions.
5 changes: 1 addition & 4 deletions client/src/CommandBar/Body/Item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,7 @@ const CommandBarItem = ({
}
} else {
setChosenStep({
id: id as Exclude<
CommandBarStepEnum,
CommandBarStepEnum.ADD_FILE_TO_STUDIO
>,
id: id as Exclude<CommandBarStepEnum, CommandBarStepEnum.ADD_TO_STUDIO>,
});
}
updateArrayInStorage(RECENT_COMMANDS_KEY, itemKey);
Expand Down
4 changes: 2 additions & 2 deletions client/src/CommandBar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import ManageRepos from './steps/ManageRepos';
import AddNewRepo from './steps/AddNewRepo';
import ToggleTheme from './steps/ToggleTheme';
import SearchFiles from './steps/SeachFiles';
import AddFileToStudio from './steps/AddFileToStudio';
import AddFileToStudio from './steps/AddToStudio';

type Props = {};

Expand Down Expand Up @@ -79,7 +79,7 @@ const CommandBar = ({}: Props) => {
<ToggleTheme />
) : chosenStep.id === CommandBarStepEnum.SEARCH_FILES ? (
<SearchFiles />
) : chosenStep.id === CommandBarStepEnum.ADD_FILE_TO_STUDIO ? (
) : chosenStep.id === CommandBarStepEnum.ADD_TO_STUDIO ? (
<AddFileToStudio {...chosenStep.data} />
) : null}
</Modal>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,27 @@ import {
} from 'react';
import { useTranslation } from 'react-i18next';
import {
AddDocToStudioDataType,
AddFileToStudioDataType,
CommandBarItemGeneralType,
CommandBarSectionType,
CommandBarStepEnum,
TabTypesEnum,
} from '../../types/general';
import { CodeStudioIcon, PlusSignIcon } from '../../icons';
import { PlusSignIcon } from '../../icons';
import Header from '../Header';
import Body from '../Body';
import Footer from '../Footer';
import { CommandBarContext } from '../../context/commandBarContext';
import { ProjectContext } from '../../context/projectContext';
import { TabsContext } from '../../context/tabsContext';
import { postCodeStudio } from '../../services/api';
import TokenUsage from '../../components/TokenUsage';
import { TOKEN_LIMIT } from '../../consts/codeStudio';

type Props = AddFileToStudioDataType & {};
type Props = (AddFileToStudioDataType | AddDocToStudioDataType) & {};

const AddFileToStudio = ({ path, repoRef, branch }: Props) => {
const AddToStudio = (props: Props) => {
const { t } = useTranslation();
const { setChosenStep } = useContext(CommandBarContext.Handlers);
const { project, refreshCurrentProjectStudios } = useContext(
Expand All @@ -50,15 +53,56 @@ const AddFileToStudio = ({ path, repoRef, branch }: Props) => {
if (project?.id) {
const newId = await postCodeStudio(project.id);
refreshCurrentProjectStudios();
openNewTab({
type: TabTypesEnum.FILE,
studioId: newId,
path,
repoRef,
branch,
});
if ('path' in props) {
openNewTab(
{
type: TabTypesEnum.FILE,
studioId: newId,
...props,
},
'left',
);
} else {
openNewTab(
{
type: TabTypesEnum.DOC,
studioId: newId,
...props,
},
'left',
);
}
openNewTab({ type: TabTypesEnum.STUDIO, studioId: newId }, 'right');
}
}, [project?.id, path, repoRef, branch]);
}, [project?.id, props, openNewTab, refreshCurrentProjectStudios]);

const handleAddToCodeStudio = useCallback(
async (studioId: string) => {
if (project?.id) {
if ('path' in props) {
openNewTab(
{
type: TabTypesEnum.FILE,
studioId,
...props,
},
'left',
);
} else {
openNewTab(
{
type: TabTypesEnum.DOC,
studioId,
...props,
},
'left',
);
}
openNewTab({ type: TabTypesEnum.STUDIO, studioId }, 'right');
}
},
[project?.id, props, openNewTab],
);

const initialSections = useMemo(() => {
return [
Expand All @@ -81,38 +125,28 @@ const AddFileToStudio = ({ path, repoRef, branch }: Props) => {
{
items: (project?.studios || []).map((s) => ({
label: s.name,
Icon: CodeStudioIcon,
Icon: () => (
<TokenUsage
percent={(s.token_counts.total / TOKEN_LIMIT) * 100}
sizeClassName={'w-6 h-6'}
/>
),
iconContainerClassName: 'bg-transparent',
id: s.id,
key: s.id,
onClick: () =>
openNewTab({
type: TabTypesEnum.FILE,
studioId: s.id,
path,
repoRef,
branch,
}),
onClick: () => handleAddToCodeStudio(s.id),
closeOnClick: true,
// footerHint: t('{{count}} context files used', {
// count: s.token_counts?.per_file.filter((f) => !!f).length,
// }),
footerHint: '',
footerHint: t('{{count}} context files used', {
count: s.context.length,
}),
footerBtns: [{ label: t('Add to existing'), shortcut: ['entr'] }],
})),
label: t('Existing studio conversations'),
itemsOffset: 1,
key: 'studio-items',
},
];
}, [
t,
project?.studios,
handleNewCodeStudio,
openNewTab,
path,
repoRef,
branch,
]);
}, [t, project?.studios, handleNewCodeStudio, openNewTab, props]);

useEffect(() => {
if (!inputValue) {
Expand Down Expand Up @@ -140,8 +174,8 @@ const AddFileToStudio = ({ path, repoRef, branch }: Props) => {
}, [initialSections, inputValue]);

const breadcrumbs = useMemo(() => {
return [t('Add file to studio')];
}, []);
return [t(`Add ${'path' in props ? 'file' : 'doc'} to studio`)];
}, [props, t]);

return (
<div className="w-full flex flex-col h-[28.875rem] max-w-[40rem] overflow-auto">
Expand All @@ -158,4 +192,4 @@ const AddFileToStudio = ({ path, repoRef, branch }: Props) => {
);
};

export default memo(AddFileToStudio);
export default memo(AddToStudio);
12 changes: 3 additions & 9 deletions client/src/Project/CurrentTabContent/ChatTab/ActionsDropdown.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { memo, useCallback, useMemo } from 'react';
import { memo, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import DropdownSection from '../../../components/Dropdown/Section';
import SectionItem from '../../../components/Dropdown/Section/SectionItem';
import { SplitViewIcon, TrashCanIcon } from '../../../icons';
import { deleteConversation } from '../../../services/api';
import { openInSplitViewShortcut } from '../../../consts/shortcuts';

type Props = {
handleMoveToAnotherSide: () => void;
Expand Down Expand Up @@ -41,20 +42,13 @@ const ActionsDropdown = ({
side,
]);

const shortcuts = useMemo(() => {
return {
splitView: ['cmd', ']'],
};
}, []);

return (
<div>
<DropdownSection>
<SectionItem
label={t('Open in split view')}
shortcut={shortcuts.splitView}
shortcut={openInSplitViewShortcut}
onClick={handleMoveToAnotherSide}
// isFocused
icon={<SplitViewIcon sizeClassName="w-4 h-4" />}
/>
{conversationId && (
Expand Down
4 changes: 2 additions & 2 deletions client/src/Project/CurrentTabContent/ChatTab/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ import { TabsContext } from '../../../context/tabsContext';
import { ChatTabType } from '../../../types/general';
import { ProjectContext } from '../../../context/projectContext';
import { CommandBarContext } from '../../../context/commandBarContext';
import { openInSplitViewShortcut } from '../../../consts/commandBar';
import { UIContext } from '../../../context/uiContext';
import { openInSplitViewShortcut } from '../../../consts/shortcuts';
import Conversation from './Conversation';
import ActionsDropdown from './ActionsDropdown';

Expand Down Expand Up @@ -70,7 +70,7 @@ const ChatTab = ({

const handleKeyEvent = useCallback(
(e: KeyboardEvent) => {
if (checkEventKeys(e, ['cmd', ']'])) {
if (checkEventKeys(e, openInSplitViewShortcut)) {
handleMoveToAnotherSide();
}
},
Expand Down
62 changes: 62 additions & 0 deletions client/src/Project/CurrentTabContent/DocTab/ActionsDropdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { memo } from 'react';
import { useTranslation } from 'react-i18next';
import DropdownSection from '../../../components/Dropdown/Section';
import SectionItem from '../../../components/Dropdown/Section/SectionItem';
import {
SplitViewIcon,
StudioCloseSignIcon,
StudioPlusSignIcon,
} from '../../../icons';
import {
addToStudioShortcut,
openInSplitViewShortcut,
removeFromStudioShortcut,
} from '../../../consts/shortcuts';

type Props = {
handleMoveToAnotherSide: () => void;
handleAddToStudio: () => void;
handleRemoveFromStudio: () => void;
isDocInContext: boolean;
};

const ActionsDropdown = ({
handleMoveToAnotherSide,
handleAddToStudio,
handleRemoveFromStudio,
isDocInContext,
}: Props) => {
const { t } = useTranslation();

return (
<div>
<DropdownSection borderBottom>
{isDocInContext ? (
<SectionItem
label={t('Remove from studio')}
onClick={handleRemoveFromStudio}
shortcut={removeFromStudioShortcut}
icon={<StudioCloseSignIcon sizeClassName="w-4 h-4" />}
/>
) : (
<SectionItem
label={t('Add to studio')}
onClick={handleAddToStudio}
shortcut={addToStudioShortcut}
icon={<StudioPlusSignIcon sizeClassName="w-4 h-4" />}
/>
)}
</DropdownSection>
<DropdownSection>
<SectionItem
label={t('Open in split view')}
shortcut={openInSplitViewShortcut}
onClick={handleMoveToAnotherSide}
icon={<SplitViewIcon sizeClassName="w-4 h-4" />}
/>
</DropdownSection>
</div>
);
};

export default memo(ActionsDropdown);
80 changes: 80 additions & 0 deletions client/src/Project/CurrentTabContent/DocTab/DocSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import React, { Dispatch, memo, SetStateAction, useCallback } from 'react';
import { Trans } from 'react-i18next';
import Button from '../../../components/Button';
import { DocSectionType } from '../../../types/api';
import RenderedSection from './RenderedSection';

type Props = DocSectionType & {
isSelected: boolean;
isNothingSelected: boolean;
isEditingSelection: boolean;
setSelectedSections: Dispatch<SetStateAction<string[]>>;
};

const DocSection = ({
text,
isSelected,
setSelectedSections,
point_id,
isNothingSelected,
doc_source,
isEditingSelection,
}: Props) => {
const setSelected = useCallback(
(b: boolean) => {
setSelectedSections((prev) => {
if (b) {
return [...prev, point_id];
}
return prev.filter((r) => r !== point_id);
});
},
[point_id, setSelectedSections],
);

const handleClick = useCallback(() => {
if (isEditingSelection) {
setSelected(!isSelected);
}
}, [isSelected, isEditingSelection]);
return (
<div
data-section-id={point_id}
className={`body-s relative group ${
isSelected
? 'bg-bg-selected opacity-100'
: isEditingSelection
? `hover:bg-bg-sub-hover ${
isNothingSelected ? '' : 'opacity-50 hover:opacity-100'
}`
: ''
} ${
isEditingSelection ? 'cursor-pointer' : ''
} pl-8 pr-4 py-3 transition-opacity duration-150 ease-in-out`}
onClick={handleClick}
>
{isEditingSelection && (
<div
className={`absolute top-2 right-2 z-10 ${
isSelected ? 'opacity-100' : 'opacity-0 group-hover:opacity-100'
} transition-opacity duration-150 ease-in-out`}
>
<Button size="mini" variant="secondary" onClick={handleClick}>
{!isSelected ? (
<Trans>Select section</Trans>
) : (
<Trans>Clear section</Trans>
)}
</Button>
</div>
)}
<RenderedSection
text={text}
baseUrl={doc_source}
isEditingSelection={isEditingSelection}
/>
</div>
);
};

export default memo(DocSection);
Loading

0 comments on commit bdd39b5

Please sign in to comment.