TT#95950 Introduce a basic pattern to create and handle Dialogs

Change-Id: I23fa5786ced7cf66ba59256c356b7b556387388f
mr9.1.1
Hans-Peter Herzog 5 years ago
parent 17594233fa
commit b47c7e6061

@ -67,6 +67,30 @@ In order to add a new page you need to go along the following steps:
} }
``` ```
### Dialogs
![Example dialog](doc/images/dialog.png)
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 ### NGCP API
All API functions are located in `src/api`. The file `src/api/common.js` All API functions are located in `src/api`. The file `src/api/common.js`

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

@ -1,46 +1,58 @@
<template> <template>
<q-dialog <q-dialog
ref="modal" ref="dialog"
minimized v-bind="$attrs"
v-on="$listeners"
> >
<div <q-card
class="csc-dialog csc-share-dialog" class="bg-dark q-dialog-plugin"
> >
<div <q-card-section
class="csc-dialog-title" class="no-padding"
>
<q-item>
<q-item-section
v-if="titleIcon !== undefined && titleIcon !== null && titleIcon !== ''"
side
no-wrap
> >
<q-icon <q-icon
v-if="titleIcon"
:name="titleIcon" :name="titleIcon"
size="24px" :color="titleIconColor"
/> />
<span </q-item-section>
class="csc-dialog-title-text" <q-item-section
>{{ title }}</span> class="text-subtitle1"
</div> no-wrap
<div
class="csc-dialog-content"
> >
{{ title }}
</q-item-section>
</q-item>
</q-card-section>
<q-separator />
<q-card-section>
<slot <slot
name="content" name="content"
/> />
</div> <slot
<div name="default"
class="csc-dialog-actions row justify-end no-wrap" />
</q-card-section>
<q-card-actions
align="right"
> >
<q-btn <q-btn
icon="clear" icon="clear"
color="default" color="white"
flat flat
:label="$t('buttons.cancel')"
@click="cancel" @click="cancel"
> />
{{ $t('buttons.cancel') }}
</q-btn>
<slot <slot
name="actions" name="actions"
/> />
</div> </q-card-actions>
</div> </q-card>
</q-dialog> </q-dialog>
</template> </template>
@ -50,25 +62,25 @@ export default {
props: { props: {
title: { title: {
type: String, type: String,
default: '' default: undefined,
required: true
}, },
titleIcon: { titleIcon: {
type: String, type: String,
default: '' default: undefined
},
titleIconColor: {
type: String,
default: 'primary'
}, },
opened: { opened: {
type: Boolean, type: Boolean,
default: false default: false
} }
}, },
data () {
return {
}
},
watch: { watch: {
opened (opened) { opened (opened) {
if (opened) { if (opened === true) {
this.open() this.open()
} else { } else {
this.close() this.close()
@ -82,12 +94,20 @@ export default {
}, },
methods: { methods: {
open () { open () {
this.$refs.modal.show() this.show()
},
show () {
this.$refs.dialog.show()
this.$emit('show')
}, },
close () { close () {
this.$refs.modal.hide() this.hide()
this.$emit('close') this.$emit('close')
}, },
hide () {
this.$refs.dialog.hide()
this.$emit('hide')
},
cancel () { cancel () {
this.close() this.close()
this.$emit('cancel') this.$emit('cancel')
@ -95,24 +115,3 @@ export default {
} }
} }
</script> </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>

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

@ -1,18 +1,21 @@
<template> <template>
<csc-dialog-base <csc-dialog
ref="dialog" ref="dialog"
icon="vpn_key" title-icon="vpn_key"
title="Change Password" :title="$t('userSettings.changePasswordDialogTitle')"
:ready="ready"
v-bind="$attrs"
v-on="$listeners"
@hide="$emit('hide', $event)"
@ok="ok"
> >
<template <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> </template>
<csc-input-password-retype <csc-input-password-retype
v-model="passwordRetype" v-model="passwordRetype"
@ -20,16 +23,16 @@
@validation-failed="ready=false" @validation-failed="ready=false"
@validation-succeeded="ready=true" @validation-succeeded="ready=true"
/> />
</csc-dialog-base> </csc-dialog>
</template> </template>
<script> <script>
import CscInputPasswordRetype from 'components/form/CscInputPasswordRetype' import CscInputPasswordRetype from 'components/form/CscInputPasswordRetype'
import CscDialogBase from 'components/CscDialogBase' import CscDialog from 'components/CscDialog'
export default { export default {
name: 'CscDialogChangePassword', name: 'CscDialogChangePassword',
components: { components: {
CscDialogBase, CscDialog,
CscInputPasswordRetype CscInputPasswordRetype
}, },
data () { data () {
@ -48,9 +51,10 @@ export default {
hide () { hide () {
this.$refs.dialog.hide() this.$refs.dialog.hide()
}, },
ok () { okEvent () {
if (this.ready) { if (this.ready) {
this.$emit('confirmed', this.passwordRetype.password) this.$emit('ok', this.passwordRetype.password)
this.hide()
} }
} }
} }

@ -2,7 +2,7 @@
<q-popup-proxy> <q-popup-proxy>
<q-list <q-list
v-bind="$attrs" v-bind="$attrs"
class="bg-main-menu" class="bg-dark"
v-on="$listeners" v-on="$listeners"
> >
<slot /> <slot />

@ -233,10 +233,6 @@
@click="jumpToCallQueue" @click="jumpToCallQueue"
/> />
</div> </div>
<csc-dialog-change-password
ref="dialogChangePassword"
@confirmed="changeWebPassword"
/>
</q-expansion-item> </q-expansion-item>
</template> </template>
@ -253,7 +249,6 @@ import CscDialogChangePassword from 'components/CscDialogChangePassword'
export default { export default {
name: 'CscPbxSeat', name: 'CscPbxSeat',
components: { components: {
CscDialogChangePassword,
CscPopupMenuItem, CscPopupMenuItem,
CscPopupMenuItemDelete, CscPopupMenuItemDelete,
CscMoreMenu, CscMoreMenu,
@ -446,14 +441,18 @@ export default {
} }
}, },
showPasswordDialog () { showPasswordDialog () {
this.$refs.dialogChangePassword.show() this.$q.dialog({
component: CscDialogChangePassword,
parent: this
}).onOk((password) => {
this.changeWebPassword(password)
})
}, },
async changeWebPassword (password) { async changeWebPassword (password) {
await this.$store.dispatch('pbxSeats/setSeatWebPassword', { await this.$store.dispatch('pbxSeats/setSeatWebPassword', {
seatId: this.seat.id, seatId: this.seat.id,
seatWebPassword: password seatWebPassword: password
}) })
this.$refs.dialogChangePassword.hide()
}, },
changeIntraPbx () { changeIntraPbx () {
this.$emit('save-intra-pbx', { this.$emit('save-intra-pbx', {

@ -67,7 +67,7 @@
</div> </div>
<q-list <q-list
v-if="!isSeatListEmpty && seatListVisibility === 'visible'" v-if="!isSeatListEmpty && seatListVisibility === 'visible'"
class="row justify-start" class="row justify-start items-start"
> >
<csc-pbx-seat <csc-pbx-seat
v-for="(seat, index) in seatListItems" v-for="(seat, index) in seatListItems"

Loading…
Cancel
Save