<commit_before>self.importScripts('data.js');

// TODO: Keep state in the window instead, because a single service worker
// can talk to multiple windows.

self.paymentRequestEvent = null;
self.resolver = null;
self.response = response1;

self.addEventListener('message', (evt) => {
  if (evt.data === 'confirm') {
    if (self.resolver !== null) {
      self.resolver(response);
      self.resolver = null;
    } else {
      evt.source.postMessage({error: 'Service worker cannot confirm payment because there is no resolver function.'});
    }
  } else if (evt.data === 'change-method-1') {
    response = response1;
    if (self.paymentRequestEvent !== null && self.paymentRequestEvent.changePaymentMethod) {
      self.paymentRequestEvent.changePaymentMethod(response.methodName, redact(response)).then((paymentMethodChangeResponse) => {
        self.client.postMessage(paymentMethodChangeResponse);
      }).catch((error) => {
        self.client.postMessage({error: error.message});
      });
    } else {
      evt.source.postMessage({error: 'Service worker cannot change payment method because there is payment request event or no change payment method feature'});
    }
  } else if (evt.data === 'change-method-2') {
    response = response2;
    if (self.paymentRequestEvent !== null && self.paymentRequestEvent.changePaymentMethod) {
      self.paymentRequestEvent.changePaymentMethod(response.methodName, redact(response)).then((paymentMethodChangeResponse) => {
        self.client.postMessage(paymentMethodChangeResponse);
      }).catch((error) => {
        self.client.postMessage({error: error.message});
      });
    } else {
      evt.source.postMessage({error: 'Service worker cannot change payment method because there is payment request event or no change payment method feature'});
    }
  } else {
    evt.source.postMessage({error: 'Service worker did not recognize the message "' + evt.data + '".'});
  }
});

self.addEventListener('paymentrequest', (evt) => {
  if (evt.delegateToWindow) {
    evt.delegateToWindow('confirm.html');
    return;
  }

  self.paymentRequestEvent = evt;
  self.paymentRequestEvent.respondWith(new Promise((resolve) => {
    self.resolver = resolve;
    evt.openWindow('confirm.html');
  }));
});
<commit_msg>Stop using self.client<commit_after>self.importScripts('data.js');

// TODO: Keep state in the window instead, because a single service worker
// can talk to multiple windows.

self.paymentRequestEvent = null;
self.resolver = null;
self.response = response1;

function notifyPaymentMethodChanged(messageDestination) {
  self.paymentRequestEvent.changePaymentMethod(self.response.methodName, redact(self.response)).then((paymentMethodChangeResponse) => {
    messageDestination.postMessage(paymentMethodChangeResponse);
  }).catch((error) => {
    messageDestination.postMessage({error: error.message});
  });
}

self.addEventListener('message', (evt) => {
  if (evt.data === 'confirm') {
    if (self.resolver !== null) {
      self.resolver(response);
      self.resolver = null;
    } else {
      evt.source.postMessage({error: 'Service worker cannot confirm payment because there is no resolver function.'});
    }
  } else if (evt.data === 'change-method-1') {
    self.response = response1;
    if (self.paymentRequestEvent !== null && self.paymentRequestEvent.changePaymentMethod) {
      notifyPaymentMethodChanged(evt.source);
    } else {
      evt.source.postMessage({error: 'Service worker cannot change payment method. There is no payment request event or no change payment method feature.'});
    }
  } else if (evt.data === 'change-method-2') {
    self.response = response2;
    if (self.paymentRequestEvent !== null && self.paymentRequestEvent.changePaymentMethod) {
      notifyPaymentMethodChanged(evt.source);
    } else {
      evt.source.postMessage({error: 'Service worker cannot change payment method. There is no payment request event or no change payment method feature.'});
    }
  } else {
    evt.source.postMessage({error: 'Service worker did not recognize the message "' + evt.data + '".'});
  }
});

self.addEventListener('paymentrequest', (evt) => {
  if (evt.delegateToWindow) {
    evt.delegateToWindow('confirm.html');
    return;
  }

  self.paymentRequestEvent = evt;
  self.paymentRequestEvent.respondWith(new Promise((resolve) => {
    self.resolver = resolve;
    evt.openWindow('confirm.html');
  }));
});
<|endoftext|>


<commit_before>'use strict';

var clear          = require('es5-ext/object/clear')
  , setPrototypeOf = require('es5-ext/object/set-prototype-of')
  , validValue     = require('es5-ext/object/valid-value')
  , callable       = require('es5-ext/object/valid-callable')
  , d              = require('d')
  , iterator       = require('es6-iterator/valid-iterable')
  , forOf          = require('es6-iterator/for-of')
  , isNative       = require('../is-native-implemented')
  , Map            = require('../polyfill')
  , Iterator       = require('../lib/primitive-iterator')

  , call = Function.prototype.call
  , create = Object.create, defineProperty = Object.defineProperty
  , defineProperties = Object.defineProperties, getPrototypeOf = Object.getPrototypeOf
  , hasOwnProperty = Object.prototype.hasOwnProperty
  , PrimitiveMap;

module.exports = PrimitiveMap = function (/*iterable, serialize*/) {
	var iterable = arguments[0], serialize = arguments[1], self;
	if (!(this instanceof PrimitiveMap)) throw new TypeError('Constructor requires \'new\'');
	if (isNative && setPrototypeOf) self = setPrototypeOf(new Map(), getPrototypeOf(this));
	else self = this;
	if (iterable != null) iterator(iterable);
	if (serialize !== undefined) {
		callable(serialize);
		defineProperty(self, '_serialize', d('', serialize));
	}
	defineProperties(self, {
		__mapKeysData__: d('c', create(null)),
		__mapValuesData__: d('c', create(null)),
		__size__: d('w', 0)
	});
	if (!iterable) return self;
	forOf(iterable, function (value) {
		var key = validValue(value)[0], sKey = self._serialize(key);
		if (sKey == null) throw new TypeError(key + " cannot be serialized");
		value = value[1];
		if (hasOwnProperty.call(self.__mapKeysData__, sKey)) {
			if (self.__mapValuesData__[sKey] === value) return;
		} else {
			++self.__size__;
		}
		self.__mapKeysData__[sKey] = key;
		self.__mapValuesData__[sKey] = value;
	});
	return self;
};
if (setPrototypeOf) setPrototypeOf(PrimitiveMap, Map);

PrimitiveMap.prototype = create(Map.prototype, {
	constructor: d(PrimitiveMap),
	_serialize: d(function (value) {
		if (value && (typeof value.toString !== 'function')) return null;
		return String(value);
	}),
	clear: d(function () {
		if (!this.__size__) return;
		clear(this.__mapKeysData__);
		clear(this.__mapValuesData__);
		this.__size__ = 0;
		this.emit('_clear');
	}),
	delete: d(function (key) {
		var sKey = this._serialize(key);
		if (sKey == null) return false;
		if (!hasOwnProperty.call(this.__mapKeysData__, sKey)) return false;
		delete this.__mapKeysData__[sKey];
		delete this.__mapValuesData__[sKey];
		--this.__size__;
		this.emit('_delete', sKey);
		return true;
	}),
	entries: d(function () { return new Iterator(this, 'key+value'); }),
	forEach: d(function (cb/*, thisArg*/) {
		var thisArg = arguments[1], iterator, result, sKey;
		callable(cb);
		iterator = this.entries();
		result = iterator._next();
		while (result !== undefined) {
			sKey = iterator.__list__[result];
			call.call(cb, thisArg, this.__mapValuesData__[sKey],
				this.__mapKeysData__[sKey], this);
			result = iterator._next();
		}
	}),
	get: d(function (key) {
		var sKey = this._serialize(key);
		if (sKey == null) return;
		return this.__mapValuesData__[sKey];
	}),
	has: d(function (key) {
		var sKey = this._serialize(key);
		if (sKey == null) return false;
		return hasOwnProperty.call(this.__mapKeysData__, sKey);
	}),
	keys: d(function () { return new Iterator(this, 'key'); }),
	size: d.gs(function () { return this.__size__; }),
	set: d(function (key, value) {
		var sKey = this._serialize(key);
		if (sKey == null) throw new TypeError(key + " cannot be serialized");
		if (hasOwnProperty.call(this.__mapKeysData__, sKey)) {
			if (this.__mapValuesData__[sKey] === value) return this;
		} else {
			++this.__size__;
		}
		this.__mapKeysData__[sKey] = key;
		this.__mapValuesData__[sKey] = value;
		this.emit('_add', sKey);
		return this;
	}),
	values: d(function () { return new Iterator(this, 'value'); })
});
<commit_msg>Rename variable<commit_after>'use strict';

