<commit_before>/**
 * Copyright 2013-2017 the original author or authors from the JHipster project.
 *
 * This file is part of the JHipster project, see https://jhipster.github.io/
 * for more information.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
const util = require('util');
const shelljs = require('shelljs');
const generator = require('yeoman-generator');
const chalk = require('chalk');
const jhiCore = require('jhipster-core');
const BaseGenerator = require('../generator-base');

const JDLGenerator = generator.extend({});

util.inherits(JDLGenerator, BaseGenerator);

module.exports = JDLGenerator.extend({
    constructor: function (...args) { // eslint-disable-line object-shorthand
        generator.apply(this, args);
        this.argument('jdlFiles', { type: Array, required: true });
        this.jdlFiles = this.options.jdlFiles;
    },

    initializing: {
        validate() {
            if (this.jdlFiles) {
                this.jdlFiles.forEach((key) => {
                    if (!shelljs.test('-f', key)) {
                        this.env.error(chalk.red(`\nCould not find ${key}, make sure the path is correct!\n`));
                    }
                });
            }
        },

        getConfig() {
            this.baseName = this.config.get('baseName');
            this.prodDatabaseType = this.config.get('prodDatabaseType');
            this.skipClient = this.config.get('skipClient');
            this.clientFramework = this.config.get('clientFramework');
            if (!this.clientFramework) {
                this.clientFramework = 'angular1';
            }
            this.clientPackageManager = this.config.get('clientPackageManager');
            if (!this.clientPackageManager) {
                if (this.useYarn) {
                    this.clientPackageManager = 'yarn';
                } else {
                    this.clientPackageManager = 'npm';
                }
            }
        }
    },

    default: {
        insight() {
            const insight = this.insight();
            insight.trackWithEvent('generator', 'import-jdl');
        },

        parseJDL() {
            this.log('The jdl is being parsed.');
            try {
                const jdlObject = jhiCore.convertToJDL(jhiCore.parseFromFiles(this.jdlFiles), this.prodDatabaseType);
                const entities = jhiCore.convertToJHipsterJSON({
                    jdlObject,
                    databaseType: this.prodDatabaseType
                });
                this.log('Writing entity JSON files.');
                jhiCore.exportToJSON(entities, this.options.force);
            } catch (e) {
                this.log(e);
                this.error('\nError while parsing entities from JDL\n');
            }
        },

        generateEntities() {
            this.log('Generating entities.');
            try {
                this.getExistingEntities().forEach((entity) => {
                    this.composeWith(require.resolve('../entity'), {
                        regenerate: true,
                        'skip-install': true,
                        'skip-client': entity.definition.skipClient,
                        'skip-server': entity.definition.skipServer,
                        'no-fluent-methods': entity.definition.noFluentMethod,
                        'skip-user-management': entity.definition.skipUserManagement,
                        arguments: [entity.name],
                    });
                });
            } catch (e) {
                this.error(`Error while generating entities from parsed JDL\n${e}`);
            }
        }
    },

    install() {
        const injectJsFilesToIndex = () => {
            this.log(`\n${chalk.bold.green('Running gulp Inject to add javascript to index\n')}`);
            this.spawnCommand('gulp', ['inject:app']);
        };
        // rebuild client for Angular
        const rebuildClient = () => {
            this.log(`\n${chalk.bold.green('Running `webpack:build:dev` to update client app')}\n`);
            this.spawnCommand(this.clientPackageManager, ['run', 'webpack:build:dev']);
        };

        if (!this.options['skip-install'] && !this.skipClient) {
            if (this.clientFramework === 'angular1') {
                injectJsFilesToIndex();
            } else {
                rebuildClient();
            }
        }
    }
});
<commit_msg>Fixed #5191<commit_after>/**
 * Copyright 2013-2017 the original author or authors from the JHipster project.
 *
 * This file is part of the JHipster project, see https://jhipster.github.io/
 * for more information.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
const util = require('util');
const shelljs = require('shelljs');
const generator = require('yeoman-generator');
const chalk = require('chalk');
const jhiCore = require('jhipster-core');
const BaseGenerator = require('../generator-base');

const JDLGenerator = generator.extend({});

util.inherits(JDLGenerator, BaseGenerator);

module.exports = JDLGenerator.extend({
    constructor: function (...args) { // eslint-disable-line object-shorthand
        generator.apply(this, args);
        this.argument('jdlFiles', { type: Array, required: true });
        this.jdlFiles = this.options.jdlFiles;
    },

    initializing: {
        validate() {
            if (this.jdlFiles) {
                this.jdlFiles.forEach((key) => {
                    if (!shelljs.test('-f', key)) {
                        this.env.error(chalk.red(`\nCould not find ${key}, make sure the path is correct!\n`));
                    }
                });
            }
        },

        getConfig() {
            this.applicationType = this.config.get('applicationType');
            this.baseName = this.config.get('baseName');
            this.prodDatabaseType = this.config.get('prodDatabaseType');
            this.skipClient = this.config.get('skipClient');
            this.clientFramework = this.config.get('clientFramework');
            if (!this.clientFramework) {
                this.clientFramework = 'angular1';
            }
            this.clientPackageManager = this.config.get('clientPackageManager');
            if (!this.clientPackageManager) {
                if (this.useYarn) {
                    this.clientPackageManager = 'yarn';
                } else {
                    this.clientPackageManager = 'npm';
                }
            }
        }
    },

    default: {
        insight() {
            const insight = this.insight();
            insight.trackWithEvent('generator', 'import-jdl');
        },

        parseJDL() {
            this.log('The jdl is being parsed.');
            try {
                const jdlObject = jhiCore.convertToJDL(jhiCore.parseFromFiles(this.jdlFiles), this.prodDatabaseType, this.applicationType);
                const entities = jhiCore.convertToJHipsterJSON({
                    jdlObject,
                    databaseType: this.prodDatabaseType
                });
                this.log('Writing entity JSON files.');
                jhiCore.exportToJSON(entities, this.options.force);
            } catch (e) {
                this.log(e);
                this.error('\nError while parsing entities from JDL\n');
            }
        },

        generateEntities() {
            this.log('Generating entities.');
            try {
                this.getExistingEntities().forEach((entity) => {
                    this.composeWith(require.resolve('../entity'), {
                        regenerate: true,
                        'skip-install': true,
                        'skip-client': entity.definition.skipClient,
                        'skip-server': entity.definition.skipServer,
                        'no-fluent-methods': entity.definition.noFluentMethod,
                        'skip-user-management': entity.definition.skipUserManagement,
                        arguments: [entity.name],
                    });
                });
            } catch (e) {
                this.error(`Error while generating entities from parsed JDL\n${e}`);
            }
        }
    },

    install() {
        const injectJsFilesToIndex = () => {
            this.log(`\n${chalk.bold.green('Running gulp Inject to add javascript to index\n')}`);
            this.spawnCommand('gulp', ['inject:app']);
        };
        // rebuild client for Angular
        const rebuildClient = () => {
            this.log(`\n${chalk.bold.green('Running `webpack:build:dev` to update client app')}\n`);
            this.spawnCommand(this.clientPackageManager, ['run', 'webpack:build:dev']);
        };

        if (!this.options['skip-install'] && !this.skipClient) {
            if (this.clientFramework === 'angular1') {
                injectJsFilesToIndex();
            } else {
                rebuildClient();
            }
        }
    }
});
<|endoftext|>


<commit_before>var DiaporamaFirstOccurence = true;
Diaporama = Class.create({

	fullscreenMode: false,

	initialize: function(div)
	{
		this.element = div;
		this.fullBox = this.element.select('div[id="diaporama_box"]')[0];
		this.nextButton = div.select('a[id="nextButton"]')[0];
		this.previousButton = div.select('a[id="prevButton"]')[0];
		this.closeButton = div.select('a[id="closeButton"]')[0];
		this.downloadButton = div.select('a[id="downloadDiapoButton"]')[0];
		this.playButton = div.select('a[id="playButton"]')[0];
		this.stopButton = div.select('a[id="stopButton"]')[0];
		this.fsButton = div.select('a[id="fsButton"]')[0];
		this.nofsButton = div.select('a[id="nofsButton"]')[0];

		this.actualSizeButton = div.select('img[id="actualSizeButton"]')[0];
		this.fitToScreenButton = div.select('img[id="fitToScreenButton"]')[0];
		this.imgTag = div.select('img[id="mainImage"]')[0];
		this.imgContainer = div.select('div[id="imageContainer"]')[0];
		fitHeightToBottom(this.imgContainer, null, 5);
		this.zoomInput = div.select('input[id="zoomValue"]')[0];
		this.timeInput = div.select('input[id="time"]')[0];
		this.baseUrl = 'content.php?action=image_proxy&file=';
		this.nextButton.onclick = function(){
			this.next();
			this.updateButtons();
			return false;
		}.bind(this);
		this.previousButton.onclick = function(){
			this.previous();
			this.updateButtons();
			return false;
		}.bind(this);
		this.closeButton.onclick = function(){
			if(this.fullscreenMode) this.exitFullScreen();
			this.close();
			hideLightBox(true);
			return false;
		}.bind(this);
		this.downloadButton.onclick = function(){
			if(!this.currentFile) return;
			document.location.href = 'content.php?action=download&file='+this.currentFile;
			return false;
		}.bind(this);
		this.actualSizeButton.onclick = function(){
			this.slider.setValue(100);
			this.resizeImage(true);
		}.bind(this);
		this.fitToScreenButton.onclick = function(){
			this.toggleFitToScreen();
		}.bind(this);
		this.playButton.onclick = function(){
			this.play();
			this.updateButtons();
			return false;
		}.bind(this);
		this.stopButton.onclick = function(){
			this.stop();
			this.updateButtons();
			return false;
		}.bind(this);
		this.fsButton.onclick = function(){
			this.setFullScreen();
			this.fsButton.hide();
			this.nofsButton.show();
		}.bind(this);
		this.nofsButton.onclick = function(){
			this.exitFullScreen();
			this.nofsButton.hide();
			this.fsButton.show();
		}.bind(this);
		modal.setCloseAction(this.close.bind(this));

		this.imgTag.onload = function(){
			this.resizeImage(true);
			this.downloadButton.removeClassName("disabled");
			this.updateModalTitle();
		}.bind(this);
		Event.observe(this.zoomInput, "keypress", function(e){
			if(e == null) e = window.event;
			if(e.keyCode == Event.KEY_RETURN || e.keyCode == Event.KEY_UP || e.keyCode == Event.KEY_DOWN){
				if(e.keyCode == Event.KEY_UP || e.keyCode == Event.KEY_DOWN)
				{
					var crtValue = parseInt(this.zoomInput.value);
					var value = (e.keyCode == Event.KEY_UP?(e.shiftKey?crtValue+10:crtValue+1):(e.shiftKey?crtValue-10:crtValue-1));
					this.zoomInput.value = value;
				}
				this.slider.setValue(this.zoomInput.value);
				this.resizeImage(false);
				Event.stop(e);
			}
			return true;
		}.bind(this));
		this.timeInput.observe('change', function(e){
			if(this.slideShowPlaying && this.pe){
				this.stop();
				this.play();
			}
		}.bind(this));
		this.containerDim = $(this.imgContainer).getDimensions();
	},

	open : function(aFilesList, sCurrentFile)
	{
		var allItems = aFilesList;
		this.items = new Array();
		this.sizes = new Hash();
		$A(allItems).each(function(rowItem){
			if(rowItem.getAttribute('is_image')=='1'){
				this.items.push(rowItem.getAttribute('filename'));
				this.sizes.set(rowItem.getAttribute('filename'),  {height:rowItem.getAttribute('image_height'),
															   width:rowItem.getAttribute('image_width')});
			}
		}.bind(this));

		if(!sCurrentFile && this.items.length) sCurrentFile = this.items[0];
		this.currentFile = sCurrentFile;

		var sliderDiv = this.element.select('div[id="slider-2"]')[0];
		var sliderInput = this.element.select('input[id="slider-input-2"]')[0];
		this.slider = new Slider(sliderDiv, sliderInput);
		this.slider.setMaximum(200);
		this.slider.setMinimum(10);
		this.slider.setValue(100);
		this.zoomInput.value = '100';
		this.slider.recalculate();
		this.slider.onchange = function(){
			this.resizeImage(false);
		}.bind(this);

		this.updateImage();
		this.updateButtons();
		if(DiaporamaFirstOccurence){
			$$(".action_bar a").each(function(el){
				new Effect.Corner(el, "round 8px");
			});
			DiaporamaFirstOccurence = false;
		}
	},

	updateModalTitle : function(){
		var titleDiv = $(modal.dialogTitle);
		var crtTitle = titleDiv.select('span.titleString')[0];
		var filenameSpans = crtTitle.select('span');
		var text = ' - '+getBaseName(this.currentFile) + ' ('+this.sizes.get(this.currentFile).width+' X '+this.sizes.get(this.currentFile).height+')';
		if(filenameSpans.length) filenameSpans[0].innerHTML = text;
		else {
			newSpan = document.createElement('span');
			newSpan.appendChild(document.createTextNode(text));
			crtTitle.appendChild(newSpan);
		}
	},

	resizeImage : function(morph){
		if(this.autoFit){
			this.computeFitToScreenFactor();
		}
		var nPercent = this.slider.getValue();
		this.zoomInput.value = nPercent;
		var height = parseInt(nPercent*this.crtHeight / 100);
		var width = parseInt(nPercent*this.crtWidth / 100);
		// Center vertically
		var margin=0;
		if (height < this.containerDim.height){
			var margin = parseInt((this.containerDim.height - height) / 2)-5;
		}
		if(morph){
			new Effect.Morph(this.imgTag,{
				style:{height:height+'px', width:width+'px',margin:margin+'px'},
				duration:0.5
				});
		}else{
			this.imgTag.setStyle({height:height+'px', width:width+'px',margin:margin+'px'});
		}
	},

	setFullScreen: function(){
		this.fullBox.absolutize();
		$(document.body).insert(this.fullBox);
		this.fullBox.setStyle({
			top:0,
			left:0,
			backgroundColor:'#fff',
			width:'100%',
			height:document.viewport.getHeight(),
			zIndex:3000});
		this.origContainerHeight = this.imgContainer.getHeight();
		fitHeightToBottom(this.imgContainer, this.fullBox);
		this.fullscreenMode = true;
	},

	exitFullScreen: function(){
		this.fullBox.relativize();
		$(this.element).insert(this.fullBox);
		this.fullBox.setStyle({top:0,left:0,zIndex:100});
		//fitHeightToBottom(this.imgContainer, null, 5);
		this.imgContainer.setStyle({height:this.origContainerHeight});
		this.fullscreenMode = false;
	},

	updateImage : function(){
		var dimObject = this.sizes.get(this.currentFile);
		this.crtHeight = dimObject.height;
		this.crtWidth = dimObject.width;
		this.crtRatio = this.crtHeight / this.crtWidth;
		this.downloadButton.addClassName("disabled");
		this.imgTag.src  = this.baseUrl + this.currentFile;
	},

	fitToScreen : function(){
		this.computeFitToScreenFactor();
		this.resizeImage(true);
	},

	computeFitToScreenFactor: function(){
		zoomFactor1 = parseInt(this.imgContainer.getHeight() / this.crtHeight * 100);
		zoomFactor2 = parseInt(this.imgContainer.getWidth() / this.crtWidth * 100);
		this.slider.setValue(Math.min(zoomFactor1, zoomFactor2)-1);
	},

	toggleFitToScreen:function(){
		if(this.autoFit){
			this.autoFit = false;
			this.fitToScreenButton.removeClassName('diaporamaButtonActive');
		}else{
			this.autoFit = true;
			this.fitToScreenButton.addClassName('diaporamaButtonActive');
			this.fitToScreen();
		}
	},

	close : function(){
		this.currentFile = null;
		this.items = null;
		this.imgTag.src = '';
		this.stop();
		if(this.fullscreenMode) this.exitFullScreen();
	},

	play: function(){
		if(!this.timeInput.value) this.timeInput.value = 3;
		this.pe = new PeriodicalExecuter(this.next.bind(this), parseInt(this.timeInput.value));
		this.slideShowPlaying = true;
	},

	stop: function(){
		if(this.pe) this.pe.stop();
		this.slideShowPlaying = false;
	},

	next : function(){
		if(this.currentFile != this.items.last())
		{
			this.currentFile = this.items[this.items.indexOf(this.currentFile)+1];
			this.updateImage();
		}
		else if(this.slideShowPlaying){
			this.currentFile = this.items[0];
			this.updateImage();
		}
	},

	previous : function(){
		if(this.currentFile != this.items.first())
		{
			this.currentFile = this.items[this.items.indexOf(this.currentFile)-1];
			this.updateImage();
		}
	},

	updateButtons : function(){
		if(this.slideShowPlaying){
			this.previousButton.addClassName("disabled");
			this.nextButton.addClassName("disabled");
			this.playButton.addClassName("disabled");
			this.stopButton.removeClassName("disabled");
		}else{
			if(this.currentFile == this.items.first()) this.previousButton.addClassName("disabled");
			else this.previousButton.removeClassName("disabled");
			if(this.currentFile == this.items.last()) this.nextButton.addClassName("disabled");
			else this.nextButton.removeClassName("disabled");
			this.playButton.removeClassName("disabled");
			this.stopButton.addClassName("disabled");
		}
	}
});<commit_msg>Fix bug : when clicking on fullscreen, the path was reset to root in explorer behind.<commit_after>var DiaporamaFirstOccurence = true;
Diaporama = Class.create({

	fullscreenMode: false,

	initialize: function(div)
	{
		this.element = div;
		this.fullBox = this.element.select('div[id="diaporama_box"]')[0];
		this.nextButton = div.select('a[id="nextButton"]')[0];
		this.previousButton = div.select('a[id="prevButton"]')[0];
		this.closeButton = div.select('a[id="closeButton"]')[0];
		this.downloadButton = div.select('a[id="downloadDiapoButton"]')[0];
		this.playButton = div.select('a[id="playButton"]')[0];
		this.stopButton = div.select('a[id="stopButton"]')[0];
		this.fsButton = div.select('a[id="fsButton"]')[0];
		this.nofsButton = div.select('a[id="nofsButton"]')[0];

		this.actualSizeButton = div.select('img[id="actualSizeButton"]')[0];
		this.fitToScreenButton = div.select('img[id="fitToScreenButton"]')[0];
		this.imgTag = div.select('img[id="mainImage"]')[0];
		this.imgContainer = div.select('div[id="imageContainer"]')[0];
		fitHeightToBottom(this.imgContainer, null, 5);
		this.zoomInput = div.select('input[id="zoomValue"]')[0];
		this.timeInput = div.select('input[id="time"]')[0];
		this.baseUrl = 'content.php?action=image_proxy&file=';
		this.nextButton.onclick = function(){
			this.next();
			this.updateButtons();
			return false;
		}.bind(this);
		this.previousButton.onclick = function(){
			this.previous();
			this.updateButtons();
			return false;
		}.bind(this);
		this.closeButton.onclick = function(){
			if(this.fullscreenMode) this.exitFullScreen();
			this.close();
			hideLightBox(true);
			return false;
		}.bind(this);
		this.downloadButton.onclick = function(){
			if(!this.currentFile) return;
			document.location.href = 'content.php?action=download&file='+this.currentFile;
			return false;
		}.bind(this);
		this.actualSizeButton.onclick = function(){
			this.slider.setValue(100);
			this.resizeImage(true);
		}.bind(this);
		this.fitToScreenButton.onclick = function(){
			this.toggleFitToScreen();
		}.bind(this);
		this.playButton.onclick = function(){
			this.play();
			this.updateButtons();
			return false;
		}.bind(this);
		this.stopButton.onclick = function(){
			this.stop();
			this.updateButtons();
			return false;
		}.bind(this);
		this.fsButton.onclick = function(){
			this.setFullScreen();
			this.fsButton.hide();
			this.nofsButton.show();
			return false;
		}.bind(this);
		this.nofsButton.onclick = function(){
			this.exitFullScreen();
			this.nofsButton.hide();
			this.fsButton.show();
			return false;
		}.bind(this);
		modal.setCloseAction(this.close.bind(this));

		this.imgTag.onload = function(){
			this.resizeImage(true);
			this.downloadButton.removeClassName("disabled");
			this.updateModalTitle();
		}.bind(this);
		Event.observe(this.zoomInput, "keypress", function(e){
			if(e == null) e = window.event;
			if(e.keyCode == Event.KEY_RETURN || e.keyCode == Event.KEY_UP || e.keyCode == Event.KEY_DOWN){
				if(e.keyCode == Event.KEY_UP || e.keyCode == Event.KEY_DOWN)
				{
					var crtValue = parseInt(this.zoomInput.value);
					var value = (e.keyCode == Event.KEY_UP?(e.shiftKey?crtValue+10:crtValue+1):(e.shiftKey?crtValue-10:crtValue-1));
					this.zoomInput.value = value;
				}
				this.slider.setValue(this.zoomInput.value);
				this.resizeImage(false);
				Event.stop(e);
			}
			return true;
		}.bind(this));
		this.timeInput.observe('change', function(e){
			if(this.slideShowPlaying && this.pe){
				this.stop();
				this.play();
			}
		}.bind(this));
		this.containerDim = $(this.imgContainer).getDimensions();
	},

	open : function(aFilesList, sCurrentFile)
	{
		var allItems = aFilesList;
		this.items = new Array();
		this.sizes = new Hash();
		$A(allItems).each(function(rowItem){
			if(rowItem.getAttribute('is_image')=='1'){
				this.items.push(rowItem.getAttribute('filename'));
				this.sizes.set(rowItem.getAttribute('filename'),  {height:rowItem.getAttribute('image_height'),
															   width:rowItem.getAttribute('image_width')});
			}
		}.bind(this));

		if(!sCurrentFile && this.items.length) sCurrentFile = this.items[0];
		this.currentFile = sCurrentFile;

		var sliderDiv = this.element.select('div[id="slider-2"]')[0];
		var sliderInput = this.element.select('input[id="slider-input-2"]')[0];
		this.slider = new Slider(sliderDiv, sliderInput);
		this.slider.setMaximum(200);
		this.slider.setMinimum(10);
		this.slider.setValue(100);
		this.zoomInput.value = '100';
		this.slider.recalculate();
		this.slider.onchange = function(){
			this.resizeImage(false);
		}.bind(this);

		this.updateImage();
		this.updateButtons();
		if(DiaporamaFirstOccurence){
			$$(".action_bar a").each(function(el){
				new Effect.Corner(el, "round 8px");
			});
			DiaporamaFirstOccurence = false;
		}
	},

	updateModalTitle : function(){
		var titleDiv = $(modal.dialogTitle);
		var crtTitle = titleDiv.select('span.titleString')[0];
		var filenameSpans = crtTitle.select('span');
		var text = ' - '+getBaseName(this.currentFile) + ' ('+this.sizes.get(this.currentFile).width+' X '+this.sizes.get(this.currentFile).height+')';
		if(filenameSpans.length) filenameSpans[0].innerHTML = text;
		else {
			newSpan = document.createElement('span');
			newSpan.appendChild(document.createTextNode(text));
			crtTitle.appendChild(newSpan);
		}
	},

	resizeImage : function(morph){
		if(this.autoFit){
			this.computeFitToScreenFactor();
		}
		var nPercent = this.slider.getValue();
		this.zoomInput.value = nPercent;
		var height = parseInt(nPercent*this.crtHeight / 100);
		var width = parseInt(nPercent*this.crtWidth / 100);
		// Center vertically
		var margin=0;
		if (height < this.containerDim.height){
			var margin = parseInt((this.containerDim.height - height) / 2)-5;
		}
		if(morph){
			new Effect.Morph(this.imgTag,{
				style:{height:height+'px', width:width+'px',margin:margin+'px'},
				duration:0.5
				});
		}else{
			this.imgTag.setStyle({height:height+'px', width:width+'px',margin:margin+'px'});
		}
	},

	setFullScreen: function(){
		this.fullBox.absolutize();
		$(document.body).insert(this.fullBox);
		this.fullBox.setStyle({
			top:0,
			left:0,
			backgroundColor:'#fff',
			width:'100%',
			height:document.viewport.getHeight(),
			zIndex:3000});
		this.origContainerHeight = this.imgContainer.getHeight();
		fitHeightToBottom(this.imgContainer, this.fullBox);
		this.fullscreenMode = true;
	},

	exitFullScreen: function(){
		this.fullBox.relativize();
		$(this.element).insert(this.fullBox);
		this.fullBox.setStyle({top:0,left:0,zIndex:100});
		//fitHeightToBottom(this.imgContainer, null, 5);
		this.imgContainer.setStyle({height:this.origContainerHeight});
		this.fullscreenMode = false;
	},

	updateImage : function(){
		var dimObject = this.sizes.get(this.currentFile);
		this.crtHeight = dimObject.height;
		this.crtWidth = dimObject.width;
		this.crtRatio = this.crtHeight / this.crtWidth;
		this.downloadButton.addClassName("disabled");
		this.imgTag.src  = this.baseUrl + this.currentFile;
	},

	fitToScreen : function(){
		this.computeFitToScreenFactor();
		this.resizeImage(true);
	},

	computeFitToScreenFactor: function(){
		zoomFactor1 = parseInt(this.imgContainer.getHeight() / this.crtHeight * 100);
		zoomFactor2 = parseInt(this.imgContainer.getWidth() / this.crtWidth * 100);
		this.slider.setValue(Math.min(zoomFactor1, zoomFactor2)-1);
	},

	toggleFitToScreen:function(){
		if(this.autoFit){
			this.autoFit = false;
			this.fitToScreenButton.removeClassName('diaporamaButtonActive');
		}else{
			this.autoFit = true;
			this.fitToScreenButton.addClassName('diaporamaButtonActive');
			this.fitToScreen();
		}
	},

	close : function(){
		this.currentFile = null;
		this.items = null;
		this.imgTag.src = '';
		this.stop();
		if(this.fullscreenMode) this.exitFullScreen();
	},

	play: function(){
		if(!this.timeInput.value) this.timeInput.value = 3;
		this.pe = new PeriodicalExecuter(this.next.bind(this), parseInt(this.timeInput.value));
		this.slideShowPlaying = true;
	},

	stop: function(){
		if(this.pe) this.pe.stop();
		this.slideShowPlaying = false;
	},

	next : function(){
		if(this.currentFile != this.items.last())
		{
			this.currentFile = this.items[this.items.indexOf(this.currentFile)+1];
			this.updateImage();
		}
		else if(this.slideShowPlaying){
			this.currentFile = this.items[0];
			this.updateImage();
		}
	},

	previous : function(){
		if(this.currentFile != this.items.first())
		{
			this.currentFile = this.items[this.items.indexOf(this.currentFile)-1];
			this.updateImage();
		}
	},

	updateButtons : function(){
		if(this.slideShowPlaying){
			this.previousButton.addClassName("disabled");
			this.nextButton.addClassName("disabled");
			this.playButton.addClassName("disabled");
			this.stopButton.removeClassName("disabled");
		}else{
			if(this.currentFile == this.items.first()) this.previousButton.addClassName("disabled");
			else this.previousButton.removeClassName("disabled");
			if(this.currentFile == this.items.last()) this.nextButton.addClassName("disabled");
			else this.nextButton.removeClassName("disabled");
			this.playButton.removeClassName("disabled");
			this.stopButton.addClassName("disabled");
		}
	}
});<|endoftext|>


<commit_before>/**
 * Production environment settings
 *
 * This file can include shared settings for a production environment,
 * such as API keys or remote database passwords.  If you're using
 * a version control solution for your Sails app, this file will
 * be committed to your repository unless you add it to your .gitignore
 * file.  If your repository will be publicly viewable, don't add
 * any private information to this file!
 *
 */

