<commit_before>import * as THREE from 'three';
import { MeshoptDecoder } from 'three/examples/jsm/libs/meshopt_decoder.module.js';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
import { FullScreenQuad } from 'three/examples/jsm/postprocessing/Pass.js';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import { GUI } from 'three/examples/jsm/libs/lil-gui.module.min.js';
import Stats from 'stats.js';
import { GenerateMeshBVHWorker } from '../src/workers/GenerateMeshBVHWorker.js';
import { StaticGeometryGenerator } from '..';
import { GenerateSDFMaterial } from './utils/GenerateSDFMaterial.js';

const params = {

	gpuGeneration: true,
	size: 50,
	margin: 0.1,
	regenerate: () => updateSDF(),

};

let renderer, camera, scene, knot, clock, gui, helper, group, stats;
let outputContainer, loadContainer, loadBar, loadText, bvh, geometry, sdfTex, sdfPass;
let bvhGenerationWorker;

init();
render();

function init() {

	const bgColor = 0x111111;

	outputContainer = document.getElementById( 'output' );
	loadContainer = document.getElementById( 'loading-container' );
	loadBar = document.querySelector( '#loading-container .bar' );
	loadText = document.querySelector( '#loading-container .text' );

	// renderer setup
	renderer = new THREE.WebGLRenderer( { antialias: true } );
	renderer.setPixelRatio( window.devicePixelRatio );
	renderer.setSize( window.innerWidth, window.innerHeight );
	renderer.setClearColor( bgColor, 1 );
	renderer.outputEncoding = THREE.sRGBEncoding;
	document.body.appendChild( renderer.domElement );

	// scene setup
	scene = new THREE.Scene();
	scene.fog = new THREE.Fog( 0x111111, 20, 60 );

	const light = new THREE.DirectionalLight( 0xffffff, 1 );
	light.position.set( 1, 1, 1 );
	scene.add( light );
	scene.add( new THREE.AmbientLight( 0xffffff, 0.2 ) );

	// camera setup
	camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 50 );
	camera.position.set( 0, 0, 4 );
	camera.far = 100;
	camera.updateProjectionMatrix();

	new OrbitControls( camera, renderer.domElement );

	clock = new THREE.Clock();

	// stats setup
	stats = new Stats();
	document.body.appendChild( stats.dom );

	sdfPass = new FullScreenQuad( new GenerateSDFMaterial() );

	bvhGenerationWorker = new GenerateMeshBVHWorker();

	new GLTFLoader()
		.setMeshoptDecoder( MeshoptDecoder )
		.loadAsync( 'https://raw.githubusercontent.com/gkjohnson/3d-demo-data/main/models/vino-bike/scene.gltf' )
		.then( gltf => {

			const staticGen = new StaticGeometryGenerator( gltf.scene );
			staticGen.attributes = [ 'position', 'normal' ];
			staticGen.useGroups = false;

			geometry = staticGen.generate().center();

			return bvhGenerationWorker.generate( geometry, { maxLeafTris: 1 } );

		} )
		.then( result => {

			bvh = result;

			const mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial() );
			scene.add( mesh );

			updateSDF();

		} );

	gui = new GUI();

	const generation = gui.addFolder( 'generation' );
	generation.add( params, 'gpuGeneration' );
	generation.add( params, 'size', 10, 200, 1 );
	generation.add( params, 'margin', 0, 1 );
	generation.add( params, 'regenerate' );

	window.addEventListener( 'resize', function () {

		camera.aspect = window.innerWidth / window.innerHeight;
		camera.updateProjectionMatrix();

		renderer.setSize( window.innerWidth, window.innerHeight );

	}, false );

}

function updateSDF() {

	const dim = params.size;
	const matrix = new THREE.Matrix4();
	const center = new THREE.Vector3();
	const quat = new THREE.Quaternion();
	const scale = new THREE.Vector3();

	geometry.boundingBox.getCenter( center );
	scale.subVectors( geometry.boundingBox.max, geometry.boundingBox.min );
	scale.x += params.margin;
	scale.y += params.margin;
	scale.z += params.margin;
	matrix.compose( center, quat, scale ).invert();

	if ( sdfTex ) {

		sdfTex.dispose();

	}

	const pxWidth = 1 / dim;
	const halfWidth = 0.5 * pxWidth;

	const startTime = window.performance.now();
	if ( params.gpuGeneration ) {

		sdfTex = new THREE.WebGL3DRenderTarget( dim, dim, dim );
		sdfTex.texture.format = THREE.RedFormat;
		sdfTex.texture.type = THREE.FloatType;
		sdfTex.texture.minFilter = THREE.LinearFilter;
		sdfTex.texture.magFilter = THREE.LinearFilter;

		sdfPass.material.uniforms.bvh.value.updateFrom( bvh );
		sdfPass.material.uniforms.matrix.value.copy( matrix );

		for ( let i = 0; i < dim; i ++ ) {

			sdfPass.material.uniforms.zValue.value = i * pxWidth + halfWidth;

			renderer.setRenderTarget( sdfTex, i );
			sdfPass.render( renderer );

		}

		// initiate readback to get a rough estimate of time taken to generate the sdf
		renderer.readRenderTargetPixels( sdfTex, 0, 0, 1, 1, new Float32Array( 4 ) );
		renderer.setRenderTarget( null );

	} else {

		sdfTex = new THREE.Data3DTexture( new Float32Array( dim ** 3 ), dim, dim, dim );
		sdfTex.format = THREE.RedFormat;
		sdfTex.type = THREE.FloatType;
		sdfTex.minFilter = THREE.LinearFilter;
		sdfTex.magFilter = THREE.LinearFilter;

		const point = new THREE.Vector3();
		for ( let x = 0; x < dim; x ++ ) {

			for ( let y = 0; y < dim; y ++ ) {

				for ( let z = 0; z < dim; z ++ ) {

					point.set(
						halfWidth + x * pxWidth - 0.5,
						halfWidth + y * pxWidth - 0.5,
						halfWidth + z * pxWidth - 0.5,
					).applyMatrix4( matrix );

					const index = x + y * dim + z * dim * dim;
					sdfTex.image.data[ index ] = bvh.closestPointToPoint( point );

				}

			}

		}

	}

	const delta = window.performance.now() - startTime;
	outputContainer.innerText = `${ delta.toFixed( 2 ) }ms`;

}

function render() {

	stats.update();
	requestAnimationFrame( render );

	if ( helper ) {

		helper.visible = params.displayHelper;

	}

	renderer.render( scene, camera );

}
<commit_msg>make a signed field<commit_after>import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
import { FullScreenQuad } from 'three/examples/jsm/postprocessing/Pass.js';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import { GUI } from 'three/examples/jsm/libs/lil-gui.module.min.js';
import Stats from 'stats.js';
import { GenerateMeshBVHWorker } from '../src/workers/GenerateMeshBVHWorker.js';
import { StaticGeometryGenerator } from '..';
import { GenerateSDFMaterial } from './utils/GenerateSDFMaterial.js';

const params = {

	gpuGeneration: true,
	size: 50,
	margin: 0.1,
	regenerate: () => updateSDF(),

};

let renderer, camera, scene, knot, clock, gui, helper, group, stats;
let outputContainer, loadContainer, loadBar, loadText, bvh, geometry, sdfTex, sdfPass;
let bvhGenerationWorker;

init();
render();

function init() {

	const bgColor = 0x111111;

	outputContainer = document.getElementById( 'output' );
	loadContainer = document.getElementById( 'loading-container' );
	loadBar = document.querySelector( '#loading-container .bar' );
	loadText = document.querySelector( '#loading-container .text' );

	// renderer setup
	renderer = new THREE.WebGLRenderer( { antialias: true } );
	renderer.setPixelRatio( window.devicePixelRatio );
	renderer.setSize( window.innerWidth, window.innerHeight );
	renderer.setClearColor( bgColor, 1 );
	renderer.outputEncoding = THREE.sRGBEncoding;
	document.body.appendChild( renderer.domElement );

	// scene setup
	scene = new THREE.Scene();
	scene.fog = new THREE.Fog( 0x111111, 20, 60 );

	const light = new THREE.DirectionalLight( 0xffffff, 1 );
	light.position.set( 1, 1, 1 );
	scene.add( light );
	scene.add( new THREE.AmbientLight( 0xffffff, 0.2 ) );

	// camera setup
	camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 50 );
	camera.position.set( 0, 0, 4 );
	camera.far = 100;
	camera.updateProjectionMatrix();

	new OrbitControls( camera, renderer.domElement );

	clock = new THREE.Clock();

	// stats setup
	stats = new Stats();
	document.body.appendChild( stats.dom );

	sdfPass = new FullScreenQuad( new GenerateSDFMaterial() );

	bvhGenerationWorker = new GenerateMeshBVHWorker();

	new GLTFLoader()
		.loadAsync( 'https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/Suzanne/glTF/Suzanne.gltf' )
		.then( gltf => {

			const staticGen = new StaticGeometryGenerator( gltf.scene );
			staticGen.attributes = [ 'position', 'normal' ];
			staticGen.useGroups = false;

			geometry = staticGen.generate().center();

			return bvhGenerationWorker.generate( geometry, { maxLeafTris: 1 } );

		} )
		.then( result => {

			bvh = result;

			const mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial() );
			scene.add( mesh );

			updateSDF();

		} );

	gui = new GUI();

	const generation = gui.addFolder( 'generation' );
	generation.add( params, 'gpuGeneration' );
	generation.add( params, 'size', 10, 200, 1 );
	generation.add( params, 'margin', 0, 1 );
	generation.add( params, 'regenerate' );

	window.addEventListener( 'resize', function () {

		camera.aspect = window.innerWidth / window.innerHeight;
		camera.updateProjectionMatrix();

		renderer.setSize( window.innerWidth, window.innerHeight );

	}, false );

}

function updateSDF() {

	const dim = params.size;
	const matrix = new THREE.Matrix4();
	const center = new THREE.Vector3();
	const quat = new THREE.Quaternion();
	const scale = new THREE.Vector3();

	geometry.boundingBox.getCenter( center );
	scale.subVectors( geometry.boundingBox.max, geometry.boundingBox.min );
	scale.x += params.margin;
	scale.y += params.margin;
	scale.z += params.margin;
	matrix.compose( center, quat, scale ).invert();

	if ( sdfTex ) {

		sdfTex.dispose();

	}

	const pxWidth = 1 / dim;
	const halfWidth = 0.5 * pxWidth;

	const startTime = window.performance.now();
	if ( params.gpuGeneration ) {

		sdfTex = new THREE.WebGL3DRenderTarget( dim, dim, dim );
		sdfTex.texture.format = THREE.RedFormat;
		sdfTex.texture.type = THREE.FloatType;
		sdfTex.texture.minFilter = THREE.LinearFilter;
		sdfTex.texture.magFilter = THREE.LinearFilter;

		sdfPass.material.uniforms.bvh.value.updateFrom( bvh );
		sdfPass.material.uniforms.matrix.value.copy( matrix );

		for ( let i = 0; i < dim; i ++ ) {

			sdfPass.material.uniforms.zValue.value = i * pxWidth + halfWidth;

			renderer.setRenderTarget( sdfTex, i );
			sdfPass.render( renderer );

		}

		// initiate readback to get a rough estimate of time taken to generate the sdf
		renderer.readRenderTargetPixels( sdfTex, 0, 0, 1, 1, new Float32Array( 4 ) );
		renderer.setRenderTarget( null );

	} else {

		sdfTex = new THREE.Data3DTexture( new Float32Array( dim ** 3 ), dim, dim, dim );
		sdfTex.format = THREE.RedFormat;
		sdfTex.type = THREE.FloatType;
		sdfTex.minFilter = THREE.LinearFilter;
		sdfTex.magFilter = THREE.LinearFilter;

		const posAttr = geometry.attributes.position;
		const indexAttr = geometry.index;
		const point = new THREE.Vector3();
		const normal = new THREE.Vector3();
		const delta = new THREE.Vector3();
		const target = {};
		const tri = new THREE.Triangle();
		for ( let x = 0; x < dim; x ++ ) {

			for ( let y = 0; y < dim; y ++ ) {

				for ( let z = 0; z < dim; z ++ ) {

					point.set(
						halfWidth + x * pxWidth - 0.5,
						halfWidth + y * pxWidth - 0.5,
						halfWidth + z * pxWidth - 0.5,
					).applyMatrix4( matrix );

					const index = x + y * dim + z * dim * dim;
					const dist = bvh.closestPointToPoint( point, target );

					// get the face normal to determine if the distance should be positive or negative
					const faceIndex = target.faceIndex;
					const i0 = indexAttr.getX( faceIndex * 3 + 0 );
					const i1 = indexAttr.getX( faceIndex * 3 + 1 );
					const i2 = indexAttr.getX( faceIndex * 3 + 2 );
					tri.setFromAttributeAndIndices( posAttr, i0, i1, i2 );
					tri.getNormal( normal );
					delta.subVectors( target.point, point );

					sdfTex.image.data[ index ] = normal.dot( delta ) > 0.0 ? - dist : dist;

				}

			}

		}

	}

	const delta = window.performance.now() - startTime;
	outputContainer.innerText = `${ delta.toFixed( 2 ) }ms`;

}

