Merge branch 'development' into require-update-footer
This commit is contained in:
commit
d92898e153
|
@ -17,23 +17,19 @@
|
|||
<q-item-label v-if="paymentId" header>{{ $t("fieldLabels.paymentId") }}: {{ paymentId }}</q-item-label>
|
||||
<q-item-label v-if="extra" header class="extra non-selectable">{{ extra }}</q-item-label>
|
||||
</q-item-section>
|
||||
|
||||
<q-menu context-menu>
|
||||
<q-list separator class="context-menu">
|
||||
<q-item v-close-popup clickable @click.native="copyAddress($event)">
|
||||
<q-item-section>
|
||||
{{ $t("menuItems.copyAddress") }}
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-menu>
|
||||
<ContextMenu :menu-items="menuItems" @copyAddress="copyAddress" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
const { clipboard } = require("electron");
|
||||
import ContextMenu from "components/menus/contextmenu";
|
||||
|
||||
export default {
|
||||
name: "AddressHeader",
|
||||
components: {
|
||||
ContextMenu
|
||||
},
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
|
@ -60,13 +56,13 @@ export default {
|
|||
}
|
||||
},
|
||||
data() {
|
||||
return {};
|
||||
const menuItems = [{ action: "copyAddress", i18n: "menuItems.copyAddress" }];
|
||||
return {
|
||||
menuItems
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
copyAddress(event) {
|
||||
if (event) {
|
||||
event.stopPropagation();
|
||||
}
|
||||
copyAddress() {
|
||||
if (this.$refs.copy) {
|
||||
this.$refs.copy.$el.blur();
|
||||
}
|
||||
|
|
|
@ -1,228 +0,0 @@
|
|||
<template>
|
||||
<div
|
||||
class="identicon"
|
||||
:style="{
|
||||
backgroundImage: 'url(' + img + ')',
|
||||
width: 8 * size + 'px',
|
||||
height: 8 * size + 'px'
|
||||
}"
|
||||
>
|
||||
<q-menu v-if="menu" context-menu>
|
||||
<q-list separator class="context-menu">
|
||||
<q-item v-close-popup clickable :disabled="img == defaultImg" @click.native="saveIdenticon()">
|
||||
<q-item-section>
|
||||
Save identicon to file
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-menu>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "Identicon",
|
||||
props: {
|
||||
address: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
size: {
|
||||
type: Number,
|
||||
default: 5
|
||||
},
|
||||
menu: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
randseed: new Array(4),
|
||||
img: "",
|
||||
defaultImg:
|
||||
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gkHECkpHU3uFgAAAZlJREFUWMPt2D1PwkAYB/D/AxWIbZUCAvGNwZiAcTG+JQ4sJn4AV7+UfgNXjY6ObrppXBiEGBMUgimKKHDy2jpUUHGTIhe5Z7rc8OTX9p67e0oXu3cmOA4HOA8BFEABFMBhB0q9JnBrEgIxGeqsGx7fCBwSoVExUMpUoV+VwPTG4ICRLQ2BmPJj3qU44Y/K8EdlpE8LeExUBgPU5kZhGiaYXkfmrIhytg6SgMn1cYSWVRARIps+ML3+6zfZE5Dl60gd5b/NmU0ge/6CQpJhYScMAPBFZTC9+PdF0o37GtViE6ZhXZQ8Xom/KiYCQNa4+WbwB5yOe0FkCQspxhcwtKJiYtGq7ucbhtd0dXD7YHeEV1VMbXgBAOVcDbcnT/ycJMElpYOrPNSQPNR5OupMzMS1zvZzfaDbktU2YHht7HP7OdZte2zbgHLI3Rm3aiZ/QHJ+fGjD3i7WNqDTZaUiB/F13WqHHRXbV6BHk0BOAhHA8g3+gPPbQbgUayFe7t3ztwbNVn9+8fz/nqQdif2caDsFUAAFUACHEfgOXvt3FLbL3AsAAAAASUVORK5CYII="
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isDefault: function() {
|
||||
return this.img == this.defaultImg;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
address: function(address) {
|
||||
if (address && this.isAddressValid(address)) {
|
||||
this.createIcon({
|
||||
seed: address,
|
||||
scale: this.size
|
||||
});
|
||||
} else {
|
||||
this.img = this.defaultImg;
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if (this.address && this.isAddressValid(this.address)) {
|
||||
this.createIcon({
|
||||
seed: this.address,
|
||||
scale: 12
|
||||
});
|
||||
} else {
|
||||
this.img = this.defaultImg;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
saveIdenticon() {
|
||||
if (this.img == this.defaultImg) return;
|
||||
this.$gateway.send("core", "save_png", {
|
||||
img: this.img,
|
||||
type: "Identicon"
|
||||
});
|
||||
},
|
||||
|
||||
isAddressValid(input) {
|
||||
if (!/^[0-9A-Za-z]+$/.test(input)) return false;
|
||||
|
||||
switch (input.substring(0, 4)) {
|
||||
case "Sumo":
|
||||
case "RYoL":
|
||||
case "Suto":
|
||||
case "RYoT":
|
||||
return input.length === 99;
|
||||
|
||||
case "Subo":
|
||||
case "Suso":
|
||||
return input.length == 98;
|
||||
|
||||
case "RYoS":
|
||||
case "RYoU":
|
||||
return input.length == 99;
|
||||
|
||||
case "Sumi":
|
||||
case "RYoN":
|
||||
case "Suti":
|
||||
case "RYoE":
|
||||
return input.length === 110;
|
||||
|
||||
case "RYoK":
|
||||
case "RYoH":
|
||||
return input.length === 55;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
seedrand(seed) {
|
||||
for (var i = 0; i < this.randseed.length; i++) {
|
||||
this.randseed[i] = 0;
|
||||
}
|
||||
for (var j = 0; j < seed.length; j++) {
|
||||
this.randseed[j % 4] = (this.randseed[j % 4] << 5) - this.randseed[j % 4] + seed.charCodeAt(j);
|
||||
}
|
||||
},
|
||||
|
||||
rand() {
|
||||
// based on Java's String.hashCode(), expanded to 4 32bit values
|
||||
var t = this.randseed[0] ^ (this.randseed[0] << 11);
|
||||
|
||||
this.randseed[0] = this.randseed[1];
|
||||
this.randseed[1] = this.randseed[2];
|
||||
this.randseed[2] = this.randseed[3];
|
||||
this.randseed[3] = this.randseed[3] ^ (this.randseed[3] >> 19) ^ t ^ (t >> 8);
|
||||
|
||||
return (this.randseed[3] >>> 0) / ((1 << 31) >>> 0);
|
||||
},
|
||||
|
||||
createColor() {
|
||||
//saturation is the whole color spectrum
|
||||
var h = Math.floor(this.rand() * 360);
|
||||
//saturation goes from 40 to 100, it avoids greyish colors
|
||||
var s = this.rand() * 60 + 40 + "%";
|
||||
//lightness can be anything from 0 to 100, but probabilities are a bell curve around 50%
|
||||
var l = (this.rand() + this.rand() + this.rand() + this.rand()) * 25 + "%";
|
||||
|
||||
var color = "hsl(" + h + "," + s + "," + l + ")";
|
||||
return color;
|
||||
},
|
||||
|
||||
createImageData(size) {
|
||||
var width = size; // Only support square icons for now
|
||||
var height = size;
|
||||
|
||||
var dataWidth = Math.ceil(width / 2);
|
||||
var mirrorWidth = width - dataWidth;
|
||||
|
||||
var data = [];
|
||||
for (var y = 0; y < height; y++) {
|
||||
var row = [];
|
||||
for (var x = 0; x < dataWidth; x++) {
|
||||
// this makes foreground and background color to have a 43% (1/2.3) probability
|
||||
// spot color has 13% chance
|
||||
row[x] = Math.floor(this.rand() * 2.3);
|
||||
}
|
||||
var r = row.slice(0, mirrorWidth);
|
||||
r.reverse();
|
||||
row = row.concat(r);
|
||||
|
||||
for (var i = 0; i < row.length; i++) {
|
||||
data.push(row[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
},
|
||||
|
||||
buildOpts(opts) {
|
||||
var newOpts = {};
|
||||
|
||||
newOpts.seed = opts.seed || Math.floor(Math.random() * Math.pow(10, 16)).toString(16);
|
||||
|
||||
this.seedrand(newOpts.seed);
|
||||
|
||||
newOpts.size = opts.size || 8;
|
||||
newOpts.scale = opts.scale || 4;
|
||||
newOpts.color = opts.color || this.createColor();
|
||||
newOpts.bgcolor = opts.bgcolor || this.createColor();
|
||||
newOpts.spotcolor = opts.spotcolor || this.createColor();
|
||||
|
||||
return newOpts;
|
||||
},
|
||||
|
||||
renderIcon(opts, canvas) {
|
||||
opts = this.buildOpts(opts || {});
|
||||
var imageData = this.createImageData(opts.size);
|
||||
var width = Math.sqrt(imageData.length);
|
||||
|
||||
canvas.width = canvas.height = opts.size * opts.scale;
|
||||
|
||||
var cc = canvas.getContext("2d");
|
||||
cc.fillStyle = opts.bgcolor;
|
||||
cc.fillRect(0, 0, canvas.width, canvas.height);
|
||||
cc.fillStyle = opts.color;
|
||||
|
||||
for (var i = 0; i < imageData.length; i++) {
|
||||
// if data is 0, leave the background
|
||||
if (imageData[i]) {
|
||||
var row = Math.floor(i / width);
|
||||
var col = i % width;
|
||||
|
||||
// if data is 2, choose spot color, if 1 choose foreground
|
||||
cc.fillStyle = imageData[i] == 1 ? opts.color : opts.spotcolor;
|
||||
|
||||
cc.fillRect(col * opts.scale, row * opts.scale, opts.scale, opts.scale);
|
||||
}
|
||||
}
|
||||
return canvas;
|
||||
},
|
||||
|
||||
createIcon(opts) {
|
||||
var canvas = document.createElement("canvas");
|
||||
this.renderIcon(opts, canvas);
|
||||
this.img = canvas.toDataURL();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style></style>
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
<script>
|
||||
import { mapState } from "vuex";
|
||||
import LNSInputForm from "components/lns_input_form";
|
||||
import LNSInputForm from "./lns_input_form";
|
||||
import WalletPassword from "src/mixins/wallet_password";
|
||||
const objectAssignDeep = require("object-assign-deep");
|
||||
|
|
@ -40,49 +40,13 @@
|
|||
<q-item-section v-if="!isLocked(record)" side>
|
||||
{{ record.register_height | blockHeight }}
|
||||
</q-item-section>
|
||||
|
||||
<q-menu context-menu>
|
||||
<q-list separator class="context-menu">
|
||||
<template v-if="!isLocked(record)">
|
||||
<q-item
|
||||
v-close-popup
|
||||
clickable
|
||||
@click.native="copy(record.name, $event, $t('notification.positive.nameCopied'))"
|
||||
>
|
||||
<q-item-section>
|
||||
{{ $t("menuItems.copyName") }}
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-item v-close-popup clickable @click.native="copyValue(record, $event)">
|
||||
<q-item-section>
|
||||
{{ record | copyValue }}
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</template>
|
||||
|
||||
<q-item
|
||||
v-close-popup
|
||||
clickable
|
||||
@click.native="copy(record.owner, $event, $t('notification.positive.ownerCopied'))"
|
||||
>
|
||||
<q-item-section>
|
||||
{{ $t("menuItems.copyOwner") }}
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-item
|
||||
v-if="record.backup_owner !== ''"
|
||||
v-close-popup
|
||||
clickable
|
||||
@click.native="copy(record.backup_owner, $event, $t('notification.positive.backupOwnerCopied'))"
|
||||
>
|
||||
<q-item-section>
|
||||
{{ $t("menuItems.copyBackupOwner") }}
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-menu>
|
||||
<ContextMenu
|
||||
:menu-items="validMenuItems(record)"
|
||||
@ownerCopy="copy(record.owner, $t('notification.positive.ownerCopied'))"
|
||||
@nameCopy="copy(record.name, $t('notification.positive.nameCopied'))"
|
||||
@copyValue="copyValue(record)"
|
||||
@backupOwnerCopy="copy(record.backup_owner, $t('notification.positive.backupOwnerCopied'))"
|
||||
/>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</div>
|
||||
|
@ -94,11 +58,13 @@ import { mapState } from "vuex";
|
|||
import { i18n } from "boot/i18n";
|
||||
import LokiField from "components/loki_field";
|
||||
import { lns_name } from "src/validators/common";
|
||||
import ContextMenu from "components/menus/contextmenu";
|
||||
|
||||
export default {
|
||||
name: "LNSRecordList",
|
||||
components: {
|
||||
LokiField
|
||||
LokiField,
|
||||
ContextMenu
|
||||
},
|
||||
filters: {
|
||||
blockHeight(value) {
|
||||
|
@ -150,6 +116,22 @@ export default {
|
|||
}
|
||||
}),
|
||||
methods: {
|
||||
validMenuItems(record) {
|
||||
const lockedItems = [
|
||||
{ action: "nameCopy", i18n: "menuItems.copyName" },
|
||||
{ action: "copyValue", i18n: record | this.copyValue }
|
||||
];
|
||||
let menuItems = [{ action: "ownerCopy", i18n: "menuItems.copyOwner" }];
|
||||
const backupOwnerItem = [{ action: "backupOwnerCopy", i18n: "menuItems.copyBackupOwner" }];
|
||||
|
||||
if (!this.isLocked(record)) {
|
||||
menuItems = [...lockedItems, ...menuItems];
|
||||
}
|
||||
if (record.backup_owner !== "") {
|
||||
menuItems = [...menuItems, ...backupOwnerItem];
|
||||
}
|
||||
return menuItems;
|
||||
},
|
||||
isLocked(record) {
|
||||
return !record.name || !record.value;
|
||||
},
|
||||
|
@ -220,9 +202,7 @@ export default {
|
|||
}
|
||||
this.copy(record.value, event, message);
|
||||
},
|
||||
copy(value, event, message) {
|
||||
event.stopPropagation();
|
||||
this.blurEventButton(event);
|
||||
copy(value, message) {
|
||||
if (!value) return;
|
||||
clipboard.writeText(value.trim());
|
||||
this.$q.notify({
|
|
@ -0,0 +1,39 @@
|
|||
<template>
|
||||
<q-menu context-menu>
|
||||
<q-list separator class="context-menu-list">
|
||||
<div v-for="(item, index) in menuItems" :key="index">
|
||||
<ContextMenuItem :action="item.action" :i18n="item.i18n" @clicked="clickedMenu(item)" />
|
||||
</div>
|
||||
</q-list>
|
||||
</q-menu>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ContextMenuItem from "./contextmenu_item";
|
||||
|
||||
export default {
|
||||
name: "ContextMenu",
|
||||
components: {
|
||||
ContextMenuItem
|
||||
},
|
||||
props: {
|
||||
menuItems: {
|
||||
type: Array,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
clickedMenu(item) {
|
||||
this.$emit(item.action);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.context-menu-list {
|
||||
min-width: 150px;
|
||||
max-height: 300px;
|
||||
color: white;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,30 @@
|
|||
<template>
|
||||
<q-item v-close-popup clickable @click.native="clickedItem">
|
||||
<q-item-section>
|
||||
{{ $t(i18n) }}
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "ContextMenuItem",
|
||||
props: {
|
||||
action: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
i18n: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
clickedItem() {
|
||||
this.$emit("clicked");
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style></style>
|
|
@ -51,7 +51,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { version } from "../../package.json";
|
||||
import { version } from "../../../package.json";
|
||||
import { mapState } from "vuex";
|
||||
import SettingsModal from "components/settings";
|
||||
export default {
|
|
@ -46,27 +46,18 @@
|
|||
</q-item-section>
|
||||
</q-item>
|
||||
</template>
|
||||
<q-menu context-menu>
|
||||
<q-list separator class="context-menu">
|
||||
<q-item v-close-popup clickable @click.native="details(address)">
|
||||
<q-item-section>
|
||||
{{ $t("menuItems.showDetails") }}
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-item v-close-popup clickable @click.native="copyAddress(address.address, $event)">
|
||||
<q-item-section>
|
||||
{{ $t("menuItems.copyAddress") }}
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-menu>
|
||||
<ContextMenu :menu-items="menuItems" @showDetails="details(address)" @copyAddress="copyAddress(address.address)" />
|
||||
</q-list>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ContextMenu from "components/menus/contextmenu";
|
||||
|
||||
export default {
|
||||
name: "ReceiveItem",
|
||||
components: {
|
||||
ContextMenu
|
||||
},
|
||||
filters: {
|
||||
toString: function(value) {
|
||||
if (typeof value !== "number") return "N/A";
|
||||
|
@ -112,6 +103,15 @@ export default {
|
|||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
const menuItems = [
|
||||
{ action: "showDetails", i18n: "menuItems.showDetails" },
|
||||
{ action: "copyAddress", i18n: "menuItems.copyAddress" }
|
||||
];
|
||||
return {
|
||||
menuItems
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
qrImage() {
|
||||
const image = this.whiteQRIcon ? "qr-code" : "qr-code-grey";
|
||||
|
|
|
@ -110,15 +110,7 @@
|
|||
<FormatLoki :amount="contributor.amount" raw-value />
|
||||
</q-item-label>
|
||||
</q-item-label>
|
||||
<q-menu context-menu>
|
||||
<q-list separator class="context-menu">
|
||||
<q-item v-close-popup @click.native="copyAddress(contributor.address, $event)">
|
||||
<q-item-section>
|
||||
{{ $t("menuItems.copyAddress") }}
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-menu>
|
||||
<ContextMenu :menu-items="menuItems" @copyAddress="copyAddress(contributor.address)" />
|
||||
</q-item>
|
||||
</q-list>
|
||||
</div>
|
||||
|
@ -136,10 +128,12 @@ const { clipboard } = require("electron");
|
|||
import { mapState } from "vuex";
|
||||
import { date } from "quasar";
|
||||
import FormatLoki from "components/format_loki";
|
||||
import ContextMenu from "components/menus/contextmenu";
|
||||
export default {
|
||||
name: "ServiceNodeDetails",
|
||||
components: {
|
||||
FormatLoki
|
||||
FormatLoki,
|
||||
ContextMenu
|
||||
},
|
||||
props: {
|
||||
unlock: {
|
||||
|
@ -148,9 +142,12 @@ export default {
|
|||
}
|
||||
},
|
||||
data() {
|
||||
const menuItems = [{ action: "copyAddress", i18n: "menuItems.copyAddress" }];
|
||||
|
||||
return {
|
||||
isVisible: false,
|
||||
node: {}
|
||||
node: {},
|
||||
menuItems
|
||||
};
|
||||
},
|
||||
computed: mapState({
|
||||
|
@ -200,14 +197,7 @@ export default {
|
|||
formatDate(timestamp) {
|
||||
return date.formatDate(timestamp, "YYYY-MM-DD hh:mm a");
|
||||
},
|
||||
copyAddress(address, event) {
|
||||
event.stopPropagation();
|
||||
for (let i = 0; i < event.path.length; i++) {
|
||||
if (event.path[i].tagName == "BUTTON") {
|
||||
event.path[i].blur();
|
||||
break;
|
||||
}
|
||||
}
|
||||
copyAddress(address) {
|
||||
clipboard.writeText(address);
|
||||
this.$q.notify({
|
||||
type: "positive",
|
|
@ -58,7 +58,7 @@ import { required, decimal } from "vuelidate/lib/validators";
|
|||
import { service_node_key, greater_than_zero } from "src/validators/common";
|
||||
import LokiField from "components/loki_field";
|
||||
import WalletPassword from "src/mixins/wallet_password";
|
||||
import ServiceNodeUnlock from "components/service_node_unlock";
|
||||
import ServiceNodeUnlock from "./service_node_unlock";
|
||||
|
||||
export default {
|
||||
name: "ServiceNodeStaking",
|
|
@ -31,20 +31,11 @@
|
|||
}}
|
||||
</q-item-label>
|
||||
</q-item-section>
|
||||
<q-menu context-menu>
|
||||
<q-list separator class="context-menu">
|
||||
<q-item v-close-popup clickable @click.native="copyKey(node.service_node_pubkey, $event)">
|
||||
<q-item-section>
|
||||
{{ $t("menuItems.copyServiceNodeKey") }}
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item v-close-popup clickable @click.native="openExplorer(node.service_node_pubkey)">
|
||||
<q-item-section>
|
||||
{{ $t("menuItems.viewOnExplorer") }}
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-menu>
|
||||
<ContextMenu
|
||||
:menu-items="menuItems"
|
||||
@viewOnExplorer="openExplorer(node.service_node_pubkey)"
|
||||
@copyServiceNodeKey="copyKey(node.service_node_pubkey)"
|
||||
/>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</div>
|
||||
|
@ -64,15 +55,26 @@ import { required } from "vuelidate/lib/validators";
|
|||
import { service_node_key } from "src/validators/common";
|
||||
import WalletPassword from "src/mixins/wallet_password";
|
||||
import FormatLoki from "components/format_loki";
|
||||
import ServiceNodeDetails from "components/service_node_details";
|
||||
import ServiceNodeDetails from "./service_node_details";
|
||||
import ContextMenu from "components/menus/contextmenu";
|
||||
|
||||
export default {
|
||||
name: "ServiceNodeUnlock",
|
||||
components: {
|
||||
FormatLoki,
|
||||
ServiceNodeDetails
|
||||
ServiceNodeDetails,
|
||||
ContextMenu
|
||||
},
|
||||
mixins: [WalletPassword],
|
||||
data() {
|
||||
const menuItems = [
|
||||
{ action: "copyServiceNodeKey", i18n: "menuItems.copyServiceNodeKey" },
|
||||
{ action: "viewOnExplorer", i18n: "menuItems.viewOnExplorer" }
|
||||
];
|
||||
return {
|
||||
menuItems
|
||||
};
|
||||
},
|
||||
computed: mapState({
|
||||
theme: state => state.gateway.app.config.appearance.theme,
|
||||
unlock_status: state => state.gateway.service_node_status.unlock,
|
||||
|
@ -226,14 +228,7 @@ export default {
|
|||
confirmed
|
||||
});
|
||||
},
|
||||
copyKey(key, event) {
|
||||
event.stopPropagation();
|
||||
for (let i = 0; i < event.path.length; i++) {
|
||||
if (event.path[i].tagName == "BUTTON") {
|
||||
event.path[i].blur();
|
||||
break;
|
||||
}
|
||||
}
|
||||
copyKey(key) {
|
||||
clipboard.writeText(key);
|
||||
this.$q.notify({
|
||||
type: "positive",
|
|
@ -132,16 +132,7 @@
|
|||
<q-item-label class="non-selectable">{{ in_tx_address_used.address_index_text }}</q-item-label>
|
||||
<q-item-label class="monospace ellipsis">{{ in_tx_address_used.address }}</q-item-label>
|
||||
</q-item-label>
|
||||
|
||||
<q-menu context-menu>
|
||||
<q-list separator class="context-menu">
|
||||
<q-item v-close-popup clickable @click.native="copyAddress(in_tx_address_used.address, $event)">
|
||||
<q-item-section>
|
||||
{{ $t("menuItems.copyAddress") }}
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-menu>
|
||||
<ContextMenu :menu-items="menuItems" @copyAddress="copyAddress(in_tx_address_used.address)" />
|
||||
</q-item>
|
||||
</q-list>
|
||||
</div>
|
||||
|
@ -162,15 +153,7 @@
|
|||
<q-item-label class="monospace ellipsis">{{ destination.address }}</q-item-label>
|
||||
<q-item-label><FormatLoki :amount="destination.amount"/></q-item-label>
|
||||
</q-item-label>
|
||||
<q-menu context-menu>
|
||||
<q-list separator class="context-menu">
|
||||
<q-item v-close-popup clickable @click.native="copyAddress(destination.address, $event)">
|
||||
<q-item-section>
|
||||
{{ $t("menuItems.copyAddress") }}
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-menu>
|
||||
<ContextMenu :menu-items="menuItems" @copyAddress="copyAddress(destination.address)" />
|
||||
</q-item>
|
||||
</template>
|
||||
<template v-else>
|
||||
|
@ -212,13 +195,16 @@ import { mapState } from "vuex";
|
|||
import { date } from "quasar";
|
||||
import TxTypeIcon from "components/tx_type_icon";
|
||||
import FormatLoki from "components/format_loki";
|
||||
import ContextMenu from "components/menus/contextmenu";
|
||||
export default {
|
||||
name: "TxDetails",
|
||||
components: {
|
||||
TxTypeIcon,
|
||||
FormatLoki
|
||||
FormatLoki,
|
||||
ContextMenu
|
||||
},
|
||||
data() {
|
||||
const menuItems = [{ action: "copyAddress", i18n: "menuItems.copyAddress" }];
|
||||
return {
|
||||
isVisible: false,
|
||||
txNotes: "",
|
||||
|
@ -235,7 +221,8 @@ export default {
|
|||
txid: "",
|
||||
type: "",
|
||||
unlock_time: 0
|
||||
}
|
||||
},
|
||||
menuItems
|
||||
};
|
||||
},
|
||||
computed: mapState({
|
||||
|
@ -331,14 +318,7 @@ export default {
|
|||
formatDate(timestamp) {
|
||||
return date.formatDate(timestamp, "YYYY-MM-DD hh:mm a");
|
||||
},
|
||||
copyAddress(address, event) {
|
||||
event.stopPropagation();
|
||||
for (let i = 0; i < event.path.length; i++) {
|
||||
if (event.path[i].tagName == "BUTTON") {
|
||||
event.path[i].blur();
|
||||
break;
|
||||
}
|
||||
}
|
||||
copyAddress(address) {
|
||||
clipboard.writeText(address);
|
||||
this.$q.notify({
|
||||
type: "positive",
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
</q-item-section>
|
||||
<q-item-label class="main">
|
||||
<q-item-label class="amount">
|
||||
<FormatLoki :amount="tx.amount" />
|
||||
<FormatLoki :amount="tx.amount || 0" />
|
||||
</q-item-label>
|
||||
<q-item-label caption>{{ tx.txid }}</q-item-label>
|
||||
</q-item-label>
|
||||
|
@ -31,28 +31,12 @@
|
|||
</q-item-label>
|
||||
<q-item-label caption>{{ formatHeight(tx) }}</q-item-label>
|
||||
</q-item-section>
|
||||
|
||||
<q-menu context-menu>
|
||||
<q-list separator style="min-width: 150px; max-height: 300px;">
|
||||
<q-item v-close-popup clickable @click.native="details(tx)">
|
||||
<q-item-section>
|
||||
{{ $t("menuItems.showDetails") }}
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-item v-close-popup clickable @click.native="copyTxid(tx.txid, $event)">
|
||||
<q-item-section>
|
||||
{{ $t("menuItems.copyTransactionId") }}
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-item v-close-popup clickable @click.native="openExplorer(tx.txid)">
|
||||
<q-item-section>
|
||||
{{ $t("menuItems.viewOnExplorer") }}
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-menu>
|
||||
<ContextMenu
|
||||
:menu-items="menuItems"
|
||||
@copyTxId="copyTxId(tx.txid)"
|
||||
@showDetails="details(tx)"
|
||||
@openExplorer="openExplorer(tx.txid)"
|
||||
/>
|
||||
</q-item>
|
||||
<QSpinnerDots slot="message" :size="40"></QSpinnerDots>
|
||||
</q-list>
|
||||
|
@ -70,6 +54,7 @@ import { QSpinnerDots } from "quasar";
|
|||
import TxDetails from "components/tx_details";
|
||||
import FormatLoki from "components/format_loki";
|
||||
import { i18n } from "boot/i18n";
|
||||
import ContextMenu from "components/menus/contextmenu";
|
||||
|
||||
export default {
|
||||
name: "TxList",
|
||||
|
@ -101,7 +86,8 @@ export default {
|
|||
components: {
|
||||
QSpinnerDots,
|
||||
TxDetails,
|
||||
FormatLoki
|
||||
FormatLoki,
|
||||
ContextMenu
|
||||
},
|
||||
props: {
|
||||
limit: {
|
||||
|
@ -131,10 +117,16 @@ export default {
|
|||
}
|
||||
},
|
||||
data() {
|
||||
const menuItems = [
|
||||
{ action: "showDetails", i18n: "menuItems.showDetails" },
|
||||
{ action: "copyTxId", i18n: "menuItems.copyTransactionId" },
|
||||
{ action: "openExplorer", i18n: "menuItems.viewOnExplorer" }
|
||||
];
|
||||
return {
|
||||
page: 0,
|
||||
tx_list_filtered: [],
|
||||
tx_list_paged: []
|
||||
tx_list_paged: [],
|
||||
menuItems
|
||||
};
|
||||
},
|
||||
computed: mapState({
|
||||
|
@ -291,14 +283,7 @@ export default {
|
|||
return this.$t("strings.blockHeight") + `: ${height} (${confirms} confirm${confirms == 1 ? "" : "s"})`;
|
||||
else return this.$t("strings.blockHeight") + `: ${height} (${this.$t("strings.transactionConfirmed")})`;
|
||||
},
|
||||
copyTxid(txid, event) {
|
||||
event.stopPropagation();
|
||||
for (let i = 0; i < event.path.length; i++) {
|
||||
if (event.path[i].tagName == "BUTTON") {
|
||||
event.path[i].blur();
|
||||
break;
|
||||
}
|
||||
}
|
||||
copyTxId(txid) {
|
||||
clipboard.writeText(txid);
|
||||
this.$q.notify({
|
||||
type: "positive",
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
<script>
|
||||
import { mapState } from "vuex";
|
||||
import FormatLoki from "components/format_loki";
|
||||
import WalletSettings from "components/wallet_settings";
|
||||
import WalletSettings from "components/menus/wallet_settings";
|
||||
import CopyIcon from "components/icons/copy_icon";
|
||||
export default {
|
||||
name: "WalletDetails",
|
||||
|
|
|
@ -367,12 +367,6 @@ footer,
|
|||
}
|
||||
}
|
||||
|
||||
.context-menu {
|
||||
min-width: 150px;
|
||||
max-height: 300px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.menu-list {
|
||||
.q-item * {
|
||||
color: white;
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
<script>
|
||||
import StatusFooter from "components/footer";
|
||||
import MainMenu from "components/mainmenu";
|
||||
import MainMenu from "components/menus/mainmenu";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
|
|
@ -59,7 +59,7 @@ import { openURL } from "quasar";
|
|||
import { mapState } from "vuex";
|
||||
import WalletDetails from "components/wallet_details";
|
||||
import StatusFooter from "components/footer";
|
||||
import MainMenu from "components/mainmenu";
|
||||
import MainMenu from "components/menus/mainmenu";
|
||||
export default {
|
||||
name: "LayoutDefault",
|
||||
components: {
|
||||
|
|
|
@ -115,6 +115,12 @@ export default {
|
|||
}
|
||||
},
|
||||
methods: {
|
||||
createWallet() {
|
||||
this.$q.loading.show({
|
||||
delay: 0
|
||||
});
|
||||
this.$gateway.send("wallet", "create_wallet", this.wallet);
|
||||
},
|
||||
create() {
|
||||
this.$v.wallet.$touch();
|
||||
|
||||
|
@ -136,10 +142,8 @@ export default {
|
|||
}
|
||||
|
||||
// Warn user if no password is set
|
||||
let passwordPromise = Promise.resolve();
|
||||
if (!this.wallet.password) {
|
||||
// TODO: Password box de-duplicate across components
|
||||
passwordPromise = this.$q.dialog({
|
||||
const passwordPromise = this.$q.dialog({
|
||||
title: this.$t("dialog.noPassword.title"),
|
||||
message: this.$t("dialog.noPassword.message"),
|
||||
ok: {
|
||||
|
@ -153,17 +157,15 @@ export default {
|
|||
dark: this.theme == "dark",
|
||||
color: "positive"
|
||||
});
|
||||
passwordPromise
|
||||
.onOk(() => {
|
||||
this.createWallet();
|
||||
})
|
||||
.onDismiss(() => {})
|
||||
.onCancel(() => {});
|
||||
} else {
|
||||
this.createWallet();
|
||||
}
|
||||
|
||||
passwordPromise
|
||||
.onOk(() => {
|
||||
this.$q.loading.show({
|
||||
delay: 0
|
||||
});
|
||||
this.$gateway.send("wallet", "create_wallet", this.wallet);
|
||||
})
|
||||
.onDismiss(() => {})
|
||||
.onCancel(() => {});
|
||||
},
|
||||
cancel() {
|
||||
this.$router.replace({ path: "/wallet-select" });
|
||||
|
|
|
@ -58,21 +58,11 @@
|
|||
<q-item-label class="wallet-name" caption>{{ wallet.name }}</q-item-label>
|
||||
<q-item-label class="monospace ellipsis" caption>{{ wallet.address }}</q-item-label>
|
||||
</q-item-section>
|
||||
<q-menu context-menu>
|
||||
<q-list separator class="context-menu">
|
||||
<q-item v-close-popup clickable @click.native="openWallet(wallet)">
|
||||
<q-item-section>
|
||||
{{ $t("menuItems.openWallet") }}
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-item v-close-popup clickable @click.native="copyAddress(wallet.address, $event)">
|
||||
<q-item-section>
|
||||
{{ $t("menuItems.copyAddress") }}
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-menu>
|
||||
<ContextMenu
|
||||
:menu-items="menuItems"
|
||||
@openWallet="openWallet(wallet)"
|
||||
@copyAddress="copyAddress(wallet.address)"
|
||||
/>
|
||||
</q-item>
|
||||
<q-separator />
|
||||
</template>
|
||||
|
@ -90,8 +80,21 @@
|
|||
<script>
|
||||
const { clipboard } = require("electron");
|
||||
import { mapState } from "vuex";
|
||||
import ContextMenu from "components/menus/contextmenu";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ContextMenu
|
||||
},
|
||||
data() {
|
||||
const menuItems = [
|
||||
{ action: "openWallet", i18n: "menuItems.openWallet" },
|
||||
{ action: "copyAddress", i18n: "menuItems.copyAddress" }
|
||||
];
|
||||
return {
|
||||
menuItems
|
||||
};
|
||||
},
|
||||
computed: mapState({
|
||||
theme: state => state.gateway.app.config.appearance.theme,
|
||||
wallets: state => state.gateway.wallets,
|
||||
|
@ -220,14 +223,7 @@ export default {
|
|||
importLegacyWallet() {
|
||||
this.$router.replace({ path: "wallet-select/import-legacy" });
|
||||
},
|
||||
copyAddress(address, event) {
|
||||
event.stopPropagation();
|
||||
for (let i = 0; i < event.path.length; i++) {
|
||||
if (event.path[i].tagName == "BUTTON") {
|
||||
event.path[i].blur();
|
||||
break;
|
||||
}
|
||||
}
|
||||
copyAddress(address) {
|
||||
clipboard.writeText(address);
|
||||
this.$q.notify({
|
||||
type: "positive",
|
||||
|
|
|
@ -28,28 +28,12 @@
|
|||
/>
|
||||
</q-item-label>
|
||||
</q-item-section>
|
||||
|
||||
<q-menu context-menu>
|
||||
<q-list class="context-menu">
|
||||
<q-item v-close-popup clickable @click.native="details(entry)">
|
||||
<q-item-section>
|
||||
{{ $t("menuItems.showDetails") }}
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-item v-close-popup clickable @click.native="sendToAddress(entry, $event)">
|
||||
<q-item-section>
|
||||
{{ $t("menuItems.sendToThisAddress") }}
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-item v-close-popup clickable @click.native="copyAddress(entry, $event)">
|
||||
<q-item-section>
|
||||
{{ $t("menuItems.copyAddress") }}
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-menu>
|
||||
<ContextMenu
|
||||
:menu-items="menuItems"
|
||||
@showDetails="details(entry)"
|
||||
@sendToAddress="sendToAddress(entry)"
|
||||
@copyAddress="copyAddress(entry)"
|
||||
/>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</template>
|
||||
|
@ -68,9 +52,21 @@
|
|||
const { clipboard } = require("electron");
|
||||
import { mapState } from "vuex";
|
||||
import AddressBookDetails from "components/address_book_details";
|
||||
import ContextMenu from "components/menus/contextmenu";
|
||||
export default {
|
||||
components: {
|
||||
AddressBookDetails
|
||||
AddressBookDetails,
|
||||
ContextMenu
|
||||
},
|
||||
data() {
|
||||
const menuItems = [
|
||||
{ action: "showDetails", i18n: "menuItems.showDetails" },
|
||||
{ action: "sendToAddress", i18n: "menuItems.sendToThisAddress" },
|
||||
{ action: "copyAddress", i18n: "menuItems.copyAddress" }
|
||||
];
|
||||
return {
|
||||
menuItems
|
||||
};
|
||||
},
|
||||
computed: mapState({
|
||||
theme: state => state.gateway.app.config.appearance.theme,
|
||||
|
@ -99,14 +95,7 @@ export default {
|
|||
this.$refs.addressBookDetails.mode = "new";
|
||||
this.$refs.addressBookDetails.isVisible = true;
|
||||
},
|
||||
sendToAddress(address, event) {
|
||||
event.stopPropagation();
|
||||
for (let i = 0; i < event.path.length; i++) {
|
||||
if (event.path[i].tagName == "BUTTON") {
|
||||
event.path[i].blur();
|
||||
break;
|
||||
}
|
||||
}
|
||||
sendToAddress(address) {
|
||||
this.$router.replace({
|
||||
path: "send",
|
||||
query: {
|
||||
|
@ -115,14 +104,7 @@ export default {
|
|||
}
|
||||
});
|
||||
},
|
||||
copyAddress(entry, event) {
|
||||
event.stopPropagation();
|
||||
for (let i = 0; i < event.path.length; i++) {
|
||||
if (event.path[i].tagName == "BUTTON") {
|
||||
event.path[i].blur();
|
||||
break;
|
||||
}
|
||||
}
|
||||
copyAddress(entry) {
|
||||
clipboard.writeText(entry.address);
|
||||
if (entry.payment_id) {
|
||||
this.$q
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import LNSInput from "components/lns_input";
|
||||
import LNSRecordList from "components/lns_record_list";
|
||||
import LNSInput from "components/lns/lns_input";
|
||||
import LNSRecordList from "components/lns/lns_record_list";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
|
|
@ -57,21 +57,7 @@
|
|||
<q-card class="qr-code-card">
|
||||
<div class="text-center q-mb-sm q-pa-md" style="background: white;">
|
||||
<QrcodeVue ref="qr" :value="QR.address" size="240"> </QrcodeVue>
|
||||
<!-- This menu appears on right click of QR code -->
|
||||
<q-menu context-menu>
|
||||
<q-list class="context-menu">
|
||||
<q-item v-close-popup clickable @click.native="copyQR()">
|
||||
<q-item-section>
|
||||
{{ $t("menuItems.copyQR") }}
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item v-close-popup clickable @click.native="saveQR()">
|
||||
<q-item-section>
|
||||
{{ $t("menuItems.saveQR") }}
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-menu>
|
||||
<ContextMenu :menu-items="menuItems" @copyQR="copyQR()" @saveQR="saveQR()" />
|
||||
</div>
|
||||
<q-card-actions>
|
||||
<q-btn color="primary" :label="$t('buttons.close')" @click="QR.visible = false" />
|
||||
|
@ -88,6 +74,7 @@ import { mapState } from "vuex";
|
|||
import QrcodeVue from "qrcode.vue";
|
||||
import AddressDetails from "components/address_details";
|
||||
import ReceiveItem from "components/receive_item";
|
||||
import ContextMenu from "components/menus/contextmenu";
|
||||
|
||||
export default {
|
||||
filters: {
|
||||
|
@ -105,14 +92,20 @@ export default {
|
|||
components: {
|
||||
AddressDetails,
|
||||
QrcodeVue,
|
||||
ReceiveItem
|
||||
ReceiveItem,
|
||||
ContextMenu
|
||||
},
|
||||
data() {
|
||||
const menuItems = [
|
||||
{ action: "copyQR", i18n: "menuItems.copyQR" },
|
||||
{ action: "saveQR", i18n: "menuItems.saveQR" }
|
||||
];
|
||||
return {
|
||||
QR: {
|
||||
visible: false,
|
||||
address: null
|
||||
}
|
||||
},
|
||||
menuItems
|
||||
};
|
||||
},
|
||||
computed: mapState({
|
||||
|
@ -143,15 +136,7 @@ export default {
|
|||
let img = this.$refs.qr.$el.childNodes[0].toDataURL();
|
||||
this.$gateway.send("core", "save_png", { img, type: "QR Code" });
|
||||
},
|
||||
copyAddress(address, event) {
|
||||
event.stopPropagation();
|
||||
|
||||
for (let i = 0; i < event.path.length; i++) {
|
||||
if (event.path[i].tagName == "BUTTON") {
|
||||
event.path[i].blur();
|
||||
break;
|
||||
}
|
||||
}
|
||||
copyAddress(address) {
|
||||
clipboard.writeText(address);
|
||||
this.$q.notify({
|
||||
type: "positive",
|
||||
|
|
|
@ -338,7 +338,6 @@ export default {
|
|||
};
|
||||
},
|
||||
onConfirmTransaction() {
|
||||
console.log("Confirming transaction");
|
||||
// put the loading spinner up
|
||||
this.$store.commit("gateway/set_tx_status", {
|
||||
code: DO_NOTHING,
|
||||
|
|
|
@ -23,8 +23,8 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import ServiceNodeStaking from "components/service_node_staking";
|
||||
import ServiceNodeRegistration from "components/service_node_registration";
|
||||
import ServiceNodeStaking from "components/service_node/service_node_staking";
|
||||
import ServiceNodeRegistration from "components/service_node/service_node_registration";
|
||||
export default {
|
||||
components: {
|
||||
ServiceNodeStaking,
|
||||
|
|
Loading…
Reference in New Issue