<commit_before>"use strict";

function gsuiGridSamples() {
	var root = this._clone();

	this.rootElement = root;
	this._elPanel = root.querySelector( ".gsui-panel" );
	this._elGrid = root.querySelector( ".gsui-grid" );
	this._elGridCnt = this._elGrid.querySelector( ".gsui-content" );
	this._elPanelExt = this._elPanel.querySelector( ".gsui-extend" );
	this._elPanelCnt = this._elPanel.querySelector( ".gsui-content" );
	this.uiTimeLine = new gsuiTimeLine();
	this.uiBeatLines = new gsuiBeatLines();
	root.prepend( this.uiTimeLine.rootElement );
	this._elGrid.prepend( this.uiBeatLines.rootElement );

	this._elPanelExt.onmousedown = this._evmdPanelEx.bind( this );
	this._elGrid.onmousedown = this._evmdGrid.bind( this );
	this._elGrid.onwheel = this._evowGrid.bind( this );
	this._elPanel.onwheel = this._evowPanel.bind( this );
	this.uiTimeLine.onchangeCurrentTime = this._evocCurrentTime.bind( this );
	this.uiTimeLine.oninputLoop = this._evoiLoop.bind( this );
	this._panelMaxWidth = Infinity;
	this._contentY =
	this._panelMinWidth =
	this._timeOffset = 0;
	this._pxPerBeat = 80;
	this.setFontSize( 40 );
	this.panelWidth( 100 );
}

gsuiGridSamples.prototype = {
	resized() {
		var panelStyle = getComputedStyle( this._elPanel );

		this.width = this.rootElement.clientWidth;
		this._panelMinWidth = parseFloat( panelStyle.minWidth );
		this._panelMaxWidth = parseFloat( panelStyle.maxWidth ) || this.width;
		this._resizeGrid();
		this._updateGrid();
	},
	offset( offset, beatPx ) {
		this._timeOffset = offset;
		this._pxPerBeat = beatPx;
		this._updateGrid();
	},
	currentTime( beat ) {
		this.uiTimeLine.currentTime( beat );
		this.uiBeatLines.currentTime( beat );
	},
	loop( a, b ) {
		this.uiTimeLine.loop( a, b );
		this.uiBeatLines.loop( a, b );
	},
	panelWidth( width ) {
		width = Math.max( this._panelMinWidth, Math.min( width, this._panelMaxWidth ) );
		if ( this._timeOffset > 0 ) {
			this._timeOffset += ( width - this._panelWidth ) / this._pxPerBeat;
		}
		this._panelWidth = width;
		this._updatePanelSize();
	},
	contentY( yEm ) {
		var h = ( this.uiTrackList || this.uiKeys ).rootElement.clientHeight;

		h = Math.max( 0, h - this._elGrid.clientHeight ) / this._fontSize;
		this._contentY = yEm = Math.min( Math.max( 0, yEm ), h );
		this._elGridCnt.style.marginTop =
		this._elPanelCnt.style.marginTop = -yEm + "em";
	},
	setFontSize( emPx ) {
		this._fontSize = ~~Math.min( Math.max( 16, emPx ), 256 );
		this.rootElement.style.fontSize = this._fontSize + "px";
	},
	loadKeys() {
		this._loadPanelCmp( "uiKeys", "uiTrackList" );
	},
	loadTrackList() {
		this._loadPanelCmp( "uiTrackList", "uiKeys" );
	},
	nbOctaves( from, nbOct ) {
		if ( this.uiKeys ) {
			this.uiKeys.octaves( from, nbOct );
			this._addRows( this.uiKeys );
		}
	},
	nbTracks( n ) {
		if ( this.uiTrackList ) {
			this.uiTrackList.nbTracks( n );
			this._addRows( this.uiTrackList );
		}
	},

	// private:
	_clone() {
		var div = document.createElement( "div" );

		gsuiGridSamples.template = gsuiGridSamples.template || this._init();
		div.appendChild( document.importNode( gsuiGridSamples.template.content, true ) );
		return div.removeChild( div.querySelector( "*" ) );
	},
	_init() {
		document.body.addEventListener( "mousemove", function( e ) {
			gsuiGridSamples._focused && gsuiGridSamples._focused._evmmRoot( e );
		} );
		document.body.addEventListener( "mouseup", function( e ) {
			gsuiGridSamples._focused && gsuiGridSamples._focused._evmuRoot( e );
		} );
		return document.getElementById( "gsuiGridSamples" );
	},
	_loadPanelCmp( cmpStr, oldCmpStr ) {
		var cmp = this[ cmpStr ],
			oldCmp = this[ oldCmpStr ];

		if ( oldCmp ) {
			oldCmp[ oldCmpStr === "uiKeys" ? "octaves" : "nbTracks" ]( 0, 0 );
			oldCmp.rootElement.remove();
			this.setFontSize( this._fontSize * ( oldCmpStr === "uiKeys" ? 1.5 : 2 / 3 ) );
			delete this[ oldCmpStr ];
		}
		if ( !cmp ) {
			this[ cmpStr ] = cmp = cmpStr === "uiKeys" ? new gsuiKeys() : new gsuiTrackList();
			this._elPanelCnt.prepend( cmp.rootElement );
		}
	},
	_addRows( cmp ) {
		cmp.newRowElements.forEach( this._elGridCnt.appendChild.bind( this._elGridCnt ) );
	},
	_resizeGrid() {
		this.uiTimeLine.resized();
		this.uiBeatLines.resized();
	},
	_contentScroll( e ) {
		this.contentY( this._contentY + ( 20 * ( e.deltaY > 0 ? 1 : -1 ) ) / this._fontSize );
	},
	_updateGrid() {
		this.uiTimeLine.offset( this._timeOffset, this._pxPerBeat );
		this.uiBeatLines.offset( this._timeOffset, this._pxPerBeat );
		this._timeOffset = this.uiTimeLine._offset;
		this._pxPerBeat = this.uiTimeLine._pxPerBeat;
	},
	_updatePanelSize() {
		this._elPanel.style.width =
		this._elGrid.style.left = this._panelWidth + "px";
		this.uiTimeLine.rootElement.style.left = this._panelWidth - 1 + "px";
		this._resizeGrid();
		this._updateGrid();
	},

	// events:
	_evocCurrentTime( beat ) {
		this.uiBeatLines.currentTime( beat );
		this.onchangeCurrentTime && this.onchangeCurrentTime( beat );
	},
	_evoiLoop( toggle, a, b ) {
		this.uiBeatLines.loop( toggle && a, b );
		this.oninputLoop && this.oninputLoop( toggle, a, b );
	},
	_evmdGrid( e ) {
		if ( e.altKey ) {
			this._gridDragging = true;
			this._mouseOffset = this._timeOffset;
			this._mouseContentY = this._contentY;
			this._mousePageX = e.pageX;
			this._mousePageY = e.pageY;
			gsuiGridSamples._focused = this;
		}
	},
	_evmdPanelEx( e ) {
		this._rootLeft = this.rootElement.getBoundingClientRect().left;
		this._panelResizing = this._elPanelExt.clientWidth - e.layerX;
		this._elPanelExt.classList.add( "gsui-hover" );
		gsuiGridSamples._focused = this;
	},
	_evowGrid( e ) {
		if ( !e.shiftKey && !e.ctrlKey ) {
			this._contentScroll( e );
		} else {
			var layerX, offInc, beatPx = this._pxPerBeat;

			if ( e.ctrlKey ) {
				layerX = e.pageX - this._elGrid.getBoundingClientRect().left;
				beatPx = Math.min( Math.max( 8, beatPx * ( e.deltaY > 0 ? .9 : 1.1 ) ), 512 );
				offInc = ( layerX / this._pxPerBeat * ( beatPx - this._pxPerBeat ) ) / beatPx;
			} else {
				offInc = ( e.deltaY > 0 ? 20 : -20 ) / beatPx;
			}
			this.offset( Math.max( 0, this._timeOffset + offInc ), beatPx );
		}
		return false;
	},
	_evowPanel( e ) {
		if ( e.ctrlKey ) {
			var layerY = e.pageY - this._elPanel.getBoundingClientRect().top,
				oldFs = this._fontSize,
				fs = oldFs * ( e.deltaY > 0 ? .9 : 1.1 );

			this.setFontSize( fs );
			fs = this._fontSize;
			this.contentY( this._contentY + ( layerY / oldFs * ( fs - oldFs ) ) / fs );
		} else if ( !e.shiftKey ) {
			this._contentScroll( e );
		}
		return false;
	},
	_evmmRoot( e ) {
		if ( this._gridDragging ) {
			var of = ( e.pageX - this._mousePageX ) / this._pxPerBeat,
				cy = ( e.pageY - this._mousePageY ) / this._fontSize;

			this.offset( this._mouseOffset - of, this._pxPerBeat );
			this.contentY( this._mouseContentY - cy );
		} else if ( this._panelResizing != null ) {
			this.panelWidth( e.pageX - this._rootLeft + this._panelResizing );
		}
	},
	_evmuRoot( e ) {
		this._elPanelExt.classList.remove( "gsui-hover" );
		delete this._gridDragging;
		delete this._panelResizing;
		delete gsuiGridSamples._focused;
	}
};
<commit_msg>gsuiGridSamples: .timeSignature( a, b )<commit_after>"use strict";

function gsuiGridSamples() {
	var root = this._clone();

	this.rootElement = root;
	this._elPanel = root.querySelector( ".gsui-panel" );
	this._elGrid = root.querySelector( ".gsui-grid" );
	this._elGridCnt = this._elGrid.querySelector( ".gsui-content" );
	this._elPanelExt = this._elPanel.querySelector( ".gsui-extend" );
	this._elPanelCnt = this._elPanel.querySelector( ".gsui-content" );
	this.uiTimeLine = new gsuiTimeLine();
	this.uiBeatLines = new gsuiBeatLines();
	root.prepend( this.uiTimeLine.rootElement );
	this._elGrid.prepend( this.uiBeatLines.rootElement );

	this._elPanelExt.onmousedown = this._evmdPanelEx.bind( this );
	this._elGrid.onmousedown = this._evmdGrid.bind( this );
	this._elGrid.onwheel = this._evowGrid.bind( this );
	this._elPanel.onwheel = this._evowPanel.bind( this );
	this.uiTimeLine.onchangeCurrentTime = this._evocCurrentTime.bind( this );
	this.uiTimeLine.oninputLoop = this._evoiLoop.bind( this );
	this._panelMaxWidth = Infinity;
	this._contentY =
	this._panelMinWidth =
	this._timeOffset = 0;
	this._pxPerBeat = 80;
	this.setFontSize( 40 );
	this.panelWidth( 100 );
}