function render() {

	stats.update();
	requestAnimationFrame( render );

	if ( helper ) {

		helper.visible = params.displayHelper;

	}

	renderer.render( scene, camera );

}
<|endoftext|>


<commit_before>import React from 'react';
import { storiesOf, action, addDecorator } from '@kadira/storybook';

import { muiTheme } from './../../src/';

import CardExampleControlled from '../CardExampleControlled.jsx';
import RaisedButtonExampleSimple from '../RaisedButtonExampleSimple.jsx';
import DatePickerExampleSimple from '../DatePickerExampleSimple.jsx';

import greyTheme from './greyTheme.json';
import SupportProject from '../SupportProject.jsx';
import MaterialAppExampleCard from '../LoremMaterial/blankMaterialAppExampleCard.jsx';
import MaterialAppExampleProgress from '../LoremMaterial/blankMaterialAppExampleProgress.jsx';
import MaterialAirlineBooking from '../LoremMaterial/MaterialAirlineBooking.jsx';
import MaterialStepper from '../LoremMaterial/MaterialStepper.jsx';
import MaterialContactList from '../LoremMaterial/MaterialContactList.jsx';
import MaterialLoginPage from '../LoremMaterial/MaterialLoginPage.jsx';

import PumpkinHead from '../LoremMaterial/pumpkinHead.jsx';
import pumOrigTheme from '../LoremMaterial/pumOrigTheme.json';
import pumFullTheme from '../LoremMaterial/pumFullTheme.json';
import pumAltTheme from '../LoremMaterial/pumAltTheme.json';

// Additional user themes
import halloweentheme from '../LoremMaterial/halloweentheme.json';
import pumAlt2Theme from '../LoremMaterial/pumAlt2Theme.json';
const userTemes = [pumAlt2Theme, halloweentheme];

import fifteen from 'fifteen-kilos';

const SHOW_SUPPORT = true;

/** note: decorators
 *  You can add decorator globally:
 *  addDecorator(muiTheme(greyTheme));
 *  You can pass a single object or an array of themes
 */
addDecorator(muiTheme([
    pumOrigTheme,
    pumFullTheme,
    pumAltTheme,
    'Light Theme',
    'Dark Theme',
    greyTheme,
    ...userTemes,
]));

storiesOf('Helloween', module)
    .addDecorator((story) => (

          {story()}

    ))
    .add('Pumpkin Head', () => (
      <PumpkinHead />
    ));

storiesOf('Material-UI', module)
    .addDecorator((story) => (

          {story()}
          {SHOW_SUPPORT ? <SupportProject /> : null}

    ))
    .add('Card Example Controlled', () => (
      <CardExampleControlled />
    ))
    .add('Raised Button Example Simple', () => (
      <RaisedButtonExampleSimple />
    ))
    .add('Date Picker Example Simple', () => (
      <DatePickerExampleSimple />
    ));

storiesOf('Material App', module)
    .add('Hactoberfest issues:', () => (
      <MaterialAppExampleCard />
    ))
    .add('Airline Booking', () => (
      <MaterialAirlineBooking />
    ))
    .add('Contact List', () => (
      <MaterialContactList />
    ))
    .add('Stepper', () => (
      <MaterialStepper />
    ))
    .add('Login page', () => (
      <MaterialLoginPage />
    ))
    .add('blank page', () => (
      <MaterialAppExampleProgress />
    ));

storiesOf('Compatible Projects', module)
    .add('description', () => (
      <ReactTemesProvider>

Here is a list of compatible projects:

fifteen-kilos github

      </ReactTemesProvider>
    ))
    .add('fifteen-kilos', () => (
      <ReactTemesProvider>
        {fifteen}
      </ReactTemesProvider>
    ));

storiesOf('Without addon', module)
    .add('Text', () => (

Lorem ipsum

    ));

function ReactTemesProvider(props, context) {
    const { palette } = context.muiTheme;
    const themeProps = {
        style: { color: palette.textColor },
    };
    return (

        {props.children}

    );
}
ReactTemesProvider.propTypes = {
    children: React.PropTypes.element,
};
ReactTemesProvider.contextTypes = {
    muiTheme: React.PropTypes.object.isRequired,
};
<commit_msg>publish new helloween themes<commit_after>import React from 'react';
import { storiesOf, action, addDecorator } from '@kadira/storybook';

import { muiTheme } from './../../src/';

import CardExampleControlled from '../CardExampleControlled.jsx';
import RaisedButtonExampleSimple from '../RaisedButtonExampleSimple.jsx';
import DatePickerExampleSimple from '../DatePickerExampleSimple.jsx';

import greyTheme from './greyTheme.json';
import SupportProject from '../SupportProject.jsx';
import MaterialAppExampleCard from '../LoremMaterial/blankMaterialAppExampleCard.jsx';
import MaterialAppExampleProgress from '../LoremMaterial/blankMaterialAppExampleProgress.jsx';
import MaterialAirlineBooking from '../LoremMaterial/MaterialAirlineBooking.jsx';
import MaterialStepper from '../LoremMaterial/MaterialStepper.jsx';
import MaterialContactList from '../LoremMaterial/MaterialContactList.jsx';
import MaterialLoginPage from '../LoremMaterial/MaterialLoginPage.jsx';

import PumpkinHead from '../LoremMaterial/pumpkinHead.jsx';
import pumOrigTheme from '../LoremMaterial/pumOrigTheme.json';
import pumFullTheme from '../LoremMaterial/pumFullTheme.json';
import pumAltTheme from '../LoremMaterial/pumAltTheme.json';

// Additional user themes
import halloweentheme from '../LoremMaterial/halloweentheme.json';
import pumAlt2Theme from '../LoremMaterial/pumAlt2Theme.json';
import pumHead from '../LoremMaterial/pumHead.json';
const userTemes = [pumHead, pumAlt2Theme, halloweentheme];

import fifteen from 'fifteen-kilos';

const SHOW_SUPPORT = true;

/** note: decorators
 *  You can add decorator globally:
 *  addDecorator(muiTheme(greyTheme));
 *  You can pass a single object or an array of themes
 */
addDecorator(muiTheme([
    pumOrigTheme,
    pumFullTheme,
    pumAltTheme,
    'Light Theme',
    'Dark Theme',
    greyTheme,
    ...userTemes,
]));

storiesOf('Helloween', module)
    .addDecorator((story) => (

          {story()}

    ))
    .add('Pumpkin Head', () => (
      <PumpkinHead />
    ));

storiesOf('Material-UI', module)
    .addDecorator((story) => (

          {story()}
          {SHOW_SUPPORT ? <SupportProject /> : null}

    ))
    .add('Card Example Controlled', () => (
      <CardExampleControlled />
    ))
    .add('Raised Button Example Simple', () => (
      <RaisedButtonExampleSimple />
    ))
    .add('Date Picker Example Simple', () => (
      <DatePickerExampleSimple />
    ));

storiesOf('Material App', module)
    .add('Hactoberfest issues:', () => (
      <MaterialAppExampleCard />
    ))
    .add('Airline Booking', () => (
      <MaterialAirlineBooking />
    ))
    .add('Contact List', () => (
      <MaterialContactList />
    ))
    .add('Stepper', () => (
      <MaterialStepper />
    ))
    .add('Login page', () => (
      <MaterialLoginPage />
    ))
    .add('blank page', () => (
      <MaterialAppExampleProgress />
    ));

storiesOf('Compatible Projects', module)
    .add('description', () => (
      <ReactTemesProvider>

Here is a list of compatible projects:

fifteen-kilos github

      </ReactTemesProvider>
    ))
    .add('fifteen-kilos', () => (
      <ReactTemesProvider>
        {fifteen}
      </ReactTemesProvider>
    ));

storiesOf('Without addon', module)
    .add('Text', () => (

Lorem ipsum

    ));

function ReactTemesProvider(props, context) {
    const { palette } = context.muiTheme;
    const themeProps = {
        style: { color: palette.textColor },
    };
    return (

        {props.children}

    );
}
ReactTemesProvider.propTypes = {
    children: React.PropTypes.element,
};
ReactTemesProvider.contextTypes = {
    muiTheme: React.PropTypes.object.isRequired,
};
<|endoftext|>


<commit_before>Clock.bpm = 140
verb = Bus2('spaceverb')
delay = Bus2('delay.1/6')

drums = EDrums()
drums.cowbell.connect( verb, .25 )
drums.clap.connect( verb, .025 )
drums.tidal( 'kd <cp [cp kd] cp cb> <kd*2 [kd ~ kd ch]> <cp [cp kd] kd*2>' )

hat = Hat({ gain:.075 })
hat.trigger.seq( [1,.5], 1/16 )
hat.decay = gen( .02 + cycle( beats(16) * 4 ) * .0125 )
hat.fx.add( Distortion({ pregain:100, postgain:.1 }) )

bass = Synth('acidBass2', { saturation:20, gain:.3 })
  .connect( delay, .25 )
  .connect( verb, .125 )

bass.note.seq( [0,0,0,7,0,14,2,14], Euclid(7,16)  )
bass.glide.seq( [1,2500,1,1,5000,1], 1/8 )
bass.octave.seq( [-3,-2,-3,-1,-3,-3], [1/4,1/2] )

kick = Kick('deep')
kick.trigger.seq( 1,1/4 )

pad = PolySynth('rhodes', { decay:8, gain:.15 })
pad.fx[0].disconnect()
pad.fx[0].connect( verb, 1 )
pad.chord.seq([[0,2,4,6], [1,2,4,7]], 4 )

Theory.degree.seq( ['i','-iv','-v'], [8,4,4] )
<commit_msg>updated with bassline / misc changes from fasttriggerfish<commit_after>// created by fasttriggerfish and thecharlie

Clock.bpm = 120
Theory.root = 'd#4'
Theory.mode = 'dorian'

verb  = Bus2( 'spaceverb' )
delay = Bus2( 'delay.1/6' )

bass = Synth('acidBass2', { saturation:20, gain:.3 })
  .connect( delay, .25 )
  .connect( verb, .125 )

bass.note.tidal( '0 0 0 0 4 6 0 ~ 0 ~ 7 -7 ~ 0 -7 0' )
bass.decay.seq( [1/32, 1/16], 1/2 )
bass.glide.seq( [1,1,100,100 ], 1/4 )
bass.Q = gen( 0.5 + cycle(0.1) * 0.49 )
bass.cutoff = gen( 0.5 + cycle(0.07) * 0.45 )

