Skip to content
This repository has been archived by the owner on Jan 2, 2025. It is now read-only.

Commit

Permalink
studio history
Browse files Browse the repository at this point in the history
  • Loading branch information
anastasiya1155 committed Jan 25, 2024
1 parent ad5b241 commit 16f9909
Show file tree
Hide file tree
Showing 33 changed files with 551 additions and 124 deletions.
8 changes: 7 additions & 1 deletion client/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { memo } from 'react';
import { DndProvider } from 'react-dnd';
import * as Sentry from '@sentry/react';
import { HTML5Backend } from 'react-dnd-html5-backend';
import { Toaster } from 'sonner';
import { AnalyticsContextProvider } from './context/providers/AnalyticsContextProvider';
Expand All @@ -17,6 +18,7 @@ import TabsContextProvider from './context/providers/TabsContextProvider';
import { FileHighlightsContextProvider } from './context/providers/FileHighlightsContextProvider';
import RepositoriesContextProvider from './context/providers/RepositoriesContextProvider';
import UpgradeRequiredPopup from './components/UpgradeRequiredPopup';
import ErrorFallback from './components/ErrorFallback';

const toastOptions = {
unStyled: true,
Expand Down Expand Up @@ -65,4 +67,8 @@ const App = () => {
);
};

export default memo(App);
export default memo(
Sentry.withErrorBoundary(App, {
fallback: (props) => <ErrorFallback {...props} />,
}),
);
2 changes: 1 addition & 1 deletion client/src/Project/CurrentTabContent/ChatTab/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const ChatTab = ({
handleMoveToAnotherSide,
}: Props) => {
const { t } = useTranslation();
const { focusedPanel } = useContext(TabsContext.All);
const { focusedPanel } = useContext(TabsContext.FocusedPanel);
const { closeTab } = useContext(TabsContext.Handlers);
const { isLeftSidebarFocused } = useContext(UIContext.Focus);
const { setFocusedTabItems } = useContext(CommandBarContext.Handlers);
Expand Down
2 changes: 1 addition & 1 deletion client/src/Project/CurrentTabContent/DocTab/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ const DocTab = ({
isDocInContext,
}: Props) => {
const { t } = useTranslation();
const { focusedPanel } = useContext(TabsContext.All);
const { focusedPanel } = useContext(TabsContext.FocusedPanel);
const { updateTabProperty } = useContext(TabsContext.Handlers);
const { isLeftSidebarFocused } = useContext(UIContext.Focus);
const { setFocusedTabItems, setChosenStep, setIsVisible } = useContext(
Expand Down
2 changes: 1 addition & 1 deletion client/src/Project/CurrentTabContent/FileTab/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ const FileTab = ({
);
const [isPending, startTransition] = useTransition();
const { openNewTab, updateTabProperty } = useContext(TabsContext.Handlers);
const { focusedPanel } = useContext(TabsContext.All);
const { focusedPanel } = useContext(TabsContext.FocusedPanel);
const { isLeftSidebarFocused } = useContext(UIContext.Focus);
const { setOnBoardingState } = useContext(UIContext.Onboarding);
const { project, refreshCurrentProjectStudios } = useContext(
Expand Down
3 changes: 2 additions & 1 deletion client/src/Project/CurrentTabContent/Header/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ type Props = {
};

const ProjectHeader = ({ side }: Props) => {
const { leftTabs, rightTabs, focusedPanel } = useContext(TabsContext.All);
const { leftTabs, rightTabs } = useContext(TabsContext.All);
const { focusedPanel } = useContext(TabsContext.FocusedPanel);
const { tab } = useContext(
TabsContext[side === 'left' ? 'CurrentLeft' : 'CurrentRight'],
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,8 @@ const ConversationInput = ({
if (isActiveTab) {
if (i === undefined) {
onMessageChange(e.target.value, i);
} else {
setValue(e.target.value);
}
setValue(e.target.value);
}
},
[i, onMessageChange, isActiveTab],
Expand Down Expand Up @@ -187,7 +186,7 @@ const ConversationInput = ({
<textarea
className={`w-full bg-transparent outline-none focus:outline-0 resize-none body-base placeholder:text-label-muted`}
placeholder={t('Start typing...')}
value={i === undefined ? message : value}
value={value}
onChange={handleChange}
autoComplete="off"
spellCheck="false"
Expand Down
139 changes: 81 additions & 58 deletions client/src/Project/CurrentTabContent/StudioTab/Conversation/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,18 @@ import { BranchIcon, WarningSignIcon } from '../../../../icons';
import SpinLoaderContainer from '../../../../components/Loaders/SpinnerLoader';
import { StudioConversationMessageAuthor } from '../../../../types/general';
import { getTemplates } from '../../../../services/api';
import { StudioTemplateType } from '../../../../types/api';
import {
HistoryConversationTurn,
StudioTemplateType,
} from '../../../../types/api';
import { checkEventKeys } from '../../../../utils/keyboardUtils';
import { useTemplateShortcut } from '../../../../consts/shortcuts';
import useKeyboardNavigation from '../../../../hooks/useKeyboardNavigation';
import { UIContext } from '../../../../context/uiContext';
import KeyHintButton from '../../../../components/Button/KeyHintButton';
import Button from '../../../../components/Button';
import { CommandBarContext } from '../../../../context/commandBarContext';
import { mapConversation } from '../../../../utils/mappers';
import GeneratedDiff from './GeneratedDiff';
import ConversationInput from './Input';
import StarterMessage from './StarterMessage';
Expand All @@ -36,6 +40,7 @@ type Props = {
isActiveTab: boolean;
requestsLeft: number;
studioId: string;
snapshot?: HistoryConversationTurn | null;
};

const generateShortcut = ['cmd', 'entr'];
Expand All @@ -48,6 +53,7 @@ const Conversation = ({
isActiveTab,
requestsLeft,
studioId,
snapshot,
}: Props) => {
const { t } = useTranslation();
const scrollableRef = useRef<HTMLDivElement>(null);
Expand Down Expand Up @@ -100,7 +106,8 @@ const Conversation = ({
studioData.inputValue &&
!isTokenLimitExceeded &&
!hasContextError &&
requestsLeft
requestsLeft &&
!snapshot
// && !isChangeUnsaved
) {
studioData.onSubmit();
Expand All @@ -124,11 +131,12 @@ const Conversation = ({
studioData.isLoading,
studioData.handleCancel,
requestsLeft,
snapshot,
],
);
useKeyboardNavigation(
handleKeyEvent,
!isActiveTab || isDropdownShown || isVisible,
!isActiveTab || isDropdownShown || isVisible || !!snapshot,
);

const hasCodeBlock = useMemo(() => {
Expand All @@ -143,15 +151,23 @@ const Conversation = ({
return studioData.diff?.chunks.find((c) => c.repo.startsWith('local//'));
}, [studioData.diff]);

const mappedSnapshotConversation = useMemo(() => {
if (!snapshot) {
return null;
}
return mapConversation(snapshot.messages);
}, [snapshot]);

return !studioData ? null : (
<div className="w-full max-w-2xl mx-auto flex flex-col flex-1 overflow-auto">
<ScrollToBottom
className="max-w-full flex flex-col overflow-auto"
wrapperRef={scrollableRef}
key={snapshot?.id}
>
<StarterMessage />
<NoFilesMessage studioId={studioId} />
{studioData.conversation.map((m, i) => (
{(mappedSnapshotConversation || studioData.conversation).map((m, i) => (
<ConversationInput
key={i}
author={m.author}
Expand Down Expand Up @@ -222,7 +238,7 @@ const Conversation = ({
)}
{hasContextError && <ContextError />}
{!studioData.isLoading &&
// !studioData.isPreviewing &&
!snapshot &&
!studioData.waitingForDiff &&
!studioData.diff &&
!(
Expand All @@ -246,68 +262,75 @@ const Conversation = ({
/>
)}
</ScrollToBottom>
<div
className={`flex items-start justify-between flex-shrink-0 w-full p-4 gap-4 border-t border-bg-border ${
isScrollable ? 'bg-bg-base border-x rounded-tl-md rounded-tr-md' : ''
}`}
>
<div className="flex gap-2 items-center select-none">
<KeyHintButton
text={t('Clear conversation')}
shortcut={noShortcut}
onClick={studioData.clearConversation}
/>
</div>
<div className="flex gap-2 items-center select-none">
{studioData.isLoading ? (
{!snapshot && (
<div
className={`flex items-start justify-between flex-shrink-0 w-full p-4 gap-4 border-t border-bg-border ${
isScrollable
? 'bg-bg-base border-x rounded-tl-md rounded-tr-md'
: ''
}`}
>
<div className="flex gap-2 items-center select-none">
<KeyHintButton
text={t('Stop generating')}
shortcut={stopShortcut}
onClick={studioData.handleCancel}
text={t('Clear conversation')}
shortcut={noShortcut}
onClick={studioData.clearConversation}
disabled={!!snapshot}
/>
) : (
<>
{(hasCodeBlock || studioData.diff) &&
(studioData.isDiffApplied ||
studioData.waitingForDiff ? null : !studioData.diff ? (
<KeyHintButton
text={t('Apply changes')}
shortcut={noShortcut}
onClick={studioData.handleApplyChanges}
/>
) : (
<>
</div>
<div className="flex gap-2 items-center select-none">
{studioData.isLoading ? (
<KeyHintButton
text={t('Stop generating')}
shortcut={stopShortcut}
onClick={studioData.handleCancel}
/>
) : (
<>
{(hasCodeBlock || studioData.diff) &&
(studioData.isDiffApplied ||
studioData.waitingForDiff ? null : !studioData.diff ? (
<KeyHintButton
text={t(isDiffForLocalRepo ? 'Cancel' : 'Close')}
text={t('Apply changes')}
shortcut={noShortcut}
onClick={() => studioData.setDiff(null)}
onClick={studioData.handleApplyChanges}
disabled={!!snapshot}
/>
{isDiffForLocalRepo && (
) : (
<>
<KeyHintButton
text={'Apply locally'}
text={t(isDiffForLocalRepo ? 'Cancel' : 'Close')}
shortcut={noShortcut}
onClick={studioData.handleConfirmDiff}
onClick={() => studioData.setDiff(null)}
/>
)}
</>
))}
{!studioData.diff && (
<KeyHintButton
text={t('Generate')}
shortcut={generateShortcut}
onClick={studioData.onSubmit}
disabled={
hasContextError ||
isTokenLimitExceeded ||
!studioData.inputValue ||
!requestsLeft
}
/>
)}
</>
)}
{isDiffForLocalRepo && (
<KeyHintButton
text={'Apply locally'}
shortcut={noShortcut}
onClick={studioData.handleConfirmDiff}
/>
)}
</>
))}
{!studioData.diff && (
<KeyHintButton
text={t('Generate')}
shortcut={generateShortcut}
onClick={studioData.onSubmit}
disabled={
hasContextError ||
isTokenLimitExceeded ||
!studioData.inputValue ||
!requestsLeft ||
!!snapshot
}
/>
)}
</>
)}
</div>
</div>
</div>
)}
</div>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {
} from '../../../types/api';
import { PersonalQuotaContext } from '../../../context/personalQuotaContext';
import { UIContext } from '../../../context/uiContext';
import { mapConversation } from '../../../utils/mappers';

type Props = {
tabKey: string; //studioId
Expand All @@ -45,15 +46,6 @@ const throttledPatch = throttle(
{ leading: false, trailing: true },
);

function mapConversation(
messages: CodeStudioMessageType[],
): StudioConversationMessage[] {
return messages.map((m) => {
const author = Object.keys(m)[0] as StudioConversationMessageAuthor;
return { author, message: Object.values(m)[0] };
});
}

const StudioPersistentState = ({ tabKey, side }: Props) => {
const { t } = useTranslation();
const { apiUrl } = useContext(DeviceContext);
Expand Down Expand Up @@ -197,6 +189,11 @@ const StudioPersistentState = ({ tabKey, side }: Props) => {
},
[tabKey, project?.id, side],
);
useEffect(() => {
setStudios((prev) => {
return { ...prev, [tabKey]: { ...prev[tabKey], refetchCodeStudio } };
});
}, [refetchCodeStudio]);

useEffect(() => {
refetchCodeStudio();
Expand Down
Loading

0 comments on commit 16f9909

Please sign in to comment.