feat: show commit hash in footer and implement auto server health check for AppWPP
This commit is contained in:
+7
-1
@@ -8,7 +8,8 @@ import {
|
||||
Lock,
|
||||
Loader2,
|
||||
MessageSquare,
|
||||
Bookmark
|
||||
Bookmark,
|
||||
GitCommit
|
||||
} from 'lucide-react';
|
||||
import Header from './components/Header';
|
||||
import SecurityBadge from './components/SecurityBadge';
|
||||
@@ -251,6 +252,11 @@ export default function App() {
|
||||
<span className="footer-shield">
|
||||
<ShieldCheck size={14} /> 100% no cliente (Executa em qualquer navegador)
|
||||
</span>
|
||||
<span>•</span>
|
||||
<span className="footer-commit" title="Versão do commit da aplicação">
|
||||
<GitCommit size={14} className="text-cyan" />
|
||||
<span>Commit: <code className="commit-hash-pill">{typeof __COMMIT_HASH__ !== 'undefined' ? __COMMIT_HASH__ : 'dev'}</code></span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
@@ -14,7 +14,8 @@ import {
|
||||
AlertCircle,
|
||||
CheckCircle2,
|
||||
Info,
|
||||
Edit2
|
||||
Edit2,
|
||||
RefreshCw
|
||||
} from 'lucide-react';
|
||||
import { getStoredServers, saveServers } from '../../utils/appWppStorage';
|
||||
import {
|
||||
@@ -24,7 +25,9 @@ import {
|
||||
checkSessionStatus,
|
||||
clearSessionData,
|
||||
generateToken,
|
||||
ensureQRPrefix
|
||||
ensureQRPrefix,
|
||||
testServerConnection,
|
||||
listAllServerSessions
|
||||
} from '../../utils/wppConnectApi';
|
||||
import WppSessionCard from './WppSessionCard';
|
||||
import ModalServer from './ModalServer';
|
||||
@@ -91,6 +94,63 @@ export default function AppWPP() {
|
||||
};
|
||||
|
||||
const activeServer = servers.find((s) => s.id === activeServerId) || null;
|
||||
const [isCheckingServer, setIsCheckingServer] = useState(false);
|
||||
|
||||
const checkServerOnlineStatus = async (serverToCheck) => {
|
||||
const srv = serverToCheck || servers.find((s) => s.id === activeServerId) || activeServer;
|
||||
if (!srv || !srv.baseUrl || !srv.secretKey) return;
|
||||
|
||||
setIsCheckingServer(true);
|
||||
try {
|
||||
const res = await testServerConnection(srv.baseUrl, srv.secretKey);
|
||||
const isOnline = res.ok === true;
|
||||
updateServersState((prevServers) =>
|
||||
prevServers.map((s) => (s.id === srv.id ? { ...s, online: isOnline } : s))
|
||||
);
|
||||
|
||||
// Se estiver online, sincroniza o status das sessões já ativas no servidor
|
||||
if (isOnline) {
|
||||
try {
|
||||
const sessionsOnServer = await listAllServerSessions(srv);
|
||||
if (Array.isArray(sessionsOnServer)) {
|
||||
updateServersState((prevServers) =>
|
||||
prevServers.map((s) => {
|
||||
if (s.id !== srv.id) return s;
|
||||
const updatedSessions = (s.sessions || []).map((sess) => {
|
||||
const match = sessionsOnServer.find((x) =>
|
||||
x === sess.name || x?.name === sess.name || x?.session === sess.name
|
||||
);
|
||||
if (match) {
|
||||
const statusStr = typeof match === 'string' ? 'connected' : (match.status || 'connected');
|
||||
const isConn = statusStr === 'CONNECTED' || statusStr === 'connected' || statusStr === true;
|
||||
return { ...sess, status: isConn ? 'connected' : sess.status };
|
||||
}
|
||||
return sess;
|
||||
});
|
||||
return { ...s, sessions: updatedSessions };
|
||||
})
|
||||
);
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
} catch (e) {
|
||||
updateServersState((prevServers) =>
|
||||
prevServers.map((s) => (s.id === srv.id ? { ...s, online: false } : s))
|
||||
);
|
||||
} finally {
|
||||
setIsCheckingServer(false);
|
||||
}
|
||||
};
|
||||
|
||||
// Checa automaticamente o status do servidor ativo na inicialização e ao alternar
|
||||
useEffect(() => {
|
||||
if (activeServerId && servers.length > 0) {
|
||||
const srv = servers.find((s) => s.id === activeServerId);
|
||||
if (srv) {
|
||||
checkServerOnlineStatus(srv);
|
||||
}
|
||||
}
|
||||
}, [activeServerId, servers.length]);
|
||||
|
||||
// Servidor CRUD
|
||||
const handleSaveServer = (serverData) => {
|
||||
@@ -415,9 +475,20 @@ export default function AppWPP() {
|
||||
<div className="wpp-server-title-box">
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: '0.75rem' }}>
|
||||
<h2 className="wpp-view-server-name">{activeServer.name}</h2>
|
||||
<span className={`wpp-badge-status ${activeServer.online ? 'badge-online' : 'badge-offline'}`}>
|
||||
{activeServer.online ? 'Online' : 'Offline'}
|
||||
<div className="wpp-status-wrapper">
|
||||
<span className={`wpp-badge-status ${isCheckingServer ? 'badge-checking' : (activeServer.online ? 'badge-online' : 'badge-offline')}`}>
|
||||
{isCheckingServer ? 'Verificando...' : (activeServer.online ? 'Online' : 'Offline')}
|
||||
</span>
|
||||
<button
|
||||
type="button"
|
||||
className="btn-refresh-status"
|
||||
title="Verificar status do servidor agora"
|
||||
onClick={() => checkServerOnlineStatus(activeServer)}
|
||||
disabled={isCheckingServer}
|
||||
>
|
||||
<RefreshCw size={12} className={isCheckingServer ? 'animate-spin' : ''} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<span className="wpp-view-server-url">{activeServer.baseUrl}</span>
|
||||
</div>
|
||||
|
||||
@@ -1262,6 +1262,24 @@ body {
|
||||
color: #34d399;
|
||||
}
|
||||
|
||||
.footer-commit {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.35rem;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.commit-hash-pill {
|
||||
font-family: var(--font-mono);
|
||||
background: rgba(14, 165, 233, 0.12);
|
||||
border: 1px solid rgba(14, 165, 233, 0.25);
|
||||
color: #38bdf8;
|
||||
padding: 0.1rem 0.45rem;
|
||||
border-radius: 4px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* Utilities */
|
||||
.text-cyan { color: var(--accent-cyan); }
|
||||
.text-emerald { color: var(--accent-emerald); }
|
||||
@@ -1640,6 +1658,42 @@ body {
|
||||
border: 1px solid rgba(100, 116, 139, 0.3);
|
||||
}
|
||||
|
||||
.badge-checking {
|
||||
background: rgba(234, 179, 8, 0.15);
|
||||
color: #facc15;
|
||||
border: 1px solid rgba(234, 179, 8, 0.3);
|
||||
}
|
||||
|
||||
.wpp-status-wrapper {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.4rem;
|
||||
}
|
||||
|
||||
.btn-refresh-status {
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
border: 1px solid var(--border-color);
|
||||
color: var(--text-muted);
|
||||
border-radius: 6px;
|
||||
padding: 0.2rem 0.35rem;
|
||||
cursor: pointer;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.btn-refresh-status:hover:not(:disabled) {
|
||||
color: #38bdf8;
|
||||
border-color: rgba(56, 189, 248, 0.4);
|
||||
background: rgba(56, 189, 248, 0.1);
|
||||
}
|
||||
|
||||
.btn-refresh-status:disabled {
|
||||
opacity: 0.6;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.wpp-server-actions-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
+17
-1
@@ -1,9 +1,25 @@
|
||||
import react from '@vitejs/plugin-react'
|
||||
import { defineConfig } from 'vite'
|
||||
import react from '@vitejs/plugin-react'
|
||||
import { execSync } from 'child_process'
|
||||
|
||||
let commitHash = process.env.COMMIT_REF
|
||||
? process.env.COMMIT_REF.slice(0, 7)
|
||||
: '';
|
||||
|
||||
if (!commitHash) {
|
||||
try {
|
||||
commitHash = execSync('git rev-parse --short HEAD').toString().trim();
|
||||
} catch (e) {
|
||||
commitHash = 'dev';
|
||||
}
|
||||
}
|
||||
|
||||
// https://vite.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
define: {
|
||||
__COMMIT_HASH__: JSON.stringify(commitHash)
|
||||
},
|
||||
server: {
|
||||
proxy: {
|
||||
'/api-wpp': {
|
||||
|
||||
Reference in New Issue
Block a user