@webpros/tsxuserprofilevue 3.5.2 → 3.5.3
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/USAGE_GUIDE.md +659 -0
- package/dist/tsxUserProfile.js +17 -14
- package/package.json +3 -3
package/USAGE_GUIDE.md
ADDED
|
@@ -0,0 +1,659 @@
|
|
|
1
|
+
# TSXUserProfile Component - Usage Guide
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
TSXUserProfile is a Vue 3 web component for managing user profiles and licenses. It can be embedded in any web application and communicates via events.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
### NPM
|
|
10
|
+
```bash
|
|
11
|
+
npm install @webpros/tsxuserprofilevue
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
### CDN
|
|
15
|
+
```html
|
|
16
|
+
<script type="module" crossorigin src="https://unpkg.com/@webpros/tsxuserprofilevue/dist/index.js"></script>
|
|
17
|
+
<link rel="stylesheet" href="https://unpkg.com/@webpros/tsxuserprofilevue/dist/tsxUserProfile.css">
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Basic Usage
|
|
21
|
+
|
|
22
|
+
### HTML
|
|
23
|
+
```html
|
|
24
|
+
<tsx-user-profile
|
|
25
|
+
base-api-url="https://api.example.com"
|
|
26
|
+
current-language="en"
|
|
27
|
+
user-data='{"email":"user@example.com","firstName":"John","familyName":"Doe","timezone":"America/New_York"}'
|
|
28
|
+
token="your-auth-token"
|
|
29
|
+
></tsx-user-profile>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Vue 3
|
|
33
|
+
```vue
|
|
34
|
+
<script setup>
|
|
35
|
+
import '@webpros/tsxuserprofilevue'
|
|
36
|
+
|
|
37
|
+
const userData = {
|
|
38
|
+
email: 'user@example.com',
|
|
39
|
+
firstName: 'John',
|
|
40
|
+
familyName: 'Doe',
|
|
41
|
+
timezone: 'America/New_York',
|
|
42
|
+
gravatar: 'https://www.gravatar.com/avatar/...',
|
|
43
|
+
nixstatsId: '12345',
|
|
44
|
+
threeSixtyId: '67890'
|
|
45
|
+
}
|
|
46
|
+
</script>
|
|
47
|
+
|
|
48
|
+
<template>
|
|
49
|
+
<tsx-user-profile
|
|
50
|
+
base-api-url="https://api.example.com"
|
|
51
|
+
:user-data="JSON.stringify(userData)"
|
|
52
|
+
current-language="en"
|
|
53
|
+
token="your-auth-token"
|
|
54
|
+
/>
|
|
55
|
+
</template>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### React
|
|
59
|
+
```jsx
|
|
60
|
+
import '@webpros/tsxuserprofilevue'
|
|
61
|
+
|
|
62
|
+
function UserProfile() {
|
|
63
|
+
const userData = {
|
|
64
|
+
email: 'user@example.com',
|
|
65
|
+
firstName: 'John',
|
|
66
|
+
familyName: 'Doe',
|
|
67
|
+
timezone: 'America/New_York'
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
<tsx-user-profile
|
|
72
|
+
base-api-url="https://api.example.com"
|
|
73
|
+
user-data={JSON.stringify(userData)}
|
|
74
|
+
current-language="en"
|
|
75
|
+
token="your-auth-token"
|
|
76
|
+
/>
|
|
77
|
+
)
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Component Props
|
|
82
|
+
|
|
83
|
+
### Required Props
|
|
84
|
+
|
|
85
|
+
| Prop | Type | Description |
|
|
86
|
+
|------|------|-------------|
|
|
87
|
+
| `base-api-url` | String | **Required**. Base URL for API calls |
|
|
88
|
+
|
|
89
|
+
### Optional Props
|
|
90
|
+
|
|
91
|
+
| Prop | Type | Default | Description |
|
|
92
|
+
|------|------|---------|-------------|
|
|
93
|
+
| `current-language` | String | `'en'` | Language code: `'de'`, `'en'`, `'fr'`, `'es'`, `'it'`, `'ja'`, `'ru'`, `'pt'` |
|
|
94
|
+
| `user-data` | String (JSON) | `'{}'` | User information as JSON string (see User Data Structure) |
|
|
95
|
+
| `view` | String | `'profile'` | View type: `'profile'` or `'license'` |
|
|
96
|
+
| `token` | String | `''` | Authentication token for API requests |
|
|
97
|
+
| `read-only` | Boolean/String | `false` | Makes the component read-only (no editing) |
|
|
98
|
+
| `off-canvas` | Boolean | `false` | Display as off-canvas sidebar instead of inline |
|
|
99
|
+
| `open-canvas` | Boolean | `false` | Initial state of off-canvas (open/closed) |
|
|
100
|
+
| `partner-type` | String | `''` | Partner type: `'standaloneRetail'`, `'standalonePartner'`, `'whitelabel'`, `'platform'`, `'partner'` |
|
|
101
|
+
| `is-license-partner` | Boolean | `false` | Whether user is a license partner |
|
|
102
|
+
| `extra-inactive-fields` | String (JSON) | `'[]'` | Additional fields to hide (JSON array string) |
|
|
103
|
+
| `locale-saving-url` | String | `''` | URL endpoint for saving language preferences |
|
|
104
|
+
| `override-base-api-url` | String | `''` | Override the base API URL for specific requests |
|
|
105
|
+
| `complete-upsell-url` | String | `''` | URL for license upsell/purchase flow |
|
|
106
|
+
|
|
107
|
+
## User Data Structure
|
|
108
|
+
|
|
109
|
+
The `user-data` prop accepts a JSON string with the following structure:
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
interface IProfileUser {
|
|
113
|
+
// Basic Information
|
|
114
|
+
email?: string // User's email address
|
|
115
|
+
firstName?: string // User's first name
|
|
116
|
+
familyName?: string // User's last name
|
|
117
|
+
name?: string // Full name (alternative to firstName/familyName)
|
|
118
|
+
nickname?: string // User's nickname
|
|
119
|
+
|
|
120
|
+
// Avatar
|
|
121
|
+
gravatar?: string // Gravatar URL or email hash
|
|
122
|
+
|
|
123
|
+
// System Information
|
|
124
|
+
timezone?: string | null // IANA timezone (e.g., 'America/New_York')
|
|
125
|
+
nixstatsId?: string // Nixstats user ID
|
|
126
|
+
threeSixtyId?: string // 360 Monitoring user ID
|
|
127
|
+
|
|
128
|
+
// Authentication
|
|
129
|
+
sessionToken?: string // Session token
|
|
130
|
+
isOauthUser?: boolean // Whether user authenticated via OAuth
|
|
131
|
+
|
|
132
|
+
// Permissions
|
|
133
|
+
isDeletable?: boolean // Whether account can be deleted
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Example User Data
|
|
138
|
+
|
|
139
|
+
```javascript
|
|
140
|
+
const userData = {
|
|
141
|
+
email: 'john.doe@example.com',
|
|
142
|
+
firstName: 'John',
|
|
143
|
+
familyName: 'Doe',
|
|
144
|
+
nickname: 'johnd',
|
|
145
|
+
gravatar: 'https://www.gravatar.com/avatar/1e45f0572fb68149199a0acb56ccc3dc',
|
|
146
|
+
timezone: 'Europe/Berlin',
|
|
147
|
+
nixstatsId: '12345',
|
|
148
|
+
threeSixtyId: '67890',
|
|
149
|
+
isOauthUser: false,
|
|
150
|
+
isDeletable: true
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Pass as JSON string
|
|
154
|
+
<tsx-user-profile user-data={JSON.stringify(userData)} />
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Important Notes
|
|
158
|
+
|
|
159
|
+
- **All fields are optional**
|
|
160
|
+
- If `timezone` is not provided, the component will use the browser's timezone
|
|
161
|
+
- If `gravatar` is an email, it will be converted to a Gravatar URL automatically
|
|
162
|
+
- If `isDeletable` is `false`, the "Remove Account" option will be hidden
|
|
163
|
+
|
|
164
|
+
## Inactive Fields Configuration
|
|
165
|
+
|
|
166
|
+
You can hide specific sections of the profile using the `extra-inactive-fields` prop and automatic hiding based on `partner-type`.
|
|
167
|
+
|
|
168
|
+
### Available Fields to Hide
|
|
169
|
+
|
|
170
|
+
- `naming` - Name editing section
|
|
171
|
+
- `ids` - User IDs display (nixstatsId, threeSixtyId)
|
|
172
|
+
- `password` - Password change section
|
|
173
|
+
- `language` - Language selector
|
|
174
|
+
- `timezone` - Timezone selector
|
|
175
|
+
- `consent` - Consent/privacy settings
|
|
176
|
+
- `dnt` - Do Not Track settings
|
|
177
|
+
- `removeAccount` - Account deletion option
|
|
178
|
+
- `comparePlansLink` - Compare plans link (license view)
|
|
179
|
+
|
|
180
|
+
### Automatic Hiding by Partner Type
|
|
181
|
+
|
|
182
|
+
Different partner types automatically hide certain fields:
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
// Partner Type Configurations
|
|
186
|
+
{
|
|
187
|
+
'standaloneRetail': [], // No fields hidden
|
|
188
|
+
'standalonePartner': ['consent', 'comparePlansLink'],
|
|
189
|
+
'whitelabel': ['naming', 'password', 'consent'],
|
|
190
|
+
'platform': ['naming', 'password', 'consent'],
|
|
191
|
+
'partner': ['consent', 'comparePlansLink']
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Manual Configuration
|
|
196
|
+
|
|
197
|
+
Use `extra-inactive-fields` to hide additional fields:
|
|
198
|
+
|
|
199
|
+
```html
|
|
200
|
+
<!-- Hide password and timezone fields -->
|
|
201
|
+
<tsx-user-profile
|
|
202
|
+
base-api-url="https://api.example.com"
|
|
203
|
+
user-data='{"email":"user@example.com"}'
|
|
204
|
+
extra-inactive-fields='["password", "timezone"]'
|
|
205
|
+
/>
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Combined Example
|
|
209
|
+
|
|
210
|
+
```html
|
|
211
|
+
<!-- Partner type hides some fields, extra-inactive-fields adds more -->
|
|
212
|
+
<tsx-user-profile
|
|
213
|
+
base-api-url="https://api.example.com"
|
|
214
|
+
partner-type="whitelabel"
|
|
215
|
+
extra-inactive-fields='["language", "ids"]'
|
|
216
|
+
/>
|
|
217
|
+
<!-- This will hide: naming, password, consent (from whitelabel) + language, ids (from extra) -->
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## Event Handling
|
|
221
|
+
|
|
222
|
+
The component uses [MITT](https://github.com/developit/mitt) for event communication. All user interactions emit events that you can listen to.
|
|
223
|
+
|
|
224
|
+
### Setting Up Event Listeners
|
|
225
|
+
|
|
226
|
+
```javascript
|
|
227
|
+
// Listen to all TSXUserProfile events
|
|
228
|
+
window.mitt.on('tsxUserProfile', (payload) => {
|
|
229
|
+
console.log('Event received:', payload)
|
|
230
|
+
|
|
231
|
+
switch(payload.action) {
|
|
232
|
+
case 'updateTimezone':
|
|
233
|
+
console.log('Timezone changed to:', payload.data)
|
|
234
|
+
// Save to your backend
|
|
235
|
+
break
|
|
236
|
+
case 'updateName':
|
|
237
|
+
console.log('Name changed:', payload.data)
|
|
238
|
+
break
|
|
239
|
+
case 'updatePassword':
|
|
240
|
+
console.log('Password change requested')
|
|
241
|
+
break
|
|
242
|
+
// ... handle other events
|
|
243
|
+
}
|
|
244
|
+
})
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### Available Events
|
|
248
|
+
|
|
249
|
+
| Event Action | Payload Data | Description |
|
|
250
|
+
|-------------|--------------|-------------|
|
|
251
|
+
| `updateTimezone` | `string` | User changed timezone |
|
|
252
|
+
| `updateName` | `{firstName: string, familyName: string}` | User updated name |
|
|
253
|
+
| `updatePassword` | `{oldPassword: string, newPassword: string}` | Password change request |
|
|
254
|
+
| `updateLanguage` | `string` | Language changed |
|
|
255
|
+
| `deleteAccount` | `{}` | Account deletion requested |
|
|
256
|
+
| `updateConsent` | `boolean` | Consent settings changed |
|
|
257
|
+
| `updateDnt` | `boolean` | Do Not Track setting changed |
|
|
258
|
+
|
|
259
|
+
### Event Example
|
|
260
|
+
|
|
261
|
+
```javascript
|
|
262
|
+
// Initialize MITT if not already done
|
|
263
|
+
window.mitt = window.mitt || mitt()
|
|
264
|
+
|
|
265
|
+
// Listen for timezone changes
|
|
266
|
+
window.mitt.on('tsxUserProfile', (payload) => {
|
|
267
|
+
if (payload.action === 'updateTimezone') {
|
|
268
|
+
// Send to your API
|
|
269
|
+
fetch('/api/user/timezone', {
|
|
270
|
+
method: 'POST',
|
|
271
|
+
headers: { 'Content-Type': 'application/json' },
|
|
272
|
+
body: JSON.stringify({ timezone: payload.data })
|
|
273
|
+
})
|
|
274
|
+
}
|
|
275
|
+
})
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
## Styling and Theming
|
|
279
|
+
|
|
280
|
+
The component uses CSS custom properties (variables) for theming. Define these in your stylesheet:
|
|
281
|
+
|
|
282
|
+
```css
|
|
283
|
+
:root {
|
|
284
|
+
/* Base Colors */
|
|
285
|
+
--tsxup-brightest: #ffffff;
|
|
286
|
+
--tsxup-brightest-darker: #e5e7eb;
|
|
287
|
+
--tsxup-darkest: #111827;
|
|
288
|
+
--tsxup-darkest-light: #4b5563;
|
|
289
|
+
|
|
290
|
+
/* Signal Colors */
|
|
291
|
+
--tsxup-signal-success: #4CA154;
|
|
292
|
+
--tsxup-signal-error: #b73737;
|
|
293
|
+
|
|
294
|
+
/* Brand Colors */
|
|
295
|
+
--tsxup-primary: #1E40AF;
|
|
296
|
+
--tsxup-primary-light: #668bca;
|
|
297
|
+
|
|
298
|
+
/* Text */
|
|
299
|
+
--tsxup-text: var(--tsxup-darkest);
|
|
300
|
+
--tsxup-text-lighter: var(--tsxup-darkest-light);
|
|
301
|
+
--tsxup-headline: var(--tsxup-darkest);
|
|
302
|
+
|
|
303
|
+
/* Buttons */
|
|
304
|
+
--tsxUp-button-color: var(--tsxup-brightest);
|
|
305
|
+
--tsxUp-button-bg: var(--tsxup-primary);
|
|
306
|
+
--tsxUp-button-color-hover: var(--tsxup-brightest);
|
|
307
|
+
--tsxUp-button-bg-hover: var(--tsxup-primary-light);
|
|
308
|
+
|
|
309
|
+
/* Select Fields */
|
|
310
|
+
--tsxUp-selectField-border: var(--tsxup-brightest-darker);
|
|
311
|
+
--tsxUp-selectField-background: var(--tsxup-brightest);
|
|
312
|
+
--tsxUp-selectField-backgroundHover: var(--tsxup-brightest);
|
|
313
|
+
--tsxUp-selectField-backgroundDisabled: var(--tsxup-brightest-darker);
|
|
314
|
+
--tsxUp-selectField-color: var(--tsxup-darkest);
|
|
315
|
+
--tsxUp-selectField-selectedBackground: var(--tsxup-primary-light);
|
|
316
|
+
--tsxUp-selectField-selectedColor: var(--tsxup-brightest);
|
|
317
|
+
}
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### Dark Mode Example
|
|
321
|
+
|
|
322
|
+
```css
|
|
323
|
+
@media (prefers-color-scheme: dark) {
|
|
324
|
+
:root {
|
|
325
|
+
--tsxup-brightest: #1f2937;
|
|
326
|
+
--tsxup-brightest-darker: #374151;
|
|
327
|
+
--tsxup-darkest: #f9fafb;
|
|
328
|
+
--tsxup-darkest-light: #d1d5db;
|
|
329
|
+
--tsxup-text: var(--tsxup-darkest);
|
|
330
|
+
--tsxup-headline: var(--tsxup-darkest);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
## Advanced Usage Examples
|
|
336
|
+
|
|
337
|
+
### Off-Canvas Sidebar Mode
|
|
338
|
+
|
|
339
|
+
Display the profile as a sliding sidebar panel:
|
|
340
|
+
|
|
341
|
+
```html
|
|
342
|
+
<tsx-user-profile
|
|
343
|
+
base-api-url="https://api.example.com"
|
|
344
|
+
user-data='{"email":"user@example.com","firstName":"John"}'
|
|
345
|
+
off-canvas="true"
|
|
346
|
+
open-canvas="false"
|
|
347
|
+
view="profile"
|
|
348
|
+
token="your-token"
|
|
349
|
+
/>
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
Control the canvas programmatically:
|
|
353
|
+
|
|
354
|
+
```javascript
|
|
355
|
+
// Open the canvas
|
|
356
|
+
window.mitt.emit('openCanvas', { view: 'profile' })
|
|
357
|
+
|
|
358
|
+
// Close the canvas
|
|
359
|
+
window.mitt.emit('closeCanvas')
|
|
360
|
+
|
|
361
|
+
// Switch to license view
|
|
362
|
+
window.mitt.emit('openCanvas', { view: 'license' })
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
### License Management View
|
|
366
|
+
|
|
367
|
+
Display license and subscription information:
|
|
368
|
+
|
|
369
|
+
```html
|
|
370
|
+
<tsx-user-profile
|
|
371
|
+
base-api-url="https://api.example.com"
|
|
372
|
+
view="license"
|
|
373
|
+
read-only="false"
|
|
374
|
+
complete-upsell-url="https://example.com/upsell"
|
|
375
|
+
token="your-token"
|
|
376
|
+
/>
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
### Read-Only Profile
|
|
380
|
+
|
|
381
|
+
Display user information without editing capabilities:
|
|
382
|
+
|
|
383
|
+
```html
|
|
384
|
+
<tsx-user-profile
|
|
385
|
+
base-api-url="https://api.example.com"
|
|
386
|
+
user-data='{"email":"user@example.com","firstName":"John","familyName":"Doe"}'
|
|
387
|
+
read-only="true"
|
|
388
|
+
extra-inactive-fields='["password", "removeAccount"]'
|
|
389
|
+
/>
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
### Multi-Language Support
|
|
393
|
+
|
|
394
|
+
```html
|
|
395
|
+
<!-- German -->
|
|
396
|
+
<tsx-user-profile
|
|
397
|
+
base-api-url="https://api.example.com"
|
|
398
|
+
current-language="de"
|
|
399
|
+
user-data='{"email":"benutzer@beispiel.de"}'
|
|
400
|
+
/>
|
|
401
|
+
|
|
402
|
+
<!-- French -->
|
|
403
|
+
<tsx-user-profile
|
|
404
|
+
base-api-url="https://api.example.com"
|
|
405
|
+
current-language="fr"
|
|
406
|
+
user-data='{"email":"utilisateur@exemple.fr"}'
|
|
407
|
+
/>
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
Supported languages: `de`, `en`, `fr`, `es`, `it`, `ja`, `ru`, `pt`
|
|
411
|
+
|
|
412
|
+
### Complete Integration Example
|
|
413
|
+
|
|
414
|
+
```html
|
|
415
|
+
<!DOCTYPE html>
|
|
416
|
+
<html lang="en">
|
|
417
|
+
<head>
|
|
418
|
+
<meta charset="UTF-8">
|
|
419
|
+
<title>User Profile</title>
|
|
420
|
+
<script type="module" src="https://unpkg.com/@webpros/tsxuserprofilevue/dist/index.js"></script>
|
|
421
|
+
<link rel="stylesheet" href="https://unpkg.com/@webpros/tsxuserprofilevue/dist/tsxUserProfile.css">
|
|
422
|
+
<style>
|
|
423
|
+
:root {
|
|
424
|
+
--tsxup-primary: #0066cc;
|
|
425
|
+
--tsxup-primary-light: #3399ff;
|
|
426
|
+
}
|
|
427
|
+
.profile-container {
|
|
428
|
+
max-width: 800px;
|
|
429
|
+
margin: 0 auto;
|
|
430
|
+
padding: 20px;
|
|
431
|
+
}
|
|
432
|
+
</style>
|
|
433
|
+
</head>
|
|
434
|
+
<body>
|
|
435
|
+
<div class="profile-container">
|
|
436
|
+
<h1>My Profile</h1>
|
|
437
|
+
<tsx-user-profile
|
|
438
|
+
id="userProfile"
|
|
439
|
+
base-api-url="https://api.example.com"
|
|
440
|
+
current-language="en"
|
|
441
|
+
token="your-auth-token"
|
|
442
|
+
/>
|
|
443
|
+
</div>
|
|
444
|
+
|
|
445
|
+
<script type="module">
|
|
446
|
+
import mitt from 'https://unpkg.com/mitt/dist/mitt.mjs'
|
|
447
|
+
|
|
448
|
+
// Initialize MITT
|
|
449
|
+
window.mitt = window.mitt || mitt()
|
|
450
|
+
|
|
451
|
+
// Fetch user data from your API
|
|
452
|
+
async function loadUserData() {
|
|
453
|
+
const response = await fetch('https://api.example.com/user/profile', {
|
|
454
|
+
headers: { 'Authorization': 'Bearer your-auth-token' }
|
|
455
|
+
})
|
|
456
|
+
const userData = await response.json()
|
|
457
|
+
|
|
458
|
+
// Set user data on component
|
|
459
|
+
const profile = document.getElementById('userProfile')
|
|
460
|
+
profile.setAttribute('user-data', JSON.stringify(userData))
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
// Handle events
|
|
464
|
+
window.mitt.on('tsxUserProfile', async (payload) => {
|
|
465
|
+
console.log('Event:', payload)
|
|
466
|
+
|
|
467
|
+
// Save changes to your API
|
|
468
|
+
if (payload.action === 'updateTimezone') {
|
|
469
|
+
await fetch('https://api.example.com/user/timezone', {
|
|
470
|
+
method: 'POST',
|
|
471
|
+
headers: {
|
|
472
|
+
'Authorization': 'Bearer your-auth-token',
|
|
473
|
+
'Content-Type': 'application/json'
|
|
474
|
+
},
|
|
475
|
+
body: JSON.stringify({ timezone: payload.data })
|
|
476
|
+
})
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
if (payload.action === 'updateName') {
|
|
480
|
+
await fetch('https://api.example.com/user/name', {
|
|
481
|
+
method: 'POST',
|
|
482
|
+
headers: {
|
|
483
|
+
'Authorization': 'Bearer your-auth-token',
|
|
484
|
+
'Content-Type': 'application/json'
|
|
485
|
+
},
|
|
486
|
+
body: JSON.stringify(payload.data)
|
|
487
|
+
})
|
|
488
|
+
}
|
|
489
|
+
})
|
|
490
|
+
|
|
491
|
+
// Load user data on page load
|
|
492
|
+
loadUserData()
|
|
493
|
+
</script>
|
|
494
|
+
</body>
|
|
495
|
+
</html>
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
## Framework-Specific Integration
|
|
499
|
+
|
|
500
|
+
### Vue 3 / Nuxt 3
|
|
501
|
+
|
|
502
|
+
```vue
|
|
503
|
+
<script setup>
|
|
504
|
+
import { ref, onMounted } from 'vue'
|
|
505
|
+
import '@webpros/tsxuserprofilevue'
|
|
506
|
+
import mitt from 'mitt'
|
|
507
|
+
|
|
508
|
+
// Initialize MITT
|
|
509
|
+
if (!window.mitt) {
|
|
510
|
+
window.mitt = mitt()
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
const userData = ref({
|
|
514
|
+
email: 'user@example.com',
|
|
515
|
+
firstName: 'John',
|
|
516
|
+
familyName: 'Doe',
|
|
517
|
+
timezone: 'America/New_York'
|
|
518
|
+
})
|
|
519
|
+
|
|
520
|
+
onMounted(() => {
|
|
521
|
+
window.mitt.on('tsxUserProfile', (payload) => {
|
|
522
|
+
console.log('Profile event:', payload)
|
|
523
|
+
// Handle events
|
|
524
|
+
})
|
|
525
|
+
})
|
|
526
|
+
</script>
|
|
527
|
+
|
|
528
|
+
<template>
|
|
529
|
+
<div class="profile-wrapper">
|
|
530
|
+
<tsx-user-profile
|
|
531
|
+
base-api-url="https://api.example.com"
|
|
532
|
+
:user-data="JSON.stringify(userData)"
|
|
533
|
+
current-language="en"
|
|
534
|
+
token="your-token"
|
|
535
|
+
/>
|
|
536
|
+
</div>
|
|
537
|
+
</template>
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
### React / Next.js
|
|
541
|
+
|
|
542
|
+
```jsx
|
|
543
|
+
import { useEffect, useRef } from 'react'
|
|
544
|
+
import '@webpros/tsxuserprofilevue'
|
|
545
|
+
import mitt from 'mitt'
|
|
546
|
+
|
|
547
|
+
export default function UserProfile() {
|
|
548
|
+
const userData = {
|
|
549
|
+
email: 'user@example.com',
|
|
550
|
+
firstName: 'John',
|
|
551
|
+
familyName: 'Doe',
|
|
552
|
+
timezone: 'America/New_York'
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
useEffect(() => {
|
|
556
|
+
// Initialize MITT
|
|
557
|
+
if (!window.mitt) {
|
|
558
|
+
window.mitt = mitt()
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
// Event listener
|
|
562
|
+
const handleEvent = (payload) => {
|
|
563
|
+
console.log('Profile event:', payload)
|
|
564
|
+
// Handle events
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
window.mitt.on('tsxUserProfile', handleEvent)
|
|
568
|
+
|
|
569
|
+
return () => {
|
|
570
|
+
window.mitt.off('tsxUserProfile', handleEvent)
|
|
571
|
+
}
|
|
572
|
+
}, [])
|
|
573
|
+
|
|
574
|
+
return (
|
|
575
|
+
<div className="profile-wrapper">
|
|
576
|
+
<tsx-user-profile
|
|
577
|
+
base-api-url="https://api.example.com"
|
|
578
|
+
user-data={JSON.stringify(userData)}
|
|
579
|
+
current-language="en"
|
|
580
|
+
token="your-token"
|
|
581
|
+
/>
|
|
582
|
+
</div>
|
|
583
|
+
)
|
|
584
|
+
}
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
## Troubleshooting
|
|
588
|
+
|
|
589
|
+
### Component Not Rendering
|
|
590
|
+
|
|
591
|
+
1. **Check if the script is loaded**: Verify the component script is included
|
|
592
|
+
2. **Check user-data format**: Must be a valid JSON string
|
|
593
|
+
3. **Check base-api-url**: This prop is required
|
|
594
|
+
|
|
595
|
+
### Events Not Firing
|
|
596
|
+
|
|
597
|
+
1. **Initialize MITT**: Ensure `window.mitt` is initialized before the component loads
|
|
598
|
+
2. **Check event listener**: Make sure you're listening to `'tsxUserProfile'` events
|
|
599
|
+
|
|
600
|
+
### Styling Issues
|
|
601
|
+
|
|
602
|
+
1. **CSS Variables**: Ensure CSS variables are defined in your stylesheet
|
|
603
|
+
2. **CSS Import**: Import the component's CSS file
|
|
604
|
+
3. **Wrapper Styling**: Add custom styling via a wrapper div
|
|
605
|
+
|
|
606
|
+
### TypeScript Support
|
|
607
|
+
|
|
608
|
+
```typescript
|
|
609
|
+
// Type definitions for user data
|
|
610
|
+
interface IProfileUser {
|
|
611
|
+
email?: string
|
|
612
|
+
firstName?: string
|
|
613
|
+
familyName?: string
|
|
614
|
+
name?: string
|
|
615
|
+
nickname?: string
|
|
616
|
+
gravatar?: string
|
|
617
|
+
timezone?: string | null
|
|
618
|
+
nixstatsId?: string
|
|
619
|
+
threeSixtyId?: string
|
|
620
|
+
sessionToken?: string
|
|
621
|
+
isOauthUser?: boolean
|
|
622
|
+
isDeletable?: boolean
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
// Event payload type
|
|
626
|
+
interface TSXUserProfileEvent {
|
|
627
|
+
action: string
|
|
628
|
+
data: any
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
// Usage
|
|
632
|
+
const userData: IProfileUser = {
|
|
633
|
+
email: 'user@example.com',
|
|
634
|
+
firstName: 'John',
|
|
635
|
+
familyName: 'Doe'
|
|
636
|
+
}
|
|
637
|
+
```
|
|
638
|
+
|
|
639
|
+
## API Requirements
|
|
640
|
+
|
|
641
|
+
The component expects certain API endpoints to be available at the `base-api-url`:
|
|
642
|
+
|
|
643
|
+
- `GET /user/profile` - Fetch user profile data
|
|
644
|
+
- `POST /user/timezone` - Update timezone
|
|
645
|
+
- `POST /user/name` - Update name
|
|
646
|
+
- `POST /user/password` - Change password
|
|
647
|
+
- `GET /licenses` - Fetch license information (for license view)
|
|
648
|
+
- `GET /plans` - Fetch available subscription plans
|
|
649
|
+
|
|
650
|
+
Ensure your backend implements these endpoints or use the event system to handle data persistence.
|
|
651
|
+
|
|
652
|
+
## License
|
|
653
|
+
|
|
654
|
+
MIT
|
|
655
|
+
|
|
656
|
+
## Support
|
|
657
|
+
|
|
658
|
+
For issues and questions, please visit the [GitHub repository](https://github.com/leankoala-gmbh/tsxuserprofilevue).
|
|
659
|
+
|