var clear          = require('es5-ext/object/clear')
  , setPrototypeOf = require('es5-ext/object/set-prototype-of')
  , validValue     = require('es5-ext/object/valid-value')
  , callable       = require('es5-ext/object/valid-callable')
  , d              = require('d')
  , iterator       = require('es6-iterator/valid-iterable')
  , forOf          = require('es6-iterator/for-of')
  , isNative       = require('../is-native-implemented')
  , MapPolyfill    = require('../polyfill')
  , Iterator       = require('../lib/primitive-iterator')

  , call = Function.prototype.call
  , create = Object.create, defineProperty = Object.defineProperty
  , defineProperties = Object.defineProperties, getPrototypeOf = Object.getPrototypeOf
  , hasOwnProperty = Object.prototype.hasOwnProperty
  , PrimitiveMap;

module.exports = PrimitiveMap = function (/*iterable, serialize*/) {
	var iterable = arguments[0], serialize = arguments[1], self;
	if (!(this instanceof PrimitiveMap)) throw new TypeError('Constructor requires \'new\'');
	if (isNative && setPrototypeOf) self = setPrototypeOf(new Map(), getPrototypeOf(this));
	else self = this;
	if (iterable != null) iterator(iterable);
	if (serialize !== undefined) {
		callable(serialize);
		defineProperty(self, '_serialize', d('', serialize));
	}
	defineProperties(self, {
		__mapKeysData__: d('c', create(null)),
		__mapValuesData__: d('c', create(null)),
		__size__: d('w', 0)
	});
	if (!iterable) return self;
	forOf(iterable, function (value) {
		var key = validValue(value)[0], sKey = self._serialize(key);
		if (sKey == null) throw new TypeError(key + " cannot be serialized");
		value = value[1];
		if (hasOwnProperty.call(self.__mapKeysData__, sKey)) {
			if (self.__mapValuesData__[sKey] === value) return;
		} else {
			++self.__size__;
		}
		self.__mapKeysData__[sKey] = key;
		self.__mapValuesData__[sKey] = value;
	});
	return self;
};
if (setPrototypeOf) setPrototypeOf(PrimitiveMap, MapPolyfill);

PrimitiveMap.prototype = create(MapPolyfill.prototype, {
	constructor: d(PrimitiveMap),
	_serialize: d(function (value) {
		if (value && (typeof value.toString !== 'function')) return null;
		return String(value);
	}),
	clear: d(function () {
		if (!this.__size__) return;
		clear(this.__mapKeysData__);
		clear(this.__mapValuesData__);
		this.__size__ = 0;
		this.emit('_clear');
	}),
	delete: d(function (key) {
		var sKey = this._serialize(key);
		if (sKey == null) return false;
		if (!hasOwnProperty.call(this.__mapKeysData__, sKey)) return false;
		delete this.__mapKeysData__[sKey];
		delete this.__mapValuesData__[sKey];
		--this.__size__;
		this.emit('_delete', sKey);
		return true;
	}),
	entries: d(function () { return new Iterator(this, 'key+value'); }),
	forEach: d(function (cb/*, thisArg*/) {
		var thisArg = arguments[1], iterator, result, sKey;
		callable(cb);
		iterator = this.entries();
		result = iterator._next();
		while (result !== undefined) {
			sKey = iterator.__list__[result];
			call.call(cb, thisArg, this.__mapValuesData__[sKey],
				this.__mapKeysData__[sKey], this);
			result = iterator._next();
		}
	}),
	get: d(function (key) {
		var sKey = this._serialize(key);
		if (sKey == null) return;
		return this.__mapValuesData__[sKey];
	}),
	has: d(function (key) {
		var sKey = this._serialize(key);
		if (sKey == null) return false;
		return hasOwnProperty.call(this.__mapKeysData__, sKey);
	}),
	keys: d(function () { return new Iterator(this, 'key'); }),
	size: d.gs(function () { return this.__size__; }),
	set: d(function (key, value) {
		var sKey = this._serialize(key);
		if (sKey == null) throw new TypeError(key + " cannot be serialized");
		if (hasOwnProperty.call(this.__mapKeysData__, sKey)) {
			if (this.__mapValuesData__[sKey] === value) return this;
		} else {
			++this.__size__;
		}
		this.__mapKeysData__[sKey] = key;
		this.__mapValuesData__[sKey] = value;
		this.emit('_add', sKey);
		return this;
	}),
	values: d(function () { return new Iterator(this, 'value'); })
});
<|endoftext|>


<commit_before>/**
 * @author Serhii Maksymchuk from Ubrainians for imCode
 * 20.02.18
 */
