316 lines
14 KiB
HTML
316 lines
14 KiB
HTML
{% extends "base.html" %}
|
|
{% load i18n %}
|
|
|
|
{% block title %}{% trans "Setting Details" %} | {{ setting.key }}{% endblock %}
|
|
|
|
{% block customCSS %}
|
|
<style>
|
|
/* Card Hover Effects */
|
|
.settings-card {
|
|
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
}
|
|
|
|
.settings-card:hover {
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1);
|
|
}
|
|
|
|
/* Button Hover Effects */
|
|
.btn-action {
|
|
transition: all 0.2s ease;
|
|
}
|
|
|
|
.btn-action:hover {
|
|
transform: translateY(-1px);
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
}
|
|
|
|
.btn-primary {
|
|
transition: all 0.2s ease;
|
|
}
|
|
|
|
.btn-primary:hover {
|
|
transform: translateY(-1px);
|
|
box-shadow: 0 4px 12px rgba(157, 34, 53, 0.4);
|
|
}
|
|
|
|
.btn-secondary {
|
|
transition: all 0.2s ease;
|
|
}
|
|
|
|
.btn-secondary:hover {
|
|
background-color: rgba(157, 34, 53, 0.05);
|
|
border-color: rgba(157, 34, 53, 0.3);
|
|
}
|
|
|
|
/* Secret Value Toggle */
|
|
.secret-value {
|
|
transition: all 0.2s ease;
|
|
cursor: pointer;
|
|
user-select: none;
|
|
}
|
|
|
|
.secret-value:hover {
|
|
color: #9d2235 !important;
|
|
}
|
|
|
|
/* Info Item Styling */
|
|
.info-item {
|
|
transition: all 0.2s ease;
|
|
}
|
|
|
|
.info-item:hover {
|
|
background-color: rgba(157, 34, 53, 0.02);
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
|
|
|
|
<!-- Breadcrumb -->
|
|
<nav aria-label="breadcrumb" class="mb-6">
|
|
<ol class="flex items-center gap-2 text-sm">
|
|
<li>
|
|
<a href="{% url 'settings_list' %}"
|
|
class="text-gray-500 hover:text-temple-red transition-colors flex items-center gap-1">
|
|
<i data-lucide="sliders-horizontal" class="w-4 h-4"></i>
|
|
{% trans "Integrations" %}
|
|
</a>
|
|
</li>
|
|
<li class="text-gray-400">/</li>
|
|
<li class="text-temple-red font-semibold truncate max-w-xs">
|
|
{{ setting.key }}
|
|
</li>
|
|
</ol>
|
|
</nav>
|
|
|
|
<!-- Page Header -->
|
|
<div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-6">
|
|
<div>
|
|
<h1 class="text-2xl sm:text-3xl font-bold text-gray-900 mb-2 flex items-center gap-3">
|
|
<div class="w-12 h-12 rounded-xl bg-temple-red/10 flex items-center justify-center">
|
|
<i data-lucide="file-key" class="w-6 h-6 text-temple-red"></i>
|
|
</div>
|
|
{% trans "Setting Details" %}
|
|
</h1>
|
|
<p class="text-gray-500 text-sm sm:text-base">
|
|
{{ setting.name|default:setting.key }}
|
|
</p>
|
|
</div>
|
|
<div class="flex gap-3">
|
|
<a href="{% url 'settings_update' setting.pk %}"
|
|
class="btn-primary inline-flex items-center gap-2 px-6 py-3 bg-temple-red text-white rounded-xl font-semibold shadow-lg hover:shadow-xl">
|
|
<i data-lucide="edit-3" class="w-5 h-5"></i>
|
|
{% trans "Edit" %}
|
|
</a>
|
|
<a href="{% url 'settings_list' %}"
|
|
class="btn-secondary inline-flex items-center gap-2 px-6 py-3 border-2 border-gray-200 text-gray-700 rounded-xl font-semibold hover:border-gray-300">
|
|
<i data-lucide="arrow-left" class="w-5 h-5"></i>
|
|
{% trans "Back" %}
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6 lg:gap-8">
|
|
|
|
<!-- Left Column - Configuration (2/3 width) -->
|
|
<div class="lg:col-span-2 space-y-6">
|
|
<!-- Configuration Card -->
|
|
<div class="settings-card bg-white rounded-2xl shadow-sm border border-gray-200 overflow-hidden">
|
|
<!-- Card Header -->
|
|
<div class="px-6 py-4 border-b border-gray-100 bg-gradient-to-r from-gray-50 to-white">
|
|
<div class="flex items-center gap-3">
|
|
<div class="w-10 h-10 rounded-xl bg-temple-red/10 flex items-center justify-center">
|
|
<i data-lucide="settings-2" class="w-5 h-5 text-temple-red"></i>
|
|
</div>
|
|
<div>
|
|
<h2 class="text-lg font-bold text-gray-900">{% trans "Configuration" %}</h2>
|
|
<p class="text-sm text-gray-500">{% trans "View and manage your settings" %}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Card Body -->
|
|
<div class="p-6 sm:p-8 space-y-6">
|
|
|
|
<!-- Internal Key -->
|
|
<div class="space-y-3">
|
|
<label class="flex items-center gap-2 text-sm font-semibold text-gray-700 uppercase tracking-wider">
|
|
<i data-lucide="key" class="w-4 h-4 text-gray-400"></i>
|
|
{% trans "Internal Key" %}
|
|
</label>
|
|
<div class="p-4 rounded-xl border-2 border-gray-200 bg-gray-50 flex items-center justify-between">
|
|
<code class="text-temple-red font-mono text-base">{{ setting.key }}</code>
|
|
<button type="button"
|
|
class="btn-action w-10 h-10 rounded-lg bg-white hover:bg-gray-100 flex items-center justify-center text-gray-500 hover:text-temple-red transition-colors border border-gray-200"
|
|
onclick="copyToClipboard('{{ setting.key|escapejs }}', this)"
|
|
title="{% trans 'Copy to Clipboard' %}">
|
|
<i data-lucide="copy" class="w-5 h-5"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Sensitive Value -->
|
|
<div class="space-y-3">
|
|
<label class="flex items-center gap-2 text-sm font-semibold text-gray-700 uppercase tracking-wider">
|
|
<i data-lucide="lock" class="w-4 h-4 text-gray-400"></i>
|
|
{% trans "Sensitive Value" %}
|
|
</label>
|
|
<div class="p-4 rounded-xl border-2 border-gray-200 bg-gray-50">
|
|
<div class="flex flex-col sm:flex-row gap-3 sm:gap-4">
|
|
<div class="flex-1 min-w-0">
|
|
<span class="secret-value font-mono text-gray-600 px-3 py-2.5 rounded-lg inline-block break-all"
|
|
id="revealContainer"
|
|
data-full-value="{{ setting.value }}"
|
|
data-masked="••••••••••••••••••••••••"
|
|
onclick="toggleSecret(this)">
|
|
••••••••••••••••••••••••
|
|
</span>
|
|
</div>
|
|
<div class="flex items-center gap-2 flex-shrink-0">
|
|
<button type="button"
|
|
class="btn-action w-10 h-10 rounded-lg bg-white hover:bg-gray-100 flex items-center justify-center text-gray-500 hover:text-temple-red transition-colors border border-gray-200"
|
|
onclick="toggleSecret(document.getElementById('revealContainer'))"
|
|
title="{% trans 'Show/Hide' %}">
|
|
<i data-lucide="eye" class="w-5 h-5"></i>
|
|
</button>
|
|
<button type="button"
|
|
class="btn-action w-10 h-10 rounded-lg bg-white hover:bg-gray-100 flex items-center justify-center text-gray-500 hover:text-temple-red transition-colors border border-gray-200"
|
|
onclick="copyToClipboard('{{ setting.value|escapejs }}', this)"
|
|
title="{% trans 'Copy to Clipboard' %}">
|
|
<i data-lucide="copy" class="w-5 h-5"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Right Column - Metadata (1/3 width) -->
|
|
<div class="space-y-6">
|
|
<!-- Metadata Card -->
|
|
<div class="settings-card bg-white rounded-2xl shadow-sm border border-gray-200 overflow-hidden">
|
|
<!-- Card Header -->
|
|
<div class="px-6 py-4 border-b border-gray-100 bg-gradient-to-r from-gray-50 to-white">
|
|
<div class="flex items-center gap-3">
|
|
<div class="w-10 h-10 rounded-xl bg-temple-red/10 flex items-center justify-center">
|
|
<i data-lucide="info" class="w-5 h-5 text-temple-red"></i>
|
|
</div>
|
|
<div>
|
|
<h2 class="text-lg font-bold text-gray-900">{% trans "Metadata" %}</h2>
|
|
<p class="text-sm text-gray-500">{% trans "Setting information" %}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Card Body -->
|
|
<div class="p-6 space-y-4">
|
|
<!-- Category -->
|
|
<div class="info-item p-3 rounded-xl bg-gray-50">
|
|
<div class="flex items-center gap-2 text-sm text-gray-500 mb-1">
|
|
<i data-lucide="tag" class="w-4 h-4"></i>
|
|
{% trans "Category" %}
|
|
</div>
|
|
<div class="font-semibold text-gray-900">{{ setting.get_category_display }}</div>
|
|
</div>
|
|
|
|
<hr class="border-gray-200">
|
|
|
|
<!-- Created -->
|
|
<div class="info-item p-3 rounded-xl bg-gray-50">
|
|
<div class="flex items-center gap-2 text-sm text-gray-500 mb-1">
|
|
<i data-lucide="calendar-plus" class="w-4 h-4"></i>
|
|
{% trans "Created" %}
|
|
</div>
|
|
<div class="font-semibold text-gray-900">
|
|
{{ setting.created_at|date:"F d, Y H:i" }}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Last Updated -->
|
|
<div class="info-item p-3 rounded-xl bg-gray-50">
|
|
<div class="flex items-center gap-2 text-sm text-gray-500 mb-1">
|
|
<i data-lucide="clock" class="w-4 h-4"></i>
|
|
{% trans "Last Updated" %}
|
|
</div>
|
|
<div class="font-semibold text-gray-900">
|
|
{{ setting.updated_at|date:"F d, Y H:i" }}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modified By -->
|
|
<div class="info-item p-3 rounded-xl bg-gray-50">
|
|
<div class="flex items-center gap-2 text-sm text-gray-500 mb-1">
|
|
<i data-lucide="user" class="w-4 h-4"></i>
|
|
{% trans "Modified By" %}
|
|
</div>
|
|
<div class="font-semibold text-gray-900">
|
|
{{ setting.updated_by.get_full_name|default:"System" }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
{% endblock %}
|
|
|
|
{% block customJS %}
|
|
<script>
|
|
// Initialize Lucide icons
|
|
lucide.createIcons();
|
|
|
|
function toggleSecret(element) {
|
|
const fullValue = element.getAttribute('data-full-value');
|
|
const maskedValue = element.getAttribute('data-masked');
|
|
const allButtons = document.querySelectorAll('[onclick*="toggleSecret"]');
|
|
let eyeIcon = null;
|
|
|
|
// Find the eye button icon
|
|
allButtons.forEach(btn => {
|
|
const icon = btn.querySelector('i');
|
|
if (icon && (icon.getAttribute('data-lucide') === 'eye' || icon.getAttribute('data-lucide') === 'eye-off')) {
|
|
eyeIcon = icon;
|
|
}
|
|
});
|
|
|
|
if (element.textContent.trim() === maskedValue) {
|
|
element.textContent = fullValue;
|
|
element.classList.remove('text-gray-600');
|
|
element.classList.add('text-gray-900', 'bg-temple-red/5');
|
|
if (eyeIcon) eyeIcon.setAttribute('data-lucide', 'eye-off');
|
|
} else {
|
|
element.textContent = maskedValue;
|
|
element.classList.remove('text-gray-900', 'bg-temple-red/5');
|
|
element.classList.add('text-gray-600');
|
|
if (eyeIcon) eyeIcon.setAttribute('data-lucide', 'eye');
|
|
}
|
|
lucide.createIcons();
|
|
}
|
|
|
|
function copyToClipboard(text, btn) {
|
|
navigator.clipboard.writeText(text).then(() => {
|
|
const icon = btn.querySelector('i');
|
|
const originalLucide = icon.getAttribute('data-lucide');
|
|
icon.setAttribute('data-lucide', 'check-circle-2');
|
|
icon.classList.remove('text-gray-500', 'hover:text-temple-red');
|
|
icon.classList.add('text-green-500');
|
|
|
|
lucide.createIcons();
|
|
|
|
setTimeout(() => {
|
|
icon.setAttribute('data-lucide', originalLucide);
|
|
icon.classList.remove('text-green-500');
|
|
icon.classList.add('text-gray-500', 'hover:text-temple-red');
|
|
lucide.createIcons();
|
|
}, 2000);
|
|
});
|
|
}
|
|
</script>
|
|
{% endblock %} |