Skip to content

Commit f0aca38

Browse files
committed
feedback 1
1 parent 885f3f0 commit f0aca38

File tree

10 files changed

+153
-99
lines changed

10 files changed

+153
-99
lines changed

plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/toolwindow/AmazonQToolWindowFactory.kt

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@
33

44
package software.aws.toolkits.jetbrains.services.amazonq.toolwindow
55

6+
import com.intellij.icons.AllIcons
67
import com.intellij.openapi.actionSystem.ActionManager
78
import com.intellij.openapi.application.runInEdt
89
import com.intellij.openapi.project.DumbAware
910
import com.intellij.openapi.project.Project
1011
import com.intellij.openapi.wm.ToolWindow
1112
import com.intellij.openapi.wm.ToolWindowFactory
1213
import com.intellij.openapi.wm.ex.ToolWindowEx
14+
import com.intellij.ui.EditorNotificationPanel
1315
import com.intellij.ui.components.panels.Wrapper
1416
import com.intellij.util.ui.components.BorderLayoutPanel
1517
import software.aws.toolkits.core.utils.debug
@@ -22,17 +24,17 @@ import software.aws.toolkits.jetbrains.core.credentials.pinning.QConnection
2224
import software.aws.toolkits.jetbrains.core.credentials.sono.Q_SCOPES
2325
import software.aws.toolkits.jetbrains.core.credentials.sso.bearer.BearerTokenAuthState
2426
import software.aws.toolkits.jetbrains.core.credentials.sso.bearer.BearerTokenProviderListener
25-
import software.aws.toolkits.jetbrains.core.notifications.NotificationFollowupActions
27+
import software.aws.toolkits.jetbrains.core.notifications.NotificationActionList
28+
import software.aws.toolkits.jetbrains.core.notifications.NotificationManager
2629
import software.aws.toolkits.jetbrains.core.notifications.ShowCriticalNotificationBannerListener
27-
import software.aws.toolkits.jetbrains.core.notifications.getBannerActionList
2830
import software.aws.toolkits.jetbrains.core.webview.BrowserState
2931
import software.aws.toolkits.jetbrains.services.amazonq.QWebviewPanel
3032
import software.aws.toolkits.jetbrains.services.amazonq.RefreshQChatPanelButtonPressedListener
3133
import software.aws.toolkits.jetbrains.services.amazonq.gettingstarted.openMeetQPage
3234
import software.aws.toolkits.jetbrains.utils.isQConnected
3335
import software.aws.toolkits.jetbrains.utils.isQExpired
3436
import software.aws.toolkits.jetbrains.utils.isQWebviewsAvailable
35-
import software.aws.toolkits.jetbrains.utils.notifyInfo
37+
import software.aws.toolkits.resources.AwsCoreBundle
3638
import software.aws.toolkits.resources.message
3739
import software.aws.toolkits.telemetry.FeatureId
3840
import java.awt.event.ComponentAdapter
@@ -76,8 +78,8 @@ class AmazonQToolWindowFactory : ToolWindowFactory, DumbAware {
7678
project.messageBus.connect().subscribe(
7779
ShowCriticalNotificationBannerListener.TOPIC,
7880
object : ShowCriticalNotificationBannerListener {
79-
override fun onReceiveEmergencyNotification(title: String, message: String, actions: List<NotificationFollowupActions>?) {
80-
notificationPanel.updateNotificationPanel(title, message, actions)
81+
override fun onReceiveEmergencyNotification(title: String, message: String, notificationActionList: List<NotificationActionList>) {
82+
notificationPanel.updateNotificationPanel(title, message, notificationActionList)
8183
}
8284
}
8385
)
@@ -87,14 +89,8 @@ class AmazonQToolWindowFactory : ToolWindowFactory, DumbAware {
8789
object : BearerTokenProviderListener {
8890
override fun onChange(providerId: String, newScopes: List<String>?) {
8991
if (ToolkitConnectionManager.getInstance(project).connectionStateForFeature(QConnection.getInstance()) == BearerTokenAuthState.AUTHORIZED) {
90-
// change this
9192
val qComponent = AmazonQToolWindow.getInstance(project).component
9293

93-
val content = contentManager.factory.createContent(qComponent, null, false).also {
94-
it.isCloseable = true
95-
it.isPinnable = true
96-
}
97-
9894
runInEdt {
9995
qPanel.updateQPanel(qComponent)
10096
}
@@ -191,14 +187,16 @@ class NotificationPanel : BorderLayoutPanel() {
191187
wrapper.removeAll()
192188
}
193189

194-
fun updateNotificationPanel(title: String, message: String, actions: List<NotificationFollowupActions>?) {
195-
val editorNotificationPanel = getBannerActionList(actions, title, message)
196-
197-
editorNotificationPanel.createActionLabel("Dismiss") {
190+
fun updateNotificationPanel(title: String, message: String, notificationActionList: List<NotificationActionList>) {
191+
val panel = EditorNotificationPanel()
192+
panel.text = title
193+
panel.icon(AllIcons.General.Error)
194+
val panelWithActions = NotificationManager.buildBannerPanel(panel, notificationActionList)
195+
panelWithActions.createActionLabel(AwsCoreBundle.message("general.dismiss")) {
198196
removeNotificationPanel()
199197
}
200198

201-
wrapper.setContent(editorNotificationPanel)
199+
wrapper.setContent(panelWithActions)
202200
}
203201
}
204202

@@ -213,7 +211,7 @@ class QPanel : BorderLayoutPanel() {
213211
try {
214212
wrapper.setContent(content)
215213
} catch (e: Exception) {
216-
notifyInfo("Error while creating window")
214+
getLogger<QPanel>().error("Error while creating window")
217215
}
218216
}
219217
}

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/AwsToolkit.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ object AwsToolkit {
2828

2929
const val GITHUB_URL = "https://github.com/aws/aws-toolkit-jetbrains"
3030
const val AWS_DOCS_URL = "https://docs.aws.amazon.com/console/toolkit-for-jetbrains"
31+
const val GITHUB_CHANGELOG = "https://github.com/aws/aws-toolkit-jetbrains/blob/main/CHANGELOG.md"
3132
}
3233

3334
data class PluginInfo(val id: String, val name: String) {

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/CustomizeNotificationsUi.kt

Lines changed: 58 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import com.intellij.openapi.actionSystem.AnAction
99
import com.intellij.openapi.actionSystem.AnActionEvent
1010
import com.intellij.openapi.ui.Messages
1111
import com.intellij.ui.EditorNotificationPanel
12+
import software.aws.toolkits.jetbrains.AwsToolkit
13+
import software.aws.toolkits.resources.AwsCoreBundle
1214

1315
fun checkSeverity(notificationSeverity: String): NotificationSeverity = when (notificationSeverity) {
1416
"Critical" -> NotificationSeverity.CRITICAL
@@ -17,83 +19,73 @@ fun checkSeverity(notificationSeverity: String): NotificationSeverity = when (no
1719
else -> NotificationSeverity.INFO
1820
}
1921

20-
fun getNotificationActionList(
21-
notificationFollowupActions: List<NotificationFollowupActions>?,
22-
notificationTitle: String,
23-
notificationMessage: String,
24-
): List<AnAction> {
25-
val actionList = mutableListOf<AnAction>()
26-
actionList.add(
27-
getNotifAction("Expand") {
28-
Messages.showYesNoDialog(null, notificationMessage, notificationTitle, "OK", "Cancel", AllIcons.General.Error)
29-
}
30-
)
31-
if (notificationFollowupActions.isNullOrEmpty()) return actionList
32-
notificationFollowupActions.forEach { notificationAction ->
33-
if (notificationAction.type == "ShowUrl") {
34-
actionList.add(
35-
getNotifAction("Learn more") {
36-
notificationAction.content.locale.url?.let { url -> BrowserUtil.browse(url) }
37-
}
38-
)
39-
}
22+
object NotificationManager {
23+
fun createActions(
24+
followupActions: List<NotificationFollowupActions>?,
25+
message: String,
26+
title: String,
4027

41-
if (notificationAction.type == "UpdateExtension") {
42-
actionList.add(
43-
getNotifAction("Update") {
44-
// add update logic
45-
}
46-
)
47-
}
48-
49-
if (notificationAction.type == "openChangelog") {
50-
actionList.add(
51-
getNotifAction("Changelog") {
52-
BrowserUtil.browse("https://github.com/aws/aws-toolkit-jetbrains/blob/main/CHANGELOG.md")
53-
}
54-
)
55-
}
56-
}
57-
return actionList
58-
}
28+
): List<NotificationActionList> = buildList {
29+
add(
30+
NotificationActionList(AwsCoreBundle.message("notification.expand")) {
31+
Messages.showYesNoDialog(
32+
null,
33+
message,
34+
title,
35+
AwsCoreBundle.message("general.ok"),
36+
AwsCoreBundle.message("general.cancel"),
37+
AllIcons.General.Error
38+
)
39+
}
40+
)
5941

60-
fun getNotifAction(title: String, block: () -> Unit): AnAction = object : AnAction(title) {
61-
override fun actionPerformed(e: AnActionEvent) {
62-
block()
63-
}
64-
}
42+
followupActions?.forEach { action ->
43+
if (action.type == "ShowUrl") {
44+
add(
45+
NotificationActionList(AwsCoreBundle.message("notification.learn_more")) {
46+
action.content.locale.url?.let { url -> BrowserUtil.browse(url) }
47+
}
48+
)
49+
}
6550

66-
fun getBannerActionList(
67-
notificationFollowupActions: List<NotificationFollowupActions>?,
68-
notificationTitle: String,
69-
notificationMessage: String,
70-
): EditorNotificationPanel {
71-
val panel = EditorNotificationPanel()
51+
if (action.type == "UpdateExtension") {
52+
add(
53+
NotificationActionList(AwsCoreBundle.message("notification.update")) {
54+
// TODO: Add update logic
55+
}
56+
)
57+
}
7258

73-
panel.text = notificationTitle
74-
panel.icon(AllIcons.General.Error)
75-
panel.createActionLabel("Expand") {
76-
Messages.showYesNoDialog(null, notificationMessage, notificationTitle, "OK", "Cancel", AllIcons.General.Error)
77-
}
78-
if (notificationFollowupActions.isNullOrEmpty()) return panel
79-
notificationFollowupActions.forEach { notificationAction ->
80-
if (notificationAction.type == "ShowUrl") {
81-
panel.createActionLabel("Learn more") {
82-
notificationAction.content.locale.url?.let { url -> BrowserUtil.browse(url) }
59+
if (action.type == "OpenChangelog") {
60+
add(
61+
NotificationActionList(AwsCoreBundle.message("notification.changelog")) {
62+
BrowserUtil.browse(AwsToolkit.GITHUB_CHANGELOG)
63+
}
64+
)
8365
}
8466
}
67+
}
8568

86-
if (notificationAction.type == "UpdateExtension") {
87-
panel.createActionLabel("Update") {
88-
// add update logic
69+
fun buildNotificationActions(actions: List<NotificationActionList>): List<AnAction> = actions.map { (title, block) ->
70+
object : AnAction(title) {
71+
override fun actionPerformed(e: AnActionEvent) {
72+
block()
8973
}
9074
}
75+
}
9176

92-
if (notificationAction.type == "openChangelog") {
93-
panel.createActionLabel("Changelog") {
94-
BrowserUtil.browse("https://github.com/aws/aws-toolkit-jetbrains/blob/main/CHANGELOG.md")
77+
fun buildBannerPanel(panel: EditorNotificationPanel, actions: List<NotificationActionList>): EditorNotificationPanel {
78+
actions.forEach { (actionTitle, block) ->
79+
panel.createActionLabel(actionTitle) {
80+
block()
9581
}
9682
}
83+
84+
return panel
9785
}
98-
return panel
9986
}
87+
88+
data class NotificationActionList(
89+
val title: String,
90+
val blockToExecute: () -> Unit,
91+
)

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/DisplayToastNotifications.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,17 @@ object DisplayToastNotifications {
2222
if (RulesEngine.displayNotification(notificationData, project)) {
2323
val notificationContent = notificationData.content.locale
2424
val severity = notificationData.severity
25+
val followupActions = NotificationManager.createActions(notificationData.actions, notificationContent.description, notificationContent.title)
2526
showToast(
2627
notificationContent.title,
2728
notificationContent.description,
28-
getNotificationActionList(notificationData.actions, notificationContent.title, notificationContent.description),
29+
NotificationManager.buildNotificationActions(followupActions),
2930
checkSeverity(severity),
3031
notificationData.id
3132
)
3233

3334
if (severity == "Critical") {
34-
ShowCriticalNotificationBannerListener.showBanner(notificationContent.title, notificationContent.description, notificationData.actions)
35+
ShowCriticalNotificationBannerListener.showBanner(notificationContent.title, notificationContent.description, followupActions)
3536
}
3637
}
3738
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package software.aws.toolkits.jetbrains.core.notifications
5+
6+
import com.intellij.openapi.actionSystem.AnAction
7+
import com.intellij.openapi.actionSystem.AnActionEvent
8+
import com.intellij.openapi.util.registry.Registry
9+
10+
class DummyNotificationAction : AnAction("Show notif") {
11+
override fun actionPerformed(e: AnActionEvent) {
12+
if (!Registry.`is`("aws.toolkit.developerMode")) return
13+
ShowCriticalNotificationBannerListener.showBanner(
14+
"hello hello",
15+
"This is a bug",
16+
NotificationManager.createActions(emptyList(), "This is a bug", "hello hello")
17+
)
18+
}
19+
}

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/ShowCriticalNotificationBannerListener.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ import com.intellij.util.messages.Topic
88
import java.util.EventListener
99

1010
interface ShowCriticalNotificationBannerListener : EventListener {
11-
fun onReceiveEmergencyNotification(title: String, message: String, actions: List<NotificationFollowupActions>?) {}
11+
fun onReceiveEmergencyNotification(title: String, message: String, notificationActionList: List<NotificationActionList>) {}
1212

1313
companion object {
1414
@Topic.AppLevel
1515
val TOPIC = Topic.create("Show critical banner", ShowCriticalNotificationBannerListener::class.java)
1616

17-
fun showBanner(title: String, message: String, actions: List<NotificationFollowupActions>?) {
18-
ApplicationManager.getApplication().messageBus.syncPublisher(TOPIC).onReceiveEmergencyNotification(title, message, actions)
17+
fun showBanner(title: String, message: String, notificationActionList: List<NotificationActionList>) {
18+
ApplicationManager.getApplication().messageBus.syncPublisher(TOPIC).onReceiveEmergencyNotification(title, message, notificationActionList)
1919
}
2020
}
2121
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package software.aws.toolkits.jetbrains.core.notifications
5+
6+
import org.assertj.core.api.Assertions.assertThat
7+
import org.junit.jupiter.api.Test
8+
9+
class NotificationManagerTest {
10+
11+
@Test
12+
fun `If no follow-up actions, expand action is present`() {
13+
val sut = NotificationManager.createActions(null, "Dummy Test Action", "Dummy title")
14+
assertThat(sut).isNotNull
15+
assertThat(sut).hasSize(1)
16+
assertThat(sut.first().title).isEqualTo("Expand")
17+
}
18+
19+
@Test
20+
fun `Show Url action shows the option to learn more`() {
21+
val followupActions = NotificationFollowupActions(
22+
"ShowUrl",
23+
NotificationFollowupActionsContent(NotificationActionDescription("title", "http://leadsnowhere"))
24+
)
25+
val sut = NotificationManager.createActions(listOf(followupActions), "Dummy Test Action", "Dummy title")
26+
assertThat(sut).isNotNull
27+
assertThat(sut).hasSize(2)
28+
assertThat(sut.first().title).isEqualTo("Expand")
29+
assertThat(sut[1].title).isEqualTo("Learn more")
30+
}
31+
}

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1252,6 +1252,7 @@ general.default=Default
12521252
general.delete=Delete
12531253
general.delete_accessible_name=Delete confirmation box
12541254
general.details=(details)
1255+
general.dismiss=Dismiss
12551256
general.execute_button=Execute
12561257
general.execution.canceled=canceled
12571258
general.execution.cli_error=Command did not exit successfully, exit code: {0}\n
@@ -1269,6 +1270,7 @@ general.name.label=Name:
12691270
general.no_changes=No changes were provided
12701271
general.notification.action.hide_forever=Don't show again
12711272
general.notification.action.hide_once=Dismiss
1273+
general.ok=OK
12721274
general.open.in.progress=Opening...
12731275
general.open_in_aws_console=Open in AWS Console
12741276
general.open_in_aws_console.error=Failed to open link in browser
@@ -1511,6 +1513,10 @@ lambda.workflow.update_code.wait_for_updatable=Waiting for function to transitio
15111513
loading_resource.failed=Failed loading resources
15121514
loading_resource.loading=Loading...
15131515
loading_resource.still_loading=Resources are still loading
1516+
notification.changelog=Changelog
1517+
notification.expand=Expand
1518+
notification.learn_more=Learn more
1519+
notification.update=Update
15141520
plugin.incompatible.fix=Disable incompatible plugins and restart IDE
15151521
plugin.incompatible.message=The plugin versions for Amazon Q, AWS Toolkit, and AWS Toolkit Core must match or conflicts may occur.
15161522
plugin.incompatible.title=AWS Plugin Incompatibility

plugins/core/src/main/resources/META-INF/plugin.xml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,7 @@
2626
<projectListeners>
2727
<listener class="software.aws.toolkits.jetbrains.services.telemetry.OpenedFileTypesMetricsListener" topic="com.intellij.openapi.fileEditor.FileEditorManagerListener"/>
2828
</projectListeners>
29-
29+
<actions>
30+
<action class="software.aws.toolkits.jetbrains.core.notifications.DummyNotificationAction"/>
31+
</actions>
3032
</idea-plugin>

0 commit comments

Comments
 (0)