@micha.bigler/ui-core-micha 1.4.35 → 1.4.37
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/auth/authApi.js
CHANGED
|
@@ -255,6 +255,32 @@ export async function generateRecoveryCodes() {
|
|
|
255
255
|
// -----------------------------
|
|
256
256
|
// Invitations & Access Codes
|
|
257
257
|
// -----------------------------
|
|
258
|
+
export async function fetchAccessCodes() {
|
|
259
|
+
try {
|
|
260
|
+
const res = await apiClient.get(`${ACCESS_CODES_BASE}/`);
|
|
261
|
+
return res.data || [];
|
|
262
|
+
}
|
|
263
|
+
catch (error) {
|
|
264
|
+
throw normaliseApiError(error, 'Auth.ACCESS_CODE_LIST_FAILED');
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
export async function createAccessCode(code) {
|
|
268
|
+
try {
|
|
269
|
+
const res = await apiClient.post(`${ACCESS_CODES_BASE}/`, { code });
|
|
270
|
+
return res.data;
|
|
271
|
+
}
|
|
272
|
+
catch (error) {
|
|
273
|
+
throw normaliseApiError(error, 'Auth.ACCESS_CODE_SAVE_FAILED');
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
export async function deleteAccessCode(id) {
|
|
277
|
+
try {
|
|
278
|
+
await apiClient.delete(`${ACCESS_CODES_BASE}/${id}/`);
|
|
279
|
+
}
|
|
280
|
+
catch (error) {
|
|
281
|
+
throw normaliseApiError(error, 'Auth.ACCESS_CODE_DELETE_FAILED');
|
|
282
|
+
}
|
|
283
|
+
}
|
|
258
284
|
export async function validateAccessCode(code) {
|
|
259
285
|
try {
|
|
260
286
|
const res = await apiClient.post(`${ACCESS_CODES_BASE}/validate/`, { code });
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
// src/auth/components/AccessCodeManager.jsx
|
|
3
3
|
import React, { useEffect, useState } from 'react';
|
|
4
|
-
import
|
|
5
|
-
import { Box, Stack, Typography, Slider, Button, TextField, IconButton, Chip, Alert, CircularProgress, } from '@mui/material';
|
|
4
|
+
import { Box, Stack, Typography, Slider, Button, TextField, Chip, Alert, CircularProgress, } from '@mui/material';
|
|
6
5
|
import CloseIcon from '@mui/icons-material/Close';
|
|
7
6
|
import { useTranslation } from 'react-i18next';
|
|
8
|
-
|
|
7
|
+
// Pfad ggf. anpassen je nach Struktur: von src/auth/components zu src/auth/authApi
|
|
8
|
+
import { fetchAccessCodes, createAccessCode, deleteAccessCode, } from '../auth/authApi';
|
|
9
9
|
export function AccessCodeManager() {
|
|
10
10
|
const { t } = useTranslation();
|
|
11
11
|
const [codes, setCodes] = useState([]);
|
|
@@ -15,25 +15,22 @@ export function AccessCodeManager() {
|
|
|
15
15
|
const [manualCode, setManualCode] = useState('');
|
|
16
16
|
const [errorKey, setErrorKey] = useState(null);
|
|
17
17
|
const [successKey, setSuccessKey] = useState(null);
|
|
18
|
-
//
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
const backendCode = (_b = (_a = err === null || err === void 0 ? void 0 : err.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.code;
|
|
18
|
+
// Helper that prefers backend error code if available
|
|
19
|
+
const setErrorFromErrorObject = (err, fallbackCode) => {
|
|
20
|
+
const backendCode = err === null || err === void 0 ? void 0 : err.code;
|
|
22
21
|
setErrorKey(backendCode || fallbackCode);
|
|
23
22
|
};
|
|
24
|
-
//
|
|
23
|
+
// Load all access codes from backend
|
|
25
24
|
const loadCodes = async () => {
|
|
26
25
|
setLoading(true);
|
|
27
26
|
setErrorKey(null);
|
|
28
27
|
setSuccessKey(null);
|
|
29
28
|
try {
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
});
|
|
33
|
-
setCodes(res.data || []);
|
|
29
|
+
const data = await fetchAccessCodes();
|
|
30
|
+
setCodes(Array.isArray(data) ? data : []);
|
|
34
31
|
}
|
|
35
32
|
catch (err) {
|
|
36
|
-
|
|
33
|
+
setErrorFromErrorObject(err, 'Auth.ACCESS_CODE_LIST_FAILED');
|
|
37
34
|
}
|
|
38
35
|
finally {
|
|
39
36
|
setLoading(false);
|
|
@@ -41,6 +38,7 @@ export function AccessCodeManager() {
|
|
|
41
38
|
};
|
|
42
39
|
useEffect(() => {
|
|
43
40
|
loadCodes();
|
|
41
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
44
42
|
}, []);
|
|
45
43
|
// Generates a random code with the selected length
|
|
46
44
|
const generateRandomCode = (len) => {
|
|
@@ -54,12 +52,12 @@ export function AccessCodeManager() {
|
|
|
54
52
|
setErrorKey(null);
|
|
55
53
|
setSuccessKey(null);
|
|
56
54
|
try {
|
|
57
|
-
const
|
|
58
|
-
setCodes((prev) => [...prev,
|
|
55
|
+
const created = await createAccessCode(code);
|
|
56
|
+
setCodes((prev) => [...prev, created]);
|
|
59
57
|
setSuccessKey('Auth.ACCESS_CODE_SAVE_SUCCESS');
|
|
60
58
|
}
|
|
61
59
|
catch (err) {
|
|
62
|
-
|
|
60
|
+
setErrorFromErrorObject(err, 'Auth.ACCESS_CODE_SAVE_FAILED');
|
|
63
61
|
}
|
|
64
62
|
finally {
|
|
65
63
|
setSubmitting(false);
|
|
@@ -81,14 +79,12 @@ export function AccessCodeManager() {
|
|
|
81
79
|
setErrorKey(null);
|
|
82
80
|
setSuccessKey(null);
|
|
83
81
|
try {
|
|
84
|
-
await
|
|
85
|
-
withCredentials: true,
|
|
86
|
-
});
|
|
82
|
+
await deleteAccessCode(id);
|
|
87
83
|
setCodes((prev) => prev.filter((c) => c.id !== id));
|
|
88
84
|
setSuccessKey('Auth.ACCESS_CODE_DELETE_SUCCESS');
|
|
89
85
|
}
|
|
90
86
|
catch (err) {
|
|
91
|
-
|
|
87
|
+
setErrorFromErrorObject(err, 'Auth.ACCESS_CODE_DELETE_FAILED');
|
|
92
88
|
}
|
|
93
89
|
};
|
|
94
90
|
if (loading) {
|
package/package.json
CHANGED
package/src/auth/authApi.jsx
CHANGED
|
@@ -265,6 +265,32 @@ export async function generateRecoveryCodes() {
|
|
|
265
265
|
// Invitations & Access Codes
|
|
266
266
|
// -----------------------------
|
|
267
267
|
|
|
268
|
+
export async function fetchAccessCodes() {
|
|
269
|
+
try {
|
|
270
|
+
const res = await apiClient.get(`${ACCESS_CODES_BASE}/`);
|
|
271
|
+
return res.data || [];
|
|
272
|
+
} catch (error) {
|
|
273
|
+
throw normaliseApiError(error, 'Auth.ACCESS_CODE_LIST_FAILED');
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
export async function createAccessCode(code) {
|
|
278
|
+
try {
|
|
279
|
+
const res = await apiClient.post(`${ACCESS_CODES_BASE}/`, { code });
|
|
280
|
+
return res.data;
|
|
281
|
+
} catch (error) {
|
|
282
|
+
throw normaliseApiError(error, 'Auth.ACCESS_CODE_SAVE_FAILED');
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
export async function deleteAccessCode(id) {
|
|
287
|
+
try {
|
|
288
|
+
await apiClient.delete(`${ACCESS_CODES_BASE}/${id}/`);
|
|
289
|
+
} catch (error) {
|
|
290
|
+
throw normaliseApiError(error, 'Auth.ACCESS_CODE_DELETE_FAILED');
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
268
294
|
export async function validateAccessCode(code) {
|
|
269
295
|
try {
|
|
270
296
|
const res = await apiClient.post(`${ACCESS_CODES_BASE}/validate/`, { code });
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
// src/auth/components/AccessCodeManager.jsx
|
|
2
2
|
import React, { useEffect, useState } from 'react';
|
|
3
|
-
import axios from 'axios';
|
|
4
3
|
import {
|
|
5
4
|
Box,
|
|
6
5
|
Stack,
|
|
@@ -8,14 +7,19 @@ import {
|
|
|
8
7
|
Slider,
|
|
9
8
|
Button,
|
|
10
9
|
TextField,
|
|
11
|
-
IconButton,
|
|
12
10
|
Chip,
|
|
13
11
|
Alert,
|
|
14
12
|
CircularProgress,
|
|
15
13
|
} from '@mui/material';
|
|
16
14
|
import CloseIcon from '@mui/icons-material/Close';
|
|
17
15
|
import { useTranslation } from 'react-i18next';
|
|
18
|
-
|
|
16
|
+
|
|
17
|
+
// Pfad ggf. anpassen je nach Struktur: von src/auth/components zu src/auth/authApi
|
|
18
|
+
import {
|
|
19
|
+
fetchAccessCodes,
|
|
20
|
+
createAccessCode,
|
|
21
|
+
deleteAccessCode,
|
|
22
|
+
} from '../auth/authApi';
|
|
19
23
|
|
|
20
24
|
export function AccessCodeManager() {
|
|
21
25
|
const { t } = useTranslation();
|
|
@@ -30,24 +34,22 @@ export function AccessCodeManager() {
|
|
|
30
34
|
const [errorKey, setErrorKey] = useState(null);
|
|
31
35
|
const [successKey, setSuccessKey] = useState(null);
|
|
32
36
|
|
|
33
|
-
//
|
|
34
|
-
const
|
|
35
|
-
const backendCode = err?.
|
|
37
|
+
// Helper that prefers backend error code if available
|
|
38
|
+
const setErrorFromErrorObject = (err, fallbackCode) => {
|
|
39
|
+
const backendCode = err?.code;
|
|
36
40
|
setErrorKey(backendCode || fallbackCode);
|
|
37
41
|
};
|
|
38
42
|
|
|
39
|
-
//
|
|
43
|
+
// Load all access codes from backend
|
|
40
44
|
const loadCodes = async () => {
|
|
41
45
|
setLoading(true);
|
|
42
46
|
setErrorKey(null);
|
|
43
47
|
setSuccessKey(null);
|
|
44
48
|
try {
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
});
|
|
48
|
-
setCodes(res.data || []);
|
|
49
|
+
const data = await fetchAccessCodes();
|
|
50
|
+
setCodes(Array.isArray(data) ? data : []);
|
|
49
51
|
} catch (err) {
|
|
50
|
-
|
|
52
|
+
setErrorFromErrorObject(err, 'Auth.ACCESS_CODE_LIST_FAILED');
|
|
51
53
|
} finally {
|
|
52
54
|
setLoading(false);
|
|
53
55
|
}
|
|
@@ -55,6 +57,7 @@ export function AccessCodeManager() {
|
|
|
55
57
|
|
|
56
58
|
useEffect(() => {
|
|
57
59
|
loadCodes();
|
|
60
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
58
61
|
}, []);
|
|
59
62
|
|
|
60
63
|
// Generates a random code with the selected length
|
|
@@ -70,15 +73,11 @@ export function AccessCodeManager() {
|
|
|
70
73
|
setErrorKey(null);
|
|
71
74
|
setSuccessKey(null);
|
|
72
75
|
try {
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
{ code },
|
|
76
|
-
{ withCredentials: true },
|
|
77
|
-
);
|
|
78
|
-
setCodes((prev) => [...prev, res.data]);
|
|
76
|
+
const created = await createAccessCode(code);
|
|
77
|
+
setCodes((prev) => [...prev, created]);
|
|
79
78
|
setSuccessKey('Auth.ACCESS_CODE_SAVE_SUCCESS');
|
|
80
79
|
} catch (err) {
|
|
81
|
-
|
|
80
|
+
setErrorFromErrorObject(err, 'Auth.ACCESS_CODE_SAVE_FAILED');
|
|
82
81
|
} finally {
|
|
83
82
|
setSubmitting(false);
|
|
84
83
|
}
|
|
@@ -102,13 +101,11 @@ export function AccessCodeManager() {
|
|
|
102
101
|
setErrorKey(null);
|
|
103
102
|
setSuccessKey(null);
|
|
104
103
|
try {
|
|
105
|
-
await
|
|
106
|
-
withCredentials: true,
|
|
107
|
-
});
|
|
104
|
+
await deleteAccessCode(id);
|
|
108
105
|
setCodes((prev) => prev.filter((c) => c.id !== id));
|
|
109
106
|
setSuccessKey('Auth.ACCESS_CODE_DELETE_SUCCESS');
|
|
110
107
|
} catch (err) {
|
|
111
|
-
|
|
108
|
+
setErrorFromErrorObject(err, 'Auth.ACCESS_CODE_DELETE_FAILED');
|
|
112
109
|
}
|
|
113
110
|
};
|
|
114
111
|
|
|
@@ -133,7 +130,7 @@ export function AccessCodeManager() {
|
|
|
133
130
|
</Alert>
|
|
134
131
|
)}
|
|
135
132
|
|
|
136
|
-
{/*
|
|
133
|
+
{/* Active codes list */}
|
|
137
134
|
<Box sx={{ mb: 3 }}>
|
|
138
135
|
<Typography variant="subtitle1" gutterBottom>
|
|
139
136
|
{t('Auth.ACCESS_CODE_SECTION_ACTIVE')}
|
|
@@ -143,11 +140,7 @@ export function AccessCodeManager() {
|
|
|
143
140
|
{t('Auth.ACCESS_CODE_NONE')}
|
|
144
141
|
</Typography>
|
|
145
142
|
) : (
|
|
146
|
-
<Stack
|
|
147
|
-
direction="row"
|
|
148
|
-
flexWrap="wrap"
|
|
149
|
-
gap={1}
|
|
150
|
-
>
|
|
143
|
+
<Stack direction="row" flexWrap="wrap" gap={1}>
|
|
151
144
|
{codes.map((code) => (
|
|
152
145
|
<Chip
|
|
153
146
|
key={code.id}
|
|
@@ -193,7 +186,7 @@ export function AccessCodeManager() {
|
|
|
193
186
|
</Button>
|
|
194
187
|
</Box>
|
|
195
188
|
|
|
196
|
-
{/*
|
|
189
|
+
{/* Manual add */}
|
|
197
190
|
<Box sx={{ mb: 2, maxWidth: 360 }}>
|
|
198
191
|
<Typography variant="subtitle1" gutterBottom>
|
|
199
192
|
{t('Auth.ACCESS_CODE_SECTION_MANUAL')}
|
|
@@ -218,4 +211,3 @@ export function AccessCodeManager() {
|
|
|
218
211
|
</Box>
|
|
219
212
|
);
|
|
220
213
|
}
|
|
221
|
-
|