<commit_before>/*global define*/
define([
        '../Core/Color',
        '../Core/defaultValue',
        '../Core/defined',
        '../Core/destroyObject',
        '../Core/DeveloperError',
        '../Scene/BillboardCollection',
        '../Renderer/TextureAtlasBuilder'
    ], function(
        Color,
        defaultValue,
        defined,
        destroyObject,
        DeveloperError,
        BillboardCollection,
        TextureAtlasBuilder) {
    "use strict";

    /**
     * A DynamicObject visualizer which maps the DynamicPoint instance
     * in DynamicObject.point to a Billboard primitive with a point texture.
     * @alias DynamicPointVisualizer
     * @constructor
     *
     * @param {Scene} scene The scene the primitives will be rendered in.
     * @param {DynamicObjectCollection} [dynamicObjectCollection] The dynamicObjectCollection to visualize.
     *
     * @see DynamicPoint
     * @see Scene
     * @see DynamicObject
     * @see DynamicObjectCollection
     * @see CompositeDynamicObjectCollection
     * @see DynamicBillboardVisualizer
     * @see DynamicConeVisualizer
     * @see DynamicConeVisualizerUsingCustomSensor
     * @see DynamicLabelVisualizer
     * @see DynamicPyramidVisualizer
     */
    var DynamicPointVisualizer = function(scene, dynamicObjectCollection) {
        //>>includeStart('debug', pragmas.debug);
        if (!defined(scene)) {
            throw new DeveloperError('scene is required.');
        }
        //>>includeEnd('debug');

        this._scene = scene;
        this._unusedIndexes = [];
        this._dynamicObjectCollection = undefined;
        var billboardCollection = this._billboardCollection = new BillboardCollection();
        var atlas = this._textureAtlas = scene.context.createTextureAtlas();
        this._textureAtlasBuilder = new TextureAtlasBuilder(atlas);
        billboardCollection.textureAtlas = atlas;
        scene.primitives.add(billboardCollection);
        this.setDynamicObjectCollection(dynamicObjectCollection);
    };

    /**
     * Returns the scene being used by this visualizer.
     *
     * @returns {Scene} The scene being used by this visualizer.
     */
    DynamicPointVisualizer.prototype.getScene = function() {
        return this._scene;
    };

    /**
     * Gets the DynamicObjectCollection being visualized.
     *
     * @returns {DynamicObjectCollection} The DynamicObjectCollection being visualized.
     */
    DynamicPointVisualizer.prototype.getDynamicObjectCollection = function() {
        return this._dynamicObjectCollection;
    };

    /**
     * Sets the DynamicObjectCollection to visualize.
     *
     * @param dynamicObjectCollection The DynamicObjectCollection to visualizer.
     */
    DynamicPointVisualizer.prototype.setDynamicObjectCollection = function(dynamicObjectCollection) {
        var oldCollection = this._dynamicObjectCollection;
        if (oldCollection !== dynamicObjectCollection) {
            if (defined(oldCollection)) {
                oldCollection.collectionChanged.removeEventListener(DynamicPointVisualizer.prototype._onObjectsRemoved, this);
                this.removeAllPrimitives();
            }
            this._dynamicObjectCollection = dynamicObjectCollection;
            if (defined(dynamicObjectCollection)) {
                dynamicObjectCollection.collectionChanged.addEventListener(DynamicPointVisualizer.prototype._onObjectsRemoved, this);
            }
        }
    };

    /**
     * Updates all of the primitives created by this visualizer to match their
     * DynamicObject counterpart at the given time.
     *
     * @param {JulianDate} time The time to update to.
     */
    DynamicPointVisualizer.prototype.update = function(time) {
        //>>includeStart('debug', pragmas.debug);
        if (!defined(time)) {
            throw new DeveloperError('time is required.');
        }
        //>>includeEnd('debug');

        if (defined(this._dynamicObjectCollection)) {
            var dynamicObjects = this._dynamicObjectCollection.getObjects();
            for ( var i = 0, len = dynamicObjects.length; i < len; i++) {
                updateObject(this, time, dynamicObjects[i]);
            }
        }
    };

    /**
     * Removes all primitives from the scene.
     */
    DynamicPointVisualizer.prototype.removeAllPrimitives = function() {
        this._unusedIndexes = [];
        this._billboardCollection.removeAll();
        if (defined(this._dynamicObjectCollection)) {
            var dynamicObjects = this._dynamicObjectCollection.getObjects();
            for ( var i = dynamicObjects.length - 1; i > -1; i--) {
                dynamicObjects[i]._pointVisualizerIndex = undefined;
            }
        }
    };

    /**
     * Returns true if this object was destroyed; otherwise, false.
     *

     * If this object was destroyed, it should not be used; calling any function other than
     * isDestroyed will result in a {@link DeveloperError} exception.
     *
     * @memberof DynamicPointVisualizer
     *
     * @returns {Boolean} True if this object was destroyed; otherwise, false.
     *
     * @see DynamicPointVisualizer#destroy
     */
    DynamicPointVisualizer.prototype.isDestroyed = function() {
        return false;
    };

    /**
     * Destroys the WebGL resources held by this object.  Destroying an object allows for deterministic
     * release of WebGL resources, instead of relying on the garbage collector to destroy this object.
     *

     * Once an object is destroyed, it should not be used; calling any function other than
     * isDestroyed will result in a {@link DeveloperError} exception.  Therefore,
     * assign the return value (undefined) to the object as done in the example.
     *
     * @memberof DynamicPointVisualizer
     *
     * @returns {undefined}
     *
     * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.
     *
     * @see DynamicPointVisualizer#isDestroyed
     *
     * @example
     * visualizer = visualizer && visualizer.destroy();
     */
    DynamicPointVisualizer.prototype.destroy = function() {
        this.setDynamicObjectCollection(undefined);
        this._scene.primitives.remove(this._billboardCollection);
        return destroyObject(this);
    };

    var color;
    var position;
    var outlineColor;
    var scaleByDistance;
    function updateObject(dynamicPointVisualizer, time, dynamicObject) {
        var dynamicPoint = dynamicObject._point;
        if (!defined(dynamicPoint)) {
            return;
        }

        var positionProperty = dynamicObject._position;
        if (!defined(positionProperty)) {
            return;
        }

        var billboard;
        var showProperty = dynamicPoint._show;
        var pointVisualizerIndex = dynamicObject._pointVisualizerIndex;
        var show = dynamicObject.isAvailable(time) && (!defined(showProperty) || showProperty.getValue(time));

        if (!show) {
            //don't bother creating or updating anything else
            if (defined(pointVisualizerIndex)) {
                billboard = dynamicPointVisualizer._billboardCollection.get(pointVisualizerIndex);
                billboard.setShow(false);
                billboard.setImageIndex(-1);
                dynamicObject._pointVisualizerIndex = undefined;
                dynamicPointVisualizer._unusedIndexes.push(pointVisualizerIndex);
            }
            return;
        }

        var needRedraw = false;
        if (!defined(pointVisualizerIndex)) {
            var unusedIndexes = dynamicPointVisualizer._unusedIndexes;
            var length = unusedIndexes.length;
            if (length > 0) {
                pointVisualizerIndex = unusedIndexes.pop();
                billboard = dynamicPointVisualizer._billboardCollection.get(pointVisualizerIndex);
            } else {
                pointVisualizerIndex = dynamicPointVisualizer._billboardCollection.length;
                billboard = dynamicPointVisualizer._billboardCollection.add();
            }
            dynamicObject._pointVisualizerIndex = pointVisualizerIndex;
            billboard.id = dynamicObject;

            // CZML_TODO Determine official defaults
            billboard._visualizerColor = Color.clone(Color.WHITE, billboard._visualizerColor);
            billboard._visualizerOutlineColor = Color.clone(Color.BLACK, billboard._visualizerOutlineColor);
            billboard._visualizerOutlineWidth = 0;
            billboard._visualizerPixelSize = 1;
            needRedraw = true;
        } else {
            billboard = dynamicPointVisualizer._billboardCollection.get(pointVisualizerIndex);
        }

        billboard.setShow(true);

        position = positionProperty.getValue(time, position);
        if (defined(position)) {
            billboard.setPosition(position);
        }

        var property = dynamicPoint._color;
        if (defined(property)) {
            color = property.getValue(time, color);
            if (!Color.equals(billboard._visualizerColor, color)) {
                Color.clone(color, billboard._visualizerColor);
                needRedraw = true;
            }
        }

        property = dynamicPoint._outlineColor;
        if (defined(property)) {
            outlineColor = property.getValue(time, outlineColor);
            if (!Color.equals(billboard._visualizerOutlineColor, outlineColor)) {
                Color.clone(outlineColor, billboard._visualizerOutlineColor);
                needRedraw = true;
            }
        }

        property = dynamicPoint._outlineWidth;
        if (defined(property)) {
            var outlineWidth = property.getValue(time);
            if (billboard._visualizerOutlineWidth !== outlineWidth) {
                billboard._visualizerOutlineWidth = outlineWidth;
                needRedraw = true;
            }
        }

        property = dynamicPoint._pixelSize;
        if (defined(property)) {
            var pixelSize = property.getValue(time);
            if (billboard._visualizerPixelSize !== pixelSize) {
                billboard._visualizerPixelSize = pixelSize;
                needRedraw = true;
            }
        }

        property = dynamicPoint._scaleByDistance;
        if (defined(property)) {
            scaleByDistance = property.getValue(time, scaleByDistance);
            if (defined(scaleByDistance)) {
                billboard.setScaleByDistance(scaleByDistance);
            }
        }

        if (needRedraw) {
            var cssColor = defaultValue(billboard._visualizerColor, Color.WHITE).toCssColorString();
            var cssOutlineColor = defaultValue(billboard._visualizerOutlineColor, Color.BLACK).toCssColorString();
            var cssPixelSize = defaultValue(billboard._visualizerPixelSize, 3);
            var cssOutlineWidth = defaultValue(billboard._visualizerOutlineWidth, 2);
            var textureId = JSON.stringify([cssColor, cssPixelSize, cssOutlineColor, cssOutlineWidth]);

            dynamicPointVisualizer._textureAtlasBuilder.addTextureFromFunction(textureId, function(id, loadedCallback) {
                var canvas = document.createElement('canvas');

                var length = cssPixelSize + (2 * cssOutlineWidth);
                canvas.height = canvas.width = length;

                var context2D = canvas.getContext('2d');
                context2D.clearRect(0, 0, length, length);

                if (cssOutlineWidth !== 0) {
                    context2D.beginPath();
                    context2D.arc(length / 2, length / 2, length / 2, 0, 2 * Math.PI, true);
                    context2D.closePath();
                    context2D.fillStyle = cssOutlineColor;
                    context2D.fill();
                }

                context2D.beginPath();
                context2D.arc(length / 2, length / 2, cssPixelSize / 2, 0, 2 * Math.PI, true);
                context2D.closePath();
                context2D.fillStyle = cssColor;
                context2D.fill();

                loadedCallback(canvas);
            }, function(imageIndex) {
                billboard.setImageIndex(imageIndex);
            });
        }
    }

    DynamicPointVisualizer.prototype._onObjectsRemoved = function(dynamicObjectCollection, added, dynamicObjects) {
        var thisBillboardCollection = this._billboardCollection;
        var thisUnusedIndexes = this._unusedIndexes;
        for ( var i = dynamicObjects.length - 1; i > -1; i--) {
            var dynamicObject = dynamicObjects[i];
            var pointVisualizerIndex = dynamicObject._pointVisualizerIndex;
            if (defined(pointVisualizerIndex)) {
                var billboard = thisBillboardCollection.get(pointVisualizerIndex);
                billboard.setShow(false);
                billboard.setImageIndex(-1);
                dynamicObject._pointVisualizerIndex = undefined;
                thisUnusedIndexes.push(pointVisualizerIndex);
            }
        }
    };

    return DynamicPointVisualizer;
});
<commit_msg>Fix #1554 where a transparent point leaked its outline color.<commit_after>/*global define*/
define([
        '../Core/Color',
        '../Core/defaultValue',
        '../Core/defined',
        '../Core/destroyObject',
        '../Core/DeveloperError',
        '../Scene/BillboardCollection',
        '../Renderer/TextureAtlasBuilder'
    ], function(
        Color,
        defaultValue,
        defined,
        destroyObject,
        DeveloperError,
        BillboardCollection,
        TextureAtlasBuilder) {
    "use strict";

    /**
     * A DynamicObject visualizer which maps the DynamicPoint instance
     * in DynamicObject.point to a Billboard primitive with a point texture.
     * @alias DynamicPointVisualizer
     * @constructor
     *
     * @param {Scene} scene The scene the primitives will be rendered in.
     * @param {DynamicObjectCollection} [dynamicObjectCollection] The dynamicObjectCollection to visualize.
     *
     * @see DynamicPoint
     * @see Scene
     * @see DynamicObject
     * @see DynamicObjectCollection
     * @see CompositeDynamicObjectCollection
     * @see DynamicBillboardVisualizer
     * @see DynamicConeVisualizer
     * @see DynamicConeVisualizerUsingCustomSensor
     * @see DynamicLabelVisualizer
     * @see DynamicPyramidVisualizer
     */
    var DynamicPointVisualizer = function(scene, dynamicObjectCollection) {
        //>>includeStart('debug', pragmas.debug);
        if (!defined(scene)) {
            throw new DeveloperError('scene is required.');
        }
        //>>includeEnd('debug');

        this._scene = scene;
        this._unusedIndexes = [];
        this._dynamicObjectCollection = undefined;
        var billboardCollection = this._billboardCollection = new BillboardCollection();
        var atlas = this._textureAtlas = scene.context.createTextureAtlas();
        this._textureAtlasBuilder = new TextureAtlasBuilder(atlas);
        billboardCollection.textureAtlas = atlas;
        scene.primitives.add(billboardCollection);
        this.setDynamicObjectCollection(dynamicObjectCollection);
    };

    /**
     * Returns the scene being used by this visualizer.
     *
     * @returns {Scene} The scene being used by this visualizer.
     */
    DynamicPointVisualizer.prototype.getScene = function() {
        return this._scene;
    };

    /**
     * Gets the DynamicObjectCollection being visualized.
     *
     * @returns {DynamicObjectCollection} The DynamicObjectCollection being visualized.
     */
    DynamicPointVisualizer.prototype.getDynamicObjectCollection = function() {
        return this._dynamicObjectCollection;
    };

    /**
     * Sets the DynamicObjectCollection to visualize.
     *
     * @param dynamicObjectCollection The DynamicObjectCollection to visualizer.
     */
    DynamicPointVisualizer.prototype.setDynamicObjectCollection = function(dynamicObjectCollection) {
        var oldCollection = this._dynamicObjectCollection;
        if (oldCollection !== dynamicObjectCollection) {
            if (defined(oldCollection)) {
                oldCollection.collectionChanged.removeEventListener(DynamicPointVisualizer.prototype._onObjectsRemoved, this);
                this.removeAllPrimitives();
            }
            this._dynamicObjectCollection = dynamicObjectCollection;
            if (defined(dynamicObjectCollection)) {
                dynamicObjectCollection.collectionChanged.addEventListener(DynamicPointVisualizer.prototype._onObjectsRemoved, this);
            }
        }
    };

    /**
     * Updates all of the primitives created by this visualizer to match their
     * DynamicObject counterpart at the given time.
     *
     * @param {JulianDate} time The time to update to.
     */
    DynamicPointVisualizer.prototype.update = function(time) {
        //>>includeStart('debug', pragmas.debug);
        if (!defined(time)) {
            throw new DeveloperError('time is required.');
        }
        //>>includeEnd('debug');

        if (defined(this._dynamicObjectCollection)) {
            var dynamicObjects = this._dynamicObjectCollection.getObjects();
            for ( var i = 0, len = dynamicObjects.length; i < len; i++) {
                updateObject(this, time, dynamicObjects[i]);
            }
        }
    };

    /**
     * Removes all primitives from the scene.
     */
    DynamicPointVisualizer.prototype.removeAllPrimitives = function() {
        this._unusedIndexes = [];
        this._billboardCollection.removeAll();
        if (defined(this._dynamicObjectCollection)) {
            var dynamicObjects = this._dynamicObjectCollection.getObjects();
            for ( var i = dynamicObjects.length - 1; i > -1; i--) {
                dynamicObjects[i]._pointVisualizerIndex = undefined;
            }
        }
    };

    /**
     * Returns true if this object was destroyed; otherwise, false.
     *

     * If this object was destroyed, it should not be used; calling any function other than
     * isDestroyed will result in a {@link DeveloperError} exception.
     *
     * @memberof DynamicPointVisualizer
     *
     * @returns {Boolean} True if this object was destroyed; otherwise, false.
     *
     * @see DynamicPointVisualizer#destroy
     */
    DynamicPointVisualizer.prototype.isDestroyed = function() {
        return false;
    };

    /**
     * Destroys the WebGL resources held by this object.  Destroying an object allows for deterministic
     * release of WebGL resources, instead of relying on the garbage collector to destroy this object.
     *

     * Once an object is destroyed, it should not be used; calling any function other than
     * isDestroyed will result in a {@link DeveloperError} exception.  Therefore,
     * assign the return value (undefined) to the object as done in the example.
     *
     * @memberof DynamicPointVisualizer
     *
     * @returns {undefined}
     *
     * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.
     *
     * @see DynamicPointVisualizer#isDestroyed
     *
     * @example
     * visualizer = visualizer && visualizer.destroy();
     */
    DynamicPointVisualizer.prototype.destroy = function() {
        this.setDynamicObjectCollection(undefined);
        this._scene.primitives.remove(this._billboardCollection);
        return destroyObject(this);
    };

    var color;
    var position;
    var outlineColor;
    var scaleByDistance;
    function updateObject(dynamicPointVisualizer, time, dynamicObject) {
        var dynamicPoint = dynamicObject._point;
        if (!defined(dynamicPoint)) {
            return;
        }

        var positionProperty = dynamicObject._position;
        if (!defined(positionProperty)) {
            return;
        }

        var billboard;
        var showProperty = dynamicPoint._show;
        var pointVisualizerIndex = dynamicObject._pointVisualizerIndex;
        var show = dynamicObject.isAvailable(time) && (!defined(showProperty) || showProperty.getValue(time));

        if (!show) {
            //don't bother creating or updating anything else
            if (defined(pointVisualizerIndex)) {
                billboard = dynamicPointVisualizer._billboardCollection.get(pointVisualizerIndex);
                billboard.setShow(false);
                billboard.setImageIndex(-1);
                dynamicObject._pointVisualizerIndex = undefined;
                dynamicPointVisualizer._unusedIndexes.push(pointVisualizerIndex);
            }
            return;
        }

        var needRedraw = false;
        if (!defined(pointVisualizerIndex)) {
            var unusedIndexes = dynamicPointVisualizer._unusedIndexes;
            var length = unusedIndexes.length;
            if (length > 0) {
                pointVisualizerIndex = unusedIndexes.pop();
                billboard = dynamicPointVisualizer._billboardCollection.get(pointVisualizerIndex);
            } else {
                pointVisualizerIndex = dynamicPointVisualizer._billboardCollection.length;
                billboard = dynamicPointVisualizer._billboardCollection.add();
            }
            dynamicObject._pointVisualizerIndex = pointVisualizerIndex;
            billboard.id = dynamicObject;

            // CZML_TODO Determine official defaults
            billboard._visualizerColor = Color.clone(Color.WHITE, billboard._visualizerColor);
            billboard._visualizerOutlineColor = Color.clone(Color.BLACK, billboard._visualizerOutlineColor);
            billboard._visualizerOutlineWidth = 0;
            billboard._visualizerPixelSize = 1;
            needRedraw = true;
        } else {
            billboard = dynamicPointVisualizer._billboardCollection.get(pointVisualizerIndex);
        }

        billboard.setShow(true);

        position = positionProperty.getValue(time, position);
        if (defined(position)) {
            billboard.setPosition(position);
        }

        var property = dynamicPoint._color;
        if (defined(property)) {
            color = property.getValue(time, color);
            if (!Color.equals(billboard._visualizerColor, color)) {
                Color.clone(color, billboard._visualizerColor);
                needRedraw = true;
            }
        }

        property = dynamicPoint._outlineColor;
        if (defined(property)) {
            outlineColor = property.getValue(time, outlineColor);
            if (!Color.equals(billboard._visualizerOutlineColor, outlineColor)) {
                Color.clone(outlineColor, billboard._visualizerOutlineColor);
                needRedraw = true;
            }
        }

        property = dynamicPoint._outlineWidth;
        if (defined(property)) {
            var outlineWidth = property.getValue(time);
            if (billboard._visualizerOutlineWidth !== outlineWidth) {
                billboard._visualizerOutlineWidth = outlineWidth;
                needRedraw = true;
            }
        }

        property = dynamicPoint._pixelSize;
        if (defined(property)) {
            var pixelSize = property.getValue(time);
            if (billboard._visualizerPixelSize !== pixelSize) {
                billboard._visualizerPixelSize = pixelSize;
                needRedraw = true;
            }
        }

        property = dynamicPoint._scaleByDistance;
        if (defined(property)) {
            scaleByDistance = property.getValue(time, scaleByDistance);
            if (defined(scaleByDistance)) {
                billboard.setScaleByDistance(scaleByDistance);
            }
        }

        if (needRedraw) {
            var centerColor = defaultValue(billboard._visualizerColor, Color.WHITE);
            var centerAlpha = centerColor.alpha;
            var cssColor = centerColor.toCssColorString();
            var cssOutlineColor = defaultValue(billboard._visualizerOutlineColor, Color.BLACK).toCssColorString();
            var cssPixelSize = defaultValue(billboard._visualizerPixelSize, 3);
            var cssOutlineWidth = defaultValue(billboard._visualizerOutlineWidth, 2);
            var textureId = JSON.stringify([cssColor, cssPixelSize, cssOutlineColor, cssOutlineWidth]);

            dynamicPointVisualizer._textureAtlasBuilder.addTextureFromFunction(textureId, function(id, loadedCallback) {
                var canvas = document.createElement('canvas');

                var length = cssPixelSize + (2 * cssOutlineWidth);
                canvas.height = canvas.width = length;

                var context2D = canvas.getContext('2d');
                context2D.clearRect(0, 0, length, length);

                if (cssOutlineWidth !== 0) {
                    context2D.beginPath();
                    context2D.arc(length / 2, length / 2, length / 2, 0, 2 * Math.PI, true);
                    context2D.closePath();
                    context2D.fillStyle = cssOutlineColor;
                    context2D.fill();
                    // Punch a hole in the center if needed.
                    if (centerAlpha < 1.0) {
                        context2D.save();
                        context2D.globalCompositeOperation = 'destination-out';
                        context2D.beginPath();
                        context2D.arc(length / 2, length / 2, cssPixelSize / 2, 0, 2 * Math.PI, true);
                        context2D.closePath();
                        context2D.fillStyle = 'black';
                        context2D.fill();
                        context2D.restore();
                    }
                }

                context2D.beginPath();
                context2D.arc(length / 2, length / 2, cssPixelSize / 2, 0, 2 * Math.PI, true);
                context2D.closePath();
                context2D.fillStyle = cssColor;
                context2D.fill();

                loadedCallback(canvas);
            }, function(imageIndex) {
                billboard.setImageIndex(imageIndex);
            });
        }
    }

    DynamicPointVisualizer.prototype._onObjectsRemoved = function(dynamicObjectCollection, added, dynamicObjects) {
        var thisBillboardCollection = this._billboardCollection;
        var thisUnusedIndexes = this._unusedIndexes;
        for ( var i = dynamicObjects.length - 1; i > -1; i--) {
            var dynamicObject = dynamicObjects[i];
            var pointVisualizerIndex = dynamicObject._pointVisualizerIndex;
            if (defined(pointVisualizerIndex)) {
                var billboard = thisBillboardCollection.get(pointVisualizerIndex);
                billboard.setShow(false);
                billboard.setImageIndex(-1);
                dynamicObject._pointVisualizerIndex = undefined;
                thisUnusedIndexes.push(pointVisualizerIndex);
            }
        }
    };

    return DynamicPointVisualizer;
});
<|endoftext|>