module.exports = {

  /***************************************************************************
   * Set the default database connection for models in the production        *
   * environment (see config/connections.js and config/models.js )           *
   ***************************************************************************/

  // models: {
  //  connection: 'someMysqlServer'
  //  migrate: 'safe';
  // },

  /***************************************************************************
   * Uncomment to set the CORS Setting for your App in the production        *
   * environment (see config/cors.js )                                       *
   ***************************************************************************/

  //Uncomment this if you want CORS deactivated for production
  //cors: {
  //  allRoutes: false,
  //  origin: '*',
  //  credentials: false,
  //  methods: 'GET, POST, PUT, DELETE, OPTIONS, HEAD',
  //  headers: false
  //},

  /***************************************************************************
   * Set the port in the production environment to 80                        *
   ***************************************************************************/

  // port: 80,

  /***************************************************************************
   * Set the log level in production environment to "silent"                 *
   ***************************************************************************/

  // log: {
  //   level: "silent"
  // }

};
<commit_msg>Deactivate shortcut routes for production env<commit_after>/**
 * Production environment settings
 *
 * This file can include shared settings for a production environment,
 * such as API keys or remote database passwords.  If you're using
 * a version control solution for your Sails app, this file will
 * be committed to your repository unless you add it to your .gitignore
 * file.  If your repository will be publicly viewable, don't add
 * any private information to this file!
 *
 */

