/** * setup-wizard.tsx - Dailymotion Pro Setup Wizard * * This is the entry point for the setup wizard, which has been modularized. * Logic is now located in src/admin/setup-wizard/ and src/Libs/. * * @file setup-wizard.tsx * @version 2.2.0 */ import { updateFeedback, hideFeedback } from "./Libs/UiHelper"; import { navigateToWizardStep } from "./Admin/SetupWizard/Navigation"; import { changeButtonStatus, configureWizardApi, storeApi as apiStoreApi, setupAutomated as apiSetupAutomated, storeManualEmbedSettings as apiStoreManualEmbedSettings, updateServerStep } from "./Admin/SetupWizard/WizardApi"; import { qs } from "./Libs/Utils"; import { addListeners } from "./Admin/SetupWizard/Listeners"; import { hidePopup, showPopup } from "./Admin/VideoEmbed/Popup"; import { storeContextualSettingsFlow } from "./Admin/Shared/Contextual"; declare const dmProSetupWizard: any; /** * Initialize the setup wizard */ function initializeSetupWizard(): void { configureWizardApi(dmProSetupWizard); const storedPlayerIds = localStorage.getItem('playerIds'); if (storedPlayerIds && storedPlayerIds !== '{}' && storedPlayerIds !== '[]') { try { const playerIds = JSON.parse(storedPlayerIds); if (playerIds.contextual_ids && playerIds.contextual_ids.length > 0) { updatePlayerIdsUI('contextual-player-id', playerIds.contextual_ids); updatePlayerIdsUI('manual-player-id', playerIds.ids); } } catch (error) { console.error('Error parsing stored player IDs:', error); } } const urlParams = new URLSearchParams(window.location.search); const stepParam = urlParams.get('step'); if (stepParam) { const step = stepParam.includes('.') ? parseFloat(stepParam) : parseInt(stepParam); if (!isNaN(step)) { navigateToWizardStep(step); } } window.addEventListener('popstate', (event) => { if (event.state && event.state.step !== undefined) { navigateToWizardStep(event.state.step); } }); } /** * Update Player IDs in UI */ function updatePlayerIdsUI(elementId: string, data: any[]): void { const actualElementId = elementId === 'contextual-player-ids' ? 'contextual-player-id' : elementId; const playerIdsList = qs(actualElementId); if (playerIdsList) { const options = data.map(player => ``).join(''); playerIdsList.innerHTML = `` + options; } } /** * Refactored Event Listeners (Declarative) */ function addEventListeners(): void { const selectors = { '#go-to-step-2': () => navigateToWizardStep(2), // From Welcome to Connection '#go-to-step-2-1': () => navigateToWizardStep(2.1), // From Connection to form connection '#back-to-step-2': () => navigateToWizardStep(2), '#back-to-step-3': () => navigateToWizardStep(3), '#back-to-step-4': () => navigateToWizardStep(4), 'button[onclick="nextStep(1)"]': () => navigateToWizardStep(1), '.feedback-close': () => { const feedbackElement = document.querySelector('.feedback') as HTMLElement; if (feedbackElement) hideFeedback(feedbackElement); }, '#confirmContextual .btn.btn-primary': async () => { await storeContextualSettingsFlow(); } }; // Attach simple click listeners // @ts-ignore Object.entries(selectors).forEach(([selector, handler]) => { const elements = document.querySelectorAll(selector); elements.forEach(el => { el.removeAttribute('onclick'); el.addEventListener('click', (e) => { e.preventDefault(); handler(); }); }); }); // TODO: refactor this on the next cycle // Handle open/close popups document.querySelectorAll('[onclick="openPopupBtn()"]').forEach(el => { el.removeAttribute('onclick'); el.addEventListener('click', () => showPopup('confirmSkip')); }); document.querySelectorAll('[onclick="closePopup()"]').forEach(el => { el.removeAttribute('onclick'); el.addEventListener('click', () => { hidePopup('confirmSkip'); hidePopup('confirmContextual'); }); }); // Forms const attachFormHandler = (selector: string, handler: (e: Event) => void) => { const form = document.querySelector(selector); if (form) { form.removeAttribute('onsubmit'); form.addEventListener('submit', handler); } }; // This process will go to the default embed settings page. attachFormHandler('form[onsubmit="storeApi()"]', async (e) => { e.preventDefault(); changeButtonStatus('api-store__button', 'loading', 'Storing...'); const apiData = { api_key: (qs('api-key') as HTMLInputElement).value, api_secret: (qs('api-secret') as HTMLInputElement).value, channel_id: (qs('channel-id') as HTMLInputElement).value, }; try { const data = await apiStoreApi(apiData); if (data.data.status === 200) { changeButtonStatus('api-store__button', 'success', 'Stored Successfully'); updateFeedback(data.message, 'feedback-success'); setTimeout(() => { window.location.href = dmProSetupWizard.adminUrl + 'admin.php?page=dm-pro-admin-panel&subpage=setup-wizard&step=3'; }, 3000); } else { changeButtonStatus('api-store__button', 'error'); updateFeedback(data.message, 'feedback-error'); } } catch (error: any) { changeButtonStatus('api-store__button', 'error'); updateFeedback(error.message, 'feedback-error'); } }); attachFormHandler('form[onsubmit="storeContextualEmbedSettings()"]', async (e) => { e.preventDefault(); const contextualEmbedEnabled = (qs('contextual_embed') as HTMLInputElement)?.checked; if (contextualEmbedEnabled) { showPopup('confirmContextual'); } else { console.warn('Form submitted with contextual embed disabled - this should not happen'); } }); attachFormHandler('form[onsubmit="storeManualEmbedSettings()"]', async (e) => { e.preventDefault(); changeButtonStatus('manual-embed-settings__button', 'loading', 'Storing...'); const manualPlayerIdField = qs('manual-player-id') as HTMLSelectElement | null; const settingsData = { manual_player_id: manualPlayerIdField ? manualPlayerIdField.value : '', manual_video_heading: (qs('manual-video-heading') as HTMLInputElement)?.checked, manual_video_heading_text: (qs('manual-video-heading-text') as HTMLInputElement)?.value, manual_font_heading: (qs('manual-font-heading') as HTMLSelectElement)?.value, manual_heading_size: (qs('manual-heading-size') as HTMLSelectElement)?.value, manual_mute: (qs('manual-mute') as HTMLInputElement)?.checked, manual_video_title: (qs('manual-video-title') as HTMLInputElement)?.checked, manual_font_title: (qs('manual-font-title') as HTMLSelectElement)?.value, manual_title_size: (qs('manual-title-size') as HTMLSelectElement)?.value }; try { const data = await apiStoreManualEmbedSettings(settingsData); if (data.data.status === 200) { changeButtonStatus('manual-embed-settings__button', 'success', 'Stored Successfully'); const contextualSlot = document.querySelector('.progress-bar .slot[data-step="4"]'); const nextStep = contextualSlot ? 4 : 5; navigateToWizardStep(nextStep); updateFeedback(data.message, 'feedback-success'); } else { changeButtonStatus('manual-embed-settings__button', 'error'); updateFeedback(data.message, 'feedback-error'); } } catch (error: any) { changeButtonStatus('manual-embed-settings__button', 'error'); updateFeedback(error.message, 'feedback-error'); } }); // Special Buttons const attachClickListener = (selector: string, handler: () => void) => { document.querySelectorAll(selector).forEach(el => { el.removeAttribute('onclick'); el.addEventListener('click', (e) => { e.preventDefault(); handler(); }); }); }; attachClickListener('[onclick="setupDefault()"]', async () => { const setupDefaultButton = qs('go-to-step-3-1'); const shouldFetchPlayerIds = setupDefaultButton?.dataset.fetchPlayerIds === 'true'; try { changeButtonStatus('go-to-step-3-1', 'loading', 'Processing...'); if (shouldFetchPlayerIds) { const data = await apiSetupAutomated(); localStorage.setItem('playerIds', JSON.stringify(data)); updatePlayerIdsUI('manual-player-id', data.ids); } changeButtonStatus('go-to-step-3-1', 'success', 'Process finished'); } catch (error: any) { // Player ID fetch is optional for this flow; continue to form. updateFeedback(error.message || 'Failed to fetch player IDs', 'feedback-error'); } finally { navigateToWizardStep(3.1); } }); attachClickListener('[onclick="setupAutomated()"]', async () => { try { changeButtonStatus('go-to-step-4-1', 'loading', 'Processing...'); const data = await apiSetupAutomated(); localStorage.setItem('playerIds', JSON.stringify(data)); updatePlayerIdsUI('contextual-player-id', data.contextual_ids); changeButtonStatus('go-to-step-4-1', 'success', 'Process finished'); setTimeout(() => { window.location.href = dmProSetupWizard.adminUrl + 'admin.php?page=dm-pro-admin-panel&subpage=setup-wizard&step=4.1'; }, 300); } catch (error: any) { updateFeedback(error.message || 'Failed to fetch player IDs', 'feedback-error'); } }); attachClickListener('[onclick="skipSetup()"]', async () => { try { await updateServerStep(-1, { flow: 'default', skip_step: 0 }); localStorage.removeItem('playerIds'); setTimeout(() => { window.location.href = "admin.php?page=dm-pro-admin-panel&subpage=dashboard"; }, 300); } catch (error: any) { updateFeedback(error.message, 'feedback-error', 0); } }); attachClickListener('[onclick="skipConnectStep()"]', async () => { try { await updateServerStep(3, { flow: 'dynamic4', skip_step: 2 }); // The remove playerIds from local storage and redirect to step 3 is substituted to navigateToWizardStep(3) localStorage.removeItem('playerIds'); window.location.href = dmProSetupWizard.adminUrl + 'admin.php?page=dm-pro-admin-panel&subpage=setup-wizard&step=3'; } catch (error: any) { updateFeedback(error.message || 'Failed to skip connect step', 'feedback-error'); } }); attachClickListener('[onclick="skipDefaultStep()"]', () => { const contextualSlot = document.querySelector('.progress-bar .slot[data-step="4"]'); const nextStep = contextualSlot ? 4 : 5; navigateToWizardStep(nextStep, { skip_step: 3 }); }); attachClickListener('[onclick="skipToFinishStep()"]', () => navigateToWizardStep(5, { skip_step: 4 })); } // Initial Run document.addEventListener('DOMContentLoaded', () => { initializeSetupWizard(); addEventListeners(); addListeners(); });