Skip to content

Commit 60b859c

Browse files
authored
Add resources tab (#2150)
* Add resources tab * Adding UI tests
1 parent ed96ad0 commit 60b859c

File tree

7 files changed

+64
-5
lines changed

7 files changed

+64
-5
lines changed

jetbrains-core/src/software/aws/toolkits/jetbrains/services/cloudformation/stack/EventsTable.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ interface EventsTable : View {
3131
fun showBusyIcon()
3232
}
3333

34-
private class StatusCellRenderer : DefaultTableCellRenderer() {
34+
class StatusCellRenderer : DefaultTableCellRenderer() {
3535
override fun getTableCellRendererComponent(table: JTable, value: Any, isSelected: Boolean, hasFocus: Boolean, row: Int, column: Int): Component =
3636
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column).also {
3737
it.foreground = StatusType.fromStatusValue(value as String).color
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package software.aws.toolkits.jetbrains.services.cloudformation.stack
5+
6+
import com.intellij.openapi.Disposable
7+
import com.intellij.util.ui.JBUI
8+
import software.amazon.awssdk.services.cloudformation.model.StackResource
9+
import software.aws.toolkits.jetbrains.utils.ui.WrappingCellRenderer
10+
import software.aws.toolkits.resources.message
11+
import javax.swing.JComponent
12+
13+
class ResourceTableView : View, ResourceListener, Disposable {
14+
private val table = DynamicTableView<StackResource>(
15+
DynamicTableView.Field(message("cloudformation.stack.logical_id")) { it.logicalResourceId() },
16+
DynamicTableView.Field(message("cloudformation.stack.physical_id")) { it.physicalResourceId() },
17+
DynamicTableView.Field(message("cloudformation.stack.type")) { it.resourceType() },
18+
DynamicTableView.Field(message("cloudformation.stack.status"), renderer = StatusCellRenderer()) { it.resourceStatusAsString() },
19+
DynamicTableView.Field(
20+
message("cloudformation.stack.reason"),
21+
renderer = WrappingCellRenderer(wrapOnSelection = true, wrapOnToggle = false)
22+
) { it.resourceStatusReason() }
23+
).apply { component.border = JBUI.Borders.empty() }
24+
25+
override val component: JComponent = table.component
26+
27+
override fun updatedResources(resources: List<StackResource>) = table.updateItems(resources, clearExisting = true)
28+
29+
override fun dispose() {}
30+
}
31+
32+
interface ResourceListener {
33+
fun updatedResources(resources: List<StackResource>)
34+
}

jetbrains-core/src/software/aws/toolkits/jetbrains/services/cloudformation/stack/Stack.kt

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ private class StackUI(private val project: Project, private val stackName: Strin
6666

6767
private val eventsTable: EventsTableImpl
6868
private val outputsTable = OutputsTableView()
69+
private val resourcesTable = ResourceTableView()
6970

7071
init {
7172
val tree = TreeViewImpl(project, stackName)
@@ -119,11 +120,19 @@ private class StackUI(private val project: Project, private val stackName: Strin
119120
}
120121
)
121122

123+
this.add(
124+
message("cloudformation.stack.tab_labels.resources"),
125+
JPanel().apply {
126+
layout = BoxLayout(this, BoxLayout.Y_AXIS)
127+
add(resourcesTable.component)
128+
}
129+
)
130+
122131
this.add(
123132
message("cloudformation.stack.tab_labels.outputs"),
124133
JPanel().apply {
125134
layout = BoxLayout(this, BoxLayout.Y_AXIS)
126-
add(outputsTable.component)
135+
add(add(outputsTable.component))
127136
}
128137
)
129138
}
@@ -133,6 +142,7 @@ private class StackUI(private val project: Project, private val stackName: Strin
133142
tree,
134143
eventsTable = eventsTable,
135144
outputsTable = outputsTable,
145+
resourceListener = resourcesTable,
136146
stackName = stackName,
137147
updateEveryMs = UPDATE_STACK_STATUS_INTERVAL,
138148
listener = this,
@@ -141,7 +151,7 @@ private class StackUI(private val project: Project, private val stackName: Strin
141151
)
142152

143153
toolWindowTab = toolWindow.addTab(stackName, mainPanel, id = stackId)
144-
listOf(tree, updater, animator, eventsTable, outputsTable, pageButtons).forEach { Disposer.register(toolWindowTab, it) }
154+
listOf(tree, updater, animator, eventsTable, outputsTable, resourcesTable, pageButtons).forEach { Disposer.register(toolWindowTab, it) }
145155
}
146156

147157
fun start() {

jetbrains-core/src/software/aws/toolkits/jetbrains/services/cloudformation/stack/Updater.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ class Updater(
3131
private val treeView: TreeView,
3232
private val eventsTable: EventsTable,
3333
private val outputsTable: OutputsListener,
34+
private val resourceListener: ResourceListener,
3435
private val stackName: String,
3536
private val updateEveryMs: Int,
3637
private val listener: UpdateListener,
@@ -96,6 +97,7 @@ class Updater(
9697

9798
app.invokeLater {
9899
outputsTable.updatedOutputs(stackDetails.outputs)
100+
resourceListener.updatedResources(stackDetails.resources)
99101

100102
showData(
101103
stackStatus = newStackStatus,

jetbrains-core/tst/software/aws/toolkits/jetbrains/services/cloudformation/stack/UpdaterTest.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ class UpdaterTest {
4747
private val eventsTable = mock(EventsTable::class.java)
4848
private val outputTable = mock(OutputsListener::class.java)
4949
private val updateListener = mock(UpdateListener::class.java)
50+
private val resourceListener = mock(ResourceListener::class.java)
5051

5152
@Before
5253
fun setUp() {
@@ -93,6 +94,7 @@ class UpdaterTest {
9394
Updater(
9495
treeView = treeView,
9596
eventsTable = eventsTable,
97+
resourceListener = resourceListener,
9698
outputsTable = outputTable,
9799
stackName = "MyStack",
98100
updateEveryMs = 1,

resources/resources/software/aws/toolkits/resources/localized_messages.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ cloudformation.stack.reason=Status Reason
182182
cloudformation.stack.status=Status
183183
cloudformation.stack.tab_labels.events=Events
184184
cloudformation.stack.tab_labels.outputs=Outputs
185+
cloudformation.stack.tab_labels.resources=Resources
185186
cloudformation.stack.type=Type
186187
cloudformation.stack.view=View Stack Status
187188
cloudformation.template_index.missing_type=Resource type must not be null for indexing

ui-tests/tst/software/aws/toolkits/jetbrains/uitests/tests/CloudFormationBrowserTest.kt

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,18 +73,25 @@ class CloudFormationBrowserTest {
7373
}
7474
}
7575
step("Check events") {
76-
clickOnEvents()
76+
clickOn("Events")
7777
step("Assert that there are two CREATE_COMPLETE events shown") {
7878
val createComplete = findAllText("CREATE_COMPLETE")
7979
assertThat(createComplete).hasSize(2)
8080
}
8181
}
8282
step("Check outputs") {
83-
clickOnOutputs()
83+
clickOn("Outputs")
8484
step("Assert that the stack output is there") {
8585
findText("Cool description")
8686
}
8787
}
88+
step("Check resources") {
89+
clickOn("Resources")
90+
step("Assert that the stack resource is there") {
91+
val createComplete = findAllText("CREATE_COMPLETE")
92+
assertThat(createComplete).hasSize(1)
93+
}
94+
}
8895
step("Delete stack $stack") {
8996
showAwsExplorer()
9097
awsExplorer {
@@ -116,6 +123,9 @@ class CloudFormationBrowserTest {
116123
waitForStackDeletion()
117124
}
118125

126+
private fun IdeaFrame.clickOn(tab: String) {
127+
findAndClick("//div[@accessiblename='$tab' and @class='JLabel' and @text='$tab']")
128+
}
119129
private fun IdeaFrame.clickOnOutputs() {
120130
findAndClick("//div[@accessiblename='Outputs' and @class='JLabel' and @text='Outputs']")
121131
}

0 commit comments

Comments
 (0)