feat: 🔥 Remove save button
This commit is contained in:
@ -37,7 +37,7 @@ export const GoogleSheetsSettingsBody = ({
|
||||
onOptionsChange,
|
||||
stepId,
|
||||
}: Props) => {
|
||||
const { save, hasUnsavedChanges } = useTypebot()
|
||||
const { save } = useTypebot()
|
||||
const { sheets, isLoading } = useSheets({
|
||||
credentialsId: options?.credentialsId,
|
||||
spreadsheetId: options?.spreadsheetId,
|
||||
@ -83,10 +83,7 @@ export const GoogleSheetsSettingsBody = ({
|
||||
}
|
||||
|
||||
const handleCreateNewClick = async () => {
|
||||
if (hasUnsavedChanges) {
|
||||
const errorToastId = await save()
|
||||
if (errorToastId) return
|
||||
}
|
||||
await save()
|
||||
const linkElement = document.createElement('a')
|
||||
linkElement.href = getGoogleSheetsConsentScreenUrl(
|
||||
window.location.href,
|
||||
|
@ -1,33 +0,0 @@
|
||||
import { IconButton, Text, Tooltip } from '@chakra-ui/react'
|
||||
import { CheckIcon, SaveIcon } from 'assets/icons'
|
||||
import { useTypebot } from 'contexts/TypebotContext/TypebotContext'
|
||||
import React from 'react'
|
||||
|
||||
export const SaveButton = () => {
|
||||
const { save, isSavingLoading, hasUnsavedChanges } = useTypebot()
|
||||
|
||||
const handleSaveClick = async () => {
|
||||
await save()
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{hasUnsavedChanges && (
|
||||
<Text fontSize="sm" color="gray.500">
|
||||
Unsaved changes
|
||||
</Text>
|
||||
)}
|
||||
<Tooltip label="Save changes">
|
||||
<IconButton
|
||||
isDisabled={!hasUnsavedChanges}
|
||||
onClick={handleSaveClick}
|
||||
isLoading={isSavingLoading}
|
||||
icon={
|
||||
hasUnsavedChanges ? <SaveIcon /> : <CheckIcon color="green.400" />
|
||||
}
|
||||
aria-label={hasUnsavedChanges ? 'Save' : 'Saved'}
|
||||
/>
|
||||
</Tooltip>
|
||||
</>
|
||||
)
|
||||
}
|
@ -1,4 +1,12 @@
|
||||
import { Flex, HStack, Button, IconButton, Tooltip } from '@chakra-ui/react'
|
||||
import {
|
||||
Flex,
|
||||
HStack,
|
||||
Button,
|
||||
IconButton,
|
||||
Tooltip,
|
||||
Spinner,
|
||||
Text,
|
||||
} from '@chakra-ui/react'
|
||||
import { ChevronLeftIcon, RedoIcon, UndoIcon } from 'assets/icons'
|
||||
import { NextChakraLink } from 'components/nextChakra/NextChakraLink'
|
||||
import { RightPanel, useEditor } from 'contexts/EditorContext'
|
||||
@ -7,7 +15,6 @@ import { useRouter } from 'next/router'
|
||||
import React from 'react'
|
||||
import { PublishButton } from '../buttons/PublishButton'
|
||||
import { EditableTypebotName } from './EditableTypebotName'
|
||||
import { SaveButton } from './SaveButton'
|
||||
|
||||
export const headerHeight = 56
|
||||
|
||||
@ -21,7 +28,7 @@ export const TypebotHeader = () => {
|
||||
redo,
|
||||
canUndo,
|
||||
canRedo,
|
||||
publishedTypebot,
|
||||
isSavingLoading,
|
||||
} = useTypebot()
|
||||
const { setRightPanel } = useEditor()
|
||||
|
||||
@ -96,7 +103,13 @@ export const TypebotHeader = () => {
|
||||
</Button>
|
||||
)}
|
||||
</HStack>
|
||||
<Flex pos="absolute" left="1rem" justify="center" align="center">
|
||||
<HStack
|
||||
pos="absolute"
|
||||
left="1rem"
|
||||
justify="center"
|
||||
align="center"
|
||||
spacing="6"
|
||||
>
|
||||
<HStack alignItems="center">
|
||||
<IconButton
|
||||
aria-label="Back"
|
||||
@ -129,10 +142,17 @@ export const TypebotHeader = () => {
|
||||
/>
|
||||
</Tooltip>
|
||||
</HStack>
|
||||
</Flex>
|
||||
{isSavingLoading && (
|
||||
<HStack>
|
||||
<Spinner speed="0.7s" size="sm" color="gray.400" />
|
||||
<Text fontSize="sm" color="gray.400">
|
||||
Saving...
|
||||
</Text>
|
||||
</HStack>
|
||||
)}
|
||||
</HStack>
|
||||
|
||||
<HStack right="40px" pos="absolute">
|
||||
<SaveButton />
|
||||
<Button onClick={handlePreviewClick}>Preview</Button>
|
||||
<PublishButton />
|
||||
</HStack>
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ToastId, useToast } from '@chakra-ui/react'
|
||||
import { useToast } from '@chakra-ui/react'
|
||||
import { PublicTypebot, Settings, Theme, Typebot } from 'models'
|
||||
import { useRouter } from 'next/router'
|
||||
import {
|
||||
@ -32,7 +32,8 @@ import useUndo from 'services/utils/useUndo'
|
||||
import { useDebounce } from 'use-debounce'
|
||||
import { itemsAction, ItemsActions } from './actions/items'
|
||||
import { generate } from 'short-uuid'
|
||||
const autoSaveTimeout = 40000
|
||||
import { deepEqual } from 'fast-equals'
|
||||
const autoSaveTimeout = 10000
|
||||
|
||||
type UpdateTypebotPayload = Partial<{
|
||||
theme: Theme
|
||||
@ -49,9 +50,8 @@ const typebotContext = createContext<
|
||||
publishedTypebot?: PublicTypebot
|
||||
isPublished: boolean
|
||||
isPublishing: boolean
|
||||
hasUnsavedChanges: boolean
|
||||
isSavingLoading: boolean
|
||||
save: () => Promise<ToastId | undefined>
|
||||
save: () => Promise<void>
|
||||
undo: () => void
|
||||
redo: () => void
|
||||
canRedo: boolean
|
||||
@ -93,6 +93,13 @@ export const TypebotContext = ({
|
||||
}),
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
if (!typebot || !localTypebot || deepEqual(typebot, localTypebot)) return
|
||||
if (typebot?.blocks.length === localTypebot?.blocks.length)
|
||||
setLocalTypebot({ ...typebot })
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [typebot])
|
||||
|
||||
const [
|
||||
{ present: localTypebot },
|
||||
{
|
||||
@ -106,12 +113,16 @@ export const TypebotContext = ({
|
||||
] = useUndo<Typebot | undefined>(undefined)
|
||||
|
||||
const saveTypebot = async () => {
|
||||
if (deepEqual(typebot, localTypebot)) return
|
||||
const typebotToSave = currentTypebotRef.current
|
||||
if (!typebotToSave) return
|
||||
setIsSavingLoading(true)
|
||||
const { error } = await updateTypebot(typebotToSave.id, typebotToSave)
|
||||
setIsSavingLoading(false)
|
||||
if (error) return toast({ title: error.name, description: error.message })
|
||||
if (error) {
|
||||
toast({ title: error.name, description: error.message })
|
||||
return
|
||||
}
|
||||
mutate({ typebot: typebotToSave })
|
||||
window.removeEventListener('beforeunload', preventUserFromRefreshing)
|
||||
}
|
||||
@ -130,18 +141,9 @@ export const TypebotContext = ({
|
||||
})
|
||||
}
|
||||
|
||||
const hasUnsavedChanges = useMemo(
|
||||
() =>
|
||||
isDefined(typebot) &&
|
||||
isDefined(localTypebot) &&
|
||||
!checkIfTypebotsAreEqual(localTypebot, typebot),
|
||||
[typebot, localTypebot]
|
||||
)
|
||||
|
||||
useAutoSave({
|
||||
handler: saveTypebot,
|
||||
item: localTypebot,
|
||||
canSave: hasUnsavedChanges,
|
||||
debounceTimeout: autoSaveTimeout,
|
||||
})
|
||||
|
||||
@ -257,7 +259,6 @@ export const TypebotContext = ({
|
||||
value={{
|
||||
typebot: localTypebot,
|
||||
publishedTypebot,
|
||||
hasUnsavedChanges,
|
||||
isSavingLoading,
|
||||
save: saveTypebot,
|
||||
undo,
|
||||
@ -306,18 +307,24 @@ export const useFetchedTypebot = ({
|
||||
const useAutoSave = <T,>({
|
||||
handler,
|
||||
item,
|
||||
canSave,
|
||||
debounceTimeout,
|
||||
}: {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
handler: (item?: T) => Promise<any>
|
||||
item?: T
|
||||
canSave: boolean
|
||||
debounceTimeout: number
|
||||
}) => {
|
||||
const [debouncedItem] = useDebounce(item, debounceTimeout)
|
||||
useEffect(() => {
|
||||
const save = () => handler(item)
|
||||
document.addEventListener('visibilitychange', save)
|
||||
return () => {
|
||||
document.removeEventListener('visibilitychange', save)
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [])
|
||||
return useEffect(() => {
|
||||
if (canSave) handler(item)
|
||||
handler(item)
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [debouncedItem])
|
||||
}
|
||||
|
Reference in New Issue
Block a user