@jheavenknows/bluerouter 5.0.20 → 5.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/.next-cli-build/BUILD_ID +1 -1
- package/app/.next-cli-build/app-path-routes-manifest.json +6 -6
- package/app/.next-cli-build/build-manifest.json +2 -2
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/analytics/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/api-keys/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/basic-chat/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/cli-tools/[toolId]/page.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/cli-tools/[toolId]/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/cli-tools/page.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/cli-tools/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/combos/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/console-log/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/endpoint/page.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/endpoint/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/[kind]/[id]/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/[kind]/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/combo/[id]/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/web/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/mitm/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/page.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/personalcloudprovider/page.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/personalcloudprovider/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/profile/page.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/profile/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/prompt-logs/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/provider-health/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/[id]/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/new/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/proxy-pools/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/quota/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/skills/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/translator/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/(dashboard)/dashboard/usage/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/_global-error.html +1 -1
- package/app/.next-cli-build/server/app/_global-error.rsc +1 -1
- package/app/.next-cli-build/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/_not-found.html +1 -1
- package/app/.next-cli-build/server/app/_not-found.rsc +5 -5
- package/app/.next-cli-build/server/app/_not-found.segments/_full.segment.rsc +5 -5
- package/app/.next-cli-build/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/_not-found.segments/_index.segment.rsc +5 -5
- package/app/.next-cli-build/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/api/auth/ldap/test/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/auth/ldap/users/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/auth/login/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/auth/logout/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/auth/oidc/callback/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/auth/oidc/start/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/auth/oidc/test/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/auth/status/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/branding/[asset]/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/branding/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/branding/upload/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/cli-tools/all-statuses/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/cli-tools/antigravity-mitm/alias/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/cli-tools/antigravity-mitm/autostart/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/cli-tools/antigravity-mitm/prompt-log-db/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/cli-tools/antigravity-mitm/root-ca/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/cli-tools/antigravity-mitm/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/cli-tools/copilot-settings/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/cli-tools/cowork-settings/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/combos/[id]/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/combos/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/dashboard/analytics/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/dashboard/combos/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/dashboard/endpoint/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/dashboard/prompt-logs/[id]/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/dashboard/prompt-logs/options/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/dashboard/prompt-logs/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/keys/[id]/rotate/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/keys/[id]/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/keys/route.js +1 -1
- package/app/.next-cli-build/server/app/api/keys/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/mcp/[plugin]/message/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/mcp/[plugin]/sse/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/media-providers/tts/deepgram/voices/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/media-providers/tts/elevenlabs/voices/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/media-providers/tts/inworld/voices/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/media-providers/tts/minimax/voices/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/models/alias/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/models/availability/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/models/custom/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/models/disabled/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/models/route.js +1 -1
- package/app/.next-cli-build/server/app/api/models/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/models/test/route.js +1 -1
- package/app/.next-cli-build/server/app/api/models/test/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/oauth/[provider]/[action]/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/oauth/codex/import-token/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/oauth/cursor/auto-import/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/oauth/cursor/import/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/oauth/gitlab/pat/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/oauth/iflow/cookie/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/oauth/kiro/import/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/oauth/kiro/social-exchange/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/personal-cloud-providers/[id]/api-key-models/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/personal-cloud-providers/[id]/import-models/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/personal-cloud-providers/[id]/models/[...routeModel]/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/personal-cloud-providers/[id]/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/personal-cloud-providers/permissions/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/personal-cloud-providers/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/personal-cloud-providers/routing/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/pricing/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/provider-health/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/provider-nodes/[id]/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/provider-nodes/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/providers/[id]/models/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/providers/[id]/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/providers/[id]/test/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/providers/[id]/test-models/route.js +1 -1
- package/app/.next-cli-build/server/app/api/providers/[id]/test-models/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/providers/client/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/providers/route.js +1 -1
- package/app/.next-cli-build/server/app/api/providers/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/providers/test-batch/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/providers/validate/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/proxy-pools/[id]/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/proxy-pools/[id]/test/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/proxy-pools/cloudflare-deploy/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/proxy-pools/deno-deploy/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/proxy-pools/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/proxy-pools/vercel-deploy/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/settings/database/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/settings/require-login/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/settings/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/translator/console-logs/route.js +1 -1
- package/app/.next-cli-build/server/app/api/translator/console-logs/stream/route.js +1 -1
- package/app/.next-cli-build/server/app/api/translator/send/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/translator/translate/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/tunnel/disable/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/tunnel/enable/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/tunnel/status/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/tunnel/tailscale-check/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/tunnel/tailscale-disable/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/tunnel/tailscale-enable/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/tunnel/tailscale-install/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/tunnel/tailscale-login/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/tunnel/tailscale-start-daemon/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/usage/[connectionId]/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/usage/chart/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/usage/history/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/usage/providers/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/usage/request-details/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/usage/request-logs/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/usage/stats/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/usage/stream/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/v1/api/chat/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/v1/audio/speech/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/v1/audio/transcriptions/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/v1/chat/completions/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/v1/embeddings/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/v1/images/generations/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/v1/messages/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/v1/models/[kind]/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/v1/models/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/v1/responses/compact/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/v1/responses/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/v1/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/v1/search/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/v1/web/fetch/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/v1beta/models/[...path]/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/v1beta/models/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/version/route.js +1 -1
- package/app/.next-cli-build/server/app/api/version/shutdown/route.js +1 -1
- package/app/.next-cli-build/server/app/api/version/shutdown/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/api/version/update/route.js +1 -1
- package/app/.next-cli-build/server/app/api/version/update/route.js.nft.json +1 -1
- package/app/.next-cli-build/server/app/callback/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/callback.html +1 -1
- package/app/.next-cli-build/server/app/callback.rsc +5 -5
- package/app/.next-cli-build/server/app/callback.segments/_full.segment.rsc +5 -5
- package/app/.next-cli-build/server/app/callback.segments/_head.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/callback.segments/_index.segment.rsc +5 -5
- package/app/.next-cli-build/server/app/callback.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/callback.segments/callback/__PAGE__.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/callback.segments/callback.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/analytics.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/analytics.rsc +6 -6
- package/app/.next-cli-build/server/app/dashboard/analytics.segments/!KGRhc2hib2FyZCk/dashboard/analytics/__PAGE__.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/analytics.segments/!KGRhc2hib2FyZCk/dashboard/analytics.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/analytics.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/analytics.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next-cli-build/server/app/dashboard/analytics.segments/_full.segment.rsc +6 -6
- package/app/.next-cli-build/server/app/dashboard/analytics.segments/_head.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/analytics.segments/_index.segment.rsc +5 -5
- package/app/.next-cli-build/server/app/dashboard/analytics.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/api-keys.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/api-keys.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/api-keys.segments/!KGRhc2hib2FyZCk/dashboard/api-keys/__PAGE__.segment.rsc +2 -2
- package/app/.next-cli-build/server/app/dashboard/api-keys.segments/!KGRhc2hib2FyZCk/dashboard/api-keys.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/api-keys.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/api-keys.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next-cli-build/server/app/dashboard/api-keys.segments/_full.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/api-keys.segments/_head.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/api-keys.segments/_index.segment.rsc +5 -5
- package/app/.next-cli-build/server/app/dashboard/api-keys.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/basic-chat.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/basic-chat.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk/dashboard/basic-chat/__PAGE__.segment.rsc +2 -2
- package/app/.next-cli-build/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk/dashboard/basic-chat.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next-cli-build/server/app/dashboard/basic-chat.segments/_full.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/basic-chat.segments/_head.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/basic-chat.segments/_index.segment.rsc +5 -5
- package/app/.next-cli-build/server/app/dashboard/basic-chat.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/cli-tools.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/cli-tools.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard/cli-tools/__PAGE__.segment.rsc +2 -2
- package/app/.next-cli-build/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard/cli-tools.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next-cli-build/server/app/dashboard/cli-tools.segments/_full.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/cli-tools.segments/_head.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/cli-tools.segments/_index.segment.rsc +5 -5
- package/app/.next-cli-build/server/app/dashboard/cli-tools.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/combos.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/combos.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard/combos/__PAGE__.segment.rsc +2 -2
- package/app/.next-cli-build/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard/combos.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next-cli-build/server/app/dashboard/combos.segments/_full.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/combos.segments/_head.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/combos.segments/_index.segment.rsc +5 -5
- package/app/.next-cli-build/server/app/dashboard/combos.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/endpoint.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/endpoint.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard/endpoint/__PAGE__.segment.rsc +2 -2
- package/app/.next-cli-build/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard/endpoint.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next-cli-build/server/app/dashboard/endpoint.segments/_full.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/endpoint.segments/_head.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/endpoint.segments/_index.segment.rsc +5 -5
- package/app/.next-cli-build/server/app/dashboard/endpoint.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/media-providers/web.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/media-providers/web.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/!KGRhc2hib2FyZCk/dashboard/media-providers/web/__PAGE__.segment.rsc +2 -2
- package/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/!KGRhc2hib2FyZCk/dashboard/media-providers/web.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/!KGRhc2hib2FyZCk/dashboard/media-providers.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/_full.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/_head.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/_index.segment.rsc +5 -5
- package/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/mitm.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/mitm.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard/mitm/__PAGE__.segment.rsc +2 -2
- package/app/.next-cli-build/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard/mitm.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next-cli-build/server/app/dashboard/mitm.segments/_full.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/mitm.segments/_head.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/mitm.segments/_index.segment.rsc +5 -5
- package/app/.next-cli-build/server/app/dashboard/mitm.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/profile.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/profile.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard/profile/__PAGE__.segment.rsc +2 -2
- package/app/.next-cli-build/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard/profile.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next-cli-build/server/app/dashboard/profile.segments/_full.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/profile.segments/_head.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/profile.segments/_index.segment.rsc +5 -5
- package/app/.next-cli-build/server/app/dashboard/profile.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/prompt-logs.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/prompt-logs.rsc +6 -6
- package/app/.next-cli-build/server/app/dashboard/prompt-logs.segments/!KGRhc2hib2FyZCk/dashboard/prompt-logs/__PAGE__.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/prompt-logs.segments/!KGRhc2hib2FyZCk/dashboard/prompt-logs.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/prompt-logs.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/prompt-logs.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next-cli-build/server/app/dashboard/prompt-logs.segments/_full.segment.rsc +6 -6
- package/app/.next-cli-build/server/app/dashboard/prompt-logs.segments/_head.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/prompt-logs.segments/_index.segment.rsc +5 -5
- package/app/.next-cli-build/server/app/dashboard/prompt-logs.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/provider-health.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/provider-health.rsc +6 -6
- package/app/.next-cli-build/server/app/dashboard/provider-health.segments/!KGRhc2hib2FyZCk/dashboard/provider-health/__PAGE__.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/provider-health.segments/!KGRhc2hib2FyZCk/dashboard/provider-health.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/provider-health.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/provider-health.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next-cli-build/server/app/dashboard/provider-health.segments/_full.segment.rsc +6 -6
- package/app/.next-cli-build/server/app/dashboard/provider-health.segments/_head.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/provider-health.segments/_index.segment.rsc +5 -5
- package/app/.next-cli-build/server/app/dashboard/provider-health.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/providers/new.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/providers/new.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers/new/__PAGE__.segment.rsc +2 -2
- package/app/.next-cli-build/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers/new.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next-cli-build/server/app/dashboard/providers/new.segments/_full.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/providers/new.segments/_head.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/providers/new.segments/_index.segment.rsc +5 -5
- package/app/.next-cli-build/server/app/dashboard/providers/new.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/providers.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/providers.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard/providers/__PAGE__.segment.rsc +2 -2
- package/app/.next-cli-build/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard/providers.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next-cli-build/server/app/dashboard/providers.segments/_full.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/providers.segments/_head.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/providers.segments/_index.segment.rsc +5 -5
- package/app/.next-cli-build/server/app/dashboard/providers.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/proxy-pools.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/proxy-pools.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard/proxy-pools/__PAGE__.segment.rsc +2 -2
- package/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard/proxy-pools.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/_full.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/_head.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/_index.segment.rsc +5 -5
- package/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/quota.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/quota.rsc +8 -8
- package/app/.next-cli-build/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard/quota/__PAGE__.segment.rsc +3 -3
- package/app/.next-cli-build/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard/quota.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next-cli-build/server/app/dashboard/quota.segments/_full.segment.rsc +8 -8
- package/app/.next-cli-build/server/app/dashboard/quota.segments/_head.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/quota.segments/_index.segment.rsc +5 -5
- package/app/.next-cli-build/server/app/dashboard/quota.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/settings/pricing/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/dashboard/settings/pricing.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/settings/pricing.rsc +5 -5
- package/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/_full.segment.rsc +5 -5
- package/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/_head.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/_index.segment.rsc +5 -5
- package/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/dashboard/settings/pricing/__PAGE__.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/dashboard/settings/pricing.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/dashboard/settings.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/dashboard.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/skills.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/skills.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/skills.segments/!KGRhc2hib2FyZCk/dashboard/skills/__PAGE__.segment.rsc +2 -2
- package/app/.next-cli-build/server/app/dashboard/skills.segments/!KGRhc2hib2FyZCk/dashboard/skills.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/skills.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/skills.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next-cli-build/server/app/dashboard/skills.segments/_full.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/skills.segments/_head.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/skills.segments/_index.segment.rsc +5 -5
- package/app/.next-cli-build/server/app/dashboard/skills.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/translator.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/translator.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard/translator/__PAGE__.segment.rsc +2 -2
- package/app/.next-cli-build/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard/translator.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next-cli-build/server/app/dashboard/translator.segments/_full.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/translator.segments/_head.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/translator.segments/_index.segment.rsc +5 -5
- package/app/.next-cli-build/server/app/dashboard/translator.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/usage.html +1 -1
- package/app/.next-cli-build/server/app/dashboard/usage.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard/usage/__PAGE__.segment.rsc +2 -2
- package/app/.next-cli-build/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard/usage.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next-cli-build/server/app/dashboard/usage.segments/_full.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard/usage.segments/_head.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard/usage.segments/_index.segment.rsc +5 -5
- package/app/.next-cli-build/server/app/dashboard/usage.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard.html +1 -1
- package/app/.next-cli-build/server/app/dashboard.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard.segments/!KGRhc2hib2FyZCk/dashboard/__PAGE__.segment.rsc +2 -2
- package/app/.next-cli-build/server/app/dashboard.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next-cli-build/server/app/dashboard.segments/_full.segment.rsc +7 -7
- package/app/.next-cli-build/server/app/dashboard.segments/_head.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/dashboard.segments/_index.segment.rsc +5 -5
- package/app/.next-cli-build/server/app/dashboard.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/index.html +1 -1
- package/app/.next-cli-build/server/app/index.rsc +5 -5
- package/app/.next-cli-build/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/index.segments/_full.segment.rsc +5 -5
- package/app/.next-cli-build/server/app/index.segments/_head.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/index.segments/_index.segment.rsc +5 -5
- package/app/.next-cli-build/server/app/index.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/landing/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/landing.html +1 -1
- package/app/.next-cli-build/server/app/landing.rsc +5 -5
- package/app/.next-cli-build/server/app/landing.segments/_full.segment.rsc +5 -5
- package/app/.next-cli-build/server/app/landing.segments/_head.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/landing.segments/_index.segment.rsc +5 -5
- package/app/.next-cli-build/server/app/landing.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/landing.segments/landing/__PAGE__.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/landing.segments/landing.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/login/page.js +1 -1
- package/app/.next-cli-build/server/app/login/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app/login.html +1 -1
- package/app/.next-cli-build/server/app/login.rsc +6 -6
- package/app/.next-cli-build/server/app/login.segments/_full.segment.rsc +6 -6
- package/app/.next-cli-build/server/app/login.segments/_head.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/login.segments/_index.segment.rsc +5 -5
- package/app/.next-cli-build/server/app/login.segments/_tree.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/login.segments/login/__PAGE__.segment.rsc +2 -2
- package/app/.next-cli-build/server/app/login.segments/login.segment.rsc +1 -1
- package/app/.next-cli-build/server/app/page_client-reference-manifest.js +1 -1
- package/app/.next-cli-build/server/app-paths-manifest.json +6 -6
- package/app/.next-cli-build/server/chunks/2338.js +1 -1
- package/app/.next-cli-build/server/chunks/3110.js +1 -1
- package/app/.next-cli-build/server/chunks/402.js +3 -3
- package/app/.next-cli-build/server/chunks/4746.js +1 -1
- package/app/.next-cli-build/server/chunks/6328.js +1 -1
- package/app/.next-cli-build/server/chunks/700.js +1 -1
- package/app/.next-cli-build/server/chunks/8895.js +4 -4
- package/app/.next-cli-build/server/chunks/9434.js +1 -1
- package/app/.next-cli-build/server/middleware-build-manifest.js +1 -1
- package/app/.next-cli-build/server/pages/404.html +1 -1
- package/app/.next-cli-build/server/pages/500.html +1 -1
- package/app/.next-cli-build/static/chunks/{5263-5a847e4923149bc4.js → 5263-7885a40f96e3aac4.js} +1 -1
- package/app/.next-cli-build/static/chunks/{5497-b19f85c1ee9399df.js → 5497-447ba121006d7d18.js} +2 -2
- package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/personalcloudprovider/page-6b05f21639482913.js +1 -0
- package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/profile/{page-fab8d943eca47f0e.js → page-5b90e61fcf793123.js} +1 -1
- package/app/.next-cli-build/static/chunks/app/login/page-e47b11b0d77ecb52.js +1 -0
- package/app/cli/.build-home/AppData/Roaming/bluerouter/db/data.sqlite-shm +0 -0
- package/app/cli/.build-home/AppData/Roaming/bluerouter/db/data.sqlite-wal +0 -0
- package/app/package.json +1 -1
- package/package.json +1 -1
- package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/personalcloudprovider/page-961751cc2691b310.js +0 -1
- package/app/.next-cli-build/static/chunks/app/login/page-debca44f3cbe55f7.js +0 -1
- /package/app/.next-cli-build/static/{QT87bXKEm4EpZ4Gqjzv3v → 6b3mOIJ7Aghz0AE6a6_RL}/_buildManifest.js +0 -0
- /package/app/.next-cli-build/static/{QT87bXKEm4EpZ4Gqjzv3v → 6b3mOIJ7Aghz0AE6a6_RL}/_ssgManifest.js +0 -0
- /package/app/cli/.build-home/AppData/Roaming/bluerouter/db/backups/{upgrade-5.0.15-to-5.0.16-5.0.16-20260625-075952 → upgrade-5.0.19-to-5.0.20-5.0.20-20260625-100030}/data.sqlite +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[3538],{43503:(e,t,s)=>{"use strict";s.d(t,{default:()=>c});var n=s(95155),r=s(12115),a=s(35497),l=s(57250);function i(e,t){return t.find(t=>t.id===e)?.name||e}function d(e){return String(e||"").trim().toLowerCase()}function o(e){return Array.isArray(e?.importedModels)?e.importedModels:[]}function c(){let[e,t]=(0,r.useState)(!0),[s,c]=(0,r.useState)(!1),[x,m]=(0,r.useState)(""),[h,u]=(0,r.useState)(""),[p,b]=(0,r.useState)(""),[g,j]=(0,r.useState)(!1),[f,y]=(0,r.useState)([]),[v,N]=(0,r.useState)([]),[k,w]=(0,r.useState)(null),[C,A]=(0,r.useState)(null),[I,M]=(0,r.useState)(""),[S,O]=(0,r.useState)(null),[T,$]=(0,r.useState)([]),[E,R]=(0,r.useState)(!1),[K,q]=(0,r.useState)(""),[z,P]=(0,r.useState)([]),[F,U]=(0,r.useState)(!1),[L,B]=(0,r.useState)(!1),[D,_]=(0,r.useState)({}),[G,H]=(0,r.useState)(""),[J,X]=(0,r.useState)({}),[Z,V]=(0,r.useState)(null),[W,Q]=(0,r.useState)({}),[Y,ee]=(0,r.useState)(""),[et,es]=(0,r.useState)(""),[en,er]=(0,r.useState)({}),[ea,el]=(0,r.useState)({}),[ei,ed]=(0,r.useState)(""),[eo,ec]=(0,r.useState)(!1),[ex,em]=(0,r.useState)(!0),eh=(0,r.useCallback)(async()=>{t(!0),m("");try{let e=await fetch("/api/personal-cloud-providers",{cache:"no-store"}),t=await e.json().catch(()=>({}));if(!e.ok)throw Error(t.error||"Kh\xf4ng tải được personal cloud providers");b(t.userId||""),j(!0===t.isAdmin),y(t.providers||[]),N(t.connections||[]),em(!1!==t.globalRtkEnabled),er(t.routing||{}),el(e=>{let s={...e};for(let[e,n]of Object.entries(t.routing||{}))s[e]={...n};return s}),H(e=>e||t.userId||"")}catch(e){m(e.message||"Kh\xf4ng tải được personal cloud providers")}finally{t(!1)}},[]),eu=(0,r.useCallback)(async()=>{if(g){B(!0);try{let e=await fetch("/api/personal-cloud-providers/permissions",{cache:"no-store"}),t=await e.json().catch(()=>({}));if(!e.ok)throw Error(t.error||"Kh\xf4ng tải được quyền OAuth");_(t.permissions||{})}catch(e){m(e.message||"Kh\xf4ng tải được quyền OAuth")}finally{B(!1)}}},[g]);(0,r.useEffect)(()=>{eh()},[eh]),(0,r.useEffect)(()=>{g&&eu()},[g,eu]),(0,r.useEffect)(()=>{let e=D[d(G)]||{},t={};for(let s of f)t[s.id]=!0===e[s.id];X(t)},[G,D,f]);let ep=(0,r.useMemo)(()=>{let e=d(S?.ownerUser||p);return e?T.filter(t=>d(t.ownerUser||t.createdByUser||p)===e):[]},[T,S,p]),eb=(0,r.useMemo)(()=>Object.entries(D).map(([e,t])=>{let s=f.filter(e=>t?.[e.id]===!0);return{userId:e,providerState:t||{},enabledProviders:s}}).filter(e=>e.enabledProviders.length>0).sort((e,t)=>e.userId.localeCompare(t.userId)),[D,f]),eg=async()=>{w(null),u("OAuth account đ\xe3 được th\xeam. Model sẽ được import tự động nếu provider hỗ trợ."),await eh()},ej=async(e,t)=>{m(""),u("");try{let s=await fetch(`/api/personal-cloud-providers/${encodeURIComponent(e)}`,{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)}),n=await s.json().catch(()=>({}));if(!s.ok)throw Error(n.error||"Kh\xf4ng cập nhật được connection");await eh()}catch(e){m(e.message||"Kh\xf4ng cập nhật được connection")}},ef=async e=>{m(""),u(""),M(e.id);try{let t=await fetch(`/api/personal-cloud-providers/${encodeURIComponent(e.id)}/import-models`,{method:"POST"}),s=await t.json().catch(()=>({}));if(!t.ok)throw Error(s.error||"Kh\xf4ng import được model");N(t=>t.map(t=>t.id===e.id?{...t,availableModels:s.models||[],importedModels:s.importedModels||[],modelImport:s.modelImport||t.modelImport}:t)),V(t=>t?.id===e.id?{...t,availableModels:s.models||[],importedModels:s.importedModels||[],modelImport:s.modelImport||t.modelImport}:t);let n=s.modelImport?.source==="provider"?"provider":"catalog fallback";u(`Đ\xe3 cập nhật ${s.models?.length||0} model từ ${n}.`)}catch(e){m(e.message||"Kh\xf4ng import được model")}finally{M("")}},ey=async e=>{R(!0);try{let t=d(e?.ownerUser||p),s=t?`&ownerUser=${encodeURIComponent(t)}`:"",n=await fetch(`/api/keys?pageSize=100&status=active${s}`,{cache:"no-store"}),r=await n.json().catch(()=>({}));if(!n.ok)throw Error(r.error||"Kh\xf4ng tải được API keys");let a=Array.isArray(r.keys)?r.keys:[];$(a);let l=d(r.userId),i=a.find(e=>d(e.ownerUser||e.createdByUser||l)===t);q(e=>e||i?.id||"")}catch(e){m(e.message||"Kh\xf4ng tải được API keys")}finally{R(!1)}},ev=async e=>{let t,s;m(""),u(""),O(e),P((s=(t=o(e)).filter(e=>"llm"===(e.type||"llm")).slice(0,3).map(e=>e.routeModel).filter(Boolean)).length>0?s:t.slice(0,3).map(e=>e.routeModel).filter(Boolean)),q(""),await ey(e)},eN=async()=>{if(!S)return;if(!K)return void m("Chọn API key cần th\xeam model.");let e=Array.from(new Set((Array.isArray(z)?z:[]).map(e=>String(e||"").trim()).filter(Boolean)));if(0===e.length)return void m("Chọn \xedt nhất một model.");U(!0),m(""),u("");try{let t=await fetch(`/api/personal-cloud-providers/${encodeURIComponent(S.id)}/api-key-models`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKeyId:K,models:e})}),s=await t.json().catch(()=>({}));if(!t.ok)throw Error(s.error||"Kh\xf4ng th\xeam được model v\xe0o API key");O(null),u(`Đ\xe3 th\xeam ${s.addedModels?.length||e.length} model v\xe0o API key ${s.key?.name||""}.`)}catch(e){m(e.message||"Kh\xf4ng th\xeam được model v\xe0o API key")}finally{U(!1)}},ek=async()=>{if(C){m(""),u("");try{let e=await fetch(`/api/personal-cloud-providers/${encodeURIComponent(C.id)}`,{method:"DELETE"}),t=await e.json().catch(()=>({}));if(!e.ok)throw Error(t.error||"Kh\xf4ng x\xf3a được connection");A(null),await eh()}catch(e){m(e.message||"Kh\xf4ng x\xf3a được connection")}}},ew=async(e,t)=>{if(e?.id&&t?.routeModel){m(""),ee(t.routeModel),Q(e=>({...e,[t.routeModel]:{...e[t.routeModel]||{},loading:!0}}));try{let s=`/api/personal-cloud-providers/${encodeURIComponent(e.id)}/models/${t.routeModel.split("/").map(encodeURIComponent).join("/")}`,n=await fetch(s,{method:"POST"}),r=await n.json().catch(()=>({})),a={ok:r?.ok===!0,status:r?.status||n.status,text:r?.text||"",error:r?.error||(n.ok?"":"Test failed"),latencyMs:r?.latencyMs||0};Q(e=>({...e,[t.routeModel]:a}))}catch(e){Q(s=>({...s,[t.routeModel]:{ok:!1,error:e.message||"Test failed"}}))}finally{ee("")}}},eC=async(e,t)=>{if(e?.id&&t?.routeModel&&window.confirm(`X\xf3a model ${t.routeModel} khỏi connection ${e.name||e.id}?`)){m(""),u(""),es(t.routeModel);try{let s=`/api/personal-cloud-providers/${encodeURIComponent(e.id)}/models/${t.routeModel.split("/").map(encodeURIComponent).join("/")}`,n=await fetch(s,{method:"DELETE"}),r=await n.json().catch(()=>({}));if(!n.ok)throw Error(r?.error||"Kh\xf4ng x\xf3a được model");(e=>{if(!e?.connectionId&&!e?.id)return;let t=e.connectionId||e.id;N(s=>s.map(s=>s.id===t?{...s,importedModels:Array.isArray(e.importedModels)?e.importedModels:s.importedModels,availableModels:Array.isArray(e.models)?e.models:Array.isArray(e.availableModels)?e.availableModels:s.availableModels,modelImport:e.modelImport||s.modelImport}:s)),V(s=>s?.id===t?{...s,importedModels:Array.isArray(e.importedModels)?e.importedModels:s.importedModels,availableModels:Array.isArray(e.models)?e.models:Array.isArray(e.availableModels)?e.availableModels:s.availableModels,modelImport:e.modelImport||s.modelImport}:s)})(r),Q(e=>{let s={...e};return delete s[t.routeModel],s}),u(`Đ\xe3 x\xf3a model ${t.routeModel}.`)}catch(e){m(e.message||"Kh\xf4ng x\xf3a được model")}finally{es("")}}},eA=(e,t)=>{el(s=>{let n={...s[e]||{},...t};for(let e of Object.keys(n))(""===n[e]||void 0===n[e])&&delete n[e];return{...s,[e]:n}})},eI=async e=>{m(""),u(""),ed(e);try{let t=ea[e]||{},s={providerId:e,override:{fallbackStrategy:t.fallbackStrategy||"",stickyRoundRobinLimit:t.stickyRoundRobinLimit,stickyScope:t.stickyScope||"",stickyTtlMinutes:t.stickyTtlMinutes,stickyFallbackToClientIp:t.stickyFallbackToClientIp,stickyRebindOnFailure:t.stickyRebindOnFailure,stickyRebindFailureThreshold:t.stickyRebindFailureThreshold}},n=await fetch("/api/personal-cloud-providers/routing",{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)}),r=await n.json().catch(()=>({}));if(!n.ok)throw Error(r?.error||"Kh\xf4ng lưu được routing");er(r.routing||{}),u(`Đ\xe3 cập nhật routing cho ${e}.`)}catch(e){m(e.message||"Kh\xf4ng lưu được routing")}finally{ed("")}},eM=async e=>{m(""),u(""),ed(e);try{let t=await fetch(`/api/personal-cloud-providers/routing?providerId=${encodeURIComponent(e)}`,{method:"DELETE"}),s=await t.json().catch(()=>({}));if(!t.ok)throw Error(s?.error||"Kh\xf4ng reset được routing");er(s.routing||{}),el(t=>{let s={...t};return delete s[e],s}),u(`Đ\xe3 reset ${e} về ch\xednh s\xe1ch mặc định.`)}catch(e){m(e.message||"Kh\xf4ng reset được routing")}finally{ed("")}},eS=async()=>{let e=d(G);if(!e)return void m("Nhập username/email cần cấp quyền.");c(!0),m(""),u("");try{let t=await fetch("/api/personal-cloud-providers/permissions",{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify({userId:e,providers:J})}),s=await t.json().catch(()=>({}));if(!t.ok)throw Error(s.error||"Kh\xf4ng lưu được quyền OAuth");_(s.permissions||{});let n=s.user?.id||e;n!==e&&H(n),u(`Đ\xe3 lưu quyền OAuth cho ${n}.`),await eh()}catch(e){m(e.message||"Kh\xf4ng lưu được quyền OAuth")}finally{c(!1)}},eO=async e=>{let t=d(e);if(t&&window.confirm(`Thu hồi to\xe0n bộ quyền OAuth provider của ${t}? OAuth account của user n\xe0y sẽ bị X\xd3A hẳn (token, model đ\xe3 import) v\xe0 model tương ứng sẽ bị gỡ khỏi mọi API key đ\xe3 g\xe1n. H\xe0nh động n\xe0y kh\xf4ng thể ho\xe0n t\xe1c.`)){c(!0),m(""),u("");try{let e=await fetch(`/api/personal-cloud-providers/permissions?userId=${encodeURIComponent(t)}`,{method:"DELETE"}),s=await e.json().catch(()=>({}));if(!e.ok)throw Error(s.error||"Kh\xf4ng thu hồi được quyền OAuth");_(s.permissions||{}),d(G)===t&&H(""),u(`Đ\xe3 thu hồi quyền v\xe0 x\xf3a OAuth account của ${t}.`),await eh()}catch(e){m(e.message||"Kh\xf4ng thu hồi được quyền OAuth")}finally{c(!1)}}},eT=k?function(e={}){return{id:e.id,name:e.name||e.id,icon:e.icon||"cloud",color:e.color||"#64748b",website:e.website||"",notice:e.notice||null,deprecationNotice:e.deprecationNotice||"",serviceKinds:e.serviceKinds||["llm"]}}(k):null,e$=g?f:f.filter(e=>e.enabled),eE=o(S),eR=S?.modelImport||{},eK=o(Z);return(0,n.jsxs)("div",{className:"space-y-6",children:[(0,n.jsx)("div",{children:(0,n.jsxs)("div",{className:"flex flex-col gap-3 md:flex-row md:items-start md:justify-between",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("h1",{className:"text-2xl font-semibold text-text-main",children:"Personal Cloud Providers"}),(0,n.jsx)("p",{className:"mt-1 text-sm text-text-muted",children:"Kết nối OAuth c\xe1 nh\xe2n cho Claude Code, OpenAI Codex v\xe0 Antigravity. Account c\xe1 nh\xe2n chỉ owner nh\xecn thấy, chỉ API key của owner được d\xf9ng. Cột RTK cho ph\xe9p override ri\xeang từng account (Lu\xf4n ON / Lu\xf4n OFF) bất kể cấu h\xecnh RTK global ở /dashboard/endpoint đang on hay off — để trống th\xec theo global."})]}),(0,n.jsxs)("div",{className:"rounded-2xl border border-border bg-surface px-4 py-3 text-sm",children:[(0,n.jsx)("div",{className:"text-xs uppercase tracking-wide text-text-muted",children:"Current user"}),(0,n.jsx)("div",{className:"mt-1 break-all font-mono text-text-main",children:p||"—"})]})]})}),x?(0,n.jsx)("div",{className:"rounded-2xl border border-red-500/30 bg-red-500/10 px-4 py-3 text-sm text-red-700 dark:text-red-300",children:x}):null,h?(0,n.jsx)("div",{className:"rounded-2xl border border-green-500/30 bg-green-500/10 px-4 py-3 text-sm text-green-700 dark:text-green-300",children:h}):null,(0,n.jsx)("div",{className:"grid gap-4 lg:grid-cols-3",children:0===f.length?(0,n.jsx)("div",{className:"rounded-2xl border border-dashed border-border p-8 text-center text-sm text-text-muted lg:col-span-3",children:"Admin chưa cấp quyền personal OAuth provider n\xe0o cho user n\xe0y."}):f.map(e=>(0,n.jsxs)(a.Zp,{className:"space-y-4",children:[(0,n.jsxs)("div",{className:"flex items-start gap-3",children:[(0,n.jsx)("span",{className:"inline-flex size-10 shrink-0 items-center justify-center rounded-xl",style:{backgroundColor:`${e.color||"#64748b"}22`},children:(0,n.jsx)(l.A,{src:`/providers/${e.id}.png`,alt:e.name,size:34,className:"max-h-[34px] max-w-[34px] rounded-lg object-contain",fallbackText:e.id.slice(0,2).toUpperCase(),fallbackColor:e.color||"#64748b"})}),(0,n.jsxs)("div",{className:"min-w-0 flex-1",children:[(0,n.jsxs)("div",{className:"flex items-center gap-2",children:[(0,n.jsx)("h2",{className:"font-semibold text-text-main",children:e.name}),e.enabled?(0,n.jsx)(a.Ex,{variant:"success",size:"sm",children:"Enabled"}):(0,n.jsx)(a.Ex,{variant:"warning",size:"sm",children:"Locked"})]}),(0,n.jsx)("p",{className:"mt-1 text-xs text-text-muted",children:e.enabled?"Được admin cấp quyền, c\xf3 thể add OAuth account c\xe1 nh\xe2n.":"Admin chưa cấp quyền cho user n\xe0y."})]})]}),e.deprecationNotice?(0,n.jsx)("p",{className:"rounded-xl border border-amber-500/30 bg-amber-500/10 p-3 text-xs text-amber-700 dark:text-amber-300",children:e.deprecationNotice}):null,(0,n.jsxs)(a.$n,{fullWidth:!0,disabled:!e.enabled,onClick:()=>{e.enabled&&w(e)},icon:"add_link",children:["Add ",e.name," account"]})]},e.id))}),(0,n.jsxs)(a.Zp,{className:"space-y-4",children:[(0,n.jsxs)("div",{className:"flex flex-col gap-2 md:flex-row md:items-center md:justify-between",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"My personal accounts"}),(0,n.jsx)("p",{className:"text-sm text-text-muted",children:"OAuth xong sẽ tự import model nếu provider hỗ trợ. Nếu kh\xf4ng gọi được endpoint model, hệ thống d\xf9ng catalog fallback để user vẫn chọn được model."})]}),(0,n.jsx)(a.$n,{variant:"outline",size:"sm",onClick:eh,loading:e,icon:"refresh",children:"Refresh"})]}),e?(0,n.jsx)("div",{className:"rounded-2xl border border-dashed border-border p-8 text-center text-sm text-text-muted",children:"Đang tải..."}):0===v.length?(0,n.jsx)("div",{className:"rounded-2xl border border-dashed border-border p-8 text-center text-sm text-text-muted",children:"Chưa c\xf3 personal OAuth account n\xe0o."}):(0,n.jsx)("div",{className:"overflow-x-auto rounded-2xl border border-border",children:(0,n.jsxs)("table",{className:"min-w-full divide-y divide-border text-sm",children:[(0,n.jsx)("thead",{className:"bg-surface/80 text-left text-xs uppercase tracking-wide text-text-muted",children:(0,n.jsxs)("tr",{children:[(0,n.jsx)("th",{className:"px-4 py-3 font-medium",children:"Connection"}),(0,n.jsx)("th",{className:"px-4 py-3 font-medium",children:"Provider"}),(0,n.jsx)("th",{className:"px-4 py-3 font-medium",children:"Account"}),(0,n.jsx)("th",{className:"px-4 py-3 font-medium",children:"Models"}),(0,n.jsx)("th",{className:"px-4 py-3 font-medium",children:"Created"}),(0,n.jsx)("th",{className:"px-4 py-3 font-medium",children:"Active"}),(0,n.jsx)("th",{className:"px-4 py-3 font-medium",children:(0,n.jsxs)("span",{className:"inline-flex items-center gap-1.5",children:["RTK (Token Savings)",(0,n.jsxs)(a.Ex,{variant:ex?"success":"default",size:"sm",className:"normal-case",children:["Global: ",ex?"ON":"OFF"]}),(0,n.jsx)("button",{type:"button",onClick:()=>ec(!0),title:"RTK l\xe0 g\xec? Bấm để xem giải th\xedch",className:"inline-flex size-4 shrink-0 items-center justify-center rounded-full border border-border text-[10px] font-bold normal-case text-text-muted transition-colors hover:border-brand-500 hover:text-brand-600",children:"?"})]})}),(0,n.jsx)("th",{className:"px-4 py-3 text-right font-medium",children:"Actions"})]})}),(0,n.jsx)("tbody",{className:"divide-y divide-border bg-background",children:v.map(e=>{let t=Array.isArray(e?.availableModels)?e.availableModels:[],s=e.modelImport||{};return(0,n.jsxs)("tr",{className:"align-top hover:bg-surface/50",children:[(0,n.jsxs)("td",{className:"px-4 py-4",children:[(0,n.jsx)("div",{className:"font-medium text-text-main",children:e.name||e.id}),(0,n.jsx)("div",{className:"mt-1 font-mono text-xs text-text-muted",children:e.id})]}),(0,n.jsx)("td",{className:"px-4 py-4",children:(0,n.jsxs)("div",{className:"flex items-center gap-2",children:[(0,n.jsx)(l.A,{src:`/providers/${e.provider}.png`,alt:e.provider,size:24,className:"max-h-[24px] max-w-[24px] rounded object-contain",fallbackText:e.provider.slice(0,2).toUpperCase()}),(0,n.jsx)("span",{children:i(e.provider,f)})]})}),(0,n.jsxs)("td",{className:"px-4 py-4",children:[(0,n.jsx)("div",{className:"break-all text-text-main",children:e.email||e.displayName||"—"}),(0,n.jsxs)("div",{className:"mt-1 break-all text-xs text-text-muted",children:["Owner: ",e.ownerUser||p||"—"]})]}),(0,n.jsxs)("td",{className:"px-4 py-4",children:[(0,n.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[function(e={}){return"provider"===(e.source||"catalog")?(0,n.jsx)(a.Ex,{variant:"success",size:"sm",children:"Imported"}):(0,n.jsx)(a.Ex,{variant:"warning",size:"sm",children:"Catalog"})}(s),(0,n.jsxs)("span",{className:"text-xs text-text-muted",children:[t.length," model(s)"]})]}),s.warning?(0,n.jsx)("div",{className:"mt-1 max-w-[320px] truncate text-xs text-amber-600 dark:text-amber-300",title:s.warning,children:s.warning}):null,t.length>0?(0,n.jsxs)("div",{className:"mt-2 flex max-w-[360px] flex-wrap gap-1",children:[t.slice(0,4).map(e=>(0,n.jsx)("span",{className:"rounded-full border border-border bg-surface px-2 py-0.5 font-mono text-[11px] text-text-muted",children:e.routeModel},e.routeModel)),t.length>4?(0,n.jsxs)("span",{className:"rounded-full border border-border bg-surface px-2 py-0.5 text-[11px] text-text-muted",children:["+",t.length-4]}):null]}):null]}),(0,n.jsx)("td",{className:"px-4 py-4 text-xs text-text-muted",children:function(e){if(!e)return"—";try{return new Intl.DateTimeFormat("vi-VN",{dateStyle:"short",timeStyle:"short"}).format(new Date(e))}catch{return e}}(e.createdAt)}),(0,n.jsx)("td",{className:"px-4 py-4",children:(0,n.jsx)(a.lM,{checked:!1!==e.isActive,onChange:t=>ej(e.id,{isActive:t})})}),(0,n.jsx)("td",{className:"px-4 py-4",children:(0,n.jsxs)("select",{value:!0===e.rtkEnabled?"on":!1===e.rtkEnabled?"off":"inherit",onChange:t=>{let s=t.target.value;ej(e.id,{rtkEnabled:"inherit"===s?null:"on"===s})},className:"h-9 w-full min-w-[140px] rounded-xl border border-border bg-background px-2 text-xs text-text-main outline-none focus:border-brand-500",children:[(0,n.jsx)("option",{value:"inherit",children:"Theo global"}),(0,n.jsx)("option",{value:"on",children:"Lu\xf4n ON"}),(0,n.jsx)("option",{value:"off",children:"Lu\xf4n OFF"})]})}),(0,n.jsx)("td",{className:"px-4 py-4",children:(0,n.jsxs)("div",{className:"flex flex-wrap justify-end gap-2",children:[(0,n.jsx)(a.$n,{variant:"outline",size:"sm",loading:I===e.id,onClick:()=>ef(e),children:"Import models"}),(0,n.jsx)(a.$n,{variant:"outline",size:"sm",disabled:0===o(e).length,onClick:()=>{m(""),u(""),V(e),Q({}),ee(""),es("")},children:"Manage models"}),(0,n.jsx)(a.$n,{variant:"secondary",size:"sm",disabled:0===o(e).length,onClick:()=>ev(e),children:"Add to API key"}),(0,n.jsx)(a.$n,{variant:"outline",size:"sm",onClick:()=>{let t;return t=window.prompt("T\xean connection mới",e.name||""),void(t?.trim()&&ej(e.id,{name:t.trim()}))},children:"Rename"}),(0,n.jsx)(a.$n,{variant:"danger",size:"sm",onClick:()=>A(e),children:"Delete"})]})})]},e.id)})})]})})]}),(0,n.jsxs)(a.Zp,{className:"space-y-4",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Routing strategy"}),(0,n.jsxs)("p",{className:"text-sm text-text-muted",children:["Khi bạn c\xf3 nhiều personal account cho c\xf9ng provider, đ\xe2y l\xe0 ch\xednh s\xe1ch chọn account cho từng request. Để trống = kế thừa ch\xednh s\xe1ch của admin ở ",(0,n.jsx)("span",{className:"font-mono",children:"/dashboard/providers/<provider>"}),"."]})]}),(0,n.jsx)("div",{className:"grid gap-4 lg:grid-cols-3",children:0===e$.length?(0,n.jsx)("div",{className:"rounded-2xl border border-dashed border-border p-6 text-center text-sm text-text-muted lg:col-span-3",children:"Bạn chưa được cấp quyền provider n\xe0o, n\xean chưa cần thiết lập routing."}):e$.map(e=>{let t=ea[e.id]||{},s=en[e.id]||null,r=!s,l=t.fallbackStrategy||"",i="round-robin"===l,d=ei===e.id;return(0,n.jsxs)("div",{className:"rounded-2xl border border-border bg-surface p-4 space-y-3",children:[(0,n.jsxs)("div",{className:"flex items-center justify-between gap-2",children:[(0,n.jsxs)("div",{className:"min-w-0",children:[(0,n.jsx)("div",{className:"font-semibold text-text-main",children:e.name}),(0,n.jsx)("div",{className:"text-xs text-text-muted",children:r?"Đang kế thừa policy global":`Override active: ${s.fallbackStrategy||"inherit"}`})]}),r?(0,n.jsx)(a.Ex,{variant:"default",size:"sm",children:"Inherit"}):(0,n.jsx)(a.Ex,{variant:"success",size:"sm",children:"Override"})]}),(0,n.jsxs)("label",{className:"block text-sm",children:[(0,n.jsx)("span",{className:"mb-1 block font-medium text-text-main",children:"Strategy"}),(0,n.jsxs)("select",{value:l,onChange:t=>eA(e.id,{fallbackStrategy:t.target.value}),className:"h-10 w-full rounded-xl border border-border bg-background px-3 text-sm text-text-main outline-none focus:border-brand-500",disabled:d,children:[(0,n.jsx)("option",{value:"",children:"Inherit (use global)"}),(0,n.jsx)("option",{value:"fill-first",children:"fill-first — chạy hết account 1 mới sang account 2"}),(0,n.jsx)("option",{value:"round-robin",children:"round-robin — lu\xe2n phi\xean theo sticky limit"}),(0,n.jsx)("option",{value:"least-latency",children:"least-latency — chọn account nhanh nhất"}),(0,n.jsx)("option",{value:"p2c",children:"p2c — power-of-two-choices"})]})]}),i?(0,n.jsxs)("div",{className:"space-y-2 rounded-xl border border-border/50 bg-background/50 p-3",children:[(0,n.jsx)("div",{className:"text-xs text-text-muted",children:"Round-robin sticky params (để trống = d\xf9ng gi\xe1 trị global)"}),(0,n.jsxs)("label",{className:"block text-xs",children:[(0,n.jsx)("span",{className:"mb-1 block text-text-muted",children:"Sticky limit (số request li\xean tiếp trước khi rotate)"}),(0,n.jsx)(a.pd,{type:"number",min:1,value:t.stickyRoundRobinLimit??"",onChange:t=>eA(e.id,{stickyRoundRobinLimit:t.target.value?Number(t.target.value):void 0}),placeholder:"v\xed dụ 3",disabled:d})]}),(0,n.jsxs)("label",{className:"block text-xs",children:[(0,n.jsx)("span",{className:"mb-1 block text-text-muted",children:"Sticky scope"}),(0,n.jsxs)("select",{value:t.stickyScope||"",onChange:t=>eA(e.id,{stickyScope:t.target.value}),className:"h-9 w-full rounded-xl border border-border bg-background px-3 text-xs text-text-main outline-none focus:border-brand-500",disabled:d,children:[(0,n.jsx)("option",{value:"",children:"(inherit)"}),(0,n.jsx)("option",{value:"global",children:"global — rotate cho mọi request"}),(0,n.jsx)("option",{value:"client_ip",children:"client_ip — sticky theo IP"}),(0,n.jsx)("option",{value:"client_session",children:"client_session — sticky theo CLI session"})]})]}),(0,n.jsxs)("label",{className:"block text-xs",children:[(0,n.jsx)("span",{className:"mb-1 block text-text-muted",children:"Sticky TTL (ph\xfat)"}),(0,n.jsx)(a.pd,{type:"number",min:1,value:t.stickyTtlMinutes??"",onChange:t=>eA(e.id,{stickyTtlMinutes:t.target.value?Number(t.target.value):void 0}),placeholder:"v\xed dụ 120",disabled:d})]})]}):null,(0,n.jsxs)("div",{className:"flex flex-wrap gap-2 pt-1",children:[(0,n.jsx)(a.$n,{size:"sm",loading:d,onClick:()=>eI(e.id),children:"Save"}),(0,n.jsx)(a.$n,{size:"sm",variant:"ghost",disabled:d||r,onClick:()=>eM(e.id),children:"Reset to inherit"})]})]},e.id)})})]}),g?(0,n.jsxs)(a.Zp,{className:"space-y-4",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Admin: OAuth provider access"}),(0,n.jsx)("p",{className:"text-sm text-text-muted",children:"Default l\xe0 kh\xf4ng c\xf3 quyền. Nhập username/email rồi bật provider được ph\xe9p add personal account."})]}),(0,n.jsxs)("div",{className:"grid gap-3 md:grid-cols-[minmax(0,1fr)_auto] md:items-end",children:[(0,n.jsx)(a.pd,{label:"User ID / Email",value:G,onChange:e=>H(e.target.value),placeholder:"anh-tct hoặc anh-tct@fujinet.net"}),(0,n.jsx)(a.$n,{onClick:eS,loading:s,icon:"save",children:"Save permissions"})]}),(0,n.jsx)("div",{className:"grid gap-3 md:grid-cols-3",children:f.map(e=>(0,n.jsx)("div",{className:"rounded-2xl border border-border bg-surface p-4",children:(0,n.jsx)(a.lM,{checked:!0===J[e.id],onChange:t=>X(s=>({...s,[e.id]:t})),label:e.name,description:J[e.id]?"User được ph\xe9p add account":"User chưa được cấp quyền"})},e.id))}),(0,n.jsxs)("div",{className:"border-t border-border pt-4",children:[(0,n.jsxs)("div",{className:"mb-3 flex flex-col gap-2 md:flex-row md:items-center md:justify-between",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("h3",{className:"font-semibold text-text-main",children:"Granted OAuth Access"}),(0,n.jsx)("p",{className:"text-xs text-text-muted",children:"Danh s\xe1ch user hiện đang được cấp quyền add personal OAuth account."})]}),(0,n.jsx)(a.$n,{variant:"outline",size:"sm",onClick:eu,loading:L,icon:"refresh",children:"Refresh list"})]}),L?(0,n.jsx)("div",{className:"rounded-2xl border border-dashed border-border p-6 text-center text-sm text-text-muted",children:"Đang tải quyền..."}):0===eb.length?(0,n.jsx)("div",{className:"rounded-2xl border border-dashed border-border p-6 text-center text-sm text-text-muted",children:"Chưa c\xf3 user n\xe0o được cấp quyền OAuth provider."}):(0,n.jsx)("div",{className:"overflow-x-auto rounded-2xl border border-border",children:(0,n.jsxs)("table",{className:"min-w-full divide-y divide-border text-sm",children:[(0,n.jsx)("thead",{className:"bg-surface/80 text-left text-xs uppercase tracking-wide text-text-muted",children:(0,n.jsxs)("tr",{children:[(0,n.jsx)("th",{className:"px-4 py-3 font-medium",children:"User"}),f.map(e=>(0,n.jsx)("th",{className:"px-4 py-3 font-medium",children:e.name},e.id)),(0,n.jsx)("th",{className:"px-4 py-3 text-right font-medium",children:"Actions"})]})}),(0,n.jsx)("tbody",{className:"divide-y divide-border bg-background",children:eb.map(e=>(0,n.jsxs)("tr",{className:"hover:bg-surface/50",children:[(0,n.jsxs)("td",{className:"px-4 py-4",children:[(0,n.jsx)("div",{className:"break-all font-mono text-text-main",children:e.userId}),d(G)===e.userId?(0,n.jsx)("div",{className:"mt-1 text-xs text-brand-600 dark:text-brand-300",children:"Đang edit ở form ph\xeda tr\xean"}):null]}),f.map(t=>(0,n.jsx)("td",{className:"px-4 py-4",children:!0===e.providerState[t.id]?(0,n.jsx)(a.Ex,{variant:"success",size:"sm",children:"ON"}):(0,n.jsx)(a.Ex,{variant:"default",size:"sm",children:"OFF"})},t.id)),(0,n.jsx)("td",{className:"px-4 py-4",children:(0,n.jsxs)("div",{className:"flex flex-wrap justify-end gap-2",children:[(0,n.jsx)(a.$n,{variant:"outline",size:"sm",onClick:()=>(e=>{let t=d(e);H(t);let s=D[t]||{},n={};for(let e of f)n[e.id]=!0===s[e.id];X(n)})(e.userId),children:"Edit"}),(0,n.jsx)(a.$n,{variant:"danger",size:"sm",loading:s,onClick:()=>eO(e.userId),children:"Revoke"})]})})]},e.userId))})]})})]})]}):null,S?(0,n.jsx)(a.aF,{isOpen:!!S,onClose:()=>O(null),title:"Add models to API key",size:"full",footer:(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(a.$n,{variant:"ghost",onClick:()=>O(null),disabled:F,children:"Cancel"}),(0,n.jsx)(a.$n,{onClick:eN,loading:F,disabled:!K||0===z.length,children:"Add selected models"})]}),children:(0,n.jsxs)("div",{className:"space-y-4",children:[(0,n.jsxs)("div",{className:"rounded-2xl border border-border bg-surface p-4 text-sm",children:[(0,n.jsx)("div",{className:"font-semibold text-text-main",children:S.name||S.id}),(0,n.jsxs)("div",{className:"mt-1 text-text-muted",children:[i(S.provider,f)," \xb7 ",eE.length," imported model(s)"]}),eR.warning?(0,n.jsx)("div",{className:"mt-2 text-xs text-amber-600 dark:text-amber-300",children:eR.warning}):null,0===eE.length?(0,n.jsx)("div",{className:"mt-2 rounded-xl border border-amber-500/30 bg-amber-500/10 p-3 text-xs text-amber-700 dark:text-amber-300",children:'Chưa import được model n\xe0o từ provider. Bấm "Import models" tr\xean d\xf2ng connection trước khi g\xe1n v\xe0o API key.'}):null]}),(0,n.jsxs)("label",{className:"block text-sm",children:[(0,n.jsx)("span",{className:"mb-1 block font-medium text-text-main",children:"API key"}),(0,n.jsxs)("select",{value:K,onChange:e=>q(e.target.value),className:"h-10 w-full rounded-xl border border-border bg-background px-3 text-sm text-text-main outline-none focus:border-brand-500",disabled:E,children:[(0,n.jsx)("option",{value:"",children:E?"Đang tải API keys...":"Chọn API key"}),ep.map(e=>(0,n.jsxs)("option",{value:e.id,children:[e.name," \xb7 ",e.ownerUser||p]},e.id))]})]}),0!==ep.length||E?null:(0,n.jsx)("div",{className:"rounded-xl border border-amber-500/30 bg-amber-500/10 p-3 text-sm text-amber-700 dark:text-amber-300",children:"User n\xe0y chưa c\xf3 API key active để th\xeam model."}),(0,n.jsxs)("div",{className:"flex items-center justify-between gap-2",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("h3",{className:"font-semibold text-text-main",children:"Models"}),(0,n.jsx)("p",{className:"text-xs text-text-muted",children:"Model được lưu v\xe0o allowedModels của API key. Request sẽ route qua personal OAuth account của owner."})]}),(0,n.jsxs)("div",{className:"flex gap-2",children:[(0,n.jsx)(a.$n,{variant:"outline",size:"sm",onClick:()=>P(eE.map(e=>e.routeModel).filter(Boolean)),children:"Select all"}),(0,n.jsx)(a.$n,{variant:"ghost",size:"sm",onClick:()=>P([]),children:"Clear"})]})]}),(0,n.jsx)("div",{className:"grid gap-2 md:grid-cols-2",children:eE.map(e=>(0,n.jsxs)("label",{className:"flex cursor-pointer items-start gap-3 rounded-xl border border-border bg-background p-3 hover:bg-surface",children:[(0,n.jsx)("input",{type:"checkbox",className:"mt-1",checked:z.includes(e.routeModel),onChange:()=>{var t;return t=e.routeModel,void P(e=>e.includes(t)?e.filter(e=>e!==t):[...e,t])}}),(0,n.jsxs)("span",{className:"min-w-0 flex-1",children:[(0,n.jsx)("span",{className:"block font-medium text-text-main",children:e.name||e.id}),(0,n.jsx)("span",{className:"mt-1 block break-all font-mono text-xs text-text-muted",children:e.routeModel}),e.type&&"llm"!==e.type?(0,n.jsx)("span",{className:"mt-2 inline-flex rounded-full bg-surface px-2 py-0.5 text-[11px] text-text-muted",children:e.type}):null]})]},e.routeModel))})]})}):null,Z?(0,n.jsx)(a.aF,{isOpen:!!Z,onClose:()=>V(null),title:"Manage imported models",size:"full",footer:(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(a.$n,{variant:"ghost",onClick:()=>V(null),children:"Close"}),(0,n.jsx)(a.$n,{variant:"outline",loading:I===Z.id,onClick:()=>ef(Z),icon:"refresh",children:"Re-import from provider"})]}),children:(0,n.jsxs)("div",{className:"space-y-4",children:[(0,n.jsxs)("div",{className:"rounded-2xl border border-border bg-surface p-4 text-sm",children:[(0,n.jsx)("div",{className:"font-semibold text-text-main",children:Z.name||Z.id}),(0,n.jsxs)("div",{className:"mt-1 text-text-muted",children:[i(Z.provider,f)," \xb7 ",eK.length," imported model(s)"]}),(0,n.jsx)("div",{className:"mt-2 text-xs text-text-muted",children:'Test gửi 1 prompt "Say hello in five words" qua ch\xednh OAuth account của bạn, qua đ\xfang proxy của connection. X\xf3a model sẽ bỏ n\xf3 khỏi list importable; c\xe1c API key đ\xe3 gắn model n\xe0y kh\xf4ng bị thay đổi (request đến model đ\xf3 sẽ do provider ph\xeda tr\xean quyết định chấp nhận hay kh\xf4ng).'})]}),0===eK.length?(0,n.jsx)("div",{className:"rounded-2xl border border-dashed border-border p-8 text-center text-sm text-text-muted",children:'Chưa c\xf3 model n\xe0o được import. Bấm "Re-import from provider".'}):(0,n.jsx)("div",{className:"overflow-x-auto rounded-2xl border border-border",children:(0,n.jsxs)("table",{className:"min-w-full divide-y divide-border text-sm",children:[(0,n.jsx)("thead",{className:"bg-surface/80 text-left text-xs uppercase tracking-wide text-text-muted",children:(0,n.jsxs)("tr",{children:[(0,n.jsx)("th",{className:"px-4 py-3 font-medium",children:"Model"}),(0,n.jsx)("th",{className:"px-4 py-3 font-medium",children:"Route ID"}),(0,n.jsx)("th",{className:"px-4 py-3 font-medium",children:"Test result"}),(0,n.jsx)("th",{className:"px-4 py-3 text-right font-medium",children:"Actions"})]})}),(0,n.jsx)("tbody",{className:"divide-y divide-border bg-background",children:eK.map(e=>{let t=W[e.routeModel],s=Y===e.routeModel,r=et===e.routeModel;return(0,n.jsxs)("tr",{className:"align-top",children:[(0,n.jsxs)("td",{className:"px-4 py-3",children:[(0,n.jsx)("div",{className:"font-medium text-text-main",children:e.name||e.id}),e.type&&"llm"!==e.type?(0,n.jsx)("div",{className:"mt-1 text-xs text-text-muted",children:e.type}):null]}),(0,n.jsx)("td",{className:"px-4 py-3 font-mono text-xs text-text-muted break-all",children:e.routeModel}),(0,n.jsx)("td",{className:"px-4 py-3 text-xs",children:s?(0,n.jsx)("span",{className:"text-text-muted",children:"Đang test..."}):t?t.ok?(0,n.jsxs)("div",{className:"space-y-1",children:[(0,n.jsxs)("div",{className:"text-green-700 dark:text-green-300",children:["OK \xb7 ",t.latencyMs||0,"ms"]}),(0,n.jsx)("div",{className:"break-all text-text-muted",children:(t.text||"").slice(0,200)})]}):(0,n.jsxs)("div",{className:"space-y-1",children:[(0,n.jsxs)("div",{className:"text-red-700 dark:text-red-300",children:["FAIL \xb7 status ",t.status||"?"]}),(0,n.jsx)("div",{className:"break-all text-text-muted",children:(t.error||"").slice(0,200)})]}):(0,n.jsx)("span",{className:"text-text-muted",children:"—"})}),(0,n.jsx)("td",{className:"px-4 py-3",children:(0,n.jsxs)("div",{className:"flex flex-wrap justify-end gap-2",children:[(0,n.jsx)(a.$n,{variant:"outline",size:"sm",loading:s,disabled:r,onClick:()=>ew(Z,e),children:"Say hello"}),(0,n.jsx)(a.$n,{variant:"danger",size:"sm",loading:r,disabled:s,onClick:()=>eC(Z,e),children:"Delete"})]})})]},e.routeModel)})})]})})]})}):null,eo?(0,n.jsx)(a.aF,{isOpen:eo,onClose:()=>ec(!1),title:"RTK (Token Savings) l\xe0 g\xec?",size:"xl",footer:(0,n.jsx)(a.$n,{onClick:()=>ec(!1),children:"Đ\xe3 hiểu"}),children:(0,n.jsxs)("div",{className:"space-y-5 text-sm text-text-main",children:[(0,n.jsxs)("div",{className:"flex items-center gap-2 rounded-xl border border-border bg-surface px-3 py-2",children:[(0,n.jsx)("span",{className:"text-xs text-text-muted",children:"Global RTK hiện đang:"}),(0,n.jsx)(a.Ex,{variant:ex?"success":"default",size:"sm",children:ex?"ON":"OFF"}),(0,n.jsx)("span",{className:"text-xs text-text-muted",children:'— \xe1p dụng cho mọi account chọn "Theo global"'})]}),(0,n.jsx)("p",{className:"text-text-muted",children:"RTK l\xe0 bộ lọc n\xe9n output của tool (Bash, Grep, Glob, Read...) ngay trong request trước khi gửi l\xean model, gi\xfap giảm số token phải gửi m\xe0 kh\xf4ng l\xe0m mất th\xf4ng tin quan trọng — chỉ t\xe1c động tới phần tool output, kh\xf4ng đụng v\xe0o nội dung chat."}),(0,n.jsxs)("div",{children:[(0,n.jsx)("h3",{className:"mb-2 font-semibold text-text-main",children:"Hoạt động ra sao với CLI tool"}),(0,n.jsx)("p",{className:"text-text-muted",children:"Mỗi khi Claude Code / Codex CLI / OpenCode... gọi tool v\xe0 nhận lại output, RTK tự nhận diện định dạng quen thuộc rồi r\xfat gọn theo đ\xfang cấu tr\xfac của n\xf3:"}),(0,n.jsxs)("ul",{className:"mt-2 list-disc space-y-1 pl-5 text-text-muted",children:[(0,n.jsxs)("li",{children:[(0,n.jsx)("span",{className:"font-mono text-text-main",children:"git diff"})," — giữ v\xe0i d\xf2ng context quanh thay đổi, cắt phần hunk qu\xe1 d\xe0i"]}),(0,n.jsxs)("li",{children:[(0,n.jsx)("span",{className:"font-mono text-text-main",children:"git status"})," / ",(0,n.jsx)("span",{className:"font-mono text-text-main",children:"git log"})," — gom gọn danh s\xe1ch file thay đổi, danh s\xe1ch commit"]}),(0,n.jsxs)("li",{children:[(0,n.jsx)("span",{className:"font-mono text-text-main",children:"grep"})," / ",(0,n.jsx)("span",{className:"font-mono text-text-main",children:"find"})," — giới hạn số match hiển thị mỗi file/thư mục"]}),(0,n.jsxs)("li",{children:[(0,n.jsx)("span",{className:"font-mono text-text-main",children:"ls -la"})," / ",(0,n.jsx)("span",{className:"font-mono text-text-main",children:"tree"})," — t\xf3m tắt theo loại file, cắt c\xe2y thư mục qu\xe1 s\xe2u"]}),(0,n.jsx)("li",{children:"Build log (npm/yarn/cargo...) — chỉ giữ d\xf2ng quan trọng (lỗi, kết quả build)"}),(0,n.jsx)("li",{children:"Output d\xe0i chung kh\xf4ng r\xf5 định dạng — fallback dedup d\xf2ng lặp hoặc smart-truncate (giữ đầu + cuối)"})]})]}),(0,n.jsxs)("div",{children:[(0,n.jsx)("h3",{className:"mb-2 font-semibold text-text-main",children:"Hiệu quả thực tế"}),(0,n.jsx)("div",{className:"overflow-x-auto rounded-xl border border-border",children:(0,n.jsxs)("table",{className:"min-w-full text-xs",children:[(0,n.jsx)("thead",{className:"bg-surface/80 text-left uppercase tracking-wide text-text-muted",children:(0,n.jsxs)("tr",{children:[(0,n.jsx)("th",{className:"px-3 py-2 font-medium",children:"Loại output"}),(0,n.jsx)("th",{className:"px-3 py-2 font-medium",children:"Trước"}),(0,n.jsx)("th",{className:"px-3 py-2 font-medium",children:"Sau"}),(0,n.jsx)("th",{className:"px-3 py-2 font-medium",children:"Tiết kiệm"})]})}),(0,n.jsxs)("tbody",{className:"divide-y divide-border",children:[(0,n.jsxs)("tr",{children:[(0,n.jsx)("td",{className:"px-3 py-2 font-mono",children:"git diff"}),(0,n.jsx)("td",{className:"px-3 py-2",children:"7384B"}),(0,n.jsx)("td",{className:"px-3 py-2",children:"3894B"}),(0,n.jsx)("td",{className:"px-3 py-2 text-green-600 dark:text-green-400",children:"47.3%"})]}),(0,n.jsxs)("tr",{children:[(0,n.jsx)("td",{className:"px-3 py-2 font-mono",children:"grep -n"}),(0,n.jsx)("td",{className:"px-3 py-2",children:"3723B"}),(0,n.jsx)("td",{className:"px-3 py-2",children:"1447B"}),(0,n.jsx)("td",{className:"px-3 py-2 text-green-600 dark:text-green-400",children:"61.1%"})]}),(0,n.jsxs)("tr",{children:[(0,n.jsx)("td",{className:"px-3 py-2 font-mono",children:"find"}),(0,n.jsx)("td",{className:"px-3 py-2",children:"729B"}),(0,n.jsx)("td",{className:"px-3 py-2",children:"264B"}),(0,n.jsx)("td",{className:"px-3 py-2 text-green-600 dark:text-green-400",children:"63.8%"})]})]})]})})]}),(0,n.jsxs)("div",{children:[(0,n.jsx)("h3",{className:"mb-2 font-semibold text-text-main",children:"Khi n\xe0o KH\xd4NG bị n\xe9n"}),(0,n.jsxs)("ul",{className:"list-disc space-y-1 pl-5 text-text-muted",children:[(0,n.jsx)("li",{children:"Chat thường kh\xf4ng gọi tool — kh\xf4ng c\xf3 g\xec để n\xe9n"}),(0,n.jsx)("li",{children:"Output nhỏ hơn 500B — kh\xf4ng đ\xe1ng n\xe9n"}),(0,n.jsxs)("li",{children:["Output b\xe1o lỗi (",(0,n.jsx)("span",{className:"font-mono text-text-main",children:"is_error"}),") — lu\xf4n giữ nguy\xean để debug"]}),(0,n.jsx)("li",{children:"Output lớn hơn 10MB — bỏ qua để tr\xe1nh tốn CPU xử l\xfd"})]})]}),(0,n.jsxs)("div",{children:[(0,n.jsx)("h3",{className:"mb-2 font-semibold text-text-main",children:"Global vs từng account"}),(0,n.jsxs)("p",{className:"text-text-muted",children:["Dropdown RTK ở bảng tr\xean cho ph\xe9p override ri\xeang từng account:",(0,n.jsx)("span",{className:"font-semibold text-text-main",children:" Theo global"})," (mặc định, d\xf9ng đ\xfang setting global),",(0,n.jsx)("span",{className:"font-semibold text-text-main",children:" Lu\xf4n ON"})," hoặc",(0,n.jsx)("span",{className:"font-semibold text-text-main",children:" Lu\xf4n OFF"})," — override lu\xf4n thắng global theo cả 2 chiều, n\xean c\xf3 thể để global OFF v\xe0 chỉ bật cho account d\xf9ng CLI tool, hoặc ngược lại."]})]})]})}):null,eT?(0,n.jsx)(a.LF,{isOpen:!!k,provider:k.id,providerInfo:eT,connectionScope:"personal",onSuccess:eg,onClose:()=>w(null)}):null,C?(0,n.jsx)(a.uo,{isOpen:!!C,onClose:()=>A(null),onConfirm:ek,title:"Delete personal account",message:`X\xf3a connection ${C.name||C.id}?`,confirmText:"Delete",cancelText:"Cancel",variant:"danger"}):null]})}},47584:(e,t,s)=>{Promise.resolve().then(s.bind(s,43503))}},e=>{e.O(0,[2574,3862,246,5792,5263,5497,8441,3794,7358],()=>e(e.s=47584)),_N_E=e.O()}]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[3471],{7973:(e,a,t)=>{Promise.resolve().then(t.bind(t,64561))},14051:(e,a,t)=>{e.exports=t(34701)()},34701:(e,a,t)=>{"use strict";var s=t(82114);function r(){}function l(){}l.resetWarningCache=r,e.exports=function(){function e(e,a,t,r,l,o){if(o!==s){var i=Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw i.name="Invariant Violation",i}}function a(){return e}e.isRequired=e;var t={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:a,element:e,elementType:e,instanceOf:a,node:e,objectOf:a,oneOf:a,oneOfType:a,shape:a,exact:a,checkPropTypes:l,resetWarningCache:r};return t.PropTypes=t,t}},44656:(e,a,t)=>{"use strict";t.d(a,{BrandingProvider:()=>p,notifyBrandingChanged:()=>c,useBranding:()=>u});var s=t(95155),r=t(12115),l=t(14051),o=t.n(l);let i={siteTitle:"",siteShortName:"",siteDescription:"",logoUrl:null,faviconUrl:null,logoMime:null,faviconMime:null,hasLogo:!1,hasFavicon:!1},d=(0,r.createContext)({...i,loading:!0,refresh:async()=>{}}),n="bluerouter:branding-updated";function c(){window.dispatchEvent(new CustomEvent(n))}function p({initialBranding:e,children:a}){let[t,l]=(0,r.useState)(e||i),[o,c]=(0,r.useState)(!e),u=(0,r.useCallback)(async()=>{try{let e=await fetch("/api/branding",{cache:"no-store"});if(!e.ok)return;let a=await e.json();l({...i,...a})}catch{}finally{c(!1)}},[]);(0,r.useEffect)(()=>{u()},[u]),(0,r.useEffect)(()=>{let e=()=>u();return window.addEventListener(n,e),()=>window.removeEventListener(n,e)},[u]);let m=(0,r.useMemo)(()=>({...t,loading:o,refresh:u}),[t,o,u]);return(0,s.jsx)(d.Provider,{value:m,children:a})}function u(){return(0,r.useContext)(d)}p.propTypes={initialBranding:o().object,children:o().node}},64561:(e,a,t)=>{"use strict";t.r(a),t.d(a,{default:()=>b});var s=t(95155),r=t(12115),l=t(44656);let o="(|(sAMAccountName={{username}})(userPrincipalName={{username}})(mail={{username}}))",i="image/svg+xml,image/png,image/webp,image/jpeg,image/gif",d=`${i},image/x-icon,image/vnd.microsoft.icon,.ico`;function n({status:e}){if(!e?.message)return null;let a="error"===e.type?"text-red-600 bg-red-50 border-red-200":"text-green-700 bg-green-50 border-green-200";return(0,s.jsx)("div",{className:`mt-3 rounded-xl border px-4 py-3 text-sm ${a}`,children:e.message})}function c({icon:e,title:a,desc:t,children:r}){return(0,s.jsxs)("section",{className:"rounded-2xl border border-border bg-surface p-6 shadow-sm",children:[(0,s.jsxs)("div",{className:"mb-5 flex items-start gap-3",children:[e&&(0,s.jsx)("span",{className:"material-symbols-outlined text-primary",children:e}),(0,s.jsxs)("div",{children:[(0,s.jsx)("h2",{className:"text-xl font-bold text-text-main",children:a}),t&&(0,s.jsx)("p",{className:"mt-1 text-sm text-text-muted",children:t})]})]}),r]})}function p({label:e,hint:a,children:t}){return(0,s.jsxs)("label",{className:"block",children:[(0,s.jsx)("span",{className:"mb-1 block text-sm font-semibold text-text-main",children:e}),t,a&&(0,s.jsx)("span",{className:"mt-1 block text-xs text-text-muted",children:a})]})}function u(e){return(0,s.jsx)("input",{...e,className:`w-full rounded-xl border border-border bg-background px-3 py-2 text-sm outline-none focus:border-primary ${e.className||""}`})}function m(e){return(0,s.jsx)("textarea",{...e,className:`w-full rounded-xl border border-border bg-background px-3 py-2 text-sm outline-none focus:border-primary ${e.className||""}`})}function x({title:e,desc:a,checked:t,onChange:r,disabled:l}){return(0,s.jsxs)("div",{className:"flex items-start justify-between gap-4 rounded-xl border border-border bg-background px-4 py-3",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("div",{className:"text-sm font-semibold text-text-main",children:e}),a&&(0,s.jsx)("div",{className:"mt-1 text-xs text-text-muted",children:a})]}),(0,s.jsx)("button",{type:"button",disabled:l,onClick:()=>r(!t),className:`relative mt-0.5 h-6 w-11 rounded-full transition disabled:opacity-50 ${t?"bg-primary":"bg-border"}`,children:(0,s.jsx)("span",{className:`absolute top-0.5 h-5 w-5 rounded-full bg-white transition ${t?"left-5":"left-0.5"}`})})]})}function b(){let[e,a]=(0,r.useState)({}),[t,b]=(0,r.useState)(!0),[h,g]=(0,r.useState)({current:"",new:"",confirm:""}),[y,f]=(0,r.useState)({type:"",message:""}),[v,j]=(0,r.useState)(!1),[w,N]=(0,r.useState)(!1),[D,C]=(0,r.useState)({type:"",message:""}),A=(0,r.useRef)(null),[U,S]=(0,r.useState)("admin"),[L,k]=(0,r.useState)({type:"",message:""}),[P,I]=(0,r.useState)({ldapEnabled:!1,ldapUrl:"",ldapBindDn:"",ldapBindPassword:"",ldapUserBaseDn:"",ldapUserSearchFilter:o,ldapUserNameAttribute:"sAMAccountName",ldapUserDisplayAttribute:"displayName",ldapUserEmailAttribute:"mail",ldapLoginAllowedGroupDn:"",ldapAdminGroupDn:"",ldapMonitorAdminGroupDn:"",ldapNestedGroups:!0,ldapAllowedUsers:[],ldapTlsRejectUnauthorized:!0,ldapConnectTimeoutMs:8e3}),[B,E]=(0,r.useState)({type:"",message:""}),[O,T]=(0,r.useState)(!1),[G,M]=(0,r.useState)(!1),[R,F]=(0,r.useState)(""),[_,$]=(0,r.useState)([]),[V,z]=(0,r.useState)(!1),[W,q]=(0,r.useState)({authMode:"password",oidcIssuerUrl:"",oidcClientId:"",oidcScopes:"openid profile email",oidcLoginLabel:"Sign in with OIDC"}),[J,H]=(0,r.useState)(""),[K,Q]=(0,r.useState)({type:"",message:""}),[Y,X]=(0,r.useState)(!1),[Z,ee]=(0,r.useState)(!1),[ea,et]=(0,r.useState)({type:"",message:""}),es=(0,l.useBranding)(),[er,el]=(0,r.useState)(""),[eo,ei]=(0,r.useState)(""),[ed,en]=(0,r.useState)(""),[ec,ep]=(0,r.useState)({type:"",message:""}),[eu,em]=(0,r.useState)(!1),[ex,eb]=(0,r.useState)(!1),[eh,eg]=(0,r.useState)(!1),[ey,ef]=(0,r.useState)(!1),ev=(0,r.useRef)(null),ej=(0,r.useRef)(null),ew=async()=>{b(!0);try{let e=await fetch("/api/settings",{cache:"no-store"}),t=await e.json();a(t),S(t.localLoginUsername||"admin"),I({ldapEnabled:!0===t.ldapEnabled,ldapUrl:t.ldapUrl||"",ldapBindDn:t.ldapBindDn||"",ldapBindPassword:"",ldapUserBaseDn:t.ldapUserBaseDn||t.ldapBaseDn||"",ldapUserSearchFilter:t.ldapUserSearchFilter||o,ldapUserNameAttribute:t.ldapUserNameAttribute||"sAMAccountName",ldapUserDisplayAttribute:t.ldapUserDisplayAttribute||"displayName",ldapUserEmailAttribute:t.ldapUserEmailAttribute||"mail",ldapLoginAllowedGroupDn:t.ldapLoginAllowedGroupDn||"",ldapAdminGroupDn:t.ldapAdminGroupDn||"",ldapMonitorAdminGroupDn:t.ldapMonitorAdminGroupDn||"",ldapNestedGroups:!1!==t.ldapNestedGroups,ldapAllowedUsers:Array.isArray(t.ldapAllowedUsers)?t.ldapAllowedUsers:[],ldapTlsRejectUnauthorized:!1!==t.ldapTlsRejectUnauthorized,ldapConnectTimeoutMs:t.ldapConnectTimeoutMs||8e3}),q({authMode:t.authMode||"password",oidcIssuerUrl:t.oidcIssuerUrl||"",oidcClientId:t.oidcClientId||"",oidcScopes:t.oidcScopes||"openid profile email",oidcLoginLabel:t.oidcLoginLabel||"Sign in with OIDC"}),el(t.siteTitle||""),ei(t.siteShortName||""),en(t.siteDescription||""),("oidc"===t.authMode||"both"===t.authMode)&&ee(!0)}catch(e){console.log("Failed to fetch settings:",e)}finally{b(!1)}};(0,r.useEffect)(()=>{ew()},[]);let eN=async e=>{let t=await fetch("/api/settings",{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)}),s=await t.json().catch(()=>({}));if(!t.ok)throw Error(s.error||"Failed to save settings");return a(e=>({...e,...s})),s},eD=async t=>{et({type:"",message:""});let s=!1!==e.sidebarAdvancedToolsVisible;a(e=>({...e,sidebarAdvancedToolsVisible:t}));try{let e=await eN({sidebarAdvancedToolsVisible:t}),s=!1!==e.sidebarAdvancedToolsVisible;a(e=>({...e,sidebarAdvancedToolsVisible:s})),window.dispatchEvent(new CustomEvent("bluerouter:sidebar-advanced-tools",{detail:{visible:s}})),et({type:"success",message:s?"Advanced tools are visible in the sidebar.":"Advanced tools are hidden from the sidebar."})}catch(e){a(e=>({...e,sidebarAdvancedToolsVisible:s})),window.dispatchEvent(new CustomEvent("bluerouter:sidebar-advanced-tools",{detail:{visible:s}})),et({type:"error",message:e.message||"Failed to save sidebar setting."})}},eC=async e=>{e.preventDefault(),k({type:"",message:""});try{let e=await eN({localLoginUsername:U});S(e.localLoginUsername||U||"admin"),k({type:"success",message:"Local account name saved."})}catch(e){k({type:"error",message:e.message})}},eA=async e=>{if(e.preventDefault(),h.new!==h.confirm)return void f({type:"error",message:"Passwords do not match"});j(!0),f({type:"",message:""});try{await eN({currentPassword:h.current,newPassword:h.new}),f({type:"success",message:"Password updated successfully"}),g({current:"",new:"",confirm:""})}catch(e){f({type:"error",message:e.message||"Failed to update password"})}finally{j(!1)}},eU=async()=>{N(!0),C({type:"",message:""});try{let e=await fetch("/api/settings/database");if(!e.ok){let a=await e.json().catch(()=>({}));throw Error(a.error||"Failed to export database")}let a=await e.json(),t=JSON.stringify(a,null,2),s=new Blob([t],{type:"application/json"}),r=URL.createObjectURL(s),l=document.createElement("a"),o=new Date().toISOString().replace(/[.:]/g,"-");l.href=r,l.download=`bluerouter-backup-${o}.json`,document.body.appendChild(l),l.click(),document.body.removeChild(l),URL.revokeObjectURL(r),C({type:"success",message:"Database backup downloaded."})}catch(e){C({type:"error",message:e.message||"Failed to export database."})}finally{N(!1)}},eS=async e=>{let a=e.target.files?.[0];if(a){N(!0),C({type:"",message:""});try{let e=await a.text(),t=JSON.parse(e),s=await fetch("/api/settings/database",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)}),r=await s.json().catch(()=>({}));if(!s.ok)throw Error(r.error||"Failed to import database");await ew(),C({type:"success",message:"Database imported successfully."})}catch(e){C({type:"error",message:e.message||"Invalid backup file."})}finally{A.current&&(A.current.value=""),N(!1)}}},eL=(e,a)=>I(t=>({...t,[e]:a})),ek=async e=>{e?.preventDefault?.(),T(!0),E({type:"",message:""});try{let e={...P,ldapBaseDn:P.ldapUserBaseDn,ldapAllowedUsers:P.ldapAllowedUsers};e.ldapBindPassword||delete e.ldapBindPassword;let a=await eN(e);I(e=>({...e,ldapBindPassword:"",ldapEnabled:!0===a.ldapEnabled,ldapUserBaseDn:a.ldapUserBaseDn||a.ldapBaseDn||e.ldapUserBaseDn,ldapLoginAllowedGroupDn:a.ldapLoginAllowedGroupDn||"",ldapAdminGroupDn:a.ldapAdminGroupDn||"",ldapMonitorAdminGroupDn:a.ldapMonitorAdminGroupDn||"",ldapNestedGroups:!1!==a.ldapNestedGroups,ldapAllowedUsers:Array.isArray(a.ldapAllowedUsers)?a.ldapAllowedUsers:e.ldapAllowedUsers})),E({type:"success",message:"LDAP settings saved."})}catch(e){E({type:"error",message:e.message||"Failed to save LDAP settings"})}finally{T(!1)}},eP=async()=>{M(!0),E({type:"",message:""});try{await ek();let e=await fetch("/api/auth/ldap/test",{method:"POST"}),a=await e.json().catch(()=>({}));e.ok&&a.ok?E({type:"success",message:a.message||"LDAP connection OK."}):E({type:"error",message:a.error||"LDAP test failed."})}catch(e){E({type:"error",message:e.message||"LDAP test failed."})}finally{M(!1)}},eI=async()=>{z(!0),E({type:"",message:""});try{await ek();let e=await fetch(`/api/auth/ldap/users?q=${encodeURIComponent(R)}`,{cache:"no-store"}),a=await e.json().catch(()=>({}));e.ok?($(a.users||[]),E({type:"success",message:`Loaded ${(a.users||[]).length} LDAP user(s).`})):E({type:"error",message:a.error||"Failed to load LDAP users."})}catch(e){E({type:"error",message:e.message||"Failed to load LDAP users."})}finally{z(!1)}},eB=e=>{let a=String(e||"").trim();a&&I(e=>{let t=new Set(e.ldapAllowedUsers||[]);return t.has(a)?t.delete(a):t.add(a),{...e,ldapAllowedUsers:[...t]}})},eE=async(a=W.authMode||"password")=>{let t=W.oidcIssuerUrl.trim(),s=W.oidcClientId.trim(),r=W.oidcScopes.trim(),l=W.oidcLoginLabel.trim(),o=J.trim();if("password"!==a&&(!t||!s||!o)&&!e.oidcConfigured)return void Q({type:"error",message:"Issuer URL, client ID, and client secret are required to enable OIDC."});X(!0),Q({type:"",message:""});try{let e={authMode:a,oidcIssuerUrl:t,oidcClientId:s,oidcScopes:r||"openid profile email",oidcLoginLabel:l||"Sign in with OIDC"};o&&(e.oidcClientSecret=o);let i=await eN(e);q({authMode:i.authMode||a,oidcIssuerUrl:i.oidcIssuerUrl||t,oidcClientId:i.oidcClientId||s,oidcScopes:i.oidcScopes||r||"openid profile email",oidcLoginLabel:i.oidcLoginLabel||l||"Sign in with OIDC"}),H(""),Q({type:"success",message:"OIDC settings saved."})}catch(e){Q({type:"error",message:e.message||"Failed to save OIDC settings"})}finally{X(!1)}},eO=async(e,a)=>{if(!a)return;if(a.size>1048576)return void ep({type:"error",message:"File exceeds 1 MB limit."});let t="logo"===e?eb:eg;t(!0),ep({type:"",message:""});try{let t=new FormData;t.append("asset",e),t.append("file",a);let s=await fetch("/api/branding/upload",{method:"POST",body:t}),r=await s.json().catch(()=>({}));if(!s.ok)throw Error(r.error||"Upload failed");(0,l.notifyBrandingChanged)(),ep({type:"success",message:`${"logo"===e?"Logo":"Favicon"} uploaded.`})}catch(e){ep({type:"error",message:e.message||"Upload failed."})}finally{t(!1)}},eT=async e=>{let a=e.target.files?.[0];await eO("logo",a),ev.current&&(ev.current.value="")},eG=async e=>{let a=e.target.files?.[0];await eO("favicon",a),ej.current&&(ej.current.value="")},eM=async e=>{e.preventDefault(),em(!0),ep({type:"",message:""});try{await eN({siteTitle:er.trim(),siteShortName:eo.trim(),siteDescription:ed.trim()}),(0,l.notifyBrandingChanged)(),ep({type:"success",message:"Branding text saved."})}catch(e){ep({type:"error",message:e.message||"Failed to save branding."})}finally{em(!1)}},eR=async e=>{ep({type:"",message:""});try{let a=await fetch(`/api/branding?asset=${e}`,{method:"DELETE"}),t=await a.json().catch(()=>({}));if(!a.ok)throw Error(t.error||"Failed to remove asset");(0,l.notifyBrandingChanged)(),ep({type:"success",message:`${"logo"===e?"Logo":"Favicon"} removed.`})}catch(e){ep({type:"error",message:e.message||"Failed to remove asset."})}},eF=async()=>{ef(!0),ep({type:"",message:""});try{let e=await fetch("/api/branding",{method:"DELETE"});if(!e.ok){let a=await e.json().catch(()=>({}));throw Error(a.error||"Failed to reset branding")}await eN({siteTitle:"",siteShortName:"",siteDescription:""}),el(""),ei(""),en(""),(0,l.notifyBrandingChanged)(),ep({type:"success",message:"Branding reset to defaults."})}catch(e){ep({type:"error",message:e.message||"Failed to reset branding."})}finally{ef(!1)}};return t?(0,s.jsx)("div",{className:"p-8 text-text-muted",children:"Loading settings..."}):(0,s.jsxs)("div",{className:"mx-auto max-w-6xl space-y-6 p-6",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("h1",{className:"text-3xl font-bold text-text-main",children:"Settings"}),(0,s.jsx)("p",{className:"mt-1 text-text-muted",children:"Configure local dashboard login, LDAP/Active Directory login, and OIDC login."})]}),(0,s.jsxs)(c,{icon:"view_sidebar",title:"Sidebar tools",desc:"Show or hide advanced dashboard tools to keep the sidebar clean.",children:[(0,s.jsx)(x,{title:"Show Advanced tools",desc:"When disabled, Media / Web, AI Traffic Gateway, CLI Tools, Proxy Pools, Skills, Console Log and Translator are hidden from the sidebar. Core admin pages remain visible.",checked:!1!==e.sidebarAdvancedToolsVisible,onChange:eD}),(0,s.jsx)(n,{status:ea})]}),(0,s.jsxs)(c,{icon:"palette",title:"Branding",desc:"Customize site title, logo and favicon shown in the dashboard, browser tab and login page. Max 1 MB per file.",children:[(0,s.jsxs)("div",{className:"grid gap-6 lg:grid-cols-2",children:[(0,s.jsxs)("div",{className:"space-y-4",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("div",{className:"mb-2 text-sm font-semibold text-text-main",children:"Logo"}),(0,s.jsxs)("div",{className:"flex items-center gap-4 rounded-xl border border-border bg-background p-4",children:[(0,s.jsx)("div",{className:"flex h-16 w-16 shrink-0 items-center justify-center overflow-hidden rounded-lg border border-border bg-surface",children:es?.logoUrl?(0,s.jsx)("img",{src:es.logoUrl,alt:"Current logo",className:"max-h-full max-w-full object-contain"}):(0,s.jsx)("span",{className:"material-symbols-outlined text-text-muted",children:"hub"})}),(0,s.jsxs)("div",{className:"flex-1 space-y-2",children:[(0,s.jsx)("div",{className:"text-xs text-text-muted",children:"Shown in the dashboard sidebar and login page. SVG, PNG, WebP, JPEG, GIF."}),(0,s.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,s.jsx)("button",{type:"button",disabled:ex,onClick:()=>ev.current?.click(),className:"rounded-xl bg-primary px-3 py-1.5 text-xs font-semibold text-white disabled:opacity-50",children:ex?"Uploading...":es?.logoUrl?"Replace logo":"Upload logo"}),es?.logoUrl?(0,s.jsx)("button",{type:"button",onClick:()=>eR("logo"),className:"rounded-xl border border-border px-3 py-1.5 text-xs font-semibold text-text-main hover:border-red-300 hover:text-red-600",children:"Remove"}):null]})]}),(0,s.jsx)("input",{ref:ev,type:"file",accept:i,className:"hidden",onChange:eT})]})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("div",{className:"mb-2 text-sm font-semibold text-text-main",children:"Favicon"}),(0,s.jsxs)("div",{className:"flex items-center gap-4 rounded-xl border border-border bg-background p-4",children:[(0,s.jsx)("div",{className:"flex h-16 w-16 shrink-0 items-center justify-center overflow-hidden rounded-lg border border-border bg-surface",children:es?.faviconUrl?(0,s.jsx)("img",{src:es.faviconUrl,alt:"Current favicon",className:"max-h-10 max-w-10 object-contain"}):(0,s.jsx)("span",{className:"material-symbols-outlined text-text-muted",children:"public"})}),(0,s.jsxs)("div",{className:"flex-1 space-y-2",children:[(0,s.jsx)("div",{className:"text-xs text-text-muted",children:"Shown in the browser tab. ICO, SVG, PNG, WebP, JPEG, GIF."}),(0,s.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,s.jsx)("button",{type:"button",disabled:eh,onClick:()=>ej.current?.click(),className:"rounded-xl bg-primary px-3 py-1.5 text-xs font-semibold text-white disabled:opacity-50",children:eh?"Uploading...":es?.faviconUrl?"Replace favicon":"Upload favicon"}),es?.faviconUrl?(0,s.jsx)("button",{type:"button",onClick:()=>eR("favicon"),className:"rounded-xl border border-border px-3 py-1.5 text-xs font-semibold text-text-main hover:border-red-300 hover:text-red-600",children:"Remove"}):null]})]}),(0,s.jsx)("input",{ref:ej,type:"file",accept:d,className:"hidden",onChange:eG})]})]})]}),(0,s.jsxs)("form",{onSubmit:eM,className:"space-y-3",children:[(0,s.jsx)(p,{label:"Site title",hint:"Shown in browser tab and login page. Leave blank for default.",children:(0,s.jsx)(u,{value:er,onChange:e=>el(e.target.value),placeholder:"AI Router Gateway"})}),(0,s.jsx)(p,{label:"Short name",hint:"Shown in dashboard sidebar. Defaults to site title or 'Blue Router'.",children:(0,s.jsx)(u,{value:eo,onChange:e=>ei(e.target.value),placeholder:"Blue Router"})}),(0,s.jsx)(p,{label:"Description",hint:"Used for browser metadata.",children:(0,s.jsx)(m,{rows:3,value:ed,onChange:e=>en(e.target.value),placeholder:"AI Infrastructure Management"})}),(0,s.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,s.jsx)("button",{type:"submit",disabled:eu,className:"rounded-xl bg-primary px-4 py-2 text-sm font-semibold text-white disabled:opacity-50",children:eu?"Saving...":"Save branding text"}),(0,s.jsx)("button",{type:"button",disabled:ey,onClick:eF,className:"rounded-xl border border-border px-4 py-2 text-sm font-semibold text-text-main hover:border-red-300 hover:text-red-600 disabled:opacity-50",children:ey?"Resetting...":"Reset to defaults"})]})]})]}),(0,s.jsx)(n,{status:ec})]}),(0,s.jsx)(c,{icon:"shield",title:"Dashboard Login",desc:"Local account remains available even when LDAP is enabled.",children:(0,s.jsxs)("div",{className:"grid gap-6 lg:grid-cols-2",children:[(0,s.jsxs)("form",{onSubmit:eC,className:"space-y-3",children:[(0,s.jsx)("h3",{className:"font-semibold text-text-main",children:"Local account"}),(0,s.jsx)(p,{label:"Local username",children:(0,s.jsx)(u,{value:U,onChange:e=>S(e.target.value)})}),(0,s.jsx)("button",{className:"rounded-xl bg-primary px-4 py-2 text-sm font-semibold text-white",children:"Save account"}),(0,s.jsx)(n,{status:L})]}),(0,s.jsxs)("form",{onSubmit:eA,className:"space-y-3",children:[(0,s.jsx)("h3",{className:"font-semibold text-text-main",children:"Local password"}),e.hasPassword&&(0,s.jsx)(p,{label:"Current password",children:(0,s.jsx)(u,{type:"password",value:h.current,onChange:e=>g({...h,current:e.target.value}),required:!0})}),(0,s.jsx)(p,{label:"New password",children:(0,s.jsx)(u,{type:"password",value:h.new,onChange:e=>g({...h,new:e.target.value}),required:!0})}),(0,s.jsx)(p,{label:"Confirm password",children:(0,s.jsx)(u,{type:"password",value:h.confirm,onChange:e=>g({...h,confirm:e.target.value}),required:!0})}),(0,s.jsx)("button",{disabled:v,className:"rounded-xl bg-primary px-4 py-2 text-sm font-semibold text-white disabled:opacity-50",children:e.hasPassword?"Update Password":"Set Password"}),(0,s.jsx)(n,{status:y})]})]})}),(0,s.jsxs)(c,{icon:"database",title:"Database Backup",desc:"Export or restore the local bluerouter configuration database.",children:[(0,s.jsxs)("div",{className:"flex flex-wrap items-center gap-3",children:[(0,s.jsx)("button",{onClick:eU,disabled:w,className:"rounded-xl bg-primary px-4 py-2 text-sm font-semibold text-white disabled:opacity-50",children:"Download Backup"}),(0,s.jsx)("button",{onClick:()=>A.current?.click(),disabled:w,className:"rounded-xl border border-border px-4 py-2 text-sm font-semibold text-text-main hover:border-primary/50 disabled:opacity-50",children:"Import Backup"}),(0,s.jsx)("input",{ref:A,type:"file",accept:"application/json",className:"hidden",onChange:eS})]}),(0,s.jsx)(n,{status:D})]}),(0,s.jsx)(c,{icon:"corporate_fare",title:"LDAP / Active Directory Login",desc:"Search users from a User Base DN, restrict login by group DN, and grant admin by group DN. The old Selected LDAP users list is kept as a manual admin list.",children:(0,s.jsxs)("form",{onSubmit:ek,className:"space-y-5",children:[(0,s.jsx)("div",{className:"flex flex-wrap gap-3",children:(0,s.jsx)("button",{type:"button",onClick:()=>eL("ldapEnabled",!P.ldapEnabled),className:`rounded-xl px-3 py-2 text-sm font-semibold ${P.ldapEnabled?"bg-primary text-white":"border border-border text-text-muted"}`,children:P.ldapEnabled?"Enabled":"Disabled"})}),(0,s.jsxs)("div",{className:"grid gap-4 lg:grid-cols-2",children:[(0,s.jsx)(p,{label:"LDAP URL",children:(0,s.jsx)(u,{value:P.ldapUrl,onChange:e=>eL("ldapUrl",e.target.value),placeholder:"ldap://dc01.company.local:389"})}),(0,s.jsx)(p,{label:"LDAP User Base DN",hint:"OU/container/domain where user objects are searched. Do not use a group DN here.",children:(0,s.jsx)(u,{value:P.ldapUserBaseDn,onChange:e=>eL("ldapUserBaseDn",e.target.value),placeholder:"OU=Users,OU=xxx,DC=xx,DC=vn"})}),(0,s.jsx)(p,{label:"LDAP Bind DN",children:(0,s.jsx)(u,{value:P.ldapBindDn,onChange:e=>eL("ldapBindDn",e.target.value),placeholder:"CN=svc-bluerouter,OU=Service Accounts,DC=company,DC=local"})}),(0,s.jsx)(p,{label:"LDAP Bind Password",children:(0,s.jsx)(u,{type:"password",value:P.ldapBindPassword,onChange:e=>eL("ldapBindPassword",e.target.value),placeholder:e.ldapHasBindPassword?"Saved — leave blank to keep":"Service account password"})}),(0,s.jsx)(p,{label:"LDAP Login Allowed Group DN",hint:"Only members of this group can log in. Leave blank to allow any valid LDAP user.",children:(0,s.jsx)(u,{value:P.ldapLoginAllowedGroupDn,onChange:e=>eL("ldapLoginAllowedGroupDn",e.target.value),placeholder:"CN=Apikeys_Groups,OU=AppGroups,OU=xxx,DC=xx,DC=vn"})}),(0,s.jsx)(p,{label:"LDAP Admin Group DN",hint:"Members of this group get full admin dashboard access.",children:(0,s.jsx)(u,{value:P.ldapAdminGroupDn,onChange:e=>eL("ldapAdminGroupDn",e.target.value),placeholder:"CN=BlueRouter_Admins,OU=AppGroups,OU=xxx,DC=xx,DC=vn"})}),(0,s.jsx)(p,{label:"LDAP Monitor Admin Group DN",hint:"Members can use only Endpoint, API Keys, Usage, Analytics, Quota Tracker and Prompt Logs with admin-like permissions inside those tabs.",children:(0,s.jsx)(u,{value:P.ldapMonitorAdminGroupDn,onChange:e=>eL("ldapMonitorAdminGroupDn",e.target.value),placeholder:"CN=BlueRouter_Monitor_Admins,OU=AppGroups,OU=xxx,DC=xx,DC=vn"})})]}),(0,s.jsxs)("div",{className:"grid gap-4 lg:grid-cols-2",children:[(0,s.jsx)(p,{label:"User search filter",hint:"Use {{username}} placeholder.",children:(0,s.jsx)(u,{value:P.ldapUserSearchFilter,onChange:e=>eL("ldapUserSearchFilter",e.target.value)})}),(0,s.jsx)(p,{label:"Login group mode",hint:"Nested groups uses AD matching rule 1.2.840.113556.1.4.1941.",children:(0,s.jsx)(x,{title:"Nested group membership",desc:"Recommended for Active Directory nested groups.",checked:P.ldapNestedGroups,onChange:e=>eL("ldapNestedGroups",e)})}),(0,s.jsx)(p,{label:"Username attribute",children:(0,s.jsx)(u,{value:P.ldapUserNameAttribute,onChange:e=>eL("ldapUserNameAttribute",e.target.value)})}),(0,s.jsx)(p,{label:"Display attribute",children:(0,s.jsx)(u,{value:P.ldapUserDisplayAttribute,onChange:e=>eL("ldapUserDisplayAttribute",e.target.value)})}),(0,s.jsx)(p,{label:"Email attribute",children:(0,s.jsx)(u,{value:P.ldapUserEmailAttribute,onChange:e=>eL("ldapUserEmailAttribute",e.target.value)})}),(0,s.jsx)(p,{label:"Connect timeout ms",children:(0,s.jsx)(u,{type:"number",value:P.ldapConnectTimeoutMs,onChange:e=>eL("ldapConnectTimeoutMs",e.target.value)})})]}),(0,s.jsx)(x,{title:"Reject invalid TLS certificates",desc:"Disable only for test/self-signed LDAP TLS.",checked:P.ldapTlsRejectUnauthorized,onChange:e=>eL("ldapTlsRejectUnauthorized",e)}),(0,s.jsxs)("div",{className:"rounded-2xl border border-border bg-background p-4",children:[(0,s.jsxs)("div",{className:"mb-3",children:[(0,s.jsx)("h3",{className:"font-semibold text-text-main",children:"Manual admin users / LDAP owner list"}),(0,s.jsx)("p",{className:"mt-1 text-xs text-text-muted",children:"Users loaded here come from Login Allowed Group DN when set. Selected users are also treated as manual admins for backward compatibility."})]}),(0,s.jsxs)("div",{className:"mb-3 flex gap-2",children:[(0,s.jsx)(u,{value:R,onChange:e=>F(e.target.value),placeholder:"Search users..."}),(0,s.jsx)("button",{type:"button",onClick:eI,disabled:V,className:"rounded-xl border border-border px-4 py-2 text-sm font-semibold text-text-main disabled:opacity-50",children:V?"Loading...":"Load users"})]}),_.length>0&&(0,s.jsx)("div",{className:"max-h-72 overflow-auto rounded-xl border border-border",children:_.map(e=>{let a=P.ldapAllowedUsers.includes(e.username);return(0,s.jsxs)("button",{type:"button",onClick:()=>eB(e.username),className:`flex w-full items-center justify-between gap-3 border-b border-border px-3 py-2 text-left text-sm last:border-b-0 ${a?"bg-primary/10":"bg-background hover:bg-surface"}`,children:[(0,s.jsxs)("span",{children:[(0,s.jsx)("span",{className:"font-semibold text-text-main",children:e.displayName||e.username}),(0,s.jsxs)("span",{className:"ml-2 text-text-muted",children:[e.username,e.email?` \xb7 ${e.email}`:""]})]}),(0,s.jsx)("span",{className:"material-symbols-outlined text-primary",children:a?"check_circle":"radio_button_unchecked"})]},e.dn||e.username)})}),(0,s.jsxs)("div",{className:"mt-3",children:[(0,s.jsxs)("div",{className:"mb-2 text-sm font-semibold text-text-main",children:["Selected manual admin users (",P.ldapAllowedUsers.length,")"]}),0===P.ldapAllowedUsers.length?(0,s.jsx)("div",{className:"text-sm text-text-muted",children:"No users selected."}):(0,s.jsx)("div",{className:"flex flex-wrap gap-2",children:P.ldapAllowedUsers.map(e=>(0,s.jsxs)("button",{type:"button",onClick:()=>eB(e),className:"rounded-full border border-primary/30 bg-primary/10 px-3 py-1 text-xs text-primary",children:[e," \xd7"]},e))})]})]}),(0,s.jsxs)("div",{className:"flex flex-wrap gap-3",children:[(0,s.jsx)("button",{type:"button",onClick:eP,disabled:G,className:"rounded-xl border border-border px-4 py-2 text-sm font-semibold text-text-main disabled:opacity-50",children:G?"Testing...":"Save & test LDAP"}),(0,s.jsx)("button",{type:"submit",disabled:O,className:"rounded-xl bg-primary px-4 py-2 text-sm font-semibold text-white disabled:opacity-50",children:O?"Saving...":"Save LDAP settings"})]}),(0,s.jsx)(n,{status:B})]})}),(0,s.jsxs)(c,{icon:"lock_open",title:"OIDC Dashboard Login",desc:"oidc"===e.authMode?"OIDC active":"both"===e.authMode?"Password + OIDC active":"Optional SSO via Authentik/Keycloak/Google",children:[(0,s.jsx)("button",{type:"button",onClick:()=>ee(e=>!e),className:"mb-4 rounded-xl border border-border px-4 py-2 text-sm font-semibold text-text-main",children:Z?"Hide OIDC settings":"Show OIDC settings"}),Z&&(0,s.jsxs)("div",{className:"space-y-4",children:[(0,s.jsx)("div",{className:"grid gap-3 md:grid-cols-3",children:[{value:"password",title:"Password/LDAP",desc:"Keep local and LDAP login."},{value:"oidc",title:"OIDC only",desc:"Disable local/LDAP login when configured."},{value:"both",title:"Both",desc:"Allow either OIDC or local/LDAP."}].map(e=>{let a=W.authMode===e.value;return(0,s.jsxs)("button",{type:"button",onClick:()=>q(a=>({...a,authMode:e.value})),className:`rounded-xl border p-3 text-left ${a?"border-primary bg-primary/10":"border-border bg-background hover:border-primary/40"}`,children:[(0,s.jsx)("div",{className:"font-semibold text-text-main",children:e.title}),(0,s.jsx)("div",{className:"mt-1 text-xs text-text-muted",children:e.desc})]},e.value)})}),(0,s.jsxs)("div",{className:"grid gap-4 lg:grid-cols-2",children:[(0,s.jsx)(p,{label:"Issuer URL",children:(0,s.jsx)(u,{value:W.oidcIssuerUrl,onChange:e=>q({...W,oidcIssuerUrl:e.target.value})})}),(0,s.jsx)(p,{label:"Client ID",children:(0,s.jsx)(u,{value:W.oidcClientId,onChange:e=>q({...W,oidcClientId:e.target.value})})}),(0,s.jsx)(p,{label:"Client Secret",children:(0,s.jsx)(u,{type:"password",value:J,onChange:e=>H(e.target.value),placeholder:e.oidcConfigured?"Saved — leave blank to keep":"Client secret"})}),(0,s.jsx)(p,{label:"Scopes",children:(0,s.jsx)(u,{value:W.oidcScopes,onChange:e=>q({...W,oidcScopes:e.target.value})})}),(0,s.jsx)(p,{label:"Login label",children:(0,s.jsx)(u,{value:W.oidcLoginLabel,onChange:e=>q({...W,oidcLoginLabel:e.target.value})})})]}),(0,s.jsx)("button",{type:"button",onClick:()=>eE(),disabled:Y,className:"rounded-xl bg-primary px-4 py-2 text-sm font-semibold text-white disabled:opacity-50",children:Y?"Saving...":"Save OIDC settings"}),(0,s.jsx)(n,{status:K})]})]})]})}},82114:e=>{"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"}},e=>{e.O(0,[8441,3794,7358],()=>e(e.s=7973)),_N_E=e.O()}]);
|
|
1
|
+
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[3471],{7973:(e,a,t)=>{Promise.resolve().then(t.bind(t,64561))},14051:(e,a,t)=>{e.exports=t(34701)()},34701:(e,a,t)=>{"use strict";var s=t(82114);function r(){}function l(){}l.resetWarningCache=r,e.exports=function(){function e(e,a,t,r,l,o){if(o!==s){var i=Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw i.name="Invariant Violation",i}}function a(){return e}e.isRequired=e;var t={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:a,element:e,elementType:e,instanceOf:a,node:e,objectOf:a,oneOf:a,oneOfType:a,shape:a,exact:a,checkPropTypes:l,resetWarningCache:r};return t.PropTypes=t,t}},44656:(e,a,t)=>{"use strict";t.d(a,{BrandingProvider:()=>p,notifyBrandingChanged:()=>c,useBranding:()=>u});var s=t(95155),r=t(12115),l=t(14051),o=t.n(l);let i={siteTitle:"",siteShortName:"",siteDescription:"",logoUrl:null,faviconUrl:null,logoMime:null,faviconMime:null,hasLogo:!1,hasFavicon:!1},d=(0,r.createContext)({...i,loading:!0,refresh:async()=>{}}),n="bluerouter:branding-updated";function c(){window.dispatchEvent(new CustomEvent(n))}function p({initialBranding:e,children:a}){let[t,l]=(0,r.useState)(e||i),[o,c]=(0,r.useState)(!e),u=(0,r.useCallback)(async()=>{try{let e=await fetch("/api/branding",{cache:"no-store"});if(!e.ok)return;let a=await e.json();l({...i,...a})}catch{}finally{c(!1)}},[]);(0,r.useEffect)(()=>{u()},[u]),(0,r.useEffect)(()=>{let e=()=>u();return window.addEventListener(n,e),()=>window.removeEventListener(n,e)},[u]);let m=(0,r.useMemo)(()=>({...t,loading:o,refresh:u}),[t,o,u]);return(0,s.jsx)(d.Provider,{value:m,children:a})}function u(){return(0,r.useContext)(d)}p.propTypes={initialBranding:o().object,children:o().node}},64561:(e,a,t)=>{"use strict";t.r(a),t.d(a,{default:()=>b});var s=t(95155),r=t(12115),l=t(44656);let o="(|(sAMAccountName={{username}})(userPrincipalName={{username}})(mail={{username}}))",i="image/svg+xml,image/png,image/webp,image/jpeg,image/gif",d=`${i},image/x-icon,image/vnd.microsoft.icon,.ico`;function n({status:e}){if(!e?.message)return null;let a="error"===e.type?"text-red-600 bg-red-50 border-red-200":"text-green-700 bg-green-50 border-green-200";return(0,s.jsx)("div",{className:`mt-3 rounded-xl border px-4 py-3 text-sm ${a}`,children:e.message})}function c({icon:e,title:a,desc:t,children:r}){return(0,s.jsxs)("section",{className:"rounded-2xl border border-border bg-surface p-6 shadow-sm",children:[(0,s.jsxs)("div",{className:"mb-5 flex items-start gap-3",children:[e&&(0,s.jsx)("span",{className:"material-symbols-outlined text-primary",children:e}),(0,s.jsxs)("div",{children:[(0,s.jsx)("h2",{className:"text-xl font-bold text-text-main",children:a}),t&&(0,s.jsx)("p",{className:"mt-1 text-sm text-text-muted",children:t})]})]}),r]})}function p({label:e,hint:a,children:t}){return(0,s.jsxs)("label",{className:"block",children:[(0,s.jsx)("span",{className:"mb-1 block text-sm font-semibold text-text-main",children:e}),t,a&&(0,s.jsx)("span",{className:"mt-1 block text-xs text-text-muted",children:a})]})}function u(e){return(0,s.jsx)("input",{...e,className:`w-full rounded-xl border border-border bg-background px-3 py-2 text-sm outline-none focus:border-primary ${e.className||""}`})}function m(e){return(0,s.jsx)("textarea",{...e,className:`w-full rounded-xl border border-border bg-background px-3 py-2 text-sm outline-none focus:border-primary ${e.className||""}`})}function x({title:e,desc:a,checked:t,onChange:r,disabled:l}){return(0,s.jsxs)("div",{className:"flex items-start justify-between gap-4 rounded-xl border border-border bg-background px-4 py-3",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("div",{className:"text-sm font-semibold text-text-main",children:e}),a&&(0,s.jsx)("div",{className:"mt-1 text-xs text-text-muted",children:a})]}),(0,s.jsx)("button",{type:"button",disabled:l,onClick:()=>r(!t),className:`relative mt-0.5 h-6 w-11 rounded-full transition disabled:opacity-50 ${t?"bg-primary":"bg-border"}`,children:(0,s.jsx)("span",{className:`absolute top-0.5 h-5 w-5 rounded-full bg-white transition ${t?"left-5":"left-0.5"}`})})]})}function b(){let[e,a]=(0,r.useState)({}),[t,b]=(0,r.useState)(!0),[h,g]=(0,r.useState)({current:"",new:"",confirm:""}),[y,f]=(0,r.useState)({type:"",message:""}),[v,j]=(0,r.useState)(!1),[w,N]=(0,r.useState)(!1),[D,C]=(0,r.useState)({type:"",message:""}),A=(0,r.useRef)(null),[U,S]=(0,r.useState)("admin"),[L,k]=(0,r.useState)({type:"",message:""}),[P,I]=(0,r.useState)({ldapEnabled:!1,ldapUrl:"",ldapBindDn:"",ldapBindPassword:"",ldapUserBaseDn:"",ldapUserSearchFilter:o,ldapUserNameAttribute:"sAMAccountName",ldapUserDisplayAttribute:"displayName",ldapUserEmailAttribute:"mail",ldapLoginAllowedGroupDn:"",ldapAdminGroupDn:"",ldapMonitorAdminGroupDn:"",ldapNestedGroups:!0,ldapAllowedUsers:[],ldapTlsRejectUnauthorized:!0,ldapConnectTimeoutMs:8e3}),[E,O]=(0,r.useState)({type:"",message:""}),[B,T]=(0,r.useState)(!1),[G,M]=(0,r.useState)(!1),[F,R]=(0,r.useState)(""),[_,$]=(0,r.useState)([]),[V,z]=(0,r.useState)(!1),[W,q]=(0,r.useState)({authMode:"password",oidcIssuerUrl:"",oidcClientId:"",oidcScopes:"openid profile email",oidcLoginLabel:"Sign in with OIDC"}),[J,H]=(0,r.useState)(""),[K,Q]=(0,r.useState)({type:"",message:""}),[Y,X]=(0,r.useState)(!1),[Z,ee]=(0,r.useState)(!1),[ea,et]=(0,r.useState)({type:"",message:""}),es=(0,l.useBranding)(),[er,el]=(0,r.useState)(""),[eo,ei]=(0,r.useState)(""),[ed,en]=(0,r.useState)(""),[ec,ep]=(0,r.useState)({type:"",message:""}),[eu,em]=(0,r.useState)(!1),[ex,eb]=(0,r.useState)(!1),[eh,eg]=(0,r.useState)(!1),[ey,ef]=(0,r.useState)(!1),ev=(0,r.useRef)(null),ej=(0,r.useRef)(null),ew=async()=>{b(!0);try{let e=await fetch("/api/settings",{cache:"no-store"}),t=await e.json();a(t),S(t.localLoginUsername||"admin"),I({ldapEnabled:!0===t.ldapEnabled,ldapUrl:t.ldapUrl||"",ldapBindDn:t.ldapBindDn||"",ldapBindPassword:"",ldapUserBaseDn:t.ldapUserBaseDn||t.ldapBaseDn||"",ldapUserSearchFilter:t.ldapUserSearchFilter||o,ldapUserNameAttribute:t.ldapUserNameAttribute||"sAMAccountName",ldapUserDisplayAttribute:t.ldapUserDisplayAttribute||"displayName",ldapUserEmailAttribute:t.ldapUserEmailAttribute||"mail",ldapLoginAllowedGroupDn:t.ldapLoginAllowedGroupDn||"",ldapAdminGroupDn:t.ldapAdminGroupDn||"",ldapMonitorAdminGroupDn:t.ldapMonitorAdminGroupDn||"",ldapNestedGroups:!1!==t.ldapNestedGroups,ldapAllowedUsers:Array.isArray(t.ldapAllowedUsers)?t.ldapAllowedUsers:[],ldapTlsRejectUnauthorized:!1!==t.ldapTlsRejectUnauthorized,ldapConnectTimeoutMs:t.ldapConnectTimeoutMs||8e3}),q({authMode:t.authMode||"password",oidcIssuerUrl:t.oidcIssuerUrl||"",oidcClientId:t.oidcClientId||"",oidcScopes:t.oidcScopes||"openid profile email",oidcLoginLabel:t.oidcLoginLabel||"Sign in with OIDC"}),el(t.siteTitle||""),ei(t.siteShortName||""),en(t.siteDescription||""),("oidc"===t.authMode||"both"===t.authMode)&&ee(!0)}catch(e){console.log("Failed to fetch settings:",e)}finally{b(!1)}};(0,r.useEffect)(()=>{ew()},[]);let eN=async e=>{let t=await fetch("/api/settings",{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)}),s=await t.json().catch(()=>({}));if(!t.ok)throw Error(s.error||"Failed to save settings");return a(e=>({...e,...s})),s},eD=async t=>{et({type:"",message:""});let s=!1!==e.sidebarAdvancedToolsVisible;a(e=>({...e,sidebarAdvancedToolsVisible:t}));try{let e=await eN({sidebarAdvancedToolsVisible:t}),s=!1!==e.sidebarAdvancedToolsVisible;a(e=>({...e,sidebarAdvancedToolsVisible:s})),window.dispatchEvent(new CustomEvent("bluerouter:sidebar-advanced-tools",{detail:{visible:s}})),et({type:"success",message:s?"Advanced tools are visible in the sidebar.":"Advanced tools are hidden from the sidebar."})}catch(e){a(e=>({...e,sidebarAdvancedToolsVisible:s})),window.dispatchEvent(new CustomEvent("bluerouter:sidebar-advanced-tools",{detail:{visible:s}})),et({type:"error",message:e.message||"Failed to save sidebar setting."})}},eC=async e=>{e.preventDefault(),k({type:"",message:""});try{let e=await eN({localLoginUsername:U});S(e.localLoginUsername||U||"admin"),k({type:"success",message:"Local account name saved."})}catch(e){k({type:"error",message:e.message})}},eA=async e=>{if(e.preventDefault(),h.new!==h.confirm)return void f({type:"error",message:"Passwords do not match"});j(!0),f({type:"",message:""});try{await eN({currentPassword:h.current,newPassword:h.new}),f({type:"success",message:"Password updated successfully"}),g({current:"",new:"",confirm:""})}catch(e){f({type:"error",message:e.message||"Failed to update password"})}finally{j(!1)}},eU=async()=>{N(!0),C({type:"",message:""});try{let e=await fetch("/api/settings/database");if(!e.ok){let a=await e.json().catch(()=>({}));throw Error(a.error||"Failed to export database")}let a=await e.json(),t=JSON.stringify(a,null,2),s=new Blob([t],{type:"application/json"}),r=URL.createObjectURL(s),l=document.createElement("a"),o=new Date().toISOString().replace(/[.:]/g,"-");l.href=r,l.download=`bluerouter-backup-${o}.json`,document.body.appendChild(l),l.click(),document.body.removeChild(l),URL.revokeObjectURL(r),C({type:"success",message:"Database backup downloaded."})}catch(e){C({type:"error",message:e.message||"Failed to export database."})}finally{N(!1)}},eS=async e=>{let a=e.target.files?.[0];if(a){N(!0),C({type:"",message:""});try{let e=await a.text(),t=JSON.parse(e),s=await fetch("/api/settings/database",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)}),r=await s.json().catch(()=>({}));if(!s.ok)throw Error(r.error||"Failed to import database");await ew(),C({type:"success",message:"Database imported successfully."})}catch(e){C({type:"error",message:e.message||"Invalid backup file."})}finally{A.current&&(A.current.value=""),N(!1)}}},eL=(e,a)=>I(t=>({...t,[e]:a})),ek=async e=>{e?.preventDefault?.(),T(!0),O({type:"",message:""});try{let e={...P,ldapBaseDn:P.ldapUserBaseDn,ldapAllowedUsers:P.ldapAllowedUsers};e.ldapBindPassword||delete e.ldapBindPassword;let a=await eN(e);I(e=>({...e,ldapBindPassword:"",ldapEnabled:!0===a.ldapEnabled,ldapUserBaseDn:a.ldapUserBaseDn||a.ldapBaseDn||e.ldapUserBaseDn,ldapLoginAllowedGroupDn:a.ldapLoginAllowedGroupDn||"",ldapAdminGroupDn:a.ldapAdminGroupDn||"",ldapMonitorAdminGroupDn:a.ldapMonitorAdminGroupDn||"",ldapNestedGroups:!1!==a.ldapNestedGroups,ldapAllowedUsers:Array.isArray(a.ldapAllowedUsers)?a.ldapAllowedUsers:e.ldapAllowedUsers})),O({type:"success",message:"LDAP settings saved."})}catch(e){O({type:"error",message:e.message||"Failed to save LDAP settings"})}finally{T(!1)}},eP=async()=>{M(!0),O({type:"",message:""});try{await ek();let e=await fetch("/api/auth/ldap/test",{method:"POST"}),a=await e.json().catch(()=>({}));e.ok&&a.ok?O({type:"success",message:a.message||"LDAP connection OK."}):O({type:"error",message:a.error||"LDAP test failed."})}catch(e){O({type:"error",message:e.message||"LDAP test failed."})}finally{M(!1)}},eI=async()=>{z(!0),O({type:"",message:""});try{await ek();let e=await fetch(`/api/auth/ldap/users?q=${encodeURIComponent(F)}`,{cache:"no-store"}),a=await e.json().catch(()=>({}));e.ok?($(a.users||[]),O({type:"success",message:`Loaded ${(a.users||[]).length} LDAP user(s).`})):O({type:"error",message:a.error||"Failed to load LDAP users."})}catch(e){O({type:"error",message:e.message||"Failed to load LDAP users."})}finally{z(!1)}},eE=e=>{let a=String(e||"").trim();a&&I(e=>{let t=new Set(e.ldapAllowedUsers||[]);return t.has(a)?t.delete(a):t.add(a),{...e,ldapAllowedUsers:[...t]}})},eO=async(a=W.authMode||"password")=>{let t=W.oidcIssuerUrl.trim(),s=W.oidcClientId.trim(),r=W.oidcScopes.trim(),l=W.oidcLoginLabel.trim(),o=J.trim();if("password"!==a&&(!t||!s||!o)&&!e.oidcConfigured)return void Q({type:"error",message:"Issuer URL, client ID, and client secret are required to enable OIDC."});X(!0),Q({type:"",message:""});try{let e={authMode:a,oidcIssuerUrl:t,oidcClientId:s,oidcScopes:r||"openid profile email",oidcLoginLabel:l||"Sign in with OIDC"};o&&(e.oidcClientSecret=o);let i=await eN(e);q({authMode:i.authMode||a,oidcIssuerUrl:i.oidcIssuerUrl||t,oidcClientId:i.oidcClientId||s,oidcScopes:i.oidcScopes||r||"openid profile email",oidcLoginLabel:i.oidcLoginLabel||l||"Sign in with OIDC"}),H(""),Q({type:"success",message:"OIDC settings saved."})}catch(e){Q({type:"error",message:e.message||"Failed to save OIDC settings"})}finally{X(!1)}},eB=async(e,a)=>{if(!a)return;if(a.size>1048576)return void ep({type:"error",message:"File exceeds 1 MB limit."});let t="logo"===e?eb:eg;t(!0),ep({type:"",message:""});try{let t=new FormData;t.append("asset",e),t.append("file",a);let s=await fetch("/api/branding/upload",{method:"POST",body:t}),r=await s.json().catch(()=>({}));if(!s.ok)throw Error(r.error||"Upload failed");(0,l.notifyBrandingChanged)(),ep({type:"success",message:`${"logo"===e?"Logo":"Favicon"} uploaded.`})}catch(e){ep({type:"error",message:e.message||"Upload failed."})}finally{t(!1)}},eT=async e=>{let a=e.target.files?.[0];await eB("logo",a),ev.current&&(ev.current.value="")},eG=async e=>{let a=e.target.files?.[0];await eB("favicon",a),ej.current&&(ej.current.value="")},eM=async e=>{e.preventDefault(),em(!0),ep({type:"",message:""});try{await eN({siteTitle:er.trim(),siteShortName:eo.trim(),siteDescription:ed.trim()}),(0,l.notifyBrandingChanged)(),ep({type:"success",message:"Branding text saved."})}catch(e){ep({type:"error",message:e.message||"Failed to save branding."})}finally{em(!1)}},eF=async e=>{ep({type:"",message:""});try{let a=await fetch(`/api/branding?asset=${e}`,{method:"DELETE"}),t=await a.json().catch(()=>({}));if(!a.ok)throw Error(t.error||"Failed to remove asset");(0,l.notifyBrandingChanged)(),ep({type:"success",message:`${"logo"===e?"Logo":"Favicon"} removed.`})}catch(e){ep({type:"error",message:e.message||"Failed to remove asset."})}},eR=async()=>{ef(!0),ep({type:"",message:""});try{let e=await fetch("/api/branding",{method:"DELETE"});if(!e.ok){let a=await e.json().catch(()=>({}));throw Error(a.error||"Failed to reset branding")}await eN({siteTitle:"",siteShortName:"",siteDescription:""}),el(""),ei(""),en(""),(0,l.notifyBrandingChanged)(),ep({type:"success",message:"Branding reset to defaults."})}catch(e){ep({type:"error",message:e.message||"Failed to reset branding."})}finally{ef(!1)}};return t?(0,s.jsx)("div",{className:"p-8 text-text-muted",children:"Loading settings..."}):(0,s.jsxs)("div",{className:"mx-auto max-w-6xl space-y-6 p-6",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("h1",{className:"text-3xl font-bold text-text-main",children:"Settings"}),(0,s.jsx)("p",{className:"mt-1 text-text-muted",children:"Configure local dashboard login, LDAP/Active Directory login, and OIDC login."})]}),(0,s.jsxs)(c,{icon:"view_sidebar",title:"Sidebar tools",desc:"Show or hide advanced dashboard tools to keep the sidebar clean.",children:[(0,s.jsx)(x,{title:"Show Advanced tools",desc:"When disabled, Media / Web, AI Traffic Gateway, CLI Tools, Proxy Pools, Skills, Console Log and Translator are hidden from the sidebar. Core admin pages remain visible.",checked:!1!==e.sidebarAdvancedToolsVisible,onChange:eD}),(0,s.jsx)(n,{status:ea})]}),(0,s.jsxs)(c,{icon:"palette",title:"Branding",desc:"Customize site title, logo and favicon shown in the dashboard, browser tab and login page. Max 1 MB per file.",children:[(0,s.jsxs)("div",{className:"grid gap-6 lg:grid-cols-2",children:[(0,s.jsxs)("div",{className:"space-y-4",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("div",{className:"mb-2 text-sm font-semibold text-text-main",children:"Logo"}),(0,s.jsxs)("div",{className:"flex items-center gap-4 rounded-xl border border-border bg-background p-4",children:[(0,s.jsx)("div",{className:"flex h-16 w-16 shrink-0 items-center justify-center overflow-hidden rounded-lg border border-border bg-surface",children:es?.logoUrl?(0,s.jsx)("img",{src:es.logoUrl,alt:"Current logo",className:"max-h-full max-w-full object-contain"}):(0,s.jsx)("span",{className:"material-symbols-outlined text-text-muted",children:"hub"})}),(0,s.jsxs)("div",{className:"flex-1 space-y-2",children:[(0,s.jsx)("div",{className:"text-xs text-text-muted",children:"Shown in the dashboard sidebar and login page. SVG, PNG, WebP, JPEG, GIF."}),(0,s.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,s.jsx)("button",{type:"button",disabled:ex,onClick:()=>ev.current?.click(),className:"rounded-xl bg-primary px-3 py-1.5 text-xs font-semibold text-white disabled:opacity-50",children:ex?"Uploading...":es?.logoUrl?"Replace logo":"Upload logo"}),es?.logoUrl?(0,s.jsx)("button",{type:"button",onClick:()=>eF("logo"),className:"rounded-xl border border-border px-3 py-1.5 text-xs font-semibold text-text-main hover:border-red-300 hover:text-red-600",children:"Remove"}):null]})]}),(0,s.jsx)("input",{ref:ev,type:"file",accept:i,className:"hidden",onChange:eT})]})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("div",{className:"mb-2 text-sm font-semibold text-text-main",children:"Favicon"}),(0,s.jsxs)("div",{className:"flex items-center gap-4 rounded-xl border border-border bg-background p-4",children:[(0,s.jsx)("div",{className:"flex h-16 w-16 shrink-0 items-center justify-center overflow-hidden rounded-lg border border-border bg-surface",children:es?.faviconUrl?(0,s.jsx)("img",{src:es.faviconUrl,alt:"Current favicon",className:"max-h-10 max-w-10 object-contain"}):(0,s.jsx)("span",{className:"material-symbols-outlined text-text-muted",children:"public"})}),(0,s.jsxs)("div",{className:"flex-1 space-y-2",children:[(0,s.jsx)("div",{className:"text-xs text-text-muted",children:"Shown in the browser tab. ICO, SVG, PNG, WebP, JPEG, GIF."}),(0,s.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,s.jsx)("button",{type:"button",disabled:eh,onClick:()=>ej.current?.click(),className:"rounded-xl bg-primary px-3 py-1.5 text-xs font-semibold text-white disabled:opacity-50",children:eh?"Uploading...":es?.faviconUrl?"Replace favicon":"Upload favicon"}),es?.faviconUrl?(0,s.jsx)("button",{type:"button",onClick:()=>eF("favicon"),className:"rounded-xl border border-border px-3 py-1.5 text-xs font-semibold text-text-main hover:border-red-300 hover:text-red-600",children:"Remove"}):null]})]}),(0,s.jsx)("input",{ref:ej,type:"file",accept:d,className:"hidden",onChange:eG})]})]})]}),(0,s.jsxs)("form",{onSubmit:eM,className:"space-y-3",children:[(0,s.jsx)(p,{label:"Site title",hint:"Shown in browser tab and login page. Leave blank for default.",children:(0,s.jsx)(u,{value:er,onChange:e=>el(e.target.value),placeholder:"AI Router Gateway"})}),(0,s.jsx)(p,{label:"Company short name",hint:"Shown in dashboard sidebar and login hero text. Defaults to site title/sidebar default or 'Fujinet' on login.",children:(0,s.jsx)(u,{value:eo,onChange:e=>ei(e.target.value),placeholder:"Fujinet"})}),(0,s.jsx)(p,{label:"Description",hint:"Used for browser metadata.",children:(0,s.jsx)(m,{rows:3,value:ed,onChange:e=>en(e.target.value),placeholder:"AI Infrastructure Management"})}),(0,s.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,s.jsx)("button",{type:"submit",disabled:eu,className:"rounded-xl bg-primary px-4 py-2 text-sm font-semibold text-white disabled:opacity-50",children:eu?"Saving...":"Save branding text"}),(0,s.jsx)("button",{type:"button",disabled:ey,onClick:eR,className:"rounded-xl border border-border px-4 py-2 text-sm font-semibold text-text-main hover:border-red-300 hover:text-red-600 disabled:opacity-50",children:ey?"Resetting...":"Reset to defaults"})]})]})]}),(0,s.jsx)(n,{status:ec})]}),(0,s.jsx)(c,{icon:"shield",title:"Dashboard Login",desc:"Local account remains available even when LDAP is enabled.",children:(0,s.jsxs)("div",{className:"grid gap-6 lg:grid-cols-2",children:[(0,s.jsxs)("form",{onSubmit:eC,className:"space-y-3",children:[(0,s.jsx)("h3",{className:"font-semibold text-text-main",children:"Local account"}),(0,s.jsx)(p,{label:"Local username",children:(0,s.jsx)(u,{value:U,onChange:e=>S(e.target.value)})}),(0,s.jsx)("button",{className:"rounded-xl bg-primary px-4 py-2 text-sm font-semibold text-white",children:"Save account"}),(0,s.jsx)(n,{status:L})]}),(0,s.jsxs)("form",{onSubmit:eA,className:"space-y-3",children:[(0,s.jsx)("h3",{className:"font-semibold text-text-main",children:"Local password"}),e.hasPassword&&(0,s.jsx)(p,{label:"Current password",children:(0,s.jsx)(u,{type:"password",value:h.current,onChange:e=>g({...h,current:e.target.value}),required:!0})}),(0,s.jsx)(p,{label:"New password",children:(0,s.jsx)(u,{type:"password",value:h.new,onChange:e=>g({...h,new:e.target.value}),required:!0})}),(0,s.jsx)(p,{label:"Confirm password",children:(0,s.jsx)(u,{type:"password",value:h.confirm,onChange:e=>g({...h,confirm:e.target.value}),required:!0})}),(0,s.jsx)("button",{disabled:v,className:"rounded-xl bg-primary px-4 py-2 text-sm font-semibold text-white disabled:opacity-50",children:e.hasPassword?"Update Password":"Set Password"}),(0,s.jsx)(n,{status:y})]})]})}),(0,s.jsxs)(c,{icon:"database",title:"Database Backup",desc:"Export or restore the local bluerouter configuration database.",children:[(0,s.jsxs)("div",{className:"flex flex-wrap items-center gap-3",children:[(0,s.jsx)("button",{onClick:eU,disabled:w,className:"rounded-xl bg-primary px-4 py-2 text-sm font-semibold text-white disabled:opacity-50",children:"Download Backup"}),(0,s.jsx)("button",{onClick:()=>A.current?.click(),disabled:w,className:"rounded-xl border border-border px-4 py-2 text-sm font-semibold text-text-main hover:border-primary/50 disabled:opacity-50",children:"Import Backup"}),(0,s.jsx)("input",{ref:A,type:"file",accept:"application/json",className:"hidden",onChange:eS})]}),(0,s.jsx)(n,{status:D})]}),(0,s.jsx)(c,{icon:"corporate_fare",title:"LDAP / Active Directory Login",desc:"Search users from a User Base DN, restrict login by group DN, and grant admin by group DN. The old Selected LDAP users list is kept as a manual admin list.",children:(0,s.jsxs)("form",{onSubmit:ek,className:"space-y-5",children:[(0,s.jsx)("div",{className:"flex flex-wrap gap-3",children:(0,s.jsx)("button",{type:"button",onClick:()=>eL("ldapEnabled",!P.ldapEnabled),className:`rounded-xl px-3 py-2 text-sm font-semibold ${P.ldapEnabled?"bg-primary text-white":"border border-border text-text-muted"}`,children:P.ldapEnabled?"Enabled":"Disabled"})}),(0,s.jsxs)("div",{className:"grid gap-4 lg:grid-cols-2",children:[(0,s.jsx)(p,{label:"LDAP URL",children:(0,s.jsx)(u,{value:P.ldapUrl,onChange:e=>eL("ldapUrl",e.target.value),placeholder:"ldap://dc01.company.local:389"})}),(0,s.jsx)(p,{label:"LDAP User Base DN",hint:"OU/container/domain where user objects are searched. Do not use a group DN here.",children:(0,s.jsx)(u,{value:P.ldapUserBaseDn,onChange:e=>eL("ldapUserBaseDn",e.target.value),placeholder:"OU=Users,OU=xxx,DC=xx,DC=vn"})}),(0,s.jsx)(p,{label:"LDAP Bind DN",children:(0,s.jsx)(u,{value:P.ldapBindDn,onChange:e=>eL("ldapBindDn",e.target.value),placeholder:"CN=svc-bluerouter,OU=Service Accounts,DC=company,DC=local"})}),(0,s.jsx)(p,{label:"LDAP Bind Password",children:(0,s.jsx)(u,{type:"password",value:P.ldapBindPassword,onChange:e=>eL("ldapBindPassword",e.target.value),placeholder:e.ldapHasBindPassword?"Saved — leave blank to keep":"Service account password"})}),(0,s.jsx)(p,{label:"LDAP Login Allowed Group DN",hint:"Only members of this group can log in. Leave blank to allow any valid LDAP user.",children:(0,s.jsx)(u,{value:P.ldapLoginAllowedGroupDn,onChange:e=>eL("ldapLoginAllowedGroupDn",e.target.value),placeholder:"CN=Apikeys_Groups,OU=AppGroups,OU=xxx,DC=xx,DC=vn"})}),(0,s.jsx)(p,{label:"LDAP Admin Group DN",hint:"Members of this group get full admin dashboard access.",children:(0,s.jsx)(u,{value:P.ldapAdminGroupDn,onChange:e=>eL("ldapAdminGroupDn",e.target.value),placeholder:"CN=BlueRouter_Admins,OU=AppGroups,OU=xxx,DC=xx,DC=vn"})}),(0,s.jsx)(p,{label:"LDAP Monitor Admin Group DN",hint:"Members can use only Endpoint, API Keys, Usage, Analytics, Quota Tracker and Prompt Logs with admin-like permissions inside those tabs.",children:(0,s.jsx)(u,{value:P.ldapMonitorAdminGroupDn,onChange:e=>eL("ldapMonitorAdminGroupDn",e.target.value),placeholder:"CN=BlueRouter_Monitor_Admins,OU=AppGroups,OU=xxx,DC=xx,DC=vn"})})]}),(0,s.jsxs)("div",{className:"grid gap-4 lg:grid-cols-2",children:[(0,s.jsx)(p,{label:"User search filter",hint:"Use {{username}} placeholder.",children:(0,s.jsx)(u,{value:P.ldapUserSearchFilter,onChange:e=>eL("ldapUserSearchFilter",e.target.value)})}),(0,s.jsx)(p,{label:"Login group mode",hint:"Nested groups uses AD matching rule 1.2.840.113556.1.4.1941.",children:(0,s.jsx)(x,{title:"Nested group membership",desc:"Recommended for Active Directory nested groups.",checked:P.ldapNestedGroups,onChange:e=>eL("ldapNestedGroups",e)})}),(0,s.jsx)(p,{label:"Username attribute",children:(0,s.jsx)(u,{value:P.ldapUserNameAttribute,onChange:e=>eL("ldapUserNameAttribute",e.target.value)})}),(0,s.jsx)(p,{label:"Display attribute",children:(0,s.jsx)(u,{value:P.ldapUserDisplayAttribute,onChange:e=>eL("ldapUserDisplayAttribute",e.target.value)})}),(0,s.jsx)(p,{label:"Email attribute",children:(0,s.jsx)(u,{value:P.ldapUserEmailAttribute,onChange:e=>eL("ldapUserEmailAttribute",e.target.value)})}),(0,s.jsx)(p,{label:"Connect timeout ms",children:(0,s.jsx)(u,{type:"number",value:P.ldapConnectTimeoutMs,onChange:e=>eL("ldapConnectTimeoutMs",e.target.value)})})]}),(0,s.jsx)(x,{title:"Reject invalid TLS certificates",desc:"Disable only for test/self-signed LDAP TLS.",checked:P.ldapTlsRejectUnauthorized,onChange:e=>eL("ldapTlsRejectUnauthorized",e)}),(0,s.jsxs)("div",{className:"rounded-2xl border border-border bg-background p-4",children:[(0,s.jsxs)("div",{className:"mb-3",children:[(0,s.jsx)("h3",{className:"font-semibold text-text-main",children:"Manual admin users / LDAP owner list"}),(0,s.jsx)("p",{className:"mt-1 text-xs text-text-muted",children:"Users loaded here come from Login Allowed Group DN when set. Selected users are also treated as manual admins for backward compatibility."})]}),(0,s.jsxs)("div",{className:"mb-3 flex gap-2",children:[(0,s.jsx)(u,{value:F,onChange:e=>R(e.target.value),placeholder:"Search users..."}),(0,s.jsx)("button",{type:"button",onClick:eI,disabled:V,className:"rounded-xl border border-border px-4 py-2 text-sm font-semibold text-text-main disabled:opacity-50",children:V?"Loading...":"Load users"})]}),_.length>0&&(0,s.jsx)("div",{className:"max-h-72 overflow-auto rounded-xl border border-border",children:_.map(e=>{let a=P.ldapAllowedUsers.includes(e.username);return(0,s.jsxs)("button",{type:"button",onClick:()=>eE(e.username),className:`flex w-full items-center justify-between gap-3 border-b border-border px-3 py-2 text-left text-sm last:border-b-0 ${a?"bg-primary/10":"bg-background hover:bg-surface"}`,children:[(0,s.jsxs)("span",{children:[(0,s.jsx)("span",{className:"font-semibold text-text-main",children:e.displayName||e.username}),(0,s.jsxs)("span",{className:"ml-2 text-text-muted",children:[e.username,e.email?` \xb7 ${e.email}`:""]})]}),(0,s.jsx)("span",{className:"material-symbols-outlined text-primary",children:a?"check_circle":"radio_button_unchecked"})]},e.dn||e.username)})}),(0,s.jsxs)("div",{className:"mt-3",children:[(0,s.jsxs)("div",{className:"mb-2 text-sm font-semibold text-text-main",children:["Selected manual admin users (",P.ldapAllowedUsers.length,")"]}),0===P.ldapAllowedUsers.length?(0,s.jsx)("div",{className:"text-sm text-text-muted",children:"No users selected."}):(0,s.jsx)("div",{className:"flex flex-wrap gap-2",children:P.ldapAllowedUsers.map(e=>(0,s.jsxs)("button",{type:"button",onClick:()=>eE(e),className:"rounded-full border border-primary/30 bg-primary/10 px-3 py-1 text-xs text-primary",children:[e," \xd7"]},e))})]})]}),(0,s.jsxs)("div",{className:"flex flex-wrap gap-3",children:[(0,s.jsx)("button",{type:"button",onClick:eP,disabled:G,className:"rounded-xl border border-border px-4 py-2 text-sm font-semibold text-text-main disabled:opacity-50",children:G?"Testing...":"Save & test LDAP"}),(0,s.jsx)("button",{type:"submit",disabled:B,className:"rounded-xl bg-primary px-4 py-2 text-sm font-semibold text-white disabled:opacity-50",children:B?"Saving...":"Save LDAP settings"})]}),(0,s.jsx)(n,{status:E})]})}),(0,s.jsxs)(c,{icon:"lock_open",title:"OIDC Dashboard Login",desc:"oidc"===e.authMode?"OIDC active":"both"===e.authMode?"Password + OIDC active":"Optional SSO via Authentik/Keycloak/Google",children:[(0,s.jsx)("button",{type:"button",onClick:()=>ee(e=>!e),className:"mb-4 rounded-xl border border-border px-4 py-2 text-sm font-semibold text-text-main",children:Z?"Hide OIDC settings":"Show OIDC settings"}),Z&&(0,s.jsxs)("div",{className:"space-y-4",children:[(0,s.jsx)("div",{className:"grid gap-3 md:grid-cols-3",children:[{value:"password",title:"Password/LDAP",desc:"Keep local and LDAP login."},{value:"oidc",title:"OIDC only",desc:"Disable local/LDAP login when configured."},{value:"both",title:"Both",desc:"Allow either OIDC or local/LDAP."}].map(e=>{let a=W.authMode===e.value;return(0,s.jsxs)("button",{type:"button",onClick:()=>q(a=>({...a,authMode:e.value})),className:`rounded-xl border p-3 text-left ${a?"border-primary bg-primary/10":"border-border bg-background hover:border-primary/40"}`,children:[(0,s.jsx)("div",{className:"font-semibold text-text-main",children:e.title}),(0,s.jsx)("div",{className:"mt-1 text-xs text-text-muted",children:e.desc})]},e.value)})}),(0,s.jsxs)("div",{className:"grid gap-4 lg:grid-cols-2",children:[(0,s.jsx)(p,{label:"Issuer URL",children:(0,s.jsx)(u,{value:W.oidcIssuerUrl,onChange:e=>q({...W,oidcIssuerUrl:e.target.value})})}),(0,s.jsx)(p,{label:"Client ID",children:(0,s.jsx)(u,{value:W.oidcClientId,onChange:e=>q({...W,oidcClientId:e.target.value})})}),(0,s.jsx)(p,{label:"Client Secret",children:(0,s.jsx)(u,{type:"password",value:J,onChange:e=>H(e.target.value),placeholder:e.oidcConfigured?"Saved — leave blank to keep":"Client secret"})}),(0,s.jsx)(p,{label:"Scopes",children:(0,s.jsx)(u,{value:W.oidcScopes,onChange:e=>q({...W,oidcScopes:e.target.value})})}),(0,s.jsx)(p,{label:"Login label",children:(0,s.jsx)(u,{value:W.oidcLoginLabel,onChange:e=>q({...W,oidcLoginLabel:e.target.value})})})]}),(0,s.jsx)("button",{type:"button",onClick:()=>eO(),disabled:Y,className:"rounded-xl bg-primary px-4 py-2 text-sm font-semibold text-white disabled:opacity-50",children:Y?"Saving...":"Save OIDC settings"}),(0,s.jsx)(n,{status:K})]})]})]})}},82114:e=>{"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"}},e=>{e.O(0,[8441,3794,7358],()=>e(e.s=7973)),_N_E=e.O()}]);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[4520],{33796:(e,a,t)=>{Promise.resolve().then(t.bind(t,83016))},54642:e=>{var a;"u">typeof __nccwpck_require__&&(__nccwpck_require__.ab="//"),(a={}).endianness=function(){return"LE"},a.hostname=function(){return"u">typeof location?location.hostname:""},a.loadavg=function(){return[]},a.uptime=function(){return 0},a.freemem=function(){return Number.MAX_VALUE},a.totalmem=function(){return Number.MAX_VALUE},a.cpus=function(){return[]},a.type=function(){return"Browser"},a.release=function(){return"u">typeof navigator?navigator.appVersion:""},a.networkInterfaces=a.getNetworkInterfaces=function(){return{}},a.arch=function(){return"javascript"},a.platform=function(){return"browser"},a.tmpdir=a.tmpDir=function(){return"/tmp"},a.EOL="\n",a.homedir=function(){return"/"},e.exports=a},83016:(e,a,t)=>{"use strict";t.r(a),t.d(a,{default:()=>u});var r=t(95155),c=t(39092),s=t.n(c),n=t(12115),i=t(73321),o=t(90620),l=t(44656);let d=[{badge:"CHAT",title:"AI Web Chat",description:"Tr\xf2 chuyện với AI nội bộ, hỗ trợ viết code, ph\xe2n t\xedch t\xe0i liệu, brainstorm \xfd tưởng v\xe0 hỏi đ\xe1p kỹ thuật.",href:"https://ai.fujinet.vn/",cta:"Mở AI Chat",icon:"chat",accent:"#d946ef",accentRgb:"217,70,239"},{badge:"DỊCH",title:"AI Translator",description:"Dịch Word, Excel, PowerPoint, h\xecnh ảnh v\xe0 PDF bằng AI, ưu ti\xean giữ nguy\xean định dạng gốc.",href:"https://translate-workspace.fujinet.vn",cta:"Mở Translator",icon:"translate",accent:"#a855f7",accentRgb:"168,85,247"},{badge:"TICKET",title:"IT Support",description:"Gửi y\xeau cầu hỗ trợ kỹ thuật, theo d\xf5i tiến độ ticket, trao đổi với IT v\xe0 xem lịch sử xử l\xfd sự cố.",href:"https://itsupport.fujinet.vn",cta:"Gửi Ticket",icon:"support",accent:"#3b82f6",accentRgb:"59,130,246"},{badge:"MEETING",title:"Web Meeting",description:"Họp video conference nội bộ trực tuyến, hỗ trợ chia sẻ m\xe0n h\xecnh, trao đổi nh\xf3m v\xe0 l\xe0m việc từ xa.",href:"https://meeting.fujinet.net",cta:"V\xe0o Meeting",icon:"meeting",accent:"#10b981",accentRgb:"16,185,129"},{badge:"ASSET",title:"IT Resource",description:"Quản l\xfd thiết bị, t\xe0i khoản, VPN, Work From Home v\xe0 c\xe1c dịch vụ hạ tầng CNTT nội bộ.",href:"https://itresource.fujinet.net/",cta:"Mở Resource",icon:"resource",accent:"#06b6d4",accentRgb:"6,182,212"}],x="fjs-login-weekly-style",g=["sunday","monday","tuesday","wednesday","thursday","friday","saturday"],f=[{id:"sunday",dayLabel:"Chủ nhật",shortLabel:"CN",name:"Solar Genesis",pageBg:"radial-gradient(circle at 8% -10%, rgba(251,191,36,0.30), transparent 31%), radial-gradient(circle at 92% 18%, rgba(244,63,94,0.24), transparent 30%), radial-gradient(circle at 50% 112%, rgba(34,211,238,0.16), transparent 34%), #150b07",heroGradient:"linear-gradient(135deg, #3b1607 0%, #7c2d12 42%, #f97316 100%)",titleGradient:"linear-gradient(135deg, #fff7ed 0%, #fed7aa 42%, #fef08a 72%, #a7f3d0 100%)",buttonGradient:"linear-gradient(90deg, #f97316 0%, #f43f5e 54%, #facc15 100%)",footerIconGradient:"linear-gradient(135deg, #f97316, #f43f5e)",primary:"#f97316",secondary:"#f43f5e",accent:"#facc15",primaryRgb:"249,115,22",secondaryRgb:"244,63,94",accentRgb:"250,204,21",softText:"rgba(255,237,213,0.78)",mutedText:"rgba(255,237,213,0.50)",heroSubtitle:"rgba(254,215,170,0.74)",heroBody:"rgba(255,237,213,0.78)",formBg:"linear-gradient(180deg, #fffaf4 0%, #ffffff 46%, #fff7ed 100%)",cardBg:"linear-gradient(180deg, rgba(255,255,255,0.075), rgba(255,255,255,0.030))",aurora:["rgba(249,115,22,0.30)","rgba(244,63,94,0.26)","rgba(250,204,21,0.22)","rgba(34,211,238,0.13)"],panelOrbs:["rgba(251,146,60,0.44)","rgba(244,63,94,0.36)","rgba(250,204,21,0.18)"],formOrbs:["rgba(249,115,22,0.14)","rgba(244,63,94,0.10)"],serviceAccents:[{accent:"#f97316",accentRgb:"249,115,22"},{accent:"#f43f5e",accentRgb:"244,63,94"},{accent:"#facc15",accentRgb:"250,204,21"},{accent:"#22c55e",accentRgb:"34,197,94"},{accent:"#06b6d4",accentRgb:"6,182,212"}]},{id:"monday",dayLabel:"Thứ 2",shortLabel:"T2",name:"Ocean Intelligence",pageBg:"radial-gradient(circle at 5% 0%, rgba(14,165,233,0.30), transparent 32%), radial-gradient(circle at 88% 20%, rgba(37,99,235,0.26), transparent 34%), radial-gradient(circle at 50% 110%, rgba(45,212,191,0.18), transparent 32%), #06111f",heroGradient:"linear-gradient(135deg, #082f49 0%, #1e3a8a 48%, #0891b2 100%)",titleGradient:"linear-gradient(135deg, #dffafe 0%, #bfdbfe 45%, #67e8f9 75%, #ffffff 100%)",buttonGradient:"linear-gradient(90deg, #0284c7 0%, #2563eb 52%, #22d3ee 100%)",footerIconGradient:"linear-gradient(135deg, #0284c7, #22d3ee)",primary:"#0284c7",secondary:"#2563eb",accent:"#22d3ee",primaryRgb:"2,132,199",secondaryRgb:"37,99,235",accentRgb:"34,211,238",softText:"rgba(224,242,254,0.80)",mutedText:"rgba(224,242,254,0.48)",heroSubtitle:"rgba(186,230,253,0.78)",heroBody:"rgba(224,242,254,0.76)",formBg:"linear-gradient(180deg, #f0f9ff 0%, #ffffff 48%, #eff6ff 100%)",cardBg:"linear-gradient(180deg, rgba(240,249,255,0.075), rgba(255,255,255,0.026))",aurora:["rgba(14,165,233,0.30)","rgba(37,99,235,0.27)","rgba(34,211,238,0.20)","rgba(16,185,129,0.12)"],panelOrbs:["rgba(14,165,233,0.42)","rgba(37,99,235,0.42)","rgba(34,211,238,0.18)"],formOrbs:["rgba(14,165,233,0.13)","rgba(37,99,235,0.10)"],serviceAccents:[{accent:"#0ea5e9",accentRgb:"14,165,233"},{accent:"#2563eb",accentRgb:"37,99,235"},{accent:"#22d3ee",accentRgb:"34,211,238"},{accent:"#14b8a6",accentRgb:"20,184,166"},{accent:"#38bdf8",accentRgb:"56,189,248"}]},{id:"tuesday",dayLabel:"Thứ 3",shortLabel:"T3",name:"Crimson Forge",pageBg:"radial-gradient(circle at 6% -10%, rgba(239,68,68,0.30), transparent 31%), radial-gradient(circle at 92% 18%, rgba(249,115,22,0.24), transparent 31%), radial-gradient(circle at 48% 112%, rgba(168,85,247,0.17), transparent 34%), #16070b",heroGradient:"linear-gradient(135deg, #450a0a 0%, #7f1d1d 45%, #9a3412 100%)",titleGradient:"linear-gradient(135deg, #fee2e2 0%, #fecaca 36%, #fed7aa 66%, #f5d0fe 100%)",buttonGradient:"linear-gradient(90deg, #dc2626 0%, #f97316 52%, #a855f7 100%)",footerIconGradient:"linear-gradient(135deg, #dc2626, #f97316)",primary:"#dc2626",secondary:"#f97316",accent:"#a855f7",primaryRgb:"220,38,38",secondaryRgb:"249,115,22",accentRgb:"168,85,247",softText:"rgba(254,226,226,0.80)",mutedText:"rgba(254,226,226,0.48)",heroSubtitle:"rgba(254,202,202,0.74)",heroBody:"rgba(254,226,226,0.76)",formBg:"linear-gradient(180deg, #fff7f7 0%, #ffffff 48%, #fff1f2 100%)",cardBg:"linear-gradient(180deg, rgba(255,255,255,0.072), rgba(255,255,255,0.026))",aurora:["rgba(239,68,68,0.30)","rgba(249,115,22,0.26)","rgba(168,85,247,0.19)","rgba(250,204,21,0.10)"],panelOrbs:["rgba(239,68,68,0.45)","rgba(249,115,22,0.38)","rgba(168,85,247,0.18)"],formOrbs:["rgba(239,68,68,0.12)","rgba(249,115,22,0.10)"],serviceAccents:[{accent:"#ef4444",accentRgb:"239,68,68"},{accent:"#f97316",accentRgb:"249,115,22"},{accent:"#a855f7",accentRgb:"168,85,247"},{accent:"#f59e0b",accentRgb:"245,158,11"},{accent:"#fb7185",accentRgb:"251,113,133"}]},{id:"wednesday",dayLabel:"Thứ 4",shortLabel:"T4",name:"Emerald Matrix",pageBg:"radial-gradient(circle at 8% -8%, rgba(16,185,129,0.30), transparent 31%), radial-gradient(circle at 90% 18%, rgba(20,184,166,0.24), transparent 31%), radial-gradient(circle at 50% 112%, rgba(132,204,22,0.16), transparent 33%), #06140f",heroGradient:"linear-gradient(135deg, #052e16 0%, #064e3b 48%, #0f766e 100%)",titleGradient:"linear-gradient(135deg, #dcfce7 0%, #a7f3d0 43%, #5eead4 72%, #ecfccb 100%)",buttonGradient:"linear-gradient(90deg, #059669 0%, #14b8a6 52%, #84cc16 100%)",footerIconGradient:"linear-gradient(135deg, #059669, #84cc16)",primary:"#059669",secondary:"#14b8a6",accent:"#84cc16",primaryRgb:"5,150,105",secondaryRgb:"20,184,166",accentRgb:"132,204,22",softText:"rgba(220,252,231,0.80)",mutedText:"rgba(220,252,231,0.48)",heroSubtitle:"rgba(167,243,208,0.76)",heroBody:"rgba(220,252,231,0.76)",formBg:"linear-gradient(180deg, #f0fdf4 0%, #ffffff 48%, #ecfdf5 100%)",cardBg:"linear-gradient(180deg, rgba(236,253,245,0.074), rgba(255,255,255,0.026))",aurora:["rgba(16,185,129,0.30)","rgba(20,184,166,0.25)","rgba(132,204,22,0.18)","rgba(34,211,238,0.10)"],panelOrbs:["rgba(16,185,129,0.42)","rgba(20,184,166,0.38)","rgba(132,204,22,0.17)"],formOrbs:["rgba(16,185,129,0.12)","rgba(20,184,166,0.10)"],serviceAccents:[{accent:"#10b981",accentRgb:"16,185,129"},{accent:"#14b8a6",accentRgb:"20,184,166"},{accent:"#84cc16",accentRgb:"132,204,22"},{accent:"#22c55e",accentRgb:"34,197,94"},{accent:"#06b6d4",accentRgb:"6,182,212"}]},{id:"thursday",dayLabel:"Thứ 5",shortLabel:"T5",name:"Royal Nebula",pageBg:"radial-gradient(circle at 8% -8%, rgba(99,102,241,0.31), transparent 31%), radial-gradient(circle at 90% 20%, rgba(139,92,246,0.27), transparent 32%), radial-gradient(circle at 50% 112%, rgba(6,182,212,0.17), transparent 33%), #090b22",heroGradient:"linear-gradient(135deg, #172554 0%, #312e81 48%, #581c87 100%)",titleGradient:"linear-gradient(135deg, #e0e7ff 0%, #ddd6fe 45%, #c4b5fd 72%, #a5f3fc 100%)",buttonGradient:"linear-gradient(90deg, #4f46e5 0%, #8b5cf6 52%, #06b6d4 100%)",footerIconGradient:"linear-gradient(135deg, #4f46e5, #8b5cf6)",primary:"#4f46e5",secondary:"#8b5cf6",accent:"#06b6d4",primaryRgb:"79,70,229",secondaryRgb:"139,92,246",accentRgb:"6,182,212",softText:"rgba(224,231,255,0.80)",mutedText:"rgba(224,231,255,0.48)",heroSubtitle:"rgba(221,214,254,0.76)",heroBody:"rgba(224,231,255,0.76)",formBg:"linear-gradient(180deg, #f8f7ff 0%, #ffffff 48%, #f0f9ff 100%)",cardBg:"linear-gradient(180deg, rgba(255,255,255,0.074), rgba(255,255,255,0.028))",aurora:["rgba(99,102,241,0.30)","rgba(139,92,246,0.28)","rgba(6,182,212,0.17)","rgba(59,130,246,0.13)"],panelOrbs:["rgba(99,102,241,0.42)","rgba(139,92,246,0.42)","rgba(6,182,212,0.17)"],formOrbs:["rgba(99,102,241,0.12)","rgba(139,92,246,0.10)"],serviceAccents:[{accent:"#6366f1",accentRgb:"99,102,241"},{accent:"#8b5cf6",accentRgb:"139,92,246"},{accent:"#3b82f6",accentRgb:"59,130,246"},{accent:"#06b6d4",accentRgb:"6,182,212"},{accent:"#a855f7",accentRgb:"168,85,247"}]},{id:"friday",dayLabel:"Thứ 6",shortLabel:"T6",name:"Cyber Sakura",pageBg:"radial-gradient(circle at 8% -8%, rgba(236,72,153,0.29), transparent 31%), radial-gradient(circle at 90% 18%, rgba(217,70,239,0.25), transparent 32%), radial-gradient(circle at 48% 112%, rgba(251,113,133,0.18), transparent 32%), #17071a",heroGradient:"linear-gradient(135deg, #500724 0%, #831843 45%, #86198f 100%)",titleGradient:"linear-gradient(135deg, #fce7f3 0%, #fbcfe8 40%, #f5d0fe 70%, #fed7aa 100%)",buttonGradient:"linear-gradient(90deg, #db2777 0%, #d946ef 52%, #fb7185 100%)",footerIconGradient:"linear-gradient(135deg, #db2777, #d946ef)",primary:"#db2777",secondary:"#d946ef",accent:"#fb7185",primaryRgb:"219,39,119",secondaryRgb:"217,70,239",accentRgb:"251,113,133",softText:"rgba(252,231,243,0.80)",mutedText:"rgba(252,231,243,0.48)",heroSubtitle:"rgba(251,207,232,0.76)",heroBody:"rgba(252,231,243,0.76)",formBg:"linear-gradient(180deg, #fff5fb 0%, #ffffff 48%, #fdf4ff 100%)",cardBg:"linear-gradient(180deg, rgba(255,255,255,0.074), rgba(255,255,255,0.026))",aurora:["rgba(236,72,153,0.30)","rgba(217,70,239,0.26)","rgba(251,113,133,0.18)","rgba(251,146,60,0.12)"],panelOrbs:["rgba(236,72,153,0.42)","rgba(217,70,239,0.40)","rgba(251,113,133,0.17)"],formOrbs:["rgba(236,72,153,0.12)","rgba(217,70,239,0.10)"],serviceAccents:[{accent:"#ec4899",accentRgb:"236,72,153"},{accent:"#d946ef",accentRgb:"217,70,239"},{accent:"#fb7185",accentRgb:"251,113,133"},{accent:"#f97316",accentRgb:"249,115,22"},{accent:"#a855f7",accentRgb:"168,85,247"}]},{id:"saturday",dayLabel:"Thứ 7",shortLabel:"T7",name:"Aurora Command",pageBg:"#0a0a1f",heroGradient:"linear-gradient(135deg, #1e1b4b 0%, #4c1d95 48%, #581c87 100%)",titleGradient:"linear-gradient(135deg, #ddd6fe 0%, #f5d0fe 52%, #a5f3fc 100%)",buttonGradient:"linear-gradient(90deg, #4f46e5 0%, #7c3aed 50%, #9333ea 100%)",footerIconGradient:"linear-gradient(135deg, #4f46e5, #7c3aed)",primary:"#4f46e5",secondary:"#7c3aed",accent:"#22d3ee",primaryRgb:"79,70,229",secondaryRgb:"124,58,237",accentRgb:"34,211,238",softText:"rgba(237,233,254,0.80)",mutedText:"rgba(237,233,254,0.48)",heroSubtitle:"rgba(221,214,254,0.70)",heroBody:"rgba(237,233,254,0.76)",formBg:"#ffffff",cardBg:"linear-gradient(180deg, rgba(255,255,255,0.060), rgba(255,255,255,0.030))",aurora:["rgba(124,58,237,0.30)","rgba(79,70,229,0.30)","rgba(217,70,239,0.25)","rgba(6,182,212,0.15)"],panelOrbs:["rgba(217,70,239,0.40)","rgba(99,102,241,0.40)","rgba(236,72,153,0.20)"],formOrbs:["rgba(124,58,237,0.12)","rgba(79,70,229,0.10)"],serviceAccents:[{accent:"#d946ef",accentRgb:"217,70,239"},{accent:"#a855f7",accentRgb:"168,85,247"},{accent:"#3b82f6",accentRgb:"59,130,246"},{accent:"#10b981",accentRgb:"16,185,129"},{accent:"#06b6d4",accentRgb:"6,182,212"}]}],b=f.reduce((e,a)=>(e[a.id]=a,e),{}),h="saturday";function p({name:e,className:a="h-5 w-5"}){let t={className:a,fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};return"chat"===e?(0,r.jsxs)("svg",{...t,children:[(0,r.jsx)("path",{d:"M7.5 8.5h9"}),(0,r.jsx)("path",{d:"M7.5 12h5.5"}),(0,r.jsx)("path",{d:"M21 11.5a7.5 7.5 0 0 1-7.5 7.5H8l-5 3v-5.2A7.5 7.5 0 1 1 21 11.5Z"})]}):"translate"===e?(0,r.jsxs)("svg",{...t,children:[(0,r.jsx)("path",{d:"M4 5h7"}),(0,r.jsx)("path",{d:"M8 3v2"}),(0,r.jsx)("path",{d:"M10 5c-.6 3.2-2.4 5.7-5 7.5"}),(0,r.jsx)("path",{d:"M5 8c1.2 1.8 2.7 3.2 4.7 4.2"}),(0,r.jsx)("path",{d:"m14 21 4-9 4 9"}),(0,r.jsx)("path",{d:"M15.5 17.5h5"})]}):"support"===e?(0,r.jsxs)("svg",{...t,children:[(0,r.jsx)("path",{d:"M4 13a8 8 0 0 1 16 0"}),(0,r.jsx)("path",{d:"M18 19a3 3 0 0 1-3 3h-2"}),(0,r.jsx)("path",{d:"M4 13v3a2 2 0 0 0 2 2h1v-7H6a2 2 0 0 0-2 2Z"}),(0,r.jsx)("path",{d:"M20 13v3a2 2 0 0 1-2 2h-1v-7h1a2 2 0 0 1 2 2Z"})]}):"meeting"===e?(0,r.jsxs)("svg",{...t,children:[(0,r.jsx)("rect",{x:"3",y:"6",width:"13",height:"12",rx:"2"}),(0,r.jsx)("path",{d:"m16 10 5-3v10l-5-3"}),(0,r.jsx)("path",{d:"M7.5 10h4"}),(0,r.jsx)("path",{d:"M7.5 14h2.5"})]}):"resource"===e?(0,r.jsxs)("svg",{...t,children:[(0,r.jsx)("rect",{x:"4",y:"5",width:"16",height:"11",rx:"2"}),(0,r.jsx)("path",{d:"M8 20h8"}),(0,r.jsx)("path",{d:"M12 16v4"}),(0,r.jsx)("path",{d:"M8 9h8"}),(0,r.jsx)("path",{d:"M8 12h4"})]}):null}function m({service:e}){return(0,r.jsxs)("a",{href:e.href,target:"_blank",rel:"noopener noreferrer",className:"group relative flex flex-col justify-between overflow-hidden rounded-2xl border border-white/12 p-4 backdrop-blur-xl transition-all duration-300 hover:-translate-y-1 hover:border-white/25",style:{background:e.cardBg,boxShadow:"0 8px 24px rgba(0,0,0,0.25), inset 0 1px 0 rgba(255,255,255,0.05)"},children:[(0,r.jsx)("div",{className:"pointer-events-none absolute -right-8 -top-8 h-24 w-24 rounded-full opacity-50 blur-2xl transition-opacity duration-300 group-hover:opacity-80",style:{background:e.accent}}),(0,r.jsx)("div",{className:"pointer-events-none absolute inset-x-0 bottom-0 h-px opacity-0 transition-opacity duration-300 group-hover:opacity-100",style:{background:`linear-gradient(90deg, transparent, ${e.accent}, transparent)`}}),(0,r.jsxs)("div",{className:"relative z-10 mb-3 flex items-center justify-between",children:[(0,r.jsx)("span",{className:"rounded-full px-2.5 py-0.5 text-[9px] font-black uppercase tracking-[0.18em] text-white shadow-lg",style:{background:e.accent,boxShadow:`0 4px 12px rgba(${e.accentRgb}, 0.4)`},children:e.badge}),(0,r.jsx)("span",{className:"grid h-8 w-8 place-items-center rounded-xl bg-white/95 shadow-md ring-1 ring-white/20 transition-transform group-hover:scale-110 group-hover:rotate-3",style:{color:e.accent},children:(0,r.jsx)(p,{name:e.icon,className:"h-4 w-4"})})]}),(0,r.jsxs)("div",{className:"relative z-10 flex-1",children:[(0,r.jsx)("h3",{className:"text-sm font-bold text-white",children:e.title}),(0,r.jsx)("p",{className:"mt-1 text-[11px] leading-relaxed text-white/55 line-clamp-2",children:e.description})]}),(0,r.jsxs)("div",{className:"relative z-10 mt-3 flex items-center gap-1.5 text-[10px] font-black uppercase tracking-[0.14em] transition-colors group-hover:text-white",style:{color:e.ctaColor},children:[e.cta,(0,r.jsx)("svg",{className:"h-3 w-3 transition-transform group-hover:translate-x-1",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:3,strokeLinecap:"round",strokeLinejoin:"round",children:(0,r.jsx)("path",{d:"M5 12h14M13 5l7 7-7 7"})})]})]})}function u(){let[e,a]=(0,n.useState)("admin"),[t,c]=(0,n.useState)(""),[p,u]=(0,n.useState)(!1),[j,y]=(0,n.useState)(""),[v,w]=(0,n.useState)(""),[k,N]=(0,n.useState)(0),[R,L]=(0,n.useState)(!1),[M,C]=(0,n.useState)(null),[S,B]=(0,n.useState)("password"),[T,I]=(0,n.useState)(!1),[A,G]=(0,n.useState)("Sign in with OIDC"),[_,$]=(0,n.useState)(!1),[O,W]=(0,n.useState)(!1),[E,P]=(0,n.useState)("admin"),[D,z]=(0,n.useState)("auto"),[F,V]=(0,n.useState)(h),[Z,H]=(0,n.useState)(!1),U=(0,i.useRouter)(),q=(0,l.useBranding)(),Q=q?.logoUrl||null,J=q?.siteTitle||"",X=q?.siteShortName||"Fujinet",K=J||o.vQ?.name||"FJS Digital Workspace",Y=b["auto"===D?F:D]||b.saturday,ee=d.map((e,a)=>({...e,...Y.serviceAccents[a]||{},cardBg:Y.cardBg,ctaColor:Y.heroSubtitle}));(0,n.useEffect)(()=>{let e=()=>{let e;V(g[new Date().getDay()]||h),z("auto"===(e=window.localStorage.getItem(x))||b[e]?e:"auto"),H(!0)};e(),window.addEventListener("focus",e);let a=()=>{document.hidden||e()};return document.addEventListener("visibilitychange",a),()=>{window.removeEventListener("focus",e),document.removeEventListener("visibilitychange",a)}},[]);let ea=e=>{let a="auto"===e||b[e]?e:"auto";z(a),window.localStorage.setItem(x,a)};(0,n.useEffect)(()=>{if(k<=0)return;let e=setInterval(()=>N(e=>e>0?e-1:0),1e3);return()=>clearInterval(e)},[k]),(0,n.useEffect)(()=>{!async function(){let e=new AbortController,t=setTimeout(()=>e.abort(),5e3),r=window.location.origin;try{let c=await fetch(`${r}/api/auth/status`,{signal:e.signal});if(clearTimeout(t),c.ok){let e=await c.json();C(!!e.hasPassword),B(e.authMode||"password"),I(!0===e.oidcConfigured),G(e.oidcLoginLabel||"Sign in with OIDC"),$(!0===e.ldapEnabled),W(!0===e.ldapConfigured),P(e.localLoginUsername||"admin"),a(e.localLoginUsername||"admin")}else C(!0)}catch{clearTimeout(t),C(!0)}}()},[U]);let et=async a=>{a.preventDefault(),L(!0),y(""),w("");try{let a=await fetch("/api/auth/login",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({username:e,password:t,loginType:"auto"})});if(a.ok)U.push("/dashboard"),U.refresh();else{let e=await a.json();y(e.error||"Invalid account or password"),e.resetHint&&w(e.resetHint),e.retryAfter&&N(Number(e.retryAfter))}}catch{y("An error occurred. Please try again.")}finally{L(!1)}},er=T&&["oidc","both"].includes(S),ec="oidc"!==S||!T,es=_&&O&&ec;return(0,r.jsxs)("main",{"data-theme-ready":Z?"true":"false",style:{"--theme-primary":Y.primary,"--theme-secondary":Y.secondary,"--theme-accent":Y.accent,"--theme-primary-rgb":Y.primaryRgb,"--theme-secondary-rgb":Y.secondaryRgb,"--theme-accent-rgb":Y.accentRgb,"--theme-button-gradient":Y.buttonGradient,"--theme-footer-icon-gradient":Y.footerIconGradient,"--theme-soft-text":Y.softText,"--theme-muted-text":Y.mutedText,background:Y.pageBg},className:"jsx-39c38f012cc9c82a relative min-h-screen overflow-hidden text-slate-800",children:[(0,r.jsxs)("div",{className:"jsx-39c38f012cc9c82a pointer-events-none absolute inset-0",children:[(0,r.jsx)("div",{style:{background:Y.aurora[0]},className:"jsx-39c38f012cc9c82a absolute -top-40 -left-40 h-[600px] w-[600px] rounded-full blur-[120px] animate-[floaty_12s_ease-in-out_infinite]"}),(0,r.jsx)("div",{style:{background:Y.aurora[1]},className:"jsx-39c38f012cc9c82a absolute top-1/3 -right-40 h-[500px] w-[500px] rounded-full blur-[120px] animate-[floaty_14s_ease-in-out_infinite_-3s]"}),(0,r.jsx)("div",{style:{background:Y.aurora[2]},className:"jsx-39c38f012cc9c82a absolute -bottom-40 left-1/3 h-[550px] w-[550px] rounded-full blur-[120px] animate-[floaty_16s_ease-in-out_infinite_-6s]"}),(0,r.jsx)("div",{style:{background:Y.aurora[3]},className:"jsx-39c38f012cc9c82a absolute top-1/2 left-1/2 h-[400px] w-[400px] -translate-x-1/2 -translate-y-1/2 rounded-full blur-[100px] animate-[floaty_10s_ease-in-out_infinite_-2s]"})]}),(0,r.jsx)(s(),{id:"39c38f012cc9c82a",children:'@keyframes floaty{0%,100%{transform:translate(0,0)scale(1)}33%{transform:translate(40px,-30px)scale(1.08)}66%{transform:translate(-30px,20px)scale(.95)}}@keyframes shimmer{0%{transform:translatex(-100%)}100%{transform:translatex(200%)}}@keyframes fadeUp{from{opacity:0;transform:translatey(20px)}to{opacity:1;transform:translatey(0)}}.shimmer-btn::after{content:"";position:absolute;top:0;left:0;bottom:0;width:60%;background:linear-gradient(90deg,transparent,rgba(255,255,255,.3),transparent);animation:shimmer 2.8s ease-in-out infinite;pointer-events:none}.fade-up{animation:fadeUp.6s ease-out backwards}.theme-input-icon{transition:color.2s ease}.theme-input-wrap:focus-within .theme-input-icon{color:var(--theme-primary)!important}.theme-input:focus{border-color:var(--theme-primary)!important;box-shadow:0 10px 24px rgba(var(--theme-primary-rgb),.12),0 0 0 4px rgba(var(--theme-primary-rgb),.12)!important}.theme-outline-button:hover{border-color:rgba(var(--theme-primary-rgb),.38)!important;background:rgba(var(--theme-primary-rgb),.055)!important;box-shadow:0 12px 28px rgba(var(--theme-primary-rgb),.1)!important}.theme-submit-btn{background:var(--theme-button-gradient);box-shadow:0 18px 42px rgba(var(--theme-primary-rgb),.3)}.theme-submit-btn:hover{box-shadow:0 22px 52px rgba(var(--theme-primary-rgb),.4)}.theme-footer-mark{background:var(--theme-footer-icon-gradient)}.theme-footer-link{color:var(--theme-soft-text)}.theme-footer-link:hover{color:#fff;text-decoration:underline}.theme-input-wrap button:hover{color:var(--theme-primary)!important}.theme-style-panel{border:1px solid rgba(255,255,255,.12);background:rgba(255,255,255,.04);box-shadow:inset 0 1px 0 rgba(255,255,255,.06),0 12px 32px rgba(0,0,0,.12)}.theme-style-palette{display:inline-flex;align-items:center;gap:6px;padding:4px;border-radius:14px;background:rgba(255,255,255,.055);border:1px solid rgba(255,255,255,.085)}.theme-style-swatch{position:relative;width:28px;height:28px;flex:0 0 28px;display:grid;place-items:center;border:1px solid rgba(255,255,255,.18);border-radius:8px;color:#fff;cursor:pointer;overflow:hidden;outline:none;box-shadow:inset 0 1px 0 rgba(255,255,255,.22),0 8px 18px rgba(0,0,0,.18);transition:transform.16s ease,border-color.16s ease,box-shadow.16s ease,opacity.16s ease}.theme-style-swatch::before{content:"";position:absolute;inset:0;background:linear-gradient(135deg,rgba(255,255,255,.3),transparent 45%,rgba(0,0,0,.18));pointer-events:none}.theme-style-swatch:hover{transform:translatey(-2px)scale(1.04);border-color:rgba(255,255,255,.62);box-shadow:inset 0 1px 0 rgba(255,255,255,.3),0 12px 26px rgba(0,0,0,.24),0 0 0 4px rgba(var(--theme-accent-rgb),.1)}.theme-style-swatch:focus-visible{border-color:rgba(255,255,255,.92);box-shadow:inset 0 1px 0 rgba(255,255,255,.28),0 0 0 4px rgba(var(--theme-accent-rgb),.18),0 14px 28px rgba(0,0,0,.24)}.theme-style-swatch.is-active{border-color:rgba(255,255,255,.95);box-shadow:inset 0 1px 0 rgba(255,255,255,.32),0 0 0 3px rgba(var(--theme-accent-rgb),.2),0 14px 30px rgba(0,0,0,.28)}.theme-style-swatch.is-active::after{content:"✓";position:absolute;right:-1px;top:-1px;width:14px;height:14px;display:grid;place-items:center;border-radius:0 7px 0 8px;background:rgba(2,6,23,.82);color:#fff;font-size:9px;font-weight:1000;line-height:1;box-shadow:0 4px 12px rgba(0,0,0,.22)}.theme-style-swatch-auto span{position:relative;z-index:1;font-size:10px;font-weight:1000;letter-spacing:-.03em;text-shadow:0 1px 8px rgba(0,0,0,.42)}@media(max-width:420px){.theme-style-palette{gap:5px}.theme-style-swatch{width:25px;height:25px;flex-basis:25px;border-radius:7px}}'}),(0,r.jsxs)("div",{className:"jsx-39c38f012cc9c82a relative z-10 mx-auto flex min-h-screen max-w-7xl flex-col justify-center px-4 py-6 sm:px-6 lg:px-8 lg:py-8",children:[(0,r.jsxs)("div",{style:{boxShadow:"0 30px 90px rgba(0,0,0,0.45)"},className:"jsx-39c38f012cc9c82a grid w-full overflow-hidden rounded-[2rem] border border-white/10 bg-white/[0.02] backdrop-blur-2xl fade-up lg:grid-cols-[1.1fr_0.9fr]",children:[(0,r.jsxs)("div",{style:{background:Y.heroGradient},className:"jsx-39c38f012cc9c82a relative hidden overflow-hidden p-8 lg:flex lg:flex-col lg:justify-between lg:p-10",children:[(0,r.jsx)("div",{style:{background:Y.panelOrbs[0]},className:"jsx-39c38f012cc9c82a pointer-events-none absolute -top-20 -right-20 h-72 w-72 rounded-full blur-[60px]"}),(0,r.jsx)("div",{style:{background:Y.panelOrbs[1]},className:"jsx-39c38f012cc9c82a pointer-events-none absolute -bottom-20 -left-20 h-72 w-72 rounded-full blur-[60px]"}),(0,r.jsx)("div",{style:{background:Y.panelOrbs[2]},className:"jsx-39c38f012cc9c82a pointer-events-none absolute top-1/2 left-1/2 h-48 w-48 -translate-x-1/2 -translate-y-1/2 rounded-full blur-[50px]"}),(0,r.jsx)("div",{style:{backgroundImage:"linear-gradient(rgba(255,255,255,0.07) 1px, transparent 1px), linear-gradient(90deg, rgba(255,255,255,0.07) 1px, transparent 1px)",backgroundSize:"32px 32px",maskImage:"radial-gradient(ellipse at center, black 30%, transparent 75%)",WebkitMaskImage:"radial-gradient(ellipse at center, black 30%, transparent 75%)"},className:"jsx-39c38f012cc9c82a pointer-events-none absolute inset-0 opacity-40"}),(0,r.jsxs)("div",{className:"jsx-39c38f012cc9c82a relative z-10 flex flex-col gap-3",children:[(0,r.jsx)("div",{style:{width:"fit-content"},className:"jsx-39c38f012cc9c82a inline-flex h-12 items-center rounded-2xl bg-white/95 px-4 shadow-2xl shadow-indigo-900/40 ring-1 ring-white/20",children:(0,r.jsx)("img",{src:Q||"/fjslogo.svg",alt:K,className:"jsx-39c38f012cc9c82a h-7 w-auto"})}),(0,r.jsx)("div",{style:{color:Y.heroSubtitle},className:"jsx-39c38f012cc9c82a text-[11px] uppercase tracking-[0.18em]",children:"Software Solutions \xb7 Internal Portal"})]}),(0,r.jsxs)("div",{className:"jsx-39c38f012cc9c82a relative z-10",children:[(0,r.jsxs)("div",{style:{background:`rgba(${Y.primaryRgb}, 0.13)`},className:"jsx-39c38f012cc9c82a mb-5 inline-flex items-center gap-2 rounded-full border border-white/20 px-3.5 py-1.5 text-[10px] font-semibold uppercase tracking-[0.18em] text-white backdrop-blur-md",children:[(0,r.jsxs)("span",{className:"jsx-39c38f012cc9c82a relative flex h-1.5 w-1.5",children:[(0,r.jsx)("span",{className:"jsx-39c38f012cc9c82a absolute inline-flex h-full w-full animate-ping rounded-full bg-emerald-400 opacity-75"}),(0,r.jsx)("span",{className:"jsx-39c38f012cc9c82a relative inline-flex h-1.5 w-1.5 rounded-full bg-emerald-400"})]}),J?`${J} \xb7 Internal`:"AI Router Gateway \xb7 Internal"]}),(0,r.jsxs)("h1",{className:"jsx-39c38f012cc9c82a text-3xl font-black leading-[1.1] tracking-tight text-white xl:text-4xl",children:["Truy cập cổng"," ",(0,r.jsx)("span",{style:{backgroundImage:Y.titleGradient},className:"jsx-39c38f012cc9c82a bg-clip-text text-transparent",children:"AI nội bộ"})," ",X]}),(0,r.jsx)("p",{style:{color:Y.heroBody},className:"jsx-39c38f012cc9c82a mt-4 max-w-md text-sm leading-relaxed",children:"API key gateway d\xf9ng chung cho to\xe0n bộ workload AI — translation, coding assistance, agent runtime v\xe0 internal services."})]}),(0,r.jsx)("div",{className:"jsx-39c38f012cc9c82a relative z-10 space-y-2.5",children:[{icon:(0,r.jsx)("path",{d:"M16.5 10.5V7a4.5 4.5 0 0 0-9 0v3.5M5 10.5h14v9a1.5 1.5 0 0 1-1.5 1.5h-11A1.5 1.5 0 0 1 5 19.5v-9Z",className:"jsx-39c38f012cc9c82a"}),text:"Đăng nhập bằng t\xe0i khoản nội bộ"},{icon:(0,r.jsx)("path",{d:"M12 3 4 6.5v5C4 16.5 7.5 20.5 12 21c4.5-.5 8-4.5 8-9.5v-5L12 3Z",className:"jsx-39c38f012cc9c82a"}),text:"Quản l\xfd & tự cấp API key"},{icon:(0,r.jsx)("path",{d:"M13 2 3 14h7l-1 8 10-12h-7l1-8Z",className:"jsx-39c38f012cc9c82a"}),text:"Self-hosted \xb7 bảo mật dữ liệu"}].map((e,a)=>(0,r.jsxs)("div",{style:{color:Y.heroBody},className:"jsx-39c38f012cc9c82a flex items-center gap-3 text-[13px]",children:[(0,r.jsx)("div",{className:"jsx-39c38f012cc9c82a flex h-8 w-8 shrink-0 items-center justify-center rounded-xl border border-white/15 bg-white/10 backdrop-blur-md",children:(0,r.jsx)("svg",{fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:"jsx-39c38f012cc9c82a h-3.5 w-3.5 text-white",children:e.icon})}),(0,r.jsx)("span",{className:"jsx-39c38f012cc9c82a",children:e.text})]},a))})]}),(0,r.jsxs)("div",{style:{background:Y.formBg},className:"jsx-39c38f012cc9c82a relative flex flex-col p-7 sm:p-10",children:[(0,r.jsx)("div",{style:{background:Y.formOrbs[0]},className:"jsx-39c38f012cc9c82a pointer-events-none absolute -top-24 -right-24 h-72 w-72 rounded-full blur-3xl"}),(0,r.jsx)("div",{style:{background:Y.formOrbs[1]},className:"jsx-39c38f012cc9c82a pointer-events-none absolute -bottom-24 -left-24 h-64 w-64 rounded-full blur-3xl"}),(0,r.jsxs)("div",{className:"jsx-39c38f012cc9c82a mb-6 flex items-center gap-3 lg:hidden",children:[(0,r.jsx)("div",{style:{background:Y.buttonGradient,boxShadow:`0 12px 28px rgba(${Y.primaryRgb}, 0.24)`},className:"jsx-39c38f012cc9c82a inline-flex h-10 items-center rounded-xl px-3 shadow-lg",children:(0,r.jsx)("img",{src:Q||"/fjslogo.svg",alt:K,className:`jsx-39c38f012cc9c82a h-6 w-auto ${Q?"":"brightness-0 invert"}`})}),(0,r.jsx)("div",{className:"jsx-39c38f012cc9c82a",children:(0,r.jsx)("div",{style:{color:Y.primary},className:"jsx-39c38f012cc9c82a text-[10px] uppercase tracking-[0.18em]",children:J||"AI Router Gateway"})})]}),(0,r.jsxs)("div",{className:"jsx-39c38f012cc9c82a relative z-10 flex flex-1 flex-col",children:[(0,r.jsxs)("div",{className:"jsx-39c38f012cc9c82a",children:[(0,r.jsxs)("span",{style:{background:Y.buttonGradient,boxShadow:`0 12px 28px rgba(${Y.primaryRgb}, 0.22)`},className:"jsx-39c38f012cc9c82a inline-flex items-center gap-1.5 rounded-full px-3 py-1 text-[10px] font-black uppercase tracking-[0.18em] text-white shadow-lg",children:[(0,r.jsxs)("svg",{fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2.5,className:"jsx-39c38f012cc9c82a h-3 w-3",children:[(0,r.jsx)("rect",{x:"4",y:"11",width:"16",height:"9",rx:"2",className:"jsx-39c38f012cc9c82a"}),(0,r.jsx)("path",{d:"M8 11V7a4 4 0 0 1 8 0v4",className:"jsx-39c38f012cc9c82a"})]}),"Đăng nhập"]}),(0,r.jsx)("h2",{className:"jsx-39c38f012cc9c82a mt-3 text-2xl font-black tracking-tight text-slate-950",children:"Ch\xe0o mừng trở lại"}),(0,r.jsx)("p",{className:"jsx-39c38f012cc9c82a mt-1.5 text-sm text-slate-500",children:"Đăng nhập để quản l\xfd API key & route AI traffic nội bộ."})]}),null===M?(0,r.jsxs)("div",{className:"jsx-39c38f012cc9c82a mt-6 flex items-center justify-center gap-3 rounded-2xl border border-slate-200 bg-slate-50/80 px-4 py-5 text-sm text-slate-500",children:[(0,r.jsxs)("svg",{style:{color:Y.primary},fill:"none",viewBox:"0 0 24 24",className:"jsx-39c38f012cc9c82a h-4 w-4 animate-spin",children:[(0,r.jsx)("circle",{cx:"12",cy:"12",r:"10",stroke:"currentColor",strokeWidth:"3",className:"jsx-39c38f012cc9c82a opacity-25"}),(0,r.jsx)("path",{fill:"currentColor",d:"M4 12a8 8 0 0 1 8-8V0C5.4 0 0 5.4 0 12h4Z",className:"jsx-39c38f012cc9c82a opacity-75"})]}),"Đang tải cấu h\xecnh x\xe1c thực..."]}):(0,r.jsxs)("div",{className:"jsx-39c38f012cc9c82a mt-6",children:[er&&(0,r.jsxs)("button",{type:"button",onClick:()=>{window.location.href="/api/auth/oidc/start"},className:"jsx-39c38f012cc9c82a theme-outline-button group mb-3 flex w-full items-center justify-center gap-2.5 rounded-2xl border border-slate-200 bg-white px-4 py-2.5 text-sm font-bold text-slate-700 shadow-sm transition-all hover:-translate-y-0.5",children:[(0,r.jsxs)("svg",{style:{color:Y.primary},fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2.2,strokeLinecap:"round",strokeLinejoin:"round",className:"jsx-39c38f012cc9c82a h-4 w-4",children:[(0,r.jsx)("circle",{cx:"12",cy:"12",r:"10",className:"jsx-39c38f012cc9c82a"}),(0,r.jsx)("path",{d:"m9 12 2 2 4-4",className:"jsx-39c38f012cc9c82a"})]}),A,(0,r.jsx)("svg",{fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2.5,className:"jsx-39c38f012cc9c82a h-3.5 w-3.5 text-slate-400 transition-transform group-hover:translate-x-0.5",children:(0,r.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M5 12h14M13 5l7 7-7 7",className:"jsx-39c38f012cc9c82a"})})]}),er&&ec&&(0,r.jsxs)("div",{className:"jsx-39c38f012cc9c82a mb-3 flex items-center gap-3 text-[11px] font-semibold uppercase tracking-[0.18em] text-slate-400",children:[(0,r.jsx)("span",{className:"jsx-39c38f012cc9c82a h-px flex-1 bg-slate-200"}),"hoặc",(0,r.jsx)("span",{className:"jsx-39c38f012cc9c82a h-px flex-1 bg-slate-200"})]}),ec?(0,r.jsxs)("form",{onSubmit:et,className:"jsx-39c38f012cc9c82a space-y-3",children:[(0,r.jsxs)("div",{className:"jsx-39c38f012cc9c82a",children:[(0,r.jsx)("label",{className:"jsx-39c38f012cc9c82a mb-1 block text-[11px] font-black uppercase tracking-[0.16em] text-slate-500",children:"T\xe0i khoản"}),(0,r.jsxs)("div",{className:"jsx-39c38f012cc9c82a theme-input-wrap group relative",children:[(0,r.jsx)("span",{className:"jsx-39c38f012cc9c82a theme-input-icon pointer-events-none absolute left-3.5 top-1/2 -translate-y-1/2 text-slate-400 transition-colors",children:(0,r.jsxs)("svg",{fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:"jsx-39c38f012cc9c82a h-4 w-4",children:[(0,r.jsx)("circle",{cx:"12",cy:"8",r:"4",className:"jsx-39c38f012cc9c82a"}),(0,r.jsx)("path",{d:"M4 21c0-4.4 3.6-8 8-8s8 3.6 8 8",className:"jsx-39c38f012cc9c82a"})]})}),(0,r.jsx)("input",{value:e,onChange:e=>a(e.target.value),placeholder:es?"admin hoặc LDAP username":E||"admin",autoFocus:!er,required:!0,className:"jsx-39c38f012cc9c82a theme-input w-full rounded-2xl border border-slate-200 bg-white py-2.5 pl-11 pr-3.5 text-sm font-medium text-slate-900 shadow-sm outline-none transition-all placeholder:font-normal placeholder:text-slate-400"})]})]}),(0,r.jsxs)("div",{className:"jsx-39c38f012cc9c82a",children:[(0,r.jsx)("label",{className:"jsx-39c38f012cc9c82a mb-1 block text-[11px] font-black uppercase tracking-[0.16em] text-slate-500",children:"Mật khẩu"}),(0,r.jsxs)("div",{className:"jsx-39c38f012cc9c82a theme-input-wrap group relative",children:[(0,r.jsx)("span",{className:"jsx-39c38f012cc9c82a theme-input-icon pointer-events-none absolute left-3.5 top-1/2 -translate-y-1/2 text-slate-400 transition-colors",children:(0,r.jsxs)("svg",{fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:"jsx-39c38f012cc9c82a h-4 w-4",children:[(0,r.jsx)("rect",{x:"4",y:"11",width:"16",height:"10",rx:"2",className:"jsx-39c38f012cc9c82a"}),(0,r.jsx)("path",{d:"M8 11V7a4 4 0 0 1 8 0v4",className:"jsx-39c38f012cc9c82a"})]})}),(0,r.jsx)("input",{type:p?"text":"password",value:t,onChange:e=>c(e.target.value),placeholder:"Nhập mật khẩu",required:!0,className:"jsx-39c38f012cc9c82a theme-input w-full rounded-2xl border border-slate-200 bg-white py-2.5 pl-11 pr-11 text-sm font-medium text-slate-900 shadow-sm outline-none transition-all placeholder:font-normal placeholder:text-slate-400"}),(0,r.jsx)("button",{type:"button",onClick:()=>u(e=>!e),tabIndex:-1,style:{"--hover-color":Y.primary},"aria-label":p?"Ẩn mật khẩu":"Hiện mật khẩu",className:"jsx-39c38f012cc9c82a absolute right-3 top-1/2 -translate-y-1/2 rounded-lg p-1.5 text-slate-400 transition-colors hover:bg-slate-100",children:p?(0,r.jsxs)("svg",{fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:"jsx-39c38f012cc9c82a h-4 w-4",children:[(0,r.jsx)("path",{d:"M3 3l18 18",className:"jsx-39c38f012cc9c82a"}),(0,r.jsx)("path",{d:"M10.6 6.1A10.5 10.5 0 0 1 12 6c6.5 0 10 7 10 7a17 17 0 0 1-2.2 3.2M6.6 6.6A17 17 0 0 0 2 13s3.5 7 10 7a10 10 0 0 0 5.4-1.6",className:"jsx-39c38f012cc9c82a"}),(0,r.jsx)("path",{d:"M9.9 9.9a3 3 0 0 0 4.2 4.2",className:"jsx-39c38f012cc9c82a"})]}):(0,r.jsxs)("svg",{fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:"jsx-39c38f012cc9c82a h-4 w-4",children:[(0,r.jsx)("path",{d:"M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7S2 12 2 12Z",className:"jsx-39c38f012cc9c82a"}),(0,r.jsx)("circle",{cx:"12",cy:"12",r:"3",className:"jsx-39c38f012cc9c82a"})]})})]})]}),"oidc"===S&&!T&&(0,r.jsxs)("div",{className:"jsx-39c38f012cc9c82a flex items-start gap-2.5 rounded-2xl border border-amber-200 bg-amber-50 p-2.5 text-xs text-amber-800",children:[(0,r.jsx)("svg",{fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,className:"jsx-39c38f012cc9c82a mt-0.5 h-4 w-4 shrink-0",children:(0,r.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M12 9v4m0 4h.01M10.3 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0Z",className:"jsx-39c38f012cc9c82a"})}),(0,r.jsx)("span",{className:"jsx-39c38f012cc9c82a",children:"OIDC đang bật nhưng chưa cấu h\xecnh. Password login vẫn d\xf9ng được để recovery."})]}),"both"===S&&T&&(0,r.jsxs)("div",{style:{borderColor:`rgba(${Y.primaryRgb}, 0.22)`,background:`rgba(${Y.primaryRgb}, 0.075)`,color:Y.primary},className:"jsx-39c38f012cc9c82a flex items-start gap-2.5 rounded-2xl border p-2.5 text-xs",children:[(0,r.jsxs)("svg",{fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,className:"jsx-39c38f012cc9c82a mt-0.5 h-4 w-4 shrink-0",children:[(0,r.jsx)("circle",{cx:"12",cy:"12",r:"10",className:"jsx-39c38f012cc9c82a"}),(0,r.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M12 16v-4m0-4h.01",className:"jsx-39c38f012cc9c82a"})]}),(0,r.jsx)("span",{className:"jsx-39c38f012cc9c82a",children:"Password/OIDC login đều khả dụng."})]}),j&&(0,r.jsxs)("div",{className:"jsx-39c38f012cc9c82a flex items-start gap-2.5 rounded-2xl border border-red-200 bg-red-50 p-2.5 text-sm text-red-700",children:[(0,r.jsxs)("svg",{fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,className:"jsx-39c38f012cc9c82a mt-0.5 h-4 w-4 shrink-0",children:[(0,r.jsx)("circle",{cx:"12",cy:"12",r:"10",className:"jsx-39c38f012cc9c82a"}),(0,r.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M12 8v4m0 4h.01",className:"jsx-39c38f012cc9c82a"})]}),(0,r.jsx)("span",{className:"jsx-39c38f012cc9c82a",children:j})]}),k>0&&(0,r.jsxs)("div",{className:"jsx-39c38f012cc9c82a flex items-start gap-2.5 rounded-2xl border border-red-200 bg-red-50 p-2.5 text-sm text-red-700",children:[(0,r.jsxs)("svg",{fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,className:"jsx-39c38f012cc9c82a mt-0.5 h-4 w-4 shrink-0",children:[(0,r.jsx)("circle",{cx:"12",cy:"12",r:"10",className:"jsx-39c38f012cc9c82a"}),(0,r.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M12 6v6l4 2",className:"jsx-39c38f012cc9c82a"})]}),(0,r.jsxs)("span",{className:"jsx-39c38f012cc9c82a",children:["Đ\xe3 kh\xf3a. Thử lại sau ",k,"s."]})]}),v&&(0,r.jsxs)("div",{className:"jsx-39c38f012cc9c82a rounded-2xl border border-slate-200 bg-slate-50 p-2.5 text-xs text-slate-600",children:["Qu\xean mật khẩu? Mở"," ",(0,r.jsx)("span",{className:"jsx-39c38f012cc9c82a rounded bg-slate-200/70 px-1.5 py-0.5 font-mono text-[11px]",children:"bluerouter"})," ","CLI tr\xean host → Settings → Reset Password to Default."]}),(0,r.jsx)("button",{type:"submit",disabled:R||k>0,className:"jsx-39c38f012cc9c82a theme-submit-btn shimmer-btn relative mt-1 flex w-full items-center justify-center gap-2 overflow-hidden rounded-2xl px-4 py-3 text-sm font-black uppercase tracking-[0.06em] text-white transition-all hover:-translate-y-0.5 active:translate-y-0 disabled:cursor-not-allowed disabled:opacity-60 disabled:hover:translate-y-0",children:(0,r.jsx)("span",{className:"jsx-39c38f012cc9c82a relative z-10 flex items-center gap-2",children:R?(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)("svg",{fill:"none",viewBox:"0 0 24 24",className:"jsx-39c38f012cc9c82a h-4 w-4 animate-spin",children:[(0,r.jsx)("circle",{cx:"12",cy:"12",r:"10",stroke:"currentColor",strokeWidth:"3",className:"jsx-39c38f012cc9c82a opacity-25"}),(0,r.jsx)("path",{fill:"currentColor",d:"M4 12a8 8 0 0 1 8-8V0C5.4 0 0 5.4 0 12h4Z",className:"jsx-39c38f012cc9c82a opacity-75"})]}),"Đang đăng nhập..."]}):k>0?(0,r.jsxs)(r.Fragment,{children:["Đợi ",k,"s"]}):(0,r.jsxs)(r.Fragment,{children:["Đăng nhập",(0,r.jsx)("svg",{fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2.5,strokeLinecap:"round",strokeLinejoin:"round",className:"jsx-39c38f012cc9c82a h-4 w-4",children:(0,r.jsx)("path",{d:"M5 12h14M13 5l7 7-7 7",className:"jsx-39c38f012cc9c82a"})})]})})}),!1===M&&(0,r.jsx)("p",{className:"jsx-39c38f012cc9c82a text-center text-xs text-slate-500",children:"Chưa c\xf3 custom password. Default password vẫn d\xf9ng được cho đến khi bạn đổi."})]}):j&&(0,r.jsx)("div",{className:"jsx-39c38f012cc9c82a rounded-2xl border border-red-200 bg-red-50 p-3 text-sm text-red-700",children:j})]})]})]})]}),(0,r.jsxs)("div",{style:{animationDelay:"0.15s"},className:"jsx-39c38f012cc9c82a relative z-10 mt-6 fade-up",children:[(0,r.jsxs)("div",{className:"jsx-39c38f012cc9c82a mb-4 flex items-center justify-between",children:[(0,r.jsxs)("div",{className:"jsx-39c38f012cc9c82a flex items-center gap-3",children:[(0,r.jsx)("span",{style:{background:`linear-gradient(90deg, transparent, rgba(${Y.accentRgb}, 0.62))`},className:"jsx-39c38f012cc9c82a h-px w-8"}),(0,r.jsx)("span",{style:{color:Y.heroSubtitle},className:"jsx-39c38f012cc9c82a text-[11px] font-black uppercase tracking-[0.22em]",children:"Hệ thống nội bộ"}),(0,r.jsx)("span",{style:{background:`linear-gradient(270deg, transparent, rgba(${Y.accentRgb}, 0.62))`},className:"jsx-39c38f012cc9c82a h-px w-8"})]}),(0,r.jsx)("span",{className:"jsx-39c38f012cc9c82a text-[11px] text-white/40",children:"Truy cập nhanh c\xe1c dịch vụ"})]}),(0,r.jsx)("div",{className:"jsx-39c38f012cc9c82a grid gap-3 sm:grid-cols-2 lg:grid-cols-5",children:ee.map(e=>(0,r.jsx)(m,{service:e},e.badge))})]}),(0,r.jsxs)("footer",{className:"jsx-39c38f012cc9c82a relative z-10 mt-6 flex flex-col items-center justify-between gap-3 border-t border-white/10 pt-5 text-xs text-white/40 sm:flex-row",children:[(0,r.jsxs)("div",{className:"jsx-39c38f012cc9c82a flex items-center gap-3",children:[(0,r.jsx)("div",{className:"jsx-39c38f012cc9c82a theme-footer-mark flex h-8 w-8 items-center justify-center rounded-xl text-white shadow-lg ring-1 ring-white/10",children:(0,r.jsxs)("svg",{fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2.2,strokeLinecap:"round",strokeLinejoin:"round",className:"jsx-39c38f012cc9c82a h-4 w-4",children:[(0,r.jsx)("path",{d:"M12 3.75 19.5 8v8L12 20.25 4.5 16V8L12 3.75Z",className:"jsx-39c38f012cc9c82a"}),(0,r.jsx)("path",{d:"M12 8v8",className:"jsx-39c38f012cc9c82a"}),(0,r.jsx)("path",{d:"m7.5 10.25 4.5 2.5 4.5-2.5",className:"jsx-39c38f012cc9c82a"})]})}),(0,r.jsxs)("div",{className:"jsx-39c38f012cc9c82a leading-tight",children:[(0,r.jsx)("div",{className:"jsx-39c38f012cc9c82a font-semibold text-white/70",children:"Fujinet Internal Portal"}),(0,r.jsx)("div",{className:"jsx-39c38f012cc9c82a text-[11px] text-white/40",children:"AI Workspace \xb7 Meeting \xb7 Support \xb7 Resource"})]})]}),(0,r.jsxs)("div",{className:"jsx-39c38f012cc9c82a flex flex-col items-center gap-3 sm:flex-row",children:[(0,r.jsxs)("div",{className:"jsx-39c38f012cc9c82a theme-style-panel flex items-center gap-2 rounded-2xl px-2.5 py-2 text-[11px] text-white/50 backdrop-blur-md",children:[(0,r.jsx)("span",{style:{background:Y.accent,boxShadow:`0 0 18px rgba(${Y.accentRgb}, 0.75)`},className:"jsx-39c38f012cc9c82a h-2.5 w-2.5 rounded-full shadow-lg"}),(0,r.jsx)("span",{className:"jsx-39c38f012cc9c82a hidden font-semibold text-white/55 md:inline",children:"Style"}),(0,r.jsxs)("div",{role:"radiogroup","aria-label":"Chọn phong c\xe1ch m\xe0u sắc",className:"jsx-39c38f012cc9c82a theme-style-palette",children:[(0,r.jsx)("button",{type:"button",role:"radio","aria-checked":"auto"===D,"aria-label":`Auto theo ng\xe0y - ${Y.dayLabel} - ${Y.name}`,title:`Auto \xb7 ${Y.dayLabel} \xb7 ${Y.name}`,onClick:()=>ea("auto"),style:{background:`conic-gradient(from 135deg, ${Y.primary}, ${Y.secondary}, ${Y.accent}, ${Y.primary})`},className:`jsx-39c38f012cc9c82a theme-style-swatch theme-style-swatch-auto ${"auto"===D?"is-active":""}`,children:(0,r.jsx)("span",{className:"jsx-39c38f012cc9c82a",children:"A"})}),f.map(e=>{let a=D===e.id;return(0,r.jsx)("button",{type:"button",role:"radio","aria-checked":a,"aria-label":`${e.dayLabel} - ${e.name}`,title:`${e.dayLabel} \xb7 ${e.name}`,onClick:()=>ea(e.id),style:{background:`linear-gradient(135deg, ${e.primary} 0%, ${e.secondary} 52%, ${e.accent} 100%)`},className:`jsx-39c38f012cc9c82a theme-style-swatch ${a?"is-active":""}`},e.id)})]})]}),(0,r.jsxs)("div",{className:"jsx-39c38f012cc9c82a text-white/50",children:["\xa9 2026 Fujinet Systems."," ",(0,r.jsx)("a",{href:"mailto:itadmin@fujinet.net",className:"jsx-39c38f012cc9c82a theme-footer-link font-semibold",children:"Contact: itadmin@fujinet.net"})]})]})]})]})]})}}},e=>{e.O(0,[5242,5263,8441,3794,7358],()=>e(e.s=33796)),_N_E=e.O()}]);
|
|
Binary file
|
|
Binary file
|
package/app/package.json
CHANGED
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[3538],{43503:(e,t,s)=>{"use strict";s.d(t,{default:()=>c});var n=s(95155),r=s(12115),l=s(35497),a=s(57250);function i(e,t){return t.find(t=>t.id===e)?.name||e}function d(e){return String(e||"").trim().toLowerCase()}function o(e){return Array.isArray(e?.importedModels)?e.importedModels:[]}function c(){let[e,t]=(0,r.useState)(!0),[s,c]=(0,r.useState)(!1),[x,m]=(0,r.useState)(""),[h,u]=(0,r.useState)(""),[p,b]=(0,r.useState)(""),[g,j]=(0,r.useState)(!1),[f,y]=(0,r.useState)([]),[v,N]=(0,r.useState)([]),[k,w]=(0,r.useState)(null),[C,A]=(0,r.useState)(null),[I,M]=(0,r.useState)(""),[S,O]=(0,r.useState)(null),[T,$]=(0,r.useState)([]),[E,R]=(0,r.useState)(!1),[K,q]=(0,r.useState)(""),[z,P]=(0,r.useState)([]),[F,L]=(0,r.useState)(!1),[U,B]=(0,r.useState)(!1),[D,_]=(0,r.useState)({}),[G,H]=(0,r.useState)(""),[J,X]=(0,r.useState)({}),[Z,V]=(0,r.useState)(null),[W,Q]=(0,r.useState)({}),[Y,ee]=(0,r.useState)(""),[et,es]=(0,r.useState)(""),[en,er]=(0,r.useState)({}),[el,ea]=(0,r.useState)({}),[ei,ed]=(0,r.useState)(""),[eo,ec]=(0,r.useState)(!1),[ex,em]=(0,r.useState)(!0),eh=(0,r.useCallback)(async()=>{t(!0),m("");try{let e=await fetch("/api/personal-cloud-providers",{cache:"no-store"}),t=await e.json().catch(()=>({}));if(!e.ok)throw Error(t.error||"Kh\xf4ng tải được personal cloud providers");b(t.userId||""),j(!0===t.isAdmin),y(t.providers||[]),N(t.connections||[]),em(!1!==t.globalRtkEnabled),er(t.routing||{}),ea(e=>{let s={...e};for(let[e,n]of Object.entries(t.routing||{}))s[e]={...n};return s}),H(e=>e||t.userId||"")}catch(e){m(e.message||"Kh\xf4ng tải được personal cloud providers")}finally{t(!1)}},[]),eu=(0,r.useCallback)(async()=>{if(g){B(!0);try{let e=await fetch("/api/personal-cloud-providers/permissions",{cache:"no-store"}),t=await e.json().catch(()=>({}));if(!e.ok)throw Error(t.error||"Kh\xf4ng tải được quyền OAuth");_(t.permissions||{})}catch(e){m(e.message||"Kh\xf4ng tải được quyền OAuth")}finally{B(!1)}}},[g]);(0,r.useEffect)(()=>{eh()},[eh]),(0,r.useEffect)(()=>{g&&eu()},[g,eu]),(0,r.useEffect)(()=>{let e=D[d(G)]||{},t={};for(let s of f)t[s.id]=!0===e[s.id];X(t)},[G,D,f]);let ep=(0,r.useMemo)(()=>{let e=d(p);return T.filter(t=>d(t.ownerUser||t.createdByUser||p)===e)},[T,p]),eb=(0,r.useMemo)(()=>Object.entries(D).map(([e,t])=>{let s=f.filter(e=>t?.[e.id]===!0);return{userId:e,providerState:t||{},enabledProviders:s}}).filter(e=>e.enabledProviders.length>0).sort((e,t)=>e.userId.localeCompare(t.userId)),[D,f]),eg=async()=>{w(null),u("OAuth account đ\xe3 được th\xeam. Model sẽ được import tự động nếu provider hỗ trợ."),await eh()},ej=async(e,t)=>{m(""),u("");try{let s=await fetch(`/api/personal-cloud-providers/${encodeURIComponent(e)}`,{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)}),n=await s.json().catch(()=>({}));if(!s.ok)throw Error(n.error||"Kh\xf4ng cập nhật được connection");await eh()}catch(e){m(e.message||"Kh\xf4ng cập nhật được connection")}},ef=async e=>{m(""),u(""),M(e.id);try{let t=await fetch(`/api/personal-cloud-providers/${encodeURIComponent(e.id)}/import-models`,{method:"POST"}),s=await t.json().catch(()=>({}));if(!t.ok)throw Error(s.error||"Kh\xf4ng import được model");N(t=>t.map(t=>t.id===e.id?{...t,availableModels:s.models||[],importedModels:s.importedModels||[],modelImport:s.modelImport||t.modelImport}:t)),V(t=>t?.id===e.id?{...t,availableModels:s.models||[],importedModels:s.importedModels||[],modelImport:s.modelImport||t.modelImport}:t);let n=s.modelImport?.source==="provider"?"provider":"catalog fallback";u(`Đ\xe3 cập nhật ${s.models?.length||0} model từ ${n}.`)}catch(e){m(e.message||"Kh\xf4ng import được model")}finally{M("")}},ey=async()=>{R(!0);try{let e=await fetch("/api/keys?pageSize=100&status=active",{cache:"no-store"}),t=await e.json().catch(()=>({}));if(!e.ok)throw Error(t.error||"Kh\xf4ng tải được API keys");$(t.keys||[]);let s=d(p||t.userId),n=(t.keys||[]).find(e=>d(e.ownerUser||e.createdByUser||t.userId)===s);q(e=>e||n?.id||"")}catch(e){m(e.message||"Kh\xf4ng tải được API keys")}finally{R(!1)}},ev=async e=>{let t,s;m(""),u(""),O(e),P((s=(t=o(e)).filter(e=>"llm"===(e.type||"llm")).slice(0,3).map(e=>e.routeModel).filter(Boolean)).length>0?s:t.slice(0,3).map(e=>e.routeModel).filter(Boolean)),q(""),await ey()},eN=async()=>{if(!S)return;if(!K)return void m("Chọn API key cần th\xeam model.");let e=Array.from(new Set((Array.isArray(z)?z:[]).map(e=>String(e||"").trim()).filter(Boolean)));if(0===e.length)return void m("Chọn \xedt nhất một model.");L(!0),m(""),u("");try{let t=await fetch(`/api/personal-cloud-providers/${encodeURIComponent(S.id)}/api-key-models`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKeyId:K,models:e})}),s=await t.json().catch(()=>({}));if(!t.ok)throw Error(s.error||"Kh\xf4ng th\xeam được model v\xe0o API key");O(null),u(`Đ\xe3 th\xeam ${s.addedModels?.length||e.length} model v\xe0o API key ${s.key?.name||""}.`)}catch(e){m(e.message||"Kh\xf4ng th\xeam được model v\xe0o API key")}finally{L(!1)}},ek=async()=>{if(C){m(""),u("");try{let e=await fetch(`/api/personal-cloud-providers/${encodeURIComponent(C.id)}`,{method:"DELETE"}),t=await e.json().catch(()=>({}));if(!e.ok)throw Error(t.error||"Kh\xf4ng x\xf3a được connection");A(null),await eh()}catch(e){m(e.message||"Kh\xf4ng x\xf3a được connection")}}},ew=async(e,t)=>{if(e?.id&&t?.routeModel){m(""),ee(t.routeModel),Q(e=>({...e,[t.routeModel]:{...e[t.routeModel]||{},loading:!0}}));try{let s=`/api/personal-cloud-providers/${encodeURIComponent(e.id)}/models/${t.routeModel.split("/").map(encodeURIComponent).join("/")}`,n=await fetch(s,{method:"POST"}),r=await n.json().catch(()=>({})),l={ok:r?.ok===!0,status:r?.status||n.status,text:r?.text||"",error:r?.error||(n.ok?"":"Test failed"),latencyMs:r?.latencyMs||0};Q(e=>({...e,[t.routeModel]:l}))}catch(e){Q(s=>({...s,[t.routeModel]:{ok:!1,error:e.message||"Test failed"}}))}finally{ee("")}}},eC=async(e,t)=>{if(e?.id&&t?.routeModel&&window.confirm(`X\xf3a model ${t.routeModel} khỏi connection ${e.name||e.id}?`)){m(""),u(""),es(t.routeModel);try{let s=`/api/personal-cloud-providers/${encodeURIComponent(e.id)}/models/${t.routeModel.split("/").map(encodeURIComponent).join("/")}`,n=await fetch(s,{method:"DELETE"}),r=await n.json().catch(()=>({}));if(!n.ok)throw Error(r?.error||"Kh\xf4ng x\xf3a được model");(e=>{if(!e?.connectionId&&!e?.id)return;let t=e.connectionId||e.id;N(s=>s.map(s=>s.id===t?{...s,importedModels:Array.isArray(e.importedModels)?e.importedModels:s.importedModels,availableModels:Array.isArray(e.models)?e.models:Array.isArray(e.availableModels)?e.availableModels:s.availableModels,modelImport:e.modelImport||s.modelImport}:s)),V(s=>s?.id===t?{...s,importedModels:Array.isArray(e.importedModels)?e.importedModels:s.importedModels,availableModels:Array.isArray(e.models)?e.models:Array.isArray(e.availableModels)?e.availableModels:s.availableModels,modelImport:e.modelImport||s.modelImport}:s)})(r),Q(e=>{let s={...e};return delete s[t.routeModel],s}),u(`Đ\xe3 x\xf3a model ${t.routeModel}.`)}catch(e){m(e.message||"Kh\xf4ng x\xf3a được model")}finally{es("")}}},eA=(e,t)=>{ea(s=>{let n={...s[e]||{},...t};for(let e of Object.keys(n))(""===n[e]||void 0===n[e])&&delete n[e];return{...s,[e]:n}})},eI=async e=>{m(""),u(""),ed(e);try{let t=el[e]||{},s={providerId:e,override:{fallbackStrategy:t.fallbackStrategy||"",stickyRoundRobinLimit:t.stickyRoundRobinLimit,stickyScope:t.stickyScope||"",stickyTtlMinutes:t.stickyTtlMinutes,stickyFallbackToClientIp:t.stickyFallbackToClientIp,stickyRebindOnFailure:t.stickyRebindOnFailure,stickyRebindFailureThreshold:t.stickyRebindFailureThreshold}},n=await fetch("/api/personal-cloud-providers/routing",{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)}),r=await n.json().catch(()=>({}));if(!n.ok)throw Error(r?.error||"Kh\xf4ng lưu được routing");er(r.routing||{}),u(`Đ\xe3 cập nhật routing cho ${e}.`)}catch(e){m(e.message||"Kh\xf4ng lưu được routing")}finally{ed("")}},eM=async e=>{m(""),u(""),ed(e);try{let t=await fetch(`/api/personal-cloud-providers/routing?providerId=${encodeURIComponent(e)}`,{method:"DELETE"}),s=await t.json().catch(()=>({}));if(!t.ok)throw Error(s?.error||"Kh\xf4ng reset được routing");er(s.routing||{}),ea(t=>{let s={...t};return delete s[e],s}),u(`Đ\xe3 reset ${e} về ch\xednh s\xe1ch mặc định.`)}catch(e){m(e.message||"Kh\xf4ng reset được routing")}finally{ed("")}},eS=async()=>{let e=d(G);if(!e)return void m("Nhập username/email cần cấp quyền.");c(!0),m(""),u("");try{let t=await fetch("/api/personal-cloud-providers/permissions",{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify({userId:e,providers:J})}),s=await t.json().catch(()=>({}));if(!t.ok)throw Error(s.error||"Kh\xf4ng lưu được quyền OAuth");_(s.permissions||{});let n=s.user?.id||e;n!==e&&H(n),u(`Đ\xe3 lưu quyền OAuth cho ${n}.`),await eh()}catch(e){m(e.message||"Kh\xf4ng lưu được quyền OAuth")}finally{c(!1)}},eO=async e=>{let t=d(e);if(t&&window.confirm(`Thu hồi to\xe0n bộ quyền OAuth provider của ${t}? OAuth account của user n\xe0y sẽ bị X\xd3A hẳn (token, model đ\xe3 import) v\xe0 model tương ứng sẽ bị gỡ khỏi mọi API key đ\xe3 g\xe1n. H\xe0nh động n\xe0y kh\xf4ng thể ho\xe0n t\xe1c.`)){c(!0),m(""),u("");try{let e=await fetch(`/api/personal-cloud-providers/permissions?userId=${encodeURIComponent(t)}`,{method:"DELETE"}),s=await e.json().catch(()=>({}));if(!e.ok)throw Error(s.error||"Kh\xf4ng thu hồi được quyền OAuth");_(s.permissions||{}),d(G)===t&&H(""),u(`Đ\xe3 thu hồi quyền v\xe0 x\xf3a OAuth account của ${t}.`),await eh()}catch(e){m(e.message||"Kh\xf4ng thu hồi được quyền OAuth")}finally{c(!1)}}},eT=k?function(e={}){return{id:e.id,name:e.name||e.id,icon:e.icon||"cloud",color:e.color||"#64748b",website:e.website||"",notice:e.notice||null,deprecationNotice:e.deprecationNotice||"",serviceKinds:e.serviceKinds||["llm"]}}(k):null,e$=g?f:f.filter(e=>e.enabled),eE=o(S),eR=S?.modelImport||{},eK=o(Z);return(0,n.jsxs)("div",{className:"space-y-6",children:[(0,n.jsx)("div",{children:(0,n.jsxs)("div",{className:"flex flex-col gap-3 md:flex-row md:items-start md:justify-between",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("h1",{className:"text-2xl font-semibold text-text-main",children:"Personal Cloud Providers"}),(0,n.jsx)("p",{className:"mt-1 text-sm text-text-muted",children:"Kết nối OAuth c\xe1 nh\xe2n cho Claude Code, OpenAI Codex v\xe0 Antigravity. Account c\xe1 nh\xe2n chỉ owner nh\xecn thấy, chỉ API key của owner được d\xf9ng. Cột RTK cho ph\xe9p override ri\xeang từng account (Lu\xf4n ON / Lu\xf4n OFF) bất kể cấu h\xecnh RTK global ở /dashboard/endpoint đang on hay off — để trống th\xec theo global."})]}),(0,n.jsxs)("div",{className:"rounded-2xl border border-border bg-surface px-4 py-3 text-sm",children:[(0,n.jsx)("div",{className:"text-xs uppercase tracking-wide text-text-muted",children:"Current user"}),(0,n.jsx)("div",{className:"mt-1 break-all font-mono text-text-main",children:p||"—"})]})]})}),x?(0,n.jsx)("div",{className:"rounded-2xl border border-red-500/30 bg-red-500/10 px-4 py-3 text-sm text-red-700 dark:text-red-300",children:x}):null,h?(0,n.jsx)("div",{className:"rounded-2xl border border-green-500/30 bg-green-500/10 px-4 py-3 text-sm text-green-700 dark:text-green-300",children:h}):null,(0,n.jsx)("div",{className:"grid gap-4 lg:grid-cols-3",children:0===f.length?(0,n.jsx)("div",{className:"rounded-2xl border border-dashed border-border p-8 text-center text-sm text-text-muted lg:col-span-3",children:"Admin chưa cấp quyền personal OAuth provider n\xe0o cho user n\xe0y."}):f.map(e=>(0,n.jsxs)(l.Zp,{className:"space-y-4",children:[(0,n.jsxs)("div",{className:"flex items-start gap-3",children:[(0,n.jsx)("span",{className:"inline-flex size-10 shrink-0 items-center justify-center rounded-xl",style:{backgroundColor:`${e.color||"#64748b"}22`},children:(0,n.jsx)(a.A,{src:`/providers/${e.id}.png`,alt:e.name,size:34,className:"max-h-[34px] max-w-[34px] rounded-lg object-contain",fallbackText:e.id.slice(0,2).toUpperCase(),fallbackColor:e.color||"#64748b"})}),(0,n.jsxs)("div",{className:"min-w-0 flex-1",children:[(0,n.jsxs)("div",{className:"flex items-center gap-2",children:[(0,n.jsx)("h2",{className:"font-semibold text-text-main",children:e.name}),e.enabled?(0,n.jsx)(l.Ex,{variant:"success",size:"sm",children:"Enabled"}):(0,n.jsx)(l.Ex,{variant:"warning",size:"sm",children:"Locked"})]}),(0,n.jsx)("p",{className:"mt-1 text-xs text-text-muted",children:e.enabled?"Được admin cấp quyền, c\xf3 thể add OAuth account c\xe1 nh\xe2n.":"Admin chưa cấp quyền cho user n\xe0y."})]})]}),e.deprecationNotice?(0,n.jsx)("p",{className:"rounded-xl border border-amber-500/30 bg-amber-500/10 p-3 text-xs text-amber-700 dark:text-amber-300",children:e.deprecationNotice}):null,(0,n.jsxs)(l.$n,{fullWidth:!0,disabled:!e.enabled,onClick:()=>{e.enabled&&w(e)},icon:"add_link",children:["Add ",e.name," account"]})]},e.id))}),(0,n.jsxs)(l.Zp,{className:"space-y-4",children:[(0,n.jsxs)("div",{className:"flex flex-col gap-2 md:flex-row md:items-center md:justify-between",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"My personal accounts"}),(0,n.jsx)("p",{className:"text-sm text-text-muted",children:"OAuth xong sẽ tự import model nếu provider hỗ trợ. Nếu kh\xf4ng gọi được endpoint model, hệ thống d\xf9ng catalog fallback để user vẫn chọn được model."})]}),(0,n.jsx)(l.$n,{variant:"outline",size:"sm",onClick:eh,loading:e,icon:"refresh",children:"Refresh"})]}),e?(0,n.jsx)("div",{className:"rounded-2xl border border-dashed border-border p-8 text-center text-sm text-text-muted",children:"Đang tải..."}):0===v.length?(0,n.jsx)("div",{className:"rounded-2xl border border-dashed border-border p-8 text-center text-sm text-text-muted",children:"Chưa c\xf3 personal OAuth account n\xe0o."}):(0,n.jsx)("div",{className:"overflow-x-auto rounded-2xl border border-border",children:(0,n.jsxs)("table",{className:"min-w-full divide-y divide-border text-sm",children:[(0,n.jsx)("thead",{className:"bg-surface/80 text-left text-xs uppercase tracking-wide text-text-muted",children:(0,n.jsxs)("tr",{children:[(0,n.jsx)("th",{className:"px-4 py-3 font-medium",children:"Connection"}),(0,n.jsx)("th",{className:"px-4 py-3 font-medium",children:"Provider"}),(0,n.jsx)("th",{className:"px-4 py-3 font-medium",children:"Account"}),(0,n.jsx)("th",{className:"px-4 py-3 font-medium",children:"Models"}),(0,n.jsx)("th",{className:"px-4 py-3 font-medium",children:"Created"}),(0,n.jsx)("th",{className:"px-4 py-3 font-medium",children:"Active"}),(0,n.jsx)("th",{className:"px-4 py-3 font-medium",children:(0,n.jsxs)("span",{className:"inline-flex items-center gap-1.5",children:["RTK (Token Savings)",(0,n.jsxs)(l.Ex,{variant:ex?"success":"default",size:"sm",className:"normal-case",children:["Global: ",ex?"ON":"OFF"]}),(0,n.jsx)("button",{type:"button",onClick:()=>ec(!0),title:"RTK l\xe0 g\xec? Bấm để xem giải th\xedch",className:"inline-flex size-4 shrink-0 items-center justify-center rounded-full border border-border text-[10px] font-bold normal-case text-text-muted transition-colors hover:border-brand-500 hover:text-brand-600",children:"?"})]})}),(0,n.jsx)("th",{className:"px-4 py-3 text-right font-medium",children:"Actions"})]})}),(0,n.jsx)("tbody",{className:"divide-y divide-border bg-background",children:v.map(e=>{let t=Array.isArray(e?.availableModels)?e.availableModels:[],s=e.modelImport||{};return(0,n.jsxs)("tr",{className:"align-top hover:bg-surface/50",children:[(0,n.jsxs)("td",{className:"px-4 py-4",children:[(0,n.jsx)("div",{className:"font-medium text-text-main",children:e.name||e.id}),(0,n.jsx)("div",{className:"mt-1 font-mono text-xs text-text-muted",children:e.id})]}),(0,n.jsx)("td",{className:"px-4 py-4",children:(0,n.jsxs)("div",{className:"flex items-center gap-2",children:[(0,n.jsx)(a.A,{src:`/providers/${e.provider}.png`,alt:e.provider,size:24,className:"max-h-[24px] max-w-[24px] rounded object-contain",fallbackText:e.provider.slice(0,2).toUpperCase()}),(0,n.jsx)("span",{children:i(e.provider,f)})]})}),(0,n.jsxs)("td",{className:"px-4 py-4",children:[(0,n.jsx)("div",{className:"break-all text-text-main",children:e.email||e.displayName||"—"}),(0,n.jsxs)("div",{className:"mt-1 break-all text-xs text-text-muted",children:["Owner: ",e.ownerUser||p||"—"]})]}),(0,n.jsxs)("td",{className:"px-4 py-4",children:[(0,n.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[function(e={}){return"provider"===(e.source||"catalog")?(0,n.jsx)(l.Ex,{variant:"success",size:"sm",children:"Imported"}):(0,n.jsx)(l.Ex,{variant:"warning",size:"sm",children:"Catalog"})}(s),(0,n.jsxs)("span",{className:"text-xs text-text-muted",children:[t.length," model(s)"]})]}),s.warning?(0,n.jsx)("div",{className:"mt-1 max-w-[320px] truncate text-xs text-amber-600 dark:text-amber-300",title:s.warning,children:s.warning}):null,t.length>0?(0,n.jsxs)("div",{className:"mt-2 flex max-w-[360px] flex-wrap gap-1",children:[t.slice(0,4).map(e=>(0,n.jsx)("span",{className:"rounded-full border border-border bg-surface px-2 py-0.5 font-mono text-[11px] text-text-muted",children:e.routeModel},e.routeModel)),t.length>4?(0,n.jsxs)("span",{className:"rounded-full border border-border bg-surface px-2 py-0.5 text-[11px] text-text-muted",children:["+",t.length-4]}):null]}):null]}),(0,n.jsx)("td",{className:"px-4 py-4 text-xs text-text-muted",children:function(e){if(!e)return"—";try{return new Intl.DateTimeFormat("vi-VN",{dateStyle:"short",timeStyle:"short"}).format(new Date(e))}catch{return e}}(e.createdAt)}),(0,n.jsx)("td",{className:"px-4 py-4",children:(0,n.jsx)(l.lM,{checked:!1!==e.isActive,onChange:t=>ej(e.id,{isActive:t})})}),(0,n.jsx)("td",{className:"px-4 py-4",children:(0,n.jsxs)("select",{value:!0===e.rtkEnabled?"on":!1===e.rtkEnabled?"off":"inherit",onChange:t=>{let s=t.target.value;ej(e.id,{rtkEnabled:"inherit"===s?null:"on"===s})},className:"h-9 w-full min-w-[140px] rounded-xl border border-border bg-background px-2 text-xs text-text-main outline-none focus:border-brand-500",children:[(0,n.jsx)("option",{value:"inherit",children:"Theo global"}),(0,n.jsx)("option",{value:"on",children:"Lu\xf4n ON"}),(0,n.jsx)("option",{value:"off",children:"Lu\xf4n OFF"})]})}),(0,n.jsx)("td",{className:"px-4 py-4",children:(0,n.jsxs)("div",{className:"flex flex-wrap justify-end gap-2",children:[(0,n.jsx)(l.$n,{variant:"outline",size:"sm",loading:I===e.id,onClick:()=>ef(e),children:"Import models"}),(0,n.jsx)(l.$n,{variant:"outline",size:"sm",disabled:0===o(e).length,onClick:()=>{m(""),u(""),V(e),Q({}),ee(""),es("")},children:"Manage models"}),(0,n.jsx)(l.$n,{variant:"secondary",size:"sm",disabled:0===o(e).length,onClick:()=>ev(e),children:"Add to API key"}),(0,n.jsx)(l.$n,{variant:"outline",size:"sm",onClick:()=>{let t;return t=window.prompt("T\xean connection mới",e.name||""),void(t?.trim()&&ej(e.id,{name:t.trim()}))},children:"Rename"}),(0,n.jsx)(l.$n,{variant:"danger",size:"sm",onClick:()=>A(e),children:"Delete"})]})})]},e.id)})})]})})]}),(0,n.jsxs)(l.Zp,{className:"space-y-4",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Routing strategy"}),(0,n.jsxs)("p",{className:"text-sm text-text-muted",children:["Khi bạn c\xf3 nhiều personal account cho c\xf9ng provider, đ\xe2y l\xe0 ch\xednh s\xe1ch chọn account cho từng request. Để trống = kế thừa ch\xednh s\xe1ch của admin ở ",(0,n.jsx)("span",{className:"font-mono",children:"/dashboard/providers/<provider>"}),"."]})]}),(0,n.jsx)("div",{className:"grid gap-4 lg:grid-cols-3",children:0===e$.length?(0,n.jsx)("div",{className:"rounded-2xl border border-dashed border-border p-6 text-center text-sm text-text-muted lg:col-span-3",children:"Bạn chưa được cấp quyền provider n\xe0o, n\xean chưa cần thiết lập routing."}):e$.map(e=>{let t=el[e.id]||{},s=en[e.id]||null,r=!s,a=t.fallbackStrategy||"",i="round-robin"===a,d=ei===e.id;return(0,n.jsxs)("div",{className:"rounded-2xl border border-border bg-surface p-4 space-y-3",children:[(0,n.jsxs)("div",{className:"flex items-center justify-between gap-2",children:[(0,n.jsxs)("div",{className:"min-w-0",children:[(0,n.jsx)("div",{className:"font-semibold text-text-main",children:e.name}),(0,n.jsx)("div",{className:"text-xs text-text-muted",children:r?"Đang kế thừa policy global":`Override active: ${s.fallbackStrategy||"inherit"}`})]}),r?(0,n.jsx)(l.Ex,{variant:"default",size:"sm",children:"Inherit"}):(0,n.jsx)(l.Ex,{variant:"success",size:"sm",children:"Override"})]}),(0,n.jsxs)("label",{className:"block text-sm",children:[(0,n.jsx)("span",{className:"mb-1 block font-medium text-text-main",children:"Strategy"}),(0,n.jsxs)("select",{value:a,onChange:t=>eA(e.id,{fallbackStrategy:t.target.value}),className:"h-10 w-full rounded-xl border border-border bg-background px-3 text-sm text-text-main outline-none focus:border-brand-500",disabled:d,children:[(0,n.jsx)("option",{value:"",children:"Inherit (use global)"}),(0,n.jsx)("option",{value:"fill-first",children:"fill-first — chạy hết account 1 mới sang account 2"}),(0,n.jsx)("option",{value:"round-robin",children:"round-robin — lu\xe2n phi\xean theo sticky limit"}),(0,n.jsx)("option",{value:"least-latency",children:"least-latency — chọn account nhanh nhất"}),(0,n.jsx)("option",{value:"p2c",children:"p2c — power-of-two-choices"})]})]}),i?(0,n.jsxs)("div",{className:"space-y-2 rounded-xl border border-border/50 bg-background/50 p-3",children:[(0,n.jsx)("div",{className:"text-xs text-text-muted",children:"Round-robin sticky params (để trống = d\xf9ng gi\xe1 trị global)"}),(0,n.jsxs)("label",{className:"block text-xs",children:[(0,n.jsx)("span",{className:"mb-1 block text-text-muted",children:"Sticky limit (số request li\xean tiếp trước khi rotate)"}),(0,n.jsx)(l.pd,{type:"number",min:1,value:t.stickyRoundRobinLimit??"",onChange:t=>eA(e.id,{stickyRoundRobinLimit:t.target.value?Number(t.target.value):void 0}),placeholder:"v\xed dụ 3",disabled:d})]}),(0,n.jsxs)("label",{className:"block text-xs",children:[(0,n.jsx)("span",{className:"mb-1 block text-text-muted",children:"Sticky scope"}),(0,n.jsxs)("select",{value:t.stickyScope||"",onChange:t=>eA(e.id,{stickyScope:t.target.value}),className:"h-9 w-full rounded-xl border border-border bg-background px-3 text-xs text-text-main outline-none focus:border-brand-500",disabled:d,children:[(0,n.jsx)("option",{value:"",children:"(inherit)"}),(0,n.jsx)("option",{value:"global",children:"global — rotate cho mọi request"}),(0,n.jsx)("option",{value:"client_ip",children:"client_ip — sticky theo IP"}),(0,n.jsx)("option",{value:"client_session",children:"client_session — sticky theo CLI session"})]})]}),(0,n.jsxs)("label",{className:"block text-xs",children:[(0,n.jsx)("span",{className:"mb-1 block text-text-muted",children:"Sticky TTL (ph\xfat)"}),(0,n.jsx)(l.pd,{type:"number",min:1,value:t.stickyTtlMinutes??"",onChange:t=>eA(e.id,{stickyTtlMinutes:t.target.value?Number(t.target.value):void 0}),placeholder:"v\xed dụ 120",disabled:d})]})]}):null,(0,n.jsxs)("div",{className:"flex flex-wrap gap-2 pt-1",children:[(0,n.jsx)(l.$n,{size:"sm",loading:d,onClick:()=>eI(e.id),children:"Save"}),(0,n.jsx)(l.$n,{size:"sm",variant:"ghost",disabled:d||r,onClick:()=>eM(e.id),children:"Reset to inherit"})]})]},e.id)})})]}),g?(0,n.jsxs)(l.Zp,{className:"space-y-4",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Admin: OAuth provider access"}),(0,n.jsx)("p",{className:"text-sm text-text-muted",children:"Default l\xe0 kh\xf4ng c\xf3 quyền. Nhập username/email rồi bật provider được ph\xe9p add personal account."})]}),(0,n.jsxs)("div",{className:"grid gap-3 md:grid-cols-[minmax(0,1fr)_auto] md:items-end",children:[(0,n.jsx)(l.pd,{label:"User ID / Email",value:G,onChange:e=>H(e.target.value),placeholder:"anh-tct hoặc anh-tct@fujinet.net"}),(0,n.jsx)(l.$n,{onClick:eS,loading:s,icon:"save",children:"Save permissions"})]}),(0,n.jsx)("div",{className:"grid gap-3 md:grid-cols-3",children:f.map(e=>(0,n.jsx)("div",{className:"rounded-2xl border border-border bg-surface p-4",children:(0,n.jsx)(l.lM,{checked:!0===J[e.id],onChange:t=>X(s=>({...s,[e.id]:t})),label:e.name,description:J[e.id]?"User được ph\xe9p add account":"User chưa được cấp quyền"})},e.id))}),(0,n.jsxs)("div",{className:"border-t border-border pt-4",children:[(0,n.jsxs)("div",{className:"mb-3 flex flex-col gap-2 md:flex-row md:items-center md:justify-between",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("h3",{className:"font-semibold text-text-main",children:"Granted OAuth Access"}),(0,n.jsx)("p",{className:"text-xs text-text-muted",children:"Danh s\xe1ch user hiện đang được cấp quyền add personal OAuth account."})]}),(0,n.jsx)(l.$n,{variant:"outline",size:"sm",onClick:eu,loading:U,icon:"refresh",children:"Refresh list"})]}),U?(0,n.jsx)("div",{className:"rounded-2xl border border-dashed border-border p-6 text-center text-sm text-text-muted",children:"Đang tải quyền..."}):0===eb.length?(0,n.jsx)("div",{className:"rounded-2xl border border-dashed border-border p-6 text-center text-sm text-text-muted",children:"Chưa c\xf3 user n\xe0o được cấp quyền OAuth provider."}):(0,n.jsx)("div",{className:"overflow-x-auto rounded-2xl border border-border",children:(0,n.jsxs)("table",{className:"min-w-full divide-y divide-border text-sm",children:[(0,n.jsx)("thead",{className:"bg-surface/80 text-left text-xs uppercase tracking-wide text-text-muted",children:(0,n.jsxs)("tr",{children:[(0,n.jsx)("th",{className:"px-4 py-3 font-medium",children:"User"}),f.map(e=>(0,n.jsx)("th",{className:"px-4 py-3 font-medium",children:e.name},e.id)),(0,n.jsx)("th",{className:"px-4 py-3 text-right font-medium",children:"Actions"})]})}),(0,n.jsx)("tbody",{className:"divide-y divide-border bg-background",children:eb.map(e=>(0,n.jsxs)("tr",{className:"hover:bg-surface/50",children:[(0,n.jsxs)("td",{className:"px-4 py-4",children:[(0,n.jsx)("div",{className:"break-all font-mono text-text-main",children:e.userId}),d(G)===e.userId?(0,n.jsx)("div",{className:"mt-1 text-xs text-brand-600 dark:text-brand-300",children:"Đang edit ở form ph\xeda tr\xean"}):null]}),f.map(t=>(0,n.jsx)("td",{className:"px-4 py-4",children:!0===e.providerState[t.id]?(0,n.jsx)(l.Ex,{variant:"success",size:"sm",children:"ON"}):(0,n.jsx)(l.Ex,{variant:"default",size:"sm",children:"OFF"})},t.id)),(0,n.jsx)("td",{className:"px-4 py-4",children:(0,n.jsxs)("div",{className:"flex flex-wrap justify-end gap-2",children:[(0,n.jsx)(l.$n,{variant:"outline",size:"sm",onClick:()=>(e=>{let t=d(e);H(t);let s=D[t]||{},n={};for(let e of f)n[e.id]=!0===s[e.id];X(n)})(e.userId),children:"Edit"}),(0,n.jsx)(l.$n,{variant:"danger",size:"sm",loading:s,onClick:()=>eO(e.userId),children:"Revoke"})]})})]},e.userId))})]})})]})]}):null,S?(0,n.jsx)(l.aF,{isOpen:!!S,onClose:()=>O(null),title:"Add models to API key",size:"full",footer:(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(l.$n,{variant:"ghost",onClick:()=>O(null),disabled:F,children:"Cancel"}),(0,n.jsx)(l.$n,{onClick:eN,loading:F,disabled:!K||0===z.length,children:"Add selected models"})]}),children:(0,n.jsxs)("div",{className:"space-y-4",children:[(0,n.jsxs)("div",{className:"rounded-2xl border border-border bg-surface p-4 text-sm",children:[(0,n.jsx)("div",{className:"font-semibold text-text-main",children:S.name||S.id}),(0,n.jsxs)("div",{className:"mt-1 text-text-muted",children:[i(S.provider,f)," \xb7 ",eE.length," imported model(s)"]}),eR.warning?(0,n.jsx)("div",{className:"mt-2 text-xs text-amber-600 dark:text-amber-300",children:eR.warning}):null,0===eE.length?(0,n.jsx)("div",{className:"mt-2 rounded-xl border border-amber-500/30 bg-amber-500/10 p-3 text-xs text-amber-700 dark:text-amber-300",children:'Chưa import được model n\xe0o từ provider. Bấm "Import models" tr\xean d\xf2ng connection trước khi g\xe1n v\xe0o API key.'}):null]}),(0,n.jsxs)("label",{className:"block text-sm",children:[(0,n.jsx)("span",{className:"mb-1 block font-medium text-text-main",children:"API key"}),(0,n.jsxs)("select",{value:K,onChange:e=>q(e.target.value),className:"h-10 w-full rounded-xl border border-border bg-background px-3 text-sm text-text-main outline-none focus:border-brand-500",disabled:E,children:[(0,n.jsx)("option",{value:"",children:E?"Đang tải API keys...":"Chọn API key"}),ep.map(e=>(0,n.jsxs)("option",{value:e.id,children:[e.name," \xb7 ",e.ownerUser||p]},e.id))]})]}),0!==ep.length||E?null:(0,n.jsx)("div",{className:"rounded-xl border border-amber-500/30 bg-amber-500/10 p-3 text-sm text-amber-700 dark:text-amber-300",children:"User n\xe0y chưa c\xf3 API key active để th\xeam model."}),(0,n.jsxs)("div",{className:"flex items-center justify-between gap-2",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("h3",{className:"font-semibold text-text-main",children:"Models"}),(0,n.jsx)("p",{className:"text-xs text-text-muted",children:"Model được lưu v\xe0o allowedModels của API key. Request sẽ route qua personal OAuth account của owner."})]}),(0,n.jsxs)("div",{className:"flex gap-2",children:[(0,n.jsx)(l.$n,{variant:"outline",size:"sm",onClick:()=>P(eE.map(e=>e.routeModel).filter(Boolean)),children:"Select all"}),(0,n.jsx)(l.$n,{variant:"ghost",size:"sm",onClick:()=>P([]),children:"Clear"})]})]}),(0,n.jsx)("div",{className:"grid gap-2 md:grid-cols-2",children:eE.map(e=>(0,n.jsxs)("label",{className:"flex cursor-pointer items-start gap-3 rounded-xl border border-border bg-background p-3 hover:bg-surface",children:[(0,n.jsx)("input",{type:"checkbox",className:"mt-1",checked:z.includes(e.routeModel),onChange:()=>{var t;return t=e.routeModel,void P(e=>e.includes(t)?e.filter(e=>e!==t):[...e,t])}}),(0,n.jsxs)("span",{className:"min-w-0 flex-1",children:[(0,n.jsx)("span",{className:"block font-medium text-text-main",children:e.name||e.id}),(0,n.jsx)("span",{className:"mt-1 block break-all font-mono text-xs text-text-muted",children:e.routeModel}),e.type&&"llm"!==e.type?(0,n.jsx)("span",{className:"mt-2 inline-flex rounded-full bg-surface px-2 py-0.5 text-[11px] text-text-muted",children:e.type}):null]})]},e.routeModel))})]})}):null,Z?(0,n.jsx)(l.aF,{isOpen:!!Z,onClose:()=>V(null),title:"Manage imported models",size:"full",footer:(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(l.$n,{variant:"ghost",onClick:()=>V(null),children:"Close"}),(0,n.jsx)(l.$n,{variant:"outline",loading:I===Z.id,onClick:()=>ef(Z),icon:"refresh",children:"Re-import from provider"})]}),children:(0,n.jsxs)("div",{className:"space-y-4",children:[(0,n.jsxs)("div",{className:"rounded-2xl border border-border bg-surface p-4 text-sm",children:[(0,n.jsx)("div",{className:"font-semibold text-text-main",children:Z.name||Z.id}),(0,n.jsxs)("div",{className:"mt-1 text-text-muted",children:[i(Z.provider,f)," \xb7 ",eK.length," imported model(s)"]}),(0,n.jsx)("div",{className:"mt-2 text-xs text-text-muted",children:'Test gửi 1 prompt "Say hello in five words" qua ch\xednh OAuth account của bạn, qua đ\xfang proxy của connection. X\xf3a model sẽ bỏ n\xf3 khỏi list importable; c\xe1c API key đ\xe3 gắn model n\xe0y kh\xf4ng bị thay đổi (request đến model đ\xf3 sẽ do provider ph\xeda tr\xean quyết định chấp nhận hay kh\xf4ng).'})]}),0===eK.length?(0,n.jsx)("div",{className:"rounded-2xl border border-dashed border-border p-8 text-center text-sm text-text-muted",children:'Chưa c\xf3 model n\xe0o được import. Bấm "Re-import from provider".'}):(0,n.jsx)("div",{className:"overflow-x-auto rounded-2xl border border-border",children:(0,n.jsxs)("table",{className:"min-w-full divide-y divide-border text-sm",children:[(0,n.jsx)("thead",{className:"bg-surface/80 text-left text-xs uppercase tracking-wide text-text-muted",children:(0,n.jsxs)("tr",{children:[(0,n.jsx)("th",{className:"px-4 py-3 font-medium",children:"Model"}),(0,n.jsx)("th",{className:"px-4 py-3 font-medium",children:"Route ID"}),(0,n.jsx)("th",{className:"px-4 py-3 font-medium",children:"Test result"}),(0,n.jsx)("th",{className:"px-4 py-3 text-right font-medium",children:"Actions"})]})}),(0,n.jsx)("tbody",{className:"divide-y divide-border bg-background",children:eK.map(e=>{let t=W[e.routeModel],s=Y===e.routeModel,r=et===e.routeModel;return(0,n.jsxs)("tr",{className:"align-top",children:[(0,n.jsxs)("td",{className:"px-4 py-3",children:[(0,n.jsx)("div",{className:"font-medium text-text-main",children:e.name||e.id}),e.type&&"llm"!==e.type?(0,n.jsx)("div",{className:"mt-1 text-xs text-text-muted",children:e.type}):null]}),(0,n.jsx)("td",{className:"px-4 py-3 font-mono text-xs text-text-muted break-all",children:e.routeModel}),(0,n.jsx)("td",{className:"px-4 py-3 text-xs",children:s?(0,n.jsx)("span",{className:"text-text-muted",children:"Đang test..."}):t?t.ok?(0,n.jsxs)("div",{className:"space-y-1",children:[(0,n.jsxs)("div",{className:"text-green-700 dark:text-green-300",children:["OK \xb7 ",t.latencyMs||0,"ms"]}),(0,n.jsx)("div",{className:"break-all text-text-muted",children:(t.text||"").slice(0,200)})]}):(0,n.jsxs)("div",{className:"space-y-1",children:[(0,n.jsxs)("div",{className:"text-red-700 dark:text-red-300",children:["FAIL \xb7 status ",t.status||"?"]}),(0,n.jsx)("div",{className:"break-all text-text-muted",children:(t.error||"").slice(0,200)})]}):(0,n.jsx)("span",{className:"text-text-muted",children:"—"})}),(0,n.jsx)("td",{className:"px-4 py-3",children:(0,n.jsxs)("div",{className:"flex flex-wrap justify-end gap-2",children:[(0,n.jsx)(l.$n,{variant:"outline",size:"sm",loading:s,disabled:r,onClick:()=>ew(Z,e),children:"Say hello"}),(0,n.jsx)(l.$n,{variant:"danger",size:"sm",loading:r,disabled:s,onClick:()=>eC(Z,e),children:"Delete"})]})})]},e.routeModel)})})]})})]})}):null,eo?(0,n.jsx)(l.aF,{isOpen:eo,onClose:()=>ec(!1),title:"RTK (Token Savings) l\xe0 g\xec?",size:"xl",footer:(0,n.jsx)(l.$n,{onClick:()=>ec(!1),children:"Đ\xe3 hiểu"}),children:(0,n.jsxs)("div",{className:"space-y-5 text-sm text-text-main",children:[(0,n.jsxs)("div",{className:"flex items-center gap-2 rounded-xl border border-border bg-surface px-3 py-2",children:[(0,n.jsx)("span",{className:"text-xs text-text-muted",children:"Global RTK hiện đang:"}),(0,n.jsx)(l.Ex,{variant:ex?"success":"default",size:"sm",children:ex?"ON":"OFF"}),(0,n.jsx)("span",{className:"text-xs text-text-muted",children:'— \xe1p dụng cho mọi account chọn "Theo global"'})]}),(0,n.jsx)("p",{className:"text-text-muted",children:"RTK l\xe0 bộ lọc n\xe9n output của tool (Bash, Grep, Glob, Read...) ngay trong request trước khi gửi l\xean model, gi\xfap giảm số token phải gửi m\xe0 kh\xf4ng l\xe0m mất th\xf4ng tin quan trọng — chỉ t\xe1c động tới phần tool output, kh\xf4ng đụng v\xe0o nội dung chat."}),(0,n.jsxs)("div",{children:[(0,n.jsx)("h3",{className:"mb-2 font-semibold text-text-main",children:"Hoạt động ra sao với CLI tool"}),(0,n.jsx)("p",{className:"text-text-muted",children:"Mỗi khi Claude Code / Codex CLI / OpenCode... gọi tool v\xe0 nhận lại output, RTK tự nhận diện định dạng quen thuộc rồi r\xfat gọn theo đ\xfang cấu tr\xfac của n\xf3:"}),(0,n.jsxs)("ul",{className:"mt-2 list-disc space-y-1 pl-5 text-text-muted",children:[(0,n.jsxs)("li",{children:[(0,n.jsx)("span",{className:"font-mono text-text-main",children:"git diff"})," — giữ v\xe0i d\xf2ng context quanh thay đổi, cắt phần hunk qu\xe1 d\xe0i"]}),(0,n.jsxs)("li",{children:[(0,n.jsx)("span",{className:"font-mono text-text-main",children:"git status"})," / ",(0,n.jsx)("span",{className:"font-mono text-text-main",children:"git log"})," — gom gọn danh s\xe1ch file thay đổi, danh s\xe1ch commit"]}),(0,n.jsxs)("li",{children:[(0,n.jsx)("span",{className:"font-mono text-text-main",children:"grep"})," / ",(0,n.jsx)("span",{className:"font-mono text-text-main",children:"find"})," — giới hạn số match hiển thị mỗi file/thư mục"]}),(0,n.jsxs)("li",{children:[(0,n.jsx)("span",{className:"font-mono text-text-main",children:"ls -la"})," / ",(0,n.jsx)("span",{className:"font-mono text-text-main",children:"tree"})," — t\xf3m tắt theo loại file, cắt c\xe2y thư mục qu\xe1 s\xe2u"]}),(0,n.jsx)("li",{children:"Build log (npm/yarn/cargo...) — chỉ giữ d\xf2ng quan trọng (lỗi, kết quả build)"}),(0,n.jsx)("li",{children:"Output d\xe0i chung kh\xf4ng r\xf5 định dạng — fallback dedup d\xf2ng lặp hoặc smart-truncate (giữ đầu + cuối)"})]})]}),(0,n.jsxs)("div",{children:[(0,n.jsx)("h3",{className:"mb-2 font-semibold text-text-main",children:"Hiệu quả thực tế"}),(0,n.jsx)("div",{className:"overflow-x-auto rounded-xl border border-border",children:(0,n.jsxs)("table",{className:"min-w-full text-xs",children:[(0,n.jsx)("thead",{className:"bg-surface/80 text-left uppercase tracking-wide text-text-muted",children:(0,n.jsxs)("tr",{children:[(0,n.jsx)("th",{className:"px-3 py-2 font-medium",children:"Loại output"}),(0,n.jsx)("th",{className:"px-3 py-2 font-medium",children:"Trước"}),(0,n.jsx)("th",{className:"px-3 py-2 font-medium",children:"Sau"}),(0,n.jsx)("th",{className:"px-3 py-2 font-medium",children:"Tiết kiệm"})]})}),(0,n.jsxs)("tbody",{className:"divide-y divide-border",children:[(0,n.jsxs)("tr",{children:[(0,n.jsx)("td",{className:"px-3 py-2 font-mono",children:"git diff"}),(0,n.jsx)("td",{className:"px-3 py-2",children:"7384B"}),(0,n.jsx)("td",{className:"px-3 py-2",children:"3894B"}),(0,n.jsx)("td",{className:"px-3 py-2 text-green-600 dark:text-green-400",children:"47.3%"})]}),(0,n.jsxs)("tr",{children:[(0,n.jsx)("td",{className:"px-3 py-2 font-mono",children:"grep -n"}),(0,n.jsx)("td",{className:"px-3 py-2",children:"3723B"}),(0,n.jsx)("td",{className:"px-3 py-2",children:"1447B"}),(0,n.jsx)("td",{className:"px-3 py-2 text-green-600 dark:text-green-400",children:"61.1%"})]}),(0,n.jsxs)("tr",{children:[(0,n.jsx)("td",{className:"px-3 py-2 font-mono",children:"find"}),(0,n.jsx)("td",{className:"px-3 py-2",children:"729B"}),(0,n.jsx)("td",{className:"px-3 py-2",children:"264B"}),(0,n.jsx)("td",{className:"px-3 py-2 text-green-600 dark:text-green-400",children:"63.8%"})]})]})]})})]}),(0,n.jsxs)("div",{children:[(0,n.jsx)("h3",{className:"mb-2 font-semibold text-text-main",children:"Khi n\xe0o KH\xd4NG bị n\xe9n"}),(0,n.jsxs)("ul",{className:"list-disc space-y-1 pl-5 text-text-muted",children:[(0,n.jsx)("li",{children:"Chat thường kh\xf4ng gọi tool — kh\xf4ng c\xf3 g\xec để n\xe9n"}),(0,n.jsx)("li",{children:"Output nhỏ hơn 500B — kh\xf4ng đ\xe1ng n\xe9n"}),(0,n.jsxs)("li",{children:["Output b\xe1o lỗi (",(0,n.jsx)("span",{className:"font-mono text-text-main",children:"is_error"}),") — lu\xf4n giữ nguy\xean để debug"]}),(0,n.jsx)("li",{children:"Output lớn hơn 10MB — bỏ qua để tr\xe1nh tốn CPU xử l\xfd"})]})]}),(0,n.jsxs)("div",{children:[(0,n.jsx)("h3",{className:"mb-2 font-semibold text-text-main",children:"Global vs từng account"}),(0,n.jsxs)("p",{className:"text-text-muted",children:["Dropdown RTK ở bảng tr\xean cho ph\xe9p override ri\xeang từng account:",(0,n.jsx)("span",{className:"font-semibold text-text-main",children:" Theo global"})," (mặc định, d\xf9ng đ\xfang setting global),",(0,n.jsx)("span",{className:"font-semibold text-text-main",children:" Lu\xf4n ON"})," hoặc",(0,n.jsx)("span",{className:"font-semibold text-text-main",children:" Lu\xf4n OFF"})," — override lu\xf4n thắng global theo cả 2 chiều, n\xean c\xf3 thể để global OFF v\xe0 chỉ bật cho account d\xf9ng CLI tool, hoặc ngược lại."]})]})]})}):null,eT?(0,n.jsx)(l.LF,{isOpen:!!k,provider:k.id,providerInfo:eT,connectionScope:"personal",onSuccess:eg,onClose:()=>w(null)}):null,C?(0,n.jsx)(l.uo,{isOpen:!!C,onClose:()=>A(null),onConfirm:ek,title:"Delete personal account",message:`X\xf3a connection ${C.name||C.id}?`,confirmText:"Delete",cancelText:"Cancel",variant:"danger"}):null]})}},47584:(e,t,s)=>{Promise.resolve().then(s.bind(s,43503))}},e=>{e.O(0,[2574,3862,246,5792,5263,5497,8441,3794,7358],()=>e(e.s=47584)),_N_E=e.O()}]);
|