diff --git a/app/src/App.vue b/app/src/App.vue
index 773da152..8347c71a 100644
--- a/app/src/App.vue
+++ b/app/src/App.vue
@@ -53,6 +53,8 @@
+
+
diff --git a/app/src/composables/useAutoModal.js b/app/src/composables/useAutoModal.js
new file mode 100644
index 00000000..b0ba93ec
--- /dev/null
+++ b/app/src/composables/useAutoModal.js
@@ -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,
+ }),
+ })
+ }
+}
diff --git a/app/src/main.js b/app/src/main.js
index 77627699..92f7cbcd 100644
--- a/app/src/main.js
+++ b/app/src/main.js
@@ -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'],
diff --git a/app/src/scss/main.scss b/app/src/scss/main.scss
index 1c15f2e2..7e770aaa 100644
--- a/app/src/scss/main.scss
+++ b/app/src/scss/main.scss
@@ -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';
diff --git a/app/src/views/PostInstall.vue b/app/src/views/PostInstall.vue
index ac9c0dd4..599f7794 100644
--- a/app/src/views/PostInstall.vue
+++ b/app/src/views/PostInstall.vue
@@ -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
diff --git a/app/src/views/app/AppCatalog.vue b/app/src/views/app/AppCatalog.vue
index ba5b1c40..5948d4ca 100644
--- a/app/src/views/app/AppCatalog.vue
+++ b/app/src/views/app/AppCatalog.vue
@@ -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
diff --git a/app/src/views/app/AppInfo.vue b/app/src/views/app/AppInfo.vue
index 4226ffd8..4b55fc60 100644
--- a/app/src/views/app/AppInfo.vue
+++ b/app/src/views/app/AppInfo.vue
@@ -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"
>
@@ -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
diff --git a/app/src/views/app/AppInstall.vue b/app/src/views/app/AppInstall.vue
index e6a4b6d8..4b8d9a97 100644
--- a/app/src/views/app/AppInstall.vue
+++ b/app/src/views/app/AppInstall.vue
@@ -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' })
diff --git a/app/src/views/backup/BackupInfo.vue b/app/src/views/backup/BackupInfo.vue
index 7d119126..ccc1b3b5 100644
--- a/app/src/views/backup/BackupInfo.vue
+++ b/app/src/views/backup/BackupInfo.vue
@@ -137,6 +137,7 @@