-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e5d7f1d
commit a0929c4
Showing
20 changed files
with
472 additions
and
43 deletions.
There are no files selected for viewing
132 changes: 132 additions & 0 deletions
132
...components/dashboard/WorkspaceSettingsModal/MyAccountForm/ApiTokensList/ApiTokensList.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
import { | ||
TableContainer, | ||
Table, | ||
Thead, | ||
Tr, | ||
Th, | ||
Tbody, | ||
Td, | ||
Button, | ||
Text, | ||
Heading, | ||
Checkbox, | ||
Skeleton, | ||
Stack, | ||
Flex, | ||
useDisclosure, | ||
} from '@chakra-ui/react' | ||
import { ConfirmModal } from 'components/modals/ConfirmModal' | ||
import { useToast } from 'components/shared/hooks/useToast' | ||
import { User } from 'db' | ||
import React, { useState } from 'react' | ||
import { | ||
ApiTokenFromServer, | ||
deleteApiToken, | ||
useApiTokens, | ||
} from 'services/user/apiTokens' | ||
import { timeSince } from 'services/utils' | ||
import { byId, isDefined } from 'utils' | ||
import { CreateTokenModal } from './CreateTokenModal' | ||
|
||
type Props = { user: User } | ||
|
||
export const ApiTokensList = ({ user }: Props) => { | ||
const { showToast } = useToast() | ||
const { apiTokens, isLoading, mutate } = useApiTokens({ | ||
userId: user.id, | ||
onError: (e) => | ||
showToast({ title: 'Failed to fetch tokens', description: e.message }), | ||
}) | ||
const { | ||
isOpen: isCreateOpen, | ||
onOpen: onCreateOpen, | ||
onClose: onCreateClose, | ||
} = useDisclosure() | ||
const [deletingId, setDeletingId] = useState<string>() | ||
|
||
const refreshListWithNewToken = (token: ApiTokenFromServer) => { | ||
if (!apiTokens) return | ||
mutate({ apiTokens: [token, ...apiTokens] }) | ||
} | ||
|
||
const deleteToken = async (tokenId?: string) => { | ||
if (!apiTokens || !tokenId) return | ||
const { error } = await deleteApiToken({ userId: user.id, tokenId }) | ||
if (!error) mutate({ apiTokens: apiTokens.filter((t) => t.id !== tokenId) }) | ||
} | ||
|
||
return ( | ||
<Stack spacing={4}> | ||
<Heading fontSize="2xl">API tokens</Heading> | ||
<Text> | ||
These tokens allow other apps to control your whole account and | ||
typebots. Be careful! | ||
</Text> | ||
<Flex justifyContent="flex-end"> | ||
<Button onClick={onCreateOpen}>Create</Button> | ||
<CreateTokenModal | ||
userId={user.id} | ||
isOpen={isCreateOpen} | ||
onNewToken={refreshListWithNewToken} | ||
onClose={onCreateClose} | ||
/> | ||
</Flex> | ||
|
||
<TableContainer> | ||
<Table> | ||
<Thead> | ||
<Tr> | ||
<Th>Name</Th> | ||
<Th w="130px">Created</Th> | ||
<Th w="0" /> | ||
</Tr> | ||
</Thead> | ||
<Tbody> | ||
{apiTokens?.map((token) => ( | ||
<Tr key={token.id}> | ||
<Td>{token.name}</Td> | ||
<Td>{timeSince(token.createdAt)} ago</Td> | ||
<Td> | ||
<Button | ||
size="xs" | ||
colorScheme="red" | ||
variant="outline" | ||
onClick={() => setDeletingId(token.id)} | ||
> | ||
Delete | ||
</Button> | ||
</Td> | ||
</Tr> | ||
))} | ||
{isLoading && | ||
Array.from({ length: 3 }).map((_, idx) => ( | ||
<Tr key={idx}> | ||
<Td> | ||
<Checkbox isDisabled /> | ||
</Td> | ||
<Td> | ||
<Skeleton h="5px" /> | ||
</Td> | ||
<Td> | ||
<Skeleton h="5px" /> | ||
</Td> | ||
</Tr> | ||
))} | ||
</Tbody> | ||
</Table> | ||
</TableContainer> | ||
<ConfirmModal | ||
isOpen={isDefined(deletingId)} | ||
onConfirm={() => deleteToken(deletingId)} | ||
onClose={() => setDeletingId(undefined)} | ||
message={ | ||
<Text> | ||
The token <strong>{apiTokens?.find(byId(deletingId))?.name}</strong>{' '} | ||
will be permanently deleted, are you sure you want to continue? | ||
</Text> | ||
} | ||
confirmButtonLabel="Delete" | ||
/> | ||
</Stack> | ||
) | ||
} |
100 changes: 100 additions & 0 deletions
100
...ponents/dashboard/WorkspaceSettingsModal/MyAccountForm/ApiTokensList/CreateTokenModal.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
import { | ||
Modal, | ||
ModalOverlay, | ||
ModalContent, | ||
ModalHeader, | ||
ModalCloseButton, | ||
ModalBody, | ||
Stack, | ||
Input, | ||
ModalFooter, | ||
Button, | ||
Text, | ||
InputGroup, | ||
InputRightElement, | ||
} from '@chakra-ui/react' | ||
import { CopyButton } from 'components/shared/buttons/CopyButton' | ||
import React, { FormEvent, useState } from 'react' | ||
import { ApiTokenFromServer, createApiToken } from 'services/user/apiTokens' | ||
|
||
type Props = { | ||
userId: string | ||
isOpen: boolean | ||
onNewToken: (token: ApiTokenFromServer) => void | ||
onClose: () => void | ||
} | ||
|
||
export const CreateTokenModal = ({ | ||
userId, | ||
isOpen, | ||
onClose, | ||
onNewToken, | ||
}: Props) => { | ||
const [name, setName] = useState('') | ||
const [isSubmitting, setIsSubmitting] = useState(false) | ||
const [newTokenValue, setNewTokenValue] = useState<string>() | ||
|
||
const createToken = async (e: FormEvent) => { | ||
e.preventDefault() | ||
setIsSubmitting(true) | ||
const { data } = await createApiToken(userId, { name }) | ||
if (data?.apiToken) { | ||
setNewTokenValue(data.apiToken.token) | ||
onNewToken(data.apiToken) | ||
} | ||
setIsSubmitting(false) | ||
} | ||
return ( | ||
<Modal isOpen={isOpen} onClose={onClose}> | ||
<ModalOverlay /> | ||
<ModalContent> | ||
<ModalHeader> | ||
{newTokenValue ? 'Token Created' : 'Create Token'} | ||
</ModalHeader> | ||
<ModalCloseButton /> | ||
{newTokenValue ? ( | ||
<ModalBody as={Stack} spacing="4"> | ||
<Text> | ||
Please copy your token and store it in a safe place.{' '} | ||
<strong>For security reasons we cannot show it again.</strong> | ||
</Text> | ||
<InputGroup size="md"> | ||
<Input readOnly pr="4.5rem" value={newTokenValue} /> | ||
<InputRightElement width="4.5rem"> | ||
<CopyButton h="1.75rem" size="sm" textToCopy={newTokenValue} /> | ||
</InputRightElement> | ||
</InputGroup> | ||
</ModalBody> | ||
) : ( | ||
<ModalBody as="form" onSubmit={createToken}> | ||
<Text mb="4"> | ||
Enter a unique name for your token to differentiate it from other | ||
tokens. | ||
</Text> | ||
<Input | ||
placeholder="I.e. Zapier, Github, Make.com" | ||
onChange={(e) => setName(e.target.value)} | ||
/> | ||
</ModalBody> | ||
)} | ||
|
||
<ModalFooter> | ||
{newTokenValue ? ( | ||
<Button onClick={onClose} colorScheme="blue"> | ||
Done | ||
</Button> | ||
) : ( | ||
<Button | ||
colorScheme="blue" | ||
isDisabled={name.length === 0} | ||
isLoading={isSubmitting} | ||
onClick={createToken} | ||
> | ||
Create token | ||
</Button> | ||
)} | ||
</ModalFooter> | ||
</ModalContent> | ||
</Modal> | ||
) | ||
} |
1 change: 1 addition & 0 deletions
1
...builder/components/dashboard/WorkspaceSettingsModal/MyAccountForm/ApiTokensList/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { ApiTokensList } from './ApiTokensList' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1 change: 1 addition & 0 deletions
1
apps/builder/components/dashboard/WorkspaceSettingsModal/MyAccountForm/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { MyAccountForm } from './MyAccountForm' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import { withSentry } from '@sentry/nextjs' | ||
import prisma from 'libs/prisma' | ||
import { NextApiRequest, NextApiResponse } from 'next' | ||
import { getAuthenticatedUser } from 'services/api/utils' | ||
import { generateId, methodNotAllowed, notAuthenticated } from 'utils' | ||
|
||
const handler = async (req: NextApiRequest, res: NextApiResponse) => { | ||
const user = await getAuthenticatedUser(req) | ||
if (!user) return notAuthenticated(res) | ||
if (req.method === 'GET') { | ||
const apiTokens = await prisma.apiToken.findMany({ | ||
where: { ownerId: user.id }, | ||
select: { | ||
id: true, | ||
name: true, | ||
createdAt: true, | ||
}, | ||
orderBy: { createdAt: 'desc' }, | ||
}) | ||
return res.send({ apiTokens }) | ||
} | ||
if (req.method === 'POST') { | ||
const data = typeof req.body === 'string' ? JSON.parse(req.body) : req.body | ||
const apiToken = await prisma.apiToken.create({ | ||
data: { name: data.name, ownerId: user.id, token: generateId(24) }, | ||
}) | ||
return res.send({ | ||
apiToken: { | ||
id: apiToken.id, | ||
name: apiToken.name, | ||
createdAt: apiToken.createdAt, | ||
token: apiToken.token, | ||
}, | ||
}) | ||
} | ||
methodNotAllowed(res) | ||
} | ||
|
||
export default withSentry(handler) |
Oops, something went wrong.
a0929c4
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs:
viewer-v2-alpha – ./apps/viewer
sat.cr8.ai
bt.id8rs.com
an.nigerias.io
ar.nigerias.io
am.nigerias.io
apo.nigerias.io
chat.sureb4.com
aso.nigerias.io
apr.nigerias.io
vhpage.cr8.ai
games.klujo.com
eventhub.com.au
sakuranembro.it
bot.piccinato.co
bot.upfunnel.art
feedback.ofx.one
faqs.nigerias.io
clo.closeer.work
voicehelp.cr8.ai
stan.vselise.com
app.chatforms.net
zap.techadviser.in
bot.eventhub.com.au
forms.webisharp.com
bot.cotemeuplano.com
bot.ansuraniphone.my
bot.incusservices.com
chat.hayurihijab.com
typebot.stillio.com
bot.meuesocial.com.br
gcase.barrettamario.it
c23111azqw.nigerias.io
info.clickasuransi.com
kodawariab736.skeep.it
serviziaziendali.online
83242573.actualizar.xyz
hunterbot.saleshunter.ai
mainmenu.diddancing.com
type.opaulovieira.com.br
aibot.angrybranding.co.uk
boyfriend-breakup.riku.ai
type.dericsoncalari.com.br
piazzatorre.barrettamario.it
onboarding.libertydreamcare.ie
bookings.littlepartymonkeys.com
studiotecnicoimmobiliaremerelli.it
viewer-v2-alpha-typebot-io.vercel.app
type.talitasouzamarques.com.br
bot.comercializadoraomicron.com
personal-trainer.barrettamario.it
viewer-v2-alpha-git-main-typebot-io.vercel.app
a0929c4
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs:
viewer-v2 – ./apps/viewer
bot.joof.it
bergamo.store
yoda.riku.ai
app.yvon.earth
gollum.riku.ai
talk.gocare.io
bot.tvbeat.it
bots.bridge.ai
bot.jesopizz.it
chat.hayuri.id
viewer.typebot.io
bot.contakit.com
fitness.riku.ai
bot.rihabilita.it
zap.fundviser.in
bot.dsignagency.com
bot.danyservice.it
chatbot.matthesv.de
88584434.therpm.club
demo.wemakebots.xyz
92109660.therpm.club
bot.barrettamario.it
hello.advergreen.com
bot.digitalpointer.id
bot.coachayongzul.com
bot.eikju.photography
bot.outstandbrand.com
bot.robertohairlab.it
criar.somaperuzzo.com
bot.ilmuseoaiborghi.it
bot.pratikmandalia.com
form.bridesquadapp.com
michaeljackson.riku.ai
88152257.actualizar.xyz
87656003.actualizar.xyz
arrivalx2.wpwakanda.com
91375310.actualizar.xyz
bot.hotelplayarimini.it
invite.bridesquadapp.com
link.venturasuceder.com
bot.amicidisanfaustino.it
chat.thehomebuyersusa.com
bot.adventureconsulting.hu
forms.hiabhaykulkarni.com
typebot-viewer.vercel.app
herbalife.barrettamario.it
casestudyemb.wpwakanda.com
chat.atlasoutfittersk9.com
homepageonly.wpwakanda.com
liveconvert.kandalearn.com
mainmenu1one.wpwakanda.com
tarian.theiofoundation.org
bot.pinpointinteractive.com
bot.polychromes-project.com
bot.seidinembroseanchetu.it
forms.escoladeautomacao.com.br
bot.seidibergamoseanchetu.it
liveconvert2.kandalearn.com
bot.studiotecnicoimmobiliaremerelli.it
viewer-v2-git-main-typebot-io.vercel.app
viewer-v2-typebot-io.vercel.app
a0929c4
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs:
landing-page-v2 – ./apps/landing-page
landing-page-v2-typebot-io.vercel.app
landing-page-v2-git-main-typebot-io.vercel.app
www.get-typebot.com
get-typebot.com
www.typebot.io
typebot.io
a0929c4
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs:
builder-v2 – ./apps/builder
app.typebot.io
builder-v2-typebot-io.vercel.app
builder-v2-git-main-typebot-io.vercel.app