@checkstack/auth-frontend 0.5.3 → 0.5.5
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/CHANGELOG.md +33 -0
- package/package.json +1 -1
- package/src/components/ApplicationsTab.tsx +20 -15
- package/src/components/AuthSettingsPage.tsx +9 -3
- package/src/components/RolesTab.tsx +26 -21
- package/src/components/TeamAccessEditor.tsx +26 -23
- package/src/components/TeamsTab.tsx +23 -18
- package/src/components/UsersTab.tsx +17 -14
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
# @checkstack/auth-frontend
|
|
2
2
|
|
|
3
|
+
## 0.5.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 223081d: Add icon support to PageLayout and improve mobile responsiveness
|
|
8
|
+
|
|
9
|
+
**PageLayout Icons:**
|
|
10
|
+
|
|
11
|
+
- Added required `icon` prop to `PageLayout` and `PageHeader` components that accepts a Lucide icon component reference
|
|
12
|
+
- Icons are rendered with consistent `h-6 w-6 text-primary` styling
|
|
13
|
+
- Updated all page components to include appropriate icons in their headers
|
|
14
|
+
|
|
15
|
+
**Mobile Layout Improvements:**
|
|
16
|
+
|
|
17
|
+
- Standardized responsive padding in main app shell (`p-3` on mobile, `p-6` on desktop)
|
|
18
|
+
- Added `CardHeaderRow` component for mobile-safe card headers with proper wrapping
|
|
19
|
+
- Improved `DateRangeFilter` responsive behavior with vertical stacking on mobile
|
|
20
|
+
- Migrated pages to use `PageLayout` for consistent responsive behavior
|
|
21
|
+
|
|
22
|
+
- Updated dependencies [223081d]
|
|
23
|
+
- @checkstack/ui@0.5.0
|
|
24
|
+
|
|
25
|
+
## 0.5.4
|
|
26
|
+
|
|
27
|
+
### Patch Changes
|
|
28
|
+
|
|
29
|
+
- Updated dependencies [db1f56f]
|
|
30
|
+
- Updated dependencies [538e45d]
|
|
31
|
+
- @checkstack/common@0.6.0
|
|
32
|
+
- @checkstack/ui@0.4.1
|
|
33
|
+
- @checkstack/auth-common@0.5.3
|
|
34
|
+
- @checkstack/frontend-api@0.3.3
|
|
35
|
+
|
|
3
36
|
## 0.5.3
|
|
4
37
|
|
|
5
38
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -2,6 +2,7 @@ import React, { useState } from "react";
|
|
|
2
2
|
import {
|
|
3
3
|
Card,
|
|
4
4
|
CardHeader,
|
|
5
|
+
CardHeaderRow,
|
|
5
6
|
CardTitle,
|
|
6
7
|
CardContent,
|
|
7
8
|
Table,
|
|
@@ -70,7 +71,7 @@ export const ApplicationsTab: React.FC<ApplicationsTabProps> = ({
|
|
|
70
71
|
refetch: refetchApplications,
|
|
71
72
|
} = authClient.getApplications.useQuery(
|
|
72
73
|
{},
|
|
73
|
-
{ enabled: canManageApplications }
|
|
74
|
+
{ enabled: canManageApplications },
|
|
74
75
|
);
|
|
75
76
|
|
|
76
77
|
// Mutations
|
|
@@ -88,7 +89,7 @@ export const ApplicationsTab: React.FC<ApplicationsTabProps> = ({
|
|
|
88
89
|
},
|
|
89
90
|
onError: (error) => {
|
|
90
91
|
toast.error(
|
|
91
|
-
error instanceof Error ? error.message : "Failed to create application"
|
|
92
|
+
error instanceof Error ? error.message : "Failed to create application",
|
|
92
93
|
);
|
|
93
94
|
},
|
|
94
95
|
});
|
|
@@ -99,7 +100,7 @@ export const ApplicationsTab: React.FC<ApplicationsTabProps> = ({
|
|
|
99
100
|
},
|
|
100
101
|
onError: (error) => {
|
|
101
102
|
toast.error(
|
|
102
|
-
error instanceof Error ? error.message : "Failed to update application"
|
|
103
|
+
error instanceof Error ? error.message : "Failed to update application",
|
|
103
104
|
);
|
|
104
105
|
},
|
|
105
106
|
});
|
|
@@ -112,7 +113,7 @@ export const ApplicationsTab: React.FC<ApplicationsTabProps> = ({
|
|
|
112
113
|
},
|
|
113
114
|
onError: (error) => {
|
|
114
115
|
toast.error(
|
|
115
|
-
error instanceof Error ? error.message : "Failed to delete application"
|
|
116
|
+
error instanceof Error ? error.message : "Failed to delete application",
|
|
116
117
|
);
|
|
117
118
|
},
|
|
118
119
|
});
|
|
@@ -129,7 +130,9 @@ export const ApplicationsTab: React.FC<ApplicationsTabProps> = ({
|
|
|
129
130
|
},
|
|
130
131
|
onError: (error) => {
|
|
131
132
|
toast.error(
|
|
132
|
-
error instanceof Error
|
|
133
|
+
error instanceof Error
|
|
134
|
+
? error.message
|
|
135
|
+
: "Failed to regenerate secret",
|
|
133
136
|
);
|
|
134
137
|
},
|
|
135
138
|
});
|
|
@@ -148,7 +151,7 @@ export const ApplicationsTab: React.FC<ApplicationsTabProps> = ({
|
|
|
148
151
|
const handleToggleApplicationRole = (
|
|
149
152
|
appId: string,
|
|
150
153
|
roleId: string,
|
|
151
|
-
currentRoles: string[]
|
|
154
|
+
currentRoles: string[],
|
|
152
155
|
) => {
|
|
153
156
|
const newRoles = currentRoles.includes(roleId)
|
|
154
157
|
? currentRoles.filter((r) => r !== roleId)
|
|
@@ -173,14 +176,16 @@ export const ApplicationsTab: React.FC<ApplicationsTabProps> = ({
|
|
|
173
176
|
return (
|
|
174
177
|
<>
|
|
175
178
|
<Card>
|
|
176
|
-
<CardHeader
|
|
177
|
-
<
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
<
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
179
|
+
<CardHeader>
|
|
180
|
+
<CardHeaderRow>
|
|
181
|
+
<CardTitle>External Applications</CardTitle>
|
|
182
|
+
{canManageApplications && (
|
|
183
|
+
<Button onClick={() => setCreateAppDialogOpen(true)} size="sm">
|
|
184
|
+
<Plus className="h-4 w-4 mr-2" />
|
|
185
|
+
Create Application
|
|
186
|
+
</Button>
|
|
187
|
+
)}
|
|
188
|
+
</CardHeaderRow>
|
|
184
189
|
</CardHeader>
|
|
185
190
|
<CardContent>
|
|
186
191
|
<Alert variant="info" className="mb-4">
|
|
@@ -242,7 +247,7 @@ export const ApplicationsTab: React.FC<ApplicationsTabProps> = ({
|
|
|
242
247
|
handleToggleApplicationRole(
|
|
243
248
|
app.id,
|
|
244
249
|
role.id,
|
|
245
|
-
app.roles
|
|
250
|
+
app.roles,
|
|
246
251
|
)
|
|
247
252
|
}
|
|
248
253
|
/>
|
|
@@ -44,7 +44,7 @@ export const AuthSettingsPage: React.FC = () => {
|
|
|
44
44
|
["users", "roles", "teams", "strategies", "applications"].includes(tab)
|
|
45
45
|
) {
|
|
46
46
|
setActiveTab(
|
|
47
|
-
tab as "users" | "roles" | "teams" | "strategies" | "applications"
|
|
47
|
+
tab as "users" | "roles" | "teams" | "strategies" | "applications",
|
|
48
48
|
);
|
|
49
49
|
}
|
|
50
50
|
|
|
@@ -94,7 +94,7 @@ export const AuthSettingsPage: React.FC = () => {
|
|
|
94
94
|
refetch: refetchStrategies,
|
|
95
95
|
} = authClient.getStrategies.useQuery(
|
|
96
96
|
{},
|
|
97
|
-
{ enabled: canManageStrategies.allowed }
|
|
97
|
+
{ enabled: canManageStrategies.allowed },
|
|
98
98
|
);
|
|
99
99
|
|
|
100
100
|
const dataLoading =
|
|
@@ -191,6 +191,7 @@ export const AuthSettingsPage: React.FC = () => {
|
|
|
191
191
|
return (
|
|
192
192
|
<PageLayout
|
|
193
193
|
title="Authentication Settings"
|
|
194
|
+
icon={Shield}
|
|
194
195
|
loading={accessRulesLoading}
|
|
195
196
|
allowed={isAllowed}
|
|
196
197
|
>
|
|
@@ -199,7 +200,12 @@ export const AuthSettingsPage: React.FC = () => {
|
|
|
199
200
|
activeTab={activeTab}
|
|
200
201
|
onTabChange={(tabId) =>
|
|
201
202
|
setActiveTab(
|
|
202
|
-
tabId as
|
|
203
|
+
tabId as
|
|
204
|
+
| "users"
|
|
205
|
+
| "roles"
|
|
206
|
+
| "teams"
|
|
207
|
+
| "strategies"
|
|
208
|
+
| "applications",
|
|
203
209
|
)
|
|
204
210
|
}
|
|
205
211
|
className="mb-6"
|
|
@@ -2,6 +2,7 @@ import React, { useState } from "react";
|
|
|
2
2
|
import {
|
|
3
3
|
Card,
|
|
4
4
|
CardHeader,
|
|
5
|
+
CardHeaderRow,
|
|
5
6
|
CardTitle,
|
|
6
7
|
CardContent,
|
|
7
8
|
Table,
|
|
@@ -57,7 +58,7 @@ export const RolesTab: React.FC<RolesTabProps> = ({
|
|
|
57
58
|
},
|
|
58
59
|
onError: (error) => {
|
|
59
60
|
toast.error(
|
|
60
|
-
error instanceof Error ? error.message : "Failed to create role"
|
|
61
|
+
error instanceof Error ? error.message : "Failed to create role",
|
|
61
62
|
);
|
|
62
63
|
},
|
|
63
64
|
});
|
|
@@ -69,7 +70,7 @@ export const RolesTab: React.FC<RolesTabProps> = ({
|
|
|
69
70
|
},
|
|
70
71
|
onError: (error) => {
|
|
71
72
|
toast.error(
|
|
72
|
-
error instanceof Error ? error.message : "Failed to update role"
|
|
73
|
+
error instanceof Error ? error.message : "Failed to update role",
|
|
73
74
|
);
|
|
74
75
|
},
|
|
75
76
|
});
|
|
@@ -82,7 +83,7 @@ export const RolesTab: React.FC<RolesTabProps> = ({
|
|
|
82
83
|
},
|
|
83
84
|
onError: (error) => {
|
|
84
85
|
toast.error(
|
|
85
|
-
error instanceof Error ? error.message : "Failed to delete role"
|
|
86
|
+
error instanceof Error ? error.message : "Failed to delete role",
|
|
86
87
|
);
|
|
87
88
|
},
|
|
88
89
|
});
|
|
@@ -103,16 +104,18 @@ export const RolesTab: React.FC<RolesTabProps> = ({
|
|
|
103
104
|
description?: string;
|
|
104
105
|
accessRules: string[];
|
|
105
106
|
}) => {
|
|
106
|
-
await (params.id
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
107
|
+
await (params.id
|
|
108
|
+
? updateRoleMutation.mutateAsync({
|
|
109
|
+
id: params.id,
|
|
110
|
+
name: params.name,
|
|
111
|
+
description: params.description,
|
|
112
|
+
accessRules: params.accessRules,
|
|
113
|
+
})
|
|
114
|
+
: createRoleMutation.mutateAsync({
|
|
115
|
+
name: params.name,
|
|
116
|
+
description: params.description,
|
|
117
|
+
accessRules: params.accessRules,
|
|
118
|
+
}));
|
|
116
119
|
};
|
|
117
120
|
|
|
118
121
|
const handleDeleteRole = () => {
|
|
@@ -123,14 +126,16 @@ export const RolesTab: React.FC<RolesTabProps> = ({
|
|
|
123
126
|
return (
|
|
124
127
|
<>
|
|
125
128
|
<Card>
|
|
126
|
-
<CardHeader
|
|
127
|
-
<
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
<
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
129
|
+
<CardHeader>
|
|
130
|
+
<CardHeaderRow>
|
|
131
|
+
<CardTitle>Role Management</CardTitle>
|
|
132
|
+
{canCreateRoles && (
|
|
133
|
+
<Button onClick={handleCreateRole} size="sm">
|
|
134
|
+
<Plus className="h-4 w-4 mr-2" />
|
|
135
|
+
Create Role
|
|
136
|
+
</Button>
|
|
137
|
+
)}
|
|
138
|
+
</CardHeaderRow>
|
|
134
139
|
</CardHeader>
|
|
135
140
|
<CardContent>
|
|
136
141
|
{canReadRoles ? (
|
|
@@ -2,6 +2,7 @@ import React, { useState, useEffect } from "react";
|
|
|
2
2
|
import {
|
|
3
3
|
Card,
|
|
4
4
|
CardHeader,
|
|
5
|
+
CardHeaderRow,
|
|
5
6
|
CardTitle,
|
|
6
7
|
CardContent,
|
|
7
8
|
Button,
|
|
@@ -77,7 +78,7 @@ export const TeamAccessEditor: React.FC<TeamAccessEditorProps> = ({
|
|
|
77
78
|
const toast = useToast();
|
|
78
79
|
|
|
79
80
|
const { allowed: canManageTeams } = accessApi.useAccess(
|
|
80
|
-
authAccess.teams.manage
|
|
81
|
+
authAccess.teams.manage,
|
|
81
82
|
);
|
|
82
83
|
|
|
83
84
|
const [expanded, setExpanded] = useState(initialExpanded);
|
|
@@ -90,7 +91,7 @@ export const TeamAccessEditor: React.FC<TeamAccessEditorProps> = ({
|
|
|
90
91
|
refetch: refetchAccess,
|
|
91
92
|
} = authClient.getResourceTeamAccess.useQuery(
|
|
92
93
|
{ resourceType, resourceId },
|
|
93
|
-
{ enabled: expanded && !!resourceId }
|
|
94
|
+
{ enabled: expanded && !!resourceId },
|
|
94
95
|
);
|
|
95
96
|
|
|
96
97
|
// Query: All teams
|
|
@@ -104,7 +105,7 @@ export const TeamAccessEditor: React.FC<TeamAccessEditorProps> = ({
|
|
|
104
105
|
refetch: refetchSettings,
|
|
105
106
|
} = authClient.getResourceAccessSettings.useQuery(
|
|
106
107
|
{ resourceType, resourceId },
|
|
107
|
-
{ enabled: expanded && !!resourceId }
|
|
108
|
+
{ enabled: expanded && !!resourceId },
|
|
108
109
|
);
|
|
109
110
|
|
|
110
111
|
const loading = accessLoading || teamsLoading || settingsLoading;
|
|
@@ -120,7 +121,7 @@ export const TeamAccessEditor: React.FC<TeamAccessEditorProps> = ({
|
|
|
120
121
|
},
|
|
121
122
|
onError: (error) => {
|
|
122
123
|
toast.error(
|
|
123
|
-
error instanceof Error ? error.message : "Failed to update access"
|
|
124
|
+
error instanceof Error ? error.message : "Failed to update access",
|
|
124
125
|
);
|
|
125
126
|
},
|
|
126
127
|
});
|
|
@@ -133,7 +134,7 @@ export const TeamAccessEditor: React.FC<TeamAccessEditorProps> = ({
|
|
|
133
134
|
},
|
|
134
135
|
onError: (error) => {
|
|
135
136
|
toast.error(
|
|
136
|
-
error instanceof Error ? error.message : "Failed to remove access"
|
|
137
|
+
error instanceof Error ? error.message : "Failed to remove access",
|
|
137
138
|
);
|
|
138
139
|
},
|
|
139
140
|
});
|
|
@@ -145,7 +146,7 @@ export const TeamAccessEditor: React.FC<TeamAccessEditorProps> = ({
|
|
|
145
146
|
},
|
|
146
147
|
onError: (error) => {
|
|
147
148
|
toast.error(
|
|
148
|
-
error instanceof Error ? error.message : "Failed to update settings"
|
|
149
|
+
error instanceof Error ? error.message : "Failed to update settings",
|
|
149
150
|
);
|
|
150
151
|
},
|
|
151
152
|
});
|
|
@@ -168,10 +169,10 @@ export const TeamAccessEditor: React.FC<TeamAccessEditorProps> = ({
|
|
|
168
169
|
|
|
169
170
|
const handleUpdateAccess = (
|
|
170
171
|
teamId: string,
|
|
171
|
-
updates: { canRead?: boolean; canManage?: boolean }
|
|
172
|
+
updates: { canRead?: boolean; canManage?: boolean },
|
|
172
173
|
) => {
|
|
173
174
|
const currentAccess = (accessList as TeamAccess[]).find(
|
|
174
|
-
(a) => a.teamId === teamId
|
|
175
|
+
(a) => a.teamId === teamId,
|
|
175
176
|
);
|
|
176
177
|
setAccessMutation.mutate({
|
|
177
178
|
resourceType,
|
|
@@ -199,7 +200,7 @@ export const TeamAccessEditor: React.FC<TeamAccessEditorProps> = ({
|
|
|
199
200
|
|
|
200
201
|
// Check if this was the last team - if so, reset teamOnly
|
|
201
202
|
const remainingTeams = (accessList as TeamAccess[]).filter(
|
|
202
|
-
(a) => a.teamId !== teamId
|
|
203
|
+
(a) => a.teamId !== teamId,
|
|
203
204
|
);
|
|
204
205
|
if (remainingTeams.length === 0 && teamOnly) {
|
|
205
206
|
setSettingsMutation.mutate({
|
|
@@ -213,7 +214,7 @@ export const TeamAccessEditor: React.FC<TeamAccessEditorProps> = ({
|
|
|
213
214
|
// Get teams that don't already have access
|
|
214
215
|
const typedAccessList = accessList as TeamAccess[];
|
|
215
216
|
const availableTeams = (teams as Team[]).filter(
|
|
216
|
-
(t) => !typedAccessList.some((a) => a.teamId === t.id)
|
|
217
|
+
(t) => !typedAccessList.some((a) => a.teamId === t.id),
|
|
217
218
|
);
|
|
218
219
|
|
|
219
220
|
const adding = setAccessMutation.isPending;
|
|
@@ -412,19 +413,21 @@ export const TeamAccessEditor: React.FC<TeamAccessEditorProps> = ({
|
|
|
412
413
|
// Card mode (default)
|
|
413
414
|
return (
|
|
414
415
|
<Card>
|
|
415
|
-
<CardHeader
|
|
416
|
-
<
|
|
417
|
-
<
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
416
|
+
<CardHeader>
|
|
417
|
+
<CardHeaderRow>
|
|
418
|
+
<CardTitle className="text-base flex items-center gap-2">
|
|
419
|
+
<Shield className="h-4 w-4" />
|
|
420
|
+
Team Access Control
|
|
421
|
+
</CardTitle>
|
|
422
|
+
<Button
|
|
423
|
+
type="button"
|
|
424
|
+
variant="ghost"
|
|
425
|
+
size="sm"
|
|
426
|
+
onClick={() => setExpanded(false)}
|
|
427
|
+
>
|
|
428
|
+
Collapse
|
|
429
|
+
</Button>
|
|
430
|
+
</CardHeaderRow>
|
|
428
431
|
</CardHeader>
|
|
429
432
|
<CardContent className="space-y-4">
|
|
430
433
|
{loading ? (
|
|
@@ -2,6 +2,7 @@ import React, { useState, useEffect } from "react";
|
|
|
2
2
|
import {
|
|
3
3
|
Card,
|
|
4
4
|
CardHeader,
|
|
5
|
+
CardHeaderRow,
|
|
5
6
|
CardTitle,
|
|
6
7
|
CardContent,
|
|
7
8
|
Table,
|
|
@@ -102,7 +103,7 @@ export const TeamsTab: React.FC<TeamsTabProps> = ({
|
|
|
102
103
|
refetch: refetchTeamDetail,
|
|
103
104
|
} = authClient.getTeam.useQuery(
|
|
104
105
|
{ teamId: selectedTeamId ?? "" },
|
|
105
|
-
{ enabled: !!selectedTeamId && membersDialogOpen }
|
|
106
|
+
{ enabled: !!selectedTeamId && membersDialogOpen },
|
|
106
107
|
);
|
|
107
108
|
|
|
108
109
|
// Mutations
|
|
@@ -115,7 +116,7 @@ export const TeamsTab: React.FC<TeamsTabProps> = ({
|
|
|
115
116
|
},
|
|
116
117
|
onError: (error) => {
|
|
117
118
|
toast.error(
|
|
118
|
-
error instanceof Error ? error.message : "Failed to create team"
|
|
119
|
+
error instanceof Error ? error.message : "Failed to create team",
|
|
119
120
|
);
|
|
120
121
|
},
|
|
121
122
|
});
|
|
@@ -129,7 +130,7 @@ export const TeamsTab: React.FC<TeamsTabProps> = ({
|
|
|
129
130
|
},
|
|
130
131
|
onError: (error) => {
|
|
131
132
|
toast.error(
|
|
132
|
-
error instanceof Error ? error.message : "Failed to update team"
|
|
133
|
+
error instanceof Error ? error.message : "Failed to update team",
|
|
133
134
|
);
|
|
134
135
|
},
|
|
135
136
|
});
|
|
@@ -143,7 +144,7 @@ export const TeamsTab: React.FC<TeamsTabProps> = ({
|
|
|
143
144
|
},
|
|
144
145
|
onError: (error) => {
|
|
145
146
|
toast.error(
|
|
146
|
-
error instanceof Error ? error.message : "Failed to delete team"
|
|
147
|
+
error instanceof Error ? error.message : "Failed to delete team",
|
|
147
148
|
);
|
|
148
149
|
},
|
|
149
150
|
});
|
|
@@ -157,7 +158,7 @@ export const TeamsTab: React.FC<TeamsTabProps> = ({
|
|
|
157
158
|
},
|
|
158
159
|
onError: (error) => {
|
|
159
160
|
toast.error(
|
|
160
|
-
error instanceof Error ? error.message : "Failed to add member"
|
|
161
|
+
error instanceof Error ? error.message : "Failed to add member",
|
|
161
162
|
);
|
|
162
163
|
},
|
|
163
164
|
});
|
|
@@ -170,7 +171,7 @@ export const TeamsTab: React.FC<TeamsTabProps> = ({
|
|
|
170
171
|
},
|
|
171
172
|
onError: (error) => {
|
|
172
173
|
toast.error(
|
|
173
|
-
error instanceof Error ? error.message : "Failed to remove member"
|
|
174
|
+
error instanceof Error ? error.message : "Failed to remove member",
|
|
174
175
|
);
|
|
175
176
|
},
|
|
176
177
|
});
|
|
@@ -182,7 +183,7 @@ export const TeamsTab: React.FC<TeamsTabProps> = ({
|
|
|
182
183
|
},
|
|
183
184
|
onError: (error) => {
|
|
184
185
|
toast.error(
|
|
185
|
-
error instanceof Error ? error.message : "Failed to promote to manager"
|
|
186
|
+
error instanceof Error ? error.message : "Failed to promote to manager",
|
|
186
187
|
);
|
|
187
188
|
},
|
|
188
189
|
});
|
|
@@ -194,7 +195,9 @@ export const TeamsTab: React.FC<TeamsTabProps> = ({
|
|
|
194
195
|
},
|
|
195
196
|
onError: (error) => {
|
|
196
197
|
toast.error(
|
|
197
|
-
error instanceof Error
|
|
198
|
+
error instanceof Error
|
|
199
|
+
? error.message
|
|
200
|
+
: "Failed to remove manager role",
|
|
198
201
|
);
|
|
199
202
|
},
|
|
200
203
|
});
|
|
@@ -304,14 +307,16 @@ export const TeamsTab: React.FC<TeamsTabProps> = ({
|
|
|
304
307
|
return (
|
|
305
308
|
<>
|
|
306
309
|
<Card>
|
|
307
|
-
<CardHeader
|
|
308
|
-
<
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
<
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
310
|
+
<CardHeader>
|
|
311
|
+
<CardHeaderRow>
|
|
312
|
+
<CardTitle>Team Management</CardTitle>
|
|
313
|
+
{canManageTeams && (
|
|
314
|
+
<Button onClick={handleCreateTeam} size="sm">
|
|
315
|
+
<Plus className="h-4 w-4 mr-2" />
|
|
316
|
+
Create Team
|
|
317
|
+
</Button>
|
|
318
|
+
)}
|
|
319
|
+
</CardHeaderRow>
|
|
315
320
|
</CardHeader>
|
|
316
321
|
<CardContent>
|
|
317
322
|
{canReadTeams ? (
|
|
@@ -463,7 +468,7 @@ export const TeamsTab: React.FC<TeamsTabProps> = ({
|
|
|
463
468
|
<div className="space-y-4">
|
|
464
469
|
{/* Add Member Form */}
|
|
465
470
|
{(teamDetailData.managers.some((m) =>
|
|
466
|
-
users.some((u) => u.id === m.id)
|
|
471
|
+
users.some((u) => u.id === m.id),
|
|
467
472
|
) ||
|
|
468
473
|
canManageTeams) && (
|
|
469
474
|
<div className="flex gap-2">
|
|
@@ -508,7 +513,7 @@ export const TeamsTab: React.FC<TeamsTabProps> = ({
|
|
|
508
513
|
) : (
|
|
509
514
|
teamDetailData.members.map((member) => {
|
|
510
515
|
const isManager = teamDetailData.managers.some(
|
|
511
|
-
(m) => m.id === member.id
|
|
516
|
+
(m) => m.id === member.id,
|
|
512
517
|
);
|
|
513
518
|
return (
|
|
514
519
|
<div
|
|
@@ -2,6 +2,7 @@ import React, { useState } from "react";
|
|
|
2
2
|
import {
|
|
3
3
|
Card,
|
|
4
4
|
CardHeader,
|
|
5
|
+
CardHeaderRow,
|
|
5
6
|
CardTitle,
|
|
6
7
|
CardContent,
|
|
7
8
|
Table,
|
|
@@ -53,7 +54,7 @@ export const UsersTab: React.FC<UsersTabProps> = ({
|
|
|
53
54
|
const [createUserDialogOpen, setCreateUserDialogOpen] = useState(false);
|
|
54
55
|
|
|
55
56
|
const hasCredentialStrategy = strategies.some(
|
|
56
|
-
(s) => s.id === "credential" && s.enabled
|
|
57
|
+
(s) => s.id === "credential" && s.enabled,
|
|
57
58
|
);
|
|
58
59
|
|
|
59
60
|
// Mutations
|
|
@@ -65,7 +66,7 @@ export const UsersTab: React.FC<UsersTabProps> = ({
|
|
|
65
66
|
},
|
|
66
67
|
onError: (error) => {
|
|
67
68
|
toast.error(
|
|
68
|
-
error instanceof Error ? error.message : "Failed to delete user"
|
|
69
|
+
error instanceof Error ? error.message : "Failed to delete user",
|
|
69
70
|
);
|
|
70
71
|
},
|
|
71
72
|
});
|
|
@@ -76,7 +77,7 @@ export const UsersTab: React.FC<UsersTabProps> = ({
|
|
|
76
77
|
},
|
|
77
78
|
onError: (error) => {
|
|
78
79
|
toast.error(
|
|
79
|
-
error instanceof Error ? error.message : "Failed to update roles"
|
|
80
|
+
error instanceof Error ? error.message : "Failed to update roles",
|
|
80
81
|
);
|
|
81
82
|
},
|
|
82
83
|
});
|
|
@@ -88,7 +89,7 @@ export const UsersTab: React.FC<UsersTabProps> = ({
|
|
|
88
89
|
},
|
|
89
90
|
onError: (error) => {
|
|
90
91
|
toast.error(
|
|
91
|
-
error instanceof Error ? error.message : "Failed to create user"
|
|
92
|
+
error instanceof Error ? error.message : "Failed to create user",
|
|
92
93
|
);
|
|
93
94
|
throw error;
|
|
94
95
|
},
|
|
@@ -102,7 +103,7 @@ export const UsersTab: React.FC<UsersTabProps> = ({
|
|
|
102
103
|
const handleToggleRole = (
|
|
103
104
|
userId: string,
|
|
104
105
|
roleId: string,
|
|
105
|
-
currentRoles: string[]
|
|
106
|
+
currentRoles: string[],
|
|
106
107
|
) => {
|
|
107
108
|
if (currentUserId === userId) {
|
|
108
109
|
toast.error("You cannot update your own roles");
|
|
@@ -127,14 +128,16 @@ export const UsersTab: React.FC<UsersTabProps> = ({
|
|
|
127
128
|
return (
|
|
128
129
|
<>
|
|
129
130
|
<Card>
|
|
130
|
-
<CardHeader
|
|
131
|
-
<
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
<
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
131
|
+
<CardHeader>
|
|
132
|
+
<CardHeaderRow>
|
|
133
|
+
<CardTitle>User Management</CardTitle>
|
|
134
|
+
{canCreateUsers && hasCredentialStrategy && (
|
|
135
|
+
<Button onClick={() => setCreateUserDialogOpen(true)} size="sm">
|
|
136
|
+
<Plus className="h-4 w-4 mr-2" />
|
|
137
|
+
Create User
|
|
138
|
+
</Button>
|
|
139
|
+
)}
|
|
140
|
+
</CardHeaderRow>
|
|
138
141
|
</CardHeader>
|
|
139
142
|
<CardContent>
|
|
140
143
|
<Alert variant="info" className="mb-4">
|
|
@@ -188,7 +191,7 @@ export const UsersTab: React.FC<UsersTabProps> = ({
|
|
|
188
191
|
handleToggleRole(
|
|
189
192
|
user.id,
|
|
190
193
|
role.id,
|
|
191
|
-
user.roles
|
|
194
|
+
user.roles,
|
|
192
195
|
)
|
|
193
196
|
}
|
|
194
197
|
/>
|