<commit_before>'use strict';

// external deps
var ObjectId = require('mongodb').ObjectId;

// internal deps
require('mongodb-toolkit');
var BateeqModels = require('bateeq-models');
var generateCode = require('../../utils/code-generator');
var map = BateeqModels.map;

var TransferOutDoc = BateeqModels.inventory.TransferOutDoc;
var TransferOutItem = BateeqModels.inventory.TransferOutItem;

var moduleId = "EFR-KB/RTP";

module.exports = class TokoKirimBarangReturnManager {
    constructor(db, user) {
        this.db = db;
        this.user = user;
        this.transferOutDocCollection = this.db.use(map.inventory.TransferOutDoc);
        var StorageManager = require('./storage-manager');
        this.storageManager = new StorageManager(db, user);

        var ArticleVariantManager = require('../core/article/article-variant-manager');
        this.articleVariantManager = new ArticleVariantManager(db, user);

        var InventoryManager = require('./inventory-manager');
        this.inventoryManager = new InventoryManager(db, user);

        var TransferOutDocManager = require('./transfer-out-doc-manager');
        this.transferOutDocManager = new TransferOutDocManager(db, user);

        var ModuleManager = require('../core/module-manager');
        this.moduleManager = new ModuleManager(db, user);
    }

    read(paging) {
        var _paging = Object.assign({
            page: 1,
            size: 20,
            order: '_id',
            asc: true
        }, paging);

        return new Promise((resolve, reject) => {
            var regexModuleId = new RegExp(moduleId, "i");
            var filter = {
                _deleted: false,
                'code': {
                    '$regex': regexModuleId
                }
            };
            var query = _paging.keyword ? {
                '$and': [filter]
            } : filter;

            if (_paging.keyword) {
                var regex = new RegExp(_paging.keyword, "i");
                var filterCode = {
                    'code': {
                        '$regex': regex
                    }
                };
                var $or = {
                    '$or': [filterCode]
                };

                query['$and'].push($or);
            }

            this.transferOutDocCollection
                .where(query)
                .page(_paging.page, _paging.size)
                .orderBy(_paging.order, _paging.asc)
                .execute()
                .then(transferOutDocs => {
                    resolve(transferOutDocs);
                })
                .catch(e => {
                    reject(e);
                });
        });
    }

    getById(id) {
        return new Promise((resolve, reject) => {
            var query = {
                _id: new ObjectId(id),
                _deleted: false
            };
            this.getSingleByQuery(query)
                .then(transferOutDoc => {
                    resolve(transferOutDoc);
                })
                .catch(e => {
                    reject(e);
                });
        });
    }

    getByIdOrDefault(id) {
        return new Promise((resolve, reject) => {
            var query = {
                _id: new ObjectId(id),
                _deleted: false
            };
            this.getSingleOrDefaultByQuery(query)
                .then(transferOutDoc => {
                    resolve(transferOutDoc);
                })
                .catch(e => {
                    reject(e);
                });
        });
    }

    getSingleByQuery(query) {
        return new Promise((resolve, reject) => {
            this.transferOutDocCollection
                .single(query)
                .then(transferOutDoc => {
                    resolve(transferOutDoc);
                })
                .catch(e => {
                    reject(e);
                });
        })
    }

    getSingleOrDefaultByQuery(query) {
        return new Promise((resolve, reject) => {
            this.transferOutDocCollection
                .singleOrDefault(query)
                .then(transferOutDoc => {
                    resolve(transferOutDoc);
                })
                .catch(e => {
                    reject(e);
                });
        })
    }

    create(transferOutDoc) {
        return new Promise((resolve, reject) => {
            this._validate(transferOutDoc)
                .then(validTransferOutDoc => {
                    validTransferOutDoc.code = generateCode(moduleId);
                    this.transferOutDocManager.create(validTransferOutDoc)
                        .then(id => {
                            resolve(id);
                        })
                        .catch(e => {
                            reject(e);
                        })
                })
                .catch(e => {
                    reject(e);
                })

        });
    }

    update(transferOutDoc) {
        return new Promise((resolve, reject) => {
            this._validate(transferOutDoc)
                .then(validTransferOutDoc => {
                    this.transferOutDocManager.update(validTransferOutDoc)
                        .then(id => {
                            resolve(id);
                        })
                        .catch(ex => {
                            reject(ex);
                        })
                })
                .catch(e => {
                    reject(e);
                })
        });
    }

    delete(transferOutDoc) {
        return new Promise((resolve, reject) => {
            this._validate(transferOutDoc)
                .then(validTransferOutDoc => {
                    validTransferOutDoc._deleted = true;
                    this.transferOutDocManager.update(validTransferOutDoc)
                        .then(id => {
                            resolve(id);
                        })
                        .catch(e => {
                            reject(e);
                        })
                })
                .catch(e => {
                    reject(e);
                })
        });
    }

    _validate(transferOutDoc) {
        return new Promise((resolve, reject) => {
            var valid = transferOutDoc;
            this.moduleManager.getByCode(moduleId)
                .then(module => {
                    var config = module.config;
                    if (!valid.sourceId || valid.sourceId == '')
                        errors["sourceId"] = "sourceId is required";
                    else {
                        if (config) {
                            if (config.source) {
                                var isAny = false;
                                if (config.source.type == "selection") {
                                    for (var sourceId of config.source.value) {
                                        if (sourceId.toString() == valid.sourceId.toString()) {
                                            isAny = true;
                                            break;
                                        }
                                    }
                                }
                                else {
                                    if (config.source.value.toString() == valid.sourceId.toString())
                                        isAny = true;
                                }
                                if (!isAny)
                                    errors["sourceId"] = "sourceId is not valid";
                            }
                        }
                    }

                    if (!valid.destinationId || valid.destinationId == '')
                        errors["destinationId"] = "destinationId is required";
                    else {
                        if (config) {
                            if (config.destination) {
                                var isAny = false;
                                if (config.destination.type == "selection") {
                                    for (var destinationId of config.destination.value) {
                                        if (destinationId.toString() == valid.destinationId.toString()) {
                                            isAny = true;
                                            break;
                                        }
                                    }
                                }
                                else {
                                    if (config.destination.value.toString() == valid.destinationId.toString())
                                        isAny = true;
                                }
                                if (!isAny)
                                    errors["destinationId"] = "destinationId is not valid";
                            }
                        }
                    }
                    resolve(valid);
                })
                .catch(e => {
                    reject(new Error(`Unable to load module:${moduleId}`));
                });
        });
    }
}; <commit_msg>add validate in efr-kb-rtp<commit_after>'use strict';

// external deps
var ObjectId = require('mongodb').ObjectId;

// internal deps
require('mongodb-toolkit');
var BateeqModels = require('bateeq-models');
var generateCode = require('../../utils/code-generator');
var map = BateeqModels.map;

var TransferOutDoc = BateeqModels.inventory.TransferOutDoc;
var TransferOutItem = BateeqModels.inventory.TransferOutItem;

var moduleId = "EFR-KB/RTP";

