forked from chatwoot/chatwoot
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add user profile avatar (chatwoot#9298)
* feat: add avatar * chore: add more colors * chore: add helpers * chore: build prettier issues * chore: refactor shouldShowImage * chore: code cleanup * Update app/javascript/v3/components/Form/InitialsAvatar.vue Co-authored-by: Sivin Varghese <[email protected]> * chore: revire comments --------- Co-authored-by: Sivin Varghese <[email protected]>
- Loading branch information
Showing
7 changed files
with
638 additions
and
171 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
<template> | ||
<div | ||
class="rounded-xl flex leading-[100%] font-medium items-center justify-center text-center cursor-default" | ||
:class="`h-[${size}px] w-[${size}px] ${colorClass}`" | ||
:style="style" | ||
aria-hidden="true" | ||
> | ||
<slot>{{ initial }}</slot> | ||
</div> | ||
</template> | ||
|
||
<script setup> | ||
import { computed } from 'vue'; | ||
import { userInitial } from 'v3/helpers/CommonHelper'; | ||
const colors = { | ||
1: 'bg-ash-200 text-ash-900', | ||
2: 'bg-amber-200 text-amber-900', | ||
3: 'bg-pink-100 text-pink-800', | ||
4: 'bg-purple-100 text-purple-800', | ||
5: 'bg-indigo-100 text-indigo-800', | ||
6: 'bg-grass-100 text-grass-800', | ||
7: 'bg-mint-100 text-mint-800', | ||
8: 'bg-orange-100 text-orange-800', | ||
}; | ||
const props = defineProps({ | ||
name: { | ||
type: String, | ||
default: '', | ||
}, | ||
size: { | ||
type: Number, | ||
default: 72, | ||
}, | ||
}); | ||
const style = computed(() => ({ | ||
fontSize: `${Math.floor(props.size / 2.5)}px`, | ||
})); | ||
const colorClass = computed(() => { | ||
return colors[(props.name.length % 8) + 1]; | ||
}); | ||
const initial = computed(() => userInitial(props.name)); | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
<template> | ||
<div class="relative rounded-xl h-[72px] w-[72px] cursor-pointe group"> | ||
<img | ||
v-if="shouldShowImage" | ||
class="rounded-xl h-[72px] w-[72px]" | ||
:alt="name" | ||
:src="src" | ||
draggable="false" | ||
@load="onImageLoad" | ||
@error="onImageLoadError" | ||
/> | ||
<initials-avatar v-else-if="!shouldShowImage" :name="name" :size="72" /> | ||
|
||
<input | ||
ref="fileInputRef" | ||
type="file" | ||
accept="image/png, image/jpeg, image/jpg, image/gif, image/webp" | ||
hidden | ||
@change="onImageUpload" | ||
/> | ||
<div class="hidden group-hover:block"> | ||
<button | ||
v-if="src" | ||
class="absolute z-10 flex items-center justify-center w-6 h-6 p-1 border border-white rounded-full select-none dark:border-ash-75 reset-base -top-2 -right-2 bg-ash-300" | ||
@click="onAvatarDelete" | ||
> | ||
<fluent-icon icon="dismiss" size="16" class="text-ash-900" /> | ||
</button> | ||
<button | ||
class="reset-base absolute h-[72px] w-[72px] top-0 left-0 rounded-xl select-none flex items-center justify-center bg-modal-backdrop-dark dark:bg-modal-backdrop-dark" | ||
@click="openFileInput" | ||
> | ||
<fluent-icon icon="avatar-upload" size="32" class="text-white" /> | ||
</button> | ||
</div> | ||
</div> | ||
</template> | ||
<script setup> | ||
import { computed, ref } from 'vue'; | ||
import InitialsAvatar from './InitialsAvatar.vue'; | ||
const props = defineProps({ | ||
src: { | ||
type: String, | ||
default: '', | ||
}, | ||
name: { | ||
type: String, | ||
default: '', | ||
}, | ||
}); | ||
const emits = defineEmits(['change', 'delete']); | ||
const hasImageLoaded = ref(false); | ||
const imageLoadedError = ref(false); | ||
const fileInputRef = ref(null); | ||
const shouldShowImage = computed(() => props.src && !imageLoadedError.value); | ||
const onImageLoadError = () => { | ||
imageLoadedError.value = true; | ||
}; | ||
const onImageLoad = () => { | ||
hasImageLoaded.value = true; | ||
imageLoadedError.value = false; | ||
}; | ||
const openFileInput = () => { | ||
fileInputRef.value.click(); | ||
}; | ||
const onImageUpload = event => { | ||
const [file] = event.target.files; | ||
emits('change', { | ||
file, | ||
url: file ? URL.createObjectURL(file) : null, | ||
}); | ||
}; | ||
const onAvatarDelete = () => { | ||
emits('delete'); | ||
}; | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,9 @@ | ||
export const replaceRouteWithReload = url => { | ||
window.location = url; | ||
}; | ||
|
||
export const userInitial = name => { | ||
const parts = name.split(/[ -]/).filter(Boolean); | ||
let initials = parts.map(part => part[0].toUpperCase()).join(''); | ||
return initials.slice(0, 2); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { userInitial } from '../CommonHelper'; | ||
|
||
describe('#userInitial', () => { | ||
it('returns the initials of the user', () => { | ||
expect(userInitial('John Doe')).toEqual('JD'); | ||
expect(userInitial('John')).toEqual('J'); | ||
expect(userInitial('John-Doe')).toEqual('JD'); | ||
expect(userInitial('John Doe Smith')).toEqual('JD'); | ||
}); | ||
}); |
Oops, something went wrong.