Files
breadcrumb-the-shire/modules/helpdesk/web/js/helpdesk-settings.js
fs ea786f5341 feat(helpdesk): add multi-tenant BC connection settings with risk radar refinements
Introduce per-tenant override for helpdesk BC connection config.
New table helpdesk_tenant_settings stores tenant-specific credentials
with encrypted secrets (AES-256-GCM). EffectiveHelpdeskSettingsService
resolves global vs tenant config per request. Settings UI extended with
tenant override tab, toggle, and dual editing mode.

All runtime consumers (OData, SOAP, OAuth) read through the new
resolver. Token cache flushed on any config change. Default behavior
unchanged — tenants use global config until override explicitly enabled.

Also includes risk radar UI refinements: Stripe-style card redesign
with accent borders and score pills, removal of redundant KPI tiles
and search, and filtering of zero-score entries.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 10:29:59 +02:00

159 lines
5.0 KiB
JavaScript

/**
* Helpdesk settings page — auth mode toggle and connection test.
*/
import { showAsyncFlash } from '/js/components/app-async-flash.js';
const settingsForm = document.getElementById('helpdesk-settings-form');
const getMessage = (key, fallback) => {
if (!settingsForm || !settingsForm.dataset) {
return fallback;
}
return settingsForm.dataset[key] || fallback;
};
// Toggle OAuth2 vs Basic Auth field visibility
const authModeSelect = document.getElementById('auth_mode');
const basicFields = document.getElementById('helpdesk-basic-auth-fields');
const oauth2Fields = document.getElementById('helpdesk-oauth2-fields');
const toggleAuthFields = () => {
if (!authModeSelect || !basicFields || !oauth2Fields) {
return;
}
const isOAuth2 = authModeSelect.value === 'oauth2';
basicFields.toggleAttribute('hidden', isOAuth2);
oauth2Fields.toggleAttribute('hidden', !isOAuth2);
};
if (authModeSelect) {
authModeSelect.addEventListener('change', toggleAuthFields);
toggleAuthFields();
}
// Connection test button
const testButton = document.getElementById('helpdesk-test-connection-button');
const testResult = document.getElementById('helpdesk-connection-test-result');
const setTestResult = (variant, message) => {
if (!testResult) {
return;
}
testResult.textContent = message;
testResult.dataset.variant = variant;
testResult.hidden = !message;
};
const setButtonLoadingState = (isLoading) => {
if (!testButton) {
return;
}
const defaultLabel = testButton.dataset.labelDefault || getMessage('testDefaultLabel', 'Test connection');
const loadingLabel = testButton.dataset.labelLoading || getMessage('testLoadingLabel', 'Testing...');
testButton.disabled = isLoading;
testButton.toggleAttribute('aria-busy', isLoading);
testButton.textContent = isLoading ? loadingLabel : defaultLabel;
};
const parseJsonSafely = async (response) => {
try {
return await response.json();
} catch {
return null;
}
};
// Tenant override toggle — show/hide tenant fields + set save_target
const overrideToggle = document.getElementById('helpdesk-override-toggle');
const tenantFields = document.getElementById('helpdesk-tenant-fields');
const saveTargetInput = document.getElementById('helpdesk-settings-save-target');
const tenantAuthModeSelect = document.getElementById('tenant_auth_mode');
const tenantBasicFields = document.getElementById('helpdesk-tenant-basic-auth-fields');
const tenantOauth2Fields = document.getElementById('helpdesk-tenant-oauth2-fields');
if (overrideToggle && tenantFields) {
overrideToggle.addEventListener('change', () => {
tenantFields.hidden = !overrideToggle.checked;
});
}
// On form submit, set save_target based on active tab
if (settingsForm && saveTargetInput) {
settingsForm.addEventListener('submit', () => {
const tenantPanel = settingsForm.querySelector('[data-tab-panel="tenant"]:not([hidden])');
saveTargetInput.value = tenantPanel ? 'tenant' : 'global';
});
}
// Tenant auth mode toggle
if (tenantAuthModeSelect && tenantBasicFields && tenantOauth2Fields) {
tenantAuthModeSelect.addEventListener('change', () => {
const isOAuth2 = tenantAuthModeSelect.value === 'oauth2';
tenantBasicFields.hidden = isOAuth2;
tenantOauth2Fields.hidden = !isOAuth2;
});
}
if (testButton) {
testButton.addEventListener('click', async () => {
setButtonLoadingState(true);
setTestResult('info', getMessage('testLoadingLabel', 'Testing...'));
try {
const csrfMeta = document.querySelector('meta[name="csrf-token"]');
const csrfInput = document.querySelector('input[name="csrf_token"]');
const csrfToken = csrfInput?.value || csrfMeta?.content || '';
const formData = new FormData();
if (csrfToken) {
formData.append('csrf_token', csrfToken);
}
const response = await fetch(
new URL('helpdesk/settings/test-connection-data', document.baseURI).href,
{
method: 'POST',
body: formData,
credentials: 'same-origin',
},
);
const data = await parseJsonSafely(response);
const successMessage = getMessage('testSuccessMessage', 'Connection successful');
const defaultErrorMessage = getMessage('testErrorMessage', 'Connection failed');
if (response.ok && data?.ok) {
const message = data.message || successMessage;
setTestResult('success', message);
showAsyncFlash('success', message);
} else {
let message = defaultErrorMessage;
if (data?.error) {
message = data.error;
} else if (!response.ok) {
message = `${defaultErrorMessage} (HTTP ${response.status})`;
}
if (data?.debug?.http_code) {
message += ` (HTTP ${data.debug.http_code})`;
}
setTestResult('warning', message);
showAsyncFlash('error', message);
}
} catch {
const message = getMessage('testErrorMessage', 'Connection failed');
setTestResult('warning', message);
showAsyncFlash('error', message);
} finally {
setButtonLoadingState(false);
}
});
}