yunohost-admin/app/src/views/update/SystemUpdate.vue
2024-03-02 02:47:30 +01:00

238 lines
7.1 KiB
Vue

<template>
<ViewBase
:queries="queries" queries-wait @queries-response="onQueriesResponse"
skeleton="CardListSkeleton"
>
<!-- MIGRATIONS WARN -->
<YAlert v-if="pendingMigrations" variant="warning" alert>
<span v-html="$t('pending_migrations')" />
</YAlert>
<!-- MAJOR YUNOHOST UPGRADE WARN -->
<YAlert v-if="importantYunohostUpgrade" variant="warning" alert>
<span v-html="$t('important_yunohost_upgrade')" />
</YAlert>
<!-- SYSTEM UPGRADE -->
<YCard :title="$t('system')" icon="server" no-body>
<BListGroup v-if="system" flush>
<BListGroupItem v-for="{ name, current_version, new_version } in system" :key="name">
<h5 class="m-0">
{{ name }}
<small class="text-secondary">({{ $t('from_to', [current_version, new_version]) }})</small>
</h5>
</BListGroupItem>
</BListGroup>
<BCardBody v-else-if="system === null">
<span class="text-success"><YIcon iname="check-circle" /> {{ $t('system_packages_nothing') }}</span>
</BCardBody>
<template #buttons v-if="system">
<BButton
variant="success" v-t="'system_upgrade_all_packages_btn'"
@click="performSystemUpgrade()"
/>
</template>
</YCard>
<!-- APPS UPGRADE -->
<YCard :title="$t('applications')" icon="cubes" no-body>
<BListGroup v-if="apps" flush>
<BListGroupItem
v-for="{ name, id, current_version, new_version } in apps" :key="id"
class="d-flex justify-content-between align-items-center"
>
<h5 class="m-0">
{{ name }}
<small>({{ id }}) {{ $t('from_to', [current_version, new_version]) }}</small>
</h5>
<BButton
variant="success" size="sm" v-t="'system_upgrade_btn'"
@click="confirmAppsUpgrade(id)"
/>
</BListGroupItem>
</BListGroup>
<BCardBody v-else-if="apps === null">
<span class="text-success"><YIcon iname="check-circle" /> {{ $t('system_apps_nothing') }}</span>
</BCardBody>
<template #buttons v-if="apps">
<BButton
variant="success" v-t="'system_upgrade_all_applications_btn'"
@click="confirmAppsUpgrade()"
/>
</template>
</YCard>
<BModal
id="apps-pre-upgrade"
:title="$t('app.upgrade.confirm.title')"
header-bg-variant="warning"
:header-class="theme ? 'text-white' : 'text-black'"
:ok-title="$t('system_upgrade_btn')" ok-variant="success"
:cancel-title="$t('cancel')"
@ok="performAppsUpgrade(preUpgrade.apps.map((app) => app.id))"
>
<h3>
{{ $t('app.upgrade.confirm.apps') }}
</h3>
<ul>
<li v-for="{ name, id } in preUpgrade.apps" :key="id">
{{ name }} ({{ id }})
</li>
</ul>
<div v-if="preUpgrade.hasNotifs" class="mt-4">
<h3>
{{ $t('app.upgrade.notifs.pre.title') }}
</h3>
<YAlert variant="warning">
{{ $t('app.upgrade.notifs.pre.alert' ) }}
</YAlert>
<div class="card-collapse-wrapper">
<CardCollapse
v-for="{ id, name, notif } in preUpgrade.apps" :key="`${id}-notifs`"
:title="name" :id="`${id}-notifs`"
visible flush
>
<BCardBody>
<VueShowdown :markdown="notif" flavor="github" :options="{ headerLevelStart: 6 }" />
</BCardBody>
</CardCollapse>
</div>
</div>
</BModal>
</ViewBase>
</template>
<script>
import api from '@/api'
import { mapGetters } from 'vuex'
import CardCollapse from '@/components/CardCollapse.vue'
export default {
name: 'SystemUpdate',
components: {
CardCollapse
},
data () {
return {
queries: [
['PUT', 'update/all', {}, 'update']
],
// API data
system: undefined,
apps: undefined,
importantYunohostUpgrade: undefined,
pendingMigrations: undefined,
preUpgrade: {
apps: [],
notifs: []
}
}
},
computed: {
...mapGetters(['theme'])
},
methods: {
// eslint-disable-next-line camelcase
onQueriesResponse ({ apps, system, important_yunohost_upgrade, pending_migrations }) {
this.apps = apps.length ? apps : null
this.system = system.length ? system : null
// eslint-disable-next-line camelcase
this.importantYunohostUpgrade = important_yunohost_upgrade
this.pendingMigrations = pending_migrations.length !== 0
},
formatAppNotifs (notifs) {
return Object.keys(notifs).reduce((acc, key) => {
return acc + '\n\n' + notifs[key]
}, '')
},
async confirmAppsUpgrade (id = null) {
const appList = id ? [this.apps.find((app) => app.id === id)] : this.apps
const apps = appList.map((app) => ({
id: app.id,
name: app.name,
notif: app.notifications.PRE_UPGRADE
? this.formatAppNotifs(app.notifications.PRE_UPGRADE)
: ''
}))
this.preUpgrade = { apps, hasNotifs: apps.some((app) => app.notif) }
this.$bvModal.show('apps-pre-upgrade')
},
async performAppsUpgrade (ids) {
const apps = ids.map((id) => this.apps.find((app) => app.id === id))
const lastAppId = apps[apps.length - 1].id
for (const app of apps) {
const continue_ = await api.put(
`apps/${app.id}/upgrade`, {}, { key: 'upgrade.app', app: app.name }
).then((response) => {
const postMessage = this.formatAppNotifs(response.notifications.POST_UPGRADE)
const isLast = app.id === lastAppId
this.apps = this.apps.filter((a) => app.id !== a.id)
if (postMessage) {
const message = this.$i18n.t('app.upgrade.notifs.post.alert') + '\n\n' + postMessage
return this.$askMdConfirmation(message, {
title: this.$i18n.t('app.upgrade.notifs.post.title', { name: app.name }),
okTitle: this.$i18n.t(isLast ? 'ok' : 'app.upgrade.continue'),
cancelTitle: this.$i18n.t('app.upgrade.stop')
}, isLast)
} else {
return Promise.resolve(true)
}
})
if (!continue_) break
}
if (!this.apps.length) {
this.apps = null
}
},
async performSystemUpgrade () {
const confirmed = await this.$askConfirmation(this.$i18n.t('confirm_update_system'))
if (!confirmed) return
api.put('upgrade/system', {}, { key: 'upgrade.system' }).then(() => {
if (this.system.some(({ name }) => name.includes('yunohost'))) {
this.$store.dispatch('TRY_TO_RECONNECT', { attemps: 1, origin: 'upgrade_system', initialDelay: 2000 })
}
this.system = null
})
}
}
}
</script>
<style scoped lang="scss">
.card-collapse-wrapper {
border: $card-border-width solid $card-border-color;
border-radius: $card-border-radius;
.card {
&:first-child {
border-top: 0;
border-top-right-radius: $card-border-radius;
border-top-left-radius: $card-border-radius;
}
&:last-child {
border-bottom: 0;
}
}
}
</style>