diff --git a/packages/api/src/routers/auth/auth_router.ts b/packages/api/src/routers/auth/auth_router.ts index b3d8853b6..d9289111e 100644 --- a/packages/api/src/routers/auth/auth_router.ts +++ b/packages/api/src/routers/auth/auth_router.ts @@ -356,6 +356,11 @@ export function authRouter() { cors(corsConfig), async (req: express.Request, res: express.Response) => { const { email, password } = req.body + if (!email || !password) { + res.redirect(`${env.client.url}/email-login?errorCodes=AUTH_FAILED`) + return + } + const query = ` mutation login{ login(input: { @@ -418,6 +423,11 @@ export function authRouter() { cors(corsConfig), async (req: express.Request, res: express.Response) => { const { email, password, name, username, bio } = req.body + if (!email || !password || !name || !username) { + res.redirect(`${env.client.url}/email-signup?errorCodes=BAD_DATA`) + return + } + const query = ` mutation signup { signup(input: { @@ -425,7 +435,7 @@ export function authRouter() { password: "${password}", name: "${name}", username: "${username}", - bio: "${bio}" + bio: "${bio ?? ''}" }) { __typename ... on SignupSuccess { diff --git a/packages/web/components/elements/Button.tsx b/packages/web/components/elements/Button.tsx index 2d0fe45d3..1b4cce9da 100644 --- a/packages/web/components/elements/Button.tsx +++ b/packages/web/components/elements/Button.tsx @@ -217,3 +217,22 @@ export const Button = styled('button', { style: 'ctaWhite', }, }) + +export const IconButton = styled(Button, { + variants: { + style: { + ctaWhite: { + color: 'red', + padding: '10px', + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + border: '1px solid $grayBorder', + boxSizing: 'border-box', + borderRadius: 6, + width: 40, + height: 40, + }, + }, + }, +}) \ No newline at end of file diff --git a/packages/web/components/elements/ModalPrimitives.tsx b/packages/web/components/elements/ModalPrimitives.tsx index 876104de3..33006fc8b 100644 --- a/packages/web/components/elements/ModalPrimitives.tsx +++ b/packages/web/components/elements/ModalPrimitives.tsx @@ -34,6 +34,7 @@ const Modal = styled(Content, { boxShadow: theme.shadows.cardBoxShadow.toString(), position: 'fixed', '&:focus': { outline: 'none' }, + zIndex:'1', }) export const ModalContent = styled(Modal, { diff --git a/packages/web/components/elements/Table.tsx b/packages/web/components/elements/Table.tsx index d854dedb3..ce81966bf 100644 --- a/packages/web/components/elements/Table.tsx +++ b/packages/web/components/elements/Table.tsx @@ -1,10 +1,20 @@ -import { Box, HStack, SpanBox, VStack } from './LayoutPrimitives' +import { isDarkTheme } from '../../lib/themeUpdater' +import { + Table as ResponsiveTable, + Thead, + Tbody, + Tr, + Th, + Td, +} from 'react-super-responsive-table' +import 'react-super-responsive-table/dist/SuperResponsiveTableStyle.css' +import { PencilSimple, Plus, Trash } from 'phosphor-react' +import { Box, SpanBox, VStack } from './LayoutPrimitives' import { styled } from '../tokens/stitches.config' import { StyledText } from './StyledText' import { InfoLink } from './InfoLink' import { Button } from './Button' -import { PencilSimple, Plus, Trash } from 'phosphor-react' -import { isDarkTheme } from '../../lib/themeUpdater' +import { IconButton } from './Button' interface TableProps { heading: string @@ -23,61 +33,25 @@ const HeaderWrapper = styled(Box, { }, }) -const TableCard = styled(Box, { - backgroundColor: '$grayBg', - display: 'flex', - alignItems: 'center', - padding: '10px 12px', +const StyledTable = styled(ResponsiveTable, { + margin: ' 0 auto', border: '0.5px solid $grayBgActive', + backgroundColor: '$graySolid', + borderCollapse: 'collapse', + borderRadius: '5px', width: '100%', - + mt: '$3', '&:hover': { border: '0.5px solid #FFD234', }, - '@md': { - paddingLeft: '0', - }, +}) +const TableBody = styled(Tbody, { + backgroundColor: '$grayBg', }) -const TableHeading = styled(Box, { - backgroundColor: '$grayBgActive', - border: '1px solid rgba(0, 0, 0, 0.06)', - display: 'none', - alignItems: 'center', - padding: '14px 0 14px 40px', - borderRadius: '5px 5px 0px 0px', - width: '100%', - '@md': { - display: 'flex', - }, -}) - -const Input = styled('input', { - backgroundColor: 'transparent', - color: '$grayTextContrast', - marginTop: '5px', - '&[disabled]': { - border: 'none', - }, -}) - -const IconButton = styled(Button, { - variants: { - style: { - ctaWhite: { - color: 'red', - padding: '10px', - display: 'flex', - justifyContent: 'center', - alignItems: 'center', - border: '1px solid $grayBorder', - boxSizing: 'border-box', - borderRadius: 6, - width: 40, - height: 40, - }, - }, - }, +const TableRow = styled(Tr, { + border: '0 !important', + borderTop: '0.5px solid $grayBgActive !important', }) export function Table(props: TableProps): JSX.Element { @@ -140,108 +114,87 @@ export function Table(props: TableProps): JSX.Element { )} - - {props.headers.map((header, index) => ( - - - {header} - - - ))} - - - {Array.from(props.rows.keys()).map((key, index) => ( - - - {Object.values(props.rows.get(key) || {}).map((cell, index) => ( - - + + + {props.headers.map((header: string, index: number) => ( + + - + > + {header} + + ))} - {props.onEdit && ( - { - props.onEdit && - props.onEdit({ ...props.rows.get(key), id: key }) - }} - > - - - )} - {props.onDelete && ( - { - props.onDelete && props.onDelete(key) - }} - > - - - )} - - - ))} + + + + + {Array.from(props.rows.keys()).map((key, index) => ( + + {Object.values(props.rows.get(key) || {}).map((cell, index) => ( + + + {cell} + + + ))} + + {props.onDelete && ( + + { + props.onDelete && props.onDelete(key) + }} + > + + + + )} + {props.onEdit && ( + + { + props.onEdit && + props.onEdit({ ...props.rows.get(key), id: key }) + }} + > + + + + )} + + ))} + + ) } diff --git a/packages/web/components/templates/EmailLogin.tsx b/packages/web/components/templates/EmailLogin.tsx index e8a8962bd..f644974dd 100644 --- a/packages/web/components/templates/EmailLogin.tsx +++ b/packages/web/components/templates/EmailLogin.tsx @@ -52,6 +52,7 @@ export function EmailLogin(): JSX.Element { { e.preventDefault(); setEmail(e.target.value); }} @@ -63,6 +64,7 @@ export function EmailLogin(): JSX.Element { setPassword(e.target.value)} diff --git a/packages/web/package.json b/packages/web/package.json index 8d7aad7f2..cf0f6317f 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -43,6 +43,7 @@ "react-colorful": "^5.5.1", "react-dom": "^17.0.2", "react-hot-toast": "^2.1.1", + "react-super-responsive-table": "^5.2.1", "react-topbar-progress-indicator": "^4.1.1", "react-twitter-widgets": "^1.10.0", "swr": "^1.0.1", diff --git a/packages/web/pages/settings/api.tsx b/packages/web/pages/settings/api.tsx index 1060a24a8..a78b2b285 100644 --- a/packages/web/pages/settings/api.tsx +++ b/packages/web/pages/settings/api.tsx @@ -10,6 +10,7 @@ import { revokeApiKeyMutation } from '../../lib/networking/mutations/revokeApiKe import { PrimaryLayout } from '../../components/templates/PrimaryLayout' import { Table } from '../../components/elements/Table' + import { FormInputProps } from '../../components/elements/FormElements' import { FormModal } from '../../components/patterns/FormModal' import { ConfirmationModal } from '../../components/patterns/ConfirmationModal' @@ -57,9 +58,10 @@ export default function Api(): JSX.Element { usedAt: apiKey.usedAt ? new Date(apiKey.usedAt).toISOString() : 'Never used', - expiresAt: new Date(apiKey.expiresAt).getTime() != neverExpiresDate.getTime() - ? new Date(apiKey.expiresAt).toDateString() - : 'Never', + expiresAt: + new Date(apiKey.expiresAt).getTime() != neverExpiresDate.getTime() + ? new Date(apiKey.expiresAt).toDateString() + : 'Never', }) ) return rows @@ -117,7 +119,7 @@ export default function Api(): JSX.Element { additionalDays = 365 break case 'Never': - break; + break } const newExpires = additionalDays ? new Date() : neverExpiresDate if (additionalDays) { @@ -126,7 +128,13 @@ export default function Api(): JSX.Element { setExpiresAt(newExpires) }, type: 'select', - options: ['in 7 days', 'in 30 days', 'in 90 days', 'in 1 year', 'Never'], + options: [ + 'in 7 days', + 'in 30 days', + 'in 90 days', + 'in 1 year', + 'Never', + ], value: defaultExpiresAt, }, ])