<commit_before>import loggerCreator from "app/utils/logger";
//noinspection JSUnresolvedVariable
const moduleLogger = loggerCreator("MasterPage");

import React, { Component } from "react";
import { Image, StyleSheet } from "react-native";
import { observer } from "mobx-react";

import { MenuContext } from "app/shared_components/context_menu/context_menu";
import NavSidebar from "./nav_sidebar/nav_sidebar";
import constants from "app/utils/constants";
import { navigator } from "app/stores/navigator.js";
import settings from "app/utils/settings/settings";
import settingsNative from "app/utils/settings/settings_native";

import PlayerPage from "app/pages/player_page/player_page";
import SettingsPage from "app/pages/settings/settings_page";

import backgroundImage from "app/images/background.jpg";
import Topbar from "./topbar";
import PlaylistSidebar from "app/pages/master_page/playlist_sidebar/playlist_sidebar";
import { player } from "app/stores/player/player";
import { playlistsStore } from "app/stores/playlists_store";
import { masterStore } from "app/stores/master_store";
import SearchPage from "app/pages/search_page/search_page";
import SavePlaylistPage from "app/pages/search_page/playlist_name_part";

const styles = StyleSheet.create({
  container: {
    flex: 1,
    position: "relative",
    // remove width and height to override fixed static size
    width: null,
    height: null,
    alignSelf: "stretch",
    resizeMode: "cover",
    overflow: "hidden",
  },
  menuContext: { flex: 1, alignSelf: "stretch" },
});