module.exports = {

  /***************************************************************************
   * Set the default database connection for models in the production        *
   * environment (see config/connections.js and config/models.js )           *
   ***************************************************************************/

  // models: {
  //  connection: 'someMysqlServer'
  //  migrate: 'safe';
  // },

  /***************************************************************************
   * Uncomment to set the CORS Setting for your App in the production        *
   * environment (see config/cors.js )                                       *
   ***************************************************************************/

  //Uncomment this if you want CORS deactivated for production
  //cors: {
  //  allRoutes: false,
  //  origin: '*',
  //  credentials: false,
  //  methods: 'GET, POST, PUT, DELETE, OPTIONS, HEAD',
  //  headers: false
  //},

  //Deactivate some default routes for production, for security reasons
  blueprints: {
    //Uncomment if you want to disable action routes
    //actions: false,
    shortcuts: false
  }

  /***************************************************************************
   * Set the port in the production environment to 80                        *
   ***************************************************************************/

  // port: 80,

  /***************************************************************************
   * Set the log level in production environment to "silent"                 *
   ***************************************************************************/

  // log: {
  //   level: "silent"
  // }

};
<|endoftext|>


<commit_before>var express = require('express')
var path = require('path')
var logger = require('morgan')
var bodyParser = require('body-parser')

var routes = require('./routes/api')

var app = express()

// uncomment after placing your favicon in /public
app.use(logger('dev'))
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: false }))

app.use('/api', routes)

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found')
  err.status = 404
  next(err)
})

// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
  app.use(function(err, req, res, next) {
    res.status(err.status || 500)
	.send({
      message: err.message,
      error: err
    })
  })
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
  res.status(err.status || 500)
  .send({
    message: err.message,
    error: {}
  })
})

module.exports = app
<commit_msg>implementado resposta a servidor openshift (health)<commit_after>var express = require('express')
var path = require('path')
var logger = require('morgan')
var bodyParser = require('body-parser')

var routes = require('./routes/api')

var app = express()

// uncomment after placing your favicon in /public
app.use(logger('dev'))
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: false }))

app.use('/api', routes)

//openshift verificação de funcionamento
app.all('/health', function (req, res) {
	res.status(200).send()
})

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found')
  err.status = 404
  next(err)
})

// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
  app.use(function(err, req, res, next) {
    res.status(err.status || 500)
	.send({
      message: err.message,
      error: err
    })
  })
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
  res.status(err.status || 500)
  .send({
    message: err.message,
    error: {}
  })
})

module.exports = app
<|endoftext|>


