@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.
@@ -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,2 @@
1
+ export * from './lib/user-avatar.service';
2
+ //# sourceMappingURL=public-api.d.ts.map
@@ -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,5 @@
1
+ /*
2
+ * Public API Surface of ng-user-avatar
3
+ */
4
+ export * from './lib/user-avatar.service';
5
+ //# sourceMappingURL=public-api.js.map
@@ -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
+ }