feat(platform): add new services, tools, tests and crews modules
New router intelligence modules (26 files): alert_ingest/store, audit_store, architecture_pressure, backlog_generator/store, cost_analyzer, data_governance, dependency_scanner, drift_analyzer, incident_* (5 files), llm_enrichment, platform_priority_digest, provider_budget, release_check_runner, risk_* (6 files), signature_state_store, sofiia_auto_router, tool_governance New services: - sofiia-console: Dockerfile, adapters/, monitor/nodes/ops/voice modules, launchd, react static - memory-service: integration_endpoints, integrations, voice_endpoints, static UI - aurora-service: full app suite (analysis, job_store, orchestrator, reporting, schemas, subagents) - sofiia-supervisor: new supervisor service - aistalk-bridge-lite: Telegram bridge lite - calendar-service: CalDAV calendar service with reminders - mlx-stt-service / mlx-tts-service: Apple Silicon speech services - binance-bot-monitor: market monitor service - node-worker: STT/TTS memory providers New tools (9): agent_email, browser_tool, contract_tool, observability_tool, oncall_tool, pr_reviewer_tool, repo_tool, safe_code_executor, secure_vault New crews: agromatrix_crew (10 modules: depth_classifier, doc_facts, doc_focus, farm_state, light_reply, llm_factory, memory_manager, proactivity, reflection_engine, session_context, style_adapter, telemetry) Tests: 85+ test files for all new modules Made-with: Cursor
This commit is contained in:
225
services/sofiia-console/static/react/ExportSettings.tsx
Normal file
225
services/sofiia-console/static/react/ExportSettings.tsx
Normal file
@@ -0,0 +1,225 @@
|
||||
import React, { useMemo } from "react";
|
||||
|
||||
export type AuroraResolution = "original" | "1080p" | "4k" | "8k" | "custom";
|
||||
export type AuroraFormat = "mp4_h264" | "mp4_h265" | "avi_lossless" | "frames_png";
|
||||
export type AuroraRoi = "full_frame" | "auto_faces" | "auto_plates" | "manual";
|
||||
|
||||
export interface AuroraCropBox {
|
||||
x: number;
|
||||
y: number;
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
||||
export interface ExportSettingsValue {
|
||||
resolution: AuroraResolution;
|
||||
format: AuroraFormat;
|
||||
roi: AuroraRoi;
|
||||
customWidth?: number;
|
||||
customHeight?: number;
|
||||
crop?: AuroraCropBox | null;
|
||||
}
|
||||
|
||||
interface ExportSettingsProps {
|
||||
value: ExportSettingsValue;
|
||||
onChange: (next: ExportSettingsValue) => void;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
function toInt(v: string, fallback = 0): number {
|
||||
const n = Number.parseInt(v, 10);
|
||||
return Number.isFinite(n) ? Math.max(0, n) : fallback;
|
||||
}
|
||||
|
||||
export const ExportSettings: React.FC<ExportSettingsProps> = ({
|
||||
value,
|
||||
onChange,
|
||||
disabled = false,
|
||||
}) => {
|
||||
const crop = value.crop ?? { x: 0, y: 0, width: 0, height: 0 };
|
||||
const showCustomResolution = value.resolution === "custom";
|
||||
const showManualCrop = value.roi === "manual";
|
||||
const summary = useMemo(() => {
|
||||
const res =
|
||||
value.resolution === "custom"
|
||||
? `${value.customWidth || 0}x${value.customHeight || 0}`
|
||||
: value.resolution;
|
||||
return `${res} • ${value.format} • ${value.roi}`;
|
||||
}, [value]);
|
||||
|
||||
return (
|
||||
<section
|
||||
style={{
|
||||
border: "1px solid #2f2f35",
|
||||
borderRadius: 10,
|
||||
padding: 12,
|
||||
background: "#111217",
|
||||
color: "#e5e7eb",
|
||||
}}
|
||||
aria-label="Aurora export settings"
|
||||
>
|
||||
<div style={{ fontSize: 13, fontWeight: 700, marginBottom: 10 }}>Export Settings</div>
|
||||
|
||||
<label style={{ display: "block", marginBottom: 8 }}>
|
||||
<span style={{ fontSize: 12, color: "#9ca3af", display: "block", marginBottom: 4 }}>
|
||||
Resolution
|
||||
</span>
|
||||
<select
|
||||
disabled={disabled}
|
||||
value={value.resolution}
|
||||
onChange={(e) => onChange({ ...value, resolution: e.target.value as AuroraResolution })}
|
||||
style={{ width: "100%" }}
|
||||
>
|
||||
<option value="original">Original</option>
|
||||
<option value="1080p">1080p</option>
|
||||
<option value="4k">4K</option>
|
||||
<option value="8k">8K</option>
|
||||
<option value="custom">Custom</option>
|
||||
</select>
|
||||
</label>
|
||||
|
||||
{showCustomResolution && (
|
||||
<div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8, marginBottom: 8 }}>
|
||||
<label>
|
||||
<span style={{ fontSize: 12, color: "#9ca3af", display: "block", marginBottom: 4 }}>
|
||||
Width
|
||||
</span>
|
||||
<input
|
||||
type="number"
|
||||
min={1}
|
||||
disabled={disabled}
|
||||
value={value.customWidth || 0}
|
||||
onChange={(e) => onChange({ ...value, customWidth: toInt(e.target.value, 0) })}
|
||||
/>
|
||||
</label>
|
||||
<label>
|
||||
<span style={{ fontSize: 12, color: "#9ca3af", display: "block", marginBottom: 4 }}>
|
||||
Height
|
||||
</span>
|
||||
<input
|
||||
type="number"
|
||||
min={1}
|
||||
disabled={disabled}
|
||||
value={value.customHeight || 0}
|
||||
onChange={(e) => onChange({ ...value, customHeight: toInt(e.target.value, 0) })}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<label style={{ display: "block", marginBottom: 8 }}>
|
||||
<span style={{ fontSize: 12, color: "#9ca3af", display: "block", marginBottom: 4 }}>
|
||||
Format
|
||||
</span>
|
||||
<select
|
||||
disabled={disabled}
|
||||
value={value.format}
|
||||
onChange={(e) => onChange({ ...value, format: e.target.value as AuroraFormat })}
|
||||
style={{ width: "100%" }}
|
||||
>
|
||||
<option value="mp4_h264">MP4 (H.264)</option>
|
||||
<option value="mp4_h265">MP4 (H.265)</option>
|
||||
<option value="avi_lossless">AVI (lossless)</option>
|
||||
<option value="frames_png">Frames (PNG)</option>
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<label style={{ display: "block", marginBottom: 8 }}>
|
||||
<span style={{ fontSize: 12, color: "#9ca3af", display: "block", marginBottom: 4 }}>
|
||||
ROI
|
||||
</span>
|
||||
<select
|
||||
disabled={disabled}
|
||||
value={value.roi}
|
||||
onChange={(e) => onChange({ ...value, roi: e.target.value as AuroraRoi })}
|
||||
style={{ width: "100%" }}
|
||||
>
|
||||
<option value="full_frame">Full frame</option>
|
||||
<option value="auto_faces">Auto faces</option>
|
||||
<option value="auto_plates">Auto license plates</option>
|
||||
<option value="manual">Manual crop box</option>
|
||||
</select>
|
||||
</label>
|
||||
|
||||
{showManualCrop && (
|
||||
<div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8, marginBottom: 8 }}>
|
||||
<label>
|
||||
<span style={{ fontSize: 12, color: "#9ca3af", display: "block", marginBottom: 4 }}>
|
||||
X
|
||||
</span>
|
||||
<input
|
||||
type="number"
|
||||
min={0}
|
||||
disabled={disabled}
|
||||
value={crop.x}
|
||||
onChange={(e) =>
|
||||
onChange({
|
||||
...value,
|
||||
crop: { ...crop, x: toInt(e.target.value, 0) },
|
||||
})
|
||||
}
|
||||
/>
|
||||
</label>
|
||||
<label>
|
||||
<span style={{ fontSize: 12, color: "#9ca3af", display: "block", marginBottom: 4 }}>
|
||||
Y
|
||||
</span>
|
||||
<input
|
||||
type="number"
|
||||
min={0}
|
||||
disabled={disabled}
|
||||
value={crop.y}
|
||||
onChange={(e) =>
|
||||
onChange({
|
||||
...value,
|
||||
crop: { ...crop, y: toInt(e.target.value, 0) },
|
||||
})
|
||||
}
|
||||
/>
|
||||
</label>
|
||||
<label>
|
||||
<span style={{ fontSize: 12, color: "#9ca3af", display: "block", marginBottom: 4 }}>
|
||||
Width
|
||||
</span>
|
||||
<input
|
||||
type="number"
|
||||
min={0}
|
||||
disabled={disabled}
|
||||
value={crop.width}
|
||||
onChange={(e) =>
|
||||
onChange({
|
||||
...value,
|
||||
crop: { ...crop, width: toInt(e.target.value, 0) },
|
||||
})
|
||||
}
|
||||
/>
|
||||
</label>
|
||||
<label>
|
||||
<span style={{ fontSize: 12, color: "#9ca3af", display: "block", marginBottom: 4 }}>
|
||||
Height
|
||||
</span>
|
||||
<input
|
||||
type="number"
|
||||
min={0}
|
||||
disabled={disabled}
|
||||
value={crop.height}
|
||||
onChange={(e) =>
|
||||
onChange({
|
||||
...value,
|
||||
crop: { ...crop, height: toInt(e.target.value, 0) },
|
||||
})
|
||||
}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div style={{ marginTop: 6, fontSize: 12, color: "#9ca3af" }}>
|
||||
Selected: <span style={{ color: "#e5e7eb" }}>{summary}</span>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default ExportSettings;
|
||||
|
||||
Reference in New Issue
Block a user