[feat] update multiple extensions from the UI (#2833)
* feat: add `Update` button * feat: select all updatable extensions * feat: dialog improvements * fix: bad logging and permissions
This commit is contained in:
parent
25d59e4142
commit
b81b30c896
3 changed files with 135 additions and 8 deletions
|
|
@ -35,6 +35,17 @@
|
||||||
v-if="!g.user.admin && tab != 'installed'"
|
v-if="!g.user.admin && tab != 'installed'"
|
||||||
v-text="$t('only_admins_can_install')"
|
v-text="$t('only_admins_can_install')"
|
||||||
></i>
|
></i>
|
||||||
|
<q-space></q-space>
|
||||||
|
<q-badge
|
||||||
|
v-if="g.user.admin && updatableExtensions?.length"
|
||||||
|
@click="showUpdateAllDialog = true"
|
||||||
|
color="primary"
|
||||||
|
class="float-right q-pa-sm q-mr-md cursor-pointer"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
v-text="$t('new_version') + ` (${updatableExtensions?.length})`"
|
||||||
|
></span>
|
||||||
|
</q-badge>
|
||||||
</q-tabs>
|
</q-tabs>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -229,7 +240,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<q-dialog v-model="showUninstallDialog">
|
<q-dialog v-model="showUninstallDialog" position="top">
|
||||||
<q-card class="q-pa-lg">
|
<q-card class="q-pa-lg">
|
||||||
<h6 class="q-my-md text-primary" v-text="$t('warning')"></h6>
|
<h6 class="q-my-md text-primary" v-text="$t('warning')"></h6>
|
||||||
<p>
|
<p>
|
||||||
|
|
@ -266,7 +277,7 @@
|
||||||
</q-card>
|
</q-card>
|
||||||
</q-dialog>
|
</q-dialog>
|
||||||
|
|
||||||
<q-dialog v-model="showDropDbDialog">
|
<q-dialog v-model="showDropDbDialog" position="top">
|
||||||
<q-card v-if="selectedExtension" class="q-pa-lg">
|
<q-card v-if="selectedExtension" class="q-pa-lg">
|
||||||
<h6 class="q-my-md text-primary" v-text="$t('warning')"></h6>
|
<h6 class="q-my-md text-primary" v-text="$t('warning')"></h6>
|
||||||
<p><span v-text="$t('extension_db_drop_warning')"></span><br /></p>
|
<p><span v-text="$t('extension_db_drop_warning')"></span><br /></p>
|
||||||
|
|
@ -296,7 +307,7 @@
|
||||||
</q-card>
|
</q-card>
|
||||||
</q-dialog>
|
</q-dialog>
|
||||||
|
|
||||||
<q-dialog v-model="showManageExtensionDialog">
|
<q-dialog v-model="showManageExtensionDialog" position="top">
|
||||||
<q-card v-if="selectedRelease" class="q-pa-lg lnbits__dialog-card">
|
<q-card v-if="selectedRelease" class="q-pa-lg lnbits__dialog-card">
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
<div v-if="selectedRelease.paymentRequest">
|
<div v-if="selectedRelease.paymentRequest">
|
||||||
|
|
@ -632,7 +643,7 @@
|
||||||
</q-card>
|
</q-card>
|
||||||
</q-dialog>
|
</q-dialog>
|
||||||
|
|
||||||
<q-dialog v-model="showPayToEnableDialog">
|
<q-dialog v-model="showPayToEnableDialog" position="top">
|
||||||
<q-card v-if="selectedExtension" class="q-pa-md">
|
<q-card v-if="selectedExtension" class="q-pa-md">
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
<p>
|
<p>
|
||||||
|
|
@ -738,7 +749,7 @@
|
||||||
</q-card>
|
</q-card>
|
||||||
</q-dialog>
|
</q-dialog>
|
||||||
|
|
||||||
<q-dialog v-model="showExtensionDetailsDialog">
|
<q-dialog v-model="showExtensionDetailsDialog" position="top">
|
||||||
<q-card
|
<q-card
|
||||||
v-if="selectedExtensionDetails"
|
v-if="selectedExtensionDetails"
|
||||||
class="q-pa-sm"
|
class="q-pa-sm"
|
||||||
|
|
@ -884,6 +895,63 @@
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
</q-card>
|
</q-card>
|
||||||
</q-dialog>
|
</q-dialog>
|
||||||
|
<q-dialog v-model="showUpdateAllDialog" position="top">
|
||||||
|
<q-card class="q-pa-md q-pt-md lnbits__dialog-card">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<h6 class="q-my-md" v-text="$t('update')"></h6>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="updatableExtensions?.length > 1" class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<q-btn
|
||||||
|
outline
|
||||||
|
color="grey"
|
||||||
|
@click="selectAllUpdatableExtensionss()"
|
||||||
|
v-text="$t('select_all')"
|
||||||
|
></q-btn>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<q-virtual-scroll :items="updatableExtensions" style="max-height: 400px">
|
||||||
|
<template v-slot="{ item, index }">
|
||||||
|
<div class="row">
|
||||||
|
<div class="q-col">
|
||||||
|
<q-checkbox
|
||||||
|
v-model="item.selectedForUpdate"
|
||||||
|
:disable="item.isUpgraded"
|
||||||
|
value="false"
|
||||||
|
:label="item.name + ` (v${item.latestRelease?.version})`"
|
||||||
|
>
|
||||||
|
<q-spinner
|
||||||
|
v-if="item.inProgress"
|
||||||
|
color="primary"
|
||||||
|
size="1.5em"
|
||||||
|
class="q-ml-md"
|
||||||
|
></q-spinner>
|
||||||
|
</q-checkbox>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</q-virtual-scroll>
|
||||||
|
<div class="row q-mt-lg">
|
||||||
|
<q-btn
|
||||||
|
@click="updateSelectedExtensions()"
|
||||||
|
outline
|
||||||
|
color="grey"
|
||||||
|
v-text="$t('update')"
|
||||||
|
></q-btn>
|
||||||
|
|
||||||
|
<q-btn
|
||||||
|
v-close-popup
|
||||||
|
flat
|
||||||
|
color="grey"
|
||||||
|
class="q-ml-auto"
|
||||||
|
v-text="$t('cancel')"
|
||||||
|
></q-btn>
|
||||||
|
</div>
|
||||||
|
</q-card>
|
||||||
|
</q-dialog>
|
||||||
{% endblock %} {% block scripts %} {{ window_vars(user) }}
|
{% endblock %} {% block scripts %} {{ window_vars(user) }}
|
||||||
<script>
|
<script>
|
||||||
window.app = Vue.createApp({
|
window.app = Vue.createApp({
|
||||||
|
|
@ -898,11 +966,13 @@
|
||||||
tab: 'all',
|
tab: 'all',
|
||||||
manageExtensionTab: 'releases',
|
manageExtensionTab: 'releases',
|
||||||
filteredExtensions: null,
|
filteredExtensions: null,
|
||||||
|
updatableExtensions: [],
|
||||||
showUninstallDialog: false,
|
showUninstallDialog: false,
|
||||||
showManageExtensionDialog: false,
|
showManageExtensionDialog: false,
|
||||||
showExtensionDetailsDialog: false,
|
showExtensionDetailsDialog: false,
|
||||||
showDropDbDialog: false,
|
showDropDbDialog: false,
|
||||||
showPayToEnableDialog: false,
|
showPayToEnableDialog: false,
|
||||||
|
showUpdateAllDialog: false,
|
||||||
dropDbExtensionId: '',
|
dropDbExtensionId: '',
|
||||||
selectedExtension: null,
|
selectedExtension: null,
|
||||||
selectedImage: null,
|
selectedImage: null,
|
||||||
|
|
@ -1074,6 +1144,7 @@
|
||||||
)
|
)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
Quasar.Notify.create({
|
Quasar.Notify.create({
|
||||||
|
timeout: 2000,
|
||||||
type: 'positive',
|
type: 'positive',
|
||||||
message: `Extension '${extension.id}' ${action}d!`
|
message: `Extension '${extension.id}' ${action}d!`
|
||||||
})
|
})
|
||||||
|
|
@ -1476,12 +1547,63 @@
|
||||||
} finally {
|
} finally {
|
||||||
release.inProgress = false
|
release.inProgress = false
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
selectAllUpdatableExtensionss: async function () {
|
||||||
|
this.updatableExtensions.forEach(e => (e.selectedForUpdate = true))
|
||||||
|
},
|
||||||
|
updateSelectedExtensions: async function () {
|
||||||
|
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`,
|
||||||
|
this.g.user.wallets[0].adminkey,
|
||||||
|
{
|
||||||
|
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
|
||||||
|
this.toggleExtension(ext)
|
||||||
|
} catch (err) {
|
||||||
|
console.warn(err)
|
||||||
|
Quasar.Notify.create({
|
||||||
|
type: 'negative',
|
||||||
|
message: `Failed to update ${ext.code}!`
|
||||||
|
})
|
||||||
|
} finally {
|
||||||
|
ext.inProgress = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Quasar.Notify.create({
|
||||||
|
type: 'positive',
|
||||||
|
message: `${count} extensions updated!`
|
||||||
|
})
|
||||||
|
this.showUpdateAllDialog = false
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.reload()
|
||||||
|
}, 2000)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
created: function () {
|
created: function () {
|
||||||
this.extensions = JSON.parse('{{extensions | tojson | safe}}').map(e => ({
|
this.extensions = JSON.parse('{{extensions | tojson | safe}}').map(e => ({
|
||||||
...e,
|
...e,
|
||||||
inProgress: false
|
inProgress: false,
|
||||||
|
selectedForUpdate: false
|
||||||
}))
|
}))
|
||||||
this.filteredExtensions = this.extensions.concat([])
|
this.filteredExtensions = this.extensions.concat([])
|
||||||
for (let i = 0; i < this.filteredExtensions.length; i++) {
|
for (let i = 0; i < this.filteredExtensions.length; i++) {
|
||||||
|
|
@ -1493,6 +1615,9 @@
|
||||||
if (window.user) {
|
if (window.user) {
|
||||||
this.user = LNbits.map.user(window.user)
|
this.user = LNbits.map.user(window.user)
|
||||||
}
|
}
|
||||||
|
this.updatableExtensions = this.extensions.filter(ext =>
|
||||||
|
this.hasNewVersion(ext)
|
||||||
|
)
|
||||||
},
|
},
|
||||||
mixins: [windowMixin]
|
mixins: [windowMixin]
|
||||||
})
|
})
|
||||||
|
|
|
||||||
2
lnbits/static/bundle.min.js
vendored
2
lnbits/static/bundle.min.js
vendored
File diff suppressed because one or more lines are too long
|
|
@ -156,6 +156,7 @@ window.localisation.en = {
|
||||||
expiry: 'Expiry',
|
expiry: 'Expiry',
|
||||||
webhook: 'Webhook',
|
webhook: 'Webhook',
|
||||||
payment_proof: 'Payment Proof',
|
payment_proof: 'Payment Proof',
|
||||||
|
update: 'Update',
|
||||||
update_available: 'Update {version} available!',
|
update_available: 'Update {version} available!',
|
||||||
latest_update: 'You are on the latest version {version}.',
|
latest_update: 'You are on the latest version {version}.',
|
||||||
notifications: 'Notifications',
|
notifications: 'Notifications',
|
||||||
|
|
@ -273,5 +274,6 @@ window.localisation.en = {
|
||||||
license: 'License',
|
license: 'License',
|
||||||
reset_key: 'Reset Key',
|
reset_key: 'Reset Key',
|
||||||
reset_password: 'Reset Password',
|
reset_password: 'Reset Password',
|
||||||
border_choices: 'Border Choices'
|
border_choices: 'Border Choices',
|
||||||
|
select_all: 'Select All'
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue