Loading animation example (with automatic page refesh)

Hi,
here are two little exaples for page loading animations with css.

Progressbar looping:

Get-UDDashboard | Stop-UDDashboard

$pages = @()
$pages += New-UDPage -Name "home" -Endpoint {
  $Cache:Loading = $true
  $Cache:i = 0

  New-UDRow -Endpoint{
    if($Cache:Loading){
      $visibility = 'visible'
      $Cache:i = $Cache:i + 20
      if($Cache:i -eq 120){$Cache:i = 20}
      if($Cache:i -ge 60){$lcolor = 'white'}else{$lcolor = 'black'}
    }else{
      $visibility = 'hidden'
    }
    
    New-UDElement -Tag div -Content {
      New-UDElement -Tag div -Content {
      } -Attributes @{
        style = @{
          backgroundColor = 'rgb(36, 81, 131)'
          height = '50px'
          width = "$($Cache:i)%"
        }
      }
      
      New-UDElement -Tag span -Content {
        'loading...'
      } -Attributes @{
        style = @{
          position = 'absolute'
          top = '50%'
          left = '50%'
          transform = 'translate(-50%, -50%)'
          color = $lcolor
          'font-size' = '20px'
        }
      }

    } -Attributes @{
      style = @{
        position = 'fixed'
        top = '50%'
        left = '50%'
        transform = 'translate(-50%, -50%)'
        height = '50px'
        width = '50%'
        outline = 'solid black'
        visibility = $visibility
      }
    }
  } -AutoRefresh -RefreshInterval 1
  
  New-UDRow -Endpoint {
    $Cache:Loading = $true
    
    #Payload
    Start-Sleep -Seconds 10
    New-UDCard -Title Content -Content {
      New-UDHeading -Text 'job finished'
    }
    ########
    
    $Cache:Loading = $false
  }
}

$Dashboard = New-UDDashboard -Title 'test' -Page $pages
Start-UDDashboard -Port 10001 -Dashboard $Dashboard

Progressbar dynamically refreshed based on job progress:

Get-UDDashboard | Stop-UDDashboard

$pages = @()
$pages += New-UDPage -Name "home" -Endpoint {
  $Cache:Loading = $true
  $Cache:LoadingPercent = 0
  
  New-UDRow -Endpoint{
    if($Cache:Loading){
      $visibility = 'visible'
      if($Cache:LoadingPercent -ge 60){$lcolor = 'white'}else{$lcolor = 'black'}
    }else{
      $visibility = 'hidden'
    }
    
    New-UDElement -Tag div -Content {
      New-UDElement -Tag div -Content {
      } -Attributes @{
        style = @{
          backgroundColor = 'rgb(36, 81, 131)'
          height = '50px'
          width = "$($Cache:LoadingPercent)%"
        }
      }
      
      New-UDElement -Tag span -Content {
        "$Cache:LoadingText" #'loading...'
      } -Attributes @{
        style = @{
          position = 'absolute'
          top = '50%'
          left = '50%'
          transform = 'translate(-50%, -50%)'
          color = $lcolor
          'font-size' = '20px'
        }
      }

    } -Attributes @{
      style = @{
        position = 'fixed'
        top = '50%'
        left = '50%'
        transform = 'translate(-50%, -50%)'
        height = '50px'
        width = '50%'
        outline = 'solid black'
        visibility = $visibility
      }
    }
  } -AutoRefresh -RefreshInterval 1
  
  New-UDRow -Endpoint {
    $Cache:Loading = $true
    
    #Payload
    $Cache:LoadingText = 'loading text 1'
    $Cache:LoadingPercent = 20
    Start-Sleep -Seconds 3
    
    $Cache:LoadingText = 'loading text 2'
    $Cache:LoadingPercent = 40
    Start-Sleep -Seconds 3
    
    $Cache:LoadingText = 'loading text 3'
    $Cache:LoadingPercent = 60
    Start-Sleep -Seconds 3
    
    $Cache:LoadingText = 'loading text 4'
    $Cache:LoadingPercent = 80
    Start-Sleep -Seconds 3
    
    $Cache:LoadingText = 'loading text 5'
    $Cache:LoadingPercent = 100
    Start-Sleep -Seconds 3

    New-UDCard -Title Content -Content {
      New-UDHeading -Text 'job finished'
    }
    ########
    
    $Cache:Loading = $false
  }
}