define(
    "imcms-document-profile-select-window-builder",
    [
        "imcms-window-builder", "imcms-bem-builder", "imcms-i18n-texts", "imcms-components-builder",
        "imcms-profiles-rest-api", "imcms-document-validation-rest-api", "imcms", "imcms-modal-window-builder"
    ],
    function (WindowBuilder, BEM, texts, components, profilesRestApi, documentValidationAPI, imcms, modal) {

        texts = texts.editors.newDocumentProfile;

        let radioButtonsGroup, $parentDocIdInput, $profilesSelect, $profileSelectBlock, $parentSelect,
            $validationErrorBlock;

        function buildProfileSelect() {
            const $profilesSelectContainer = components.selects.selectContainer("<div>", {
                id: "doc-profiles",
                text: texts.selectProfile,
                name: "profile",
                emptySelect: true,
                style: [
                    {"height": "100px"},
                    {"overflow-x": "hidden"},
                    {"overflow-y": "scroll"}
                ]
            });

            $profilesSelect = $profilesSelectContainer.getSelect();

            return new BEM({
                block: "imcms-profile-select",
                elements: {
                    "select": $profilesSelectContainer
                }
            }).buildBlockStructure("<div>", {"style": "display: none;"});
        }

        function buildParentSelect() {
            $parentDocIdInput = components.texts.textBox("<div>", {
                name: "title",
                text: texts.selectParent + ":",
                placeholder: texts.selectParentPlaceholder,
            });

            return new BEM({
                block: "imcms-parent-select",
                elements: {
                    "text-box": $parentDocIdInput
                }
            }).buildBlockStructure("<div>", {"style": "display: none;"});
        }

        let $currentDocIdOption, $profilesOption;

        function buildChoosingRadio($profileSelect, $parentSelect) {
            const $choosingTitle = components.texts.titleText("<div>", texts.chooseProfileOrParent);

            $profilesOption = components.radios.imcmsRadio("<div>", {
                text: texts.buildByProfile,
                name: "select-profile-or-doc-or-current_doc",
                value: "profile",
                click: () => {
                    $validationErrorBlock.slideUp(400);
                    $parentSelect.slideUp(400);
                    $profileSelect.slideDown(400);
                }
            }).css("display", "none");

            const $docIdOption = components.radios.imcmsRadio("<div>", {
                text: texts.buildByParent,
                name: "select-profile-or-doc-or-current_doc",
                value: "docId",
                checked: true,
                click: () => {
                    $validationErrorBlock.slideUp(400);
                    $parentSelect.slideDown(400);
                    $profileSelect.slideUp(400);
                }
            });

            $currentDocIdOption = components.radios.imcmsRadio("<div>", {
                text: texts.buildByCurrentDocId,
                name: "select-profile-or-doc-or-current_doc",
                value: "currentDocId",
                click: () => {
                    $validationErrorBlock.slideUp(400);
                    $parentSelect.slideUp(400);
                    $profileSelect.slideUp(400);
                }
            }).css("display", "none");

            radioButtonsGroup = components.radios.group($profilesOption, $docIdOption, $currentDocIdOption);

            return new BEM({
                block: "new-doc-parent-options",
                elements: {
                    "title": $choosingTitle,
                    "by-current-doc-id": $currentDocIdOption,
                    "by-profile": $profilesOption,
                    "by-doc-id": $docIdOption
                }
            }).buildBlockStructure("<div>");
        }

        function buildValidationErrorBlock() {
            return components.texts.errorText("<div>", texts.validationErrorMessage, {"style": "display: none;"});
        }

        function buildBody() {
            $profileSelectBlock = buildProfileSelect();
            $parentSelect = buildParentSelect();
            $validationErrorBlock = buildValidationErrorBlock();
            const $radioBlock = buildChoosingRadio($profileSelectBlock, $parentSelect);

            return new BEM({
                block: "imcms-document-profile",
                elements: {
                    "choose-the-way": $radioBlock,
                    "profile-select": $profileSelectBlock,
                    "parent-select": $parentSelect,
                    "validation-error": $validationErrorBlock
                }
            }).buildBlockStructure("<div>");
        }

        function onSubmit() {
            const checkedValue = radioButtonsGroup.getCheckedValue();

            if ("docId" === checkedValue) {
                const selectedParentDoc = $parentDocIdInput.getValue().trim();

                if (selectedParentDoc) {
                    documentValidationAPI.checkIsTextDocument(selectedParentDoc)
                        .done(isTextDoc => {
                            if (isTextDoc) {
                                closeWindow();
                                onProfileOrParentSelectedCallback(selectedParentDoc);
                            } else {
                                $validationErrorBlock.slideDown(400);
                            }
                        })
                        .fail(() => $validationErrorBlock.slideDown(400));
                } else {
                    $validationErrorBlock.slideDown(400);
                }
            } else if ("profile" === checkedValue) {
                const parentDocId = $profilesSelect.getSelectedValue();

                if (parentDocId) {
                    closeWindow();
                    onProfileOrParentSelectedCallback(parentDocId);

                } else {
                    $validationErrorBlock.slideDown(400);
                }
            } else if ("currentDocId" === checkedValue) {
                closeWindow();
                onProfileOrParentSelectedCallback(imcms.document.id);
            }
        }

        function buildFooter() {
            return WindowBuilder.buildFooter([
                components.buttons.positiveButton({
                    text: texts.createDocButton,
                    click: onSubmit
                })
            ]);
        }

        function buildProfileSelectWindow() {
            return new BEM({
                block: "imcms-document-profile-select-window",
                elements: {
                    "head": windowBuilder.buildHead(texts.title),
                    "body": buildBody(),
                    "footer": buildFooter()
                }
            }).buildBlockStructure("<div>");
        }

        function clear() {
            radioButtonsGroup.setCheckedValue("docId");
            $parentSelect.css("display", "none");
            $profileSelectBlock.css("display", "none");
            $parentDocIdInput.setValue('');
            $profilesSelect.selectFirst();
            $validationErrorBlock.css("display", "none");
        }

        function loadData(onParentSelected, config) {
            profilesRestApi.read()
                .done(profiles => {
                    const profilesDataMapped = profiles.map(profile => {
                        /** @namespace profile.documentName */
                        return {
                            text: profile.name,
                            "data-value": profile.documentName
                        };
                    });

                    let profilesExist = profilesDataMapped && profilesDataMapped.length;

                    if (profilesExist) {
                        components.selects.addOptionsToSelect(profilesDataMapped, $profilesSelect);
                        $profilesOption && $profilesOption.css("display", "block");
                        profilesExist = true;
                    }

                    let isInMenu = config && config.inMenu;
                    const cssDisplayValue = isInMenu ? "block" : "none";
                    $currentDocIdOption.css({"display": cssDisplayValue});

                    const checkedValue = isInMenu
                        ? "currentDocId"
                        : profilesExist ? "profile" : "docId";

                    radioButtonsGroup.setCheckedValue(checkedValue);

                    if (!isInMenu) {
                        if (profilesExist) {
                            $profileSelectBlock.css("display", "block");
                            $profilesOption.css("display", "block");

                        } else {
                            $parentSelect.css("display", "block");
                        }
                    }
                })
                .fail(() => modal.buildErrorWindow(texts.error.loadProfilesFailed));
        }

        function closeWindow() {
            windowBuilder.closeWindow();
        }

        var windowBuilder = new WindowBuilder({
            factory: buildProfileSelectWindow,
            loadDataStrategy: loadData,
            clearDataStrategy: clear,
            onEscKeyPressed: closeWindow,
            onEnterKeyPressed: onSubmit
        });

        var onProfileOrParentSelectedCallback;

        return {
            build: function (onParentSelected, config) {
                onProfileOrParentSelectedCallback = onParentSelected;
                windowBuilder.buildWindowWithShadow.apply(windowBuilder, arguments);
            }
        };
    }
);
<commit_msg>Issue IMCMS-492: GUI tweaks and fixes Item 9: - Add label when only parent document option; - Disable displaying of option when only parent document option;<commit_after>/**
 * @author Serhii Maksymchuk from Ubrainians for imCode
 * 20.02.18
 */
define(
    "imcms-document-profile-select-window-builder",
    [
        "imcms-window-builder", "imcms-bem-builder", "imcms-i18n-texts", "imcms-components-builder",
        "imcms-profiles-rest-api", "imcms-document-validation-rest-api", "imcms", "imcms-modal-window-builder"
    ],
    function (WindowBuilder, BEM, texts, components, profilesRestApi, documentValidationAPI, imcms, modal) {

        texts = texts.editors.newDocumentProfile;

        let radioButtonsGroup, $parentDocIdInput, $parentDocOptionTitle, $profilesSelect, $profileSelectBlock, $parentSelect,
            $validationErrorBlock;

        function buildProfileSelect() {
            const $profilesSelectContainer = components.selects.selectContainer("<div>", {
                id: "doc-profiles",
                text: texts.selectProfile,
                name: "profile",
                emptySelect: true,
                style: [
                    {"height": "100px"},
                    {"overflow-x": "hidden"},
                    {"overflow-y": "scroll"}
                ]
            });

            $profilesSelect = $profilesSelectContainer.getSelect();

            return new BEM({
                block: "imcms-profile-select",
                elements: {
                    "select": $profilesSelectContainer
                }
            }).buildBlockStructure("<div>", {"style": "display: none;"});
        }

        function buildParentSelect() {
            $parentDocIdInput = components.texts.textBox("<div>", {
                name: "title",
                text: texts.selectParent + ":",
                placeholder: texts.selectParentPlaceholder,
            });

            $parentDocOptionTitle = components.texts.secondaryText("<div>", texts.buildByParent).css({"display": "none"});

            return new BEM({
                block: "imcms-parent-select",
                elements: {
                    "text-box": $parentDocIdInput,
                    "option-info": $parentDocOptionTitle,
                }
            }).buildBlockStructure("<div>", {"style": "display: none;"});
        }

        let $currentDocIdOption, $profilesOption, $docIdOption;

        function buildChoosingRadio($profileSelect, $parentSelect) {
            const $choosingTitle = components.texts.titleText("<div>", texts.chooseProfileOrParent);

            $profilesOption = components.radios.imcmsRadio("<div>", {
                text: texts.buildByProfile,
                name: "select-profile-or-doc-or-current_doc",
                value: "profile",
                click: () => {
                    $validationErrorBlock.slideUp(400);
                    $parentSelect.slideUp(400);
                    $profileSelect.slideDown(400);
                }
            }).css("display", "none");

            $docIdOption = components.radios.imcmsRadio("<div>", {
                text: texts.buildByParent,
                name: "select-profile-or-doc-or-current_doc",
                value: "docId",
                checked: true,
                click: () => {
                    $validationErrorBlock.slideUp(400);
                    $parentSelect.slideDown(400);
                    $profileSelect.slideUp(400);
                }
            });

            $currentDocIdOption = components.radios.imcmsRadio("<div>", {
                text: texts.buildByCurrentDocId,
                name: "select-profile-or-doc-or-current_doc",
                value: "currentDocId",
                click: () => {
                    $validationErrorBlock.slideUp(400);
                    $parentSelect.slideUp(400);
                    $profileSelect.slideUp(400);
                }
            }).css("display", "none");

            radioButtonsGroup = components.radios.group($profilesOption, $docIdOption, $currentDocIdOption);

            return new BEM({
                block: "new-doc-parent-options",
                elements: {
                    "title": $choosingTitle,
                    "by-current-doc-id": $currentDocIdOption,
                    "by-profile": $profilesOption,
                    "by-doc-id": $docIdOption
                }
            }).buildBlockStructure("<div>");
        }

        function buildValidationErrorBlock() {
            return components.texts.errorText("<div>", texts.validationErrorMessage, {"style": "display: none;"});
        }

        function buildBody() {
            $profileSelectBlock = buildProfileSelect();
            $parentSelect = buildParentSelect();
            $validationErrorBlock = buildValidationErrorBlock();
            const $radioBlock = buildChoosingRadio($profileSelectBlock, $parentSelect);

            return new BEM({
                block: "imcms-document-profile",
                elements: {
                    "choose-the-way": $radioBlock,
                    "profile-select": $profileSelectBlock,
                    "parent-select": $parentSelect,
                    "validation-error": $validationErrorBlock
                }
            }).buildBlockStructure("<div>");
        }

        function onSubmit() {
            const checkedValue = radioButtonsGroup.getCheckedValue();

            if ("docId" === checkedValue) {
                const selectedParentDoc = $parentDocIdInput.getValue().trim();

                if (selectedParentDoc) {
                    documentValidationAPI.checkIsTextDocument(selectedParentDoc)
                        .done(isTextDoc => {
                            if (isTextDoc) {
                                closeWindow();
                                onProfileOrParentSelectedCallback(selectedParentDoc);
                            } else {
                                $validationErrorBlock.slideDown(400);
                            }
                        })
                        .fail(() => $validationErrorBlock.slideDown(400));
                } else {
                    $validationErrorBlock.slideDown(400);
                }
            } else if ("profile" === checkedValue) {
                const parentDocId = $profilesSelect.getSelectedValue();

                if (parentDocId) {
                    closeWindow();
                    onProfileOrParentSelectedCallback(parentDocId);

                } else {
                    $validationErrorBlock.slideDown(400);
                }
            } else if ("currentDocId" === checkedValue) {
                closeWindow();
                onProfileOrParentSelectedCallback(imcms.document.id);
            }
        }

        function buildFooter() {
            return WindowBuilder.buildFooter([
                components.buttons.positiveButton({
                    text: texts.createDocButton,
                    click: onSubmit
                })
            ]);
        }

        function buildProfileSelectWindow() {
            return new BEM({
                block: "imcms-document-profile-select-window",
                elements: {
                    "head": windowBuilder.buildHead(texts.title),
                    "body": buildBody(),
                    "footer": buildFooter()
                }
            }).buildBlockStructure("<div>");
        }

        function clear() {
            radioButtonsGroup.setCheckedValue("docId");
            $parentSelect.css("display", "none");
            $profileSelectBlock.css("display", "none");
            $parentDocIdInput.setValue('');
            $profilesSelect.selectFirst();
            $validationErrorBlock.css("display", "none");
        }

        function loadData(onParentSelected, config) {
            profilesRestApi.read()
                .done(profiles => {
                    const profilesDataMapped = profiles.map(profile => {
                        /** @namespace profile.documentName */
                        return {
                            text: profile.name,
                            "data-value": profile.documentName
                        };
                    });

                    let profilesExist = profilesDataMapped && profilesDataMapped.length;

                    if (profilesExist) {
                        components.selects.addOptionsToSelect(profilesDataMapped, $profilesSelect);
                        $profilesOption && $profilesOption.css("display", "block");
                        profilesExist = true;
                    }

                    const isInMenu = config && config.inMenu;
                    const cssDisplayValue = isInMenu ? "block" : "none";
                    $currentDocIdOption.css({"display": cssDisplayValue});

                    if (!profilesExist && !isInMenu) {
                        $docIdOption.css({"display": "none"});
                        $parentDocOptionTitle.css({"display": "block"});
                    }

                    const checkedValue = isInMenu
                        ? "currentDocId"
                        : profilesExist ? "profile" : "docId";

                    radioButtonsGroup.setCheckedValue(checkedValue);

                    if (!isInMenu) {
                        if (profilesExist) {
                            $profileSelectBlock.css("display", "block");
                            $profilesOption.css("display", "block");

                        } else {
                            $parentSelect.css("display", "block");
                        }
                    }
                })
                .fail(() => modal.buildErrorWindow(texts.error.loadProfilesFailed));
        }

        function closeWindow() {
            windowBuilder.closeWindow();
        }

        var windowBuilder = new WindowBuilder({
            factory: buildProfileSelectWindow,
            loadDataStrategy: loadData,
            clearDataStrategy: clear,
            onEscKeyPressed: closeWindow,
            onEnterKeyPressed: onSubmit
        });

        var onProfileOrParentSelectedCallback;

        return {
            build: function (onParentSelected, config) {
                onProfileOrParentSelectedCallback = onParentSelected;
                windowBuilder.buildWindowWithShadow.apply(windowBuilder, arguments);
            }
        };
    }
);
<|endoftext|>


