From 755267a0b476dc0498ed944056c2e9e1db8530e5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 4 Aug 2025 17:40:08 +0000 Subject: [PATCH 1/9] Initial plan From 711f6c0d0e1029bddc001c7ad5953c92b82fcaf7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 4 Aug 2025 17:53:22 +0000 Subject: [PATCH 2/9] Fix BPMN viewer 404 error logging by suppressing expected directory search failures Co-authored-by: litlfred <662242+litlfred@users.noreply.github.com> --- src/services/githubService.js | 31 ++++++++++++++++++-- src/tests/githubService.bpmn.test.js | 44 ++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 3 deletions(-) diff --git a/src/services/githubService.js b/src/services/githubService.js index 1fc80be6f..f2c710d34 100644 --- a/src/services/githubService.js +++ b/src/services/githubService.js @@ -998,8 +998,30 @@ class GitHubService { // Recursively fetch BPMN files from a directory and its subdirectories async getBpmnFilesRecursive(owner, repo, path, ref = 'main', allFiles = []) { try { - // Use authenticated octokit if available, otherwise create a public instance - const octokit = this.isAuth() ? this.octokit : new Octokit(); + // Create a custom logger that suppresses 404 errors for expected BPMN directory searches + const quietLogger = { + debug: () => {}, + info: () => {}, + warn: (message, ...args) => { + // Suppress 404 warnings for BPMN directory searches + if (typeof message === 'string' && message.includes('404')) { + return; + } + console.warn(message, ...args); + }, + error: (message, ...args) => { + // Suppress 404 errors for BPMN directory searches + if (typeof message === 'string' && message.includes('404')) { + return; + } + console.error(message, ...args); + } + }; + + // Use authenticated octokit if available, otherwise create a public instance with quiet logger + const octokit = this.isAuth() ? this.octokit : new Octokit({ + log: quietLogger + }); const { data } = await octokit.rest.repos.getContent({ owner, @@ -1056,7 +1078,10 @@ class GitHubService { const files = await this.getBpmnFilesRecursive(owner, repo, path, ref); allBpmnFiles.push(...files); } catch (error) { - console.warn(`Could not fetch BPMN files from ${path}:`, error.message); + // Only log warnings for unexpected errors (not 404s which are expected when directories don't exist) + if (error.status !== 404) { + console.warn(`Could not fetch BPMN files from ${path}:`, error.message); + } // Continue trying other paths } } diff --git a/src/tests/githubService.bpmn.test.js b/src/tests/githubService.bpmn.test.js index 81799dd3f..4faea1d14 100644 --- a/src/tests/githubService.bpmn.test.js +++ b/src/tests/githubService.bpmn.test.js @@ -194,5 +194,49 @@ describe('GitHubService BPMN functionality', () => { expect(files).toHaveLength(1); expect(files[0].name).toBe('duplicate.bpmn'); }); + + it('should suppress console warnings for 404 errors', async () => { + const mockError = new Error('Not Found'); + mockError.status = 404; + + // Create a spy on console.warn to verify it's not called for 404 errors + const consoleSpy = jest.spyOn(console, 'warn').mockImplementation(() => {}); + + // Mock all paths to return 404 errors + mockOctokit.rest.repos.getContent.mockRejectedValue(mockError); + + const files = await githubService.getBpmnFiles('owner', 'repo'); + + // Should return empty array when no directories exist + expect(files).toEqual([]); + + // console.warn should not have been called for 404 errors + expect(consoleSpy).not.toHaveBeenCalled(); + + consoleSpy.mockRestore(); + }); + + it('should still log warnings for non-404 errors', async () => { + const mockError = new Error('Internal Server Error'); + mockError.status = 500; + + // Create a spy on console.warn to verify it's called for non-404 errors + const consoleSpy = jest.spyOn(console, 'warn').mockImplementation(() => {}); + + // Mock first path to return 500 error, others to succeed with empty results + mockOctokit.rest.repos.getContent + .mockRejectedValueOnce(mockError) + .mockResolvedValue({ data: [] }); + + const files = await githubService.getBpmnFiles('owner', 'repo'); + + // Should return empty array + expect(files).toEqual([]); + + // console.warn should have been called for the 500 error + expect(consoleSpy).toHaveBeenCalledWith('Could not fetch BPMN files from input/business-processes:', 'Internal Server Error'); + + consoleSpy.mockRestore(); + }); }); }); \ No newline at end of file From 6ce65f44558d602b6e60b33db537d8609d248ffd Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 4 Aug 2025 18:19:18 +0000 Subject: [PATCH 3/9] Restrict BPMN directory search to only input/business-processes and input/business-process as requested Co-authored-by: litlfred <662242+litlfred@users.noreply.github.com> --- src/services/githubService.js | 35 ++++------------------------ src/tests/githubService.bpmn.test.js | 2 +- 2 files changed, 5 insertions(+), 32 deletions(-) diff --git a/src/services/githubService.js b/src/services/githubService.js index f2c710d34..cddf48fdc 100644 --- a/src/services/githubService.js +++ b/src/services/githubService.js @@ -998,30 +998,8 @@ class GitHubService { // Recursively fetch BPMN files from a directory and its subdirectories async getBpmnFilesRecursive(owner, repo, path, ref = 'main', allFiles = []) { try { - // Create a custom logger that suppresses 404 errors for expected BPMN directory searches - const quietLogger = { - debug: () => {}, - info: () => {}, - warn: (message, ...args) => { - // Suppress 404 warnings for BPMN directory searches - if (typeof message === 'string' && message.includes('404')) { - return; - } - console.warn(message, ...args); - }, - error: (message, ...args) => { - // Suppress 404 errors for BPMN directory searches - if (typeof message === 'string' && message.includes('404')) { - return; - } - console.error(message, ...args); - } - }; - - // Use authenticated octokit if available, otherwise create a public instance with quiet logger - const octokit = this.isAuth() ? this.octokit : new Octokit({ - log: quietLogger - }); + // Use authenticated octokit if available, otherwise create a public instance + const octokit = this.isAuth() ? this.octokit : new Octokit(); const { data } = await octokit.rest.repos.getContent({ owner, @@ -1062,15 +1040,10 @@ class GitHubService { async getBpmnFiles(owner, repo, ref = 'main') { const allBpmnFiles = []; - // Try multiple possible directory names where BPMN files might be stored + // Search for BPMN files in the specified business process directories const possiblePaths = [ 'input/business-processes', - 'input/business-process', - 'public/docs/workflows', - 'docs/workflows', - 'workflows', - 'bpmn', - 'processes' + 'input/business-process' ]; for (const path of possiblePaths) { diff --git a/src/tests/githubService.bpmn.test.js b/src/tests/githubService.bpmn.test.js index 4faea1d14..f744f2006 100644 --- a/src/tests/githubService.bpmn.test.js +++ b/src/tests/githubService.bpmn.test.js @@ -223,7 +223,7 @@ describe('GitHubService BPMN functionality', () => { // Create a spy on console.warn to verify it's called for non-404 errors const consoleSpy = jest.spyOn(console, 'warn').mockImplementation(() => {}); - // Mock first path to return 500 error, others to succeed with empty results + // Mock first path to return 500 error, second path to succeed with empty results mockOctokit.rest.repos.getContent .mockRejectedValueOnce(mockError) .mockResolvedValue({ data: [] }); From 45ed57a0ff21f010c587312b3ce318e646fd1c96 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 7 Aug 2025 15:42:01 +0000 Subject: [PATCH 4/9] Fix missing githubService methods and BPMN viewer PageProvider context issues Co-authored-by: litlfred <662242+litlfred@users.noreply.github.com> --- src/components/BPMNViewer.js | 10 ++++++++-- src/components/DAKDashboardWithFramework.js | 4 ++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/components/BPMNViewer.js b/src/components/BPMNViewer.js index 560bd171a..38fc49f93 100644 --- a/src/components/BPMNViewer.js +++ b/src/components/BPMNViewer.js @@ -6,6 +6,14 @@ import { PageLayout, useDAKParams } from './framework'; import './BPMNViewer.css'; const BPMNViewerComponent = () => { + return ( + + + + ); +}; + +const BPMNViewerContent = () => { const location = useLocation(); const navigate = useNavigate(); const viewerRef = useRef(null); @@ -475,7 +483,6 @@ const BPMNViewerComponent = () => { } return ( -
@@ -598,7 +605,6 @@ const BPMNViewerComponent = () => {
-
); }; diff --git a/src/components/DAKDashboardWithFramework.js b/src/components/DAKDashboardWithFramework.js index 7135780bb..3df538985 100644 --- a/src/components/DAKDashboardWithFramework.js +++ b/src/components/DAKDashboardWithFramework.js @@ -32,7 +32,7 @@ const DAKDashboardContent = () => { try { // Check repository permissions - const hasPermission = await githubService.checkRepositoryPermissions(repository.owner.login, repository.name); + const hasPermission = await githubService.checkRepositoryWritePermissions(repository.owner.login, repository.name); setHasWriteAccess(hasPermission); } catch (error) { console.error('Error checking repository permissions:', error); @@ -58,7 +58,7 @@ const DAKDashboardContent = () => { } try { - const issues = await githubService.getRepositoryIssues(repository.owner.login, repository.name); + const issues = await githubService.getIssues(repository.owner.login, repository.name); // Count issues by label const counts = {}; From a16a45fe4b4496304bb87c1ac6b991d610b1cac0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 7 Aug 2025 19:34:27 +0000 Subject: [PATCH 5/9] Fix actor definition schema loading path for GitHub Pages deployment Co-authored-by: litlfred <662242+litlfred@users.noreply.github.com> --- src/services/actorDefinitionService.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/actorDefinitionService.js b/src/services/actorDefinitionService.js index 3d9702252..283ad3858 100644 --- a/src/services/actorDefinitionService.js +++ b/src/services/actorDefinitionService.js @@ -18,7 +18,7 @@ class ActorDefinitionService { */ async loadSchema() { try { - const response = await fetch('/schemas/actor-definition.json'); + const response = await fetch(`${process.env.PUBLIC_URL || ''}/schemas/actor-definition.json`); this.actorSchema = await response.json(); } catch (error) { console.warn('Could not load actor definition schema:', error); From 4bfd8da6ad79ffaaf0b0e663666203cdca596435 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 7 Aug 2025 19:57:47 +0000 Subject: [PATCH 6/9] Remove excessive console.log statements from PageProvider to clean up console output Co-authored-by: litlfred <662242+litlfred@users.noreply.github.com> --- src/components/framework/PageProvider.js | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/components/framework/PageProvider.js b/src/components/framework/PageProvider.js index b2a6d6507..fa6278f61 100644 --- a/src/components/framework/PageProvider.js +++ b/src/components/framework/PageProvider.js @@ -24,7 +24,6 @@ const PageContext = createContext(null); */ export const usePage = () => { const context = useContext(PageContext); - console.log('usePage: called, context is:', context ? 'available' : 'null'); if (!context) { console.error('usePage: PageContext is null - component not wrapped in PageProvider'); throw new Error('usePage must be used within a PageProvider'); @@ -39,9 +38,6 @@ const determinePageType = (params) => { const { user, repo } = params; const asset = params['*']; // Wildcard parameter for asset path - console.log('PageProvider: determinePageType called with params:', params); - console.log('PageProvider: extracted values:', { user, repo, asset }); - if (asset) return PAGE_TYPES.ASSET; if (user && repo) return PAGE_TYPES.DAK; if (user) return PAGE_TYPES.USER; @@ -56,12 +52,6 @@ export const PageProvider = ({ children, pageName }) => { const location = useLocation(); const navigate = useNavigate(); - console.log('PageProvider: initialized with:', { - pageName, - params, - locationPathname: location.pathname - }); - const [pageState, setPageState] = useState({ type: determinePageType(params), pageName, From d197dce7d5e7ecf12a3c4d55219d2b78973c9d0b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 8 Aug 2025 15:19:41 +0000 Subject: [PATCH 7/9] Add detailed debug logging to BPMN file search to diagnose directory search issues Co-authored-by: litlfred <662242+litlfred@users.noreply.github.com> --- src/services/githubService.js | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/services/githubService.js b/src/services/githubService.js index cddf48fdc..26bcda3e7 100644 --- a/src/services/githubService.js +++ b/src/services/githubService.js @@ -998,8 +998,10 @@ class GitHubService { // Recursively fetch BPMN files from a directory and its subdirectories async getBpmnFilesRecursive(owner, repo, path, ref = 'main', allFiles = []) { try { + console.log(`🔎 githubService.getBpmnFilesRecursive: Searching ${owner}/${repo}/${path} (ref: ${ref})`); // Use authenticated octokit if available, otherwise create a public instance const octokit = this.isAuth() ? this.octokit : new Octokit(); + console.log(`🔐 githubService.getBpmnFilesRecursive: Using ${this.isAuth() ? 'authenticated' : 'public'} octokit`); const { data } = await octokit.rest.repos.getContent({ owner, @@ -1008,9 +1010,12 @@ class GitHubService { ref }); + console.log(`📦 githubService.getBpmnFilesRecursive: Received data type: ${Array.isArray(data) ? 'array' : 'single file'}, length: ${Array.isArray(data) ? data.length : 1}`); + // Handle single file response if (!Array.isArray(data)) { if (data.name.endsWith('.bpmn')) { + console.log(`📄 githubService.getBpmnFilesRecursive: Found single BPMN file: ${data.name}`); allFiles.push(data); } return allFiles; @@ -1019,15 +1024,19 @@ class GitHubService { // Handle directory response for (const item of data) { if (item.type === 'file' && item.name.endsWith('.bpmn')) { + console.log(`📄 githubService.getBpmnFilesRecursive: Found BPMN file: ${item.name}`); allFiles.push(item); } else if (item.type === 'dir') { + console.log(`📁 githubService.getBpmnFilesRecursive: Found subdirectory: ${item.name}, recursing...`); // Recursively search subdirectories await this.getBpmnFilesRecursive(owner, repo, item.path, ref, allFiles); } } + console.log(`✅ githubService.getBpmnFilesRecursive: Completed search of ${path}, found ${allFiles.length} total files so far`); return allFiles; } catch (error) { + console.log(`❌ githubService.getBpmnFilesRecursive: Error searching ${path}:`, error.status, error.message); // If directory doesn't exist, return empty array (not an error) if (error.status === 404) { return allFiles; @@ -1038,6 +1047,7 @@ class GitHubService { // Get all BPMN files from a repository's business process directories async getBpmnFiles(owner, repo, ref = 'main') { + console.log(`🔍 githubService.getBpmnFiles: Starting search for ${owner}/${repo} (ref: ${ref})`); const allBpmnFiles = []; // Search for BPMN files in the specified business process directories @@ -1048,12 +1058,16 @@ class GitHubService { for (const path of possiblePaths) { try { + console.log(`📁 githubService.getBpmnFiles: Searching in directory: ${path}`); const files = await this.getBpmnFilesRecursive(owner, repo, path, ref); + console.log(`✅ githubService.getBpmnFiles: Found ${files.length} BPMN files in ${path}`); allBpmnFiles.push(...files); } catch (error) { // Only log warnings for unexpected errors (not 404s which are expected when directories don't exist) if (error.status !== 404) { - console.warn(`Could not fetch BPMN files from ${path}:`, error.message); + console.warn(`❌ Could not fetch BPMN files from ${path}:`, error.message); + } else { + console.log(`📂 githubService.getBpmnFiles: Directory ${path} not found (404) - this is expected if the directory doesn't exist`); } // Continue trying other paths } @@ -1064,6 +1078,8 @@ class GitHubService { index === self.findIndex(f => f.path === file.path) ); + console.log(`🎯 githubService.getBpmnFiles: Final result - ${uniqueFiles.length} unique BPMN files found`); + console.log(`📋 githubService.getBpmnFiles: File list:`, uniqueFiles.map(f => f.name)); return uniqueFiles; } From ef851e52e648ca56a244f639f19203689b629982 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 8 Aug 2025 16:08:39 +0000 Subject: [PATCH 8/9] Add detailed debug logging to BPMNPreview component to diagnose blank preview issue Co-authored-by: litlfred <662242+litlfred@users.noreply.github.com> --- src/components/BPMNPreview.js | 47 ++++++++++++++++++++-- src/components/BusinessProcessSelection.js | 11 +++++ 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/src/components/BPMNPreview.js b/src/components/BPMNPreview.js index f6f634a8e..17c2e082d 100644 --- a/src/components/BPMNPreview.js +++ b/src/components/BPMNPreview.js @@ -11,7 +11,15 @@ const BPMNPreview = ({ file, repository, selectedBranch, profile }) => { useEffect(() => { const loadPreview = async () => { - if (!file || !repository || !containerRef.current) return; + if (!file || !repository || !containerRef.current) { + console.log('🚫 BPMNPreview: Missing required props:', { + hasFile: !!file, + hasRepository: !!repository, + hasContainer: !!containerRef.current, + fileName: file?.name + }); + return; + } try { setLoading(true); @@ -27,6 +35,16 @@ const BPMNPreview = ({ file, repository, selectedBranch, profile }) => { const ref = selectedBranch || 'main'; const isDemo = file.path?.includes('demo/') || file.sha?.startsWith('demo-'); + console.log('🎬 BPMNPreview: Starting preview load for file:', { + fileName: file.name, + filePath: file.path, + owner: owner, + repoName: repoName, + ref: ref, + isDemo: isDemo, + hasDownloadUrl: !!file.download_url + }); + let bpmnXml; if (isDemo) { @@ -82,12 +100,15 @@ const BPMNPreview = ({ file, repository, selectedBranch, profile }) => { `; } else { // For real files, try to load the actual BPMN content + console.log('📥 BPMNPreview: Attempting to load real BPMN file content...'); try { bpmnXml = await githubService.getFileContent(owner, repoName, file.path, ref); + console.log('✅ BPMNPreview: Successfully loaded BPMN content, length:', bpmnXml?.length); } catch (fileError) { - console.warn('Could not load BPMN file content:', fileError); + console.warn('❌ BPMNPreview: Could not load BPMN file content:', fileError.message, fileError.status); // Fallback to a generic BPMN diagram if file can't be loaded const processName = file.name.replace('.bpmn', '').replace(/[-_]/g, ' '); + console.log('🔄 BPMNPreview: Using fallback BPMN diagram for:', processName); bpmnXml = ` { } } + console.log('🔧 BPMNPreview: Creating BPMN viewer...'); // Create and initialize viewer with clean separation const viewer = new BpmnViewer(); viewerRef.current = viewer; try { + console.log('🔗 BPMNPreview: Attaching viewer to container...'); // Attach viewer to container first await viewer.attachTo(containerRef.current); + console.log('📊 BPMNPreview: Importing BPMN XML...'); // Then import XML await viewer.importXML(bpmnXml); + console.log('🎯 BPMNPreview: Fitting to viewport...'); // Fit to viewport for preview const canvas = viewer.get('canvas'); canvas.zoom('fit-viewport'); + console.log('✅ BPMNPreview: Successfully rendered preview for:', file.name); setLoading(false); } catch (importError) { - console.error('Failed to import BPMN XML:', importError); + console.error('❌ BPMNPreview: Failed to import BPMN XML:', importError.message || importError); setError('Failed to load preview'); setLoading(false); } } catch (renderError) { - console.error('Failed to render BPMN preview:', renderError); + console.error('❌ BPMNPreview: Failed to render BPMN preview:', renderError.message || renderError); + console.log('🔍 BPMNPreview: Error details:', { + fileName: file.name, + filePath: file.path, + errorMessage: renderError.message, + errorStack: renderError.stack + }); setError('Failed to load preview'); setLoading(false); } @@ -182,8 +214,15 @@ const BPMNPreview = ({ file, repository, selectedBranch, profile }) => { // Only run if we have all required props if (file && repository && containerRef.current) { + console.log('🚀 BPMNPreview: Starting loadPreview for:', file.name); loadPreview(); } else { + console.log('⏭️ BPMNPreview: Skipping loadPreview, missing props:', { + hasFile: !!file, + hasRepository: !!repository, + hasContainer: !!containerRef.current, + fileName: file?.name + }); setLoading(false); } diff --git a/src/components/BusinessProcessSelection.js b/src/components/BusinessProcessSelection.js index bf8420491..139eaf27a 100644 --- a/src/components/BusinessProcessSelection.js +++ b/src/components/BusinessProcessSelection.js @@ -116,6 +116,17 @@ const BusinessProcessSelection = () => { const bpmnFiles = await githubService.getBpmnFiles(owner, repoName, ref); + console.log('📊 BusinessProcessSelection: Received BPMN files:', { + count: bpmnFiles.length, + files: bpmnFiles.map(f => ({ + name: f.name, + path: f.path, + size: f.size, + hasDownloadUrl: !!f.download_url, + sha: f.sha?.substring(0, 8) + })) + }); + // If no files found and we're in demo mode, provide fallback files if (bpmnFiles.length === 0 && profile?.isDemo) { console.log('No BPMN files found in demo mode, providing fallback demo files'); From eac8c0c33a5d03f41031e95cd17c91b4cb50e8fd Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 8 Aug 2025 16:18:38 +0000 Subject: [PATCH 9/9] Add comprehensive debug logging to BPMN preview rendering pipeline to diagnose blank preview issues Co-authored-by: litlfred <662242+litlfred@users.noreply.github.com> --- src/components/BPMNPreview.css | 2 + src/components/BPMNPreview.js | 111 ++++++++++++++++++++++++++++++--- 2 files changed, 106 insertions(+), 7 deletions(-) diff --git a/src/components/BPMNPreview.css b/src/components/BPMNPreview.css index d52308d89..a1b5f5e4e 100644 --- a/src/components/BPMNPreview.css +++ b/src/components/BPMNPreview.css @@ -12,7 +12,9 @@ .preview-container { width: 100%; height: 100%; + min-height: 160px; background: var(--bpmn-preview-bg); + position: relative; } .bpmn-preview-svg { diff --git a/src/components/BPMNPreview.js b/src/components/BPMNPreview.js index 17c2e082d..53677dca1 100644 --- a/src/components/BPMNPreview.js +++ b/src/components/BPMNPreview.js @@ -102,10 +102,36 @@ const BPMNPreview = ({ file, repository, selectedBranch, profile }) => { // For real files, try to load the actual BPMN content console.log('📥 BPMNPreview: Attempting to load real BPMN file content...'); try { + console.log('🌐 BPMNPreview: Calling githubService.getFileContent with params:', { + owner, repoName, path: file.path, ref + }); bpmnXml = await githubService.getFileContent(owner, repoName, file.path, ref); console.log('✅ BPMNPreview: Successfully loaded BPMN content, length:', bpmnXml?.length); + console.log('🔍 BPMNPreview: Content preview (first 100 chars):', bpmnXml?.substring(0, 100)); + + // Validate that we got actual BPMN content + if (!bpmnXml || typeof bpmnXml !== 'string') { + throw new Error('Invalid content received: not a string'); + } + + if (!bpmnXml.includes('bpmn:definitions') && !bpmnXml.includes(' { } console.log('🔧 BPMNPreview: Creating BPMN viewer...'); + console.log('🔍 BPMNPreview: About to create viewer with BPMN content length:', bpmnXml?.length); + // Create and initialize viewer with clean separation const viewer = new BpmnViewer(); viewerRef.current = viewer; + + console.log('✅ BPMNPreview: BPMN viewer instance created successfully'); try { console.log('🔗 BPMNPreview: Attaching viewer to container...'); - // Attach viewer to container first - await viewer.attachTo(containerRef.current); + console.log('🔍 BPMNPreview: Container element details:', { + exists: !!containerRef.current, + className: containerRef.current?.className, + width: containerRef.current?.offsetWidth, + height: containerRef.current?.offsetHeight, + parentExists: !!containerRef.current?.parentElement + }); + + // Create timeout promise for viewer operations + const createTimeoutPromise = (operation, timeoutMs = 10000) => { + return new Promise((_, reject) => { + setTimeout(() => { + reject(new Error(`${operation} timeout after ${timeoutMs}ms`)); + }, timeoutMs); + }); + }; + + // Attach viewer to container first with timeout + const attachPromise = viewer.attachTo(containerRef.current); + await Promise.race([attachPromise, createTimeoutPromise('Viewer attach', 5000)]); + console.log('✅ BPMNPreview: Successfully attached viewer to container'); console.log('📊 BPMNPreview: Importing BPMN XML...'); - // Then import XML - await viewer.importXML(bpmnXml); + console.log('🔍 BPMNPreview: XML content preview (first 200 chars):', bpmnXml?.substring(0, 200)); + + // Import XML with timeout handling + const importStartTime = Date.now(); + const importPromise = viewer.importXML(bpmnXml); + const importResult = await Promise.race([importPromise, createTimeoutPromise('XML import', 15000)]); + const importTime = Date.now() - importStartTime; + + console.log(`✅ BPMNPreview: Successfully imported BPMN XML in ${importTime}ms`); + console.log('📊 BPMNPreview: Import result details:', { + warnings: importResult?.warnings?.length || 0, + hasWarnings: !!(importResult?.warnings?.length), + warningDetails: importResult?.warnings + }); + + if (importResult?.warnings?.length > 0) { + console.warn('⚠️ BPMNPreview: Import warnings:', importResult.warnings); + } console.log('🎯 BPMNPreview: Fitting to viewport...'); // Fit to viewport for preview const canvas = viewer.get('canvas'); + console.log('🔍 BPMNPreview: Canvas service retrieved:', !!canvas); + + const zoomStartTime = Date.now(); canvas.zoom('fit-viewport'); + const zoomTime = Date.now() - zoomStartTime; + + console.log(`✅ BPMNPreview: Successfully fitted to viewport in ${zoomTime}ms`); + + // Final validation - check if diagram was actually rendered + const viewbox = canvas.viewbox(); + console.log('🔍 BPMNPreview: Final viewport details:', { + viewbox, + hasElements: viewbox.inner?.width > 0 && viewbox.inner?.height > 0, + containerHasContent: containerRef.current?.children?.length > 0 + }); + + // Check if container actually has content + if (containerRef.current?.children?.length === 0) { + console.warn('⚠️ BPMNPreview: Container is empty after rendering - potential issue'); + } - console.log('✅ BPMNPreview: Successfully rendered preview for:', file.name); + console.log(`🎉 BPMNPreview: Successfully rendered preview for: ${file.name}`); setLoading(false); } catch (importError) { - console.error('❌ BPMNPreview: Failed to import BPMN XML:', importError.message || importError); - setError('Failed to load preview'); + console.error('❌ BPMNPreview: Failed to import BPMN XML:', importError); + console.error('🔍 BPMNPreview: Import error details:', { + message: importError.message, + stack: importError.stack, + fileName: file.name, + xmlLength: bpmnXml?.length, + xmlPreview: bpmnXml?.substring(0, 300), + containerState: { + exists: !!containerRef.current, + hasChildren: containerRef.current?.children?.length || 0, + clientHeight: containerRef.current?.clientHeight, + clientWidth: containerRef.current?.clientWidth + } + }); + setError(`Failed to load preview: ${importError.message}`); setLoading(false); }