170 lines
5.0 KiB
Vue
170 lines
5.0 KiB
Vue
<template>
|
|
<div>
|
|
<q-list class="service-node-list" no-border>
|
|
<q-item
|
|
v-for="node in serviceNodes"
|
|
:key="node.service_node_pubkey"
|
|
@click.native="details(nodeWithMinContribution(node))"
|
|
>
|
|
<q-item-section>
|
|
<q-item-label class="ellipsis"
|
|
>{{ $t("strings.serviceNodeDetails.snKey") }}:
|
|
{{ node.service_node_pubkey }}</q-item-label
|
|
>
|
|
<q-item-label class="non-selectable">
|
|
<span v-if="node.ourContributionAmount > 0">
|
|
<span v-if="getRole(node)">{{ getRole(node) }} •</span>
|
|
<span>
|
|
{{ $t("strings.contribution") }}:
|
|
<FormatOxen :amount="node.ourContributionAmount" />
|
|
</span>
|
|
</span>
|
|
<!-- you only have a contribution amount of 0 if you are a "contributor"
|
|
by way of the node having reserved a spot for you on the node -->
|
|
<span
|
|
v-if="
|
|
node.ourContributionAmount === 0 && node.awaitingContribution
|
|
"
|
|
>
|
|
{{ $t("strings.serviceNodeDetails.reserved") }} •
|
|
</span>
|
|
<span v-if="node.awaitingContribution" class="contrib-amounts">
|
|
{{ $t("strings.serviceNodeDetails.minContribution") }}:
|
|
{{ getMinContribution(node, our_address) }} OXEN •
|
|
{{ $t("strings.serviceNodeDetails.maxContribution") }}:
|
|
{{ openForContributionOxen(node, our_address) }} OXEN
|
|
</span>
|
|
</q-item-label>
|
|
</q-item-section>
|
|
<q-item-section side>
|
|
<span class="fee">{{ getFee(node) }}</span>
|
|
</q-item-section>
|
|
<q-item-section side>
|
|
<q-btn
|
|
v-if="node.requested_unlock_height === 0"
|
|
color="primary"
|
|
size="md"
|
|
:label="$t(buttonI18n)"
|
|
:disabled="!is_ready"
|
|
side
|
|
@click="action(nodeWithMinContribution(node), $event)"
|
|
/>
|
|
<q-item-label v-if="node.requested_unlock_height > 0" header>
|
|
{{
|
|
$t("strings.unlockingAtHeight", {
|
|
number: node.requested_unlock_height
|
|
})
|
|
}}
|
|
</q-item-label>
|
|
</q-item-section>
|
|
<ContextMenu
|
|
:menu-items="menuItems"
|
|
@viewOnExplorer="openExplorer(node.service_node_pubkey)"
|
|
@copyServiceNodeKey="copyKey(node.service_node_pubkey)"
|
|
/>
|
|
</q-item>
|
|
</q-list>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { clipboard } from "electron";
|
|
import ContextMenu from "components/menus/contextmenu";
|
|
import FormatOxen from "components/format_oxen";
|
|
import ServiceNodeMixin from "src/mixins/service_node_mixin";
|
|
import { mapState } from "vuex";
|
|
|
|
export default {
|
|
name: "ServiceNodeList",
|
|
components: {
|
|
ContextMenu,
|
|
FormatOxen
|
|
},
|
|
mixins: [ServiceNodeMixin],
|
|
props: {
|
|
serviceNodes: {
|
|
type: Array,
|
|
required: true
|
|
},
|
|
details: {
|
|
type: Function,
|
|
required: true
|
|
},
|
|
buttonI18n: {
|
|
type: String,
|
|
required: true
|
|
},
|
|
action: {
|
|
type: Function,
|
|
required: true
|
|
}
|
|
},
|
|
data() {
|
|
const menuItems = [
|
|
{ action: "copyServiceNodeKey", i18n: "menuItems.copyServiceNodeKey" },
|
|
{ action: "viewOnExplorer", i18n: "menuItems.viewOnExplorer" }
|
|
];
|
|
return {
|
|
menuItems
|
|
};
|
|
},
|
|
computed: mapState({
|
|
our_address: state => {
|
|
const primary = state.gateway.wallet.address_list.primary[0];
|
|
return (primary && primary.address) || null;
|
|
}
|
|
}),
|
|
methods: {
|
|
nodeWithMinContribution(node) {
|
|
const nodeWithMinContribution = {
|
|
...node,
|
|
minContribution: this.getMinContribution(node, this.our_address)
|
|
};
|
|
return nodeWithMinContribution;
|
|
},
|
|
is_ready() {
|
|
return this.$store.getters["gateway/isReady"];
|
|
},
|
|
getRole(node) {
|
|
let role = "";
|
|
const opAddress = node.operator_address;
|
|
if (opAddress === this.our_address) {
|
|
role = "strings.operator";
|
|
} else if (node.ourContributionAmount && opAddress !== this.our_address) {
|
|
// if we're not the operator and we have a contribution amount
|
|
role = "strings.contributor";
|
|
}
|
|
return this.$t(role);
|
|
},
|
|
getNumContributors(node) {
|
|
return node.contributors.length;
|
|
},
|
|
getFee(node) {
|
|
const operatorPortion = node.portions_for_operator;
|
|
const percentageFee = (operatorPortion / 18446744073709551612) * 100;
|
|
return `${percentageFee.toFixed(2)}% ${this.$t(
|
|
"strings.transactions.fee"
|
|
)}`;
|
|
},
|
|
copyKey(key) {
|
|
clipboard.writeText(key);
|
|
this.$q.notify({
|
|
type: "positive",
|
|
timeout: 1000,
|
|
message: this.$t("notification.positive.copied", {
|
|
item: "Service node key"
|
|
})
|
|
});
|
|
},
|
|
openExplorer(key) {
|
|
this.$gateway.send("core", "open_explorer", {
|
|
type: "service_node",
|
|
id: key
|
|
});
|
|
}
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss"></style>
|