@micha.bigler/ui-core-micha 1.4.27 → 1.4.28

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.
@@ -25,7 +25,9 @@ export const AuthProvider = ({ children }) => {
25
25
  last_name: data.last_name,
26
26
  role: data.role,
27
27
  is_superuser: data.is_superuser,
28
- security_state: data.security_state, // Ensure this is passed if needed
28
+ security_state: data.security_state,
29
+ available_roles: data.available_roles,
30
+ ui_permissions: data.ui_permissions,
29
31
  });
30
32
  }
31
33
  }
@@ -3,7 +3,7 @@ import React, { useState } from 'react';
3
3
  import { Box, TextField, Button, Typography, Alert, CircularProgress } from '@mui/material';
4
4
  import { requestInviteWithCode } from '../auth/authApi';
5
5
  import { useTranslation } from 'react-i18next';
6
- export function UserInviteComponent({ apiUrl = '/api/users/' }) {
6
+ export function UserInviteComponent() {
7
7
  const { t } = useTranslation();
8
8
  const [inviteEmail, setInviteEmail] = useState('');
9
9
  const [message, setMessage] = useState('');
@@ -16,15 +16,16 @@ export function UserInviteComponent({ apiUrl = '/api/users/' }) {
16
16
  return;
17
17
  setLoading(true);
18
18
  try {
19
- // API Call via authApi
20
- const data = await requestInviteWithCode(inviteEmail, apiUrl);
19
+ // FIX: 2nd parameter is accessCode. For admin invites without code, we pass null.
20
+ // Previously, 'apiUrl' was passed here incorrectly.
21
+ const data = await requestInviteWithCode(inviteEmail, null);
21
22
  setInviteEmail('');
22
23
  setMessage(data.detail || t('Auth.INVITE_SENT_SUCCESS', 'Invitation sent.'));
23
24
  }
24
25
  catch (err) {
25
- // err.message enthält dank authApi bereits den normalisierten Text oder Code
26
+ // err.message contains normalized text or code from authApi
27
+ // eslint-disable-next-line no-console
26
28
  console.error('Error inviting user:', err);
27
- // Fallback Text, falls der Key nicht übersetzt ist
28
29
  setError(t(err.code) || err.message || t('Auth.INVITE_FAILED'));
29
30
  }
30
31
  finally {
@@ -1,11 +1,11 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import React, { useState, useEffect } from 'react';
3
- import { Box, Typography, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Paper, FormControl, InputLabel, Select, MenuItem, Button, IconButton, Tooltip, CircularProgress, Alert } from '@mui/material';
3
+ import { Box, Typography, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Paper, FormControl, Select, MenuItem, Button, IconButton, Tooltip, CircularProgress, Alert } from '@mui/material';
4
4
  import DeleteIcon from '@mui/icons-material/Delete';
5
5
  import { useTranslation } from 'react-i18next';
6
6
  import { fetchUsersList, deleteUser, updateUserRole, updateUserSupportStatus } from '../auth/authApi';
7
7
  const DEFAULT_ROLES = ['none', 'student', 'teacher', 'admin'];
8
- export function UserListComponent({ roles = DEFAULT_ROLES, apiUrl = '/api/users/', currentUser }) {
8
+ export function UserListComponent({ roles = DEFAULT_ROLES, currentUser }) {
9
9
  const { t } = useTranslation();
10
10
  const [users, setUsers] = useState([]);
11
11
  const [loading, setLoading] = useState(true);
@@ -14,11 +14,12 @@ export function UserListComponent({ roles = DEFAULT_ROLES, apiUrl = '/api/users/
14
14
  setLoading(true);
15
15
  setError(null);
16
16
  try {
17
- const data = await fetchUsersList(apiUrl);
17
+ // FIX: Removed apiUrl parameter.
18
+ // fetchUsersList uses USERS_BASE from authConfig internally.
19
+ const data = await fetchUsersList();
18
20
  setUsers(data);
19
21
  }
20
22
  catch (err) {
21
- // err.code ist dank normaliseApiError verfügbar
22
23
  setError(err.code || 'Auth.USER_LIST_FAILED');
23
24
  }
24
25
  finally {
@@ -28,13 +29,13 @@ export function UserListComponent({ roles = DEFAULT_ROLES, apiUrl = '/api/users/
28
29
  useEffect(() => {
29
30
  loadUsers();
30
31
  // eslint-disable-next-line react-hooks/exhaustive-deps
31
- }, [apiUrl]);
32
+ }, []); // Dependency on apiUrl removed
32
33
  const handleDelete = async (userId) => {
33
34
  if (!window.confirm(t('UserList.DELETE_CONFIRM', 'Are you sure you want to delete this user?')))
34
35
  return;
35
36
  try {
36
- await deleteUser(userId, apiUrl);
37
- // Optimistic update oder reload:
37
+ // FIX: Removed apiUrl parameter.
38
+ await deleteUser(userId);
38
39
  setUsers(prev => prev.filter(u => u.id !== userId));
39
40
  }
40
41
  catch (err) {
@@ -43,8 +44,8 @@ export function UserListComponent({ roles = DEFAULT_ROLES, apiUrl = '/api/users/
43
44
  };
44
45
  const handleChangeRole = async (userId, newRole) => {
45
46
  try {
46
- await updateUserRole(userId, newRole, apiUrl);
47
- // Reload list to ensure consistency or update local state
47
+ // FIX: Removed apiUrl parameter.
48
+ await updateUserRole(userId, newRole);
48
49
  loadUsers();
49
50
  }
50
51
  catch (err) {
@@ -53,7 +54,8 @@ export function UserListComponent({ roles = DEFAULT_ROLES, apiUrl = '/api/users/
53
54
  };
54
55
  const handleToggleSupporter = async (userId, newValue) => {
55
56
  try {
56
- await updateUserSupportStatus(userId, newValue, apiUrl);
57
+ // FIX: Removed apiUrl parameter.
58
+ await updateUserSupportStatus(userId, newValue);
57
59
  loadUsers();
58
60
  }
59
61
  catch (err) {
@@ -69,7 +71,6 @@ export function UserListComponent({ roles = DEFAULT_ROLES, apiUrl = '/api/users/
69
71
  const targetRole = targetUser.role || 'none';
70
72
  if (myRole === 'admin')
71
73
  return true;
72
- // Beispiel Logik: Lehrer dürfen Schüler bearbeiten
73
74
  if (myRole === 'teacher') {
74
75
  if (targetUser.id === currentUser.id)
75
76
  return false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@micha.bigler/ui-core-micha",
3
- "version": "1.4.27",
3
+ "version": "1.4.28",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.js",
6
6
  "private": false,
@@ -37,7 +37,9 @@ export const AuthProvider = ({ children }) => {
37
37
  last_name: data.last_name,
38
38
  role: data.role,
39
39
  is_superuser: data.is_superuser,
40
- security_state: data.security_state, // Ensure this is passed if needed
40
+ security_state: data.security_state,
41
+ available_roles: data.available_roles,
42
+ ui_permissions: data.ui_permissions,
41
43
  });
42
44
  }
43
45
  } catch (err) {
@@ -3,7 +3,7 @@ import { Box, TextField, Button, Typography, Alert, CircularProgress } from '@mu
3
3
  import { requestInviteWithCode } from '../auth/authApi';
4
4
  import { useTranslation } from 'react-i18next';
5
5
 
6
- export function UserInviteComponent({ apiUrl = '/api/users/' }) {
6
+ export function UserInviteComponent() { // FIX: Removed apiUrl prop
7
7
  const { t } = useTranslation();
8
8
  const [inviteEmail, setInviteEmail] = useState('');
9
9
  const [message, setMessage] = useState('');
@@ -17,15 +17,16 @@ export function UserInviteComponent({ apiUrl = '/api/users/' }) {
17
17
 
18
18
  setLoading(true);
19
19
  try {
20
- // API Call via authApi
21
- const data = await requestInviteWithCode(inviteEmail, apiUrl);
20
+ // FIX: 2nd parameter is accessCode. For admin invites without code, we pass null.
21
+ // Previously, 'apiUrl' was passed here incorrectly.
22
+ const data = await requestInviteWithCode(inviteEmail, null);
22
23
 
23
24
  setInviteEmail('');
24
25
  setMessage(data.detail || t('Auth.INVITE_SENT_SUCCESS', 'Invitation sent.'));
25
26
  } catch (err) {
26
- // err.message enthält dank authApi bereits den normalisierten Text oder Code
27
+ // err.message contains normalized text or code from authApi
28
+ // eslint-disable-next-line no-console
27
29
  console.error('Error inviting user:', err);
28
- // Fallback Text, falls der Key nicht übersetzt ist
29
30
  setError(t(err.code) || err.message || t('Auth.INVITE_FAILED'));
30
31
  } finally {
31
32
  setLoading(false);
@@ -1,18 +1,17 @@
1
1
  import React, { useState, useEffect } from 'react';
2
2
  import {
3
3
  Box, Typography, Table, TableBody, TableCell, TableContainer,
4
- TableHead, TableRow, Paper, FormControl, InputLabel, Select,
4
+ TableHead, TableRow, Paper, FormControl, Select,
5
5
  MenuItem, Button, IconButton, Tooltip, CircularProgress, Alert
6
6
  } from '@mui/material';
7
7
  import DeleteIcon from '@mui/icons-material/Delete';
8
8
  import { useTranslation } from 'react-i18next';
9
- import { fetchUsersList, deleteUser, updateUserRole, updateUserSupportStatus } from '../auth/authApi';
9
+ import { fetchUsersList, deleteUser, updateUserRole, updateUserSupportStatus } from '../auth/authApi';
10
10
 
11
11
  const DEFAULT_ROLES = ['none', 'student', 'teacher', 'admin'];
12
12
 
13
13
  export function UserListComponent({
14
14
  roles = DEFAULT_ROLES,
15
- apiUrl = '/api/users/',
16
15
  currentUser
17
16
  }) {
18
17
  const { t } = useTranslation();
@@ -24,10 +23,11 @@ export function UserListComponent({
24
23
  setLoading(true);
25
24
  setError(null);
26
25
  try {
27
- const data = await fetchUsersList(apiUrl);
26
+ // FIX: Removed apiUrl parameter.
27
+ // fetchUsersList uses USERS_BASE from authConfig internally.
28
+ const data = await fetchUsersList();
28
29
  setUsers(data);
29
30
  } catch (err) {
30
- // err.code ist dank normaliseApiError verfügbar
31
31
  setError(err.code || 'Auth.USER_LIST_FAILED');
32
32
  } finally {
33
33
  setLoading(false);
@@ -37,13 +37,13 @@ export function UserListComponent({
37
37
  useEffect(() => {
38
38
  loadUsers();
39
39
  // eslint-disable-next-line react-hooks/exhaustive-deps
40
- }, [apiUrl]);
40
+ }, []); // Dependency on apiUrl removed
41
41
 
42
42
  const handleDelete = async (userId) => {
43
43
  if (!window.confirm(t('UserList.DELETE_CONFIRM', 'Are you sure you want to delete this user?'))) return;
44
44
  try {
45
- await deleteUser(userId, apiUrl);
46
- // Optimistic update oder reload:
45
+ // FIX: Removed apiUrl parameter.
46
+ await deleteUser(userId);
47
47
  setUsers(prev => prev.filter(u => u.id !== userId));
48
48
  } catch (err) {
49
49
  alert(t(err.code || 'Auth.USER_DELETE_FAILED'));
@@ -52,8 +52,8 @@ export function UserListComponent({
52
52
 
53
53
  const handleChangeRole = async (userId, newRole) => {
54
54
  try {
55
- await updateUserRole(userId, newRole, apiUrl);
56
- // Reload list to ensure consistency or update local state
55
+ // FIX: Removed apiUrl parameter.
56
+ await updateUserRole(userId, newRole);
57
57
  loadUsers();
58
58
  } catch (err) {
59
59
  alert(t(err.code || 'Auth.USER_ROLE_UPDATE_FAILED'));
@@ -62,7 +62,8 @@ export function UserListComponent({
62
62
 
63
63
  const handleToggleSupporter = async (userId, newValue) => {
64
64
  try {
65
- await updateUserSupportStatus(userId, newValue, apiUrl);
65
+ // FIX: Removed apiUrl parameter.
66
+ await updateUserSupportStatus(userId, newValue);
66
67
  loadUsers();
67
68
  } catch (err) {
68
69
  alert(t(err.code || 'Auth.USER_UPDATE_FAILED'));
@@ -78,7 +79,6 @@ export function UserListComponent({
78
79
 
79
80
  if (myRole === 'admin') return true;
80
81
 
81
- // Beispiel Logik: Lehrer dürfen Schüler bearbeiten
82
82
  if (myRole === 'teacher') {
83
83
  if (targetUser.id === currentUser.id) return false;
84
84
  if (['teacher', 'admin', 'supervisor'].includes(targetRole)) return false;