<commit_before>HopObject.inject({
	absoluteHref: function(action) {
		return app.properties.serverUri + this.href(action);
	},

	instanceOf: function(ctor) {
		var proto = this.__proto__;
		while (proto && proto !== Object.prototype) {
			if (proto.constructor.name == ctor.name)
				return true;
			proto = proto.__proto__;
		}
		return false;
	},

	isVisiting: function() {
		return this == path[path.length - 1];
	},

	/**
	 * Parses the text into a helma skin and renders it. This will be deprecated
	 * in favour of Markup.js and Template.js
	 */
	renderText: function(text, out) {
		if (text) {
			var skin = createSkin(format(text));
			if (out == res)	this.renderSkin(skin);
			else {
				var str = this.renderSkinAsString(skin);
				if (out) out.write(str);
				else return str;
			}
		}
	},

	/**
	 * Render HTML is the method in base lib apps that's supposed to render the
	 * final result. This here is just a scafold, apps should provide their own.
	 * But since core parts rely on it to be there, here it is, along with a
	 * simple template.
	 */
	renderHtml: function(param, out) {
		param.title = param.title || this.getDisplayName && this.getDisplayName() || this.name;
		return this.renderTemplate('html', param, out);
	},

	/**
	 * Renders html for a popup window by using the popup.jstl instead of html.jst
	 * TODO: Maybe merge both templates using switches?
	 */
	renderPopup: function(param, out) {
		param.title = param.title || this.getDisplayName && this.getDisplayName() || this.name;
		return this.renderTemplate('popup', param, out);
	},

	/**
	 * Renders the navigation for a paginated ilst. param.position is read to determine the current position
	 * and set if it's undefined.
	 * param.maxPerPage specifies the amount of items per page
	 * ...
	 * TODO: Consider moving elsewhere?
	 */
	renderPagination: function(param, out) {
		var last = Math.max(0, Math.floor((param.count - 1) / param.maxPerPage));
		var pos = 0;
		if (req.data.pos != null) {
			pos = parseInt(req.data.pos);
		} else if (param.position) {
			pos = param.position;
		}
		if (pos < 0) pos = last;
		param.position = pos;
		var index = pos * param.maxPerPage;
		// Render pagination only if needed:
		var multiPage = param.count > param.maxPerPage;
		if (multiPage || param.prefix) {
			if (multiPage) {
				// If we're loading into a container, request the action of the same name on the object.
				// This is convention, the only place this is used right now is for the loading of 'posts'.
				var href = param.href ? param.href : param.container ? this.href(param.container) : this.href();
				var pages = [ pos > 0
					? renderLink({ content: '<', href: href, query: 'pos=' + (pos - 1), update: param.container })
					: '<'
				];
				var step = 1;
				var num = last;
				while (num >= (step == 1 ? 15 : 7)) {
					step++;
					num = last / step;
				}
				for (var i = 0; i <= last; i += step) {
					var name = i + 1;
					if (step > 1)
						name += '-' + (name + step - 1);
					if (pos >= i && pos < i + step)
						pages.push(name);
					else
						pages.push(renderLink({ content: name, href: href, query: 'pos=' + i, update: param.container }));
				}
				pages.push(pos < last
					? renderLink({ content: '>', href: href, query: 'pos=' + (pos + 1), update: param.container })
					: '>'
				);
				param.pages = pages.join(' ');
			}
			if (param.count > 0) {
				param.first = index + 1;
				param.last = Math.min(param.count, index + param.maxPerPage);
			}
			if (param.plural == null)
				param.plural = param.singular + 's';
			return this.renderTemplate('pagination', param, out);
		}
	},

	/**
	 * Returns the object's fulLId. This is the object's prototype and id
	 * seperated by a dash. This id can be used again to retrieve the object
	 * Through HopObject.get(fullId);
	 */
	getFullId: function() {
		// Use this.cache.creationId instead of real _if if set, so transient
		// nodes can pretend to be another node. Used when transient nodes
		// about to be created are lost in the cache, or when transient nodes
		// or forced to become persisted early, e.g. by adding a reference
		// to another persisted node before creation is finished.
		// See EditNode#initialize
		return this._prototype + '-' + (this.cache.creationId || this._id);
	},

	getParent: function() {
		// to be used wherever _parent is accessed, so apps can override
		// the way parents are handled (e.g. liento)
		return this._parent; // default is returning _parent
	},

	/**
	 * Radomly picks one entry from the list.
	 */
	pick: function() {
		return this.get(Math.rand(this.count()));
	},

	statics: {
		/**
		 * Takes either an id / prototype pair of a full id ("prototype-id")
		 * and returns the corresponding object, if any.
		 */
		get: function(id, prototype) {
			// Support fullId prototype-id notation for string parameters:
			if (id == null)
				return null;
			if (prototype == undefined) {
				// id is a fullId:
				var parts = id.split('-');
				prototype = parts[0];
				id = parts[1];
			}
			return HopObject.getById(id, prototype);
		},

		/**
		 * Returns object identified by a local url, or null if no object can be found.
		 */
		getByUrl: function(url) {
			var path = decodeUrl(url).split('/');
			var obj = root;
			for (var i = 0, l = path.length; i < l && obj != null; i++) {
				var name = path[i];
				if (name) {
					var next = obj.getChildElement(name);
					// If next is null, only set obj to null if it is not the
					// last one or not matching the action on the last object
					// with the same name.
					if (next || i < l - 1 || !obj[name + '_action'])
						obj = next;
				}
			}
			return obj;
		}
	}
});
<commit_msg>Rename HopObject#isVisiting() to more meaningful #isActive().<commit_after>HopObject.inject({
	absoluteHref: function(action) {
		return app.properties.serverUri + this.href(action);
	},

	instanceOf: function(ctor) {
		var proto = this.__proto__;
		while (proto && proto !== Object.prototype) {
			if (proto.constructor.name == ctor.name)
				return true;
			proto = proto.__proto__;
		}
		return false;
	},

	isActive: function() {
		return this == path[path.length - 1];
	},

	/**
	 * Parses the text into a helma skin and renders it. This will be deprecated
	 * in favour of Markup.js and Template.js
	 */
	renderText: function(text, out) {
		if (text) {
			var skin = createSkin(format(text));
			if (out == res)	this.renderSkin(skin);
			else {
				var str = this.renderSkinAsString(skin);
				if (out) out.write(str);
				else return str;
			}
		}
	},

	/**
	 * Render HTML is the method in base lib apps that's supposed to render the
	 * final result. This here is just a scafold, apps should provide their own.
	 * But since core parts rely on it to be there, here it is, along with a
	 * simple template.
	 */
	renderHtml: function(param, out) {
		param.title = param.title || this.getDisplayName && this.getDisplayName() || this.name;
		return this.renderTemplate('html', param, out);
	},

	/**
	 * Renders html for a popup window by using the popup.jstl instead of html.jst
	 * TODO: Maybe merge both templates using switches?
	 */
	renderPopup: function(param, out) {
		param.title = param.title || this.getDisplayName && this.getDisplayName() || this.name;
		return this.renderTemplate('popup', param, out);
	},

	/**
	 * Renders the navigation for a paginated ilst. param.position is read to determine the current position
	 * and set if it's undefined.
	 * param.maxPerPage specifies the amount of items per page
	 * ...
	 * TODO: Consider moving elsewhere?
	 */
	renderPagination: function(param, out) {
		var last = Math.max(0, Math.floor((param.count - 1) / param.maxPerPage));
		var pos = 0;
		if (req.data.pos != null) {
			pos = parseInt(req.data.pos);
		} else if (param.position) {
			pos = param.position;
		}
		if (pos < 0) pos = last;
		param.position = pos;
		var index = pos * param.maxPerPage;
		// Render pagination only if needed:
		var multiPage = param.count > param.maxPerPage;
		if (multiPage || param.prefix) {
			if (multiPage) {
				// If we're loading into a container, request the action of the same name on the object.
				// This is convention, the only place this is used right now is for the loading of 'posts'.
				var href = param.href ? param.href : param.container ? this.href(param.container) : this.href();
				var pages = [ pos > 0
					? renderLink({ content: '<', href: href, query: 'pos=' + (pos - 1), update: param.container })
					: '<'
				];
				var step = 1;
				var num = last;
				while (num >= (step == 1 ? 15 : 7)) {
					step++;
					num = last / step;
				}
				for (var i = 0; i <= last; i += step) {
					var name = i + 1;
					if (step > 1)
						name += '-' + (name + step - 1);
					if (pos >= i && pos < i + step)
						pages.push(name);
					else
						pages.push(renderLink({ content: name, href: href, query: 'pos=' + i, update: param.container }));
				}
				pages.push(pos < last
					? renderLink({ content: '>', href: href, query: 'pos=' + (pos + 1), update: param.container })
					: '>'
				);
				param.pages = pages.join(' ');
			}
			if (param.count > 0) {
				param.first = index + 1;
				param.last = Math.min(param.count, index + param.maxPerPage);
			}
			if (param.plural == null)
				param.plural = param.singular + 's';
			return this.renderTemplate('pagination', param, out);
		}
	},

	/**
	 * Returns the object's fulLId. This is the object's prototype and id
	 * seperated by a dash. This id can be used again to retrieve the object
	 * Through HopObject.get(fullId);
	 */
	getFullId: function() {
		// Use this.cache.creationId instead of real _if if set, so transient
		// nodes can pretend to be another node. Used when transient nodes
		// about to be created are lost in the cache, or when transient nodes
		// or forced to become persisted early, e.g. by adding a reference
		// to another persisted node before creation is finished.
		// See EditNode#initialize
		return this._prototype + '-' + (this.cache.creationId || this._id);
	},

	getParent: function() {
		// to be used wherever _parent is accessed, so apps can override
		// the way parents are handled (e.g. liento)
		return this._parent; // default is returning _parent
	},

	/**
	 * Radomly picks one entry from the list.
	 */
	pick: function() {
		return this.get(Math.rand(this.count()));
	},

	statics: {
		/**
		 * Takes either an id / prototype pair of a full id ("prototype-id")
		 * and returns the corresponding object, if any.
		 */
		get: function(id, prototype) {
			// Support fullId prototype-id notation for string parameters:
			if (id == null)
				return null;
			if (prototype == undefined) {
				// id is a fullId:
				var parts = id.split('-');
				prototype = parts[0];
				id = parts[1];
			}
			return HopObject.getById(id, prototype);
		},

		/**
		 * Returns object identified by a local url, or null if no object can be found.
		 */
		getByUrl: function(url) {
			var path = decodeUrl(url).split('/');
			var obj = root;
			for (var i = 0, l = path.length; i < l && obj != null; i++) {
				var name = path[i];
				if (name) {
					var next = obj.getChildElement(name);
					// If next is null, only set obj to null if it is not the
					// last one or not matching the action on the last object
					// with the same name.
					if (next || i < l - 1 || !obj[name + '_action'])
						obj = next;
				}
			}
			return obj;
		}
	}
});
<|endoftext|>


<commit_before>/**
 * Load app configurations
 */

const fs = require('fs');
const path = require('path');
const chalk = require('chalk');

const devConfig = require('./config.default.dev');
const prodConfig = require('./config.default.prod');

/**
 * app configs
 * @type {{}}
 */
let config = {};

//get custom config path from env
const customConfigPath = process.env.NODE_CONFIG_PATH;
const nodeBuildEnv = process.env.NODE_BUILD_ENV;

const DEFAULT_PREFIX_KEY = 'defaultPrefix';

