migration(bvn): update modals and modal system

This commit is contained in:
axolotle 2024-03-17 16:06:08 +01:00
parent 915023de1d
commit 622e5be061
19 changed files with 146 additions and 69 deletions

View file

@ -53,6 +53,8 @@
</main>
</ViewLockOverlay>
<BModalOrchestrator />
<!-- HISTORY CONSOLE -->
<HistoryConsole />

View file

@ -0,0 +1,42 @@
import { h } from 'vue'
import { useModalController, BModal } from 'bootstrap-vue-next'
import { VueShowdown } from 'vue-showdown'
export function useAutoModal() {
const { confirm, show } = useModalController()
return function (
message,
props_,
{ markdown = false, cancelable = true } = {},
) {
const props = {
okTitle: this.$t('ok'),
cancelTitle: this.$t('cancel'),
centered: true,
okOnly: !cancelable,
...(markdown
? { headerBgVariant: 'warning', headerClass: 'text-black' }
: {
hideHeader: true,
bodyBgVariant: 'warning',
bodyClass: ['fw-bold', 'rounded-top', 'text-black'],
}),
...props_,
}
const fn = cancelable ? confirm : show
return fn?.({
props,
component: h(BModal, null, {
default: () =>
markdown
? h(VueShowdown, {
markdown: message,
options: { headerLevelStart: 3 },
})
: message,
}),
})
}
}

View file