drums = Drums()
drums.fx.add( Distortion({ pregain:1.5, postgain:1 }) )

drums.tidal('kd {kd, sd} kd {kd, sd}')

hat = Hat({ gain:.075 })
hat.trigger.seq( [1,.5], [1/8, 1/16] )
hat.decay = gen( .02 + cycle( beats(16) * 4 ) * .0125 )
hat.fx.add( Distortion({ pregain:100, postgain:.1 }) )

pad = PolySynth('rhodes', { decay:8, gain:.15 })
pad.fx[0].connect( Main, .125)
pad.fx[0].connect( verb, 1 )
pad.chord.seq([[0,2,4,6], [1,2,4,7]], 4 )

Theory.degree.seq( ['i','-iv','-V'], [8,4,4] )
<|endoftext|>


<commit_before>/*global ServiceRegistry, ProjectConfig, ares, ComponentsRegistry, async, enyo, Phonegap */
/**
 * This kind is the top kind of project handling. It contains:
 * - The project list
 * - the interface towards the user's file (harmonia)
 * - Popups to manage projects (create, scan, error ...)
 */
enyo.kind({
	name: "ProjectView",
	kind: "FittableColumns",
	classes: "enyo-unselectable",
	debug: true,
	published: {
		// harcoded until ENYO-2755 is fixed
		panelIndex: 0
	},
	components: [
		{kind: "ProjectList",
			onModifySettings: "modifySettingsAction",
			onCreateProject: "createProjectAction",
			onOpenProject: "openProjectAction",
			onSearchProjects: "searchProjectsAction",
			onDuplicateProject: "duplicateProjectAction",
			onProjectRemoved: "projectRemoved",
			name: "projectList"
		},
		{kind: "ProjectWizardCreate", canGenerate: false, name: "projectWizardCreate", classes:"ares-masked-content-popup"},
		{kind: "ProjectWizardScan", canGenerate: false, name: "projectWizardScan", classes:"ares-masked-content-popup"},
		{kind: "ProjectWizardModify", canGenerate: false,
			name: "projectWizardModify"
		},
		{kind: "ProjectWizardCopy", name: "projectWizardCopy", classes:"ares-masked-content-popup"}
	],
	handlers: {
		onAddProjectInList: "addProjectInList",
		onPreview: "previewAction",
		onBuild: "buildAction",
		onInstall: "installAction",
		onRun: "runAction",
		onRunDebug: "runDebugAction"
	},
	events: {
		onHideWaitPopup: "",
		onShowWaitPopup: "",
		onError: "",
		onProjectSelected: "",
		onProjectSave: "",
		onRegisterMe: ""
	},
	create: function() {
		ares.setupTraceLogger(this);
		this.inherited(arguments);
		this.doRegisterMe({name:"projectView", reference:this});
	},
	/**
	 * Refresh the {ProjectView} (if relevant), following a change of the given file
	 * @param {Object} toSelectId. Asynchronous
	 */
	refreshFileTree: function(toSelectId,next) {
		ComponentsRegistry.getComponent("harmonia").refreshFileTree(toSelectId,next);
	},
	searchProjectsAction: function(inSender, inEvent) {
		this.$.projectWizardScan.setHeaderText('Select a folder hierarchy');
		this.$.projectWizardScan.setRecurse(true);
		this.$.projectWizardScan.show();
		return true; //Stop event propagation
	},
	openProjectAction: function(inSender, inEvent) {
		this.$.projectWizardScan.setHeaderText('Select an existing Ares application folder (contains a project.json file)');
		this.$.projectWizardScan.setRecurse(false);
		this.$.projectWizardScan.show();
		return true; //Stop event propagation
	},
	duplicateProjectAction: function(inSender, inEvent) {
		if(!this.currentProject()){
			this.doError({msg: "Please project list select item."});
			return false;
		}

		this.$.projectWizardCopy.start( this.currentProject() );
		return true; //Stop event propagation
	},
	createProjectAction: function(inSender, inEvent) {
		this.$.projectWizardCreate.start();
		return true; //Stop event propagation
	},
	modifySettingsAction: function(inSender, inEvent) {
		this.$.projectWizardModify.start( this.currentProject() );

		return true; //Stop event propagation
	},

	addProjectInList: function(inSender, inEvent) {
		this.doHideWaitPopup();
		try {
			// Add an entry into the project list
			this.$.projectList.addProject(inEvent.name, inEvent.folderId, inEvent.service, inEvent.dontSelect);
		} catch(e) {
			var msg = e.toString();
			this.error(msg);
			this.doError({msg: msg});
			return false;
		}
		return true; //Stop event propagation
	},
	currentProject: function() {
		return this.$.projectList.getSelectedProject() ;
	},
	/**
	 *
	 * @param {Object} project
	 * @param {Function} next
	 */
	setupProjectConfig: function(project, next) {
		ares.assertCb(next);

		var pname = project.getName();
		if ( this.currentProject() && pname === this.currentProject().getName() ) {
			this.trace("skip setup of already selected project" + pname);
			next();
			return;
		}

		// FIXME: temporary hack to create config.json on the
		// fly if needed... would be better to create/load it
		// when the workspace is loaded & when a new project
		// is created that would save per-click HTTP traffic
		// to the FileSystemService.
		var self = this;
		var config = new ProjectConfig();
		this.trace("setup project config init on "+ project.getName() );
		var initData = {
			service: project.getService(),
			folderId: project.getFolderId()
		};

		async.series(
			[
				// read default config from remote server
				config.init.bind(config, initData) ,
				function (next) {
					self.trace("ProjectView: setup project set config on "+ project.getName() );
					project.setConfig(config);

					self.initializeDownloadStatus(project, config.data.providers.phonegap.enabled);
					self.initializeValidPgbConf(project, config.data.providers.phonegap.enabled);
					next();
				},
				function (next) {
					// Pass service definition & configuration to Harmonia
					// & consequently to HermesFileTree
					self.trace("ProjectView: setup project on harmonia "+ project.getName() );
					ComponentsRegistry.getComponent("harmonia").setProject(project, next);
				}

			],
			function (err) {
				self.trace("ProjectView: setup project config done on " + project.getName() + " err is ",err );
				if (err) {
					self.doError({msg: err.toString(), err: err});
				}
				next(err);
			}
		);
	},
	/**
	 * Initialize the attribute "downloadStatus" of the project
	 *
	 * this attribute is used only by Phonegap Build.
	 * @private
	 */
	initializeDownloadStatus: function(inProject, inPhonegapEnabled) {
		if (inProject.getDownloadStatus() === undefined && inPhonegapEnabled) {
			var downloadStatus = {};
			var index = 0;

			for (index in Phonegap.UIConfiguration.platformDrawersContent) {
				downloadStatus[Phonegap.UIConfiguration.platformDrawersContent[index].id] = "Ready for download";
			}

			inProject.setDownloadStatus(downloadStatus);
		}
	},

	initializeValidPgbConf: function(inProject, inPhonegapEnabled) {
		if (inProject.getValidPgbConf() === undefined && inPhonegapEnabled) {
			var pgbValidation = {};
			var pgbUiData = Phonegap.UIConfiguration.commonDrawersContent.concat(Phonegap.UIConfiguration.platformDrawersContent);
			var index =0;

			for (index in pgbUiData) {
				//The creation of the pgbValidation drawer attribute and its initialization are done in the same time.
				pgbValidation[pgbUiData[index].id] = {};

				for (var i=0, maxLength = pgbUiData[index].rows.length; i<maxLength; i++) {
					//The creation of the pgbValidation row attribute and its initialization are done in the same time.
					pgbValidation[pgbUiData[index].id][pgbUiData[index].rows[i].name] = true;
				}
				pgbValidation[pgbUiData[index].id]["validDrawer"] = true;
			}

			inProject.setValidPgbConf(pgbValidation);
		}
	},

	projectRemoved: function(inSender, inEvent) {
		ComponentsRegistry.getComponent("harmonia").setProject(null, ares.noNext);
	},
	/**
	 * Event handler: handle build project action (select provider & run action)
	 * @param {enyo.Component} inSender
	 * @param {Object} inEvent
	 * @property inEvent {Ares.Model.Project} project
	 * @private
	 */
	buildAction: function(inSender, inEvent) {
		var project = inEvent && inEvent.project;
		if (project) {
			this.projectSaveAndAction(project, 'build', 'build');
		}
		return true; // stop bubble-up
	},

	/**
	 * Event handler: handle install application action (select provider & run action)
	 * @param {enyo.Component} inSender
	 * @param {Object} inEvent
	 * @property inEvent {Ares.Model.Project} project
	 * @private
	 */
	installAction: function(inSender, inEvent) {
		var project = inEvent && inEvent.project;
		if (project) {
			this.projectSaveAndAction(project, 'test', 'install');
		}
		return true; // stop bubble-up
	},
	/**
	 * Event handler: handle run application action (select provider & run action)
	 * @param {enyo.Component} inSender
	 * @param {Object} inEvent
	 * @property inEvent {Ares.Model.Project} project
	 * @private
	 */
	runAction: function(inSender, inEvent) {
		var project = inEvent && inEvent.project;
		if (project) {
			this.projectSaveAndAction(project, 'test', 'run');
		}
		return true; // stop bubble-up
	},
	/**
	 * Event handler: handle debug application action (select provider & run action)
	 * @param {enyo.Component} inSender
	 * @param {Object} inEvent
	 * @property inEvent {Ares.Model.Project} project
	 * @private
	 */
	runDebugAction: function(inSender, inEvent) {
		var project = inEvent && inEvent.project;
		if (project) {
			this.projectSaveAndAction(project, 'test', 'runDebug');
		}
		return true; // stop bubble-up
	},

	/**
	 * Request to save project and perform action
	 * @param {Ares.Model.Project} project
	 * @param {String} serviceType
	 * @param {String} action
	 */
	projectSaveAndAction: function(project, serviceType, action) {
		var cb = function (err) {
			if (err) {
				this.trace(err);
			} else {
				this.projectAction( project, serviceType, action);
			}
		};
		if (project) {
			this.doProjectSave({ project: project, callback: cb.bind(this) });
		}
	},

	/**
	 * @private
	 */
	projectAction: function(project, serviceType, action) {
		var self = this;
		this.doShowWaitPopup({msg: "Starting: " + action, service: serviceType});
		// TODO: Must be reworked to allow the selection of builder/tester in the UI - ENYO-2049
		var services = ServiceRegistry.instance.getServicesByType(serviceType);
		var provider =	services[services.length - 1];
		if (!provider) {
			this.doError({msg: 'No ' + serviceType + ' service available'});
		} else if (typeof provider[action] !== 'function') {
			this.doError({msg: 'Service ' + provider.name + ' does not provide action: ' + action});
		} else {
			provider[action](project, function(inError) {
				self.doHideWaitPopup();
				self.refreshFileTree(project.getFolderId());
				if (inError) {
					self.doError({msg: inError.toString(), err: inError});
				}
			});
		}
	},

	launchPreview: function (project) {
		var cb = function (err) {
			if (err) {
				this.trace(err);
			} else {
				this._launchPreview(project);
			}
		};
		this.doProjectSave({ project: project, callback: cb.bind(this) });
	},

	_launchPreview: function (project) {
		var config = project.getConfig() ;
		var topFile = config.data.preview.top_file ;
		var projectUrl = project.getProjectUrl() + '/' + topFile ;

		var winLoc = window.location.toString()
			    .replace(/\/ide\/$/,'/preview/preview.html') // Ares std
			    .replace('/ide/index.html','/preview/preview.html') // Ares minified
			    .replace('/ide/debug.html','/ide/preview.html') // Ares debug (every files)
			    .replace('/ide/test.html','/ide/preview.html'); // Ares-under-test
		var previewUrl = winLoc
				+ ( winLoc.indexOf('?') != -1 ? '&' : '?' )
				+ 'url=' + encodeURIComponent(projectUrl)+'&name=' + project.id;

		this.trace("preview on URL ", previewUrl) ;

		window.open(
			previewUrl,
			'_blank', // ensure that a new window is created each time preview is tapped
			'scrollbars=0,menubar=1,resizable=1',
			false
		);
	},

	/**
	 * Event handler: Launch a preview widget of the selected project in a separate frame
	 * @param {enyo.Component} inSender
	 * @param {Object} inEvent
	 * @property inEvent {Ares.Model.Project} project
	 * @private
	 */
	previewAction: function(inSender, inEvent) {
		var project = inEvent.project;
		if ( project) {
			this.launchPreview(project);
		}
		return true; // stop the bubble
	}
});
<commit_msg>ENYO-2627: clean leftover `debug: true`<commit_after>/*global ServiceRegistry, ProjectConfig, ares, ComponentsRegistry, async, enyo, Phonegap */
/**
 * This kind is the top kind of project handling. It contains:
 * - The project list
 * - the interface towards the user's file (harmonia)
 * - Popups to manage projects (create, scan, error ...)
 */