gsuiGridSamples.prototype = {
	resized() {
		var panelStyle = getComputedStyle( this._elPanel );

		this.width = this.rootElement.clientWidth;
		this._panelMinWidth = parseFloat( panelStyle.minWidth );
		this._panelMaxWidth = parseFloat( panelStyle.maxWidth ) || this.width;
		this._resizeGrid();
		this._updateGrid();
	},
	offset( offset, beatPx ) {
		this._timeOffset = offset;
		this._pxPerBeat = beatPx;
		this._updateGrid();
	},
	timeSignature( a, b ) {
		this.uiTimeLine.timeSignature( a, b );
		this.uiBeatLines.timeSignature( a, b );
	},
	currentTime( beat ) {
		this.uiTimeLine.currentTime( beat );
		this.uiBeatLines.currentTime( beat );
	},
	loop( a, b ) {
		this.uiTimeLine.loop( a, b );
		this.uiBeatLines.loop( a, b );
	},
	panelWidth( width ) {
		width = Math.max( this._panelMinWidth, Math.min( width, this._panelMaxWidth ) );
		if ( this._timeOffset > 0 ) {
			this._timeOffset += ( width - this._panelWidth ) / this._pxPerBeat;
		}
		this._panelWidth = width;
		this._updatePanelSize();
	},
	contentY( yEm ) {
		var h = ( this.uiTrackList || this.uiKeys ).rootElement.clientHeight;

		h = Math.max( 0, h - this._elGrid.clientHeight ) / this._fontSize;
		this._contentY = yEm = Math.min( Math.max( 0, yEm ), h );
		this._elGridCnt.style.marginTop =
		this._elPanelCnt.style.marginTop = -yEm + "em";
	},
	setFontSize( emPx ) {
		this._fontSize = ~~Math.min( Math.max( 16, emPx ), 256 );
		this.rootElement.style.fontSize = this._fontSize + "px";
	},
	loadKeys() {
		this._loadPanelCmp( "uiKeys", "uiTrackList" );
	},
	loadTrackList() {
		this._loadPanelCmp( "uiTrackList", "uiKeys" );
	},
	nbOctaves( from, nbOct ) {
		if ( this.uiKeys ) {
			this.uiKeys.octaves( from, nbOct );
			this._addRows( this.uiKeys );
		}
	},
	nbTracks( n ) {
		if ( this.uiTrackList ) {
			this.uiTrackList.nbTracks( n );
			this._addRows( this.uiTrackList );
		}
	},

	// private:
	_clone() {
		var div = document.createElement( "div" );

		gsuiGridSamples.template = gsuiGridSamples.template || this._init();
		div.appendChild( document.importNode( gsuiGridSamples.template.content, true ) );
		return div.removeChild( div.querySelector( "*" ) );
	},
	_init() {
		document.body.addEventListener( "mousemove", function( e ) {
			gsuiGridSamples._focused && gsuiGridSamples._focused._evmmRoot( e );
		} );
		document.body.addEventListener( "mouseup", function( e ) {
			gsuiGridSamples._focused && gsuiGridSamples._focused._evmuRoot( e );
		} );
		return document.getElementById( "gsuiGridSamples" );
	},
	_loadPanelCmp( cmpStr, oldCmpStr ) {
		var cmp = this[ cmpStr ],
			oldCmp = this[ oldCmpStr ];

		if ( oldCmp ) {
			oldCmp[ oldCmpStr === "uiKeys" ? "octaves" : "nbTracks" ]( 0, 0 );
			oldCmp.rootElement.remove();
			this.setFontSize( this._fontSize * ( oldCmpStr === "uiKeys" ? 1.5 : 2 / 3 ) );
			delete this[ oldCmpStr ];
		}
		if ( !cmp ) {
			this[ cmpStr ] = cmp = cmpStr === "uiKeys" ? new gsuiKeys() : new gsuiTrackList();
			this._elPanelCnt.prepend( cmp.rootElement );
		}
	},
	_addRows( cmp ) {
		cmp.newRowElements.forEach( this._elGridCnt.appendChild.bind( this._elGridCnt ) );
	},
	_resizeGrid() {
		this.uiTimeLine.resized();
		this.uiBeatLines.resized();
	},
	_contentScroll( e ) {
		this.contentY( this._contentY + ( 20 * ( e.deltaY > 0 ? 1 : -1 ) ) / this._fontSize );
	},
	_updateGrid() {
		this.uiTimeLine.offset( this._timeOffset, this._pxPerBeat );
		this.uiBeatLines.offset( this._timeOffset, this._pxPerBeat );
		this._timeOffset = this.uiTimeLine._offset;
		this._pxPerBeat = this.uiTimeLine._pxPerBeat;
	},
	_updatePanelSize() {
		this._elPanel.style.width =
		this._elGrid.style.left = this._panelWidth + "px";
		this.uiTimeLine.rootElement.style.left = this._panelWidth - 1 + "px";
		this._resizeGrid();
		this._updateGrid();
	},

	// events:
	_evocCurrentTime( beat ) {
		this.uiBeatLines.currentTime( beat );
		this.onchangeCurrentTime && this.onchangeCurrentTime( beat );
	},
	_evoiLoop( toggle, a, b ) {
		this.uiBeatLines.loop( toggle && a, b );
		this.oninputLoop && this.oninputLoop( toggle, a, b );
	},
	_evmdGrid( e ) {
		if ( e.altKey ) {
			this._gridDragging = true;
			this._mouseOffset = this._timeOffset;
			this._mouseContentY = this._contentY;
			this._mousePageX = e.pageX;
			this._mousePageY = e.pageY;
			gsuiGridSamples._focused = this;
		}
	},
	_evmdPanelEx( e ) {
		this._rootLeft = this.rootElement.getBoundingClientRect().left;
		this._panelResizing = this._elPanelExt.clientWidth - e.layerX;
		this._elPanelExt.classList.add( "gsui-hover" );
		gsuiGridSamples._focused = this;
	},
	_evowGrid( e ) {
		if ( !e.shiftKey && !e.ctrlKey ) {
			this._contentScroll( e );
		} else {
			var layerX, offInc, beatPx = this._pxPerBeat;

			if ( e.ctrlKey ) {
				layerX = e.pageX - this._elGrid.getBoundingClientRect().left;
				beatPx = Math.min( Math.max( 8, beatPx * ( e.deltaY > 0 ? .9 : 1.1 ) ), 512 );
				offInc = ( layerX / this._pxPerBeat * ( beatPx - this._pxPerBeat ) ) / beatPx;
			} else {
				offInc = ( e.deltaY > 0 ? 20 : -20 ) / beatPx;
			}
			this.offset( Math.max( 0, this._timeOffset + offInc ), beatPx );
		}
		return false;
	},
	_evowPanel( e ) {
		if ( e.ctrlKey ) {
			var layerY = e.pageY - this._elPanel.getBoundingClientRect().top,
				oldFs = this._fontSize,
				fs = oldFs * ( e.deltaY > 0 ? .9 : 1.1 );

			this.setFontSize( fs );
			fs = this._fontSize;
			this.contentY( this._contentY + ( layerY / oldFs * ( fs - oldFs ) ) / fs );
		} else if ( !e.shiftKey ) {
			this._contentScroll( e );
		}
		return false;
	},
	_evmmRoot( e ) {
		if ( this._gridDragging ) {
			var of = ( e.pageX - this._mousePageX ) / this._pxPerBeat,
				cy = ( e.pageY - this._mousePageY ) / this._fontSize;

			this.offset( this._mouseOffset - of, this._pxPerBeat );
			this.contentY( this._mouseContentY - cy );
		} else if ( this._panelResizing != null ) {
			this.panelWidth( e.pageX - this._rootLeft + this._panelResizing );
		}
	},
	_evmuRoot( e ) {
		this._elPanelExt.classList.remove( "gsui-hover" );
		delete this._gridDragging;
		delete this._panelResizing;
		delete gsuiGridSamples._focused;
	}
};
<|endoftext|>


<commit_before>import Table from 'table-layout'
import { promises as fs } from 'fs'
import ansi from 'ansi-escape-sequences'

const rows = JSON.parse(await fs.readFile('./example/data/stock-prices.json', 'utf8'))
const maxValue = Math.max(...rows.map(r => r.return))
const minValue = Math.min(...rows.map(r => r.return))

function getColour (value) {
  const ratio = value >= 0 ? value / maxValue : value / minValue
  return Math.round((100 * ratio) + 155)
}

/* solved via language - user has control */
{
  const proxy = rows.map(row => {
    return new Proxy(row, {
      get (target, property, receiver) {
        if (property === 'return') {
          if (target.return >= 0) {
            return ansi.format(target.return + '%', `fg-rgb(0, ${getColour(target.return)}, 0)`)
          } else {
            return ansi.format(target.return + '%', `fg-rgb(${getColour(target.return)}, 0, 0)`)
          }
        } else {
          return Reflect.get(target, property, receiver)
        }
      }
    })
  })
  const table = new Table(proxy, {
    maxWidth: 60
  })

  console.log(table.toString())
}

<commit_msg>minor optimisation<commit_after>import Table from 'table-layout'
import { promises as fs } from 'fs'
import ansi from 'ansi-escape-sequences'

const rows = JSON.parse(await fs.readFile('./example/data/stock-prices.json', 'utf8'))
const maxValue = Math.max(...rows.map(r => r.return))
const minValue = Math.min(...rows.map(r => r.return))

function getColour (value) {
  const ratio = value >= 0 ? value / maxValue : value / minValue
  return Math.round((100 * ratio) + 155)
}

/* solved via language - user has control */
{
  const proxy = rows.map(row => {
    return new Proxy(row, {
      get (target, property, receiver) {
        if (property === 'return') {
          const ansiColour = target.return >= 0
            ? `fg-rgb(0, ${getColour(target.return)}, 0)`
            : `fg-rgb(${getColour(target.return)}, 0, 0)`
          return ansi.format(target.return + '%', ansiColour)
        } else {
          return Reflect.get(target, property, receiver)
        }
      }
    })
  })
  const table = new Table(proxy, {
    maxWidth: 60
  })

  console.log(table.toString())
}

<|endoftext|>


<commit_before>import React, { Component } from 'react';
import Head from 'next/head';
import { PrismCode } from 'react-prism';
import { Table } from 'reactstrap';
import Layout from '../../components/ComponentsLayout';

import PlayerExample from '../../examples/Player';
import PlayerControlExample from '../../examples/PlayerControl';

export default class PlayerPage extends Component {

  static async getInitialProps ({ query }) {
    const responsePlayer = await fetch(`http://localhost:9000/code/Player.js`)
    const responsePlayerControl = await fetch(`http://localhost:9000/code/PlayerControl.js`)
    const PlayerExampleSource = await responsePlayer.text()
    const PlayerControlExampleSource = await responsePlayerControl.text()
    return { PlayerExampleSource, PlayerControlExampleSource }
  }

