Skip to content

Commit 616a30d

Browse files
authored
Add ability to suggest additional resource types (#2970)
1 parent b061876 commit 616a30d

File tree

7 files changed

+76
-12
lines changed

7 files changed

+76
-12
lines changed

core/src/software/aws/toolkits/core/telemetry/TelemetryPublisher.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@ import software.amazon.awssdk.services.toolkittelemetry.model.Sentiment
88
interface TelemetryPublisher : AutoCloseable {
99
suspend fun publish(metricEvents: Collection<MetricEvent>)
1010

11-
suspend fun sendFeedback(sentiment: Sentiment, comment: String)
11+
suspend fun sendFeedback(sentiment: Sentiment, comment: String, metadata: Map<String, String>)
1212
}

jetbrains-core/src/software/aws/toolkits/jetbrains/services/telemetry/DefaultTelemetryPublisher.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class DefaultTelemetryPublisher(
3838
}
3939
}
4040

41-
override suspend fun sendFeedback(sentiment: Sentiment, comment: String) {
41+
override suspend fun sendFeedback(sentiment: Sentiment, comment: String, metadata: Map<String, String>) {
4242
withContext(getCoroutineBgContext()) {
4343
client.postFeedback {
4444
it.awsProduct(clientMetadata.productName)
@@ -49,6 +49,9 @@ class DefaultTelemetryPublisher(
4949
it.parentProductVersion(clientMetadata.parentProductVersion)
5050
it.sentiment(sentiment)
5151
it.comment(comment)
52+
if (metadata.isNotEmpty()) {
53+
it.metadata(metadata.map { (k, v) -> MetadataEntry.builder().key(k).value(v).build() })
54+
}
5255
}
5356
}
5457
}

jetbrains-core/src/software/aws/toolkits/jetbrains/services/telemetry/TelemetryService.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,8 @@ abstract class TelemetryService(private val publisher: TelemetryPublisher, priva
114114
batcher.enqueue(event)
115115
}
116116

117-
suspend fun sendFeedback(sentiment: Sentiment, comment: String) {
118-
publisher.sendFeedback(sentiment, comment)
117+
suspend fun sendFeedback(sentiment: Sentiment, comment: String, metadata: Map<String, String> = emptyMap()) {
118+
publisher.sendFeedback(sentiment, comment, metadata)
119119
}
120120

121121
companion object {

jetbrains-core/src/software/aws/toolkits/jetbrains/settings/DynamicResourcesConfigurable.kt

Lines changed: 59 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,35 @@
33

44
package software.aws.toolkits.jetbrains.settings
55

6-
import com.intellij.openapi.application.ApplicationManager
7-
import com.intellij.openapi.application.ModalityState
8-
import com.intellij.openapi.application.runInEdt
96
import com.intellij.openapi.options.BoundConfigurable
107
import com.intellij.openapi.project.ProjectManager
8+
import com.intellij.openapi.ui.InputValidator
9+
import com.intellij.openapi.ui.Messages
10+
import com.intellij.openapi.ui.messages.MessagesService
1111
import com.intellij.ui.CheckBoxList
1212
import com.intellij.ui.FilterComponent
1313
import com.intellij.ui.ListSpeedSearch
1414
import com.intellij.ui.layout.panel
15+
import kotlinx.coroutines.launch
16+
import kotlinx.coroutines.withContext
17+
import software.amazon.awssdk.services.toolkittelemetry.model.Sentiment
1518
import software.aws.toolkits.core.utils.replace
19+
import software.aws.toolkits.jetbrains.core.coroutines.applicationCoroutineScope
20+
import software.aws.toolkits.jetbrains.core.coroutines.getCoroutineBgContext
21+
import software.aws.toolkits.jetbrains.core.coroutines.getCoroutineUiContext
1622
import software.aws.toolkits.jetbrains.core.explorer.ExplorerToolWindow
1723
import software.aws.toolkits.jetbrains.services.dynamic.DynamicResourceSupportedTypes
1824
import software.aws.toolkits.jetbrains.services.dynamic.explorer.OtherResourcesNode
25+
import software.aws.toolkits.jetbrains.services.telemetry.TelemetryService
26+
import software.aws.toolkits.jetbrains.ui.feedback.FEEDBACK_SOURCE
27+
import software.aws.toolkits.jetbrains.utils.notifyError
1928
import software.aws.toolkits.resources.message
29+
import software.aws.toolkits.telemetry.FeedbackTelemetry
2030
import javax.swing.ListSelectionModel
2131

2232
class DynamicResourcesConfigurable : BoundConfigurable(message("aws.settings.dynamic_resources_configurable.title")) {
2333

34+
private val coroutineScope = applicationCoroutineScope()
2435
private val checklist = CheckBoxList<String>()
2536
private val allResources = mutableSetOf<String>()
2637
private val selected = mutableSetOf<String>()
@@ -43,14 +54,22 @@ class DynamicResourcesConfigurable : BoundConfigurable(message("aws.settings.dyn
4354

4455
override fun createPanel() = panel {
4556
selected.replace(DynamicResourcesSettings.getInstance().selected)
46-
ApplicationManager.getApplication().executeOnPooledThread {
57+
coroutineScope.launch(getCoroutineBgContext()) {
4758
allResources.addAll(DynamicResourceSupportedTypes.getInstance().getSupportedTypes())
48-
runInEdt(ModalityState.any()) {
59+
withContext(getCoroutineUiContext()) {
4960
updateCheckboxList()
5061
}
5162
}
52-
53-
row { filter(growX) }
63+
row {
64+
cell(isFullWidth = true) {
65+
filter(growX, pushX)
66+
link(message("aws.settings.dynamic_resources_configurable.suggest_types.prompt")) {
67+
showTypeSuggestionBox()?.let { suggestion ->
68+
submitSuggestion(suggestion)
69+
}
70+
}
71+
}
72+
}
5473
row {
5574
scrollPane(checklist)
5675
.constraints(growX, pushX)
@@ -78,6 +97,19 @@ class DynamicResourcesConfigurable : BoundConfigurable(message("aws.settings.dyn
7897
}
7998
}
8099

100+
private fun submitSuggestion(suggestion: String) {
101+
coroutineScope.launch(getCoroutineBgContext()) {
102+
try {
103+
TelemetryService.getInstance().sendFeedback(Sentiment.NEGATIVE, suggestion, mapOf(FEEDBACK_SOURCE to "Resource Type Suggestions")).also {
104+
FeedbackTelemetry.result(project = null, success = true)
105+
}
106+
} catch (e: Exception) {
107+
e.notifyError(message("feedback.submit_failed", e))
108+
FeedbackTelemetry.result(project = null, success = false)
109+
}
110+
}
111+
}
112+
81113
private fun CheckBoxList<*>.toggleAll(state: Boolean) {
82114
(0 until model.size).forEach { idx ->
83115
checkboxStateHandler(idx, state)
@@ -112,4 +144,24 @@ class DynamicResourcesConfigurable : BoundConfigurable(message("aws.settings.dyn
112144
}
113145
}
114146
}
147+
148+
companion object {
149+
private const val INITIAL_INPUT = "AWS::"
150+
private const val MAX_LENGTH = 2000
151+
152+
private fun showTypeSuggestionBox(): String? = MessagesService.getInstance().showMultilineInputDialog(
153+
project = null,
154+
message = message("aws.settings.dynamic_resources_configurable.suggest_types.dialog.message"),
155+
title = message("aws.settings.dynamic_resources_configurable.suggest_types.dialog.title"),
156+
initialValue = INITIAL_INPUT,
157+
icon = Messages.getQuestionIcon(),
158+
object : InputValidator {
159+
override fun checkInput(inputString: String?) = validateSuggestion(inputString)
160+
override fun canClose(inputString: String?) = validateSuggestion(inputString)
161+
}
162+
)?.takeIf { it.isNotBlank() }
163+
164+
private fun validateSuggestion(inputString: String?) =
165+
inputString != null && inputString.isNotBlank() && inputString != INITIAL_INPUT && inputString.length <= MAX_LENGTH
166+
}
115167
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package software.aws.toolkits.jetbrains.ui.feedback
5+
6+
const val FEEDBACK_SOURCE = "source"

jetbrains-core/tst/software/aws/toolkits/jetbrains/services/telemetry/MockTelemetryService.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class NoOpTelemetryService : TelemetryService {
2121
class NoOpPublisher() : TelemetryPublisher {
2222
override suspend fun publish(metricEvents: Collection<MetricEvent>) {}
2323

24-
override suspend fun sendFeedback(sentiment: Sentiment, comment: String) {}
24+
override suspend fun sendFeedback(sentiment: Sentiment, comment: String, metadata: Map<String, String>) {}
2525

2626
override fun close() {}
2727
}

resources/resources/software/aws/toolkits/resources/MessagesBundle.properties

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ aws.settings.aws_cli_settings=AWS CLI Settings
8989
aws.settings.clouddebug.location=cloud-debug CLI executable:
9090
aws.settings.dynamic_resources_configurable.clear_all=Clear All
9191
aws.settings.dynamic_resources_configurable.select_all=Select All
92+
aws.settings.dynamic_resources_configurable.suggest_types.dialog.message=Please suggest additional AWS resource types (e.g. AWS::S3::Bucket)\nyou would like to see supported in future releases.\n\n(max length: 2000 chars)
93+
aws.settings.dynamic_resources_configurable.suggest_types.dialog.title=Additional Resource Type Suggestions
94+
aws.settings.dynamic_resources_configurable.suggest_types.prompt=Don't see a resource type you expected?
9295
aws.settings.dynamic_resources_configurable.title=Resources
9396
aws.settings.executables.auto_resolved=(Auto-resolved: {0})
9497
aws.settings.executables.cannot_determine_version=Cannot determine version of {0}: {1}

0 commit comments

Comments
 (0)