forked from Qortal/qortal-ui
Update deps and upgrade to latest vaadin. Minor fixes
This commit is contained in:
parent
4f5d3ad138
commit
fcdd4c99ea
@ -9,139 +9,139 @@ const path = require("path");
|
||||
const alias = require("@rollup/plugin-alias");
|
||||
|
||||
const aliases = {
|
||||
// 'qortal-ui-crypto': 'node_modules/qortal-ui-crypto/api.js'
|
||||
// 'qortal-ui-crypto': 'node_modules/qortal-ui-crypto/api.js'
|
||||
};
|
||||
|
||||
const generateRollupConfig = (inputFile, outputFile) => {
|
||||
return {
|
||||
inputOptions: {
|
||||
onwarn: (warning, rollupWarn) => {
|
||||
if (warning.code !== "CIRCULAR_DEPENDENCY") {
|
||||
rollupWarn(warning);
|
||||
}
|
||||
},
|
||||
input: inputFile,
|
||||
plugins: [
|
||||
alias({
|
||||
// entries: {}
|
||||
entries: Object.keys(aliases).map((find) => {
|
||||
return {
|
||||
find,
|
||||
replacement: aliases[find],
|
||||
};
|
||||
}),
|
||||
}),
|
||||
nodeResolve({
|
||||
preferBuiltins: false,
|
||||
mainFields: ['module', 'browser']
|
||||
}),
|
||||
replace({
|
||||
preventAssignment: true,
|
||||
"process.env.NODE_ENV": JSON.stringify("production"),
|
||||
}),
|
||||
commonjs(),
|
||||
globals(),
|
||||
progress(),
|
||||
babel.babel({
|
||||
babelHelpers: 'bundled',
|
||||
exclude: "node_modules/**",
|
||||
}),
|
||||
terser({
|
||||
compress: true,
|
||||
output: {
|
||||
comments: false,
|
||||
},
|
||||
})
|
||||
],
|
||||
},
|
||||
outputOptions: {
|
||||
file: outputFile,
|
||||
format: "umd",
|
||||
},
|
||||
};
|
||||
return {
|
||||
inputOptions: {
|
||||
onwarn(warning, warn) {
|
||||
if (warning.code === 'THIS_IS_UNDEFINED') return;
|
||||
if (warning.code !== 'CIRCULAR_DEPENDENCY') throw new Error(warning.message);
|
||||
warn(warning);
|
||||
},
|
||||
input: inputFile,
|
||||
plugins: [
|
||||
alias({
|
||||
// entries: {}
|
||||
entries: Object.keys(aliases).map((find) => {
|
||||
return {
|
||||
find,
|
||||
replacement: aliases[find],
|
||||
};
|
||||
}),
|
||||
}),
|
||||
nodeResolve({
|
||||
preferBuiltins: false,
|
||||
mainFields: ['module', 'browser']
|
||||
}),
|
||||
replace({
|
||||
preventAssignment: true,
|
||||
"process.env.NODE_ENV": JSON.stringify("production"),
|
||||
}),
|
||||
commonjs(),
|
||||
globals(),
|
||||
progress(),
|
||||
babel.babel({
|
||||
babelHelpers: 'bundled',
|
||||
exclude: "node_modules/**",
|
||||
}),
|
||||
terser({
|
||||
compress: true,
|
||||
output: {
|
||||
comments: false,
|
||||
},
|
||||
})
|
||||
],
|
||||
},
|
||||
outputOptions: {
|
||||
file: outputFile,
|
||||
format: "umd",
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const generateForPlugins = () => {
|
||||
const configs = [
|
||||
{
|
||||
in: "plugins/core/main.src.js",
|
||||
out: "plugins/core/main.js",
|
||||
},
|
||||
{
|
||||
in: "plugins/core/trade-portal/trade-portal.src.js",
|
||||
out: "plugins/core/trade-portal/trade-portal.js",
|
||||
},
|
||||
{
|
||||
in: "plugins/core/send-coin/send-coin.src.js",
|
||||
out: "plugins/core/send-coin/send-coin.js",
|
||||
},
|
||||
{
|
||||
in: "plugins/core/wallet/wallet-app.src.js",
|
||||
out: "plugins/core/wallet/wallet-app.js",
|
||||
},
|
||||
{
|
||||
in: "plugins/core/reward-share/reward-share.src.js",
|
||||
out: "plugins/core/reward-share/reward-share.js",
|
||||
},
|
||||
{
|
||||
in: "plugins/core/node-management/node-management.src.js",
|
||||
out: "plugins/core/node-management/node-management.js",
|
||||
},
|
||||
{
|
||||
in: "plugins/core/group-management/group-management.src.js",
|
||||
out: "plugins/core/group-management/group-management.js",
|
||||
},
|
||||
// {
|
||||
// in: 'plugins/core/group-management/group-transaction/group-transaction.src.js',
|
||||
// out: 'plugins/core/group-management/group-transaction/group-transaction.js'
|
||||
// },
|
||||
{
|
||||
in: "plugins/core/name-registration/name-registration.src.js",
|
||||
out: "plugins/core/name-registration/name-registration.js",
|
||||
},
|
||||
{
|
||||
in: "plugins/core/qdn/websites.src.js",
|
||||
out: "plugins/core/qdn/websites.js",
|
||||
},
|
||||
{
|
||||
in: "plugins/core/qdn/publish/publish.src.js",
|
||||
out: "plugins/core/qdn/publish/publish.js",
|
||||
},
|
||||
{
|
||||
in: "plugins/core/qdn/browser/browser.src.js",
|
||||
out: "plugins/core/qdn/browser/browser.js",
|
||||
},
|
||||
{
|
||||
in: "plugins/core/qdn/data-management/data-management.src.js",
|
||||
out: "plugins/core/qdn/data-management/data-management.js",
|
||||
},
|
||||
{
|
||||
in: "plugins/core/messaging/messaging.src.js",
|
||||
out: "plugins/core/messaging/messaging.js",
|
||||
},
|
||||
{
|
||||
in: "plugins/core/messaging/chain-messaging/chain-messaging.src.js",
|
||||
out: "plugins/core/messaging/chain-messaging/chain-messaging.js",
|
||||
},
|
||||
{
|
||||
in: "plugins/core/messaging/q-chat/q-chat.src.js",
|
||||
out: "plugins/core/messaging/q-chat/q-chat.js",
|
||||
},
|
||||
{
|
||||
in: "plugins/core/minting/minting-info.src.js",
|
||||
out: "plugins/core/minting/minting-info.js",
|
||||
},
|
||||
{
|
||||
in: "plugins/core/puzzles/puzzles.src.js",
|
||||
out: "plugins/core/puzzles/puzzles.js",
|
||||
},
|
||||
].map((file) => {
|
||||
return generateRollupConfig(
|
||||
path.join(__dirname, file.in),
|
||||
path.join(__dirname, file.out)
|
||||
);
|
||||
});
|
||||
const configs = [
|
||||
{
|
||||
in: "plugins/core/main.src.js",
|
||||
out: "plugins/core/main.js",
|
||||
},
|
||||
{
|
||||
in: "plugins/core/trade-portal/trade-portal.src.js",
|
||||
out: "plugins/core/trade-portal/trade-portal.js",
|
||||
},
|
||||
{
|
||||
in: "plugins/core/send-coin/send-coin.src.js",
|
||||
out: "plugins/core/send-coin/send-coin.js",
|
||||
},
|
||||
{
|
||||
in: "plugins/core/wallet/wallet-app.src.js",
|
||||
out: "plugins/core/wallet/wallet-app.js",
|
||||
},
|
||||
{
|
||||
in: "plugins/core/reward-share/reward-share.src.js",
|
||||
out: "plugins/core/reward-share/reward-share.js",
|
||||
},
|
||||
{
|
||||
in: "plugins/core/node-management/node-management.src.js",
|
||||
out: "plugins/core/node-management/node-management.js",
|
||||
},
|
||||
{
|
||||
in: "plugins/core/group-management/group-management.src.js",
|
||||
out: "plugins/core/group-management/group-management.js",
|
||||
},
|
||||
// {
|
||||
// in: 'plugins/core/group-management/group-transaction/group-transaction.src.js',
|
||||
// out: 'plugins/core/group-management/group-transaction/group-transaction.js'
|
||||
// },
|
||||
{
|
||||
in: "plugins/core/name-registration/name-registration.src.js",
|
||||
out: "plugins/core/name-registration/name-registration.js",
|
||||
},
|
||||
{
|
||||
in: "plugins/core/qdn/websites.src.js",
|
||||
out: "plugins/core/qdn/websites.js",
|
||||
},
|
||||
{
|
||||
in: "plugins/core/qdn/publish/publish.src.js",
|
||||
out: "plugins/core/qdn/publish/publish.js",
|
||||
},
|
||||
{
|
||||
in: "plugins/core/qdn/browser/browser.src.js",
|
||||
out: "plugins/core/qdn/browser/browser.js",
|
||||
},
|
||||
{
|
||||
in: "plugins/core/qdn/data-management/data-management.src.js",
|
||||
out: "plugins/core/qdn/data-management/data-management.js",
|
||||
},
|
||||
{
|
||||
in: "plugins/core/messaging/messaging.src.js",
|
||||
out: "plugins/core/messaging/messaging.js",
|
||||
},
|
||||
{
|
||||
in: "plugins/core/messaging/chain-messaging/chain-messaging.src.js",
|
||||
out: "plugins/core/messaging/chain-messaging/chain-messaging.js",
|
||||
},
|
||||
{
|
||||
in: "plugins/core/messaging/q-chat/q-chat.src.js",
|
||||
out: "plugins/core/messaging/q-chat/q-chat.js",
|
||||
},
|
||||
{
|
||||
in: "plugins/core/minting/minting-info.src.js",
|
||||
out: "plugins/core/minting/minting-info.js",
|
||||
},
|
||||
{
|
||||
in: "plugins/core/puzzles/puzzles.src.js",
|
||||
out: "plugins/core/puzzles/puzzles.js",
|
||||
},
|
||||
].map((file) => {
|
||||
return generateRollupConfig(
|
||||
path.join(__dirname, file.in),
|
||||
path.join(__dirname, file.out)
|
||||
);
|
||||
});
|
||||
|
||||
return configs;
|
||||
return configs;
|
||||
};
|
||||
module.exports = generateForPlugins;
|
||||
|
@ -22,7 +22,7 @@
|
||||
"emoji-picker-js": "https://github.com/Qortal/emoji-picker-js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.17.2",
|
||||
"@babel/core": "^7.17.5",
|
||||
"@github/time-elements": "^3.1.2",
|
||||
"@material/mwc-button": "^0.25.3",
|
||||
"@material/mwc-dialog": "^0.25.3",
|
||||
@ -39,11 +39,11 @@
|
||||
"@rollup/plugin-commonjs": "^21.0.1",
|
||||
"@rollup/plugin-node-resolve": "^13.1.3",
|
||||
"@rollup/plugin-replace": "^3.1.0",
|
||||
"@vaadin/vaadin-grid": "^5.9.3",
|
||||
"@vaadin/grid": "^22.0.5",
|
||||
"epml": "^0.3.3",
|
||||
"html-escaper": "^3.0.3",
|
||||
"lit": "^2.1.3",
|
||||
"rollup": "^2.67.2",
|
||||
"lit": "^2.2.0",
|
||||
"rollup": "^2.67.3",
|
||||
"rollup-plugin-node-globals": "^1.4.0",
|
||||
"rollup-plugin-progress": "^1.1.2",
|
||||
"rollup-plugin-terser": "^7.0.2"
|
||||
|
@ -2,11 +2,9 @@ import { LitElement, html, css } from 'lit'
|
||||
import { Epml } from '../../../epml.js'
|
||||
|
||||
import { escape, unescape } from 'html-escaper';
|
||||
import { inputKeyCodes } from '../../utils/keyCodes.js';
|
||||
|
||||
import { inputKeyCodes } from '../../utils/keyCodes.js'
|
||||
import './ChatScroller.js'
|
||||
import './TimeAgo.js'
|
||||
|
||||
import { EmojiPicker } from 'emoji-picker-js';
|
||||
import '@polymer/paper-spinner/paper-spinner-lite.js'
|
||||
|
||||
|
@ -406,7 +406,7 @@ class ChatWelcomePage extends LitElement {
|
||||
getAddressPublicKey()
|
||||
}
|
||||
|
||||
_textMenu(event) {
|
||||
_textMenu(event) {
|
||||
const getSelectedText = () => {
|
||||
var text = "";
|
||||
if (typeof window.getSelection != "undefined") {
|
||||
|
@ -46,7 +46,6 @@ class TimeAgo extends LitElement {
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { LitElement, html, css } from 'lit'
|
||||
import { Epml } from '../../../epml.js'
|
||||
|
||||
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
||||
|
||||
class ToolTip extends LitElement {
|
||||
@ -92,7 +91,6 @@ class ToolTip extends LitElement {
|
||||
})
|
||||
parentEpml.subscribe('config', c => {
|
||||
if (!configLoaded) {
|
||||
// setTimeout(getGroupIdFromURL, 1)
|
||||
configLoaded = true
|
||||
}
|
||||
this.config = JSON.parse(c)
|
||||
|
@ -6,11 +6,9 @@ import '@material/mwc-icon'
|
||||
import '@material/mwc-button'
|
||||
import '@material/mwc-textfield'
|
||||
import '@material/mwc-dialog'
|
||||
|
||||
import '@polymer/paper-spinner/paper-spinner-lite.js'
|
||||
import '@vaadin/vaadin-grid/vaadin-grid.js'
|
||||
import '@vaadin/vaadin-grid/theme/material/all-imports.js'
|
||||
|
||||
import '@vaadin/grid/vaadin-grid.js'
|
||||
import '@vaadin/grid/theme/material/all-imports.js'
|
||||
import '@github/time-elements'
|
||||
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
||||
@ -143,7 +141,7 @@ class GroupManagement extends LitElement {
|
||||
|
||||
<div class="divCard">
|
||||
<h3 style="margin: 0; margin-bottom: 1em; text-align: center;">Your Joined Groups</h3>
|
||||
<vaadin-grid id="joinedGroupsGrid" style="height:auto;" ?hidden="${this.isEmptyArray(this.joinedGroups)}" aria-label="Joined Groups" .items="${this.joinedGroups}" height-by-rows>
|
||||
<vaadin-grid theme="compact" id="joinedGroupsGrid" ?hidden="${this.isEmptyArray(this.joinedGroups)}" .items="${this.joinedGroups}" aria-label="Joined Groups" all-rows-visible>
|
||||
<vaadin-grid-column header="Name" path="groupName"></vaadin-grid-column>
|
||||
<vaadin-grid-column header="Description" path="description"></vaadin-grid-column>
|
||||
<vaadin-grid-column width="9.8rem" flex-grow="0" header="Role" .renderer=${(root, column, data) => {
|
||||
@ -160,7 +158,7 @@ class GroupManagement extends LitElement {
|
||||
|
||||
<div class="divCard">
|
||||
<h3 style="margin: 0; margin-bottom: 1em; text-align: center;">Public Groups</h3>
|
||||
<vaadin-grid id="publicGroupsGrid" style="height:auto;" ?hidden="${this.isEmptyArray(this.publicGroups)}" aria-label="Public Open Groups" .items="${this.publicGroups}" height-by-rows>
|
||||
<vaadin-grid theme="compact" id="publicGroupsGrid" ?hidden="${this.isEmptyArray(this.publicGroups)}" .items="${this.publicGroups}" aria-label="Public Open Groups" all-rows-visible>
|
||||
<vaadin-grid-column path="groupName"></vaadin-grid-column>
|
||||
<vaadin-grid-column header="Description" path="description"></vaadin-grid-column>
|
||||
<vaadin-grid-column path="owner"></vaadin-grid-column>
|
||||
@ -494,18 +492,18 @@ class GroupManagement extends LitElement {
|
||||
const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port;
|
||||
const url = `${nodeUrl}/transactions/unitfee?txType=CREATE_GROUP`;
|
||||
await fetch(url)
|
||||
.then((response) => {
|
||||
if (response.ok) {
|
||||
return response.json();
|
||||
}
|
||||
return Promise.reject(response);
|
||||
})
|
||||
.then((json) => {
|
||||
this.createFee = (Number(json) / 1e8).toFixed(8);
|
||||
})
|
||||
.catch((response) => {
|
||||
console.log(response.status, response.statusText, 'Need Core Update');
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.ok) {
|
||||
return response.json();
|
||||
}
|
||||
return Promise.reject(response);
|
||||
})
|
||||
.then((json) => {
|
||||
this.createFee = (Number(json) / 1e8).toFixed(8);
|
||||
})
|
||||
.catch((response) => {
|
||||
console.log(response.status, response.statusText, 'Need Core Update');
|
||||
})
|
||||
}
|
||||
|
||||
async unitJoinFee() {
|
||||
@ -513,18 +511,18 @@ class GroupManagement extends LitElement {
|
||||
const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port;
|
||||
const url = `${nodeUrl}/transactions/unitfee?txType=JOIN_GROUP`;
|
||||
await fetch(url)
|
||||
.then((response) => {
|
||||
if (response.ok) {
|
||||
return response.json();
|
||||
}
|
||||
return Promise.reject(response);
|
||||
})
|
||||
.then((json) => {
|
||||
this.joinFee = (Number(json) / 1e8).toFixed(8);
|
||||
})
|
||||
.catch((response) => {
|
||||
console.log(response.status, response.statusText, 'Need Core Update');
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.ok) {
|
||||
return response.json();
|
||||
}
|
||||
return Promise.reject(response);
|
||||
})
|
||||
.then((json) => {
|
||||
this.joinFee = (Number(json) / 1e8).toFixed(8);
|
||||
})
|
||||
.catch((response) => {
|
||||
console.log(response.status, response.statusText, 'Need Core Update');
|
||||
})
|
||||
}
|
||||
|
||||
async unitLeaveFee() {
|
||||
@ -532,18 +530,18 @@ class GroupManagement extends LitElement {
|
||||
const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port;
|
||||
const url = `${nodeUrl}/transactions/unitfee?txType=LEAVE_GROUP`;
|
||||
await fetch(url)
|
||||
.then((response) => {
|
||||
if (response.ok) {
|
||||
return response.json();
|
||||
}
|
||||
return Promise.reject(response);
|
||||
})
|
||||
.then((json) => {
|
||||
this.leaveFee = (Number(json) / 1e8).toFixed(8);
|
||||
})
|
||||
.catch((response) => {
|
||||
console.log(response.status, response.statusText, 'Need Core Update');
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.ok) {
|
||||
return response.json();
|
||||
}
|
||||
return Promise.reject(response);
|
||||
})
|
||||
.then((json) => {
|
||||
this.leaveFee = (Number(json) / 1e8).toFixed(8);
|
||||
})
|
||||
.catch((response) => {
|
||||
console.log(response.status, response.statusText, 'Need Core Update');
|
||||
})
|
||||
}
|
||||
|
||||
resetDefaultSettings() {
|
||||
|
@ -1,19 +1,8 @@
|
||||
import { LitElement, html, css } from 'lit'
|
||||
// import { render } from 'lit/html.js'
|
||||
// import { Epml } from '../../../src/epml.js'
|
||||
import { Epml } from '../../../../epml.js'
|
||||
|
||||
import '@polymer/paper-spinner/paper-spinner-lite.js'
|
||||
|
||||
// import * as thing from 'time-elements'
|
||||
// import '@vaadin/vaadin-grid/vaadin-grid.js'
|
||||
// import '@vaadin/vaadin-grid/theme/material/all-imports.js'
|
||||
|
||||
// import '@material/mwc-icon'
|
||||
// import '@material/mwc-textfield'
|
||||
// import '@material/mwc-button'
|
||||
// import '@material/mwc-dialog'
|
||||
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
||||
|
||||
class GroupTransaction extends LitElement {
|
||||
@ -75,7 +64,6 @@ class GroupTransaction extends LitElement {
|
||||
}
|
||||
|
||||
.group-transaction-card {
|
||||
/* margin:12px; */
|
||||
padding:12px 24px;
|
||||
background:#fff;
|
||||
border-radius:2px;
|
||||
@ -132,121 +120,16 @@ class GroupTransaction extends LitElement {
|
||||
render() {
|
||||
return html`
|
||||
<div id="group-transaction-page">
|
||||
|
||||
<div class="group-transaction-card">
|
||||
<h2>Group Transaction</h2>
|
||||
|
||||
<p>${this.addMintingAccountMessage}</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
|
||||
// getMintingAccountGrid() {
|
||||
|
||||
// const myGrid = this.shadowRoot.querySelector('#mintingAccountsGrid')
|
||||
|
||||
// myGrid.addEventListener('click', (e) => {
|
||||
// this.tempMintingAccount = myGrid.getEventContext(e).item
|
||||
|
||||
// this.shadowRoot.querySelector('#removeMintingAccountDialog').show()
|
||||
// })
|
||||
|
||||
// }
|
||||
|
||||
|
||||
// addPeer(e) {
|
||||
// this.addPeerLoading = true
|
||||
// const addPeerAddress = this.shadowRoot.querySelector('#addPeerAddress').value
|
||||
|
||||
// parentEpml.request('apiCall', {
|
||||
// url: `/peers`,
|
||||
// method: 'POST',
|
||||
// body: addPeerAddress
|
||||
// }).then(res => {
|
||||
// this.addPeerMessage = res.message
|
||||
|
||||
// this.addPeerLoading = false
|
||||
// })
|
||||
|
||||
// }
|
||||
|
||||
|
||||
// addMintingAccount(e) {
|
||||
// this.addMintingAccountLoading = true
|
||||
// this.addMintingAccountMessage = "Loading..."
|
||||
|
||||
// this.addMintingAccountKey = this.shadowRoot.querySelector('#addMintingAccountKey').value
|
||||
|
||||
// parentEpml.request('apiCall', {
|
||||
// url: `/admin/mintingaccounts`,
|
||||
// method: 'POST',
|
||||
// body: this.addMintingAccountKey
|
||||
// }).then(res => {
|
||||
// if (res === true) {
|
||||
// this.updateMintingAccounts()
|
||||
// this.addMintingAccountKey = ''
|
||||
// this.addMintingAccountMessage = 'Minting Node Added Successfully!'
|
||||
// this.addMintingAccountLoading = false
|
||||
// } else {
|
||||
// this.addMintingAccountKey = ''
|
||||
// this.addMintingAccountMessage = 'Failed to Add Minting Node!' // Corrected an error here thanks to crow (-_-)
|
||||
// this.addMintingAccountLoading = false
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
|
||||
// updateMintingAccounts() {
|
||||
// parentEpml.request('apiCall', {
|
||||
// url: `/admin/mintingaccounts`
|
||||
// }).then(res => {
|
||||
|
||||
// this.mintingAccounts = []
|
||||
// setTimeout(() => { this.mintingAccounts = res }, 1)
|
||||
// })
|
||||
|
||||
// // setTimeout(updateMintingAccounts, this.config.user.nodeSettings.pingInterval) // Perhaps should be slower...?
|
||||
// }
|
||||
|
||||
// removeMintingAccount(e) {
|
||||
// this.removeMintingAccountLoading = true
|
||||
// this.removeMintingAccountMessage = "Loading..."
|
||||
|
||||
// this.removeMintingAccountKey = this.shadowRoot.querySelector('#removeMintingAccountKey').value
|
||||
|
||||
// this.mintingAccounts.forEach(mintingAccount => {
|
||||
// if (this.tempMintingAccount.recipientAccount === mintingAccount.recipientAccount) {
|
||||
|
||||
// parentEpml.request('apiCall', {
|
||||
// url: `/admin/mintingaccounts`,
|
||||
// method: 'DELETE',
|
||||
// body: this.removeMintingAccountKey
|
||||
// }).then(res => {
|
||||
// if (res === true) {
|
||||
// this.updateMintingAccounts()
|
||||
// this.removeMintingAccountKey = ''
|
||||
// this.removeMintingAccountMessage = 'Minting Node Removed Successfully!'
|
||||
// this.removeMintingAccountLoading = false
|
||||
// } else {
|
||||
// this.removeMintingAccountKey = ''
|
||||
// this.removeMintingAccountMessage = 'Failed to Remove Minting Node!'
|
||||
// this.removeMintingAccountLoading = false
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
// })
|
||||
|
||||
// }
|
||||
|
||||
firstUpdated() {
|
||||
|
||||
// Call getMintingAccountGrid
|
||||
// this.getMintingAccountGrid()
|
||||
|
||||
// Call updateMintingAccounts
|
||||
// this.updateMintingAccounts()
|
||||
|
||||
const getGroupIdFromURL = () => {
|
||||
let tempUrl = document.location.href
|
||||
let decodeTempUrl = decodeURI(tempUrl)
|
||||
@ -276,7 +159,6 @@ class GroupTransaction extends LitElement {
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
parentEpml.imReady()
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,30 @@
|
||||
<head>
|
||||
<link rel="stylesheet" href="/font/material-icons.css">
|
||||
<style>
|
||||
html {
|
||||
--scrollbarBG: #a1a1a1;
|
||||
--thumbBG: #6a6c75;
|
||||
}
|
||||
|
||||
*::-webkit-scrollbar {
|
||||
width: 11px;
|
||||
}
|
||||
|
||||
* {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: var(--thumbBG) var(--scrollbarBG);
|
||||
}
|
||||
|
||||
*::-webkit-scrollbar-track {
|
||||
background: var(--scrollbarBG);
|
||||
}
|
||||
|
||||
*::-webkit-scrollbar-thumb {
|
||||
background-color: var(--thumbBG);
|
||||
border-radius: 6px;
|
||||
border: 3px solid var(--scrollbarBG);
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
margin: 0;
|
||||
@ -15,7 +39,6 @@
|
||||
|
||||
<body>
|
||||
<group-transaction></group-transaction>
|
||||
|
||||
<script src="group-transaction.js"></script>
|
||||
</body>
|
||||
|
||||
|
@ -39,7 +39,6 @@
|
||||
|
||||
<body>
|
||||
<group-management></group-management>
|
||||
|
||||
<script src="group-management.js"></script>
|
||||
</body>
|
||||
|
||||
|
File diff suppressed because one or more lines are too long
@ -98,7 +98,7 @@ parentEpml.ready().then(() => {
|
||||
menus: [],
|
||||
parent: false
|
||||
},
|
||||
{
|
||||
{
|
||||
url: 'puzzles',
|
||||
domain: 'core',
|
||||
page: 'puzzles/index.html',
|
||||
@ -106,7 +106,7 @@ parentEpml.ready().then(() => {
|
||||
icon: 'extension',
|
||||
menus: [],
|
||||
parent: false
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
const registerPlugins = (pluginInfo) => {
|
||||
|
@ -3,7 +3,7 @@ import { LitElement, html, css } from 'lit'
|
||||
class ChainMessaging extends LitElement {
|
||||
static get properties() {
|
||||
return {
|
||||
loading: { type: Boolean },
|
||||
loading: { type: Boolean }
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,13 +30,11 @@ class ChainMessaging extends LitElement {
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
// ...
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<div id="chain-messaging-page">
|
||||
|
||||
<h2 style="text-align: center; margin-top: 3rem;">Coming Soon!</h2>
|
||||
</div>
|
||||
`
|
||||
|
@ -28,6 +28,7 @@
|
||||
border: 3px solid var(--scrollbarBG);
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: "Roboto", sans-serif;
|
||||
@ -38,7 +39,6 @@
|
||||
|
||||
<body>
|
||||
<q-messaging></q-messaging>
|
||||
|
||||
<script src="messaging.js"></script>
|
||||
</body>
|
||||
|
||||
|
@ -40,7 +40,6 @@ class Messaging extends LitElement {
|
||||
color: rgb(3, 169, 244);
|
||||
margin-top: .5rem;
|
||||
font-weight: 400;
|
||||
/* font-size: 19px; */
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@ -60,7 +59,6 @@ class Messaging extends LitElement {
|
||||
.divCard {
|
||||
border: 1px solid #eee;
|
||||
padding: 1em;
|
||||
/** box-shadow: 0 1px 1px 0 rgba(0,0,0,0.14), 0 2px 1px -1px rgba(0,0,0,0.12), 0 1px 2px 0 rgba(0,0,0,0.20); **/
|
||||
box-shadow: 0 .3px 1px 0 rgba(0,0,0,0.14), 0 1px 1px -1px rgba(0,0,0,0.12), 0 1px 2px 0 rgba(0,0,0,0.20);
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
@ -33,14 +33,13 @@
|
||||
margin: 0;
|
||||
font-family: "Roboto", sans-serif;
|
||||
background-color: #fff;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<q-chat></q-chat>
|
||||
<script type="module" src="q-chat.js"></script>
|
||||
<script src="q-chat.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -2,13 +2,10 @@ import { LitElement, html, css } from 'lit'
|
||||
import { render } from 'lit/html.js'
|
||||
import { Epml } from '../../../../epml.js'
|
||||
|
||||
// Components
|
||||
import '../../components/ChatWelcomePage.js'
|
||||
import '../../components/ChatHead.js'
|
||||
import '../../components/ChatPage.js'
|
||||
|
||||
import '@polymer/paper-spinner/paper-spinner-lite.js'
|
||||
|
||||
import '@material/mwc-icon'
|
||||
import '@material/mwc-button'
|
||||
import '@material/mwc-dialog'
|
||||
@ -296,11 +293,10 @@ class Chat extends LitElement {
|
||||
</div>
|
||||
|
||||
<div class="chat">
|
||||
<div id="newMessageBar" class="new-message-bar hide-new-message-bar clearfix" @click=${ () => this.scrollToBottom()}>
|
||||
<div id="newMessageBar" class="new-message-bar hide-new-message-bar clearfix" @click=${() => this.scrollToBottom()}>
|
||||
<span style="flex: 1;">New Message</span>
|
||||
<span>(Click to scroll down) <mwc-icon style="font-size: 16px; vertical-align: bottom;">keyboard_arrow_down</mwc-icon></span>
|
||||
</div>
|
||||
|
||||
<div class="chat-history">
|
||||
${window.parent.location.pathname !== "/app/q-chat" ? html`${this.renderChatPage(this.chatId)}` : html`${this.renderChatWelcomePage()}`}
|
||||
</div>
|
||||
@ -474,9 +470,7 @@ class Chat extends LitElement {
|
||||
})
|
||||
parentEpml.subscribe('chat_heads', chatHeads => {
|
||||
chatHeads = JSON.parse(chatHeads)
|
||||
// setTimeout(() => {
|
||||
this.getChatHeadFromState(chatHeads)
|
||||
// }, 5000)
|
||||
})
|
||||
parentEpml.request('apiCall', {
|
||||
url: `/addresses/balance/${window.parent.reduxStore.getState().app.selectedAddress.address}`
|
||||
|
@ -32,7 +32,7 @@
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: "Roboto", sans-serif;
|
||||
background: #fff;
|
||||
background-color: #fff;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
@ -1,13 +1,13 @@
|
||||
import { LitElement, html, css } from "lit";
|
||||
import { render } from "lit/html.js";
|
||||
import { Epml } from "../../../epml.js";
|
||||
import { LitElement, html, css } from 'lit'
|
||||
import { render } from 'lit/html.js'
|
||||
import { Epml } from '../../../epml.js'
|
||||
|
||||
import "@material/mwc-icon";
|
||||
import "@material/mwc-button";
|
||||
import "@material/mwc-dialog";
|
||||
import "@material/mwc-textfield";
|
||||
import '@material/mwc-icon'
|
||||
import '@material/mwc-button'
|
||||
import '@material/mwc-dialog'
|
||||
import '@material/mwc-textfield'
|
||||
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent });
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
||||
|
||||
class MintingInfo extends LitElement {
|
||||
static get properties() {
|
||||
@ -18,7 +18,7 @@ class MintingInfo extends LitElement {
|
||||
nodeInfo: { type: Array },
|
||||
sampleBlock: { type: Array },
|
||||
addressInfo: { type: Array },
|
||||
addressLevel: { type: Array },
|
||||
addressLevel: { type: Array }
|
||||
}
|
||||
}
|
||||
|
||||
@ -195,8 +195,8 @@ class MintingInfo extends LitElement {
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.renderMintingPage() === "false") {
|
||||
return html`
|
||||
if (this.renderMintingPage() === "false") {
|
||||
return html`
|
||||
<div>
|
||||
<div>
|
||||
<span class="header-title">General Minting Details</span>
|
||||
@ -247,7 +247,7 @@ class MintingInfo extends LitElement {
|
||||
</mwc-dialog>
|
||||
</div>
|
||||
`} else {
|
||||
return html`
|
||||
return html`
|
||||
<div>
|
||||
<div>
|
||||
<span class="header-title">General Minting Details</span>
|
||||
@ -356,14 +356,14 @@ class MintingInfo extends LitElement {
|
||||
|
||||
firstUpdated() {
|
||||
const getAdminInfo = () => {
|
||||
parentEpml.request("apiCall", {url: `/admin/info`}).then((res) => {
|
||||
setTimeout(() => {this.adminInfo = res;}, 1);
|
||||
parentEpml.request("apiCall", { url: `/admin/info` }).then((res) => {
|
||||
setTimeout(() => { this.adminInfo = res; }, 1);
|
||||
});
|
||||
setTimeout(getAdminInfo, 30000);
|
||||
};
|
||||
|
||||
const getNodeInfo = () => {
|
||||
parentEpml.request("apiCall", {url: `/admin/status`}).then((res) => {
|
||||
parentEpml.request("apiCall", { url: `/admin/status` }).then((res) => {
|
||||
this.nodeInfo = res;
|
||||
// Now look up the sample block
|
||||
getSampleBlock()
|
||||
@ -373,21 +373,21 @@ class MintingInfo extends LitElement {
|
||||
|
||||
const getSampleBlock = () => {
|
||||
let callBlock = parseFloat(this.nodeInfo.height) - 10000;
|
||||
parentEpml.request("apiCall", {url: `/blocks/byheight/${callBlock}`}).then((res) => {
|
||||
setTimeout(() => {this.sampleBlock = res;}, 1);
|
||||
parentEpml.request("apiCall", { url: `/blocks/byheight/${callBlock}` }).then((res) => {
|
||||
setTimeout(() => { this.sampleBlock = res; }, 1);
|
||||
});
|
||||
};
|
||||
|
||||
const getAddressInfo = () => {
|
||||
parentEpml.request('apiCall', {url: `/addresses/${window.parent.reduxStore.getState().app.selectedAddress.address}`}).then((res) => {
|
||||
setTimeout(() => {this.addressInfo = res;}, 1);
|
||||
parentEpml.request('apiCall', { url: `/addresses/${window.parent.reduxStore.getState().app.selectedAddress.address}` }).then((res) => {
|
||||
setTimeout(() => { this.addressInfo = res; }, 1);
|
||||
});
|
||||
setTimeout(getAddressInfo, 30000);
|
||||
};
|
||||
|
||||
const getAddressLevel = () => {
|
||||
parentEpml.request('apiCall', {url: `/addresses/online/levels`}).then((res) => {
|
||||
setTimeout(() => {this.addressLevel = res;}, 1);
|
||||
parentEpml.request('apiCall', { url: `/addresses/online/levels` }).then((res) => {
|
||||
setTimeout(() => { this.addressLevel = res; }, 1);
|
||||
});
|
||||
setTimeout(getAddressLevel, 30000);
|
||||
};
|
||||
@ -432,30 +432,30 @@ class MintingInfo extends LitElement {
|
||||
|
||||
renderActivateHelp() {
|
||||
if (this.renderMintingPage() === "false") {
|
||||
return html `Activate Account Details <div class="level-blue">==></div> Not Activated<br><mwc-button class="red-button" @click=${() => this.shadowRoot.querySelector("#activateAccountDialog").show()}><mwc-icon class="help-icon">help_outline</mwc-icon> Press For Help</mwc-button>`;
|
||||
return html`Activate Account Details <div class="level-blue">==></div> Not Activated<br><mwc-button class="red-button" @click=${() => this.shadowRoot.querySelector("#activateAccountDialog").show()}><mwc-icon class="help-icon">help_outline</mwc-icon> Press For Help</mwc-button>`;
|
||||
} else {
|
||||
return "No Details";
|
||||
}
|
||||
}
|
||||
_averageBlockTime() {
|
||||
let avgBlockString = (this.adminInfo.currentTimestamp - this.sampleBlock.timestamp).toString();
|
||||
let averageTimeString = ((avgBlockString / 1000) / 10000).toFixed(2);
|
||||
let averageBlockTimeString = (averageTimeString).toString();
|
||||
let averageTimeString = ((avgBlockString / 1000) / 10000).toFixed(2);
|
||||
let averageBlockTimeString = (averageTimeString).toString();
|
||||
return "" + averageBlockTimeString;
|
||||
}
|
||||
|
||||
_timeCalc() {
|
||||
let timeString = (this.adminInfo.currentTimestamp - this.sampleBlock.timestamp).toString();
|
||||
let averageString = ((timeString / 1000) / 10000).toFixed(2);
|
||||
let averageBlockDay = (86400 / averageString).toFixed(2);
|
||||
let averageBlockDayString = (averageBlockDay).toString();
|
||||
let averageString = ((timeString / 1000) / 10000).toFixed(2);
|
||||
let averageBlockDay = (86400 / averageString).toFixed(2);
|
||||
let averageBlockDayString = (averageBlockDay).toString();
|
||||
return "" + averageBlockDayString;
|
||||
}
|
||||
|
||||
_dayReward() {
|
||||
let rewardString = (this._timeCalc() * this._blockReward()).toFixed(2);
|
||||
let rewardDayString = (rewardString).toString();
|
||||
return "" + rewardDayString ;
|
||||
let rewardDayString = (rewardString).toString();
|
||||
return "" + rewardDayString;
|
||||
}
|
||||
|
||||
_mintingStatus() {
|
||||
@ -478,7 +478,7 @@ class MintingInfo extends LitElement {
|
||||
|
||||
renderMintingHelp() {
|
||||
if (this._mintingStatus() === "Not Minting") {
|
||||
return html `Minting Account Details <div class="level-blue">==></div> Not A Minter<br><mwc-button class="red-button" @click=${() => this.shadowRoot.querySelector("#becomeMinterDialog").show()}><mwc-icon class="help-icon">help_outline</mwc-icon> Press For Help</mwc-button>`;
|
||||
return html`Minting Account Details <div class="level-blue">==></div> Not A Minter<br><mwc-button class="red-button" @click=${() => this.shadowRoot.querySelector("#becomeMinterDialog").show()}><mwc-icon class="help-icon">help_outline</mwc-icon> Press For Help</mwc-button>`;
|
||||
} else {
|
||||
return "Minting Account Details";
|
||||
}
|
||||
|
@ -32,14 +32,14 @@
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: "Roboto", sans-serif;
|
||||
background: #fff;
|
||||
background-color: #fff;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<name-registration></name-registration>
|
||||
<script type="module" src="name-registration.js"></script>
|
||||
<script src="name-registration.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -6,10 +6,9 @@ import '@material/mwc-icon'
|
||||
import '@material/mwc-button'
|
||||
import '@material/mwc-textfield'
|
||||
import '@material/mwc-dialog'
|
||||
|
||||
import '@polymer/paper-spinner/paper-spinner-lite.js'
|
||||
import '@vaadin/vaadin-grid/vaadin-grid.js'
|
||||
import '@vaadin/vaadin-grid/theme/material/all-imports.js'
|
||||
import '@vaadin/grid/vaadin-grid.js'
|
||||
import '@vaadin/grid/theme/material/all-imports.js'
|
||||
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
||||
|
||||
@ -86,10 +85,10 @@ class NameRegistration extends LitElement {
|
||||
|
||||
<div class="divCard">
|
||||
<h3 style="margin: 0; margin-bottom: 1em; text-align: center;">Registered Names</h3>
|
||||
<vaadin-grid id="namesGrid" style="height:auto;" ?hidden="${this.isEmptyArray(this.names)}" aria-label="Names" .items="${this.names}" height-by-rows>
|
||||
<vaadin-grid theme="compact" id="namesGrid" ?hidden="${this.isEmptyArray(this.names)}" aria-label="Names" .items="${this.names}" all-rows-visible>
|
||||
<vaadin-grid-column width="5rem" flex-grow="0" header="Avatar" .renderer=${(root, column, data) => {
|
||||
render(html`${this.renderAvatar(data.item)}`, root)
|
||||
}}></vaadin-grid-column>
|
||||
}}></vaadin-grid-column>
|
||||
<vaadin-grid-column path="name"></vaadin-grid-column>
|
||||
<vaadin-grid-column path="owner"></vaadin-grid-column>
|
||||
<vaadin-grid-column width="12rem" flex-grow="0" header="Action" .renderer=${(root, column, data) => {
|
||||
@ -216,18 +215,18 @@ class NameRegistration extends LitElement {
|
||||
const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port;
|
||||
const url = `${nodeUrl}/transactions/unitfee?txType=REGISTER_NAME`;
|
||||
await fetch(url)
|
||||
.then((response) => {
|
||||
if (response.ok) {
|
||||
return response.json();
|
||||
}
|
||||
return Promise.reject(response);
|
||||
})
|
||||
.then((json) => {
|
||||
this.fee = (Number(json) / 1e8).toFixed(8);
|
||||
})
|
||||
.catch((response) => {
|
||||
console.log(response.status, response.statusText, 'Need Core Update');
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.ok) {
|
||||
return response.json();
|
||||
}
|
||||
return Promise.reject(response);
|
||||
})
|
||||
.then((json) => {
|
||||
this.fee = (Number(json) / 1e8).toFixed(8);
|
||||
})
|
||||
.catch((response) => {
|
||||
console.log(response.status, response.statusText, 'Need Core Update');
|
||||
})
|
||||
}
|
||||
|
||||
getApiKey() {
|
||||
@ -248,7 +247,7 @@ class NameRegistration extends LitElement {
|
||||
const nameInput = this.shadowRoot.getElementById("nameInput").value
|
||||
const descInput = this.shadowRoot.getElementById("descInput").value
|
||||
|
||||
// Check for valid...^
|
||||
// Check for valid...
|
||||
this.registerNameLoading = true
|
||||
|
||||
// Get Last Ref
|
||||
|
@ -1,42 +1,42 @@
|
||||
import { LitElement, html, css } from "lit";
|
||||
import { LitElement, html, css } from 'lit'
|
||||
import { render } from 'lit/html.js'
|
||||
import { Epml } from "../../../epml.js";
|
||||
import { Epml } from '../../../epml.js'
|
||||
|
||||
import "@polymer/paper-spinner/paper-spinner-lite.js";
|
||||
import "@vaadin/vaadin-grid/vaadin-grid.js";
|
||||
import "@vaadin/vaadin-grid/theme/material/all-imports.js";
|
||||
import "@material/mwc-icon";
|
||||
import "@material/mwc-textfield";
|
||||
import "@material/mwc-button";
|
||||
import "@material/mwc-dialog";
|
||||
import '@polymer/paper-spinner/paper-spinner-lite.js'
|
||||
import '@material/mwc-icon'
|
||||
import '@material/mwc-textfield'
|
||||
import '@material/mwc-button'
|
||||
import '@material/mwc-dialog'
|
||||
import '@vaadin/grid/vaadin-grid.js'
|
||||
import '@vaadin/grid/theme/material/all-imports.js'
|
||||
|
||||
const parentEpml = new Epml({ type: "WINDOW", source: window.parent });
|
||||
const parentEpml = new Epml({ type: "WINDOW", source: window.parent })
|
||||
|
||||
class NodeManagement extends LitElement {
|
||||
static get properties() {
|
||||
return {
|
||||
loading: { type: Boolean },
|
||||
upTime: { type: String },
|
||||
mintingAccounts: { type: Array },
|
||||
peers: { type: Array },
|
||||
addMintingAccountLoading: { type: Boolean },
|
||||
removeMintingAccountLoading: { type: Boolean },
|
||||
addPeerLoading: { type: Boolean },
|
||||
confPeerLoading: { type: Boolean },
|
||||
addMintingAccountKey: { type: String },
|
||||
removeMintingAccountKey: { type: String },
|
||||
addPeerMessage: { type: String },
|
||||
confPeerMessage: { type: String },
|
||||
addMintingAccountMessage: { type: String },
|
||||
removeMintingAccountMessage: { type: String },
|
||||
tempMintingAccount: { type: Object },
|
||||
nodeConfig: { type: Object },
|
||||
nodeDomain: { type: String },
|
||||
};
|
||||
}
|
||||
static get properties() {
|
||||
return {
|
||||
loading: { type: Boolean },
|
||||
upTime: { type: String },
|
||||
mintingAccounts: { type: Array },
|
||||
peers: { type: Array },
|
||||
addMintingAccountLoading: { type: Boolean },
|
||||
removeMintingAccountLoading: { type: Boolean },
|
||||
addPeerLoading: { type: Boolean },
|
||||
confPeerLoading: { type: Boolean },
|
||||
addMintingAccountKey: { type: String },
|
||||
removeMintingAccountKey: { type: String },
|
||||
addPeerMessage: { type: String },
|
||||
confPeerMessage: { type: String },
|
||||
addMintingAccountMessage: { type: String },
|
||||
removeMintingAccountMessage: { type: String },
|
||||
tempMintingAccount: { type: Object },
|
||||
nodeConfig: { type: Object },
|
||||
nodeDomain: { type: String }
|
||||
};
|
||||
}
|
||||
|
||||
static get styles() {
|
||||
return css`
|
||||
static get styles() {
|
||||
return css`
|
||||
* {
|
||||
--mdc-theme-primary: rgb(3, 169, 244);
|
||||
--paper-input-container-focus-color: var(--mdc-theme-primary);
|
||||
@ -72,7 +72,6 @@ class NodeManagement extends LitElement {
|
||||
}
|
||||
|
||||
.node-card {
|
||||
/* margin:12px; */
|
||||
padding: 12px 24px;
|
||||
background: #fff;
|
||||
border-radius: 2px;
|
||||
@ -95,38 +94,39 @@ class NodeManagement extends LitElement {
|
||||
display: hidden !important;
|
||||
visibility: none !important;
|
||||
}
|
||||
|
||||
.details {
|
||||
display: flex;
|
||||
font-size: 18px;
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.upTime = "";
|
||||
this.mintingAccounts = [];
|
||||
this.peers = [];
|
||||
this.addPeerLoading = false;
|
||||
this.confPeerLoading = false;
|
||||
this.addMintingAccountLoading = false;
|
||||
this.removeMintingAccountLoading = false;
|
||||
this.addMintingAccountKey = "";
|
||||
this.addPeerMessage = "";
|
||||
this.confPeerMessage = "";
|
||||
this.addMintingAccountMessage = "";
|
||||
this.tempMintingAccount = {};
|
||||
this.config = {
|
||||
user: {
|
||||
node: {},
|
||||
},
|
||||
};
|
||||
this.nodeConfig = {};
|
||||
this.nodeDomain = "";
|
||||
}
|
||||
constructor() {
|
||||
super();
|
||||
this.upTime = "";
|
||||
this.mintingAccounts = [];
|
||||
this.peers = [];
|
||||
this.addPeerLoading = false;
|
||||
this.confPeerLoading = false;
|
||||
this.addMintingAccountLoading = false;
|
||||
this.removeMintingAccountLoading = false;
|
||||
this.addMintingAccountKey = "";
|
||||
this.addPeerMessage = "";
|
||||
this.confPeerMessage = "";
|
||||
this.addMintingAccountMessage = "";
|
||||
this.tempMintingAccount = {};
|
||||
this.config = {
|
||||
user: {
|
||||
node: {},
|
||||
},
|
||||
};
|
||||
this.nodeConfig = {};
|
||||
this.nodeDomain = "";
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
render() {
|
||||
return html`
|
||||
<div id="node-management-page">
|
||||
<div class="node-card">
|
||||
<h2>Node management for: ${this.nodeDomain}</h2>
|
||||
@ -143,7 +143,7 @@ class NodeManagement extends LitElement {
|
||||
<mwc-button
|
||||
style="float:right;"
|
||||
@click=${() =>
|
||||
this.shadowRoot
|
||||
this.shadowRoot
|
||||
.querySelector("#addMintingAccountDialog")
|
||||
.show()}
|
||||
><mwc-icon>add</mwc-icon>Add minting account</mwc-button
|
||||
@ -201,7 +201,7 @@ class NodeManagement extends LitElement {
|
||||
</mwc-button>
|
||||
</mwc-dialog>
|
||||
|
||||
<vaadin-grid id="mintingAccountsGrid" style="height:auto;" ?hidden="${this.isEmptyArray(this.mintingAccounts)}" aria-label="Minting Accounts" .items="${this.mintingAccounts}" height-by-rows>
|
||||
<vaadin-grid theme="compact" id="mintingAccountsGrid" ?hidden="${this.isEmptyArray(this.mintingAccounts)}" .items="${this.mintingAccounts}" aria-label="Minting Accounts" all-rows-visible>
|
||||
<vaadin-grid-column auto-width header="Minting Account" path="mintingAccount"></vaadin-grid-column>
|
||||
<vaadin-grid-column auto-width header="Recipient Account" path="recipientAccount"></vaadin-grid-column>
|
||||
<vaadin-grid-column width="12em" header="Action" .renderer=${(root, column, data) => {
|
||||
@ -253,12 +253,12 @@ class NodeManagement extends LitElement {
|
||||
</mwc-button>
|
||||
</mwc-dialog>
|
||||
|
||||
<vaadin-grid id="peersGrid" style="height:auto;" ?hidden="${this.isEmptyArray(this.peers)}" aria-label="Peers" .items="${this.peers}" height-by-rows>
|
||||
<vaadin-grid theme="compact" id="peersGrid" ?hidden="${this.isEmptyArray(this.peers)}" .items="${this.peers}" aria-label="Peers" all-rows-visible>
|
||||
<vaadin-grid-column path="address"></vaadin-grid-column>
|
||||
<vaadin-grid-column path="lastHeight"></vaadin-grid-column>
|
||||
<vaadin-grid-column path="version" header="Build Version"></vaadin-grid-column>
|
||||
<vaadin-grid-column path="age" header="Connected for"></vaadin-grid-column>
|
||||
<vaadin-grid-column width="12em" header="Action" .renderer=${(root, column, data) => {
|
||||
<vaadin-grid-column width="12em" header="Action" .renderer=${(root, column, data) => {
|
||||
render(html`<mwc-button class="red" @click=${() => this.removePeer(data.item.address, data.index)}><mwc-icon>delete</mwc-icon>Remove</mwc-button><mwc-button class="green" @click=${() => this.forceSyncPeer(data.item.address, data.index)}>Force Sync</mwc-button>`, root)
|
||||
}}></vaadin-grid-column>
|
||||
</vaadin-grid>
|
||||
@ -269,81 +269,81 @@ class NodeManagement extends LitElement {
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
forceSyncPeer (peerAddress, rowIndex) {
|
||||
parentEpml
|
||||
.request("apiCall", {
|
||||
url: `/admin/forcesync?apiKey=${this.getApiKey()}`,
|
||||
method: "POST",
|
||||
body: peerAddress,
|
||||
})
|
||||
.then((res) => {
|
||||
parentEpml.request('showSnackBar', "Starting Sync with Peer: " + peerAddress );
|
||||
});
|
||||
}
|
||||
|
||||
removePeer(peerAddress, rowIndex) {
|
||||
parentEpml
|
||||
.request("apiCall", {
|
||||
url: `/peers?apiKey=${this.getApiKey()}`,
|
||||
method: "DELETE",
|
||||
body: peerAddress,
|
||||
})
|
||||
.then((res) => {
|
||||
parentEpml.request('showSnackBar', "Successfully removed Peer: " + peerAddress );
|
||||
this.peers.splice(rowIndex, 1);
|
||||
});
|
||||
}
|
||||
|
||||
onPageNavigation(pageUrl) {
|
||||
parentEpml.request("setPageUrl", pageUrl);
|
||||
}
|
||||
}
|
||||
|
||||
addPeer(e) {
|
||||
this.addPeerLoading = true;
|
||||
const addPeerAddress = this.shadowRoot.querySelector("#addPeerAddress")
|
||||
.value;
|
||||
forceSyncPeer(peerAddress, rowIndex) {
|
||||
parentEpml
|
||||
.request("apiCall", {
|
||||
url: `/admin/forcesync?apiKey=${this.getApiKey()}`,
|
||||
method: "POST",
|
||||
body: peerAddress,
|
||||
})
|
||||
.then((res) => {
|
||||
parentEpml.request('showSnackBar', "Starting Sync with Peer: " + peerAddress);
|
||||
});
|
||||
}
|
||||
|
||||
parentEpml
|
||||
.request("apiCall", {
|
||||
url: `/peers?apiKey=${this.getApiKey()}`,
|
||||
method: "POST",
|
||||
body: addPeerAddress,
|
||||
})
|
||||
.then((res) => {
|
||||
this.addPeerMessage = res.message;
|
||||
this.addPeerLoading = false;
|
||||
});
|
||||
}
|
||||
removePeer(peerAddress, rowIndex) {
|
||||
parentEpml
|
||||
.request("apiCall", {
|
||||
url: `/peers?apiKey=${this.getApiKey()}`,
|
||||
method: "DELETE",
|
||||
body: peerAddress,
|
||||
})
|
||||
.then((res) => {
|
||||
parentEpml.request('showSnackBar', "Successfully removed Peer: " + peerAddress);
|
||||
this.peers.splice(rowIndex, 1);
|
||||
});
|
||||
}
|
||||
|
||||
addMintingAccount(e) {
|
||||
this.addMintingAccountLoading = true;
|
||||
this.addMintingAccountMessage = "Loading...";
|
||||
onPageNavigation(pageUrl) {
|
||||
parentEpml.request("setPageUrl", pageUrl);
|
||||
}
|
||||
|
||||
this.addMintingAccountKey = this.shadowRoot.querySelector(
|
||||
"#addMintingAccountKey"
|
||||
).value;
|
||||
addPeer(e) {
|
||||
this.addPeerLoading = true;
|
||||
const addPeerAddress = this.shadowRoot.querySelector("#addPeerAddress")
|
||||
.value;
|
||||
|
||||
parentEpml
|
||||
.request("apiCall", {
|
||||
url: `/admin/mintingaccounts?apiKey=${this.getApiKey()}`,
|
||||
method: "POST",
|
||||
body: this.addMintingAccountKey,
|
||||
})
|
||||
.then((res) => {
|
||||
if (res === true) {
|
||||
this.updateMintingAccounts();
|
||||
this.addMintingAccountKey = "";
|
||||
this.addMintingAccountMessage = "Minting Node Added Successfully!";
|
||||
this.addMintingAccountLoading = false;
|
||||
} else {
|
||||
this.addMintingAccountKey = "";
|
||||
this.addMintingAccountMessage = "Failed to Add Minting Node!"; // Corrected an error here thanks to crow (-_-)
|
||||
this.addMintingAccountLoading = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
parentEpml
|
||||
.request("apiCall", {
|
||||
url: `/peers?apiKey=${this.getApiKey()}`,
|
||||
method: "POST",
|
||||
body: addPeerAddress,
|
||||
})
|
||||
.then((res) => {
|
||||
this.addPeerMessage = res.message;
|
||||
this.addPeerLoading = false;
|
||||
});
|
||||
}
|
||||
|
||||
addMintingAccount(e) {
|
||||
this.addMintingAccountLoading = true;
|
||||
this.addMintingAccountMessage = "Loading...";
|
||||
|
||||
this.addMintingAccountKey = this.shadowRoot.querySelector(
|
||||
"#addMintingAccountKey"
|
||||
).value;
|
||||
|
||||
parentEpml
|
||||
.request("apiCall", {
|
||||
url: `/admin/mintingaccounts?apiKey=${this.getApiKey()}`,
|
||||
method: "POST",
|
||||
body: this.addMintingAccountKey,
|
||||
})
|
||||
.then((res) => {
|
||||
if (res === true) {
|
||||
this.updateMintingAccounts();
|
||||
this.addMintingAccountKey = "";
|
||||
this.addMintingAccountMessage = "Minting Node Added Successfully!";
|
||||
this.addMintingAccountLoading = false;
|
||||
} else {
|
||||
this.addMintingAccountKey = "";
|
||||
this.addMintingAccountMessage = "Failed to Add Minting Node!"; // Corrected an error here thanks to crow (-_-)
|
||||
this.addMintingAccountLoading = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
updateMintingAccounts() {
|
||||
parentEpml.request("apiCall", {
|
||||
@ -358,9 +358,9 @@ class NodeManagement extends LitElement {
|
||||
const getSelectedText = () => {
|
||||
var text = "";
|
||||
if (typeof window.getSelection != "undefined") {
|
||||
text = window.getSelection().toString();
|
||||
text = window.getSelection().toString();
|
||||
} else if (typeof this.shadowRoot.selection != "undefined" && this.shadowRoot.selection.type == "Text") {
|
||||
text = this.shadowRoot.selection.createRange().text;
|
||||
text = this.shadowRoot.selection.createRange().text;
|
||||
}
|
||||
return text;
|
||||
}
|
||||
@ -369,18 +369,18 @@ class NodeManagement extends LitElement {
|
||||
let selectedText = getSelectedText();
|
||||
if (selectedText && typeof selectedText === 'string') {
|
||||
|
||||
let _eve = { pageX: event.pageX, pageY: event.pageY, clientX: event.clientX, clientY: event.clientY }
|
||||
let _eve = { pageX: event.pageX, pageY: event.pageY, clientX: event.clientX, clientY: event.clientY }
|
||||
|
||||
let textMenuObject = { selectedText: selectedText, eventObject: _eve, isFrame: true }
|
||||
let textMenuObject = { selectedText: selectedText, eventObject: _eve, isFrame: true }
|
||||
|
||||
parentEpml.request('openCopyTextMenu', textMenuObject)
|
||||
parentEpml.request('openCopyTextMenu', textMenuObject)
|
||||
}
|
||||
}
|
||||
|
||||
checkSelectedTextAndShowMenu()
|
||||
}
|
||||
|
||||
removeMintingAccount(publicKey) {
|
||||
removeMintingAccount(publicKey) {
|
||||
this.removeMintingAccountLoading = true;
|
||||
|
||||
parentEpml.request("apiCall", {
|
||||
@ -397,116 +397,116 @@ class NodeManagement extends LitElement {
|
||||
parentEpml.request('showSnackBar', "Failed to Remove Minting Account!");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
|
||||
// Call updateMintingAccounts
|
||||
this.updateMintingAccounts();
|
||||
|
||||
window.addEventListener("contextmenu", (event) => {
|
||||
event.preventDefault();
|
||||
this._textMenu(event)
|
||||
});
|
||||
window.addEventListener("click", () => {
|
||||
parentEpml.request('closeCopyTextMenu', null)
|
||||
});
|
||||
window.onkeyup = (e) => {
|
||||
if (e.keyCode === 27) parentEpml.request('closeCopyTextMenu', null)
|
||||
}
|
||||
|
||||
// Calculate HH MM SS from Milliseconds...
|
||||
const convertMsToTime = (milliseconds) => {
|
||||
let day, hour, minute, seconds;
|
||||
seconds = Math.floor(milliseconds / 1000);
|
||||
minute = Math.floor(seconds / 60);
|
||||
seconds = seconds % 60;
|
||||
hour = Math.floor(minute / 60);
|
||||
minute = minute % 60;
|
||||
day = Math.floor(hour / 24);
|
||||
hour = hour % 24;
|
||||
if (isNaN(day)) {
|
||||
return "offline";
|
||||
}
|
||||
return day + "d " + hour + "h " + minute + "m";
|
||||
};
|
||||
firstUpdated() {
|
||||
|
||||
const getNodeUpTime = () => {
|
||||
parentEpml
|
||||
.request("apiCall", {
|
||||
url: `/admin/uptime`,
|
||||
})
|
||||
.then((res) => {
|
||||
this.upTime = "";
|
||||
setTimeout(() => {
|
||||
this.upTime = convertMsToTime(res);
|
||||
}, 1);
|
||||
// Call updateMintingAccounts
|
||||
this.updateMintingAccounts();
|
||||
|
||||
window.addEventListener("contextmenu", (event) => {
|
||||
event.preventDefault();
|
||||
this._textMenu(event)
|
||||
});
|
||||
|
||||
setTimeout(getNodeUpTime, this.config.user.nodeSettings.pingInterval);
|
||||
};
|
||||
|
||||
const updatePeers = () => {
|
||||
parentEpml
|
||||
.request("apiCall", {
|
||||
url: `/peers`,
|
||||
})
|
||||
.then((res) => {
|
||||
setTimeout(() => {
|
||||
this.peers = res;
|
||||
}, 1);
|
||||
window.addEventListener("click", () => {
|
||||
parentEpml.request('closeCopyTextMenu', null)
|
||||
});
|
||||
|
||||
setTimeout(updatePeers, this.config.user.nodeSettings.pingInterval);
|
||||
};
|
||||
|
||||
const getNodeConfig = () => {
|
||||
parentEpml.request("getNodeConfig").then((res) => {
|
||||
setTimeout(() => {
|
||||
this.nodeConfig = res;
|
||||
}, 1);
|
||||
let myNode = window.parent.reduxStore.getState().app.nodeConfig
|
||||
.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node];
|
||||
this.nodeDomain = myNode.domain + ":" + myNode.port;
|
||||
});
|
||||
|
||||
setTimeout(getNodeConfig, 1000);
|
||||
};
|
||||
|
||||
let configLoaded = false;
|
||||
parentEpml.ready().then(() => {
|
||||
parentEpml.subscribe("config", async c => {
|
||||
if (!configLoaded) {
|
||||
setTimeout(getNodeUpTime, 1);
|
||||
setTimeout(updatePeers, 1);
|
||||
setTimeout(this.updateMintingAccounts, 1);
|
||||
setTimeout(getNodeConfig, 1);
|
||||
configLoaded = true;
|
||||
window.onkeyup = (e) => {
|
||||
if (e.keyCode === 27) parentEpml.request('closeCopyTextMenu', null)
|
||||
}
|
||||
this.config = JSON.parse(c);
|
||||
})
|
||||
parentEpml.subscribe('copy_menu_switch', async value => {
|
||||
if (value === 'false' && window.getSelection().toString().length !== 0) this.clearSelection();
|
||||
})
|
||||
});
|
||||
parentEpml.imReady();
|
||||
}
|
||||
|
||||
getApiKey() {
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node];
|
||||
let apiKey = myNode.apiKey;
|
||||
return apiKey;
|
||||
}
|
||||
// Calculate HH MM SS from Milliseconds...
|
||||
const convertMsToTime = (milliseconds) => {
|
||||
let day, hour, minute, seconds;
|
||||
seconds = Math.floor(milliseconds / 1000);
|
||||
minute = Math.floor(seconds / 60);
|
||||
seconds = seconds % 60;
|
||||
hour = Math.floor(minute / 60);
|
||||
minute = minute % 60;
|
||||
day = Math.floor(hour / 24);
|
||||
hour = hour % 24;
|
||||
if (isNaN(day)) {
|
||||
return "offline";
|
||||
}
|
||||
return day + "d " + hour + "h " + minute + "m";
|
||||
};
|
||||
|
||||
clearSelection() {
|
||||
window.getSelection().removeAllRanges()
|
||||
window.parent.getSelection().removeAllRanges()
|
||||
}
|
||||
const getNodeUpTime = () => {
|
||||
parentEpml
|
||||
.request("apiCall", {
|
||||
url: `/admin/uptime`,
|
||||
})
|
||||
.then((res) => {
|
||||
this.upTime = "";
|
||||
setTimeout(() => {
|
||||
this.upTime = convertMsToTime(res);
|
||||
}, 1);
|
||||
});
|
||||
|
||||
isEmptyArray(arr) {
|
||||
if (!arr) return true;
|
||||
return arr.length === 0;
|
||||
}
|
||||
setTimeout(getNodeUpTime, this.config.user.nodeSettings.pingInterval);
|
||||
};
|
||||
|
||||
const updatePeers = () => {
|
||||
parentEpml
|
||||
.request("apiCall", {
|
||||
url: `/peers`,
|
||||
})
|
||||
.then((res) => {
|
||||
setTimeout(() => {
|
||||
this.peers = res;
|
||||
}, 1);
|
||||
});
|
||||
|
||||
setTimeout(updatePeers, this.config.user.nodeSettings.pingInterval);
|
||||
};
|
||||
|
||||
const getNodeConfig = () => {
|
||||
parentEpml.request("getNodeConfig").then((res) => {
|
||||
setTimeout(() => {
|
||||
this.nodeConfig = res;
|
||||
}, 1);
|
||||
let myNode = window.parent.reduxStore.getState().app.nodeConfig
|
||||
.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node];
|
||||
this.nodeDomain = myNode.domain + ":" + myNode.port;
|
||||
});
|
||||
|
||||
setTimeout(getNodeConfig, 1000);
|
||||
};
|
||||
|
||||
let configLoaded = false;
|
||||
parentEpml.ready().then(() => {
|
||||
parentEpml.subscribe("config", async c => {
|
||||
if (!configLoaded) {
|
||||
setTimeout(getNodeUpTime, 1);
|
||||
setTimeout(updatePeers, 1);
|
||||
setTimeout(this.updateMintingAccounts, 1);
|
||||
setTimeout(getNodeConfig, 1);
|
||||
configLoaded = true;
|
||||
}
|
||||
this.config = JSON.parse(c);
|
||||
})
|
||||
parentEpml.subscribe('copy_menu_switch', async value => {
|
||||
if (value === 'false' && window.getSelection().toString().length !== 0) this.clearSelection();
|
||||
})
|
||||
});
|
||||
parentEpml.imReady();
|
||||
}
|
||||
|
||||
getApiKey() {
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node];
|
||||
let apiKey = myNode.apiKey;
|
||||
return apiKey;
|
||||
}
|
||||
|
||||
clearSelection() {
|
||||
window.getSelection().removeAllRanges()
|
||||
window.parent.getSelection().removeAllRanges()
|
||||
}
|
||||
|
||||
isEmptyArray(arr) {
|
||||
if (!arr) return true;
|
||||
return arr.length === 0;
|
||||
}
|
||||
}
|
||||
|
||||
window.customElements.define("node-management", NodeManagement);
|
||||
|
@ -32,14 +32,14 @@
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: "Roboto", sans-serif;
|
||||
background: #fff;
|
||||
background-color: #fff;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<puzzles-info></puzzles-info>
|
||||
<script type="module" src="puzzles.js"></script>
|
||||
<script src="puzzles.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
@ -6,37 +6,36 @@ import { Epml } from '../../../epml.js'
|
||||
import nacl from '../../../../qortal-ui-crypto/api/deps/nacl-fast.js'
|
||||
import Base58 from '../../../../qortal-ui-crypto/api/deps/Base58.js'
|
||||
import publicKeyToAddress from '../../../../qortal-ui-crypto/api/wallet/publicKeyToAddress.js'
|
||||
|
||||
import '@material/mwc-icon'
|
||||
import '@material/mwc-button'
|
||||
import '@material/mwc-textfield'
|
||||
import '@material/mwc-dialog'
|
||||
import '@material/mwc-slider'
|
||||
|
||||
import '@polymer/paper-spinner/paper-spinner-lite.js'
|
||||
import '@vaadin/vaadin-grid/vaadin-grid.js'
|
||||
import '@vaadin/vaadin-grid/theme/material/all-imports.js'
|
||||
import '@vaadin/grid/vaadin-grid.js'
|
||||
import '@vaadin/grid/theme/material/all-imports.js'
|
||||
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
||||
|
||||
const DEFAULT_FEE = 0.001
|
||||
const PAYMENT_TX_TYPE = 2
|
||||
|
||||
class Puzzles extends LitElement {
|
||||
static get properties() {
|
||||
return {
|
||||
loading: { type: Boolean },
|
||||
invalid: { type: Boolean },
|
||||
puzzles: { type: Array },
|
||||
solved: { type: Object },
|
||||
selectedAddress: { type: Object },
|
||||
selectedPuzzle: { type: Object },
|
||||
error: { type: Boolean },
|
||||
message: { type: String }
|
||||
}
|
||||
}
|
||||
static get properties() {
|
||||
return {
|
||||
loading: { type: Boolean },
|
||||
invalid: { type: Boolean },
|
||||
puzzles: { type: Array },
|
||||
solved: { type: Object },
|
||||
selectedAddress: { type: Object },
|
||||
selectedPuzzle: { type: Object },
|
||||
error: { type: Boolean },
|
||||
message: { type: String }
|
||||
}
|
||||
}
|
||||
|
||||
static get styles() {
|
||||
return css`
|
||||
static get styles() {
|
||||
return css`
|
||||
* {
|
||||
--mdc-theme-primary: rgb(3, 169, 244);
|
||||
--mdc-theme-secondary: var(--mdc-theme-primary);
|
||||
@ -65,48 +64,48 @@ class Puzzles extends LitElement {
|
||||
font-size: smaller;
|
||||
}
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
this.loading = false
|
||||
this.invalid = true
|
||||
this.puzzles = []
|
||||
this.solved = {}
|
||||
this.selectedAddress = {}
|
||||
this.selectedPuzzle = {}
|
||||
this.error = false
|
||||
this.message = ''
|
||||
}
|
||||
constructor() {
|
||||
super()
|
||||
this.loading = false
|
||||
this.invalid = true
|
||||
this.puzzles = []
|
||||
this.solved = {}
|
||||
this.selectedAddress = {}
|
||||
this.selectedPuzzle = {}
|
||||
this.error = false
|
||||
this.message = ''
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
render() {
|
||||
return html`
|
||||
<div id="puzzle-page">
|
||||
<div style="min-height:48px; display: flex; padding-bottom: 6px;">
|
||||
<h3 style="margin: 0; flex: 1; padding-top: 8px; display: inline;">Puzzles</h3>
|
||||
</div>
|
||||
|
||||
<vaadin-grid id="puzzlesGrid" style="height:auto;" ?hidden="${this.isEmptyArray(this.puzzles)}" .items="${this.puzzles}" height-by-rows>
|
||||
<vaadin-grid-column auto-width header="Reward" .renderer=${(root, column, data) => {
|
||||
if (data.item.isSolved) {
|
||||
render(html`<span style="font-size: smaller;">SOLVED by ${data.item.winner}</span>`, root)
|
||||
} else {
|
||||
render(html`<span>${data.item.reward} QORT</span>`, root)
|
||||
}
|
||||
}}></vaadin-grid-column>
|
||||
<div class="divCard">
|
||||
<vaadin-grid theme="compact" id="puzzlesGrid" ?hidden="${this.isEmptyArray(this.puzzles)}" .items="${this.puzzles}" aria-label="Puzzles" all-rows-visible>
|
||||
<vaadin-grid-column auto-width header="Reward" .renderer=${(root, column, data) => {
|
||||
if (data.item.isSolved) {
|
||||
render(html`<span style="font-size: smaller;">SOLVED by ${data.item.winner}</span>`, root)
|
||||
} else {
|
||||
render(html`<span>${data.item.reward} QORT</span>`, root)
|
||||
}
|
||||
}}></vaadin-grid-column>
|
||||
<vaadin-grid-column auto-width path="name"></vaadin-grid-column>
|
||||
<vaadin-grid-column auto-width path="description"></vaadin-grid-column>
|
||||
<vaadin-grid-column auto-width path="clue" style="font-family: monospace; font-size: smaller;"></vaadin-grid-column>
|
||||
<vaadin-grid-column width="12em" header="Action" .renderer=${(root, column, data) => {
|
||||
if (data.item.isSolved) {
|
||||
render(html``, root)
|
||||
} else {
|
||||
render(html`<mwc-button @click=${() => this.guessPuzzle(data.item)}><mwc-icon>queue</mwc-icon>Guess</mwc-button>`, root)
|
||||
}
|
||||
}}></vaadin-grid-column>
|
||||
</vaadin-grid>
|
||||
if (data.item.isSolved) {
|
||||
render(html``, root)
|
||||
} else {
|
||||
render(html`<mwc-button @click=${() => this.guessPuzzle(data.item)}><mwc-icon>queue</mwc-icon>Guess</mwc-button>`, root)
|
||||
}
|
||||
}}></vaadin-grid-column>
|
||||
</vaadin-grid>
|
||||
|
||||
<mwc-dialog id="puzzleGuessDialog" scrimClickAction="${this.loading ? '' : 'close'}">
|
||||
<mwc-dialog id="puzzleGuessDialog" scrimClickAction="${this.loading ? '' : 'close'}">
|
||||
<div>Enter your guess to solve this puzzle and win ${this.selectedPuzzle.reward} QORT:</div>
|
||||
<br>
|
||||
<div id="puzzleGuessName">Name: ${this.selectedPuzzle.name}</div>
|
||||
@ -122,7 +121,8 @@ class Puzzles extends LitElement {
|
||||
<paper-spinner-lite
|
||||
style="margin-top:12px;"
|
||||
?active="${this.loading}"
|
||||
alt="Claiming puzzle reward"></paper-spinner-lite>
|
||||
alt="Claiming puzzle reward">
|
||||
</paper-spinner-lite>
|
||||
</span>
|
||||
<span ?hidden=${this.message === ''} style="${this.error ? 'color:red;' : ''}">
|
||||
${this.message}
|
||||
@ -145,317 +145,317 @@ class Puzzles extends LitElement {
|
||||
</mwc-dialog>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
window.addEventListener("contextmenu", (event) => {
|
||||
event.preventDefault();
|
||||
this._textMenu(event)
|
||||
});
|
||||
firstUpdated() {
|
||||
window.addEventListener("contextmenu", (event) => {
|
||||
event.preventDefault();
|
||||
this._textMenu(event)
|
||||
});
|
||||
|
||||
window.addEventListener("click", () => {
|
||||
parentEpml.request('closeCopyTextMenu', null)
|
||||
});
|
||||
window.addEventListener("click", () => {
|
||||
parentEpml.request('closeCopyTextMenu', null)
|
||||
});
|
||||
|
||||
window.onkeyup = (e) => {
|
||||
if (e.keyCode === 27) {
|
||||
parentEpml.request('closeCopyTextMenu', null)
|
||||
}
|
||||
}
|
||||
window.onkeyup = (e) => {
|
||||
if (e.keyCode === 27) {
|
||||
parentEpml.request('closeCopyTextMenu', null)
|
||||
}
|
||||
}
|
||||
|
||||
const textBox = this.shadowRoot.getElementById("puzzleGuess")
|
||||
const textBox = this.shadowRoot.getElementById("puzzleGuess")
|
||||
|
||||
// keep track of input validity so we can enabled/disable submit button
|
||||
textBox.validityTransform = (newValue, nativeValidity) => {
|
||||
this.invalid = !nativeValidity.valid
|
||||
return nativeValidity
|
||||
}
|
||||
// keep track of input validity so we can enabled/disable submit button
|
||||
textBox.validityTransform = (newValue, nativeValidity) => {
|
||||
this.invalid = !nativeValidity.valid
|
||||
return nativeValidity
|
||||
}
|
||||
|
||||
const getPuzzleGroupMembers = async () => {
|
||||
return await parentEpml.request('apiCall', {
|
||||
url: `/groups/members/165`
|
||||
})
|
||||
}
|
||||
const getPuzzleGroupMembers = async () => {
|
||||
return await parentEpml.request('apiCall', {
|
||||
url: `/groups/members/165`
|
||||
})
|
||||
}
|
||||
|
||||
const getBalance = async(address) => {
|
||||
return await parentEpml.request('apiCall', {
|
||||
url: `/addresses/balance/${address}`
|
||||
})
|
||||
}
|
||||
const getBalance = async (address) => {
|
||||
return await parentEpml.request('apiCall', {
|
||||
url: `/addresses/balance/${address}`
|
||||
})
|
||||
}
|
||||
|
||||
const getName = async(memberAddress) => {
|
||||
let _names = await parentEpml.request('apiCall', {
|
||||
url: `/names/address/${memberAddress}`
|
||||
})
|
||||
const getName = async (memberAddress) => {
|
||||
let _names = await parentEpml.request('apiCall', {
|
||||
url: `/names/address/${memberAddress}`
|
||||
})
|
||||
|
||||
if (_names.length === 0) return "";
|
||||
if (_names.length === 0) return "";
|
||||
|
||||
return _names[0].name
|
||||
}
|
||||
return _names[0].name
|
||||
}
|
||||
|
||||
const getNameInfo = async(name) => {
|
||||
// We have to explicitly encode '#' to stop them being interpreted as in-page references
|
||||
name = name.replaceAll('#', '%23')
|
||||
const getNameInfo = async (name) => {
|
||||
// We have to explicitly encode '#' to stop them being interpreted as in-page references
|
||||
name = name.replaceAll('#', '%23')
|
||||
|
||||
return await parentEpml.request('apiCall', {
|
||||
url: `/names/${name}`
|
||||
})
|
||||
}
|
||||
return await parentEpml.request('apiCall', {
|
||||
url: `/names/${name}`
|
||||
})
|
||||
}
|
||||
|
||||
const getFirstOutgoingPayment = async(sender) => {
|
||||
let _payments = await parentEpml.request('apiCall', {
|
||||
url: `/transactions/search?confirmationStatus=CONFIRMED&limit=20&txType=PAYMENT&address=${sender}`
|
||||
})
|
||||
const getFirstOutgoingPayment = async (sender) => {
|
||||
let _payments = await parentEpml.request('apiCall', {
|
||||
url: `/transactions/search?confirmationStatus=CONFIRMED&limit=20&txType=PAYMENT&address=${sender}`
|
||||
})
|
||||
|
||||
return _payments.find(payment => payment.creatorAddress === sender)
|
||||
}
|
||||
return _payments.find(payment => payment.creatorAddress === sender)
|
||||
}
|
||||
|
||||
const updatePuzzles = async () => {
|
||||
let _puzzleGroupMembers = await getPuzzleGroupMembers()
|
||||
const updatePuzzles = async () => {
|
||||
let _puzzleGroupMembers = await getPuzzleGroupMembers()
|
||||
|
||||
let _puzzles = []
|
||||
let _puzzles = []
|
||||
|
||||
await Promise.all(_puzzleGroupMembers.members
|
||||
.sort((a, b) => b.joined - a.joined)
|
||||
.map(async (member) => {
|
||||
let _puzzleAddress = member.member
|
||||
await Promise.all(_puzzleGroupMembers.members
|
||||
.sort((a, b) => b.joined - a.joined)
|
||||
.map(async (member) => {
|
||||
let _puzzleAddress = member.member
|
||||
|
||||
if (member.isAdmin) return
|
||||
if (member.isAdmin) return
|
||||
|
||||
// Already solved? No need to refresh info
|
||||
if (this.solved[_puzzleAddress]) {
|
||||
_puzzles.push(this.solved[_puzzleAddress])
|
||||
return
|
||||
}
|
||||
// Already solved? No need to refresh info
|
||||
if (this.solved[_puzzleAddress]) {
|
||||
_puzzles.push(this.solved[_puzzleAddress])
|
||||
return
|
||||
}
|
||||
|
||||
let _name = await getName(_puzzleAddress)
|
||||
// No name???
|
||||
if (_name === "") return
|
||||
let _name = await getName(_puzzleAddress)
|
||||
// No name???
|
||||
if (_name === "") return
|
||||
|
||||
let _reward = await getBalance(_puzzleAddress)
|
||||
let _isSolved = _reward < 1.0;
|
||||
let _nameInfo = await getNameInfo(_name)
|
||||
let _reward = await getBalance(_puzzleAddress)
|
||||
let _isSolved = _reward < 1.0;
|
||||
let _nameInfo = await getNameInfo(_name)
|
||||
|
||||
let _nameData = JSON.parse(_nameInfo.data)
|
||||
let _nameData = JSON.parse(_nameInfo.data)
|
||||
|
||||
let _puzzle = {
|
||||
reward: _reward,
|
||||
address: _puzzleAddress,
|
||||
name: _name,
|
||||
description: _nameData.description,
|
||||
isSolved: _isSolved
|
||||
}
|
||||
let _puzzle = {
|
||||
reward: _reward,
|
||||
address: _puzzleAddress,
|
||||
name: _name,
|
||||
description: _nameData.description,
|
||||
isSolved: _isSolved
|
||||
}
|
||||
|
||||
if (!_isSolved && _nameData.clue)
|
||||
_puzzle.clue = _nameData.clue;
|
||||
if (!_isSolved && _nameData.clue)
|
||||
_puzzle.clue = _nameData.clue;
|
||||
|
||||
if (_isSolved) {
|
||||
// Info on winner
|
||||
let _payment = await getFirstOutgoingPayment(_puzzleAddress)
|
||||
_puzzle.winner = _payment.recipient
|
||||
// Does winner have a name?
|
||||
let _winnerName = await getName(_puzzle.winner)
|
||||
if (_winnerName) _puzzle.winner = _winnerName
|
||||
// Add to 'solved' map to prevent info refresh as it'll never change
|
||||
this.solved[_puzzleAddress] = _puzzle
|
||||
}
|
||||
if (_isSolved) {
|
||||
// Info on winner
|
||||
let _payment = await getFirstOutgoingPayment(_puzzleAddress)
|
||||
_puzzle.winner = _payment.recipient
|
||||
// Does winner have a name?
|
||||
let _winnerName = await getName(_puzzle.winner)
|
||||
if (_winnerName) _puzzle.winner = _winnerName
|
||||
// Add to 'solved' map to prevent info refresh as it'll never change
|
||||
this.solved[_puzzleAddress] = _puzzle
|
||||
}
|
||||
|
||||
_puzzles.push(_puzzle);
|
||||
}))
|
||||
_puzzles.push(_puzzle);
|
||||
}))
|
||||
|
||||
this.puzzles = _puzzles;
|
||||
this.puzzles = _puzzles;
|
||||
|
||||
setTimeout(updatePuzzles, 20000)
|
||||
}
|
||||
setTimeout(updatePuzzles, 20000)
|
||||
}
|
||||
|
||||
let configLoaded = false
|
||||
let configLoaded = false
|
||||
|
||||
parentEpml.ready().then(() => {
|
||||
parentEpml.subscribe('selected_address', async selectedAddress => {
|
||||
this.selectedAddress = {}
|
||||
selectedAddress = JSON.parse(selectedAddress)
|
||||
if (!selectedAddress || Object.entries(selectedAddress).length === 0) return
|
||||
this.selectedAddress = selectedAddress
|
||||
})
|
||||
parentEpml.ready().then(() => {
|
||||
parentEpml.subscribe('selected_address', async selectedAddress => {
|
||||
this.selectedAddress = {}
|
||||
selectedAddress = JSON.parse(selectedAddress)
|
||||
if (!selectedAddress || Object.entries(selectedAddress).length === 0) return
|
||||
this.selectedAddress = selectedAddress
|
||||
})
|
||||
|
||||
parentEpml.subscribe('config', c => {
|
||||
if (!configLoaded) {
|
||||
setTimeout(updatePuzzles, 1)
|
||||
configLoaded = true
|
||||
}
|
||||
this.config = JSON.parse(c)
|
||||
})
|
||||
parentEpml.subscribe('config', c => {
|
||||
if (!configLoaded) {
|
||||
setTimeout(updatePuzzles, 1)
|
||||
configLoaded = true
|
||||
}
|
||||
this.config = JSON.parse(c)
|
||||
})
|
||||
|
||||
parentEpml.subscribe('copy_menu_switch', async value => {
|
||||
if (value === 'false' && window.getSelection().toString().length !== 0) {
|
||||
this.clearSelection()
|
||||
}
|
||||
})
|
||||
parentEpml.subscribe('copy_menu_switch', async value => {
|
||||
if (value === 'false' && window.getSelection().toString().length !== 0) {
|
||||
this.clearSelection()
|
||||
}
|
||||
})
|
||||
|
||||
parentEpml.subscribe('frame_paste_menu_switch', async res => {
|
||||
res = JSON.parse(res)
|
||||
parentEpml.subscribe('frame_paste_menu_switch', async res => {
|
||||
res = JSON.parse(res)
|
||||
|
||||
if (res.isOpen === false && this.isPasteMenuOpen === true) {
|
||||
this.pasteToTextBox(textBox)
|
||||
this.isPasteMenuOpen = false
|
||||
}
|
||||
})
|
||||
})
|
||||
if (res.isOpen === false && this.isPasteMenuOpen === true) {
|
||||
this.pasteToTextBox(textBox)
|
||||
this.isPasteMenuOpen = false
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
parentEpml.imReady()
|
||||
parentEpml.imReady()
|
||||
|
||||
textBox.addEventListener('contextmenu', (event) => {
|
||||
const getSelectedText = () => {
|
||||
var text = "";
|
||||
textBox.addEventListener('contextmenu', (event) => {
|
||||
const getSelectedText = () => {
|
||||
var text = "";
|
||||
|
||||
if (typeof window.getSelection != "undefined") {
|
||||
text = window.getSelection().toString();
|
||||
} else if (typeof this.shadowRoot.selection != "undefined" && this.shadowRoot.selection.type == "Text") {
|
||||
text = this.shadowRoot.selection.createRange().text;
|
||||
}
|
||||
if (typeof window.getSelection != "undefined") {
|
||||
text = window.getSelection().toString();
|
||||
} else if (typeof this.shadowRoot.selection != "undefined" && this.shadowRoot.selection.type == "Text") {
|
||||
text = this.shadowRoot.selection.createRange().text;
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
const checkSelectedTextAndShowMenu = () => {
|
||||
let selectedText = getSelectedText();
|
||||
const checkSelectedTextAndShowMenu = () => {
|
||||
let selectedText = getSelectedText();
|
||||
|
||||
if (selectedText && typeof selectedText === 'string') {
|
||||
// ...
|
||||
} else {
|
||||
this.pasteMenu(event)
|
||||
this.isPasteMenuOpen = true
|
||||
if (selectedText && typeof selectedText === 'string') {
|
||||
// ...
|
||||
} else {
|
||||
this.pasteMenu(event)
|
||||
this.isPasteMenuOpen = true
|
||||
|
||||
// Prevent Default and Stop Event Bubbling
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
}
|
||||
}
|
||||
// Prevent Default and Stop Event Bubbling
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
}
|
||||
}
|
||||
|
||||
checkSelectedTextAndShowMenu()
|
||||
})
|
||||
}
|
||||
checkSelectedTextAndShowMenu()
|
||||
})
|
||||
}
|
||||
|
||||
async guessPuzzle(puzzle) {
|
||||
this.selectedPuzzle = puzzle
|
||||
this.shadowRoot.getElementById("puzzleGuess").value = ''
|
||||
this.shadowRoot.getElementById("puzzleGuess").checkValidity()
|
||||
this.message = ''
|
||||
this.invalid = true
|
||||
async guessPuzzle(puzzle) {
|
||||
this.selectedPuzzle = puzzle
|
||||
this.shadowRoot.getElementById("puzzleGuess").value = ''
|
||||
this.shadowRoot.getElementById("puzzleGuess").checkValidity()
|
||||
this.message = ''
|
||||
this.invalid = true
|
||||
|
||||
this.shadowRoot.querySelector('#puzzleGuessDialog').show()
|
||||
}
|
||||
this.shadowRoot.querySelector('#puzzleGuessDialog').show()
|
||||
}
|
||||
|
||||
async submitPuzzleGuess(e) {
|
||||
this.loading = true
|
||||
this.error = false
|
||||
async submitPuzzleGuess(e) {
|
||||
this.loading = true
|
||||
this.error = false
|
||||
|
||||
// Check for valid guess
|
||||
const guess = this.shadowRoot.getElementById("puzzleGuess").value
|
||||
// Check for valid guess
|
||||
const guess = this.shadowRoot.getElementById("puzzleGuess").value
|
||||
|
||||
let _rawGuess = Base58.decode(guess)
|
||||
let _keyPair = nacl.sign.keyPair.fromSeed(_rawGuess)
|
||||
let _rawGuess = Base58.decode(guess)
|
||||
let _keyPair = nacl.sign.keyPair.fromSeed(_rawGuess)
|
||||
|
||||
let _guessAddress = publicKeyToAddress(_keyPair.publicKey)
|
||||
let _guessAddress = publicKeyToAddress(_keyPair.publicKey)
|
||||
|
||||
console.log("Guess '" + _guessAddress + "' vs puzzle's address '" + this.selectedPuzzle.address + "'")
|
||||
if (_guessAddress !== this.selectedPuzzle.address) {
|
||||
this.error = true
|
||||
this.message = 'Guess incorrect!'
|
||||
this.loading = false
|
||||
return
|
||||
}
|
||||
console.log("Guess '" + _guessAddress + "' vs puzzle's address '" + this.selectedPuzzle.address + "'")
|
||||
if (_guessAddress !== this.selectedPuzzle.address) {
|
||||
this.error = true
|
||||
this.message = 'Guess incorrect!'
|
||||
this.loading = false
|
||||
return
|
||||
}
|
||||
|
||||
// Get Last Ref
|
||||
const getLastRef = async (address) => {
|
||||
let myRef = await parentEpml.request('apiCall', {
|
||||
url: `/addresses/lastreference/${address}`
|
||||
})
|
||||
return myRef
|
||||
}
|
||||
// Get Last Ref
|
||||
const getLastRef = async (address) => {
|
||||
let myRef = await parentEpml.request('apiCall', {
|
||||
url: `/addresses/lastreference/${address}`
|
||||
})
|
||||
return myRef
|
||||
}
|
||||
|
||||
let lastRef = await getLastRef(_guessAddress)
|
||||
let amount = this.selectedPuzzle.reward - DEFAULT_FEE;
|
||||
let recipientAddress = this.selectedAddress.address
|
||||
let txnParams = {
|
||||
recipient: recipientAddress,
|
||||
amount: amount,
|
||||
lastReference: lastRef,
|
||||
fee: DEFAULT_FEE
|
||||
}
|
||||
let lastRef = await getLastRef(_guessAddress)
|
||||
let amount = this.selectedPuzzle.reward - DEFAULT_FEE;
|
||||
let recipientAddress = this.selectedAddress.address
|
||||
let txnParams = {
|
||||
recipient: recipientAddress,
|
||||
amount: amount,
|
||||
lastReference: lastRef,
|
||||
fee: DEFAULT_FEE
|
||||
}
|
||||
|
||||
// Mostly copied from qortal-ui-core/src/plugins/routes.js
|
||||
let txnResponse = await parentEpml.request('standaloneTransaction', {
|
||||
type: 2,
|
||||
keyPair: {
|
||||
publicKey: _keyPair.publicKey,
|
||||
privateKey: _keyPair.secretKey
|
||||
},
|
||||
params: txnParams
|
||||
})
|
||||
// Mostly copied from qortal-ui-core/src/plugins/routes.js
|
||||
let txnResponse = await parentEpml.request('standaloneTransaction', {
|
||||
type: 2,
|
||||
keyPair: {
|
||||
publicKey: _keyPair.publicKey,
|
||||
privateKey: _keyPair.secretKey
|
||||
},
|
||||
params: txnParams
|
||||
})
|
||||
|
||||
if (txnResponse.success) {
|
||||
this.message = 'Reward claim submitted - check wallet for reward!'
|
||||
} else {
|
||||
this.error = true
|
||||
if (txnResponse.data) {
|
||||
this.message = "Error while claiming reward: " + txnResponse.data.message
|
||||
} else {
|
||||
this.message = "Error while claiming reward: " + txnResponse.message
|
||||
}
|
||||
}
|
||||
if (txnResponse.success) {
|
||||
this.message = 'Reward claim submitted - check wallet for reward!'
|
||||
} else {
|
||||
this.error = true
|
||||
if (txnResponse.data) {
|
||||
this.message = "Error while claiming reward: " + txnResponse.data.message
|
||||
} else {
|
||||
this.message = "Error while claiming reward: " + txnResponse.message
|
||||
}
|
||||
}
|
||||
|
||||
this.loading = false
|
||||
}
|
||||
this.loading = false
|
||||
}
|
||||
|
||||
pasteToTextBox(textBox) {
|
||||
// Return focus to the window
|
||||
window.focus()
|
||||
pasteToTextBox(textBox) {
|
||||
// Return focus to the window
|
||||
window.focus()
|
||||
|
||||
navigator.clipboard.readText().then(clipboardText => {
|
||||
navigator.clipboard.readText().then(clipboardText => {
|
||||
|
||||
textBox.value += clipboardText
|
||||
textBox.focus()
|
||||
});
|
||||
}
|
||||
textBox.value += clipboardText
|
||||
textBox.focus()
|
||||
});
|
||||
}
|
||||
|
||||
pasteMenu(event) {
|
||||
let eventObject = { pageX: event.pageX, pageY: event.pageY, clientX: event.clientX, clientY: event.clientY }
|
||||
parentEpml.request('openFramePasteMenu', eventObject)
|
||||
}
|
||||
pasteMenu(event) {
|
||||
let eventObject = { pageX: event.pageX, pageY: event.pageY, clientX: event.clientX, clientY: event.clientY }
|
||||
parentEpml.request('openFramePasteMenu', eventObject)
|
||||
}
|
||||
|
||||
_textMenu(event) {
|
||||
const getSelectedText = () => {
|
||||
var text = "";
|
||||
if (typeof window.getSelection != "undefined") {
|
||||
text = window.getSelection().toString();
|
||||
} else if (typeof this.shadowRoot.selection != "undefined" && this.shadowRoot.selection.type == "Text") {
|
||||
text = this.shadowRoot.selection.createRange().text;
|
||||
}
|
||||
return text;
|
||||
}
|
||||
_textMenu(event) {
|
||||
const getSelectedText = () => {
|
||||
var text = "";
|
||||
if (typeof window.getSelection != "undefined") {
|
||||
text = window.getSelection().toString();
|
||||
} else if (typeof this.shadowRoot.selection != "undefined" && this.shadowRoot.selection.type == "Text") {
|
||||
text = this.shadowRoot.selection.createRange().text;
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
const checkSelectedTextAndShowMenu = () => {
|
||||
let selectedText = getSelectedText();
|
||||
if (selectedText && typeof selectedText === 'string') {
|
||||
let _eve = { pageX: event.pageX, pageY: event.pageY, clientX: event.clientX, clientY: event.clientY }
|
||||
let textMenuObject = { selectedText: selectedText, eventObject: _eve, isFrame: true }
|
||||
parentEpml.request('openCopyTextMenu', textMenuObject)
|
||||
}
|
||||
}
|
||||
const checkSelectedTextAndShowMenu = () => {
|
||||
let selectedText = getSelectedText();
|
||||
if (selectedText && typeof selectedText === 'string') {
|
||||
let _eve = { pageX: event.pageX, pageY: event.pageY, clientX: event.clientX, clientY: event.clientY }
|
||||
let textMenuObject = { selectedText: selectedText, eventObject: _eve, isFrame: true }
|
||||
parentEpml.request('openCopyTextMenu', textMenuObject)
|
||||
}
|
||||
}
|
||||
|
||||
checkSelectedTextAndShowMenu()
|
||||
}
|
||||
checkSelectedTextAndShowMenu()
|
||||
}
|
||||
|
||||
isEmptyArray(arr) {
|
||||
if (!arr) { return true }
|
||||
return arr.length === 0
|
||||
}
|
||||
isEmptyArray(arr) {
|
||||
if (!arr) { return true }
|
||||
return arr.length === 0
|
||||
}
|
||||
|
||||
clearSelection() {
|
||||
window.getSelection().removeAllRanges()
|
||||
window.parent.getSelection().removeAllRanges()
|
||||
}
|
||||
clearSelection() {
|
||||
window.getSelection().removeAllRanges()
|
||||
window.parent.getSelection().removeAllRanges()
|
||||
}
|
||||
}
|
||||
|
||||
window.customElements.define('puzzles-info', Puzzles)
|
||||
|
@ -12,23 +12,23 @@ import '@polymer/paper-progress/paper-progress.js'
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
||||
|
||||
class WebBrowser extends LitElement {
|
||||
static get properties() {
|
||||
return {
|
||||
url: { type: String },
|
||||
name: { type: String },
|
||||
service: { type: String },
|
||||
identifier: { type: String },
|
||||
followedNames: { type: Array },
|
||||
blockedNames: { type: Array },
|
||||
}
|
||||
}
|
||||
static get properties() {
|
||||
return {
|
||||
url: { type: String },
|
||||
name: { type: String },
|
||||
service: { type: String },
|
||||
identifier: { type: String },
|
||||
followedNames: { type: Array },
|
||||
blockedNames: { type: Array }
|
||||
}
|
||||
}
|
||||
|
||||
static get observers() {
|
||||
return ['_kmxKeyUp(amount)']
|
||||
}
|
||||
static get observers() {
|
||||
return ['_kmxKeyUp(amount)']
|
||||
}
|
||||
|
||||
static get styles() {
|
||||
return css`
|
||||
static get styles() {
|
||||
return css`
|
||||
* {
|
||||
--mdc-theme-primary: rgb(3, 169, 244);
|
||||
--mdc-theme-secondary: var(--mdc-theme-primary);
|
||||
@ -40,8 +40,6 @@ class WebBrowser extends LitElement {
|
||||
}
|
||||
|
||||
#websitesWrapper .buttons {
|
||||
/* --paper-button-ink-color: var(--paper-green-500);
|
||||
color: var(--paper-green-500); */
|
||||
width: auto !important;
|
||||
}
|
||||
|
||||
@ -94,10 +92,10 @@ class WebBrowser extends LitElement {
|
||||
}
|
||||
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
render() {
|
||||
return html`
|
||||
<div id="websitesWrapper" style="width:auto; padding:10px; background: #fff;">
|
||||
<div class="layout horizontal center">
|
||||
<div class="address-bar">
|
||||
@ -118,9 +116,9 @@ class WebBrowser extends LitElement {
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
renderFollowUnfollowButton() {
|
||||
renderFollowUnfollowButton() {
|
||||
// Only show the follow/unfollow button if we have permission to modify the list on this node
|
||||
if (this.followedNames == null || !Array.isArray(this.followedNames)) {
|
||||
return html``
|
||||
@ -153,50 +151,50 @@ class WebBrowser extends LitElement {
|
||||
}
|
||||
|
||||
|
||||
// Navigation
|
||||
// Navigation
|
||||
|
||||
goBack() {
|
||||
window.history.back();
|
||||
goBack() {
|
||||
window.history.back();
|
||||
}
|
||||
|
||||
goForward() {
|
||||
window.history.forward();
|
||||
goForward() {
|
||||
window.history.forward();
|
||||
}
|
||||
|
||||
refresh() {
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
goBackToList() {
|
||||
window.location="../index.html";
|
||||
refresh() {
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
follow() {
|
||||
this.followName(this.name);
|
||||
goBackToList() {
|
||||
window.location = "../index.html";
|
||||
}
|
||||
|
||||
unfollow() {
|
||||
this.unfollowName(this.name);
|
||||
follow() {
|
||||
this.followName(this.name);
|
||||
}
|
||||
|
||||
block() {
|
||||
this.blockName(this.name);
|
||||
unfollow() {
|
||||
this.unfollowName(this.name);
|
||||
}
|
||||
|
||||
unblock() {
|
||||
this.unblockName(this.name);
|
||||
block() {
|
||||
this.blockName(this.name);
|
||||
}
|
||||
|
||||
delete() {
|
||||
this.deleteCurrentResource();
|
||||
unblock() {
|
||||
this.unblockName(this.name);
|
||||
}
|
||||
|
||||
delete() {
|
||||
this.deleteCurrentResource();
|
||||
}
|
||||
|
||||
|
||||
async followName(name) {
|
||||
async followName(name) {
|
||||
let items = [
|
||||
name
|
||||
]
|
||||
let namesJsonString = JSON.stringify({"items": items})
|
||||
let namesJsonString = JSON.stringify({ "items": items })
|
||||
|
||||
let ret = await parentEpml.request('apiCall', {
|
||||
url: `/lists/followedNames?apiKey=${this.getApiKey()}`,
|
||||
@ -211,7 +209,7 @@ class WebBrowser extends LitElement {
|
||||
// Successfully followed - add to local list
|
||||
// Remove it first by filtering the list - doing it this way ensures the UI updates
|
||||
// immediately, as apposed to only adding if it doesn't already exist
|
||||
this.followedNames = this.followedNames.filter(item => item != name);
|
||||
this.followedNames = this.followedNames.filter(item => item != name);
|
||||
this.followedNames.push(name)
|
||||
}
|
||||
else {
|
||||
@ -225,7 +223,7 @@ class WebBrowser extends LitElement {
|
||||
let items = [
|
||||
name
|
||||
]
|
||||
let namesJsonString = JSON.stringify({"items": items})
|
||||
let namesJsonString = JSON.stringify({ "items": items })
|
||||
|
||||
let ret = await parentEpml.request('apiCall', {
|
||||
url: `/lists/followedNames?apiKey=${this.getApiKey()}`,
|
||||
@ -238,7 +236,7 @@ class WebBrowser extends LitElement {
|
||||
|
||||
if (ret === true) {
|
||||
// Successfully unfollowed - remove from local list
|
||||
this.followedNames = this.followedNames.filter(item => item != name);
|
||||
this.followedNames = this.followedNames.filter(item => item != name);
|
||||
}
|
||||
else {
|
||||
parentEpml.request('showSnackBar', 'Error occurred when trying to unfollow this registered name. Please try again')
|
||||
@ -251,7 +249,7 @@ class WebBrowser extends LitElement {
|
||||
let items = [
|
||||
name
|
||||
]
|
||||
let namesJsonString = JSON.stringify({"items": items})
|
||||
let namesJsonString = JSON.stringify({ "items": items })
|
||||
|
||||
let ret = await parentEpml.request('apiCall', {
|
||||
url: `/lists/blockedNames?apiKey=${this.getApiKey()}`,
|
||||
@ -266,7 +264,7 @@ class WebBrowser extends LitElement {
|
||||
// Successfully blocked - add to local list
|
||||
// Remove it first by filtering the list - doing it this way ensures the UI updates
|
||||
// immediately, as apposed to only adding if it doesn't already exist
|
||||
this.blockedNames = this.blockedNames.filter(item => item != name);
|
||||
this.blockedNames = this.blockedNames.filter(item => item != name);
|
||||
this.blockedNames.push(name)
|
||||
}
|
||||
else {
|
||||
@ -280,7 +278,7 @@ class WebBrowser extends LitElement {
|
||||
let items = [
|
||||
name
|
||||
]
|
||||
let namesJsonString = JSON.stringify({"items": items})
|
||||
let namesJsonString = JSON.stringify({ "items": items })
|
||||
|
||||
let ret = await parentEpml.request('apiCall', {
|
||||
url: `/lists/blockedNames?apiKey=${this.getApiKey()}`,
|
||||
@ -293,7 +291,7 @@ class WebBrowser extends LitElement {
|
||||
|
||||
if (ret === true) {
|
||||
// Successfully unblocked - remove from local list
|
||||
this.blockedNames = this.blockedNames.filter(item => item != name);
|
||||
this.blockedNames = this.blockedNames.filter(item => item != name);
|
||||
}
|
||||
else {
|
||||
parentEpml.request('showSnackBar', 'Error occurred when trying to unblock this registered name. Please try again')
|
||||
@ -302,14 +300,14 @@ class WebBrowser extends LitElement {
|
||||
return ret
|
||||
}
|
||||
|
||||
async deleteCurrentResource() {
|
||||
if (this.followedNames.indexOf(this.name) != -1) {
|
||||
async deleteCurrentResource() {
|
||||
if (this.followedNames.indexOf(this.name) != -1) {
|
||||
// Following name - so deleting won't work
|
||||
parentEpml.request('showSnackBar', "Can't delete data from followed names. Please unfollow first.");
|
||||
return;
|
||||
parentEpml.request('showSnackBar', "Can't delete data from followed names. Please unfollow first.");
|
||||
return;
|
||||
}
|
||||
|
||||
let identifier = this.identifier == null ? "default" : resource.identifier;
|
||||
let identifier = this.identifier == null ? "default" : resource.identifier;
|
||||
|
||||
let ret = await parentEpml.request('apiCall', {
|
||||
url: `/arbitrary/resource/${this.service}/${this.name}/${identifier}?apiKey=${this.getApiKey()}`,
|
||||
@ -328,52 +326,51 @@ class WebBrowser extends LitElement {
|
||||
|
||||
|
||||
|
||||
// Helper Functions (Re-Used in Most part of the UI )
|
||||
// Helper Functions (Re-Used in Most part of the UI )
|
||||
|
||||
textColor(color) {
|
||||
return color == 'light' ? 'rgba(255,255,255,0.7)' : 'rgba(0,0,0,0.87)'
|
||||
}
|
||||
textColor(color) {
|
||||
return color == 'light' ? 'rgba(255,255,255,0.7)' : 'rgba(0,0,0,0.87)'
|
||||
}
|
||||
|
||||
_textMenu(event) {
|
||||
const getSelectedText = () => {
|
||||
var text = ''
|
||||
if (typeof window.getSelection != 'undefined') {
|
||||
text = window.getSelection().toString()
|
||||
} else if (typeof this.shadowRoot.selection != 'undefined' && this.shadowRoot.selection.type == 'Text') {
|
||||
text = this.shadowRoot.selection.createRange().text
|
||||
}
|
||||
return text
|
||||
}
|
||||
_textMenu(event) {
|
||||
const getSelectedText = () => {
|
||||
var text = ''
|
||||
if (typeof window.getSelection != 'undefined') {
|
||||
text = window.getSelection().toString()
|
||||
} else if (typeof this.shadowRoot.selection != 'undefined' && this.shadowRoot.selection.type == 'Text') {
|
||||
text = this.shadowRoot.selection.createRange().text
|
||||
}
|
||||
return text
|
||||
}
|
||||
|
||||
const checkSelectedTextAndShowMenu = () => {
|
||||
let selectedText = getSelectedText()
|
||||
if (selectedText && typeof selectedText === 'string') {
|
||||
let _eve = { pageX: event.pageX, pageY: event.pageY, clientX: event.clientX, clientY: event.clientY }
|
||||
const checkSelectedTextAndShowMenu = () => {
|
||||
let selectedText = getSelectedText()
|
||||
if (selectedText && typeof selectedText === 'string') {
|
||||
let _eve = { pageX: event.pageX, pageY: event.pageY, clientX: event.clientX, clientY: event.clientY }
|
||||
|
||||
let textMenuObject = { selectedText: selectedText, eventObject: _eve, isFrame: true }
|
||||
let textMenuObject = { selectedText: selectedText, eventObject: _eve, isFrame: true }
|
||||
|
||||
parentEpml.request('openCopyTextMenu', textMenuObject)
|
||||
}
|
||||
}
|
||||
parentEpml.request('openCopyTextMenu', textMenuObject)
|
||||
}
|
||||
}
|
||||
|
||||
checkSelectedTextAndShowMenu()
|
||||
}
|
||||
checkSelectedTextAndShowMenu()
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
this.url = 'about:blank'
|
||||
constructor() {
|
||||
super()
|
||||
this.url = 'about:blank'
|
||||
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
this.name = urlParams.get('name');
|
||||
this.service = urlParams.get('service');
|
||||
this.identifier = null; // FUTURE: add support for identifiers
|
||||
|
||||
this.followedNames = []
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
this.name = urlParams.get('name');
|
||||
this.service = urlParams.get('service');
|
||||
// FUTURE: add support for identifiers
|
||||
this.identifier = null;
|
||||
this.followedNames = []
|
||||
this.blockedNames = []
|
||||
|
||||
|
||||
const getFollowedNames = async () => {
|
||||
// this.followedNames = []
|
||||
const getFollowedNames = async () => {
|
||||
|
||||
let followedNames = await parentEpml.request('apiCall', {
|
||||
url: `/lists/followedNames?apiKey=${this.getApiKey()}`
|
||||
@ -384,7 +381,6 @@ class WebBrowser extends LitElement {
|
||||
}
|
||||
|
||||
const getBlockedNames = async () => {
|
||||
// this.blockedNames = []
|
||||
|
||||
let blockedNames = await parentEpml.request('apiCall', {
|
||||
url: `/lists/blockedNames?apiKey=${this.getApiKey()}`
|
||||
@ -394,28 +390,28 @@ class WebBrowser extends LitElement {
|
||||
setTimeout(getBlockedNames, this.config.user.nodeSettings.pingInterval)
|
||||
}
|
||||
|
||||
const render = () => {
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
|
||||
const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port
|
||||
this.url = `${nodeUrl}/render/${this.service}/${this.name}`;
|
||||
const render = () => {
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
|
||||
const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port
|
||||
this.url = `${nodeUrl}/render/${this.service}/${this.name}`;
|
||||
}
|
||||
|
||||
const authorizeAndRender = () => {
|
||||
const authorizeAndRender = () => {
|
||||
parentEpml.request('apiCall', {
|
||||
url: `/render/authorize/${this.name}?apiKey=${this.getApiKey()}`,
|
||||
method: "POST"
|
||||
method: "POST"
|
||||
}).then(res => {
|
||||
console.log(res)
|
||||
if (res.error) {
|
||||
// Authorization problem - API key incorrect?
|
||||
}
|
||||
else {
|
||||
render()
|
||||
}
|
||||
console.log(res)
|
||||
if (res.error) {
|
||||
// Authorization problem - API key incorrect?
|
||||
}
|
||||
else {
|
||||
render()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
let configLoaded = false
|
||||
let configLoaded = false
|
||||
parentEpml.ready().then(() => {
|
||||
parentEpml.subscribe('selected_address', async selectedAddress => {
|
||||
this.selectedAddress = {}
|
||||
@ -424,10 +420,10 @@ class WebBrowser extends LitElement {
|
||||
this.selectedAddress = selectedAddress
|
||||
})
|
||||
parentEpml.subscribe('config', c => {
|
||||
this.config = JSON.parse(c)
|
||||
this.config = JSON.parse(c)
|
||||
if (!configLoaded) {
|
||||
authorizeAndRender()
|
||||
setTimeout(getFollowedNames, 1)
|
||||
setTimeout(getFollowedNames, 1)
|
||||
setTimeout(getBlockedNames, 1)
|
||||
configLoaded = true
|
||||
}
|
||||
@ -440,36 +436,36 @@ class WebBrowser extends LitElement {
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
firstUpdated() {
|
||||
|
||||
window.addEventListener('contextmenu', (event) => {
|
||||
event.preventDefault()
|
||||
this._textMenu(event)
|
||||
})
|
||||
window.addEventListener('contextmenu', (event) => {
|
||||
event.preventDefault()
|
||||
this._textMenu(event)
|
||||
})
|
||||
|
||||
window.addEventListener('click', () => {
|
||||
parentEpml.request('closeCopyTextMenu', null)
|
||||
})
|
||||
window.addEventListener('click', () => {
|
||||
parentEpml.request('closeCopyTextMenu', null)
|
||||
})
|
||||
|
||||
window.onkeyup = (e) => {
|
||||
if (e.keyCode === 27) {
|
||||
parentEpml.request('closeCopyTextMenu', null)
|
||||
}
|
||||
}
|
||||
}
|
||||
window.onkeyup = (e) => {
|
||||
if (e.keyCode === 27) {
|
||||
parentEpml.request('closeCopyTextMenu', null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getApiKey() {
|
||||
getApiKey() {
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node];
|
||||
let apiKey = myNode.apiKey;
|
||||
return apiKey;
|
||||
}
|
||||
|
||||
clearSelection() {
|
||||
window.getSelection().removeAllRanges()
|
||||
window.parent.getSelection().removeAllRanges()
|
||||
}
|
||||
clearSelection() {
|
||||
window.getSelection().removeAllRanges()
|
||||
window.parent.getSelection().removeAllRanges()
|
||||
}
|
||||
}
|
||||
|
||||
window.customElements.define('web-browser', WebBrowser)
|
||||
|
@ -32,6 +32,7 @@
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: "Roboto", sans-serif;
|
||||
background-color: #fff;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
@ -4,9 +4,8 @@ import { Epml } from '../../../../epml'
|
||||
|
||||
import '@material/mwc-icon'
|
||||
import '@material/mwc-button'
|
||||
|
||||
import '@vaadin/vaadin-grid/vaadin-grid.js'
|
||||
import '@vaadin/vaadin-grid/theme/material/all-imports.js'
|
||||
import '@vaadin/grid/vaadin-grid.js'
|
||||
import '@vaadin/grid/theme/material/all-imports.js'
|
||||
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
||||
|
||||
@ -147,7 +146,7 @@ class DataManagement extends LitElement {
|
||||
</div>
|
||||
<div class="divCard">
|
||||
<h3 style="margin: 0; margin-bottom: 1em; text-align: center;">Data hosted by this node</h3>
|
||||
<vaadin-grid id="resourcesGrid" style="height:auto;" ?hidden="${this.isEmptyArray(this.datres)}" page-size="20" height-by-rows>
|
||||
<vaadin-grid theme="compact" id="resourcesGrid" ?hidden="${this.isEmptyArray(this.datres)}" aria-label="Data Hosted" page-size="20" all-rows-visible>
|
||||
<vaadin-grid-column header="Registered Name" path="name"></vaadin-grid-column>
|
||||
<vaadin-grid-column header="Service" path="service"></vaadin-grid-column>
|
||||
<vaadin-grid-column header="Identifier" .renderer=${(root, column, data) => {
|
||||
|
@ -39,7 +39,6 @@
|
||||
|
||||
<body>
|
||||
<websites-list></websites-list>
|
||||
|
||||
<script src="websites.js"></script>
|
||||
</body>
|
||||
|
||||
|
@ -32,6 +32,7 @@
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: "Roboto", sans-serif;
|
||||
background-color: #fff;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
@ -12,39 +12,37 @@ import '@polymer/paper-progress/paper-progress.js'
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
||||
|
||||
class PublishData extends LitElement {
|
||||
static get properties() {
|
||||
return {
|
||||
name: { type: String },
|
||||
service: { type: String },
|
||||
identifier: { type: String },
|
||||
category: { type: String },
|
||||
uploadType: { type: String },
|
||||
showName: { type: Boolean },
|
||||
showService: { type: Boolean },
|
||||
showIdentifier: { type: Boolean },
|
||||
serviceLowercase: { type: String },
|
||||
names: { type: Array },
|
||||
registeredName: { type: String },
|
||||
selectedName: { type: String },
|
||||
path: { type: String },
|
||||
portForwardingEnabled: { type: Boolean },
|
||||
//selectedAddress: { type: Object },
|
||||
static get properties() {
|
||||
return {
|
||||
name: { type: String },
|
||||
service: { type: String },
|
||||
identifier: { type: String },
|
||||
category: { type: String },
|
||||
uploadType: { type: String },
|
||||
showName: { type: Boolean },
|
||||
showService: { type: Boolean },
|
||||
showIdentifier: { type: Boolean },
|
||||
serviceLowercase: { type: String },
|
||||
names: { type: Array },
|
||||
registeredName: { type: String },
|
||||
selectedName: { type: String },
|
||||
path: { type: String },
|
||||
portForwardingEnabled: { type: Boolean },
|
||||
amount: { type: Number },
|
||||
generalMessage: { type: String },
|
||||
successMessage: { type: String },
|
||||
errorMessage: { type: String },
|
||||
loading: { type: Boolean },
|
||||
btnDisable: { type: Boolean }
|
||||
}
|
||||
}
|
||||
|
||||
amount: { type: Number },
|
||||
generalMessage: { type: String },
|
||||
successMessage: { type: String },
|
||||
errorMessage: { type: String },
|
||||
loading: { type: Boolean },
|
||||
btnDisable: { type: Boolean },
|
||||
}
|
||||
}
|
||||
static get observers() {
|
||||
return ['_kmxKeyUp(amount)']
|
||||
}
|
||||
|
||||
static get observers() {
|
||||
return ['_kmxKeyUp(amount)']
|
||||
}
|
||||
|
||||
static get styles() {
|
||||
return css`
|
||||
static get styles() {
|
||||
return css`
|
||||
* {
|
||||
--mdc-theme-primary: rgb(3, 169, 244);
|
||||
--mdc-theme-secondary: var(--mdc-theme-primary);
|
||||
@ -56,8 +54,6 @@ class PublishData extends LitElement {
|
||||
}
|
||||
|
||||
#publishWrapper .buttons {
|
||||
/* --paper-button-ink-color: var(--paper-green-500);
|
||||
color: var(--paper-green-500); */
|
||||
width: auto !important;
|
||||
}
|
||||
|
||||
@ -88,10 +84,10 @@ class PublishData extends LitElement {
|
||||
width: 30px;
|
||||
}
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
render() {
|
||||
return html`
|
||||
<div id="publishWrapper" style="width:auto; padding:10px; background: #fff; height:100vh;">
|
||||
<div class="layout horizontal center" style=" padding:12px 15px;">
|
||||
<div class="address-bar">
|
||||
@ -131,330 +127,330 @@ class PublishData extends LitElement {
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
// Navigation
|
||||
// Navigation
|
||||
|
||||
goBack() {
|
||||
window.history.back();
|
||||
goBack() {
|
||||
window.history.back();
|
||||
}
|
||||
|
||||
|
||||
renderUploadField() {
|
||||
if (this.uploadType === "file") {
|
||||
return html`<p>
|
||||
renderUploadField() {
|
||||
if (this.uploadType === "file") {
|
||||
return html`<p>
|
||||
<input style="width:100%;" id="file" type="file" />
|
||||
</p>`;
|
||||
}
|
||||
else if (this.uploadType === "zip") {
|
||||
return html`<p>
|
||||
}
|
||||
else if (this.uploadType === "zip") {
|
||||
return html`<p>
|
||||
<span class="upload-text">Select zip file containing static content:</span><br />
|
||||
<input style="width:100%;" id="file" type="file" accept=".zip" />
|
||||
</p>`;
|
||||
}
|
||||
else {
|
||||
return html`<p>
|
||||
}
|
||||
else {
|
||||
return html`<p>
|
||||
<mwc-textfield style="width:100%;" label="Local path to static files" id="path" type="text" value="${this.path}"></mwc-textfield>
|
||||
</p>`;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
doPublish(e) {
|
||||
let registeredName = this.shadowRoot.getElementById('registeredName').value
|
||||
let service = this.shadowRoot.getElementById('service').value
|
||||
let identifier = this.shadowRoot.getElementById('identifier').value
|
||||
doPublish(e) {
|
||||
let registeredName = this.shadowRoot.getElementById('registeredName').value
|
||||
let service = this.shadowRoot.getElementById('service').value
|
||||
let identifier = this.shadowRoot.getElementById('identifier').value
|
||||
|
||||
// If name is hidden, use the value passed in via the name parameter
|
||||
if (!this.showName) {
|
||||
registeredName = this.name
|
||||
}
|
||||
// If name is hidden, use the value passed in via the name parameter
|
||||
if (!this.showName) {
|
||||
registeredName = this.name
|
||||
}
|
||||
|
||||
let file;
|
||||
let path;
|
||||
let file;
|
||||
let path;
|
||||
|
||||
if (this.uploadType === "file" || this.uploadType === "zip") {
|
||||
file = this.shadowRoot.getElementById('file').files[0]
|
||||
}
|
||||
else if (this.uploadType === "path") {
|
||||
path = this.shadowRoot.getElementById('path').value
|
||||
}
|
||||
if (this.uploadType === "file" || this.uploadType === "zip") {
|
||||
file = this.shadowRoot.getElementById('file').files[0]
|
||||
}
|
||||
else if (this.uploadType === "path") {
|
||||
path = this.shadowRoot.getElementById('path').value
|
||||
}
|
||||
|
||||
this.generalMessage = ''
|
||||
this.successMessage = ''
|
||||
this.errorMessage = ''
|
||||
this.generalMessage = ''
|
||||
this.successMessage = ''
|
||||
this.errorMessage = ''
|
||||
|
||||
if (registeredName === '') {
|
||||
this.showName = true
|
||||
parentEpml.request('showSnackBar', 'Please select a registered name to publish data for')
|
||||
}
|
||||
else if (this.uploadType === "file" && file == null) {
|
||||
parentEpml.request('showSnackBar', 'Please select a file to host')
|
||||
}
|
||||
else if (this.uploadType === "zip" && file == null) {
|
||||
parentEpml.request('showSnackBar', 'Please select a zip file to host')
|
||||
}
|
||||
else if (this.uploadType === "path" && path === '') {
|
||||
parentEpml.request('showSnackBar', 'Please enter the directory path containing the static content')
|
||||
}
|
||||
else if (service === '') {
|
||||
parentEpml.request('showSnackBar', 'Please enter a service name')
|
||||
}
|
||||
else {
|
||||
this.publishData(registeredName, path, file, service, identifier)
|
||||
}
|
||||
}
|
||||
if (registeredName === '') {
|
||||
this.showName = true
|
||||
parentEpml.request('showSnackBar', 'Please select a registered name to publish data for')
|
||||
}
|
||||
else if (this.uploadType === "file" && file == null) {
|
||||
parentEpml.request('showSnackBar', 'Please select a file to host')
|
||||
}
|
||||
else if (this.uploadType === "zip" && file == null) {
|
||||
parentEpml.request('showSnackBar', 'Please select a zip file to host')
|
||||
}
|
||||
else if (this.uploadType === "path" && path === '') {
|
||||
parentEpml.request('showSnackBar', 'Please enter the directory path containing the static content')
|
||||
}
|
||||
else if (service === '') {
|
||||
parentEpml.request('showSnackBar', 'Please enter a service name')
|
||||
}
|
||||
else {
|
||||
this.publishData(registeredName, path, file, service, identifier)
|
||||
}
|
||||
}
|
||||
|
||||
async publishData(registeredName, path, file, service, identifier) {
|
||||
this.loading = true
|
||||
this.btnDisable = true
|
||||
async publishData(registeredName, path, file, service, identifier) {
|
||||
this.loading = true
|
||||
this.btnDisable = true
|
||||
|
||||
const validateName = async (receiverName) => {
|
||||
let nameRes = await parentEpml.request('apiCall', {
|
||||
type: 'api',
|
||||
url: `/names/${receiverName}`,
|
||||
})
|
||||
const validateName = async (receiverName) => {
|
||||
let nameRes = await parentEpml.request('apiCall', {
|
||||
type: 'api',
|
||||
url: `/names/${receiverName}`,
|
||||
})
|
||||
|
||||
return nameRes
|
||||
}
|
||||
return nameRes
|
||||
}
|
||||
|
||||
const showError = async (errorMessage) => {
|
||||
this.loading = false
|
||||
this.btnDisable = false
|
||||
this.generalMessage = ''
|
||||
this.successMessage = ''
|
||||
console.error(errorMessage)
|
||||
}
|
||||
const showError = async (errorMessage) => {
|
||||
this.loading = false
|
||||
this.btnDisable = false
|
||||
this.generalMessage = ''
|
||||
this.successMessage = ''
|
||||
console.error(errorMessage)
|
||||
}
|
||||
|
||||
const validate = async () => {
|
||||
let validNameRes = await validateName(registeredName)
|
||||
if (validNameRes.error) {
|
||||
this.errorMessage = "Error: " + validNameRes.message
|
||||
showError(this.errorMessage)
|
||||
throw new Error(this.errorMessage);
|
||||
}
|
||||
const validate = async () => {
|
||||
let validNameRes = await validateName(registeredName)
|
||||
if (validNameRes.error) {
|
||||
this.errorMessage = "Error: " + validNameRes.message
|
||||
showError(this.errorMessage)
|
||||
throw new Error(this.errorMessage);
|
||||
}
|
||||
|
||||
this.generalMessage = "Processing data... this can take some time...";
|
||||
this.generalMessage = "Processing data... this can take some time...";
|
||||
|
||||
let transactionBytes = await uploadData(registeredName, path, file)
|
||||
if (transactionBytes.error) {
|
||||
this.errorMessage = "Error: " + transactionBytes.message
|
||||
showError(this.errorMessage)
|
||||
throw new Error(this.errorMessage);
|
||||
}
|
||||
else if (transactionBytes.includes("Error 500 Internal Server Error")) {
|
||||
this.errorMessage = "Internal Server Error when publishing data"
|
||||
showError(this.errorMessage)
|
||||
throw new Error(this.errorMessage);
|
||||
}
|
||||
let transactionBytes = await uploadData(registeredName, path, file)
|
||||
if (transactionBytes.error) {
|
||||
this.errorMessage = "Error: " + transactionBytes.message
|
||||
showError(this.errorMessage)
|
||||
throw new Error(this.errorMessage);
|
||||
}
|
||||
else if (transactionBytes.includes("Error 500 Internal Server Error")) {
|
||||
this.errorMessage = "Internal Server Error when publishing data"
|
||||
showError(this.errorMessage)
|
||||
throw new Error(this.errorMessage);
|
||||
}
|
||||
|
||||
this.generalMessage = "Computing proof of work... this can take some time...";
|
||||
this.generalMessage = "Computing proof of work... this can take some time...";
|
||||
|
||||
let signAndProcessRes = await signAndProcess(transactionBytes)
|
||||
if (signAndProcessRes.error) {
|
||||
this.errorMessage = "Error: " + signAndProcessRes.message
|
||||
showError(this.errorMessage)
|
||||
throw new Error(this.errorMessage);
|
||||
}
|
||||
let signAndProcessRes = await signAndProcess(transactionBytes)
|
||||
if (signAndProcessRes.error) {
|
||||
this.errorMessage = "Error: " + signAndProcessRes.message
|
||||
showError(this.errorMessage)
|
||||
throw new Error(this.errorMessage);
|
||||
}
|
||||
|
||||
this.btnDisable = false
|
||||
this.loading = false
|
||||
this.errorMessage = ''
|
||||
this.generalMessage = ''
|
||||
this.successMessage = 'Transaction successful!'
|
||||
}
|
||||
this.btnDisable = false
|
||||
this.loading = false
|
||||
this.errorMessage = ''
|
||||
this.generalMessage = ''
|
||||
this.successMessage = 'Transaction successful!'
|
||||
}
|
||||
|
||||
const uploadData = async (registeredName, path, file) => {
|
||||
let postBody = path
|
||||
let urlSuffix = ""
|
||||
if (file != null) {
|
||||
const uploadData = async (registeredName, path, file) => {
|
||||
let postBody = path
|
||||
let urlSuffix = ""
|
||||
if (file != null) {
|
||||
|
||||
// If we're sending zipped data, make sure to use the /zip version of the POST /arbitrary/* API
|
||||
if (this.uploadType === "zip") {
|
||||
urlSuffix = "/zip"
|
||||
}
|
||||
// If we're sending file data, use the /base64 version of the POST /arbitrary/* API
|
||||
else if (this.uploadType === "file") {
|
||||
urlSuffix = "/base64"
|
||||
}
|
||||
// If we're sending zipped data, make sure to use the /zip version of the POST /arbitrary/* API
|
||||
if (this.uploadType === "zip") {
|
||||
urlSuffix = "/zip"
|
||||
}
|
||||
// If we're sending file data, use the /base64 version of the POST /arbitrary/* API
|
||||
else if (this.uploadType === "file") {
|
||||
urlSuffix = "/base64"
|
||||
}
|
||||
|
||||
// Base64 encode the file to work around compatibility issues between javascript and java byte arrays
|
||||
let fileBuffer = new Uint8Array(await file.arrayBuffer())
|
||||
postBody = Buffer.from(fileBuffer).toString('base64');
|
||||
}
|
||||
// Base64 encode the file to work around compatibility issues between javascript and java byte arrays
|
||||
let fileBuffer = new Uint8Array(await file.arrayBuffer())
|
||||
postBody = Buffer.from(fileBuffer).toString('base64');
|
||||
}
|
||||
|
||||
let uploadDataUrl = `/arbitrary/${this.service}/${registeredName}${urlSuffix}`
|
||||
if (identifier != null && identifier.trim().length > 0) {
|
||||
uploadDataUrl = `/arbitrary/${service}/${registeredName}/${this.identifier}${urlSuffix}`
|
||||
}
|
||||
let uploadDataUrl = `/arbitrary/${this.service}/${registeredName}${urlSuffix}`
|
||||
if (identifier != null && identifier.trim().length > 0) {
|
||||
uploadDataUrl = `/arbitrary/${service}/${registeredName}/${this.identifier}${urlSuffix}`
|
||||
}
|
||||
|
||||
let uploadDataRes = await parentEpml.request('apiCall', {
|
||||
type: 'api',
|
||||
method: 'POST',
|
||||
url: `${uploadDataUrl}?apiKey=${this.getApiKey()}`,
|
||||
body: `${postBody}`,
|
||||
})
|
||||
let uploadDataRes = await parentEpml.request('apiCall', {
|
||||
type: 'api',
|
||||
method: 'POST',
|
||||
url: `${uploadDataUrl}?apiKey=${this.getApiKey()}`,
|
||||
body: `${postBody}`,
|
||||
})
|
||||
|
||||
return uploadDataRes
|
||||
}
|
||||
return uploadDataRes
|
||||
}
|
||||
|
||||
const convertBytesForSigning = async (transactionBytesBase58) => {
|
||||
let convertedBytes = await parentEpml.request('apiCall', {
|
||||
type: 'api',
|
||||
method: 'POST',
|
||||
url: `/transactions/convert`,
|
||||
body: `${transactionBytesBase58}`,
|
||||
})
|
||||
const convertBytesForSigning = async (transactionBytesBase58) => {
|
||||
let convertedBytes = await parentEpml.request('apiCall', {
|
||||
type: 'api',
|
||||
method: 'POST',
|
||||
url: `/transactions/convert`,
|
||||
body: `${transactionBytesBase58}`,
|
||||
})
|
||||
|
||||
return convertedBytes
|
||||
}
|
||||
return convertedBytes
|
||||
}
|
||||
|
||||
const signAndProcess = async (transactionBytesBase58) => {
|
||||
let convertedBytesBase58 = await convertBytesForSigning(transactionBytesBase58)
|
||||
if (convertedBytesBase58.error) {
|
||||
this.errorMessage = "Error: " + convertedBytesBase58.message
|
||||
showError(this.errorMessage)
|
||||
throw new Error(this.errorMessage);
|
||||
}
|
||||
|
||||
const convertedBytes = window.parent.Base58.decode(convertedBytesBase58);
|
||||
const _convertedBytesArray = Object.keys(convertedBytes).map(function (key) { return convertedBytes[key]; });
|
||||
const signAndProcess = async (transactionBytesBase58) => {
|
||||
let convertedBytesBase58 = await convertBytesForSigning(transactionBytesBase58)
|
||||
if (convertedBytesBase58.error) {
|
||||
this.errorMessage = "Error: " + convertedBytesBase58.message
|
||||
showError(this.errorMessage)
|
||||
throw new Error(this.errorMessage);
|
||||
}
|
||||
|
||||
const convertedBytes = window.parent.Base58.decode(convertedBytesBase58);
|
||||
const _convertedBytesArray = Object.keys(convertedBytes).map(function (key) { return convertedBytes[key]; });
|
||||
const convertedBytesArray = new Uint8Array(_convertedBytesArray)
|
||||
const convertedBytesHash = new window.parent.Sha256().process(convertedBytesArray).finish().result
|
||||
|
||||
const hashPtr = window.parent.sbrk(32, window.parent.heap);
|
||||
const hashAry = new Uint8Array(window.parent.memory.buffer, hashPtr, 32);
|
||||
const hashPtr = window.parent.sbrk(32, window.parent.heap);
|
||||
const hashAry = new Uint8Array(window.parent.memory.buffer, hashPtr, 32);
|
||||
hashAry.set(convertedBytesHash);
|
||||
|
||||
const difficulty = 14;
|
||||
const workBufferLength = 8 * 1024 * 1024;
|
||||
const workBufferPtr = window.parent.sbrk(workBufferLength, window.parent.heap);
|
||||
|
||||
this.errorMessage = '';
|
||||
this.successMessage = '';
|
||||
let nonce = window.parent.computePow(hashPtr, workBufferPtr, workBufferLength, difficulty)
|
||||
this.errorMessage = '';
|
||||
this.successMessage = '';
|
||||
let nonce = window.parent.computePow(hashPtr, workBufferPtr, workBufferLength, difficulty)
|
||||
|
||||
let response = await parentEpml.request('sign_arbitrary', {
|
||||
let response = await parentEpml.request('sign_arbitrary', {
|
||||
nonce: this.selectedAddress.nonce,
|
||||
arbitraryBytesBase58: transactionBytesBase58,
|
||||
arbitraryBytesForSigningBase58: convertedBytesBase58,
|
||||
arbitraryBytesForSigningBase58: convertedBytesBase58,
|
||||
arbitraryNonce: nonce
|
||||
})
|
||||
|
||||
let myResponse = { error: '' }
|
||||
if (response === false) {
|
||||
myResponse.error = "Unable to sign and process transaction"
|
||||
}
|
||||
else {
|
||||
myResponse = response
|
||||
}
|
||||
let myResponse = { error: '' }
|
||||
if (response === false) {
|
||||
myResponse.error = "Unable to sign and process transaction"
|
||||
}
|
||||
else {
|
||||
myResponse = response
|
||||
}
|
||||
|
||||
return myResponse
|
||||
}
|
||||
return myResponse
|
||||
}
|
||||
|
||||
validate()
|
||||
}
|
||||
validate()
|
||||
}
|
||||
|
||||
|
||||
// Helper Functions (Re-Used in Most part of the UI )
|
||||
// Helper Functions (Re-Used in Most part of the UI )
|
||||
|
||||
textColor(color) {
|
||||
return color == 'light' ? 'rgba(255,255,255,0.7)' : 'rgba(0,0,0,0.87)'
|
||||
}
|
||||
textColor(color) {
|
||||
return color == 'light' ? 'rgba(255,255,255,0.7)' : 'rgba(0,0,0,0.87)'
|
||||
}
|
||||
|
||||
_textMenu(event) {
|
||||
const getSelectedText = () => {
|
||||
var text = ''
|
||||
if (typeof window.getSelection != 'undefined') {
|
||||
text = window.getSelection().toString()
|
||||
} else if (typeof this.shadowRoot.selection != 'undefined' && this.shadowRoot.selection.type == 'Text') {
|
||||
text = this.shadowRoot.selection.createRange().text
|
||||
}
|
||||
return text
|
||||
}
|
||||
_textMenu(event) {
|
||||
const getSelectedText = () => {
|
||||
var text = ''
|
||||
if (typeof window.getSelection != 'undefined') {
|
||||
text = window.getSelection().toString()
|
||||
} else if (typeof this.shadowRoot.selection != 'undefined' && this.shadowRoot.selection.type == 'Text') {
|
||||
text = this.shadowRoot.selection.createRange().text
|
||||
}
|
||||
return text
|
||||
}
|
||||
|
||||
const checkSelectedTextAndShowMenu = () => {
|
||||
let selectedText = getSelectedText()
|
||||
if (selectedText && typeof selectedText === 'string') {
|
||||
let _eve = { pageX: event.pageX, pageY: event.pageY, clientX: event.clientX, clientY: event.clientY }
|
||||
const checkSelectedTextAndShowMenu = () => {
|
||||
let selectedText = getSelectedText()
|
||||
if (selectedText && typeof selectedText === 'string') {
|
||||
let _eve = { pageX: event.pageX, pageY: event.pageY, clientX: event.clientX, clientY: event.clientY }
|
||||
|
||||
let textMenuObject = { selectedText: selectedText, eventObject: _eve, isFrame: true }
|
||||
let textMenuObject = { selectedText: selectedText, eventObject: _eve, isFrame: true }
|
||||
|
||||
parentEpml.request('openCopyTextMenu', textMenuObject)
|
||||
}
|
||||
}
|
||||
parentEpml.request('openCopyTextMenu', textMenuObject)
|
||||
}
|
||||
}
|
||||
|
||||
checkSelectedTextAndShowMenu()
|
||||
}
|
||||
checkSelectedTextAndShowMenu()
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
constructor() {
|
||||
super()
|
||||
|
||||
this.showName = false;
|
||||
this.showService = false
|
||||
this.showIdentifier = false
|
||||
this.showName = false;
|
||||
this.showService = false
|
||||
this.showIdentifier = false
|
||||
|
||||
const urlParams = new URLSearchParams(window.location.search)
|
||||
this.name = urlParams.get('name')
|
||||
this.service = urlParams.get('service')
|
||||
this.identifier = urlParams.get('identifier')
|
||||
this.category = urlParams.get('category')
|
||||
this.uploadType = urlParams.get('uploadType') !== "null" ? urlParams.get('uploadType') : "file"
|
||||
const urlParams = new URLSearchParams(window.location.search)
|
||||
this.name = urlParams.get('name')
|
||||
this.service = urlParams.get('service')
|
||||
this.identifier = urlParams.get('identifier')
|
||||
this.category = urlParams.get('category')
|
||||
this.uploadType = urlParams.get('uploadType') !== "null" ? urlParams.get('uploadType') : "file"
|
||||
|
||||
if (urlParams.get('showName') === "true") {
|
||||
this.showName = true
|
||||
}
|
||||
if (urlParams.get('showService') === "true") {
|
||||
this.showService = true
|
||||
}
|
||||
if (urlParams.get('showIdentifier') === "true") {
|
||||
this.showIdentifier = true
|
||||
}
|
||||
|
||||
if (this.identifier != null) {
|
||||
if (this.identifier === "null" || this.identifier.trim().length == 0) {
|
||||
this.identifier = null
|
||||
}
|
||||
}
|
||||
if (urlParams.get('showName') === "true") {
|
||||
this.showName = true
|
||||
}
|
||||
if (urlParams.get('showService') === "true") {
|
||||
this.showService = true
|
||||
}
|
||||
if (urlParams.get('showIdentifier') === "true") {
|
||||
this.showIdentifier = true
|
||||
}
|
||||
|
||||
this.portForwardingEnabled = true // Default to true so the message doesn't appear and disappear quickly
|
||||
this.names = []
|
||||
this.registeredName = ''
|
||||
this.selectedName = 'invalid'
|
||||
this.path = ''
|
||||
//this.selectedAddress = {}
|
||||
this.successMessage = ''
|
||||
this.generalMessage = ''
|
||||
this.errorMessage = ''
|
||||
this.loading = false
|
||||
this.btnDisable = false
|
||||
if (this.identifier != null) {
|
||||
if (this.identifier === "null" || this.identifier.trim().length == 0) {
|
||||
this.identifier = null
|
||||
}
|
||||
}
|
||||
|
||||
const fetchNames = () => {
|
||||
// Default to true so the message doesn't appear and disappear quickly
|
||||
this.portForwardingEnabled = true
|
||||
this.names = []
|
||||
this.registeredName = ''
|
||||
this.selectedName = 'invalid'
|
||||
this.path = ''
|
||||
this.successMessage = ''
|
||||
this.generalMessage = ''
|
||||
this.errorMessage = ''
|
||||
this.loading = false
|
||||
this.btnDisable = false
|
||||
|
||||
const fetchNames = () => {
|
||||
parentEpml.request('apiCall', {
|
||||
url: `/names/address/${this.selectedAddress.address}?limit=0&reverse=true`
|
||||
}).then(res => {
|
||||
|
||||
setTimeout(() => {
|
||||
this.names = res
|
||||
this.registeredName = res[0].name;
|
||||
}, 1)
|
||||
this.names = res
|
||||
this.registeredName = res[0].name;
|
||||
}, 1)
|
||||
})
|
||||
setTimeout(fetchNames, this.config.user.nodeSettings.pingInterval)
|
||||
}
|
||||
|
||||
const fetchPeersSummary = () => {
|
||||
const fetchPeersSummary = () => {
|
||||
parentEpml.request('apiCall', {
|
||||
url: `/peers/summary`
|
||||
}).then(res => {
|
||||
|
||||
setTimeout(() => {
|
||||
this.portForwardingEnabled = (res.inboundConnections != null && res.inboundConnections > 0);
|
||||
}, 1)
|
||||
this.portForwardingEnabled = (res.inboundConnections != null && res.inboundConnections > 0);
|
||||
}, 1)
|
||||
})
|
||||
setTimeout(fetchNames, this.config.user.nodeSettings.pingInterval)
|
||||
}
|
||||
|
||||
let configLoaded = false
|
||||
let configLoaded = false
|
||||
parentEpml.ready().then(() => {
|
||||
parentEpml.subscribe('selected_address', async selectedAddress => {
|
||||
this.selectedAddress = {}
|
||||
@ -465,7 +461,7 @@ class PublishData extends LitElement {
|
||||
parentEpml.subscribe('config', c => {
|
||||
if (!configLoaded) {
|
||||
setTimeout(fetchNames, 1)
|
||||
setTimeout(fetchPeersSummary, 1)
|
||||
setTimeout(fetchPeersSummary, 1)
|
||||
configLoaded = true
|
||||
}
|
||||
this.config = JSON.parse(c)
|
||||
@ -478,41 +474,41 @@ class PublishData extends LitElement {
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
firstUpdated() {
|
||||
|
||||
window.addEventListener('contextmenu', (event) => {
|
||||
event.preventDefault()
|
||||
this._textMenu(event)
|
||||
})
|
||||
window.addEventListener('contextmenu', (event) => {
|
||||
event.preventDefault()
|
||||
this._textMenu(event)
|
||||
})
|
||||
|
||||
window.addEventListener('click', () => {
|
||||
parentEpml.request('closeCopyTextMenu', null)
|
||||
})
|
||||
window.addEventListener('click', () => {
|
||||
parentEpml.request('closeCopyTextMenu', null)
|
||||
})
|
||||
|
||||
window.onkeyup = (e) => {
|
||||
if (e.keyCode === 27) {
|
||||
parentEpml.request('closeCopyTextMenu', null)
|
||||
}
|
||||
}
|
||||
}
|
||||
window.onkeyup = (e) => {
|
||||
if (e.keyCode === 27) {
|
||||
parentEpml.request('closeCopyTextMenu', null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
selectName(e) {
|
||||
const name = this.shadowRoot.getElementById('registeredName').innerHTML
|
||||
this.selectedName = name
|
||||
}
|
||||
selectName(e) {
|
||||
const name = this.shadowRoot.getElementById('registeredName').innerHTML
|
||||
this.selectedName = name
|
||||
}
|
||||
|
||||
getApiKey() {
|
||||
getApiKey() {
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node];
|
||||
let apiKey = myNode.apiKey;
|
||||
return apiKey;
|
||||
}
|
||||
|
||||
clearSelection() {
|
||||
window.getSelection().removeAllRanges()
|
||||
window.parent.getSelection().removeAllRanges()
|
||||
}
|
||||
clearSelection() {
|
||||
window.getSelection().removeAllRanges()
|
||||
window.parent.getSelection().removeAllRanges()
|
||||
}
|
||||
}
|
||||
|
||||
window.customElements.define('publish-data', PublishData)
|
||||
|
@ -5,9 +5,8 @@ import { Epml } from '../../../epml.js'
|
||||
import '@material/mwc-icon'
|
||||
import '@material/mwc-button'
|
||||
import '@material/mwc-textfield'
|
||||
|
||||
import '@vaadin/vaadin-grid/vaadin-grid.js'
|
||||
import '@vaadin/vaadin-grid/theme/material/all-imports.js'
|
||||
import '@vaadin/grid/vaadin-grid.js'
|
||||
import '@vaadin/grid/theme/material/all-imports.js'
|
||||
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
||||
|
||||
@ -15,14 +14,14 @@ class Websites extends LitElement {
|
||||
static get properties() {
|
||||
return {
|
||||
service: { type: String },
|
||||
identifier: { type: String },
|
||||
identifier: { type: String },
|
||||
loading: { type: Boolean },
|
||||
resources: { type: Array },
|
||||
followedNames: { type: Array },
|
||||
blockedNames: { type: Array },
|
||||
relayMode: { type: Boolean },
|
||||
selectedAddress: { type: Object },
|
||||
searchName: { type: String },
|
||||
searchName: { type: String },
|
||||
searchResources: { type: Array },
|
||||
searchFollowedNames: { type: Array },
|
||||
searchBlockedNames: { type: Array }
|
||||
@ -159,7 +158,7 @@ class Websites extends LitElement {
|
||||
constructor() {
|
||||
super()
|
||||
this.service = "WEBSITE"
|
||||
this.identifier = null
|
||||
this.identifier = null
|
||||
this.selectedAddress = {}
|
||||
this.resources = []
|
||||
this.followedNames = []
|
||||
@ -185,15 +184,15 @@ class Websites extends LitElement {
|
||||
<mwc-textfield outlined label="Name To Search" id="searchName" type="text" value="${this.searchName}"></mwc-textfield> <br>
|
||||
<mwc-button raised icon="search" @click="${(e) => this.doSearch(e)}">Search</mwc-button>
|
||||
</div><br />
|
||||
<vaadin-grid id="searchResourcesGrid" style="height:auto;" ?hidden="${this.isEmptyArray(this.searchResources)}" .items="${this.searchResources}" height-by-rows>
|
||||
<vaadin-grid theme="compact" id="searchResourcesGrid" ?hidden="${this.isEmptyArray(this.searchResources)}" .items="${this.searchResources}" aria-label="Search Websites" all-rows-visible>
|
||||
<vaadin-grid-column width="5rem" flex-grow="0" header="Avatar" .renderer=${(root, column, data) => {
|
||||
render(html`${this.renderSearchAvatar(data.item)}`, root)
|
||||
render(html`${this.renderSearchAvatar(data.item)}`, root)
|
||||
}}></vaadin-grid-column>
|
||||
<vaadin-grid-column header="Name" .renderer=${(root, column, data) => {
|
||||
render(html`${this.renderSearchName(data.item)}`, root)
|
||||
}}></vaadin-grid-column>
|
||||
<vaadin-grid-column header="Status" .renderer=${(root, column, data) => {
|
||||
render(html`${this.renderSearchStatus(data.item)}`, root)
|
||||
render(html`${this.renderSearchStatus(data.item)}`, root)
|
||||
}}></vaadin-grid-column>
|
||||
<vaadin-grid-column header="Size" .renderer=${(root, column, data) => {
|
||||
render(html`${this.renderSearchSize(data.item)}`, root)
|
||||
@ -205,10 +204,12 @@ class Websites extends LitElement {
|
||||
render(html`${this.renderSearchBlockUnblockButton(data.item)}`, root);
|
||||
}}></vaadin-grid-column>
|
||||
</vaadin-grid><br />
|
||||
</div>
|
||||
<div class="divCard">
|
||||
<h3 style="margin: 0; margin-bottom: 1em; text-align: center;">Websites</h3>
|
||||
<vaadin-grid id="resourcesGrid" style="height:auto;" ?hidden="${this.isEmptyArray(this.resources)}" page-size="20" height-by-rows>
|
||||
<vaadin-grid theme="compact" id="resourcesGrid" ?hidden="${this.isEmptyArray(this.resources)}" aria-label="Websites" page-size="20" all-rows-visible>
|
||||
<vaadin-grid-column width="5rem" flex-grow="0" header="Avatar" .renderer=${(root, column, data) => {
|
||||
render(html`${this.renderAvatar(data.item)}`, root)
|
||||
render(html`${this.renderAvatar(data.item)}`, root)
|
||||
}}></vaadin-grid-column>
|
||||
<vaadin-grid-column header="Name" .renderer=${(root, column, data) => {
|
||||
render(html`${this.renderName(data.item)}`, root)
|
||||
@ -246,7 +247,7 @@ class Websites extends LitElement {
|
||||
})
|
||||
|
||||
this.followedNames = followedNames
|
||||
setTimeout(getFollowedNames, this.config.user.nodeSettings.pingInterval)
|
||||
setTimeout(getFollowedNames, 60000)
|
||||
}
|
||||
|
||||
const getBlockedNames = async () => {
|
||||
@ -255,7 +256,7 @@ class Websites extends LitElement {
|
||||
})
|
||||
|
||||
this.blockedNames = blockedNames
|
||||
setTimeout(getBlockedNames, this.config.user.nodeSettings.pingInterval)
|
||||
setTimeout(getBlockedNames, 60000)
|
||||
}
|
||||
|
||||
const getSearchFollowedNames = async () => {
|
||||
@ -264,7 +265,7 @@ class Websites extends LitElement {
|
||||
})
|
||||
|
||||
this.searchFollowedNames = searchFollowedNames
|
||||
setTimeout(getSearchFollowedNames, this.config.user.nodeSettings.pingInterval)
|
||||
setTimeout(getSearchFollowedNames, 60000)
|
||||
}
|
||||
|
||||
const getSearchBlockedNames = async () => {
|
||||
@ -273,7 +274,7 @@ class Websites extends LitElement {
|
||||
})
|
||||
|
||||
this.searchBlockedNames = searchBlockedNames
|
||||
setTimeout(getSearchBlockedNames, this.config.user.nodeSettings.pingInterval)
|
||||
setTimeout(getSearchBlockedNames, 60000)
|
||||
}
|
||||
|
||||
const getRelayMode = async () => {
|
||||
@ -282,7 +283,7 @@ class Websites extends LitElement {
|
||||
})
|
||||
|
||||
this.relayMode = relayMode;
|
||||
setTimeout(getRelayMode, this.config.user.nodeSettings.pingInterval)
|
||||
setTimeout(getRelayMode, 60000)
|
||||
}
|
||||
|
||||
|
||||
@ -318,7 +319,7 @@ class Websites extends LitElement {
|
||||
setTimeout(getSearchFollowedNames, 1)
|
||||
setTimeout(getSearchBlockedNames, 1)
|
||||
setTimeout(getRelayMode, 1)
|
||||
setInterval(this.getArbitraryResources, 120 * 1000)
|
||||
setInterval(this.getArbitraryResources, 120000)
|
||||
configLoaded = true
|
||||
}
|
||||
this.config = JSON.parse(c)
|
||||
@ -419,13 +420,13 @@ class Websites extends LitElement {
|
||||
}
|
||||
|
||||
doSearch(e) {
|
||||
this.searchResult()
|
||||
this.searchResult()
|
||||
}
|
||||
|
||||
async searchResult() {
|
||||
let searchName = this.shadowRoot.getElementById('searchName').value
|
||||
if (searchName.length === 0) {
|
||||
parentEpml.request('showSnackBar', 'Name Can Not Be Empty!')
|
||||
parentEpml.request('showSnackBar', 'Name Can Not Be Empty!')
|
||||
} else {
|
||||
let searchResources = await parentEpml.request('apiCall', {
|
||||
url: `/arbitrary/resources/search?service=${this.service}&query=${searchName}&default=true&limit=5&reverse=false&includestatus=true`
|
||||
@ -481,7 +482,7 @@ class Websites extends LitElement {
|
||||
let items = [
|
||||
name
|
||||
]
|
||||
let namesJsonString = JSON.stringify({"items": items})
|
||||
let namesJsonString = JSON.stringify({ "items": items })
|
||||
let ret = await parentEpml.request('apiCall', {
|
||||
url: `/lists/followedNames?apiKey=${this.getApiKey()}`,
|
||||
method: 'POST',
|
||||
@ -491,7 +492,7 @@ class Websites extends LitElement {
|
||||
body: `${namesJsonString}`
|
||||
})
|
||||
if (ret === true) {
|
||||
this.searchFollowedNames = this.searchFollowedNames.filter(item => item != name);
|
||||
this.searchFollowedNames = this.searchFollowedNames.filter(item => item != name);
|
||||
this.searchFollowedNames.push(name)
|
||||
}
|
||||
else {
|
||||
@ -505,7 +506,7 @@ class Websites extends LitElement {
|
||||
let items = [
|
||||
name
|
||||
]
|
||||
let namesJsonString = JSON.stringify({"items": items})
|
||||
let namesJsonString = JSON.stringify({ "items": items })
|
||||
let ret = await parentEpml.request('apiCall', {
|
||||
url: `/lists/followedNames?apiKey=${this.getApiKey()}`,
|
||||
method: 'DELETE',
|
||||
@ -515,7 +516,7 @@ class Websites extends LitElement {
|
||||
body: `${namesJsonString}`
|
||||
})
|
||||
if (ret === true) {
|
||||
this.searchFollowedNames = this.searchFollowedNames.filter(item => item != name);
|
||||
this.searchFollowedNames = this.searchFollowedNames.filter(item => item != name);
|
||||
}
|
||||
else {
|
||||
parentEpml.request('showSnackBar', 'Error occurred when trying to unfollow this registered name. Please try again')
|
||||
@ -541,7 +542,7 @@ class Websites extends LitElement {
|
||||
let items = [
|
||||
name
|
||||
]
|
||||
let namesJsonString = JSON.stringify({"items": items})
|
||||
let namesJsonString = JSON.stringify({ "items": items })
|
||||
let ret = await parentEpml.request('apiCall', {
|
||||
url: `/lists/blockedNames?apiKey=${this.getApiKey()}`,
|
||||
method: 'POST',
|
||||
@ -551,7 +552,7 @@ class Websites extends LitElement {
|
||||
body: `${namesJsonString}`
|
||||
})
|
||||
if (ret === true) {
|
||||
this.searchBlockedNames = this.searchBlockedNames.filter(item => item != name);
|
||||
this.searchBlockedNames = this.searchBlockedNames.filter(item => item != name);
|
||||
this.searchBlockedNames.push(name)
|
||||
}
|
||||
else {
|
||||
@ -565,7 +566,7 @@ class Websites extends LitElement {
|
||||
let items = [
|
||||
name
|
||||
]
|
||||
let namesJsonString = JSON.stringify({"items": items})
|
||||
let namesJsonString = JSON.stringify({ "items": items })
|
||||
let ret = await parentEpml.request('apiCall', {
|
||||
url: `/lists/blockedNames?apiKey=${this.getApiKey()}`,
|
||||
method: 'DELETE',
|
||||
@ -575,7 +576,7 @@ class Websites extends LitElement {
|
||||
body: `${namesJsonString}`
|
||||
})
|
||||
if (ret === true) {
|
||||
this.searchBlockedNames = this.searchBlockedNames.filter(item => item != name);
|
||||
this.searchBlockedNames = this.searchBlockedNames.filter(item => item != name);
|
||||
}
|
||||
else {
|
||||
parentEpml.request('showSnackBar', 'Error occurred when trying to unblock this registered name. Please try again')
|
||||
@ -619,7 +620,7 @@ class Websites extends LitElement {
|
||||
let items = [
|
||||
name
|
||||
]
|
||||
let namesJsonString = JSON.stringify({"items": items})
|
||||
let namesJsonString = JSON.stringify({ "items": items })
|
||||
|
||||
let ret = await parentEpml.request('apiCall', {
|
||||
url: `/lists/followedNames?apiKey=${this.getApiKey()}`,
|
||||
@ -634,7 +635,7 @@ class Websites extends LitElement {
|
||||
// Successfully followed - add to local list
|
||||
// Remove it first by filtering the list - doing it this way ensures the UI updates
|
||||
// immediately, as apposed to only adding if it doesn't already exist
|
||||
this.followedNames = this.followedNames.filter(item => item != name);
|
||||
this.followedNames = this.followedNames.filter(item => item != name);
|
||||
this.followedNames.push(name)
|
||||
}
|
||||
else {
|
||||
@ -649,7 +650,7 @@ class Websites extends LitElement {
|
||||
let items = [
|
||||
name
|
||||
]
|
||||
let namesJsonString = JSON.stringify({"items": items})
|
||||
let namesJsonString = JSON.stringify({ "items": items })
|
||||
|
||||
let ret = await parentEpml.request('apiCall', {
|
||||
url: `/lists/followedNames?apiKey=${this.getApiKey()}`,
|
||||
@ -662,7 +663,7 @@ class Websites extends LitElement {
|
||||
|
||||
if (ret === true) {
|
||||
// Successfully unfollowed - remove from local list
|
||||
this.followedNames = this.followedNames.filter(item => item != name);
|
||||
this.followedNames = this.followedNames.filter(item => item != name);
|
||||
}
|
||||
else {
|
||||
parentEpml.request('showSnackBar', 'Error occurred when trying to unfollow this registered name. Please try again')
|
||||
@ -676,7 +677,7 @@ class Websites extends LitElement {
|
||||
let items = [
|
||||
name
|
||||
]
|
||||
let namesJsonString = JSON.stringify({"items": items})
|
||||
let namesJsonString = JSON.stringify({ "items": items })
|
||||
|
||||
let ret = await parentEpml.request('apiCall', {
|
||||
url: `/lists/blockedNames?apiKey=${this.getApiKey()}`,
|
||||
@ -691,7 +692,7 @@ class Websites extends LitElement {
|
||||
// Successfully blocked - add to local list
|
||||
// Remove it first by filtering the list - doing it this way ensures the UI updates
|
||||
// immediately, as apposed to only adding if it doesn't already exist
|
||||
this.blockedNames = this.blockedNames.filter(item => item != name);
|
||||
this.blockedNames = this.blockedNames.filter(item => item != name);
|
||||
this.blockedNames.push(name)
|
||||
}
|
||||
else {
|
||||
@ -706,7 +707,7 @@ class Websites extends LitElement {
|
||||
let items = [
|
||||
name
|
||||
]
|
||||
let namesJsonString = JSON.stringify({"items": items})
|
||||
let namesJsonString = JSON.stringify({ "items": items })
|
||||
|
||||
let ret = await parentEpml.request('apiCall', {
|
||||
url: `/lists/blockedNames?apiKey=${this.getApiKey()}`,
|
||||
@ -719,7 +720,7 @@ class Websites extends LitElement {
|
||||
|
||||
if (ret === true) {
|
||||
// Successfully unblocked - remove from local list
|
||||
this.blockedNames = this.blockedNames.filter(item => item != name);
|
||||
this.blockedNames = this.blockedNames.filter(item => item != name);
|
||||
}
|
||||
else {
|
||||
parentEpml.request('showSnackBar', 'Error occurred when trying to unblock this registered name. Please try again')
|
||||
@ -796,7 +797,7 @@ class Websites extends LitElement {
|
||||
if (bytes == 0) return '0 bytes';
|
||||
var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
|
||||
return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[i];
|
||||
}
|
||||
}
|
||||
|
||||
_textMenu(event) {
|
||||
|
||||
|
@ -32,14 +32,14 @@
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: "Roboto", sans-serif;
|
||||
background: #fff;
|
||||
background-color: #fff;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<reward-share></reward-share>
|
||||
<script type="module" src="reward-share.js"></script>
|
||||
<script src="reward-share.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -7,10 +7,9 @@ import '@material/mwc-button'
|
||||
import '@material/mwc-textfield'
|
||||
import '@material/mwc-dialog'
|
||||
import '@material/mwc-slider'
|
||||
|
||||
import '@polymer/paper-spinner/paper-spinner-lite.js'
|
||||
import '@vaadin/vaadin-grid/vaadin-grid.js'
|
||||
import '@vaadin/vaadin-grid/theme/material/all-imports.js'
|
||||
import '@vaadin/grid/vaadin-grid.js'
|
||||
import '@vaadin/grid/theme/material/all-imports.js'
|
||||
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
||||
|
||||
@ -43,6 +42,12 @@ class RewardShare extends LitElement {
|
||||
padding: 12px 24px;
|
||||
}
|
||||
|
||||
.divCard {
|
||||
border: 1px solid #eee;
|
||||
padding: 1em;
|
||||
box-shadow: 0 .3px 1px 0 rgba(0,0,0,0.14), 0 1px 1px -1px rgba(0,0,0,0.12), 0 1px 2px 0 rgba(0,0,0,0.20);
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin:0;
|
||||
}
|
||||
@ -73,18 +78,21 @@ class RewardShare extends LitElement {
|
||||
return html`
|
||||
<div id="reward-share-page">
|
||||
<div style="min-height:48px; display: flex; padding-bottom: 6px;">
|
||||
<h3 style="margin: 0; flex: 1; padding-top: 8px; display: inline;">Rewardshares involving this account</h3>
|
||||
<h3 style="margin: 0; flex: 1; padding-top: 8px; display: inline;">Rewardshares</h3>
|
||||
<mwc-button style="float:right;" @click=${() => this.shadowRoot.querySelector('#createRewardShareDialog').show()}><mwc-icon>add</mwc-icon>Create reward share</mwc-button>
|
||||
</div>
|
||||
|
||||
<vaadin-grid id="accountRewardSharesGrid" style="height:auto;" ?hidden="${this.isEmptyArray(this.rewardShares)}" .items="${this.rewardShares}" height-by-rows>
|
||||
<vaadin-grid-column auto-width path="mintingAccount"></vaadin-grid-column>
|
||||
<vaadin-grid-column auto-width path="sharePercent"></vaadin-grid-column>
|
||||
<vaadin-grid-column auto-width path="recipient"></vaadin-grid-column>
|
||||
<vaadin-grid-column width="12em" header="Action" .renderer=${(root, column, data) => {
|
||||
render(html`${this.renderRemoveRewardShareButton(data.item)}`, root)
|
||||
}}></vaadin-grid-column>
|
||||
</vaadin-grid>
|
||||
<div class="divCard">
|
||||
<h3 style="margin: 0; margin-bottom: 1em; text-align: center;">Rewardshares Involving In This Account</h3>
|
||||
<vaadin-grid theme="compact" id="accountRewardSharesGrid" ?hidden="${this.isEmptyArray(this.rewardShares)}" .items="${this.rewardShares}" all-rows-visible>
|
||||
<vaadin-grid-column auto-width path="mintingAccount"></vaadin-grid-column>
|
||||
<vaadin-grid-column auto-width path="sharePercent"></vaadin-grid-column>
|
||||
<vaadin-grid-column auto-width path="recipient"></vaadin-grid-column>
|
||||
<vaadin-grid-column width="12em" header="Action" .renderer=${(root, column, data) => {
|
||||
render(html`${this.renderRemoveRewardShareButton(data.item)}`, root)
|
||||
}}></vaadin-grid-column>
|
||||
</vaadin-grid>
|
||||
</div>
|
||||
|
||||
<mwc-dialog id="createRewardShareDialog" scrimClickAction="${this.createRewardShareLoading ? '' : 'close'}">
|
||||
<div>Level 1 - 4 can create a Self Share and Level 5 or above can create a Reward Share!</div>
|
||||
@ -248,7 +256,7 @@ class RewardShare extends LitElement {
|
||||
const recipientPublicKey = this.shadowRoot.getElementById("recipientPublicKey").value
|
||||
const percentageShare = this.shadowRoot.getElementById("rewardSharePercentageSlider").value
|
||||
|
||||
// Check for valid...^
|
||||
// Check for valid...
|
||||
this.createRewardShareLoading = true
|
||||
|
||||
let recipientAddress = window.parent.base58PublicKeyToAddress(recipientPublicKey)
|
||||
@ -339,8 +347,8 @@ class RewardShare extends LitElement {
|
||||
this.error = true
|
||||
this.message = `CANNOT CREATE SELF SHARE! at level ${accountDetails.level}`
|
||||
}
|
||||
} else { //Check for creating reward shares
|
||||
|
||||
} else {
|
||||
//Check for creating reward shares
|
||||
if (accountDetails.level >= 5) {
|
||||
|
||||
this.error = false
|
||||
@ -402,7 +410,7 @@ class RewardShare extends LitElement {
|
||||
async removeRewardShare(rewardShareObject) {
|
||||
const myPercentageShare = -1
|
||||
|
||||
// Check for valid...^
|
||||
// Check for valid...
|
||||
this.removeRewardShareLoading = true
|
||||
|
||||
// Get Last Ref
|
||||
|
@ -32,6 +32,7 @@
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: "Roboto", sans-serif;
|
||||
background-color: #fff;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -15,20 +15,20 @@ blockTests.push((block, addr) => {
|
||||
})
|
||||
|
||||
export class AddressWatcher {
|
||||
constructor (addresses) {
|
||||
constructor(addresses) {
|
||||
addresses = addresses || []
|
||||
this.reset()
|
||||
|
||||
addresses.forEach(addr => this.addAddress(addr))
|
||||
}
|
||||
|
||||
reset () {
|
||||
reset() {
|
||||
this._addresses = {}
|
||||
this._addressStreams = {}
|
||||
}
|
||||
|
||||
// Adds an address to watch
|
||||
addAddress (address) {
|
||||
addAddress(address) {
|
||||
const addr = address.address
|
||||
this._addresses[addr] = address
|
||||
|
||||
@ -37,7 +37,7 @@ export class AddressWatcher {
|
||||
this.updateAddress(addr)
|
||||
}
|
||||
|
||||
async testBlock (block) {
|
||||
async testBlock(block) {
|
||||
const pendingUpdateAddresses = []
|
||||
const transactions = await parentEpml.request('apiCall', { url: `/transactions/block/${block.signature}` })
|
||||
transactions.forEach(transaction => {
|
||||
@ -57,7 +57,7 @@ export class AddressWatcher {
|
||||
pendingUpdateAddresses.forEach(addr => this.updateAddress(addr))
|
||||
}
|
||||
|
||||
async updateAddress (addr) {
|
||||
async updateAddress(addr) {
|
||||
let addressRequest = await parentEpml.request('apiCall', {
|
||||
type: 'explorer',
|
||||
data: {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { parentEpml } from '../connect.js'
|
||||
|
||||
export class UnconfirmedTransactionWatcher {
|
||||
constructor () {
|
||||
constructor() {
|
||||
this._unconfirmedTransactionStreams = {}
|
||||
this.reset() // Sets defaults
|
||||
|
||||
@ -10,13 +10,13 @@ export class UnconfirmedTransactionWatcher {
|
||||
}, 10 * 1000)
|
||||
}
|
||||
|
||||
reset () {
|
||||
reset() {
|
||||
this._addresses = {}
|
||||
this._addressesUnconfirmedTransactions = {}
|
||||
}
|
||||
|
||||
// Adds an address to watch
|
||||
addAddress (address) {
|
||||
addAddress(address) {
|
||||
const addr = address.address
|
||||
this._addresses[addr] = address
|
||||
this._addressesUnconfirmedTransactions[addr] = []
|
||||
@ -24,13 +24,13 @@ export class UnconfirmedTransactionWatcher {
|
||||
this._unconfirmedTransactionStreams[addr] = new EpmlStream(`unconfirmedOfAddress/${addr}`, () => this._addressesUnconfirmedTransactions[addr])
|
||||
}
|
||||
|
||||
check () {
|
||||
check() {
|
||||
const c = this._addressTransactionCheck()
|
||||
.then(() => setTimeout(() => this.check(), 5000))
|
||||
.catch(() => setTimeout(() => this.check(), 5000))
|
||||
}
|
||||
|
||||
async _addressTransactionCheck () {
|
||||
async _addressTransactionCheck() {
|
||||
return Promise.all(Object.keys(this._addresses).map(addr => {
|
||||
return parentEpml.request('apiCall', {
|
||||
type: 'api',
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
<head>
|
||||
<link rel="stylesheet" href="/font/material-icons.css">
|
||||
<meta charset="UTF-8">
|
||||
<style>
|
||||
html {
|
||||
--scrollbarBG: #a1a1a1;
|
||||
@ -33,14 +32,14 @@
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: "Roboto", sans-serif;
|
||||
background: #fff;
|
||||
background-color: #fff;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<trade-portal></trade-portal>
|
||||
<script type="module" src="trade-portal.js"></script>
|
||||
<script src="trade-portal.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
File diff suppressed because it is too large
Load Diff
@ -1,43 +1,45 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="/font/material-icons.css" />
|
||||
<style>
|
||||
html {
|
||||
--scrollbarBG: #a1a1a1;
|
||||
--thumbBG: #6a6c75;
|
||||
}
|
||||
|
||||
*::-webkit-scrollbar {
|
||||
width: 11px;
|
||||
}
|
||||
<head>
|
||||
<link rel="stylesheet" href="/font/material-icons.css">
|
||||
<style>
|
||||
html {
|
||||
--scrollbarBG: #a1a1a1;
|
||||
--thumbBG: #6a6c75;
|
||||
}
|
||||
|
||||
* {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: var(--thumbBG) var(--scrollbarBG);
|
||||
}
|
||||
*::-webkit-scrollbar {
|
||||
width: 11px;
|
||||
}
|
||||
|
||||
*::-webkit-scrollbar-track {
|
||||
background: var(--scrollbarBG);
|
||||
}
|
||||
* {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: var(--thumbBG) var(--scrollbarBG);
|
||||
}
|
||||
|
||||
*::-webkit-scrollbar-thumb {
|
||||
background-color: var(--thumbBG);
|
||||
border-radius: 6px;
|
||||
border: 3px solid var(--scrollbarBG);
|
||||
}
|
||||
*::-webkit-scrollbar-track {
|
||||
background: var(--scrollbarBG);
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
margin: 0;
|
||||
background: white;
|
||||
font-family: 'Roboto', sans-serif;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
*::-webkit-scrollbar-thumb {
|
||||
background-color: var(--thumbBG);
|
||||
border-radius: 6px;
|
||||
border: 3px solid var(--scrollbarBG);
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: "Roboto", sans-serif;
|
||||
background-color: #fff;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<multi-wallet></multi-wallet>
|
||||
<script src="wallet-app.js"></script>
|
||||
</body>
|
||||
|
||||
<body>
|
||||
<multi-wallet></multi-wallet>
|
||||
<script src="wallet-app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -3,37 +3,35 @@ import { render } from 'lit/html.js'
|
||||
import { Epml } from '../../../epml.js'
|
||||
|
||||
import '../components/ButtonIconCopy'
|
||||
|
||||
import '@material/mwc-icon'
|
||||
import '@material/mwc-button'
|
||||
import '@material/mwc-dialog'
|
||||
|
||||
import '@polymer/paper-spinner/paper-spinner-lite.js'
|
||||
import '@vaadin/vaadin-grid/vaadin-grid.js'
|
||||
import '@vaadin/vaadin-grid/theme/material/all-imports.js'
|
||||
|
||||
import '@vaadin/grid/vaadin-grid.js'
|
||||
import '@vaadin/grid/theme/material/all-imports.js'
|
||||
import '@github/time-elements'
|
||||
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
||||
const coinsNames=['qort','btc','ltc','doge']
|
||||
|
||||
const coinsNames = ['qort', 'btc', 'ltc', 'doge']
|
||||
|
||||
class MultiWallet extends LitElement {
|
||||
static get properties() {
|
||||
return {
|
||||
loading: { type: Boolean },
|
||||
transactions: { type: Object },
|
||||
lastBlock: { type: Object },
|
||||
selectedTransaction: { type: Object },
|
||||
isTextMenuOpen: { type: Boolean },
|
||||
wallets:{type : Map},
|
||||
_selectedWallet:'qort',
|
||||
balanceString:'Fetching balance ...'
|
||||
}
|
||||
}
|
||||
static get properties() {
|
||||
return {
|
||||
loading: { type: Boolean },
|
||||
transactions: { type: Object },
|
||||
lastBlock: { type: Object },
|
||||
selectedTransaction: { type: Object },
|
||||
isTextMenuOpen: { type: Boolean },
|
||||
wallets: { type: Map },
|
||||
_selectedWallet: 'qort',
|
||||
balanceString: 'Fetching balance ...'
|
||||
}
|
||||
}
|
||||
|
||||
static get styles() {
|
||||
return [
|
||||
css`
|
||||
static get styles() {
|
||||
return [
|
||||
css`
|
||||
#pages {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
@ -114,7 +112,6 @@ class MultiWallet extends LitElement {
|
||||
table td,
|
||||
th {
|
||||
white-space: nowrap;
|
||||
/* padding:10px; */
|
||||
text-align: left;
|
||||
font-size: 14px;
|
||||
padding: 0 12px;
|
||||
@ -151,8 +148,6 @@ class MultiWallet extends LitElement {
|
||||
padding: 0;
|
||||
}
|
||||
#transactionList > * {
|
||||
/* padding-left:24px;
|
||||
padding-right:24px; */
|
||||
}
|
||||
.color-in {
|
||||
color: #02977e;
|
||||
@ -254,7 +249,6 @@ class MultiWallet extends LitElement {
|
||||
border-top: 1px solid #e5e5e5;
|
||||
padding-top: 0px;
|
||||
height: 100%;
|
||||
/* overflow: auto; */
|
||||
}
|
||||
|
||||
.show {
|
||||
@ -339,7 +333,7 @@ class MultiWallet extends LitElement {
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
border-radius: 3px;
|
||||
filter: grayscale(100%);
|
||||
filter: grayscale(100%);
|
||||
}
|
||||
.currency-box.active .currency-image,
|
||||
.currency-box:hover .currency-image {
|
||||
@ -473,65 +467,64 @@ class MultiWallet extends LitElement {
|
||||
}
|
||||
}
|
||||
`,
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
|
||||
this.lastBlock = {
|
||||
height: 0,
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
|
||||
this.selectedTransaction = {}
|
||||
this.isTextMenuOpen = false
|
||||
this.loading = true
|
||||
this.lastBlock = {
|
||||
height: 0,
|
||||
}
|
||||
|
||||
this.selectWallet = this.selectWallet.bind(this)
|
||||
|
||||
this.wallets=new Map()
|
||||
let coinProp={
|
||||
balance:0,
|
||||
wallet:null,
|
||||
transactions:[],
|
||||
fetchingWalletBalance:false,
|
||||
fetchingWalletTransactions:false
|
||||
}
|
||||
coinsNames.forEach((c,i)=>{//reset fetching status, c:coin, i:index
|
||||
this.wallets.set(c,{...coinProp})
|
||||
},this)//thisArg=this
|
||||
this.selectedTransaction = {}
|
||||
this.isTextMenuOpen = false
|
||||
this.loading = true
|
||||
|
||||
this.wallets.get('qort').wallet = window.parent.reduxStore.getState().app.selectedAddress
|
||||
this.wallets.get('btc').wallet = window.parent.reduxStore.getState().app.selectedAddress.btcWallet
|
||||
this.wallets.get('ltc').wallet = window.parent.reduxStore.getState().app.selectedAddress.ltcWallet
|
||||
this.wallets.get('doge').wallet = window.parent.reduxStore.getState().app.selectedAddress.dogeWallet
|
||||
this.selectWallet = this.selectWallet.bind(this)
|
||||
|
||||
this._selectedWallet='qort'
|
||||
this.wallets = new Map()
|
||||
let coinProp = {
|
||||
balance: 0,
|
||||
wallet: null,
|
||||
transactions: [],
|
||||
fetchingWalletBalance: false,
|
||||
fetchingWalletTransactions: false
|
||||
}
|
||||
coinsNames.forEach((c, i) => {
|
||||
this.wallets.set(c, { ...coinProp })
|
||||
}, this)
|
||||
|
||||
parentEpml.ready().then(() => {
|
||||
parentEpml.subscribe('selected_address', async (selectedAddress) => {
|
||||
selectedAddress = JSON.parse(selectedAddress)
|
||||
if (!selectedAddress || Object.entries(selectedAddress).length === 0) return
|
||||
|
||||
this.wallets.get('qort').wallet = selectedAddress
|
||||
this.wallets.get('btc').wallet = window.parent.reduxStore.getState().app.selectedAddress.btcWallet
|
||||
this.wallets.get('ltc').wallet = window.parent.reduxStore.getState().app.selectedAddress.ltcWallet
|
||||
this.wallets.get('doge').wallet = window.parent.reduxStore.getState().app.selectedAddress.dogeWallet
|
||||
// this.updateAccountTransactions();
|
||||
})
|
||||
this.wallets.get('qort').wallet = window.parent.reduxStore.getState().app.selectedAddress
|
||||
this.wallets.get('btc').wallet = window.parent.reduxStore.getState().app.selectedAddress.btcWallet
|
||||
this.wallets.get('ltc').wallet = window.parent.reduxStore.getState().app.selectedAddress.ltcWallet
|
||||
this.wallets.get('doge').wallet = window.parent.reduxStore.getState().app.selectedAddress.dogeWallet
|
||||
|
||||
parentEpml.subscribe('copy_menu_switch', async (value) => {
|
||||
if (value === 'false' && this.isTextMenuOpen === true) {
|
||||
this.clearSelection()
|
||||
this.isTextMenuOpen = false
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
this._selectedWallet = 'qort'
|
||||
|
||||
render() {
|
||||
return html`
|
||||
parentEpml.ready().then(() => {
|
||||
parentEpml.subscribe('selected_address', async (selectedAddress) => {
|
||||
selectedAddress = JSON.parse(selectedAddress)
|
||||
if (!selectedAddress || Object.entries(selectedAddress).length === 0) return
|
||||
|
||||
this.wallets.get('qort').wallet = selectedAddress
|
||||
this.wallets.get('btc').wallet = window.parent.reduxStore.getState().app.selectedAddress.btcWallet
|
||||
this.wallets.get('ltc').wallet = window.parent.reduxStore.getState().app.selectedAddress.ltcWallet
|
||||
this.wallets.get('doge').wallet = window.parent.reduxStore.getState().app.selectedAddress.dogeWallet
|
||||
})
|
||||
|
||||
parentEpml.subscribe('copy_menu_switch', async (value) => {
|
||||
if (value === 'false' && this.isTextMenuOpen === true) {
|
||||
this.clearSelection()
|
||||
this.isTextMenuOpen = false
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<div class="wrapper">
|
||||
<div class="wallet">
|
||||
<div style="font-size: 20px; color: #777; padding: 16px; border-bottom: 1px solid #eee;">Wallets</div>
|
||||
@ -599,13 +592,11 @@ class MultiWallet extends LitElement {
|
||||
<span class="title">Receiver</span>
|
||||
<br />
|
||||
<div><span class="">${this.selectedTransaction.recipient}</span></div>
|
||||
${!this.selectedTransaction.amount
|
||||
? ''
|
||||
: html`
|
||||
<span class="title">Amount</span>
|
||||
<br />
|
||||
<div><span class="">${this.selectedTransaction.amount} QORT</span></div>
|
||||
`}
|
||||
${!this.selectedTransaction.amount ? '' : html`
|
||||
<span class="title">Amount</span>
|
||||
<br />
|
||||
<div><span class="">${this.selectedTransaction.amount} QORT</span></div>
|
||||
`}
|
||||
<span class="title"> Transaction Fee </span>
|
||||
<br />
|
||||
<div><span class="">${this.selectedTransaction.fee}</span></div>
|
||||
@ -626,52 +617,52 @@ class MultiWallet extends LitElement {
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
getSelectedWalletAddress() {
|
||||
return this._selectedWallet === 'qort'
|
||||
? this.wallets.get(this._selectedWallet).wallet.address
|
||||
: this.wallets.get(this._selectedWallet).wallet.address
|
||||
}
|
||||
|
||||
getSelectedWalletAddress() {
|
||||
return this._selectedWallet === 'qort'
|
||||
? this.wallets.get(this._selectedWallet).wallet.address
|
||||
: this.wallets.get(this._selectedWallet).wallet.address
|
||||
}
|
||||
|
||||
async getTransactionGrid(coin) {
|
||||
this.transactionsGrid = this.shadowRoot.querySelector(`#${coin}TransactionsGrid`)
|
||||
if (coin === 'qort') {
|
||||
this.transactionsGrid.addEventListener(
|
||||
'click',
|
||||
(e) => {
|
||||
let myItem = this.transactionsGrid.getEventContext(e).item
|
||||
this.showTransactionDetails(myItem, this.wallets.get(this._selectedWallet).transactions)
|
||||
},
|
||||
{ passive: true }
|
||||
)
|
||||
}
|
||||
|
||||
this.pagesControl = this.shadowRoot.querySelector('#pages')
|
||||
this.pages = undefined
|
||||
}
|
||||
async getTransactionGrid(coin) {
|
||||
this.transactionsGrid = this.shadowRoot.querySelector(`#${coin}TransactionsGrid`)
|
||||
if (coin === 'qort') {
|
||||
this.transactionsGrid.addEventListener(
|
||||
'click',
|
||||
(e) => {
|
||||
let myItem = this.transactionsGrid.getEventContext(e).item
|
||||
this.showTransactionDetails(myItem, this.wallets.get(this._selectedWallet).transactions)
|
||||
},
|
||||
{ passive: true }
|
||||
)
|
||||
}
|
||||
|
||||
async renderTransactions() {
|
||||
if (this._selectedWallet === 'qort') {
|
||||
render(this.renderQortTransactions(this.wallets.get(this._selectedWallet).transactions, this._selectedWallet), this.transactionsDOM)
|
||||
} else {
|
||||
render(this.renderBTCLikeTransactions(this.wallets.get(this._selectedWallet).transactions, this._selectedWallet), this.transactionsDOM)
|
||||
}
|
||||
}
|
||||
this.pagesControl = this.shadowRoot.querySelector('#pages')
|
||||
this.pages = undefined
|
||||
}
|
||||
|
||||
renderQortTransactions(transactions, coin) {
|
||||
const requiredConfirmations = 3 // arbitrary value
|
||||
// initially `currentBlockHeight` might not be set in the store
|
||||
const currentBlockHeight = window.parent.reduxStore.getState().app.blockInfo.height
|
||||
if (Array.isArray(transactions)) {
|
||||
transactions = transactions.map(tx => {
|
||||
tx.confirmations = (currentBlockHeight - (tx.blockHeight - 1)) || ''
|
||||
return tx
|
||||
})
|
||||
}
|
||||
async renderTransactions() {
|
||||
if (this._selectedWallet === 'qort') {
|
||||
render(this.renderQortTransactions(this.wallets.get(this._selectedWallet).transactions, this._selectedWallet), this.transactionsDOM)
|
||||
} else {
|
||||
render(this.renderBTCLikeTransactions(this.wallets.get(this._selectedWallet).transactions, this._selectedWallet), this.transactionsDOM)
|
||||
}
|
||||
}
|
||||
|
||||
return html`
|
||||
renderQortTransactions(transactions, coin) {
|
||||
const requiredConfirmations = 3 // arbitrary value
|
||||
// initially `currentBlockHeight` might not be set in the store
|
||||
const currentBlockHeight = window.parent.reduxStore.getState().app.blockInfo.height
|
||||
if (Array.isArray(transactions)) {
|
||||
transactions = transactions.map(tx => {
|
||||
tx.confirmations = (currentBlockHeight - (tx.blockHeight - 1)) || ''
|
||||
return tx
|
||||
})
|
||||
}
|
||||
|
||||
return html`
|
||||
<dom-module id="vaadin-grid-qort-theme" theme-for="vaadin-grid">
|
||||
<template>
|
||||
<style>
|
||||
@ -685,20 +676,20 @@ class MultiWallet extends LitElement {
|
||||
</template>
|
||||
</dom-module>
|
||||
<div style="padding-left:12px;" ?hidden="${!this.isEmptyArray(transactions)}">Address has no transactions yet.</div>
|
||||
<vaadin-grid theme="${coin}" id="${coin}TransactionsGrid" ?hidden="${this.isEmptyArray(this.wallets.get(this._selectedWallet).transactions)}" page-size="20" height-by-rows>
|
||||
<vaadin-grid theme="${coin}" id="${coin}TransactionsGrid" ?hidden="${this.isEmptyArray(this.wallets.get(this._selectedWallet).transactions)}" page-size="20" all-rows-visible>
|
||||
<vaadin-grid-column
|
||||
auto-width
|
||||
.renderer=${(root, column, data) => {
|
||||
if (!currentBlockHeight) {
|
||||
return render(html``, root)
|
||||
}
|
||||
const confirmed = data.item.confirmations >= requiredConfirmations
|
||||
if (confirmed) {
|
||||
render(html`<mwc-icon title="${ data.item.confirmations } Confirmations" style="color: #00C851">check</mwc-icon>`, root)
|
||||
} else {
|
||||
render(html`<mwc-icon title="${ data.item.confirmations || 0 }/${ requiredConfirmations } Confirmations" style="color: #777">schedule</mwc-icon>`, root)
|
||||
}
|
||||
}}
|
||||
if (!currentBlockHeight) {
|
||||
return render(html``, root)
|
||||
}
|
||||
const confirmed = data.item.confirmations >= requiredConfirmations
|
||||
if (confirmed) {
|
||||
render(html`<mwc-icon title="${data.item.confirmations} Confirmations" style="color: #00C851">check</mwc-icon>`, root)
|
||||
} else {
|
||||
render(html`<mwc-icon title="${data.item.confirmations || 0}/${requiredConfirmations} Confirmations" style="color: #777">schedule</mwc-icon>`, root)
|
||||
}
|
||||
}}
|
||||
>
|
||||
</vaadin-grid-column>
|
||||
<vaadin-grid-column
|
||||
@ -706,8 +697,8 @@ class MultiWallet extends LitElement {
|
||||
resizable
|
||||
header="Type"
|
||||
.renderer=${(root, column, data) => {
|
||||
render(html` ${data.item.type} ${data.item.creatorAddress === this.wallets.get('qort').wallet.address ? html`<span class="color-out">OUT</span>` : html`<span class="color-in">IN</span>`} `, root)
|
||||
}}
|
||||
render(html` ${data.item.type} ${data.item.creatorAddress === this.wallets.get('qort').wallet.address ? html`<span class="color-out">OUT</span>` : html`<span class="color-in">IN</span>`} `, root)
|
||||
}}
|
||||
>
|
||||
</vaadin-grid-column>
|
||||
<vaadin-grid-column auto-width resizable header="Sender" path="creatorAddress"></vaadin-grid-column>
|
||||
@ -719,29 +710,29 @@ class MultiWallet extends LitElement {
|
||||
resizable
|
||||
header="Time"
|
||||
.renderer=${(root, column, data) => {
|
||||
const time = new Date(data.item.timestamp)
|
||||
render(html` <time-ago datetime=${time.toISOString()}> </time-ago> `, root)
|
||||
}}
|
||||
const time = new Date(data.item.timestamp)
|
||||
render(html` <time-ago datetime=${time.toISOString()}> </time-ago> `, root)
|
||||
}}
|
||||
>
|
||||
</vaadin-grid-column>
|
||||
</vaadin-grid>
|
||||
<div id="pages"></div>
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
renderBTCLikeTransactions(transactions, coin) {
|
||||
return html`
|
||||
renderBTCLikeTransactions(transactions, coin) {
|
||||
return html`
|
||||
<div style="padding-left:12px;" ?hidden="${!this.isEmptyArray(transactions)}">Address has no transactions yet.</div>
|
||||
<vaadin-grid id="${coin}TransactionsGrid" ?hidden="${this.isEmptyArray(this.wallets.get(this._selectedWallet).transactions)}" page-size="20" height-by-rows>
|
||||
<vaadin-grid id="${coin}TransactionsGrid" ?hidden="${this.isEmptyArray(this.wallets.get(this._selectedWallet).transactions)}" page-size="20" all-rows-visible>
|
||||
<vaadin-grid-column auto-width resizable header="Transaction Hash" path="txHash"></vaadin-grid-column>
|
||||
<vaadin-grid-column
|
||||
auto-width
|
||||
resizable
|
||||
header="Total Amount"
|
||||
.renderer=${(root, column, data) => {
|
||||
const amount = (Number(data.item.totalAmount) / 1e8).toFixed(8)
|
||||
render(html`${amount}`, root)
|
||||
}}
|
||||
const amount = (Number(data.item.totalAmount) / 1e8).toFixed(8)
|
||||
render(html`${amount}`, root)
|
||||
}}
|
||||
>
|
||||
</vaadin-grid-column>
|
||||
<vaadin-grid-column
|
||||
@ -749,122 +740,122 @@ class MultiWallet extends LitElement {
|
||||
resizable
|
||||
header="Time"
|
||||
.renderer=${(root, column, data) => {
|
||||
const time = new Date(data.item.timestamp * 1000)
|
||||
render(html` <time-ago datetime=${time.toISOString()}> </time-ago> `, root)
|
||||
}}
|
||||
const time = new Date(data.item.timestamp * 1000)
|
||||
render(html` <time-ago datetime=${time.toISOString()}> </time-ago> `, root)
|
||||
}}
|
||||
>
|
||||
</vaadin-grid-column>
|
||||
</vaadin-grid>
|
||||
<div id="pages"></div>
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
async updateItemsFromPage(page, changeWallet = false) {
|
||||
if (page === undefined) {
|
||||
return
|
||||
}
|
||||
async updateItemsFromPage(page, changeWallet = false) {
|
||||
if (page === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
changeWallet === true ? (this.pagesControl.innerHTML = '') : null
|
||||
changeWallet === true ? (this.pagesControl.innerHTML = '') : null
|
||||
|
||||
if (!this.pages) {
|
||||
this.pages = Array.apply(null, { length: Math.ceil(this.wallets.get(this._selectedWallet).transactions.length / this.transactionsGrid.pageSize) }).map((item, index) => {
|
||||
return index + 1
|
||||
})
|
||||
if (!this.pages) {
|
||||
this.pages = Array.apply(null, { length: Math.ceil(this.wallets.get(this._selectedWallet).transactions.length / this.transactionsGrid.pageSize) }).map((item, index) => {
|
||||
return index + 1
|
||||
})
|
||||
|
||||
const prevBtn = document.createElement('button')
|
||||
prevBtn.textContent = '<'
|
||||
prevBtn.addEventListener('click', () => {
|
||||
const selectedPage = parseInt(this.pagesControl.querySelector('[selected]').textContent)
|
||||
this.updateItemsFromPage(selectedPage - 1)
|
||||
})
|
||||
this.pagesControl.appendChild(prevBtn)
|
||||
const prevBtn = document.createElement('button')
|
||||
prevBtn.textContent = '<'
|
||||
prevBtn.addEventListener('click', () => {
|
||||
const selectedPage = parseInt(this.pagesControl.querySelector('[selected]').textContent)
|
||||
this.updateItemsFromPage(selectedPage - 1)
|
||||
})
|
||||
this.pagesControl.appendChild(prevBtn)
|
||||
|
||||
this.pages.forEach((pageNumber) => {
|
||||
const pageBtn = document.createElement('button')
|
||||
pageBtn.textContent = pageNumber
|
||||
pageBtn.addEventListener('click', (e) => {
|
||||
this.updateItemsFromPage(parseInt(e.target.textContent))
|
||||
})
|
||||
if (pageNumber === page) {
|
||||
pageBtn.setAttribute('selected', true)
|
||||
}
|
||||
this.pagesControl.appendChild(pageBtn)
|
||||
})
|
||||
this.pages.forEach((pageNumber) => {
|
||||
const pageBtn = document.createElement('button')
|
||||
pageBtn.textContent = pageNumber
|
||||
pageBtn.addEventListener('click', (e) => {
|
||||
this.updateItemsFromPage(parseInt(e.target.textContent))
|
||||
})
|
||||
if (pageNumber === page) {
|
||||
pageBtn.setAttribute('selected', true)
|
||||
}
|
||||
this.pagesControl.appendChild(pageBtn)
|
||||
})
|
||||
|
||||
const nextBtn = window.document.createElement('button')
|
||||
nextBtn.textContent = '>'
|
||||
nextBtn.addEventListener('click', () => {
|
||||
const selectedPage = parseInt(this.pagesControl.querySelector('[selected]').textContent)
|
||||
this.updateItemsFromPage(selectedPage + 1)
|
||||
})
|
||||
this.pagesControl.appendChild(nextBtn)
|
||||
}
|
||||
const nextBtn = window.document.createElement('button')
|
||||
nextBtn.textContent = '>'
|
||||
nextBtn.addEventListener('click', () => {
|
||||
const selectedPage = parseInt(this.pagesControl.querySelector('[selected]').textContent)
|
||||
this.updateItemsFromPage(selectedPage + 1)
|
||||
})
|
||||
this.pagesControl.appendChild(nextBtn)
|
||||
}
|
||||
|
||||
const buttons = Array.from(this.pagesControl.children)
|
||||
buttons.forEach((btn, index) => {
|
||||
if (parseInt(btn.textContent) === page) {
|
||||
btn.setAttribute('selected', true)
|
||||
} else {
|
||||
btn.removeAttribute('selected')
|
||||
}
|
||||
if (index === 0) {
|
||||
if (page === 1) {
|
||||
btn.setAttribute('disabled', '')
|
||||
} else {
|
||||
btn.removeAttribute('disabled')
|
||||
}
|
||||
}
|
||||
if (index === buttons.length - 1) {
|
||||
if (page === this.pages.length) {
|
||||
btn.setAttribute('disabled', '')
|
||||
} else {
|
||||
btn.removeAttribute('disabled')
|
||||
}
|
||||
}
|
||||
})
|
||||
let start = (page - 1) * this.transactionsGrid.pageSize
|
||||
let end = page * this.transactionsGrid.pageSize
|
||||
const buttons = Array.from(this.pagesControl.children)
|
||||
buttons.forEach((btn, index) => {
|
||||
if (parseInt(btn.textContent) === page) {
|
||||
btn.setAttribute('selected', true)
|
||||
} else {
|
||||
btn.removeAttribute('selected')
|
||||
}
|
||||
if (index === 0) {
|
||||
if (page === 1) {
|
||||
btn.setAttribute('disabled', '')
|
||||
} else {
|
||||
btn.removeAttribute('disabled')
|
||||
}
|
||||
}
|
||||
if (index === buttons.length - 1) {
|
||||
if (page === this.pages.length) {
|
||||
btn.setAttribute('disabled', '')
|
||||
} else {
|
||||
btn.removeAttribute('disabled')
|
||||
}
|
||||
}
|
||||
})
|
||||
let start = (page - 1) * this.transactionsGrid.pageSize
|
||||
let end = page * this.transactionsGrid.pageSize
|
||||
|
||||
this.transactionsGrid.items = this.wallets.get(this._selectedWallet).transactions.slice(start, end)
|
||||
}
|
||||
this.transactionsGrid.items = this.wallets.get(this._selectedWallet).transactions.slice(start, end)
|
||||
}
|
||||
|
||||
_textMenu(event) {
|
||||
const getSelectedText = () => {
|
||||
var text = ''
|
||||
if (typeof window.getSelection != 'undefined') {
|
||||
text = window.getSelection().toString()
|
||||
} else if (typeof this.shadowRoot.selection != 'undefined' && this.shadowRoot.selection.type == 'Text') {
|
||||
text = this.shadowRoot.selection.createRange().text
|
||||
}
|
||||
return text
|
||||
}
|
||||
const checkSelectedTextAndShowMenu = () => {
|
||||
let selectedText = getSelectedText()
|
||||
if (selectedText && typeof selectedText === 'string') {
|
||||
let _eve = { pageX: event.pageX, pageY: event.pageY, clientX: event.clientX, clientY: event.clientY }
|
||||
_textMenu(event) {
|
||||
const getSelectedText = () => {
|
||||
var text = ''
|
||||
if (typeof window.getSelection != 'undefined') {
|
||||
text = window.getSelection().toString()
|
||||
} else if (typeof this.shadowRoot.selection != 'undefined' && this.shadowRoot.selection.type == 'Text') {
|
||||
text = this.shadowRoot.selection.createRange().text
|
||||
}
|
||||
return text
|
||||
}
|
||||
const checkSelectedTextAndShowMenu = () => {
|
||||
let selectedText = getSelectedText()
|
||||
if (selectedText && typeof selectedText === 'string') {
|
||||
let _eve = { pageX: event.pageX, pageY: event.pageY, clientX: event.clientX, clientY: event.clientY }
|
||||
|
||||
let textMenuObject = { selectedText: selectedText, eventObject: _eve, isFrame: true }
|
||||
let textMenuObject = { selectedText: selectedText, eventObject: _eve, isFrame: true }
|
||||
|
||||
parentEpml.request('openCopyTextMenu', textMenuObject)
|
||||
}
|
||||
}
|
||||
parentEpml.request('openCopyTextMenu', textMenuObject)
|
||||
}
|
||||
}
|
||||
|
||||
checkSelectedTextAndShowMenu()
|
||||
}
|
||||
checkSelectedTextAndShowMenu()
|
||||
}
|
||||
|
||||
getApiKey() {
|
||||
getApiKey() {
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node];
|
||||
let apiKey = myNode.apiKey;
|
||||
return apiKey;
|
||||
}
|
||||
|
||||
clearSelection() {
|
||||
window.getSelection().removeAllRanges()
|
||||
window.parent.getSelection().removeAllRanges()
|
||||
}
|
||||
clearSelection() {
|
||||
window.getSelection().removeAllRanges()
|
||||
window.parent.getSelection().removeAllRanges()
|
||||
}
|
||||
|
||||
transactionItem(transactionObject) {
|
||||
return `
|
||||
transactionItem(transactionObject) {
|
||||
return `
|
||||
<div class='transaction-item ${transactionObject.type}'>
|
||||
<div class='transaction-item_details'>
|
||||
<h3>${transactionObject.name}</h3>
|
||||
@ -875,193 +866,197 @@ class MultiWallet extends LitElement {
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
// DOM refs
|
||||
this.currencyBoxes = this.shadowRoot.querySelectorAll('.currency-box')
|
||||
this.transactionsDOM = this.shadowRoot.getElementById('transactionsDOM')
|
||||
firstUpdated() {
|
||||
// DOM refs
|
||||
this.currencyBoxes = this.shadowRoot.querySelectorAll('.currency-box')
|
||||
this.transactionsDOM = this.shadowRoot.getElementById('transactionsDOM')
|
||||
|
||||
// Attach eventlisteners to the cuurency boxes
|
||||
this.currencyBoxes.forEach((currencyBox) => {
|
||||
currencyBox.addEventListener('click', this.selectWallet)
|
||||
})
|
||||
// Attach eventlisteners to the cuurency boxes
|
||||
this.currencyBoxes.forEach((currencyBox) => {
|
||||
currencyBox.addEventListener('click', this.selectWallet)
|
||||
})
|
||||
|
||||
this.showWallet()
|
||||
this.showWallet()
|
||||
|
||||
window.addEventListener('contextmenu', (event) => {
|
||||
event.preventDefault()
|
||||
this.isTextMenuOpen = true
|
||||
this._textMenu(event)
|
||||
})
|
||||
window.addEventListener('click', () => {
|
||||
if (this.isTextMenuOpen) {
|
||||
parentEpml.request('closeCopyTextMenu', null)
|
||||
}
|
||||
})
|
||||
window.onkeyup = (e) => {
|
||||
if (e.keyCode === 27) {
|
||||
parentEpml.request('closeCopyTextMenu', null)
|
||||
}
|
||||
}
|
||||
}
|
||||
window.addEventListener('contextmenu', (event) => {
|
||||
event.preventDefault()
|
||||
this.isTextMenuOpen = true
|
||||
this._textMenu(event)
|
||||
})
|
||||
window.addEventListener('click', () => {
|
||||
if (this.isTextMenuOpen) {
|
||||
parentEpml.request('closeCopyTextMenu', null)
|
||||
}
|
||||
})
|
||||
window.onkeyup = (e) => {
|
||||
if (e.keyCode === 27) {
|
||||
parentEpml.request('closeCopyTextMenu', null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
selectWallet(event) {
|
||||
event.preventDefault()
|
||||
|
||||
const target = event.currentTarget
|
||||
selectWallet(event) {
|
||||
event.preventDefault()
|
||||
|
||||
// if (target.classList.contains('active')) return
|
||||
// removed to allow one click wallet refresh
|
||||
const target = event.currentTarget
|
||||
|
||||
this.currencyBoxes.forEach((currencyBox) => {
|
||||
if (currencyBox.classList.contains('active')) {
|
||||
currencyBox.classList.remove('active')
|
||||
}
|
||||
})
|
||||
target.classList.add('active')
|
||||
this._selectedWallet=target.attributes.coin.value
|
||||
this.showWallet()
|
||||
}
|
||||
// if (target.classList.contains('active')) return
|
||||
// removed to allow one click wallet refresh
|
||||
|
||||
async showWallet(){
|
||||
this.transactionsDOM.hidden = true
|
||||
this.loading = true
|
||||
this.currencyBoxes.forEach((currencyBox) => {
|
||||
if (currencyBox.classList.contains('active')) {
|
||||
currencyBox.classList.remove('active')
|
||||
}
|
||||
})
|
||||
target.classList.add('active')
|
||||
this._selectedWallet = target.attributes.coin.value
|
||||
this.showWallet()
|
||||
}
|
||||
|
||||
if (this._selectedWallet=='qort') {
|
||||
if (!window.parent.reduxStore.getState().app.blockInfo.height) {
|
||||
// we make sure that `blockHeight` is set before rendering QORT transactions
|
||||
await parentEpml.request('apiCall', { url: `/blocks/height`, type: 'api' })
|
||||
.then(height => parentEpml.request('updateBlockInfo', { height }))
|
||||
}
|
||||
}
|
||||
const coin=this._selectedWallet
|
||||
await this.fetchWalletDetails(this._selectedWallet)
|
||||
if(this._selectedWallet == coin){//if the wallet didn't switch
|
||||
await this.renderTransactions()
|
||||
await this.getTransactionGrid(this._selectedWallet)
|
||||
await this.updateItemsFromPage(1, true)
|
||||
this.loading = false
|
||||
this.transactionsDOM.hidden = false
|
||||
}
|
||||
}
|
||||
async fetchWalletDetails(coin){//this function will fetch the balance and transactions of the given wallet
|
||||
this.balanceString="Fetching balance ..."
|
||||
switch (coin) {
|
||||
case 'qort':
|
||||
//fetching the qort balance
|
||||
parentEpml
|
||||
.request('apiCall', {
|
||||
url: `/addresses/balance/${this.wallets.get('qort').wallet.address}?apiKey=${this.getApiKey()}`,
|
||||
})
|
||||
.then((res) => {
|
||||
if (isNaN(Number(res))) {
|
||||
parentEpml.request('showSnackBar', `Failed to Fetch QORT Balance. Try again!`)
|
||||
} else {
|
||||
if(this._selectedWallet==coin){//check if we are still fetching wallet balance ...
|
||||
this.wallets.get(coin).balance = res
|
||||
this.balanceString=this.wallets.get(this._selectedWallet).balance+" "+this._selectedWallet.toLocaleUpperCase()
|
||||
}
|
||||
}
|
||||
})
|
||||
//fetching the qort transactions
|
||||
const txsQort = await parentEpml.request('apiCall', {
|
||||
url: `/transactions/search?address=${this.wallets.get('qort').wallet.address}&confirmationStatus=CONFIRMED&reverse=true`,
|
||||
})
|
||||
if(this._selectedWallet==coin)
|
||||
this.wallets.get(coin).transactions = txsQort
|
||||
|
||||
break
|
||||
case 'btc':
|
||||
case 'ltc':
|
||||
case 'doge':
|
||||
//fetching the balance
|
||||
const walletName = `${coin}Wallet`
|
||||
parentEpml
|
||||
.request('apiCall', {
|
||||
url: `/crosschain/${coin}/walletbalance?apiKey=${this.getApiKey()}`,
|
||||
method: 'POST',
|
||||
body: `${window.parent.reduxStore.getState().app.selectedAddress[walletName].derivedMasterPublicKey}`,
|
||||
})
|
||||
.then((res) => {
|
||||
if (isNaN(Number(res))) {
|
||||
parentEpml.request('showSnackBar', `Failed to Fetch ${coin.toLocaleUpperCase()} Balance. Try again!`)
|
||||
} else {
|
||||
if(this._selectedWallet==coin){//check if we are still fetching wallet balance ...
|
||||
this.wallets.get(this._selectedWallet).balance = (Number(res) / 1e8).toFixed(8)
|
||||
this.balanceString=this.wallets.get(this._selectedWallet).balance+" "+this._selectedWallet.toLocaleUpperCase()
|
||||
}
|
||||
}
|
||||
})
|
||||
//fetching transactions
|
||||
const txs = await parentEpml.request('apiCall', {
|
||||
url: `/crosschain/${coin}/wallettransactions?apiKey=${this.getApiKey()}`,
|
||||
method: 'POST',
|
||||
body: `${window.parent.reduxStore.getState().app.selectedAddress[walletName].derivedMasterPublicKey}`,
|
||||
})
|
||||
const compareFn = (a, b) => {
|
||||
return b.timestamp - a.timestamp
|
||||
}
|
||||
const sortedTransactions = txs.sort(compareFn)
|
||||
async showWallet() {
|
||||
this.transactionsDOM.hidden = true
|
||||
this.loading = true
|
||||
|
||||
if(this._selectedWallet==coin){
|
||||
this.wallets.get(this._selectedWallet).transactions = sortedTransactions
|
||||
}
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
if (this._selectedWallet == 'qort') {
|
||||
if (!window.parent.reduxStore.getState().app.blockInfo.height) {
|
||||
// we make sure that `blockHeight` is set before rendering QORT transactions
|
||||
await parentEpml.request('apiCall', { url: `/blocks/height`, type: 'api' })
|
||||
.then(height => parentEpml.request('updateBlockInfo', { height }))
|
||||
}
|
||||
}
|
||||
const coin = this._selectedWallet
|
||||
await this.fetchWalletDetails(this._selectedWallet)
|
||||
if (this._selectedWallet == coin) {
|
||||
//if the wallet didn't switch
|
||||
await this.renderTransactions()
|
||||
await this.getTransactionGrid(this._selectedWallet)
|
||||
await this.updateItemsFromPage(1, true)
|
||||
this.loading = false
|
||||
this.transactionsDOM.hidden = false
|
||||
}
|
||||
}
|
||||
async fetchWalletDetails(coin) {
|
||||
//this function will fetch the balance and transactions of the given wallet
|
||||
this.balanceString = "Fetching balance ..."
|
||||
switch (coin) {
|
||||
case 'qort':
|
||||
//fetching the qort balance
|
||||
parentEpml
|
||||
.request('apiCall', {
|
||||
url: `/addresses/balance/${this.wallets.get('qort').wallet.address}?apiKey=${this.getApiKey()}`,
|
||||
})
|
||||
.then((res) => {
|
||||
if (isNaN(Number(res))) {
|
||||
parentEpml.request('showSnackBar', `Failed to Fetch QORT Balance. Try again!`)
|
||||
} else {
|
||||
if (this._selectedWallet == coin) {
|
||||
//check if we are still fetching wallet balance ...
|
||||
this.wallets.get(coin).balance = res
|
||||
this.balanceString = this.wallets.get(this._selectedWallet).balance + " " + this._selectedWallet.toLocaleUpperCase()
|
||||
}
|
||||
}
|
||||
})
|
||||
//fetching the qort transactions
|
||||
const txsQort = await parentEpml.request('apiCall', {
|
||||
url: `/transactions/search?address=${this.wallets.get('qort').wallet.address}&confirmationStatus=CONFIRMED&reverse=true`,
|
||||
})
|
||||
if (this._selectedWallet == coin)
|
||||
this.wallets.get(coin).transactions = txsQort
|
||||
|
||||
showTransactionDetails(myTransaction, allTransactions) {
|
||||
allTransactions.forEach((transaction) => {
|
||||
if (myTransaction.signature === transaction.signature) {
|
||||
// Do something...
|
||||
let txnFlow = myTransaction.creatorAddress === this.wallets.get('qort').wallet.address ? 'OUT' : 'IN'
|
||||
this.selectedTransaction = { ...transaction, txnFlow }
|
||||
if (this.selectedTransaction.signature.length != 0) {
|
||||
this.shadowRoot.querySelector('#showTransactionDetailsDialog').show()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
break
|
||||
case 'btc':
|
||||
case 'ltc':
|
||||
case 'doge':
|
||||
//fetching the balance
|
||||
const walletName = `${coin}Wallet`
|
||||
parentEpml
|
||||
.request('apiCall', {
|
||||
url: `/crosschain/${coin}/walletbalance?apiKey=${this.getApiKey()}`,
|
||||
method: 'POST',
|
||||
body: `${window.parent.reduxStore.getState().app.selectedAddress[walletName].derivedMasterPublicKey}`,
|
||||
})
|
||||
.then((res) => {
|
||||
if (isNaN(Number(res))) {
|
||||
parentEpml.request('showSnackBar', `Failed to Fetch ${coin.toLocaleUpperCase()} Balance. Try again!`)
|
||||
} else {
|
||||
if (this._selectedWallet == coin) {
|
||||
//check if we are still fetching wallet balance ...
|
||||
this.wallets.get(this._selectedWallet).balance = (Number(res) / 1e8).toFixed(8)
|
||||
this.balanceString = this.wallets.get(this._selectedWallet).balance + " " + this._selectedWallet.toLocaleUpperCase()
|
||||
}
|
||||
}
|
||||
})
|
||||
//fetching transactions
|
||||
const txs = await parentEpml.request('apiCall', {
|
||||
url: `/crosschain/${coin}/wallettransactions?apiKey=${this.getApiKey()}`,
|
||||
method: 'POST',
|
||||
body: `${window.parent.reduxStore.getState().app.selectedAddress[walletName].derivedMasterPublicKey}`,
|
||||
})
|
||||
const compareFn = (a, b) => {
|
||||
return b.timestamp - a.timestamp
|
||||
}
|
||||
const sortedTransactions = txs.sort(compareFn)
|
||||
|
||||
isEmptyArray(arr) {
|
||||
if (!arr) {
|
||||
return true
|
||||
}
|
||||
return arr.length === 0
|
||||
}
|
||||
if (this._selectedWallet == coin) {
|
||||
this.wallets.get(this._selectedWallet).transactions = sortedTransactions
|
||||
}
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
floor(num) {
|
||||
num = parseFloat(num)
|
||||
return isNaN(num) ? 0 : this._format(Math.floor(num))
|
||||
}
|
||||
showTransactionDetails(myTransaction, allTransactions) {
|
||||
allTransactions.forEach((transaction) => {
|
||||
if (myTransaction.signature === transaction.signature) {
|
||||
// Do something...
|
||||
let txnFlow = myTransaction.creatorAddress === this.wallets.get('qort').wallet.address ? 'OUT' : 'IN'
|
||||
this.selectedTransaction = { ...transaction, txnFlow }
|
||||
if (this.selectedTransaction.signature.length != 0) {
|
||||
this.shadowRoot.querySelector('#showTransactionDetailsDialog').show()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
decimals(num) {
|
||||
num = parseFloat(num) // So that conversion to string can get rid of insignificant zeros
|
||||
// return isNaN(num) ? 0 : (num + "").split(".")[1]
|
||||
return num % 1 > 0 ? (num + '').split('.')[1] : '0'
|
||||
}
|
||||
isEmptyArray(arr) {
|
||||
if (!arr) {
|
||||
return true
|
||||
}
|
||||
return arr.length === 0
|
||||
}
|
||||
|
||||
subtract(num1, num2) {
|
||||
return num1 - num2
|
||||
}
|
||||
floor(num) {
|
||||
num = parseFloat(num)
|
||||
return isNaN(num) ? 0 : this._format(Math.floor(num))
|
||||
}
|
||||
|
||||
getConfirmations(height, lastBlockHeight) {
|
||||
return lastBlockHeight - height + 1
|
||||
}
|
||||
decimals(num) {
|
||||
num = parseFloat(num)
|
||||
// So that conversion to string can get rid of insignificant zeros
|
||||
return num % 1 > 0 ? (num + '').split('.')[1] : '0'
|
||||
}
|
||||
|
||||
_format(num) {
|
||||
return num.toLocaleString()
|
||||
}
|
||||
subtract(num1, num2) {
|
||||
return num1 - num2
|
||||
}
|
||||
|
||||
textColor(color) {
|
||||
return color === 'light' ? 'rgba(255,255,255,0.7)' : 'rgba(0,0,0,0.87)'
|
||||
}
|
||||
_unconfirmedClass(unconfirmed) {
|
||||
return unconfirmed ? 'unconfirmed' : ''
|
||||
}
|
||||
getConfirmations(height, lastBlockHeight) {
|
||||
return lastBlockHeight - height + 1
|
||||
}
|
||||
|
||||
_format(num) {
|
||||
return num.toLocaleString()
|
||||
}
|
||||
|
||||
textColor(color) {
|
||||
return color === 'light' ? 'rgba(255,255,255,0.7)' : 'rgba(0,0,0,0.87)'
|
||||
}
|
||||
_unconfirmedClass(unconfirmed) {
|
||||
return unconfirmed ? 'unconfirmed' : ''
|
||||
}
|
||||
}
|
||||
|
||||
window.customElements.define('multi-wallet', MultiWallet)
|
||||
|
Loading…
x
Reference in New Issue
Block a user