  render() {
    const { PlayerExampleSource, PlayerControlExampleSource } = this.props;
    return (
      <Layout page="Player">

          <title>Video-React - Player</title>

Player

          Player is the root component of the Video-React player. All the others components should be in this component.

Attributes

          All the attributes for the Player component, they can be added as React properties.

              Name
              Type
              Default
              Description

              fluid
              bool
              true

                In fluid mode,
                it’s 100% wide all the time,
                the height will be calculated by the video's ratio.

              width
              number
              -
              Video width. (This attribute is effective only if you set fluid as false)

              height
              number
              -
              Video height. (This attribute is effective only if you set fluid as false)

              src
              string
              -

                The URL of the video to embed. This is optional;
                you may instead use the <source> element within the Player block to specify the video to embed.

              poster
              string
              -

                A URL indicating a poster frame to show until the user plays or seeks.
                If this attribute isn't specified, nothing is displayed until the first frame is available;
                then the first frame is shown as the poster frame.

              preload
              enum
              -

                This enumerated attribute is intended to provide a hint to the browser about what the author thinks will lead to the best user experience. It may have one of the following values:

none: indicates that the video should not be preloaded.

metadata: indicates that only video metadata (e.g. length) is fetched.

auto: indicates that the whole video file could be downloaded, even if the user is not expected to use it.

the empty string: synonym of the auto value.

              muted
              bool
              false

                A Boolean attribute which indicates the default setting of the audio contained in the video.
                If set, the audio will be initially silenced.
                Its default value is false, meaning that the audio will be played when the video is played.

              playsInline
              bool
              false

                [iOS only]Determines whether HTML5 videos play inline or use the native full-screen controller.

              aspectRatio
              string
              auto

                The aspect ratio is the width of the video divided by its height.
                Posible values: auto, 16:9, 4:3, etc.

              autoPlay
              bool
              false

                if specified, the video automatically begins to play back as soon as it can do so without stopping to finish loading the data.

              startTime
              number
              -

                Seek the Video at A Specific Time On Load

Properties

              Name
              Description

              playbackRate

                Sets or returns the speed of the video playback. For example:

                  <PrismCode className="language-jsx">
                    {
`<Player ref="player">
  <source src="https://media.w3.org/2010/05/sintel/trailer_hd.mp4" />
</Player>

// access the player object by ref
// set playbackRate to 2
this.refs.player.playbackRate = 2; `
                    }
                  </PrismCode>

              muted
              Sets or returns whether the video is muted or not

              volume
              Sets or returns the volume of the video

              videoWidth
              Returns the width of the video

              videoHeight
              Returns the height of the video

              video
              Returns the Video component object

Methods

          The Player component has some methods to control the video and the player.

              Name
              Description

              getState()

                Get the redux State. For example:

                  <PrismCode className="language-jsx">
                    {
`const { player } = this.refs.player.getState();
console.log(player.currentTime); // print current time`
                    }
                  </PrismCode>

              play()

                Play the video.

              pause()

                Pause the video.

              load()

                Change the video source and re-load the video

              addTextTrack()

                Add a new text track to the video

              canPlayType()

                Check if your browser can play different types of video:

              seek(time)

                Seek video by time (seconds)

              forward(seconds)

                Jump forward x seconds

              replay(seconds)

                Jump back x seconds

              toggleFullscreen()

                Enter or exist full screen

              subscribeToStateChange(listener)

                Subscribe to the player state changes.

                  <PrismCode className="language-jsx">
                    {
`componentDidMount() {
  // subscribe state change
  this.refs.player.subscribeToStateChange(this.handleStateChange.bind(this));
}

handleStateChange(state, prevState) {
  // copy player state to this component's state
  this.setState({
    player: state,
    currentTime: state.currentTime
  });
}`
                    }
                  </PrismCode>

State

          We use redux to manage the player state.
          Using getState method can get the state object.
          This is the list of all the states.

              Name
              Description

              player

                The player state includes all the states about the video and the player.
                Below is the properties list of the player state.

              currentSrc
              Returns the URL of the current video

              duration
              Returns the length of the current video (in seconds)

              currentTime
              Returns the current playback position in the video (in seconds)

              seekingTime
              Returns the current seeking position in the video (in seconds)

              buffered
              Returns a TimeRanges object representing the buffered parts of the video

              waiting
              Returns whether the player needs to buffer the next frame

              seeking
              Returns whether the user is currently seeking in the video

              paused
              Returns whether the player has been paused

              autoPaused
              Returns whether the player has been paused by the player itself

              ended
              Returns whether the playback of the video has ended or not

              playbackRate
              Returns the speed of the video playback

              muted
              Returns whether the video is muted or not

              volume
              Returns the volume of the video

              readyState
              Returns the current ready state of the video

              networkState
              Returns the current network state of the video

              videoWidth
              Returns the volume of the video

              videoHeight
              Returns the height of the video

              hasStarted
              Returns whether the video has been started

              userActivity
              Returns whether the user is in activity.

              isActive
              Returns whether the player is in activity.

              isFullscreen
              Returns whether the player is in fullscreen.

Examples

Some examples to show how to use the player.

Control the player

This is an example on how to control the player from outside the component.

          <PlayerControlExample />

          <PrismCode className="language-jsx">
            {PlayerControlExampleSource}
          </PrismCode>

Change the player url

This is an example on how to change the video url.

          <PlayerExample />

          <PrismCode className="language-jsx">
            {PlayerExampleSource}
          </PrismCode>

      </Layout>
    );
  }
}
<commit_msg>Fixed #88: document typo<commit_after>import React, { Component } from 'react';
import Head from 'next/head';
import { PrismCode } from 'react-prism';
import { Table } from 'reactstrap';
import Layout from '../../components/ComponentsLayout';

import PlayerExample from '../../examples/Player';
import PlayerControlExample from '../../examples/PlayerControl';

export default class PlayerPage extends Component {

  static async getInitialProps ({ query }) {
    const responsePlayer = await fetch(`http://localhost:9000/code/Player.js`)
    const responsePlayerControl = await fetch(`http://localhost:9000/code/PlayerControl.js`)
    const PlayerExampleSource = await responsePlayer.text()
    const PlayerControlExampleSource = await responsePlayerControl.text()
    return { PlayerExampleSource, PlayerControlExampleSource }
  }

  render() {
    const { PlayerExampleSource, PlayerControlExampleSource } = this.props;
    return (
      <Layout page="Player">

          <title>Video-React - Player</title>

Player

          Player is the root component of the Video-React player. All the others components should be in this component.

Attributes

          All the attributes for the Player component, they can be added as React properties.

              Name
              Type
              Default
              Description

              fluid
              bool
              true

                In fluid mode,
                it’s 100% wide all the time,
                the height will be calculated by the video's ratio.

              width
              number
              -
              Video width. (This attribute is effective only if you set fluid as false)

              height
              number
              -
              Video height. (This attribute is effective only if you set fluid as false)

              src
              string
              -

                The URL of the video to embed. This is optional;
                you may instead use the <source> element within the Player block to specify the video to embed.

              poster
              string
              -

                A URL indicating a poster frame to show until the user plays or seeks.
                If this attribute isn't specified, nothing is displayed until the first frame is available;
                then the first frame is shown as the poster frame.

              preload
              enum
              -

                This enumerated attribute is intended to provide a hint to the browser about what the author thinks will lead to the best user experience. It may have one of the following values:

none: indicates that the video should not be preloaded.

metadata: indicates that only video metadata (e.g. length) is fetched.

auto: indicates that the whole video file could be downloaded, even if the user is not expected to use it.

the empty string: synonym of the auto value.

              muted
              bool
              false

                A Boolean attribute which indicates the default setting of the audio contained in the video.
                If set, the audio will be initially silenced.
                Its default value is false, meaning that the audio will be played when the video is played.

              playsInline
              bool
              false

                [iOS only]Determines whether HTML5 videos play inline or use the native full-screen controller.

              aspectRatio
              string
              auto

                The aspect ratio is the width of the video divided by its height.
                Posible values: auto, 16:9, 4:3, etc.

              autoPlay
              bool
              false

                if specified, the video automatically begins to play back as soon as it can do so without stopping to finish loading the data.

              startTime
              number
              -

                Seek the Video at A Specific Time On Load

Properties

              Name
              Description

              playbackRate

                Sets or returns the speed of the video playback. For example:

                  <PrismCode className="language-jsx">
                    {
`<Player ref="player">
  <source src="https://media.w3.org/2010/05/sintel/trailer_hd.mp4" />
</Player>

// access the player object by ref
// set playbackRate to 2
this.refs.player.playbackRate = 2; `
                    }
                  </PrismCode>

              muted
              Sets or returns whether the video is muted or not

              volume
              Sets or returns the volume of the video

              videoWidth
              Returns the width of the video

              videoHeight
              Returns the height of the video

              video
              Returns the Video component object

Methods

          The Player component has some methods to control the video and the player.

              Name
              Description

              getState()

                Get the redux State. For example:

                  <PrismCode className="language-jsx">
                    {
`const { player } = this.refs.player.getState();
console.log(player.currentTime); // print current time`
                    }
                  </PrismCode>

              play()

                Play the video.

              pause()

                Pause the video.

              load()

                Change the video source and re-load the video

              addTextTrack()

                Add a new text track to the video

              canPlayType()

                Check if your browser can play different types of video:

              seek(time)

                Seek video by time (seconds)

              forward(seconds)

                Jump forward x seconds

              replay(seconds)

                Jump back x seconds

              toggleFullscreen()

                Enter or exist full screen

              subscribeToStateChange(listener)

                Subscribe to the player state changes.

                  <PrismCode className="language-jsx">
                    {
`componentDidMount() {
  // subscribe state change
  this.refs.player.subscribeToStateChange(this.handleStateChange.bind(this));
}

handleStateChange(state, prevState) {
  // copy player state to this component's state
  this.setState({
    player: state,
    currentTime: state.currentTime
  });
}`
                    }
                  </PrismCode>

State

          We use redux to manage the player state.
          Using getState method can get the state object.
          This is the list of all the states.

              Name
              Description

              player

                The player state includes all the states about the video and the player.
                Below is the properties list of the player state.

              currentSrc
              Returns the URL of the current video

              duration
              Returns the length of the current video (in seconds)

              currentTime
              Returns the current playback position in the video (in seconds)

              seekingTime
              Returns the current seeking position in the video (in seconds)

              buffered
              Returns a TimeRanges object representing the buffered parts of the video

              waiting
              Returns whether the player needs to buffer the next frame

              seeking
              Returns whether the user is currently seeking in the video

              paused
              Returns whether the player has been paused

              autoPaused
              Returns whether the player has been paused by the player itself

              ended
              Returns whether the playback of the video has ended or not

              playbackRate
              Returns the speed of the video playback

              muted
              Returns whether the video is muted or not

              volume
              Returns the volume of the video

              readyState
              Returns the current ready state of the video

              networkState
              Returns the current network state of the video

              videoWidth
              Returns the width of the video

              videoHeight
              Returns the height of the video

              hasStarted
              Returns whether the video has been started

              userActivity
              Returns whether the user is in activity.

              isActive
              Returns whether the player is in activity.

              isFullscreen
              Returns whether the player is in fullscreen.

Examples

Some examples to show how to use the player.

Control the player

This is an example on how to control the player from outside the component.

          <PlayerControlExample />

          <PrismCode className="language-jsx">
            {PlayerControlExampleSource}
          </PrismCode>

Change the player url

This is an example on how to change the video url.

          <PlayerExample />

          <PrismCode className="language-jsx">
            {PlayerExampleSource}
          </PrismCode>

      </Layout>
    );
  }
}
<|endoftext|>


<commit_before>'use strict';

module.exports = {
  js: {
    files: ['<%= yeoman.app %>/scripts/**/*.js'],
    // tasks: ['newer:jshint:all'],
    options: {
      livereload: true
    }
  },
  compass: {
    files: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
    tasks: ['compass:server', 'autoprefixer']
  },
  gruntfile: {
    files: ['Gruntfile.js']
  },
  livereload: {
    options: {
      livereload: '<%= connect.options.livereload %>'
    },
    files: ['<%= yeoman.app %>/views/**/*.html','.tmp/styles/{,*/}*.css']
  }
};
<commit_msg>Avoid a annoying bug of grunt serve on Windows<commit_after>'use strict';

module.exports = {
  js: {
    files: ['<%= yeoman.app %>/scripts/**/*.js'],
    // tasks: ['newer:jshint:all'],
    options: {
      interval: 5000,
      livereload: true
    }
  },
  compass: {
    files: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
    tasks: ['compass:server', 'autoprefixer']
  },
  gruntfile: {
    files: ['Gruntfile.js']
  },
  livereload: {
    options: {
      livereload: '<%= connect.options.livereload %>'
    },
    files: ['<%= yeoman.app %>/views/**/*.html','.tmp/styles/{,*/}*.css']
  }
};
<|endoftext|>


<commit_before>'use strict';

const assert = require('assert');
const _ = require('lodash');
const Promise = require('bluebird');
const errors = require('../common/errors');
const logger = require('../common/logger');
const utils = require('../common/utils');
const catalog = require('../common/models/catalog');
const FabrikBaseController = require('./FabrikBaseController');
const lockManager = require('../data-access-layer/eventmesh').lockManager;
const AssertionError = assert.AssertionError;
const BadRequest = errors.BadRequest;
const PreconditionFailed = errors.PreconditionFailed;
const NotFound = errors.NotFound;
const ServiceInstanceNotFound = errors.ServiceInstanceNotFound;
const ServiceBindingAlreadyExists = errors.ServiceBindingAlreadyExists;
const ContinueWithNext = errors.ContinueWithNext;
const CONST = require('../common/constants');
const eventmesh = require('../data-access-layer/eventmesh');
const config = require('../common/config');
const formatUrl = require('url').format;

