869 lines
25 KiB
JavaScript
869 lines
25 KiB
JavaScript
window.PageExtensions = {
|
|
template: '#page-extensions',
|
|
mixins: [window.windowMixin],
|
|
data() {
|
|
return {
|
|
extbuilderEnabled: false,
|
|
slide: 0,
|
|
fullscreen: false,
|
|
autoplay: true,
|
|
searchTerm: '',
|
|
tab: 'installed',
|
|
manageExtensionTab: 'releases',
|
|
filteredExtensions: [],
|
|
updatableExtensions: [],
|
|
showUninstallDialog: false,
|
|
showManageExtensionDialog: false,
|
|
showExtensionDetailsDialog: false,
|
|
showDropDbDialog: false,
|
|
showPayToEnableDialog: false,
|
|
showUpdateAllDialog: false,
|
|
dropDbExtensionId: '',
|
|
selectedExtension: null,
|
|
selectedImage: null,
|
|
selectedExtensionDetails: null,
|
|
selectedExtensionRepos: null,
|
|
selectedRelease: null,
|
|
uninstallAndDropDb: false,
|
|
maxStars: 5,
|
|
paylinkWebsocket: null,
|
|
searchToggle: false,
|
|
reviewsUrl: null,
|
|
reviewsDialog: {
|
|
show: false,
|
|
extension: null,
|
|
loading: false,
|
|
submitting: false,
|
|
form: {
|
|
name: '',
|
|
rating: 0,
|
|
comment: ''
|
|
},
|
|
error: null
|
|
},
|
|
reviews: [],
|
|
reviewsTable: {
|
|
loading: false,
|
|
columns: [
|
|
{
|
|
name: 'name',
|
|
align: 'left',
|
|
label: this.$t('Name'),
|
|
field: 'name',
|
|
sortable: true
|
|
},
|
|
{
|
|
name: 'comment',
|
|
align: 'left',
|
|
label: this.$t('Comment'),
|
|
field: 'comment'
|
|
},
|
|
{
|
|
name: 'created_at',
|
|
align: 'left',
|
|
label: this.$t('Date'),
|
|
field: 'created_at'
|
|
},
|
|
{
|
|
name: 'rating',
|
|
align: 'right',
|
|
label: 'Rating',
|
|
field: 'rating'
|
|
}
|
|
],
|
|
pagination: {
|
|
rowsPerPage: 5,
|
|
sortBy: 'created_at',
|
|
descending: true,
|
|
page: 1
|
|
}
|
|
},
|
|
paymentDialog: {
|
|
show: false,
|
|
invoice: '',
|
|
hash: ''
|
|
}
|
|
}
|
|
},
|
|
watch: {
|
|
searchTerm(term) {
|
|
this.filterExtensions(term, this.tab)
|
|
},
|
|
tab(val) {
|
|
this.filterExtensions(this.searchTerm, val)
|
|
}
|
|
},
|
|
methods: {
|
|
filterExtensions(term, tab) {
|
|
// Filter the extensions list
|
|
function extensionNameContains(searchTerm) {
|
|
return function (extension) {
|
|
return (
|
|
extension.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
|
extension.shortDescription
|
|
?.toLowerCase()
|
|
.includes(searchTerm.toLowerCase())
|
|
)
|
|
}
|
|
}
|
|
|
|
this.filteredExtensions = this.extensions
|
|
.filter(e => (tab === 'all' ? !e.isInstalled : true))
|
|
.filter(e => (tab === 'installed' ? e.isInstalled : true))
|
|
.filter(e =>
|
|
tab === 'installed' ? (e.isActive ? true : !!this.g.user.admin) : true
|
|
)
|
|
.filter(e => (tab === 'featured' ? e.isFeatured : true))
|
|
.filter(extensionNameContains(term))
|
|
.map(e => ({
|
|
...e,
|
|
details_link:
|
|
e.installedRelease?.details_link || e.latestRelease?.details_link
|
|
}))
|
|
},
|
|
|
|
async installExtension(release) {
|
|
// no longer required to check if the invoice was paid
|
|
// the install logic has been triggered one way or another
|
|
this.unsubscribeFromPaylinkWs()
|
|
|
|
this.selectedExtension.inProgress = true
|
|
this.showManageExtensionDialog = false
|
|
release.payment_hash =
|
|
release.payment_hash || this.getPaylinkHash(release.pay_link)
|
|
|
|
LNbits.api
|
|
.request('POST', `/api/v1/extension`, this.g.user.wallets[0].adminkey, {
|
|
ext_id: this.selectedExtension.id,
|
|
archive: release.archive,
|
|
source_repo: release.source_repo,
|
|
payment_hash: release.payment_hash,
|
|
version: release.version
|
|
})
|
|
.then(response => {
|
|
this.selectedExtension.inProgress = false
|
|
const extension = this.extensions.find(
|
|
ext => ext.id === this.selectedExtension.id
|
|
)
|
|
extension.isAvailable = true
|
|
extension.isInstalled = true
|
|
extension.installedRelease = release
|
|
this.toggleExtension(extension)
|
|
extension.inProgress = false
|
|
this.selectedExtension = extension
|
|
this.extensions = this.extensions.concat([])
|
|
this.tab = 'installed'
|
|
})
|
|
.catch(err => {
|
|
console.warn(err)
|
|
this.selectedExtension.inProgress = false
|
|
LNbits.utils.notifyApiError(err)
|
|
})
|
|
},
|
|
async uninstallExtension() {
|
|
this.showManageExtensionDialog = false
|
|
this.showUninstallDialog = false
|
|
this.selectedExtension.inProgress = true
|
|
LNbits.api
|
|
.request(
|
|
'DELETE',
|
|
`/api/v1/extension/${this.selectedExtension.id}`,
|
|
this.g.user.wallets[0].adminkey
|
|
)
|
|
.then(response => {
|
|
const extension = this.extensions.find(
|
|
ext => ext.id === this.selectedExtension.id
|
|
)
|
|
extension.isAvailable = false
|
|
extension.isInstalled = false
|
|
extension.inProgress = false
|
|
extension.installedRelease = null
|
|
this.filteredExtensions = this.filteredExtensions.filter(
|
|
ext => ext.id !== extension.id
|
|
)
|
|
Quasar.Notify.create({
|
|
type: 'positive',
|
|
message: 'Extension uninstalled!'
|
|
})
|
|
if (this.uninstallAndDropDb) {
|
|
this.showDropDb()
|
|
}
|
|
})
|
|
.catch(err => {
|
|
LNbits.utils.notifyApiError(err)
|
|
extension.inProgress = false
|
|
})
|
|
},
|
|
async dropExtensionDb() {
|
|
const extension = this.selectedExtension
|
|
this.showManageExtensionDialog = false
|
|
this.showDropDbDialog = false
|
|
this.dropDbExtensionId = ''
|
|
extension.inProgress = true
|
|
LNbits.api
|
|
.request(
|
|
'DELETE',
|
|
`/api/v1/extension/${extension.id}/db`,
|
|
this.g.user.wallets[0].adminkey
|
|
)
|
|
.then(response => {
|
|
extension.installedRelease = null
|
|
extension.inProgress = false
|
|
extension.hasDatabaseTables = false
|
|
Quasar.Notify.create({
|
|
type: 'positive',
|
|
message: 'Extension DB deleted!'
|
|
})
|
|
})
|
|
.catch(err => {
|
|
LNbits.utils.notifyApiError(err)
|
|
extension.inProgress = false
|
|
})
|
|
},
|
|
toggleExtension(extension) {
|
|
const action = extension.isActive ? 'activate' : 'deactivate'
|
|
LNbits.api
|
|
.request(
|
|
'PUT',
|
|
`/api/v1/extension/${extension.id}/${action}`,
|
|
this.g.user.wallets[0].adminkey
|
|
)
|
|
.then(response => {
|
|
Quasar.Notify.create({
|
|
timeout: 2000,
|
|
type: 'positive',
|
|
message: `Extension '${extension.id}' ${action}d!`
|
|
})
|
|
})
|
|
.catch(err => {
|
|
LNbits.utils.notifyApiError(err)
|
|
extension.isActive = false
|
|
extension.inProgress = false
|
|
})
|
|
},
|
|
async enableExtensionForUser(extension) {
|
|
if (extension.isPaymentRequired) {
|
|
this.showPayToEnable(extension)
|
|
return
|
|
}
|
|
this.enableExtension(extension)
|
|
},
|
|
async enableExtension(extension) {
|
|
LNbits.api
|
|
.request(
|
|
'PUT',
|
|
`/api/v1/extension/${extension.id}/enable`,
|
|
this.g.user.wallets[0].adminkey
|
|
)
|
|
.then(response => {
|
|
this.g.user.extensions = this.g.user.extensions.concat([extension.id])
|
|
Quasar.Notify.create({
|
|
type: 'positive',
|
|
message: 'Extension enabled!'
|
|
})
|
|
})
|
|
.catch(err => {
|
|
console.warn(err)
|
|
LNbits.utils.notifyApiError(err)
|
|
})
|
|
},
|
|
disableExtension(extension) {
|
|
LNbits.api
|
|
.request(
|
|
'PUT',
|
|
`/api/v1/extension/${extension.id}/disable`,
|
|
this.g.user.wallets[0].adminkey
|
|
)
|
|
.then(response => {
|
|
this.g.user.extensions = this.g.user.extensions.filter(
|
|
ext => ext !== extension.id
|
|
)
|
|
Quasar.Notify.create({
|
|
type: 'positive',
|
|
message: 'Extension disabled!'
|
|
})
|
|
})
|
|
.catch(err => {
|
|
console.warn(error)
|
|
LNbits.utils.notifyApiError(err)
|
|
})
|
|
},
|
|
showPayToEnable(extension) {
|
|
this.selectedExtension = extension
|
|
this.selectedExtension.payToEnable.paidAmount =
|
|
extension.payToEnable.amount
|
|
this.selectedExtension.payToEnable.showQRCode = false
|
|
this.showPayToEnableDialog = true
|
|
},
|
|
updatePayToInstallData(extension) {
|
|
LNbits.api
|
|
.request(
|
|
'PUT',
|
|
`/api/v1/extension/${extension.id}/sell`,
|
|
this.g.user.wallets[0].adminkey,
|
|
{
|
|
required: extension.payToEnable.required,
|
|
amount: extension.payToEnable.amount,
|
|
wallet: extension.payToEnable.wallet
|
|
}
|
|
)
|
|
.then(response => {
|
|
Quasar.Notify.create({
|
|
type: 'positive',
|
|
message: 'Payment info updated!'
|
|
})
|
|
this.showManageExtensionDialog = false
|
|
})
|
|
.catch(err => {
|
|
LNbits.utils.notifyApiError(err)
|
|
extension.inProgress = false
|
|
})
|
|
},
|
|
|
|
showUninstall() {
|
|
this.showManageExtensionDialog = false
|
|
this.showUninstallDialog = true
|
|
this.uninstallAndDropDb = false
|
|
},
|
|
|
|
showDropDb() {
|
|
this.showDropDbDialog = true
|
|
},
|
|
|
|
async showManageExtension(extension) {
|
|
this.selectedExtension = extension
|
|
this.selectedRelease = null
|
|
this.selectedExtensionRepos = null
|
|
this.manageExtensionTab = 'releases'
|
|
this.showManageExtensionDialog = true
|
|
|
|
try {
|
|
const {data} = await LNbits.api.request(
|
|
'GET',
|
|
`/api/v1/extension/${extension.id}/releases`
|
|
)
|
|
|
|
this.selectedExtensionRepos = data.reduce((repos, release) => {
|
|
repos[release.source_repo] = repos[release.source_repo] || {
|
|
releases: [],
|
|
isInstalled: false,
|
|
repo: release.repo
|
|
}
|
|
release.inProgress = false
|
|
release.error = null
|
|
release.loaded = false
|
|
release.isInstalled = this.isInstalledVersion(
|
|
this.selectedExtension,
|
|
release
|
|
)
|
|
if (release.isInstalled) {
|
|
repos[release.source_repo].isInstalled = true
|
|
}
|
|
if (release.pay_link) {
|
|
release.requiresPayment = true
|
|
release.paidAmount = release.cost_sats
|
|
release.payment_hash = this.getPaylinkHash(release.pay_link)
|
|
}
|
|
|
|
repos[release.source_repo].releases.push(release)
|
|
return repos
|
|
}, {})
|
|
} catch (error) {
|
|
LNbits.utils.notifyApiError(error)
|
|
extension.inProgress = false
|
|
}
|
|
},
|
|
|
|
async showExtensionDetails(extId, detailsLink) {
|
|
if (!detailsLink) {
|
|
return
|
|
}
|
|
// keep a reference to the extension so we can show rating stats
|
|
this.selectedExtension =
|
|
this.extensions.find(ext => ext.id === extId) || this.selectedExtension
|
|
this.selectedExtensionDetails = null
|
|
this.showExtensionDetailsDialog = true
|
|
this.slide = 0
|
|
this.fullscreen = false
|
|
|
|
try {
|
|
const {data} = await LNbits.api.request(
|
|
'GET',
|
|
`/api/v1/extension/${extId}/details?details_link=${detailsLink}`
|
|
)
|
|
|
|
this.selectedExtensionDetails = data
|
|
this.selectedExtensionDetails.description_md =
|
|
LNbits.utils.convertMarkdown(data.description_md)
|
|
} catch (error) {
|
|
console.warn(error)
|
|
}
|
|
},
|
|
async payAndInstall(release) {
|
|
try {
|
|
this.selectedExtension.inProgress = true
|
|
this.showManageExtensionDialog = false
|
|
const paymentInfo = await this.requestPaymentForInstall(
|
|
this.selectedExtension.id,
|
|
release
|
|
)
|
|
this.rememberPaylinkHash(release.pay_link, paymentInfo.payment_hash)
|
|
const wallet = this.g.user.wallets.find(w => w.id === release.wallet)
|
|
const {data} = await LNbits.api.payInvoice(
|
|
wallet,
|
|
paymentInfo.payment_request
|
|
)
|
|
|
|
release.payment_hash = data.payment_hash
|
|
|
|
await this.installExtension(release)
|
|
} catch (err) {
|
|
console.warn(err)
|
|
LNbits.utils.notifyApiError(err)
|
|
} finally {
|
|
this.selectedExtension.inProgress = false
|
|
}
|
|
},
|
|
async payAndEnable(extension) {
|
|
try {
|
|
const paymentInfo = await this.requestPaymentForEnable(
|
|
extension.id,
|
|
extension.payToEnable.paidAmount
|
|
)
|
|
|
|
const wallet = this.g.user.wallets.find(
|
|
w => w.id === extension.payToEnable.paymentWallet
|
|
)
|
|
const {data} = await LNbits.api.payInvoice(
|
|
wallet,
|
|
paymentInfo.payment_request
|
|
)
|
|
this.enableExtension(extension)
|
|
this.showPayToEnableDialog = false
|
|
} catch (err) {
|
|
console.warn(err)
|
|
LNbits.utils.notifyApiError(err)
|
|
}
|
|
},
|
|
async showInstallQRCode(release) {
|
|
this.selectedRelease = release
|
|
|
|
try {
|
|
const data = await this.requestPaymentForInstall(
|
|
this.selectedExtension.id,
|
|
release
|
|
)
|
|
|
|
this.selectedRelease.paymentRequest = data.payment_request
|
|
this.selectedRelease.payment_hash = data.payment_hash
|
|
this.selectedRelease = _.clone(this.selectedRelease)
|
|
this.rememberPaylinkHash(
|
|
this.selectedRelease.pay_link,
|
|
this.selectedRelease.payment_hash
|
|
)
|
|
|
|
this.subscribeToPaylinkWs(
|
|
this.selectedRelease.pay_link,
|
|
data.payment_hash
|
|
)
|
|
} catch (err) {
|
|
console.warn(err)
|
|
LNbits.utils.notifyApiError(err)
|
|
}
|
|
},
|
|
|
|
async showEnableQRCode(extension) {
|
|
try {
|
|
extension.payToEnable.showQRCode = true
|
|
this.selectedExtension = _.clone(extension)
|
|
|
|
const data = await this.requestPaymentForEnable(
|
|
extension.id,
|
|
extension.payToEnable.paidAmount
|
|
)
|
|
extension.payToEnable.paymentRequest = data.payment_request
|
|
this.selectedExtension = _.clone(extension)
|
|
|
|
const url = new URL(window.location)
|
|
url.protocol = url.protocol === 'https:' ? 'wss' : 'ws'
|
|
url.pathname = `/api/v1/ws/${data.payment_hash}`
|
|
const ws = new WebSocket(url)
|
|
ws.addEventListener('message', async ({data}) => {
|
|
const payment = JSON.parse(data)
|
|
if (payment.pending === false) {
|
|
Quasar.Notify.create({
|
|
type: 'positive',
|
|
message: 'Invoice Paid!'
|
|
})
|
|
|
|
this.enableExtension(extension)
|
|
ws.close()
|
|
}
|
|
})
|
|
} catch (err) {
|
|
console.warn(err)
|
|
LNbits.utils.notifyApiError(err)
|
|
}
|
|
},
|
|
|
|
async requestPaymentForInstall(extId, release) {
|
|
const {data} = await LNbits.api.request(
|
|
'PUT',
|
|
`/api/v1/extension/${extId}/invoice/install`,
|
|
null,
|
|
{
|
|
ext_id: extId,
|
|
archive: release.archive,
|
|
source_repo: release.source_repo,
|
|
cost_sats: release.paidAmount,
|
|
version: release.version
|
|
}
|
|
)
|
|
return data
|
|
},
|
|
|
|
async requestPaymentForEnable(extId, amount) {
|
|
const {data} = await LNbits.api.request(
|
|
'PUT',
|
|
`/api/v1/extension/${extId}/invoice/enable`,
|
|
null,
|
|
{
|
|
amount
|
|
}
|
|
)
|
|
return data
|
|
},
|
|
|
|
clearHangingInvoice(release) {
|
|
this.forgetPaylinkHash(release.pay_link)
|
|
release.payment_hash = null
|
|
},
|
|
|
|
rememberPaylinkHash(pay_link, payment_hash) {
|
|
this.$q.localStorage.set(
|
|
`lnbits.extensions.paylink.${pay_link}`,
|
|
payment_hash
|
|
)
|
|
},
|
|
getPaylinkHash(pay_link) {
|
|
return this.$q.localStorage.getItem(
|
|
`lnbits.extensions.paylink.${pay_link}`
|
|
)
|
|
},
|
|
forgetPaylinkHash(pay_link) {
|
|
this.$q.localStorage.remove(`lnbits.extensions.paylink.${pay_link}`)
|
|
},
|
|
subscribeToPaylinkWs(pay_link, payment_hash) {
|
|
const url = new URL(`${pay_link}/${payment_hash}`)
|
|
url.protocol = url.protocol === 'https:' ? 'wss' : 'ws'
|
|
this.paylinkWebsocket = new WebSocket(url)
|
|
this.paylinkWebsocket.addEventListener('message', async ({data}) => {
|
|
const resp = JSON.parse(data)
|
|
if (resp.paid) {
|
|
Quasar.Notify.create({
|
|
type: 'positive',
|
|
message: 'Invoice Paid!'
|
|
})
|
|
this.installExtension(this.selectedRelease)
|
|
} else {
|
|
Quasar.Notify.create({
|
|
type: 'warning',
|
|
message: 'Invoice tracking lost!'
|
|
})
|
|
}
|
|
})
|
|
},
|
|
unsubscribeFromPaylinkWs() {
|
|
try {
|
|
this.paylinkWebsocket && this.paylinkWebsocket.close()
|
|
} catch (error) {
|
|
console.warn(error)
|
|
}
|
|
},
|
|
|
|
hasNewVersion(extension) {
|
|
if (extension.installedRelease && extension.latestRelease) {
|
|
return (
|
|
extension.installedRelease.version !== extension.latestRelease.version
|
|
)
|
|
}
|
|
},
|
|
isInstalledVersion(extension, release) {
|
|
if (extension.installedRelease) {
|
|
return (
|
|
extension.installedRelease.source_repo === release.source_repo &&
|
|
extension.installedRelease.version === release.version
|
|
)
|
|
}
|
|
},
|
|
getReleaseIcon(release) {
|
|
if (!release.is_version_compatible) return 'block'
|
|
if (release.isInstalled) return 'download_done'
|
|
|
|
return 'download'
|
|
},
|
|
getReleaseIconColor(release) {
|
|
if (!release.is_version_compatible) return 'text-red'
|
|
if (release.isInstalled) return 'text-green'
|
|
|
|
return ''
|
|
},
|
|
async getGitHubReleaseDetails(release) {
|
|
if (!release.is_github_release || release.loaded) {
|
|
return
|
|
}
|
|
const [org, repo] = release.source_repo.split('/')
|
|
release.inProgress = true
|
|
try {
|
|
const {data} = await LNbits.api.request(
|
|
'GET',
|
|
`/api/v1/extension/release/${org}/${repo}/${release.version}`
|
|
)
|
|
release.loaded = true
|
|
release.is_version_compatible = data.is_version_compatible
|
|
release.min_lnbits_version = data.min_lnbits_version
|
|
release.warning = data.warning
|
|
} catch (error) {
|
|
console.warn(error)
|
|
release.error = error
|
|
LNbits.utils.notifyApiError(error)
|
|
} finally {
|
|
release.inProgress = false
|
|
}
|
|
},
|
|
async selectAllUpdatableExtensionss() {
|
|
this.updatableExtensions.forEach(e => (e.selectedForUpdate = true))
|
|
},
|
|
async updateSelectedExtensions() {
|
|
let count = 0
|
|
for (const ext of this.updatableExtensions) {
|
|
try {
|
|
if (!ext.selectedForUpdate) {
|
|
continue
|
|
}
|
|
ext.inProgress = true
|
|
await LNbits.api.request('POST', `/api/v1/extension`, null, {
|
|
ext_id: ext.id,
|
|
archive: ext.latestRelease.archive,
|
|
source_repo: ext.latestRelease.source_repo,
|
|
payment_hash: ext.latestRelease.payment_hash,
|
|
version: ext.latestRelease.version
|
|
})
|
|
count++
|
|
ext.isAvailable = true
|
|
ext.isInstalled = true
|
|
ext.isUpgraded = true
|
|
ext.inProgress = false
|
|
ext.installedRelease = ext.latestRelease
|
|
ext.isActive = true
|
|
this.toggleExtension(ext)
|
|
} catch (err) {
|
|
console.warn(err)
|
|
Quasar.Notify.create({
|
|
type: 'negative',
|
|
message: `Failed to update ${ext.id}!`
|
|
})
|
|
} finally {
|
|
ext.inProgress = false
|
|
}
|
|
}
|
|
Quasar.Notify.create({
|
|
type: count ? 'positive' : 'warning',
|
|
message: `${count ? count : 'No'} extensions updated!`
|
|
})
|
|
this.showUpdateAllDialog = false
|
|
},
|
|
formatAvg(raw) {
|
|
const val = Number(raw || 0)
|
|
return Math.round((val / 2 / 100) * 2) / 2
|
|
},
|
|
|
|
async loadReviewStats() {
|
|
if (!this.reviewsUrl) {
|
|
console.info('Extension reviews are not configured')
|
|
return
|
|
}
|
|
try {
|
|
const {data} = await LNbits.api.request(
|
|
'GET',
|
|
`/api/v1/extension/reviews/tags`
|
|
)
|
|
const map = {}
|
|
data.forEach(stat => {
|
|
map[stat.tag] = stat
|
|
})
|
|
this.extensions.forEach(ext => {
|
|
ext.reviewStats = map[ext.id] || null
|
|
})
|
|
this.filterExtensions(this.searchTerm, this.tab)
|
|
} catch (error) {
|
|
console.warn(error)
|
|
}
|
|
},
|
|
async openReviews(extension) {
|
|
const targetExtension =
|
|
extension ||
|
|
(this.selectedExtensionDetails
|
|
? this.extensions.find(e => e.id === this.selectedExtensionDetails.id)
|
|
: null)
|
|
if (!targetExtension) {
|
|
return
|
|
}
|
|
if (!this.reviewsUrl) {
|
|
Quasar.Notify.create({
|
|
type: 'warning',
|
|
message: this.$t('reviews_url_not_configured')
|
|
})
|
|
return
|
|
}
|
|
this.reviewsDialog.extension = targetExtension
|
|
this.selectedExtension = extension
|
|
this.reviewsDialog.show = true
|
|
await this.getTagReviews()
|
|
},
|
|
async getTagReviews(props) {
|
|
if (!this.reviewsUrl) {
|
|
Quasar.Notify.create({
|
|
type: 'warning',
|
|
message: this.$t('reviews_url_not_configured')
|
|
})
|
|
return
|
|
}
|
|
try {
|
|
this.reviewsTable.loading = true
|
|
const params = LNbits.utils.prepareFilterQuery(this.reviewsTable, props)
|
|
const {data} = await LNbits.api.request(
|
|
'GET',
|
|
`/api/v1/extension/reviews/${this.selectedExtension.id}?${params}`
|
|
)
|
|
this.reviews = data.data
|
|
this.reviewsTable.pagination.rowsNumber = data.total
|
|
} catch (e) {
|
|
LNbits.utils.notifyApiError(e)
|
|
} finally {
|
|
this.reviewsTable.loading = false
|
|
}
|
|
},
|
|
|
|
formatReviewDate(val) {
|
|
if (!val) return ''
|
|
const numeric = Number(val)
|
|
if (!Number.isNaN(numeric)) {
|
|
return this.utils.formatTimestamp(numeric)
|
|
}
|
|
return this.utils.formatDate(val)
|
|
},
|
|
async submitReview() {
|
|
if (!this.reviewsDialog.extension || !this.reviewsUrl) {
|
|
return
|
|
}
|
|
this.reviewsDialog.submitting = true
|
|
try {
|
|
const payload = {
|
|
tag: this.reviewsDialog.extension.id,
|
|
name: this.reviewsDialog.form.name,
|
|
rating: this.reviewsDialog.form.rating * 100,
|
|
comment: this.reviewsDialog.form.comment
|
|
}
|
|
const {data} = await LNbits.api.request(
|
|
'PUT',
|
|
`/api/v1/extension/reviews`,
|
|
null,
|
|
payload
|
|
)
|
|
if (data.payment_request) {
|
|
this.openInvoiceDialog(data.payment_request, data.payment_hash)
|
|
} else {
|
|
Quasar.Notify.create({
|
|
type: 'positive',
|
|
message: 'Review submitted'
|
|
})
|
|
this.resetReviewForm()
|
|
await this.getTagReviews()
|
|
await this.loadReviewStats()
|
|
}
|
|
} catch (error) {
|
|
LNbits.utils.notifyApiError(error)
|
|
} finally {
|
|
this.reviewsDialog.submitting = false
|
|
}
|
|
},
|
|
openInvoiceDialog(invoice, hash) {
|
|
this.paymentDialog.invoice = invoice
|
|
this.paymentDialog.hash = hash
|
|
this.paymentDialog.show = true
|
|
this.listenForPayment(hash)
|
|
},
|
|
resetReviewForm() {
|
|
this.reviewsDialog.form = {
|
|
name: '',
|
|
rating: 0,
|
|
comment: ''
|
|
}
|
|
this.paymentDialog = {
|
|
show: false,
|
|
invoice: '',
|
|
hash: ''
|
|
}
|
|
},
|
|
listenForPayment(hash) {
|
|
try {
|
|
const base = new URL(this.reviewsUrl)
|
|
base.protocol = base.protocol === 'https:' ? 'wss:' : 'ws:'
|
|
base.pathname = `/api/v1/ws/${hash}`
|
|
const ws = new WebSocket(base)
|
|
ws.addEventListener('message', async () => {
|
|
Quasar.Notify.create({
|
|
type: 'positive',
|
|
message: this.$t('reviews_invoice_paid')
|
|
})
|
|
this.paymentDialog.show = false
|
|
this.resetReviewForm()
|
|
setTimeout(async () => {
|
|
await this.getTagReviews()
|
|
}, 1000)
|
|
|
|
await this.loadReviewStats()
|
|
ws.close()
|
|
})
|
|
} catch (error) {
|
|
console.warn(error)
|
|
}
|
|
},
|
|
async fetchAllExtensions() {
|
|
try {
|
|
const {data} = await LNbits.api.request('GET', `/api/v1/extension/all`)
|
|
return data
|
|
} catch (error) {
|
|
console.warn(error)
|
|
LNbits.utils.notifyApiError(error)
|
|
return []
|
|
}
|
|
}
|
|
},
|
|
async created() {
|
|
this.extensions = await this.fetchAllExtensions()
|
|
this.extbuilderEnabled = this.g.user.admin || this.LNBITS_EXT_BUILDER
|
|
this.reviewsUrl = this.LNBITS_EXTENSIONS_REVIEWS_URL
|
|
|
|
if (this.g.user.extensions.length === 0) {
|
|
this.tab = 'all'
|
|
}
|
|
|
|
const extId = window.location.hash.replace('#', '')
|
|
const ext = this.extensions.find(ext => ext.id === extId)
|
|
|
|
if (ext) {
|
|
this.searchTerm = ext.id
|
|
if (ext.isInstalled) this.tab = 'installed'
|
|
}
|
|
this.updatableExtensions = this.extensions.filter(ext =>
|
|
this.hasNewVersion(ext)
|
|
)
|
|
|
|
await this.loadReviewStats()
|
|
|
|
this.filterExtensions(this.searchTerm, this.tab)
|
|
}
|
|
}
|