ozellik: google oauth, gmail-drive araclari ve admin durum kartlarini ekle

This commit is contained in:
2026-03-22 18:50:06 +03:00
parent 177fd8e1a7
commit ad847b1cf4
20 changed files with 970 additions and 14 deletions

View File

@@ -2,8 +2,10 @@ import { FormEvent, useEffect, useState } from "react";
import { api } from "./api";
import type {
AnythingLLMStatus,
AutomationRecord,
DashboardSnapshot,
GoogleIntegrationStatus,
MemoryRecord,
OllamaStatus,
RuntimeSettings,
@@ -20,11 +22,13 @@ const defaultSettings: RuntimeSettings = {
local_model: "qwen3-vl-8b-instruct-mlx@5bit",
zai_model: "glm-5",
anythingllm_base_url: "http://127.0.0.1:3001",
anythingllm_workspace_slug: "wiseclaw",
anythingllm_workspace_slug: "benim-calisma-alanim",
tools: [
{ name: "brave_search", enabled: true },
{ name: "second_brain", enabled: true },
{ name: "browser_use", enabled: true },
{ name: "gmail", enabled: true },
{ name: "google_drive", enabled: true },
{ name: "searxng_search", enabled: false },
{ name: "web_fetch", enabled: true },
{ name: "apple_notes", enabled: true },
@@ -46,8 +50,14 @@ export function App() {
const [zaiSecretValue, setZaiSecretValue] = useState("");
const [anythingSecretMask, setAnythingSecretMask] = useState("");
const [anythingSecretValue, setAnythingSecretValue] = useState("");
const [googleClientIdMask, setGoogleClientIdMask] = useState("");
const [googleClientIdValue, setGoogleClientIdValue] = useState("");
const [googleClientSecretMask, setGoogleClientSecretMask] = useState("");
const [googleClientSecretValue, setGoogleClientSecretValue] = useState("");
const [ollamaStatus, setOllamaStatus] = useState<OllamaStatus | null>(null);
const [telegramStatus, setTelegramStatus] = useState<TelegramStatus | null>(null);
const [googleStatus, setGoogleStatus] = useState<GoogleIntegrationStatus | null>(null);
const [anythingStatus, setAnythingStatus] = useState<AnythingLLMStatus | null>(null);
const [status, setStatus] = useState("Loading WiseClaw admin...");
const providerLabel = settings.model_provider === "local" ? "Local (LM Studio)" : "Z.AI";
const searchProviderLabel = settings.search_provider === "brave" ? "Brave" : "SearXNG";
@@ -63,7 +73,23 @@ export function App() {
async function load() {
try {
const [dashboardData, settingsData, userData, profileData, automationData, memoryData, secretData, zaiSecretData, anythingSecretData, ollamaData, telegramData] =
const [
dashboardData,
settingsData,
userData,
profileData,
automationData,
memoryData,
secretData,
zaiSecretData,
anythingSecretData,
googleClientIdData,
googleClientSecretData,
ollamaData,
telegramData,
anythingllmData,
googleData,
] =
await Promise.all([
api.getDashboard(),
api.getSettings(),
@@ -74,8 +100,12 @@ export function App() {
api.getSecretMask("brave_api_key"),
api.getSecretMask("zai_api_key"),
api.getSecretMask("anythingllm_api_key"),
api.getSecretMask("google_client_id"),
api.getSecretMask("google_client_secret"),
api.getOllamaStatus(),
api.getTelegramStatus(),
api.getAnythingLLMStatus(),
api.getGoogleStatus(),
]);
setDashboard(dashboardData);
setSettings(settingsData);
@@ -86,8 +116,12 @@ export function App() {
setSecretMask(secretData.masked);
setZaiSecretMask(zaiSecretData.masked);
setAnythingSecretMask(anythingSecretData.masked);
setGoogleClientIdMask(googleClientIdData.masked);
setGoogleClientSecretMask(googleClientSecretData.masked);
setOllamaStatus(ollamaData);
setTelegramStatus(telegramData);
setAnythingStatus(anythingllmData);
setGoogleStatus(googleData);
setStatus("WiseClaw admin ready.");
} catch (error) {
setStatus(error instanceof Error ? error.message : "Failed to load admin data.");
@@ -135,6 +169,18 @@ export function App() {
await load();
}
async function handleGoogleClientSubmit(event: FormEvent) {
event.preventDefault();
if (!googleClientIdValue.trim() || !googleClientSecretValue.trim()) {
return;
}
await api.saveGoogleClient(googleClientIdValue.trim(), googleClientSecretValue.trim());
setGoogleClientIdValue("");
setGoogleClientSecretValue("");
setStatus("Google OAuth client saved.");
await load();
}
async function handleAddUser(event: FormEvent<HTMLFormElement>) {
event.preventDefault();
const form = new FormData(event.currentTarget);
@@ -197,8 +243,8 @@ export function App() {
</div>
<div className="hero-grid">
<div>
<span>Terminal mode</span>
<strong>{settings.terminal_mode}</strong>
<span>AnythingLLM</span>
<strong>{anythingStatus?.reachable && anythingStatus?.workspace_found ? "Active" : "Off"}</strong>
</div>
<div>
<span>Search provider</span>
@@ -220,6 +266,21 @@ export function App() {
<strong>{telegramStatus?.configured ? "Configured" : "Missing token"}</strong>
<p>{telegramStatus?.message || "Checking..."}</p>
</div>
<div className="integration-card">
<span>Google auth:</span>
<strong>{googleStatus?.connected ? "Connected" : "Not connected"}</strong>
<p>{googleStatus?.message || "Checking Google OAuth status..."}</p>
{googleStatus?.connect_url ? (
<a
className="button-link"
href={googleStatus.connect_url}
target="_blank"
rel="noreferrer"
>
{googleStatus.connected ? "Reconnect Google" : "Connect Google"}
</a>
) : null}
</div>
</div>
</section>
@@ -293,7 +354,7 @@ export function App() {
<input
value={settings.anythingllm_workspace_slug}
onChange={(event) => setSettings({ ...settings, anythingllm_workspace_slug: event.target.value })}
placeholder="wiseclaw"
placeholder="benim-calisma-alanim"
/>
</label>
@@ -406,6 +467,32 @@ export function App() {
</label>
</form>
<form className="panel secret-panel" onSubmit={handleGoogleClientSubmit}>
<div className="panel-head">
<h3>Google OAuth</h3>
<button type="submit">Update</button>
</div>
<p className="muted">Current client ID: {googleClientIdMask || "not configured"}</p>
<p className="muted">Current client secret: {googleClientSecretMask || "not configured"}</p>
<label>
Google client ID
<input
value={googleClientIdValue}
onChange={(event) => setGoogleClientIdValue(event.target.value)}
placeholder="Paste Google OAuth client ID"
/>
</label>
<label>
Google client secret
<input
type="password"
value={googleClientSecretValue}
onChange={(event) => setGoogleClientSecretValue(event.target.value)}
placeholder="Paste Google OAuth client secret"
/>
</label>
</form>
<form className="panel" onSubmit={handleAddUser}>
<div className="panel-head">
<h3>Telegram Whitelist</h3>

View File

@@ -1,6 +1,8 @@
import type {
AnythingLLMStatus,
AutomationRecord,
DashboardSnapshot,
GoogleIntegrationStatus,
MemoryRecord,
OllamaStatus,
RuntimeSettings,
@@ -53,6 +55,13 @@ export const api = {
method: "POST",
body: JSON.stringify({ key, value }),
}),
saveGoogleClient: (client_id: string, client_secret: string) =>
request<{ status: string }>("/admin/integrations/google/client", {
method: "POST",
body: JSON.stringify({ client_id, client_secret }),
}),
getOllamaStatus: () => request<OllamaStatus>("/admin/integrations/llm"),
getTelegramStatus: () => request<TelegramStatus>("/admin/integrations/telegram"),
getAnythingLLMStatus: () => request<AnythingLLMStatus>("/admin/integrations/anythingllm"),
getGoogleStatus: () => request<GoogleIntegrationStatus>("/admin/integrations/google"),
};

View File

@@ -167,7 +167,7 @@ label {
.integration-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
gap: 0.9rem;
}
@@ -192,6 +192,19 @@ label {
color: #4f5b57;
}
.button-link {
display: inline-flex;
align-items: center;
justify-content: center;
margin-top: 0.6rem;
padding: 0.65rem 0.9rem;
border-radius: 999px;
background: #1f5c66;
color: #f5f1e8;
text-decoration: none;
font-weight: 600;
}
.grid.two-up {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));

View File

@@ -85,3 +85,18 @@ export type TelegramStatus = {
polling_active: boolean;
message: string;
};
export type GoogleIntegrationStatus = {
client_configured: boolean;
connected: boolean;
connect_url: string;
message: string;
};
export type AnythingLLMStatus = {
reachable: boolean;
workspace_found: boolean;
base_url: string;
workspace_slug: string;
message: string;
};