@observer
export default class MasterPage extends Component {
  async componentWillMount() {
    let logger = loggerCreator("componentWillMount", moduleLogger);

    this.state = {
      ready: false,
    };

    logger.info(`loading settings`);
    await settings.load();
    await settingsNative.load();

    logger.info(`is host configured?`);
    if (settings.host) {
      logger.info(`updated status. playing? ${player.isPlaying}`);
      if (player.isPlaying) {
        logger.info(`player currently playing - navigating to player`);
        navigator.navigateToPlayer();
      }
      logger.info(`loading playlists`);
      playlistsStore.updatePlaylists().then(() => {
        logger.info(`finishing loading playlists`);
      });
    } else {
      logger.info(`host not found in settings - showing settings page`);
      navigator.navigateToSettings();
      masterStore.closeSidebars();
    }

    logger.info(`initialization finished`);
    this.setState({ ready: true });
  }

  render() {
    let logger = loggerCreator(this.render.name, moduleLogger);
    logger.info(`activate route: ${navigator.activeRoute}`);

    let page = null;
    let activeRoute = navigator.activeRoute;

    if (activeRoute) {
      switch (activeRoute.address) {
        case constants.ROUTE_PLAYER_PAGE:
          page = <PlayerPage {...activeRoute} />;
          break;
        case constants.ROUTE_SETTINGS_PAGE:
          page = <SettingsPage {...activeRoute} />;
          break;
        case constants.ROUTE_SEARCH_PAGE:
          page = <SearchPage {...activeRoute} />;
          break;
        default:
          throw new Error("unexpected route");
      }
    }

    if (this.state.ready) {
      return (
        <Image source={backgroundImage} style={styles.container}>
          <MenuContext customStyles={{ menuContextWrapper: styles.menuContext }}>
            <Topbar />
            {page}
          </MenuContext>
          <NavSidebar />
          {player.currentPlaylist ? <PlaylistSidebar /> : null}
        </Image>
      );
    } else {
      return null;
    }
  }
}

MasterPage.propTypes = {};
<commit_msg>touching anything besides the sidebar causes it to close<commit_after>import loggerCreator from "app/utils/logger";
//noinspection JSUnresolvedVariable
const moduleLogger = loggerCreator("MasterPage");

import React, { Component } from "react";
import { Image, StyleSheet, View } from "react-native";
import { observer } from "mobx-react";

import { MenuContext } from "app/shared_components/context_menu/context_menu";
import NavSidebar from "./nav_sidebar/nav_sidebar";
import constants from "app/utils/constants";
import { navigator } from "app/stores/navigator.js";
import settings from "app/utils/settings/settings";
import settingsNative from "app/utils/settings/settings_native";

import PlayerPage from "app/pages/player_page/player_page";
import SettingsPage from "app/pages/settings/settings_page";

import backgroundImage from "app/images/background.jpg";
import Topbar from "./topbar";
import PlaylistSidebar from "app/pages/master_page/playlist_sidebar/playlist_sidebar";
import { player } from "app/stores/player/player";
import { playlistsStore } from "app/stores/playlists_store";
import { masterStore } from "app/stores/master_store";
import SearchPage from "app/pages/search_page/search_page";

const styles = StyleSheet.create({
  container: {
    flex: 1,
    position: "relative",
    // remove width and height to override fixed static size
    width: null,
    height: null,
    alignSelf: "stretch",
    resizeMode: "cover",
    overflow: "hidden",
  },
  menuContext: { flex: 1, alignSelf: "stretch" },
  sidebarCurtain: {
    position: "absolute",
    top: 0,
    left: 0,
    bottom: 0,
    right: 0,
    backgroundColor: "transparent",
  },
});

@observer
export default class MasterPage extends Component {
  async componentWillMount() {
    let logger = loggerCreator("componentWillMount", moduleLogger);

    this.state = {
      ready: false,
    };

    logger.info(`loading settings`);
    await settings.load();
    await settingsNative.load();

    logger.info(`is host configured?`);
    if (settings.host) {
      logger.info(`updated status. playing? ${player.isPlaying}`);
      if (player.isPlaying) {
        logger.info(`player currently playing - navigating to player`);
        navigator.navigateToPlayer();
      }
      logger.info(`loading playlists`);
      playlistsStore.updatePlaylists().then(() => {
        logger.info(`finishing loading playlists`);
      });
    } else {
      logger.info(`host not found in settings - showing settings page`);
      navigator.navigateToSettings();
      masterStore.closeSidebars();
    }

    logger.info(`initialization finished`);
    this.setState({ ready: true });
  }

  onSidebarCurtainPress = () => {
    masterStore.closeSidebars();
  };

  render() {
    let logger = loggerCreator(this.render.name, moduleLogger);
    logger.info(`activate route: ${navigator.activeRoute}`);

    let page = null;
    let activeRoute = navigator.activeRoute;

    if (activeRoute) {
      switch (activeRoute.address) {
        case constants.ROUTE_PLAYER_PAGE:
          page = <PlayerPage {...activeRoute} />;
          break;
        case constants.ROUTE_SETTINGS_PAGE:
          page = <SettingsPage {...activeRoute} />;
          break;
        case constants.ROUTE_SEARCH_PAGE:
          page = <SearchPage {...activeRoute} />;
          break;
        default:
          throw new Error("unexpected route");
      }
    }

    if (this.state.ready) {
      return (
        <Image source={backgroundImage} style={styles.container}>
          <MenuContext customStyles={{ menuContextWrapper: styles.menuContext }}>
            <Topbar />
            {page}
          </MenuContext>
          {masterStore.isPlaylistSidebarOpen || masterStore.isNavigationSidebarOpen
            ? <View style={styles.sidebarCurtain} onStartShouldSetResponder={this.onSidebarCurtainPress} />
            : null}
          <NavSidebar />
          {player.currentPlaylist ? <PlaylistSidebar /> : null}
        </Image>
      );
    } else {
      return null;
    }
  }
}

