4
1
mirror of https://github.com/Qortal/qortal-ui.git synced 2025-02-11 17:55:51 +00:00

add bootstrap button to node and added new request

This commit is contained in:
PhilReact 2024-01-03 14:24:54 +02:00
parent fee90d4934
commit 02c378687b
3 changed files with 221 additions and 168 deletions

View File

@ -1274,7 +1274,7 @@
"tour16": "Checklist",
"tour17": "Please start the Core to access the Qortal blockchain.",
"tour18": "Refresh (bootstrap)",
"tour19": "Currently syncing... you must be fully synchronized to use Qortal",
"tour19": "Currently syncing... you must be fully synchronized to use Qortal.",
"tour20": "blocks behind. Would you like to refresh (bootstrap) to speed up the syncing process?",
"tour21": "blocks remaining.",
"tour22": "Refresh (bootstrap) requested. Please wait."

View File

@ -1,8 +1,8 @@
import {css, html, LitElement} from 'lit'
import {render} from 'lit/html.js'
import {Epml} from '../../../epml.js'
import { css, html, LitElement } from 'lit'
import { render } from 'lit/html.js'
import { Epml } from '../../../epml.js'
import isElectron from 'is-electron'
import {get, registerTranslateConfig, translate, use} from '../../../../core/translate/index.js'
import { get, registerTranslateConfig, translate, use } from '../../../../core/translate/index.js'
import '@polymer/paper-spinner/paper-spinner-lite.js'
import '@material/mwc-icon'
import '@material/mwc-textfield'
@ -11,7 +11,7 @@ import '@material/mwc-dialog'
import '@vaadin/grid'
registerTranslateConfig({
loader: lang => fetch(`/language/${lang}.json`).then(res => res.json())
loader: lang => fetch(`/language/${lang}.json`).then(res => res.json())
})
const parentEpml = new Epml({ type: "WINDOW", source: window.parent })
@ -146,10 +146,11 @@ class NodeManagement extends LitElement {
}
render() {
return html`
return html`
<div id="node-management-page">
<div class="node-card">
<h2>${translate("nodepage.nchange1")} ${this.nodeDomain}</h2>
<mwc-button style="float:right;" ?hidden="${(this.upTime === "offline")}" @click=${() => this.bootstrap()}><mwc-icon>restart_alt</mwc-icon>&nbsp;${translate("tour.tour18")}</mwc-button>
<mwc-button style="float:right;" class="red" ?hidden="${(this.upTime === "offline")}" @click=${() => this.stopNode()}><mwc-icon>dangerous</mwc-icon>&nbsp;${translate("nodepage.nchange31")}</mwc-button>
<mwc-button style="float:right;" ?hidden="${(this.upTime === "offline")}" @click=${() => this.restartNode()}><mwc-icon>360</mwc-icon>&nbsp;${translate("nodepage.nchange33")}</mwc-button>
<span class="sblack"><br>${translate("nodepage.nchange2")} ${this.upTime}</span>
@ -166,12 +167,12 @@ class NodeManagement extends LitElement {
<vaadin-grid-column auto-width header="${translate("nodepage.nchange9")}" path="mintingAccount"></vaadin-grid-column>
<vaadin-grid-column auto-width header="${translate("nodepage.nchange10")}" path="recipientAccount"></vaadin-grid-column>
<vaadin-grid-column width="12em" header="${translate("nodepage.nchange11")}" .renderer=${(root, column, data) => {
render(html`
render(html`
<mwc-button class="red" ?disabled=${this.removeMintingAccountLoading} @click=${() => this.removeMintingAccount(data.item.publicKey)}>
<mwc-icon>create</mwc-icon>&nbsp;${translate("nodepage.nchange12")}
</mwc-button>
`, root)
}}></vaadin-grid-column>
}}></vaadin-grid-column>
</vaadin-grid>
${this.isEmptyArray(this.mintingAccounts) ? html`<span style="color: var(--black);">${translate("nodepage.nchange13")}</span>` : ""}
</div><br>
@ -189,7 +190,7 @@ class NodeManagement extends LitElement {
<vaadin-grid-column header="${translate("nodepage.nchange20")}" path="version"></vaadin-grid-column>
<vaadin-grid-column header="${translate("nodepage.nchange21")}" path="age"></vaadin-grid-column>
<vaadin-grid-column width="12em" header="${translate("nodepage.nchange22")}" .renderer=${(root, column, data) => {
render(html`
render(html`
<mwc-button class="red" @click=${() => this.removePeer(data.item.address, data.index)}>
<mwc-icon>delete</mwc-icon>&nbsp;${translate("nodepage.nchange12")}
</mwc-button>
@ -197,7 +198,7 @@ class NodeManagement extends LitElement {
&nbsp;${translate("nodepage.nchange23")}
</mwc-button>
`, root)
}}></vaadin-grid-column>
}}></vaadin-grid-column>
</vaadin-grid>
${this.isEmptyArray(this.peers) ? html`<span style="color: var(--black);">${translate("nodepage.nchange24")}</span>` : ""}
</div><br>
@ -408,7 +409,7 @@ class NodeManagement extends LitElement {
method: "GET"
})
.then((res) => {
let snackString = get("nodepage.nchange32")
let snackString = get("nodepage.nchange32")
parentEpml.request('showSnackBar', `${snackString}`)
})
}
@ -420,21 +421,34 @@ class NodeManagement extends LitElement {
method: "GET"
})
.then((res) => {
let snackString = get("nodepage.nchange34")
let snackString = get("nodepage.nchange34")
parentEpml.request('showSnackBar', `${snackString}`)
})
}
bootstrap() {
parentEpml
.request("apiCall", {
url: `/admin/bootstrap/?apiKey=${this.getApiKey()}`,
method: "GET"
})
.then((res) => {
if (res === true) {
let snackString = get("tour.tour22")
parentEpml.request('showSnackBar', `${snackString}`)
}
})
}
async addPeer() {
this.addPeerLoading = true
const addPeerAddress = this.shadowRoot.getElementById('addPeerAddress').value
console.log("ADDRESS", addPeerAddress)
await parentEpml.request("apiCall", {
url: `/peers?apiKey=${this.getApiKey()}`,
method: "POST",
body: addPeerAddress
}).then((res) => {
console.log("RES", res)
if (res === true) {
let trueString = get("walletpage.wchange52")
parentEpml.request('showSnackBar', `${trueString}`)

View File

@ -1,7 +1,7 @@
import {css, html, LitElement} from 'lit'
import {Epml} from '../../../../epml'
import { css, html, LitElement } from 'lit'
import { Epml } from '../../../../epml'
import isElectron from 'is-electron'
import {get, registerTranslateConfig, translate, use} from '../../../../../core/translate/index.js'
import { get, registerTranslateConfig, translate, use } from '../../../../../core/translate/index.js'
import ShortUniqueId from 'short-unique-id';
import FileSaver from 'file-saver'
import * as actions from '../../components/qdn-action-types'
@ -10,10 +10,10 @@ import '@material/mwc-icon'
import '@material/mwc-checkbox'
import WebWorker from 'web-worker:./computePowWorkerFile.src.js'
import WebWorkerChat from 'web-worker:./computePowWorker.src.js'
import {publishData} from '../../../utils/publish-image.js'
import {Loader} from '../../../utils/loader.js';
import {QORT_DECIMALS} from '../../../../../crypto/api/constants'
import {mimeToExtensionMap} from '../../components/qdn-action-constants';
import { publishData } from '../../../utils/publish-image.js'
import { Loader } from '../../../utils/loader.js';
import { QORT_DECIMALS } from '../../../../../crypto/api/constants'
import { mimeToExtensionMap } from '../../components/qdn-action-constants';
import {
base64ToUint8Array,
decryptDeprecatedSingle,
@ -51,7 +51,7 @@ class WebBrowser extends LitElement {
dogeFeePerByte: { type: Number },
dgbFeePerByte: { type: Number },
rvnFeePerByte: { type: Number },
arrrWalletAddress: { type: String }
arrrWalletAddress: { type: String }
}
}
@ -323,39 +323,39 @@ class WebBrowser extends LitElement {
async linkOpenNewTab(link) {
const value = link
let newQuery = value
if (newQuery.endsWith('/')) {
newQuery = newQuery.slice(0, -1)
}
const res = await this.extractComponents(newQuery)
if (!res) return
const { service, name, identifier, path } = res
let query = `?service=${service}`
if (name) {
query = query + `&name=${name}`
}
if (identifier) {
query = query + `&identifier=${identifier}`
}
if (path) {
query = query + `&path=${path}`
}
const value = link
let newQuery = value
if (newQuery.endsWith('/')) {
newQuery = newQuery.slice(0, -1)
}
const res = await this.extractComponents(newQuery)
if (!res) return
const { service, name, identifier, path } = res
let query = `?service=${service}`
if (name) {
query = query + `&name=${name}`
}
if (identifier) {
query = query + `&identifier=${identifier}`
}
if (path) {
query = query + `&path=${path}`
}
window.parent.reduxStore.dispatch(window.parent.reduxAction.setNewTab({
url: `qdn/browser/index.html${query}`,
id: this.uid.rnd(),
myPlugObj: {
"url": service === 'WEBSITE' ? "websites" : "qapps",
"domain": "core",
"page": `qdn/browser/index.html${query}`,
"title": name,
"icon": service === 'WEBSITE' ? 'vaadin:desktop' : 'vaadin:external-browser',
"mwcicon": service === 'WEBSITE' ? 'desktop_mac' : 'open_in_browser',
"menus": [],
"parent": false
}
}))
window.parent.reduxStore.dispatch(window.parent.reduxAction.setNewTab({
url: `qdn/browser/index.html${query}`,
id: this.uid.rnd(),
myPlugObj: {
"url": service === 'WEBSITE' ? "websites" : "qapps",
"domain": "core",
"page": `qdn/browser/index.html${query}`,
"title": name,
"icon": service === 'WEBSITE' ? 'vaadin:desktop' : 'vaadin:external-browser',
"mwcicon": service === 'WEBSITE' ? 'desktop_mac' : 'open_in_browser',
"menus": [],
"parent": false
}
}))
}
@ -467,7 +467,7 @@ class WebBrowser extends LitElement {
return joinFee
}
async getArbitraryFee (){
async getArbitraryFee() {
const timestamp = Date.now()
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port
@ -714,11 +714,11 @@ class WebBrowser extends LitElement {
}
const makeTransactionRequest = async (lastRef) => {
let votedialog3 = get("transactions.votedialog3")
let votedialog4 = get("transactions.votedialog4")
let votedialog5 = get("transactions.votedialog5")
let votedialog6 = get("transactions.votedialog6")
let feeDialog = get("walletpage.wchange12")
let votedialog3 = get("transactions.votedialog3")
let votedialog4 = get("transactions.votedialog4")
let votedialog5 = get("transactions.votedialog5")
let votedialog6 = get("transactions.votedialog6")
let feeDialog = get("walletpage.wchange12")
let myTxnrequest = await parentEpml.request('transaction', {
type: 8,
@ -836,6 +836,45 @@ class WebBrowser extends LitElement {
}
}
case actions.ENCRYPT_DATA: {
try {
let dataSentBack = {}
let data64 = data.data64
let publicKeys = data.publicKeys || []
if (data.file) {
data64 = await fileToBase64(data.file)
}
if (!data64) {
dataSentBack['error'] = "Please include data to encrypt"
response = JSON.stringify(dataSentBack)
break
}
const encryptDataResponse = encryptDataGroup({
data64, publicKeys: publicKeys
})
if (encryptDataResponse) {
data64 = encryptDataResponse
response = JSON.stringify(encryptDataResponse)
break;
} else {
dataSentBack['error'] = "Unable to encrypt"
response = JSON.stringify(dataSentBack)
break
}
} catch (error) {
const data = {}
const errorMsg = error.message || "Error in encrypting data"
data['error'] = errorMsg
response = JSON.stringify(data)
break
}
}
case actions.DECRYPT_DATA: {
const { encryptedData, publicKey } = data
@ -1100,7 +1139,7 @@ class WebBrowser extends LitElement {
try {
let list = JSON.parse(localStorage.getItem('friends-my-friend-list') || "[]")
list = list.map((friend)=> friend.name || "")
list = list.map((friend) => friend.name || "")
response = JSON.stringify(list)
} catch (error) {
const data = {}
@ -1388,13 +1427,13 @@ class WebBrowser extends LitElement {
try {
const requiredFields = ['service', 'name']
const missingFields = []
requiredFields.forEach((field) => {
if (!resource[field]) {
missingFields.push(field)
}
})
if (missingFields.length > 0) {
const missingFieldsString = missingFields.join(', ')
const errorMsg = `Missing fields: ${missingFieldsString}`
@ -1404,7 +1443,7 @@ class WebBrowser extends LitElement {
})
continue
}
if (!resource.file && !resource.data64) {
const errorMsg = 'No data or file was submitted'
failedPublishesIdentifiers.push({
@ -1413,7 +1452,7 @@ class WebBrowser extends LitElement {
})
continue
}
const service = resource.service
const name = resource.name
let identifier = resource.identifier
@ -1430,7 +1469,7 @@ class WebBrowser extends LitElement {
if (resource.identifier == null) {
identifier = 'default'
}
if (!data.encrypt && service.endsWith("_PRIVATE")) {
const errorMsg = "Only encrypted data can go into private services"
failedPublishesIdentifiers.push({
@ -1442,36 +1481,36 @@ class WebBrowser extends LitElement {
if (data.file) {
data64 = await fileToBase64(data.file)
}
if (data.encrypt) {
try {
const encryptDataResponse = encryptDataGroup({
data64, publicKeys: data.publicKeys
})
if (encryptDataResponse) {
data64 = encryptDataResponse
}
} catch (error) {
const errorMsg = error.message || 'Upload failed due to failed encryption'
failedPublishesIdentifiers.push({
reason: errorMsg,
identifier: resource.identifier
})
continue
failedPublishesIdentifiers.push({
reason: errorMsg,
identifier: resource.identifier
})
continue
}
}
if (resource.file && !data.encrypt) {
data64 = await fileToBase64(resource.file)
}
const worker = new WebWorker()
try {
await publishData({
await publishData({
registeredName: encodeURIComponent(name),
file: data64,
service: service,
@ -1494,9 +1533,9 @@ class WebBrowser extends LitElement {
withFee: res2.userData.isWithFee === true ? true : false,
feeAmount: feeAmount
})
worker.terminate()
await new Promise((res)=> {
await new Promise((res) => {
setTimeout(() => {
res()
}, 1000);
@ -1510,7 +1549,7 @@ class WebBrowser extends LitElement {
})
continue
}
} catch (error) {
failedPublishesIdentifiers.push({
reason: "Unknown error",
@ -1518,27 +1557,27 @@ class WebBrowser extends LitElement {
})
continue
}
}
this.loader.hide()
if(failedPublishesIdentifiers.length > 0){
if (failedPublishesIdentifiers.length > 0) {
response = failedPublishesIdentifiers
const obj = {}
const errorMsg = {
unsuccessfulPublishes: failedPublishesIdentifiers
}
obj['error'] = errorMsg
response = JSON.stringify(obj)
this.loader.hide()
const errorMsg = {
unsuccessfulPublishes: failedPublishesIdentifiers
}
obj['error'] = errorMsg
response = JSON.stringify(obj)
this.loader.hide()
break
}
}
response = true
break
response = true
break
}
case actions.VOTE_ON_POLL: {
@ -1642,7 +1681,7 @@ class WebBrowser extends LitElement {
}
case actions.OPEN_NEW_TAB: {
if(!data.qortalLink){
if (!data.qortalLink) {
const obj = {}
const errorMsg = 'Please enter a qortal link - qortal://...'
obj['error'] = errorMsg
@ -1674,10 +1713,10 @@ class WebBrowser extends LitElement {
name: this.name
}
)
if (res.action === 'accept'){
if (res.action === 'accept') {
this.addAppToNotificationList(this.name)
response = true
break
response = true
break
} else {
response = false
break
@ -1694,33 +1733,33 @@ class WebBrowser extends LitElement {
try {
const id = `appNotificationList-${this.selectedAddress.address}`
const checkData = localStorage.getItem(id) ? JSON.parse(localStorage.getItem(id)) : null
if(!checkData || !checkData[this.name]) throw new Error('App not on permission list')
const appInfo = checkData[this.name]
const lastNotification = appInfo.lastNotification
const interval = appInfo.interval
if (lastNotification && interval) {
const timeDifference = Date.now() - lastNotification
if (!checkData || !checkData[this.name]) throw new Error('App not on permission list')
const appInfo = checkData[this.name]
const lastNotification = appInfo.lastNotification
const interval = appInfo.interval
if (lastNotification && interval) {
const timeDifference = Date.now() - lastNotification
if (timeDifference > interval) {
if (timeDifference > interval) {
parentEpml.request('showNotification', {
title, type: "qapp-local-notification", sound: '', url, options: { body: message, icon, badge: icon }
})
response = true
this.updateLastNotification(id, this.name)
break
} else {
throw new Error(`invalid data`)
}
} else if (!lastNotification) {
parentEpml.request('showNotification', {
title, type: "qapp-local-notification", sound: '', url, options: { body: message, icon, badge: icon }
})
response = true
this.updateLastNotification(id, this.name)
break
})
response = true
this.updateLastNotification(id)
break
} else {
throw new Error(`invalid data`)
}
} else if(!lastNotification){
parentEpml.request('showNotification', {
title, type: "qapp-local-notification", sound: '', url, options: { body: message, icon, badge: icon }
})
response = true
this.updateLastNotification(id)
break
} else {
throw new Error(`invalid data`)
}
} catch (error) {
const obj = {}
@ -2261,7 +2300,7 @@ class WebBrowser extends LitElement {
function handleResponseEvent(event) {
// Handle the data from the event, if any
const responseData = event.detail;
if(responseData && responseData.uniqueId !== uniqueId) return
if (responseData && responseData.uniqueId !== uniqueId) return
// Clean up by removing the event listener once we've received the response
window.removeEventListener('qortal-request-set-profile-data-response', handleResponseEvent);
@ -2275,8 +2314,8 @@ class WebBrowser extends LitElement {
// Set up an event listener to wait for the response
window.addEventListener('qortal-request-set-profile-data-response', handleResponseEvent);
});
if(!res.response) throw new Error('Failed to set property')
response = JSON.stringify(res.response);
if (!res.response) throw new Error('Failed to set property')
response = JSON.stringify(res.response);
} catch (error) {
const obj = {};
@ -2310,10 +2349,10 @@ class WebBrowser extends LitElement {
try {
const customEvent = new CustomEvent('open-visiting-profile', {
detail: data.name
});
window.parent.dispatchEvent(customEvent);
const customEvent = new CustomEvent('open-visiting-profile', {
detail: data.name
});
window.parent.dispatchEvent(customEvent);
response = JSON.stringify(true);
} catch (error) {
const obj = {};
@ -2345,19 +2384,19 @@ class WebBrowser extends LitElement {
}
const res3 = await showModalAndWait(
actions.GET_USER_WALLET
);
);
if (res3.action === 'accept') {
let coin = data.coin;
let userWallet = {};
let arrrAddress = "";
if (coin === "ARRR") {
arrrAddress = await parentEpml.request('apiCall', {
url: `/crosschain/arrr/walletaddress?apiKey=${this.getApiKey()}`,
method: 'POST',
body: `${window.parent.reduxStore.getState().app.selectedAddress.arrrWallet.seed58}`
if (res3.action === 'accept') {
let coin = data.coin;
let userWallet = {};
let arrrAddress = "";
if (coin === "ARRR") {
arrrAddress = await parentEpml.request('apiCall', {
url: `/crosschain/arrr/walletaddress?apiKey=${this.getApiKey()}`,
method: 'POST',
body: `${window.parent.reduxStore.getState().app.selectedAddress.arrrWallet.seed58}`
})
}
}
switch (coin) {
case 'QORT':
userWallet['address'] = window.parent.reduxStore.getState().app.selectedAddress.address
@ -2486,7 +2525,7 @@ class WebBrowser extends LitElement {
})
if (isNaN(Number(res))) {
const data = {}
const errorMsg = get("browserpage.bchange21")
const errorMsg = get("browserpage.bchange21")
data['error'] = errorMsg
response = JSON.stringify(data)
return
@ -3478,7 +3517,7 @@ class WebBrowser extends LitElement {
break
}
}
break;
break;
default:
console.log('Unhandled message: ' + JSON.stringify(data))
return
@ -3577,44 +3616,44 @@ class WebBrowser extends LitElement {
}
addAppToNotificationList(appName) {
if(!appName) throw new Error('unknown app name')
if (!appName) throw new Error('unknown app name')
const id = `appNotificationList-${this.selectedAddress.address}`
const checkData = localStorage.getItem(id) ? JSON.parse(localStorage.getItem(id)) : null
if (!checkData) {
const newData = {
[appName]: {
interval: 900000, // 15mins in milliseconds
lastNotification: null,
},
}
localStorage.setItem(id, JSON.stringify(newData))
const newData = {
[appName]: {
interval: 900000, // 15mins in milliseconds
lastNotification: null,
},
}
localStorage.setItem(id, JSON.stringify(newData))
} else {
const copyData = { ...checkData }
copyData[appName] = {
interval: 900000, // 15mins in milliseconds
lastNotification: null,
}
localStorage.setItem(id, JSON.stringify(copyData))
const copyData = { ...checkData }
copyData[appName] = {
interval: 900000, // 15mins in milliseconds
lastNotification: null,
}
localStorage.setItem(id, JSON.stringify(copyData))
}
}
}
updateLastNotification(id, appName) {
updateLastNotification(id, appName) {
const checkData = localStorage.getItem(id) ? JSON.parse(localStorage.getItem(id)) : null
if (checkData) {
const copyData = { ...checkData }
if (copyData[appName]) {
copyData[appName].lastNotification = Date.now() // Make sure to use Date.now(), not date.now()
} else {
copyData[appName] = {
interval: 900000, // 15mins in milliseconds
lastNotification: Date.now(),
const copyData = { ...checkData }
if (copyData[appName]) {
copyData[appName].lastNotification = Date.now() // Make sure to use Date.now(), not date.now()
} else {
copyData[appName] = {
interval: 900000, // 15mins in milliseconds
lastNotification: Date.now(),
}
}
}
localStorage.setItem(id, JSON.stringify(copyData))
localStorage.setItem(id, JSON.stringify(copyData))
}
}
}
renderFollowUnfollowButton() {