<commit_before>/*
Copyright 2019 New Vector Ltd
Copyright 2020 The Matrix.org Foundation C.I.C.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import React from 'react';
import PropTypes from 'prop-types';
import {_t, getCurrentLanguage} from "../../../../../languageHandler";
import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
import AccessibleButton from "../../../elements/AccessibleButton";
import SdkConfig from "../../../../../SdkConfig";
import createRoom from "../../../../../createRoom";
import Modal from "../../../../../Modal";
import * as sdk from "../../../../../";
import PlatformPeg from "../../../../../PlatformPeg";
import * as KeyboardShortcuts from "../../../../../accessibility/KeyboardShortcuts";
import UpdateCheckButton from "../../UpdateCheckButton";

export default class HelpUserSettingsTab extends React.Component {
    static propTypes = {
        closeSettingsFn: PropTypes.func.isRequired,
    };

    constructor() {
        super();

        this.state = {
            appVersion: null,
            canUpdate: false,
        };
    }

    componentDidMount(): void {
        PlatformPeg.get().getAppVersion().then((ver) => this.setState({appVersion: ver})).catch((e) => {
            console.error("Error getting vector version: ", e);
        });
        PlatformPeg.get().canSelfUpdate().then((v) => this.setState({canUpdate: v})).catch((e) => {
            console.error("Error getting self updatability: ", e);
        });
    }

    _onClearCacheAndReload = (e) => {
        if (!PlatformPeg.get()) return;

        // Dev note: please keep this log line, it's useful when troubleshooting a MatrixClient suddenly
        // stopping in the middle of the logs.
        console.log("Clear cache & reload clicked");
        MatrixClientPeg.get().stopClient();
        MatrixClientPeg.get().store.deleteAllData().then(() => {
            PlatformPeg.get().reload();
        });
    };

    _onBugReport = (e) => {
        const BugReportDialog = sdk.getComponent("dialogs.BugReportDialog");
        if (!BugReportDialog) {
            return;
        }
        Modal.createTrackedDialog('Bug Report Dialog', '', BugReportDialog, {});
    };

    _onStartBotChat = (e) => {
        this.props.closeSettingsFn();
        createRoom({
            dmUserId: SdkConfig.get().welcomeUserId,
            andView: true,
        });
    };

    _showSpoiler = (event) => {
        const target = event.target;
        target.innerHTML = target.getAttribute('data-spoiler');

        const range = document.createRange();
        range.selectNodeContents(target);

        const selection = window.getSelection();
        selection.removeAllRanges();
        selection.addRange(range);
    };

    _renderLegal() {
        const tocLinks = SdkConfig.get().terms_and_conditions_links;
        if (!tocLinks) return null;

        const legalLinks = [];
        for (const tocEntry of SdkConfig.get().terms_and_conditions_links) {
            legalLinks.push(

                {tocEntry.text}

);
        }

        return (

                {_t("Legal")}

                    {legalLinks}

        );
    }

    _renderCredits() {
        // Note: This is not translated because it is legal text.
        // Also,   is ugly but necessary.
        return (

                {_t("Credits")}

                        The
                        default cover photo is ©
                        Jesús Roncero{' '}
                        used under the terms of

                        CC-BY-SA 4.0.

                        The  twemoji-colr font is ©
                        Mozilla Foundation{' '}
                        used under the terms of

                        Apache 2.0.

                        The
                        Twemoji emoji art is ©
                        Twitter, Inc and other
                        contributors used under the terms of

                        CC-BY 4.0.

        );
    }

    render() {
        const brand = SdkConfig.get().brand;

        let faqText = _t(
            'For help with using %(brand)s, click here.',
            {
                brand,
            },
            {
                'a': (sub) =>
                    {sub}
                ,
            },
        );
        if (SdkConfig.get().welcomeUserId && getCurrentLanguage().startsWith('en')) {
            faqText = (

                    {_t(
                        'For help with using %(brand)s, click here or start a chat with our ' +
                        'bot using the button below.',
                        {
                            brand,
                        },
                        {
                            'a': (sub) =>
                                {sub}
                            ,
                        },
                    )}

                        <AccessibleButton onClick={this._onStartBotChat} kind='primary'>
                            {_t("Chat with %(brand)s Bot", { brand })}
                        </AccessibleButton>

            );
        }

        const appVersion = this.state.appVersion || 'unknown';

        let olmVersion = MatrixClientPeg.get().olmVersion;
        olmVersion = olmVersion ? `${olmVersion[0]}.${olmVersion[1]}.${olmVersion[2]}` : '<not-enabled>';

        let updateButton = null;
        if (this.state.canUpdate) {
            updateButton = <UpdateCheckButton />;
        }

        return (

{_t("Help & About")}

                    {_t('Bug reporting')}

                        {
                            _t( "If you've submitted a bug via GitHub, debug logs can help " +
                                "us track down the problem. Debug logs contain application " +
                                "usage data including your username, the IDs or aliases of " +
                                "the rooms or groups you have visited and the usernames of " +
                                "other users. They do not contain messages.",
                            )
                        }

                            <AccessibleButton onClick={this._onBugReport} kind='primary'>
                                {_t("Submit debug logs")}
                            </AccessibleButton>

                            <AccessibleButton onClick={this._onClearCacheAndReload} kind='danger'>
                                {_t("Clear cache and reload")}
                            </AccessibleButton>

                        {
                            _t( "To report a Matrix-related security issue, please read the Matrix.org " +
                                "Security Disclosure Policy.", {},
                                {
                                    'a': (sub) =>
                                        {sub},
                                })
                        }

                    {_t("FAQ")}

                        {faqText}

                    <AccessibleButton kind="primary" onClick={KeyboardShortcuts.toggleDialog}>
                        { _t("Keyboard Shortcuts") }
                    </AccessibleButton>

                    {_t("Versions")}

                        {_t("%(brand)s version:", { brand })} {appVersion}

                        {_t("olm version:")} {olmVersion}

                        {updateButton}

                {this._renderLegal()}
                {this._renderCredits()}

                    {_t("Advanced")}

                        {_t("Homeserver is")} {MatrixClientPeg.get().getHomeserverUrl()}

                        {_t("Identity Server is")} {MatrixClientPeg.get().getIdentityServerUrl()}

                        {_t("Access Token:") + ' '}
                        <AccessibleButton element="span" onClick={this._showSpoiler}
                                          data-spoiler={MatrixClientPeg.get().getAccessToken()}>
                            <{ _t("click to reveal") }>
                        </AccessibleButton>

        );
    }
}
<commit_msg>Update attribution<commit_after>/*
Copyright 2019 New Vector Ltd
Copyright 2020 The Matrix.org Foundation C.I.C.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import React from 'react';
import PropTypes from 'prop-types';
import {_t, getCurrentLanguage} from "../../../../../languageHandler";
import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
import AccessibleButton from "../../../elements/AccessibleButton";
import SdkConfig from "../../../../../SdkConfig";
import createRoom from "../../../../../createRoom";
import Modal from "../../../../../Modal";
import * as sdk from "../../../../../";
import PlatformPeg from "../../../../../PlatformPeg";
import * as KeyboardShortcuts from "../../../../../accessibility/KeyboardShortcuts";
import UpdateCheckButton from "../../UpdateCheckButton";

export default class HelpUserSettingsTab extends React.Component {
    static propTypes = {
        closeSettingsFn: PropTypes.func.isRequired,
    };

    constructor() {
        super();

        this.state = {
            appVersion: null,
            canUpdate: false,
        };
    }

    componentDidMount(): void {
        PlatformPeg.get().getAppVersion().then((ver) => this.setState({appVersion: ver})).catch((e) => {
            console.error("Error getting vector version: ", e);
        });
        PlatformPeg.get().canSelfUpdate().then((v) => this.setState({canUpdate: v})).catch((e) => {
            console.error("Error getting self updatability: ", e);
        });
    }

    _onClearCacheAndReload = (e) => {
        if (!PlatformPeg.get()) return;

        // Dev note: please keep this log line, it's useful when troubleshooting a MatrixClient suddenly
        // stopping in the middle of the logs.
        console.log("Clear cache & reload clicked");
        MatrixClientPeg.get().stopClient();
        MatrixClientPeg.get().store.deleteAllData().then(() => {
            PlatformPeg.get().reload();
        });
    };

    _onBugReport = (e) => {
        const BugReportDialog = sdk.getComponent("dialogs.BugReportDialog");
        if (!BugReportDialog) {
            return;
        }
        Modal.createTrackedDialog('Bug Report Dialog', '', BugReportDialog, {});
    };

    _onStartBotChat = (e) => {
        this.props.closeSettingsFn();
        createRoom({
            dmUserId: SdkConfig.get().welcomeUserId,
            andView: true,
        });
    };

    _showSpoiler = (event) => {
        const target = event.target;
        target.innerHTML = target.getAttribute('data-spoiler');

        const range = document.createRange();
        range.selectNodeContents(target);

        const selection = window.getSelection();
        selection.removeAllRanges();
        selection.addRange(range);
    };

    _renderLegal() {
        const tocLinks = SdkConfig.get().terms_and_conditions_links;
        if (!tocLinks) return null;

        const legalLinks = [];
        for (const tocEntry of SdkConfig.get().terms_and_conditions_links) {
            legalLinks.push(

                {tocEntry.text}

);
        }

        return (

                {_t("Legal")}

                    {legalLinks}

        );
    }

    _renderCredits() {
        // Note: This is not translated because it is legal text.
        // Also,   is ugly but necessary.
        return (

                {_t("Credits")}

                        The
                        default cover photo is ©
                        Jesús Roncero{' '}
                        used under the terms of

                        CC-BY-SA 4.0.

                        The  twemoji-colr font is ©
                        Mozilla Foundation{' '}
                        used under the terms of

                        Apache 2.0.

                        The
                        Twemoji emoji art is ©
                        Twitter, Inc and other
                        contributors used under the terms of

                        CC-BY 4.0.

        );
    }

    render() {
        const brand = SdkConfig.get().brand;

        let faqText = _t(
            'For help with using %(brand)s, click here.',
            {
                brand,
            },
            {
                'a': (sub) =>
                    {sub}
                ,
            },
        );
        if (SdkConfig.get().welcomeUserId && getCurrentLanguage().startsWith('en')) {
            faqText = (

                    {_t(
                        'For help with using %(brand)s, click here or start a chat with our ' +
                        'bot using the button below.',
                        {
                            brand,
                        },
                        {
                            'a': (sub) =>
                                {sub}
                            ,
                        },
                    )}

                        <AccessibleButton onClick={this._onStartBotChat} kind='primary'>
                            {_t("Chat with %(brand)s Bot", { brand })}
                        </AccessibleButton>

            );
        }

        const appVersion = this.state.appVersion || 'unknown';

        let olmVersion = MatrixClientPeg.get().olmVersion;
        olmVersion = olmVersion ? `${olmVersion[0]}.${olmVersion[1]}.${olmVersion[2]}` : '<not-enabled>';

        let updateButton = null;
        if (this.state.canUpdate) {
            updateButton = <UpdateCheckButton />;
        }

        return (

{_t("Help & About")}

                    {_t('Bug reporting')}

                        {
                            _t( "If you've submitted a bug via GitHub, debug logs can help " +
                                "us track down the problem. Debug logs contain application " +
                                "usage data including your username, the IDs or aliases of " +
                                "the rooms or groups you have visited and the usernames of " +
                                "other users. They do not contain messages.",
                            )
                        }

                            <AccessibleButton onClick={this._onBugReport} kind='primary'>
                                {_t("Submit debug logs")}
                            </AccessibleButton>

                            <AccessibleButton onClick={this._onClearCacheAndReload} kind='danger'>
                                {_t("Clear cache and reload")}
                            </AccessibleButton>

                        {
                            _t( "To report a Matrix-related security issue, please read the Matrix.org " +
                                "Security Disclosure Policy.", {},
                                {
                                    'a': (sub) =>
                                        {sub},
                                })
                        }

                    {_t("FAQ")}

                        {faqText}

                    <AccessibleButton kind="primary" onClick={KeyboardShortcuts.toggleDialog}>
                        { _t("Keyboard Shortcuts") }
                    </AccessibleButton>

                    {_t("Versions")}

                        {_t("%(brand)s version:", { brand })} {appVersion}

                        {_t("olm version:")} {olmVersion}

                        {updateButton}

                {this._renderLegal()}
                {this._renderCredits()}

                    {_t("Advanced")}

                        {_t("Homeserver is")} {MatrixClientPeg.get().getHomeserverUrl()}

                        {_t("Identity Server is")} {MatrixClientPeg.get().getIdentityServerUrl()}

                        {_t("Access Token:") + ' '}
                        <AccessibleButton element="span" onClick={this._showSpoiler}
                                          data-spoiler={MatrixClientPeg.get().getAccessToken()}>
                            <{ _t("click to reveal") }>
                        </AccessibleButton>

        );
    }
}
<|endoftext|>


<commit_before>/*
 * jQuery Pines Notify (pnotify) Plugin 1.0
 *
 * Copyright (c) 2009 Hunter Perrin
 *
 * Licensed (along with all of Pines) under the GNU Affero GPL:
 *	  http://www.gnu.org/licenses/agpl.html
 */

