Skip to content

Commit 076e605

Browse files
committed
Display script progress function
1 parent b98a701 commit 076e605

File tree

12 files changed

+210
-71
lines changed

12 files changed

+210
-71
lines changed

package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "lazy-admin",
3-
"version": "0.4.3",
3+
"version": "0.4.4",
44
"description": "GUI for PowerShell scripts to simplify day to day IT tasks.",
55
"productName": "Lazy Admin",
66
"cordovaId": "eu.houby-studio.lazy-admin",
@@ -13,7 +13,7 @@
1313
"release": "quasar build --mode electron --publish onTagOrDraft"
1414
},
1515
"dependencies": {
16-
"@quasar/extras": "^1.9.3",
16+
"@quasar/extras": "^1.9.4",
1717
"axios": "^0.19.2",
1818
"electron-log": "^4.1.1",
1919
"electron-updater": "^4.3.1",
@@ -28,7 +28,7 @@
2828
},
2929
"devDependencies": {
3030
"@quasar/app": "^1.9.6",
31-
"@quasar/quasar-app-extension-qmarkdown": "^1.0.29",
31+
"@quasar/quasar-app-extension-qmarkdown": "^1.0.30",
3232
"@vue/eslint-config-standard": "^4.0.0",
3333
"awesome-node-loader": "^1.1.1",
3434
"babel-eslint": "^10.0.1",
@@ -50,4 +50,4 @@
5050
"browserslist": [
5151
"last 1 version, not dead, ie >= 11"
5252
]
53-
}
53+
}

scripts-definitions/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ Possible values for definitions file:
6363
* commandName: Preferably name of the Cmdlet or function, which this definition uses, displayed to user to get the idea what the command might do
6464
* icon: name of icon, if omitted, powershell icon is used
6565
* returns: type of the result, which application should expect after command is executed ("raw", "PSObject")
66+
* progress: does command output progress before emitting results (true, false)
6667
* insidePsSession: whether command should be run in Remote PSSession or locally (true, false)
6768
* usesLoginObjects: whether command utilizes $CredentialObject or $LazySession created upon logging in (true, false)
6869
* confirm: before executing the command, ask user for confirmation (true, false)
@@ -113,6 +114,7 @@ This is only example, there are many possibilities how to write definitions.
113114
"commandName": "${Verb-Noun}",
114115
"icon": "${icon-name}",
115116
"returns": "${returnType}",
117+
"progress": "${Boolean}",
116118
"insidePsSession": ${Boolean},
117119
"usesLoginObjects": ${Boolean},
118120
"friendlyName": "${friendlyName}",
@@ -151,6 +153,7 @@ This is only example, there are many possibilities how to write definitions.
151153
"acceptsParams": ${Boolean},
152154
"joinParamsAsString": ${Boolean},
153155
"returns": "${returnType}",
156+
"progress": "${Boolean}",
154157
"insidePsSession": ${Boolean},
155158
"confirm": ${Boolean},
156159
"passedParameters": [

scripts-definitions/base-module-example.json

Lines changed: 50 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"base-module-example": {
3-
"version": "0.1.6",
3+
"version": "0.1.7",
44
"icon": "mdi-powershell",
55
"displayName": {
66
"default": "Base commands",
@@ -15,7 +15,6 @@
1515
"definition": [
1616
{
1717
"commandName": "Get-Disk",
18-
"type": "simple",
1918
"icon": "mdi-harddisk",
2019
"returns": "PSObject",
2120
"insidePsSession": false,
@@ -52,8 +51,8 @@
5251
"required": false,
5352
"type": "Number",
5453
"hint": {
55-
"default": "Supply index number of the disk",
56-
"en-us": "Supply index number of the disk",
54+
"default": "Supply index number of the disk",
55+
"en-us": "Supply index number of the disk",
5756
"cs-cz": "Zadejte indexové číslo disku"
5857
}
5958
}
@@ -62,7 +61,6 @@
6261
},
6362
{
6463
"commandName": "Get-Help",
65-
"type": "simple",
6664
"returns": "raw",
6765
"insidePsSession": true,
6866
"friendlyName": {
@@ -119,7 +117,6 @@
119117
},
120118
{
121119
"commandName": "Invoke-Command",
122-
"type": "simple",
123120
"icon": "mdi-powershell",
124121
"returns": "raw",
125122
"insidePsSession": false,
@@ -154,7 +151,6 @@
154151
},
155152
{
156153
"commandName": "Start-PowerShell",
157-
"type": "simple",
158154
"icon": "mdi-powershell",
159155
"returns": "raw",
160156
"insidePsSession": false,
@@ -177,7 +173,6 @@
177173
},
178174
{
179175
"commandName": "Test-Connection",
180-
"type": "simple",
181176
"icon": "mdi-powershell",
182177
"returns": "raw",
183178
"insidePsSession": false,
@@ -223,7 +218,6 @@
223218
},
224219
{
225220
"commandName": "Test-Parameters",
226-
"type": "simple",
227221
"icon": "mdi-powershell",
228222
"returns": "raw",
229223
"insidePsSession": false,
@@ -674,6 +668,53 @@
674668
"commandBlock": "if ({{Repeat}}) {Write-Output '{{__raw_argument}}'}"
675669
}
676670
]
671+
},
672+
{
673+
"commandName": "Test-Progress",
674+
"icon": "mdi-progress-clock",
675+
"returns": "PSObject",
676+
"insidePsSession": false,
677+
"usesLoginObjects": false,
678+
"progress": true,
679+
"friendlyName": {
680+
"default": "Test progress output",
681+
"en-us": "Test progress output",
682+
"cs-cz": "Test výstupu průběhu"
683+
},
684+
"description": {
685+
"default": "Outputs message to console every couple seconds.",
686+
"en-us": "Outputs message to console every couple seconds.",
687+
"cs-cz": "Vypíše zprávu do konzole každých pár vteřin."
688+
},
689+
"help": {
690+
"default": "https://raw.githubusercontent.com/wiki/houby-studio/lazy-admin/Test-Progress.md",
691+
"en-us": "https://raw.githubusercontent.com/wiki/houby-studio/lazy-admin/Test-Progress.md"
692+
},
693+
"parameters": [
694+
{
695+
"parameter": "Message",
696+
"value": "This is default progress message",
697+
"required": true,
698+
"type": "String",
699+
"hint": {
700+
"default": "Supply message to be written to console",
701+
"en-us": "Supply message to be written to console",
702+
"cs-cz": "Zadejte zprávu, která se vypíše do konzole"
703+
}
704+
},
705+
{
706+
"parameter": "Number",
707+
"value": "5",
708+
"required": false,
709+
"type": "Number",
710+
"hint": {
711+
"default": "Supply number of times message should be written to console",
712+
"en-us": "Supply number of times message should be written to console",
713+
"cs-cz": "Zadejte číslo, kolikrát se vypíše zpráva do konzole"
714+
}
715+
}
716+
],
717+
"commandBlock": "for (($i=0); $i -lt {{Number}}; $i++) {Write-Output \"{{Message}} $i\"; Start-Sleep -Seconds 1};\"EOIP\"; Get-Partition | Select Type | ConvertTo-Json -Compress"
677718
}
678719
]
679720
}

