Skip to content

Commit d440c01

Browse files
Merge pull request #892 from redhat-developer/show-openShift-toolkit-recommendation
OpenShift Toolkit extension recommendation
2 parents 1b45356 + d3eac0a commit d440c01

7 files changed

Lines changed: 155 additions & 0 deletions

File tree

package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,11 @@
218218
"type": "boolean",
219219
"default": false,
220220
"description": "Enforces alphabetical ordering of keys in mappings when set to true"
221+
},
222+
"yaml.recommendations.show": {
223+
"type": "boolean",
224+
"default": "true",
225+
"description": "Suggest additional extensions based on YAML usage."
221226
}
222227
}
223228
},

src/extension.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { getConflictingExtensions, showUninstallConflictsNotification } from './
2121
import { TelemetryErrorHandler, TelemetryOutputChannel } from './telemetry';
2222
import { TextDecoder } from 'util';
2323
import { createJSONSchemaStatusBarItem } from './schema-status-bar-item';
24+
import { initializeRecommendation } from './recommendation';
2425

2526
export interface ISchemaAssociations {
2627
[pattern: string]: string[];
@@ -206,6 +207,8 @@ export function startClient(
206207
client.onNotification(SchemaSelectionRequests.schemaStoreInitialized, () => {
207208
createJSONSchemaStatusBarItem(context, client);
208209
});
210+
211+
initializeRecommendation(context);
209212
})
210213
.catch((err) => {
211214
sendStartupTelemetryEvent(runtime.telemetry, false, err);

src/recommendation/handler.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Red Hat, Inc. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
'use strict';
7+
8+
export interface IHandler {
9+
handle(extName: string, message: string): Promise<void>;
10+
11+
canRecommendExtension(extName: string): boolean;
12+
}

src/recommendation/handlerImpl.ts

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Red Hat, Inc. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
'use strict';
7+
8+
import * as vscode from 'vscode';
9+
import { IHandler } from './handler';
10+
11+
const KEY_RECOMMENDATION_USER_CHOICE_MAP = 'recommendationUserChoice';
12+
13+
async function installExtensionCmdHandler(extensionName: string, displayName: string): Promise<unknown> {
14+
return vscode.window
15+
.withProgress(
16+
{ location: vscode.ProgressLocation.Notification, title: `Installing ${displayName || extensionName}...` },
17+
() => {
18+
return vscode.commands.executeCommand('workbench.extensions.installExtension', extensionName);
19+
}
20+
)
21+
.then(() => {
22+
vscode.window.showInformationMessage(`Successfully installed ${displayName || extensionName}.`);
23+
});
24+
}
25+
26+
enum UserChoice {
27+
install = 'Install',
28+
never = 'Never',
29+
later = 'Later',
30+
}
31+
32+
export class HandlerImpl implements IHandler {
33+
userChoice: () => unknown;
34+
storeUserChoice: (choice: unknown) => void;
35+
constructor(context: vscode.ExtensionContext) {
36+
this.userChoice = () => {
37+
return context.globalState.get(KEY_RECOMMENDATION_USER_CHOICE_MAP, {});
38+
};
39+
40+
this.storeUserChoice = (choice: unknown) => {
41+
context.globalState.update(KEY_RECOMMENDATION_USER_CHOICE_MAP, choice);
42+
};
43+
}
44+
45+
isExtensionInstalled(extName: string): boolean {
46+
return !!vscode.extensions.getExtension(extName);
47+
}
48+
49+
canRecommendExtension(extName: string): boolean {
50+
return this.userChoice()[extName] !== UserChoice.never && !this.isExtensionInstalled(extName);
51+
}
52+
53+
async handle(extName: string, message: string): Promise<void> {
54+
if (this.isExtensionInstalled(extName)) {
55+
return;
56+
}
57+
58+
const choice = this.userChoice();
59+
if (choice[extName] === UserChoice.never) {
60+
return;
61+
}
62+
63+
const actions: Array<string> = Object.values(UserChoice);
64+
const answer = await vscode.window.showInformationMessage(message, ...actions);
65+
if (answer === UserChoice.install) {
66+
await installExtensionCmdHandler(extName, extName);
67+
}
68+
69+
choice[extName] = answer;
70+
this.storeUserChoice(choice);
71+
}
72+
}

src/recommendation/index.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Red Hat, Inc. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
'use strict';
7+
8+
import * as vscode from 'vscode';
9+
import { HandlerImpl } from './handlerImpl';
10+
import { initializeRecommendation as initOpenShiftToolkit } from './openShiftToolkit';
11+
12+
export function initializeRecommendation(context: vscode.ExtensionContext): void {
13+
const handler = new HandlerImpl(context);
14+
initOpenShiftToolkit(context, handler);
15+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Red Hat, Inc. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
'use strict';
7+
8+
import * as fs from 'fs';
9+
import * as path from 'path';
10+
import * as vscode from 'vscode';
11+
import { IHandler } from './handler';
12+
13+
const EXTENSION_NAME = 'redhat.vscode-openshift-connector';
14+
const GH_ORG_URL = `https://github.com/redhat-developer/vscode-openshift-tools`;
15+
const RECOMMENDATION_MESSAGE = `The workspace has a devfile.yaml. Install [OpenShift Toolkit](${GH_ORG_URL}) extension for assistance with deploying to a cluster?`;
16+
const YAML_RECOMMENDATIONS_SHOW = 'yaml.recommendations.show';
17+
18+
function isDevfileYAML(uri: vscode.Uri): boolean {
19+
if (fs.lstatSync(uri.fsPath).isDirectory()) {
20+
const devFileYamlPath = path.join(uri.fsPath, 'devfile.yaml');
21+
return fs.existsSync(devFileYamlPath);
22+
}
23+
return !!uri.path && path.basename(uri.path).toLowerCase() === 'devfile.yaml';
24+
}
25+
26+
export function initializeRecommendation(context: vscode.ExtensionContext, handler: IHandler): void {
27+
const show = vscode.workspace.getConfiguration().get(YAML_RECOMMENDATIONS_SHOW);
28+
if (!show) {
29+
return;
30+
}
31+
if (!handler.canRecommendExtension(EXTENSION_NAME)) {
32+
return;
33+
}
34+
context.subscriptions.push(
35+
vscode.workspace.onDidOpenTextDocument((e) => {
36+
if (isDevfileYAML(e.uri)) {
37+
handler.handle(EXTENSION_NAME, RECOMMENDATION_MESSAGE);
38+
}
39+
})
40+
);
41+
42+
const isdevfileYAMLOpened = vscode.workspace.workspaceFolders.findIndex((workspace) => isDevfileYAML(workspace.uri)) !== -1;
43+
if (isdevfileYAMLOpened) {
44+
handler.handle(EXTENSION_NAME, RECOMMENDATION_MESSAGE);
45+
}
46+
}

webpack.config.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ const clientWeb = {
7676
fallback: {
7777
path: require.resolve('path-browserify'),
7878
util: require.resolve('util'),
79+
fs: false,
7980
},
8081
},
8182
module: {
@@ -138,6 +139,7 @@ const serverWeb = {
138139
path: require.resolve('path-browserify/'),
139140
url: require.resolve('url/'),
140141
buffer: require.resolve('buffer/'),
142+
fs: false,
141143
},
142144
},
143145
plugins: [

0 commit comments

Comments
 (0)