diff --git a/apps/studio/components/interfaces/SQLEditor/MonacoEditor.tsx b/apps/studio/components/interfaces/SQLEditor/MonacoEditor.tsx index dc954c5088a..a44e6a8b63c 100644 --- a/apps/studio/components/interfaces/SQLEditor/MonacoEditor.tsx +++ b/apps/studio/components/interfaces/SQLEditor/MonacoEditor.tsx @@ -19,6 +19,7 @@ import { SHORTCUT_IDS } from '@/state/shortcuts/registry' import { useIsShortcutEnabled } from '@/state/shortcuts/useIsShortcutEnabled' import { useSidebarManagerSnapshot } from '@/state/sidebar-manager-state' import { useSqlEditorV2StateSnapshot } from '@/state/sql-editor-v2' +import { wasNeverPersisted } from '@/state/sql-editor/sql-editor-lifecycle' import { canEditSnippet } from '@/state/sql-editor/sql-editor-rules' import { useTabsStateSnapshot } from '@/state/tabs' @@ -237,7 +238,7 @@ export const MonacoEditor = ({ useEffect(() => { if (debouncedValue.length > 0 && snippet) { - const shouldInvalidate = snippet.snippet.isNotSavedInDatabaseYet + const shouldInvalidate = wasNeverPersisted(snippet.snippet.status) snapV2.setSql({ id, sql: value, shouldInvalidate }) } // eslint-disable-next-line react-hooks/exhaustive-deps diff --git a/apps/studio/components/interfaces/SQLEditor/MoveQueryModal.tsx b/apps/studio/components/interfaces/SQLEditor/MoveQueryModal.tsx index 7fd3ea7ae7e..af39f60b7ea 100644 --- a/apps/studio/components/interfaces/SQLEditor/MoveQueryModal.tsx +++ b/apps/studio/components/interfaces/SQLEditor/MoveQueryModal.tsx @@ -41,11 +41,8 @@ import { getContentById } from '@/data/content/content-id-query' import { useContentUpsertMutation } from '@/data/content/content-upsert-mutation' import { useSQLSnippetFolderCreateMutation } from '@/data/content/sql-folder-create-mutation' import { Snippet } from '@/data/content/sql-folders-query' -import { - SnippetWithContent, - useSnippetFolders, - useSqlEditorV2StateSnapshot, -} from '@/state/sql-editor-v2' +import type { SnippetWithContent } from '@/data/content/sql-folders-query' +import { useSnippetFolders, useSqlEditorV2StateSnapshot } from '@/state/sql-editor-v2' import { createTabId, useTabsStateSnapshot } from '@/state/tabs' interface MoveQueryModalProps { diff --git a/apps/studio/components/interfaces/SQLEditor/RenameQueryModal.tsx b/apps/studio/components/interfaces/SQLEditor/RenameQueryModal.tsx index fa5da761acf..1f92fc58090 100644 --- a/apps/studio/components/interfaces/SQLEditor/RenameQueryModal.tsx +++ b/apps/studio/components/interfaces/SQLEditor/RenameQueryModal.tsx @@ -26,7 +26,7 @@ import * as z from 'zod' import { ButtonTooltip } from '@/components/ui/ButtonTooltip' import { useCheckOpenAIKeyQuery } from '@/data/ai/check-api-key-query' import { useSqlTitleGenerateMutation } from '@/data/ai/sql-title-mutation' -import { getContentById } from '@/data/content/content-id-query' +import { getContentById, getSqlSnippetById } from '@/data/content/content-id-query' import { UpsertContentPayload, useContentUpsertMutation, @@ -109,8 +109,9 @@ export const RenameQueryModal = ({ // [Joshen] For SQL V2 - content is loaded on demand so we need to fetch the data if its not already loaded in the valtio state if (!('content' in localSnippet)) { - localSnippet = await getContentById({ projectRef: ref, id }) - snapV2.addSnippet({ projectRef: ref, snippet: localSnippet }) + const fetched = await getSqlSnippetById({ projectRef: ref, id }) + snapV2.addSnippet({ projectRef: ref, snippet: fetched }) + localSnippet = fetched } const changedSnippet = await upsertContent({ diff --git a/apps/studio/components/interfaces/SQLEditor/SQLEditor.utils.ts b/apps/studio/components/interfaces/SQLEditor/SQLEditor.utils.ts index 0e497cca467..9e01e8c24a2 100644 --- a/apps/studio/components/interfaces/SQLEditor/SQLEditor.utils.ts +++ b/apps/studio/components/interfaces/SQLEditor/SQLEditor.utils.ts @@ -9,11 +9,11 @@ import { updateWithoutWhereRegex, } from './SQLEditor.constants' import { ContentDiff } from './SQLEditor.types' +import type { SnippetWithContent } from '@/data/content/sql-folders-query' import type { DatabaseEventTrigger } from '@/data/database-event-triggers/database-event-triggers-query' import { generateUuid } from '@/lib/api/snippets.browser' import { removeCommentsFromSql } from '@/lib/helpers' import { sqlEventParser } from '@/lib/sql-event-parser' -import type { SnippetWithContent } from '@/state/sql-editor-v2' export type CreateTableWithoutRLS = { schema?: string @@ -83,7 +83,7 @@ export const createSqlSnippetSkeletonV2 = ({ content_id: id ?? '', unchecked_sql: untrustedSql(sql ?? ''), } as any, - isNotSavedInDatabaseYet: true, + status: 'new', } } diff --git a/apps/studio/components/interfaces/SQLEditor/UtilityPanel/SavingIndicator.tsx b/apps/studio/components/interfaces/SQLEditor/UtilityPanel/SavingIndicator.tsx index 12c34a4214d..dd62160f012 100644 --- a/apps/studio/components/interfaces/SQLEditor/UtilityPanel/SavingIndicator.tsx +++ b/apps/studio/components/interfaces/SQLEditor/UtilityPanel/SavingIndicator.tsx @@ -6,6 +6,7 @@ import { Button, Tooltip, TooltipContent, TooltipTrigger } from 'ui' import ReadOnlyBadge from './ReadOnlyBadge' import { useProfile } from '@/lib/profile' import { useSqlEditorV2StateSnapshot } from '@/state/sql-editor-v2' +import { isSaveFailed, isSaving } from '@/state/sql-editor/sql-editor-lifecycle' import { isSnippetOwner } from '@/state/sql-editor/sql-editor-rules' export type SavingIndicatorProps = { id: string } @@ -14,17 +15,19 @@ const SavingIndicator = ({ id }: SavingIndicatorProps) => { const { profile } = useProfile() const snapV2 = useSqlEditorV2StateSnapshot() - const savingState = snapV2.savingStates[id] - const previousState = usePrevious(savingState) + const snippet = snapV2.snippets[id] + const status = snippet?.snippet.status + const saving = isSaving(status) + const saveFailed = isSaveFailed(status) + const previousSaving = usePrevious(saving) const [showSavedText, setShowSavedText] = useState(false) - const snippet = snapV2.snippets[id] const snippetIsOwned = !!snippet && isSnippetOwner(snippet.snippet, profile?.id) useEffect(() => { let cancel = false - if (previousState === 'UPDATING' && savingState === 'IDLE') { + if (previousSaving && status === 'saved') { setShowSavedText(true) setTimeout(() => { if (!cancel) setShowSavedText(false) @@ -34,14 +37,14 @@ const SavingIndicator = ({ id }: SavingIndicatorProps) => { return () => { cancel = true } - }, [savingState]) + }, [status, previousSaving]) const retry = () => snapV2.addNeedsSaving(id) return ( <>
- {snippetIsOwned && savingState === 'UPDATING_FAILED' && ( + {snippetIsOwned && saveFailed && (