<commit_before>/*
 * This file is part of Cockpit.
 *
 * Copyright (C) 2015 Red Hat, Inc.
 *
 * Cockpit is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * Cockpit is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Cockpit; If not, see <http://www.gnu.org/licenses/>.
 */

(function() {
    "use strict";

    var angular = require('angular');
    require('angular-bootstrap/ui-bootstrap.js');

    angular.module('ui.cockpit', [
        'ui.bootstrap',
    ])

    /*
     * Implements a <modal-dialog> directive that works with ui-bootstrap's
     * $modal service. Implements Cockpit dialog HIG behavior.
     *
     * This wraps <modal-group> and provides a default implementation
     * of result and cancel where the dialog is closed when either method
     * is called.
     */
    .directive('modalDialog', [
        "$q",
        function($q) {
            return {
                restrict: 'E',
                transclude: true,
                template: '<modal-group><ng-transclude></ng-transclude></modal-group>',
                link: function(scope, element, attrs) {

                    scope.cancel = function() {
                        scope.$dismiss();
                    };

                    scope.result = function(success, result) {
                        /* Close dialog on success */
                        if (success)
                            scope.$close(result);
                    };
                },
            };
        }
    ])

    /*
     * Implements a <modal-group> directive that works with ui-bootstrap's
     * $modal service. Implements Cockpit dialog HIG behavior.
     *
     * To use this directive your parent scope must implement a result
     * and cancel method. See <modal-dialog> for the default implementation.
     *
     * This dialog treats a button with .btn-cancel class as a cancel
     * button. Clicking it will call the cancel method or (see below) cancel
     * a completion promise.
     *
     * From inside the dialog, you can invoke the following methods on
     * the scope:
     *
     * failure(ex)
     * failure([ex1, ex2])
     *
     * Displays errors either globally or on fields. The ex.message or
     * ex.toString() is displayed as the failure message. If ex.target
     * is a valid CSS selector, then the failure message will be displayed
     * under the selected field.
     *
     * failure()
     * failure(null)
     *
     * Clears all failures from display.
     *
     * complete(promise)
     * complete(data)
     *
     * Complete the dialog. If a promise is passed, then the dialog will
     * enter into a wait state until the promise completes. If promise resolves
     * then the result method with be called with the resolve value. If the promise
     * rejects, then failures will be displayed by invoking failure() above.
     *
     * While the promise is completing, all .form-control and .btn will
     * be disabled. If promise.cancel() is a method, then the .btn-cancel
     * will remain clickable, and clicking it will cancel the promise, and
     * when the promise completes, will call the cancel method.
     */
    .directive('modalGroup', [
        "$q",
        function($q) {
            return {
                restrict: 'E',
                transclude: true,
                template: '<ng-transclude></ng-transclude>',
                link: function(scope, element, attrs) {
                    var state = null;

                    function detach() {
                        if (state)
                            state.detach();
                        state = null;
                    }

                    scope.complete = function(thing) {
                        var buttonSel = scope.modalGroupButtonSel || ".modal-footer";
                        var errorAfter = scope.modalGroupErrorAfter || false;

                        detach();
                        if (!thing || !thing.then)
                            thing = $q(thing);
                        state = new DialogState(element, buttonSel, errorAfter, thing, scope);
                    };

                    scope.failure = function(/* ... */) {
                        var errors;
                        var n = arguments.length;
                        if (n === 0) {
                            errors = null;
                        } else if (n === 1) {
                            errors = arguments[0];
                        } else {
                            errors = [];
                            errors.push.apply(errors, arguments);
                        }

                        if (!errors) {
                            detach();
                            return;
                        }

                        var defer = $q.defer();
                        defer.reject(errors);
                        scope.complete(defer.promise);
                    };

                    /* Dialog cancellation before promises kick in */
                    function dismissDialog() {
                        scope.cancel();
                    }

                    var cancel = queryFirst(element, ".btn-cancel");
                    cancel.on("click", dismissDialog);
                    scope.$on("$routeChangeStart", dismissDialog);

                    scope.$on("$destroy", function() {
                        cancel.off("click", dismissDialog);
                        detach();
                    });
                },
            };
        }
    ]);

    function queryAll(element, selector) {
        var list, result = [];
        var j, i, jlen, len = element.length;
        for (i = 0; i < len; i++) {
            list = element[i].querySelectorAll(selector);
            if (list) {
                for (j = 0, jlen = list.length; j < jlen; j++)
                    result.push(list[j]);
            }
        }
        return angular.element(result);
    }

    function queryFirst(element, selector) {
        var result = null;
        var i, len = element.length;
        for (i = 0; !result && i < len; i++)
            result = element[i].querySelector(selector);
        return angular.element(result);
    }

    /*
     * This state object handles one of three different states.
     * This does not exist in the case "before" these states are relevant.
     *
     * state = null: pending
     * state = true: succeeded
     * state = false: failed
     */
    function DialogState(element, btnSel, errorAfter, promise, scope) {
        var state = null;
        var result = null;

        /* Set to true when cancel was requested */
        var cancelled = false;
        var detached = false;

        /* The wait field elements */
        var disabled = [];
        var wait = angular.element("
");
        wait.append(angular.element("
"));
        var notify = angular.element("");
        wait.append(notify);

        this.detach = detachState;

        if (!promise) {
            detachState();
            return;
        }

        promise.then(function(data) {
            result = data;
            if (promise)
                changeState(true);
        }, function(data) {
            result = data;
            if (promise)
                changeState(false);
        }, function(data) {
            if (promise)
                notifyWait(data);
        });

        window.setTimeout(function() {
            if (promise && scope && state === null) {
                changeState(null);
                scope.$digest();
            }
        }, 0);

        function changeState(value) {
            if (detached)
                return;
            state = value;
            if (cancelled) {
                scope.cancel();
                return;
            } else if (state === null) {
                clearErrors();
                displayWait();
            } else if (state === true) {
                clearErrors();
                clearWait();
                scope.result(true, result);
            } else if (state === false) {
                clearWait();
                displayErrors(result);
                scope.result(false, result);
            } else {
                console.warn("invalid dialog state", state);
            }
        }

        function detachState() {
            scope = null;
            promise = null;
            clearErrors();
            clearWait();
        }

        function displayErrors(errors) {
            clearErrors();

            if (!angular.isArray(errors))
                errors = [errors];
            errors.forEach(function(error) {
                var target = null;
                /* Each error can have a target field */
                if (error.target)
                    target = queryFirst(element, error.target);
                if (target && target[0])
                    fieldError(target, error);
                else
                    globalError(error);
            });
        }

        function globalError(error) {
            var alert = angular.element("
");
            alert.text(error.message || error.toString());
            alert.prepend(angular.element(""));

            var wrapper = queryFirst(element, btnSel);
            if (wrapper.length) {
                if (errorAfter)
                    wrapper.append(alert);
                else
                    wrapper.prepend(alert);
            } else {
                element.append(alert);
            }
        }

        function fieldError(target, error) {
            var message = angular.element("
");
            message.text(error.message || error.toString());
            var wrapper = target.parent();
            wrapper.addClass("has-error");
            target.after(message);
            wrapper.on("keypress change", handleClear);
        }

        function handleClear(ev) {
            var target = ev.target;
            /* jshint validthis:true */
            while (target !== this) {
                clearError(angular.element(target));
                target = target.parentNode;
            }
        }

        function clearError(target) {
            var wrapper = target.parent();
            queryAll(wrapper, ".dialog-error").remove();
            wrapper.removeClass("has-error");
            wrapper.off("keypress change", handleClear);
        }

        function clearErrors() {
            var messages = queryAll(element, ".dialog-error");
            angular.forEach(messages, function(message) {
                clearError(angular.element(message));
            });
        }

        function handleCancel(ev) {
            if (promise.cancel)
                promise.cancel();
            cancelled = true;
            ev.stopPropagation();
            ev.preventDefault();
            return false;
        }

        function notifyWait(data) {
            var message = data.message || data;
            if (typeof message == "string" || typeof message == "number")
                notify.text(message);
            else if (!message)
                notify.text("");
        }

        function clearWait() {
            var control;
            while (true) {
                control = disabled.pop();
                if (!control)
                    break;
                control.removeAttr("disabled");
            }
            wait.remove();
            queryFirst(element, ".btn-cancel").off("click", handleCancel);
        }

        function displayWait() {
            clearWait();

            /* Insert the wait area */
            queryFirst(element, btnSel).prepend(wait);

            /* Disable everything and stash previous disabled state */
            function disable(el) {
                var control = angular.element(el);
                if (control.attr("disabled") ||
                    promise.cancel && control.hasClass("btn-cancel"))
                    return;
                disabled.push(control);
                control.attr("disabled", "disabled");
            }

            angular.forEach(queryAll(element, ".form-control"), disable);
            angular.forEach(queryAll(element, ".form-checkbox"), disable);
            angular.forEach(queryAll(element, ".btn"), disable);

            queryFirst(element, ".btn-cancel").on("click", handleCancel);
        }
    }

}());
<commit_msg>lib: Log errors in Angular dialogs<commit_after>/*
 * This file is part of Cockpit.
 *
 * Copyright (C) 2015 Red Hat, Inc.
 *
 * Cockpit is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * Cockpit is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Cockpit; If not, see <http://www.gnu.org/licenses/>.
 */

(function() {
    "use strict";

    var angular = require('angular');
    require('angular-bootstrap/ui-bootstrap.js');

    angular.module('ui.cockpit', [
        'ui.bootstrap',
    ])

    /*
     * Implements a <modal-dialog> directive that works with ui-bootstrap's
     * $modal service. Implements Cockpit dialog HIG behavior.
     *
     * This wraps <modal-group> and provides a default implementation
     * of result and cancel where the dialog is closed when either method
     * is called.
     */
    .directive('modalDialog', [
        "$q",
        function($q) {
            return {
                restrict: 'E',
                transclude: true,
                template: '<modal-group><ng-transclude></ng-transclude></modal-group>',
                link: function(scope, element, attrs) {

                    scope.cancel = function() {
                        scope.$dismiss();
                    };

                    scope.result = function(success, result) {
                        /* Close dialog on success */
                        if (success)
                            scope.$close(result);
                    };
                },
            };
        }
    ])

    /*
     * Implements a <modal-group> directive that works with ui-bootstrap's
     * $modal service. Implements Cockpit dialog HIG behavior.
     *
     * To use this directive your parent scope must implement a result
     * and cancel method. See <modal-dialog> for the default implementation.
     *
     * This dialog treats a button with .btn-cancel class as a cancel
     * button. Clicking it will call the cancel method or (see below) cancel
     * a completion promise.
     *
     * From inside the dialog, you can invoke the following methods on
     * the scope:
     *
     * failure(ex)
     * failure([ex1, ex2])
     *
     * Displays errors either globally or on fields. The ex.message or
     * ex.toString() is displayed as the failure message. If ex.target
     * is a valid CSS selector, then the failure message will be displayed
     * under the selected field.
     *
     * failure()
     * failure(null)
     *
     * Clears all failures from display.
     *
     * complete(promise)
     * complete(data)
     *
     * Complete the dialog. If a promise is passed, then the dialog will
     * enter into a wait state until the promise completes. If promise resolves
     * then the result method with be called with the resolve value. If the promise
     * rejects, then failures will be displayed by invoking failure() above.
     *
     * While the promise is completing, all .form-control and .btn will
     * be disabled. If promise.cancel() is a method, then the .btn-cancel
     * will remain clickable, and clicking it will cancel the promise, and
     * when the promise completes, will call the cancel method.
     */
    .directive('modalGroup', [
        "$q",
        function($q) {
            return {
                restrict: 'E',
                transclude: true,
                template: '<ng-transclude></ng-transclude>',
                link: function(scope, element, attrs) {
                    var state = null;

                    function detach() {
                        if (state)
                            state.detach();
                        state = null;
                    }

                    scope.complete = function(thing) {
                        var buttonSel = scope.modalGroupButtonSel || ".modal-footer";
                        var errorAfter = scope.modalGroupErrorAfter || false;

                        detach();
                        if (!thing || !thing.then)
                            thing = $q(thing);
                        state = new DialogState(element, buttonSel, errorAfter, thing, scope);
                    };

                    scope.failure = function(/* ... */) {
                        var errors;
                        var n = arguments.length;
                        if (n === 0) {
                            errors = null;
                        } else if (n === 1) {
                            errors = arguments[0];
                        } else {
                            errors = [];
                            errors.push.apply(errors, arguments);
                        }

                        if (!errors) {
                            detach();
                            return;
                        }

                        var defer = $q.defer();
                        defer.reject(errors);
                        scope.complete(defer.promise);
                    };

                    /* Dialog cancellation before promises kick in */
                    function dismissDialog() {
                        scope.cancel();
                    }

                    var cancel = queryFirst(element, ".btn-cancel");
                    cancel.on("click", dismissDialog);
                    scope.$on("$routeChangeStart", dismissDialog);

                    scope.$on("$destroy", function() {
                        cancel.off("click", dismissDialog);
                        detach();
                    });
                },
            };
        }
    ]);

    function queryAll(element, selector) {
        var list, result = [];
        var j, i, jlen, len = element.length;
        for (i = 0; i < len; i++) {
            list = element[i].querySelectorAll(selector);
            if (list) {
                for (j = 0, jlen = list.length; j < jlen; j++)
                    result.push(list[j]);
            }
        }
        return angular.element(result);
    }

    function queryFirst(element, selector) {
        var result = null;
        var i, len = element.length;
        for (i = 0; !result && i < len; i++)
            result = element[i].querySelector(selector);
        return angular.element(result);
    }

    /*
     * This state object handles one of three different states.
     * This does not exist in the case "before" these states are relevant.
     *
     * state = null: pending
     * state = true: succeeded
     * state = false: failed
     */
    function DialogState(element, btnSel, errorAfter, promise, scope) {
        var state = null;
        var result = null;

        /* Set to true when cancel was requested */
        var cancelled = false;
        var detached = false;

        /* The wait field elements */
        var disabled = [];
        var wait = angular.element("
");
        wait.append(angular.element("
"));
        var notify = angular.element("");
        wait.append(notify);

        this.detach = detachState;

        if (!promise) {
            detachState();
            return;
        }

        promise.then(function(data) {
            result = data;
            if (promise)
                changeState(true);
        }, function(data) {
            result = data;
            if (promise)
                changeState(false);
        }, function(data) {
            if (promise)
                notifyWait(data);
        });

        window.setTimeout(function() {
            if (promise && scope && state === null) {
                changeState(null);
                scope.$digest();
            }
        }, 0);

        function changeState(value) {
            if (detached)
                return;
            state = value;
            if (cancelled) {
                scope.cancel();
                return;
            } else if (state === null) {
                clearErrors();
                displayWait();
            } else if (state === true) {
                clearErrors();
                clearWait();
                scope.result(true, result);
            } else if (state === false) {
                clearWait();
                displayErrors(result);
                scope.result(false, result);
            } else {
                console.warn("invalid dialog state", state);
            }
        }

        function detachState() {
            scope = null;
            promise = null;
            clearErrors();
            clearWait();
        }

        function displayErrors(errors) {
            clearErrors();

            if (!angular.isArray(errors))
                errors = [errors];
            errors.forEach(function(error) {
                var target = null;
                /* Each error can have a target field */
                if (error.target)
                    target = queryFirst(element, error.target);
                if (target && target[0])
                    fieldError(target, error);
                else
                    globalError(error);
            });
        }

        function globalError(error) {
            var alert = angular.element("
");
            var message = error.message || error.toString();
            console.warn(message);
            alert.text(message);
            alert.prepend(angular.element(""));

            var wrapper = queryFirst(element, btnSel);
            if (wrapper.length) {
                if (errorAfter)
                    wrapper.append(alert);
                else
                    wrapper.prepend(alert);
            } else {
                element.append(alert);
            }
        }

        function fieldError(target, error) {
            var message = angular.element("
");
            message.text(error.message || error.toString());
            var wrapper = target.parent();
            wrapper.addClass("has-error");
            target.after(message);
            wrapper.on("keypress change", handleClear);
        }

        function handleClear(ev) {
            var target = ev.target;
            /* jshint validthis:true */
            while (target !== this) {
                clearError(angular.element(target));
                target = target.parentNode;
            }
        }

        function clearError(target) {
            var wrapper = target.parent();
            queryAll(wrapper, ".dialog-error").remove();
            wrapper.removeClass("has-error");
            wrapper.off("keypress change", handleClear);
        }

        function clearErrors() {
            var messages = queryAll(element, ".dialog-error");
            angular.forEach(messages, function(message) {
                clearError(angular.element(message));
            });
        }

        function handleCancel(ev) {
            if (promise.cancel)
                promise.cancel();
            cancelled = true;
            ev.stopPropagation();
            ev.preventDefault();
            return false;
        }

        function notifyWait(data) {
            var message = data.message || data;
            if (typeof message == "string" || typeof message == "number")
                notify.text(message);
            else if (!message)
                notify.text("");
        }

        function clearWait() {
            var control;
            while (true) {
                control = disabled.pop();
                if (!control)
                    break;
                control.removeAttr("disabled");
            }
            wait.remove();
            queryFirst(element, ".btn-cancel").off("click", handleCancel);
        }

        function displayWait() {
            clearWait();

            /* Insert the wait area */
            queryFirst(element, btnSel).prepend(wait);

            /* Disable everything and stash previous disabled state */
            function disable(el) {
                var control = angular.element(el);
                if (control.attr("disabled") ||
                    promise.cancel && control.hasClass("btn-cancel"))
                    return;
                disabled.push(control);
                control.attr("disabled", "disabled");
            }

            angular.forEach(queryAll(element, ".form-control"), disable);
            angular.forEach(queryAll(element, ".form-checkbox"), disable);
            angular.forEach(queryAll(element, ".btn"), disable);

            queryFirst(element, ".btn-cancel").on("click", handleCancel);
        }
    }

}());
<|endoftext|>


<commit_before>import { getUTCTime } from 'binary-common-utils/lib/tools'

export const noop = () => {}

export const tradeOptionToProposal = tradeOption =>
  tradeOption.contractTypes.map(type => ({
    duration_unit: tradeOption.duration_unit,
    basis: 'stake',
    currency: tradeOption.currency,
    symbol: tradeOption.symbol,
    duration: tradeOption.duration,
    amount: tradeOption.amount.toFixed(2),
    contract_type: type,
    ...(tradeOption.prediction !== undefined && {
      barrier: tradeOption.prediction,
    }),
    ...(tradeOption.barrierOffset !== undefined && {
      barrier: tradeOption.barrierOffset,
    }),
    ...(tradeOption.secondBarrierOffset !== undefined && {
      barrier2: tradeOption.secondBarrierOffset,
    }),
  }))

export const getDirection = ticks => {
  const length = ticks.length
  const [tick1, tick2] = ticks.slice(-2)

  let direction = ''
  if (length >= 2) {
    direction = tick1.quote > tick2.quote ? 'rise' : direction
    direction = tick1.quote < tick2.quote ? 'fall' : direction
  }

  return direction
}

export const subscribeToStream = (observer, name, respHandler, request,
  registerOnce, type, unregister) =>
  new Promise((resolve) => {
    observer.register(
      name, (...args) => {
        respHandler(...args)
        resolve()
      }, registerOnce, type && { type, unregister }, true)
    request()
  })

export const registerStream = (observer, name, cb) => {
  if (observer.isRegistered(name)) {
    return
  }
  observer.register(name, cb)
}

// Total is more than 60s
const backoffDelays = [512, 1024, 2048, 4096, 5096, 6096, 7096, 8096, 9096, 10096, 11096]

export const getBackoffDelay = (e, delayIndex) => (e.name === 'RateLimit' ? 60000 : backoffDelays[delayIndex])

export const shouldThrowError = (e, types = [], delayIndex = 0) => e &&
  (!types.concat(['CallError', 'WrongResponse', 'RateLimit', 'DisconnectError']).includes(e.name) ||
    delayIndex === backoffDelays.length)

export const doUntilDone =
  (f, types) => new Promise((resolve, reject) => {
    let delayIndex = 0

    const repeat = e => {
      if (shouldThrowError(e, types, delayIndex)) {
        reject(e)
        return
      }

      setTimeout(() => {
        const promise = f()

        if (promise) {
          promise.then(resolve).catch(repeat)
        } else {
          resolve()
        }
      }, getBackoffDelay(e, delayIndex++))
    }
    repeat()
  })

const toFixedTwo = num => +(num).toFixed(2)

export const addFixed = (a, b) => toFixedTwo(+a + (+b))

export const subtractFixed = (a, b) => toFixedTwo(+a - (+b))

export const createDetails = (contract) => {
  const profit = subtractFixed(contract.sell_price, contract.buy_price)
  const result = (profit < 0) ? 'loss' : 'win'

  return [
    contract.transaction_ids.buy, (+contract.buy_price),
    (+contract.sell_price), profit, contract.contract_type,
    getUTCTime(new Date(parseInt(`${contract.entry_tick_time}000`, 10))),
    (+contract.entry_tick),
    getUTCTime(new Date(parseInt(`${contract.exit_tick_time}000`, 10))),
    (+contract.exit_tick),
    (+((contract.barrier) ? contract.barrier : 0)),
    result,
  ]
}

export const getUUID = () => `${new Date().getTime() * Math.random()}`
<commit_msg>Check for undefined error in getBackoffDelay<commit_after>import { getUTCTime } from 'binary-common-utils/lib/tools'

export const noop = () => {}

export const tradeOptionToProposal = tradeOption =>
  tradeOption.contractTypes.map(type => ({
    duration_unit: tradeOption.duration_unit,
    basis: 'stake',
    currency: tradeOption.currency,
    symbol: tradeOption.symbol,
    duration: tradeOption.duration,
    amount: tradeOption.amount.toFixed(2),
    contract_type: type,
    ...(tradeOption.prediction !== undefined && {
      barrier: tradeOption.prediction,
    }),
    ...(tradeOption.barrierOffset !== undefined && {
      barrier: tradeOption.barrierOffset,
    }),
    ...(tradeOption.secondBarrierOffset !== undefined && {
      barrier2: tradeOption.secondBarrierOffset,
    }),
  }))

export const getDirection = ticks => {
  const length = ticks.length
  const [tick1, tick2] = ticks.slice(-2)

  let direction = ''
  if (length >= 2) {
    direction = tick1.quote > tick2.quote ? 'rise' : direction
    direction = tick1.quote < tick2.quote ? 'fall' : direction
  }

  return direction
}

export const subscribeToStream = (observer, name, respHandler, request,
  registerOnce, type, unregister) =>
  new Promise((resolve) => {
    observer.register(
      name, (...args) => {
        respHandler(...args)
        resolve()
      }, registerOnce, type && { type, unregister }, true)
    request()
  })

export const registerStream = (observer, name, cb) => {
  if (observer.isRegistered(name)) {
    return
  }
  observer.register(name, cb)
}

// Total is more than 60s
const backoffDelays = [512, 1024, 2048, 4096, 5096, 6096, 7096, 8096, 9096, 10096, 11096]

export const getBackoffDelay = (e, delayIndex) => ((e && e.name === 'RateLimit') ? 60000 : backoffDelays[delayIndex])

export const shouldThrowError = (e, types = [], delayIndex = 0) => e &&
  (!types.concat(['CallError', 'WrongResponse', 'RateLimit', 'DisconnectError']).includes(e.name) ||
    delayIndex === backoffDelays.length)

export const doUntilDone =
  (f, types) => new Promise((resolve, reject) => {
    let delayIndex = 0

    const repeat = e => {
      if (shouldThrowError(e, types, delayIndex)) {
        reject(e)
        return
      }

      setTimeout(() => {
        const promise = f()

        if (promise) {
          promise.then(resolve).catch(repeat)
        } else {
          resolve()
        }
      }, getBackoffDelay(e, delayIndex++))
    }
    repeat()
  })

const toFixedTwo = num => +(num).toFixed(2)

export const addFixed = (a, b) => toFixedTwo(+a + (+b))

export const subtractFixed = (a, b) => toFixedTwo(+a - (+b))

export const createDetails = (contract) => {
  const profit = subtractFixed(contract.sell_price, contract.buy_price)
  const result = (profit < 0) ? 'loss' : 'win'

  return [
    contract.transaction_ids.buy, (+contract.buy_price),
    (+contract.sell_price), profit, contract.contract_type,
    getUTCTime(new Date(parseInt(`${contract.entry_tick_time}000`, 10))),
    (+contract.entry_tick),
    getUTCTime(new Date(parseInt(`${contract.exit_tick_time}000`, 10))),
    (+contract.exit_tick),
    (+((contract.barrier) ? contract.barrier : 0)),
    result,
  ]
}

export const getUUID = () => `${new Date().getTime() * Math.random()}`
<|endoftext|>


<commit_before>var userid = null;
var bimgs =  ['multicare.png','hb.png','health.png','dental.png'];;
angular.module('ionicApp', ['ionic'])

.config(function($stateProvider, $urlRouterProvider) {

  $stateProvider
    .state('signin', {
      url: '/sign-in',
      templateUrl: 'templates/sign-in.html',
      controller: 'SignInCtrl'
    })
    .state('schedule', {
      url: '/schedule',
      templateUrl: 'templates/schedule.html',
      controller: 'ScheduleCtrl'
    })
    .state('form', {
      url: '/form',
      templateUrl: 'templates/app-form.html',
      controller: 'FormCtrl'
    })
    .state('signup', {
      url: '/sign-up',
      templateUrl: 'templates/sign-up.html',
      controller: 'SignUpCtrl'
    });
  $urlRouterProvider.otherwise('/sign-in');
})

.controller('ScheduleCtrl', function($scope, $http, $ionicPopup, $state){
  $scope.stories = [];
  $scope.appointments = info;

  $scope.showAlert = function(title, body) {
   var alertPopup = $ionicPopup.alert({
     title: title,
     template: body
   });
   alertPopup.then(function(res) {
     console.log('Error');
   });
 };

  $scope.doRefresh = function() {
    //console.log('called refresh!');
    $http.get('#/schedule')
     .success(function(/*newItems*/) {
      //  $scope.items = newItems;
      $scope.appointments = info;
     })
     .finally(function() {
       // Stop the ion-refresher from spinning
       $scope.$broadcast('scroll.refreshComplete');
     });
    };

  $scope.logout = function() {
    userid = null;
    $state.go('signin');
  }

  $scope.removeApp = function(id){
    //Works! Logs correct id :D
    console.log(id);
    $.ajax({
      //removed the /2 from url.
      url: ('https://api-us.clusterpoint.com//100600/Appointly/' + id),
      type: 'DELETE',
      dataType: 'json',
      // data: ("{'id'=" + id + "}"),
      beforeSend: function(xhr) {
        xhr.setRequestHeader('Authorization', 'Basic ' + btoa('bpshonyak@live.com:Password01'));
      },
      success: function(data) {
        if (typeof success != 'undefined') {
          success(data);
        }
        $scope.showAlert("Success!", "Appointment has been canceled!");
        console.log("Delete Succeded!");
      },
        fail: function(data) {
          alert(data.error);
          console.log('Fail!');
          if (typeof fail != 'undefined') {
            fail(data);
          }
          $scope.showAlert("Error!", "Appointment could not be deleted!");
          console.log("Delte Failed!");
        }
      })

      setTimeout(function()
      {
          $scope.doRefresh();

      }, 2000);
  }

})

.controller('SignUpCtrl', function($http, $scope, $state, $ionicPopup) {
  $scope.showAlert = function(title, body) {
    var alertPopup = $ionicPopup.alert({
      title: title,
      template: body
    });
    alertPopup.then(function(res) {
      $state.go('signin');
    });
  };

  $scope.signup = function(name, email, phone, pass) {

    var send = {
        // "name"      : name,
        // "email"     : email,
        // "phone"     : phone,
        // "pass"      : pass,
        "id"            : phone,
        "password"      : pass,
    }

    console.log(JSON.stringify(send));

    $.ajax({
      url: 'https://api-us.clusterpoint.com/100600/User_Accounts/_insert',
      type: 'POST',
      dataType: 'json',
      data: JSON.stringify(send),
      beforeSend: function(xhr) {
        xhr.setRequestHeader('Authorization', 'Basic ' + btoa('bpshonyak@live.com:Password01'));
      },
      success: function(data) {
        if (typeof success != 'undefined') {
          success(data);
        }
        console.log(data);
        $scope.showAlert('Done!','You are in!');
      },
      fail: function(data) {
        alert('No!');
        alert(data.error);
        console.log('Fail!');
        if (typeof fail != 'undefined') {
          fail(data);
        }
      }
    })

    // users.done(function (data){
    //   var d = data.documents;
    //   //----------------------------------------------------------
    //   console.log(d);
    //   var result = $.grep(d, function(e) {
    //     return e.id == number && e.password == password;
    //   });
    //   console.log(result);
    //   if (result.length == 0) {
    //     $scope.showAlert('Error', 'Incorrect Number or Password!');
    //   } else if (result.length == 1) {
    //     $state.go('sign-in');
    //   } else {
    //     $scope.showAlert('Error', 'Duplicate Users Found!');
    //   }
    // })
  }

})

.controller('SignInCtrl', function($http, $scope, $state, $ionicPopup) {

  $scope.showAlert = function(title, body) {
    var alertPopup = $ionicPopup.alert({
      title: title,
      template: body
    });
    alertPopup.then(function(res) {
      console.log('Error');
    });
  };

  //console.log('Enter SingInCtrl');
  $scope.url = '#';
  $scope.acc_number = '';
  $scope.acc_password = '';
  $scope.login = function(number, password) {
    // console.log(number);
    // console.log('Enter login function');
    // console.log('number: ' + number);
    // console.log('password: ' + password);
    var users = $.ajax({
      url: 'https://api-us.clusterpoint.com/100600/User_Accounts/_list_last',
      type: 'GET',
      dataType: 'json',
      // data      : '{"query": "<name>Test</name>"}',
      beforeSend: function(xhr) {
        xhr.setRequestHeader('Authorization', 'Basic ' + btoa('bpshonyak@live.com:Password01'));
      },
      success: function(data) {
        //console.log('Retrived Users!');
        if (typeof success != 'undefined') {
          // jQuery.parseJSON(doc.responseJSON.documents.toSource();
          success(data);
        }
      },
      fail: function(data) {
        alert(data.error);
        //console.log('Fail!');
        if (typeof fail != 'undefined') {
          fail(data);
        }
      }
    });

    users.done(function(data) {
      var d = data.documents;
      //----------------------------------------------------------
      console.log(d);
      var result = $.grep(d, function(e) {
        return e.id == number && e.password == password;
      });
      console.log(result);
      if (result.length == 0) {
        $scope.showAlert('Error', 'Incorrect Number or Password!');
      } else if (result.length == 1) {
        userid = number;
        console.log('user id:');
        console.log(userid);
        $state.go('schedule');
      } else {
        $scope.showAlert('Error', 'Duplicate Users Found!');
      }
    });

  }

  // $scope.signIn = function(user) {
  //   console.log('Sign-In', user);
  //   $state.go('schedule');
  // };

})

.controller('HomeTabCtrl', function($scope) {
  console.log('HomeTabCtrl');
})

.controller('FormCtrl', function($http, $scope, $state, $timeout, $ionicPopup, $filter) {

    $scope.app_numb;
    $scope.app_name;
    $scope.app_img_p = bimgs[Math.floor(Math.random()*bimgs.length)];
    $scope.app_date = new Date();
    $scope.app_time = $scope.app_date;

    $scope.doRefresh = function() {
      console.log('called refresh!');
      $http.get('#/schedule')
       .success(function(/*newItems*/) {
        //  $scope.items = newItems;
        $scope.appointments = info;
       })
       .finally(function() {
         // Stop the ion-refresher from spinning
         $scope.$broadcast('scroll.refreshComplete');
       });
      };

    $scope.go = function(app_numb, app_date, app_name, app_time, app_location) {
      // app_date = app_date.toString();
      // app_time = app_time.toString();
      // console.log('Passed into function:');
      // console.log(app_id);
      // console.log(app_date);
      // console.log(app_name);
      // console.log(app_time);
      // var fullTime = app_time.split(" ");
      // app_time = fullTime[0];
      // var app_zone = fullTime[1];
      // app_date(new Date(), "mmmm dS, yyyy");

      // console.log('Fulltime: ');
      // console.log(fullTime);
      // console.log('Time: ');
      // console.log(app_time);
      // console.log('Zone: ');
      // console.log(app_zone);
      if (userid == null){
        $state.go("signin");
        return;
      }

      var app_id = "a" + userid + Date.now().toString();

      var send = {
        "id"      :   app_id.toString(),
        "user_id" :   userid,
        "numb"    :   app_numb,
        "name"    :   app_name,
        "img_p"   :   $scope.app_img_p,
        "date"    :   app_date.toString(),
        "time"    :   app_time.toString(),
        "location":   app_location
      }

      console.log(send);

      $scope.showAlert = function() {
        var alertPopup = $ionicPopup.alert({
          title: 'All done!',
          template: 'Appointment Requested'
        });
        alertPopup.then(function(res) {
          $state.go('schedule');
          console.log('Thank you for not eating my delicious ice cream cone');
          setTimeout(function()
          {
              $scope.doRefresh();

          }, 2000);
        });
      };

    var test_date = $filter('date')(app_date, "dd/MM/yyyy");
    var test_time = $filter('date')(app_time, "HH:mm a");

      // Simple GET request example :
    $http.get('http://appointly.mybluemix.net/twiliouth?number=+1' + app_numb + '&message=An appointment has been requested on ' + test_date + ' at ' + test_time + '.').
      success(function(data, status, headers, config) {
        // this callback will be called asynchronously
        // when the response is available
        //console.log('MSG sent to phone!');
      }).
      error(function(data, status, headers, config) {
        // called asynchronously if an error occurs
        // or server returns response with an error status.
      });

      // $.ajax({
      //   url: 'http://appointly.mybluemix.net/',
      //   type: 'GET',
      //   contentType: "text/plain; charset=utf-8",
      //   dataType: 'text',
      //   data: send.name + " scheduled an appoinment with you at " + send.time + " on " + send.date + ", location: " + send.location,
      //   // beforeSend: function(xhr) {
      //   //   xhr.setRequestHeader('Authorization', 'Basic ' + btoa('bpshonyak@live.com:Password01'));
      //   // },
      //   success: function(data) {
      //     alert("Submitted!");
      //     if (typeof success != 'undefined') {
      //       // jQuery.parseJSON(doc.responseJSON.documents.toSource());
      //       success(data);
      //     }
      //   },
      //   fail: function(data) {
      //     alert('No!');
      //     alert(data.error);
      //     console.log('Fail!');
      //     if (typeof fail != 'undefined') {
      //       fail(data);
      //     }
      //   }
      // })

      $.ajax({
        //removed the /2 from url.
        url: 'https://api-us.clusterpoint.com//100600/Appointly/_insert',
        type: 'POST',
        dataType: 'json',
        data: JSON.stringify(send),
        beforeSend: function(xhr) {
          xhr.setRequestHeader('Authorization', 'Basic ' + btoa('bpshonyak@live.com:Password01'));
        },
        success: function(data) {
          if (typeof success != 'undefined') {
            success(data);
          }
          $scope.showAlert();
        },
        fail: function(data) {
          alert('No!');
          alert(data.error);
          console.log('Fail!');
          if (typeof fail != 'undefined') {
            fail(data);
          }
        }
      })

    }
  })
  .controller('MainCtrl', function($http, $scope) {
    $scope.test = 'Scope Works!';

    // $scope.stories = [];
    //
    // $scope.appointments = info;

    // [{
    //   name: 'Green Valley Clinic',
    //   img_p: 'health.png',
    //   date: 'June 30th',
    //   time: 10,
    //   zone: 'am'
    // }, {
    //   name: 'Silver Point Dental',
    //   img_p: 'dental.png',
    //   date: 'July 16th',
    //   time: 2,
    //   zone: 'pm'
    // }, {
    //   name: 'Multicare',
    //   img_p: 'multicare.png',
    //   date: 'July 25th',
    //   time: 4,
    //   zone: 'pm'
    // }];

  });
<commit_msg>added goToSchedule rootScope function.<commit_after>var userid = null;
var bimgs =  ['multicare.png','hb.png','health.png','dental.png'];;
angular.module('ionicApp', ['ionic'])

.config(function($stateProvider, $urlRouterProvider) {

  $stateProvider
    .state('signin', {
      url: '/sign-in',
      templateUrl: 'templates/sign-in.html',
      controller: 'SignInCtrl'
    })
    .state('schedule', {
      url: '/schedule',
      templateUrl: 'templates/schedule.html',
      controller: 'ScheduleCtrl'
    })
    .state('form', {
      url: '/form',
      templateUrl: 'templates/app-form.html',
      controller: 'FormCtrl'
    })
    .state('signup', {
      url: '/sign-up',
      templateUrl: 'templates/sign-up.html',
      controller: 'SignUpCtrl'
    });
  $urlRouterProvider.otherwise('/sign-in');
})

.controller('ScheduleCtrl', function($scope, $http, $ionicPopup, $state, $timeout){
  $scope.stories = [];
  $scope.appointments = info;

  $scope.showAlert = function(title, body) {
   var alertPopup = $ionicPopup.alert({
     title: title,
     template: body
   });
   alertPopup.then(function(res) {
     console.log('Error');
   });
 };

  $scope.doRefresh = function() {
    //console.log('called refresh!');
    $http.get('#/schedule')
     .success(function(/*newItems*/) {
      //  $scope.items = newItems;
      $scope.appointments = info;
     })
     .finally(function() {
       // Stop the ion-refresher from spinning
       $scope.$broadcast('scroll.refreshComplete');
     });
    };

  $scope.logout = function() {
    userid = null;
    $state.go('signin');
  }

  $scope.removeApp = function(id){
    //Works! Logs correct id :D
    console.log(id);
    $.ajax({
      //removed the /2 from url.
      url: ('https://api-us.clusterpoint.com//100600/Appointly/' + id),
      type: 'DELETE',
      dataType: 'json',
      // data: ("{'id'=" + id + "}"),
      beforeSend: function(xhr) {
        xhr.setRequestHeader('Authorization', 'Basic ' + btoa('bpshonyak@live.com:Password01'));
      },
      success: function(data) {
        if (typeof success != 'undefined') {
          success(data);
        }
        $scope.showAlert("Success!", "Appointment has been canceled!");
        console.log("Delete Succeded!");
      },
        fail: function(data) {
          alert(data.error);
          console.log('Fail!');
          if (typeof fail != 'undefined') {
            fail(data);
          }
          $scope.showAlert("Error!", "Appointment could not be deleted!");
          console.log("Delte Failed!");
        }
      })

      setTimeout(function()
      {
          $scope.doRefresh();

      }, 2000);
  }

})

.controller('SignUpCtrl', function($http, $scope, $state, $ionicPopup) {
  $scope.showAlert = function(title, body) {
    var alertPopup = $ionicPopup.alert({
      title: title,
      template: body
    });
    alertPopup.then(function(res) {
      $state.go('signin');
    });
  };

  $scope.signup = function(name, email, phone, pass) {

    var send = {
        // "name"      : name,
        // "email"     : email,
        // "phone"     : phone,
        // "pass"      : pass,
        "id"            : phone,
        "password"      : pass,
    }

    console.log(JSON.stringify(send));

    $.ajax({
      url: 'https://api-us.clusterpoint.com/100600/User_Accounts/_insert',
      type: 'POST',
      dataType: 'json',
      data: JSON.stringify(send),
      beforeSend: function(xhr) {
        xhr.setRequestHeader('Authorization', 'Basic ' + btoa('bpshonyak@live.com:Password01'));
      },
      success: function(data) {
        if (typeof success != 'undefined') {
          success(data);
        }
        console.log(data);
        $scope.showAlert('Done!','You are in!');
      },
      fail: function(data) {
        alert('No!');
        alert(data.error);
        console.log('Fail!');
        if (typeof fail != 'undefined') {
          fail(data);
        }
      }
    })

    // users.done(function (data){
    //   var d = data.documents;
    //   //----------------------------------------------------------
    //   console.log(d);
    //   var result = $.grep(d, function(e) {
    //     return e.id == number && e.password == password;
    //   });
    //   console.log(result);
    //   if (result.length == 0) {
    //     $scope.showAlert('Error', 'Incorrect Number or Password!');
    //   } else if (result.length == 1) {
    //     $state.go('sign-in');
    //   } else {
    //     $scope.showAlert('Error', 'Duplicate Users Found!');
    //   }
    // })
  }

})

.controller('SignInCtrl', function($http, $scope, $rootScope, $state, $ionicPopup, $timeout) {

  $rootScope.goToSchedule = function() {
    console.log('called goToSchedule!');
    $http.get('#/schedule')
     .success(function(/*newItems*/) {
      //  $scope.items = newItems;
      $scope.appointments = info;
     })
     .finally(function() {
       // Stop the ion-refresher from spinning
       $scope.$broadcast('scroll.refreshComplete');
     });
    };

  $scope.showAlert = function(title, body) {
    var alertPopup = $ionicPopup.alert({
      title: title,
      template: body
    });
    alertPopup.then(function(res) {

    });
  };

  //console.log('Enter SingInCtrl');
  $scope.url = '#';
  $scope.acc_number = '';
  $scope.acc_password = '';
  $scope.login = function(number, password) {
    // console.log(number);
    // console.log('Enter login function');
    // console.log('number: ' + number);
    // console.log('password: ' + password);
    var users = $.ajax({
      url: 'https://api-us.clusterpoint.com/100600/User_Accounts/_list_last',
      type: 'GET',
      dataType: 'json',
      // data      : '{"query": "<name>Test</name>"}',
      beforeSend: function(xhr) {
        xhr.setRequestHeader('Authorization', 'Basic ' + btoa('bpshonyak@live.com:Password01'));
      },
      success: function(data) {
        //console.log('Retrived Users!');
        if (typeof success != 'undefined') {
          // jQuery.parseJSON(doc.responseJSON.documents.toSource();
          success(data);
        }
      },
      fail: function(data) {
        alert(data.error);
        //console.log('Fail!');
        if (typeof fail != 'undefined') {
          fail(data);
        }
      }
    });

    users.done(function(data) {
      var d = data.documents;
      //----------------------------------------------------------
      console.log(d);
      var result = $.grep(d, function(e) {
        return e.id == number && e.password == password;
      });
      console.log(result);
      if (result.length == 0) {
        $scope.showAlert('Error', 'Incorrect Number or Password!');
      } else if (result.length == 1) {
        userid = number;
        console.log('user id:');
        console.log(userid);
        $state.go('schedule');
        setTimeout(function()
        {
            $rootScope.goToSchedule();

        }, 2000);
      } else {
        $scope.showAlert('Error', 'Duplicate Users Found!');
      }
    });

  }

  // $scope.signIn = function(user) {
  //   console.log('Sign-In', user);
  //   $state.go('schedule');
  // };

})

.controller('HomeTabCtrl', function($scope) {
  console.log('HomeTabCtrl');
})

.controller('FormCtrl', function($http, $scope, $state, $timeout, $ionicPopup, $filter) {

    $scope.app_numb;
    $scope.app_name;
    $scope.app_img_p = bimgs[Math.floor(Math.random()*bimgs.length)];
    $scope.app_date = new Date();
    $scope.app_time = $scope.app_date;

    $scope.doRefresh = function() {
      console.log('called refresh!');
      $http.get('#/schedule')
       .success(function(/*newItems*/) {
        //  $scope.items = newItems;
        $scope.appointments = info;
       })
       .finally(function() {
         // Stop the ion-refresher from spinning
         $scope.$broadcast('scroll.refreshComplete');
       });
      };

    $scope.go = function(app_numb, app_date, app_name, app_time, app_location) {
      // app_date = app_date.toString();
      // app_time = app_time.toString();
      // console.log('Passed into function:');
      // console.log(app_id);
      // console.log(app_date);
      // console.log(app_name);
      // console.log(app_time);
      // var fullTime = app_time.split(" ");
      // app_time = fullTime[0];
      // var app_zone = fullTime[1];
      // app_date(new Date(), "mmmm dS, yyyy");

      // console.log('Fulltime: ');
      // console.log(fullTime);
      // console.log('Time: ');
      // console.log(app_time);
      // console.log('Zone: ');
      // console.log(app_zone);
      if (userid == null){
        $state.go("signin");
        return;
      }

      var app_id = "a" + userid + Date.now().toString();

      var send = {
        "id"      :   app_id.toString(),
        "user_id" :   userid,
        "numb"    :   app_numb,
        "name"    :   app_name,
        "img_p"   :   $scope.app_img_p,
        "date"    :   app_date.toString(),
        "time"    :   app_time.toString(),
        "location":   app_location
      }

      console.log(send);

      $scope.showAlert = function() {
        var alertPopup = $ionicPopup.alert({
          title: 'All done!',
          template: 'Appointment Requested'
        });
        alertPopup.then(function(res) {
          $state.go('schedule');
          console.log('Thank you for not eating my delicious ice cream cone');
          setTimeout(function()
          {
              $scope.doRefresh();

          }, 2000);
        });
      };

    var test_date = $filter('date')(app_date, "dd/MM/yyyy");
    var test_time = $filter('date')(app_time, "HH:mm a");

      // Simple GET request example :
    $http.get('http://appointly.mybluemix.net/twiliouth?number=+1' + app_numb + '&message=An appointment has been requested on ' + test_date + ' at ' + test_time + '.').
      success(function(data, status, headers, config) {
        // this callback will be called asynchronously
        // when the response is available
        //console.log('MSG sent to phone!');
      }).
      error(function(data, status, headers, config) {
        // called asynchronously if an error occurs
        // or server returns response with an error status.
      });

      // $.ajax({
      //   url: 'http://appointly.mybluemix.net/',
      //   type: 'GET',
      //   contentType: "text/plain; charset=utf-8",
      //   dataType: 'text',
      //   data: send.name + " scheduled an appoinment with you at " + send.time + " on " + send.date + ", location: " + send.location,
      //   // beforeSend: function(xhr) {
      //   //   xhr.setRequestHeader('Authorization', 'Basic ' + btoa('bpshonyak@live.com:Password01'));
      //   // },
      //   success: function(data) {
      //     alert("Submitted!");
      //     if (typeof success != 'undefined') {
      //       // jQuery.parseJSON(doc.responseJSON.documents.toSource());
      //       success(data);
      //     }
      //   },
      //   fail: function(data) {
      //     alert('No!');
      //     alert(data.error);
      //     console.log('Fail!');
      //     if (typeof fail != 'undefined') {
      //       fail(data);
      //     }
      //   }
      // })

      $.ajax({
        //removed the /2 from url.
        url: 'https://api-us.clusterpoint.com//100600/Appointly/_insert',
        type: 'POST',
        dataType: 'json',
        data: JSON.stringify(send),
        beforeSend: function(xhr) {
          xhr.setRequestHeader('Authorization', 'Basic ' + btoa('bpshonyak@live.com:Password01'));
        },
        success: function(data) {
          if (typeof success != 'undefined') {
            success(data);
          }
          $scope.showAlert();
        },
        fail: function(data) {
          alert('No!');
          alert(data.error);
          console.log('Fail!');
          if (typeof fail != 'undefined') {
            fail(data);
          }
        }
      })

    }
  })
  .controller('MainCtrl', function($http, $scope) {
    $scope.test = 'Scope Works!';

    // $scope.stories = [];
    //
    // $scope.appointments = info;

    // [{
    //   name: 'Green Valley Clinic',
    //   img_p: 'health.png',
    //   date: 'June 30th',
    //   time: 10,
    //   zone: 'am'
    // }, {
    //   name: 'Silver Point Dental',
    //   img_p: 'dental.png',
    //   date: 'July 16th',
    //   time: 2,
    //   zone: 'pm'
    // }, {
    //   name: 'Multicare',
    //   img_p: 'multicare.png',
    //   date: 'July 25th',
    //   time: 4,
    //   zone: 'pm'
    // }];

  });
<|endoftext|>


<commit_before>const path = require('path');

const userConfigPath = path.join(process.cwd(), './config/universal-redux.config.js');

function getConfig() {
  try {
    const config = require(path.resolve(userConfigPath));
    if (config.verbose) {
      console.log(`Loaded project level config from ${userConfigPath}`);
    }
    return config;
  } catch (err) {
    console.error('No configuration file provided, using defaults.', err);
    return {};
  }
}

module.exports = getConfig();
<commit_msg>do not report error in case of no config provided<commit_after>const path = require('path');

const userConfigPath = path.join(process.cwd(), './config/universal-redux.config.js');

function getConfig() {
  try {
    const config = require(path.resolve(userConfigPath));
    if (config.verbose) {
      console.log(`Loaded project level config from ${userConfigPath}`);
    }
    return config;
  } catch (err) {
    console.warn('No configuration file found, using defaults.');
    return {};
  }
}

module.exports = getConfig();
<|endoftext|>


<commit_before>enyo.kind({
    name: "moon.sample.music.TrackTwoColumnsWideSample",
    kind: "moon.Panel",
    titleAbove: "02",
    title: "Browse Tracks",
    titleBelow: "15 Tracks",
    headerComponents: [
        {kind: "moon.IconButton", src: "../assets/icon-album.png"},
        {kind: "moon.IconButton", src: "../assets/icon-list.png"}
    ],
    components: [
        {
            name: "trackList",
            kind: "moon.DataGridList",
            fit: true,
            minWidth: 180,
            minHeight: 260,
            components: [
                {
                    kind: "moon.GridListImageItem",
                    ontap: "changeName",
                    bindings: [
                        {from: ".model.coverUrl", to: ".source"},
						{from: ".model.track", to: ".caption"},
                        {from: ".model.artist", to: ".subCaption"}
                    ]
                }
            ]
        }
    ],
    bindings: [
        {from: ".controller.track", to: ".$.trackList.controller"}
    ]
});

// Sample Model

enyo.ready(function (){
    var sampleModel = new enyo.Model({
        track: new enyo.Collection([
            {coverUrl: "../assets/default-music.png", track: "Track name 1",  artist: "Artist name 1",  album: "Album name", time: "3:40"},
            {coverUrl: "../assets/default-music.png", track: "Track name 2",  artist: "Artist name 2",  album: "Album name", time: "3:40"},
            {coverUrl: "../assets/default-music.png", track: "Track name 3",  artist: "Artist name 3",  album: "Album name", time: "3:40"},
            {coverUrl: "../assets/default-music.png", track: "Track name 4",  artist: "Artist name 4",  album: "Album name", time: "3:40"},
            {coverUrl: "../assets/default-music.png", track: "Track name 5",  artist: "Artist name 5",  album: "Album name", time: "3:40"},
            {coverUrl: "../assets/default-music.png", track: "Track name 6",  artist: "Artist name 6",  album: "Album name", time: "3:40"},
            {coverUrl: "../assets/default-music.png", track: "Track name 7",  artist: "Artist name 7",  album: "Album name", time: "3:40"},
            {coverUrl: "../assets/default-music.png", track: "Track name 8",  artist: "Artist name 8",  album: "Album name", time: "3:40"},
            {coverUrl: "../assets/default-music.png", track: "Track name 9",  artist: "Artist name 9",  album: "Album name", time: "3:40"},
            {coverUrl: "../assets/default-music.png", track: "Track name 10", artist: "Artist name 10", album: "Album name", time: "3:40"},
            {coverUrl: "../assets/default-music.png", track: "Track name 11", artist: "Artist name 11", album: "Album name", time: "3:40"},
            {coverUrl: "../assets/default-music.png", track: "Track name 12", artist: "Artist name 12", album: "Album name", time: "3:40"},
            {coverUrl: "../assets/default-music.png", track: "Track name 13", artist: "Artist name 13", album: "Album name", time: "3:40"},
            {coverUrl: "../assets/default-music.png", track: "Track name 14", artist: "Artist name 14", album: "Album name", time: "3:40"},
            {coverUrl: "../assets/default-music.png", track: "Track name 15", artist: "Artist name 15", album: "Album name", time: "3:40"},
            {coverUrl: "../assets/default-music.png", track: "Track name 16", artist: "Artist name 16", album: "Album name", time: "3:40"},
            {coverUrl: "../assets/default-music.png", track: "Track name 17", artist: "Artist name 17", album: "Album name", time: "3:40"},
            {coverUrl: "../assets/default-music.png", track: "Track name 18", artist: "Artist name 18", album: "Album name", time: "3:40"},
            {coverUrl: "../assets/default-music.png", track: "Track name 19", artist: "Artist name 19", album: "Album name", time: "3:40"},
            {coverUrl: "../assets/default-music.png", track: "Track name 20", artist: "Artist name 20", album: "Album name", time: "3:40"},
            {coverUrl: "../assets/default-music.png", track: "Track name 21", artist: "Artist name 21", album: "Album name", time: "3:40"},
            {coverUrl: "../assets/default-music.png", track: "Track name 22", artist: "Artist name 22", album: "Album name", time: "3:40"},
            {coverUrl: "../assets/default-music.png", track: "Track name 23", artist: "Artist name 23", album: "Album name", time: "3:40"},
            {coverUrl: "../assets/default-music.png", track: "Track name 24", artist: "Artist name 24", album: "Album name", time: "3:40"},
            {coverUrl: "../assets/default-music.png", track: "Track name 25", artist: "Artist name 25", album: "Album name", time: "3:40"},
            {coverUrl: "../assets/default-music.png", track: "Track name 26", artist: "Artist name 26", album: "Album name", time: "3:40"}
        ])
    });

// Sample Application

    new enyo.Application({
        view: {
            classes: "enyo-unselectable moon",
            components: [
                {
                    kind: "moon.sample.music.TrackTwoColumnsWideSample",
                    controller: ".app.controllers.trackController",
                    classes: "enyo-fit"
                }
            ]
        },
        controllers: [
            {
                name: "trackController",
                kind: "enyo.ModelController",
                model: sampleModel,
                changeName: function(inSender, inEvent) {
                    /** Todo: find the way how to access active datalist row */
                    inSender.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent.controller.set("track", "Good track");
                }
            }
        ]
    });
});
<commit_msg>cleanup sample pattern and fix some broken features<commit_after>enyo.kind({
	name: "moon.sample.music.TrackTwoColumnsWideSample",
	kind: "moon.Panel",
	classes: "moon enyo-unselectable enyo-fit",
	titleAbove: "02",
	title: "Browse Tracks",
	titleBelow: "26 Tracks",
	controller: ".app.controllers.playlistController",
	headerComponents: [
		{kind: "moon.IconButton", src: "../assets/icon-album.png"},
		{kind: "moon.IconButton", src: "../assets/icon-list.png"}
	],
	components: [
		{name: "trackList", kind: "moon.DataGridList", fit: true, minWidth: 180, minHeight: 260, components: [
			{kind: "moon.GridListImageItem", ontap: "changeName", bindings: [
				{from: ".model.coverUrl", to: ".source"},
				{from: ".model.track", to: ".caption"},
				{from: ".model.artist", to: ".subCaption"}
			]}
		]}
	],
	bindings: [
		{from: ".controller.tracks", to: ".$.trackList.controller"}
	],
	changeName: function (inSender, inEvent) {
		inEvent.model.set("track", "Good Track!");
	}
});

enyo.ready(function () {
	// create our sample playlist with a collection of tracks
	var playlist = new enyo.Model({tracks: new enyo.Collection()}),
		c        = playlist.get("tracks");
	// create some tracks for our playlist
	for (var i=0; i<26; ++i) {
		c.add({coverUrl: "../assets/default-music.png", track: "Track name " + (i+1), artist: "Artist name " + (i+1), album: "Album name", time: "3:40"});
	}
	new enyo.Application({
		name: "app",
		view: "moon.sample.music.TrackTwoColumnsWideSample",
		controllers: [
			{name: "playlistController", kind: "enyo.ModelController", model: playlist}
		]
	});
});
<|endoftext|>


<commit_before>angular.module('anol.geocoder')
/**
 * @ngdoc directive
 * @name anol.geocoder.directive:anolGeocoderSearchbox
 *
 * @restrict A
 * @requires $http
 * @required $timeout
 * @requires anol.map.MapService
 * @requires anol.map.ControlsService
 *
 * @param {string} anolGeocoderSearchbox Url to geocoder service
 * @param {string} display Result property to use for display results
 * @param {string} coordinate Result properties for lon and lat values
 *
 * @description
 * Search for a location string on given geocoder, display and select results
 */
.directive('anolGeocoderSearchbox', ['$http', '$timeout', 'MapService', 'ControlsService',
  function($http, $timeout, MapService, ControlsService) {
    return {
      restrict: 'A',
      require: '?^anolMap',
      transclude: true,
      templateUrl: 'src/modules/geocoder/templates/searchbox.html',
      scope: {
        searchUrl: '@anolGeocoderSearchbox',
        display: '@',
        coordinate_: '@coordinate'
      },
      link: function(scope, element, attrs, AnolMapController) {
        var handleResponse = function(response) {
          var results = [];
          angular.forEach(response, function(result) {
            results.push({
              displayText: result[scope.display],
              coordinate: [
                parseFloat(result[scope.coordinate[0]]),
                parseFloat(result[scope.coordinate[1]])
              ]
            });
          });
          scope.searchResults = results;
          element.find('.anol-searchbox').addClass('open');
        };

        scope.searchResults = [];
        scope.coordinate = scope.coordinate_.split(',');

        scope.handleInputKeypress = function(event) {
          event.stopPropagation();
          if(event.key === 'ArrowDown' && scope.searchResults.length > 0) {
            // use timeout to prevent input element on-blur bug. ($apply already in progress error is raised)
            $timeout(function() {
              element.find('.dropdown-menu li a:first').focus();
            }, 0);
          }
          if(event.key === 'Enter') {
            $http.get(scope.searchUrl + scope.searchString)
              .success(function(response) {
                handleResponse(response);
              });
          }
          return false;
        };

        scope.handleDropdownKeypress = function(event) {
          event.stopPropagation();
          var targetParent = angular.element(event.currentTarget).parent();
          if(event.key === 'ArrowDown') {
            targetParent.next().find('a').focus();
          }
          if(event.key === 'ArrowUp') {
            var target = targetParent.prev().find('a');
            if(target.length === 0) {
              element.find('.form-control').focus();
            } else {
              target.focus();
            }
          }
          return false;
        };

        scope.handleMouseover = function(event) {
          // use timeout to prevent input element on-blur bug. ($apply already in progress error is raised)
          $timeout(function() {
            angular.element(event.currentTarget).focus();
          }, 0);
        };

        scope.showResult = function(result) {
          var view = MapService.getMap().getView();
          view.setCenter(
            ol.proj.transform(
              result.coordinate,
              'EPSG:4326',
              view.getProjection()
            )
          );
          scope.searchResults = [];
          element.find('.anol-searchbox').removeClass('open');
        };

        if(angular.isDefined(AnolMapController)) {
          element.addClass('ol-unselectable');
        }

        ControlsService.addControl(new ol.control.Control({
          element: element.first().context
        }));
      }
    };
}]);<commit_msg>Prevent page scrolling when navigating through search results<commit_after>angular.module('anol.geocoder')
/**
 * @ngdoc directive
 * @name anol.geocoder.directive:anolGeocoderSearchbox
 *
 * @restrict A
 * @requires $http
 * @required $timeout
 * @requires anol.map.MapService
 * @requires anol.map.ControlsService
 *
 * @param {string} anolGeocoderSearchbox Url to geocoder service
 * @param {string} display Result property to use for display results
 * @param {string} coordinate Result properties for lon and lat values
 *
 * @description
 * Search for a location string on given geocoder, display and select results
 */
.directive('anolGeocoderSearchbox', ['$http', '$timeout', 'MapService', 'ControlsService',
  function($http, $timeout, MapService, ControlsService) {
    return {
      restrict: 'A',
      require: '?^anolMap',
      transclude: true,
      templateUrl: 'src/modules/geocoder/templates/searchbox.html',
      scope: {
        searchUrl: '@anolGeocoderSearchbox',
        display: '@',
        coordinate_: '@coordinate'
      },
      link: function(scope, element, attrs, AnolMapController) {
        var handleResponse = function(response) {
          var results = [];
          angular.forEach(response, function(result) {
            results.push({
              displayText: result[scope.display],
              coordinate: [
                parseFloat(result[scope.coordinate[0]]),
                parseFloat(result[scope.coordinate[1]])
              ]
            });
          });
          scope.searchResults = results;
          element.find('.anol-searchbox').addClass('open');
        };

        scope.searchResults = [];
        scope.coordinate = scope.coordinate_.split(',');

        scope.handleInputKeypress = function(event) {
          event.stopPropagation();
          if(event.key === 'ArrowDown' && scope.searchResults.length > 0) {
            event.preventDefault();
            // use timeout to prevent input element on-blur bug. ($apply already in progress error is raised)
            $timeout(function() {
              element.find('.dropdown-menu li a:first').focus();
            }, 0);
          }
          if(event.key === 'Enter') {
            $http.get(scope.searchUrl + scope.searchString)
              .success(function(response) {
                handleResponse(response);
              });
          }
          return false;
        };

        scope.handleDropdownKeypress = function(event) {
          event.stopPropagation();
          var targetParent = angular.element(event.currentTarget).parent();
          if(event.key === 'ArrowDown') {
            event.preventDefault();
            targetParent.next().find('a').focus();
          }
          if(event.key === 'ArrowUp') {
            event.preventDefault();
            var target = targetParent.prev().find('a');
            if(target.length === 0) {
              element.find('.form-control').focus();
            } else {
              target.focus();
            }
          }
          return false;
        };

        scope.handleMouseover = function(event) {
          // use timeout to prevent input element on-blur bug. ($apply already in progress error is raised)
          $timeout(function() {
            angular.element(event.currentTarget).focus();
          }, 0);
        };

        scope.showResult = function(result) {
          var view = MapService.getMap().getView();
          view.setCenter(
            ol.proj.transform(
              result.coordinate,
              'EPSG:4326',
              view.getProjection()
            )
          );
          scope.searchResults = [];
          element.find('.anol-searchbox').removeClass('open');
        };

        if(angular.isDefined(AnolMapController)) {
          element.addClass('ol-unselectable');
        }

        ControlsService.addControl(new ol.control.Control({
          element: element.first().context
        }));
      }
    };
}]);<|endoftext|>