assets/js/imports.js

/* ==========================================================================
   Import providers
   ========================================================================== */

/*
|--------------------------------------------------------------------------
| Shared import modal
|--------------------------------------------------------------------------
|
| The dashboard uses one import modal for all providers. Provider-specific
| panels are switched from data-import-provider so future importers can be
| added without duplicating modal logic.
|
*/

(() => {
    const availableProviders = new Set([
        'matomo_api',
        'matomo_db',
    ]);

    function importText(message) {
        return {
            error: message?.dataset.error ?? 'Unable to import data.',
            importing: message?.dataset.importing ?? 'Importing data...',
            modeApi: message?.dataset.modeApi ?? 'API',
            modeDatabase: message?.dataset.modeDatabase ?? 'Database',
            networkError: message?.dataset.networkError ?? 'Network error.',
            providerUnavailable: message?.dataset.providerUnavailable ?? 'This platform is not available yet.',
            testing: message?.dataset.testing ?? 'Testing connection...',
        };
    }

    function importFormToObject(form) {
        const data = new FormData(form);
        const result = {};

        for (const [name, value] of data.entries()) {
            result[name] = value;
        }

        form.querySelectorAll('input[type="checkbox"]').forEach((input) => {
            result[input.name] = input.checked;
        });

        return result;
    }

    function providerLabels(message) {
        const text = importText(message);

        return {
            adobe_analytics: 'Adobe Analytics',
            google_analytics: 'Google Analytics',
            matomo_api: `Matomo ${text.modeApi}`,
            matomo_db: `Matomo ${text.modeDatabase}`,
            plausible: 'Plausible',
            umami: 'Umami',
        };
    }

    function setButtonsDisabled(form, disabled) {
        form.querySelectorAll('[data-import-action-button]').forEach((button) => {
            button.disabled = disabled;
        });
    }

    function setMessage(message, text, status = '') {
        if (!message) {
            return;
        }

        message.className = status;
        message.textContent = text || '';
    }

    function setProviderInputsState(form, provider) {
        form.querySelectorAll('[data-import-provider-input]').forEach((input) => {
            input.disabled = input.dataset.importProviderInput !== provider;
        });
    }

    function setProvider(provider, form = document.getElementById('import-form')) {
        if (!form) {
            return;
        }

        const selectedProvider = provider || 'matomo_api';
        const hiddenProvider = form.querySelector('input[name="provider"]');
        const label = form.closest('dialog')?.querySelector('[data-import-provider-label]');
        const message = form.querySelector('#import-message');
        const text = importText(message);
        const labels = providerLabels(message);
        const isAvailable = availableProviders.has(selectedProvider);

        if (hiddenProvider) {
            hiddenProvider.value = selectedProvider;
        }

        if (label) {
            label.textContent = labels[selectedProvider] ?? selectedProvider;
        }

        form.querySelectorAll('[data-import-provider-panel]').forEach((panel) => {
            panel.hidden = panel.dataset.importProviderPanel !== selectedProvider;
        });

        form.querySelectorAll('[data-import-shared-panel]').forEach((panel) => {
            panel.hidden = !isAvailable;
        });

        form.querySelectorAll('[data-import-action-button]').forEach((button) => {
            button.hidden = !isAvailable;
        });

        setProviderInputsState(form, selectedProvider);
        setMessage(message, isAvailable ? '' : text.providerUnavailable, isAvailable ? '' : 'info');
    }

    window.brivaciaSetImportProvider = setProvider;

    const modal = document.getElementById('import-modal');

    if (modal?.dataset.importProvider) {
        setProvider(modal.dataset.importProvider);
    }

    document.addEventListener('change', (event) => {
        const toggle = event.target.closest('[data-import-domain-toggle]');

        if (!toggle) {
            return;
        }

        const panel = toggle.closest('[data-import-provider-panel]');
        const field = panel?.querySelector('[data-import-domain-field]');

        if (field) {
            field.hidden = !toggle.checked;
        }
    });

    document.addEventListener('click', (event) => {
        const button = event.target.closest('#import-form button[value="cancel"]');

        if (!button) {
            return;
        }

        button.closest('dialog')?.close();
    });

    document.addEventListener('click', (event) => {
        const button = event.target.closest('[data-token-toggle]');

        if (!button) {
            return;
        }

        const input = button.previousElementSibling;

        if (!(input instanceof HTMLInputElement)) {
            return;
        }

        input.type = input.type === 'password' ? 'text' : 'password';
    });

    document.addEventListener('submit', async (event) => {
        const form = event.target.closest('#import-form');

        if (!form) {
            return;
        }

        event.preventDefault();

        const provider = form.querySelector('input[name="provider"]')?.value || '';
        const message = form.querySelector('#import-message');
        const text = importText(message);

        if (!availableProviders.has(provider)) {
            setMessage(message, text.providerUnavailable, 'info');
            return;
        }

        const submitter = event.submitter;
        const action = submitter?.value === 'test' ? 'test' : 'import';

        setMessage(message, action === 'test' ? text.testing : text.importing);
        setButtonsDisabled(form, true);

        try {
            const response = await fetch(`/api/import.php?action=${action}`, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify(importFormToObject(form)),
            });

            const data = await response.json();

            if (!response.ok || !data.ok) {
                setMessage(message, data.error || text.error, 'danger');
                return;
            }

            setMessage(message, data.message || '', 'success');

            if (action === 'import') {
                setTimeout(() => {
                    form.closest('dialog')?.close();
                    window.location.reload();
                }, 1200);
            }
        } catch {
            setMessage(message, text.networkError, 'danger');
        } finally {
            setButtonsDisabled(form, false);
        }
    });
})();