src/i18n/cs-cz/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ export default {
6868
alwaysConfirm: 'Vždy požadovat potvrzení před spuštěním příkazu.', // Used in: SettingsPage.vue
6969
inputDense: 'Zobrazovat vstupní parametry v těsném rozložení.', // Used in: SettingsPage.vue
7070
tableDense: 'Zobrazovat tabulky v těsném rozložení.', // Used in: SettingsPage.vue
71+
displayProgress: 'Vždy zobrazovat průběh skriptu.', // Used in: SettingsPage.vue
7172
masterDefinition: 'Hlavní definice', // Used in: AboutPage.vue
7273
update: 'Aktualizovat', // Used in: AboutPage.vue
7374
restartRequired: 'Vyžadován restart.', // Used in: AboutPage.vue

src/i18n/en-us/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ export default {
6868
alwaysConfirm: 'Always require confirmation before script execution.', // Used in: SettingsPage.vue
6969
inputDense: 'Display input parameters in dense layout.', // Used in: SettingsPage.vue
7070
tableDense: 'Display tables in dense layout.', // Used in: SettingsPage.vue
71+
displayProgress: 'Always display script progress.', // Used in: SettingsPage.vue
7172
autoClipboard: 'Automatically store command results to clipboard.', // Used in: SettingsPage.vue
7273
masterDefinition: 'Master definition', // Used in: AboutPage.vue
7374
update: 'Update', // Used in: AboutPage.vue

src/pages/ScriptsPage.vue

Lines changed: 68 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,26 @@
289289
</q-page-sticky>
290290
</q-card>
291291
</q-dialog>
292+
<!-- Dialog to show progress window -->
293+
<q-dialog
294+
v-model="displayProgressDiag"
295+
transition-show="slide-up"
296+
transition-hide="slide-down"
297+
position="bottom"
298+
full-width
299+
>
300+
<q-card
301+
class="full-width"
302+
ref="progressCard"
303+
>
304+
<q-card-section>
305+
<q-markdown
306+
:src="scriptProgress"
307+
ref="progressCode"
308+
/>
309+
</q-card-section>
310+
</q-card>
311+
</q-dialog>
292312
<!-- Dialog to show results window -->
293313
<q-dialog
294314
v-model="displayResultsDiag"
@@ -605,11 +625,13 @@ export default {
605625
results: {}, // Command result object displayed in Results Dialog
606626
resultsSelected: [[]], // Array of selected objects from Results Dialog
607627
resultsFilter: '', // Filter for results table
628+
scriptProgress: '', // Display current script execution progress
608629
externalHelpFile: '', // Holds Help text loaded from external source
609630
displayCommandDiag: false, // Visibility state for command dialog
610631
displayHelpDiag: false, // Visibility state for help dialog
611632
displayResultsDiag: false, // Visibility state for results dialog
612633
displayPreExecuteCheck: false, // Visibility state for preexecute dialog
634+
displayProgressDiag: false, // Visibility state for progress dialog
613635
paramType: { // Table translating PowerShell variable types to Quasar components names and options
614636
'String': ['q-input', 'text'],
615637
'Number': ['q-input', 'number'],
@@ -645,7 +667,7 @@ export default {
645667
}
646668
},
647669
computed: {
648-
...mapGetters('lazystore', ['getLanguage', 'getSearchScripts', 'getSearchHistory', 'getScriptsArray', 'getDefinitions', 'getCommandMaximized', 'getAlwaysConfirm', 'getHistoryLength', 'getHistoryVisible', 'getHistory', 'getDenseInput', 'getDenseTable', 'getLoginSkipped', 'getCredentialsSaved']),
670+
...mapGetters('lazystore', ['getLanguage', 'getSearchScripts', 'getSearchHistory', 'getScriptsArray', 'getDefinitions', 'getCommandMaximized', 'getAlwaysConfirm', 'getHistoryLength', 'getHistoryVisible', 'getHistory', 'getDenseInput', 'getDenseTable', 'getLoginSkipped', 'getCredentialsSaved', 'getDisplayProgress']),
649671
language: function () {
650672
return this.getLanguage
651673
},
@@ -698,6 +720,9 @@ export default {
698720
denseTable: function () {
699721
return this.getDenseTable
700722
},
723+
displayProgress: function () {
724+
return this.getDisplayProgress
725+
},
701726
loginSkipped: function () {
702727
return this.getLoginSkipped
703728
},
@@ -899,6 +924,8 @@ export default {
899924
this.$q.loading.show({
900925
message: '<h6>' + this.$t('cancelling') + '</h6><p>' + this.$t('pleaseWait') + '</p>'
901926
})
927+
// Stop listening to output, hide progress dialog and reset dialog
928+
this.stopProgress()
902929
// Kill current powershell proccess
903930
childProcess.exec(`taskkill /f /pid ${this.$pwsh.shell.pid}`, (error, stdout, stderr) => {
904931
if (error) {
@@ -1027,12 +1054,9 @@ export default {
10271054
// @"
10281055
// `
10291056
// }
1030-
// console.log('Checking input: ', input)
10311057
if (input) {
1032-
// console.log('input is here!')
10331058
// If parameter has additional text format, insert it
10341059
if (param.format) {
1035-
// console.log('format is here!')
10361060
tempResultCommand = tempResultCommand.replace(`{{${param.parameter}}}`, `${param.format}`)
10371061
}
10381062
// If parameter was supplied, insert param in place of template variable
@@ -1063,6 +1087,27 @@ export default {
10631087
this.resultCommand = this.resultCommand.replace(/(\r\n|\n|\r)/gm, ';')
10641088
}
10651089
},
1090+
async executionProgress (data) {
1091+
// Do not display ending string, which starts with EOI hash or progress delimiter, which is EOIP
1092+
if (!data.startsWith('EOI')) {
1093+
this.scriptProgress += data
1094+
}
1095+
// Try to scroll if output is too long
1096+
setTimeout(() => {
1097+
try {
1098+
this.$refs.progressCard.$el.scrollTo(0, this.$refs.progressCode.$el.clientHeight)
1099+
} catch { }
1100+
}, 100)
1101+
},
1102+
async stopProgress () {
1103+
if (this.displayProgress || this.currentCommand.progress) {
1104+
this.$pwsh.shell.streams.stdout.removeListener('data', this.executionProgress)
1105+
setTimeout(() => {
1106+
this.displayProgressDiag = false
1107+
this.scriptProgress = ''
1108+
}, 1000)
1109+
}
1110+
},
10661111
executeCommand () {
10671112
this.toggleLoading(true)
10681113
this.$pwsh.shell.clear().then(() => {
@@ -1071,8 +1116,24 @@ export default {
10711116
} else {
10721117
this.$pwsh.shell.addCommand(this.resultCommand)
10731118
}
1119+
// Write output to progress window if it is still running after one second to prevent useless progress window flash for fast commands
1120+
if (this.displayProgress || this.currentCommand.progress) {
1121+
this.$pwsh.shell.streams.stdout.on('data', this.executionProgress)
1122+
setTimeout(() => {
1123+
if (this.$pwsh.shell.invocationStateInfo === 'Running') {
1124+
this.displayProgressDiag = true
1125+
}
1126+
}, 1000)
1127+
}
10741128
this.$pwsh.shell.invoke().then(output => {
10751129
// Code block to handle PowerShell return data
1130+
// Stop listening to output, hide progress dialog and reset dialog
1131+
this.stopProgress()
1132+
// If command emits progress end, split progress from results
1133+
if (this.currentCommand.progress || this.currentCommand.progress) {
1134+
let splitOutput = output.split('EOIP', 2)
1135+
output = splitOutput[splitOutput.length - 1]
1136+
}
10761137
let data
10771138
let params
10781139
let dataArray = []
@@ -1123,7 +1184,9 @@ export default {
11231184
this.toggleLoading()
11241185
}).catch(error => {
11251186
// If PowerShell itself runs into problem and throws, catch and display error as raw output.
1126-
console.log(error)
1187+
console.error(error)
1188+
// Stop listening to output, hide progress dialog and reset dialog
1189+
this.stopProgress()
11271190
this.results[this.currentWorkflowIndex] = {
11281191
error: true,
11291192
returnType: 'raw',

src/pages/SettingsPage.vue

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,14 @@
3636
/>
3737
</div>
3838
</div>
39+
<div class="row">
40+
<div class="col-12">
41+
<q-checkbox
42+
v-model="displayProgress"
43+
:label="$t('displayProgress')"
44+
/>
45+
</div>
46+
</div>
3947
</q-card-section>
4048
</q-card>
4149
</div>
@@ -53,7 +61,7 @@ export default {
5361
}
5462
},
5563
computed: {
56-
...mapGetters('lazystore', ['getAlwaysConfirm', 'getDenseInput', 'getDenseTable']),
64+
...mapGetters('lazystore', ['getAlwaysConfirm', 'getDenseInput', 'getDenseTable', 'getDisplayProgress']),
5765
alwaysConfirm: {
5866
get () {
5967
return this.getAlwaysConfirm
@@ -77,6 +85,14 @@ export default {
7785
set (val) {
7886
this.$store.dispatch('lazystore/setDenseTable', val)
7987
}
88+
},
89+
displayProgress: {
90+
get () {
91+
return this.getDisplayProgress
92+
},
93+
set (val) {
94+
this.$store.dispatch('lazystore/setDisplayProgress', val)
95+
}
8096
}
8197
}
8298
}

src/store/lazystore/actions.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,3 +117,8 @@ export async function setLoginSkipped ({ commit }, skipped) {
117117
export async function setCredentialsSaved ({ commit }, saved) {
118118
commit('SET_CREDENTIALSSAVED', saved)
119119
}
120+
121+
// Commit mutation to set whether script progress dialog is shown or not - Accessed in SettingsPage.vue
122+
export async function setDisplayProgress ({ commit }, showProgress) {
123+
commit('SET_DISPLAYPROGRESS', showProgress)
124+
}

src/store/lazystore/getters.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ export function getCredentialsSaved (state) {
7878
return state.credentials_saved
7979
}
8080

81+
export function getDisplayProgress (state) {
82+
return state.display_progress
83+
}
84+
8185
// Dynamically build array of scripts to display in ScriptsPage.vue page
8286
export function getScriptsArray (state) {
8387
try {

0 commit comments

Comments
 (0)