enyo.kind({
	name: "ProjectView",
	kind: "FittableColumns",
	classes: "enyo-unselectable",
	debug: false,
	published: {
		// harcoded until ENYO-2755 is fixed
		panelIndex: 0
	},
	components: [
		{kind: "ProjectList",
			onModifySettings: "modifySettingsAction",
			onCreateProject: "createProjectAction",
			onOpenProject: "openProjectAction",
			onSearchProjects: "searchProjectsAction",
			onDuplicateProject: "duplicateProjectAction",
			onProjectRemoved: "projectRemoved",
			name: "projectList"
		},
		{kind: "ProjectWizardCreate", canGenerate: false, name: "projectWizardCreate", classes:"ares-masked-content-popup"},
		{kind: "ProjectWizardScan", canGenerate: false, name: "projectWizardScan", classes:"ares-masked-content-popup"},
		{kind: "ProjectWizardModify", canGenerate: false,
			name: "projectWizardModify"
		},
		{kind: "ProjectWizardCopy", name: "projectWizardCopy", classes:"ares-masked-content-popup"}
	],
	handlers: {
		onAddProjectInList: "addProjectInList",
		onPreview: "previewAction",
		onBuild: "buildAction",
		onInstall: "installAction",
		onRun: "runAction",
		onRunDebug: "runDebugAction"
	},
	events: {
		onHideWaitPopup: "",
		onShowWaitPopup: "",
		onError: "",
		onProjectSelected: "",
		onProjectSave: "",
		onRegisterMe: ""
	},
	create: function() {
		ares.setupTraceLogger(this);
		this.inherited(arguments);
		this.doRegisterMe({name:"projectView", reference:this});
	},
	/**
	 * Refresh the {ProjectView} (if relevant), following a change of the given file
	 * @param {Object} toSelectId. Asynchronous
	 */
	refreshFileTree: function(toSelectId,next) {
		ComponentsRegistry.getComponent("harmonia").refreshFileTree(toSelectId,next);
	},
	searchProjectsAction: function(inSender, inEvent) {
		this.$.projectWizardScan.setHeaderText('Select a folder hierarchy');
		this.$.projectWizardScan.setRecurse(true);
		this.$.projectWizardScan.show();
		return true; //Stop event propagation
	},
	openProjectAction: function(inSender, inEvent) {
		this.$.projectWizardScan.setHeaderText('Select an existing Ares application folder (contains a project.json file)');
		this.$.projectWizardScan.setRecurse(false);
		this.$.projectWizardScan.show();
		return true; //Stop event propagation
	},
	duplicateProjectAction: function(inSender, inEvent) {
		if(!this.currentProject()){
			this.doError({msg: "Please project list select item."});
			return false;
		}

		this.$.projectWizardCopy.start( this.currentProject() );
		return true; //Stop event propagation
	},
	createProjectAction: function(inSender, inEvent) {
		this.$.projectWizardCreate.start();
		return true; //Stop event propagation
	},
	modifySettingsAction: function(inSender, inEvent) {
		this.$.projectWizardModify.start( this.currentProject() );

		return true; //Stop event propagation
	},

	addProjectInList: function(inSender, inEvent) {
		this.doHideWaitPopup();
		try {
			// Add an entry into the project list
			this.$.projectList.addProject(inEvent.name, inEvent.folderId, inEvent.service, inEvent.dontSelect);
		} catch(e) {
			var msg = e.toString();
			this.error(msg);
			this.doError({msg: msg});
			return false;
		}
		return true; //Stop event propagation
	},
	currentProject: function() {
		return this.$.projectList.getSelectedProject() ;
	},
	/**
	 *
	 * @param {Object} project
	 * @param {Function} next
	 */
	setupProjectConfig: function(project, next) {
		ares.assertCb(next);

		var pname = project.getName();
		if ( this.currentProject() && pname === this.currentProject().getName() ) {
			this.trace("skip setup of already selected project" + pname);
			next();
			return;
		}

		// FIXME: temporary hack to create config.json on the
		// fly if needed... would be better to create/load it
		// when the workspace is loaded & when a new project
		// is created that would save per-click HTTP traffic
		// to the FileSystemService.
		var self = this;
		var config = new ProjectConfig();
		this.trace("setup project config init on "+ project.getName() );
		var initData = {
			service: project.getService(),
			folderId: project.getFolderId()
		};

		async.series(
			[
				// read default config from remote server
				config.init.bind(config, initData) ,
				function (next) {
					self.trace("ProjectView: setup project set config on "+ project.getName() );
					project.setConfig(config);

					self.initializeDownloadStatus(project, config.data.providers.phonegap.enabled);
					self.initializeValidPgbConf(project, config.data.providers.phonegap.enabled);
					next();
				},
				function (next) {
					// Pass service definition & configuration to Harmonia
					// & consequently to HermesFileTree
					self.trace("ProjectView: setup project on harmonia "+ project.getName() );
					ComponentsRegistry.getComponent("harmonia").setProject(project, next);
				}

			],
			function (err) {
				self.trace("ProjectView: setup project config done on " + project.getName() + " err is ",err );
				if (err) {
					self.doError({msg: err.toString(), err: err});
				}
				next(err);
			}
		);
	},
	/**
	 * Initialize the attribute "downloadStatus" of the project
	 *
	 * this attribute is used only by Phonegap Build.
	 * @private
	 */
	initializeDownloadStatus: function(inProject, inPhonegapEnabled) {
		if (inProject.getDownloadStatus() === undefined && inPhonegapEnabled) {
			var downloadStatus = {};
			var index = 0;

			for (index in Phonegap.UIConfiguration.platformDrawersContent) {
				downloadStatus[Phonegap.UIConfiguration.platformDrawersContent[index].id] = "Ready for download";
			}

			inProject.setDownloadStatus(downloadStatus);
		}
	},

	initializeValidPgbConf: function(inProject, inPhonegapEnabled) {
		if (inProject.getValidPgbConf() === undefined && inPhonegapEnabled) {
			var pgbValidation = {};
			var pgbUiData = Phonegap.UIConfiguration.commonDrawersContent.concat(Phonegap.UIConfiguration.platformDrawersContent);
			var index =0;

			for (index in pgbUiData) {
				//The creation of the pgbValidation drawer attribute and its initialization are done in the same time.
				pgbValidation[pgbUiData[index].id] = {};

				for (var i=0, maxLength = pgbUiData[index].rows.length; i<maxLength; i++) {
					//The creation of the pgbValidation row attribute and its initialization are done in the same time.
					pgbValidation[pgbUiData[index].id][pgbUiData[index].rows[i].name] = true;
				}
				pgbValidation[pgbUiData[index].id]["validDrawer"] = true;
			}

			inProject.setValidPgbConf(pgbValidation);
		}
	},

	projectRemoved: function(inSender, inEvent) {
		ComponentsRegistry.getComponent("harmonia").setProject(null, ares.noNext);
	},
	/**
	 * Event handler: handle build project action (select provider & run action)
	 * @param {enyo.Component} inSender
	 * @param {Object} inEvent
	 * @property inEvent {Ares.Model.Project} project
	 * @private
	 */
	buildAction: function(inSender, inEvent) {
		var project = inEvent && inEvent.project;
		if (project) {
			this.projectSaveAndAction(project, 'build', 'build');
		}
		return true; // stop bubble-up
	},

	/**
	 * Event handler: handle install application action (select provider & run action)
	 * @param {enyo.Component} inSender
	 * @param {Object} inEvent
	 * @property inEvent {Ares.Model.Project} project
	 * @private
	 */
	installAction: function(inSender, inEvent) {
		var project = inEvent && inEvent.project;
		if (project) {
			this.projectSaveAndAction(project, 'test', 'install');
		}
		return true; // stop bubble-up
	},
	/**
	 * Event handler: handle run application action (select provider & run action)
	 * @param {enyo.Component} inSender
	 * @param {Object} inEvent
	 * @property inEvent {Ares.Model.Project} project
	 * @private
	 */
	runAction: function(inSender, inEvent) {
		var project = inEvent && inEvent.project;
		if (project) {
			this.projectSaveAndAction(project, 'test', 'run');
		}
		return true; // stop bubble-up
	},
	/**
	 * Event handler: handle debug application action (select provider & run action)
	 * @param {enyo.Component} inSender
	 * @param {Object} inEvent
	 * @property inEvent {Ares.Model.Project} project
	 * @private
	 */
	runDebugAction: function(inSender, inEvent) {
		var project = inEvent && inEvent.project;
		if (project) {
			this.projectSaveAndAction(project, 'test', 'runDebug');
		}
		return true; // stop bubble-up
	},

	/**
	 * Request to save project and perform action
	 * @param {Ares.Model.Project} project
	 * @param {String} serviceType
	 * @param {String} action
	 */
	projectSaveAndAction: function(project, serviceType, action) {
		var cb = function (err) {
			if (err) {
				this.trace(err);
			} else {
				this.projectAction( project, serviceType, action);
			}
		};
		if (project) {
			this.doProjectSave({ project: project, callback: cb.bind(this) });
		}
	},

	/**
	 * @private
	 */
	projectAction: function(project, serviceType, action) {
		var self = this;
		this.doShowWaitPopup({msg: "Starting: " + action, service: serviceType});
		// TODO: Must be reworked to allow the selection of builder/tester in the UI - ENYO-2049
		var services = ServiceRegistry.instance.getServicesByType(serviceType);
		var provider =	services[services.length - 1];
		if (!provider) {
			this.doError({msg: 'No ' + serviceType + ' service available'});
		} else if (typeof provider[action] !== 'function') {
			this.doError({msg: 'Service ' + provider.name + ' does not provide action: ' + action});
		} else {
			provider[action](project, function(inError) {
				self.doHideWaitPopup();
				self.refreshFileTree(project.getFolderId());
				if (inError) {
					self.doError({msg: inError.toString(), err: inError});
				}
			});
		}
	},

	launchPreview: function (project) {
		var cb = function (err) {
			if (err) {
				this.trace(err);
			} else {
				this._launchPreview(project);
			}
		};
		this.doProjectSave({ project: project, callback: cb.bind(this) });
	},

	_launchPreview: function (project) {
		var config = project.getConfig() ;
		var topFile = config.data.preview.top_file ;
		var projectUrl = project.getProjectUrl() + '/' + topFile ;

		var winLoc = window.location.toString()
			    .replace(/\/ide\/$/,'/preview/preview.html') // Ares std
			    .replace('/ide/index.html','/preview/preview.html') // Ares minified
			    .replace('/ide/debug.html','/ide/preview.html') // Ares debug (every files)
			    .replace('/ide/test.html','/ide/preview.html'); // Ares-under-test
		var previewUrl = winLoc
				+ ( winLoc.indexOf('?') != -1 ? '&' : '?' )
				+ 'url=' + encodeURIComponent(projectUrl)+'&name=' + project.id;

		this.trace("preview on URL ", previewUrl) ;

		window.open(
			previewUrl,
			'_blank', // ensure that a new window is created each time preview is tapped
			'scrollbars=0,menubar=1,resizable=1',
			false
		);
	},

	/**
	 * Event handler: Launch a preview widget of the selected project in a separate frame
	 * @param {enyo.Component} inSender
	 * @param {Object} inEvent
	 * @property inEvent {Ares.Model.Project} project
	 * @private
	 */
	previewAction: function(inSender, inEvent) {
		var project = inEvent.project;
		if ( project) {
			this.launchPreview(project);
		}
		return true; // stop the bubble
	}
});
<|endoftext|>


