@@ -282,6 +282,101 @@ const writeDashboardCompactDensityStateForType = (type, enabled) => {
282282} ;
283283const getDashboardStartedOnlySelectorForType = ( type ) => ( type === 'vm' ? 'input#vms' : 'input#apps' ) ;
284284const isDashboardLegacyLayoutForType = ( type ) => normalizeDashboardPrefsForType ( type ) . layout === 'legacy' ;
285+ const getDashboardNativeRowSelectorForType = ( type ) => (
286+ type === 'vm'
287+ ? 'span.outer.vms:not(.folder-vm)'
288+ : 'span.outer.apps:not(.folder-docker)'
289+ ) ;
290+ const getDashboardNativeRowName = ( $row ) => String (
291+ $row ?. find ( 'span.inner' ) . contents ( ) . first ( ) . text ( ) || ''
292+ ) . trim ( ) ;
293+ const stripDashboardFolderizedStateFromRow = ( $row ) => {
294+ if ( ! $row || ! $row . length ) {
295+ return ;
296+ }
297+ $row . find ( 'span.fv-dashboard-member-actions' ) . remove ( ) ;
298+ $row . removeClass ( ( _ , className = '' ) => className
299+ . split ( / \s + / )
300+ . filter ( ( token ) => {
301+ if ( ! token ) {
302+ return false ;
303+ }
304+ if ( token === 'folder-element-docker' || token === 'folder-element-vm' || token === 'autostart' ) {
305+ return true ;
306+ }
307+ return / ^ f o l d e r - [ A - Z a - z 0 - 9 . _ - ] + - e l e m e n t $ / . test ( token ) ;
308+ } )
309+ . join ( ' ' ) ) ;
310+ } ;
311+ const readDashboardNativeOrderSnapshotForType = async ( type ) => {
312+ const resolvedType = type === 'vm' ? 'vm' : 'docker' ;
313+ const existingReq = Array . isArray ( folderReq ?. [ resolvedType ] ) ? folderReq [ resolvedType ] [ 3 ] : null ;
314+ if ( existingReq && typeof existingReq . then === 'function' ) {
315+ try {
316+ return Object . values ( JSON . parse ( await existingReq ) ) ;
317+ } catch ( _error ) {
318+ // Fall through to a fresh fetch.
319+ }
320+ }
321+ try {
322+ const payload = await $ . get ( `/plugins/folderview.plus/server/read_unraid_order.php?type=${ resolvedType } ` ) . promise ( ) ;
323+ return Object . values ( JSON . parse ( payload ) ) ;
324+ } catch ( _error ) {
325+ return [ ] ;
326+ }
327+ } ;
328+ const restoreDashboardNativeRowsForType = async ( type ) => {
329+ const resolvedType = type === 'vm' ? 'vm' : 'docker' ;
330+ const $container = resolveDashboardWidgetInlineHostForType ( resolvedType ) . first ( ) ;
331+ if ( ! $container . length ) {
332+ return ;
333+ }
334+ const selector = getDashboardNativeRowSelectorForType ( resolvedType ) ;
335+ const rowEntries = [ ] ;
336+ $container . find ( selector ) . each ( ( _ , node ) => {
337+ const $row = $ ( node ) ;
338+ if ( $row . closest ( '.fv-dashboard-layout-inline-host' ) . length ) {
339+ return ;
340+ }
341+ rowEntries . push ( {
342+ $row,
343+ name : getDashboardNativeRowName ( $row )
344+ } ) ;
345+ } ) ;
346+ rowEntries . forEach ( ( entry ) => {
347+ stripDashboardFolderizedStateFromRow ( entry . $row ) ;
348+ entry . $row . detach ( ) ;
349+ } ) ;
350+ $container . children ( '.folder-showcase-outer' ) . remove ( ) ;
351+ const orderSnapshot = await readDashboardNativeOrderSnapshotForType ( resolvedType ) ;
352+ const rowMap = new Map ( ) ;
353+ const appended = new Set ( ) ;
354+ for ( const entry of rowEntries ) {
355+ if ( entry . name && ! rowMap . has ( entry . name ) ) {
356+ rowMap . set ( entry . name , entry ) ;
357+ }
358+ }
359+ for ( const name of orderSnapshot ) {
360+ const key = String ( name || '' ) . trim ( ) ;
361+ if ( ! key || ! rowMap . has ( key ) || appended . has ( key ) ) {
362+ continue ;
363+ }
364+ appended . add ( key ) ;
365+ $container . append ( rowMap . get ( key ) . $row ) ;
366+ }
367+ for ( const entry of rowEntries ) {
368+ const key = String ( entry . name || '' ) . trim ( ) ;
369+ if ( key && appended . has ( key ) ) {
370+ continue ;
371+ }
372+ $container . append ( entry . $row ) ;
373+ }
374+ if ( resolvedType === 'vm' ) {
375+ globalFolders . vms = { } ;
376+ } else {
377+ globalFolders . docker = { } ;
378+ }
379+ } ;
285380const isDashboardStartedOnlyEnabledForType = ( type ) => {
286381 const selector = getDashboardStartedOnlySelectorForType ( type ) ;
287382 const $toggle = $ ( selector ) . first ( ) ;
@@ -620,6 +715,19 @@ const saveDashboardLayoutPrefForType = async (type, prefsPayload) => {
620715 } ) . promise ( ) ;
621716 return parseJsonPayloadSafe ( payload ) ;
622717} ;
718+ const rerenderDashboardWidgetStructureForType = async ( type ) => {
719+ const resolvedType = type === 'vm' ? 'vm' : 'docker' ;
720+ await restoreDashboardNativeRowsForType ( resolvedType ) ;
721+ if ( isDashboardLegacyLayoutForType ( resolvedType ) ) {
722+ scheduleDashboardLayoutApplyForType ( resolvedType ) ;
723+ syncDashboardWidgetLayoutQuickControlForType ( resolvedType ) ;
724+ scheduleDashboardWidgetVisibilitySyncForType ( resolvedType , 0 ) ;
725+ return ;
726+ }
727+ prepareDashboardFolderRequestsForType ( resolvedType ) ;
728+ await createFolders ( [ resolvedType ] ) ;
729+ scheduleDashboardWidgetVisibilitySyncForType ( resolvedType , 0 ) ;
730+ } ;
623731const handleDashboardWidgetLayoutQuickSwitch = async ( type , value ) => {
624732 const resolvedType = type === 'vm' ? 'vm' : 'docker' ;
625733 const nextLayout = normalizeDashboardLayoutMode ( value ) ;
@@ -653,9 +761,8 @@ const handleDashboardWidgetLayoutQuickSwitch = async (type, value) => {
653761 throw new Error ( response ?. error || 'Failed to save dashboard preferences.' ) ;
654762 }
655763 folderTypePrefs [ resolvedType ] = utils . normalizePrefs ( response . prefs || nextPrefs ) ;
656- if ( requiresStructureReload && typeof window . loadlist === 'function' ) {
657- loadedFolder = false ;
658- window . loadlist ( ) ;
764+ if ( requiresStructureReload ) {
765+ await rerenderDashboardWidgetStructureForType ( resolvedType ) ;
659766 return ;
660767 }
661768 scheduleDashboardLayoutApplyForType ( resolvedType ) ;
@@ -1368,13 +1475,17 @@ let createFoldersQueued = false;
13681475/**
13691476 * Handles the creation of all folders
13701477 */
1371- const createFolders = async ( ) => {
1478+ const createFolders = async ( types = [ 'docker' , 'vm' ] ) => {
1479+ const renderTypes = new Set (
1480+ ( Array . isArray ( types ) ? types : [ types ] )
1481+ . map ( ( type ) => ( type === 'vm' ? 'vm' : 'docker' ) )
1482+ ) ;
13721483 // ########################################
13731484 // ########## DOCKER ##########
13741485 // ########################################
13751486
13761487 // if docker is enabled
1377- if ( $ ( 'tbody#docker_view' ) . length > 0 ) {
1488+ if ( renderTypes . has ( 'docker' ) && $ ( 'tbody#docker_view' ) . length > 0 ) {
13781489 showDashboardRuntimeLoadingRow ( 'docker' ) ;
13791490 try {
13801491 let prom = await Promise . all ( folderReq . docker ) ;
@@ -1402,9 +1513,7 @@ const createFolders = async () => {
14021513 globalFolders . docker = { } ;
14031514 scheduleDashboardLayoutApplyForType ( 'docker' ) ;
14041515 syncDashboardWidgetLayoutQuickControlForType ( 'docker' ) ;
1405- return ;
1406- }
1407-
1516+ } else {
14081517 // Filter the order to get the container that aren't in the order, this happen when a new container is created
14091518 let newOnes = order . filter ( x => ! unraidOrder . includes ( x ) ) ;
14101519
@@ -1569,6 +1678,7 @@ const createFolders = async () => {
15691678 // Assing the folder done to the global object
15701679 globalFolders . docker = foldersDone ;
15711680 scheduleDashboardLayoutApplyForType ( 'docker' ) ;
1681+ }
15721682 } finally {
15731683 hideDashboardRuntimeLoadingRow ( 'docker' ) ;
15741684 }
@@ -1580,7 +1690,7 @@ const createFolders = async () => {
15801690 // ########################################
15811691
15821692 // if vm is enabled
1583- if ( $ ( 'tbody#vm_view' ) . length > 0 ) {
1693+ if ( renderTypes . has ( 'vm' ) && $ ( 'tbody#vm_view' ) . length > 0 ) {
15841694 showDashboardRuntimeLoadingRow ( 'vm' ) ;
15851695 try {
15861696 const prom = await Promise . all ( folderReq . vm ) ;
@@ -1608,9 +1718,7 @@ const createFolders = async () => {
16081718 globalFolders . vms = { } ;
16091719 scheduleDashboardLayoutApplyForType ( 'vm' ) ;
16101720 syncDashboardWidgetLayoutQuickControlForType ( 'vm' ) ;
1611- return ;
1612- }
1613-
1721+ } else {
16141722 // Filter the webui order to get the container that aren't in the order, this happen when a new container is created
16151723 let newOnes = order . filter ( x => ! unraidOrder . includes ( x ) ) ;
16161724
@@ -1774,6 +1882,7 @@ const createFolders = async () => {
17741882
17751883 globalFolders . vms = foldersDone ;
17761884 scheduleDashboardLayoutApplyForType ( 'vm' ) ;
1885+ }
17771886 } finally {
17781887 hideDashboardRuntimeLoadingRow ( 'vm' ) ;
17791888 }
@@ -3401,44 +3510,45 @@ const queueCreateFoldersRender = () => {
34013510 }
34023511 } ) ;
34033512} ;
3404-
3405- // Patching the original function to make sure the containers are rendered before insering the folder
3406- window . loadlist_original = loadlist ;
3407- window . loadlist = ( x ) => {
3408- loadedFolder = false ;
3409- if ( $ ( 'tbody#docker_view' ) . length > 0 ) {
3513+ const prepareDashboardFolderRequestsForType = ( type ) => {
3514+ const resolvedType = type === 'vm' ? 'vm' : 'docker' ;
3515+ const hasWidget = resolvedType === 'vm'
3516+ ? $ ( 'tbody#vm_view' ) . length > 0
3517+ : $ ( 'tbody#docker_view' ) . length > 0 ;
3518+ if ( ! hasWidget ) {
3519+ folderReq [ resolvedType ] = [ ] ;
3520+ return [ ] ;
3521+ }
3522+ if ( resolvedType === 'docker' ) {
34103523 const safeDockerPrefsReq = $ . get ( '/plugins/folderview.plus/server/prefs.php?type=docker' )
34113524 . then ( ( data ) => data , ( ) => JSON . stringify ( { ok : false , prefs : { } } ) ) ;
34123525 folderReq . docker = [
3413- // Get the folders
34143526 $ . get ( '/plugins/folderview.plus/server/read.php?type=docker' ) . promise ( ) ,
3415- // Get the order as unraid sees it
34163527 $ . get ( '/plugins/folderview.plus/server/read_order.php?type=docker' ) . promise ( ) ,
3417- // Get the info on containers, needed for autostart, update and started
34183528 $ . get ( '/plugins/folderview.plus/server/read_info.php?type=docker' ) . promise ( ) ,
3419- // Get the order that is shown in the webui
34203529 $ . get ( '/plugins/folderview.plus/server/read_unraid_order.php?type=docker' ) . promise ( ) ,
3421- // Get sort and auto-assignment preferences
34223530 safeDockerPrefsReq
34233531 ] ;
3532+ return folderReq . docker ;
34243533 }
3534+ const safeVmPrefsReq = $ . get ( '/plugins/folderview.plus/server/prefs.php?type=vm' )
3535+ . then ( ( data ) => data , ( ) => JSON . stringify ( { ok : false , prefs : { } } ) ) ;
3536+ folderReq . vm = [
3537+ $ . get ( '/plugins/folderview.plus/server/read.php?type=vm' ) . promise ( ) ,
3538+ $ . get ( '/plugins/folderview.plus/server/read_order.php?type=vm' ) . promise ( ) ,
3539+ $ . get ( '/plugins/folderview.plus/server/read_info.php?type=vm' ) . promise ( ) ,
3540+ $ . get ( '/plugins/folderview.plus/server/read_unraid_order.php?type=vm' ) . promise ( ) ,
3541+ safeVmPrefsReq
3542+ ] ;
3543+ return folderReq . vm ;
3544+ } ;
34253545
3426- if ( $ ( 'tbody#vm_view' ) . length > 0 ) {
3427- const safeVmPrefsReq = $ . get ( '/plugins/folderview.plus/server/prefs.php?type=vm' )
3428- . then ( ( data ) => data , ( ) => JSON . stringify ( { ok : false , prefs : { } } ) ) ;
3429- folderReq . vm = [
3430- // Get the folders
3431- $ . get ( '/plugins/folderview.plus/server/read.php?type=vm' ) . promise ( ) ,
3432- // Get the order as unraid sees it
3433- $ . get ( '/plugins/folderview.plus/server/read_order.php?type=vm' ) . promise ( ) ,
3434- // Get the info on VMs, needed for autostart and started
3435- $ . get ( '/plugins/folderview.plus/server/read_info.php?type=vm' ) . promise ( ) ,
3436- // Get the order that is shown in the webui
3437- $ . get ( '/plugins/folderview.plus/server/read_unraid_order.php?type=vm' ) . promise ( ) ,
3438- // Get sort and auto-assignment preferences
3439- safeVmPrefsReq
3440- ] ;
3441- }
3546+ // Patching the original function to make sure the containers are rendered before insering the folder
3547+ window . loadlist_original = loadlist ;
3548+ window . loadlist = ( x ) => {
3549+ loadedFolder = false ;
3550+ prepareDashboardFolderRequestsForType ( 'docker' ) ;
3551+ prepareDashboardFolderRequestsForType ( 'vm' ) ;
34423552 loadlist_original ( x ) ;
34433553} ;
34443554
0 commit comments