@mui-toolpad-extended-tuni/users 3.0.4 → 3.2.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/README.md CHANGED
@@ -15,8 +15,8 @@ npm install @mui-toolpad-extended-tuni/users @mui-toolpad-extended-tuni/main @mu
15
15
  This package requires the following peer dependencies to be installed:
16
16
 
17
17
  ### Required Packages
18
- - **`@mui-toolpad-extended-tuni/main`**: ^3.3.0 - **MUST be installed separately**
19
- - **`@mui-toolpad-extended-tuni/core`**: ^3.1.0 - **MUST be installed separately** (also required by main)
18
+ - **`@mui-toolpad-extended-tuni/main`**: ^3.4.0 - **MUST be installed separately**
19
+ - **`@mui-toolpad-extended-tuni/core`**: ^3.2.0 - **MUST be installed separately** (also required by main)
20
20
 
21
21
  ### React & UI Framework
22
22
  - `react@^19.0.0`
@@ -39,6 +39,52 @@ npm install @mui-toolpad-extended-tuni/users @mui-toolpad-extended-tuni/main @mu
39
39
  axios zustand
40
40
  ```
41
41
 
42
+ ## API Configuration
43
+
44
+ This package uses configurable API endpoints. Each microservice accepts its own `apiEndpoints` prop, allowing you to configure endpoints independently for only the services you use.
45
+
46
+ ### Default Endpoints
47
+
48
+ If no `apiEndpoints` prop is provided, the package uses these default endpoints:
49
+
50
+ - `getCurrent: "api/users/current/"` - GET current authenticated user
51
+ - `get: "api/users/"` - GET list of users
52
+ - `post: "api/users/"` - POST create new user
53
+ - `put: "api/users/:id/"` - PUT update user (use `:id` placeholder)
54
+ - `delete: "api/users/:id/"` - DELETE user (use `:id` placeholder)
55
+ - `logout: "/auth/lti_logout/"` - POST logout user
56
+
57
+ ### Customizing Endpoints
58
+
59
+ Configure endpoints directly on the `UserMicroservice` component:
60
+
61
+ ```tsx
62
+ import { UserMicroservice } from '@mui-toolpad-extended-tuni/users';
63
+ import type { UsersApiEndpoints } from '@mui-toolpad-extended-tuni/users';
64
+
65
+ const usersEndpoints: UsersApiEndpoints = {
66
+ getCurrent: "https://api.example.com/v1/users/me",
67
+ get: "https://api.example.com/v1/users",
68
+ post: "https://api.example.com/v1/users",
69
+ put: "https://api.example.com/v1/users/:id",
70
+ delete: "https://api.example.com/v1/users/:id",
71
+ logout: "https://api.example.com/v1/auth/logout",
72
+ };
73
+
74
+ <UserMicroservice apiEndpoints={usersEndpoints} />
75
+ ```
76
+
77
+ **Note**: You can use either full URLs or relative paths. Placeholders like `:id` will be replaced with actual values at runtime.
78
+
79
+ **Partial Configuration**: You can configure only the endpoints you need to customize. Unspecified endpoints will use defaults:
80
+
81
+ ```tsx
82
+ <UserMicroservice apiEndpoints={{
83
+ getCurrent: "api/v2/users/me", // Only override getCurrent endpoint
84
+ // Other endpoints use defaults
85
+ }} />
86
+ ```
87
+
42
88
  ## Usage
43
89
 
44
90
  ### Basic Setup
@@ -110,6 +156,261 @@ function App() {
110
156
  }
111
157
  ```
112
158
 