MasterPage.propTypes = {};
<|endoftext|>


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

    angular
        .module('app.avengers')
        .run(['routehelper', function(routehelper){
            routehelper.configureRoutes(getRoutes());
        }]);

    function getRoutes() {
        return [
            {
                url: '/avengers',
                config: {
                    templateUrl: 'app/avengers/avengers.html',
                    title: 'avengers',
                    settings: {
                        nav: 2,
                        content: ' Avengers'
                    }
                }
            }
        ];
    }
})();<commit_msg>modular: added leading slash to avengers route<commit_after>(function () {
    'use strict';

    angular
        .module('app.avengers')
        .run(['routehelper', function(routehelper){
            routehelper.configureRoutes(getRoutes());
        }]);

    function getRoutes() {
        return [
            {
                url: '/avengers',
                config: {
                    templateUrl: '/app/avengers/avengers.html',
                    title: 'avengers',
                    settings: {
                        nav: 2,
                        content: ' Avengers'
                    }
                }
            }
        ];
    }
})();<|endoftext|>


<commit_before>var redis = require('node-redis'),
    fs = require('fs'),
    path = require('path'),
    EventEmitter = require("events").EventEmitter,
    uuid = require('node-uuid');

var Thoonk = function() {
    EventEmitter.call(this);

    this.redis = redis.createClient();
    this.lredis = redis.createClient();
    this.ready = false;

    this.lredis.on('message', function(channel, msg) {
        msg = msg.toString();
        this.emit(channel, channel, msg);
    }.bind(this));

    this.lredis.on('subscribe', function(channel) {
        this.emit('subscribed.' + channel);
    }.bind(this));

    this.scripts = {};
    this.shas = {};

    this.instance = uuid();

    this.subscriptions = {};

    this.objects = {};
};

Thoonk.prototype = EventEmitter.prototype;
Thoonk.prototype.constructor = Thoonk;

(function() {
    //continue extending Thoonk

    this.quit = function() {
        this.redis.quit();
        this.lredis.quit();
    };

    this.registerType = function(objname, theobject, callback) {
        this.objects[objname] = function(name) {
            return new theobject(name, this);
        }.bind(this);
        var dir = theobject.prototype.scriptdir;
        this.scripts[theobject.prototype.objtype] = {};
        this.shas[theobject.prototype.objtype] = {}
        var curdir = fs.readdirSync(dir);
        curdir.forEach(function(filename, fidx, curdir) {
            if(path.extname(filename) == '.lua') {
                var verbname = path.basename(filename).slice(0,-4);
                this.scripts[theobject.prototype.objtype][verbname] = fs.readFileSync(dir + '/' + filename).toString();
                var last = (fidx + 1 == curdir.length);
                this.redis.sendCommand('SCRIPT', ['LOAD', this.scripts[theobject.prototype.objtype][verbname]], function(err, reply) {
                    this.shas[theobject.prototype.objtype][verbname] = reply.toString();
                    if(last) {
                        if(callback) {
                            callback(false);
                        }
                        this.emit('loaded.' + objname);
                    }
                }.bind(this));
            }
        }.bind(this));
    };

    this.create = function() {
    };

    this._runscript = function(objtype, scriptname, feedname, args, callback) {
        args = [this.shas[objtype][scriptname], '0', feedname].concat(args);
        this.redis.sendCommand('EVALSHA', args, callback);
    };

    this.feed = function(name, config) {
        return new Feed(name);
    };

}).call(Thoonk.prototype);

var ThoonkBaseObject = function(name, thoonk) {
    EventEmitter.call(this);
    this.thoonk = thoonk;
    this.redis = this.thoonk.redis;
    this.name = name;
    //TODO: create feed if it doesn't exist
};

ThoonkBaseObject.prototype = EventEmitter.prototype;
ThoonkBaseObject.constructor = ThoonkBaseObject;

(function() {

    this._build_event = function(eventtype) {
        return 'event.' + this.objtype + '.' + eventtype + ':' + this.name
    };

    this.handle_event = function(channel, msg) {
        //override this function in your object
    };

    this.init_subscribe = function(functions) {
        if(!this.thoonk.subscriptions.hasOwnProperty(this.name)) {
            this.thoonk.once('subscribed.' + this._build_event(this.subscribables[this.subscribables.length - 1]), function() {
                this.emit('subscribe_ready');
            }.bind(this));
            this.thoonk.subscriptions[this.name] = this.subscribables;
            for(var subscribable in this.subscribables) {
                this.thoonk.lredis.subscribe(this._build_event(this.subscribables[subscribable]));
            }
        }
        if(!this.subinitted) {
            for(var subscribable in this.subscribables) {
                this.thoonk.on(this._build_event(this.subscribables[subscribable]), this.handle_event.bind(this));
            }
            this.subinitted = true;
        }
    };

    this.runscript = function(scriptname, args, callback) {
        this.thoonk._runscript(this.objtype, scriptname, this.name, args, callback);
    };

}).call(ThoonkBaseObject.prototype);

exports.Thoonk = Thoonk;
exports.ThoonkBaseObject = ThoonkBaseObject;
<commit_msg>return values are now seperated for errors and parsed<commit_after>var redis = require('node-redis'),
    fs = require('fs'),
    path = require('path'),
    EventEmitter = require("events").EventEmitter,
    uuid = require('node-uuid');

var Thoonk = function() {
    EventEmitter.call(this);

    this.redis = redis.createClient();
    this.lredis = redis.createClient();
    this.ready = false;

    this.lredis.on('message', function(channel, msg) {
        msg = msg.toString();
        this.emit(channel, channel, msg);
    }.bind(this));

    this.lredis.on('subscribe', function(channel) {
        this.emit('subscribed.' + channel);
    }.bind(this));

    this.scripts = {};
    this.shas = {};

    this.instance = uuid();

    this.subscriptions = {};

    this.objects = {};
};

Thoonk.prototype = EventEmitter.prototype;
Thoonk.prototype.constructor = Thoonk;

(function() {
    //continue extending Thoonk

    this.quit = function() {
        this.redis.quit();
        this.lredis.quit();
    };

    this.registerType = function(objname, theobject, callback) {
        this.objects[objname] = function(name) {
            return new theobject(name, this);
        }.bind(this);
        var dir = theobject.prototype.scriptdir;
        this.scripts[theobject.prototype.objtype] = {};
        this.shas[theobject.prototype.objtype] = {}
        var curdir = fs.readdirSync(dir);
        curdir.forEach(function(filename, fidx, curdir) {
            if(path.extname(filename) == '.lua') {
                var verbname = path.basename(filename).slice(0,-4);
                this.scripts[theobject.prototype.objtype][verbname] = fs.readFileSync(dir + '/' + filename).toString();
                var last = (fidx + 1 == curdir.length);
                this.redis.sendCommand('SCRIPT', ['LOAD', this.scripts[theobject.prototype.objtype][verbname]], function(err, reply) {
                    this.shas[theobject.prototype.objtype][verbname] = reply.toString();
                    if(last) {
                        if(callback) {
                            callback(false);
                        }
                        this.emit('loaded.' + objname);
                    }
                }.bind(this));
            }
        }.bind(this));
    };

    this.create = function() {
    };

    this._runscript = function(objtype, scriptname, feedname, args, callback) {
        args = [this.shas[objtype][scriptname], '0', feedname].concat(args);
        this.redis.sendCommand('EVALSHA', args, callback);
    };

    this.feed = function(name, config) {
        return new Feed(name);
    };

}).call(Thoonk.prototype);

var ThoonkBaseObject = function(name, thoonk) {
    EventEmitter.call(this);
    this.thoonk = thoonk;
    this.redis = this.thoonk.redis;
    this.name = name;
    //TODO: create feed if it doesn't exist
};

ThoonkBaseObject.prototype = EventEmitter.prototype;
ThoonkBaseObject.constructor = ThoonkBaseObject;

(function() {

    this._build_event = function(eventtype) {
        return 'event.' + this.objtype + '.' + eventtype + ':' + this.name
    };

    this.handle_event = function(channel, msg) {
        //override this function in your object
    };

    this.init_subscribe = function(functions) {
        if(!this.thoonk.subscriptions.hasOwnProperty(this.name)) {
            this.thoonk.once('subscribed.' + this._build_event(this.subscribables[this.subscribables.length - 1]), function() {
                this.emit('subscribe_ready');
            }.bind(this));
            this.thoonk.subscriptions[this.name] = this.subscribables;
            for(var subscribable in this.subscribables) {
                this.thoonk.lredis.subscribe(this._build_event(this.subscribables[subscribable]));
            }
        }
        if(!this.subinitted) {
            for(var subscribable in this.subscribables) {
                this.thoonk.on(this._build_event(this.subscribables[subscribable]), this.handle_event.bind(this));
            }
            this.subinitted = true;
        }
    };

    this.runscript = function(scriptname, args, callback) {
        this.thoonk._runscript(this.objtype, scriptname, this.name, args, function(err, results) {
            if(err) {
                console.log(scriptname, err);
            } else {
                var newr = [];
                for(var i in results) {
                    if(results[i] != null && typeof results[i] === "object" && results[i].constructor == Buffer) {
                        newr.push(results[i].toString())
                    } else {
                        newr.push(results[i]);
                    }
                }
                callback.apply(this, newr);
            };
        }.bind(this));
    };

}).call(ThoonkBaseObject.prototype);

exports.Thoonk = Thoonk;
exports.ThoonkBaseObject = ThoonkBaseObject;
<|endoftext|>


