#
UDImageZoom Powershell Universal Component Module 🖼️
#
Powershell Universal 🌎
I have mentioned this a good few times in previous blogs that I really miss using Powershell Universal. I mean when I first got using this, it was just called Universal Dashboard. This then grew into a product offering three main features Jobs, APIs and Dashboards. This became Powershell Universal, read all about what it can do here:-
To me this product is just so amazing. Not only does it contain a huge amount of components for your dashboards, images, cards, accordians, buttons, select options, graphs and lots more the developer of this software also gave the opportunity to allow you as an end-user build custom components to extend the list of components that can be used.
Check out the demo instance of this software to get a feel for the main product portal where you can control all the super cool stuff you can do.
#
React Component 🔧
Yes I know I keep mentioning the word component but you may know this as a widget or self-contained application, or maybe a mini application to me a component does its own thing using its own bit of the webpage and can have certain parameters associated with it. So you could have a graph component that has a refresh button. Back in the old web days, this would refresh the whole webpage to then re-render the graph. Where-as a React component would just refresh that component, and anything else on the web-page would be un-affected by this refresh happening on the graph component. This is why to me they are isolated objects on the web-page all running in their own run-spaces.
Although Powershell Universal is like amazing, like so amazing. It is using that material-ui theme, and all the associated components with that theme. All the components for this react theme are listed here:-
So hopefully by now you know what I mean by the word component. If you are still confused then please check-out the official documentation for the components that are included into this product. Seriously this is well worth reading the documentation to understand this product more, as just like it was for me, all this was brand-new stuff to learn, and get my head around what these different components did, how they displayed on the screen, and how I could use them for particular parts of my dashboard.
#
Custom Component ⚒️
There are many places you can find custom react components that either individuals have built, or a team of people working together to build a component. One site I like to see custom react components on is npmjs.com there is also https://bit.cloud/ however I prefer to use:-
Seriously the react component library is massive, like really, really big. There are just so many components out there. Like looking at card components, hundreds are returned...but end of the day they are all card components...just a bit different looking (themed). So as always just like pretty much all my modules I try to produce I try to find something that does not already exist, and will hopefully benefit others.
I know I have done a fair-few image components in the past, but I wanted something new.
I probably got a few more, but you get the idea, I have done a fair few components already, however none of these offered the effect this component was going to bring. This technique is also used on a lot of modern sites such as Amazon, when looking at the product you want to buy, it is always helpful to get an extra good look at that product before you press that buy button.
#
Fate 👼
I am not a man of faith, but I do believe in fate. It seems life has assigned a guardian angel to look out for me and help me through a difficult patch. This particular guardian angel has allowed me to have a decent machine I can use to get back into Powershell Universal, as I have mentioned before but I only run on a really old rubbish x86 laptop. Sadly Powershell Universal is only x64. Thanks to my guardian angel I got a great cloud machine to now use.
#
Image Zoom Effect 🔎
As with all good guardian angels, they like to know you are committed to becoming that better person, or being that person you believe you can be. My particular guardian angel suggested I should make more Powershell Universal components, and this time make a image zoom component.
First step was to go to www.npmjs.com to see what I could find on there. I believe I hit that jackpot, and found a nice image zoom component that ticked all the boxes of looking great and doing what it needed to do, which was to magnify the image when the mouse hovered over it.
I always appreciate it when someone has the time to write good documentation on how to use something, and this component had just that, as well as a demo site showing you the component in action. Another great thing is this component had zero dependencies, meaning I only needed this one npm package in order to build this component. This was a major blessing as well, as in the past I can remember some components, having lots and lots of dependencies, which will slow down the build process.
#
Github Template 👾
The next section on building the custom component relies on you having a local copy of this repository which is a template you can use to convert any react component into a Powershell Universal dashboard component. I mean how amazing is that. You can convert something written in a completely different language and make it work with native Powershell commands, using Powershell. It still blows my mind how amazing this is, as now there so many possibilities on what you can now display in your dashboard.
#
Building The Component 🚧
There is an outline of how to build a custom component here:-
Further official documentation can also be found on the blog on the ironman software site. This documentation personally made more sense to me:-
Even though I had previously built a good amount I think 90+ custom components, that was using a different technique, as the software has since been updated to use a newer version of react, and so the build method changed. Honestly this change has given a ginormous improvement in the time it takes to build the custom component. When I was building these custom components on my x86 laptop, it was taking sometimes up to 20 minutes or longer to build the component depending on the amount of dependencies the component had. However using this new build technique it only takes about 5-10 seconds! Yes seconds not minutes, so using this new method is a massive time saver in itself.
#
Component JSX File 🗃️
So there are a fair few good files you need to edit in some shape or form to build a component, I think it would be a good idea for me to document this process to show how simple it really is. Before I could edit this JSX file within the components folder I needed to make sure I had installed the npm pacakge for this react component I did this by copying the command from npmjs.com
npm i react-img-zoom
So once that was installed, and I had renamed the .PSD1 and .PSM1 file to the module name I wanted. I then edited the .PSD1 file to include the RootModule as the newly named .PSM1 file, I edited the component.build.ps1 file to copy the newly named modules
Copy-Item $PSScriptRoot\UDImageZoom.psd1 $OutputPath
Copy-Item $PSScriptRoot\UDImageZoom.psm1 $OutputPath
also edited line 20 in the webpack.config.js file to be
library: 'udimagezoom'
Within the components folder there is an index.js file my edited file looked like
import UDImageZoom from './component';
UniversalDashboard.register("udimagezoom", UDImageZoom);
Please keep case-sensitive lower-case for the webpack.config.js file which then reflects what is typed as first arguement within the parenthesis as shown above.
Once you have made all these edits to the existing template files, and installed the npm package and all dependencies (in this case I only had one package to install as no dependencies) it is time to construct the actual component that will be displayed on the dashboard. This is done by editing the component.jsx file witin the components folder within the github template you downloaded. This is my final edited component.jsx file:-
import React from 'react';
import { withComponentFeatures } from 'universal-dashboard'
import Zoom from 'react-img-zoom'
const UDImageZoom = props => {
return <Zoom
img={props.img}
zoomScale={props.zoomScale}
width={props.width}
height={props.height}
transitionTime={props.transitionTime}
/>;
}
export default withComponentFeatures(UDImageZoom)
So VSCode was not complaining about any of the code above, so now I needed to edit the **.PSM1 and .PSD1 file to finish this component off before running invoke-build so this is my final PSD1 file
#
# Module manifest for module 'UDImageZoom'
#
# Generated by: adam bacon
#
# Generated on: 31/08/2022
#
@{
# Script module or binary module file associated with this manifest.
RootModule = 'UDImageZoom.psm1'
# Version number of this module.
ModuleVersion = '0.0.1'
# Supported PSEditions
# CompatiblePSEditions = @()
# ID used to uniquely identify this module
GUID = '76de2c49-86a9-4b58-9247-edbe35fed09a'
# Author of this module
Author = 'psdevuk'
# Company or vendor of this module
CompanyName = 'Home'
# Copyright statement for this module
Copyright = '(c) adamr. All rights reserved.'
# Description of the functionality provided by this module
Description = 'Gives zooming capabilities to images'
# Minimum version of the PowerShell engine required by this module
# PowerShellVersion = ''
# Name of the PowerShell host required by this module
# PowerShellHostName = ''
# Minimum version of the PowerShell host required by this module
# PowerShellHostVersion = ''
# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
# DotNetFrameworkVersion = ''
# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
# ClrVersion = ''
# Processor architecture (None, X86, Amd64) required by this module
# ProcessorArchitecture = ''
# Modules that must be imported into the global environment prior to importing this module
# RequiredModules = @()
# Assemblies that must be loaded prior to importing this module
# RequiredAssemblies = @()
# Script files (.ps1) that are run in the caller's environment prior to importing this module.
# ScriptsToProcess = @()
# Type files (.ps1xml) to be loaded when importing this module
# TypesToProcess = @()
# Format files (.ps1xml) to be loaded when importing this module
# FormatsToProcess = @()
# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
# NestedModules = @()
# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
FunctionsToExport = 'New-UDImageZoom'
# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
CmdletsToExport = '*'
# Variables to export from this module
VariablesToExport = '*'
# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
AliasesToExport = '*'
# DSC resources to export from this module
# DscResourcesToExport = @()
# List of all modules packaged with this module
# ModuleList = @()
# List of all files packaged with this module
# FileList = @()
# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
PrivateData = @{
PSData = @{
# Tags applied to this module. These help with module discovery in online galleries.
Tags = @('universaldashboard','ud-dashboard','Image','Zoom')
# A URL to the license for this module.
# LicenseUri = ''
# A URL to the main website for this project.
ProjectUri = 'https://github.com/psDevUK/UDImageZoom'
# A URL to an icon representing this module.
IconUri = 'https://github.com/psDevUK/UDImageZoom/blob/main/Logo.gif?raw=true'
# ReleaseNotes of this module
# ReleaseNotes = ''
# Prerelease string of this module
# Prerelease = ''
# Flag to indicate whether the module requires explicit user acceptance for install/update/save
# RequireLicenseAcceptance = $false
# External dependent modules of this module
# ExternalModuleDependencies = @()
} # End of PSData hashtable
} # End of PrivateData hashtable
# HelpInfo URI of this module
# HelpInfoURI = ''
# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
# DefaultCommandPrefix = ''
}
To make the actual cmdlet behind this component you need to edit the pre-defined function in the .PSM1 file so this is my finished .PSM1 before running the invoke-build
$IndexJs = Get-ChildItem "$PSScriptRoot\index.*.bundle.js"
$AssetId = [UniversalDashboard.Services.AssetService]::Instance.RegisterAsset($IndexJs.FullName)
function New-UDImageZoom {
<#
.SYNOPSIS
Zooms into an image
.DESCRIPTION
This component is using react-img-zoom to gracefully zoom into an image
.PARAMETER Id
The ID of this component
.PARAMETER Path
Specify the full path to the image to be loaded
.PARAMETER Zoom
Specify how much the zoom should be this is an integer value defaulted to 3
.PARAMETER Height
Specify the height of the image to be displayed this is an integer value only and represents pixels
.PARAMETER Width
Specify the width of the image to be displayed this is an integer value only and represents pixels
.PARAMETER Delay
Specify the amount of delay whilst zooming in and out. This is a decimal value which is defaulted to 0.6
.EXAMPLE
New-UDImageZoom -Path /UD/CoolImage.png -Height 400 -Width 400 -Zoom 5 -Delay 0.8
#>
param(
[Parameter()]
[string]$Id = (New-Guid).ToString(),
[Parameter()]
[string]$Path,
[Parameter()]
[int]$Zoom =3,
[Parameter()]
[int]$Height,
[Parameter()]
[int]$Width,
[Parameter()]
[decimal]$Delay = 0.6
)
End {
@{
assetId = $AssetId
isPlugin = $true
type = "udimagezoom"
id = $Id
img = $Path
zoomScale = $Zoom
height = $Height
width = $Width
transitionTime = $Delay
}
}
}
#
Ready, Steady, Go! 🚦
So once you have followed the above, you are now ready to run:-
invoke-build
As long as you read the official documentation on building a custom component you would have already downloaded all the prerequisite modules and software required to build custom components. I did find I needed to also install the psake module as well. This process literally took 10 seconds or less. As long as you do not get any errors, and the process completes then within the output directory you will have you brand-new custom component you built. My output directory now contained the following four files index.5e8cb3b240ba9ee67c1f.bundle.js,index.5e8cb3b240ba9ee67c1f.bundle.map,UDImageZoom.psd1,UDImageZoom.psm1. Next stage was to now test this in a simple dashboard, I made a directory called UDImageZoom within C:\Program Files\WindowsPowerShell\Modules* and copied these newly created files into this new folder directory **C:\Program Files\WindowsPowerShell\Modules\UDImageZoom*. I restarted the PowershellUniversal service then logged into the main portal. Verified the module was being picked up by the software, by searching the available modules within the program. Once I verified my new module was included, I then did a test on the dashboard.
I now had a fully working react custom component loaded into the Powershell Universal dashboard I had created. I then verified all the parameters worked, which they did then it was time to publish this module to the Powershell Gallery. Please note to include ud-component within the module tags to enable your custom component to be found on the market place exclusive to this product.