<commit_before>import React, { Component } from 'react';
import Config from '../../config'
import { browserHistory } from 'react-router';
import Spin from '../spin'
import './episode.css'

import { VelocityTransitionGroup } from 'velocity-react';
import ShareButtons from 'react-share-buttons'

var urlencode = require('urlencode')

class EpisodeId extends Component {

	handleClick() {
		let url = '/video/'  + this.props.episode.episodeSid +
							'/' + this.props.title;
		localStorage[this.props.sid] = JSON.stringify(this.props.episode.episode);
    browserHistory.push(url);
	}

	render() {

		return (
			<button type="button"
							className="btn btn-default"
							onClick={this.handleClick.bind(this)}>
				{this.props.episode.episode}
			</button>
		)
	}
}

class Episode extends Component {
  constructor(props) {
  	super(props);

  	this.state = {
  		searchDone: false,
  		json: {},
  		lastWatched: 0
  	}
  	this.config = Config();
  	this.fetchData = this.fetchData.bind(this);
  	this.updateLastVisited = this.updateLastVisited.bind(this);
  }

  /* callde first initialize */
  componentDidMount() {
  	let sid = this.props.params.sid
  	this.fetchData(sid);
  	if (localStorage[sid] !== undefined) {
  		this.setState({
  			lastWatched: JSON.parse(localStorage[sid])
  		})
  	}
  }

  fetchData(sid) {
  	let url = this.config.server + '/api/detail/' + sid;
  	fetch(url).then((res) => res.json()).then((data) => {
  		this.setState({
  			searchDone: true,
  			json: data
  		});
  	}).catch(function(error){
  		this.setState({
  			searchDone: true
  		})
  	}.bind(this));
  }

  /* update last visited in localstorage */
  updateLastVisited(obj) {
  	let lastVisited = [];
  	let MAX_LEN = 10;
  	if (localStorage['lastVisited'] !== undefined) {
  		lastVisited = JSON.parse(localStorage['lastVisited']);
  	}

  	// deduplicate
  	for (let i = 0; i < lastVisited.length; i++) {
  		if (lastVisited[i].id === obj.id) {
  			lastVisited.splice(i, 1);
  			break;
  		}
  	}

  	if (lastVisited.length > MAX_LEN) {
  		lastVisited.shift();

  	}

  	lastVisited.push({id: obj.id, cover: obj.cover, title: obj.title, brief: obj.brief});
  	localStorage['lastVisited'] = JSON.stringify(lastVisited);
  }

  render() {

  	let content = null;

  	/* Check search done */
  	if (this.state.searchDone) {
	  	if (this.state.json.data !== undefined &&
	  			this.state.json.data.season !== undefined &&
	  			this.state.json.data.season.playUrlList !== undefined &&
	  			this.state.json.data.season.playUrlList.length !== 0) {
	  		let season = this.state.json.data.season;
	  		this.updateLastVisited(season);

	  		/* episodes list */
	  		let episodes = [];
	  	  let list = season.playUrlList;
	  	  list.sort(function(a, b) {
				    return a.episode - b.episode;
				});
		  	for(var i = 0; i < list.length; i++) {
		  		let title = '《' + this.state.json.data.season.title + '》第' + list[i].episode + '集'
		  		episodes.push(
		  			<EpisodeId key={i} episode={list[i]} title={title} sid={this.props.params.sid}/>
		  		)
		  	}

		  	let note = null
		  	if(this.state.lastWatched !== 0) {
		  		note =
上次观看到第{this.state.lastWatched}集

		  	}

		  	let url = urlencode("http://kanmeiju.herokuapp.com" + this.props.location.pathname);
		  	console.log(url);
		  	let description = "我在这里观看了《" + season.title +"》，快来一起看吧！" ;
		  	let shareButton = <ShareButtons
													  sites = {["qzone", "weibo", "qq", "tencent", "douban", "linkedin", "facebook", "google", "twitter" ]}
													  url = {url}
													  title = {season.title}
													  description = {description}
													  image=''
													/>

		  	/* content */
		  	content =

{season.title}

										    		{season.brief}

									    	{episodes}

									    	{note}

									    { shareButton }

		  } else {
		  	content =

									  Error:
									  无法加载剧集。返回搜索结果

		  }
		} else {
			content = <Spin />
		}

  	return (

  	  	<VelocityTransitionGroup enter={{animation: "transition.slideLeftIn"}} leave={{animation: "transition.slideRightOut"}}
                                  runOnMount={true}>
  	  	{ content }
  	  	</VelocityTransitionGroup>

  	)

  }
}

export default Episode;<commit_msg>adding url into button<commit_after>import React, { Component } from 'react';
import Config from '../../config'
import { browserHistory } from 'react-router';
import Spin from '../spin'
import './episode.css'

import { VelocityTransitionGroup } from 'velocity-react';
import ShareButtons from 'react-share-buttons'

var urlencode = require('urlencode')

class EpisodeId extends Component {

	handleClick() {
		let url = '/video/'  + this.props.episode.episodeSid +
							'/' + this.props.title;
		localStorage[this.props.sid] = JSON.stringify(this.props.episode.episode);
    browserHistory.push(url);
	}

	render() {
		let url = '/video/'  + this.props.episode.episodeSid +
							'/' + this.props.title;
		return (
			<button url={url} type="button"
							className="btn btn-default"
							onClick={this.handleClick.bind(this)}>
				{this.props.episode.episode}
			</button>
		)
	}
}

class Episode extends Component {
  constructor(props) {
  	super(props);

  	this.state = {
  		searchDone: false,
  		json: {},
  		lastWatched: 0
  	}
  	this.config = Config();
  	this.fetchData = this.fetchData.bind(this);
  	this.updateLastVisited = this.updateLastVisited.bind(this);
  }

  /* callde first initialize */
  componentDidMount() {
  	let sid = this.props.params.sid
  	this.fetchData(sid);
  	if (localStorage[sid] !== undefined) {
  		this.setState({
  			lastWatched: JSON.parse(localStorage[sid])
  		})
  	}
  }

  fetchData(sid) {
  	let url = this.config.server + '/api/detail/' + sid;
  	fetch(url).then((res) => res.json()).then((data) => {
  		this.setState({
  			searchDone: true,
  			json: data
  		});
  	}).catch(function(error){
  		this.setState({
  			searchDone: true
  		})
  	}.bind(this));
  }

  /* update last visited in localstorage */
  updateLastVisited(obj) {
  	let lastVisited = [];
  	let MAX_LEN = 10;
  	if (localStorage['lastVisited'] !== undefined) {
  		lastVisited = JSON.parse(localStorage['lastVisited']);
  	}

  	// deduplicate
  	for (let i = 0; i < lastVisited.length; i++) {
  		if (lastVisited[i].id === obj.id) {
  			lastVisited.splice(i, 1);
  			break;
  		}
  	}

  	if (lastVisited.length > MAX_LEN) {
  		lastVisited.shift();

  	}

  	lastVisited.push({id: obj.id, cover: obj.cover, title: obj.title, brief: obj.brief});
  	localStorage['lastVisited'] = JSON.stringify(lastVisited);
  }

  render() {

  	let content = null;

  	/* Check search done */
  	if (this.state.searchDone) {
	  	if (this.state.json.data !== undefined &&
	  			this.state.json.data.season !== undefined &&
	  			this.state.json.data.season.playUrlList !== undefined &&
	  			this.state.json.data.season.playUrlList.length !== 0) {
	  		let season = this.state.json.data.season;
	  		this.updateLastVisited(season);

	  		/* episodes list */
	  		let episodes = [];
	  	  let list = season.playUrlList;
	  	  list.sort(function(a, b) {
				    return a.episode - b.episode;
				});
		  	for(var i = 0; i < list.length; i++) {
		  		let title = '《' + this.state.json.data.season.title + '》第' + list[i].episode + '集'
		  		episodes.push(
		  			<EpisodeId key={i} episode={list[i]} title={title} sid={this.props.params.sid}/>
		  		)
		  	}

		  	let note = null
		  	if(this.state.lastWatched !== 0) {
		  		note =
上次观看到第{this.state.lastWatched}集

		  	}

		  	let url = urlencode("http://kanmeiju.herokuapp.com" + this.props.location.pathname);
		  	console.log(url);
		  	let description = "我在这里观看了《" + season.title +"》，快来一起看吧！" ;
		  	let shareButton = <ShareButtons
													  sites = {["qzone", "weibo", "qq", "tencent", "douban", "linkedin", "facebook", "google", "twitter" ]}
													  url = {url}
													  title = {season.title}
													  description = {description}
													  image=''
													/>

		  	/* content */
		  	content =

{season.title}

										    		{season.brief}

									    	{episodes}

									    	{note}

									    { shareButton }

		  } else {
		  	content =

									  Error:
									  无法加载剧集。返回搜索结果

		  }
		} else {
			content = <Spin />
		}

  	return (

  	  	<VelocityTransitionGroup enter={{animation: "transition.slideLeftIn"}} leave={{animation: "transition.slideRightOut"}}
                                  runOnMount={true}>
  	  	{ content }
  	  	</VelocityTransitionGroup>

  	)

  }
}

export default Episode;<|endoftext|>


<commit_before>/*
 * ! ${copyright}
 */