class ServiceBrokerApiController extends FabrikBaseController {
  constructor() {
    super();
  }

  apiVersion(req, res) {
    /* jshint unused:false */
    const minVersion = CONST.SF_BROKER_API_VERSION_MIN;
    const version = _.get(req.headers, 'x-broker-api-version', '1.0');
    return Promise
      .try(() => {
        if (utils.compareVersions(version, minVersion) >= 0) {
          return;
        } else {
          throw new PreconditionFailed(`At least Broker API version ${minVersion} is required.`);
        }
      })
      .throw(new ContinueWithNext());
  }

  getCatalog(req, res) {
    /* jshint unused:false */
    res.status(CONST.HTTP_STATUS_CODE.OK).json(this.fabrik.getPlatformManager(req.params.platform).getCatalog(catalog));
  }

  putInstance(req, res) {
    const params = req.body;
    const planId = params.plan_id;
    const plan = catalog.getPlan(planId);

    function getDashboardUrl(serviceId, planId, instanceGuid) {
      return formatUrl(_
        .chain(config.external)
        .pick('protocol', 'host')
        .set('slashes', true)
        .set('pathname', `/manage/instances/${serviceId}/${planId}/${instanceGuid}`)
        .value()
      );
    }

    function done() {
      let statusCode = CONST.HTTP_STATUS_CODE.CREATED;
      const body = {
        dashboard_url: getDashboardUrl(params.service_id, params.plan_id, req.params.instance_id)
      };
      if (plan.manager.async) {
        statusCode = CONST.HTTP_STATUS_CODE.ACCEPTED;
      }
      res.status(statusCode).send(body);
    }

    req.operation_type = CONST.OPERATION_TYPE.CREATE;
    return Promise
      .try(() => {
        return eventmesh.apiServerClient.createResource({
          resourceGroup: plan.manager.resource_mappings.resource_group,
          resourceType: plan.manager.resource_mappings.resource_type,
          resourceId: req.params.instance_id,
          options: params,
          status: {
            state: CONST.APISERVER.RESOURCE_STATE.IN_QUEUE,
            lastOperation: {},
            response: {}
          }
        });
      })
      .then(() => {
        if (!plan.manager.async) {
          return eventmesh.apiServerClient.getResourceOperationStatus({
            resourceGroup: plan.manager.resource_mappings.resource_group,
            resourceType: plan.manager.resource_mappings.resource_type,
            resourceId: req.params.instance_id,
            start_state: CONST.APISERVER.RESOURCE_STATE.IN_QUEUE,
            started_at: new Date()
          });
        }
      })
      .then(done);
  }

  patchInstance(req, res) {
    const params = _
      .chain(req.body)
      // .omit('plan_id', 'service_id') //Not omiting even for restore. will that be a problem?
      .cloneDeep()
      .value();
    //cloning here so that the DirectorInstance.update does not unset the 'service-fabrik-operation' from original req.body object
    const isRestoreOperation = _.get(params.parameters, 'service-fabrik-operation', null) ? true : false;
    req.operation_type = CONST.OPERATION_TYPE.UPDATE;
    const planId = params.plan_id;
    const plan = catalog.getPlan(planId);

    function done(result) {
      let statusCode = CONST.HTTP_STATUS_CODE.OK;
      const body = {};
      if (plan.manager.async) {
        statusCode = CONST.HTTP_STATUS_CODE.ACCEPTED;
        if (isRestoreOperation) {
          body.operation = utils.encodeBase64(result);
        }
      }
      res.status(statusCode).send(body);
    }

    function isUpdatePossible(previousPlanId) {
      const planId = params.plan_id;
      const plan = catalog.getPlan(planId);
      const previousPlan = _.find(plan.service.plans, ['id', previousPlanId]);
      return plan === previousPlan || _.includes(plan.manager.settings.update_predecessors, previousPlan.id);
    }

    if (isRestoreOperation) {
      return Promise
        .try(() => {
          if (!req.manager.isUpdatePossible(params.previous_values.plan_id)) { //ideally this can also use the local function but not changing as this piece of code anyways go away once restore manager in place.
            throw new BadRequest(`Update to plan '${req.manager.plan.name}' is not possible`);
          }
          return req.instance.update(params);
        })
        .then(done);
    } else {
      return Promise
        .try(() => {
          if (!isUpdatePossible(params.previous_values.plan_id)) {
            throw new BadRequest(`Update to plan '${req.manager.plan.name}' is not possible`);
          }
        })
        //TODO : handle existing cases
        .then(() => {
          return eventmesh.apiServerClient.updateResource({
            resourceGroup: plan.manager.resource_mappings.resource_group,
            resourceType: plan.manager.resource_mappings.resource_type,
            resourceId: req.params.instance_id,
            options: params,
            status: {
              state: CONST.APISERVER.RESOURCE_STATE.UPDATE,
              lastOperation: {},
              response: {}
            }
          });
        })
        .catch(NotFound, () => {
          logger.info(`Resource resourceGroup: ${plan.manager.resource_mappings.resource_group},` +
            `resourceType: ${plan.manager.resource_mappings.resource_type}, resourceId: ${req.params.instance_id} not found, Creating now...`);
          return eventmesh.apiServerClient.createResource({
            resourceGroup: plan.manager.resource_mappings.resource_group,
            resourceType: plan.manager.resource_mappings.resource_type,
            resourceId: req.params.instance_id,
            options: params,
            status: {
              state: CONST.APISERVER.RESOURCE_STATE.UPDATE,
              lastOperation: {},
              response: {}
            }
          });
        })
        .then(() => {
          if (!plan.manager.async) {
            return eventmesh.apiServerClient.getResourceOperationStatus({
              resourceGroup: plan.manager.resource_mappings.resource_group,
              resourceType: plan.manager.resource_mappings.resource_type,
              resourceId: req.params.instance_id,
              start_state: CONST.APISERVER.RESOURCE_STATE.UPDATE,
              started_at: new Date()
            });
          }
        })
        .then(done);
    }
  }

  deleteInstance(req, res) {
    const params = req.query;
    const planId = params.plan_id;
    const plan = catalog.getPlan(planId);

    function done() {
      let statusCode = CONST.HTTP_STATUS_CODE.OK;
      const body = {};
      if (plan.manager.async) {
        // Delete resource from here
        statusCode = CONST.HTTP_STATUS_CODE.ACCEPTED;
      }
      res.status(statusCode).send(body);
    }

    function gone(err) {
      /* jshint unused:false */
      res.status(CONST.HTTP_STATUS_CODE.GONE).send({});
    }
    req.operation_type = CONST.OPERATION_TYPE.DELETE;

    return Promise
      .try(() => {
        return eventmesh.apiServerClient.updateResource({
          resourceGroup: plan.manager.resource_mappings.resource_group,
          resourceType: plan.manager.resource_mappings.resource_type,
          resourceId: req.params.instance_id,
          options: params,
          status: {
            state: CONST.APISERVER.RESOURCE_STATE.DELETE,
            lastOperation: {},
            response: {}
          }
        });
      })
      .catch(NotFound, () => {
        logger.info(`Resource resourceGroup: ${plan.manager.resource_mappings.resource_group},` +
          `resourceType: ${plan.manager.resource_mappings.resource_type}, resourceId: ${req.params.instance_id} not found, Creating now...`);
        return eventmesh.apiServerClient.createResource({
          resourceGroup: plan.manager.resource_mappings.resource_group,
          resourceType: plan.manager.resource_mappings.resource_type,
          resourceId: req.params.instance_id,
          options: params,
          status: {
            state: CONST.APISERVER.RESOURCE_STATE.DELETE,
            lastOperation: {},
            response: {}
          }
        });
      })
      .then(() => {
        if (!plan.manager.async) {
          return eventmesh.apiServerClient.getResourceOperationStatus({
            resourceGroup: plan.manager.resource_mappings.resource_group,
            resourceType: plan.manager.resource_mappings.resource_type,
            resourceId: req.params.instance_id,
            start_state: CONST.APISERVER.RESOURCE_STATE.DELETE,
            started_at: new Date()
          });
        }
      })
      .then(done)
      .catch(ServiceInstanceNotFound, gone);
  }
  getLastInstanceOperation(req, res) {
    const encodedOp = _.get(req, 'query.operation', undefined);
    const operation = encodedOp === undefined ? null : utils.decodeBase64(encodedOp);
    const guid = req.params.instance_id;
    let action, instanceType;
    if (operation) {
      action = _.capitalize(operation.type);
      instanceType = req.instance.constructor.typeDescription;
    }

    function done(result) {
      const body = _.pick(result, 'state', 'description');
      // Unlock resource if state is succeeded or failed
      if (result.state === CONST.OPERATION.SUCCEEDED || result.state === CONST.OPERATION.FAILED) {
        return lockManager.unlock(req.params.instance_id)
          .then(() => res.status(CONST.HTTP_STATUS_CODE.OK).send(body));
      }
      res.status(CONST.HTTP_STATUS_CODE.OK).send(body);
    }

    function failed(err) {
      return lockManager.unlock(req.params.instance_id)
        .then(() => res.status(CONST.HTTP_STATUS_CODE.OK).send({
          state: CONST.OPERATION.FAILED,
          description: `${action} ${instanceType} '${guid}' failed because "${err.message}"`
        }));
    }

    function gone() {
      return lockManager.unlock(req.params.instance_id)
        .then(() => res.status(CONST.HTTP_STATUS_CODE.GONE).send({}));
    }

    function notFound(err) {
      if (operation && operation.type === 'delete') {
        return gone();
      } else if (!operation) { //TODO : for non delete case, check when notfound is thrown and handle. similarly for AssertionError
        //      failed(err);
        return gone();
      }
      failed(err);
    }

    if (operation) { // keeping it to support last operation for the restore and for any ongoing update, delete?
      return req.instance.lastOperation(operation)
        .then(done)
        .catch(AssertionError, failed)
        .catch(ServiceInstanceNotFound, notFound);
    } else {
      const planId = req.query.plan_id;
      const plan = catalog.getPlan(planId);
      return eventmesh.apiServerClient.getLastOperation({
          resourceGroup: plan.manager.resource_mappings.resource_group,
          resourceType: plan.manager.resource_mappings.resource_type,
          resourceId: req.params.instance_id
        })
        .then(done)
        .catch(AssertionError, failed)
        .catch(NotFound, notFound);
    }
  }

  putBinding(req, res) {
    const params = _(req.body)
      .set('binding_id', req.params.binding_id)
      .value();

    function done(credentials) {
      // omit credentials from resource response
      return eventmesh.apiServerClient.updateResource({
          resourceGroup: plan.manager.resource_mappings.bind.resource_group,
          resourceType: plan.manager.resource_mappings.bind.resource_type,
          resourceId: params.binding_id,
          status: {
            response: {}
          }
        })
        .then(() => res.status(CONST.HTTP_STATUS_CODE.CREATED).send({
          credentials: credentials
        }));
    }

    function conflict(err) {
      /* jshint unused:false */
      res.status(CONST.HTTP_STATUS_CODE.CONFLICT).send({});
    }

    const planId = params.plan_id;
    const plan = catalog.getPlan(planId);

    return Promise
      .try(() => {
        return eventmesh.apiServerClient.createResource({
          resourceGroup: plan.manager.resource_mappings.bind.resource_group,
          resourceType: plan.manager.resource_mappings.bind.resource_type,
          resourceId: params.binding_id,
          labels: {
            instance_guid: req.params.instance_id
          },
          options: params,
          status: {
            state: CONST.APISERVER.RESOURCE_STATE.IN_QUEUE
          }
        });
      })
      .then(() => eventmesh.apiServerClient.getResourceOperationStatus({
        resourceGroup: plan.manager.resource_mappings.bind.resource_group,
        resourceType: plan.manager.resource_mappings.bind.resource_type,
        resourceId: params.binding_id,
        start_state: CONST.APISERVER.RESOURCE_STATE.IN_QUEUE,
        started_at: new Date()
      }))
      .then(operationStatus => done(operationStatus.response))
      .catch(ServiceBindingAlreadyExists, conflict);
  }

