From befc39f08c9213246f1d1c29f97210c0fa18fcc9 Mon Sep 17 00:00:00 2001 From: ValbertMartins Date: Wed, 12 Jul 2023 12:59:17 -0300 Subject: [PATCH 01/10] feat: add description to users --- ...53152_alter-table-users-add-description.js | 9 ++++++ models/authorization.js | 4 +++ models/user.js | 5 ++- models/validator.js | 13 ++++++++ pages/[username]/index.public.js | 20 ++++++++++-- pages/api/v1/users/[username]/index.public.js | 1 + pages/interface/components/TabNewsUI/index.js | 1 + pages/interface/hooks/useUser/index.js | 1 + pages/perfil/index.public.js | 31 +++++++++++++++++++ 9 files changed, 82 insertions(+), 3 deletions(-) create mode 100644 infra/migrations/1688768453152_alter-table-users-add-description.js diff --git a/infra/migrations/1688768453152_alter-table-users-add-description.js b/infra/migrations/1688768453152_alter-table-users-add-description.js new file mode 100644 index 000000000..a71b9db5f --- /dev/null +++ b/infra/migrations/1688768453152_alter-table-users-add-description.js @@ -0,0 +1,9 @@ +exports.up = async (pgm) => { + await pgm.addColumns('users', { + description: { + type: 'varchar(160)', + }, + }); +}; + +exports.down = false; diff --git a/models/authorization.js b/models/authorization.js index 7034430b9..22596f4f4 100644 --- a/models/authorization.js +++ b/models/authorization.js @@ -89,6 +89,7 @@ function filterInput(user, feature, input) { username: input.username, email: input.email, password: input.password, + description: input.description, notifications: input.notifications, }; } @@ -175,6 +176,7 @@ function filterOutput(user, feature, output) { filteredOutputValues = { id: output.id, username: output.username, + description: output.description, features: output.features, tabcoins: output.tabcoins, tabcash: output.tabcash, @@ -189,6 +191,7 @@ function filterOutput(user, feature, output) { id: output.id, username: output.username, email: output.email, + description: output.description, notifications: output.notifications, features: output.features, tabcoins: output.tabcoins, @@ -203,6 +206,7 @@ function filterOutput(user, feature, output) { filteredOutputValues = output.map((user) => ({ id: user.id, username: user.username, + description: user.description, features: user.features, tabcoins: user.tabcoins, tabcash: user.tabcash, diff --git a/models/user.js b/models/user.js index df8640455..0e21026d2 100644 --- a/models/user.js +++ b/models/user.js @@ -249,7 +249,8 @@ async function update(username, postedUserData, options = {}) { username = $2, email = $3, password = $4, - notifications = $5, + description = $5, + notifications = $6, updated_at = (now() at time zone 'utc') WHERE id = $1 @@ -261,6 +262,7 @@ async function update(username, postedUserData, options = {}) { userWithUpdatedValues.username, userWithUpdatedValues.email, userWithUpdatedValues.password, + userWithUpdatedValues.description, userWithUpdatedValues.notifications, ], }; @@ -286,6 +288,7 @@ async function validatePatchSchema(postedUserData) { username: 'optional', email: 'optional', password: 'optional', + description: 'optional', notifications: 'optional', }); diff --git a/models/validator.js b/models/validator.js index 0327729b6..4303dbf89 100644 --- a/models/validator.js +++ b/models/validator.js @@ -154,6 +154,19 @@ const schemas = { }); }, + description: function () { + return Joi.object({ + description: Joi.string() + .allow(null, '') + .max(160) + .when('$required.description', { is: 'required', then: Joi.required(), otherwise: Joi.optional() }) + .messages({ + 'string.max': `"description" deve conter no máximo {#limit} caracteres.`, + 'string.base': `"description" deve ser do tipo String.`, + }), + }); + }, + notifications: function () { return Joi.object({ notifications: Joi.boolean() diff --git a/pages/[username]/index.public.js b/pages/[username]/index.public.js index eb5448981..cd8073c5a 100644 --- a/pages/[username]/index.public.js +++ b/pages/[username]/index.public.js @@ -9,6 +9,7 @@ import { Label, LabelGroup, Pagehead, + Viewer, useConfirm, } from '@/TabNewsUI'; import { KebabHorizontalIcon, TrashIcon } from '@primer/octicons-react'; @@ -130,9 +131,24 @@ export default function Home({ contentListFound, pagination, userFound: userFoun )} - - {userFound.username} + + {userFound.username} + + {userFound.description && ( + + {} + + )} + {user?.features?.includes('ban:user') && OptionsMenu()} diff --git a/pages/api/v1/users/[username]/index.public.js b/pages/api/v1/users/[username]/index.public.js index 00e83642b..7b8a5bf25 100644 --- a/pages/api/v1/users/[username]/index.public.js +++ b/pages/api/v1/users/[username]/index.public.js @@ -65,6 +65,7 @@ function patchValidationHandler(request, response, next) { username: 'optional', email: 'optional', password: 'optional', + description: 'optional', notifications: 'optional', }); diff --git a/pages/interface/components/TabNewsUI/index.js b/pages/interface/components/TabNewsUI/index.js index e7bc168e3..9e942fc53 100644 --- a/pages/interface/components/TabNewsUI/index.js +++ b/pages/interface/components/TabNewsUI/index.js @@ -38,6 +38,7 @@ export { SSRProvider, Text, TextInput, + Textarea, ThemeProvider as PrimerThemeProvider, Tooltip, Truncate, diff --git a/pages/interface/hooks/useUser/index.js b/pages/interface/hooks/useUser/index.js index 3d6c8f655..26a6654b1 100644 --- a/pages/interface/hooks/useUser/index.js +++ b/pages/interface/hooks/useUser/index.js @@ -33,6 +33,7 @@ export function UserProvider({ children }) { const cachedUserProperties = { id: responseBody.id, username: responseBody.username, + description: responseBody.description, features: responseBody.features, tabcoins: responseBody.tabcoins, tabcash: responseBody.tabcash, diff --git a/pages/perfil/index.public.js b/pages/perfil/index.public.js index 565a24fb2..9cd5eee45 100644 --- a/pages/perfil/index.public.js +++ b/pages/perfil/index.public.js @@ -8,6 +8,7 @@ import { Heading, Link, TextInput, + Textarea, useConfirm, } from '@/TabNewsUI'; import { useUser, suggestEmail } from 'pages/interface'; @@ -35,6 +36,7 @@ function EditProfileForm() { const usernameRef = useRef(''); const emailRef = useRef(''); const notificationsRef = useRef(''); + const descriptionRef = useRef(''); useEffect(() => { if (router && !user && !userIsLoading) { @@ -45,6 +47,7 @@ function EditProfileForm() { usernameRef.current.value = user.username; emailRef.current.value = user.email; notificationsRef.current.checked = user.notifications; + descriptionRef.current.value = user.description; } }, [user, router, userIsLoading]); @@ -66,6 +69,7 @@ function EditProfileForm() { const username = usernameRef.current.value; const email = emailRef.current.value; + const description = descriptionRef.current.value; const notifications = notificationsRef.current.checked; setIsLoading(true); @@ -106,6 +110,10 @@ function EditProfileForm() { payload.email = email; } + if (user.description !== description) { + payload.description = description; + } + if (user.notifications !== notifications) { payload.notifications = notifications; } @@ -235,6 +243,29 @@ function EditProfileForm() { )} + + Descrição +