<commit_before>var jedit = require('json-editor'); //TODO webpackify
var FilesWidget = require('js/FilesWidget');
var Fangorn = require('js/fangorn');
var $osf = require('js/osfHelpers');
var $ = require('jquery');

JSONEditor.defaults.options.upload = function() {
   // TODO add file handling
};

JSONEditor.defaults.resolvers.unshift(function(schema) {
    if(schema.type === "string" && schema.format === "url" && schema.options && schema.options.upload === true) {
        if(window.FileReader) return "myUpload";
    }
});

JSONEditor.defaults.editors.myUpload = JSONEditor.defaults.editors.upload.extend({
    build: function() {
        var self = this;
        this.title = this.header = this.label = this.theme.getFormInputLabel(this.getTitle());

        // Input that holds the base64 string
        this.input = this.theme.getFormInputField('hidden');
        this.container.appendChild(this.input);

        // Don't show uploader if this is readonly
        if(!this.schema.readOnly && !this.schema.readonly) {

        if(!this.jsoneditor.options.upload) throw "Upload handler required for upload editor";

        // File uploader
        this.uploader = document.createElement('div');

        $(this.uploader).attr('id', 'registrationFilesGrid');

        this.uploader.addEventListener('change',function(e) {
            e.preventDefault();
            e.stopPropagation();
            console.log("change");

            if(this.files && this.files.length) {
                var fr = new FileReader();
                fr.onload = function(evt) {
                    self.preview_value = evt.target.result;
                    self.refreshPreview();
                    self.onChange(true);
                    fr = null;
                };
                fr.readAsDataURL(this.files[0]);
            }
        });
    }
        var description = this.schema.description;
        if (!description) description = '';

        this.preview = this.theme.getFormInputDescription(description);
        this.container.appendChild(this.preview);

        this.control = this.theme.getFormControl(this.label, this.uploader||this.input, this.preview);
        this.container.appendChild(this.control);
    },
    postBuild: function() {
        var nodeApiUrl = window.contextVars.node.urls.api;

        var filesWidget = new FilesWidget('registrationFilesGrid', nodeApiUrl + 'files/grid/');
        filesWidget.init();
    },
    refreshPreview: function() {
        if(this.last_preview === this.preview_value) return;
        this.last_preview = this.preview_value;

        this.preview.innerHTML = '';

        if(!this.preview_value) return;

        var self = this;

        var mime = this.preview_value.match(/^data:([^;,]+)[;,]/);
        if(mime) mime = mime[1];
        if(!mime) mime = 'unknown';

        var file = this.uploader.files[0];

        this.preview.innerHTML = 'Type: '+mime+', Size: '+file.size+' bytes';
        if(mime.substr(0,5)==="image") {
            this.preview.innerHTML += '
';
            var img = document.createElement('img');
            img.style.maxWidth = '100%';
            img.style.maxHeight = '100px';
            img.src = this.preview_value;
            this.preview.appendChild(img);
        }

        this.preview.innerHTML += '
';
        var uploadButton = this.getButton('Upload', 'upload', 'Upload');
        this.preview.appendChild(uploadButton);
        uploadButton.addEventListener('click',function(event) {
            event.preventDefault();

            uploadButton.setAttribute("disabled", "disabled");
            self.theme.removeInputError(self.uploader);

            if (self.theme.getProgressBar) {
                self.progressBar = self.theme.getProgressBar();
                self.preview.appendChild(self.progressBar);
            }

            self.jsoneditor.options.upload(self.path, file, {
                success: function(url) {
                    self.setValue(url);

                    if(self.parent) self.parent.onChildEditorChange(self);
                    else self.jsoneditor.onChange();

                    if (self.progressBar) self.preview.removeChild(self.progressBar);
                    uploadButton.removeAttribute("disabled");
                },
                failure: function(error) {
                    self.theme.addInputError(self.uploader, error);
                    if (self.progressBar) self.preview.removeChild(self.progressBar);
                    uploadButton.removeAttribute("disabled");
                },
                updateProgress: function(progress) {
                    if (self.progressBar) {
                        if (progress) self.theme.updateProgressBar(self.progressBar, progress);
                        else self.theme.updateProgressBarUnknown(self.progressBar);
                    }
                }
            });
        });
    },
    setValue: function(val) {
        if(this.value !== val) {
            this.value = val;
            this.input.value = this.value;
            this.onChange();
        }
    },
    destroy: function() {
        if(this.preview && this.preview.parentNode) this.preview.parentNode.removeChild(this.preview);
        if(this.title && this.title.parentNode) this.title.parentNode.removeChild(this.title);
        if(this.input && this.input.parentNode) this.input.parentNode.removeChild(this.input);
        if(this.uploader && this.uploader.parentNode) this.uploader.parentNode.removeChild(this.uploader);

        this._super();
    }
});

// add for single select of check boxes
JSONEditor.defaults.resolvers.unshift(function(schema) {
    if (schema.type === "array" && schema.items && !(Array.isArray(schema.items)) && schema.uniqueItems && schema.items["enum"] && ['string', 'number', 'integer'].indexOf(schema.items.type) >= 0) {
        return "singleselect";
    }
});
JSONEditor.defaults.editors.singleselect = JSONEditor.defaults.editors.multiselect.extend({
    build: function() {

        var self = this,
            i;
        if (!this.options.compact) this.header = this.label = this.theme.getFormInputLabel(this.getTitle());
        if (this.schema.description) this.description = this.theme.getFormInputDescription(this.schema.description);

        if ((!this.schema.format && this.option_keys.length < 8) || this.schema.format === "checkbox") {
            this.input_type = 'checkboxes';

            this.inputs = {};
            this.controls = {};
            for (i = 0; i < this.option_keys.length; i++) {
                this.inputs[this.option_keys[i]] = this.theme.getCheckbox();
                this.select_options[this.option_keys[i]] = this.inputs[this.option_keys[i]];
                var label = this.theme.getCheckboxLabel(this.option_keys[i]);
                this.controls[this.option_keys[i]] = this.theme.getFormControl(label, this.inputs[this.option_keys[i]]);
            }

            this.control = this.theme.getMultiCheckboxHolder(this.controls, this.label, this.description);
        } else {
            this.input_type = 'select';
            this.input = this.theme.getSelectInput(this.option_keys);
            this.input.multiple = true;
            this.input.size = Math.min(10, this.option_keys.length);

            for (i = 0; i < this.option_keys.length; i++) {
                this.select_options[this.option_keys[i]] = this.input.children[i];
            }

            if (this.schema.readOnly || this.schema.readonly) {
                this.always_disabled = true;
                this.input.disabled = true;
            }

            this.control = this.theme.getFormControl(this.label, this.input, this.description);
        }

        this.container.appendChild(this.control);

        var previous;
        this.control.addEventListener("mouseover", function(e) {
            var new_value = [];
            for (i = 0; i < self.option_keys.length; i++) {
                if (self.select_options[self.option_keys[i]].selected || self.select_options[self.option_keys[i]].checked) {
                    new_value.push(self.select_values[self.option_keys[i]]);
                }
            }
            previous = new_value;

        });
        this.control.addEventListener('change', function(e) {
            e.preventDefault();
            e.stopPropagation();

            // delete older one using previous
            var new_value = [];
            for (i = 0; i < self.option_keys.length; i++) {
                if (self.select_options[self.option_keys[i]].selected || self.select_options[self.option_keys[i]].checked) {

                    var str = '"' + self.select_values[self.option_keys[i]] + '"';
                    var blah = self.select_values[self.option_keys[i]];
                    if (previous.indexOf(blah) != -1) {
                        self.select_options[self.option_keys[i]].checked = false;
                    } else {
                        new_value.push(self.select_values[self.option_keys[i]]);
                    }
                }
            }
            self.updateValue(new_value);
            self.onChange(true);
        });
    }
});

JSONEditor.defaults.editors.commentableString = JSONEditor.defaults.editors.string.extend({
    build: function() {
        this._super();

        $(this.input).after($('Comments go here'));
    }
});
<commit_msg>JSON Editor sets path to file as value<commit_after>var jedit = require('json-editor'); //TODO webpackify
var FilesWidget = require('js/FilesWidget');
var Fangorn = require('js/fangorn');
var $osf = require('js/osfHelpers');
var $ = require('jquery');
var URI = require('URIjs');

JSONEditor.defaults.options.upload = function(type, file, cbs) {
    // TODO may want to change this
    var nodeApiUrl = window.contextVars.node.urls.api;

    var tb = this;
    var redir = new URI(file.nodeUrl);
    redir.segment('files').segment(file.provider).segmentCoded(file.path.substring(1));
    var fileurl  = redir.toString() + '/';

    if (type === 'root.upload_fail') cbs.failure('Upload failed');
    else {
        var tick = 0;
        var tickFunction = function() {
            tick += 1;
            if (tick < 100) {
                cbs.updateProgress(tick);
                window.setTimeout(tickFunction, 50)
            } else if (tick == 100) {
                cbs.updateProgress();
                window.setTimeout(tickFunction, 500)
            } else {
                cbs.success('/project' + fileurl);
            }
        };
        window.setTimeout(tickFunction)
    }
};

JSONEditor.defaults.resolvers.unshift(function(schema) {
    if(schema.type === "string" && schema.format === "url" && schema.options && schema.options.upload === true) {
        if(window.FileReader) return "myUpload";
    }
});

