PSWorkItem.psm1
# used for culture debugging # write-host "Importing with culture $(Get-Culture)" if ((Get-Culture).Name -match '\w+') { Import-LocalizedData -BindingVariable strings } else { #force using En-US if no culture found, which might happen on non-Windows systems. Import-LocalizedData -BindingVariable strings -FileName PSWorkItem.psd1 -BaseDirectory $PSScriptRoot\en-us } #Adding a failsafe check for Windows PowerShell if ($IsMacOS -or ($PSEdition -eq 'Desktop')) { Write-Warning $Strings.Unsupported #bail out Return } Get-ChildItem $PSScriptRoot\functions\*.ps1 -Recurse | ForEach-Object { . $_.FullName } #testing localization #Write-Host $strings.Testing -fore cyan #region assembly loading #there may be version conflicts #required versions [version]$NStackVersion = '1.1.1.0' [version]$TerminalGuiVersion = '1.17.1' $dlls = "$PSScriptRoot\assemblies\NStack.dll", "$PSScriptRoot\assemblies\Terminal.Gui.dll" foreach ($dll in $dlls) { $name = Split-Path -Path $dll -Leaf #write-host "Loading $dll" -fore yellow Try { Add-Type -Path $dll -ErrorAction Stop } Catch { $msg = ($strings.WarnAssemblyLoaded -f $Name) Write-Warning $msg #$verMessage = "Detected version $($PSStyle.Foreground.Red){0}$($PSStyle.Reset) which is less than the expected version of $($PSStyle.Foreground.Green){1}$($PSStyle.Reset). $($PSStyle.Italic)There may be unexpected behavior$($PSStyle.Reset). You may need to start a new PowerShell session and load this module first." Switch ($Name) { 'NStack.dll' { #get currently loaded version $ver = [System.Reflection.Assembly]::GetAssembly([NStack.uString]).GetName().version if ($ver -lt $NStackVersion) { $Detail = $strings.WarnDetected -f $ver, $NStackVersion, $PSStyle.Foreground.Red, $PSStyle.Foreground.Green, $PSStyle.Italic, $PSStyle.Reset } } 'Terminal.Gui.dll' { $ver = [System.Reflection.Assembly]::GetAssembly([Terminal.Gui.Application]).GetName().version if ($ver -lt $TerminalGuiVersion) { $Detail = $strings.WarnDetected -f $ver, $TerminalGuiVersion, $PSStyle.Foreground.Red, $PSStyle.Foreground.Green, $PSStyle.Italic, $PSStyle.Reset } } } #switch if ($Detail) { Write-Warning $Detail } } } #endregion #region class definitions <# classes for PSWorkItem and PSWorkItemArchive #> #define base PSWorkItem class class PSWorkItemBase { [int]$ID [String]$Name [String]$Category [String]$Description [DateTime]$TaskCreated = (Get-Date) [DateTime]$TaskModified = (Get-Date) [boolean]$Completed [String]$Path #this will be last resort GUID to ensure uniqueness hidden[guid]$TaskID = (New-Guid).Guid } class PSWorkItem:PSWorkItemBase { [DateTime]$DueDate = (Get-Date).AddDays(30) [int]$Progress = 0 PSWorkItem ([String]$Name, [String]$Category) { $this.Name = $Name $this.Category = $Category } PSWorkItem() { $this } } Class PSWorkItemArchive:PSWorkItemBase { [DateTime]$DueDate [int]$Progress } class PSWorkItemCategory { [String]$Category [String]$Description #constructor PSWorkItemCategory([String]$Category, [String]$Description) { $this.Category = $Category $this.Description = $Description } } class PSWorkItemDatabase { [String]$Path [DateTime]$Created [DateTime]$LastModified [int32]$Size [int32]$TaskCount [int32]$CategoryCount [int32]$ArchiveCount [String]$Encoding [int32]$PageCount [int32]$PageSize [string]$SQLiteVersion [string]$CreatedBy } #endregion #region type extensions Update-TypeData -TypeName PSWorkItemCategory -MemberType ScriptProperty -MemberName ANSIString -Value { $PSWorkItemCategory[$this.Category] -replace "`e", "``e" } -Force #endregion #region settings and configuration <# Default categories when creating a new database file. This will be a module-scoped variable, not exposed to the user #> $script:PSWorkItemDefaultCategories = 'Work', 'Personal', 'Project', 'Other' #a global hashtable used for formatting PSWorkItems $global:PSWorkItemCategory = @{ 'Work' = $PSStyle.Foreground.Cyan 'Personal' = $PSStyle.Foreground.Green } <# a hash table to store ANSI escape sequences for different commands used in verbose output with the private _verbose helper function #> $VerboseANSI = @{ 'Get-PSWorkItem' = '[1;38;5;122m' 'Get-PSWorkItemCategory' = '[1;38;5;111m' 'Set-PSWorkItem' = '[1;96m' 'New-PSWorkItem' = '[1;38;5;10m' 'Complete-PSWorkItem' = '[1;38;5;208m' 'Get-PSWorkItemReport' = '[1;38;5;159m' 'Get-PSWorkItemDatabase' = '[1;38;5;195m' 'Initialize-PSWorkItemDatabase' = '[1;38;5;214m' 'Get-PSWorkItemArchive' = '[1;38;5;228m' 'Remove-PSWorkItem' = '[1;38;5;197m' Default = '[1;38;5;51m' } #used in verbose messaging $ModuleVersion = '1.11.0' #import and use the preference file if found $PreferencePath = Join-Path -Path $HOME -ChildPath '.psworkitempref.json' If (Test-Path $PreferencePath) { $importPref = Get-Content $PreferencePath | ConvertFrom-Json $global:PSWorkItemPath = $importPref.Path $importPref.categories.foreach({ $PSWorkItemCategory[$_.category] = $_.ansi }) if ($importPref.DefaultDays) { $global:PSWorkItemDefaultDays = $importPref.DefaultDays } If ($importPref.DefaultCategory) { $global:PSDefaultParameterValues['New-PSWorkItem:Category'] = $importPref.DefaultCategory } } else { #make this variable global instead of exporting so that I don't have to use Export-ModuleMember 7/28/2022 JDH $global:PSWorkItemPath = Join-Path -Path $HOME -ChildPath 'PSWorkItem.db' $global:PSWorkItemDefaultDays = 30 } #endregion #region auto completers Register-ArgumentCompleter -CommandName Set-PSWorkItem, Remove-PSWorkItem, Complete-PSWorkItem -ParameterName ID -ScriptBlock { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter) Invoke-MySQLiteQuery 'Select Name,ID,Completed from Tasks' -database $PSWorkItemPath | ForEach-Object { [System.Management.Automation.CompletionResult]::new([int]$_.ID, [int]$_.ID, 'ParameterValue', $_.Name) } } #endregion |