<commit_before>import { createSelector } from 'reselect';
import uniqBy from 'lodash/uniqBy';
import findIndex from 'lodash/findIndex';
import { sortByKey, getColorPalette } from 'utils/data';
import { format } from 'd3-format';

// get list data
const getData = state => state.data || null;
const getSettings = state => state.settings || null;
const getLocation = state => state.location || null;
const getLocationsMeta = state => state.meta || null;
const getColors = state => state.colors || null;
const getIndicator = state => state.indicator || null;
const getLocationNames = state => state.locationNames || null;

export const getSortedData = createSelector(
  [getData, getSettings],
  (data, settings) => {
    if (!data || !data.length) return null;
    return sortByKey(
      uniqBy(data, 'id'),
      settings.unit === 'ha' ? 'gain' : 'percentage',
      true
    );
  }
);

export const getFilteredData = createSelector(
  [
    getSortedData,
    getSettings,
    getLocation,
    getLocationNames,
    getLocationsMeta,
    getColors
  ],
  (data, settings, location, locationNames, meta, colors) => {
    if (!data || !data.length) return null;
    const locationIndex = findIndex(
      data,
      d => d.id === locationNames.current.value
    );
    let trimStart = locationIndex - 2;
    let trimEnd = locationIndex + 3;
    if (locationIndex < 2) {
      trimStart = 0;
      trimEnd = 5;
    }
    if (locationIndex > data.length - 3) {
      trimStart = data.length - 5;
      trimEnd = data.length;
    }
    const dataTrimmed = data.slice(trimStart, trimEnd);
    const colorRange = getColorPalette(
      [colors.darkGreen, colors.lightGreen],
      dataTrimmed.length
    );
    return dataTrimmed.map((d, index) => {
      const locationData = meta.find(l => d.id === l.value);
      let path = '/country/';
      if (location.subRegion) {
        path += `${location.country}/${location.region}/${d.id}`;
      } else if (location.region) {
        path += `${location.country}/${d.id}`;
      } else {
        path += d.id;
      }

      return {
        ...d,
        label: (locationData && locationData.label) || '',
        color: colorRange[index],
        path,
        value: settings.unit === 'ha' ? d.gain : d.percentage
      };
    });
  }
);

export const getSentence = createSelector(
  [getData, getSettings, getIndicator, getLocationNames],
  (data, settings, indicator, locationNames) => {
    if (!data || !data.length) return null;
    const locationData = data.find(l => l.id === locationNames.current.value);
    const regionPhrase =
      indicator.value === 'gadm28'
        ? 'region-wide'
        : `in <span>${indicator && indicator.label.toLowerCase()}</span>`;

    const areaPercent = format('.1f')(locationData.percentage);
    const firstSentence = `From 2001 to 2012, ${locationNames.current &&
      locationNames.current.label} gained ${
      locationData.gain ? format('.3s')(locationData.gain) : '0'
    }ha of tree cover ${regionPhrase}`;
    const secondSentence = locationData.gain
      ? `, equivalent to a ${areaPercent}% increase relative to ${
        settings.extentYear
      } tree cover extent.`
      : '.';

    return `${firstSentence}${secondSentence}`;
  }
);
<commit_msg>add rank number<commit_after>import { createSelector } from 'reselect';
import uniqBy from 'lodash/uniqBy';
import findIndex from 'lodash/findIndex';
import { sortByKey, getColorPalette } from 'utils/data';
import { format } from 'd3-format';

// get list data
const getData = state => state.data || null;
const getSettings = state => state.settings || null;
const getLocation = state => state.location || null;
const getLocationsMeta = state => state.meta || null;
const getColors = state => state.colors || null;
const getIndicator = state => state.indicator || null;
const getLocationNames = state => state.locationNames || null;

export const getSortedData = createSelector(
  [getData, getSettings],
  (data, settings) => {
    if (!data || !data.length) return null;
    return sortByKey(
      uniqBy(data, 'id'),
      settings.unit === 'ha' ? 'gain' : 'percentage',
      true
    ).map((d, i) => ({
      ...d,
      rank: i + 1
    }));
  }
);