$Dashboard = New-UDDashboard -Title 'test' -Page $pages
Start-UDDashboard -Port 10001 -Dashboard $Dashboard
4 Likes

I love it, keep with the good work

1 Like

Thanks for sharing great stuff

1 Like

This is great. Does anybody have any examples of using this to monitor the progress of a PowerShell job? Job, Runspace job, etc and returning the output of the job in a nice format?

I’m currently trying to do this, and I’m having a hard time figuring it out. I’m close but returning data nicely is not playing well for me.

I have to dig up this old post here :wink:

@psott

Thanks for this code :slight_smile:
With your example you gave me the idea last year to display a loading animation with “real” data. This was necessary for us because we process a lot of data, e.g. a detailed overview of several thousand VMs in a grid that is generated live by the dashboard from several vCenters (no database backend).
Currently i am using this loading screen on every page where the preparation of the data “needs some time” over the last year.
I need to put the code into a generic function, that is one of the next steps. Currently for the last 12 month it is integrated and customized in every page where i need it.

Here is an example where the loading animation shows the preparation of the UDGrid data for every VM (foreach loop with PSCustomObjects, 275 in this example testing dashboard) in 2 steps:

1. Step: Gathering information - It will wait and show this progress bar until the 5 needed Cache variables are available (using a do-until loop. The Cache variables for VMs, ESX Hosts etc. will be generated with scheduled endpoints). This is useful after startup of the dashboard, where no or not all data is available for a few minutes.
2. Step - Preparing results: It will loop through the VMs Cache Variable and is generating the output (Name,Description,HostName,State,vCenter,Host,Folder,ResourcePool,Guest OS,ToolsVersion,IPAddress(es),CPUs,MemoryGB,HardDiskGB) for each PSCustomObject Member. This will take some time if you have a few thousand VMs due to the fact it needs all data from different vCenters validated from different cmdlets Get-Harddisk, Get-VM, Get-Host, Get-NetworkAdapter, Get-VMGuest using different custom functions (f.e. getting full folder path, not only the parent folder), that will be created through the above mentioned scheduled endpoints.
If you are using a few vCenter Servers, you quickly run into the problem that the VMid cannot be used as a unique identifier because it is not unique across the vCenters and the PersistentID is not available on every object. Therefore, a validation with the Uid of the respective object also takes place here (resolved with Regex/Substrings/joins…).

(Two examples in one gif, you can see the second, longer loading example if the amount of VMs and the header bar changes)

I cannot show the result (privacy policy), but after hitting 275 of 275 VMs the page will refresh and the data will be shown in the UDGrid.

(In the future we will gather all data outside of UniversalDashboard and save these data into a sql database. The dashboard(s) will only read these data from the sql database and show the results. This will be MUCH faster than crawling the needed information with UniversalDashboard. Also the memory usage in one of our largest dashboards is really enormous at first glance if we would not recycle the AppPool if a specific amount of used memory is reached but since we are caching all the data gathered by 15 different VMware powercli cmdlet, ExtensionData etc., using GarbageCollection and other cleanup stuff, it is really fast for this amount of data).

I’m not allowed to post the full code (sorry :() but it’s mostly based on the code from @psott . I am posting this as an example of what you can do with it.
Here is a snippet of the part of the “real” data in the progress bar:

...
$Session:LoadingVMs = $true
$outArrayComplete = $false
...
if ($VMs)
{
   $VMCount = $VMs.Count
}
$CurrentVMCount = 0
$Session:LoadingTextVMs = "Preparing results (0/$VMCount)..."
...
$outArray = ($VMs).foreach( {
   $CurrentVMCount++
   $Session:LoadingTextVMs = "Preparing results ($CurrentVMCount/$VMCount)..."
   $Session:LoadingPercentVMs = $CurrentVMCount / $VMCount * 100
   ...
})
$outArrayComplete = $true
...
if ($outArray -and $outArrayComplete)
{
   $Session:LoadingVMs = $false
   $CurrentVMCount = 0
   $outArray = $outArray | Sort-Object Name -CaseSensitive
   Out-UDGridData -Data $outArray
}
2 Likes