@memberjunction/ng-user-avatar 2.110.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/user-avatar.service.d.ts +58 -0
- package/dist/lib/user-avatar.service.d.ts.map +1 -0
- package/dist/lib/user-avatar.service.js +143 -0
- package/dist/lib/user-avatar.service.js.map +1 -0
- package/dist/public-api.d.ts +2 -0
- package/dist/public-api.d.ts.map +1 -0
- package/dist/public-api.js +5 -0
- package/dist/public-api.js.map +1 -0
- package/package.json +39 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { HttpClient } from '@angular/common/http';
|
|
2
|
+
import { UserEntity } from '@memberjunction/core-entities';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
/**
|
|
5
|
+
* Service for managing user avatar operations across the application.
|
|
6
|
+
*
|
|
7
|
+
* NOTE: This service does NOT depend on any Explorer-specific packages to remain
|
|
8
|
+
* usable across different Angular applications. All auth provider logic should
|
|
9
|
+
* be handled by the calling code.
|
|
10
|
+
*/
|
|
11
|
+
export declare class UserAvatarService {
|
|
12
|
+
private http;
|
|
13
|
+
constructor(http: HttpClient);
|
|
14
|
+
/**
|
|
15
|
+
* Syncs user avatar from an image URL (typically from auth provider profile).
|
|
16
|
+
* Downloads the image, converts to Base64, and saves to the user entity.
|
|
17
|
+
*
|
|
18
|
+
* @param user - The UserEntity to update with avatar data
|
|
19
|
+
* @param imageUrl - URL to the image (can be from Microsoft Graph, Google, etc.)
|
|
20
|
+
* @param authHeaders - Optional headers for authenticated requests (e.g., { 'Authorization': 'Bearer token' })
|
|
21
|
+
* @returns Promise<boolean> - true if avatar was synced and saved, false otherwise
|
|
22
|
+
*/
|
|
23
|
+
syncFromImageUrl(user: UserEntity, imageUrl: string, authHeaders?: Record<string, string>): Promise<boolean>;
|
|
24
|
+
/**
|
|
25
|
+
* Converts a Blob to a Base64 data URI string
|
|
26
|
+
* Returns format: "data:image/png;base64,iVBORw0KG..."
|
|
27
|
+
*/
|
|
28
|
+
private blobToBase64;
|
|
29
|
+
/**
|
|
30
|
+
* Converts a File to a Base64 data URI string
|
|
31
|
+
* Used for file uploads in settings UI
|
|
32
|
+
*/
|
|
33
|
+
fileToBase64(file: File): Promise<string>;
|
|
34
|
+
/**
|
|
35
|
+
* Validates if a string is a valid URL
|
|
36
|
+
*/
|
|
37
|
+
isValidUrl(url: string): boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Validates if a string is a valid Base64 data URI
|
|
40
|
+
*/
|
|
41
|
+
isValidBase64DataUri(dataUri: string): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Gets the display URL for an avatar based on user settings
|
|
44
|
+
* Priority: UserImageURL > UserImageIconClass > default
|
|
45
|
+
*
|
|
46
|
+
* @param user - The UserEntity
|
|
47
|
+
* @param defaultUrl - Optional default URL if no avatar is set
|
|
48
|
+
* @returns The URL to display, or null if using an icon
|
|
49
|
+
*/
|
|
50
|
+
getAvatarDisplayUrl(user: UserEntity, defaultUrl?: string): string | null;
|
|
51
|
+
/**
|
|
52
|
+
* Gets the icon class for an avatar if using icon mode
|
|
53
|
+
*/
|
|
54
|
+
getAvatarIconClass(user: UserEntity, defaultIcon?: string): string | null;
|
|
55
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<UserAvatarService, never>;
|
|
56
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<UserAvatarService>;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=user-avatar.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-avatar.service.d.ts","sourceRoot":"","sources":["../../src/lib/user-avatar.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;;AAG3D;;;;;;GAMG;AACH,qBAGa,iBAAiB;IAChB,OAAO,CAAC,IAAI;gBAAJ,IAAI,EAAE,UAAU;IAEpC;;;;;;;;OAQG;IACG,gBAAgB,CACpB,IAAI,EAAE,UAAU,EAChB,QAAQ,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACnC,OAAO,CAAC,OAAO,CAAC;IAoCnB;;;OAGG;IACH,OAAO,CAAC,YAAY;IASpB;;;OAGG;IACH,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC;IASzC;;OAEG;IACH,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAahC;;OAEG;IACH,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAS9C;;;;;;;OAOG;IACH,mBAAmB,CAAC,IAAI,EAAE,UAAU,EAAE,UAAU,GAAE,MAA0B,GAAG,MAAM,GAAG,IAAI;IAY5F;;OAEG;IACH,kBAAkB,CAAC,IAAI,EAAE,UAAU,EAAE,WAAW,GAAE,MAA2B,GAAG,MAAM,GAAG,IAAI;yCAjIlF,iBAAiB;6CAAjB,iBAAiB;CA4I7B"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { Injectable } from '@angular/core';
|
|
2
|
+
import { firstValueFrom } from 'rxjs';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
import * as i1 from "@angular/common/http";
|
|
5
|
+
/**
|
|
6
|
+
* Service for managing user avatar operations across the application.
|
|
7
|
+
*
|
|
8
|
+
* NOTE: This service does NOT depend on any Explorer-specific packages to remain
|
|
9
|
+
* usable across different Angular applications. All auth provider logic should
|
|
10
|
+
* be handled by the calling code.
|
|
11
|
+
*/
|
|
12
|
+
export class UserAvatarService {
|
|
13
|
+
http;
|
|
14
|
+
constructor(http) {
|
|
15
|
+
this.http = http;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Syncs user avatar from an image URL (typically from auth provider profile).
|
|
19
|
+
* Downloads the image, converts to Base64, and saves to the user entity.
|
|
20
|
+
*
|
|
21
|
+
* @param user - The UserEntity to update with avatar data
|
|
22
|
+
* @param imageUrl - URL to the image (can be from Microsoft Graph, Google, etc.)
|
|
23
|
+
* @param authHeaders - Optional headers for authenticated requests (e.g., { 'Authorization': 'Bearer token' })
|
|
24
|
+
* @returns Promise<boolean> - true if avatar was synced and saved, false otherwise
|
|
25
|
+
*/
|
|
26
|
+
async syncFromImageUrl(user, imageUrl, authHeaders) {
|
|
27
|
+
try {
|
|
28
|
+
if (!imageUrl || imageUrl.trim().length === 0) {
|
|
29
|
+
console.warn('No image URL provided for avatar sync');
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
// Fetch the image as a blob
|
|
33
|
+
const headers = authHeaders || {};
|
|
34
|
+
const blob = await firstValueFrom(this.http.get(imageUrl, { headers, responseType: 'blob' }));
|
|
35
|
+
// Convert blob to Base64 data URI
|
|
36
|
+
const base64 = await this.blobToBase64(blob);
|
|
37
|
+
// Update user entity
|
|
38
|
+
user.UserImageURL = base64;
|
|
39
|
+
user.UserImageIconClass = null; // Clear icon if we have an image
|
|
40
|
+
// Save to database
|
|
41
|
+
const saved = await user.Save();
|
|
42
|
+
if (saved) {
|
|
43
|
+
console.log('Successfully synced avatar from image URL');
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
console.warn('Failed to save avatar to database');
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
console.warn('Could not sync avatar from image URL:', error);
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Converts a Blob to a Base64 data URI string
|
|
58
|
+
* Returns format: "data:image/png;base64,iVBORw0KG..."
|
|
59
|
+
*/
|
|
60
|
+
blobToBase64(blob) {
|
|
61
|
+
return new Promise((resolve, reject) => {
|
|
62
|
+
const reader = new FileReader();
|
|
63
|
+
reader.onloadend = () => resolve(reader.result);
|
|
64
|
+
reader.onerror = reject;
|
|
65
|
+
reader.readAsDataURL(blob);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Converts a File to a Base64 data URI string
|
|
70
|
+
* Used for file uploads in settings UI
|
|
71
|
+
*/
|
|
72
|
+
fileToBase64(file) {
|
|
73
|
+
return new Promise((resolve, reject) => {
|
|
74
|
+
const reader = new FileReader();
|
|
75
|
+
reader.onload = () => resolve(reader.result);
|
|
76
|
+
reader.onerror = error => reject(error);
|
|
77
|
+
reader.readAsDataURL(file);
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Validates if a string is a valid URL
|
|
82
|
+
*/
|
|
83
|
+
isValidUrl(url) {
|
|
84
|
+
if (!url || url.trim().length === 0) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
try {
|
|
88
|
+
new URL(url);
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Validates if a string is a valid Base64 data URI
|
|
97
|
+
*/
|
|
98
|
+
isValidBase64DataUri(dataUri) {
|
|
99
|
+
if (!dataUri || !dataUri.startsWith('data:')) {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
const regex = /^data:image\/(png|jpeg|jpg|gif|webp);base64,/;
|
|
103
|
+
return regex.test(dataUri);
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Gets the display URL for an avatar based on user settings
|
|
107
|
+
* Priority: UserImageURL > UserImageIconClass > default
|
|
108
|
+
*
|
|
109
|
+
* @param user - The UserEntity
|
|
110
|
+
* @param defaultUrl - Optional default URL if no avatar is set
|
|
111
|
+
* @returns The URL to display, or null if using an icon
|
|
112
|
+
*/
|
|
113
|
+
getAvatarDisplayUrl(user, defaultUrl = 'assets/user.png') {
|
|
114
|
+
if (user.UserImageURL) {
|
|
115
|
+
return user.UserImageURL;
|
|
116
|
+
}
|
|
117
|
+
if (user.UserImageIconClass) {
|
|
118
|
+
return null; // Indicates icon should be used instead
|
|
119
|
+
}
|
|
120
|
+
return defaultUrl;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Gets the icon class for an avatar if using icon mode
|
|
124
|
+
*/
|
|
125
|
+
getAvatarIconClass(user, defaultIcon = 'fa-solid fa-user') {
|
|
126
|
+
if (user.UserImageIconClass) {
|
|
127
|
+
return user.UserImageIconClass;
|
|
128
|
+
}
|
|
129
|
+
if (!user.UserImageURL) {
|
|
130
|
+
return defaultIcon;
|
|
131
|
+
}
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
static ɵfac = function UserAvatarService_Factory(t) { return new (t || UserAvatarService)(i0.ɵɵinject(i1.HttpClient)); };
|
|
135
|
+
static ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: UserAvatarService, factory: UserAvatarService.ɵfac, providedIn: 'root' });
|
|
136
|
+
}
|
|
137
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(UserAvatarService, [{
|
|
138
|
+
type: Injectable,
|
|
139
|
+
args: [{
|
|
140
|
+
providedIn: 'root'
|
|
141
|
+
}]
|
|
142
|
+
}], () => [{ type: i1.HttpClient }], null); })();
|
|
143
|
+
//# sourceMappingURL=user-avatar.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-avatar.service.js","sourceRoot":"","sources":["../../src/lib/user-avatar.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"public-api.d.ts","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"AAIA,cAAc,2BAA2B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"public-api.js","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,2BAA2B,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@memberjunction/ng-user-avatar",
|
|
3
|
+
"version": "2.110.0",
|
|
4
|
+
"description": "MemberJunction: Angular User Avatar Service - Manages user avatar synchronization from auth providers and avatar operations",
|
|
5
|
+
"main": "./dist/public-api.js",
|
|
6
|
+
"typings": "./dist/public-api.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"/dist"
|
|
9
|
+
],
|
|
10
|
+
"scripts": {
|
|
11
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
12
|
+
"build": "ngc"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"MemberJunction",
|
|
16
|
+
"Angular",
|
|
17
|
+
"User",
|
|
18
|
+
"Avatar",
|
|
19
|
+
"Authentication"
|
|
20
|
+
],
|
|
21
|
+
"author": "",
|
|
22
|
+
"license": "ISC",
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@angular/compiler": "18.0.2",
|
|
25
|
+
"@angular/compiler-cli": "18.0.2"
|
|
26
|
+
},
|
|
27
|
+
"peerDependencies": {
|
|
28
|
+
"@angular/common": "18.0.2",
|
|
29
|
+
"@angular/core": "18.0.2",
|
|
30
|
+
"rxjs": "^7.5.0"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@memberjunction/core": "2.100.3",
|
|
34
|
+
"@memberjunction/core-entities": "2.110.0",
|
|
35
|
+
"@memberjunction/global": "2.100.3",
|
|
36
|
+
"tslib": "^2.3.0"
|
|
37
|
+
},
|
|
38
|
+
"sideEffects": false
|
|
39
|
+
}
|