+
Saatavuus-API
Julkinen API jolla verkkosivusto voi tarkistaa palvelun saatavuuden osoitteessa. Palauttaa vain osoite + nopeus - ei asiakastietoja.
@@ -1517,45 +1517,8 @@
-
-
-
-
-
- Integraatiot
-Ota käyttöön ja hallitse ulkoisia integraatioita moduuleittain.
- -
-
-
- - 📧Zammad — Asetukset -
-Synkronoi tiketit Zammad-helpdeskin kautta. O365-sähköpostit kulkevat Zammadin kautta.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Tallenna ensin URL ja token, sitten valitse ryhmät.
-
-
-
-
-
-
-
+
+
+
Telegram-hälytykset
URGENT-prioriteetin tiketit lähettävät hälytyksen Telegram-bottiin.
@@ -1677,6 +1640,46 @@
+
+
+ Integraatiot
+Ota käyttöön ulkoiset integraatiot tälle yritykselle.
+
+
+
+
+
+
+
📧 Zammad-asetukset
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Tallenna ensin, sitten valitse ryhmät.
+
+
+
+
+
+
diff --git a/script.js b/script.js
index 83fb567..eb8dc1a 100644
--- a/script.js
+++ b/script.js
@@ -2361,9 +2361,16 @@ async function loadSettings() {
document.getElementById('settings-telegram-chat').value = config.telegram_chat_id || '';
} catch (e) { console.error(e); }
- // Integraatiot
- loadIntegrations();
- loadZammadConfig();
+ // Näytä API-sivun kortit integraatioiden perusteella
+ try {
+ const integs = await apiCall('integrations');
+ const saatavuusEnabled = integs.find(i => i.type === 'saatavuus_api')?.enabled;
+ const telegramEnabled = integs.find(i => i.type === 'telegram')?.enabled;
+ const saatCard = document.getElementById('settings-saatavuus-api-card');
+ const teleCard = document.getElementById('settings-telegram-card');
+ if (saatCard) saatCard.style.display = saatavuusEnabled ? '' : 'none';
+ if (teleCard) teleCard.style.display = telegramEnabled ? '' : 'none';
+ } catch (e) { console.error(e); }
// Vastauspohjat
loadTemplates();
@@ -2439,168 +2446,11 @@ document.getElementById('btn-test-api').addEventListener('click', async () => {
const INTEGRATION_TYPES = {
zammad: { name: 'Zammad', icon: '📧', desc: 'Synkronoi tiketit Zammad-helpdeskistä (O365-sähköpostit)' },
+ saatavuus_api: { name: 'Saatavuus-API', icon: '🌐', desc: 'Julkinen API saatavuustarkistukseen verkkosivuilla' },
+ telegram: { name: 'Telegram-hälytykset', icon: '🤖', desc: 'URGENT-tikettien hälytykset Telegram-bottiin' },
};
-async function loadIntegrations() {
- const container = document.getElementById('integrations-list');
- if (!container) return;
- try {
- const integrations = await apiCall('integrations');
- renderIntegrations(integrations);
- } catch (e) {
- console.error('loadIntegrations:', e);
- }
-}
-
-function renderIntegrations(integrations) {
- const container = document.getElementById('integrations-list');
- const enabledMap = {};
- integrations.forEach(i => { enabledMap[i.type] = i.enabled; });
-
- let html = '';
- for (const [type, meta] of Object.entries(INTEGRATION_TYPES)) {
- const enabled = enabledMap[type] || false;
- html += `
-
- Tikettejä löytyi: ${res.tickets_found}
- Uusia tikettejä: ${res.created}
- Päivitettyjä: ${res.updated}
- Uusia viestejä: ${res.messages_added}`; - // Päivitä tikettilista jos ollaan tukivälilehdellä - if (typeof loadTickets === 'function') loadTickets(); - } catch (e) { - result.style.background = '#f8d7da'; - result.innerHTML = '❌ ' + e.message; - } -}); +// (Integraatiot hallitaan nyt Yritykset-välilehdellä) // ==================== MODALS ==================== @@ -2735,12 +2585,162 @@ async function showCompanyDetail(id) { // Vaihda aktiivinen yritys jotta API-kutsut kohdistuvat oikein await apiCall('company_switch', 'POST', { company_id: id }); + // Integraatiot — lataa tila + loadCompanyIntegrations(); + // Lataa postilaatikot loadMailboxes(); // Lataa käyttäjäoikeudet loadCompanyUsers(id); } +// ==================== YRITYKSEN INTEGRAATIOT ==================== + +async function loadCompanyIntegrations() { + try { + const integrations = await apiCall('integrations'); + + // Aseta kaikkien integraatioiden checkboxit + ['zammad', 'saatavuus_api', 'telegram'].forEach(type => { + const integ = integrations.find(i => i.type === type); + const cb = document.querySelector(`#integrations-checkboxes input[data-integration="${type}"]`); + if (cb) cb.checked = integ?.enabled || false; + }); + + // Zammad-config näkyvyys + const zammad = integrations.find(i => i.type === 'zammad'); + toggleCompanyZammadConfig(zammad?.enabled || false); + + // Zammad-asetukset + if (zammad?.config) { + document.getElementById('company-zammad-url').value = zammad.config.url || ''; + document.getElementById('company-zammad-token').value = zammad.config.token || ''; + if (zammad.config.group_ids && zammad.config.group_names) { + renderCompanyZammadGroups( + zammad.config.group_names.map((name, i) => ({ id: zammad.config.group_ids[i], name })), + zammad.config.group_ids + ); + } + } else { + document.getElementById('company-zammad-url').value = ''; + document.getElementById('company-zammad-token').value = ''; + document.getElementById('company-zammad-groups').innerHTML = 'Tallenna ensin, sitten valitse ryhmät.'; + } + } catch (e) { console.error('loadCompanyIntegrations:', e); } +} + +function toggleCompanyZammadConfig(show) { + const card = document.getElementById('company-zammad-config'); + if (card) card.style.display = show ? '' : 'none'; +} + +function renderCompanyZammadGroups(groups, selectedIds = []) { + const container = document.getElementById('company-zammad-groups'); + if (!groups.length) { container.innerHTML = 'Ei ryhmiä.'; return; } + container.innerHTML = groups.map(g => ` + + `).join(''); +} + +async function saveCompanyZammad() { + const url = document.getElementById('company-zammad-url').value.trim(); + const token = document.getElementById('company-zammad-token').value.trim(); + const enabled = document.querySelector('#integrations-checkboxes input[data-integration="zammad"]')?.checked || false; + + const groupCbs = document.querySelectorAll('.company-zammad-group-cb:checked'); + const groupIds = Array.from(groupCbs).map(cb => cb.value); + const groupNames = Array.from(groupCbs).map(cb => cb.dataset.name); + + await apiCall('integration_save', 'POST', { + type: 'zammad', + enabled, + config: { url, token, group_ids: groupIds, group_names: groupNames }, + }); +} + +// Integraatio-toggle apufunktio (Saatavuus-API & Telegram) +async function saveSimpleIntegration(type, enabled) { + await apiCall('integration_save', 'POST', { type, enabled, config: {} }); +} + +// Zammad checkbox toggle +document.querySelector('#integrations-checkboxes input[data-integration="zammad"]')?.addEventListener('change', async function() { + toggleCompanyZammadConfig(this.checked); + try { await saveCompanyZammad(); } catch (e) { console.error(e); } +}); + +// Saatavuus-API checkbox toggle +document.querySelector('#integrations-checkboxes input[data-integration="saatavuus_api"]')?.addEventListener('change', async function() { + try { + await saveSimpleIntegration('saatavuus_api', this.checked); + // Päivitä API-sivun kortti + const card = document.getElementById('settings-saatavuus-api-card'); + if (card) card.style.display = this.checked ? '' : 'none'; + } catch (e) { console.error(e); } +}); + +// Telegram checkbox toggle +document.querySelector('#integrations-checkboxes input[data-integration="telegram"]')?.addEventListener('change', async function() { + try { + await saveSimpleIntegration('telegram', this.checked); + // Päivitä API-sivun kortti + const card = document.getElementById('settings-telegram-card'); + if (card) card.style.display = this.checked ? '' : 'none'; + } catch (e) { console.error(e); } +}); + +// Lataa ryhmät +document.getElementById('btn-company-zammad-groups')?.addEventListener('click', async () => { + // Tallenna ensin URL ja token + try { + await saveCompanyZammad(); + const groups = await apiCall('zammad_groups'); + const activeGroups = groups.filter(g => g.active); + const integrations = await apiCall('integrations'); + const zammad = integrations.find(i => i.type === 'zammad'); + renderCompanyZammadGroups(activeGroups, zammad?.config?.group_ids || []); + } catch (e) { + alert('Virhe: ' + e.message); + } +}); + +// Testaa yhteys +document.getElementById('btn-company-zammad-test')?.addEventListener('click', async () => { + const result = document.getElementById('company-zammad-result'); + result.style.display = 'block'; + result.style.background = '#f8f9fb'; + result.textContent = 'Testataan...'; + try { + await saveCompanyZammad(); + const res = await apiCall('integration_test', 'POST', { type: 'zammad' }); + result.style.background = '#d4edda'; + result.textContent = `✅ Yhteys OK! Käyttäjä: ${res.user}, Ryhmiä: ${res.groups}`; + } catch (e) { + result.style.background = '#f8d7da'; + result.textContent = '❌ ' + e.message; + } +}); + +// Synkronoi +document.getElementById('btn-company-zammad-sync')?.addEventListener('click', async () => { + const result = document.getElementById('company-zammad-result'); + result.style.display = 'block'; + result.style.background = '#f8f9fb'; + result.innerHTML = '⏳ Synkronoidaan...'; + try { + await saveCompanyZammad(); + const res = await apiCall('zammad_sync', 'POST', {}); + result.style.background = '#d4edda'; + result.innerHTML = `✅ Synkronointi valmis!
Tikettejä: ${res.tickets_found} | Uusia: ${res.created} | Päivitetty: ${res.updated} | Viestejä: ${res.messages_added}`; + } catch (e) { + result.style.background = '#f8d7da'; + result.innerHTML = '❌ ' + e.message; + } +}); + document.getElementById('btn-company-back').addEventListener('click', () => { // Vaihda takaisin alkuperäiseen yritykseen if (currentCompany) apiCall('company_switch', 'POST', { company_id: currentCompany.id });
-
-
`;
- }
- container.innerHTML = html;
-
- // Toggle-napit
- container.querySelectorAll('.integration-enabled').forEach(cb => {
- cb.addEventListener('change', async () => {
- const type = cb.dataset.type;
- const configCard = document.getElementById(type + '-config-card');
- if (configCard) configCard.style.display = cb.checked ? '' : 'none';
- // Tallenna toggle-tila
- try {
- const existing = await apiCall('integrations');
- const old = existing.find(i => i.type === type);
- const config = old?.config || {};
- await apiCall('integration_save', 'POST', { type, enabled: cb.checked, config });
- } catch (e) { console.error(e); }
- });
- });
-
- // Näytä config-kortit käytössä oleville
- integrations.forEach(i => {
- const card = document.getElementById(i.type + '-config-card');
- if (card) card.style.display = i.enabled ? '' : 'none';
- });
-}
-
-async function loadZammadConfig() {
- try {
- const integrations = await apiCall('integrations');
- const zammad = integrations.find(i => i.type === 'zammad');
- if (zammad && zammad.config) {
- document.getElementById('zammad-url').value = zammad.config.url || '';
- document.getElementById('zammad-token').value = zammad.config.token || '';
- // Renderöi ryhmät jos tallennettu
- if (zammad.config.group_ids && zammad.config.group_names) {
- renderZammadGroupCheckboxes(
- zammad.config.group_names.map((name, i) => ({
- id: zammad.config.group_ids[i],
- name: name,
- })),
- zammad.config.group_ids
- );
- }
- }
- } catch (e) { console.error(e); }
-}
-
-function renderZammadGroupCheckboxes(groups, selectedIds = []) {
- const container = document.getElementById('zammad-groups-list');
- if (!groups.length) { container.innerHTML = 'Ei ryhmiä.'; return; }
- container.innerHTML = groups.map(g => `
-
- `).join('');
-}
-
-// Zammad — Tallenna
-document.getElementById('btn-save-zammad')?.addEventListener('click', async () => {
- const url = document.getElementById('zammad-url').value.trim();
- const token = document.getElementById('zammad-token').value.trim();
- if (!url || !token) { alert('URL ja token vaaditaan'); return; }
-
- const groupCbs = document.querySelectorAll('.zammad-group-cb:checked');
- const groupIds = Array.from(groupCbs).map(cb => cb.value);
- const groupNames = Array.from(groupCbs).map(cb => cb.dataset.name);
-
- try {
- await apiCall('integration_save', 'POST', {
- type: 'zammad',
- enabled: document.querySelector('.integration-enabled[data-type="zammad"]')?.checked || false,
- config: { url, token, group_ids: groupIds, group_names: groupNames },
- });
- alert('Zammad-asetukset tallennettu!');
- } catch (e) { alert('Virhe: ' + e.message); }
-});
-
-// Zammad — Testaa yhteys
-document.getElementById('btn-test-zammad')?.addEventListener('click', async () => {
- const result = document.getElementById('zammad-test-result');
- result.style.display = 'block';
- result.style.background = '#f8f9fb';
- result.textContent = 'Testataan yhteyttä...';
- try {
- const res = await apiCall('integration_test', 'POST', { type: 'zammad' });
- result.style.background = '#d4edda';
- result.textContent = `✅ Yhteys OK! Käyttäjä: ${res.user}, Ryhmiä: ${res.groups}`;
- } catch (e) {
- result.style.background = '#f8d7da';
- result.textContent = '❌ ' + e.message;
- }
-});
-
-// Zammad — Lataa ryhmät
-document.getElementById('btn-load-zammad-groups')?.addEventListener('click', async () => {
- try {
- const groups = await apiCall('zammad_groups');
- const activeGroups = groups.filter(g => g.active);
-
- // Hae tallennetut valitut ryhmät
- const integrations = await apiCall('integrations');
- const zammad = integrations.find(i => i.type === 'zammad');
- const selectedIds = zammad?.config?.group_ids || [];
-
- renderZammadGroupCheckboxes(activeGroups, selectedIds);
- } catch (e) { alert('Virhe: ' + e.message); }
-});
-
-// Zammad — Synkronoi nyt
-document.getElementById('btn-sync-zammad')?.addEventListener('click', async () => {
- const result = document.getElementById('zammad-sync-result');
- result.style.display = 'block';
- result.style.background = '#f8f9fb';
- result.innerHTML = '⏳ Synkronoidaan...';
- try {
- const res = await apiCall('zammad_sync', 'POST', {});
- result.style.background = '#d4edda';
- result.innerHTML = `✅ Synkronointi valmis!- Tikettejä löytyi: ${res.tickets_found}
- Uusia tikettejä: ${res.created}
- Päivitettyjä: ${res.updated}
- Uusia viestejä: ${res.messages_added}`; - // Päivitä tikettilista jos ollaan tukivälilehdellä - if (typeof loadTickets === 'function') loadTickets(); - } catch (e) { - result.style.background = '#f8d7da'; - result.innerHTML = '❌ ' + e.message; - } -}); +// (Integraatiot hallitaan nyt Yritykset-välilehdellä) // ==================== MODALS ==================== @@ -2735,12 +2585,162 @@ async function showCompanyDetail(id) { // Vaihda aktiivinen yritys jotta API-kutsut kohdistuvat oikein await apiCall('company_switch', 'POST', { company_id: id }); + // Integraatiot — lataa tila + loadCompanyIntegrations(); + // Lataa postilaatikot loadMailboxes(); // Lataa käyttäjäoikeudet loadCompanyUsers(id); } +// ==================== YRITYKSEN INTEGRAATIOT ==================== + +async function loadCompanyIntegrations() { + try { + const integrations = await apiCall('integrations'); + + // Aseta kaikkien integraatioiden checkboxit + ['zammad', 'saatavuus_api', 'telegram'].forEach(type => { + const integ = integrations.find(i => i.type === type); + const cb = document.querySelector(`#integrations-checkboxes input[data-integration="${type}"]`); + if (cb) cb.checked = integ?.enabled || false; + }); + + // Zammad-config näkyvyys + const zammad = integrations.find(i => i.type === 'zammad'); + toggleCompanyZammadConfig(zammad?.enabled || false); + + // Zammad-asetukset + if (zammad?.config) { + document.getElementById('company-zammad-url').value = zammad.config.url || ''; + document.getElementById('company-zammad-token').value = zammad.config.token || ''; + if (zammad.config.group_ids && zammad.config.group_names) { + renderCompanyZammadGroups( + zammad.config.group_names.map((name, i) => ({ id: zammad.config.group_ids[i], name })), + zammad.config.group_ids + ); + } + } else { + document.getElementById('company-zammad-url').value = ''; + document.getElementById('company-zammad-token').value = ''; + document.getElementById('company-zammad-groups').innerHTML = 'Tallenna ensin, sitten valitse ryhmät.'; + } + } catch (e) { console.error('loadCompanyIntegrations:', e); } +} + +function toggleCompanyZammadConfig(show) { + const card = document.getElementById('company-zammad-config'); + if (card) card.style.display = show ? '' : 'none'; +} + +function renderCompanyZammadGroups(groups, selectedIds = []) { + const container = document.getElementById('company-zammad-groups'); + if (!groups.length) { container.innerHTML = 'Ei ryhmiä.'; return; } + container.innerHTML = groups.map(g => ` + + `).join(''); +} + +async function saveCompanyZammad() { + const url = document.getElementById('company-zammad-url').value.trim(); + const token = document.getElementById('company-zammad-token').value.trim(); + const enabled = document.querySelector('#integrations-checkboxes input[data-integration="zammad"]')?.checked || false; + + const groupCbs = document.querySelectorAll('.company-zammad-group-cb:checked'); + const groupIds = Array.from(groupCbs).map(cb => cb.value); + const groupNames = Array.from(groupCbs).map(cb => cb.dataset.name); + + await apiCall('integration_save', 'POST', { + type: 'zammad', + enabled, + config: { url, token, group_ids: groupIds, group_names: groupNames }, + }); +} + +// Integraatio-toggle apufunktio (Saatavuus-API & Telegram) +async function saveSimpleIntegration(type, enabled) { + await apiCall('integration_save', 'POST', { type, enabled, config: {} }); +} + +// Zammad checkbox toggle +document.querySelector('#integrations-checkboxes input[data-integration="zammad"]')?.addEventListener('change', async function() { + toggleCompanyZammadConfig(this.checked); + try { await saveCompanyZammad(); } catch (e) { console.error(e); } +}); + +// Saatavuus-API checkbox toggle +document.querySelector('#integrations-checkboxes input[data-integration="saatavuus_api"]')?.addEventListener('change', async function() { + try { + await saveSimpleIntegration('saatavuus_api', this.checked); + // Päivitä API-sivun kortti + const card = document.getElementById('settings-saatavuus-api-card'); + if (card) card.style.display = this.checked ? '' : 'none'; + } catch (e) { console.error(e); } +}); + +// Telegram checkbox toggle +document.querySelector('#integrations-checkboxes input[data-integration="telegram"]')?.addEventListener('change', async function() { + try { + await saveSimpleIntegration('telegram', this.checked); + // Päivitä API-sivun kortti + const card = document.getElementById('settings-telegram-card'); + if (card) card.style.display = this.checked ? '' : 'none'; + } catch (e) { console.error(e); } +}); + +// Lataa ryhmät +document.getElementById('btn-company-zammad-groups')?.addEventListener('click', async () => { + // Tallenna ensin URL ja token + try { + await saveCompanyZammad(); + const groups = await apiCall('zammad_groups'); + const activeGroups = groups.filter(g => g.active); + const integrations = await apiCall('integrations'); + const zammad = integrations.find(i => i.type === 'zammad'); + renderCompanyZammadGroups(activeGroups, zammad?.config?.group_ids || []); + } catch (e) { + alert('Virhe: ' + e.message); + } +}); + +// Testaa yhteys +document.getElementById('btn-company-zammad-test')?.addEventListener('click', async () => { + const result = document.getElementById('company-zammad-result'); + result.style.display = 'block'; + result.style.background = '#f8f9fb'; + result.textContent = 'Testataan...'; + try { + await saveCompanyZammad(); + const res = await apiCall('integration_test', 'POST', { type: 'zammad' }); + result.style.background = '#d4edda'; + result.textContent = `✅ Yhteys OK! Käyttäjä: ${res.user}, Ryhmiä: ${res.groups}`; + } catch (e) { + result.style.background = '#f8d7da'; + result.textContent = '❌ ' + e.message; + } +}); + +// Synkronoi +document.getElementById('btn-company-zammad-sync')?.addEventListener('click', async () => { + const result = document.getElementById('company-zammad-result'); + result.style.display = 'block'; + result.style.background = '#f8f9fb'; + result.innerHTML = '⏳ Synkronoidaan...'; + try { + await saveCompanyZammad(); + const res = await apiCall('zammad_sync', 'POST', {}); + result.style.background = '#d4edda'; + result.innerHTML = `✅ Synkronointi valmis!
Tikettejä: ${res.tickets_found} | Uusia: ${res.created} | Päivitetty: ${res.updated} | Viestejä: ${res.messages_added}`; + } catch (e) { + result.style.background = '#f8d7da'; + result.innerHTML = '❌ ' + e.message; + } +}); + document.getElementById('btn-company-back').addEventListener('click', () => { // Vaihda takaisin alkuperäiseen yritykseen if (currentCompany) apiCall('company_switch', 'POST', { company_id: currentCompany.id });