daoan1412's picture
Add 2 files
92f75cf verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Camera Access Permissions</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
.permission-card {
transition: all 0.3s ease;
}
.permission-card:hover {
transform: translateY(-2px);
box-shadow: 0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -2px rgba(0,0,0,0.05);
}
.tab-content {
display: none;
}
.tab-content.active {
display: block;
animation: fadeIn 0.3s ease;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.tree-node {
position: relative;
padding-left: 20px;
}
.tree-node:before {
content: "";
position: absolute;
left: 0;
top: 10px;
width: 15px;
height: 2px;
background-color: #6b7280;
}
.tree-node:after {
content: "";
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 2px;
background-color: #6b7280;
}
.tree-node:last-child:after {
height: 10px;
}
.time-slot {
transition: all 0.2s ease;
}
.time-slot:hover {
background-color: #e5e7eb;
}
.time-slot.active {
background-color: #3b82f6;
color: white;
}
.ip-chip {
transition: all 0.2s ease;
}
.ip-chip:hover {
transform: scale(1.02);
}
.group-header {
cursor: pointer;
transition: background-color 0.2s;
}
.group-header:hover {
background-color: #f3f4f6;
}
.camera-item {
transition: all 0.2s;
}
.camera-item:hover {
background-color: #f9fafb;
}
.draggable {
cursor: move;
}
.draggable.dragging {
opacity: 0.5;
}
.dropzone {
min-height: 20px;
transition: background-color 0.2s;
}
.dropzone.active {
background-color: #e0f2fe;
}
.conflict-warning {
animation: pulse 2s infinite;
}
@keyframes pulse {
0% { box-shadow: 0 0 0 0 rgba(234, 88, 12, 0.4); }
70% { box-shadow: 0 0 0 10px rgba(234, 88, 12, 0); }
100% { box-shadow: 0 0 0 0 rgba(234, 88, 12, 0); }
}
</style>
</head>
<body class="bg-gray-50">
<div class="container mx-auto px-4 py-8">
<!-- Header -->
<div class="flex justify-between items-center mb-8">
<div>
<h1 class="text-3xl font-bold text-gray-800">Camera Access Permissions</h1>
<p class="text-gray-600">Configure and manage camera access for users and groups</p>
</div>
<div class="flex space-x-2">
<button id="saveBtn" class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg flex items-center">
<i class="fas fa-save mr-2"></i> Save Changes
</button>
<button id="bulkBtn" class="bg-green-600 hover:bg-green-700 text-white px-4 py-2 rounded-lg flex items-center">
<i class="fas fa-users mr-2"></i> Bulk Assign
</button>
</div>
</div>
<!-- User Selection -->
<div class="bg-white rounded-xl shadow-md p-6 mb-6">
<h2 class="text-xl font-semibold mb-4 text-gray-800">Select User/Group</h2>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Search User</label>
<div class="relative">
<input type="text" id="userSearch" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-blue-500 focus:border-blue-500" placeholder="Search by name or email">
<div class="absolute right-3 top-2.5 text-gray-400">
<i class="fas fa-search"></i>
</div>
</div>
<div id="userResults" class="mt-2 border border-gray-200 rounded-lg max-h-60 overflow-y-auto hidden">
<!-- User results will appear here -->
</div>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Search Group</label>
<div class="relative">
<input type="text" id="groupSearch" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-blue-500 focus:border-blue-500" placeholder="Search group name">
<div class="absolute right-3 top-2.5 text-gray-400">
<i class="fas fa-search"></i>
</div>
</div>
<div id="groupResults" class="mt-2 border border-gray-200 rounded-lg max-h-60 overflow-y-auto hidden">
<!-- Group results will appear here -->
</div>
</div>
</div>
<div id="selectedEntities" class="mt-4 flex flex-wrap gap-2 hidden">
<!-- Selected users/groups will appear here -->
</div>
</div>
<!-- Camera Access Tab -->
<div class="bg-white rounded-xl shadow-md overflow-hidden">
<div class="p-6">
<h3 class="text-lg font-medium text-gray-800 mb-4">Camera Access Overview</h3>
<p class="text-gray-600 mb-4">Configure which cameras or camera groups the user/group can access and their permission levels.</p>
<!-- Search and Filter Bar -->
<div class="bg-gray-50 p-4 rounded-lg mb-6">
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Search Cameras</label>
<div class="relative">
<input type="text" id="cameraSearch" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-blue-500 focus:border-blue-500" placeholder="Search by camera name">
<div class="absolute right-3 top-2.5 text-gray-400">
<i class="fas fa-search"></i>
</div>
</div>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Filter by Status</label>
<select class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-blue-500 focus:border-blue-500">
<option>All Cameras</option>
<option>Assigned Only</option>
<option>Unassigned Only</option>
<option>With Conflicts</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Quick Actions</label>
<div class="flex space-x-2">
<button class="bg-gray-200 hover:bg-gray-300 text-gray-800 px-3 py-2 rounded-lg text-sm flex items-center">
<i class="fas fa-expand mr-1"></i> Expand All
</button>
<button class="bg-gray-200 hover:bg-gray-300 text-gray-800 px-3 py-2 rounded-lg text-sm flex items-center">
<i class="fas fa-compress mr-1"></i> Collapse All
</button>
</div>
</div>
</div>
</div>
<!-- Camera Group Hierarchy -->
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
<!-- Camera Groups -->
<div class="lg:col-span-2">
<div class="bg-white border border-gray-200 rounded-lg shadow-sm">
<div class="p-4 border-b border-gray-200">
<h4 class="font-medium text-gray-800 flex items-center">
<i class="fas fa-sitemap text-blue-600 mr-2"></i>
Camera Groups Hierarchy
</h4>
</div>
<div id="cameraGroups" class="p-4 space-y-2">
<!-- Main Building Group -->
<div class="group-container border border-gray-200 rounded-lg overflow-hidden">
<div class="group-header bg-gray-50 p-3 flex items-center justify-between" data-group="main-building">
<div class="flex items-center">
<input type="checkbox" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded mr-2 group-checkbox" data-group="main-building">
<div class="w-8 h-8 rounded-full bg-blue-100 flex items-center justify-center mr-2">
<i class="fas fa-building text-blue-600"></i>
</div>
<span class="font-medium">Main Building</span>
<span class="ml-2 text-xs bg-blue-100 text-blue-800 px-2 py-0.5 rounded-full">12 cameras</span>
</div>
<button class="text-gray-500 hover:text-gray-700 group-toggle" data-group="main-building">
<i class="fas fa-chevron-down"></i>
</button>
</div>
<div class="group-content p-2 space-y-2" data-group="main-building" style="display: block;">
<!-- Floor 1 Group -->
<div class="group-container border border-gray-200 rounded-lg overflow-hidden ml-4">
<div class="group-header bg-gray-50 p-3 flex items-center justify-between" data-group="floor-1">
<div class="flex items-center">
<input type="checkbox" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded mr-2 group-checkbox" data-group="floor-1">
<div class="w-8 h-8 rounded-full bg-purple-100 flex items-center justify-center mr-2">
<i class="fas fa-layer-group text-purple-600"></i>
</div>
<span class="font-medium">Floor 1</span>
<span class="ml-2 text-xs bg-purple-100 text-purple-800 px-2 py-0.5 rounded-full">5 cameras</span>
</div>
<button class="text-gray-500 hover:text-gray-700 group-toggle" data-group="floor-1">
<i class="fas fa-chevron-down"></i>
</button>
</div>
<div class="group-content p-2 space-y-2" data-group="floor-1" style="display: block;">
<!-- Camera items -->
<div class="camera-item bg-white p-2 rounded border border-gray-200 flex items-center justify-between draggable" draggable="true" data-camera="lobby-cam">
<div class="flex items-center">
<input type="checkbox" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded mr-2 camera-checkbox" data-camera="lobby-cam">
<div class="w-8 h-8 rounded-full bg-green-100 flex items-center justify-center mr-2">
<i class="fas fa-video text-green-600"></i>
</div>
<span>Lobby Camera</span>
</div>
<div class="flex items-center space-x-2">
<span class="text-xs bg-yellow-100 text-yellow-800 px-2 py-0.5 rounded-full">Conflict</span>
<button class="text-gray-400 hover:text-gray-600">
<i class="fas fa-ellipsis-v"></i>
</button>
</div>
</div>
<div class="camera-item bg-white p-2 rounded border border-gray-200 flex items-center justify-between draggable" draggable="true" data-camera="elevator-cam">
<div class="flex items-center">
<input type="checkbox" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded mr-2 camera-checkbox" data-camera="elevator-cam">
<div class="w-8 h-8 rounded-full bg-green-100 flex items-center justify-center mr-2">
<i class="fas fa-video text-green-600"></i>
</div>
<span>Elevator Camera</span>
</div>
<button class="text-gray-400 hover:text-gray-600">
<i class="fas fa-ellipsis-v"></i>
</button>
</div>
<div class="camera-item bg-white p-2 rounded border border-gray-200 flex items-center justify-between draggable" draggable="true" data-camera="hallway-cam">
<div class="flex items-center">
<input type="checkbox" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded mr-2 camera-checkbox" data-camera="hallway-cam">
<div class="w-8 h-8 rounded-full bg-green-100 flex items-center justify-center mr-2">
<i class="fas fa-video text-green-600"></i>
</div>
<span>Hallway Camera</span>
</div>
<button class="text-gray-400 hover:text-gray-600">
<i class="fas fa-ellipsis-v"></i>
</button>
</div>
</div>
</div>
<!-- Floor 2 Group -->
<div class="group-container border border-gray-200 rounded-lg overflow-hidden ml-4">
<div class="group-header bg-gray-50 p-3 flex items-center justify-between" data-group="floor-2">
<div class="flex items-center">
<input type="checkbox" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded mr-2 group-checkbox" data-group="floor-2">
<div class="w-8 h-8 rounded-full bg-purple-100 flex items-center justify-center mr-2">
<i class="fas fa-layer-group text-purple-600"></i>
</div>
<span class="font-medium">Floor 2</span>
<span class="ml-2 text-xs bg-purple-100 text-purple-800 px-2 py-0.5 rounded-full">4 cameras</span>
</div>
<button class="text-gray-500 hover:text-gray-700 group-toggle" data-group="floor-2">
<i class="fas fa-chevron-down"></i>
</button>
</div>
<div class="group-content p-2 space-y-2" data-group="floor-2" style="display: none;">
<!-- Camera items would appear here when expanded -->
</div>
</div>
</div>
</div>
<!-- Parking Lot Group -->
<div class="group-container border border-gray-200 rounded-lg overflow-hidden">
<div class="group-header bg-gray-50 p-3 flex items-center justify-between" data-group="parking-lot">
<div class="flex items-center">
<input type="checkbox" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded mr-2 group-checkbox" data-group="parking-lot">
<div class="w-8 h-8 rounded-full bg-blue-100 flex items-center justify-center mr-2">
<i class="fas fa-parking text-blue-600"></i>
</div>
<span class="font-medium">Parking Lot</span>
<span class="ml-2 text-xs bg-blue-100 text-blue-800 px-2 py-0.5 rounded-full">3 cameras</span>
</div>
<button class="text-gray-500 hover:text-gray-700 group-toggle" data-group="parking-lot">
<i class="fas fa-chevron-down"></i>
</button>
</div>
<div class="group-content p-2 space-y-2" data-group="parking-lot" style="display: none;">
<!-- Camera items would appear here when expanded -->
</div>
</div>
<!-- Warehouse Group -->
<div class="group-container border border-gray-200 rounded-lg overflow-hidden">
<div class="group-header bg-gray-50 p-3 flex items-center justify-between" data-group="warehouse">
<div class="flex items-center">
<input type="checkbox" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded mr-2 group-checkbox" data-group="warehouse">
<div class="w-8 h-8 rounded-full bg-blue-100 flex items-center justify-center mr-2">
<i class="fas fa-warehouse text-blue-600"></i>
</div>
<span class="font-medium">Warehouse</span>
<span class="ml-2 text-xs bg-blue-100 text-blue-800 px-2 py-0.5 rounded-full">6 cameras</span>
</div>
<button class="text-gray-500 hover:text-gray-700 group-toggle" data-group="warehouse">
<i class="fas fa-chevron-down"></i>
</button>
</div>
<div class="group-content p-2 space-y-2" data-group="warehouse" style="display: none;">
<!-- Camera items would appear here when expanded -->
</div>
</div>
<!-- Unassigned Cameras -->
<div class="border border-gray-200 rounded-lg overflow-hidden">
<div class="bg-gray-50 p-3 flex items-center justify-between">
<div class="flex items-center">
<div class="w-8 h-8 rounded-full bg-gray-100 flex items-center justify-center mr-2">
<i class="fas fa-question text-gray-600"></i>
</div>
<span class="font-medium">Unassigned Cameras</span>
<span class="ml-2 text-xs bg-gray-100 text-gray-800 px-2 py-0.5 rounded-full">2 cameras</span>
</div>
</div>
<div class="p-2 space-y-2">
<div class="camera-item bg-white p-2 rounded border border-gray-200 flex items-center justify-between draggable" draggable="true" data-camera="gate-cam">
<div class="flex items-center">
<input type="checkbox" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded mr-2 camera-checkbox" data-camera="gate-cam">
<div class="w-8 h-8 rounded-full bg-green-100 flex items-center justify-center mr-2">
<i class="fas fa-video text-green-600"></i>
</div>
<span>Gate Camera</span>
</div>
<button class="text-gray-400 hover:text-gray-600">
<i class="fas fa-ellipsis-v"></i>
</button>
</div>
<div class="camera-item bg-white p-2 rounded border border-gray-200 flex items-center justify-between draggable" draggable="true" data-camera="backup-cam">
<div class="flex items-center">
<input type="checkbox" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded mr-2 camera-checkbox" data-camera="backup-cam">
<div class="w-8 h-8 rounded-full bg-green-100 flex items-center justify-center mr-2">
<i class="fas fa-video text-green-600"></i>
</div>
<span>Backup Camera</span>
</div>
<button class="text-gray-400 hover:text-gray-600">
<i class="fas fa-ellipsis-v"></i>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Permission Configuration -->
<div class="lg:col-span-1">
<div class="bg-white border border-gray-200 rounded-lg shadow-sm sticky top-4">
<div class="p-4 border-b border-gray-200">
<h4 class="font-medium text-gray-800 flex items-center">
<i class="fas fa-key text-blue-600 mr-2"></i>
Permission Configuration
</h4>
</div>
<div class="p-4 space-y-4">
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">Selected Items</label>
<div id="selectedItems" class="bg-gray-50 p-3 rounded-lg min-h-20 max-h-40 overflow-y-auto dropzone">
<p class="text-sm text-gray-500 italic">No items selected</p>
</div>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">Permission Level</label>
<select class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-blue-500 focus:border-blue-500">
<option>No Access</option>
<option selected>View Only</option>
<option>View + Playback</option>
<option>Full Access</option>
<option>Custom...</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">Custom Permissions</label>
<div class="space-y-2">
<div class="flex items-center">
<input id="live-view" type="checkbox" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded" checked>
<label for="live-view" class="ml-2 block text-sm text-gray-700">Live View</label>
</div>
<div class="flex items-center">
<input id="playback" type="checkbox" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded" checked>
<label for="playback" class="ml-2 block text-sm text-gray-700">Playback Recordings</label>
</div>
<div class="flex items-center">
<input id="export" type="checkbox" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded">
<label for="export" class="ml-2 block text-sm text-gray-700">Export Recordings</label>
</div>
<div class="flex items-center">
<input id="ptz-control" type="checkbox" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded">
<label for="ptz-control" class="ml-2 block text-sm text-gray-700">PTZ Control</label>
</div>
<div class="flex items-center">
<input id="configuration" type="checkbox" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded">
<label for="configuration" class="ml-2 block text-sm text-gray-700">Configuration</label>
</div>
</div>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">Inheritance Settings</label>
<div class="flex items-center">
<input id="inherit-permissions" type="checkbox" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded" checked>
<label for="inherit-permissions" class="ml-2 block text-sm text-gray-700">Inherit permissions from parent groups</label>
</div>
<p class="mt-1 text-xs text-gray-500">When enabled, permissions from parent groups will override individual camera settings</p>
</div>
<div class="pt-2">
<button class="w-full bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg">
Apply Permissions
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Conflict Resolution Modal -->
<div id="conflictModal" class="fixed inset-0 bg-gray-600 bg-opacity-50 flex items-center justify-center hidden z-50">
<div class="bg-white rounded-lg shadow-xl max-w-2xl w-full p-6">
<div class="flex justify-between items-center mb-4">
<h3 class="text-lg font-medium text-gray-800 flex items-center">
<i class="fas fa-exclamation-triangle text-yellow-500 mr-2"></i>
Permission Conflicts Detected
</h3>
<button id="closeConflictModal" class="text-gray-400 hover:text-gray-500">
<i class="fas fa-times"></i>
</button>
</div>
<div class="space-y-4">
<p class="text-gray-600">
The following cameras have conflicting permissions from multiple groups. Please resolve the conflicts before proceeding.
</p>
<div class="border border-gray-200 rounded-lg overflow-hidden">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50">
<tr>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Camera</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Current Group</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Conflicting Group</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Action</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200">
<tr>
<td class="px-6 py-4 whitespace-nowrap">
<div class="flex items-center">
<div class="w-8 h-8 rounded-full bg-green-100 flex items-center justify-center mr-2">
<i class="fas fa-video text-green-600"></i>
</div>
<span>Lobby Camera</span>
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
<div class="flex items-center">
<div class="w-6 h-6 rounded-full bg-purple-100 flex items-center justify-center mr-2">
<i class="fas fa-layer-group text-purple-600 text-xs"></i>
</div>
Floor 1
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
<div class="flex items-center">
<div class="w-6 h-6 rounded-full bg-blue-100 flex items-center justify-center mr-2">
<i class="fas fa-building text-blue-600 text-xs"></i>
</div>
Security Group
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
<select class="text-xs border border-gray-300 rounded focus:ring-blue-500 focus:border-blue-500">
<option>Keep current group</option>
<option>Use conflicting group</option>
<option>Custom settings...</option>
</select>
</td>
</tr>
</tbody>
</table>
</div>
<div class="flex justify-end space-x-3 pt-4">
<button id="cancelConflict" class="bg-gray-200 hover:bg-gray-300 text-gray-800 px-4 py-2 rounded-lg text-sm">
Cancel
</button>
<button id="resolveConflict" class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg text-sm">
Resolve Conflicts
</button>
</div>
</div>
</div>
</div>
<!-- Success Notification -->
<div id="successNotification" class="fixed bottom-4 right-4 bg-green-500 text-white px-4 py-2 rounded-lg shadow-lg flex items-center hidden z-50">
<i class="fas fa-check-circle mr-2"></i>
<span>Permissions updated successfully!</span>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Group toggle functionality
const groupToggles = document.querySelectorAll('.group-toggle');
groupToggles.forEach(toggle => {
toggle.addEventListener('click', function() {
const groupId = this.getAttribute('data-group');
const content = document.querySelector(`.group-content[data-group="${groupId}"]`);
const icon = this.querySelector('i');
if (content.style.display === 'none' || !content.style.display) {
content.style.display = 'block';
icon.classList.remove('fa-chevron-down');
icon.classList.add('fa-chevron-up');
} else {
content.style.display = 'none';
icon.classList.remove('fa-chevron-up');
icon.classList.add('fa-chevron-down');
}
});
});
// Group checkbox functionality (select all cameras in group)
const groupCheckboxes = document.querySelectorAll('.group-checkbox');
groupCheckboxes.forEach(checkbox => {
checkbox.addEventListener('change', function() {
const groupId = this.getAttribute('data-group');
const cameras = document.querySelectorAll(`.group-content[data-group="${groupId}"] .camera-checkbox`);
cameras.forEach(camCheckbox => {
camCheckbox.checked = this.checked;
});
updateSelectedItems();
});
});
// Camera checkbox functionality
const cameraCheckboxes = document.querySelectorAll('.camera-checkbox');
cameraCheckboxes.forEach(checkbox => {
checkbox.addEventListener('change', function() {
updateSelectedItems();
});
});
// Update selected items display
function updateSelectedItems() {
const selectedItemsContainer = document.getElementById('selectedItems');
const selectedCameras = document.querySelectorAll('.camera-checkbox:checked');
if (selectedCameras.length === 0) {
selectedItemsContainer.innerHTML = '<p class="text-sm text-gray-500 italic">No items selected</p>';
return;
}
selectedItemsContainer.innerHTML = '';
selectedCameras.forEach(checkbox => {
const cameraId = checkbox.getAttribute('data-camera');
const cameraItem = checkbox.closest('.camera-item');
const cameraName = cameraItem.querySelector('span').textContent;
const cameraIcon = cameraItem.querySelector('.fa-video').parentNode.cloneNode(true);
const chip = document.createElement('div');
chip.className = 'bg-blue-100 text-blue-800 px-2 py-1 rounded-full text-sm flex items-center mb-1';
chip.appendChild(cameraIcon);
chip.innerHTML += ` ${cameraName}`;
selectedItemsContainer.appendChild(chip);
});
}
// Drag and drop functionality
const draggables = document.querySelectorAll('.draggable');
const dropzones = document.querySelectorAll('.dropzone');
draggables.forEach(draggable => {
draggable.addEventListener('dragstart', function() {
this.classList.add('dragging');
});
draggable.addEventListener('dragend', function() {
this.classList.remove('dragging');
});
});
dropzones.forEach(dropzone => {
dropzone.addEventListener('dragover', function(e) {
e.preventDefault();
this.classList.add('active');
});
dropzone.addEventListener('dragleave', function() {
this.classList.remove('active');
});
dropzone.addEventListener('drop', function(e) {
e.preventDefault();
this.classList.remove('active');
const dragging = document.querySelector('.dragging');
if (dragging) {
this.appendChild(dragging);
// Check for conflicts after dropping
checkForConflicts();
}
});
});
// Check for permission conflicts
function checkForConflicts() {
// In a real app, this would check the permissions of the camera in all groups it belongs to
// For this demo, we'll just show the conflict modal if the lobby camera is selected
const lobbyCamCheckbox = document.querySelector('.camera-checkbox[data-camera="lobby-cam"]');
if (lobbyCamCheckbox && lobbyCamCheckbox.checked) {
const conflictModal = document.getElementById('conflictModal');
conflictModal.classList.remove('hidden');
}
}
// Conflict modal handling
const closeConflictModal = document.getElementById('closeConflictModal');
const cancelConflict = document.getElementById('cancelConflict');
const resolveConflict = document.getElementById('resolveConflict');
if (closeConflictModal) {
closeConflictModal.addEventListener('click', function() {
document.getElementById('conflictModal').classList.add('hidden');
});
}
if (cancelConflict) {
cancelConflict.addEventListener('click', function() {
document.getElementById('conflictModal').classList.add('hidden');
});
}
if (resolveConflict) {
resolveConflict.addEventListener('click', function() {
document.getElementById('conflictModal').classList.add('hidden');
document.getElementById('successNotification').classList.remove('hidden');
setTimeout(() => {
document.getElementById('successNotification').classList.add('hidden');
}, 3000);
});
}
// Save button functionality
const saveBtn = document.getElementById('saveBtn');
if (saveBtn) {
saveBtn.addEventListener('click', function() {
// First check for conflicts
checkForConflicts();
// If no conflicts, show success
const conflictModal = document.getElementById('conflictModal');
if (conflictModal.classList.contains('hidden')) {
document.getElementById('successNotification').classList.remove('hidden');
setTimeout(() => {
document.getElementById('successNotification').classList.add('hidden');
}, 3000);
}
});
}
// Bulk assign button functionality
const bulkBtn = document.getElementById('bulkBtn');
if (bulkBtn) {
bulkBtn.addEventListener('click', function() {
// In a real app, this would open the bulk assign modal
alert('Bulk assign functionality would open here');
});
}
// Camera search functionality
const cameraSearch = document.getElementById('cameraSearch');
if (cameraSearch) {
cameraSearch.addEventListener('input', function() {
const searchTerm = this.value.toLowerCase();
const cameras = document.querySelectorAll('.camera-item');
cameras.forEach(camera => {
const cameraName = camera.querySelector('span').textContent.toLowerCase();
if (cameraName.includes(searchTerm)) {
camera.style.display = 'flex';
// Make sure parent groups are expanded
let parentGroup = camera.closest('.group-content');
while (parentGroup) {
parentGroup.style.display = 'block';
const toggle = document.querySelector(`.group-toggle[data-group="${parentGroup.getAttribute('data-group')}"]`);
if (toggle) {
toggle.querySelector('i').classList.remove('fa-chevron-down');
toggle.querySelector('i').classList.add('fa-chevron-up');
}
parentGroup = parentGroup.closest('.group-content');
}
} else {
camera.style.display = 'none';
}
});
});
}
});
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=daoan1412/camera-access-permissions" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>