From 39080cea83e6b1da43d5ee24edae34f6ffc3dfb0 Mon Sep 17 00:00:00 2001
From: alphaeusmote <41258468-alphaeusmote@users.noreply.replit.com>
Date: Wed, 9 Apr 2025 03:26:53 +0000
Subject: [PATCH] Enhance LDAP query builder with drag-and-drop functionality
for filter groups.
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 705f2157-ef97-4fbd-89e4-8c7f2ecaea90
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/7ed01c5f-a82d-405a-b728-b2e3d127c60c/734add71-6306-4281-af3d-a32d5349dd4c.jpg
---
client/src/pages/ldap-query-builder-page.tsx | 1167 +++++++-------
.../src/pages/ldap-query-builder-page.tsx.bak | 1362 +++++++++++++++++
package-lock.json | 56 +
package.json | 3 +
4 files changed, 2061 insertions(+), 527 deletions(-)
create mode 100644 client/src/pages/ldap-query-builder-page.tsx.bak
diff --git a/client/src/pages/ldap-query-builder-page.tsx b/client/src/pages/ldap-query-builder-page.tsx
index b89c21c..73714d9 100644
--- a/client/src/pages/ldap-query-builder-page.tsx
+++ b/client/src/pages/ldap-query-builder-page.tsx
@@ -10,8 +10,27 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@
import { useQuery, useMutation } from "@tanstack/react-query";
import { queryClient, apiRequest } from "@/lib/queryClient";
import { useToast } from "@/hooks/use-toast";
-import { Loader2, Save, Trash, History, ArrowLeftRight, RefreshCw, Play, Plus, FolderPlus, X } from "lucide-react";
+import { Loader2, Save, Trash, History, ArrowLeftRight, RefreshCw, Play, Plus, FolderPlus, X, Copy, GripVertical } from "lucide-react";
import { useAuth } from "@/hooks/use-auth";
+
+// Drag and drop imports
+import {
+ DndContext,
+ closestCenter,
+ KeyboardSensor,
+ PointerSensor,
+ useSensor,
+ useSensors,
+ DragEndEvent
+} from '@dnd-kit/core';
+import {
+ arrayMove,
+ SortableContext,
+ sortableKeyboardCoordinates,
+ useSortable,
+ verticalListSortingStrategy
+} from '@dnd-kit/sortable';
+import { CSS } from '@dnd-kit/utilities';
import {
Dialog,
DialogContent,
@@ -61,6 +80,238 @@ type LdapFilterRevision = {
modifiedAt: string;
};
+// Sortable Group component for drag-and-drop
+interface SortableGroupProps {
+ id: string;
+ group: any;
+ groupIndex: number;
+ filterBuilder: any;
+ setFilterBuilder: (value: any) => void;
+ ldapAttributes: string[];
+ isLoadingAttributes: boolean;
+}
+
+const SortableGroup = ({
+ id,
+ group,
+ groupIndex,
+ filterBuilder,
+ setFilterBuilder,
+ ldapAttributes,
+ isLoadingAttributes
+}: SortableGroupProps) => {
+ const {
+ attributes,
+ listeners,
+ setNodeRef,
+ transform,
+ transition,
+ isDragging
+ } = useSortable({ id });
+
+ const style = {
+ transform: CSS.Transform.toString(transform),
+ transition,
+ zIndex: isDragging ? 1 : 0,
+ opacity: isDragging ? 0.5 : 1
+ };
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {group.conditions.map((condition: any, condIndex: number) => (
+
+
+ {ldapAttributes.length > 0 ? (
+
+ ) : (
+ {
+ const updatedGroups = [...filterBuilder.groups];
+ updatedGroups[groupIndex].conditions[condIndex].attribute = e.target.value;
+ setFilterBuilder({
+ ...filterBuilder,
+ groups: updatedGroups
+ });
+ }}
+ />
+ )}
+ {condition.attribute === "custom" && (
+ {
+ const updatedGroups = [...filterBuilder.groups];
+ updatedGroups[groupIndex].conditions[condIndex].attribute = e.target.value;
+ setFilterBuilder({
+ ...filterBuilder,
+ groups: updatedGroups
+ });
+ }}
+ />
+ )}
+
+
+
+
+
+ {
+ const updatedGroups = [...filterBuilder.groups];
+ updatedGroups[groupIndex].conditions[condIndex].value = e.target.value;
+ setFilterBuilder({
+ ...filterBuilder,
+ groups: updatedGroups
+ });
+ }}
+ />
+
+
+
+
+
+ ))}
+
+
+
+
+ );
+};
+
const LdapQueryBuilderPage = () => {
const { user } = useAuth();
const { toast } = useToast();
@@ -81,6 +332,48 @@ const LdapQueryBuilderPage = () => {
operator: "and",
groups: []
});
+
+ // Set up sensors for drag and drop
+ const sensors = useSensors(
+ useSensor(PointerSensor, {
+ activationConstraint: {
+ distance: 8,
+ },
+ }),
+ useSensor(KeyboardSensor, {
+ coordinateGetter: sortableKeyboardCoordinates,
+ })
+ );
+
+ // Handle drag end event for group reordering
+ const handleDragEnd = (event: DragEndEvent) => {
+ const { active, over } = event;
+
+ if (over && active.id !== over.id) {
+ const activeId = active.id.toString();
+ const overId = over.id.toString();
+
+ const activeIndex = filterBuilder.groups.findIndex(
+ (_: any, i: number) => `group-${i}` === activeId
+ );
+ const overIndex = filterBuilder.groups.findIndex(
+ (_: any, i: number) => `group-${i}` === overId
+ );
+
+ if (activeIndex !== -1 && overIndex !== -1) {
+ const newGroups = arrayMove(
+ filterBuilder.groups,
+ activeIndex,
+ overIndex
+ );
+
+ setFilterBuilder({
+ ...filterBuilder,
+ groups: newGroups
+ });
+ }
+ }
+ };
// Query to get LDAP connections
const {
@@ -263,9 +556,7 @@ const LdapQueryBuilderPage = () => {
: filter.filter;
// Make sure it has valid structure
- if (filterData &&
- filterData.operator &&
- Array.isArray(filterData.conditions)) {
+ if (filterData && filterData.operator) {
setFilterBuilder(filterData);
}
} catch (err) {
@@ -483,59 +774,42 @@ const LdapQueryBuilderPage = () => {
- Date
+ Version
Modified By
+ Date
LDAP Filter
- Actions
+
- {revisions && revisions.length > 0 ? (
- revisions.map((rev: LdapFilterRevision) => (
-
-
- {new Date(rev.modifiedAt).toLocaleString()}
-
- User ID: {rev.modifiedBy}
-
-
- {rev.ldapFilter}
-
-
-
-
-
-
- ))
- ) : (
-
-
- No revision history found
+ {revisions.map((rev: LdapFilterRevision) => (
+
+ v{rev.id}
+ User #{rev.modifiedBy}
+ {new Date(rev.modifiedAt).toLocaleString()}
+ {rev.ldapFilter}
+
+
- )}
+ ))}
)}
-
+
-
@@ -548,49 +822,44 @@ const LdapQueryBuilderPage = () => {
const renderTestResultsDialog = () => {
return (