159
+ ## API Endpoints
160
+
161
+ This package makes the following API calls. All endpoints are configurable via `apiConfig`.
162
+
163
+ ### GET `/api/users/current/` (or configured `getCurrent` endpoint)
164
+
165
+ Retrieves the currently authenticated user.
166
+
167
+ **Request**: No body required (uses session/cookies for authentication)
168
+
169
+ **Response**: `200 OK`
170
+ ```json
171
+ {
172
+ "id": "user-123",
173
+ "name": "John Doe",
174
+ "email": "john.doe@example.com",
175
+ "gender": "male",
176
+ "image": {
177
+ "large": "https://example.com/images/user-large.jpg",
178
+ "medium": "https://example.com/images/user-medium.jpg",
179
+ "thumbnail": "https://example.com/images/user-thumbnail.jpg"
180
+ },
181
+ "department": "Computer Science",
182
+ "platform_roles": ["user", "creator"],
183
+ "privacy_settings": {
184
+ "allow_analytics": true,
185
+ "allow_personalization": true,
186
+ "allow_communications": true,
187
+ "allow_third_party_sharing": false
188
+ },
189
+ "gdpr_consent": {
190
+ "accepted": true,
191
+ "accepted_date": "2024-01-15T10:00:00Z",
192
+ "last_updated": "2024-01-15T10:00:00Z"
193
+ },
194
+ "data_retention": {
195
+ "delete_account_after_inactivity": 365,
196
+ "delete_data_after_account_deletion": 30
197
+ },
198
+ "preferences": {
199
+ "navigation_type": "direct",
200
+ "visible_course_lists": {
201
+ "is_student": true,
202
+ "is_student_old": true,
203
+ "is_teacher": false,
204
+ "is_teacher_old": false,
205
+ "available": true
206
+ },
207
+ "last_visited_courses": ["COMP.CS.100:compcs100-fall-2024"],
208
+ "visible_navigation": ["Courses", "Calendar"]
209
+ }
210
+ }
211
+ ```
212
+
213
+ **Response Type**: `UserData`
214
+
215
+ ### GET `/api/users/` (or configured `get` endpoint)
216
+
217
+ Retrieves a list of users. Optionally filtered by course.
218
+
219
+ **Request Parameters** (query string):
220
+ - `course_id` (optional) - Filter users by course ID
221
+
222
+ **Example**: `GET /api/users/?course_id=course-123`
223
+
224
+ **Response**: `200 OK`
225
+ ```json
226
+ [
227
+ {
228
+ "id": "user-123",
229
+ "name": "John Doe",
230
+ "email": "john.doe@example.com",
231
+ // ... same structure as getCurrent
232
+ },
233
+ {
234
+ "id": "user-456",
235
+ "name": "Jane Smith",
236
+ "email": "jane.smith@example.com",
237
+ // ...
238
+ }
239
+ ]
240
+ ```
241
+
242
+ **Response Type**: `UserData[]`
243
+
244
+ ### POST `/api/users/` (or configured `post` endpoint)
245
+
246
+ Creates a new user.
247
+
248
+ **Request Body**: `Partial<UserData>` (snake_case)
249
+ ```json
250
+ {
251
+ "name": "John Doe",
252
+ "email": "john.doe@example.com",
253
+ "gender": "male",
254
+ "department": "Computer Science",
255
+ "platform_roles": ["user"],
256
+ "privacy_settings": {
257
+ "allow_analytics": true,
258
+ "allow_personalization": true,
259
+ "allow_communications": true,
260
+ "allow_third_party_sharing": false
261
+ },
262
+ "gdpr_consent": {
263
+ "accepted": true,
264
+ "last_updated": "2024-01-15T10:00:00Z"
265
+ },
266
+ "data_retention": {
267
+ "delete_account_after_inactivity": 365,
268
+ "delete_data_after_account_deletion": 30
269
+ },
270
+ "preferences": {
271
+ "navigation_type": "direct",
272
+ "visible_course_lists": {
273
+ "is_student": true,
274
+ "is_student_old": true,
275
+ "is_teacher": false,
276
+ "is_teacher_old": false,
277
+ "available": true
278
+ },
279
+ "last_visited_courses": [],
280
+ "visible_navigation": ["Courses"]
281
+ }
282
+ }
283
+ ```
284
+
285
+ **Response**: `201 Created`
286
+ ```json
287
+ {
288
+ "id": "user-123",
289
+ "name": "John Doe",
290
+ // ... full UserData object with generated ID
291
+ }
292
+ ```
293
+
294
+ **Response Type**: `UserData`
295
+
296
+ **Note**: The request body should be in snake_case format. The package automatically converts from camelCase.
297
+
298
+ ### PUT `/api/users/:id/` (or configured `put` endpoint)
299
+
300
+ Updates an existing user.
301
+
302
+ **Request Parameters**:
303
+ - `:id` (path parameter) - User ID
304
+
305
+ **Request Body**: `UserData` (snake_case, must include `id`)
306
+ ```json
307
+ {
308
+ "id": "user-123",
309
+ "name": "Updated Name",
310
+ "email": "updated.email@example.com",
311
+ // ... all UserData fields
312
+ }
313
+ ```
314
+
315
+ **Response**: `200 OK`
316
+ ```json
317
+ {
318
+ "id": "user-123",
319
+ "name": "Updated Name",
320
+ // ... updated UserData object
321
+ }
322
+ ```
323
+
324
+ **Response Type**: `UserData`
325
+
326
+ ### DELETE `/api/users/:id/` (or configured `delete` endpoint)
327
+
328
+ Deletes a user.
329
+
330
+ **Request Parameters**:
331
+ - `:id` (path parameter) - User ID
332
+
333
+ **Response**: `200 OK` or `204 No Content`
334
+
335
+ **Response Type**: `void`
336
+
337
+ ### POST `/auth/lti_logout/` (or configured `logout` endpoint)
338
+
339
+ Logs out the current user (LTI logout).
340
+
341
+ **Request**: No body required
342
+
343
+ **Response**: `200 OK` or `204 No Content`
344
+
345
+ **Response Type**: `void`
346
+
347
+ ## Data Types
348
+
349
+ ### UserData
350
+
351
+ Complete user object returned by API.
352
+
353
+ ```typescript
354
+ interface UserData {
355
+ id: userId; // Unique user ID (string)
356
+ name: string; // User's full name
357
+ email: string; // User's email address
358
+ gender?: gender; // "male" | "female" | "other" (optional)
359
+ image?: { // User profile images (optional)
360
+ large: string; // Large image URL
361
+ medium: string; // Medium image URL
362
+ thumbnail: string; // Thumbnail image URL
363
+ };
364
+ department?: string; // User's department (optional)
365
+ platformRoles: PlatformRole[]; // Array of platform roles
366
+ privacySettings: { // Privacy preferences
367
+ allowAnalytics: boolean;
368
+ allowPersonalization: boolean;
369
+ allowCommunications: boolean;
370
+ allowThirdPartySharing: boolean;
371
+ };
372
+ gdprConsent: { // GDPR consent information
373
+ accepted: boolean;
374
+ acceptedDate?: string; // ISO date string (optional)
375
+ lastUpdated: string; // ISO date string
376
+ };
377
+ dataRetention: { // Data retention settings
378
+ deleteAccountAfterInactivity?: number; // Days (optional)
379
+ deleteDataAfterAccountDeletion?: number; // Days (optional)
380
+ };
381
+ preferences: { // User preferences
382
+ navigationType: navigationTypes; // "direct" | "instances"
383
+ visibleCourseLists: {
384
+ isStudent: boolean;
385
+ isStudentOld: boolean;
386
+ isTeacher: boolean;
387
+ isTeacherOld: boolean;
388
+ available: boolean;
389
+ };
390
+ lastVisitedCourses: string[]; // Array of "code:instance" strings
391
+ visibleNavigation: string[]; // Array of visible navigation items
392
+ };
393
+ }
394
+ ```
395
+
396
+ ### Type Definitions
397
+
398
+ ```typescript
399
+ type userId = string;
400
+ type navigationTypes = "direct" | "instances";
401
+ type gender = "male" | "female" | "other";
402
+ type PlatformRole = "admin" | "developer" | "moderator" | "creator" | "user" | "guest";
403
+ ```
404
+
405
+ ### Request/Response Format
406
+
407
+ **Important**: The backend API expects and returns data in **snake_case** format (e.g., `platform_roles`, `privacy_settings`). This package automatically converts between camelCase (used in TypeScript) and snake_case (used in API requests/responses).
408
+
409
+ **Example conversion**:
410
+ - TypeScript: `platformRoles` → API: `platform_roles`
411
+ - TypeScript: `privacySettings` → API: `privacy_settings`
412
+ - TypeScript: `lastVisitedCourses` → API: `last_visited_courses`
413
+
113
414
  ## Exports