(function($) {
	var first_top;
	var history_handle_top;
	var timer;
	$.extend({
		pnotify_remove_all: function () {
			var body = $("body");
			var body_data = body.data("pnotify");
			$.each(body_data, function(){
				if (this.pnotify_remove)
					this.pnotify_remove();
			});
		},
		pnotify_position_all: function () {
			timer = null;
			var body = $("body");
			var next = first_top;
			var body_data = body.data("pnotify");
			// TODO: Maybe do horizontal positioning here too. Use top % screenheight for top value.
			$.each(body_data, function(){
				var postop;
				var display = this.css("display");
				if (display != "none") {
					// Calculate the top value, disregarding the scroll, since position=fixed.
					postop = this.offset().top - $(window).scrollTop();
					if (!first_top) {
						first_top = postop;
						next = first_top;
					}
				}
				if (next) {
					if (postop > next) {
						this.animate({top: next+"px"}, {duration: 500, queue: false});
					} else {
						this.css("top", next+"px");
					}
				}
				if (display != "none") {
					next += this.height() + 10;
				}
			});
		},
		pnotify: function(options) {
			var body = $("body");
			var closer;

			// Build main options.
			var opts;
			if (typeof options == "string") {
				opts = $.extend({}, $.pnotify.defaults);
				opts.pnotify_text = options;
			} else {
				opts = $.extend({}, $.pnotify.defaults, options);
			}

			if (opts.pnotify_before_init) {
				if (opts.pnotify_before_init(opts) === false) {
					return null;
				}
			}

			var pnotify = $("
").addClass("ui-widget ui-helper-clearfix ui-pnotify");
			pnotify.container = $("
").addClass("ui-corner-all ui-pnotify-container");
			pnotify.append(pnotify.container);

			pnotify.pnotify_version = "1.0.0";

			pnotify.pnotify_init = function() {
				body.append(pnotify);

				// Add events to stop fading when the user mouses over.
				if (opts.pnotify_hide) {
					pnotify.mouseenter(function(){
						pnotify.stop();
						pnotify.fadeTo("fast", opts.pnotify_opacity);
						pnotify.pnotify_cancel_remove();
					}).mouseleave(function(){
						pnotify.pnotify_queue_remove();
						$.pnotify_position_all();
					});
				}

				if (opts.pnotify_closer) {
					if (closer) closer.remove();
					closer = $("
").addClass("ui-pnotify-closer").css("cursor", "pointer");
					closer.append($("").addClass("ui-icon ui-icon-circle-close"));
					closer.click(function(){
						pnotify.pnotify_remove();
					});
					closer.hide();
					pnotify.container.prepend(closer);
					pnotify.hover(function(){
						closer.show();
					}, function(){
						closer.hide();
					});
				}
			};

			pnotify.pnotify_queue_position = function() {
				if (timer) {
					clearTimeout(timer);
				}
				timer = setTimeout($.pnotify_position_all, 10);
			};

			pnotify.pnotify_display = function() {
				if (pnotify.parent().get()) {
					pnotify.pnotify_init();
				}
				if (opts.pnotify_before_open)
					opts.pnotify_before_open(pnotify);
				pnotify.pnotify_queue_position();
				// First show it, then set its opacity to 0, then fade into the set opacity.
				pnotify.show().fadeTo(0, 0).fadeTo(opts.pnotify_fade_speed, opts.pnotify_opacity, function(){
					if (opts.pnotify_after_open)
						opts.pnotify_after_open(pnotify);

					// Now set it to hide.
					if (opts.pnotify_hide) {
						pnotify.pnotify_queue_remove();
					}
				});
			};

			pnotify.pnotify_remove = function() {
				if (opts.pnotify_before_close)
					opts.pnotify_before_close(pnotify);
				if (pnotify.timer) {
					window.clearTimeout(pnotify.timer);
					pnotify.timer = null;
				}
				pnotify.fadeOut(opts.pnotify_fade_speed, function(){
					if (opts.pnotify_after_close)
						opts.pnotify_after_close(pnotify);
					pnotify.pnotify_queue_position();
					if (opts.pnotify_remove)
						pnotify.remove();
				});
			};

			pnotify.pnotify_cancel_remove = function() {
				if (pnotify.timer) {
					window.clearTimeout(pnotify.timer);
				}
			};

			pnotify.pnotify_queue_remove = function() {
				pnotify.pnotify_cancel_remove();
				pnotify.timer = window.setTimeout(function(){
					pnotify.pnotify_remove();
				}, (isNaN(opts.pnotify_delay) ? 0 : opts.pnotify_delay));
			};

			if (opts.pnotify_type == "error") {
				pnotify.container.addClass("ui-state-error");
			} else if (opts.pnotify_type == "notice") {
				pnotify.container.addClass("ui-state-highlight");
			}

			if ((opts.pnotify_notice_icon && opts.pnotify_type == "notice") || (opts.pnotify_error_icon && opts.pnotify_type == "error")) {
				var icon = $("
").addClass("ui-pnotify-icon");
				icon.append($("").addClass(opts.pnotify_type == "notice" ? opts.pnotify_notice_icon : opts.pnotify_error_icon));
				pnotify.container.append(icon);
			}

			if (typeof opts.pnotify_title == "string") {
				var title = $("").addClass("ui-pnotify-title");
				title.html(opts.pnotify_title);
				pnotify.container.append(title);
			}

			if (typeof opts.pnotify_text == "string") {
				var text = $("").addClass("ui-pnotify-text");
				text.html(opts.pnotify_text);
				pnotify.container.append(text);
			}

			if (typeof opts.pnotify_width == "string") {
				pnotify.css("width", opts.pnotify_width);
			}

			if (typeof opts.pnotify_min_height == "string") {
				pnotify.container.css("min-height", opts.pnotify_min_height);
			}

			pnotify.hide();

			var body_data = body.data("pnotify");
			if (typeof body_data != "object")
				body_data = Array();
			body_data = $.merge(body_data, [pnotify]);
			body.data("pnotify", body_data);

			if (opts.pnotify_after_init)
				opts.pnotify_after_init(pnotify);

			pnotify.pnotify_display();

			if (opts.pnotify_history) {
				var body_history = body.data("pnotify_history");
				if (typeof body_history == "undefined") {
					body_history = $("
").addClass("ui-pnotify-history-container ui-state-default ui-corner-bottom");
					body.append(body_history);

					body_history.append($("
Redisplay
").addClass("ui-pnotify-history-header"));
					body_history.append($("<button>All</button>").addClass("ui-pnotify-history-all ui-state-default ui-corner-all").hover(function(){
						$(this).addClass("ui-state-hover");
					}, function(){
						$(this).removeClass("ui-state-hover");
					}).click(function(){
						$.each(body_data, function(){
							if (this.pnotify_display)
								this.pnotify_display();
						});
					}));
					body_history.append($("<button>Last</button>").addClass("ui-pnotify-history-last ui-state-default ui-corner-all").hover(function(){
						$(this).addClass("ui-state-hover");
					}, function(){
						$(this).removeClass("ui-state-hover");
					}).click(function(){
						if (body_data[body_data.length - 1] && body_data[body_data.length - 1].pnotify_display)
							body_data[body_data.length - 1].pnotify_display();
					}));

					var handle = $("").addClass("ui-pnotify-history-pulldown ui-icon ui-icon-grip-dotted-horizontal").mouseenter(function(){
						body_history.animate({top: "0"}, {duration: 100, queue: false})
					});
					body_history.append(handle);
					history_handle_top = handle.offset().top + 2;

					body_history.mouseleave(function(){
						body_history.animate({top: "-"+history_handle_top+"px"}, {duration: 100, queue: false});
					});
					body_history.css({top: "-"+history_handle_top+"px"});

					body.data("pnotify_history", body_history);
				}
			}

			return pnotify;
		}
	});

	$.pnotify.defaults = {
		// Display a pull down menu to redisplay previous notices.
		pnotify_history: true,
		// Width of the notice.
		pnotify_width: "300px",
		// Minimum height of the notice. It will expand to fit content.
		pnotify_min_height: "16px",
		// Type of the notice. "notice" or "error".
		pnotify_type: "notice",
		// The icon class to use if type is notice.
		pnotify_notice_icon: "ui-icon ui-icon-info",
		// The icon class to use if type is error.
		pnotify_error_icon: "ui-icon ui-icon-alert",
		// Speed at which the notice fades in and out. "slow", "def", "fast" or number of milliseconds.
		pnotify_fade_speed: "slow",
		// Opacity to fade to.
		pnotify_opacity: 1,
		// Provide a button for the user to manually close a notice.
		pnotify_closer: true,
		// After a delay, make the notice disappear.
		pnotify_hide: true,
		// Delay in milliseconds before the notice disappears.
		pnotify_delay: 8000,
		// Remove the notice from the DOM after it disappears.
		pnotify_remove: true
	};
})(jQuery);<commit_msg>Notice history option.<commit_after>/*
 * jQuery Pines Notify (pnotify) Plugin 1.0
 *
 * Copyright (c) 2009 Hunter Perrin
 *
 * Licensed (along with all of Pines) under the GNU Affero GPL:
 *	  http://www.gnu.org/licenses/agpl.html
 */

(function($) {
	var first_top;
	var history_handle_top;
	var timer;
	$.extend({
		pnotify_remove_all: function () {
			var body = $("body");
			var body_data = body.data("pnotify");
			$.each(body_data, function(){
				if (this.pnotify_remove)
					this.pnotify_remove();
			});
		},
		pnotify_position_all: function () {
			timer = null;
			var body = $("body");
			var next = first_top;
			var body_data = body.data("pnotify");
			// TODO: Maybe do horizontal positioning here too. Use top % screenheight for top value.
			$.each(body_data, function(){
				var postop;
				var display = this.css("display");
				if (display != "none") {
					// Calculate the top value, disregarding the scroll, since position=fixed.
					postop = this.offset().top - $(window).scrollTop();
					if (!first_top) {
						first_top = postop;
						next = first_top;
					}
				}
				if (next) {
					if (postop > next) {
						this.animate({top: next+"px"}, {duration: 500, queue: false});
					} else {
						this.css("top", next+"px");
					}
				}
				if (display != "none") {
					next += this.height() + 10;
				}
			});
		},
		pnotify: function(options) {
			var body = $("body");
			var closer;

			// Build main options.
			var opts;
			if (typeof options == "string") {
				opts = $.extend({}, $.pnotify.defaults);
				opts.pnotify_text = options;
			} else {
				opts = $.extend({}, $.pnotify.defaults, options);
			}

			if (opts.pnotify_before_init) {
				if (opts.pnotify_before_init(opts) === false) {
					return null;
				}
			}

			var pnotify = $("
").addClass("ui-widget ui-helper-clearfix ui-pnotify");
			pnotify.container = $("
").addClass("ui-corner-all ui-pnotify-container");
			pnotify.append(pnotify.container);

			pnotify.pnotify_version = "1.0.0";

			pnotify.pnotify_init = function() {
				body.append(pnotify);

				// Add events to stop fading when the user mouses over.
				if (opts.pnotify_hide) {
					pnotify.mouseenter(function(){
						pnotify.stop();
						pnotify.fadeTo("fast", opts.pnotify_opacity);
						pnotify.pnotify_cancel_remove();
					}).mouseleave(function(){
						pnotify.pnotify_queue_remove();
						$.pnotify_position_all();
					});
				}

				if (opts.pnotify_closer) {
					if (closer) closer.remove();
					closer = $("
").addClass("ui-pnotify-closer").css("cursor", "pointer");
					closer.append($("").addClass("ui-icon ui-icon-circle-close"));
					closer.click(function(){
						pnotify.pnotify_remove();
					});
					closer.hide();
					pnotify.container.prepend(closer);
					pnotify.hover(function(){
						closer.show();
					}, function(){
						closer.hide();
					});
				}
			};

			pnotify.pnotify_queue_position = function() {
				if (timer) {
					clearTimeout(timer);
				}
				timer = setTimeout($.pnotify_position_all, 10);
			};

			pnotify.pnotify_display = function() {
				if (pnotify.parent().get()) {
					pnotify.pnotify_init();
				}
				if (opts.pnotify_before_open)
					opts.pnotify_before_open(pnotify);
				pnotify.pnotify_queue_position();
				// First show it, then set its opacity to 0, then fade into the set opacity.
				pnotify.show().fadeTo(0, 0).fadeTo(opts.pnotify_fade_speed, opts.pnotify_opacity, function(){
					if (opts.pnotify_after_open)
						opts.pnotify_after_open(pnotify);

					// Now set it to hide.
					if (opts.pnotify_hide) {
						pnotify.pnotify_queue_remove();
					}
				});
			};

			pnotify.pnotify_remove = function() {
				if (opts.pnotify_before_close)
					opts.pnotify_before_close(pnotify);
				if (pnotify.timer) {
					window.clearTimeout(pnotify.timer);
					pnotify.timer = null;
				}
				pnotify.fadeOut(opts.pnotify_fade_speed, function(){
					if (opts.pnotify_after_close)
						opts.pnotify_after_close(pnotify);
					pnotify.pnotify_queue_position();
					if (opts.pnotify_remove)
						pnotify.remove();
				});
			};

			pnotify.pnotify_cancel_remove = function() {
				if (pnotify.timer) {
					window.clearTimeout(pnotify.timer);
				}
			};

			pnotify.pnotify_queue_remove = function() {
				pnotify.pnotify_cancel_remove();
				pnotify.timer = window.setTimeout(function(){
					pnotify.pnotify_remove();
				}, (isNaN(opts.pnotify_delay) ? 0 : opts.pnotify_delay));
			};

			if (opts.pnotify_type == "error") {
				pnotify.container.addClass("ui-state-error");
			} else if (opts.pnotify_type == "notice") {
				pnotify.container.addClass("ui-state-highlight");
			}

			if ((opts.pnotify_notice_icon && opts.pnotify_type == "notice") || (opts.pnotify_error_icon && opts.pnotify_type == "error")) {
				var icon = $("
").addClass("ui-pnotify-icon");
				icon.append($("").addClass(opts.pnotify_type == "notice" ? opts.pnotify_notice_icon : opts.pnotify_error_icon));
				pnotify.container.append(icon);
			}

			if (typeof opts.pnotify_title == "string") {
				var title = $("").addClass("ui-pnotify-title");
				title.html(opts.pnotify_title);
				pnotify.container.append(title);
			}

			if (typeof opts.pnotify_text == "string") {
				var text = $("").addClass("ui-pnotify-text");
				text.html(opts.pnotify_text);
				pnotify.container.append(text);
			}

			if (typeof opts.pnotify_width == "string") {
				pnotify.css("width", opts.pnotify_width);
			}

			if (typeof opts.pnotify_min_height == "string") {
				pnotify.container.css("min-height", opts.pnotify_min_height);
			}

			pnotify.pnotify_history = opts.pnotify_history;

			pnotify.hide();

			var body_data = body.data("pnotify");
			if (typeof body_data != "object")
				body_data = Array();
			body_data = $.merge(body_data, [pnotify]);
			body.data("pnotify", body_data);

			if (opts.pnotify_after_init)
				opts.pnotify_after_init(pnotify);

			pnotify.pnotify_display();

			if (opts.pnotify_history) {
				var body_history = body.data("pnotify_history");
				if (typeof body_history == "undefined") {
					body_history = $("
").addClass("ui-pnotify-history-container ui-state-default ui-corner-bottom");
					body.append(body_history);

					body_history.append($("
Redisplay
").addClass("ui-pnotify-history-header"));
					body_history.append($("<button>All</button>").addClass("ui-pnotify-history-all ui-state-default ui-corner-all").hover(function(){
						$(this).addClass("ui-state-hover");
					}, function(){
						$(this).removeClass("ui-state-hover");
					}).click(function(){
						$.each(body_data, function(){
							if (this.pnotify_history && this.pnotify_display)
								this.pnotify_display();
						});
					}));
					body_history.append($("<button>Last</button>").addClass("ui-pnotify-history-last ui-state-default ui-corner-all").hover(function(){
						$(this).addClass("ui-state-hover");
					}, function(){
						$(this).removeClass("ui-state-hover");
					}).click(function(){
						var i = 1;
						while (!body_data[body_data.length - i] || !body_data[body_data.length - i].pnotify_history) {
							if (body_data.length - i == 0)
								return;
							i++;
						}
						if (body_data[body_data.length - i].pnotify_display)
							body_data[body_data.length - i].pnotify_display();
					}));

					var handle = $("").addClass("ui-pnotify-history-pulldown ui-icon ui-icon-grip-dotted-horizontal").mouseenter(function(){
						body_history.animate({top: "0"}, {duration: 100, queue: false})
					});
					body_history.append(handle);
					history_handle_top = handle.offset().top + 2;

					body_history.mouseleave(function(){
						body_history.animate({top: "-"+history_handle_top+"px"}, {duration: 100, queue: false});
					});
					body_history.css({top: "-"+history_handle_top+"px"});

					body.data("pnotify_history", body_history);
				}
			}

			return pnotify;
		}
	});

	$.pnotify.defaults = {
		// Display a pull down menu to redisplay previous notices, and place this notice in the history.
		pnotify_history: true,
		// Width of the notice.
		pnotify_width: "300px",
		// Minimum height of the notice. It will expand to fit content.
		pnotify_min_height: "16px",
		// Type of the notice. "notice" or "error".
		pnotify_type: "notice",
		// The icon class to use if type is notice.
		pnotify_notice_icon: "ui-icon ui-icon-info",
		// The icon class to use if type is error.
		pnotify_error_icon: "ui-icon ui-icon-alert",
		// Speed at which the notice fades in and out. "slow", "def", "fast" or number of milliseconds.
		pnotify_fade_speed: "slow",
		// Opacity to fade to.
		pnotify_opacity: 1,
		// Provide a button for the user to manually close a notice.
		pnotify_closer: true,
		// After a delay, make the notice disappear.
		pnotify_hide: true,
		// Delay in milliseconds before the notice disappears.
		pnotify_delay: 8000,
		// Remove the notice from the DOM after it disappears.
		pnotify_remove: true
	};
})(jQuery);<|endoftext|>


<commit_before>import { get, post, ajax } from 'jquery'
import AppDispatcher from './AppDispatcher'
import ServerActions from './actions/ServerActions'
import RestaurantActions from './actions/RestaurantActions';
import ActivityActions from './actions/ActivityActions';

const API = {
  getAllClientData() {
    get('/api/clients/')
    .done(res => ServerActions.receivedClientData(res))
    .fail(err => ServerActions.receivedError(err));
  },
  deleteAllClients() {
    ajax({
      url: '/api/clients/',
      method: 'DELETE',
    })
    .done(res => ServerActions.receivedClientData(res))
    .fail(err => ServerActions.receivedError(err));
  },
  createClient() {
    post('/api/clients/')
    .done(res => ServerActions.receivedNewClient(res))
    .fail(err => ServerActions.receivedError(err));
  },
  getClientData(clientId) {
    get(`/api/clients/${clientId}`)
    .done(res => { ServerActions.receivedClientData(res) })
    .fail(err => ServerActions.receivedError(err));
  },
  addClientData(newClientData, clientId) {
    ajax({
      url: `/api/clients/${clientId}`,
      method: 'PUT',
      data: newClientData,
    })
    .done(res => ServerActions.receivedClientData(res[0]))
    .fail(err => ServerActions.receivedError(err));
  },
  deleteClient(clientId) {
    ajax({
      url: `/api/clients/${clientId}`,
      method: 'DELETE',
    })
    .done()
    .fail(err => ServerActions.receivedError(err));
  },

  getRestaurants(id, city) {
    get('/api/yelp', { city, id })
    .done(res => ServerActions.receivedClientData(res))
    .fail(err => ServerActions.receivedError(err));
  },

  // getLunch(id, city) {
  //   get(`/api/yelp/lunch/${city}`)
  //   .done(response => response.json())
  //   .done(data => {
  //     RestaurantActions.getLunch(data.businesses);
  //     API.addClientData({
  //       lunch: data.businesses
  //     }, `${id}`)
  //   })
  //   .fail(err => console.log('err:', err))
  // },
  //
  // getDinner(id, city) {
  //   get(`/api/yelp/dinner/${city}`)
  //   .done(response => response.json())
  //   .done(data => {
  //     RestaurantActions.getDinner(data.businesses);
  //     API.addClientData({
  //       dinner: data.businesses
  //     }, `${id}`)
  //   })
  //   .fail(err => console.log('err:', err))
  // },

  getActivities(id, city) {
    get(`/api/yelp/activities/${city}`)
    .done(response => response.json())
    .done(data => {
      ActivityActions.getActivities(data.businesses)
      API.addClientData({
        activities: data.businesses
      }, `${id}`)
    })
    .fail(err => console.log('err:', err))
  },

}

export default API
<commit_msg>updated API with getRestaurants and getActivities<commit_after>import { get, post, ajax } from 'jquery'
import AppDispatcher from './AppDispatcher'
import ServerActions from './actions/ServerActions'
import RestaurantActions from './actions/RestaurantActions';
import ActivityActions from './actions/ActivityActions';

const API = {
  getAllClientData() {
    get('/api/clients/')
    .done(res => ServerActions.receivedClientData(res))
    .fail(err => ServerActions.receivedError(err));
  },
  deleteAllClients() {
    ajax({
      url: '/api/clients/',
      method: 'DELETE',
    })
    .done(res => ServerActions.receivedClientData(res))
    .fail(err => ServerActions.receivedError(err));
  },
  createClient() {
    post('/api/clients/')
    .done(res => ServerActions.receivedNewClient(res))
    .fail(err => ServerActions.receivedError(err));
  },
  getClientData(clientId) {
    get(`/api/clients/${clientId}`)
    .done(res => { ServerActions.receivedClientData(res) })
    .fail(err => ServerActions.receivedError(err));
  },
  addClientData(newClientData, clientId) {
    ajax({
      url: `/api/clients/${clientId}`,
      method: 'PUT',
      data: newClientData,
    })
    .done(res => ServerActions.receivedClientData(res[0]))
    .fail(err => ServerActions.receivedError(err));
  },
  deleteClient(clientId) {
    ajax({
      url: `/api/clients/${clientId}`,
      method: 'DELETE',
    })
    .done()
    .fail(err => ServerActions.receivedError(err));
  },
  getRestaurants(id, city) {
    get(`/api/yelp/restaurants/${id}`, city)
    .done(res => ServerActions.receivedClientData(res))
    .fail(err => ServerActions.receivedError(err));
  },
  getActivities(id, city) {
    get(`/api/yelp/activities/${id}`, city)
    .done(res => ServerActions.receivedClientData(res))
    .fail(err => ServerActions.receivedError(err));
  },

}

export default API
<|endoftext|>


<commit_before><commit_msg>added app.js<commit_after>console.log("we're live with js & express!");<|endoftext|>


<commit_before>Session.setDefault('filters', []);

Template.app.helpers({
	view: function() {
		return UserSession.get('view') || 'comfort';
	},
	// TODO rename
	effects: function(){
		return UserSession.get('effects') || 'static';
	}
});

Meteor.startup(function () {
	// TODO HTML5 navigation history with routes
	// Backbone.history.start({pushState: true});

	// auto activation of bootstrap tooltips
	$(function(){
		$('[data-toggle="tooltip"]').livequery(function(){
			$(this).tooltip();
		}, function(){
			$(this).tooltip('destroy');
		});
	})
});
<commit_msg>init bootstrap<commit_after>Session.setDefault('filters', []);

Template.app.helpers({
	view: function() {
		return UserSession.get('view') || 'comfort';
	},
	// TODO rename
	effects: function(){
		return UserSession.get('effects') || 'static';
	}
});

Meteor.startup(function () {
	// TODO HTML5 navigation history with routes
	// Backbone.history.start({pushState: true});
	initBootstrap();
});

function initBootstrap(){
	// auto activation of bootstrap tooltips
	$(function(){
		$('[data-toggle="tooltip"]').livequery(function(){
			$(this).tooltip();
		}, function(){
			$(this).tooltip('destroy');
		});
	})
}<|endoftext|>


<commit_before>/* eslint-disable angular/window-service */

// The webpack entrypoint
function requireAll (context) {
  context.keys().forEach(context)
}

// Globals that are expected in application code and some libraries
window.$ = window.jQuery = require('jquery')
window._ = require('lodash')
window.moment = require('moment')
window.sprintf = require('sprintf-js').sprintf
window.c3 = require('c3/c3.js')
window.d3 = require('d3/d3.js')

// Vendor libraries, order matters
require('jquery-ui-bundle')
require('moment-timezone')
require('es6-shim')
require('angular')
require('angular-animate')
require('angular-cookies')
require('angular-resource')
require('angular-messages')
require('angular-sanitize')
require('angular-base64')
require('angular-bootstrap-switch')
require('angular-file-saver')
require('angular-ui-bootstrap')
require('angular-ui-sortable')
require('angular-gettext')
require('bootstrap')
require('angular-dragdrop')
require('angular-drag-and-drop-lists/angular-drag-and-drop-lists')
require('bootstrap-combobox')
require('bootstrap-datepicker')
require('bootstrap-select')
require('bootstrap-switch')
require('bootstrap-touchspin')
require('@uirouter/angularjs')
require('@uirouter/angularjs/release/stateEvents')
require('patternfly/dist/js/patternfly.js')
require('@manageiq/ui-components/dist/js/ui-components.js')
require('ngprogress/build/ngprogress.min.js')
require('ngstorage')
require('datatables.net/js/jquery.dataTables')
require('datatables.net-select/js/dataTables.select')
require('angular-datatables')
require('angular-datatables/dist/plugins/select/angular-datatables.select')
require('ui-select')
require('patternfly-timeline/dist/timeline')

// eslint-disable-next-line import/no-webpack-loader-syntax
require('imports-loader?this=>window!actioncable')

// Must be required last because of its dependencies
require('angular-patternfly/dist/angular-patternfly')

// Application scripts, order matters
require('./app/app.module.js')

// Vendor styles, order matters
require('angular-patternfly/dist/styles/angular-patternfly.css')
require('@manageiq/ui-components/dist/css/ui-components.css')
require('ngprogress/ngProgress.css')
require('datatables.net-dt/css/jquery.dataTables.css')
require('ui-select/dist/select.css')
require('patternfly-timeline/dist/timeline.css')

// Application styles
require('./assets/sass/styles.sass')

// Angular templates
requireAll(require.context('./app', true, /\.html$/))

// Skin overrides, require all js and css files within `client/skin`
requireAll(require.context('./', true, /skin\/.*\.(js|css)$/))
<commit_msg>Added global for patternflyVersion<commit_after>/* eslint-disable angular/window-service */

// The webpack entrypoint
function requireAll (context) {
  context.keys().forEach(context)
}

// Globals that are expected in application code and some libraries
window.$ = window.jQuery = require('jquery')
window._ = require('lodash')
window.moment = require('moment')
window.sprintf = require('sprintf-js').sprintf
window.c3 = require('c3/c3.js')
window.d3 = require('d3/d3.js')
window.patternflyVersion = 4
// Vendor libraries, order matters
require('jquery-ui-bundle')
require('moment-timezone')
require('es6-shim')
require('angular')
require('angular-animate')
require('angular-cookies')
require('angular-resource')
require('angular-messages')
require('angular-sanitize')
require('angular-base64')
require('angular-bootstrap-switch')
require('angular-file-saver')
require('angular-ui-bootstrap')
require('angular-ui-sortable')
require('angular-gettext')
require('bootstrap')
require('angular-dragdrop')
require('angular-drag-and-drop-lists/angular-drag-and-drop-lists')
require('bootstrap-combobox')
require('bootstrap-datepicker')
require('bootstrap-select')
require('bootstrap-switch')
require('bootstrap-touchspin')
require('@uirouter/angularjs')
require('@uirouter/angularjs/release/stateEvents')
require('patternfly/dist/js/patternfly.js')
require('@manageiq/ui-components/dist/js/ui-components.js')
require('ngprogress/build/ngprogress.min.js')
require('ngstorage')
require('datatables.net/js/jquery.dataTables')
require('datatables.net-select/js/dataTables.select')
require('angular-datatables')
require('angular-datatables/dist/plugins/select/angular-datatables.select')
require('ui-select')
require('patternfly-timeline/dist/timeline')

// eslint-disable-next-line import/no-webpack-loader-syntax
require('imports-loader?this=>window!actioncable')

// Must be required last because of its dependencies
require('angular-patternfly/dist/angular-patternfly')

// Application scripts, order matters
require('./app/app.module.js')

// Vendor styles, order matters
require('angular-patternfly/dist/styles/angular-patternfly.css')
require('@manageiq/ui-components/dist/css/ui-components.css')
require('ngprogress/ngProgress.css')
require('datatables.net-dt/css/jquery.dataTables.css')
require('ui-select/dist/select.css')
require('patternfly-timeline/dist/timeline.css')

// Application styles
require('./assets/sass/styles.sass')

// Angular templates
requireAll(require.context('./app', true, /\.html$/))

// Skin overrides, require all js and css files within `client/skin`
requireAll(require.context('./', true, /skin\/.*\.(js|css)$/))
<|endoftext|>


<commit_before>function idsToIndexes(arr, ids) {
  var indexes = [];

  ids.forEach(function(id) {
    var i = arr.findIndex(function(el) {
      return el.id === id;
    });

    if (i >= 0) {
      indexes.push(i);
    }
  });

  return indexes;
}

function idsToElements(arr, ids) {
  return ids.map(function(id) {
    return arr.find(function(el) {
      return el.id === id;
    });
  });
}

function removeElements(arr, elements) {
  _.remove(arr, function(n) {
    return _.some(elements, n);
  });

  return arr;
}

function filterIndexes(indexes) {
  if (indexes[0] !== 0) {
    return indexes;
  }
  var previous = 0;
  var filteredIndexes = [];
  indexes.forEach(function(index) {
    if (index !== 0 && index - 1 !== previous) {
      filteredIndexes.push(index);
    } else {
      previous = index;
    }
  });
  return filteredIndexes;
}

function filterReverseIndexes(indexes, endIndex) {
  if (indexes[0] !== endIndex) {
    return indexes;
  }
  var previous = endIndex;
  var filteredIndexes = [];
  indexes.forEach(function(index) {
    if (index !== endIndex && index + 1 !== previous) {
      filteredIndexes.push(index);
    } else {
      previous = index;
    }
  });
  return filteredIndexes;
}

// move selected elements between two arrays
export function between({from, to, selected}) {
  var moved = idsToElements(from, selected);

  return {
    from: removeElements(from, moved),
    to: to.concat(moved),
  };
}

// move selected elements to the top of the array
export function top({array, selected}) {
  var moved = idsToElements(array, selected);
  array = removeElements(array, moved);

  return moved.concat(array);
}

// move selected elements to the bottom of the array
export function bottom({array, selected}) {
  var moved = idsToElements(array, selected);
  array = removeElements(array, moved);

  return array.concat(moved);
}

// move selected elements one position up
export function up({array, selected}) {
  var indexes = idsToIndexes(array, selected);
  indexes = filterIndexes(indexes);
  indexes.forEach(function(index) {
    if (index > 0) {
      var temp = array[index];
      array[index] = array[index - 1];
      array[index - 1] = temp;
    }
  });
  return array;
}

// move selected elements one position up
export function down({array, selected}) {
  var indexes = idsToIndexes(array, selected).reverse();
  indexes = filterReverseIndexes(indexes, array.length - 1);
  indexes.forEach(function(index) {
    if (index < array.length - 1) {
      var temp = array[index];
      array[index] = array[index + 1];
      array[index + 1] = temp;
    }
  });
  return array;
}
<commit_msg>move.js - es6 & lodash<commit_after>import { find, findIndex, some, reject } from 'lodash';

// [{id: 123}], [123] => [0]
function idsToElements(arr, ids) {
  return ids.map((id) => find(arr, { id }));
}

function idsToIndexes(arr, ids) {
  return ids.map((id) => findIndex(arr, { id }));
}

function removeElements(arr, elements) {
  return reject(arr, (elem) => some(elements, elem));
}

function filterIndexes(indexes) {
  if (indexes[0] !== 0) {
    return indexes;
  }
  var previous = 0;
  var filteredIndexes = [];
  indexes.forEach(function(index) {
    if (index !== 0 && index - 1 !== previous) {
      filteredIndexes.push(index);
    } else {
      previous = index;
    }
  });
  return filteredIndexes;
}

function filterReverseIndexes(indexes, endIndex) {
  if (indexes[0] !== endIndex) {
    return indexes;
  }
  var previous = endIndex;
  var filteredIndexes = [];
  indexes.forEach(function(index) {
    if (index !== endIndex && index + 1 !== previous) {
      filteredIndexes.push(index);
    } else {
      previous = index;
    }
  });
  return filteredIndexes;
}

// move selected elements between two arrays
export function between({from, to, selected}) {
  var moved = idsToElements(from, selected);

  return {
    from: removeElements(from, moved),
    to: to.concat(moved),
  };
}

// move selected elements to the top of the array
export function top({array, selected}) {
  var moved = idsToElements(array, selected);
  array = removeElements(array, moved);

  return moved.concat(array);
}

// move selected elements to the bottom of the array
export function bottom({array, selected}) {
  var moved = idsToElements(array, selected);
  array = removeElements(array, moved);

  return array.concat(moved);
}

// move selected elements one position up
export function up({array, selected}) {
  var indexes = idsToIndexes(array, selected);
  indexes = filterIndexes(indexes);
  indexes.forEach(function(index) {
    if (index > 0) {
      var temp = array[index];
      array[index] = array[index - 1];
      array[index - 1] = temp;
    }
  });
  return array;
}

// move selected elements one position up
export function down({array, selected}) {
  var indexes = idsToIndexes(array, selected).reverse();
  indexes = filterReverseIndexes(indexes, array.length - 1);
  indexes.forEach(function(index) {
    if (index < array.length - 1) {
      var temp = array[index];
      array[index] = array[index + 1];
      array[index + 1] = temp;
    }
  });
  return array;
}
<|endoftext|>


<commit_before>/**
 * @file Timebased trigger daily exact
 * @url https://www.facebook.com/groups/googleappsscript/permalink/548100505739510/
 */

/**
 *
 */
function runOnce() {
  trigger_();
}

/**
 *
 */
function trigger_() {
  try {
    triggerAction();
  } catch (error) {
    console.error(error.message, error);
  } finally {
    var hours = 10;
    var minutes = 17;
    var seconds = 56;
    var now = new Date();
    var nextTime = new Date();
    nextTime.setHours(0, 0, 24 * 3600 + hours * 3600 + minutes * 60 + seconds);
    var delta = nextTime.getTime() - now.getTime();
    ScriptApp.newTrigger('trigger_')
      .timeBased()
      .after(delta)
      .create();
  }
}

/**
 *
 */
function triggerAction() {
  console.log("I'm fine");
}
<commit_msg>tbt update<commit_after>/**
 * @file Timebased trigger daily exact
 * @url https://www.facebook.com/groups/googleappsscript/permalink/548100505739510/
 * @url https://qna.habr.com/q/789131
 */

/**
 *
 */
function runOnce() {
  trigger_();
}

/**
 *
 */
function trigger_() {
  try {
    triggerAction();
  } catch (error) {
    console.error(error.message, error);
  } finally {
    var hours = 10;
    var minutes = 17;
    var seconds = 56;
    var now = new Date();
    var nextTime = new Date();
    nextTime.setHours(0, 0, 24 * 3600 + hours * 3600 + minutes * 60 + seconds);
    var delta = nextTime.getTime() - now.getTime();
    ScriptApp.newTrigger('trigger_').timeBased().after(delta).create();
  }
}

/**
 *
 */
function triggerAction() {
  console.log("I'm fine");
}
<|endoftext|>


<commit_before>'use strict';

angular.module('hgApp.controller.dashCtrl', [])

.controller('dashCtrl', function ($rootScope, $scope, $http, $location, $stateParams, propertyManager) {
  $scope.addPropertyStatus = false;

  //Show Popover
  $scope.showPopover = function () {
    $('#noticationStatus').popover();
  };

  $scope.listProperties = function (event, user) {
    $scope.allProperties = propertyManager.list(user);
  };

  $scope.showNewPropertyModal = function () {
    $('#addPropertyModal').modal('show');
  };

  $scope.uploadOnboardDocuments = function (inputData) {
    $scope.newDocData = inputData;
    console.log($scope.newDocData);
    $scope.StepOne = false;
  };

  if ($rootScope.auth.user) {
    $scope.listProperties(null, $rootScope.auth.user);
  } else {
    // Initialize the scope, only if the user has logged in.
    $scope.$on("$firebaseSimpleLogin:login", $scope.listProperties);
  }
});<commit_msg>Don’t need to set this variable.<commit_after>'use strict';

angular.module('hgApp.controller.dashCtrl', [])

.controller('dashCtrl', function ($rootScope, $scope, $http, $location, $stateParams, propertyManager) {
  //Show Popover
  $scope.showPopover = function () {
    $('#noticationStatus').popover();
  };

  $scope.listProperties = function (event, user) {
    $scope.allProperties = propertyManager.list(user);
  };

  $scope.showNewPropertyModal = function () {
    $('#addPropertyModal').modal('show');
  };

  $scope.uploadOnboardDocuments = function (inputData) {
    $scope.newDocData = inputData;
    console.log($scope.newDocData);
    $scope.StepOne = false;
  };

  if ($rootScope.auth.user) {
    $scope.listProperties(null, $rootScope.auth.user);
  } else {
    // Initialize the scope, only if the user has logged in.
    $scope.$on("$firebaseSimpleLogin:login", $scope.listProperties);
  }
});<|endoftext|>


<commit_before>'use strict';

/* Controllers */

var analyticsControllers = angular.module('analyticsControllers'); // get, don't create!!

/**
 * controller for KDP on entry page
 */
analyticsControllers.controller('KPlayerController', ['$scope', '$attrs',
    function($scope, $attrs) {
		var self = this;
		this.playerElement = null;

  		this.init = function init (element) {
  			self.playerElement = element;
  		};

  		$scope.$watch('playerEntryId', function( value ) {
  			if (value) {
  				if (value != -1) {
		  			kWidget.embed({
		            	"targetId": "kplayer",
		            	"wid": "_" + $scope.pid,
		              	"uiconf_id": $scope.uiconfId,
		              	"entry_id": value,
		              	"flashvars": {
		              		"streamerType": "auto"
		              	}
		            });
  				} else {
  					self.playerElement.html('
Live Session Was Not Recorded
');
  				}
	  		}
  		});
}]);

/**
 * controller for map on entry page
 */
analyticsControllers.controller('OLMapController', ['$scope', '$attrs',  'EntrySvc',
    function($scope, $attrs, EntrySvc) {
		var self = this;
		this.mapElement = null;
		this.slider = null;
		this.map = null;
		this.citiesLayer = null;
		this.countriesLayer = null;

		this.init = function init (element) {
			self.mapElement = element;

			// create map
			self.map = new OpenLayers.Map('map');

			// create OSM layer
			var osm = new OpenLayers.Layer.OSM();

			self.map.addLayer(osm);
			self.map.zoomToMaxExtent();

			self.map.events.register('zoomend', this, function (event) {
		        var zLevel = self.map.getZoom();
		        if( zLevel < 5)
		        {
		        	// show countries
		            self.citiesLayer.setVisibility(false);
		            self.countriesLayer.setVisibility(true);
		        }
		        else {
		        	// show cities
		        	self.citiesLayer.setVisibility(true);
		            self.countriesLayer.setVisibility(false);
		        }
		    });

			// create slider
			this.slider = angular.element('#mapslider');
			this.slider.slider({ max: 50 , min: 5});
		};

		this.createStyleMap = function createStyleMap() {
			// style
			var style = new OpenLayers.Style({
				pointRadius: "${radius}",
				fillColor: "#ffcc66",
				fillOpacity: 0.8,
				strokeColor: "#cc6633",
				strokeWidth: 2,
				strokeOpacity: 0.8,
				title : "${tooltip}"
			},
			{
				context: {
					radius: function(feature) {
						return feature.attributes.data / 100;
					},
					tooltip: function(feature) {
						return feature.attributes.text+ " " + feature.attributes.data;
					}
				}
			}
			);

			// create a styleMap with a custom default symbolizer
			var styleMap = new OpenLayers.StyleMap({
				"default": style,
				"select": {
					fillColor: "#8aeeef",
					strokeColor: "#32a8a9"
				}
			});

			return styleMap;
		};

		/**
		 * get data to display on map
		 * @param time unix timestamp. if null, current time is used.
		 */
		this.getMapData = function getMapData(time) {
			EntrySvc.getMap($scope.entryId, time).then(function(data) {
				var value = data.objects;
				if (value) { // value is array of KalturaGeoTimeLiveStats
					// remove existing layers
					if (self.citiesLayer) {
						self.map.removeLayer(self.citiesLayer);
					}
					if (self.countriesLayer) {
						self.map.removeLayer(self.countriesLayer);
					}

					// process data to create new layers
					var countriesData = {};
					var features = new Array();
					var point;
					for ( var i = 0; i < value.length; i++) {
						// accumulate data for country-level layer
						if (!countriesData[value[i].country.name]) {
							// init - keep whole value for lat/long
							countriesData[value[i].country.name] = value[i];
						}
						else {
							// sum audience
							countriesData[value[i].country.name]['audience'] += value[i].audience;
						}
						point = new OpenLayers.Geometry.Point(value[i].city.longitude, value[i].city.latitude).transform('EPSG:4326', 'EPSG:3857');
						features[i] = new OpenLayers.Feature.Vector(
								point,
								{
									"data" : value[i].audience,
									"text" : value[i].city.name
								}
								);
					}

					// create cities layer
					var layer = self.citiesLayer = new OpenLayers.Layer.Vector('Cities', {
						"projection": "EPSG:3857",
						"visibility" : false,
						"styleMap" : self.createStyleMap()
					});
					layer.addFeatures(features);
					self.map.addLayer(layer);

					// create countries layer
					features = new Array();
					for (var key in countriesData) {
						point = new OpenLayers.Geometry.Point(countriesData[key].country.longitude, countriesData[key].country.latitude).transform('EPSG:4326', 'EPSG:3857');
						features.push(new OpenLayers.Feature.Vector(
								point,
								{
									"data" : countriesData[key].audience,
									"text" : countriesData[key].country.name
								}
								));
					}

					// create countries layer
					layer = self.countriesLayer = new OpenLayers.Layer.Vector('Countries', {
						"projection": "EPSG:3857",
						"styleMap" : self.createStyleMap()
					});
					layer.addFeatures(features);
					self.map.addLayer(layer);

					layer.refresh();
				}
			});
		};

		this.updateMap = function updateMap(event, time) {
			self.getMapData(time);
		};

		$scope.$on('updateScreen', self.updateMap);

}]);

/**
 * controller for (rickshaw) graph on entry page
 */
analyticsControllers.controller('RGraphController', ['$scope', '$attrs',
    function($scope, $attrs) {
		var self = this;
		this.graphElement = null; // HTML element showing the graph
		this.graph = null;	// graph JS object
		this.series = null;

		this.init = function init (element) {
			self.graphElement = element;
			var d = new Date();
			self.series = [
			    {
					color : 'steelblue',
					data : [ {x:d.getTime(), y:0} ],
					name : "Line 1"
				}
			];

			/**
			 * set graph data as attribute
			 */
			$scope.$watch($attrs.additionalgraphdata, function(value) {
				if (graph != null && Array.isArray(value) && value.length > 0) {
					self.updateGraphContent(value);
				}
			});

			/**
			 * set graph data as attribute
			 */
			$scope.$watch($attrs.graphdata, function(value) {
				if (graph != null && Array.isArray(value) && value.length > 0) {
					self.resetGraphContent(value);
				}
			});

			var graph = self.graph = new Rickshaw.Graph({
				element : element[0].children[0],
				width : element.width(),
				height : element.height() - 20,
				renderer : 'line',
				series : self.series
			});
			graph.render();

			var preview = new Rickshaw.Graph.RangeSlider({
				graph : graph,
				element : element[0].children[1]
			});

			var xAxis = new Rickshaw.Graph.Axis.Time({
				graph : graph,
				ticksTreatment : 'glow',
				timeFixture : new Rickshaw.Fixtures.Time.Local()
			});
			xAxis.render();

			var yAxis = new Rickshaw.Graph.Axis.Y({
				graph : graph,
				tickFormat : Rickshaw.Fixtures.Number.formatKMBT,
				ticksTreatment : 'glow'
			});
			yAxis.render();

			var Hover = Rickshaw.Class.create(Rickshaw.Graph.HoverDetail, {

				initialize: function(args) {

					var graph = this.graph = args.graph;

					this.xFormatter = args.xFormatter || function(x) {
						return new Date( x * 1000 ).toUTCString();
					};

					this.yFormatter = args.yFormatter || function(y) {
						return y === null ? y : y.toFixed(2);
					};

					var element = this.element = document.createElement('div');
					element.className = 'detail';

					this.visible = true;
					graph.element.appendChild(element);

					this.lastEvent = null;

					this.onShow = args.onShow;
					this.onHide = args.onHide;
					this.onRender = args.onRender;
					this.onClick = args.onClick;

					this.formatter = args.formatter || this.formatter;

					this._addListeners();
				},

				render: function(args) {

					var graph = this.graph;
					var points = args.points;
					var point = points.filter( function(p) { return p.active; } ).shift();

					if (point.value.y === null) return;

					var formattedXValue = point.formattedXValue;
					var formattedYValue = point.formattedYValue;

					this.element.innerHTML = '';
					this.element.style.left = graph.x(point.value.x) + 'px';
					this.element.setAttribute("data-time", point.value.x);  // add the x value as data property on detail node

					var xLabel = document.createElement('div');

					xLabel.className = 'x_label';
					xLabel.innerHTML = formattedXValue;
					this.element.appendChild(xLabel);

					var item = document.createElement('div');

					item.className = 'item';

					// invert the scale if this series displays using a scale
					var series = point.series;
					var actualY = series.scale ? series.scale.invert(point.value.y) : point.value.y;

					item.innerHTML = this.formatter(series, point.value.x, actualY, formattedXValue, formattedYValue, point);
					item.style.top = this.graph.y(point.value.y0 + point.value.y) + 'px';

					this.element.appendChild(item);

					var dot = document.createElement('div');

					dot.className = 'dot';
					dot.style.top = item.style.top;
					dot.style.borderColor = series.color;

					this.element.appendChild(dot);

					if (point.active) {
						item.classList.add('active');
						dot.classList.add('active');
					}

					// Assume left alignment until the element has been displayed and
					// bounding box calculations are possible.
					var alignables = [xLabel, item];
					alignables.forEach(function(el) {
						el.classList.add('left');
					});

					this.show();

					// If left-alignment results in any error, try right-alignment.
					var leftAlignError = this._calcLayoutError(alignables);
					if (leftAlignError > 0) {
						alignables.forEach(function(el) {
							el.classList.remove('left');
							el.classList.add('right');
						});

						// If right-alignment is worse than left alignment, switch back.
						var rightAlignError = this._calcLayoutError(alignables);
						if (rightAlignError > leftAlignError) {
							alignables.forEach(function(el) {
								el.classList.remove('right');
								el.classList.add('left');
							});
						}
					}

					if (typeof this.onRender == 'function') {
						this.onRender(args);
					}
				},

				_addListeners: function() {

					this.graph.element.addEventListener(
						'mousemove',
						function(e) {
							this.visible = true;
							this.update(e);
						}.bind(this),
						false
					);

					this.graph.onUpdate( function() { this.update(); }.bind(this) );

					this.graph.element.addEventListener(
						'mouseout',
						function(e) {
							if (e.relatedTarget && !(e.relatedTarget.compareDocumentPosition(this.graph.element) & Node.DOCUMENT_POSITION_CONTAINS)) {
								this.hide();
							}
						}.bind(this),
						false
					);

					// add click handler if required
					if (typeof this.onClick == 'function') {
						this.graph.element.addEventListener(
								'click',
								function(e) {
									// use data-time to go to correct time in player
									var time = this.element.getAttribute('data-time');
									this.onClick(time);
								}.bind(this),
								false
						);

					}
				}
			});

			var hoverDetail = new Hover( {
			    graph: graph,
			    formatter: function(series, x, y, formattedXValue, formattedYValue, point) {
			    	return y + ' views';
			    },
				onClick : function (time) {
					alert(time);
				}
			} );
		};

		/**
		 * remove all previous data and set new
		 * @param value
		 */
		this.resetGraphContent = function resetGraphContent(value) {
			var ar = self.series[0].data;
			while (ar.length > 0) {
				ar.pop();
			}
			for ( var i = 0; i < value.length; i++) {
				ar.push(value[i]);
			}
			self.graph.update();
		};

		/**
		 * add new data and purge oldest so we keep only 36 hrs
		 * @param value
		 */
		this.updateGraphContent = function updateGraphContent(value) {
			var ar = self.series[0].data;
			// find matching point in 'ar'
			var lastX = ar[ar.length-1].x;
			for (var i = value.length-1; i>0; i--) {
				if (value[i].x == lastX) {
					break;
				}
			}
			// now i+1 is the index of the first element in 'value' that needs to be inserted to 'ar'
			// add required elements from value to ar, while removing elements from tail
			i++;
			while(i<value.length) {
				ar.shift();
				ar.push(value[i]);
				i++;
			}
			self.graph.update();
		};

}]);<commit_msg>when updating map, keep visible layer correct<commit_after>'use strict';

/* Controllers */

var analyticsControllers = angular.module('analyticsControllers'); // get, don't create!!

/**
 * controller for KDP on entry page
 */
analyticsControllers.controller('KPlayerController', ['$scope', '$attrs',
    function($scope, $attrs) {
		var self = this;
		this.playerElement = null;

  		this.init = function init (element) {
  			self.playerElement = element;
  		};

  		$scope.$watch('playerEntryId', function( value ) {
  			if (value) {
  				if (value != -1) {
		  			kWidget.embed({
		            	"targetId": "kplayer",
		            	"wid": "_" + $scope.pid,
		              	"uiconf_id": $scope.uiconfId,
		              	"entry_id": value,
		              	"flashvars": {
		              		"streamerType": "auto"
		              	}
		            });
  				} else {
  					self.playerElement.html('
Live Session Was Not Recorded
');
  				}
	  		}
  		});
}]);

/**
 * controller for map on entry page
 */
analyticsControllers.controller('OLMapController', ['$scope', '$attrs',  'EntrySvc',
    function($scope, $attrs, EntrySvc) {
		var self = this;
		this.mapElement = null;
		this.slider = null;
		this.map = null;
		this.citiesLayer = null;
		this.countriesLayer = null;

		this.init = function init (element) {
			self.mapElement = element;

			// create map
			self.map = new OpenLayers.Map('map');

			// create OSM layer
			var osm = new OpenLayers.Layer.OSM();

			self.map.addLayer(osm);
			self.map.zoomToMaxExtent();

			self.map.events.register('zoomend', this, function (event) {
		        var zLevel = self.map.getZoom();
		        if( zLevel < 4)
		        {
		        	// show countries
		            self.citiesLayer.setVisibility(false);
		            self.countriesLayer.setVisibility(true);
		        }
		        else {
		        	// show cities
		        	self.citiesLayer.setVisibility(true);
		            self.countriesLayer.setVisibility(false);
		        }
		    });

			// create slider
			this.slider = angular.element('#mapslider');
			this.slider.slider({ max: 50 , min: 5});
		};

		this.createStyleMap = function createStyleMap() {
			// style
			var style = new OpenLayers.Style({
				pointRadius: "${radius}",
				fillColor: "#ffcc66",
				fillOpacity: 0.8,
				strokeColor: "#cc6633",
				strokeWidth: 2,
				strokeOpacity: 0.8,
				title : "${tooltip}"
			},
			{
				context: {
					radius: function(feature) {
						return feature.attributes.data / 100;
					},
					tooltip: function(feature) {
						return feature.attributes.text+ " " + feature.attributes.data;
					}
				}
			}
			);

			// create a styleMap with a custom default symbolizer
			var styleMap = new OpenLayers.StyleMap({
				"default": style,
				"select": {
					fillColor: "#8aeeef",
					strokeColor: "#32a8a9"
				}
			});

			return styleMap;
		};

		/**
		 * get data to display on map
		 * @param time unix timestamp. if null, current time is used.
		 */
		this.getMapData = function getMapData(time) {
			EntrySvc.getMap($scope.entryId, time).then(function(data) {
				var value = data.objects;
				if (value) { // value is array of KalturaGeoTimeLiveStats
					// remove existing layers
					if (self.citiesLayer) {
						self.map.removeLayer(self.citiesLayer);
					}
					if (self.countriesLayer) {
						self.map.removeLayer(self.countriesLayer);
					}

					// process data to create new layers
					var countriesData = {};
					var features = new Array();
					var point;
					for ( var i = 0; i < value.length; i++) {
						// accumulate data for country-level layer
						if (!countriesData[value[i].country.name]) {
							// init - keep whole value for lat/long
							countriesData[value[i].country.name] = value[i];
						}
						else {
							// sum audience
							countriesData[value[i].country.name]['audience'] += value[i].audience;
						}
						point = new OpenLayers.Geometry.Point(value[i].city.longitude, value[i].city.latitude).transform('EPSG:4326', 'EPSG:3857');
						features[i] = new OpenLayers.Feature.Vector(
								point,
								{
									"data" : value[i].audience,
									"text" : value[i].city.name
								}
								);
					}

					// create cities layer
					var layer = self.citiesLayer = new OpenLayers.Layer.Vector('Cities', {
						"projection": "EPSG:3857",
						"visibility" : self.map.zoom > 3,
						"styleMap" : self.createStyleMap()
					});
					layer.addFeatures(features);
					self.map.addLayer(layer);

					// create countries layer
					features = new Array();
					for (var key in countriesData) {
						point = new OpenLayers.Geometry.Point(countriesData[key].country.longitude, countriesData[key].country.latitude).transform('EPSG:4326', 'EPSG:3857');
						features.push(new OpenLayers.Feature.Vector(
								point,
								{
									"data" : countriesData[key].audience,
									"text" : countriesData[key].country.name
								}
								));
					}

					// create countries layer
					layer = self.countriesLayer = new OpenLayers.Layer.Vector('Countries', {
						"projection": "EPSG:3857",
						"visibility" : self.map.zoom < 4,
						"styleMap" : self.createStyleMap()
					});
					layer.addFeatures(features);
					self.map.addLayer(layer);

					layer.refresh();
				}
			});
		};

		this.updateMap = function updateMap(event, time) {
			self.getMapData(time);
		};

		$scope.$on('updateScreen', self.updateMap);

}]);

/**
 * controller for (rickshaw) graph on entry page
 */
analyticsControllers.controller('RGraphController', ['$scope', '$attrs',
    function($scope, $attrs) {
		var self = this;
		this.graphElement = null; // HTML element showing the graph
		this.graph = null;	// graph JS object
		this.series = null;

		this.init = function init (element) {
			self.graphElement = element;
			var d = new Date();
			self.series = [
			    {
					color : 'steelblue',
					data : [ {x:d.getTime(), y:0} ],
					name : "Line 1"
				}
			];

			/**
			 * set graph data as attribute
			 */
			$scope.$watch($attrs.additionalgraphdata, function(value) {
				if (graph != null && Array.isArray(value) && value.length > 0) {
					self.updateGraphContent(value);
				}
			});

			/**
			 * set graph data as attribute
			 */
			$scope.$watch($attrs.graphdata, function(value) {
				if (graph != null && Array.isArray(value) && value.length > 0) {
					self.resetGraphContent(value);
				}
			});

			var graph = self.graph = new Rickshaw.Graph({
				element : element[0].children[0],
				width : element.width(),
				height : element.height() - 20,
				renderer : 'line',
				series : self.series
			});
			graph.render();

			var preview = new Rickshaw.Graph.RangeSlider({
				graph : graph,
				element : element[0].children[1]
			});

			var xAxis = new Rickshaw.Graph.Axis.Time({
				graph : graph,
				ticksTreatment : 'glow',
				timeFixture : new Rickshaw.Fixtures.Time.Local()
			});
			xAxis.render();

			var yAxis = new Rickshaw.Graph.Axis.Y({
				graph : graph,
				tickFormat : Rickshaw.Fixtures.Number.formatKMBT,
				ticksTreatment : 'glow'
			});
			yAxis.render();

			var Hover = Rickshaw.Class.create(Rickshaw.Graph.HoverDetail, {

				initialize: function(args) {

					var graph = this.graph = args.graph;

					this.xFormatter = args.xFormatter || function(x) {
						return new Date( x * 1000 ).toUTCString();
					};

					this.yFormatter = args.yFormatter || function(y) {
						return y === null ? y : y.toFixed(2);
					};

					var element = this.element = document.createElement('div');
					element.className = 'detail';

					this.visible = true;
					graph.element.appendChild(element);

					this.lastEvent = null;

					this.onShow = args.onShow;
					this.onHide = args.onHide;
					this.onRender = args.onRender;
					this.onClick = args.onClick;

					this.formatter = args.formatter || this.formatter;

					this._addListeners();
				},

				render: function(args) {

					var graph = this.graph;
					var points = args.points;
					var point = points.filter( function(p) { return p.active; } ).shift();

					if (point.value.y === null) return;

					var formattedXValue = point.formattedXValue;
					var formattedYValue = point.formattedYValue;

					this.element.innerHTML = '';
					this.element.style.left = graph.x(point.value.x) + 'px';
					this.element.setAttribute("data-time", point.value.x);  // add the x value as data property on detail node

					var xLabel = document.createElement('div');

					xLabel.className = 'x_label';
					xLabel.innerHTML = formattedXValue;
					this.element.appendChild(xLabel);

					var item = document.createElement('div');

					item.className = 'item';

					// invert the scale if this series displays using a scale
					var series = point.series;
					var actualY = series.scale ? series.scale.invert(point.value.y) : point.value.y;

					item.innerHTML = this.formatter(series, point.value.x, actualY, formattedXValue, formattedYValue, point);
					item.style.top = this.graph.y(point.value.y0 + point.value.y) + 'px';

					this.element.appendChild(item);

					var dot = document.createElement('div');

					dot.className = 'dot';
					dot.style.top = item.style.top;
					dot.style.borderColor = series.color;

					this.element.appendChild(dot);

					if (point.active) {
						item.classList.add('active');
						dot.classList.add('active');
					}

					// Assume left alignment until the element has been displayed and
					// bounding box calculations are possible.
					var alignables = [xLabel, item];
					alignables.forEach(function(el) {
						el.classList.add('left');
					});

					this.show();

					// If left-alignment results in any error, try right-alignment.
					var leftAlignError = this._calcLayoutError(alignables);
					if (leftAlignError > 0) {
						alignables.forEach(function(el) {
							el.classList.remove('left');
							el.classList.add('right');
						});

						// If right-alignment is worse than left alignment, switch back.
						var rightAlignError = this._calcLayoutError(alignables);
						if (rightAlignError > leftAlignError) {
							alignables.forEach(function(el) {
								el.classList.remove('right');
								el.classList.add('left');
							});
						}
					}

					if (typeof this.onRender == 'function') {
						this.onRender(args);
					}
				},

				_addListeners: function() {

					this.graph.element.addEventListener(
						'mousemove',
						function(e) {
							this.visible = true;
							this.update(e);
						}.bind(this),
						false
					);

					this.graph.onUpdate( function() { this.update(); }.bind(this) );

					this.graph.element.addEventListener(
						'mouseout',
						function(e) {
							if (e.relatedTarget && !(e.relatedTarget.compareDocumentPosition(this.graph.element) & Node.DOCUMENT_POSITION_CONTAINS)) {
								this.hide();
							}
						}.bind(this),
						false
					);

					// add click handler if required
					if (typeof this.onClick == 'function') {
						this.graph.element.addEventListener(
								'click',
								function(e) {
									// use data-time to go to correct time in player
									var time = this.element.getAttribute('data-time');
									this.onClick(time);
								}.bind(this),
								false
						);

					}
				}
			});

			var hoverDetail = new Hover( {
			    graph: graph,
			    formatter: function(series, x, y, formattedXValue, formattedYValue, point) {
			    	return y + ' views';
			    },
				onClick : function (time) {
					alert(time);
				}
			} );
		};

		/**
		 * remove all previous data and set new
		 * @param value
		 */
		this.resetGraphContent = function resetGraphContent(value) {
			var ar = self.series[0].data;
			while (ar.length > 0) {
				ar.pop();
			}
			for ( var i = 0; i < value.length; i++) {
				ar.push(value[i]);
			}
			self.graph.update();
		};

		/**
		 * add new data and purge oldest so we keep only 36 hrs
		 * @param value
		 */
		this.updateGraphContent = function updateGraphContent(value) {
			var ar = self.series[0].data;
			// find matching point in 'ar'
			var lastX = ar[ar.length-1].x;
			for (var i = value.length-1; i>0; i--) {
				if (value[i].x == lastX) {
					break;
				}
			}
			// now i+1 is the index of the first element in 'value' that needs to be inserted to 'ar'
			// add required elements from value to ar, while removing elements from tail
			i++;
			while(i<value.length) {
				ar.shift();
				ar.push(value[i]);
				i++;
			}
			self.graph.update();
		};

}]);<|endoftext|>