  deleteBinding(req, res) {
    const params = _(req.query)
      .set('binding_id', req.params.binding_id)
      .value();

    function done() {
      res.status(CONST.HTTP_STATUS_CODE.OK).send({});
    }

    function gone(err) {
      /* jshint unused:false */
      res.status(CONST.HTTP_STATUS_CODE.GONE).send({});
    }
    const planId = params.plan_id;
    const plan = catalog.getPlan(planId);

    return Promise
      .try(() => {
        return eventmesh.apiServerClient.updateResource({
            resourceGroup: plan.manager.resource_mappings.bind.resource_group,
            resourceType: plan.manager.resource_mappings.bind.resource_type,
            resourceId: params.binding_id,
            options: params,
            status: {
              state: CONST.APISERVER.RESOURCE_STATE.DELETE
            }
          })
          .catch((NotFound), () => {
            logger.info(`Resource resourceGroup: ${plan.manager.resource_mappings.bind.resource_group},` +
              `resourceType: ${plan.manager.resource_mappings.bind.resource_type}, resourceId: ${params.binding_id} not found, Creating now...`);
            return eventmesh.apiServerClient.createResource({
              resourceGroup: plan.manager.resource_mappings.bind.resource_group,
              resourceType: plan.manager.resource_mappings.bind.resource_type,
              resourceId: params.binding_id,
              labels: {
                instance_guid: req.params.instance_id
              },
              options: params,
              status: {
                state: CONST.APISERVER.RESOURCE_STATE.DELETE
              }
            });
          });
      })
      .then(() => eventmesh.apiServerClient.getResourceOperationStatus({
        resourceGroup: plan.manager.resource_mappings.bind.resource_group,
        resourceType: plan.manager.resource_mappings.bind.resource_type,
        resourceId: params.binding_id,
        start_state: CONST.APISERVER.RESOURCE_STATE.DELETE,
        started_at: new Date()
      }))
      .then(() => eventmesh.apiServerClient.deleteResource({
        resourceGroup: plan.manager.resource_mappings.bind.resource_group,
        resourceType: plan.manager.resource_mappings.bind.resource_type,
        resourceId: params.binding_id
      }))
      .then(done)
      .catch(NotFound, gone);
  }

}

module.exports = ServiceBrokerApiController;<commit_msg>Error handling first part<commit_after>'use strict';

const assert = require('assert');
const _ = require('lodash');
const Promise = require('bluebird');
const errors = require('../common/errors');
const logger = require('../common/logger');
const utils = require('../common/utils');
const catalog = require('../common/models/catalog');
const FabrikBaseController = require('./FabrikBaseController');
const lockManager = require('../data-access-layer/eventmesh').lockManager;
const AssertionError = assert.AssertionError;
const BadRequest = errors.BadRequest;
const PreconditionFailed = errors.PreconditionFailed;
const NotFound = errors.NotFound;
const ServiceInstanceNotFound = errors.ServiceInstanceNotFound;
const ServiceBindingAlreadyExists = errors.ServiceBindingAlreadyExists;
const ContinueWithNext = errors.ContinueWithNext;
const Conflict = errors.Conflict;
const CONST = require('../common/constants');
const eventmesh = require('../data-access-layer/eventmesh');
const config = require('../common/config');
const formatUrl = require('url').format;

class ServiceBrokerApiController extends FabrikBaseController {
  constructor() {
    super();
  }

  apiVersion(req, res) {
    /* jshint unused:false */
    const minVersion = CONST.SF_BROKER_API_VERSION_MIN;
    const version = _.get(req.headers, 'x-broker-api-version', '1.0');
    return Promise
      .try(() => {
        if (utils.compareVersions(version, minVersion) >= 0) {
          return;
        } else {
          throw new PreconditionFailed(`At least Broker API version ${minVersion} is required.`);
        }
      })
      .throw(new ContinueWithNext());
  }

  getCatalog(req, res) {
    /* jshint unused:false */
    res.status(CONST.HTTP_STATUS_CODE.OK).json(this.fabrik.getPlatformManager(req.params.platform).getCatalog(catalog));
  }

  putInstance(req, res) {
    const params = req.body;
    const planId = params.plan_id;
    const plan = catalog.getPlan(planId);

    function getDashboardUrl(serviceId, planId, instanceGuid) {
      return formatUrl(_
        .chain(config.external)
        .pick('protocol', 'host')
        .set('slashes', true)
        .set('pathname', `/manage/instances/${serviceId}/${planId}/${instanceGuid}`)
        .value()
      );
    }

    function done() {
      let statusCode = CONST.HTTP_STATUS_CODE.CREATED;
      const body = {
        dashboard_url: getDashboardUrl(params.service_id, params.plan_id, req.params.instance_id)
      };
      if (plan.manager.async) {
        statusCode = CONST.HTTP_STATUS_CODE.ACCEPTED;
      }
      res.status(statusCode).send(body);
    }
    function conflict() {
      res.status(CONST.HTTP_STATUS_CODE.CONFLICT).send({});
    }

    req.operation_type = CONST.OPERATION_TYPE.CREATE;
    return Promise
      .try(() => {
        return eventmesh.apiServerClient.createResource({
          resourceGroup: plan.manager.resource_mappings.resource_group,
          resourceType: plan.manager.resource_mappings.resource_type,
          resourceId: req.params.instance_id,
          options: params,
          status: {
            state: CONST.APISERVER.RESOURCE_STATE.IN_QUEUE,
            lastOperation: {},
            response: {}
          }
        });
      })
      .then(() => {
        if (!plan.manager.async) {
          return eventmesh.apiServerClient.getResourceOperationStatus({
            resourceGroup: plan.manager.resource_mappings.resource_group,
            resourceType: plan.manager.resource_mappings.resource_type,
            resourceId: req.params.instance_id,
            start_state: CONST.APISERVER.RESOURCE_STATE.IN_QUEUE,
            started_at: new Date()
          });
        }
      })
      .then(done)
      .catch(Conflict, conflict);
  }

  patchInstance(req, res) {
    const params = _
      .chain(req.body)
      // .omit('plan_id', 'service_id') //Not omiting even for restore. will that be a problem?
      .cloneDeep()
      .value();
    //cloning here so that the DirectorInstance.update does not unset the 'service-fabrik-operation' from original req.body object
    const isRestoreOperation = _.get(params.parameters, 'service-fabrik-operation', null) ? true : false;
    req.operation_type = CONST.OPERATION_TYPE.UPDATE;
    const planId = params.plan_id;
    const plan = catalog.getPlan(planId);

    function done(result) {
      let statusCode = CONST.HTTP_STATUS_CODE.OK;
      const body = {};
      if (plan.manager.async) {
        statusCode = CONST.HTTP_STATUS_CODE.ACCEPTED;
        if (isRestoreOperation) {
          body.operation = utils.encodeBase64(result);
        }
      }
      res.status(statusCode).send(body);
    }

    function isUpdatePossible(previousPlanId) {
      const planId = params.plan_id;
      const plan = catalog.getPlan(planId);
      const previousPlan = _.find(plan.service.plans, ['id', previousPlanId]);
      return plan === previousPlan || _.includes(plan.manager.settings.update_predecessors, previousPlan.id);
    }

    if (isRestoreOperation) {
      return Promise
        .try(() => {
          if (!req.manager.isUpdatePossible(params.previous_values.plan_id)) { //ideally this can also use the local function but not changing as this piece of code anyways go away once restore manager in place.
            throw new BadRequest(`Update to plan '${req.manager.plan.name}' is not possible`);
          }
          return req.instance.update(params);
        })
        .then(done);
    } else {
      return Promise
        .try(() => {
          if (!isUpdatePossible(params.previous_values.plan_id)) {
            throw new BadRequest(`Update to plan '${req.manager.plan.name}' is not possible`);
          }
        })
        //TODO : handle existing cases
        .then(() => {
          return eventmesh.apiServerClient.updateResource({
            resourceGroup: plan.manager.resource_mappings.resource_group,
            resourceType: plan.manager.resource_mappings.resource_type,
            resourceId: req.params.instance_id,
            options: params,
            status: {
              state: CONST.APISERVER.RESOURCE_STATE.UPDATE,
              lastOperation: {},
              response: {}
            }
          });
        })
        .catch(NotFound, () => {
          logger.info(`Resource resourceGroup: ${plan.manager.resource_mappings.resource_group},` +
            `resourceType: ${plan.manager.resource_mappings.resource_type}, resourceId: ${req.params.instance_id} not found, Creating now...`);
          return eventmesh.apiServerClient.createResource({
            resourceGroup: plan.manager.resource_mappings.resource_group,
            resourceType: plan.manager.resource_mappings.resource_type,
            resourceId: req.params.instance_id,
            options: params,
            status: {
              state: CONST.APISERVER.RESOURCE_STATE.UPDATE,
              lastOperation: {},
              response: {}
            }
          });
        })
        .then(() => {
          if (!plan.manager.async) {
            return eventmesh.apiServerClient.getResourceOperationStatus({
              resourceGroup: plan.manager.resource_mappings.resource_group,
              resourceType: plan.manager.resource_mappings.resource_type,
              resourceId: req.params.instance_id,
              start_state: CONST.APISERVER.RESOURCE_STATE.UPDATE,
              started_at: new Date()
            });
          }
        })
        .then(done);
    }
  }

