feat: add bulk import and paste feature for .env and json configs
This commit is contained in:
@@ -7,12 +7,14 @@ import { App, AppEnvironment, AuditLog, ConfigEntry, ConfigType, Environment } f
|
||||
import { cn, envBadgeStyles, maskSecret, typeColor } from '@/lib/utils'
|
||||
import { AppIcon } from './AppIcon'
|
||||
import { IconPicker } from './IconPicker'
|
||||
import { BulkImportModal } from './BulkImportModal'
|
||||
import {
|
||||
Eye, EyeOff, Copy, Plus, Trash2, Edit2, Check, X,
|
||||
Key, RefreshCw, Clock, Search, Download, FileCode,
|
||||
Shield, Code2, AlertTriangle, Terminal, Smartphone,
|
||||
Globe, Sparkles, Filter, ChevronRight, CheckCircle2,
|
||||
Lock, ExternalLink, HelpCircle, Settings, Settings2, ImageIcon
|
||||
Lock, ExternalLink, HelpCircle, Settings, Settings2, ImageIcon,
|
||||
FileText, ClipboardPaste
|
||||
} from 'lucide-react'
|
||||
|
||||
interface Props {
|
||||
@@ -36,6 +38,7 @@ export function AppDetailClient({ app, environments, configs, auditLogs }: Props
|
||||
const [copiedSlug, setCopiedSlug] = useState(false)
|
||||
const [showAddModal, setShowAddModal] = useState(false)
|
||||
const [showEditModal, setShowEditModal] = useState(false)
|
||||
const [showBulkModal, setShowBulkModal] = useState(false)
|
||||
const [revealedIds, setRevealedIds] = useState<Set<string>>(new Set())
|
||||
const [codeSnippetTab, setCodeSnippetTab] = useState<'rn' | 'next' | 'curl'>('rn')
|
||||
const [isDeletingApp, setIsDeletingApp] = useState(false)
|
||||
@@ -144,7 +147,7 @@ export function AppDetailClient({ app, environments, configs, auditLogs }: Props
|
||||
</div>
|
||||
|
||||
{/* Quick App Actions */}
|
||||
<div className="flex items-center gap-2.5 self-start md:self-auto pt-2 md:pt-0">
|
||||
<div className="flex flex-wrap items-center gap-2.5 self-start md:self-auto pt-2 md:pt-0">
|
||||
<button
|
||||
onClick={() => setShowEditModal(true)}
|
||||
className="flex items-center gap-2 bg-slate-900 hover:bg-slate-800 border border-slate-800 hover:border-slate-700 text-slate-300 hover:text-white font-semibold text-xs sm:text-sm px-3.5 py-2.5 rounded-xl transition-all"
|
||||
@@ -154,6 +157,15 @@ export function AppDetailClient({ app, environments, configs, auditLogs }: Props
|
||||
<span>İkon / Ayarlar</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={() => setShowBulkModal(true)}
|
||||
className="flex items-center gap-2 bg-slate-900 hover:bg-slate-800 border border-emerald-500/30 hover:border-emerald-500/50 text-emerald-400 hover:text-emerald-300 font-semibold text-xs sm:text-sm px-3.5 py-2.5 rounded-xl transition-all shadow-sm"
|
||||
title=".env veya JSON içeriğini toplu yapıştır"
|
||||
>
|
||||
<ClipboardPaste className="w-4 h-4" />
|
||||
<span>Toplu Yapıştır (.env)</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={() => setShowAddModal(true)}
|
||||
className="flex items-center gap-2 bg-emerald-500 hover:bg-emerald-400 active:bg-emerald-600 text-slate-950 font-bold text-xs sm:text-sm px-4 py-2.5 rounded-xl shadow-lg shadow-emerald-500/20 transition-all hover:scale-[1.02]"
|
||||
@@ -250,8 +262,17 @@ export function AppDetailClient({ app, environments, configs, auditLogs }: Props
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* Quick Export Tools */}
|
||||
{/* Quick Import & Export Tools */}
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<button
|
||||
onClick={() => setShowBulkModal(true)}
|
||||
className="inline-flex items-center gap-1.5 px-3 py-2 rounded-xl bg-emerald-500/10 border border-emerald-500/30 hover:bg-emerald-500/20 text-xs font-semibold text-emerald-400 hover:text-emerald-300 transition-colors shadow-sm"
|
||||
title=".env veya JSON içeriğini toplu içe aktar"
|
||||
>
|
||||
<ClipboardPaste className="w-3.5 h-3.5" />
|
||||
<span>Toplu Yapıştır</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={exportAsEnv}
|
||||
className="inline-flex items-center gap-1.5 px-3 py-2 rounded-xl bg-slate-900 border border-slate-800 hover:border-slate-700 text-xs font-medium text-slate-300 hover:text-white transition-colors"
|
||||
@@ -338,13 +359,23 @@ export function AppDetailClient({ app, environments, configs, auditLogs }: Props
|
||||
: 'Uygulamanızın ihtiyaç duyduğu API URL, Secret veya Flag değişkenlerini ekleyin.'}
|
||||
</p>
|
||||
{!searchQuery && typeFilter === 'all' && (
|
||||
<button
|
||||
onClick={() => setShowAddModal(true)}
|
||||
className="inline-flex items-center gap-1.5 bg-emerald-500 hover:bg-emerald-400 text-slate-950 text-xs font-bold px-4 py-2 rounded-xl transition-transform hover:scale-105 shadow-md shadow-emerald-500/20"
|
||||
>
|
||||
<Plus className="w-3.5 h-3.5 stroke-[2.5]" />
|
||||
<span>İlk Değişkeni Ekle</span>
|
||||
</button>
|
||||
<div className="flex flex-wrap items-center justify-center gap-3">
|
||||
<button
|
||||
onClick={() => setShowAddModal(true)}
|
||||
className="inline-flex items-center gap-1.5 bg-emerald-500 hover:bg-emerald-400 text-slate-950 text-xs font-bold px-4 py-2.5 rounded-xl transition-transform hover:scale-105 shadow-md shadow-emerald-500/20"
|
||||
>
|
||||
<Plus className="w-3.5 h-3.5 stroke-[2.5]" />
|
||||
<span>Tek Tek Ekle</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={() => setShowBulkModal(true)}
|
||||
className="inline-flex items-center gap-1.5 bg-slate-900 hover:bg-slate-800 border border-emerald-500/30 hover:border-emerald-500/50 text-emerald-400 hover:text-emerald-300 text-xs font-semibold px-4 py-2.5 rounded-xl transition-colors"
|
||||
>
|
||||
<ClipboardPaste className="w-3.5 h-3.5" />
|
||||
<span>Toplu Yapıştır (.env / JSON)</span>
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
@@ -656,6 +687,21 @@ export async function getAppConfig(env = 'production') {
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* ─── BULK IMPORT / PASTE MODAL ─── */}
|
||||
{showBulkModal && (
|
||||
<BulkImportModal
|
||||
environmentId={currentEnv?.id ?? ''}
|
||||
environment={activeEnv}
|
||||
appId={app.id}
|
||||
existingKeys={envConfigs.map(c => c.key)}
|
||||
onClose={() => setShowBulkModal(false)}
|
||||
onSaved={() => {
|
||||
setShowBulkModal(false)
|
||||
router.refresh()
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user