|
38 | 38 | const addDiscoveredBtn = document.getElementById('add-discovered-btn');
|
39 | 39 | const rediscoverBtn = document.getElementById('rediscover-btn');
|
40 | 40 |
|
41 |
| - // VVV НОВОЕ: Элементы для модального окна управления пользователями VVV |
| 41 | + // VVV Элементы для модального окна управления пользователями VVV |
42 | 42 | const userManagementModal = document.getElementById('user-management-modal');
|
43 | 43 | const userManagementCloseBtn = document.getElementById('user-management-close-btn');
|
44 | 44 | const userListEl = document.getElementById('user-list');
|
|
49 | 49 | const saveUserBtn = document.getElementById('save-user-btn');
|
50 | 50 | const cancelUserBtn = document.getElementById('cancel-user-btn');
|
51 | 51 |
|
| 52 | + // VVV НОВОЕ: Элементы для модального окна управления правами VVV |
| 53 | + const permissionsModal = document.getElementById('permissions-modal'); |
| 54 | + const permissionsModalCloseBtn = document.getElementById('permissions-modal-close-btn'); |
| 55 | + const permissionsModalTitle = document.getElementById('permissions-modal-title'); |
| 56 | + const permissionsListEl = document.getElementById('permissions-list'); |
| 57 | + const savePermissionsBtn = document.getElementById('save-permissions-btn'); |
| 58 | + const cancelPermissionsBtn = document.getElementById('cancel-permissions-btn'); |
| 59 | + |
52 | 60 | let toastTimeout;
|
53 | 61 | let editingCameraId = null;
|
54 | 62 | let settingsCameraId = null;
|
55 | 63 | let rangeSyncFunctions = {};
|
56 | 64 | let selectedDiscoveredDevice = null;
|
57 | 65 | let isDiscovering = false;
|
| 66 | + let editingPermissionsForUser = null; |
| 67 | + |
| 68 | + const availablePermissions = [ |
| 69 | + { key: 'view_archive', labelKey: 'view_archive', defaultLabel: 'Просмотр архива' }, |
| 70 | + { key: 'export_archive', labelKey: 'export_archive', defaultLabel: 'Экспорт из архива' }, |
| 71 | + { key: 'edit_cameras', labelKey: 'edit_cameras', defaultLabel: 'Управление камерами' }, |
| 72 | + { key: 'delete_cameras', labelKey: 'delete_cameras', defaultLabel: 'Удаление камер' }, |
| 73 | + { key: 'access_settings', labelKey: 'access_settings', defaultLabel: 'Доступ к настройкам' }, |
| 74 | + { key: 'manage_layout', labelKey: 'manage_layout', defaultLabel: 'Управление сеткой' }, |
| 75 | + ]; |
58 | 76 |
|
59 | 77 | const openModal = (modalElement) => modalElement.classList.remove('hidden');
|
60 | 78 | const closeModal = (modalElement) => {
|
|
129 | 147 | allTabs.forEach(btn => {
|
130 | 148 | const tabName = btn.dataset.tab;
|
131 | 149 | const isGeneralTab = tabName === 'tab-general';
|
132 |
| - // --- ИЗМЕНЕНИЕ: Логика для вкладки пользователей удалена отсюда --- |
133 | 150 | const isCameraTab = !isGeneralTab;
|
134 | 151 |
|
135 | 152 | if (isGeneralSettings) {
|
|
192 | 209 | }
|
193 | 210 | }
|
194 | 211 |
|
195 |
| - // VVV НОВАЯ ФУНКЦИЯ VVV |
196 | 212 | async function openUserManagementModal() {
|
197 | 213 | openModal(userManagementModal);
|
198 | 214 | await renderUserList();
|
|
349 | 365 | if (result.success) {
|
350 | 366 | result.users.forEach(user => {
|
351 | 367 | const li = document.createElement('li');
|
| 368 | + const isCurrentUser = user.username === App.stateManager.state.currentUser?.username; |
| 369 | + |
352 | 370 | li.style.cssText = "display: flex; justify-content: space-between; align-items: center; padding: 10px; border-bottom: 1px solid #eee;";
|
353 | 371 | li.innerHTML = `
|
354 | 372 | <div>
|
355 | 373 | <strong>${user.username}</strong>
|
356 | 374 | <small style="color: #666; margin-left: 10px;">(${App.t('role_' + user.role)})</small>
|
357 | 375 | </div>
|
358 |
| - <div> |
359 |
| - <button class="change-pass-btn" style="margin-right: 10px;">${App.t('change_password')}</button> |
360 |
| - <button class="delete-user-btn" style="color: var(--danger-color);">${App.t('context_delete')}</button> |
| 376 | + <div style="display: flex; align-items: center; gap: 10px;"> |
| 377 | + ${user.role === 'operator' ? `<button class="permissions-btn" data-username="${user.username}">${App.t('permissions_btn', 'Права')}</button>` : ''} |
| 378 | + <button class="change-pass-btn">${App.t('change_password')}</button> |
| 379 | + <button class="delete-user-btn" style="color: var(--danger-color);" ${isCurrentUser ? 'disabled' : ''}>${App.t('context_delete')}</button> |
361 | 380 | </div>
|
362 | 381 | `;
|
363 | 382 |
|
| 383 | + const permissionsBtn = li.querySelector('.permissions-btn'); |
| 384 | + if (permissionsBtn) { |
| 385 | + permissionsBtn.addEventListener('click', () => openPermissionsModal(user)); |
| 386 | + } |
| 387 | + |
364 | 388 | li.querySelector('.change-pass-btn').addEventListener('click', async () => {
|
365 | 389 | const newPassword = prompt(App.t('enter_new_password_for', { username: user.username }));
|
366 | 390 | if (newPassword && newPassword.trim()) {
|
|
418 | 442 | }
|
419 | 443 | }
|
420 | 444 |
|
| 445 | + // VVV НОВЫЕ ФУНКЦИИ ДЛЯ МОДАЛЬНОГО ОКНА ПРАВ VVV |
| 446 | + function openPermissionsModal(user) { |
| 447 | + editingPermissionsForUser = user; |
| 448 | + permissionsModalTitle.textContent = App.t('permissions_for_user', { username: user.username }); |
| 449 | + permissionsListEl.innerHTML = ''; |
| 450 | + |
| 451 | + availablePermissions.forEach(perm => { |
| 452 | + const isChecked = user.permissions && user.permissions[perm.key]; |
| 453 | + const item = document.createElement('div'); |
| 454 | + item.className = 'form-check-inline'; |
| 455 | + item.innerHTML = ` |
| 456 | + <input type="checkbox" id="perm-${perm.key}" data-key="${perm.key}" class="form-check-input" ${isChecked ? 'checked' : ''}> |
| 457 | + <label for="perm-${perm.key}">${App.t(perm.labelKey, perm.defaultLabel)}</label> |
| 458 | + `; |
| 459 | + permissionsListEl.appendChild(item); |
| 460 | + }); |
| 461 | + |
| 462 | + openModal(permissionsModal); |
| 463 | + } |
| 464 | + |
| 465 | + async function savePermissions() { |
| 466 | + if (!editingPermissionsForUser) return; |
| 467 | + |
| 468 | + const newPermissions = {}; |
| 469 | + permissionsListEl.querySelectorAll('input[type="checkbox"]').forEach(checkbox => { |
| 470 | + if (checkbox.checked) { |
| 471 | + newPermissions[checkbox.dataset.key] = true; |
| 472 | + } |
| 473 | + }); |
| 474 | + |
| 475 | + const result = await window.api.updateUserPermissions({ |
| 476 | + username: editingPermissionsForUser.username, |
| 477 | + permissions: newPermissions |
| 478 | + }); |
| 479 | + |
| 480 | + if (result.success) { |
| 481 | + showToast(App.t('permissions_saved_success', 'Права успешно сохранены.')); |
| 482 | + closeModal(permissionsModal); |
| 483 | + await renderUserList(); // Обновляем список, чтобы подтянуть новые данные |
| 484 | + } else { |
| 485 | + alert(`${App.t('error')}: ${result.error}`); |
| 486 | + } |
| 487 | + } |
| 488 | + |
421 | 489 | function init() {
|
422 | 490 | window.api.onOnvifDeviceFound((device) => {
|
423 | 491 | if (discoverList.children.length > 0 && discoverList.children[0].textContent.includes(App.i18n.t('searching_for_cameras'))) {
|
|
447 | 515 | const addCameraSidebarBtn = document.getElementById('add-camera-sidebar-btn');
|
448 | 516 | const addGroupBtn = document.getElementById('add-group-btn');
|
449 | 517 | const generalSettingsBtn = document.getElementById('general-settings-btn');
|
450 |
| - // VVV НОВОЕ VVV |
451 | 518 | const userManagementBtn = document.getElementById('user-management-btn');
|
452 | 519 |
|
453 | 520 | addCameraSidebarBtn.addEventListener('click', () => openAddModal());
|
|
474 | 541 | discoverModal.addEventListener('click', (e) => { if (e.target === discoverModal) closeModal(discoverModal); });
|
475 | 542 | addDiscoveredBtn.addEventListener('click', addDiscoveredCamera);
|
476 | 543 |
|
477 |
| - // VVV НОВОЕ: Обработчики для модального окна управления пользователями VVV |
| 544 | + // VVV Обработчики для модального окна управления пользователями VVV |
478 | 545 | userManagementBtn.addEventListener('click', openUserManagementModal);
|
479 | 546 | userManagementCloseBtn.addEventListener('click', () => closeModal(userManagementModal));
|
480 | 547 | userManagementModal.addEventListener('click', (e) => { if (e.target === userManagementModal) closeModal(userManagementModal); });
|
|
485 | 552 | saveUserBtn.addEventListener('click', saveNewUser);
|
486 | 553 | cancelUserBtn.addEventListener('click', () => closeModal(addUserModal));
|
487 | 554 |
|
| 555 | + // VVV НОВОЕ: Обработчики для модального окна прав VVV |
| 556 | + savePermissionsBtn.addEventListener('click', savePermissions); |
| 557 | + cancelPermissionsBtn.addEventListener('click', () => closeModal(permissionsModal)); |
| 558 | + permissionsModalCloseBtn.addEventListener('click', () => closeModal(permissionsModal)); |
| 559 | + permissionsModal.addEventListener('click', (e) => { if (e.target === permissionsModal) closeModal(permissionsModal); }); |
| 560 | + |
488 | 561 | languageSelect.addEventListener('change', async (e) => {
|
489 | 562 | const newLang = e.target.value;
|
490 | 563 | stateManager.setAppSettings({ language: newLang });
|
|
513 | 586 | }
|
514 | 587 | });
|
515 | 588 |
|
516 |
| - // --- ИЗМЕНЕНИЕ: Упрощенная логика для вкладок настроек --- |
517 | 589 | settingsModal.querySelectorAll('.tab-button').forEach(button => {
|
518 | 590 | button.addEventListener('click', () => {
|
519 | 591 | settingsModal.querySelectorAll('.tab-button, .tab-content').forEach(el => el.classList.remove('active'));
|
|
535 | 607 | closeModal(addGroupModal);
|
536 | 608 | closeModal(discoverModal);
|
537 | 609 | closeModal(addUserModal);
|
538 |
| - closeModal(userManagementModal); // VVV НОВОЕ VVV |
| 610 | + closeModal(permissionsModal); |
| 611 | + closeModal(userManagementModal); |
539 | 612 | }
|
540 | 613 | });
|
541 | 614 | }
|
|
0 commit comments