<commit_before>(function (mw, $) {
	"use strict";

	var tvpapiAnalytics = mw.tvpapiRequest.extend({

		defaultConfig: {
			mediaHitInterval: 30,
			startTime:null,
			useNonDvrLinearMediaHits:false
		},

		isPlaying: false,
		concurrentFlag: false,
		fileId: null,
		didFirstPlay: false,
		mediaHitInterval: null,
		useNonDvrLinearMediaHits: false,

		setup: function() {
			if (this.getConfig("startTime")){
				this.continueTime = this.getConfig("startTime");
				this.playFromContinue = true;
			}
			this.bindEvents();
			this.bindContinueToTime();
		},

		bindEvents: function() {
			var _this = this;

			this.bind('playerReady', function(){
				_this.didFirstPlay = false;
				_this.fileId = _this.getPlayer().getSource() ? _this.getPlayer().getSource().assetid : null;
			});

			this.bind('firstPlay', function(){
				_this.didFirstPlay = true;
				_this.sendMediaMark('first_play');
			});

			this.bind('onplay', function(){
				_this.isPlaying = true;
				_this.startMediaHitInterval();
				_this.sendMediaMark('play');
			});

			this.bind('onpause', function(){
				_this.isPlaying = false;
				// During player start up, the player trigger "onpause" events
				// We use didFirstPlay flag to ignore them
				if( _this.didFirstPlay ) {
					_this.sendMediaMark('pause');
				}
			});

			this.bind('onEndedDone', function(){
				_this.isPlaying = false;
				_this.sendMediaMark('finish');
			});

			this.bind('widgetLoaded', function(){
				_this.sendMediaMark('load');
			});

			this.bind('SourceChange', function(){
				if(!_this.didFirstPlay) return;
				_this.sendMediaMark('bitrate_change');
			});

			this.bind('onChangeMedia', function(){
				_this.didFirstPlay = false;
			});
		},

		bindContinueToTime: function() {
			this.bind('tvpapiContinueToTime', $.proxy(function(e, seekTime){
				this.playFromContinue = true;
				this.continueTime = seekTime;
			},this));
			this.bind('seeked', $.proxy(function(){
				this.playFromContinue = false;
			},this));
		},

		startMediaHitInterval: function() {
			var _this = this;
			this.clearMediaHitInterval();
			this.mediaHitInterval = setInterval(function(){
				if( _this.isPlaying ) {
					_this.sendMediaHit();
					_this.playFromContinue = false;
				}
			}, this.getConfig('mediaHitInterval') * 1000 );
		},

		clearMediaHitInterval: function() {
			clearInterval(this.mediaHitInterval);
			this.mediaHitInterval = null;
		},

		sendMediaMark: function( action ) {
			var params = this.getBaseParams();
			params['Action'] = action;
			this.report('MediaMark', params);
		},

		sendMediaHit: function() {
		    var isLive = this.getPlayer().isLive();
		    var isDvr = this.getPlayer().isDVR();

			// Do not send media hit in the following conditions: concurrent limit, current time not updated (might be error) when media is not (live and not dvr and flag is set)
			if(this.concurrentFlag || (!(isLive && !isDvr && this.useNonDvrLinearMediaHits) && this.getPlayer().getPlayerElementTime() === 0) ){
			    return;
			}
			this.report('MediaHit', this.getBaseParams());
		},

		getCurrentTime: function() {
			var currentTime;
			if( this.playFromContinue ) {
				currentTime = this.continueTime;
			} else {
				currentTime = Math.round(this.getPlayer().getPlayerElementTime());
			}
			return currentTime;
		},

		getBaseParams: function() {
		    var isLive = this.getPlayer().isLive();
            var isDvr = this.getPlayer().isDVR();
			return {
				"initObj": this.getInitObj(),
				"mediaType": 0,
				"iMediaID": this.getProxyConfig('MediaID'),
				"iFileID": this.fileId,
				"iLocation": (isLive && !isDvr && this.useNonDvrLinearMediaHits) ? 0 : this.getCurrentTime()
			};
		},

		report: function(service, data){
			// Do not send requests during ad playback
			if( !this.getPlayer().isInSequence() ) {
				var printableData =  JSON.stringify(data, null, '\t');
				//Emit the report API event
				this.getPlayer().triggerHelper(service, data);
				this.log('report: ' + service + ": " + printableData);
				this.restMethod = service;
				var url = this.getRequestUrl();
				if (url) {

					var _this = this;

					this.doRequest(url, data).then(
							function (data) {
								_this.log('response for ' + service + ': ' + data);
								if (data == 'Concurrent') {
									_this.concurrentFlag = true;
									_this.getPlayer().triggerHelper('tvpapiShowConcurrent');
								}
							},
							function (xmlHttpRequest, status, errorThrown) {
								_this.log('sendPostRequest error: ' + errorThrown);
							},
							null
					);
				}
			}

			return false;
		}
	});
	mw.PluginManager.add( 'tvpapiAnalytics', tvpapiAnalytics);
})(window.mw, window.jQuery);
<commit_msg>fix: tvpanalytics fix bug related to enable nonDvrLinearMediaHits flag (#3814)<commit_after>(function (mw, $) {
	"use strict";

	var tvpapiAnalytics = mw.tvpapiRequest.extend({

		defaultConfig: {
			mediaHitInterval: 30,
			startTime:null,
			useNonDvrLinearMediaHits:false
		},

		isPlaying: false,
		concurrentFlag: false,
		fileId: null,
		didFirstPlay: false,
		mediaHitInterval: null,

		setup: function() {
			if (this.getConfig("startTime")){
				this.continueTime = this.getConfig("startTime");
				this.playFromContinue = true;
			}
			this.bindEvents();
			this.bindContinueToTime();
		},

		bindEvents: function() {
			var _this = this;

			this.bind('playerReady', function(){
				_this.didFirstPlay = false;
				_this.fileId = _this.getPlayer().getSource() ? _this.getPlayer().getSource().assetid : null;
			});

			this.bind('firstPlay', function(){
				_this.didFirstPlay = true;
				_this.sendMediaMark('first_play');
			});

			this.bind('onplay', function(){
				_this.isPlaying = true;
				_this.startMediaHitInterval();
				_this.sendMediaMark('play');
			});

			this.bind('onpause', function(){
				_this.isPlaying = false;
				// During player start up, the player trigger "onpause" events
				// We use didFirstPlay flag to ignore them
				if( _this.didFirstPlay ) {
					_this.sendMediaMark('pause');
				}
			});

			this.bind('onEndedDone', function(){
				_this.isPlaying = false;
				_this.sendMediaMark('finish');
			});

			this.bind('widgetLoaded', function(){
				_this.sendMediaMark('load');
			});

			this.bind('SourceChange', function(){
				if(!_this.didFirstPlay) return;
				_this.sendMediaMark('bitrate_change');
			});

			this.bind('onChangeMedia', function(){
				_this.didFirstPlay = false;
			});
		},

		bindContinueToTime: function() {
			this.bind('tvpapiContinueToTime', $.proxy(function(e, seekTime){
				this.playFromContinue = true;
				this.continueTime = seekTime;
			},this));
			this.bind('seeked', $.proxy(function(){
				this.playFromContinue = false;
			},this));
		},

		startMediaHitInterval: function() {
			var _this = this;
			this.clearMediaHitInterval();
			this.mediaHitInterval = setInterval(function(){
				if( _this.isPlaying ) {
					_this.sendMediaHit();
					_this.playFromContinue = false;
				}
			}, this.getConfig('mediaHitInterval') * 1000 );
		},

		clearMediaHitInterval: function() {
			clearInterval(this.mediaHitInterval);
			this.mediaHitInterval = null;
		},

		sendMediaMark: function( action ) {
			var params = this.getBaseParams();
			params['Action'] = action;
			this.report('MediaMark', params);
		},

		sendMediaHit: function() {
		    var isLive = this.getPlayer().isLive();
		    var isDvr = this.getPlayer().isDVR();
		    var enableNonDvrLinearMediaHits = this.getConfig('useNonDvrLinearMediaHits');

			// Do not send media hit in the following conditions: concurrent limit, current time not updated (might be error) when media is not (live and not dvr and flag is set)
			if(this.concurrentFlag || (!(isLive && !isDvr && enableNonDvrLinearMediaHits) && this.getPlayer().getPlayerElementTime() === 0) ){
			    return;
			}
			this.report('MediaHit', this.getBaseParams());
		},

		getCurrentTime: function() {
			var currentTime;
			if( this.playFromContinue ) {
				currentTime = this.continueTime;
			} else {
				currentTime = Math.round(this.getPlayer().getPlayerElementTime());
			}
			return currentTime;
		},

		getBaseParams: function() {
		    var isLive = this.getPlayer().isLive();
            var isDvr = this.getPlayer().isDVR();
            var enableNonDvrLinearMediaHits = this.getConfig('useNonDvrLinearMediaHits');
			return {
				"initObj": this.getInitObj(),
				"mediaType": 0,
				"iMediaID": this.getProxyConfig('MediaID'),
				"iFileID": this.fileId,
				"iLocation": (isLive && !isDvr && enableNonDvrLinearMediaHits) ? 0 : this.getCurrentTime()
			};
		},

		report: function(service, data){
			// Do not send requests during ad playback
			if( !this.getPlayer().isInSequence() ) {
				var printableData =  JSON.stringify(data, null, '\t');
				//Emit the report API event
				this.getPlayer().triggerHelper(service, data);
				this.log('report: ' + service + ": " + printableData);
				this.restMethod = service;
				var url = this.getRequestUrl();
				if (url) {

					var _this = this;

					this.doRequest(url, data).then(
							function (data) {
								_this.log('response for ' + service + ': ' + data);
								if (data == 'Concurrent') {
									_this.concurrentFlag = true;
									_this.getPlayer().triggerHelper('tvpapiShowConcurrent');
								}
							},
							function (xmlHttpRequest, status, errorThrown) {
								_this.log('sendPostRequest error: ' + errorThrown);
							},
							null
					);
				}
			}

			return false;
		}
	});
	mw.PluginManager.add( 'tvpapiAnalytics', tvpapiAnalytics);
})(window.mw, window.jQuery);<|endoftext|>


