@@ -4600,8 +4600,35 @@ const maybeShowUpdateNotesPanel = async () => {
46004600 } ) ;
46014601} ;
46024602
4603- const fetchFolders = async ( type ) => apiGetJson ( `/plugins/folderview.plus/server/read.php?type=${ type } ` ) ;
4604- const fetchTypeInfo = async ( type ) => apiGetJson ( `/plugins/folderview.plus/server/read_info.php?type=${ type } ` ) ;
4603+ const sanitizeTypeMapResponse = ( response ) => {
4604+ if ( ! response || typeof response !== 'object' || Array . isArray ( response ) ) {
4605+ return { } ;
4606+ }
4607+ if ( response . ok === false && typeof response . error === 'string' ) {
4608+ return { } ;
4609+ }
4610+ return response ;
4611+ } ;
4612+
4613+ const sanitizeTypeInfoMap = ( value ) => {
4614+ const source = sanitizeTypeMapResponse ( value ) ;
4615+ const output = { } ;
4616+ for ( const [ name , item ] of Object . entries ( source ) ) {
4617+ if ( typeof name !== 'string' || ! name . trim ( ) ) {
4618+ continue ;
4619+ }
4620+ if ( ! item || typeof item !== 'object' || Array . isArray ( item ) ) {
4621+ continue ;
4622+ }
4623+ output [ name ] = item ;
4624+ }
4625+ return output ;
4626+ } ;
4627+
4628+ const fetchFolders = async ( type ) => (
4629+ utils . normalizeFolderMap ( sanitizeTypeMapResponse ( await apiGetJson ( `/plugins/folderview.plus/server/read.php?type=${ type } ` ) ) )
4630+ ) ;
4631+ const fetchTypeInfo = async ( type ) => sanitizeTypeInfoMap ( await apiGetJson ( `/plugins/folderview.plus/server/read_info.php?type=${ type } ` ) ) ;
46054632
46064633const fetchBackups = async ( type ) => {
46074634 const resolvedType = normalizeManagedType ( type ) ;
@@ -5628,6 +5655,7 @@ const offerUndoAction = async (type, backup, actionLabel) => {
56285655const buildRowsHtml = ( type , folders , memberSnapshot = { } , hideEmptyFolders = false , healthMetrics = null , statusContext = null ) => {
56295656 const isDockerType = type === 'docker' ;
56305657 const TABLE_COLUMN_COUNT = 10 ;
5658+ const folderCount = Object . keys ( folders || { } ) . length ;
56315659 const dockerHealthPrefs = isDockerType ? normalizeHealthPrefs ( 'docker' ) : null ;
56325660 const statusPrefs = normalizeStatusPrefs ( type ) ;
56335661 const rows = [ ] ;
@@ -5945,6 +5973,15 @@ const buildRowsHtml = (type, folders, memberSnapshot = {}, hideEmptyFolders = fa
59455973 const clearButton = showClearFilters
59465974 ? `<button type="button" class="folder-empty-clear-filter" onclick="clearFolderTableFilters('${ type } ')">Clear filters</button>`
59475975 : '' ;
5976+ if ( folderCount <= 0 && ! showClearFilters ) {
5977+ const firstRunMessage = isDockerType
5978+ ? 'No Docker folders yet. Create your first folder in the Docker tab or import an export file.'
5979+ : 'No VM folders yet. Create your first folder in the VMs tab or import an export file.' ;
5980+ return `<tr><td colspan="${ TABLE_COLUMN_COUNT } " class="folder-empty-cell">${ firstRunMessage } </td></tr>` ;
5981+ }
5982+ if ( folderCount > 0 && hideEmptyFolders && ! showClearFilters ) {
5983+ return `<tr><td colspan="${ TABLE_COLUMN_COUNT } " class="folder-empty-cell">All folders are currently hidden by "Hide empty folders".</td></tr>` ;
5984+ }
59485985 return `<tr><td colspan="${ TABLE_COLUMN_COUNT } " class="folder-empty-cell">No folders match current filters${ filterSuffix } . ${ clearButton } </td></tr>` ;
59495986 }
59505987 return rows . join ( '' ) ;
0 commit comments