Skip to content

Commit c696176

Browse files
Merge pull request #6642 from microsoft/feature-survey-monkey
Provide customer survey in Intellij toolkit
2 parents c0ca9e9 + ea35e83 commit c696176

File tree

7 files changed

+221
-4
lines changed

7 files changed

+221
-4
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*/
5+
6+
package com.microsoft.azure.toolkit.intellij.common.feedback;
7+
8+
import com.intellij.openapi.actionSystem.AnAction;
9+
import com.intellij.openapi.actionSystem.AnActionEvent;
10+
import com.intellij.openapi.fileEditor.FileEditorManager;
11+
import com.intellij.openapi.project.DumbAware;
12+
import com.intellij.openapi.util.Key;
13+
import com.intellij.openapi.vfs.VirtualFile;
14+
import com.intellij.testFramework.LightVirtualFile;
15+
import com.microsoft.azure.toolkit.ide.common.icon.AzureIcons;
16+
import com.microsoft.azure.toolkit.intellij.common.AzureFileType;
17+
import com.microsoft.azure.toolkit.intellij.common.IntelliJAzureIcons;
18+
import com.microsoft.azure.toolkit.lib.common.task.AzureTaskManager;
19+
20+
import javax.annotation.Nonnull;
21+
import java.util.Objects;
22+
23+
public class ProvideFeedbackAction extends AnAction implements DumbAware {
24+
public static final Key<String> ID = new Key<>("ProvideFeedbackAction");
25+
26+
@Override
27+
public void actionPerformed(@Nonnull AnActionEvent anActionEvent) {
28+
final FileEditorManager fileEditorManager = FileEditorManager.getInstance(Objects.requireNonNull(anActionEvent.getProject()));
29+
if (fileEditorManager == null) {
30+
return;
31+
}
32+
LightVirtualFile itemVirtualFile = searchExistingFile(fileEditorManager);
33+
if (itemVirtualFile == null) {
34+
itemVirtualFile = new LightVirtualFile("Provide Feedback");
35+
itemVirtualFile.putUserData(ID, ProvideFeedbackAction.class.getCanonicalName());
36+
itemVirtualFile.setFileType(new AzureFileType(ProvideFeedbackEditorProvider.TYPE, IntelliJAzureIcons.getIcon(AzureIcons.Common.AZURE)));
37+
}
38+
final LightVirtualFile finalItemVirtualFile = itemVirtualFile;
39+
AzureTaskManager.getInstance().runLater(() -> fileEditorManager.openFile(finalItemVirtualFile, true /*focusEditor*/, true /*searchForOpen*/));
40+
}
41+
42+
private LightVirtualFile searchExistingFile(FileEditorManager fileEditorManager) {
43+
LightVirtualFile virtualFile = null;
44+
for (final VirtualFile editedFile : fileEditorManager.getOpenFiles()) {
45+
final String fileResourceId = editedFile.getUserData(ID);
46+
if (fileResourceId != null && fileResourceId.equals(ProvideFeedbackAction.class.getCanonicalName()) &&
47+
editedFile.getFileType().getName().equals(ProvideFeedbackEditorProvider.TYPE)) {
48+
virtualFile = (LightVirtualFile) editedFile;
49+
break;
50+
}
51+
}
52+
return virtualFile;
53+
}
54+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.microsoft.azure.toolkit.intellij.common.feedback.ProvideFeedbackEditor">
3+
<grid id="27dc6" binding="pnlRoot" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
4+
<margin top="0" left="0" bottom="0" right="0"/>
5+
<constraints>
6+
<xy x="20" y="20" width="524" height="400"/>
7+
</constraints>
8+
<properties/>
9+
<border type="none"/>
10+
<children/>
11+
</grid>
12+
</form>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
/*
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*/
5+
6+
package com.microsoft.azure.toolkit.intellij.common.feedback;
7+
8+
import com.intellij.ide.BrowserUtil;
9+
import com.intellij.openapi.fileEditor.FileEditorManager;
10+
import com.intellij.openapi.project.DumbAware;
11+
import com.intellij.openapi.project.Project;
12+
import com.intellij.openapi.util.Disposer;
13+
import com.intellij.openapi.vfs.VirtualFile;
14+
import com.intellij.ui.jcef.JBCefBrowser;
15+
import com.intellij.ui.jcef.JBCefBrowserBase;
16+
import com.intellij.ui.jcef.JBCefClient;
17+
import com.intellij.ui.jcef.JBCefJSQuery;
18+
import com.intellij.uiDesigner.core.GridConstraints;
19+
import com.microsoft.azure.toolkit.intellij.common.BaseEditor;
20+
import com.microsoft.azure.toolkit.lib.common.task.AzureTaskManager;
21+
import org.cef.browser.CefBrowser;
22+
import org.cef.browser.CefFrame;
23+
import org.cef.handler.CefLoadHandlerAdapter;
24+
import org.cef.handler.CefRequestHandlerAdapter;
25+
import org.cef.network.CefRequest;
26+
import org.jetbrains.annotations.Nls;
27+
28+
import javax.annotation.Nonnull;
29+
import javax.swing.*;
30+
31+
public class ProvideFeedbackEditor extends BaseEditor implements DumbAware {
32+
private final JBCefJSQuery myJSQueryOpenInBrowser;
33+
private final JBCefBrowser jbCefBrowser;
34+
private JPanel pnlRoot;
35+
36+
public ProvideFeedbackEditor(final Project project, VirtualFile virtualFile) {
37+
super(virtualFile);
38+
this.jbCefBrowser = new JBCefBrowser("https://www.surveymonkey.com/r/PNB5NBL?mode=simple");
39+
final CefBrowser browser = jbCefBrowser.getCefBrowser();
40+
final JBCefClient client = jbCefBrowser.getJBCefClient();
41+
pnlRoot.add(jbCefBrowser.getComponent(), new GridConstraints(0, 0, 1, 1, 0, GridConstraints.FILL_BOTH, 3, 3, null, null, null, 0));
42+
// Create a JS query instance
43+
this.myJSQueryOpenInBrowser = JBCefJSQuery.create((JBCefBrowserBase) jbCefBrowser);
44+
myJSQueryOpenInBrowser.addHandler((e) -> {
45+
AzureTaskManager.getInstance().runLater(() -> {
46+
final FileEditorManager fileEditorManager = FileEditorManager.getInstance(project);
47+
fileEditorManager.closeFile(virtualFile);
48+
});
49+
return new JBCefJSQuery.Response("ok!");
50+
});
51+
client.addRequestHandler(openLinkWithLocalBrowser(), browser);
52+
client.addLoadHandler(modifySubmitButtonInSurveyCollectionPage(), browser);
53+
}
54+
55+
@Nonnull
56+
private CefLoadHandlerAdapter modifySubmitButtonInSurveyCollectionPage() {
57+
return new CefLoadHandlerAdapter() {
58+
@Override
59+
public void onLoadEnd(CefBrowser browser, CefFrame frame, int httpStatusCode) {
60+
if (!browser.getURL().contains("www.surveymonkey.com/r/PNB5NBL")) {
61+
return;
62+
}
63+
final String js = "window.JavaPanelBridge = {\n" +
64+
" closeTab: function (e) {\n" +
65+
" " + myJSQueryOpenInBrowser.inject("e") +
66+
" }\n" +
67+
"};\n" +
68+
"var azToolkitCloseBtn = document.querySelector('.thank-you-page-container.survey-submit-actions a.survey-page-button.btn');\n" +
69+
"if (azToolkitCloseBtn) {\n" +
70+
" azToolkitCloseBtn.innerHTML='Close';" +
71+
" azToolkitCloseBtn.addEventListener('click', () => {\n" +
72+
" window.JavaPanelBridge.closeTab();\n" +
73+
" });\n" +
74+
"}";
75+
browser.executeJavaScript(js, browser.getURL(), 0);
76+
}
77+
};
78+
}
79+
80+
@Nonnull
81+
private CefRequestHandlerAdapter openLinkWithLocalBrowser() {
82+
return new CefRequestHandlerAdapter() {
83+
@Override
84+
public boolean onBeforeBrowse(CefBrowser browser, CefFrame frame, CefRequest request, boolean user_gesture, boolean is_redirect) {
85+
if (request.getURL().contains("survey-thanks")) {
86+
return true;
87+
} else if (!request.getURL().contains("www.surveymonkey.com/r/PNB5NBL")) {
88+
BrowserUtil.browse(request.getURL());
89+
return true;
90+
}
91+
return false;
92+
}
93+
};
94+
}
95+
96+
@Override
97+
public JComponent getComponent() {
98+
return pnlRoot;
99+
}
100+
101+
@Override
102+
@Nonnull
103+
@Nls(capitalization = Nls.Capitalization.Title)
104+
public String getName() {
105+
return "Provide Feedback";
106+
}
107+
108+
@Override
109+
public void dispose() {
110+
Disposer.dispose(myJSQueryOpenInBrowser);
111+
Disposer.dispose(jbCefBrowser);
112+
}
113+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.microsoft.azure.toolkit.intellij.common.feedback;
2+
3+
import com.intellij.openapi.fileEditor.FileEditor;
4+
import com.intellij.openapi.fileEditor.FileEditorPolicy;
5+
import com.intellij.openapi.fileEditor.FileEditorProvider;
6+
import com.intellij.openapi.project.DumbAware;
7+
import com.intellij.openapi.project.Project;
8+
import com.intellij.openapi.vfs.VirtualFile;
9+
10+
import javax.annotation.Nonnull;
11+
12+
public class ProvideFeedbackEditorProvider implements FileEditorProvider, DumbAware {
13+
public static final String TYPE = "Microsoft.Customer_Survey";
14+
15+
@Override
16+
public boolean accept(@Nonnull Project project, @Nonnull VirtualFile virtualFile) {
17+
return virtualFile.getFileType().getName().equals(getEditorTypeId());
18+
}
19+
20+
@Nonnull
21+
@Override
22+
public FileEditor createEditor(@Nonnull Project project, @Nonnull VirtualFile virtualFile) {
23+
return new ProvideFeedbackEditor(project, virtualFile);
24+
}
25+
26+
@Nonnull
27+
@Override
28+
public String getEditorTypeId() {
29+
return TYPE;
30+
}
31+
32+
@Nonnull
33+
@Override
34+
public FileEditorPolicy getPolicy() {
35+
return FileEditorPolicy.HIDE_DEFAULT_EDITOR;
36+
}
37+
}

PluginsAndFeatures/azure-toolkit-for-intellij/azure-intellij-plugin-lib/src/main/resources/META-INF/azure-intellij-plugin-lib.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
id="Azure Streaming Log" canCloseContents="true"/>
1616
<webHelpProvider implementation="com.microsoft.azure.toolkit.intellij.common.help.AzureWebHelpProvider"/>
1717
<applicationService serviceImplementation="com.microsoft.azure.toolkit.intellij.common.settings.IntellijStore"/>
18+
<fileEditorProvider implementation="com.microsoft.azure.toolkit.intellij.common.feedback.ProvideFeedbackEditorProvider" />
1819
</extensions>
1920
<actions>
2021
<action id="Actions.WhatsNew"
@@ -25,5 +26,7 @@
2526
text="Never Show Again"
2627
description="Never show again">
2728
</action>
29+
<action id="Actions.ProvideFeedback" class="com.microsoft.azure.toolkit.intellij.common.feedback.ProvideFeedbackAction"
30+
text="Provide Feedback" icon="/icons/Common/feedback.svg"/>
2831
</actions>
2932
</idea-plugin>

PluginsAndFeatures/azure-toolkit-for-intellij/src/main/java/com/microsoft/intellij/ui/ServerExplorerToolWindowFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,7 @@ public void paintComponent(Graphics g) {
440440

441441
private void addToolbarItems(ToolWindow toolWindow, final Project project, final AzureModule azureModule) {
442442
final AnAction refreshAction = new RefreshAllAction(azureModule);
443-
final AnAction feedbackAction = ActionManager.getInstance().getAction("AzureToolkit.Survey");
443+
final AnAction feedbackAction = ActionManager.getInstance().getAction("Actions.ProvideFeedback");
444444
final AnAction signInAction = ActionManager.getInstance().getAction("AzureToolkit.AzureSignIn");
445445
final AnAction selectSubscriptionsAction = ActionManager.getInstance().getAction("AzureToolkit.SelectSubscriptions");
446446
toolWindow.setTitleActions(Arrays.asList(refreshAction, selectSubscriptionsAction, signInAction, Separator.create(), feedbackAction));

PluginsAndFeatures/azure-toolkit-for-intellij/src/main/resources/META-INF/plugin.xml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -195,8 +195,6 @@
195195
</group>
196196
<action class="com.microsoft.intellij.actions.NewCustomerIssueFeedbackAction" id="AzureToolkit.GithubIssue" text="Report Issues" />
197197
<action class="com.microsoft.intellij.actions.NewFeatureRequestFeedbackAction" id="AzureToolkit.FeatureRequest" text="Request Feature" />
198-
<action class="com.microsoft.intellij.actions.QualtricsSurveyAction" id="AzureToolkit.Survey" text="Provide Feedback"
199-
icon="/icons/Common/feedback.svg"/>
200198
<action id="Actions.SparkJobDisconnect" class="com.microsoft.azure.hdinsight.spark.run.action.SparkBatchJobDisconnectAction"
201199
text="Disconnect" description="Disconnect the log view from remote Spark Job"
202200
icon="/icons/SparkJobDisconnect.png">
@@ -271,7 +269,7 @@
271269
<separator/>
272270
<reference ref="AzureToolkit.GithubIssue"/>
273271
<reference ref="AzureToolkit.FeatureRequest"/>
274-
<reference ref="AzureToolkit.Survey"/>
272+
<reference ref="Actions.ProvideFeedback"/>
275273
<reference ref="Actions.WhatsNew"/>
276274
</group>
277275

0 commit comments

Comments
 (0)