andrewinci/Insulator

View on GitHub
app/src/main/kotlin/insulator/views/main/topic/TopicView.kt

Summary

Maintainability
C
1 day
Test Coverage
F
0%
package insulator.views.main.topic

import insulator.di.TopicScope
import insulator.helper.dispatch
import insulator.helper.hideOnReadonly
import insulator.helper.toObservable
import insulator.kafka.consumer.ConsumeFrom
import insulator.kafka.model.Cluster
import insulator.kafka.producer.SerializationFormat
import insulator.ui.common.InsulatorTabView
import insulator.ui.component.appBar
import insulator.ui.component.confirmationButton
import insulator.ui.component.fieldName
import insulator.ui.component.searchBox
import insulator.ui.style.ButtonStyle
import insulator.viewmodel.main.topic.RecordViewModel
import insulator.viewmodel.main.topic.TopicViewModel
import javafx.beans.binding.Bindings
import javafx.event.EventTarget
import javafx.geometry.Insets
import javafx.geometry.Pos
import javafx.scene.control.Control
import javafx.scene.control.SelectionMode
import javafx.scene.control.TableCell
import javafx.scene.layout.Priority
import tornadofx.* // ktlint-disable no-wildcard-imports
import javax.inject.Inject

@TopicScope
class TopicView @Inject constructor(
    override val viewModel: TopicViewModel,
    private val cluster: Cluster
) : InsulatorTabView() {

    private val CONSUME = "Consume"
    private val STOP = "Stop"

    override val root = vbox {
        appBar {
            title = viewModel.nameProperty.value
            subtitle = viewModel.subtitleProperty
            buttons = listOf(showInfoButton(), deleteButton())
        }
        borderpane {
            padding = Insets(-5.0, 0.0, 10.0, 0.0)
            left = hbox(alignment = Pos.CENTER, spacing = 5.0) {
                produceButton()
                consumeStopButton()
                fieldName("from")
                consumeFromComboBox()
                valueFormatOptions()
                button("Clear") { action { viewModel.consumerViewModel.clearRecords() } }
            }
            right = searchBox(viewModel.consumerViewModel.searchItem, this@TopicView)
        }
        recordsTable()
    }

    private fun EventTarget.produceButton() {
        button("Produce") {
            id = "button-produce"
            action { viewModel.showProducerView(currentWindow) }
            addClass(ButtonStyle.blueButton)
        }.hideOnReadonly()
    }

    private fun EventTarget.consumeStopButton() {
        button(
            with(viewModel.consumerViewModel.isConsumingProperty) {
                Bindings.createStringBinding({ if (!this.value) CONSUME else STOP }, this)
            }
        ) {
            id = "button-consume-stop"
            action { viewModel.dispatch { consumerViewModel.consume() } }
        }
    }

    private fun EventTarget.valueFormatOptions() {
        if (cluster.isSchemaRegistryConfigured()) {
            viewModel.consumerViewModel.deserializeValueProperty.set(SerializationFormat.Avro.name)
            fieldName("deserializer")
            combobox<String> {
                items = SerializationFormat.values().toObservable { it.toString() }
                valueProperty().bindBidirectional(viewModel.consumerViewModel.deserializeValueProperty)
                enableWhen(viewModel.consumerViewModel.isConsumingProperty.not())
            }
        }
    }

    private fun EventTarget.consumeFromComboBox() =
        combobox<String> {
            items = ConsumeFrom.values().toObservable { it.text }
            valueProperty().bindBidirectional(viewModel.consumerViewModel.consumeFromProperty)
        }.enableWhen(viewModel.consumerViewModel.isConsumingProperty.not())

    private fun EventTarget.deleteButton() =
        confirmationButton("Delete", "The topic \"${viewModel.nameProperty.value}\" will be removed.") {
            viewModel.dispatch { delete() }
            closeTab()
        }.enableWhen(viewModel.consumerViewModel.isConsumingProperty.not()).hideOnReadonly()

    private fun EventTarget.showInfoButton() = button("Info") {
        id = "button-info"
        action { viewModel.showTopicInfoView(currentWindow) }
        addClass(ButtonStyle.blueButton)
    }

    private fun EventTarget.recordsTable() =
        tableview<RecordViewModel> {
            val partitionColumn = column("P", RecordViewModel::partitionProperty) { prefWidthProperty().set(30.0); isReorderable = false }
            val offsetColumn = column("O", RecordViewModel::offsetProperty) { prefWidthProperty().set(30.0); isReorderable = false }
            val timeColumn = column("Time", RecordViewModel::formattedTimeStampProperty) { prefWidthProperty().set(150.0); isReorderable = false }
            val keyColumn = column("Key", RecordViewModel::keyProperty) { prefWidthProperty().set(300.0); isReorderable = false }
            val valueColumn = column("Value", RecordViewModel::valueProperty) {
                isReorderable = false
                prefWidthProperty().bind(
                    this.tableView.widthProperty()
                        .minus(partitionColumn.widthProperty())
                        .minus(offsetColumn.widthProperty())
                        .minus(timeColumn.widthProperty())
                        .minus(keyColumn.widthProperty())
                        .minus(20.0)
                )
            }
            valueColumn.setCellFactory {
                TableCell<RecordViewModel, String>().apply {
                    graphic = text {
                        addClass("text")
                        wrappingWidthProperty().bind(valueColumn.widthProperty().subtract(Bindings.multiply(2.0, graphicTextGapProperty())))
                        textProperty().bind(stringBinding(itemProperty()) { get()?.toString() ?: "" })
                    }
                    prefHeight = Control.USE_COMPUTED_SIZE
                }
            }
            viewModel.consumerViewModel.comparatorProperty.bind(this.comparatorProperty())
            itemsProperty().bind(viewModel.consumerViewModel.filteredRecords)

            contextMenu = contextmenu {
                item("Copy") { action { viewModel.copySelectedRecordToClipboard() } }
                item("Copy all") { action { viewModel.copyAllRecordsToClipboard() } }
            }
            onDoubleClick { viewModel.showRecordInfoView(currentWindow) }
            bindSelected(viewModel.selectedItem)
            selectionModel.selectionMode = SelectionMode.SINGLE

            vgrow = Priority.ALWAYS
            hgrow = Priority.ALWAYS
        }

    override fun onError(throwable: Throwable) = close()

    override fun onTabClosed() {
        viewModel.dispatch { viewModel.consumerViewModel.stop() }
    }
}