  deleteInstance(req, res) {
    const params = req.query;
    const planId = params.plan_id;
    const plan = catalog.getPlan(planId);

    function done() {
      let statusCode = CONST.HTTP_STATUS_CODE.OK;
      const body = {};
      if (plan.manager.async) {
        // Delete resource from here
        statusCode = CONST.HTTP_STATUS_CODE.ACCEPTED;
      }
      res.status(statusCode).send(body);
    }
    req.operation_type = CONST.OPERATION_TYPE.DELETE;

    return Promise
      .try(() => {
        return eventmesh.apiServerClient.updateResource({
          resourceGroup: plan.manager.resource_mappings.resource_group,
          resourceType: plan.manager.resource_mappings.resource_type,
          resourceId: req.params.instance_id,
          options: params,
          status: {
            state: CONST.APISERVER.RESOURCE_STATE.DELETE,
            lastOperation: {},
            response: {}
          }
        });
      })
      .catch(NotFound, () => {
        logger.info(`Resource resourceGroup: ${plan.manager.resource_mappings.resource_group},` +
          `resourceType: ${plan.manager.resource_mappings.resource_type}, resourceId: ${req.params.instance_id} not found, Creating now...`);
        return eventmesh.apiServerClient.createResource({
          resourceGroup: plan.manager.resource_mappings.resource_group,
          resourceType: plan.manager.resource_mappings.resource_type,
          resourceId: req.params.instance_id,
          options: params,
          status: {
            state: CONST.APISERVER.RESOURCE_STATE.DELETE,
            lastOperation: {},
            response: {}
          }
        });
      })
      .then(() => {
        if (!plan.manager.async) {
          return eventmesh.apiServerClient.getResourceOperationStatus({
            resourceGroup: plan.manager.resource_mappings.resource_group,
            resourceType: plan.manager.resource_mappings.resource_type,
            resourceId: req.params.instance_id,
            start_state: CONST.APISERVER.RESOURCE_STATE.DELETE,
            started_at: new Date()
          });
        }
      })
      .then(done);
  }
  getLastInstanceOperation(req, res) {
    const encodedOp = _.get(req, 'query.operation', undefined);
    const operation = encodedOp === undefined ? null : utils.decodeBase64(encodedOp);
    const guid = req.params.instance_id;
    let action, instanceType;
    if (operation) {
      action = _.capitalize(operation.type);
      instanceType = req.instance.constructor.typeDescription;
    }

    function done(result) {
      const body = _.pick(result, 'state', 'description');
      // Unlock resource if state is succeeded or failed
      if (result.state === CONST.OPERATION.SUCCEEDED || result.state === CONST.OPERATION.FAILED) {
        return lockManager.unlock(req.params.instance_id)
          .then(() => res.status(CONST.HTTP_STATUS_CODE.OK).send(body));
      }
      res.status(CONST.HTTP_STATUS_CODE.OK).send(body);
    }

    function failed(err) {
      return lockManager.unlock(req.params.instance_id)
        .then(() => res.status(CONST.HTTP_STATUS_CODE.OK).send({
          state: CONST.OPERATION.FAILED,
          description: `${action} ${instanceType} '${guid}' failed because "${err.message}"`
        }));
    }

    function gone() {
      return lockManager.unlock(req.params.instance_id)
        .then(() => res.status(CONST.HTTP_STATUS_CODE.GONE).send({}));
    }

    function notFound(err) {
      if (operation && operation.type === 'delete') {
        return gone();
      } else if (!operation) { //TODO : for non delete case, check when notfound is thrown and handle. similarly for AssertionError
        //      failed(err);
        return gone();
      }
      failed(err);
    }

    if (operation) { // keeping it to support last operation for the restore and for any ongoing update, delete?
      return req.instance.lastOperation(operation)
        .then(done)
        .catch(AssertionError, failed)
        .catch(ServiceInstanceNotFound, notFound);
    } else {
      const planId = req.query.plan_id;
      const plan = catalog.getPlan(planId);
      return eventmesh.apiServerClient.getLastOperation({
          resourceGroup: plan.manager.resource_mappings.resource_group,
          resourceType: plan.manager.resource_mappings.resource_type,
          resourceId: req.params.instance_id
        })
        .then(done)
        .catch(NotFound, notFound);
    }
  }

  putBinding(req, res) {
    const params = _(req.body)
      .set('binding_id', req.params.binding_id)
      .value();

    function done(credentials) {
      // omit credentials from resource response
      return eventmesh.apiServerClient.updateResource({
          resourceGroup: plan.manager.resource_mappings.bind.resource_group,
          resourceType: plan.manager.resource_mappings.bind.resource_type,
          resourceId: params.binding_id,
          status: {
            response: {}
          }
        })
        .then(() => res.status(CONST.HTTP_STATUS_CODE.CREATED).send({
          credentials: credentials
        }));
    }

    function conflict(err) {
      /* jshint unused:false */
      res.status(CONST.HTTP_STATUS_CODE.CONFLICT).send({});
    }

    const planId = params.plan_id;
    const plan = catalog.getPlan(planId);

    return Promise
      .try(() => {
        return eventmesh.apiServerClient.createResource({
          resourceGroup: plan.manager.resource_mappings.bind.resource_group,
          resourceType: plan.manager.resource_mappings.bind.resource_type,
          resourceId: params.binding_id,
          labels: {
            instance_guid: req.params.instance_id
          },
          options: params,
          status: {
            state: CONST.APISERVER.RESOURCE_STATE.IN_QUEUE
          }
        });
      })
      .then(() => eventmesh.apiServerClient.getResourceOperationStatus({
        resourceGroup: plan.manager.resource_mappings.bind.resource_group,
        resourceType: plan.manager.resource_mappings.bind.resource_type,
        resourceId: params.binding_id,
        start_state: CONST.APISERVER.RESOURCE_STATE.IN_QUEUE,
        started_at: new Date()
      }))
      .then(operationStatus => done(operationStatus.response))
      .catch(ServiceBindingAlreadyExists, conflict);
  }

  deleteBinding(req, res) {
    const params = _(req.query)
      .set('binding_id', req.params.binding_id)
      .value();

    function done() {
      res.status(CONST.HTTP_STATUS_CODE.OK).send({});
    }

    function gone(err) {
      /* jshint unused:false */
      res.status(CONST.HTTP_STATUS_CODE.GONE).send({});
    }
    const planId = params.plan_id;
    const plan = catalog.getPlan(planId);

    return Promise
      .try(() => {
        return eventmesh.apiServerClient.updateResource({
            resourceGroup: plan.manager.resource_mappings.bind.resource_group,
            resourceType: plan.manager.resource_mappings.bind.resource_type,
            resourceId: params.binding_id,
            options: params,
            status: {
              state: CONST.APISERVER.RESOURCE_STATE.DELETE
            }
          })
          .catch((NotFound), () => {
            logger.info(`Resource resourceGroup: ${plan.manager.resource_mappings.bind.resource_group},` +
              `resourceType: ${plan.manager.resource_mappings.bind.resource_type}, resourceId: ${params.binding_id} not found, Creating now...`);
            return eventmesh.apiServerClient.createResource({
              resourceGroup: plan.manager.resource_mappings.bind.resource_group,
              resourceType: plan.manager.resource_mappings.bind.resource_type,
              resourceId: params.binding_id,
              labels: {
                instance_guid: req.params.instance_id
              },
              options: params,
              status: {
                state: CONST.APISERVER.RESOURCE_STATE.DELETE
              }
            });
          });
      })
      .then(() => eventmesh.apiServerClient.getResourceOperationStatus({
        resourceGroup: plan.manager.resource_mappings.bind.resource_group,
        resourceType: plan.manager.resource_mappings.bind.resource_type,
        resourceId: params.binding_id,
        start_state: CONST.APISERVER.RESOURCE_STATE.DELETE,
        started_at: new Date()
      }))
      .then(() => eventmesh.apiServerClient.deleteResource({
        resourceGroup: plan.manager.resource_mappings.bind.resource_group,
        resourceType: plan.manager.resource_mappings.bind.resource_type,
        resourceId: params.binding_id
      }))
      .then(done)
      .catch(NotFound, gone);
  }

}

module.exports = ServiceBrokerApiController;<|endoftext|>


<commit_before>mumuki.load(function () {
  $('[data-toggle="popover"]').popover({trigger: 'hover', html: true});
});
<commit_msg>Removing unused popever.js<commit_after><|endoftext|>


<commit_before>define(['jquery', 'DoughBaseComponent'], function($, DoughBaseComponent) {

  'use strict';

  var Glossary;

  Glossary = function($el, config) {
    Glossary.baseConstructor.call(this, $el, config);

    var article = $('[data-dough-glossary-content]'),
        articleContent = $(article).html(),
        updatedContent;

    $.getJSON('/glossary.json', function(data){
      data.glossary.map(function (item) {

        // If the article content contains any of the keywords in the JSON
        if(articleContent.indexOf(item.term) >= 1){

          console.log('The term ' + item.term + ' has been found in this article')

          $(item).each(function(){
            var updatedContent = articleContent.replace(RegExp("(?!<.*?)\\b(" + item.term + ")\\b(?![^<>]*?(<\/a>|<\/h2>|<\/h3>|>))","gi"),
                                                               "<button class='unstyled-button glossary__term' aria-label='" + item.term + " (see description)'>" + item.term + "</button>" + item.term + "" + item.description + "<button class='glossary__description-close'>close</button>");
            articleContent = updatedContent;
            $(article).html(updatedContent);
          });

        };
      });

      // Show descriptions
      $('.glossary__term').on('click', function(){
        $(this).next('.glossary__description').addClass('glossary__description--active');
        return false;
      });

      // Close descriptions using button
      $('.glossary__description-close').on('click', function(){
        $(this).parents('.glossary__description').removeClass('glossary__description--active');
        console.log('closed');
      });

      // Close descriptions by clicking outside description element
      $('body').click(function() {
        if(!$(this.target).is('.glossary__description')) {
          $(".glossary__description").removeClass('glossary__description--active');
        }
      });

    });

  };

  DoughBaseComponent.extend(Glossary);
  Glossary.componentName = 'Glossary';

  // Initialise the component
  Glossary.prototype.init = function(initialised) {
    this._initialisedSuccess(initialised);
  };

  return Glossary;
});
<commit_msg>updated javascript file to position tooltip above the clicked element and scroll tooltip to the top of the page<commit_after>define(['jquery', 'DoughBaseComponent'], function($, DoughBaseComponent) {

  'use strict';

  var Glossary;

  Glossary = function($el, config) {
    Glossary.baseConstructor.call(this, $el, config);

    var article = $('[data-dough-glossary-content]'),
        articleContent = $(article).html(),
        updatedContent;

    $.getJSON('/glossary.json', function(data){
      data.glossary.map(function (item) {

        // If the article content contains any of the keywords in the JSON
        if(articleContent.indexOf(item.term) >= 1){

          console.log('The term ' + item.term + ' has been found in this article')

          $(item).each(function(){
            var updatedContent = articleContent.replace(RegExp("(?!<.*?)\\b(" + item.term + ")\\b(?![^<>]*?(<\/a>|<\/h2>|<\/h3>|>))","gi"),
                                                               "<button class='unstyled-button glossary__term' aria-label='" + item.term + " (see description)'>" + item.term + "</button>" + item.term + "" + item.description + "<button class='glossary__description-close'><svg xmlns='http://www.w3.org/2000/svg' \
        class='svg-icon svg-icon--mobile-close-box'><use xmlns:xlink='http://www.w3.org/1999/xlink' xlink:href='#svg-icon--mobile-close-box'>\
        </use></svg></button>");

            articleContent = updatedContent;
            $(article).html(updatedContent);

          });

        };
      });

      // Show descriptions
      $('.glossary__term').on('click', function(){
        $(".glossary__description").removeClass('glossary__description--active');
        $(this).next('.glossary__description').addClass('glossary__description--active');

        // Calculate parent container width and apply its width to the tooltip width
        // Determine the clicked elements verticle position in the document and substract the height to position the tooltip
        var container = $('html,body'),
        scrollTo = $('.glossary__description--active'),
        tooltipWidth = $('.l-article-3col-main').innerWidth() - 10,
        top = $(this).position().top - scrollTo.outerHeight() - 10;

        // apply top positioning and width to tooltip class using tooltipWidth and top variables
        $('.glossary__description').css({top: top, width: tooltipWidth});

        // scroll and animate tooltip to the top of the page
        container.animate({
            scrollTop: scrollTo.offset().top - container.offset().top - 70 + container.scrollTop()
        });

        return false;
      });

      // Close descriptions using button
      $('.glossary__description-close').on('click', function(){
        $(this).parents('.glossary__description').removeClass('glossary__description--active');
        console.log('closed');
      });

      // Close descriptions by clicking outside description element
      $('body').click(function() {
        if(!$(this.target).is('.glossary__description')) {
          $(".glossary__description").removeClass('glossary__description--active');
        }
      });

    });

  };

  DoughBaseComponent.extend(Glossary);
  Glossary.componentName = 'Glossary';

  // Initialise the component
  Glossary.prototype.init = function(initialised) {
    this._initialisedSuccess(initialised);
  };

  return Glossary;
});
<|endoftext|>


