2
0

Add editor header translation keys (#1110)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Implemented internationalization support across various components
using the `useTranslate` function for dynamic content translation.

- **Enhancements**
- Updated UI elements such as buttons, tooltips, placeholders, and
labels to display translated text, improving accessibility and user
experience for non-English speakers.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Baptiste Arnaud <contact@baptiste-arnaud.fr>
Co-authored-by: Baptiste Arnaud <baptiste.arnaud95@gmail.com>
This commit is contained in:
Gabriel Pavão
2023-12-28 06:50:33 -03:00
committed by GitHub
parent 74f5a17de0
commit d42e4a9ce1
38 changed files with 520 additions and 199 deletions

View File

@ -1,4 +1,4 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
pnpm lint
pnpm lint && pnpm format:fix

View File

@ -0,0 +1,2 @@
emojiList.json
iconNames.ts

View File

@ -8,7 +8,8 @@
"start": "dotenv -e ./.env -e ../../.env -- next start",
"lint": "dotenv -e ./.env -e ../../.env -- next lint",
"test": "dotenv -e ./.env -e ../../.env -- pnpm playwright test",
"test:show-report": "pnpm playwright show-report src/test/reporters"
"test:show-report": "pnpm playwright show-report src/test/reporters",
"format:fix": "prettier --write ./src"
},
"dependencies": {
"@chakra-ui/anatomy": "2.1.1",

View File

@ -150,14 +150,14 @@
"editor.gettingStartedModal.seeAction.item.label": "Weitere Videos",
"editor.gettingStartedModal.seeAction.label": "In Aktion sehen",
"editor.gettingStartedModal.seeAction.time": "5 Minuten",
"editor.headers.flowButton.label": "Ablauf",
"editor.headers.helpButton.label": "Hilfe",
"editor.headers.previewButton.label": "Vorschau",
"editor.headers.resultsButton.label": "Ergebnisse",
"editor.headers.savingSpinner.label": "Speichern...",
"editor.headers.settingsButton.label": "Einstellungen",
"editor.headers.shareButton.label": "Teilen",
"editor.headers.themeButton.label": "Design",
"editor.header.flowButton.label": "Ablauf",
"editor.header.helpButton.label": "Hilfe",
"editor.header.previewButton.label": "Vorschau",
"editor.header.resultsButton.label": "Ergebnisse",
"editor.header.savingSpinner.label": "Speichern...",
"editor.header.settingsButton.label": "Einstellungen",
"share.button.label": "Teilen",
"editor.header.themeButton.label": "Design",
"editor.sidebarBlock.abTest.label": "AB-Test",
"editor.sidebarBlock.analytics.label": "Analytics",
"editor.sidebarBlock.audio.label": "Audio",

View File

@ -117,7 +117,24 @@
"blocks.integrations.googleSheets.blockCard.tooltip": "Google Sheets",
"cancel": "Cancel",
"clickToEdit": "Click to edit...",
"collaboration.roles.edit.label": "Can edit",
"collaboration.roles.full.label": "Full access",
"collaboration.roles.view.label": "Can view",
"confirmModal.defaultTitle": "Are you sure?",
"emojiList.categories.activities.label": "ACTIVITIES",
"emojiList.categories.animalsAndNature.label": "ANIMALS & NATURE",
"emojiList.categories.flags.label": "FLAGS",
"emojiList.categories.foodAndDrink.label": "FOOD & DRINK",
"emojiList.categories.objects.label": "OBJECTS",
"emojiList.categories.people.label": "PEOPLE",
"emojiList.categories.recent.label": "RECENT",
"emojiList.categories.symbols.label": "SYMBOLS",
"emojiList.categories.travelAndPlaces.label": "TRAVEL & PLACES",
"emojiList.searchInput.placeholder": "Search...",
"variables.button.tooltip": "Insert a variable",
"variables.button.searchInput.placeholder": "Search for a variable",
"copy": "Copy",
"copied": "Copied",
"dashboard.header.settingsButton.label": "Settings & Members",
"dashboard.redirectionMessage": "You are being redirected...",
"dashboard.title": "My typebots",
@ -140,7 +157,13 @@
"editor.blocks.bubbles.image.switchWithLabel.onClick.placeholder": "Link alt text (description)",
"editor.blocks.bubbles.textEditor.plate.label": "Text editor",
"editor.blocks.bubbles.textEditor.searchVariable.placeholder": "Search for a variable",
"editor.graph.menu.documentationItem.label": "Documentation",
"editor.graph.menu.editorSettingsItem.label": "Editor settings",
"editor.graph.menu.exportFlowItem.label": "Export flow",
"editor.blocks.start.text": "Start",
"editor.header.linkTab.searchInputPlaceholder.label": "Paste the image link...",
"editor.header.tooltip.changeIcon.label": "Change icon",
"editor.header.uploadTab.uploadButton.label": "Choose an image",
"editor.editableTypebotName.tooltip.rename.label": "Rename",
"editor.gettingStartedModal.editorBasics.heading": "Editor Basics",
"editor.gettingStartedModal.editorBasics.list.four.label": "Preview your bot by clicking the test button on the top right",
@ -151,14 +174,42 @@
"editor.gettingStartedModal.seeAction.item.label": "Other videos",
"editor.gettingStartedModal.seeAction.label": "See it in action",
"editor.gettingStartedModal.seeAction.time": "5 minutes",
"editor.headers.flowButton.label": "Flow",
"editor.headers.helpButton.label": "Help",
"editor.headers.previewButton.label": "Test",
"editor.headers.resultsButton.label": "Results",
"editor.headers.savingSpinner.label": "Saving...",
"editor.headers.settingsButton.label": "Settings",
"editor.headers.shareButton.label": "Share",
"editor.headers.themeButton.label": "Theme",
"editor.header.flowButton.label": "Flow",
"editor.header.helpButton.label": "Help",
"editor.header.previewButton.label": "Test",
"publishButton.closed.label": "Closed",
"publishButton.label": "Publish",
"publishButton.tooltip.nonPublishedChanges.label": "There are non published changes.",
"publishButton.tooltip.publishedVersion.from.label": "Published version from",
"publishButton.tooltip.publishedVersion.ago.label": "ago",
"publishButton.published.label": "Published",
"publishButton.dropdown.close.label": "Close typebot to new responses",
"publishButton.dropdown.reopen.label": "Reopen typebot to new responses",
"publishButton.dropdown.showMenu.label": "Show published typebot menu",
"publishButton.dropdown.unpublish.label": "Unpublish typebot",
"publish.versionWarning.title.label": "⚠️ New engine version",
"publish.versionWarning.message.aboutToDeploy.label": "You are about to a deploy a version of your bot with an updated engine. (Typebot V6).",
"publish.versionWarning.message.check.label": "Make sure to check out all the",
"publish.versionWarning.message.breakingChanges.label": "associated breaking changes",
"publish.versionWarning.message.testInPreviewMode.label": "Then test, the bot thoroughly in preview mode before publishing.",
"publish.error.label": "Error while publishing typebot",
"publishButton.dropdown.restoreVersion.label": "Restore published version",
"editor.header.redoButton.label": "Redo",
"editor.header.resultsButton.label": "Results",
"editor.header.savingSpinner.label": "Saving...",
"editor.header.settingsButton.label": "Settings",
"share.button.label": "Share",
"share.button.popover.ariaLabel": "Open share popover",
"share.button.popover.collaboratorsFetch.error.label": "Couldn't fetch collaborators",
"share.button.popover.invitationsFetch.error.label": "Couldn't fetch invitations",
"share.button.popover.invitationSent.successToast.label": "Invitation sent! 📧",
"share.button.popover.inviteButton.label": "Invite",
"share.button.popover.inviteInput.placeholder": "colleague@company.com",
"share.button.popover.publicFlow.label": "Make the flow publicly available",
"editor.header.themeButton.label": "Theme",
"editor.header.undo.tooltip.label": "Changes reverted!",
"editor.header.undoButton.label": "Undo",
"editor.header.unpublishTypebot.error.label": "Error while unpublishing typebot",
"editor.sidebarBlock.abTest.label": "AB Test",
"editor.sidebarBlock.analytics.label": "Analytics",
"editor.sidebarBlock.audio.label": "Audio",
@ -213,6 +264,7 @@
"folders.typebotButton.showMoreOptions": "Show more options",
"folders.typebotButton.unpublish": "Unpublish",
"pending": "Pending",
"preview.restartButton.label": "Restart",
"remove": "Remove",
"skip": "Skip",
"templates.buttons.fromScratchButton.label": "Start from scratch",

View File

@ -151,14 +151,14 @@
"editor.gettingStartedModal.seeAction.item.label": "Otros videos",
"editor.gettingStartedModal.seeAction.label": "Verlo en acción",
"editor.gettingStartedModal.seeAction.time": "5 minutos",
"editor.headers.flowButton.label": "Flujo",
"editor.headers.helpButton.label": "Ayuda",
"editor.headers.previewButton.label": "Previsualización",
"editor.headers.resultsButton.label": "Resultados",
"editor.headers.savingSpinner.label": "Guardando...",
"editor.headers.settingsButton.label": "Configuración",
"editor.headers.shareButton.label": "Compartir",
"editor.headers.themeButton.label": "Tema",
"editor.header.flowButton.label": "Flujo",
"editor.header.helpButton.label": "Ayuda",
"editor.header.previewButton.label": "Previsualización",
"editor.header.resultsButton.label": "Resultados",
"editor.header.savingSpinner.label": "Guardando...",
"editor.header.settingsButton.label": "Configuración",
"share.button.label": "Compartir",
"editor.header.themeButton.label": "Tema",
"editor.sidebarBlock.abTest.label": "Prueba A/B",
"editor.sidebarBlock.analytics.label": "Análisis",
"editor.sidebarBlock.audio.label": "Audio",

View File

@ -151,14 +151,14 @@
"editor.gettingStartedModal.seeAction.item.label": "Autres vidéos",
"editor.gettingStartedModal.seeAction.label": "Voir en action",
"editor.gettingStartedModal.seeAction.time": "5 minutes",
"editor.headers.flowButton.label": "Flow",
"editor.headers.helpButton.label": "Aide",
"editor.headers.previewButton.label": "Tester",
"editor.headers.resultsButton.label": "Résultats",
"editor.headers.savingSpinner.label": "Enregistrement...",
"editor.headers.settingsButton.label": "Paramètres",
"editor.headers.shareButton.label": "Partage",
"editor.headers.themeButton.label": "Thème",
"editor.header.flowButton.label": "Flow",
"editor.header.helpButton.label": "Aide",
"editor.header.previewButton.label": "Tester",
"editor.header.resultsButton.label": "Résultats",
"editor.header.savingSpinner.label": "Enregistrement...",
"editor.header.settingsButton.label": "Paramètres",
"share.button.label": "Partage",
"editor.header.themeButton.label": "Thème",
"editor.sidebarBlock.abTest.label": "AB Test",
"editor.sidebarBlock.analytics.label": "Analytics",
"editor.sidebarBlock.audio.label": "Audio",

View File

@ -117,7 +117,24 @@
"blocks.integrations.googleSheets.blockCard.tooltip": "Google Sheets",
"cancel": "Cancelar",
"clickToEdit": "Clique para editar...",
"collaboration.roles.edit.label": "Pode editar",
"collaboration.roles.full.label": "Acesso Total",
"collaboration.roles.view.label": "Pode ver",
"confirmModal.defaultTitle": "Tem certeza?",
"emojiList.categories.activities.label": "ATIVIDADES",
"emojiList.categories.animalsAndNature.label": "ANIMAIS & NATUREZA",
"emojiList.categories.flags.label": "BANDEIRAS",
"emojiList.categories.foodAndDrink.label": "COMIDA & BEBIDA",
"emojiList.categories.objects.label": "OBJETOS",
"emojiList.categories.people.label": "PESSOAS",
"emojiList.categories.recent.label": "RECENTE",
"emojiList.categories.symbols.label": "SÍMBOLOS",
"emojiList.categories.travelAndPlaces.label": "VIAJEM E LUGARES",
"emojiList.searchInput.placeholder": "Buscar...",
"variables.button.tooltip": "Insira uma variável",
"variables.button.searchInput.placeholder": "Procure por uma variável",
"copy": "Copiar",
"copied": "Copiado",
"dashboard.header.settingsButton.label": "Configurações & Membros",
"dashboard.redirectionMessage": "Você está sendo redirecionado...",
"dashboard.title": "Meus typebots",
@ -140,7 +157,13 @@
"editor.blocks.bubbles.image.switchWithLabel.onClick.placeholder": "Texto alternativo do link (descrição)",
"editor.blocks.bubbles.textEditor.plate.label": "Editor de texto",
"editor.blocks.bubbles.textEditor.searchVariable.placeholder": "Pesquisar uma variável",
"editor.graph.menu.documentationItem.label": "Documentação",
"editor.graph.menu.editorSettingsItem.label": "Configurações do editor",
"editor.graph.menu.exportFlowItem.label": "Exportar fluxo",
"editor.blocks.start.text": "Início",
"editor.header.linkTab.searchInputPlaceholder.label": "Cole o link da imagem...",
"editor.header.tooltip.changeIcon.label": "Alterar Ícone",
"editor.header.uploadTab.uploadButton.label": "Escolha uma imagem",
"editor.editableTypebotName.tooltip.rename.label": "Renomear",
"editor.gettingStartedModal.editorBasics.heading": "Fundamentos do Editor",
"editor.gettingStartedModal.editorBasics.list.four.label": "Pré-visualize o seu bot ao clicar no botão de visualizar no canto superior direito",
@ -151,14 +174,42 @@
"editor.gettingStartedModal.seeAction.item.label": "Outros vídeos",
"editor.gettingStartedModal.seeAction.label": "Veja como funciona em",
"editor.gettingStartedModal.seeAction.time": "5 minutos",
"editor.headers.flowButton.label": "Fluxo",
"editor.headers.helpButton.label": "Ajuda",
"editor.headers.previewButton.label": "Visualizar",
"editor.headers.resultsButton.label": "Resultados",
"editor.headers.savingSpinner.label": "Salvando...",
"editor.headers.settingsButton.label": "Configurações",
"editor.headers.shareButton.label": "Compartilhar",
"editor.headers.themeButton.label": "Tema",
"editor.header.flowButton.label": "Fluxo",
"editor.header.helpButton.label": "Ajuda",
"editor.header.previewButton.label": "Visualizar",
"publishButton.label": "Publicar",
"publishButton.closed.label": "Fechado",
"publishButton.tooltip.nonPublishedChanges.label": "Existem alterações não publicadas.",
"publishButton.tooltip.publishedVersion.from.label": "Versão publicada de",
"publishButton.tooltip.publishedVersion.ago.label": "atrás",
"publishButton.published.label": "Publicado",
"publishButton.dropdown.close.label": "Fechar typebot para novas respostas",
"publishButton.dropdown.reopen.label": "Reabrir typebot para novas respostas",
"publishButton.dropdown.showMenu.label": "Mostrar menu de typebot publicado",
"publishButton.dropdown.unpublish.label": "Despublicar typebot",
"publish.versionWarning.title.label": "⚠️ Nova versão da engine",
"publish.versionWarning.message.aboutToDeploy.label": "Você está prestes a fazer o deploy de uma versão do seu bot com uma engine atualizada. (Typebot V6).",
"publish.versionWarning.message.check.label": "Assegure-se de verificar todos as",
"publish.versionWarning.message.breakingChanges.label": "significativas alterações associadas",
"publish.versionWarning.message.testInPreviewMode.label": "Em seguida, teste o bot completamente no modo de visualização antes de publicar.",
"publish.error.label": "Erro durante a publicação do typebot",
"publishButton.dropdown.restoreVersion.label": "Restaurar versão publicada",
"editor.header.redoButton.label": "Refazer",
"editor.header.resultsButton.label": "Resultados",
"editor.header.savingSpinner.label": "Salvando...",
"editor.header.settingsButton.label": "Configurações",
"share.button.label": "Compartilhar",
"share.button.popover.ariaLabel": "Abrir popover de compartilhamento",
"share.button.popover.collaboratorsFetch.error.label": "Falha ao buscar os colaboradores",
"share.button.popover.invitationsFetch.error.label": "Falha ao buscar os convites",
"share.button.popover.invitationSent.successToast.label": "Convite enviado! 📧",
"share.button.popover.inviteButton.label": "Convidar",
"share.button.popover.inviteInput.placeholder": "colega@empresa.com",
"share.button.popover.publicFlow.label": "Disponibilizar o fluxo publicamente",
"editor.header.themeButton.label": "Tema",
"editor.header.undo.tooltip.label": "Alterações revertidas Changes reverted!",
"editor.header.undoButton.label": "Desfazer",
"editor.header.unpublishTypebot.error.label": "Erro durante a despublicação do typebot",
"editor.sidebarBlock.abTest.label": "Teste AB",
"editor.sidebarBlock.analytics.label": "Analytics",
"editor.sidebarBlock.audio.label": "Áudio",
@ -213,6 +264,7 @@
"folders.typebotButton.showMoreOptions": "Mostrar mais opções",
"folders.typebotButton.unpublish": "Despublicar",
"pending": "Pendente",
"preview.restartButton.label": "Reiniciar",
"remove": "Remover",
"skip": "Pular",
"templates.buttons.fromScratchButton.label": "Comece do zero",

View File

@ -151,14 +151,14 @@
"editor.gettingStartedModal.seeAction.item.label": "Outros vídeos",
"editor.gettingStartedModal.seeAction.label": "Veja o funcionamento em",
"editor.gettingStartedModal.seeAction.time": "5 minutos",
"editor.headers.flowButton.label": "Fluxo",
"editor.headers.helpButton.label": "Ajuda",
"editor.headers.previewButton.label": "Visualizar",
"editor.headers.resultsButton.label": "Resultados",
"editor.headers.savingSpinner.label": "Salvando...",
"editor.headers.settingsButton.label": "Configurações",
"editor.headers.shareButton.label": "Compartilhar",
"editor.headers.themeButton.label": "Tema",
"editor.header.flowButton.label": "Fluxo",
"editor.header.helpButton.label": "Ajuda",
"editor.header.previewButton.label": "Visualizar",
"editor.header.resultsButton.label": "Resultados",
"editor.header.savingSpinner.label": "Salvando...",
"editor.header.settingsButton.label": "Configurações",
"share.button.label": "Compartilhar",
"editor.header.themeButton.label": "Tema",
"editor.sidebarBlock.abTest.label": "Teste AB",
"editor.sidebarBlock.analytics.label": "Analytics",
"editor.sidebarBlock.audio.label": "Áudio",

View File

@ -151,14 +151,14 @@
"editor.gettingStartedModal.seeAction.item.label": "Alte videoclipuri",
"editor.gettingStartedModal.seeAction.label": "Vedeți-l în acțiune",
"editor.gettingStartedModal.seeAction.time": "5 minute",
"editor.headers.flowButton.label": "curgere",
"editor.headers.helpButton.label": "Ajutor",
"editor.headers.previewButton.label": "previzualizare",
"editor.headers.resultsButton.label": "Rezultate",
"editor.headers.savingSpinner.label": "Salvare...",
"editor.headers.settingsButton.label": "Setări",
"editor.headers.shareButton.label": "Acțiune",
"editor.headers.themeButton.label": "Temă",
"editor.header.flowButton.label": "curgere",
"editor.header.helpButton.label": "Ajutor",
"editor.header.previewButton.label": "previzualizare",
"editor.header.resultsButton.label": "Rezultate",
"editor.header.savingSpinner.label": "Salvare...",
"editor.header.settingsButton.label": "Setări",
"share.button.label": "Acțiune",
"editor.header.themeButton.label": "Temă",
"editor.sidebarBlock.abTest.label": "Testul AB",
"editor.sidebarBlock.analytics.label": "Analitica",
"editor.sidebarBlock.audio.label": "Audio",

View File

@ -1,5 +1,6 @@
import React, { useEffect } from 'react'
import { ButtonProps, Button, useClipboard } from '@chakra-ui/react'
import { useTranslate } from '@tolgee/react'
interface CopyButtonProps extends ButtonProps {
textToCopy: string
@ -13,6 +14,7 @@ interface CopyButtonProps extends ButtonProps {
export const CopyButton = (props: CopyButtonProps) => {
const { textToCopy, onCopied, ...buttonProps } = props
const { hasCopied, onCopy, setValue } = useClipboard(textToCopy)
const { t } = useTranslate()
useEffect(() => {
setValue(textToCopy)
@ -27,7 +29,9 @@ export const CopyButton = (props: CopyButtonProps) => {
}}
{...buttonProps}
>
{!hasCopied ? props.text?.copy ?? 'Copy' : props.text?.copied ?? 'Copied'}
{!hasCopied
? props.text?.copy ?? t('copy')
: props.text?.copied ?? t('copied')}
</Button>
)
}

View File

@ -11,6 +11,7 @@ import React from 'react'
import { EmojiOrImageIcon } from './EmojiOrImageIcon'
import { ImageUploadContent } from './ImageUploadContent'
import { FilePathUploadProps } from '@/features/upload/api/generateUploadUrl'
import { useTranslate } from '@tolgee/react'
type Props = {
uploadFileProps: FilePathUploadProps
@ -25,13 +26,14 @@ export const EditableEmojiOrImageIcon = ({
onChangeIcon,
boxSize,
}: Props) => {
const { t } = useTranslate()
const bg = useColorModeValue('gray.100', 'gray.700')
return (
<Popover isLazy>
{({ onClose }: { onClose: () => void }) => (
<>
<Tooltip label="Change icon">
<Tooltip label={t('editor.header.tooltip.changeIcon.label')}>
<Flex
cursor="pointer"
p="2"

View File

@ -11,6 +11,7 @@ import { useEffect, useMemo, useRef, useState } from 'react'
import { iconNames } from './iconNames'
import { TextInput } from '../inputs'
import { ColorPicker } from '../ColorPicker'
import { useTranslate } from '@tolgee/react'
const batchSize = 200
@ -39,6 +40,7 @@ export const IconPicker = ({ onIconSelected }: Props) => {
[initialIconColor, selectedColor]
)
const [recentIconNames, setRecentIconNames] = useState([])
const { t } = useTranslate()
useEffect(() => {
const recentIconNames = localStorage.getItem(localStorageRecentIconNamesKey)
@ -105,7 +107,7 @@ export const IconPicker = ({ onIconSelected }: Props) => {
<Stack>
<HStack>
<TextInput
placeholder="Search..."
placeholder={t('emojiList.searchInput.placeholder')}
onChange={searchIcon}
withVariableButton={false}
debounceTimeout={300}

View File

@ -7,6 +7,7 @@ import { EmojiSearchableList } from './emoji/EmojiSearchableList'
import { UnsplashPicker } from './UnsplashPicker'
import { IconPicker } from './IconPicker'
import { FilePathUploadProps } from '@/features/upload/api/generateUploadUrl'
import { useTranslate } from '@tolgee/react'
type Tabs = 'link' | 'upload' | 'giphy' | 'emoji' | 'unsplash' | 'icon'
@ -173,7 +174,10 @@ type ContentProps = { onNewUrl: (url: string) => void }
const UploadFileContent = ({
uploadFileProps,
onNewUrl,
}: ContentProps & { uploadFileProps: FilePathUploadProps }) => (
}: ContentProps & { uploadFileProps: FilePathUploadProps }) => {
const { t } = useTranslate()
return (
<Flex justify="center" py="2">
<UploadButton
fileType="image"
@ -181,23 +185,28 @@ const UploadFileContent = ({
onFileUploaded={onNewUrl}
colorScheme="blue"
>
Choose an image
{t('editor.header.uploadTab.uploadButton.label')}
</UploadButton>
</Flex>
)
}
const EmbedLinkContent = ({
defaultUrl,
onNewUrl,
}: ContentProps & { defaultUrl?: string }) => (
}: ContentProps & { defaultUrl?: string }) => {
const { t } = useTranslate()
return (
<Stack py="2">
<TextInput
placeholder={'Paste the image link...'}
placeholder={t('editor.header.linkTab.searchInputPlaceholder.label')}
onChange={onNewUrl}
defaultValue={defaultUrl ?? ''}
/>
</Stack>
)
}
const GiphyContent = ({ onNewUrl }: ContentProps) => (
<GiphyPicker onSubmit={onNewUrl} />

View File

@ -9,6 +9,7 @@ import {
Text,
} from '@chakra-ui/react'
import { useState, ChangeEvent, useEffect, useRef } from 'react'
import { useTranslate } from '@tolgee/react'
const emojiTags = emojiTagsData as Record<string, string[]>
@ -41,6 +42,7 @@ export const EmojiSearchableList = ({
const [filteredFlags, setFilteredFlags] = useState(flags)
const [totalDisplayedCategories, setTotalDisplayedCategories] = useState(1)
const [recentEmojis, setRecentEmojis] = useState([])
const { t } = useTranslate()
useEffect(() => {
const recentIconNames = localStorage.getItem(localStorageRecentEmojisKey)
@ -104,12 +106,15 @@ export const EmojiSearchableList = ({
return (
<Stack>
<ClassicInput placeholder="Search..." onChange={handleSearchChange} />
<ClassicInput
placeholder={t('emojiList.searchInput.placeholder')}
onChange={handleSearchChange}
/>
<Stack ref={scrollContainer} overflow="scroll" maxH="350px" spacing={4}>
{recentEmojis.length > 0 && (
<Stack>
<Text fontSize="xs" color="gray.400" fontWeight="semibold" pl="2">
RECENT
{t('emojiList.categories.recent.label')}
</Text>
<EmojiGrid emojis={recentEmojis} onEmojiClick={selectEmoji} />
</Stack>
@ -117,7 +122,7 @@ export const EmojiSearchableList = ({
{filteredPeople.length > 0 && (
<Stack>
<Text fontSize="xs" color="gray.400" fontWeight="semibold" pl="2">
PEOPLE
{t('emojiList.categories.people.label')}
</Text>
<EmojiGrid emojis={filteredPeople} onEmojiClick={selectEmoji} />
</Stack>
@ -125,7 +130,7 @@ export const EmojiSearchableList = ({
{filteredAnimals.length > 0 && totalDisplayedCategories >= 2 && (
<Stack>
<Text fontSize="xs" color="gray.400" fontWeight="semibold" pl="2">
ANIMALS & NATURE
{t('emojiList.categories.animalsAndNature.label')}
</Text>
<EmojiGrid emojis={filteredAnimals} onEmojiClick={selectEmoji} />
</Stack>
@ -133,7 +138,7 @@ export const EmojiSearchableList = ({
{filteredFood.length > 0 && totalDisplayedCategories >= 3 && (
<Stack>
<Text fontSize="xs" color="gray.400" fontWeight="semibold" pl="2">
FOOD & DRINK
{t('emojiList.categories.foodAndDrink.label')}
</Text>
<EmojiGrid emojis={filteredFood} onEmojiClick={selectEmoji} />
</Stack>
@ -141,7 +146,7 @@ export const EmojiSearchableList = ({
{filteredTravel.length > 0 && totalDisplayedCategories >= 4 && (
<Stack>
<Text fontSize="xs" color="gray.400" fontWeight="semibold" pl="2">
TRAVEL & PLACES
{t('emojiList.categories.travelAndPlaces.label')}
</Text>
<EmojiGrid emojis={filteredTravel} onEmojiClick={selectEmoji} />
</Stack>
@ -149,7 +154,7 @@ export const EmojiSearchableList = ({
{filteredActivities.length > 0 && totalDisplayedCategories >= 5 && (
<Stack>
<Text fontSize="xs" color="gray.400" fontWeight="semibold" pl="2">
ACTIVITIES
{t('emojiList.categories.activities.label')}
</Text>
<EmojiGrid emojis={filteredActivities} onEmojiClick={selectEmoji} />
</Stack>
@ -157,7 +162,7 @@ export const EmojiSearchableList = ({
{filteredObjects.length > 0 && totalDisplayedCategories >= 6 && (
<Stack>
<Text fontSize="xs" color="gray.400" fontWeight="semibold" pl="2">
OBJECTS
{t('emojiList.categories.objects.label')}
</Text>
<EmojiGrid emojis={filteredObjects} onEmojiClick={selectEmoji} />
</Stack>
@ -165,7 +170,7 @@ export const EmojiSearchableList = ({
{filteredSymbols.length > 0 && totalDisplayedCategories >= 7 && (
<Stack>
<Text fontSize="xs" color="gray.400" fontWeight="semibold" pl="2">
SYMBOLS
{t('emojiList.categories.symbols.label')}
</Text>
<EmojiGrid emojis={filteredSymbols} onEmojiClick={selectEmoji} />
</Stack>
@ -173,7 +178,7 @@ export const EmojiSearchableList = ({
{filteredFlags.length > 0 && totalDisplayedCategories >= 8 && (
<Stack>
<Text fontSize="xs" color="gray.400" fontWeight="semibold" pl="2">
FLAGS
{t('emojiList.categories.flags.label')}
</Text>
<EmojiGrid emojis={filteredFlags} onEmojiClick={selectEmoji} />
</Stack>

View File

@ -12,7 +12,7 @@ export const AzureAdLogo = (props: IconProps) => {
<g id="g1016" transform="translate(-63.947 -88.179)">
<path
id="path1008"
fill='#00bef2'
fill="#00bef2"
d="M290 166.3c.4 0 .8.5 1.4 1.4.5.8 42.6 51.3 93.6 112.2 51 60.9 92.6 111 92.4 111.3-.1.3-40.7 33.6-90.2 73.9s-91.6 74.6-93.5 76.2c-3.3 2.7-3.5 2.8-4.7 1.6-.7-.7-42.9-35.2-93.8-76.7S102.8 390.5 103 390c.2-.5 42-50.4 93.1-111s92.9-110.7 93.1-111.5c.2-.8.5-1.2.8-1.2z"
/>
<path

View File

@ -2,12 +2,33 @@ import { IconProps, Icon } from '@chakra-ui/react'
export const GitlabLogo = (props: IconProps) => (
<Icon viewBox="0 0 256 236" {...props}>
<path d="M128.075 236.075l47.104-144.97H80.97l47.104 144.97z" fill="#E24329" />
<path d="M128.075 236.074L80.97 91.104H14.956l113.119 144.97z" fill="#FC6D26" />
<path d="M14.956 91.104L.642 135.16a9.752 9.752 0 0 0 3.542 10.903l123.891 90.012-113.12-144.97z" fill="#FCA326" />
<path d="M14.956 91.105H80.97L52.601 3.79c-1.46-4.493-7.816-4.492-9.275 0l-28.37 87.315z" fill="#E24329" />
<path d="M128.075 236.074l47.104-144.97h66.015l-113.12 144.97z" fill="#FC6D26" />
<path d="M241.194 91.104l14.314 44.056a9.752 9.752 0 0 1-3.543 10.903l-123.89 90.012 113.119-144.97z" fill="#FCA326" />
<path d="M241.194 91.105h-66.015l28.37-87.315c1.46-4.493 7.816-4.492 9.275 0l28.37 87.315z" fill="#E24329" />
<path
d="M128.075 236.075l47.104-144.97H80.97l47.104 144.97z"
fill="#E24329"
/>
<path
d="M128.075 236.074L80.97 91.104H14.956l113.119 144.97z"
fill="#FC6D26"
/>
<path
d="M14.956 91.104L.642 135.16a9.752 9.752 0 0 0 3.542 10.903l123.891 90.012-113.12-144.97z"
fill="#FCA326"
/>
<path
d="M14.956 91.105H80.97L52.601 3.79c-1.46-4.493-7.816-4.492-9.275 0l-28.37 87.315z"
fill="#E24329"
/>
<path
d="M128.075 236.074l47.104-144.97h66.015l-113.12 144.97z"
fill="#FC6D26"
/>
<path
d="M241.194 91.104l14.314 44.056a9.752 9.752 0 0 1-3.543 10.903l-123.89 90.012 113.119-144.97z"
fill="#FCA326"
/>
<path
d="M241.194 91.105h-66.015l28.37-87.315c1.46-4.493 7.816-4.492 9.275 0l28.37 87.315z"
fill="#E24329"
/>
</Icon>
)

View File

@ -28,9 +28,11 @@ import { deleteInvitationQuery } from '../queries/deleteInvitationQuery'
import { updateCollaboratorQuery } from '../queries/updateCollaboratorQuery'
import { deleteCollaboratorQuery } from '../queries/deleteCollaboratorQuery'
import { sendInvitationQuery } from '../queries/sendInvitationQuery'
import { TFnType, useTranslate } from '@tolgee/react'
export const CollaborationList = () => {
const { currentRole, workspace } = useWorkspace()
const { t } = useTranslate()
const { typebot } = useTypebot()
const [invitationType, setInvitationType] = useState<CollaborationType>(
CollaborationType.READ
@ -50,7 +52,7 @@ export const CollaborationList = () => {
typebotId: typebot?.id,
onError: (e) =>
showToast({
title: "Couldn't fetch collaborators",
title: t('share.button.popover.collaboratorsFetch.error.label'),
description: e.message,
}),
})
@ -62,7 +64,7 @@ export const CollaborationList = () => {
typebotId: typebot?.id,
onError: (e) =>
showToast({
title: "Couldn't fetch invitations",
title: t('share.button.popover.invitationsFetch.error.label'),
description: e.message,
}),
})
@ -132,7 +134,10 @@ export const CollaborationList = () => {
mutateCollaborators({ collaborators: collaborators ?? [] })
if (error)
return showToast({ title: error.name, description: error.message })
showToast({ status: 'success', title: 'Invitation sent! 📧' })
showToast({
status: 'success',
title: t('share.button.popover.invitationSent.successToast.label'),
})
setInvitationEmail('')
}
@ -141,7 +146,7 @@ export const CollaborationList = () => {
<HStack as="form" onSubmit={handleInvitationSubmit} px="4" pb="2">
<Input
size="sm"
placeholder="colleague@company.com"
placeholder={t('share.button.popover.inviteInput.placeholder')}
name="inviteEmail"
value={invitationEmail}
onChange={(e) => setInvitationEmail(e.target.value)}
@ -163,7 +168,7 @@ export const CollaborationList = () => {
type="submit"
isDisabled={!hasFullAccess}
>
Invite
{t('share.button.popover.inviteButton.label')}
</Button>
</HStack>
{workspace && (
@ -176,6 +181,7 @@ export const CollaborationList = () => {
</HStack>
<Tag flexShrink={0}>
{convertCollaborationTypeEnumToReadable(
t,
CollaborationType.FULL_ACCESS
)}
</Tag>
@ -227,6 +233,8 @@ const CollaborationTypeMenuButton = ({
type: CollaborationType
onChange: (type: CollaborationType) => void
}) => {
const { t } = useTranslate()
return (
<Menu placement="bottom-end">
<MenuButton
@ -235,15 +243,15 @@ const CollaborationTypeMenuButton = ({
as={Button}
rightIcon={<ChevronLeftIcon transform={'rotate(-90deg)'} />}
>
{convertCollaborationTypeEnumToReadable(type)}
{convertCollaborationTypeEnumToReadable(t, type)}
</MenuButton>
<MenuList minW={0}>
<Stack maxH={'35vh'} overflowY="scroll" spacing="0">
<MenuItem onClick={() => onChange(CollaborationType.READ)}>
{convertCollaborationTypeEnumToReadable(CollaborationType.READ)}
{convertCollaborationTypeEnumToReadable(t, CollaborationType.READ)}
</MenuItem>
<MenuItem onClick={() => onChange(CollaborationType.WRITE)}>
{convertCollaborationTypeEnumToReadable(CollaborationType.WRITE)}
{convertCollaborationTypeEnumToReadable(t, CollaborationType.WRITE)}
</MenuItem>
</Stack>
</MenuList>
@ -252,14 +260,15 @@ const CollaborationTypeMenuButton = ({
}
export const convertCollaborationTypeEnumToReadable = (
t: TFnType,
type: CollaborationType
) => {
switch (type) {
case CollaborationType.READ:
return 'Can view'
return t('collaboration.roles.view.label')
case CollaborationType.WRITE:
return 'Can edit'
return t('collaboration.roles.edit.label')
case CollaborationType.FULL_ACCESS:
return 'Full access'
return t('collaboration.roles.full.label')
}
}

View File

@ -13,6 +13,7 @@ import {
import { CollaborationType } from '@typebot.io/prisma'
import React from 'react'
import { convertCollaborationTypeEnumToReadable } from './CollaborationList'
import { useTranslate } from '@tolgee/react'
type Props = {
image?: string
@ -35,6 +36,7 @@ export const CollaboratorItem = ({
onDeleteClick,
onChangeCollaborationType,
}: Props) => {
const { t } = useTranslate()
const hoverBgColor = useColorModeValue('gray.100', 'gray.700')
const handleEditClick = () =>
onChangeCollaborationType(CollaborationType.WRITE)
@ -48,19 +50,19 @@ export const CollaboratorItem = ({
name={name}
image={image}
isGuest={isGuest}
tag={convertCollaborationTypeEnumToReadable(type)}
tag={convertCollaborationTypeEnumToReadable(t, type)}
/>
</MenuButton>
{isOwner && (
<MenuList shadow="lg">
<MenuItem onClick={handleEditClick}>
{convertCollaborationTypeEnumToReadable(CollaborationType.WRITE)}
{convertCollaborationTypeEnumToReadable(t, CollaborationType.WRITE)}
</MenuItem>
<MenuItem onClick={handleViewClick}>
{convertCollaborationTypeEnumToReadable(CollaborationType.READ)}
{convertCollaborationTypeEnumToReadable(t, CollaborationType.READ)}
</MenuItem>
<MenuItem color="red.500" onClick={onDeleteClick}>
Remove
{t('remove')}
</MenuItem>
</MenuList>
)}
@ -80,7 +82,10 @@ export const CollaboratorIdentityContent = ({
image?: string
isGuest?: boolean
email: string
}) => (
}) => {
const { t } = useTranslate()
return (
<HStack justifyContent="space-between" maxW="full" py="2" px="4">
<HStack minW={0} spacing={3}>
<Avatar name={name} src={image} size="sm" />
@ -100,8 +105,9 @@ export const CollaboratorIdentityContent = ({
</Stack>
</HStack>
<HStack flexShrink={0}>
{isGuest && <Tag color="gray.400">Pending</Tag>}
{isGuest && <Tag color="gray.400">{t('pending')}</Tag>}
<Tag>{tag}</Tag>
</HStack>
</HStack>
)
}

View File

@ -22,6 +22,7 @@ import { useRouter } from 'next/router'
import React, { useEffect, useState } from 'react'
import { EditorSettingsModal } from './EditorSettingsModal'
import { parseDefaultPublicId } from '@/features/publish/helpers/parseDefaultPublicId'
import { useTranslate } from '@tolgee/react'
export const BoardMenuButton = (props: FlexProps) => {
const { query } = useRouter()
@ -29,6 +30,7 @@ export const BoardMenuButton = (props: FlexProps) => {
const { user } = useUser()
const [isDownloading, setIsDownloading] = useState(false)
const { isOpen, onOpen, onClose } = useDisclosure()
const { t } = useTranslate()
useEffect(() => {
if (user && !user.graphNavigation && !query.isFirstBot) onOpen()
@ -71,13 +73,13 @@ export const BoardMenuButton = (props: FlexProps) => {
/>
<MenuList>
<MenuItem icon={<BookIcon />} onClick={redirectToDocumentation}>
Documentation
{t('editor.graph.menu.documentationItem.label')}
</MenuItem>
<MenuItem icon={<SettingsIcon />} onClick={onOpen}>
Editor settings
{t('editor.graph.menu.editorSettingsItem.label')}
</MenuItem>
<MenuItem icon={<DownloadIcon />} onClick={downloadFlow}>
Export flow
{t('editor.graph.menu.exportFlowItem.label')}
</MenuItem>
</MenuList>
<EditorSettingsModal isOpen={isOpen} onClose={onClose} />

View File

@ -116,7 +116,7 @@ export const TypebotHeader = () => {
variant={router.pathname.includes('/edit') ? 'outline' : 'ghost'}
size="sm"
>
{t('editor.headers.flowButton.label')}
{t('editor.header.flowButton.label')}
</Button>
<Button
as={Link}
@ -125,7 +125,7 @@ export const TypebotHeader = () => {
variant={router.pathname.endsWith('theme') ? 'outline' : 'ghost'}
size="sm"
>
{t('editor.headers.themeButton.label')}
{t('editor.header.themeButton.label')}
</Button>
<Button
as={Link}
@ -134,7 +134,7 @@ export const TypebotHeader = () => {
variant={router.pathname.endsWith('settings') ? 'outline' : 'ghost'}
size="sm"
>
{t('editor.headers.settingsButton.label')}
{t('editor.header.settingsButton.label')}
</Button>
<Button
as={Link}
@ -143,7 +143,7 @@ export const TypebotHeader = () => {
variant={router.pathname.endsWith('share') ? 'outline' : 'ghost'}
size="sm"
>
{t('editor.headers.shareButton.label')}
{t('share.button.label')}
</Button>
{isDefined(publishedTypebot) && (
<Button
@ -153,7 +153,7 @@ export const TypebotHeader = () => {
variant={router.pathname.includes('results') ? 'outline' : 'ghost'}
size="sm"
>
{t('editor.headers.resultsButton.label')}
{t('editor.header.resultsButton.label')}
</Button>
)}
</HStack>
@ -211,7 +211,11 @@ export const TypebotHeader = () => {
{currentUserMode === 'write' && (
<HStack>
<Tooltip
label={isUndoShortcutTooltipOpen ? 'Changes reverted!' : 'Undo'}
label={
isUndoShortcutTooltipOpen
? t('editor.header.undo.tooltip.label')
: t('editor.header.undoButton.label')
}
isOpen={isUndoShortcutTooltipOpen ? true : undefined}
hasArrow={isUndoShortcutTooltipOpen}
>
@ -219,18 +223,18 @@ export const TypebotHeader = () => {
display={['none', 'flex']}
icon={<UndoIcon />}
size="sm"
aria-label="Undo"
aria-label={t('editor.header.undoButton.label')}
onClick={undo}
isDisabled={!canUndo}
/>
</Tooltip>
<Tooltip label="Redo">
<Tooltip label={t('editor.header.redoButton.label')}>
<IconButton
display={['none', 'flex']}
icon={<RedoIcon />}
size="sm"
aria-label="Redo"
aria-label={t('editor.header.redoButton.label')}
onClick={redo}
isDisabled={!canRedo}
/>
@ -238,14 +242,14 @@ export const TypebotHeader = () => {
</HStack>
)}
<Button leftIcon={<BuoyIcon />} onClick={handleHelpClick} size="sm">
{t('editor.headers.helpButton.label')}
{t('editor.header.helpButton.label')}
</Button>
</HStack>
{isSavingLoading && (
<HStack>
<Spinner speed="0.7s" size="sm" color="gray.400" />
<Text fontSize="sm" color="gray.400">
{t('editor.headers.savingSpinner.label')}
{t('editor.header.savingSpinner.label')}
</Text>
</HStack>
)}
@ -263,7 +267,7 @@ export const TypebotHeader = () => {
leftIcon={<PlayIcon />}
size="sm"
>
{t('editor.headers.previewButton.label')}
{t('editor.header.previewButton.label')}
</Button>
)}
{currentUserMode === 'write' && <PublishButton size="sm" />}

View File

@ -62,7 +62,7 @@ export const GuestTypebotHeader = () => {
variant={router.pathname.includes('/edit') ? 'outline' : 'ghost'}
size="sm"
>
{t('editor.headers.flowButton.label')}
{t('editor.header.flowButton.label')}
</Button>
<Button
as={Link}
@ -71,7 +71,7 @@ export const GuestTypebotHeader = () => {
variant={router.pathname.endsWith('theme') ? 'outline' : 'ghost'}
size="sm"
>
{t('editor.headers.themeButton.label')}
{t('editor.header.themeButton.label')}
</Button>
<Button
as={Link}
@ -80,7 +80,7 @@ export const GuestTypebotHeader = () => {
variant={router.pathname.endsWith('settings') ? 'outline' : 'ghost'}
size="sm"
>
{t('editor.headers.settingsButton.label')}
{t('editor.header.settingsButton.label')}
</Button>
</HStack>
<HStack

View File

@ -1,11 +1,14 @@
import { FlagIcon } from '@/components/icons'
import { HStack, Text } from '@chakra-ui/react'
import { useTranslate } from '@tolgee/react'
export const StartEventNode = () => {
const { t } = useTranslate()
return (
<HStack spacing={3}>
<FlagIcon />
<Text>Start</Text>
<Text>{t('editor.blocks.start.text')}</Text>
</HStack>
)
}

View File

@ -17,6 +17,7 @@ import { runtimes } from '../data'
import { PreviewDrawerBody } from './PreviewDrawerBody'
import { useDrag } from '@use-gesture/react'
import { ResizeHandle } from './ResizeHandle'
import { useTranslate } from '@tolgee/react'
const preferredRuntimeKey = 'preferredRuntime'
@ -30,6 +31,7 @@ const getDefaultRuntime = (typebotId?: string) => {
export const PreviewDrawer = () => {
const { typebot, save, isSavingLoading } = useTypebot()
const { t } = useTranslate()
const { setRightPanel } = useEditor()
const { setPreviewingBlock } = useGraph()
const [width, setWidth] = useState(500)
@ -103,7 +105,7 @@ export const PreviewDrawer = () => {
isLoading={isSavingLoading}
variant="ghost"
>
Restart
{t('preview.restartButton.label')}
</Button>
) : null}
</HStack>

View File

@ -73,7 +73,7 @@ export const PublishButton = ({
trpc.typebot.publishTypebot.useMutation({
onError: (error) => {
showToast({
title: 'Error while publishing typebot',
title: t('publish.error.label'),
description: error.message,
})
if (error.data?.httpStatus === 403) logOut()
@ -91,7 +91,7 @@ export const PublishButton = ({
trpc.typebot.unpublishTypebot.useMutation({
onError: (error) =>
showToast({
title: 'Error while unpublishing typebot',
title: t('editor.header.unpublishTypebot.error.label'),
description: error.message,
}),
onSuccess: () => {
@ -149,41 +149,40 @@ export const PublishButton = ({
onConfirm={handlePublishClick}
onClose={onNewEngineWarningClose}
confirmButtonColor="blue"
title="⚠️ New engine version"
title={t('publish.versionWarning.title.label')}
message={
<Stack spacing="3">
<Text>
You are about to a deploy a version of your bot with an updated
engine (Typebot V6).
{t('publish.versionWarning.message.aboutToDeploy.label')}
</Text>
<Text fontWeight="bold">
Make sure to check out all the{' '}
{t('publish.versionWarning.message.check.label')}{' '}
<TextLink
href="https://docs.typebot.io/breaking-changes#typebot-v6"
isExternal
>
associated breaking changes
{t('publish.versionWarning.message.breakingChanges.label')}
</TextLink>
</Text>
<Text>
{' '}
Then test, the bot thoroughly in preview mode before publishing.
{t('publish.versionWarning.message.testInPreviewMode.label')}
</Text>
</Stack>
}
confirmButtonLabel={'Publish'}
confirmButtonLabel={t('publishButton.label')}
/>
)}
<Tooltip
placement="bottom-end"
label={
<Stack>
<Text>There are non published changes.</Text>
<Text>{t('publishButton.tooltip.nonPublishedChanges.label')}</Text>
<Text fontStyle="italic">
Published version from{' '}
{t('publishButton.tooltip.publishedVersion.from.label')}{' '}
{publishedTypebot &&
parseTimeSince(publishedTypebot.updatedAt.toString())}{' '}
ago
{t('publishButton.tooltip.publishedVersion.ago.label')}
</Text>
</Stack>
}
@ -205,9 +204,9 @@ export const PublishButton = ({
>
{isPublished
? typebot?.isClosed
? 'Closed'
: 'Published'
: 'Publish'}
? t('publishButton.closed.label')
: t('publishButton.published.label')
: t('publishButton.label')}
</Button>
</Tooltip>
@ -218,27 +217,27 @@ export const PublishButton = ({
colorScheme={'blue'}
borderLeftRadius={0}
icon={<ChevronLeftIcon transform="rotate(-90deg)" />}
aria-label="Show published typebot menu"
aria-label={t('publishButton.dropdown.showMenu.label')}
size="sm"
isDisabled={isPublishing || isSavingLoading}
/>
<MenuList>
{!isPublished && (
<MenuItem onClick={restorePublishedTypebot}>
Restore published version
{t('publishButton.dropdown.restoreVersion.label')}
</MenuItem>
)}
{!typebot?.isClosed ? (
<MenuItem onClick={closeTypebot} icon={<LockedIcon />}>
Close typebot to new responses
{t('publishButton.dropdown.close.label')}
</MenuItem>
) : (
<MenuItem onClick={openTypebot} icon={<UnlockedIcon />}>
Reopen typebot to new responses
{t('publishButton.dropdown.reopen.label')}
</MenuItem>
)}
<MenuItem onClick={unpublishTypebot} icon={<CloudOffIcon />}>
Unpublish typebot
{t('publishButton.dropdown.unpublish.label')}
</MenuItem>
</MenuList>
</Menu>

View File

@ -6,10 +6,7 @@ import { parseReactBotProps } from '../../snippetParsers'
type Props = { widthLabel?: string; heightLabel: string }
export const NextjsStandardSnippet = ({
widthLabel,
heightLabel,
}: Props) => {
export const NextjsStandardSnippet = ({ widthLabel, heightLabel }: Props) => {
const { typebot } = useTypebot()
const snippet = prettier.format(
`import { Standard } from "@typebot.io/nextjs";

View File

@ -4,8 +4,10 @@ import { SwitchWithRelatedSettings } from '@/components/SwitchWithRelatedSetting
import { CopyButton } from '@/components/CopyButton'
import { CollaborationList } from '@/features/collaboration/components/CollaborationList'
import { useTypebot } from '@/features/editor/providers/TypebotProvider'
import { useTranslate } from '@tolgee/react'
export const SharePopoverContent = () => {
const { t } = useTranslate()
const { typebot, updateTypebot } = useTypebot()
const currentUrl = `${window.location.origin}/typebots/${typebot?.id}/edit`
@ -30,7 +32,7 @@ export const SharePopoverContent = () => {
<CollaborationList />
<Stack p="4" borderTopWidth={1}>
<SwitchWithRelatedSettings
label={'Make the flow publicly available'}
label={t('share.button.popover.publicFlow.label')}
initialValue={typebot?.settings.publicShare?.isEnabled ?? false}
onCheckChange={updateIsPublicShareEnabled}
>

View File

@ -7,18 +7,21 @@ import {
import { UsersIcon } from '@/components/icons'
import React from 'react'
import { SharePopoverContent } from './SharePopoverContent'
import { useTranslate } from '@tolgee/react'
export const ShareTypebotButton = ({ isLoading }: { isLoading: boolean }) => {
const { t } = useTranslate()
return (
<Popover isLazy placement="bottom-end">
<PopoverTrigger>
<Button
isLoading={isLoading}
leftIcon={<UsersIcon />}
aria-label="Open share popover"
aria-label={t('share.button.popover.ariaLabel')}
size="sm"
>
Share
{t('share.button.label')}
</Button>
</PopoverTrigger>
<PopoverContent

View File

@ -15,12 +15,14 @@ import React, { useRef } from 'react'
import { VariableSearchInput } from '@/components/inputs/VariableSearchInput'
import { useOutsideClick } from '@/hooks/useOutsideClick'
import { useParentModal } from '@/features/graph/providers/ParentModalProvider'
import { useTranslate } from '@tolgee/react'
type Props = {
onSelectVariable: (variable: Pick<Variable, 'name' | 'id'>) => void
} & Omit<IconButtonProps, 'aria-label'>
export const VariablesButton = ({ onSelectVariable, ...props }: Props) => {
const { t } = useTranslate()
const { isOpen, onOpen, onClose } = useDisclosure()
const popoverRef = useRef<HTMLDivElement>(null)
const { ref: parentModalRef } = useParentModal()
@ -35,9 +37,9 @@ export const VariablesButton = ({ onSelectVariable, ...props }: Props) => {
<Popover isLazy isOpen={isOpen}>
<PopoverAnchor>
<Flex>
<Tooltip label="Insert a variable">
<Tooltip label={t('variables.button.tooltip')}>
<IconButton
aria-label={'Insert a variable'}
aria-label={t('variables.button.tooltip')}
icon={<UserIcon />}
pos="relative"
onClick={onOpen}
@ -54,7 +56,7 @@ export const VariablesButton = ({ onSelectVariable, ...props }: Props) => {
onClose()
if (variable) onSelectVariable(variable)
}}
placeholder="Search for a variable"
placeholder={t('variables.button.searchInput.placeholder')}
shadow="lg"
autoFocus
/>

View File

@ -1 +1,137 @@
{"id":"clemrhnsp00001auiaoun42wf","version":"3","createdAt":"2023-02-27T11:53:48.217Z","updatedAt":"2023-02-27T11:53:48.217Z","icon":null,"name":"My typebot","folderId":null,"groups":[{"id":"et7lna5mxbmn9blchekkejdf","title":"Start","blocks":[{"id":"ivcklgamqz8e3uwmtshm32n9","type":"start","label":"Start","groupId":"et7lna5mxbmn9blchekkejdf","outgoingEdgeId":"ogi8zj19v4krzm9xe4c9orv2"}],"graphCoordinates":{"x":0,"y":0}},{"id":"wrd4694r5fo8czflp4t79259","graphCoordinates":{"x":41.28125,"y":169.53125},"title":"Group #1","blocks":[{"id":"pjnrvjh6un6el1tjsbu7d6w1","groupId":"wrd4694r5fo8czflp4t79259","type":"text","content":{"html":"<div>Hello this is a test!</div>","richText":[{"type":"p","children":[{"text":"Hello this is a test!"}]}],"plainText":"Hello this is a test!"}},{"id":"wvt13rpcvuy5s7mj83bm946s","groupId":"wrd4694r5fo8czflp4t79259","type":"text","content":{"html":"<div>How are you?</div>","richText":[{"type":"p","children":[{"text":"How are you?"}]}],"plainText":"How are you?"}},{"id":"he864w99l8y6c6epfd9girvv","groupId":"wrd4694r5fo8czflp4t79259","type":"text input","options":{"isLong":false,"labels":{"button":"Send","placeholder":"Type your answer..."}},"outgoingEdgeId":"a42zatxkw0q8w2kq886m9ek8"}]},{"id":"eao5ufv4wtl0yos09w6wag3j","graphCoordinates":{"x":411.078125,"y":169.94140625},"title":"Group #2","blocks":[{"id":"t33v5ijddw2e2786jiurep3p","groupId":"eao5ufv4wtl0yos09w6wag3j","type":"Jump","options":{}}]}],"variables":[],"edges":[{"from":{"groupId":"et7lna5mxbmn9blchekkejdf","blockId":"ivcklgamqz8e3uwmtshm32n9"},"to":{"groupId":"wrd4694r5fo8czflp4t79259"},"id":"ogi8zj19v4krzm9xe4c9orv2"},{"from":{"groupId":"wrd4694r5fo8czflp4t79259","blockId":"he864w99l8y6c6epfd9girvv"},"to":{"groupId":"eao5ufv4wtl0yos09w6wag3j"},"id":"a42zatxkw0q8w2kq886m9ek8"}],"theme":{"chat":{"inputs":{"color":"#303235","backgroundColor":"#FFFFFF","placeholderColor":"#9095A0"},"buttons":{"color":"#FFFFFF","backgroundColor":"#0042DA"},"hostAvatar":{"url":"https://avatars.githubusercontent.com/u/16015833?v=4","isEnabled":true},"hostBubbles":{"color":"#303235","backgroundColor":"#F7F8FF"},"guestBubbles":{"color":"#FFFFFF","backgroundColor":"#FF8E21"}},"general":{"font":"Open Sans","background":{"type":"Color","content":"#ffffff"}}},"settings":{"general":{"isBrandingEnabled":true,"isInputPrefillEnabled":true,"isResultSavingEnabled":true,"isHideQueryParamsEnabled":true,"isNewResultOnRefreshEnabled":true},"metadata":{"description":"Build beautiful conversational forms and embed them directly in your applications without a line of code. Triple your response rate and collect answers that has more value compared to a traditional form."},"typingEmulation":{"speed":300,"enabled":true,"maxDelay":1.5}},"publicId":null,"customDomain":null,"workspaceId":"freeWorkspace","resultsTablePreferences":null,"isArchived":false,"isClosed":false}
{
"id": "clemrhnsp00001auiaoun42wf",
"version": "3",
"createdAt": "2023-02-27T11:53:48.217Z",
"updatedAt": "2023-02-27T11:53:48.217Z",
"icon": null,
"name": "My typebot",
"folderId": null,
"groups": [
{
"id": "et7lna5mxbmn9blchekkejdf",
"title": "Start",
"blocks": [
{
"id": "ivcklgamqz8e3uwmtshm32n9",
"type": "start",
"label": "Start",
"groupId": "et7lna5mxbmn9blchekkejdf",
"outgoingEdgeId": "ogi8zj19v4krzm9xe4c9orv2"
}
],
"graphCoordinates": { "x": 0, "y": 0 }
},
{
"id": "wrd4694r5fo8czflp4t79259",
"graphCoordinates": { "x": 41.28125, "y": 169.53125 },
"title": "Group #1",
"blocks": [
{
"id": "pjnrvjh6un6el1tjsbu7d6w1",
"groupId": "wrd4694r5fo8czflp4t79259",
"type": "text",
"content": {
"html": "<div>Hello this is a test!</div>",
"richText": [
{ "type": "p", "children": [{ "text": "Hello this is a test!" }] }
],
"plainText": "Hello this is a test!"
}
},
{
"id": "wvt13rpcvuy5s7mj83bm946s",
"groupId": "wrd4694r5fo8czflp4t79259",
"type": "text",
"content": {
"html": "<div>How are you?</div>",
"richText": [
{ "type": "p", "children": [{ "text": "How are you?" }] }
],
"plainText": "How are you?"
}
},
{
"id": "he864w99l8y6c6epfd9girvv",
"groupId": "wrd4694r5fo8czflp4t79259",
"type": "text input",
"options": {
"isLong": false,
"labels": { "button": "Send", "placeholder": "Type your answer..." }
},
"outgoingEdgeId": "a42zatxkw0q8w2kq886m9ek8"
}
]
},
{
"id": "eao5ufv4wtl0yos09w6wag3j",
"graphCoordinates": { "x": 411.078125, "y": 169.94140625 },
"title": "Group #2",
"blocks": [
{
"id": "t33v5ijddw2e2786jiurep3p",
"groupId": "eao5ufv4wtl0yos09w6wag3j",
"type": "Jump",
"options": {}
}
]
}
],
"variables": [],
"edges": [
{
"from": {
"groupId": "et7lna5mxbmn9blchekkejdf",
"blockId": "ivcklgamqz8e3uwmtshm32n9"
},
"to": { "groupId": "wrd4694r5fo8czflp4t79259" },
"id": "ogi8zj19v4krzm9xe4c9orv2"
},
{
"from": {
"groupId": "wrd4694r5fo8czflp4t79259",
"blockId": "he864w99l8y6c6epfd9girvv"
},
"to": { "groupId": "eao5ufv4wtl0yos09w6wag3j" },
"id": "a42zatxkw0q8w2kq886m9ek8"
}
],
"theme": {
"chat": {
"inputs": {
"color": "#303235",
"backgroundColor": "#FFFFFF",
"placeholderColor": "#9095A0"
},
"buttons": { "color": "#FFFFFF", "backgroundColor": "#0042DA" },
"hostAvatar": {
"url": "https://avatars.githubusercontent.com/u/16015833?v=4",
"isEnabled": true
},
"hostBubbles": { "color": "#303235", "backgroundColor": "#F7F8FF" },
"guestBubbles": { "color": "#FFFFFF", "backgroundColor": "#FF8E21" }
},
"general": {
"font": "Open Sans",
"background": { "type": "Color", "content": "#ffffff" }
}
},
"settings": {
"general": {
"isBrandingEnabled": true,
"isInputPrefillEnabled": true,
"isResultSavingEnabled": true,
"isHideQueryParamsEnabled": true,
"isNewResultOnRefreshEnabled": true
},
"metadata": {
"description": "Build beautiful conversational forms and embed them directly in your applications without a line of code. Triple your response rate and collect answers that has more value compared to a traditional form."
},
"typingEmulation": { "speed": 300, "enabled": true, "maxDelay": 1.5 }
},
"publicId": null,
"customDomain": null,
"workspaceId": "freeWorkspace",
"resultsTablePreferences": null,
"isArchived": false,
"isClosed": false
}

View File

@ -7,6 +7,7 @@
"build": "dotenv -e ./.env -e ../../.env -- next build",
"start": "dotenv -e ./.env -e ../../.env -- next start",
"lint": "dotenv -e ./.env -e ../../.env -- next lint",
"format:fix": "prettier --write ./src",
"test": "dotenv -e ./.env -e ../../.env -- pnpm playwright test",
"test:report": "pnpm playwright show-report"
},

View File

@ -14,9 +14,9 @@
"db:migrate": "cd packages/prisma && pnpm run db:migrate",
"generate-change-log": "git fetch --all && pnpx gitmoji-changelog",
"locales:sync": "tolgee sync './apps/builder/src/**/*.ts?(x)' --continue-on-warning --remove-unused",
"locales:push": "tolgee push ./apps/builder/public/locales",
"locales:pull": "tolgee pull ./apps/builder/public/locales",
"create-new-block": "cd packages/forge/cli && pnpm start"
"create-new-block": "cd packages/forge/cli && pnpm start",
"format:fix": "turbo run format:fix"
},
"devDependencies": {
"cross-env": "7.0.3",

View File

@ -8,7 +8,8 @@
"scripts": {
"dev": "rollup --watch --config rollup.config.js",
"build": "rollup --config rollup.config.js",
"lint": "eslint --fix \"src/**/*.ts*\""
"lint": "eslint --fix \"src/**/*.ts*\"",
"format:fix": "prettier --write ./src"
},
"license": "MIT",
"dependencies": {

View File

@ -8,7 +8,8 @@
"scripts": {
"dev": "rollup --watch --config rollup.config.js",
"build": "rollup --config rollup.config.js",
"lint": "eslint --fix \"src/**/*.ts*\""
"lint": "eslint --fix \"src/**/*.ts*\"",
"format:fix": "prettier --write ./src"
},
"keywords": [],
"author": "Baptiste Arnaud",

View File

@ -10,7 +10,8 @@
"stories:build": "ladle build",
"dev": "rollup --watch --config rollup.config.js",
"build": "rollup --config rollup.config.js",
"lint": "eslint --fix \"src/**/*.ts*\""
"lint": "eslint --fix \"src/**/*.ts*\"",
"format:fix": "prettier --write ./src"
},
"keywords": [],
"author": "Baptiste Arnaud",

View File

@ -5,6 +5,9 @@
"lint": {
"outputs": []
},
"format:fix": {
"outputs": []
},
"dev": {
"dependsOn": [
"^dev",