Skip to content

Commit 86b191b

Browse files
author
James Pogran
authored
Merge pull request #488 from glennsarti/add-progress-bar
(GH-494) Add Progress Bar for long lived operations
2 parents e1c97fe + 053a0cd commit 86b191b

File tree

7 files changed

+159
-55
lines changed

7 files changed

+159
-55
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,8 @@ The information returned will be pasted into the open editor window where your c
197197

198198
![puppet_resource](https://raw.githubusercontent.com/lingua-pupuli/puppet-vscode/master/docs/assets/puppet_resource.gif)
199199

200+
You can change the notification message from the default message box, to a status bar notification or none at all, using the `puppet.notification.puppetResource` configuration setting.
201+
200202
#### Puppet Node Graph preview
201203

202204
You can preview the [node graph](https://puppet.com/blog/visualize-your-infrastructure-models) of a manifest while you edit your Puppet Code.
@@ -209,6 +211,8 @@ The node graph will appear next to the manifest
209211

210212
![puppet_node_graph](https://raw.githubusercontent.com/lingua-pupuli/puppet-vscode/master/docs/assets/puppet_node_graph.gif)
211213

214+
You can change the notification message from the default message box, to a status bar notification or none at all, using the `puppet.notification.nodeGraph` configuration setting.
215+
212216
### Puppet Development Kit Support
213217

214218
You can use the [Puppet Development Kit](https://puppet.com/blog/develop-modules-faster-new-puppet-development-kit) inside VS Code from the command palette. To use any of the above commands, open the command palette and start typing a command. You can also use the right-click context menu or the editor menu to reach these commands.

docs/assets/puppet_node_graph.gif

-1.34 MB
Loading

docs/assets/puppet_resource.gif

-47.7 KB
Loading

package.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,26 @@
403403
"agent"
404404
]
405405
},
406+
"puppet.notification.nodeGraph": {
407+
"type": "string",
408+
"default": "messagebox",
409+
"description": "The type of notification used when a node graph is being generated. Default value of messagebox",
410+
"enum": [
411+
"messagebox",
412+
"statusbar",
413+
"none"
414+
]
415+
},
416+
"puppet.notification.puppetResource": {
417+
"type": "string",
418+
"default": "messagebox",
419+
"description": "The type of notification used when a running Puppet Resouce. Default value of messagebox",
420+
"enum": [
421+
"messagebox",
422+
"statusbar",
423+
"none"
424+
]
425+
},
406426
"puppet.editorService.modulePath": {
407427
"description": "**DEPRECATED** Please use puppet.editorService.puppet.modulePath instead"
408428
},

src/feature/NodeGraphFeature.ts

Lines changed: 65 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@ import * as path from 'path';
66
import { IFeature } from "../feature";
77
import { ILogger } from "../logging";
88
import { ConnectionStatus } from '../interfaces';
9-
import { CompileNodeGraphRequest } from '../messages';
9+
import { CompileNodeGraphRequest, CompileNodeGraphResponse } from '../messages';
1010
import { reporter } from '../telemetry/telemetry';
1111
import * as viz from 'viz.js';
1212
import { ConnectionHandler } from "../handler";
13+
import { ISettings, SettingsFromWorkspace } from '../settings';
1314

1415
const PuppetNodeGraphToTheSideCommandId: string = 'extension.puppetShowNodeGraphToSide';
1516

@@ -47,6 +48,7 @@ class NodeGraphWebViewProvider implements vscode.Disposable {
4748
this.parentFeature.onProviderWebPanelDisposed(this);
4849
});
4950

51+
this.webPanel.webview.html = "Generating...";
5052
this.updateAsync();
5153
}
5254

@@ -67,40 +69,74 @@ class NodeGraphWebViewProvider implements vscode.Disposable {
6769
const requestData = {
6870
external: this.docUri.toString()
6971
};
70-
return this.connectionHandler.languageClient
72+
73+
// Calculate where the progress message should go, if at all.
74+
const currentSettings:ISettings = SettingsFromWorkspace();
75+
var notificationType = vscode.ProgressLocation.Notification;
76+
if (currentSettings.notification !== undefined && currentSettings.notification.nodeGraph !== undefined) {
77+
switch (currentSettings.notification.nodeGraph.toLowerCase()) {
78+
case "messagebox": notificationType = vscode.ProgressLocation.Notification; break;
79+
case "statusbar": notificationType = vscode.ProgressLocation.Window; break;
80+
case "none": notificationType = undefined; break;
81+
default: break; // Default is already set
82+
}
83+
}
84+
85+
if (notificationType !== undefined) {
86+
return vscode.window.withProgress({
87+
location: notificationType,
88+
title: "Puppet",
89+
cancellable: false
90+
}, (progress) => {
91+
progress.report({message: "Generating Node Graph"});
92+
return this.connectionHandler.languageClient
93+
.sendRequest(CompileNodeGraphRequest.type, requestData)
94+
.then(
95+
(compileResult) => {
96+
return this.responseToHTMLString(compileResult);
97+
});
98+
});
99+
}
100+
else {
101+
return this.connectionHandler.languageClient
71102
.sendRequest(CompileNodeGraphRequest.type, requestData)
72103
.then(
73104
(compileResult) => {
105+
return this.responseToHTMLString(compileResult);
106+
});
107+
}
108+
}
74109

