mirror of
https://github.com/R0m1k3/Socialflow.git
synced 2026-10-11 17:26:45 +02:00
Add functionality to manage user permissions for social media pages
Integrate new dialogs and mutations to allow administrators to assign and update user permissions for social media pages, including fetching all pages and user-specific page permissions. Replit-Commit-Author: Agent Replit-Commit-Session-Id: ae4037a0-2a6f-4530-9bac-79b543286bda Replit-Commit-Checkpoint-Type: intermediate_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/397bca8c-984f-43ff-841a-10897aeb8140/ae4037a0-2a6f-4530-9bac-79b543286bda/u2SCNAb
This commit is contained in:
1 parent
c70da5136f
commit
a4c952872f
2 files changed
+151
-6
No files matched your search
@@ -1,4 +1,4 @@
|
||||
import { useState } from "react";
|
||||
import { useState, useEffect } from "react";
|
||||
import { useQuery, useMutation } from "@tanstack/react-query";
|
||||
import Sidebar from "@/components/sidebar";
|
||||
import TopBar from "@/components/topbar";
|
||||
@@ -11,9 +11,10 @@ import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, D
|
||||
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle } from "@/components/ui/alert-dialog";
|
||||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Checkbox } from "@/components/ui/checkbox";
|
||||
import { useToast } from "@/hooks/use-toast";
|
||||
import { apiRequest, queryClient } from "@/lib/queryClient";
|
||||
import { Users, UserPlus, Pencil, Trash2, Shield, User as UserIcon } from "lucide-react";
|
||||
import { Users, UserPlus, Pencil, Trash2, Shield, User as UserIcon, Settings } from "lucide-react";
|
||||
|
||||
type UserData = {
|
||||
id: string;
|
||||
@@ -21,6 +22,19 @@ type UserData = {
|
||||
role: "admin" | "user";
|
||||
};
|
||||
|
||||
type SocialPage = {
|
||||
id: string;
|
||||
name: string;
|
||||
platform: string;
|
||||
userId: string;
|
||||
};
|
||||
|
||||
type UserPagePermission = {
|
||||
id: string;
|
||||
userId: string;
|
||||
pageId: string;
|
||||
};
|
||||
|
||||
export default function UsersAdmin() {
|
||||
const [sidebarOpen, setSidebarOpen] = useState(false);
|
||||
const { toast } = useToast();
|
||||
@@ -41,11 +55,27 @@ export default function UsersAdmin() {
|
||||
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
||||
const [userToDelete, setUserToDelete] = useState<UserData | null>(null);
|
||||
|
||||
// Permissions dialog states
|
||||
const [permissionsDialogOpen, setPermissionsDialogOpen] = useState(false);
|
||||
const [permissionsUser, setPermissionsUser] = useState<UserData | null>(null);
|
||||
const [selectedPageIds, setSelectedPageIds] = useState<string[]>([]);
|
||||
|
||||
// Charger la liste des utilisateurs
|
||||
const { data: users, isLoading } = useQuery<UserData[]>({
|
||||
queryKey: ["/api/users"],
|
||||
});
|
||||
|
||||
// Charger toutes les pages (admin voit toutes les pages)
|
||||
const { data: allPages } = useQuery<SocialPage[]>({
|
||||
queryKey: ["/api/pages"],
|
||||
});
|
||||
|
||||
// Charger les permissions de l'utilisateur sélectionné
|
||||
const { data: userPermissions } = useQuery<UserPagePermission[]>({
|
||||
queryKey: ["/api/users", permissionsUser?.id, "page-permissions"],
|
||||
enabled: !!permissionsUser && permissionsDialogOpen,
|
||||
});
|
||||
|
||||
// Mutation pour créer un utilisateur
|
||||
const createUserMutation = useMutation({
|
||||
mutationFn: async (userData: { username: string; password: string; role: string }) => {
|
||||
@@ -119,6 +149,31 @@ export default function UsersAdmin() {
|
||||
},
|
||||
});
|
||||
|
||||
// Mutation pour mettre à jour les permissions d'un utilisateur
|
||||
const updatePermissionsMutation = useMutation({
|
||||
mutationFn: async ({ userId, pageIds }: { userId: string; pageIds: string[] }) => {
|
||||
const res = await apiRequest("POST", `/api/users/${userId}/page-permissions`, { pageIds });
|
||||
return await res.json();
|
||||
},
|
||||
onSuccess: () => {
|
||||
toast({
|
||||
title: "Permissions mises à jour",
|
||||
description: "Les permissions de l'utilisateur ont été mises à jour avec succès",
|
||||
});
|
||||
setPermissionsDialogOpen(false);
|
||||
setPermissionsUser(null);
|
||||
setSelectedPageIds([]);
|
||||
queryClient.invalidateQueries({ queryKey: ["/api/users"] });
|
||||
},
|
||||
onError: (error: any) => {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Erreur",
|
||||
description: error.message || "Erreur lors de la mise à jour des permissions",
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
|
||||
@@ -191,6 +246,37 @@ export default function UsersAdmin() {
|
||||
}
|
||||
};
|
||||
|
||||
const handlePermissionsClick = (user: UserData) => {
|
||||
setPermissionsUser(user);
|
||||
setPermissionsDialogOpen(true);
|
||||
};
|
||||
|
||||
// Mettre à jour selectedPageIds quand les permissions sont chargées
|
||||
useEffect(() => {
|
||||
if (userPermissions) {
|
||||
setSelectedPageIds(userPermissions.map(p => p.pageId));
|
||||
}
|
||||
}, [userPermissions]);
|
||||
|
||||
const handlePermissionsSubmit = () => {
|
||||
if (permissionsUser) {
|
||||
updatePermissionsMutation.mutate({
|
||||
userId: permissionsUser.id,
|
||||
pageIds: selectedPageIds,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const togglePagePermission = (pageId: string) => {
|
||||
setSelectedPageIds(prev => {
|
||||
if (prev.includes(pageId)) {
|
||||
return prev.filter(id => id !== pageId);
|
||||
} else {
|
||||
return [...prev, pageId];
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex h-screen overflow-hidden bg-background">
|
||||
{sidebarOpen && (
|
||||
@@ -264,6 +350,16 @@ export default function UsersAdmin() {
|
||||
</TableCell>
|
||||
<TableCell className="text-right">
|
||||
<div className="flex justify-end gap-2">
|
||||
{user.role === "user" && (
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => handlePermissionsClick(user)}
|
||||
data-testid={`button-permissions-user-${user.id}`}
|
||||
>
|
||||
<Settings className="w-4 h-4" />
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
@@ -447,6 +543,59 @@ export default function UsersAdmin() {
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
|
||||
{/* Dialog de gestion des permissions */}
|
||||
<Dialog open={permissionsDialogOpen} onOpenChange={setPermissionsDialogOpen}>
|
||||
<DialogContent className="max-w-2xl max-h-[80vh] overflow-y-auto">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Gérer les permissions</DialogTitle>
|
||||
<DialogDescription>
|
||||
Sélectionnez les pages auxquelles l'utilisateur <strong>{permissionsUser?.username}</strong> peut accéder
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="py-4">
|
||||
{allPages && allPages.length > 0 ? (
|
||||
<div className="space-y-3">
|
||||
{allPages.map((page) => (
|
||||
<div key={page.id} className="flex items-center space-x-2 p-3 border rounded-lg hover:bg-accent">
|
||||
<Checkbox
|
||||
id={`page-${page.id}`}
|
||||
checked={selectedPageIds.includes(page.id)}
|
||||
onCheckedChange={() => togglePagePermission(page.id)}
|
||||
data-testid={`checkbox-page-${page.id}`}
|
||||
/>
|
||||
<Label
|
||||
htmlFor={`page-${page.id}`}
|
||||
className="flex-1 cursor-pointer"
|
||||
>
|
||||
<div className="font-medium">{page.name}</div>
|
||||
<div className="text-sm text-muted-foreground">
|
||||
{page.platform === "facebook" ? "Facebook" : "Instagram"}
|
||||
</div>
|
||||
</Label>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div className="text-center py-8 text-muted-foreground">
|
||||
Aucune page disponible
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<Button variant="outline" onClick={() => setPermissionsDialogOpen(false)}>
|
||||
Annuler
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handlePermissionsSubmit}
|
||||
disabled={updatePermissionsMutation.isPending}
|
||||
data-testid="button-save-permissions"
|
||||
>
|
||||
{updatePermissionsMutation.isPending ? "Enregistrement..." : "Enregistrer"}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user