(function () { 'use strict'; function t(app, text) { if (window.OC && OC.L10N && typeof OC.L10N.translate === 'function') { return OC.L10N.translate(app, text); } return text; } function byId(id) { return document.getElementById(id); } function checked(id) { var field = byId(id); return !!(field && field.checked); } function value(id) { var field = byId(id); return field ? field.value : ''; } function setStatus(root, message) { var status = byId('nqs-save-status'); if (status) { status.textContent = message; } } function parseJsonResponse(response) { return response.text().then(function (text) { var data = {}; if (text) { try { data = JSON.parse(text); } catch (_error) { data = {}; } } if (!response.ok || (data && data.ok === false)) { throw new Error((data && data.error) ? data.error : t('nuqloud_scrum', 'Request failed.')); } return data; }); } function postJson(url, data) { return fetch(url, { method: 'POST', credentials: 'same-origin', headers: csrfHeaders(), body: JSON.stringify(data || {}) }).then(parseJsonResponse); } function getJson(url) { return fetch(url, { method: 'GET', credentials: 'same-origin', headers: csrfHeaders() }).then(parseJsonResponse); } function payload() { return { enabled: checked('nqs-enabled'), automationCredentialSource: value('nqs-automation-credential-source'), talkServiceUser: value('nqs-talk-service-user'), talkServiceAppPassword: value('nqs-talk-service-password'), clearTalkServiceAppPassword: checked('nqs-clear-talk-service-password'), workspaceFilterMode: value('nqs-workspace-filter-mode'), workspaceAllowlist: value('nqs-workspace-allowlist'), deckSyncEnabled: checked('nqs-deck-sync-enabled'), fileMirrorEnabled: checked('nqs-file-mirror-enabled'), fileMirrorMode: value('nqs-file-mirror-mode'), reactionWorkflowEnabled: checked('nqs-reaction-workflow-enabled'), botCommandsEnabled: checked('nqs-bot-commands-enabled'), summaryEnabled: checked('nqs-summary-enabled'), syncIntervalMinutes: value('nqs-sync-interval') }; } function csrfHeaders() { var headers = { 'Content-Type': 'application/json', 'Accept': 'application/json' }; if (window.OC && OC.requestToken) { headers.requesttoken = OC.requestToken; } return headers; } function workspaceToggleUrl(root, workspaceId) { var template = root.getAttribute('data-workspace-toggle-url') || ''; return template.replace('WORKSPACE_ID', encodeURIComponent(String(workspaceId))); } function workspaceTasksUrl(root, workspaceId) { var template = root.getAttribute('data-workspace-tasks-url') || ''; return template.replace('WORKSPACE_ID', encodeURIComponent(String(workspaceId))); } function renderWorkspaces(root, workspaces) { var list = byId('nqs-workspaces-list'); if (!list) { return; } list.textContent = ''; if (!workspaces.length) { var empty = document.createElement('p'); empty.className = 'nqs-note'; empty.textContent = root.getAttribute('data-no-conversations-message') || t('nuqloud_scrum', 'No Talk conversations have been discovered yet.'); list.appendChild(empty); return; } workspaces.forEach(function (workspace) { var row = document.createElement('div'); row.className = 'nqs-workspace-row'; row.setAttribute('role', 'listitem'); var meta = document.createElement('div'); meta.className = 'nqs-workspace-meta'; var name = document.createElement('strong'); name.textContent = workspace.talkRoomName || workspace.talkToken || t('nuqloud_scrum', 'Unnamed conversation'); var detail = document.createElement('span'); detail.textContent = workspace.talkToken || ''; meta.appendChild(name); meta.appendChild(detail); var status = document.createElement('span'); status.className = workspace.syncEnabled ? 'nqs-pill nqs-pill-enabled' : 'nqs-pill'; status.textContent = workspace.syncEnabled ? t('nuqloud_scrum', 'Scrum enabled') : t('nuqloud_scrum', 'Scrum disabled'); var button = document.createElement('button'); button.className = 'button'; button.type = 'button'; button.textContent = workspace.syncEnabled ? t('nuqloud_scrum', 'Disable Scrum') : t('nuqloud_scrum', 'Enable Scrum'); button.addEventListener('click', function () { toggleWorkspace(root, Number(workspace.id), !workspace.syncEnabled, button); }); var tasksButton = document.createElement('button'); tasksButton.className = 'button'; tasksButton.type = 'button'; tasksButton.textContent = t('nuqloud_scrum', 'View tasks'); tasksButton.addEventListener('click', function () { toggleTasks(root, Number(workspace.id), row, tasksButton); }); row.appendChild(meta); row.appendChild(status); row.appendChild(button); row.appendChild(tasksButton); list.appendChild(row); }); } function loadWorkspaces(root) { var url = root.getAttribute('data-workspaces-url') || ''; if (!url) { setStatus(root, t('nuqloud_scrum', 'Workspace list endpoint is missing.')); return Promise.resolve(); } return getJson(url).then(function (result) { var data = result && result.data ? result.data : {}; var workspaces = Array.isArray(data.workspaces) ? data.workspaces : []; renderWorkspaces(root, workspaces); }).catch(function (error) { setStatus(root, (root.getAttribute('data-workspace-list-error-message') || t('nuqloud_scrum', 'Unable to load conversations.')) + ' ' + error.message); }); } function toggleWorkspace(root, workspaceId, enabled, button) { var url = workspaceToggleUrl(root, workspaceId); if (!url || !workspaceId) { setStatus(root, root.getAttribute('data-workspace-toggle-error-message') || t('nuqloud_scrum', 'Unable to update conversation Scrum status.')); return; } button.disabled = true; postJson(url, { enabled: enabled }).then(function () { setStatus(root, enabled ? t('nuqloud_scrum', 'Scrum enabled.') : t('nuqloud_scrum', 'Scrum disabled.')); return loadWorkspaces(root); }).catch(function (error) { setStatus(root, (root.getAttribute('data-workspace-toggle-error-message') || t('nuqloud_scrum', 'Unable to update conversation Scrum status.')) + ' ' + error.message); }).finally(function () { button.disabled = false; }); } function toggleTasks(root, workspaceId, row, button) { var existing = row.querySelector('.nqs-task-list'); if (existing) { existing.remove(); button.textContent = t('nuqloud_scrum', 'View tasks'); return; } var url = workspaceTasksUrl(root, workspaceId); if (!url || !workspaceId) { setStatus(root, root.getAttribute('data-task-list-error-message') || t('nuqloud_scrum', 'Unable to load tasks.')); return; } button.disabled = true; getJson(url).then(function (result) { var data = result && result.data ? result.data : {}; var tasks = Array.isArray(data.tasks) ? data.tasks : []; row.appendChild(renderTaskList(root, tasks)); button.textContent = t('nuqloud_scrum', 'Hide tasks'); }).catch(function (error) { setStatus(root, (root.getAttribute('data-task-list-error-message') || t('nuqloud_scrum', 'Unable to load tasks.')) + ' ' + error.message); }).finally(function () { button.disabled = false; }); } function renderTaskList(root, tasks) { var list = document.createElement('div'); list.className = 'nqs-task-list'; if (!tasks.length) { var empty = document.createElement('p'); empty.className = 'nqs-note'; empty.textContent = root.getAttribute('data-no-tasks-message') || t('nuqloud_scrum', 'No tasks have been synced for this conversation yet.'); list.appendChild(empty); return list; } tasks.forEach(function (task) { var item = document.createElement('div'); item.className = 'nqs-task-item'; var title = document.createElement('strong'); title.textContent = task.title || t('nuqloud_scrum', 'Untitled task'); var meta = document.createElement('span'); meta.textContent = [ task.status || 'inbox', task.folderPath || '' ].filter(Boolean).join(' | '); item.appendChild(title); item.appendChild(meta); list.appendChild(item); }); return list; } document.addEventListener('DOMContentLoaded', function () { var root = byId('nqs-admin'); if (!root) { return; } var saveButton = byId('nqs-save-settings'); if (!saveButton) { return; } var loadButton = byId('nqs-load-workspaces'); if (loadButton) { loadButton.addEventListener('click', function () { loadButton.disabled = true; loadWorkspaces(root).finally(function () { loadButton.disabled = false; }); }); } loadWorkspaces(root); saveButton.addEventListener('click', function () { var url = root.getAttribute('data-settings-url') || ''; if (!url) { setStatus(root, t('nuqloud_scrum', 'Settings endpoint is missing.')); return; } saveButton.disabled = true; setStatus(root, t('nuqloud_scrum', 'Saving settings...')); postJson(url, payload()).then(function () { var password = byId('nqs-talk-service-password'); var clearPassword = byId('nqs-clear-talk-service-password'); if (password) { password.value = ''; } if (clearPassword) { clearPassword.checked = false; } setStatus(root, root.getAttribute('data-saved-message') || t('nuqloud_scrum', 'Settings saved.')); }).catch(function (error) { setStatus(root, (root.getAttribute('data-error-message') || t('nuqloud_scrum', 'Unable to save settings.')) + ' ' + error.message); }).finally(function () { saveButton.disabled = false; }); }); var syncButton = byId('nqs-sync-workspaces'); if (!syncButton) { return; } syncButton.addEventListener('click', function () { var url = root.getAttribute('data-sync-workspaces-url') || ''; if (!url) { setStatus(root, t('nuqloud_scrum', 'Workspace sync endpoint is missing.')); return; } syncButton.disabled = true; setStatus(root, t('nuqloud_scrum', 'Syncing workspaces...')); postJson(url, {}).then(function (result) { var data = result && result.data ? result.data : {}; var count = typeof data.createdOrUpdated === 'number' ? data.createdOrUpdated : 0; loadWorkspaces(root); setStatus( root, (root.getAttribute('data-sync-complete-message') || t('nuqloud_scrum', 'Workspace sync complete.')) + ' ' + count + ' ' + t('nuqloud_scrum', 'workspace(s) updated.') ); }).catch(function (error) { setStatus(root, (root.getAttribute('data-sync-error-message') || t('nuqloud_scrum', 'Unable to sync workspaces.')) + ' ' + error.message); }).finally(function () { syncButton.disabled = false; }); }); var messageSyncButton = byId('nqs-sync-messages'); if (!messageSyncButton) { return; } messageSyncButton.addEventListener('click', function () { var url = root.getAttribute('data-sync-messages-url') || ''; if (!url) { setStatus(root, t('nuqloud_scrum', 'Message sync endpoint is missing.')); return; } messageSyncButton.disabled = true; setStatus(root, t('nuqloud_scrum', 'Syncing messages...')); postJson(url, {}).then(function (result) { var data = result && result.data ? result.data : {}; var taskCount = typeof data.tasks === 'number' ? data.tasks : 0; var messageCount = typeof data.messages === 'number' ? data.messages : 0; var fileCount = typeof data.files === 'number' ? data.files : 0; loadWorkspaces(root); setStatus( root, (root.getAttribute('data-message-sync-complete-message') || t('nuqloud_scrum', 'Message sync complete.')) + ' ' + taskCount + ' ' + t('nuqloud_scrum', 'task(s),') + ' ' + messageCount + ' ' + t('nuqloud_scrum', 'message(s),') + ' ' + fileCount + ' ' + (root.getAttribute('data-files-updated-message') || t('nuqloud_scrum', 'file reference(s) updated.')) ); }).catch(function (error) { setStatus(root, (root.getAttribute('data-message-sync-error-message') || t('nuqloud_scrum', 'Unable to sync messages.')) + ' ' + error.message); }).finally(function () { messageSyncButton.disabled = false; }); }); }); }());