Files
openfang/crates/openfang-api/static/js/pages/approvals.js
jaberjaber23 5692c96494 Initial commit — OpenFang Agent Operating System
Open-source Agent OS built in Rust.

- 14 crates, 1,767+ tests, zero clippy warnings
- 7 autonomous Hands (Clip, Lead, Collector, Predictor, Researcher, Twitter, Browser)
- 16 security systems (WASM sandbox, Merkle audit trail, taint tracking, Ed25519 signing, SSRF protection, secret zeroization, HMAC-SHA256 mutual auth, and more)
- 30 pre-built agents across 4 performance tiers
- 40 channel adapters (Telegram, Discord, Slack, WhatsApp, Teams, and 35 more)
- 38 built-in tools + MCP client/server + A2A protocol
- 26 LLM providers with intelligent routing and cost tracking
- 60+ bundled skills with FangHub marketplace
- Tauri 2.0 native desktop app
- 140+ REST/WS/SSE API endpoints with Alpine.js dashboard
- OpenAI-compatible /v1/chat/completions endpoint
- One-command install, production-ready
2026-02-26 01:00:27 +03:00

67 lines
1.9 KiB
JavaScript

// OpenFang Approvals Page — Execution approval queue for sensitive agent actions
'use strict';
function approvalsPage() {
return {
approvals: [],
filterStatus: 'all',
loading: true,
loadError: '',
get filtered() {
var f = this.filterStatus;
if (f === 'all') return this.approvals;
return this.approvals.filter(function(a) { return a.status === f; });
},
get pendingCount() {
return this.approvals.filter(function(a) { return a.status === 'pending'; }).length;
},
async loadData() {
this.loading = true;
this.loadError = '';
try {
var data = await OpenFangAPI.get('/api/approvals');
this.approvals = data.approvals || [];
} catch(e) {
this.loadError = e.message || 'Could not load approvals.';
}
this.loading = false;
},
async approve(id) {
try {
await OpenFangAPI.post('/api/approvals/' + id + '/approve', {});
OpenFangToast.success('Approved');
await this.loadData();
} catch(e) {
OpenFangToast.error(e.message);
}
},
async reject(id) {
var self = this;
OpenFangToast.confirm('Reject Action', 'Are you sure you want to reject this action?', async function() {
try {
await OpenFangAPI.post('/api/approvals/' + id + '/reject', {});
OpenFangToast.success('Rejected');
await self.loadData();
} catch(e) {
OpenFangToast.error(e.message);
}
});
},
timeAgo(dateStr) {
if (!dateStr) return '';
var d = new Date(dateStr);
var secs = Math.floor((Date.now() - d.getTime()) / 1000);
if (secs < 60) return secs + 's ago';
if (secs < 3600) return Math.floor(secs / 60) + 'm ago';
if (secs < 86400) return Math.floor(secs / 3600) + 'h ago';
return Math.floor(secs / 86400) + 'd ago';
}
};
}