JSONEditor.defaults.editors.myUpload = JSONEditor.defaults.editors.upload.extend({
    build: function() {
        var self = this;
        this.title = this.header = this.label = this.theme.getFormInputLabel(this.getTitle());

        // Input that holds the base64 string
        this.input = this.theme.getFormInputField('hidden');
        this.container.appendChild(this.input);

        // Don't show uploader if this is readonly
        if(!this.schema.readOnly && !this.schema.readonly) {

        if(!this.jsoneditor.options.upload) throw "Upload handler required for upload editor";

        // File uploader
        this.uploader = document.createElement('div');

        $(this.uploader).attr('id', 'registrationFilesGrid');

        this.uploader.addEventListener('click',function(e) {
            e.preventDefault();
            e.stopPropagation();
            folder = $(this).find($(event.target).attr('data-id'));
            //console.log(self.preview_value);
            if (self.preview_value.kind === 'file') {
                self.refreshPreview();
                self.onChange(true);
            } else {
                self.preview_value = undefined;
                self.refreshPreview();
            }

        });
    }
        var description = this.schema.description;
        if (!description) description = '';

        this.preview = this.theme.getFormInputDescription(description);
        this.container.appendChild(this.preview);

        this.control = this.theme.getFormControl(this.label, this.uploader||this.input, this.preview);
        this.container.appendChild(this.control);

        var nodeApiUrl = window.contextVars.node.urls.api;
        var fangornOpts = {
            onselectrow: function(row, event) {
                self.preview_value = row.data;
                this.path = row.data.path;
                self.files = row.data;

                var tb = this;
                var redir = new URI(row.data.nodeUrl);
                redir.segment('files').segment(row.data.provider).segmentCoded(row.data.path.substring(1));
                var fileurl  = redir.toString() + '/';
                console.log(fileurl);
            }
        };

        var filesWidget = new FilesWidget('registrationFilesGrid', nodeApiUrl + 'files/grid/', fangornOpts);
        filesWidget.init();

    },
    refreshPreview: function() {
        if(this.last_preview === this.preview_value) return;
        this.last_preview = this.preview_value;

        this.preview.innerHTML = '';

        if(!this.preview_value) return;

        var self = this;

        var mime = this.preview_value.name.match(/^data:([^;,]+)[;,]/);
        if(mime) mime = mime[1];
        if(!mime) mime = 'unknown';

        var file = this.files;

        this.preview.innerHTML = 'Type: '+mime+', Size: '+file.size+' bytes';
        if(mime.substr(0,5)==="image") {
            this.preview.innerHTML += '
';
            var img = document.createElement('img');
            img.style.maxWidth = '100%';
            img.style.maxHeight = '100px';
            img.src = this.preview_value;
            this.preview.appendChild(img);
        }

        this.preview.innerHTML += '
';
        var uploadButton = this.getButton('Upload', 'upload', 'Upload');
        this.preview.appendChild(uploadButton);
        uploadButton.addEventListener('click',function(event) {
            event.preventDefault();

            uploadButton.setAttribute("disabled", "disabled");
            self.theme.removeInputError(self.uploader);

            if (self.theme.getProgressBar) {
                self.progressBar = self.theme.getProgressBar();
                self.preview.appendChild(self.progressBar);
            }

            self.jsoneditor.options.upload(self.path, file, {
                success: function(url) {
                    self.setValue(url);

                    if(self.parent) self.parent.onChildEditorChange(self);
                    else self.jsoneditor.onChange();

                    if (self.progressBar) self.preview.removeChild(self.progressBar);
                    uploadButton.removeAttribute("disabled");
                },
                failure: function(error) {
                    self.theme.addInputError(self.uploader, error);
                    if (self.progressBar) self.preview.removeChild(self.progressBar);
                    uploadButton.removeAttribute("disabled");
                },
                updateProgress: function(progress) {
                    if (self.progressBar) {
                        if (progress) self.theme.updateProgressBar(self.progressBar, progress);
                        else self.theme.updateProgressBarUnknown(self.progressBar);
                    }
                }
            });
        });
    }
});

// add for single select of check boxes
JSONEditor.defaults.resolvers.unshift(function(schema) {
    if (schema.type === "array" && schema.items && !(Array.isArray(schema.items)) && schema.uniqueItems && schema.items["enum"] && ['string', 'number', 'integer'].indexOf(schema.items.type) >= 0) {
        return "singleselect";
    }
});
JSONEditor.defaults.editors.singleselect = JSONEditor.defaults.editors.multiselect.extend({
    build: function() {

        var self = this,
            i;
        if (!this.options.compact) this.header = this.label = this.theme.getFormInputLabel(this.getTitle());
        if (this.schema.description) this.description = this.theme.getFormInputDescription(this.schema.description);

        if ((!this.schema.format && this.option_keys.length < 8) || this.schema.format === "checkbox") {
            this.input_type = 'checkboxes';

            this.inputs = {};
            this.controls = {};
            for (i = 0; i < this.option_keys.length; i++) {
                this.inputs[this.option_keys[i]] = this.theme.getCheckbox();
                this.select_options[this.option_keys[i]] = this.inputs[this.option_keys[i]];
                var label = this.theme.getCheckboxLabel(this.option_keys[i]);
                this.controls[this.option_keys[i]] = this.theme.getFormControl(label, this.inputs[this.option_keys[i]]);
            }

            this.control = this.theme.getMultiCheckboxHolder(this.controls, this.label, this.description);
        } else {
            this.input_type = 'select';
            this.input = this.theme.getSelectInput(this.option_keys);
            this.input.multiple = true;
            this.input.size = Math.min(10, this.option_keys.length);

            for (i = 0; i < this.option_keys.length; i++) {
                this.select_options[this.option_keys[i]] = this.input.children[i];
            }

            if (this.schema.readOnly || this.schema.readonly) {
                this.always_disabled = true;
                this.input.disabled = true;
            }

            this.control = this.theme.getFormControl(this.label, this.input, this.description);
        }

        this.container.appendChild(this.control);

        var previous;
        this.control.addEventListener("mouseover", function(e) {
            var new_value = [];
            for (i = 0; i < self.option_keys.length; i++) {
                if (self.select_options[self.option_keys[i]].selected || self.select_options[self.option_keys[i]].checked) {
                    new_value.push(self.select_values[self.option_keys[i]]);
                }
            }
            previous = new_value;

        });
        this.control.addEventListener('change', function(e) {
            e.preventDefault();
            e.stopPropagation();

            // delete older one using previous
            var new_value = [];
            for (i = 0; i < self.option_keys.length; i++) {
                if (self.select_options[self.option_keys[i]].selected || self.select_options[self.option_keys[i]].checked) {

                    var str = '"' + self.select_values[self.option_keys[i]] + '"';
                    var blah = self.select_values[self.option_keys[i]];
                    if (previous.indexOf(blah) != -1) {
                        self.select_options[self.option_keys[i]].checked = false;
                    } else {
                        new_value.push(self.select_values[self.option_keys[i]]);
                    }
                }
            }
            self.updateValue(new_value);
            self.onChange(true);
        });
    }
});

JSONEditor.defaults.editors.commentableString = JSONEditor.defaults.editors.string.extend({
    build: function() {
        this._super();

        $(this.input).after($('Comments go here'));
    }
});
<|endoftext|>


<commit_before>/*global describe, it, expect, example, before, after, beforeEach, afterEach, mocha, sinon*/
'use strict';

var assert = require('chai').assert;
var $osf = require('js/osfHelpers');

var Stats = require('js/share/stats');

describe('share/stats', () => {

    describe('#sourcesAgg', () => {

        it('builds correct query, aggregation and filters for a source aggregation', () => {
            var returnedAgg = Stats.sourcesAgg();
            var requiredAgg = {
                'query': {
                  'match_all': {}
                },
                'aggregations': {
                  'sources': {
                    'terms': {
                      'field': '_type',
                      'size': 0,
                      'exclude': 'of|and|or',
                      'min_doc_count': 0
                    }
                  }
                },
                'filters': {}
              };
            assert.deepEqual(returnedAgg, requiredAgg);
        });
    });

    describe('#sourcesByDatesAgg', () => {

        it('builds correct query, aggregation and filters for a sourcesByDates aggregation', () => {
            var returnedAgg = Stats.sourcesByDatesAgg();
            var requiredAgg = {
                'aggregations': {
                  'sourcesByTimes': {
                    'terms': {
                      'field': '_type',
                      'size': 0,
                      'exclude': 'of|and|or',
                      'min_doc_count': 0
                    },
                    'aggregations': {
                      'articlesOverTime': {
                          'aggregations': {
                              'articlesOverTime': {
                                'date_histogram': {
                                    'field': 'providerUpdatedDateTime',
                                    'interval': 'week',
                                    'min_doc_count': 0,
                                    'extended_bounds': {
                                        'min': 1429562338929,
                                        'max': 1437424738929
                                    }
                                }
                              }
                            },
                            'filter': {
                                'range': {
                                    'providerUpdatedDateTime': {
                                        'gte': 1429562338929,
                                        'lte': 1437424738929
                                    }
                                }
                            }
                        }
                    }
                  }
                },
            };

            requiredAgg.aggregations.sourcesByTimes.aggregations.articlesOverTime.aggregations.articlesOverTime.date_histogram.extended_bounds = returnedAgg.aggregations.sourcesByTimes.aggregations.articlesOverTime.aggregations.articlesOverTime.date_histogram.extended_bounds;
            requiredAgg.aggregations.sourcesByTimes.aggregations.articlesOverTime.filter.range.providerUpdatedDateTime = returnedAgg.aggregations.sourcesByTimes.aggregations.articlesOverTime.filter.range.providerUpdatedDateTime ;
            var diffInMs = requiredAgg.aggregations.sourcesByTimes.aggregations.articlesOverTime.aggregations.articlesOverTime.date_histogram.extended_bounds.max - returnedAgg.aggregations.sourcesByTimes.aggregations.articlesOverTime.aggregations.articlesOverTime.date_histogram.extended_bounds.min;
            var testDate = new Date(0);
            testDate.setUTCSeconds(diffInMs/1000);
            assert.equal(testDate.getMonth(),3);
            assert.deepEqual(returnedAgg, requiredAgg);
        });
    });

    describe('#shareDonutGraphParser', () => {

        it('Parse returned sources elasticsearch data into correct format for c3 donut graph, including correct colors', () => {
            var rawData = {};
            rawData.aggregations = {'sources':{
                'buckets':[
                  { 'key': 'figshare','doc_count': 1378},
                  { 'key': 'calhoun', 'doc_count': 119},
                  { 'key': 'ucescholarship', 'doc_count': 74},
                  { 'key': 'mit', 'doc_count': 68},
                  { 'key': 'pubmedcentral', 'doc_count': 52 },
                  { 'key': 'datacite', 'doc_count': 40 },
                  { 'key': 'dash', 'doc_count': 28},
                  { 'key': 'caltech', 'doc_count': 24},
                  { 'key': 'bhl', 'doc_count': 23},
                  { 'key': 'scholarworks_umass', 'doc_count': 23},
                  { 'key': 'udel', 'doc_count': 20},
                  { 'key': 'upennsylvania', 'doc_count': 13},
                  { 'key': 'doepages','doc_count': 12},
                  { 'key': 'smithsonian', 'doc_count': 8},
                  { 'key': 'opensiuc', 'doc_count': 4},
                  { 'key': 'scholarsbank', 'doc_count': 4},
                  { 'key': 'trinity', 'doc_count': 2},
                  { 'key': 'asu', 'doc_count': 1}],
                'sum_other_doc_count': 0,
                'doc_count_error_upper_bound': 0
              }
            };
            var returnedData = Stats.shareDonutGraphParser(rawData);
            var requiredData = {
                  'name': 'shareDonutGraph',
                  'columns': [
                    [ 'figshare',1378],
                    ['calhoun',119],
                    ['ucescholarship',74],
                    ['mit',68],
                    ['pubmedcentral',52],
                    ['datacite',40],
                    ['dash',28],
                    ['caltech',24],
                    ['bhl',23],
                    ['scholarworks_umass',23],
                    ['udel',20],
                    ['upennsylvania',13],
                    ['doepages',12],
                    ['smithsonian',8],
                    ['opensiuc',4],
                    ['scholarsbank',4],
                    ['trinity',2],
                    ['asu',1]
                  ],
                  'colors': {
                    'figshare': '#a6cee3',
                    'calhoun': '#1f78b4',
                    'ucescholarship': '#b2df8a',
                    'mit': '#33a02c',
                    'pubmedcentral': '#fb9a99',
                    'datacite': '#e31a1c',
                    'dash': '#fdbf6f',
                    'caltech': '#ff7f00',
                    'bhl': '#cab2d6',
                    'scholarworks_umass': '#6a3d9a',
                    'udel': '#ffff99',
                    'upennsylvania': '#b15928',
                    'doepages': '#62a3cb',
                    'smithsonian': '#68ab9f',
                    'opensiuc': '#72bf5b',
                    'scholarsbank': '#979d62',
                    'trinity': '#ef5a5a',
                    'asu': '#f06c45'
                  },
                  'type': 'donut',
                  'title': '18 Providers'
                };
            assert.deepEqual(returnedData, requiredData);
        });
    });

    describe('#shareTimeGraphParser', () => {

        it('Parse returned sources elasticsearch data into correct format for c3 donut graph, including correct colors', () => {
            var rawData = {};
            rawData.aggregations = {
              'sourcesByTimes': {
                'buckets': [
                  {
                    'articlesOverTime': {
                      'buckets': [
                        {'key': 1434326400000, 'doc_count': 0},
                        {'key': 1434931200000, 'doc_count': 0},
                        {'key': 1435536000000, 'doc_count': 1378},
                        {'key': 1436140800000, 'doc_count': 0},
                        {'key': 1436745600000, 'doc_count': 0},
                        {'key': 1437350400000, 'doc_count': 0}
                      ]
                    },
                    'key': 'figshare',
                    'doc_count': 1378
                  },
                  {
                    'articlesOverTime': {
                      'buckets': [
                        {'key': 1434326400000, 'doc_count': 0},
                        {'key': 1434931200000, 'doc_count': 0},
                        {'key': 1435536000000, 'doc_count': 73},
                        {'key': 1436140800000, 'doc_count': 0},
                        {'key': 1436745600000, 'doc_count': 0},
                        {'key': 1437350400000, 'doc_count': 0}
                      ]
                    },
                    'key': 'ucescholarship',
                    'doc_count': 73
                  }
                ],
                'sum_other_doc_count': 390,
                'doc_count_error_upper_bound': 20
              }
            };
            var returnedData = Stats.shareTimeGraphParser(rawData);
            var requiredData = {
              'name': 'shareTimeGraph',
              'columns': [
                ['x', 1434326400000, 1434931200000, 1435536000000, 1436140800000, 1436745600000, 1437350400000],
                ['figshare', 0, 0, 1378, 1378, 1378, 1378],
                ['ucescholarship', 0, 0, 73, 73, 73, 73]
              ],
              'colors': {
                'figshare': '#a6cee3',
                'ucescholarship': '#1f78b4'
              },
              'type': 'area-spline',
              'x': 'x',
              'groups': [['x','figshare', 'ucescholarship']]
            };
            assert.deepEqual(returnedData, requiredData);
        });
    });
});

