@@ -726,6 +726,94 @@ const Remote = {
726726 return { status, modules : modules . join ( ", " ) } ;
727727 } ,
728728
729+ /**
730+ * Determines the status of a class based on visible/hidden modules
731+ * @param {object } classData - Class data with show/hide/toggle arrays
732+ * @returns {object } Status object with status and details
733+ */
734+ getClassStatus ( classData ) {
735+ if ( ! classData || ! this . savedData . modules ) {
736+ return { status : "unknown" , details : "" } ;
737+ }
738+
739+ // Create map for fast module access
740+ const moduleMap = { } ;
741+ for ( const module of this . savedData . modules ) {
742+ moduleMap [ module . name ] = module ;
743+ moduleMap [ module . identifier ] = module ;
744+ }
745+
746+ let visibleCount = 0 ;
747+ let hiddenCount = 0 ;
748+ let totalCount = 0 ;
749+
750+ // Check show modules
751+ if ( classData . show ) {
752+ const showModules = Array . isArray ( classData . show ) ? classData . show : [ classData . show ] ;
753+ for ( const moduleName of showModules ) {
754+ const module = moduleMap [ moduleName ] ;
755+ if ( module ) {
756+ totalCount ++ ;
757+ if ( module . hidden ) {
758+ hiddenCount ++ ;
759+ } else {
760+ visibleCount ++ ;
761+ }
762+ }
763+ }
764+ }
765+
766+ // Check hide modules
767+ if ( classData . hide ) {
768+ const hideModules = Array . isArray ( classData . hide ) ? classData . hide : [ classData . hide ] ;
769+ for ( const moduleName of hideModules ) {
770+ const module = moduleMap [ moduleName ] ;
771+ if ( module ) {
772+ totalCount ++ ;
773+ if ( module . hidden ) {
774+ hiddenCount ++ ;
775+ } else {
776+ visibleCount ++ ;
777+ }
778+ }
779+ }
780+ }
781+
782+ // Check toggle modules (we just show if they're visible/hidden)
783+ if ( classData . toggle ) {
784+ const toggleModules = Array . isArray ( classData . toggle ) ? classData . toggle : [ classData . toggle ] ;
785+ for ( const moduleName of toggleModules ) {
786+ const module = moduleMap [ moduleName ] ;
787+ if ( module ) {
788+ totalCount ++ ;
789+ if ( module . hidden ) {
790+ hiddenCount ++ ;
791+ } else {
792+ visibleCount ++ ;
793+ }
794+ }
795+ }
796+ }
797+
798+ // Determine status
799+ let status = "class-mixed" ;
800+ if ( totalCount === 0 ) {
801+ status = "class-empty" ;
802+ } else if ( hiddenCount === 0 && visibleCount > 0 ) {
803+ status = "class-active" ;
804+ } else if ( visibleCount === 0 && hiddenCount > 0 ) {
805+ status = "class-inactive" ;
806+ }
807+
808+ return {
809+ status,
810+ details : `${ visibleCount } /${ totalCount } ` ,
811+ visibleCount,
812+ hiddenCount,
813+ totalCount
814+ } ;
815+ } ,
816+
729817 addToggleElements ( parent ) {
730818 const outerSpan = document . createElement ( "span" ) ;
731819 outerSpan . className = "stack fa-fw" ;
@@ -1401,7 +1489,11 @@ const Remote = {
14011489
14021490 async loadClasses ( ) {
14031491 try {
1492+ // Always reload module data to get fresh status
1493+ const { data : moduleData } = await this . loadList ( "visible-modules" , "modules" ) ;
1494+ this . savedData . modules = moduleData ;
14041495 const { data : classes } = await this . loadList ( "classes" , "classes" ) ;
1496+
14051497 for ( const index in classes ) {
14061498 const node = document . createElement ( "div" ) ;
14071499 node . id = "classes-before-result" ;
@@ -1418,7 +1510,8 @@ const Remote = {
14181510 payload : {
14191511 classes : index
14201512 }
1421- }
1513+ } ,
1514+ classData : classes [ index ] // Store class data for status checking
14221515 } ;
14231516
14241517 const existingButton = document . getElementById ( `${ content . id } -button` ) ;
@@ -1787,6 +1880,102 @@ const Remote = {
17871880 }
17881881 } ,
17891882
1883+ addClassStatusBadge ( item , classData ) {
1884+ const classStatus = this . getClassStatus ( classData ) ;
1885+ const statusBadge = document . createElement ( "span" ) ;
1886+ statusBadge . className = `class-status-badge ${ classStatus . status } ` ;
1887+ statusBadge . textContent = classStatus . details ;
1888+ statusBadge . title = `${ classStatus . visibleCount } visible, ${ classStatus . hiddenCount } hidden` ;
1889+ item . append ( statusBadge ) ;
1890+ item . classList . add ( classStatus . status ) ;
1891+ } ,
1892+
1893+ createMenuTypeElement ( item , content , menu ) {
1894+ const mcmArrow = document . createElement ( "span" ) ;
1895+ mcmArrow . className = "fa fa-fw fa-angle-right" ;
1896+ mcmArrow . setAttribute ( "aria-hidden" , "true" ) ;
1897+ item . append ( mcmArrow ) ;
1898+ item . dataset . parent = menu ;
1899+ item . dataset . type = "menu" ;
1900+ document . querySelector ( "#back-button" ) . classList . add ( `${ content . id } -menu` ) ;
1901+ const menuContent = document . querySelector ( ".menu-content" ) ;
1902+ if ( menuContent ) {
1903+ menuContent . classList . add ( `${ content . id } -menu` ) ;
1904+ }
1905+ item . addEventListener ( "click" , ( ) => {
1906+ globalThis . location . hash = `${ content . id } -menu` ;
1907+ } ) ;
1908+ } ,
1909+
1910+ createSliderElement ( item , content ) {
1911+ const contain = document . createElement ( "div" ) ;
1912+ contain . classList . add ( "flex-1" ) ;
1913+
1914+ const slide = document . createElement ( "input" ) ;
1915+ slide . id = `${ content . id } -slider` ;
1916+ slide . className = "slider" ;
1917+ slide . type = "range" ;
1918+ slide . min = content . min || 0 ;
1919+ slide . max = content . max || 100 ;
1920+ slide . step = content . step || 10 ;
1921+ slide . value = content . defaultValue || 50 ;
1922+
1923+ slide . addEventListener ( "change" , ( ) => {
1924+ this . sendSocketNotification ( "REMOTE_ACTION" , {
1925+ action : content . action . toUpperCase ( ) ,
1926+ ...content . content ,
1927+ payload : {
1928+ ...content . content === undefined ? { } : ( typeof content . content . payload === "string" ? { string : content . content . payload } : content . content . payload ) ,
1929+ value : slide . value
1930+ } ,
1931+ value : slide . value
1932+ } ) ;
1933+ } ) ;
1934+
1935+ contain . append ( slide ) ;
1936+ item . append ( contain ) ;
1937+ } ,
1938+
1939+ createInputElement ( content , menu ) {
1940+ const input = document . createElement ( "input" ) ;
1941+ input . id = `${ content . id } -input` ;
1942+ input . className = `menu-element ${ menu } -menu medium` ;
1943+ input . type = "text" ;
1944+ input . placeholder = content . text ;
1945+
1946+ input . addEventListener ( "focusout" , ( ) => {
1947+ this . sendSocketNotification ( "REMOTE_ACTION" , {
1948+ action : content . action . toUpperCase ( ) ,
1949+ ...content . content ,
1950+ payload : {
1951+ ...content . content === undefined ? { } : ( typeof content . content . payload === "string" ? { string : content . content . payload } : content . content . payload ) ,
1952+ value : input . value
1953+ } ,
1954+ value : input . value
1955+ } ) ;
1956+ } ) ;
1957+
1958+ return input ;
1959+ } ,
1960+
1961+ addItemClickHandler ( item , content , menu ) {
1962+ item . dataset . type = "item" ;
1963+ item . addEventListener ( "click" , ( ) => {
1964+ this . sendSocketNotification ( "REMOTE_ACTION" , {
1965+ action : content . action . toUpperCase ( ) ,
1966+ payload : { } ,
1967+ ...content . content
1968+ } ) ;
1969+
1970+ // Reload classes menu after executing class action to update status badges
1971+ if ( content . action === "MANAGE_CLASSES" && menu === "classes" ) {
1972+ setTimeout ( ( ) => {
1973+ this . loadClasses ( ) ;
1974+ } , 1000 ) ;
1975+ }
1976+ } ) ;
1977+ } ,
1978+
17901979 createMenuElement ( content , menu , insertAfter ) {
17911980 if ( ! content ) { return ; }
17921981 const item = document . createElement ( "div" ) ;
@@ -1807,87 +1996,24 @@ const Remote = {
18071996 item . append ( mcmText ) ;
18081997 }
18091998
1810- switch ( content . type ) {
1811- case "menu" : {
1812- const mcmArrow = document . createElement ( "span" ) ;
1813- mcmArrow . className = "fa fa-fw fa-angle-right" ;
1814- mcmArrow . setAttribute ( "aria-hidden" , "true" ) ;
1815- item . append ( mcmArrow ) ;
1816- item . dataset . parent = menu ;
1817- item . dataset . type = "menu" ;
1818- document . querySelector ( "#back-button" ) . classList . add ( `${ content . id } -menu` ) ;
1819- const menuContent = document . querySelector ( ".menu-content" ) ;
1820- if ( menuContent ) {
1821- menuContent . classList . add ( `${ content . id } -menu` ) ;
1822- }
1823- item . addEventListener ( "click" , ( ) => {
1824- globalThis . location . hash = `${ content . id } -menu` ;
1825- } ) ;
1999+ // Add status badge for Classes menu
2000+ if ( menu === "classes" && content . classData ) {
2001+ this . addClassStatusBadge ( item , content . classData ) ;
2002+ }
18262003
2004+ switch ( content . type ) {
2005+ case "menu" :
2006+ this . createMenuTypeElement ( item , content , menu ) ;
18272007 break ;
1828- }
1829- case "slider" : {
1830- const contain = document . createElement ( "div" ) ;
1831- contain . classList . add ( "flex-1" ) ;
1832-
1833- const slide = document . createElement ( "input" ) ;
1834- slide . id = `${ content . id } -slider` ;
1835- slide . className = "slider" ;
1836- slide . type = "range" ;
1837- slide . min = content . min || 0 ;
1838- slide . max = content . max || 100 ;
1839- slide . step = content . step || 10 ;
1840- slide . value = content . defaultValue || 50 ;
1841-
1842- slide . addEventListener ( "change" , ( ) => {
1843- this . sendSocketNotification ( "REMOTE_ACTION" , {
1844- action : content . action . toUpperCase ( ) ,
1845- ...content . content ,
1846- payload : {
1847- ...content . content === undefined ? { } : ( typeof content . content . payload === "string" ? { string : content . content . payload } : content . content . payload ) ,
1848- value : slide . value
1849- } ,
1850- value : slide . value
1851- } ) ;
1852- } ) ;
1853-
1854- contain . append ( slide ) ;
1855- item . append ( contain ) ;
1856-
2008+ case "slider" :
2009+ this . createSliderElement ( item , content ) ;
18572010 break ;
1858- }
1859- case "input" : {
1860- const input = document . createElement ( "input" ) ;
1861- input . id = `${ content . id } -input` ;
1862- input . className = `menu-element ${ menu } -menu medium` ;
1863- input . type = "text" ;
1864- input . placeholder = content . text ;
1865-
1866- input . addEventListener ( "focusout" , ( ) => {
1867- this . sendSocketNotification ( "REMOTE_ACTION" , {
1868- action : content . action . toUpperCase ( ) ,
1869- ...content . content ,
1870- payload : {
1871- ...content . content === undefined ? { } : ( typeof content . content . payload === "string" ? { string : content . content . payload } : content . content . payload ) ,
1872- value : input . value
1873- } ,
1874- value : input . value
1875- } ) ;
1876- } ) ;
1877-
1878- return input ;
1879- }
1880- default : if ( content . action && content . content ) {
1881- item . dataset . type = "item" ;
1882- item . addEventListener ( "click" , ( ) => {
1883- this . sendSocketNotification ( "REMOTE_ACTION" , {
1884- action : content . action . toUpperCase ( ) ,
1885- payload : { } ,
1886- ...content . content
1887- } ) ;
1888- } ) ;
1889- }
1890-
2011+ case "input" :
2012+ return this . createInputElement ( content , menu ) ;
2013+ default :
2014+ if ( content . action && content . content ) {
2015+ this . addItemClickHandler ( item , content , menu ) ;
2016+ }
18912017 }
18922018
18932019 if ( ! globalThis . location . hash && menu !== "main" ||
0 commit comments