diff --git a/app/missions/[missionId]/page.tsx b/app/missions/[missionId]/page.tsx index 645856d..7fe03d8 100644 --- a/app/missions/[missionId]/page.tsx +++ b/app/missions/[missionId]/page.tsx @@ -61,6 +61,10 @@ interface Mission { createdAt: string; creator: User; missionUsers: any[]; + rocketChatChannelId?: string | null; + outlineCollectionId?: string | null; + giteaRepositoryUrl?: string | null; + leantimeProjectId?: string | null; } export default function MissionDetailPage() { @@ -186,6 +190,60 @@ export default function MissionDetailPage() { iconPath: oddNumber ? `/F SDG Icons 2019 WEB/F-WEB-Goal-${oddNumber.padStart(2, '0')}.png` : "" }; }; + + // Function to convert application URL to iframe URL + // Example: parole.slm-lab.net/channel/xxx -> hub.slm-lab.net/parole/channel/xxx + const convertToIframeUrl = (appUrl: string | null | undefined): string | null => { + if (!appUrl) return null; + + try { + // If it's already a full URL, parse it + if (appUrl.startsWith('http://') || appUrl.startsWith('https://')) { + const url = new URL(appUrl); + const hostname = url.hostname; + const pathname = url.pathname; + const search = url.search; + + // Extract subdomain (e.g., "parole" from "parole.slm-lab.net") + const subdomainMatch = hostname.match(/^([^.]+)\.slm-lab\.net$/); + if (!subdomainMatch) { + // If URL doesn't match expected pattern, return original + return appUrl; + } + + const subdomain = subdomainMatch[1]; + // Remove leading slash from pathname if present + const cleanPath = pathname.startsWith('/') ? pathname.substring(1) : pathname; + + // Build iframe URL: hub.slm-lab.net/[subdomain]/[path][search] + const iframeUrl = `https://hub.slm-lab.net/${subdomain}/${cleanPath}${search}`; + return iframeUrl; + } else { + // If it's not a full URL, assume it's a relative path and return as is + // (This shouldn't happen for these fields, but handle it gracefully) + return appUrl; + } + } catch (error) { + console.error('Error converting URL to iframe URL:', error); + return appUrl; // Return original URL if conversion fails + } + }; + + // Function to build Leantime URL from project ID + // If leantimeProjectId is a URL, convert it; if it's just an ID, build the URL + const getLeantimeUrl = (projectId: string | null | undefined): string | null => { + if (!projectId) return null; + + // If it's already a full URL, convert it + if (projectId.startsWith('http://') || projectId.startsWith('https://')) { + return convertToIframeUrl(projectId); + } + + // Otherwise, it's just an ID - build the full URL + // Format: agilite.slm-lab.net/projects/showProject/[id] + const appUrl = `https://agilite.slm-lab.net/projects/showProject/${projectId}`; + return convertToIframeUrl(appUrl); + }; // Handle delete mission const handleDeleteMission = async () => { @@ -568,6 +626,102 @@ export default function MissionDetailPage() { )} + {/* Liens d'intégration */} + {(mission.rocketChatChannelId || mission.outlineCollectionId || mission.giteaRepositoryUrl || mission.leantimeProjectId) && ( +
+

Liens d'intégration

+
+ {mission.rocketChatChannelId && ( +
+
+
+ +
+
+

Tenant de Parole

+

RocketChat

+
+
+ + Ouvrir + +
+ )} + + {mission.outlineCollectionId && ( +
+
+
+ +
+
+

Tenant du Chapitre

+

Outline

+
+
+ + Ouvrir + +
+ )} + + {mission.giteaRepositoryUrl && ( +
+
+
+ +
+
+

Tenant du Code

+

Gitea

+
+
+ + Ouvrir + +
+ )} + + {mission.leantimeProjectId && ( +
+
+
+ +
+
+

Tenant des Devoirs

+

Leantime

+
+
+ + Ouvrir + +
+ )} +
+
+ )} + {/* Mission Status & Action Buttons */}
{/* Closed Status */}