@@ -3,8 +3,10 @@ import { ChevronLeftIcon } from '@/components/icons'
|
||||
import { useTypebotDnd } from '../TypebotDndProvider'
|
||||
import Link from 'next/link'
|
||||
import React, { useMemo } from 'react'
|
||||
import { useI18n } from '@/locales'
|
||||
|
||||
export const BackButton = ({ id }: { id: string | null }) => {
|
||||
const t = useI18n()
|
||||
const { draggedTypebot, setMouseOverFolderId, mouseOverFolderId } =
|
||||
useTypebotDnd()
|
||||
|
||||
@@ -26,7 +28,7 @@ export const BackButton = ({ id }: { id: string | null }) => {
|
||||
onMouseEnter={handleMouseEnter}
|
||||
onMouseLeave={handleMouseLeave}
|
||||
>
|
||||
Back
|
||||
{t('back')}
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3,12 +3,14 @@ import { PlusIcon } from '@/components/icons'
|
||||
import { useRouter } from 'next/router'
|
||||
import { stringify } from 'qs'
|
||||
import React from 'react'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
|
||||
export const CreateBotButton = ({
|
||||
folderId,
|
||||
isFirstBot,
|
||||
...props
|
||||
}: { folderId?: string; isFirstBot: boolean } & ButtonProps) => {
|
||||
const scopedT = useScopedI18n('folders.createTypebotButton')
|
||||
const router = useRouter()
|
||||
|
||||
const handleClick = () =>
|
||||
@@ -39,7 +41,7 @@ export const CreateBotButton = ({
|
||||
textAlign="center"
|
||||
mt="6"
|
||||
>
|
||||
Create a typebot
|
||||
{scopedT('label')}
|
||||
</Text>
|
||||
</VStack>
|
||||
</Button>
|
||||
|
||||
@@ -9,10 +9,12 @@ import {
|
||||
import { useWorkspace } from '@/features/workspace'
|
||||
import { Plan } from 'db'
|
||||
import React from 'react'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
|
||||
type Props = { isLoading: boolean; onClick: () => void }
|
||||
|
||||
export const CreateFolderButton = ({ isLoading, onClick }: Props) => {
|
||||
const scopedT = useScopedI18n('folders.createFolderButton')
|
||||
const { workspace } = useWorkspace()
|
||||
const { isOpen, onOpen, onClose } = useDisclosure()
|
||||
|
||||
@@ -27,7 +29,7 @@ export const CreateFolderButton = ({ isLoading, onClick }: Props) => {
|
||||
isLoading={isLoading}
|
||||
>
|
||||
<HStack>
|
||||
<Text>Create a folder</Text>
|
||||
<Text>{scopedT('label')}</Text>
|
||||
{isFreePlan(workspace) && <LockTag plan={Plan.STARTER} />}
|
||||
</HStack>
|
||||
<ChangePlanModal
|
||||
|
||||
@@ -25,6 +25,7 @@ import React, { useMemo } from 'react'
|
||||
import { deleteFolderQuery } from '../queries/deleteFolderQuery'
|
||||
import { useToast } from '@/hooks/useToast'
|
||||
import { updateFolderQuery } from '../queries/updateFolderQuery'
|
||||
import { useI18n, useScopedI18n } from '@/locales'
|
||||
|
||||
export const FolderButton = ({
|
||||
folder,
|
||||
@@ -35,6 +36,8 @@ export const FolderButton = ({
|
||||
onFolderDeleted: () => void
|
||||
onFolderRenamed: (newName: string) => void
|
||||
}) => {
|
||||
const t = useI18n()
|
||||
const scopedT = useScopedI18n('folders.folderButton')
|
||||
const router = useRouter()
|
||||
const { draggedTypebot, setMouseOverFolderId, mouseOverFolderId } =
|
||||
useTypebotDnd()
|
||||
@@ -49,7 +52,6 @@ export const FolderButton = ({
|
||||
const { error } = await deleteFolderQuery(folder.id)
|
||||
return error
|
||||
? showToast({
|
||||
title: "Couldn't delete the folder",
|
||||
description: error.message,
|
||||
})
|
||||
: onFolderDeleted()
|
||||
@@ -59,7 +61,7 @@ export const FolderButton = ({
|
||||
if (newName === '' || newName === folder.name) return
|
||||
const { error } = await updateFolderQuery(folder.id, { name: newName })
|
||||
return error
|
||||
? showToast({ title: 'An error occured', description: error.message })
|
||||
? showToast({ title: t('errorMessage'), description: error.message })
|
||||
: onFolderRenamed(newName)
|
||||
}
|
||||
|
||||
@@ -106,7 +108,7 @@ export const FolderButton = ({
|
||||
onOpen()
|
||||
}}
|
||||
>
|
||||
Delete
|
||||
{t('delete')}
|
||||
</MenuItem>
|
||||
</MenuList>
|
||||
</Menu>
|
||||
@@ -138,8 +140,9 @@ export const FolderButton = ({
|
||||
confirmButtonLabel={'Delete'}
|
||||
message={
|
||||
<Text>
|
||||
Are you sure you want to delete <strong>{folder.name}</strong>{' '}
|
||||
folder? (Everything inside will be move to your dashboard)
|
||||
{scopedT('deleteConfirmationMessage', {
|
||||
folderName: <strong>{folder.name}</strong>,
|
||||
})}
|
||||
</Text>
|
||||
}
|
||||
title={`Delete ${folder.name}?`}
|
||||
|
||||
@@ -24,12 +24,14 @@ import { CreateFolderButton } from './CreateFolderButton'
|
||||
import { ButtonSkeleton, FolderButton } from './FolderButton'
|
||||
import { TypebotButton } from './TypebotButton'
|
||||
import { TypebotCardOverlay } from './TypebotButtonOverlay'
|
||||
import { useI18n } from '@/locales'
|
||||
|
||||
type Props = { folder: DashboardFolder | null }
|
||||
|
||||
const dragDistanceTolerance = 20
|
||||
|
||||
export const FolderContent = ({ folder }: Props) => {
|
||||
const t = useI18n()
|
||||
const { workspace, currentRole } = useWorkspace()
|
||||
const [isCreatingFolder, setIsCreatingFolder] = useState(false)
|
||||
const {
|
||||
@@ -57,7 +59,9 @@ export const FolderContent = ({ folder }: Props) => {
|
||||
workspaceId: workspace?.id,
|
||||
parentId: folder?.id,
|
||||
onError: (error) => {
|
||||
showToast({ title: "Couldn't fetch folders", description: error.message })
|
||||
showToast({
|
||||
description: error.message,
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
@@ -70,7 +74,6 @@ export const FolderContent = ({ folder }: Props) => {
|
||||
folderId: folder === null ? 'root' : folder.id,
|
||||
onError: (error) => {
|
||||
showToast({
|
||||
title: "Couldn't fetch typebots",
|
||||
description: error.message,
|
||||
})
|
||||
},
|
||||
@@ -94,7 +97,7 @@ export const FolderContent = ({ folder }: Props) => {
|
||||
setIsCreatingFolder(false)
|
||||
if (error)
|
||||
return showToast({
|
||||
title: 'An error occured',
|
||||
title: t('errorMessage'),
|
||||
description: error.message,
|
||||
})
|
||||
if (newFolder) mutateFolders({ folders: [...folders, newFolder] })
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Seo } from '@/components/Seo'
|
||||
import { DashboardHeader } from '@/features/dashboard'
|
||||
import { useToast } from '@/hooks/useToast'
|
||||
import { useI18n } from '@/locales'
|
||||
import { Stack, Flex, Spinner } from '@chakra-ui/react'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useFolder } from '../hooks/useFolder'
|
||||
@@ -8,6 +9,7 @@ import { TypebotDndProvider } from '../TypebotDndProvider'
|
||||
import { FolderContent } from './FolderContent'
|
||||
|
||||
export const FolderPage = () => {
|
||||
const t = useI18n()
|
||||
const router = useRouter()
|
||||
|
||||
const { showToast } = useToast()
|
||||
@@ -16,7 +18,6 @@ export const FolderPage = () => {
|
||||
folderId: router.query.id?.toString(),
|
||||
onError: (error) => {
|
||||
showToast({
|
||||
title: "Couldn't fetch folder content",
|
||||
description: error.message,
|
||||
})
|
||||
},
|
||||
@@ -24,7 +25,7 @@ export const FolderPage = () => {
|
||||
|
||||
return (
|
||||
<Stack minH="100vh">
|
||||
<Seo title="My typebots" />
|
||||
<Seo title={t('dashboard.title')} />
|
||||
<DashboardHeader />
|
||||
<TypebotDndProvider>
|
||||
{!folder ? (
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import React from 'react'
|
||||
import {
|
||||
Alert,
|
||||
AlertIcon,
|
||||
Button,
|
||||
Flex,
|
||||
IconButton,
|
||||
MenuItem,
|
||||
Stack,
|
||||
Tag,
|
||||
Text,
|
||||
useDisclosure,
|
||||
@@ -28,6 +31,7 @@ import {
|
||||
import { MoreButton } from './MoreButton'
|
||||
import { EmojiOrImageIcon } from '@/components/EmojiOrImageIcon'
|
||||
import { deletePublishedTypebotQuery } from '@/features/publish/queries/deletePublishedTypebotQuery'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
|
||||
type Props = {
|
||||
typebot: TypebotInDashboard
|
||||
@@ -42,6 +46,7 @@ export const TypebotButton = ({
|
||||
onTypebotUpdated,
|
||||
onMouseDown,
|
||||
}: Props) => {
|
||||
const scopedT = useScopedI18n('folders.typebotButton')
|
||||
const router = useRouter()
|
||||
const { workspace } = useWorkspace()
|
||||
const { draggedTypebot } = useTypebotDnd()
|
||||
@@ -68,7 +73,6 @@ export const TypebotButton = ({
|
||||
const { error } = await deleteTypebotQuery(typebot.id)
|
||||
if (error)
|
||||
return showToast({
|
||||
title: "Couldn't delete typebot",
|
||||
description: error.message,
|
||||
})
|
||||
onTypebotUpdated()
|
||||
@@ -78,14 +82,13 @@ export const TypebotButton = ({
|
||||
e.stopPropagation()
|
||||
const { data } = await getTypebotQuery(typebot.id)
|
||||
const typebotToDuplicate = data?.typebot
|
||||
if (!typebotToDuplicate) return { error: new Error('Typebot not found') }
|
||||
if (!typebotToDuplicate) return
|
||||
const { data: createdTypebot, error } = await importTypebotQuery(
|
||||
data.typebot,
|
||||
workspace?.plan ?? Plan.FREE
|
||||
)
|
||||
if (error)
|
||||
return showToast({
|
||||
title: "Couldn't duplicate typebot",
|
||||
description: error.message,
|
||||
})
|
||||
if (createdTypebot) router.push(`/typebots/${createdTypebot?.id}/edit`)
|
||||
@@ -153,14 +156,18 @@ export const TypebotButton = ({
|
||||
pos="absolute"
|
||||
top="20px"
|
||||
right="20px"
|
||||
aria-label={`Show ${typebot.name} menu`}
|
||||
aria-label={scopedT('showMoreOptions')}
|
||||
>
|
||||
{typebot.publishedTypebotId && (
|
||||
<MenuItem onClick={handleUnpublishClick}>Unpublish</MenuItem>
|
||||
<MenuItem onClick={handleUnpublishClick}>
|
||||
{scopedT('unpublish')}
|
||||
</MenuItem>
|
||||
)}
|
||||
<MenuItem onClick={handleDuplicateClick}>Duplicate</MenuItem>
|
||||
<MenuItem onClick={handleDuplicateClick}>
|
||||
{scopedT('duplicate')}
|
||||
</MenuItem>
|
||||
<MenuItem color="red.400" onClick={handleDeleteClick}>
|
||||
Delete
|
||||
{scopedT('delete')}
|
||||
</MenuItem>
|
||||
</MoreButton>
|
||||
</>
|
||||
@@ -181,12 +188,17 @@ export const TypebotButton = ({
|
||||
{!isReadOnly && (
|
||||
<ConfirmModal
|
||||
message={
|
||||
<Text>
|
||||
Are you sure you want to delete your Typebot "{typebot.name}
|
||||
".
|
||||
<br />
|
||||
All associated data will be lost.
|
||||
</Text>
|
||||
<Stack spacing="4">
|
||||
<Text>
|
||||
{scopedT('deleteConfirmationMessage', {
|
||||
typebotName: <strong>{typebot.name}</strong>,
|
||||
})}
|
||||
</Text>
|
||||
<Alert status="warning">
|
||||
<AlertIcon />
|
||||
{scopedT('deleteConfirmationMessageWarning')}
|
||||
</Alert>
|
||||
</Stack>
|
||||
}
|
||||
confirmButtonLabel="Delete"
|
||||
onConfirm={handleDeleteTypebotClick}
|
||||
|
||||
Reference in New Issue
Block a user