From 439006e571b00ecfe9c04dc43a3638281e3a806c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Gonz=C3=A1lez=20Rubio?= Date: Fri, 3 Jan 2025 18:21:19 +0100 Subject: [PATCH] feat: improve user admin table - fix #235 (#236) --- app/client/package.json | 2 +- .../components/users/users.component.tsx | 40 ++++++++++++++----- .../admin/components/users/users.module.scss | 21 ++++------ app/client/src/shared/consts/email.utils.ts | 4 ++ app/client/src/shared/consts/index.ts | 1 + app/client/src/shared/utils/email.utils.ts | 5 +++ app/client/yarn.lock | 8 ++-- 7 files changed, 52 insertions(+), 29 deletions(-) create mode 100644 app/client/src/shared/consts/email.utils.ts diff --git a/app/client/package.json b/app/client/package.json index 45aad4a..981a664 100644 --- a/app/client/package.json +++ b/app/client/package.json @@ -9,7 +9,7 @@ "vite-tsconfig-paths": "4.3.2" }, "dependencies": { - "@oh/components": "npm:@jsr/oh__components@0.1.14", + "@oh/components": "npm:@jsr/oh__components@0.1.15", "@vitejs/plugin-react": "^4.3.1", "@vitejs/plugin-react-refresh": "1.3.6", "js-cookie": "3.0.5", diff --git a/app/client/src/modules/home/components/admin/components/users/users.component.tsx b/app/client/src/modules/home/components/admin/components/users/users.component.tsx index 83a1363..efb90bf 100644 --- a/app/client/src/modules/home/components/admin/components/users/users.component.tsx +++ b/app/client/src/modules/home/components/admin/components/users/users.component.tsx @@ -1,5 +1,5 @@ import { useAdmin } from "shared/hooks"; -import React, { useMemo } from "react"; +import React from "react"; import { cn, getCensoredEmail } from "shared/utils"; import dayjs from "dayjs"; @@ -18,17 +18,42 @@ export const UsersComponent = () => { title="Users" searchable={true} pageRows={20} + rowFunc={($row, columns) => { + return ( + + {columns.map(($column) => { + const title = $row[$column.key]; + let value = title; + + if ($column.key === "email") value = getCensoredEmail(title); + if ($column.key === "accountId") + value = value.substring(0, 12) + "..."; + + return ( + + {value} + + ); + })} + + ); + }} data={users.map((user) => { const expireAt = dayjs(user.createdAt).add(1, "day"); const remainingMinutes = expireAt.diff(today, "minutes"); return { ...user, - admin: user.admin ? "✔️" : "❌", - otp: user.otp ? "✔️" : "❌", + otp: user.otp ? "✅" : "❌", verified: user.verified - ? "✔️" - : `❌ ${Math.floor(remainingMinutes / 60)} hours ${remainingMinutes % 60} minutes`, + ? "✅" + : `⏳ ${Math.floor(remainingMinutes / 60)} hours ${remainingMinutes % 60} minutes`, + createdAt: dayjs(user.createdAt).format("YYYY/MM/DD HH:mm:ss"), }; })} columns={[ @@ -50,11 +75,6 @@ export const UsersComponent = () => { key: "username", label: "Username", }, - { - sortable: true, - key: "admin", - label: "Admin", - }, { sortable: true, key: "otp", diff --git a/app/client/src/modules/home/components/admin/components/users/users.module.scss b/app/client/src/modules/home/components/admin/components/users/users.module.scss index 45a558b..a439d99 100644 --- a/app/client/src/modules/home/components/admin/components/users/users.module.scss +++ b/app/client/src/modules/home/components/admin/components/users/users.module.scss @@ -1,19 +1,12 @@ .users { - .list { - display: flex; - flex-direction: column; - gap: 0.5rem; + .row { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; - .item { - display: flex; - gap: 1rem; - background-color: var(--text-2-bg); - padding: 1rem 2rem; - - &.admin { - background-color: var(--color-yellow-2); - color: var(--color-dark-9); - } + &.admin { + background-color: var(--color-yellow-2) !important; + color: var(--color-dark-9) !important; } } } diff --git a/app/client/src/shared/consts/email.utils.ts b/app/client/src/shared/consts/email.utils.ts new file mode 100644 index 0000000..e0f1099 --- /dev/null +++ b/app/client/src/shared/consts/email.utils.ts @@ -0,0 +1,4 @@ +// Regex is not the appropriate way to validate email addresses, but anyway... +// https://stackoverflow.com/a/201378 +export const EMAIL_REGEX = + /^(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])$/; diff --git a/app/client/src/shared/consts/index.ts b/app/client/src/shared/consts/index.ts index c9f49ec..7fd4cdc 100644 --- a/app/client/src/shared/consts/index.ts +++ b/app/client/src/shared/consts/index.ts @@ -1,3 +1,4 @@ export * from "./urls.consts"; export * from "./captcha.consts"; export * from "./at.consts"; +export * from "./email.utils"; diff --git a/app/client/src/shared/utils/email.utils.ts b/app/client/src/shared/utils/email.utils.ts index efab6cb..de5a869 100644 --- a/app/client/src/shared/utils/email.utils.ts +++ b/app/client/src/shared/utils/email.utils.ts @@ -1,4 +1,9 @@ +import { EMAIL_REGEX } from "shared/consts"; + export const getCensoredEmail = (email: string): string => email.substring(0, 1) + "**@**.**" + email.substring(email.length - 1, email.length); + +export const isEmail = (email: string): boolean => + new RegExp(EMAIL_REGEX).test(email); diff --git a/app/client/yarn.lock b/app/client/yarn.lock index ee728ad..bc75791 100644 --- a/app/client/yarn.lock +++ b/app/client/yarn.lock @@ -328,10 +328,10 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" -"@oh/components@npm:@jsr/oh__components@0.1.14": - version "0.1.14" - resolved "https://npm.jsr.io/~/11/@jsr/oh__components/0.1.14.tgz#24DCAEB87C8901CFCA1DBD46A92E4C4285A8C58F" - integrity sha512-Az+Pim0lMTvECNjLJ7tTnZxN5Pef/mj5F6auFYTqe1g0y3BIPtQORejrAjuL/U3Qk8ypg1Av1Ux4137rN0TyGQ== +"@oh/components@npm:@jsr/oh__components@0.1.15": + version "0.1.15" + resolved "https://npm.jsr.io/~/11/@jsr/oh__components/0.1.15.tgz#0DE246195DB6872CF2CC6D303B34A793D2B6448B" + integrity sha512-tVzBK84Tl+8DhPSxL2w5Goz20GtpWcX78lV3Ig9/RoL0y8e7FlKQ2b4yccWdCIpcFVcxfejhXOx2JRcP3mG3aA== dependencies: react "18.3.1"