(() => { const { TARGET_ORIGIN, TARGET_PATHNAME, TARGET_PARAM, TARGET_PARAM_VALUE, TARGET_APP_URL, HCM_ORIGIN, HCM_WELCOME_PATHNAME, HCM_MY_INFORMATION_APPS_GROUP_ID, WORKLIST_ORIGIN, WORKLIST_SAASUI_PATHNAME, USER_BUTTON_LABEL, ALLOWED_STAGE_TYPES, SELECTORS, IDS, CLASSES, STORAGE_KEYS, CACHE, DETAIL_SORT_KEYS, BRIDGE, API_ENDPOINTS, COMCIP_REQUEST, COMCIP_TIME_ENTRY_FRAME_ID, ACTION_TEAM_OPTIONS, ACTION_COMPLEXITY_OPTIONS, } = globalThis.ArchPanelConfig; const storageService = globalThis.ArchPanelStorageService; const chromeService = globalThis.ArchPanelChromeService; const { normalizeText, cleanString, firstNonEmptyString, normalizeString, toNumber, toIsoDateString, extractArray, mapWithConcurrency, getFieldValue, flattenDisplayRecord, isVisible, formatWholeNumber, formatCurrency, formatHours, formatWeekNumber, formatOperationalWeekLabel, formatPercent, formatProgressPercent, formatDate, getDateInputValue, formatDateInputDisplay, formatDateForTimeEntryRequest, parseTimeEntryDate, formatDateTime, getLocalDateKey, getOperationalWeekInfo, getCalendarRowWeekDate, parseDatePreservingDateOnly, getErrorMessage, escapeHtml, cssEscape, } = globalThis.ArchPanelUtils; const { getStoredTheme, setStoredTheme, getStoredSidebarCollapsed, setStoredSidebarCollapsed, getStoredCalendarView, setStoredCalendarView, getStoredTimeManagementSelectedDate, setStoredTimeManagementSelectedDate, } = globalThis.ArchPanelPreferencesService.create({ STORAGE_KEYS, getDateInputValue, parseDatePreservingDateOnly, }); const { applyDialogTheme, ensureStyles, applyTheme, findUserAnchor, resolveInsertionTarget, lockScroll, unlockScroll, } = globalThis.ArchPanelShellView.create({ IDS, CLASSES, USER_BUTTON_LABEL, normalizeText, isVisible, }); const { normalizeWorkload, isWonWorkload, normalizeTeamValue, teamContainsUser, stripTransientFields, createExportPayload, createDatasetSnapshot, normalizeCachedExportPayload, } = globalThis.ArchPanelWorkloadDatasetDomain.create({ ALLOWED_STAGE_TYPES, cleanString, firstNonEmptyString, normalizeString, toNumber, extractArray, formatDateTime, normalizePendingServiceRequests: (...args) => comcipRepository.normalizePendingServiceRequests(...args), }); const { buildWorkloadStartCalendar, getWeekStartDate, getCalendarAnchorDate, } = globalThis.ArchPanelWorkloadCalendarDomain.create({ getLocalDateKey, getOperationalWeekInfo, getCalendarRowWeekDate, formatOperationalWeekLabel, formatDate, parseDatePreservingDateOnly, }); const { readCachedDataset, writeCachedDataset, readCachedTaskTypePayload, writeCachedTaskTypePayload, writeCachedWorklistToken, readCachedWorklistToken, } = globalThis.ArchPanelCacheRepository.create({ CACHE, storageService, normalizeCachedExportPayload, cleanString, }); const hcmPage = globalThis.ArchPanelHcmPage.create({ HCM_MY_INFORMATION_APPS_GROUP_ID, WORKLIST_ORIGIN, WORKLIST_SAASUI_PATHNAME, IDS, cleanString, hcmTileTemplate: globalThis.ArchPanelTemplates.hcmTile, onOpenArchPanel: openModal, writeCachedWorklistToken, }); const appState = { theme: getStoredTheme(), sidebarCollapsed: getStoredSidebarCollapsed(), calendarYear: new Date().getFullYear(), calendarMonth: new Date().getMonth(), calendarView: getStoredCalendarView(), calendarAnchorDateKey: getLocalDateKey(new Date()), status: "idle", loadingMessage: "", loadingProgress: 0, errorMessage: "", dataset: null, sessionAuthHeaders: {}, detailModal: null, actionFormModal: null, rampComparisonModal: null, forecastUpdateConfirmModal: null, timeEntriesDrawer: null, timeManagementModal: null, taskTypeCache: { promise: null, }, timeManagementActivityCache: new Map(), pendingTimeManagementHighlightRowId: "", timeManagementDatePicker: { isOpen: false, year: new Date().getFullYear(), month: new Date().getMonth(), }, pendingFocusSelector: "", spaFrameLifecycleIntervalId: null, lastSpaFrameLifecycleError: "", }; let syncFrame = 0; let restoreFocusTarget = null; let closeTimer = 0; const { ensurePageBridge, fetchJson, sendComcipRequestMessage, ensureSpaFrame, handleBridgeMessage, } = globalThis.ArchPanelTransportService.create({ TARGET_ORIGIN, TARGET_APP_URL, IDS, BRIDGE, COMCIP_REQUEST, COMCIP_TIME_ENTRY_FRAME_ID, chromeService, cleanString, firstNonEmptyString, isHcmWelcomePage, getSessionAuthHeaders: () => appState.sessionAuthHeaders, setSessionAuthHeaders: (headers) => { appState.sessionAuthHeaders = headers; }, }); const createExportHtml = globalThis.ArchPanelExportHtml.createExportHtml; const { renderServiceRequestDetailTable, renderSortButton, renderOpportunityLink, renderWorkloadLink, getHeaderSummary, } = globalThis.ArchPanelRenderHelpers.create({ appState, escapeHtml, cleanString, formatWholeNumber, formatCurrency, formatDate, formatHours, }); let workbenchController = null; let modalEvents = null; function getSortedDetailItems() { return workbenchController?.getSortedDetailItems() || []; } function findWorkloadById(workloadId) { return workbenchController?.findWorkloadById(workloadId) || null; } function isTargetPage() { const currentUrl = new URL(window.location.href); return ( currentUrl.origin === TARGET_ORIGIN && currentUrl.pathname === TARGET_PATHNAME && currentUrl.searchParams.get(TARGET_PARAM) === TARGET_PARAM_VALUE ); } function isHcmWelcomePage() { const currentUrl = new URL(window.location.href); return ( currentUrl.origin === HCM_ORIGIN && currentUrl.pathname === HCM_WELCOME_PATHNAME ); } function scheduleSync() { if (syncFrame) { return; } syncFrame = window.requestAnimationFrame(() => { syncFrame = 0; syncButton(); }); } function syncButton() { const mount = document.getElementById(IDS.mount); const hcmTile = document.getElementById(IDS.hcmTile); if (isHcmWelcomePage()) { mount?.remove(); ensureStyles(); ensureModal(); hcmPage.syncHcmTile(); ensureSpaFrame(); hcmPage.syncWorklistIframeToken(); return; } if (!isTargetPage()) { mount?.remove(); hcmTile?.remove(); removeModal(); unlockScroll(); return; } hcmTile?.remove(); const header = document.querySelector(SELECTORS.header); const functionsContainer = header?.querySelector(SELECTORS.functions); const anchor = functionsContainer ? findUserAnchor(functionsContainer) : null; if (!header || !functionsContainer) { return; } ensureStyles(); const themedMount = mount ?? createMount(); const overlay = ensureModal(); applyTheme(header, functionsContainer, anchor, themedMount, overlay); const targetSibling = resolveInsertionTarget( functionsContainer, anchor, themedMount ); if ( themedMount.parentElement !== functionsContainer || themedMount.nextElementSibling !== targetSibling ) { const verifiedTarget = targetSibling && targetSibling.parentElement === functionsContainer ? targetSibling : null; if (verifiedTarget) { functionsContainer.insertBefore(themedMount, verifiedTarget); } else { functionsContainer.appendChild(themedMount); } } } function createMount() { const mount = document.createElement("div"); mount.id = IDS.mount; mount.className = "arch-panel-extension-entry"; const button = document.createElement("button"); button.id = IDS.button; button.type = "button"; button.className = "arch-panel-extension-button"; button.textContent = "Arch panel"; button.setAttribute("aria-label", "Open Arch panel"); button.addEventListener("click", openModal); mount.appendChild(button); return mount; } function ensureModal() { const existingOverlay = document.getElementById(IDS.overlay); if (existingOverlay) { return existingOverlay; } const overlay = document.createElement("div"); overlay.id = IDS.overlay; overlay.className = "arch-panel-extension-overlay"; overlay.hidden = true; overlay.setAttribute("aria-hidden", "true"); overlay.addEventListener("click", modalEvents.handleOverlayClick); overlay.addEventListener("change", modalEvents.handleOverlayChange); overlay.addEventListener("input", modalEvents.handleOverlayInput); overlay.addEventListener("keydown", modalEvents.handleOverlayKeydown); overlay.addEventListener("focusin", modalEvents.handleOverlayFocusIn); overlay.addEventListener("pointerover", modalEvents.handleOverlayPointerOver); overlay.addEventListener("pointermove", modalEvents.handleOverlayPointerMove); overlay.addEventListener("pointerout", modalEvents.handleOverlayPointerOut); overlay.addEventListener("scroll", modalEvents.handleOverlayScroll, true); document.body.appendChild(overlay); renderModal(); return overlay; } function renderModal() { const overlay = document.getElementById(IDS.overlay); if (!overlay) { return; } const previousScrollState = captureModalScrollState(overlay); const activeFocusSelector = getRestorableFocusSelector(document.activeElement); const requestedFocusSelector = appState.pendingFocusSelector || activeFocusSelector; overlay.innerHTML = createModalMarkup(); applyDialogTheme(overlay, appState.theme); restoreModalScrollState(overlay, previousScrollState); window.requestAnimationFrame(() => { if (requestedFocusSelector && shouldRestoreFocusAfterRender()) { const focusTarget = overlay.querySelector(requestedFocusSelector); if (focusTarget instanceof HTMLElement) { focusTarget.focus({ preventScroll: true }); if (focusTarget instanceof HTMLInputElement) { focusTarget.select(); } } } appState.pendingFocusSelector = ""; scrollPendingTimeManagementHighlightIntoView(overlay); }); } function shouldRestoreFocusAfterRender() { if (appState.pendingFocusSelector) { return true; } return ( !appState.detailModal && !appState.actionFormModal && !appState.rampComparisonModal && !appState.forecastUpdateConfirmModal && !appState.timeManagementModal ); } function scrollPendingTimeManagementHighlightIntoView(overlay) { const rowId = cleanString(appState.pendingTimeManagementHighlightRowId); if (!rowId) { return; } appState.pendingTimeManagementHighlightRowId = ""; const row = overlay.querySelector( `.arch-panel-extension-time-management-entry-row[data-row-id="${cssEscape(rowId)}"]` ); if (row instanceof HTMLElement) { row.scrollIntoView({ behavior: "smooth", block: "center", inline: "nearest", }); } } function captureModalScrollState(overlay) { const mainShell = overlay.querySelector(".arch-panel-extension-main-shell"); const shellBody = overlay.querySelector(".arch-panel-extension-shell-body"); const dialog = overlay.querySelector(".arch-panel-extension-dialog"); const detailTable = overlay.querySelector( ".arch-panel-extension-table-wrap.is-detail" ); return { windowX: window.scrollX, windowY: window.scrollY, documentTop: document.documentElement.scrollTop, bodyTop: document.body.scrollTop, mainShellTop: mainShell ? mainShell.scrollTop : 0, shellBodyTop: shellBody ? shellBody.scrollTop : 0, dialogTop: dialog ? dialog.scrollTop : 0, detailTableTop: detailTable ? detailTable.scrollTop : 0, detailTableLeft: detailTable ? detailTable.scrollLeft : 0, }; } function restoreModalScrollState(overlay, scrollState) { const restore = () => { const mainShell = overlay.querySelector(".arch-panel-extension-main-shell"); const shellBody = overlay.querySelector(".arch-panel-extension-shell-body"); const dialog = overlay.querySelector(".arch-panel-extension-dialog"); const detailTable = overlay.querySelector( ".arch-panel-extension-table-wrap.is-detail" ); if (mainShell) { mainShell.scrollTop = scrollState.mainShellTop; } if (shellBody) { shellBody.scrollTop = scrollState.shellBodyTop; } if (dialog) { dialog.scrollTop = scrollState.dialogTop; } if (detailTable) { detailTable.scrollTop = scrollState.detailTableTop; detailTable.scrollLeft = scrollState.detailTableLeft; } document.documentElement.scrollTop = scrollState.documentTop; document.body.scrollTop = scrollState.bodyTop; window.scrollTo(scrollState.windowX, scrollState.windowY); }; window.requestAnimationFrame(() => { restore(); window.requestAnimationFrame(restore); }); } function getRestorableFocusSelector(element) { if (!(element instanceof HTMLElement)) { return ""; } const action = element.getAttribute("data-action"); if ( action === "calendar-prev" || action === "calendar-next" || action === "calendar-today" ) { return `[data-action="${action}"]`; } if (action === "calendar-view") { const calendarView = element.getAttribute("data-calendar-view"); return calendarView ? `[data-action="calendar-view"][data-calendar-view="${calendarView}"]` : `[data-action="${action}"]`; } const detailScope = element.getAttribute("data-detail-scope"); const detailValue = element.getAttribute("data-detail-value"); if (detailScope === "calendar-day" && detailValue) { return getCalendarDayFocusSelector(detailValue); } return ""; } function getCalendarDayFocusSelector(dateKey) { return `[data-action="open-detail"][data-detail-scope="calendar-day"][data-detail-value="${dateKey}"]`; } function createModalMarkup() { return `
Enterprise workload intelligence