forked from baron/baron-sso
fix(adminfront): prevent bulk import modal from unmounting when dropdown closes
Lifted the modal state out of the DropdownMenuContent to ensure the dialog does not unmount immediately when the dropdown item is clicked.
This commit is contained in:
@@ -146,6 +146,7 @@ function UserListPage() {
|
|||||||
React.useState("");
|
React.useState("");
|
||||||
const [sortConfig, setSortConfig] =
|
const [sortConfig, setSortConfig] =
|
||||||
React.useState<SortConfig<UserSortKey> | null>(null);
|
React.useState<SortConfig<UserSortKey> | null>(null);
|
||||||
|
const [bulkUploadOpen, setBulkUploadOpen] = React.useState(false);
|
||||||
|
|
||||||
const limit = 1000;
|
const limit = 1000;
|
||||||
const offset = (page - 1) * limit;
|
const offset = (page - 1) * limit;
|
||||||
@@ -513,10 +514,16 @@ function UserListPage() {
|
|||||||
{t("ui.admin.users.csv_template", "템플릿 다운로드")}
|
{t("ui.admin.users.csv_template", "템플릿 다운로드")}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
<UserBulkUploadModal
|
<DropdownMenuItem
|
||||||
variant="dropdown"
|
onSelect={(e) => {
|
||||||
onSuccess={() => query.refetch()}
|
e.preventDefault();
|
||||||
/>
|
setBulkUploadOpen(true);
|
||||||
|
}}
|
||||||
|
className="cursor-pointer"
|
||||||
|
>
|
||||||
|
<Upload size={16} className="mr-2 opacity-50" />
|
||||||
|
{t("ui.admin.users.list.bulk_import", "일괄 등록 (CSV)")}
|
||||||
|
</DropdownMenuItem>
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
onClick={() => handleExport(false)}
|
onClick={() => handleExport(false)}
|
||||||
@@ -538,6 +545,12 @@ function UserListPage() {
|
|||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
|
<UserBulkUploadModal
|
||||||
|
variant="custom"
|
||||||
|
open={bulkUploadOpen}
|
||||||
|
onOpenChange={setBulkUploadOpen}
|
||||||
|
onSuccess={() => query.refetch()}
|
||||||
|
/>
|
||||||
<Dialog>
|
<Dialog>
|
||||||
<DialogTrigger asChild>
|
<DialogTrigger asChild>
|
||||||
<Button variant="outline" size="icon" className="h-9 w-9">
|
<Button variant="outline" size="icon" className="h-9 w-9">
|
||||||
|
|||||||
@@ -43,7 +43,9 @@ import {
|
|||||||
|
|
||||||
interface UserBulkUploadModalProps {
|
interface UserBulkUploadModalProps {
|
||||||
onSuccess?: () => void;
|
onSuccess?: () => void;
|
||||||
variant?: "button" | "dropdown";
|
variant?: "button" | "dropdown" | "custom";
|
||||||
|
open?: boolean;
|
||||||
|
onOpenChange?: (open: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildUserTenantPreviewRows(
|
function buildUserTenantPreviewRows(
|
||||||
@@ -141,8 +143,15 @@ export const downloadUserTemplate = () => {
|
|||||||
export function UserBulkUploadModal({
|
export function UserBulkUploadModal({
|
||||||
onSuccess,
|
onSuccess,
|
||||||
variant = "button",
|
variant = "button",
|
||||||
|
open: controlledOpen,
|
||||||
|
onOpenChange: controlledOnOpenChange,
|
||||||
}: UserBulkUploadModalProps) {
|
}: UserBulkUploadModalProps) {
|
||||||
const [open, setOpen] = React.useState(false);
|
const [localOpen, setLocalOpen] = React.useState(false);
|
||||||
|
const open = controlledOpen !== undefined ? controlledOpen : localOpen;
|
||||||
|
const setOpen = (val: boolean) => {
|
||||||
|
setLocalOpen(val);
|
||||||
|
controlledOnOpenChange?.(val);
|
||||||
|
};
|
||||||
const [file, setFile] = React.useState<File | null>(null);
|
const [file, setFile] = React.useState<File | null>(null);
|
||||||
const [parsing, setParsing] = React.useState(false);
|
const [parsing, setParsing] = React.useState(false);
|
||||||
const [previewData, setPreviewData] = React.useState<BulkUserItem[]>([]);
|
const [previewData, setPreviewData] = React.useState<BulkUserItem[]>([]);
|
||||||
@@ -359,7 +368,7 @@ export function UserBulkUploadModal({
|
|||||||
<Upload size={16} className="mr-2 opacity-50" />
|
<Upload size={16} className="mr-2 opacity-50" />
|
||||||
{t("ui.admin.users.list.bulk_import", "일괄 등록 (CSV)")}
|
{t("ui.admin.users.list.bulk_import", "일괄 등록 (CSV)")}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
) : (
|
) : variant === "custom" ? null : (
|
||||||
<DialogTrigger asChild>
|
<DialogTrigger asChild>
|
||||||
<Button variant="outline" className="gap-2" {...triggerProps}>
|
<Button variant="outline" className="gap-2" {...triggerProps}>
|
||||||
<Upload size={16} />
|
<Upload size={16} />
|
||||||
@@ -378,7 +387,7 @@ export function UserBulkUploadModal({
|
|||||||
if (!val) reset();
|
if (!val) reset();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{variant !== "dropdown" && triggerNode}
|
{variant !== "dropdown" && variant !== "custom" && triggerNode}
|
||||||
<DialogContent className="max-w-2xl">
|
<DialogContent className="max-w-2xl">
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle data-testid="bulk-upload-title">
|
<DialogTitle data-testid="bulk-upload-title">
|
||||||
|
|||||||
Reference in New Issue
Block a user