diff --git a/README.md b/README.md index af03256e..51b2572c 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,30 @@ In order to add a new page you need to go along the following steps: } ``` +### Dialogs + + + +The basic dialog component is `src/components/CscDialog.vue`. + +#### How to create a new custom dialog + +Check the example implementation in `src/components/CscDialogChangePassword.vue`. + +#### How to call custom dialogs from within a Vue.js Component method + +To reduce the boilerplate code of dialog components, we call Dialogs +via [Quasar Dialog Plugin](https://quasar.dev/quasar-plugins/dialog). + +```javascript +this.$q.dialog({ + component: CscDialogChangePassword, + parent: this +}).onOk((password) => { + this.changeWebPassword(password) +}) +``` + ### NGCP API All API functions are located in `src/api`. The file `src/api/common.js` diff --git a/doc/images/dialog.png b/doc/images/dialog.png new file mode 100644 index 00000000..856945e0 Binary files /dev/null and b/doc/images/dialog.png differ diff --git a/src/components/CscDialog.vue b/src/components/CscDialog.vue index 0d854533..df2108bb 100644 --- a/src/components/CscDialog.vue +++ b/src/components/CscDialog.vue @@ -1,46 +1,58 @@ <template> <q-dialog - ref="modal" - minimized + ref="dialog" + v-bind="$attrs" + v-on="$listeners" > - <div - class="csc-dialog csc-share-dialog" + <q-card + class="bg-dark q-dialog-plugin" > - <div - class="csc-dialog-title" - > - <q-icon - v-if="titleIcon" - :name="titleIcon" - size="24px" - /> - <span - class="csc-dialog-title-text" - >{{ title }}</span> - </div> - <div - class="csc-dialog-content" + <q-card-section + class="no-padding" > + <q-item> + <q-item-section + v-if="titleIcon !== undefined && titleIcon !== null && titleIcon !== ''" + side + no-wrap + > + <q-icon + :name="titleIcon" + :color="titleIconColor" + /> + </q-item-section> + <q-item-section + class="text-subtitle1" + no-wrap + > + {{ title }} + </q-item-section> + </q-item> + </q-card-section> + <q-separator /> + <q-card-section> <slot name="content" /> - </div> - <div - class="csc-dialog-actions row justify-end no-wrap" + <slot + name="default" + /> + </q-card-section> + <q-card-actions + align="right" > <q-btn icon="clear" - color="default" + color="white" flat + :label="$t('buttons.cancel')" @click="cancel" - > - {{ $t('buttons.cancel') }} - </q-btn> + /> <slot name="actions" /> - </div> - </div> + </q-card-actions> + </q-card> </q-dialog> </template> @@ -50,25 +62,25 @@ export default { props: { title: { type: String, - default: '' + default: undefined, + required: true }, titleIcon: { type: String, - default: '' + default: undefined + }, + titleIconColor: { + type: String, + default: 'primary' }, opened: { type: Boolean, default: false } }, - data () { - return { - - } - }, watch: { opened (opened) { - if (opened) { + if (opened === true) { this.open() } else { this.close() @@ -82,12 +94,20 @@ export default { }, methods: { open () { - this.$refs.modal.show() + this.show() + }, + show () { + this.$refs.dialog.show() + this.$emit('show') }, close () { - this.$refs.modal.hide() + this.hide() this.$emit('close') }, + hide () { + this.$refs.dialog.hide() + this.$emit('hide') + }, cancel () { this.close() this.$emit('cancel') @@ -95,24 +115,3 @@ export default { } } </script> - -<style lang="stylus" rel="stylesheet/stylus"> - .csc-dialog - max-width 480px - background-color $body-background - .csc-dialog-title - text-transform uppercase - font-size 14px - line-height 14px - padding $flex-gutter-sm - background-color $item-highlight-color - .csc-dialog-title-text - vertical-align middle - i - margin-right $flex-gutter-xs - vertical-align middle - .csc-dialog-content - padding $flex-gutter-md - .csc-dialog-actions - padding $flex-gutter-sm -</style> diff --git a/src/components/CscDialogBase.vue b/src/components/CscDialogBase.vue deleted file mode 100644 index e982dbee..00000000 --- a/src/components/CscDialogBase.vue +++ /dev/null @@ -1,91 +0,0 @@ -<template> - <q-dialog - ref="dialog" - v-bind="$attrs" - v-on="$listeners" - @hide="$emit('hide', $event)" - > - <q-card - class="bg-main-menu q-dialog-plugin" - > - <q-card-section - class="text-h6" - > - <q-icon - v-if="icon !== undefined" - :name="icon" - size="24px" - class="self-center" - /> - {{ title }} - </q-card-section> - <q-card-section> - <slot /> - </q-card-section> - <q-card-actions - align="right" - > - <q-btn - icon="clear" - :label="$t('buttons.cancel')" - flat - @click="hide" - /> - <q-btn - icon="check" - :label="$t('buttons.confirm')" - unelevated - text-color="dark" - color="primary" - :disable="!ready" - @click="okEvent" - /> - </q-card-actions> - </q-card> - </q-dialog> -</template> - -<script> -export default { - name: 'CscDialogBase', - components: { - }, - props: { - icon: { - type: String, - default: undefined - }, - title: { - type: String, - default: undefined - }, - ready: { - type: Boolean, - default: true - } - }, - data () { - return { - passwordRetype: { - password: '', - passwordRetype: '' - } - } - }, - methods: { - show () { - this.$refs.dialog.show() - }, - hide () { - this.$refs.dialog.hide() - }, - okEvent ($event) { - this.$emit('ok', $event) - this.hide() - }, - cancelEvent ($event) { - this.hide() - } - } -} -</script> diff --git a/src/components/CscDialogChangePassword.vue b/src/components/CscDialogChangePassword.vue index c8cb2a4f..c2d84928 100644 --- a/src/components/CscDialogChangePassword.vue +++ b/src/components/CscDialogChangePassword.vue @@ -1,18 +1,21 @@ <template> - <csc-dialog-base + <csc-dialog ref="dialog" - icon="vpn_key" - title="Change Password" - :ready="ready" - v-bind="$attrs" - v-on="$listeners" - @hide="$emit('hide', $event)" - @ok="ok" + title-icon="vpn_key" + :title="$t('userSettings.changePasswordDialogTitle')" > <template - v-slot:title + v-slot:actions > - Change Password + <q-btn + icon="check" + :label="$t('buttons.confirm')" + :disable="!ready" + unelevated + text-color="dark" + color="primary" + @click="okEvent" + /> </template> <csc-input-password-retype v-model="passwordRetype" @@ -20,16 +23,16 @@ @validation-failed="ready=false" @validation-succeeded="ready=true" /> - </csc-dialog-base> + </csc-dialog> </template> <script> import CscInputPasswordRetype from 'components/form/CscInputPasswordRetype' -import CscDialogBase from 'components/CscDialogBase' +import CscDialog from 'components/CscDialog' export default { name: 'CscDialogChangePassword', components: { - CscDialogBase, + CscDialog, CscInputPasswordRetype }, data () { @@ -48,9 +51,10 @@ export default { hide () { this.$refs.dialog.hide() }, - ok () { + okEvent () { if (this.ready) { - this.$emit('confirmed', this.passwordRetype.password) + this.$emit('ok', this.passwordRetype.password) + this.hide() } } } diff --git a/src/components/CscPopupMenu.vue b/src/components/CscPopupMenu.vue index 834c0116..f3c06ad7 100644 --- a/src/components/CscPopupMenu.vue +++ b/src/components/CscPopupMenu.vue @@ -2,7 +2,7 @@ <q-popup-proxy> <q-list v-bind="$attrs" - class="bg-main-menu" + class="bg-dark" v-on="$listeners" > <slot /> diff --git a/src/components/pages/PbxConfiguration/CscPbxSeat.vue b/src/components/pages/PbxConfiguration/CscPbxSeat.vue index 61a68620..3ad16a75 100644 --- a/src/components/pages/PbxConfiguration/CscPbxSeat.vue +++ b/src/components/pages/PbxConfiguration/CscPbxSeat.vue @@ -233,10 +233,6 @@ @click="jumpToCallQueue" /> </div> - <csc-dialog-change-password - ref="dialogChangePassword" - @confirmed="changeWebPassword" - /> </q-expansion-item> </template> @@ -253,7 +249,6 @@ import CscDialogChangePassword from 'components/CscDialogChangePassword' export default { name: 'CscPbxSeat', components: { - CscDialogChangePassword, CscPopupMenuItem, CscPopupMenuItemDelete, CscMoreMenu, @@ -446,14 +441,18 @@ export default { } }, showPasswordDialog () { - this.$refs.dialogChangePassword.show() + this.$q.dialog({ + component: CscDialogChangePassword, + parent: this + }).onOk((password) => { + this.changeWebPassword(password) + }) }, async changeWebPassword (password) { await this.$store.dispatch('pbxSeats/setSeatWebPassword', { seatId: this.seat.id, seatWebPassword: password }) - this.$refs.dialogChangePassword.hide() }, changeIntraPbx () { this.$emit('save-intra-pbx', { diff --git a/src/components/pages/PbxConfiguration/CscPbxSeats.vue b/src/components/pages/PbxConfiguration/CscPbxSeats.vue index 96de5ca1..8f1b074b 100644 --- a/src/components/pages/PbxConfiguration/CscPbxSeats.vue +++ b/src/components/pages/PbxConfiguration/CscPbxSeats.vue @@ -67,7 +67,7 @@ </div> <q-list v-if="!isSeatListEmpty && seatListVisibility === 'visible'" - class="row justify-start" + class="row justify-start items-start" > <csc-pbx-seat v-for="(seat, index) in seatListItems"