Feat/Added Matcher
This commit is contained in:
parent
277c7e15b9
commit
22614417b1
@ -1,6 +1,7 @@
|
||||
import { AUTH_COOKIE_NAME, BE_BASE_URL } from "@/app/services/constants";
|
||||
import { NextResponse } from "next/server";
|
||||
import { decodeJwt } from "jose";
|
||||
import { JWTPayload } from "@/app/utils/auth";
|
||||
|
||||
export async function POST(request: Request) {
|
||||
try {
|
||||
@ -21,15 +22,8 @@ export async function POST(request: Request) {
|
||||
// Check MustChangePassword flag from current token
|
||||
let mustChangePassword = false;
|
||||
try {
|
||||
const payload = decodeJwt(token);
|
||||
const mustChangeClaim = payload.MustChangePassword;
|
||||
if (typeof mustChangeClaim === "boolean") {
|
||||
mustChangePassword = mustChangeClaim;
|
||||
} else if (typeof mustChangeClaim === "string") {
|
||||
mustChangePassword = mustChangeClaim.toLowerCase() === "true";
|
||||
} else {
|
||||
mustChangePassword = false;
|
||||
}
|
||||
const payload = decodeJwt<JWTPayload>(token);
|
||||
mustChangePassword = payload.MustChangePassword;
|
||||
} catch (err) {
|
||||
console.error("❌ Failed to decode current JWT:", err);
|
||||
}
|
||||
@ -89,7 +83,7 @@ export async function POST(request: Request) {
|
||||
// Derive maxAge from JWT exp if available; fallback to 12h
|
||||
let maxAge = 60 * 60 * 12;
|
||||
try {
|
||||
const payload = decodeJwt(newToken);
|
||||
const payload = decodeJwt<JWTPayload>(newToken);
|
||||
if (payload?.exp) {
|
||||
const secondsLeft = payload.exp - Math.floor(Date.now() / 1000);
|
||||
if (secondsLeft > 0) maxAge = secondsLeft;
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import { AUTH_COOKIE_NAME, BE_BASE_URL } from "@/app/services/constants";
|
||||
import { NextResponse } from "next/server";
|
||||
import { cookies } from "next/headers";
|
||||
import { decodeJwt } from "jose";
|
||||
import { AUTH_COOKIE_NAME, BE_BASE_URL } from "@/app/services/constants";
|
||||
import { JWTPayload } from "@/app/utils/auth";
|
||||
|
||||
export async function POST(request: Request) {
|
||||
try {
|
||||
@ -14,8 +15,6 @@ export async function POST(request: Request) {
|
||||
body: JSON.stringify({ email, password }),
|
||||
});
|
||||
|
||||
console.log("[LOGIN] resp", resp);
|
||||
|
||||
if (!resp.ok) {
|
||||
const errJson = await safeJson(resp);
|
||||
return NextResponse.json(
|
||||
@ -39,7 +38,7 @@ export async function POST(request: Request) {
|
||||
let maxAge = 60 * 60 * 12; // fallback to 12h
|
||||
|
||||
try {
|
||||
const payload = decodeJwt(token);
|
||||
const payload = decodeJwt<JWTPayload>(token);
|
||||
|
||||
// Extract exp if present
|
||||
if (payload?.exp) {
|
||||
|
||||
55
app/dashboard/admin/matcher/MatcherBoard/DraggableItem.tsx
Normal file
55
app/dashboard/admin/matcher/MatcherBoard/DraggableItem.tsx
Normal file
@ -0,0 +1,55 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import { useDraggable } from "@dnd-kit/core";
|
||||
import { CSS } from "@dnd-kit/utilities";
|
||||
import { Card, CardContent, Typography } from "@mui/material";
|
||||
import { DraggableItemProps } from "../types";
|
||||
|
||||
export function DraggableItem({ item, isDragging }: DraggableItemProps) {
|
||||
const {
|
||||
attributes,
|
||||
listeners,
|
||||
setNodeRef,
|
||||
transform,
|
||||
isDragging: isItemDragging,
|
||||
} = useDraggable({
|
||||
id: item.id,
|
||||
});
|
||||
|
||||
const style = {
|
||||
transform: CSS.Translate.toString(transform),
|
||||
opacity: isItemDragging || isDragging ? 0.5 : 1,
|
||||
};
|
||||
|
||||
return (
|
||||
<Card
|
||||
ref={setNodeRef}
|
||||
style={style}
|
||||
{...attributes}
|
||||
{...listeners}
|
||||
className="matcher-board__item"
|
||||
sx={{
|
||||
mb: 1,
|
||||
cursor: "grab",
|
||||
"&:active": {
|
||||
cursor: "grabbing",
|
||||
},
|
||||
"&:hover": {
|
||||
boxShadow: 3,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<CardContent sx={{ p: 1.5, "&:last-child": { pb: 1.5 } }}>
|
||||
<Typography variant="body2" fontWeight={500}>
|
||||
{item.name}
|
||||
</Typography>
|
||||
{item.id && (
|
||||
<Typography variant="caption" color="text.secondary">
|
||||
ID: {item.id}
|
||||
</Typography>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
80
app/dashboard/admin/matcher/MatcherBoard/DroppableColumn.tsx
Normal file
80
app/dashboard/admin/matcher/MatcherBoard/DroppableColumn.tsx
Normal file
@ -0,0 +1,80 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import { useDroppable } from "@dnd-kit/core";
|
||||
import { Box, Typography, Chip } from "@mui/material";
|
||||
import { DroppableColumnProps } from "../types";
|
||||
import { DraggableItem } from "./DraggableItem";
|
||||
|
||||
export function DroppableColumn({
|
||||
id,
|
||||
title,
|
||||
items,
|
||||
activeId,
|
||||
}: DroppableColumnProps) {
|
||||
const { setNodeRef, isOver } = useDroppable({
|
||||
id,
|
||||
});
|
||||
|
||||
return (
|
||||
<Box
|
||||
ref={setNodeRef}
|
||||
className="matcher-board__column"
|
||||
sx={{
|
||||
flex: 1,
|
||||
minWidth: 300,
|
||||
maxWidth: 400,
|
||||
bgcolor: isOver ? "action.hover" : "background.paper",
|
||||
borderRadius: 2,
|
||||
p: 2,
|
||||
border: "2px solid",
|
||||
borderColor: isOver ? "primary.main" : "divider",
|
||||
transition: "all 0.2s ease",
|
||||
}}
|
||||
>
|
||||
<Typography variant="h6" sx={{ mb: 2, fontWeight: 600 }}>
|
||||
{title}
|
||||
</Typography>
|
||||
<Box
|
||||
className="matcher-board__column-content"
|
||||
sx={{
|
||||
minHeight: 400,
|
||||
maxHeight: 600,
|
||||
overflowY: "auto",
|
||||
}}
|
||||
>
|
||||
{items.map(item => (
|
||||
<DraggableItem
|
||||
key={item.id}
|
||||
item={item}
|
||||
isDragging={activeId === item.id}
|
||||
/>
|
||||
))}
|
||||
{items.length === 0 && (
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
minHeight: 200,
|
||||
border: "2px dashed",
|
||||
borderColor: "divider",
|
||||
borderRadius: 1,
|
||||
}}
|
||||
>
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
Drop items here
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
<Chip
|
||||
label={`${items.length} items`}
|
||||
size="small"
|
||||
sx={{ mt: 2 }}
|
||||
color="primary"
|
||||
variant="outlined"
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
36
app/dashboard/admin/matcher/MatcherBoard/MatcherBoard.scss
Normal file
36
app/dashboard/admin/matcher/MatcherBoard/MatcherBoard.scss
Normal file
@ -0,0 +1,36 @@
|
||||
.matcher-board {
|
||||
&__column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
&__column-content {
|
||||
&::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
background: #f1f1f1;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: #888;
|
||||
border-radius: 4px;
|
||||
|
||||
&:hover {
|
||||
background: #555;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__item {
|
||||
transition:
|
||||
transform 0.2s ease,
|
||||
box-shadow 0.2s ease;
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
}
|
||||
}
|
||||
125
app/dashboard/admin/matcher/MatcherBoard/MatcherBoard.tsx
Normal file
125
app/dashboard/admin/matcher/MatcherBoard/MatcherBoard.tsx
Normal file
@ -0,0 +1,125 @@
|
||||
"use client";
|
||||
|
||||
import React, { useState } from "react";
|
||||
import {
|
||||
DndContext,
|
||||
DragEndEvent,
|
||||
DragOverlay,
|
||||
DragStartEvent,
|
||||
PointerSensor,
|
||||
useSensor,
|
||||
useSensors,
|
||||
closestCenter,
|
||||
} from "@dnd-kit/core";
|
||||
import { Box, Card, CardContent, Typography } from "@mui/material";
|
||||
import { MatcherBoardProps } from "../types";
|
||||
import { DroppableColumn } from "./DroppableColumn";
|
||||
import { findActiveItem, isItemInSource, addItemIfNotPresent } from "../utils";
|
||||
import "./MatcherBoard.scss";
|
||||
|
||||
export default function MatcherBoard({
|
||||
sourceItems: initialSourceItems,
|
||||
targetItems: initialTargetItems,
|
||||
config,
|
||||
onMatch,
|
||||
}: MatcherBoardProps) {
|
||||
const [sourceItems, setSourceItems] = useState(initialSourceItems);
|
||||
const [targetItems, setTargetItems] = useState(initialTargetItems);
|
||||
const [activeId, setActiveId] = useState<string | null>(null);
|
||||
|
||||
const sensors = useSensors(
|
||||
useSensor(PointerSensor, {
|
||||
activationConstraint: {
|
||||
distance: 8,
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
const handleDragStart = (event: DragStartEvent) => {
|
||||
setActiveId(String(event.active.id));
|
||||
};
|
||||
|
||||
const handleDragEnd = (event: DragEndEvent) => {
|
||||
const { active, over } = event;
|
||||
setActiveId(null);
|
||||
|
||||
if (!over) return;
|
||||
|
||||
const activeId = String(active.id);
|
||||
const overId = String(over.id);
|
||||
|
||||
const activeItem = findActiveItem(sourceItems, targetItems, activeId);
|
||||
if (!activeItem) return;
|
||||
|
||||
const activeIsSource = isItemInSource(sourceItems, activeId);
|
||||
const droppedOnSource = overId === "source";
|
||||
const droppedOnTarget = overId === "target";
|
||||
|
||||
// If dragging from source to target column
|
||||
if (activeIsSource && droppedOnTarget) {
|
||||
setSourceItems(prev => prev.filter(item => item.id !== activeId));
|
||||
setTargetItems(prev => addItemIfNotPresent(prev, activeItem));
|
||||
|
||||
if (onMatch) {
|
||||
onMatch(activeId, "target");
|
||||
}
|
||||
} else if (!activeIsSource && droppedOnSource) {
|
||||
setTargetItems(prev => prev.filter(item => item.id !== activeId));
|
||||
setSourceItems(prev => addItemIfNotPresent(prev, activeItem));
|
||||
}
|
||||
};
|
||||
|
||||
const activeItem = activeId
|
||||
? findActiveItem(sourceItems, targetItems, activeId)
|
||||
: null;
|
||||
|
||||
return (
|
||||
<DndContext
|
||||
sensors={sensors}
|
||||
collisionDetection={closestCenter}
|
||||
onDragStart={handleDragStart}
|
||||
onDragEnd={handleDragEnd}
|
||||
>
|
||||
<Box
|
||||
className="matcher-board"
|
||||
sx={{
|
||||
display: "flex",
|
||||
gap: 3,
|
||||
p: 3,
|
||||
width: "100%",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
>
|
||||
<DroppableColumn
|
||||
id="source"
|
||||
title={config.sourceLabel}
|
||||
items={sourceItems}
|
||||
activeId={activeId}
|
||||
/>
|
||||
<DroppableColumn
|
||||
id="target"
|
||||
title={config.targetLabel}
|
||||
items={targetItems}
|
||||
activeId={activeId}
|
||||
/>
|
||||
</Box>
|
||||
<DragOverlay>
|
||||
{activeItem ? (
|
||||
<Card
|
||||
sx={{
|
||||
width: 250,
|
||||
boxShadow: 6,
|
||||
transform: "rotate(5deg)",
|
||||
}}
|
||||
>
|
||||
<CardContent sx={{ p: 1.5, "&:last-child": { pb: 1.5 } }}>
|
||||
<Typography variant="body2" fontWeight={500}>
|
||||
{activeItem.name}
|
||||
</Typography>
|
||||
</CardContent>
|
||||
</Card>
|
||||
) : null}
|
||||
</DragOverlay>
|
||||
</DndContext>
|
||||
);
|
||||
}
|
||||
109
app/dashboard/admin/matcher/MatcherPageClient.tsx
Normal file
109
app/dashboard/admin/matcher/MatcherPageClient.tsx
Normal file
@ -0,0 +1,109 @@
|
||||
"use client";
|
||||
|
||||
import React, { useState, useCallback } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import {
|
||||
Box,
|
||||
Typography,
|
||||
Select,
|
||||
MenuItem,
|
||||
FormControl,
|
||||
InputLabel,
|
||||
Alert,
|
||||
} from "@mui/material";
|
||||
import MatcherBoard from "./MatcherBoard/MatcherBoard";
|
||||
import { MATCH_CONFIGS } from "./constants";
|
||||
import { MatchableEntity, MatchConfig } from "./types";
|
||||
import toast from "react-hot-toast";
|
||||
|
||||
interface MatcherPageClientProps {
|
||||
initialSourceItems: MatchableEntity[];
|
||||
initialTargetItems: MatchableEntity[];
|
||||
initialMatchType: string;
|
||||
config: MatchConfig;
|
||||
}
|
||||
|
||||
export default function MatcherPageClient({
|
||||
initialSourceItems,
|
||||
initialTargetItems,
|
||||
initialMatchType,
|
||||
config: initialConfig,
|
||||
}: MatcherPageClientProps) {
|
||||
const router = useRouter();
|
||||
const [matchType, setMatchType] = useState(initialMatchType);
|
||||
const [sourceItems, setSourceItems] = useState(initialSourceItems);
|
||||
const [targetItems, setTargetItems] = useState(initialTargetItems);
|
||||
|
||||
const currentConfig = MATCH_CONFIGS[matchType] || initialConfig;
|
||||
|
||||
const handleMatchTypeChange = (newType: string) => {
|
||||
setMatchType(newType);
|
||||
// Update URL and reload page to fetch new data via SSR
|
||||
router.push(`/dashboard/admin/matcher?type=${newType}`);
|
||||
router.refresh();
|
||||
};
|
||||
|
||||
const handleMatch = useCallback(
|
||||
async (sourceId: string, targetId: string) => {
|
||||
try {
|
||||
// TODO: Call API endpoint to save the match
|
||||
// For now, just show a toast
|
||||
toast.success(
|
||||
`Matched ${currentConfig.sourceLabel} to ${currentConfig.targetLabel}`
|
||||
);
|
||||
console.log("Match:", {
|
||||
sourceId,
|
||||
targetId,
|
||||
matchType,
|
||||
});
|
||||
} catch (error) {
|
||||
toast.error("Failed to save match");
|
||||
console.error("Error saving match:", error);
|
||||
}
|
||||
},
|
||||
[currentConfig, matchType]
|
||||
);
|
||||
|
||||
return (
|
||||
<Box sx={{ p: 3, width: "100%" }}>
|
||||
<Box
|
||||
sx={{
|
||||
mb: 3,
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<Typography variant="h4" sx={{ fontWeight: 600 }}>
|
||||
Entity Matcher
|
||||
</Typography>
|
||||
<FormControl sx={{ minWidth: 250 }}>
|
||||
<InputLabel>Match Type</InputLabel>
|
||||
<Select
|
||||
value={matchType}
|
||||
label="Match Type"
|
||||
onChange={e => handleMatchTypeChange(e.target.value)}
|
||||
>
|
||||
{Object.entries(MATCH_CONFIGS).map(([key, config]) => (
|
||||
<MenuItem key={key} value={key}>
|
||||
{config.sourceLabel} → {config.targetLabel}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
</Box>
|
||||
|
||||
<Alert severity="info" sx={{ mb: 3 }}>
|
||||
Drag items from the left column to the right column to create matches.
|
||||
You can also drag items back to remove matches.
|
||||
</Alert>
|
||||
|
||||
<MatcherBoard
|
||||
sourceItems={sourceItems}
|
||||
targetItems={targetItems}
|
||||
config={currentConfig}
|
||||
onMatch={handleMatch}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
48
app/dashboard/admin/matcher/constants.ts
Normal file
48
app/dashboard/admin/matcher/constants.ts
Normal file
@ -0,0 +1,48 @@
|
||||
import { MatchConfig } from "./types";
|
||||
|
||||
export const MATCH_CONFIGS: Record<string, MatchConfig> = {
|
||||
"permissions-to-groups": {
|
||||
type: "permissions-to-groups",
|
||||
sourceLabel: "Permissions",
|
||||
targetLabel: "Groups",
|
||||
sourceEndpoint: "/api/dashboard/admin/permissions",
|
||||
targetEndpoint: "/api/dashboard/admin/groups",
|
||||
sourceCollectionKeys: ["permissions", "data", "items"],
|
||||
targetCollectionKeys: ["groups", "data", "items"],
|
||||
sourcePrimaryKey: "name",
|
||||
targetPrimaryKey: "name",
|
||||
},
|
||||
"methods-to-psp": {
|
||||
type: "methods-to-psp",
|
||||
sourceLabel: "Methods",
|
||||
targetLabel: "PSPs",
|
||||
sourceEndpoint: "/api/dashboard/admin/methods",
|
||||
targetEndpoint: "/api/dashboard/admin/psps",
|
||||
sourceCollectionKeys: ["methods", "data", "items"],
|
||||
targetCollectionKeys: ["psps", "data", "items"],
|
||||
sourcePrimaryKey: "name",
|
||||
targetPrimaryKey: "name",
|
||||
},
|
||||
"psp-to-merchant": {
|
||||
type: "psp-to-merchant",
|
||||
sourceLabel: "PSPs",
|
||||
targetLabel: "Merchants",
|
||||
sourceEndpoint: "/api/dashboard/admin/psps",
|
||||
targetEndpoint: "/api/dashboard/admin/merchants",
|
||||
sourceCollectionKeys: ["psps", "data", "items"],
|
||||
targetCollectionKeys: ["merchants", "data", "items"],
|
||||
sourcePrimaryKey: "name",
|
||||
targetPrimaryKey: "name",
|
||||
},
|
||||
"groups-to-users": {
|
||||
type: "groups-to-users",
|
||||
sourceLabel: "Groups",
|
||||
targetLabel: "Users",
|
||||
sourceEndpoint: "/api/dashboard/admin/groups",
|
||||
targetEndpoint: "/api/dashboard/admin/users",
|
||||
sourceCollectionKeys: ["groups", "data", "items"],
|
||||
targetCollectionKeys: ["users", "data", "items"],
|
||||
sourcePrimaryKey: "name",
|
||||
targetPrimaryKey: "email",
|
||||
},
|
||||
};
|
||||
42
app/dashboard/admin/matcher/page.tsx
Normal file
42
app/dashboard/admin/matcher/page.tsx
Normal file
@ -0,0 +1,42 @@
|
||||
import { cookies } from "next/headers";
|
||||
import MatcherPageClient from "./MatcherPageClient";
|
||||
import { MATCH_CONFIGS } from "./constants";
|
||||
import { getMatcherData } from "@/app/services/matcher";
|
||||
import { getBaseUrl } from "@/app/services/constants";
|
||||
|
||||
export default async function MatcherPage({
|
||||
searchParams,
|
||||
}: {
|
||||
searchParams: Promise<Record<string, string | string[] | undefined>>;
|
||||
}) {
|
||||
const params = await searchParams;
|
||||
const matchType =
|
||||
(params.type as string) || Object.keys(MATCH_CONFIGS)[0] || "";
|
||||
|
||||
const baseUrl = getBaseUrl();
|
||||
|
||||
// Forward cookies for auth when calling the internal API route
|
||||
const cookieStore = await cookies();
|
||||
const cookieHeader = cookieStore
|
||||
.getAll()
|
||||
.map((c: { name: string; value: string }) => `${c.name}=${c.value}`)
|
||||
.join("; ");
|
||||
|
||||
const { sourceItems, targetItems } = await getMatcherData(
|
||||
matchType,
|
||||
cookieHeader,
|
||||
baseUrl
|
||||
);
|
||||
|
||||
const config =
|
||||
MATCH_CONFIGS[matchType] || MATCH_CONFIGS[Object.keys(MATCH_CONFIGS)[0]];
|
||||
|
||||
return (
|
||||
<MatcherPageClient
|
||||
initialSourceItems={sourceItems}
|
||||
initialTargetItems={targetItems}
|
||||
initialMatchType={matchType}
|
||||
config={config}
|
||||
/>
|
||||
);
|
||||
}
|
||||
58
app/dashboard/admin/matcher/types.ts
Normal file
58
app/dashboard/admin/matcher/types.ts
Normal file
@ -0,0 +1,58 @@
|
||||
type MatchType =
|
||||
| "permissions-to-groups"
|
||||
| "methods-to-psp"
|
||||
| "psp-to-merchant"
|
||||
| "groups-to-users";
|
||||
|
||||
interface MatchableEntity {
|
||||
id: string | number;
|
||||
name: string;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
interface MatchColumn {
|
||||
id: string;
|
||||
title: string;
|
||||
items: MatchableEntity[];
|
||||
}
|
||||
|
||||
interface MatchConfig {
|
||||
type: MatchType;
|
||||
sourceLabel: string;
|
||||
targetLabel: string;
|
||||
sourceEndpoint: string;
|
||||
targetEndpoint: string;
|
||||
sourceCollectionKeys?: string[];
|
||||
targetCollectionKeys?: string[];
|
||||
sourcePrimaryKey?: string;
|
||||
targetPrimaryKey?: string;
|
||||
}
|
||||
|
||||
interface MatcherBoardProps {
|
||||
sourceItems: MatchableEntity[];
|
||||
targetItems: MatchableEntity[];
|
||||
config: MatchConfig;
|
||||
onMatch?: (sourceId: string, targetId: string) => void;
|
||||
}
|
||||
|
||||
interface DraggableItemProps {
|
||||
item: MatchableEntity;
|
||||
isDragging?: boolean;
|
||||
}
|
||||
|
||||
interface DroppableColumnProps {
|
||||
id: string;
|
||||
title: string;
|
||||
items: MatchableEntity[];
|
||||
activeId: string | null;
|
||||
}
|
||||
|
||||
export type {
|
||||
MatchType,
|
||||
MatchableEntity,
|
||||
MatchColumn,
|
||||
MatchConfig,
|
||||
MatcherBoardProps,
|
||||
DraggableItemProps,
|
||||
DroppableColumnProps,
|
||||
};
|
||||
72
app/dashboard/admin/matcher/utils.ts
Normal file
72
app/dashboard/admin/matcher/utils.ts
Normal file
@ -0,0 +1,72 @@
|
||||
import { MatchableEntity } from "./types";
|
||||
|
||||
const DEFAULT_COLLECTION_KEYS = ["data", "items"];
|
||||
|
||||
export function resolveCollection(
|
||||
payload: unknown,
|
||||
preferredKeys: string[] = []
|
||||
): Record<string, unknown>[] {
|
||||
if (typeof payload !== "object" || payload === null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const obj = payload as Record<string, unknown>;
|
||||
|
||||
for (const key of [...preferredKeys, ...DEFAULT_COLLECTION_KEYS]) {
|
||||
const maybeCollection = obj?.[key];
|
||||
if (Array.isArray(maybeCollection)) {
|
||||
return maybeCollection as Record<string, unknown>[];
|
||||
}
|
||||
}
|
||||
|
||||
if (Array.isArray(payload)) {
|
||||
return payload as Record<string, unknown>[];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
export function normalizeEntity(
|
||||
item: Record<string, unknown>,
|
||||
primaryKey: string = "name",
|
||||
fallbackId: number
|
||||
): MatchableEntity {
|
||||
const id = item.id ?? item._id ?? fallbackId;
|
||||
const name =
|
||||
(item[primaryKey] as string) ||
|
||||
(item.name as string) ||
|
||||
(item.title as string) ||
|
||||
(item.email as string) ||
|
||||
`Item ${id}`;
|
||||
|
||||
return {
|
||||
id: String(id),
|
||||
name: String(name),
|
||||
...item,
|
||||
};
|
||||
}
|
||||
|
||||
export function findActiveItem(
|
||||
sourceItems: MatchableEntity[],
|
||||
targetItems: MatchableEntity[],
|
||||
activeId: string
|
||||
): MatchableEntity | undefined {
|
||||
return [...sourceItems, ...targetItems].find(item => item.id === activeId);
|
||||
}
|
||||
|
||||
export function isItemInSource(
|
||||
sourceItems: MatchableEntity[],
|
||||
activeId: string
|
||||
): boolean {
|
||||
return sourceItems.some(item => item.id === activeId);
|
||||
}
|
||||
|
||||
export function addItemIfNotPresent(
|
||||
items: MatchableEntity[],
|
||||
item: MatchableEntity
|
||||
): MatchableEntity[] {
|
||||
if (items.some(existingItem => existingItem.id === item.id)) {
|
||||
return items;
|
||||
}
|
||||
return [...items, item];
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
import Users from "@/app/features/Pages/Admin/Users/users";
|
||||
import { cookies } from "next/headers";
|
||||
import { getBaseUrl } from "@/app/services/constants";
|
||||
|
||||
export default async function BackOfficeUsersPage({
|
||||
searchParams,
|
||||
@ -11,14 +12,7 @@ export default async function BackOfficeUsersPage({
|
||||
const limit = params.limit || "10";
|
||||
const page = params.page || "1";
|
||||
|
||||
// Build absolute URL for server-side fetch
|
||||
// In server components, fetch requires absolute URLs
|
||||
const port = process.env.PORT || "3000";
|
||||
const baseUrl =
|
||||
process.env.NEXT_PUBLIC_BASE_URL ||
|
||||
(process.env.VERCEL_URL
|
||||
? `https://${process.env.VERCEL_URL}`
|
||||
: `http://localhost:${port}`);
|
||||
const baseUrl = getBaseUrl();
|
||||
|
||||
const url = new URL(`${baseUrl}/api/dashboard/admin/users`);
|
||||
url.searchParams.set("limit", typeof limit === "string" ? limit : limit[0]);
|
||||
|
||||
@ -1,6 +1,12 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import {
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useState,
|
||||
useTransition,
|
||||
} from "react";
|
||||
import {
|
||||
DataGrid,
|
||||
GridColDef,
|
||||
@ -9,13 +15,16 @@ import {
|
||||
} from "@mui/x-data-grid";
|
||||
import TextField from "@mui/material/TextField";
|
||||
import { Box, debounce } from "@mui/material";
|
||||
import useSWR from "swr";
|
||||
import { getAudits } from "@/app/services/audits";
|
||||
import { usePathname, useRouter, useSearchParams } from "next/navigation";
|
||||
|
||||
import { AuditRow } from "./auditTransforms";
|
||||
import { PAGE_SIZE_OPTIONS } from "./auditConstants";
|
||||
import {
|
||||
AuditQueryResult,
|
||||
AuditRow,
|
||||
DEFAULT_PAGE_SIZE,
|
||||
} from "./auditTransforms";
|
||||
buildSortParam,
|
||||
deriveColumns,
|
||||
parseSortModel,
|
||||
toTitle,
|
||||
} from "./utils";
|
||||
|
||||
const FALLBACK_COLUMNS: GridColDef[] = [
|
||||
{
|
||||
@ -27,103 +36,55 @@ const FALLBACK_COLUMNS: GridColDef[] = [
|
||||
},
|
||||
];
|
||||
|
||||
const toTitle = (field: string) =>
|
||||
field
|
||||
.replace(/_/g, " ")
|
||||
.replace(/-/g, " ")
|
||||
.replace(/([a-z])([A-Z])/g, "$1 $2")
|
||||
.replace(/\s+/g, " ")
|
||||
.trim()
|
||||
.replace(/^\w/g, char => char.toUpperCase());
|
||||
|
||||
const deriveColumns = (rows: AuditRow[]): GridColDef[] => {
|
||||
if (!rows.length) return [];
|
||||
|
||||
return Object.keys(rows[0]).map(field => ({
|
||||
field,
|
||||
headerName: toTitle(field),
|
||||
flex: field === "id" ? 0 : 1,
|
||||
minWidth: field === "id" ? 140 : 200,
|
||||
sortable: true,
|
||||
}));
|
||||
};
|
||||
|
||||
interface AuditTableClientProps {
|
||||
initialData: AuditQueryResult;
|
||||
rows: AuditRow[];
|
||||
total: number;
|
||||
pageIndex: number;
|
||||
pageSize: number;
|
||||
sortParam?: string;
|
||||
entityQuery?: string;
|
||||
}
|
||||
|
||||
const ENTITY_PREFIX = "LIKE/";
|
||||
|
||||
const buildSortParam = (sortModel: GridSortModel) =>
|
||||
sortModel.length && sortModel[0].field && sortModel[0].sort
|
||||
? `${sortModel[0].field}:${sortModel[0].sort}`
|
||||
: undefined;
|
||||
|
||||
const buildEntityParam = (entitySearch: string) =>
|
||||
entitySearch.trim() ? `${ENTITY_PREFIX}${entitySearch.trim()}` : undefined;
|
||||
|
||||
export default function AuditTableClient({
|
||||
initialData,
|
||||
rows,
|
||||
total,
|
||||
pageIndex,
|
||||
pageSize,
|
||||
sortParam,
|
||||
entityQuery = "",
|
||||
}: AuditTableClientProps) {
|
||||
const [paginationModel, setPaginationModel] = useState<GridPaginationModel>({
|
||||
page: initialData.pageIndex ?? 0,
|
||||
pageSize: DEFAULT_PAGE_SIZE,
|
||||
});
|
||||
const [sortModel, setSortModel] = useState<GridSortModel>([]);
|
||||
const [entitySearch, setEntitySearch] = useState<string>("");
|
||||
const [entitySearchInput, setEntitySearchInput] = useState<string>("");
|
||||
const router = useRouter();
|
||||
const pathname = usePathname();
|
||||
const searchParams = useSearchParams();
|
||||
const searchParamsString = searchParams.toString();
|
||||
const [isNavigating, startTransition] = useTransition();
|
||||
|
||||
const [columns, setColumns] = useState<GridColDef[]>(
|
||||
initialData.rows.length ? deriveColumns(initialData.rows) : FALLBACK_COLUMNS
|
||||
);
|
||||
|
||||
const debouncedSetEntitySearch = useMemo(
|
||||
() =>
|
||||
debounce((value: string) => {
|
||||
setEntitySearch(value);
|
||||
setPaginationModel(prev => ({ ...prev, page: 0 }));
|
||||
}, 500),
|
||||
[]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
debouncedSetEntitySearch.clear();
|
||||
};
|
||||
}, [debouncedSetEntitySearch]);
|
||||
|
||||
const sortParam = useMemo(() => buildSortParam(sortModel), [sortModel]);
|
||||
const entityParam = useMemo(
|
||||
() => buildEntityParam(entitySearch),
|
||||
[entitySearch]
|
||||
);
|
||||
|
||||
const { data, error, isLoading, isValidating } = useSWR(
|
||||
[
|
||||
"audits",
|
||||
paginationModel.page,
|
||||
paginationModel.pageSize,
|
||||
sortParam ?? "",
|
||||
entityParam ?? "",
|
||||
],
|
||||
() =>
|
||||
getAudits({
|
||||
limit: paginationModel.pageSize,
|
||||
page: paginationModel.page + 1,
|
||||
sort: sortParam,
|
||||
entity: entityParam,
|
||||
// Derive values directly from props
|
||||
const paginationModel = useMemo<GridPaginationModel>(
|
||||
() => ({
|
||||
page: pageIndex,
|
||||
pageSize,
|
||||
}),
|
||||
{
|
||||
keepPreviousData: true,
|
||||
revalidateOnFocus: true,
|
||||
revalidateOnReconnect: true,
|
||||
fallbackData: initialData,
|
||||
}
|
||||
[pageIndex, pageSize]
|
||||
);
|
||||
|
||||
const rows = data?.rows ?? initialData.rows;
|
||||
const rowCount = data?.total ?? initialData.total ?? rows.length;
|
||||
const loading = isLoading || (isValidating && !rows.length);
|
||||
const sortModel = useMemo(() => parseSortModel(sortParam), [sortParam]);
|
||||
const columns = useMemo(
|
||||
() => (rows.length ? deriveColumns(rows) : FALLBACK_COLUMNS),
|
||||
[rows]
|
||||
);
|
||||
|
||||
// Only entitySearchInput needs state since it's a controlled input
|
||||
const normalizedEntityQuery = entityQuery.trim();
|
||||
const [entitySearchInput, setEntitySearchInput] = useState<string>(
|
||||
normalizedEntityQuery
|
||||
);
|
||||
|
||||
// Sync entity input when query prop changes (e.g., from URL navigation)
|
||||
useEffect(() => {
|
||||
setEntitySearchInput(normalizedEntityQuery);
|
||||
}, [normalizedEntityQuery]);
|
||||
|
||||
const pageTitle = useMemo(
|
||||
() =>
|
||||
sortModel.length && sortModel[0].field
|
||||
@ -132,32 +93,65 @@ export default function AuditTableClient({
|
||||
[sortModel]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
setColumns(prev =>
|
||||
rows.length ? deriveColumns(rows) : prev.length ? prev : FALLBACK_COLUMNS
|
||||
const navigateWithParams = useCallback(
|
||||
(updates: Record<string, string | null | undefined>) => {
|
||||
const params = new URLSearchParams(searchParamsString);
|
||||
|
||||
Object.entries(updates).forEach(([key, value]) => {
|
||||
if (!value) {
|
||||
params.delete(key);
|
||||
} else {
|
||||
params.set(key, value);
|
||||
}
|
||||
});
|
||||
|
||||
startTransition(() => {
|
||||
const queryString = params.toString();
|
||||
router.push(queryString ? `${pathname}?${queryString}` : pathname);
|
||||
});
|
||||
},
|
||||
[pathname, router, searchParamsString, startTransition]
|
||||
);
|
||||
}, [rows]);
|
||||
|
||||
const debouncedEntityNavigate = useMemo(
|
||||
() =>
|
||||
debounce((value: string) => {
|
||||
navigateWithParams({
|
||||
page: "1",
|
||||
entity: value.trim() ? value.trim() : null,
|
||||
});
|
||||
}, 500),
|
||||
[navigateWithParams]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
debouncedEntityNavigate.clear();
|
||||
};
|
||||
}, [debouncedEntityNavigate]);
|
||||
|
||||
const handlePaginationChange = (model: GridPaginationModel) => {
|
||||
setPaginationModel(model);
|
||||
navigateWithParams({
|
||||
page: String(model.page + 1),
|
||||
limit: String(model.pageSize),
|
||||
});
|
||||
};
|
||||
|
||||
const handleSortModelChange = (model: GridSortModel) => {
|
||||
setSortModel(model);
|
||||
setPaginationModel(prev => ({ ...prev, page: 0 }));
|
||||
navigateWithParams({
|
||||
page: "1",
|
||||
sort: buildSortParam(model) ?? null,
|
||||
});
|
||||
};
|
||||
|
||||
const handleEntitySearchChange = (value: string) => {
|
||||
setEntitySearchInput(value);
|
||||
debouncedSetEntitySearch(value);
|
||||
debouncedEntityNavigate(value);
|
||||
};
|
||||
|
||||
const errorMessage =
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: error
|
||||
? "Failed to load audits"
|
||||
: null;
|
||||
const loading = isNavigating;
|
||||
|
||||
console.log("LOADING", loading);
|
||||
|
||||
return (
|
||||
<div className="audits-page">
|
||||
@ -172,11 +166,6 @@ export default function AuditTableClient({
|
||||
/>
|
||||
</Box>
|
||||
<h1 className="page-title">{pageTitle}</h1>
|
||||
{errorMessage && (
|
||||
<div className="error-alert" role="alert">
|
||||
{errorMessage}
|
||||
</div>
|
||||
)}
|
||||
<div className="table-container">
|
||||
<div className="scroll-wrapper">
|
||||
<div
|
||||
@ -191,10 +180,10 @@ export default function AuditTableClient({
|
||||
sortingMode="server"
|
||||
paginationModel={paginationModel}
|
||||
onPaginationModelChange={handlePaginationChange}
|
||||
rowCount={rowCount}
|
||||
rowCount={total}
|
||||
sortModel={sortModel}
|
||||
onSortModelChange={handleSortModelChange}
|
||||
pageSizeOptions={[10, 25, 50, 100]}
|
||||
pageSizeOptions={[...PAGE_SIZE_OPTIONS]}
|
||||
disableRowSelectionOnClick
|
||||
sx={{
|
||||
border: 0,
|
||||
|
||||
2
app/dashboard/audits/auditConstants.ts
Normal file
2
app/dashboard/audits/auditConstants.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export const ENTITY_PREFIX = "LIKE/";
|
||||
export const PAGE_SIZE_OPTIONS = [10, 25, 50, 100];
|
||||
7
app/dashboard/audits/loading.tsx
Normal file
7
app/dashboard/audits/loading.tsx
Normal file
@ -0,0 +1,7 @@
|
||||
export default function AuditLoading() {
|
||||
return (
|
||||
<div className="audits-page loading-state">
|
||||
<p>Loading audit logs...</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -1,70 +1,55 @@
|
||||
import "./page.scss";
|
||||
|
||||
import AuditTableClient from "./AuditTableClient";
|
||||
import { DEFAULT_PAGE_SIZE } from "./auditTransforms";
|
||||
import { fetchAudits } from "@/app/services/audits";
|
||||
import {
|
||||
AuditApiResponse,
|
||||
AuditQueryResult,
|
||||
DEFAULT_PAGE_SIZE,
|
||||
extractArray,
|
||||
normalizeRows,
|
||||
resolveTotal,
|
||||
} from "./auditTransforms";
|
||||
import { cookies } from "next/headers";
|
||||
import {
|
||||
AUDIT_CACHE_TAG,
|
||||
AUTH_COOKIE_NAME,
|
||||
BE_BASE_URL,
|
||||
REVALIDATE_SECONDS,
|
||||
} from "@/app/services/constants";
|
||||
ENTITY_PREFIX,
|
||||
PAGE_SIZE_OPTIONS,
|
||||
} from "@/app/dashboard/audits/auditConstants";
|
||||
|
||||
async function fetchInitialAudits(): Promise<AuditQueryResult> {
|
||||
const cookieStore = await cookies();
|
||||
const token = cookieStore.get(AUTH_COOKIE_NAME)?.value;
|
||||
type AuditPageProps = {
|
||||
searchParams?: Record<string, string | string[] | undefined>;
|
||||
};
|
||||
|
||||
if (!token) {
|
||||
throw new Error("Missing auth token");
|
||||
}
|
||||
const toSingleValue = (value?: string | string[]): string | undefined => {
|
||||
if (Array.isArray(value)) return value[0];
|
||||
return value;
|
||||
};
|
||||
|
||||
const params = new URLSearchParams();
|
||||
params.set("limit", DEFAULT_PAGE_SIZE.toString());
|
||||
params.set("page", "1");
|
||||
const clampNumber = (value: number, min: number, max?: number) => {
|
||||
if (Number.isNaN(value)) return min;
|
||||
if (value < min) return min;
|
||||
if (typeof max === "number" && value > max) return max;
|
||||
return value;
|
||||
};
|
||||
|
||||
const backendUrl = `${BE_BASE_URL}/api/v1/audit${
|
||||
params.size ? `?${params.toString()}` : ""
|
||||
}`;
|
||||
export default async function AuditPage({ searchParams = {} }: AuditPageProps) {
|
||||
const pageParam = toSingleValue(searchParams.page);
|
||||
const limitParam = toSingleValue(searchParams.limit);
|
||||
const sortParam = toSingleValue(searchParams.sort) || undefined;
|
||||
const entityQuery = toSingleValue(searchParams.entity)?.trim() || "";
|
||||
|
||||
const response = await fetch(backendUrl, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
next: {
|
||||
revalidate: REVALIDATE_SECONDS,
|
||||
tags: [AUDIT_CACHE_TAG],
|
||||
},
|
||||
const page = clampNumber(parseInt(pageParam || "1", 10), 1);
|
||||
const parsedLimit = parseInt(limitParam || String(DEFAULT_PAGE_SIZE), 10);
|
||||
const limit =
|
||||
PAGE_SIZE_OPTIONS.find(size => size === parsedLimit) ?? DEFAULT_PAGE_SIZE;
|
||||
|
||||
const data = await fetchAudits({
|
||||
limit,
|
||||
page,
|
||||
sort: sortParam,
|
||||
entity: entityQuery ? `${ENTITY_PREFIX}${entityQuery}` : undefined,
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response
|
||||
.json()
|
||||
.catch(() => ({ message: "Failed to fetch audits" }));
|
||||
throw new Error(errorData?.message || "Failed to fetch audits");
|
||||
}
|
||||
|
||||
const payload = (await response.json()) as AuditApiResponse;
|
||||
const rows = normalizeRows(extractArray(payload), 0);
|
||||
const total = resolveTotal(payload, rows.length);
|
||||
|
||||
return {
|
||||
rows,
|
||||
total,
|
||||
payload,
|
||||
pageIndex: 0,
|
||||
};
|
||||
}
|
||||
|
||||
export default async function AuditPage() {
|
||||
const initialData = await fetchInitialAudits();
|
||||
return <AuditTableClient initialData={initialData} />;
|
||||
return (
|
||||
<AuditTableClient
|
||||
rows={data.rows}
|
||||
total={data.total ?? data.rows.length}
|
||||
pageIndex={data.pageIndex}
|
||||
pageSize={limit}
|
||||
sortParam={sortParam}
|
||||
entityQuery={entityQuery}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
38
app/dashboard/audits/utils.ts
Normal file
38
app/dashboard/audits/utils.ts
Normal file
@ -0,0 +1,38 @@
|
||||
import { GridColDef, GridSortModel } from "@mui/x-data-grid";
|
||||
import { AuditRow } from "./auditTransforms";
|
||||
|
||||
export const buildSortParam = (sortModel: GridSortModel) =>
|
||||
sortModel.length && sortModel[0].field && sortModel[0].sort
|
||||
? `${sortModel[0].field}:${sortModel[0].sort}`
|
||||
: undefined;
|
||||
|
||||
export const parseSortModel = (sortParam?: string): GridSortModel => {
|
||||
if (!sortParam) return [];
|
||||
const [field, direction] = sortParam.split(":");
|
||||
if (!field || (direction !== "asc" && direction !== "desc")) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [{ field, sort: direction }];
|
||||
};
|
||||
|
||||
export const toTitle = (field: string) =>
|
||||
field
|
||||
.replace(/_/g, " ")
|
||||
.replace(/-/g, " ")
|
||||
.replace(/([a-z])([A-Z])/g, "$1 $2")
|
||||
.replace(/\s+/g, " ")
|
||||
.trim()
|
||||
.replace(/^\w/g, char => char.toUpperCase());
|
||||
|
||||
export const deriveColumns = (rows: AuditRow[]): GridColDef[] => {
|
||||
if (!rows.length) return [];
|
||||
|
||||
return Object.keys(rows[0]).map(field => ({
|
||||
field,
|
||||
headerName: toTitle(field),
|
||||
flex: field === "id" ? 0 : 1,
|
||||
minWidth: field === "id" ? 140 : 200,
|
||||
sortable: true,
|
||||
}));
|
||||
};
|
||||
@ -1,19 +1,5 @@
|
||||
import SettingsPageClient from "@/app/features/Pages/Settings/SettingsPageClient";
|
||||
|
||||
// We can enable this if we want to fetch the user from the database by the id but it's not necessary since we already have the user in the redux store
|
||||
// async function getUser() {
|
||||
// const token = (await cookies()).get("auth_token")?.value;
|
||||
// const payload = token ? await validateToken(token) : null;
|
||||
// const userId = payload?.id; // requires JWT to include id
|
||||
// if (!userId) throw new Error("No user id in token");
|
||||
// const res = await fetch(`${process.env.NEXT_PUBLIC_BASE_URL}/api/dashboard/admin/users/${userId}`, {
|
||||
// headers: { Authorization: `Bearer ${token}` },
|
||||
// cache: "no-store",
|
||||
// });
|
||||
// if (!res.ok) throw new Error("Failed to fetch user");
|
||||
// return res.json();
|
||||
// }
|
||||
|
||||
export default async function SettingsPage() {
|
||||
// const user = await getUser();
|
||||
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
.header {
|
||||
backdrop-filter: blur(10px);
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
.header__toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { cookies } from "next/headers";
|
||||
|
||||
import {
|
||||
AuditApiResponse,
|
||||
AuditQueryResult,
|
||||
@ -6,43 +8,64 @@ import {
|
||||
normalizeRows,
|
||||
resolveTotal,
|
||||
} from "@/app/dashboard/audits/auditTransforms";
|
||||
import { IGetAuditsParams } from "./types";
|
||||
import { AUDIT_CACHE_TAG, REVALIDATE_SECONDS } from "./constants";
|
||||
import {
|
||||
AUDIT_CACHE_TAG,
|
||||
AUTH_COOKIE_NAME,
|
||||
BE_BASE_URL,
|
||||
REVALIDATE_SECONDS,
|
||||
} from "./constants";
|
||||
|
||||
export async function getAudits({
|
||||
interface FetchAuditsParams {
|
||||
limit?: number;
|
||||
page?: number;
|
||||
sort?: string;
|
||||
filter?: string;
|
||||
entity?: string;
|
||||
}
|
||||
|
||||
export async function fetchAudits({
|
||||
limit = DEFAULT_PAGE_SIZE,
|
||||
page = 1,
|
||||
sort,
|
||||
filter,
|
||||
entity,
|
||||
signal,
|
||||
}: IGetAuditsParams = {}): Promise<AuditQueryResult> {
|
||||
}: FetchAuditsParams = {}): Promise<AuditQueryResult> {
|
||||
const cookieStore = await cookies();
|
||||
const token = cookieStore.get(AUTH_COOKIE_NAME)?.value;
|
||||
|
||||
if (!token) {
|
||||
throw new Error("Missing auth token");
|
||||
}
|
||||
|
||||
const params = new URLSearchParams();
|
||||
|
||||
if (limit) params.set("limit", String(limit));
|
||||
if (page) params.set("page", String(page));
|
||||
params.set("limit", String(limit));
|
||||
params.set("page", String(page));
|
||||
if (sort) params.set("sort", sort);
|
||||
if (filter) params.set("filter", filter);
|
||||
if (entity) params.set("Entity", entity);
|
||||
|
||||
const queryString = params.toString();
|
||||
const response = await fetch(
|
||||
`/api/dashboard/audits${queryString ? `?${queryString}` : ""}`,
|
||||
{
|
||||
const backendUrl = `${BE_BASE_URL}/api/v1/audit${
|
||||
params.size ? `?${params.toString()}` : ""
|
||||
}`;
|
||||
|
||||
const response = await fetch(backendUrl, {
|
||||
method: "GET",
|
||||
signal,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
next: {
|
||||
revalidate: REVALIDATE_SECONDS,
|
||||
tags: [AUDIT_CACHE_TAG],
|
||||
},
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response
|
||||
.json()
|
||||
.catch(() => ({ message: "Unknown error" }));
|
||||
throw new Error(errorData.message || "Failed to fetch audits");
|
||||
.catch(() => ({ message: "Failed to fetch audits" }));
|
||||
throw new Error(errorData?.message || "Failed to fetch audits");
|
||||
}
|
||||
|
||||
const payload = (await response.json()) as AuditApiResponse;
|
||||
|
||||
@ -3,3 +3,13 @@ export const REVALIDATE_SECONDS = 60;
|
||||
|
||||
export const BE_BASE_URL = process.env.BE_BASE_URL || "";
|
||||
export const AUTH_COOKIE_NAME = "auth_token";
|
||||
|
||||
export function getBaseUrl(): string {
|
||||
const port = process.env.PORT || "3000";
|
||||
return (
|
||||
process.env.NEXT_PUBLIC_BASE_URL ||
|
||||
(process.env.VERCEL_URL
|
||||
? `https://${process.env.VERCEL_URL}`
|
||||
: `http://localhost:${port}`)
|
||||
);
|
||||
}
|
||||
|
||||
83
app/services/matcher.ts
Normal file
83
app/services/matcher.ts
Normal file
@ -0,0 +1,83 @@
|
||||
import { MATCH_CONFIGS } from "../dashboard/admin/matcher/constants";
|
||||
import { MatchableEntity, MatchConfig } from "../dashboard/admin/matcher/types";
|
||||
import {
|
||||
normalizeEntity,
|
||||
resolveCollection,
|
||||
} from "../dashboard/admin/matcher/utils";
|
||||
|
||||
export async function getMatcherData(
|
||||
matchType: string,
|
||||
cookieHeader: string,
|
||||
baseUrl: string
|
||||
): Promise<{
|
||||
sourceItems: MatchableEntity[];
|
||||
targetItems: MatchableEntity[];
|
||||
}> {
|
||||
const config = MATCH_CONFIGS[matchType];
|
||||
if (!config) {
|
||||
return { sourceItems: [], targetItems: [] };
|
||||
}
|
||||
|
||||
try {
|
||||
const [sourceItems, targetItems] = await Promise.all([
|
||||
fetchEntities(config.sourceEndpoint, config, cookieHeader, baseUrl, true),
|
||||
fetchEntities(
|
||||
config.targetEndpoint,
|
||||
config,
|
||||
cookieHeader,
|
||||
baseUrl,
|
||||
false
|
||||
),
|
||||
]);
|
||||
|
||||
return { sourceItems, targetItems };
|
||||
} catch (error) {
|
||||
console.error("Error fetching matcher data:", error);
|
||||
return { sourceItems: [], targetItems: [] };
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchEntities(
|
||||
endpoint: string,
|
||||
config: MatchConfig,
|
||||
cookieHeader: string,
|
||||
baseUrl: string,
|
||||
isSource: boolean
|
||||
): Promise<MatchableEntity[]> {
|
||||
const url = new URL(`${baseUrl}${endpoint}`);
|
||||
|
||||
// For now, fetch all items (no pagination limit)
|
||||
// In production, you might want to add pagination
|
||||
const response = await fetch(url.toString(), {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Cookie: cookieHeader,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
filters: {},
|
||||
pagination: { page: 1, limit: 1000 },
|
||||
sort: {},
|
||||
}),
|
||||
cache: "no-store",
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
console.error(`Failed to fetch from ${endpoint}:`, response.status);
|
||||
return [];
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
console.log("[fetchEntities] data:", data, url.toString());
|
||||
const collectionKeys = isSource
|
||||
? config.sourceCollectionKeys
|
||||
: config.targetCollectionKeys;
|
||||
const primaryKey = isSource
|
||||
? config.sourcePrimaryKey
|
||||
: config.targetPrimaryKey;
|
||||
|
||||
const collection = resolveCollection(data, collectionKeys);
|
||||
return collection.map((item, index) =>
|
||||
normalizeEntity(item, primaryKey || "name", index + 1)
|
||||
);
|
||||
}
|
||||
@ -1,8 +0,0 @@
|
||||
export interface IGetAuditsParams {
|
||||
limit?: number;
|
||||
page?: number;
|
||||
sort?: string;
|
||||
filter?: string;
|
||||
entity?: string;
|
||||
signal?: AbortSignal;
|
||||
}
|
||||
@ -9,6 +9,8 @@ export interface JWTPayload {
|
||||
role: string;
|
||||
iat: number;
|
||||
exp: number;
|
||||
MustChangePassword: boolean;
|
||||
Groups: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -19,6 +19,9 @@
|
||||
"prepare": "husky"
|
||||
},
|
||||
"dependencies": {
|
||||
"@dnd-kit/core": "^6.3.1",
|
||||
"@dnd-kit/sortable": "^10.0.0",
|
||||
"@dnd-kit/utilities": "^3.2.2",
|
||||
"@emotion/react": "^11.14.0",
|
||||
"@emotion/styled": "^11.14.0",
|
||||
"@mui/icons-material": "^7.1.1",
|
||||
|
||||
454
yarn.lock
454
yarn.lock
@ -104,6 +104,59 @@
|
||||
"@types/tough-cookie" "^4.0.5"
|
||||
tough-cookie "^4.1.4"
|
||||
|
||||
"@dnd-kit/accessibility@^3.1.1":
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@dnd-kit/accessibility/-/accessibility-3.1.1.tgz#3b4202bd6bb370a0730f6734867785919beac6af"
|
||||
integrity sha512-2P+YgaXF+gRsIihwwY1gCsQSYnu9Zyj2py8kY5fFvUM1qm2WA2u639R6YNVfU4GWr+ZM5mqEsfHZZLoRONbemw==
|
||||
dependencies:
|
||||
tslib "^2.0.0"
|
||||
|
||||
"@dnd-kit/core@^6.3.1":
|
||||
version "6.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@dnd-kit/core/-/core-6.3.1.tgz#4c36406a62c7baac499726f899935f93f0e6d003"
|
||||
integrity sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==
|
||||
dependencies:
|
||||
"@dnd-kit/accessibility" "^3.1.1"
|
||||
"@dnd-kit/utilities" "^3.2.2"
|
||||
tslib "^2.0.0"
|
||||
|
||||
"@dnd-kit/sortable@^10.0.0":
|
||||
version "10.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@dnd-kit/sortable/-/sortable-10.0.0.tgz#1f9382b90d835cd5c65d92824fa9dafb78c4c3e8"
|
||||
integrity sha512-+xqhmIIzvAYMGfBYYnbKuNicfSsk4RksY2XdmJhT+HAC01nix6fHCztU68jooFiMUB01Ky3F0FyOvhG/BZrWkg==
|
||||
dependencies:
|
||||
"@dnd-kit/utilities" "^3.2.2"
|
||||
tslib "^2.0.0"
|
||||
|
||||
"@dnd-kit/utilities@^3.2.2":
|
||||
version "3.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@dnd-kit/utilities/-/utilities-3.2.2.tgz#5a32b6af356dc5f74d61b37d6f7129a4040ced7b"
|
||||
integrity sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg==
|
||||
dependencies:
|
||||
tslib "^2.0.0"
|
||||
|
||||
"@emnapi/core@^1.4.3":
|
||||
version "1.7.1"
|
||||
resolved "https://registry.yarnpkg.com/@emnapi/core/-/core-1.7.1.tgz#3a79a02dbc84f45884a1806ebb98e5746bdfaac4"
|
||||
integrity sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==
|
||||
dependencies:
|
||||
"@emnapi/wasi-threads" "1.1.0"
|
||||
tslib "^2.4.0"
|
||||
|
||||
"@emnapi/runtime@^1.4.3":
|
||||
version "1.7.1"
|
||||
resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.7.1.tgz#a73784e23f5d57287369c808197288b52276b791"
|
||||
integrity sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==
|
||||
dependencies:
|
||||
tslib "^2.4.0"
|
||||
|
||||
"@emnapi/wasi-threads@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz#60b2102fddc9ccb78607e4a3cf8403ea69be41bf"
|
||||
integrity sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==
|
||||
dependencies:
|
||||
tslib "^2.4.0"
|
||||
|
||||
"@emotion/babel-plugin@^11.13.5":
|
||||
version "11.13.5"
|
||||
resolved "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz"
|
||||
@ -149,7 +202,7 @@
|
||||
resolved "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz"
|
||||
integrity sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==
|
||||
|
||||
"@emotion/react@^11.0.0-rc.0", "@emotion/react@^11.14.0", "@emotion/react@^11.4.1", "@emotion/react@^11.5.0", "@emotion/react@^11.9.0":
|
||||
"@emotion/react@^11.14.0":
|
||||
version "11.14.0"
|
||||
resolved "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz"
|
||||
integrity sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==
|
||||
@ -179,7 +232,7 @@
|
||||
resolved "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz"
|
||||
integrity sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==
|
||||
|
||||
"@emotion/styled@^11.14.0", "@emotion/styled@^11.3.0", "@emotion/styled@^11.8.1":
|
||||
"@emotion/styled@^11.14.0":
|
||||
version "11.14.0"
|
||||
resolved "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.0.tgz"
|
||||
integrity sha512-XxfOnXFffatap2IyCeJyNov3kiDQWoR08gPUQxvbL7fxKryGBKUZUkG6Hz48DZwVrJSVh9sJboyV1Ds4OW6SgA==
|
||||
@ -317,6 +370,124 @@
|
||||
resolved "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz"
|
||||
integrity sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==
|
||||
|
||||
"@img/sharp-darwin-arm64@0.34.2":
|
||||
version "0.34.2"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.2.tgz#65049ef7c6be7857da742cd028f97602ce209635"
|
||||
integrity sha512-OfXHZPppddivUJnqyKoi5YVeHRkkNE2zUFT2gbpKxp/JZCFYEYubnMg+gOp6lWfasPrTS+KPosKqdI+ELYVDtg==
|
||||
optionalDependencies:
|
||||
"@img/sharp-libvips-darwin-arm64" "1.1.0"
|
||||
|
||||
"@img/sharp-darwin-x64@0.34.2":
|
||||
version "0.34.2"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.2.tgz#d37ff7c75c46d5a68a3756e3f1924ef7ca7b285e"
|
||||
integrity sha512-dYvWqmjU9VxqXmjEtjmvHnGqF8GrVjM2Epj9rJ6BUIXvk8slvNDJbhGFvIoXzkDhrJC2jUxNLz/GUjjvSzfw+g==
|
||||
optionalDependencies:
|
||||
"@img/sharp-libvips-darwin-x64" "1.1.0"
|
||||
|
||||
"@img/sharp-libvips-darwin-arm64@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.1.0.tgz#843f7c09c7245dc0d3cfec2b3c83bb08799a704f"
|
||||
integrity sha512-HZ/JUmPwrJSoM4DIQPv/BfNh9yrOA8tlBbqbLz4JZ5uew2+o22Ik+tHQJcih7QJuSa0zo5coHTfD5J8inqj9DA==
|
||||
|
||||
"@img/sharp-libvips-darwin-x64@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.1.0.tgz#1239c24426c06a8e833815562f78047a3bfbaaf8"
|
||||
integrity sha512-Xzc2ToEmHN+hfvsl9wja0RlnXEgpKNmftriQp6XzY/RaSfwD9th+MSh0WQKzUreLKKINb3afirxW7A0fz2YWuQ==
|
||||
|
||||
"@img/sharp-libvips-linux-arm64@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.1.0.tgz#20d276cefd903ee483f0441ba35961679c286315"
|
||||
integrity sha512-IVfGJa7gjChDET1dK9SekxFFdflarnUB8PwW8aGwEoF3oAsSDuNUTYS+SKDOyOJxQyDC1aPFMuRYLoDInyV9Ew==
|
||||
|
||||
"@img/sharp-libvips-linux-arm@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.1.0.tgz#067c0b566eae8063738cf1b1db8f8a8573b5465c"
|
||||
integrity sha512-s8BAd0lwUIvYCJyRdFqvsj+BJIpDBSxs6ivrOPm/R7piTs5UIwY5OjXrP2bqXC9/moGsyRa37eYWYCOGVXxVrA==
|
||||
|
||||
"@img/sharp-libvips-linux-ppc64@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.1.0.tgz#682334595f2ca00e0a07a675ba170af165162802"
|
||||
integrity sha512-tiXxFZFbhnkWE2LA8oQj7KYR+bWBkiV2nilRldT7bqoEZ4HiDOcePr9wVDAZPi/Id5fT1oY9iGnDq20cwUz8lQ==
|
||||
|
||||
"@img/sharp-libvips-linux-s390x@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.1.0.tgz#82fcd68444b3666384235279c145c2b28d8ee302"
|
||||
integrity sha512-xukSwvhguw7COyzvmjydRb3x/09+21HykyapcZchiCUkTThEQEOMtBj9UhkaBRLuBrgLFzQ2wbxdeCCJW/jgJA==
|
||||
|
||||
"@img/sharp-libvips-linux-x64@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.1.0.tgz#65b2b908bf47156b0724fde9095676c83a18cf5a"
|
||||
integrity sha512-yRj2+reB8iMg9W5sULM3S74jVS7zqSzHG3Ol/twnAAkAhnGQnpjj6e4ayUz7V+FpKypwgs82xbRdYtchTTUB+Q==
|
||||
|
||||
"@img/sharp-libvips-linuxmusl-arm64@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.1.0.tgz#72accf924e80b081c8db83b900b444a67c203f01"
|
||||
integrity sha512-jYZdG+whg0MDK+q2COKbYidaqW/WTz0cc1E+tMAusiDygrM4ypmSCjOJPmFTvHHJ8j/6cAGyeDWZOsK06tP33w==
|
||||
|
||||
"@img/sharp-libvips-linuxmusl-x64@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.1.0.tgz#1fa052737e203f46bf44192acd01f9faf11522d7"
|
||||
integrity sha512-wK7SBdwrAiycjXdkPnGCPLjYb9lD4l6Ze2gSdAGVZrEL05AOUJESWU2lhlC+Ffn5/G+VKuSm6zzbQSzFX/P65A==
|
||||
|
||||
"@img/sharp-linux-arm64@0.34.2":
|
||||
version "0.34.2"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.2.tgz#c9690fac5f3137eaab3f7ad6065390d10f66f1fa"
|
||||
integrity sha512-D8n8wgWmPDakc83LORcfJepdOSN6MvWNzzz2ux0MnIbOqdieRZwVYY32zxVx+IFUT8er5KPcyU3XXsn+GzG/0Q==
|
||||
optionalDependencies:
|
||||
"@img/sharp-libvips-linux-arm64" "1.1.0"
|
||||
|
||||
"@img/sharp-linux-arm@0.34.2":
|
||||
version "0.34.2"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.2.tgz#771dd2ec645f85f98441359bfc118afaf38cbd8b"
|
||||
integrity sha512-0DZzkvuEOqQUP9mo2kjjKNok5AmnOr1jB2XYjkaoNRwpAYMDzRmAqUIa1nRi58S2WswqSfPOWLNOr0FDT3H5RQ==
|
||||
optionalDependencies:
|
||||
"@img/sharp-libvips-linux-arm" "1.1.0"
|
||||
|
||||
"@img/sharp-linux-s390x@0.34.2":
|
||||
version "0.34.2"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.2.tgz#82132d158abff57bd90b53574f2865f72f94e6c8"
|
||||
integrity sha512-EGZ1xwhBI7dNISwxjChqBGELCWMGDvmxZXKjQRuqMrakhO8QoMgqCrdjnAqJq/CScxfRn+Bb7suXBElKQpPDiw==
|
||||
optionalDependencies:
|
||||
"@img/sharp-libvips-linux-s390x" "1.1.0"
|
||||
|
||||
"@img/sharp-linux-x64@0.34.2":
|
||||
version "0.34.2"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.2.tgz#d815fb87899d462b28b62a9252ad127f02fe0740"
|
||||
integrity sha512-sD7J+h5nFLMMmOXYH4DD9UtSNBD05tWSSdWAcEyzqW8Cn5UxXvsHAxmxSesYUsTOBmUnjtxghKDl15EvfqLFbQ==
|
||||
optionalDependencies:
|
||||
"@img/sharp-libvips-linux-x64" "1.1.0"
|
||||
|
||||
"@img/sharp-linuxmusl-arm64@0.34.2":
|
||||
version "0.34.2"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.2.tgz#cfac45b2abbc04628f676e123bfe3aeb300266c7"
|
||||
integrity sha512-NEE2vQ6wcxYav1/A22OOxoSOGiKnNmDzCYFOZ949xFmrWZOVII1Bp3NqVVpvj+3UeHMFyN5eP/V5hzViQ5CZNA==
|
||||
optionalDependencies:
|
||||
"@img/sharp-libvips-linuxmusl-arm64" "1.1.0"
|
||||
|
||||
"@img/sharp-linuxmusl-x64@0.34.2":
|
||||
version "0.34.2"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.2.tgz#b876c23ff51d0fb6d9f3b0a07e2f4d1436c203ad"
|
||||
integrity sha512-DOYMrDm5E6/8bm/yQLCWyuDJwUnlevR8xtF8bs+gjZ7cyUNYXiSf/E8Kp0Ss5xasIaXSHzb888V1BE4i1hFhAA==
|
||||
optionalDependencies:
|
||||
"@img/sharp-libvips-linuxmusl-x64" "1.1.0"
|
||||
|
||||
"@img/sharp-wasm32@0.34.2":
|
||||
version "0.34.2"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-wasm32/-/sharp-wasm32-0.34.2.tgz#b1dd0bab547dccf517586eb1fa5852160bba3b82"
|
||||
integrity sha512-/VI4mdlJ9zkaq53MbIG6rZY+QRN3MLbR6usYlgITEzi4Rpx5S6LFKsycOQjkOGmqTNmkIdLjEvooFKwww6OpdQ==
|
||||
dependencies:
|
||||
"@emnapi/runtime" "^1.4.3"
|
||||
|
||||
"@img/sharp-win32-arm64@0.34.2":
|
||||
version "0.34.2"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.2.tgz#f37bee0f60c167f825a09d2b8de6849b823e8b30"
|
||||
integrity sha512-cfP/r9FdS63VA5k0xiqaNaEoGxBg9k7uE+RQGzuK9fHt7jib4zAVVseR9LsE4gJcNWgT6APKMNnCcnyOtmSEUQ==
|
||||
|
||||
"@img/sharp-win32-ia32@0.34.2":
|
||||
version "0.34.2"
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.2.tgz#8fc30b6655bc6ff8910344a2020d334aa6361672"
|
||||
integrity sha512-QLjGGvAbj0X/FXl8n1WbtQ6iVBpWU7JO94u/P2M4a8CFYsvQi4GW2mRy/JqkRx0qpBzaOdKJKw8uc930EX2AHw==
|
||||
|
||||
"@img/sharp-win32-x64@0.34.2":
|
||||
version "0.34.2"
|
||||
resolved "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.2.tgz"
|
||||
@ -410,7 +581,7 @@
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.27.1"
|
||||
|
||||
"@mui/material@^5.15.14 || ^6.0.0 || ^7.0.0", "@mui/material@^7.1.2":
|
||||
"@mui/material@^7.1.2":
|
||||
version "7.1.2"
|
||||
resolved "https://registry.npmjs.org/@mui/material/-/material-7.1.2.tgz"
|
||||
integrity sha512-Z5PYKkA6Kd8vS04zKxJNpwuvt6IoMwqpbidV7RCrRQQKwczIwcNcS8L6GnN4pzFYfEs+N9v6co27DmG07rcnoA==
|
||||
@ -449,7 +620,7 @@
|
||||
csstype "^3.1.3"
|
||||
prop-types "^15.8.1"
|
||||
|
||||
"@mui/system@^5.15.14 || ^6.0.0 || ^7.0.0", "@mui/system@^7.1.1":
|
||||
"@mui/system@^7.1.1":
|
||||
version "7.1.1"
|
||||
resolved "https://registry.npmjs.org/@mui/system/-/system-7.1.1.tgz"
|
||||
integrity sha512-Kj1uhiqnj4Zo7PDjAOghtXJtNABunWvhcRU0O7RQJ7WOxeynoH6wXPcilphV8QTFtkKaip8EiNJRiCD+B3eROA==
|
||||
@ -516,6 +687,15 @@
|
||||
"@mui/utils" "^7.1.1"
|
||||
reselect "^5.1.1"
|
||||
|
||||
"@napi-rs/wasm-runtime@^0.2.11":
|
||||
version "0.2.12"
|
||||
resolved "https://registry.yarnpkg.com/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz#3e78a8b96e6c33a6c517e1894efbd5385a7cb6f2"
|
||||
integrity sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==
|
||||
dependencies:
|
||||
"@emnapi/core" "^1.4.3"
|
||||
"@emnapi/runtime" "^1.4.3"
|
||||
"@tybys/wasm-util" "^0.10.0"
|
||||
|
||||
"@next/env@15.3.3":
|
||||
version "15.3.3"
|
||||
resolved "https://registry.npmjs.org/@next/env/-/env-15.3.3.tgz"
|
||||
@ -528,6 +708,41 @@
|
||||
dependencies:
|
||||
fast-glob "3.3.1"
|
||||
|
||||
"@next/swc-darwin-arm64@15.3.3":
|
||||
version "15.3.3"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.3.3.tgz#994de8515cdfb74d337bdad645c33605de44c68b"
|
||||
integrity sha512-WRJERLuH+O3oYB4yZNVahSVFmtxRNjNF1I1c34tYMoJb0Pve+7/RaLAJJizyYiFhjYNGHRAE1Ri2Fd23zgDqhg==
|
||||
|
||||
"@next/swc-darwin-x64@15.3.3":
|
||||
version "15.3.3"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-15.3.3.tgz#71588bad245180ffd1af1e1f894477287e739eb0"
|
||||
integrity sha512-XHdzH/yBc55lu78k/XwtuFR/ZXUTcflpRXcsu0nKmF45U96jt1tsOZhVrn5YH+paw66zOANpOnFQ9i6/j+UYvw==
|
||||
|
||||
"@next/swc-linux-arm64-gnu@15.3.3":
|
||||
version "15.3.3"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.3.3.tgz#66a15f749c14f04a89f8c7e21c7a8d343fc34e6e"
|
||||
integrity sha512-VZ3sYL2LXB8znNGcjhocikEkag/8xiLgnvQts41tq6i+wql63SMS1Q6N8RVXHw5pEUjiof+II3HkDd7GFcgkzw==
|
||||
|
||||
"@next/swc-linux-arm64-musl@15.3.3":
|
||||
version "15.3.3"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.3.3.tgz#14bd66213f7f33d6909574750bcb05037221a2ac"
|
||||
integrity sha512-h6Y1fLU4RWAp1HPNJWDYBQ+e3G7sLckyBXhmH9ajn8l/RSMnhbuPBV/fXmy3muMcVwoJdHL+UtzRzs0nXOf9SA==
|
||||
|
||||
"@next/swc-linux-x64-gnu@15.3.3":
|
||||
version "15.3.3"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.3.3.tgz#4a19434545e5e752d9a3ed71f9b34982725f6293"
|
||||
integrity sha512-jJ8HRiF3N8Zw6hGlytCj5BiHyG/K+fnTKVDEKvUCyiQ/0r5tgwO7OgaRiOjjRoIx2vwLR+Rz8hQoPrnmFbJdfw==
|
||||
|
||||
"@next/swc-linux-x64-musl@15.3.3":
|
||||
version "15.3.3"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.3.3.tgz#41ab140dd0a04ab7291adbec5836c1ce251a588c"
|
||||
integrity sha512-HrUcTr4N+RgiiGn3jjeT6Oo208UT/7BuTr7K0mdKRBtTbT4v9zJqCDKO97DUqqoBK1qyzP1RwvrWTvU6EPh/Cw==
|
||||
|
||||
"@next/swc-win32-arm64-msvc@15.3.3":
|
||||
version "15.3.3"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.3.3.tgz#fcd1d7e0007b7b73d1acdbf0ad6d91f7aa2deb15"
|
||||
integrity sha512-SxorONgi6K7ZUysMtRF3mIeHC5aA3IQLmKFQzU0OuhuUYwpOBc1ypaLJLP5Bf3M9k53KUUUj4vTPwzGvl/NwlQ==
|
||||
|
||||
"@next/swc-win32-x64-msvc@15.3.3":
|
||||
version "15.3.3"
|
||||
resolved "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.3.3.tgz"
|
||||
@ -541,7 +756,7 @@
|
||||
"@nodelib/fs.stat" "2.0.5"
|
||||
run-parallel "^1.1.9"
|
||||
|
||||
"@nodelib/fs.stat@^2.0.2", "@nodelib/fs.stat@2.0.5":
|
||||
"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2":
|
||||
version "2.0.5"
|
||||
resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz"
|
||||
integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
|
||||
@ -577,6 +792,66 @@
|
||||
resolved "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz"
|
||||
integrity sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==
|
||||
|
||||
"@parcel/watcher-android-arm64@2.5.1":
|
||||
version "2.5.1"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz#507f836d7e2042f798c7d07ad19c3546f9848ac1"
|
||||
integrity sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==
|
||||
|
||||
"@parcel/watcher-darwin-arm64@2.5.1":
|
||||
version "2.5.1"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz#3d26dce38de6590ef79c47ec2c55793c06ad4f67"
|
||||
integrity sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==
|
||||
|
||||
"@parcel/watcher-darwin-x64@2.5.1":
|
||||
version "2.5.1"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz#99f3af3869069ccf774e4ddfccf7e64fd2311ef8"
|
||||
integrity sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==
|
||||
|
||||
"@parcel/watcher-freebsd-x64@2.5.1":
|
||||
version "2.5.1"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz#14d6857741a9f51dfe51d5b08b7c8afdbc73ad9b"
|
||||
integrity sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==
|
||||
|
||||
"@parcel/watcher-linux-arm-glibc@2.5.1":
|
||||
version "2.5.1"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz#43c3246d6892381db473bb4f663229ad20b609a1"
|
||||
integrity sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==
|
||||
|
||||
"@parcel/watcher-linux-arm-musl@2.5.1":
|
||||
version "2.5.1"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz#663750f7090bb6278d2210de643eb8a3f780d08e"
|
||||
integrity sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==
|
||||
|
||||
"@parcel/watcher-linux-arm64-glibc@2.5.1":
|
||||
version "2.5.1"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz#ba60e1f56977f7e47cd7e31ad65d15fdcbd07e30"
|
||||
integrity sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==
|
||||
|
||||
"@parcel/watcher-linux-arm64-musl@2.5.1":
|
||||
version "2.5.1"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz#f7fbcdff2f04c526f96eac01f97419a6a99855d2"
|
||||
integrity sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==
|
||||
|
||||
"@parcel/watcher-linux-x64-glibc@2.5.1":
|
||||
version "2.5.1"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz#4d2ea0f633eb1917d83d483392ce6181b6a92e4e"
|
||||
integrity sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==
|
||||
|
||||
"@parcel/watcher-linux-x64-musl@2.5.1":
|
||||
version "2.5.1"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz#277b346b05db54f55657301dd77bdf99d63606ee"
|
||||
integrity sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==
|
||||
|
||||
"@parcel/watcher-win32-arm64@2.5.1":
|
||||
version "2.5.1"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz#7e9e02a26784d47503de1d10e8eab6cceb524243"
|
||||
integrity sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==
|
||||
|
||||
"@parcel/watcher-win32-ia32@2.5.1":
|
||||
version "2.5.1"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz#2d0f94fa59a873cdc584bf7f6b1dc628ddf976e6"
|
||||
integrity sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==
|
||||
|
||||
"@parcel/watcher-win32-x64@2.5.1":
|
||||
version "2.5.1"
|
||||
resolved "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz"
|
||||
@ -655,6 +930,13 @@
|
||||
dependencies:
|
||||
tslib "^2.8.0"
|
||||
|
||||
"@tybys/wasm-util@^0.10.0":
|
||||
version "0.10.1"
|
||||
resolved "https://registry.yarnpkg.com/@tybys/wasm-util/-/wasm-util-0.10.1.tgz#ecddd3205cf1e2d5274649ff0eedd2991ed7f414"
|
||||
integrity sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==
|
||||
dependencies:
|
||||
tslib "^2.4.0"
|
||||
|
||||
"@types/cookie@^0.6.0":
|
||||
version "0.6.0"
|
||||
resolved "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz"
|
||||
@ -738,7 +1020,7 @@
|
||||
resolved "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz"
|
||||
integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==
|
||||
|
||||
"@types/node@^20", "@types/node@>=18":
|
||||
"@types/node@^20":
|
||||
version "20.19.1"
|
||||
resolved "https://registry.npmjs.org/@types/node/-/node-20.19.1.tgz"
|
||||
integrity sha512-jJD50LtlD2dodAEO653i3YF04NWak6jN3ky+Ri3Em3mGR39/glWiboM/IePaRbgwSfqM1TpGXfAg8ohn/4dTgA==
|
||||
@ -783,7 +1065,7 @@
|
||||
resolved "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz"
|
||||
integrity sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==
|
||||
|
||||
"@types/react@*", "@types/react@^17.0.0 || ^18.0.0 || ^19.0.0", "@types/react@^18.2.25 || ^19", "@types/react@^19", "@types/react@^19.0.0":
|
||||
"@types/react@*", "@types/react@^19":
|
||||
version "19.1.8"
|
||||
resolved "https://registry.npmjs.org/@types/react/-/react-19.1.8.tgz"
|
||||
integrity sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g==
|
||||
@ -827,7 +1109,7 @@
|
||||
natural-compare "^1.4.0"
|
||||
ts-api-utils "^2.1.0"
|
||||
|
||||
"@typescript-eslint/parser@^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", "@typescript-eslint/parser@^8.34.1":
|
||||
"@typescript-eslint/parser@^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0":
|
||||
version "8.34.1"
|
||||
resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.34.1.tgz"
|
||||
integrity sha512-4O3idHxhyzjClSMJ0a29AcoK0+YwnEqzI6oz3vlRf3xw0zbzt15MzXwItOlnr5nIth6zlY2RENLsOPvhyrKAQA==
|
||||
@ -855,7 +1137,7 @@
|
||||
"@typescript-eslint/types" "8.34.1"
|
||||
"@typescript-eslint/visitor-keys" "8.34.1"
|
||||
|
||||
"@typescript-eslint/tsconfig-utils@^8.34.1", "@typescript-eslint/tsconfig-utils@8.34.1":
|
||||
"@typescript-eslint/tsconfig-utils@8.34.1", "@typescript-eslint/tsconfig-utils@^8.34.1":
|
||||
version "8.34.1"
|
||||
resolved "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.34.1.tgz"
|
||||
integrity sha512-K4Sjdo4/xF9NEeA2khOb7Y5nY6NSXBnod87uniVYW9kHP+hNlDV8trUSFeynA2uxWam4gIWgWoygPrv9VMWrYg==
|
||||
@ -870,7 +1152,7 @@
|
||||
debug "^4.3.4"
|
||||
ts-api-utils "^2.1.0"
|
||||
|
||||
"@typescript-eslint/types@^8.34.1", "@typescript-eslint/types@8.34.1":
|
||||
"@typescript-eslint/types@8.34.1", "@typescript-eslint/types@^8.34.1":
|
||||
version "8.34.1"
|
||||
resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.34.1.tgz"
|
||||
integrity sha512-rjLVbmE7HR18kDsjNIZQHxmv9RZwlgzavryL5Lnj2ujIRTeXlKtILHgRNmQ3j4daw7zd+mQgy+uyt6Zo6I0IGA==
|
||||
@ -909,6 +1191,98 @@
|
||||
"@typescript-eslint/types" "8.34.1"
|
||||
eslint-visitor-keys "^4.2.1"
|
||||
|
||||
"@unrs/resolver-binding-android-arm-eabi@1.9.0":
|
||||
version "1.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.9.0.tgz#e91317973356eb845c9186db5f9ec43e8d0002eb"
|
||||
integrity sha512-h1T2c2Di49ekF2TE8ZCoJkb+jwETKUIPDJ/nO3tJBKlLFPu+fyd93f0rGP/BvArKx2k2HlRM4kqkNarj3dvZlg==
|
||||
|
||||
"@unrs/resolver-binding-android-arm64@1.9.0":
|
||||
version "1.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.9.0.tgz#fbdd79b2a8e478e02e1c0751dfbc100017522161"
|
||||
integrity sha512-sG1NHtgXtX8owEkJ11yn34vt0Xqzi3k9TJ8zppDmyG8GZV4kVWw44FHwKwHeEFl07uKPeC4ZoyuQaGh5ruJYPA==
|
||||
|
||||
"@unrs/resolver-binding-darwin-arm64@1.9.0":
|
||||
version "1.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.9.0.tgz#24bb42710227ae2f4fea191151f3acc6a75b50d6"
|
||||
integrity sha512-nJ9z47kfFnCxN1z/oYZS7HSNsFh43y2asePzTEZpEvK7kGyuShSl3RRXnm/1QaqFL+iP+BjMwuB+DYUymOkA5A==
|
||||
|
||||
"@unrs/resolver-binding-darwin-x64@1.9.0":
|
||||
version "1.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.9.0.tgz#4a205940ec311ac8396c3f25043644b78cc98a20"
|
||||
integrity sha512-TK+UA1TTa0qS53rjWn7cVlEKVGz2B6JYe0C++TdQjvWYIyx83ruwh0wd4LRxYBM5HeuAzXcylA9BH2trARXJTw==
|
||||
|
||||
"@unrs/resolver-binding-freebsd-x64@1.9.0":
|
||||
version "1.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.9.0.tgz#ed82e000f7248011696ecc8894f574caa197b0be"
|
||||
integrity sha512-6uZwzMRFcD7CcCd0vz3Hp+9qIL2jseE/bx3ZjaLwn8t714nYGwiE84WpaMCYjU+IQET8Vu/+BNAGtYD7BG/0yA==
|
||||
|
||||
"@unrs/resolver-binding-linux-arm-gnueabihf@1.9.0":
|
||||
version "1.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.9.0.tgz#534a8b32118590f7fb9edd21c6576243a89a8aad"
|
||||
integrity sha512-bPUBksQfrgcfv2+mm+AZinaKq8LCFvt5PThYqRotqSuuZK1TVKkhbVMS/jvSRfYl7jr3AoZLYbDkItxgqMKRkg==
|
||||
|
||||
"@unrs/resolver-binding-linux-arm-musleabihf@1.9.0":
|
||||
version "1.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.9.0.tgz#b31718752e77cecbbcf7ba1e01dea97c1a5ee7e0"
|
||||
integrity sha512-uT6E7UBIrTdCsFQ+y0tQd3g5oudmrS/hds5pbU3h4s2t/1vsGWbbSKhBSCD9mcqaqkBwoqlECpUrRJCmldl8PA==
|
||||
|
||||
"@unrs/resolver-binding-linux-arm64-gnu@1.9.0":
|
||||
version "1.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.9.0.tgz#0f11ba195020cfa869533fb74733d68162349d14"
|
||||
integrity sha512-vdqBh911wc5awE2bX2zx3eflbyv8U9xbE/jVKAm425eRoOVv/VseGZsqi3A3SykckSpF4wSROkbQPvbQFn8EsA==
|
||||
|
||||
"@unrs/resolver-binding-linux-arm64-musl@1.9.0":
|
||||
version "1.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.9.0.tgz#8b6bc086cf9efaa22e8f2fef381786d6636b8e19"
|
||||
integrity sha512-/8JFZ/SnuDr1lLEVsxsuVwrsGquTvT51RZGvyDB/dOK3oYK2UqeXzgeyq6Otp8FZXQcEYqJwxb9v+gtdXn03eQ==
|
||||
|
||||
"@unrs/resolver-binding-linux-ppc64-gnu@1.9.0":
|
||||
version "1.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.9.0.tgz#5cd15899af31c2bbf90bfca5f798f64a16770e23"
|
||||
integrity sha512-FkJjybtrl+rajTw4loI3L6YqSOpeZfDls4SstL/5lsP2bka9TiHUjgMBjygeZEis1oC8LfJTS8FSgpKPaQx2tQ==
|
||||
|
||||
"@unrs/resolver-binding-linux-riscv64-gnu@1.9.0":
|
||||
version "1.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.9.0.tgz#4f2c75af52437eb10b48ea5b72750fb65fb174be"
|
||||
integrity sha512-w/NZfHNeDusbqSZ8r/hp8iL4S39h4+vQMc9/vvzuIKMWKppyUGKm3IST0Qv0aOZ1rzIbl9SrDeIqK86ZpUK37w==
|
||||
|
||||
"@unrs/resolver-binding-linux-riscv64-musl@1.9.0":
|
||||
version "1.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.9.0.tgz#6a87e82e0dd39d34ff37ddba6accf73cdb396e86"
|
||||
integrity sha512-bEPBosut8/8KQbUixPry8zg/fOzVOWyvwzOfz0C0Rw6dp+wIBseyiHKjkcSyZKv/98edrbMknBaMNJfA/UEdqw==
|
||||
|
||||
"@unrs/resolver-binding-linux-s390x-gnu@1.9.0":
|
||||
version "1.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.9.0.tgz#6524cc3c01309022de86c4a7317fe7d9f9fb855c"
|
||||
integrity sha512-LDtMT7moE3gK753gG4pc31AAqGUC86j3AplaFusc717EUGF9ZFJ356sdQzzZzkBk1XzMdxFyZ4f/i35NKM/lFA==
|
||||
|
||||
"@unrs/resolver-binding-linux-x64-gnu@1.9.0":
|
||||
version "1.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.9.0.tgz#85fb8a45dccf3823cd73ea4b61b2c3f2e8ab6653"
|
||||
integrity sha512-WmFd5KINHIXj8o1mPaT8QRjA9HgSXhN1gl9Da4IZihARihEnOylu4co7i/yeaIpcfsI6sYs33cNZKyHYDh0lrA==
|
||||
|
||||
"@unrs/resolver-binding-linux-x64-musl@1.9.0":
|
||||
version "1.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.9.0.tgz#235e539da5872df51c03e0e050a1c715e25044ca"
|
||||
integrity sha512-CYuXbANW+WgzVRIl8/QvZmDaZxrqvOldOwlbUjIM4pQ46FJ0W5cinJ/Ghwa/Ng1ZPMJMk1VFdsD/XwmCGIXBWg==
|
||||
|
||||
"@unrs/resolver-binding-wasm32-wasi@1.9.0":
|
||||
version "1.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.9.0.tgz#1bc614ce2ba61330c16bffa1e50f41d95d25c0a6"
|
||||
integrity sha512-6Rp2WH0OoitMYR57Z6VE8Y6corX8C6QEMWLgOV6qXiJIeZ1F9WGXY/yQ8yDC4iTraotyLOeJ2Asea0urWj2fKQ==
|
||||
dependencies:
|
||||
"@napi-rs/wasm-runtime" "^0.2.11"
|
||||
|
||||
"@unrs/resolver-binding-win32-arm64-msvc@1.9.0":
|
||||
version "1.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.9.0.tgz#0d8704275a9f2634d81b35d8a00a2f4bd8dec7fa"
|
||||
integrity sha512-rknkrTRuvujprrbPmGeHi8wYWxmNVlBoNW8+4XF2hXUnASOjmuC9FNF1tGbDiRQWn264q9U/oGtixyO3BT8adQ==
|
||||
|
||||
"@unrs/resolver-binding-win32-ia32-msvc@1.9.0":
|
||||
version "1.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.9.0.tgz#46909cbeb9a38b3f31a64833fe03aa1aebb8da2b"
|
||||
integrity sha512-Ceymm+iBl+bgAICtgiHyMLz6hjxmLJKqBim8tDzpX61wpZOx2bPK6Gjuor7I2RiUynVjvvkoRIkrPyMwzBzF3A==
|
||||
|
||||
"@unrs/resolver-binding-win32-x64-msvc@1.9.0":
|
||||
version "1.9.0"
|
||||
resolved "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.9.0.tgz"
|
||||
@ -919,7 +1293,7 @@ acorn-jsx@^5.3.2:
|
||||
resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz"
|
||||
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
|
||||
|
||||
"acorn@^6.0.0 || ^7.0.0 || ^8.0.0", acorn@^8.15.0:
|
||||
acorn@^8.15.0:
|
||||
version "8.15.0"
|
||||
resolved "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz"
|
||||
integrity sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==
|
||||
@ -1298,12 +1672,12 @@ cross-spawn@^7.0.6:
|
||||
shebang-command "^2.0.0"
|
||||
which "^2.0.1"
|
||||
|
||||
csstype@^3.0.10, csstype@^3.0.2, csstype@^3.1.3:
|
||||
csstype@^3.0.2, csstype@^3.1.3:
|
||||
version "3.1.3"
|
||||
resolved "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz"
|
||||
integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==
|
||||
|
||||
d3-array@^3.1.6, "d3-array@2 - 3", "d3-array@2.10.0 - 3":
|
||||
"d3-array@2 - 3", "d3-array@2.10.0 - 3", d3-array@^3.1.6:
|
||||
version "3.2.4"
|
||||
resolved "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz"
|
||||
integrity sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==
|
||||
@ -1325,7 +1699,7 @@ d3-ease@^3.0.1:
|
||||
resolved "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz"
|
||||
integrity sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==
|
||||
|
||||
d3-interpolate@^3.0.1, "d3-interpolate@1.2.0 - 3":
|
||||
"d3-interpolate@1.2.0 - 3", d3-interpolate@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz"
|
||||
integrity sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==
|
||||
@ -1362,7 +1736,7 @@ d3-shape@^3.1.0:
|
||||
dependencies:
|
||||
d3-time "1 - 3"
|
||||
|
||||
d3-time@^3.0.0, "d3-time@1 - 3", "d3-time@2.1.1 - 3":
|
||||
"d3-time@1 - 3", "d3-time@2.1.1 - 3", d3-time@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz"
|
||||
integrity sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==
|
||||
@ -1413,12 +1787,12 @@ date-fns@^2.16.1:
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.21.0"
|
||||
|
||||
"date-fns@^2.25.0 || ^3.2.0 || ^4.0.0", date-fns@^4.1.0, "date-fns@3.0.6 || >=3.0.0":
|
||||
date-fns@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz"
|
||||
integrity sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==
|
||||
|
||||
dayjs@^1.10.7, dayjs@^1.11.13:
|
||||
dayjs@^1.11.13:
|
||||
version "1.11.13"
|
||||
resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz"
|
||||
integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==
|
||||
@ -1701,7 +2075,7 @@ eslint-module-utils@^2.12.0:
|
||||
dependencies:
|
||||
debug "^3.2.7"
|
||||
|
||||
eslint-plugin-import@*, eslint-plugin-import@^2.31.0:
|
||||
eslint-plugin-import@^2.31.0:
|
||||
version "2.31.0"
|
||||
resolved "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz"
|
||||
integrity sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==
|
||||
@ -1794,7 +2168,7 @@ eslint-visitor-keys@^4.2.1:
|
||||
resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz"
|
||||
integrity sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==
|
||||
|
||||
eslint@*, "eslint@^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9", "eslint@^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9", "eslint@^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7", "eslint@^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0", "eslint@^6.0.0 || ^7.0.0 || >=8.0.0", "eslint@^7.23.0 || ^8.0.0 || ^9.0.0", "eslint@^8.57.0 || ^9.0.0", eslint@^9:
|
||||
eslint@^9:
|
||||
version "9.29.0"
|
||||
resolved "https://registry.npmjs.org/eslint/-/eslint-9.29.0.tgz"
|
||||
integrity sha512-GsGizj2Y1rCWDu6XoEekL3RLilp0voSePurjZIkxL3wlm5o5EC9VpgaP7lrCvjnkuLvzFBQWB3vWB3K5KQTveQ==
|
||||
@ -1883,17 +2257,6 @@ fast-equals@^5.0.1:
|
||||
resolved "https://registry.npmjs.org/fast-equals/-/fast-equals-5.2.2.tgz"
|
||||
integrity sha512-V7/RktU11J3I36Nwq2JnZEM7tNm17eBJz+u25qdxBZeCKiX6BkVSZQjwWIr+IobgnZy+ag73tTZgZi7tr0LrBw==
|
||||
|
||||
fast-glob@^3.3.2:
|
||||
version "3.3.3"
|
||||
resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz"
|
||||
integrity sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==
|
||||
dependencies:
|
||||
"@nodelib/fs.stat" "^2.0.2"
|
||||
"@nodelib/fs.walk" "^1.2.3"
|
||||
glob-parent "^5.1.2"
|
||||
merge2 "^1.3.0"
|
||||
micromatch "^4.0.8"
|
||||
|
||||
fast-glob@3.3.1:
|
||||
version "3.3.1"
|
||||
resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz"
|
||||
@ -1905,6 +2268,17 @@ fast-glob@3.3.1:
|
||||
merge2 "^1.3.0"
|
||||
micromatch "^4.0.4"
|
||||
|
||||
fast-glob@^3.3.2:
|
||||
version "3.3.3"
|
||||
resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz"
|
||||
integrity sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==
|
||||
dependencies:
|
||||
"@nodelib/fs.stat" "^2.0.2"
|
||||
"@nodelib/fs.walk" "^1.2.3"
|
||||
glob-parent "^5.1.2"
|
||||
merge2 "^1.3.0"
|
||||
micromatch "^4.0.8"
|
||||
|
||||
fast-json-stable-stringify@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz"
|
||||
@ -2828,7 +3202,7 @@ picomatch@^2.3.1:
|
||||
resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz"
|
||||
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
|
||||
|
||||
"picomatch@^3 || ^4", picomatch@^4.0.2:
|
||||
picomatch@^4.0.2:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz"
|
||||
integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==
|
||||
@ -2898,7 +3272,7 @@ react-date-range@^2.0.1:
|
||||
react-list "^0.8.13"
|
||||
shallow-equal "^1.2.1"
|
||||
|
||||
"react-dom@^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom@^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom@^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", react-dom@^19.0.0, react-dom@>=16, react-dom@>=16.6.0:
|
||||
react-dom@^19.0.0:
|
||||
version "19.1.0"
|
||||
resolved "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz"
|
||||
integrity sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==
|
||||
@ -2933,7 +3307,7 @@ react-list@^0.8.13:
|
||||
resolved "https://registry.npmjs.org/react-list/-/react-list-0.8.18.tgz"
|
||||
integrity sha512-1OSdDvzuKuwDJvQNuhXxxL+jTmmdtKg1i6KtYgxI9XR98kbOql1FcSGP+Lcvo91fk3cYng+Z6YkC6X9HRJwxfw==
|
||||
|
||||
"react-redux@^7.2.1 || ^8.1.3 || ^9.0.0", react-redux@^9.2.0:
|
||||
react-redux@^9.2.0:
|
||||
version "9.2.0"
|
||||
resolved "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz"
|
||||
integrity sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==
|
||||
@ -2960,7 +3334,7 @@ react-transition-group@^4.4.5:
|
||||
loose-envify "^1.4.0"
|
||||
prop-types "^15.6.2"
|
||||
|
||||
"react@^0.14 || ^15.0.0-rc || >=15.0", "react@^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^16.9.0 || ^17.0.0 || ^18 || ^19", "react@^17.0.0 || ^18.0.0 || ^19.0.0", "react@^18.0 || ^19", "react@^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", react@^19.0.0, react@^19.1.0, "react@>= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0", react@>=16, react@>=16.6.0, react@>=16.8.0, "react@0.14 || 15 - 19":
|
||||
react@^19.0.0:
|
||||
version "19.1.0"
|
||||
resolved "https://registry.npmjs.org/react/-/react-19.1.0.tgz"
|
||||
integrity sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==
|
||||
@ -3013,7 +3387,7 @@ redux@^4.0.0:
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.9.2"
|
||||
|
||||
redux@^5.0.0, redux@^5.0.1, "redux@>=5 <6", redux@>4.0.0:
|
||||
redux@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz"
|
||||
integrity sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==
|
||||
@ -3099,7 +3473,7 @@ run-parallel@^1.1.9:
|
||||
dependencies:
|
||||
queue-microtask "^1.2.2"
|
||||
|
||||
rxjs@^7.8.2, "rxjs@>=7 <8":
|
||||
rxjs@^7.8.2:
|
||||
version "7.8.2"
|
||||
resolved "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz"
|
||||
integrity sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==
|
||||
@ -3134,7 +3508,7 @@ safe-regex-test@^1.0.3, safe-regex-test@^1.1.0:
|
||||
es-errors "^1.3.0"
|
||||
is-regex "^1.2.1"
|
||||
|
||||
sass@^1.3.0, sass@^1.89.2:
|
||||
sass@^1.89.2:
|
||||
version "1.90.0"
|
||||
resolved "https://registry.npmjs.org/sass/-/sass-1.90.0.tgz"
|
||||
integrity sha512-9GUyuksjw70uNpb1MTYWsH9MQHOHY6kwfnkafC24+7aOMZn9+rVMBxRbLvw756mrBFbIsFg6Xw9IkR2Fnn3k+Q==
|
||||
@ -3291,7 +3665,7 @@ simple-swizzle@^0.2.2:
|
||||
dependencies:
|
||||
is-arrayish "^0.3.1"
|
||||
|
||||
source-map-js@^1.0.2, "source-map-js@>=0.6.2 <2.0.0":
|
||||
"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.2:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz"
|
||||
integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==
|
||||
@ -3507,7 +3881,7 @@ tsconfig-paths@^3.15.0:
|
||||
minimist "^1.2.6"
|
||||
strip-bom "^3.0.0"
|
||||
|
||||
tslib@^2.1.0, tslib@^2.4.0, tslib@^2.8.0:
|
||||
tslib@^2.0.0, tslib@^2.1.0, tslib@^2.4.0, tslib@^2.8.0:
|
||||
version "2.8.1"
|
||||
resolved "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz"
|
||||
integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==
|
||||
@ -3574,7 +3948,7 @@ typed-array-length@^1.0.7:
|
||||
possible-typed-array-names "^1.0.0"
|
||||
reflect.getprototypeof "^1.0.6"
|
||||
|
||||
typescript@^5, "typescript@>= 4.8.x", typescript@>=3.3.1, typescript@>=4.8.4, "typescript@>=4.8.4 <5.9.0":
|
||||
typescript@^5:
|
||||
version "5.8.3"
|
||||
resolved "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz"
|
||||
integrity sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user