function initConfig(customConfig) {
  let defaultConfigJS = '../app-config.js';
  const defaultConfigJSAlt = './app-config.js';

  try {
    fs.statSync(path.join(__dirname, defaultConfigJS));
  } catch (e) {
    defaultConfigJS = defaultConfigJSAlt;
  }

  const configPath = customConfigPath
    ? path.resolve(customConfigPath)
    : path.join(__dirname, defaultConfigJS);
  // console.log(configPath);
  let configInfo = {};
  let hasCustomConfig = true;
  let checkMsg = '';

  try {
    fs.statSync(configPath);
  } catch (e) {
    hasCustomConfig = false;
  }

  // console.log('process.env.STATIC_PREFIX: ', process.env.STATIC_PREFIX);
  // console.log('process.env.APP_PREFIX: ', process.env.APP_PREFIX);

  if (hasCustomConfig) {
    configInfo = require(configPath);
    checkMsg += `Using [${chalk.green(configPath)}] as basic app configuration`;
  } else {
    configInfo = !nodeBuildEnv ? prodConfig : devConfig;
    checkMsg += `Using [${chalk.green(
      !nodeBuildEnv ? 'config.default.prod' : 'config.default.dev'
    )}] as app configuration`;
  }
  console.log(checkMsg);

  if (customConfig) {
    console.log('merging custom config into basic config from config file...');
    Object.assign(configInfo, customConfig);
  }

  //cache non-empty config from env at init time instead of accessing from process.env at runtime to improve performance
  for (let key in configInfo) {
    if (configInfo.hasOwnProperty(key)) {
      config[key] = process.env.hasOwnProperty(key)
        ? process.env[key]
        : configInfo[key];
    }
  }
}

function getConfigProperty(key) {
  let value = undefined;
  if (config.hasOwnProperty(key)) {
    // console.log(`config[${key}] from cache`);
    value = config[key];
  } else {
    // console.log(`config[${key}] from process.env`);
    value = process.env[key];
  }
  return value;
}

// console.log('config: ', config);

initConfig();

module.exports = {
  getListeningPort: () => {
    return getConfigProperty('PORT') || getConfigProperty('NODE_PORT');
  },
  getNodeEnv: () => {
    return getConfigProperty('NODE_ENV');
  },
  isDevMode: () => {
    const env = getConfigProperty('NODE_ENV');
    return 'dev' === env || 'development' === env;
  },
  isProdMode: () => {
    const env = getConfigProperty('NODE_ENV');
    return 'prod' === env || 'production' === env;
  },
  isNodeProxyEnabled: () => {
    return !!getConfigProperty('NODE_PROXY');
  },
  getStaticAssetsEndpoint: () => {
    //AKA, get CDN domain
    return getConfigProperty('STATIC_ENDPOINT');
  },
  getAppPrefix: () => {
    return getConfigProperty('APP_PREFIX') || '';
  },
  getStaticPrefix: () => {
    return getConfigProperty('STATIC_PREFIX') || '';
  },
  isPrefixTailSlashEnabled: () => {
    return !!getConfigProperty('PREFIX_TRAILING_SLASH');
  },
  getApiEndPoints: () => {
    return getConfigProperty('API_ENDPOINTS');
  },
  getProxyDebugLevel: () => {
    return getConfigProperty('PROXY_DEBUG_LEVEL');
  },
  isHMREnabled: () => {
    const val = getConfigProperty('ENABLE_HMR');
    return module.exports.isDevMode() && isTrue(val);
  },
  isSSREnabled: () => {
    const val = getConfigProperty('ENABLE_SSR');
    return isTrue(val) && !module.exports.isHMREnabled();
  },
  isBundleAnalyzerEnabled: () => {
    const val = getConfigProperty('BUNDLE_ANALYZER');
    return isTrue(val);
  },
  isCustomAPIPrefix: () => {
    return !!getConfigProperty('CUSTOM_API_PREFIX');
  },
  getLogPath: () => {
    return getConfigProperty('LOG_PATH') || path.join(__dirname, '../logs');
  },
  getHttpProxy: () => {
    return getConfigProperty('HTTP_PROXY');
  },
  getSocksProxy: () => {
    return getConfigProperty('SOCKS_PROXY');
  },
  getDefaultApiEndPoint: () => {
    const obj = getConfigProperty('API_ENDPOINTS');
    return obj[obj[DEFAULT_PREFIX_KEY]];
  },
  getDefaultApiEndPointKey: () => {
    return DEFAULT_PREFIX_KEY;
  },
  isInlineStyles: () => {
    return getConfigProperty('INLINE_STYLES');
  },
  isCSSModules: () => {
    return isTrue(getConfigProperty('CSS_MODULES'));
  },
  getHMRPort: () => {
    return getConfigProperty('HMR_PORT');
  },
  getEnv: key => {
    return getConfigProperty(key);
  },
};

function isTrue(val) {
  return !!(val && (val === true || val === 'true' || val === '1'));
}
<commit_msg>:sparkles: Auto create app-config file when in dev mode<commit_after>/**
 * Load app configurations
 */

const fs = require('fs');
const path = require('path');
const chalk = require('chalk');

const devConfig = require('./config.default.dev');
const prodConfig = require('./config.default.prod');

/**
 * app configs
 * @type {{}}
 */
let config = {};

//get custom config path from env
const customConfigPath = process.env.NODE_CONFIG_PATH;
const nodeBuildEnv = process.env.NODE_BUILD_ENV;

const DEFAULT_PREFIX_KEY = 'defaultPrefix';

const DEFAULT_CONFIG_FILE_NAME = 'app-config.js';

function initConfig(customConfig) {
  let defaultConfigJS = `../${DEFAULT_CONFIG_FILE_NAME}`;
  const defaultConfigJSAlt = `./${DEFAULT_CONFIG_FILE_NAME}`;

  try {
    fs.statSync(path.join(__dirname, defaultConfigJS));
  } catch (e) {
    defaultConfigJS = defaultConfigJSAlt;
  }

  let configPath = customConfigPath
    ? path.resolve(customConfigPath)
    : path.join(__dirname, defaultConfigJS);
  // console.log(configPath);
  let configInfo;
  let hasCustomConfig = true;
  let checkMsg = '';

  try {
    fs.statSync(configPath);
  } catch (e) {
    if (!process.env.NODE_ENV || process.env.NODE_ENV === 'development') {
      configPath = autoCreateConfigFile();
    } else {
      hasCustomConfig = false;
    }
  }

  // console.log('process.env.STATIC_PREFIX: ', process.env.STATIC_PREFIX);
  // console.log('process.env.APP_PREFIX: ', process.env.APP_PREFIX);

  if (hasCustomConfig) {
    configInfo = require(configPath);
    checkMsg += `Using [${chalk.green(configPath)}] as app configuration`;
  } else {
    configInfo =
      !nodeBuildEnv || nodeBuildEnv !== 'development' ? prodConfig : devConfig;
    checkMsg += `Using [${chalk.green(
      !nodeBuildEnv ? 'config.default.prod' : 'config.default.dev'
    )}] as app configuration`;
  }
  console.log(checkMsg);

  if (customConfig) {
    console.log('merging custom config into basic config from config file...');
    Object.assign(configInfo, customConfig);
  }

  //cache non-empty config from env at init time instead of accessing from process.env at runtime to improve performance
  for (let key in configInfo) {
    if (configInfo.hasOwnProperty(key)) {
      config[key] = process.env.hasOwnProperty(key)
        ? process.env[key]
        : configInfo[key];
    }
  }
}

function autoCreateConfigFile() {
  const targetFile = path.join(__dirname, `../${DEFAULT_CONFIG_FILE_NAME}`);
  fs.copyFileSync(path.join(__dirname, 'app-config.js.sample'), targetFile);
  console.log(`Create ${DEFAULT_CONFIG_FILE_NAME} in project root`);
  return targetFile;
}

function getConfigProperty(key) {
  let value;
  if (config.hasOwnProperty(key)) {
    // console.log(`config[${key}] from cache`);
    value = config[key];
  } else {
    // console.log(`config[${key}] from process.env`);
    value = process.env[key];
  }
  return value;
}

// console.log('config: ', config);

initConfig();

module.exports = {
  getListeningPort: () => {
    return getConfigProperty('PORT') || getConfigProperty('NODE_PORT');
  },
  getNodeEnv: () => {
    return getConfigProperty('NODE_ENV');
  },
  isDevMode: () => {
    const env = getConfigProperty('NODE_ENV');
    return 'dev' === env || 'development' === env;
  },
  isProdMode: () => {
    const env = getConfigProperty('NODE_ENV');
    return 'prod' === env || 'production' === env;
  },
  isNodeProxyEnabled: () => {
    return !!getConfigProperty('NODE_PROXY');
  },
  getStaticAssetsEndpoint: () => {
    //AKA, get CDN domain
    return getConfigProperty('STATIC_ENDPOINT');
  },
  getAppPrefix: () => {
    return getConfigProperty('APP_PREFIX') || '';
  },
  getStaticPrefix: () => {
    return getConfigProperty('STATIC_PREFIX') || '';
  },
  isPrefixTailSlashEnabled: () => {
    return !!getConfigProperty('PREFIX_TRAILING_SLASH');
  },
  getApiEndPoints: () => {
    return getConfigProperty('API_ENDPOINTS');
  },
  getProxyDebugLevel: () => {
    return getConfigProperty('PROXY_DEBUG_LEVEL');
  },
  isHMREnabled: () => {
    const val = getConfigProperty('ENABLE_HMR');
    return module.exports.isDevMode() && isTrue(val);
  },
  isSSREnabled: () => {
    const val = getConfigProperty('ENABLE_SSR');
    return isTrue(val) && !module.exports.isHMREnabled();
  },
  isBundleAnalyzerEnabled: () => {
    const val = getConfigProperty('BUNDLE_ANALYZER');
    return isTrue(val);
  },
  isCustomAPIPrefix: () => {
    return !!getConfigProperty('CUSTOM_API_PREFIX');
  },
  getLogPath: () => {
    return getConfigProperty('LOG_PATH') || path.join(__dirname, '../logs');
  },
  getHttpProxy: () => {
    return getConfigProperty('HTTP_PROXY');
  },
  getSocksProxy: () => {
    return getConfigProperty('SOCKS_PROXY');
  },
  getDefaultApiEndPoint: () => {
    const obj = getConfigProperty('API_ENDPOINTS');
    return obj[obj[DEFAULT_PREFIX_KEY]];
  },
  getDefaultApiEndPointKey: () => {
    return DEFAULT_PREFIX_KEY;
  },
  isInlineStyles: () => {
    return getConfigProperty('INLINE_STYLES');
  },
  isCSSModules: () => {
    return isTrue(getConfigProperty('CSS_MODULES'));
  },
  getHMRPort: () => {
    return getConfigProperty('HMR_PORT');
  },
  getEnv: key => {
    return getConfigProperty(key);
  },
};

function isTrue(val) {
  return !!(val && (val === true || val === 'true' || val === '1'));
}
<|endoftext|>


<commit_before>// Copyright 2015 Square Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
"use strict";

var module = angular.module("main",[]);

google.load("visualization", "1.0", {"packages":["corechart", "timeline"]});