<commit_before>// Toolbar Item: 'Edit'

WulinMaster.actions.Edit = $.extend({}, WulinMaster.actions.BaseAction, {
  name: 'edit',

  handler: function () {
    var grid = this.getGrid();

    // Batch update action
    batchUpdateByAjax(grid);
    return false;
  },
});

var batchUpdateByAjax = function (grid, version) {
  var ids, name, scope, width, height, selectedIndexes, url;
  selectedIndexes = grid.getSelectedRows();
  name = grid.name;
  scope = $('#' + name + '_form');

  if (!selectedIndexes || selectedIndexes.length === 0) {
    displayErrorMessage('Please select a record');
  } else {
    ids = grid.getSelectedIds();
    if (ids.length > 350) {
      displayErrorMessage(
        'You select too many rows, please select less than 350 rows.'
      );
      return;
    }
    url = grid.path + '/wulin_master_edit_form' + grid.query;
    if (version) url = url + '&update_version=' + version;
    $.get(url, function (data) {
      Ui.createModelModal(grid, data, {
        onOpenEnd: function (modal, trigger) {
          Ui.setupForm(grid, true, selectedIndexes);
          Ui.setupComponents(grid);
          showFlagCheckBox(modal, ids);
          checkTheBox(name);
          submitForm(grid, ids, selectedIndexes);
        },
      });
    });
  }
};

var fillValues = function (scope, grid, selectedIndexes) {
  var data,
    inputBox,
    dataArr,
    comm = {};
  if (selectedIndexes.length == 1) {
    data = grid.loader.data[selectedIndexes[0]];
    loadValue(scope, data);
  } else {
    dataArr = $.map(selectedIndexes, function (n, i) {
      return grid.loader.data[n];
    });
    $.each(dataArr, function (index, n) {
      for (var k in n) {
        if (index === 0) {
          if (k != 'id' && k != 'slick_index') comm[k] = n[k];
        } else {
          if ($.type(n[k]) != 'object' && comm[k] !== n[k]) {
            delete comm[k];
          } else if (
            $.type(n[k]) === 'object' &&
            $.type(comm[k]) === 'object' &&
            !compareArray(comm[k]['id'], n[k]['id'])
          ) {
            delete comm[k];
          }
        }
      }
    });
    loadValue(scope, comm);
  }

  // Avoid label overlapping input to MD textfield
  $('#' + grid.name + '_form .field')
    .filter(function () {
      return !!$(this).find('input').val();
    })
    .find('label')
    .addClass('active');
};

var loadValue = function (scope, data) {
  for (var i in data) {
    if ($('input:text[data-field="' + i + '"]', scope).size() > 0) {
      $('input[data-field="' + i + '"]', scope).val(data[i]);
    } else if ($('textarea[data-field="' + i + '"]', scope).size() > 0) {
      $('textarea[data-field="' + i + '"]', scope).val(data[i]);
      if (data[i]) {
        $('textarea[data-field="' + i + '"]', scope)
          .siblings('label')
          .addClass('active');
      }
    } else if ($('input:checkbox[data-field="' + i + '"]', scope).size() > 0) {
      if (data[i]) {
        $('input:checkbox[data-field="' + i + '"]', scope).prop(
          'checked',
          true
        );
      } else {
        $('input:checkbox[data-field="' + i + '"]', scope).removeAttr(
          'checked'
        );
      }
    } else if ($('select[data-field="' + i + '"]', scope).size() > 0) {
      inputBox = $('select[data-field="' + i + '"]', scope);
      inputBox.siblings('label').addClass('active');
      if ($.type(data[i]) === 'string') {
        inputBox.val(data[i]);
      } else if ($.type(data[i]) === 'object') {
        if ($.type(data[i]['id']) === 'array') {
          inputBox.val(data[i]['id']);
        } else {
          inputBox.val(data[i]['id']);
        }
      } else if ($.type(data[i]) === 'array') {
        inputBox.val(data[i]);
      }
      inputBox.trigger('chosen:updated');
    }
  }
};

var showFlagCheckBox = function (scope, ids) {
  if (ids.length > 1) {
    $('.target_flag_container', scope).show();
  } else {
    $('.target_flag_container', scope).hide();
  }
};

var checkTheBox = function (name) {
  var scope = $('#' + name + '_form');
  // Check flag when change value of the box
  scope
    .off('keyup', 'input:text, input:password, textarea')
    .on('keyup', 'input:text, input:password, textarea', function (e) {
      $(
        'input.target_flag:checkbox[data-target-id="' +
          $(e.currentTarget).attr('data-target-id') +
          '"]'
      ).prop('checked', true);
    });
  scope
    .off('change', 'input:checkbox, input:file')
    .on('change', 'input:checkbox:not(.target_flag), input:file', function (e) {
      $(
        'input.target_flag:checkbox[data-target-id="' +
          $(e.currentTarget).attr('data-target-id') +
          '"]'
      ).prop('checked', true);
    });

  // Date picker \ datetime picker \ time picker
  scope
    .off('change', 'input.flatpickr-input')
    .on('change', 'input.flatpickr-input', function (e) {
      $(
        'input.target_flag:checkbox[data-target-id="' +
          $(e.currentTarget).attr('data-target-id') +
          '"]'
      ).prop('checked', true);
    });

  // Empty input box when flag change to unchecked
  scope
    .off('change', 'input.target_flag:visible')
    .on('change', 'input.target_flag:visible', function () {
      if ($(this).prop('checked') == false) {
        $('input[data-target-id="' + $(this).attr('data-target-id') + '"]')
          .not(':button, :submit, :reset, :hidden, .target_flag')
          .val('')
          .removeAttr('checked')
          .removeAttr('selected');
        $('select[data-target-id="' + $(this).attr('data-target-id') + '"]')
          .val('')
          .trigger('chosen:updated');
      }
    });
};

var grepValues = function (formData, jqForm, options) {
  var flagDom;
  for (var i = formData.length - 1; i >= 0; i--) {
    flagDom = $(
      'input.target_flag:checkbox[data-target-id="' +
        $('[name="' + formData[i].name + '"]')
          .not('[type="hidden"]')
          .attr('data-target-id') +
        '"]',
      jqForm
    );
    if (flagDom.not(':checked').size() > 0) {
      formData.splice(i, 1);
    }
  }
};

var submitForm = function (grid, ids, selectedIndexes) {
  var name = grid.name,
    $scope = $('#' + name + '_form'),
    $form = $('form', $scope);
  var submitButton = $form.find("input[type='submit']");
  $scope.off('click', '.update_btn').on('click', '.update_btn', function () {
    var options = {
      dateType: 'json',
      url: grid.path + '/' + ids + '.json' + grid.query,
      data: { _method: 'PUT' },
      beforeSubmit: grepValues,
      beforeSend: function () {
        submitButton.prop('disabled', 'disabled');
      },
      success: function (msg) {
        if (msg.success) {
          Ui.resetForm(grid.name);
          grid.loader.reloadData();
          if (grid.reloadMasterAfterUpdates && grid.master_grid) {
            grid.master_grid.loader.reloadData();
          }
          if (selectedIndexes.length > 1) {
            displayNewNotification(
              selectedIndexes.length +
                ' ' +
                grid.model.toLowerCase() +
                's updated'
            );
          } else {
            displayNewNotification(
              '1 ' + grid.model.toLowerCase() + ' updated'
            );
          }
        } else {
          displayErrorMessage(msg.error_message);
          saveMessage('Error updating ' + grid.model.toLowerCase(), 'error');
          grid.loader.reloadData();
        }
        $scope.closest('.modal').modal('close');
      },
      complete: function () {
        submitButton.prop('disabled', null);
      },
    };
    $form.ajaxSubmit(options);
    return false;
  });
};

var compareArray = function (x, y) {
  if ($.type(x) == 'array' && $.type(y) == 'array') {
    if (x.length != y.length) {
      return false;
    }

    for (var k in x) {
      if (x[k] != y[k]) {
        //!== So that the the values are not converted while comparison
        return false;
      }
    }
    return true;
  } else {
    return x === y;
  }
};

WulinMaster.ActionManager.register(WulinMaster.actions.Edit);
<commit_msg>MISC ekohe/hbs/bss_core#30 - Add argument scope for function checkTheBox<commit_after>// Toolbar Item: 'Edit'

WulinMaster.actions.Edit = $.extend({}, WulinMaster.actions.BaseAction, {
  name: 'edit',

  handler: function () {
    var grid = this.getGrid();

    // Batch update action
    batchUpdateByAjax(grid);
    return false;
  },
});

var batchUpdateByAjax = function (grid, version) {
  var ids, name, scope, width, height, selectedIndexes, url;
  selectedIndexes = grid.getSelectedRows();
  name = grid.name;
  scope = $('#' + name + '_form');

  if (!selectedIndexes || selectedIndexes.length === 0) {
    displayErrorMessage('Please select a record');
  } else {
    ids = grid.getSelectedIds();
    if (ids.length > 350) {
      displayErrorMessage(
        'You select too many rows, please select less than 350 rows.'
      );
      return;
    }
    url = grid.path + '/wulin_master_edit_form' + grid.query;
    if (version) url = url + '&update_version=' + version;
    $.get(url, function (data) {
      Ui.createModelModal(grid, data, {
        onOpenEnd: function (modal, trigger) {
          Ui.setupForm(grid, true, selectedIndexes);
          Ui.setupComponents(grid);
          showFlagCheckBox(modal, ids);
          checkTheBox(name);
          submitForm(grid, ids, selectedIndexes);
        },
      });
    });
  }
};

var fillValues = function (scope, grid, selectedIndexes) {
  var data,
    inputBox,
    dataArr,
    comm = {};
  if (selectedIndexes.length == 1) {
    data = grid.loader.data[selectedIndexes[0]];
    loadValue(scope, data);
  } else {
    dataArr = $.map(selectedIndexes, function (n, i) {
      return grid.loader.data[n];
    });
    $.each(dataArr, function (index, n) {
      for (var k in n) {
        if (index === 0) {
          if (k != 'id' && k != 'slick_index') comm[k] = n[k];
        } else {
          if ($.type(n[k]) != 'object' && comm[k] !== n[k]) {
            delete comm[k];
          } else if (
            $.type(n[k]) === 'object' &&
            $.type(comm[k]) === 'object' &&
            !compareArray(comm[k]['id'], n[k]['id'])
          ) {
            delete comm[k];
          }
        }
      }
    });
    loadValue(scope, comm);
  }

  // Avoid label overlapping input to MD textfield
  $('#' + grid.name + '_form .field')
    .filter(function () {
      return !!$(this).find('input').val();
    })
    .find('label')
    .addClass('active');
};

var loadValue = function (scope, data) {
  for (var i in data) {
    if ($('input:text[data-field="' + i + '"]', scope).size() > 0) {
      $('input[data-field="' + i + '"]', scope).val(data[i]);
    } else if ($('textarea[data-field="' + i + '"]', scope).size() > 0) {
      $('textarea[data-field="' + i + '"]', scope).val(data[i]);
      if (data[i]) {
        $('textarea[data-field="' + i + '"]', scope)
          .siblings('label')
          .addClass('active');
      }
    } else if ($('input:checkbox[data-field="' + i + '"]', scope).size() > 0) {
      if (data[i]) {
        $('input:checkbox[data-field="' + i + '"]', scope).prop(
          'checked',
          true
        );
      } else {
        $('input:checkbox[data-field="' + i + '"]', scope).removeAttr(
          'checked'
        );
      }
    } else if ($('select[data-field="' + i + '"]', scope).size() > 0) {
      inputBox = $('select[data-field="' + i + '"]', scope);
      inputBox.siblings('label').addClass('active');
      if ($.type(data[i]) === 'string') {
        inputBox.val(data[i]);
      } else if ($.type(data[i]) === 'object') {
        if ($.type(data[i]['id']) === 'array') {
          inputBox.val(data[i]['id']);
        } else {
          inputBox.val(data[i]['id']);
        }
      } else if ($.type(data[i]) === 'array') {
        inputBox.val(data[i]);
      }
      inputBox.trigger('chosen:updated');
    }
  }
};

