commons-proxy 2.0.0
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/LICENSE +21 -0
- package/README.md +757 -0
- package/bin/cli.js +146 -0
- package/package.json +97 -0
- package/public/Complaint Details.pdf +0 -0
- package/public/Cyber Crime Portal.pdf +0 -0
- package/public/app.js +229 -0
- package/public/css/src/input.css +523 -0
- package/public/css/style.css +1 -0
- package/public/favicon.png +0 -0
- package/public/index.html +549 -0
- package/public/js/components/account-manager.js +356 -0
- package/public/js/components/add-account-modal.js +414 -0
- package/public/js/components/claude-config.js +420 -0
- package/public/js/components/dashboard/charts.js +605 -0
- package/public/js/components/dashboard/filters.js +362 -0
- package/public/js/components/dashboard/stats.js +110 -0
- package/public/js/components/dashboard.js +236 -0
- package/public/js/components/logs-viewer.js +100 -0
- package/public/js/components/models.js +36 -0
- package/public/js/components/server-config.js +349 -0
- package/public/js/config/constants.js +102 -0
- package/public/js/data-store.js +375 -0
- package/public/js/settings-store.js +58 -0
- package/public/js/store.js +99 -0
- package/public/js/translations/en.js +367 -0
- package/public/js/translations/id.js +412 -0
- package/public/js/translations/pt.js +308 -0
- package/public/js/translations/tr.js +358 -0
- package/public/js/translations/zh.js +373 -0
- package/public/js/utils/account-actions.js +189 -0
- package/public/js/utils/error-handler.js +96 -0
- package/public/js/utils/model-config.js +42 -0
- package/public/js/utils/ui-logger.js +143 -0
- package/public/js/utils/validators.js +77 -0
- package/public/js/utils.js +69 -0
- package/public/proxy-server-64.png +0 -0
- package/public/views/accounts.html +361 -0
- package/public/views/dashboard.html +484 -0
- package/public/views/logs.html +97 -0
- package/public/views/models.html +331 -0
- package/public/views/settings.html +1327 -0
- package/src/account-manager/credentials.js +378 -0
- package/src/account-manager/index.js +462 -0
- package/src/account-manager/onboarding.js +112 -0
- package/src/account-manager/rate-limits.js +369 -0
- package/src/account-manager/storage.js +160 -0
- package/src/account-manager/strategies/base-strategy.js +109 -0
- package/src/account-manager/strategies/hybrid-strategy.js +339 -0
- package/src/account-manager/strategies/index.js +79 -0
- package/src/account-manager/strategies/round-robin-strategy.js +76 -0
- package/src/account-manager/strategies/sticky-strategy.js +138 -0
- package/src/account-manager/strategies/trackers/health-tracker.js +162 -0
- package/src/account-manager/strategies/trackers/index.js +9 -0
- package/src/account-manager/strategies/trackers/quota-tracker.js +120 -0
- package/src/account-manager/strategies/trackers/token-bucket-tracker.js +155 -0
- package/src/auth/database.js +169 -0
- package/src/auth/oauth.js +548 -0
- package/src/auth/token-extractor.js +117 -0
- package/src/cli/accounts.js +648 -0
- package/src/cloudcode/index.js +29 -0
- package/src/cloudcode/message-handler.js +510 -0
- package/src/cloudcode/model-api.js +248 -0
- package/src/cloudcode/rate-limit-parser.js +235 -0
- package/src/cloudcode/request-builder.js +93 -0
- package/src/cloudcode/session-manager.js +47 -0
- package/src/cloudcode/sse-parser.js +121 -0
- package/src/cloudcode/sse-streamer.js +293 -0
- package/src/cloudcode/streaming-handler.js +615 -0
- package/src/config.js +125 -0
- package/src/constants.js +407 -0
- package/src/errors.js +242 -0
- package/src/fallback-config.js +29 -0
- package/src/format/content-converter.js +193 -0
- package/src/format/index.js +20 -0
- package/src/format/request-converter.js +255 -0
- package/src/format/response-converter.js +120 -0
- package/src/format/schema-sanitizer.js +673 -0
- package/src/format/signature-cache.js +88 -0
- package/src/format/thinking-utils.js +648 -0
- package/src/index.js +148 -0
- package/src/modules/usage-stats.js +205 -0
- package/src/providers/anthropic-provider.js +258 -0
- package/src/providers/base-provider.js +157 -0
- package/src/providers/cloudcode.js +94 -0
- package/src/providers/copilot.js +399 -0
- package/src/providers/github-provider.js +287 -0
- package/src/providers/google-provider.js +192 -0
- package/src/providers/index.js +211 -0
- package/src/providers/openai-compatible.js +265 -0
- package/src/providers/openai-provider.js +271 -0
- package/src/providers/openrouter-provider.js +325 -0
- package/src/providers/setup.js +83 -0
- package/src/server.js +870 -0
- package/src/utils/claude-config.js +245 -0
- package/src/utils/helpers.js +51 -0
- package/src/utils/logger.js +142 -0
- package/src/utils/native-module-helper.js +162 -0
- package/src/webui/index.js +1134 -0
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
<div x-data="accountManager" class="view-container">
|
|
2
|
+
<!-- Compact Header -->
|
|
3
|
+
<div class="flex items-center justify-between gap-4 mb-6">
|
|
4
|
+
<!-- Title with inline subtitle -->
|
|
5
|
+
<div class="flex flex-wrap items-center gap-4">
|
|
6
|
+
<h1 class="text-2xl font-bold text-white tracking-tight" x-text="$store.global.t('accountManagement')">
|
|
7
|
+
Account Management
|
|
8
|
+
</h1>
|
|
9
|
+
<div class="flex items-center h-6 px-3 rounded-full bg-space-800/80 border border-space-border/50 shadow-sm backdrop-blur-sm">
|
|
10
|
+
<span class="text-[10px] font-mono text-gray-400 uppercase tracking-wider"
|
|
11
|
+
x-text="$store.global.t('manageTokens')">
|
|
12
|
+
Manage Google Account tokens and authorization states
|
|
13
|
+
</span>
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
<!-- Action Buttons -->
|
|
18
|
+
<div class="flex items-center gap-2">
|
|
19
|
+
<!-- Search -->
|
|
20
|
+
<div class="relative" x-show="$store.data.accounts.length > 0">
|
|
21
|
+
<input type="text"
|
|
22
|
+
x-model="searchQuery"
|
|
23
|
+
:placeholder="$store.global.t('searchAccounts')"
|
|
24
|
+
:aria-label="$store.global.t('searchAccounts')"
|
|
25
|
+
class="input-search-sm w-48 pl-9 h-8"
|
|
26
|
+
@keydown.escape="searchQuery = ''">
|
|
27
|
+
<svg class="w-4 h-4 absolute left-3 top-2 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
28
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
|
|
29
|
+
</svg>
|
|
30
|
+
</div>
|
|
31
|
+
|
|
32
|
+
<!-- Export Button -->
|
|
33
|
+
<button class="btn btn-xs btn-outline border-space-border text-gray-400 hover:text-white transition-all gap-2 h-8"
|
|
34
|
+
@click="exportAccounts()"
|
|
35
|
+
x-show="$store.data.accounts.length > 0"
|
|
36
|
+
:title="$store.global.t('exportAccounts') || 'Export Accounts'">
|
|
37
|
+
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
38
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12" />
|
|
39
|
+
</svg>
|
|
40
|
+
<span x-text="$store.global.t('export') || 'Export'">Export</span>
|
|
41
|
+
</button>
|
|
42
|
+
|
|
43
|
+
<!-- Import Button -->
|
|
44
|
+
<label class="btn btn-xs btn-outline border-space-border text-gray-400 hover:text-white transition-all gap-2 h-8 cursor-pointer"
|
|
45
|
+
:title="$store.global.t('importAccounts') || 'Import Accounts'">
|
|
46
|
+
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
47
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
|
|
48
|
+
</svg>
|
|
49
|
+
<span x-text="$store.global.t('import') || 'Import'">Import</span>
|
|
50
|
+
<input type="file" accept=".json" class="hidden" @change="importAccounts($event)">
|
|
51
|
+
</label>
|
|
52
|
+
|
|
53
|
+
<button class="btn btn-xs btn-outline border-space-border text-gray-400 hover:text-white transition-all gap-2 h-8"
|
|
54
|
+
@click="reloadAccounts()"
|
|
55
|
+
:disabled="reloading">
|
|
56
|
+
<svg xmlns="http://www.w3.org/2000/svg"
|
|
57
|
+
class="w-3.5 h-3.5 transition-transform"
|
|
58
|
+
:class="{ 'animate-spin': reloading }"
|
|
59
|
+
fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
60
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
|
|
61
|
+
</svg>
|
|
62
|
+
<span x-text="$store.global.t('reload')">Reload</span>
|
|
63
|
+
</button>
|
|
64
|
+
<!-- Account Count Indicator -->
|
|
65
|
+
<div class="flex items-center h-6 px-2 rounded bg-space-800/80 border border-space-border/50"
|
|
66
|
+
:class="{ 'border-yellow-500/50': $store.data.accounts.length >= $store.data.maxAccounts }">
|
|
67
|
+
<span class="text-[11px] font-mono"
|
|
68
|
+
:class="$store.data.accounts.length >= $store.data.maxAccounts ? 'text-yellow-400' : 'text-gray-400'"
|
|
69
|
+
x-text="$store.data.accounts.length + '/' + $store.data.maxAccounts"></span>
|
|
70
|
+
</div>
|
|
71
|
+
<button class="btn bg-neon-purple hover:bg-purple-600 border-none text-white btn-xs gap-2 shadow-lg shadow-neon-purple/20 h-8"
|
|
72
|
+
:class="{ 'opacity-50 cursor-not-allowed': $store.data.accounts.length >= $store.data.maxAccounts }"
|
|
73
|
+
:disabled="$store.data.accounts.length >= $store.data.maxAccounts"
|
|
74
|
+
@click="$store.data.accounts.length < $store.data.maxAccounts && document.getElementById('add_account_modal').showModal()">
|
|
75
|
+
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
76
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4" />
|
|
77
|
+
</svg>
|
|
78
|
+
<span x-text="$store.global.t('addAccount')">Add Account</span>
|
|
79
|
+
</button>
|
|
80
|
+
</div>
|
|
81
|
+
</div>
|
|
82
|
+
|
|
83
|
+
<!-- Table Card -->
|
|
84
|
+
<div class="view-card !p-0">
|
|
85
|
+
<table class="w-full">
|
|
86
|
+
<thead x-show="$store.data.accounts.length > 0">
|
|
87
|
+
<tr class="bg-space-900/50 border-b border-space-border/50">
|
|
88
|
+
<th class="pl-6 py-3 text-left text-[10px] font-bold text-gray-500 uppercase tracking-wider w-16" x-text="$store.global.t('enabled')">Enabled</th>
|
|
89
|
+
<th class="py-3 text-left text-[10px] font-bold text-gray-500 uppercase tracking-wider flex-1 min-w-[200px]" x-text="$store.global.t('accountEmail')">Account (Email)</th>
|
|
90
|
+
<th class="py-3 text-left text-[10px] font-bold text-gray-500 uppercase tracking-wider w-20">Provider</th>
|
|
91
|
+
<th class="py-3 text-left text-[10px] font-bold text-gray-500 uppercase tracking-wider w-16" x-text="$store.global.t('tier')">Tier</th>
|
|
92
|
+
<th class="py-3 text-left text-[10px] font-bold text-gray-500 uppercase tracking-wider w-32" x-text="$store.global.t('quota')">Quota</th>
|
|
93
|
+
<th class="py-3 text-left text-[10px] font-bold text-gray-500 uppercase tracking-wider w-24" x-text="$store.global.t('health')">Health</th>
|
|
94
|
+
<th class="py-3 pr-6 text-right text-[10px] font-bold text-gray-500 uppercase tracking-wider w-32" x-text="$store.global.t('operations')">Operations</th>
|
|
95
|
+
</tr>
|
|
96
|
+
</thead>
|
|
97
|
+
<tbody>
|
|
98
|
+
<!-- Empty State -->
|
|
99
|
+
<template x-if="$store.data.accounts.length === 0">
|
|
100
|
+
<tr>
|
|
101
|
+
<td colspan="6" class="py-16 text-center">
|
|
102
|
+
<div class="flex flex-col items-center gap-4 max-w-lg mx-auto">
|
|
103
|
+
<svg class="w-20 h-20 text-gray-700" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
104
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"
|
|
105
|
+
d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z" />
|
|
106
|
+
</svg>
|
|
107
|
+
<h3 class="text-xl font-semibold text-gray-400" x-text="$store.global.t('noAccountsYet')">
|
|
108
|
+
No Accounts Yet
|
|
109
|
+
</h3>
|
|
110
|
+
<p class="text-sm text-gray-600 max-w-md leading-relaxed" x-text="$store.global.t('noAccountsDesc')">
|
|
111
|
+
Get started by adding a Google account via OAuth, or use the CLI command to import credentials.
|
|
112
|
+
</p>
|
|
113
|
+
<div class="flex items-center gap-4 mt-2">
|
|
114
|
+
<button class="btn bg-neon-purple hover:bg-purple-600 border-none text-white btn-sm gap-2 shadow-lg shadow-neon-purple/20"
|
|
115
|
+
onclick="document.getElementById('add_account_modal').showModal()">
|
|
116
|
+
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
117
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4" />
|
|
118
|
+
</svg>
|
|
119
|
+
<span x-text="$store.global.t('addFirstAccount')">Add Your First Account</span>
|
|
120
|
+
</button>
|
|
121
|
+
<span class="text-xs text-gray-600" x-text="$store.global.t('or')">or</span>
|
|
122
|
+
<div class="text-xs font-mono bg-space-800 px-3 py-2 rounded border border-space-border text-gray-400">
|
|
123
|
+
npm run accounts:add
|
|
124
|
+
</div>
|
|
125
|
+
</div>
|
|
126
|
+
</div>
|
|
127
|
+
</td>
|
|
128
|
+
</tr>
|
|
129
|
+
</template>
|
|
130
|
+
|
|
131
|
+
<!-- Account Rows -->
|
|
132
|
+
<template x-for="acc in filteredAccounts" :key="acc.email">
|
|
133
|
+
<tr class="border-b border-space-border/30 last:border-0 hover:bg-white/5 transition-colors group">
|
|
134
|
+
<td class="pl-6 py-4">
|
|
135
|
+
<label class="relative inline-flex items-center cursor-pointer">
|
|
136
|
+
<input type="checkbox" class="sr-only peer"
|
|
137
|
+
:checked="acc.enabled !== false"
|
|
138
|
+
@change="toggleAccount(acc.email, $el.checked)">
|
|
139
|
+
<div class="w-9 h-5 bg-space-800 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full rtl:peer-checked:after:-translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:start-[2px] after:bg-gray-600 after:rounded-full after:h-4 after:w-4 after:transition-all peer-checked:bg-neon-green peer-checked:after:bg-white"></div>
|
|
140
|
+
</label>
|
|
141
|
+
</td>
|
|
142
|
+
<td class="py-4">
|
|
143
|
+
<div class="tooltip tooltip-right" :data-tip="acc.email">
|
|
144
|
+
<span class="font-mono text-sm text-gray-300 truncate max-w-[320px] inline-block cursor-help group-hover:text-white transition-colors"
|
|
145
|
+
x-text="formatEmail(acc.email)">
|
|
146
|
+
</span>
|
|
147
|
+
</div>
|
|
148
|
+
</td>
|
|
149
|
+
<td class="py-4">
|
|
150
|
+
<span class="inline-block px-2 py-0.5 rounded text-[10px] font-semibold uppercase"
|
|
151
|
+
:style="`background-color: ${getProviderColor(acc)}40; color: ${getProviderColor(acc)}; border: 1px solid ${getProviderColor(acc)}`"
|
|
152
|
+
x-text="getProviderName(acc)">
|
|
153
|
+
</span>
|
|
154
|
+
</td>
|
|
155
|
+
<td class="py-4">
|
|
156
|
+
<span :class="{
|
|
157
|
+
'status-pill-ultra': acc.subscription?.tier === 'ultra',
|
|
158
|
+
'status-pill-pro': acc.subscription?.tier === 'pro',
|
|
159
|
+
'status-pill-free': !acc.subscription || acc.subscription.tier === 'free' || acc.subscription.tier === 'unknown'
|
|
160
|
+
}"
|
|
161
|
+
x-text="(acc.subscription?.tier || 'free').toUpperCase()">
|
|
162
|
+
</span>
|
|
163
|
+
</td>
|
|
164
|
+
<td class="py-4 cursor-pointer" @click="openQuotaModal(acc)">
|
|
165
|
+
<div x-data="{ quota: getMainModelQuota(acc) }">
|
|
166
|
+
<template x-if="quota.percent !== null">
|
|
167
|
+
<div class="flex items-center gap-2">
|
|
168
|
+
<div class="w-16 bg-gray-700 rounded-full h-2 overflow-hidden">
|
|
169
|
+
<div class="h-full rounded-full transition-all"
|
|
170
|
+
:class="{
|
|
171
|
+
'bg-neon-green': quota.percent > 50,
|
|
172
|
+
'bg-yellow-500': quota.percent > 20 && quota.percent <= 50,
|
|
173
|
+
'bg-red-500': quota.percent <= 20
|
|
174
|
+
}"
|
|
175
|
+
:style="`width: ${quota.percent}%`">
|
|
176
|
+
</div>
|
|
177
|
+
</div>
|
|
178
|
+
<span class="text-xs font-mono text-gray-400" x-text="quota.percent + '%'"></span>
|
|
179
|
+
</div>
|
|
180
|
+
</template>
|
|
181
|
+
<template x-if="quota.percent === null">
|
|
182
|
+
<span class="text-xs text-gray-600">-</span>
|
|
183
|
+
</template>
|
|
184
|
+
</div>
|
|
185
|
+
</td>
|
|
186
|
+
<td class="py-4">
|
|
187
|
+
<div class="flex items-center gap-2">
|
|
188
|
+
<div class="w-2 h-2 rounded-full flex-shrink-0"
|
|
189
|
+
:class="acc.status === 'ok' ?
|
|
190
|
+
'bg-neon-green shadow-[0_0_8px_rgba(34,197,94,0.6)] animate-pulse' :
|
|
191
|
+
'bg-red-500 shadow-[0_0_8px_rgba(239,68,68,0.6)]'">
|
|
192
|
+
</div>
|
|
193
|
+
<span class="text-xs font-mono font-semibold"
|
|
194
|
+
:class="acc.status === 'ok' ? 'text-neon-green' : 'text-red-400'"
|
|
195
|
+
x-text="acc.status.toUpperCase()">
|
|
196
|
+
</span>
|
|
197
|
+
</div>
|
|
198
|
+
</td>
|
|
199
|
+
<td class="py-4 pr-6">
|
|
200
|
+
<div class="flex justify-end gap-2">
|
|
201
|
+
<!-- Fix Button -->
|
|
202
|
+
<button x-show="acc.status === 'invalid'"
|
|
203
|
+
class="px-3 py-1 text-[10px] font-bold font-mono uppercase tracking-wider rounded bg-yellow-500/10 text-yellow-400 hover:bg-yellow-500/20 border border-yellow-500/30 hover:border-yellow-500/50 transition-all"
|
|
204
|
+
@click="fixAccount(acc.email)"
|
|
205
|
+
x-text="$store.global.t('fix')">
|
|
206
|
+
FIX
|
|
207
|
+
</button>
|
|
208
|
+
<button class="p-2 rounded hover:bg-white/10 text-gray-500 hover:text-white transition-colors"
|
|
209
|
+
@click="refreshAccount(acc.email)"
|
|
210
|
+
:disabled="refreshing"
|
|
211
|
+
:title="$store.global.t('refreshData')">
|
|
212
|
+
<svg class="w-4 h-4 transition-transform"
|
|
213
|
+
:class="{ 'animate-spin': refreshing }"
|
|
214
|
+
fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
215
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
|
216
|
+
d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
|
|
217
|
+
</svg>
|
|
218
|
+
</button>
|
|
219
|
+
<button
|
|
220
|
+
class="p-2 rounded transition-colors"
|
|
221
|
+
:class="acc.source === 'database' ? 'text-gray-700 cursor-not-allowed' : 'hover:bg-red-500/10 text-gray-500 hover:text-red-400'"
|
|
222
|
+
:disabled="acc.source === 'database'"
|
|
223
|
+
@click="acc.source !== 'database' && confirmDeleteAccount(acc.email)"
|
|
224
|
+
:title="acc.source === 'database' ? $store.global.t('cannotDeleteDatabase') : $store.global.t('delete')">
|
|
225
|
+
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
226
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
|
227
|
+
d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
|
|
228
|
+
</svg>
|
|
229
|
+
</button>
|
|
230
|
+
</div>
|
|
231
|
+
</td>
|
|
232
|
+
</tr>
|
|
233
|
+
</template>
|
|
234
|
+
|
|
235
|
+
<!-- No Search Results -->
|
|
236
|
+
<template x-if="$store.data.accounts.length > 0 && filteredAccounts.length === 0">
|
|
237
|
+
<tr>
|
|
238
|
+
<td colspan="6" class="py-12 text-center">
|
|
239
|
+
<div class="flex flex-col items-center gap-3">
|
|
240
|
+
<svg class="w-12 h-12 text-gray-700" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
241
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
|
|
242
|
+
</svg>
|
|
243
|
+
<p class="text-sm text-gray-600" x-text="$store.global.t('noSearchResults')">No accounts match your search</p>
|
|
244
|
+
<button class="btn-action-ghost !text-gray-500" @click="searchQuery = ''" x-text="$store.global.t('clearSearch')">Clear Search</button>
|
|
245
|
+
</div>
|
|
246
|
+
</td>
|
|
247
|
+
</tr>
|
|
248
|
+
</template>
|
|
249
|
+
</tbody>
|
|
250
|
+
</table>
|
|
251
|
+
</div>
|
|
252
|
+
|
|
253
|
+
<!-- Account Status Info -->
|
|
254
|
+
<div x-show="$store.data.accounts.length > 0" class="mt-4 px-6 py-3 bg-space-900/20 rounded-lg border border-space-border/20">
|
|
255
|
+
<p class="text-xs text-gray-600 flex items-center gap-2">
|
|
256
|
+
<svg class="w-4 h-4 text-gray-500 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
257
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
|
258
|
+
</svg>
|
|
259
|
+
<span x-html="$store.global.t('disabledAccountsNote')"></span>
|
|
260
|
+
</p>
|
|
261
|
+
</div>
|
|
262
|
+
|
|
263
|
+
<!-- Delete Confirmation Modal -->
|
|
264
|
+
<dialog id="delete_account_modal" class="modal">
|
|
265
|
+
<div class="modal-box bg-space-900 border-2 border-red-500/50">
|
|
266
|
+
<h3 class="font-bold text-lg text-red-400 flex items-center gap-2">
|
|
267
|
+
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
268
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
|
|
269
|
+
</svg>
|
|
270
|
+
<span x-text="$store.global.t('dangerousOperation')">Dangerous Operation</span>
|
|
271
|
+
</h3>
|
|
272
|
+
<p class="py-4 text-gray-300">
|
|
273
|
+
<span x-text="$store.global.t('confirmDeletePrompt')">Are you sure you want to delete account</span>
|
|
274
|
+
<strong class="text-white font-mono" x-text="deleteTarget"></strong>?
|
|
275
|
+
</p>
|
|
276
|
+
<div class="bg-red-500/10 border border-red-500/30 rounded p-3 mb-4">
|
|
277
|
+
<p class="text-sm text-red-300 flex items-start gap-2">
|
|
278
|
+
<svg class="w-5 h-5 flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
279
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
|
|
280
|
+
</svg>
|
|
281
|
+
<span x-text="$store.global.t('deleteWarning')">This action cannot be undone. All configuration and historical records will be permanently deleted.</span>
|
|
282
|
+
</p>
|
|
283
|
+
</div>
|
|
284
|
+
<div class="modal-action">
|
|
285
|
+
<button class="btn btn-ghost text-gray-400" onclick="document.getElementById('delete_account_modal').close()" x-text="$store.global.t('cancel')">
|
|
286
|
+
Cancel
|
|
287
|
+
</button>
|
|
288
|
+
<button class="btn bg-red-500 hover:bg-red-600 border-none text-white"
|
|
289
|
+
@click="executeDelete()"
|
|
290
|
+
:disabled="deleting"
|
|
291
|
+
:class="{ 'loading': deleting }">
|
|
292
|
+
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" x-show="!deleting">
|
|
293
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
|
|
294
|
+
</svg>
|
|
295
|
+
<span x-text="$store.global.t('confirmDelete')">Confirm Delete</span>
|
|
296
|
+
</button>
|
|
297
|
+
</div>
|
|
298
|
+
</div>
|
|
299
|
+
<form method="dialog" class="modal-backdrop">
|
|
300
|
+
<button x-text="$store.global.t('close')">close</button>
|
|
301
|
+
</form>
|
|
302
|
+
</dialog>
|
|
303
|
+
|
|
304
|
+
<!-- Quota Distribution Modal -->
|
|
305
|
+
<dialog id="quota_modal" class="modal backdrop-blur-sm">
|
|
306
|
+
<div class="modal-box max-w-2xl w-full bg-space-900 border border-space-border text-gray-300 shadow-2xl p-6">
|
|
307
|
+
<h3 class="font-bold text-xl text-white mb-2 flex items-center gap-2">
|
|
308
|
+
<svg class="w-6 h-6 text-neon-cyan" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
309
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
|
|
310
|
+
</svg>
|
|
311
|
+
<span x-text="$store.global.t('quotaDistribution')">Quota Distribution</span>
|
|
312
|
+
</h3>
|
|
313
|
+
<p class="text-sm text-gray-500 font-mono mb-6" x-text="selectedAccountEmail"></p>
|
|
314
|
+
|
|
315
|
+
<div class="grid grid-cols-1 gap-4 overflow-y-auto max-h-[60vh] pr-2 custom-scrollbar">
|
|
316
|
+
<template x-for="(limit, modelId) in selectedAccountLimits" :key="modelId">
|
|
317
|
+
<div class="p-3 bg-space-800/50 border border-space-border/30 rounded-lg">
|
|
318
|
+
<div class="flex justify-between items-center mb-2">
|
|
319
|
+
<span class="text-sm font-semibold text-gray-200" x-text="modelId"></span>
|
|
320
|
+
<div class="flex items-center gap-2">
|
|
321
|
+
<span class="text-xs font-mono"
|
|
322
|
+
:class="limit.remainingFraction > 0.5 ? 'text-neon-green' : (limit.remainingFraction > 0.2 ? 'text-yellow-500' : 'text-red-500')"
|
|
323
|
+
x-text="Math.round(limit.remainingFraction * 100) + '%'"></span>
|
|
324
|
+
</div>
|
|
325
|
+
</div>
|
|
326
|
+
|
|
327
|
+
<div class="w-full bg-gray-700 rounded-full h-2.5 mb-2 overflow-hidden">
|
|
328
|
+
<div class="h-full rounded-full transition-all duration-500"
|
|
329
|
+
:class="limit.remainingFraction > 0.5 ? 'bg-neon-green' : (limit.remainingFraction > 0.2 ? 'bg-yellow-500' : 'bg-red-500')"
|
|
330
|
+
:style="`width: ${limit.remainingFraction * 100}%`">
|
|
331
|
+
</div>
|
|
332
|
+
</div>
|
|
333
|
+
|
|
334
|
+
<div class="flex justify-between items-center">
|
|
335
|
+
<span class="text-[10px] text-gray-500 uppercase font-bold" x-text="$store.data.getModelFamily(modelId)"></span>
|
|
336
|
+
<template x-if="limit.resetTime">
|
|
337
|
+
<span class="text-[10px] text-yellow-500/80 font-mono italic"
|
|
338
|
+
x-text="$store.global.t('resetsIn', { time: window.utils.formatTimeUntil(limit.resetTime) })"></span>
|
|
339
|
+
</template>
|
|
340
|
+
</div>
|
|
341
|
+
</div>
|
|
342
|
+
</template>
|
|
343
|
+
|
|
344
|
+
<template x-if="Object.keys(selectedAccountLimits).length === 0">
|
|
345
|
+
<div class="text-center py-8 text-gray-500" x-text="$store.global.t('noQuotaData')">
|
|
346
|
+
No quota data available for this account yet.
|
|
347
|
+
</div>
|
|
348
|
+
</template>
|
|
349
|
+
</div>
|
|
350
|
+
|
|
351
|
+
<div class="modal-action">
|
|
352
|
+
<form method="dialog">
|
|
353
|
+
<button class="btn btn-ghost hover:bg-white/10" x-text="$store.global.t('close')">Close</button>
|
|
354
|
+
</form>
|
|
355
|
+
</div>
|
|
356
|
+
</div>
|
|
357
|
+
<form method="dialog" class="modal-backdrop">
|
|
358
|
+
<button x-text="$store.global.t('close')">close</button>
|
|
359
|
+
</form>
|
|
360
|
+
</dialog>
|
|
361
|
+
</div>
|