export const getFilteredData = createSelector(
  [
    getSortedData,
    getSettings,
    getLocation,
    getLocationNames,
    getLocationsMeta,
    getColors
  ],
  (data, settings, location, locationNames, meta, colors) => {
    if (!data || !data.length) return null;
    const locationIndex = findIndex(
      data,
      d => d.id === locationNames.current.value
    );
    let trimStart = locationIndex - 2;
    let trimEnd = locationIndex + 3;
    if (locationIndex < 2) {
      trimStart = 0;
      trimEnd = 5;
    }
    if (locationIndex > data.length - 3) {
      trimStart = data.length - 5;
      trimEnd = data.length;
    }
    const dataTrimmed = data.slice(trimStart, trimEnd);
    const colorRange = getColorPalette(
      [colors.darkGreen, colors.lightGreen],
      dataTrimmed.length
    );
    return dataTrimmed.map((d, index) => {
      const locationData = meta.find(l => d.id === l.value);
      let path = '/country/';
      if (location.subRegion) {
        path += `${location.country}/${location.region}/${d.id}`;
      } else if (location.region) {
        path += `${location.country}/${d.id}`;
      } else {
        path += d.id;
      }

      return {
        ...d,
        label: (locationData && locationData.label) || '',
        color: colorRange[index],
        path,
        value: settings.unit === 'ha' ? d.gain : d.percentage
      };
    });
  }
);

export const getSentence = createSelector(
  [getData, getSettings, getIndicator, getLocationNames],
  (data, settings, indicator, locationNames) => {
    if (!data || !data.length) return null;
    const locationData = data.find(l => l.id === locationNames.current.value);
    const regionPhrase =
      indicator.value === 'gadm28'
        ? 'region-wide'
        : `in <span>${indicator && indicator.label.toLowerCase()}</span>`;

    const areaPercent = format('.1f')(locationData.percentage);
    const firstSentence = `From 2001 to 2012, ${locationNames.current &&
      locationNames.current.label} gained ${
      locationData.gain ? format('.3s')(locationData.gain) : '0'
    }ha of tree cover ${regionPhrase}`;
    const secondSentence = locationData.gain
      ? `, equivalent to a ${areaPercent}% increase relative to ${
        settings.extentYear
      } tree cover extent.`
      : '.';

    return `${firstSentence}${secondSentence}`;
  }
);
<|endoftext|>


<commit_before>import { createSelector } from 'reselect';
import isEmpty from 'lodash/isEmpty';
import sumBy from 'lodash/sumBy';
import { format } from 'd3-format';
import moment from 'moment';
import { biomassToCO2 } from 'utils/calculations';

// get list data
const getLoss = state => state.loss || null;
const getExtent = state => state.extent || null;
const getSettings = state => state.settings || null;
const getLocationNames = state => state.locationNames || null;
const getActiveIndicator = state => state.activeIndicator || null;
const getColors = state => state.colors || null;

// get lists selected
export const chartData = createSelector(
  [getLoss, getExtent, getSettings],
  (data, extent, settings) => {
    if (!data || isEmpty(data)) return null;
    const { startYear, endYear } = settings;

    return data
      .filter(d => d.year >= startYear && d.year <= endYear)
      .map(d => ({
        ...d,
        area: d.area || 0,
        emissions: d.emissions || 0,
        percentage: (d.area && d.area && d.area / extent * 100) || 0
      }));
  }
);

export const chartConfig = createSelector([getColors], colors => ({
  xKey: 'year',
  yKeys: {
    bars: {
      area: {
        fill: colors.pink,
        background: false
      }
    }
  },
  xAxis: {
    tickFormatter: tick => moment(tick, 'YYYY').format('YY')
  },
  unit: 'ha',
  tooltip: [
    {
      key: 'year'
    },
    {
      key: 'area',
      unit: 'ha'
    },
    {
      key: 'percentage',
      unit: '%'
    }
  ]
}));

export const getSentence = createSelector(
  [chartData, getExtent, getSettings, getLocationNames, getActiveIndicator],
  (data, extent, settings, locationNames, indicator) => {
    if (!data) return null;
    const { startYear, endYear, extentYear, threshold } = settings;
    const locationLabel = locationNames.current && locationNames.current.label;
    const locationIntro = `${
      indicator.value !== 'gadm28'
        ? `<b>${indicator.label}</b> in <b>${locationLabel}</b>`
        : `<b>${locationLabel}</b>`
    }`;
    const totalLoss = (data && data.length && sumBy(data, 'area')) || 0;
    const totalEmissions =
      (data && data.length && biomassToCO2(sumBy(data, 'emissions'))) || 0;
    const percentageLoss =
      (totalLoss && extent && totalLoss / extent * 100) || 0;

    return `Between ${startYear} and ${endYear}, ${locationIntro} lost ${format(
      '.3s'
    )(totalLoss)}ha of tree cover${totalLoss ? '.' : ','} ${
      totalLoss > 0
        ? ` This loss is equal to ${format('.1f')(percentageLoss)}
      % of the regions tree cover extent in ${extentYear},
      and equivalent to ${format('.3s')(
    totalEmissions
  )}t of CO\u2082 emissions`
        : ''
    }
     with canopy density > ${threshold}%.`;
  }
);
<commit_msg>Updates TREE COVER LOSS IN X dynamic sentence<commit_after>import { createSelector } from 'reselect';
import isEmpty from 'lodash/isEmpty';
import sumBy from 'lodash/sumBy';
import { format } from 'd3-format';
import moment from 'moment';
import { biomassToCO2 } from 'utils/calculations';

// get list data
const getLoss = state => state.loss || null;
const getExtent = state => state.extent || null;
const getSettings = state => state.settings || null;
const getLocationNames = state => state.locationNames || null;
const getActiveIndicator = state => state.activeIndicator || null;
const getColors = state => state.colors || null;

// get lists selected
export const chartData = createSelector(
  [getLoss, getExtent, getSettings],
  (data, extent, settings) => {
    if (!data || isEmpty(data)) return null;
    const { startYear, endYear } = settings;

    return data
      .filter(d => d.year >= startYear && d.year <= endYear)
      .map(d => ({
        ...d,
        area: d.area || 0,
        emissions: d.emissions || 0,
        percentage: (d.area && d.area && d.area / extent * 100) || 0
      }));
  }
);

export const chartConfig = createSelector([getColors], colors => ({
  xKey: 'year',
  yKeys: {
    bars: {
      area: {
        fill: colors.pink,
        background: false
      }
    }
  },
  xAxis: {
    tickFormatter: tick => moment(tick, 'YYYY').format('YY')
  },
  unit: 'ha',
  tooltip: [
    {
      key: 'year'
    },
    {
      key: 'area',
      unit: 'ha'
    },
    {
      key: 'percentage',
      unit: '%'
    }
  ]
}));

export const getSentence = createSelector(
  [chartData, getExtent, getSettings, getLocationNames, getActiveIndicator],
  (data, extent, settings, locationNames, indicator) => {
    if (!data) return null;
    const { startYear, endYear, extentYear, threshold } = settings;
    const locationLabel = locationNames.current && locationNames.current.label;
    const locationIntro = `${
      indicator.value !== 'gadm28'
        ? `<b>${indicator.label}</b> in <b>${locationLabel}</b>`
        : `<b>${locationLabel}</b>`
    }`;
    const totalLoss = (data && data.length && sumBy(data, 'area')) || 0;
    const totalEmissions =
      (data && data.length && biomassToCO2(sumBy(data, 'emissions'))) || 0;
    const percentageLoss =
      (totalLoss && extent && totalLoss / extent * 100) || 0;

    return `Between ${startYear} and ${endYear}, ${locationIntro} lost ${format(
      '.3s'
    )(totalLoss)}ha of tree cover${totalLoss ? '.' : ','} ${
      totalLoss > 0
        ? ` This loss is equal to ${format('.1f')(percentageLoss)}
      % of the area's tree cover extent in ${extentYear},
      and equivalent to ${format('.3s')(
    totalEmissions
  )}t of CO\u2082 emissions`
        : ''
    }
     with canopy density > ${threshold}%.`;
  }
);
<|endoftext|>


<commit_before>var dna = require('../');
var fs = require('fs');
var path = require('path');

var txt = fs.readFileSync(path.join(__dirname, 'dna.txt'));

dna.parse(txt, function(err, snps){
  fs.writeFileSync(path.join(__dirname, 'dna.json'), JSON.stringify(snps));
});<commit_msg>encoding string required for fs.readFileSync<commit_after>var dna = require('../');
var fs = require('fs');
var path = require('path');

var txt = fs.readFileSync(path.join(__dirname, 'dna.txt'), 'utf-8');

dna.parse(txt, function(err, snps){
  fs.writeFileSync(path.join(__dirname, 'dna.json'), JSON.stringify(snps));
});<|endoftext|>