// Provides class sap.ui.rta.plugin.ContextMenu.
sap.ui.define([
	'jquery.sap.global', 'sap/ui/dt/Plugin', 'sap/ui/dt/ContextMenuControl'
], function(jQuery, Plugin, ContextMenuControl) {
	"use strict";

	/**
	 * Constructor for a new ContextMenu.
	 *
	 * @param {string} [sId] id for the new object, generated automatically if no id is given
	 * @param {object} [mSettings] initial settings for the new object
	 * @class The ContextMenu registers event handler to open the context menu. Menu entries can dynamically be added
	 * @extends sap.ui.dt.Plugin
	 * @author SAP SE
	 * @version ${version}
	 * @constructor
	 * @private
	 * @since 1.34
	 * @alias sap.ui.dt.plugin.ContextMenu
	 * @experimental Since 1.34. This class is experimental and provides only limited functionality. Also the API might be changed in future.
	 */
	var ContextMenu = Plugin.extend("sap.ui.dt.plugin.ContextMenu", /** @lends sap.ui.rta.plugin.ContextMenu.prototype */
	{
		metadata: {
			// ---- object ----

			// ---- control specific ----
			library: "sap.ui.dt",
			properties: {
				contextElement : {
					type : "object"
				}
			},
			associations: {},
			events: {
				openedContextMenu: {},
				// TODO check if needed and how contextMenuControl handles it...
				closedContextMenu: {}
			}
		}
	});

	/**
	 * Register an overlay
	 *
	 * @param {sap.ui.dt.Overlay} oOverlay overlay object
	 * @override
	 */
	ContextMenu.prototype.registerElementOverlay = function(oOverlay) {
		oOverlay.attachBrowserEvent("contextmenu", this._onContextMenu, this);
		oOverlay.attachBrowserEvent("keydown", this._onKeyDown, this);
	};

	/**
	 * Additionally to super->deregisterOverlay this method detaches the browser events
	 *
	 * @param {sap.ui.dt.Overlay} oOverlay overlay object
	 * @override
	 */
	ContextMenu.prototype.deregisterElementOverlay = function(oOverlay) {
		oOverlay.detachBrowserEvent("contextmenu", this._onContextMenu, this);
		oOverlay.detachBrowserEvent("keydown", this._onKeyDown, this);
	};

	ContextMenu.prototype.init = function() {
		this._aMenuItems = [];
	};

	ContextMenu.prototype.exit = function() {
		delete this._aMenuItems;
		if (this._oContextMenuControl) {
			this._oContextMenuControl.destroy();
			delete this._oContextMenuControl;
		}
	};

	/**
	 * Add menu items in the following format
	 *
	 * @param {object} mMenuItem json object with the menu item settings
	 * @param {string} mMenuItem.id id, which corresponds to the text key
	 * @param {string} aMenuItems.text menu item text (translated)
	 * @param {function} mMenuItem.handler event handler if menu is selected, the element for which the menu was opened is passed to the handler
	 * @param {function} mMenuItem.startSection? function to determine if a new section should be started, the element for which the menu was opened
	 *        is passed to the handler, default false
	 * @param {function} mMenuItem.available? function to determine if the menu entry should be shown, the element for which the menu should be opened
	 *        is passed, default true
	 * @param {function} mMenuItem.enabled? function to determine if the menu entry should be enabled, the element for which the menu should be opened
	 *        is passed, default true
	 */
	ContextMenu.prototype.addMenuItem = function(mMenuItem) {
		this._aMenuItems.push(mMenuItem);
	};

	ContextMenu.prototype.open = function(oOriginalEvent, oTargetOverlay) {
		this.setContextElement(oTargetOverlay.getElementInstance());

		this._oContextMenuControl = new ContextMenuControl();
		this._oContextMenuControl.setMenuItems(this._aMenuItems, oTargetOverlay);
		this._oContextMenuControl.setOverlayDomRef(oTargetOverlay);
		this._oContextMenuControl.attachItemSelect(this._onItemSelected, this);

		this._oContextMenuControl.openMenu({
			pageX: oOriginalEvent.pageX,
			pageY: oOriginalEvent.pageY
		});

		this.fireOpenedContextMenu();
	};

	/**
	 * Called when an context menu item gets selected by user
	 *
	 * @param {sap.ui.base.Event} oEvent event object
	 * @override
	 * @private
	 */
	ContextMenu.prototype._onItemSelected = function(oEvent) {
		var sId = oEvent.getParameter("item").data("id");
		this._aMenuItems.some(function(oItem) {
			if (sId === oItem.id) {
				var oDesignTime = this.getDesignTime();
				var aSelection = oDesignTime.getSelection();
				oItem.handler(aSelection);
				return true;
			}
		}, this);
	};

	/**
	 * Handle context menu event
	 *
	 * @param {sap.ui.base.Event} oEvent event object
	 * @private
	 */
	ContextMenu.prototype._onContextMenu = function(oEvent) {
		// hide browser-context menu
		oEvent.preventDefault();
		var oOverlay = sap.ui.getCore().byId(oEvent.currentTarget.id);

		if (oOverlay && oOverlay.isSelectable()) {
			if (!oOverlay.isSelected()) {
				oOverlay.setSelected(true);
			}

			this.open(oEvent, oOverlay);
			oEvent.stopPropagation();
		}
	};

	/**
	 * Handle keydown event
	 *
	 * @param {sap.ui.base.Event} oEvent event object
	 * @private
	 */
	ContextMenu.prototype._onKeyDown = function(oEvent) {
		var oOverlay = sap.ui.getCore().byId(oEvent.currentTarget.id);

		if ((oEvent.keyCode === jQuery.sap.KeyCodes.F10) && (oEvent.shiftKey === true) && (oEvent.altKey === false) && (oEvent.ctrlKey === false)) {
			// hide browser-context menu
			oEvent.preventDefault();
			oEvent.stopPropagation();
			if (oOverlay && oOverlay.isSelectable()) {
				if (!oOverlay.isSelected()) {
					oOverlay.setSelected(true);
				}
				var iWidth = oOverlay.$().width() / 2;
				var iHeight = oOverlay.$().height() / 2;
				var iTop = oOverlay.$().offset().top;
				var iLeft = oOverlay.$().offset().left;

				this.open({
					pageX: iLeft + iWidth,
					pageY: iTop + iHeight
				}, oOverlay);
			}
		}
	};

	return ContextMenu;
}, /* bExport= */true);
<commit_msg>[FIX] Context menu can be called during rename and throws error<commit_after>/*
 * ! ${copyright}
 */

// Provides class sap.ui.rta.plugin.ContextMenu.
sap.ui.define([
	'jquery.sap.global', 'sap/ui/dt/Plugin', 'sap/ui/dt/ContextMenuControl'
], function(jQuery, Plugin, ContextMenuControl) {
	"use strict";

	/**
	 * Constructor for a new ContextMenu.
	 *
	 * @param {string} [sId] id for the new object, generated automatically if no id is given
	 * @param {object} [mSettings] initial settings for the new object
	 * @class The ContextMenu registers event handler to open the context menu. Menu entries can dynamically be added
	 * @extends sap.ui.dt.Plugin
	 * @author SAP SE
	 * @version ${version}
	 * @constructor
	 * @private
	 * @since 1.34
	 * @alias sap.ui.dt.plugin.ContextMenu
	 * @experimental Since 1.34. This class is experimental and provides only limited functionality. Also the API might be changed in future.
	 */
	var ContextMenu = Plugin.extend("sap.ui.dt.plugin.ContextMenu", /** @lends sap.ui.rta.plugin.ContextMenu.prototype */
	{
		metadata: {
			// ---- object ----

			// ---- control specific ----
			library: "sap.ui.dt",
			properties: {
				contextElement : {
					type : "object"
				}
			},
			associations: {},
			events: {
				openedContextMenu: {},
				// TODO check if needed and how contextMenuControl handles it...
				closedContextMenu: {}
			}
		}
	});

	/**
	 * Register an overlay
	 *
	 * @param {sap.ui.dt.Overlay} oOverlay overlay object
	 * @override
	 */
	ContextMenu.prototype.registerElementOverlay = function(oOverlay) {
		oOverlay.attachBrowserEvent("contextmenu", this._onContextMenu, this);
		oOverlay.attachBrowserEvent("keydown", this._onKeyDown, this);
	};

	/**
	 * Additionally to super->deregisterOverlay this method detaches the browser events
	 *
	 * @param {sap.ui.dt.Overlay} oOverlay overlay object
	 * @override
	 */
	ContextMenu.prototype.deregisterElementOverlay = function(oOverlay) {
		oOverlay.detachBrowserEvent("contextmenu", this._onContextMenu, this);
		oOverlay.detachBrowserEvent("keydown", this._onKeyDown, this);
	};

	ContextMenu.prototype.init = function() {
		this._aMenuItems = [];
	};

	ContextMenu.prototype.exit = function() {
		delete this._aMenuItems;
		if (this._oContextMenuControl) {
			this._oContextMenuControl.destroy();
			delete this._oContextMenuControl;
		}
	};

	/**
	 * Add menu items in the following format
	 *
	 * @param {object} mMenuItem json object with the menu item settings
	 * @param {string} mMenuItem.id id, which corresponds to the text key
	 * @param {string} aMenuItems.text menu item text (translated)
	 * @param {function} mMenuItem.handler event handler if menu is selected, the element for which the menu was opened is passed to the handler
	 * @param {function} mMenuItem.startSection? function to determine if a new section should be started, the element for which the menu was opened
	 *        is passed to the handler, default false
	 * @param {function} mMenuItem.available? function to determine if the menu entry should be shown, the element for which the menu should be opened
	 *        is passed, default true
	 * @param {function} mMenuItem.enabled? function to determine if the menu entry should be enabled, the element for which the menu should be opened
	 *        is passed, default true
	 */
	ContextMenu.prototype.addMenuItem = function(mMenuItem) {
		this._aMenuItems.push(mMenuItem);
	};

	ContextMenu.prototype.open = function(oOriginalEvent, oTargetOverlay) {
		this.setContextElement(oTargetOverlay.getElementInstance());

		this._oContextMenuControl = new ContextMenuControl();
		this._oContextMenuControl.setMenuItems(this._aMenuItems, oTargetOverlay);
		this._oContextMenuControl.setOverlayDomRef(oTargetOverlay);
		this._oContextMenuControl.attachItemSelect(this._onItemSelected, this);

		this._oContextMenuControl.openMenu({
			pageX: oOriginalEvent.pageX,
			pageY: oOriginalEvent.pageY
		});

		this.fireOpenedContextMenu();
	};

	/**
	 * Called when an context menu item gets selected by user
	 *
	 * @param {sap.ui.base.Event} oEvent event object
	 * @override
	 * @private
	 */
	ContextMenu.prototype._onItemSelected = function(oEvent) {
		var aSelection = [];
		var sId = oEvent.getParameter("item").data("id");
		this._aMenuItems.some(function(oItem) {
			if (sId === oItem.id) {
				var oDesignTime = this.getDesignTime();
				aSelection = oDesignTime.getSelection();

				jQuery.sap.assert(aSelection.length > 0, "sap.ui.rta - Opening context menu, with empty selection - check event order");

				oItem.handler(aSelection);
				return true;
			}
		}, this);
	};

	/**
	 * Handle context menu event
	 *
	 * @param {sap.ui.base.Event} oEvent event object
	 * @private
	 */
	ContextMenu.prototype._onContextMenu = function(oEvent) {
		// hide browser-context menu
		oEvent.preventDefault();
		document.activeElement.blur();

		var oOverlay = sap.ui.getCore().byId(oEvent.currentTarget.id);

		if (oOverlay && oOverlay.isSelectable()) {
			if (!oOverlay.isSelected()) {
				oOverlay.setSelected(true);
			}

			this.open(oEvent, oOverlay);
			oEvent.stopPropagation();
		}
	};

	/**
	 * Handle keydown event
	 *
	 * @param {sap.ui.base.Event} oEvent event object
	 * @private
	 */
	ContextMenu.prototype._onKeyDown = function(oEvent) {
		var oOverlay = sap.ui.getCore().byId(oEvent.currentTarget.id);

		if ((oEvent.keyCode === jQuery.sap.KeyCodes.F10) && (oEvent.shiftKey === true) && (oEvent.altKey === false) && (oEvent.ctrlKey === false)) {
			// hide browser-context menu
			oEvent.preventDefault();
			oEvent.stopPropagation();
			if (oOverlay && oOverlay.isSelectable()) {
				if (!oOverlay.isSelected()) {
					oOverlay.setSelected(true);
				}
				var iWidth = oOverlay.$().width() / 2;
				var iHeight = oOverlay.$().height() / 2;
				var iTop = oOverlay.$().offset().top;
				var iLeft = oOverlay.$().offset().left;

				this.open({
					pageX: iLeft + iWidth,
					pageY: iTop + iHeight
				}, oOverlay);
			}
		}
	};

	return ContextMenu;
}, /* bExport= */true);
<|endoftext|>


<commit_before>'use strict';

import React, {
  Image,
  StyleSheet,
  Text,
  TextInput,
  Switch,
  View,
} from 'react-native';
import { CloudinaryImageNative } from 'react-cloudinary';
import _ from 'lodash';
import Button from 'react-native-button';
import Icon from 'react-native-vector-icons/FontAwesome';
import ModalPicker from 'react-native-modal-picker'
import numeral from 'numeral';

import CountPicker from './CountPicker';

function getInitialState(props) {
  const { orderProduct } = props;
  const quantity = _.get(orderProduct, 'data.stock.quantity', orderProduct.quantity);
  return {
    quantity: quantity.toString(),
    reason: _.get(orderProduct, 'data.stock.reason', 0),
    confirmed: orderProduct.status !== 101,
  };
}