module.exports = class TokoKirimBarangReturnManager {
    constructor(db, user) {
        this.db = db;
        this.user = user;
        this.transferOutDocCollection = this.db.use(map.inventory.TransferOutDoc);
        var StorageManager = require('./storage-manager');
        this.storageManager = new StorageManager(db, user);

        var ArticleVariantManager = require('../core/article/article-variant-manager');
        this.articleVariantManager = new ArticleVariantManager(db, user);

        var InventoryManager = require('./inventory-manager');
        this.inventoryManager = new InventoryManager(db, user);

        var TransferOutDocManager = require('./transfer-out-doc-manager');
        this.transferOutDocManager = new TransferOutDocManager(db, user);

        var ModuleManager = require('../core/module-manager');
        this.moduleManager = new ModuleManager(db, user);

        var SPKBarangManager = require('../merchandiser/efr-pk-manager');
        this.spkBarangManager = new SPKBarangManager(db, user);
    }

    read(paging) {
        var _paging = Object.assign({
            page: 1,
            size: 20,
            order: '_id',
            asc: true
        }, paging);

        return new Promise((resolve, reject) => {
            var regexModuleId = new RegExp(moduleId, "i");
            var filter = {
                _deleted: false,
                'code': {
                    '$regex': regexModuleId
                }
            };
            var query = _paging.keyword ? {
                '$and': [filter]
            } : filter;

            if (_paging.keyword) {
                var regex = new RegExp(_paging.keyword, "i");
                var filterCode = {
                    'code': {
                        '$regex': regex
                    }
                };
                var $or = {
                    '$or': [filterCode]
                };

                query['$and'].push($or);
            }

            this.transferOutDocCollection
                .where(query)
                .page(_paging.page, _paging.size)
                .orderBy(_paging.order, _paging.asc)
                .execute()
                .then(transferOutDocs => {
                    resolve(transferOutDocs);
                })
                .catch(e => {
                    reject(e);
                });
        });
    }

    getById(id) {
        return new Promise((resolve, reject) => {
            var query = {
                _id: new ObjectId(id),
                _deleted: false
            };
            this.getSingleByQuery(query)
                .then(transferOutDoc => {
                    resolve(transferOutDoc);
                })
                .catch(e => {
                    reject(e);
                });
        });
    }

    getByIdOrDefault(id) {
        return new Promise((resolve, reject) => {
            var query = {
                _id: new ObjectId(id),
                _deleted: false
            };
            this.getSingleOrDefaultByQuery(query)
                .then(transferOutDoc => {
                    resolve(transferOutDoc);
                })
                .catch(e => {
                    reject(e);
                });
        });
    }

    getByCodeOrDefault(code) {
        return new Promise((resolve, reject) => {
            var query = {
                code: code,
                _deleted: false
            };
            this.getSingleOrDefaultByQuery(query)
                .then(transferOutDoc => {
                    resolve(transferOutDoc);
                })
                .catch(e => {
                    reject(e);
                });
        });
    }

    getSingleByQuery(query) {
        return new Promise((resolve, reject) => {
            this.transferOutDocCollection
                .single(query)
                .then(transferOutDoc => {
                    resolve(transferOutDoc);
                })
                .catch(e => {
                    reject(e);
                });
        })
    }

    getSingleOrDefaultByQuery(query) {
        return new Promise((resolve, reject) => {
            this.transferOutDocCollection
                .singleOrDefault(query)
                .then(transferOutDoc => {
                    resolve(transferOutDoc);
                })
                .catch(e => {
                    reject(e);
                });
        })
    }

    create(transferOutDoc) {
        return new Promise((resolve, reject) => {
            this._validate(transferOutDoc)
                .then(validTransferOutDoc => {
                    validTransferOutDoc.code = generateCode(moduleId);
                    this.transferOutDocManager.create(validTransferOutDoc)
                        .then(id => {
                            resolve(id);
                        })
                        .catch(e => {
                            reject(e);
                        })
                })
                .catch(e => {
                    reject(e);
                })

        });
    }

    update(transferOutDoc) {
        return new Promise((resolve, reject) => {
            this._validate(transferOutDoc)
                .then(validTransferOutDoc => {
                    this.transferOutDocManager.update(validTransferOutDoc)
                        .then(id => {
                            resolve(id);
                        })
                        .catch(ex => {
                            reject(ex);
                        })
                })
                .catch(e => {
                    reject(e);
                })
        });
    }

    delete(transferOutDoc) {
        return new Promise((resolve, reject) => {
            this._validate(transferOutDoc)
                .then(validTransferOutDoc => {
                    validTransferOutDoc._deleted = true;
                    this.transferOutDocManager.update(validTransferOutDoc)
                        .then(id => {
                            resolve(id);
                        })
                        .catch(e => {
                            reject(e);
                        })
                })
                .catch(e => {
                    reject(e);
                })
        });
    }

    _validate(transferOutDoc) {
        var errors = {};
        return new Promise((resolve, reject) => {
            var valid = transferOutDoc;
            var getSpk;
            this.moduleManager.getByCode(moduleId)
                .then(module => {
                    var config = module.config;
                    if (!valid.sourceId || valid.sourceId == '')
                        errors["sourceId"] = "sourceId is required";
                    else {
                        if (config) {
                            if (config.source) {
                                var isAny = false;
                                if (config.source.type == "selection") {
                                    for (var sourceId of config.source.value) {
                                        if (sourceId.toString() == valid.sourceId.toString()) {
                                            isAny = true;
                                            break;
                                        }
                                    }
                                }
                                else {
                                    if (config.source.value.toString() == valid.sourceId.toString())
                                        isAny = true;
                                }
                                if (!isAny)
                                    errors["sourceId"] = "sourceId is not valid";
                            }
                        }
                    }

                    if (!valid.destinationId || valid.destinationId == '')
                        errors["destinationId"] = "destinationId is required";
                    else {
                        if (config) {
                            if (config.destination) {
                                var isAny = false;
                                if (config.destination.type == "selection") {
                                    for (var destinationId of config.destination.value) {
                                        if (destinationId.toString() == valid.destinationId.toString()) {
                                            isAny = true;
                                            break;
                                        }
                                    }
                                }
                                else {
                                    if (config.destination.value.toString() == valid.destinationId.toString())
                                        isAny = true;
                                }
                                if (!isAny)
                                    errors["destinationId"] = "destinationId is not valid";
                            }
                        }
                    }
                    if (!valid.reference) {
                        errors["reference"] = "reference is required";
                    }
                    else {
                        getSpk = this.spkBarangManager.getByPackingList(valid.reference);
                    }
                    var getItem = [];
                    if (valid.items && valid.items.length > 0) {
                        for (var item of valid.items) {
                            getItem.push(this.inventoryManager.getByStorageIdAndArticleVarianIdOrDefault(valid.sourceId, item.articleVariantId))
                        }
                    }
                    else {
                        errors["items"] = "items is required";
                    }
                    Promise.all([getSpk].concat(getItem))
                        .then(results => {
                            var index = 0;
                            var itemErrors = [];
                            var itemError = {};

                            var dataSpk = results[0];
                            if (!dataSpk) {
                                errors["reference"] = "reference not found";
                            }
                            var items = results.slice(1, results.length)
                            if (items.length > 0) {
                                for (var item of valid.items) {
                                    if (items[index] == null) {
                                        var inventoryQuantity = 0;
                                    } else {
                                        var inventoryQuantity = items[index].quantity;
                                    }
                                    index++;
                                    if (item.quantity > inventoryQuantity) {
                                        itemError["quantity"] = "Tidak bisa simpan jika Quantity Pengiriman > Quantity Stock";
                                    }
                                    itemErrors.push(itemError);
                                }
                            }
                            for (var itemError of itemErrors) {
                                for (var prop in itemError) {
                                    errors.items = itemErrors;
                                    break;
                                }
                                if (errors.items)
                                    break;
                            }
                            for (var prop in errors) {
                                var ValidationError = require('../../validation-error');
                                reject(new ValidationError('data does not pass validation', errors));
                            }
                            resolve(valid);
                        }).catch(e => {
                            reject(e);
                        })
                })
                .catch(e => {
                    reject(e);
                });
        });
    }
}; <|endoftext|>


<commit_before>import ns from 'imajs/client/core/namespace.js';

ns.namespace('Core.Page');

/**
 * Page manager for controller.
 *
 * @class Manager
 * @implements Core.Interface.PageManager
 * @namespace Core.Page
 * @module Core
 * @submodule Core.Page
 */
export default class Manager extends ns.Core.Interface.PageManager {

	/**
	 * @method constructor
	 * @constructor
	 * @param {Core.Page.Factory} pageFactory
	 * @param {Core.Interface.PageRender} pageRender
	 * @param {Core.Interface.PageStateManager} stateManager
	 * @param {Core.Interface.Window} window
	 * @param {Core.Interface.EventBus} eventBus
	 */
	constructor(pageFactory, pageRender, stateManager, window, eventBus) {
		super();

		/**
		 * @private
		 * @property _pageFactory
		 * @type {Core.Page.Factory}
		 * @default pageFactory
		 */
		this._pageFactory = pageFactory;

		/**
		 * @property _pageRender
		 * @private
		 * @type {Core.Abstract.PageRender}
		 * @default pageRender
		 */
		this._pageRender = pageRender;

		/**
		 * @private
		 * @property _stateManager
		 * @type {Core.Interface.PageStateManager}
		 * @default stateManager
		 */
		this._stateManager = stateManager;

		/**
		 * @private
		 * @property _window
		 * @type {Core.Interface.Window}
		 * @default window
		 */
		this._window = window;

		/**
		 * @private
		 * @property _eventBus
		 * @type {Core.Interface.EventBus}
		 * @default eventBus
		 */
		this._eventBus = eventBus;

		/**
		 * @private
		 * @property _lastManagedPage
		 * @type {Object<string, *>}
		 */
		this._lastManagedPage = {
			controller: null,
			controllerInstance: null,
			decoratedController: null,
			view: null,
			viewInstance: null,
			options: null,
			params: null
		};

	}

	/**
	 * Manager controller with params.
	 *
	 * @inheritDoc
	 * @override
	 * @method manage
	 * @param {string|function} controller
	 * @param {string|function} view
	 * @param {{onlyUpdate: boolean}} options
	 * @param {Object<string, string>=} [params={}] The route parameters.
	 * @return {Promise}
	 */
	manage(controller, view, options, params = {}) {
		this._preManage(options);

		if (this._hasOnlyUpdate(controller, view, options)) {
			return (
				this._pageRender
					.update(this._lastManagedPage.decoratedController, params)
					.then(() => this._postManage(options))
			);
		}

		var controllerInstance = this._pageFactory.createController(controller);
		var decoratedController = this._pageFactory.decorateController(controllerInstance);
		var viewInstance = this._pageFactory.createView(view);

		this._destroyController();
		this._initController(controllerInstance, params);
		this._lastManagedPage = {
			controller,
			controllerInstance,
			decoratedController,
			view,
			viewInstance,
			options,
			params
		};

		return (
			this._pageRender
				.mount(decoratedController, viewInstance)
				.then(() => this._postManage(options))
		);
	}

	/**
	 * Scroll page to defined vertical and horizontal values.
	 *
	 * Scrolling is async.
	 *
	 * @inheritDoc
	 * @override
	 * @method scrollTo
	 * @param {number} [x=0] x is the pixel along the horizontal axis of the document
	 * @param {number} [y=0] y is the pixel along the vertical axis of the document
	 */
	scrollTo(x = 0, y = 0) {
		setTimeout(() => {
			this._window.scrollTo(x, y);
		}, 0);
	}

	/**
	 * Initialization manager.
	 *
	 * @inheritDoc
	 * @override
	 * @method init
	 */
	init() {
		this._lastManagedPage = {
			controller: null,
			controllerInstance: null,
			decoratedController: null,
			view: null,
			viewInstance: null,
			options: null,
			params: null
		};

		this._stateManager.onChange = (newState) => this._onChangeStateHandler(newState);
		this._eventBus.listenAll(this._window.getWindow(), (e) => this._onCustomEventHandler(e));
	}

	/**
	 * Initializes the provided controller using the provided parameters.
	 *
	 * @private
	 * @method _initController
	 * @param {Core.Abstract.Controller} controller The controller to initialize.
	 * @param {Object<string, *>=} params Parameters to use to initialize
	 *        the controller.
	 */
	_initController(controller, params) {
		controller.setRouteParams(params);
		controller.setStateManager(this._stateManager);
		controller.init();
	}

	/**
	 * Destroy current page controller.
	 *
	 * @private
	 * @method _destroyController
	 */
	_destroyController() {
		var controllerInstance = this._lastManagedPage.controllerInstance;

		if (controllerInstance) {
			controllerInstance.destroy();
			controllerInstance.setStateManager(null);
			this._pageRender.unmount();
			this._lastManagedPage.controllerInstance = null;
		}
	}

	/**
	 * On change handler for state.
	 *
	 * @private
	 * @method _onChangeStateHandler
	 */
	_onChangeStateHandler(state) {
		if (this._lastManagedPage.controllerInstance) {
			this._pageRender.setState(state);
		}
	}