<commit_before>$(document).ready(function() {
    update_number_graphs();

    if ($('#permalink')) {
        var text = $('#permalink').val();
        text = window.location.protocol + window.location.host + text;
        $('#permalink').val(text);
    }
    // Bind the graph time range selection buttons
    $('.options .currentTime').live('click', function() {
        var dateRangeButton = this;

        if ($('#sync').prop('checked')) {
            var from = $('input[name=from]');
            var to = $('input[name=to]');
        } else {
            var dates = $(dateRangeButton).parents('.options')
                .siblings('.daterange');
            var from = $(dates).children('[name=from]');
            var to = $(dates).children('[name=to]');
        }

        var toDate = new Date();
        var fromDate = new Date();

        var timezoneString;
        if ($('#utc').prop('checked')) {
            var offset = new Date().getTimezoneOffset();
            toDate = toDate.setTimezoneOffset(0);
            fromDate = fromDate.setTimezoneOffset(0);
            timezoneString = "+0000";
        } else {
            timezoneString = getTimezoneString(fromDate);
        }

        if ($(dateRangeButton).attr('name') == 'day') {
            fromDate.setDate(fromDate.getDate()-1);
        } else if ($(dateRangeButton).attr('name') == 'week') {
            fromDate.setDate(fromDate.getDate()-7);
        } else if ($(dateRangeButton).attr('name') == 'month') {
            fromDate.setMonth(fromDate.getMonth()-1);
        } else if ($(dateRangeButton).attr('name') == 'year') {
            fromDate.setFullYear(fromDate.getFullYear()-1);
        }

        var dateFormat = 'MM/dd/yyyy HH:mm ';
        from.val(fromDate.toString(dateFormat) + timezoneString)
        to.val(toDate.toString(dateFormat) + timezoneString)

        updateZoom(from.first().parent().siblings('.graph').parent(),
            fromDate, toDate);
    });

    $('#localtime, #utc').bind('change', function() {
        // Guarantee that localstorage gets the change before redrawing graphs
        $('#configurator').trigger('change');
        graphs = $('.graph');
        graphs.each(function(index, element) {
            if ($(element).data('data')) {
                redrawGraph(element, $(element).data('data'));
            }
        });
    });

    // Autocomplete anything with class = "... autocomplete ..."
    $('.autocomplete').each(function () {
        $(this).autocomplete ( { source : "/railroad/ajax/autocomplete/" +
            $(this).attr('name'), minLength: 1, autoFocus: true})
    });

    //Make it so pressing enter triggers the add graphs button
    $('#host,#service,#group').live('keypress', function(e) {
        if (e.keyCode === 13) {
            $('#add').trigger('click');
        }
    });

    $('#cleargraphs').click(function () {
        $('#graphs').data('meta', []);
        selectServiceObjs();
    });

    $('.graphcheckbox').change(function () {
        var checkp = true;
        var checkboxes = $('.service_row').filter('visible')
            .find('.graphcheckbox');
        checkboxes.each(function (index, element) {
            if (  ! $(element).prop('checked') ) {
                checkp = false;
            }
        });
        $('.checkall').prop('checked', checkp);
    });

    $('#clearform').bind('click', function () {
        $('#host').val("");
        $('#group').val("");
        $('#service').val("");
    });

    // Downtime requests
    $('#downtime-from, #downtime-to').val('');
    $('#downtime-comment').val('');

    makeDatetimePicker($('#downtime-from').first());
    makeDatetimePicker($('#downtime-to').last());
    $('#configurator #downtime-submit').bind('click', function() {
        $('#downtime-submit').parent().after(
            '');

        // gather data
        var expr = '';
        var checkedServiceRows =
            $('.service_row').filter(
            function(index) {
                return $(this).find('.controls input')
                    .filter(':checked').length > 0;
            });

        if ($('#downtime-host').prop('checked')) {
            var hosts = [];
            $(checkedServiceRows).find('dd[name=host]')
                .each(function(index, element) {
                    hosts.push('host:' + $(element).text().trim());
                });
            hosts = hosts.uniqueList();
            expr = hosts.join(' or ')
        } else {
            var hosts = [];
            var services = [];
            var objs = [];
            $(checkedServiceRows).find('dd[name=host]')
                .each(function(index, element) {
                    hosts.push('host:"' + $(element).text().trim() + '"');
                });
            $(checkedServiceRows).find('dd[name=service]')
                .each(function(index, element) {
                    services.push('service:"' + $(element).text().trim() + '"');
                });
            for (var i=0; i<hosts.length; i++) {
                objs.push(hosts[i] + ' and ' + services[i]);
            }
            objs = objs.uniqueList();
            expr = '(' + (objs.join(') or (')) + ')';
        }

        if (!expr) {
            console.log('no graphs')
            return;
        }

        var from = $('#downtime-from').datepicker('getDate');
        var to = $('#downtime-to').datepicker('getDate');

        var now = new Date();
        if (!(from && to) || from < now || to < now) {
            $('#downtimeLoading').after('You must enter a future date.');
            $('#downtimeLoading').remove();

            setTimeout(function() {
                $('#downtimeError').fadeOut(function() {
                    $('#downtimeError').remove();
                });
            }, 5000);
            console.log('invalid dates');
            return;
        }

        // Correct for time zones, since the datetimepicker doesn't store the
        // time zone. *glare*
        if ($('#utc').prop('checked')) {
            from.setTimezoneOffset(0);
            to.setTimezoneOffset(0);
        }
        from = Math.round(from.getTime() / 1000.0);
        to = Math.round(to.getTime() / 1000.0);

        var comment = $('#downtime-comment').prop('value');
        if (!expr) {
            console.log('no comment');
            return;
        }

        var user = $('#remoteuserid').text().trim();

        var args = [expr, from, to, user, comment]
        var data = {
            'command': 'scheduleDowntime',
            'args': JSON.stringify(args),
        }

        $.ajax({
            url: '/railroad/ajax/xmlrpc',
            data: data,
            dataType: 'text',
            success: function(cancellationCode) {
                console.log(cancellationCode);
                $('#downtimeLoading').after(('' +
                    'Success! Cancellation code: {0}')
                    .format(cancellationCode));
                $('#downtimeLoading').remove();
            },
            error: function () {
                console.log('error');
                $('#downtimeLoading').after(
                    'There was an error.');
                $('#downtimeLoading').remove();
            }
        });
    });

    /**** Tool bar ****/
    bindMenu($('#checkall'), $('#selectall.menu'));
    $('#selectall.menu li').bind('click', function(e) {
        switch ($(this).attr('name')) {
            case 'all':
                $('.service_row .controls input[type=checkbox]')
                    .prop('checked', true);
                break;
            case 'none':
                $('.service_row .controls input[type=checkbox]')
                    .prop('checked', false);
                break;
            case 'state_ok':
            case 'state_warning':
            case 'state_critical':
            case 'state_unknown':
                var button = this;
                $('.service_row').filter(':visible')
                .each(function(index, elem) {
                    var className = $(button).attr('name');
                    if ($(elem).children('.status_text').hasClass(className)) {
                        $(elem).children('.controls').children('input')
                            .prop('checked', true);
                    }
                });
                break;
        }
        $('.graphcheckbox').trigger('change');
        $('#selectall.menu').hide();
    });

    $('#remove_checked').bind('click', function() {
        var toRemove = [];
        var count = 0;
        $('.service_row').each(function(index, element) {
            if ($(element).find('.graphcheckbox').prop('checked')) {
                console.log($(element));
                toRemove.push($(element).find('.graphInfo'));
            }
        });
        if (toRemove.length > 0) {
            var meta = $('#graphs').data('meta');
            meta.removeMatching(function(e) {
                for (var i=0; i<toRemove.length; i++) {
                    if (toRemove[i].hasClass(e['slug'])) {
                        return true;
                    }
                }
                return false;
            });
            selectServiceObjs();
        }
        $('#checkall input').prop('checked', false);
    });
    $('#expand_checked').bind('click', function() {
        allChecked(expand_row);
    });
    $('#collapse_checked').bind('click', function() {
        allChecked(collapse_row);
    });

    bindMenu($('#sortby'), $('#sortbymenu'));
    $('#sortbymenu li').bind('click', function(e) {
        var name = $(this).attr('name');
        sortGraphs(name, !!$('#sortdirection').data('ascending'));

        $('#sortbymenu').hide();
        $('#sortby').data('lastSort', name);
    });
    $('#sortdirection').bind('click', function(e) {
        var name = $('#sortby').data('lastSort');
        if (!name) {
            name = 'host';
        }

        var ascend = !$(this).data('ascending');
        $(this).data('ascending', ascend);
        $(this).children('div').toggleClass('arrow_s_line')
                               .toggleClass('arrow_n_line');

        sortGraphs(name, ascend);
    });

    $('#check_controls input[type=checkbox]').bind('click', function(event) {
        $('.service_row .controls input[type=checkbox]').prop('checked',
            $(this).prop('checked'));
        // Don't trigger the click event of the parent
        event.stopPropagation();
    });

    // Handle configurator form submissions
    $('#configurator #add').bind('click', function() {
        var fields = $('#configurator').serialize();
        $('#clearform').trigger('click');
        getServiceObjs(fields);
        return false;
    });

    // *************************** Row manipulations ***************************
    // Expand all/of type buttons
    $('#expansion_by_type').find('input').bind('change', function() {
        //To shorten the else if line below to < 80 chars
        var allCheckboxes = $(this).parent().siblings().children('input');
        if (! $(this).prop('checked')) {
            $('#expandall').prop('checked', false);
        } else if ($(allCheckboxes).not(':checked').length == 0) {
            // If all inputs are checked
            $('#expandall').prop('checked', true);
        }
    });

    $('#expandall').change(function() {
        var state = $(this).prop('checked');
        $('#expansion_by_type input').prop('checked', state);
    });

    /********** Page manipulations **********/
    // Note that page numbers are 0 based.
    $('#nextpage').bind('click', function() {
        var start = $('#graphs').data('start');
        var totalgraphs;
        if ( $('#graphs').data('meta') ) {
            totalgraphs = $('#graphs').data('meta').length;
        } else {
            console.log ('There was an error determining how many' +
                ' total graphs there are');
            return;
        }
        var perpage = getPerPage();
        var enabled = !!$(this).data('enabled');
        if (enabled && start <= totalgraphs - perpage) {
            start += perpage;
            $('#graphs').data('start', start);
            selectServiceObjs();
        }
    });
    $('#prevpage').bind('click', function() {
        var start = $('#graphs').data('start');
        var enabled = !!$(this).data('enabled');
        var perpage = getPerPage();
        if (enabled && start > 0) {
            start -= perpage;
            $('#graphs').data('start', start);
            selectServiceObjs();
        }
    });

    /********** Load preloaded graphs onto the page **********/
    var json = $('#json_services').text();
    json = unescape(json).trim();
    if (json) {
        var meta = $.parseJSON(json);
        $('#graphs').data('meta', meta);
        selectServiceObjs();
    }

    // Start the AJAX graph refreshes
    setTimeout(autoFetchData, 60 * 1000);

    // Permalink setup
    $('#closePermalinkDescription').click(function () {
        $('#permalinkDiv').hide();
    });

    $('#generateLink').click(function () {
        if (!$('#generateLink').data('description')) {
            $('#generateLink').text('Done');
            $('#permalinkDiv').show();
            $('#permalinkDiv').position({
                my: 'right top',
                at: 'left top',
                of: $('#generateLink')});

            $('#generateLink').data('description', true);
        } else {
            $('#permalinkDiv').hide();
            $('#generateLink').html(
                '');
            servicesList = generateState();
            $.ajax({
                data: {"services" :servicesList,
                    description: $('#permalinkDescription').val()},
                url: '/railroad/permalink/generate/',
                type: 'POST',
                success: function (link, textStatus, XMLHttpRequest) {
                        var text = window.location.protocol + "//" +
                            window.location.host +"/railroad/permalink/" + link;
                        $('#generateLink').before('Permalink:' +
                            '<input id="permalink" type="text"/>');
                        $('#permalink').val(text).select();
                        $('#permalink').attr('readonly', true);
                        $('#generateLink').remove();
                        $('#permalinkLoading').remove();
                    },
                error: function (error, textStatus, XMLHttpRequest) {
                        console.log("there was an error");
                        $('#generateLink').html('Get Permalink');
                        $('#generateLink')
                            .before('Error');
                        setTimeout(function() {
                            $('#generateLink').siblings('.error').fadeOut(1000,
                                function() { $(this).remove(); });
                        }, 3000);
                        $('#generateLink').data('description', '');
                    },
            });
        }
    });
});
<commit_msg>Make scheduling downtime nicer. Tweak start dates to be in the future.<commit_after>$(document).ready(function() {
    update_number_graphs();

    if ($('#permalink')) {
        var text = $('#permalink').val();
        text = window.location.protocol + window.location.host + text;
        $('#permalink').val(text);
    }
    // Bind the graph time range selection buttons
    $('.options .currentTime').live('click', function() {
        var dateRangeButton = this;

        if ($('#sync').prop('checked')) {
            var from = $('input[name=from]');
            var to = $('input[name=to]');
        } else {
            var dates = $(dateRangeButton).parents('.options')
                .siblings('.daterange');
            var from = $(dates).children('[name=from]');
            var to = $(dates).children('[name=to]');
        }

        var toDate = new Date();
        var fromDate = new Date();

        var timezoneString;
        if ($('#utc').prop('checked')) {
            var offset = new Date().getTimezoneOffset();
            toDate = toDate.setTimezoneOffset(0);
            fromDate = fromDate.setTimezoneOffset(0);
            timezoneString = "+0000";
        } else {
            timezoneString = getTimezoneString(fromDate);
        }

        if ($(dateRangeButton).attr('name') == 'day') {
            fromDate.setDate(fromDate.getDate()-1);
        } else if ($(dateRangeButton).attr('name') == 'week') {
            fromDate.setDate(fromDate.getDate()-7);
        } else if ($(dateRangeButton).attr('name') == 'month') {
            fromDate.setMonth(fromDate.getMonth()-1);
        } else if ($(dateRangeButton).attr('name') == 'year') {
            fromDate.setFullYear(fromDate.getFullYear()-1);
        }

        var dateFormat = 'MM/dd/yyyy HH:mm ';
        from.val(fromDate.toString(dateFormat) + timezoneString)
        to.val(toDate.toString(dateFormat) + timezoneString)

        updateZoom(from.first().parent().siblings('.graph').parent(),
            fromDate, toDate);
    });

    $('#localtime, #utc').bind('change', function() {
        // Guarantee that localstorage gets the change before redrawing graphs
        $('#configurator').trigger('change');
        graphs = $('.graph');
        graphs.each(function(index, element) {
            if ($(element).data('data')) {
                redrawGraph(element, $(element).data('data'));
            }
        });
    });

    // Autocomplete anything with class = "... autocomplete ..."
    $('.autocomplete').each(function () {
        $(this).autocomplete ( { source : "/railroad/ajax/autocomplete/" +
            $(this).attr('name'), minLength: 1, autoFocus: true})
    });

    //Make it so pressing enter triggers the add graphs button
    $('#host,#service,#group').live('keypress', function(e) {
        if (e.keyCode === 13) {
            $('#add').trigger('click');
        }
    });

    $('#cleargraphs').click(function () {
        $('#graphs').data('meta', []);
        selectServiceObjs();
    });

    $('.graphcheckbox').change(function () {
        var checkp = true;
        var checkboxes = $('.service_row').filter('visible')
            .find('.graphcheckbox');
        checkboxes.each(function (index, element) {
            if (  ! $(element).prop('checked') ) {
                checkp = false;
            }
        });
        $('.checkall').prop('checked', checkp);
    });

    $('#clearform').bind('click', function () {
        $('#host').val("");
        $('#group').val("");
        $('#service').val("");
    });

    // Downtime requests
    $('#downtime-from, #downtime-to').val('');
    $('#downtime-comment').val('');

    makeDatetimePicker($('#downtime-from').first());
    makeDatetimePicker($('#downtime-to').last());

    var makeDowntimeError = function(err) {
        $('#downtime-submit')
            .after('{0}'
                .format(err));

        setTimeout(function() {
            $('#downtimeError').fadeOut(function() {
                $('#downtimeError').remove();
            });
        }, 5000);
        console.log(err);
    }

    $('#configurator #downtime-submit').bind('click', function() {
        $('#downtime-submit').parent().after(
            '');

        // gather data
        var expr = '';
        var checkedServiceRows =
            $('.service_row').filter(
            function(index) {
                return $(this).find('.controls input')
                    .filter(':checked').length > 0;
            });

        if ($('#downtime-host').prop('checked')) {
            var hosts = [];
            $(checkedServiceRows).find('dd[name=host]')
                .each(function(index, element) {
                    hosts.push('host:' + $(element).text().trim());
                });
            hosts = hosts.uniqueList();
            expr = hosts.join(' or ')
        } else {
            var hosts = [];
            var services = [];
            var objs = [];
            $(checkedServiceRows).find('dd[name=host]')
                .each(function(index, element) {
                    hosts.push('host:"' + $(element).text().trim() + '"');
                });
            $(checkedServiceRows).find('dd[name=service]')
                .each(function(index, element) {
                    services.push('service:"' + $(element).text().trim() + '"');
                });
            for (var i=0; i<hosts.length; i++) {
                objs.push(hosts[i] + ' and ' + services[i]);
            }
            objs = objs.uniqueList();
            expr = '(' + (objs.join(') or (')) + ')';
        }

        if (!expr) {
            makeDowntimeError("No graphs selected.");
            $('#downtimeLoading').remove();
            return;
        }

        var from = $('#downtime-from').datepicker('getDate');
        var to = $('#downtime-to').datepicker('getDate');

        var about_now = new Date().add({minutes: 5});
        if (from < about_now) {
            from = about_now;
        }
        if (!(from && to)) {
            makeDowntimeError("Invalid dates!");
            $('#downtimeLoading').remove();
            return;
        }
        if (to < about_now) {
            makeDowntimeError("Can't schedule downtimes in the past.");
            $('#downtimeLoading').remove();
            return;
        }

        // Correct for time zones, since the datetimepicker doesn't store the
        // time zone. *glare*
        if ($('#utc').prop('checked')) {
            from.setTimezoneOffset(0);
            to.setTimezoneOffset(0);
        }
        from = Math.round(from.getTime() / 1000.0);
        to = Math.round(to.getTime() / 1000.0);

        var comment = $('#downtime-comment').prop('value');
        if (!expr) {
            console.log('no comment');
            return;
        }

        var user = $('#remoteuserid').text().trim();

        var args = [expr, from, to, user, comment]
        var data = {
            'command': 'scheduleDowntime',
            'args': JSON.stringify(args),
        }

        $.ajax({
            url: '/railroad/ajax/xmlrpc',
            data: data,
            dataType: 'text',
            success: function(cancellationCode) {
                console.log(cancellationCode);
                $('#downtimeLoading').after(('' +
                    'Success! Cancellation code: {0}')
                    .format(cancellationCode));
                $('#downtimeLoading').remove();
            },
            error: function () {
                makeDowntimeError("There was an error.");
                $('#downtimeLoading').remove();
            }
        });
    });

    /**** Tool bar ****/
    bindMenu($('#checkall'), $('#selectall.menu'));
    $('#selectall.menu li').bind('click', function(e) {
        switch ($(this).attr('name')) {
            case 'all':
                $('.service_row .controls input[type=checkbox]')
                    .prop('checked', true);
                break;
            case 'none':
                $('.service_row .controls input[type=checkbox]')
                    .prop('checked', false);
                break;
            case 'state_ok':
            case 'state_warning':
            case 'state_critical':
            case 'state_unknown':
                var button = this;
                $('.service_row').filter(':visible')
                .each(function(index, elem) {
                    var className = $(button).attr('name');
                    if ($(elem).children('.status_text').hasClass(className)) {
                        $(elem).children('.controls').children('input')
                            .prop('checked', true);
                    }
                });
                break;
        }
        $('.graphcheckbox').trigger('change');
        $('#selectall.menu').hide();
    });

    $('#remove_checked').bind('click', function() {
        var toRemove = [];
        var count = 0;
        $('.service_row').each(function(index, element) {
            if ($(element).find('.graphcheckbox').prop('checked')) {
                console.log($(element));
                toRemove.push($(element).find('.graphInfo'));
            }
        });
        if (toRemove.length > 0) {
            var meta = $('#graphs').data('meta');
            meta.removeMatching(function(e) {
                for (var i=0; i<toRemove.length; i++) {
                    if (toRemove[i].hasClass(e['slug'])) {
                        return true;
                    }
                }
                return false;
            });
            selectServiceObjs();
        }
        $('#checkall input').prop('checked', false);
    });
    $('#expand_checked').bind('click', function() {
        allChecked(expand_row);
    });
    $('#collapse_checked').bind('click', function() {
        allChecked(collapse_row);
    });

    bindMenu($('#sortby'), $('#sortbymenu'));
    $('#sortbymenu li').bind('click', function(e) {
        var name = $(this).attr('name');
        sortGraphs(name, !!$('#sortdirection').data('ascending'));

        $('#sortbymenu').hide();
        $('#sortby').data('lastSort', name);
    });
    $('#sortdirection').bind('click', function(e) {
        var name = $('#sortby').data('lastSort');
        if (!name) {
            name = 'host';
        }

        var ascend = !$(this).data('ascending');
        $(this).data('ascending', ascend);
        $(this).children('div').toggleClass('arrow_s_line')
                               .toggleClass('arrow_n_line');

        sortGraphs(name, ascend);
    });

    $('#check_controls input[type=checkbox]').bind('click', function(event) {
        $('.service_row .controls input[type=checkbox]').prop('checked',
            $(this).prop('checked'));
        // Don't trigger the click event of the parent
        event.stopPropagation();
    });

    // Handle configurator form submissions
    $('#configurator #add').bind('click', function() {
        var fields = $('#configurator').serialize();
        $('#clearform').trigger('click');
        getServiceObjs(fields);
        return false;
    });

    // *************************** Row manipulations ***************************
    // Expand all/of type buttons
    $('#expansion_by_type').find('input').bind('change', function() {
        //To shorten the else if line below to < 80 chars
        var allCheckboxes = $(this).parent().siblings().children('input');
        if (! $(this).prop('checked')) {
            $('#expandall').prop('checked', false);
        } else if ($(allCheckboxes).not(':checked').length == 0) {
            // If all inputs are checked
            $('#expandall').prop('checked', true);
        }
    });

    $('#expandall').change(function() {
        var state = $(this).prop('checked');
        $('#expansion_by_type input').prop('checked', state);
    });

    /********** Page manipulations **********/
    // Note that page numbers are 0 based.
    $('#nextpage').bind('click', function() {
        var start = $('#graphs').data('start');
        var totalgraphs;
        if ( $('#graphs').data('meta') ) {
            totalgraphs = $('#graphs').data('meta').length;
        } else {
            console.log ('There was an error determining how many' +
                ' total graphs there are');
            return;
        }
        var perpage = getPerPage();
        var enabled = !!$(this).data('enabled');
        if (enabled && start <= totalgraphs - perpage) {
            start += perpage;
            $('#graphs').data('start', start);
            selectServiceObjs();
        }
    });
    $('#prevpage').bind('click', function() {
        var start = $('#graphs').data('start');
        var enabled = !!$(this).data('enabled');
        var perpage = getPerPage();
        if (enabled && start > 0) {
            start -= perpage;
            $('#graphs').data('start', start);
            selectServiceObjs();
        }
    });

    /********** Load preloaded graphs onto the page **********/
    var json = $('#json_services').text();
    json = unescape(json).trim();
    if (json) {
        var meta = $.parseJSON(json);
        $('#graphs').data('meta', meta);
        selectServiceObjs();
    }

    // Start the AJAX graph refreshes
    setTimeout(autoFetchData, 60 * 1000);

    // Permalink setup
    $('#closePermalinkDescription').click(function () {
        $('#permalinkDiv').hide();
    });

    $('#generateLink').click(function () {
        if (!$('#generateLink').data('description')) {
            $('#generateLink').text('Done');
            $('#permalinkDiv').show();
            $('#permalinkDiv').position({
                my: 'right top',
                at: 'left top',
                of: $('#generateLink')});

            $('#generateLink').data('description', true);
        } else {
            $('#permalinkDiv').hide();
            $('#generateLink').html(
                '');
            servicesList = generateState();
            $.ajax({
                data: {"services" :servicesList,
                    description: $('#permalinkDescription').val()},
                url: '/railroad/permalink/generate/',
                type: 'POST',
                success: function (link, textStatus, XMLHttpRequest) {
                        var text = window.location.protocol + "//" +
                            window.location.host +"/railroad/permalink/" + link;
                        $('#generateLink').before('Permalink:' +
                            '<input id="permalink" type="text"/>');
                        $('#permalink').val(text).select();
                        $('#permalink').attr('readonly', true);
                        $('#generateLink').remove();
                        $('#permalinkLoading').remove();
                    },
                error: function (error, textStatus, XMLHttpRequest) {
                        console.log("there was an error");
                        $('#generateLink').html('Get Permalink');
                        $('#generateLink')
                            .before('Error');
                        setTimeout(function() {
                            $('#generateLink').siblings('.error').fadeOut(1000,
                                function() { $(this).remove(); });
                        }, 3000);
                        $('#generateLink').data('description', '');
                    },
            });
        }
    });
});
<|endoftext|>