75-
var svgContent = '';
76-
if (compileResult.dotContent !== null) {
77-
var styling = `
78-
bgcolor = "transparent"
79-
color = "white"
80-
rankdir = "TB"
81-
node [ shape="box" penwidth="2" color="#e0e0e0" style="rounded,filled" fontname="Courier New" fillcolor=black, fontcolor="white"]
82-
edge [ style="bold" color="#f0f0f0" penwith="2" ]
83-
84-
label = ""`;
85-
86-
var graphContent = compileResult.dotContent;
87-
if (graphContent === undefined) { graphContent = ''; }
88-
// vis.jz sees backslashes as escape characters, however they are not in the DOT language. Instead
89-
// we should escape any backslash coming from a valid DOT file in preparation to be rendered
90-
graphContent = graphContent.replace(/\\/g,"\\\\");
91-
graphContent = graphContent.replace(`label = "editorservices"`,styling);
92-
93-
svgContent = viz(graphContent,"svg");
94-
}
110+
private responseToHTMLString(compileResult: CompileNodeGraphResponse): string {
111+
var svgContent = '';
112+
if (compileResult.dotContent !== null) {
113+
var styling = `
114+
bgcolor = "transparent"
115+
color = "white"
116+
rankdir = "TB"
117+
node [ shape="box" penwidth="2" color="#e0e0e0" style="rounded,filled" fontname="Courier New" fillcolor=black, fontcolor="white"]
118+
edge [ style="bold" color="#f0f0f0" penwith="2" ]
119+
120+
label = ""`;
121+
122+
var graphContent = compileResult.dotContent;
123+
if (graphContent === undefined) { graphContent = ''; }
124+
// vis.jz sees backslashes as escape characters, however they are not in the DOT language. Instead
125+
// we should escape any backslash coming from a valid DOT file in preparation to be rendered
126+
graphContent = graphContent.replace(/\\/g,"\\\\");
127+
graphContent = graphContent.replace(`label = "editorservices"`,styling);
128+
129+
svgContent = viz(graphContent,"svg");
130+
}
95131

96-
var errorContent = `<div style='font-size: 1.5em'>${compileResult.error}</div>`;
97-
if ((compileResult.error === undefined) || (compileResult.error === null)) { errorContent = ''; }
132+
var errorContent = `<div style='font-size: 1.5em'>${compileResult.error}</div>`;
133+
if ((compileResult.error === undefined) || (compileResult.error === null)) { errorContent = ''; }
98134

99-
if (reporter) {
100-
reporter.sendTelemetryEvent(PuppetNodeGraphToTheSideCommandId);
101-
}
135+
if (reporter) {
136+
reporter.sendTelemetryEvent(PuppetNodeGraphToTheSideCommandId);
137+
}
102138

103-
const html: string = `<!DOCTYPE html>
139+
const html: string = `<!DOCTYPE html>
104140
<html lang="en">
105141
<head>
106142
<meta charset="UTF-8">
@@ -130,8 +166,7 @@ ${svgContent}
130166
</div>
131167
</body></html>`;
132168

133-
return html;
134-
});
169+
return html;
135170
}
136171

137172
public dispose(): any {

src/feature/PuppetResourceFeature.ts

Lines changed: 59 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
import * as vscode from 'vscode';
44
import { IFeature } from '../feature';
55
import { ILogger } from '../logging';
6-
import { PuppetCommandStrings, PuppetResourceRequestParams, PuppetResourceRequest } from '../messages';
6+
import { PuppetCommandStrings, PuppetResourceRequestParams, PuppetResourceRequest, PuppetResourceResponse } from '../messages';
77
import { reporter } from '../telemetry/telemetry';
88
import { ConnectionStatus } from '../interfaces';
99
import { ConnectionHandler } from '../handler';
10+
import { ISettings, SettingsFromWorkspace } from '../settings';
1011

1112
export class PuppetResourceFeature implements IFeature {
1213
private _connectionHandler: ConnectionHandler;
@@ -42,36 +43,69 @@ export class PuppetResourceFeature implements IFeature {
4243
let requestParams = new RequestParams();
4344
requestParams.typename = moduleName;
4445

45-
thisCommand._connectionHandler.languageClient
46-
.sendRequest(PuppetResourceRequest.type, requestParams)
47-
.then(resourceResult => {
48-
if (resourceResult.error !== undefined && resourceResult.error.length > 0) {
49-
this.logger.error(resourceResult.error);
50-
return;
51-
}
52-
if (resourceResult.data === undefined || resourceResult.data.length === 0) {
53-
return;
54-
}
55-
56-
if (!editor) {
57-
return;
58-
}
59-
60-
var newPosition = new vscode.Position(0, 0);
61-
if (editor.selection.isEmpty) {
62-
const position = editor.selection.active;
63-
newPosition = position.with(position.line, 0);
64-
}
46+
// Calculate where the progress message should go, if at all.
47+
const currentSettings:ISettings = SettingsFromWorkspace();
48+
var notificationType = vscode.ProgressLocation.Notification;
49+
if (currentSettings.notification !== undefined && currentSettings.notification.puppetResource !== undefined) {
50+
switch (currentSettings.notification.puppetResource.toLowerCase()) {
51+
case "messagebox": notificationType = vscode.ProgressLocation.Notification; break;
52+
case "statusbar": notificationType = vscode.ProgressLocation.Window; break;
53+
case "none": notificationType = undefined; break;
54+
default: break; // Default is already set
55+
}
56+
}
6557

66-
this.editCurrentDocument(doc.uri, resourceResult.data, newPosition);
67-
if (reporter) {
68-
reporter.sendTelemetryEvent(PuppetCommandStrings.PuppetResourceCommandId);
69-
}
58+
if (notificationType !== undefined) {
59+
vscode.window.withProgress({
60+
location: notificationType,
61+
title: "Puppet",
62+
cancellable: false
63+
}, (progress) => {
64+
progress.report({message: `Gathering Puppet ${moduleName} Resources`});
65+
return thisCommand._connectionHandler.languageClient
66+
.sendRequest(PuppetResourceRequest.type, requestParams)
67+
.then(resourceResult => {
68+
this.respsonseToVSCodeEdit(resourceResult, editor, doc);
69+
}
70+
);
7071
});
72+
} else {
73+
thisCommand._connectionHandler.languageClient
74+
.sendRequest(PuppetResourceRequest.type, requestParams)
75+
.then(resourceResult => {
76+
this.respsonseToVSCodeEdit(resourceResult, editor, doc);
77+
}
78+
);
79+
}
7180
}
7281
});
7382
}
7483

84+
private respsonseToVSCodeEdit(resourceResult: PuppetResourceResponse, editor: vscode.TextEditor, doc: vscode.TextDocument) {
85+
if (resourceResult.error !== undefined && resourceResult.error.length > 0) {
86+
this.logger.error(resourceResult.error);
87+
return;
88+
}
89+
if (resourceResult.data === undefined || resourceResult.data.length === 0) {
90+
return;
91+
}
92+
93+
if (!editor) {
94+
return;
95+
}
96+
97+
var newPosition = new vscode.Position(0, 0);
98+
if (editor.selection.isEmpty) {
99+
const position = editor.selection.active;
100+
newPosition = position.with(position.line, 0);
101+
}
102+
103+
this.editCurrentDocument(doc.uri, resourceResult.data, newPosition);
104+
if (reporter) {
105+
reporter.sendTelemetryEvent(PuppetCommandStrings.PuppetResourceCommandId);
106+
}
107+
}
108+
75109
private pickPuppetResource(): Thenable<string | undefined> {
76110
let options: vscode.QuickPickOptions = {
77111
placeHolder: 'Enter a Puppet resource to interrogate',

src/settings.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,18 @@ export interface IPDKSettings {
6262
// Future Use
6363
}
6464

65+
export interface INotificationSettings {
66+
nodeGraph?: string;
67+
puppetResource?: string;
68+
}
69+
6570
export interface ISettings {
6671
editorService?: IEditorServiceSettings;
6772
format?: IFormatSettings;
6873
installDirectory?: string;
6974
installType?: PuppetInstallType;
7075
lint?: ILintSettings;
76+
notification?: INotificationSettings;
7177
pdk?: IPDKSettings;
7278
}
7379

@@ -161,6 +167,10 @@ export function DefaultWorkspaceSettings(): ISettings {
161167
lint: {
162168
enable: true,
163169
},
170+
notification: {
171+
nodeGraph: "messagebox",
172+
puppetResource: "messagebox"
173+
},
164174
pdk: {
165175
}
166176
};
@@ -177,6 +187,7 @@ export function SettingsFromWorkspace(): ISettings {
177187
installDirectory: workspaceConfig.get<string>("installDirectory", defaults.installDirectory),
178188
installType: workspaceConfig.get<PuppetInstallType>("installType", defaults.installType),
179189
lint: workspaceConfig.get<ILintSettings>("lint", defaults.lint),
190+
notification: workspaceConfig.get<INotificationSettings>("notification", defaults.notification),
180191
pdk: workspaceConfig.get<IPDKSettings>("pdk", defaults.pdk)
181192
};
182193

0 commit comments

Comments
 (0)