export default React.createClass({
  getInitialState() {
    return getInitialState(this.props);
  },
  toggleConfirm(confirmed) {
    this.setState({confirmed});
    if (confirmed) {
      const { quantity, reason } = this.state;
      this.props.confirm(+quantity, reason).then(
        () => this.setState(getInitialState(this.props))
      );
    }
  },
  setQuantity(quantity) {
    const { orderProduct } = this.props;
    if (quantity) {
      quantity = _.clamp(_.toSafeInteger(quantity), 0, orderProduct.quantity);
    }
    this.setState({
      quantity: quantity.toString(),
      reason: quantity == orderProduct.quantity ? 0 : (this.state.reason || 10),
    });
  },
  renderThumbnail({ product, productVariant }) {
    const image = _.get(productVariant, 'appImages.default.0');
    if (image) {
      return (
        <CloudinaryImageNative
          publicId={image.publicId}
          options={{ width: 100, height: 100 }}
          style={styles.thumbnail}
        />
      );
    }
  },
  renderReasonModal() {
    const { orderProduct } = this.props;
    const disabled= this.state.confirmed || this.state.quantity == orderProduct.quantity;
    const data = {
      0: { key: 0, label: '재고 있음' },
      10: { key: 10, label: '재입고 예정' },
      30: { key: 30, label: '품절' },
    };
    const selected = data[this.state.reason].label;
    const button = (
      <View style={styles.reasonButton}>
        <Text style={styles.reasonButtonText}>{selected}</Text>
      </View>
    );
    if (disabled) {
      return button;
    }
    return (
      <ModalPicker
        data={_.values(data).slice(1)}
        initValue={selected}
        onChange={(option)=> this.setState({ reason: option.key })}
      >
        {button}
      </ModalPicker>
    );
  },
  render() {
    const { orderProduct } = this.props;
    const { product, productVariant } = orderProduct;
    const { name } = product;
    const { color, size } = productVariant.data;
    const image = _.get(productVariant, 'appImages.default.0');
    return (
      <View style={styles.container}>
        <View style={{ flex: 1 }}>
          <Text>{name.ko}</Text>
          <Text>{color} / {size}</Text>
          <Text>{`${numeral(orderProduct.KRW).format('0,0')}원`}</Text>
          {this.renderThumbnail(orderProduct)}
        </View>
        <View style={{ flex: 1, alignItems: 'center' }}>
          <Text>주문수량: {numeral(orderProduct.quantity).format('0,0')}</Text>
          <Button
            containerStyle={styles.quantityButton}
            onPress={() => this.setQuantity(this.state.quantity + 1)}
          >
            <Icon name='chevron-up' size={20} />
          </Button>
          <TextInput
            autoCapitalize='none'
            autoCorrect={false}
            keyboardType='number-pad'
            onChangeText={this.setQuantity}
            value={this.state.quantity}
            style={styles.quantityInput}
            editable={!this.state.confirmed}
          />
          <Button
            containerStyle={styles.quantityButton}
            onPress={() => this.setQuantity(this.state.quantity - 1)}
          >
            <Icon name='chevron-down' size={20} />
          </Button>
        </View>
        <View style={{ flex: 1, alignItems: 'center' }}>
          <Text>수량 변경 사유</Text>
          {this.renderReasonModal()}
        </View>
        <View style={{ marginHorizontal: 5 }}>
          <Text>주문확인</Text>
          <Switch
            onValueChange={this.toggleConfirm}
            value={this.state.confirmed}
            disabled={orderProduct.status !== 101 &&
              orderProduct.status !== 102 && orderProduct.status !== 104}
          />
        </View>
      </View>
    );
  }
});

const styles = StyleSheet.create({
  container: {
    flexDirection: 'row',
    alignItems: 'center',
    padding: 5,
  },
  thumbnail: {
    backgroundColor: '#dddddd',
    borderColor: 'gray',
    borderWidth: 1,
    height: 50,
    width: 50,
  },
  quantityButton: {
    paddingHorizontal: 15,
  },
  quantityInput: {
    borderColor: 'gray',
    borderRadius: 6,
    borderWidth: 1,
    height: 45,
    textAlign: 'center',
  },
  reasonButton: {
    borderColor: 'gray',
    borderRadius: 6,
    borderWidth: 1,
    height: 45,
    width: 80,
    marginHorizontal: 5,
    justifyContent:'center',
  },
  reasonButtonText: {
    textAlign: 'center',
  },
});
<commit_msg>update order product cell layout.<commit_after>'use strict';

import React, {
  Image,
  StyleSheet,
  Text,
  TextInput,
  Switch,
  View,
} from 'react-native';
import { CloudinaryImageNative } from 'react-cloudinary';
import _ from 'lodash';
import Button from 'react-native-button';
import Icon from 'react-native-vector-icons/FontAwesome';
import ModalPicker from 'react-native-modal-picker'
import numeral from 'numeral';

import CountPicker from './CountPicker';

function getInitialState(props) {
  const { orderProduct } = props;
  const quantity = _.get(orderProduct, 'data.stock.quantity', orderProduct.quantity);
  return {
    quantity: quantity.toString(),
    reason: _.get(orderProduct, 'data.stock.reason', 0),
    confirmed: orderProduct.status !== 101,
  };
}

export default React.createClass({
  getInitialState() {
    return getInitialState(this.props);
  },
  toggleConfirm(confirmed) {
    this.setState({confirmed});
    if (confirmed) {
      const { quantity, reason } = this.state;
      this.props.confirm(+quantity, reason).then(
        () => this.setState(getInitialState(this.props))
      );
    }
  },
  setQuantity(quantity) {
    const { orderProduct } = this.props;
    if (quantity) {
      quantity = _.clamp(_.toSafeInteger(quantity), 0, orderProduct.quantity);
    }
    this.setState({
      quantity: quantity.toString(),
      reason: quantity == orderProduct.quantity ? 0 : (this.state.reason || 10),
    });
  },
  renderThumbnail({ product, productVariant }) {
    const image = _.get(productVariant, 'appImages.default.0');
    if (image) {
      return (
        <CloudinaryImageNative
          publicId={image.publicId}
          options={{ width: 100, height: 100 }}
          style={styles.thumbnail}
        />
      );
    }
  },
  renderReasonModal() {
    const { orderProduct } = this.props;
    const disabled= this.state.confirmed || this.state.quantity == orderProduct.quantity;
    const data = {
      0: { key: 0, label: '재고 있음' },
      10: { key: 10, label: '재입고 예정' },
      30: { key: 30, label: '품절' },
    };
    const selected = data[this.state.reason].label;
    const button = (
      <View style={styles.reasonButton}>
        <Text style={styles.reasonButtonText}>{selected}</Text>
      </View>
    );
    if (disabled) {
      return button;
    }
    return (
      <ModalPicker
        data={_.values(data).slice(1)}
        initValue={selected}
        onChange={(option)=> this.setState({ reason: option.key })}
      >
        {button}
      </ModalPicker>
    );
  },
  render() {
    const { orderProduct } = this.props;
    const { product, productVariant } = orderProduct;
    const { name } = product;
    const { color, size } = productVariant.data;
    const image = _.get(productVariant, 'appImages.default.0');
    return (
      <View style={styles.container}>
        <View style={styles.columnContainer}>
          <Text>{name.ko}</Text>
          <View style={styles.columnMainContainer}>
            <Text>{color} / {size}</Text>
            <Text>{`${numeral(orderProduct.KRW).format('0,0')}원`}</Text>
            {this.renderThumbnail(orderProduct)}
          </View>
        </View>
        <View style={styles.columnContainer}>
          <Text>주문수량: {numeral(orderProduct.quantity).format('0,0')}</Text>
          <View style={styles.columnMainContainer}>
            <Button
              containerStyle={styles.quantityButton}
              onPress={() => this.setQuantity(this.state.quantity + 1)}
            >
              <Icon name='chevron-up' size={20} />
            </Button>
            <TextInput
              autoCapitalize='none'
              autoCorrect={false}
              keyboardType='number-pad'
              onChangeText={this.setQuantity}
              value={this.state.quantity}
              style={styles.quantityInput}
              editable={!this.state.confirmed}
            />
            <Button
              containerStyle={styles.quantityButton}
              onPress={() => this.setQuantity(this.state.quantity - 1)}
            >
              <Icon name='chevron-down' size={20} />
            </Button>
          </View>
        </View>
        <View style={styles.columnContainer}>
            <Text>수량 변경 사유</Text>
          <View style={styles.columnMainContainer}>
            {this.renderReasonModal()}
          </View>
        </View>
        <View style={styles.columnContainer}>
          <Text>주문확인</Text>
          <View style={styles.columnMainContainer}>
            <Switch
              onValueChange={this.toggleConfirm}
              value={this.state.confirmed}
              disabled={orderProduct.status !== 101 &&
                orderProduct.status !== 102 && orderProduct.status !== 104}
            />
          </View>
        </View>
      </View>
    );
  }
});

const styles = StyleSheet.create({
  container: {
    alignItems: 'stretch',
    flexDirection: 'row',
    justifyContent:'space-between',
  },
  columnContainer: {
    alignItems: 'center',
    flexDirection: 'column',
    marginHorizontal: 5,
  },
  columnMainContainer: {
    flex: 1,
    alignItems: 'center',
    justifyContent:'center',
  },
  thumbnail: {
    backgroundColor: '#dddddd',
    borderColor: 'gray',
    borderWidth: 1,
    height: 50,
    width: 50,
  },
  quantityButton: {
    paddingHorizontal: 15,
  },
  quantityInput: {
    borderColor: 'gray',
    borderRadius: 6,
    borderWidth: 1,
    height: 45,
    textAlign: 'center',
  },
  reasonButton: {
    borderColor: 'gray',
    borderRadius: 6,
    borderWidth: 1,
    height: 45,
    width: 80,
    marginHorizontal: 5,
    justifyContent:'center',
  },
  reasonButtonText: {
    textAlign: 'center',
  },
});
<|endoftext|>


<commit_before>/*
*  Copyright (c) Codiad & Kent Safranski (codiad.com), distributed
*  as-is and without warranty under the MIT License. See
*  [root]/license.txt for more. This information must remain intact.
*/

//////////////////////////////////////////////////////////////////////
// Use window.load to delay until project scripts load
//////////////////////////////////////////////////////////////////////

$(window).load(function(){ filemanager.init(); });

