feat(editor): ✨ Restore published version button
Had to migrate webhooks into a standalone table
This commit is contained in:
@ -1,17 +1,16 @@
|
||||
import { Block, PublicBlock, PublicStep, PublicTypebot, Typebot } from 'models'
|
||||
import { PublicTypebot, Typebot } from 'models'
|
||||
import shortId from 'short-uuid'
|
||||
import { HStack, Text } from '@chakra-ui/react'
|
||||
import { CalendarIcon, CodeIcon } from 'assets/icons'
|
||||
import { StepIcon } from 'components/editor/StepsSideBar/StepIcon'
|
||||
import { byId, isInputStep, sendRequest } from 'utils'
|
||||
import { isDefined } from '@udecode/plate-common'
|
||||
|
||||
export const parseTypebotToPublicTypebot = (
|
||||
typebot: Typebot
|
||||
): PublicTypebot => ({
|
||||
id: shortId.generate(),
|
||||
typebotId: typebot.id,
|
||||
blocks: parseBlocksToPublicBlocks(typebot.blocks),
|
||||
blocks: typebot.blocks,
|
||||
edges: typebot.edges,
|
||||
name: typebot.name,
|
||||
publicId: typebot.publicId,
|
||||
@ -19,18 +18,29 @@ export const parseTypebotToPublicTypebot = (
|
||||
theme: typebot.theme,
|
||||
variables: typebot.variables,
|
||||
customDomain: typebot.customDomain,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
})
|
||||
|
||||
export const parseBlocksToPublicBlocks = (blocks: Block[]): PublicBlock[] =>
|
||||
blocks.map((b) => ({
|
||||
...b,
|
||||
steps: b.steps.map(
|
||||
(s) =>
|
||||
('webhook' in s && isDefined(s.webhook)
|
||||
? { ...s, webhook: s.webhook.id }
|
||||
: s) as PublicStep
|
||||
),
|
||||
}))
|
||||
export const parsePublicTypebotToTypebot = (
|
||||
typebot: PublicTypebot,
|
||||
existingTypebot: Typebot
|
||||
): Typebot => ({
|
||||
id: typebot.typebotId,
|
||||
blocks: typebot.blocks,
|
||||
edges: typebot.edges,
|
||||
name: typebot.name,
|
||||
publicId: typebot.publicId,
|
||||
settings: typebot.settings,
|
||||
theme: typebot.theme,
|
||||
variables: typebot.variables,
|
||||
customDomain: typebot.customDomain,
|
||||
createdAt: existingTypebot.createdAt,
|
||||
updatedAt: existingTypebot.updatedAt,
|
||||
publishedTypebotId: typebot.id,
|
||||
folderId: existingTypebot.folderId,
|
||||
ownerId: existingTypebot.ownerId,
|
||||
})
|
||||
|
||||
export const createPublishedTypebot = async (typebot: PublicTypebot) =>
|
||||
sendRequest<PublicTypebot>({
|
||||
|
@ -29,8 +29,6 @@ import {
|
||||
defaultGoogleAnalyticsOptions,
|
||||
defaultWebhookOptions,
|
||||
StepWithOptionsType,
|
||||
defaultWebhookAttributes,
|
||||
Webhook,
|
||||
Item,
|
||||
ItemType,
|
||||
defaultConditionContent,
|
||||
@ -39,7 +37,7 @@ import {
|
||||
import shortId, { generate } from 'short-uuid'
|
||||
import { Typebot } from 'models'
|
||||
import useSWR from 'swr'
|
||||
import { fetcher, omit, toKebabCase } from '../utils'
|
||||
import { fetcher, toKebabCase } from '../utils'
|
||||
import {
|
||||
isBubbleStepType,
|
||||
stepTypeHasItems,
|
||||
@ -48,8 +46,8 @@ import {
|
||||
} from 'utils'
|
||||
import { deepEqual } from 'fast-equals'
|
||||
import { stringify } from 'qs'
|
||||
import { isChoiceInput, isConditionStep, sendRequest } from 'utils'
|
||||
import { parseBlocksToPublicBlocks } from '../publicTypebot'
|
||||
import { isChoiceInput, isConditionStep, sendRequest, omit } from 'utils'
|
||||
import cuid from 'cuid'
|
||||
|
||||
export type TypebotInDashboard = Pick<
|
||||
Typebot,
|
||||
@ -173,16 +171,11 @@ export const parseNewStep = (
|
||||
options: stepTypeHasOption(type)
|
||||
? parseDefaultStepOptions(type)
|
||||
: undefined,
|
||||
webhook: stepTypeHasWebhook(type) ? parseDefaultWebhook() : undefined,
|
||||
webhookId: stepTypeHasWebhook(type) ? cuid() : undefined,
|
||||
items: stepTypeHasItems(type) ? parseDefaultItems(type, id) : undefined,
|
||||
} as DraggableStep
|
||||
}
|
||||
|
||||
const parseDefaultWebhook = (): Webhook => ({
|
||||
id: generate(),
|
||||
...defaultWebhookAttributes,
|
||||
})
|
||||
|
||||
const parseDefaultItems = (
|
||||
type: LogicStepType.CONDITION | InputStepType.CHOICE,
|
||||
stepId: string
|
||||
@ -255,7 +248,7 @@ export const checkIfPublished = (
|
||||
typebot: Typebot,
|
||||
publicTypebot: PublicTypebot
|
||||
) =>
|
||||
deepEqual(parseBlocksToPublicBlocks(typebot.blocks), publicTypebot.blocks) &&
|
||||
deepEqual(typebot.blocks, publicTypebot.blocks) &&
|
||||
deepEqual(typebot.settings, publicTypebot.settings) &&
|
||||
deepEqual(typebot.theme, publicTypebot.theme) &&
|
||||
deepEqual(typebot.variables, publicTypebot.variables)
|
||||
|
@ -1,6 +1,6 @@
|
||||
import imageCompression from 'browser-image-compression'
|
||||
import { Parser } from 'htmlparser2'
|
||||
import { PublicStep, Step, Typebot } from 'models'
|
||||
import { Step, Typebot } from 'models'
|
||||
|
||||
export const fetcher = async (input: RequestInfo, init?: RequestInit) => {
|
||||
const res = await fetch(input, init)
|
||||
@ -36,26 +36,6 @@ export const toKebabCase = (value: string) => {
|
||||
return matched.map((x) => x.toLowerCase()).join('-')
|
||||
}
|
||||
|
||||
interface Omit {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
<T extends object, K extends [...(keyof T)[]]>(obj: T, ...keys: K): {
|
||||
[K2 in Exclude<keyof T, K[number]>]: T[K2]
|
||||
}
|
||||
}
|
||||
|
||||
export const omit: Omit = (obj, ...keys) => {
|
||||
const ret = {} as {
|
||||
[K in keyof typeof obj]: typeof obj[K]
|
||||
}
|
||||
let key: keyof typeof obj
|
||||
for (key in obj) {
|
||||
if (!keys.includes(key)) {
|
||||
ret[key] = obj[key]
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
export const uploadFile = async (file: File, key: string) => {
|
||||
const res = await fetch(
|
||||
`/api/storage/upload-url?key=${encodeURIComponent(
|
||||
@ -98,7 +78,7 @@ export const removeUndefinedFields = <T>(obj: T): T =>
|
||||
{} as T
|
||||
)
|
||||
|
||||
export const stepHasOptions = (step: Step | PublicStep) => 'options' in step
|
||||
export const stepHasOptions = (step: Step) => 'options' in step
|
||||
|
||||
export const parseVariableHighlight = (content: string, typebot: Typebot) => {
|
||||
const varNames = typebot.variables.map((v) => v.name)
|
||||
@ -128,3 +108,32 @@ export const readFile = (file: File): Promise<string> => {
|
||||
fr.readAsText(file)
|
||||
})
|
||||
}
|
||||
|
||||
export const timeSince = (date: string) => {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
//@ts-ignore
|
||||
const seconds = Math.floor((new Date() - new Date(date)) / 1000)
|
||||
|
||||
let interval = seconds / 31536000
|
||||
|
||||
if (interval > 1) {
|
||||
return Math.floor(interval) + ' years'
|
||||
}
|
||||
interval = seconds / 2592000
|
||||
if (interval > 1) {
|
||||
return Math.floor(interval) + ' months'
|
||||
}
|
||||
interval = seconds / 86400
|
||||
if (interval > 1) {
|
||||
return Math.floor(interval) + ' days'
|
||||
}
|
||||
interval = seconds / 3600
|
||||
if (interval > 1) {
|
||||
return Math.floor(interval) + ' hours'
|
||||
}
|
||||
interval = seconds / 60
|
||||
if (interval > 1) {
|
||||
return Math.floor(interval) + ' minutes'
|
||||
}
|
||||
return Math.floor(seconds) + ' seconds'
|
||||
}
|
||||
|
9
apps/builder/services/webhook.ts
Normal file
9
apps/builder/services/webhook.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { Webhook } from 'models'
|
||||
import { sendRequest } from 'utils'
|
||||
|
||||
export const saveWebhook = (webhookId: string, webhook: Partial<Webhook>) =>
|
||||
sendRequest<{ webhook: Webhook }>({
|
||||
method: 'PUT',
|
||||
url: `/api/webhooks/${webhookId}`,
|
||||
body: webhook,
|
||||
})
|
Reference in New Issue
Block a user