148 lines
4.2 KiB
JavaScript
148 lines
4.2 KiB
JavaScript
import ngModule from '../../module';
|
|
import Popup from '../popup';
|
|
import './style.scss';
|
|
|
|
/**
|
|
* Dialog component that allows to register function handlers for responses. If
|
|
* any of the handlers returns false or a promise that resolves to false,
|
|
* the dialog closing is cancelled. Also, if promise is returned, the dialog
|
|
* will wait until it is resolved by locking itself and displaying a loading
|
|
* animation.
|
|
*
|
|
* @property {Function} onResponse Handler for dialog response
|
|
* @property {Function} onAccept Shortcut handler for accept response
|
|
* @slot body The dialog HTML body
|
|
* @slot buttons The dialog HTML buttons
|
|
*/
|
|
export default class Dialog extends Popup {
|
|
/**
|
|
* Shows the dialog and optionally registers a handler for the response.
|
|
*
|
|
* @param {*} data Optional user data to pass to response handler
|
|
* @param {Function} responseHandler An optional response handler
|
|
* @return {Promise} A promise that will be resolved with response when dialog is closed
|
|
*/
|
|
show(data, responseHandler) {
|
|
if (this.shown)
|
|
return this.$q.reject(new Error('Dialog already shown'));
|
|
super.show();
|
|
|
|
if (typeof data == 'function') {
|
|
responseHandler = data;
|
|
data = null;
|
|
}
|
|
|
|
this.data = data;
|
|
this.showHandler = responseHandler;
|
|
return this.$q(resolve => {
|
|
this.resolve = resolve;
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Hides the dialog resolving the promise returned by show().
|
|
*
|
|
* @param {String} response The response
|
|
*/
|
|
hide(response) {
|
|
if (!this.shown) return;
|
|
super.hide();
|
|
|
|
this.showHandler = null;
|
|
if (this.resolve)
|
|
this.resolve(response);
|
|
}
|
|
|
|
/**
|
|
* Calls the response handlers.
|
|
*
|
|
* @param {String} response The response code
|
|
* @return {Boolean} The response handler return
|
|
*/
|
|
respond(response) {
|
|
if (!this.shown)
|
|
return this.$q.resolve();
|
|
return this.responseHandler(response);
|
|
}
|
|
|
|
/**
|
|
* The default response handler, it can be overriden by child classes to
|
|
* add custom logic.
|
|
*
|
|
* @param {String} response The response code
|
|
* @return {Boolean} The response handler return
|
|
*/
|
|
responseHandler(response) {
|
|
let handlerArgs = {
|
|
$response: response,
|
|
$data: this.data
|
|
};
|
|
let cancellers = [];
|
|
|
|
if (this.onResponse)
|
|
cancellers.push(this.onResponse(handlerArgs));
|
|
if (response == 'accept' && this.onAccept)
|
|
cancellers.push(this.onAccept(handlerArgs));
|
|
if (this.showHandler)
|
|
cancellers.push(this.showHandler(response, this.data));
|
|
|
|
let promises = [];
|
|
let resolvedCancellers = [];
|
|
|
|
for (let canceller of cancellers) {
|
|
if (canceller instanceof Object && canceller.then)
|
|
promises.push(canceller);
|
|
else
|
|
resolvedCancellers.push(canceller);
|
|
}
|
|
|
|
let close = () => {
|
|
if (resolvedCancellers.indexOf(false) == -1)
|
|
this.hide(response);
|
|
else
|
|
return false;
|
|
};
|
|
|
|
if (promises.length) {
|
|
this.loading = true;
|
|
|
|
return this.$q.all(promises)
|
|
.then(res => {
|
|
resolvedCancellers = resolvedCancellers.concat(res);
|
|
return close();
|
|
})
|
|
.finally(() => {
|
|
this.loading = false;
|
|
});
|
|
} else
|
|
return this.$q.resolve(close());
|
|
}
|
|
|
|
onButtonClick(event) {
|
|
let buttons = this.popup.querySelector('.buttons');
|
|
let tplButtons = buttons.querySelector('tpl-buttons');
|
|
let node = event.target;
|
|
while (node.parentNode != tplButtons) {
|
|
if (node == buttons) return;
|
|
node = node.parentNode;
|
|
}
|
|
|
|
this.respond(node.getAttribute('response'));
|
|
}
|
|
}
|
|
|
|
ngModule.vnComponent('vnDialog', {
|
|
slotTemplate: require('./index.html'),
|
|
controller: Dialog,
|
|
transclude: {
|
|
title: '?tplTitle',
|
|
body: '?tplBody',
|
|
buttons: '?tplButtons'
|
|
},
|
|
bindings: {
|
|
message: '@?',
|
|
onResponse: '&?',
|
|
onAccept: '&?'
|
|
}
|
|
});
|