feat: ✨ Add collaboration
This commit is contained in:
@ -19,7 +19,7 @@ import {
|
||||
checkIfTypebotsAreEqual,
|
||||
parseDefaultPublicId,
|
||||
updateTypebot,
|
||||
} from 'services/typebots'
|
||||
} from 'services/typebots/typebots'
|
||||
import { fetcher, preventUserFromRefreshing } from 'services/utils'
|
||||
import useSWR from 'swr'
|
||||
import { isDefined, isNotDefined } from 'utils'
|
||||
@ -33,6 +33,7 @@ import { useDebounce } from 'use-debounce'
|
||||
import { itemsAction, ItemsActions } from './actions/items'
|
||||
import { generate } from 'short-uuid'
|
||||
import { deepEqual } from 'fast-equals'
|
||||
import { User } from 'db'
|
||||
const autoSaveTimeout = 10000
|
||||
|
||||
type UpdateTypebotPayload = Partial<{
|
||||
@ -48,6 +49,8 @@ const typebotContext = createContext<
|
||||
{
|
||||
typebot?: Typebot
|
||||
publishedTypebot?: PublicTypebot
|
||||
owner?: User
|
||||
isReadOnly?: boolean
|
||||
isPublished: boolean
|
||||
isPublishing: boolean
|
||||
isSavingLoading: boolean
|
||||
@ -84,14 +87,16 @@ export const TypebotContext = ({
|
||||
position: 'top-right',
|
||||
status: 'error',
|
||||
})
|
||||
const { typebot, publishedTypebot, isLoading, mutate } = useFetchedTypebot({
|
||||
typebotId,
|
||||
onError: (error) =>
|
||||
toast({
|
||||
title: 'Error while fetching typebot',
|
||||
description: error.message,
|
||||
}),
|
||||
})
|
||||
|
||||
const { typebot, publishedTypebot, owner, isReadOnly, isLoading, mutate } =
|
||||
useFetchedTypebot({
|
||||
typebotId,
|
||||
onError: (error) =>
|
||||
toast({
|
||||
title: 'Error while fetching typebot',
|
||||
description: error.message,
|
||||
}),
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
@ -264,6 +269,8 @@ export const TypebotContext = ({
|
||||
value={{
|
||||
typebot: localTypebot,
|
||||
publishedTypebot,
|
||||
owner,
|
||||
isReadOnly,
|
||||
isSavingLoading,
|
||||
save: saveTypebot,
|
||||
undo,
|
||||
@ -297,13 +304,20 @@ export const useFetchedTypebot = ({
|
||||
onError: (error: Error) => void
|
||||
}) => {
|
||||
const { data, error, mutate } = useSWR<
|
||||
{ typebot: Typebot; publishedTypebot?: PublicTypebot },
|
||||
{
|
||||
typebot: Typebot
|
||||
publishedTypebot?: PublicTypebot
|
||||
owner?: User
|
||||
isReadOnly?: boolean
|
||||
},
|
||||
Error
|
||||
>(`/api/typebots/${typebotId}`, fetcher)
|
||||
if (error) onError(error)
|
||||
return {
|
||||
typebot: data?.typebot,
|
||||
publishedTypebot: data?.publishedTypebot,
|
||||
owner: data?.owner,
|
||||
isReadOnly: data?.isReadOnly,
|
||||
isLoading: !error && !data,
|
||||
mutate,
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import {
|
||||
DraggableStepType,
|
||||
StepIndices,
|
||||
} from 'models'
|
||||
import { parseNewStep } from 'services/typebots'
|
||||
import { parseNewStep } from 'services/typebots/typebots'
|
||||
import { removeEmptyBlocks } from './blocks'
|
||||
import { WritableDraft } from 'immer/dist/types/types-external'
|
||||
import { SetTypebot } from '../TypebotContext'
|
||||
|
@ -7,16 +7,21 @@ import {
|
||||
useEffect,
|
||||
useState,
|
||||
} from 'react'
|
||||
import { TypebotInDashboard } from 'services/typebots'
|
||||
import { TypebotInDashboard } from 'services/typebots/typebots'
|
||||
|
||||
const typebotDndContext = createContext<{
|
||||
draggedTypebot?: TypebotInDashboard
|
||||
setDraggedTypebot: Dispatch<SetStateAction<TypebotInDashboard | undefined>>
|
||||
mouseOverFolderId?: string | null
|
||||
setMouseOverFolderId: Dispatch<SetStateAction<string | undefined | null>>
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
//@ts-ignore
|
||||
}>({})
|
||||
}>({
|
||||
setDraggedTypebot: () => {
|
||||
console.log('Not implemented')
|
||||
},
|
||||
setMouseOverFolderId: () => {
|
||||
console.log('Not implemented')
|
||||
},
|
||||
})
|
||||
|
||||
export const TypebotDndContext = ({ children }: { children: ReactNode }) => {
|
||||
const [draggedTypebot, setDraggedTypebot] = useState<TypebotInDashboard>()
|
||||
|
@ -9,7 +9,7 @@ import {
|
||||
useState,
|
||||
} from 'react'
|
||||
import { isDefined, isNotDefined } from 'utils'
|
||||
import { updateUser as updateUserInDb } from 'services/user'
|
||||
import { updateUser as updateUserInDb } from 'services/user/user'
|
||||
import { useToast } from '@chakra-ui/react'
|
||||
import { deepEqual } from 'fast-equals'
|
||||
import { User } from 'db'
|
||||
@ -56,7 +56,15 @@ export const UserContext = ({ children }: { children: ReactNode }) => {
|
||||
if (!router.isReady) return
|
||||
if (status === 'loading') return
|
||||
if (status === 'unauthenticated' && !isSigningIn())
|
||||
router.replace('/signin')
|
||||
router.replace({
|
||||
pathname: '/signin',
|
||||
query:
|
||||
router.pathname !== '/typebots'
|
||||
? {
|
||||
redirectPath: router.asPath,
|
||||
}
|
||||
: undefined,
|
||||
})
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [status, router])
|
||||
|
||||
|
Reference in New Issue
Block a user