Explorer x500names (#631)

Format party names in explorer, so they look nice after X500 name changes.
This commit is contained in:
Katarzyna Streich 2017-05-05 14:00:55 +01:00 committed by GitHub
parent 0309426cb9
commit c062d48e6e
7 changed files with 62 additions and 17 deletions

View File

@ -0,0 +1,15 @@
package net.corda.explorer.formatters
import net.corda.core.crypto.Party
import net.corda.core.crypto.commonName
import org.bouncycastle.asn1.x500.X500Name
object PartyNameFormatter {
val short = object : Formatter<String> {
override fun format(value: String) = X500Name(value).commonName
}
val full = object : Formatter<String> {
override fun format(value: String): String = value
}
}

View File

@ -23,6 +23,7 @@ import net.corda.client.jfx.model.observableList
import net.corda.client.jfx.model.observableValue import net.corda.client.jfx.model.observableValue
import net.corda.client.jfx.utils.ChosenList import net.corda.client.jfx.utils.ChosenList
import net.corda.client.jfx.utils.map import net.corda.client.jfx.utils.map
import net.corda.explorer.formatters.PartyNameFormatter
import net.corda.explorer.model.CordaViewModel import net.corda.explorer.model.CordaViewModel
import tornadofx.* import tornadofx.*
@ -49,7 +50,7 @@ class MainView : View() {
init { init {
// Header // Header
userButton.textProperty().bind(myIdentity.map { it?.legalIdentity?.name }) userButton.textProperty().bind(myIdentity.map { it?.legalIdentity?.let { PartyNameFormatter.short.format(it.name) } })
exit.setOnAction { exit.setOnAction {
(root.scene.window as Stage).fireEvent(WindowEvent(root.scene.window, WindowEvent.WINDOW_CLOSE_REQUEST)) (root.scene.window as Stage).fireEvent(WindowEvent(root.scene.window, WindowEvent.WINDOW_CLOSE_REQUEST))
} }

View File

@ -29,6 +29,7 @@ import net.corda.core.contracts.ContractState
import net.corda.core.crypto.Party import net.corda.core.crypto.Party
import net.corda.core.crypto.toBase58String import net.corda.core.crypto.toBase58String
import net.corda.core.node.NodeInfo import net.corda.core.node.NodeInfo
import net.corda.explorer.formatters.PartyNameFormatter
import net.corda.explorer.model.CordaView import net.corda.explorer.model.CordaView
import tornadofx.* import tornadofx.*
@ -84,7 +85,7 @@ class Network : CordaView() {
private fun NodeInfo.render(): MapViewComponents { private fun NodeInfo.render(): MapViewComponents {
val node = this val node = this
val mapLabel = label(node.legalIdentity.name) { val mapLabel = label(PartyNameFormatter.short.format(node.legalIdentity.name)) {
graphic = FontAwesomeIconView(FontAwesomeIcon.DOT_CIRCLE_ALT) graphic = FontAwesomeIconView(FontAwesomeIcon.DOT_CIRCLE_ALT)
contentDisplay = ContentDisplay.TOP contentDisplay = ContentDisplay.TOP
val coordinate = Bindings.createObjectBinding({ val coordinate = Bindings.createObjectBinding({
@ -98,10 +99,11 @@ class Network : CordaView() {
val button = button { val button = button {
graphic = vbox { graphic = vbox {
label(node.legalIdentity.name) { font = Font.font(font.family, FontWeight.BOLD, 15.0) } label(PartyNameFormatter.short.format(node.legalIdentity.name)) { font = Font.font(font.family, FontWeight.BOLD, 15.0) }
gridpane { gridpane {
hgap = 5.0 hgap = 5.0
vgap = 5.0 vgap = 5.0
row("Full name :") { label(PartyNameFormatter.full.format(node.legalIdentity.name)) }
row("Pub Key :") { copyableLabel(SimpleObjectProperty(node.legalIdentity.owningKey.toBase58String())) } row("Pub Key :") { copyableLabel(SimpleObjectProperty(node.legalIdentity.owningKey.toBase58String())) }
row("Services :") { label(node.advertisedServices.map { it.info }.joinToString(", ")) } row("Services :") { label(node.advertisedServices.map { it.info }.joinToString(", ")) }
node.physicalLocation?.apply { row("Location :") { label(this@apply.description) } } node.physicalLocation?.apply { row("Location :") { label(this@apply.description) } }

View File

@ -30,6 +30,8 @@ import net.corda.core.crypto.toStringShort
import net.corda.core.node.NodeInfo import net.corda.core.node.NodeInfo
import net.corda.explorer.AmountDiff import net.corda.explorer.AmountDiff
import net.corda.explorer.formatters.AmountFormatter import net.corda.explorer.formatters.AmountFormatter
import net.corda.explorer.formatters.Formatter
import net.corda.explorer.formatters.PartyNameFormatter
import net.corda.explorer.identicon.identicon import net.corda.explorer.identicon.identicon
import net.corda.explorer.identicon.identiconToolTip import net.corda.explorer.identicon.identiconToolTip
import net.corda.explorer.model.CordaView import net.corda.explorer.model.CordaView
@ -132,8 +134,22 @@ class TransactionViewer : CordaView("Transactions") {
} }
} }
column("Output", Transaction::outputs).cellFormat { text = it.toText() } column("Output", Transaction::outputs).cellFormat { text = it.toText() }
column("Input Party", Transaction::inputParties).cellFormat { text = it.flatten().map { it.value?.legalIdentity?.name }.filterNotNull().toSet().joinToString() } column("Input Party", Transaction::inputParties).setCustomCellFactory {
column("Output Party", Transaction::outputParties).cellFormat { text = it.flatten().map { it.value?.legalIdentity?.name }.filterNotNull().toSet().joinToString() } label {
text = it.formatJoinPartyNames(formatter = PartyNameFormatter.short)
tooltip {
text = it.formatJoinPartyNames("\n", PartyNameFormatter.full)
}
}
}
column("Output Party", Transaction::outputParties).setCustomCellFactory {
label {
text = it.formatJoinPartyNames(formatter = PartyNameFormatter.short)
tooltip {
text = it.formatJoinPartyNames("\n", PartyNameFormatter.full)
}
}
}
column("Command type", Transaction::commandTypes).cellFormat { text = it.map { it.simpleName }.joinToString() } column("Command type", Transaction::commandTypes).cellFormat { text = it.map { it.simpleName }.joinToString() }
column("Total value", Transaction::totalValueEquiv).cellFormat { column("Total value", Transaction::totalValueEquiv).cellFormat {
text = "${it.positivity.sign}${AmountFormatter.boring.format(it.amount)}" text = "${it.positivity.sign}${AmountFormatter.boring.format(it.amount)}"
@ -154,6 +170,12 @@ class TransactionViewer : CordaView("Transactions") {
}) })
} }
private fun ObservableList<List<ObservableValue<NodeInfo?>>>.formatJoinPartyNames(separator: String = "", formatter: Formatter<String>): String {
return flatten().map {
it.value?.legalIdentity?.let { formatter.format(it.name) }
}.filterNotNull().toSet().joinToString(separator)
}
private fun ObservableList<StateAndRef<ContractState>>.getParties() = map { it.state.data.participants.map { getModel<NetworkIdentityModel>().lookup(it) } } private fun ObservableList<StateAndRef<ContractState>>.getParties() = map { it.state.data.participants.map { getModel<NetworkIdentityModel>().lookup(it) } }
private fun ObservableList<StateAndRef<ContractState>>.toText() = map { it.contract().javaClass.simpleName }.groupBy { it }.map { "${it.key} (${it.value.size})" }.joinToString() private fun ObservableList<StateAndRef<ContractState>>.toText() = map { it.contract().javaClass.simpleName }.groupBy { it }.map { "${it.key} (${it.value.size})" }.joinToString()
@ -196,7 +218,7 @@ class TransactionViewer : CordaView("Transactions") {
signatures.children.addAll(signatureData.map { signature -> signatures.children.addAll(signatureData.map { signature ->
val nodeInfo = getModel<NetworkIdentityModel>().lookup(signature) val nodeInfo = getModel<NetworkIdentityModel>().lookup(signature)
copyableLabel(nodeInfo.map { "${signature.toStringShort()} (${it?.legalIdentity?.name ?: "???"})" }) copyableLabel(nodeInfo.map { "${signature.toStringShort()} (${it?.legalIdentity?.let { PartyNameFormatter.short.format(it.name)} ?: "???"})" })
}) })
} }
@ -225,7 +247,7 @@ class TransactionViewer : CordaView("Transactions") {
val anonymousIssuer: AnonymousParty = data.amount.token.issuer.party val anonymousIssuer: AnonymousParty = data.amount.token.issuer.party
val issuer: AbstractParty = anonymousIssuer.resolveIssuer().value ?: anonymousIssuer val issuer: AbstractParty = anonymousIssuer.resolveIssuer().value ?: anonymousIssuer
// TODO: Anonymous should probably be italicised or similar // TODO: Anonymous should probably be italicised or similar
label(issuer.nameOrNull() ?: "Anonymous") { label(issuer.nameOrNull()?.let { PartyNameFormatter.short.format(it) } ?: "Anonymous") {
tooltip(anonymousIssuer.owningKey.toBase58String()) tooltip(anonymousIssuer.owningKey.toBase58String())
} }
} }
@ -233,7 +255,7 @@ class TransactionViewer : CordaView("Transactions") {
label("Owner :") { gridpaneConstraints { hAlignment = HPos.RIGHT } } label("Owner :") { gridpaneConstraints { hAlignment = HPos.RIGHT } }
val owner = data.owner val owner = data.owner
val nodeInfo = getModel<NetworkIdentityModel>().lookup(owner) val nodeInfo = getModel<NetworkIdentityModel>().lookup(owner)
label(nodeInfo.map { it?.legalIdentity?.name ?: "???" }) { label(nodeInfo.map { it?.legalIdentity?.let { PartyNameFormatter.short.format(it.name) } ?: "???" }) {
tooltip(data.owner.toBase58String()) tooltip(data.owner.toBase58String())
} }
} }

View File

@ -25,6 +25,7 @@ import net.corda.core.contracts.StateAndRef
import net.corda.core.contracts.withoutIssuer import net.corda.core.contracts.withoutIssuer
import net.corda.core.crypto.AbstractParty import net.corda.core.crypto.AbstractParty
import net.corda.explorer.formatters.AmountFormatter import net.corda.explorer.formatters.AmountFormatter
import net.corda.explorer.formatters.PartyNameFormatter
import net.corda.explorer.identicon.identicon import net.corda.explorer.identicon.identicon
import net.corda.explorer.identicon.identiconToolTip import net.corda.explorer.identicon.identiconToolTip
import net.corda.explorer.model.CordaView import net.corda.explorer.model.CordaView
@ -126,7 +127,10 @@ class CashViewer : CordaView("Cash") {
} }
equivLabel.textProperty().bind(equivAmount.map { it.token.currencyCode.toString() }) equivLabel.textProperty().bind(equivAmount.map { it.token.currencyCode.toString() })
// TODO: Anonymous should probably be italicised or similar // TODO: Anonymous should probably be italicised or similar
issuerValueLabel.textProperty().bind(SimpleStringProperty(resolvedIssuer.nameOrNull() ?: "Anonymous")) issuerValueLabel.textProperty().bind(SimpleStringProperty(resolvedIssuer.nameOrNull()?.let {
PartyNameFormatter.short.format(it)
} ?: "Anonymous"))
issuerValueLabel.apply { tooltip(resolvedIssuer.nameOrNull()?.let { PartyNameFormatter.full.format(it) } ?: "Anonymous") }
originatedValueLabel.text = stateRow.originated.toString() originatedValueLabel.text = stateRow.originated.toString()
amountValueLabel.text = amountFormatter.format(amountNoIssuer) amountValueLabel.text = amountFormatter.format(amountNoIssuer)
equivValueLabel.textProperty().bind(equivAmount.map { equivFormatter.format(it) }) equivValueLabel.textProperty().bind(equivAmount.map { equivFormatter.format(it) })
@ -230,7 +234,7 @@ class CashViewer : CordaView("Cash") {
val node = it.value.value val node = it.value.value
when (node) { when (node) {
// TODO: Anonymous should probably be italicised or similar // TODO: Anonymous should probably be italicised or similar
is ViewerNode.IssuerNode -> SimpleStringProperty(node.issuer.nameOrNull() ?: "Anonymous") is ViewerNode.IssuerNode -> SimpleStringProperty(node.issuer.nameOrNull()?.let { PartyNameFormatter.short.format(it) } ?: "Anonymous")
is ViewerNode.CurrencyNode -> node.amount.map { it.token.toString() } is ViewerNode.CurrencyNode -> node.amount.map { it.token.toString() }
} }
} }

View File

@ -28,6 +28,7 @@ import net.corda.core.messaging.startFlow
import net.corda.core.node.NodeInfo import net.corda.core.node.NodeInfo
import net.corda.core.serialization.OpaqueBytes import net.corda.core.serialization.OpaqueBytes
import net.corda.core.then import net.corda.core.then
import net.corda.explorer.formatters.PartyNameFormatter
import net.corda.explorer.model.CashTransaction import net.corda.explorer.model.CashTransaction
import net.corda.explorer.model.IssuerModel import net.corda.explorer.model.IssuerModel
import net.corda.explorer.model.ReportingCurrencyModel import net.corda.explorer.model.ReportingCurrencyModel
@ -167,7 +168,7 @@ class NewTransaction : Fragment() {
// Party A textfield always display my identity name, not editable. // Party A textfield always display my identity name, not editable.
partyATextField.isEditable = false partyATextField.isEditable = false
partyATextField.textProperty().bind(myIdentity.map { it?.legalIdentity?.name ?: "" }) partyATextField.textProperty().bind(myIdentity.map { it?.legalIdentity?.let { PartyNameFormatter.short.format(it.name) } ?: "" })
partyALabel.textProperty().bind(transactionTypeCB.valueProperty().map { it?.partyNameA?.let { "$it : " } }) partyALabel.textProperty().bind(transactionTypeCB.valueProperty().map { it?.partyNameA?.let { "$it : " } })
partyATextField.visibleProperty().bind(transactionTypeCB.valueProperty().map { it?.partyNameA }.isNotNull()) partyATextField.visibleProperty().bind(transactionTypeCB.valueProperty().map { it?.partyNameA }.isNotNull())
@ -176,17 +177,17 @@ class NewTransaction : Fragment() {
partyBChoiceBox.apply { partyBChoiceBox.apply {
visibleProperty().bind(transactionTypeCB.valueProperty().map { it?.partyNameB }.isNotNull()) visibleProperty().bind(transactionTypeCB.valueProperty().map { it?.partyNameB }.isNotNull())
items = parties.sorted() items = parties.sorted()
converter = stringConverter { it?.legalIdentity?.name ?: "" } converter = stringConverter { it?.legalIdentity?.let { PartyNameFormatter.short.format(it.name) } ?: "" }
} }
// Issuer // Issuer
issuerLabel.visibleProperty().bind(transactionTypeCB.valueProperty().isNotNull) issuerLabel.visibleProperty().bind(transactionTypeCB.valueProperty().isNotNull)
issuerChoiceBox.apply { issuerChoiceBox.apply {
items = issuers.map { it.legalIdentity }.unique().sorted() items = issuers.map { it.legalIdentity }.unique().sorted()
converter = stringConverter { it.name } converter = stringConverter { PartyNameFormatter.short.format(it.name) }
visibleProperty().bind(transactionTypeCB.valueProperty().map { it == CashTransaction.Pay }) visibleProperty().bind(transactionTypeCB.valueProperty().map { it == CashTransaction.Pay })
} }
issuerTextField.apply { issuerTextField.apply {
textProperty().bind(myIdentity.map { it?.legalIdentity?.name }) textProperty().bind(myIdentity.map { it?.legalIdentity?.let { PartyNameFormatter.short.format(it.name) } })
visibleProperty().bind(transactionTypeCB.valueProperty().map { it == CashTransaction.Issue || it == CashTransaction.Exit }) visibleProperty().bind(transactionTypeCB.valueProperty().map { it == CashTransaction.Issue || it == CashTransaction.Exit })
isEditable = false isEditable = false
} }

View File

@ -19,10 +19,10 @@
<Insets bottom="25" left="5" right="5" top="5"/> <Insets bottom="25" left="5" right="5" top="5"/>
</StackPane.margin> </StackPane.margin>
<TitledPane styleClass="networkTile" text="My Identity"> <TitledPane styleClass="networkTile" text="My Identity">
<BorderPane fx:id="myIdentityPane"/> <BorderPane fx:id="myIdentityPane" minHeight="150"/>
</TitledPane> </TitledPane>
<TitledPane styleClass="networkTile" text="Notaries"> <TitledPane styleClass="networkTile" text="Notaries">
<BorderPane> <BorderPane minHeight="150">
<center> <center>
<ScrollPane hbarPolicy="NEVER"> <ScrollPane hbarPolicy="NEVER">
<VBox fx:id="notaryList" maxWidth="-Infinity"/> <VBox fx:id="notaryList" maxWidth="-Infinity"/>
@ -31,7 +31,7 @@
</BorderPane> </BorderPane>
</TitledPane> </TitledPane>
<TitledPane styleClass="networkTile" text="Peers" VBox.vgrow="ALWAYS"> <TitledPane styleClass="networkTile" text="Peers" VBox.vgrow="ALWAYS">
<BorderPane> <BorderPane minHeight="150">
<center> <center>
<ScrollPane hbarPolicy="NEVER"> <ScrollPane hbarPolicy="NEVER">
<VBox fx:id="peerList" maxWidth="-Infinity"> <VBox fx:id="peerList" maxWidth="-Infinity">