mirror of https://github.com/nocodb/nocodb
Muhammed Mustafa
1 year ago
8 changed files with 200 additions and 18 deletions
@ -0,0 +1,113 @@ |
|||||||
|
<script lang="ts" setup> |
||||||
|
const { currentUser } = storeToRefs(useUsers()) |
||||||
|
|
||||||
|
const isErrored = ref(false) |
||||||
|
const isTitleUpdating = ref(false) |
||||||
|
const form = ref({ |
||||||
|
title: '', |
||||||
|
email: '', |
||||||
|
}) |
||||||
|
|
||||||
|
const { updateUserProfile } = useUsers() |
||||||
|
const formValidator = ref() |
||||||
|
|
||||||
|
const formRules = { |
||||||
|
title: [ |
||||||
|
{ required: true, message: 'Name required' }, |
||||||
|
{ min: 2, message: 'Name must be at least 2 characters long' }, |
||||||
|
{ max: 60, message: 'Name must be at most 60 characters long' }, |
||||||
|
], |
||||||
|
} |
||||||
|
|
||||||
|
const onSubmit = async () => { |
||||||
|
const valid = await formValidator.value.validate() |
||||||
|
|
||||||
|
if (!valid) return |
||||||
|
|
||||||
|
if (isTitleUpdating.value) return |
||||||
|
|
||||||
|
isTitleUpdating.value = true |
||||||
|
isErrored.value = false |
||||||
|
|
||||||
|
try { |
||||||
|
await updateUserProfile({ attrs: { display_name: form.value.title } }) |
||||||
|
} catch (e: any) { |
||||||
|
console.error(e) |
||||||
|
} finally { |
||||||
|
isTitleUpdating.value = false |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
watch( |
||||||
|
() => currentUser.value?.display_name, |
||||||
|
() => { |
||||||
|
if (!currentUser.value?.display_name) return |
||||||
|
|
||||||
|
form.value.title = currentUser.value.display_name |
||||||
|
form.value.email = currentUser.value.email |
||||||
|
}, |
||||||
|
{ |
||||||
|
immediate: true, |
||||||
|
}, |
||||||
|
) |
||||||
|
|
||||||
|
watch( |
||||||
|
() => form.value.title, |
||||||
|
async () => { |
||||||
|
try { |
||||||
|
isErrored.value = !(await formValidator.value.validate()) |
||||||
|
} catch (e: any) { |
||||||
|
isErrored.value = true |
||||||
|
} |
||||||
|
}, |
||||||
|
) |
||||||
|
</script> |
||||||
|
|
||||||
|
<template> |
||||||
|
<div class="flex flex-col items-center"> |
||||||
|
<div class="flex flex-col w-150"> |
||||||
|
<div class="flex font-medium text-xl">Profile</div> |
||||||
|
<div class="mt-5 flex flex-col border-1 rounded-2xl border-gray-200 p-6 gap-y-2"> |
||||||
|
<div class="flex font-medium text-base">Account details</div> |
||||||
|
<div class="flex text-gray-500">Control your appearance.</div> |
||||||
|
<div class="flex flex-row mt-4 gap-x-8"> |
||||||
|
<div class="flex h-20"> |
||||||
|
<GeneralUserIcon size="xlarge" /> |
||||||
|
</div> |
||||||
|
<a-form ref="formValidator" layout="vertical" no-style :model="form" class="w-full" @finish="onSubmit"> |
||||||
|
<div class="text-gray-800 mb-1.5">Name</div> |
||||||
|
<a-form-item name="title" :rules="formRules.title"> |
||||||
|
<a-input |
||||||
|
v-model:value="form.title" |
||||||
|
class="w-full !rounded-md !py-1.5" |
||||||
|
placeholder="Name" |
||||||
|
data-testid="nc-account-settings-rename-input" |
||||||
|
/> |
||||||
|
</a-form-item> |
||||||
|
<div class="text-gray-800 mb-1.5">Account Email ID</div> |
||||||
|
<a-input |
||||||
|
v-model:value="form.email" |
||||||
|
class="w-full !rounded-md !py-1.5" |
||||||
|
placeholder="Email" |
||||||
|
:disabled="true" |
||||||
|
data-testid="nc-account-settings-email-input" |
||||||
|
/> |
||||||
|
<div class="flex flex-row w-full justify-end mt-8"> |
||||||
|
<NcButton |
||||||
|
type="primary" |
||||||
|
html-type="submit" |
||||||
|
:disabled="isErrored || (form.title && form.title === currentUser?.display_name)" |
||||||
|
:loading="isTitleUpdating" |
||||||
|
data-testid="nc-account-settings-save" |
||||||
|
@click="onSubmit" |
||||||
|
> |
||||||
|
<template #loading> Saving </template> |
||||||
|
Save |
||||||
|
</NcButton> |
||||||
|
</div> |
||||||
|
</a-form> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
@ -0,0 +1,65 @@ |
|||||||
|
import { acceptHMRUpdate, defineStore } from 'pinia' |
||||||
|
|
||||||
|
export const useUsers = defineStore('userStore', () => { |
||||||
|
const { api } = useApi() |
||||||
|
const { user } = useGlobal() |
||||||
|
|
||||||
|
const currentUser = computed({ |
||||||
|
get: () => user.value, |
||||||
|
set: (value) => { |
||||||
|
user.value = value |
||||||
|
}, |
||||||
|
}) |
||||||
|
|
||||||
|
const updateUserProfile = async ({ |
||||||
|
attrs, |
||||||
|
}: { |
||||||
|
attrs: { |
||||||
|
display_name?: string |
||||||
|
} |
||||||
|
}) => { |
||||||
|
if (!user.value) throw new Error('User is not defined') |
||||||
|
|
||||||
|
await api.userProfile.update(attrs) |
||||||
|
|
||||||
|
user.value = { |
||||||
|
...user.value, |
||||||
|
...attrs, |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const loadCurrentUser = async () => { |
||||||
|
const res = await api.auth.me() |
||||||
|
|
||||||
|
user.value = { |
||||||
|
...user.value, |
||||||
|
...res, |
||||||
|
roles: res.roles, |
||||||
|
project_roles: res.project_roles, |
||||||
|
workspace_roles: res.workspace_roles, |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
watch( |
||||||
|
() => user.value?.id, |
||||||
|
(newId, oldId) => { |
||||||
|
if (!newId) return |
||||||
|
if (newId === oldId) return |
||||||
|
|
||||||
|
loadCurrentUser() |
||||||
|
}, |
||||||
|
{ |
||||||
|
immediate: true, |
||||||
|
}, |
||||||
|
) |
||||||
|
|
||||||
|
return { |
||||||
|
loadCurrentUser, |
||||||
|
updateUserProfile, |
||||||
|
currentUser, |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
if (import.meta.hot) { |
||||||
|
import.meta.hot.accept(acceptHMRUpdate(useUsers as any, import.meta.hot)) |
||||||
|
} |
Loading…
Reference in new issue