module.config(function($locationProvider) {
  $locationProvider.html5Mode(true);
});

module.factory("$google", function($rootScope) {
  // abstraction over the async loading of google libraries.
  // registered functions are either invoked immediately (if the library finished loading).
  // or queued in an array.
  var googleFunctions = [];
  var googleLoaded = false;
  google.setOnLoadCallback(function(){
    $rootScope.$apply(function() {
      googleLoaded = true;
      googleFunctions.map(function(googleFunction) {
        googleFunction();
      });
      googleFunctions.length = 0; // clear the array.
    });
  });

  return function(func) {
    if (googleLoaded) {
      func();
    } else {
      googleFunctions.push(func);
    }
  }
});

// Autocompletion setup (depends on $http to perform request to /token).
module.run(function($http) {
  if (!document.getElementById("query-input")) {
    return;
  }
  var autocom = new Autocom(document.getElementById("query-input"));
  var keywords = ["describe", "select", "from", "to", "resolution", "where", "all", "metrics", "sample", "by"];
  autocom.options = keywords;
  autocom.prefixPattern = "`[a-zA-Z_][a-zA-Z._-]*`?|[a-zA-Z_][a-zA-Z._-]*";
  autocom.continuePattern = "[a-zA-Z_`.-]";
  autocom.tooltipX = 0;
  autocom.tooltipY = 20;
  autocom.config.skipWord = 0.05; // make it (5x) cheaper to skip letters in a candidate word
  autocom.config.skipWordEnd = 0.01; // add a small cost to skipping ends of words, which benefits shorter candidates
  $http.get("/token").success(function(data, status, headers, config) {
    if (!data.success || !data.body) {
      return;
    }
    if (data.body.functions) {
      autocom.options = autocom.options.concat( data.body.functions );
    }
    if (data.body.metrics) {
      autocom.options = autocom.options.concat( data.body.metrics.map(function(name) {
        if (name.indexOf("-") >= 0) {
          return "`" + name + "`";
        }
        return name;
      }));
    }
  });
});

// A counter is an object with .inc() and .dec() methods,
// as well as .pos() and .zero() predicates.
function Counter() {
  var count = 0;
  this.inc = function() {
    count++;
  };
  this.dec = function() {
    count--;
  };
  this.pos = function() {
    return count > 0;
  };
  this.zero = function() {
    return count === 0;
  };
};
// A singleton Counter for launched queries.
module.factory("$launchedQueries", function() {
  return new Counter();
});
// A singleton Counter for waiting charts
module.factory("$chartWaiting", function() {
  return new Counter();
});

// A ticket booth will give you a ticket with .next()
// The ticket will be .valid() until another ticket has been asked for.
function TicketBooth() {
  var count = 0;
  function Ticket(n) {
    this.valid = function() {
      return n === count;
    }
  }
  this.next = function() {
    return new Ticket(++count);
  };
}
// A singleton ticketbooth for query counting
module.factory("$queryTicketBooth", function() {
  return new TicketBooth();
});

// chart-related functions
function clearChart(chart) {
  if (chart.chart !== null) {
    chart.chart.clearChart();
    chart.chart = null;
  }
};

module.factory("$asyncRender", function($chartWaiting, $rootScope) {
  return function(chart, dataTable, options) {
    google.visualization.events.addListener(chart.chart, "ready", function() {
      $rootScope.$apply(function() { $chartWaiting.dec(); });
    });
    setTimeout(function(){chart.chart.draw(dataTable, options)}, 1);
  };
});

module.factory("$launchRequest", function($google, $http, $receive, $queryTicketBooth, $launchedQueries, $q) {
  return function(params) {
    var resultPromise = $q.defer(); // Will be resolved with received value.
    var ticket = $queryTicketBooth.next();
    $launchedQueries.inc();
    var request = $http.get("/query", {
      params:params
    }).success(function(data, status, headers, config) {
      $launchedQueries.dec();
      if (ticket.valid()) {
        resultPromise.resolve(data);
        $google(function() { $receive(data) });
      }
    }).error(function(data, status, headers, config) {
      $launchedQueries.dec();
      if (ticket.valid()) {
        resultPromise.resolve(data);
        $google(function() { $receive(data) });
      }
    });
    return resultPromise.promise;
  };
});

module.factory("$receiveSelect", function(
      $asyncRender,
      $chartWaiting,
      $inputModel,
      $location,
      $mainChart
  ) {
  return function(object) {
    if (!(object && object.name == "select" && object.body && object.body.length && object.body[0].series && object.body[0].series.length && object.body[0].timerange)) {
      // invalid data.
      return;
    }
    $chartWaiting.inc();
    var series = [];
    var labels = ["Time"];
    var table = [labels];
    for (var i = 0; i < object.body.length; i++) {
      // Each of these is a list of series
      var serieslist = object.body[i];
      for (var j = 0; j < serieslist.series.length; j++) {
        var s = object.body[i].series[j];
        series.push(s);
        labels.push(makeLabel(serieslist, s));
      }
    }
    // Next, add each row.
    var timerange = object.body[0].timerange;
    for (var t = 0; t < series[0].values.length; t++) {
      var row = [dateFromIndex(t, timerange)];
      for (var i = 0; i < series.length; i++) {
        var cell = series[i].values[t];
        if (cell === null) {
          row.push(NaN);
        } else {
          row.push(cell);
        }
      }
      table.push(row);
    }
    var dataTable = google.visualization.arrayToDataTable(table);
    var options = {
      legend:    {position: "bottom"},
      title:     $location.search()["title"],
      chartArea: {left: "5%", width:"90%", top: "5%", height: "90%"}
    }
    if ($inputModel.renderType === "line") {
      $mainChart.chart = new google.visualization.LineChart($mainChart.dom);
    } else if ($inputModel.renderType === "area") {
      options.isStacked = true;
      $mainChart.chart = new google.visualization.AreaChart($mainChart.dom);
    }
    $asyncRender($mainChart, dataTable, options);
  };
});

module.factory("$profilingEnabled", function($inputModel) {
  return {
    hasProfiling: function(data) {
      return $inputModel.profile && data && data.profile;
    }
  };
});

module.factory("$receiveProfile", function($profilingEnabled, $chartWaiting, $asyncRender, $timelineChart) {
  return function(object) {
    if (!$profilingEnabled.hasProfiling(object)) {
      return
    }
    $chartWaiting.inc();
    var dataTable = new google.visualization.DataTable();
    var options = {
      chartArea: {left: "5%", width:"90%", height: "500px"},
      avoidOverlappingGridLines: false
    };
    $timelineChart.chart = new google.visualization.Timeline($timelineChart.dom);
    dataTable.addColumn({ type: 'string', id: 'Name' });
    dataTable.addColumn({ type: 'number', id: 'Start' });
    dataTable.addColumn({ type: 'number', id: 'End' });
    var minValue = Number.POSITIVE_INFINITY;
    for (var i = 0; i < object.profile.length; i++) {
      var profile = object.profile[i];
      minValue = Math.min(profile.start, minValue);
      minValue = Math.min(profile.finish, minValue);
    };
    function normalize(value) {
      return value - minValue;
    };
    for (var i = 0; i < object.profile.length; i++) {
      var profile = object.profile[i];
      var row = [ profile.name , normalize(profile.start), normalize(profile.finish) ];
      dataTable.addRows([row]);
    }
    $asyncRender($timelineChart, dataTable, options);
  };
});

module.factory("$mainChart", function() {
  return {
    dom:   document.getElementById("chart-div"),
    chart: null
  };
});

module.factory("$timelineChart", function() {
  return {
    dom:   document.getElementById("timeline-div"),
    chart: null
  };
});

module.factory("$receive", function($mainChart, $timelineChart, $receiveSelect, $receiveProfile) {
  return function(object) {
    clearChart($mainChart);
    clearChart($timelineChart);
    $receiveSelect(object, $mainChart);
    $receiveProfile(object, $timelineChart);
  };
});

module.factory("$inputModel", function() {
  return {
    profile: false,
    query: "",
    renderType: "line"
  };
});

module.controller("mainCtrl", function(
  $location,
  $scope,
  $launchedQueries,
  $chartWaiting,
  $launchRequest,
  $inputModel,
  $profilingEnabled
  ) {

  // Store the $inputModel so that the view can change it through inputs.
  $scope.inputModel = $inputModel;

  $scope.embedLink = "";

  $scope.queryResult = "";

  function updateEmbed() {
    var url = $location.absUrl();
    var queryAt = url.indexOf("?");
    $scope.embedLink = $location.protocol() + "://" + $location.host() + ":" + $location.port()
      + "/embed" + url.substring(queryAt);
  }

  // Triggers when the button is clicked.
  $scope.onSubmitQuery = function() {
    $location.search("query", $inputModel.query);
    $location.search("renderType", $inputModel.renderType);
    $location.search("profile", $inputModel.profile.toString());
  };

  $scope.$on("$locationChangeSuccess", function() {
    // this triggers at least once (in the beginning).
    var queries = $location.search();
    $inputModel.query = queries["query"] || "";
    $inputModel.renderType = queries["renderType"] || "line";
    $inputModel.profile = queries["profile"] === "true";
    if ($inputModel.query) {
      $launchRequest({
        profile: $inputModel.profile,
        query:   $inputModel.query
      }).then(function(data) {
        $scope.queryResult = data;
      });
    }
  });

  // true if the output should be tabular.
  $scope.isTabular = function() {
    return ["describe all", "describe metrics", "describe"].indexOf($scope.queryResult.name) >= 0;
  };

  $scope.hasProfiling = $profilingEnabled.hasProfiling; // So that the HTML view can check for profiling

  $scope.screenState = function() {
    if ($launchedQueries.pos()) {
      return "loading";
    } else if ($launchedQueries.zero() && $chartWaiting.pos()) {
      return "rendering";
    } else if ($scope.queryResult && !$scope.queryResult.success) {
      return "error";
    } else {
      return "rendered";
    }
  };
  updateEmbed()
});

module.controller("embedCtrl", function($location, $scope, $launchedQueries, $chartWaiting, $launchRequest, $inputModel, $profilingEnabled){
  $scope.queryResult = "";
  $scope.screenState = function() {
    if ($launchedQueries.pos()) {
      return "loading";
    } else if ($launchedQueries.zero() && $chartWaiting.pos()) {
      return "rendering";
    } else if ($scope.queryResult && !$scope.queryResult.success) {
      return "error";
    } else {
      return "rendered";
    }
  };
  $scope.hasProfiling = $profilingEnabled.hasProfiling;

  var queries = $location.search();
  $inputModel.profile = false;
  $inputModel.query = "";
  $inputModel.renderType = queries["renderType"] || "line";
  $launchRequest({
    profile: false,
    query:   queries["query"] || ""
  }).then(function(data) {
    $scope.queryResult = data;
  });

  var url = $location.absUrl();
  var at = url.indexOf("?");
  $scope.metricsURL = $location.protocol() + "://" + $location.host() + ":" + $location.port()
    + "/ui" + url.substring(at);
});