@ -29,41 +29,6 @@ app.use(VueShowdownPlugin, {
},
})
// Ugly wrapper for `$bvModal.msgBoxConfirm` to set default i18n button titles
// FIXME find or wait for a better way
app.config.globalProperties.$askConfirmation = function (message, props) {
return this.$bvModal.msgBoxConfirm(message, {
okTitle: this.$t('ok'),
cancelTitle: this.$t('cancel'),
bodyBgVariant: 'warning',
centered: true,
bodyClass: [
'font-weight-bold',
'rounded-top',
store.state.dark ? 'text-white' : 'text-black',
],
...props,
})
}
app.config.globalProperties.$askMdConfirmation = function (
markdown,
props,
ok = false,
) {
const content = this.$createElement('vue-showdown', {
props: { markdown, flavor: 'github', options: { headerLevelStart: 4 } },
})
return this.$bvModal['msgBox' + (ok ? 'Ok' : 'Confirm')](content, {
okTitle: this.$t('yes'),
cancelTitle: this.$t('cancel'),
headerBgVariant: 'warning',
headerClass: store.state.dark ? 'text-white' : 'text-black',
centered: true,
...props,
})
}
// Register global components
const globalComponentsModules = import.meta.glob(
['@/components/globals/*.vue', '@/components/globals/*/*.vue'],

View file

@ -45,7 +45,9 @@
// Utilities
@import '~bootstrap/scss/utilities/api';
@import '~bootstrap-vue-next/src/styles/styles.scss';
// @import '~bootstrap-vue-next/src/styles/styles.scss';
// FIXME modals doesn't appears if we import the scss
@import 'bootstrap-vue-next/dist/bootstrap-vue-next.css';
// Import fonts
@import 'font';

View file

@ -92,6 +92,7 @@
import { useVuelidate } from '@vuelidate/core'
import api from '@/api'
import { useAutoModal } from '@/composables/useAutoModal'
import { DomainForm } from '@/views/_partials'
import LoginView from '@/views/LoginView.vue'
import { formatFormData } from '@/helpers/yunohostArguments'
@ -114,6 +115,7 @@ export default {
setup() {
return {
v$: useVuelidate(),
modalConfirm: useAutoModal(),
}
},
@ -179,7 +181,7 @@ export default {
},
async setUser() {
const confirmed = await this.$askConfirmation(
const confirmed = await this.modalConfirm(
this.$t('confirm_postinstall', { domain: this.domain }),
)
if (!confirmed) return

View file

@ -223,6 +223,7 @@
import { useVuelidate } from '@vuelidate/core'
import CardDeckFeed from '@/components/CardDeckFeed.vue'
import { useAutoModal } from '@/composables/useAutoModal'
import { required, appRepoUrl } from '@/helpers/validators'
import { randint } from '@/helpers/commons'
@ -243,6 +244,7 @@ export default {
setup() {
return {
v$: useVuelidate(),
modalConfirm: useAutoModal(),
}
},
@ -403,7 +405,7 @@ export default {
async onInstallClick(appId) {
const app = this.apps.find((app) => app.id === appId)
if (!app.decent_quality) {
const confirmed = await this.$askConfirmation(
const confirmed = await this.modalConfirm(
this.$t('confirm_install_app_' + app.state),
)
if (!confirmed) return
@ -413,7 +415,7 @@ export default {
// INSTALL CUSTOM APP
async onCustomInstallClick() {
const confirmed = await this.$askConfirmation(
const confirmed = await this.modalConfirm(
this.$t('confirm_install_custom_app'),
)
if (!confirmed) return

View file

@ -343,8 +343,8 @@
id="uninstall-modal"
:title="$t('confirm_uninstall', { name: id })"
header-bg-variant="warning"
header-class="text-black"
:body-class="{ 'd-none': !app.supports_purge }"
body-bg-variant=""
@ok="uninstall"
>
<BFormGroup v-if="app.supports_purge">
@ -366,6 +366,7 @@ import { mapGetters } from 'vuex'
import { useVuelidate } from '@vuelidate/core'
import api, { objectToParams } from '@/api'
import { useAutoModal } from '@/composables/useAutoModal'
import { humanPermissionName } from '@/helpers/filters/human'
import { helpers, required } from '@/helpers/validators'
import { isEmptyValue } from '@/helpers/commons'
@ -390,6 +391,7 @@ export default {
setup() {
return {
v$: useVuelidate(),
modalConfirm: useAutoModal(),
}
},
@ -646,7 +648,7 @@ export default {
},
async changeUrl() {
const confirmed = await this.$askConfirmation(
const confirmed = await this.modalConfirm(
this.$t('confirm_app_change_url'),
)
if (!confirmed) return
@ -662,9 +664,7 @@ export default {
},
async setAsDefaultDomain(undo = false) {
const confirmed = await this.$askConfirmation(
this.$t('confirm_app_default'),
)
const confirmed = await this.modalConfirm(this.$t('confirm_app_default'))
if (!confirmed) return
api

View file

@ -209,6 +209,7 @@
import { useVuelidate } from '@vuelidate/core'
import api, { objectToParams } from '@/api'
import { useAutoModal } from '@/composables/useAutoModal'
import {
formatYunoHostArguments,
formatI18nField,
@ -230,6 +231,7 @@ export default {
setup() {
return {
v$: useVuelidate(),
modalConfirm: useAutoModal(),
}
},
@ -379,7 +381,7 @@ export default {
async performInstall() {
if ('path' in this.form && this.form.path === '/') {
const confirmed = await this.$askConfirmation(
const confirmed = await this.modalConfirm(
this.$t('confirm_install_domain_root', {
domain: this.form.domain,
}),
@ -405,15 +407,14 @@ export default {
if (postInstall) {
const message =
this.$t('app.install.notifs.post.alert') + '\n\n' + postInstall
await this.$askMdConfirmation(
await this.modalConfirm(
message,
{
title: this.$t('app.install.notifs.post.title', {
name: this.app.name,
}),
okTitle: this.$t('ok'),
},
true,
{ markdown: true, cancelable: false },
)
}
this.$router.push({ name: 'app-list' })

View file

@ -137,6 +137,7 @@
<script>
import api from '@/api'
import { useAutoModal } from '@/composables/useAutoModal'
import { readableDate } from '@/helpers/filters/date'
import { humanSize } from '@/helpers/filters/human'
import { isEmptyValue } from '@/helpers/commons'
@ -149,6 +150,12 @@ export default {
name: { type: String, required: true },
},
setup() {
return {
modalConfirm: useAutoModal(),
}
},
data() {
return {
queries: [['GET', `backups/${this.name}?with_details`]],
@ -215,7 +222,7 @@ export default {
},
async restoreBackup() {
const confirmed = await this.$askConfirmation(
const confirmed = await this.modalConfirm(
this.$t('confirm_restore', { name: this.name }),
)
if (!confirmed) return
@ -245,7 +252,7 @@ export default {
},
async deleteBackup() {
const confirmed = await this.$askConfirmation(
const confirmed = await this.modalConfirm(
this.$t('confirm_delete', { name: this.name }),
)
if (!confirmed) return

View file

@ -145,6 +145,7 @@
<script>
import api from '@/api'
import { useAutoModal } from '@/composables/useAutoModal'
import { isEmptyValue } from '@/helpers/commons'
export default {
@ -154,6 +155,12 @@ export default {
name: { type: String, required: true },
},
setup() {
return {
modalConfirm: useAutoModal(),
}
},
data() {
return {
queries: [['GET', `domains/${this.name}/dns/suggest`]],
@ -246,7 +253,7 @@ export default {
async pushDnsChanges() {
if (this.force) {
const confirmed = await this.$askConfirmation(
const confirmed = await this.modalConfirm(
this.$t('domain.dns.push_force_confirm'),
)
if (!confirmed) return

View file

@ -125,8 +125,8 @@
:title="$t('confirm_delete', { name: this.name })"
@ok="deleteDomain"
header-bg-variant="warning"
body-class=""
body-bg-variant=""
header-class="text-black"
:body-class="{ 'd-none': !isMainDynDomain }"
>
<BFormGroup v-if="isMainDynDomain">
<BFormCheckbox v-model="unsubscribeDomainFromDyndns">
@ -141,6 +141,7 @@
import { mapGetters } from 'vuex'
import api, { objectToParams } from '@/api'
import { useAutoModal } from '@/composables/useAutoModal'
import {
formatFormData,
formatYunoHostConfigPanels,
@ -160,6 +161,12 @@ export default {
name: { type: String, required: true },
},
setup() {
return {
modalConfirm: useAutoModal(),
}
},
data() {
return {
queries: [
@ -279,7 +286,7 @@ export default {
},
async setAsDefaultDomain() {
const confirmed = await this.$askConfirmation(
const confirmed = await this.modalConfirm(
this.$t('confirm_change_maindomain'),
)
if (!confirmed) return

View file

@ -134,6 +134,7 @@
<script>
import api from '@/api'
import { useAutoModal } from '@/composables/useAutoModal'
import { isEmptyValue } from '@/helpers/commons'
import TagsSelectizeItem from '@/components/globals/formItems/TagsSelectizeItem.vue'
@ -146,6 +147,12 @@ export default {
TagsSelectizeItem,
},
setup() {
return {
modalConfirm: useAutoModal(),
}
},
data() {
return {
queries: [
@ -264,7 +271,7 @@ export default {
async onPermissionChanged({ option, groupName, action, applyMethod }) {
const permId = this.permissions.find((perm) => perm.label === option).id
if (action === 'add' && ['sftp.main', 'ssh.main'].includes(permId)) {
const confirmed = await this.$askConfirmation(
const confirmed = await this.modalConfirm(
this.$t('confirm_group_add_access_permission', {
name: groupName,
perm: option,
@ -310,7 +317,7 @@ export default {
},
async deleteGroup(groupName) {
const confirmed = await this.$askConfirmation(
const confirmed = await this.modalConfirm(
this.$t('confirm_delete', { name: groupName }),
)
if (!confirmed) return

View file

@ -83,6 +83,7 @@
<script>
import api from '@/api'
import { useAutoModal } from '@/composables/useAutoModal'
import { distanceToNow } from '@/helpers/filters/date'
export default {
@ -92,6 +93,12 @@ export default {
name: { type: String, required: true },
},
setup() {
return {
modalConfirm: useAutoModal(),
}
},
data() {
return {
queries: [
@ -132,7 +139,7 @@ export default {
},
async updateService(action) {
const confirmed = await this.$askConfirmation(
const confirmed = await this.modalConfirm(
this.$t('confirm_service_' + action, { name: this.name }),
)
if (!confirmed) return

View file

@ -121,6 +121,7 @@
import { useVuelidate } from '@vuelidate/core'
import api from '@/api'
import { useAutoModal } from '@/composables/useAutoModal'
import { required, integer, between } from '@/helpers/validators'
export default {
@ -129,6 +130,7 @@ export default {
setup() {
return {
v$: useVuelidate(),
modalConfirm: useAutoModal(),
}
},
@ -214,7 +216,7 @@ export default {
},
async togglePort({ action, port, protocol, connection }) {
const confirmed = await this.$askConfirmation(
const confirmed = await this.modalConfirm(
this.$t('confirm_firewall_' + action, {
port,
protocol,
@ -244,7 +246,7 @@ export default {
async toggleUpnp(value) {
const action = this.upnpEnabled ? 'disable' : 'enable'
const confirmed = await this.$askConfirmation(
const confirmed = await this.modalConfirm(
this.$t('confirm_upnp_' + action),
)
if (!confirmed) return

View file

@ -88,11 +88,18 @@
<script>
import api from '@/api'
import { useAutoModal } from '@/composables/useAutoModal'
// FIXME not tested with pending migrations (disclaimer and stuff)
export default {
name: 'ToolMigrations',
setup() {
return {
modalConfirm: useAutoModal(),
}
},
data() {
return {
queries: [
@ -136,7 +143,7 @@ export default {
},
async skipMigration(id) {
const confirmed = await this.$askConfirmation(
const confirmed = await this.modalConfirm(
this.$t('confirm_migrations_skip'),
)
if (!confirmed) return

View file

@ -35,13 +35,20 @@
<script>
import api from '@/api'
import { useAutoModal } from '@/composables/useAutoModal'
export default {
name: 'ToolPower',
setup() {
return {
modalConfirm: useAutoModal(),
}
},
methods: {
async triggerAction(action) {
const confirmed = await this.$askConfirmation(
const confirmed = await this.modalConfirm(
this.$t('confirm_reboot_action_' + action),
)
if (!confirmed) return

View file

@ -88,10 +88,11 @@
</YCard>
<BModal
v-model="showPreUpgradeModal"
id="apps-pre-upgrade"
:title="$t('app.upgrade.confirm.title')"
header-bg-variant="warning"
:header-class="dark ? 'text-white' : 'text-black'"
header-class="text-black"
:ok-title="$t('system_upgrade_btn')"
ok-variant="success"
:cancel-title="$t('cancel')"
@ -139,6 +140,7 @@
<script>
import api from '@/api'
import { useAutoModal } from '@/composables/useAutoModal'
import { mapGetters } from 'vuex'
import CardCollapse from '@/components/CardCollapse.vue'
@ -150,6 +152,12 @@ export default {
CardCollapse,
},
setup() {
return {
modalConfirm: useAutoModal(),
}
},
data() {
return {
queries: [['PUT', 'update/all', {}, 'update']],
@ -158,6 +166,7 @@ export default {
apps: undefined,
importantYunohostUpgrade: undefined,
pendingMigrations: undefined,
showPreUpgradeModal: false,
preUpgrade: {
apps: [],
notifs: [],
@ -200,7 +209,7 @@ export default {
: '',
}))
this.preUpgrade = { apps, hasNotifs: apps.some((app) => app.notif) }
this.$bvModal.show('apps-pre-upgrade')
this.showPreUpgradeModal = true
},
async performAppsUpgrade(ids) {
@ -224,7 +233,7 @@ export default {
if (postMessage) {
const message =
this.$t('app.upgrade.notifs.post.alert') + '\n\n' + postMessage
return this.$askMdConfirmation(
return this.modalConfirm(
message,
{
title: this.$t('app.upgrade.notifs.post.title', {
@ -233,7 +242,7 @@ export default {
okTitle: this.$t(isLast ? 'ok' : 'app.upgrade.continue'),
cancelTitle: this.$t('app.upgrade.stop'),
},
isLast,
{ markdown: true, cancelable: !isLast },
)
} else {
return Promise.resolve(true)
@ -248,7 +257,7 @@ export default {
},
async performSystemUpgrade() {
const confirmed = await this.$askConfirmation(
const confirmed = await this.modalConfirm(
this.$t('confirm_update_system'),
)
if (!confirmed) return

View file

@ -23,6 +23,7 @@
<script>
import api from '@/api'
import { useAutoModal } from '@/composables/useAutoModal'
import { useVuelidate } from '@vuelidate/core'
import { formatFormData } from '@/helpers/yunohostArguments'
@ -34,6 +35,7 @@ export default {
setup() {
return {
v$: useVuelidate(),
modalConfirm: useAutoModal(),
}
},
@ -89,7 +91,7 @@ export default {
methods: {
async onSubmit() {
if (this.form.delete) {
const confirmed = await this.$askConfirmation(
const confirmed = await this.modalConfirm(
this.$t('users_import_confirm_destructive'),
{ okTitle: this.$t('users_import_delete_others') },
)

View file

@ -83,8 +83,7 @@
:title="$t('confirm_delete', { name: user.username })"
@ok="deleteUser"
header-bg-variant="warning"
body-class=""
body-bg-variant=""
header-class="text-black"
>
<BFormGroup>
<BFormCheckbox v-model="purge">