oxen-electron-gui-wallet/src/components/service_node/service_node_list.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>