function dateFromIndex(index, timerange) {
  return new Date(timerange.start + timerange.resolution * index);
}

function makeLabel(serieslist, series) {
  var label = serieslist.name + " ";
  for (var key in series.tagset) {
    label += key + ":" + series.tagset[key] + " ";
  }
  return label;
}
<commit_msg>re-hack the angular integration of Autocom<commit_after>// Copyright 2015 Square Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
"use strict";

var module = angular.module("main",[]);

google.load("visualization", "1.0", {"packages":["corechart", "timeline"]});

module.config(function($locationProvider) {
  $locationProvider.html5Mode(true);
});

module.factory("$google", function($rootScope) {
  // abstraction over the async loading of google libraries.
  // registered functions are either invoked immediately (if the library finished loading).
  // or queued in an array.
  var googleFunctions = [];
  var googleLoaded = false;
  google.setOnLoadCallback(function(){
    $rootScope.$apply(function() {
      googleLoaded = true;
      googleFunctions.map(function(googleFunction) {
        googleFunction();
      });
      googleFunctions.length = 0; // clear the array.
    });
  });

  return function(func) {
    if (googleLoaded) {
      func();
    } else {
      googleFunctions.push(func);
    }
  }
});

// Autocompletion setup (depends on $http to perform request to /token).
module.run(function($http) {
  if (!document.getElementById("query-input")) {
    return;
  }
  var autocom = new Autocom(document.getElementById("query-input"));
  var keywords = ["describe", "select", "from", "to", "resolution", "where", "all", "metrics", "sample", "by"];
  autocom.options = keywords;
  autocom.prefixPattern = "`[a-zA-Z_][a-zA-Z._-]*`?|[a-zA-Z_][a-zA-Z._-]*";
  autocom.continuePattern = "[a-zA-Z_`.-]";
  autocom.tooltipX = 0;
  autocom.tooltipY = 20;
  autocom.config.skipWord = 0.05; // make it (5x) cheaper to skip letters in a candidate word
  autocom.config.skipWordEnd = 0.01; // add a small cost to skipping ends of words, which benefits shorter candidates
  $http.get("/token").success(function(data, status, headers, config) {
    if (!data.success || !data.body) {
      return;
    }
    if (data.body.functions) {
      autocom.options = autocom.options.concat( data.body.functions );
    }
    if (data.body.metrics) {
      autocom.options = autocom.options.concat( data.body.metrics.map(function(name) {
        if (name.indexOf("-") >= 0) {
          return "`" + name + "`";
        }
        return name;
      }));
    }
  });
});

// A counter is an object with .inc() and .dec() methods,
// as well as .pos() and .zero() predicates.
function Counter() {
  var count = 0;
  this.inc = function() {
    count++;
  };
  this.dec = function() {
    count--;
  };
  this.pos = function() {
    return count > 0;
  };
  this.zero = function() {
    return count === 0;
  };
};
// A singleton Counter for launched queries.
module.factory("$launchedQueries", function() {
  return new Counter();
});
// A singleton Counter for waiting charts
module.factory("$chartWaiting", function() {
  return new Counter();
});

// A ticket booth will give you a ticket with .next()
// The ticket will be .valid() until another ticket has been asked for.
function TicketBooth() {
  var count = 0;
  function Ticket(n) {
    this.valid = function() {
      return n === count;
    }
  }
  this.next = function() {
    return new Ticket(++count);
  };
}
// A singleton ticketbooth for query counting
module.factory("$queryTicketBooth", function() {
  return new TicketBooth();
});

// chart-related functions
function clearChart(chart) {
  if (chart.chart !== null) {
    chart.chart.clearChart();
    chart.chart = null;
  }
};

module.factory("$asyncRender", function($chartWaiting, $rootScope) {
  return function(chart, dataTable, options) {
    google.visualization.events.addListener(chart.chart, "ready", function() {
      $rootScope.$apply(function() { $chartWaiting.dec(); });
    });
    setTimeout(function(){chart.chart.draw(dataTable, options)}, 1);
  };
});

module.factory("$launchRequest", function($google, $http, $receive, $queryTicketBooth, $launchedQueries, $q) {
  return function(params) {
    var resultPromise = $q.defer(); // Will be resolved with received value.
    var ticket = $queryTicketBooth.next();
    $launchedQueries.inc();
    var request = $http.get("/query", {
      params:params
    }).success(function(data, status, headers, config) {
      $launchedQueries.dec();
      if (ticket.valid()) {
        resultPromise.resolve(data);
        $google(function() { $receive(data) });
      }
    }).error(function(data, status, headers, config) {
      $launchedQueries.dec();
      if (ticket.valid()) {
        resultPromise.resolve(data);
        $google(function() { $receive(data) });
      }
    });
    return resultPromise.promise;
  };
});

module.factory("$receiveSelect", function(
      $asyncRender,
      $chartWaiting,
      $inputModel,
      $location,
      $mainChart
  ) {
  return function(object) {
    if (!(object && object.name == "select" && object.body && object.body.length && object.body[0].series && object.body[0].series.length && object.body[0].timerange)) {
      // invalid data.
      return;
    }
    $chartWaiting.inc();
    var series = [];
    var labels = ["Time"];
    var table = [labels];
    for (var i = 0; i < object.body.length; i++) {
      // Each of these is a list of series
      var serieslist = object.body[i];
      for (var j = 0; j < serieslist.series.length; j++) {
        var s = object.body[i].series[j];
        series.push(s);
        labels.push(makeLabel(serieslist, s));
      }
    }
    // Next, add each row.
    var timerange = object.body[0].timerange;
    for (var t = 0; t < series[0].values.length; t++) {
      var row = [dateFromIndex(t, timerange)];
      for (var i = 0; i < series.length; i++) {
        var cell = series[i].values[t];
        if (cell === null) {
          row.push(NaN);
        } else {
          row.push(cell);
        }
      }
      table.push(row);
    }
    var dataTable = google.visualization.arrayToDataTable(table);
    var options = {
      legend:    {position: "bottom"},
      title:     $location.search()["title"],
      chartArea: {left: "5%", width:"90%", top: "5%", height: "90%"}
    }
    if ($inputModel.renderType === "line") {
      $mainChart.chart = new google.visualization.LineChart($mainChart.dom);
    } else if ($inputModel.renderType === "area") {
      options.isStacked = true;
      $mainChart.chart = new google.visualization.AreaChart($mainChart.dom);
    }
    $asyncRender($mainChart, dataTable, options);
  };
});

module.factory("$profilingEnabled", function($inputModel) {
  return {
    hasProfiling: function(data) {
      return $inputModel.profile && data && data.profile;
    }
  };
});

module.factory("$receiveProfile", function($profilingEnabled, $chartWaiting, $asyncRender, $timelineChart) {
  return function(object) {
    if (!$profilingEnabled.hasProfiling(object)) {
      return
    }
    $chartWaiting.inc();
    var dataTable = new google.visualization.DataTable();
    var options = {
      chartArea: {left: "5%", width:"90%", height: "500px"},
      avoidOverlappingGridLines: false
    };
    $timelineChart.chart = new google.visualization.Timeline($timelineChart.dom);
    dataTable.addColumn({ type: 'string', id: 'Name' });
    dataTable.addColumn({ type: 'number', id: 'Start' });
    dataTable.addColumn({ type: 'number', id: 'End' });
    var minValue = Number.POSITIVE_INFINITY;
    for (var i = 0; i < object.profile.length; i++) {
      var profile = object.profile[i];
      minValue = Math.min(profile.start, minValue);
      minValue = Math.min(profile.finish, minValue);
    };
    function normalize(value) {
      return value - minValue;
    };
    for (var i = 0; i < object.profile.length; i++) {
      var profile = object.profile[i];
      var row = [ profile.name , normalize(profile.start), normalize(profile.finish) ];
      dataTable.addRows([row]);
    }
    $asyncRender($timelineChart, dataTable, options);
  };
});

module.factory("$mainChart", function() {
  return {
    dom:   document.getElementById("chart-div"),
    chart: null
  };
});

module.factory("$timelineChart", function() {
  return {
    dom:   document.getElementById("timeline-div"),
    chart: null
  };
});

module.factory("$receive", function($mainChart, $timelineChart, $receiveSelect, $receiveProfile) {
  return function(object) {
    clearChart($mainChart);
    clearChart($timelineChart);
    $receiveSelect(object, $mainChart);
    $receiveProfile(object, $timelineChart);
  };
});

module.factory("$inputModel", function() {
  return {
    profile: false,
    query: "",
    renderType: "line"
  };
});

module.controller("mainCtrl", function(
  $location,
  $scope,
  $launchedQueries,
  $chartWaiting,
  $launchRequest,
  $inputModel,
  $profilingEnabled
  ) {

  // Store the $inputModel so that the view can change it through inputs.
  $scope.inputModel = $inputModel;

  $scope.embedLink = "";

  $scope.queryResult = "";

  function updateEmbed() {
    var url = $location.absUrl();
    var queryAt = url.indexOf("?");
    $scope.embedLink = $location.protocol() + "://" + $location.host() + ":" + $location.port()
      + "/embed" + url.substring(queryAt);
  }

  // Triggers when the button is clicked.
  $scope.onSubmitQuery = function() {
    $inputModel.query = document.getElementById("query-input").value;
    $location.search("query", $inputModel.query);
    $location.search("renderType", $inputModel.renderType);
    $location.search("profile", $inputModel.profile.toString());
  };

  $scope.$on("$locationChangeSuccess", function() {
    // this triggers at least once (in the beginning).
    var queries = $location.search();
    $inputModel.query = queries["query"] || "";
    $inputModel.renderType = queries["renderType"] || "line";
    $inputModel.profile = queries["profile"] === "true";
    if ($inputModel.query) {
      $launchRequest({
        profile: $inputModel.profile,
        query:   $inputModel.query
      }).then(function(data) {
        $scope.queryResult = data;
      });
    }
  });

  // true if the output should be tabular.
  $scope.isTabular = function() {
    return ["describe all", "describe metrics", "describe"].indexOf($scope.queryResult.name) >= 0;
  };

  $scope.hasProfiling = $profilingEnabled.hasProfiling; // So that the HTML view can check for profiling

  $scope.screenState = function() {
    if ($launchedQueries.pos()) {
      return "loading";
    } else if ($launchedQueries.zero() && $chartWaiting.pos()) {
      return "rendering";
    } else if ($scope.queryResult && !$scope.queryResult.success) {
      return "error";
    } else {
      return "rendered";
    }
  };
  updateEmbed()
});

