diff --git a/components/ApiMethodTag.tsx b/components/ApiMethodTag.tsx new file mode 100644 index 0000000..0bbb216 --- /dev/null +++ b/components/ApiMethodTag.tsx @@ -0,0 +1,29 @@ +import { Tag, TagProps } from '@chakra-ui/react'; +import { ApiMethod } from '@prisma/client'; + +type Props = TagProps & { + method: ApiMethod; +}; + +const config: Record = { + GET: { + children: "GET", + colorScheme: "green", + }, + POST: { + children: "POST", + colorScheme: "yellow", + }, + PUT: { + children: "PUT", + colorScheme: "blue", + }, + DELETE: { + children: "DEL", + colorScheme: "red", + }, +}; + +export default function ApiMethodTag({ method, ...props }: Props) { + return ; +} diff --git a/components/BackLink.tsx b/components/BackLink.tsx index 0544eec..58d4e5e 100644 --- a/components/BackLink.tsx +++ b/components/BackLink.tsx @@ -1,5 +1,5 @@ import { Button } from '@chakra-ui/react'; -import { ArrowBackIcon } from '@chakra-ui/icons'; +import { ChevronLeftIcon } from '@heroicons/react/outline'; import { useRouter } from 'next/router'; export default function BackLink(props) { @@ -7,7 +7,7 @@ export default function BackLink(props) { return (
-
) } diff --git a/components/ConfirmDialog.tsx b/components/ConfirmDialog.tsx new file mode 100644 index 0000000..f4a7d00 --- /dev/null +++ b/components/ConfirmDialog.tsx @@ -0,0 +1,109 @@ +import { + AlertDialog, + AlertDialogBody, + AlertDialogContent, + AlertDialogFooter, + AlertDialogHeader, + AlertDialogOverlay, + Button, + ChakraProvider +} from '@chakra-ui/react'; +import { useRef } from 'react'; +import { render, unmountComponentAtNode } from 'react-dom'; + +import theme from '@/lib/chakra-theme'; + +type ConfirmDialogOptions = { + title: string; + description: string; + btnConfirmTxt: string; +}; + +type AlertComponentProps = ConfirmDialogOptions & { + onCancel: () => any; + onConfirm: () => any; +}; + +function AlertComponent({ + title, + description, + btnConfirmTxt, + onCancel, + onConfirm +}: AlertComponentProps) { + const cancelRef = useRef(); + + return ( + + + + + + {title} + + + + {description} + + + + + + + + + + + ); +} + +/** + * Helper function to show confirm dialog + * @param param0 Options for confirm dialog shown + * @returns Promise which resolves to a boolean indicating whether user confirmed the action + */ +function confirmDialog({ + title = 'Are you sure?', + description = 'This action is irreversible.', + btnConfirmTxt = 'Confirm', +}: Partial) { + let container = document.getElementById('alert-dialog'); + if (!container) { + container = document.createElement('div'); + container.id = 'alert-dialog'; + document.body.appendChild(container); + } + + return new Promise((resolve) => { + const close = () => { + unmountComponentAtNode(container); + container.remove(); + }; + + const handleCancel = () => { + close(); + resolve(false); + }; + const handleConfirm = () => { + close(); + resolve(true); + }; + + render( + , + container + ); + }); +} + +export default confirmDialog; diff --git a/components/QueryParamInput.tsx b/components/QueryParamInput.tsx index c8e70bd..0ff9edf 100644 --- a/components/QueryParamInput.tsx +++ b/components/QueryParamInput.tsx @@ -1,5 +1,5 @@ import { Flex, Input, IconButton, InputProps } from '@chakra-ui/react'; -import { DeleteIcon } from '@chakra-ui/icons'; +import { XIcon } from '@heroicons/react/outline'; import { MouseEventHandler } from 'react'; import SecretInput, { SecretInputProps } from './SecretInput'; @@ -15,9 +15,8 @@ export default function QueryParamInput({ keyProps, valueProps, onRemove }: Prop alignItems="center" justifyContent="space-between" border="1px" - borderColor="gray.200" - py="3" - px="6" + borderColor="gray.100" + p="3" bg="white" _first={{ roundedTop: "md" }} _notFirst={{ mt: -1 }} @@ -26,18 +25,22 @@ export default function QueryParamInput({ keyProps, valueProps, onRemove }: Prop } + icon={} + variant="ghost" aria-label="Remove" size="sm" - colorScheme="gray" + color="gray.500" onClick={onRemove} /> diff --git a/components/index.ts b/components/index.ts index f15b9c0..22267b4 100644 --- a/components/index.ts +++ b/components/index.ts @@ -1,3 +1,4 @@ +export { default as ApiMethodTag } from './ApiMethodTag'; export { default as ApiStats } from './ApiStats'; export { default as BackLink } from './BackLink'; export { default as Footer } from './Footer'; @@ -6,3 +7,4 @@ export { default as MockDeploymentBanner } from './MockDeploymentBanner'; export { default as QueryParamInput } from './QueryParamInput'; export { default as SecretInput } from './SecretInput'; export { default as SectionHeading } from './SectionHeading'; +export { default as confirmDialog } from './ConfirmDialog'; diff --git a/lib/chakra-theme.ts b/lib/chakra-theme.ts new file mode 100644 index 0000000..fc59b92 --- /dev/null +++ b/lib/chakra-theme.ts @@ -0,0 +1,15 @@ +import { extendTheme, ThemeConfig } from '@chakra-ui/react'; + +const theme = extendTheme({ + config: { + initialColorMode: 'light', + useSystemColorMode: false, + }, + fonts: { + heading: "Raleway", + body: "Inter", + }, +} as ThemeConfig); + + +export default theme; diff --git a/package-lock.json b/package-lock.json index cce4009..bf8138f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -556,26 +556,46 @@ } }, "@chakra-ui/accordion": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@chakra-ui/accordion/-/accordion-1.4.1.tgz", - "integrity": "sha512-/E0FW5YHNVD6WwMGiuQuXpA70P2CKAV+MzcMITnSGPWsh9XD0mcXvMkIALVojfFk9tcCFdIGnxX/HWr41LzgIg==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@chakra-ui/accordion/-/accordion-1.4.3.tgz", + "integrity": "sha512-UKpi7xd+hcT/OIDRBRT4vkvVmpym5K9tf3tPyPdwpJcCfCd0D8dvmgZWBM4vCCRPCNfuoyxba5z97witzLCf+g==", "requires": { "@chakra-ui/descendant": "2.1.1", - "@chakra-ui/hooks": "1.7.1", - "@chakra-ui/icon": "1.2.1", + "@chakra-ui/hooks": "1.7.2", + "@chakra-ui/icon": "2.0.0", "@chakra-ui/react-utils": "1.2.1", - "@chakra-ui/transition": "1.4.1", + "@chakra-ui/transition": "1.4.2", "@chakra-ui/utils": "1.9.1" + }, + "dependencies": { + "@chakra-ui/icon": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@chakra-ui/icon/-/icon-2.0.0.tgz", + "integrity": "sha512-/GuU+xIcOIy9uSUUUCu249ZJB/nLDbjWGkfpoSdBwqT4+ytJrKt+0Ckh3Ub14sz3BJD+Z6IiIt6ySOA9+7lbsA==", + "requires": { + "@chakra-ui/utils": "1.9.1" + } + } } }, "@chakra-ui/alert": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@chakra-ui/alert/-/alert-1.3.1.tgz", - "integrity": "sha512-BeR6l/1CLZarA3uAe+5Q3hioYf7SixYfy9rOte/29ck1lx9PLjjuPYYmuDPtZNbGibhUCh48z4U/uK2x8mbpKQ==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@chakra-ui/alert/-/alert-1.3.2.tgz", + "integrity": "sha512-+OMeVeGtydpj6nry0zH7qFDt36zEaxckRnufx1BGiCfWdUg6ahVwKXl8qX93Q8w82od7eAoBKMgGJz7IVL5NPw==", "requires": { - "@chakra-ui/icon": "1.2.1", + "@chakra-ui/icon": "2.0.0", "@chakra-ui/react-utils": "1.2.1", "@chakra-ui/utils": "1.9.1" + }, + "dependencies": { + "@chakra-ui/icon": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@chakra-ui/icon/-/icon-2.0.0.tgz", + "integrity": "sha512-/GuU+xIcOIy9uSUUUCu249ZJB/nLDbjWGkfpoSdBwqT4+ytJrKt+0Ckh3Ub14sz3BJD+Z6IiIt6ySOA9+7lbsA==", + "requires": { + "@chakra-ui/utils": "1.9.1" + } + } } }, "@chakra-ui/anatomy": { @@ -587,11 +607,11 @@ } }, "@chakra-ui/avatar": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@chakra-ui/avatar/-/avatar-1.3.1.tgz", - "integrity": "sha512-WI0/kcpTJViOH093V0bz8EB+e/rc+gjF+T5DkOuh1YWFxRRG5v+4Yd3PdEJtQgzWtBVhlbGWmE7WvBizyKwFCA==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@chakra-ui/avatar/-/avatar-1.3.2.tgz", + "integrity": "sha512-Z4CQI2haksy0YIV1gKa967P94WZUVzlMN+Wgs8PJJoxxmeY6tVruuvp5+Zb5D5kSAmQBvGWxlgJjClKXzeCQ7A==", "requires": { - "@chakra-ui/image": "1.1.1", + "@chakra-ui/image": "1.1.2", "@chakra-ui/react-utils": "1.2.1", "@chakra-ui/utils": "1.9.1" } @@ -606,22 +626,22 @@ } }, "@chakra-ui/button": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@chakra-ui/button/-/button-1.5.1.tgz", - "integrity": "sha512-BvP29quEhP6OTgDiRsugD6adgkeOTEQpoDsZUVEmHnNVrbFfdsICEKKQTtDJ2iPf+hmpFrtnpN50vCLdAANKcw==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@chakra-ui/button/-/button-1.5.2.tgz", + "integrity": "sha512-1LyZ7o4g+ZF0Qfwr77Fa3qHtCGhghoIPG2lcUWhhPk+8ygHNF0ZOngfsiDD7aoEj0uXsvlgZ/hdiqv0PmMTRzg==", "requires": { - "@chakra-ui/hooks": "1.7.1", + "@chakra-ui/hooks": "1.7.2", "@chakra-ui/react-utils": "1.2.1", "@chakra-ui/spinner": "1.2.1", "@chakra-ui/utils": "1.9.1" } }, "@chakra-ui/checkbox": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@chakra-ui/checkbox/-/checkbox-1.6.1.tgz", - "integrity": "sha512-Z5ZMeUYIRjRbi/knhYhSQshZH7OnROA7ezl9a9oVSKRF7iLMNMibQSlQLXmqUWaTKSgrS37cpKAzfgEuemyiUQ==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@chakra-ui/checkbox/-/checkbox-1.6.2.tgz", + "integrity": "sha512-eu4MeKWqwFc3zakjMnUi1pGXQ17HzeWbvQHwEZCYgIDk+S9DXopQr8o38zaHzs/MHmlelCzM96IBgTWZXWR/eg==", "requires": { - "@chakra-ui/hooks": "1.7.1", + "@chakra-ui/hooks": "1.7.2", "@chakra-ui/react-utils": "1.2.1", "@chakra-ui/utils": "1.9.1", "@chakra-ui/visually-hidden": "1.1.1" @@ -637,20 +657,30 @@ } }, "@chakra-ui/close-button": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@chakra-ui/close-button/-/close-button-1.2.1.tgz", - "integrity": "sha512-A/cuFtJPF8rp5p6tCIGlQdHB89gLCSOzxWssoTXAGJnmlwY2YunFHxgkYZXwPbDqFrM8ndya7Ys+AuL1JZsa3g==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@chakra-ui/close-button/-/close-button-1.2.2.tgz", + "integrity": "sha512-SqeLib0qgMjK3OsO1g5OnAHUmdCC8GMjToNEea7TeSrA44bH9EXVhFTkMMu2PnDVHbQmi4Ee1cuulNJt0UhQ3g==", "requires": { - "@chakra-ui/icon": "1.2.1", + "@chakra-ui/icon": "2.0.0", "@chakra-ui/utils": "1.9.1" + }, + "dependencies": { + "@chakra-ui/icon": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@chakra-ui/icon/-/icon-2.0.0.tgz", + "integrity": "sha512-/GuU+xIcOIy9uSUUUCu249ZJB/nLDbjWGkfpoSdBwqT4+ytJrKt+0Ckh3Ub14sz3BJD+Z6IiIt6ySOA9+7lbsA==", + "requires": { + "@chakra-ui/utils": "1.9.1" + } + } } }, "@chakra-ui/color-mode": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@chakra-ui/color-mode/-/color-mode-1.3.1.tgz", - "integrity": "sha512-UuuYMfYxaBE5fPtIR6dwIJn3snT0tVX67RN2RHv4/LQgUeiddq4VziXT3bd+tyIe9+zcsqrZhV7J7YP0h/Id/Q==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@chakra-ui/color-mode/-/color-mode-1.3.3.tgz", + "integrity": "sha512-vEMG9PRtVllAxbJE76bM4fRdo+hRZsPX/9cO+gR1YegYQNeobbV9Ive/MKNYQzdlbQ855Ytn6cPGr2hzy9MdRg==", "requires": { - "@chakra-ui/hooks": "1.7.1", + "@chakra-ui/hooks": "1.7.2", "@chakra-ui/react-env": "1.1.1", "@chakra-ui/utils": "1.9.1" } @@ -664,11 +694,11 @@ } }, "@chakra-ui/counter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@chakra-ui/counter/-/counter-1.2.1.tgz", - "integrity": "sha512-Gm4njMzEsDyAzdQtExn40TvmupzkPBrT5DiCu0DlxYqpLqCfqV49HgJHEG5oW3WV+WaC9mzg7VV+idKYh/d+Gg==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@chakra-ui/counter/-/counter-1.2.2.tgz", + "integrity": "sha512-EljrsJYHpR5tZ1UczzlZ7gwKZs3ijF2tKCAAmsTpRerPbwGFvrmhfFfLexgbc0vxmeuZYUVeuiClLXQT4lvd5w==", "requires": { - "@chakra-ui/hooks": "1.7.1", + "@chakra-ui/hooks": "1.7.2", "@chakra-ui/utils": "1.9.1" } }, @@ -686,11 +716,11 @@ } }, "@chakra-ui/editable": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@chakra-ui/editable/-/editable-1.3.1.tgz", - "integrity": "sha512-MwyTtsnHNqmKmHv9SH3KIHWa06D4gBwcuTawTiSnYBUJL6My8ry/Wdca1to9So2tD6hcjz3TPTzOJOlyv0eiZg==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@chakra-ui/editable/-/editable-1.3.2.tgz", + "integrity": "sha512-WY0dq+hQOIyMAamFj2fECNb1AtOwxoddAbZ6k4/epiKNkaRA5ENzgPdV6Gw3t02fDXv95D0J4V4XcpNgfCz6TA==", "requires": { - "@chakra-ui/hooks": "1.7.1", + "@chakra-ui/hooks": "1.7.2", "@chakra-ui/react-utils": "1.2.1", "@chakra-ui/utils": "1.9.1" } @@ -705,20 +735,30 @@ } }, "@chakra-ui/form-control": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@chakra-ui/form-control/-/form-control-1.5.1.tgz", - "integrity": "sha512-ASZYQFOs5mAoaNXAN/ZaesMy3XV07F0/Eba5PQ7Dejdn91aep6lqF889hmr8yqcR646xCOY7ISyYsskfh9QHrQ==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@chakra-ui/form-control/-/form-control-1.5.3.tgz", + "integrity": "sha512-+UkOJJYUSGVATeNK/2b+KJx3qRGAtqpD1sR2mqd9DhgmJ/JUGV8q4LVcXIcVs/7BYNqP9B0JQUBIDlHNuTwlJA==", "requires": { - "@chakra-ui/hooks": "1.7.1", - "@chakra-ui/icon": "1.2.1", + "@chakra-ui/hooks": "1.7.2", + "@chakra-ui/icon": "2.0.0", "@chakra-ui/react-utils": "1.2.1", "@chakra-ui/utils": "1.9.1" + }, + "dependencies": { + "@chakra-ui/icon": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@chakra-ui/icon/-/icon-2.0.0.tgz", + "integrity": "sha512-/GuU+xIcOIy9uSUUUCu249ZJB/nLDbjWGkfpoSdBwqT4+ytJrKt+0Ckh3Ub14sz3BJD+Z6IiIt6ySOA9+7lbsA==", + "requires": { + "@chakra-ui/utils": "1.9.1" + } + } } }, "@chakra-ui/hooks": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@chakra-ui/hooks/-/hooks-1.7.1.tgz", - "integrity": "sha512-hgN19X6GUKQYAHczmFY+GAT8vl9h+X+nGWrIAnmvZ6BgUXxDajnTNhZeWhj0ZkR+7A7dCE6Y/3X44GafUgChMw==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@chakra-ui/hooks/-/hooks-1.7.2.tgz", + "integrity": "sha512-XJnya9ugAPYUedtQULKaLYBezE9cZMOkDm0MQl7FEuJKZ9ocHD6Pwpwf9Z03R91XQmcNL8gZ1NS0GT9v/xNl3Q==", "requires": { "@chakra-ui/react-utils": "1.2.1", "@chakra-ui/utils": "1.9.1", @@ -726,50 +766,43 @@ "copy-to-clipboard": "3.3.1" } }, - "@chakra-ui/icon": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@chakra-ui/icon/-/icon-1.2.1.tgz", - "integrity": "sha512-uZxFsiY4Tld+LvGIX7cky0H6oMRac8udPMQRzIk/UQeNZcsWisGetatbQsew3y1lWV/iH/8+TlDuW13GWGyGGQ==", - "requires": { - "@chakra-ui/utils": "1.9.1" - } - }, - "@chakra-ui/icons": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@chakra-ui/icons/-/icons-1.1.1.tgz", - "integrity": "sha512-/+u6euCOFw6J1DZW7NcVFtib4mygJBoqRdsKiU1Z3uiTC+zQTBzcCt54NQ+kK8rhuNzJ+odahnt/AbjBJgZ+5A==", - "requires": { - "@chakra-ui/icon": "1.2.1", - "@types/react": "^17.0.15" - } - }, "@chakra-ui/image": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@chakra-ui/image/-/image-1.1.1.tgz", - "integrity": "sha512-bz1pn08XlXcO3r1KnpdjQgN3R2soiTx10sG2d5Pw9BdGdySf7Y73wiLh+Tan1xJHp6p2KH1hz4f7uKXXDn7Qmw==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@chakra-ui/image/-/image-1.1.2.tgz", + "integrity": "sha512-bW4PMONYpWRLJ10di7W5BhYUOcCohNLhiTygOmVRMHWfUk9vmxhORlNu0EaSXUKGXiQ35cTVu4Ysv3L/1xYPRQ==", "requires": { - "@chakra-ui/hooks": "1.7.1", + "@chakra-ui/hooks": "1.7.2", "@chakra-ui/utils": "1.9.1" } }, "@chakra-ui/input": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@chakra-ui/input/-/input-1.3.1.tgz", - "integrity": "sha512-Z+LqkwVPMeUBuvB9dLDPKkBnWV52Q1PVl3KW9ouDIFg7SoemeYkBt3p4ttEKE+eIPsPlrcH1u2A/RGcCTZOe1g==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@chakra-ui/input/-/input-1.3.3.tgz", + "integrity": "sha512-Fsivp608cKdc2tSQvPXczHtyfU6YHLju+EuAs5pjqKC8ZTwPawBRkCvlTGPPd7VwyTHkp08X5qARCxEgjRFbzw==", "requires": { - "@chakra-ui/form-control": "1.5.1", + "@chakra-ui/form-control": "1.5.3", "@chakra-ui/react-utils": "1.2.1", "@chakra-ui/utils": "1.9.1" } }, "@chakra-ui/layout": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@chakra-ui/layout/-/layout-1.5.1.tgz", - "integrity": "sha512-nKiyZ5adjNTbBV3oFIUGIPijwutO1NGdev1jHtnZc3xo2urCIkBvKU8+mVjlX04IwZ7oLKoP3EiDDv0g7+o41Q==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@chakra-ui/layout/-/layout-1.7.0.tgz", + "integrity": "sha512-ZjRqLGs16T4PcWH445SkELVuxxfecjjUeprtFnNw13QzwydP46L8+GB3ycp6wyJDa6DMo77TxQQnK5jUUwY6Mw==", "requires": { - "@chakra-ui/icon": "1.2.1", + "@chakra-ui/icon": "2.0.0", "@chakra-ui/react-utils": "1.2.1", "@chakra-ui/utils": "1.9.1" + }, + "dependencies": { + "@chakra-ui/icon": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@chakra-ui/icon/-/icon-2.0.0.tgz", + "integrity": "sha512-/GuU+xIcOIy9uSUUUCu249ZJB/nLDbjWGkfpoSdBwqT4+ytJrKt+0Ckh3Ub14sz3BJD+Z6IiIt6ySOA9+7lbsA==", + "requires": { + "@chakra-ui/utils": "1.9.1" + } + } } }, "@chakra-ui/live-region": { @@ -781,75 +814,85 @@ } }, "@chakra-ui/media-query": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@chakra-ui/media-query/-/media-query-1.2.1.tgz", - "integrity": "sha512-Ho/qiPGTjNukFTE9WBdYV9FIXU7KFTJPqdRQPWANkz+j275n6sqSE1j5LRJllP+ett21KeuWLN4zL33pP0Ox+g==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@chakra-ui/media-query/-/media-query-1.2.3.tgz", + "integrity": "sha512-DbStv1VUSBwFj/MNemxRUtoibSoR9ZRcW31UUjtkiIH58cSB5lyEPv9rdD/1HRXpJfSaWQ439Tbuf03gOC4SVQ==", "requires": { "@chakra-ui/react-env": "1.1.1", "@chakra-ui/utils": "1.9.1" } }, "@chakra-ui/menu": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@chakra-ui/menu/-/menu-1.8.1.tgz", - "integrity": "sha512-fgzzFukBj4sQzTRf4q/+nHiVTKhrMtJdofnluqce/SCRJ1G+bbovUySblTzfI8iFlTSZt/eWc/Nju4JB1S+3Yg==", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@chakra-ui/menu/-/menu-1.8.3.tgz", + "integrity": "sha512-TehcqHLKlMdkeXTtCYXzWNa6nbAk1cpjGz6OPl2ua0eisoOKgPolpkreCfYrWV9NNk0BmzZn+Su+z60jbhqggA==", "requires": { "@chakra-ui/clickable": "1.2.1", "@chakra-ui/descendant": "2.1.1", - "@chakra-ui/hooks": "1.7.1", + "@chakra-ui/hooks": "1.7.2", "@chakra-ui/popper": "2.4.1", "@chakra-ui/react-utils": "1.2.1", - "@chakra-ui/transition": "1.4.1", + "@chakra-ui/transition": "1.4.2", "@chakra-ui/utils": "1.9.1" } }, "@chakra-ui/modal": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@chakra-ui/modal/-/modal-1.10.1.tgz", - "integrity": "sha512-cboC2ITm+5FjhrBc6yJ5cW4VXnfwlLhFa1EkPqF1k4kvYGyUHArvPN1q8AiPYOIrupHYu2Iu6YmQPg7TJwNImg==", + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/@chakra-ui/modal/-/modal-1.10.3.tgz", + "integrity": "sha512-b0kVv4kNFWVbJPprEgFqqBH8EeneLAueSV+0t9Z1MpvIF0EUB6qe2JQZ0X8eDOtNYX4Tp7Y7LRCQ/M/HMm9WRw==", "requires": { - "@chakra-ui/close-button": "1.2.1", + "@chakra-ui/close-button": "1.2.2", "@chakra-ui/focus-lock": "1.2.1", - "@chakra-ui/hooks": "1.7.1", - "@chakra-ui/portal": "1.3.1", + "@chakra-ui/hooks": "1.7.2", + "@chakra-ui/portal": "1.3.2", "@chakra-ui/react-utils": "1.2.1", - "@chakra-ui/transition": "1.4.1", + "@chakra-ui/transition": "1.4.2", "@chakra-ui/utils": "1.9.1", "aria-hidden": "^1.1.1", "react-remove-scroll": "2.4.1" } }, "@chakra-ui/number-input": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@chakra-ui/number-input/-/number-input-1.3.1.tgz", - "integrity": "sha512-4vBRSShT5pedElgP9YGVC+9RHzQGmUVZqu3p0gZW0fLGVVQ9C1EGrO7djL+k3tgklyu8RvSwkRDJqEPvbQKDgQ==", - "requires": { - "@chakra-ui/counter": "1.2.1", - "@chakra-ui/form-control": "1.5.1", - "@chakra-ui/hooks": "1.7.1", - "@chakra-ui/icon": "1.2.1", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@chakra-ui/number-input/-/number-input-1.3.3.tgz", + "integrity": "sha512-nptvORoG+PvvuURkzh0juSYxj3L9HnWIeNncC/7oXgm2AFGxIcqUk8pUJaUNM2mlbLjJZS19/MWlfzgsYJmJrQ==", + "requires": { + "@chakra-ui/counter": "1.2.2", + "@chakra-ui/form-control": "1.5.3", + "@chakra-ui/hooks": "1.7.2", + "@chakra-ui/icon": "2.0.0", "@chakra-ui/react-utils": "1.2.1", "@chakra-ui/utils": "1.9.1" + }, + "dependencies": { + "@chakra-ui/icon": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@chakra-ui/icon/-/icon-2.0.0.tgz", + "integrity": "sha512-/GuU+xIcOIy9uSUUUCu249ZJB/nLDbjWGkfpoSdBwqT4+ytJrKt+0Ckh3Ub14sz3BJD+Z6IiIt6ySOA9+7lbsA==", + "requires": { + "@chakra-ui/utils": "1.9.1" + } + } } }, "@chakra-ui/pin-input": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@chakra-ui/pin-input/-/pin-input-1.7.1.tgz", - "integrity": "sha512-eFFc5sofiyion+NxELWfCzD23XHIBDrJcfKKbNxt8jdXg9Ek4mFpmvnxBVrK0DIz6cVYgKY8c364OmxNUf4IyA==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@chakra-ui/pin-input/-/pin-input-1.7.2.tgz", + "integrity": "sha512-2dGNdU+Xlu0u1OxuelJBKQu7dDKaD5kN9moZMoKpjpXB8Kibh7GM3OO/Z25aMM/E9Kly21qXgHju0Tj/ovBJuw==", "requires": { "@chakra-ui/descendant": "2.1.1", - "@chakra-ui/hooks": "1.7.1", + "@chakra-ui/hooks": "1.7.2", "@chakra-ui/react-utils": "1.2.1", "@chakra-ui/utils": "1.9.1" } }, "@chakra-ui/popover": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@chakra-ui/popover/-/popover-1.10.1.tgz", - "integrity": "sha512-/dMUQfd+h9j3GBtkA/nYaQ5xeu4vk0psUClFvLOAJRwXGN3aMrzn/mhrvHWQ/cJuwQrO1WzxH2+g6pwsFOm9ng==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@chakra-ui/popover/-/popover-1.11.1.tgz", + "integrity": "sha512-WV1R2L1V6mbpe6/aInr4yFe6rAu7+pT8Od6Hki5KsIv+4QvoEMYsvJ0VOhaURLLD+NaKXFCsfpc9immluia+AA==", "requires": { - "@chakra-ui/close-button": "1.2.1", - "@chakra-ui/hooks": "1.7.1", + "@chakra-ui/close-button": "1.2.2", + "@chakra-ui/hooks": "1.7.2", "@chakra-ui/popper": "2.4.1", "@chakra-ui/react-utils": "1.2.1", "@chakra-ui/utils": "1.9.1" @@ -865,11 +908,11 @@ } }, "@chakra-ui/portal": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@chakra-ui/portal/-/portal-1.3.1.tgz", - "integrity": "sha512-6UOGZCfujgdijcPs/JTEY5IB5WtKvUbfrSQYsG5CDa+guIwvnoP5qZ+rH6BR6DSSM8Wr/1n+WrtanhfFZShHKA==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@chakra-ui/portal/-/portal-1.3.2.tgz", + "integrity": "sha512-dWUCwEZNpPnbR21+eBbEGuvvOcz5AuS+TZ4V0sUdUEI8B3dPUEylJsveZpYjOCS/YAh4xoxbo6I6haRgrfguvw==", "requires": { - "@chakra-ui/hooks": "1.7.1", + "@chakra-ui/hooks": "1.7.2", "@chakra-ui/react-utils": "1.2.1", "@chakra-ui/utils": "1.9.1" } @@ -884,82 +927,92 @@ } }, "@chakra-ui/provider": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@chakra-ui/provider/-/provider-1.7.1.tgz", - "integrity": "sha512-E2z56BAYytg+sA7arxUtg54AzhYPpR5QUcR4L679aahgiod+5y6H5TSZcTnxTFRLXVLZbBbP/eH63seIcRqCRQ==", + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/@chakra-ui/provider/-/provider-1.7.4.tgz", + "integrity": "sha512-W+mut8fVk6MZx2Sgz4SSIrVVCUAFXE8/AZK3G71qFb9j/7m30zdWCsSzY9yd0XMjJF2cJvEXjEPAVYWz9BEoBA==", "requires": { "@chakra-ui/css-reset": "1.1.1", - "@chakra-ui/hooks": "1.7.1", - "@chakra-ui/portal": "1.3.1", + "@chakra-ui/hooks": "1.7.2", + "@chakra-ui/portal": "1.3.2", "@chakra-ui/react-env": "1.1.1", - "@chakra-ui/system": "1.8.1", + "@chakra-ui/system": "1.9.0", "@chakra-ui/utils": "1.9.1" } }, "@chakra-ui/radio": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@chakra-ui/radio/-/radio-1.4.1.tgz", - "integrity": "sha512-Rq7goauffMNqwGVuPh4zh0kX0AuvTll66PhOwPu+GYHzsYO5+L9X875Q9QBnJEFtDjNF/MVIrH9WrKWjdWLqWw==", + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/@chakra-ui/radio/-/radio-1.4.4.tgz", + "integrity": "sha512-Tz8bl+yhD2pKHUFyNZtP056eawqOUkSA7n2qEebnoH7Zp65B9zwYHkpvL+2nhL5swBwpnGrUpuK3WOqGz4dvXA==", "requires": { - "@chakra-ui/form-control": "1.5.1", - "@chakra-ui/hooks": "1.7.1", + "@chakra-ui/form-control": "1.5.3", + "@chakra-ui/hooks": "1.7.2", "@chakra-ui/react-utils": "1.2.1", "@chakra-ui/utils": "1.9.1", "@chakra-ui/visually-hidden": "1.1.1" } }, "@chakra-ui/react": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@chakra-ui/react/-/react-1.7.1.tgz", - "integrity": "sha512-mbU6M/lxD9BCuXXSEcscPpWqR4mWxXyTk0vkWcgLG59lMFAZ4/Ll+rG1xRHaCuRsAndWNws8h4+NcxY0eECfLQ==", + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/@chakra-ui/react/-/react-1.7.4.tgz", + "integrity": "sha512-wBxfQRcIz6YGXQh3S2E6sXCVcqrVuUygMeMdkCMMfZQTI2VFLkvn6SDYzLHcm1PtMygZnF1mU30GOcmArpVotA==", "requires": { - "@chakra-ui/accordion": "1.4.1", - "@chakra-ui/alert": "1.3.1", - "@chakra-ui/avatar": "1.3.1", + "@chakra-ui/accordion": "1.4.3", + "@chakra-ui/alert": "1.3.2", + "@chakra-ui/avatar": "1.3.2", "@chakra-ui/breadcrumb": "1.3.1", - "@chakra-ui/button": "1.5.1", - "@chakra-ui/checkbox": "1.6.1", - "@chakra-ui/close-button": "1.2.1", + "@chakra-ui/button": "1.5.2", + "@chakra-ui/checkbox": "1.6.2", + "@chakra-ui/close-button": "1.2.2", "@chakra-ui/control-box": "1.1.1", - "@chakra-ui/counter": "1.2.1", + "@chakra-ui/counter": "1.2.2", "@chakra-ui/css-reset": "1.1.1", - "@chakra-ui/editable": "1.3.1", - "@chakra-ui/form-control": "1.5.1", - "@chakra-ui/hooks": "1.7.1", - "@chakra-ui/icon": "1.2.1", - "@chakra-ui/image": "1.1.1", - "@chakra-ui/input": "1.3.1", - "@chakra-ui/layout": "1.5.1", + "@chakra-ui/editable": "1.3.2", + "@chakra-ui/form-control": "1.5.3", + "@chakra-ui/hooks": "1.7.2", + "@chakra-ui/icon": "2.0.0", + "@chakra-ui/image": "1.1.2", + "@chakra-ui/input": "1.3.3", + "@chakra-ui/layout": "1.7.0", "@chakra-ui/live-region": "1.1.1", - "@chakra-ui/media-query": "1.2.1", - "@chakra-ui/menu": "1.8.1", - "@chakra-ui/modal": "1.10.1", - "@chakra-ui/number-input": "1.3.1", - "@chakra-ui/pin-input": "1.7.1", - "@chakra-ui/popover": "1.10.1", + "@chakra-ui/media-query": "1.2.3", + "@chakra-ui/menu": "1.8.3", + "@chakra-ui/modal": "1.10.3", + "@chakra-ui/number-input": "1.3.3", + "@chakra-ui/pin-input": "1.7.2", + "@chakra-ui/popover": "1.11.1", "@chakra-ui/popper": "2.4.1", - "@chakra-ui/portal": "1.3.1", + "@chakra-ui/portal": "1.3.2", "@chakra-ui/progress": "1.2.1", - "@chakra-ui/provider": "1.7.1", - "@chakra-ui/radio": "1.4.1", + "@chakra-ui/provider": "1.7.4", + "@chakra-ui/radio": "1.4.4", "@chakra-ui/react-env": "1.1.1", - "@chakra-ui/select": "1.2.1", - "@chakra-ui/skeleton": "1.2.1", - "@chakra-ui/slider": "1.5.1", + "@chakra-ui/select": "1.2.3", + "@chakra-ui/skeleton": "1.2.4", + "@chakra-ui/slider": "1.5.3", "@chakra-ui/spinner": "1.2.1", - "@chakra-ui/stat": "1.2.1", - "@chakra-ui/switch": "1.3.1", - "@chakra-ui/system": "1.8.1", + "@chakra-ui/stat": "1.2.2", + "@chakra-ui/switch": "1.3.2", + "@chakra-ui/system": "1.9.0", "@chakra-ui/table": "1.3.1", - "@chakra-ui/tabs": "1.6.1", - "@chakra-ui/tag": "1.2.1", - "@chakra-ui/textarea": "1.2.1", - "@chakra-ui/theme": "1.12.1", - "@chakra-ui/toast": "1.4.1", - "@chakra-ui/tooltip": "1.4.1", - "@chakra-ui/transition": "1.4.1", + "@chakra-ui/tabs": "1.6.2", + "@chakra-ui/tag": "1.2.2", + "@chakra-ui/textarea": "1.2.3", + "@chakra-ui/theme": "1.12.3", + "@chakra-ui/toast": "1.5.1", + "@chakra-ui/tooltip": "1.4.3", + "@chakra-ui/transition": "1.4.2", "@chakra-ui/utils": "1.9.1", "@chakra-ui/visually-hidden": "1.1.1" + }, + "dependencies": { + "@chakra-ui/icon": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@chakra-ui/icon/-/icon-2.0.0.tgz", + "integrity": "sha512-/GuU+xIcOIy9uSUUUCu249ZJB/nLDbjWGkfpoSdBwqT4+ytJrKt+0Ckh3Ub14sz3BJD+Z6IiIt6ySOA9+7lbsA==", + "requires": { + "@chakra-ui/utils": "1.9.1" + } + } } }, "@chakra-ui/react-env": { @@ -979,31 +1032,31 @@ } }, "@chakra-ui/select": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@chakra-ui/select/-/select-1.2.1.tgz", - "integrity": "sha512-GqRmYGjVnw/Z/2RQiW7Ywuu9O5E0spmMUBjeE/v0rqjixBqrmdApjg5pmJ4YmUMvUI/WkGtR3FR5W9Y5PpvfKw==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@chakra-ui/select/-/select-1.2.3.tgz", + "integrity": "sha512-LGT8z06InjfMTQyWgQUqinucvObkO0bOR87c4swWlAESkS6w+g8PsH9UJ87NT5W+hzCybvqSfRjMHYwC9qUnrg==", "requires": { - "@chakra-ui/form-control": "1.5.1", + "@chakra-ui/form-control": "1.5.3", "@chakra-ui/utils": "1.9.1" } }, "@chakra-ui/skeleton": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@chakra-ui/skeleton/-/skeleton-1.2.1.tgz", - "integrity": "sha512-08yOmINorbxtv1xgZpHiTE7YCYdicZ5dCkc7nCVxvYQihH5efkEiLbP3EefZzFCTqa2KFN8BvgD5eA76TqleXA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@chakra-ui/skeleton/-/skeleton-1.2.4.tgz", + "integrity": "sha512-j5cAwXfyb7sybk+QjSz5TlQkQVeekdRZBF4xEm4TXGGZiMSTsd9/7BOBtxopakn/YKDP1owZ4oSGZGYGNmTS8w==", "requires": { - "@chakra-ui/hooks": "1.7.1", - "@chakra-ui/media-query": "1.2.1", - "@chakra-ui/system": "1.8.1", + "@chakra-ui/hooks": "1.7.2", + "@chakra-ui/media-query": "1.2.3", + "@chakra-ui/system": "1.9.0", "@chakra-ui/utils": "1.9.1" } }, "@chakra-ui/slider": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@chakra-ui/slider/-/slider-1.5.1.tgz", - "integrity": "sha512-3C0DnUapVdVq9hU1VWAsk0qc6ws1TesjQl/KTkxlP4yBJxKAja1HtyeN9c1x4jizl1a1Q7BJrYICupy70Ju76A==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@chakra-ui/slider/-/slider-1.5.3.tgz", + "integrity": "sha512-i14b8MYlantiACI4jyjxU5PdX3Nwmz65TdINd7LywrKZu0ahE4GRXCcIGyM48vlXWfdkFhKLqLuF7+EYwLYtHA==", "requires": { - "@chakra-ui/hooks": "1.7.1", + "@chakra-ui/hooks": "1.7.2", "@chakra-ui/react-utils": "1.2.1", "@chakra-ui/utils": "1.9.1" } @@ -1018,41 +1071,51 @@ } }, "@chakra-ui/stat": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@chakra-ui/stat/-/stat-1.2.1.tgz", - "integrity": "sha512-BTZFeh/8VdgUX080taCQj1g/rS4wGc+y3GQnklqlZ9N/bEv0gyLqQga7TFC/NkVl3cvjRiMnCCPj6vRih9x+Og==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@chakra-ui/stat/-/stat-1.2.2.tgz", + "integrity": "sha512-0StsPDC56MjzhdlBl0R8wU0uwj9L1tvhQzge/ELSDn4tQDI7VovrxpFzVH0qsj7EZDwZa0BRQaSrstzWvgmJ/Q==", "requires": { - "@chakra-ui/icon": "1.2.1", + "@chakra-ui/icon": "2.0.0", "@chakra-ui/utils": "1.9.1", "@chakra-ui/visually-hidden": "1.1.1" + }, + "dependencies": { + "@chakra-ui/icon": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@chakra-ui/icon/-/icon-2.0.0.tgz", + "integrity": "sha512-/GuU+xIcOIy9uSUUUCu249ZJB/nLDbjWGkfpoSdBwqT4+ytJrKt+0Ckh3Ub14sz3BJD+Z6IiIt6ySOA9+7lbsA==", + "requires": { + "@chakra-ui/utils": "1.9.1" + } + } } }, "@chakra-ui/styled-system": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@chakra-ui/styled-system/-/styled-system-1.14.1.tgz", - "integrity": "sha512-dgXFYZdJicsddUnPV1X7lQksgMD0z5EvwGaIh2JHJERqNRIvth/CBAnVLQQvy/xSJK5YaSEmeuVVU0veUOQcXg==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/@chakra-ui/styled-system/-/styled-system-1.16.0.tgz", + "integrity": "sha512-5vGU4eCixFMXp9u9PT+5724ptzBLP5AcFks88h19TpIevcElCkvAXw2G2CDJ0jJZM59l61nJGHIjn246f3iJUA==", "requires": { "@chakra-ui/utils": "1.9.1", "csstype": "^3.0.9" } }, "@chakra-ui/switch": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@chakra-ui/switch/-/switch-1.3.1.tgz", - "integrity": "sha512-92hXJ2/ozj7B3cJNT259mFNoad7Ck892uHTuEQ/GIdXb25doE6F1wCp0TreOnGiEgU5YSaxpdrcZjA0QODP//w==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@chakra-ui/switch/-/switch-1.3.2.tgz", + "integrity": "sha512-aqhAq93DW97qD/KTBiWe2ip64vxSkN/qimMRFdG4xqtS2DxGeicQiv7Eis3NgAq2xIMM9XOoeXutU4kGkha1+w==", "requires": { - "@chakra-ui/checkbox": "1.6.1", + "@chakra-ui/checkbox": "1.6.2", "@chakra-ui/utils": "1.9.1" } }, "@chakra-ui/system": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@chakra-ui/system/-/system-1.8.1.tgz", - "integrity": "sha512-CFHdAjXuEDIAvNBatTBo1Tfu/HJ1LfbmjGWI4uTRfA4sDIt+cCRc/VKSfl0IKQwy70yJOMoTehZBjS8g3RTymQ==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@chakra-ui/system/-/system-1.9.0.tgz", + "integrity": "sha512-CnLmx3nVZo87puSKxDNNQUwJyWYCnx4ZUFXdDFNdKroQyZUpSYLVv1OniXbkjwEt1YdZMsWm93lZQb/0VRcKvg==", "requires": { - "@chakra-ui/color-mode": "1.3.1", + "@chakra-ui/color-mode": "1.3.3", "@chakra-ui/react-utils": "1.2.1", - "@chakra-ui/styled-system": "1.14.1", + "@chakra-ui/styled-system": "1.16.0", "@chakra-ui/utils": "1.9.1", "react-fast-compare": "3.2.0" } @@ -1066,39 +1129,49 @@ } }, "@chakra-ui/tabs": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@chakra-ui/tabs/-/tabs-1.6.1.tgz", - "integrity": "sha512-p7HdHcleJWNwteWYVPt2KF52YbS5pIIfs/IpgtnYZRsJbqvRVxSwgg5Wsn+vuxFXBKW0cA2rDGbyzsZ+ChtEXQ==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@chakra-ui/tabs/-/tabs-1.6.2.tgz", + "integrity": "sha512-J0OY4sEhZW0jxlj4MkotLiD0/snMk7IsqvDxUB17MxuFRs5ytUssHzCqO7fexH7fSfd54ITNoUIns6Ir2ueCsA==", "requires": { "@chakra-ui/clickable": "1.2.1", "@chakra-ui/descendant": "2.1.1", - "@chakra-ui/hooks": "1.7.1", + "@chakra-ui/hooks": "1.7.2", "@chakra-ui/react-utils": "1.2.1", "@chakra-ui/utils": "1.9.1" } }, "@chakra-ui/tag": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@chakra-ui/tag/-/tag-1.2.1.tgz", - "integrity": "sha512-O068n+qBc+CSyvpRBJ6Lwep6SydQ9UysRqw1ETF+4fJSp9dMrBp8vOcl2SVacKaCu13qdv8UdRMBxUiTz3lh7A==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@chakra-ui/tag/-/tag-1.2.2.tgz", + "integrity": "sha512-H25y9nEyUAUdwQDND9P4mMXKf1wf9UH4A3DyP237qVKIyYBpa4aCH8eJU4dunh2yIzASB0DWcr7lsul/HAHxmg==", "requires": { - "@chakra-ui/icon": "1.2.1", + "@chakra-ui/icon": "2.0.0", "@chakra-ui/utils": "1.9.1" + }, + "dependencies": { + "@chakra-ui/icon": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@chakra-ui/icon/-/icon-2.0.0.tgz", + "integrity": "sha512-/GuU+xIcOIy9uSUUUCu249ZJB/nLDbjWGkfpoSdBwqT4+ytJrKt+0Ckh3Ub14sz3BJD+Z6IiIt6ySOA9+7lbsA==", + "requires": { + "@chakra-ui/utils": "1.9.1" + } + } } }, "@chakra-ui/textarea": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@chakra-ui/textarea/-/textarea-1.2.1.tgz", - "integrity": "sha512-3xDsL1qQ+eY5r4GcRL4bg90vtV/xxVlw0Z3PFehFP5JW7VwXNZIRjauR/+HlOA8eYq0cF6ch2boR1GPso6rQtw==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@chakra-ui/textarea/-/textarea-1.2.3.tgz", + "integrity": "sha512-yLObhuSnIX11GyjsiEIC2gFTDtUoGSpHUqHRD8nF9BmuePHqFzG3jdkBrFMd09u0Ee6kr6o0tia6g9Wt29TyQQ==", "requires": { - "@chakra-ui/form-control": "1.5.1", + "@chakra-ui/form-control": "1.5.3", "@chakra-ui/utils": "1.9.1" } }, "@chakra-ui/theme": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@chakra-ui/theme/-/theme-1.12.1.tgz", - "integrity": "sha512-8yDril3rSzv42eKR0x7KdnrpN1ubY0m6q37CVUADgtboJqoJwWWX2/hqkv8CX6WJf8ZwPwFL5QIwS2FPSGgi+g==", + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/@chakra-ui/theme/-/theme-1.12.3.tgz", + "integrity": "sha512-aqMGSfQLYOrcWBKaD5GuVYrpI5Zoq4Gt3D9P+drB/CDTRgBLWuJI1rbKOSSSJUK4RNZ0WbakPwz6wXiVS3vVdQ==", "requires": { "@chakra-ui/anatomy": "1.2.1", "@chakra-ui/theme-tools": "1.3.1", @@ -1115,36 +1188,36 @@ } }, "@chakra-ui/toast": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@chakra-ui/toast/-/toast-1.4.1.tgz", - "integrity": "sha512-vzQkYwnGq2nx0bOKIQ6XpJaGzUwnWKmUjcVrz9NzGwVI4g93PS7+13515R0m1NrDp30132OeDXQ+tmQwCRRe6w==", - "requires": { - "@chakra-ui/alert": "1.3.1", - "@chakra-ui/close-button": "1.2.1", - "@chakra-ui/hooks": "1.7.1", - "@chakra-ui/theme": "1.12.1", - "@chakra-ui/transition": "1.4.1", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@chakra-ui/toast/-/toast-1.5.1.tgz", + "integrity": "sha512-cynOM/mGqf/dPulYOQMcpQnbf8pQWV2SEz1ymW1Nni1hh6zCqW6+pI+YeMxeadJLAwohnRumwzLsRiSL4l+YRQ==", + "requires": { + "@chakra-ui/alert": "1.3.2", + "@chakra-ui/close-button": "1.2.2", + "@chakra-ui/hooks": "1.7.2", + "@chakra-ui/theme": "1.12.3", + "@chakra-ui/transition": "1.4.2", "@chakra-ui/utils": "1.9.1", "@reach/alert": "0.13.2" } }, "@chakra-ui/tooltip": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@chakra-ui/tooltip/-/tooltip-1.4.1.tgz", - "integrity": "sha512-KvTuqSqIpIgE+YNUwN7ONDRkSGR6SK9+dgSx2PfKy0Sel7UgDPVtxByuZ6tfJ9O1VTRYEdF9k+s6Gf8eRFQbNA==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@chakra-ui/tooltip/-/tooltip-1.4.3.tgz", + "integrity": "sha512-d+JsT65LPYFoGEfmqvqa3xDzW1enBdAHns3GYoHnie92pLseMKQYJsITO5SmwNGnEiOHbJ8pkB/hggo+xHKkpg==", "requires": { - "@chakra-ui/hooks": "1.7.1", + "@chakra-ui/hooks": "1.7.2", "@chakra-ui/popper": "2.4.1", - "@chakra-ui/portal": "1.3.1", + "@chakra-ui/portal": "1.3.2", "@chakra-ui/react-utils": "1.2.1", "@chakra-ui/utils": "1.9.1", "@chakra-ui/visually-hidden": "1.1.1" } }, "@chakra-ui/transition": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@chakra-ui/transition/-/transition-1.4.1.tgz", - "integrity": "sha512-s/VFucc6grNdP1bxw0oQLzy167gjAgyl/GiGH9nt54nioDEiSsvn70qKg7sjajNTvpoot+urQUdr4Qh+fIUFZQ==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@chakra-ui/transition/-/transition-1.4.2.tgz", + "integrity": "sha512-S+BNmpErHlntl//uaqv0sJegzMsQms0OnJapeZaRsvZL4s1SVYrR8kMrXigkdpeh4lAUqGsLpQHPKkzaKGbBOw==", "requires": { "@chakra-ui/utils": "1.9.1" } @@ -1370,6 +1443,11 @@ "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.1.tgz", "integrity": "sha512-gfta+H8aziZsm8pZa0vj04KO6biEiisppNgA1kbJvFrrWu9Vm7eaUEy76DIxsuTaWvti5fkJVhllWc6ZTE+Mdw==" }, + "@heroicons/react": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@heroicons/react/-/react-1.0.5.tgz", + "integrity": "sha512-UDMyLM2KavIu2vlWfMspapw9yii7aoLwzI2Hudx4fyoPwfKfxU8r3cL8dEBXOjcLG0/oOONZzbT14M1HoNtEcg==" + }, "@humanwhocodes/config-array": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", @@ -1579,9 +1657,9 @@ } }, "@popperjs/core": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.10.2.tgz", - "integrity": "sha512-IXf3XA7+XyN7CP9gGh/XB0UxVMlvARGEgGXLubFICsUMGz6Q+DU+i4gGlpOxTjKvXjkJDJC8YdqdKkDj9qZHEQ==" + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.2.tgz", + "integrity": "sha512-92FRmppjjqz29VMJ2dn+xdyXZBrMlE42AV6Kq6BwjWV7CNUW1hs2FtxSNLQE+gJhaZ6AAmYuO9y8dshhcBl7vA==" }, "@prisma/client": { "version": "3.4.2", @@ -1706,12 +1784,14 @@ "@types/prop-types": { "version": "15.7.4", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.4.tgz", - "integrity": "sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==" + "integrity": "sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==", + "dev": true }, "@types/react": { "version": "17.0.34", "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.34.tgz", "integrity": "sha512-46FEGrMjc2+8XhHXILr+3+/sTe3OfzSPU9YGKILLrUYbQ1CLQC9Daqo1KzENGXAWwrFwiY0l4ZbF20gRvgpWTg==", + "dev": true, "requires": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -1730,7 +1810,8 @@ "@types/scheduler": { "version": "0.16.2", "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", - "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==" + "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==", + "dev": true }, "@types/warning": { "version": "3.0.0", diff --git a/package.json b/package.json index 9dc4b12..8cdea6f 100644 --- a/package.json +++ b/package.json @@ -11,12 +11,12 @@ "lint": "next lint" }, "dependencies": { - "@chakra-ui/icons": "^1.1.1", - "@chakra-ui/react": "^1.7.1", + "@chakra-ui/react": "^1.7.4", "@emotion/react": "^11.5.0", "@emotion/styled": "^11.3.0", "@fontsource/inter": "^4.5.0", "@fontsource/raleway": "^4.5.0", + "@heroicons/react": "^1.0.5", "@prisma/client": "^3.4.2", "axios": "^0.24.0", "copy-to-clipboard": "^3.3.1", diff --git a/pages/_app.tsx b/pages/_app.tsx index 14cad9d..a5c1d29 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -5,18 +5,7 @@ import '@fontsource/inter/400.css'; import '@fontsource/inter/500.css'; import { Footer, MockDeploymentBanner } from '@/components'; - -const theme = extendTheme({ - config: { - initialColorMode: 'light', - useSystemColorMode: false, - }, - fonts: { - heading: "Raleway", - body: "Inter", - }, -} as ThemeConfig); - +import theme from '@/lib/chakra-theme'; const isMock = process.env.NEXT_PUBLIC_MOCK_DEPLOYMENT === "true"; diff --git a/pages/api/routes/create.ts b/pages/api/routes/create.ts index 14badbb..9830b28 100644 --- a/pages/api/routes/create.ts +++ b/pages/api/routes/create.ts @@ -9,27 +9,52 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) } const { name, method, projectId } = req.body; - const apiUrl = new URL(req.body.apiUrl); + let newRouteId: { id: string }; - // Handle multiple query params - const queryParams = [...apiUrl.searchParams]; + if (typeof req.query.from === 'string') { + // Duplicate existing API route + const fromApiRoute = await prisma.apiRoute.findUnique({ + where: { id: req.query.from }, + }); - const newRouteId = await prisma.apiRoute.create({ - data: { - name, - method, - apiUrl: apiUrl.origin + apiUrl.pathname, - projectId, - id: nanoid(), - caching: {}, - headers: [], - queryParams, - rateLimiting: {}, - }, - select: { - id: true, - }, - }); + if (fromApiRoute === null) { + // API route to duplicate from was not found + res.status(400).send("Invalid API route id was passed to 'from' parameter"); + return; + } + + newRouteId = await prisma.apiRoute.create({ + data: { + ...fromApiRoute, + name: name ?? fromApiRoute.name, + id: nanoid(), + successes: 0, + fails: 0, + avgResponseMs: 0, + }, + select: { id: true }, + }); + } else { + // Create a new API route + const apiUrl = new URL(req.body.apiUrl); + // Handle multiple query params + const queryParams = [...apiUrl.searchParams]; + + newRouteId = await prisma.apiRoute.create({ + data: { + name, + method, + apiUrl: apiUrl.origin + apiUrl.pathname, + projectId, + id: nanoid(), + caching: {}, + headers: [], + queryParams, + rateLimiting: {}, + }, + select: { id: true }, + }); + } res.status(200).json(newRouteId); } diff --git a/pages/projects/[projectId]/_apis.tsx b/pages/projects/[projectId]/_apis.tsx index 38ace18..1a8df0f 100644 --- a/pages/projects/[projectId]/_apis.tsx +++ b/pages/projects/[projectId]/_apis.tsx @@ -22,28 +22,34 @@ import { FormControl, FormLabel, useToast, + Menu, + MenuButton, + MenuList, + MenuItem, } from '@chakra-ui/react'; -import { AddIcon, DeleteIcon } from '@chakra-ui/icons'; +import { DuplicateIcon, TrashIcon, DotsVerticalIcon, PlusIcon } from '@heroicons/react/outline'; import { useState } from 'react'; import { useRouter } from 'next/router'; import { useForm } from 'react-hook-form'; import axios from 'axios'; -import { SectionHeading, SecretInput } from '@/components'; +import { SectionHeading, SecretInput, ApiMethodTag, confirmDialog } from '@/components'; import ProjectSecrets from '@/lib/contexts/ProjectSecrets'; export const getServerSideProps = () => ({ props: {} }); +type ApiRoute = { + id: string; + name: string; + apiUrl: string; + method: ApiMethod; + successes: number; + fails: number; +}; + type Props = { project: (Project & { - ApiRoute: { - id: string; - name: string; - apiUrl: string; - method: ApiMethod; - successes: number; - fails: number; - }[]; + ApiRoute: ApiRoute[]; Secret: { name: string; }[]; @@ -57,46 +63,101 @@ type NewApiFormData = { apiUrl: string; }; +type DuplicateApiFormData = { + name: string; + apiId: string; +}; + export default function Apis({ project, ...props }: Props) { - const { getValues, control, register, formState: { isSubmitting: isCreatingApi } } = useForm({ + const { + getValues: getNewFormValues, + control, + register: registerNewForm, + handleSubmit: handleNewFormSubmit, + formState: { isSubmitting: isCreatingApi } + } = useForm({ defaultValues: { name: '', method: ApiMethod.GET, apiUrl: '', }, }); + const { + register: registerDuplicateForm, + setValue: setDuplicateFormValue, + getValues: getDuplicateFormValues, + handleSubmit: handleDuplicateFormSubmit, + formState: { isSubmitting: isDuplicatingApi }, + } = useForm({ + defaultValues: { + name: '', + apiId: '', + }, + }); const [showCreationModal, setShowCreationModal] = useState(false); + const [duplicateModal, setDuplicateModal] = useState({ show: false, fromApiName: '' }); const [deletingApi, setDeletingApi] = useState(''); const router = useRouter(); const toast = useToast(); - const createApi = async (e) => { - e.preventDefault(); + const createApi = async () => { if (isCreatingApi) return; try { const response = await axios.post(`/api/routes/create`, { - ...getValues(), + ...getNewFormValues(), projectId: project.id, }); const newApiRouteId = response.data.id as string; router.push(`/projects/${project.id}/routes/${newApiRouteId}`); } catch(err) { console.log(err); - toast({ status: "error", title: "Ah! An error occurred, maybe try again?" }); + toast({ status: "error", title: "Ah! An error occurred while creating the API route, maybe try again?" }); } finally { setShowCreationModal(false); } }; - const deleteApi = async (e, apiId: string) => { + const duplicateApi = async () => { + if (isDuplicatingApi) return; + + try { + const { apiId, name } = getDuplicateFormValues(); + const response = await axios.post(`/api/routes/create?from=${apiId}`, { name }); + const newApiRouteId = response.data.id as string; + router.push(`/projects/${project.id}/routes/${newApiRouteId}`); + } catch(err) { + console.log(err); + toast({ status: "error", title: "Ah! An error occurred while duplicating, maybe try again?" }); + } finally { + setDuplicateModal({ show: false, fromApiName: '' }); + } + }; + + const deleteApi = async (e, apiId: string, apiName: string) => { e.stopPropagation(); if (deletingApi) return; - setDeletingApi(apiId); - await axios.delete(`/api/routes/${apiId}`); + + const confirmed = await confirmDialog({ + title: `Delete ${apiName} API route`, + description: `Deleting this API route will remove all configurations and immediately make its proxy URL unusable. This action is irreversible.`, + btnConfirmTxt: 'Delete API route', + }); + + if (confirmed) { + await axios.delete(`/api/routes/${apiId}`); + router.replace(router.asPath, undefined, { scroll: false }); + } + setDeletingApi(''); - router.replace(router.asPath, undefined, { scroll: false }); + }; + + const openDuplicateApiModal = async (e, api: ApiRoute) => { + e.stopPropagation(); + setDuplicateFormValue('apiId', api.id); + setDuplicateFormValue('name', `${api.name} Duplicate`); + setDuplicateModal({ show: true, fromApiName: api.name }); }; return ( @@ -106,7 +167,7 @@ export default function Apis({ project, ...props }: Props) { API endpoints that are configured with Diode. - @@ -121,25 +182,34 @@ export default function Apis({ project, ...props }: Props) { _first={{ roundedTop: "md" }} _notFirst={{ mt: -1 }} _last={{ roundedBottom: "md" }} - _hover={{ textDecoration: "none", shadow: "md", transform: "scale(1.01)" }} + _hover={{ bg: "gray.50" }} > - {api.method} + {api.name} {decodeURI(api.apiUrl)} - - } - aria-label="Remove" + + } + variant="ghost" size="sm" - colorScheme="gray" ml="auto" - onClick={(e) => deleteApi(e, api.id)} isLoading={api.id === deletingApi} + onClick={e => e.stopPropagation()} /> - + + } onClick={(e) => openDuplicateApiModal(e, api)}> + Duplicate + + } color="red.500" onClick={(e) => deleteApi(e, api.id, api.name)}> + Delete + + + @@ -159,16 +229,16 @@ export default function Apis({ project, ...props }: Props) { New API route Let's get building! 💪 -
+ - API Name - + API route name + Method - {Object.keys(ApiMethod).map((method) => )} @@ -194,6 +264,33 @@ export default function Apis({ project, ...props }: Props) { + + setDuplicateModal({ show: false, fromApiName: '' })}> + + + + Duplicate "{duplicateModal.fromApiName}" API route + + This action will create a new API route with the same configuration as "{duplicateModal.fromApiName}" API route. + + + + + + API route name + + + + + + + + + + + ); } diff --git a/pages/projects/[projectId]/_danger-zone.tsx b/pages/projects/[projectId]/_danger-zone.tsx index a906c0b..8815534 100644 --- a/pages/projects/[projectId]/_danger-zone.tsx +++ b/pages/projects/[projectId]/_danger-zone.tsx @@ -1,5 +1,5 @@ import { Box, Flex, Button } from '@chakra-ui/react'; -import { DeleteIcon } from '@chakra-ui/icons'; +import { TrashIcon } from '@heroicons/react/outline'; import { SectionHeading } from '@/components'; import { useState } from 'react'; @@ -36,7 +36,7 @@ export default function DangerZone({ onDelete, buttonText, children, ...props }: colorScheme="red" color="red.500" variant="outline" - rightIcon={} + rightIcon={} onClick={deleteHandler} isLoading={deleting} > diff --git a/pages/projects/[projectId]/_secrets.tsx b/pages/projects/[projectId]/_secrets.tsx index 51e5a2d..f7b41a7 100644 --- a/pages/projects/[projectId]/_secrets.tsx +++ b/pages/projects/[projectId]/_secrets.tsx @@ -1,11 +1,23 @@ import type { Project } from '@prisma/client'; -import { Box, Flex, Text, Button, IconButton, Tooltip, Input, useToast } from '@chakra-ui/react'; -import { AddIcon, DeleteIcon } from '@chakra-ui/icons'; +import { + Box, + Flex, + Text, + Button, + IconButton, + Tooltip, + Input, + InputGroup, + InputRightElement, + useToast, +} from '@chakra-ui/react'; +import { PlusIcon, TrashIcon } from '@heroicons/react/outline'; import { useState } from 'react'; import { useRouter } from 'next/router'; import axios from 'axios'; +import { useForm } from 'react-hook-form'; -import { SectionHeading } from '@/components'; +import { SectionHeading, confirmDialog } from '@/components'; export const getServerSideProps = () => ({ props: {} }); @@ -18,47 +30,62 @@ type Props = { [key: string]: any; }; +type NewSecretFormData = { + name: string; + value: string; +}; + export default function Secrets({ project, ...props }: Props) { const [showNewForm, setShowNewForm] = useState(false); - const [newSecretName, setNewSecretName] = useState(''); - const [newSecretValue, setNewSecretValue] = useState(''); - const [creatingSecret, setCreatingSecret] = useState(false); const [deletingSecret, setDeletingSecret] = useState(''); + const [showValue, setShowValue] = useState(false); + const { + register, + getValues, + handleSubmit, + setValue, + formState: { isSubmitting: creatingSecret }, + } = useForm(); const toast = useToast(); const router = useRouter(); const closeCreation = () => { setShowNewForm(false); - setNewSecretName(''); - setNewSecretValue(''); + setValue('name', ''); + setValue('value', ''); }; - const createSecret = async (e) => { - e.preventDefault(); + const createSecret = async () => { if (creatingSecret) return; - if (project.Secret.some(({ name }) => name === newSecretName)) { + const newSecret = getValues(); + + if (project.Secret.some(({ name }) => name === newSecret.name)) { toast({ status: "error", title: "Secret with this name already exists" }); return; } - setCreatingSecret(true); - await axios.post(`/api/projects/${project.id}/secrets/create`, { - name: newSecretName, - value: newSecretValue, - }); - setCreatingSecret(false); + await axios.post(`/api/projects/${project.id}/secrets/create`, newSecret); closeCreation(); router.replace(router.asPath, undefined, { scroll: false }); }; const deleteSecret = async (secretName: string) => { if (deletingSecret) return; - setDeletingSecret(secretName); - await axios.delete(`/api/projects/${project.id}/secrets/${secretName}`); + + const confirmed = await confirmDialog({ + title: `Delete ${secretName} secret`, + description: `Deleting this secret will make all the references to ${secretName} in request URL, headers, query params an empty string. This action is irreversible.`, + btnConfirmTxt: 'Delete Secret', + }); + + if (confirmed) { + await axios.delete(`/api/projects/${project.id}/secrets/${secretName}`); + router.replace(router.asPath, undefined, { scroll: false }); + } + setDeletingSecret(''); - router.replace(router.asPath, undefined, { scroll: false }); }; return ( @@ -69,7 +96,7 @@ export default function Secrets({ project, ...props }: Props) {
These are encrypted and stored on the database. -
@@ -94,8 +121,9 @@ export default function Secrets({ project, ...props }: Props) { } + icon={} aria-label="Remove" + variant="ghost" size="sm" colorScheme="gray" isLoading={deletingSecret === name} @@ -105,13 +133,33 @@ export default function Secrets({ project, ...props }: Props) { ))} {showNewForm && ( - -
+ + - setNewSecretName(e.target.value)} /> - setNewSecretValue(e.target.value)} mx={8} /> + + + + + + + - @@ -577,7 +596,7 @@ export default function ApiRoutePage({ apiRoute }: Props) { - ✂️ Partial Query Experimental + ✂️ Partial Query Query for only relevant fields in the JSON response, by passing diode-filter query param. @@ -601,7 +620,7 @@ export default function ApiRoutePage({ apiRoute }: Props) { colorScheme="green" bg="green.400" shadow="lg" - rightIcon={} + rightIcon={} isLoading={isSubmitting} > Save changes diff --git a/pages/projects/index.tsx b/pages/projects/index.tsx index c13525c..69b4a5b 100644 --- a/pages/projects/index.tsx +++ b/pages/projects/index.tsx @@ -22,7 +22,7 @@ import { FormLabel, Input } from '@chakra-ui/react'; -import { AddIcon } from '@chakra-ui/icons'; +import { PlusIcon } from '@heroicons/react/outline'; import { Project } from '@prisma/client'; import axios from 'axios'; @@ -80,7 +80,7 @@ export default function Projects({ projects }: Props) { Projects -