<commit_before>(function (server, user) {

    var processPerms = function (perms, fn) {
        var perm, actions, i, length;
        for (perm in perms) {
            if (perms.hasOwnProperty(perm)) {
                actions = perms[perm];
                length = actions.length;
                for (i = 0; i < length; i++) {
                    fn(perm, actions[i]);
                }
            }
        }
    };

    var UserManager = function (serv, auth) {
        if (auth.username) {
            this.server = serv;
            if (!serv.authenticate(auth.username, auth.password)) {
                throw new Error('Unauthorized request for UserManager : ' + stringify(auth.username));
            }
            this.tenant = server.tenantId({
                domain: auth.domain,
                username: auth.username
            });
            var realmService = server.osgiService('org.wso2.carbon.user.core.service.RealmService'),
                realm = realmService.getTenantUserRealm(this.tenant);
            this.manager = realm.getUserStoreManager();
            this.authorizer = realm.getAuthorizationManager();
        } else {
            throw new Error('Unsupported authentication mechanism : ' + stringify(auth.username));
        }
    };
    user.UserManager = UserManager;

    UserManager.prototype.getUser = function (username) {
        if (!this.manager.isExistingUser(username)) {
            return null;
        }
        return new user.User(this, username);
    };

    UserManager.prototype.addUser = function (username, password, roles, claims, profile) {
        this.manager.addUser(username, password, roles || [], claims || null, profile);
    };

    UserManager.prototype.removeUser = function (username) {
        this.manager.deleteUser(username);
    };

    UserManager.prototype.isUserExists = function (username) {
        return this.manager.isExistingUser(username);
    };

    UserManager.prototype.isRoleExists = function (role) {
        return this.manager.isExistingRole(role);
    };

    UserManager.prototype.getClaims = function (username) {
        return this.manager.getUserClaimValues(username);
    };

    UserManager.prototype.setClaims = function (username, claims, profile) {
        return this.manager.setUserClaimValues(username, claims, profile);
    };

    UserManager.prototype.isAuthorized = function (role, permission, action) {
        return this.authorizer.isRoleAuthorized(role, permission, action);
    };

    UserManager.prototype.addRole = function (role, users, permissions) {
        var perms = [],
            Permission = Packages.org.wso2.carbon.user.api.Permission;
        processPerms(permissions, function (id, action) {
            perms.push(new Permission(id, action));
        });
        this.manager['addRole(java.lang.String,java.lang.String[],org.wso2.carbon.user.api.Permission[])']
            (role, users, perms);
    };

    UserManager.prototype.removeRole = function (role) {
        this.manager.deleteRole(role);
    };

    UserManager.prototype.authorizeRole = function (role, permission, action) {
        var that = this;
        if (permission instanceof String || typeof permission === 'string') {
            if (!that.isAuthorized(role, permission, action)) {
                that.authorizer.authorizeRole(role, permission, action);
            }
        } else {
            processPerms(permission, function (id, action) {
                if (!that.isAuthorized(role, id, action)) {
                    that.authorizer.authorizeRole(role, id, action);
                }
            });
        }
    };

    UserManager.prototype.denyRole = function (role, permission, action) {
        var deny = this.authorizer.denyRole;
        if (permission instanceof String || typeof permission === 'string') {
            deny(role, permission, action);
        } else {
            processPerms(permission, function (id, action) {
                deny(role, id, action);
            });
        }
    };

}(server, user));<commit_msg>renaming UserManager method signatures<commit_after>(function (server, user) {

    var processPerms = function (perms, fn) {
        var perm, actions, i, length;
        for (perm in perms) {
            if (perms.hasOwnProperty(perm)) {
                actions = perms[perm];
                length = actions.length;
                for (i = 0; i < length; i++) {
                    fn(perm, actions[i]);
                }
            }
        }
    };

    var UserManager = function (serv, auth) {
        if (auth.username) {
            this.server = serv;
            if (!serv.authenticate(auth.username, auth.password)) {
                throw new Error('Unauthorized request for UserManager : ' + stringify(auth.username));
            }
            this.tenant = server.tenantId({
                domain: auth.domain,
                username: auth.username
            });
            var realmService = server.osgiService('org.wso2.carbon.user.core.service.RealmService'),
                realm = realmService.getTenantUserRealm(this.tenant);
            this.manager = realm.getUserStoreManager();
            this.authorizer = realm.getAuthorizationManager();
        } else {
            throw new Error('Unsupported authentication mechanism : ' + stringify(auth.username));
        }
    };
    user.UserManager = UserManager;

    UserManager.prototype.getUser = function (username) {
        if (!this.manager.isExistingUser(username)) {
            return null;
        }
        return new user.User(this, username);
    };

    UserManager.prototype.addUser = function (username, password, roles, claims, profile) {
        this.manager.addUser(username, password, roles || [], claims || null, profile);
    };

    UserManager.prototype.removeUser = function (username) {
        this.manager.deleteUser(username);
    };

    UserManager.prototype.userExists = function (username) {
        return this.manager.isExistingUser(username);
    };

    UserManager.prototype.roleExists = function (role) {
        return this.manager.isExistingRole(role);
    };

    UserManager.prototype.getClaims = function (username) {
        return this.manager.getUserClaimValues(username);
    };

    UserManager.prototype.setClaims = function (username, claims, profile) {
        return this.manager.setUserClaimValues(username, claims, profile);
    };

    UserManager.prototype.isAuthorized = function (role, permission, action) {
        return this.authorizer.isRoleAuthorized(role, permission, action);
    };

    UserManager.prototype.addRole = function (role, users, permissions) {
        var perms = [],
            Permission = Packages.org.wso2.carbon.user.api.Permission;
        processPerms(permissions, function (id, action) {
            perms.push(new Permission(id, action));
        });
        this.manager['addRole(java.lang.String,java.lang.String[],org.wso2.carbon.user.api.Permission[])']
            (role, users, perms);
    };

    UserManager.prototype.removeRole = function (role) {
        this.manager.deleteRole(role);
    };

    UserManager.prototype.authorizeRole = function (role, permission, action) {
        var that = this;
        if (permission instanceof String || typeof permission === 'string') {
            if (!that.isAuthorized(role, permission, action)) {
                that.authorizer.authorizeRole(role, permission, action);
            }
        } else {
            processPerms(permission, function (id, action) {
                if (!that.isAuthorized(role, id, action)) {
                    that.authorizer.authorizeRole(role, id, action);
                }
            });
        }
    };

    UserManager.prototype.denyRole = function (role, permission, action) {
        var deny = this.authorizer.denyRole;
        if (permission instanceof String || typeof permission === 'string') {
            deny(role, permission, action);
        } else {
            processPerms(permission, function (id, action) {
                deny(role, id, action);
            });
        }
    };

}(server, user));<|endoftext|>


<commit_before>/**
 * TimezZ - with this plugin you can easily make a stopwatch or timer.
 *
 * @author Valery Strelets
 * @see https://github.com/BrooonS/TimezZ
 * @license https://github.com/BrooonS/timezz/blob/master/LICENSE
 */

import { version } from './package.json';

const ONE_SECOND = 1000;
const ONE_MINUTE = ONE_SECOND * 60;
const ONE_HOUR = ONE_MINUTE * 60;
const ONE_DAY = ONE_HOUR * 24;

export default class TimezZ {
  constructor(selector, userSettings = {}) {
    this.VERSION = version;
    this.elements = Array.from(document.querySelectorAll(selector));

    this.validateDate(userSettings.date);
    this.validateElements(this.elements);

    this.settings = {
      date: userSettings.date,
      isStopped: userSettings.isStopped || false,
      canContinue: userSettings.canContinue || false,
      template: userSettings.template || 'NUMBERLETTER ',
      beforeCreate: userSettings.beforeCreate || (() => {}),
      beforeDestroy: userSettings.beforeDestroy || (() => {}),
      update: userSettings.update || (() => {}),
    };

    if (typeof this.settings?.beforeCreate === 'function') {
      this.settings.beforeCreate();
    }

    this.initTimer();
  }

  initTimer() {
    const calculateTemplate = (math) => {
      const fixNumber = (number) => (number >= 10 ? `${number}` : `0${number}`);

      return fixNumber(Math.floor(Math.abs(math)));
    };

    const countDate = new Date(this.settings.date).getTime();
    const currentTime = new Date().getTime();
    const distance = countDate - currentTime;
    const canContinue = this.settings.canContinue || distance > 0;

    const countDays = calculateTemplate(distance / ONE_DAY);
    const countHours = calculateTemplate((distance % ONE_DAY) / ONE_HOUR);
    const countMinutes = calculateTemplate((distance % ONE_HOUR) / ONE_MINUTE);
    const countSeconds = calculateTemplate((distance % ONE_MINUTE) / ONE_SECOND);

    this.elements.forEach((element, index) => {
      this.elements[index].innerHTML = (
        this.formatHTML(canContinue ? countDays : '0', 'days')
        + this.formatHTML(canContinue ? countHours : '0', 'hours')
        + this.formatHTML(canContinue ? countMinutes : '0', 'minutes')
        + this.formatHTML(canContinue ? countSeconds : '0', 'seconds')
      );
    });

    if (!this.settings.isStopped && canContinue) {
      this.timeout = setTimeout(this.initTimer.bind(this), ONE_SECOND);
    }
  }

  formatHTML(number, letter) {
    const replace = (string) => string
      .replace(/NUMBER/g, number)
      .replace(/LETTER/g, letter);

    if (!this.settings) {
      return '';
    }

    if (typeof this.settings.template === 'string') {
      return replace(this.settings.template);
    }

    if (typeof this.settings.template === 'object') {
      return Object.keys(this.settings.template)
        .reduce((acc, key) => acc + replace(this.settings?.template[key]), '');
    }

    return '';
  }

  validateDate = (date) => {
    if (Number.isNaN(new Date(date).getTime())) {
      throw new Error('[TimezZ]: Date isn\'t valid. Check documentation for more info. https://github.com/BrooonS/timezz');
    }
  }

  validateElements = (elements) => {
    if (elements.length === 0) {
      throw new Error('[TimezZ]: Selector elements not found. Check documentation for more info. https://github.com/BrooonS/timezz');
    }
  }

  destroy() {
    if (this.settings && typeof this.settings.beforeDestroy === 'function') {
      this.settings.beforeDestroy();
    }

    if (this.timeout) {
      clearTimeout(this.timeout);
    }
    this.elements.forEach((element, index) => {
      this.elements[index].innerHTML = '';
    });
    this.settings = null;
    this.elements = [];
  }
}
<commit_msg>add update<commit_after>/**
 * TimezZ - with this plugin you can easily make a stopwatch or timer.
 *
 * @author Valery Strelets
 * @see https://github.com/BrooonS/TimezZ
 * @license https://github.com/BrooonS/timezz/blob/master/LICENSE
 */

import { version } from './package.json';

const ONE_SECOND = 1000;
const ONE_MINUTE = ONE_SECOND * 60;
const ONE_HOUR = ONE_MINUTE * 60;
const ONE_DAY = ONE_HOUR * 24;

export default class TimezZ {
  constructor(selector, userSettings = {}) {
    this.VERSION = version;
    this.elements = Array.from(document.querySelectorAll(selector));

    this.validateDate(userSettings.date);
    this.validateElements(this.elements);

    this.settings = {
      date: userSettings.date,
      isStopped: userSettings.isStopped || false,
      canContinue: userSettings.canContinue || false,
      template: userSettings.template || 'NUMBERLETTER ',
      beforeCreate: userSettings.beforeCreate || null,
      beforeDestroy: userSettings.beforeDestroy || null,
      update: userSettings.update || null,
    };

    if (typeof this.settings?.beforeCreate === 'function') {
      this.settings.beforeCreate();
    }

    this.initTimer();
  }

  initTimer() {
    const calculateTemplate = (math) => {
      const fixNumber = (number) => (number >= 10 ? `${number}` : `0${number}`);

      return fixNumber(Math.floor(Math.abs(math)));
    };

    const countDate = new Date(this.settings.date).getTime();
    const currentTime = new Date().getTime();
    const distance = countDate - currentTime;
    const canContinue = this.settings.canContinue || distance > 0;

    const countDays = calculateTemplate(distance / ONE_DAY);
    const countHours = calculateTemplate((distance % ONE_DAY) / ONE_HOUR);
    const countMinutes = calculateTemplate((distance % ONE_HOUR) / ONE_MINUTE);
    const countSeconds = calculateTemplate((distance % ONE_MINUTE) / ONE_SECOND);

    if (typeof this.settings.update === 'function') {
      this.settings.update({ distance });
    }

    this.elements.forEach((element, index) => {
      this.elements[index].innerHTML = (
        this.formatHTML(canContinue ? countDays : '0', 'days')
        + this.formatHTML(canContinue ? countHours : '0', 'hours')
        + this.formatHTML(canContinue ? countMinutes : '0', 'minutes')
        + this.formatHTML(canContinue ? countSeconds : '0', 'seconds')
      );
    });

    if (!this.settings.isStopped && canContinue) {
      this.timeout = setTimeout(this.initTimer.bind(this), ONE_SECOND);
    }
  }

