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 @@