diff --git a/public/index.html b/public/index.html
index 8a69f34..e744c7b 100644
--- a/public/index.html
+++ b/public/index.html
@@ -36,6 +36,7 @@
+
@@ -135,6 +136,14 @@
| Username | Created | New Password | |
+
+
+
Пользователи клиентов IntraDesk
+
+
+
+
+
diff --git a/public/js/auth.js b/public/js/auth.js
index 727cc9c..5f22ee8 100644
--- a/public/js/auth.js
+++ b/public/js/auth.js
@@ -109,6 +109,50 @@ async function loadCommentCounts() { const d = await apiGet('/api/comments/count
async function loadClientDict() { const d = await apiGet('/api/clients'); if (Array.isArray(d)) window._allClients = d; }
async function loadClientUsers() { const d = await apiGet('/api/client-users'); if (d && typeof d === 'object') window._clientUsers = d; }
+async function syncIntraClients() {
+ const btn = document.getElementById('sync-clients-btn');
+ const statusEl = document.getElementById('sync-clients-status');
+ if (btn) { btn.disabled = true; btn.textContent = '⏳ Синхронизация...'; }
+ if (statusEl) statusEl.textContent = '';
+ try {
+ const r = await apiPost('/api/admin/sync-client-users', {});
+ if (r?.ok) {
+ if (statusEl) statusEl.textContent = `✓ Синхронизировано. Записей в базе: ${r.count}`;
+ await loadClientUsers();
+ renderIntraClientsList();
+ } else {
+ if (statusEl) statusEl.textContent = `❌ ${r?.error || 'Ошибка'}`;
+ }
+ } catch (e) {
+ if (statusEl) statusEl.textContent = `❌ ${e.message}`;
+ } finally {
+ if (btn) { btn.disabled = false; btn.textContent = '↻ Синхронизировать'; }
+ }
+}
+
+function renderIntraClientsList() {
+ const container = document.getElementById('intra-clients-list');
+ if (!container) return;
+ const clientUsers = window._clientUsers || {};
+ const allClients = window._allClients || [];
+ if (!allClients.length) {
+ container.innerHTML = 'Нет данных. Нажмите «Синхронизировать».
';
+ return;
+ }
+ const sorted = [...allClients].sort((a, b) => a.name.localeCompare(b.name, 'ru'));
+ container.innerHTML = sorted.map((c) => {
+ const users = clientUsers[String(c.client_id)] || [];
+ const usersHtml = users.length
+ ? users.map((u) => `${escHtml(u)}
`).join('')
+ : 'нет пользователей
';
+ return `
+
${escHtml(c.name)} (id: ${c.client_id}, ${users.length} польз.)
+ ${usersHtml}
+
`;
+ }).join('');
+}
+
+
async function loadTasksFromServer(silent = false) {
if (!silent && !allData.length) showLoading();
const data = await apiGet('/api/tasks');
@@ -366,6 +410,7 @@ function openSettingsTab(tabName) {
document.querySelectorAll('.settings-tab-pane').forEach((pane) => {
pane.style.display = pane.dataset.tab === tabName ? 'block' : 'none';
});
+ if (tabName === 'intra-clients') renderIntraClientsList();
}
async function loadInternalStatusesAdmin() {