114
415
 
115
416
  ### Components
@@ -121,15 +422,27 @@ function App() {
121
422
  ### Store
122
423
  - `useUserStore` - Zustand store for user management
123
424
 
425
+ ### Network Functions
426
+ - `getCurrentUser()` - Fetch current authenticated user
427
+ - `getUsers(courseId?: string)` - Fetch list of users (optionally filtered by course)
428
+ - `createUser(userData: Partial<UserData>)` - Create new user
429
+ - `updateUser(userData: UserData)` - Update existing user
430
+ - `deleteUser(userId: string)` - Delete user
431
+ - `logoutUser()` - Logout current user
432
+
433
+ ### Hooks
434
+ - `useUsersApiConfig()` - Hook to access users API endpoint configuration
435
+
124
436
  ### Configuration
125
437
  - `configureUserBus` - Configures UserBus with store methods (called automatically)
126
438
 
127
439
  ### Types
128
- - `UserData` - User data type (re-exported from main package)
129
- - `PlatformRole` - Platform role type (re-exported from main package)
130
- - `navigationTypes` - Navigation types (re-exported from main package)
131
- - `gender` - Gender type (re-exported from main package)
132
- - `userId` - User ID type (re-exported from main package)
440
+ - `UserData` - Complete user data type
441
+ - `UsersApiEndpoints` - API endpoint configuration type
442
+ - `PlatformRole` - Platform role type
443
+ - `navigationTypes` - Navigation types
444
+ - `gender` - Gender type
445
+ - `userId` - User ID type
133
446
 
134
447
  ## Features
135
448
 
@@ -1,6 +1,9 @@
1
1
  import { default as React, ReactNode } from 'react';
2
- interface UserMicroserviceProps {
2
+ import { UsersApiEndpoints } from '@mui-toolpad-extended-tuni/core';
3
+ export interface UserMicroserviceProps {
3
4
  children?: ReactNode;
5
+ /** API endpoint configuration for the users microservice */
6
+ apiEndpoints?: UsersApiEndpoints;
4
7
  }
5
8
  /**
6
9
  * UserMicroservice Component
@@ -0,0 +1,15 @@
1
+ import { UsersApiEndpoints } from '@mui-toolpad-extended-tuni/core';
2
+ /**
3
+ * Hook to access users API configuration.
4
+ * Returns the users endpoint configuration merged with defaults.
5
+ *
6
+ * @returns Users API endpoints configuration, or undefined if not registered
7
+ * @throws Error if used outside of ApiConfigProvider
8
+ *
9
+ * @example
10
+ * ```tsx
11
+ * const usersConfig = useUsersApiConfig();
12
+ * const endpoint = usersConfig?.getCurrent; // "api/users/current/" or custom value
13
+ * ```
14
+ */
15
+ export declare const useUsersApiConfig: () => UsersApiEndpoints | undefined;