forked from snxraven/p2ns
feat: consolidate utility functions into P2NS Plugin SDK
- Centralized common formatting, DOM, and status utilities in `includes/plugins/sdk.js` - Created `sdk.utils.format`, `sdk.utils.dom`, and `sdk.utils.status` namespaces - Refactored `domain.consensus` and `peer.visualize` plugins to use the global SDK - Updated `plugin-handler` to serve SDK utilities globally via `/sdk-utils.js` - Enhanced SDK validation by delegating to the core validation infrastructure - Fixed bugs in metric rendering and missing frontend utility functions
This commit is contained in:
@@ -176,6 +176,7 @@
|
||||
</div>
|
||||
|
||||
<!-- Scripts -->
|
||||
<script src="/sdk-utils.js"></script>
|
||||
<script src="/js/utils.js"></script>
|
||||
<script src="/js/api.js"></script>
|
||||
<script src="/js/websocket.js"></script>
|
||||
|
||||
@@ -1,103 +1,48 @@
|
||||
/**
|
||||
* Utility functions for domain consensus plugin
|
||||
* Now using P2NS Plugin SDK for common utilities
|
||||
*/
|
||||
|
||||
/**
|
||||
* Format a timestamp to human-readable string
|
||||
*/
|
||||
function formatTimestamp(timestamp) {
|
||||
if (!timestamp) return 'Never';
|
||||
const date = new Date(timestamp);
|
||||
const now = new Date();
|
||||
const diff = now - date;
|
||||
|
||||
if (diff < 60000) {
|
||||
return `${Math.floor(diff / 1000)}s ago`;
|
||||
} else if (diff < 3600000) {
|
||||
return `${Math.floor(diff / 60000)}m ago`;
|
||||
} else if (diff < 86400000) {
|
||||
return `${Math.floor(diff / 3600000)}h ago`;
|
||||
} else {
|
||||
return date.toLocaleString();
|
||||
}
|
||||
return window.sdk?.utils?.format?.formatTimestamp(timestamp) || 'Never';
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a peer ID to shortened version
|
||||
*/
|
||||
function formatPeerId(peerId) {
|
||||
if (!peerId) return 'N/A';
|
||||
if (peerId.length <= 16) return peerId;
|
||||
return `${peerId.slice(0, 8)}...${peerId.slice(-8)}`;
|
||||
return window.sdk?.utils?.format?.formatPeerId(peerId) || 'N/A';
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a hash to shortened version
|
||||
*/
|
||||
function formatHash(hash) {
|
||||
if (!hash) return 'N/A';
|
||||
if (hash.length <= 20) return hash;
|
||||
return `${hash.slice(0, 10)}...${hash.slice(-10)}`;
|
||||
return window.sdk?.utils?.format?.formatHash(hash) || 'N/A';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get status badge class based on consensus status
|
||||
*/
|
||||
function getStatusBadgeClass(status) {
|
||||
switch (status) {
|
||||
case 'resolved':
|
||||
return 'status-badge resolved';
|
||||
case 'insufficient_quorum':
|
||||
return 'status-badge insufficient_quorum';
|
||||
case 'tie':
|
||||
return 'status-badge tie';
|
||||
case 'no_claims':
|
||||
return 'status-badge no_claims';
|
||||
case 'error':
|
||||
return 'status-badge error';
|
||||
default:
|
||||
return 'status-badge no_claims';
|
||||
}
|
||||
return window.sdk?.utils?.status?.getConsensusBadgeClass(status) || 'status-badge no_claims';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get status text for consensus status
|
||||
*/
|
||||
function getStatusText(status) {
|
||||
switch (status) {
|
||||
case 'resolved':
|
||||
return 'Resolved';
|
||||
case 'insufficient_quorum':
|
||||
return 'Insufficient Quorum';
|
||||
case 'tie':
|
||||
return 'Tie';
|
||||
case 'no_claims':
|
||||
return 'No Claims';
|
||||
case 'error':
|
||||
return 'Error';
|
||||
default:
|
||||
return 'Unknown';
|
||||
}
|
||||
return window.sdk?.utils?.status?.getConsensusText(status) || 'Unknown';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get status color for consensus status
|
||||
*/
|
||||
function getStatusColor(status) {
|
||||
switch (status) {
|
||||
case 'resolved':
|
||||
return '#10b981'; // green-500
|
||||
case 'insufficient_quorum':
|
||||
return '#eab308'; // yellow-500
|
||||
case 'tie':
|
||||
return '#f97316'; // orange-500
|
||||
case 'no_claims':
|
||||
return '#6b7280'; // gray-500
|
||||
case 'error':
|
||||
return '#ef4444'; // red-500
|
||||
default:
|
||||
return '#6b7280'; // gray-500
|
||||
}
|
||||
return window.sdk?.utils?.status?.getConsensusColor(status) || '#6b7280';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -112,58 +57,34 @@ function calculateQuorumPercentage(totalVotes, minVotes) {
|
||||
* Escape HTML to prevent XSS
|
||||
*/
|
||||
function escapeHtml(text) {
|
||||
const div = document.createElement('div');
|
||||
div.textContent = text;
|
||||
return div.innerHTML;
|
||||
return window.sdk?.utils?.dom?.escapeHtml(text) || text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy text to clipboard
|
||||
*/
|
||||
async function copyToClipboard(text) {
|
||||
try {
|
||||
await navigator.clipboard.writeText(text);
|
||||
return true;
|
||||
} catch (err) {
|
||||
// Fallback for older browsers
|
||||
const textArea = document.createElement('textarea');
|
||||
textArea.value = text;
|
||||
textArea.style.position = 'fixed';
|
||||
textArea.style.opacity = '0';
|
||||
document.body.appendChild(textArea);
|
||||
textArea.select();
|
||||
try {
|
||||
document.execCommand('copy');
|
||||
document.body.removeChild(textArea);
|
||||
return true;
|
||||
} catch (err) {
|
||||
document.body.removeChild(textArea);
|
||||
return false;
|
||||
}
|
||||
if (window.sdk?.utils?.dom?.copyToClipboard) {
|
||||
return await window.sdk.utils.dom.copyToClipboard(text);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Debounce function
|
||||
*/
|
||||
function debounce(func, wait) {
|
||||
let timeout;
|
||||
return function executedFunction(...args) {
|
||||
const later = () => {
|
||||
clearTimeout(timeout);
|
||||
func(...args);
|
||||
};
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(later, wait);
|
||||
};
|
||||
if (window.sdk?.utils?.dom?.debounce) {
|
||||
return window.sdk.utils.dom.debounce(func, wait);
|
||||
}
|
||||
return func;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format number with commas
|
||||
*/
|
||||
function formatNumber(num) {
|
||||
if (num === null || num === undefined) return '0';
|
||||
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
||||
return window.sdk?.utils?.format?.formatNumber(num) || '0';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -229,4 +150,3 @@ window.utils = {
|
||||
createProgressBar,
|
||||
updateSidebarStats
|
||||
};
|
||||
|
||||
|
||||
@@ -261,6 +261,7 @@
|
||||
</div>
|
||||
|
||||
<!-- Scripts -->
|
||||
<script src="/sdk-utils.js"></script>
|
||||
<script src="/js/utils.js"></script>
|
||||
<script src="/js/data-processor.js"></script>
|
||||
<script src="/js/websocket-client.js"></script>
|
||||
|
||||
@@ -1,60 +1,27 @@
|
||||
/**
|
||||
* Utility functions for peer.visualize
|
||||
* Now using P2NS Plugin SDK for common utilities
|
||||
*/
|
||||
|
||||
/**
|
||||
* Format peer ID (short or long)
|
||||
*/
|
||||
function formatPeerId(peerId, short = true) {
|
||||
if (!peerId) return 'Unknown';
|
||||
if (short) {
|
||||
return peerId.slice(0, 16) + '...';
|
||||
}
|
||||
return peerId;
|
||||
return window.sdk?.utils?.format?.formatPeerId(peerId, short) || 'Unknown';
|
||||
}
|
||||
|
||||
/**
|
||||
* Format timestamp to readable string
|
||||
*/
|
||||
function formatTimestamp(timestamp) {
|
||||
if (!timestamp) return 'Never';
|
||||
const date = new Date(timestamp);
|
||||
const now = new Date();
|
||||
const diff = now - date;
|
||||
|
||||
if (diff < 60000) {
|
||||
return 'Just now';
|
||||
} else if (diff < 3600000) {
|
||||
const minutes = Math.floor(diff / 60000);
|
||||
return `${minutes} minute${minutes !== 1 ? 's' : ''} ago`;
|
||||
} else if (diff < 86400000) {
|
||||
const hours = Math.floor(diff / 3600000);
|
||||
return `${hours} hour${hours !== 1 ? 's' : ''} ago`;
|
||||
} else {
|
||||
return date.toLocaleDateString() + ' ' + date.toLocaleTimeString();
|
||||
}
|
||||
return window.sdk?.utils?.format?.formatTimestamp(timestamp) || 'Never';
|
||||
}
|
||||
|
||||
/**
|
||||
* Format duration (milliseconds to readable string)
|
||||
*/
|
||||
function formatDuration(ms) {
|
||||
if (!ms || ms === 0) return '0s';
|
||||
|
||||
const seconds = Math.floor(ms / 1000);
|
||||
const minutes = Math.floor(seconds / 60);
|
||||
const hours = Math.floor(minutes / 60);
|
||||
const days = Math.floor(hours / 24);
|
||||
|
||||
if (days > 0) {
|
||||
return `${days}d ${hours % 24}h`;
|
||||
} else if (hours > 0) {
|
||||
return `${hours}h ${minutes % 60}m`;
|
||||
} else if (minutes > 0) {
|
||||
return `${minutes}m ${seconds % 60}s`;
|
||||
} else {
|
||||
return `${seconds}s`;
|
||||
}
|
||||
return window.sdk?.utils?.format?.formatDuration(ms) || '0s';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -79,29 +46,20 @@ function getNodeColor(node) {
|
||||
* Debounce function
|
||||
*/
|
||||
function debounce(func, wait) {
|
||||
let timeout;
|
||||
return function executedFunction(...args) {
|
||||
const later = () => {
|
||||
clearTimeout(timeout);
|
||||
func(...args);
|
||||
};
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(later, wait);
|
||||
};
|
||||
if (window.sdk?.utils?.dom?.debounce) {
|
||||
return window.sdk.utils.dom.debounce(func, wait);
|
||||
}
|
||||
return func;
|
||||
}
|
||||
|
||||
/**
|
||||
* Throttle function
|
||||
*/
|
||||
function throttle(func, limit) {
|
||||
let inThrottle;
|
||||
return function(...args) {
|
||||
if (!inThrottle) {
|
||||
func.apply(this, args);
|
||||
inThrottle = true;
|
||||
setTimeout(() => inThrottle = false, limit);
|
||||
}
|
||||
};
|
||||
if (window.sdk?.utils?.dom?.throttle) {
|
||||
return window.sdk.utils.dom.throttle(func, limit);
|
||||
}
|
||||
return func;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -137,11 +95,7 @@ function arraysEqual(a, b) {
|
||||
* Format bytes to human readable
|
||||
*/
|
||||
function formatBytes(bytes) {
|
||||
if (bytes === 0) return '0 Bytes';
|
||||
const k = 1024;
|
||||
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
return Math.round(bytes / Math.pow(k, i) * 100) / 100 + ' ' + sizes[i];
|
||||
return window.sdk?.utils?.format?.formatBytes(bytes) || '0 Bytes';
|
||||
}
|
||||
|
||||
// Export for use in other modules
|
||||
@@ -160,6 +114,3 @@ if (typeof module !== 'undefined' && module.exports) {
|
||||
formatBytes
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user