forked from Qortal/Q-Nodecontrol
Initial commit
This commit is contained in:
2
.gitattributes
vendored
Normal file
2
.gitattributes
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
||||
24
.gitignore
vendored
Normal file
24
.gitignore
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 AlphaX-Qortal
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
19
README.md
Normal file
19
README.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# Q-Nodecontrol - Vite.js and TypeScript
|
||||
|
||||
## How to use
|
||||
|
||||
Download the source [or clone the repo](https://github.com/AlphaX-Qortal/Q-Nodecontrol):
|
||||
|
||||
Install it and run development:
|
||||
|
||||
```bash
|
||||
npm install
|
||||
npm run dev -- --host
|
||||
```
|
||||
|
||||
Install it and build production:
|
||||
|
||||
```bash
|
||||
npm install
|
||||
npm run build
|
||||
```
|
||||
16
index.html
Normal file
16
index.html
Normal file
@@ -0,0 +1,16 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" type="image/png" href="/qnc.png" />
|
||||
<meta name="viewport" content="initial-scale=1, width=device-width" />
|
||||
<title>Qortal Nodecontrol</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
2541
package-lock.json
generated
Normal file
2541
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
31
package.json
Normal file
31
package.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "q-nodecontrol",
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "tsc && vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@emotion/react": "11.14.0",
|
||||
"@emotion/styled": "11.14.0",
|
||||
"@mui/icons-material": "7.0.0",
|
||||
"@mui/material": "7.0.0",
|
||||
"@fontsource/lato": "^5.2.5",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0",
|
||||
"react-icons": "^5.5.0",
|
||||
"react-router": "^7.4.0",
|
||||
"react-router-dom": "^7.4.0",
|
||||
"react-window": "^1.8.11"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "19.0.12",
|
||||
"@types/react-dom": "19.0.4",
|
||||
"@vitejs/plugin-react": "4.3.4",
|
||||
"typescript": "5.8.2",
|
||||
"vite": "6.2.3"
|
||||
}
|
||||
}
|
||||
BIN
public/qnc.png
Normal file
BIN
public/qnc.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
1180
src/App.tsx
Normal file
1180
src/App.tsx
Normal file
File diff suppressed because it is too large
Load Diff
BIN
src/assets/noavatar.png
Normal file
BIN
src/assets/noavatar.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.4 KiB |
BIN
src/assets/q-nodecontrol.png
Normal file
BIN
src/assets/q-nodecontrol.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
84
src/components/NodeWidget.tsx
Normal file
84
src/components/NodeWidget.tsx
Normal file
@@ -0,0 +1,84 @@
|
||||
import * as React from 'react';
|
||||
import { FC, createElement } from 'react';
|
||||
import {
|
||||
Card,
|
||||
Box,
|
||||
Typography,
|
||||
Divider
|
||||
} from '@mui/material';
|
||||
|
||||
interface Props {
|
||||
icon: FC<any>;
|
||||
title?: string;
|
||||
subtitle?: React.ReactNode;
|
||||
children?: React.ReactNode;
|
||||
};
|
||||
|
||||
const NodeWidget = ({ icon, title, subtitle, children }: Props) => (
|
||||
<Card
|
||||
sx={{
|
||||
minHeight: 52,
|
||||
minWidth: '280px',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
flex: '1',
|
||||
borderRadius: '10px'
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
position: 'relative',
|
||||
overflow: 'hidden',
|
||||
padding: '16px',
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
'& .icon': {
|
||||
color: '#05a2e4',
|
||||
},
|
||||
'&:before': {
|
||||
position: 'absolute',
|
||||
top: '30%',
|
||||
left: -65,
|
||||
display: 'block',
|
||||
content: `''`,
|
||||
height: '200%',
|
||||
aspectRatio: '1',
|
||||
transform: 'translate(-30%, -60%)',
|
||||
borderRadius: '50%',
|
||||
backgroundColor: '#05a2e4',
|
||||
opacity: 0.15
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
width="5em"
|
||||
className="icon"
|
||||
sx={{
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
paddingRight: '48px',
|
||||
paddingBottom: '30px'
|
||||
}}
|
||||
>
|
||||
{createElement(icon, { fontSize: 'xlarge' })}
|
||||
</Box>
|
||||
<Box textAlign="right">
|
||||
<Typography
|
||||
color="textSecondary"
|
||||
sx={{ fontFamily: 'magistralbold' }}
|
||||
>
|
||||
{title}
|
||||
</Typography>
|
||||
<Typography variant="h5" component="h2">
|
||||
{subtitle || ' '}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
{children && <Divider />}
|
||||
{children}
|
||||
</Card>
|
||||
);
|
||||
|
||||
export default NodeWidget;
|
||||
BIN
src/fonts/Magistral-Bold.woff2
Normal file
BIN
src/fonts/Magistral-Bold.woff2
Normal file
Binary file not shown.
68
src/global.d.ts
vendored
Normal file
68
src/global.d.ts
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
interface QortalRequestOptions {
|
||||
action: string;
|
||||
name?: string;
|
||||
service?: string;
|
||||
data64?: string;
|
||||
title?: string;
|
||||
description?: string;
|
||||
category?: string;
|
||||
tags?: string[] | string;
|
||||
identifier?: string;
|
||||
address?: string;
|
||||
metaData?: string;
|
||||
encoding?: string;
|
||||
includeMetadata?: boolean;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
reverse?: boolean;
|
||||
resources?: any[];
|
||||
filename?: string;
|
||||
list_name?: string;
|
||||
item?: string;
|
||||
items?: string[];
|
||||
tag1?: string;
|
||||
tag2?: string;
|
||||
tag3?: string;
|
||||
tag4?: string;
|
||||
tag5?: string;
|
||||
coin?: string;
|
||||
destinationAddress?: string;
|
||||
amount?: number | Number;
|
||||
recipient?: string;
|
||||
fee?: number | any;
|
||||
blob?: Blob;
|
||||
mimeType?: string;
|
||||
file?: File;
|
||||
encryptedData?: string;
|
||||
mode?: string;
|
||||
query?: string;
|
||||
excludeBlocked?: boolean;
|
||||
exactMatchNames?: boolean;
|
||||
creationBytes?: string;
|
||||
type?: string;
|
||||
host?: string;
|
||||
port?: number;
|
||||
assetId?: number;
|
||||
confirmationStatus?: string;
|
||||
startBlock?: number;
|
||||
blockLimit?: number;
|
||||
txGroupId?: number;
|
||||
memo?: string;
|
||||
value?: string | any;
|
||||
};
|
||||
|
||||
declare function qortalRequest(
|
||||
options: QortalRequestOptions
|
||||
): Promise<any>;
|
||||
|
||||
declare function qortalRequestWithTimeout(
|
||||
options: QortalRequestOptions,
|
||||
time: number
|
||||
): Promise<any>;
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
_qdnBase: any;
|
||||
_qdnTheme: string;
|
||||
}
|
||||
};
|
||||
41
src/main.tsx
Normal file
41
src/main.tsx
Normal file
@@ -0,0 +1,41 @@
|
||||
import * as React from 'react';
|
||||
import * as ReactDOM from 'react-dom/client';
|
||||
import { BrowserRouter, To, useNavigate } from "react-router-dom";
|
||||
import App from './App';
|
||||
|
||||
interface CustomWindow extends Window {
|
||||
_qdnBase: string;
|
||||
};
|
||||
|
||||
const customWindow = window as unknown as CustomWindow;
|
||||
const baseUrl = customWindow?._qdnBase || "";
|
||||
|
||||
export const useIframe = () => {
|
||||
const navigate = useNavigate();
|
||||
React.useEffect(() => {
|
||||
function handleNavigation(event: { data: { action: string; path: To; }; }) {
|
||||
if (event.data?.action === "NAVIGATE_TO_PATH" && event.data.path) {
|
||||
navigate(event.data.path); // Navigate directly to the specified path
|
||||
|
||||
// Send a response back to the parent window after navigation is handled
|
||||
window.parent.postMessage(
|
||||
{ action: "NAVIGATION_SUCCESS", path: event.data.path },
|
||||
"*"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("message", handleNavigation);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("message", handleNavigation);
|
||||
};
|
||||
}, [navigate]);
|
||||
return { navigate };
|
||||
};
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root')!).render(
|
||||
<BrowserRouter basename={baseUrl}>
|
||||
<App />
|
||||
</BrowserRouter>
|
||||
);
|
||||
1
src/vite-env.d.ts
vendored
Normal file
1
src/vite-env.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/// <reference types="vite/client" />
|
||||
27
tsconfig.json
Normal file
27
tsconfig.json
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": [
|
||||
"ES2020",
|
||||
"DOM",
|
||||
"DOM.Iterable"
|
||||
],
|
||||
"module": "ESNext",
|
||||
"skipLibCheck": true,
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx"
|
||||
},
|
||||
"include": [
|
||||
"src"
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.node.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
13
tsconfig.node.json
Normal file
13
tsconfig.node.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"skipLibCheck": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true
|
||||
},
|
||||
"include": [
|
||||
"vite.config.ts"
|
||||
]
|
||||
}
|
||||
10
vite.config.ts
Normal file
10
vite.config.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { defineConfig } from 'vite';
|
||||
import react from '@vitejs/plugin-react';
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
base: "",
|
||||
build: {
|
||||
chunkSizeWarningLimit: 5000,
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user