	/**
	 * On custom event handler.
	 *
	 * It calls listener in the active controller. Name of listener is defined by prefix 'on' and event name.
	 * If event name is 'toggle', listener should be 'onToggle'.
	 *
	 * @private
	 * @method _onCustomEventHandler
	 * @param {CustomEvent} event
	 */
	_onCustomEventHandler(event) {
		var eventName = event.detail.eventName;
		var onEventName = 'on' + eventName.charAt(0).toUpperCase() + eventName.slice(1);
		var eventData = event.detail.data;
		var controllerInstance = this._lastManagedPage.controllerInstance;

		if (controllerInstance) {

			if (typeof controllerInstance[onEventName] === 'function') {
				controllerInstance[onEventName](eventData);
			} else {
				console.warn(`The active controller has no listener for the encountered` +
						` event '${eventName}'. Check your event name for typos, or` +
						` create an '${onEventName}' event listener method on the active` +
						` controller or add an event listener that stops the propagation` +
						` of this event to an ancestor component of the component that fired this event.`);
			}
		}
	}

	/**
	 * Return true if manager has to update last managed controller and view.
	 *
	 * @private
	 * @method _hasOnlyUpdate
	 * @param {string|function} controller
	 * @param {string|function} view
	 * @param {{onlyUpdate: boolean}} options
	 * @return {boolean}
	 */
	_hasOnlyUpdate(controller, view, options) {
		return options.onlyUpdate &&
				this._lastManagedPage.controller === controller &&
				this._lastManagedPage.view === view;
	}

	/**
	 * Make defined instruction as scroll for current page options before than
	 * change page.
	 *
	 * @private
	 * @method _preManage
	 * @param {{onlyUpdate: boolean, autoScroll: boolean}} options
	 */
	_preManage(options) {
		if (options.autoScroll) {
			this.scrollTo();
		}
	}

	/**
	 * Make defined instruction for current page options after that
	 * changed page.
	 *
	 * @private
	 * @method _postManage
	 * @param {{onlyUpdate: boolean, autoScroll: boolean}} options
	 */
	_postManage(options) {}

}

ns.Core.Page.Manager = Manager;
<commit_msg>#19 controller update method receive last params<commit_after>import ns from 'imajs/client/core/namespace.js';

ns.namespace('Core.Page');

/**
 * Page manager for controller.
 *
 * @class Manager
 * @implements Core.Interface.PageManager
 * @namespace Core.Page
 * @module Core
 * @submodule Core.Page
 */
export default class Manager extends ns.Core.Interface.PageManager {

	/**
	 * @method constructor
	 * @constructor
	 * @param {Core.Page.Factory} pageFactory
	 * @param {Core.Interface.PageRender} pageRender
	 * @param {Core.Interface.PageStateManager} stateManager
	 * @param {Core.Interface.Window} window
	 * @param {Core.Interface.EventBus} eventBus
	 */
	constructor(pageFactory, pageRender, stateManager, window, eventBus) {
		super();

		/**
		 * @private
		 * @property _pageFactory
		 * @type {Core.Page.Factory}
		 * @default pageFactory
		 */
		this._pageFactory = pageFactory;

		/**
		 * @property _pageRender
		 * @private
		 * @type {Core.Abstract.PageRender}
		 * @default pageRender
		 */
		this._pageRender = pageRender;

		/**
		 * @private
		 * @property _stateManager
		 * @type {Core.Interface.PageStateManager}
		 * @default stateManager
		 */
		this._stateManager = stateManager;

		/**
		 * @private
		 * @property _window
		 * @type {Core.Interface.Window}
		 * @default window
		 */
		this._window = window;

		/**
		 * @private
		 * @property _eventBus
		 * @type {Core.Interface.EventBus}
		 * @default eventBus
		 */
		this._eventBus = eventBus;

		/**
		 * @private
		 * @property _lastManagedPage
		 * @type {Object<string, *>}
		 */
		this._lastManagedPage = {
			controller: null,
			controllerInstance: null,
			decoratedController: null,
			view: null,
			viewInstance: null,
			options: null,
			params: null
		};

	}

	/**
	 * Manager controller with params.
	 *
	 * @inheritDoc
	 * @override
	 * @method manage
	 * @param {string|function} controller
	 * @param {string|function} view
	 * @param {{onlyUpdate: boolean}} options
	 * @param {Object<string, string>=} [params={}] The route parameters.
	 * @return {Promise}
	 */
	manage(controller, view, options, params = {}) {
		this._preManage(options);

		if (this._hasOnlyUpdate(controller, view, options)) {
			var lastDecoratedController = this._lastManagedPage.decoratedController;
			var lastRouteParams = lastDecoratedController.getRouteParams();

			lastDecoratedController.setRouteParams(params);

			return (
				this._pageRender
					.update(lastDecoratedController, lastRouteParams)
					.then(() => this._postManage(options))
			);
		}

		var controllerInstance = this._pageFactory.createController(controller);
		var decoratedController = this._pageFactory.decorateController(controllerInstance);
		var viewInstance = this._pageFactory.createView(view);

		this._destroyController();
		this._initController(controllerInstance, params);
		this._lastManagedPage = {
			controller,
			controllerInstance,
			decoratedController,
			view,
			viewInstance,
			options,
			params
		};

		return (
			this._pageRender
				.mount(decoratedController, viewInstance)
				.then(() => this._postManage(options))
		);
	}

	/**
	 * Scroll page to defined vertical and horizontal values.
	 *
	 * Scrolling is async.
	 *
	 * @inheritDoc
	 * @override
	 * @method scrollTo
	 * @param {number} [x=0] x is the pixel along the horizontal axis of the document
	 * @param {number} [y=0] y is the pixel along the vertical axis of the document
	 */
	scrollTo(x = 0, y = 0) {
		setTimeout(() => {
			this._window.scrollTo(x, y);
		}, 0);
	}

	/**
	 * Initialization manager.
	 *
	 * @inheritDoc
	 * @override
	 * @method init
	 */
	init() {
		this._lastManagedPage = {
			controller: null,
			controllerInstance: null,
			decoratedController: null,
			view: null,
			viewInstance: null,
			options: null,
			params: null
		};

		this._stateManager.onChange = (newState) => this._onChangeStateHandler(newState);
		this._eventBus.listenAll(this._window.getWindow(), (e) => this._onCustomEventHandler(e));
	}

	/**
	 * Initializes the provided controller using the provided parameters.
	 *
	 * @private
	 * @method _initController
	 * @param {Core.Abstract.Controller} controller The controller to initialize.
	 * @param {Object<string, *>=} params Parameters to use to initialize
	 *        the controller.
	 */
	_initController(controller, params) {
		controller.setRouteParams(params);
		controller.setStateManager(this._stateManager);
		controller.init();
	}

	/**
	 * Destroy current page controller.
	 *
	 * @private
	 * @method _destroyController
	 */
	_destroyController() {
		var controllerInstance = this._lastManagedPage.controllerInstance;

		if (controllerInstance) {
			controllerInstance.destroy();
			controllerInstance.setStateManager(null);
			this._pageRender.unmount();
			this._lastManagedPage.controllerInstance = null;
		}
	}

	/**
	 * On change handler for state.
	 *
	 * @private
	 * @method _onChangeStateHandler
	 */
	_onChangeStateHandler(state) {
		if (this._lastManagedPage.controllerInstance) {
			this._pageRender.setState(state);
		}
	}

	/**
	 * On custom event handler.
	 *
	 * It calls listener in the active controller. Name of listener is defined by prefix 'on' and event name.
	 * If event name is 'toggle', listener should be 'onToggle'.
	 *
	 * @private
	 * @method _onCustomEventHandler
	 * @param {CustomEvent} event
	 */
	_onCustomEventHandler(event) {
		var eventName = event.detail.eventName;
		var onEventName = 'on' + eventName.charAt(0).toUpperCase() + eventName.slice(1);
		var eventData = event.detail.data;
		var controllerInstance = this._lastManagedPage.controllerInstance;

		if (controllerInstance) {

			if (typeof controllerInstance[onEventName] === 'function') {
				controllerInstance[onEventName](eventData);
			} else {
				console.warn(`The active controller has no listener for the encountered` +
						` event '${eventName}'. Check your event name for typos, or` +
						` create an '${onEventName}' event listener method on the active` +
						` controller or add an event listener that stops the propagation` +
						` of this event to an ancestor component of the component that fired this event.`);
			}
		}
	}

	/**
	 * Return true if manager has to update last managed controller and view.
	 *
	 * @private
	 * @method _hasOnlyUpdate
	 * @param {string|function} controller
	 * @param {string|function} view
	 * @param {{onlyUpdate: boolean}} options
	 * @return {boolean}
	 */
	_hasOnlyUpdate(controller, view, options) {
		return options.onlyUpdate &&
				this._lastManagedPage.controller === controller &&
				this._lastManagedPage.view === view;
	}

	/**
	 * Make defined instruction as scroll for current page options before than
	 * change page.
	 *
	 * @private
	 * @method _preManage
	 * @param {{onlyUpdate: boolean, autoScroll: boolean}} options
	 */
	_preManage(options) {
		if (options.autoScroll) {
			this.scrollTo();
		}
	}

	/**
	 * Make defined instruction for current page options after that
	 * changed page.
	 *
	 * @private
	 * @method _postManage
	 * @param {{onlyUpdate: boolean, autoScroll: boolean}} options
	 */
	_postManage(options) {}

}

ns.Core.Page.Manager = Manager;
<|endoftext|>


<commit_before>/* eslint-disable import/no-commonjs */
const fs = require('fs');
const path = require('path');