var filemanager = {

    clipboard : '',

    no_open : ['jpg','jpeg','png','gif','svg','bmp','exe','zip','tar','tar.gz'],

    controller : 'components/filemanager/controller.php',
    dialog : 'components/filemanager/dialog.php',
    dialog_upload : 'components/filemanager/dialog_upload.php',

    init : function(){
        // Initialize node listener
        this.node_listener();
        // Context Menu Event Listener
        this.context_menu_event_listener();
        // Load uploader
        $.loadScript("components/filemanager/upload_scripts/jquery.ui.widget.js",true);
        $.loadScript("components/filemanager/upload_scripts/jquery.iframe-transport.js",true);
        $.loadScript("components/filemanager/upload_scripts/jquery.fileupload.js",true);
    },

    //////////////////////////////////////////////////////////////////
    // Listen for dbclick events on nodes
    //////////////////////////////////////////////////////////////////

    node_listener : function(){
        $('#file-manager a').live('dblclick',function(){ // Open or Expand
            if($(this).hasClass('directory')){
                filemanager.index($(this).attr('data-path'));
            }else{
                filemanager.open_file($(this).attr('data-path'));
            }
        })
        .live("contextmenu", function(e){ // Context Menu
            e.preventDefault();
            filemanager.context_menu_show(e,$(this).attr('data-path'),$(this).attr('data-type'));
            $(this).addClass('context-menu-active');
        });
    },

    //////////////////////////////////////////////////////////////////
    // Context Menu
    //////////////////////////////////////////////////////////////////

    context_menu_show : function(e,path,type){
        // Selective options
        switch(type){
            case 'directory':
                $('#context-menu .directory-only, #context-menu .non-root').show();
                $('#context-menu .file-only').hide();
                break;
            case 'file':
                $('#context-menu .directory-only').hide();
                $('#context-menu .file-only,#context-menu .non-root').show();
                break;
            case 'root':
                $('#context-menu .directory-only').show();
                $('#context-menu .non-root, #context-menu .file-only').hide();
                break;
        }
        // Show menu
        $('#context-menu').css({'top':(e.pageY-10)+'px','left':(e.pageX-10)+'px'})
            .fadeIn(200).attr('data-path',path).attr('data-type',type);
        // Show faded 'paste' if nothing in clipboard
        if(this.clipboard==''){ $('#context-menu a[data-action="paste"]').addClass('disabled');
        }else{ $('#context-menu a[data-action="paste"]').removeClass('disabled'); }
        // Hide menu
        $('#file-manager, #editor-region').on('mouseover',function(){ filemanager.context_menu_hide(); });
    },

    context_menu_hide : function(){
        $('#context-menu').fadeOut(200);
        $('#file-manager a').removeClass('context-menu-active');
    },

    context_menu_event_listener : function(){
        $('#context-menu a').live('click',function(){
            filemanager.context_menu_hide();
            var path = $('#context-menu').attr('data-path');
            var action = $(this).attr('data-action');
            switch(action){
                case 'new_file':
                    filemanager.create_node(path,'file');
                    break;
                case 'new_directory':
                    filemanager.create_node(path,'directory');
                    break;
                case 'copy':
                    filemanager.copy_node(path);
                    break;
                case 'paste':
                    filemanager.paste_node(path);
                    break;
                case 'rename':
                    filemanager.rename_node(path);
                    break;
                case 'delete':
                    filemanager.delete_node(path);
                    break;
                case 'upload':
                    filemanager.upload_to_node(path);
                    break;
                case 'backup':
                    filemanager.download(path);
                    break;
            }
        });
    },

    //////////////////////////////////////////////////////////////////
    // Return the node name (sans path)
    //////////////////////////////////////////////////////////////////

    get_short_name : function(path){ return path.split('/').pop(); },

    //////////////////////////////////////////////////////////////////
    // Return extension
    //////////////////////////////////////////////////////////////////

    get_extension : function(path){ return path.split('.').pop(); },

    //////////////////////////////////////////////////////////////////
    // Return type
    //////////////////////////////////////////////////////////////////

    get_type : function(path){ return $('#file-manager a[data-path="'+path+'"]').attr('data-type'); },

    //////////////////////////////////////////////////////////////////
    // Create node in file tree
    //////////////////////////////////////////////////////////////////

    create_object : function(parent,path,type){
        // NODE FORMAT:
{short_name}

        var parent_node = $('#file-manager a[data-path="'+parent+'"]');
        if(!$('#file-manager a[data-path="'+path+'"]').length){ // Doesn't already exist
            if(parent_node.hasClass('open') && parent_node.hasClass('directory')){ // Only append node if parent is open (and a directory)
                var short_name = filemanager.get_short_name(path);
                if(type=='directory'){
                    var appendage = '
'+short_name+'
';
                }else{
                    var appendage = '
'+short_name+'
';
                }
                if(parent_node.siblings('ul').length){ // UL exists, other children to play with
                    parent_node.siblings('ul').append(appendage);
                }else{
                    $('
'+appendage+'
').insertAfter(parent_node);
                }
            }
        }
    },

    //////////////////////////////////////////////////////////////////
    // Loop out all files and folders in directory path
    //////////////////////////////////////////////////////////////////

    index : function(path){
        node = $('#file-manager a[data-path="'+path+'"]');
        node.addClass('loading');
        $.get(this.controller+'?action=index&path='+path,function(data){
            if(node.hasClass('open')){
                node.parent('li').children('ul').slideUp(300,function(){
                    $(this).remove();
                    node.removeClass('open');
                });
            }else{
                node.addClass('open');
                objects_response = jsend.parse(data);
                if(objects_response!='error'){
                    files = objects_response.index;
                    if(files.length>0){
                        var appendage = '
';
                        $.each(files,function(index){
                            var ext = '';
                            var name = files[index].name.replace(path,'');
                            name = name.split('/').join(' ');
                            if(files[index].type=='file'){ var ext = ' ext-'+name.split('.').pop(); }
                            appendage += '
'+name+'
';
                        });
                        appendage += '
';
                        $(appendage).insertAfter(node);
                        node.siblings('ul').slideDown(300);
                    }
                }
            }
            node.removeClass('loading');
        });

    },

    //////////////////////////////////////////////////////////////////
    // Open File
    //////////////////////////////////////////////////////////////////

    open_file : function(path){
        var ext = filemanager.get_extension(path);
        if($.inArray(ext,filemanager.no_open)<0){
            $.get(this.controller+'?action=open&path='+path,function(data){
                open_response = jsend.parse(data);
                if(open_response!='error'){
                    editor.open(path,open_response.content);
                }
            });
        }else{
            filemanager.download(path);
        }
    },

    //////////////////////////////////////////////////////////////////
    // Open in browser
    //////////////////////////////////////////////////////////////////

    open_in_browser : function(path){
        $.get(this.controller+'?action=open_in_browser&path='+path,function(data){
            openib_response = jsend.parse(data);
            if(openib_response!='error'){
                window.open(openib_response.url,'_newtab');
            }
        });
    },

    //////////////////////////////////////////////////////////////////
    // Save file
    //////////////////////////////////////////////////////////////////

    save_file : function(path,content){
        $.post(this.controller+'?action=modify&path='+path,{content:content},function(data){
            save_response = jsend.parse(data);
            if(save_response!='error'){
                message.success('File Saved');
            }
        });
    },

    //////////////////////////////////////////////////////////////////
    // Create Object
    //////////////////////////////////////////////////////////////////

    create_node : function(path,type){
        modal.load(250,this.dialog+'?action=create&type='+type+'&path='+path);
        $('#modal-content form').live('submit',function(e){
            e.preventDefault();
            var short_name = $('#modal-content form input[name="object_name"]').val();
            var path = $('#modal-content form input[name="path"]').val();
            var type = $('#modal-content form input[name="type"]').val();
            var create_path = path + '/' + short_name;
            $.get(filemanager.controller+'?action=create&path='+create_path+'&type='+type,function(data){
                create_response = jsend.parse(data);
                if(create_response!='error'){
                    message.success(type.charAt(0).toUpperCase() + type.slice(1)+' Created');
                    modal.unload();
                    // Add new element to filemanager screen
                    filemanager.create_object(path,create_path,type);
                }
            });
        });
    },

    //////////////////////////////////////////////////////////////////
    // Copy to Clipboard
    //////////////////////////////////////////////////////////////////

    copy_node : function(path){ this.clipboard = path; message.success('Copied to Clipboard'); },

    //////////////////////////////////////////////////////////////////
    // Paste
    //////////////////////////////////////////////////////////////////

    paste_node : function(path){
        if(this.clipboard==''){ message.error('Nothing in Your Clipboard'); }
        else if(path==filemanager.clipboard){ message.error('Cannot Paste Directory Into Itself'); }
        else{
            var short_name = filemanager.get_short_name(filemanager.clipboard);
            if($('#file-manager a[data-path="'+path+'/'+short_name+'"]').length){ // Confirm overwrite?
                modal.load(400,this.dialog+'?action=overwrite&path='+path+'/'+short_name);
                $('#modal-content form').live('submit',function(e){
                    e.preventDefault();
                    filemanager.process_paste_node(path);
                });
            }else{ // No conflicts; proceed...
                filemanager.process_paste_node(path);
            }
        }
    },

    process_paste_node : function(path){
        var short_name = filemanager.get_short_name(filemanager.clipboard);
        var type = filemanager.get_type(filemanager.clipboard);
        $.get(filemanager.controller+'?action=duplicate&path='+filemanager.clipboard+'&destination='+path+'/'+short_name,function(data){
            paste_response = jsend.parse(data);
            if(paste_response!='error'){
                filemanager.create_object(path,path+'/'+short_name,type);
                modal.unload();
            }
        });
    },

    //////////////////////////////////////////////////////////////////
    // Rename
    //////////////////////////////////////////////////////////////////

    rename_node : function(path){
        var short_name = filemanager.get_short_name(path);
        var type = filemanager.get_type(path);
        modal.load(250,this.dialog+'?action=rename&path='+path+'&short_name='+short_name+'&type='+type);
        $('#modal-content form').live('submit',function(e){
            e.preventDefault();
            new_name = $('#modal-content form input[name="object_name"]').val();
            // Build new path
            var arr = path.split('/');
            var temp = new Array();
            for(i = 0; i < arr.length-1; i++){ temp.push(arr[i]) }
            new_path = temp.join('/') + '/'+new_name;
            $.get(filemanager.controller+'?action=modify&path='+path+'&new_name='+new_name,function(data){
                rename_response = jsend.parse(data);
                if(rename_response!='error'){
                    message.success(type.charAt(0).toUpperCase() + type.slice(1)+' Renamed');
                    var node = $('#file-manager a[data-path="'+path+'"]');
                    // Change pathing and name for node
                    node.attr('data-path',new_path).html(new_name);
                    if(type=='file'){ // Change icons for file
                        cur_ext_class = 'ext-'+filemanager.get_extension(path);
                        new_ext_class = 'ext-'+filemanager.get_extension(new_path);
                        $('#file-manager a[data-path="'+new_path+'"]').removeClass(cur_ext_class).addClass(new_ext_class);
                    }else{ // Change pathing on any sub-files/directories
                        filemanager.repath_subs(path,new_path);
                    }
                    // Change any active files
                    active.rename(path,new_path);
                    modal.unload();
                }
            });
        });
    },

    repath_subs : function(old_path,new_path){
        $('#file-manager a[data-path="'+new_path+'"]').siblings('ul').find('a').each(function(){
            // Hit the children, hit 'em hard
            var cur_path = $(this).attr('data-path');
            var revised_path = cur_path.replace(old_path,new_path);
            $(this).attr('data-path',revised_path);
        });
    },

    //////////////////////////////////////////////////////////////////
    // Delete
    //////////////////////////////////////////////////////////////////

    delete_node : function(path){
        modal.load(400,this.dialog+'?action=delete&path='+path);
        $('#modal-content form').live('submit',function(e){
            e.preventDefault();
            $.get(filemanager.controller+'?action=delete&path='+path,function(data){
                delete_response = jsend.parse(data);
                if(delete_response!='error'){
                    var node = $('#file-manager a[data-path="'+path+'"]');
                    node.parent('li').remove();
                    // Close any active files
                    $('#active-files a').each(function(){
                        var cur_path = $(this).attr('data-path');
                        if(cur_path.indexOf(path)==0){
                            active.remove(cur_path);
                        }
                    });
                }
                modal.unload();
            });
        });
    },

    //////////////////////////////////////////////////////////////////
    // Upload
    //////////////////////////////////////////////////////////////////

    upload_to_node : function(path){
        modal.load(500,this.dialog_upload+'?path='+path);
    },

    //////////////////////////////////////////////////////////////////
    // Download
    //////////////////////////////////////////////////////////////////

    download : function(path){
        var type = filemanager.get_type(path);
        $('#download').attr('src','components/filemanager/download.php?path='+path+'&type='+type);
    }
};<commit_msg>Adding Default Action to filemanager<commit_after>/*
*  Copyright (c) Codiad & Kent Safranski (codiad.com), distributed
*  as-is and without warranty under the MIT License. See
*  [root]/license.txt for more. This information must remain intact.
*/

//////////////////////////////////////////////////////////////////////
// Use window.load to delay until project scripts load
//////////////////////////////////////////////////////////////////////

$(window).load(function(){ filemanager.init(); });

var filemanager = {

    clipboard : '',

    no_open : ['jpg','jpeg','png','gif','svg','bmp','exe','zip','tar','tar.gz'],

    controller : 'components/filemanager/controller.php',
    dialog : 'components/filemanager/dialog.php',
    dialog_upload : 'components/filemanager/dialog_upload.php',

    init : function(){
        // Initialize node listener
        this.node_listener();
        // Context Menu Event Listener
        this.context_menu_event_listener();
        // Load uploader
        $.loadScript("components/filemanager/upload_scripts/jquery.ui.widget.js",true);
        $.loadScript("components/filemanager/upload_scripts/jquery.iframe-transport.js",true);
        $.loadScript("components/filemanager/upload_scripts/jquery.fileupload.js",true);
    },

    //////////////////////////////////////////////////////////////////
    // Listen for dbclick events on nodes
    //////////////////////////////////////////////////////////////////

    node_listener : function(){
        $('#file-manager a').live('dblclick',function(){ // Open or Expand
            if($(this).hasClass('directory')){
                filemanager.index($(this).attr('data-path'));
            }else{
                filemanager.open_file($(this).attr('data-path'));
            }
        })
        .live("contextmenu", function(e){ // Context Menu
            e.preventDefault();
            filemanager.context_menu_show(e,$(this).attr('data-path'),$(this).attr('data-type'));
            $(this).addClass('context-menu-active');
        });
    },

    //////////////////////////////////////////////////////////////////
    // Context Menu
    //////////////////////////////////////////////////////////////////

    context_menu_show : function(e,path,type){
        // Selective options
        switch(type){
            case 'directory':
                $('#context-menu .directory-only, #context-menu .non-root').show();
                $('#context-menu .file-only').hide();
                break;
            case 'file':
                $('#context-menu .directory-only').hide();
                $('#context-menu .file-only,#context-menu .non-root').show();
                break;
            case 'root':
                $('#context-menu .directory-only').show();
                $('#context-menu .non-root, #context-menu .file-only').hide();
                break;
        }
        // Show menu
        $('#context-menu').css({'top':(e.pageY-10)+'px','left':(e.pageX-10)+'px'})
            .fadeIn(200).attr('data-path',path).attr('data-type',type);
        // Show faded 'paste' if nothing in clipboard
        if(this.clipboard==''){ $('#context-menu a[data-action="paste"]').addClass('disabled');
        }else{ $('#context-menu a[data-action="paste"]').removeClass('disabled'); }
        // Hide menu
        $('#file-manager, #editor-region').on('mouseover',function(){ filemanager.context_menu_hide(); });
    },

    context_menu_hide : function(){
        $('#context-menu').fadeOut(200);
        $('#file-manager a').removeClass('context-menu-active');
    },

    context_menu_event_listener : function(){
        $('#context-menu a').live('click',function(){
            filemanager.context_menu_hide();
            var path = $('#context-menu').attr('data-path');
            var action = $(this).attr('data-action');
            switch(action){
                case 'new_file':
                    filemanager.create_node(path,'file');
                    break;
                case 'new_directory':
                    filemanager.create_node(path,'directory');
                    break;
                case 'copy':
                    filemanager.copy_node(path);
                    break;
                case 'paste':
                    filemanager.paste_node(path);
                    break;
                case 'rename':
                    filemanager.rename_node(path);
                    break;
                case 'delete':
                    filemanager.delete_node(path);
                    break;
                case 'upload':
                    filemanager.upload_to_node(path);
                    break;
                case 'backup':
                    filemanager.download(path);
                    break;
                default:
                    //Endables other actions to be applyed by changing the data-action attribute to object-function
                    string = action.replace('-','.');
                    eval(string + '(path);');
                    break;
            }
        });
    },

    //////////////////////////////////////////////////////////////////
    // Return the node name (sans path)
    //////////////////////////////////////////////////////////////////

    get_short_name : function(path){ return path.split('/').pop(); },

    //////////////////////////////////////////////////////////////////
    // Return extension
    //////////////////////////////////////////////////////////////////

    get_extension : function(path){ return path.split('.').pop(); },

    //////////////////////////////////////////////////////////////////
    // Return type
    //////////////////////////////////////////////////////////////////

    get_type : function(path){ return $('#file-manager a[data-path="'+path+'"]').attr('data-type'); },

    //////////////////////////////////////////////////////////////////
    // Create node in file tree
    //////////////////////////////////////////////////////////////////

    create_object : function(parent,path,type){
        // NODE FORMAT:
{short_name}

        var parent_node = $('#file-manager a[data-path="'+parent+'"]');
        if(!$('#file-manager a[data-path="'+path+'"]').length){ // Doesn't already exist
            if(parent_node.hasClass('open') && parent_node.hasClass('directory')){ // Only append node if parent is open (and a directory)
                var short_name = filemanager.get_short_name(path);
                if(type=='directory'){
                    var appendage = '
'+short_name+'
';
                }else{
                    var appendage = '
'+short_name+'
';
                }
                if(parent_node.siblings('ul').length){ // UL exists, other children to play with
                    parent_node.siblings('ul').append(appendage);
                }else{
                    $('
'+appendage+'
').insertAfter(parent_node);
                }
            }
        }
    },

    //////////////////////////////////////////////////////////////////
    // Loop out all files and folders in directory path
    //////////////////////////////////////////////////////////////////

    index : function(path){
        node = $('#file-manager a[data-path="'+path+'"]');
        node.addClass('loading');
        $.get(this.controller+'?action=index&path='+path,function(data){
            if(node.hasClass('open')){
                node.parent('li').children('ul').slideUp(300,function(){
                    $(this).remove();
                    node.removeClass('open');
                });
            }else{
                node.addClass('open');
                objects_response = jsend.parse(data);
                if(objects_response!='error'){
                    files = objects_response.index;
                    if(files.length>0){
                        var appendage = '
';
                        $.each(files,function(index){
                            var ext = '';
                            var name = files[index].name.replace(path,'');
                            name = name.split('/').join(' ');
                            if(files[index].type=='file'){ var ext = ' ext-'+name.split('.').pop(); }
                            appendage += '
'+name+'
';
                        });
                        appendage += '
';
                        $(appendage).insertAfter(node);
                        node.siblings('ul').slideDown(300);
                    }
                }
            }
            node.removeClass('loading');
        });

    },

    //////////////////////////////////////////////////////////////////
    // Open File
    //////////////////////////////////////////////////////////////////

    open_file : function(path){
        var ext = filemanager.get_extension(path);
        if($.inArray(ext,filemanager.no_open)<0){
            $.get(this.controller+'?action=open&path='+path,function(data){
                open_response = jsend.parse(data);
                if(open_response!='error'){
                    editor.open(path,open_response.content);
                }
            });
        }else{
            filemanager.download(path);
        }
    },

    //////////////////////////////////////////////////////////////////
    // Open in browser
    //////////////////////////////////////////////////////////////////

    open_in_browser : function(path){
        $.get(this.controller+'?action=open_in_browser&path='+path,function(data){
            openib_response = jsend.parse(data);
            if(openib_response!='error'){
                window.open(openib_response.url,'_newtab');
            }
        });
    },

    //////////////////////////////////////////////////////////////////
    // Save file
    //////////////////////////////////////////////////////////////////

    save_file : function(path,content){
        $.post(this.controller+'?action=modify&path='+path,{content:content},function(data){
            save_response = jsend.parse(data);
            if(save_response!='error'){
                message.success('File Saved');
            }
        });
    },

    //////////////////////////////////////////////////////////////////
    // Create Object
    //////////////////////////////////////////////////////////////////

    create_node : function(path,type){
        modal.load(250,this.dialog+'?action=create&type='+type+'&path='+path);
        $('#modal-content form').live('submit',function(e){
            e.preventDefault();
            var short_name = $('#modal-content form input[name="object_name"]').val();
            var path = $('#modal-content form input[name="path"]').val();
            var type = $('#modal-content form input[name="type"]').val();
            var create_path = path + '/' + short_name;
            $.get(filemanager.controller+'?action=create&path='+create_path+'&type='+type,function(data){
                create_response = jsend.parse(data);
                if(create_response!='error'){
                    message.success(type.charAt(0).toUpperCase() + type.slice(1)+' Created');
                    modal.unload();
                    // Add new element to filemanager screen
                    filemanager.create_object(path,create_path,type);
                }
            });
        });
    },

    //////////////////////////////////////////////////////////////////
    // Copy to Clipboard
    //////////////////////////////////////////////////////////////////

    copy_node : function(path){ this.clipboard = path; message.success('Copied to Clipboard'); },

    //////////////////////////////////////////////////////////////////
    // Paste
    //////////////////////////////////////////////////////////////////

    paste_node : function(path){
        if(this.clipboard==''){ message.error('Nothing in Your Clipboard'); }
        else if(path==filemanager.clipboard){ message.error('Cannot Paste Directory Into Itself'); }
        else{
            var short_name = filemanager.get_short_name(filemanager.clipboard);
            if($('#file-manager a[data-path="'+path+'/'+short_name+'"]').length){ // Confirm overwrite?
                modal.load(400,this.dialog+'?action=overwrite&path='+path+'/'+short_name);
                $('#modal-content form').live('submit',function(e){
                    e.preventDefault();
                    filemanager.process_paste_node(path);
                });
            }else{ // No conflicts; proceed...
                filemanager.process_paste_node(path);
            }
        }
    },

    process_paste_node : function(path){
        var short_name = filemanager.get_short_name(filemanager.clipboard);
        var type = filemanager.get_type(filemanager.clipboard);
        $.get(filemanager.controller+'?action=duplicate&path='+filemanager.clipboard+'&destination='+path+'/'+short_name,function(data){
            paste_response = jsend.parse(data);
            if(paste_response!='error'){
                filemanager.create_object(path,path+'/'+short_name,type);
                modal.unload();
            }
        });
    },

    //////////////////////////////////////////////////////////////////
    // Rename
    //////////////////////////////////////////////////////////////////

    rename_node : function(path){
        var short_name = filemanager.get_short_name(path);
        var type = filemanager.get_type(path);
        modal.load(250,this.dialog+'?action=rename&path='+path+'&short_name='+short_name+'&type='+type);
        $('#modal-content form').live('submit',function(e){
            e.preventDefault();
            new_name = $('#modal-content form input[name="object_name"]').val();
            // Build new path
            var arr = path.split('/');
            var temp = new Array();
            for(i = 0; i < arr.length-1; i++){ temp.push(arr[i]) }
            new_path = temp.join('/') + '/'+new_name;
            $.get(filemanager.controller+'?action=modify&path='+path+'&new_name='+new_name,function(data){
                rename_response = jsend.parse(data);
                if(rename_response!='error'){
                    message.success(type.charAt(0).toUpperCase() + type.slice(1)+' Renamed');
                    var node = $('#file-manager a[data-path="'+path+'"]');
                    // Change pathing and name for node
                    node.attr('data-path',new_path).html(new_name);
                    if(type=='file'){ // Change icons for file
                        cur_ext_class = 'ext-'+filemanager.get_extension(path);
                        new_ext_class = 'ext-'+filemanager.get_extension(new_path);
                        $('#file-manager a[data-path="'+new_path+'"]').removeClass(cur_ext_class).addClass(new_ext_class);
                    }else{ // Change pathing on any sub-files/directories
                        filemanager.repath_subs(path,new_path);
                    }
                    // Change any active files
                    active.rename(path,new_path);
                    modal.unload();
                }
            });
        });
    },

    repath_subs : function(old_path,new_path){
        $('#file-manager a[data-path="'+new_path+'"]').siblings('ul').find('a').each(function(){
            // Hit the children, hit 'em hard
            var cur_path = $(this).attr('data-path');
            var revised_path = cur_path.replace(old_path,new_path);
            $(this).attr('data-path',revised_path);
        });
    },

    //////////////////////////////////////////////////////////////////
    // Delete
    //////////////////////////////////////////////////////////////////

    delete_node : function(path){
        modal.load(400,this.dialog+'?action=delete&path='+path);
        $('#modal-content form').live('submit',function(e){
            e.preventDefault();
            $.get(filemanager.controller+'?action=delete&path='+path,function(data){
                delete_response = jsend.parse(data);
                if(delete_response!='error'){
                    var node = $('#file-manager a[data-path="'+path+'"]');
                    node.parent('li').remove();
                    // Close any active files
                    $('#active-files a').each(function(){
                        var cur_path = $(this).attr('data-path');
                        if(cur_path.indexOf(path)==0){
                            active.remove(cur_path);
                        }
                    });
                }
                modal.unload();
            });
        });
    },

    //////////////////////////////////////////////////////////////////
    // Upload
    //////////////////////////////////////////////////////////////////

    upload_to_node : function(path){
        modal.load(500,this.dialog_upload+'?path='+path);
    },

    //////////////////////////////////////////////////////////////////
    // Download
    //////////////////////////////////////////////////////////////////

    download : function(path){
        var type = filemanager.get_type(path);
        $('#download').attr('src','components/filemanager/download.php?path='+path+'&type='+type);
    }
};<|endoftext|>


<commit_before>/**
 * Simple IMG wrapper
 *
 * @class image
 * @augments elation.ui.base
 * @memberof elation.ui
 *
 * @param {object} args
 * @param {string} args.src
 */
elation.require("ui.base", function() {
  elation.component.add("ui.image", function() {
    this.defaultcontainer = {tag: 'img', classname: 'ui_image'};

    this.init = function() {
      if (this.args.src) {
        this.container.src = this.args.src;
      }
      if (this.args.classname) {
        elation.html.addclass(this.container, this.args.classname);
      }

      if (this.args.hidden) {
        this.hide();
      }
    }
  }, elation.ui.base);
});
<commit_msg>Use propertyProxies for ui.image<commit_after>/**
 * Simple IMG wrapper
 *
 * @class image
 * @augments elation.ui.base
 * @memberof elation.ui
 *
 * @param {object} args
 * @param {string} args.src
 */
elation.require("ui.base", function() {
  elation.component.add("ui.image", function() {
    this.defaultcontainer = {tag: 'img', classname: 'ui_image'};

    this.init = function() {
      this.addPropertyProxies(['src', 'width', 'height']);
      if (this.args.src) {
        this.src = this.args.src;
      }
      if (this.args.classname) {
        elation.html.addclass(this.container, this.args.classname);
      }

      if (this.args.hidden) {
        this.hide();
      }
    }
  }, elation.ui.base);
});
<|endoftext|>


<commit_before>import { call, put, select, take, takeLatest } from 'redux-saga/effects';
import {
  fetchDataSelection,
  receiveDataSelectionFailure,
  receiveDataSelectionSuccess,
  removeGeometryFilter,
  setMarkers
} from '../../ducks/data-selection/actions';
import dataSelectionConfig from '../../services/data-selection/data-selection-config';
import { getMarkers, query } from '../../services/data-selection/data-selection-api';
import { getMapBoundingBox, getMapZoom } from '../../../map/ducks/map/map-selectors';
import {
  ADD_FILTER,
  EMPTY_FILTERS,
  getFiltersWithoutShape,
  REMOVE_FILTER
} from '../../ducks/filters/filters';
import { preserveQuery, toDatasetPage } from '../../../store/redux-first-router/actions';
import { isDataSelectionPage } from '../../../store/redux-first-router/selectors';
import { cancel, disable, enable, setPolygon } from '../../../map/services/draw-tool/draw-tool';
import {
  CANCEL_DATA_SELECTION,
  END_DATA_SELECTION,
  FETCH_DATA_SELECTION_REQUEST,
  REMOVE_GEOMETRY_FILTER,
  RESET_DATA_SELECTION,
  SET_DATASET,
  SET_GEOMETRY_FILTER,
  SET_PAGE,
  SET_VIEW,
  START_DATA_SELECTION,
  VIEWS
} from '../../ducks/data-selection/constants';
import {
  getDataSelection,
  getGeomarkersShape,
  getGeometryFilters
} from '../../ducks/data-selection/selectors';
import { waitForAuthentication } from '../user/user';
import {
  MAP_BOUNDING_BOX,
  mapEmptyGeometry,
  mapEndDrawing,
  mapLoadingAction,
  mapStartDrawing
} from '../../../map/ducks/map/map';
import PARAMETERS from '../../../store/parameters';
import drawToolConfig from '../../../map/services/draw-tool/draw-tool.config';

function* getMapMarkers(dataset, activeFilters) {
  // Since bounding box can be set later, we check if we have to wait for the boundingbox to get set
  let boundingBox = yield select(getMapBoundingBox);
  if (!boundingBox) {
    yield take(MAP_BOUNDING_BOX);
    boundingBox = yield select(getMapBoundingBox);
  }
  const mapZoom = yield select(getMapZoom);
  const markerData = yield call(getMarkers,
    dataset, activeFilters, mapZoom, boundingBox);
  yield put(setMarkers(markerData));
}

function* retrieveDataSelection(action) {
  const {
    dataset,
    view,
    page,
    searchText,
    catalogFilters
  } = action.payload;

  try {
    yield call(waitForAuthentication);
    const activeFilters = yield select(getFiltersWithoutShape);
    const shape = yield select(getGeomarkersShape);
    // exclude the geometryFilter from the attribute filters
    // TODO DP-6442 improve the geometryFilter handling
    const activeAttributeFilters = Object.keys(activeFilters)
                                         .reduce((result, key) => ({
                                           ...result,
                                           [key]: activeFilters[key]
                                         }), {});

    const result = yield call(query,
      dataset, view, activeAttributeFilters, page, searchText, shape, catalogFilters);

    // Put the results in the reducer
    yield put(receiveDataSelectionSuccess({
      dataset, view, activeFilters, page, shape, result
    }));

    // Check if markers need to be fetched
    const { MAX_NUMBER_OF_CLUSTERED_MARKERS } = dataSelectionConfig.datasets[dataset];
    const markersShouldBeFetched = (
      view !== VIEWS.TABLE && result.numberOfRecords <= MAX_NUMBER_OF_CLUSTERED_MARKERS
    );

    if (markersShouldBeFetched) {
      yield put(mapLoadingAction(true));
      yield call(getMapMarkers, dataset, { ...activeFilters, shape });
      yield put(mapLoadingAction(false));
    }
    yield put(mapLoadingAction(false)); // reset loading after retrieving data selection
  } catch (e) {
    yield put(receiveDataSelectionFailure({
      error: e.message,
      dataset
    }));
    yield put(mapLoadingAction(false));
  }
}

export function* fetchDataSelectionEffect() {
  const state = yield select();

  // Always ensure we are on the right page, otherwise this can be called unintentionally
  if (isDataSelectionPage(state)) {
    const dataSelection = getDataSelection(state);
    yield put(
      fetchDataSelection({
        ...dataSelection
      })
    );
  }
}

function* clearShapeFilter(action) {
  if (action.payload === 'shape') {
    yield put(removeGeometryFilter());
  }
}

function* switchPage(additionalParams = {}) {
  const state = yield select();
  const dataSelection = getDataSelection(state);
  yield put(preserveQuery(toDatasetPage(dataSelection.dataset), additionalParams));
}

function* setGeometryFilters({ payload }) {
  const geometryFilters = yield select(getGeometryFilters);
  yield put(mapEndDrawing({ polygon: payload }));

  // Don't switch page if line is drawn
  if (payload.markers.length > 2) {
    yield call(switchPage, {
      [PARAMETERS.GEO]: geometryFilters,
      [PARAMETERS.VIEW]: VIEWS.LIST
    });
  }
}

function* clearDrawing() {
  yield call(setPolygon, []);
  yield call(enable);
  yield put(mapEmptyGeometry());
}

function* startDrawing() {
  yield call(setPolygon, []);
  yield call(enable);
  yield put(mapStartDrawing({ drawingMode: drawToolConfig.DRAWING_MODE.DRAW }));
}

function* endDrawing() {
  yield call(disable);
}

function* cancelDrawing() {
  yield put(mapEmptyGeometry());
  yield call(cancel);
}

export default function* watchFetchDataSelection() {
  yield takeLatest(REMOVE_FILTER, clearShapeFilter);
  yield takeLatest(SET_GEOMETRY_FILTER, setGeometryFilters);
  yield takeLatest(
    [SET_VIEW, SET_PAGE, ADD_FILTER, REMOVE_FILTER, REMOVE_GEOMETRY_FILTER, EMPTY_FILTERS],
    fetchDataSelectionEffect
  );

  // Actions
  yield takeLatest(FETCH_DATA_SELECTION_REQUEST, retrieveDataSelection);
  yield takeLatest([SET_DATASET], switchPage);

  yield takeLatest(RESET_DATA_SELECTION, clearDrawing);
  yield takeLatest(START_DATA_SELECTION, startDrawing);
  yield takeLatest(END_DATA_SELECTION, endDrawing);
  yield takeLatest(CANCEL_DATA_SELECTION, cancelDrawing);
}
<commit_msg>Fixed drawtool issue<commit_after>import { call, put, select, take, takeLatest } from 'redux-saga/effects';
import {
  fetchDataSelection,
  receiveDataSelectionFailure,
  receiveDataSelectionSuccess,
  removeGeometryFilter,
  setMarkers
} from '../../ducks/data-selection/actions';
import dataSelectionConfig from '../../services/data-selection/data-selection-config';
import { getMarkers, query } from '../../services/data-selection/data-selection-api';
import { getMapBoundingBox, getMapZoom } from '../../../map/ducks/map/map-selectors';
import {
  ADD_FILTER,
  EMPTY_FILTERS,
  getFiltersWithoutShape,
  REMOVE_FILTER
} from '../../ducks/filters/filters';
import { preserveQuery, toDatasetPage } from '../../../store/redux-first-router/actions';
import { isDataSelectionPage } from '../../../store/redux-first-router/selectors';
import { cancel, disable, enable, setPolygon } from '../../../map/services/draw-tool/draw-tool';
import {
  CANCEL_DATA_SELECTION,
  END_DATA_SELECTION,
  FETCH_DATA_SELECTION_REQUEST,
  REMOVE_GEOMETRY_FILTER,
  RESET_DATA_SELECTION,
  SET_DATASET,
  SET_GEOMETRY_FILTER,
  SET_PAGE,
  SET_VIEW,
  START_DATA_SELECTION,
  VIEWS
} from '../../ducks/data-selection/constants';
import {
  getDataSelection,
  getGeomarkersShape,
  getGeometryFilters
} from '../../ducks/data-selection/selectors';
import { waitForAuthentication } from '../user/user';
import {
  MAP_BOUNDING_BOX,
  mapEmptyGeometry,
  mapEndDrawing,
  mapLoadingAction,
  mapStartDrawing
} from '../../../map/ducks/map/map';
import PARAMETERS from '../../../store/parameters';
import drawToolConfig from '../../../map/services/draw-tool/draw-tool.config';

function* getMapMarkers(dataset, activeFilters) {
  // Since bounding box can be set later, we check if we have to wait for the boundingbox to get set
  let boundingBox = yield select(getMapBoundingBox);
  if (!boundingBox) {
    yield take(MAP_BOUNDING_BOX);
    boundingBox = yield select(getMapBoundingBox);
  }
  const mapZoom = yield select(getMapZoom);
  const markerData = yield call(getMarkers,
    dataset, activeFilters, mapZoom, boundingBox);
  yield put(setMarkers(markerData));
}

function* retrieveDataSelection(action) {
  const {
    dataset,
    view,
    page,
    searchText,
    catalogFilters
  } = action.payload;

  try {
    yield call(waitForAuthentication);
    const activeFilters = yield select(getFiltersWithoutShape);
    const shape = yield select(getGeomarkersShape);
    // exclude the geometryFilter from the attribute filters
    // TODO DP-6442 improve the geometryFilter handling
    const activeAttributeFilters = Object.keys(activeFilters)
                                         .reduce((result, key) => ({
                                           ...result,
                                           [key]: activeFilters[key]
                                         }), {});

    const result = yield call(query,
      dataset, view, activeAttributeFilters, page, searchText, shape, catalogFilters);

    // Put the results in the reducer
    yield put(receiveDataSelectionSuccess({
      dataset, view, activeFilters, page, shape, result
    }));

    // Check if markers need to be fetched
    const { MAX_NUMBER_OF_CLUSTERED_MARKERS } = dataSelectionConfig.datasets[dataset];
    const markersShouldBeFetched = (
      view !== VIEWS.TABLE && result.numberOfRecords <= MAX_NUMBER_OF_CLUSTERED_MARKERS
    );

    if (markersShouldBeFetched) {
      yield put(mapLoadingAction(true));
      yield call(getMapMarkers, dataset, { ...activeFilters, shape });
      yield put(mapLoadingAction(false));
    }
    yield put(mapLoadingAction(false)); // reset loading after retrieving data selection
  } catch (e) {
    yield put(receiveDataSelectionFailure({
      error: e.message,
      dataset
    }));
    yield put(mapLoadingAction(false));
  }
}

function* requestDataSelectionEffect() {
  yield put(mapLoadingAction(true));
  const dataSelection = yield select(getDataSelection);
  yield put(
    fetchDataSelection({
      ...dataSelection
    })
  );
}

export function* fetchDataSelectionEffect() {
  const dataSelectionPage = yield select(isDataSelectionPage);

  // Always ensure we are on the right page, otherwise this can be called unintentionally
  if (dataSelectionPage) {
    yield call(requestDataSelectionEffect);
  }
}

function* clearShapeFilter(action) {
  if (action.payload === 'shape') {
    yield put(removeGeometryFilter());
  }
}

function* switchPage(additionalParams = {}) {
  const { dataset } = yield select(getDataSelection);
  yield put(preserveQuery(toDatasetPage(dataset), additionalParams));
}

function* setGeometryFilters({ payload }) {
  const geometryFilters = yield select(getGeometryFilters);
  const dataSelectionPage = yield select(isDataSelectionPage);
  yield put(mapEndDrawing({ polygon: payload }));

  // Don't switch page if line is drawn
  if (payload.markers.length > 2) {
    // We shouldn't switch page if we are on a dataSelection page
    if (dataSelectionPage) {
      yield call(requestDataSelectionEffect);
    } else {
      yield call(switchPage, {
        [PARAMETERS.GEO]: geometryFilters,
        [PARAMETERS.VIEW]: VIEWS.LIST
      });
    }
  }
}

function* clearDrawing() {
  yield call(setPolygon, []);
  yield call(enable);
  yield put(mapEmptyGeometry());
}

function* startDrawing() {
  yield call(setPolygon, []);
  yield call(enable);
  yield put(mapStartDrawing({ drawingMode: drawToolConfig.DRAWING_MODE.DRAW }));
}

function* endDrawing() {
  yield call(disable);
}

function* cancelDrawing() {
  yield put(mapEmptyGeometry());
  yield call(cancel);
}

export default function* watchFetchDataSelection() {
  yield takeLatest(REMOVE_FILTER, clearShapeFilter);
  yield takeLatest(SET_GEOMETRY_FILTER, setGeometryFilters);
  yield takeLatest(
    [SET_VIEW, SET_PAGE, ADD_FILTER, REMOVE_FILTER, REMOVE_GEOMETRY_FILTER, EMPTY_FILTERS],
    fetchDataSelectionEffect
  );

  // Actions
  yield takeLatest(FETCH_DATA_SELECTION_REQUEST, retrieveDataSelection);
  yield takeLatest([SET_DATASET], switchPage);

  yield takeLatest(RESET_DATA_SELECTION, clearDrawing);
  yield takeLatest(START_DATA_SELECTION, startDrawing);
  yield takeLatest(END_DATA_SELECTION, endDrawing);
  yield takeLatest(CANCEL_DATA_SELECTION, cancelDrawing);
}
<|endoftext|>


<commit_before>class WebsocketClientService {

    constructor($q, $rootScope, websocketActionCreator) {
        'ngInject';

        this._$q = $q;
        this._$rootScope = $rootScope;
        this._websocketActionCreator = websocketActionCreator;

        this._connectionAttempts = 1;
        this._eventsSubscribed = {};
        this._currentOnGoingMessages = {};
    }

    connect() {
        const defer = this._$q.defer();

        if (_.isUndefined(this._websocket) || this._websocket.readyState === WebSocket.CLOSED) {
            this._websocket = new WebSocket(`ws://${location.hostname}/api/v1/ws`);

            this._websocket.onopen = () => {
                const watcherPromises = [];

                this._connectionAttempts = 1;
                this._reconnect = true;

                _.each(this._eventsSubscribed, (watcher) => {
                    watcherPromises.push(this.sendMessage(watcher)
                        .then((response) => this._websocketActionCreator.subscribedResource(response)));
                });
                this._$q.all(watcherPromises)
                    .then(() => defer.resolve());
            };

            this._websocket.onmessage = (evt) => {
                const message = JSON.parse(evt.data);

                this._$rootScope.$apply(() => {
                    if (message.correlation) {
                        if (message.status_code >= 400) {
                            this._currentOnGoingMessages[message.correlation].reject(message);
                        } else {
                            this._currentOnGoingMessages[message.correlation].resolve(message);
                        }

                        delete this._currentOnGoingMessages[message.correlation];
                    } else {
                        this._websocketActionCreator.updateResource(message);
                    }
                });
            };

            this._websocket.onerror = () => {
                defer.reject();
            };

            this._websocket.onclose = () => {
                if (this._reconnect) {
                    const time = generateInterval(this._connectionAttempts);

                    setTimeout(() => {
                        this._connectionAttempts++;
                        this.connect();
                    }, time);
                }
            };
        } else {
            defer.resolve();
        }

        return defer.promise;
    }

    disconnect() {
        const promises = [];

        _.each(this._eventsSubscribed, (value) => promises.push(this.unSubscribeEvent(value)));

        return this._$q.all(promises)
            .then(() => {
                this._reconnect = false;
                this._websocket.close();
            });
    }

    sendMessage(message) {
        if (this._websocket.readyState !== WebSocket.OPEN) {
            return this._$q.reject('Not Connected');
        }

        const defer = this._$q.defer();
        const correlationId = _.uniqueId();

        this._currentOnGoingMessages[correlationId] = defer;

        message.correlation = correlationId;
        this._websocket.send(JSON.stringify(message));

        return defer.promise;
    }

    subscribeEvent(action, namespace) {
        const message = {
            action,
            operation: 'watch'
        };

        if (!_.isUndefined(namespace)) {
            message.body = {
                namespace
            };
        }

        return this.sendMessage(message)
            .then((response) => {
                this._eventsSubscribed[action] = message;
                this._websocketActionCreator.subscribedResource(response);
            });
    }

    unSubscribeEvent(action) {
        const message = {
            action,
            operation: 'unwatch'
        };

        return this._$q.when(this._eventsSubscribed[action] && this.sendMessage(message)
                .then((response) => {
                    delete this._eventsSubscribed[action];
                    this._websocketActionCreator.unSubscribedResource(response);
                }));
    }

    updateEvent(action, body) {
        const message = {
            action,
            body,
            operation: 'update'
        };

        return this._$q.when(this.sendMessage(message));
    }
}

function generateInterval(k) {
    return Math.min(30, Math.pow(2, k) - 1) * 1000;
}

export default WebsocketClientService;
<commit_msg>Remove watchers on disconnect<commit_after>class WebsocketClientService {

    constructor($q, $rootScope, websocketActionCreator) {
        'ngInject';

        this._$q = $q;
        this._$rootScope = $rootScope;
        this._websocketActionCreator = websocketActionCreator;

        this._connectionAttempts = 1;
        this._eventsSubscribed = {};
        this._currentOnGoingMessages = {};
    }

    connect() {
        const defer = this._$q.defer();

        if (_.isUndefined(this._websocket) || this._websocket.readyState === WebSocket.CLOSED) {
            this._websocket = new WebSocket(`ws://${location.hostname}/api/v1/ws`);

            this._websocket.onopen = () => {
                const watcherPromises = [];

                this._connectionAttempts = 1;
                this._reconnect = true;

                _.each(this._eventsSubscribed, (watcher) => {
                    watcherPromises.push(this.sendMessage(watcher)
                        .then((response) => this._websocketActionCreator.subscribedResource(response)));
                });
                this._$q.all(watcherPromises)
                    .then(() => defer.resolve());
            };

            this._websocket.onmessage = (evt) => {
                const message = JSON.parse(evt.data);

                this._$rootScope.$apply(() => {
                    if (message.correlation) {
                        if (message.status_code >= 400) {
                            this._currentOnGoingMessages[message.correlation].reject(message);
                        } else {
                            this._currentOnGoingMessages[message.correlation].resolve(message);
                        }

                        delete this._currentOnGoingMessages[message.correlation];
                    } else {
                        this._websocketActionCreator.updateResource(message);
                    }
                });
            };

            this._websocket.onerror = () => {
                defer.reject();
            };

            this._websocket.onclose = () => {
                if (this._reconnect) {
                    const time = generateInterval(this._connectionAttempts);

                    setTimeout(() => {
                        this._connectionAttempts++;
                        this.connect();
                    }, time);
                }
            };
        } else {
            defer.resolve();
        }

        return defer.promise;
    }

    disconnect() {
        const promises = [];

        _.each(this._eventsSubscribed, (value, key) => promises.push(this.unSubscribeEvent(key)));

        return this._$q.all(promises)
            .then(() => {
                this._reconnect = false;
                this._websocket.close();
            });
    }

    sendMessage(message) {
        if (this._websocket.readyState !== WebSocket.OPEN) {
            return this._$q.reject('Not Connected');
        }

        const defer = this._$q.defer();
        const correlationId = _.uniqueId();

        this._currentOnGoingMessages[correlationId] = defer;

        message.correlation = correlationId;
        this._websocket.send(JSON.stringify(message));

        return defer.promise;
    }

    subscribeEvent(action, namespace) {
        const message = {
            action,
            operation: 'watch'
        };

        if (!_.isUndefined(namespace)) {
            message.body = {
                namespace
            };
        }

        return this.sendMessage(message)
            .then((response) => {
                this._eventsSubscribed[action] = message;
                this._websocketActionCreator.subscribedResource(response);
            });
    }

    unSubscribeEvent(action) {
        const message = {
            action,
            operation: 'unwatch'
        };

        return this._$q.when(this._eventsSubscribed[action] && this.sendMessage(message)
                .then((response) => {
                    delete this._eventsSubscribed[action];
                    this._websocketActionCreator.unSubscribedResource(response);
                }));
    }

    updateEvent(action, body) {
        const message = {
            action,
            body,
            operation: 'update'
        };

        return this._$q.when(this.sendMessage(message));
    }
}

function generateInterval(k) {
    return Math.min(30, Math.pow(2, k) - 1) * 1000;
}

export default WebsocketClientService;
<|endoftext|>


<commit_before>goog.provide('Blockly.Python.audio');

goog.require('Blockly.Python');

function createAudioParser(audioFile) {
  Blockly.Python[audioFile] = function(block) {
    return ['\"'+ audioFile + '\"', Blockly.Python.ORDER_NONE];
  };
}

function loadAudioParser() {
  var request = new XMLHttpRequest();
  request.open("GET", "/audio/list", true);

  request.onload = function(evt) {
    var response = JSON.parse(request.responseText);

    for(var i=0; i < response.length; i++) {
      createAudioParser(response[i]);
    }
  }

  request.send();
}

Blockly.Python['speaker'] = function(block) {
  Blockly.Python.definitions_['import_speaker'] = 'from hackclock.runapp.Libs.GStreamer import Speaker';
  Blockly.Python.definitions_['init_speaker'] = 'speaker = Speaker()';
  return ['speaker', Blockly.Python.ORDER_ATOMIC];
};

Blockly.Python['google_music_radio'] = function(block) {
  Blockly.Python.definitions_['import_speaker'] = 'from hackclock.runapp.Libs.GStreamer import Speaker';
  Blockly.Python.definitions_['import_googlemusic'] = 'from hackclock.runapp.Libs.GoogleMusic import AudioStream';
  Blockly.Python.definitions_['init_speaker'] = 'speaker = Speaker()';
  Blockly.Python.definitions_['init_googlemusic'] = 'audio_stream = AudioStream()';

  return ['audio_stream', Blockly.Python.ORDER_NONE];
};

Blockly.Python['play_list'] = function(block) {
  var value_speaker = Blockly.Python.valueToCode(block, 'speaker', Blockly.Python.ORDER_ATOMIC);
  var value_songs = Blockly.Python.valueToCode(block, 'songs', Blockly.Python.ORDER_ATOMIC);
  return ''+value_speaker+'.playList('+value_songs+')\n';
};

Blockly.Python['is_playing'] = function(block) {
  var value_speaker = Blockly.Python.valueToCode(block, 'speaker', Blockly.Python.ORDER_ATOMIC);
  return [value_speaker + '.isPlaying()', Blockly.Python.ORDER_NONE];
};

Blockly.Python['audio_stop'] = function(block) {
  var value_speaker = Blockly.Python.valueToCode(block, 'speaker', Blockly.Python.ORDER_ATOMIC);
  return value_speaker + ".stop()\n";
};
<commit_msg>Resolved issue #23<commit_after>goog.provide('Blockly.Python.audio');

goog.require('Blockly.Python');

function createAudioParser(audioFile) {
  Blockly.Python[audioFile] = function(block) {
    return ['\"'+ audioFile + '\"', Blockly.Python.ORDER_NONE];
  };
}

function loadAudioParser() {
  var request = new XMLHttpRequest();
  request.open("GET", "/audio/list", true);

  request.onload = function(evt) {
    var response = JSON.parse(request.responseText);

    for(var i=0; i < response.length; i++) {
      createAudioParser(response[i]);
    }
  }

  request.send();
}

Blockly.Python['speaker'] = function(block) {
  Blockly.Python.definitions_['import_speaker'] = 'from hackclock.runapp.Libs.GStreamer import Speaker';
  Blockly.Python.definitions_['init_speaker'] = 'speaker = Speaker()';
  return ['speaker', Blockly.Python.ORDER_ATOMIC];
};

Blockly.Python['google_music_radio'] = function(block) {
  Blockly.Python.definitions_['import_speaker'] = 'from hackclock.runapp.Libs.GStreamer import Speaker';
  Blockly.Python.definitions_['import_googlemusic'] = 'from hackclock.runapp.Libs.GoogleMusic import AudioStream';
  Blockly.Python.definitions_['init_speaker'] = 'speaker = Speaker()';
  Blockly.Python.definitions_['init_googlemusic'] = 'audio_stream = AudioStream()';

  return ['audio_stream', Blockly.Python.ORDER_ATOMIC];
};

Blockly.Python['play_list'] = function(block) {
  var value_speaker = Blockly.Python.valueToCode(block, 'speaker', Blockly.Python.ORDER_ATOMIC);
  var value_songs = Blockly.Python.valueToCode(block, 'songs', Blockly.Python.ORDER_ATOMIC);
  return ''+value_speaker+'.playList('+value_songs+')\n';
};

Blockly.Python['is_playing'] = function(block) {
  var value_speaker = Blockly.Python.valueToCode(block, 'speaker', Blockly.Python.ORDER_ATOMIC);
  return [value_speaker + '.isPlaying()', Blockly.Python.ORDER_NONE];
};

Blockly.Python['audio_stop'] = function(block) {
  var value_speaker = Blockly.Python.valueToCode(block, 'speaker', Blockly.Python.ORDER_ATOMIC);
  return value_speaker + ".stop()\n";
};
<|endoftext|>


<commit_before>self.deprecationWorkflow = self.deprecationWorkflow || {};
self.deprecationWorkflow.config = {
    workflow: [
        // revert one liquid-fire and liquid-wormhole remove uses of `this.$()`
        {handler: 'silence', matchId: 'ember-views.curly-components.jquery-element'},
        // revert once ember-infinity removes usage of `isVisible`
        // https://github.com/ember-infinity/ember-infinity/pull/399
        {handler: 'silence', matchId: 'ember-component.is-visible'}
    ]
};
<commit_msg>Silenced Component#sendAction deprecation<commit_after>self.deprecationWorkflow = self.deprecationWorkflow || {};
self.deprecationWorkflow.config = {
    workflow: [
        // remove once ember-drag-drop removes usage of Component#sendAction
        // https://github.com/mharris717/ember-drag-drop/issues/155
        {handler: 'silence', matchId: 'ember-component.send-action'},

        // remove once liquid-fire and liquid-wormhole remove uses of `this.$()`
        {handler: 'silence', matchId: 'ember-views.curly-components.jquery-element'},

        // remove once ember-infinity removes usage of `isVisible`
        // https://github.com/ember-infinity/ember-infinity/pull/399
        {handler: 'silence', matchId: 'ember-component.is-visible'}
    ]
};
<|endoftext|>


<commit_before>// sinko.js version 0.1 (alpha) - http://github.com/dies-el/sinko
var SinkoInstance=function(d){var a={},c={},e={};a._source=d;var h=function(b,f){var g=Sinko.find(b,f);if(g[0])switch(g[0].tagName){case "INPUT":case "SELECT":case "TEXTAREA":return g[0].value;default:return g[0].innerHTML}};a.ins=function(b,f){c[b]=f};a.outs=function(b,f){if(arguments.length>1){if(e[b]==undefined)e[b]=[];switch(typeof f){case "function":e[b].push(f);break;case "object":e[b]=f;break}}return e[b]};a.sync_in=function(){for(property in c)switch(typeof c[property]){case "undefined":a._source[property]=
undefined;break;case "function":a._source[property]=c[property].apply(a._source);break;case "string":a._source[property]=h(c[property]);break;case "object":if(c[property].length>0)a._source[property]=Sinko.selector_library!="jquery"?h(c[property].selector):h(c[property]);break}};a.sync_out=function(){for(property in e)for(var b=0;b<e[property].length;b++)e[property][b].apply(a._source)};a.sync=function(){a.sync_in();a.sync_out()};return a},Sinko=function(d){d.available_selector_libraries=function(){var a=
[];typeof Sizzle!="undefined"&&a.push("sizzle");typeof jQuery!="undefined"&&a.push("jquery");return a}();d.defaults={selector_library:d.available_selector_libraries[0]};d.init=function(a){a.sinko=SinkoInstance(a)};d.find=function(){return function(a,c){switch(d.defaults.selector_library){case "sizzle":return Sizzle(a,c);case "jquery":return jQuery(a,c)}}}();return d}(Sinko||{});
<commit_msg>Rebuilt minified version<commit_after>// sinko.js version 0.1 (alpha) - http://github.com/dies-el/sinko
var SinkoInstance=function(d){var a={},c={},e={};a._source=d;var h=function(b,f){var g=Sinko.find(b,f);if(g[0])switch(g[0].tagName){case "INPUT":case "SELECT":case "TEXTAREA":return g[0].value;default:return g[0].innerHTML}};a.ins=function(b,f){c[b]=f};a.outs=function(b,f){if(arguments.length>1){if(e[b]==undefined)e[b]=[];switch(typeof f){case "function":e[b].push(f);break;case "object":e[b]=f;break}}return e[b]};a.sync_in=function(){for(property in c)switch(typeof c[property]){case "undefined":a._source[property]=
undefined;break;case "function":a._source[property]=c[property].apply(a._source);break;case "string":a._source[property]=h(c[property]);break;case "object":if(c[property].length>0)a._source[property]=Sinko.selector_library=="jquery"?h(c[property]):h(c[property].selector);break}};a.sync_out=function(){for(property in e)for(var b=0;b<e[property].length;b++)e[property][b].apply(a._source)};a.sync=function(){a.sync_in();a.sync_out()};return a},Sinko=function(d){d.available_selector_libraries=function(){var a=
[];typeof Sizzle!="undefined"&&a.push("sizzle");typeof jQuery!="undefined"&&a.push("jquery");return a}();d.defaults={selector_library:d.available_selector_libraries[0]};d.init=function(a){a.sinko=SinkoInstance(a)};d.find=function(){return function(a,c){switch(d.defaults.selector_library){case "sizzle":return Sizzle(a,c);case "jquery":return jQuery(a,c)}}}();return d}(Sinko||{});
<|endoftext|>


<commit_before>{
        'type': 'Tank', // game or console
        'name': 'Game Name',
        'authors': ['Fulano de tal', 'Ciclano'],
        'company': ['CompanyX'],
        'year': '1951',
        'date': '20-06-1951', // Day, Month, Year
        'headline': 'First Game about sport',
        'resume': [
            'Lorem ipsum dolor sit amet, ut viverra vestibulum odio, ',
            'aliquam in massa, velit rutrum pede ipsum mauris duis, ',
            'congue massa sem elit, integer risus. Faucibus in lacus, ',
            'ligula ornare nibh, elit suspendisse tortor sed volutpat, ',
            'etiam tempus wisi semper montes odio, lorem vitae vel eu '
        ].join(''),
        'full_text': [
            'Lorem ipsum dolor sit amet, ut viverra vestibulum odio, ',
            'aliquam in massa, velit rutrum pede ipsum mauris duis, ',
            'congue massa sem elit, integer risus. Faucibus in lacus, ',
            'ligula ornare nibh, elit suspendisse tortor sed volutpat, ',
            'etiam tempus wisi semper montes odio, lorem vitae vel eu ',
            'convallis. Volutpat blandit egestas et libero eu per, venenatis ',
            'aenean, proin quis aliquam viverra potenti vestibulum auctor, ',
            'non amet tellus sodales. In ullamco tellus risus nisl morbi amet. ',
            'Vel quisque nunc in placerat. Vitae id urna, nulla suspendisse, ',
            'molestie sodales ac nisl nulla, tempus occaecati. Sodales lectus, ',
            'mauris dis lectus amet, nascetur ipsum, hac suspendisse blandit eros.'
        ].join(''),
        'thumbnail': 'thumbnail_example.png',
        'main_img': {'name': 'main_picture.png', 'caption': "description"},
        'images': [
            {'name': 'picture1.png', 'caption': "description1"},
            {'name': 'picture2.png', 'caption': "description2"},
            {'name': 'picture3.png', 'caption': "description3"}
        ],
        'video_gameplay': [
            {'url': 'video_url', 'caption': "description", 'type': "youtube"} // type: youtube or vimeo
        ],
        'demos': [
            {'url': 'demonstration_url', 'caption': "description"}
        ],
        'references': [
            {'url': 'reference_url1', 'caption': "description"},
            {'url': 'reference_url2', 'caption': "description"},
            {'url': 'reference_url3', 'caption': "description"}
        ]
}
<commit_msg>Delete Tank_Tank.js<commit_after><|endoftext|>