mirror of
https://github.com/Qortal/Qortal-Hub.git
synced 2025-04-23 19:37:52 +00:00
added note status indicator
This commit is contained in:
parent
e3a6d826f9
commit
e4f70b9070
@ -116,6 +116,7 @@ import { NotAuthenticated } from "./ExtStates/NotAuthenticated";
|
|||||||
import { openIndexedDB, showSaveFilePicker } from "./components/Apps/useQortalMessageListener";
|
import { openIndexedDB, showSaveFilePicker } from "./components/Apps/useQortalMessageListener";
|
||||||
import { fileToBase64 } from "./utils/fileReading";
|
import { fileToBase64 } from "./utils/fileReading";
|
||||||
import { handleGetFileFromIndexedDB } from "./utils/indexedDB";
|
import { handleGetFileFromIndexedDB } from "./utils/indexedDB";
|
||||||
|
import { CoreSyncStatus } from "./components/CoreSyncStatus";
|
||||||
|
|
||||||
|
|
||||||
type extStates =
|
type extStates =
|
||||||
@ -1458,6 +1459,8 @@ function App() {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
<Spacer height="20px" />
|
||||||
|
<CoreSyncStatus />
|
||||||
</AuthenticatedContainerInnerRight>
|
</AuthenticatedContainerInnerRight>
|
||||||
</AuthenticatedContainer>
|
</AuthenticatedContainer>
|
||||||
);
|
);
|
||||||
|
BIN
src/assets/syncStatus/synced.png
Normal file
BIN
src/assets/syncStatus/synced.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
BIN
src/assets/syncStatus/synced_minting.png
Normal file
BIN
src/assets/syncStatus/synced_minting.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
BIN
src/assets/syncStatus/syncing.png
Normal file
BIN
src/assets/syncStatus/syncing.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
59
src/components/CoreSyncStatus.css
Normal file
59
src/components/CoreSyncStatus.css
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
.lineHeight {
|
||||||
|
line-height: 33%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip {
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip .bottom {
|
||||||
|
min-width: 200px;
|
||||||
|
max-width: 250px;
|
||||||
|
top: 35px;
|
||||||
|
right: 0px;
|
||||||
|
/* transform: translate(-50%, 0); */
|
||||||
|
padding: 10px 10px;
|
||||||
|
color: var(--black);
|
||||||
|
background-color: var(--bg-2);
|
||||||
|
font-weight: normal;
|
||||||
|
font-size: 13px;
|
||||||
|
border-radius: 8px;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 99999999;
|
||||||
|
box-sizing: border-box;
|
||||||
|
box-shadow: 0 1px 8px rgba(0, 0, 0, 0.5);
|
||||||
|
border: 1px solid var(--black);
|
||||||
|
visibility: hidden;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip:hover .bottom {
|
||||||
|
visibility: visible;
|
||||||
|
opacity: 1;
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip .bottom i {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 100%;
|
||||||
|
left: 50%;
|
||||||
|
margin-left: -12px;
|
||||||
|
width: 24px;
|
||||||
|
height: 12px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip .bottom i::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, 50%) rotate(45deg);
|
||||||
|
background-color: var(--white);
|
||||||
|
border: 1px solid var(--black);
|
||||||
|
box-shadow: 0 1px 8px rgba(0, 0, 0, 0.5);
|
||||||
|
}
|
105
src/components/CoreSyncStatus.tsx
Normal file
105
src/components/CoreSyncStatus.tsx
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import syncedImg from '../assets/syncStatus/synced.png'
|
||||||
|
import syncedMintingImg from '../assets/syncStatus/synced.png'
|
||||||
|
import syncingImg from '../assets/syncStatus/synced.png'
|
||||||
|
import { getBaseApiReact } from '../App';
|
||||||
|
import './CoreSyncStatus.css'
|
||||||
|
export const CoreSyncStatus = () => {
|
||||||
|
const [nodeInfos, setNodeInfos] = useState({});
|
||||||
|
const [coreInfos, setCoreInfos] = useState({});
|
||||||
|
const [isUsingGateway, setIsUsingGateway] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const getNodeInfos = async () => {
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
setIsUsingGateway(!!getBaseApiReact()?.includes('ext-node.qortal.link'))
|
||||||
|
const url = `${getBaseApiReact()}/admin/status`;
|
||||||
|
const response = await fetch(url, {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const data = await response.json();
|
||||||
|
setNodeInfos(data);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Request failed', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getCoreInfos = async () => {
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
const url = `${getBaseApiReact()}/admin/info`;
|
||||||
|
const response = await fetch(url, {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const data = await response.json();
|
||||||
|
setCoreInfos(data);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Request failed', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
getNodeInfos();
|
||||||
|
getCoreInfos();
|
||||||
|
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
getNodeInfos();
|
||||||
|
getCoreInfos();
|
||||||
|
}, 30000);
|
||||||
|
|
||||||
|
return () => clearInterval(interval);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const renderSyncStatusIcon = () => {
|
||||||
|
const { isSynchronizing = false, syncPercent = 0, isMintingPossible = false, height = 0, numberOfConnections = 0 } = nodeInfos;
|
||||||
|
const buildVersion = coreInfos?.buildVersion ? coreInfos?.buildVersion.substring(0, 12) : '';
|
||||||
|
|
||||||
|
let imagePath = '/img/syncing.png';
|
||||||
|
let message = `Synchronizing`
|
||||||
|
if (isSynchronizing === true && syncPercent === 99) {
|
||||||
|
imagePath = syncedImg
|
||||||
|
} else if (isSynchronizing && !isMintingPossible && syncPercent === 100) {
|
||||||
|
imagePath = syncingImg;
|
||||||
|
message = `Synchronized (Not Minting)`
|
||||||
|
} else if (!isSynchronizing && !isMintingPossible && syncPercent === 100) {
|
||||||
|
imagePath = syncingImg;
|
||||||
|
message = `Synchronized (Not Minting)`
|
||||||
|
} else if (isSynchronizing && isMintingPossible && syncPercent === 100) {
|
||||||
|
imagePath = syncedMintingImg;
|
||||||
|
message = `Synchronized (Minting)`
|
||||||
|
} else if (!isSynchronizing && isMintingPossible && syncPercent === 100) {
|
||||||
|
imagePath = syncedMintingImg;
|
||||||
|
message = `Synchronized (Minting)`
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="tooltip" style={{ display: 'inline' }}>
|
||||||
|
<span><img src={imagePath} style={{ height: 'auto', width: '24px' }} alt="sync status" /></span>
|
||||||
|
<div className="bottom">
|
||||||
|
<h3>Core Information</h3>
|
||||||
|
<h4 className="lineHeight">Core Version: <span style={{ color: '#03a9f4' }}>{buildVersion}</span></h4>
|
||||||
|
<h4 className="lineHeight">{message}</h4>
|
||||||
|
<h4 className="lineHeight">Block Height: <span style={{ color: '#03a9f4' }}>{height || ''}</span></h4>
|
||||||
|
<h4 className="lineHeight">Connected Peers: <span style={{ color: '#03a9f4' }}>{numberOfConnections || ''}</span></h4>
|
||||||
|
<h4 className="lineHeight">Using gateway: <span style={{ color: '#03a9f4' }}>{isUsingGateway?.toString()}</span></h4>
|
||||||
|
<i></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div id="core-sync-status-id">
|
||||||
|
{renderSyncStatusIcon()}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user