module.exports = {
  mergeStrategy: { toSameBranch: ['master'] },
  versionUpdated: ({ version, dir }) => {
    fs.writeFileSync(
      path.resolve(dir, 'src', 'lib', 'version.ts'),
      `export default '${version}';\n`
    );
  },
  beforeCommitChanges: ({ exec }) => {
    exec('yarn doctoc');
  },
  pullRequestTeamReviewer: ['instantsearch-for-websites'],
  slack: {
    // disable slack notification for `prepared` and `releaseStart` lifecycle.
    // Ship.js will send slack message only for `releaseSuccess`.
    prepared: null,
    releaseStart: null,
    releaseSuccess: ({
      appName,
      version,
      releaseTag,
      latestCommitHash,
      latestCommitUrl,
      repoURL,
    }) => ({
      pretext: [
        `:tada: Successfully released *${appName}@${version}*`,
        '',
        `Make sure to run \`yarn run release-templates\` in \`create-instantsearch-app\`.`,
      ].join('\n'),
      fields: [
        {
          title: 'Branch',
          value: 'master',
          short: true,
        },
        {
          title: 'Commit',
          value: `*<${latestCommitUrl}|${latestCommitHash}>*`,
          short: true,
        },
        {
          title: 'Version',
          value: version,
          short: true,
        },
        {
          title: 'Release',
          value: `${repoURL}/releases/tag/${releaseTag}`,
        },
      ],
    }),
  },
};
<commit_msg>chore(release): use tagName instead of releaseTag (#4298)<commit_after>/* eslint-disable import/no-commonjs */
const fs = require('fs');
const path = require('path');

module.exports = {
  mergeStrategy: { toSameBranch: ['master'] },
  versionUpdated: ({ version, dir }) => {
    fs.writeFileSync(
      path.resolve(dir, 'src', 'lib', 'version.ts'),
      `export default '${version}';\n`
    );
  },
  beforeCommitChanges: ({ exec }) => {
    exec('yarn doctoc');
  },
  pullRequestTeamReviewer: ['instantsearch-for-websites'],
  slack: {
    // disable slack notification for `prepared` and `releaseStart` lifecycle.
    // Ship.js will send slack message only for `releaseSuccess`.
    prepared: null,
    releaseStart: null,
    releaseSuccess: ({
      appName,
      version,
      tagName,
      latestCommitHash,
      latestCommitUrl,
      repoURL,
    }) => ({
      pretext: [
        `:tada: Successfully released *${appName}@${version}*`,
        '',
        `Make sure to run \`yarn run release-templates\` in \`create-instantsearch-app\`.`,
      ].join('\n'),
      fields: [
        {
          title: 'Branch',
          value: 'master',
          short: true,
        },
        {
          title: 'Commit',
          value: `*<${latestCommitUrl}|${latestCommitHash}>*`,
          short: true,
        },
        {
          title: 'Version',
          value: version,
          short: true,
        },
        {
          title: 'Release',
          value: `${repoURL}/releases/tag/${tagName}`,
        },
      ],
    }),
  },
};
<|endoftext|>


<commit_before>document.getElementById("id_logic_level_version").innerHTML="Logic level version 2017.10.25.0";
window.addEventListener('deviceorientation', ondeviceorientation);
window.addEventListener('devicemotion', ondevicemotion);
//-------------------------------------------------------
 function ondeviceorientation(event) {
	document.getElementById("id_alpha").innerHTML = Math.round(event.alpha * 10) / 10;
	document.getElementById("id_beta").innerHTML = Math.round(event.beta * 10) / 10;
	document.getElementById("id_gamma").innerHTML = Math.round(event.gamma * 10) / 10;

}
//-------------------------------------------------------
function ondevicemotion(event)
{
	document.getElementById("id_acc").innerHTML = Math.round(event.acceleration.x * 10) / 10 + "" + Math.round(event.acceleration.y * 10) / 10 + "" + Math.round(event.acceleration.x * 10) / 10;
	document.getElementById("id_acc_g").innerHTML = Math.round(event.accelerationIncludingGravity.x * 10) / 10 + "" + Math.round(event.accelerationIncludingGravity.y * 10) / 10 + "" + Math.round(event.accelerationIncludingGravity.x * 10) / 10;

}<commit_msg>variabila<commit_after>document.getElementById("id_logic_level_version").innerHTML="Logic level version 2017.10.25.0";
window.addEventListener('deviceorientation', ondeviceorientation);
window.addEventListener('devicemotion', ondevicemotion);
//-------------------------------------------------------
 function ondeviceorientation(event) {
	document.getElementById("id_alpha").innerHTML = Math.round(event.alpha * 10) / 10;
	document.getElementById("id_beta").innerHTML = Math.round(event.beta * 10) / 10;
	document.getElementById("id_gamma").innerHTML = Math.round(event.gamma * 10) / 10;

}
//-------------------------------------------------------
function ondevicemotion(event)
{
	document.getElementById("id_acc").innerHTML = "Acc = " Math.round(event.acceleration.x * 10) / 10 + "" + Math.round(event.acceleration.y * 10) / 10 + "" + Math.round(event.acceleration.x * 10) / 10;
	var ag = event.accelerationIncludingGravity;
	var x_incl = Math.atan(ag.x / ag.z);
	var y_incl = Math.atan(ag.y / ag.z);

	document.getElementById("id_acc_g").innerHTML = "AccG = " Math.round(event.accelerationIncludingGravity.x * 10) / 10 + "" + Math.round(event.accelerationIncludingGravity.y * 10) / 10 + "incl_x = " x_incl + "incl+y = " + y+incl;

}<|endoftext|>


<commit_before>'use strict';

let Response = require('../../tools/response');
let mongoose = require('mongoose');
let async = require('async');

module.exports = function (projectSchema) {
    // Tools methods
    projectSchema.statics.create = function (params, callback) {
        let Self = this;

        params.kanban = null;
        params.userStories = [];

        let project = new Self(params);

        project.save(callback);
    };

    projectSchema.statics.edit = function (params, callback) {
        let Self = this;

        async.waterfall([
            (next) => Self.findOne({'_id': params._id}, next),
            (project, next) => {
                if (!project)
                    next('No project found !');
                else
                    Self.update({_id: params._id}, {$set: params}, next);
            }
        ], (err, project) => {
            if (err)
                return callback(err);

            callback(null, project);
        });
    };

    projectSchema.statics.addUser = function (params, callback) {
        let Self = this;

        async.waterfall([
            (next) => Self.findOne({'_id': params._id}, next),
            (project, next) => {
                if (!project)
                    next('No project found !');
                else
                    Self.update({_id: params._id}, {$push: {users: params.userId}}, next);
            }
        ], (err, project) => {
            if (err)
                return callback(err);

            callback(null, project);
        });
    };

    projectSchema.statics.getById = function(params, callback) {
        mongoose.model('Project')
            .findById(params.id)
            .exec(callback);
    };

    projectSchema.statics.getAll = function(params, callback) {
        mongoose.model('Project')
            .find()
            .exec(callback);
    };

    // Verifications methods
    function checkParametersForCreate(req, res, callback) {
        let parametersOk = false;

        if (!req.body || !req.body.name) {
            Response.missing(res, 'name', -11);
        } else if (!req.body.description) {
            Response.missing(res, 'description', -12);
        } else {
            parametersOk = true;
        }

        if (parametersOk) {
            callback();
        } else {
            callback({
                alreadySent: true
            });
        }
    }

    // Express calls
    projectSchema.statics.exCreate = function (req, res) {
        async.waterfall([
            (next) => checkParametersForCreate(req, res, next),
            (next) => mongoose.model('Project').create(req.body, next)
        ], (err, project) => {
            if (err && err.alreadySent) {
                return;
            }

            if (err && err.code === Response.MongoCodes.alreadyExist)
                return Response.alreadyExist(res, 'name');
            else if (err)
                return Response.insertError(res, err);

            return Response.success(res, 'Project added', project);
        });
    };

    projectSchema.statics.exEdit = function (req, res) {
        /*
         TODO: Wait for authentication to enable this code !
         if (!req.isLogged())
         return Response.notAllowed(res);
         */

        mongoose.model('Project').edit(req.body, (err) => {
            if (err)
                return Response.editError(res, err);

            return Response.success(res, 'Edit successfull', {});
        });
    };

    projectSchema.statics.exRegister = function (req, res) {
        async.waterfall([
            (next) => {
                let parametersOK = false;

                if (!req.body || !req.body.userId)
                    Response.missing(res, 'userId', -11);
                else
                    parametersOK = true;

                if (parametersOK) {
                    let params = req.body;
                    params._id = req.body.userId;
                    mongoose.model('User').exists(params, res, next);
                } else {
                    next({
                        alreadySent: true
                    });
                }
            },
            (next) => mongoose.model('Project').addUser(req.body, next)
        ], (err, project) => {
            if (err && err.alreadySent)
                return;

            if (err)
                return Response.insertError(res, err);

            return Response.success(res, 'User added', project);
        });
    };

    projectSchema.statics.exGet = function(req, res) {
        mongoose.model('Project').getById(req.params, (err, project) => {
            if (err)
                return Response.selectError(err);

            if (!project)
                return Response.resourceNotFound(res, 'project');

            Response.success(res, 'Project found !', project);
        });
    };

    projectSchema.statics.exGetAll = function (req, res) {
        mongoose.model('Project').getAll({}, (err, projects) => {
            if (err)
                return Response.selectError(err);

            if (!projects || projects.length === 0)
                return Response.resourceNotFound(res, 'projects');

            Response.success(res, 'Projects found !', projects);
        });
    };
};<commit_msg>fix(server): Fixing request body in exRegister function.<commit_after>'use strict';

let Response = require('../../tools/response');
let mongoose = require('mongoose');
let async = require('async');

module.exports = function (projectSchema) {
    // Tools methods
    projectSchema.statics.create = function (params, callback) {
        let Self = this;

        params.kanban = null;
        params.userStories = [];

        let project = new Self(params);

        project.save(callback);
    };

    projectSchema.statics.edit = function (params, callback) {
        let Self = this;

        async.waterfall([
            (next) => Self.findOne({'_id': params._id}, next),
            (project, next) => {
                if (!project)
                    next('No project found !');
                else
                    Self.update({_id: params._id}, {$set: params}, next);
            }
        ], (err, project) => {
            if (err)
                return callback(err);

            callback(null, project);
        });
    };

    projectSchema.statics.addUser = function (params, callback) {
        let Self = this;

        async.waterfall([
            (next) => Self.findOne({'_id': params._id}, next),
            (project, next) => {
                if (!project)
                    next('No project found !');
                else
                    Self.update({_id: params._id}, {$push: {users: params.userId}}, next);
            }
        ], (err, project) => {
            if (err)
                return callback(err);

            callback(null, project);
        });
    };

    projectSchema.statics.getById = function(params, callback) {
        mongoose.model('Project')
            .findById(params.id)
            .exec(callback);
    };

    projectSchema.statics.getAll = function(params, callback) {
        mongoose.model('Project')
            .find()
            .exec(callback);
    };

    // Verifications methods
    function checkParametersForCreate(req, res, callback) {
        let parametersOk = false;

        if (!req.body || !req.body.name) {
            Response.missing(res, 'name', -11);
        } else if (!req.body.description) {
            Response.missing(res, 'description', -12);
        } else {
            parametersOk = true;
        }

        if (parametersOk) {
            callback();
        } else {
            callback({
                alreadySent: true
            });
        }
    }

    // Express calls
    projectSchema.statics.exCreate = function (req, res) {
        async.waterfall([
            (next) => checkParametersForCreate(req, res, next),
            (next) => mongoose.model('Project').create(req.body, next)
        ], (err, project) => {
            if (err && err.alreadySent) {
                return;
            }

            if (err && err.code === Response.MongoCodes.alreadyExist)
                return Response.alreadyExist(res, 'name');
            else if (err)
                return Response.insertError(res, err);

            return Response.success(res, 'Project added', project);
        });
    };

    projectSchema.statics.exEdit = function (req, res) {
        /*
         TODO: Wait for authentication to enable this code !
         if (!req.isLogged())
         return Response.notAllowed(res);
         */

        mongoose.model('Project').edit(req.body, (err) => {
            if (err)
                return Response.editError(res, err);

            return Response.success(res, 'Edit successfull', {});
        });
    };

    projectSchema.statics.exRegister = function (req, res) {
        async.waterfall([
            (next) => {
                let parametersOK = false;

                if (!req.body || !req.body.userId)
                    Response.missing(res, 'userId', -11);
                else
                    parametersOK = true;

                if (parametersOK) {
                    let params = req;
                    params.body._id = req.body.userId;
                    mongoose.model('User').exists(params, res, next);
                } else {
                    next({
                        alreadySent: true
                    });
                }
            },
            (next) => mongoose.model('Project').addUser(req.body, next)
        ], (err, project) => {
            if (err && err.alreadySent)
                return;

            if (err)
                return Response.insertError(res, err);

            return Response.success(res, 'User added', project);
        });
    };

    projectSchema.statics.exGet = function(req, res) {
        mongoose.model('Project').getById(req.params, (err, project) => {
            if (err)
                return Response.selectError(err);

            if (!project)
                return Response.resourceNotFound(res, 'project');

            Response.success(res, 'Project found !', project);
        });
    };

    projectSchema.statics.exGetAll = function (req, res) {
        mongoose.model('Project').getAll({}, (err, projects) => {
            if (err)
                return Response.selectError(err);

            if (!projects || projects.length === 0)
                return Response.resourceNotFound(res, 'projects');

            Response.success(res, 'Projects found !', projects);
        });
    };
};<|endoftext|>


<commit_before>(function () {
	"use strict";

	angular.module("ngMobileDialog", []).provider("$dialog", function () {
		var vm = this;
		vm.multiple = false;
		vm.headers = {};
		vm.currentScopes = {};
		vm.$get = function ($timeout, $compile, $rootScope, $controller, $injector, $q, $http, $templateCache) {

			function Dialog(opts, modalEl) {
				this.options = opts;
				this.modalEl = modalEl;
			}

			Dialog.prototype.open = function () {
				var self = this;
				var $body = angular.element("body");
				var $backdrop = angular.element(".dialog-backdrop");

				this._loadResolves().then(function (locals) {
					try{
						var $scope = locals.$scope = locals.$scope ? locals.$scope : $rootScope.$new();
						$scope.dialogId = new Date();
						vm.currentScopes[$scope.dialogId] = $scope;

						if (self.options.controller) {
							var ctrl = $controller(self.options.controller, locals);
							self.modalEl.data("ngControllerController", ctrl);
						}

						self.modalEl.addClass("dialog");

						var $modal = $compile(self.modalEl)($scope).find(".dialog").prevObject;

						$scope.options = self.options;

						var backdrop = self.options.backdrop === false ? false : true;

						if (backdrop) {
							$backdrop.on("click", function () {
								$scope.resolve();
							});
						}

						$scope.resolve = function (result) {
							delete vm.currentScopes[$scope.dialogId];
							self.deferred.resolve(result);
							self.deferred = null;
							$modal.removeClass("active");

							$timeout(function () {
								$scope.$destroy();
								vm.currentDialog = null;
							}, 100);
						};

						$scope.$on("$destroy", function () {
							$modal.remove();
							$backdrop.remove();
							$body.off("keypress");
							$body.trigger("hidden.ngMobileDialog");
						});

						$scope.$on("$locationChangeSuccess", function () {
							$modal.removeClass("active");
						});

						$timeout(function () {
							$modal.addClass("active");
							$backdrop.addClass("in");
							$body.on("keypress", function (e) {
								if (e.keyCode === 13) {
									e.preventDefault();
								}
							});
						}, 50);
					}catch(ex){
						console.log(ex);
					}
				});

				this.deferred = $q.defer();
				return this.deferred.promise;
			};

			Dialog.prototype._loadResolves = function () {
				var values = [];
				var keys = [];

				angular.forEach(this.options.resolve || [], function (value, key) {
					keys.push(key);
					values.push(angular.isString(value) ? $injector.get(value) : $injector.invoke(value));
				});

				return $q.all(values).then(function (values) {
					var locals = {};
					angular.forEach(values, function (value, index) {
						locals[keys[index]] = value;
					});

					return locals;
				});
			};

			return {
				create: function (opts, callback) {
					if (!this.multiple && angular.element(".dialog").length) {
						return;
					}

					if (!opts.template && !opts.templateUrl) {
						throw new Error("Template or template url must be informed!");
					}

					var templateCache = null;

					if (opts.templateUrl) {
						templateCache = $templateCache.get(opts.templateUrl);

						if (templateCache) {
							setElements(templateCache);
							return;
						}
					}

					if (opts.template && !opts.templateUrl) {
						setElements(opts.template);
						return;
					}

					$http.get(opts.templateUrl, {
						headers: this.headers
					})
					.success(function(data) {
						setElements(data);
						$templateCache.put(opts.templateUrl, data);
				  	}).error(function() {
						throw new Error("Can not load dialog template from url: " + opts.templateUrl);
				  	});

					function setElements (template) {
						var backdrop = "\n

";

						var modalEl = angular.element("
");
						modalEl.html(template);

						angular.element("body").append(modalEl).append(backdrop);

						var dialog = new Dialog(opts, modalEl);

						callback(dialog);
					}
				},
				multiple: this.multiple,
				headers: this.headers,
				resolve: function (result){
					if(vm.currentScopes){
						for (var key in vm.currentScopes) {
						   if (vm.currentScopes.hasOwnProperty(key)) {
							   var obj = vm.currentScopes[key];
								obj.resolve(result);
							}
						}
					}
				}
			};
		};
	});
})();
<commit_msg>Drop jQuery dependencie<commit_after>(function () {
	"use strict";

	angular.module("ngMobileDialog", []).provider("$dialog", function () {
		var vm = this;
		vm.multiple = false;
		vm.headers = {};
		vm.currentScopes = {};
		vm.$get = function ($timeout, $compile, $rootScope, $controller, $injector, $q, $http, $templateCache) {

			function Dialog(opts, modalEl) {
				this.options = opts;
				this.modalEl = modalEl;
			}

			Dialog.prototype.open = function () {
				var self = this;
				var $body = document.body;
				var $backdrop = document.querySelector(".dialog-backdrop");

				this._loadResolves().then(function (locals) {
						var $scope = locals.$scope = locals.$scope ? locals.$scope : $rootScope.$new();
						$scope.dialogId = new Date();
						vm.currentScopes[$scope.dialogId] = $scope;

						if (self.options.controller) {
							var ctrl = $controller(self.options.controller, locals);
							self.modalEl.dataset.ngControllerController = self.options.controller;
						}

						self.modalEl.classList.add("dialog");

						var $modal = $compile(self.modalEl)($scope)[0];

						$scope.options = self.options;

						var backdrop = self.options.backdrop === false ? false : true;

						if (backdrop) {
							$backdrop.addEventListener("click", function () {
								$scope.resolve();
							});
						}

						$scope.resolve = function (result) {
							delete vm.currentScopes[$scope.dialogId];
							self.deferred.resolve(result);
							self.deferred = null;
							$modal.classList.remove("active");

							$timeout(function () {
								$scope.$destroy();
								vm.currentDialog = null;
							}, 100);
						};

						$scope.$on("$destroy", function () {
							$modal.remove();
							$backdrop.remove();
							var event = new Event("hidden.ngMobileDialog");
							$body.dispatchEvent(event);
						});

						$scope.$on("$locationChangeSuccess", function () {
							$modal.classList.remove("active");
						});

						$timeout(function () {
							$modal.classList.add("active");
							$backdrop.classList.add("in");
							$body.addEventListener("keypress", function (e) {
								if (e.keyCode === 13) {
									e.preventDefault();
								}
							});
						}, 50);
				});

				this.deferred = $q.defer();
				return this.deferred.promise;
			};

			Dialog.prototype._loadResolves = function () {
				var values = [];
				var keys = [];

				angular.forEach(this.options.resolve || [], function (value, key) {
					keys.push(key);
					values.push(angular.isString(value) ? $injector.get(value) : $injector.invoke(value));
				});

				return $q.all(values).then(function (values) {
					var locals = {};
					angular.forEach(values, function (value, index) {
						locals[keys[index]] = value;
					});

					return locals;
				});
			};

			return {
				create: function (opts, callback) {
					if (!this.multiple && document.querySelector(".dialog").length) {
						return;
					}

					if (!opts.template && !opts.templateUrl) {
						throw new Error("Template or template url must be informed!");
					}

					var templateCache = null;

					if (opts.templateUrl) {
						templateCache = $templateCache.get(opts.templateUrl);

						if (templateCache) {
							setElements(templateCache);
							return;
						}
					}

					if (opts.template && !opts.templateUrl) {
						setElements(opts.template);
						return;
					}

					$http.get(opts.templateUrl, {
						headers: this.headers
					})
					.success(function(data) {
						setElements(data);
						$templateCache.put(opts.templateUrl, data);
				  	}).error(function() {
						throw new Error("Can not load dialog template from url: " + opts.templateUrl);
				  	});

					function setElements (template) {
						var backdrop = document.createElement("div");
						backdrop.classList.add("dialog-backdrop");
						backdrop.classList.add("fade");

					        var body = document.body;

					        var modalEl = document.createElement("div");
					        modalEl.innerHTML = template;

					        modalEl.querySelector(".modal-header > button.close").dataset.ngClick = "resolve()";

						body.appendChild(modalEl);
						body.appendChild(backdrop);

						var dialog = new Dialog(opts, modalEl);

						callback(dialog);
					}
				},
				multiple: this.multiple,
				headers: this.headers,
				resolve: function (result){
					if(vm.currentScopes){
						for (var key in vm.currentScopes) {
						   if (vm.currentScopes.hasOwnProperty(key)) {
							   var obj = vm.currentScopes[key];
								obj.resolve(result);
							}
						}
					}
				}
			};
		};
	});
})();
<|endoftext|>


<commit_before>/*global jQuery */

/*
 * Create modal dialogs.
 * The dialog plugin does not work on an element.
 *
 * Syntax
 * ===============
 *  $.dialog.open(name)
 *  $.dialog.close(name)
 *  $.dialog.alert(msg)
 *  $.dialog.confirm(msg[,options])
 *
 * Promise Methods
 * ===============
 *  .onOpen(function(element){})
 *  .onClose(function(element){})
 *  .onClose(function(boolean or text of optional button){}) - confirm only.
 *  .autoClose(msecs)
 *
 * Confirm Options
 * ===============
 *  ok: "Text of OK button"
 *  cancel: "Text of Cancel button"
 *  option: "Text of optional button" - goes to the left of the Cancel button
 *    The text of the button is returned in the onClose method if clicked.
 *
 * How it Works
 * ===============
 * It creates a div with the class of "blocker fade" at the end of the body.
 * It gets a file by name that ends in ".html" and adds it to the blocker div.
 * When shown it adds the "in" class to the blocker div. It then calls onOpen
 * function where you can add behavior to the dialog. The onClose method allows
 * you to remove any event handlers and respond to a confirm dialog.
 */

(function ($) {

  // Globals
  var dialogs = {}, settings = {
    path: "",
    extension: ".html",
    replace: true,
    blocker: '

',
    confirm: {
      option_btn_start: '<button class="btn btn-warning option" type="button">',
      option_btn_end: '</button>',
      option_btn_class: 'option'
    }
  };

  // jQuery not defined.
  if (!$) {
    return;
  }

  $.dialog = (function () {
    /*
     * Close the dialog.
     */
    function close(name) {
      var dialogEl, dialog = dialogs[name].dialog;

      // If close has already been called, return.
      if (!dialog) {
        return;
      }

      // If there is a timeout, clear the timeout to stop it.
      if (dialog.timeout) {
        clearTimeout(dialog.timeout);
        dialog.timeout = null;
      }

      // Get the blocker element of the dialog.
      dialogEl = $('#' + name);

      // Hide the dialog.
      dialogEl.hide().removeClass("in");

      // Remove click handlers.
      dialogEl.find(".cancel, .ok, ." + settings.confirm.option_btn_class).off("click.dialog");

      // Remove html and all handlers if replace setting.
      dialogEl.empty();

      // Remove key handlers.
      $(document).off("keyup.dialog");
      $(document).off("keydown.dialog");

      // Run the close function.
      dialog.onClose(dialogEl);

      // Delete the open dialog object for this dialog.
      dialog = {};
    }

    /*
     * Check for the Esc key pressed. If pressed, close the dialog.
     */
    function checkEsc(name) {
      // Capture the Esc key to close the dialog.
      $(document).on("keyup.dialog", function (event) {
        if (event.keyCode === 27) {
          event.stopPropagation();
          close(name);
        }
      });
    }

    /*
     * Check for the Enter/Return key pressed. If pressed call callback function.
     */
    function checkEnter(name, callback) {
      // Capture the Enter key to close the dialog.
      $(document).on("keydown.dialog", function (event) {
        if (event.keyCode === 13) {
          event.preventDefault();
          event.stopPropagation();
          if (typeof callback === "function") {
            callback();
          }
          close(name);
        }
      });
    }

    /*
     * Show the dialog, add close behavior, and call any passed onOpen function.
     */
    function show(name) {
      var dialogEl = $('#' + name),
        dialog = dialogs[name].dialog;

      // Show the dialog.
      dialogEl.show().addClass("in");

      // Run onOpen function
      dialog.onOpen(dialogEl);

      // Check for auto close of dialog.
      dialog.autoClose();

      // Close on Esc key.
      checkEsc(name);

      // Close on Cancel button.
      dialogEl.find(".cancel, .ok, ." + settings.confirm.option_btn_class).on("click.dialog", function () {
        close(name);
      });
    }

    /*
     * Get dialog html from the server and add it to the DOM.
     */
    function get(name) {
      // Create background blocker and add id.
      var blocker = $(settings.blocker).attr("id", name);
      $.ajax(settings.path + name + settings.extension).done(function (data) {
        // Store dialog html.
        dialogs[name].html = data;
        // Add dialog html to blocker.
        blocker.append(data);
        // Add blocker to end of body.
        $("body").append(blocker);
        show(name);
      }).error(function (xhr, status) {
        console.log("Error getting dialog", name, "error:", status, xhr);
      });
    }

    /*
     * Open the dialog.
     */
    function open() {
      // If the dialog html has been added to the DOM, show the dialog, otherwise
      // get the dialog html from the server and add it to the DOM and show the
      // dialog.

      var i, a, name, dialog, onOpen, onClose, autoClose;

      // Process variable number of arguments.
      for (i = 0; i < arguments.length; i++) {
        a = arguments[i];
        if (typeof a === "string") {
          name = a;
        } else if (typeof a === "function") {
          if (!onOpen) {
            onOpen = a;
          } else {
            onClose = a;
          }
        } else if (typeof a === "number") {
          autoClose = a;
        }
      }

      // Create dialog object for dialog.
      if (!dialogs[name]) {
        dialogs[name] = {dialog: {}};
      } else if (settings.replace) {
        // Replace the html of the dialog each time it is displayed.
        $('#' + name).html(dialogs[name].html);
      }

      dialog = dialogs[name].dialog;

      // Allow the dialog object to be auto closed.
      dialog.autoClose = function (msecs) {
        msecs = msecs || autoClose;
        if (typeof msecs === "number" && !dialog.timeout) {
          this.timeout = setTimeout(function () {
            dialogs[name].dialog.timeout = null;
            close(name);
          }, msecs);
        }
        return dialog;
      };

      dialog.onOpen = function (fn) {
        var dialogEl, origFn;
        if (typeof fn === "function") {
          dialogEl = $('#' + name);
          if (dialogEl.length) {
            fn(dialogEl);
          } else if (onOpen) {
            origFn = onOpen;
            this.onOpen = function (el) {
              origFn(el);
              fn(el);
            };
          } else {
            onOpen = fn;
          }
        } else if (fn && fn.jquery && typeof onOpen === "function") {
          // Was passed a jQuery object, call the onOpen function.
          onOpen(fn);
        }
        return dialog;
      };

      dialog.onClose = function (fn) {
        var origFn;
        if (typeof fn === "function") {
          if (this.onClose) {
            origFn = this.onClose;
            this.onClose = function (el) {
              origFn(el);
              fn(el);
            };
          } else {
            this.onClose = fn;
          }
        } else if (fn && fn.jquery && typeof onClose === "function") {
          onClose(fn);
        }
        return dialog;
      };

      // Is the dialog already in the DOM?
      if ($('#' + name).length) {
        show(name);
      } else {
        get(name);
      }

      return dialog;
    }

    /*
     * Display an alert message with an OK button.
     */
    function alert() {
      var a, msg, onClose, autoClose, i;

      // Process variable number of arguments.
      for (i = 0; i < arguments.length; i++) {
        a = arguments[i];
        if (typeof a === "string") {
          msg = a;
        } else if (typeof a === "function") {
          onClose = a;
        } else if (typeof a === "number") {
          autoClose = a;
        }
      }

      function onOpen(dialogEl) {
        // Add the alert message to the alert dialog. If wider than 320 pixels change new lines to
.
        dialogEl.focus().find(".msg").html(msg.replace(/\n/g, (document.body.offsetWidth > 320 ? "
" : " ")));
        checkEnter("alert");
      }

      return open("alert", onOpen, onClose, autoClose);
    }

    /*
     * Display a dialog with a message and cancel and ok buttons.
     * If the user clicks the OK button, pass true to the callback
     * function. Otherwise pass false to the callback function.
     */
    function confirm() {
      var bReturn = false, a, msg, i, options = {
        ok: undefined,
        cancel: undefined,
        option: undefined,
        onOpen: undefined,
        onClose: undefined
      };

      // Process variable number of arguments.
      for (i = 0; i < arguments.length; i++) {
        a = arguments[i];
        if (typeof a === "string") {
          if (!msg) {
            msg = a;
          } else if (!options.ok) {
            options.ok = a;
          } else {
            options.cancel = a;
          }
        } else if (typeof a === "function") {
          options.onClose = a;
        } else {
          options = $.extend(options, a);
        }
      }

      function onOpen(dialogEl) {
        var dialog_ok_btn = dialogEl.find(".ok"), dialog_cancel_btn = dialogEl.find(".cancel"), dialog_option_btn;

        // Set OK button text.
        if (options.ok) {
          dialog_ok_btn.text(options.ok);
        } else {
          dialog_ok_btn.text(dialog_ok_btn.attr("data-default"));
        }

        // Set Cancel button text.
        if (options.cancel) {
          dialog_cancel_btn.text(options.cancel);
        } else {
          dialog_cancel_btn.text(dialog_cancel_btn.attr("data-default"));
        }

        // Change the message. If wider than 320 pixels change new lines to
.
        dialogEl.focus().find(".msg").html(msg.replace(/\n/g, (document.body.offsetWidth > 320 ? "
" : " ")));

        // If the user clicks ok, set the return value.
        dialogEl.find(".ok").on("click.confirm", function () {
          bReturn = true;
        });

        // Add option button if requested.
        if (options.option) {
          // Create option button.
          dialog_option_btn = $(settings.confirm.option_btn_start + options.option + settings.confirm.option_btn_end);
          // Add it to the form.
          dialog_cancel_btn.before(dialog_option_btn);
          // If the user clicks ok, set the return value to the option button text.
          dialog_option_btn.on("click.confirm", function (event) {
            event.stopPropagation();
            // Return the text of the button.
            bReturn = options.option;
          });
        }

        // If the user presses the Enter key, set the return value as if they
        // clicked the OK button.
        checkEnter("confirm", function () {
          bReturn = true;
        });

        if (typeof options.onOpen === "function") {
          options.onOpen(dialogEl);
        }

        return dialogs.confirm.dialog;
      }

      function onClose(dialogEl) {
        if (typeof dialogEl === "function") {
          options.onClose = dialogEl;
          return dialogs.confirm.dialog;
        }

        // remove click handlers and option button.
        dialogEl.find(".ok, ." + settings.confirm.option_btn_class).off("click.confirm");
        if (options.option && !settings.replace) {
          dialogEl.find(settings.confirm.option_btn_class).remove();
        }

        // Call the callback function with a return value.
        if (typeof options.onClose === "function") {
          options.onClose(bReturn);
        }
        return dialogs.confirm.dialog;
      }

      // Overwrite onClose method with confirm onClose method.
      open("confirm", onOpen).onClose = onClose;
      return dialogs.confirm.dialog;
    }

    /*
     * Change path and extension settings.
     */
    function set(obj) {
      settings = $.extend(true, settings, obj);
    }

    /*
     * Helper functions to determine the type of value passed by confirm.onClose.
     */
    function isOk(val) {
      return typeof val === "boolean" && val;
    }

    function isCancel(val) {
      return typeof val === "boolean" && !val;
    }

    function isOption(val) {
      return typeof val === "string" && val ? true : false;
    }

    // Return public methods.
    return {
      open: open,
      close: close,
      alert: alert,
      confirm: confirm,
      set: set,
      isOk: isOk,
      isCancel: isCancel,
      isOption: isOption
    };
  }());
}(jQuery));
<commit_msg>Add use strict<commit_after>/*global jQuery */

/*
 * Create modal dialogs.
 * The dialog plugin does not work on an element.
 *
 * Syntax
 * ===============
 *  $.dialog.open(name)
 *  $.dialog.close(name)
 *  $.dialog.alert(msg)
 *  $.dialog.confirm(msg[,options])
 *
 * Promise Methods
 * ===============
 *  .onOpen(function(element){})
 *  .onClose(function(element){})
 *  .onClose(function(boolean or text of optional button){}) - confirm only.
 *  .autoClose(msecs)
 *
 * Confirm Options
 * ===============
 *  ok: "Text of OK button"
 *  cancel: "Text of Cancel button"
 *  option: "Text of optional button" - goes to the left of the Cancel button
 *    The text of the button is returned in the onClose method if clicked.
 *
 * How it Works
 * ===============
 * It creates a div with the class of "blocker fade" at the end of the body.
 * It gets a file by name that ends in ".html" and adds it to the blocker div.
 * When shown it adds the "in" class to the blocker div. It then calls onOpen
 * function where you can add behavior to the dialog. The onClose method allows
 * you to remove any event handlers and respond to a confirm dialog.
 */

(function ($) {
  'use strict';

  // Globals
  var dialogs = {}, settings = {
    path: "",
    extension: ".html",
    replace: true,
    blocker: '

',
    confirm: {
      option_btn_start: '<button class="btn btn-warning option" type="button">',
      option_btn_end: '</button>',
      option_btn_class: 'option'
    }
  };

  // jQuery not defined.
  if (!$) {
    return;
  }

  $.dialog = (function () {
    /*
     * Close the dialog.
     */
    function close(name) {
      var dialogEl, dialog = dialogs[name].dialog;

      // If close has already been called, return.
      if (!dialog) {
        return;
      }

      // If there is a timeout, clear the timeout to stop it.
      if (dialog.timeout) {
        clearTimeout(dialog.timeout);
        dialog.timeout = null;
      }

      // Get the blocker element of the dialog.
      dialogEl = $('#' + name);

      // Hide the dialog.
      dialogEl.hide().removeClass("in");

      // Remove click handlers.
      dialogEl.find(".cancel, .ok, ." + settings.confirm.option_btn_class).off("click.dialog");

      // Remove html and all handlers if replace setting.
      dialogEl.empty();

      // Remove key handlers.
      $(document).off("keyup.dialog");
      $(document).off("keydown.dialog");

      // Run the close function.
      dialog.onClose(dialogEl);

      // Delete the open dialog object for this dialog.
      dialog = {};
    }

    /*
     * Check for the Esc key pressed. If pressed, close the dialog.
     */
    function checkEsc(name) {
      // Capture the Esc key to close the dialog.
      $(document).on("keyup.dialog", function (event) {
        if (event.keyCode === 27) {
          event.stopPropagation();
          close(name);
        }
      });
    }

    /*
     * Check for the Enter/Return key pressed. If pressed call callback function.
     */
    function checkEnter(name, callback) {
      // Capture the Enter key to close the dialog.
      $(document).on("keydown.dialog", function (event) {
        if (event.keyCode === 13) {
          event.preventDefault();
          event.stopPropagation();
          if (typeof callback === "function") {
            callback();
          }
          close(name);
        }
      });
    }

    /*
     * Show the dialog, add close behavior, and call any passed onOpen function.
     */
    function show(name) {
      var dialogEl = $('#' + name),
        dialog = dialogs[name].dialog;

      // Show the dialog.
      dialogEl.show().addClass("in");

      // Run onOpen function
      dialog.onOpen(dialogEl);

      // Check for auto close of dialog.
      dialog.autoClose();

      // Close on Esc key.
      checkEsc(name);

      // Close on Cancel button.
      dialogEl.find(".cancel, .ok, ." + settings.confirm.option_btn_class).on("click.dialog", function () {
        close(name);
      });
    }

    /*
     * Get dialog html from the server and add it to the DOM.
     */
    function get(name) {
      // Create background blocker and add id.
      var blocker = $(settings.blocker).attr("id", name);
      $.ajax(settings.path + name + settings.extension).done(function (data) {
        // Store dialog html.
        dialogs[name].html = data;
        // Add dialog html to blocker.
        blocker.append(data);
        // Add blocker to end of body.
        $("body").append(blocker);
        show(name);
      }).error(function (xhr, status) {
        console.log("Error getting dialog", name, "error:", status, xhr);
      });
    }

    /*
     * Open the dialog.
     */
    function open() {
      // If the dialog html has been added to the DOM, show the dialog, otherwise
      // get the dialog html from the server and add it to the DOM and show the
      // dialog.

      var i, a, name, dialog, onOpen, onClose, autoClose;

      // Process variable number of arguments.
      for (i = 0; i < arguments.length; i++) {
        a = arguments[i];
        if (typeof a === "string") {
          name = a;
        } else if (typeof a === "function") {
          if (!onOpen) {
            onOpen = a;
          } else {
            onClose = a;
          }
        } else if (typeof a === "number") {
          autoClose = a;
        }
      }

      // Create dialog object for dialog.
      if (!dialogs[name]) {
        dialogs[name] = {dialog: {}};
      } else if (settings.replace) {
        // Replace the html of the dialog each time it is displayed.
        $('#' + name).html(dialogs[name].html);
      }

      dialog = dialogs[name].dialog;

      // Allow the dialog object to be auto closed.
      dialog.autoClose = function (msecs) {
        msecs = msecs || autoClose;
        if (typeof msecs === "number" && !dialog.timeout) {
          this.timeout = setTimeout(function () {
            dialogs[name].dialog.timeout = null;
            close(name);
          }, msecs);
        }
        return dialog;
      };

      dialog.onOpen = function (fn) {
        var dialogEl, origFn;
        if (typeof fn === "function") {
          dialogEl = $('#' + name);
          if (dialogEl.length) {
            fn(dialogEl);
          } else if (onOpen) {
            origFn = onOpen;
            this.onOpen = function (el) {
              origFn(el);
              fn(el);
            };
          } else {
            onOpen = fn;
          }
        } else if (fn && fn.jquery && typeof onOpen === "function") {
          // Was passed a jQuery object, call the onOpen function.
          onOpen(fn);
        }
        return dialog;
      };

      dialog.onClose = function (fn) {
        var origFn;
        if (typeof fn === "function") {
          if (this.onClose) {
            origFn = this.onClose;
            this.onClose = function (el) {
              origFn(el);
              fn(el);
            };
          } else {
            this.onClose = fn;
          }
        } else if (fn && fn.jquery && typeof onClose === "function") {
          onClose(fn);
        }
        return dialog;
      };

      // Is the dialog already in the DOM?
      if ($('#' + name).length) {
        show(name);
      } else {
        get(name);
      }

      return dialog;
    }

    /*
     * Display an alert message with an OK button.
     */
    function alert() {
      var a, msg, onClose, autoClose, i;

      // Process variable number of arguments.
      for (i = 0; i < arguments.length; i++) {
        a = arguments[i];
        if (typeof a === "string") {
          msg = a;
        } else if (typeof a === "function") {
          onClose = a;
        } else if (typeof a === "number") {
          autoClose = a;
        }
      }

      function onOpen(dialogEl) {
        // Add the alert message to the alert dialog. If wider than 320 pixels change new lines to
.
        dialogEl.focus().find(".msg").html(msg.replace(/\n/g, (document.body.offsetWidth > 320 ? "
" : " ")));
        checkEnter("alert");
      }

      return open("alert", onOpen, onClose, autoClose);
    }

    /*
     * Display a dialog with a message and cancel and ok buttons.
     * If the user clicks the OK button, pass true to the callback
     * function. Otherwise pass false to the callback function.
     */
    function confirm() {
      var bReturn = false, a, msg, i, options = {
        ok: undefined,
        cancel: undefined,
        option: undefined,
        onOpen: undefined,
        onClose: undefined
      };

      // Process variable number of arguments.
      for (i = 0; i < arguments.length; i++) {
        a = arguments[i];
        if (typeof a === "string") {
          if (!msg) {
            msg = a;
          } else if (!options.ok) {
            options.ok = a;
          } else {
            options.cancel = a;
          }
        } else if (typeof a === "function") {
          options.onClose = a;
        } else {
          options = $.extend(options, a);
        }
      }

      function onOpen(dialogEl) {
        var dialog_ok_btn = dialogEl.find(".ok"), dialog_cancel_btn = dialogEl.find(".cancel"), dialog_option_btn;

        // Set OK button text.
        if (options.ok) {
          dialog_ok_btn.text(options.ok);
        } else {
          dialog_ok_btn.text(dialog_ok_btn.attr("data-default"));
        }

        // Set Cancel button text.
        if (options.cancel) {
          dialog_cancel_btn.text(options.cancel);
        } else {
          dialog_cancel_btn.text(dialog_cancel_btn.attr("data-default"));
        }

        // Change the message. If wider than 320 pixels change new lines to
.
        dialogEl.focus().find(".msg").html(msg.replace(/\n/g, (document.body.offsetWidth > 320 ? "
" : " ")));

        // If the user clicks ok, set the return value.
        dialogEl.find(".ok").on("click.confirm", function () {
          bReturn = true;
        });

        // Add option button if requested.
        if (options.option) {
          // Create option button.
          dialog_option_btn = $(settings.confirm.option_btn_start + options.option + settings.confirm.option_btn_end);
          // Add it to the form.
          dialog_cancel_btn.before(dialog_option_btn);
          // If the user clicks ok, set the return value to the option button text.
          dialog_option_btn.on("click.confirm", function (event) {
            event.stopPropagation();
            // Return the text of the button.
            bReturn = options.option;
          });
        }

        // If the user presses the Enter key, set the return value as if they
        // clicked the OK button.
        checkEnter("confirm", function () {
          bReturn = true;
        });

        if (typeof options.onOpen === "function") {
          options.onOpen(dialogEl);
        }

        return dialogs.confirm.dialog;
      }

      function onClose(dialogEl) {
        if (typeof dialogEl === "function") {
          options.onClose = dialogEl;
          return dialogs.confirm.dialog;
        }

        // remove click handlers and option button.
        dialogEl.find(".ok, ." + settings.confirm.option_btn_class).off("click.confirm");
        if (options.option && !settings.replace) {
          dialogEl.find(settings.confirm.option_btn_class).remove();
        }

        // Call the callback function with a return value.
        if (typeof options.onClose === "function") {
          options.onClose(bReturn);
        }
        return dialogs.confirm.dialog;
      }

      // Overwrite onClose method with confirm onClose method.
      open("confirm", onOpen).onClose = onClose;
      return dialogs.confirm.dialog;
    }

    /*
     * Change path and extension settings.
     */
    function set(obj) {
      settings = $.extend(true, settings, obj);
    }

    /*
     * Helper functions to determine the type of value passed by confirm.onClose.
     */
    function isOk(val) {
      return typeof val === "boolean" && val;
    }

    function isCancel(val) {
      return typeof val === "boolean" && !val;
    }

    function isOption(val) {
      return typeof val === "string" && val ? true : false;
    }

    // Return public methods.
    return {
      open: open,
      close: close,
      alert: alert,
      confirm: confirm,
      set: set,
      isOk: isOk,
      isCancel: isCancel,
      isOption: isOption
    };
  }());
}(jQuery));
<|endoftext|>


<commit_before>const _ = require('underscore');

const PlotCard = require('../../../plotcard.js');

class WildfireAssault extends PlotCard {
    constructor(owner, cardData) {
        super(owner, cardData);

        this.state = {};
    }

    onReveal(player) {
        if(!this.inPlay || this.owner !== player) {
            return true;
        }

        var firstPlayer = this.game.getFirstPlayer();

        if(!firstPlayer) {
            return true;
        }

        var otherPlayer = this.game.getOtherPlayer(firstPlayer);

        this.state[firstPlayer.id] = {};
        this.state[firstPlayer.id].selecting = true;
        this.state[firstPlayer.id].doneSelecting = false;

        this.setupSelection(firstPlayer);

        if(otherPlayer) {
            this.state[otherPlayer.id] = {};
            this.state[otherPlayer.id].selecting = false;
            this.state[otherPlayer.id].doneSelecting = false;
        }

        return false;
    }

    setupSelection(player) {
        var buttons = [{ command: 'plot', method: 'cancelSelection', text: 'Done' }];

        this.state[player.id].selecting = true;

        var otherPlayer = this.game.getOtherPlayer(player);
        if(otherPlayer) {
            otherPlayer.menuTitle = 'Waiting for opponent to select characters';
            otherPlayer.buttons = [];
        }

        this.game.promptForSelect(player, this.onCardSelected.bind(this), 'Select characters to save', buttons, true);
    }

    cancelSelection(player) {
        if(!this.inPlay || !this.state[player.id].selecting) {
            return;
        }

        this.state[player.id].doneSelecting = true;

        this.proceedToNextStep();
    }

    onCardSelected(player, cardId) {
        if(!this.inPlay || !this.state[player.id].selecting) {
            return false;
        }

        var card = player.findCardInPlayByUuid(cardId);
        if(!card || card.getType() !== 'character') {
            return false;
        }

        var numSelected = player.cardsInPlay.reduce((counter, card) => {
            if(!card.selected) {
                return counter;
            }

            return counter + 1;
        }, 0);

        if(numSelected === 3 && !card.selected) {
            return false;
        }

        card.selected = !card.selected;

        return true;
    }

    doDiscard() {
        var sortedPlayers = this.game.getPlayersInFirstPlayerOrder();

        _.each(sortedPlayers, player => {
            var notSelected = player.cardsInPlay.filter(card => {
                return !card.selected;
            });

            var params = '';
            var paramIndex = 2;

            _.each(notSelected, card => {
                card.selected = false;

                if(card.getType() !== 'character') {
                    return;
                }

                player.discardCard(card.uuid, player.deadPile);

                params += '{' + paramIndex++ + '} ';

            });

            if(!_.isEmpty(notSelected)) {
                this.game.addMessage('{0} uses {1} to kill ' + params, player, this, ...notSelected);
            }

            player.cardsInPlay.each(card => {
                card.selected = false;
            });
        });

        this.game.playerRevealDone(this.owner);
    }

    proceedToNextStep() {
        var stillToSelect = _.find(this.game.getPlayers(), player => {
            return !this.state[player.id].doneSelecting;
        });

        if(!stillToSelect) {
            this.doDiscard();

            return;
        }

        this.setupSelection(stillToSelect);
    }
}

WildfireAssault.code = '01026';

module.exports = WildfireAssault;
<commit_msg>Stop wildfire assault from taking clicks when discard is done fix wildfire assault chat messages<commit_after>const _ = require('underscore');

const PlotCard = require('../../../plotcard.js');

class WildfireAssault extends PlotCard {
    constructor(owner, cardData) {
        super(owner, cardData);

        this.state = {};
    }

    onReveal(player) {
        if(!this.inPlay || this.owner !== player) {
            return true;
        }

        var firstPlayer = this.game.getFirstPlayer();

        if(!firstPlayer) {
            return true;
        }

        var otherPlayer = this.game.getOtherPlayer(firstPlayer);

        this.state[firstPlayer.id] = {};
        this.state[firstPlayer.id].selecting = true;
        this.state[firstPlayer.id].doneSelecting = false;

        this.setupSelection(firstPlayer);

        if(otherPlayer) {
            this.state[otherPlayer.id] = {};
            this.state[otherPlayer.id].selecting = false;
            this.state[otherPlayer.id].doneSelecting = false;
        }

        return false;
    }

    setupSelection(player) {
        var buttons = [{ command: 'plot', method: 'cancelSelection', text: 'Done' }];

        this.state[player.id].selecting = true;

        var otherPlayer = this.game.getOtherPlayer(player);
        if(otherPlayer) {
            otherPlayer.menuTitle = 'Waiting for opponent to select characters';
            otherPlayer.buttons = [];
        }

        this.game.promptForSelect(player, this.onCardSelected.bind(this), 'Select characters to save', buttons, true);
    }

    cancelSelection(player) {
        if(!this.inPlay || !this.state[player.id].selecting) {
            return;
        }

        this.state[player.id].doneSelecting = true;

        this.proceedToNextStep();
    }

    onCardSelected(player, cardId) {
        if(!this.inPlay || !this.state[player.id].selecting) {
            return false;
        }

        var card = player.findCardInPlayByUuid(cardId);
        if(!card || card.getType() !== 'character') {
            return false;
        }

        var numSelected = player.cardsInPlay.reduce((counter, card) => {
            if(!card.selected) {
                return counter;
            }

            return counter + 1;
        }, 0);

        if(numSelected === 3 && !card.selected) {
            return false;
        }

        card.selected = !card.selected;

        return true;
    }

    doDiscard() {
        var sortedPlayers = this.game.getPlayersInFirstPlayerOrder();

        _.each(sortedPlayers, player => {
            var toKill = player.cardsInPlay.filter(card => {
                return card.getType() === 'character' && !card.selected;
            });

            var params = '';
            var paramIndex = 2;

            _.each(toKill, card => {
                card.selected = false;

                player.discardCard(card.uuid, player.deadPile);

                params += '{' + paramIndex++ + '} ';

            });

            if(_.isEmpty(toKill)) {
                this.game.addMessage('{0} does not kill any characters with {1}', player, this);
            } else {
                this.game.addMessage('{0} uses {1} to kill ' + params, player, this, ...toKill);
            }

            player.cardsInPlay.each(card => {
                card.selected = false;
            });

            player.selectCard = false;
        });

        _.each(this.state, s => {
            s.selecting = false;
        });

        this.game.playerRevealDone(this.owner);
    }

    proceedToNextStep() {
        var stillToSelect = _.find(this.game.getPlayers(), player => {
            return !this.state[player.id].doneSelecting;
        });

        if(!stillToSelect) {
            this.doDiscard();

            return;
        }

        this.setupSelection(stillToSelect);
    }
}

WildfireAssault.code = '01026';

module.exports = WildfireAssault;
<|endoftext|>