var showFlagCheckBox = function (scope, ids) {
  if (ids.length > 1) {
    $('.target_flag_container', scope).show();
  } else {
    $('.target_flag_container', scope).hide();
  }
};

var checkTheBox = function (name, scope) {
  var scope = scope || `#${name}_form`;
  var $scope = $(scope);
  // Check flag when change value of the box
  $scope
    .off('keyup', 'input:text, input:password, textarea')
    .on('keyup', 'input:text, input:password, textarea', function (e) {
      $(
        'input.target_flag:checkbox[data-target-id="' +
          $(e.currentTarget).attr('data-target-id') +
          '"]'
      ).prop('checked', true);
    });
  $scope
    .off('change', 'input:checkbox, input:file')
    .on('change', 'input:checkbox:not(.target_flag), input:file', function (e) {
      $(
        'input.target_flag:checkbox[data-target-id="' +
          $(e.currentTarget).attr('data-target-id') +
          '"]'
      ).prop('checked', true);
    });

  // Date picker \ datetime picker \ time picker
  $scope
    .off('change', 'input.flatpickr-input')
    .on('change', 'input.flatpickr-input', function (e) {
      $(
        'input.target_flag:checkbox[data-target-id="' +
          $(e.currentTarget).attr('data-target-id') +
          '"]'
      ).prop('checked', true);
    });

  // Empty input box when flag change to unchecked
  $scope
    .off('change', 'input.target_flag:visible')
    .on('change', 'input.target_flag:visible', function () {
      if ($(this).prop('checked') == false) {
        $('input[data-target-id="' + $(this).attr('data-target-id') + '"]')
          .not(':button, :submit, :reset, :hidden, .target_flag')
          .val('')
          .removeAttr('checked')
          .removeAttr('selected');
        $('select[data-target-id="' + $(this).attr('data-target-id') + '"]')
          .val('')
          .trigger('chosen:updated');
      }
    });
};

var grepValues = function (formData, jqForm, options) {
  var flagDom;
  for (var i = formData.length - 1; i >= 0; i--) {
    flagDom = $(
      'input.target_flag:checkbox[data-target-id="' +
        $('[name="' + formData[i].name + '"]')
          .not('[type="hidden"]')
          .attr('data-target-id') +
        '"]',
      jqForm
    );
    if (flagDom.not(':checked').size() > 0) {
      formData.splice(i, 1);
    }
  }
};

var submitForm = function (grid, ids, selectedIndexes) {
  var name = grid.name,
    $scope = $('#' + name + '_form'),
    $form = $('form', $scope);
  var submitButton = $form.find("input[type='submit']");
  $scope.off('click', '.update_btn').on('click', '.update_btn', function () {
    var options = {
      dateType: 'json',
      url: grid.path + '/' + ids + '.json' + grid.query,
      data: { _method: 'PUT' },
      beforeSubmit: grepValues,
      beforeSend: function () {
        submitButton.prop('disabled', 'disabled');
      },
      success: function (msg) {
        if (msg.success) {
          Ui.resetForm(grid.name);
          grid.loader.reloadData();
          if (grid.reloadMasterAfterUpdates && grid.master_grid) {
            grid.master_grid.loader.reloadData();
          }
          if (selectedIndexes.length > 1) {
            displayNewNotification(
              selectedIndexes.length +
                ' ' +
                grid.model.toLowerCase() +
                's updated'
            );
          } else {
            displayNewNotification(
              '1 ' + grid.model.toLowerCase() + ' updated'
            );
          }
        } else {
          displayErrorMessage(msg.error_message);
          saveMessage('Error updating ' + grid.model.toLowerCase(), 'error');
          grid.loader.reloadData();
        }
        $scope.closest('.modal').modal('close');
      },
      complete: function () {
        submitButton.prop('disabled', null);
      },
    };
    $form.ajaxSubmit(options);
    return false;
  });
};

var compareArray = function (x, y) {
  if ($.type(x) == 'array' && $.type(y) == 'array') {
    if (x.length != y.length) {
      return false;
    }

    for (var k in x) {
      if (x[k] != y[k]) {
        //!== So that the the values are not converted while comparison
        return false;
      }
    }
    return true;
  } else {
    return x === y;
  }
};

WulinMaster.ActionManager.register(WulinMaster.actions.Edit);
<|endoftext|>


<commit_before>// @flow
import React, { Component } from 'react';
import { AppBar, IconButton, RaisedButton } from 'material-ui';
import AddCircle from 'material-ui/svg-icons/content/add-circle';
import Styles from '../../../styles/custom'

class List extends Component {

  constructor(props) {
    super(props);
    this.handleToAdd = this.handleToAdd.bind(this);
    this.handleToRun = this.handleToRun.bind(this);
  }

  handleToAdd() {
    const { transitionTo } = this.props.urlManagerActions;
    transitionTo('/add-album');
  }

  handleToRun() {
    const { transitionTo } = this.props.urlManagerActions;
    transitionTo('/run-album/1');
  }

  componentDidMount() {
    console.log(555, this);
    this.props.albumsActions.get();
  }

  render() {
    return (

        <AppBar
          title="List albums"
          iconElementRight={
            <IconButton
              style={Styles.iconButton.large}
              iconStyle={Styles.iconButton.largeIcon}
              onClick={this.handleToAdd}
            >
              <AddCircle />
            </IconButton>
          }
        />
        <RaisedButton
          label="Run"
          secondary={true}
          onClick={this.handleToRun}
        />

    );
  }
}
export default List;
<commit_msg>Show list albums<commit_after>// @flow
import React, { Component } from 'react';
import { AppBar, IconButton, RaisedButton } from 'material-ui';
import AddCircle from 'material-ui/svg-icons/content/add-circle';
import Styles from '../../../styles/custom'
import Paper from 'material-ui/Paper';

const style = {
  width: 172,
  height: 172,
  margin: 10,
  textAlign: 'center',
  display: 'inline-block',
};

class List extends Component {

  constructor(props) {
    super(props);
    this.handleToAdd = this.handleToAdd.bind(this);
    this.handleToRun = this.handleToRun.bind(this);
  }

  handleToAdd() {
    const { transitionTo } = this.props.urlManagerActions;
    transitionTo('/add-album');
  }

  handleToRun() {
    const { transitionTo } = this.props.urlManagerActions;
    transitionTo('/run-album/1');
  }

  componentDidMount() {
    // get list albums
    this.props.albumsActions.get();
  }

  render() {
    const { records } = this.props.album;

    const list = records.map((item) => {
      return (
        <Paper style={style} zDepth={2} key={item.id}>

        </Paper>
      );
    });

    return (

        <AppBar
          title="List albums"
          iconElementRight={
            <IconButton
              style={Styles.iconButton.large}
              iconStyle={Styles.iconButton.largeIcon}
              onClick={this.handleToAdd}
            >
              <AddCircle />
            </IconButton>
          }
        />

          {list}

    );
  }
}
// <RaisedButton
// label="Run"
// secondary={true}
// onClick={this.handleToRun}
// />
export default List;
<|endoftext|>


<commit_before>
/*
 * == BSD2 LICENSE ==
 * Copyright (c) 2017, Tidepool Project
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the associated License, which is identical to the BSD 2-Clause
 * License as published by the Open Source Initiative at opensource.org.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the License for more details.
 *
 * You should have received a copy of the License along with this program; if
 * not, you can obtain one from Tidepool Project at tidepool.org.
 * == BSD2 LICENSE ==
 */
import _ from 'lodash';
import bows from 'bows';
import React from 'react';

import PrintHeader from '../printheader';

import utils from '../../core/utils';

import * as viz from '@tidepool/viz';
const PumpSettingsContainer = viz.containers.PumpSettingsContainer;

const tideline = {
  log: bows('SettingsPrintView')
};

const SettingsPrintView = React.createClass({
  chartType: 'settings',
  log: bows('Settings View'),
  propTypes: {
    bgPrefs: React.PropTypes.object.isRequired,
    currentPatientInViewId: React.PropTypes.string.isRequired,
    timePrefs: React.PropTypes.object.isRequired,
    patientData: React.PropTypes.object.isRequired,
    patient: React.PropTypes.object,
    trackMetric: React.PropTypes.func.isRequired,
  },
  renderHeader: function() {
    return (
      <PrintHeader
        title="Pump Settings"
        patient={this.props.patient}
      />
    );
  },
  render: function() {
    const mostRecentSettings = _.last(this.props.patientData.grouped.pumpSettings);
    const manufacturer = _.get(mostRecentSettings, 'source').toLowerCase();
    return (
<<<<<<< HEAD
      <PumpSettingsContainer
        currentPatientInViewId={this.props.currentPatientInViewId}
        bgUnits={this.props.bgPrefs.bgUnits}
        manufacturerKey={manufacturer}
        pumpSettings={mostRecentSettings}
        timePrefs={this.props.timePrefs}
        view='print'
      />
=======

        {this.renderHeader()}

          <PumpSettingsContainer
            currentPatientInViewId={this.props.currentPatientInViewId}
            bgUnits={this.props.bgPrefs.bgUnits}
            manufacturerKey={manufacturer}
            pumpSettings={mostRecentSettings}
            timePrefs={this.props.timePrefs}
            printView={true}
          />

>>>>>>> master
    );
  }
});

module.exports = SettingsPrintView;
<commit_msg>fix merge<commit_after>
/*
 * == BSD2 LICENSE ==
 * Copyright (c) 2017, Tidepool Project
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the associated License, which is identical to the BSD 2-Clause
 * License as published by the Open Source Initiative at opensource.org.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the License for more details.
 *
 * You should have received a copy of the License along with this program; if
 * not, you can obtain one from Tidepool Project at tidepool.org.
 * == BSD2 LICENSE ==
 */
import _ from 'lodash';
import bows from 'bows';
import React from 'react';

import PrintHeader from '../printheader';

import utils from '../../core/utils';

import * as viz from '@tidepool/viz';
const PumpSettingsContainer = viz.containers.PumpSettingsContainer;

const tideline = {
  log: bows('SettingsPrintView')
};

const SettingsPrintView = React.createClass({
  chartType: 'settings',
  log: bows('Settings View'),
  propTypes: {
    bgPrefs: React.PropTypes.object.isRequired,
    currentPatientInViewId: React.PropTypes.string.isRequired,
    timePrefs: React.PropTypes.object.isRequired,
    patientData: React.PropTypes.object.isRequired,
    patient: React.PropTypes.object,
    trackMetric: React.PropTypes.func.isRequired,
  },
  renderHeader: function() {
    return (
      <PrintHeader
        title="Pump Settings"
        patient={this.props.patient}
      />
    );
  },
  render: function() {
    const mostRecentSettings = _.last(this.props.patientData.grouped.pumpSettings);
    const manufacturer = _.get(mostRecentSettings, 'source').toLowerCase();
    return (
      <PumpSettingsContainer
        currentPatientInViewId={this.props.currentPatientInViewId}
        bgUnits={this.props.bgPrefs.bgUnits}
        manufacturerKey={manufacturer}
        pumpSettings={mostRecentSettings}
        timePrefs={this.props.timePrefs}
        view='print'
      />
    );
  }
});

module.exports = SettingsPrintView;
<|endoftext|>