@@ -15,6 +15,7 @@ const CurateRouter = (function () {
1515 let routePrefix = '/custom' ;
1616 let focusTrap = null ;
1717 let isInitialized = false ;
18+ let lastNonCustomUrl = '/' ; // Track last non-custom URL for close button
1819 let configuration = {
1920 routePrefix : '/custom' ,
2021 showHeader : true ,
@@ -120,6 +121,15 @@ const CurateRouter = (function () {
120121 const path = window . location . pathname ;
121122
122123 if ( path . startsWith ( routePrefix ) ) {
124+ // Check if user is logged in before rendering custom routes
125+ if ( typeof pydio !== 'undefined' && ( ! pydio . user || pydio . user === null ) ) {
126+ // User is not logged in, don't render custom page
127+ if ( currentPage ) {
128+ closePage ( ) ;
129+ }
130+ return ;
131+ }
132+
123133 const routePath = path . substring ( routePrefix . length ) || '/' ;
124134
125135 // Check if we're already on this route - prevent duplicate navigation
@@ -137,9 +147,14 @@ const CurateRouter = (function () {
137147 } else {
138148 showErrorPage ( `Route not found: ${ routePath } ` ) ;
139149 }
140- } else if ( currentPage ) {
141- // We're navigating away from custom routes
142- closePage ( ) ;
150+ } else {
151+ // Track non-custom URLs for the close button
152+ lastNonCustomUrl = path ;
153+
154+ if ( currentPage ) {
155+ // We're navigating away from custom routes
156+ closePage ( ) ;
157+ }
143158 }
144159 }
145160
@@ -420,41 +435,64 @@ const CurateRouter = (function () {
420435 header . className = 'curate-router-header' ;
421436 header . style . cssText = `
422437 display: flex;
438+ justify-content: space-between;
423439 align-items: center;
424- padding: 16px 20px;
425- border-bottom: 1px solid #e0e0e0;
426- background: #f5f5f5;
427- min-height: 56px;
428- ` ;
429-
430- const backButton = document . createElement ( 'button' ) ;
431- backButton . className = 'curate-router-back-button' ;
432- backButton . innerHTML = '← Back' ;
433- backButton . style . cssText = `
434- background: none;
435- border: none;
436- font-size: 14px;
437- cursor: pointer;
438- padding: 8px 12px;
439- border-radius: 4px;
440- margin-right: 16px;
440+ padding: 20px;
441+ margin-bottom: 20px;
442+ padding-bottom: 16px;
443+ border-bottom: 1px solid var(--md-sys-color-outline, #c4c7c5);
444+ background: var(--md-sys-color-surface-variant, #fdfcff);
441445 ` ;
442- backButton . addEventListener ( 'click' , back ) ;
443446
444447 const titleElement = document . createElement ( 'h1' ) ;
445448 titleElement . textContent = title ;
446449 titleElement . style . cssText = `
447450 margin: 0;
448- font-size: 18px;
449- font-weight: 600;
451+ color: var(--md-sys-color-on-background, #1d1b20);
452+ font-size: 28px;
453+ font-weight: 400;
450454 ` ;
451455
452- header . appendChild ( backButton ) ;
456+ // Create close button
457+ const closeButton = document . createElement ( 'button' ) ;
458+ closeButton . textContent = '✕ Close' ;
459+ closeButton . addEventListener ( 'click' , closeAndReturnToUnderlying ) ;
460+ closeButton . style . cssText = `
461+ background: var(--md-sys-color-primary-container);
462+ color: var(--md-sys-color-on-primary-container);
463+ border: none;
464+ border-radius: 4px;
465+ padding: 6px 12px;
466+ font-size: 13px;
467+ cursor: pointer;
468+ transition: opacity 0.2s;
469+ ` ;
470+
471+ closeButton . addEventListener ( 'mouseenter' , ( ) => {
472+ closeButton . style . opacity = '0.8' ;
473+ } ) ;
474+ closeButton . addEventListener ( 'mouseleave' , ( ) => {
475+ closeButton . style . opacity = '1' ;
476+ } ) ;
477+
453478 header . appendChild ( titleElement ) ;
479+ header . appendChild ( closeButton ) ;
454480
455481 return header ;
456482 }
457483
484+ /**
485+ * Close the custom page and return to the underlying Pydio URL
486+ */
487+ function closeAndReturnToUnderlying ( ) {
488+ if ( currentPage ) {
489+ // Navigate to the last non-custom URL (or fallback to base path)
490+ const targetUrl = lastNonCustomUrl || '/' ;
491+ window . history . pushState ( null , '' , targetUrl ) ;
492+ closePage ( ) ;
493+ }
494+ }
495+
458496 function createNavigationUtils ( ) {
459497 return {
460498 navigate : ( path ) => navigate ( path ) ,
@@ -598,6 +636,40 @@ const CurateRouter = (function () {
598636 return currentPage !== null ;
599637 }
600638
639+ /**
640+ * Check if a given path is a valid registered route
641+ *
642+ * @param {string } path - The path to check (can be full path or just route path)
643+ * @returns {boolean } True if the path matches a registered route, false otherwise
644+ *
645+ * @example
646+ * // Check if current URL is a valid custom route
647+ * if (Curate.router.isValidRoute(window.location.pathname)) {
648+ * console.log('Current URL is a valid custom route');
649+ * }
650+ *
651+ * @example
652+ * // Check a specific route
653+ * if (Curate.router.isValidRoute('/custom/pure-integration')) {
654+ * console.log('Pure integration route exists');
655+ * }
656+ */
657+ function isValidRoute ( path ) {
658+ if ( ! path ) return false ;
659+
660+ // If path includes the route prefix, extract just the route part
661+ let routePath = path ;
662+ if ( path . startsWith ( routePrefix ) ) {
663+ routePath = path . substring ( routePrefix . length ) || '/' ;
664+ } else if ( ! path . startsWith ( '/' ) ) {
665+ routePath = '/' + path ;
666+ }
667+
668+ // Check if this route matches any registered routes
669+ const match = findMatchingRoute ( routePath ) ;
670+ return match !== null ;
671+ }
672+
601673 /**
602674 * Manually check and navigate to current URL route
603675 * Useful for handling page refreshes or manual URL entry
@@ -638,6 +710,7 @@ const CurateRouter = (function () {
638710 back,
639711 getCurrentPage,
640712 isActive,
713+ isValidRoute,
641714 checkRoute
642715 } ;
643716} ) ( ) ;
0 commit comments