much improved version
This commit is contained in:
parent
e87992cbbd
commit
9b2bf6b658
38
app/Components/About.tsx
Normal file
38
app/Components/About.tsx
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import { Box, Card, CardContent, Typography, Link, Button, Avatar, Stack } from "@mui/material";
|
||||||
|
import GitHubIcon from "@mui/icons-material/GitHub";
|
||||||
|
|
||||||
|
export default function About() {
|
||||||
|
const repo = "https://github.com/";
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box sx={{ display: "flex", justifyContent: "center", p: 3 }}>
|
||||||
|
<Card sx={{ maxWidth: 800, width: "100%" }}>
|
||||||
|
<CardContent>
|
||||||
|
<Stack direction="row" spacing={2} alignItems="center" sx={{ mb: 2 }}>
|
||||||
|
<Avatar sx={{ bgcolor: "primary.main" }}>
|
||||||
|
<GitHubIcon />
|
||||||
|
</Avatar>
|
||||||
|
<Typography variant="h5">Depin Web Client</Typography>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
<Typography variant="body1" color="text.secondary" paragraph>
|
||||||
|
Web client for the MSBD5017 Depin project.
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
<Typography variant="body2" paragraph>
|
||||||
|
In case the website is down, you can run your own local instance by following the instructions in the GitHub repository.
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
<Stack direction={{ xs: "column", sm: "row" }} spacing={2} alignItems="center">
|
||||||
|
<Link href={repo} target="_blank" rel="noopener noreferrer" underline="none">
|
||||||
|
<Button startIcon={<GitHubIcon />} variant="outlined">
|
||||||
|
Open GitHub Repository
|
||||||
|
</Button>
|
||||||
|
</Link>
|
||||||
|
</Stack>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// ...existing code...
|
||||||
126
app/Components/Metamask/NewDiscover.tsx
Normal file
126
app/Components/Metamask/NewDiscover.tsx
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
// ...existing code...
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import { useSyncProviders } from "./useSyncProviders";
|
||||||
|
import useAuth from "~/hooks/useAuth";
|
||||||
|
import type { EIP6963ProviderDetail } from "./EthereumProviderTypes";
|
||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Grid,
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
Avatar,
|
||||||
|
Typography,
|
||||||
|
Button,
|
||||||
|
Stack,
|
||||||
|
CircularProgress,
|
||||||
|
Alert,
|
||||||
|
} from "@mui/material";
|
||||||
|
|
||||||
|
const shortAddress = (addr: string) =>
|
||||||
|
addr.length > 12 ? `${addr.slice(0, 6)}...${addr.slice(-6)}` : addr;
|
||||||
|
|
||||||
|
export const DiscoverWalletProviders: React.FC = () => {
|
||||||
|
const providers = useSyncProviders();
|
||||||
|
const { auth, setAuth } = useAuth();
|
||||||
|
const [loadingUuid, setLoadingUuid] = useState<string | null>(null);
|
||||||
|
const [error, setError] = useState<string | null>(null);
|
||||||
|
|
||||||
|
const handleConnect = async (providerWithInfo: EIP6963ProviderDetail) => {
|
||||||
|
setError(null);
|
||||||
|
setLoadingUuid(providerWithInfo.info.uuid);
|
||||||
|
try {
|
||||||
|
const accounts = await providerWithInfo.provider.request({
|
||||||
|
method: "eth_requestAccounts",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (Array.isArray(accounts) && accounts.length > 0 && typeof accounts[0] === "string") {
|
||||||
|
setAuth({ providerWithInfo, accounts });
|
||||||
|
} else {
|
||||||
|
setError("No accounts returned from wallet.");
|
||||||
|
}
|
||||||
|
} catch (err: any) {
|
||||||
|
console.error(err);
|
||||||
|
setError(err?.message ?? String(err));
|
||||||
|
} finally {
|
||||||
|
setLoadingUuid(null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
<Typography variant="h6" gutterBottom>
|
||||||
|
Wallets Detected
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
{error && (
|
||||||
|
<Alert severity="error" sx={{ mb: 2 }}>
|
||||||
|
{error}
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{providers.length === 0 ? (
|
||||||
|
<Alert severity="info">There are no announced providers.</Alert>
|
||||||
|
) : (
|
||||||
|
<Grid container spacing={2}>
|
||||||
|
{providers.map((p) => (
|
||||||
|
<Grid size={{ xs: 12, sm: 6, md: 4 }} key={p.info.uuid}>
|
||||||
|
<Card variant="outlined">
|
||||||
|
<CardContent>
|
||||||
|
<Stack direction="row" spacing={2} alignItems="center">
|
||||||
|
<Avatar src={p.info.icon} alt={p.info.name} />
|
||||||
|
<Box sx={{ flex: 1 }}>
|
||||||
|
<Typography variant="subtitle1">{p.info.name}</Typography>
|
||||||
|
</Box>
|
||||||
|
<Box>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
onClick={() => handleConnect(p)}
|
||||||
|
disabled={!!loadingUuid}
|
||||||
|
startIcon={loadingUuid === p.info.uuid ? <CircularProgress size={18} /> : null}
|
||||||
|
aria-label={`Connect to ${p.info.name}`}
|
||||||
|
>
|
||||||
|
{loadingUuid === p.info.uuid ? "Connecting" : "Connect"}
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</Stack>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
</Grid>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Box sx={{ mt: 3 }}>
|
||||||
|
<Typography variant="h6" gutterBottom>
|
||||||
|
{auth?.accounts?.length > 0 ? "Wallet Selected" : "No Wallet Selected"}
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
{auth?.accounts?.length > 0 && auth.providerWithInfo && (
|
||||||
|
<Card variant="outlined">
|
||||||
|
<CardContent>
|
||||||
|
<Stack direction="row" spacing={2} alignItems="center">
|
||||||
|
<Avatar src={auth.providerWithInfo.info.icon} alt={auth.providerWithInfo.info.name} />
|
||||||
|
<Box sx={{ flex: 1 }}>
|
||||||
|
<Typography variant="subtitle1">{auth.providerWithInfo.info.name}</Typography>
|
||||||
|
<Typography variant="body2" color="text.secondary">
|
||||||
|
{shortAddress(auth.accounts[0])}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
onClick={() => setAuth({ providerWithInfo: { ...auth.providerWithInfo }, accounts: [] })}
|
||||||
|
aria-label="Disconnect wallet"
|
||||||
|
>
|
||||||
|
Disconnect
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DiscoverWalletProviders;
|
||||||
|
// ...existing code...
|
||||||
@ -2,9 +2,11 @@ import * as React from 'react';
|
|||||||
import ButtonGroup from '@mui/material/ButtonGroup';
|
import ButtonGroup from '@mui/material/ButtonGroup';
|
||||||
import Button from '@mui/material/Button';
|
import Button from '@mui/material/Button';
|
||||||
import Avatar from '@mui/material/Avatar';
|
import Avatar from '@mui/material/Avatar';
|
||||||
import { Grid, Card, CardContent, CardActions, Typography, Box, Chip } from "@mui/material";
|
import { Grid, Card, CardContent, CardActions, Typography, Box, Chip, Dialog, DialogTitle, DialogContent, DialogActions, TextField } from "@mui/material";
|
||||||
import ServerIcon from '@mui/icons-material/Dns';
|
import ServerIcon from '@mui/icons-material/Dns';
|
||||||
import SignalCellularAltIcon from '@mui/icons-material/SignalCellularAlt';
|
import SignalCellularAltIcon from '@mui/icons-material/SignalCellularAlt';
|
||||||
|
import AttachMoneyIcon from '@mui/icons-material/AttachMoney';
|
||||||
|
import Rating from '@mui/material/Rating';
|
||||||
import useAuth from '~/hooks/useAuth';
|
import useAuth from '~/hooks/useAuth';
|
||||||
import { signMessage } from './Metamask/Connections';
|
import { signMessage } from './Metamask/Connections';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
@ -12,10 +14,14 @@ import axios from 'axios';
|
|||||||
interface Node {
|
interface Node {
|
||||||
ip: string;
|
ip: string;
|
||||||
traffic: number;
|
traffic: number;
|
||||||
|
price : number;
|
||||||
}
|
}
|
||||||
|
|
||||||
function NodeItem({node}: {node: Node}) {
|
function NodeItem({node}: {node: Node}) {
|
||||||
const { auth } = useAuth();
|
const { auth } = useAuth();
|
||||||
|
const [ratingOpen, setRatingOpen] = React.useState(false);
|
||||||
|
const [ratingValue, setRatingValue] = React.useState<number | null>(null);
|
||||||
|
const [submittingRating, setSubmittingRating] = React.useState(false);
|
||||||
const connect = async ({ip}: {ip: string}) => {
|
const connect = async ({ip}: {ip: string}) => {
|
||||||
const res = await signMessage(auth.providerWithInfo.provider, auth.accounts[0]);
|
const res = await signMessage(auth.providerWithInfo.provider, auth.accounts[0]);
|
||||||
try {
|
try {
|
||||||
@ -28,7 +34,33 @@ function NodeItem({node}: {node: Node}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const disconnect = ({ip}: {ip: string}) => {
|
const disconnect = ({ip}: {ip: string}) => {
|
||||||
console.log("Disconnect from ", ip);
|
// TODO check code
|
||||||
|
setRatingOpen(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleCloseRating = () => {
|
||||||
|
setRatingOpen(false);
|
||||||
|
setRatingValue(null);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmitRating = async () => {
|
||||||
|
if (ratingValue == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setSubmittingRating(true);
|
||||||
|
try {
|
||||||
|
// await axios.post('http://' + node.ip + ":8080/rate", {
|
||||||
|
// rating: ratingValue,
|
||||||
|
// }, {
|
||||||
|
// headers: { "Content-Type": "application/json" }
|
||||||
|
// });
|
||||||
|
// console.log('Rating submitted');
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Failed to submit rating', err);
|
||||||
|
} finally {
|
||||||
|
setSubmittingRating(false);
|
||||||
|
handleCloseRating();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -56,6 +88,19 @@ function NodeItem({node}: {node: Node}) {
|
|||||||
variant="outlined"
|
variant="outlined"
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
|
||||||
|
<AttachMoneyIcon color="action" fontSize="small" />
|
||||||
|
<Typography variant="body2" color="text.secondary">
|
||||||
|
Price:
|
||||||
|
</Typography>
|
||||||
|
<Chip
|
||||||
|
label={node.price}
|
||||||
|
size="small"
|
||||||
|
color={node.price > 15 ? "warning" : "success"}
|
||||||
|
variant="outlined"
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
<CardActions sx={{ justifyContent: 'flex-end', p: 2, pt: 0 }}>
|
<CardActions sx={{ justifyContent: 'flex-end', p: 2, pt: 0 }}>
|
||||||
<ButtonGroup
|
<ButtonGroup
|
||||||
@ -79,12 +124,30 @@ function NodeItem({node}: {node: Node}) {
|
|||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
</CardActions>
|
</CardActions>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
<Dialog open={ratingOpen} onClose={handleCloseRating}>
|
||||||
|
<DialogTitle>Rate this server</DialogTitle>
|
||||||
|
<DialogContent sx={{ display: 'flex', flexDirection: 'column', gap: 2, minWidth: 320 }}>
|
||||||
|
<Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>
|
||||||
|
<Typography component="span">Your rating:</Typography>
|
||||||
|
<Rating
|
||||||
|
name={`server-rating-${node.ip}`}
|
||||||
|
value={ratingValue}
|
||||||
|
onChange={(_, newValue) => setRatingValue(newValue)}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button onClick={handleCloseRating} disabled={submittingRating}>Cancel</Button>
|
||||||
|
<Button onClick={handleSubmitRating} disabled={submittingRating || ratingValue == null} variant="contained">Submit</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
</Grid>
|
</Grid>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function FolderList() {
|
export default function FolderList() {
|
||||||
const [nodes, setNodes] = React.useState([{ip: "57.158.82.48", traffic: 5},{ip: "10.0.0.3", traffic: 3},{ip: "10.0.0.4", traffic: 7}]);
|
const [nodes, setNodes] = React.useState([{ip: "57.158.82.48", traffic: 5, price: 10},{ip: "57.158.82.47", traffic: 3, price: 15},{ip: "57.158.82.49", traffic: 7, price: 20}]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box sx={{ flexGrow: 1, p: 3 }}>
|
<Box sx={{ flexGrow: 1, p: 3 }}>
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
|
import About from "~/Components/About";
|
||||||
|
|
||||||
|
|
||||||
|
export default function AboutPage() {
|
||||||
export default function About() {
|
|
||||||
return(
|
return(
|
||||||
<h3>About Page</h3>
|
<About />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1,7 +1,10 @@
|
|||||||
import { DiscoverWalletProviders } from "~/Components/Metamask/DiscoverWalletProviders";
|
import { DiscoverWalletProviders } from "~/Components/Metamask/DiscoverWalletProviders";
|
||||||
|
import NewDiscover from "~/Components/Metamask/NewDiscover";
|
||||||
|
|
||||||
|
|
||||||
export default function Wallets() {
|
export default function Wallets() {
|
||||||
return(
|
return(
|
||||||
<DiscoverWalletProviders />
|
// <DiscoverWalletProviders />
|
||||||
|
<NewDiscover />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
15
package-lock.json
generated
15
package-lock.json
generated
@ -60,7 +60,6 @@
|
|||||||
"integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==",
|
"integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/code-frame": "^7.27.1",
|
"@babel/code-frame": "^7.27.1",
|
||||||
"@babel/generator": "^7.28.5",
|
"@babel/generator": "^7.28.5",
|
||||||
@ -566,7 +565,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz",
|
"resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz",
|
||||||
"integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==",
|
"integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.18.3",
|
"@babel/runtime": "^7.18.3",
|
||||||
"@emotion/babel-plugin": "^11.13.5",
|
"@emotion/babel-plugin": "^11.13.5",
|
||||||
@ -610,7 +608,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.1.tgz",
|
"resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.1.tgz",
|
||||||
"integrity": "sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw==",
|
"integrity": "sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.18.3",
|
"@babel/runtime": "^7.18.3",
|
||||||
"@emotion/babel-plugin": "^11.13.5",
|
"@emotion/babel-plugin": "^11.13.5",
|
||||||
@ -1209,7 +1206,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@mui/material/-/material-7.3.5.tgz",
|
"resolved": "https://registry.npmjs.org/@mui/material/-/material-7.3.5.tgz",
|
||||||
"integrity": "sha512-8VVxFmp1GIm9PpmnQoCoYo0UWHoOrdA57tDL62vkpzEgvb/d71Wsbv4FRg7r1Gyx7PuSo0tflH34cdl/NvfHNQ==",
|
"integrity": "sha512-8VVxFmp1GIm9PpmnQoCoYo0UWHoOrdA57tDL62vkpzEgvb/d71Wsbv4FRg7r1Gyx7PuSo0tflH34cdl/NvfHNQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.28.4",
|
"@babel/runtime": "^7.28.4",
|
||||||
"@mui/core-downloads-tracker": "^7.3.5",
|
"@mui/core-downloads-tracker": "^7.3.5",
|
||||||
@ -1598,7 +1594,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@react-router/serve/-/serve-7.9.6.tgz",
|
"resolved": "https://registry.npmjs.org/@react-router/serve/-/serve-7.9.6.tgz",
|
||||||
"integrity": "sha512-qIT8hp1RJ0VAHyXpfuwoO31b9evrjPLRhUugqYJ7BZLpyAwhRsJIaQvvj60yZwWBMF2/3LdZu7M39rf0FhL6Iw==",
|
"integrity": "sha512-qIT8hp1RJ0VAHyXpfuwoO31b9evrjPLRhUugqYJ7BZLpyAwhRsJIaQvvj60yZwWBMF2/3LdZu7M39rf0FhL6Iw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mjackson/node-fetch-server": "^0.2.0",
|
"@mjackson/node-fetch-server": "^0.2.0",
|
||||||
"@react-router/express": "7.9.6",
|
"@react-router/express": "7.9.6",
|
||||||
@ -2219,7 +2214,6 @@
|
|||||||
"integrity": "sha512-LCCV0HdSZZZb34qifBsyWlUmok6W7ouER+oQIGBScS8EsZsQbrtFTUrDX4hOl+CS6p7cnNC4td+qrSVGSCTUfQ==",
|
"integrity": "sha512-LCCV0HdSZZZb34qifBsyWlUmok6W7ouER+oQIGBScS8EsZsQbrtFTUrDX4hOl+CS6p7cnNC4td+qrSVGSCTUfQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"undici-types": "~6.21.0"
|
"undici-types": "~6.21.0"
|
||||||
}
|
}
|
||||||
@ -2241,7 +2235,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.6.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.6.tgz",
|
||||||
"integrity": "sha512-p/jUvulfgU7oKtj6Xpk8cA2Y1xKTtICGpJYeJXz2YVO2UcvjQgeRMLDGfDeqeRW2Ta+0QNFwcc8X3GH8SxZz6w==",
|
"integrity": "sha512-p/jUvulfgU7oKtj6Xpk8cA2Y1xKTtICGpJYeJXz2YVO2UcvjQgeRMLDGfDeqeRW2Ta+0QNFwcc8X3GH8SxZz6w==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"csstype": "^3.2.2"
|
"csstype": "^3.2.2"
|
||||||
}
|
}
|
||||||
@ -2495,7 +2488,6 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"baseline-browser-mapping": "^2.8.25",
|
"baseline-browser-mapping": "^2.8.25",
|
||||||
"caniuse-lite": "^1.0.30001754",
|
"caniuse-lite": "^1.0.30001754",
|
||||||
@ -3134,7 +3126,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz",
|
"resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz",
|
||||||
"integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==",
|
"integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"accepts": "~1.3.8",
|
"accepts": "~1.3.8",
|
||||||
"array-flatten": "1.1.1",
|
"array-flatten": "1.1.1",
|
||||||
@ -4465,7 +4456,6 @@
|
|||||||
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
},
|
},
|
||||||
@ -4629,7 +4619,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz",
|
||||||
"integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==",
|
"integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
@ -4639,7 +4628,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz",
|
||||||
"integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==",
|
"integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"scheduler": "^0.27.0"
|
"scheduler": "^0.27.0"
|
||||||
},
|
},
|
||||||
@ -4668,7 +4656,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-7.9.6.tgz",
|
"resolved": "https://registry.npmjs.org/react-router/-/react-router-7.9.6.tgz",
|
||||||
"integrity": "sha512-Y1tUp8clYRXpfPITyuifmSoE2vncSME18uVLgaqyxh9H35JWpIfzHo+9y3Fzh5odk/jxPW29IgLgzcdwxGqyNA==",
|
"integrity": "sha512-Y1tUp8clYRXpfPITyuifmSoE2vncSME18uVLgaqyxh9H35JWpIfzHo+9y3Fzh5odk/jxPW29IgLgzcdwxGqyNA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cookie": "^1.0.1",
|
"cookie": "^1.0.1",
|
||||||
"set-cookie-parser": "^2.6.0"
|
"set-cookie-parser": "^2.6.0"
|
||||||
@ -5317,7 +5304,6 @@
|
|||||||
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"peer": true,
|
|
||||||
"bin": {
|
"bin": {
|
||||||
"tsc": "bin/tsc",
|
"tsc": "bin/tsc",
|
||||||
"tsserver": "bin/tsserver"
|
"tsserver": "bin/tsserver"
|
||||||
@ -5433,7 +5419,6 @@
|
|||||||
"integrity": "sha512-NL8jTlbo0Tn4dUEXEsUg8KeyG/Lkmc4Fnzb8JXN/Ykm9G4HNImjtABMJgkQoVjOBN/j2WAwDTRytdqJbZsah7w==",
|
"integrity": "sha512-NL8jTlbo0Tn4dUEXEsUg8KeyG/Lkmc4Fnzb8JXN/Ykm9G4HNImjtABMJgkQoVjOBN/j2WAwDTRytdqJbZsah7w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"esbuild": "^0.25.0",
|
"esbuild": "^0.25.0",
|
||||||
"fdir": "^6.5.0",
|
"fdir": "^6.5.0",
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user