Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: added mutation and function to platform for updating user profile name #3929

Merged
merged 9 commits into from Mar 25, 2024
2 changes: 2 additions & 0 deletions packages/hoppscotch-common/locales/en.json
Expand Up @@ -315,6 +315,7 @@
"danger_zone": "Danger zone",
"delete_account": "Your account is currently an owner in these workspaces:",
"delete_account_description": "You must either remove yourself, transfer ownership, or delete these workspaces before you can delete your account.",
"empty_profile_name": "Profile name cannot be empty",
"empty_req_name": "Empty Request Name",
"f12_details": "(F12 for details)",
"gql_prettify_invalid_query": "Couldn't prettify an invalid query, solve query syntax errors and try again",
Expand All @@ -334,6 +335,7 @@
"page_not_found": "This page could not be found",
"please_install_extension": "Please install the extension and add origin to the extension.",
"proxy_error": "Proxy error",
"same_profile_name": "Updated profile name is same as the current profile name",
"script_fail": "Could not execute pre-request script",
"something_went_wrong": "Something went wrong",
"test_script_fail": "Could not execute post-request script",
Expand Down
2 changes: 1 addition & 1 deletion packages/hoppscotch-common/src/components/teams/Team.vue
Expand Up @@ -20,7 +20,7 @@
: ''
"
>
<div class="p-4">
<div class="p-4 truncate">
<label
class="font-semibold text-secondaryDark"
:class="{ 'cursor-pointer': compact && team.myRole === 'OWNER' }"
Expand Down
35 changes: 23 additions & 12 deletions packages/hoppscotch-common/src/pages/profile.vue
Expand Up @@ -210,6 +210,8 @@ import { toggleSetting } from "~/newstore/settings"
import IconVerified from "~icons/lucide/verified"
import IconSettings from "~icons/lucide/settings"

import * as E from "fp-ts/Either"

type ProfileTabs = "sync" | "teams"

const selectedProfileTab = ref<ProfileTabs>("sync")
Expand Down Expand Up @@ -244,19 +246,28 @@ const displayName = ref(currentUser.value?.displayName || "")
const updatingDisplayName = ref(false)
watchEffect(() => (displayName.value = currentUser.value?.displayName || ""))

const updateDisplayName = () => {
const updateDisplayName = async () => {
if (!displayName.value) {
toast.error(`${t("error.empty_profile_name")}`)
return
}

if (currentUser.value?.displayName === displayName.value) {
toast.error(`${t("error.same_profile_name")}`)
return
}

updatingDisplayName.value = true
platform.auth
.setDisplayName(displayName.value as string)
.then(() => {
toast.success(`${t("profile.updated")}`)
})
.catch(() => {
toast.error(`${t("error.something_went_wrong")}`)
})
.finally(() => {
updatingDisplayName.value = false
})

const res = await platform.auth.setDisplayName(displayName.value)

if (E.isLeft(res)) {
toast.error(t("error.something_went_wrong"))
} else if (E.isRight(res)) {
toast.success(`${t("profile.updated")}`)
}

updatingDisplayName.value = false
}

const emailAddress = ref(currentUser.value?.email || "")
Expand Down
7 changes: 5 additions & 2 deletions packages/hoppscotch-common/src/platform/auth.ts
Expand Up @@ -4,6 +4,7 @@ import { Component } from "vue"
import { getI18n } from "~/modules/i18n"
import * as E from "fp-ts/Either"
import { AxiosRequestConfig } from "axios"
import { GQLError } from "~/helpers/backend/GQLClient"

/**
* A common (and required) set of fields that describe a user.
Expand Down Expand Up @@ -229,9 +230,11 @@ export type AuthPlatformDef = {
/**
* Updates the display name of the user
* @param name The new name to set this to.
* @returns An empty promise that is resolved when the operation is complete
* @returns A promise that resolves with the display name update status when the operation is complete
*/
setDisplayName: (name: string) => Promise<void>
setDisplayName: (
name: string
) => Promise<E.Either<GQLError<string>, undefined>>

/**
* Returns the list of allowed auth providers for the platform ( the currently supported ones are GOOGLE, GITHUB, EMAIL, MICROSOFT, SAML )
Expand Down
@@ -0,0 +1,5 @@
mutation UpdateUserDisplayName($updatedDisplayName: String!) {
updateDisplayName(updatedDisplayName: $updatedDisplayName) {
displayName
}
}
15 changes: 15 additions & 0 deletions packages/hoppscotch-selfhost-web/src/platform/auth/auth.api.ts
@@ -1,6 +1,12 @@
import { runMutation } from "@hoppscotch/common/helpers/backend/GQLClient"
import axios from "axios"
import * as E from "fp-ts/Either"
import { z } from "zod"
import {
UpdateUserDisplayNameDocument,
UpdateUserDisplayNameMutation,
UpdateUserDisplayNameMutationVariables,
} from "../../api/generated/graphql"

const expectedAllowedProvidersSchema = z.object({
// currently supported values are "GOOGLE", "GITHUB", "EMAIL", "MICROSOFT", "SAML"
Expand Down Expand Up @@ -28,3 +34,12 @@ export const getAllowedAuthProviders = async () => {
return E.left("SOMETHING_WENT_WRONG")
}
}

export const updateUserDisplayName = (updatedDisplayName: string) =>
runMutation<
UpdateUserDisplayNameMutation,
UpdateUserDisplayNameMutationVariables,
""
>(UpdateUserDisplayNameDocument, {
updatedDisplayName,
})()
Expand Up @@ -8,7 +8,8 @@ import { PersistenceService } from "@hoppscotch/common/services/persistence"
import axios from "axios"
import { BehaviorSubject, Subject } from "rxjs"
import { Ref, ref, watch } from "vue"
import { getAllowedAuthProviders } from "./auth.api"
import { getAllowedAuthProviders, updateUserDisplayName } from "./auth.api"
import * as E from "fp-ts/Either"

export const authEvents$ = new Subject<AuthEvent | { event: "token_refresh" }>()
const currentUser$ = new BehaviorSubject<HoppUser | null>(null)
Expand Down Expand Up @@ -317,9 +318,22 @@ export const def: AuthPlatformDef = {
async setEmailAddress(_email: string) {
return
},
// eslint-disable-next-line @typescript-eslint/no-unused-vars

nivedin marked this conversation as resolved.
Show resolved Hide resolved
async setDisplayName(name: string) {
return
if (!name) return E.left("USER_NAME_CANNOT_BE_EMPTY")
if (!currentUser$.value) return E.left("NO_USER_LOGGED_IN")

const res = await updateUserDisplayName(name)

if (E.isRight(res)) {
setUser({
...currentUser$.value,
displayName: res.right.updateDisplayName.displayName ?? null,
})

return E.right(undefined)
}
return E.left(res.left)
},

async signOutUser() {
Expand Down