feat: ✨ feature flags
This commit is contained in:
+35
-1
@@ -42,7 +42,7 @@
|
||||
</div>
|
||||
<i class="fas fa-chevron-right text-gray-400"></i>
|
||||
</a>
|
||||
{% if has_permission('view_tags') %}
|
||||
{% if has_permission('view_tags') and is_feature_enabled('device_tags') %}
|
||||
<a href="/tags" class="bg-gray-200 dark:bg-zinc-800 hover:bg-gray-300 dark:hover:bg-zinc-700 p-6 rounded-lg shadow-md flex items-center justify-between transition-colors">
|
||||
<div class="flex items-center space-x-4">
|
||||
<i class="fas fa-tags text-3xl text-gray-600 dark:text-gray-400"></i>
|
||||
@@ -167,6 +167,40 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Feature Flags Section -->
|
||||
{% if has_permission('manage_users') %}
|
||||
<div class="bg-gray-200 dark:bg-zinc-800 p-6 rounded-lg shadow-md mt-8">
|
||||
<h2 class="text-2xl font-bold mb-6">Feature Flags</h2>
|
||||
<form action="/admin/feature_flags" method="POST">
|
||||
<div class="space-y-4">
|
||||
{% for flag in feature_flags %}
|
||||
<div class="flex items-center justify-between p-4 bg-gray-300 dark:bg-zinc-700 rounded-lg">
|
||||
<div class="flex-1">
|
||||
<label for="feature_{{ flag.key }}" class="text-lg font-semibold cursor-pointer">
|
||||
{{ flag.key|replace('_', ' ')|title }}
|
||||
</label>
|
||||
{% if flag.description %}
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400 mt-1">{{ flag.description }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<label class="relative inline-flex items-center cursor-pointer">
|
||||
<input type="checkbox" name="feature_{{ flag.key }}" id="feature_{{ flag.key }}"
|
||||
class="sr-only peer" {% if flag.enabled %}checked{% endif %}>
|
||||
<div class="w-11 h-6 bg-gray-600 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-gray-800 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-gray-500 dark:peer-checked:bg-zinc-600"></div>
|
||||
</label>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="flex justify-end mt-6">
|
||||
<button type="submit" class="bg-gray-300 hover:bg-gray-400 dark:bg-zinc-700 dark:hover:bg-zinc-600 hover:cursor-pointer px-6 py-2 rounded-lg font-medium">
|
||||
Save Changes
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -22,7 +22,9 @@
|
||||
<div class="flex space-x-4">
|
||||
<button onclick="showTab('assign-ips')" id="tab-assign-ips" class="tab-btn px-4 py-2 font-medium border-b-2 border-gray-600 text-gray-900 dark:text-gray-100 hover:cursor-pointer">Bulk IP Assignment</button>
|
||||
<button onclick="showTab('create-devices')" id="tab-create-devices" class="tab-btn px-4 py-2 font-medium border-b-2 border-transparent text-gray-500 hover:text-gray-700 dark:hover:text-gray-300 hover:cursor-pointer">Bulk Device Creation</button>
|
||||
{% if is_feature_enabled('device_tags') %}
|
||||
<button onclick="showTab('assign-tags')" id="tab-assign-tags" class="tab-btn px-4 py-2 font-medium border-b-2 border-transparent text-gray-500 hover:text-gray-700 dark:hover:text-gray-300 hover:cursor-pointer">Bulk Tag Assignment</button>
|
||||
{% endif %}
|
||||
<button onclick="showTab('export')" id="tab-export" class="tab-btn px-4 py-2 font-medium border-b-2 border-transparent text-gray-500 hover:text-gray-700 dark:hover:text-gray-300 hover:cursor-pointer">Bulk Export</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -94,6 +96,7 @@
|
||||
</div>
|
||||
|
||||
<!-- Bulk Tag Assignment -->
|
||||
{% if is_feature_enabled('device_tags') %}
|
||||
<div id="panel-assign-tags" class="tab-panel hidden bg-gray-200 dark:bg-zinc-800 p-6 rounded-lg shadow-md">
|
||||
{% if can_assign_device_tag %}
|
||||
<h2 class="text-2xl font-bold mb-4">Bulk Tag Assignment</h2>
|
||||
@@ -123,6 +126,7 @@
|
||||
<p class="text-gray-500">You don't have permission to assign tags to devices.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Bulk Export -->
|
||||
<div id="panel-export" class="tab-panel hidden bg-gray-200 dark:bg-zinc-800 p-6 rounded-lg shadow-md">
|
||||
|
||||
@@ -115,6 +115,7 @@
|
||||
{% endif %}
|
||||
|
||||
<!-- Tags Section -->
|
||||
{% if is_feature_enabled('device_tags') %}
|
||||
<div class="tags-section mb-6">
|
||||
<h3 class="text-lg font-bold mb-2">Tags:</h3>
|
||||
<div class="flex flex-wrap gap-2 mb-4">
|
||||
@@ -155,6 +156,7 @@
|
||||
</form>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<form action="/update_device_description" method="POST" class="mb-6 mt-4">
|
||||
<input type="hidden" name="device_id" value="{{ device.id }}">
|
||||
|
||||
@@ -16,14 +16,16 @@
|
||||
<h1 class="text-3xl font-bold mb-6 text-center">Device Manager</h1>
|
||||
<div class="flex flex-row justify-center gap-4 mb-6 flex-wrap">
|
||||
<a href="/add_device" class="text-center bg-gray-200 hover:bg-gray-400 dark:bg-zinc-700 dark:hover:bg-zinc-600 px-4 py-2 rounded-lg">Add New Device</a>
|
||||
{% if is_feature_enabled('bulk_operations') %}
|
||||
<a href="/bulk" class="text-center bg-gray-200 hover:bg-gray-400 dark:bg-zinc-700 dark:hover:bg-zinc-600 px-4 py-2 rounded-lg">Bulk Operations</a>
|
||||
{% endif %}
|
||||
<a href="/device_type_stats" class="text-center bg-gray-200 hover:bg-gray-400 dark:bg-zinc-700 dark:hover:bg-zinc-600 px-4 py-2 rounded-lg">View Device Stats</a>
|
||||
</div>
|
||||
|
||||
<!-- Filters Section -->
|
||||
<div class="mb-6 space-y-4">
|
||||
<!-- Tag Filter -->
|
||||
{% if all_tag_names %}
|
||||
{% if is_feature_enabled('device_tags') and all_tag_names %}
|
||||
<div class="flex items-center space-x-2">
|
||||
<label class="text-sm font-medium">Filter by tag:</label>
|
||||
<select id="tag-filter" class="border p-2 rounded-lg bg-gray-200 dark:bg-zinc-800 border-gray-600">
|
||||
@@ -67,6 +69,7 @@
|
||||
</span>
|
||||
</div>
|
||||
<!-- Tags -->
|
||||
{% if is_feature_enabled('device_tags') %}
|
||||
{% set tags = device_tags.get(device.id, []) %}
|
||||
{% if tags %}
|
||||
<div class="flex flex-wrap gap-1 mt-2">
|
||||
@@ -78,6 +81,7 @@
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
<span>Devices</span>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if has_permission('view_racks') %}
|
||||
{% if has_permission('view_racks') and is_feature_enabled('racks') %}
|
||||
<a href="/racks" class="text-gray-200 hover:text-gray-400 font-medium flex items-center gap-2">
|
||||
<i class="fas fa-th"></i>
|
||||
<span>Racks</span>
|
||||
@@ -86,7 +86,7 @@
|
||||
<span>Devices</span>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if has_permission('view_racks') %}
|
||||
{% if has_permission('view_racks') and is_feature_enabled('racks') %}
|
||||
<a href="/racks" class="block px-6 py-2 text-gray-200 hover:text-gray-400 font-medium flex items-center gap-2">
|
||||
<i class="fas fa-th"></i>
|
||||
<span>Racks</span>
|
||||
|
||||
+18
-13
@@ -251,21 +251,26 @@
|
||||
<td class="text-left align-top hidden sm:table-cell desc-col">
|
||||
{% set device_desc = ip[4] if ip[4] else '' %}
|
||||
{% set ip_notes = ip[5] if ip|length > 5 and ip[5] else '' %}
|
||||
{% set combined_desc = '' %}
|
||||
{% if device_desc %}
|
||||
{% set combined_desc = device_desc %}
|
||||
{% endif %}
|
||||
{% if ip_notes %}
|
||||
{% if combined_desc %}
|
||||
{% set combined_desc = combined_desc + '\n' + ip_notes %}
|
||||
{% else %}
|
||||
{% set combined_desc = ip_notes %}
|
||||
{% if ip_notes_enabled %}
|
||||
{% set combined_desc = '' %}
|
||||
{% if device_desc %}
|
||||
{% set combined_desc = device_desc %}
|
||||
{% endif %}
|
||||
{% if ip_notes %}
|
||||
{% if combined_desc %}
|
||||
{% set combined_desc = combined_desc + '\n' + ip_notes %}
|
||||
{% else %}
|
||||
{% set combined_desc = ip_notes %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if can_edit_subnet %}
|
||||
<textarea data-ip-id="{{ ip[0] }}" data-device-desc="{{ device_desc|e }}" rows="1" class="ip-notes-textarea border border-gray-600 rounded w-full p-2 bg-gray-200 dark:bg-zinc-800" style="overflow: hidden; resize: none;">{{ combined_desc }}</textarea>
|
||||
{% else %}
|
||||
<textarea readonly rows="1" class="border border-gray-600 rounded w-full cursor-pointer p-2" style="overflow: hidden; resize: none;">{{ combined_desc }}</textarea>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if can_edit_subnet %}
|
||||
<textarea data-ip-id="{{ ip[0] }}" data-device-desc="{{ device_desc|e }}" rows="1" class="ip-notes-textarea border border-gray-600 rounded w-full p-2 bg-gray-200 dark:bg-zinc-800" style="overflow: hidden; resize: none;">{{ combined_desc }}</textarea>
|
||||
{% else %}
|
||||
<textarea readonly rows="1" class="border border-gray-600 rounded w-full cursor-pointer p-2" style="overflow: hidden; resize: none;">{{ combined_desc }}</textarea>
|
||||
{# IP notes disabled - show only device description, read-only #}
|
||||
<textarea readonly rows="1" class="border border-gray-600 rounded w-full cursor-pointer p-2 bg-gray-200 dark:bg-zinc-800" style="overflow: hidden; resize: none;">{{ device_desc }}</textarea>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
Reference in New Issue
Block a user