  formatHTML(number, letter) {
    const replace = (string) => string
      .replace(/NUMBER/g, number)
      .replace(/LETTER/g, letter);

    if (!this.settings) {
      return '';
    }

    if (typeof this.settings.template === 'string') {
      return replace(this.settings.template);
    }

    if (typeof this.settings.template === 'object') {
      return Object.keys(this.settings.template)
        .reduce((acc, key) => acc + replace(this.settings?.template[key]), '');
    }

    return '';
  }

  validateDate = (date) => {
    if (Number.isNaN(new Date(date).getTime())) {
      throw new Error('[TimezZ]: Date isn\'t valid. Check documentation for more info. https://github.com/BrooonS/timezz');
    }
  }

  validateElements = (elements) => {
    if (elements.length === 0) {
      throw new Error('[TimezZ]: Selector elements not found. Check documentation for more info. https://github.com/BrooonS/timezz');
    }
  }

  destroy() {
    if (this.settings && typeof this.settings.beforeDestroy === 'function') {
      this.settings.beforeDestroy();
    }

    if (this.timeout) {
      clearTimeout(this.timeout);
    }
    this.elements.forEach((element, index) => {
      this.elements[index].innerHTML = '';
    });
    this.settings = null;
    this.elements = [];
  }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013 LabKey Corporation
 *
 * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0
 */
Ext4.ns('EHR.Ext3Utils');

EHR.Ext3Utils = new function(){
    return {
        /**
         * A utility that will load a EHR form template based on the title and storeId.  These correspond to records in ehr.formtemplates.
         * @param {string} title The title of the template
         * @param {string} storeId The storeId associated with the template
         */
        loadTemplateByName: function(title, storeId){
            LABKEY.Query.selectRows({
                schemaName: 'ehr',
                queryName: 'formtemplates',
                filterArray: [
                    LABKEY.Filter.create('title', title, LABKEY.Filter.Types.EQUAL),
                    LABKEY.Filter.create('storeId', storeId, LABKEY.Filter.Types.EQUAL)
                ],
                success: onLoadTemplate
            });

            function onLoadTemplate(data){
                if(!data || !data.rows.length)
                    return;

                EHR.Utils.loadTemplate(data.rows[0].entityid)
            }
        },

        /**
         * A utility that will load a EHR form template based on the templateId.  These correspond to records in ehr.formtemplates.
         * @param {string} templateId The templateId, which is the GUID of the corresponding record in ehr.formtemplates
         */
        loadTemplate: function(templateId){
            if(!templateId)
                return;

            LABKEY.Query.selectRows({
                schemaName: 'ehr',
                queryName: 'formtemplaterecords',
                filterArray: [LABKEY.Filter.create('templateId', templateId, LABKEY.Filter.Types.EQUAL)],
                sort: '-rowid',
                success: onLoadTemplate,
                scope: this
            });

            Ext.Msg.wait("Loading Template...");

            function onLoadTemplate(data){
                if(!data || !data.rows.length){
                    Ext.Msg.hide();
                    return;
                }

                var toAdd = {};

                Ext.each(data.rows, function(row){
                    var data = Ext.decode(row.json);
                    var store = Ext.StoreMgr.get(row.storeid);

                    //verify store exists
                    if(!store){
                        Ext.StoreMgr.on('add', function(){
                            onLoadTemplate(data);
                        }, this, {single: true, delay: 200});
                        return false;
                    };

                    //also verify it is loaded
                    if(!store.fields || !store.fields.length){
                        store.on('load', function(){
                            onLoadTemplate(data);
                        }, this, {single: true, delay: 200});
                        return false;
                    };

                    if(!toAdd[store.storeId])
                        toAdd[store.storeId] = [];

                    toAdd[store.storeId].push(data);
                });

                for (var i in toAdd){
                    var store = Ext.StoreMgr.get(i);
                    toAdd[i].reverse();
                    var recs = store.addRecords(toAdd[i])
                }

                Ext.Msg.hide();
            }
        },

        /**
         * A utility that will create a variant of EHR.ext.ImportPanel based on a supplied config.
         * This is used by the data entry page to create the appropriate panel based on records from ehr.formtypes
         * @param {object} config The configuration object.  Can contain any properties used by EHR.ext.ImportPanel in addition to the ones below.
         * @param {string} [config.formType] The formType to create, which should correspond to a value in ehr.formtypes.  However, if it does not match a known FormType, it will assume this is a SimpleTask (ie. Task consisting of only one query) and the FormType will be used as the queryName.
         * @param {string} [config.formUUID] The GUID to use when creating this form.  If creating a new form (as opposed to loading an existing one) this should be left blank.
         * @param {string} [config.panelType] The type of ImportPanel to create.  Should correspond to a class under EHR.ext.ImportPanel (ie. TaskPanel or TaskDetailsPanel)
         *
         */
        createImportPanel: function(config){
            var multi = new LABKEY.MultiRequest();

            var formSections;
            multi.add(LABKEY.Query.selectRows, {
                schemaName: 'ehr',
                queryName: 'formpanelsections',
                filterArray: [LABKEY.Filter.create('formType', config.formType, LABKEY.Filter.Types.EQUAL)],
                sort: 'destination,sort_order',
                scope: this,
                successCallback: function(results){
                    formSections = results.rows;
                },
                failure: EHR.Utils.onError
            });

            var formConfig;
            multi.add(LABKEY.Query.selectRows, {
                schemaName: 'ehr',
                queryName: 'formtypes',
                filterArray: [LABKEY.Filter.create('formType', config.formType, LABKEY.Filter.Types.EQUAL)],
                scope: this,
                successCallback: function(results){
                    if(results.rows.length)
                        formConfig = results.rows[0];
                    else
                        formConfig = {};
                },
                failure: EHR.Utils.onError
            });
            multi.send(onSuccess, this);

            function onSuccess(){
                if(!formSections.length){
                    //we assume this is a simple query:
                    config.queryName = config.formType;
                    config.schemaName = 'study';
                    if(config.panelType=='TaskPanel')
                        EHR.Ext3Utils.createSimpleTaskPanel(config);
                    else if (config.panelType=='TaskDetailsPanel')
                        EHR.Ext3Utils.createSimpleTaskDetailsPanel(config);
                    else
                        alert('Form type not found');
                    return;
                }

                var panelCfg = formConfig.configjson ? Ext.util.JSON.decode(formConfig.configjson) : {};
                panelCfg = Ext.apply(panelCfg, config);

                Ext.applyIf(panelCfg, {
                    title: config.formType,
                    formHeaders: [],
                    formSections: [],
                    formTabs: []
                });

                Ext.each(formSections, function(row){
                    var metaSources;
                    if(row.metadatasources)
                        metaSources = row.metadatasources.split(',');

                    var obj = {
                        xtype: row.xtype,
                        schemaName: row.schemaName,
                        queryName: row.queryName,
                        title: row.title || row.queryName,
                        metadata: EHR.Metadata.getTableMetadata(row.queryName, metaSources)
                    };

                    if(row.buttons)
                        obj.tbarBtns = row.buttons.split(',');

                    if(row.initialTemplates && !config.formUUID){
                        panelCfg.initialTemplates = panelCfg.initialTemplates || [];
                        var templates = row.initialTemplates.split(',');
                        var storeId;
                        Ext.each(templates, function(t){
                            storeId = [row.schemaName, row.queryName, '', ''].join('||');
                            panelCfg.initialTemplates.push({storeId: row.storeId, title: t});
                        }, this);

                    }

                    if(row.configJson){
                        var json = Ext.util.JSON.decode(row.configJson);
                        Ext.apply(obj, json);
                    }

                    if(config.noTabs && row.destination == 'formTabs')
                        panelCfg['formSections'].push(obj);
                    else
                        panelCfg[row.destination].push(obj);
                }, this);

                return new EHR.ext.ImportPanel[config.panelType](panelCfg);
            }

        },

        /**
         * A utility that will create an EHR.ext.ImportPanel.TaskPanel containing only a single section.
         * This is a special case of ImportPanel, because there does not need to be a record in ehr.formtypes describing the panel sections.
         * @param {object} config The configuration object.  Can contain any properties used by EHR.ext.ImportPanel in addition to the ones below.
         * @param {string} [config.queryName] The queryName to load in the panel's single section.
         * @param {string} [config.schemaName] The schemaName to load in the panel's single section.
         *
         */
        createSimpleTaskPanel: function(config){
            if(!config || !config.queryName){
                alert('Must provide queryName');
                return;
            }

            var panelCfg = Ext.apply({}, config);
            Ext.apply(panelCfg, {
                title: config.queryName,
                formHeaders: [{xtype: 'ehr-abstractpanel'}],
                formSections: [{
                    xtype: 'ehr-gridformpanel',
                    schemaName: config.schemaName,
                    queryName: config.queryName,
                    title: config.title || config.queryName,
                    viewName:  '~~UPDATE~~',
                    columns: EHR.Metadata.Columns[config.queryName],
                    metadata: EHR.Metadata.getTableMetadata(config.queryName, ['Task'])
                }],
                formTabs: []
            });

            return new EHR.ext.ImportPanel.TaskPanel(panelCfg);
        },

        /**
         * A utility that will create an EHR.ext.ImportPanel.TaskDetailsPanel containing only a single section.
         * This is a special case of ImportPanel, because there does not need to be a record in ehr.formtypes describing the panel sections.
         * @param {object} config The configuration object.  Can contain any properties used by EHR.ext.ImportPanel in addition to the ones below.
         * @param {string} [config.queryName] The queryName to load in the panel's single section.
         * @param {string} [config.schemaName] The schemaName to load in the panel's single section.
         *
         */
        createSimpleTaskDetailsPanel: function(config){
            if(!config || !config.queryName){
                alert('Must provide queryName');
                return;
            }

            var panelCfg = Ext.apply({}, config);
            Ext.apply(panelCfg, {
                title: config.queryName,
                formSections: [{
                    xtype: 'ehr-gridformpanel',
                    schemaName: config.schemaName,
                    queryName: config.queryName,
                    readOnly: true,
                    title: config.title || config.queryName,
                    viewName: '~~UPDATE~~',
                    columns: EHR.Metadata.Columns[config.queryName],
                    metadata: EHR.Metadata.getTableMetadata(config.queryName, ['Task'])
                }],
                formTabs: []
            });

            return new EHR.ext.ImportPanel.TaskDetailsPanel(panelCfg);
        }
    }
}<commit_msg>Ticket 38440: Dropdown menus cut off in taskDetails view<commit_after>/*
 * Copyright (c) 2013 LabKey Corporation
 *
 * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0
 */
Ext4.ns('EHR.Ext3Utils');

EHR.Ext3Utils = new function(){
    return {
        /**
         * A utility that will load a EHR form template based on the title and storeId.  These correspond to records in ehr.formtemplates.
         * @param {string} title The title of the template
         * @param {string} storeId The storeId associated with the template
         */
        loadTemplateByName: function(title, storeId){
            LABKEY.Query.selectRows({
                schemaName: 'ehr',
                queryName: 'formtemplates',
                filterArray: [
                    LABKEY.Filter.create('title', title, LABKEY.Filter.Types.EQUAL),
                    LABKEY.Filter.create('storeId', storeId, LABKEY.Filter.Types.EQUAL)
                ],
                success: onLoadTemplate
            });

            function onLoadTemplate(data){
                if(!data || !data.rows.length)
                    return;

                EHR.Utils.loadTemplate(data.rows[0].entityid)
            }
        },

        /**
         * A utility that will load a EHR form template based on the templateId.  These correspond to records in ehr.formtemplates.
         * @param {string} templateId The templateId, which is the GUID of the corresponding record in ehr.formtemplates
         */
        loadTemplate: function(templateId){
            if(!templateId)
                return;

            LABKEY.Query.selectRows({
                schemaName: 'ehr',
                queryName: 'formtemplaterecords',
                filterArray: [LABKEY.Filter.create('templateId', templateId, LABKEY.Filter.Types.EQUAL)],
                sort: '-rowid',
                success: onLoadTemplate,
                scope: this
            });

            Ext.Msg.wait("Loading Template...");

            function onLoadTemplate(data){
                if(!data || !data.rows.length){
                    Ext.Msg.hide();
                    return;
                }

                var toAdd = {};

                Ext.each(data.rows, function(row){
                    var data = Ext.decode(row.json);
                    var store = Ext.StoreMgr.get(row.storeid);

                    //verify store exists
                    if(!store){
                        Ext.StoreMgr.on('add', function(){
                            onLoadTemplate(data);
                        }, this, {single: true, delay: 200});
                        return false;
                    };

                    //also verify it is loaded
                    if(!store.fields || !store.fields.length){
                        store.on('load', function(){
                            onLoadTemplate(data);
                        }, this, {single: true, delay: 200});
                        return false;
                    };

                    if(!toAdd[store.storeId])
                        toAdd[store.storeId] = [];

                    toAdd[store.storeId].push(data);
                });

                for (var i in toAdd){
                    var store = Ext.StoreMgr.get(i);
                    toAdd[i].reverse();
                    var recs = store.addRecords(toAdd[i])
                }

                Ext.Msg.hide();
            }
        },

        /**
         * A utility that will create a variant of EHR.ext.ImportPanel based on a supplied config.
         * This is used by the data entry page to create the appropriate panel based on records from ehr.formtypes
         * @param {object} config The configuration object.  Can contain any properties used by EHR.ext.ImportPanel in addition to the ones below.
         * @param {string} [config.formType] The formType to create, which should correspond to a value in ehr.formtypes.  However, if it does not match a known FormType, it will assume this is a SimpleTask (ie. Task consisting of only one query) and the FormType will be used as the queryName.
         * @param {string} [config.formUUID] The GUID to use when creating this form.  If creating a new form (as opposed to loading an existing one) this should be left blank.
         * @param {string} [config.panelType] The type of ImportPanel to create.  Should correspond to a class under EHR.ext.ImportPanel (ie. TaskPanel or TaskDetailsPanel)
         *
         */
        createImportPanel: function(config){
            var multi = new LABKEY.MultiRequest();

            var formSections;
            multi.add(LABKEY.Query.selectRows, {
                schemaName: 'ehr',
                queryName: 'formpanelsections',
                filterArray: [LABKEY.Filter.create('formType', config.formType, LABKEY.Filter.Types.EQUAL)],
                sort: 'destination,sort_order',
                scope: this,
                successCallback: function(results){
                    formSections = results.rows;
                },
                failure: EHR.Utils.onError
            });

            var formConfig;
            multi.add(LABKEY.Query.selectRows, {
                schemaName: 'ehr',
                queryName: 'formtypes',
                filterArray: [LABKEY.Filter.create('formType', config.formType, LABKEY.Filter.Types.EQUAL)],
                scope: this,
                successCallback: function(results){
                    if(results.rows.length)
                        formConfig = results.rows[0];
                    else
                        formConfig = {};
                },
                failure: EHR.Utils.onError
            });
            multi.send(onSuccess, this);

            function onSuccess(){
                if(!formSections.length){
                    //we assume this is a simple query:
                    config.queryName = config.formType;
                    config.schemaName = 'study';
                    if(config.panelType=='TaskPanel')
                        EHR.Ext3Utils.createSimpleTaskPanel(config);
                    else if (config.panelType=='TaskDetailsPanel')
                        EHR.Ext3Utils.createSimpleTaskDetailsPanel(config);
                    else
                        alert('Form type not found');
                    return;
                }

                var panelCfg = formConfig.configjson ? Ext.util.JSON.decode(formConfig.configjson) : {};
                panelCfg = Ext.apply(panelCfg, config);

                Ext.applyIf(panelCfg, {
                    title: config.formType,
                    formHeaders: [],
                    formSections: [],
                    formTabs: []
                });

                Ext.each(formSections, function(row){
                    var metaSources;
                    if(row.metadatasources)
                        metaSources = row.metadatasources.split(',');

                    var obj = {
                        xtype: row.xtype,
                        schemaName: row.schemaName,
                        queryName: row.queryName,
                        title: row.title || row.queryName,
                        metadata: EHR.Metadata.getTableMetadata(row.queryName, metaSources)
                    };

                    if(row.buttons)
                        obj.tbarBtns = row.buttons.split(',');

                    if(row.initialTemplates && !config.formUUID){
                        panelCfg.initialTemplates = panelCfg.initialTemplates || [];
                        var templates = row.initialTemplates.split(',');
                        var storeId;
                        Ext.each(templates, function(t){
                            storeId = [row.schemaName, row.queryName, '', ''].join('||');
                            panelCfg.initialTemplates.push({storeId: row.storeId, title: t});
                        }, this);

                    }

                    if(row.configJson){
                        var json = Ext.util.JSON.decode(row.configJson);
                        Ext.apply(obj, json);
                    }

                    if(config.noTabs && row.destination == 'formTabs')
                        panelCfg['formSections'].push(obj);
                    else
                        panelCfg[row.destination].push(obj);
                }, this);

                if (panelCfg.panelType === 'TaskDetailsPanel' && panelCfg.readOnly) {
                    // Avoid creating ExtJS3 panel-wrapped QueryWebParts - just add them directly to the DOM via
                    // the JavaScript API. See ticket 38440
                    var index = 0;
                    index = this.addQueryWebParts(panelCfg.formHeaders, panelCfg, index);
                    index = this.addQueryWebParts(panelCfg.formSections, panelCfg, index);
                }
                else {
                    return new EHR.ext.ImportPanel[config.panelType](panelCfg);
                }
            }

        },

        addQueryWebParts: function(sections, panelCfg, index) {
            var rootElement = Ext.get(panelCfg.renderTo);
            Ext.each(sections, function(section){
                if (section.schemaName && section.queryName) {
                    var targetId = panelCfg.renderTo + index;
                    rootElement.createChild({id: targetId, tag: 'div'});
                    var qwpConfig = {
                        schemaName: section.schemaName,
                        queryName: section.queryName,
                        filters: [LABKEY.Filter.create('taskId', panelCfg.formUUID, LABKEY.Filter.Types.EQUAL)],
                        allowChooseQuery: false,
                        allowChooseView: true,
                        showRecordSelectors: true,
                        showDetailsColumn: false,
                        showDeleteButton: false,
                        timeout: 0,
                        linkTarget: '_blank',
                        renderTo: targetId,
                        failure: EHR.Utils.onError,
                        scope: this
                    };
                    var qwp = new LABKEY.QueryWebPart(qwpConfig);
                    index++;
                }

            }, this);
            return index;
        },

        /**
         * A utility that will create an EHR.ext.ImportPanel.TaskPanel containing only a single section.
         * This is a special case of ImportPanel, because there does not need to be a record in ehr.formtypes describing the panel sections.
         * @param {object} config The configuration object.  Can contain any properties used by EHR.ext.ImportPanel in addition to the ones below.
         * @param {string} [config.queryName] The queryName to load in the panel's single section.
         * @param {string} [config.schemaName] The schemaName to load in the panel's single section.
         *
         */
        createSimpleTaskPanel: function(config){
            if(!config || !config.queryName){
                alert('Must provide queryName');
                return;
            }

            var panelCfg = Ext.apply({}, config);
            Ext.apply(panelCfg, {
                title: config.queryName,
                formHeaders: [{xtype: 'ehr-abstractpanel'}],
                formSections: [{
                    xtype: 'ehr-gridformpanel',
                    schemaName: config.schemaName,
                    queryName: config.queryName,
                    title: config.title || config.queryName,
                    viewName:  '~~UPDATE~~',
                    columns: EHR.Metadata.Columns[config.queryName],
                    metadata: EHR.Metadata.getTableMetadata(config.queryName, ['Task'])
                }],
                formTabs: []
            });

            return new EHR.ext.ImportPanel.TaskPanel(panelCfg);
        },

        /**
         * A utility that will create an EHR.ext.ImportPanel.TaskDetailsPanel containing only a single section.
         * This is a special case of ImportPanel, because there does not need to be a record in ehr.formtypes describing the panel sections.
         * @param {object} config The configuration object.  Can contain any properties used by EHR.ext.ImportPanel in addition to the ones below.
         * @param {string} [config.queryName] The queryName to load in the panel's single section.
         * @param {string} [config.schemaName] The schemaName to load in the panel's single section.
         *
         */
        createSimpleTaskDetailsPanel: function(config){
            if(!config || !config.queryName){
                alert('Must provide queryName');
                return;
            }

            var panelCfg = Ext.apply({}, config);
            Ext.apply(panelCfg, {
                title: config.queryName,
                formSections: [{
                    xtype: 'ehr-gridformpanel',
                    schemaName: config.schemaName,
                    queryName: config.queryName,
                    readOnly: true,
                    title: config.title || config.queryName,
                    viewName: '~~UPDATE~~',
                    columns: EHR.Metadata.Columns[config.queryName],
                    metadata: EHR.Metadata.getTableMetadata(config.queryName, ['Task'])
                }],
                formTabs: []
            });

            return new EHR.ext.ImportPanel.TaskDetailsPanel(panelCfg);
        }
    }
}<|endoftext|>