module.controller("embedCtrl", function($location, $scope, $launchedQueries, $chartWaiting, $launchRequest, $inputModel, $profilingEnabled){
  $scope.queryResult = "";
  $scope.screenState = function() {
    if ($launchedQueries.pos()) {
      return "loading";
    } else if ($launchedQueries.zero() && $chartWaiting.pos()) {
      return "rendering";
    } else if ($scope.queryResult && !$scope.queryResult.success) {
      return "error";
    } else {
      return "rendered";
    }
  };
  $scope.hasProfiling = $profilingEnabled.hasProfiling;

  var queries = $location.search();
  $inputModel.profile = false;
  $inputModel.query = "";
  $inputModel.renderType = queries["renderType"] || "line";
  $launchRequest({
    profile: false,
    query:   queries["query"] || ""
  }).then(function(data) {
    $scope.queryResult = data;
  });

  var url = $location.absUrl();
  var at = url.indexOf("?");
  $scope.metricsURL = $location.protocol() + "://" + $location.host() + ":" + $location.port()
    + "/ui" + url.substring(at);
});

function dateFromIndex(index, timerange) {
  return new Date(timerange.start + timerange.resolution * index);
}

function makeLabel(serieslist, series) {
  var label = serieslist.name + " ";
  for (var key in series.tagset) {
    label += key + ":" + series.tagset[key] + " ";
  }
  return label;
}
<|endoftext|>


<commit_before>/* eslint-disable import/no-unresolved, import/extensions */
import React, { PureComponent, PropTypes } from 'react';
import { View, StyleSheet, NativeModules, findNodeHandle } from 'react-native';
/* eslint-enable import/no-unresolved, import/extensions */

import IconToggle from '../IconToggle';
import isFunction from '../utils/isFunction';

const UIManager = NativeModules.UIManager;

const propTypes = {
    isSearchActive: PropTypes.bool.isRequired,
    searchValue: PropTypes.string.isRequired,
    searchable: PropTypes.object,
    style: PropTypes.object,
    size: PropTypes.number,
    rightElement: PropTypes.any,
    onRightElementPress: PropTypes.func,
    onSearchClearRequest: PropTypes.func.isRequired,
    onSearchPress: PropTypes.func.isRequired,
};
const defaultProps = {
    style: {},
};
const contextTypes = {
    uiTheme: PropTypes.object.isRequired,
};

function getStyles(props, context) {
    const { isSearchActive } = props;
    const { toolbar, toolbarSearchActive } = context.uiTheme;

    return {
        rightElementContainer: [
            toolbar.rightElementContainer,
            isSearchActive && toolbarSearchActive.rightElementContainer,
            props.style.rightElementContainer,
        ],
        rightElement: [
            toolbar.rightElement,
            isSearchActive && toolbarSearchActive.rightElement,
            props.style.rightElement,
        ],
    };
}

class RightElement extends PureComponent {
    onMenuPressed = (labels) => {
        const { onRightElementPress } = this.props;

        UIManager.showPopupMenu(
            findNodeHandle(this.menu),
            labels,
            () => {},
            (result, index) => {
                if (onRightElementPress) {
                    onRightElementPress({ action: 'menu', result, index });
                }
            },
        );
    };
    onSearchPressed = () => {
        const { onSearchPress } = this.props;

        if (isFunction(onSearchPress)) {
            onSearchPress();
        }
    };
    render() {
        const {
            isSearchActive,
            rightElement,
            onRightElementPress,
            searchable,
            size,
            searchValue,
            onSearchClearRequest,
        } = this.props;

        const styles = getStyles(this.props, this.context, this.state);

        // if there is no rightElement and searchable feature is off then we are sure on the right
        // is nothing
        if (!rightElement && !searchable) {
            return null;
        }

        let actionsMap = [];
        let result = [];

        if (rightElement) {
            if (typeof rightElement === 'string') {
                actionsMap.push(rightElement);
            } else if (Array.isArray(rightElement)) {
                actionsMap = rightElement;
            } else if (rightElement.actions) {
                actionsMap = rightElement.actions;
            }
        }

        const flattenRightElement = StyleSheet.flatten(styles.rightElement);

        if (actionsMap) {
            result = actionsMap.map((action, index) => {
                if (React.isValidElement(action)) {
                    return action;
                }

                return (
                    <IconToggle
                        key={index}
                        name={action}
                        color={flattenRightElement.color}
                        size={size}
                        style={flattenRightElement}
                        onPress={() =>
                            onRightElementPress && onRightElementPress({ action, index })
                        }
                    />
                );
            });
        }

        if (React.isValidElement(rightElement)) {
            result.push(React.cloneElement(rightElement, { key: 'customRightElement' }));
        }

        // if searchable feature is on and search is active with some text, then we show clear
        // button, to be able to clear text
        if (searchable) {
            if (isSearchActive && searchValue.length > 0) {
                result.push(
                    <IconToggle
                        key="searchClear"
                        name="clear"
                        color={flattenRightElement.color}
                        size={size}
                        style={flattenRightElement}
                        onPress={onSearchClearRequest}
                    />,
                );
            } else if (!isSearchActive) {
                result.push(
                    <IconToggle
                        key="searchIcon"
                        name="search"
                        color={flattenRightElement.color}
                        size={size}
                        style={flattenRightElement}
                        onPress={this.onSearchPressed}
                    />,
                );
            }
        }

        if (rightElement && rightElement.menu && !isSearchActive) {
            result.push(
                <View key="menuIcon">
                    {/* We need this view as an anchor for drop down menu. findNodeHandle can
                        find just view with width and height, even it needs backgroundColor :/
                    */}
                    <View
                        ref={(c) => { this.menu = c; }}
                        style={{
                            backgroundColor: 'transparent',
                            width: 1,
                            height: StyleSheet.hairlineWidth,
                        }}
                    />
                    <IconToggle
                        name="more-vert"
                        color={flattenRightElement.color}
                        size={size}
                        onPress={() => this.onMenuPressed(rightElement.menu.labels)}
                        style={flattenRightElement}
                    />
                </View>,
            );
        }

        return (
            <View style={styles.rightElementContainer}>
                {result}
            </View>
        );
    }
}

RightElement.propTypes = propTypes;
RightElement.defaultProps = defaultProps;
RightElement.contextTypes = contextTypes;

export default RightElement;
<commit_msg>Hide all other icons when search is active (#114)<commit_after>/* eslint-disable import/no-unresolved, import/extensions */
import React, { PureComponent, PropTypes } from 'react';
import { View, StyleSheet, NativeModules, findNodeHandle } from 'react-native';
/* eslint-enable import/no-unresolved, import/extensions */

import IconToggle from '../IconToggle';
import isFunction from '../utils/isFunction';

const UIManager = NativeModules.UIManager;

const propTypes = {
    isSearchActive: PropTypes.bool.isRequired,
    searchValue: PropTypes.string.isRequired,
    searchable: PropTypes.object,
    style: PropTypes.object,
    size: PropTypes.number,
    rightElement: PropTypes.any,
    onRightElementPress: PropTypes.func,
    onSearchClearRequest: PropTypes.func.isRequired,
    onSearchPress: PropTypes.func.isRequired,
};
const defaultProps = {
    style: {},
};
const contextTypes = {
    uiTheme: PropTypes.object.isRequired,
};

function getStyles(props, context) {
    const { isSearchActive } = props;
    const { toolbar, toolbarSearchActive } = context.uiTheme;

    return {
        rightElementContainer: [
            toolbar.rightElementContainer,
            isSearchActive && toolbarSearchActive.rightElementContainer,
            props.style.rightElementContainer,
        ],
        rightElement: [
            toolbar.rightElement,
            isSearchActive && toolbarSearchActive.rightElement,
            props.style.rightElement,
        ],
    };
}

class RightElement extends PureComponent {
    onMenuPressed = (labels) => {
        const { onRightElementPress } = this.props;

        UIManager.showPopupMenu(
            findNodeHandle(this.menu),
            labels,
            () => {},
            (result, index) => {
                if (onRightElementPress) {
                    onRightElementPress({ action: 'menu', result, index });
                }
            },
        );
    };
    onSearchPressed = () => {
        const { onSearchPress } = this.props;

        if (isFunction(onSearchPress)) {
            onSearchPress();
        }
    };
    render() {
        const {
            isSearchActive,
            rightElement,
            onRightElementPress,
            searchable,
            size,
            searchValue,
            onSearchClearRequest,
        } = this.props;

        const styles = getStyles(this.props, this.context, this.state);

        // if there is no rightElement and searchable feature is off then we are sure on the right
        // is nothing
        if (!rightElement && !searchable) {
            return null;
        }

        let actionsMap = [];
        let result = [];

        if (rightElement) {
            if (typeof rightElement === 'string') {
                actionsMap.push(rightElement);
            } else if (Array.isArray(rightElement)) {
                actionsMap = rightElement;
            } else if (rightElement.actions) {
                actionsMap = rightElement.actions;
            }
        }

        const flattenRightElement = StyleSheet.flatten(styles.rightElement);

        if (actionsMap) {
            result = actionsMap.map((action, index) => {
                if (React.isValidElement(action)) {
                    return action;
                }

                return (
                    <IconToggle
                        key={index}
                        name={action}
                        color={flattenRightElement.color}
                        size={size}
                        style={flattenRightElement}
                        onPress={() =>
                            onRightElementPress && onRightElementPress({ action, index })
                        }
                    />
                );
            });
        }

        if (React.isValidElement(rightElement)) {
            result.push(React.cloneElement(rightElement, { key: 'customRightElement' }));
        }

        // if searchable feature is on and search is active with some text, then we show clear
        // button, to be able to clear text
        if (searchable) {
            if (isSearchActive) {
                // clear result to hide other icons
                result = [];

                if (searchValue.length > 0) {
                    result.push(
                        <IconToggle
                            key="searchClear"
                            name="clear"
                            color={flattenRightElement.color}
                            size={size}
                            style={flattenRightElement}
                            onPress={onSearchClearRequest}
                        />,
                    );
                }
            } else {
                result.push(
                    <IconToggle
                        key="searchIcon"
                        name="search"
                        color={flattenRightElement.color}
                        size={size}
                        style={flattenRightElement}
                        onPress={this.onSearchPressed}
                    />,
                );
            }
        }

        if (rightElement && rightElement.menu && !isSearchActive) {
            result.push(
                <View key="menuIcon">
                    {/* We need this view as an anchor for drop down menu. findNodeHandle can
                        find just view with width and height, even it needs backgroundColor :/
                    */}
                    <View
                        ref={(c) => { this.menu = c; }}
                        style={{
                            backgroundColor: 'transparent',
                            width: 1,
                            height: StyleSheet.hairlineWidth,
                        }}
                    />
                    <IconToggle
                        name="more-vert"
                        color={flattenRightElement.color}
                        size={size}
                        onPress={() => this.onMenuPressed(rightElement.menu.labels)}
                        style={flattenRightElement}
                    />
                </View>,
            );
        }

        return (
            <View style={styles.rightElementContainer}>
                {result}
            </View>
        );
    }
}

RightElement.propTypes = propTypes;
RightElement.defaultProps = defaultProps;
RightElement.contextTypes = contextTypes;

export default RightElement;
<|endoftext|>