<commit_msg>Fix time graph parser tests<commit_after>/*global describe, it, expect, example, before, after, beforeEach, afterEach, mocha, sinon*/
'use strict';

var assert = require('chai').assert;
var $osf = require('js/osfHelpers');

var Stats = require('js/share/stats');

describe('share/stats', () => {

    describe('#sourcesAgg', () => {

        it('builds correct query, aggregation and filters for a source aggregation', () => {
            var returnedAgg = Stats.sourcesAgg();
            var requiredAgg = {
                'query': {
                  'match_all': {}
                },
                'aggregations': {
                  'sources': {
                    'terms': {
                      'field': '_type',
                      'size': 0,
                      'exclude': 'of|and|or',
                      'min_doc_count': 0
                    }
                  }
                },
                'filters': {}
              };
            assert.deepEqual(returnedAgg, requiredAgg);
        });
    });

    describe('#sourcesByDatesAgg', () => {

        it('builds correct query, aggregation and filters for a sourcesByDates aggregation', () => {
            var returnedAgg = Stats.sourcesByDatesAgg();
            var requiredAgg = {
                'aggregations': {
                  'sourcesByTimes': {
                    'terms': {
                      'field': '_type',
                      'size': 0,
                      'exclude': 'of|and|or',
                      'min_doc_count': 0
                    },
                    'aggregations': {
                      'articlesOverTime': {
                          'aggregations': {
                              'articlesOverTime': {
                                'date_histogram': {
                                    'field': 'providerUpdatedDateTime',
                                    'interval': 'week',
                                    'min_doc_count': 0,
                                    'extended_bounds': {
                                        'min': 1429562338929,
                                        'max': 1437424738929
                                    }
                                }
                              }
                            },
                            'filter': {
                                'range': {
                                    'providerUpdatedDateTime': {
                                        'gte': 1429562338929,
                                        'lte': 1437424738929
                                    }
                                }
                            }
                        }
                    }
                  }
                },
            };

            requiredAgg.aggregations.sourcesByTimes.aggregations.articlesOverTime.aggregations.articlesOverTime.date_histogram.extended_bounds = returnedAgg.aggregations.sourcesByTimes.aggregations.articlesOverTime.aggregations.articlesOverTime.date_histogram.extended_bounds;
            requiredAgg.aggregations.sourcesByTimes.aggregations.articlesOverTime.filter.range.providerUpdatedDateTime = returnedAgg.aggregations.sourcesByTimes.aggregations.articlesOverTime.filter.range.providerUpdatedDateTime ;
            var diffInMs = requiredAgg.aggregations.sourcesByTimes.aggregations.articlesOverTime.aggregations.articlesOverTime.date_histogram.extended_bounds.max - returnedAgg.aggregations.sourcesByTimes.aggregations.articlesOverTime.aggregations.articlesOverTime.date_histogram.extended_bounds.min;
            var testDate = new Date(0);
            testDate.setUTCSeconds(diffInMs/1000);
            assert.equal(testDate.getMonth(),3);
            assert.deepEqual(returnedAgg, requiredAgg);
        });
    });

    describe('#shareDonutGraphParser', () => {

        it('Parse returned sources elasticsearch data into correct format for c3 donut graph, including correct colors', () => {
            var rawData = {};
            rawData.aggregations = {'sources':{
                'buckets':[
                  { 'key': 'figshare','doc_count': 1378},
                  { 'key': 'calhoun', 'doc_count': 119},
                  { 'key': 'ucescholarship', 'doc_count': 74},
                  { 'key': 'mit', 'doc_count': 68},
                  { 'key': 'pubmedcentral', 'doc_count': 52 },
                  { 'key': 'datacite', 'doc_count': 40 },
                  { 'key': 'dash', 'doc_count': 28},
                  { 'key': 'caltech', 'doc_count': 24},
                  { 'key': 'bhl', 'doc_count': 23},
                  { 'key': 'scholarworks_umass', 'doc_count': 23},
                  { 'key': 'udel', 'doc_count': 20},
                  { 'key': 'upennsylvania', 'doc_count': 13},
                  { 'key': 'doepages','doc_count': 12},
                  { 'key': 'smithsonian', 'doc_count': 8},
                  { 'key': 'opensiuc', 'doc_count': 4},
                  { 'key': 'scholarsbank', 'doc_count': 4},
                  { 'key': 'trinity', 'doc_count': 2},
                  { 'key': 'asu', 'doc_count': 1}],
                'sum_other_doc_count': 0,
                'doc_count_error_upper_bound': 0
              }
            };
            var returnedData = Stats.shareDonutGraphParser(rawData);
            var requiredData = {
                  'name': 'shareDonutGraph',
                  'columns': [
                    [ 'figshare',1378],
                    ['calhoun',119],
                    ['ucescholarship',74],
                    ['mit',68],
                    ['pubmedcentral',52],
                    ['datacite',40],
                    ['dash',28],
                    ['caltech',24],
                    ['bhl',23],
                    ['scholarworks_umass',23],
                    ['udel',20],
                    ['upennsylvania',13],
                    ['doepages',12],
                    ['smithsonian',8],
                    ['opensiuc',4],
                    ['scholarsbank',4],
                    ['trinity',2],
                    ['asu',1]
                  ],
                  'colors': {
                    'figshare': '#a6cee3',
                    'calhoun': '#1f78b4',
                    'ucescholarship': '#b2df8a',
                    'mit': '#33a02c',
                    'pubmedcentral': '#fb9a99',
                    'datacite': '#e31a1c',
                    'dash': '#fdbf6f',
                    'caltech': '#ff7f00',
                    'bhl': '#cab2d6',
                    'scholarworks_umass': '#6a3d9a',
                    'udel': '#ffff99',
                    'upennsylvania': '#b15928',
                    'doepages': '#62a3cb',
                    'smithsonian': '#68ab9f',
                    'opensiuc': '#72bf5b',
                    'scholarsbank': '#979d62',
                    'trinity': '#ef5a5a',
                    'asu': '#f06c45'
                  },
                  'type': 'donut',
                  'title': '18 Providers'
                };
            assert.deepEqual(returnedData, requiredData);
        });
    });

    describe('#shareTimeGraphParser', () => {

        it('Parse returned sources elasticsearch data into correct format for c3 stacked graph, including correct colors', () => {
            var rawData = {};
            rawData.aggregations = {
              'sourcesByTimes': {
                'buckets': [
                  {
                    'articlesOverTime': {
                        'articlesOverTime': {
                            'buckets': [
                                {'key': 1434326400000, 'doc_count': 0},
                                {'key': 1434931200000, 'doc_count': 0},
                                {'key': 1435536000000, 'doc_count': 1378},
                                {'key': 1436140800000, 'doc_count': 0},
                                {'key': 1436745600000, 'doc_count': 0},
                                {'key': 1437350400000, 'doc_count': 0}
                            ]
                        }
                    },
                    'key': 'figshare',
                    'doc_count': 1378
                  },
                  {
                    'articlesOverTime': {
                        'articlesOverTime': {
                            'buckets': [
                                {'key': 1434326400000, 'doc_count': 0},
                                {'key': 1434931200000, 'doc_count': 0},
                                {'key': 1435536000000, 'doc_count': 73},
                                {'key': 1436140800000, 'doc_count': 0},
                                {'key': 1436745600000, 'doc_count': 0},
                                {'key': 1437350400000, 'doc_count': 0}
                            ]
                        }
                    },
                    'key': 'ucescholarship',
                    'doc_count': 73
                  }
                ],
                'sum_other_doc_count': 390,
                'doc_count_error_upper_bound': 20
              }
            };
            var returnedData = Stats.shareTimeGraphParser(rawData);
            var requiredData = {
              'name': 'shareTimeGraph',
              'columns': [
                ['x', 1434326400000, 1434931200000, 1435536000000, 1436140800000, 1436745600000, 1437350400000],
                ['figshare', 0, 0, 1378, 1378, 1378, 1378],
                ['ucescholarship', 0, 0, 73, 73, 73, 73]
              ],
              'colors': {
                'figshare': '#a6cee3',
                'ucescholarship': '#1f78b4'
              },
              'type': 'area-spline',
              'x': 'x',
              'groups': [['x','figshare', 'ucescholarship']]
            };
            assert.deepEqual(returnedData, requiredData);
        });
    });
});

<|endoftext|>


<commit_before>module.exports = function(grunt) {
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),

        sass: {
            options: {
                includePaths: ['bower_components/foundation/scss']
            },
            dist: {
                options: {
                    outputStyle: 'compressed'
                },
                files: {
                    'css/foundation.css': 'scss/foundation.scss'
                }
            }
        },

        watch: {
            grunt: { files: ['Gruntfile.js'] },

            sass: {
                files: 'scss/**/*.scss',
                tasks: ['sass']
            }
        }
    });

    grunt.loadNpmTasks('grunt-sass');
    grunt.loadNpmTasks('grunt-contrib-watch');

    grunt.registerTask('build', ['sass']);
    grunt.registerTask('default', ['build','watch']);
}<commit_msg>Newline<commit_after>module.exports = function(grunt) {
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),

        sass: {
            options: {
                includePaths: ['bower_components/foundation/scss']
            },
            dist: {
                options: {
                    outputStyle: 'compressed'
                },
                files: {
                    'css/foundation.css': 'scss/foundation.scss'
                }
            }
        },

        watch: {
            grunt: { files: ['Gruntfile.js'] },

            sass: {
                files: 'scss/**/*.scss',
                tasks: ['sass']
            }
        }
    });

    grunt.loadNpmTasks('grunt-sass');
    grunt.loadNpmTasks('grunt-contrib-watch');

    grunt.registerTask('build', ['sass']);
    grunt.registerTask('default', ['build','watch']);
}
<|endoftext|>


