Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,67 +16,205 @@
Easily view, add, edit, or delete domains. Keep your domain list organized and up-to-date with our management tools.
{% endblock og_description %}
{% block body %}
<div class="fixed bottom-2.5 right-3.75">
<a href="https://github.com/OWASP-BLT/BLT/blob/main/website/templates/organization/organization_manage_domains.html">
<i class="fab fa-github"></i>
</a>
<a href="https://www.figma.com/file/s0xuxeU6O2guoWEfA9OElZ/Design?node-id=3%3A76&t=pqxWpF3hcYxjEDrs-1">
<i class="fab fa-figma"></i>
</a>
</div>
<div class="bg-[#F3F5F7] w-full h-full flex flex-col items-center">
<div class="flex items-center md:justify-between w-full md:h-max mt-5 flex-col md:flex-row">
<p class="text-red-700 font-satoshi font-bold text-[35px] px-8">Manage Domains</p>
<div class="w-full md:w-[15%] flex justify-center md:justify-end mr-10">
<a href="{% url 'add_domain' organization %}"
class="flex items-center justify-center md:justify-center px-16 py-7 bg-[#DC4654] rounded-xl hover:bg-red-600 transition-all">
<i class="fa-sharp fa-solid fa-plus fa-xl text-white"></i>
</a>
<div class="min-h-screen bg-gradient-to-br from-gray-50 to-gray-100">
<!-- Header Section -->
<div class="bg-white shadow-sm border-b border-gray-200">
<div class=" mx-auto px-4 sm:px-6 lg:px-8 py-6">
<div class="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4">
<div>
<h1 class="text-3xl font-bold text-gray-900">Manage Domains</h1>
<p class="mt-1 text-sm text-gray-500">Organize and control your domain portfolio</p>
</div>
<a href="{% url 'add_domain' organization %}"
class="inline-flex items-center px-4 py-3 bg-[#e74c3c] text-white rounded-xl font-medium hover:bg-red-700 transition-all duration-200 select-none">
<svg class="w-5 h-5 mr-2"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"></path>
</svg>
Add New Domain
</a>
</div>
</div>
</div>
<div class="w-[96%] max-h-[70vh] p-4 mt-10 bg-white border border-gray-200 rounded-lg shadow-md sm:p-8">
<div class="flex items-center justify-between mb-4">
<h5 class="text-xl font-bold leading-none text-gray-900">All Domains</h5>
<a href="#" class="text-sm font-medium text-blue-600 hover:underline">View all</a>
</div>
<div class="flow-root h-full mt-5">
<ul role="list" class="divide-y divide-gray-200 px-5 overflow-y-scroll">
{% for domain in domains %}
<li class="py-3 sm:py-4">
<div class="flex items-center space-x-4">
<div class="flex-shrink-0">
<img class="w-8 h-8 rounded-full"
src="{% if domain.logo %}{{ MEDIA_URL }}{{ domain.logo }}{% else %}https://via.placeholder.com/50?text=No+Logo{% endif %}"
alt="Domain Logo"
width="32px"
height="32px">
</div>
<div class="flex-1 min-w-0">
<p class="text-sm font-medium text-gray-900 truncate">{{ domain.name | capfirst }}</p>
<p class="text-sm text-gray-500 truncate">{{ domain.url }}</p>
</div>
<div class="inline-flex items-center text-base font-semibold text-gray-900">
<a href="{% url 'edit_domain' organization domain.id %}">Edit</a>
<a class="ml-4" href="{% url 'view_domain' domain.id %}">View</a>
<form id="deleteForm"
action="{% url 'add_domain' organization %}"
method="post"
class="inline">
{% csrf_token %}
<input type="hidden" name="_method" value="delete">
<input type="hidden" name="domain_id" value="{{ domain.id }}">
<button type="submit"
class="ml-4"
onclick="return confirm('Are you sure you want to delete this domain?')">
Delete
</button>
</form>
<!-- Main Content -->
<div class="w-full mx-auto px-4 sm:px-6 lg:px-4 py-4">
<!-- Domains List -->
{% if domains %}
<div class="bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden">
<div class="px-6 py-4 border-b border-gray-200">
<h2 class="text-lg font-semibold text-gray-900">All Domains</h2>
</div>
<div class="divide-y divide-gray-200" id="domainsList">
{% for domain in domains %}
<div class="domain-item p-6 hover:bg-gray-50 transition-all duration-200"
data-name="{{ domain.name|lower }}"
data-url="{{ domain.url|lower }}">
<div class="flex items-center justify-between">
<div class="flex items-center space-x-4 truncate">
<div class="flex-shrink-0">
<div class="w-12 h-12 select-none rounded-lg bg-gradient-to-br from-[#e74c3c] to-red-600 flex items-center justify-center text-white font-bold text-lg shadow-md">
{% if domain.logo %}
<img class="w-full h-full rounded-lg object-cover"
src="{{ MEDIA_URL }}{{ domain.logo }}"
alt="{{ domain.name }} Logo"
height="48"
width="48"
loading="lazy"
decoding="async">
{% else %}
{{ domain.name|first|upper }}
{% endif %}
</div>
</div>
<div>
<h3 class="text-lg font-semibold text-gray-900">{{ domain.name|capfirst }}</h3>
{% if domain.url %}
<a href="{% if domain.url|slice:':4' == 'http' %}{{ domain.url }}{% else %}https://{{ domain.url }}{% endif %}"
target="_blank"
rel="noopener noreferrer"
class="text-sm text-[#e74c3c] hover:text-red-800 hover:underline flex items-center gap-1">
{{ domain.url|default_if_none:"" }}
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14">
</path>
</svg>
</a>
{% else %}
<span class="text-sm text-gray-400">No URL provided</span>
{% endif %}
</div>
</div>
<div class="flex items-center space-x-2 select-none">
<a href="{% url 'view_domain' domain.id %}"
class="inline-flex items-center px-3 py-1.5 bg-gray-100 text-gray-700 rounded-lg hover:bg-gray-200 transition-all"
title="View Domain">
<svg class="w-4 h-4 mr-1.5"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z">
</path>
</svg>
View
</a>
<a href="{% url 'edit_domain' organization domain.id %}"
class="inline-flex items-center px-3 py-1.5 bg-blue-100 text-blue-700 rounded-lg hover:bg-blue-200 transition-all"
title="Edit Domain">
<svg class="w-4 h-4 mr-1.5"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z">
</path>
</svg>
Edit
</a>
<form action="{% url 'add_domain' organization %}"
method="post"
class="inline delete-form">
{% csrf_token %}
<input type="hidden" name="_method" value="delete">
<input type="hidden" name="domain_id" value="{{ domain.id }}">
<button type="submit"
class="inline-flex items-center px-3 py-1.5 bg-red-100 text-red-700 rounded-lg hover:bg-red-200 transition-all"
title="Delete Domain">
<svg class="w-4 h-4 mr-1.5"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24">
<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">
</path>
</svg>
Delete
</button>
</form>
</div>
</div>
</div>
</li>
{% endfor %}
</ul>
{% endfor %}
</div>
</div>
{% else %}
<!-- Empty State -->
<div class="bg-white rounded-xl shadow-sm border border-gray-200 p-12">
<div class="text-center">
<svg class="mx-auto h-12 w-12 text-gray-400"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9">
</path>
</svg>
<h3 class="mt-4 text-lg font-semibold text-gray-900">No domains yet</h3>
<p class="mt-2 text-sm text-gray-500">Get started by adding your first domain.</p>
<div class="mt-6">
<a href="{% url 'add_domain' organization %}"
class="inline-flex items-center px-4 py-2 bg-[#e74c3c] text-white rounded-lg hover:bg-red-700 transition-all duration-200">
<svg class="w-5 h-5 mr-2"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"></path>
</svg>
Add Your First Domain
</a>
</div>
</div>
</div>
{% endif %}
</div>
</div>
<!-- Loading Overlay -->
<div id="loadingOverlay"
class="hidden fixed inset-0 bg-gray-900 bg-opacity-50 z-50">
<div class="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2">
<div class="bg-white rounded-lg p-6 flex items-center space-x-3">
<svg class="animate-spin h-5 w-5 text-[#e74c3c]"
fill="none"
viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z">
</path>
</svg>
<span class="text-gray-700">Loading...</span>
</div>
</div>
</div>
<script>
// Delete confirmation handling
document.addEventListener('DOMContentLoaded', function() {
const deleteForms = document.querySelectorAll('.delete-form');
const loadingOverlay = document.getElementById('loadingOverlay');

deleteForms.forEach(form => {
form.addEventListener('submit', function(e) {
e.preventDefault();

const domainName = this.closest('.domain-item').querySelector('h3').textContent.trim();

if (confirm(`Are you sure you want to delete ${domainName}? This action cannot be undone.`)) {
if (loadingOverlay) {
loadingOverlay.classList.remove('hidden');
}
this.submit();
}
});
});

// Add hover effects
const domainItems = document.querySelectorAll('.domain-item');
domainItems.forEach(item => {
item.addEventListener('mouseenter', function() {
this.style.transform = 'translateX(4px)';
});

item.addEventListener('mouseleave', function() {
this.style.transform = 'translateX(0)';
});
});
});
</script>
{% endblock body %}