Merge pull request #107 from YasinKose/main
Feat(ui): add Turkish language support and UI enhancements Introduces Turkish language support and several UI/UX improvements to the web management interface.
This commit is contained in:
@@ -129,7 +129,7 @@
|
||||
x-text="(acc.subscription?.tier || 'free').toUpperCase()">
|
||||
</span>
|
||||
</td>
|
||||
<td class="py-4">
|
||||
<td class="py-4 cursor-pointer" @click="openQuotaModal(acc)">
|
||||
<div x-data="{ quota: getMainModelQuota(acc) }">
|
||||
<template x-if="quota.percent !== null">
|
||||
<div class="flex items-center gap-2">
|
||||
@@ -268,4 +268,62 @@
|
||||
<button>close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
<!-- Quota Distribution Modal -->
|
||||
<dialog id="quota_modal" class="modal backdrop-blur-sm">
|
||||
<div class="modal-box max-w-2xl w-full bg-space-900 border border-space-border text-gray-300 shadow-2xl p-6">
|
||||
<h3 class="font-bold text-xl text-white mb-2 flex items-center gap-2">
|
||||
<svg class="w-6 h-6 text-neon-cyan" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<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" />
|
||||
</svg>
|
||||
<span x-text="$store.global.t('quotaDistribution')">Quota Distribution</span>
|
||||
</h3>
|
||||
<p class="text-sm text-gray-500 font-mono mb-6" x-text="selectedAccountEmail"></p>
|
||||
|
||||
<div class="grid grid-cols-1 gap-4 overflow-y-auto max-h-[60vh] pr-2 custom-scrollbar">
|
||||
<template x-for="(limit, modelId) in selectedAccountLimits" :key="modelId">
|
||||
<div class="p-3 bg-space-800/50 border border-space-border/30 rounded-lg">
|
||||
<div class="flex justify-between items-center mb-2">
|
||||
<span class="text-sm font-semibold text-gray-200" x-text="modelId"></span>
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-xs font-mono"
|
||||
:class="limit.remainingFraction > 0.5 ? 'text-neon-green' : (limit.remainingFraction > 0.2 ? 'text-yellow-500' : 'text-red-500')"
|
||||
x-text="Math.round(limit.remainingFraction * 100) + '%'"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="w-full bg-gray-700 rounded-full h-2.5 mb-2 overflow-hidden">
|
||||
<div class="h-full rounded-full transition-all duration-500"
|
||||
:class="limit.remainingFraction > 0.5 ? 'bg-neon-green' : (limit.remainingFraction > 0.2 ? 'bg-yellow-500' : 'bg-red-500')"
|
||||
:style="`width: ${limit.remainingFraction * 100}%`">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-[10px] text-gray-500 uppercase font-bold" x-text="$store.data.getModelFamily(modelId)"></span>
|
||||
<template x-if="limit.resetTime">
|
||||
<span class="text-[10px] text-yellow-500/80 font-mono italic"
|
||||
x-text="$store.global.t('resetsIn', { time: window.utils.formatTimeUntil(limit.resetTime) })"></span>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template x-if="Object.keys(selectedAccountLimits).length === 0">
|
||||
<div class="text-center py-8 text-gray-500" x-text="$store.global.t('noQuotaData')">
|
||||
No quota data available for this account yet.
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<div class="modal-action">
|
||||
<form method="dialog">
|
||||
<button class="btn btn-ghost hover:bg-white/10" x-text="$store.global.t('close')">Close</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button>close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
</div>
|
||||
@@ -48,7 +48,7 @@
|
||||
<div class="text-[10px] font-mono text-gray-600 hidden lg:block">
|
||||
<span x-text="filteredLogs.length"></span>/<span x-text="logs.length"></span>
|
||||
</div>
|
||||
<label class="cursor-pointer flex items-center gap-2" title="Auto-scroll to bottom">
|
||||
<label class="cursor-pointer flex items-center gap-2">
|
||||
<span class="text-[10px] font-mono text-gray-500 uppercase hidden sm:inline-block"
|
||||
x-text="$store.global.t('autoScroll')">Auto-Scroll</span>
|
||||
<input type="checkbox" class="toggle toggle-xs toggle-success" x-model="isAutoScroll">
|
||||
|
||||
@@ -86,6 +86,18 @@
|
||||
@click="$store.data.filters.family = 'gemini'; $store.data.computeQuotaRows()"
|
||||
x-text="$store.global.t('geminiCaps')">GEMINI</button>
|
||||
</div>
|
||||
|
||||
<!-- Show Hidden Toggle -->
|
||||
<button
|
||||
class="btn h-9 px-4 ml-2 border border-space-border/50 bg-space-800 hover:bg-space-700 hover:border-space-border hover:text-white transition-all gap-2 min-h-0"
|
||||
:class="$store.settings.showHiddenModels ? 'text-neon-purple border-neon-purple/50 bg-neon-purple/10' : 'text-gray-400'"
|
||||
@click="$store.settings.toggle('showHiddenModels'); $store.data.computeQuotaRows()"
|
||||
:title="$store.settings.showHiddenModels ? $store.global.t('hideHidden') : $store.global.t('showHidden')">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.88 9.88l-3.29-3.29m7.532 7.532l3.29 3.29M3 3l3.59 3.59m0 0A9.953 9.953 0 0112 5c4.478 0 8.268 2.943 9.543 7a10.025 10.025 0 01-4.132 5.411m0 0L21 21" />
|
||||
</svg>
|
||||
<span class="text-[10px] font-medium uppercase tracking-wide" x-text="$store.settings.showHiddenModels ? $store.global.t('hiddenOn') : $store.global.t('hiddenOff')"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -156,7 +168,7 @@
|
||||
</thead>
|
||||
<tbody class="text-sm">
|
||||
<template x-for="row in $store.data.quotaRows" :key="row.modelId">
|
||||
<tr class="group">
|
||||
<tr class="group transition-all duration-300" :class="row.hidden ? 'opacity-40 grayscale hover:opacity-100 hover:grayscale-0 bg-space-900/50' : ''">
|
||||
<td class="pl-4">
|
||||
<div class="w-2 h-2 rounded-full transition-all duration-500"
|
||||
:class="row.avgQuota > 0 ? 'bg-neon-green shadow-[0_0_8px_rgba(34,197,94,0.6)]' : 'bg-red-500 shadow-[0_0_8px_rgba(239,68,68,0.6)]'">
|
||||
|
||||
@@ -71,20 +71,14 @@
|
||||
<label class="label">
|
||||
<span class="label-text text-gray-300" x-text="$store.global.t('language')">Language</span>
|
||||
</label>
|
||||
<div class="join w-full grid grid-cols-2">
|
||||
<button
|
||||
class="join-item btn btn-sm border-space-border/50 bg-space-800 transition-all font-medium"
|
||||
:class="$store.global.lang === 'en'
|
||||
? 'bg-neon-purple/20 text-neon-purple border-neon-purple/60 shadow-lg shadow-neon-purple/10'
|
||||
: 'text-gray-400 hover:text-white hover:bg-space-700 hover:border-space-border'"
|
||||
@click="$store.global.setLang('en')">English</button>
|
||||
<button
|
||||
class="join-item btn btn-sm border-space-border/50 bg-space-800 transition-all font-medium"
|
||||
:class="$store.global.lang === 'zh'
|
||||
? 'bg-neon-purple/20 text-neon-purple border-neon-purple/60 shadow-lg shadow-neon-purple/10'
|
||||
: 'text-gray-400 hover:text-white hover:bg-space-700 hover:border-space-border'"
|
||||
@click="$store.global.setLang('zh')">中文</button>
|
||||
</div>
|
||||
<select
|
||||
class="select select-bordered select-sm w-full bg-space-800 border-space-border/50 text-gray-300 focus:border-neon-purple focus:ring-1 focus:ring-neon-purple/50 font-medium transition-all !py-0 leading-tight"
|
||||
:value="$store.global.lang"
|
||||
@change="$store.global.setLang($event.target.value)">
|
||||
<option value="en">English</option>
|
||||
<option value="zh">中文</option>
|
||||
<option value="tr">Türkçe</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Polling Interval -->
|
||||
@@ -753,15 +747,19 @@
|
||||
</svg>
|
||||
</div>
|
||||
<div x-show="isEditing(modelId)" class="flex items-center gap-1">
|
||||
<input type="text" x-model="newMapping"
|
||||
<select x-model="newMapping"
|
||||
:x-ref="'input-' + modelId"
|
||||
class="input input-xs bg-space-800 border-space-border text-white focus:outline-none focus:border-neon-cyan flex-1 font-mono text-xs"
|
||||
placeholder="e.g. claude-sonnet-4-5 or gemini-3-flash"
|
||||
class="select select-sm bg-space-800 border-space-border text-white focus:outline-none focus:border-neon-cyan flex-1 font-mono text-xs !h-8 min-h-0"
|
||||
@keydown.enter="await updateModelConfig(modelId, { mapping: newMapping }); stopEditing()"
|
||||
@keydown.escape="newMapping = config.mapping || ''; stopEditing()">
|
||||
<option value="" x-text="$store.global.t('none')">None</option>
|
||||
<template x-for="mId in $store.data.models" :key="mId">
|
||||
<option :value="mId" x-text="mId" :selected="mId === newMapping"></option>
|
||||
</template>
|
||||
</select>
|
||||
<button class="btn-action-success"
|
||||
@click="await updateModelConfig(modelId, { mapping: newMapping }); stopEditing()"
|
||||
title="Save">
|
||||
:title="$store.global.t('saveChanges')">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="w-3.5 h-3.5" fill="none"
|
||||
viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round"
|
||||
@@ -770,7 +768,7 @@
|
||||
</button>
|
||||
<button class="btn-action-neutral"
|
||||
@click="newMapping = config.mapping || ''; stopEditing()"
|
||||
title="Cancel">
|
||||
:title="$store.global.t('cancel')">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="w-3.5 h-3.5" fill="none"
|
||||
viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round"
|
||||
@@ -780,7 +778,7 @@
|
||||
<button x-show="config.mapping"
|
||||
class="btn-action-danger"
|
||||
@click="await updateModelConfig(modelId, { mapping: '' }); stopEditing()"
|
||||
title="Clear mapping">
|
||||
:title="$store.global.t('delete')">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="w-3.5 h-3.5" fill="none"
|
||||
viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round"
|
||||
|
||||
Reference in New Issue
Block a user