<commit_before>var execSync = require('child_process').execSync;
var moment = require('moment');
var path = require('path');

var utils = require('../../utils');
var LineupManager = require('../lineup-manager');

var LiquidsoapLineupManager = function(radioConfig, cwd, radioObj) {
    LineupManager.call(this, radioConfig, cwd, radioObj);
}

utils.inheritsFrom(LiquidsoapLineupManager, LineupManager);

LiquidsoapLineupManager.prototype.schedulePlayback = function(currentProgram) {

    // Let Liquidsoap know that the lineup has been changed
    this.logger.info("Changing the current lineup file to " + this.today.lineupFilePath);

    try {
        execSync("cd " + __dirname + "; ./update-lineup-file.sh " + this.today.lineupFilePath, {
            encoding: 'utf-8'
        });
    } catch (e) {
            // telnet return non-zero exit codes, simply ignore them!
    }

    /** We should now register cron events **/
    // Register event using 'at'
    if (this.hasPreProgram(currentProgram)) {
        this.logger.info("PreShow playback scheduled for " + moment(currentProgram.PreShow.Meta.TentativeStartTime).format("YYYY-MM-DDTHH:mm:ss").toString());
        execSync("echo 'cd " + __dirname + "; ./playback-pre-program.sh' | at -t " + moment(currentProgram.PreShow.Meta.TentativeStartTime).subtract(1, 'minutes').format("YYYYMMDDHHmm.ss").toString() + " 2>&1", {
            encoding: 'utf-8'
        });

        currentProgram.PreShow.Scheduler = {};
        currentProgram.PreShow.Scheduler.ScheduledAt = currentProgram.PreShow.Meta.TentativeStartTime;
        currentProgram.PreShow.Scheduler.SchedulerId = ret.split(" ")[1]; // The second token (e.g. "job xxx at Thu Jun 29 20:24:58 2017")
    }

    // Register auto-asaad program announcement! (One minute earlier and the rest is handled in the shell file)
    this.logger.info("Show playback scheduled for " + moment(currentProgram.Show.Meta.TentativeStartTime).format("YYYY-MM-DDTHH:mm:ss").toString());
    execSync("echo 'cd " + __dirname + "; ./playback-program.sh' " + lineupFilePath + "| at -t " + moment(currentProgram.Show.Meta.TentativeStartTime).subtract(1, 'minutes').format("YYYYMMDDHHmm.ss").toString() + " 2>&1", {
        encoding: 'utf-8'
    });

    currentProgram.Show.Scheduler = {};
    currentProgram.Show.Scheduler.ScheduledAt = currentProgram.Show.Meta.TentativeStartTime;
    currentProgram.Show.Scheduler.SchedulerId = ret.split(" ")[1]; // The second token (e.g. "job xxx at Thu Jun 29 20:24:58 2017")
}

LiquidsoapLineupManager.prototype.getMediaDuration = function(media) {

    var cmd = 'mp3info -p "%S" ' + media.path;
    var mediaDuration = parseFloat(execSync(cmd, {
        encoding: 'utf-8'
    }));

    return mediaDuration;
}

module.exports = LiquidsoapLineupManager;
<commit_msg>liquidsoap stabalizing<commit_after>var execSync = require('child_process').execSync;
var moment = require('moment');
var path = require('path');

var utils = require('../../utils');
var LineupManager = require('../lineup-manager');

var LiquidsoapLineupManager = function(radioConfig, cwd, radioObj) {
    LineupManager.call(this, radioConfig, cwd, radioObj);
}

utils.inheritsFrom(LiquidsoapLineupManager, LineupManager);

LiquidsoapLineupManager.prototype.schedulePlayback = function(currentProgram) {

    // Let Liquidsoap know that the lineup has been changed
    this.logger.info("Changing the current lineup file to " + this.today.lineupFilePath);

    try {
        execSync("cd " + __dirname + "; ./update-lineup-file.sh " + this.today.lineupFilePath, {
            encoding: 'utf-8'
        });
    } catch (e) {
            // telnet return non-zero exit codes, simply ignore them!
    }

    /** We should now register cron events **/
    // Register event using 'at'
    if (this.hasPreProgram(currentProgram)) {
        this.logger.info("PreShow playback scheduled for " + moment(currentProgram.PreShow.Meta.TentativeStartTime).format("YYYY-MM-DDTHH:mm:ss").toString());
        var ret = execSync("echo 'cd " + __dirname + "; ./playback-pre-program.sh' | at -t " + moment(currentProgram.PreShow.Meta.TentativeStartTime).subtract(1, 'minutes').format("YYYYMMDDHHmm.ss").toString() + " 2>&1", {
            encoding: 'utf-8'
        });

        currentProgram.PreShow.Scheduler = {};
        currentProgram.PreShow.Scheduler.ScheduledAt = currentProgram.PreShow.Meta.TentativeStartTime;
        currentProgram.PreShow.Scheduler.SchedulerId = ret.split(" ")[1]; // The second token (e.g. "job xxx at Thu Jun 29 20:24:58 2017")
    }

    // Register auto-asaad program announcement! (One minute earlier and the rest is handled in the shell file)
    this.logger.info("Show playback scheduled for " + moment(currentProgram.Show.Meta.TentativeStartTime).format("YYYY-MM-DDTHH:mm:ss").toString());
    var ret = execSync("echo 'cd " + __dirname + "; ./playback-program.sh' " + this.today.lineupFilePath + "| at -t " + moment(currentProgram.Show.Meta.TentativeStartTime).subtract(1, 'minutes').format("YYYYMMDDHHmm.ss").toString() + " 2>&1", {
        encoding: 'utf-8'
    });

    currentProgram.Show.Scheduler = {};
    currentProgram.Show.Scheduler.ScheduledAt = currentProgram.Show.Meta.TentativeStartTime;
    currentProgram.Show.Scheduler.SchedulerId = ret.split(" ")[1]; // The second token (e.g. "job xxx at Thu Jun 29 20:24:58 2017")
}

LiquidsoapLineupManager.prototype.getMediaDuration = function(media) {

    var cmd = 'mp3info -p "%S" ' + media.path;
    var mediaDuration = parseFloat(execSync(cmd, {
        encoding: 'utf-8'
    }));

    return mediaDuration;
}

module.exports = LiquidsoapLineupManager;
<|endoftext|>


<commit_before>import Navigation from './index';
import React from 'react';
import CookieMessage from '@economist/component-cookie-message';
import links from './links';
// const subscriber = [ links.myeconomist, links.logout ];
// const anomymous = [ links.subscribe, links.register, links.login ];
const registered = [ links.subscribe, links.myeconomist, links.logout ];
// This ensures the cookie is never written.
const fakeCookie = {
  load: () => {},
  save: () => {},
};
export default (

     <Navigation className="navigation navigation--registered navigation--sticked"
       links={registered}
       svgUri="assets/icons.svg"
     >

          <CookieMessage reactCookieInstance={fakeCookie}/>

     </Navigation>

Cookie Message is optional for this component.

Cookie message will only be showned once, this example have this functionality removed

Stretch the page to test the sticky functionality applied to the navigation

Stretch the page to test the sticky functionality applied to the navigation

Stretch the page to test the sticky functionality applied to the navigation

Stretch the page to test the sticky functionality applied to the navigation

Stretch the page to test the sticky functionality applied to the navigation

Stretch the page to test the sticky functionality applied to the navigation

Stretch the page to test the sticky functionality applied to the navigation

Stretch the page to test the sticky functionality applied to the navigation

Stretch the page to test the sticky functionality applied to the navigation

Stretch the page to test the sticky functionality applied to the navigation

Stretch the page to test the sticky functionality applied to the navigation

Stretch the page to test the sticky functionality applied to the navigation

Stretch the page to test the sticky functionality applied to the navigation

Stretch the page to test the sticky functionality applied to the navigation

Stretch the page to test the sticky functionality applied to the navigation

);
<commit_msg>Can change the example via query-string<commit_after>import Navigation from './index';
import React from 'react';
import CookieMessage from '@economist/component-cookie-message';
import links from './links';

const subscriber = [ links.myeconomist, links.logout ];
const anonymous = [ links.subscribe, links.register, links.login ];
const registered = [ links.subscribe, links.myeconomist, links.logout ];
let userState = anonymous;
if (typeof window !== 'undefined') {
  switch (location.search) {
    case '?user=registered':
      userState = registered;
      break;
    case '?user=subscriber':
      userState = subscriber;
      break;
    default:
      userState = anonymous;
      break;
  }
}
// This ensures the cookie is never written.
const fakeCookie = {
  load: () => {},
  save: () => {},
};
export default (

     <Navigation className="navigation navigation--registered navigation--sticked"
       links={userState}
       svgUri="assets/icons.svg"
     >

          <CookieMessage reactCookieInstance={fakeCookie}/>

     </Navigation>

Cookie Message is optional for this component.

Cookie message will only be showned once, this example have this functionality removed

Stretch the page to test the sticky functionality applied to the navigation

Stretch the page to test the sticky functionality applied to the navigation

Stretch the page to test the sticky functionality applied to the navigation

Stretch the page to test the sticky functionality applied to the navigation

Stretch the page to test the sticky functionality applied to the navigation

Stretch the page to test the sticky functionality applied to the navigation

Stretch the page to test the sticky functionality applied to the navigation

Stretch the page to test the sticky functionality applied to the navigation

Stretch the page to test the sticky functionality applied to the navigation

Stretch the page to test the sticky functionality applied to the navigation

Stretch the page to test the sticky functionality applied to the navigation

Stretch the page to test the sticky functionality applied to the navigation

Stretch the page to test the sticky functionality applied to the navigation

Stretch the page to test the sticky functionality applied to the navigation

Stretch the page to test the sticky functionality applied to the navigation

);
<|endoftext|>


<commit_before> var myFirebaseRef = new Firebase("https://charityjuke.firebaseio.com");

function updateButtonDisplay() {
    var user = localStorage.user_id;
        if (user) {
            $("#login").hide();
            $("#event").show();
            $("#browse").show();
        } else {
            $("#event").hide();
            $("#browse").hide();
            $("#login").show();
        }
};

function facebookLogin() {
    myFirebaseRef.authWithOAuthPopup("facebook", function(error, authData) {
    if (error) {
      console.log("Login Failed!", error);

    } else {
      console.log("Authenticated successfully with payload:", authData);
       localStorage.user_id = authData.facebook.id; // So hacky. Please change.
       // Insert or update this user:
        myFirebaseRef.child("users").child("User " + authData.facebook.id).set({
        user_id: authData.facebook.id,
        name: authData.facebook.displayName,
        profile_img: authData.facebook.profileImageURL
      }); //end set
    } // end else
  }); // authwithoauthpopup
    updateButtonDisplay();
};
<commit_msg>maybe this fix<commit_after> var myFirebaseRef = new Firebase("https://charityjuke.firebaseio.com");

function updateButtonDisplay() {
    var user = localStorage.user_id;
        if (user) {
            $("#login").hide();
            $("#event").show();
            $("#browse").show();
        } else {
            $("#event").hide();
            $("#browse").hide();
            $("#login").show();
        }
};

function facebookLogin() {
    myFirebaseRef.authWithOAuthPopup("facebook", function(error, authData) {
    if (error) {
      console.log("Login Failed!", error);

    } else {
      console.log("Authenticated successfully with payload:", authData);
       localStorage.user_id = authData.facebook.id; // So hacky. Please change.
       // Insert or update this user:
        myFirebaseRef.child("users").child("User " + authData.facebook.id).set({
        user_id: authData.facebook.id,
        name: authData.facebook.displayName,
        profile_img: authData.facebook.profileImageURL
      }); //end set
            updateButtonDisplay();
    } // end else
  }); // authwithoauthpopup
};
<|endoftext|>