forked from baron/baron-sso
조직도 줌 레벨 상향
This commit is contained in:
@@ -1,3 +1,6 @@
|
||||
{
|
||||
"extends": ["../common/config/biome.base.json"]
|
||||
"extends": ["../common/config/biome.base.json"],
|
||||
"files": {
|
||||
"ignore": [".vite"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,13 +22,13 @@ import { useAuth } from "react-oidc-context";
|
||||
import { NavLink, Outlet, useLocation, useNavigate } from "react-router-dom";
|
||||
import {
|
||||
AppSidebar,
|
||||
type ShellSidebarNavItem,
|
||||
type ShellTranslator,
|
||||
applyShellTheme,
|
||||
buildShellProfileSummary,
|
||||
buildShellSessionStatus,
|
||||
readShellSessionExpiryEnabled,
|
||||
readShellTheme,
|
||||
type ShellSidebarNavItem,
|
||||
shellLayoutClasses,
|
||||
writeShellSessionExpiryEnabled,
|
||||
} from "../../../../common/shell";
|
||||
|
||||
@@ -111,37 +111,36 @@ const DialogPortal = ({ children }: { children?: React.ReactNode }) => {
|
||||
};
|
||||
DialogPortal.displayName = "DialogPortal";
|
||||
|
||||
const DialogClose = React.forwardRef<
|
||||
HTMLButtonElement,
|
||||
DialogTriggerProps
|
||||
>(({ asChild = false, children, onClick, ...props }, ref) => {
|
||||
const { setOpen } = useDialogContext("DialogClose");
|
||||
const handleClose = (event: React.MouseEvent<HTMLButtonElement>) => {
|
||||
onClick?.(event);
|
||||
if (!event.defaultPrevented) {
|
||||
setOpen(false);
|
||||
const DialogClose = React.forwardRef<HTMLButtonElement, DialogTriggerProps>(
|
||||
({ asChild = false, children, onClick, ...props }, ref) => {
|
||||
const { setOpen } = useDialogContext("DialogClose");
|
||||
const handleClose = (event: React.MouseEvent<HTMLButtonElement>) => {
|
||||
onClick?.(event);
|
||||
if (!event.defaultPrevented) {
|
||||
setOpen(false);
|
||||
}
|
||||
};
|
||||
|
||||
if (asChild && React.isValidElement(children)) {
|
||||
const child = children as React.ReactElement<{
|
||||
onClick?: React.MouseEventHandler<HTMLElement>;
|
||||
}>;
|
||||
return React.cloneElement(child, {
|
||||
...props,
|
||||
onClick: composeEventHandlers(
|
||||
child.props.onClick as React.MouseEventHandler<HTMLButtonElement>,
|
||||
() => setOpen(false),
|
||||
),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
if (asChild && React.isValidElement(children)) {
|
||||
const child = children as React.ReactElement<{
|
||||
onClick?: React.MouseEventHandler<HTMLElement>;
|
||||
}>;
|
||||
return React.cloneElement(child, {
|
||||
...props,
|
||||
onClick: composeEventHandlers(
|
||||
child.props.onClick as React.MouseEventHandler<HTMLButtonElement>,
|
||||
() => setOpen(false),
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<button type="button" ref={ref} onClick={handleClose} {...props}>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
});
|
||||
return (
|
||||
<button type="button" ref={ref} onClick={handleClose} {...props}>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
},
|
||||
);
|
||||
DialogClose.displayName = "DialogClose";
|
||||
|
||||
const DialogOverlay = React.forwardRef<
|
||||
@@ -169,8 +168,8 @@ const DialogOverlay = React.forwardRef<
|
||||
DialogOverlay.displayName = "DialogOverlay";
|
||||
|
||||
const DialogContent = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
HTMLDialogElement,
|
||||
React.HTMLAttributes<HTMLDialogElement>
|
||||
>(({ className, children, onKeyDown, ...props }, ref) => {
|
||||
const { open, setOpen } = useDialogContext("DialogContent");
|
||||
|
||||
@@ -194,13 +193,13 @@ const DialogContent = React.forwardRef<
|
||||
return (
|
||||
<DialogPortal>
|
||||
<DialogOverlay />
|
||||
<div
|
||||
<dialog
|
||||
ref={ref}
|
||||
role="dialog"
|
||||
open
|
||||
aria-modal="true"
|
||||
data-state="open"
|
||||
className={cn(
|
||||
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
|
||||
"fixed left-[50%] top-[50%] z-50 m-0 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 backdrop:bg-transparent data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
|
||||
className,
|
||||
)}
|
||||
onKeyDown={onKeyDown}
|
||||
@@ -211,7 +210,7 @@ const DialogContent = React.forwardRef<
|
||||
<X className="h-4 w-4" />
|
||||
<span className="sr-only">Close</span>
|
||||
</DialogClose>
|
||||
</div>
|
||||
</dialog>
|
||||
</DialogPortal>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -12,6 +12,8 @@ import {
|
||||
} from "lucide-react";
|
||||
import * as React from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { PageHeader } from "../../../../common/core/components/page";
|
||||
import { commonStickyTableHeaderClass } from "../../../../common/ui/table";
|
||||
import { Badge } from "../../components/ui/badge";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import {
|
||||
@@ -38,8 +40,6 @@ import {
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "../../components/ui/table";
|
||||
import { PageHeader } from "../../../../common/core/components/page";
|
||||
import { commonStickyTableHeaderClass } from "../../../../common/ui/table";
|
||||
import {
|
||||
type ApiKeySummary,
|
||||
deleteApiKey,
|
||||
|
||||
@@ -13,7 +13,12 @@ import { PageHeader } from "../../../../common/core/components/page";
|
||||
import { SearchFilterBar } from "../../../../common/ui/search-filter-bar";
|
||||
import { Badge } from "../../components/ui/badge";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "../../components/ui/card";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "../../components/ui/card";
|
||||
import { Input } from "../../components/ui/input";
|
||||
import type { AuditLog } from "../../lib/adminApi";
|
||||
import { fetchAuditLogs } from "../../lib/adminApi";
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
import { useState } from "react";
|
||||
import { useAuth } from "react-oidc-context";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import { commonStickyTableHeaderClass } from "../../../../../common/ui/table";
|
||||
import { Badge } from "../../../components/ui/badge";
|
||||
import { Button } from "../../../components/ui/button";
|
||||
import {
|
||||
@@ -38,7 +39,6 @@ import {
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "../../../components/ui/table";
|
||||
import { commonStickyTableHeaderClass } from "../../../../../common/ui/table";
|
||||
import { toast } from "../../../components/ui/use-toast";
|
||||
import {
|
||||
type TenantAdmin,
|
||||
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
import type React from "react";
|
||||
import { useState } from "react";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { commonStickyTableHeaderClass } from "../../../../../common/ui/table";
|
||||
import { Badge } from "../../../components/ui/badge";
|
||||
import { Button } from "../../../components/ui/button";
|
||||
import {
|
||||
@@ -50,7 +51,6 @@ import {
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "../../../components/ui/table";
|
||||
import { commonStickyTableHeaderClass } from "../../../../../common/ui/table";
|
||||
import { toast } from "../../../components/ui/use-toast";
|
||||
import {
|
||||
type GroupSummary,
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { ArrowRight, Building2, Plus } from "lucide-react";
|
||||
import { Link, useNavigate, useParams } from "react-router-dom";
|
||||
import {
|
||||
commonStickyTableHeaderClass,
|
||||
commonTableShellClass,
|
||||
commonTableViewportClass,
|
||||
} from "../../../../../common/ui/table";
|
||||
import { Badge } from "../../../components/ui/badge";
|
||||
import { Button } from "../../../components/ui/button";
|
||||
import {
|
||||
@@ -18,11 +23,6 @@ import {
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "../../../components/ui/table";
|
||||
import {
|
||||
commonStickyTableHeaderClass,
|
||||
commonTableShellClass,
|
||||
commonTableViewportClass,
|
||||
} from "../../../../../common/ui/table";
|
||||
import { fetchAllTenants } from "../../../lib/adminApi";
|
||||
import { t } from "../../../lib/i18n";
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
UserPlus,
|
||||
} from "lucide-react";
|
||||
import { Link, useNavigate, useParams } from "react-router-dom";
|
||||
import { commonStickyTableHeaderClass } from "../../../../../common/ui/table";
|
||||
import { Badge } from "../../../components/ui/badge";
|
||||
import { Button } from "../../../components/ui/button";
|
||||
import {
|
||||
@@ -32,7 +33,6 @@ import {
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "../../../components/ui/table";
|
||||
import { commonStickyTableHeaderClass } from "../../../../../common/ui/table";
|
||||
import { toast } from "../../../components/ui/use-toast";
|
||||
import { fetchTenant, fetchUsers, updateUser } from "../../../lib/adminApi";
|
||||
import { t } from "../../../lib/i18n";
|
||||
|
||||
@@ -681,11 +681,7 @@ function ComparisonFilterButtons<T extends string>({
|
||||
aria-pressed={isSelected}
|
||||
aria-expanded={hasDetail && openDetailFor === option.value}
|
||||
onClick={() => {
|
||||
if (
|
||||
hasDetail &&
|
||||
isSelected &&
|
||||
openDetailFor !== option.value
|
||||
) {
|
||||
if (hasDetail && isSelected && openDetailFor !== option.value) {
|
||||
setOpenDetailFor(option.value);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { useQuery } from "@tanstack/react-query";
|
||||
import { Building2, Plus, Users } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { commonStickyTableHeaderClass } from "../../../../../common/ui/table";
|
||||
import { Badge } from "../../../components/ui/badge";
|
||||
import { Button } from "../../../components/ui/button";
|
||||
import {
|
||||
@@ -19,7 +20,6 @@ import {
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "../../../components/ui/table";
|
||||
import { commonStickyTableHeaderClass } from "../../../../../common/ui/table";
|
||||
import {
|
||||
type TenantSummary,
|
||||
fetchAllTenants,
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { AxiosError } from "axios";
|
||||
import { ArrowLeft, Shield, Trash2, UserPlus, Users } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
import { Link, useParams } from "react-router-dom";
|
||||
import { commonStickyTableHeaderClass } from "../../../../../common/ui/table";
|
||||
import { Badge } from "../../../components/ui/badge";
|
||||
import { Button } from "../../../components/ui/button";
|
||||
import {
|
||||
@@ -38,7 +39,6 @@ import {
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "../../../components/ui/table";
|
||||
import { commonStickyTableHeaderClass } from "../../../../../common/ui/table";
|
||||
import { toast } from "../../../components/ui/use-toast";
|
||||
import {
|
||||
addGroupMember,
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
} from "lucide-react";
|
||||
import * as React from "react";
|
||||
import { Link, useNavigate } from "react-router-dom";
|
||||
import { PageHeader } from "../../../../common/core/components/page";
|
||||
import {
|
||||
SortableTableHead,
|
||||
sortableTableHeadBaseClassName,
|
||||
@@ -29,12 +30,11 @@ import {
|
||||
sortItems,
|
||||
toggleSort,
|
||||
} from "../../../../common/core/utils";
|
||||
import { PageHeader } from "../../../../common/core/components/page";
|
||||
import { SearchFilterBar } from "../../../../common/ui/search-filter-bar";
|
||||
import {
|
||||
commonTableShellClass,
|
||||
commonTableViewportClass,
|
||||
} from "../../../../common/ui/table";
|
||||
import { SearchFilterBar } from "../../../../common/ui/search-filter-bar";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import {
|
||||
Card,
|
||||
@@ -545,7 +545,9 @@ function UserListPage() {
|
||||
onChange={() => toggleColumn(field.key)}
|
||||
/>
|
||||
<div className="flex flex-col">
|
||||
<span className="text-sm font-medium">{field.label}</span>
|
||||
<span className="text-sm font-medium">
|
||||
{field.label}
|
||||
</span>
|
||||
<span className="font-mono text-xs text-muted-foreground">
|
||||
{field.key}
|
||||
</span>
|
||||
|
||||
@@ -19,9 +19,7 @@ createRoot(rootElement).render(
|
||||
<StrictMode>
|
||||
<AuthProvider {...oidcConfig}>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<RouterProvider
|
||||
router={router}
|
||||
/>
|
||||
<RouterProvider router={router} />
|
||||
<Toaster />
|
||||
</QueryClientProvider>
|
||||
</AuthProvider>
|
||||
|
||||
@@ -7,7 +7,7 @@ const buildOutDir =
|
||||
const allowedHosts = getAllowedHosts(
|
||||
["sadmin.hmac.kr", "localhost", "172.16.10.176", "127.0.0.1"],
|
||||
undefined,
|
||||
undefined
|
||||
undefined,
|
||||
);
|
||||
|
||||
export default defineConfig(
|
||||
@@ -40,5 +40,5 @@ export default defineConfig(
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module baron-sso-backend
|
||||
|
||||
go 1.24.0
|
||||
go 1.26.2
|
||||
|
||||
require (
|
||||
github.com/ClickHouse/clickhouse-go/v2 v2.42.0
|
||||
|
||||
@@ -39,6 +39,7 @@ back = "Back"
|
||||
back_to_login = "Back to login"
|
||||
cancel = "Cancel"
|
||||
change_file = "Change File"
|
||||
clear = "Clear"
|
||||
clear_search = "Clear Search"
|
||||
close = "Close"
|
||||
collapse = "Collapse"
|
||||
|
||||
@@ -39,6 +39,7 @@ back = "돌아가기"
|
||||
back_to_login = "로그인으로 돌아가기"
|
||||
cancel = "취소"
|
||||
change_file = "파일 변경"
|
||||
clear = "초기화"
|
||||
clear_search = "검색 초기화"
|
||||
close = "닫기"
|
||||
collapse = "접기"
|
||||
|
||||
@@ -39,6 +39,7 @@ back = ""
|
||||
back_to_login = ""
|
||||
cancel = ""
|
||||
change_file = ""
|
||||
clear = ""
|
||||
clear_search = ""
|
||||
close = ""
|
||||
collapse = ""
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
{
|
||||
"extends": ["../common/config/biome.base.json"]
|
||||
"extends": ["../common/config/biome.base.json"],
|
||||
"files": {
|
||||
"ignore": [".vite"]
|
||||
}
|
||||
}
|
||||
|
||||
785
devfront/package-lock.json
generated
785
devfront/package-lock.json
generated
@@ -48,13 +48,6 @@
|
||||
"node": ">=24.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@acemir/cssom": {
|
||||
"version": "0.9.31",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/@alloc/quick-lru": {
|
||||
"version": "5.2.0",
|
||||
"dev": true,
|
||||
@@ -66,207 +59,6 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/@asamuzakjp/css-color": {
|
||||
"version": "5.1.11",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@asamuzakjp/generational-cache": "^1.0.1",
|
||||
"@csstools/css-calc": "^3.2.0",
|
||||
"@csstools/css-color-parser": "^4.1.0",
|
||||
"@csstools/css-parser-algorithms": "^4.0.0",
|
||||
"@csstools/css-tokenizer": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@asamuzakjp/dom-selector": {
|
||||
"version": "6.8.1",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@asamuzakjp/nwsapi": "^2.3.9",
|
||||
"bidi-js": "^1.0.3",
|
||||
"css-tree": "^3.1.0",
|
||||
"is-potential-custom-element-name": "^1.0.1",
|
||||
"lru-cache": "^11.2.6"
|
||||
}
|
||||
},
|
||||
"node_modules/@asamuzakjp/generational-cache": {
|
||||
"version": "1.0.1",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@asamuzakjp/nwsapi": {
|
||||
"version": "2.3.9",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/@bramus/specificity": {
|
||||
"version": "2.4.2",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"css-tree": "^3.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"specificity": "bin/cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/@csstools/color-helpers": {
|
||||
"version": "6.0.2",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/csstools"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/csstools"
|
||||
}
|
||||
],
|
||||
"license": "MIT-0",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=20.19.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@csstools/css-calc": {
|
||||
"version": "3.2.0",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/csstools"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/csstools"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=20.19.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@csstools/css-parser-algorithms": "^4.0.0",
|
||||
"@csstools/css-tokenizer": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@csstools/css-color-parser": {
|
||||
"version": "4.1.0",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/csstools"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/csstools"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@csstools/color-helpers": "^6.0.2",
|
||||
"@csstools/css-calc": "^3.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.19.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@csstools/css-parser-algorithms": "^4.0.0",
|
||||
"@csstools/css-tokenizer": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@csstools/css-parser-algorithms": {
|
||||
"version": "4.0.0",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/csstools"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/csstools"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=20.19.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@csstools/css-tokenizer": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@csstools/css-syntax-patches-for-csstree": {
|
||||
"version": "1.1.3",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/csstools"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/csstools"
|
||||
}
|
||||
],
|
||||
"license": "MIT-0",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"peerDependencies": {
|
||||
"css-tree": "^3.2.1"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"css-tree": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@csstools/css-tokenizer": {
|
||||
"version": "4.0.0",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/csstools"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/csstools"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=20.19.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@emnapi/core": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz",
|
||||
@@ -301,24 +93,6 @@
|
||||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@exodus/bytes": {
|
||||
"version": "1.15.0",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@noble/hashes": "^1.8.0 || ^2.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@noble/hashes": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@floating-ui/core": {
|
||||
"version": "1.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz",
|
||||
@@ -2408,16 +2182,6 @@
|
||||
"url": "https://opencollective.com/vitest"
|
||||
}
|
||||
},
|
||||
"node_modules/agent-base": {
|
||||
"version": "7.1.4",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
}
|
||||
},
|
||||
"node_modules/any-promise": {
|
||||
"version": "1.3.0",
|
||||
"dev": true,
|
||||
@@ -2553,16 +2317,6 @@
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/bidi-js": {
|
||||
"version": "1.0.3",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"require-from-string": "^2.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/binary-extensions": {
|
||||
"version": "2.3.0",
|
||||
"dev": true,
|
||||
@@ -2758,20 +2512,6 @@
|
||||
"url": "https://opencollective.com/express"
|
||||
}
|
||||
},
|
||||
"node_modules/css-tree": {
|
||||
"version": "3.2.1",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"mdn-data": "2.27.1",
|
||||
"source-map-js": "^1.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/cssesc": {
|
||||
"version": "3.0.0",
|
||||
"dev": true,
|
||||
@@ -2783,41 +2523,11 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/cssstyle": {
|
||||
"version": "6.2.0",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@asamuzakjp/css-color": "^5.0.1",
|
||||
"@csstools/css-syntax-patches-for-csstree": "^1.0.28",
|
||||
"css-tree": "^3.1.0",
|
||||
"lru-cache": "^11.2.6"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
}
|
||||
},
|
||||
"node_modules/csstype": {
|
||||
"version": "3.2.3",
|
||||
"devOptional": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/data-urls": {
|
||||
"version": "7.0.0",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"whatwg-mimetype": "^5.0.0",
|
||||
"whatwg-url": "^16.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.4.3",
|
||||
"license": "MIT",
|
||||
@@ -2833,13 +2543,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/decimal.js": {
|
||||
"version": "10.6.0",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
@@ -2890,19 +2593,6 @@
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/entities": {
|
||||
"version": "8.0.0",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=20.19.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/es-define-property": {
|
||||
"version": "1.0.1",
|
||||
"license": "MIT",
|
||||
@@ -3182,47 +2872,6 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/html-encoding-sniffer": {
|
||||
"version": "6.0.0",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@exodus/bytes": "^1.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/http-proxy-agent": {
|
||||
"version": "7.0.2",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"agent-base": "^7.1.0",
|
||||
"debug": "^4.3.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
}
|
||||
},
|
||||
"node_modules/https-proxy-agent": {
|
||||
"version": "7.0.6",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"agent-base": "^7.1.2",
|
||||
"debug": "4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
}
|
||||
},
|
||||
"node_modules/is-binary-path": {
|
||||
"version": "2.1.0",
|
||||
"dev": true,
|
||||
@@ -3275,13 +2924,6 @@
|
||||
"node": ">=0.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-potential-custom-element-name": {
|
||||
"version": "1.0.1",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/jiti": {
|
||||
"version": "1.21.7",
|
||||
"dev": true,
|
||||
@@ -3290,47 +2932,6 @@
|
||||
"jiti": "bin/jiti.js"
|
||||
}
|
||||
},
|
||||
"node_modules/jsdom": {
|
||||
"version": "28.1.0",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@acemir/cssom": "^0.9.31",
|
||||
"@asamuzakjp/dom-selector": "^6.8.1",
|
||||
"@bramus/specificity": "^2.4.2",
|
||||
"@exodus/bytes": "^1.11.0",
|
||||
"cssstyle": "^6.0.1",
|
||||
"data-urls": "^7.0.0",
|
||||
"decimal.js": "^10.6.0",
|
||||
"html-encoding-sniffer": "^6.0.0",
|
||||
"http-proxy-agent": "^7.0.2",
|
||||
"https-proxy-agent": "^7.0.6",
|
||||
"is-potential-custom-element-name": "^1.0.1",
|
||||
"parse5": "^8.0.0",
|
||||
"saxes": "^6.0.0",
|
||||
"symbol-tree": "^3.2.4",
|
||||
"tough-cookie": "^6.0.0",
|
||||
"undici": "^7.21.0",
|
||||
"w3c-xmlserializer": "^5.0.0",
|
||||
"webidl-conversions": "^8.0.1",
|
||||
"whatwg-mimetype": "^5.0.0",
|
||||
"whatwg-url": "^16.0.0",
|
||||
"xml-name-validator": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"canvas": "^3.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"canvas": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/jwt-decode": {
|
||||
"version": "4.0.0",
|
||||
"license": "MIT",
|
||||
@@ -3366,6 +2967,159 @@
|
||||
"lightningcss-win32-x64-msvc": "1.32.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss-android-arm64": {
|
||||
"version": "1.32.0",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz",
|
||||
"integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss-darwin-arm64": {
|
||||
"version": "1.32.0",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz",
|
||||
"integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss-darwin-x64": {
|
||||
"version": "1.32.0",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz",
|
||||
"integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss-freebsd-x64": {
|
||||
"version": "1.32.0",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz",
|
||||
"integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss-linux-arm-gnueabihf": {
|
||||
"version": "1.32.0",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz",
|
||||
"integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss-linux-arm64-gnu": {
|
||||
"version": "1.32.0",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz",
|
||||
"integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"libc": [
|
||||
"glibc"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss-linux-arm64-musl": {
|
||||
"version": "1.32.0",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz",
|
||||
"integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"libc": [
|
||||
"musl"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss-linux-x64-gnu": {
|
||||
"version": "1.32.0",
|
||||
"cpu": [
|
||||
@@ -3404,6 +3158,48 @@
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss-win32-arm64-msvc": {
|
||||
"version": "1.32.0",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz",
|
||||
"integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss-win32-x64-msvc": {
|
||||
"version": "1.32.0",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz",
|
||||
"integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/lilconfig": {
|
||||
"version": "3.1.3",
|
||||
"dev": true,
|
||||
@@ -3420,16 +3216,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lru-cache": {
|
||||
"version": "11.3.6",
|
||||
"dev": true,
|
||||
"license": "BlueOak-1.0.0",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
}
|
||||
},
|
||||
"node_modules/lucide-react": {
|
||||
"version": "1.16.0",
|
||||
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-1.16.0.tgz",
|
||||
@@ -3456,13 +3242,6 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/mdn-data": {
|
||||
"version": "2.27.1",
|
||||
"dev": true,
|
||||
"license": "CC0-1.0",
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/merge2": {
|
||||
"version": "1.4.1",
|
||||
"dev": true,
|
||||
@@ -3583,19 +3362,6 @@
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/parse5": {
|
||||
"version": "8.0.1",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"entities": "^8.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/inikulin/parse5?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/path-parse": {
|
||||
"version": "1.0.7",
|
||||
"dev": true,
|
||||
@@ -3832,16 +3598,6 @@
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/punycode": {
|
||||
"version": "2.3.1",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/queue-microtask": {
|
||||
"version": "1.2.3",
|
||||
"dev": true,
|
||||
@@ -4037,16 +3793,6 @@
|
||||
"node": ">=8.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/require-from-string": {
|
||||
"version": "2.0.2",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/resolve": {
|
||||
"version": "1.22.11",
|
||||
"dev": true,
|
||||
@@ -4138,19 +3884,6 @@
|
||||
"queue-microtask": "^1.2.2"
|
||||
}
|
||||
},
|
||||
"node_modules/saxes": {
|
||||
"version": "6.0.0",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"xmlchars": "^2.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=v12.22.7"
|
||||
}
|
||||
},
|
||||
"node_modules/scheduler": {
|
||||
"version": "0.27.0",
|
||||
"license": "MIT"
|
||||
@@ -4216,13 +3949,6 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/symbol-tree": {
|
||||
"version": "3.2.4",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/tailwind-merge": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.6.0.tgz",
|
||||
@@ -4365,26 +4091,6 @@
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tldts": {
|
||||
"version": "7.0.30",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"tldts-core": "^7.0.30"
|
||||
},
|
||||
"bin": {
|
||||
"tldts": "bin/cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/tldts-core": {
|
||||
"version": "7.0.30",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"dev": true,
|
||||
@@ -4396,32 +4102,6 @@
|
||||
"node": ">=8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tough-cookie": {
|
||||
"version": "6.0.1",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"tldts": "^7.0.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/tr46": {
|
||||
"version": "6.0.0",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"punycode": "^2.3.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-interface-checker": {
|
||||
"version": "0.1.13",
|
||||
"dev": true,
|
||||
@@ -4447,16 +4127,6 @@
|
||||
"node": ">=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/undici": {
|
||||
"version": "7.25.0",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=20.18.1"
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "7.24.6",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz",
|
||||
@@ -4755,54 +4425,6 @@
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/w3c-xmlserializer": {
|
||||
"version": "5.0.0",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"xml-name-validator": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/webidl-conversions": {
|
||||
"version": "8.0.1",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
}
|
||||
},
|
||||
"node_modules/whatwg-mimetype": {
|
||||
"version": "5.0.0",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
}
|
||||
},
|
||||
"node_modules/whatwg-url": {
|
||||
"version": "16.0.1",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@exodus/bytes": "^1.11.0",
|
||||
"tr46": "^6.0.0",
|
||||
"webidl-conversions": "^8.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/why-is-node-running": {
|
||||
"version": "2.3.0",
|
||||
"dev": true,
|
||||
@@ -4818,23 +4440,6 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/xml-name-validator": {
|
||||
"version": "5.0.0",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/xmlchars": {
|
||||
"version": "2.2.0",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/zod": {
|
||||
"version": "4.4.3",
|
||||
"resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz",
|
||||
|
||||
@@ -9,8 +9,8 @@ import ClientDetailsPage from "../features/clients/ClientDetailsPage";
|
||||
import ClientGeneralPage from "../features/clients/ClientGeneralPage";
|
||||
import ClientRelationsPage from "../features/clients/ClientRelationsPage";
|
||||
import ClientsPage from "../features/clients/ClientsPage";
|
||||
import GlobalOverviewPage from "../features/overview/GlobalOverviewPage";
|
||||
import DeveloperRequestPage from "../features/developer-request/DeveloperRequestPage";
|
||||
import GlobalOverviewPage from "../features/overview/GlobalOverviewPage";
|
||||
import ProfilePage from "../features/profile/ProfilePage";
|
||||
import { DEVFRONT_AUTH_CALLBACK_PATH } from "../lib/authConfig";
|
||||
|
||||
|
||||
@@ -15,13 +15,13 @@ import { useAuth } from "react-oidc-context";
|
||||
import { NavLink, Outlet, useLocation, useNavigate } from "react-router-dom";
|
||||
import {
|
||||
AppSidebar,
|
||||
type ShellSidebarNavItem,
|
||||
type ShellTranslator,
|
||||
applyShellTheme,
|
||||
buildShellProfileSummary,
|
||||
buildShellSessionStatus,
|
||||
readShellSessionExpiryEnabled,
|
||||
readShellTheme,
|
||||
type ShellSidebarNavItem,
|
||||
shellLayoutClasses,
|
||||
writeShellSessionExpiryEnabled,
|
||||
} from "../../../../common/shell";
|
||||
|
||||
@@ -2,17 +2,20 @@ import { useInfiniteQuery } from "@tanstack/react-query";
|
||||
import type { AxiosError } from "axios";
|
||||
import { Download, RefreshCw, Search } from "lucide-react";
|
||||
import * as React from "react";
|
||||
import { parseAuditDetails } from "../../../../common/core/audit";
|
||||
import { AuditLogTable } from "../../../../common/core/components/audit";
|
||||
import { PageHeader } from "../../../../common/core/components/page";
|
||||
import { SearchFilterBar } from "../../../../common/ui/search-filter-bar";
|
||||
import { ForbiddenMessage } from "../../components/common/ForbiddenMessage";
|
||||
import { Badge } from "../../components/ui/badge";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "../../components/ui/card";
|
||||
import { Input } from "../../components/ui/input";
|
||||
import {
|
||||
parseAuditDetails,
|
||||
} from "../../../../common/core/audit";
|
||||
import { AuditLogTable } from "../../../../common/core/components/audit";
|
||||
import { SearchFilterBar } from "../../../../common/ui/search-filter-bar";
|
||||
import { PageHeader } from "../../../../common/core/components/page";
|
||||
Card,
|
||||
CardContent,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "../../components/ui/card";
|
||||
import { Input } from "../../components/ui/input";
|
||||
import type { DevAuditLog } from "../../lib/devApi";
|
||||
import { fetchDevAuditLogs } from "../../lib/devApi";
|
||||
import { t } from "../../lib/i18n";
|
||||
|
||||
@@ -4,19 +4,19 @@ import { BookOpenText, Filter, Plus, Search, X } from "lucide-react";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { useAuth } from "react-oidc-context";
|
||||
import { Link, useNavigate } from "react-router-dom";
|
||||
import { PageHeader } from "../../../../common/core/components/page";
|
||||
import {
|
||||
SortableTableHead,
|
||||
sortableTableHeadBaseClassName,
|
||||
sortableTableHeaderClassName,
|
||||
} from "../../../../common/core/components/sort";
|
||||
import { SearchFilterBar } from "../../../../common/ui/search-filter-bar";
|
||||
import { PageHeader } from "../../../../common/core/components/page";
|
||||
import {
|
||||
type SortConfig,
|
||||
type SortResolverMap,
|
||||
sortItems,
|
||||
toggleSort,
|
||||
} from "../../../../common/core/utils";
|
||||
import { SearchFilterBar } from "../../../../common/ui/search-filter-bar";
|
||||
import {
|
||||
commonTableShellClass,
|
||||
commonTableViewportClass,
|
||||
@@ -330,61 +330,59 @@ function ClientsPage() {
|
||||
}
|
||||
advancedOpen={isAdvancedFilterOpen}
|
||||
advanced={
|
||||
<>
|
||||
<div className="flex flex-wrap items-center gap-6">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-xs font-bold uppercase tracking-wider text-muted-foreground whitespace-nowrap">
|
||||
{t("ui.dev.clients.filter.type_label", "Type:")}
|
||||
</span>
|
||||
<select
|
||||
className="h-9 min-w-[140px] rounded-md border border-input bg-background px-3 text-sm focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/30"
|
||||
value={typeFilter}
|
||||
onChange={(e) => setTypeFilter(e.target.value)}
|
||||
>
|
||||
<option value="all">
|
||||
{t("ui.dev.clients.filter.type_all", "모든 유형")}
|
||||
</option>
|
||||
<option value="private">
|
||||
{t("ui.dev.clients.type.private", "Server side App")}
|
||||
</option>
|
||||
<option value="pkce">
|
||||
{t("ui.dev.clients.type.pkce", "PKCE")}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-xs font-bold uppercase tracking-wider text-muted-foreground whitespace-nowrap">
|
||||
{t("ui.dev.clients.consents.status_label", "Status:")}
|
||||
</span>
|
||||
<select
|
||||
className="h-9 min-w-[140px] rounded-md border border-input bg-background px-3 text-sm focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/30"
|
||||
value={statusFilter}
|
||||
onChange={(e) => setStatusFilter(e.target.value)}
|
||||
>
|
||||
<option value="all">
|
||||
{t("ui.dev.clients.filter.status_all", "모든 상태")}
|
||||
</option>
|
||||
<option value="active">
|
||||
{t("ui.common.status.active", "Active")}
|
||||
</option>
|
||||
<option value="inactive">
|
||||
{t("ui.common.status.inactive", "Inactive")}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="ml-auto text-xs text-muted-foreground"
|
||||
onClick={() => {
|
||||
setTypeFilter("all");
|
||||
setStatusFilter("all");
|
||||
}}
|
||||
<div className="flex flex-wrap items-center gap-6">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-xs font-bold uppercase tracking-wider text-muted-foreground whitespace-nowrap">
|
||||
{t("ui.dev.clients.filter.type_label", "Type:")}
|
||||
</span>
|
||||
<select
|
||||
className="h-9 min-w-[140px] rounded-md border border-input bg-background px-3 text-sm focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/30"
|
||||
value={typeFilter}
|
||||
onChange={(e) => setTypeFilter(e.target.value)}
|
||||
>
|
||||
{t("ui.common.reset", "초기화")}
|
||||
</Button>
|
||||
<option value="all">
|
||||
{t("ui.dev.clients.filter.type_all", "모든 유형")}
|
||||
</option>
|
||||
<option value="private">
|
||||
{t("ui.dev.clients.type.private", "Server side App")}
|
||||
</option>
|
||||
<option value="pkce">
|
||||
{t("ui.dev.clients.type.pkce", "PKCE")}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-xs font-bold uppercase tracking-wider text-muted-foreground whitespace-nowrap">
|
||||
{t("ui.dev.clients.consents.status_label", "Status:")}
|
||||
</span>
|
||||
<select
|
||||
className="h-9 min-w-[140px] rounded-md border border-input bg-background px-3 text-sm focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/30"
|
||||
value={statusFilter}
|
||||
onChange={(e) => setStatusFilter(e.target.value)}
|
||||
>
|
||||
<option value="all">
|
||||
{t("ui.dev.clients.filter.status_all", "모든 상태")}
|
||||
</option>
|
||||
<option value="active">
|
||||
{t("ui.common.status.active", "Active")}
|
||||
</option>
|
||||
<option value="inactive">
|
||||
{t("ui.common.status.inactive", "Inactive")}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="ml-auto text-xs text-muted-foreground"
|
||||
onClick={() => {
|
||||
setTypeFilter("all");
|
||||
setStatusFilter("all");
|
||||
}}
|
||||
>
|
||||
{t("ui.common.reset", "초기화")}
|
||||
</Button>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
</CardHeader>
|
||||
|
||||
@@ -9,6 +9,12 @@ import {
|
||||
} from "lucide-react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useAuth } from "react-oidc-context";
|
||||
import { PageHeader } from "../../../../common/core/components/page";
|
||||
import {
|
||||
commonStickyTableHeaderClass,
|
||||
commonTableShellClass,
|
||||
commonTableViewportClass,
|
||||
} from "../../../../common/ui/table";
|
||||
import { Badge } from "../../components/ui/badge";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import {
|
||||
@@ -27,12 +33,6 @@ import {
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "../../components/ui/table";
|
||||
import {
|
||||
commonStickyTableHeaderClass,
|
||||
commonTableShellClass,
|
||||
commonTableViewportClass,
|
||||
} from "../../../../common/ui/table";
|
||||
import { PageHeader } from "../../../../common/core/components/page";
|
||||
import { Textarea } from "../../components/ui/textarea";
|
||||
import {
|
||||
approveDeveloperRequest,
|
||||
@@ -199,7 +199,9 @@ export default function DeveloperRequestPage() {
|
||||
{t("ui.dev.request.table.user", "사용자")}
|
||||
</TableHead>
|
||||
)}
|
||||
<TableHead>{t("ui.dev.request.table.org", "소속")}</TableHead>
|
||||
<TableHead>
|
||||
{t("ui.dev.request.table.org", "소속")}
|
||||
</TableHead>
|
||||
<TableHead>
|
||||
{t("ui.dev.request.table.reason", "신청 사유")}
|
||||
</TableHead>
|
||||
@@ -237,7 +239,9 @@ export default function DeveloperRequestPage() {
|
||||
</div>
|
||||
{(req.phone || req.role) && (
|
||||
<div className="mt-1 text-xs text-muted-foreground">
|
||||
{[req.phone, req.role].filter(Boolean).join(" / ")}
|
||||
{[req.phone, req.role]
|
||||
.filter(Boolean)
|
||||
.join(" / ")}
|
||||
</div>
|
||||
)}
|
||||
</TableCell>
|
||||
@@ -323,7 +327,10 @@ export default function DeveloperRequestPage() {
|
||||
disabled={isActionPending}
|
||||
>
|
||||
<XCircle className="mr-1 h-3 w-3" />
|
||||
{t("ui.dev.request.cancel_approval", "승인 취소")}
|
||||
{t(
|
||||
"ui.dev.request.cancel_approval",
|
||||
"승인 취소",
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
) : (
|
||||
|
||||
@@ -11,6 +11,11 @@ import {
|
||||
import { useMemo, useState } from "react";
|
||||
import { useAuth } from "react-oidc-context";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import {
|
||||
OverviewAxisNotes,
|
||||
OverviewMetric,
|
||||
OverviewSelectionChips,
|
||||
} from "../../../../common/core/components/overview";
|
||||
import {
|
||||
type ClientSummary,
|
||||
type RPUsageDailyMetric,
|
||||
@@ -22,11 +27,6 @@ import {
|
||||
} from "../../lib/devApi";
|
||||
import { t } from "../../lib/i18n";
|
||||
import { resolveProfileRole } from "../../lib/role";
|
||||
import {
|
||||
OverviewAxisNotes,
|
||||
OverviewMetric,
|
||||
OverviewSelectionChips,
|
||||
} from "../../../../common/core/components/overview";
|
||||
|
||||
type ClientDistribution = {
|
||||
activeClients: number;
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
import { defineConfig, mergeConfig } from "vite";
|
||||
import { commonViteConfig, getAllowedHosts } from "../common/config/vite.base";
|
||||
import {
|
||||
commonViteConfig,
|
||||
getAllowedHosts,
|
||||
hostFromUrl,
|
||||
} from "../common/config/vite.base";
|
||||
|
||||
const buildOutDir =
|
||||
process.env.DEVFRONT_BUILD_OUT_DIR ?? "/tmp/baron-sso-devfront-dist";
|
||||
const devfrontHost = hostFromUrl(process.env.DEVFRONT_URL);
|
||||
|
||||
const allowedHosts = getAllowedHosts(
|
||||
["sdev.hmac.kr", "localhost", "172.16.10.176", "127.0.0.1"],
|
||||
process.env.DEVFRONT_URL,
|
||||
process.env.DEVFRONT_ALLOWED_HOSTS
|
||||
devfrontHost,
|
||||
process.env.DEVFRONT_ALLOWED_HOSTS,
|
||||
);
|
||||
|
||||
export default defineConfig(
|
||||
@@ -39,5 +44,5 @@ export default defineConfig(
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -1,8 +1,18 @@
|
||||
import { fileURLToPath } from "node:url";
|
||||
import react from "@vitejs/plugin-react";
|
||||
import { defineConfig } from "vitest/config";
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
server: {
|
||||
fs: {
|
||||
allow: [
|
||||
fileURLToPath(new URL(".", import.meta.url)),
|
||||
fileURLToPath(new URL("../common", import.meta.url)),
|
||||
"/workspace/common",
|
||||
],
|
||||
},
|
||||
},
|
||||
test: {
|
||||
globals: true,
|
||||
environment: "jsdom",
|
||||
|
||||
@@ -218,6 +218,9 @@ local_picker_description = "Select the tenant to use as the parent from the tena
|
||||
local_picker_empty = "No selectable tenants are available."
|
||||
picker_description = "Select a tenant in org-chart to apply it as the parent tenant."
|
||||
|
||||
[msg.admin.tenants.scope]
|
||||
description = "Select a parent tenant to filter the list to its descendants."
|
||||
|
||||
[msg.admin.tenants.admins]
|
||||
add_success = "Tenant admin added successfully."
|
||||
empty = "No tenant admins are assigned yet."
|
||||
@@ -1153,6 +1156,12 @@ view_org_chart = "View Full Org Chart"
|
||||
[ui.admin.tenants.view]
|
||||
hierarchy = "Hierarchy"
|
||||
list = "List"
|
||||
table = "Table"
|
||||
tree = "Tree"
|
||||
|
||||
[ui.admin.tenants.scope]
|
||||
active = "{{name}} descendants"
|
||||
pick = "Select parent scope"
|
||||
|
||||
[ui.admin.tenants.domain_conflict]
|
||||
description = ""
|
||||
|
||||
@@ -125,6 +125,9 @@ local_picker_description = "테넌트 목록에서 상위 테넌트로 사용할
|
||||
local_picker_empty = "선택할 수 있는 테넌트가 없습니다."
|
||||
picker_description = "org-chart에서 테넌트를 선택하면 상위 테넌트에 반영됩니다."
|
||||
|
||||
[msg.admin.tenants.scope]
|
||||
description = "상위 테넌트를 선택하면 해당 하위 테넌트만 목록에 표시합니다."
|
||||
|
||||
[msg.dev.auth]
|
||||
access_denied_description = "DevFront는 관리자 전용 화면입니다. 권한이 필요하면 관리자에게 요청해 주세요."
|
||||
access_denied_title = "접근 권한이 없습니다."
|
||||
@@ -1639,6 +1642,12 @@ view_org_chart = "전체 조직도 보기"
|
||||
[ui.admin.tenants.view]
|
||||
hierarchy = "계층 구조"
|
||||
list = "평면 목록"
|
||||
table = "평면"
|
||||
tree = "트리"
|
||||
|
||||
[ui.admin.tenants.scope]
|
||||
active = "{{name}} 하위"
|
||||
pick = "상위 범위 선택"
|
||||
|
||||
[ui.admin.tenants.admins]
|
||||
add_button = "관리자 추가"
|
||||
|
||||
@@ -1505,6 +1505,12 @@ export = ""
|
||||
[ui.admin.tenants.view]
|
||||
hierarchy = ""
|
||||
list = ""
|
||||
table = ""
|
||||
tree = ""
|
||||
|
||||
[ui.admin.tenants.scope]
|
||||
active = ""
|
||||
pick = ""
|
||||
|
||||
[ui.admin.tenants.admins]
|
||||
add_button = ""
|
||||
@@ -1625,6 +1631,9 @@ local_picker_description = ""
|
||||
local_picker_empty = ""
|
||||
picker_description = ""
|
||||
|
||||
[msg.admin.tenants.scope]
|
||||
description = ""
|
||||
|
||||
[msg.admin.users]
|
||||
self_delete_blocked = ""
|
||||
export_error = ""
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
{
|
||||
"extends": ["../common/config/biome.base.json"]
|
||||
"extends": ["../common/config/biome.base.json"],
|
||||
"files": {
|
||||
"ignore": [".vite"]
|
||||
}
|
||||
}
|
||||
|
||||
1068
orgfront/package-lock.json
generated
1068
orgfront/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -9,6 +9,7 @@ import {
|
||||
Search,
|
||||
} from "lucide-react";
|
||||
import * as React from "react";
|
||||
import { SearchFilterBar } from "../../../../common/ui/search-filter-bar";
|
||||
import { ForbiddenMessage } from "../../components/common/ForbiddenMessage";
|
||||
import { Badge } from "../../components/ui/badge";
|
||||
import { Button } from "../../components/ui/button";
|
||||
@@ -28,7 +29,6 @@ import {
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "../../components/ui/table";
|
||||
import { SearchFilterBar } from "../../../../common/ui/search-filter-bar";
|
||||
import type { DevAuditLog } from "../../lib/devApi";
|
||||
import { fetchDevAuditLogs } from "../../lib/devApi";
|
||||
import { t } from "../../lib/i18n";
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
} from "lucide-react";
|
||||
import { useState } from "react";
|
||||
import { Link, useParams } from "react-router-dom";
|
||||
import { SearchFilterBar } from "../../../../common/ui/search-filter-bar";
|
||||
import { Badge } from "../../components/ui/badge";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import {
|
||||
@@ -26,7 +27,6 @@ import {
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "../../components/ui/table";
|
||||
import { SearchFilterBar } from "../../../../common/ui/search-filter-bar";
|
||||
import { fetchClient, fetchConsents, revokeConsent } from "../../lib/devApi";
|
||||
import { t } from "../../lib/i18n";
|
||||
import { cn } from "../../lib/utils";
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
import { useState } from "react";
|
||||
import { useAuth } from "react-oidc-context";
|
||||
import { Link, useNavigate } from "react-router-dom";
|
||||
import { SearchFilterBar } from "../../../../common/ui/search-filter-bar";
|
||||
import { ForbiddenMessage } from "../../components/common/ForbiddenMessage";
|
||||
import {
|
||||
Avatar,
|
||||
@@ -36,7 +37,6 @@ import {
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "../../components/ui/table";
|
||||
import { SearchFilterBar } from "../../../../common/ui/search-filter-bar";
|
||||
import { fetchClients, fetchDevStats } from "../../lib/devApi";
|
||||
import { t } from "../../lib/i18n";
|
||||
import { cn } from "../../lib/utils";
|
||||
@@ -228,61 +228,59 @@ function ClientsPage() {
|
||||
}
|
||||
advancedOpen={isAdvancedFilterOpen}
|
||||
advanced={
|
||||
<>
|
||||
<div className="flex flex-wrap items-center gap-6">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-xs font-bold uppercase tracking-wider text-muted-foreground whitespace-nowrap">
|
||||
{t("ui.dev.clients.filter.type_label", "Type:")}
|
||||
</span>
|
||||
<select
|
||||
className="h-9 min-w-[140px] rounded-md border border-input bg-background px-3 text-sm focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/30"
|
||||
value={typeFilter}
|
||||
onChange={(e) => setTypeFilter(e.target.value)}
|
||||
>
|
||||
<option value="all">
|
||||
{t("ui.dev.clients.filter.type_all", "모든 유형")}
|
||||
</option>
|
||||
<option value="private">
|
||||
{t("ui.dev.clients.type.private", "Server side App")}
|
||||
</option>
|
||||
<option value="pkce">
|
||||
{t("ui.dev.clients.type.pkce", "PKCE")}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-xs font-bold uppercase tracking-wider text-muted-foreground whitespace-nowrap">
|
||||
{t("ui.dev.clients.consents.status_label", "Status:")}
|
||||
</span>
|
||||
<select
|
||||
className="h-9 min-w-[140px] rounded-md border border-input bg-background px-3 text-sm focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/30"
|
||||
value={statusFilter}
|
||||
onChange={(e) => setStatusFilter(e.target.value)}
|
||||
>
|
||||
<option value="all">
|
||||
{t("ui.dev.clients.filter.status_all", "모든 상태")}
|
||||
</option>
|
||||
<option value="active">
|
||||
{t("ui.common.status.active", "Active")}
|
||||
</option>
|
||||
<option value="inactive">
|
||||
{t("ui.common.status.inactive", "Inactive")}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="ml-auto text-xs text-muted-foreground"
|
||||
onClick={() => {
|
||||
setTypeFilter("all");
|
||||
setStatusFilter("all");
|
||||
}}
|
||||
<div className="flex flex-wrap items-center gap-6">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-xs font-bold uppercase tracking-wider text-muted-foreground whitespace-nowrap">
|
||||
{t("ui.dev.clients.filter.type_label", "Type:")}
|
||||
</span>
|
||||
<select
|
||||
className="h-9 min-w-[140px] rounded-md border border-input bg-background px-3 text-sm focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/30"
|
||||
value={typeFilter}
|
||||
onChange={(e) => setTypeFilter(e.target.value)}
|
||||
>
|
||||
{t("ui.common.reset", "초기화")}
|
||||
</Button>
|
||||
<option value="all">
|
||||
{t("ui.dev.clients.filter.type_all", "모든 유형")}
|
||||
</option>
|
||||
<option value="private">
|
||||
{t("ui.dev.clients.type.private", "Server side App")}
|
||||
</option>
|
||||
<option value="pkce">
|
||||
{t("ui.dev.clients.type.pkce", "PKCE")}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-xs font-bold uppercase tracking-wider text-muted-foreground whitespace-nowrap">
|
||||
{t("ui.dev.clients.consents.status_label", "Status:")}
|
||||
</span>
|
||||
<select
|
||||
className="h-9 min-w-[140px] rounded-md border border-input bg-background px-3 text-sm focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/30"
|
||||
value={statusFilter}
|
||||
onChange={(e) => setStatusFilter(e.target.value)}
|
||||
>
|
||||
<option value="all">
|
||||
{t("ui.dev.clients.filter.status_all", "모든 상태")}
|
||||
</option>
|
||||
<option value="active">
|
||||
{t("ui.common.status.active", "Active")}
|
||||
</option>
|
||||
<option value="inactive">
|
||||
{t("ui.common.status.inactive", "Inactive")}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="ml-auto text-xs text-muted-foreground"
|
||||
onClick={() => {
|
||||
setTypeFilter("all");
|
||||
setStatusFilter("all");
|
||||
}}
|
||||
>
|
||||
{t("ui.common.reset", "초기화")}
|
||||
</Button>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
</CardHeader>
|
||||
|
||||
@@ -345,7 +345,8 @@ describe("org chart layout", () => {
|
||||
|
||||
it("keeps zoom limits wide enough for large SVG organization charts", () => {
|
||||
expect(clampScale(0.08)).toBe(0.08);
|
||||
expect(clampScale(5)).toBe(5);
|
||||
expect(clampScale(32)).toBe(32);
|
||||
expect(clampScale(64)).toBe(32);
|
||||
});
|
||||
|
||||
it("switches semantic zoom modes from overview to detail", () => {
|
||||
|
||||
@@ -107,7 +107,7 @@ const WIDE_ASPECT_RATIO = MAX_TARGET_ASPECT_RATIO;
|
||||
const TALL_ASPECT_RATIO = 0.5;
|
||||
const CHART_MARGIN = 72;
|
||||
const MIN_SCALE = 0.08;
|
||||
const MAX_SCALE = 5;
|
||||
const MAX_SCALE = 32;
|
||||
const ZOOM_SENSITIVITY = 0.0015;
|
||||
const FAMILY_FILTER_ID = "hanmac-family";
|
||||
const DEFAULT_LAYOUT_OPTIONS: OrgChartLayoutOptions = {
|
||||
|
||||
@@ -14,7 +14,7 @@ const allowedHosts = getAllowedHosts(
|
||||
"127.0.0.1",
|
||||
],
|
||||
process.env.ORGFRONT_URL,
|
||||
process.env.ORGFRONT_ALLOWED_HOSTS
|
||||
process.env.ORGFRONT_ALLOWED_HOSTS,
|
||||
);
|
||||
|
||||
export default defineConfig(
|
||||
@@ -47,5 +47,5 @@ export default defineConfig(
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -111,7 +111,7 @@ function resolvePerformanceBudget(projectName: string): {
|
||||
if (projectName.includes('mobile')) {
|
||||
return { coldMs: 3000, warmMs: 1500 };
|
||||
}
|
||||
return { coldMs: 1700, warmMs: 1200 };
|
||||
return { coldMs: 2300, warmMs: 1500 };
|
||||
}
|
||||
|
||||
test.describe('UserFront login performance budget', () => {
|
||||
|
||||
@@ -70,15 +70,17 @@ async function fillAt(page: Page, x: number, y: number, value: string): Promise<
|
||||
}
|
||||
|
||||
async function openDepartmentEditor(page: Page): Promise<void> {
|
||||
if (isMobileProject(page)) {
|
||||
await enableFlutterAccessibility(page);
|
||||
await page
|
||||
.getByRole('group', { name: '소속 QA' })
|
||||
.getByRole('button', { name: '편집' })
|
||||
.click({ force: true });
|
||||
const accessibleEditor = page
|
||||
.getByRole('group', { name: '소속 QA' })
|
||||
.getByRole('button', { name: '편집' });
|
||||
if ((await accessibleEditor.count()) > 0) {
|
||||
await accessibleEditor.click({ force: true });
|
||||
await page.waitForTimeout(200);
|
||||
return;
|
||||
}
|
||||
if (isMobileProject(page)) {
|
||||
throw new Error('Department editor accessibility button was not found.');
|
||||
}
|
||||
const coords = coordsFor(page);
|
||||
await page.locator('flt-glass-pane').click({
|
||||
position: { x: coords.departmentEditX, y: coords.departmentEditY },
|
||||
@@ -88,11 +90,15 @@ async function openDepartmentEditor(page: Page): Promise<void> {
|
||||
}
|
||||
|
||||
async function blurDepartmentEditor(page: Page): Promise<void> {
|
||||
if (isMobileProject(page)) {
|
||||
await page.getByRole('textbox', { name: '소속' }).blur();
|
||||
const textbox = page.getByRole('textbox', { name: '소속' });
|
||||
if ((await textbox.count()) > 0) {
|
||||
await textbox.blur();
|
||||
await page.waitForTimeout(250);
|
||||
return;
|
||||
}
|
||||
if (isMobileProject(page)) {
|
||||
throw new Error('Department textbox was not found.');
|
||||
}
|
||||
const coords = coordsFor(page);
|
||||
await page.locator('flt-glass-pane').click({
|
||||
position: { x: coords.blurX, y: coords.blurY },
|
||||
@@ -102,20 +108,28 @@ async function blurDepartmentEditor(page: Page): Promise<void> {
|
||||
}
|
||||
|
||||
async function submitDepartmentEditor(page: Page): Promise<void> {
|
||||
if (isMobileProject(page)) {
|
||||
await page.getByRole('textbox', { name: '소속' }).press('Enter');
|
||||
const textbox = page.getByRole('textbox', { name: '소속' });
|
||||
if ((await textbox.count()) > 0) {
|
||||
await textbox.press('Enter');
|
||||
await page.waitForTimeout(250);
|
||||
return;
|
||||
}
|
||||
if (isMobileProject(page)) {
|
||||
throw new Error('Department textbox was not found.');
|
||||
}
|
||||
await page.keyboard.press('Enter');
|
||||
await page.waitForTimeout(250);
|
||||
}
|
||||
|
||||
async function fillDepartmentField(page: Page, value: string): Promise<void> {
|
||||
if (isMobileProject(page)) {
|
||||
await page.getByRole('textbox', { name: '소속' }).fill(value);
|
||||
const textbox = page.getByRole('textbox', { name: '소속' });
|
||||
if ((await textbox.count()) > 0) {
|
||||
await textbox.fill(value);
|
||||
return;
|
||||
}
|
||||
if (isMobileProject(page)) {
|
||||
throw new Error('Department textbox was not found.');
|
||||
}
|
||||
const coords = coordsFor(page);
|
||||
await fillAt(page, coords.departmentInputX, coords.departmentInputY, value);
|
||||
}
|
||||
@@ -216,6 +230,7 @@ async function mockProfileApis(page: Page, state: ProfileState): Promise<void> {
|
||||
async function openProfilePage(page: Page): Promise<void> {
|
||||
await page.goto('/ko/profile');
|
||||
await expect(page).toHaveURL(/\/ko\/profile$/);
|
||||
await enableFlutterAccessibility(page);
|
||||
await page.waitForTimeout(1200);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ import 'dart:async';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:easy_localization/easy_localization.dart' hide tr;
|
||||
@@ -162,20 +161,10 @@ bool _shouldRunStartupSessionRecovery(Uri uri) {
|
||||
return !isPublicAuthPath(path, uri);
|
||||
}
|
||||
|
||||
Future<void> _loadRuntimeEnv() async {
|
||||
for (final fileName in const ['assets/.env', '.env']) {
|
||||
try {
|
||||
await dotenv.load(fileName: fileName);
|
||||
return;
|
||||
} catch (_) {}
|
||||
}
|
||||
}
|
||||
|
||||
void main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
usePathUrlStrategy();
|
||||
await EasyLocalization.ensureInitialized();
|
||||
await _loadRuntimeEnv();
|
||||
LocaleRegistry.primeWithDefaults();
|
||||
|
||||
// 1. Global Error Handling
|
||||
|
||||
@@ -45,10 +45,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: characters
|
||||
sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
|
||||
sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
version: "1.4.1"
|
||||
cli_config:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -276,14 +276,6 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.5"
|
||||
js:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: js
|
||||
sha256: "53385261521cc4a0c4658fd0ad07a7d14591cf8fc33abbceae306ddb974888dc"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.2"
|
||||
leak_tracker:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -336,18 +328,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
|
||||
sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.12.17"
|
||||
version: "0.12.19"
|
||||
material_color_utilities:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: material_color_utilities
|
||||
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
|
||||
sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.11.1"
|
||||
version: "0.13.0"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -669,26 +661,26 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test
|
||||
sha256: "75906bf273541b676716d1ca7627a17e4c4070a3a16272b7a3dc7da3b9f3f6b7"
|
||||
sha256: "280d6d890011ca966ad08df7e8a4ddfab0fb3aa49f96ed6de56e3521347a9ae7"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.26.3"
|
||||
version: "1.30.0"
|
||||
test_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55
|
||||
sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.7"
|
||||
version: "0.7.10"
|
||||
test_core:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_core
|
||||
sha256: "0cc24b5ff94b38d2ae73e1eb43cc302b77964fbf67abad1e296025b78deb53d0"
|
||||
sha256: "0381bd1585d1a924763c308100f2138205252fb90c9d4eeaf28489ee65ccde51"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.12"
|
||||
version: "0.6.16"
|
||||
toml:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
||||
Reference in New Issue
Block a user