Skip to content

Commit 5c1b451

Browse files
authored
Merge pull request #135 from iceljc/features/add-user-avatar
Features/add user avatar
2 parents d2cf67d + 1975318 commit 5c1b451

File tree

9 files changed

+89
-22
lines changed

9 files changed

+89
-22
lines changed

src/lib/common/MessageImageGallery.svelte

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<script>
22
import { onMount } from 'svelte';
33
import FileGallery from '$lib/common/FileGallery.svelte';
4-
import { getUserStore } from '$lib/helpers/store';
54
import { PUBLIC_SERVICE_URL } from '$env/static/public';
5+
import { userStore } from '$lib/helpers/store';
66
77
/** @type {string} */
88
export let galleryClasses = '';
@@ -19,15 +19,13 @@
1919
let token = "";
2020
2121
onMount(() => {
22-
const user = getUserStore();
23-
token = user.token;
2422
if (fetchFiles != null && fetchFiles != undefined) {
2523
fetchFiles().then(data => {
2624
// @ts-ignore
2725
files = data?.filter(item => !!item.file_url)?.map(item => {
2826
return {
2927
...item,
30-
file_data: `${PUBLIC_SERVICE_URL}${item.file_url}?access_token=${token}`
28+
file_data: `${PUBLIC_SERVICE_URL}${item.file_url}?access_token=${$userStore?.token}`
3129
};
3230
}) || [];
3331
});

src/lib/common/ProfileDropdown.svelte

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,25 @@
33
import { resetLocalStorage } from '$lib/helpers/store';
44
import { goto } from '$app/navigation';
55
import { browser } from '$app/environment';
6+
import { userStore } from '$lib/helpers/store';
7+
import { PUBLIC_SERVICE_URL } from '$env/static/public';
68
import { _ } from 'svelte-i18n';
9+
import { buildUrl } from '$lib/helpers/utils/common';
710
8-
/**
9-
* @type {{ full_name: any; }}
10-
*/
11-
export let user;
11+
/** @type {any} */
12+
export let user;
13+
1214
function logout() {
1315
if (browser){
1416
resetLocalStorage(true);
1517
}
1618
goto('login');
1719
};
20+
21+
/** @param {any} e */
22+
function handleAvatarLoad(e) {
23+
e.target.src = 'images/users/user-dummy.jpg';
24+
}
1825
</script>
1926

2027
<Dropdown class="d-inline-block">
@@ -24,7 +31,12 @@
2431
class="btn header-item waves-effect"
2532
id="page-header-user-dropdown"
2633
>
27-
<img class="rounded-circle header-profile-user" src='images/users/user-dummy.jpg' alt="Header Avatar" />
34+
<img
35+
class="rounded-circle header-profile-user"
36+
src={`${buildUrl(PUBLIC_SERVICE_URL, user?.avatar)}?access_token=${$userStore?.token}`}
37+
alt=""
38+
on:error={e => handleAvatarLoad(e)}
39+
/>
2840
<span class="d-none d-xl-inline-block ms-1" key="t-fullname">{user?.full_name}</span>
2941
<i class="mdi mdi-chevron-down d-none d-xl-inline-block" />
3042
</DropdownToggle>

src/lib/helpers/types.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,13 @@ IRichContent.prototype.quick_replies;
412412
* @property {string?} [payload] - The payload message.
413413
*/
414414

415+
/**
416+
* @typedef {Object} FileModel
417+
* @property {string} file_name - The plugin full name.
418+
* @property {string} file_data - The plugin name.
419+
* @property {string} file_url - Row count.
420+
*/
421+
415422
/**
416423
* Invoked when a new conersation is created.
417424
* This callback type is called `requestCallback` and is displayed as a global symbol.

src/lib/helpers/utils/common.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
11
export function range(size = 3, startAt = 0) {
22
return [...Array(size).keys()].map((i) => i + startAt);
3-
};
3+
};
4+
5+
/**
6+
* @param {string} baseUrl
7+
* @param {string} relativePath
8+
*/
9+
export function buildUrl(baseUrl, relativePath) {
10+
return new URL(relativePath, baseUrl);
11+
}

src/lib/services/api-endpoints.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export const endpoints = {
66
tokenUrl: `${host}/token`,
77
myInfoUrl: `${host}/user/me`,
88
usrCreationUrl: `${host}/user`,
9+
userAvatarUrl: `${host}/user/avatar`,
910

1011
// setting
1112
settingListUrl: `${host}/settings`,

src/lib/services/auth-service.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ export async function myInfo() {
6666
* @param {string} lastName
6767
* @param {string} email
6868
* @param {string} password
69-
* @param {function} onSucceed()
69+
* @param {function} onSucceed
7070
*/
7171
export async function register(firstName, lastName, email, password, onSucceed) {
7272
let data = JSON.stringify({
@@ -91,4 +91,12 @@ export async function register(firstName, lastName, email, password, onSucceed)
9191
}
9292
})
9393
.catch(error => alert(error.message));
94+
}
95+
96+
/**
97+
* @param {import('$types').FileModel} file
98+
*/
99+
export async function uploadUserAvatar(file) {
100+
const response = await axios.post(endpoints.userAvatarUrl, { ...file });
101+
return response?.data;
94102
}

src/routes/chat/[agentId]/[conversationId]/chat-image/chat-image-gallery.svelte

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,6 @@
3939
files={files}
4040
disabled={disabled}
4141
needDelete
42-
onDelete={deleteFile} />
42+
onDelete={deleteFile}
43+
/>
4344
</div>

src/routes/page/conversation/[conversationId]/+page.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
const params = $page.params;
1616
1717
/** @type {import('$types').ConversationModel} */
18-
export let conversation;
18+
let conversation;
1919
2020
onMount(async () => {
2121
conversation = await getConversation(params.conversationId);

src/routes/page/user/me/+page.svelte

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
11
<script>
2-
import { PUBLIC_BRAND_NAME, PUBLIC_LOGIN_IMAGE } from '$env/static/public';
2+
import { onMount } from 'svelte';
3+
import { PUBLIC_BRAND_NAME } from '$env/static/public';
34
import { Row, Col, Card, CardBody, CardTitle, Table } from '@sveltestrap/sveltestrap';
45
import Breadcrumb from '$lib/common/Breadcrumb.svelte';
56
import HeadTitle from '$lib/common/HeadTitle.svelte';
6-
import { onMount } from 'svelte';
7-
import { myInfo } from '$lib/services/auth-service';
7+
import FileDropZone from '$lib/common/FileDropZone.svelte';
8+
import { myInfo, uploadUserAvatar } from '$lib/services/auth-service';
89
import { _ } from 'svelte-i18n';
9-
10+
import { userStore } from '$lib/helpers/store';
11+
import { PUBLIC_SERVICE_URL } from '$env/static/public';
12+
import { buildUrl } from '$lib/helpers/utils/common';
13+
1014
/** @type {import('$types').UserModel} */
1115
let currentUser;
1216
let isLoading = false;
17+
1318
onMount(async () => {
1419
isLoading = true;
1520
await myInfo()
@@ -20,6 +25,21 @@
2025
isLoading = false;
2126
});
2227
});
28+
29+
/** @param {any} e */
30+
async function handleFileDrop(e) {
31+
const { acceptedFiles } = e.detail;
32+
const file = acceptedFiles[0];
33+
if (!!!file) return;
34+
35+
await uploadUserAvatar(file);
36+
window.location.reload();
37+
}
38+
39+
/** @param {any} e */
40+
function handleAvatarLoad(e) {
41+
e.target.src = 'images/users/user-dummy.jpg';
42+
}
2343
</script>
2444

2545
<HeadTitle title="{$_('My Profile')}" />
@@ -41,11 +61,23 @@
4161
<Row>
4262
<Col sm={4}>
4363
<div class="avatar-md profile-user-wid mb-4">
44-
<img
45-
src="images/users/user-dummy.jpg"
46-
alt="avatar"
47-
class="img-thumbnail rounded-circle"
48-
/>
64+
<FileDropZone
65+
accept="image/*"
66+
disableDefaultStyles
67+
containerStyles={'width: 100%; height: 100%;'}
68+
noDrag
69+
multiple={false}
70+
fileLimit={1}
71+
on:drop={e => handleFileDrop(e)}
72+
>
73+
<img
74+
src={`${buildUrl(PUBLIC_SERVICE_URL, currentUser?.avatar || '').href}?access_token=${$userStore?.token}`}
75+
alt=""
76+
class="img-thumbnail rounded-circle"
77+
style="width: 100%; height: 100%;"
78+
on:error={e => handleAvatarLoad(e)}
79+
/>
80+
</FileDropZone>
4981
</div>
5082
<h5 class="font-size-15 text-truncate">{currentUser?.full_name}</h5>
5183
<p class="text-muted mb-0 text-truncate">{currentUser?.role ?? 'Role: N/A'}</p>

0 commit comments

Comments
 (0)